[SCM] Core functionality for performing astronomy and astrophysics with Python branch, debian, updated. 2d60183453ed8123379372820d44ebe120179f71

Ole Streicher debian at liska.ath.cx
Sun Jan 6 17:57:30 UTC 2013


The following commit has been merged in the debian branch:
commit d0cb2363a7c4b795759f8b4096b3cd439ff08489
Author: Ole Streicher <debian at liska.ath.cx>
Date:   Sun Jan 6 17:35:12 2013 +0100

    Beta release 0.2b1

diff --git a/PKG-INFO b/PKG-INFO
index 55925b1..206e77c 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,12 +1,12 @@
 Metadata-Version: 1.1
 Name: astropy
-Version: 0.1
+Version: 0.2b1
 Summary: Community-developed python astronomy tools
 Home-page: http://astropy.org
 Author: The Astropy Developers
 Author-email: astropy.team at gmail.com
 License: BSD
-Download-URL: http://cloud.github.com/downloads/astropy/astropy/astropy-0.1.tar.gz
+Download-URL: http://pypi.python.org/packages/source/a/astropy/astropy-0.2b1.tar.gz
 Description: 
         Astropy is a package intended to contain core functionality and some
         common tools needed for performing astronomy and astrophysics research with
@@ -14,5 +14,16 @@ Description:
         managing them.
         
 Platform: UNKNOWN
+Classifier: Intended Audience :: Science/Research
+Classifier: License :: OSI Approved :: BSD License
+Classifier: Operating System :: OS Independent
+Classifier: Programming Language :: C
+Classifier: Programming Language :: Cython
+Classifier: Programming Language :: Python :: 2.6
+Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: Implementation :: CPython
+Classifier: Topic :: Scientific/Engineering :: Astronomy
+Classifier: Topic :: Scientific/Engineering :: Physics
 Requires: numpy
 Provides: astropy
diff --git a/astropy/__init__.py b/astropy/__init__.py
index 0156b37..35c24d6 100644
--- a/astropy/__init__.py
+++ b/astropy/__init__.py
@@ -30,7 +30,6 @@ except ImportError:
     __githash__ = ''
 
 # set up the test command
-_test_runner = None
 def _get_test_runner():
     from .tests.helper import TestRunner
     return TestRunner(__path__[0])
@@ -101,4 +100,4 @@ def test(package=None, test_path=None, args=None, plugins=None,
 
 #if we are *not* in setup mode, import the logger
 if not _ASTROPY_SETUP_:
-    from logger import log
+    from .logger import log
diff --git a/astropy/_constants/__init__.py b/astropy/_constants/__init__.py
new file mode 100644
index 0000000..9e706d0
--- /dev/null
+++ b/astropy/_constants/__init__.py
@@ -0,0 +1,6 @@
+# Licensed under a 3-clause BSD style license - see LICENSE.rst
+"""
+This is a hidden sub-package containing the definitions of the constants used
+in `astropy.units` and `astropy.constants`. These need to be included outside
+both of those sub-packages to avoid circular dependencies.
+"""
diff --git a/astropy/_constants/cgs.py b/astropy/_constants/cgs.py
new file mode 100644
index 0000000..7708c88
--- /dev/null
+++ b/astropy/_constants/cgs.py
@@ -0,0 +1,115 @@
+# Licensed under a 3-clause BSD style license - see LICENSE.rst
+"""
+Astronomical and physics constants in cgs units.  The constants
+available (with approximate values) are:
+"""
+# This docstring is extended by __init__.py
+
+# The values of constants are defined here instead of `astropy/constants` in
+# order to avoid circular dependencies, since Constant depends on Quantity,
+# Quantity depends on Unit, and Unit depends on the value of some of the
+# constants, so they need to be kept separately.
+
+from .definition import ConstantDefinition
+from . import si
+
+# PHYSICAL CONSTANTS
+
+# Planck constant
+h = ConstantDefinition(si.h * 1.e7, si.h.uncertainty * 1.e7,
+                       si.h.name, si.h.reference, 'erg.s')
+
+# Reduced Planck constant
+hbar = ConstantDefinition(si.hbar * 1.e7, si.hbar.uncertainty * 1.e7,
+                          si.hbar.name, si.hbar.reference, 'erg.s')
+
+# Boltzmann constant [CODATA]
+k_B = ConstantDefinition(si.k_B * 1.e7, si.k_B.uncertainty * 1.e7,
+                         si.k_B.name, si.k_B.reference, 'erg.s')
+
+# Speed of light [CODATA]
+c = ConstantDefinition(si.c * 1.e2, si.c.uncertainty * 1.e2,
+                       si.c.name, si.c.reference, 'cm/s')
+
+# Gravitional constant [CODATA]
+G = ConstantDefinition(si.G * 1.e3, si.G.uncertainty * 1.e3,
+                       si.G.name, si.G.reference, 'cm3.g-1.s-2')
+
+# Proton mass [CODATA]
+m_p = ConstantDefinition(si.m_p * 1.e3, si.m_p.uncertainty * 1.e3,
+                         si.m_p.name, si.m_p.reference, 'g')
+
+# Neutron mass [CODATA]
+m_n = ConstantDefinition(si.m_n * 1.e3, si.m_n.uncertainty * 1.e3,
+                         si.m_n.name, si.m_n.reference, 'g')
+
+# Electron mass [CODATA]
+m_e = ConstantDefinition(si.m_e * 1.e3, si.m_e.uncertainty * 1.e3,
+                         si.m_e.name, si.m_e.reference, 'g')
+
+# Stefan-Boltzmann constant
+sigma_sb = ConstantDefinition(si.sigma_sb * 1.e3, si.sigma_sb.uncertainty * 1.e3,
+                              si.sigma_sb.name, si.sigma_sb.reference,
+                              'erg.cm-2.K-4.s-1')
+
+# Electron charge
+e = ConstantDefinition(si.e * si.c * 10., si.e.uncertainty * si.c * 10.,
+                       si.e.name, si.e.reference, 'statC')
+
+# Avogadro's number
+N_A = ConstantDefinition(si.N_A, si.N_A.uncertainty,
+                         si.N_A.name, si.N_A.reference, 'mol-1')
+
+# Gas constant
+R = ConstantDefinition(si.R * 1.e7, si.R.uncertainty * 1.e7,
+                       si.R.name, si.R.reference, 'erg.K-1.mol-1')
+
+# Rydberg constant
+Ryd = ConstantDefinition(si.Ryd * 1.e-2, si.Ryd.uncertainty * 1.e-2,
+                         si.Ryd.name, si.Ryd.reference, 'cm-1')
+
+# DISTANCE
+
+# Astronomical Unit
+au = ConstantDefinition(si.au * 1.e2, si.au.uncertainty * 1.e2,
+                        si.au.name, si.au.reference, 'cm')
+
+# Parsec
+pc = ConstantDefinition(si.pc * 1.e2, si.pc.uncertainty * 1.e2,
+                        si.pc.name, si.pc.reference, 'cm')
+
+# Kiloparsec
+kpc = ConstantDefinition(si.kpc * 1.e2, si.kpc.uncertainty * 1.e2,
+                         si.kpc.name, si.kpc.reference, 'cm')
+
+# SOLAR QUANTITIES
+
+# Solar luminosity
+L_sun = ConstantDefinition(si.L_sun * 1.e7, si.L_sun.uncertainty * 1.e7,
+                           si.L_sun.name, si.L_sun.reference, 'erg/s')
+
+# Solar mass
+M_sun = ConstantDefinition(si.M_sun * 1.e3, si.M_sun.uncertainty * 1.e3,
+                           si.M_sun.name, si.M_sun.reference, 'g')
+
+# Solar radius
+R_sun = ConstantDefinition(si.R_sun * 1.e2, si.R_sun.uncertainty * 1.e2,
+                           si.R_sun.name, si.R_sun.reference, 'cm')
+
+# OTHER SOLAR SYSTEM QUANTITIES
+
+# Jupiter mass
+M_jup = ConstantDefinition(si.M_jup * 1.e3, si.M_jup.uncertainty * 1.e3,
+                           si.M_jup.name, si.M_jup.reference, 'g')
+
+# Jupiter equatorial radius
+R_jup = ConstantDefinition(si.R_jup * 1.e2, si.R_jup.uncertainty * 1.e2,
+                           si.R_jup.name, si.R_jup.reference, 'cm')
+
+# Earth mass
+M_earth = ConstantDefinition(si.M_earth * 1.e3, si.M_earth.uncertainty * 1.e3,
+                             si.M_earth.name, si.M_earth.reference, 'g')
+
+# Earth equatorial radius
+R_earth = ConstantDefinition(si.R_earth * 1.e2, si.R_earth.uncertainty * 1.e2,
+                             si.R_earth.name, si.R_earth.reference, 'cm')
diff --git a/astropy/_constants/definition.py b/astropy/_constants/definition.py
new file mode 100644
index 0000000..b3091a3
--- /dev/null
+++ b/astropy/_constants/definition.py
@@ -0,0 +1,14 @@
+class ConstantDefinition(float):
+    """
+    A float with meta-data related to physical constants
+    """
+    def __init__(self, value, uncertainty, name, reference, units):
+        super(ConstantDefinition, self).__init__()
+        self.value = value
+        self.uncertainty = uncertainty
+        self.name = name
+        self.reference = reference
+        self.units = units
+
+    def __new__(cls, value, uncertainty, name, reference, units):
+        return super(ConstantDefinition, cls).__new__(cls, value)
diff --git a/astropy/_constants/si.py b/astropy/_constants/si.py
new file mode 100644
index 0000000..76fd9f8
--- /dev/null
+++ b/astropy/_constants/si.py
@@ -0,0 +1,142 @@
+# Licensed under a 3-clause BSD style license - see LICENSE.rst
+"""
+Astronomical and physics constants in SI units. The constants
+available (with approximate values) are:
+"""
+# This docstring is extended by __init__.py
+
+# The values of constants are defined here instead of `astropy/constants` in
+# order to avoid circular dependencies, since Constant depends on Quantity,
+# Quantity depends on Unit, and Unit depends on the value of some of the
+# constants, so they need to be kept separately.
+
+import numpy as np
+
+from .definition import ConstantDefinition
+
+# PHYSICAL CONSTANTS
+
+# Planck constant
+h = ConstantDefinition(6.62606957e-34, 0.00000029e-34,
+                       "Planck constant",
+                       'CODATA 2010', 'J.s')
+
+# Reduced Planck constant
+hbar = ConstantDefinition(h * 0.5 / np.pi, h.uncertainty * 0.5 / np.pi,
+                          "Reduced Planck constant",
+                          'CODATA 2010', 'J.s')
+
+# Boltzmann constant
+k_B = ConstantDefinition(1.3806488e-23, 0.0000013e-23,
+                         "Boltzmann constant",
+                         'CODATA 2010', 'J/K')
+
+# Speed of light
+c = ConstantDefinition(2.99792458e8, 0.,
+                       "Speed of light in vacuum",
+                       'CODATA 2010', 'm/s')
+
+# Gravitional constant
+G = ConstantDefinition(6.67384e-11, 0.00080e-11,
+                       "Gravitational constant",
+                       'CODATA 2010', 'm3.kg-1.s-2')
+
+# Proton mass
+m_p = ConstantDefinition(1.672621777e-27, 0.000000074e-27,
+                         "Proton mass",
+                         'CODATA 2010', 'kg')
+
+# Neutron mass
+m_n = ConstantDefinition(1.674927351e-27, 0.000000074e-27,
+                         "Neutron mass",
+                         'CODATA 2010', 'kg')
+
+# Electron mass
+m_e = ConstantDefinition(9.10938291e-31, 0.00000040e-31,
+                         "Electron mass",
+                         'CODATA 2010', 'kg')
+
+# Stefan-Boltzmann constant
+sigma_sb = ConstantDefinition(5.670373e-8, 0.000021e-8,
+                              "Stefan-Boltzmann constant",
+                              'CODATA 2010', 'W.m-2.K-4')
+
+# Electron charge
+e = ConstantDefinition(1.602176565e-19, 0.000000035e-19,
+                       "Electron charge",
+                       'CODATA 2010', 'C')
+
+# Avogadro's number
+N_A = ConstantDefinition(6.02214129e23, 0.00000027e23,
+                         "Avogadro's number",
+                         'CODATA 2010', 'mol-1')
+
+# Gas constant
+R = ConstantDefinition(8.3144621, 0.0000075,
+                       "Gas constant",
+                       'CODATA 2010', 'J.mol-1.K-1')
+
+# Rydberg constant
+Ryd = ConstantDefinition(10973731.568539, 0.000055,
+                         'Rydberg constant',
+                         'CODATA 2010', 'm-1')
+
+# DISTANCE
+
+# Astronomical Unit
+au = ConstantDefinition(1.49597870700e11, 0.0,
+                        "Astronomical Unit",
+                        "IAU 2012 Resolution B2", 'm')
+
+# Parsec
+
+pc = ConstantDefinition(au / np.tan(np.radians(1. / 3600.)),
+                        au.uncertainty / np.tan(np.radians(1. / 3600.)),
+                        "Parsec",
+                        "Derived from au", 'm')
+
+# Kiloparsec
+kpc = ConstantDefinition(1000. * au / np.tan(np.radians(1. / 3600.)),
+                         1000. * au.uncertainty / np.tan(np.radians(1. / 3600.)),
+                         "Kiloparsec",
+                         "Derived from au", 'm')
+
+# SOLAR QUANTITIES
+
+# Solar luminosity
+L_sun = ConstantDefinition(3.846e26, 0.0005e26,
+                           "Solar luminosity",
+                           "Allen's Astrophysical Quantities 4th Ed.", 'W')
+
+# Solar mass
+M_sun = ConstantDefinition(1.9891e30, 0.00005e30,
+                           "Solar mass",
+                           "Allen's Astrophysical Quantities 4th Ed.", 'kg')
+
+# Solar radius
+R_sun = ConstantDefinition(6.95508e8, 0.00026e8,
+                           "Solar radius",
+                           "Allen's Astrophysical Quantities 4th Ed.", 'm')
+
+
+# OTHER SOLAR SYSTEM QUANTITIES
+
+# Jupiter mass
+M_jup = ConstantDefinition(1.8987e27, 0.00005e27,
+                           "Jupiter mass",
+                           "Allen's Astrophysical Quantities 4th Ed.", 'kg')
+
+# Jupiter equatorial radius
+R_jup = ConstantDefinition(7.1492e7, 0.00005e7,
+                           "Jupiter equatorial radius",
+                           "Allen's Astrophysical Quantities 4th Ed.", 'm')
+
+# Earth mass
+M_earth = ConstantDefinition(5.9742e24, 0.00005e24,
+                             "Earth mass",
+                             "Allen's Astrophysical Quantities 4th Ed.", 'kg')
+
+# Earth equatorial radius
+R_earth = ConstantDefinition(6.378136e6, 0.0000005e6,
+                             "Earth equatorial radius",
+                             "Allen's Astrophysical Quantities 4th Ed.", 'm')
diff --git a/astropy/config/__init__.py b/astropy/config/__init__.py
index 2e642a2..38b4798 100644
--- a/astropy/config/__init__.py
+++ b/astropy/config/__init__.py
@@ -8,5 +8,4 @@ affiliated package index.
 
 from .paths import *
 from .configuration import *
-from .data import *
 from .affiliated import *
diff --git a/astropy/config/data.py b/astropy/config/data.py
deleted file mode 100644
index 63b1273..0000000
--- a/astropy/config/data.py
+++ /dev/null
@@ -1,725 +0,0 @@
-# Licensed under a 3-clause BSD style license - see LICENSE.rst
-""" This module contains helper functions for accessing, downloading, and
-caching data files.
-"""
-
-from __future__ import division
-
-import sys
-import atexit
-
-from .configuration import ConfigurationItem
-
-
-__all__ = ['get_data_fileobj', 'get_data_filename', 'get_data_contents',
-           'get_data_fileobjs', 'get_data_filenames', 'compute_hash',
-           'clear_data_cache', 'CacheMissingWarning']
-
-DATAURL = ConfigurationItem(
-    'dataurl', 'http://data.astropy.org/', 'URL for astropy remote data site.')
-REMOTE_TIMEOUT = ConfigurationItem(
-    'remote_timeout', 3., 'Time to wait for remote data query (in seconds).')
-COMPUTE_HASH_BLOCK_SIZE = ConfigurationItem(
-    'hash_block_size', 2 ** 16,  # 64K
-    'Block size for computing MD5 file hashes.')
-DATA_CACHE_DL_BLOCK_SIZE = ConfigurationItem(
-    'data_dl_block_size', 2 ** 16,  # 64K
-    'Number of bytes of remote data to download per step.')
-DATA_CACHE_LOCK_ATTEMPTS = ConfigurationItem(
-    'data_cache_lock_attempts', 3, 'Number of times to try to get the lock ' +
-    'while accessing the data cache before giving up.')
-DELETE_TEMPORARY_DOWNLOADS_AT_EXIT = ConfigurationItem(
-    'delete_temporary_downloads_at_exit', True, 'If True, temporary download' +
-    ' files created when the cache is inacessible will be deleted at the end' +
-    ' of the python session.')
-
-
-if sys.version_info[0] < 3:  # pragma: py2
-    #used for supporting with statements in get_data_fileobj
-    def _fake_enter(self):
-        return self
-
-    def _fake_exit(self, type, value, traceback):
-        self.close()
-
-
-class CacheMissingWarning(Warning):
-    """
-    This warning indicates the standard cache directory is not accessible, with
-    the first argument providing the warning message. If args[1] is present, it
-    is a filename indicating the path to a temporary file that was created to
-    store a remote data download in the absence of the cache.
-    """
-
-
-def get_data_fileobj(dataname, cache=True):
-    """
-    Retrieves a data file from the standard locations and provides the file as
-    a file-like object.
-
-    Parameters
-    ----------
-    dataname : str
-        Name/location of the desired data file.  One of the following:
-
-            * The name of a data file included in the source
-              distribution.  The path is relative to the module
-              calling this function.  For example, if calling from
-              `astropy.pkname`, use ``'data/file.dat'`` to get the
-              file in ``astropy/pkgname/data/file.dat``.  Double-dots
-              can be used to go up a level.  In the same example, use
-              ``'../data/file.dat'`` to get ``astropy/data/file.dat``.
-            * If a matching local file does not exist, the Astropy
-              data server will be queried for the file.
-            * A hash like that produced by `compute_hash` can be
-              requested, prefixed by 'hash/'
-              e.g. 'hash/395dd6493cc584df1e78b474fb150840'.  The hash
-              will first be searched for locally, and if not found,
-              the Astropy data server will be queried.
-            * A URL to some other file.
-
-    cache : bool
-        If True, the file will be downloaded and saved locally or the
-        already-cached local copy will be accessed. If False, the file-like
-        object will directly access the resource (e.g. if a remote URL is
-        accessed, an object like that from `urllib2.urlopen` is returned).
-
-    Returns
-    -------
-    fileobj : file-like
-        An object with the contents of the data file available via
-        :func:`read`.  Can be used as part of a ``with`` statement,
-        automatically closing itself after the ``with`` block.
-
-    Raises
-    ------
-    urllib2.URLError
-        If a remote file cannot be found.
-    IOError
-        If problems occur writing or reading a local file.
-
-    Examples
-    --------
-
-    This will retrieve a data file and its contents for the `astropy.wcs`
-    tests::
-
-        from astropy.config import get_data_fileobj
-
-        with get_data_fileobj('data/3d_cd.hdr') as fobj:
-            fcontents = fobj.read()
-
-
-    This downloads a data file and its contents from a specified URL, and does
-    *not* cache it remotely::
-
-        from astropy.config import get_data_fileobj
-
-        vegaurl = 'ftp://ftp.stsci.edu/cdbs/grid/k93models/standards/vega.fits'
-        with get_data_fileobj(vegaurl,False) as fobj:
-            fcontents = fobj.read()
-
-    See Also
-    --------
-    get_data_contents : returns the contents of a file or url as a bytes object
-    get_data_filename : returns a local name for a file containing the data
-    """
-    from os.path import isdir, isfile
-    from urlparse import urlparse
-    from urllib2 import urlopen
-    from types import MethodType
-
-    if cache:
-        return open(get_data_filename(dataname), 'rb')
-    else:
-        url = urlparse(dataname)
-        if url[0] != '':  # url[0]==url.scheme, but url[0] is py 2.6-compat
-            #it's actually a url for a net location
-            urlres = urlopen(dataname, timeout=REMOTE_TIMEOUT())
-        else:
-            datafn = _find_pkg_data_path(dataname)
-            if isdir(datafn):
-                raise IOError(
-                    "Tried to access a data file that's actually "
-                    "a package data directory")
-            elif isfile(datafn):
-                return open(datafn, 'rb')
-            else:
-                #not local file - need to get remote data
-                urlres = urlopen(DATAURL() + datafn, timeout=REMOTE_TIMEOUT())
-
-        if sys.version_info[0] < 3:  # pragma: py2
-            #need to add in context managers to support with urlopen for <3.x
-            urlres.__enter__ = MethodType(_fake_enter, urlres)
-            urlres.__exit__ = MethodType(_fake_exit, urlres)
-
-        return urlres
-
-
-def get_data_filename(dataname):
-    """
-    Retrieves a data file from the standard locations and provides the local
-    name of the file.
-
-    This function is similar to `get_data_fileobj` but returns the file *name*
-    instead of a readable file-like object.  This means that this function must
-    always cache remote files locally, unlike `get_data_fileobj`.
-
-    Parameters
-    ----------
-    dataname : str
-        Name/location of the desired data file.  One of the following:
-
-            * The name of a data file included in the source
-              distribution.  The path is relative to the module
-              calling this function.  For example, if calling from
-              `astropy.pkname`, use ``'data/file.dat'`` to get the
-              file in ``astropy/pkgname/data/file.dat``.  Double-dots
-              can be used to go up a level.  In the same example, use
-              ``'../data/file.dat'`` to get ``astropy/data/file.dat``.
-            * If a matching local file does not exist, the Astropy
-              data server will be queried for the file.
-            * A hash like that produced by `compute_hash` can be
-              requested, prefixed by 'hash/'
-              e.g. 'hash/395dd6493cc584df1e78b474fb150840'.  The hash
-              will first be searched for locally, and if not found,
-              the Astropy data server will be queried.
-            * A URL to some other file.
-
-    Raises
-    ------
-    urllib2.URLError
-        If a remote file cannot be found.
-    IOError
-        If problems occur writing or reading a local file.
-
-    Returns
-    -------
-    filename : str
-        A file path on the local file system corresponding to the data
-        requested in `dataname`.
-
-    Examples
-    --------
-
-    This will retrieve the contents of the data file for the `astropy.wcs`
-    tests::
-
-        from astropy.config import get_data_filename
-
-        fn = get_data_filename('data/3d_cd.hdr')
-        with open(fn) as f:
-            fcontents = f.read()
-
-
-    This retrieves a data file by hash either locally or from the astropy data
-    server::
-
-        from astropy.config import get_data_filename
-
-        fn = get_data_filename('hash/da34a7b07ef153eede67387bf950bb32')
-        with open(fn) as f:
-            fcontents = f.read()
-
-    See Also
-    --------
-    get_data_contents : returns the contents of a file or url as a bytes object
-    get_data_fileobj : returns a file-like object with the data
-    """
-    from os.path import isdir, isfile
-    from urlparse import urlparse
-
-    url = urlparse(dataname)
-    if url[0] != '':  # url[0]==url.scheme, but url[0] is py 2.6-compat
-        #it's actually a url for a net location
-        return _cache_remote(dataname)
-    elif dataname.startswith('hash/'):
-            #first try looking for a local version if a hash is specified
-            hashfn = _find_hash_fn(dataname[5:])
-            if hashfn is None:
-                return _cache_remote(DATAURL() + dataname)
-            else:
-                return hashfn
-    else:
-        datafn = _find_pkg_data_path(dataname)
-        if isdir(datafn):
-            raise IOError(
-                "Tried to access a data file that's actually "
-                "a package data directory")
-        elif isfile(datafn):
-            return datafn
-        else:
-            #look for the file on the data server
-            return _cache_remote(DATAURL() + dataname)
-
-
-def get_data_contents(dataname, cache=True):
-    """
-    Retrieves a data file from the standard locations and returns its
-    contents as a bytes object.
-
-    Parameters
-    ----------
-    dataname : str
-        Name/location of the desired data file.  One of the following:
-
-            * The name of a data file included in the source
-              distribution.  The path is relative to the module
-              calling this function.  For example, if calling from
-              `astropy.pkname`, use ``'data/file.dat'`` to get the
-              file in ``astropy/pkgname/data/file.dat``.  Double-dots
-              can be used to go up a level.  In the same example, use
-              ``'../data/file.dat'`` to get ``astropy/data/file.dat``.
-            * If a matching local file does not exist, the Astropy
-              data server will be queried for the file.
-            * A hash like that produced by `compute_hash` can be
-              requested, prefixed by 'hash/'
-              e.g. 'hash/395dd6493cc584df1e78b474fb150840'.  The hash
-              will first be searched for locally, and if not found,
-              the Astropy data server will be queried.
-            * A URL to some other file.
-
-    cache : bool
-        If True, the file will be downloaded and saved locally or the
-        already-cached local copy will be accessed. If False, the file-like
-        object will directly access the resource (e.g. if a remote URL is
-        accessed, an object like that from `urllib2.urlopen` is returned).
-
-    Returns
-    -------
-    contents : bytes
-        The complete contents of the file as a bytes object.
-
-    Raises
-    ------
-    urllib2.URLError
-        If a remote file cannot be found.
-    IOError
-        If problems occur writing or reading a local file.
-
-    See Also
-    --------
-    get_data_fileobj : returns a file-like object with the data
-    get_data_filename : returns a local name for a file containing the data
-    """
-    with get_data_fileobj(dataname, cache=cache) as fd:
-        contents = fd.read()
-    return contents
-
-
-def get_data_filenames(datadir, pattern='*'):
-    """
-    Returns the path of all of the data files in a given directory
-    that match a given glob pattern.
-
-    Parameters
-    ----------
-    datadir : str
-        Name/location of the desired data files.  One of the following:
-
-            * The name of a directory included in the source
-              distribution.  The path is relative to the module
-              calling this function.  For example, if calling from
-              `astropy.pkname`, use ``'data'`` to get the
-              files in ``astropy/pkgname/data``.
-            * Remote URLs are not currently supported.
-
-    pattern : str, optional
-        A UNIX-style filename glob pattern to match files.  See the
-        `glob` module in the standard library for more information.
-        By default, matches all files.
-
-    Returns
-    -------
-    filenames : iterator of str
-        Paths on the local filesystem in *datadir* matching *pattern*.
-
-    Examples
-    --------
-    This will retrieve the contents of the data file for the `astropy.wcs`
-    tests::
-
-        from astropy.config import get_data_filenames
-
-        for fn in get_data_filename('maps', '*.hdr'):
-            with open(fn) as f:
-                fcontents = f.read()
-    """
-    import fnmatch
-    from os.path import isdir, isfile, join
-    from os import listdir
-
-    path = _find_pkg_data_path(datadir)
-    if isfile(path):
-        raise IOError(
-            "Tried to access a data directory that's actually "
-            "a package data file")
-    elif isdir(path):
-        for filename in listdir(path):
-            if fnmatch.fnmatch(filename, pattern):
-                yield join(path, filename)
-    else:
-        raise IOError("Path not found")
-
-
-def get_data_fileobjs(datadir, pattern='*'):
-    """
-    Returns readable file objects for all of the data files in a given
-    directory that match a given glob pattern.
-
-    Parameters
-    ----------
-    datadir : str
-        Name/location of the desired data files.  One of the following:
-
-            * The name of a directory included in the source
-              distribution.  The path is relative to the module
-              calling this function.  For example, if calling from
-              `astropy.pkname`, use ``'data'`` to get the
-              files in ``astropy/pkgname/data``
-            * Remote URLs are not currently supported
-
-    pattern : str, optional
-        A UNIX-style filename glob pattern to match files.  See the
-        `glob` module in the standard library for more information.
-        By default, matches all files.
-
-    Returns
-    -------
-    fileobjs : iterator of file objects
-        File objects for each of the files on the local filesystem in
-        *datadir* matching *pattern*.
-
-    Examples
-    --------
-    This will retrieve the contents of the data file for the `astropy.wcs`
-    tests::
-
-        from astropy.config import get_data_filenames
-
-        for fd in get_data_filename('maps', '*.hdr'):
-            fcontents = fd.read()
-    """
-    for fn in get_data_filenames(datadir, pattern):
-        with open(fn, 'rb') as fd:
-            yield fd
-
-
-def compute_hash(localfn):
-    """ Computes the MD5 hash for a file.
-
-    The hash for a data file is used for looking up data files in a unique
-    fashion. This is of particular use for tests; a test may require a
-    particular version of a particular file, in which case it can be accessed
-    via hash to get the appropriate version.
-
-    Typically, if you wish to write a test that requires a particular data
-    file, you will want to submit that file to the astropy data servers, and
-    use e.g. ``get_data_filename('hash/a725fa6ba642587436612c2df0451956')``,
-    but with the hash for your file in place of the hash in the example.
-
-    Parameters
-    ----------
-    localfn : str
-        The path to the file for which the hash should be generated.
-
-    Returns
-    -------
-    md5hash : str
-        The hex digest of the MD5 hash for the contents of the `localfn` file.
-
-    """
-    import hashlib
-
-    with open(localfn, 'rb') as f:
-        h = hashlib.md5()
-        block = f.read(COMPUTE_HASH_BLOCK_SIZE())
-        while block:
-            h.update(block)
-            block = f.read(COMPUTE_HASH_BLOCK_SIZE())
-
-    return h.hexdigest()
-
-
-def _find_pkg_data_path(dataname):
-    """
-    Look for data in the source-included data directories and return the
-    path.
-    """
-    from os.path import abspath, dirname, join
-    from ..utils.misc import find_current_module
-
-    module = find_current_module(1, True)
-    rootpkgname = module.__package__.split('.')[0]
-    rootpkg = __import__(rootpkgname)
-
-    module_path = dirname(module.__file__)
-    path = join(module_path, dataname)
-
-    root_dir = dirname(rootpkg.__file__)
-    assert abspath(path).startswith(abspath(root_dir)), \
-           ("attempted to get a local data file outside "
-            "of the " + rootpkgname + " tree")
-
-    return path
-
-
-def _find_hash_fn(hash):
-    """
-    Looks for a local file by hash - returns file name if found and a valid
-    file, otherwise returns None.
-    """
-    from os.path import isfile, join
-    from warnings import warn
-
-    try:
-        dldir, urlmapfn = _get_data_cache_locs()
-    except (IOError, OSError) as e:
-        msg = 'Could not access cache directory to search for data file: '
-        warn(CacheMissingWarning(msg + str(e)))
-        return None
-    hashfn = join(dldir, hash)
-    if isfile(hashfn):
-        return hashfn
-    else:
-        return None
-
-
-def _cache_remote(remoteurl):
-    """
-    Accepts a URL, downloads and caches the result returning the filename, with
-    a name determined by the file's MD5 hash. If present in the cache, just
-    returns the filename.
-    """
-    import hashlib
-    from contextlib import closing
-    from os.path import join
-    from tempfile import NamedTemporaryFile
-    from shutil import move
-    from urllib2 import urlopen
-    from warnings import warn
-
-    from ..utils.console import ProgressBarOrSpinner
-
-    try:
-        dldir, urlmapfn = _get_data_cache_locs()
-        docache = True
-    except (IOError, OSError) as e:
-        msg = 'Remote data cache could not be accessed due to '
-        estr = '' if len(e.args) < 1 else (': ' + str(e))
-        warn(CacheMissingWarning(msg + e.__class__.__name__ + estr))
-        docache = False
-
-    if docache:
-        _acquire_data_cache_lock()
-    try:
-        if docache:
-            with _open_shelve(urlmapfn, True) as url2hash:
-                if str(remoteurl) in url2hash:
-                    return url2hash[str(remoteurl)]
-
-        with closing(urlopen(remoteurl, timeout=REMOTE_TIMEOUT())) as remote:
-            #keep a hash to rename the local file to the hashed name
-            hash = hashlib.md5()
-
-            info = remote.info()
-            if 'Content-Length' in info:
-                try:
-                    size = int(info['Content-Length'])
-                except ValueError:
-                    size = None
-            else:
-                size = None
-
-            dlmsg = "Downloading {0}".format(remoteurl)
-            with ProgressBarOrSpinner(size, dlmsg) as p:
-                with NamedTemporaryFile(delete=False) as f:
-                    bytes_read = 0
-                    block = remote.read(DATA_CACHE_DL_BLOCK_SIZE())
-                    while block:
-                        f.write(block)
-                        hash.update(block)
-                        bytes_read += len(block)
-                        p.update(bytes_read)
-                        block = remote.read(DATA_CACHE_DL_BLOCK_SIZE())
-        if docache:
-            with _open_shelve(urlmapfn, True) as url2hash:
-                localpath = join(dldir, hash.hexdigest())
-                move(f.name, localpath)
-                url2hash[str(remoteurl)] = localpath
-        else:
-            localpath = f.name
-            msg = 'File downloaded to temp file due to lack of cache access.'
-            warn(CacheMissingWarning(msg, localpath))
-            if DELETE_TEMPORARY_DOWNLOADS_AT_EXIT():
-                global _tempfilestodel
-                _tempfilestodel.append(localpath)
-
-    finally:
-        if docache:
-            _release_data_cache_lock()
-
-    return localpath
-
-
-#this is used by _cache_remote and _deltemps to determine the files to delete
-# when the interpreter exits
-_tempfilestodel = []
-
-
- at atexit.register
-def _deltemps():
-    import os
-
-    global _tempfilestodel
-
-    while len(_tempfilestodel) > 0:
-        fn = _tempfilestodel.pop()
-        if os.path.isfile(fn):
-            os.remove(fn)
-
-
-def clear_data_cache(hashorurl=None):
-    """ Clears the data file cache by deleting the local file(s).
-
-    Parameters
-    ----------
-    hashorurl : str or None
-        If None, the whole cache is cleared.  Otherwise, either specifies a
-        hash for the cached file that is supposed to be deleted, or a URL that
-        has previously been downloaded to the cache.
-
-    Raises
-    ------
-    OSEerror
-        If the requested filename is not present in the data directory.
-
-    """
-    from os import unlink
-    from os.path import join, exists, abspath
-    from shutil import rmtree
-    from warnings import warn
-
-    try:
-        dldir, urlmapfn = _get_data_cache_locs()
-    except (IOError, OSError) as e:
-        msg = 'Not clearing data cache - cache inacessable due to '
-        estr = '' if len(e.args) < 1 else (': ' + str(e))
-        warn(CacheMissingWarning(msg + e.__class__.__name__ + estr))
-        return
-
-    _acquire_data_cache_lock()
-    try:
-
-        if hashorurl is None:
-            if exists(dldir):
-                rmtree(dldir)
-            if exists(urlmapfn):
-                unlink(urlmapfn)
-        else:
-            with _open_shelve(urlmapfn, True) as url2hash:
-                filepath = join(dldir, hashorurl)
-                assert abspath(filepath).startswith(abspath(dldir)), \
-                       ("attempted to use clear_data_cache on a location" +
-                        " that's not inside the data cache directory")
-
-                if exists(filepath):
-                    for k, v in url2hash.items():
-                        if v == filepath:
-                            del url2hash[k]
-                    unlink(filepath)
-
-                elif hashorurl in url2hash:
-                    filepath = url2hash[hashorurl]
-                    del url2hash[hashorurl]
-                    unlink(filepath)
-
-                else:
-                    msg = 'Could not find file or url {0}'
-                    raise OSError(msg.format(hashorurl))
-    finally:
-        _release_data_cache_lock()
-
-
-def _get_data_cache_locs():
-    """ Finds the path to the data cache directory.
-
-    Returns
-    -------
-    datadir : str
-        The path to the data cache directory.
-    shelveloc : str
-        The path to the shelve object that stores the cache info.
-    """
-    from .paths import get_cache_dir
-    from os.path import exists, isdir, join
-    from os import mkdir
-
-    datadir = join(get_cache_dir(), 'data')
-    shelveloc = join(get_cache_dir(), 'data_urlmap')
-    if not exists(datadir):
-        mkdir(datadir)
-    elif not isdir(datadir):
-        msg = 'Data cache directory {0} is not a directory'
-        raise IOError(msg.format(datadir))
-
-    if isdir(shelveloc):
-        msg = 'Data cache shelve object location {0} is a directory'
-        raise IOError(msg.format(shelveloc))
-
-    return datadir, shelveloc
-
-
-def _open_shelve(shelffn, withclosing=False):
-    """
-    opens a shelf in a way that is py3.x and py2.x compatible.  If
-    `withclosing` is  True, it will be opened with closing, allowing use like:
-
-        with _open_shelve('somefile',True) as s:
-            ...
-    """
-    import shelve
-    from contextlib import closing
-
-    if sys.version_info[0] > 2:  # pragma: py3
-        shelf = shelve.open(shelffn, protocol=2)
-    else:  # pragma: py2
-        shelf = shelve.open(shelffn + '.db', protocol=2)
-
-    if withclosing:
-        return closing(shelf)
-    else:
-        return shelf
-
-
-#the cache directory must be locked before any writes are performed.  Same for
-#the hash shelve, so this should be used for both.  Note
-def _acquire_data_cache_lock():
-    from os.path import join
-    from os import mkdir
-    from time import sleep
-
-    lockdir = join(_get_data_cache_locs()[0], 'lock')
-    for i in range(DATA_CACHE_LOCK_ATTEMPTS()):
-        try:
-            mkdir(lockdir)
-        except OSError:
-            sleep(1)
-        else:
-            return
-    msg = 'Unable to acquire lock for cache directory ({0} exists)'
-    raise RuntimeError(msg.format(lockdir))
-
-
-def _release_data_cache_lock():
-    from os.path import join, exists, isdir
-    from os import rmdir
-
-    lockdir = join(_get_data_cache_locs()[0], 'lock')
-
-    if exists(lockdir) and isdir(lockdir):
-        rmdir(lockdir)
-    else:
-        msg = 'Error releasing lock. "{0}" either does not exist or is not ' +\
-              'a directory.'
-        raise RuntimeError(msg.format(lockdir))
diff --git a/astropy/config/paths.py b/astropy/config/paths.py
index 7726cb0..da9b5ba 100644
--- a/astropy/config/paths.py
+++ b/astropy/config/paths.py
@@ -99,7 +99,7 @@ def get_config_dir(create=True):
     #first look for XDG_CONFIG_HOME
     xch = environ.get('XDG_CONFIG_HOME')
 
-    if xch is not None:
+    if xch is not None and path.exists(xch):
         xchpth = path.join(xch, 'astropy')
         if not path.islink(xchpth):
             if path.exists(xchpth):
@@ -133,7 +133,7 @@ def get_cache_dir():
     #first look for XDG_CACHE_HOME
     xch = environ.get('XDG_CACHE_HOME')
 
-    if xch is not None:
+    if xch is not None and path.exists(xch):
         xchpth = path.join(xch, 'astropy')
         if not path.islink(xchpth):
             if path.exists(xchpth):
diff --git a/astropy/config/setup_package.py b/astropy/config/setup_package.py
deleted file mode 100644
index 59e5b99..0000000
--- a/astropy/config/setup_package.py
+++ /dev/null
@@ -1,5 +0,0 @@
-def get_package_data():
-    # Installs the testing data files
-    return {
-        'astropy.config.tests': ['data/*.dat']
-        }
diff --git a/astropy/config/tests/test_configs.py b/astropy/config/tests/test_configs.py
index b95cf5b..aec28d9 100644
--- a/astropy/config/tests/test_configs.py
+++ b/astropy/config/tests/test_configs.py
@@ -127,7 +127,7 @@ def test_configitem_save(tmpdir):
 
 def test_configitem_types():
     from ..configuration import ConfigurationItem
-    from pytest import raises
+    from ...tests.helper import pytest
 
     ci1 = ConfigurationItem('tstnm1', 34)
     assert isinstance(ci1(), int)
@@ -141,18 +141,18 @@ def test_configitem_types():
     ci4 = ConfigurationItem('tstnm4', 'astring')
     assert isinstance(ci4(), str)
 
-    with raises(TypeError):
+    with pytest.raises(TypeError):
         ci1.set(34.3)
     ci2.set(12)  # this would should succeed as up-casting
-    with raises(TypeError):
+    with pytest.raises(TypeError):
         ci3.set('fasd')
-    with raises(TypeError):
+    with pytest.raises(TypeError):
         ci4.set(546.245)
 
 
 def test_configitem_options(tmpdir):
     from ..configuration import ConfigurationItem, get_config
-    from pytest import raises
+    from ...tests.helper import pytest
 
     cio = ConfigurationItem('tstnmo', ['op1', 'op2', 'op3'])
     sec = get_config(cio.module)
@@ -162,7 +162,7 @@ def test_configitem_options(tmpdir):
     assert sec['tstnmo'] == 'op1'
 
     cio.set('op2')
-    with raises(TypeError):
+    with pytest.raises(TypeError):
         cio.set('op5')
     assert sec['tstnmo'] == 'op2'
 
@@ -185,7 +185,7 @@ def test_config_noastropy_fallback(monkeypatch, recwarn):
     Tests to make sure configuration items fall back to their defaults when
     there's a problem accessing the astropy directory
     """
-    from pytest import raises
+    from ...tests.helper import pytest
     from .. import paths, configuration
 
     #make sure the config directory is not searched
@@ -201,7 +201,7 @@ def test_config_noastropy_fallback(monkeypatch, recwarn):
     # also have to make sure the stored configuration objects are cleared
     monkeypatch.setattr(configuration, '_cfgobjs', {})
 
-    with raises(OSError):
+    with pytest.raises(OSError):
         #make sure the config dir search fails
         paths.get_config_dir()
 
diff --git a/astropy/config/tests/test_data.py b/astropy/config/tests/test_data.py
deleted file mode 100644
index bff8ecf..0000000
--- a/astropy/config/tests/test_data.py
+++ /dev/null
@@ -1,166 +0,0 @@
-# Licensed under a 3-clause BSD style license - see LICENSE.rst
-from ...tests.helper import remote_data, raises
-
-import io
-
-TESTURL = 'http://www.google.com/index.html'
-
-
- at remote_data
-def test_url_cache():
-    from ..data import get_data_filename, clear_data_cache
-    from os.path import isfile
-
-    fnout = get_data_filename(TESTURL)
-    assert isfile(fnout)
-    clear_data_cache(TESTURL)
-    assert not isfile(fnout)
-
-
- at remote_data
-def test_url_nocache():
-    from ..data import get_data_fileobj
-
-    with get_data_fileobj(TESTURL, cache=False) as googlepage:
-        assert googlepage.read().decode().find('oogle</title>') > -1
-
-
- at remote_data
-def test_find_by_hash():
-    from ..data import get_data_fileobj, get_data_filename, clear_data_cache
-    from os.path import isfile
-    import hashlib
-
-    with get_data_fileobj(TESTURL) as googlepage:
-        hash = hashlib.md5(googlepage.read())
-
-    hashstr = 'hash/' + hash.hexdigest()
-
-    fnout = get_data_filename(hashstr)
-    assert isfile(fnout)
-    clear_data_cache(hashstr[5:])
-    assert not isfile(fnout)
-
-
-def test_local_data_obj():
-    from ..data import get_data_fileobj
-
-    with get_data_fileobj('data/local.dat') as f:
-        f.readline()
-        assert f.read().rstrip() == b'CONTENT'
-
-
-def test_local_data_name():
-    from ..data import get_data_filename
-    from os.path import isfile
-
-    fnout = get_data_filename('data/local.dat')
-    assert isfile(fnout) and fnout.endswith('local.dat')
-
-    #get something in the astropy root
-    fnout2 = get_data_filename('../../data/README.rst')
-    assert isfile(fnout2) and fnout2.endswith('README.rst')
-
-
- at raises(AssertionError)
-def test_local_data_nonlocalfail():
-    from ..data import get_data_filename
-
-    #this would go *outside* the atropy tree
-    fn = get_data_filename('../../../data/README.rst')
-
-
-def test_compute_hash(tmpdir):
-    import string
-    import tempfile
-    import hashlib
-    from ..data import compute_hash
-
-    rands = b'1234567890abcdefghijklmnopqrstuvwxyz'
-
-    filename = tmpdir.join('tmp.dat').strpath
-
-    with io.open(filename, 'wb') as ntf:
-        ntf.write(rands)
-        ntf.flush()
-
-    chhash = compute_hash(filename)
-    shash = hashlib.md5(rands).hexdigest()
-
-    assert chhash == shash
-
-
-def test_get_data_contents():
-    from ..data import get_data_fileobj, get_data_contents
-
-    with get_data_fileobj('data/local.dat') as f:
-        contents1 = f.read()
-
-    contents2 = get_data_contents('data/local.dat')
-
-    assert contents1 == contents2
-
-
- at remote_data
-def test_data_noastropy_fallback(monkeypatch, recwarn):
-    """
-    Tests to make sure configuration items fall back to their defaults when
-    there's a problem accessing the astropy directory
-    """
-    from os import path, remove
-    from pytest import raises
-    from .. import paths, data
-
-    #better yet, set the configuration to make sure the temp files are deleted
-    data.DELETE_TEMPORARY_DOWNLOADS_AT_EXIT.set(True)
-
-    #make sure the config directory is not searched
-    monkeypatch.setenv('XDG_CONFIG_HOME', 'foo')
-    monkeypatch.delenv('XDG_CONFIG_HOME')
-
-    # make sure the _find_or_create_astropy_dir function fails as though the
-    # astropy dir could not be accessed
-    def osraiser(dirnm, linkto):
-        raise OSError
-    monkeypatch.setattr(paths, '_find_or_create_astropy_dir', osraiser)
-
-    with raises(OSError):
-        #make sure the config dir search fails
-        paths.get_cache_dir()
-
-    #first try with cache
-    fnout = data.get_data_filename(TESTURL)
-    assert path.isfile(fnout)
-
-    assert len(recwarn.list) > 1
-    w1 = recwarn.pop()
-    w2 = recwarn.pop()
-
-    assert w1.category == data.CacheMissingWarning
-    assert 'Remote data cache could not be accessed' in w1.message.args[0]
-    assert w2.category == data.CacheMissingWarning
-    assert 'File downloaded to temp file' in w2.message.args[0]
-    assert fnout == w2.message.args[1]
-
-    #clearing the cache should be a no-up that doesn't affect fnout
-    data.clear_data_cache(TESTURL)
-    assert path.isfile(fnout)
-
-    #now remove it so tests don't clutter up the temp dir
-    #this should get called at exit, anyway, but we do it here just to make
-    #sure it's working correctly
-    data._deltemps()
-    assert not path.isfile(fnout)
-
-    assert len(recwarn.list) > 0
-    w3 = recwarn.pop()
-
-    assert w3.category == data.CacheMissingWarning
-    assert 'Not clearing data cache - cache inacessable' in str(w3.message)
-
-    #now try with no cache
-    with data.get_data_fileobj(TESTURL, cache=False) as googlepage:
-        assert googlepage.read().decode().find('oogle</title>') > -1
-
-    #no warnings should be raise in fileobj because cache is unnecessary
-    assert len(recwarn.list) == 0
diff --git a/astropy/constants/__init__.py b/astropy/constants/__init__.py
index db9b206..c2a0d17 100644
--- a/astropy/constants/__init__.py
+++ b/astropy/constants/__init__.py
@@ -40,7 +40,7 @@ __doc__ += """\
 """
 
 # update the si cand cgs module doctrings.
-for module in si,cgs:
+for module in si, cgs:
     module.__doc__ += """
 ========== ============== ================ =========================
    Name        Value            Unit       Description
@@ -49,7 +49,7 @@ for module in si,cgs:
     for nm, val in sorted(module.__dict__.items()):
         if isinstance(val, Constant):
             module.__doc__ += '{0:^10} {1:^14.9g} {2:^16} {3}\n'.format(
-                nm, val.real, val.units, val.name)
+                nm, val.value, val.unit, val.name)
 
     module.__doc__ += """\
 ========== ============== ================ =========================
diff --git a/astropy/constants/cgs.py b/astropy/constants/cgs.py
index ad0f959..51da345 100644
--- a/astropy/constants/cgs.py
+++ b/astropy/constants/cgs.py
@@ -5,106 +5,20 @@ available (with approximate values) are:
 """
 # This docstring is extended by __init__.py
 
-from .constant import Constant
-from . import si
-
-# PHYSICAL CONSTANTS
-
-# Planck constant
-h = Constant(si.h * 1.e7, si.h.error * 1.e7,
-             si.h.name, si.h.origin, 'erg.s')
-
-# Reduced Planck constant
-hbar = Constant(si.hbar * 1.e7, si.hbar.error * 1.e7,
-                si.hbar.name, si.hbar.origin, 'erg.s')
-
-# Boltzmann constant [CODATA]
-k_B = Constant(si.k_B * 1.e7, si.k_B.error * 1.e7,
-               si.k_B.name, si.k_B.origin, 'erg.s')
-
-# Speed of light [CODATA]
-c = Constant(si.c * 1.e2, si.c.error * 1.e2,
-             si.c.name, si.c.origin, 'cm/s')
-
-# Gravitional constant [CODATA]
-G = Constant(si.G * 1.e3, si.G.error * 1.e3,
-             si.G.name, si.G.origin, 'cm^3/g/s^2')
-
-# Proton mass [CODATA]
-m_p = Constant(si.m_p * 1.e3, si.m_p.error * 1.e3,
-               si.m_p.name, si.m_p.origin, 'g')
-
-# Neutron mass [CODATA]
-m_n = Constant(si.m_n * 1.e3, si.m_n.error * 1.e3,
-               si.m_n.name, si.m_n.origin, 'g')
-
-# Electron mass [CODATA]
-m_e = Constant(si.m_e * 1.e3, si.m_e.error * 1.e3,
-               si.m_e.name, si.m_e.origin, 'g')
-
-# Stefan-Boltzmann constant
-sigma_sb = Constant(si.sigma_sb * 1.e3, si.sigma_sb.error * 1.e3,
-                    si.sigma_sb.name, si.sigma_sb.origin,
-                    'erg/cm^2/K^4/s')
-
-# Electron charge
-e = Constant(si.e * si.c * 10., si.e.error * si.c * 10.,
-             si.e.name, si.e.origin, 'statC')
-
-# Avogadro's number
-N_A = Constant(si.N_A, si.N_A.error,
-               si.N_A.name, si.N_A.origin, '/mol')
+# The values of the constants in this module are defined in
+# `astropy/_constants/si.py` in order to avoid circular dependencies, since
+# Constant depends on Quantity, Quantity depends on Unit, and Unit depends on
+# the value of some of the constants, so they need to be kept separately.
 
-# Gas constant
-R = Constant(si.R * 1.e7, si.R.error * 1.e7,
-             si.R.name, si.R.origin, 'erg/K/mol')
-
-# Rydberg constant
-Ryd = Constant(si.Ryd * 1.e-2, si.Ryd.error * 1.e-2,
-               si.Ryd.name, si.Ryd.origin, 'cm^-1')
-
-# DISTANCE
-
-# Astronomical Unit
-au = Constant(si.au * 1.e2, si.au.error * 1.e2,
-              si.au.name, si.au.origin, 'cm')
-
-# Parsec
-pc = Constant(si.pc * 1.e2, si.pc.error * 1.e2,
-              si.pc.name, si.pc.origin, 'cm')
-
-# Kiloparsec
-kpc = Constant(si.kpc * 1.e2, si.kpc.error * 1.e2,
-               si.kpc.name, si.kpc.origin, 'cm')
-
-# SOLAR QUANTITIES
-
-# Solar luminosity
-L_sun = Constant(si.L_sun * 1.e7, si.L_sun.error * 1.e7,
-                 si.L_sun.name, si.L_sun.origin, 'erg/s')
-
-# Solar mass
-M_sun = Constant(si.M_sun * 1.e3, si.M_sun.error * 1.e3,
-                 si.M_sun.name, si.M_sun.origin, 'g')
-
-# Solar radius
-R_sun = Constant(si.R_sun * 1.e2, si.R_sun.error * 1.e2,
-                 si.R_sun.name, si.R_sun.origin, 'cm')
-
-# OTHER SOLAR SYSTEM QUANTITIES
-
-# Jupiter mass
-M_jup = Constant(si.M_jup * 1.e3, si.M_jup.error * 1.e3,
-                 si.M_jup.name, si.M_jup.origin, 'g')
-
-# Jupiter equatorial radius
-R_jup = Constant(si.R_jup * 1.e2, si.R_jup.error * 1.e2,
-                 si.R_jup.name, si.R_jup.origin, 'cm')
+from .constant import Constant
+from .._constants import cgs as _cgs
+from .._constants.definition import ConstantDefinition
 
-# Earth mass
-M_earth = Constant(si.M_earth * 1.e3, si.M_earth.error * 1.e3,
-                 si.M_earth.name, si.M_earth.origin, 'g')
+# Define actual Quantity-based Constants. Need to use _c in the loop instead
+# of c to avoid overwriting the speed of light constant.
+for nm, val in sorted(_cgs.__dict__.items()):
+    if isinstance(val, ConstantDefinition):
+        _c = Constant(val.value, val.units, val.uncertainty, val.name, val.reference)
+        locals()[nm] = _c
 
-# Earth equatorial radius
-R_earth = Constant(si.R_earth * 1.e2, si.R_earth.error * 1.e2,
-                 si.R_earth.name, si.R_earth.origin, 'cm')
+del _cgs, nm, val, _c
diff --git a/astropy/constants/constant.py b/astropy/constants/constant.py
index 1a87d04..f779847 100644
--- a/astropy/constants/constant.py
+++ b/astropy/constants/constant.py
@@ -1,53 +1,51 @@
 # Licensed under a 3-clause BSD style license - see LICENSE.rst
 
+from ..units.quantity import Quantity
 
-class Constant(float):
+__all__ = ['Constant']
+
+
+class Constant(Quantity):
     """A physical or astronomical constant.
 
-    Objects of this class behave just like `float` values when used in
-    expressions, but they contain additional information
+    These objects are quantities that are meant to represent physical constants
 
     Attributes
     ----------
     name : str
         The name of this constant.
-    error : float
+    uncertainty : float
         The uncertainty in the value of this constant.
-    origin : str
+    reference : str
         The source used for the value of this constant.
-    units : str
-        A string describing the units
-
-    .. warning ::
-        The `units` attribute will be replaced when the Astropy units package
-        is implemented. Don't count on it being a simple string in the future.
-
+    units : `astropy.units.UnitBase` instance
+        The units of this constant. Can be set either as a string or
+        `astropy.units.UnitBase`.
     """
 
-    def __init__(self, value, error, name, origin, units):
-        super(Constant, self).__init__()
-        self.error = error
+    def __init__(self, value, unit, uncertainty, name, reference):
+        super(Constant, self).__init__(value, unit)
+        self.uncertainty = uncertainty
         self.name = name
-        self.origin = origin
-        self.units = units
+        self.reference = reference
 
-    def __new__(cls, value, error, name, origin, units):
+    def __new__(cls, value, uncertainty, name, reference, units):
         return super(Constant, cls).__new__(cls, value)
 
     def __repr__(self):
-        s = "<{0}: ".format(self.__class__.__name__)
+        s = "<Constant: "
         s += "name='{0}' ".format(self.name)
-        s += "value={0} ".format(super(Constant, self).__repr__())
-        s += "error={0} ".format(self.error)
-        s += "units='{0}' ".format(self.units)
-        s += "origin='{0}' ".format(self.origin)
+        s += "value={0} ".format(self.value)
+        s += "error={0} ".format(self.uncertainty)
+        s += "units='{0}' ".format(self.unit)
+        s += "reference='{0}'".format(self.reference)
         s += ">"
         return s
 
     def __str__(self):
         s = "  Name   = {0}\n".format(self.name)
-        s += "  Value  = {0}\n".format(super(Constant, self).__repr__())
-        s += "  Error  = {0}\n".format(self.error)
-        s += "  Units = {0}\n".format(self.units)
-        s += "  Origin = {0}".format(self.origin)
+        s += "  Value  = {0}\n".format(self.value)
+        s += "  Error  = {0}\n".format(self.uncertainty)
+        s += "  Units = {0}\n".format(self.unit)
+        s += "  Reference = {0}".format(self.reference)
         return s
diff --git a/astropy/constants/si.py b/astropy/constants/si.py
index 48215d9..9baaf8e 100644
--- a/astropy/constants/si.py
+++ b/astropy/constants/si.py
@@ -5,129 +5,20 @@ available (with approximate values) are:
 """
 # This docstring is extended by __init__.py
 
-import numpy as np
-from .constant import Constant
-
-# PHYSICAL CONSTANTS
-
-# Planck constant
-h = Constant(6.62606957e-34, 0.00000029e-34,
-             "Planck constant",
-             'CODATA 2010', 'J.s')
-
-# Reduced Planck constant
-hbar = Constant(h * 0.5 / np.pi, h.error * 0.5 / np.pi,
-                "Reduced Planck constant",
-                'CODATA 2010', 'J.s')
-
-# Boltzmann constant
-k_B = Constant(1.3806488e-23, 0.0000013e-23,
-               "Boltzmann constant",
-               'CODATA 2010', 'J/K')
-
-# Speed of light
-c = Constant(2.99792458e8, 0.,
-             "Speed of light in vacuum",
-             'CODATA 2010', 'm/s')
-
-# Gravitional constant
-G = Constant(6.67384e-11, 0.00080e-11,
-             "Gravitational constant",
-             'CODATA 2010', 'm^3/kg/s^2')
-
-# Proton mass
-m_p = Constant(1.672621777e-27, 0.000000074e-27,
-               "Proton mass",
-               'CODATA 2010', 'kg')
-
-# Neutron mass
-m_n = Constant(1.674927351e-27, 0.000000074e-27,
-               "Neutron mass",
-               'CODATA 2010', 'kg')
-
-# Electron mass
-m_e = Constant(9.10938291e-31, 0.00000040e-31,
-               "Electron mass",
-               'CODATA 2010', 'kg')
-
-# Stefan-Boltzmann constant
-sigma_sb = Constant(5.670373e-8, 0.000021e-8,
-                    "Stefan-Boltzmann constant",
-                    'CODATA 2010', 'W/m^2/K^4')
-
-# Electron charge
-e = Constant(1.602176565e-19, 0.000000035e-19,
-             "Electron charge",
-             'CODATA 2010', 'C')
-
-# Avogadro's number
-N_A = Constant(6.02214129e23, 0.00000027e23,
-               "Avogadro's number",
-               'CODATA 2010', '/mol')
-
-# Gas constant
-R = Constant(8.3144621, 0.0000075,
-             "Gas constant",
-             'CODATA 2010', 'J/mol/K')
+# The values of the constants in this module are defined in
+# `astropy/_constants/si.py` in order to avoid circular dependencies, since
+# Constant depends on Quantity, Quantity depends on Unit, and Unit depends on
+# the value of some of the constants, so they need to be kept separately.
 
-# Rydberg constant
-Ryd = Constant(10973731.568539, 0.000055,
-               'Rydberg constant',
-               'CODATA 2010', 'm^-1')
-
-# DISTANCE
-
-# Astronomical Unit
-au = Constant(1.4959787066e11, 0.00000000005e11,
-              "Astronomical Unit",
-              "Allen's Astrophysical Quantities 4th Ed.", 'm')
-
-# Parsec
-pc = Constant(3.0856776e16, 0.00000005e16,
-              "Parsec",
-              "Allen's Astrophysical Quantities 4th Ed.", 'm')
-
-# Kiloparsec
-kpc = Constant(3.0856776e19, 0.00000005e19,
-              "Kiloparsec",
-              "Allen's Astrophysical Quantities 4th Ed.", 'm')
-
-# SOLAR QUANTITIES
-
-# Solar luminosity
-L_sun = Constant(3.846e26, 0.0005e26,
-                 "Solar luminosity",
-                 "Allen's Astrophysical Quantities 4th Ed.", 'W')
-
-# Solar mass
-M_sun = Constant(1.9891e30, 0.00005e30,
-                 "Solar mass",
-                 "Allen's Astrophysical Quantities 4th Ed.", 'kg')
-
-# Solar radius
-R_sun = Constant(6.95508e8, 0.00026e8,
-                 "Solar radius",
-                 "Allen's Astrophysical Quantities 4th Ed.", 'm')
-
-
-# OTHER SOLAR SYSTEM QUANTITIES
-
-# Jupiter mass
-M_jup = Constant(1.8987e27, 0.00005e27,
-                 "Jupiter mass",
-                 "Allen's Astrophysical Quantities 4th Ed.", 'kg')
-
-# Jupiter equatorial radius
-R_jup = Constant(7.1492e7, 0.00005e7,
-                 "Jupiter equatorial radius",
-                 "Allen's Astrophysical Quantities 4th Ed.", 'm')
+from .constant import Constant
+from .._constants import si as _si
+from .._constants.definition import ConstantDefinition
 
-# Earth mass
-M_earth = Constant(5.9742e24, 0.00005e24,
-                  "Earth mass",
-                  "Allen's Astrophysical Quantities 4th Ed.", 'kg')
+# Define actual Quantity-based Constants. Need to use _c in the loop instead
+# of c to avoid overwriting the speed of light constant.
+for nm, val in sorted(_si.__dict__.items()):
+    if isinstance(val, ConstantDefinition):
+        _c = Constant(val.value, val.units, val.uncertainty, val.name, val.reference)
+        locals()[nm] = _c
 
-# Earth equatorial radius
-R_earth = Constant(6.378136e6, 0.0000005e6,
-                   "Earth equatorial radius",
-                   "Allen's Astrophysical Quantities 4th Ed.", 'm')
+del _si, nm, val, _c
diff --git a/astropy/constants/tests/test_constant.py b/astropy/constants/tests/test_constant.py
index 6e28c06..cd8671b 100644
--- a/astropy/constants/tests/test_constant.py
+++ b/astropy/constants/tests/test_constant.py
@@ -6,36 +6,44 @@ from .. import Constant, si, cgs
 
 def test_c():
     #c is an exactly defined constant, so it shouldn't be changing
-    assert si.c == 2.99792458e8
-    assert cgs.c == 2.99792458e10
-
-    #check that the float-translation stuff works as expected
-    assert si.c.real == si.c * 1
-    assert cgs.c.real == cgs.c - 0
+    assert si.c.value == 2.99792458e8
+    assert cgs.c.value == 2.99792458e10
 
     #make sure it has the necessary attributes and they're not blank
-    assert si.c.error == 0  # c is a *defined* quantity
+    assert si.c.uncertainty == 0  # c is a *defined* quantity
     assert si.c.name
-    assert si.c.origin
-    assert si.c.units
-    assert cgs.c.error == 0  # c is a *defined* quantity
+    assert si.c.reference
+    assert si.c.unit
+    assert cgs.c.uncertainty == 0  # c is a *defined* quantity
     assert cgs.c.name
-    assert cgs.c.origin
-    assert cgs.c.units
+    assert cgs.c.reference
+    assert cgs.c.unit
 
 
 def test_h():
     #check that the value is fairly close to what it should be (not exactly
     #checking because this might get updated in the future)
-    assert abs(si.h - 6.626e-34) < 1e-38
-    assert abs(cgs.h - 6.626e-27) < 1e-31
+    assert abs(si.h.value - 6.626e-34) < 1e-38
+    assert abs(cgs.h.value - 6.626e-27) < 1e-31
 
     #make sure it has the necessary attributes and they're not blank
-    assert si.h.error
+    assert si.h.uncertainty
     assert si.h.name
-    assert si.h.origin
-    assert si.h.units
-    assert cgs.h.error
+    assert si.h.reference
+    assert si.h.unit
+    assert cgs.h.uncertainty
     assert cgs.h.name
-    assert cgs.h.origin
-    assert cgs.h.units
+    assert cgs.h.reference
+    assert cgs.h.unit
+
+
+def test_unit():
+
+    from ... import units as u
+
+    for key, val in si.__dict__.items() + cgs.__dict__.items():
+        if isinstance(val, Constant):
+            # Getting the unit forces the unit parser to run.  Confirm
+            # that none of the constants defined in astropy have
+            # invalid unit.
+            assert not isinstance(val.unit, u.UnrecognizedUnit)
diff --git a/astropy/coordinates/__init__.py b/astropy/coordinates/__init__.py
new file mode 100644
index 0000000..63c1a66
--- /dev/null
+++ b/astropy/coordinates/__init__.py
@@ -0,0 +1,16 @@
+# Licensed under a 3-clause BSD style license - see LICENSE.rst
+
+"""
+This subpackage contains classes and functions for celestial coordinates
+of astronomical objects. It also contains a framework for conversions
+between coordinate systems.
+"""
+
+from .errors import *
+from .angles import *
+from .coordsystems import *
+from .distances import *
+from .transformations import *
+from .builtin_systems import *
+
+__doc__ += builtin_systems._transform_graph_docs
\ No newline at end of file
diff --git a/astropy/coordinates/angle_utilities.py b/astropy/coordinates/angle_utilities.py
new file mode 100755
index 0000000..f43131c
--- /dev/null
+++ b/astropy/coordinates/angle_utilities.py
@@ -0,0 +1,616 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+# Licensed under a 3-clause BSD style license - see LICENSE.rst
+
+"""
+This module contains utility functions that are for internal use in
+astropy.coordinates.angles. Mainly they are conversions from one format
+of data to another.
+"""
+import re
+import math
+import inspect # NB: get the function name with: inspect.stack()[0][3]
+
+from .errors import *
+from ..utils import format_exception
+
+
+def _check_hour_range(hrs):
+    ''' Checks that the given value is in the range (-24,24). '''
+    if not -24. < hrs < 24.:
+        raise IllegalHourError(hrs)
+
+
+def _check_minute_range(min):
+    ''' Checks that the given value is in the range [0,60). '''
+    if not 0. <= min < 60.:
+        # "Error: minutes not in range [0,60) ({0}).".format(min))
+        raise IllegalMinuteError(min)
+
+
+def _check_second_range(sec):
+    ''' Checks that the given value is in the range [0,60). '''
+    if not 0. <= sec < 60.:
+        # "Error: seconds not in range [0,60) ({0}).".format(sec))
+        raise IllegalSecondError(sec)
+
+
+def check_hms_ranges(h, m, s):
+    _check_hour_range(h)
+    _check_minute_range(m)
+    _check_second_range(s)
+    return None
+
+# these regexes are used in parse_degrees
+# accept these as (one or more repeated) delimiters: :, whitespace, /
+_dms_div_regex_str = '[:|/|\t|\-|\sDdMmSs]{1,2}'
+# Look for a pattern where d,m,s is specified
+_dms_regex = re.compile('^([+-]{0,1}\d{1,3})' + _dms_div_regex_str +
+                        '(\d{1,2})' + _dms_div_regex_str +
+                        '(\d{1,2}[\.0-9]*)' + '[Ss]{0,1}' + '$')
+# look for a pattern where only d,m is specified
+_dm_regex = re.compile('^([+-]{0,1}\d{1,3})' + _dms_div_regex_str +
+                       '(\d{1,2})' + '[Mm]{0,1}' + '$')
+
+
+def parse_degrees(degrees, output_dms=False):
+    """
+    Parses an input "degrees" value into decimal degrees or a
+    degree,arcminute,arcsecond tuple.
+
+    Convert degrees given in any parseable format (float, string, or Angle)
+    into degrees, arcminutes, and arcseconds components or decimal degrees.
+
+    Parameters
+    ----------
+    degrees : float, int, str
+        If a string, accepts values in these formats:
+            * [+|-]DD:MM:SS.sss (string), e.g. +12:52:32.423 or -12:52:32.423
+            * DD.dddd (float, string), e.g. 12.542326
+            * DD MM SS.sss (string, array), e.g. +12 52 32.423
+        Whitespace may be spaces and/or tabs.
+    output_dms : bool
+        If True, returns a tuple of (degree, arcminute, arcsecond)
+
+    Returns
+    -------
+    deg : float or tuple
+         Returns degrees in decimal form unless the keyword "output_dms" is
+         True, in which case a tuple (d, m, s).
+    """
+
+    from .angles import Angle
+
+    # either a string or a float
+    x = degrees
+
+    if isinstance(x, float) or isinstance(x, int):
+        parsed_degrees = float(x)
+
+    elif isinstance(x, basestring):
+        x = x.strip()
+
+        string_parsed = False
+
+        # See if the string is just a float or int value.
+        try:
+            parsed_degrees = float(x)
+            string_parsed = True
+        except ValueError:
+            pass
+
+        if not string_parsed:
+            try:
+                elems = _dms_regex.search(x).groups()
+                parsed_degrees = dms_to_degrees(
+                    int(elems[0]), int(elems[1]), float(elems[2]))
+                string_parsed = True
+            except AttributeError:
+                # regular expression did not match - try again below
+                # make sure to let things like IllegalMinuteError, etc. through
+                pass
+
+        if not string_parsed:
+            try:
+                elems = _dm_regex.search(x).groups()
+                parsed_degrees = dms_to_degrees(
+                    int(elems[0]), int(elems[1]), 0.0)
+                string_parsed = True
+            except AttributeError:
+                # regular expression did not match - try again below
+                # make sure to let things like IllegalMinuteError, etc. through
+                pass
+
+        if not string_parsed:
+            # look for a '°' symbol
+            for unitStr in ["degrees", "degree", "deg", "d", "°"]:
+                x = x.replace(unitStr, '')
+                try:
+                    parsed_degrees = float(x)
+                    string_parsed = True
+                except ValueError:
+                    pass
+
+        if not string_parsed:
+            raise ValueError(format_exception(
+                "{func}: Invalid input string! ('{0}')", x))
+
+    elif isinstance(x, Angle):
+        parsed_degrees = x.degrees
+
+    elif isinstance(x, tuple):
+        parsed_degrees = dms_to_degrees(*x)
+
+    else:
+        raise ValueError(format_exception(
+            "{func}: could not parse value of {0}.", type(x)))
+
+    return degrees_to_dms(parsed_degrees) if output_dms else parsed_degrees
+
+
+# these regexes are used in parse_hours
+# accept these as (one or more repeated) delimiters: :, whitespace, /
+_hms_div_regex_str = '[:|/|\t|\-|\sHhMmSs]{1,2}'
+# Look for a pattern where h,m,s is specified
+_hms_regex = re.compile('^([+-]{0,1}\d{1,2})' + _hms_div_regex_str +
+                        '(\d{1,2})' + _hms_div_regex_str +
+                        '(\d{1,2}[\.0-9]*)' + '[Ss]{0,1}' + '$')
+# look for a pattern where only h,m is specified
+_hm_regex = re.compile('^([+-]{0,1}\d{1,2})' + _hms_div_regex_str +
+                       '(\d{1,2})' + '[Mm]{0,1}' + '$')
+
+
+def parse_hours(hours, output_hms=False):
+    """
+    Returns an hour value (as a decimal or HMS tuple) from the integer, float,
+    or string provided.
+
+    Convert hours given in any parseable format (float, string, tuple, list, or
+    Angle) into hour, minute, and seconds components or decimal hours.
+
+    Parameters
+    ----------
+    hours : float, str, int
+        If a string, accepts values in these formats:
+            * HH:MM:SS.sss (string), e.g. 12:52:32.423
+            * HH.dddd (float, string), e.g. 12.542326
+            * HH MM SS.sss (string, array), e.g. 12 52 32.423
+        Surrounding whitespace in a string value is allowed.
+    output_hms : bool
+        If True, returns a tuple of (hour, minute, second)
+
+    Returns
+    -------
+    hrs : float or tuple
+         Returns degrees in hours form unless the keyword "output_dms" is
+         True, in which case a tuple (h, m, s).
+    """
+    import datetime as py_datetime
+
+    from .angles import Angle
+
+    # either a string or a float
+    x = hours
+
+    if isinstance(x, float) or isinstance(x, int):
+        parsed_hours = x
+        parsed_hms = hours_to_hms(parsed_hours)
+
+    elif isinstance(x, basestring):
+        x = x.strip()
+
+        try:
+            parsed_hours = float(x)
+            parsed_hms = hours_to_hms(parsed_hours)
+        except ValueError:
+
+            string_parsed = False
+
+            try:
+                elems = _hms_regex.search(x).groups()
+                string_parsed = True
+            except:
+                pass  # try again below
+
+            if string_parsed:
+                h, m, s = float(elems[0]), int(elems[1]), float(elems[2])
+                parsed_hours = hms_to_hours(h, m, s)
+                parsed_hms = (h, m, s)
+
+            else:
+                try:
+                    elems = _hm_regex.search(x).groups()
+                    string_parsed = True
+                except:
+                    raise ValueError(format_exception(
+                        "{func}: Invalid input string, can't parse to "
+                        "HMS. ({0})", x))
+                h, m, s = float(elems[0]), int(elems[1]), 0.0
+                parsed_hours = hms_to_hours(h, m, s)
+                parsed_hms = (h, m, s)
+
+    elif isinstance(x, Angle):
+        parsed_hours = x.hours
+        parsed_hms = hours_to_hms(parsed_hours)
+
+    #TODO: make a decision as to whether or not to allow datetime objects
+    #elif isinstance(x, py_datetime.datetime):
+    #    parsed_hours = datetimeToDecimalTime(x)
+    #    parsed_hms = hours_to_hms(parsed_hours)
+
+    elif isinstance(x, tuple):
+        if len(x) == 3:
+            parsed_hours = hms_to_hours(*x)
+            parsed_hms = x
+        else:
+            raise ValueError(format_exception(
+                "{filename}:{func}: Incorrect number of values given, expected "
+                "(h,m,s), got: {0}", x))
+
+    elif isinstance(x, list):
+        if len(x) == 3:
+            try:
+                h = float(x[0])
+                m = float(x[1])
+                s = float(x[2])
+            except ValueError:
+                raise ValueError(format_exception(
+                    "{filename}:{func}: Array values ([h,m,s] expected) "
+                    "could not be coerced into floats. {0}", x))
+
+            parsed_hours = hms_to_hours(h, m, s)
+            parsed_hms = (h, m, s)
+            if output_hms:
+                return (h, m, s)
+            else:
+                return hms_to_hours(h, m, s)
+
+        else:
+            raise ValueError(format_exception(
+                "{filename}:{func}: Array given must contain exactly three "
+                "elements ([h,m,s]), provided: {0}", x))
+
+    else:
+        raise ValueError(
+            "parse_hours: could not parse value of type "
+            "{0}.".format(type(x).__name__))
+
+    if output_hms:
+        return parsed_hms
+    else:
+        return parsed_hours
+
+
+def parse_radians(radians):
+    """
+    Parses an input "radians" value into a float number.
+
+    Convert radians given in any parseable format (float or Angle) into float
+    radians.
+
+    ..Note::
+        This function is mostly for consistency with the other "parse"
+        functions, like parse_hours and parse_degrees.
+
+    Parameters
+    ----------
+    radians : float, int, Angle
+        The input angle.
+    """
+
+    from .angles import Angle
+
+    x = radians
+
+    if type(x) in [float, int]:
+        return float(x)
+    elif isinstance(x, Angle):
+        return x.radians
+    else:
+        raise ValueError(format_exception(
+            "{func}: could not parse value of type {0}.", type(x).__name__))
+
+
+def degrees_to_dms(d):
+    """
+    Convert any parseable degree value (see: parse_degrees) into a
+    ``(degree, arcminute, arcsecond)`` tuple.
+    """
+    sign = math.copysign(1.0, d)
+
+    (df, d) = math.modf(abs(d))  # (degree fraction, degree)
+    (mf, m) = math.modf(df * 60.)  # (minute fraction, minute)
+    s = mf * 60.
+
+    _check_minute_range(m)
+    _check_second_range(s)
+
+    return (float(sign * d), int(sign * m), sign * s)
+
+
+def dms_to_degrees(d, m, s):
+    """ Convert degrees, arcminute, arcsecond to a float degrees value. """
+
+    _check_minute_range(m)
+    _check_second_range(s)
+
+   # determine sign
+    sign = math.copysign(1.0, d)
+
+    try:
+        d = int(abs(d))
+        m = int(abs(m))
+        s = float(abs(s))
+    except ValueError:
+        raise ValueError(format_exception(
+            "{func}: dms values ({1[0]},{2[1]},{3[2]}) could not be "
+            "converted to numbers.", d, m, s))
+
+    return sign * (d + m / 60. + s / 3600.)
+
+
+def hms_to_hours(h, m, s):
+    """ Convert hour, minute, second to a float hour value. """
+
+    check_hms_ranges(h, m, s)
+
+    try:
+        h = int(h)
+        m = int(m)
+        s = float(s)
+    except ValueError:
+        raise ValueError(format_exception(
+            "{func}: HMS values ({1[0]},{2[1]},{3[2]}) could not be "
+            "converted to numbers.", h, m, s))
+
+    return h + m / 60. + s / 3600.
+
+
+def hms_to_degrees(h, m, s):
+    """ Convert hour, minute, second to a float degrees value. """
+
+    return hms_to_hours(h, m, s) * 15.
+
+
+def hms_to_radians(h, m, s):
+    """ Convert hour, minute, second to a float radians value. """
+
+    return math.radians(hms_to_degrees(h, m, s))
+
+
+def hms_to_dms(h, m, s):
+    """
+    Convert degrees, arcminutes, arcseconds to an ``(hour, minute, second)``
+    tuple.
+    """
+
+    return degrees_to_dms(hms_to_degrees(h, m, s))
+
+
+def hours_to_decimal(h):
+    """
+    Convert any parseable hour value (see: parse_hours) into a float value.
+    """
+
+    return parse_hours(h, output_hms=False)
+
+
+def hours_to_radians(h):
+    """ Convert an angle in Hours to Radians. """
+
+    return math.radians(h * 15.)
+
+
+def hours_to_hms(h):
+    """
+    Convert any parseable hour value (see: parse_hours) into an
+    ``(hour, minute, second)`` tuple.
+    """
+
+    sign = math.copysign(1.0, h)
+
+    (hf, h) = math.modf(abs(h))  # (degree fraction, degree)
+    (mf, m) = math.modf(hf * 60.0)  # (minute fraction, minute)
+    s = mf * 60.0
+
+    check_hms_ranges(h, m, s)  # throws exception if out of range
+
+    return (float(sign * h), int(sign * m), sign * s)
+
+
+def radians_to_degrees(r):
+    """ Convert an angle in Radians to Degrees """
+
+    try:
+        r = float(r)
+    except ValueError:
+        raise ValueError(format_exception(
+            "{func}: degree value ({1[0]}) could not be converted to a "
+            "float.", r))
+
+    return math.degrees(r)
+
+
+def radians_to_hours(r):
+    """ Convert an angle in Radians to Hours """
+
+    return radians_to_degrees(r) / 15.
+
+
+def radians_to_hms(r):
+    """ Convert an angle in Radians to an hour,minute,second tuple """
+
+    hours = radians_to_hours(r)
+    return hours_to_hms(hours)
+
+
+def radians_to_dms(r):
+    """ Convert an angle in Radians to an degree,arcminute,arcsecond tuple """
+
+    degrees = math.degrees(r)
+    return degrees_to_dms(degrees)
+
+
+def hours_to_string(h, precision=5, pad=False, sep=('h', 'm', 's')):
+    """
+    Takes a decimal hour value and returns a string formatted as hms with
+    separator specified by the 'sep' parameter.
+
+    TODO: More detailed description here!
+    """
+
+    if pad:
+        pad = 2
+    else:
+        pad = 0
+
+    if not isinstance(sep, tuple):
+        # Note: This will convert 'hms' to ('h', 'm', 's'); a potentially nice
+        # shortcut
+        sep = tuple(sep)
+
+    if len(sep) == 1:
+        sep = sep + (sep[0], '')
+    elif len(sep) == 2:
+        sep = sep + ('',)
+    elif len(sep) != 3:
+        raise ValueError(
+            "Invalid separator specification for converting angle to string.")
+
+    literal = ('{0:0{pad}.0f}{sep[0]}{1:02d}{sep[1]}{2:0{width}.{precision}f}'
+               '{sep[2]}')
+    h, m, s = hours_to_hms(h)
+    return literal.format(h, abs(m), abs(s), sep=sep, pad=pad,
+                          width=(precision + 3), precision=precision)
+
+
+def degrees_to_string(d, precision=5, pad=False, sep=':'):
+    """
+    Takes a decimal hour value and returns a string formatted as dms with
+    separator specified by the 'sep' parameter.
+    """
+
+    if pad:
+        pad = 2
+    else:
+        pad = 0
+
+    if not isinstance(sep, tuple):
+        sep = tuple(sep)
+
+    if len(sep) == 1:
+        sep = sep + (sep[0], '')
+    elif len(sep) == 2:
+        sep = sep + ('',)
+    elif len(sep) != 3:
+        raise ValueError(
+            "Invalid separator specification for converting angle to string.")
+
+    literal = ('{0:0{pad}.0f}{sep[0]}{1:02d}{sep[1]}{2:0{width}.{precision}f}'
+               '{sep[2]}')
+    d, m, s = degrees_to_dms(d)
+    return literal.format(d, abs(m), abs(s), sep=sep, pad=pad,
+                          width=(precision + 3), precision=precision)
+
+
+#<----------Spherical angular distances------------->
+def small_angle_sphere_dist(lon1, lat1, lon2, lat2):
+    """
+    Euclidean angular distance "on a sphere" - only valid on sphere in the
+    small-angle approximation.
+
+    .. warning::
+        Do not use this unless you know small-angle is a valid approximation
+        for your problem and performance is a major conern.  In general this
+        is very wrong.
+
+    Inputs must be in radians.
+    """
+
+    from math import cos
+
+    dlat = lat2 - lat1
+    dlon = (lon2 - lon1) * cos((lat1 + lat2) / 2.)
+
+    return (dlat ** 2 + dlon ** 2) ** 0.5
+
+
+def simple_sphere_dist(lon1, lat1, lon2, lat2):
+    """
+    Simple formula for angular distance on a sphere: numerically unstable
+    for small distances.
+
+    Inputs must be in radians.
+    """
+
+    # FIXME: array: use numpy functions
+    from math import acos, sin, cos
+
+    cdlon = cos(lon2 - lon1)
+    return acos(sin(lat1) * sin(lat2) + cos(lat1) * cos(-lat2) * cdlon)
+
+
+def haversine_sphere_dist(lon1, lat1, lon2, lat2):
+    """
+    Haversine formula for angular distance on a sphere: more stable at poles
+
+    Inputs must be in radians.
+    """
+
+    # FIXME: array: use numpy functions
+    from math import asin, sin, cos
+
+    sdlat = sin((lat2 - lat1) / 2)
+    sdlon = sin((lon2 - lon1) / 2)
+    coslats = cos(lat1) * cos(lat2)
+
+    return 2 * asin((sdlat ** 2 + coslats * sdlon ** 2) ** 0.5)
+
+
+def haversine_atan_sphere_dist(lon1, lat1, lon2, lat2):
+    """
+    Haversine formula for angular distance on a sphere: more stable at poles.
+    This version uses arctan instead of arcsin and thus does better with sign
+    conventions.
+
+    Inputs must be in radians.
+    """
+
+    # FIXME: array: use numpy functions
+    from math import atan2, sin, cos
+
+    sdlat = sin((lat2 - lat1) / 2)
+    sdlon = sin((lon2 - lon1) / 2)
+    coslats = cos(lat1) * cos(lat2)
+
+    numerator = sdlat ** 2 + coslats * sdlon ** 2
+
+    return 2 * atan2(numerator ** 0.5, (1 - numerator) ** 0.5)
+
+
+def vincenty_sphere_dist(lon1, lat1, lon2, lat2):
+    """
+    Vincenty formula for angular distance on a sphere: stable at poles and
+    antipodes but more complex/computationally expensive.
+
+    Note that this is the only version actually used in the `AngularSeparation`
+    classes, so the other `*_spher_dist` functions are only for possible
+    future internal use.
+
+    Inputs must be in radians.
+    """
+    #FIXME: array: use numpy functions
+    from math import atan2, sin, cos
+
+    sdlon = sin(lon2 - lon1)
+    cdlon = cos(lon2 - lon1)
+    slat1 = sin(lat1)
+    slat2 = sin(lat2)
+    clat1 = cos(lat1)
+    clat2 = cos(lat2)
+
+    num1 = clat2 * sdlon
+    num2 = clat1 * slat2 - slat1 * clat2 * cdlon
+    denominator = slat1 * slat2 + clat1 * clat2 * cdlon
+
+    return atan2((num1 ** 2 + num2 ** 2) ** 0.5, denominator)
diff --git a/astropy/coordinates/angles.py b/astropy/coordinates/angles.py
new file mode 100644
index 0000000..5a94cfb
--- /dev/null
+++ b/astropy/coordinates/angles.py
@@ -0,0 +1,824 @@
+# -*- coding: utf-8 -*-
+# Licensed under a 3-clause BSD style license - see LICENSE.rst
+
+"""
+This module contains the fundamental classes used for representing
+coordinates in astropy.
+"""
+
+import math
+
+import numpy as np
+
+from . import angle_utilities as util
+from .errors import *
+from .. import units as u
+from ..utils.compat.odict import OrderedDict
+
+__all__ = ['Angle', 'RA', 'Dec', 'AngularSeparation']
+
+TWOPI = math.pi * 2.0  # no need to calculate this all the time
+
+
+#used in Angle initializer to convert various strings into their parseable forms
+_unitstrmap = OrderedDict([
+   ("degrees", 'd'),
+   ("degree", 'd'),
+   ("deg", 'd'),
+   ("°", 'd'),
+   ("hours", 'h'),
+   ("hour", 'h'),
+   ("hr", 'h'),
+   ("radians", ''),
+   ("radian", ''),
+   ("rad", ''),
+   ("d", 'd'),
+   ("h", 'h')])
+
+
+class Angle(object):
+    """ An angle.
+
+    An angle can be specified either as a float, tuple (see below),
+    or string.  If A string, it must be in one of the following formats:
+
+    * '1:2:3.4'
+    * '1 2 3.4'
+    * '1h2m3.4s'
+    * '1d2m3.4s'
+
+    Parameters
+    ----------
+    angle : float, int, str, tuple
+        The angle value. If a tuple, will be interpreted as (h, m s) or
+        (d, m, s) depending on `unit`. If a string, it will be interpreted
+        following the rules described above.
+    unit : `~astropy.units.UnitBase`, str
+        The unit of the value specified for the angle.  This may be any
+        string that `~astropy.units.Unit` understands, but it is better to
+        give an actual unit object.  Must be one of `~astropy.units.degree`,
+        `~astropy.units.radian`, or `~astropy.units.hour`.
+    bounds : tuple
+        A tuple indicating the upper and lower value that the new angle object may
+        have.
+
+    Raises
+    ------
+    `~astropy.coordinates.errors.UnitsError`
+        If a unit is not provided or it is not hour, radian, or degree.
+
+    """
+
+    def __init__(self, angle, unit=None, bounds=(-360, 360)):
+        from ..utils import isiterable
+
+        self._bounds = bounds
+
+        if isinstance(angle, Angle):
+            angle = angle.radians
+            unit = u.radian
+
+        self.is_array = (isiterable(angle) and
+                         not isinstance(angle, basestring) and
+                         not isinstance(angle, tuple))
+
+        # short circuit arrays for now
+        if self.is_array:
+            raise NotImplementedError("Angles as arrays are not yet supported.")
+
+        # -------------------------------
+        # unit validation and angle value
+        # -------------------------------
+        if isinstance(unit, u.UnitBase):
+            pass
+        elif isinstance(unit, basestring):
+            unit = u.Unit(unit)
+        elif unit is None:
+            # try to determine unit from the "angle" value
+            if self.is_array:
+                # this is currently unreachable, but in principal should work when arrays are added in the future
+                try:
+                    angle = [x.lower() for x in angle]
+                except AttributeError:
+                        # If units are not specified as a parameter, the only chance
+                        # to determine them is in a string value - if it's not a string,
+                        # then there's not enough information to create an Angle.
+                        raise UnitsError("Could not parse an angle value in the array provided"
+                                         "- units could not be determined.".format(angle[idx]))
+                for idx, a in enumerate(angle):
+                    a_unit = None
+                    # order is important here - longest name first
+                    for unitStr in ["degrees", "degree", "deg", "°"]:
+                        if unitStr in a:
+                            a_unit = u.radian
+                            a = angle.replace(unitStr, "")
+                            angle[idx] = math.radians(util.parse_degrees(a))
+                            break
+                    if unit is None:
+                        for unitStr in ["hours", "hour", "hr"]:
+                            if unitStr in a:
+                                a_unit = u.radian
+                                a = angle.replace(unitStr, "")
+                                angle[idx] = math.radians(util.parse_hours(a) * 15.)
+                                break
+                    if unit is None:
+                        for unitStr in ["radians", "radian", "rad"]:
+                            if unitStr in angle:
+                                a_unit = u.radian
+                                a = angle.replace(unitStr, "")
+                                angle[idx] = util.parse_radians(a)
+                                break
+                    if a_unit is None:
+                        raise UnitsError('Could not parse the angle value "{0}" '
+                                         '- units could not be determined.'.format(angle[idx]))
+                unit = u.radian
+
+            else:  # single value
+                if isinstance(angle, basestring):
+                    inputangle = angle
+                    angle = angle.lower().strip()
+
+                    for fromstr, tostr in _unitstrmap.iteritems():
+                        if fromstr in angle:
+                            angle = angle.replace(fromstr, tostr)
+                            if tostr == "h":
+                                unit = u.hour
+                                # this is for "1:2:3.4 hours" case
+                                if angle[-1] == 'h':
+                                    angle = angle[:-1]
+                            elif tostr == "d":
+                                unit = u.degree
+                                # this is for "1:2:3.4 degrees" case
+                                if angle[-1] == 'd':
+                                    angle = angle[:-1]
+                            elif tostr == "":
+                                unit = u.radian
+                            else:
+                                raise ValueError('Unrecognized tostr... this should never happen!')
+                            break
+                    else:
+                        raise UnitsError('Could not infer Angle units '
+                            'from provided string "{0}"'.format(inputangle))
+
+
+
+        else:
+            raise UnitsError('Requested unit "{0}" for Angle, which could not be '
+                'interpreted as a unit - should be a string or astropy.units '
+                'unit object'.format(unit))
+
+        if unit is None:
+            raise UnitsError("No unit was specified in Angle initializer; the "
+                "unit parameter should be an object from the  astropy.units "
+                "module (e.g. 'from astropy import units as u', then use "
+                "'u.degree').")
+
+        if self.is_array:
+            pass  # already performed conversions to radians above
+        else:
+            if unit is u.degree:
+                self._radians = math.radians(util.parse_degrees(angle))
+            elif unit is u.radian:
+                self._radians = float(angle)
+            elif unit is u.hour:
+                self._radians = util.hours_to_radians(util.parse_hours(angle))
+            else:
+                raise UnitsError("The unit value provided was not one of u.degree, u.hour, u.radian'.")
+
+        # ---------------
+        # bounds checking
+        # ---------------
+        # TODO: handle arrays
+        # handle bounds units, convert to radians
+        if bounds == None:
+            pass  # no range checking performed
+        else:
+            try:
+                if unit is u.radian:
+                    lower_bound = bounds[0]
+                    upper_bound = bounds[1]
+                elif unit is u.degree:
+                    lower_bound = math.radians(bounds[0])
+                    upper_bound = math.radians(bounds[1])
+                elif unit is u.hour:
+                    lower_bound = math.radians(bounds[0] * 15.)
+                    upper_bound = math.radians(bounds[1] * 15.)
+                # invalid units handled above
+            except TypeError:
+                raise TypeError("Bounds specified for Angle must be a two element list, "
+                                "e.g. [0,360] (was given '{0}').".format(type(bounds).__name__))
+
+            # bounds check
+            if lower_bound < self._radians < upper_bound:
+                pass  # looks good
+            else:
+                if self._radians > upper_bound:
+                    while True:
+                        self._radians -= TWOPI
+                        if self._radians < lower_bound:
+                            raise BoundsError("The angle given falls outside of the specified bounds.")
+                        elif lower_bound < self._radians < upper_bound:
+                            break
+
+                if self._radians < lower_bound:
+                    while True:
+                        self._radians += TWOPI
+                        if self._radians > upper_bound:
+                            raise BoundsError("The angle given falls outside of the specified bounds.")
+                        elif lower_bound < self._radians < upper_bound:
+                            break
+
+    @property
+    def bounds(self):
+        """" The angle's bounds, an immutable property. """
+        return self._bounds
+
+    @property
+    def degrees(self):
+        """ The angle's value in degrees (read-only property). """
+        return math.degrees(self.radians)  # converts radians to degrees
+
+    @property
+    def radians(self):
+        """ The angle's value in radians (read-only property). """
+        return self._radians
+
+    @property
+    def hours(self):
+        """ The angle's value in hours (read-only property). """
+        return util.radians_to_hours(self.radians)
+
+    @property
+    def hms(self):
+        """ The angle's value in hours, and print as an (h,m,s) tuple (read-only property). """
+        return util.radians_to_hms(self.radians)
+
+    @property
+    def dms(self):
+        """ The angle's value in degrees, and print as an (d,m,s) tuple (read-only property). """
+        return util.radians_to_dms(self.radians)
+
+    def format(self, unit=u.degree, decimal=False, sep='fromunit', precision=5,
+               alwayssign=False, pad=False):
+        """ A string representation of the angle.
+
+        Parameters
+        ----------
+        units : `~astropy.units.UnitBase`
+            Specifies the units, should be 'degree', 'hour', or 'radian'
+        decimal : bool
+            If True, a decimal respresentation will be used, otherwise
+            the returned string will be in sexagesimal form.
+        sep : str
+            The separator between numbers in a sexagesimal representation.
+            E.g., if it is ':', the result is "12:41:11.1241". Also accepts
+            2 or 3 separators. E.g., ``sep='hms'`` would give the result
+            "12h41m11.1241s", or sep='-:' would yield "11-21:17.124".
+            Alternatively, the special string 'fromunit' means 'dms' if
+            the unit is degrees, or 'hms' if the unit is hours.
+        precision : int
+            The level of decimal precision.  if `decimal` is True, this is
+            the raw precision, otherwise it gives the precision of the last
+            place of the sexagesimal representation (seconds).
+        alwayssign : bool
+            If True, include the sign no matter what.  If False, only
+            include the sign if it is necessary (negative).
+        pad : bool
+            If True, include leading zeros when needed to ensure a fixed
+            number of characters for sexagesimal representation.
+
+        Returns
+        -------
+        strrepr : str
+            A string representation of the angle.
+
+        """
+        unit = u.Unit(unit)
+
+        if unit is u.degree:
+            if decimal:
+                res = ("{0:0." + str(precision) + "}").format(self.degrees)
+            else:
+                if sep == 'fromunit':
+                    sep = 'dms'
+                res = util.degrees_to_string(self.degrees, precision=precision, sep=sep, pad=pad)
+
+        elif unit is u.radian:
+            if decimal:
+                res = ("{0:0." + str(precision) + "}").format(self.radians)
+            elif sep == 'fromunit':
+                res = ("{0:0." + str(precision) + "}").format(self.radians) + 'radian'
+            else:
+                raise ValueError('Radians cannot be in sexagesimal representation')
+
+        elif unit is u.hour:
+            if decimal:
+                res = ("{0:0." + str(precision) + "}").format(self.hours)
+            else:
+                if sep == 'fromunit':
+                    sep = 'hms'
+                res = util.hours_to_string(self.hours, precision=precision, sep=sep, pad=pad)
+        else:
+            raise UnitsError("The unit value provided was not one of u.degree, u.hour, u.radian'.")
+
+        if alwayssign and not res.startswith('-'):
+            return '+' + res
+        else:
+            return res
+
+    def __str__(self):
+        return self.format()
+
+    # ----------------------------------------------------------------------------
+    # Emulating numeric types
+    # -----------------------
+    # Ref: http://docs.python.org/reference/datamodel.html#emulating-numeric-types
+    # ----------------------------------------------------------------------------
+
+    # Addition
+    def __add__(self, other):
+        if isinstance(other, type(self)):
+            if self.bounds != other.bounds:
+                msg = "Can't add angles because bounds don't match: {0} and {1}"
+                raise ValueError(msg.format(self.bounds, other.bounds))
+            else:
+                return Angle(self.radians + other.radians, unit=u.radian, bounds=self.bounds)
+        else:
+            raise NotImplementedError("An {0} object can only be added to another "
+                                      "{0} object.".format(type(self).__name__))
+
+    def __radd__(self, other):
+        return self.__add__(other)
+
+    # Subtraction
+    def __sub__(self, other):
+        if isinstance(other, type(self)):
+            if self.bounds != other.bounds:
+                msg = "Can't add angles because bounds don't match: {0} and {1}"
+                raise ValueError(msg.format(self.bounds, other.bounds))
+            else:
+                return Angle(self.radians - other.radians, unit=u.radian, bounds=self.bounds)
+        else:
+            raise NotImplementedError("An {0} object can only be subtracted from another "
+                                      "{0} object.".format(type(self).__name__))
+
+    def __rsub__(self, other):
+        if isinstance(other, type(self)):
+            if self.bounds != other.bounds:
+                msg = "Can't add angles because bounds don't match: {0} and {1}"
+                raise ValueError(msg.format(self.bounds, other.bounds))
+            else:
+                return Angle(other.radians - self.radians, unit=u.radian, bounds=self.bounds)
+        else:
+            raise NotImplementedError("An {0} object can only be subtracted from another "
+                                      "{0} object.".format(type(self).__name__))
+
+    # Multiplication
+    def __mul__(self, other):
+        if isinstance(other, type(self)):
+            raise NotImplementedError("Multiplication is not supported between two {0} "
+                                      "objects ".format(type(self).__name__))
+        elif type(other) in [float, int]:
+            return Angle(self.radians * other, unit=u.radian)
+        else:
+            raise NotImplementedError("An {0} object can only be multiplied by a float or integer.".format(type(self).__name__))
+
+    def __rmul__(self, other):
+        return self.__mul__(other)
+
+    # Division
+    def __div__(self, other):
+        if isinstance(other, type(self)):
+            raise NotImplementedError("Division is not supported between two {0} "
+                                      "objects.".format(type(self).__name__))
+        elif type(other) in [float, int]:
+            return Angle(self.radians / other, unit=u.radian)
+        else:
+            raise NotImplementedError("An {0} object can only be divided by a float or integer.".format(type(self).__name__))
+
+    def __rdiv__(self, other):
+        if isinstance(other, type(self)):
+            raise NotImplementedError("Division is not supported between two {0} "
+                                      "objects.".format(type(self).__name__))
+        elif type(other) in [float, int]:
+            return Angle(other / self.radians, unit=u.radian)
+        else:
+            raise NotImplementedError("An {0} object can only be divided by a float or integer.".format(type(self).__name__))
+
+    def __truediv__(self, other):
+        return self.__div__(other)
+
+    def __rtruediv__(self, other):
+        return self.__rdiv__(other)
+
+    # other operations
+
+    def __neg__(self):
+        return Angle(-self.radians, unit=u.radian)
+
+    def __eq__(self, other):
+        if isinstance(other, Angle):
+            return self.radians == other.radians
+        if other == None:
+            return False
+        else:
+            raise NotImplementedError("To compare {0} objects, compare their "
+                                      "float values directly.".format(type(self).__name__))
+
+    def __ne__(self, other):
+        # return not self.radians == other.radians
+        return not self.__eq__(other)
+
+    def __lt__(self, other):
+        if isinstance(other, type(self)):
+            return self.radians < other.radians
+        else:
+            raise NotImplementedError("An {0} object can only be compared to another {0} "
+                                      "object.".format(type(self).__name__))
+
+    def __gt__(self, other):
+        if isinstance(other, type(self)):
+            return self.radians > other.radians
+        else:
+            raise NotImplementedError("An {0} object can only be compared to another {0} "
+                                      "object.".format(type(self).__name__))
+
+    def __ge__(self, other):
+        if isinstance(other, type(self)):
+            return self.radians >= other.radians
+        else:
+            raise NotImplementedError("An {0} object can only be compared to another {0} "
+                                      "object.".format(type(self).__name__))
+
+    def __le__(self, other):
+        if isinstance(other, type(self)):
+            return self.radians <= other.radians
+        else:
+            raise NotImplementedError("An {0} object can only be compared to another {0} "
+                                      "object.".format(type(self).__name__))
+
+    def __abs__(self):
+        return Angle(abs(self.radians), unit=u.radian)
+
+    def __repr__(self):
+        return "<{0} {1:.5f} deg>".format(type(self).__name__, self.degrees)
+
+
+class RA(Angle):
+    """ An object that represents a right ascension angle.
+
+    This object can be created from a numeric value along with a unit. If the
+    value specified is greater than "24", then a unit of degrees is assumed. Bounds
+    are fixed to [0,360] degrees.
+
+    Parameters
+    ----------
+    angle : float, int, str, tuple
+        The angle value. If a tuple, will be interpreted as (h, m s) or
+        (d, m, s) depending on `unit`. If a string, it will be interpreted
+        following the rules described above.
+    unit : `~astropy.units.UnitBase`, str
+        The unit of the value specified for the angle.  This may be any
+        string that `~astropy.units.Unit` understands, but it is better to
+        give an actual unit object.  Must be one of `~astropy.units.degree`,
+        `~astropy.units.radian`, or `~astropy.units.hour`.
+
+    Raises
+    ------
+    `~astropy.coordinates.errors.UnitsError`
+        If a unit is not provided or it is not hour, radian, or degree.
+    """
+
+    def __init__(self, angle, unit=None):
+        super(RA, self).__init__(angle, unit=unit, bounds=(0, 360))
+
+    # The initializer as originally conceived allowed the unit to be unspecified
+    # if it's bigger  than 24, because hours typically aren't past 24.
+    # It is also then implicit that `RA` is usually in hours.
+    # This is commented out for now because in discussion for v0.2 we decided to
+    # keep things simple and just use the same behavior as Angle.
+    # In v0.3 it may be either uncommented,
+    # moved somewhere else, or eliminated completely
+    # TODO: decide if this should stay in or permanently be removed
+    #
+    # def __init__(self, angle, unit=None):
+    #
+    #     # This block attempts to determine the validity of the unit,
+    #     # particularly with regard to the specifics of RA.
+    #     # After this block, the normal Angle initializer handles most of the
+    #     # validation/creation.
+    #
+    #     if isinstance(angle, Angle):
+    #         return super(RA, self).__init__(angle.radians, unit=u.radian, bounds=(0, 360))
+    #
+    #     if unit is u.hour:
+    #         pass  # to Angle initializer
+    #         # self._radians = math.radians(decimal_hours * 15.)
+    #     elif unit is u.degree:
+    #         pass  # to Angle initializer
+    #         # decimal_degrees = util.parse_degrees(angle)
+    #         # self._radians = math.radians(decimal_degrees)
+    #     elif unit is u.radian:
+    #         pass  # to Angle initializer
+    #         # self._radians = util.parse_radians(angle)
+    #
+    #
+    #     elif unit is None:
+    #         # Try to figure out the unit if we can.
+    #         if isinstance(angle, float) or isinstance(angle, int):
+    #             if angle > 24:
+    #                 unit = u.degree
+    #             else:
+    #                 raise UnitsError("No units were specified, and the angle value was ambiguous between hours and degrees.")
+    #         elif isinstance(angle, basestring):
+    #             # Try to deduce the units from hints in the string.
+    #             # Further, enforce absolute bounds here, i.e. don't let
+    #             # Angle +-2Ï€ to see if the angle falls in the bounds.
+    #             if "d" in angle or "°" in angle:
+    #                 # If in the form "12d32m53s", look for the "d" and assume degrees.
+    #                 angle = math.radians(util.parse_degrees(angle))
+    #                 if 0 < angle < TWOPI:
+    #                     unit = u.radian
+    #                 else:
+    #                     raise RangeError("The provided angle was assumed to be in degrees, but was out of the range (0,360) degrees.")
+    #             elif "h" in angle:
+    #                 # Same for "12h32m53s" for hours.
+    #                 # self._radians = math.radians(util.parse_hours(angle)*15.0)
+    #                 unit = u.hour
+    #             else:
+    #                 # could be in a form: "54:43:26" -
+    #                 # if so AND the resulting decimal value is > 24 or < -24, assume degrees
+    #                 decimal_value = util.parse_degrees(angle)
+    #                 if decimal_value > 24:
+    #                     unit = u.degree
+    #                 elif 0 <= decimal_value <= 24.0:
+    #                     raise UnitsError("No units were specified, and the angle value was ambiguous between hours and degrees.")
+    #                 elif decimal_value < 0:
+    #                     raise RangeError("No units were specified; could not assume any since the value was less than zero.")
+    #         elif isinstance(angle, tuple):
+    #             if len(angle) == 3 and 0 <= angle[0] < 24.0:
+    #                 raise UnitsError("No units were specified, and the angle value was ambiguous between hours and degrees.")
+    #             else:
+    #                 unit = u.degree
+    #         else:
+    #             raise ValueError("Angle values of type {0} not supported.".format(type(angle).__name__))
+    #
+    #     if unit is None:
+    #         raise UnitsError("Units must be specified for RA, one of u.degree, u.hour, or u.radian.")
+    #
+    #     # By here, the unit should be defined.
+    #     super(RA, self).__init__(angle, unit=unit, bounds=(0, 360))
+
+    def hour_angle(self, lst):
+        """ Computes the hour angle for this RA given a local sidereal
+        time (LST).
+
+        Parameters
+        ----------
+        lst : `~astropy.coordinates.angle.Angle`, `~astropy.time.Time`
+            A local sidereal time (LST).
+
+        Returns
+        -------
+        hour_angle : `~astropy.coordinates.angle.Angle`
+            The hour angle for this RA at the LST `lst`.
+        """
+        if hasattr(lst, 'mjd'):
+            lst = Angle(np.remainder(lst.mjd, 1), unit=u.hour)
+
+        return Angle(lst.radians - self.radians, unit=u.radian, bounds=(0, TWOPI))
+
+    def lst(self, hour_angle):
+        """
+        Calculates the local sidereal time (LST) if this RA is at a
+        particular hour angle.
+
+        Parameters
+        ----------
+        hour_angle :  `~astropy.coordinates.angle.Angle`
+            An hour angle.
+
+        Returns
+        -------
+        lst : `~astropy.coordinates.angle.Angle`
+            The local siderial time as an angle.
+
+        """
+        return Angle(hour_angle.radians + self.radians, unit=u.radian, bounds=(0, TWOPI))
+
+
+class Dec(Angle):
+    """
+    Represents a declination value.
+
+    This object can be created from a numeric value along with a unit, or else a
+    string in any commonly represented format, e.g. "12 43 23.53", "-32d52m29s".
+    Unless otherwise specified via the 'unit' parameter, degrees are assumed.
+    Bounds are fixed to [-90,90] degrees.
+
+    Parameters
+    ----------
+    angle : float, int, str, tuple
+        The angle value. If a tuple, will be interpreted as (h, m s) or
+        (d, m, s) depending on `unit`. If a string, it will be interpreted
+        following the rules described above.
+    unit : `~astropy.units.UnitBase`, str
+        The unit of the value specified for the angle.  This may be any
+        string that `~astropy.units.Unit` understands, but it is better to
+        give an actual unit object.  Must be one of `~astropy.units.degree`,
+        `~astropy.units.radian`, or `~astropy.units.hour`.
+    bounds : tuple
+        A tuple indicating the upper and lower value that the new angle object may
+        have.
+
+        Raises
+        ------
+        `~astropy.coordinates.errors.UnitsError`
+            If a unit is not provided or it is not hour, radian, or degree.
+    """
+    def __init__(self, angle, unit=None):
+        super(Dec, self).__init__(angle, unit=unit, bounds=(-90, 90))
+
+    # TODO: do here whatever is decided for the "smart" RA initializer above
+    #
+    # def __init__(self, angle, unit=u.degree):
+    #     super(RA, self).__init__(angle, unit=unit, bounds=(0, 360))
+    #
+    #     if isinstance(angle, Angle):
+    #         return super(Dec, self).__init__(angle.radians, unit=u.radian, bounds=(-90, 90))
+    #
+    #     super(Dec, self).__init__(angle, unit=unit, bounds=(-90, 90))
+
+
+class AngularSeparation(Angle):
+    """
+    An on-sky separation between two directions.
+
+    .. note::
+        This is computed using the Vincenty great circle distance
+        formula, and hence should be numerically stable even for
+        near antipodal points.
+
+    Parameters
+    ----------
+    lat1 : float
+        The value of the first latitudinal/elevation angle.
+    lon1 : float
+        The value of the first longitudinal/azimuthal angle.
+    lat2 : float
+        The value of the second latitudinal/elevation angle.
+    lon2 : float
+        The value of the second longitudinal/azimuthal angle.
+    units : `~astropy.units`
+        The units of the given angles.
+
+
+    """
+    def __init__(self, lat1, lon1, lat2, lon2, units):
+
+        units = u.Unit(units)
+        lat1 = units.to(u.radian, lat1)
+        if 0 == lon1 == lat2 == lon2:
+            sepval = lat1
+        else:
+            lon1 = units.to(u.radian, lon1)
+            lat2 = units.to(u.radian, lat2)
+            lon2 = units.to(u.radian, lon2)
+
+            sepval = util.vincenty_sphere_dist(lon1, lat1, lon2, lat2)
+
+        super(AngularSeparation, self).__init__(sepval, u.radian)
+
+    def __add__(self, other):
+        raise TypeError('+ is ambiguous for AngularSeparation objects; not supported')
+
+    def __radd__(self, other):
+        raise TypeError('+ is ambiguous for AngularSeparation objects; not supported')
+
+    def __sub__(self, other):
+        raise TypeError('- is ambiguous for AngularSeparation objects; not supported')
+
+    def __rsub__(self, other):
+        raise TypeError('- is ambiguous for AngularSeparation objects; not supported')
+
+    @property
+    def arcmins(self):
+        """
+        The value of this separation in arcminutes.
+        """
+        return self.degrees * 60.
+
+    @property
+    def arcsecs(self):
+        """
+        The value of this separation in arcseconds.
+        """
+        return self.degrees * 3600.
+
+#<----------------------------------Rotations---------------------------------->
+
+
+def rotation_matrix(angle, axis='z', degrees=True):
+    """
+    Generate a 3x3 cartesian rotation matrix in for rotation about
+    a particular axis.
+
+    Parameters
+    ----------
+    angle : scalar
+        The amount of rotation this matrix should represent. In degrees
+        if `degrees` is True, otherwise radians.
+    axis : str or 3-sequence
+        Either 'x','y', 'z', or a (x,y,z) specifying an axis to rotate
+        about. If 'x','y', or 'z', the rotation sense is
+        counterclockwise looking down the + axis (e.g. positive
+        rotations obey left-hand-rule).
+    degrees : bool
+        If True the input angle is degrees, otherwise radians.
+
+    Returns
+    -------
+    rmat: `numpy.matrix`
+        A unitary rotation matrix.
+    """
+    from math import sin, cos, radians, sqrt
+
+    if degrees:
+        angle = radians(angle)
+
+    if axis == 'z':
+        s = sin(angle)
+        c = cos(angle)
+        return np.matrix(((c, s, 0),
+                          (-s, c, 0),
+                          (0, 0, 1)))
+    elif axis == 'y':
+        s = sin(angle)
+        c = cos(angle)
+        return np.matrix(((c, 0, -s),
+                          (0, 1, 0),
+                          (s, 0, c)))
+    elif axis == 'x':
+        s = sin(angle)
+        c = cos(angle)
+        return np.matrix(((1, 0, 0),
+                          (0, c, s),
+                          (0, -s, c)))
+    else:
+        x, y, z = axis
+        w = cos(angle / 2)
+
+        # normalize
+        if w == 1:
+            x = y = z = 0
+        else:
+            l = sqrt((x * x + y * y + z * z) / (1 - w * w))
+            x /= l
+            y /= l
+            z /= l
+
+        wsq = w * w
+        xsq = x * x
+        ysq = y * y
+        zsq = z * z
+        return np.matrix(((wsq + xsq - ysq - zsq, 2 * x * y - 2 * w * z, 2 * x * z + 2 * w * y),
+                          (2 * x * y + 2 * w * z, wsq - xsq + ysq - zsq, 2 * y * z - 2 * w * x),
+                          (2 * x * z - 2 * w * y, 2 * y * z + 2 * w * x, wsq - xsq - ysq + zsq)))
+
+
+def angle_axis(matrix, degrees=True):
+    """
+    Computes the angle of rotation and the rotation axis for a given rotation
+    matrix.
+
+    Parameters
+    ----------
+    matrix : array-like
+        A 3 x 3 unitary rotation matrix.
+    degrees : bool
+        If True, output is in degrees.
+
+    Returns
+    -------
+    angle : scalar
+        The angle of rotation for this matrix. In degrees if `degrees is
+        True, otherwise radians.
+    axis : array (length 3)
+        The axis of rotation for this matrix.
+
+    """
+    from math import sin, cos, acos, degrees, sqrt
+
+    m = np.asmatrix(matrix)
+    if m.shape != (3, 3):
+        raise ValueError('matrix is not 3x3')
+
+    angle = acos((m[0, 0] + m[1, 1] + m[2, 2] - 1) / 2)
+    denom = sqrt(2 * ((m[2, 1] - m[1, 2]) + (m[0, 2] - m[2, 0]) + (m[1, 0] - m[0, 1])))
+    axis = np.array((m[2, 1] - m[1, 2], m[0, 2] - m[2, 0], m[1, 0] - m[0, 1])) / denom
+    axis /= sqrt(np.sum(axis ** 2))
+
+    if degrees:
+        return degrees(angle), axis
+    else:
+        return angle, axis
diff --git a/astropy/coordinates/builtin_systems.py b/astropy/coordinates/builtin_systems.py
new file mode 100644
index 0000000..6da3a08
--- /dev/null
+++ b/astropy/coordinates/builtin_systems.py
@@ -0,0 +1,782 @@
+# Licensed under a 3-clause BSD style license - see LICENSE.rst
+
+"""
+This module contains the implementations of specific coordinate systems
+and the conversions between them.
+"""
+
+import numpy as np
+
+from .angles import Angle
+from .coordsystems import SphericalCoordinatesBase
+from ..time import Time
+from . import transformations
+from .. import units as u
+
+__all__ = ['ICRSCoordinates', 'FK5Coordinates', 'FK4Coordinates',
+           'FK4NoETermCoordinates', 'GalacticCoordinates', 'HorizontalCoordinates'
+          ]
+
+# The UTC time scale is not properly defined prior to 1960, so Time('B1950',
+# scale='utc') will emit a warning. Instead, we use Time('B1950', scale='tai')
+# which is equivalent, but does not emit a warning.
+_EQUINOX_J2000 = Time('J2000', scale='utc')
+_EQUINOX_B1950 = Time('B1950', scale='tai')
+
+
+#<--------------Coordinate definitions; transformations are below-------------->
+ at transformations.coordinate_alias('icrs')
+class ICRSCoordinates(SphericalCoordinatesBase):
+    """
+    A coordinate in the ICRS.
+
+    If you're looking for "J2000" coordinates, and aren't sure if you
+    want to use this or `FK5Coordinates`, you probably want to use ICRS.
+    It's more well-defined as a catalog coordinate and is an inertial
+    system.
+
+
+    Parameters
+    ----------
+    {params}
+    obstime : `~astropy.time.Time` or None
+        The time of observation for this coordinate.  If None, it will be taken
+        to be the same as the `equinox`.
+
+    Alternatively, a single argument that is any kind of spherical coordinate
+    can be provided, and will be converted to ICRSCoordinates and used as this
+    coordinate.
+
+    """
+    __doc__ = __doc__.format(params=SphericalCoordinatesBase._init_docstring_param_templ.format(lonnm='ra', latnm='dec'))
+
+    def __init__(self, *args, **kwargs):
+        super(ICRSCoordinates, self).__init__()
+
+        self._obstime = kwargs.pop('obstime', None)
+
+        if self._obstime is not None and not isinstance(self._obstime, Time):
+            raise TypeError('specified obstime is not None or a Time object')
+
+        if len(args) == 1 and len(kwargs) == 0 and isinstance(args[0], SphericalCoordinatesBase):
+            newcoord = args[0].transform_to(self.__class__)
+            self.ra = newcoord.ra
+            self.dec = newcoord.dec
+            self._distance = newcoord._distance
+        else:
+            super(ICRSCoordinates, self)._initialize_latlon('ra', 'dec', True, args, kwargs)
+
+    def __repr__(self):
+        if self.distance is not None:
+            diststr = ', Distance={0:.2g} {1!s}'.format(self.distance._value, self.distance._unit)
+        else:
+            diststr = ''
+
+        msg = "<{0} RA={1:.5f} deg, Dec={2:.5f} deg{3}>"
+        return msg.format(self.__class__.__name__, self.ra.degrees,
+                          self.dec.degrees, diststr)
+
+    @property
+    def lonangle(self):
+        return self.ra
+
+    @property
+    def latangle(self):
+        return self.dec
+
+    @property
+    def equinox(self):
+        return _EQUINOX_J2000
+
+    @property
+    def obstime(self):
+        if self._obstime is None:
+            return self.equinox
+        else:
+            return self._obstime
+
+
+ at transformations.coordinate_alias('fk5')
+class FK5Coordinates(SphericalCoordinatesBase):
+    """
+    A coordinate in the FK5 system.
+
+    Parameters
+    ----------
+    {params}
+    equinox : `~astropy.time.Time`, optional
+        The equinox for these coordinates.  Defaults to J2000.
+    obstime : `~astropy.time.Time` or None
+        The time of observation for this coordinate.  If None, it will be taken
+        to be the same as the `equinox`.
+
+    Alternatively, a single argument that is any kind of spherical coordinate
+    can be provided, and will be converted to `FK5Coordinates` and used as this
+    coordinate.
+    """
+    __doc__ = __doc__.format(params=SphericalCoordinatesBase._init_docstring_param_templ.format(lonnm='ra', latnm='dec'))
+
+    def __init__(self, *args, **kwargs):
+        super(FK5Coordinates, self).__init__()
+
+        self._equinox = kwargs.pop('equinox', _EQUINOX_J2000)
+        self._obstime = kwargs.pop('obstime', None)
+
+        if not isinstance(self._equinox, Time):
+            raise TypeError('specified equinox is not a Time object')
+        if self._obstime is not None and not isinstance(self._obstime, Time):
+            raise TypeError('specified obstime is not None or a Time object')
+
+        if len(args) == 1 and len(kwargs) == 0 and isinstance(args[0], SphericalCoordinatesBase):
+            newcoord = args[0].transform_to(self.__class__)
+            self.ra = newcoord.ra
+            self.dec = newcoord.dec
+            self._distance = newcoord._distance
+        else:
+            super(FK5Coordinates, self)._initialize_latlon('ra', 'dec', True, args, kwargs)
+
+    def __repr__(self):
+        if self.distance is not None:
+            diststr = ', Distance={0:.2g} {1!s}'.format(self.distance._value, self.distance._unit)
+        else:
+            diststr = ''
+
+        msg = "<{0} RA={1:.5f} deg, Dec={2:.5f} deg{3}>"
+        return msg.format(self.__class__.__name__, self.ra.degrees,
+                          self.dec.degrees, diststr)
+
+    @property
+    def lonangle(self):
+        return self.ra
+
+    @property
+    def latangle(self):
+        return self.dec
+
+    @property
+    def equinox(self):
+        return self._equinox
+
+    @property
+    def obstime(self):
+        if self._obstime is None:
+            return self.equinox
+        else:
+            return self._obstime
+
+    def precess_to(self, newequinox):
+        """
+        Precesses the coordinates from their current `equinox` to a new equinox and
+        returns the resulting coordinate.
+
+        Parameters
+        ----------
+        newequinox : `~astropy.time.Time`
+            The equinox to precess these coordinates to.
+
+        Returns
+        -------
+        newcoord : FK5Coordinates
+            The new coordinate
+        """
+        from .earth_orientation import precession_matrix_Capitaine
+
+        pmat = precession_matrix_Capitaine(self._equinox, newequinox)
+
+        v = [self.x, self.y, self.z]
+        x, y, z = np.dot(pmat.A, v)
+
+        if self.distance is not None:
+            return self.__class__(x=x, y=y, z=z, unit=self.distance._unit, equinox=newequinox)
+        else:
+            return self.__class__(x=x, y=y, z=z, equinox=newequinox)
+
+
+ at transformations.coordinate_alias('fk4')
+class FK4Coordinates(SphericalCoordinatesBase):
+    """
+    A coordinate in the FK4 system.
+
+
+    Parameters
+    ----------
+    {params}
+    equinox : `~astropy.time.Time`, optional
+        The equinox for these coordinates.  Defaults to B1950.
+    obstime : `~astropy.time.Time` or None
+        The time of observation for this coordinate.  If None, it will be taken
+        to be the same as the `equinox`.
+
+    Alternatively, a single argument that is any kind of spherical coordinate
+    can be provided, and will be converted to `FK4Coordinates` and used as this
+    coordinate.
+    """
+    __doc__ = __doc__.format(params=SphericalCoordinatesBase._init_docstring_param_templ.format(lonnm='ra', latnm='dec'))
+
+    def __init__(self, *args, **kwargs):
+        super(FK4Coordinates, self).__init__()
+
+        self._equinox = kwargs.pop('equinox', _EQUINOX_B1950)
+        self._obstime = kwargs.pop('obstime', None)
+
+        if not isinstance(self._equinox, Time):
+            raise TypeError('specified equinox is not a Time object')
+        if self._obstime is not None and not isinstance(self._obstime, Time):
+            raise TypeError('specified obstime is not None or a Time object')
+
+        if len(args) == 1 and len(kwargs) == 0 and isinstance(args[0], SphericalCoordinatesBase):
+            newcoord = args[0].transform_to(self.__class__)
+            self.ra = newcoord.ra
+            self.dec = newcoord.dec
+            self._distance = newcoord._distance
+        else:
+            super(FK4Coordinates, self)._initialize_latlon('ra', 'dec', True, args, kwargs)
+
+    def __repr__(self):
+        if self.distance is not None:
+            diststr = ', Distance={0:.2g} {1!s}'.format(self.distance._value, self.distance._unit)
+        else:
+            diststr = ''
+
+        msg = "<{0} RA={1:.5f} deg, Dec={2:.5f} deg{3}>"
+        return msg.format(self.__class__.__name__, self.ra.degrees,
+                          self.dec.degrees, diststr)
+
+    @property
+    def lonangle(self):
+        return self.ra
+
+    @property
+    def latangle(self):
+        return self.dec
+
+    @property
+    def equinox(self):
+        return self._equinox
+
+    @property
+    def obstime(self):
+        if self._obstime is None:
+            return self.equinox
+        else:
+            return self._obstime
+
+    def precess_to(self, newequinox):
+        """
+        Precesses the coordinates from their current `equinox` to a new equinox.
+
+        Parameters
+        ----------
+        newequinox : `~astropy.time.Time`
+            The equinox to precess these coordinates to.
+
+        Returns
+        -------
+        newcoord : FK4Coordinates
+            The new coordinate
+        """
+        from .earth_orientation import _precession_matrix_besselian
+
+        pmat = _precession_matrix_besselian(self._equinox.byear, newequinox.byear)
+
+        v = [self.x, self.y, self.z]
+        x, y, z = np.dot(pmat.A, v)
+
+        if self.distance is not None:
+            return self.__class__(x=x, y=y, z=z, unit=self.distance._unit, equinox=newequinox)
+        else:
+            return self.__class__(x=x, y=y, z=z, equinox=newequinox)
+
+
+ at transformations.coordinate_alias('fk4_no_e')
+class FK4NoETermCoordinates(SphericalCoordinatesBase):
+    """
+    A coordinate in the FK4 system.
+
+
+    Parameters
+    ----------
+    {params}
+    equinox : `~astropy.time.Time`, optional
+        The equinox for these coordinates.  Defaults to B1950.
+    obstime : `~astropy.time.Time` or None
+        The time of observation for this coordinate.  If None, it will be taken
+        to be the same as the `equinox`.
+
+    Alternatively, a single argument that is any kind of spherical coordinate
+    can be provided, and will be converted to `FK4NoETermCoordinates` and used as this
+    coordinate.
+    """
+    __doc__ = __doc__.format(params=SphericalCoordinatesBase._init_docstring_param_templ.format(lonnm='ra', latnm='dec'))
+
+    def __init__(self, *args, **kwargs):
+        super(FK4NoETermCoordinates, self).__init__()
+
+        self._equinox = kwargs.pop('equinox', _EQUINOX_B1950)
+        self._obstime = kwargs.pop('obstime', None)
+
+        if not isinstance(self._equinox, Time):
+            raise TypeError('specified equinox is not a Time object')
+        if self._obstime is not None and not isinstance(self._obstime, Time):
+            raise TypeError('specified obstime is not None or a Time object')
+
+        if len(args) == 1 and len(kwargs) == 0 and isinstance(args[0], SphericalCoordinatesBase):
+            newcoord = args[0].transform_to(self.__class__)
+            self.ra = newcoord.ra
+            self.dec = newcoord.dec
+            self._distance = newcoord._distance
+        else:
+            super(FK4NoETermCoordinates, self)._initialize_latlon('ra', 'dec', True, args, kwargs)
+
+    def __repr__(self):
+        if self.distance is not None:
+            diststr = ', Distance={0:.2g} {1!s}'.format(self.distance._value, self.distance._unit)
+        else:
+            diststr = ''
+
+        msg = "<{0} RA={1:.5f} deg, Dec={2:.5f} deg{3}>"
+        return msg.format(self.__class__.__name__, self.ra.degrees,
+                          self.dec.degrees, diststr)
+
+    @property
+    def lonangle(self):
+        return self.ra
+
+    @property
+    def latangle(self):
+        return self.dec
+
+    @property
+    def equinox(self):
+        return self._equinox
+
+    @property
+    def obstime(self):
+        if self._obstime is None:
+            return self.equinox
+        else:
+            return self._obstime
+
+    def precess_to(self, newequinox):
+        """
+        Precesses the coordinates from their current `equinox` to a new equinox.
+
+        Parameters
+        ----------
+        newequinox : `~astropy.time.Time`
+            The equinox to precess these coordinates to.
+
+        Returns
+        -------
+        newcoord : FK4NoETermCoordinates
+            The new coordinate
+        """
+        from .earth_orientation import _precession_matrix_besselian
+
+        pmat = _precession_matrix_besselian(self._equinox.byear, newequinox.byear)
+
+        v = [self.x, self.y, self.z]
+        x, y, z = np.dot(pmat.A, v)
+
+        if self.distance is not None:
+            return self.__class__(x=x, y=y, z=z, unit=self.distance._unit, equinox=newequinox)
+        else:
+            return self.__class__(x=x, y=y, z=z, equinox=newequinox)
+
+
+ at transformations.coordinate_alias('galactic')
+class GalacticCoordinates(SphericalCoordinatesBase):
+    """
+    A coordinate in Galactic Coordinates.
+
+    .. note::
+
+        Transformations from Galactic Coordinates to other systems are
+        not well-defined because of ambiguities in the definition of
+        Galactic Coordinates. See
+        `Lie et al. 2011 <http://dx.doi.org/10.1051/0004-6361/201014961>`
+        for more details on this.  Here, we use the
+        `Reid & Brunthaler 2004 <http://dx.doi.org/10.1086/424960>`
+        definition for converting to/from FK5, and assume the IAU
+        definition applies for converting to FK4 *without* e-terms.
+
+    Parameters
+    ----------
+    {params}
+    obstime : `~astropy.time.Time` or None
+        The time of observation for this coordinate.  If None, it will be taken
+        to be the same as the `equinox`.
+
+    Alternatively, a single argument that is any kind of spherical coordinate
+    can be provided, and will be converted to `GalacticCoordinates` and
+    used as this coordinate.
+    """
+    __doc__ = __doc__.format(params=SphericalCoordinatesBase._init_docstring_param_templ.format(lonnm='l', latnm='b'))
+
+    # North galactic pole and zeropoint of l in FK4/FK5 coordinates. Needed for
+    # transformations to/from FK4/5
+
+    # These are from Reid & Brunthaler 2004
+    _ngp_J2000 = FK5Coordinates(192.859508, 27.128336, unit=(u.degree, u.degree))
+    _lon0_J2000 = Angle(122.932, unit=u.degree)
+    # These are from the IAU's definition of galactic coordinates
+    _ngp_B1950 = FK4Coordinates(192.25, 27.4, unit=(u.degree, u.degree))
+    _lon0_B1950 = Angle(123, unit=u.degree)
+
+    def __init__(self, *args, **kwargs):
+        super(GalacticCoordinates, self).__init__()
+
+        self._obstime = kwargs.pop('obstime', None)
+
+        if self._obstime is not None and not isinstance(self._obstime, Time):
+            raise TypeError('specified obstime is not None or a Time object')
+
+        if len(args) == 1 and len(kwargs) == 0 and isinstance(args[0], SphericalCoordinatesBase):
+            newcoord = args[0].transform_to(self.__class__)
+            self.l = newcoord.l
+            self.b = newcoord.b
+            self._distance = newcoord._distance
+        else:
+            super(GalacticCoordinates, self)._initialize_latlon('l', 'b', False, args, kwargs)
+
+    def __repr__(self):
+        if self.distance is not None:
+            diststr = ', Distance={0:.2g} {1!s}'.format(self.distance._value, self.distance._unit)
+        else:
+            diststr = ''
+
+        msg = "<{0} l={1:.5f} deg, b={2:.5f} deg{3}>"
+        return msg.format(self.__class__.__name__, self.l.degrees,
+                          self.b.degrees, diststr)
+
+    @property
+    def lonangle(self):
+        return self.l
+
+    @property
+    def latangle(self):
+        return self.b
+
+
+ at transformations.coordinate_alias('horizontal')
+class HorizontalCoordinates(SphericalCoordinatesBase):
+    """
+    A coordinate in the Horizontal or "az/el" system.
+
+    Parameters
+    ----------
+    {params}
+    equinox : `~astropy.time.Time`, optional
+        The equinox for these coordinates.  Defaults to J2000.
+    obstime : `~astropy.time.Time` or None
+        The time of observation for this coordinate.  If None, it will be taken
+        to be the same as the `equinox`.
+
+    Alternatively, a single argument that is any kind of spherical coordinate
+    can be provided, and will be converted to `HorizontalCoordinates` and used
+    as this coordinate.
+    """
+    __doc__ = __doc__.format(params=SphericalCoordinatesBase._init_docstring_param_templ.format(lonnm='az', latnm='el'))
+
+    def __init__(self, *args, **kwargs):
+        super(HorizontalCoordinates, self).__init__()
+
+        self._equinox = kwargs.pop('equinox', _EQUINOX_J2000)
+        self._obstime = kwargs.pop('obstime', None)
+
+        if not isinstance(self._equinox, Time):
+            raise TypeError('specified equinox is not a Time object')
+        if self._obstime is not None and not isinstance(self._obstime, Time):
+            raise TypeError('specified obstime is not None or a Time object')
+
+        if len(args) == 1 and len(kwargs) == 0 and isinstance(args[0], SphericalCoordinatesBase):
+            newcoord = args[0].transform_to(self.__class__)
+            self.az = newcoord.az
+            self.el = newcoord.el
+            self._distance = newcoord._distance
+        else:
+            super(HorizontalCoordinates, self)._initialize_latlon('az', 'el', False, args, kwargs)
+
+    def __repr__(self):
+        if self.distance is not None:
+            diststr = ', Distance={0:.2g} {1!s}'.format(self.distance._value, self.distance._unit)
+        else:
+            diststr = ''
+
+        msg = "<{0} az={1:.5f} deg, el={2:.5f} deg{3}>"
+        return msg.format(self.__class__.__name__, self.az.degrees,
+                          self.el.degrees, diststr)
+
+    @property
+    def lonangle(self):
+        return self.az
+
+    @property
+    def latangle(self):
+        return self.el
+
+    @property
+    def equinox(self):
+        return self._equinox
+
+    @property
+    def obstime(self):
+        if self._obstime is None:
+            return self.equinox
+        else:
+            return self._obstime
+
+
+#<--------------------------------transformations------------------------------>
+# ICRS to/from FK5
+ at transformations.static_transform_matrix(ICRSCoordinates, FK5Coordinates)
+def icrs_to_fk5():
+    """
+    B-matrix from USNO circular 179
+    """
+    from .angles import rotation_matrix
+
+    eta0 = -19.9 / 3600000.
+    xi0 = 9.1 / 3600000.
+    da0 = -22.9 / 3600000.
+
+    m1 = rotation_matrix(-eta0, 'x')
+    m2 = rotation_matrix(xi0, 'y')
+    m3 = rotation_matrix(da0, 'z')
+
+    return m1 * m2 * m3
+
+
+# can't be static because the equinox is needed
+ at transformations.dynamic_transform_matrix(FK5Coordinates, ICRSCoordinates)
+def fk5_to_icrs(fk5c):
+    from .earth_orientation import _precess_from_J2000_Capitaine
+
+    pmat = _precess_from_J2000_Capitaine(fk5c.equinox.jyear).T
+
+    # transpose gets equinox -> J2000
+    fk5toicrsmat = icrs_to_fk5().T
+
+    return fk5toicrsmat * pmat
+
+# FK4-NO-E to/from FK4
+
+# In the present framework, we include two coordinate classes for FK4
+# coordinates - one including the E-terms of aberration (FK4Coordinates), and
+# one not including them (FK4NoETermCoordinates). In the following functions,
+# we describe the transformation between these two.
+
+def fk4_e_terms(equinox):
+    """
+    Return the e-terms of aberation vector
+
+    Parameters
+    ----------
+    equinox : Time object
+        The equinox for which to compute the e-terms
+    """
+
+    from . import earth_orientation as earth
+
+    # Constant of aberration at J2000
+    k = 0.0056932
+
+    # Eccentricity of the Earth's orbit
+    e = earth.eccentricity(equinox.jd)
+    e = np.radians(e)
+
+    # Mean longitude of perigee of the solar orbit
+    g = earth.mean_lon_of_perigee(equinox.jd)
+    g = np.radians(g)
+
+    # Obliquity of the ecliptic
+    o = earth.obliquity(equinox.jd, algorithm=1980)
+    o = np.radians(o)
+
+    return e * k * np.sin(g), \
+           -e * k * np.cos(g) * np.cos(o), \
+           -e * k * np.cos(g) * np.sin(o)
+
+
+ at transformations.transform_function(FK4Coordinates, FK4NoETermCoordinates, priority=1)
+def fk4_to_fk4_no_e(fk4c):
+
+    # Extract cartesian vector
+    r = np.array([fk4c.x, fk4c.y, fk4c.z])
+
+    # Find distance (for re-normalization)
+    d_orig = np.sqrt(np.sum(r ** 2))
+
+    # Apply E-terms of aberration
+    eterms_a = fk4_e_terms(fk4c.equinox)
+    r = r - eterms_a + np.dot(r, eterms_a) * r
+
+    # Find new distance (for re-normalization)
+    d_new = np.sqrt(np.sum(r ** 2))
+
+    # Renormalize
+    r = r * d_orig / d_new
+
+    unit = None if fk4c.distance is None else fk4c.distance._unit
+    result = FK4NoETermCoordinates(x=r[0], y=r[1], z=r[2], unit=unit, equinox=fk4c.equinox)
+
+    return result
+
+
+ at transformations.transform_function(FK4NoETermCoordinates, FK4Coordinates, priority=1)
+def fk4_no_e_to_fk4(fk4c):
+
+    # Extract cartesian vector
+    r = np.array([fk4c.x, fk4c.y, fk4c.z])
+
+    # Find distance (for re-normalization)
+    d_orig = np.sqrt(np.sum(r ** 2))
+
+    # Apply E-terms of aberration
+    eterms_a = fk4_e_terms(fk4c.equinox)
+    r0 = r.copy()
+    for j in range(10):
+        r = (r0 + eterms_a) / (1. + np.dot(r, eterms_a))
+
+    # Find new distance (for re-normalization)
+    d_new = np.sqrt(np.sum(r ** 2))
+
+    # Renormalize
+    r = r * d_orig / d_new
+
+    unit = None if fk4c.distance is None else fk4c.distance._unit
+    result = FK4Coordinates(x=r[0], y=r[1], z=r[2], unit=unit, equinox=fk4c.equinox)
+
+    return result
+
+# FK5 to/from FK4
+
+# These transformations are very slightly prioritized >1 (lower priority number means
+# better path) to prefer the FK5 path over FK4 when possible
+#can't be static because the equinox is needed
+
+# B1950->J2000 matrix from Murray 1989 A&A 218,325 eqn 28
+B1950_TO_J2000_M = \
+    np.mat([[0.9999256794956877, -0.0111814832204662, -0.0048590038153592],
+            [0.0111814832391717,  0.9999374848933135, -0.0000271625947142],
+            [0.0048590037723143, -0.0000271702937440,  0.9999881946023742]])
+
+FK4_CORR = \
+    np.mat([[-0.0026455262, -1.1539918689, +2.1111346190],
+            [+1.1540628161, -0.0129042997, +0.0236021478],
+            [-2.1112979048, -0.0056024448, +0.0102587734]]) * 1.e-6
+
+# This transformation can't be static because the observation date is needed.
+ at transformations.dynamic_transform_matrix(FK4NoETermCoordinates, FK5Coordinates, priority=1)
+def fk4_no_e_to_fk5(fk4c, skip_precession=False):
+
+    # Add in correction terms for FK4 rotating system - Murray 89 eqn 29
+    # Note this is *julian century*, not besselian
+    T = (fk4c.obstime.jyear - 1950.) / 100.
+
+    B = B1950_TO_J2000_M + FK4_CORR * T
+
+    # If equinox is not B1950, need to precess first
+    if skip_precession or fk4c.equinox == _EQUINOX_B1950:
+        return B
+    else:
+        from .earth_orientation import _precession_matrix_besselian
+        return B * _precession_matrix_besselian(fk4c.equinox.byear, 1950)
+
+# This transformation can't be static because the observation date is needed.
+ at transformations.dynamic_transform_matrix(FK5Coordinates, FK4NoETermCoordinates, priority=1)
+def fk5_to_fk4_no_e(fk5c):
+
+    # Get transposed matrix from FK4 -> FK5 assuming equinox B1950 -> J2000
+    B = fk4_no_e_to_fk5(fk5c, skip_precession=True).T
+
+    # If equinox is not B1950, need to precess first
+    if fk5c.equinox == _EQUINOX_J2000:
+        return B
+    else:
+        from .earth_orientation import precession_matrix_Capitaine
+        return B * precession_matrix_Capitaine(fk5c.equinox, _EQUINOX_J2000)
+
+# GalacticCoordinates to/from FK4/FK5
+# can't be static because the equinox is needed
+ at transformations.dynamic_transform_matrix(FK5Coordinates, GalacticCoordinates)
+def _fk5_to_gal(fk5coords):
+    from .angles import rotation_matrix
+    from .earth_orientation import _precess_from_J2000_Capitaine
+
+    # needed mainly to support inverse from galactic
+    jequinox = 2000 if fk5coords.equinox is None else fk5coords.equinox.jyear
+
+    mat1 = rotation_matrix(180 - GalacticCoordinates._lon0_J2000.degrees, 'z')
+    mat2 = rotation_matrix(90 - GalacticCoordinates._ngp_J2000.dec.degrees, 'y')
+    mat3 = rotation_matrix(GalacticCoordinates._ngp_J2000.ra.degrees, 'z')
+    # transpose gets equinox -> J2000
+    matprec = _precess_from_J2000_Capitaine(jequinox).T
+    return mat1 * mat2 * mat3 * matprec
+
+
+ at transformations.dynamic_transform_matrix(GalacticCoordinates, FK5Coordinates)
+def _gal_to_fk5(galcoords):
+    return _fk5_to_gal(galcoords).T
+
+
+ at transformations.dynamic_transform_matrix(FK4NoETermCoordinates, GalacticCoordinates, priority=1)
+def _fk4_to_gal(fk4coords):
+    from .angles import rotation_matrix
+    from .earth_orientation import _precession_matrix_besselian
+
+    # needed mainly to support inverse from galactic
+    bequinox = 1950 if fk4coords.equinox is None else fk4coords.equinox.byear
+
+    mat1 = rotation_matrix(180 - GalacticCoordinates._lon0_B1950.degrees, 'z')
+    mat2 = rotation_matrix(90 - GalacticCoordinates._ngp_B1950.dec.degrees, 'y')
+    mat3 = rotation_matrix(GalacticCoordinates._ngp_B1950.ra.degrees, 'z')
+    matprec = _precession_matrix_besselian(bequinox, 1950)
+    return mat1 * mat2 * mat3 * matprec
+
+
+ at transformations.dynamic_transform_matrix(GalacticCoordinates, FK4NoETermCoordinates, priority=1)
+def _gal_to_fk4(galcoords):
+    return _fk4_to_gal(galcoords).T
+
+
+def _make_transform_graph_docs():
+    """
+    Generates a string for use with the coordinate package's docstring
+    to show the available transforms and coordinate systems
+    """
+    from inspect import isclass
+    from textwrap import dedent
+
+    from .transformations import master_transform_graph
+
+    coosys = [item for item in globals().values()
+              if isclass(item) and issubclass(item, SphericalCoordinatesBase)]
+    coosys.remove(SphericalCoordinatesBase)
+    graphstr = master_transform_graph.to_dot_graph(addnodes=coosys)
+
+    docstr = """
+    The diagram below shows all of the coordinate systems built into the
+    `~astropy.coordinates` package, their aliases (usable for converting
+    other coordinates to them using attribute-style access) and the
+    pre-defined transformations between them.  The user is free to
+    override any of these transformations by defining new trasnformation
+    between these systems, but the pre-defined transformations should be
+    sufficient for typical usage.
+
+    The graph also indicates the priority for each transformation as a
+    number next to the arrow.  These priorities are used to decide the
+    preferred order when two trasnformation paths have the same number
+    of steps.  These priorities are defined such that path with a
+    *smaller* total priority are favored over larger.
+    E.g., the path from `ICRSCoordinates` to `GalacticCoordinates` goes
+    through `FK5Coordinates` because the total path length is 2 instead
+    of 2.03.
+
+
+    .. graphviz::
+
+    """
+
+    return dedent(docstr) + '    ' + graphstr.replace('\n', '\n    ')
+_transform_graph_docs = _make_transform_graph_docs()
diff --git a/astropy/coordinates/coordsystems.py b/astropy/coordinates/coordsystems.py
new file mode 100644
index 0000000..d6739b5
--- /dev/null
+++ b/astropy/coordinates/coordsystems.py
@@ -0,0 +1,511 @@
+# Licensed under a 3-clause BSD style license - see LICENSE.rst
+
+"""
+This module contains the base classes and frameworks for coordinate objects.
+"""
+from abc import ABCMeta, abstractproperty, abstractmethod
+
+from .. import units as u
+from .angles import RA, Dec, Angle, AngularSeparation
+from .distances import *
+
+__all__ = ['SphericalCoordinatesBase']
+
+
+class SphericalCoordinatesBase(object):
+    """
+    Abstract superclass for all coordinate classes representing points
+    in three dimensions.
+
+    Notes
+    -----
+    Subclasses must implement `__init__`, and define the `latangle` and
+    `lonangle` properties.  They may also override the `equinox`
+    property, or leave it unaltered to indicate the coordinates are
+    equinoxless.
+
+    `_initialize_latlon` is provided to implement typical
+    initialization features, and should be called from a subclass'
+    `__init__`.  See the classes in
+    `astropy.coordinates.builtin_systems` for examples of this.
+    """
+
+    __metaclass__ = ABCMeta
+
+    @abstractmethod
+    def __init__(self, *args, **kwargs):
+        """
+        Subclasses must override this, but they should also call this to set up
+        internal state.
+        """
+        self._distance = None
+        self._cartpoint = None
+
+    def __eq__(self, other):
+        try:
+            return (self.latangle == other.latangle and
+                    self.lonangle == other.lonangle and
+                    self.distance == other.distance and
+                    self.equinox == other.equinox)
+        except AttributeError:
+            return False
+
+    _init_docstring_param_templ = """coordstr : str
+        A single string with the coordinates.  Cannot be used with
+        `{latnm}` and `{lonnm}` nor `x`/`y`/`z`.
+    {lonnm} : `~astropy.coordinates.angle.Angle`, float, int, str
+        This must be given with `{latnm}`.
+    {latnm} : `~astropy.coordinates.angle.Angle`, float, int, str
+        This must be given with `{lonnm}`.
+    distance : `~astropy.coordinates.coordsystems.Distance`, optional
+        This may be given with `{latnm}` and `{lonnm}` or `coordstr`
+        and not `x`, `y`, or `z`.  If not given, `None` (unit sphere)
+        will be assumed.
+    x : number
+        The first cartesian coordinate. Must be given with `y` and `z`
+        and not with `{lonnm}` or `{latnm}` nor `coordstr`.
+    y : number
+        The second cartesian coordinate. Must be given with `x` and `z`
+        and not with `{lonnm}` or `{latnm}` nor `coordstr`.
+    z : number
+        The third cartesian coordinate. Must be given with `x` and `y`
+        and not with `{lonnm}` or `{latnm}` nor `coordstr`.
+    cartpoint : `~astropy.coordinates.distance.CartesianPoints`
+        A cartesian point with the coordinates.  Cannot be used with
+        any other arguments.
+    unit
+        The `unit` parameter's interpretation depends on what other
+        parameters are given:
+
+        * If `{lonnm}` and `{latnm}` or `coordstr` are given:
+            `unit` must be a length-2 sequence specifying the units of
+            `{lonnm}` and `{latnm}`, respectively. They can be either
+            `~astropy.units.UnitBase` objects or strings that will be
+            converted using `~astropy.units.Unit`.  They can also be
+            None to attempt to automatically interpret the units (see
+            `~astropy.coordinates.angles.Angle` for details.) If `unit`
+            is just `None`, this will be interpreted the same as
+            ``(None, None)``.
+
+        * If `x`, `y`, and `z` are given:
+            `unit` must be a single unit with dimensions of length"""
+
+    def _initialize_latlon(self, lonname, latname, useradec, initargs, initkwargs):
+        """
+        Subclasses should use this to initialize standard lat/lon-style
+        coordinates.
+
+        This recognizes both the lat/lon style and the cartesian form.
+
+        Parameters
+        ----------
+        lonname : str
+            The name of the longitude-like coordinate attribute
+        latname : str
+            The name of the latitude-like coordinate attribute
+        useradec : bool
+            If True, the `RA` and `Dec` classes will be used for the
+            angles.  Otherwise, a basic `Angle` will be used.
+        initargs : list
+            The ``*args`` from the initializer
+        initkwargs : dict
+            The ``**kwargs`` from the initializer
+        """
+        initkwargs = dict(initkwargs)  # copy
+        nargs = len(initargs)
+        sclsnm = self.__class__.__name__
+
+        if nargs == 1:
+            if isinstance(initargs[0], CartesianPoints):
+                initkwargs['cartpoint'] = initargs[0]
+            else:
+                initkwargs['coordstr'] = initargs[0]
+        if nargs > 1:
+            if lonname in initkwargs:
+                raise TypeError("{0} got multiple values for keyword argument "
+                                "'{1}'".format(sclsnm, lonname))
+            initkwargs[lonname] = initargs[0]
+        if nargs >= 2:
+            if latname in initkwargs:
+                raise TypeError("{0} got multiple values for keyword argument "
+                                "'{1}'".format(sclsnm, latname))
+            initkwargs[latname] = initargs[1]
+        if nargs > 2:
+            raise TypeError('{0} takes up to 2 positional arguments '
+                            '({1} given)'.format(sclsnm, len(initargs)))
+
+        unit = initkwargs.pop('unit', None)
+        coordstr = initkwargs.pop('coordstr', None)
+        lonval = initkwargs.pop(lonname, None)
+        latval = initkwargs.pop(latname, None)
+        distval = initkwargs.pop('distance', None)
+        cartpoint = initkwargs.pop('cartpoint', None)
+        x = initkwargs.pop('x', None)
+        y = initkwargs.pop('y', None)
+        z = initkwargs.pop('z', None)
+
+        if len(initkwargs) > 0:
+            raise TypeError('{0} got unexpected keyword argument'
+                            ' {1}'.format(sclsnm, initkwargs.keys()))
+
+        angleinit = ((lonval is not None and latval is not None) or
+                     coordstr is not None)
+        cartinit = ((x is not None and y is not None and z is not None) or
+                    cartpoint is not None)
+
+        if angleinit and not cartinit:
+            # lat/lon-style initialization
+            for v in [x, y, z, cartpoint]:
+                if v is not None:
+                    raise ValueError('Cannot give both angular and cartesian '
+                                     'coordinates while initializing ' + sclsnm)
+
+            try:
+                # this raises a TypeError if `unit` is not None or iterable
+                units = [None, None] if unit is None else list(unit)
+            except TypeError:
+                raise ValueError('Must give a sequence of 2 units or None '
+                                 'while initializing {0}. Instead got a '
+                                 'non-sequence {1}'.format(sclsnm, unit))
+
+            if len(units) == 2:
+                try:
+                    if units[0] is not None:
+                        units[0] = u.Unit(units[0])
+                    if units[1] is not None:
+                        units[1] = u.Unit(units[1])
+                except ValueError:
+                    raise ValueError('Could not convert units to unit objects '
+                                     'while initializing ' + sclsnm)
+            else:
+                raise ValueError('Must give a sequence of 2 units or None '
+                             'while initializing {0}. Instead got a sequence '
+                             'of {1}.'.format(sclsnm, len(units)))
+
+            if coordstr is not None:
+                # need to try to parse the coordinate from a single argument
+                # populates latval and lonval variables, which then get made
+                # into coordinates below
+                if isinstance(coordstr, basestring):
+                    if "," in coordstr:
+                        lonval, latval = coordstr.split(",")
+                    else:
+                        coosplit = coordstr.split()
+                        if len(coosplit) == 6:
+                            lonval = " ".join(coosplit[0:3])
+                            latval = " ".join(coosplit[3:])
+                        elif len(coosplit) == 2:
+                            lonval, latval = coosplit
+                        else:
+                            msg = ("Could not parse {lonname}/{latname} values "
+                                   "from the string provided: '{coordstr}'.")
+                            raise ValueError(msg.format(lonname=lonname,
+                                                        latname=latname,
+                                                        coordstr=coordstr))
+                else:
+                    raise ValueError("A {0} cannot be created with a single value of type "
+                                     "'{1}', must be a string.".format(sclsnm, type(coordstr).__name__))
+
+            # now actually create the angle objects
+            if useradec:
+                lonang = RA(lonval, unit=units[0])
+                latang = Dec(latval, unit=units[1])
+            else:
+                if isinstance(lonval, RA):
+                    raise TypeError('Cannot provide an RA object to non-RA/Dec system {0}'.format(sclsnm))
+                if isinstance(latval, Dec):
+                    raise TypeError('Cannot provide a Dec object to non-RA/Dec system {0}'.format(sclsnm))
+                lonang = Angle(lonval, unit=units[0])
+                latang = Angle(latval, unit=units[1])
+
+            dist = None if distval is None else Distance(distval)  # copy
+
+        elif cartinit and not angleinit:
+            # cartesian-style initialization
+            for v in [coordstr, lonval, latval, distval]:
+                if v is not None:
+                    raise ValueError('Cannot give both angular and cartesian '
+                                     'coordinates while initializing ' + sclsnm)
+
+            if cartpoint is not None:
+                for v in [x, y, z, unit]:
+                    if v is not None:
+                        raise ValueError('Cannot give both a CartesianPoints '
+                                         'and x/y/z/unit parameters while '
+                                         'initializing ' + sclsnm)
+                x = cartpoint.x
+                y = cartpoint.y
+                z = cartpoint.z
+                unit = cartpoint.unit
+            r, latval, lonval = cartesian_to_spherical(x, y, z)
+
+            if useradec:
+                lonang = RA(lonval, unit=u.radian)
+                latang = Dec(latval, unit=u.radian)
+            else:
+                lonang = Angle(lonval, unit=u.radian)
+                latang = Angle(latval, unit=u.radian)
+
+            dist = None if unit is None else Distance(r, unit)
+
+        else:
+            raise TypeError('Must initialize {coordnm} with '
+                            '{latname}/{lonname}/(distance) or x/y/z '
+                            ''.format(coordnm=sclsnm, latname=latname,
+                                      lonname=lonname))
+
+        # now actually set the values
+        setattr(self, lonname, lonang)
+        setattr(self, latname, latang)
+        self._distance = dist
+
+    @abstractproperty
+    def latangle(self):
+        """
+        The latitudinal/elevation angle for these coordinates as an
+        `~astropy.coorinates.angles.Angle` object.
+
+        .. note ::
+            This should be overridden in subclasses as a read-only property that
+            just returns an attribute a way to abstract the exact choice of
+            names for the coordiantes. E.g., `ICRSCoordinates` implements this
+            by doing ``return self.ra``.
+        """
+
+    @abstractproperty
+    def lonangle(self):
+        """
+        The longitudinal/azimuthal angle for these coordinates as an
+        `~astropy.coorinates.angles.Angle` object.
+
+        .. note ::
+            This should be overridden in subclasses as a read-only property that
+            just returns an attribute a way to abstract the exact choice of
+            names for the coordinates. E.g., `ICRSCoordinates` implements this
+            by doing ``return self.dec``.
+        """
+
+    @property
+    def equinox(self):
+        """
+        The equinox of this system, or None to indicate no equinox specified.
+        """
+        return None
+
+    @property
+    def distance(self):
+        """
+        The radial distance for this coordinate object as an
+        `~astropy.coordinates.coordsystems.Distance` object.
+
+        If set as a tuple, the tuple will be passed into the
+        `~astropy.coordinates.coordsystems.Distance` constructor.
+
+        Alternatively, this may be `None`, indicating an unknown/not given
+        distance. Where necessary, this object will be interpreted as angles on
+        the unit sphere.
+        """
+        return self._distance
+
+    @distance.setter
+    def distance(self, val):
+        if val is None:
+            self._distance = None
+        elif isinstance(val, tuple):
+            self._distance = Distance(*val)
+        elif isinstance(val, Distance):
+            self._distance = val
+        else:
+            raise TypeError(
+                'Spherical coordinate distance must be a Distance object, a '
+                'tuple that can be used to instantiate a Distance object, or '
+                'None.')
+
+    @property
+    def x(self):
+        self._make_cart()
+        return self._cartpoint.x
+
+    @property
+    def y(self):
+        self._make_cart()
+        return self._cartpoint.y
+
+    @property
+    def z(self):
+        self._make_cart()
+        return self._cartpoint.z
+
+    @property
+    def cartesian(self):
+        self._make_cart()
+        return self._cartpoint
+
+    def _make_cart(self, override=False):
+        if override or self._cartpoint is None:
+            if self._distance is None:
+                r = 1
+                runit = None
+            else:
+                r = self._distance._value
+                runit = self._distance._unit
+            x, y, z = spherical_to_cartesian(r, self.latangle.radians,
+                                                self.lonangle.radians)
+            self._cartpoint = CartesianPoints(x, y, z, runit)
+
+    def separation(self, other):
+        """
+        Computes on-sky separation between this coordinate and another.
+
+        See the `~astropy.coordinates.angles.AngularSeparation` docstring
+        for further details on the actual calculation.
+
+        Parameters
+        ----------
+        other : `~astropy.coordinates.coordsystems.SphericalCoordinatesBase`
+            The coordinate system to get the separation to.
+
+        Returns
+        -------
+        sep : `~astropy.coordinates.angles.AngularSeparation`
+            The on-sky separation between this and the `other` coordinate.
+        """
+        other_in_self_system = other.transform_to(self.__class__)
+
+        lat1 = self.latangle.radians
+        lat2 = other_in_self_system.latangle.radians
+        lon1 = self.lonangle.radians
+        lon2 = other_in_self_system.lonangle.radians
+        return AngularSeparation(lat1, lon1, lat2, lon2, u.radian)
+
+    def separation_3d(self, other):
+        """
+        Computes three dimensional separation between this coordinate
+        and another.
+
+        Parameters
+        ----------
+        other : `~astropy.coordinates.coordsystems.SphericalCoordinatesBase`
+            The coordinate system to get the distance to.
+
+        Returns
+        -------
+        sep : `~astropy.coordinates.coordsystems.Distance`
+            The real-space distance between these two coordinates.
+
+        Raises
+        ------
+        ValueError
+            If this or the other coordinate do not have distances.
+        """
+        if self._distance is None:
+            raise ValueError('This object does not have a distance; cannot '
+                             'compute 3d separation.')
+
+        # do this first just in case the conversion somehow creates a distance
+        other_in_self_system = other.transform_to(self.__class__)
+
+        if other_in_self_system._distance is None:
+            raise ValueError('The other object does not have a distance; '
+                             'cannot compute 3d separation.')
+
+        dscale = other_in_self_system._distance._unit.to(self._distance._unit, 1)
+
+        dx = self.x - other_in_self_system.x * dscale
+        dy = self.y - other_in_self_system.y * dscale
+        dz = self.z - other_in_self_system.z * dscale
+
+        distval = (dx ** 2 + dy ** 2 + dz ** 2) ** 0.5
+        return Distance(distval, self._distance._unit)
+
+    #<------------transformation-related stuff here-------------------->
+    def transform_to(self, tosys):
+        """
+        Transform this coordinate to a new system.
+
+        Parameters
+        ----------
+        tosys : class
+            The system to transform this coordinate into.
+
+        Returns
+        -------
+        transcoord
+            A new object with this coordinate represented in the `tosys` system.
+
+        Raises
+        ------
+        ValueError
+            If there is no possible transformation route.
+        """
+        from copy import deepcopy
+        from .transformations import master_transform_graph
+        from .errors import ConvertError
+
+        if tosys is self.__class__:
+            return deepcopy(self)
+
+        trans = master_transform_graph.get_transform(self.__class__, tosys)
+        if trans is None:
+            raise ConvertError('Cannot transform from {0} to '
+                               '{1}'.format(self.__class__, tosys))
+        return trans(self)
+
+    def is_transformable_to(self, tosys):
+        """
+        Determines if this coordinate can be transformed to a particular system.
+
+        Parameters
+        ----------
+        tosys : class
+            The system to transform this coordinate into.
+
+        Returns
+        -------
+        transformable : bool or str
+            True if this can be trasnformed to `tosys`, False if not. The
+            string 'same' if `tosys` is the same system as this object
+            (i.e. no transformation is needed).
+        """
+        from .transformations import master_transform_graph
+
+        if self.__class__ is tosys:
+            return 'same'
+        else:
+            trans = master_transform_graph.get_transform(self.__class__, tosys)
+            return trans is not None
+
+    def __getattr__(self, name):
+        """
+        Overrides getattr to return coordinates that this can be transformed
+        to, based on the alias name in the master transform graph.
+        """
+        from .transformations import master_transform_graph
+
+        nmsys = master_transform_graph.lookup_name(name)
+        if self.__class__ is nmsys:
+            return self
+        if nmsys is not None and self.is_transformable_to(nmsys):
+            return self.transform_to(nmsys)
+        else:
+            msg = "'{0}' object has no attribute '{1}', nor a transform."
+            raise AttributeError(msg.format(self.__class__.__name__, name))
+
+    def __dir__(self):
+        """
+        Overriding the builtin `dir` behavior allows us to add the
+        transforms available by aliases.  This also allows ipython
+        tab-completion to know about the transforms.
+        """
+        from .transformations import master_transform_graph
+
+        # the stuff `dir` normally gives
+        dir_items = dir(type(self)) + self.__dict__.keys()
+
+        # determine the aliases that this can be transformed to.
+        for alias in master_transform_graph.get_aliases():
+            tosys = master_transform_graph.lookup_name(alias)
+            if self.is_transformable_to(tosys):
+                dir_items.append(alias)
+
+        return sorted(set(dir_items))
diff --git a/astropy/coordinates/distances.py b/astropy/coordinates/distances.py
new file mode 100644
index 0000000..a8f5df5
--- /dev/null
+++ b/astropy/coordinates/distances.py
@@ -0,0 +1,364 @@
+# Licensed under a 3-clause BSD style license - see LICENSE.rst
+
+"""
+This module contains the classes and utility functions for distance and
+cartesian coordinates.
+"""
+from abc import ABCMeta, abstractproperty, abstractmethod
+
+import numpy as np
+
+from .angles import RA, Dec, Angle, AngularSeparation
+from .errors import UnitsError
+from .. import units as u
+from .. import cosmology
+
+__all__ = ['Distance', 'CartesianPoints', 'cartesian_to_spherical',
+           'spherical_to_cartesian']
+
+
+# FIXME: make this subclass Quantity once Quantity is in master
+class Distance(object):
+    """
+    A one-dimensional distance.
+
+    This can be initialized in one of two ways, using either a distance
+    and a unit, or a redshift and (optionally) a cosmology.  `value`
+    and `unit` may be provided as positional arguments, but `z` and
+    `cosmology` are only valid as keyword arguments (see examples).
+
+    Parameters
+    ----------
+    value : scalar
+        The value of this distance
+    unit : `~astropy.units.core.UnitBase`
+        The units for this distance.  Must have dimensions of distance.
+    z : float
+        A redshift for this distance.  It will be converted to a distance
+        by computing the luminosity distance for this redshift given the
+        cosmology specified by `cosmology`.
+    cosmology : `~astropy.cosmology.Cosmology` or None
+        A cosmology that will be used to compute the distance from `z`.
+        If None, the current cosmology will be used (see
+        `astropy.cosmology` for details).
+
+    Raises
+    ------
+    UnitsError
+        If the `unit` is not a distance.
+
+    Examples
+    --------
+    >>> from astropy import units as u
+    >>> from astropy.cosmology import WMAP3
+    >>> d1 = Distance(10, u.Mpc)
+    >>> d2 = Distance(40, unit=u.au)
+    >>> d3 = Distance(value=5, unit=u.kpc)
+    >>> d4 = Distance(z=0.23)
+    >>> d5 = Distance(z=0.23, cosmology=WMAP3)
+    """
+
+    def __init__(self, *args, **kwargs):
+        if len(args) == 1 and isinstance(args[0], Distance):
+            # just copy
+            self._value = args[0]._value
+            self._unit = args[0]._unit
+        elif 'z' in kwargs:
+            z = kwargs.pop('z')
+            cosmo = kwargs.pop('cosmology', None)
+            if cosmo is None:
+                cosmo = cosmology.get_current()
+
+            if len(args) > 0 or len(kwargs) > 0:
+                raise TypeError('Cannot give both distance and redshift')
+
+            self._value = cosmo.luminosity_distance(z)
+            self._unit = u.Mpc
+        else:
+            if len(args) == 0:
+                value = kwargs.pop('value', None)
+                unit = kwargs.pop('unit', None)
+            elif len(args) == 1:
+                value = args[0]
+                unit = kwargs.pop('unit', None)
+            elif len(args) == 2:
+                value, unit = args
+            else:
+                raise TypeError('Distance constructor cannot take more than 2 arguments')
+
+            if len(kwargs) > 0:
+                raise TypeError('Invalid keywords provided to Distance: ' +
+                                str(kwargs.keys()))
+
+            if value is None:
+                raise ValueError('A value for the distance must be provided')
+            if unit is None:
+                raise UnitsError('A unit must be provided for distance.')
+
+            if not unit.is_equivalent(u.m):
+                raise UnitsError('provided unit for Distance is not a length')
+            self._value = value
+            self._unit = unit
+
+    def __repr__(self):
+        return "<{0} {1:.5f} {2!s}>".format(type(self).__name__, self._value, self._unit)
+
+    @property
+    def lightyear(self):
+        """
+        The value of this distance in light years
+        """
+        return self._unit.to(u.lyr, self._value)
+
+    @property
+    def pc(self):
+        """
+        The value of this distance in parsecs
+        """
+        return self._unit.to(u.parsec, self._value)
+
+    @property
+    def kpc(self):
+        """
+        The value of this distance in kiloparsecs
+        """
+        return self._unit.to(u.kpc, self._value)
+
+    @property
+    def Mpc(self):
+        """
+        The value of this distance in megaparsecs
+        """
+        return self._unit.to(u.Mpc, self._value)
+
+    @property
+    def au(self):
+        """
+        The value of this distance in astronomical units
+        """
+        return self._unit.to(u.au, self._value)
+
+    @property
+    def m(self):
+        """
+        The value of this distance in meters
+        """
+        return self._unit.to(u.m, self._value)
+
+    @property
+    def km(self):
+        """
+        The value of this distance in kilometers
+        """
+        return self._unit.to(u.km, self._value)
+
+    @property
+    def z(self):
+        """
+        The redshift for this distance assuming its physical distance is
+        a luminosity distance.
+
+        .. note::
+            This uses the "current" cosmology to determine the appropriate
+            distance to redshift conversions.  See `astropy.cosmology`
+            for details on how to change this.
+
+        """
+        return self.compute_z()
+
+    def compute_z(self, cosmology=None):
+        """
+        The redshift for this distance assuming its physical distance is
+        a luminosity distance.
+
+        Parameters
+        ----------
+        cosmology : `~astropy.cosmology.cosmology` or None
+            The cosmology to assume for this calculation, or None to use the
+            current cosmology.
+
+        """
+        from ..cosmology import luminosity_distance
+        from scipy import optimize
+
+        # FIXME: array: need to make this calculation more vector-friendly
+
+        f = lambda z, d, cos: (luminosity_distance(z, cos) - d) ** 2
+        return optimize.brent(f, (self.Mpc, cosmology))
+
+
+class CartesianPoints(object):
+    """
+    A cartesian representation of a point in three-dimensional space.
+
+    Attributes
+    ----------
+    x : number or array
+        The first cartesian coordinate.
+    y : number or array
+        The second cartesian coordinate.
+    z : number or array
+        The third cartesian coordinate.
+    unit : `~astropy.units.UnitBase` object or None
+        The physical unit of the coordinate values.
+    """
+
+    def __init__(self, x, y, z, unit=None):
+        self.x = x
+        self.y = y
+        self.z = z
+        self.unit = unit
+
+    def to_spherical(self):
+        """
+        Converts to the spherical representation of this point.
+
+        Returns
+        -------
+        r : float or array
+            The radial coordinate (in the same units as the inputs).
+        lat : float or array
+            The latitude in radians
+        lon : float or array
+            The longitude in radians
+
+        """
+        return cartesian_to_spherical(self.x, self.y, self.z)
+
+    def __repr__(self):
+        return '<CartesianPoints ({x}, {y}, {z}) {unit}>'.format(x=self.x,
+                y=self.y, z=self.z, unit=self.unit)
+
+    def __eq__(self, other):
+        return (isinstance(other, CartesianPoints) and self.x == other.x and
+                self.y == other.y and self.z == other.z and
+                self.unit == other.unit)
+
+    def __add__(self, other):
+        if isinstance(other, CartesianPoints) or (hasattr(other, 'x') and
+            hasattr(other, 'y') and hasattr(other, 'z') and
+            hasattr(other, 'unit')):
+            newx = self.x + other.unit.to(self.unit, other.x)
+            newy = self.y + other.unit.to(self.unit, other.y)
+            newz = self.z + other.unit.to(self.unit, other.z)
+        else:
+            msg = "unsupported operand type(s) for +: '{sel}' and '{other}'"
+            raise TypeError(msg.format(type(self).__name__,
+                                        type(other).__name__))
+        return CartesianPoints(newx, newy, newz, self.unit)
+
+    def __sub__(self, other):
+        if isinstance(other, CartesianPoints) or (hasattr(other, 'x') and
+            hasattr(other, 'y') and hasattr(other, 'z') and
+            hasattr(other, 'unit')):
+            newx = self.x - other.unit.to(self.unit, other.x)
+            newy = self.y - other.unit.to(self.unit, other.y)
+            newz = self.z - other.unit.to(self.unit, other.z)
+        else:
+            msg = "unsupported operand type(s) for -: '{sel}' and '{other}'"
+            raise TypeError(msg.format(type(self).__name__,
+                                        type(other).__name__))
+        return CartesianPoints(newx, newy, newz, self.unit)
+
+#<------------transformation-related utility functions----------------->
+
+
+def cartesian_to_spherical(x, y, z):
+    """
+    Converts 3D rectangular cartesian coordinates to spherical polar
+    coordinates.
+
+    Note that the resulting angles are latitude/longitude or
+    elevation/azimuthal form.  I.e., the origin is along the equator
+    rather than at the north pole.
+
+    .. note::
+        This is a low-level function used internally in
+        `astropy.coordinates`.  It is provided for users if they really
+        want to use it, but it is recommended that you use the
+        `astropy.coordinates` coordinate systems.
+
+    Parameters
+    ----------
+    x : scalar or array-like
+        The first cartesian coordinate.
+    y : scalar or array-like
+        The second cartesian coordinate.
+    z : scalar or array-like
+        The third cartesian coordinate.
+
+    Returns
+    -------
+    r : float or array
+        The radial coordinate (in the same units as the inputs).
+    lat : float or array
+        The latitude in radians
+    lon : float or array
+        The longitude in radians
+    """
+    import math
+
+    xsq = x ** 2
+    ysq = y ** 2
+    zsq = z ** 2
+
+    r = (xsq + ysq + zsq) ** 0.5
+    s = (xsq + ysq) ** 0.5
+
+    if np.isscalar(x) and np.isscalar(y) and np.isscalar(z):
+        lon = math.atan2(y, x)
+        lat = math.atan2(z, s)
+    else:
+        lon = np.arctan2(y, x)
+        lat = np.arctan2(z, s)
+
+    return r, lat, lon
+
+
+def spherical_to_cartesian(r, lat, lon):
+    """
+    Converts spherical polar coordinates to rectangular cartesian
+    coordinates.
+
+    Note that the input angles should be in latitude/longitude or
+    elevation/azimuthal form.  I.e., the origin is along the equator
+    rather than at the north pole.
+
+    .. note::
+        This is a low-level function used internally in
+        `astropy.coordinates`.  It is provided for users if they really
+        want to use it, but it is recommended that you use the
+        `astropy.coordinates` coordinate systems.
+
+    Parameters
+    ----------
+    r : scalar or array-like
+        The radial coordinate (in the same units as the inputs).
+    lat : scalar or array-like
+        The latitude in radians
+    lon : scalar or array-like
+        The longitude in radians
+
+    Returns
+    -------
+    x : float or array
+        The first cartesian coordinate.
+    y : float or array
+        The second cartesian coordinate.
+    z : float or array
+        The third cartesian coordinate.
+
+
+    """
+    import math
+
+    if np.isscalar(r) and np.isscalar(lat) and np.isscalar(lon):
+        x = r * math.cos(lat) * math.cos(lon)
+        y = r * math.cos(lat) * math.sin(lon)
+        z = r * math.sin(lat)
+    else:
+        x = r * np.cos(lat) * np.cos(lon)
+        y = r * np.cos(lat) * np.sin(lon)
+        z = r * np.sin(lat)
+
+    return x, y, z
diff --git a/astropy/coordinates/earth_orientation.py b/astropy/coordinates/earth_orientation.py
new file mode 100644
index 0000000..d7f4370
--- /dev/null
+++ b/astropy/coordinates/earth_orientation.py
@@ -0,0 +1,414 @@
+# Licensed under a 3-clause BSD style license - see LICENSE.rst
+
+"""
+This module contains standard functions for earth orientation, such as
+precession and nutation.
+
+This module is (currently) not intended to be part of the public API, but
+is instead primarily for internal use in `coordinates`
+"""
+import numpy as np
+
+from ..time import Time
+from .. import units as u
+
+jd1950 = Time('B1950', scale='tai').jd
+jd2000 = Time('J2000', scale='utc').jd
+_asecperrad = u.radian.to(u.arcsec)
+
+
+def eccentricity(jd):
+    """
+    Computes the eccentricity of the Earth's orbit at the requested Julian
+    Date.
+
+    Parameters
+    ----------
+    jd : scalar or array-like
+        julian date at which to compute the eccentricity
+
+    returns
+    -------
+    eccentricity : scalar or array
+        The eccentricity in degrees (or array of eccentricities)
+
+    References
+    ----------
+    * Explanatory Supplement to the Astronomical Almanac: P. Kenneth
+      Seidelmann (ed), University Science Books (1992).
+    """
+    T = (jd - jd1950) / 36525.0
+
+    p = (-0.000000126, - 0.00004193, 0.01673011)
+
+    return np.polyval(p, T)
+
+
+def mean_lon_of_perigee(jd):
+    """
+    Computes the mean longitude of perigee of the Earth's orbit at the
+    requested Julian Date.
+
+    Parameters
+    ----------
+    jd : scalar or array-like
+        julian date at which to compute the mean longitude of perigee
+
+    returns
+    -------
+    mean_lon_of_perigee : scalar or array
+        Mean longitude of perigee in degrees (or array of mean longitudes)
+
+    References
+    ----------
+    * Explanatory Supplement to the Astronomical Almanac: P. Kenneth
+      Seidelmann (ed), University Science Books (1992).
+    """
+    T = (jd - jd1950) / 36525.0
+
+    p = (0.012, 1.65, 6190.67, 1015489.951)
+
+    return np.polyval(p, T) / 3600.
+
+
+def obliquity(jd, algorithm=2006):
+    """
+    Computes the obliquity of the Earth at the requested Julian Date.
+
+    Parameters
+    ----------
+    jd : scalar or array-like
+        julian date at which to compute the obliquity
+    algorithm : int
+        Year of algorithm based on IAU adoption. Can be 2006, 2000 or 1980. The
+        2006 algorithm is mentioned in Circular 179, but the canonical reference
+        for the IAU adoption is apparently Hilton et al. 06 is composed of the
+        1980 algorithm with a precession-rate correction due to the 2000
+        precession models, and a description of the 1980 algorithm can be found
+        in the Explanatory Supplement to the Astronomical Almanac.
+
+    returns
+    -------
+    obliquity : scalar or array
+        Mean obliquity in degrees (or array of obliquities)
+
+    References
+    ----------
+    * Hilton, J. et al., 2006, Celest.Mech.Dyn.Astron. 94, 351. 2000
+    * USNO Circular 179
+    * Explanatory Supplement to the Astronomical Almanac: P. Kenneth
+      Seidelmann (ed), University Science Books (1992).
+    """
+    T = (jd - jd2000) / 36525.0
+
+    if algorithm == 2006:
+        p = (-0.0000000434, -0.000000576, 0.00200340, -0.0001831, -46.836769, 84381.406)
+        corr = 0
+    elif algorithm == 2000:
+        p = (0.001813, -0.00059, -46.8150, 84381.448)
+        corr = -0.02524 * T
+    elif algorithm == 1980:
+        p = (0.001813, -0.00059, -46.8150, 84381.448)
+        corr = 0
+    else:
+        raise ValueError('invalid algorithm year for computing obliquity')
+
+    return (np.polyval(p, T) + corr) / 3600.
+
+
+# TODO: replace this with SOFA equivalent
+def precession_matrix_Capitaine(fromepoch, toepoch):
+    """
+    Computes the precession matrix from one julian epoch to another.
+    The exact method is based on Capitaine et al. 2003, which should
+    match the IAU 2006 standard.
+
+    Parameters
+    ----------
+    fromepoch : `~astropy.time.Time`
+        The epoch to precess from.
+    toepoch : `~astropy.time.Time`
+        The epoch to precess to.
+
+    Returns
+    -------
+    pmatrix : 3x3 array
+        Precession matrix to get from `fromepoch` to `toepoch`
+
+    References
+    ----------
+    USNO Circular 179
+    """
+    mat_fromto2000 = _precess_from_J2000_Capitaine(fromepoch.jyear).T
+    mat_2000toto = _precess_from_J2000_Capitaine(toepoch.jyear)
+
+    return np.dot(mat_2000toto, mat_fromto2000)
+
+
+def _precess_from_J2000_Capitaine(epoch):
+    """
+    Computes the precession matrix from J2000 to the given Julian Epoch.
+    Expression from from Capitaine et al. 2003 as expressed in the USNO
+    Circular 179.  This should match the IAU 2006 standard from SOFA.
+
+    Parameters
+    ----------
+    epoch : scalar
+        The epoch as a julian year number (e.g. J2000 is 2000.0)
+
+    """
+    from .angles import rotation_matrix
+
+    T = (epoch - 2000.0) / 100.0
+    # from USNO circular
+    pzeta = (-0.0000003173, -0.000005971, 0.01801828, 0.2988499, 2306.083227, 2.650545)
+    pz = (-0.0000002904, -0.000028596, 0.01826837, 1.0927348, 2306.077181, -2.650545)
+    ptheta = (-0.0000001274, -0.000007089, -0.04182264, -0.4294934, 2004.191903, 0)
+    zeta = np.polyval(pzeta, T) / 3600.0
+    z = np.polyval(pz, T) / 3600.0
+    theta = np.polyval(ptheta, T) / 3600.0
+
+    return rotation_matrix(-z, 'z') *\
+           rotation_matrix(theta, 'y') *\
+           rotation_matrix(-zeta, 'z')
+
+
+def _precession_matrix_besselian(epoch1, epoch2):
+    """
+    computes the precession matrix from one Besselian epoch to another using
+    Newcomb's method.
+
+    `epoch1` and `epoch2` are in besselian year numbers
+    """
+    from .angles import rotation_matrix
+
+    # tropical years
+    t1 = (epoch1 - 1850.0) / 1000.0
+    t2 = (epoch2 - 1850.0) / 1000.0
+    dt = t2 - t1
+
+    zeta1 = 23035.545 + t1 * 139.720 + 0.060 * t1 * t1
+    zeta2 = 30.240 - 0.27 * t1
+    zeta3 = 17.995
+    pzeta = (zeta3, zeta2, zeta1, 0)
+    zeta = np.polyval(pzeta, dt) / 3600
+
+    z1 = 23035.545 + t1 * 139.720 + 0.060 * t1 * t1
+    z2 = 109.480 + 0.39 * t1
+    z3 = 18.325
+    pz = (z3, z2, z1, 0)
+    z = np.polyval(pz, dt) / 3600
+
+    theta1 = 20051.12 - 85.29 * t1 - 0.37 * t1 * t1
+    theta2 = -42.65 - 0.37 * t1
+    theta3 = -41.8
+    ptheta = (theta3, theta2, theta1, 0)
+    theta = np.polyval(ptheta, dt) / 3600
+
+    return rotation_matrix(-z, 'z') *\
+           rotation_matrix(theta, 'y') *\
+           rotation_matrix(-zeta, 'z')
+
+
+def _load_nutation_data(datastr, seriestype):
+    """
+    Loads nutation series from data stored in string form.
+
+    Seriestype can be 'lunisolar' or 'planetary'
+    """
+    from os.path import join
+
+    if seriestype == 'lunisolar':
+        dtypes = [('nl', int),
+                  ('nlp', int),
+                  ('nF', int),
+                  ('nD', int),
+                  ('nOm', int),
+                  ('ps', float),
+                  ('pst', float),
+                  ('pc', float),
+                  ('ec', float),
+                  ('ect', float),
+                  ('es', float)]
+    elif seriestype == 'planetary':
+        dtypes = [('nl', int),
+                  ('nF', int),
+                  ('nD', int),
+                  ('nOm', int),
+                  ('nme', int),
+                  ('nve', int),
+                  ('nea', int),
+                  ('nma', int),
+                  ('nju', int),
+                  ('nsa', int),
+                  ('nur', int),
+                  ('nne', int),
+                  ('npa', int),
+                  ('sp', int),
+                  ('cp', int),
+                  ('se', int),
+                  ('ce', int)]
+    else:
+        raise ValueError('requested invalid nutation series type')
+
+    lines = [l for l in datastr.split('\n') if not l.startswith('#') if not l.strip() == '']
+
+    lists = [[] for n in dtypes]
+    for l in lines:
+        for i, e in enumerate(l.split(' ')):
+            lists[i].append(dtypes[i][1](e))
+    return np.rec.fromarrays(lists, names=[e[0] for e in dtypes])
+
+_nut_data_00b = """
+#l lprime F D Omega longitude_sin longitude_sin*t longitude_cos obliquity_cos obliquity_cos*t,obliquity_sin
+
+0 0 0 0 1 -172064161.0 -174666.0 33386.0 92052331.0 9086.0 15377.0
+0 0 2 -2 2 -13170906.0 -1675.0 -13696.0 5730336.0 -3015.0 -4587.0
+0 0 2 0 2 -2276413.0 -234.0 2796.0 978459.0 -485.0 1374.0
+0 0 0 0 2 2074554.0 207.0 -698.0 -897492.0 470.0 -291.0
+0 1 0 0 0 1475877.0 -3633.0 11817.0 73871.0 -184.0 -1924.0
+0 1 2 -2 2 -516821.0 1226.0 -524.0 224386.0 -677.0 -174.0
+1 0 0 0 0 711159.0 73.0 -872.0 -6750.0 0.0 358.0
+0 0 2 0 1 -387298.0 -367.0 380.0 200728.0 18.0 318.0
+1 0 2 0 2 -301461.0 -36.0 816.0 129025.0 -63.0 367.0
+0 -1 2 -2 2 215829.0 -494.0 111.0 -95929.0 299.0 132.0
+0 0 2 -2 1 128227.0 137.0 181.0 -68982.0 -9.0 39.0
+-1 0 2 0 2 123457.0 11.0 19.0 -53311.0 32.0 -4.0
+-1 0 0 2 0 156994.0 10.0 -168.0 -1235.0 0.0 82.0
+1 0 0 0 1 63110.0 63.0 27.0 -33228.0 0.0 -9.0
+-1 0 0 0 1 -57976.0 -63.0 -189.0 31429.0 0.0 -75.0
+-1 0 2 2 2 -59641.0 -11.0 149.0 25543.0 -11.0 66.0
+1 0 2 0 1 -51613.0 -42.0 129.0 26366.0 0.0 78.0
+-2 0 2 0 1 45893.0 50.0 31.0 -24236.0 -10.0 20.0
+0 0 0 2 0 63384.0 11.0 -150.0 -1220.0 0.0 29.0
+0 0 2 2 2 -38571.0 -1.0 158.0 16452.0 -11.0 68.0
+0 -2 2 -2 2 32481.0 0.0 0.0 -13870.0 0.0 0.0
+-2 0 0 2 0 -47722.0 0.0 -18.0 477.0 0.0 -25.0
+2 0 2 0 2 -31046.0 -1.0 131.0 13238.0 -11.0 59.0
+1 0 2 -2 2 28593.0 0.0 -1.0 -12338.0 10.0 -3.0
+-1 0 2 0 1 20441.0 21.0 10.0 -10758.0 0.0 -3.0
+2 0 0 0 0 29243.0 0.0 -74.0 -609.0 0.0 13.0
+0 0 2 0 0 25887.0 0.0 -66.0 -550.0 0.0 11.0
+0 1 0 0 1 -14053.0 -25.0 79.0 8551.0 -2.0 -45.0
+-1 0 0 2 1 15164.0 10.0 11.0 -8001.0 0.0 -1.0
+0 2 2 -2 2 -15794.0 72.0 -16.0 6850.0 -42.0 -5.0
+0 0 -2 2 0 21783.0 0.0 13.0 -167.0 0.0 13.0
+1 0 0 -2 1 -12873.0 -10.0 -37.0 6953.0 0.0 -14.0
+0 -1 0 0 1 -12654.0 11.0 63.0 6415.0 0.0 26.0
+-1 0 2 2 1 -10204.0 0.0 25.0 5222.0 0.0 15.0
+0 2 0 0 0 16707.0 -85.0 -10.0 168.0 -1.0 10.0
+1 0 2 2 2 -7691.0 0.0 44.0 3268.0 0.0 19.0
+-2 0 2 0 0 -11024.0 0.0 -14.0 104.0 0.0 2.0
+0 1 2 0 2 7566.0 -21.0 -11.0 -3250.0 0.0 -5.0
+0 0 2 2 1 -6637.0 -11.0 25.0 3353.0 0.0 14.0
+0 -1 2 0 2 -7141.0 21.0 8.0 3070.0 0.0 4.0
+0 0 0 2 1 -6302.0 -11.0 2.0 3272.0 0.0 4.0
+1 0 2 -2 1 5800.0 10.0 2.0 -3045.0 0.0 -1.0
+2 0 2 -2 2 6443.0 0.0 -7.0 -2768.0 0.0 -4.0
+-2 0 0 2 1 -5774.0 -11.0 -15.0 3041.0 0.0 -5.0
+2 0 2 0 1 -5350.0 0.0 21.0 2695.0 0.0 12.0
+0 -1 2 -2 1 -4752.0 -11.0 -3.0 2719.0 0.0 -3.0
+0 0 0 -2 1 -4940.0 -11.0 -21.0 2720.0 0.0 -9.0
+-1 -1 0 2 0 7350.0 0.0 -8.0 -51.0 0.0 4.0
+2 0 0 -2 1 4065.0 0.0 6.0 -2206.0 0.0 1.0
+1 0 0 2 0 6579.0 0.0 -24.0 -199.0 0.0 2.0
+0 1 2 -2 1 3579.0 0.0 5.0 -1900.0 0.0 1.0
+1 -1 0 0 0 4725.0 0.0 -6.0 -41.0 0.0 3.0
+-2 0 2 0 2 -3075.0 0.0 -2.0 1313.0 0.0 -1.0
+3 0 2 0 2 -2904.0 0.0 15.0 1233.0 0.0 7.0
+0 -1 0 2 0 4348.0 0.0 -10.0 -81.0 0.0 2.0
+1 -1 2 0 2 -2878.0 0.0 8.0 1232.0 0.0 4.0
+0 0 0 1 0 -4230.0 0.0 5.0 -20.0 0.0 -2.0
+-1 -1 2 2 2 -2819.0 0.0 7.0 1207.0 0.0 3.0
+-1 0 2 0 0 -4056.0 0.0 5.0 40.0 0.0 -2.0
+0 -1 2 2 2 -2647.0 0.0 11.0 1129.0 0.0 5.0
+-2 0 0 0 1 -2294.0 0.0 -10.0 1266.0 0.0 -4.0
+1 1 2 0 2 2481.0 0.0 -7.0 -1062.0 0.0 -3.0
+2 0 0 0 1 2179.0 0.0 -2.0 -1129.0 0.0 -2.0
+-1 1 0 1 0 3276.0 0.0 1.0 -9.0 0.0 0.0
+1 1 0 0 0 -3389.0 0.0 5.0 35.0 0.0 -2.0
+1 0 2 0 0 3339.0 0.0 -13.0 -107.0 0.0 1.0
+-1 0 2 -2 1 -1987.0 0.0 -6.0 1073.0 0.0 -2.0
+1 0 0 0 2 -1981.0 0.0 0.0 854.0 0.0 0.0
+-1 0 0 1 0 4026.0 0.0 -353.0 -553.0 0.0 -139.0
+0 0 2 1 2 1660.0 0.0 -5.0 -710.0 0.0 -2.0
+-1 0 2 4 2 -1521.0 0.0 9.0 647.0 0.0 4.0
+-1 1 0 1 1 1314.0 0.0 0.0 -700.0 0.0 0.0
+0 -2 2 -2 1 -1283.0 0.0 0.0 672.0 0.0 0.0
+1 0 2 2 1 -1331.0 0.0 8.0 663.0 0.0 4.0
+-2 0 2 2 2 1383.0 0.0 -2.0 -594.0 0.0 -2.0
+-1 0 0 0 2 1405.0 0.0 4.0 -610.0 0.0 2.0
+1 1 2 -2 2 1290.0 0.0 0.0 -556.0 0.0 0.0
+"""[1:-1]
+_nut_data_00b = _load_nutation_data(_nut_data_00b, 'lunisolar')
+
+# TODO: replace w/SOFA equivalent
+
+
+def nutation_components2000B(jd):
+    """
+    Computes nutation components following the IAU 2000B specification
+
+    Parameters
+    ----------
+    jd : scalar
+        epoch at which to compute the nutation components as a JD
+
+    Returns
+    -------
+    eps : float
+        epsilon in radians
+    dpsi : float
+        dpsi in radians
+    deps : float
+        depsilon in raidans
+    """
+    epsa = np.radians(obliquity(jd, 2000))
+    t = (jd - jd2000) / 36525
+
+    # Fundamental (Delaunay) arguments from Simon et al. (1994) via SOFA
+    # Mean anomaly of moon
+    el = ((485868.249036 + 1717915923.2178 * t) % 1296000) / _asecperrad
+    # Mean anomaly of sun
+    elp = ((1287104.79305 + 129596581.0481 * t) % 1296000) / _asecperrad
+    # Mean argument of the latitude of Moon
+    F = ((335779.526232 + 1739527262.8478 * t) % 1296000) / _asecperrad
+    # Mean elongation of the Moon from Sun
+    D = ((1072260.70369 + 1602961601.2090 * t) % 1296000) / _asecperrad
+    # Mean longitude of the ascending node of Moon
+    Om = ((450160.398036 + -6962890.5431 * t) % 1296000) / _asecperrad
+
+    # compute nutation series using array loaded from data directory
+    dat = _nut_data_00b
+    arg = dat.nl * el + dat.nlp * elp + dat.nF * F + dat.nD * D + dat.nOm * Om
+    sarg = np.sin(arg)
+    carg = np.cos(arg)
+
+    p1u_asecperrad = _asecperrad * 1e7  # 0.1 microasrcsecperrad
+    dpsils = np.sum((dat.ps + dat.pst * t) * sarg + dat.pc * carg) / p1u_asecperrad
+    depsls = np.sum((dat.ec + dat.ect * t) * carg + dat.es * sarg) / p1u_asecperrad
+    # fixed offset in place of planetary tersm
+    m_asecperrad = _asecperrad * 1e3  # milliarcsec per rad
+    dpsipl = -0.135 / m_asecperrad
+    depspl = 0.388 / m_asecperrad
+
+    return epsa, dpsils + dpsipl, depsls + depspl  # all in radians
+
+
+def nutation_matrix(epoch):
+    """
+    Nutation matrix generated from nutation components.
+
+    Matrix converts from mean coordinate to true coordinate as
+    r_true = M * r_mean
+    """
+    from .angles import rotation_matrix
+
+    # TODO: implement higher precision 2006/2000A model if requested/needed
+    epsa, dpsi, deps = nutation_components2000B(epoch.jd)  # all in radians
+
+    rot1 = rotation_matrix(-(epsa + deps), 'x', False)
+    rot2 = rotation_matrix(-dpsi, 'z', False)
+    rot3 = rotation_matrix(epsa, 'x', False)
+
+    return rot1 * rot2 * rot3
diff --git a/astropy/coordinates/errors.py b/astropy/coordinates/errors.py
new file mode 100644
index 0000000..8e3396f
--- /dev/null
+++ b/astropy/coordinates/errors.py
@@ -0,0 +1,90 @@
+# -*- coding: utf-8 -*-
+# Licensed under a 3-clause BSD style license - see LICENSE.rst
+
+''' This module defines custom errors and exceptions used in astropy.coordinates. '''
+
+__all__ = ['RangeError', 'BoundsError', 'UnitsError', 'IllegalHourError',
+           'IllegalMinuteError', 'IllegalSecondError', 'ConvertError']
+
+
+class RangeError(ValueError):
+    """
+    Raised when some part of an angle is out of its valid range.
+    """
+
+
+class BoundsError(RangeError):
+    """
+    Raised when an angle is outside of its user-specified bounds.
+    """
+
+
+class IllegalHourError(RangeError):
+    """
+    Raised when an hour value is not in the range [0,24).
+
+    Usage::
+
+        if not 0 <= hr < 24:
+        raise IllegalHourError(hour)
+
+    Parameters
+    ----------
+    hour : int, float
+    """
+    def __init__(self, hour):
+        self.hour = hour
+
+    def __str__(self):
+        return "An invalid value for 'hours' was found ('{0}'); must be in the range [0,24).".format(self.hour)
+
+
+class IllegalMinuteError(RangeError):
+    """
+    Raised when an minute value is not in the range [0,60).
+
+    Usage:
+        if not 0 <= min < 60:
+            raise IllegalMinuteError(minute)
+
+    Parameters
+    ----------
+    minute : int, float
+    """
+    def __init__(self, minute):
+        self.minute = minute
+
+    def __str__(self):
+        return "An invalid value for 'minute' was found ('{0}'); must be in the range [0,60).".format(self.minute)
+
+
+class IllegalSecondError(RangeError):
+    """
+    Raised when an second value (time) is not in the range [0,60).
+
+    Usage:
+        if not 0 <= sec < 60:
+            raise IllegalSecondError(second)
+
+    Parameters
+    ----------
+    second : int, float
+    """
+    def __init__(self, second):
+        self.second = second
+
+    def __str__(self):
+        return "An invalid value for 'second' was found ('{0}'); must be in the range [0,60).".format(self.second)
+
+
+# TODO: consider if this should be used to `units`?
+class UnitsError(ValueError):
+    """
+    Raised if units are missing or invalid.
+    """
+
+
+class ConvertError(Exception):
+    """
+    Raised if a coordinate system cannot be converted to another
+    """
diff --git a/astropy/coordinates/setup_package.py b/astropy/coordinates/setup_package.py
new file mode 100644
index 0000000..98352d0
--- /dev/null
+++ b/astropy/coordinates/setup_package.py
@@ -0,0 +1,2 @@
+def get_package_data():
+    return {'astropy.coordinates.tests.accuracy': ['*.csv']}
diff --git a/astropy/tools/tests/__init__.py b/astropy/coordinates/tests/__init__.py
similarity index 100%
rename from astropy/tools/tests/__init__.py
rename to astropy/coordinates/tests/__init__.py
diff --git a/astropy/config/tests/__init__.py b/astropy/coordinates/tests/accuracy/__init__.py
similarity index 100%
copy from astropy/config/tests/__init__.py
copy to astropy/coordinates/tests/accuracy/__init__.py
diff --git a/astropy/coordinates/tests/accuracy/fk4_no_e_fk4.csv b/astropy/coordinates/tests/accuracy/fk4_no_e_fk4.csv
new file mode 100644
index 0000000..89ede4c
--- /dev/null
+++ b/astropy/coordinates/tests/accuracy/fk4_no_e_fk4.csv
@@ -0,0 +1,202 @@
+# This file was generated with the ref_fk4_no_e_fk4.py script, and the reference values were computed using AST
+obstime,ra_in,dec_in,ra_fk4ne,dec_fk4ne,ra_fk4,dec_fk4
+B1995.95,334.661793414,43.9385116594,334.661871722,43.9384643913,334.661715106,43.9385589276
+B1954.56,113.895199649,-14.1109832563,113.895104206,-14.1109806856,113.895295093,-14.110985827
+B1953.55,66.2107722038,-7.76265420193,66.2106936357,-7.76263900837,66.2108507719,-7.76266939548
+B1970.69,73.6417002791,41.7006137481,73.6415874825,41.7005905459,73.6418130758,41.7006369502
+B1960.78,204.381010469,-14.9357743223,204.381033022,-14.935790469,204.380987917,-14.9357581756
+B1975.98,214.396093073,-66.7648451487,214.39618819,-66.7649221332,214.395997956,-66.7647681643
+B1977.93,347.225227105,6.27744217753,347.225265767,6.27744057158,347.225188443,6.27744378347
+B1973.69,235.143754874,-5.59566003897,235.143821166,-5.59565879904,235.143688582,-5.59566127889
+B1960.79,269.606389512,26.7823112195,269.6064937,26.7823268289,269.606285325,26.78229561
+B1961.97,235.285153507,-14.0695156888,235.285221697,-14.0695245442,235.285085317,-14.0695068334
+B1960.84,269.177331338,42.9472695107,269.177458208,42.9472886864,269.177204468,42.947250335
+B1982.78,346.070424986,-3.51848810713,346.070465234,-3.51847491299,346.070384739,-3.51850130129
+B1992.32,3.01978725896,7.19732176646,3.0198007213,7.19731786183,3.0197737966,7.1973256711
+B1996.52,38.3199756112,18.8080489808,38.3199297604,18.8080292742,38.320021462,18.8080686874
+B1990.02,107.533336957,-4.33088623215,107.533242366,-4.3308791254,107.533431548,-4.33089333889
+B1984.04,236.30802591,14.3162535375,236.308095417,14.316277761,236.307956402,14.316229314
+B1960.36,291.532518915,-33.7960784017,291.532631247,-33.7960622584,291.532406582,-33.7960945449
+B1987.08,313.983328941,27.7572327639,313.983419024,27.757215788,313.983238857,27.7572497397
+B1984.85,347.273135054,-13.6880685538,347.273174533,-13.6880403026,347.273095575,-13.688096805
+B1969.09,260.526724891,-37.6134342267,260.526837065,-37.6134483095,260.526612717,-37.6134201437
+B1992.51,231.291118043,-27.2371455509,231.291186922,-27.2371716878,231.291049163,-27.237119414
+B1976.41,258.283303492,-30.1025933842,258.283404615,-30.1026049901,258.28320237,-30.1025817782
+B1994.65,168.335642599,-44.084769302,168.33559145,-44.0848244927,168.335693748,-44.0847141113
+B1991.03,117.210483914,32.8708634152,117.210375337,32.8708843641,117.210592491,32.8708424662
+B1961.43,158.272058119,-29.286471988,158.271999107,-29.2865040826,158.27211713,-29.2864398934
+B1991.03,262.688069789,-48.1516431413,262.688204769,-48.1516601921,262.687934809,-48.1516260902
+B1956.93,357.845250924,19.2890677934,357.845273996,19.2890447616,357.845227852,19.2890908252
+B1974.12,243.674536239,-10.0431678136,243.67461278,-10.0431700653,243.674459697,-10.0431655619
+B1957.44,284.696106425,19.6051067047,284.696206986,19.6051121836,284.696005864,19.6051012256
+B1972.41,61.5291328053,18.6403709997,61.5290555992,18.640359185,61.5292100114,18.6403828144
+B1983.30,9.66573928438,-22.9075078717,9.66574187976,-22.9074636315,9.66573668899,-22.9075521118
+B1989.45,288.133287813,-36.6947385674,288.1334053,-36.6947252717,288.133170326,-36.694751863
+B1983.10,325.340113758,-33.7758802174,325.340195579,-33.7758368156,325.340031937,-33.7759236192
+B1985.58,8.88343575454,-49.4693354042,8.88344142656,-49.4692581619,8.88343008249,-49.4694126467
+B1994.40,177.029034641,-67.7755279684,177.028973591,-67.7756101942,177.02909569,-67.7754457425
+B1957.08,189.451860246,-68.7071945134,189.451852687,-68.707280034,189.451867805,-68.7071089929
+B1957.38,214.691763751,-32.6160600699,214.691808834,-32.6161002775,214.691718668,-32.6160198625
+B1966.30,18.7047162369,-32.9080620608,18.7047012927,-32.9080042868,18.7047311812,-32.9081198349
+B1951.59,322.232230099,14.4669345738,322.232303942,14.4669266585,322.232156257,14.466942489
+B1984.39,262.175824918,51.7319974933,262.175969881,51.7320265851,262.175679954,51.7319684013
+B1988.24,294.6060041,34.0181871087,294.606115453,34.0181812889,294.605892748,34.0181929283
+B1967.50,180.08019102,26.2892216009,180.080170768,26.2892699746,180.080211273,26.2891732273
+B1980.80,291.668187169,-22.2789167174,291.668288006,-22.2789027838,291.668086332,-22.2789306509
+B1997.92,34.548669268,-15.8924906144,34.5486300111,-15.8924591395,34.548708525,-15.8925220893
+B1964.55,78.8220157436,-37.4332268082,78.8219051397,-37.4331986299,78.8221263475,-37.4332549865
+B1984.33,93.1388621771,60.5731416456,93.1386708523,60.5731340793,93.139053502,60.5731492117
+B1952.11,168.518071423,7.09229333513,168.51803468,7.09231202586,168.518108166,7.09227464443
+B1953.13,165.374352937,39.3890686842,165.374299611,39.3891290726,165.374406263,39.3890082959
+B1990.72,255.423520875,-17.5881075751,255.423610608,-17.5881124458,255.423431143,-17.5881027044
+B1971.83,64.0990821181,36.8289797648,64.098987426,36.8289518646,64.0991768103,36.829007665
+B1969.60,191.321958369,-52.3532066605,191.321958947,-52.3532769701,191.321957792,-52.3531363511
+B1966.53,60.3872023631,25.1025882655,60.3871229238,25.1025691776,60.3872818026,25.1026073533
+B1972.88,276.773010626,56.6051138031,276.773182582,56.6051241599,276.772838671,56.6051034461
+B1991.77,334.141397682,37.3852087993,334.141469519,37.3851690556,334.141325844,37.3852485429
+B1973.34,219.417716878,-20.2290328911,219.417764848,-20.2290543437,219.417668907,-20.2290114386
+B1971.06,54.0660580808,-29.3264933861,54.0659838918,-29.3264524474,54.06613227,-29.3265343247
+B1978.54,176.26561333,-0.572718169429,176.265589013,-0.572711155523,176.265637647,-0.572725183324
+B1986.95,135.84418338,-9.94938261687,135.844104187,-9.94938414897,135.844262573,-9.94938108476
+B1952.75,305.496508312,-8.63421746611,305.496595751,-8.63420374088,305.496420873,-8.63423119132
+B1981.21,327.995002307,-58.3471659896,327.995125925,-58.3471028456,327.994878689,-58.3472291335
+B1981.05,138.185539617,11.9337947187,138.185462216,11.9338143115,138.185617017,11.9337751259
+B1950.06,113.578525223,29.6301583121,113.578418602,29.6301753387,113.578631843,29.6301412853
+B1980.14,204.621895006,36.5235009134,204.621922605,36.5235622135,204.621867408,36.5234396134
+B1952.01,67.6144926088,-13.7094836718,67.6144111325,-13.7094635522,67.6145740851,-13.7095037914
+B1979.29,45.3029557779,36.4639084123,45.30288945,36.4638681314,45.3030221059,36.4639486932
+B1972.42,247.534489816,-3.23349952461,247.534569024,-3.23349456661,247.534410608,-3.2335044826
+B1967.69,287.858418461,26.2825631559,287.858523588,26.2825653277,287.858313334,26.2825609839
+B1996.68,206.473163472,-38.4312130715,206.473195575,-38.4312637479,206.473131368,-38.4311623951
+B1963.36,350.362793376,-7.51631961926,350.36282729,-7.51630014511,350.362759462,-7.51633909343
+B1964.06,228.259575769,40.311002157,228.259650941,40.3110571481,228.259500598,40.3109471658
+B1975.25,319.831820932,40.7337792676,319.831918659,40.7337465323,319.831723205,40.7338120029
+B1982.34,178.349313153,-38.3854710615,178.349286408,-38.3855223276,178.349339897,-38.3854197955
+B1998.53,126.58195076,-73.6980337652,126.581645487,-73.6980707198,126.582256033,-73.6979968102
+B1951.79,257.122932676,24.0154376566,257.123027615,24.0154606049,257.122837737,24.0154147083
+B1971.16,181.414481921,-17.7858263698,181.414465135,-17.7858473968,181.414498707,-17.7858053429
+B1979.42,81.2295383474,-9.26450146427,81.2294479067,-9.26448844016,81.2296287882,-9.26451448837
+B1986.59,88.1907984871,32.4238226453,88.1906888861,32.4238179627,88.1909080881,32.4238273279
+B1958.78,285.408252018,67.7826509035,285.408502334,67.7826473151,285.408001701,67.7826544915
+B1975.53,178.262069224,51.7327600597,178.262035148,51.7328376286,178.2621033,51.7326824908
+B1975.01,329.433722424,-46.8960749035,329.433814783,-46.8960177216,329.433630065,-46.8961320854
+B1994.64,340.333860195,36.5560891832,340.333920655,36.5560469817,340.333799735,36.5561313847
+B1969.13,191.963602676,21.3572019706,191.963604196,21.3572439205,191.963601156,21.3571600208
+B1983.14,90.8973340407,3.44588414281,90.897240458,3.44589104844,90.8974276234,3.44587723717
+B1952.34,259.510340943,47.0512387915,259.51047047,47.0512697696,259.510211416,47.0512078131
+B1987.56,132.277954966,30.4307232942,132.277860775,30.4307550149,132.278049157,30.4306915735
+B1968.44,179.513439448,-54.44865752,179.513406635,-54.4487285563,179.513472261,-54.4485864837
+B1997.40,81.5670170865,-19.9451944488,81.5669219294,-19.9451761627,81.5671122436,-19.9452127349
+B1967.36,127.283632829,-10.0946390302,127.283546305,-10.0946385601,127.283719352,-10.0946395003
+B1984.19,234.306643184,-86.4404274379,234.307689689,-86.4404960056,234.305596721,-86.440358869
+B1991.23,112.65584231,11.2521500479,112.655747491,11.2521615342,112.655937129,11.2521385617
+B1974.31,276.744760981,21.4151577082,276.744862642,21.4151677292,276.74465932,21.4151476871
+B1999.21,281.461357214,-15.511897988,281.461455717,-15.5118901893,281.46125871,-15.5119057865
+B1980.19,306.867413859,-11.9467360888,306.867501237,-11.9467197906,306.86732648,-11.946752387
+B1987.98,341.966066455,-2.82477813631,341.966112735,-2.82476612903,341.966020175,-2.82479014361
+B1984.23,38.6362483924,9.3322810896,38.6362039361,9.33227526676,38.6362928487,9.33228691243
+B1996.62,327.861128148,-46.529254733,327.861222674,-46.5291991016,327.86103362,-46.5293103644
+B1997.49,120.979858288,87.22617179,120.978013685,87.226204397,120.981702849,87.2261391801
+B1999.51,297.496953653,0.839666332936,297.497044724,0.83967387104,297.496862583,0.839658794827
+B1956.31,323.316228643,-0.794522598791,323.316298957,-0.794513783928,323.316158329,-0.794531413663
+B1998.83,15.3775095611,-38.7740290611,15.3775004994,-38.7739636006,15.3775186228,-38.7740945216
+B1961.46,70.486199672,-24.0682131367,70.4861102148,-24.0681861769,70.4862891293,-24.0682400965
+B1959.30,106.020475905,36.6574903487,106.020358021,36.6575015631,106.020593788,36.6574791342
+B1975.46,225.719957006,-24.2326924255,225.720016128,-24.2327172566,225.719897883,-24.2326675945
+B1976.52,31.0403178442,23.2187819108,31.040282636,23.2187540208,31.0403530525,23.2188098008
+B1964.13,51.4602071324,-27.0058546166,51.4601381551,-27.0058147039,51.4602761098,-27.0058945294
+B1965.51,185.697546923,55.594260797,185.697531081,55.5943432416,185.697562765,55.5941783525
+B1965.49,248.162878677,-23.7609450888,248.162965707,-23.7609586287,248.162791647,-23.7609315488
+B1963.32,308.385291884,51.2349043028,308.385426622,51.2348753519,308.385157147,51.2349332534
+B1979.67,233.050205996,63.3093356498,233.050347232,63.3094022915,233.05006476,63.3092690079
+B1960.86,209.382723191,-41.4659129842,209.382762908,-41.4659667228,209.382683474,-41.4658592457
+B1970.12,256.001743835,-16.3448051664,256.001833404,-16.3448088895,256.001654267,-16.3448014432
+B1964.43,90.8700685367,21.3678694408,90.8699682366,21.3678706796,90.8701688369,21.3678682019
+B1958.69,324.057486054,57.4352750563,324.057615131,57.4352248218,324.057356976,57.4353252907
+B1961.29,159.225729446,-45.2472278228,159.225658238,-45.2472794744,159.225800655,-45.2471761712
+B1999.43,7.38749687642,-53.1540997613,7.38750715011,-53.1540192078,7.38748660267,-53.1541803148
+B1971.70,345.477965039,-10.1831007688,345.478006755,-10.1830778328,345.477923323,-10.1831237048
+B1991.41,234.801152081,71.8511934075,234.80136258,71.8512610944,234.800941584,71.8511257203
+B1978.63,184.754250038,-66.4894904918,184.754223702,-66.4895738307,184.754276373,-66.4894071529
+B1982.60,245.64829793,-38.7682176459,245.648397087,-38.7682459424,245.648198773,-38.7681893494
+B1986.49,176.234540627,12.5643501076,176.234515663,12.564377805,176.23456559,12.5643224102
+B1969.56,333.536461653,-55.645568776,333.536564215,-55.6455021935,333.53635909,-55.6456353585
+B1969.64,185.716717981,-21.5568171888,185.71670839,-21.5568445326,185.716727571,-21.556789845
+B1992.98,25.9775574253,12.7249831044,25.9775324561,12.7249706335,25.9775823945,12.7249955753
+B1990.50,204.302987352,-36.6989586206,204.303014372,-36.6990074874,204.302960331,-36.6989097538
+B1991.83,221.487546141,22.5689795999,221.487598122,22.569018351,221.487494159,22.5689408487
+B1959.40,338.956666009,-30.7135370512,338.956724763,-30.7134891887,338.956607255,-30.7135849138
+B1967.98,149.5308077,21.1458572723,149.530740161,21.1458902834,149.530875238,21.1458242612
+B1974.10,95.1983908472,-1.61163007915,95.1982963974,-1.61162187599,95.198485297,-1.6116382823
+B1998.30,35.0615395317,-28.6207880841,35.0614956333,-28.620739571,35.0615834301,-28.6208365972
+B1978.17,174.903919876,-25.7547140538,174.903890465,-25.754746515,174.903949287,-25.7546815927
+B1991.38,167.27863063,54.1842744725,167.278565096,54.1843495205,167.278696164,54.1841994246
+B1953.81,10.7133541168,-26.6356033619,10.7133548501,-26.6355537205,10.7133533835,-26.6356530033
+B1977.66,249.939886269,43.0233288254,249.939997359,43.0233681421,249.939775179,43.0232895085
+B1977.40,258.100960451,-37.3838036503,258.101070404,-37.3838198729,258.1008505,-37.3837874275
+B1995.27,262.732112385,-19.8057986634,262.732208125,-19.8058013404,262.732016645,-19.8057959863
+B1968.47,149.166366188,63.2857703333,149.166225063,63.2858369635,149.166507312,63.2857037031
+B1995.06,5.4355841259,0.695799807062,5.43559350993,0.695806590879,5.43557474185,0.695793023234
+B1957.03,327.231056694,-11.1377396332,327.231123747,-11.137718635,327.230989642,-11.1377606314
+B1954.96,284.17633852,-71.0631656787,284.17663058,-71.0631583005,284.176046459,-71.0631730565
+B1998.66,59.4717008987,14.0960045791,59.4716277587,14.0959969126,59.4717740389,14.0960122456
+B1997.10,112.602946077,-17.7763932222,112.6028484,-17.7763914439,112.603043755,-17.7763950006
+B1979.55,219.940310095,-26.5130440909,219.940361247,-26.5130741126,219.940258944,-26.5130140693
+B1952.60,131.216503219,-60.6790709392,131.216335542,-60.6791085681,131.216670895,-60.6790333101
+B1952.51,56.1738921125,-19.3427782341,56.1738209005,-19.3427485454,56.1739633247,-19.3428079229
+B1966.23,63.8293728328,-59.8347944156,63.8292225342,-59.8347407237,63.829523132,-59.8348481073
+B1968.79,312.440281577,-82.909075449,312.440938353,-82.9090254915,312.439624792,-82.9091254056
+B1988.21,104.43408064,-66.6447299251,104.433841614,-66.6447318349,104.434319666,-66.644728015
+B1992.96,210.664663673,-17.5831928536,210.664697001,-17.5832123123,210.664630345,-17.5831733949
+B1977.29,163.438155327,-54.6954182678,163.438079056,-54.6954822858,163.438231598,-54.6953542498
+B1966.19,148.024127582,2.32865180198,148.024062692,2.32866254348,148.024192472,2.32864106049
+B1970.29,317.748400264,-34.6457182874,317.748492841,-34.6456795601,317.748307686,-34.6457570147
+B1955.48,249.374885326,79.5246095403,249.375329338,79.5246600743,249.374441319,79.5245590057
+B1956.86,100.53840787,-27.7507223648,100.538300623,-27.7507149055,100.538515118,-27.750729824
+B1987.27,23.1984832267,21.1208388177,23.1984619158,21.1208127728,23.1985045377,21.1208648626
+B1993.82,71.5045009532,3.00896662959,71.504418313,3.00897208869,71.5045835934,3.00896117048
+B1962.95,335.405788093,-6.90098238794,335.40584389,-6.90096525284,335.405732296,-6.90099952305
+B1984.28,307.588884401,18.8511389183,307.588974176,18.8511327496,307.588794626,18.851145087
+B1967.96,343.704504442,-46.9224252956,343.704568407,-46.9223583286,343.704440477,-46.9224922627
+B1950.30,18.8112053675,35.1485289159,18.8111898096,35.1484812505,18.8112209256,35.1485765813
+B1988.06,208.609805013,-46.3894275721,208.609846395,-46.3894876445,208.609763631,-46.3893674997
+B1970.70,172.978655994,15.4172636989,172.978625355,15.4172953255,172.978686632,15.4172320724
+B1966.69,7.8152324312,-34.9365736294,7.81523908357,-34.936512861,7.81522577882,-34.9366343978
+B1963.90,134.503366944,-72.4111269318,134.503104699,-72.4111743348,134.503629189,-72.4110795286
+B1979.63,149.073048424,14.7065160273,149.072982715,14.7065415958,149.073114132,14.7064904588
+B1966.26,217.406604209,16.5186514295,217.406648071,16.518683228,217.406560347,16.518619631
+B1996.84,241.829541848,16.5114334946,241.82961848,16.5114581776,241.829465216,16.5114088117
+B1954.80,301.991652158,46.8228690265,301.991781762,46.8228497806,301.991522554,46.8228882722
+B1994.16,280.629434995,-19.0017596678,280.629535379,-19.0017524272,280.629334611,-19.0017669083
+B1978.40,144.252375855,-10.2581330338,144.252305474,-10.258136788,144.252446236,-10.2581292796
+B1953.10,286.0305233,12.7464714044,286.030620257,12.7464773437,286.030426344,12.7464654651
+B1993.75,321.524751743,61.8464645226,321.524904902,61.8464140081,321.524598583,61.846515037
+B1961.24,94.4962887092,-44.0946278203,94.4961574273,-44.0946145181,94.4964199912,-44.0946411224
+B1989.97,356.110922656,-39.1892569317,356.110954348,-39.1891928509,356.110890964,-39.1893210125
+B1990.09,307.190555646,-43.7191034979,307.190673602,-43.7190689248,307.190437689,-43.719138071
+B1951.45,263.331776174,25.1917278571,263.331876059,25.1917473693,263.331676289,25.1917083448
+B1981.35,128.003624894,58.8666544649,128.003461169,58.8666953172,128.003788619,58.8666136124
+B1980.23,317.984216655,-8.89508525523,317.984293507,-8.89506861216,317.984139802,-8.8951018983
+B1953.91,312.465272698,5.18400310772,312.465354085,5.18400654399,312.465191311,5.18399967144
+B1988.65,344.0759205,-20.8070551085,344.07596665,-20.8070176615,344.07587435,-20.8070925556
+B1957.17,0.0386123471053,-42.7336081023,0.0386371599928,-42.7335390653,0.0385875341353,-42.7336771394
+B1973.18,5.95477509083,23.9728714179,5.95478442291,23.9728402559,5.95476575873,23.97290258
+B1954.86,113.065220613,27.4191705733,113.065116003,27.4191866686,113.065325223,27.4191544779
+B1978.49,358.313822853,67.0446512684,358.313876751,67.0445691316,358.313768955,67.0447334052
+B1970.19,53.5839203362,-15.011852649,53.5838539771,-15.0118268548,53.5839866953,-15.0118784432
+B1979.33,60.2557627351,25.6833225299,60.2556830704,25.6833027692,60.2558423998,25.6833422906
+B1987.44,273.08593329,76.4393919681,273.086334137,76.439406706,273.085532444,76.4393772296
+B1994.48,25.0306798156,-51.1202356021,25.0306434336,-51.1201589045,25.0307161977,-51.1203122997
+B1968.97,253.970437895,31.094899255,253.970536535,31.0949284071,253.970339254,31.0948701027
+B1964.62,168.89950144,-43.2270950714,168.899452201,-43.2271494771,168.89955068,-43.2270406658
+B1975.46,3.66775780511,39.2622225734,3.66777368182,39.26216915,3.66774192836,39.2622759968
+B1976.64,278.936590632,6.21231840756,278.936686041,6.21232668172,278.936495223,6.21231013337
+B1955.27,285.91236301,9.40548699672,285.912458882,9.40549352262,285.912267137,9.40548047079
+B1952.30,53.8450026285,60.7259893436,53.8448709018,60.7259324097,53.8451343557,60.7260462774
+B1981.10,8.53330744443,-7.54498028811,8.5333117472,-7.54495997493,8.53330314165,-7.54500060131
+B1991.12,274.342957522,-1.24603088049,274.3430518,-1.24602319414,274.342863244,-1.24603856684
+B1952.75,80.5212647616,19.4060625392,80.5211705543,19.4060589302,80.521358969,19.4060661482
+B1989.90,94.3827831954,15.0883386826,94.382685566,15.0883434466,94.3828808249,15.0883339185
+B1962.21,164.473020999,-47.6965440186,164.472957775,-47.69660143,164.473084223,-47.6964866073
+B1990.18,89.9736906625,-16.9964263489,89.973593279,-16.9964134056,89.9737880461,-16.9964392923
+B1964.91,204.582082173,15.6789515837,204.582105142,15.678984165,204.582059203,15.6789190023
diff --git a/astropy/coordinates/tests/accuracy/fk4_no_e_fk5.csv b/astropy/coordinates/tests/accuracy/fk4_no_e_fk5.csv
new file mode 100644
index 0000000..99102a4
--- /dev/null
+++ b/astropy/coordinates/tests/accuracy/fk4_no_e_fk5.csv
@@ -0,0 +1,202 @@
+# This file was generated with the ref_fk4_no_e_fk5.py script, and the reference values were computed using AST
+equinox_fk4,equinox_fk5,obstime,ra_in,dec_in,ra_fk5,dec_fk5,ra_fk4,dec_fk4
+B1948.36,J1992.59,B1995.95,334.661793414,43.9385116594,335.127505587,44.1614743713,334.19703321,43.7164045503
+B1971.64,J2006.23,B1954.56,113.895199649,-14.1109832563,114.294239451,-14.189617335,113.496041526,-14.0335757922
+B1970.49,J2015.57,B1953.55,66.2107722038,-7.76265420193,66.7573654302,-7.66250556575,65.6644607308,-7.86499337709
+B1931.50,J1999.69,B1970.69,73.6417002791,41.7006137481,74.8414427945,41.8037189279,72.4451689528,41.5898910005
+B1951.47,J1977.66,B1960.78,204.381010469,-14.9357743223,204.732916483,-15.0684119497,204.02947143,-14.8027671534
+B1955.96,J1999.16,B1975.98,214.396093073,-66.7648451487,215.271219746,-66.9622610907,213.531009752,-66.5653657951
+B1956.23,J2000.23,B1977.93,347.225227105,6.27744217753,347.783144277,6.51660389395,346.667337259,6.03880786927
+B1957.34,J1996.85,B1973.69,235.143754874,-5.59566003897,235.668034446,-5.72055011897,234.619987804,-5.46911905342
+B1941.60,J1993.80,B1960.79,269.606389512,26.7823112195,270.128504362,26.7816404236,269.084278188,26.7856304113
+B1930.71,J2013.89,B1961.97,235.285153507,-14.0695156888,236.447792421,-14.3293747521,234.125715822,-13.8019427393
+B1953.56,J1980.00,B1960.84,269.177331338,42.9472695107,269.379190001,42.9454157845,268.975475883,42.9496418506
+B1940.10,J1975.82,B1982.78,346.070424986,-3.51848810713,346.530942755,-3.32528640922,345.609649936,-3.71130492658
+B1934.68,J2014.12,B1992.32,3.01978725896,7.19732176646,4.04111300197,7.63872974164,1.9996375316,6.75549866988
+B1953.24,J2017.66,B1996.52,38.3199756112,18.8080489808,39.2225541698,19.0876452406,37.4201227465,18.5249551135
+B1955.52,J1986.19,B1990.02,107.533336957,-4.33088623215,107.914038138,-4.38286340945,107.152514675,-4.27999097547
+B1927.27,J2006.35,B1984.04,236.30802591,14.3162535375,237.227969566,14.0749779959,235.388744829,14.5634084162
+B1974.27,J1978.23,B1960.36,291.532518915,-33.7960784017,291.597238932,-33.7879646382,291.467788569,-33.8041689728
+B1930.19,J1986.95,B1987.08,313.983328941,27.7572327639,314.590894151,27.9778790422,313.375876285,27.5389973059
+B1945.29,J1997.99,B1984.85,347.273135054,-13.6880685538,347.963547495,-13.4015008868,346.58154003,-13.9738567052
+B1958.28,J2008.13,B1969.09,260.526724891,-37.6134342267,261.376886242,-37.6570793786,259.677433211,-37.5657291394
+B1934.85,J1985.89,B1992.51,231.291118043,-27.2371455509,232.060225806,-27.4133463836,230.524106155,-27.0579724511
+B1937.09,J1998.50,B1976.41,258.283303492,-30.1025933842,259.264766067,-30.1691519653,257.303071837,-30.0303039078
+B1956.16,J2023.91,B1994.65,168.335642599,-44.084769302,169.131984863,-44.4546574256,167.543307692,-43.7159381708
+B1964.94,J2000.65,B1991.03,117.210483914,32.8708634152,117.781943773,32.7790791562,116.63804006,32.9608828232
+B1952.23,J1998.51,B1961.43,158.272058119,-29.286471988,158.811965795,-29.5262894831,157.73289082,-29.0475527364
+B1934.88,J2008.31,B1991.03,262.688069789,-48.1516431413,264.082620089,-48.1987316304,261.295758898,-48.0946938009
+B1964.21,J2001.06,B1956.93,357.845250924,19.2890677934,358.315118415,19.4941375001,357.375940593,19.084061288
+B1965.72,J1987.86,B1974.12,243.674536239,-10.0431678136,243.97803572,-10.097540261,243.371196745,-9.98821027624
+B1960.54,J2016.21,B1957.44,284.696106425,19.6051067047,285.302622767,19.6853290904,284.089422958,19.5280584762
+B1972.20,J1981.44,B1972.41,61.5291328053,18.6403709997,61.6630317661,18.6648463372,61.3952747433,18.6157899771
+B1967.75,J1983.60,B1983.30,9.66573928438,-22.9075078717,9.8627174508,-22.8205464878,9.46866122286,-22.9945202022
+B1973.18,J1983.75,B1989.45,288.133287813,-36.6947385674,288.310596498,-36.676339325,287.955909092,-36.712964737
+B1948.23,J1994.10,B1983.10,325.340113758,-33.7758802174,326.023797476,-33.5649649991,324.65398011,-33.9850593768
+B1949.25,J1980.08,B1985.58,8.88343575454,-49.4693354042,9.24701151693,-49.2998476535,8.51878534341,-49.6389915796
+B1954.32,J1994.49,B1994.40,177.029034641,-67.7755279684,177.517646511,-67.9988963388,176.544747657,-67.552257953
+B1972.10,J2015.50,B1957.08,189.451860246,-68.7071945134,190.114123213,-68.9453284555,188.797874924,-68.4686046268
+B1943.61,J1992.69,B1957.38,214.691763751,-32.6160600699,215.421492998,-32.8397553215,213.964722034,-32.3903875087
+B1954.91,J2018.83,B1966.30,18.7047162369,-32.9080620608,19.4489945613,-32.5717365496,17.9585532678,-33.2458719202
+B1955.68,J2022.94,B1951.59,322.232230099,14.4669345738,323.034821026,14.7645630389,321.42944541,14.1725191869
+B1953.00,J2016.94,B1984.39,262.175824918,51.7319974933,262.548281917,51.6846881399,261.803746337,51.7815981232
+B1930.93,J1980.75,B1988.24,294.6060041,34.0181871087,295.074015891,34.1347005761,294.137889278,33.9037336792
+B1945.15,J2003.12,B1967.50,180.08019102,26.2892216009,180.821706382,25.9664807149,179.336612509,26.6119683301
+B1936.07,J1980.42,B1980.80,291.668187169,-22.2789167174,292.329992922,-22.1864262743,291.005523355,-22.3687549985
+B1964.41,J2018.79,B1997.92,34.548669268,-15.8924906144,35.1967101241,-15.6441308582,33.9006331013,-16.1427921034
+B1963.20,J1992.50,B1964.55,78.8220157436,-37.4332268082,79.075079173,-37.4019554736,78.5689855058,-37.465204993
+B1933.72,J2019.89,B1984.33,93.1388621771,60.5731416456,95.0905202877,60.5387165097,91.184708092,60.591240446
+B1961.19,J1981.21,B1952.11,168.518071423,7.09229333513,168.777442158,6.98298378221,168.258596163,7.20150240716
+B1971.23,J2006.89,B1953.13,165.374352937,39.3890686842,165.87176885,39.196720756,164.875283704,39.5809806285
+B1948.80,J2018.63,B1990.72,255.423520875,-17.5881075751,256.438156117,-17.6826060848,254.410141307,-17.4869506738
+B1970.65,J1975.05,B1971.83,64.0990821181,36.8289797648,64.172215273,36.8396700703,64.0259656206,36.8182613277
+B1946.87,J1990.24,B1969.60,191.321958369,-52.3532066605,191.941068845,-52.5897148324,190.706679307,-52.1161877868
+B1928.29,J1976.44,B1966.53,60.3872023631,25.1025882655,61.1139601332,25.2335783606,59.6618880776,24.9686447968
+B1943.19,J2002.49,B1972.88,276.773010626,56.6051138031,277.035261703,56.6448029825,276.510294672,56.5669265636
+B1934.47,J1983.76,B1991.77,334.141397682,37.3852087993,334.681936673,37.63269657,333.601820309,37.1388490904
+B1932.42,J2004.50,B1973.34,219.417716878,-20.2290328911,220.436864842,-20.53677356,218.402163145,-19.9167676954
+B1935.55,J1975.26,B1971.06,54.0660580808,-29.3264933861,54.4742787759,-29.1973856015,53.6578513784,-29.4568765774
+B1968.98,J1989.10,B1978.54,176.26561333,-0.572718169429,176.523526883,-0.684515911301,176.007690571,-0.460953265257
+B1965.89,J2012.99,B1986.95,135.84418338,-9.94938261687,136.4156383,-10.1384151142,135.27243952,-9.76217234374
+B1956.58,J2018.60,B1952.75,305.496508312,-8.63421746611,306.333192119,-8.43166153129,304.658373119,-8.83266452583
+B1972.76,J2000.27,B1981.21,327.995002307,-58.3471659896,328.478135531,-58.216943679,327.509419894,-58.4767020929
+B1930.95,J1999.19,B1981.05,138.185539617,11.9337947187,139.11218066,11.6486009656,137.256622001,12.2148869077
+B1955.11,J1977.39,B1950.06,113.578525223,29.6301583121,113.928637253,29.5801804457,113.228110262,29.6794410184
+B1941.57,J2012.54,B1980.14,204.621895006,36.5235009134,205.408269314,36.1654570594,203.833462777,36.8838069508
+B1966.08,J2016.57,B1952.01,67.6144926088,-13.7094836718,68.1982560465,-13.6037505529,67.030977723,-13.8178646409
+B1957.99,J2018.30,B1979.29,45.3029557779,36.4639084123,46.2543764288,36.6980750272,44.3559469687,36.2257877401
+B1946.13,J2016.34,B1972.42,247.534489816,-3.23349952461,248.455025871,-3.37995755876,246.615033795,-3.08124145001
+B1960.80,J1999.98,B1967.69,287.858418461,26.2825631559,288.257968726,26.350185895,287.458797059,26.2163884515
+B1935.76,J1975.44,B1996.68,206.473163472,-38.4312130715,207.060791642,-38.6284341117,205.887695173,-38.2329839969
+B1925.84,J1992.06,B1963.36,350.362793376,-7.51631961926,351.218703416,-7.15237789524,349.505768066,-7.87933870474
+B1939.04,J2012.01,B1964.06,228.259575769,40.311002157,228.937164323,40.0423286476,227.581733934,40.5832613094
+B1955.09,J2020.54,B1975.25,319.831820932,40.7337792676,320.468436705,41.0135236496,319.195878847,40.4566449257
+B1948.03,J1989.70,B1982.34,178.349313153,-38.3854710615,178.878815281,-38.6173901794,177.821462042,-38.1536135802
+B1960.53,J1984.34,B1998.53,126.58195076,-73.6980337652,126.522212859,-73.7769656974,126.639550025,-73.6189928568
+B1933.23,J2019.21,B1951.79,257.122932676,24.0154376566,258.016684748,23.9123993004,256.229480593,24.1257542269
+B1972.01,J1994.20,B1971.16,181.414481921,-17.7858263698,181.700080407,-17.9093349916,181.129088126,-17.6623025404
+B1972.77,J2005.85,B1979.42,81.2295383474,-9.26450146427,81.6239207678,-9.2370487074,80.8352159785,-9.29320699924
+B1974.04,J2004.85,B1986.59,88.1907984871,32.4238226453,88.6946934578,32.4284817102,87.6869564835,32.4176559135
+B1927.94,J1991.17,B1958.78,285.408252018,67.7826509035,285.385328422,67.8761253941,285.427216468,67.6890523656
+B1962.02,J2007.00,B1975.53,178.262069224,51.7327600597,178.846486725,51.48241739,177.67431932,51.983025032
+B1955.03,J1997.43,B1975.01,329.433722424,-46.8960749035,330.103614247,-46.692118107,328.760372892,-47.0986245326
+B1929.45,J2009.92,B1994.64,340.333860195,36.5560891832,341.254677798,36.9791399195,339.41634063,36.1354568961
+B1974.47,J1983.10,B1969.13,191.963602676,21.3572019706,192.070505327,21.3101918576,191.856675141,21.4042306751
+B1952.44,J1984.77,B1983.14,90.8973340407,3.44588414281,91.3225022889,3.4423974082,90.4721556483,3.44803542582
+B1958.72,J1999.14,B1952.34,259.510340943,47.0512387915,259.790647567,47.0108077311,259.230159931,47.0927522883
+B1961.24,J2000.00,B1987.56,132.277954966,30.4307232942,132.867785214,30.2847386621,131.686701777,30.5750623541
+B1953.42,J2013.40,B1968.44,179.513439448,-54.44865752,180.28117417,-54.7825927917,178.751891964,-54.1147599287
+B1951.37,J1984.64,B1997.40,81.5670170865,-19.9451944488,81.9269374609,-19.9186092791,81.2071330825,-19.9729303814
+B1932.54,J2024.61,B1967.36,127.283632829,-10.0946390302,128.389991343,-10.4090695278,126.176062442,-9.78808786127
+B1937.01,J1991.26,B1984.19,234.306643184,-86.4404274379,239.159196268,-86.6062091923,229.877779523,-86.2547679857
+B1945.13,J2017.30,B1991.23,112.65584231,11.2521500479,113.653522343,11.0941650144,111.656584771,11.4036739314
+B1928.39,J2015.91,B1974.31,276.744760981,21.4151577082,277.676112471,21.4763175641,275.813216777,21.3618641896
+B1962.92,J2020.33,B1999.21,281.461357214,-15.511897988,282.28369792,-15.4461443386,280.638389569,-15.573154518
+B1942.13,J2011.97,B1980.19,306.867413859,-11.9467360888,307.826980276,-11.7108610078,305.905696925,-12.1773958306
+B1974.49,J1990.83,B1987.98,341.966066455,-2.82477813631,342.177020368,-2.73822865168,341.755054209,-2.91122392552
+B1969.43,J1976.38,B1984.23,38.6362483924,9.3322810896,38.7295143004,9.36248136387,38.5430036498,9.30204150263
+B1971.93,J2003.15,B1996.62,327.861128148,-46.529254733,328.357950708,-46.3816911362,327.362455314,-46.6760151537
+B1961.96,J2022.83,B1997.49,120.979858288,87.22617179,127.356289341,87.0356348542,113.806804821,87.3823224486
+B1926.35,J1982.80,B1999.51,297.496953653,0.839666332936,298.215707802,0.986504246823,296.777520197,0.696326958488
+B1944.12,J2012.89,B1956.31,323.316228643,-0.794522598791,324.199877999,-0.485711290555,322.43128765,-1.09980368764
+B1925.53,J1977.07,B1998.83,15.3775095611,-38.7740290611,15.975820035,-38.4977806231,14.777479512,-39.0510731102
+B1928.26,J1984.73,B1961.46,70.486199672,-24.0682131367,71.0773386429,-23.9647188389,69.8952283629,-24.1747645717
+B1959.07,J2001.01,B1959.30,106.020475905,36.6574903487,106.724489447,36.5916635763,105.315480342,36.7205573317
+B1974.33,J1998.24,B1975.46,225.719957006,-24.2326924255,226.069642,-24.3253436846,225.370713094,-24.1394598386
+B1958.31,J2014.48,B1976.52,31.0403178442,23.2187819108,31.8305300515,23.4855979353,30.252581142,22.9497454125
+B1945.76,J1981.40,B1964.13,51.4602071324,-27.0058546166,51.8377992184,-26.8827293131,51.0826217069,-27.1300027947
+B1927.06,J2019.62,B1965.51,185.697546923,55.594260797,186.80220854,55.0820030044,184.579796584,56.1075102073
+B1969.71,J1983.82,B1965.49,248.162878677,-23.7609450888,248.376028149,-23.7900358626,247.949821476,-23.7315830399
+B1960.34,J1996.74,B1963.32,308.385291884,51.2349043028,308.653885549,51.3611262862,308.116543047,51.1094272568
+B1948.94,J1982.47,B1979.67,233.050205996,63.3093356498,233.183624905,63.1972984089,232.917717277,63.4217190672
+B1935.78,J2009.44,B1960.86,209.382723191,-41.4659129842,210.508471779,-41.8212717612,208.265390379,-41.1066153061
+B1929.09,J2015.70,B1970.12,256.001743835,-16.3448051664,257.249402003,-16.4563411788,254.755864037,-16.2230882626
+B1958.66,J1984.63,B1964.43,90.8700685367,21.3678694408,91.2595104175,21.3651813051,90.4806144234,21.369574816
+B1974.74,J2003.91,B1958.69,324.057486054,57.4352750563,324.282176393,57.5669676284,323.83284781,57.3039563174
+B1954.68,J2011.04,B1961.29,159.225729446,-45.2472278228,159.836674886,-45.541209348,158.616784774,-44.9544310498
+B1967.01,J1998.76,B1999.43,7.38749687642,-53.1540997613,7.76348958513,-52.978901243,7.01015979396,-53.3294476754
+B1932.65,J1988.10,B1971.70,345.477965039,-10.1831007688,346.201723123,-9.88376000525,344.753111544,-10.4814629211
+B1968.81,J2011.71,B1991.41,234.801152081,71.8511934075,234.75819291,71.7134587916,234.849277912,71.9887729277
+B1952.24,J1992.46,B1978.63,184.754250038,-66.4894904918,185.31507512,-66.7125454196,184.198875868,-66.2662547282
+B1974.18,J2008.57,B1982.60,245.64829793,-38.7682176459,246.229734859,-38.8462753796,245.067899116,-38.6883914108
+B1961.79,J1977.75,B1986.49,176.234540627,12.5643501076,176.440478946,12.4756870596,176.028521797,12.6529921788
+B1929.65,J2019.85,B1969.56,333.536461653,-55.645568776,335.008274077,-55.1931712959,332.042112951,-56.0921730529
+B1939.61,J2001.08,B1969.64,185.716717981,-21.5568171888,186.518819162,-21.8971031217,184.916731889,-21.2160545858
+B1938.65,J1988.76,B1992.98,25.9775574253,12.7249831044,26.6478047282,12.9750431145,25.30853404,12.4734949987
+B1928.56,J2017.18,B1990.50,204.302987352,-36.6989586206,205.594712571,-37.1462777072,203.0212666,-36.2470793085
+B1959.00,J1997.12,B1991.83,221.487546141,22.5689795999,221.917649745,22.4105410037,221.057403953,22.7284735519
+B1936.24,J2008.46,B1959.40,338.956666009,-30.7135370512,339.96511112,-30.3370017697,337.943007518,-31.0875245016
+B1952.57,J2024.63,B1967.98,149.5308077,21.1458572723,150.530972008,20.7983136142,148.526893227,21.4898432119
+B1963.49,J2017.63,B1974.10,95.1983908472,-1.61163007915,95.8836923542,-1.64073778617,94.5129553374,-1.58611303786
+B1935.59,J2021.68,B1998.30,35.0615395317,-28.6207880841,36.013756926,-28.230800891,34.108208406,-29.0153533631
+B1939.64,J2018.11,B1978.17,174.903919876,-25.7547140538,175.892230462,-26.1901662894,173.918861307,-25.3199298979
+B1942.82,J1978.35,B1991.38,167.27863063,54.1842744725,167.792865117,53.9911451576,166.761561647,54.3770117742
+B1972.82,J1989.59,B1953.81,10.7133541168,-26.6356033619,10.9196530538,-26.5438625332,10.5069242085,-26.7274067313
+B1958.01,J1984.82,B1977.66,249.939886269,43.0233288254,250.152708941,42.9723921243,249.727120549,43.0747862488
+B1972.53,J1995.55,B1977.40,258.100960451,-37.3838036503,258.492060536,-37.4098004846,257.710089764,-37.356950996
+B1929.84,J1995.96,B1995.27,262.732112385,-19.8057986634,263.710992923,-19.8492450608,261.753853467,-19.7561160195
+B1938.23,J2022.91,B1968.47,149.166366188,63.2857703333,150.716387336,62.8777259431,147.585925919,63.6872128631
+B1938.61,J2021.20,B1995.06,5.4355841259,0.695799807062,6.49453219621,1.15308515723,4.37708671511,0.237709638907
+B1966.75,J2024.18,B1957.03,327.231056694,-11.1377396332,328.000338248,-10.8677167475,326.460220195,-11.4054365616
+B1965.64,J1994.07,B1954.96,284.17633852,-71.0631656787,284.986812185,-71.023307137,283.363277683,-71.1008495735
+B1939.69,J2023.20,B1998.66,59.4717008987,14.0960045791,60.6437035945,14.328043327,58.3026637155,13.8557849823
+B1957.49,J2004.52,B1997.10,112.602946077,-17.7763932222,113.128066437,-17.8781256601,112.077653347,-17.6768763275
+B1946.05,J2000.05,B1979.55,219.940310095,-26.5130440909,220.729784133,-26.7422090278,219.153387495,-26.2812240409
+B1928.73,J1989.10,B1952.60,131.216503219,-60.6790709392,131.538762739,-60.9012667241,130.892392069,-60.458301418
+B1961.94,J1983.12,B1952.51,56.1738921125,-19.3427782341,56.4110363048,-19.277323069,55.9367786527,-19.4086389221
+B1954.27,J1997.44,B1966.23,63.8293728328,-59.8347944156,64.0119166618,-59.729130492,63.6478301692,-59.9411437379
+B1942.23,J1992.36,B1968.79,312.440281577,-82.909075449,314.686445788,-82.716709549,310.089004633,-83.0931764134
+B1937.90,J2001.19,B1988.21,104.43408064,-66.6447299251,104.453108425,-66.7326176146,104.411797906,-66.5569652662
+B1939.59,J2002.19,B1992.96,210.664663673,-17.5831928536,211.524274634,-17.8816169868,209.807499075,-17.2821058793
+B1963.49,J1975.54,B1977.29,163.438155327,-54.6954182678,163.565812054,-54.7597430346,163.310636547,-54.6311360803
+B1946.22,J1989.83,B1966.19,148.024127582,2.32865180198,148.587881848,2.12205454824,147.4598279,2.53398329697
+B1939.43,J1983.41,B1970.29,317.748400264,-34.6457182874,318.424549161,-34.4635023474,317.070001399,-34.8259880426
+B1938.21,J2022.93,B1955.48,249.374885326,79.5246095403,248.102397286,79.3535339601,250.706479605,79.6856520522
+B1938.85,J1986.82,B1956.86,100.53840787,-27.7507223648,101.014813183,-27.8006647295,100.061930435,-27.7029635357
+B1967.12,J2016.63,B1987.27,23.1984832267,21.1208388177,23.8758085173,21.373531354,22.5228650317,20.8668643466
+B1933.48,J2010.39,B1993.82,71.5045009532,3.00896662959,72.5117326573,3.14121771682,70.4983597655,2.86958134305
+B1937.60,J2003.03,B1962.95,335.405788093,-6.90098238794,336.26168125,-6.56861752396,334.548406282,-7.23108048852
+B1954.59,J2010.06,B1984.28,307.588884401,18.8511389183,308.216046805,19.0408491208,306.961527852,18.6641076356
+B1973.77,J1985.60,B1967.96,343.704504442,-46.9224252956,343.875951545,-46.8591633148,343.532811099,-46.9856319247
+B1925.21,J2009.55,B1950.30,18.8112053675,35.1485289159,20.0024206727,35.5914321179,17.6282310843,34.702488267
+B1937.00,J2006.08,B1988.06,208.609805013,-46.3894275721,209.692670963,-46.7252945952,207.535889978,-46.0500943647
+B1961.33,J2010.87,B1970.70,172.978655994,15.4172636989,173.622309813,15.1433334088,172.333980129,15.6908149586
+B1937.54,J1982.63,B1966.69,7.8152324312,-34.9365736294,8.36836736742,-34.688026104,7.26063844242,-35.1854511343
+B1970.91,J1979.71,B1963.90,134.503366944,-72.4111269318,134.50595835,-72.4454843369,134.500551115,-72.3767711725
+B1950.41,J2022.56,B1979.63,149.073048424,14.7065160273,150.050293767,14.3602043524,148.092931537,15.0493015642
+B1950.13,J1995.20,B1966.26,217.406604209,16.5186514295,217.938935407,16.3200334608,216.874300735,16.7186856279
+B1960.62,J2007.17,B1996.84,241.829541848,16.5114334946,242.358489224,16.3901534117,241.300790354,16.6348221277
+B1956.99,J2023.02,B1954.80,301.991652158,46.8228690265,302.505263266,47.0190374374,301.477638783,46.6294966913
+B1939.22,J2016.87,B1994.16,280.629434995,-19.0017596678,281.769997009,-18.9177962123,279.487664877,-19.0772612574
+B1925.49,J1981.53,B1978.40,144.252375855,-10.2581330338,144.937158573,-10.5124362227,143.567309058,-10.006008783
+B1954.74,J2000.05,B1953.10,286.0305233,12.7464714044,286.556205108,12.8172544241,285.504676194,12.6779134146
+B1967.05,J1984.09,B1993.75,321.524751743,61.8464645226,321.632971919,61.9207781138,321.416450206,61.7722624353
+B1949.33,J1977.52,B1961.24,94.4962887092,-44.0946278203,94.7059415448,-44.1072194614,94.2866143528,-44.0826087841
+B1964.04,J2019.75,B1989.97,356.110922656,-39.1892569317,356.840327262,-38.8797072373,355.378110002,-39.4985381971
+B1945.63,J1988.30,B1990.09,307.190555646,-43.7191034979,307.916952389,-43.5743180165,306.461507156,-43.8614854707
+B1943.99,J1977.69,B1951.45,263.331776174,25.1917278571,263.675941152,25.1704984165,262.987636197,25.2140768109
+B1969.92,J1999.97,B1981.35,128.003624894,58.8666544649,128.605737687,58.7629529731,127.398829454,58.9689675244
+B1969.84,J2014.01,B1980.23,317.984216655,-8.89508525523,318.575678141,-8.71153679083,317.391922121,-9.07693345337
+B1961.02,J2002.85,B1953.91,312.465272698,5.18400310772,312.985580994,5.34203296971,311.944618588,5.02753402011
+B1939.24,J1981.75,B1988.65,344.0759205,-20.8070551085,344.644700272,-20.5791609914,343.505986239,-21.0343039973
+B1941.99,J1994.43,B1957.17,0.0386123471053,-42.7336081023,0.708747131881,-42.4416361362,359.365316955,-43.025582347
+B1939.26,J1987.88,B1973.18,5.95477509083,23.9728714179,6.5909526232,24.2419429246,5.32008332697,23.7034884386
+B1963.98,J2001.37,B1954.86,113.065220613,27.4191705733,113.643404238,27.3366368146,112.486263629,27.4997700815
+B1925.23,J2020.13,B1978.49,358.313822853,67.0446512684,359.505559565,67.5728883986,357.14681594,66.5167328688
+B1929.23,J2017.66,B1970.19,53.5839203362,-15.011852649,54.610957277,-14.7231509285,52.5576449921,-15.3076533827
+B1947.07,J2016.84,B1979.33,60.2557627351,25.6833225299,61.3134611254,25.8729083597,59.2011689172,25.4875201301
+B1937.55,J1985.79,B1987.44,273.08593329,76.4393919681,272.591344908,76.4526927726,273.578774594,76.4237802487
+B1970.29,J1981.68,B1994.48,25.0306798156,-51.1202356021,25.1435488988,-51.0628198065,24.9177386023,-51.177704254
+B1969.04,J1981.01,B1968.97,253.970437895,31.094899255,254.085382476,31.0765584395,253.855499113,31.1133685873
+B1960.83,J2018.73,B1964.62,168.89950144,-43.2270950714,169.584603614,-43.5437889415,168.217301809,-42.9111416391
+B1936.93,J1979.00,B1975.46,3.66775780511,39.2622225734,4.22000281563,39.4958903381,3.11745305971,39.0284106254
+B1971.26,J1994.47,B1976.64,278.936590632,6.21231840756,279.220262021,6.23271017522,278.652884808,6.19255870349
+B1973.48,J1984.09,B1955.27,285.91236301,9.40548699672,286.039106102,9.42175539099,285.785609343,9.38934433416
+B1953.91,J1995.56,B1952.30,53.8450026285,60.7259893436,54.7155379279,60.8613834632,52.9800334576,60.5877592411
+B1938.45,J2016.67,B1981.10,8.53330744443,-7.54498028811,9.52668790991,-7.1149113183,7.53943191911,-7.97616983921
+B1940.05,J2023.92,B1991.12,274.342957522,-1.24603088049,275.427502795,-1.20626637794,273.258110296,-1.27698166464
+B1956.27,J1975.21,B1952.75,80.5212647616,19.4060625392,80.8007537943,19.4231777982,80.2418410241,19.3884398656
+B1963.99,J2002.99,B1989.90,94.3827831954,15.0883386826,94.9409404907,15.0706908672,93.8245150675,15.1038774277
+B1946.06,J2012.59,B1962.21,164.473020999,-47.6965440186,165.218388831,-48.0540734375,163.731379108,-47.3403011601
+B1957.85,J1994.50,B1990.18,89.9736906625,-16.9964263489,90.3810379284,-16.9970588536,89.5663435591,-16.9972444015
+B1946.18,J1990.43,B1964.91,204.582082173,15.6789515837,205.12023156,15.4553934359,204.04377436,15.9034725087
diff --git a/astropy/coordinates/tests/accuracy/galactic_fk4.csv b/astropy/coordinates/tests/accuracy/galactic_fk4.csv
new file mode 100644
index 0000000..c3c8276
--- /dev/null
+++ b/astropy/coordinates/tests/accuracy/galactic_fk4.csv
@@ -0,0 +1,202 @@
+# This file was generated with the ref_galactic_fk4.py script, and the reference values were computed using AST
+equinox_fk4,obstime,lon_in,lat_in,ra_fk4,dec_fk4,lon_gal,lat_gal
+J1998.36,B1995.95,334.661793414,43.9385116594,215.729885213,-13.2119623291,95.9916336135,-10.7923599366
+J2021.64,B1954.56,113.895199649,-14.1109832563,0.0191713429163,47.9584946764,230.354307383,2.91031092906
+J2020.49,B1953.55,66.2107722038,-7.76265420193,307.0396671,25.0473933964,202.190459847,-36.2511029663
+J1981.50,B1970.69,73.6417002791,41.7006137481,249.552478408,47.490161693,163.738209835,-0.997514227815
+J2001.47,B1960.78,204.381010469,-14.9357743223,85.7262507794,0.592842446128,319.182343564,46.4865699629
+J2005.96,B1975.98,214.396093073,-66.7648451487,38.7974895634,-25.3131215325,311.259111645,-5.26093959516
+J2006.23,B1977.93,347.225227105,6.27744217753,251.681067557,-35.6975782982,82.4439145069,-48.3754431897
+J2007.34,B1973.69,235.143754874,-5.59566003897,108.194271484,-22.3032173532,0.622684927771,37.7376079889
+J1991.60,B1960.79,269.606389512,26.7823112195,159.265817549,-27.2400623832,52.4594618492,22.7351205489
+J1980.71,B1961.97,235.285153507,-14.0695156888,99.5923664647,-26.0329761781,353.421599279,31.5338685058
+J2003.56,B1960.84,269.177331338,42.9472695107,168.194363902,-13.373076419,69.4875812789,27.7142399301
+J1990.10,B1982.78,346.070424986,-3.51848810713,260.556249219,-42.5373980474,71.1723254841,-55.2318229113
+J1984.68,B1992.32,3.01978725896,7.19732176646,261.223075691,-22.5183053503,106.371052811,-54.3443814356
+J2003.24,B1996.52,38.3199756112,18.8080489808,268.244155911,13.0679884186,153.915977612,-37.8861321281
+J2005.52,B1990.02,107.533336957,-4.33088623215,345.276777715,55.2303472065,218.881057613,2.11460956182
+J1977.27,B1984.04,236.30802591,14.3162535375,126.558516177,-13.1859909524,24.4040838917,47.3681313134
+J2024.27,B1960.36,291.532518915,-33.7960784017,65.6262288958,-78.0827780664,4.70715132794,-21.1240080657
+J1980.19,B1987.08,313.983328941,27.7572327639,204.395115343,-33.9974383642,72.5499341116,-11.3261456428
+J1995.29,B1984.85,347.273135054,-13.6880685538,273.878542915,-46.5817989568,57.2967846205,-62.636282227
+J2008.28,B1969.09,260.526724891,-37.6134342267,75.5423582477,-53.0108213216,349.993949344,-0.500521761262
+J1984.85,B1992.51,231.291118043,-27.2371455509,84.3750724965,-27.2619452007,340.394703326,24.1136027935
+J1987.09,B1976.41,258.283303492,-30.1025933842,87.5349107922,-50.9413101937,355.216758932,5.09769033822
+J2006.16,B1994.65,168.335642599,-44.084769302,44.0040901708,7.58736494962,284.861051883,15.3412175718
+J2014.94,B1991.03,117.210483914,32.8708634152,231.950026475,82.367116716,187.3264088,25.4619880653
+J2002.23,B1961.43,158.272058119,-29.286471988,46.4761761399,24.2223508812,269.917276667,24.5785034911
+J1984.88,B1991.03,262.688069789,-48.1516431413,57.7755536872,-52.5013674166,342.226051771,-7.92146528355
+J2014.21,B1956.93,357.845250924,19.2890677934,248.037990583,-19.4340699812,103.672360905,-41.3775036599
+J2015.72,B1974.12,243.674536239,-10.0431678136,108.027253494,-31.863249456,2.91619105856,28.4959537625
+J2010.54,B1957.44,284.696106425,19.6051067047,170.340404941,-40.0951306839,51.2254926849,7.33605738412
+J2022.20,B1972.41,61.5291328053,18.6403709997,277.730191309,33.3416109651,174.063892959,-24.5412790814
+J2017.75,B1983.30,9.66573928438,-22.9075078717,295.17981175,-30.0450764744,85.3259571782,-84.8466105492
+J2023.18,B1989.45,288.133287813,-36.6947385674,61.7090085882,-74.1820684991,0.817296879039,-19.4797887996
+J1998.23,B1983.10,325.340113758,-33.7758802174,307.31206399,-69.6283338955,11.6623486171,-48.8815187305
+J1999.25,B1985.58,8.88343575454,-49.4693354042,325.965770063,-35.6133692502,309.666273629,-67.4551398942
+J2004.32,B1994.40,177.029034641,-67.7755279684,31.2372626731,-12.9650951893,296.955672515,-5.62000346764
+J2022.10,B1957.08,189.451860246,-68.7071945134,33.5293665419,-17.1203080138,301.559917262,-5.75405801934
+J1993.61,B1957.38,214.691763751,-32.6160600699,73.7224767298,-15.6028544376,323.538376206,26.6926709764
+J2004.91,B1966.30,18.7047162369,-32.9080620608,308.505564328,-25.5373410674,263.547066418,-82.3338996972
+J2005.68,B1951.59,322.232230099,14.4669345738,219.553504168,-44.4049264885,66.7343979667,-25.6090866517
+J2003.00,B1984.39,262.175824918,51.7319974933,169.003247618,-3.42937646572,78.8860186239,33.5626186817
+J1980.93,B1988.24,294.6060041,34.0181871087,184.771961476,-28.2403711462,68.3561968833,5.91397226579
+J1995.15,B1967.50,180.08019102,26.2892216009,115.670140935,39.4176352042,214.406973761,78.6105433559
+J1986.07,B1980.80,291.668187169,-22.2789167174,125.910652709,-78.6378819053,16.4272341834,-17.5632578893
+J2014.41,B1997.92,34.548669268,-15.8924906144,297.966081457,-5.74276095396,188.103833481,-67.1344687124
+J2013.20,B1964.55,78.8220157436,-37.4332268082,338.41386544,13.3803692475,241.413633182,-34.4957267196
+J1983.72,B1984.33,93.1388621771,60.5731416456,215.515242863,51.025917079,153.788670192,19.0304556569
+J2011.19,B1952.11,168.518071423,7.09229333513,86.7960140054,42.4095753728,249.125769518,59.3639239957
+J2021.23,B1953.13,165.374352937,39.3890686842,133.539016217,52.7585931969,177.607817121,63.8456065457
+J1998.80,B1990.72,255.423520875,-17.5881075751,104.861453622,-45.3027201728,3.92822669713,14.6469670383
+J2020.65,B1971.83,64.0990821181,36.8289797648,256.321772318,39.914355366,162.091739264,-10.1708006469
+J1996.87,B1969.60,191.321958369,-52.3532066605,47.9455555868,-9.26762335019,302.005131299,10.4906094438
+J1978.29,B1966.53,60.3872023631,25.1025882655,269.550425169,34.4047511633,168.612591713,-20.2821406332
+J1993.19,B1972.88,276.773010626,56.6051138031,178.703826596,-3.3434530167,85.5633134045,25.6194736799
+J1984.47,B1991.77,334.141397682,37.3852087993,218.479404766,-19.0772794069,91.968516951,-15.9701580762
+J1982.42,B1973.34,219.417716878,-20.2290328911,87.1109593231,-14.6004706289,334.420144542,35.926923956
+J1985.55,B1971.06,54.0660580808,-29.3264933861,318.139103598,3.17485146412,226.277308044,-53.6788644695
+J2018.98,B1978.54,176.26561333,-0.572718169429,83.8491889252,31.8061689325,269.795526718,58.0046040213
+J2015.89,B1986.95,135.84418338,-9.94938261687,33.531734841,50.9381624137,238.492810285,23.3637333893
+J2006.58,B1952.75,305.496508312,-8.63421746611,200.932667574,-71.3815196871,35.373262982,-23.9548001451
+J2022.76,B1981.21,327.995002307,-58.3471659896,350.834964718,-54.0901563813,335.114901978,-45.751212695
+J1980.95,B1981.05,138.185539617,11.9337947187,58.631520613,69.0711593141,218.447399995,36.9072609382
+J2005.11,B1950.06,113.578525223,29.6301583121,263.636462216,81.3987773508,189.681688921,21.6122927944
+J1991.57,B1980.14,204.621895006,36.5235009134,133.680798913,22.0411777739,78.808513096,76.2737160193
+J2016.08,B1952.01,67.6144926088,-13.7094836718,313.132620076,22.6386092017,209.654020089,-37.5533649541
+J2007.99,B1979.29,45.3029557779,36.4639084123,253.115407251,25.0961411128,150.086524604,-19.5316401959
+J1996.13,B1972.42,247.534489816,-3.23349952461,117.046928774,-32.0174103517,11.9107776158,29.166414441
+J2010.80,B1967.69,287.858418461,26.2825631559,176.528272624,-34.7137695077,58.5625336575,7.68664923227
+J1985.76,B1996.68,206.473163472,-38.4312130715,65.3730874222,-11.8626802001,314.662473159,23.1067145187
+J1975.84,B1963.36,350.362793376,-7.51631961926,267.890694432,-41.0314521815,72.0362114405,-61.1485139616
+J1989.04,B1964.06,228.259575769,40.311002157,144.950655363,6.68810736787,66.3208521242,57.9479583999
+J2005.09,B1975.25,319.831820932,40.7337792676,206.517019036,-20.3728721852,85.376518971,-6.19125657467
+J1998.03,B1982.34,178.349313153,-38.3854710615,53.3367731423,6.47139870346,290.627978018,23.0870158337
+J2010.53,B1998.53,126.58195076,-73.6980337652,14.0339286057,-10.7989965101,287.063023216,-19.6793830621
+J1983.23,B1951.79,257.122932676,24.0154376566,147.559357599,-22.3222385045,45.3959106575,32.4293515474
+J2022.01,B1971.16,181.414481921,-17.7858263698,71.6065443096,17.7205783522,287.370198984,43.7863289812
+J2022.77,B1979.42,81.2295383474,-9.26450146427,319.219354065,35.7151156735,211.413414641,-23.6522137945
+J2024.04,B1986.59,88.1907984871,32.4238226453,264.445366137,59.5075300274,177.63221018,2.82201785023
+J1977.94,B1958.78,285.408252018,67.7826509035,186.006666089,5.9317624038,98.5359798987,24.0369224888
+J2012.02,B1975.53,178.262069224,51.7327600597,149.616027267,42.1293667525,143.189803372,62.9449441105
+J2005.03,B1975.01,329.433722424,-46.8960749035,333.526505486,-61.2774858546,350.879342803,-50.7102611905
+J1979.45,B1994.64,340.333860195,36.5560891832,223.292370195,-17.1540759917,95.9213163317,-19.343112709
+J2024.47,B1969.13,191.963602676,21.3572019706,114.434412024,27.503830072,291.719299139,84.2576478027
+J2002.44,B1983.14,90.8973340407,3.44588414281,314.995461083,51.3170142615,204.308033362,-9.04466471803
+J2008.72,B1952.34,259.510340943,47.0512387915,164.869262172,-6.16993929742,73.122316095,35.0776892287
+J2011.24,B1987.56,132.277954966,30.4307232942,127.48825526,81.1338000052,193.90517209,37.3016929434
+J2003.42,B1968.44,179.513439448,-54.44865752,42.0526470828,-4.9188999851,295.12094312,7.62776271377
+J2001.37,B1997.40,81.5670170865,-19.9451944488,328.061837334,28.1928252216,222.515151909,-27.3578081826
+J1982.54,B1967.36,127.283632829,-10.0946390302,19.6477131913,52.4470778861,233.960957731,16.5452929993
+J1987.01,B1984.19,234.306643184,-86.4404274379,16.4715901103,-28.4445608636,305.546826719,-24.5135301459
+J1995.13,B1991.23,112.65584231,11.2521500479,339.527728916,71.3900724033,207.206370175,13.7939581949
+J1978.39,B1974.31,276.744760981,21.4151577082,162.407802968,-35.1255983687,49.8499233813,14.5681779743
+J2012.92,B1999.21,281.461357214,-15.511897988,128.74174115,-66.9721136327,18.3606180783,-5.64535469428
+J1992.13,B1980.19,306.867413859,-11.9467360888,207.123394118,-74.3365109128,32.8334594598,-26.7428218865
+J2024.49,B1987.98,341.966066455,-2.82477813631,257.079269135,-45.5062849208,66.5166383458,-51.5988768204
+J2019.43,B1984.23,38.6362483924,9.3322810896,277.298399175,9.29190831823,160.679381282,-46.0098367014
+J2021.93,B1996.62,327.861128148,-46.529254733,334.498175895,-62.285753657,351.779204131,-49.5514803605
+J2011.96,B1997.49,120.979858288,87.22617179,193.112689708,29.8355211732,125.900479598,27.8877168914
+J1976.35,B1999.51,297.496953653,0.839666332936,181.085417356,-61.4154773919,40.6846762696,-12.8402998175
+J1994.12,B1956.31,323.316228643,-0.794522598791,232.744583525,-57.172811607,53.4475657454,-35.7640525677
+J1975.53,B1998.83,15.3775095611,-38.7740290611,313.687711979,-29.7532661336,292.123823728,-78.249288242
+J1978.26,B1961.46,70.486199672,-24.0682131367,323.035235152,17.9223915313,223.250351558,-38.1828370964
+J2009.07,B1959.30,106.020475905,36.6574903487,244.972778375,72.7878865437,180.327652321,18.0468441903
+J2024.33,B1975.46,225.719957006,-24.2326924255,86.0366112823,-21.5082578389,337.38182103,29.8986234954
+J2008.31,B1976.52,31.0403178442,23.2187819108,261.302299942,8.78047554861,143.772447485,-36.7511639142
+J1995.76,B1964.13,51.4602071324,-27.0058546166,315.065766587,2.55796617517,221.775446591,-55.7242078312
+J1977.06,B1965.51,185.697546923,55.594260797,153.338541661,37.440299398,131.049487592,61.2247044105
+J2019.71,B1965.49,248.162878677,-23.7609450888,94.0591617121,-40.8224910786,354.392971779,16.4900856964
+J2010.34,B1963.32,308.385291884,51.2349043028,196.476156832,-11.5444983515,88.2071202318,6.64482242886
+J1998.94,B1979.67,233.050205996,63.3093356498,166.867510536,15.6637804493,98.5156204798,45.4612418027
+J1985.78,B1960.86,209.382723191,-41.4659129842,63.4734186744,-15.1442383851,316.163237599,19.6100595169
+J1979.09,B1970.12,256.001743835,-16.3448051664,106.649451565,-45.3254094121,5.44744564064,14.6683716892
+J2008.66,B1964.43,90.8700685367,21.3678694408,287.008253726,60.3030901692,188.510594416,-0.450177420343
+J2024.74,B1958.69,324.057486054,57.4352750563,204.387834151,-3.71156697525,98.8294418875,3.92980570683
+J2004.68,B1961.29,159.225729446,-45.2472278228,37.9943842023,10.4609560801,279.445767043,11.4162684154
+J2017.01,B1999.43,7.38749687642,-53.1540997613,330.796893447,-36.432735539,310.561617023,-63.5428435122
+J1982.65,B1971.70,345.477965039,-10.1831007688,267.939382589,-46.5465175303,61.3892410717,-59.2635781091
+J2018.81,B1991.41,234.801152081,71.8511934075,175.271116162,19.166721209,107.275353666,39.7113209648
+J2002.24,B1978.63,184.754250038,-66.4894904918,34.1841541814,-14.4958117979,299.686716649,-3.81069739954
+J2024.18,B1982.60,245.64829793,-38.7682176459,73.9547095701,-41.3059410321,341.54798842,7.97381666623
+J2011.79,B1986.49,176.234540627,12.5643501076,97.7788131928,38.1835469935,252.339039389,68.6211958128
+J1979.65,B1969.56,333.536461653,-55.645568776,343.316605394,-54.0790917446,336.652926202,-50.1180340532
+J1989.61,B1969.64,185.716717981,-21.5568171888,70.5091730065,12.162471916,294.316919615,40.7880063819
+J1988.65,B1992.98,25.9775574253,12.7249831044,268.242055984,-0.265815951959,142.501478254,-48.0628732689
+J1978.56,B1990.50,204.302987352,-36.6989586206,66.0962720642,-9.57087489783,313.310472546,25.1146611916
+J2009.00,B1991.83,221.487546141,22.5689795999,126.853873425,2.99323159891,29.3329007943,63.7844492045
+J1986.24,B1959.40,338.956666009,-30.7135370512,297.785788922,-58.4349148844,18.009575125,-60.3855752943
+J2002.57,B1967.98,149.5308077,21.1458572723,94.8524518306,65.0524091023,211.851072125,50.1739306174
+J2013.49,B1974.10,95.1983908472,-1.61163007915,325.627893674,50.8317830992,210.781640873,-7.70049786191
+J1985.59,B1998.30,35.0615395317,-28.6207880841,309.362547589,-10.9681750175,222.2815235,-70.2039555167
+J1989.64,B1978.17,174.903919876,-25.7547140538,60.6700456981,17.1698957102,283.434726362,34.3456435324
+J1992.82,B1991.38,167.27863063,54.1842744725,155.134423626,47.955156172,150.615261991,57.1592810224
+J2022.82,B1953.81,10.7133541168,-26.6356033619,299.700062775,-30.2854018223,42.0331929301,-87.8059255496
+J2008.01,B1977.66,249.939886269,43.0233288254,157.107675338,-4.65986958657,67.7233796,41.7069452763
+J2022.53,B1977.40,258.100960451,-37.3838036503,76.1621887374,-51.0815347034,348.967532389,1.36680578377
+J1979.84,B1995.27,262.732112385,-19.8057986634,105.205356822,-52.5372854117,6.11993733263,7.43500801549
+J1988.23,B1968.47,149.166366188,63.2857703333,174.688450428,50.0778473898,148.575911001,44.2672282651
+J1988.61,B1995.06,5.4355841259,0.695799807062,268.674810006,-23.9106016257,107.664837783,-61.2469672937
+J2016.75,B1957.03,327.231056694,-11.1377396332,252.951382603,-62.1498935414,44.0578705009,-44.1656816269
+J2015.64,B1954.96,284.17633852,-71.0631656787,21.4861837786,-44.7317770239,324.040057511,-25.8326289675
+J1989.69,B1998.66,59.4717008987,14.0960045791,281.495047329,29.7732755945,176.567960403,-28.6862393249
+J2007.49,B1997.10,112.602946077,-17.7763932222,359.226063676,44.0329923131,233.074018942,0.179492159778
+J1996.05,B1979.55,219.940310095,-26.5130440909,81.4465458752,-17.5043303516,331.149281423,30.3269968045
+J1978.73,B1952.60,131.216503219,-60.6790709392,16.634154156,1.81850032112,276.99056645,-10.9885663722
+J2011.94,B1952.51,56.1738921125,-19.3427782341,311.186999671,10.4337104739,211.304689863,-49.7748029903
+J2004.27,B1966.23,63.8293728328,-59.8347944156,346.99277437,-9.45023426908,270.969703277,-42.5256665899
+J1992.23,B1968.79,312.440281577,-82.909075449,11.3540896839,-34.157150499,310.093208312,-30.498791986
+J1987.90,B1988.21,104.43408064,-66.6447299251,5.45340291535,-4.88740816946,277.212698727,-24.1397093769
+J1989.59,B1992.96,210.664663673,-17.5831928536,86.0165552167,-5.98416607071,326.19870132,41.9722447163
+J2013.49,B1977.29,163.438155327,-54.6954182678,35.0847453795,1.14728902679,286.284423558,4.38048943444
+J1996.22,B1966.19,148.024127582,2.32865180198,61.1653789554,55.4628176364,235.147968548,40.5062869945
+J1989.43,B1970.29,317.748400264,-34.6457182874,316.831643302,-75.2962612516,9.65732035894,-42.8175894028
+J1988.21,B1955.48,249.374885326,79.5246095403,183.718980722,20.6913682813,112.565520636,32.5641832214
+J1988.85,B1956.86,100.53840787,-27.7507223648,349.546329312,30.9972476643,237.218549213,-14.0500966148
+J2017.12,B1987.27,23.1984832267,21.1208388177,259.952338902,1.35554765265,135.43691251,-40.8550069313
+J1983.48,B1993.82,71.5045009532,3.00896662959,299.603452073,35.2702997539,194.634394328,-25.8112525209
+J1987.60,B1962.95,335.405788093,-6.90098238794,255.324007551,-53.1294372006,55.8410528163,-49.2268304977
+J2004.59,B1984.28,307.588884401,18.8511389183,199.036872823,-43.8235513129,61.4614776755,-11.7984990917
+J2023.77,B1967.96,343.704504442,-46.9224252956,326.142463635,-52.3943400975,344.29956144,-59.491008965
+J1975.21,B1950.30,18.8112053675,35.1485289159,245.286476487,4.93182941858,128.71934377,-27.3093230426
+J1987.00,B1988.06,208.609805013,-46.3894275721,58.5433364885,-16.5301679525,314.238428253,15.0130783715
+J2011.33,B1970.70,172.978655994,15.4172636989,99.5237786852,42.2246688539,240.910040544,68.0540051284
+J1987.54,B1966.69,7.8152324312,-34.9365736294,307.969684049,-34.8499910529,330.146180835,-81.2012202729
+J2020.91,B1963.90,134.503366944,-72.4111269318,16.6485961895,-9.74558853146,287.251430013,-17.0236932061
+J2000.41,B1979.63,149.073048424,14.7065160273,81.1217800627,62.690435672,220.791567295,47.4907829088
+J2000.13,B1966.26,217.406604209,16.5186514295,119.582956349,3.61620654175,12.9778311665,64.930795113
+J2010.62,B1996.84,241.829541848,16.5114334946,131.926345089,-16.4641006337,30.2129120083,43.7266326194
+J2006.99,B1954.80,301.991652158,46.8228690265,192.281654734,-16.0819438067,82.1831278354,7.65942031664
+J1989.22,B1994.16,280.629434995,-19.0017596678,119.763163085,-67.9434807772,15.0327362766,-6.7748272396
+J1975.49,B1978.40,144.252375855,-10.2581330338,44.2663724488,47.1780541535,244.906125318,30.0146889384
+J2004.74,B1953.10,286.0305233,12.7464714044,168.403291875,-46.9082451034,45.684929198,3.05860565516
+J2017.05,B1993.75,321.524751743,61.8464645226,201.729972147,0.142282640146,100.9998867,8.01195048206
+J1999.33,B1961.24,94.4962887092,-44.0946278203,352.197455758,14.1646347321,251.750996447,-24.2178084719
+J2014.04,B1989.97,356.110922656,-39.1892569317,312.562642311,-44.4976591581,347.918750957,-71.4003276728
+J1995.63,B1990.09,307.190555646,-43.7191034979,2.19409366458,-73.0808365619,356.907677491,-35.5140842361
+J1993.99,B1951.45,263.331776174,25.1917278571,153.169840501,-25.2115873395,48.721484719,27.5451183286
+J2019.92,B1981.35,128.003624894,58.8666544649,188.132407462,57.9560573023,158.151363881,35.6484565698
+J2019.84,B1980.23,317.984216655,-8.89508525523,234.105102561,-66.9359336144,41.2540921899,-35.0019322625
+J2011.02,B1953.91,312.465272698,5.18400310772,210.387316474,-56.4513187131,52.2045687218,-23.2783213403
+J1989.24,B1988.65,344.0759205,-20.8070551085,282.194864755,-52.0563161521,40.4226717361,-63.1239129244
+J1991.99,B1957.17,0.0386123471053,-42.7336081023,317.113101073,-41.6722671173,333.272026627,-71.3154908857
+J1989.26,B1973.18,5.95477509083,23.9728714179,248.645776385,-10.559858406,115.039830262,-38.4244563396
+J2013.98,B1954.86,113.065220613,27.4191705733,278.378621564,81.2392172048,191.670829361,20.3160887911
+J1975.23,B1978.49,358.313822853,67.0446512684,211.780718733,12.9835628445,117.438946252,4.91999007663
+J1979.23,B1970.19,53.5839203362,-15.011852649,305.729478083,10.5974755105,203.68085793,-50.0750506428
+J1997.07,B1979.33,60.2557627351,25.6833225299,269.003573186,34.456942967,167.932574018,-20.1669832622
+J1987.55,B1987.44,273.08593329,76.4393919681,185.756212072,15.2737854446,107.678579719,28.6298222935
+J2020.29,B1994.48,25.0306798156,-51.1202356021,329.572709072,-25.482154153,285.52934787,-64.2572780699
+J2019.04,B1968.97,253.970437895,31.094899255,151.036217235,-15.4523165082,52.7995114065,37.292668285
+J2010.83,B1964.62,168.89950144,-43.2270950714,44.9384665428,8.00028298712,284.864643848,16.2980080563
+J1986.93,B1975.46,3.66775780511,39.2622225734,235.238676188,-2.72528403932,115.361704733,-23.0060112816
+J2021.26,B1976.64,278.936590632,6.21231840756,154.692659833,-49.4790598243,36.5657932055,6.53011956709
+J2023.48,B1955.27,285.91236301,9.40548699672,166.481412833,-50.0386245303,42.5308356905,1.81955485147
+J2003.91,B1952.30,53.8450026285,60.7259893436,226.147190382,33.5643817186,141.659779689,3.93637165962
+J1988.45,B1981.10,8.53330744443,-7.54498028811,278.255981158,-25.1174817952,110.761077739,-69.9571108312
+J1990.05,B1991.12,274.342957522,-1.24603088049,141.305593094,-52.2551761295,27.9749402015,6.88675256757
+J2006.27,B1952.75,80.5212647616,19.4060625392,284.864123639,50.4777772377,185.129288864,-9.72047187101
+J2013.99,B1989.90,94.3827831954,15.0883386826,301.493234394,60.9106556021,195.582917069,-0.623869405575
+J1996.06,B1962.21,164.473020999,-47.6965440186,39.4946578672,6.36223553605,283.94830707,10.9316648861
+J2007.85,B1990.18,89.9736906625,-16.9964263489,333.217747094,35.5496625256,222.809109826,-18.9265144618
+J1996.18,B1964.91,204.582082173,15.6789515837,113.317697869,14.3475448707,348.941256944,74.1578851882
diff --git a/astropy/coordinates/tests/accuracy/icrs_fk5.csv b/astropy/coordinates/tests/accuracy/icrs_fk5.csv
new file mode 100644
index 0000000..ed6703c
--- /dev/null
+++ b/astropy/coordinates/tests/accuracy/icrs_fk5.csv
@@ -0,0 +1,202 @@
+# This file was generated with the ref_icrs_fk5.py script, and the reference values were computed using AST
+equinox_fk5,obstime,ra_in,dec_in,ra_fk5,dec_fk5,ra_icrs,dec_icrs
+J1998.36,B1995.95,334.661793414,43.9385116594,334.644564717,43.9302620645,334.679023415,43.9467624314
+J2021.64,B1954.56,113.895199649,-14.1109832563,114.144749047,-14.1600275394,113.645603942,-14.0624187531
+J2020.49,B1953.55,66.2107722038,-7.76265420193,66.4590983513,-7.71687128381,65.9625042534,-7.80888947142
+J1981.50,B1970.69,73.6417002791,41.7006137481,73.3167722987,41.6713224382,73.9668646614,41.7293444168
+J2001.47,B1960.78,204.381010469,-14.9357743223,204.400749583,-14.9432299686,204.361272512,-14.9283175102
+J2005.96,B1975.98,214.396093073,-66.7648451487,214.51622501,-66.7922023737,214.276152292,-66.7374486425
+J2006.23,B1977.93,347.225227105,6.27744217753,347.304207997,6.31127500827,347.146246763,6.24361991082
+J2007.34,B1973.69,235.143754874,-5.59566003897,235.241093646,-5.61898190462,235.046433786,-5.57228120384
+J1991.60,B1960.79,269.606389512,26.7823112195,269.522379939,26.7826702924,269.690399178,26.7820207078
+J1980.71,B1961.97,235.285153507,-14.0695156888,235.015999226,-14.0081475332,235.554479961,-14.1304690349
+J2003.56,B1960.84,269.177331338,42.9472695107,269.20449399,42.9469939989,269.150168743,42.9475544195
+J1990.10,B1982.78,346.070424986,-3.51848810713,345.942775401,-3.57196685618,346.198054805,-3.46497978924
+J1984.68,B1992.32,3.01978725896,7.19732176646,2.82298721926,7.11213924582,3.21663102538,7.28248887117
+J2003.24,B1996.52,38.3199756112,18.8080489808,38.3653094841,18.8221903901,38.2746486329,18.7938987191
+J2005.52,B1990.02,107.533336957,-4.33088623215,107.601845445,-4.34016819794,107.464824543,-4.32163930179
+J1977.27,B1984.04,236.30802591,14.3162535375,236.043743614,14.3866995821,236.572362968,14.2462932004
+J2024.27,B1960.36,291.532518915,-33.7960784017,291.927410812,-33.7460496092,291.137240582,-33.8452405537
+J1980.19,B1987.08,313.983328941,27.7572327639,313.771329108,27.6807919311,314.195342452,27.8339672537
+J1995.29,B1984.85,347.273135054,-13.6880685538,347.211387919,-13.7136412695,347.334872743,-13.662489607
+J2008.28,B1969.09,260.526724891,-37.6134342267,260.667857852,-37.6209601213,260.385615908,-37.6057963361
+J1984.85,B1992.51,231.291118043,-27.2371455509,231.063254934,-27.1842630084,231.519165836,-27.2897662439
+J1987.09,B1976.41,258.283303492,-30.1025933842,258.077147166,-30.0878669846,258.489514237,-30.1170665366
+J2006.16,B1994.65,168.335642599,-44.084769302,168.407881134,-44.1183592869,168.263437199,-44.0511880472
+J2014.94,B1991.03,117.210483914,32.8708634152,117.449614999,32.8326715727,116.971180598,32.9087464534
+J2002.23,B1961.43,158.272058119,-29.286471988,158.29805553,-29.2980114305,158.246062428,-29.2749346296
+J1984.88,B1991.03,262.688069789,-48.1516431413,262.401200048,-48.1407150038,262.975034556,-48.1621531697
+J2014.21,B1956.93,357.845250924,19.2890677934,358.026315201,19.3681291925,357.664269464,19.2100157767
+J2015.72,B1974.12,243.674536239,-10.0431678136,243.889881509,-10.0818251308,243.459271586,-10.0042157281
+J2010.54,B1957.44,284.696106425,19.6051067047,284.810926274,19.6200552,284.581280582,19.5902719604
+J2022.20,B1972.41,61.5291328053,18.6403709997,61.8503393647,18.6989763949,61.2081620218,18.581156754
+J2017.75,B1983.30,9.66573928438,-22.9075078717,9.88608757274,-22.8101292831,9.44526590432,-23.0049503113
+J2023.18,B1989.45,288.133287813,-36.6947385674,288.521507272,-36.654154333,287.744731719,-36.7344915409
+J1998.23,B1983.10,325.340113758,-33.7758802174,325.313691637,-33.783980295,325.366532233,-33.7677775537
+J1999.25,B1985.58,8.88343575454,-49.4693354042,8.87458135076,-49.4734614153,8.89228952149,-49.4652094919
+J2004.32,B1994.40,177.029034641,-67.7755279684,177.081382811,-67.7995455131,176.976736518,-67.7515115552
+J2022.10,B1957.08,189.451860246,-68.7071945134,189.787950236,-68.8284977585,189.117915692,-68.5857730927
+J1993.61,B1957.38,214.691763751,-32.6160600699,214.596970957,-32.5867949166,214.786602083,-32.6452917256
+J2004.91,B1966.30,18.7047162369,-32.9080620608,18.7619437329,-32.8821737407,18.6474776276,-32.9339591431
+J2005.68,B1951.59,322.232230099,14.4669345738,322.300004441,14.4919497078,322.164454374,14.4419423495
+J2003.00,B1984.39,262.175824918,51.7319974933,262.193291036,51.7297325887,262.15835963,51.7342674421
+J1980.93,B1988.24,294.6060041,34.0181871087,294.426858562,33.9741356521,294.78513452,34.0625403768
+J1995.15,B1967.50,180.08019102,26.2892216009,180.018069261,26.3162194666,180.142298341,26.2622237714
+J1986.07,B1980.80,291.668187169,-22.2789167174,291.460165406,-22.3074160406,291.876124294,-22.2501557708
+J2014.41,B1997.92,34.548669268,-15.8924906144,34.7203476357,-15.826491503,34.3769912557,-15.9586260582
+J2013.20,B1964.55,78.8220157436,-37.4332268082,78.9359542832,-37.4190574603,78.7080839461,-37.4475395217
+J1983.72,B1984.33,93.1388621771,60.5731416456,92.7698274429,60.5778081354,93.5078078659,60.5678923219
+J2011.19,B1952.11,168.518071423,7.09229333513,168.662964922,7.03122231792,168.373145295,7.15333299716
+J2021.23,B1953.13,165.374352937,39.3890686842,165.670569356,39.2746286306,165.077550855,39.5033543186
+J1998.80,B1990.72,255.423520875,-17.5881075751,255.406106679,-17.5864187707,255.440935444,-17.5897944148
+J2020.65,B1971.83,64.0990821181,36.8289797648,64.4412908098,36.8788812849,63.757239339,36.77846091
+J1996.87,B1969.60,191.321958369,-52.3532066605,191.277444974,-52.3361209946,191.366491705,-52.3702896721
+J1978.29,B1966.53,60.3872023631,25.1025882655,60.0600049106,25.0425615489,60.7146932542,25.1620146503
+J1993.19,B1972.88,276.773010626,56.6051138031,276.742873164,56.6006572956,276.803141964,56.6095901107
+J1984.47,B1991.77,334.141397682,37.3852087993,333.971320286,37.3074623211,334.311570487,37.4630672642
+J1982.42,B1973.34,219.417716878,-20.2290328911,219.169713749,-20.1532857902,219.66593381,-20.3045108915
+J1985.55,B1971.06,54.0660580808,-29.3264933861,53.9175360432,-29.3737907652,54.2145819747,-29.2793648485
+J2018.98,B1978.54,176.26561333,-0.572718169429,176.5087243,-0.678171194716,176.022494179,-0.467294315659
+J2015.89,B1986.95,135.84418338,-9.94938261687,136.036951663,-10.0129567306,135.651382202,-9.88601582693
+J2006.58,B1952.75,305.496508312,-8.63421746611,305.585332083,-8.61291748186,305.407668201,-8.65547120765
+J2022.76,B1981.21,327.995002307,-58.3471659896,328.394703325,-58.2394830075,327.593625588,-58.4543795694
+J1980.95,B1981.05,138.185539617,11.9337947187,137.926465957,12.0126777715,138.444435852,11.854592026
+J2005.11,B1950.06,113.578525223,29.6301583121,113.658818144,29.6187548389,113.498216367,29.6415252375
+J1991.57,B1980.14,204.621895006,36.5235009134,204.528365616,36.5661830045,204.715395365,36.4808507277
+J2016.08,B1952.01,67.6144926088,-13.7094836718,67.8003322803,-13.675528411,67.4286781478,-13.7437074086
+J2007.99,B1979.29,45.3029557779,36.4639084123,45.4287375369,36.4951563695,45.1772514486,36.4325910517
+J1996.13,B1972.42,247.534489816,-3.23349952461,247.483791774,-3.22525417405,247.585191141,-3.24172726082
+J2010.80,B1967.69,287.858418461,26.2825631559,287.968526608,26.3010624761,287.748304904,26.2641738179
+J1985.76,B1996.68,206.473163472,-38.4312130715,206.262844929,-38.3601778797,206.683760191,-38.5021184668
+J1975.84,B1963.36,350.362793376,-7.51631961926,350.050245875,-7.64886538089,350.675192428,-7.38365103931
+J1989.04,B1964.06,228.259575769,40.311002157,228.157788783,40.3516658201,228.36135704,40.2704193663
+J2005.09,B1975.25,319.831820932,40.7337792676,319.881302594,40.7554460493,319.782343346,40.712128268
+J1998.03,B1982.34,178.349313153,-38.3854710615,178.324338212,-38.3745092745,178.374291779,-38.3964329888
+J2010.53,B1998.53,126.58195076,-73.6980337652,126.555725353,-73.7329650434,126.607757619,-73.6630811157
+J1983.23,B1951.79,257.122932676,24.0154376566,256.948650568,24.0363842696,257.297226196,23.9947678892
+J2022.01,B1971.16,181.414481921,-17.7858263698,181.697561318,-17.9083119018,181.131603746,-17.6633258663
+J2022.77,B1979.42,81.2295383474,-9.26450146427,81.5008624611,-9.24547745382,80.9582426792,-9.28411870238
+J2024.04,B1986.59,88.1907984871,32.4238226453,88.5837995469,32.4275810011,87.7978296174,32.4191468321
+J1977.94,B1958.78,285.408252018,67.7826509035,285.415288738,67.7500149744,285.400733562,67.815271794
+J2012.02,B1975.53,178.262069224,51.7327600597,178.418521574,51.6658699581,178.105379001,51.7996446322
+J2005.03,B1975.01,329.433722424,-46.8960749035,329.513358137,-46.8719488299,329.354038052,-46.9201811836
+J1979.45,B1994.64,340.333860195,36.5560891832,340.099269221,36.4484316911,340.568666175,36.6639044187
+J2024.47,B1969.13,191.963602676,21.3572019706,192.265985395,21.2240120738,191.661020584,21.4905409785
+J2002.44,B1983.14,90.8973340407,3.44588414281,90.9294194634,3.44566140242,90.8652485585,3.44609927685
+J2008.72,B1952.34,259.510340943,47.0512387915,259.570777662,47.0424288828,259.449910071,47.060099055
+J2011.24,B1987.56,132.277954966,30.4307232942,132.449103167,30.388553739,132.106687114,30.4727545196
+J2003.42,B1968.44,179.513439448,-54.44865752,179.557050535,-54.4676997913,179.469848483,-54.4296153679
+J2001.37,B1997.40,81.5670170865,-19.9451944488,81.5818413055,-19.9440843678,81.5521929287,-19.9463064817
+J1982.54,B1967.36,127.283632829,-10.0946390302,127.073706282,-10.0359014336,127.493515779,-10.1536599704
+J1987.01,B1984.19,234.306643184,-86.4404274379,233.208246223,-86.397666282,235.429405927,-86.482050156
+J1995.13,B1991.23,112.65584231,11.2521500479,112.588477624,11.262573342,112.723199816,11.2416973345
+J1978.39,B1974.31,276.744760981,21.4151577082,276.514780435,21.4012711846,276.974729777,21.4295237953
+J2012.92,B1999.21,281.461357214,-15.511897988,281.646447197,-15.4974841762,281.27623546,-15.5260840726
+J1992.13,B1980.19,306.867413859,-11.9467360888,306.759165107,-11.9729853099,306.975635305,-11.9204206469
+J2024.49,B1987.98,341.966066455,-2.82477813631,342.281869892,-2.69502407373,341.650132043,-2.95429956154
+J2019.43,B1984.23,38.6362483924,9.3322810896,38.8963811972,9.41661462037,38.3762808891,9.24764100258
+J2021.93,B1996.62,327.861128148,-46.529254733,328.210157236,-46.4256790337,327.511186361,-46.632434339
+J2011.96,B1997.49,120.979858288,87.22617179,122.295667673,87.1912385961,119.633038513,87.2597786682
+J1976.35,B1999.51,297.496953653,0.839666332936,297.195644583,0.779185153185,297.798143461,0.9007616283
+J1994.12,B1956.31,323.316228643,-0.794522598791,323.240624027,-0.820755621072,323.391823819,-0.768263773348
+J1975.53,B1998.83,15.3775095611,-38.7740290611,15.0928652608,-38.9054807438,15.6617662484,-38.6427567079
+J1978.26,B1961.46,70.486199672,-24.0682131367,70.2586642967,-24.1088709419,70.7137598878,-24.0280083925
+J2009.07,B1959.30,106.020475905,36.6574903487,106.172780811,36.6434848171,105.868125064,36.6713668422
+J2024.33,B1975.46,225.719957006,-24.2326924255,226.075567685,-24.326948892,225.364802775,-24.1378344642
+J2008.31,B1976.52,31.0403178442,23.2187819108,31.1570536178,23.258394038,30.9236362505,23.1791211798
+J1995.76,B1964.13,51.4602071324,-27.0058546166,51.4152973853,-27.0205700299,51.5051169729,-26.991153671
+J1977.06,B1965.51,185.697546923,55.594260797,185.421779304,55.721374348,185.972510783,55.4672081659
+J2019.71,B1965.49,248.162878677,-23.7609450888,248.460344259,-23.8014906584,247.865592952,-23.7198708623
+J2010.34,B1963.32,308.385291884,51.2349043028,308.461574811,51.2706847328,308.308996421,51.1991839517
+J1998.94,B1979.67,233.050205996,63.3093356498,233.046004532,63.3128868847,233.05440839,63.3057847603
+J1985.78,B1960.86,209.382723191,-41.4659129842,209.166390198,-41.3968581581,209.599369778,-41.5348210618
+J1979.09,B1970.12,256.001743835,-16.3448051664,255.700801743,-16.3163460002,256.302789611,-16.3726709454
+J2008.66,B1964.43,90.8700685367,21.3678694408,90.9998841203,21.3670776114,90.7402515844,21.3685520416
+J2024.74,B1958.69,324.057486054,57.4352750563,324.24791254,57.5469196438,323.867096755,57.3238991167
+J2004.68,B1961.29,159.225729446,-45.2472278228,159.276379685,-45.27159791,159.175093005,-45.2228659014
+J2017.01,B1999.43,7.38749687642,-53.1540997613,7.58899121668,-53.0602158752,7.18561693871,-53.2480265357
+J1982.65,B1971.70,345.477965039,-10.1831007688,345.251295994,-10.2765575516,345.704526845,-10.0895481742
+J2018.81,B1991.41,234.801152081,71.8511934075,234.781598949,71.7908263583,234.821698672,71.9115305128
+J2002.24,B1978.63,184.754250038,-66.4894904918,184.785352293,-66.5019187594,184.723164704,-66.4770616601
+J2024.18,B1982.60,245.64829793,-38.7682176459,246.056856393,-38.8232771335,245.240252475,-38.7122842298
+J2011.79,B1986.49,176.234540627,12.5643501076,176.386539261,12.4988499005,176.082498099,12.6298388968
+J1979.65,B1969.56,333.536461653,-55.645568776,333.201327008,-55.7468423589,333.870449248,-55.544000369
+J1989.61,B1969.64,185.716717981,-21.5568171888,185.58137022,-21.4992561733,185.852126151,-21.6143646005
+J1988.65,B1992.98,25.9775574253,12.7249831044,25.8259425625,12.6681381133,26.129235078,12.7817548524
+J1978.56,B1990.50,204.302987352,-36.6989586206,203.992013028,-36.590035009,204.614547277,-36.8076153687
+J2009.00,B1991.83,221.487546141,22.5689795999,221.589063682,22.531481696,221.386026462,22.6065363227
+J1986.24,B1959.40,338.956666009,-30.7135370512,338.763951811,-30.7849831444,339.149190984,-30.6419984779
+J2002.57,B1967.98,149.5308077,21.1458572723,149.566540611,21.1335179376,149.495070016,21.1581920836
+J2013.49,B1974.10,95.1983908472,-1.61163007915,95.3691226237,-1.61855225484,95.0276507441,-1.6049307767
+J1985.59,B1998.30,35.0615395317,-28.6207880841,34.9020739253,-28.6865248849,35.2209739544,-28.5551795263
+J1989.64,B1978.17,174.903919876,-25.7547140538,174.773704705,-25.6972724215,175.03419171,-25.8121673429
+J1992.82,B1991.38,167.27863063,54.1842744725,167.174390005,54.2232575861,167.382755502,54.1452753419
+J2022.82,B1953.81,10.7133541168,-26.6356033619,10.9937676648,-26.5108341533,10.4326984418,-26.7604882278
+J2008.01,B1977.66,249.939886269,43.0233288254,250.003422167,43.0080617632,249.876355463,43.0386423389
+J2022.53,B1977.40,258.100960451,-37.3838036503,258.483519166,-37.4092478087,257.718621316,-37.3575402646
+J1979.84,B1995.27,262.732112385,-19.8057986634,262.43378889,-19.7913038792,263.030493701,-19.8197136836
+J1988.23,B1968.47,149.166366188,63.2857703333,148.948549069,63.3419675102,149.383595682,63.2294456404
+J1988.61,B1995.06,5.4355841259,0.695799807062,5.28960631728,0.632663567066,5.5815705005,0.758920757926
+J2016.75,B1957.03,327.231056694,-11.1377396332,327.455533267,-11.0592260753,327.006447871,-11.2160554034
+J2015.64,B1954.96,284.17633852,-71.0631656787,284.622383668,-71.0415076498,283.729510587,-71.08416592
+J1989.69,B1998.66,59.4717008987,14.0960045791,59.3272356842,14.0667790018,59.6162113325,14.1251054777
+J2007.49,B1997.10,112.602946077,-17.7763932222,112.686574032,-17.7924540137,112.519313748,-17.7603886122
+J1996.05,B1979.55,219.940310095,-26.5130440909,219.882677955,-26.4961740042,219.997955886,-26.5298999803
+J1978.73,B1952.60,131.216503219,-60.6790709392,131.102499987,-60.6011373948,131.330276761,-60.7571815411
+J2011.94,B1952.51,56.1738921125,-19.3427782341,56.3074873507,-19.3058404816,56.0403066499,-19.3798447522
+J2004.27,B1966.23,63.8293728328,-59.8347944156,63.8473703919,-59.8243161934,63.8113850715,-59.8452793392
+J1992.23,B1968.79,312.440281577,-82.909075449,312.082844158,-82.9381618829,312.795193361,-82.879790561
+J1987.90,B1988.21,104.43408064,-66.6447299251,104.430099425,-66.6279457743,104.437942894,-66.6615185415
+J1989.59,B1992.96,210.664663673,-17.5831928536,210.521977043,-17.533300504,210.807417956,-17.6330115873
+J2013.49,B1977.29,163.438155327,-54.6954182678,163.580861698,-54.7674320028,163.295621486,-54.6234578045
+J1996.22,B1966.19,148.024127582,2.32865180198,147.975248991,2.34649291874,148.073002076,2.31080117706
+J1989.43,B1970.29,317.748400264,-34.6457182874,317.585582699,-34.6892153211,317.911087895,-34.6021088555
+J1988.21,B1955.48,249.374885326,79.5246095403,249.556636954,79.5476344368,249.19427904,79.5013904045
+J1988.85,B1956.86,100.53840787,-27.7507223648,100.427671298,-27.7394319384,100.64914055,-27.7621307317
+J2017.12,B1987.27,23.1984832267,21.1208388177,23.4324436323,21.2083599648,22.9647269089,21.0331644062
+J1983.48,B1993.82,71.5045009532,3.00896662959,71.2883142486,2.97961964121,71.7207379936,3.03798447641
+J1987.60,B1962.95,335.405788093,-6.90098238794,335.243429575,-6.9637085665,335.56809315,-6.83817480211
+J2004.59,B1984.28,307.588884401,18.8511389183,307.640784808,18.8667407469,307.536982665,18.8355554286
+J2023.77,B1967.96,343.704504442,-46.9224252956,344.048269178,-46.7952999698,343.359747105,-47.0493275593
+J1975.21,B1950.30,18.8112053675,35.1485289159,18.4626544919,35.0177535414,19.1604681331,35.2790332993
+J1987.00,B1988.06,208.609805013,-46.3894275721,208.40705329,-46.3258250272,208.812873725,-46.4529073994
+J2011.33,B1970.70,172.978655994,15.4172636989,173.125918709,15.3546485543,172.831339838,15.4798590369
+J1987.54,B1966.69,7.8152324312,-34.9365736294,7.662140954,-35.0053080694,7.96821251179,-34.8678643727
+J2020.91,B1963.90,134.503366944,-72.4111269318,134.508752259,-72.4927321248,134.496713839,-72.3295304626
+J2000.41,B1979.63,149.073048424,14.7065160273,149.078614359,14.7045538676,149.067482395,14.7084780734
+J2000.13,B1966.26,217.406604209,16.5186514295,217.408141458,16.5180765377,217.40506696,16.5192263332
+J2010.62,B1996.84,241.829541848,16.5114334946,241.950169443,16.4835846733,241.708924453,16.5393920451
+J2006.99,B1954.80,301.991652158,46.8228690265,302.04602973,46.8435076393,301.937270072,46.8022617404
+J1989.22,B1994.16,280.629434995,-19.0017596678,280.47101531,-19.0127425519,280.787831403,-18.9906136966
+J1975.49,B1978.40,144.252375855,-10.2581330338,143.952794662,-10.1475953709,144.551902691,-10.3690875087
+J2004.74,B1953.10,286.0305233,12.7464714044,286.085513107,12.7537759609,285.975531683,12.739191194
+J2017.05,B1993.75,321.524751743,61.8464645226,321.632828791,61.9208329855,321.416592726,61.7722074849
+J1999.33,B1961.24,94.4962887092,-44.0946278203,94.4913067992,-44.0943400421,94.5012706073,-44.0949159215
+J2014.04,B1989.97,356.110922656,-39.1892569317,356.295020794,-39.1112673044,355.926608129,-39.2672295394
+J1995.63,B1990.09,307.190555646,-43.7191034979,307.116027145,-43.7337921796,307.265056341,-43.7043896052
+J1993.99,B1951.45,263.331776174,25.1917278571,263.270410907,25.195633174,263.393142235,25.187858127
+J2019.92,B1981.35,128.003624894,58.8666544649,128.402920612,58.7980654005,127.60315064,58.9346336939
+J2019.84,B1980.23,317.984216655,-8.89508525523,318.249905253,-8.81284951457,317.718360008,-8.97697809843
+J2011.02,B1953.91,312.465272698,5.18400310772,312.602344189,5.22548362633,312.328177207,5.1426308705
+J1989.24,B1988.65,344.0759205,-20.8070551085,343.931796087,-20.8646386849,344.219970948,-20.7494301859
+J1991.99,B1957.17,0.0386123471053,-42.7336081023,359.935984167,-42.778197083,0.141166805258,-42.6890191696
+J1989.26,B1973.18,5.95477509083,23.9728714179,5.81446857607,23.9133953285,6.09515408275,24.0323323244
+J2013.98,B1954.86,113.065220613,27.4191705733,113.281430058,27.3885381062,112.848903077,27.4495327526
+J1975.23,B1978.49,358.313822853,67.0446512684,358.006936646,66.906817269,358.62239279,67.1825070772
+J1979.23,B1970.19,53.5839203362,-15.011852649,53.3428201185,-15.0806959511,53.8250625845,-14.9434009383
+J1997.07,B1979.33,60.2557627351,25.6833225299,60.211425166,25.6752201005,60.3001057813,25.6914140019
+J1987.55,B1987.44,273.08593329,76.4393919681,273.213340941,76.4355890802,272.958409407,76.443040877
+J2020.29,B1994.48,25.0306798156,-51.1202356021,25.2312583612,-51.0179789716,24.8298733815,-51.2226596567
+J2019.04,B1968.97,253.970437895,31.094899255,254.152950904,31.0657978691,253.787939628,31.1243251572
+J2010.83,B1964.62,168.89950144,-43.2270950714,169.027402777,-43.286276106,168.771701635,-43.167939929
+J1986.93,B1975.46,3.66775780511,39.2622225734,3.49661533708,39.1896011422,3.8390874932,39.3348301065
+J2021.26,B1976.64,278.936590632,6.21231840756,279.196246371,6.23097561081,278.676905991,6.19419108431
+J2023.48,B1955.27,285.91236301,9.40548699672,286.192352454,9.44163731007,285.632321786,9.36995103333
+J2003.91,B1952.30,53.8450026285,60.7259893436,53.9264872004,60.7388195386,53.763567111,60.7131341506
+J1988.45,B1981.10,8.53330744443,-7.54498028811,8.38660351469,-7.60858303157,8.6800005788,-7.48140196135
+J1990.05,B1991.12,274.342957522,-1.24603088049,274.214291508,-1.25015780077,274.471619291,-1.24177991998
+J2006.27,B1952.75,80.5212647616,19.4060625392,80.6137303362,19.4117801816,80.4288063349,19.4002893257
+J2013.99,B1989.90,94.3827831954,15.0883386826,94.5829613625,15.0822437507,94.1825907513,15.0941622997
+J1996.06,B1962.21,164.473020999,-47.6965440186,164.429008903,-47.6754169753,164.51704615,-47.7176755752
+J2007.85,B1990.18,89.9736906625,-16.9964263489,90.0609144086,-16.9964467144,89.8864669212,-16.9964725118
+J1996.18,B1964.91,204.582082173,15.6789515837,204.535627332,15.698292886,204.628535832,15.6596174499
diff --git a/astropy/coordinates/tests/accuracy/ref_fk4_no_e_fk4.py b/astropy/coordinates/tests/accuracy/ref_fk4_no_e_fk4.py
new file mode 100644
index 0000000..1d2ec38
--- /dev/null
+++ b/astropy/coordinates/tests/accuracy/ref_fk4_no_e_fk4.py
@@ -0,0 +1,55 @@
+# Accuracy tests for the FK4 (with no E-terms of aberration) to/from FK4
+# conversion, with arbitrary equinoxes and epoch of observation.
+
+import os
+import numpy as np
+import starlink.Ast as Ast
+from astropy.table import Table, Column
+
+np.random.seed(12345)
+
+N = 200
+
+# Sample uniformly on the unit sphere. These will be either the FK4
+# coordinates for the transformation to FK5, or the FK5 coordinates for the
+# transformation to FK4.
+ra = np.random.uniform(0., 360., N)
+dec = np.degrees(np.arcsin(np.random.uniform(-1., 1., N)))
+
+# Generate random observation epoch and equinoxes
+obstime = ["B{0:7.2f}".format(x) for x in np.random.uniform(1950., 2000., N)]
+
+ra_fk4ne, dec_fk4ne = [], []
+ra_fk4, dec_fk4 = [], []
+
+for i in range(N):
+
+    # Set up frames for AST
+    frame_fk4ne = Ast.SkyFrame('System=FK4-NO-E,Epoch={epoch},Equinox=B1950'.format(epoch=obstime[i]))
+    frame_fk4 = Ast.SkyFrame('System=FK4,Epoch={epoch},Equinox=B1950'.format(epoch=obstime[i]))
+
+    # FK4 to FK4 (no E-terms)
+    frameset = frame_fk4.convert(frame_fk4ne)
+    coords = np.degrees(frameset.tran([[np.radians(ra[i])], [np.radians(dec[i])]]))
+    ra_fk4ne.append(coords[0, 0])
+    dec_fk4ne.append(coords[1, 0])
+
+    # FK4 (no E-terms) to FK4
+    frameset = frame_fk4ne.convert(frame_fk4)
+    coords = np.degrees(frameset.tran([[np.radians(ra[i])], [np.radians(dec[i])]]))
+    ra_fk4.append(coords[0, 0])
+    dec_fk4.append(coords[1, 0])
+
+# Write out table to a CSV file
+t = Table()
+t.add_column(Column('obstime', obstime))
+t.add_column(Column('ra_in', ra))
+t.add_column(Column('dec_in', dec))
+t.add_column(Column('ra_fk4ne', ra_fk4ne))
+t.add_column(Column('dec_fk4ne', dec_fk4ne))
+t.add_column(Column('ra_fk4', ra_fk4))
+t.add_column(Column('dec_fk4', dec_fk4))
+f = open('fk4_no_e_fk4.csv', 'wb')
+f.write("# This file was generated with the {0} script, and the reference "
+        "values were computed using AST\n".format(os.path.basename(__file__)))
+t.write(f, format='ascii', delimiter=',')
diff --git a/astropy/coordinates/tests/accuracy/ref_fk4_no_e_fk5.py b/astropy/coordinates/tests/accuracy/ref_fk4_no_e_fk5.py
new file mode 100644
index 0000000..1fc4347
--- /dev/null
+++ b/astropy/coordinates/tests/accuracy/ref_fk4_no_e_fk5.py
@@ -0,0 +1,59 @@
+# Accuracy tests for the FK4 (with no E-terms of aberration) to/from FK5
+# conversion, with arbitrary equinoxes and epoch of observation.
+
+import os
+import numpy as np
+import starlink.Ast as Ast
+from astropy.table import Table, Column
+
+np.random.seed(12345)
+
+N = 200
+
+# Sample uniformly on the unit sphere. These will be either the FK4
+# coordinates for the transformation to FK5, or the FK5 coordinates for the
+# transformation to FK4.
+ra = np.random.uniform(0., 360., N)
+dec = np.degrees(np.arcsin(np.random.uniform(-1., 1., N)))
+
+# Generate random observation epoch and equinoxes
+obstime = ["B{0:7.2f}".format(x) for x in np.random.uniform(1950., 2000., N)]
+equinox_fk4 = ["B{0:7.2f}".format(x) for x in np.random.uniform(1925., 1975., N)]
+equinox_fk5 = ["J{0:7.2f}".format(x) for x in np.random.uniform(1975., 2025., N)]
+
+ra_fk4, dec_fk4 = [], []
+ra_fk5, dec_fk5 = [], []
+
+for i in range(N):
+
+    # Set up frames for AST
+    frame_fk4 = Ast.SkyFrame('System=FK4-NO-E,Epoch={epoch},Equinox={equinox_fk4}'.format(epoch=obstime[i], equinox_fk4=equinox_fk4[i]))
+    frame_fk5 = Ast.SkyFrame('System=FK5,Epoch={epoch},Equinox={equinox_fk5}'.format(epoch=obstime[i], equinox_fk5=equinox_fk5[i]))
+
+    # FK4 to FK5
+    frameset = frame_fk4.convert(frame_fk5)
+    coords = np.degrees(frameset.tran([[np.radians(ra[i])], [np.radians(dec[i])]]))
+    ra_fk5.append(coords[0, 0])
+    dec_fk5.append(coords[1, 0])
+
+    # FK5 to FK4
+    frameset = frame_fk5.convert(frame_fk4)
+    coords = np.degrees(frameset.tran([[np.radians(ra[i])], [np.radians(dec[i])]]))
+    ra_fk4.append(coords[0, 0])
+    dec_fk4.append(coords[1, 0])
+
+# Write out table to a CSV file
+t = Table()
+t.add_column(Column('equinox_fk4', equinox_fk4))
+t.add_column(Column('equinox_fk5', equinox_fk5))
+t.add_column(Column('obstime', obstime))
+t.add_column(Column('ra_in', ra))
+t.add_column(Column('dec_in', dec))
+t.add_column(Column('ra_fk5', ra_fk5))
+t.add_column(Column('dec_fk5', dec_fk5))
+t.add_column(Column('ra_fk4', ra_fk4))
+t.add_column(Column('dec_fk4', dec_fk4))
+f = open('fk4_no_e_fk5.csv', 'wb')
+f.write("# This file was generated with the {0} script, and the reference "
+        "values were computed using AST\n".format(os.path.basename(__file__)))
+t.write(f, format='ascii', delimiter=',')
diff --git a/astropy/coordinates/tests/accuracy/ref_galactic_fk4.py b/astropy/coordinates/tests/accuracy/ref_galactic_fk4.py
new file mode 100644
index 0000000..a220b2a
--- /dev/null
+++ b/astropy/coordinates/tests/accuracy/ref_galactic_fk4.py
@@ -0,0 +1,57 @@
+# Accuracy tests for the ICRS (with no E-terms of aberration) to/from FK5
+# conversion, with arbitrary equinoxes and epoch of observation.
+
+import os
+import numpy as np
+import starlink.Ast as Ast
+from astropy.table import Table, Column
+
+np.random.seed(12345)
+
+N = 200
+
+# Sample uniformly on the unit sphere. These will be either the ICRS
+# coordinates for the transformation to FK5, or the FK5 coordinates for the
+# transformation to ICRS.
+lon = np.random.uniform(0., 360., N)
+lat = np.degrees(np.arcsin(np.random.uniform(-1., 1., N)))
+
+# Generate random observation epoch and equinoxes
+obstime = ["B{0:7.2f}".format(x) for x in np.random.uniform(1950., 2000., N)]
+equinox_fk4 = ["J{0:7.2f}".format(x) for x in np.random.uniform(1975., 2025., N)]
+
+lon_gal, lat_gal = [], []
+ra_fk4, dec_fk4 = [], []
+
+for i in range(N):
+
+    # Set up frames for AST
+    frame_gal = Ast.SkyFrame('System=Galactic,Epoch={epoch}'.format(epoch=obstime[i]))
+    frame_fk4 = Ast.SkyFrame('System=FK4,Epoch={epoch},Equinox={equinox_fk4}'.format(epoch=obstime[i], equinox_fk4=equinox_fk4[i]))
+
+    # ICRS to FK5
+    frameset = frame_gal.convert(frame_fk4)
+    coords = np.degrees(frameset.tran([[np.radians(lon[i])], [np.radians(lat[i])]]))
+    ra_fk4.append(coords[0, 0])
+    dec_fk4.append(coords[1, 0])
+
+    # FK5 to ICRS
+    frameset = frame_fk4.convert(frame_gal)
+    coords = np.degrees(frameset.tran([[np.radians(lon[i])], [np.radians(lat[i])]]))
+    lon_gal.append(coords[0, 0])
+    lat_gal.append(coords[1, 0])
+
+# Write out table to a CSV file
+t = Table()
+t.add_column(Column('equinox_fk4', equinox_fk4))
+t.add_column(Column('obstime', obstime))
+t.add_column(Column('lon_in', lon))
+t.add_column(Column('lat_in', lat))
+t.add_column(Column('ra_fk4', ra_fk4))
+t.add_column(Column('dec_fk4', dec_fk4))
+t.add_column(Column('lon_gal', lon_gal))
+t.add_column(Column('lat_gal', lat_gal))
+f = open('galactic_fk4.csv', 'wb')
+f.write("# This file was generated with the {0} script, and the reference "
+        "values were computed using AST\n".format(os.path.basename(__file__)))
+t.write(f, format='ascii', delimiter=',')
diff --git a/astropy/coordinates/tests/accuracy/ref_icrs_fk5.py b/astropy/coordinates/tests/accuracy/ref_icrs_fk5.py
new file mode 100644
index 0000000..2c05a10
--- /dev/null
+++ b/astropy/coordinates/tests/accuracy/ref_icrs_fk5.py
@@ -0,0 +1,57 @@
+# Accuracy tests for the ICRS (with no E-terms of aberration) to/from FK5
+# conversion, with arbitrary equinoxes and epoch of observation.
+
+import os
+import numpy as np
+import starlink.Ast as Ast
+from astropy.table import Table, Column
+
+np.random.seed(12345)
+
+N = 200
+
+# Sample uniformly on the unit sphere. These will be either the ICRS
+# coordinates for the transformation to FK5, or the FK5 coordinates for the
+# transformation to ICRS.
+ra = np.random.uniform(0., 360., N)
+dec = np.degrees(np.arcsin(np.random.uniform(-1., 1., N)))
+
+# Generate random observation epoch and equinoxes
+obstime = ["B{0:7.2f}".format(x) for x in np.random.uniform(1950., 2000., N)]
+equinox_fk5 = ["J{0:7.2f}".format(x) for x in np.random.uniform(1975., 2025., N)]
+
+ra_icrs, dec_icrs = [], []
+ra_fk5, dec_fk5 = [], []
+
+for i in range(N):
+
+    # Set up frames for AST
+    frame_icrs = Ast.SkyFrame('System=ICRS,Epoch={epoch}'.format(epoch=obstime[i]))
+    frame_fk5 = Ast.SkyFrame('System=FK5,Epoch={epoch},Equinox={equinox_fk5}'.format(epoch=obstime[i], equinox_fk5=equinox_fk5[i]))
+
+    # ICRS to FK5
+    frameset = frame_icrs.convert(frame_fk5)
+    coords = np.degrees(frameset.tran([[np.radians(ra[i])], [np.radians(dec[i])]]))
+    ra_fk5.append(coords[0, 0])
+    dec_fk5.append(coords[1, 0])
+
+    # FK5 to ICRS
+    frameset = frame_fk5.convert(frame_icrs)
+    coords = np.degrees(frameset.tran([[np.radians(ra[i])], [np.radians(dec[i])]]))
+    ra_icrs.append(coords[0, 0])
+    dec_icrs.append(coords[1, 0])
+
+# Write out table to a CSV file
+t = Table()
+t.add_column(Column('equinox_fk5', equinox_fk5))
+t.add_column(Column('obstime', obstime))
+t.add_column(Column('ra_in', ra))
+t.add_column(Column('dec_in', dec))
+t.add_column(Column('ra_fk5', ra_fk5))
+t.add_column(Column('dec_fk5', dec_fk5))
+t.add_column(Column('ra_icrs', ra_icrs))
+t.add_column(Column('dec_icrs', dec_icrs))
+f = open('icrs_fk5.csv', 'wb')
+f.write("# This file was generated with the {0} script, and the reference "
+        "values were computed using AST\n".format(os.path.basename(__file__)))
+t.write(f, format='ascii', delimiter=',')
diff --git a/astropy/coordinates/tests/accuracy/test_fk4_no_e_fk4.py b/astropy/coordinates/tests/accuracy/test_fk4_no_e_fk4.py
new file mode 100644
index 0000000..0a3a184
--- /dev/null
+++ b/astropy/coordinates/tests/accuracy/test_fk4_no_e_fk4.py
@@ -0,0 +1,50 @@
+import os
+
+import numpy as np
+
+from .... import units as u
+from ... import FK4NoETermCoordinates, FK4Coordinates
+from ....time import Time
+from ....table import Table
+from ...angle_utilities import vincenty_sphere_dist
+
+# It looks as though SLALIB, which AST relies on, assumes a simplified version
+# of the e-terms corretion, so we have to up the tolerance a bit to get things
+# to agree.
+TOLERANCE = 1.e-5  # arcseconds
+
+ROOT = os.path.dirname(os.path.abspath(__file__))
+
+
+def test_fk4_no_e_fk5():
+
+    t = Table.read(os.path.join(ROOT, 'fk4_no_e_fk4.csv'), format='ascii')
+
+    for i in range(len(t)):
+
+        # Extract row
+        r = t[i]
+
+        # FK4 to FK5
+        c1 = FK4Coordinates(r['ra_in'], r['dec_in'],
+                            unit=(u.degree, u.degree),
+                            obstime=Time(r['obstime'], scale='utc'))
+        c2 = c1.transform_to(FK4NoETermCoordinates)
+
+        # Find difference
+        diff = vincenty_sphere_dist(c2.ra.radians, c2.dec.radians,
+                                    np.radians(r['ra_fk4ne']), np.radians(r['dec_fk4ne']))
+
+        assert np.degrees(diff) * 3600. < TOLERANCE
+
+        # FK5 to FK4
+        c1 = FK4NoETermCoordinates(r['ra_in'], r['dec_in'],
+                                   unit=(u.degree, u.degree),
+                                   obstime=Time(r['obstime'], scale='utc'))
+        c2 = c1.transform_to(FK4Coordinates)
+
+        # Find difference
+        diff = vincenty_sphere_dist(c2.ra.radians, c2.dec.radians,
+                                    np.radians(r['ra_fk4']), np.radians(r['dec_fk4']))
+
+        assert np.degrees(diff) * 3600. < TOLERANCE
diff --git a/astropy/coordinates/tests/accuracy/test_fk4_no_e_fk5.py b/astropy/coordinates/tests/accuracy/test_fk4_no_e_fk5.py
new file mode 100644
index 0000000..2c94b3f
--- /dev/null
+++ b/astropy/coordinates/tests/accuracy/test_fk4_no_e_fk5.py
@@ -0,0 +1,49 @@
+import os
+
+import numpy as np
+
+from .... import units as u
+from ... import FK4NoETermCoordinates, FK5Coordinates
+from ....time import Time
+from ....table import Table
+from ...angle_utilities import vincenty_sphere_dist
+
+TOLERANCE = 0.03  # arcseconds
+
+ROOT = os.path.dirname(os.path.abspath(__file__))
+
+
+def test_fk4_no_e_fk5():
+
+    t = Table.read(os.path.join(ROOT, 'fk4_no_e_fk5.csv'), format='ascii')
+
+    for i in range(len(t)):
+
+        # Extract row
+        r = t[i]
+
+        # FK4 to FK5
+        c1 = FK4NoETermCoordinates(r['ra_in'], r['dec_in'],
+                                   unit=(u.degree, u.degree),
+                                   obstime=Time(r['obstime'], scale='utc'),
+                                   equinox=Time(r['equinox_fk4'], scale='utc'))
+        c2 = c1.transform_to(FK5Coordinates).precess_to(Time(r['equinox_fk5'], scale='utc'))
+
+        # Find difference
+        diff = vincenty_sphere_dist(c2.ra.radians, c2.dec.radians,
+                                    np.radians(r['ra_fk5']), np.radians(r['dec_fk5']))
+
+        assert np.degrees(diff) * 3600. < TOLERANCE
+
+        # FK5 to FK4
+        c1 = FK5Coordinates(r['ra_in'], r['dec_in'],
+                            unit=(u.degree, u.degree),
+                            obstime=Time(r['obstime'], scale='utc'),
+                            equinox=Time(r['equinox_fk5'], scale='utc'))
+        c2 = c1.transform_to(FK4NoETermCoordinates).precess_to(Time(r['equinox_fk4'], scale='utc'))
+
+        # Find difference
+        diff = vincenty_sphere_dist(c2.ra.radians, c2.dec.radians,
+                                    np.radians(r['ra_fk4']), np.radians(r['dec_fk4']))
+
+        assert np.degrees(diff) * 3600. < TOLERANCE
diff --git a/astropy/coordinates/tests/accuracy/test_galactic_fk4.py b/astropy/coordinates/tests/accuracy/test_galactic_fk4.py
new file mode 100644
index 0000000..eafba36
--- /dev/null
+++ b/astropy/coordinates/tests/accuracy/test_galactic_fk4.py
@@ -0,0 +1,48 @@
+import os
+
+import numpy as np
+
+from .... import units as u
+from ... import GalacticCoordinates, FK4Coordinates
+from ....time import Time
+from ....table import Table
+from ...angle_utilities import vincenty_sphere_dist
+
+TOLERANCE = 0.5  # arcseconds
+
+ROOT = os.path.dirname(os.path.abspath(__file__))
+
+
+def test_galactic_fk4():
+
+    t = Table.read(os.path.join(ROOT, 'galactic_fk4.csv'), format='ascii')
+
+    for i in range(len(t)):
+
+        # Extract row
+        r = t[i]
+
+        # FK4 to FK5
+        c1 = GalacticCoordinates(r['lon_in'], r['lat_in'],
+                                 unit=(u.degree, u.degree),
+                                 obstime=Time(r['obstime'], scale='utc'))
+        c2 = c1.transform_to(FK4Coordinates).precess_to(Time(r['equinox_fk4'], scale='utc'))
+
+        # Find difference
+        diff = vincenty_sphere_dist(c2.ra.radians, c2.dec.radians,
+                                    np.radians(r['ra_fk4']), np.radians(r['dec_fk4']))
+
+        assert np.degrees(diff) * 3600. < TOLERANCE
+
+        # FK5 to FK4
+        c1 = FK4Coordinates(r['lon_in'], r['lat_in'],
+                            unit=(u.degree, u.degree),
+                            obstime=Time(r['obstime'], scale='utc'),
+                            equinox=Time(r['equinox_fk4'], scale='utc'))
+        c2 = c1.transform_to(GalacticCoordinates)
+
+        # Find difference
+        diff = vincenty_sphere_dist(c2.l.radians, c2.b.radians,
+                                    np.radians(r['lon_gal']), np.radians(r['lat_gal']))
+
+        assert np.degrees(diff) * 3600. < TOLERANCE
diff --git a/astropy/coordinates/tests/accuracy/test_icrs_fk5.py b/astropy/coordinates/tests/accuracy/test_icrs_fk5.py
new file mode 100644
index 0000000..014c774
--- /dev/null
+++ b/astropy/coordinates/tests/accuracy/test_icrs_fk5.py
@@ -0,0 +1,48 @@
+import os
+
+import numpy as np
+
+from .... import units as u
+from ... import ICRSCoordinates, FK5Coordinates
+from ....time import Time
+from ....table import Table
+from ...angle_utilities import vincenty_sphere_dist
+
+TOLERANCE = 0.03  # arcseconds
+
+ROOT = os.path.dirname(os.path.abspath(__file__))
+
+
+def test_icrs_no_e_fk5():
+
+    t = Table.read(os.path.join(ROOT, 'icrs_fk5.csv'), format='ascii')
+
+    for i in range(len(t)):
+
+        # Extract row
+        r = t[i]
+
+        # FK4 to FK5
+        c1 = ICRSCoordinates(r['ra_in'], r['dec_in'],
+                             unit=(u.degree, u.degree),
+                             obstime=Time(r['obstime'], scale='utc'))
+        c2 = c1.transform_to(FK5Coordinates).precess_to(Time(r['equinox_fk5'], scale='utc'))
+
+        # Find difference
+        diff = vincenty_sphere_dist(c2.ra.radians, c2.dec.radians,
+                                    np.radians(r['ra_fk5']), np.radians(r['dec_fk5']))
+
+        assert np.degrees(diff) * 3600. < TOLERANCE
+
+        # FK5 to FK4
+        c1 = FK5Coordinates(r['ra_in'], r['dec_in'],
+                            unit=(u.degree, u.degree),
+                            obstime=Time(r['obstime'], scale='utc'),
+                            equinox=Time(r['equinox_fk5'], scale='utc'))
+        c2 = c1.transform_to(ICRSCoordinates)
+
+        # Find difference
+        diff = vincenty_sphere_dist(c2.ra.radians, c2.dec.radians,
+                                    np.radians(r['ra_icrs']), np.radians(r['dec_icrs']))
+
+        assert np.degrees(diff) * 3600. < TOLERANCE
diff --git a/astropy/coordinates/tests/test_api.py b/astropy/coordinates/tests/test_api.py
new file mode 100644
index 0000000..d24a9f7
--- /dev/null
+++ b/astropy/coordinates/tests/test_api.py
@@ -0,0 +1,785 @@
+# -*- coding: utf-8 -*-
+# Licensed under a 3-clause BSD style license - see LICENSE.rst
+from __future__ import print_function
+
+from numpy import testing as npt
+from ...tests.helper import pytest
+raises = pytest.raises
+
+from ... import units as u
+from ..errors import *
+
+
+try:
+    import scipy
+except ImportError:
+    HAS_SCIPY = False
+else:
+    HAS_SCIPY = True
+
+# notes from the original api document:
+'''
+The emphasis of this package is that common tasks should
+be performed in as simple and intuitive manner as possible.
+Complex or unusual tasks are still possible, but should not
+interfere with the simplicity of common tasks.
+
+One design principle is that objects should silently accept parameters
+of any data type that can unambiguously be determined. Where data types
+are accepted, they should be specified as constants, not as strings.
+If an unknown unit is specified as a string, the code certainly
+cannot handle it.
+
+A note on units: Units (as with everything else in Python) are objects.
+Any instance of a "unit" keyword will only accept "Unit" objects, not
+bare strings. All commonly used units will be predefined in astropy.units
+(which is still under development). The exact syntax might change,
+but the ideas will not. Units may be specified as part of a string in
+an initializer (subscribing to the "accept and parse values that are
+unambiguous to a human reader" philosophy), but will not be accepted as
+a bare string anywhere else.
+
+On arrays: The interface outlined here only accepts scalar angles (and hence
+coordinates) - we will likely later expand it to allow arrays to be stored in
+these objects, but only after the scalar interfaces is complete and working.
+'''
+
+
+def test_create_angles():
+    """
+    Tests creating and accessing Angle objects
+    """
+    from .. import Angle
+
+    ''' The "angle" is a fundamental object. The internal
+    representation is stored in radians, but this is transparent to the user.
+    Units *must* be specified rather than a default value be assumed. This is
+    as much for self-documenting code as anything else.
+
+    Angle objects simply represent a single angular coordinate. More specific
+    angular coordinates (e.g. RA, Dec) are subclasses of Angle.'''
+
+    a1 = Angle(54.12412, unit=u.degree)
+    a2 = Angle("54.12412", unit=u.degree)
+    a3 = Angle("54:07:26.832", unit=u.degree)
+    a4 = Angle("54.12412 deg")
+    a5 = Angle("54.12412 degrees")
+    a6 = Angle("54.12412°") # because we like Unicode
+    a7 = Angle((54, 7, 26.832), unit=u.degree)
+    # (deg,min,sec) *tuples* are acceptable, but lists/arrays are *not*
+    # because of the need to eventually support arrays of coordinates
+    with raises(NotImplementedError):
+        Angle([54, 7, 26.832], unit=u.degree)
+
+    a10 = Angle(3.60827466667, unit=u.hour)
+    a11 = Angle("3:36:29.7888000120", unit=u.hour)
+    a12 = Angle((3, 36, 29.7888000120), unit=u.hour)  # *must* be a tuple
+
+    Angle(0.944644098745, unit=u.radian)
+
+    with raises(UnitsError):
+        Angle(54.12412)
+        #raises an exception because this is ambiguous
+
+    with raises(ValueError):
+    	a13 = Angle(12.34, unit="not a unit")
+
+    a14 = Angle("12h43m32") # no trailing 's', but unambiguous
+
+    a15 = Angle("5h4m3s") # single digits, no decimal
+
+    #ensure the above angles that should match do
+    a1 == a2 == a3 == a4 == a5 == a6 == a7
+    npt.assert_almost_equal(a1.radians, a2.radians)
+    npt.assert_almost_equal(a2.degrees, a3.degrees)
+    npt.assert_almost_equal(a3.radians, a4.radians)
+    npt.assert_almost_equal(a4.radians, a5.radians)
+    npt.assert_almost_equal(a5.radians, a6.radians)
+    npt.assert_almost_equal(a6.radians, a7.radians)
+    #assert a10 == a11 == a12
+
+    # check for illegal ranges / values
+    with raises(IllegalSecondError):
+        a = Angle("12 32 99", unit=u.degree)
+
+    with raises(IllegalMinuteError):
+        a = Angle("12 99 23", unit=u.degree)
+
+    with raises(IllegalSecondError):
+        a = Angle("12 32 99", unit=u.hour)
+
+    with raises(IllegalMinuteError):
+        a = Angle("12 99 23", unit=u.hour)
+
+    with raises(IllegalHourError):
+        a = Angle("99 25 51.0", unit=u.hour)
+
+    with raises(ValueError):
+        a = Angle("12 25 51.0xxx", unit=u.hour)
+
+    with raises(ValueError):
+        a = Angle("12h34321m32.2s")
+
+    assert a1 is not None
+
+def test_angle_ops():
+    """
+    Tests operations on Angle objects
+    """
+    from .. import Angle
+    import numpy.testing as npt
+
+    '''
+    Angles can be added and subtracted. Multiplication and division by
+    a scalar is also permitted. A negative operator is also valid.
+    All of these operate in a single dimension. Attempting to
+    multiply or divide two Angle objects will raise an exception.
+    '''
+    a1 = Angle(3.60827466667, unit=u.hour)
+    a2 = Angle("54:07:26.832", unit=u.degree)
+    a1 + a2  # creates new Angle object
+    a1 - a2
+    -a1
+
+    # division and multiplication have no unambiguous meaning here
+    with raises(NotImplementedError):
+        a1 / a2
+
+    with raises(NotImplementedError):
+        a1 * a2
+
+    (a1 * 2).hours == 2 * 3.60827466667
+    (a1 / 3.123456).hours == 3.60827466667 / 3.123456
+
+    # commutativity
+    (2 * a1).hours == (a1 * 2).hours
+
+    a3 = Angle(a1)  # makes a *copy* of the object, but identical content as a1
+    npt.assert_almost_equal(a1.radians, a3.radians)
+    assert a1 is not a3
+
+    a4 = abs(-a1)
+    assert a4.radians == a1.radians
+
+    a5 = Angle(5.0, unit=u.hour)
+    assert a5 > a1
+    assert a5 >= a1
+    assert a1 < a5
+    assert a1 <= a5
+
+def test_angle_bounds():
+    """
+    Tests setting and obeying of bounds for Angle objects, as well as
+    how operations interact with bounds
+    """
+    from .. import Angle, RangeError, BoundsError
+    import numpy.testing as npt
+
+    '''
+    By default the Angle object can accept any value, but will return
+    values in [-360,360] (retaining the sign that was specified).
+
+    One can also set artificial bounds for custom applications and range
+    checking. As Angle objects are intended to be immutable (the angle value
+    anyway), this provides a bound check upon creation. The units given in the
+    `bounds` keyword must match the units specified in the scalar.
+    '''
+
+    a1 = Angle(13343, unit=u.degree)
+    npt.assert_almost_equal(a1.degrees, 23)
+
+    a2 = Angle(-50, unit=u.degree)
+    assert a2.degrees == -50
+
+    a3 = Angle(-361, unit=u.degree)
+    npt.assert_almost_equal(a3.degrees, -1)
+
+    # custom bounds
+
+    with raises(BoundsError):
+        Angle(66, unit=u.degree, bounds=(-45, 45))
+
+    a4 = Angle(390, unit=u.degree, bounds=(-75, 75))
+    npt.assert_almost_equal(a4.degrees, 30)
+    # no BoundsError because while 390>75, 30 is within the bounds
+
+    a5 = Angle(390, unit=u.degree, bounds=(-720, 720))
+    a5.degrees == 390
+
+    a6 = Angle(1020, unit=u.degree, bounds=None)
+    a6.degrees == 1020
+
+    # bounds and operations
+
+    with raises(ValueError):
+        a4 + a5
+        # ValueError - the bounds don't match
+
+    a7 = a4 + a4
+    assert a7.bounds == (-75, 75)
+    # if the bounds match, there is no error and the bound is kept
+    npt.assert_almost_equal(a7.degrees, 60)
+
+    a8 = a4 - a4
+    assert a8.bounds == (-75, 75)
+    # To get the default bounds back, you need to create a new object with the
+    # equivalent angle
+    Angle(a4.degrees + a4.degrees, unit=u.degree)
+
+    a9 = Angle(a4.degrees + a5.degrees, unit=u.degree, bounds=[-180, 180])
+    npt.assert_almost_equal(a9.degrees, 60)
+    # if they don't match and you want to combine, just re-assign the bounds
+    # yourself
+
+    # bounds of None can also be operated on without complaint
+    a10 = a6 - a6
+    a10.degrees == 0
+
+    with raises(AttributeError):
+	    a10.bounds = (0,34)
+
+def test_angle_convert():
+    """
+    Test unit conversion of Angle objects
+    """
+
+    from .. import Angle
+    import numpy.testing as npt
+
+    angle = Angle("54.12412", unit=u.degree)
+
+    npt.assert_almost_equal(angle.hours, 3.60827466667)
+    npt.assert_almost_equal(angle.radians, 0.944644098745)
+    npt.assert_almost_equal(angle.degrees, 54.12412)
+
+    assert isinstance(angle.hms, tuple)
+    assert angle.hms[0] == 3
+    assert angle.hms[1] == 36
+    npt.assert_almost_equal(angle.hms[2], 29.78879999999947)
+
+    assert isinstance(angle.dms, tuple)
+    assert angle.dms[0] == 54
+    assert angle.dms[1] == 7
+    npt.assert_almost_equal(angle.dms[2], 26.831999999992036)
+
+    assert isinstance(angle.dms[0], float)
+    assert isinstance(angle.hms[0], float)
+
+
+def test_angle_formatting():
+    """
+    Tests string formatting for Angle objects
+    """
+    from .. import Angle
+
+    '''
+    The string method of Angle has this signature:
+    def string(self, unit=DEGREE, decimal=False, sep=" ", precision=5,
+               pad=False):
+
+    The "decimal" parameter defaults to False since if you need to print the
+    Angle as a decimal, there's no need to use the "format" method (see
+    above).
+    '''
+
+    angle = Angle("54.12412", unit=u.degree)
+
+    #__str__ is the default `format`
+    assert str(angle) == angle.format()
+
+    res = 'Angle as HMS: 3h36m29.78880s'
+    assert "Angle as HMS: {0}".format(angle.format(unit=u.hour)) == res
+
+    res = 'Angle as HMS: 3:36:29.78880'
+    assert "Angle as HMS: {0}".format(angle.format(unit=u.hour, sep=":")) == res
+
+    res = 'Angle as HMS: 3:36:29.79'
+    assert "Angle as HMS: {0}".format(angle.format(unit=u.hour, sep=":",
+                                      precision=2)) == res
+
+    # Note that you can provide one, two, or three separators passed as a
+    # tuple or list
+
+    res = 'Angle as HMS: 3h36m29.7888s'
+    assert "Angle as HMS: {0}".format(angle.format(unit=u.hour,
+                                                   sep=("h", "m", "s"),
+                                                   precision=4)) == res
+
+    res = 'Angle as HMS: 3-36|29.7888'
+    assert "Angle as HMS: {0}".format(angle.format(unit=u.hour, sep=["-", "|"],
+                                                   precision=4)) == res
+
+    res = 'Angle as HMS: 3-36-29.7888'
+    assert "Angle as HMS: {0}".format(angle.format(unit=u.hour, sep="-",
+                                                    precision=4)) == res
+
+    res = 'Angle as HMS: 03h36m29.7888s'
+    assert "Angle as HMS: {0}".format(angle.format(unit=u.hour, precision=4,
+                                                  pad=True)) == res
+
+    # Same as above, in degrees
+
+    angle = Angle("3 36 29.78880", unit=u.degree)
+
+    res = 'Angle as DMS: 3d36m29.78880s'
+    assert "Angle as DMS: {0}".format(angle.format(unit=u.degree)) == res
+
+    res = 'Angle as DMS: 3:36:29.78880'
+    assert "Angle as DMS: {0}".format(angle.format(unit=u.degree, sep=":")) == res
+
+    res = 'Angle as DMS: 3:36:29.79'
+    assert "Angle as DMS: {0}".format(angle.format(unit=u.degree, sep=":",
+                                      precision=2)) == res
+
+    # Note that you can provide one, two, or three separators passed as a
+    # tuple or list
+
+    res = 'Angle as DMS: 3d36m29.7888s'
+    assert "Angle as DMS: {0}".format(angle.format(unit=u.degree,
+                                                   sep=("d", "m", "s"),
+                                                   precision=4)) == res
+
+    res = 'Angle as DMS: 3-36|29.7888'
+    assert "Angle as DMS: {0}".format(angle.format(unit=u.degree, sep=["-", "|"],
+                                                   precision=4)) == res
+
+    res = 'Angle as DMS: 3-36-29.7888'
+    assert "Angle as DMS: {0}".format(angle.format(unit=u.degree, sep="-",
+                                                    precision=4)) == res
+
+    res = 'Angle as DMS: 03d36m29.7888s'
+    assert "Angle as DMS: {0}".format(angle.format(unit=u.degree, precision=4,
+                                                  pad=True)) == res
+
+    res = 'Angle as rad: 0.062976radian'
+    assert "Angle as rad: {0}".format(angle.format(unit=u.radian)) == res
+
+    res = 'Angle as rad decimal: 0.062976'
+    assert "Angle as rad decimal: {0}".format(angle.format(unit=u.radian, decimal=True)) == res
+
+
+    # check negative angles
+
+    angle = Angle(-1.23456789, unit=u.degree)
+
+    assert angle.format() == '-1d14m04.44440s'
+    assert angle.format(unit=u.hour) == '-0h04m56.29629s'
+    assert angle.format(unit=u.radian, decimal=True) == '-0.021547'
+
+def test_angle_format_roundtripping():
+    """
+    Ensures that the string represtation of an angle can be used to create a
+    new valid Angle.
+    """
+    from .. import Angle, RA, Dec
+
+    a1 = Angle(0, unit=u.radian)
+    a2 = Angle(10, unit=u.degree)
+    a3 = Angle(0.543, unit=u.degree)
+    a4 = Angle('1d2m3.4s')
+
+    assert Angle(str(a1)).degrees == a1.degrees
+    assert Angle(str(a2)).degrees == a2.degrees
+    assert Angle(str(a3)).degrees == a3.degrees
+    assert Angle(str(a4)).degrees == a4.degrees
+
+    #also check RA/Dec
+    ra = RA('1h2m3.4s')
+    dec = Dec('1d2m3.4s')
+
+    assert Angle(str(ra)).degrees == ra.degrees
+    assert Angle(str(dec)).degrees == dec.degrees
+
+
+def test_radec():
+    """
+    Tests creation/operations of RA and Dec objects
+    """
+    from .. import RA, Dec, Angle
+    from ...time import Time
+
+    '''
+    RA and Dec are objects that are subclassed from Angle. As with Angle, RA
+    and Dec can parse any unambiguous format (tuples, formatted strings, etc.).
+
+    The intention is not to create an Angle subclass for every possible
+    coordinate object (e.g. galactic l, galactic b). However, equatorial RA/dec
+    are so prevalent in astronomy that it's worth creating ones for these
+    units. They will be noted as "special" in the docs and use of the just the
+    Angle class is to be used for other coordinate systems.
+    '''
+
+    with raises(UnitsError):
+        ra = RA("4:08:15.162342")  # error - hours or degrees?
+    with raises(UnitsError):
+        ra = RA("-4:08:15.162342")
+
+    # the "smart" initializer allows >24 to automatically do degrees, but the
+    #Angle-based one does not
+    #TODO: adjust in 0.3 for whatever behavior is decided on
+
+    #ra = RA("26:34:15.345634")  # unambiguous b/c hours don't go past 24
+    #npt.assert_almost_equal(ra.degrees, 26.570929342)
+    with raises(UnitsError):
+        ra = RA("26:34:15.345634")
+
+    #ra = RA(68)
+    with raises(UnitsError):
+        ra = RA(68)
+
+    with raises(UnitsError):
+        ra = RA(12)
+
+    with raises(ValueError):
+        ra = RA("garbage containing a d and no units")
+
+    ra = RA("12h43m23s")
+    npt.assert_almost_equal(ra.hours, 12.7230555556)
+
+    ra = RA((56, 14, 52.52), unit=u.degree)      # can accept tuples
+    #TODO: again, fix based on >24 behavior
+    #ra = RA((56,14,52.52))
+    with raises(ValueError):
+        ra = RA((56, 14, 52.52))
+    with raises(ValueError):
+        ra = RA((12, 14, 52))  # ambiguous w/o units
+    ra = RA((12, 14, 52), unit=u.hour)
+
+    with raises(NotImplementedError):
+        ra = RA([56, 64, 52.2], unit=u.degree)  # ...but not arrays (yet)
+
+    # Units can be specified
+    ra = RA("4:08:15.162342", unit=u.hour)
+
+    #TODO: this was the "smart" initializer behavior - adjust in 0.3 appropriately
+    ## Where RA values are commonly found in hours or degrees, declination is
+    ## nearly always specified in degrees, so this is the default.
+    #dec = Dec("-41:08:15.162342")
+    with raises(UnitsError):
+        dec = Dec("-41:08:15.162342")
+    dec = Dec("-41:08:15.162342", unit=u.degree)  # same as above
+
+    # The RA and Dec objects have bounds hard-coded at (0,360) and (-90,90)
+    # degrees, respectively.
+    assert ra.bounds == (0, 360)
+    with raises(AttributeError):
+        ra.bounds = (-45, 45)
+    assert dec.bounds == (-90, 90)
+    with raises(AttributeError):
+        dec.bounds = (-45, 45)
+
+    #RA objects can also compute hour angle and local siderial times
+    ra = RA("1:00:00", unit=u.hour)
+    ha1 = ra.hour_angle(Angle(1.5, u.hour))
+    assert isinstance(ha1, Angle)
+    npt.assert_almost_equal(ha1.hours, .5)
+    ha2 = ra.hour_angle(Time('2012-1-1 3:00:00', scale='utc'))
+    npt.assert_almost_equal(ha2.hours, 23.125)
+
+    lst = ra.lst(Angle(1.5, u.hour))
+    assert isinstance(lst, Angle)
+    npt.assert_almost_equal(lst.hours, 2.5)
+
+def test_create_coordinate():
+    """
+    Tests creation and basic attributes of coordinates
+    """
+
+    '''
+    A coordinate marks a position on the sky. This is an object that contains
+    two Angle objects. There are a wide array of coordinate systems that should
+    be implemented, and it will be easy to subclass to create custom user-made
+    coordinates with conversions to standard coordinates.
+    '''
+
+    from .. import Angle, RA, Dec, ICRSCoordinates, GalacticCoordinates
+    from .. import HorizontalCoordinates
+    import numpy.testing as npt
+
+    ra = RA("4:08:15.162342", unit=u.hour)
+    dec = Dec("-41:08:15.162342", unit=u.degree)
+
+    # ra and dec are RA and Dec objects, or Angle objects
+    c = ICRSCoordinates(ra, dec)
+    c = ICRSCoordinates(Angle(4.137545095, u.hour), Angle(-41.137545095, u.degree))
+
+    c = ICRSCoordinates("54.12412 deg", "-41:08:15.162342 deg")
+    assert isinstance(c.dec, Dec) # dec is a Dec object
+
+    npt.assert_almost_equal(dec.degrees, -41.137545095)
+
+    # We should be really robust in what we accept.
+    with raises(ValueError):
+        c = ICRSCoordinates("12 34 56  -56 23 21") # ambiguous
+
+    with raises(TypeError):
+	    c = ICRSCoordinates() # not allowed
+
+    c = ICRSCoordinates(ra="12 43 12", dec=dec, unit=(u.hour, u.hour))
+
+    with raises(TypeError):
+        c = ICRSCoordinates(ra="12 43 12", unit=(u.hour,))
+
+    with raises(TypeError):
+        c = ICRSCoordinates(ra="12h43m32", b="12:32:43")
+
+    with raises(TypeError):
+        c = ICRSCoordinates(ra="12h43m32")
+
+    with raises(TypeError):
+        c = ICRSCoordinates(dec="12 32 54")
+
+    # It would be convenient to accept both (e.g. ra, dec) coordinates as a
+    # single string in the initializer. This can lead to ambiguities
+    # particularly when both are different units. The solution is to accept a
+    # sequence for the "unit" keyword  that one would expect to sent to Angle.
+    # This must be a 2-sequence with the two elements' units.
+    ICRSCoordinates('4 23 43.43  +23 45 12.324', unit=(u.hour, u.degree))
+
+    # If one of them is None, try to guess for unambiguous cases
+    ICRSCoordinates('12h43m32 +23:45:12.324', unit=(None, u.degree))
+
+    # unit=None is the same as unit=(None, None)
+    ICRSCoordinates('12h43m32 +23d45m12.324s', unit=None)
+
+
+    # Other types of coordinate systems have their own classes
+    l = Angle(123.4, unit=u.degree)
+    b = Angle(76.5, unit=u.degree)
+    c = GalacticCoordinates(l, b)  # only accepts Angle objects *not RA/Dec
+    with raises(TypeError):
+        GalacticCoordinates(ra, dec)
+
+    assert isinstance(c.l, Angle)  # *not* RA or Dec
+    assert isinstance(c.b, Angle)  # *not* RA or Dec
+
+    #some coordinates require an equinox - this is given as an astropy.time.Time
+    from ...time import Time
+
+    alt = Angle(20.5, unit=u.degree)
+    az = Angle(45, unit=u.degree)
+    timeobj = Time('J2000', scale='utc')
+    HorizontalCoordinates(alt, az, equinox=timeobj)
+
+    #some also have an option for an observation time
+    ICRSCoordinates(12, 13, unit=(u.hour, u.degree), obstime=timeobj)
+
+    #passing in a non-time object give a TypeError
+    with raises(TypeError):
+        ICRSCoordinates(12, 13, unit=(u.hour, u.degree), obstime=2000.)
+
+
+
+def test_convert_api():
+    """
+    Tests the basic coordinate conversion functionality.
+    """
+
+    from .. import Angle, RA, Dec, ICRSCoordinates, GalacticCoordinates, HorizontalCoordinates
+    from ..transformations import coordinate_alias, transform_function, master_transform_graph
+
+    '''
+    Coordinate conversion occurs on-demand internally
+    '''
+
+    ra = RA("4:08:15.162342", unit=u.hour)
+    dec = Dec("-41:08:15.162342", unit=u.degree)
+    c = ICRSCoordinates(ra=ra, dec=dec)
+
+    npt.assert_almost_equal(c.galactic.l.degrees, -114.71902, 5)
+    assert isinstance(c.galactic.b, Angle)
+    npt.assert_almost_equal(c.galactic.b.degrees, -47.554501, 5)
+
+    # can also explicitly specify a coordinate class to convert to
+    gal = c.transform_to(GalacticCoordinates)
+
+    # can still convert back to equatorial using the shorthand
+    assert gal.icrs.ra.format(unit=u.hour, sep=":",
+                              precision=2) == '4:08:15.16'
+
+    with raises(ConvertError):
+        # there's no way to convert to alt/az without a specified location
+        c.transform_to(HorizontalCoordinates)
+
+    # users can specify their own coordinates and conversions
+    @coordinate_alias('my_coord')
+    class CustomCoordinates(ICRSCoordinates):
+        pass
+
+    @transform_function(ICRSCoordinates, CustomCoordinates)
+    def icrs_to_custom(icrs_coo):
+        return CustomCoordinates(icrs_coo.ra.degrees,
+                                 icrs_coo.dec.degrees + 2.5,
+                                 unit=(u.degree, u.degree))
+
+    try:
+        # allows both ways of converting
+        mycoord1 = c.my_coord
+        mycoord2 = c.transform_to(CustomCoordinates)
+
+        assert isinstance(mycoord1, CustomCoordinates)
+        assert isinstance(mycoord2, CustomCoordinates)
+    finally:
+        #be sure to remove the registered transform
+        master_transform_graph._graph[ICRSCoordinates][CustomCoordinates].unregister()
+
+
+def test_proj_separations():
+    """
+    Test angular separation functionality
+    """
+
+    from .. import ICRSCoordinates, GalacticCoordinates, AngularSeparation, coordinate_alias
+
+    '''
+    Angular separations between two points on a sphere are supported via the
+    `separation` method.
+    '''
+
+    c1 = ICRSCoordinates(ra=0, dec=0, unit=(u.degree, u.degree))
+    c2 = ICRSCoordinates(ra=0, dec=1, unit=(u.degree, u.degree))
+
+    sep = c2.separation(c1)
+    #returns an AngularSeparation object (a subclass of Angle)
+    assert isinstance(sep, AngularSeparation)
+
+    assert sep.degrees == 1
+    assert sep.arcmins == 60.
+
+    # these operations have ambiguous interpretations for points on a sphere
+    with raises(TypeError):
+        c1 + c2
+    with raises(TypeError):
+        c1 - c2
+
+    ngp = GalacticCoordinates(l=0, b=90, unit=(u.degree, u.degree))
+    ncp = ICRSCoordinates(ra=0, dec=90, unit=(u.degree, u.degree))
+
+    # if there is a defined conversion between the relevant coordinate systems,
+    # it will be automatically performed to get the right angular separation
+    npt.assert_almost_equal(ncp.separation(ngp.icrs).degrees, ncp.separation(ngp).degrees)
+
+    # distance from the north galactic pole to celestial pole
+    npt.assert_almost_equal(ncp.separation(ngp.icrs).degrees, 62.8716627659)
+
+
+    @coordinate_alias('my_coord2')
+    class CustomCoordinate(ICRSCoordinates):
+        pass  # does not specify a coordinate transform
+
+    c4 = CustomCoordinate(0, 0, unit=(u.degree, u.degree))
+    with raises(ConvertError):
+        # raises an error if no conversion from the custom to equatorial
+        # coordinates is available
+        c4.separation(c1)
+
+
+def test_distances():
+    """
+    Tests functionality for Coordinate class distances and cartesian
+    transformations.
+    """
+    from .. import Distance, ICRSCoordinates, GalacticCoordinates, CartesianPoints
+    from ...cosmology import WMAP5, WMAP7
+
+    '''
+    Distances can also be specified, and allow for a full 3D definition of a
+    coordinate.
+    '''
+
+    #try all the different ways to initialize a Distance
+    distance = Distance(12, u.parsec)
+    d2 = Distance(40, unit=u.au)
+    d3 = Distance(value=5, unit=u.kpc)
+
+    # need to provide a unit
+    with raises(UnitsError):
+        Distance(12)
+
+    # standard units are pre-defined
+    npt.assert_almost_equal(distance.lightyear, 39.13876728075561)
+    npt.assert_almost_equal(distance.km, 370281309776063.0)
+
+    # Coordinate objects can be assigned a distance object, giving them a full
+    # 3D position
+    c = GalacticCoordinates(l=158.558650, b=-43.350066, unit=(u.degree, u.degree))
+    c.distance = Distance(12, u.parsec)
+
+    #can also set distances using tuple-format
+    c.distance = (12, u.parsec)
+    c.distance.parsec = 12
+
+    #or initialize distances via redshifts - this is actually tested in the
+    #function below that checks for scipy. This is kept here as an example
+    #c.distance = Distance(z=0.2)  # uses current cosmology
+    #with whatever your preferred cosmology may be
+    #c.distance = Distance(z=0.2, cosmology=WMAP5)
+
+
+    # Coordinate objects can be initialized with a distance using special
+    # syntax
+    #TODO: use this commented line once quantity is in
+    #c1 = GalacticCoordinates(l=158.558650, b=-43.350066, unit=u.degree, distance=12 * u.kpc)
+    c1 = GalacticCoordinates(l=158.558650, b=-43.350066,
+        unit=(u.degree, u.degree), distance=Distance(12, u.kpc))
+
+    # Coordinate objects can be instantiated with cartesian coordinates
+    # Internally they will immediately be converted to two angles + a distance
+    c2 = GalacticCoordinates(x=2, y=4, z=8, unit=u.parsec)
+
+    sep12 = c1.separation_3d(c2)
+    # returns a *3d* distance between the c1 and c2 coordinates
+    # not that this does *not*
+    assert isinstance(sep12, Distance)
+    npt.assert_almost_equal(sep12.pc, 12005.784163916317, 10)
+
+    '''
+    All spherical coordinate systems with distances can be converted to
+    cartesian coordinates.
+    '''
+
+    (x, y, z) = (c2.x, c2.y, c2.z)
+    #this only computes the CartesianPoints *once*, and then caches it
+    npt.assert_almost_equal(x, 2)
+    npt.assert_almost_equal(y, 4)
+    npt.assert_almost_equal(z, 8)
+
+    cpt = c2.cartesian
+    assert isinstance(cpt, CartesianPoints)
+    npt.assert_almost_equal(cpt.x, 2)
+    npt.assert_almost_equal(cpt.y, 4)
+    npt.assert_almost_equal(cpt.z, 8)
+
+    # with no distance, the unit sphere is assumed when converting to cartesian
+    c3 = GalacticCoordinates(l=158.558650, b=-43.350066, unit=(u.degree, u.degree), distance=None)
+    unitcart = c3.cartesian
+    npt.assert_almost_equal((unitcart.x**2 + unitcart.y**2 + unitcart.z**2)**0.5, 1.0)
+
+    # CartesianPoints objects can be added and subtracted, which are
+    # vector/elementwise they can also be given as arguments to a coordinate
+    # system
+    csum = ICRSCoordinates(c1.cartesian + c2.cartesian)
+
+    npt.assert_almost_equal(csum.x, -8.12016610185)
+    npt.assert_almost_equal(csum.y, 3.19380597435)
+    npt.assert_almost_equal(csum.z, -8.2294483707)
+    npt.assert_almost_equal(csum.ra.degrees, 158.529401774)
+    npt.assert_almost_equal(csum.dec.degrees, -43.3235825777)
+    npt.assert_almost_equal(csum.distance.kpc, 11.9942200501)
+
+
+ at pytest.mark.skipif('not HAS_SCIPY')
+def test_distances_scipy():
+    """
+    The distance-related tests that require scipy due to the cosmology
+    module needing scipy integration routines
+    """
+    from .. import Distance
+    from ...cosmology import WMAP5
+
+    #try all the different ways to initialize a Distance
+    d4 = Distance(z=0.23)  # uses default cosmology - as of writing, WMAP7
+    d5 = Distance(z=0.23, cosmology=WMAP5)
+
+    assert abs(d4.z - 0.23) < 1e-8  # redshift, assuming "current" cosmology
+    assert abs(d5.compute_z(WMAP5) - 0.23) < 1e-8 # specifying a cosmology possible
\ No newline at end of file
diff --git a/astropy/coordinates/tests/test_arrays.py b/astropy/coordinates/tests/test_arrays.py
new file mode 100644
index 0000000..fe4fe0e
--- /dev/null
+++ b/astropy/coordinates/tests/test_arrays.py
@@ -0,0 +1,27 @@
+# -*- coding: utf-8 -*-
+# Licensed under a 3-clause BSD style license - see LICENSE.rst
+from __future__ import print_function, division
+
+from ...tests.helper import pytest
+
+import numpy as np
+from numpy import testing as npt
+
+from ... import units as u
+
+
+def test_angle_arrays():
+    """
+    Test arrays values with Angle objects.
+    """
+    from .. import Angle
+
+    # Tests incomplete
+    with pytest.raises(NotImplementedError):
+        a1 = Angle([0, 45, 90, 180, 270, 360], unit=u.degree)
+
+    with pytest.raises(NotImplementedError):
+        a2 = Angle(np.array([0, 45, 90, 180, 270, 360]), unit=u.degree)
+
+    with pytest.raises(NotImplementedError):
+        a3 = Angle(["12 degrees", "3 hours", "5 deg", "4rad"])
diff --git a/astropy/coordinates/tests/test_sphere_ang_dists.py b/astropy/coordinates/tests/test_sphere_ang_dists.py
new file mode 100644
index 0000000..a6aa8d4
--- /dev/null
+++ b/astropy/coordinates/tests/test_sphere_ang_dists.py
@@ -0,0 +1,76 @@
+# -*- coding: utf-8 -*-
+# Licensed under a 3-clause BSD style license - see LICENSE.rst
+from __future__ import print_function
+
+from ...tests.helper import pytest
+
+from .. import angle_utilities
+
+distance_funcs = [angle_utilities.small_angle_sphere_dist,
+                  angle_utilities.simple_sphere_dist,
+                  angle_utilities.haversine_sphere_dist,
+                  angle_utilities.haversine_atan_sphere_dist,
+                  angle_utilities.vincenty_sphere_dist,
+                 ]
+
+# lat1, lon1, lat2, lon2 in degrees
+coords = [(0, 0, 1, 0),
+          (0, 0, 0, 10),
+          (0, 0, 0, 90),
+          (0, 0, 0, 180),
+          (45, 0, -45, 0),
+          (60, 0, -30, 0),
+          (-15, -135, 15, 45),
+          (-89, 100, 89, -80),
+          (0, 0, 0, 0),
+          (0, 0, 1. / 60., 1. / 60.)
+         ]
+correct_seps = [1, 10, 90, 180, 90, 90, 180, 180, 0, 0.023570225877234643]
+correctness_margin = 2e-10
+
+# set this to a numer to run the timing tests and trigger a failure so stdout is
+# read back in pytest - the number gives the number of iterations
+dotiming = False
+
+paramsets = []
+for coord, coorsep in zip(coords, correct_seps):
+    for df in distance_funcs:
+        paramsets.append((coord, coorsep, df))
+
+
+ at pytest.mark.parametrize(('coord', 'correctsep', 'dfunc'), paramsets)
+def test_2dseparations(coord, correctsep, dfunc):
+    """
+    A variety of tests to examine how close the various sphereical
+    distance/great circle measurements are from the expectations
+    """
+    from time import time
+    from math import fabs, radians, degrees
+
+    lat1, lon1, lat2, lon2 = coord
+
+    print('distance function', dfunc)
+    print('({0},{1}) - ({2},{3})'.format(lon1, lat1, lon2, lat2))
+    print('Correct separation', correctsep)
+
+    inputs = (radians(lon1), radians(lat1), radians(lon2), radians(lat2))
+    sep = degrees(dfunc(*inputs))
+    print('Reported:', sep)
+    print('Deviation from correct:', sep - correctsep)
+
+    if dotiming:
+        starttime = time()
+        for i in range(int(dotiming)):
+            dfunc(*inputs)
+        endtime = time()
+        dt = endtime - starttime
+        print('{0} in {1} sec'.format(int(dotiming), dt))
+        print('{0} sec per execution'.format(dt / float(int(dotiming))))
+        assert False  # Triggers py.test failures so we can see the timings
+
+    #a few cases are known to fail because of bad approximations - let them fail
+    if dfunc is angle_utilities.small_angle_sphere_dist:
+        if fabs(lat2 - lat1) > 1 and fabs(lon2 - lon1) > 1:  # radians
+            pytest.xfail('Small angle approximation fails for large angles')
+
+    assert fabs(sep - correctsep) < correctness_margin
diff --git a/astropy/coordinates/tests/test_transformations.py b/astropy/coordinates/tests/test_transformations.py
new file mode 100644
index 0000000..f6a7945
--- /dev/null
+++ b/astropy/coordinates/tests/test_transformations.py
@@ -0,0 +1,306 @@
+# -*- coding: utf-8 -*-
+# Licensed under a 3-clause BSD style license - see LICENSE.rst
+from __future__ import print_function, division
+
+import numpy as np
+from numpy import testing as npt
+
+from ... import units as u
+from ..distances import Distance
+from .. import transformations as t
+from ..builtin_systems import ICRSCoordinates, FK5Coordinates, FK4Coordinates, FK4NoETermCoordinates
+from ..builtin_systems import GalacticCoordinates
+from ...tests.helper import pytest
+
+
+
+#Coordinates just for these tests. TODO: expunge
+class TestCoo1(ICRSCoordinates):
+    pass
+
+
+class TestCoo2(ICRSCoordinates):
+    pass
+
+
+def test_transform_classes():
+    """
+    Tests the class-based/OO syntax for creating transforms
+    """
+    t.FunctionTransform(TestCoo1, TestCoo2,
+        lambda c: TestCoo2(c.ra.radians, c.dec.radians, unit=(u.radian, u.radian)))
+
+    c1 = TestCoo1(1, 2, unit=(u.radian, u.radian))
+    c1._make_cart()
+    c2 = c1.transform_to(TestCoo2)
+    npt.assert_almost_equal(c2.ra.radians, 1)
+    npt.assert_almost_equal(c2.dec.radians, 2)
+
+    def matfunc(coo):
+        return [[1, 0, 0],
+                [0, coo.ra.degrees, 0],
+                [0, 0, 1]]
+    t.DynamicMatrixTransform(TestCoo1, TestCoo2, matfunc)
+
+    c3 = TestCoo1(1, 2, unit=(u.degree, u.degree))
+    c3._make_cart()
+    c4 = c3.transform_to(TestCoo2)
+
+    npt.assert_almost_equal(c4.ra.degrees, 1)
+    npt.assert_almost_equal(c4.ra.degrees, 1)
+
+
+def test_transform_decos():
+    """
+    Tests the decorator syntax for creating transforms
+    """
+    c1 = TestCoo1(1, 2, unit=(u.degree, u.degree))
+
+    @t.transform_function(TestCoo1, TestCoo2)
+    def trans(coo1):
+        return TestCoo2(coo1.ra.radians, coo1.dec.radians * 2, unit=(u.radian, u.radian))
+
+    c1._make_cart()
+    c2 = c1.transform_to(TestCoo2)
+    npt.assert_almost_equal(c2.ra.degrees, 1)
+    npt.assert_almost_equal(c2.dec.degrees, 4)
+
+    c3 = TestCoo1(x=1, y=1, z=2, unit=u.pc)
+
+    @t.static_transform_matrix(TestCoo1, TestCoo2)
+    def matrix():
+        return [[2, 0, 0],
+                [0, 1, 0],
+                [0, 0, 1]]
+
+    c3._make_cart()
+    c4 = c3.transform_to(TestCoo2)
+
+    npt.assert_almost_equal(c4.x, 2)
+    npt.assert_almost_equal(c4.y, 1)
+    npt.assert_almost_equal(c4.z, 2)
+
+def test_coo_alias():
+    """
+    Tests the shortname/attribute-style accessing of transforms
+    """
+    t.coordinate_alias('coo2', TestCoo2)
+
+    t.FunctionTransform(TestCoo1, TestCoo2, lambda c: TestCoo2(c.ra, c.dec))
+
+    c1 = TestCoo1(1, 2, unit=(u.degree, u.degree))
+    assert c1.coo2.ra.degrees == c1.ra.degrees
+    assert c1.coo2.dec.degrees == c1.dec.degrees
+
+def test_shortest_path():
+    class FakeTransform(object):
+        def __init__(self, pri):
+            self.priority = pri
+
+    g = t.TransformGraph()
+
+    #cheating by adding graph elements directly that are not classes - the
+    #graphing algorithm still works fine with integers - it just isn't a valid
+    #TransformGraph
+
+    #the graph looks is a down-going diamond graph with the lower-right slightly
+    #heavier and a cycle from the bottom to the top
+    #also, a pair of nodes isolated from 1
+
+    g._graph[1][2] = FakeTransform(1)
+    g._graph[1][3] = FakeTransform(1)
+    g._graph[2][4] = FakeTransform(1)
+    g._graph[3][4] = FakeTransform(2)
+    g._graph[4][1] = FakeTransform(5)
+
+    g._graph[5][6] = FakeTransform(1)
+
+    path, d = g.find_shortest_path(1, 2)
+    assert path == [1, 2]
+    assert d == 1
+    path, d = g.find_shortest_path(1, 3)
+    assert path == [1, 3]
+    assert d == 1
+    path, d = g.find_shortest_path(1, 4)
+    print('Cached paths:', g._shortestpaths)
+    assert path == [1, 2, 4]
+    assert d == 2
+
+    #unreachable
+    path, d = g.find_shortest_path(1, 5)
+    assert path is None
+    assert d == float('inf')
+
+    path, d = g.find_shortest_path(5, 6)
+    assert path == [5, 6]
+    assert d == 1
+
+
+def test_sphere_cart():
+    """
+    Tests the spherical <-> cartesian transform functions
+    """
+    from ...tests.compat import assert_allclose
+    from ...utils import NumpyRNGContext
+    from ..distances import spherical_to_cartesian, cartesian_to_spherical
+
+
+    x, y, z = spherical_to_cartesian(1, 0, 0)
+    npt.assert_almost_equal(x, 1)
+    npt.assert_almost_equal(y, 0)
+    npt.assert_almost_equal(z, 0)
+
+    x, y, z = spherical_to_cartesian(0, 1, 1)
+    npt.assert_almost_equal(x, 0)
+    npt.assert_almost_equal(y, 0)
+    npt.assert_almost_equal(z, 0)
+
+    x, y, z = spherical_to_cartesian(5, 0, np.arcsin(4. / 5.))
+    npt.assert_almost_equal(x, 3)
+    npt.assert_almost_equal(y, 4)
+    npt.assert_almost_equal(z, 0)
+
+    r, lat, lon = cartesian_to_spherical(0, 1, 0)
+    npt.assert_almost_equal(r, 1)
+    npt.assert_almost_equal(lat, 0)
+    npt.assert_almost_equal(lon, np.pi / 2)
+
+    #test round-tripping
+    with NumpyRNGContext(13579):
+        x, y, z = np.random.randn(3, 5)
+
+    r, lat, lon = cartesian_to_spherical(x, y, z)
+    x2, y2, z2 = spherical_to_cartesian(r, lat, lon)
+
+    assert_allclose(x, x2)
+    assert_allclose(y, y2)
+    assert_allclose(z, z2)
+
+
+m31_sys = [(ICRSCoordinates, 'icrs'), (FK5Coordinates, 'fk5'), (FK4Coordinates, 'fk4'), (GalacticCoordinates, 'galactic')]
+m31_coo = [(10.6847929, 41.2690650), (10.6847929, 41.2690650), (10.0004738, 40.9952444), (121.1744050, -21.5729360)]
+m31_dist = Distance(770, u.kpc)
+convert_precision = 1 / 3600.  # 1 arcsec
+roundtrip_precision = 1e-4
+dist_precision = 1e-9
+
+m31_params =[]
+for i in range(len(m31_sys)):
+    for j in range(len(m31_sys)):
+        if i < j:
+            m31_params.append((m31_sys[i], m31_sys[j], m31_coo[i], m31_coo[j]))
+
+ at pytest.mark.parametrize(('fromsys', 'tosys', 'fromcoo', 'tocoo'), m31_params)
+def test_m31_coord_transforms(fromsys, tosys, fromcoo, tocoo):
+    """
+    This tests a variety of coordinate conversions for the Chandra point-source
+    catalog location of M31 from NED.
+    """
+    from math import fabs
+
+    from ...time import Time
+
+    coo1 = fromsys[0](fromcoo[0], fromcoo[1], unit=(u.degree, u.degree), distance=m31_dist)
+    coo2 = coo1.transform_to(tosys[0])
+    if tosys[0] is FK4Coordinates:
+        coo2_prec = coo2.precess_to(Time('B1950', scale='utc'))
+        assert fabs(coo2_prec.lonangle.degrees - tocoo[0]) < convert_precision  # <1 arcsec
+        assert fabs(coo2_prec.latangle.degrees - tocoo[1]) < convert_precision
+    else:
+        assert fabs(coo2.lonangle.degrees - tocoo[0]) < convert_precision  # <1 arcsec
+        assert fabs(coo2.latangle.degrees - tocoo[1]) < convert_precision
+    assert fabs(coo2.distance.kpc - m31_dist.kpc) < dist_precision
+
+    if fromsys[1] is not None:
+        coo1_2 = getattr(coo2, fromsys[1])  # implicit `transform_to` call.
+
+        #check round-tripping
+        assert fabs(coo1_2.lonangle.degrees - fromcoo[0]) < roundtrip_precision
+        assert fabs(coo1_2.latangle.degrees - fromcoo[1]) < roundtrip_precision
+        assert fabs(coo1_2.distance.kpc - m31_dist.kpc) < dist_precision
+
+        if tosys[1] is not None:
+            coo2_2 = getattr(coo1_2, tosys[1])
+            assert fabs(coo2_2.lonangle.degrees - coo2.lonangle.degrees) < roundtrip_precision
+            assert fabs(coo2_2.latangle.degrees - coo2.latangle.degrees) < roundtrip_precision
+            assert fabs(coo2_2.distance.kpc - m31_dist.kpc) < dist_precision
+
+
+def test_precession():
+    """
+    Ensures that FK4 and FK5 coordinates precess their equinoxes
+    """
+    from ...time import Time
+
+    j2000 = Time('J2000', scale='utc')
+    b1950 = Time('B1950', scale='utc')
+    j1975 = Time('J1975', scale='utc')
+    b1975 = Time('B1975', scale='utc')
+
+    fk4 = FK4Coordinates(1, 2, unit=(u.radian, u.radian))
+    assert fk4.equinox.byear == b1950.byear
+    fk4_2 = fk4.precess_to(b1975)
+    assert fk4_2.equinox.byear == b1975.byear
+
+    fk5 = FK5Coordinates(1, 2, unit=(u.radian, u.radian))
+    assert fk5.equinox.jyear == j2000.jyear
+    fk5_2 = fk5.precess_to(j1975)
+    assert fk5_2.equinox.jyear == j1975.jyear
+
+
+def test_alias_transform():
+    """
+    Tests the use of aliases to do trasnforms and also transforming from
+    a system to itself.  Also checks that `dir` correctly includes
+    valid transforms
+    """
+    c = ICRSCoordinates(12.34, 56.78, unit=(u.hour, u.degree))
+    assert isinstance(c.galactic, GalacticCoordinates)
+    assert isinstance(c.icrs, ICRSCoordinates)
+
+    d = dir(c)
+    assert 'galactic' in d
+    assert 'fk4' in d
+    assert 'fk5' in d
+
+
+def test_transform_path_pri():
+    """
+    This checks that the transformation path prioritization works by
+    making sure the ICRS -> Gal transformation always goes through FK5
+    and not FK4.
+    """
+    t.master_transform_graph.invalidate_cache()
+    tpath, td = t.master_transform_graph.find_shortest_path(ICRSCoordinates, GalacticCoordinates)
+    assert tpath == [ICRSCoordinates, FK5Coordinates, GalacticCoordinates]
+    assert td == 2
+
+    #but direct from FK4 to Galactic should still be possible
+    tpath, td = t.master_transform_graph.find_shortest_path(FK4Coordinates, GalacticCoordinates)
+    assert tpath == [FK4Coordinates, FK4NoETermCoordinates, GalacticCoordinates]
+    assert td == 2
+
+
+def test_obstime():
+    """
+    Checks to make sure observation time survives transforms, and that it's
+    accounted for at least in FK4 <-> ICRS transformations
+    """
+    from ...time import Time
+
+    b1950 = Time('B1950', scale='utc')
+    j1975 = Time('J1975', scale='utc')
+
+    fk4_50 = FK4Coordinates(1, 2, unit=(u.degree, u.degree), obstime=b1950)
+    fk4_75 = FK4Coordinates(1, 2, unit=(u.degree, u.degree), obstime=j1975)
+
+    icrs_50 = fk4_50.transform_to(ICRSCoordinates)
+    icrs_75 = fk4_75.transform_to(ICRSCoordinates)
+
+    assert icrs_50.obstime == fk4_50.obstime
+    assert icrs_75.obstime == fk4_75.obstime
+
+    # now check that the resulting coordinates are *different* - they should be,
+    # because the obstime is different
+    assert (icrs_50.ra.degrees != icrs_75.ra.degrees and
+            icrs_50.dec.degrees != icrs_75.dec.degrees)
diff --git a/astropy/coordinates/transformations.py b/astropy/coordinates/transformations.py
new file mode 100644
index 0000000..45fb35a
--- /dev/null
+++ b/astropy/coordinates/transformations.py
@@ -0,0 +1,851 @@
+# Licensed under a 3-clause BSD style license - see LICENSE.rst
+
+"""
+This module contains the framework for transforming points from
+one coordinate system to another (e.g. equatorial to galactic). The
+implementation is actually in individual coordinates in the
+`builtin_systems` module, while this module provides the framework and
+related utilities.
+"""
+from abc import ABCMeta, abstractmethod
+
+import numpy as np
+
+__all__ = ['StaticMatrixTransform', 'FunctionTransform',
+           'DynamicMatrixTransform', 'CompositeStaticMatrixTransform',
+           'static_transform_matrix', 'transform_function',
+           'dynamic_transform_matrix', 'coordinate_alias'
+          ]
+
+
+class TransformGraph(object):
+    """
+    A graph representing the paths between coordinate systems.
+    """
+
+    def __init__(self):
+        from collections import defaultdict
+
+        self._graph = defaultdict(dict)
+        self._clsaliases = {}
+
+        self.invalidate_cache()  # generates cache entries
+
+    def add_transform(self, fromsys, tosys, transform):
+        """
+        Add a new coordinate transformation to the graph.
+
+        Parameters
+        ----------
+        fromsys : class
+            The coordinate system *class* to start from
+        tosys : class
+            The coordinate system *class* to transform to
+        transform : callable
+            The transformation object. Should have call parameters compatible
+            with `CoordinateTransform`.
+
+        Raises
+        ------
+        TypeError
+            If `fromsys` or `tosys` are not classes or `transform` is
+            not callable.
+        """
+        from inspect import isclass
+
+        if not isclass(fromsys):
+            raise TypeError('fromsys must be a class')
+        if not isclass(tosys):
+            raise TypeError('tosys must be a class')
+        if not callable(transform):
+            raise TypeError('transform must be callable')
+
+        self._graph[fromsys][tosys] = transform
+        self.invalidate_cache()
+
+    def remove_transform(self, fromsys, tosys, transform):
+        """
+        Removes a coordinate transform from the graph.
+
+        Parameters
+        ----------
+        fromsys : class or None
+            The coordinate system *class* to start from. If None,
+            `transform` will be searched for and removed (`tosys` must
+            also be None).
+        tosys : class or None
+            The coordinate system *class* to transform into. If None,
+            `transform` will be searched for and removed (`fromsys` must
+            also be None).
+        transform : callable or None
+            The transformation object to be removed or None.  If None
+            and `tosys` and `fromsys` are supplied, there will be no
+            check to ensure the correct object is removed.
+        """
+        if fromsys is None or tosys is None:
+            if not (tosys is None and fromsys is None):
+                raise ValueError('fromsys and tosys must both be None if either are')
+            if transform is None:
+                raise ValueError('cannot give all Nones to remove_transform')
+
+            # search for the requested transform by brute force and remove it
+            for a in self._graph:
+                agraph = self._graph[a]
+                for b in agraph:
+                    if b is transform:
+                        del agraph[b]
+                        break
+            else:
+                raise ValueError('Could not find transform {0} in the '
+                                 'graph'.format(transform))
+
+        else:
+            if transform is None:
+                self._graph[fromsys].pop(tosys, None)
+            else:
+                curr = self._graph[fromsys].get(tosys, None)
+                if curr is transform:
+                    self._graph[fromsys].pop(tosys)
+                else:
+                    raise ValueError('Current transform from {0} to {1} is not '
+                                     '{2}'.format(fromsys, tosys, transform))
+        self.invalidate_cache()
+
+    def find_shortest_path(self, fromsys, tosys):
+        """
+        Computes the shortest distance along the transform graph from
+        one system to another.
+
+        Parameters
+        ----------
+        fromsys : class
+            The starting coordinate system.
+        tosys : class
+            The starting coordinate system.
+
+        Returns
+        -------
+        path : list of classes or None
+            The path from `fromsys` to `tosys` as an in-order sequence
+            of classes.  This list includes *both* `fromsys` and
+            `tosys`. Is None if there is no possible path.
+        distance : number
+            The total distance/priority from `fromsys` to `tosys`.  If
+            priorities are not set this is the number of trasnforms
+            needed. Is `inf` if there is no possible path.
+        """
+        import heapq
+
+        inf = float('inf')
+
+        # special-case the 0-path and 1-path
+        if tosys is fromsys:
+            return [tosys], 0
+        elif tosys in self._graph[fromsys]:
+            t = self._graph[fromsys][tosys]
+            return [fromsys, tosys], float(t.priority if hasattr(t, 'priority') else 1)
+
+        if fromsys in self._shortestpaths:
+            # already have a cached result
+            fpaths = self._shortestpaths[fromsys]
+            if tosys in fpaths:
+                return fpaths[tosys]
+            else:
+                return None, inf
+
+        # use Dijkstra's algorithm to find shortest path in all other cases
+
+        nodes = []
+        # first make the list of nodes
+        for a in self._graph:
+            if a not in nodes:
+                nodes.append(a)
+            for b in self._graph[a]:
+                if b not in nodes:
+                    nodes.append(b)
+
+        if fromsys not in nodes or tosys not in nodes:
+            # fromsys or tosys are isolated or not registered, so there's
+            # certainly no way to get from one to the other
+            return None, inf
+
+        edgeweights = {}
+        # construct another graph that is a dict of dicts of priorities
+        # (used as edge weights in Dijkstra's algorithm)
+        for a in self._graph:
+            edgeweights[a] = aew = {}
+            agraph = self._graph[a]
+            for b in agraph:
+                aew[b] = float(agraph[b].priority if hasattr(agraph[b], 'priority') else 1)
+
+        # entries in q are [distance, count, nodeobj, pathlist]
+        # count is needed because in py 3.x, tie-breaking fails on the nodes.
+        # this way, insertion order is preserved if the weights are the same
+        q = [[inf, i, n, []] for i, n in enumerate(nodes) if n is not fromsys]
+        q.insert(0, [0, -1, fromsys, []])
+
+        # this dict will store the distance to node from `fromsys` and the path
+        result = {}
+
+        # definitely starts as a valid heap because of the insert line; from the
+        # node to itself is always the shortest distance
+        while len(q) > 0:
+            d, orderi, n, path = heapq.heappop(q)
+
+            if d == inf:
+                # everything left is unreachable from fromsys, just copy them to
+                # the results and jump out of the loop
+                result[n] = (None, d)
+                for d, orderi, n, path in q:
+                    result[n] = (None, d)
+                break
+            else:
+                result[n] = (path, d)
+                path.append(n)
+                for n2 in edgeweights[n]:
+                    if n2 not in result:  # already visited
+                        # find where n2 is in the heap
+                        for i in range(len(q)):
+                            if q[i][2] == n2:
+                                break
+                        else:
+                            raise ValueError('n2 not in heap - this should be impossible!')
+
+                        newd = d + edgeweights[n][n2]
+                        if newd < q[i][0]:
+                            q[i][0] = newd
+                            q[i][3] = list(path)
+                            heapq.heapify(q)
+
+        # cache for later use
+        self._shortestpaths[fromsys] = result
+        return result[tosys]
+
+    def invalidate_cache(self):
+        """
+        Invalidates the cache that stores optimizations for traversing the
+        transform cache.  This is called automatically when transforms
+        are added or removed, but will need to be called manually if
+        weights on transforms are modified inplace.
+        """
+        self._shortestpaths = {}
+
+    # TODO: cache composites so they don't need to be generated every time?
+    def get_transform(self, fromsys, tosys):
+        """
+        Determines or generates a transformation between two coordinate
+        systems.
+
+        Parameters
+        ----------
+        fromsys : class
+            The coordinate system *class* to start from
+        tosys : class
+            The coordinate system *class* to transform into.
+
+        Returns
+        -------
+        trans : `CoordinateTransform` or None
+            If there is a path from `fromsys` to `tosys`, this is a transform
+            object for that path.  If None, no path could be found.
+        """
+        if tosys in self._graph[fromsys]:
+            return self._graph[fromsys][tosys]
+        else:
+            path, distance = self.find_shortest_path(fromsys, tosys)
+
+            if path is None:
+                return None
+
+            transforms = []
+            currsys = fromsys
+            for p in path[1:]:  # first element is fromsys so we skip it
+                transforms.append(self._graph[currsys][p])
+                currsys = p
+
+            # TODO: collapse "runs" of statics?
+            if all([isinstance(p, StaticMatrixTransform) for p in path]):
+                return CompositeStaticMatrixTransform(fromsys, tosys, transforms, register=False)
+            else:
+                return CompositeTransform(fromsys, tosys, transforms, register=False)
+
+    def add_coord_name(self, name, coordcls):
+        """
+        Adds an alias for a coordinate, primarily for allowing
+        attribute-style access of coordinate transformations (e.g.,
+        ``coordasgal = coord.galactic``).
+
+        Parameters
+        ----------
+        name : str
+            The alias for the coordinate class. Should be a valid
+            python identifier.
+        coordcls : class
+            The class object to be referenced by this name.
+
+        Raises
+        ------
+        ValueError
+            If `coordcls` already has a name assigned.
+        """
+        if coordcls in self._clsaliases.values():
+            idx = self._clsaliases.values().index(coordcls)
+            oldnm = self._clsaliases.keys()[idx]
+            msg = 'Coordinate class {0} already has a name: {1}'
+            raise ValueError(msg.format(coordcls, oldnm))
+        self._clsaliases[name] = coordcls
+
+    def lookup_name(self, name):
+        """
+        Tries to locate the coordinate class with the provided alias.
+
+        Parameters
+        ----------
+        name : str
+            The alias to look up.
+
+        Returns
+        -------
+        coordcls
+            The coordinate class corresponding to the `name` or None if
+            no such class exists.
+        """
+        return self._clsaliases.get(name, None)
+
+    def get_aliases(self):
+        """
+        Returns all available transform aliases. They will all be
+        valid arguments to `lookup_name`.
+
+        Returns
+        -------
+        nms : list
+            The aliases for coordinate systems.
+        """
+        return self._clsaliases.keys()
+
+    def to_dot_graph(self, priorities=True, addnodes=[], savefn=None,
+                     savelayout='plain', saveformat=None):
+        """
+        Converts this transform graph to the graphviz_ DOT format, and
+        optionally saves it (requires graphviz_ be installed and on your
+        path).
+
+        Parameters
+        ----------
+        priorities : bool
+            If True, show the priority values for each transform.  Otherwise,
+            the will not be included in the graph.
+        addnodes : sequence of str
+            Additional coordinate systems to add (this can include systems
+            already in the transform graph, but they will only appear once).
+        savefn : None or str
+            The file name to save this graph to or None to not save
+            to a file.
+        savelayout : str
+            The graphviz program to use to layout the graph (see
+            graphviz_ for details) or 'plain' to just save the DOT graph
+            content. Ignored if `savefn` is None.
+        saveformat : str
+            The graphviz output format. (e.g. the ``-Txxx`` option for
+            the command line program - see graphviz docs for details).
+            Ignored if `savefn` is None.
+
+        Returns
+        -------
+        dotgraph : str
+            A string with the DOT format graph.
+
+        .. _graphviz: http://www.graphviz.org/
+        """
+        from subprocess import Popen, PIPE
+
+        nodes = []
+        # find the node names
+        for a in self._graph:
+            if a not in nodes:
+                nodes.append(a)
+            for b in self._graph[a]:
+                if b not in nodes:
+                    nodes.append(b)
+        for node in addnodes:
+            if node not in nodes:
+                nodes.append(node)
+        nodenames = []
+        invclsaliases = dict([(v, k) for k, v in self._clsaliases.iteritems()])
+        for n in nodes:
+            if n in invclsaliases:
+                nodenames.append('{0} [shape=oval label="{0}\\n`{1}`"]'.format(n.__name__, invclsaliases[n]))
+            else:
+                nodenames.append(n.__name__ + '[ shape=oval ]')
+
+        edgenames = []
+        # Now the edges
+        for a in self._graph:
+            agraph = self._graph[a]
+            for b in agraph:
+                pri = agraph[b].priority if hasattr(agraph[b], 'priority') else 1
+                edgenames.append((a.__name__, b.__name__, pri))
+
+        # generate simple dot format graph
+        lines = ['digraph AstropyCoordinateTransformGraph {']
+        lines.append('; '.join(nodenames) + ';')
+        for enm1, enm2, weights in edgenames:
+            labelstr = '[ label = "{0}" ]'.format(weights) if priorities else ''
+            lines.append('{0} -> {1}{2};'.format(enm1, enm2, labelstr))
+        lines.append('')
+        lines.append('overlap=false')
+        lines.append('}')
+        dotgraph = '\n'.join(lines)
+
+        if savefn is not None:
+            if savelayout == 'plain':
+                with open(savefn, 'w') as f:
+                    f.write(dotgraph)
+            else:
+                args = [savelayout]
+                if saveformat is not None:
+                    args.append('-T' + saveformat)
+                proc = Popen(args, stdin=PIPE, stdout=PIPE, stderr=PIPE)
+                stdout, stderr = proc.communicate(dotgraph)
+                if proc.returncode != 0:
+                    raise IOError('problem running graphviz: \n' + stderr)
+
+                with open(savefn, 'w') as f:
+                    f.write(stdout)
+
+        return dotgraph
+
+    def to_networkx_graph(self):
+        """
+        Converts this transform graph into a networkx graph.
+
+        .. note::
+            You must have the `networkx <http://networkx.lanl.gov/>`_
+            package installed for this to work.
+
+        Returns
+        -------
+        nxgraph : `networkx.Graph`
+            This `TransformGraph` as a `networkx.Graph`.
+        """
+        import networkx as nx
+
+        nxgraph = nx.Graph()
+
+        # first make the nodes
+        for a in self._graph:
+            if a not in nxgraph:
+                nxgraph.add_node(a)
+            for b in self._graph[a]:
+                if b not in nxgraph:
+                    nxgraph.add_node(b)
+
+        # Now the edges
+        for a in self._graph:
+            agraph = self._graph[a]
+            for b in agraph:
+                pri = agraph[b].priority if hasattr(agraph[b], 'priority') else 1
+                nxgraph.add_edge(a, b, weight=pri)
+
+        return nxgraph
+
+
+# The primary transform graph for astropy coordinates
+master_transform_graph = TransformGraph()
+
+
+class CoordinateTransform(object):
+    """
+    An object that transforms a coordinate from one system to another.
+    Subclasses must implement `__call__` with the provided signature.
+    They should also call this superclass's `__init__` in their
+    `__init__`.
+    """
+
+    __metaclass__ = ABCMeta
+
+    def __init__(self, fromsys, tosys, register=True):
+        from inspect import isclass
+
+        self.fromsys = fromsys
+        self.tosys = tosys
+
+        if register:
+            # this will do the type-checking
+            self.register()
+        else:
+            if not isclass(fromsys) or not isclass(tosys):
+                raise TypeError('fromsys and tosys must be classes')
+
+    def register(self):
+        """
+        Add this transformation to the master transformation graph, replacing
+        anything already connecting these two coordinates.
+        """
+        master_transform_graph.add_transform(self.fromsys, self.tosys, self)
+
+    def unregister(self):
+        """
+        Remove this transformation to the master transformation graph.
+
+        Raises
+        ------
+        ValueError
+            If this is not currently in the transform graph.
+        """
+        master_transform_graph.remove_transform(self.fromsys, self.tosys, self)
+
+    @abstractmethod
+    def __call__(self, fromcoord):
+        """
+        Accepts the provided coordinate object and yields a new coordinate
+        object with the transform applied.
+        """
+
+
+# TODO: array: specify in the docs how arrays should be dealt with
+class FunctionTransform(CoordinateTransform):
+    """
+    A coordinate transformation defined by a function that simply
+    accepts a coordinate object and returns the transformed coordinate
+    object.
+
+    Parameters
+    ----------
+    fromsys : class
+        The coordinate system *class* to start from.
+    tosys : class
+        The coordinate system *class* to transform into.
+    func : callable
+        The transformation function.
+    copyobstime : bool
+        If True (default) the value of the  `_obstime` attribute will be copied
+        to the newly-produced coordinate.
+
+    priority : number
+        The priority if this transform when finding the shortest
+        coordinate tranform path - large numbers are lower priorities.
+    register : bool
+        Determines if this transformation will be registered in the
+        astropy master transform graph.
+
+    Raises
+    ------
+    TypeError
+        If `func` is not callable.
+    ValueError
+        If `func` cannot accept one argument.
+
+
+    """
+    def __init__(self, fromsys, tosys, func, copyobstime=True, priority=1,
+                 register=True):
+        from inspect import getargspec
+
+        if not callable(func):
+            raise TypeError('func must be callable')
+
+        try:
+            argspec = getargspec(func)
+            if (len(argspec[0]) - len(argspec[3]) != 1) and not argspec[1]:
+                raise ValueError('provided function does not accept a single argument')
+        except TypeError:
+            pass  # hopefully this person knows what they're doing...
+
+        self.func = func
+        self.priority = priority
+        self.copyobstime = copyobstime
+
+        super(FunctionTransform, self).__init__(fromsys, tosys)
+
+    def __call__(self, fromcoord):
+        res = self.func(fromcoord)
+        if not isinstance(res, self.tosys):
+            raise TypeError('the transformation function yielded {0} but '
+                'should have been of type {1}'.format(res, self.tosys))
+
+        if self.copyobstime:
+            # copy over the obstime
+            if hasattr(fromcoord, '_obstime') and hasattr(res, '_obstime'):
+                res._obstime = fromcoord._obstime
+
+        return res
+
+
+class StaticMatrixTransform(CoordinateTransform):
+    """
+    A coordinate transformation defined as a 3 x 3 cartesian
+    transformation matrix.
+
+    Parameters
+    ----------
+    fromsys : class
+        The coordinate system *class* to start from.
+    tosys : class
+        The coordinate system *class* to transform into.
+    matrix: array-like
+        A 3 x 3 matrix for transforming 3-vectors. In most cases will
+        be unitary (although this is not strictly required).
+    priority : number
+        The priority if this transform when finding the shortest
+        coordinate tranform path - large numbers are lower priorities.
+
+    Raises
+    ------
+    ValueError
+        If the matrix is not 3 x 3
+
+    """
+    def __init__(self, fromsys, tosys, matrix, priority=1, register=True):
+        self.matrix = np.array(matrix)
+        if self.matrix.shape != (3, 3):
+            raise ValueError('Provided matrix is not 3 x 3')
+        self.priority = priority
+        super(StaticMatrixTransform, self).__init__(fromsys, tosys)
+
+    # TODO: array: this needs some extra bits to do the broadcasting right
+    def __call__(self, fromcoord):
+        v = [fromcoord.x, fromcoord.y, fromcoord.z]
+        x, y, z = np.dot(np.asarray(self.matrix), v)
+        unit = None if fromcoord.distance is None else fromcoord.distance._unit
+        result = self.tosys(x=x, y=y, z=z, unit=unit)
+
+        # copy over the observation time
+        if hasattr(fromcoord, '_obstime') and hasattr(result, '_obstime'):
+            result._obstime = fromcoord._obstime
+
+        return result
+
+
+class CompositeStaticMatrixTransform(StaticMatrixTransform):
+    """
+    A `MatrixTransform` constructed by combining a sequence of matricies
+    together.  See `MatrixTransform` for syntax details.
+
+    Parameters
+    ----------
+    fromsys : class
+        The coordinate system *class* to start from.
+    tosys : class
+        The coordinate system *class* to transform into.
+    matrices: sequence of array-like
+        A sequence of 3 x 3 cartesian transformation matricies.
+    priority : number
+        The priority if this transform when finding the shortest
+        coordinate tranform path - large numbers are lower priorities.
+
+    """
+    def __init__(self, fromsys, tosys, matricies, priority=1, register=True):
+        self.matricies = [np.array(m) for m in matricies]
+        for m in matricies:
+            if m.shape != (3, 3):
+                raise ValueError('One of the provided matrices is not 3 x 3')
+
+        matrix = np.array(self.matricies[0])
+        if len(self.matricies) > 1:
+            for m in self.matricies[1:]:
+                matrix = np.dot(np.asarray(self.matrix), m)
+
+        super(CompositeStaticMatrixTransform, self).__init__(self, fromsys,
+            tosys, matrix, priority)
+
+
+class DynamicMatrixTransform(CoordinateTransform):
+    """
+    A coordinate transformation specified as a function that yields a
+    3 x 3 cartesian transformation matrix.
+
+    Parameters
+    ----------
+    fromsys : class
+        The coordinate system *class* to start from.
+    tosys : class
+        The coordinate system *class* to transform into.
+    matrix_func: callable
+        A callable that accepts a coordinate object and yields the 3 x 3
+        matrix that converts it to the new coordinate system.
+    priority : number
+        The priority if this transform when finding the shortest
+        coordinate tranform path - large numbers are lower priorities.
+
+    Raises
+    ------
+    TypeError
+        If `matrix_func` is not callable
+
+    """
+    def __init__(self, fromsys, tosys, matrix_func, priority=1, register=True):
+        if not callable(matrix_func):
+            raise TypeError('matrix_func is not callable')
+        self.matrix_func = matrix_func
+        self.priority = priority
+        super(DynamicMatrixTransform, self).__init__(fromsys, tosys, register)
+
+    # TODO: array: this needs some extra bits to do the broadcasting right
+    def __call__(self, fromcoord):
+        v = [fromcoord.x, fromcoord.y, fromcoord.z]
+        x, y, z = np.dot(np.asarray(self.matrix_func(fromcoord)), v)
+        unit = None if fromcoord.distance is None else fromcoord.distance._unit
+        result = self.tosys(x=x, y=y, z=z, unit=unit)
+
+        # copy over the observation time
+        if hasattr(fromcoord, '_obstime') and hasattr(result, '_obstime'):
+            result._obstime = fromcoord._obstime
+
+        return result
+
+
+class CompositeTransform(CoordinateTransform):
+    """
+    A `MatrixTransform` constructed by combining a sequence of matricies
+    together.  See `MatrixTransform` for syntax details.
+
+    Parameters
+    ----------
+    fromsys : class
+        The coordinate system *class* to start from.
+    tosys : class
+        The coordinate system *class* to transform into.
+    transforms: sequence of `CoordinateTransform`s
+        A sequence of transformations to apply in sequence.
+    priority : number
+        The priority if this transform when finding the shortest
+        coordinate tranform path - large numbers are lower priorities.
+
+    """
+    def __init__(self, fromsys, tosys, transforms, priority=1, register=True):
+        self.transforms = transforms
+        super(CompositeTransform, self).__init__(fromsys, tosys, register)
+
+    def __call__(self, fromcoord):
+        coord = fromcoord
+        for t in self.transforms:
+            coord = t(coord)
+        return coord
+
+
+#<------------function decorators for actual practical use--------------------->
+def transform_function(fromsys, tosys, copyobstime=True, priority=1):
+    """
+    A function decorator for defining transformations between coordinate
+    systems.
+
+    .. note::
+        If decorating a static method of a class, ``@staticmethod``
+        should be  added *above* this decorator.
+
+    Parameters
+    ----------
+    fromsys : class
+        The coordinate system this function starts from.
+    tosys : class
+        The coordinate system this function results in.
+    copyobstime : bool
+        If True (default) the value of the  `_obstime` attribute will be
+        copied to the newly-produced coordinate.
+    priority : number
+        The priority if this transform when finding the shortest
+        coordinate tranform path - large numbers are lower priorities.
+
+    """
+    def deco(func):
+        # this doesn't do anything directly with the trasnform because
+        #``register=True`` stores it in the transform graph automatically
+        FunctionTransform(fromsys, tosys, func, copyobstime=copyobstime,
+                          priority=priority, register=True)
+        return func
+    return deco
+
+
+def static_transform_matrix(fromsys, tosys, priority=1):
+    """
+    A function decorator for defining transformations between coordinate
+    systems using a matrix.
+
+    The decorated function should accept *no* arguments and yield a
+    3 x 3 matrix.
+
+    .. note::
+        If decorating a static method of a class, ``@staticmethod``
+        should be  added *above* this decorator.
+
+    Parameters
+    ----------
+    fromsys : class
+        The coordinate system this function starts from.
+    tosys : class
+        The coordinate system this function results in.
+    priority : number
+        The priority if this transform when finding the shortest
+        coordinate tranform path - large numbers are lower priorities.
+    """
+    def deco(matfunc):
+        StaticMatrixTransform(fromsys, tosys, matfunc(), priority, register=True)
+        return matfunc
+    return deco
+
+
+def dynamic_transform_matrix(fromsys, tosys, priority=1):
+    """
+    A function decorator for defining transformations between coordinate
+    systems using a function that yields a matrix.
+
+    The decorated function should accept a single argument, the
+    coordinate object to be transformed, and should return a 3 x 3
+    matrix.
+
+    .. note::
+        If decorating a static method of a class, ``@staticmethod``
+        should be  added *above* this decorator.
+
+    Parameters
+    ----------
+    fromsys : class
+        The coordinate system this function starts from.
+    tosys : class
+        The coordinate system this function results in.
+    priority : number
+        The priority if this transform when finding the shortest
+        coordinate tranform path - large numbers are lower priorities.
+    """
+    def deco(matfunc):
+        DynamicMatrixTransform(fromsys, tosys, matfunc, priority, register=True)
+        return matfunc
+    return deco
+
+
+def coordinate_alias(name, coordcls=None):
+    """
+    Gives a short name to this coordinate system, allowing other coordinate
+    objects to convert to this one using attribute-style access.
+
+    Parameters
+    ----------
+    name : str
+        The short alias to use for this coordinate class. Should be a
+        valid python identifier.
+    coordcls : class or None
+        Either the coordinate class to register or None to use this as a
+        decorator.
+
+    Examples
+    --------
+    For use with a class already defined, do::
+
+        coordinate_alias('fancycoords', MyFancyCoordinateClass)
+
+    To use as a decorator, do::
+
+        @coordiante_alias('fancycoords')
+        class MyFancyCoordinateClass(SphericalCoordinatesBase):
+            ...
+
+    """
+    if coordcls is None:
+        def deco(cls):
+            master_transform_graph.add_coord_name(name, cls)
+            return cls
+        return deco
+    else:
+        master_transform_graph.add_coord_name(name, coordcls)
diff --git a/astropy/cosmology/__init__.py b/astropy/cosmology/__init__.py
index eee8e4e..a214520 100644
--- a/astropy/cosmology/__init__.py
+++ b/astropy/cosmology/__init__.py
@@ -2,8 +2,9 @@
 """ astropy.cosmology contains classes and functions for cosmological
 distance measures and other cosmology-related calculations.
 
-See the Astropy documentation for detailed usage examples and
-references.
+See the `Astropy documentation
+<http://docs.astropy.org/en/latest/cosmology/index.html>`_ for more
+detailed usage examples and references.
 """
 from core import *
 from funcs import *
diff --git a/astropy/cosmology/core.py b/astropy/cosmology/core.py
index d823701..3e1584c 100644
--- a/astropy/cosmology/core.py
+++ b/astropy/cosmology/core.py
@@ -1,38 +1,44 @@
 # Licensed under a 3-clause BSD style license - see LICENSE.rst
 import sys
 import warnings
-from math import sqrt, pi
+from math import sqrt, pi, exp, log
+from abc import ABCMeta, abstractmethod
 
 import numpy as np
 
-from ..constants.cgs import pc, G, c
+from ..constants import cgs
 from ..config import ConfigurationItem
 from ..utils.misc import isiterable
+from .. import units as u
 
-import parameters
+from . import parameters
 
 # Originally authored by Andrew Becker (becker at astro.washington.edu),
 # and modified by Neil Crighton (neilcrighton at gmail.com) and Roban
 # Kramer (robanhk at gmail.com).
 
-# Many of these adapted from astro-ph/9905116
+# Many of these adapted from Hogg 1999, astro-ph/9905116
+# and Linder 2003, PRL 90, 91301
 
-__all__ = ("FLRWCosmology get_current set_current WMAP5 WMAP7").split()
+__all__ = ["FLRW", "LambdaCDM", "FlatLambdaCDM", "wCDM", "FlatwCDM",
+           "Flatw0waCDM", "w0waCDM", "wpwaCDM", "w0wzCDM","get_current",
+           "set_current", "WMAP5", "WMAP7"]
 
 # Constants
 
 # speed of light in km/s
-c_kms = c * 1e-5
-
-# Mpc in cm
-Mpc = 1e6 * pc
+c_kms = cgs.c.to('km/s').value
 
 # Mpc in km
-Mpc_km = 1e-5 * Mpc
+Mpc_km = u.Mpc.to(u.km)
 
-# Gyr in seconds
+# Gyr in seconds; note these are Julian years, which are defined
+# to be exactly 365.25 days of 86400 seconds each. If we used the units
+# framework, the days would be 365.242... days.
 Gyr = 1e9 * 365.25 * 24 * 60 * 60
 
+#Radiation parameter over c^2
+a_B_c2 = 4 * cgs.sigma_sb.value / cgs.c.value**3
 
 DEFAULT_COSMOLOGY = ConfigurationItem(
     'default_cosmology', 'no_default',
@@ -48,102 +54,476 @@ class Cosmology(object):
     implemented. """
     pass
 
-class FLRWCosmology(Cosmology):
+class FLRW(Cosmology):
     """ A class describing an isotropic and homogeneous
     (Friedmann-Lemaitre-Robertson-Walker) cosmology.
 
-    Attributes
-    ----------
-    H0 : float
-      Hubble parameter at z=0 in km/s/Mpc
-    Om : float
-      Omega matter; matter density / critical density at z=0
-    Ol : float
-      Omega lambda; dark energy density / critical density at z=0
-    Ok : float
-      Omega_k, the curvature density at z=0. Defined as 1 - Om - Ol
-    h : float
-      Dimensionless Hubble parameter (H0 = 100*h km/s/Mpc).
-      Often used to quote cosmological values independently of H0.
-    hubble_time : float
-      Hubble time in Gyr.
-    hubble_distance : float
-      Hubble distance in Mpc.
-    critical_density0 : float
-      Critical density in g cm^-3 at z=0.
+    This is an abstract base class -- you can't instantiate
+    examples of this class, but must work with one of its
+    subclasses such as `LambdaCDM` or `wCDM`.
 
     Notes
     -----
-    Note the energy density from radiation, omega_r, is ignored (valid
-    for redshifts < ~10).
+    Class instances are static -- you can't change the values
+    of the parameters.  That is, all of the attributes above are
+    read only.
 
-    Examples
-    --------
-    >>> from astro.cosmology import FLRWCosmology
-    >>> cosmo = FLRWCosmology(H0=70, Om=0.3, Ol=0.7)
+    The neutrino treatment assumes all neutrino species are massless.
+    """
+    __metaclass__ = ABCMeta
 
-    The comoving distance in Mpc at redshift z:
+    def __init__(self, H0, Om0, Ode0, Tcmb0=2.725, Neff=3.04, name='FLRW'):
+        """ Initializer.
 
-    >>> dc = cosmo.comoving_distance(z)
-    """
-    def __init__(self, H0, Om, Ol, name='FLRWCosmology'):
+        Parameters
+        ----------
+        H0 : float
+          Hubble constant in [km/sec/Mpc] at z=0
+
+        Om0 : float
+          Omega matter: density of non-relativistic matter in units
+          of the critical density at z=0.
+
+        Ode0 : float
+          Omega dark energy: density of dark energy in units
+          of the critical density at z=0.
+
+        Tcmb0 : float
+          Temperature of the CMB in Kelvin at z=0 (def: 2.725)
+
+        Neff : float
+          Effective number of Neutrino species (def: 3.04)
+
+        name : string
+          Optional name for this cosmological object.
+        """
 
         # all densities are in units of the critical density
-        self.Om = float(Om)
-        self.Ol = float(Ol)
-        Ok = 1 - self.Om - self.Ol
-        if abs(Ok) < 1e-5:
-            Ok = 0
-        self.Ok = Ok
+        self._Om0 = float(Om0)
+        self._Ode0 = float(Ode0)
+        self._Tcmb0 = float(Tcmb0)
+        self._Neff = float(Neff)
         self.name = name
 
         # Hubble parameter at z=0, km/s/Mpc
-        self.H0 = float(H0)
+        self._H0 = float(H0)
         # H0 in s^-1
-        H0_s = self.H0 / Mpc_km
+        H0_s = self._H0 / Mpc_km
         # 100 km/s/Mpc * h = H0 (so h is dimensionless)
-        self.h = self.H0 / 100.
+        self._h = self._H0 / 100.
         # Hubble time in Gyr
-        self.hubble_time = 1. / H0_s / Gyr
+        self._hubble_time = 1. / H0_s / Gyr
         # Hubble distance in Mpc
-        self.hubble_distance = c_kms / self.H0
+        self._hubble_distance = c_kms / self._H0
 
         # critical density at z=0 (grams per cubic cm)
-        self.critical_density0 = 3. * H0_s**2 / (8. * pi * G)
+        self._critical_density0 = 3. * H0_s**2 / (8. * pi * cgs.G.value)
+
+        # Compute photon density, Tcmb, neutrino parameters
+        # Tcmb0=0 removes both photons and neutrinos, is handled
+        # as a special case for efficiency
+        if self._Tcmb0 > 0:
+            # Compute photon density from Tcmb
+            self._Ogamma0 = a_B_c2 * self._Tcmb0**4 / self._critical_density0
+
+            #Compute Neutrino Omega
+            # The constant in front is 7/8 (4/11)^4/3 -- see any
+            #  cosmology book for an explanation; the 7/8 is FD vs. BE
+            #  statistics, the 4/11 is the temperature effect
+            self._Onu0 = 0.2271073 * self._Neff * self._Ogamma0
+        else:
+            self._Ogamma0 = 0.0
+            self._Onu0 = 0.0
+
+        #Compute curvature density
+        self._Ok0 = 1.0 - self._Om0 - self._Ode0 - self._Ogamma0 - self._Onu0
 
     def __repr__(self):
-        s = "%s(H0=%.3g, Om=%.3g, Ol=%.3g, Ok=%.3g)" % (
-            self.name, self.H0, self.Om, self.Ol, self.Ok)
-        return s
+        return "%s(H0=%.3g, Om0=%.3g, Ode0=%.3g, Ok0=%.3g)" % \
+            (self.name, self._H0, self._Om0, self._Ode0, self._Ok0)
+
+    #Set up a set of properties for H0, Om0, Ode0, Ok0, etc. for user access.
+    #Note that we don't let these be set (so, obj.Om0 = value fails)
+
+    @property
+    def H0(self):
+        """ Return the Hubble constant in [km/sec/Mpc] at z=0"""
+        return self._H0
+
+    @property
+    def Om0(self):
+        """ Omega matter; matter density/critical density at z=0"""
+        return self._Om0
+
+    @property
+    def Ode0(self):
+        """ Omega dark energy; dark energy density/critical density at z=0"""
+        return self._Ode0
+
+    @property
+    def Ok0(self):
+        """ Omega curvature; the effective curvature density/critical density
+        at z=0"""
+        return self._Ok0
+
+    @property
+    def Tcmb0(self):
+        """ Temperature of the CMB in Kelvin at z=0"""
+        return self._Tcmb0
+
+    @property
+    def Neff(self):
+        """ Number of effective neutrino species"""
+        return self._Neff
+
+    @property
+    def h(self):
+        """ Dimensionless Hubble constant: h = H_0 / 100 [km/sec/Mpc]"""
+        return self._h
+
+    @property
+    def hubble_time(self):
+        """ Hubble time in [Gyr]"""
+        return self._hubble_time
+
+    @property
+    def hubble_distance(self):
+        """ Hubble distance in [Mpc]"""
+        return self._hubble_distance
+
+    @property
+    def critical_density0(self):
+        """ Critical density in [g cm^-3] at z=0"""
+        return self._critical_density0
+
+    @property
+    def Ogamma0(self):
+        """ Omega gamma; the density/critical density of photons at z=0"""
+        return self._Ogamma0
+
+    @property
+    def Onu0(self):
+        """ Omega nu; the density/critical density of neutrinos at z=0"""
+        return self._Onu0
+
+    @abstractmethod
+    def w(self, z):
+        """ The dark energy equation of state.
+
+        Parameters
+        ----------
+        z : array_like
+          Input redshifts.
+
+        Returns
+        -------
+        w : ndarray, or float if input scalar
+          The dark energy equation of state
+
+        Notes
+        ------
+        The dark energy equation of state is defined as
+        :math:`w(z) = P(z)/\\rho(z)`, where :math:`P(z)` is the
+        pressure at redshift z and :math:`\\rho(z)` is the density
+        at redshift z, both in units where c=1.
+
+        This must be overridden by subclasses.
+        """
+        raise NotImplementedError("w(z) is not implemented")
+
+    def Om(self, z):
+        """ Return the density parameter for non-relativistic matter
+        at redshift `z`.
+
+        Parameters
+        ----------
+        z : array_like
+          Input redshifts.
+
+        Returns
+        -------
+        Om : ndarray, or float if input scalar
+          The density of non-relativistic matter relative to the critical
+          density at each redshift.
+        """
+
+        if isiterable(z):
+            z = np.asarray(z)
+        return self._Om0 * (1. + z)**3 * self.inv_efunc(z)**2
+
+    def Ok(self, z):
+        """ Return the equivalent density parameter for curvature
+        at redshift `z`.
+
+        Parameters
+        ----------
+        z : array_like
+          Input redshifts.
+
+        Returns
+        -------
+        Ok : ndarray, or float if input scalar
+          The equivalent density parameter for curvature at each redshift.
+        """
+
+        if self._Ok0 == 0:
+            #Common enough case to be worth checking
+            return np.zeros_like(z)
+
+        if isiterable(z):
+            z = np.asarray(z)
+        return self._Ok0 * (1. + z)**2 * self.inv_efunc(z)**2
+
+    def Ode(self, z):
+        """ Return the density parameter for dark energy at redshift `z`.
+
+        Parameters
+        ----------
+        z : array_like
+          Input redshifts.
+
+        Returns
+        -------
+        Ode : ndarray, or float if input scalar
+          The density of non-relativistic matter relative to the critical
+          density at each redshift.
+        """
+
+        if self._Ode0 == 0:
+            return np.zeros_like(z)
+
+        return self._Ode0 * self.de_density_scale(z) * self.inv_efunc(z)**2
+
+    def Ogamma(self, z):
+        """ Return the density parameter for photons at redshift `z`.
+
+        Parameters
+        ----------
+        z : array_like
+          Input redshifts.
+
+        Returns
+        -------
+        Ogamma : ndarray, or float if input scalar
+          The energy density of photons relative to the critical
+          density at each redshift.
+        """
+
+        if self._Ogamma0 == 0:
+            #Common enough case to be worth checking (although it clearly
+            # doesn't represent any real universe)
+            return np.zeros_like(z)
+
+        if isiterable(z):
+            z = np.asarray(z)
+        return self._Ogamma0 * (1. + z)**4 * self.inv_efunc(z)**2
+
+    def Onu(self, z):
+        """ Return the density parameter for massless neutrinos at redshift `z`.
+
+        Parameters
+        ----------
+        z : array_like
+          Input redshifts.
+
+        Returns
+        -------
+        Onu : ndarray, or float if input scalar
+          The energy density of photons relative to the critical
+          density at each redshift.  Note that this includes only
+          their relativistic energy, since they are assumed massless.
+        """
+
+        if self._Onu0 == 0:
+            #Common enough case to be worth checking (although it clearly
+            # doesn't represent any real universe)
+            return np.zeros_like(z)
+
+        if isiterable(z):
+            z = np.asarray(z)
+        return self._Onu0 * (1. + z)**4 * self.inv_efunc(z)**2
+
+    def Tcmb(self, z):
+        """ Return the CMB temperature at redshift `z`.
+
+        Parameters
+        ----------
+        z : array_like
+          Input redshifts.
+
+        Returns
+        -------
+        Tcmb : ndarray, or float if z is scalar
+          The temperature of the CMB in K.
+        """
+
+        if isiterable(z):
+            z = np.asarray(z)
+        return self._Tcmb0 * (1.0 + z)
+
+    def _w_integrand(self, ln1pz):
+        """ Internal convenience function for w(z) integral."""
+
+        #See Linder 2003, PRL 90, 91301 eq (5)
+        #Assumes scalar input, since this should only be called
+        # inside an integral
+
+        z = exp(ln1pz)-1.0
+        return 1.0 + self.w(z)
+
+    def de_density_scale(self, z):
+        """ Evaluates the redshift dependence of the dark energy density.
+
+        Parameters
+        ----------
+        z : array_like
+          Input redshifts.
+
+        Returns
+        -------
+        I : ndarray, or float if input scalar
+          The scaling of the energy density of dark energy with redshift.
+
+        Notes
+        -----
+        The scaling factor, I, is defined by :math:`\\rho(z) = \\rho_0 I`,
+        and is given by
+
+        .. math::
+
+            I = \\exp \\left( 3 \int_{a}^1 \\frac{ da^{\\prime} }{ a^{\\prime} }
+            \\left[ 1 + w\\left( a^{\\prime} \\right) \\right] \\right)
+
+        It will generally helpful for subclasses to overload this method if
+        the integral can be done analytically for the particular dark
+        energy equation of state that they implement.
+        """
+
+        # This allows for an arbitrary w(z) following eq (5) of
+        # Linder 2003, PRL 90, 91301.  The code here evaluates
+        # the integral numerically.  However, most popular
+        # forms of w(z) are designed to make this integral analytic,
+        # so it is probably a good idea for subclasses to overload this
+        # method if an analytic form is available.
+        #
+        # The integral we actually use (the one given in Linder)
+        # is rewritten in terms of z, so looks slightly different than the
+        # one in the documentation string, but it's the same thing.
+
+        from scipy.integrate import quad
+
+        if isiterable(z):
+            z = np.asarray(z)
+            ival = np.array([quad(self._w_integrand,0,log(1+redshift))[0]
+                             for redshift in z])
+            return np.exp(3 * ival)
+        else:
+            ival = quad(self._w_integrand,0,log(1+z))[0]
+            return exp(3 * ival)
+
+    def efunc(self, z):
+        """ Function used to calculate H(z), the Hubble parameter.
+
+        Parameters
+        ----------
+        z : array_like
+          Input redshifts.
+
+        Returns
+        -------
+        E : ndarray, or float if input scalar
+          The redshift scaling of the Hubble constant.
+
+        Notes
+        -----
+        The return value, E, is defined such that :math:`H(z) = H_0 E`.
+
+        It is not necessary to override this method, but if de_density_scale
+        takes a particularly simple form, it may be advantageous to.
+        """
 
-    def _efunc(self, z):
-        """ Function used to calculate the hubble parameter as a
-        function of redshift. Eqn 14 from Hogg."""
         if isiterable(z):
             z = np.asarray(z)
-        zp1 = 1. + z
-        return np.sqrt(self.Om*zp1**3 + self.Ok*zp1**2 + self.Ol)
 
-    def _inv_efunc(self, z):
-        """ Integrand of the comoving distance.
+        Om0, Ode0, Ok0 = self._Om0, self._Ode0, self._Ok0
+        Or0 = self._Ogamma0 + self._Onu0
+        zp1 = 1.0 + z
+
+        return np.sqrt(zp1**2 * ((Or0 * zp1 + Om0) * zp1 + Ok0) +
+                       Ode0 * self.de_density_scale(z))
+
+    def inv_efunc(self, z):
+        """Inverse of efunc.
+
+        Parameters
+        ----------
+        z : array_like
+          Input redshifts.
+
+        Returns
+        -------
+        E : ndarray, or float if input scalar
+          The redshift scaling of the inverse Hubble constant.
         """
-        zp1 = 1. + z
-        return 1. / np.sqrt(self.Om*zp1**3 + self.Ok*zp1**2 + self.Ol)
+
+        #Avoid the function overhead by repeating code
+        if isiterable(z):
+            z = np.asarray(z)
+        Om0, Ode0, Ok0 = self._Om0, self._Ode0, self._Ok0
+        Or0 = self._Ogamma0 + self._Onu0
+        zp1 = 1.0 + z
+
+        return 1.0/np.sqrt(zp1**2 * ((Or0 * zp1 + Om0) * zp1 + Ok0) +
+                           Ode0 * self.de_density_scale(z))
 
     def _tfunc(self, z):
         """ Integrand of the lookback time.
 
-        Eqn 30 from Hogg."""
-        zp1 = 1. + z
-        return 1. / (zp1*np.sqrt(self.Om*zp1**3 + self.Ok*zp1**2 + self.Ol))
+        Parameters
+        ----------
+        z : array_like
+          Input redshifts.
+
+        Returns
+        -------
+        I : ndarray, or float if input scalar
+          The integrand for the lookback time
+
+        References
+        ----------
+        Eqn 30 from Hogg 1999.
+        """
+
+        if isiterable(z):
+            zp1 = 1.0 + np.asarray(z)
+        else:
+            zp1 = 1. + z
+
+        return 1.0 / (zp1 * self.efunc(z))
 
     def _xfunc(self, z):
         """ Integrand of the absorption distance.
 
+        Parameters
+        ----------
+        z : array_like
+          Input redshifts.
+
+        Returns
+        -------
+        X : ndarray, or float if input scalar
+          The integrand for the absorption distance
+
+        References
+        ----------
         See Hogg 1999 section 11.
         """
-        zp1 = 1. + z
-        return zp1**2 / np.sqrt(self.Om*zp1**3 + self.Ok*zp1**2 + self.Ol)
+
+        if isiterable(z):
+            zp1 = 1.0 + np.asarray(z)
+        else:
+            zp1 = 1. + z
+        return zp1**2 / self.efunc(z)
 
     def H(self, z):
         """ Hubble parameter (km/s/Mpc) at redshift `z`.
@@ -158,12 +538,13 @@ class FLRWCosmology(Cosmology):
         H : ndarray, or float if input scalar
           Hubble parameter in km/s/Mpc at each input redshift.
         """
-        return self.H0 * self._efunc(z)
+
+        return self._H0 * self.efunc(z)
 
     def scale_factor(self, z):
         """ Scale factor at redshift `z`.
 
-        The scale factor is defined as `a = 1 / (1 + z)`.
+        The scale factor is defined as :math:`a = 1 / (1 + z)`.
 
         Parameters
         ----------
@@ -181,6 +562,7 @@ class FLRWCosmology(Cosmology):
 
         return 1. / (1. + z)
 
+
     def lookback_time(self, z):
         """ Lookback time in Gyr to redshift `z`.
 
@@ -197,12 +579,13 @@ class FLRWCosmology(Cosmology):
         t : ndarray, or float if input scalar
           Lookback time in Gyr to each input redshift.
         """
+
         from scipy.integrate import quad
         if not isiterable(z):
-            return self.hubble_time * quad(self._tfunc, 0, z)[0]
+            return self._hubble_time * quad(self._tfunc, 0, z)[0]
 
         out = np.array([quad(self._tfunc, 0, redshift)[0] for redshift in z])
-        return self.hubble_time * np.array(out)
+        return self._hubble_time * np.array(out)
 
     def age(self, z):
         """ Age of the universe in Gyr at redshift `z`.
@@ -217,12 +600,13 @@ class FLRWCosmology(Cosmology):
         t : ndarray, or float if input scalar
           The age of the universe in Gyr at each input redshift.
         """
+
         from scipy.integrate import quad
         if not isiterable(z):
-            return self.hubble_time * quad(self._tfunc, z, np.inf)[0]
+            return self._hubble_time * quad(self._tfunc, z, np.inf)[0]
 
         out = [quad(self._tfunc, redshift, np.inf)[0] for redshift in z]
-        return self.hubble_time * np.array(out)
+        return self._hubble_time * np.array(out)
 
     def critical_density(self, z):
         """ Critical density in grams per cubic cm at redshift `z`.
@@ -237,7 +621,8 @@ class FLRWCosmology(Cosmology):
         rho : ndarray, or float if input scalar
           Critical density in g/cm^3 at each input redshift.
         """
-        return self.critical_density0 * (self._efunc(z))**2
+
+        return self._critical_density0 * (self.efunc(z))**2
 
     def comoving_distance(self, z):
         """ Comoving line-of-sight distance in Mpc at a given
@@ -257,12 +642,13 @@ class FLRWCosmology(Cosmology):
         d : ndarray, or float if input scalar
           Comoving distance in Mpc to each input redshift.
         """
+
         from scipy.integrate import quad
         if not isiterable(z):
-            return self.hubble_distance * quad(self._inv_efunc, 0, z)[0]
+            return self._hubble_distance * quad(self.inv_efunc, 0, z)[0]
 
-        out = [quad(self._inv_efunc, 0, redshift)[0] for redshift in z]
-        return self.hubble_distance * np.array(out)
+        out = [quad(self.inv_efunc, 0, redshift)[0] for redshift in z]
+        return self._hubble_distance * np.array(out)
 
     def comoving_transverse_distance(self, z):
         """ Comoving transverse distance in Mpc at a given redshift.
@@ -287,16 +673,17 @@ class FLRWCosmology(Cosmology):
         This quantity also called the 'proper motion distance' in some
         texts.
         """
-        Ok = self.Ok
+
+        Ok0 = self._Ok0
         dc = self.comoving_distance(z)
-        if Ok == 0:
+        if Ok0 == 0:
             return dc
-        sqrtOk = sqrt(abs(Ok))
-        dh = self.hubble_distance
-        if Ok > 0:
-            return dh / sqrtOk * np.sinh(sqrtOk * dc / dh)
+        sqrtOk0 = sqrt(abs(Ok0))
+        dh = self._hubble_distance
+        if Ok0 > 0:
+            return dh / sqrtOk0 * np.sinh(sqrtOk0 * dc / dh)
         else:
-            return dh / sqrtOk * np.sin(sqrtOk * dc / dh)
+            return dh / sqrtOk0 * np.sin(sqrtOk0 * dc / dh)
 
     def angular_diameter_distance(self, z):
         """ Angular diameter distance in Mpc at a given redshift.
@@ -318,6 +705,7 @@ class FLRWCosmology(Cosmology):
         d : ndarray, or float if input scalar
           Angular diameter distance in Mpc at each input redshift.
         """
+
         if isiterable(z):
             z = np.asarray(z)
 
@@ -344,6 +732,7 @@ class FLRWCosmology(Cosmology):
         ----------
         Weinberg, 1972, pp 420-424; Weedman, 1986, pp 60-62.
         """
+
         if isiterable(z):
             z = np.asarray(z)
 
@@ -374,10 +763,11 @@ class FLRWCosmology(Cosmology):
         This method only works for flat or open curvature
         (omega_k >= 0).
         """
+
         # does not work for negative curvature
-        Ok = self.Ok
-        if Ok < 0:
-            raise CosmologyError('Ok must be > 0 to use this method.')
+        Ok0 = self._Ok0
+        if Ok0 < 0:
+            raise CosmologyError('Ok0 must be >= 0 to use this method.')
 
         outscalar = False
         if not isiterable(z1) and not isiterable(z2):
@@ -398,10 +788,10 @@ class FLRWCosmology(Cosmology):
 
         dm1 = self.comoving_transverse_distance(z1)
         dm2 = self.comoving_transverse_distance(z2)
-        dh_2 = self.hubble_distance**2
+        dh_2 = self._hubble_distance**2
 
-        out = 1. / (1. + z2) * (dm2*np.sqrt(1. + Ok*dm1**2 / dh_2) -
-                                dm1*np.sqrt(1. + Ok*dm2**2 / dh_2))
+        out = 1. / (1. + z2) * (dm2*np.sqrt(1. + Ok0*dm1**2 / dh_2) -
+                                dm1*np.sqrt(1. + Ok0*dm2**2 / dh_2))
 
         if outscalar:
             return out[0]
@@ -413,7 +803,7 @@ class FLRWCosmology(Cosmology):
 
         This is used to calculate the number of objects with some
         cross section of absorption and number density intersecting a
-        sightline along per unit redshift path.
+        sightline per unit redshift path.
 
         Parameters
         ----------
@@ -430,14 +820,19 @@ class FLRWCosmology(Cosmology):
         Hogg 1999 Section 11. (astro-ph/9905116)
         Bahcall, John N. and Peebles, P.J.E. 1969, ApJ, 156L, 7B
         """
+
         from scipy.integrate import quad
-        return quad(self._xfunc, 0, z)[0]
+        if not isiterable(z):
+            return quad(self._xfunc, 0, z)[0]
+
+        out = [quad(self._xfunc, 0, redshift)[0] for redshift in z]
+        return np.array(out)
 
     def distmod(self, z):
         """ Distance modulus at redshift `z`.
 
         The distance modulus is defined as the (apparent magnitude -
-        absolute magnitude for an object at redshift `z`).
+        absolute magnitude) for an object at redshift `z`.
 
         Parameters
         ----------
@@ -449,6 +844,7 @@ class FLRWCosmology(Cosmology):
         distmod : ndarray, or float if input scalar
           Distance modulus at each input redshift.
         """
+
         # Remember that the luminosity distance is in Mpc
         return 5. * np.log10(self.luminosity_distance(z) * 1.e5)
 
@@ -470,29 +866,1019 @@ class FLRWCosmology(Cosmology):
         V : ndarray, or float if input scalar
           Comoving volume in Mpc^3 at each input redshift.
         """
-        Ok = self.Ok
-        if Ok == 0:
+
+        Ok0 = self._Ok0
+        if Ok0 == 0:
             return 4. / 3. * pi * self.comoving_distance(z)**3
 
-        dh = self.hubble_distance
+        dh = self._hubble_distance
         dm = self.comoving_transverse_distance(z)
-        term1 = 4. * pi * dh**3 / (2. * Ok)
-        term2 = dm / dh * sqrt(1 + Ok * (dm / dh)**2)
-        term3 = sqrt(abs(Ok)) * dm / dh
+        term1 = 4. * pi * dh**3 / (2. * Ok0)
+        term2 = dm / dh * sqrt(1 + Ok0 * (dm / dh)**2)
+        term3 = sqrt(abs(Ok0)) * dm / dh
 
-        if Ok > 0:
-            return term1 * (term2 - 1. / sqrt(abs(Ok)) * np.arcsinh(term3))
+        if Ok0 > 0:
+            return term1 * (term2 - 1. / sqrt(abs(Ok0)) * np.arcsinh(term3))
         else:
-            return term1 * (term2 - 1. / sqrt(abs(Ok)) * np.arcsin(term3))
+            return term1 * (term2 - 1. / sqrt(abs(Ok0)) * np.arcsin(term3))
 
+class LambdaCDM(FLRW):
+    """FLRW cosmology with a cosmological constant and curvature.
 
-# Pre-defined cosmologies. This loops over the parameter sets in the
-# parameters module and creates a FLRWCosmology instance with the same
-# name as the parameter set in the current module's namespace.
+    This has no additional attributes beyond those of FLRW.
 
-for key in parameters.available:
-    par = getattr(parameters, key)
-    cosmo = FLRWCosmology(par['H0'], par['Om'], par['Ol'], name=key)
+    Examples
+    --------
+    >>> from astro.cosmology import LambdaCDM
+    >>> cosmo = LambdaCDM(H0=70, Om0=0.3, Ode0=0.7)
+
+    The comoving distance in Mpc at redshift z:
+
+    >>> dc = cosmo.comoving_distance(z)
+    """
+
+    def __init__(self, H0, Om0, Ode0, Tcmb0=2.725, Neff=3.04,
+                 name='LambdaCDM'):
+        """ Initializer.
+
+        Parameters
+        ----------
+        H0 : float
+          Hubble constant in [km/sec/Mpc] at z=0
+
+        Om0 : float
+          Omega matter: density of non-relativistic matter in units
+          of the critical density at z=0.
+
+        Ode0 : float
+          Omega dark energy: density of the cosmological constant in units
+          of the critical density at z=0.
+
+        Tcmb0 : float
+          Temperature of the CMB in Kelvin at z=0 (def: 2.725)
+
+        Neff : float
+          Effective number of Neutrino species (def: 3.04)
+
+        name : string
+          Optional name for this cosmological object.
+        """
+        FLRW.__init__(self, H0, Om0, Ode0, Tcmb0, Neff, name=name)
+
+    def w(self, z):
+        """Returns dark energy equation of state at redshift `z`.
+
+        Parameters
+        ----------
+        z : array_like
+          Input redshifts.
+
+        Returns
+        -------
+        w : ndarray, or float if input scalar
+          The dark energy equation of state
+
+        Notes
+        ------
+        The dark energy equation of state is defined as
+        :math:`w(z) = P(z)/\\rho(z)`, where :math:`P(z)` is the
+        pressure at redshift z and :math:`\\rho(z)` is the density
+        at redshift z, both in units where c=1.  Here this is
+        :math:`w(z) = -1`.
+        """
+
+        return -1.0*np.ones_like(z)
+
+    def de_density_scale(self, z):
+        """ Evaluates the redshift dependence of the dark energy density.
+
+        Parameters
+        ----------
+        z : array_like
+          Input redshifts.
+
+        Returns
+        -------
+        I : ndarray, or float if input scalar
+          The scaling of the energy density of dark energy with redshift.
+
+        Notes
+        -----
+        The scaling factor, I, is defined by :math:`\\rho(z) = \\rho_0 I`,
+        and in this case is given by :math:`I = 1`.
+        """
+
+        return np.ones_like(z)
+
+    def efunc(self, z):
+        """ Function used to calculate H(z), the Hubble parameter.
+
+        Parameters
+        ----------
+        z : array_like
+          Input redshifts.
+
+        Returns
+        -------
+        E : ndarray, or float if input scalar
+          The redshift scaling of the Hubble consant.
+
+        Notes
+        -----
+        The return value, E, is defined such that :math:`H(z) = H_0 E`.
+        """
+
+        if isiterable(z):
+            z = np.asarray(z)
+
+        #We override this because it takes a particularly simple
+        # form for a cosmological constant
+        Om0, Ode0, Ok0 = self._Om0, self._Ode0, self._Ok0
+        Or0 = self._Ogamma0 + self._Onu0
+        zp1 = 1.0 + z
+
+        return np.sqrt(zp1**2 * ((Or0 * zp1 + Om0) * zp1 + Ok0) + Ode0)
+
+    def inv_efunc(self, z):
+        r""" Function used to calculate :math:`\frac{1}{H_z}`.
+
+        Parameters
+        ----------
+        z : array_like
+          Input redshifts.
+
+        Returns
+        -------
+        E : ndarray, or float if input scalar
+          The inverse redshift scaling of the Hubble constant.
+
+        Notes
+        -----
+        The return value, E, is defined such that :math:`H_z = H_0 /
+        E`.
+        """
+
+        if isiterable(z):
+            z = np.asarray(z)
+        Om0, Ode0, Ok0 = self._Om0, self._Ode0, self._Ok0
+        Or0 = self._Ogamma0 + self._Onu0
+        zp1 = 1.0 + z
+
+        return 1.0 / np.sqrt(zp1**2 * ((Or0 * zp1 + Om0) * zp1 + Ok0) + Ode0)
+
+class FlatLambdaCDM(LambdaCDM):
+    """FLRW cosmology with a cosmological constant and no curvature.
+
+    This has no additional attributes beyond those of FLRW.
+
+    Examples
+    --------
+    >>> from astro.cosmology import FlatLambdaCDM
+    >>> cosmo = FlatLambdaCDM(H0=70, Om0=0.3)
+
+    The comoving distance in Mpc at redshift z:
+
+    >>> dc = cosmo.comoving_distance(z)
+    """
+    def __init__(self, H0, Om0, Tcmb0=2.725, Neff=3.04, name='FlatLambdaCDM'):
+        """ Initializer.
+
+        Parameters
+        ----------
+        H0 : float
+          Hubble constant in [km/sec/Mpc] at z=0
+
+        Om0 : float
+          Omega matter: density of non-relativistic matter in units
+          of the critical density at z=0.
+
+        Tcmb0 : float
+          Temperature of the CMB in Kelvin at z=0 (def: 2.725)
+
+        Neff : float
+          Effective number of Neutrino species (def: 3.04)
+
+        name : string
+          Optional name for this cosmological object.
+        """
+        FLRW.__init__(self, H0, Om0, 0.0, Tcmb0, Neff, name=name)
+        #Do some twiddling after the fact to get flatness
+        self._Ode0 = 1.0 - self._Om0 - self._Ogamma0 - self._Onu0
+        self._Ok0 = 0.0
+
+    def __repr__(self):
+        return "%s(H0=%.3g, Om0=%.3g, Ode0=%.3g)" % \
+            (self.name, self._H0, self._Om0, self._Ode0)
+
+
+    def efunc(self, z):
+        """ Function used to calculate H(z), the Hubble parameter.
+
+        Parameters
+        ----------
+        z : array_like
+          Input redshifts.
+
+        Returns
+        -------
+        E : ndarray, or float if input scalar
+          The redshift scaling of the Hubble consant.
+
+        Notes
+        -----
+        The return value, E, is defined such that :math:`H(z) = H_0 E`.
+        """
+
+        if isiterable(z):
+            z = np.asarray(z)
+
+        #We override this because it takes a particularly simple
+        # form for a cosmological constant
+        Om0, Ode0 = self._Om0, self._Ode0
+        Or0 = self._Ogamma0 + self._Onu0
+        zp1 = 1.0 + z
+
+        return np.sqrt(zp1**3 * (Or0 * zp1 + Om0) + Ode0)
+
+    def inv_efunc(self, z):
+        r"""Function used to calculate :math:`\frac{1}{H_z}`.
+
+        Parameters
+        ----------
+        z : array_like
+          Input redshifts.
+
+        Returns
+        -------
+        E : ndarray, or float if input scalar
+          The inverse redshift scaling of the Hubble constant.
+
+        Notes
+        -----
+        The return value, E, is defined such that :math:`H_z = H_0 / E`.
+        """
+
+        if isiterable(z):
+            z = np.asarray(z)
+        Om0, Ode0 = self._Om0, self._Ode0
+        Or0 = self._Ogamma0 + self._Onu0
+        zp1 = 1.0 + z
+
+        return 1.0 / np.sqrt(zp1**3 * (Or0 * zp1 + Om0) + Ode0)
+
+class wCDM(FLRW):
+    """FLRW cosmology with a constant dark energy equation of state
+    and curvature.
+
+    This has one additional attribute beyond those of FLRW.
+
+    Examples
+    --------
+    >>> from astro.cosmology import wCDM
+    >>> cosmo = wCDM(H0=70, Om0=0.3, Ode0=0.7, w0=-0.9)
+
+    The comoving distance in Mpc at redshift z:
+
+    >>> dc = cosmo.comoving_distance(z)
+    """
+
+    def __init__(self, H0, Om0, Ode0, w0=-1., Tcmb0=2.725,
+                 Neff=3.04, name='wCDM'):
+        """ Initializer.
+
+        Parameters
+        ----------
+        H0 : float
+          Hubble constant in [km/sec/Mpc] at z=0
+
+        Om0 : float
+          Omega matter: density of non-relativistic matter in units
+          of the critical density at z=0.
+
+        Ode0 : float
+          Omega dark energy: density of dark energy in units
+          of the critical density at z=0.
+
+        w0 : float
+          Dark energy equation of state at all redshifts.
+          This is pressure/density for dark energy in units where c=1.
+          A cosmological constant has w0=-1.0.
+
+        Tcmb0 : float
+          Temperature of the CMB in Kelvin at z=0 (def: 2.725)
+
+        Neff : float
+          Effective number of Neutrino species (def: 3.04)
+
+        name : string
+          Optional name for this cosmological object.
+        """
+        FLRW.__init__(self, H0, Om0, Ode0, Tcmb0, Neff, name=name)
+        self._w0 = float(w0)
+
+    def __repr__(self):
+        return "%s(H0=%.3g, Om0=%.3g, Ode0=%.3g, Ok0=%.3g, w0=%.3g)" % \
+            (self.name, self._H0, self._Om0,
+             self._Ode0, self._Ok0, self._w0)
+
+    @property
+    def w0(self):
+        """ Dark energy equation of state"""
+        return self._w0
+
+    def w(self, z):
+        """Returns dark energy equation of state at redshift `z`.
+
+        Parameters
+        ----------
+        z : array_like
+          Input redshifts.
+
+        Returns
+        -------
+        w : ndarray, or float if input scalar
+          The dark energy equation of state
+
+        Notes
+        ------
+        The dark energy equation of state is defined as
+        :math:`w(z) = P(z)/\\rho(z)`, where :math:`P(z)` is the
+        pressure at redshift z and :math:`\\rho(z)` is the density
+        at redshift z, both in units where c=1.  Here this is
+        :math:`w(z) = w_0`.
+        """
+
+        return self._w0*np.ones_like(z)
+
+    def de_density_scale(self, z):
+        """ Evaluates the redshift dependence of the dark energy density.
+
+        Parameters
+        ----------
+        z : array_like
+          Input redshifts.
+
+        Returns
+        -------
+        I : ndarray, or float if input scalar
+          The scaling of the energy density of dark energy with redshift.
+
+        Notes
+        -----
+        The scaling factor, I, is defined by :math:`\\rho(z) = \\rho_0 I`,
+        and in this case is given by
+        :math:`I = \\left(1 + z\\right)^{3\\left(1 + w_0\\right)}`
+        """
+
+        if isiterable(z):
+            z = np.asarray(z)
+        return (1.0 + z)**(3 * (1 + self._w0))
+
+    def efunc(self, z):
+        """ Function used to calculate H(z), the Hubble parameter.
+
+        Parameters
+        ----------
+        z : array_like
+          Input redshifts.
+
+        Returns
+        -------
+        E : ndarray, or float if input scalar
+          The redshift scaling of the Hubble consant.
+
+        Notes
+        -----
+        The return value, E, is defined such that :math:`H(z) = H_0 E`.
+        """
+
+        if isiterable(z):
+            z = np.asarray(z)
+        Om0, Ode0, Ok0, w0 = self._Om0, self._Ode, self._Ok0, self._w0
+        Or0 = self._Ogamma0 + self._Onu0
+        zp1 = 1.0 + z
+
+        return np.sqrt(zp1**2 * ((Or0 * zp1 + Om0) * zp1 + Ok0) +
+                       Ode0 * zp1**(3.0 * (1 + w0)))
+
+    def inv_efunc(self, z):
+        r""" Function used to calculate :math:`\frac{1}{H_z}`.
+
+        Parameters
+        ----------
+        z : array_like
+          Input redshifts.
+
+        Returns
+        -------
+        E : ndarray, or float if input scalar
+          The inverse redshift scaling of the Hubble constant.
+
+        Notes
+        -----
+        The return value, E, is defined such that :math:`H_z = H_0 / E`.
+        """
+
+        if isiterable(z):
+            z = np.asarray(z)
+        Om0, Ode0, Ok0, w0 = self._Om0, self._Ode0, self._Ok0, self._w0
+        Or0 = self._Ogamma0 + self._Onu0
+        zp1 = 1.0 + z
+
+        return 1.0 / np.sqrt(zp1**2 * ((Or0 * zp1 + Om0) * zp1 + Ok0) +
+                             Ode0 * zp1**(3 * (1 + w0)))
+
+
+class FlatwCDM(wCDM):
+    """FLRW cosmology with a constant dark energy equation of state
+    and no spatial curvature.
+
+    This has one additional attribute beyond those of FLRW.
+
+    Examples
+    --------
+    >>> from astro.cosmology import FlatwCDM
+    >>> cosmo = FlatwCDM(H0=70, Om0=0.3, w0=-0.9)
+
+    The comoving distance in Mpc at redshift z:
+
+    >>> dc = cosmo.comoving_distance(z)
+    """
+
+    def __init__(self, H0, Om0, w0=-1., Tcmb0=2.725,
+                 Neff=3.04, name='FlatwCDM'):
+        """ Initializer.
+
+        Parameters
+        ----------
+        H0 : float
+          Hubble constant in [km/sec/Mpc] at z=0
+
+        Om0 : float
+          Omega matter: density of non-relativistic matter in units
+          of the critical density at z=0.
+
+        w0 : float
+          Dark energy equation of state at all redshifts.
+          This is pressure/density for dark energy in units where c=1.
+          A cosmological constant has w0=-1.0.
+
+        Tcmb0 : float
+          Temperature of the CMB in Kelvin at z=0 (def: 2.725)
+
+        Neff : float
+          Effective number of Neutrino species (def: 3.04)
+
+        name: string
+          Optional name for this cosmological object.
+        """
+        FLRW.__init__(self, H0, Om0, 0.0, Tcmb0, Neff, name=name)
+        self._w0 = float(w0)
+        #Do some twiddling after the fact to get flatness
+        self._Ode0 = 1.0 - self._Om0 - self._Ogamma0 - self._Onu0
+        self._Ok0 = 0.0
+
+    def __repr__(self):
+        return "%s(H0=%.3g, Om0=%.3g, Ode0=%.3g, w0=%.3g)" % \
+            (self.name, self._H0, self._Om0,
+             self._Ode0, self._w0)
+
+    def efunc(self, z):
+        """ Function used to calculate H(z), the Hubble parameter.
+
+        Parameters
+        ----------
+        z : array_like
+          Input redshifts.
+
+        Returns
+        -------
+        E : ndarray, or float if input scalar
+          The redshift scaling of the Hubble consant.
+
+        Notes
+        -----
+        The return value, E, is defined such that :math:`H(z) = H_0 E`.
+        """
+
+        if isiterable(z):
+            z = np.asarray(z)
+        Om0, Ode0, w0 = self._Om0, self._Ode, self._w0
+        Or0 = self._Ogamma0 + self._Onu0
+        zp1 = 1.0 + z
+
+        return np.sqrt(zp1**3 * (Or0 * zp1 + Om0) +
+                       Ode0 * zp1**(3.0 * (1 + w0)))
+
+    def inv_efunc(self, z):
+        r""" Function used to calculate :math:`\frac{1}{H_z}`.
+
+        Parameters
+        ----------
+        z : array_like
+          Input redshifts.
+
+        Returns
+        -------
+        E : ndarray, or float if input scalar
+          The inverse redshift scaling of the Hubble constant.
+
+        Notes
+        -----
+        The return value, E, is defined such that :math:`H_z = H_0 / E`.
+        """
+
+        if isiterable(z):
+            z = np.asarray(z)
+        Om0, Ode0, Ok0, w0 = self._Om0, self._Ode0, self._Ok0, self._w0
+        Or0 = self._Ogamma0 + self._Onu0
+        zp1 = 1.0 + z
+
+        return 1.0 / np.sqrt(zp1**3 * (Or0 * zp1 + Om0) +
+                             Ode0 * zp1**(3 * (1 + w0)))
+
+class w0waCDM(FLRW):
+    """FLRW cosmology with a CPL dark energy equation of state and curvature.
+
+    The equation for the dark energy equation of state uses the
+    CPL form as described in Chevallier & Polarski Int. J. Mod. Phys.
+    D10, 213 (2001) and Linder PRL 90, 91301 (2003):
+    :math:`w(z) = w_0 + w_a (1-a) = w_0 + w_a z / (1+z)`.
+
+    Examples
+    --------
+    >>> from astro.cosmology import w0waCDM
+    >>> cosmo = w0waCDM(H0=70, Om0=0.3, Ode0=0.7, w0=-0.9, wa=0.2)
+
+    The comoving distance in Mpc at redshift z:
+
+    >>> dc = cosmo.comoving_distance(z)
+    """
+
+    def __init__(self, H0, Om0, Ode0, w0=-1., wa=0., Tcmb0=2.725,
+                 Neff=3.04, name='w0waCDM'):
+        """ Initializer.
+
+        Parameters
+        ----------
+        H0 : float
+          Hubble constant in [km/sec/Mpc] at z=0
+
+        Om0 : float
+          Omega matter: density of non-relativistic matter in units
+          of the critical density at z=0.
+
+        Ode0 : float
+          Omega dark energy: density of dark energy in units
+          of the critical density at z=0.
+
+        w0 : float
+          Dark energy equation of state at z=0 (a=1).
+          This is pressure/density for dark energy in units where c=1.
+
+        wa : float
+          Negative derivative of the dark energy equation of state
+          with respect to the scale factor.  A cosmological constant has
+          w0=-1.0 and wa=0.0.
+
+        Tcmb0 : float
+          Temperature of the CMB in Kelvin at z=0 (def: 2.725)
+
+        Neff : float
+          Effective number of Neutrino species (def: 3.04)
+
+        name : string
+          Optional name for this cosmological object.
+        """
+        FLRW.__init__(self, H0, Om0, Ode0, Tcmb0, Neff, name=name)
+        self._w0 = float(w0)
+        self._wa = float(wa)
+
+    def __repr__(self):
+        return "%s(H0=%.3g, Om0=%.3g, Ode0=%.3g, Ok0=%.3g, w0=%.3g, wa=%.3g)" %\
+            (self.name, self._H0, self._Om0, self._Ode0, self._Ok0,
+             self._w0, self._wa)
+
+    @property
+    def w0(self):
+        """ Dark energy equation of state at z=0"""
+        return self._w0
+
+    @property
+    def wa(self):
+        """ Negative derivative of dark energy equation of state w.r.t. a"""
+        return self._wa
+
+    def w(self, z):
+        """Returns dark energy equation of state at redshift `z`.
+
+        Parameters
+        ----------
+        z : array_like
+          Input redshifts.
+
+        Returns
+        -------
+        w : ndarray, or float if input scalar
+          The dark energy equation of state
+
+        Notes
+        ------
+        The dark energy equation of state is defined as
+        :math:`w(z) = P(z)/\\rho(z)`, where :math:`P(z)` is the
+        pressure at redshift z and :math:`\\rho(z)` is the density
+        at redshift z, both in units where c=1.  Here this is
+        :math:`w(z) = w_0 + w_a (1 - a) = w_0 + w_a \\frac{z}{1+z}`.
+        """
+
+        if isiterable(z):
+            z = np.asarray(z)
+
+        return self._w0 + self._wa * z / (1.0 + z)
+
+    def de_density_scale(self, z):
+        """ Evaluates the redshift dependence of the dark energy density.
+
+        Parameters
+        ----------
+        z : array_like
+          Input redshifts.
+
+        Returns
+        -------
+        I : ndarray, or float if input scalar
+          The scaling of the energy density of dark energy with redshift.
+
+        Notes
+        -----
+        The scaling factor, I, is defined by :math:`\\rho(z) = \\rho_0 I`,
+        and in this case is given by
+
+        .. math::
+
+          I = \\left(1 + z\\right)^{3 \\left(1 + w_0 + w_a\\right)}
+          \exp \\left(-3 w_a \\frac{z}{1+z}\\right)
+
+        """
+        if isiterable(z):
+            z = np.asarray(z)
+        zp1 = 1.0 + z
+        return zp1**(3 * (1 + self._w0 + self._wa)) * \
+            exp(-3 * self._wa * z / zp1)
+
+class Flatw0waCDM(w0waCDM):
+    """FLRW cosmology with a CPL dark energy equation of state and no curvature.
+
+    The equation for the dark energy equation of state uses the
+    CPL form as described in Chevallier & Polarski Int. J. Mod. Phys.
+    D10, 213 (2001) and Linder PRL 90, 91301 (2003):
+    :math:`w(z) = w_0 + w_a (1-a) = w_0 + w_a z / (1+z)`.
+
+    Examples
+    --------
+    >>> from astro.cosmology import Flatw0waCDM
+    >>> cosmo = Flatw0waCDM(H0=70, Om0=0.3, w0=-0.9, wa=0.2)
+
+    The comoving distance in Mpc at redshift z:
+
+    >>> dc = cosmo.comoving_distance(z)
+    """
+    def __init__(self, H0, Om0, w0=-1., wa=0., Tcmb0=2.725,
+                 Neff=3.04, name='Flatw0waCDM'):
+        """ Initializer.
+
+        Parameters
+        ----------
+        H0 : float
+          Hubble constant in [km/sec/Mpc] at z=0
+
+        Om0 : float
+          Omega matter: density of non-relativistic matter in units
+          of the critical density at z=0.
+
+        w0 : float
+          Dark energy equation of state at z=0 (a=1).
+          This is pressure/density for dark energy in units where c=1.
+
+        wa : float
+          Negative derivative of the dark energy equation of state
+          with respect to the scale factor.  A cosmological constant has
+          w0=-1.0 and wa=0.0.
+
+        Tcmb0 : float
+          Temperature of the CMB in Kelvin at z=0 (def: 2.725)
+
+        Neff : float
+          Effective number of Neutrino species (def: 3.04)
+
+        name : string
+          Optional name for this cosmological object.
+        """
+        FLRW.__init__(self, H0, Om0, 0.0, Tcmb0, Neff, name=name)
+        #Do some twiddling after the fact to get flatness
+        self._Ode0 = 1.0 - self._Om0 - self._Ogamma0 - self._Onu0
+        self._Ok0 = 0.0
+        self._w0 = float(w0)
+        self._wa = float(wa)
+
+    def __repr__(self):
+        return "%s(H0=%.3g, Om0=%.3g, Ode0=%.3g, w0=%.3g, wa=%.3g)" %\
+            (self.name, self._H0, self._Om0, self._Ode0, self._w0, self._wa)
+
+
+class wpwaCDM(FLRW):
+    """FLRW cosmology with a CPL dark energy equation of state, a pivot
+    redshift, and curvature.
+
+    The equation for the dark energy equation of state uses the
+    CPL form as described in Chevallier & Polarski Int. J. Mod. Phys.
+    D10, 213 (2001) and Linder PRL 90, 91301 (2003), but modified
+    to have a pivot redshift as in the findings of the Dark Energy
+    Task Force (Albrecht et al. arXiv:0901.0721 (2009)):
+    :math:`w(a) = w_p + w_a (a_p - a) = w_p + w_a( 1/(1+zp) - 1/(1+z) )`.
+
+    Examples
+    --------
+    >>> from astro.cosmology import wpwaCDM
+    >>> cosmo = wpwaCDM(H0=70,Om0=0.3,Ode0=0.7,wp=-0.9,wa=0.2,zp=0.4)
+
+    The comoving distance in Mpc at redshift z:
+
+    >>> dc = cosmo.comoving_distance(z)
+    """
+
+    def __init__(self, H0, Om0, Ode0, wp=-1., wa=0., zp=0,
+                 Tcmb0=2.725, Neff=3.04, name='wpwaCDM'):
+        """ Initializer.
+
+        Parameters
+        ----------
+        H0 : float
+          Hubble constant in [km/sec/Mpc] at z=0
+
+        Om0 : float
+          Omega matter: density of non-relativistic matter in units
+          of the critical density at z=0.
+
+        Ode0 : float
+          Omega dark energy: density of dark energy in units
+          of the critical density at z=0.
+
+        wp : float
+          Dark energy equation of state at the pivot redshift zp.
+          This is pressure/density for dark energy in units where c=1.
+
+        wa : float
+          Negative derivative of the dark energy equation of state
+          with respect to the scale factor.  A cosmological constant
+          has w0=-1.0 and wa=0.0.
+
+        zp : float
+          Pivot redshift -- the redshift where w(z) = wp
+
+        Tcmb0 : float
+          Temperature of the CMB in Kelvin at z=0 (def: 2.725)
+
+        Neff : float
+          Effective number of Neutrino species (def: 3.04)
+
+        name : string
+          Optional name for this cosmological object.
+        """
+        FLRW.__init__(self, H0, Om0, Ode0, Tcmb0, Neff, name=name)
+        self._wp = float(wp)
+        self._wa = float(wa)
+        self._zp = float(zp)
+
+    def __repr__(self):
+        str = "%s(H0=%.3g, Om0=%.3g, Ode0=%.3g, Ok0=%.3g, wp=%.3g, "+\
+            "wa=%.3g, zp=%.3g)"
+        return str % (self.name, self._H0, self._Om0, self._Ode0,
+                      self._Ok0, self._wp, self._wa, self._zp)
+
+    @property
+    def wp(self):
+        """ Dark energy equation of state at the pivot redshift zp"""
+        return self._wp
+
+    @property
+    def wa(self):
+        """ Negative derivative of dark energy equation of state w.r.t. a"""
+        return self._wa
+
+    @property
+    def zp(self):
+        """ The pivot redshift, where w(z) = wp"""
+        return self._zp
+
+    def w(self, z):
+        """Returns dark energy equation of state at redshift `z`.
+
+        Parameters
+        ----------
+        z : array_like
+          Input redshifts.
+
+        Returns
+        -------
+        w : ndarray, or float if input scalar
+          The dark energy equation of state
+
+        Notes
+        ------
+        The dark energy equation of state is defined as
+        :math:`w(z) = P(z)/\\rho(z)`, where :math:`P(z)` is the
+        pressure at redshift z and :math:`\\rho(z)` is the density
+        at redshift z, both in units where c=1.  Here this is
+        :math:`w(z) = w_p + w_a (a_p - a)` where :math:`a = 1/1+z`
+        and :math:`a_p = 1 / 1 + z_p`.
+        """
+
+        if isiterable(z):
+            z = np.asarray(z)
+
+        apiv = 1.0 / (1.0 + self._zp)
+        return self._wp + self._wa * (apiv - 1.0 / (1. + z))
+
+    def de_density_scale(self, z):
+        """ Evaluates the redshift dependence of the dark energy density.
+
+        Parameters
+        ----------
+        z : array_like
+          Input redshifts.
+
+        Returns
+        -------
+        I : ndarray, or float if input scalar
+          The scaling of the energy density of dark energy with redshift.
+
+        Notes
+        -----
+        The scaling factor, I, is defined by :math:`\\rho(z) = \\rho_0 I`,
+        and in this case is given by
+
+        .. math::
+
+          a_p = \\frac{1}{1 + z_p}
+
+          I = \\left(1 + z\\right)^{3 \\left(1 + w_p + a_p w_a\\right)}
+          \exp \\left(-3 w_a \\frac{z}{1+z}\\right)
+        """
+
+        if isiterable(z):
+            z = np.asarray(z)
+        zp1 = 1.0 + z
+        apiv = 1.0 / (1.0 + self._zp)
+        return zp1**(3 * (1 + self._wp + apiv * self._wa)) * \
+            exp(-3 * self._wa * z / zp1)
+
+class w0wzCDM(FLRW):
+    """FLRW cosmology with a variable dark energy equation of state
+    and curvature.
+
+    The equation for the dark energy equation of state uses the
+    simple form: :math:`w(z) = w_0 + w_z z`.
+
+    This form is not recommended for z > 1.
+
+    Examples
+    --------
+    >>> from astro.cosmology import wawzCDM
+    >>> cosmo = wawzCDM(H0=70, Om0=0.3, Ode0=0.7, w0=-0.9, wz=0.2)
+
+    The comoving distance in Mpc at redshift z:
+
+    >>> dc = cosmo.comoving_distance(z)
+    """
+
+    def __init__(self, H0, Om0, Ode0, w0=-1., wz=0., Tcmb0=2.725,
+                 Neff=3.04, name='w0wzCDM'):
+        """ Initializer.
+
+        Parameters
+        ----------
+        H0 : float
+          Hubble constant in [km/sec/Mpc] at z=0
+
+        Om0 : float
+          Omega matter: density of non-relativistic matter in units
+          of the critical density at z=0.
+
+        Ode0 : float
+          Omega dark energy: density of dark energy in units
+          of the critical density at z=0.
+
+        Ok0 : float
+          Omega curvature: equivalent curvature density in units
+          of the critical density at z=0.
+
+        w0 : float
+          Dark energy equation of state at z=0.
+          This is pressure/density for dark energy in units where c=1.
+          A cosmological constant has w0=-1.0.
+
+        wz : float
+          Derivative of the dark energy equation of state with respect to z.
+
+        Tcmb0 : float
+          Temperature of the CMB in Kelvin at z=0 (def: 2.725)
+
+        Neff : float
+          Effective number of Neutrino species (def: 3.04)
+
+        name : string
+          Optional name for this cosmological object.
+        """
+        FLRW.__init__(self, H0, Om0, Ode0, Tcmb0, Neff, name=name)
+        self._w0 = float(w0)
+        self._wz = float(wz)
+
+    def __repr__(self):
+        return "%s(H0=%.3g, Om0=%.3g, Ode0=%.3g, w0=%.3g, wz=%.3g)" % \
+            (self.name, self._H0, self._Om0, self._Ode0, self._w0, self._wz)
+
+    @property
+    def w0(self):
+        """ Dark energy equation of state at z=0"""
+        return self._w0
+
+    @property
+    def wz(self):
+        """ Derivative of the dark energy equation of state w.r.t. z"""
+        return self._wz
+
+    def w(self, z):
+        """Returns dark energy equation of state at redshift `z`.
+
+        Parameters
+        ----------
+        z : array_like
+          Input redshifts.
+
+        Returns
+        -------
+        w : ndarray, or float if input scalar
+          The dark energy equation of state
+
+        Notes
+        ------
+        The dark energy equation of state is defined as
+        :math:`w(z) = P(z)/\\rho(z)`, where :math:`P(z)` is the
+        pressure at redshift z and :math:`\\rho(z)` is the density
+        at redshift z, both in units where c=1.  Here this is given by
+        :math:`w(z) = w_0 + w_z z`.
+        """
+
+        if isiterable(z):
+            z = np.asarray(z)
+
+        return self._w0 + self._wz * z
+
+    def de_density_scale(self, z):
+        """ Evaluates the redshift dependence of the dark energy density.
+
+        Parameters
+        ----------
+        z : array_like
+          Input redshifts.
+
+        Returns
+        -------
+        I : ndarray, or float if input scalar
+          The scaling of the energy density of dark energy with redshift.
+
+        Notes
+        -----
+        The scaling factor, I, is defined by :math:`\\rho(z) = \\rho_0 I`,
+        and in this case is given by
+
+        .. math::
+
+          I = \\left(1 + z\\right)^{3 \\left(1 + w_0 - w_z\\right)}
+          \exp \\left(-3 w_z z\\right)
+        """
+
+        if isiterable(z):
+            z = np.asarray(z)
+        zp1 = 1.0 + z
+        return zp1**(3 * (1 + self._w0 - self._wz)) * exp(-3 * self._wz * z)
+
+# Pre-defined cosmologies. This loops over the parameter sets in the
+# parameters module and creates a LambdaCDM or FlatLambdaCDM instance
+# with the same name as the parameter set in the current module's namespace.
+# Note this assumes all the cosmologies in parameters are LambdaCDM,
+# which is true at least as of this writing.
+
+for key in parameters.available:
+    par = getattr(parameters, key)
+    if par['flat']:
+        cosmo = FlatLambdaCDM(par['H0'], par['Om0'], Tcmb0=par['Tcmb0'],
+                              Neff=par['Neff'], name=key)
+    else:
+        cosmo = LambdaCDM(par['H0'], par['Om0'], par['Ode0'],
+                          Tcmb0=par['Tcmb0'], Neff=par['Neff'],
+                          m_nu=par['m_nu'], name=key)
     cosmo.__doc__ = "%s cosmology\n\n(from %s)" % (key, par['reference'])
     setattr(sys.modules[__name__], key, cosmo)
 
diff --git a/astropy/cosmology/funcs.py b/astropy/cosmology/funcs.py
index 098283b..4292b81 100644
--- a/astropy/cosmology/funcs.py
+++ b/astropy/cosmology/funcs.py
@@ -95,6 +95,9 @@ def arcsec_per_kpc_proper(z, cosmo=None):
 def distmod(z, cosmo=None):
     """ Distance modulus at redshift `z`.
 
+    The distance modulus is defined as the (apparent magnitude -
+    absolute magnitude) for an object at redshift `z`.
+
     Parameters
     ----------
     z : array_like
@@ -110,7 +113,7 @@ def distmod(z, cosmo=None):
     return cosmo.distmod(z)
 
 
-def H(z=0, cosmo=None):
+def H(z, cosmo=None):
     """ Hubble parameter (km/s/Mpc) at redshift `z`.
 
     Parameters
@@ -128,9 +131,11 @@ def H(z=0, cosmo=None):
     return cosmo.H(z)
 
 
-def scale_factor(z=0, cosmo=None):
+def scale_factor(z, cosmo=None):
     """ Scale factor at redshift `z`.
 
+    The scale factor is defined as `a = 1 / (1 + z)`.
+
     Parameters
     ----------
     z : array_like
@@ -146,7 +151,7 @@ def scale_factor(z=0, cosmo=None):
     return cosmo.scale_factor(z)
 
 
-def critical_density(z=0, cosmo=None):
+def critical_density(z, cosmo=None):
     """ Critical density in grams per cubic cm at redshift `z`.
 
     Parameters
@@ -164,9 +169,12 @@ def critical_density(z=0, cosmo=None):
     return cosmo.critical_density(z)
 
 
-def lookback_time(z=0, cosmo=None):
+def lookback_time(z, cosmo=None):
     """ Lookback time in Gyr to redshift `z`.
 
+    The lookback time is the difference between the age of the
+    Universe now and the age at redshift `z`.
+
     Parameters
     ----------
     z : array_like
@@ -182,9 +190,12 @@ def lookback_time(z=0, cosmo=None):
     return cosmo.lookback_time(z)
 
 
-def comoving_distance(z=0, cosmo=None):
+def comoving_distance(z, cosmo=None):
     """ Comoving distance in Mpc at redshift `z`.
 
+    The comoving distance along the line-of-sight between two objects
+    remains constant with time for objects in the Hubble flow.
+
     Parameters
     ----------
     z : array_like
@@ -200,9 +211,13 @@ def comoving_distance(z=0, cosmo=None):
     return cosmo.comoving_distance(z)
 
 
-def angular_diameter_distance(z=0, cosmo=None):
+def angular_diameter_distance(z, cosmo=None):
     """ Angular diameter distance in Mpc at a given redshift.
 
+    This gives the proper (sometimes called 'physical') transverse
+    distance corresponding to an angle of 1 radian for an object at
+    redshift `z`.
+
     Parameters
     ----------
     z : array_like
@@ -218,8 +233,11 @@ def angular_diameter_distance(z=0, cosmo=None):
     return cosmo.angular_diameter_distance(z)
 
 
-def luminosity_distance(z=0, cosmo=None):
-    """ Angular diameter distance in Mpc at a given redshift.
+def luminosity_distance(z, cosmo=None):
+    """ Luminosity distance in Mpc at redshift `z`.
+
+    This is the distance to use when converting between the bolometric
+    flux from an object at redshift `z` and its bolometric luminosity.
 
     Parameters
     ----------
diff --git a/astropy/cosmology/parameters.py b/astropy/cosmology/parameters.py
index b7199e3..4029a13 100644
--- a/astropy/cosmology/parameters.py
+++ b/astropy/cosmology/parameters.py
@@ -5,12 +5,15 @@ given cosmology.
 Each cosmology has the following parameters defined:
 
     ==========  =====================================
-    Oc          Omega cold dark matter
-    Ob          Omega baryon
-    Om          Omega matter
-    Ol          Omega lambda
+    Oc0         Omega cold dark matter at z=0
+    Ob0         Omega baryon at z=0
+    Om0         Omega matter at z=0
+    flat        Is this assumed flat?  If not, Ode0 must be specifiec
+    Ode0        Omega dark energy at z=0 if flat is False
     H0          Hubble parameter at z=0 in km/s/Mpc
     n           Density perturbation spectral index
+    Tcmb0       Current temperature of the CMB
+    Neff        Effective number of neutrino species
     sigma8      Density perturbation amplitude
     tau         Ionisation optical depth
     z_reion     Redshift of hydrogen reionisation
@@ -27,22 +30,25 @@ WMAP 7 year parameters from Komatsu et al. 2011, ApJS, 192, 18. Table
 WMAP 5 year parameters from Komatsu et al. 2009, ApJS, 180, 330. Table
 1 (WMAP + BAO + SN ML).
 
-Both these cosmologies are flat (omega matter + omega lambda = 1).
+Both these cosmologies are flat (omega matter + omega dark energy = 1)
+and assume dark enegy is the cosmological constant (w0 = -1, wa = 0).
 """
 
 # Komatsu et al. 2011, WMAP + BAO + H0 ML (table 1).
 
 WMAP7 = dict(
-    Oc = 0.226,
-    Ob = 0.0455,
-    Om = 0.272,
-    Ol = 0.728,
+    Oc0  = 0.226,
+    Ob0  = 0.0455,
+    Om0  = 0.272,
     H0 = 70.4,
     n = 0.967,
     sigma8 = 0.810,
     tau = 0.085,
     z_reion = 10.3,
     t0 = 13.76,
+    Tcmb0 = 2.725,
+    Neff = 3.04,
+    flat = True,
     reference = ("Komatsu et al. 2011, ApJS, 192, 18. "
                  "Table 1 (WMAP + BAO + H0 ML)")
     )
@@ -50,16 +56,18 @@ WMAP7 = dict(
 # Komatsu et al. 2009 WMAP + BAO + SN ML (table 1).
 
 WMAP5 = dict(
-    Oc = 0.231,
-    Ob = 0.0459,
-    Om = 0.277,
-    Ol = 0.723,
+    Oc0  = 0.231,
+    Ob0  = 0.0459,
+    Om0  = 0.277,
     H0 = 70.2,
     n = 0.962,
     sigma8 = 0.817,
     tau = 0.088,
     z_reion = 11.3,
     t0 = 13.72,
+    Tcmb0 = 2.725,
+    Neff = 3.04,
+    flat = True,
     reference = ("Komatsu et al. 2009, ApJS, 180, 330. "
                  "Table 1 (WMAP + BAO + SN ML)")
     )
diff --git a/astropy/cosmology/tests/test_cosmology.py b/astropy/cosmology/tests/test_cosmology.py
index 516fbee..f5831aa 100644
--- a/astropy/cosmology/tests/test_cosmology.py
+++ b/astropy/cosmology/tests/test_cosmology.py
@@ -2,7 +2,7 @@
 from StringIO import StringIO
 from .. import core, funcs
 import numpy as np
-import pytest
+from ...tests.helper import pytest
 
 try:
     import scipy
@@ -11,13 +11,12 @@ except ImportError:
 else:
     HAS_SCIPY = True
 
-
 @pytest.mark.skipif('not HAS_SCIPY')
 def test_flat_z1():
     """ Test a flat cosmology at z=1 against several other on-line
     calculators.
     """
-    cosmo = core.FLRWCosmology(H0=70, Om=0.27, Ol=0.73)
+    cosmo = core.FlatLambdaCDM(H0=70, Om0=0.27, Tcmb0=0.0)
     z = 1
 
     # Test values were taken from the following web cosmology
@@ -38,10 +37,125 @@ def test_flat_z1():
     assert np.allclose(cosmo.lookback_time(z),
                        [7.841, 7.84178, 7.843],  rtol=1e-3)
 
+
+#This class is to test whether the routines work correctly
+# if one only overloads w(z)
+class test_cos(core.FLRW):
+    def __init__(self):
+        core.FLRW.__init__(self, 70.0, 0.27, 0.73, Tcmb0=0.0, name="test_cos")
+        self._w0 = -0.9
+
+    def w(self,z):
+        return self._w0*np.ones_like(z)
+
+ at pytest.mark.skipif('not HAS_SCIPY')
+def test_de_subclass():
+    #This is the comparison object
+    z = [0.2, 0.4, 0.6, 0.9]
+    cosmo = core.wCDM(H0=70, Om0=0.27, Ode0=0.73, w0=-0.9, Tcmb0=0.0)
+    #Values taken from Ned Wrights advanced cosmo calcluator, Aug 17 2012
+    assert np.allclose(cosmo.luminosity_distance(z),
+                       [975.5, 2158.2, 3507.3, 5773.1], rtol=1e-3)
+    #Now try the subclass that only gives w(z)
+    cosmo = test_cos()
+    assert np.allclose(cosmo.luminosity_distance(z),
+                       [975.5, 2158.2, 3507.3, 5773.1], rtol=1e-3)
+
+
+ at pytest.mark.skipif('not HAS_SCIPY')
+def test_varyde_lumdist_mathematica():
+    """Tests a few varying dark energy EOS models against a mathematica
+    computation"""
+
+    #w0wa models
+    z = np.array([0.2,0.4,0.9,1.2])
+    cosmo = core.w0waCDM(H0=70, Om0=0.2, Ode0=0.8, w0=-1.1, wa=0.2, Tcmb0=0.0)
+    assert np.allclose(cosmo.luminosity_distance(z),
+                       [1004.0,2268.62,6265.76,9061.84], rtol=1e-4)
+    cosmo = core.w0waCDM(H0=70, Om0=0.3, Ode0=0.7, w0=-0.9, wa=0.0, Tcmb0=0.0)
+    assert np.allclose(cosmo.luminosity_distance(z),
+                       [971.667,2141.67,5685.96,8107.41], rtol=1e-4)
+    cosmo = core.w0waCDM(H0=70, Om0=0.3, Ode0=0.7, w0=-0.9, wa=-0.5, Tcmb0=0.0)
+    assert np.allclose(cosmo.luminosity_distance(z),
+                       [974.087,2157.08,5783.92,8274.08], rtol=1e-4)
+
+    #wpwa models
+    cosmo = core.wpwaCDM(H0=70, Om0=0.2, Ode0=0.8, wp=-1.1, wa=0.2, zp=0.5,
+                         Tcmb0=0.0)
+    assert np.allclose(cosmo.luminosity_distance(z),
+                       [1010.81,2294.45,6369.45,9218.95], rtol=1e-4)
+    cosmo = core.wpwaCDM(H0=70, Om0=0.2, Ode0=0.8, wp=-1.1, wa=0.2, zp=0.9,
+                         Tcmb0=0.0)
+    assert np.allclose(cosmo.luminosity_distance(z),
+                       [1013.68,2305.3,6412.37,9283.33], rtol=1e-4)
+
+ at pytest.mark.skipif('not HAS_SCIPY')
+def test_ogamma():
+    """Tests the effects of changing the temperature of the CMB"""
+
+    #Tested against Ned Wright's advanced cosmology calculator,
+    # Sep 7 2012.  The accuracy of our comparision is limited by
+    # how many digits it outputs, which limits our test to about
+    # 0.2% accuracy.  The NWACC does not allow one
+    # to change the number of nuetrino species, fixing that at 3.
+    # Also, inspection of the NWACC code shows it uses inaccurate
+    # constants at the 0.2% level (specifically, a_B),
+    # so we shouldn't expect to match it that well. The integral is
+    # also done rather crudely.  Therefore, we should not expect
+    # the NWACC to be accurate to better than about 0.5%, which is
+    # unfortunate, but reflects a problem with it rather than this code.
+    # More accurate tests below using Mathematica
+    z = np.array([1.0, 10.0, 500.0, 1000.0])
+    cosmo = core.FlatLambdaCDM(H0=70, Om0=0.3, Tcmb0=0, Neff=3)
+    assert np.allclose(cosmo.angular_diameter_distance(z),
+                       [1651.9, 858.2, 26.855, 13.642], rtol=5e-4)
+    cosmo = core.FlatLambdaCDM(H0=70, Om0=0.3, Tcmb0=2.725, Neff=3)
+    assert np.allclose(cosmo.angular_diameter_distance(z),
+                       [1651.8, 857.9, 26.767, 13.582], rtol=5e-4)
+    cosmo = core.FlatLambdaCDM(H0=70, Om0=0.3, Tcmb0=4.0, Neff=3)
+    assert np.allclose(cosmo.angular_diameter_distance(z),
+                       [1651.4, 856.6, 26.489, 13.405], rtol=5e-4)
+
+    #Next compare with doing the integral numerically in Mathematica,
+    # which allows more precision in the test.  It is at least as
+    # good as 0.01%, possibly better
+    cosmo = core.FlatLambdaCDM(H0=70, Om0=0.3, Tcmb0=0, Neff=3.04)
+    assert np.allclose(cosmo.angular_diameter_distance(z),
+                       [1651.91, 858.205, 26.8586, 13.6469], rtol=1e-5)
+    cosmo = core.FlatLambdaCDM(H0=70, Om0=0.3, Tcmb0=2.725, Neff=3.04)
+    assert np.allclose(cosmo.angular_diameter_distance(z),
+                       [1651.76, 857.817, 26.7688, 13.5841], rtol=1e-5)
+    cosmo = core.FlatLambdaCDM(H0=70, Om0=0.3, Tcmb0=4.0, Neff=3.04)
+    assert np.allclose(cosmo.angular_diameter_distance(z),
+                       [1651.21, 856.411, 26.4845, 13.4028], rtol=1e-5)
+
+    #Just to be really sure, we also do a version where the integral
+    # is analytic, which is a Ode = 0 flat universe.  In this case
+    # Integrate(1/E(x),{x,0,z}) = 2 ( sqrt((1+Or z)/(1+z)) - 1 )/(Or - 1)
+    # Recall that c/H0 * Integrate(1/E) is FLRW.comoving_distance.
+    Ogamma0h2 = 4*5.670373e-8/299792458.0**3 * 2.725**4 / 1.87837e-26
+    Onu0h2 = Ogamma0h2 * 7.0/8.0 * (4.0/11.0)**(4.0/3.0) * 3.04
+    Or0 = (Ogamma0h2 + Onu0h2) / 0.7**2
+    Om0 = 1.0 - Or0
+    hubdis = 299792.458 / 70.0
+    cosmo = core.FlatLambdaCDM(H0=70, Om0=Om0, Tcmb0=2.725, Neff=3.04)
+    targvals = 2.0 * hubdis * \
+        (np.sqrt((1.0 + Or0 * z) / (1.0 + z)) - 1.0) / (Or0 - 1.0)
+    assert np.allclose(cosmo.comoving_distance(z), targvals, rtol=1e-5)
+
+    #Try Tcmb0 = 4
+    Or0 *= (4.0/2.725)**4
+    Om0 = 1.0 - Or0
+    cosmo = core.FlatLambdaCDM(H0=70, Om0=Om0, Tcmb0=4.0, Neff=3.04)
+    targvals = 2.0 * hubdis * \
+        (np.sqrt((1.0 + Or0 * z) / (1.0 + z)) - 1.0) / (Or0 - 1.0)
+    assert np.allclose(cosmo.comoving_distance(z), targvals, rtol=1e-5)
+
 @pytest.mark.skipif('not HAS_SCIPY')
 def test_convenience():
-    #these are all for WMAP7
-    core.set_current(core.WMAP7)
+    #these are all for WMAP7 with Tcmb = 0
+    tcos = core.FlatLambdaCDM(70.4,0.272,Tcmb0=0.0)
+    core.set_current(tcos)
 
     # scalars
     assert np.allclose(funcs.arcsec_per_kpc_comoving(3), 0.0317179)
@@ -72,9 +186,9 @@ def test_convenience():
 @pytest.mark.skipif('not HAS_SCIPY')
 def test_comoving_volume():
 
-    c_flat = core.FLRWCosmology(H0=70, Om=0.27, Ol=0.73)
-    c_open = core.FLRWCosmology(H0=70, Om=0.27, Ol=0.0)
-    c_closed = core.FLRWCosmology(H0=70, Om=2, Ol=0.0)
+    c_flat = core.LambdaCDM(H0=70, Om0=0.27, Ode0=0.73, Tcmb0=0.0)
+    c_open = core.LambdaCDM(H0=70, Om0=0.27, Ode0=0.0, Tcmb0=0.0)
+    c_closed = core.LambdaCDM(H0=70, Om0=2, Ode0=0.0, Tcmb0=0.0)
 
     redshifts = 0.5, 1, 2, 3, 5, 9
 
@@ -202,25 +316,26 @@ def test_flat_open_closed_icosmo():
 """
 
     redshifts, dm, da, dl = np.loadtxt(StringIO(cosmo_flat), unpack=1)
-    cosmo = core.FLRWCosmology(H0=70, Om=0.3, Ol=0.70)
+    cosmo = core.LambdaCDM(H0=70, Om0=0.3, Ode0=0.70, Tcmb0=0.0)
     assert np.allclose(cosmo.comoving_transverse_distance(redshifts), dm)
     assert np.allclose(cosmo.angular_diameter_distance(redshifts), da)
     assert np.allclose(cosmo.luminosity_distance(redshifts), dl)
 
     redshifts, dm, da, dl = np.loadtxt(StringIO(cosmo_open), unpack=1)
-    cosmo = core.FLRWCosmology(H0=70, Om=0.3, Ol=0.1)
+    cosmo = core.LambdaCDM(H0=70, Om0=0.3, Ode0=0.1, Tcmb0=0.0)
     assert np.allclose(cosmo.comoving_transverse_distance(redshifts), dm)
     assert np.allclose(cosmo.angular_diameter_distance(redshifts), da)
     assert np.allclose(cosmo.luminosity_distance(redshifts), dl)
 
     redshifts, dm, da, dl = np.loadtxt(StringIO(cosmo_closed), unpack=1)
-    cosmo = core.FLRWCosmology(H0=70, Om=2, Ol=0.1)
+    cosmo = core.LambdaCDM(H0=70, Om0=2, Ode0=0.1, Tcmb0=0.0)
     assert np.allclose(cosmo.comoving_transverse_distance(redshifts), dm)
     assert np.allclose(cosmo.angular_diameter_distance(redshifts), da)
     assert np.allclose(cosmo.luminosity_distance(redshifts), dl)
 
 
 def test_current():
+    core.set_current('WMAP7')
     cosmo = core.get_current()
     assert cosmo == core.WMAP7
     core.set_current('WMAP5')
@@ -228,24 +343,51 @@ def test_current():
     core.set_current(cosmo)
     assert core.get_current() == cosmo
 
+def test_wz():
+    cosmo = core.LambdaCDM(H0=70, Om0=0.3, Ode0=0.70)
+    assert np.allclose(cosmo.w([0.1,0.2,0.5,1.5,2.5,11.5]),
+                       [-1.,-1,-1,-1,-1,-1])
+    cosmo = core.wCDM(H0=70, Om0=0.3, Ode0=0.70,w0=-0.5)
+    assert np.allclose(cosmo.w([0.1,0.2,0.5,1.5,2.5,11.5]),
+                       [-0.5,-0.5,-0.5,-0.5,-0.5,-0.5])
+    cosmo = core.w0wzCDM(H0=70, Om0=0.3, Ode0=0.70,w0=-1,wz=0.5)
+    assert np.allclose(cosmo.w([0.0,0.5,1.0,1.5,2.3]),
+                       [-1.0,-0.75,-0.5,-0.25,0.15])
+    cosmo = core.w0waCDM(H0=70, Om0=0.3, Ode0=0.70,w0=-1,wa=-0.5)
+    assert np.allclose(cosmo.w([0.0,0.5,1.0,1.5,2.3]),
+                       [-1,-1.16666667,-1.25, -1.3, -1.34848485])
+    cosmo = core.wpwaCDM(H0=70, Om0=0.3, Ode0=0.70,wp=-0.9,
+                         wa=0.2,zp=0.5)
+    assert np.allclose(cosmo.w([0.1,0.2,0.5,1.5,2.5,11.5]),
+                       [-0.94848485,-0.93333333,-0.9,-0.84666667,-0.82380952,
+                         -0.78266667])
+
 @pytest.mark.skipif('not HAS_SCIPY')
 def test_age():
-    assert np.allclose(core.WMAP7.age([1,5]), [ 5.97113193,  1.20553129])
+    #WMAP7 but with Omega_relativisitic = 0
+    tcos = core.FlatLambdaCDM(70.4,0.272,Tcmb0=0.0)
+    assert np.allclose(tcos.age([1,5]), [ 5.97113193,  1.20553129])
 
 @pytest.mark.skipif('not HAS_SCIPY')
 def test_distmod():
-    assert np.allclose(core.WMAP7.distmod([1,5]), [ 44.124857,  48.40167258])
-    assert np.allclose(funcs.distmod([1,5], cosmo=core.WMAP7),
+    #WMAP7 but with Omega_relativisitic = 0
+    tcos = core.FlatLambdaCDM(70.4,0.272,Tcmb0=0.0)
+    core.set_current(tcos)
+    assert np.allclose(tcos.distmod([1,5]), [ 44.124857,  48.40167258])
+    assert np.allclose(funcs.distmod([1,5], cosmo=tcos),
                        [ 44.124857,  48.40167258])
 
 @pytest.mark.skipif('not HAS_SCIPY')
 def test_critical_density():
-    assert np.allclose(core.WMAP7.critical_density([1,5]),
-                       [  2.70362491e-29, 5.53758986e-28])
+    #WMAP7 but with Omega_relativisitic = 0
+    tcos = core.FlatLambdaCDM(70.4,0.272,Tcmb0=0.0)
+    assert np.allclose(tcos.critical_density([1,5]),
+                       [2.70362491e-29, 5.53758986e-28])
 
 @pytest.mark.skipif('not HAS_SCIPY')
 def test_angular_diameter_distance_z1z2():
-    assert (core.WMAP7.angular_diameter_distance_z1z2(1, 2) ==
+    tcos = core.FlatLambdaCDM(70.4,0.272,Tcmb0=0.0)
+    assert (tcos.angular_diameter_distance_z1z2(1, 2) ==
             646.22968662822018)
     z1 = 0, 0, 1, 0.5, 1
     z2 = 2, 1, 2, 2.5, 1.1
@@ -255,5 +397,13 @@ def test_angular_diameter_distance_z1z2():
                1159.0970895962193,
                115.72768186186921)
 
-    assert np.allclose(core.WMAP7.angular_diameter_distance_z1z2(z1, z2),
+    assert np.allclose(tcos.angular_diameter_distance_z1z2(z1, z2),
                        results)
+
+ at pytest.mark.skipif('not HAS_SCIPY')
+def test_absorption_distance():
+    tcos = core.FlatLambdaCDM(70.4,0.272,Tcmb0=0.0)
+    assert np.allclose(tcos.absorption_distance([1,3]),
+                       [ 1.72576635,  7.98685853])
+    assert np.allclose(tcos.absorption_distance(3), 7.98685853)
+
diff --git a/astropy/data/README.rst b/astropy/data/README.rst
deleted file mode 100644
index feb98cc..0000000
--- a/astropy/data/README.rst
+++ /dev/null
@@ -1,7 +0,0 @@
-Data directory
-==============
-
-This directory contains data files included with the astropy source code
-distribution.  Note that this is intended only for relatively small files - 
-large files should be externally hosted and downloaded as needed.
-
diff --git a/astropy/extern/configobj_py3/__init__.py b/astropy/extern/configobj_py3/__init__.py
deleted file mode 100644
index 54e9e57..0000000
--- a/astropy/extern/configobj_py3/__init__.py
+++ /dev/null
@@ -1,104 +0,0 @@
-# Licensed under a 3-clause BSD style license - see LICENSE.rst  
-
-"""
-This is a copy of the main portions of the  `configobj 
-<http://www.voidspace.org.uk/python/configobj.html>`_ package. This is used
-internally in the Astropy configuration system. The license for configobj is
-available  in the ``licenses/CONFIGOBJ_LICENSE.rst`` file in the Astropy
-source distribution.
-
-This is a version of configobj that has been modified by Zubin Mithra to be
-compatible with python 3.x.  This version is not official, but has been
-"blessed" by configobj's original author. This version of the code was
-obtained from https://bitbucket.org/zubin71/configobj-py3
-
-For a python 2.x version, see the ``astropy/extern/configobj`` directory.
-""" 
-
-#this holds the contents of the setup.py file used by configobj
-_configobj_setup_dot_py="""
-# setup.py
-# Install script for ConfigObj
-# Copyright (C) 2005-2010 Michael Foord, Mark Andrews, Nicola Larosa
-# E-mail: fuzzyman AT voidspace DOT org DOT uk
-#         mark AT la-la DOT com
-#         nico AT tekNico DOT net
-
-# This software is licensed under the terms of the BSD license.
-# http://www.voidspace.org.uk/python/license.shtml
-
-import sys
-from distutils.core import setup
-from configobj import __version__ as VERSION
-
-NAME = 'configobj'
-
-MODULES = 'configobj', 'validate'
-
-DESCRIPTION = 'Config file reading, writing and validation.'
-
-URL = 'http://www.voidspace.org.uk/python/configobj.html'
-
-DOWNLOAD_URL = "http://www.voidspace.org.uk/downloads/configobj-%s.zip" % VERSION
-
-LONG_DESCRIPTION = ""#"**ConfigObj** is a simple but powerful config file reader and writer: an *ini
-file round tripper*. Its main feature is that it is very easy to use, with a
-straightforward programmer's interface and a simple syntax for config files.
-It has lots of other features though :
-
-* Nested sections (subsections), to any level
-* List values
-* Multiple line values
-* Full Unicode support
-* String interpolation (substitution)
-* Integrated with a powerful validation system
-
-    - including automatic type checking/conversion
-    - and allowing default values
-    - repeated sections
-
-* All comments in the file are preserved
-* The order of keys/sections is preserved
-* Powerful ``unrepr`` mode for storing/retrieving Python data-types
-
-| Release 4.7.2 fixes several bugs in 4.7.1
-| Release 4.7.1 fixes a bug with the deprecated options keyword in
-| 4.7.0.
-| Release 4.7.0 improves performance adds features for validation and
-| fixes some bugs.""#"
-
-CLASSIFIERS = [
-    'Development Status :: 6 - Mature',
-    'Intended Audience :: Developers',
-    'License :: OSI Approved :: BSD License',
-    'Programming Language :: Python',
-    'Programming Language :: Python :: 2.3',
-    'Programming Language :: Python :: 2.4',
-    'Programming Language :: Python :: 2.5',
-    'Programming Language :: Python :: 2.6',
-    'Operating System :: OS Independent',
-    'Topic :: Software Development :: Libraries',
-    'Topic :: Software Development :: Libraries :: Python Modules',
-]
-
-AUTHOR = 'Michael Foord & Nicola Larosa'
-
-AUTHOR_EMAIL = 'fuzzyman at voidspace.org.uk'
-
-KEYWORDS = "config, ini, dictionary, application, admin, sysadmin, configuration, validation".split(', ')
-
-
-setup(name=NAME,
-      version=VERSION,
-      description=DESCRIPTION,
-      long_description=LONG_DESCRIPTION,
-      download_url=DOWNLOAD_URL,
-      author=AUTHOR,
-      author_email=AUTHOR_EMAIL,
-      url=URL,
-      py_modules=MODULES,
-      classifiers=CLASSIFIERS,
-      keywords=KEYWORDS
-     )
-""".replace('""#"','"""') 
-#the replacement is necessary because """ would otherwise terminate the string
diff --git a/astropy/extern/configobj_py3/configobj.py b/astropy/extern/configobj_py3/configobj.py
deleted file mode 100644
index 70c89f2..0000000
--- a/astropy/extern/configobj_py3/configobj.py
+++ /dev/null
@@ -1,2405 +0,0 @@
-# configobj.py
-# A config file reader/writer that supports nested sections in config files.
-# Copyright (C) 2005-2010 Michael Foord, Nicola Larosa
-# E-mail: fuzzyman AT voidspace DOT org DOT uk
-#         nico AT tekNico DOT net
-
-# ConfigObj 4
-# http://www.voidspace.org.uk/python/configobj.html
-
-# Released subject to the BSD License
-# Please see http://www.voidspace.org.uk/python/license.shtml
-
-# Scripts maintained at http://www.voidspace.org.uk/python/index.shtml
-# For information about bugfixes, updates and support, please join the
-# ConfigObj mailing list:
-# http://lists.sourceforge.net/lists/listinfo/configobj-develop
-# Comments, suggestions and bug reports welcome.
-import pdb
-
-import os
-import re
-import sys
-
-from codecs import BOM_UTF8, BOM_UTF16, BOM_UTF16_BE, BOM_UTF16_LE
-
-from ast import parse
-
-# A dictionary mapping BOM to
-# the encoding to decode with, and what to set the
-# encoding attribute to.
-BOMS = {
-    BOM_UTF8: ('utf_8', None),
-    BOM_UTF16_BE: ('utf16_be', 'utf_16'),
-    BOM_UTF16_LE: ('utf16_le', 'utf_16'),
-    BOM_UTF16: ('utf_16', 'utf_16'),
-    }
-    
-# All legal variants of the BOM codecs.
-# TODO: the list of aliases is not meant to be exhaustive, is there a
-# better way ?
-BOM_LIST = {
-    'utf_16': 'utf_16',
-    'u16': 'utf_16',
-    'utf16': 'utf_16',
-    'utf-16': 'utf_16',
-    'utf16_be': 'utf16_be',
-    'utf_16_be': 'utf16_be',
-    'utf-16be': 'utf16_be',
-    'utf16_le': 'utf16_le',
-    'utf_16_le': 'utf16_le',
-    'utf-16le': 'utf16_le',
-    'utf_8': 'utf_8',
-    'u8': 'utf_8',
-    'utf': 'utf_8',
-    'utf8': 'utf_8',
-    'utf-8': 'utf_8',
-    }
-
-# Map of encodings to the BOM to write.
-BOM_SET = {
-    'utf_8': BOM_UTF8,
-    'utf_16': BOM_UTF16,
-    'utf16_be': BOM_UTF16_BE,
-    'utf16_le': BOM_UTF16_LE,
-    None: BOM_UTF8
-    }
-
-
-def match_utf8(encoding):
-    return BOM_LIST.get(encoding.lower()) == 'utf_8'
-
-# Quote strings used for writing values
-squot = "'%s'"
-dquot = '"%s"'
-noquot = "%s"
-wspace_plus = ' \r\n\v\t\'"'
-tsquot = '"""%s"""'
-tdquot = "'''%s'''"
-
-# Sentinel for use in getattr calls to replace hasattr
-MISSING = object()
-
-__version__ = '4.7.2'
-
-try:
-    any
-except NameError:
-    def any(iterable):
-        for entry in iterable:
-            if entry:
-                return True
-        return False
-
-__all__ = (
-    '__version__',
-    'DEFAULT_INDENT_TYPE',
-    'DEFAULT_INTERPOLATION',
-    'ConfigObjError',
-    'NestingError',
-    'ParseError',
-    'DuplicateError',
-    'ConfigspecError',
-    'ConfigObj',
-    'SimpleVal',
-    'InterpolationError',
-    'InterpolationLoopError',
-    'MissingInterpolationOption',
-    'RepeatSectionError',
-    'ReloadError',
-    'UnreprError',
-    'UnknownType',
-    'flatten_errors',
-    'get_extra_values'
-)
-
-DEFAULT_INTERPOLATION = 'configparser'
-DEFAULT_INDENT_TYPE = '    '
-MAX_INTERPOL_DEPTH = 10
-
-OPTION_DEFAULTS = {
-    'interpolation': True,
-    'raise_errors': False,
-    'list_values': True,
-    'create_empty': False,
-    'file_error': False,
-    'configspec': None,
-    'stringify': True,
-    # option may be set to one of ('', ' ', '\t')
-    'indent_type': None,
-    'encoding': None,
-    'default_encoding': None,
-    'unrepr': False,
-    'write_empty_values': False,
-}
-
-def getObj(s):
-    p = parse("a=" + s)
-    obj = p.body[0].value
-    return obj
-    
-class UnknownType(Exception):
-    pass
-
-class Builder(object):
-
-    def build(self, o):
-
-        m = getattr(self, 'build_' + o.__class__.__name__, None)
-        if m is None:
-            raise UnknownType(o.__class__.__name__)
-        return m(o)
-
-    def build_List(self, o):
-        return map(self.build, o.elts)
-    
-    def build_Num(self, o):
-        return o.n
-
-    def build_Str(str, o):
-        return o.s
-
-    def build_Dict(self, o):
-        d = {}
-        items = zip(o.keys, o.values)
-        for key, value in items:
-            key = self.build(key)
-            value = self.build(value)
-            d[key] = value
-        return d
-
-    def build_Tuple(self, o):
-        return tuple(self.build_List(o))
-
-    def build_Name(self, o):
-        value = o.id
-        if value == 'None':
-            return None
-        if value == 'True':
-            return True
-        if value == 'False':
-            return False
-
-        # An undefined Name
-        raise UnknownType('Undefined Name')
-
-_builder = Builder()
-
-def unrepr(s):
-    if not s:
-        return s
-    return _builder.build(getObj(s))
-    
-    
-class ConfigObjError(SyntaxError):
-    """
-    This is the base class for all errors that ConfigObj raises.
-    It is a subclass of SyntaxError.
-    """
-    def __init__(self, message='', line_number=None, line=''):
-        self.line = line
-        self.line_number = line_number
-        SyntaxError.__init__(self, message)
-
-
-class NestingError(ConfigObjError):
-    """
-    This error indicates a level of nesting that doesn't match.
-    """
-
-
-class ParseError(ConfigObjError):
-    """
-    This error indicates that a line is badly written.
-    It is neither a valid ``key = value`` line,
-    nor a valid section marker line.
-    """
-
-
-class ReloadError(IOError):
-    """
-    A 'reload' operation failed.
-    This exception is a subclass of ``IOError``.
-    """
-    def __init__(self):
-        IOError.__init__(self, 'reload failed, filename is not set.')
-
-
-class DuplicateError(ConfigObjError):
-    """
-    The keyword or section specified already exists.
-    """
-
-
-class ConfigspecError(ConfigObjError):
-    """
-    An error occured whilst parsing a configspec.
-    """
-
-
-class InterpolationError(ConfigObjError):
-    """Base class for the two interpolation errors."""
-
-
-class InterpolationLoopError(InterpolationError):
-    """Maximum interpolation depth exceeded in string interpolation."""
-
-    def __init__(self, option):
-        InterpolationError.__init__(
-            self,
-            'interpolation loop detected in value "%s".' % option)
-
-
-class RepeatSectionError(ConfigObjError):
-    """
-    This error indicates additional sections in a section with a
-    ``__many__`` (repeated) section.
-    """
-
-
-class MissingInterpolationOption(InterpolationError):
-    """A value specified for interpolation was missing."""
-    def __init__(self, option):
-        msg = 'missing option "%s" in interpolation.' % option
-        InterpolationError.__init__(self, msg)
-
-
-class UnreprError(ConfigObjError):
-    """An error parsing in unrepr mode."""
-
-
-class InterpolationEngine(object):
-    """
-    A helper class to help perform string interpolation.
-
-    This class is an abstract base class; its descendants perform
-    the actual work.
-    """
-
-    # compiled regexp to use in self.interpolate()
-    _KEYCRE = re.compile(r"%\(([^)]*)\)s")
-    _cookie = '%'
-
-    def __init__(self, section):
-        # the Section instance that "owns" this engine
-        self.section = section
-
-
-    def interpolate(self, key, value):
-        # short-cut
-        if not self._cookie in value:
-            return value
-        
-        def recursive_interpolate(key, value, section, backtrail):
-            """The function that does the actual work.
-
-            ``value``: the string we're trying to interpolate.
-            ``section``: the section in which that string was found
-            ``backtrail``: a dict to keep track of where we've been,
-            to detect and prevent infinite recursion loops
-
-            This is similar to a depth-first-search algorithm.
-            """
-            # Have we been here already?
-            if (key, section.name) in backtrail:
-                # Yes - infinite loop detected
-                raise InterpolationLoopError(key)
-            # Place a marker on our backtrail so we won't come back here again
-            backtrail[(key, section.name)] = 1
-
-            # Now start the actual work
-            match = self._KEYCRE.search(value)
-            while match:
-                # The actual parsing of the match is implementation-dependent,
-                # so delegate to our helper function
-                k, v, s = self._parse_match(match)
-                if k is None:
-                    # That's the signal that no further interpolation is needed
-                    replacement = v
-                else:
-                    # Further interpolation may be needed to obtain final value
-                    replacement = recursive_interpolate(k, v, s, backtrail)
-                # Replace the matched string with its final value
-                start, end = match.span()
-                value = ''.join((value[:start], replacement, value[end:]))
-                new_search_start = start + len(replacement)
-                # Pick up the next interpolation key, if any, for next time
-                # through the while loop
-                match = self._KEYCRE.search(value, new_search_start)
-
-            # Now safe to come back here again; remove marker from backtrail
-            del backtrail[(key, section.name)]
-
-            return value
-
-        # Back in interpolate(), all we have to do is kick off the recursive
-        # function with appropriate starting values
-        value = recursive_interpolate(key, value, self.section, {})
-        return value
-
-
-    def _fetch(self, key):
-        """Helper function to fetch values from owning section.
-
-        Returns a 2-tuple: the value, and the section where it was found.
-        """
-        # switch off interpolation before we try and fetch anything !
-        save_interp = self.section.main.interpolation
-        self.section.main.interpolation = False
-
-        # Start at section that "owns" this InterpolationEngine
-        current_section = self.section
-        while True:
-            # try the current section first
-            val = current_section.get(key)
-            if val is not None and not isinstance(val, Section):
-                break
-            # try "DEFAULT" next
-            val = current_section.get('DEFAULT', {}).get(key)
-            if val is not None and not isinstance(val, Section):
-                break
-            # move up to parent and try again
-            # top-level's parent is itself
-            if current_section.parent is current_section:
-                # reached top level, time to give up
-                break
-            current_section = current_section.parent
-
-        # restore interpolation to previous value before returning
-        self.section.main.interpolation = save_interp
-        if val is None:
-            raise MissingInterpolationOption(key)
-        return val, current_section
-
-
-    def _parse_match(self, match):
-        """Implementation-dependent helper function.
-
-        Will be passed a match object corresponding to the interpolation
-        key we just found (e.g., "%(foo)s" or "$foo"). Should look up that
-        key in the appropriate config file section (using the ``_fetch()``
-        helper function) and return a 3-tuple: (key, value, section)
-
-        ``key`` is the name of the key we're looking for
-        ``value`` is the value found for that key
-        ``section`` is a reference to the section where it was found
-
-        ``key`` and ``section`` should be None if no further
-        interpolation should be performed on the resulting value
-        (e.g., if we interpolated "$$" and returned "$").
-        """
-        raise NotImplementedError()
-
-
-class ConfigParserInterpolation(InterpolationEngine):
-    """Behaves like ConfigParser."""
-    _cookie = '%'
-    _KEYCRE = re.compile(r"%\(([^)]*)\)s")
-
-    def _parse_match(self, match):
-        key = match.group(1)
-        value, section = self._fetch(key)
-        return key, value, section
-
-
-class TemplateInterpolation(InterpolationEngine):
-    """Behaves like string.Template."""
-    _cookie = '$'
-    _delimiter = '$'
-    _KEYCRE = re.compile(r"""
-        \$(?:
-          (?P<escaped>\$)              |   # Two $ signs
-          (?P<named>[_a-z][_a-z0-9]*)  |   # $name format
-          {(?P<braced>[^}]*)}              # ${name} format
-        )
-        """, re.IGNORECASE | re.VERBOSE)
-
-    def _parse_match(self, match):
-        # Valid name (in or out of braces): fetch value from section
-        key = match.group('named') or match.group('braced')
-        if key is not None:
-            value, section = self._fetch(key)
-            return key, value, section
-        # Escaped delimiter (e.g., $$): return single delimiter
-        if match.group('escaped') is not None:
-            # Return None for key and section to indicate it's time to stop
-            return None, self._delimiter, None
-        # Anything else: ignore completely, just return it unchanged
-        return None, match.group(), None
-
-
-interpolation_engines = {
-    'configparser': ConfigParserInterpolation,
-    'template': TemplateInterpolation,
-}
-
-def __newobj__(cls, *args):
-    # Hack for pickle
-    return cls.__new__(cls, *args)
-    
-class Section(dict):
-    """
-    A dictionary-like object that represents a section in a config file.
-
-    It does string interpolation if the 'interpolation' attribute
-    of the 'main' object is set to True.
-
-    Interpolation is tried first from this object, then from the 'DEFAULT'
-    section of this object, next from the parent and its 'DEFAULT' section,
-    and so on until the main object is reached.
-
-    A Section will behave like an ordered dictionary - following the
-    order of the ``scalars`` and ``sections`` attributes.
-    You can use this to change the order of members.
-
-    Iteration follows the order: scalars, then sections.
-    """
-
-    def __setstate__(self, state):
-        dict.update(self, state[0])
-        self.__dict__.update(state[1])
-    
-    def __reduce__(self):
-        state = (dict(self), self.__dict__)
-        return (__newobj__, (self.__class__,), state)
-
-    def __init__(self, parent, depth, main, indict=None, name=None):
-        """
-        * parent is the section above
-        * depth is the depth level of this section
-        * main is the main ConfigObj
-        * indict is a dictionary to initialise the section with
-        """
-        if indict is None:
-            indict = {}
-        dict.__init__(self)
-        # used for nesting level *and* interpolation
-        self.parent = parent
-        # used for the interpolation attribute
-        self.main = main
-        # level of nesting depth of this Section
-        self.depth = depth
-        # purely for information
-        self.name = name
-        #
-        self._initialise()
-        # we do this explicitly so that __setitem__ is used properly
-        # (rather than just passing to ``dict.__init__``)
-        for entry, value in list(indict.items()):
-            self[entry] = value
-
-    def _initialise(self):
-        # the sequence of scalar values in this Section
-        self.scalars = []
-        # the sequence of sections in this Section
-        self.sections = []
-        # for comments :-)
-        self.comments = {}
-        self.inline_comments = {}
-        # the configspec
-        self.configspec = None
-        # for defaults
-        self.defaults = []
-        self.default_values = {}
-        self.extra_values = []
-        self._created = False
-
-    def _interpolate(self, key, value):
-        try:
-            # do we already have an interpolation engine?
-            engine = self._interpolation_engine
-        except AttributeError:
-            # not yet: first time running _interpolate(), so pick the engine
-            name = self.main.interpolation
-            if name == True:  # note that "if name:" would be incorrect here
-                # backwards-compatibility: interpolation=True means use default
-                name = DEFAULT_INTERPOLATION
-            name = name.lower()  # so that "Template", "template", etc. all work
-            class_ = interpolation_engines.get(name, None)
-            if class_ is None:
-                # invalid value for self.main.interpolation
-                self.main.interpolation = False
-                return value
-            else:
-                # save reference to engine so we don't have to do this again
-                engine = self._interpolation_engine = class_(self)
-        # let the engine do the actual work
-        return engine.interpolate(key, value)
-
-    def __getitem__(self, key):
-        """Fetch the item and do string interpolation."""
-        val = dict.__getitem__(self, key)
-        if self.main.interpolation: 
-            if isinstance(val, str):
-                return self._interpolate(key, val)
-            if isinstance(val, list):
-                def _check(entry):
-                    if isinstance(entry, str):
-                        return self._interpolate(key, entry)
-                    return entry
-                new = [_check(entry) for entry in val]
-                if new != val:
-                    return new
-        return val
-
-    def __setitem__(self, key, value, unrepr=False):
-        """
-        Correctly set a value.
-        
-        Making dictionary values Section instances.
-        (We have to special case 'Section' instances - which are also dicts)
-        
-        Keys must be strings.
-        Values need only be strings (or lists of strings) if
-        ``main.stringify`` is set.
-        
-        ``unrepr`` must be set when setting a value to a dictionary, without
-        creating a new sub-section.
-        """
-        if not isinstance(key, str):
-            raise ValueError('The key "%s" is not a string.' % key)
-        
-        # add the comment
-        if key not in self.comments:
-            self.comments[key] = []
-            self.inline_comments[key] = ''
-        # remove the entry from defaults
-        if key in self.defaults:
-            self.defaults.remove(key)
-        #
-        if isinstance(value, Section):
-            if key not in self:
-                self.sections.append(key)
-            dict.__setitem__(self, key, value)
-        elif isinstance(value, dict) and not unrepr:
-            # First create the new depth level,
-            # then create the section
-            if key not in self:
-                self.sections.append(key)
-            new_depth = self.depth + 1
-            dict.__setitem__(
-                self,
-                key,
-                Section(
-                    self,
-                    new_depth,
-                    self.main,
-                    indict=value,
-                    name=key))
-        else:
-            if key not in self:
-                self.scalars.append(key)
-            if not self.main.stringify:
-                if isinstance(value, str):
-                    pass
-                elif isinstance(value, (list, tuple)):
-                    for entry in value:
-                        if not isinstance(entry, str):
-                            raise TypeError('Value is not a string "%s".' % entry)
-                else:
-                    raise TypeError('Value is not a string "%s".' % value)
-            dict.__setitem__(self, key, value)
-
-
-    def __delitem__(self, key):
-        """Remove items from the sequence when deleting."""
-        dict. __delitem__(self, key)
-        if key in self.scalars:
-            self.scalars.remove(key)
-        else:
-            self.sections.remove(key)
-        del self.comments[key]
-        del self.inline_comments[key]
-
-    def get(self, key, default=None):
-        """A version of ``get`` that doesn't bypass string interpolation."""
-        try:
-            return self[key]
-        except KeyError:
-            return default
-
-
-    def update(self, indict):
-        """
-        A version of update that uses our ``__setitem__``.
-        """
-        for entry in indict:
-            self[entry] = indict[entry]
-
-
-    def pop(self, key, default=MISSING):
-        """
-        'D.pop(k[,d]) -> v, remove specified key and return the corresponding value.
-        If key is not found, d is returned if given, otherwise KeyError is raised'
-        """
-        try:
-            val = self[key]
-        except KeyError:
-            if default is MISSING:
-                raise
-            val = default
-        else:
-            del self[key]
-        return val
-
-    def popitem(self):
-        """Pops the first (key,val)"""
-        sequence = (self.scalars + self.sections)
-        if not sequence:
-            raise KeyError(": 'popitem(): dictionary is empty'")
-        key = sequence[0]
-        val =  self[key]
-        del self[key]
-        return key, val
-    
-    def clear(self):
-        """
-        A version of clear that also affects scalars/sections
-        Also clears comments and configspec.
-        
-        Leaves other attributes alone :
-            depth/main/parent are not affected
-        """
-        dict.clear(self)
-        self.scalars = []
-        self.sections = []
-        self.comments = {}
-        self.inline_comments = {}
-        self.configspec = None
-        self.defaults = []
-        self.extra_values = []
-
-
-    def setdefault(self, key, default=None):
-        """A version of setdefault that sets sequence if appropriate."""
-        try:
-            return self[key]
-        except KeyError:
-            self[key] = default
-            return self[key]
-
-
-    def items(self):
-        """D.items() -> list of D's (key, value) pairs, as 2-tuples"""
-        return list(zip((self.scalars + self.sections), list(self.values())))
-
-
-    def keys(self):
-        """D.keys() -> list of D's keys"""
-        return (self.scalars + self.sections)
-
-
-    def values(self):
-        """D.values() -> list of D's values"""
-        return [self[key] for key in (self.scalars + self.sections)]
-
-
-    def iteritems(self):
-        """D.iteritems() -> an iterator over the (key, value) items of D"""
-        return iter(list(self.items()))
-
-
-    def iterkeys(self):
-        """D.iterkeys() -> an iterator over the keys of D"""
-        return iter((self.scalars + self.sections))
-
-    __iter__ = iterkeys
-
-
-    def itervalues(self):
-        """D.itervalues() -> an iterator over the values of D"""
-        return iter(list(self.values()))
-
-
-    def __repr__(self):
-        """x.__repr__() <==> repr(x)"""
-        def _getval(key):
-            try:
-                return self[key]
-            except MissingInterpolationOption:
-                return dict.__getitem__(self, key)
-        return '{%s}' % ', '.join([('%s: %s' % (repr(key), repr(_getval(key))))
-            for key in (self.scalars + self.sections)])
-
-    __str__ = __repr__
-    __str__.__doc__ = "x.__str__() <==> str(x)"
-
-
-    # Extra methods - not in a normal dictionary
-
-    def dict(self):
-        """
-        Return a deepcopy of self as a dictionary.
-        
-        All members that are ``Section`` instances are recursively turned to
-        ordinary dictionaries - by calling their ``dict`` method.
-        
-        >>> n = a.dict()
-        >>> n == a
-        1
-        >>> n is a
-        0
-        """
-        newdict = {}
-        for entry in self:
-            this_entry = self[entry]
-            if isinstance(this_entry, Section):
-                this_entry = this_entry.dict()
-            elif isinstance(this_entry, list):
-                # create a copy rather than a reference
-                this_entry = list(this_entry)
-            elif isinstance(this_entry, tuple):
-                # create a copy rather than a reference
-                this_entry = tuple(this_entry)
-            newdict[entry] = this_entry
-        return newdict
-
-
-    def merge(self, indict):
-        """
-        A recursive update - useful for merging config files.
-        
-        >>> a = '''[section1]
-        ...     option1 = True
-        ...     [[subsection]]
-        ...     more_options = False
-        ...     # end of file'''.splitlines()
-        >>> b = '''# File is user.ini
-        ...     [section1]
-        ...     option1 = False
-        ...     # end of file'''.splitlines()
-        >>> c1 = ConfigObj(b)
-        >>> c2 = ConfigObj(a)
-        >>> c2.merge(c1)
-        >>> c2
-        ConfigObj({'section1': {'option1': 'False', 'subsection': {'more_options': 'False'}}})
-        """
-        for key, val in list(indict.items()):
-            if (key in self and isinstance(self[key], dict) and
-                                isinstance(val, dict)):
-                self[key].merge(val)
-            else:   
-                self[key] = val
-
-
-    def rename(self, oldkey, newkey):
-        """
-        Change a keyname to another, without changing position in sequence.
-        
-        Implemented so that transformations can be made on keys,
-        as well as on values. (used by encode and decode)
-        
-        Also renames comments.
-        """
-        if oldkey in self.scalars:
-            the_list = self.scalars
-        elif oldkey in self.sections:
-            the_list = self.sections
-        else:
-            raise KeyError('Key "%s" not found.' % oldkey)
-        pos = the_list.index(oldkey)
-        #
-        val = self[oldkey]
-        dict.__delitem__(self, oldkey)
-        dict.__setitem__(self, newkey, val)
-        the_list.remove(oldkey)
-        the_list.insert(pos, newkey)
-        comm = self.comments[oldkey]
-        inline_comment = self.inline_comments[oldkey]
-        del self.comments[oldkey]
-        del self.inline_comments[oldkey]
-        self.comments[newkey] = comm
-        self.inline_comments[newkey] = inline_comment
-    
-    def walk(self, function, raise_errors=True,
-            call_on_sections=False, **keywargs):
-        """
-        Walk every member and call a function on the keyword and value.
-        
-        Return a dictionary of the return values
-        
-        If the function raises an exception, raise the errror
-        unless ``raise_errors=False``, in which case set the return value to
-        ``False``.
-        
-        Any unrecognised keyword arguments you pass to walk, will be pased on
-        to the function you pass in.
-        
-        Note: if ``call_on_sections`` is ``True`` then - on encountering a
-        subsection, *first* the function is called for the *whole* subsection,
-        and then recurses into it's members. This means your function must be
-        able to handle strings, dictionaries and lists. This allows you
-        to change the key of subsections as well as for ordinary members. The
-        return value when called on the whole subsection has to be discarded.
-        
-        See  the encode and decode methods for examples, including functions.
-        
-        .. admonition:: caution
-        
-            You can use ``walk`` to transform the names of members of a section
-            but you mustn't add or delete members.
-        
-        >>> config = '''[XXXXsection]
-        ... XXXXkey = XXXXvalue'''.splitlines()
-        >>> cfg = ConfigObj(config)
-        >>> cfg
-        ConfigObj({'XXXXsection': {'XXXXkey': 'XXXXvalue'}})
-        >>> def transform(section, key):
-        ...     val = section[key]
-        ...     newkey = key.replace('XXXX', 'CLIENT1')
-        ...     section.rename(key, newkey)
-        ...     if isinstance(val, (tuple, list, dict)):
-        ...         pass
-        ...     else:
-        ...         val = val.replace('XXXX', 'CLIENT1')
-        ...         section[newkey] = val
-        >>> cfg.walk(transform, call_on_sections=True)
-        {'CLIENT1section': {'CLIENT1key': None}}
-        >>> cfg
-        ConfigObj({'CLIENT1section': {'CLIENT1key': 'CLIENT1value'}})
-        """
-        out = {}
-        # scalars first
-        for i in range(len(self.scalars)):
-            entry = self.scalars[i]
-            try:
-                val = function(self, entry, **keywargs)
-                # bound again in case name has changed
-                entry = self.scalars[i]
-                out[entry] = val
-            except Exception:
-                if raise_errors:
-                    raise
-                else:
-                    entry = self.scalars[i]
-                    out[entry] = False
-        # then sections
-        for i in range(len(self.sections)):
-            entry = self.sections[i]
-            if call_on_sections:
-                try:
-                    function(self, entry, **keywargs)
-                except Exception:
-                    if raise_errors:
-                        raise
-                    else:
-                        entry = self.sections[i]
-                        out[entry] = False
-                # bound again in case name has changed
-                entry = self.sections[i]
-            # previous result is discarded
-            out[entry] = self[entry].walk(
-                function,
-                raise_errors=raise_errors,
-                call_on_sections=call_on_sections,
-                **keywargs)
-        return out
-    
-    def as_bool(self, key):
-        """
-        Accepts a key as input. The corresponding value must be a string or
-        the objects (``True`` or 1) or (``False`` or 0). We allow 0 and 1 to
-        retain compatibility with Python 2.2.
-        
-        If the string is one of  ``True``, ``On``, ``Yes``, or ``1`` it returns 
-        ``True``.
-        
-        If the string is one of  ``False``, ``Off``, ``No``, or ``0`` it returns 
-        ``False``.
-        
-        ``as_bool`` is not case sensitive.
-        
-        Any other input will raise a ``ValueError``.
-        
-        >>> a = ConfigObj()
-        >>> a['a'] = 'fish'
-        >>> a.as_bool('a')
-        Traceback (most recent call last):
-        ValueError: Value "fish" is neither True nor False
-        >>> a['b'] = 'True'
-        >>> a.as_bool('b')
-        1
-        >>> a['b'] = 'off'
-        >>> a.as_bool('b')
-        0
-        """
-        val = self[key]
-        if val == True:
-            return True
-        elif val == False:
-            return False
-        else:
-            try:
-                if not isinstance(val, str):
-                    # TODO: Why do we raise a KeyError here?
-                    raise KeyError()
-                else:
-                    return self.main._bools[val.lower()]
-            except KeyError:
-                raise ValueError('Value "%s" is neither True nor False' % val)
-    
-    def as_int(self, key):
-        """
-        A convenience method which coerces the specified value to an integer.
-        
-        If the value is an invalid literal for ``int``, a ``ValueError`` will
-        be raised.
-        
-        >>> a = ConfigObj()
-        >>> a['a'] = 'fish'
-        >>> a.as_int('a')
-        Traceback (most recent call last):
-        ValueError: invalid literal for int() with base 10: 'fish'
-        >>> a['b'] = '1'
-        >>> a.as_int('b')
-        1
-        >>> a['b'] = '3.2'
-        >>> a.as_int('b')
-        Traceback (most recent call last):
-        ValueError: invalid literal for int() with base 10: '3.2'
-        """
-        return int(self[key])
-    
-    def as_float(self, key):
-        """
-        A convenience method which coerces the specified value to a float.
-
-        If the value is an invalid literal for ``float``, a ``ValueError`` will
-        be raised.
-
-        >>> a = ConfigObj()
-        >>> a['a'] = 'fish'
-        >>> a.as_float('a')
-        Traceback (most recent call last):
-        ValueError: invalid literal for float(): fish
-        >>> a['b'] = '1'
-        >>> a.as_float('b')
-        1.0
-        >>> a['b'] = '3.2'
-        >>> a.as_float('b')
-        3.2000000000000002
-        """
-        return float(self[key])
-
-    def as_list(self, key):
-        """
-        A convenience method which fetches the specified value, guaranteeing
-        that it is a list.
-
-        >>> a = ConfigObj()
-        >>> a['a'] = 1
-        >>> a.as_list('a')
-        [1]
-        >>> a['a'] = (1,)
-        >>> a.as_list('a')
-        [1]
-        >>> a['a'] = [1]
-        >>> a.as_list('a')
-        [1]
-        """
-        result = self[key]
-        if isinstance(result, (tuple, list)):
-            return list(result)
-        return [result]
-
-    def restore_default(self, key):
-        """
-        Restore (and return) default value for the specified key.
-
-        This method will only work for a ConfigObj that was created
-        with a configspec and has been validated.
-
-        If there is no default value for this key, ``KeyError`` is raised.
-        """
-        default = self.default_values[key]
-        dict.__setitem__(self, key, default)
-        if key not in self.defaults:
-            self.defaults.append(key)
-        return default
-
-    def restore_defaults(self):
-        """
-        Recursively restore default values to all members
-        that have them.
-
-        This method will only work for a ConfigObj that was created
-        with a configspec and has been validated.
-
-        It doesn't delete or modify entries without default values.
-        """
-        for key in self.default_values:
-            self.restore_default(key)
-
-        for section in self.sections:
-            self[section].restore_defaults()
-
-
-class ConfigObj(Section):
-    """An object to read, create, and write config files."""
-
-    _keyword = re.compile(r'''^ # line start
-        (\s*)                   # indentation
-        (                       # keyword
-            (?:".*?")|          # double quotes
-            (?:'.*?')|          # single quotes
-            (?:[^'"=].*?)       # no quotes
-        )
-        \s*=\s*                 # divider
-        (.*)                    # value (including list values and comments)
-        $   # line end
-        ''',
-        re.VERBOSE)
-
-    _sectionmarker = re.compile(r'''^
-        (\s*)                     # 1: indentation
-        ((?:\[\s*)+)              # 2: section marker open
-        (                         # 3: section name open
-            (?:"\s*\S.*?\s*")|    # at least one non-space with double quotes
-            (?:'\s*\S.*?\s*')|    # at least one non-space with single quotes
-            (?:[^'"\s].*?)        # at least one non-space unquoted
-        )                         # section name close
-        ((?:\s*\])+)              # 4: section marker close
-        \s*(\#.*)?                # 5: optional comment
-        $''',
-        re.VERBOSE)
-
-    # this regexp pulls list values out as a single string
-    # or single values and comments
-    # FIXME: this regex adds a '' to the end of comma terminated lists
-    #   workaround in ``_handle_value``
-    _valueexp = re.compile(r'''^
-        (?:
-            (?:
-                (
-                    (?:
-                        (?:
-                            (?:".*?")|              # double quotes
-                            (?:'.*?')|              # single quotes
-                            (?:[^'",\#][^,\#]*?)    # unquoted
-                        )
-                        \s*,\s*                     # comma
-                    )*      # match all list items ending in a comma (if any)
-                )
-                (
-                    (?:".*?")|                      # double quotes
-                    (?:'.*?')|                      # single quotes
-                    (?:[^'",\#\s][^,]*?)|           # unquoted
-                    (?:(?<!,))                      # Empty value
-                )?          # last item in a list - or string value
-            )|
-            (,)             # alternatively a single comma - empty list
-        )
-        \s*(\#.*)?          # optional comment
-        $''',
-        re.VERBOSE)
-
-    # use findall to get the members of a list value
-    _listvalueexp = re.compile(r'''
-        (
-            (?:".*?")|          # double quotes
-            (?:'.*?')|          # single quotes
-            (?:[^'",\#]?.*?)       # unquoted
-        )
-        \s*,\s*                 # comma
-        ''',
-        re.VERBOSE)
-
-    # this regexp is used for the value
-    # when lists are switched off
-    _nolistvalue = re.compile(r'''^
-        (
-            (?:".*?")|          # double quotes
-            (?:'.*?')|          # single quotes
-            (?:[^'"\#].*?)|     # unquoted
-            (?:)                # Empty value
-        )
-        \s*(\#.*)?              # optional comment
-        $''',
-        re.VERBOSE)
-
-    # regexes for finding triple quoted values on one line
-    _single_line_single = re.compile(r"^'''(.*?)'''\s*(#.*)?$")
-    _single_line_double = re.compile(r'^"""(.*?)"""\s*(#.*)?$')
-    _multi_line_single = re.compile(r"^(.*?)'''\s*(#.*)?$")
-    _multi_line_double = re.compile(r'^(.*?)"""\s*(#.*)?$')
-
-    _triple_quote = {
-        "'''": (_single_line_single, _multi_line_single),
-        '"""': (_single_line_double, _multi_line_double),
-    }
-
-    # Used by the ``istrue`` Section method
-    _bools = {
-        'yes': True, 'no': False,
-        'on': True, 'off': False,
-        '1': True, '0': False,
-        'true': True, 'false': False,
-        }
-
-    def __init__(self, infile=None, options=None, configspec=None, encoding=None,
-                 interpolation=True, raise_errors=False, list_values=True,
-                 create_empty=False, file_error=False, stringify=True,
-                 indent_type=None, default_encoding=None, unrepr=False,
-                 write_empty_values=False, _inspec=False):
-        """
-        Parse a config file or create a config file object.
-        
-        ``ConfigObj(infile=None, configspec=None, encoding=None,
-                    interpolation=True, raise_errors=False, list_values=True,
-                    create_empty=False, file_error=False, stringify=True,
-                    indent_type=None, default_encoding=None, unrepr=False,
-                    write_empty_values=False, _inspec=False)``
-        """
-        self._inspec = _inspec
-        # init the superclass
-        Section.__init__(self, self, 0, self)
-        
-        infile = infile or []
-        
-        _options = {'configspec': configspec,
-                    'encoding': encoding, 'interpolation': interpolation,
-                    'raise_errors': raise_errors, 'list_values': list_values,
-                    'create_empty': create_empty, 'file_error': file_error,
-                    'stringify': stringify, 'indent_type': indent_type,
-                    'default_encoding': default_encoding, 'unrepr': unrepr,
-                    'write_empty_values': write_empty_values}
-
-        if options is None:
-            options = _options
-        else:
-            import warnings
-            warnings.warn('Passing in an options dictionary to ConfigObj() is '
-                          'deprecated. Use **options instead.',
-                          DeprecationWarning, stacklevel=2)
-            
-            # TODO: check the values too.
-            for entry in options:
-                if entry not in OPTION_DEFAULTS:
-                    raise TypeError('Unrecognised option "%s".' % entry)
-            for entry, value in list(OPTION_DEFAULTS.items()):
-                if entry not in options:
-                    options[entry] = value
-                keyword_value = _options[entry]
-                if value != keyword_value:
-                    options[entry] = keyword_value
-        
-        # XXXX this ignores an explicit list_values = True in combination
-        # with _inspec. The user should *never* do that anyway, but still...
-        if _inspec:
-            options['list_values'] = False
-        
-        self._initialise(options)
-        configspec = options['configspec']
-        self._original_configspec = configspec
-        self._load(infile, configspec)
-    
-    def _load(self, infile, configspec):
-
-        if isinstance(infile, str):
-            self.filename = infile
-            if os.path.isfile(infile):
-                h = open(infile, 'rb')
-                infile = h.read() or []
-                h.close()
-            elif self.file_error:
-                # raise an error if the file doesn't exist
-                raise IOError('Config file not found: "%s".' % self.filename)
-            else:
-                # file doesn't already exist
-                if self.create_empty:
-                    # this is a good test that the filename specified
-                    # isn't impossible - like on a non-existent device
-                    h = open(infile, 'w')
-                    h.write('')
-                    h.close()
-                infile = []        
-        elif isinstance(infile, (list, tuple)):
-            infile = list(infile)
-        elif isinstance(infile, dict):
-            # initialise self
-            # the Section class handles creating subsections
-            if isinstance(infile, ConfigObj):
-                # get a copy of our ConfigObj
-                def set_section(in_section, this_section):
-                    for entry in in_section.scalars:
-                        this_section[entry] = in_section[entry]
-                    for section in in_section.sections:
-                        this_section[section] = {}
-                        set_section(in_section[section], this_section[section])
-                set_section(infile, self)
-                
-            else:
-                for entry in infile:
-                    self[entry] = infile[entry]
-            del self._errors
-            
-            if configspec is not None:
-                self._handle_configspec(configspec)
-            else:
-                self.configspec = None
-            return
-        
-        elif getattr(infile, 'read', MISSING) is not MISSING:
-            # This supports file like objects
-            infile = infile.read() or []
-            # needs splitting into lines - but needs doing *after* decoding
-            # in case it's not an 8 bit encoding
-        else:
-            raise TypeError('infile must be a filename, file like object, or list of lines.')
-        
-        if infile:
-            # don't do it for the empty ConfigObj
-            infile = self._handle_bom(infile)
-            # infile is now *always* a list
-            #
-            # Set the newlines attribute (first line ending it finds)
-            # and strip trailing '\n' or '\r' from lines
-            for line in infile:
-                if (not line) or (line[-1] not in ('\r', '\n', '\r\n')):
-                    continue
-                for end in ('\r\n', '\n', '\r'):
-                    if line.endswith(end):
-                        self.newlines = end
-                        break
-                break
-
-            infile = [line.rstrip('\r\n') for line in infile]
-
-            
-        self._parse(infile)
-        # if we had any errors, now is the time to raise them
-        if self._errors:
-            info = "at line %s." % self._errors[0].line_number
-            if len(self._errors) > 1:
-                msg = "Parsing failed with several errors.\nFirst error %s" % info
-                error = ConfigObjError(msg)
-            else:
-                error = self._errors[0]
-            # set the errors attribute; it's a list of tuples:
-            # (error_type, message, line_number)
-            error.errors = self._errors
-            # set the config attribute
-            error.config = self
-            raise error
-        # delete private attributes
-        del self._errors
-        
-        if configspec is None:
-            self.configspec = None
-        else:
-            self._handle_configspec(configspec)
-    
-    def _initialise(self, options=None):
-        if options is None:
-            options = OPTION_DEFAULTS
-            
-        # initialise a few variables
-        self.filename = None
-        self._errors = []
-        self.raise_errors = options['raise_errors']
-        self.interpolation = options['interpolation']
-        self.list_values = options['list_values']
-        self.create_empty = options['create_empty']
-        self.file_error = options['file_error']
-        self.stringify = options['stringify']
-        self.indent_type = options['indent_type']
-        self.encoding = options['encoding']
-        self.default_encoding = options['default_encoding']
-        self.BOM = False
-        self.newlines = None
-        self.write_empty_values = options['write_empty_values']
-        self.unrepr = options['unrepr']
-        
-        self.initial_comment = []
-        self.final_comment = []
-        self.configspec = None
-        
-        if self._inspec:
-            self.list_values = False
-        
-        # Clear section attributes as well
-        Section._initialise(self)
-    
-    def __repr__(self):
-        def _getval(key):
-            try:
-                return self[key]
-            except MissingInterpolationOption:
-                return dict.__getitem__(self, key)
-        return ('ConfigObj({%s})' % 
-                ', '.join([('%s: %s' % (repr(key), repr(_getval(key)))) 
-                for key in (self.scalars + self.sections)]))
-    
-    def _handle_bom(self, infile):
-        """
-        Handle any BOM, and decode if necessary.
-        
-        If an encoding is specified, that *must* be used - but the BOM should
-        still be removed (and the BOM attribute set).
-        
-        (If the encoding is wrongly specified, then a BOM for an alternative
-        encoding won't be discovered or removed.)
-        
-        If an encoding is not specified, UTF8 or UTF16 BOM will be detected and
-        removed. The BOM attribute will be set. UTF16 will be decoded to
-        unicode.
-        
-        NOTE: This method must not be called with an empty ``infile``.
-        
-        Specifying the *wrong* encoding is likely to cause a
-        ``UnicodeDecodeError``.
-        
-        ``infile`` must always be returned as a list of lines, but may be
-        passed in as a single string.
-        """
-        if ((self.encoding is not None) and
-            (self.encoding.lower() not in BOM_LIST)):
-            # No need to check for a BOM
-            # the encoding specified doesn't have one
-            # just decode
-            return self._decode(infile, self.encoding)
-        
-        if isinstance(infile, (list, tuple)):
-            line = infile[0]
-        else:
-            line = infile
-        if self.encoding is not None:
-            # encoding explicitly supplied
-            # And it could have an associated BOM
-            # TODO: if encoding is just UTF16 - we ought to check for both
-            # TODO: big endian and little endian versions.
-            enc = BOM_LIST[self.encoding.lower()]
-            if enc == 'utf_16':
-                # For UTF16 we try big endian and little endian
-                for BOM, (encoding, final_encoding) in list(BOMS.items()):
-                    if not final_encoding:
-                        # skip UTF8
-                        continue
-                    if isinstance(infile, bytes) and infile.startswith(BOM):
-                        ### BOM discovered
-                        ##self.BOM = True
-                        # Don't need to remove BOM
-                        return self._decode(infile, encoding)
-                    
-                # If we get this far, will *probably* raise a DecodeError
-                # As it doesn't appear to start with a BOM
-                return self._decode(infile, self.encoding)
-            
-            # Must be UTF8
-            BOM = BOM_SET[enc]
-            if isinstance(line, bytes) and not line.startswith(BOM):
-                return self._decode(infile, self.encoding)
-            
-            newline = line[len(BOM):]
-            
-            # BOM removed
-            if isinstance(infile, (list, tuple)):
-                infile[0] = newline
-            else:
-                infile = newline
-            self.BOM = True
-            return self._decode(infile, self.encoding)
-        
-        # No encoding specified - so we need to check for UTF8/UTF16
-        for BOM, (encoding, final_encoding) in list(BOMS.items()):
-            if isinstance(line, bytes) and not line.startswith(BOM):
-                continue
-            else:
-                # BOM discovered
-                # self.encoding = final_encoding
-                if not final_encoding:
-                    self.BOM = True
-                    # UTF8
-                    # remove BOM
-                    newline = line[len(BOM):]
-                    if isinstance(infile, (list, tuple)):
-                        infile[0] = newline
-                    else:
-                        infile = newline
-                    # UTF8 - don't decode
-                    if isinstance(infile, str):
-                        return infile.splitlines(True)
-                    else:
-                        return infile
-                
-                infile = self._decode(infile, encoding)
-                if isinstance(infile, str):
-                    # infile read from a file will be a single string
-                    return infile.splitlines(True)
-                return self._decode(infile, encoding)
-                # UTF16 - have to decode
-
-            
-        # No BOM discovered and no encoding specified, just return
-        if isinstance(infile, str):
-            # infile read from a file will be a single string
-            return infile.splitlines(True)
-        
-        if isinstance(infile, bytes):
-            return self._decode(infile, self.encoding)
-        return infile
-
-    def _decode(self, infile, encoding):
-        """
-        Decode infile to unicode. Using the specified encoding.
-
-        if is a string, it also needs converting to a list.
-        """
-        
-        encoding = encoding or 'utf-8'
-        
-        # If `infile` is a Unicode string, return as such
-        if isinstance(infile, str):
-            return infile
-            
-        # If `infile` is bytes type; decode and split
-        if isinstance(infile, bytes):
-            return infile.decode(encoding).splitlines(True)
-
-        # If `infile` is a mix of bytes and unicode strings
-        for i, line in enumerate(infile):
-            if isinstance(line, bytes):
-                infile[i] = line.decode(encoding)
-        return infile
-    
-    def _decode_element(self, line):
-        """Decode element to unicode if necessary."""
-        if not self.encoding:
-            return line
-        if isinstance(line, bytes) and self.default_encoding:
-            return line.decode(self.default_encoding)
-        return line
-
-    def _str(self, value):
-        """
-        Used by ``stringify`` within validate, to turn non-string values
-        into strings.
-        """
-        
-        # Bytes type string should NOT be stringified at any cost.
-        if isinstance(value, bytes):
-            return value
-        if not isinstance(value, str):
-            return str(value)
-        else:
-            return value
-
-    def _parse(self, infile):
-        """Actually parse the config file."""
-        
-        temp_list_values = self.list_values
-        if self.unrepr:
-            self.list_values = False
-            
-        comment_list = []
-        done_start = False
-        this_section = self
-        maxline = len(infile) - 1
-        cur_index = -1
-        reset_comment = False
-        
-        while cur_index < maxline:
-            if reset_comment:
-                comment_list = []
-            cur_index += 1
-            line = infile[cur_index]
-            sline = line.strip()
-            # do we have anything on the line ?
-            if not sline or sline.startswith('#'):
-                reset_comment = False
-                comment_list.append(line)
-                continue
-            
-            if not done_start:
-                # preserve initial comment
-                self.initial_comment = comment_list
-                comment_list = []
-                done_start = True
-                
-            reset_comment = True
-            # first we check if it's a section marker
-            mat = self._sectionmarker.match(line)
-            if mat is not None:
-                # is a section line
-                (indent, sect_open, sect_name, sect_close, comment) = mat.groups()
-                if indent and (self.indent_type is None):
-                    self.indent_type = indent
-                cur_depth = sect_open.count('[')
-                if cur_depth != sect_close.count(']'):
-                    self._handle_error("Cannot compute the section depth at line %s.",
-                                       NestingError, infile, cur_index)
-                    continue
-                
-                if cur_depth < this_section.depth:
-                    # the new section is dropping back to a previous level
-                    try:
-                        parent = self._match_depth(this_section,
-                                                   cur_depth).parent
-                    except SyntaxError:
-                        self._handle_error("Cannot compute nesting level at line %s.",
-                                           NestingError, infile, cur_index)
-                        continue
-                elif cur_depth == this_section.depth:
-                    # the new section is a sibling of the current section
-                    parent = this_section.parent
-                elif cur_depth == this_section.depth + 1:
-                    # the new section is a child the current section
-                    parent = this_section
-                else:
-                    self._handle_error("Section too nested at line %s.",
-                                       NestingError, infile, cur_index)
-                    
-                sect_name = self._unquote(sect_name)
-                if sect_name in parent:
-                    self._handle_error('Duplicate section name at line %s.',
-                                       DuplicateError, infile, cur_index)
-                    continue
-                
-                # create the new section
-                this_section = Section(
-                    parent,
-                    cur_depth,
-                    self,
-                    name=sect_name)
-                parent[sect_name] = this_section
-                parent.inline_comments[sect_name] = comment
-                parent.comments[sect_name] = comment_list
-                continue
-            #
-            # it's not a section marker,
-            # so it should be a valid ``key = value`` line
-            mat = self._keyword.match(line)
-            if mat is None:
-                # it neither matched as a keyword
-                # or a section marker
-                self._handle_error(
-                    'Invalid line at line "%s".',
-                    ParseError, infile, cur_index)
-            else:
-                # is a keyword value
-                # value will include any inline comment
-                (indent, key, value) = mat.groups()
-                if indent and (self.indent_type is None):
-                    self.indent_type = indent
-                # check for a multiline value
-                if value[:3] in ['"""', "'''"]:
-                    try:
-                        value, comment, cur_index = self._multiline(
-                            value, infile, cur_index, maxline)
-                    except SyntaxError:
-                        self._handle_error(
-                            'Parse error in value at line %s.',
-                            ParseError, infile, cur_index)
-                        continue
-                    else:
-                        if self.unrepr:
-                            comment = ''
-                            try:
-                                value = unrepr(value)
-                            except Exception as e:
-                                if type(e) == UnknownType:
-                                    msg = 'Unknown name or type in value at line %s.'
-                                else:
-                                    msg = 'Parse error in value at line %s.'
-                                self._handle_error(msg, UnreprError, infile,
-                                    cur_index)
-                                continue
-                else:
-                    if self.unrepr:
-                        comment = ''
-                        try:
-                            value = unrepr(value)
-                        except Exception as e:
-                            if isinstance(e, UnknownType):
-                                msg = 'Unknown name or type in value at line %s.'
-                            else:
-                                msg = 'Parse error in value at line %s.'
-                            self._handle_error(msg, UnreprError, infile,
-                                cur_index)
-                            continue
-                    else:
-                        # extract comment and lists
-                        try:
-                            (value, comment) = self._handle_value(value)
-                        except SyntaxError:
-                            self._handle_error(
-                                'Parse error in value at line %s.',
-                                ParseError, infile, cur_index)
-                            continue
-                #
-                key = self._unquote(key)
-                if key in this_section:
-                    self._handle_error(
-                        'Duplicate keyword name at line %s.',
-                        DuplicateError, infile, cur_index)
-                    continue
-                # add the key.
-                # we set unrepr because if we have got this far we will never
-                # be creating a new section
-                this_section.__setitem__(key, value, unrepr=True)
-                this_section.inline_comments[key] = comment
-                this_section.comments[key] = comment_list
-                continue
-        #
-        if self.indent_type is None:
-            # no indentation used, set the type accordingly
-            self.indent_type = ''
-
-        # preserve the final comment
-        if not self and not self.initial_comment:
-            self.initial_comment = comment_list
-        elif not reset_comment:
-            self.final_comment = comment_list
-        self.list_values = temp_list_values
-    
-    def _match_depth(self, sect, depth):
-        """
-        Given a section and a depth level, walk back through the sections
-        parents to see if the depth level matches a previous section.
-        
-        Return a reference to the right section,
-        or raise a SyntaxError.
-        """
-        while depth < sect.depth:
-            if sect is sect.parent:
-                # we've reached the top level already
-                raise SyntaxError()
-            sect = sect.parent
-        if sect.depth == depth:
-            return sect
-        # shouldn't get here
-        raise SyntaxError()
-    
-    def _handle_error(self, text, ErrorClass, infile, cur_index):
-        """
-        Handle an error according to the error settings.
-        
-        Either raise the error or store it.
-        The error will have occured at ``cur_index``
-        """
-        line = infile[cur_index]
-        cur_index += 1
-        message = text % cur_index
-        error = ErrorClass(message, cur_index, line)
-        if self.raise_errors:
-            # raise the error - parsing stops here
-            raise error
-        # store the error
-        # reraise when parsing has finished
-        self._errors.append(error)
-    
-    def _unquote(self, value):
-        """Return an unquoted version of a value"""
-        if not value:
-            # should only happen during parsing of lists
-            raise SyntaxError
-        if (value[0] == value[-1]) and (value[0] in ('"', "'")):
-            value = value[1:-1]
-        return value
-    
-    def _quote(self, value, multiline=True):
-        """
-        Return a safely quoted version of a value.
-
-        Raise a ConfigObjError if the value cannot be safely quoted.
-        If multiline is ``True`` (default) then use triple quotes
-        if necessary.
-
-        * Don't quote values that don't need it.
-        * Recursively quote members of a list and return a comma joined list.
-        * Multiline is ``False`` for lists.
-        * Obey list syntax for empty and single member lists.
-
-        If ``list_values=False`` then the value is only quoted if it contains
-        a ``\\n`` (is multiline) or '#'.
-
-        If ``write_empty_values`` is set, and the value is an empty string, it
-        won't be quoted.
-        """
-        if multiline and self.write_empty_values and value == '':
-            # Only if multiline is set, so that it is used for values not
-            # keys, and not values that are part of a list
-            return ''
-
-        if multiline and isinstance(value, (list, tuple)):
-            if not value:
-                return ','
-            elif len(value) == 1:
-                return self._quote(value[0], multiline=False) + ','
-            return ', '.join([self._quote(val, multiline=False)
-                for val in value])
-        if not isinstance(value, str):
-            if self.stringify and not isinstance(value, bytes):
-                value = str(value)
-            else:
-                raise TypeError('Value "%s" is not a string.' % value)
-
-        if not value:
-            return '""'
-
-        no_lists_no_quotes = not self.list_values and '\n' not in value and '#' not in value
-        need_triple = multiline and ((("'" in value) and ('"' in value)) or ('\n' in value ))
-        hash_triple_quote = multiline and not need_triple and ("'" in value) and ('"' in value) and ('#' in value)
-        check_for_single = (no_lists_no_quotes or not need_triple) and not hash_triple_quote
-
-        if check_for_single:
-            if not self.list_values:
-                # we don't quote if ``list_values=False``
-                quot = noquot
-            # for normal values either single or double quotes will do
-            elif '\n' in value:
-                # will only happen if multiline is off - e.g. '\n' in key
-                raise ConfigObjError('Value "%s" cannot be safely quoted.' % value)
-            elif ((value[0] not in wspace_plus) and
-                    (value[-1] not in wspace_plus) and
-                    (',' not in value)):
-                quot = noquot
-            else:
-                quot = self._get_single_quote(value)
-        else:
-            # if value has '\n' or "'" *and* '"', it will need triple quotes
-            quot = self._get_triple_quote(value)
-
-        if quot == noquot and '#' in value and self.list_values:
-            quot = self._get_single_quote(value)
-
-        return quot % value
-
-    def _get_single_quote(self, value):
-        if ("'" in value) and ('"' in value):
-            raise ConfigObjError('Value "%s" cannot be safely quoted.' % value)
-        elif '"' in value:
-            quot = squot
-        else:
-            quot = dquot
-        return quot
-
-    def _get_triple_quote(self, value):
-        if (value.find('"""') != -1) and (value.find("'''") != -1):
-            raise ConfigObjError('Value "%s" cannot be safely quoted.' % value)
-        if value.find('"""') == -1:
-            quot = tdquot
-        else:
-            quot = tsquot 
-        return quot
-
-    def _handle_value(self, value):
-        """
-        Given a value string, unquote, remove comment,
-        handle lists. (including empty and single member lists)
-        """
-        if self._inspec:
-            # Parsing a configspec so don't handle comments
-            return (value, '')
-        # do we look for lists in values ?
-        if not self.list_values:
-            mat = self._nolistvalue.match(value)
-            if mat is None:
-                raise SyntaxError()
-            # NOTE: we don't unquote here
-            return mat.groups()
-        #
-        mat = self._valueexp.match(value)
-        if mat is None:
-            # the value is badly constructed, probably badly quoted,
-            # or an invalid list
-            raise SyntaxError()
-        (list_values, single, empty_list, comment) = mat.groups()
-        if (list_values == '') and (single is None):
-            # change this if you want to accept empty values
-            raise SyntaxError()
-        # NOTE: note there is no error handling from here if the regex
-        # is wrong: then incorrect values will slip through
-        if empty_list is not None:
-            # the single comma - meaning an empty list
-            return ([], comment)
-        if single is not None:
-            # handle empty values
-            if list_values and not single:
-                # FIXME: the '' is a workaround because our regex now matches
-                #   '' at the end of a list if it has a trailing comma
-                single = None
-            else:
-                single = single or '""'
-                single = self._unquote(single)
-        if list_values == '':
-            # not a list value
-            return (single, comment)
-        the_list = self._listvalueexp.findall(list_values)
-        the_list = [self._unquote(val) for val in the_list]
-        if single is not None:
-            the_list += [single]
-        return (the_list, comment)
-
-    def _multiline(self, value, infile, cur_index, maxline):
-        """Extract the value, where we are in a multiline situation."""
-        quot = value[:3]
-        newvalue = value[3:]
-        single_line = self._triple_quote[quot][0]
-        multi_line = self._triple_quote[quot][1]
-        mat = single_line.match(value)
-        if mat is not None:
-            retval = list(mat.groups())
-            retval.append(cur_index)
-            return retval
-        elif newvalue.find(quot) != -1:
-            # somehow the triple quote is missing
-            raise SyntaxError()
-        #
-        while cur_index < maxline:
-            cur_index += 1
-            newvalue += '\n'
-            line = infile[cur_index]
-            if line.find(quot) == -1:
-                newvalue += line
-            else:
-                # end of multiline, process it
-                break
-        else:
-            # we've got to the end of the config, oops...
-            raise SyntaxError()
-        mat = multi_line.match(line)
-        if mat is None:
-            # a badly formed line
-            raise SyntaxError()
-        (value, comment) = mat.groups()
-        return (newvalue + value, comment, cur_index)
-
-    def _handle_configspec(self, configspec):
-        """Parse the configspec."""
-        # FIXME: Should we check that the configspec was created with the 
-        #        correct settings ? (i.e. ``list_values=False``)
-        if not isinstance(configspec, ConfigObj):
-            try:
-                configspec = ConfigObj(configspec,
-                                       raise_errors=True,
-                                       file_error=True,
-                                       _inspec=True)
-            except ConfigObjError as e:
-                # FIXME: Should these errors have a reference
-                #        to the already parsed ConfigObj ?
-                raise ConfigspecError('Parsing configspec failed: %s' % e)
-            except IOError as e:
-                raise IOError('Reading configspec failed: %s' % e)
-
-        self.configspec = configspec
-
-    def _set_configspec(self, section, copy):
-        """
-        Called by validate. Handles setting the configspec on subsections
-        including sections to be validated by __many__
-        """
-        configspec = section.configspec
-        many = configspec.get('__many__')
-        if isinstance(many, dict):
-            for entry in section.sections:
-                if entry not in configspec:
-                    section[entry].configspec = many
-
-        for entry in configspec.sections:
-            if entry == '__many__':
-                continue
-            if entry not in section:
-                section[entry] = {}
-                section[entry]._created = True
-                if copy:
-                    # copy comments
-                    section.comments[entry] = configspec.comments.get(entry, [])
-                    section.inline_comments[entry] = configspec.inline_comments.get(entry, '')
-
-            # Could be a scalar when we expect a section
-            if isinstance(section[entry], Section):
-                section[entry].configspec = configspec[entry]
-
-    def _write_line(self, indent_string, entry, this_entry, comment):
-        """Write an individual line, for the write method"""
-        # NOTE: the calls to self._quote here handles non-StringType values.
-        if not self.unrepr:
-            val = self._decode_element(self._quote(this_entry))
-        else:
-            val = repr(this_entry)
-        return '%s%s%s%s%s' % (indent_string,
-                               self._decode_element(self._quote(entry, multiline=False)),
-                               ' = ',
-                               val,
-                               self._decode_element(comment))
-
-    def _write_marker(self, indent_string, depth, entry, comment):
-        """Write a section marker line"""
-        return '%s%s%s%s%s' % (indent_string,
-                               '[' * depth,
-                               self._quote(self._decode_element(entry), multiline=False),
-                               ']' * depth,
-                               self._decode_element(comment))
-    
-    def _handle_comment(self, comment):
-        """Deal with a comment."""
-        if not comment:
-            return ''
-        start = self.indent_type
-        if not comment.startswith('#'):
-            start += ' # '
-        return (start + comment)
-
-    # Public methods
-
-    def write(self, outfile=None, section=None):
-        """
-        Write the current ConfigObj as a file
-        
-        tekNico: FIXME: use StringIO instead of real files
-        
-        >>> filename = a.filename
-        >>> a.filename = 'test.ini'
-        >>> a.write()
-        >>> a.filename = filename
-        >>> a == ConfigObj('test.ini', raise_errors=True)
-        1
-        >>> import os
-        >>> os.remove('test.ini')
-        """
-        if self.indent_type is None:
-            # this can be true if initialised from a dictionary
-            self.indent_type = DEFAULT_INDENT_TYPE
-            
-        out = []
-        cs = '#'
-        csp = '# '
-        if section is None:
-            int_val = self.interpolation
-            self.interpolation = False
-            section = self
-            for line in self.initial_comment:
-                line = self._decode_element(line)
-                stripped_line = line.strip()
-                if stripped_line and not stripped_line.startswith(cs):
-                    line = csp + line
-                out.append(line)
-                
-        indent_string = self.indent_type * section.depth
-        for entry in (section.scalars + section.sections):
-            if entry in section.defaults:
-                # don't write out default values
-                continue
-            for comment_line in section.comments[entry]:
-                comment_line = self._decode_element(comment_line.lstrip())
-                if comment_line and not comment_line.startswith(cs):
-                    comment_line = csp + comment_line
-                out.append(indent_string + comment_line)
-            this_entry = section[entry]
-            comment = self._handle_comment(section.inline_comments[entry])
-            
-            if isinstance(this_entry, dict):
-                # a section
-                out.append(self._write_marker(
-                    indent_string,
-                    this_entry.depth,
-                    entry,
-                    comment))
-                out.extend(self.write(section=this_entry))
-            else:
-                out.append(self._write_line(
-                    indent_string,
-                    entry,
-                    this_entry,
-                    comment))
-                
-        if section is self:
-            for line in self.final_comment:
-                line = self._decode_element(line)
-                stripped_line = line.strip()
-                if stripped_line and not stripped_line.startswith(cs):
-                    line = csp + line
-                out.append(line)
-            self.interpolation = int_val
-            
-        if section is not self:
-            return out
-        
-        if (self.filename is None) and (outfile is None):
-            
-            # output a list of lines
-            # might need to encode
-            # NOTE: This will *screw* UTF16, each line will start with the BOM
-            if self.encoding:
-                out = [l.encode(self.encoding) for l in out]
-            if (self.BOM and ((self.encoding is None) or
-                (BOM_LIST.get(self.encoding.lower()) == 'utf_8'))):
-                # Add the UTF8 BOM
-                if not out:
-                    out.append('')
-                out[0] = BOM_UTF8 + out[0]
-            return out
-            
-        
-        # Turn the list to a string, joined with correct newlines
-        newline = self.newlines or os.linesep
-        if (getattr(outfile, 'mode', None) is not None and outfile.mode == 'w'
-            and sys.platform == 'win32' and newline == '\r\n'):
-            # Windows specific hack to avoid writing '\r\r\n'
-            newline = '\n'
-        output = newline.join(out)
-        if self.encoding:
-            output = output.encode(self.encoding)
-            
-        if self.BOM and ((self.encoding is None) or match_utf8(self.encoding)):
-            # Add the UTF8 BOM
-            output = BOM_UTF8 + output
-              
-        if not output.endswith(newline):
-            output += newline
-        if outfile is not None:
-            outfile.write(output)
-        else:
-            h = open(self.filename, 'wb')
-            output = output.encode() # encoding the data to bytes
-            h.write(output)
-            h.close()
-    
-    def validate(self, validator, preserve_errors=False, copy=False,
-                 section=None):
-        """
-        Test the ConfigObj against a configspec.
-        
-        It uses the ``validator`` object from *validate.py*.
-        
-        To run ``validate`` on the current ConfigObj, call: ::
-        
-            test = config.validate(validator)
-        
-        (Normally having previously passed in the configspec when the ConfigObj
-        was created - you can dynamically assign a dictionary of checks to the
-        ``configspec`` attribute of a section though).
-        
-        It returns ``True`` if everything passes, or a dictionary of
-        pass/fails (True/False). If every member of a subsection passes, it
-        will just have the value ``True``. (It also returns ``False`` if all
-        members fail).
-        
-        In addition, it converts the values from strings to their native
-        types if their checks pass (and ``stringify`` is set).
-        
-        If ``preserve_errors`` is ``True`` (``False`` is default) then instead
-        of a marking a fail with a ``False``, it will preserve the actual
-        exception object. This can contain info about the reason for failure.
-        For example the ``VdtValueTooSmallError`` indicates that the value
-        supplied was too small. If a value (or section) is missing it will
-        still be marked as ``False``.
-        
-        You must have the validate module to use ``preserve_errors=True``.
-        
-        You can then use the ``flatten_errors`` function to turn your nested
-        results dictionary into a flattened list of failures - useful for
-        displaying meaningful error messages.
-        """
-        if section is None:
-            if self.configspec is None:
-                raise ValueError('No configspec supplied.')
-            if preserve_errors:
-                # We do this once to remove a top level dependency on the validate module
-                # Which makes importing configobj faster
-                from validate import VdtMissingValue
-                self._vdtMissingValue = VdtMissingValue
-                
-            section = self
-
-            if copy:
-                section.initial_comment = section.configspec.initial_comment
-                section.final_comment = section.configspec.final_comment
-                section.encoding = section.configspec.encoding
-                section.BOM = section.configspec.BOM
-                section.newlines = section.configspec.newlines
-                section.indent_type = section.configspec.indent_type
-            
-        #
-        # section.default_values.clear() #??
-        configspec = section.configspec
-        self._set_configspec(section, copy)
-    
-        def validate_entry(entry, spec, val, missing, ret_true, ret_false):
-            section.default_values.pop(entry, None)
-
-            try:
-                section.default_values[entry] = validator.get_default_value(configspec[entry])
-            except (KeyError, AttributeError, validator.baseErrorClass):
-                # No default, bad default or validator has no 'get_default_value'
-                # (e.g. SimpleVal)
-                pass
-
-            try:
-                check = validator.check(spec,
-                                        val,
-                                        missing=missing
-                                        )
-            except validator.baseErrorClass as e:
-                if not preserve_errors or isinstance(e, self._vdtMissingValue):
-                    out[entry] = False
-                else:
-                    # preserve the error
-                    out[entry] = e
-                    ret_false = False
-                ret_true = False
-            else:
-                ret_false = False
-                out[entry] = True
-                if self.stringify or missing:
-                    # if we are doing type conversion
-                    # or the value is a supplied default
-                    if not self.stringify:
-                        if isinstance(check, (list, tuple)):
-                            # preserve lists
-                            check = [self._str(item) for item in check]
-                        elif missing and check is None:
-                            # convert the None from a default to a ''
-                            check = ''
-                        else:
-                            check = self._str(check)
-                    if (check != val) or missing:
-                        section[entry] = check
-                if not copy and missing and entry not in section.defaults:
-                    section.defaults.append(entry)
-            return ret_true, ret_false
-
-        #
-        out = {}
-        ret_true = True
-        ret_false = True
-
-        unvalidated = [k for k in section.scalars if k not in configspec]
-        incorrect_sections = [k for k in configspec.sections if k in section.scalars]
-        incorrect_scalars = [k for k in configspec.scalars if k in section.sections]
-
-        for entry in configspec.scalars:
-            if entry in ('__many__', '___many___'):
-                # reserved names
-                continue
-            if (not entry in section.scalars) or (entry in section.defaults):
-                # missing entries
-                # or entries from defaults
-                missing = True
-                val = None
-                if copy and entry not in section.scalars:
-                    # copy comments
-                    section.comments[entry] = (
-                        configspec.comments.get(entry, []))
-                    section.inline_comments[entry] = (
-                        configspec.inline_comments.get(entry, ''))
-                #
-            else:
-                missing = False
-                val = section[entry]
-
-            ret_true, ret_false = validate_entry(entry, configspec[entry], val,
-                                                 missing, ret_true, ret_false)
-
-        many = None
-        if '__many__' in configspec.scalars:
-            many = configspec['__many__']
-        elif '___many___' in configspec.scalars:
-            many = configspec['___many___']
-
-        if many is not None:
-            for entry in unvalidated:
-                val = section[entry]
-                ret_true, ret_false = validate_entry(entry, many, val, False,
-                                                     ret_true, ret_false)
-            unvalidated = []
-
-        for entry in incorrect_scalars:
-            ret_true = False
-            if not preserve_errors:
-                out[entry] = False
-            else:
-                ret_false = False
-                msg = 'Value %r was provided as a section' % entry
-                out[entry] = validator.baseErrorClass(msg)
-        for entry in incorrect_sections:
-            ret_true = False
-            if not preserve_errors:
-                out[entry] = False
-            else:
-                ret_false = False
-                msg = 'Section %r was provided as a single value' % entry
-                out[entry] = validator.baseErrorClass(msg)
-
-        # Missing sections will have been created as empty ones when the
-        # configspec was read.
-        for entry in section.sections:
-            # FIXME: this means DEFAULT is not copied in copy mode
-            if section is self and entry == 'DEFAULT':
-                continue
-            if section[entry].configspec is None:
-                unvalidated.append(entry)
-                continue
-            if copy:
-                section.comments[entry] = configspec.comments.get(entry, [])
-                section.inline_comments[entry] = configspec.inline_comments.get(entry, '')
-            check = self.validate(validator, preserve_errors=preserve_errors, copy=copy, section=section[entry])
-            out[entry] = check
-            if check == False:
-                ret_true = False
-            elif check == True:
-                ret_false = False
-            else:
-                ret_true = False
-
-        section.extra_values = unvalidated
-        if preserve_errors and not section._created:
-            # If the section wasn't created (i.e. it wasn't missing)
-            # then we can't return False, we need to preserve errors
-            ret_false = False
-        #
-        if ret_false and preserve_errors and out:
-            # If we are preserving errors, but all
-            # the failures are from missing sections / values
-            # then we can return False. Otherwise there is a
-            # real failure that we need to preserve.
-            ret_false = not any(out.values())
-        if ret_true:
-            return True
-        elif ret_false:
-            return False
-        return out
-
-    
-    def reset(self):
-        """Clear ConfigObj instance and restore to 'freshly created' state."""
-        self.clear()
-        self._initialise()
-        # FIXME: Should be done by '_initialise', but ConfigObj constructor (and reload)
-        #        requires an empty dictionary
-        self.configspec = None
-        # Just to be sure ;-)
-        self._original_configspec = None
-
-    def reload(self):
-        """
-        Reload a ConfigObj from file.
-
-        This method raises a ``ReloadError`` if the ConfigObj doesn't have
-        a filename attribute pointing to a file.
-        """
-        if not isinstance(self.filename, str):
-            raise ReloadError()
-
-        filename = self.filename
-        current_options = {}
-        for entry in OPTION_DEFAULTS:
-            if entry == 'configspec':
-                continue
-            current_options[entry] = getattr(self, entry)
-
-        configspec = self._original_configspec
-        current_options['configspec'] = configspec
-
-        self.clear()
-        self._initialise(current_options)
-        self._load(filename, configspec)
-
-class SimpleVal(object):
-    """
-    A simple validator.
-    Can be used to check that all members expected are present.
-
-    To use it, provide a configspec with all your members in (the value given
-    will be ignored). Pass an instance of ``SimpleVal`` to the ``validate``
-    method of your ``ConfigObj``. ``validate`` will return ``True`` if all
-    members are present, or a dictionary with True/False meaning
-    present/missing. (Whole missing sections will be replaced with ``False``)
-    """
-
-    def __init__(self):
-        self.baseErrorClass = ConfigObjError
-
-    def check(self, check, member, missing=False):
-        """A dummy check method, always returns the value unchanged."""
-        if missing:
-            raise self.baseErrorClass()
-        return member
-
-def flatten_errors(cfg, res, levels=None, results=None):
-    """
-    An example function that will turn a nested dictionary of results
-    (as returned by ``ConfigObj.validate``) into a flat list.
-
-    ``cfg`` is the ConfigObj instance being checked, ``res`` is the results
-    dictionary returned by ``validate``.
-
-    (This is a recursive function, so you shouldn't use the ``levels`` or
-    ``results`` arguments - they are used by the function.)
-
-    Returns a list of keys that failed. Each member of the list is a tuple::
-
-        ([list of sections...], key, result)
-
-    If ``validate`` was called with ``preserve_errors=False`` (the default)
-    then ``result`` will always be ``False``.
-
-    *list of sections* is a flattened list of sections that the key was found
-    in.
-
-    If the section was missing (or a section was expected and a scalar provided
-    - or vice-versa) then key will be ``None``.
-
-    If the value (or section) was missing then ``result`` will be ``False``.
-
-    If ``validate`` was called with ``preserve_errors=True`` and a value
-    was present, but failed the check, then ``result`` will be the exception
-    object returned. You can use this as a string that describes the failure.
-
-    For example *The value "3" is of the wrong type*.
-    """
-    if levels is None:
-        # first time called
-        levels = []
-        results = []
-    if res == True:
-        return results
-    if res == False or isinstance(res, Exception):
-        results.append((levels[:], None, res))
-        if levels:
-            levels.pop()
-        return results
-    for (key, val) in list(res.items()):
-        if val == True:
-            continue
-        if isinstance(cfg.get(key), dict):
-            # Go down one level
-            levels.append(key)
-            flatten_errors(cfg[key], val, levels, results)
-            continue
-        results.append((levels[:], key, val))
-    #
-    # Go up one level
-    if levels:
-        levels.pop()
-    #
-    return results
-
-def get_extra_values(conf, _prepend=()):
-    """
-    Find all the values and sections not in the configspec from a validated
-    ConfigObj.
-
-    ``get_extra_values`` returns a list of tuples where each tuple represents
-    either an extra section, or an extra value.
-
-    The tuples contain two values, a tuple representing the section the value 
-    is in and the name of the extra values. For extra values in the top level
-    section the first member will be an empty tuple. For values in the 'foo'
-    section the first member will be ``('foo',)``. For members in the 'bar'
-    subsection of the 'foo' section the first member will be ``('foo', 'bar')``.
-
-    NOTE: If you call ``get_extra_values`` on a ConfigObj instance that hasn't
-    been validated it will return an empty list.
-    """
-    out = []
-
-    out.extend([(_prepend, name) for name in conf.extra_values])
-    for name in conf.sections:
-        if name not in conf.extra_values:
-            out.extend(get_extra_values(conf[name], _prepend + (name,)))
-    return out
-
-
-"""*A programming language is a medium of expression.* - Paul Graham"""
\ No newline at end of file
diff --git a/astropy/extern/configobj_py3/validate.py b/astropy/extern/configobj_py3/validate.py
deleted file mode 100644
index af12814..0000000
--- a/astropy/extern/configobj_py3/validate.py
+++ /dev/null
@@ -1,1419 +0,0 @@
-# validate.py
-# A Validator object
-# Copyright (C) 2005-2010 Michael Foord, Mark Andrews, Nicola Larosa
-# E-mail: fuzzyman AT voidspace DOT org DOT uk
-#         mark AT la-la DOT com
-#         nico AT tekNico DOT net
-
-# This software is licensed under the terms of the BSD license.
-# http://www.voidspace.org.uk/python/license.shtml
-# Basically you're free to copy, modify, distribute and relicense it,
-# So long as you keep a copy of the license with it.
-
-# Scripts maintained at http://www.voidspace.org.uk/python/index.shtml
-# For information about bugfixes, updates and support, please join the
-# ConfigObj mailing list:
-# http://lists.sourceforge.net/lists/listinfo/configobj-develop
-# Comments, suggestions and bug reports welcome.
-
-"""
-    The Validator object is used to check that supplied values 
-    conform to a specification.
-    
-    The value can be supplied as a string - e.g. from a config file.
-    In this case the check will also *convert* the value to
-    the required type. This allows you to add validation
-    as a transparent layer to access data stored as strings.
-    The validation checks that the data is correct *and*
-    converts it to the expected type.
-    
-    Some standard checks are provided for basic data types.
-    Additional checks are easy to write. They can be
-    provided when the ``Validator`` is instantiated or
-    added afterwards.
-    
-    The standard functions work with the following basic data types :
-    
-    * integers
-    * floats
-    * booleans
-    * strings
-    * ip_addr
-    
-    plus lists of these datatypes
-    
-    Adding additional checks is done through coding simple functions.
-    
-    The full set of standard checks are : 
-    
-    * 'integer': matches integer values (including negative)
-                 Takes optional 'min' and 'max' arguments : ::
-    
-                   integer()
-                   integer(3, 9)  # any value from 3 to 9
-                   integer(min=0) # any positive value
-                   integer(max=9)
-    
-    * 'float': matches float values
-               Has the same parameters as the integer check.
-    
-    * 'boolean': matches boolean values - ``True`` or ``False``
-                 Acceptable string values for True are :
-                   true, on, yes, 1
-                 Acceptable string values for False are :
-                   false, off, no, 0
-    
-                 Any other value raises an error.
-    
-    * 'ip_addr': matches an Internet Protocol address, v.4, represented
-                 by a dotted-quad string, i.e. '1.2.3.4'.
-    
-    * 'string': matches any string.
-                Takes optional keyword args 'min' and 'max'
-                to specify min and max lengths of the string.
-    
-    * 'list': matches any list.
-              Takes optional keyword args 'min', and 'max' to specify min and
-              max sizes of the list. (Always returns a list.)
-    
-    * 'tuple': matches any tuple.
-              Takes optional keyword args 'min', and 'max' to specify min and
-              max sizes of the tuple. (Always returns a tuple.)
-    
-    * 'int_list': Matches a list of integers.
-                  Takes the same arguments as list.
-    
-    * 'float_list': Matches a list of floats.
-                    Takes the same arguments as list.
-    
-    * 'bool_list': Matches a list of boolean values.
-                   Takes the same arguments as list.
-    
-    * 'ip_addr_list': Matches a list of IP addresses.
-                     Takes the same arguments as list.
-    
-    * 'string_list': Matches a list of strings.
-                     Takes the same arguments as list.
-    
-    * 'mixed_list': Matches a list with different types in 
-                    specific positions. List size must match
-                    the number of arguments.
-    
-                    Each position can be one of :
-                    'integer', 'float', 'ip_addr', 'string', 'boolean'
-    
-                    So to specify a list with two strings followed
-                    by two integers, you write the check as : ::
-    
-                      mixed_list('string', 'string', 'integer', 'integer')
-    
-    * 'pass': This check matches everything ! It never fails
-              and the value is unchanged.
-    
-              It is also the default if no check is specified.
-    
-    * 'option': This check matches any from a list of options.
-                You specify this check with : ::
-    
-                  option('option 1', 'option 2', 'option 3')
-    
-    You can supply a default value (returned if no value is supplied)
-    using the default keyword argument.
-    
-    You specify a list argument for default using a list constructor syntax in
-    the check : ::
-    
-        checkname(arg1, arg2, default=list('val 1', 'val 2', 'val 3'))
-    
-    A badly formatted set of arguments will raise a ``VdtParamError``.
-"""
-
-__version__ = '1.0.1'
-
-
-__all__ = (
-    '__version__',
-    'dottedQuadToNum',
-    'numToDottedQuad',
-    'ValidateError',
-    'VdtUnknownCheckError',
-    'VdtParamError',
-    'VdtTypeError',
-    'VdtValueError',
-    'VdtValueTooSmallError',
-    'VdtValueTooBigError',
-    'VdtValueTooShortError',
-    'VdtValueTooLongError',
-    'VdtMissingValue',
-    'Validator',
-    'is_integer',
-    'is_float',
-    'is_boolean',
-    'is_list',
-    'is_tuple',
-    'is_ip_addr',
-    'is_string',
-    'is_int_list',
-    'is_bool_list',
-    'is_float_list',
-    'is_string_list',
-    'is_ip_addr_list',
-    'is_mixed_list',
-    'is_option',
-    '__docformat__',
-)
-
-
-
-import re
-
-
-_list_arg = re.compile(r'''
-    (?:
-        ([a-zA-Z_][a-zA-Z0-9_]*)\s*=\s*list\(
-            (
-                (?:
-                    \s*
-                    (?:
-                        (?:".*?")|              # double quotes
-                        (?:'.*?')|              # single quotes
-                        (?:[^'",\s\)][^,\)]*?)  # unquoted
-                    )
-                    \s*,\s*
-                )*
-                (?:
-                    (?:".*?")|              # double quotes
-                    (?:'.*?')|              # single quotes
-                    (?:[^'",\s\)][^,\)]*?)  # unquoted
-                )?                          # last one
-            )
-        \)
-    )
-''', re.VERBOSE | re.DOTALL)    # two groups
-
-_list_members = re.compile(r'''
-    (
-        (?:".*?")|              # double quotes
-        (?:'.*?')|              # single quotes
-        (?:[^'",\s=][^,=]*?)       # unquoted
-    )
-    (?:
-    (?:\s*,\s*)|(?:\s*$)            # comma
-    )
-''', re.VERBOSE | re.DOTALL)    # one group
-
-_paramstring = r'''
-    (?:
-        (
-            (?:
-                [a-zA-Z_][a-zA-Z0-9_]*\s*=\s*list\(
-                    (?:
-                        \s*
-                        (?:
-                            (?:".*?")|              # double quotes
-                            (?:'.*?')|              # single quotes
-                            (?:[^'",\s\)][^,\)]*?)       # unquoted
-                        )
-                        \s*,\s*
-                    )*
-                    (?:
-                        (?:".*?")|              # double quotes
-                        (?:'.*?')|              # single quotes
-                        (?:[^'",\s\)][^,\)]*?)       # unquoted
-                    )?                              # last one
-                \)
-            )|
-            (?:
-                (?:".*?")|              # double quotes
-                (?:'.*?')|              # single quotes
-                (?:[^'",\s=][^,=]*?)|       # unquoted
-                (?:                         # keyword argument
-                    [a-zA-Z_][a-zA-Z0-9_]*\s*=\s*
-                    (?:
-                        (?:".*?")|              # double quotes
-                        (?:'.*?')|              # single quotes
-                        (?:[^'",\s=][^,=]*?)       # unquoted
-                    )
-                )
-            )
-        )
-        (?:
-            (?:\s*,\s*)|(?:\s*$)            # comma
-        )
-    )
-    '''
-
-_matchstring = '^%s*' % _paramstring
-
-def dottedQuadToNum(ip):
-    """
-    Convert decimal dotted quad string to long integer
-    
-    >>> int(dottedQuadToNum('1 '))
-    1
-    >>> int(dottedQuadToNum(' 1.2'))
-    16777218
-    >>> int(dottedQuadToNum(' 1.2.3 '))
-    16908291
-    >>> int(dottedQuadToNum('1.2.3.4'))
-    16909060
-    >>> dottedQuadToNum('255.255.255.255')
-    4294967295L
-    >>> dottedQuadToNum('255.255.255.256')
-    Traceback (most recent call last):
-    ValueError: Not a good dotted-quad IP: 255.255.255.256
-    """
-    
-    # import here to avoid it when ip_addr values are not used
-    import socket, struct
-    
-    try:
-        return struct.unpack('!L',
-            socket.inet_aton(ip.strip()))[0]
-    except socket.error:
-        # bug in inet_aton, corrected in Python 2.4
-        if ip.strip() == '255.255.255.255':
-            return 0xFFFFFFFF
-        else:
-            raise ValueError('Not a good dotted-quad IP: %s' % ip)
-    return
-
-def numToDottedQuad(num):
-    """
-    Convert long int to dotted quad string
-    
-    >>> numToDottedQuad(-1L)
-    Traceback (most recent call last):
-    ValueError: Not a good numeric IP: -1
-    >>> numToDottedQuad(1L)
-    '0.0.0.1'
-    >>> numToDottedQuad(16777218L)
-    '1.0.0.2'
-    >>> numToDottedQuad(16908291L)
-    '1.2.0.3'
-    >>> numToDottedQuad(16909060L)
-    '1.2.3.4'
-    >>> numToDottedQuad(4294967295L)
-    '255.255.255.255'
-    >>> numToDottedQuad(4294967296L)
-    Traceback (most recent call last):
-    ValueError: Not a good numeric IP: 4294967296
-    """
-    
-    # import here to avoid it when ip_addr values are not used
-    import socket, struct
-    
-    # no need to intercept here, 4294967295L is fine
-    if num > 4294967295 or num < 0:
-        raise ValueError('Not a good numeric IP: %s' % num)
-    try:
-        return socket.inet_ntoa(
-            struct.pack('!L', int(num)))
-    except (socket.error, struct.error, OverflowError):
-        raise ValueError('Not a good numeric IP: %s' % num)
-
-class ValidateError(Exception):
-    """
-    This error indicates that the check failed.
-    It can be the base class for more specific errors.
-
-    Any check function that fails ought to raise this error.
-    (or a subclass)
-
-    >>> raise ValidateError
-    Traceback (most recent call last):
-    ValidateError
-    """
-
-class VdtMissingValue(ValidateError):
-    """No value was supplied to a check that needed one."""
-
-
-class VdtUnknownCheckError(ValidateError):
-    """An unknown check function was requested"""
-
-    def __init__(self, value):
-        """
-        >>> raise VdtUnknownCheckError('yoda')
-        Traceback (most recent call last):
-        VdtUnknownCheckError: the check "yoda" is unknown.
-        """
-        ValidateError.__init__(self, 'the check "%s" is unknown.' % (value,))
-
-
-class VdtParamError(SyntaxError):
-    """An incorrect parameter was passed"""
-
-    def __init__(self, name, value):
-        """
-        >>> raise VdtParamError('yoda', 'jedi')
-        Traceback (most recent call last):
-        VdtParamError: passed an incorrect value "jedi" for parameter "yoda".
-        """
-        SyntaxError.__init__(self, 'passed an incorrect value "%s" for parameter "%s".' % (value, name))
-
-
-class VdtTypeError(ValidateError):
-    """The value supplied was of the wrong type"""
-
-    def __init__(self, value):
-        """
-        >>> raise VdtTypeError('jedi')
-        Traceback (most recent call last):
-        VdtTypeError: the value "jedi" is of the wrong type.
-        """
-        ValidateError.__init__(self, 'the value "%s" is of the wrong type.' % (value,))
-
-
-class VdtValueError(ValidateError):
-    """The value supplied was of the correct type, but was not an allowed value."""
-    
-    def __init__(self, value):
-        """
-        >>> raise VdtValueError('jedi')
-        Traceback (most recent call last):
-        VdtValueError: the value "jedi" is unacceptable.
-        """
-        ValidateError.__init__(self, 'the value "%s" is unacceptable.' % (value,))
-
-
-class VdtValueTooSmallError(VdtValueError):
-    """The value supplied was of the correct type, but was too small."""
-
-    def __init__(self, value):
-        """
-        >>> raise VdtValueTooSmallError('0')
-        Traceback (most recent call last):
-        VdtValueTooSmallError: the value "0" is too small.
-        """
-        ValidateError.__init__(self, 'the value "%s" is too small.' % (value,))
-
-
-class VdtValueTooBigError(VdtValueError):
-    """The value supplied was of the correct type, but was too big."""
-
-    def __init__(self, value):
-        """
-        >>> raise VdtValueTooBigError('1')
-        Traceback (most recent call last):
-        VdtValueTooBigError: the value "1" is too big.
-        """
-        ValidateError.__init__(self, 'the value "%s" is too big.' % (value,))
-
-
-class VdtValueTooShortError(VdtValueError):
-    """The value supplied was of the correct type, but was too short."""
-
-    def __init__(self, value):
-        """
-        >>> raise VdtValueTooShortError('jed')
-        Traceback (most recent call last):
-        VdtValueTooShortError: the value "jed" is too short.
-        """
-        ValidateError.__init__(
-            self,
-            'the value "%s" is too short.' % (value,))
-
-
-class VdtValueTooLongError(VdtValueError):
-    """The value supplied was of the correct type, but was too long."""
-
-    def __init__(self, value):
-        """
-        >>> raise VdtValueTooLongError('jedie')
-        Traceback (most recent call last):
-        VdtValueTooLongError: the value "jedie" is too long.
-        """
-        ValidateError.__init__(self, 'the value "%s" is too long.' % (value,))
-
-class Validator(object):
-    """
-    Validator is an object that allows you to register a set of 'checks'.
-    These checks take input and test that it conforms to the check.
-    
-    This can also involve converting the value from a string into
-    the correct datatype.
-    
-    The ``check`` method takes an input string which configures which
-    check is to be used and applies that check to a supplied value.
-    
-    An example input string would be:
-    'int_range(param1, param2)'
-    
-    You would then provide something like:
-    
-    >>> def int_range_check(value, min, max):
-    ...     # turn min and max from strings to integers
-    ...     min = int(min)
-    ...     max = int(max)
-    ...     # check that value is of the correct type.
-    ...     # possible valid inputs are integers or strings
-    ...     # that represent integers
-    ...     if not isinstance(value, (int, long, str)):
-    ...         raise VdtTypeError(value)
-    ...     elif isinstance(value, str):
-    ...         # if we are given a string
-    ...         # attempt to convert to an integer
-    ...         try:
-    ...             value = int(value)
-    ...         except ValueError:
-    ...             raise VdtValueError(value)
-    ...     # check the value is between our constraints
-    ...     if not min <= value:
-    ...          raise VdtValueTooSmallError(value)
-    ...     if not value <= max:
-    ...          raise VdtValueTooBigError(value)
-    ...     return value
-    
-    >>> fdict = {'int_range': int_range_check}
-    >>> vtr1 = Validator(fdict)
-    >>> vtr1.check('int_range(20, 40)', '30')
-    30
-    >>> vtr1.check('int_range(20, 40)', '60')
-    Traceback (most recent call last):
-    VdtValueTooBigError: the value "60" is too big.
-    
-    New functions can be added with : ::
-    
-    >>> vtr2 = Validator()       
-    >>> vtr2.functions['int_range'] = int_range_check
-    
-    Or by passing in a dictionary of functions when Validator 
-    is instantiated.
-    
-    Your functions *can* use keyword arguments,
-    but the first argument should always be 'value'.
-    
-    If the function doesn't take additional arguments,
-    the parentheses are optional in the check.
-    It can be written with either of : ::
-    
-        keyword = function_name
-        keyword = function_name()
-    
-    The first program to utilise Validator() was Michael Foord's
-    ConfigObj, an alternative to ConfigParser which supports lists and
-    can validate a config file using a config schema.
-    For more details on using Validator with ConfigObj see:
-    http://www.voidspace.org.uk/python/configobj.html
-    """
-
-    # this regex does the initial parsing of the checks
-    _func_re = re.compile(r'(.+?)\((.*)\)', re.DOTALL)
-
-    # this regex takes apart keyword arguments
-    _key_arg = re.compile(r'^([a-zA-Z_][a-zA-Z0-9_]*)\s*=\s*(.*)$',  re.DOTALL)
-
-
-    # this regex finds keyword=list(....) type values
-    _list_arg = _list_arg
-
-    # this regex takes individual values out of lists - in one pass
-    _list_members = _list_members
-
-    # These regexes check a set of arguments for validity
-    # and then pull the members out
-    _paramfinder = re.compile(_paramstring, re.VERBOSE | re.DOTALL)
-    _matchfinder = re.compile(_matchstring, re.VERBOSE | re.DOTALL)
-
-
-    def __init__(self, functions=None):
-        """
-        >>> vtri = Validator()
-        """
-        self.functions = {
-            '': self._pass,
-            'integer': is_integer,
-            'float': is_float,
-            'boolean': is_boolean,
-            'ip_addr': is_ip_addr,
-            'string': is_string,
-            'list': is_list,
-            'tuple': is_tuple,
-            'int_list': is_int_list,
-            'float_list': is_float_list,
-            'bool_list': is_bool_list,
-            'ip_addr_list': is_ip_addr_list,
-            'string_list': is_string_list,
-            'mixed_list': is_mixed_list,
-            'pass': self._pass,
-            'option': is_option,
-            'force_list': force_list,
-        }
-        if functions is not None:
-            self.functions.update(functions)
-        # tekNico: for use by ConfigObj
-        self.baseErrorClass = ValidateError
-        self._cache = {}
-
-
-    def check(self, check, value, missing=False):
-        """
-        Usage: check(check, value)
-        
-        Arguments:
-            check: string representing check to apply (including arguments)
-            value: object to be checked
-        Returns value, converted to correct type if necessary
-        
-        If the check fails, raises a ``ValidateError`` subclass.
-        
-        >>> vtor.check('yoda', '')
-        Traceback (most recent call last):
-        VdtUnknownCheckError: the check "yoda" is unknown.
-        >>> vtor.check('yoda()', '')
-        Traceback (most recent call last):
-        VdtUnknownCheckError: the check "yoda" is unknown.
-        
-        >>> vtor.check('string(default="")', '', missing=True)
-        ''
-        """
-        fun_name, fun_args, fun_kwargs, default = self._parse_with_caching(check)
-            
-        if missing:
-            if default is None:
-                # no information needed here - to be handled by caller
-                raise VdtMissingValue()
-            value = self._handle_none(default)
-        
-        if value is None:
-            return None
-        
-        return self._check_value(value, fun_name, fun_args, fun_kwargs)
-
-
-    def _handle_none(self, value):
-        if value == 'None':
-            return None
-        elif value in ("'None'", '"None"'):
-            # Special case a quoted None
-            value = self._unquote(value)
-        return value
-
-
-    def _parse_with_caching(self, check):
-        if check in self._cache:
-            fun_name, fun_args, fun_kwargs, default = self._cache[check]
-            # We call list and dict below to work with *copies* of the data
-            # rather than the original (which are mutable of course)
-            fun_args = list(fun_args)
-            fun_kwargs = dict(fun_kwargs)
-        else:
-            fun_name, fun_args, fun_kwargs, default = self._parse_check(check)
-            fun_kwargs = dict([(str(key), value) for (key, value) in list(fun_kwargs.items())])
-            self._cache[check] = fun_name, list(fun_args), dict(fun_kwargs), default
-        return fun_name, fun_args, fun_kwargs, default
-        
-        
-    def _check_value(self, value, fun_name, fun_args, fun_kwargs):
-        try:
-            fun = self.functions[fun_name]
-        except KeyError:
-            raise VdtUnknownCheckError(fun_name)
-        else:
-            return fun(value, *fun_args, **fun_kwargs)
-
-
-    def _parse_check(self, check):
-        fun_match = self._func_re.match(check)
-        if fun_match:
-            fun_name = fun_match.group(1)
-            arg_string = fun_match.group(2)
-            arg_match = self._matchfinder.match(arg_string)
-            if arg_match is None:
-                # Bad syntax
-                raise VdtParamError('Bad syntax in check "%s".' % check)
-            fun_args = []
-            fun_kwargs = {}
-            # pull out args of group 2
-            for arg in self._paramfinder.findall(arg_string):
-                # args may need whitespace removing (before removing quotes)
-                arg = arg.strip()
-                listmatch = self._list_arg.match(arg)
-                if listmatch:
-                    key, val = self._list_handle(listmatch)
-                    fun_kwargs[key] = val
-                    continue
-                keymatch = self._key_arg.match(arg)
-                if keymatch:
-                    val = keymatch.group(2)
-                    if not val in ("'None'", '"None"'):
-                        # Special case a quoted None
-                        val = self._unquote(val)
-                    fun_kwargs[keymatch.group(1)] = val
-                    continue
-                
-                fun_args.append(self._unquote(arg))
-        else:
-            # allows for function names without (args)
-            return check, (), {}, None
-
-        # Default must be deleted if the value is specified too,
-        # otherwise the check function will get a spurious "default" keyword arg
-        default = fun_kwargs.pop('default', None)
-        return fun_name, fun_args, fun_kwargs, default
-
-
-    def _unquote(self, val):
-        """Unquote a value if necessary."""
-        if (len(val) >= 2) and (val[0] in ("'", '"')) and (val[0] == val[-1]):
-            val = val[1:-1]
-        return val
-
-
-    def _list_handle(self, listmatch):
-        """Take apart a ``keyword=list('val, 'val')`` type string."""
-        out = []
-        name = listmatch.group(1)
-        args = listmatch.group(2)
-        for arg in self._list_members.findall(args):
-            out.append(self._unquote(arg))
-        return name, out
-
-
-    def _pass(self, value):
-        """
-        Dummy check that always passes
-        
-        >>> vtor.check('', 0)
-        0
-        >>> vtor.check('', '0')
-        '0'
-        """
-        return value
-    
-    
-    def get_default_value(self, check):
-        """
-        Given a check, return the default value for the check
-        (converted to the right type).
-        
-        If the check doesn't specify a default value then a
-        ``KeyError`` will be raised.
-        """
-        fun_name, fun_args, fun_kwargs, default = self._parse_with_caching(check)
-        if default is None:
-            raise KeyError('Check "%s" has no default value.' % check)
-        value = self._handle_none(default)
-        if value is None:
-            return value
-        return self._check_value(value, fun_name, fun_args, fun_kwargs)
-
-def _is_num_param(names, values, to_float=False):
-    """
-    Return numbers from inputs or raise VdtParamError.
-    
-    Lets ``None`` pass through.
-    Pass in keyword argument ``to_float=True`` to
-    use float for the conversion rather than int.
-    
-    >>> _is_num_param(('', ''), (0, 1.0))
-    [0, 1]
-    >>> _is_num_param(('', ''), (0, 1.0), to_float=True)
-    [0.0, 1.0]
-    >>> _is_num_param(('a'), ('a'))
-    Traceback (most recent call last):
-    VdtParamError: passed an incorrect value "a" for parameter "a".
-    """
-    fun = to_float and float or int
-    out_params = []
-    for (name, val) in zip(names, values):
-        if val is None:
-            out_params.append(val)
-        elif isinstance(val, (int, int, float, str)):
-            try:
-                out_params.append(fun(val))
-            except ValueError as e:
-                raise VdtParamError(name, val)
-        else:
-            raise VdtParamError(name, val)
-    return out_params
-
-# built in checks
-# you can override these by setting the appropriate name
-# in Validator.functions
-# note: if the params are specified wrongly in your input string,
-#       you will also raise errors.
-
-def is_integer(value, min=None, max=None):
-    """
-    A check that tests that a given value is an integer (int, or long)
-    and optionally, between bounds. A negative value is accepted, while
-    a float will fail.
-    
-    If the value is a string, then the conversion is done - if possible.
-    Otherwise a VdtError is raised.
-    
-    >>> vtor.check('integer', '-1')
-    -1
-    >>> vtor.check('integer', '0')
-    0
-    >>> vtor.check('integer', 9)
-    9
-    >>> vtor.check('integer', 'a')
-    Traceback (most recent call last):
-    VdtTypeError: the value "a" is of the wrong type.
-    >>> vtor.check('integer', '2.2')
-    Traceback (most recent call last):
-    VdtTypeError: the value "2.2" is of the wrong type.
-    >>> vtor.check('integer(10)', '20')
-    20
-    >>> vtor.check('integer(max=20)', '15')
-    15
-    >>> vtor.check('integer(10)', '9')
-    Traceback (most recent call last):
-    VdtValueTooSmallError: the value "9" is too small.
-    >>> vtor.check('integer(10)', 9)
-    Traceback (most recent call last):
-    VdtValueTooSmallError: the value "9" is too small.
-    >>> vtor.check('integer(max=20)', '35')
-    Traceback (most recent call last):
-    VdtValueTooBigError: the value "35" is too big.
-    >>> vtor.check('integer(max=20)', 35)
-    Traceback (most recent call last):
-    VdtValueTooBigError: the value "35" is too big.
-    >>> vtor.check('integer(0, 9)', False)
-    0
-    """
-    (min_val, max_val) = _is_num_param(('min', 'max'), (min, max))
-    if not isinstance(value, (int, int, str)):
-        raise VdtTypeError(value)
-    if isinstance(value, str):
-        # if it's a string - does it represent an integer ?
-        try:
-            value = int(value)
-        except ValueError:
-            raise VdtTypeError(value)
-    if (min_val is not None) and (value < min_val):
-        raise VdtValueTooSmallError(value)
-    if (max_val is not None) and (value > max_val):
-        raise VdtValueTooBigError(value)
-    return value
-
-def is_float(value, min=None, max=None):
-    """
-    A check that tests that a given value is a float
-    (an integer will be accepted), and optionally - that it is between bounds.
-    
-    If the value is a string, then the conversion is done - if possible.
-    Otherwise a VdtError is raised.
-    
-    This can accept negative values.
-    
-    >>> vtor.check('float', '2')
-    2.0
-    
-    From now on we multiply the value to avoid comparing decimals
-    
-    >>> vtor.check('float', '-6.8') * 10
-    -68.0
-    >>> vtor.check('float', '12.2') * 10
-    122.0
-    >>> vtor.check('float', 8.4) * 10
-    84.0
-    >>> vtor.check('float', 'a')
-    Traceback (most recent call last):
-    VdtTypeError: the value "a" is of the wrong type.
-    >>> vtor.check('float(10.1)', '10.2') * 10
-    102.0
-    >>> vtor.check('float(max=20.2)', '15.1') * 10
-    151.0
-    >>> vtor.check('float(10.0)', '9.0')
-    Traceback (most recent call last):
-    VdtValueTooSmallError: the value "9.0" is too small.
-    >>> vtor.check('float(max=20.0)', '35.0')
-    Traceback (most recent call last):
-    VdtValueTooBigError: the value "35.0" is too big.
-    """
-    (min_val, max_val) = _is_num_param(
-        ('min', 'max'), (min, max), to_float=True)
-    if not isinstance(value, (int, int, float, str)):
-        raise VdtTypeError(value)
-    if not isinstance(value, float):
-        # if it's a string - does it represent a float ?
-        try:
-            value = float(value)
-        except ValueError:
-            raise VdtTypeError(value)
-    if (min_val is not None) and (value < min_val):
-        raise VdtValueTooSmallError(value)
-    if (max_val is not None) and (value > max_val):
-        raise VdtValueTooBigError(value)
-    return value
-
-bool_dict = {
-    True: True, 'on': True, '1': True, 'true': True, 'yes': True, 
-    False: False, 'off': False, '0': False, 'false': False, 'no': False,
-}
-
-def is_boolean(value):
-    """
-    Check if the value represents a boolean.
-    
-    >>> vtor.check('boolean', 0)
-    0
-    >>> vtor.check('boolean', False)
-    0
-    >>> vtor.check('boolean', '0')
-    0
-    >>> vtor.check('boolean', 'off')
-    0
-    >>> vtor.check('boolean', 'false')
-    0
-    >>> vtor.check('boolean', 'no')
-    0
-    >>> vtor.check('boolean', 'nO')
-    0
-    >>> vtor.check('boolean', 'NO')
-    0
-    >>> vtor.check('boolean', 1)
-    1
-    >>> vtor.check('boolean', True)
-    1
-    >>> vtor.check('boolean', '1')
-    1
-    >>> vtor.check('boolean', 'on')
-    1
-    >>> vtor.check('boolean', 'true')
-    1
-    >>> vtor.check('boolean', 'yes')
-    1
-    >>> vtor.check('boolean', 'Yes')
-    1
-    >>> vtor.check('boolean', 'YES')
-    1
-    >>> vtor.check('boolean', '')
-    Traceback (most recent call last):
-    VdtTypeError: the value "" is of the wrong type.
-    >>> vtor.check('boolean', 'up')
-    Traceback (most recent call last):
-    VdtTypeError: the value "up" is of the wrong type.
-    
-    """
-    if isinstance(value, str):
-        try:
-            return bool_dict[value.lower()]
-        except KeyError:
-            raise VdtTypeError(value)
-    # we do an equality test rather than an identity test
-    # this ensures Python 2.2 compatibilty
-    # and allows 0 and 1 to represent True and False
-    if value == False:
-        return False
-    elif value == True:
-        return True
-    else:
-        raise VdtTypeError(value)
-
-def is_ip_addr(value):
-    """
-    Check that the supplied value is an Internet Protocol address, v.4,
-    represented by a dotted-quad string, i.e. '1.2.3.4'.
-
-    >>> vtor.check('ip_addr', '1 ')
-    '1'
-    >>> vtor.check('ip_addr', ' 1.2')
-    '1.2'
-    >>> vtor.check('ip_addr', ' 1.2.3 ')
-    '1.2.3'
-    >>> vtor.check('ip_addr', '1.2.3.4')
-    '1.2.3.4'
-    >>> vtor.check('ip_addr', '0.0.0.0')
-    '0.0.0.0'
-    >>> vtor.check('ip_addr', '255.255.255.255')
-    '255.255.255.255'
-    >>> vtor.check('ip_addr', '255.255.255.256')
-    Traceback (most recent call last):
-    VdtValueError: the value "255.255.255.256" is unacceptable.
-    >>> vtor.check('ip_addr', '1.2.3.4.5')
-    Traceback (most recent call last):
-    VdtValueError: the value "1.2.3.4.5" is unacceptable.
-    >>> vtor.check('ip_addr', 0)
-    Traceback (most recent call last):
-    VdtTypeError: the value "0" is of the wrong type.
-    """
-    if not isinstance(value, str):
-        raise VdtTypeError(value)
-    value = value.strip()
-    try:
-        dottedQuadToNum(value)
-    except ValueError:
-        raise VdtValueError(value)
-    return value
-    
-def is_list(value, min=None, max=None):
-    """
-    Check that the value is a list of values.
-
-    You can optionally specify the minimum and maximum number of members.
-
-    It does no check on list members.
-
-    >>> vtor.check('list', ())
-    []
-    >>> vtor.check('list', [])
-    []
-    >>> vtor.check('list', (1, 2))
-    [1, 2]
-    >>> vtor.check('list', [1, 2])
-    [1, 2]
-    >>> vtor.check('list(3)', (1, 2))
-    Traceback (most recent call last):
-    VdtValueTooShortError: the value "(1, 2)" is too short.
-    >>> vtor.check('list(max=5)', (1, 2, 3, 4, 5, 6))
-    Traceback (most recent call last):
-    VdtValueTooLongError: the value "(1, 2, 3, 4, 5, 6)" is too long.
-    >>> vtor.check('list(min=3, max=5)', (1, 2, 3, 4))
-    [1, 2, 3, 4]
-    >>> vtor.check('list', 0)
-    Traceback (most recent call last):
-    VdtTypeError: the value "0" is of the wrong type.
-    >>> vtor.check('list', '12')
-    Traceback (most recent call last):
-    VdtTypeError: the value "12" is of the wrong type.
-    """
-    (min_len, max_len) = _is_num_param(('min', 'max'), (min, max))
-    if isinstance(value, str):
-        raise VdtTypeError(value)
-    try:
-        num_members = len(value)
-    except TypeError:
-        raise VdtTypeError(value)
-    if min_len is not None and num_members < min_len:
-        raise VdtValueTooShortError(value)
-    if max_len is not None and num_members > max_len:
-        raise VdtValueTooLongError(value)
-    return list(value)
-
-def is_tuple(value, min=None, max=None):
-    """
-    Check that the value is a tuple of values.
-    
-    You can optionally specify the minimum and maximum number of members.
-    
-    It does no check on members.
-    
-    >>> vtor.check('tuple', ())
-    ()
-    >>> vtor.check('tuple', [])
-    ()
-    >>> vtor.check('tuple', (1, 2))
-    (1, 2)
-    >>> vtor.check('tuple', [1, 2])
-    (1, 2)
-    >>> vtor.check('tuple(3)', (1, 2))
-    Traceback (most recent call last):
-    VdtValueTooShortError: the value "(1, 2)" is too short.
-    >>> vtor.check('tuple(max=5)', (1, 2, 3, 4, 5, 6))
-    Traceback (most recent call last):
-    VdtValueTooLongError: the value "(1, 2, 3, 4, 5, 6)" is too long.
-    >>> vtor.check('tuple(min=3, max=5)', (1, 2, 3, 4))
-    (1, 2, 3, 4)
-    >>> vtor.check('tuple', 0)
-    Traceback (most recent call last):
-    VdtTypeError: the value "0" is of the wrong type.
-    >>> vtor.check('tuple', '12')
-    Traceback (most recent call last):
-    VdtTypeError: the value "12" is of the wrong type.
-    """
-    return tuple(is_list(value, min, max))
-    
-def is_string(value, min=None, max=None):
-    """
-    Check that the supplied value is a string.
-    
-    You can optionally specify the minimum and maximum number of members.
-    
-    >>> vtor.check('string', '0')
-    '0'
-    >>> vtor.check('string', 0)
-    Traceback (most recent call last):
-    VdtTypeError: the value "0" is of the wrong type.
-    >>> vtor.check('string(2)', '12')
-    '12'
-    >>> vtor.check('string(2)', '1')
-    Traceback (most recent call last):
-    VdtValueTooShortError: the value "1" is too short.
-    >>> vtor.check('string(min=2, max=3)', '123')
-    '123'
-    >>> vtor.check('string(min=2, max=3)', '1234')
-    Traceback (most recent call last):
-    VdtValueTooLongError: the value "1234" is too long.
-    """
-    if not isinstance(value, str):
-        raise VdtTypeError(value)
-    (min_len, max_len) = _is_num_param(('min', 'max'), (min, max))
-    try:
-        num_members = len(value)
-    except TypeError:
-        raise VdtTypeError(value)
-    if min_len is not None and num_members < min_len:
-        raise VdtValueTooShortError(value)
-    if max_len is not None and num_members > max_len:
-        raise VdtValueTooLongError(value)
-    return value
-
-
-def is_int_list(value, min=None, max=None):
-    """
-    Check that the value is a list of integers.
-    
-    You can optionally specify the minimum and maximum number of members.
-    
-    Each list member is checked that it is an integer.
-    
-    >>> vtor.check('int_list', ())
-    []
-    >>> vtor.check('int_list', [])
-    []
-    >>> vtor.check('int_list', (1, 2))
-    [1, 2]
-    >>> vtor.check('int_list', [1, 2])
-    [1, 2]
-    >>> vtor.check('int_list', [1, 'a'])
-    Traceback (most recent call last):
-    VdtTypeError: the value "a" is of the wrong type.
-    """
-    return [is_integer(mem) for mem in is_list(value, min, max)]
-
-
-def is_bool_list(value, min=None, max=None):
-    """
-    Check that the value is a list of booleans.
-    
-    You can optionally specify the minimum and maximum number of members.
-    
-    Each list member is checked that it is a boolean.
-    
-    >>> vtor.check('bool_list', ())
-    []
-    >>> vtor.check('bool_list', [])
-    []
-    >>> check_res = vtor.check('bool_list', (True, False))
-    >>> check_res == [True, False]
-    1
-    >>> check_res = vtor.check('bool_list', [True, False])
-    >>> check_res == [True, False]
-    1
-    >>> vtor.check('bool_list', [True, 'a'])
-    Traceback (most recent call last):
-    VdtTypeError: the value "a" is of the wrong type.
-    """
-    return [is_boolean(mem) for mem in is_list(value, min, max)]
-
-
-def is_float_list(value, min=None, max=None):
-    """
-    Check that the value is a list of floats.
-
-    You can optionally specify the minimum and maximum number of members.
-
-    Each list member is checked that it is a float.
-
-    >>> vtor.check('float_list', ())
-    []
-    >>> vtor.check('float_list', [])
-    []
-    >>> vtor.check('float_list', (1, 2.0))
-    [1.0, 2.0]
-    >>> vtor.check('float_list', [1, 2.0])
-    [1.0, 2.0]
-    >>> vtor.check('float_list', [1, 'a'])
-    Traceback (most recent call last):
-    VdtTypeError: the value "a" is of the wrong type.
-    """
-    return [is_float(mem) for mem in is_list(value, min, max)]
-
-def is_string_list(value, min=None, max=None):
-    """
-    Check that the value is a list of strings.
-    
-    You can optionally specify the minimum and maximum number of members.
-    
-    Each list member is checked that it is a string.
-    
-    >>> vtor.check('string_list', ())
-    []
-    >>> vtor.check('string_list', [])
-    []
-    >>> vtor.check('string_list', ('a', 'b'))
-    ['a', 'b']
-    >>> vtor.check('string_list', ['a', 1])
-    Traceback (most recent call last):
-    VdtTypeError: the value "1" is of the wrong type.
-    >>> vtor.check('string_list', 'hello')
-    Traceback (most recent call last):
-    VdtTypeError: the value "hello" is of the wrong type.
-    """
-    if isinstance(value, str):
-        raise VdtTypeError(value)
-    return [is_string(mem) for mem in is_list(value, min, max)]
-
-def is_ip_addr_list(value, min=None, max=None):
-    """
-    Check that the value is a list of IP addresses.
-    
-    You can optionally specify the minimum and maximum number of members.
-    
-    Each list member is checked that it is an IP address.
-    
-    >>> vtor.check('ip_addr_list', ())
-    []
-    >>> vtor.check('ip_addr_list', [])
-    []
-    >>> vtor.check('ip_addr_list', ('1.2.3.4', '5.6.7.8'))
-    ['1.2.3.4', '5.6.7.8']
-    >>> vtor.check('ip_addr_list', ['a'])
-    Traceback (most recent call last):
-    VdtValueError: the value "a" is unacceptable.
-    """
-    return [is_ip_addr(mem) for mem in is_list(value, min, max)]
-
-def force_list(value, min=None, max=None):
-    """
-    Check that a value is a list, coercing strings into
-    a list with one member. Useful where users forget the
-    trailing comma that turns a single value into a list.
-    
-    You can optionally specify the minimum and maximum number of members.
-    A minumum of greater than one will fail if the user only supplies a
-    string.
-    
-    >>> vtor.check('force_list', ())
-    []
-    >>> vtor.check('force_list', [])
-    []
-    >>> vtor.check('force_list', 'hello')
-    ['hello']
-    """
-    if not isinstance(value, (list, tuple)):
-        value = [value]
-    return is_list(value, min, max)
-
-fun_dict = {
-    'integer': is_integer,
-    'float': is_float,
-    'ip_addr': is_ip_addr,
-    'string': is_string,
-    'boolean': is_boolean,
-}
-
-
-def is_mixed_list(value, *args):
-    """
-    Check that the value is a list.
-    Allow specifying the type of each member.
-    Work on lists of specific lengths.
-    
-    You specify each member as a positional argument specifying type
-    
-    Each type should be one of the following strings :
-      'integer', 'float', 'ip_addr', 'string', 'boolean'
-    
-    So you can specify a list of two strings, followed by
-    two integers as :
-    
-      mixed_list('string', 'string', 'integer', 'integer')
-    
-    The length of the list must match the number of positional
-    arguments you supply.
-    
-    >>> mix_str = "mixed_list('integer', 'float', 'ip_addr', 'string', 'boolean')"
-    >>> check_res = vtor.check(mix_str, (1, 2.0, '1.2.3.4', 'a', True))
-    >>> check_res == [1, 2.0, '1.2.3.4', 'a', True]
-    1
-    >>> check_res = vtor.check(mix_str, ('1', '2.0', '1.2.3.4', 'a', 'True'))
-    >>> check_res == [1, 2.0, '1.2.3.4', 'a', True]
-    1
-    >>> vtor.check(mix_str, ('b', 2.0, '1.2.3.4', 'a', True))
-    Traceback (most recent call last):
-    VdtTypeError: the value "b" is of the wrong type.
-    >>> vtor.check(mix_str, (1, 2.0, '1.2.3.4', 'a'))
-    Traceback (most recent call last):
-    VdtValueTooShortError: the value "(1, 2.0, '1.2.3.4', 'a')" is too short.
-    >>> vtor.check(mix_str, (1, 2.0, '1.2.3.4', 'a', 1, 'b'))
-    Traceback (most recent call last):
-    VdtValueTooLongError: the value "(1, 2.0, '1.2.3.4', 'a', 1, 'b')" is too long.
-    >>> vtor.check(mix_str, 0)
-    Traceback (most recent call last):
-    VdtTypeError: the value "0" is of the wrong type.
-    
-    This test requires an elaborate setup, because of a change in error string
-    output from the interpreter between Python 2.2 and 2.3 .
-    
-    >>> res_seq = (
-    ...     'passed an incorrect value "',
-    ...     'yoda',
-    ...     '" for parameter "mixed_list".',
-    ... )
-    >>> res_str = "'".join(res_seq)
-    >>> try:
-    ...     vtor.check('mixed_list("yoda")', ('a'))
-    ... except VdtParamError, err:
-    ...     str(err) == res_str
-    1
-    """
-    try:
-        length = len(value)
-    except TypeError:
-        raise VdtTypeError(value)
-    if length < len(args):
-        raise VdtValueTooShortError(value)
-    elif length > len(args):
-        raise VdtValueTooLongError(value)
-    try:
-        return [fun_dict[arg](val) for arg, val in zip(args, value)]
-    except KeyError as e:
-        raise VdtParamError('mixed_list', e)
-
-
-def is_option(value, *options):
-    """
-    This check matches the value to any of a set of options.
-    
-    >>> vtor.check('option("yoda", "jedi")', 'yoda')
-    'yoda'
-    >>> vtor.check('option("yoda", "jedi")', 'jed')
-    Traceback (most recent call last):
-    VdtValueError: the value "jed" is unacceptable.
-    >>> vtor.check('option("yoda", "jedi")', 0)
-    Traceback (most recent call last):
-    VdtTypeError: the value "0" is of the wrong type.
-    """
-    if not isinstance(value, str):
-        raise VdtTypeError(value)
-    if not value in options:
-        raise VdtValueError(value)
-    return value
-
-def _test(value, *args, **keywargs):
-    """
-    A function that exists for test purposes.
-    
-    >>> checks = [
-    ...     '3, 6, min=1, max=3, test=list(a, b, c)',
-    ...     '3',
-    ...     '3, 6',
-    ...     '3,',
-    ...     'min=1, test="a b c"',
-    ...     'min=5, test="a, b, c"',
-    ...     'min=1, max=3, test="a, b, c"',
-    ...     'min=-100, test=-99',
-    ...     'min=1, max=3',
-    ...     '3, 6, test="36"',
-    ...     '3, 6, test="a, b, c"',
-    ...     '3, max=3, test=list("a", "b", "c")',
-    ...     '''3, max=3, test=list("'a'", 'b', "x=(c)")''',
-    ...     "test='x=fish(3)'",
-    ...    ]
-    >>> v = Validator({'test': _test})
-    >>> for entry in checks:
-    ...     print v.check(('test(%s)' % entry), 3)
-    (3, ('3', '6'), {'test': ['a', 'b', 'c'], 'max': '3', 'min': '1'})
-    (3, ('3',), {})
-    (3, ('3', '6'), {})
-    (3, ('3',), {})
-    (3, (), {'test': 'a b c', 'min': '1'})
-    (3, (), {'test': 'a, b, c', 'min': '5'})
-    (3, (), {'test': 'a, b, c', 'max': '3', 'min': '1'})
-    (3, (), {'test': '-99', 'min': '-100'})
-    (3, (), {'max': '3', 'min': '1'})
-    (3, ('3', '6'), {'test': '36'})
-    (3, ('3', '6'), {'test': 'a, b, c'})
-    (3, ('3',), {'test': ['a', 'b', 'c'], 'max': '3'})
-    (3, ('3',), {'test': ["'a'", 'b', 'x=(c)'], 'max': '3'})
-    (3, (), {'test': 'x=fish(3)'})
-    
-    >>> v = Validator()
-    >>> v.check('integer(default=6)', '3')
-    3
-    >>> v.check('integer(default=6)', None, True)
-    6
-    >>> v.get_default_value('integer(default=6)')
-    6
-    >>> v.get_default_value('float(default=6)')
-    6.0
-    >>> v.get_default_value('pass(default=None)')
-    >>> v.get_default_value("string(default='None')")
-    'None'
-    >>> v.get_default_value('pass')
-    Traceback (most recent call last):
-    KeyError: 'Check "pass" has no default value.'
-    >>> v.get_default_value('pass(default=list(1, 2, 3, 4))')
-    ['1', '2', '3', '4']
-    
-    >>> v = Validator()
-    >>> v.check("pass(default=None)", None, True)
-    >>> v.check("pass(default='None')", None, True)
-    'None'
-    >>> v.check('pass(default="None")', None, True)
-    'None'
-    >>> v.check('pass(default=list(1, 2, 3, 4))', None, True)
-    ['1', '2', '3', '4']
-    
-    Bug test for unicode arguments
-    >>> v = Validator()
-    >>> v.check(u'string(min=4)', u'test')
-    u'test'
-    
-    >>> v = Validator()
-    >>> v.get_default_value(u'string(min=4, default="1234")')
-    u'1234'
-    >>> v.check(u'string(min=4, default="1234")', u'test')
-    u'test'
-    
-    >>> v = Validator()
-    >>> default = v.get_default_value('string(default=None)')
-    >>> default == None
-    1
-    """
-    return (value, args, keywargs)
-
-
-def _test2():
-    """
-    >>> 
-    >>> v = Validator()
-    >>> v.get_default_value('string(default="#ff00dd")')
-    '#ff00dd'
-    >>> v.get_default_value('integer(default=3) # comment')
-    3
-    """
-
-def _test3():
-    r"""
-    >>> vtor.check('string(default="")', '', missing=True)
-    ''
-    >>> vtor.check('string(default="\n")', '', missing=True)
-    '\n'
-    >>> print vtor.check('string(default="\n")', '', missing=True),
-    <BLANKLINE>
-    >>> vtor.check('string()', '\n')
-    '\n'
-    >>> vtor.check('string(default="\n\n\n")', '', missing=True)
-    '\n\n\n'
-    >>> vtor.check('string()', 'random \n text goes here\n\n')
-    'random \n text goes here\n\n'
-    >>> vtor.check('string(default=" \nrandom text\ngoes \n here\n\n ")',
-    ... '', missing=True)
-    ' \nrandom text\ngoes \n here\n\n '
-    >>> vtor.check("string(default='\n\n\n')", '', missing=True)
-    '\n\n\n'
-    >>> vtor.check("option('\n','a','b',default='\n')", '', missing=True)
-    '\n'
-    >>> vtor.check("string_list()", ['foo', '\n', 'bar'])
-    ['foo', '\n', 'bar']
-    >>> vtor.check("string_list(default=list('\n'))", '', missing=True)
-    ['\n']
-    """
-
-if __name__ == '__main__':
-    # run the code tests in doctest format
-    import sys
-    import doctest
-    m = sys.modules.get('__main__')
-    globs = m.__dict__.copy()
-    globs.update({
-        'vtor': Validator(),
-    })
-    doctest.testmod(m, globs=globs)
\ No newline at end of file
diff --git a/astropy/extern/pyparsing.py b/astropy/extern/pyparsing.py
new file mode 100644
index 0000000..2425092
--- /dev/null
+++ b/astropy/extern/pyparsing.py
@@ -0,0 +1,16 @@
+# Licensed under a 3-clause BSD style license - see LICENSE.rst
+
+"""
+This module just pulls in the appropriate `pyparsing` module, depending on the
+currently installed version of python.
+"""
+from sys import version_info
+
+if version_info[0] > 2:
+    from .pyparsing_py3.pyparsing_py3 import *
+    from .pyparsing_py3.pyparsing_py3 import __doc__
+else:
+    from .pyparsing_py2.pyparsing_py2 import *
+    from .pyparsing_py2.pyparsing_py2 import __doc__
+
+del version_info #cleans up the namespace
diff --git a/astropy/config/tests/__init__.py b/astropy/extern/pyparsing_py2/__init__.py
similarity index 100%
copy from astropy/config/tests/__init__.py
copy to astropy/extern/pyparsing_py2/__init__.py
diff --git a/astropy/extern/pyparsing_py2/pyparsing_py2.py b/astropy/extern/pyparsing_py2/pyparsing_py2.py
new file mode 100644
index 0000000..eb67bea
--- /dev/null
+++ b/astropy/extern/pyparsing_py2/pyparsing_py2.py
@@ -0,0 +1,3750 @@
+# module pyparsing.py
+#
+# Copyright (c) 2003-2011  Paul T. McGuire
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+#from __future__ import generators
+
+__doc__ = \
+"""
+pyparsing module - Classes and methods to define and execute parsing grammars
+
+The pyparsing module is an alternative approach to creating and executing simple grammars,
+vs. the traditional lex/yacc approach, or the use of regular expressions.  With pyparsing, you
+don't need to learn a new syntax for defining grammars or matching expressions - the parsing module
+provides a library of classes that you use to construct the grammar directly in Python.
+
+Here is a program to parse "Hello, World!" (or any greeting of the form C{"<salutation>, <addressee>!"})::
+
+    from pyparsing import Word, alphas
+
+    # define grammar of a greeting
+    greet = Word( alphas ) + "," + Word( alphas ) + "!"
+
+    hello = "Hello, World!"
+    print hello, "->", greet.parseString( hello )
+
+The program outputs the following::
+
+    Hello, World! -> ['Hello', ',', 'World', '!']
+
+The Python representation of the grammar is quite readable, owing to the self-explanatory
+class names, and the use of '+', '|' and '^' operators.
+
+The parsed results returned from C{parseString()} can be accessed as a nested list, a dictionary, or an
+object with named attributes.
+
+The pyparsing module handles some of the problems that are typically vexing when writing text parsers:
+ - extra or missing whitespace (the above program will also handle "Hello,World!", "Hello  ,  World  !", etc.)
+ - quoted strings
+ - embedded comments
+"""
+
+__version__ = "1.5.6"
+__versionTime__ = "26 June 2011 10:53"
+__author__ = "Paul McGuire <ptmcg at users.sourceforge.net>"
+
+import string
+from weakref import ref as wkref
+import copy
+import sys
+import warnings
+import re
+import sre_constants
+#~ sys.stderr.write( "testing pyparsing module, version %s, %s\n" % (__version__,__versionTime__ ) )
+
+__all__ = [
+'And', 'CaselessKeyword', 'CaselessLiteral', 'CharsNotIn', 'Combine', 'Dict', 'Each', 'Empty',
+'FollowedBy', 'Forward', 'GoToColumn', 'Group', 'Keyword', 'LineEnd', 'LineStart', 'Literal',
+'MatchFirst', 'NoMatch', 'NotAny', 'OneOrMore', 'OnlyOnce', 'Optional', 'Or',
+'ParseBaseException', 'ParseElementEnhance', 'ParseException', 'ParseExpression', 'ParseFatalException',
+'ParseResults', 'ParseSyntaxException', 'ParserElement', 'QuotedString', 'RecursiveGrammarException',
+'Regex', 'SkipTo', 'StringEnd', 'StringStart', 'Suppress', 'Token', 'TokenConverter', 'Upcase',
+'White', 'Word', 'WordEnd', 'WordStart', 'ZeroOrMore',
+'alphanums', 'alphas', 'alphas8bit', 'anyCloseTag', 'anyOpenTag', 'cStyleComment', 'col',
+'commaSeparatedList', 'commonHTMLEntity', 'countedArray', 'cppStyleComment', 'dblQuotedString',
+'dblSlashComment', 'delimitedList', 'dictOf', 'downcaseTokens', 'empty', 'getTokensEndLoc', 'hexnums',
+'htmlComment', 'javaStyleComment', 'keepOriginalText', 'line', 'lineEnd', 'lineStart', 'lineno',
+'makeHTMLTags', 'makeXMLTags', 'matchOnlyAtCol', 'matchPreviousExpr', 'matchPreviousLiteral',
+'nestedExpr', 'nullDebugAction', 'nums', 'oneOf', 'opAssoc', 'operatorPrecedence', 'printables',
+'punc8bit', 'pythonStyleComment', 'quotedString', 'removeQuotes', 'replaceHTMLEntity',
+'replaceWith', 'restOfLine', 'sglQuotedString', 'srange', 'stringEnd',
+'stringStart', 'traceParseAction', 'unicodeString', 'upcaseTokens', 'withAttribute',
+'indentedBlock', 'originalTextFor',
+]
+
+"""
+Detect if we are running version 3.X and make appropriate changes
+Robert A. Clark
+"""
+_PY3K = sys.version_info[0] > 2
+if _PY3K:
+    _MAX_INT = sys.maxsize
+    basestring = str
+    unichr = chr
+    _ustr = str
+    alphas = string.ascii_lowercase + string.ascii_uppercase
+else:
+    _MAX_INT = sys.maxint
+    range = xrange
+    set = lambda s : dict( [(c,0) for c in s] )
+    alphas = string.lowercase + string.uppercase
+
+    def _ustr(obj):
+        """Drop-in replacement for str(obj) that tries to be Unicode friendly. It first tries
+           str(obj). If that fails with a UnicodeEncodeError, then it tries unicode(obj). It
+           then < returns the unicode object | encodes it with the default encoding | ... >.
+        """
+        if isinstance(obj,unicode):
+            return obj
+
+        try:
+            # If this works, then _ustr(obj) has the same behaviour as str(obj), so
+            # it won't break any existing code.
+            return str(obj)
+
+        except UnicodeEncodeError:
+            # The Python docs (http://docs.python.org/ref/customization.html#l2h-182)
+            # state that "The return value must be a string object". However, does a
+            # unicode object (being a subclass of basestring) count as a "string
+            # object"?
+            # If so, then return a unicode object:
+            return unicode(obj)
+            # Else encode it... but how? There are many choices... :)
+            # Replace unprintables with escape codes?
+            #return unicode(obj).encode(sys.getdefaultencoding(), 'backslashreplace_errors')
+            # Replace unprintables with question marks?
+            #return unicode(obj).encode(sys.getdefaultencoding(), 'replace')
+            # ...
+
+    alphas = string.lowercase + string.uppercase
+
+# build list of single arg builtins, tolerant of Python version, that can be used as parse actions
+singleArgBuiltins = []
+import __builtin__
+for fname in "sum len enumerate sorted reversed list tuple set any all".split():
+    try:
+        singleArgBuiltins.append(getattr(__builtin__,fname))
+    except AttributeError:
+        continue
+
+def _xml_escape(data):
+    """Escape &, <, >, ", ', etc. in a string of data."""
+
+    # ampersand must be replaced first
+    from_symbols = '&><"\''
+    to_symbols = ['&'+s+';' for s in "amp gt lt quot apos".split()]
+    for from_,to_ in zip(from_symbols, to_symbols):
+        data = data.replace(from_, to_)
+    return data
+
+class _Constants(object):
+    pass
+
+nums       = string.digits
+hexnums    = nums + "ABCDEFabcdef"
+alphanums  = alphas + nums
+_bslash    = chr(92)
+printables = "".join( [ c for c in string.printable if c not in string.whitespace ] )
+
+class ParseBaseException(Exception):
+    """base exception class for all parsing runtime exceptions"""
+    # Performance tuning: we construct a *lot* of these, so keep this
+    # constructor as small and fast as possible
+    def __init__( self, pstr, loc=0, msg=None, elem=None ):
+        self.loc = loc
+        if msg is None:
+            self.msg = pstr
+            self.pstr = ""
+        else:
+            self.msg = msg
+            self.pstr = pstr
+        self.parserElement = elem
+
+    def __getattr__( self, aname ):
+        """supported attributes by name are:
+            - lineno - returns the line number of the exception text
+            - col - returns the column number of the exception text
+            - line - returns the line containing the exception text
+        """
+        if( aname == "lineno" ):
+            return lineno( self.loc, self.pstr )
+        elif( aname in ("col", "column") ):
+            return col( self.loc, self.pstr )
+        elif( aname == "line" ):
+            return line( self.loc, self.pstr )
+        else:
+            raise AttributeError(aname)
+
+    def __str__( self ):
+        return "%s (at char %d), (line:%d, col:%d)" % \
+                ( self.msg, self.loc, self.lineno, self.column )
+    def __repr__( self ):
+        return _ustr(self)
+    def markInputline( self, markerString = ">!<" ):
+        """Extracts the exception line from the input string, and marks
+           the location of the exception with a special symbol.
+        """
+        line_str = self.line
+        line_column = self.column - 1
+        if markerString:
+            line_str = "".join( [line_str[:line_column],
+                                markerString, line_str[line_column:]])
+        return line_str.strip()
+    def __dir__(self):
+        return "loc msg pstr parserElement lineno col line " \
+               "markInputLine __str__ __repr__".split()
+
+class ParseException(ParseBaseException):
+    """exception thrown when parse expressions don't match class;
+       supported attributes by name are:
+        - lineno - returns the line number of the exception text
+        - col - returns the column number of the exception text
+        - line - returns the line containing the exception text
+    """
+    pass
+
+class ParseFatalException(ParseBaseException):
+    """user-throwable exception thrown when inconsistent parse content
+       is found; stops all parsing immediately"""
+    pass
+
+class ParseSyntaxException(ParseFatalException):
+    """just like C{ParseFatalException}, but thrown internally when an
+       C{ErrorStop} ('-' operator) indicates that parsing is to stop immediately because
+       an unbacktrackable syntax error has been found"""
+    def __init__(self, pe):
+        super(ParseSyntaxException, self).__init__(
+                                    pe.pstr, pe.loc, pe.msg, pe.parserElement)
+
+#~ class ReparseException(ParseBaseException):
+    #~ """Experimental class - parse actions can raise this exception to cause
+       #~ pyparsing to reparse the input string:
+        #~ - with a modified input string, and/or
+        #~ - with a modified start location
+       #~ Set the values of the ReparseException in the constructor, and raise the
+       #~ exception in a parse action to cause pyparsing to use the new string/location.
+       #~ Setting the values as None causes no change to be made.
+       #~ """
+    #~ def __init_( self, newstring, restartLoc ):
+        #~ self.newParseText = newstring
+        #~ self.reparseLoc = restartLoc
+
+class RecursiveGrammarException(Exception):
+    """exception thrown by C{validate()} if the grammar could be improperly recursive"""
+    def __init__( self, parseElementList ):
+        self.parseElementTrace = parseElementList
+
+    def __str__( self ):
+        return "RecursiveGrammarException: %s" % self.parseElementTrace
+
+class _ParseResultsWithOffset(object):
+    def __init__(self,p1,p2):
+        self.tup = (p1,p2)
+    def __getitem__(self,i):
+        return self.tup[i]
+    def __repr__(self):
+        return repr(self.tup)
+    def setOffset(self,i):
+        self.tup = (self.tup[0],i)
+
+class ParseResults(object):
+    """Structured parse results, to provide multiple means of access to the parsed data:
+       - as a list (C{len(results)})
+       - by list index (C{results[0], results[1]}, etc.)
+       - by attribute (C{results.<resultsName>})
+       """
+    #~ __slots__ = ( "__toklist", "__tokdict", "__doinit", "__name", "__parent", "__accumNames", "__weakref__" )
+    def __new__(cls, toklist, name=None, asList=True, modal=True ):
+        if isinstance(toklist, cls):
+            return toklist
+        retobj = object.__new__(cls)
+        retobj.__doinit = True
+        return retobj
+
+    # Performance tuning: we construct a *lot* of these, so keep this
+    # constructor as small and fast as possible
+    def __init__( self, toklist, name=None, asList=True, modal=True, isinstance=isinstance ):
+        if self.__doinit:
+            self.__doinit = False
+            self.__name = None
+            self.__parent = None
+            self.__accumNames = {}
+            if isinstance(toklist, list):
+                self.__toklist = toklist[:]
+            else:
+                self.__toklist = [toklist]
+            self.__tokdict = dict()
+
+        if name is not None and name:
+            if not modal:
+                self.__accumNames[name] = 0
+            if isinstance(name,int):
+                name = _ustr(name) # will always return a str, but use _ustr for consistency
+            self.__name = name
+            if not toklist in (None,'',[]):
+                if isinstance(toklist,basestring):
+                    toklist = [ toklist ]
+                if asList:
+                    if isinstance(toklist,ParseResults):
+                        self[name] = _ParseResultsWithOffset(toklist.copy(),0)
+                    else:
+                        self[name] = _ParseResultsWithOffset(ParseResults(toklist[0]),0)
+                    self[name].__name = name
+                else:
+                    try:
+                        self[name] = toklist[0]
+                    except (KeyError,TypeError,IndexError):
+                        self[name] = toklist
+
+    def __getitem__( self, i ):
+        if isinstance( i, (int,slice) ):
+            return self.__toklist[i]
+        else:
+            if i not in self.__accumNames:
+                return self.__tokdict[i][-1][0]
+            else:
+                return ParseResults([ v[0] for v in self.__tokdict[i] ])
+
+    def __setitem__( self, k, v, isinstance=isinstance ):
+        if isinstance(v,_ParseResultsWithOffset):
+            self.__tokdict[k] = self.__tokdict.get(k,list()) + [v]
+            sub = v[0]
+        elif isinstance(k,int):
+            self.__toklist[k] = v
+            sub = v
+        else:
+            self.__tokdict[k] = self.__tokdict.get(k,list()) + [_ParseResultsWithOffset(v,0)]
+            sub = v
+        if isinstance(sub,ParseResults):
+            sub.__parent = wkref(self)
+
+    def __delitem__( self, i ):
+        if isinstance(i,(int,slice)):
+            mylen = len( self.__toklist )
+            del self.__toklist[i]
+
+            # convert int to slice
+            if isinstance(i, int):
+                if i < 0:
+                    i += mylen
+                i = slice(i, i+1)
+            # get removed indices
+            removed = list(range(*i.indices(mylen)))
+            removed.reverse()
+            # fixup indices in token dictionary
+            for name in self.__tokdict:
+                occurrences = self.__tokdict[name]
+                for j in removed:
+                    for k, (value, position) in enumerate(occurrences):
+                        occurrences[k] = _ParseResultsWithOffset(value, position - (position > j))
+        else:
+            del self.__tokdict[i]
+
+    def __contains__( self, k ):
+        return k in self.__tokdict
+
+    def __len__( self ): return len( self.__toklist )
+    def __bool__(self): return len( self.__toklist ) > 0
+    __nonzero__ = __bool__
+    def __iter__( self ): return iter( self.__toklist )
+    def __reversed__( self ): return iter( self.__toklist[::-1] )
+    def keys( self ):
+        """Returns all named result keys."""
+        return self.__tokdict.keys()
+
+    def pop( self, index=-1 ):
+        """Removes and returns item at specified index (default=last).
+           Will work with either numeric indices or dict-key indicies."""
+        ret = self[index]
+        del self[index]
+        return ret
+
+    def get(self, key, defaultValue=None):
+        """Returns named result matching the given key, or if there is no
+           such name, then returns the given C{defaultValue} or C{None} if no
+           C{defaultValue} is specified."""
+        if key in self:
+            return self[key]
+        else:
+            return defaultValue
+
+    def insert( self, index, insStr ):
+        """Inserts new element at location index in the list of parsed tokens."""
+        self.__toklist.insert(index, insStr)
+        # fixup indices in token dictionary
+        for name in self.__tokdict:
+            occurrences = self.__tokdict[name]
+            for k, (value, position) in enumerate(occurrences):
+                occurrences[k] = _ParseResultsWithOffset(value, position + (position > index))
+
+    def items( self ):
+        """Returns all named result keys and values as a list of tuples."""
+        return [(k,self[k]) for k in self.__tokdict]
+
+    def values( self ):
+        """Returns all named result values."""
+        return [ v[-1][0] for v in self.__tokdict.values() ]
+
+    def __getattr__( self, name ):
+        if True: #name not in self.__slots__:
+            if name in self.__tokdict:
+                if name not in self.__accumNames:
+                    return self.__tokdict[name][-1][0]
+                else:
+                    return ParseResults([ v[0] for v in self.__tokdict[name] ])
+            else:
+                return ""
+        return None
+
+    def __add__( self, other ):
+        ret = self.copy()
+        ret += other
+        return ret
+
+    def __iadd__( self, other ):
+        if other.__tokdict:
+            offset = len(self.__toklist)
+            addoffset = ( lambda a: (a<0 and offset) or (a+offset) )
+            otheritems = other.__tokdict.items()
+            otherdictitems = [(k, _ParseResultsWithOffset(v[0],addoffset(v[1])) )
+                                for (k,vlist) in otheritems for v in vlist]
+            for k,v in otherdictitems:
+                self[k] = v
+                if isinstance(v[0],ParseResults):
+                    v[0].__parent = wkref(self)
+
+        self.__toklist += other.__toklist
+        self.__accumNames.update( other.__accumNames )
+        return self
+
+    def __radd__(self, other):
+        if isinstance(other,int) and other == 0:
+            return self.copy()
+
+    def __repr__( self ):
+        return "(%s, %s)" % ( repr( self.__toklist ), repr( self.__tokdict ) )
+
+    def __str__( self ):
+        out = "["
+        sep = ""
+        for i in self.__toklist:
+            if isinstance(i, ParseResults):
+                out += sep + _ustr(i)
+            else:
+                out += sep + repr(i)
+            sep = ", "
+        out += "]"
+        return out
+
+    def _asStringList( self, sep='' ):
+        out = []
+        for item in self.__toklist:
+            if out and sep:
+                out.append(sep)
+            if isinstance( item, ParseResults ):
+                out += item._asStringList()
+            else:
+                out.append( _ustr(item) )
+        return out
+
+    def asList( self ):
+        """Returns the parse results as a nested list of matching tokens, all converted to strings."""
+        out = []
+        for res in self.__toklist:
+            if isinstance(res,ParseResults):
+                out.append( res.asList() )
+            else:
+                out.append( res )
+        return out
+
+    def asDict( self ):
+        """Returns the named parse results as dictionary."""
+        return dict( self.items() )
+
+    def copy( self ):
+        """Returns a new copy of a C{ParseResults} object."""
+        ret = ParseResults( self.__toklist )
+        ret.__tokdict = self.__tokdict.copy()
+        ret.__parent = self.__parent
+        ret.__accumNames.update( self.__accumNames )
+        ret.__name = self.__name
+        return ret
+
+    def asXML( self, doctag=None, namedItemsOnly=False, indent="", formatted=True ):
+        """Returns the parse results as XML. Tags are created for tokens and lists that have defined results names."""
+        nl = "\n"
+        out = []
+        namedItems = dict( [ (v[1],k) for (k,vlist) in self.__tokdict.items()
+                                                            for v in vlist ] )
+        nextLevelIndent = indent + "  "
+
+        # collapse out indents if formatting is not desired
+        if not formatted:
+            indent = ""
+            nextLevelIndent = ""
+            nl = ""
+
+        selfTag = None
+        if doctag is not None:
+            selfTag = doctag
+        else:
+            if self.__name:
+                selfTag = self.__name
+
+        if not selfTag:
+            if namedItemsOnly:
+                return ""
+            else:
+                selfTag = "ITEM"
+
+        out += [ nl, indent, "<", selfTag, ">" ]
+
+        worklist = self.__toklist
+        for i,res in enumerate(worklist):
+            if isinstance(res,ParseResults):
+                if i in namedItems:
+                    out += [ res.asXML(namedItems[i],
+                                        namedItemsOnly and doctag is None,
+                                        nextLevelIndent,
+                                        formatted)]
+                else:
+                    out += [ res.asXML(None,
+                                        namedItemsOnly and doctag is None,
+                                        nextLevelIndent,
+                                        formatted)]
+            else:
+                # individual token, see if there is a name for it
+                resTag = None
+                if i in namedItems:
+                    resTag = namedItems[i]
+                if not resTag:
+                    if namedItemsOnly:
+                        continue
+                    else:
+                        resTag = "ITEM"
+                xmlBodyText = _xml_escape(_ustr(res))
+                out += [ nl, nextLevelIndent, "<", resTag, ">",
+                                                xmlBodyText,
+                                                "</", resTag, ">" ]
+
+        out += [ nl, indent, "</", selfTag, ">" ]
+        return "".join(out)
+
+    def __lookup(self,sub):
+        for k,vlist in self.__tokdict.items():
+            for v,loc in vlist:
+                if sub is v:
+                    return k
+        return None
+
+    def getName(self):
+        """Returns the results name for this token expression."""
+        if self.__name:
+            return self.__name
+        elif self.__parent:
+            par = self.__parent()
+            if par:
+                return par.__lookup(self)
+            else:
+                return None
+        elif (len(self) == 1 and
+               len(self.__tokdict) == 1 and
+               self.__tokdict.values()[0][0][1] in (0,-1)):
+            return self.__tokdict.keys()[0]
+        else:
+            return None
+
+    def dump(self,indent='',depth=0):
+        """Diagnostic method for listing out the contents of a C{ParseResults}.
+           Accepts an optional C{indent} argument so that this string can be embedded
+           in a nested display of other data."""
+        out = []
+        out.append( indent+_ustr(self.asList()) )
+        keys = self.items()
+        keys.sort()
+        for k,v in keys:
+            if out:
+                out.append('\n')
+            out.append( "%s%s- %s: " % (indent,('  '*depth), k) )
+            if isinstance(v,ParseResults):
+                if v.keys():
+                    out.append( v.dump(indent,depth+1) )
+                else:
+                    out.append(_ustr(v))
+            else:
+                out.append(_ustr(v))
+        return "".join(out)
+
+    # add support for pickle protocol
+    def __getstate__(self):
+        return ( self.__toklist,
+                 ( self.__tokdict.copy(),
+                   self.__parent is not None and self.__parent() or None,
+                   self.__accumNames,
+                   self.__name ) )
+
+    def __setstate__(self,state):
+        self.__toklist = state[0]
+        (self.__tokdict,
+         par,
+         inAccumNames,
+         self.__name) = state[1]
+        self.__accumNames = {}
+        self.__accumNames.update(inAccumNames)
+        if par is not None:
+            self.__parent = wkref(par)
+        else:
+            self.__parent = None
+
+    def __dir__(self):
+        return dir(super(ParseResults,self)) + self.keys()
+
+def col (loc,strg):
+    """Returns current column within a string, counting newlines as line separators.
+   The first column is number 1.
+
+   Note: the default parsing behavior is to expand tabs in the input string
+   before starting the parsing process.  See L{I{ParserElement.parseString}<ParserElement.parseString>} for more information
+   on parsing strings containing <TAB>s, and suggested methods to maintain a
+   consistent view of the parsed string, the parse location, and line and column
+   positions within the parsed string.
+   """
+    return (loc<len(strg) and strg[loc] == '\n') and 1 or loc - strg.rfind("\n", 0, loc)
+
+def lineno(loc,strg):
+    """Returns current line number within a string, counting newlines as line separators.
+   The first line is number 1.
+
+   Note: the default parsing behavior is to expand tabs in the input string
+   before starting the parsing process.  See L{I{ParserElement.parseString}<ParserElement.parseString>} for more information
+   on parsing strings containing <TAB>s, and suggested methods to maintain a
+   consistent view of the parsed string, the parse location, and line and column
+   positions within the parsed string.
+   """
+    return strg.count("\n",0,loc) + 1
+
+def line( loc, strg ):
+    """Returns the line of text containing loc within a string, counting newlines as line separators.
+       """
+    lastCR = strg.rfind("\n", 0, loc)
+    nextCR = strg.find("\n", loc)
+    if nextCR >= 0:
+        return strg[lastCR+1:nextCR]
+    else:
+        return strg[lastCR+1:]
+
+def _defaultStartDebugAction( instring, loc, expr ):
+    print ("Match " + _ustr(expr) + " at loc " + _ustr(loc) + "(%d,%d)" % ( lineno(loc,instring), col(loc,instring) ))
+
+def _defaultSuccessDebugAction( instring, startloc, endloc, expr, toks ):
+    print ("Matched " + _ustr(expr) + " -> " + str(toks.asList()))
+
+def _defaultExceptionDebugAction( instring, loc, expr, exc ):
+    print ("Exception raised:" + _ustr(exc))
+
+def nullDebugAction(*args):
+    """'Do-nothing' debug action, to suppress debugging output during parsing."""
+    pass
+
+'decorator to trim function calls to match the arity of the target'
+if not _PY3K:
+    def _trim_arity(func, maxargs=2):
+        limit = [0]
+        def wrapper(*args):
+            while 1:
+                try:
+                    return func(*args[limit[0]:])
+                except TypeError:
+                    raise
+                    if limit[0] <= maxargs:
+                        limit[0] += 1
+                        continue
+                    raise
+        return wrapper
+else:
+    def _trim_arity(func, maxargs=2):
+        limit = maxargs
+        def wrapper(*args):
+            #~ nonlocal limit
+            while 1:
+                try:
+                    return func(*args[limit:])
+                except TypeError:
+                    if limit:
+                        limit -= 1
+                        continue
+                    raise
+        return wrapper
+
+class ParserElement(object):
+    """Abstract base level parser element class."""
+    DEFAULT_WHITE_CHARS = " \n\t\r"
+    verbose_stacktrace = False
+
+    def setDefaultWhitespaceChars( chars ):
+        """Overrides the default whitespace chars
+        """
+        ParserElement.DEFAULT_WHITE_CHARS = chars
+    setDefaultWhitespaceChars = staticmethod(setDefaultWhitespaceChars)
+
+    def __init__( self, savelist=False ):
+        self.parseAction = list()
+        self.failAction = None
+        #~ self.name = "<unknown>"  # don't define self.name, let subclasses try/except upcall
+        self.strRepr = None
+        self.resultsName = None
+        self.saveAsList = savelist
+        self.skipWhitespace = True
+        self.whiteChars = ParserElement.DEFAULT_WHITE_CHARS
+        self.copyDefaultWhiteChars = True
+        self.mayReturnEmpty = False # used when checking for left-recursion
+        self.keepTabs = False
+        self.ignoreExprs = list()
+        self.debug = False
+        self.streamlined = False
+        self.mayIndexError = True # used to optimize exception handling for subclasses that don't advance parse index
+        self.errmsg = ""
+        self.modalResults = True # used to mark results names as modal (report only last) or cumulative (list all)
+        self.debugActions = ( None, None, None ) #custom debug actions
+        self.re = None
+        self.callPreparse = True # used to avoid redundant calls to preParse
+        self.callDuringTry = False
+
+    def copy( self ):
+        """Make a copy of this C{ParserElement}.  Useful for defining different parse actions
+           for the same parsing pattern, using copies of the original parse element."""
+        cpy = copy.copy( self )
+        cpy.parseAction = self.parseAction[:]
+        cpy.ignoreExprs = self.ignoreExprs[:]
+        if self.copyDefaultWhiteChars:
+            cpy.whiteChars = ParserElement.DEFAULT_WHITE_CHARS
+        return cpy
+
+    def setName( self, name ):
+        """Define name for this expression, for use in debugging."""
+        self.name = name
+        self.errmsg = "Expected " + self.name
+        if hasattr(self,"exception"):
+            self.exception.msg = self.errmsg
+        return self
+
+    def setResultsName( self, name, listAllMatches=False ):
+        """Define name for referencing matching tokens as a nested attribute
+           of the returned parse results.
+           NOTE: this returns a *copy* of the original C{ParserElement} object;
+           this is so that the client can define a basic element, such as an
+           integer, and reference it in multiple places with different names.
+
+           You can also set results names using the abbreviated syntax,
+           C{expr("name")} in place of C{expr.setResultsName("name")} -
+           see L{I{__call__}<__call__>}.
+        """
+        newself = self.copy()
+        if name.endswith("*"):
+            name = name[:-1]
+            listAllMatches=True
+        newself.resultsName = name
+        newself.modalResults = not listAllMatches
+        return newself
+
+    def setBreak(self,breakFlag = True):
+        """Method to invoke the Python pdb debugger when this element is
+           about to be parsed. Set C{breakFlag} to True to enable, False to
+           disable.
+        """
+        if breakFlag:
+            _parseMethod = self._parse
+            def breaker(instring, loc, doActions=True, callPreParse=True):
+                import pdb
+                pdb.set_trace()
+                return _parseMethod( instring, loc, doActions, callPreParse )
+            breaker._originalParseMethod = _parseMethod
+            self._parse = breaker
+        else:
+            if hasattr(self._parse,"_originalParseMethod"):
+                self._parse = self._parse._originalParseMethod
+        return self
+
+    def setParseAction( self, *fns, **kwargs ):
+        """Define action to perform when successfully matching parse element definition.
+           Parse action fn is a callable method with 0-3 arguments, called as C{fn(s,loc,toks)},
+           C{fn(loc,toks)}, C{fn(toks)}, or just C{fn()}, where:
+            - s   = the original string being parsed (see note below)
+            - loc = the location of the matching substring
+            - toks = a list of the matched tokens, packaged as a ParseResults object
+           If the functions in fns modify the tokens, they can return them as the return
+           value from fn, and the modified list of tokens will replace the original.
+           Otherwise, fn does not need to return any value.
+
+           Note: the default parsing behavior is to expand tabs in the input string
+           before starting the parsing process.  See L{I{parseString}<parseString>} for more information
+           on parsing strings containing <TAB>s, and suggested methods to maintain a
+           consistent view of the parsed string, the parse location, and line and column
+           positions within the parsed string.
+           """
+        self.parseAction = list(map(_trim_arity, list(fns)))
+        self.callDuringTry = ("callDuringTry" in kwargs and kwargs["callDuringTry"])
+        return self
+
+    def addParseAction( self, *fns, **kwargs ):
+        """Add parse action to expression's list of parse actions. See L{I{setParseAction}<setParseAction>}."""
+        self.parseAction += list(map(_trim_arity, list(fns)))
+        self.callDuringTry = self.callDuringTry or ("callDuringTry" in kwargs and kwargs["callDuringTry"])
+        return self
+
+    def setFailAction( self, fn ):
+        """Define action to perform if parsing fails at this expression.
+           Fail acton fn is a callable function that takes the arguments
+           C{fn(s,loc,expr,err)} where:
+            - s = string being parsed
+            - loc = location where expression match was attempted and failed
+            - expr = the parse expression that failed
+            - err = the exception thrown
+           The function returns no value.  It may throw C{ParseFatalException}
+           if it is desired to stop parsing immediately."""
+        self.failAction = fn
+        return self
+
+    def _skipIgnorables( self, instring, loc ):
+        exprsFound = True
+        while exprsFound:
+            exprsFound = False
+            for e in self.ignoreExprs:
+                try:
+                    while 1:
+                        loc,dummy = e._parse( instring, loc )
+                        exprsFound = True
+                except ParseException:
+                    pass
+        return loc
+
+    def preParse( self, instring, loc ):
+        if self.ignoreExprs:
+            loc = self._skipIgnorables( instring, loc )
+
+        if self.skipWhitespace:
+            wt = self.whiteChars
+            instrlen = len(instring)
+            while loc < instrlen and instring[loc] in wt:
+                loc += 1
+
+        return loc
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        return loc, []
+
+    def postParse( self, instring, loc, tokenlist ):
+        return tokenlist
+
+    #~ @profile
+    def _parseNoCache( self, instring, loc, doActions=True, callPreParse=True ):
+        debugging = ( self.debug ) #and doActions )
+
+        if debugging or self.failAction:
+            #~ print ("Match",self,"at loc",loc,"(%d,%d)" % ( lineno(loc,instring), col(loc,instring) ))
+            if (self.debugActions[0] ):
+                self.debugActions[0]( instring, loc, self )
+            if callPreParse and self.callPreparse:
+                preloc = self.preParse( instring, loc )
+            else:
+                preloc = loc
+            tokensStart = preloc
+            try:
+                try:
+                    loc,tokens = self.parseImpl( instring, preloc, doActions )
+                except IndexError:
+                    raise ParseException( instring, len(instring), self.errmsg, self )
+            except ParseBaseException:
+                #~ print ("Exception raised:", err)
+                err = None
+                if self.debugActions[2]:
+                    err = sys.exc_info()[1]
+                    self.debugActions[2]( instring, tokensStart, self, err )
+                if self.failAction:
+                    if err is None:
+                        err = sys.exc_info()[1]
+                    self.failAction( instring, tokensStart, self, err )
+                raise
+        else:
+            if callPreParse and self.callPreparse:
+                preloc = self.preParse( instring, loc )
+            else:
+                preloc = loc
+            tokensStart = preloc
+            if self.mayIndexError or loc >= len(instring):
+                try:
+                    loc,tokens = self.parseImpl( instring, preloc, doActions )
+                except IndexError:
+                    raise ParseException( instring, len(instring), self.errmsg, self )
+            else:
+                loc,tokens = self.parseImpl( instring, preloc, doActions )
+
+        tokens = self.postParse( instring, loc, tokens )
+
+        retTokens = ParseResults( tokens, self.resultsName, asList=self.saveAsList, modal=self.modalResults )
+        if self.parseAction and (doActions or self.callDuringTry):
+            if debugging:
+                try:
+                    for fn in self.parseAction:
+                        tokens = fn( instring, tokensStart, retTokens )
+                        if tokens is not None:
+                            retTokens = ParseResults( tokens,
+                                                      self.resultsName,
+                                                      asList=self.saveAsList and isinstance(tokens,(ParseResults,list)),
+                                                      modal=self.modalResults )
+                except ParseBaseException:
+                    #~ print "Exception raised in user parse action:", err
+                    if (self.debugActions[2] ):
+                        err = sys.exc_info()[1]
+                        self.debugActions[2]( instring, tokensStart, self, err )
+                    raise
+            else:
+                for fn in self.parseAction:
+                    tokens = fn( instring, tokensStart, retTokens )
+                    if tokens is not None:
+                        retTokens = ParseResults( tokens,
+                                                  self.resultsName,
+                                                  asList=self.saveAsList and isinstance(tokens,(ParseResults,list)),
+                                                  modal=self.modalResults )
+
+        if debugging:
+            #~ print ("Matched",self,"->",retTokens.asList())
+            if (self.debugActions[1] ):
+                self.debugActions[1]( instring, tokensStart, loc, self, retTokens )
+
+        return loc, retTokens
+
+    def tryParse( self, instring, loc ):
+        try:
+            return self._parse( instring, loc, doActions=False )[0]
+        except ParseFatalException:
+            raise ParseException( instring, loc, self.errmsg, self)
+
+    # this method gets repeatedly called during backtracking with the same arguments -
+    # we can cache these arguments and save ourselves the trouble of re-parsing the contained expression
+    def _parseCache( self, instring, loc, doActions=True, callPreParse=True ):
+        lookup = (self,instring,loc,callPreParse,doActions)
+        if lookup in ParserElement._exprArgCache:
+            value = ParserElement._exprArgCache[ lookup ]
+            if isinstance(value, Exception):
+                raise value
+            return (value[0],value[1].copy())
+        else:
+            try:
+                value = self._parseNoCache( instring, loc, doActions, callPreParse )
+                ParserElement._exprArgCache[ lookup ] = (value[0],value[1].copy())
+                return value
+            except ParseBaseException:
+                pe = sys.exc_info()[1]
+                ParserElement._exprArgCache[ lookup ] = pe
+                raise
+
+    _parse = _parseNoCache
+
+    # argument cache for optimizing repeated calls when backtracking through recursive expressions
+    _exprArgCache = {}
+    def resetCache():
+        ParserElement._exprArgCache.clear()
+    resetCache = staticmethod(resetCache)
+
+    _packratEnabled = False
+    def enablePackrat():
+        """Enables "packrat" parsing, which adds memoizing to the parsing logic.
+           Repeated parse attempts at the same string location (which happens
+           often in many complex grammars) can immediately return a cached value,
+           instead of re-executing parsing/validating code.  Memoizing is done of
+           both valid results and parsing exceptions.
+
+           This speedup may break existing programs that use parse actions that
+           have side-effects.  For this reason, packrat parsing is disabled when
+           you first import pyparsing.  To activate the packrat feature, your
+           program must call the class method C{ParserElement.enablePackrat()}.  If
+           your program uses C{psyco} to "compile as you go", you must call
+           C{enablePackrat} before calling C{psyco.full()}.  If you do not do this,
+           Python will crash.  For best results, call C{enablePackrat()} immediately
+           after importing pyparsing.
+        """
+        if not ParserElement._packratEnabled:
+            ParserElement._packratEnabled = True
+            ParserElement._parse = ParserElement._parseCache
+    enablePackrat = staticmethod(enablePackrat)
+
+    def parseString( self, instring, parseAll=False ):
+        """Execute the parse expression with the given string.
+           This is the main interface to the client code, once the complete
+           expression has been built.
+
+           If you want the grammar to require that the entire input string be
+           successfully parsed, then set C{parseAll} to True (equivalent to ending
+           the grammar with C{StringEnd()}).
+
+           Note: C{parseString} implicitly calls C{expandtabs()} on the input string,
+           in order to report proper column numbers in parse actions.
+           If the input string contains tabs and
+           the grammar uses parse actions that use the C{loc} argument to index into the
+           string being parsed, you can ensure you have a consistent view of the input
+           string by:
+            - calling C{parseWithTabs} on your grammar before calling C{parseString}
+              (see L{I{parseWithTabs}<parseWithTabs>})
+            - define your parse action using the full C{(s,loc,toks)} signature, and
+              reference the input string using the parse action's C{s} argument
+            - explictly expand the tabs in your input string before calling
+              C{parseString}
+        """
+        ParserElement.resetCache()
+        if not self.streamlined:
+            self.streamline()
+            #~ self.saveAsList = True
+        for e in self.ignoreExprs:
+            e.streamline()
+        if not self.keepTabs:
+            instring = instring.expandtabs()
+        try:
+            loc, tokens = self._parse( instring, 0 )
+            if parseAll:
+                loc = self.preParse( instring, loc )
+                se = Empty() + StringEnd()
+                se._parse( instring, loc )
+        except ParseBaseException:
+            if ParserElement.verbose_stacktrace:
+                raise
+            else:
+                # catch and re-raise exception from here, clears out pyparsing internal stack trace
+                exc = sys.exc_info()[1]
+                raise exc
+        else:
+            return tokens
+
+    def scanString( self, instring, maxMatches=_MAX_INT, overlap=False ):
+        """Scan the input string for expression matches.  Each match will return the
+           matching tokens, start location, and end location.  May be called with optional
+           C{maxMatches} argument, to clip scanning after 'n' matches are found.  If
+           C{overlap} is specified, then overlapping matches will be reported.
+
+           Note that the start and end locations are reported relative to the string
+           being parsed.  See L{I{parseString}<parseString>} for more information on parsing
+           strings with embedded tabs."""
+        if not self.streamlined:
+            self.streamline()
+        for e in self.ignoreExprs:
+            e.streamline()
+
+        if not self.keepTabs:
+            instring = _ustr(instring).expandtabs()
+        instrlen = len(instring)
+        loc = 0
+        preparseFn = self.preParse
+        parseFn = self._parse
+        ParserElement.resetCache()
+        matches = 0
+        try:
+            while loc <= instrlen and matches < maxMatches:
+                try:
+                    preloc = preparseFn( instring, loc )
+                    nextLoc,tokens = parseFn( instring, preloc, callPreParse=False )
+                except ParseException:
+                    loc = preloc+1
+                else:
+                    if nextLoc > loc:
+                        matches += 1
+                        yield tokens, preloc, nextLoc
+                        if overlap:
+                            nextloc = preparseFn( instring, loc )
+                            if nextloc > loc:
+                                loc = nextLoc
+                            else:
+                                loc += 1
+                        else:
+                            loc = nextLoc
+                    else:
+                        loc = preloc+1
+        except ParseBaseException:
+            if ParserElement.verbose_stacktrace:
+                raise
+            else:
+                # catch and re-raise exception from here, clears out pyparsing internal stack trace
+                exc = sys.exc_info()[1]
+                raise exc
+
+    def transformString( self, instring ):
+        """Extension to C{scanString}, to modify matching text with modified tokens that may
+           be returned from a parse action.  To use C{transformString}, define a grammar and
+           attach a parse action to it that modifies the returned token list.
+           Invoking C{transformString()} on a target string will then scan for matches,
+           and replace the matched text patterns according to the logic in the parse
+           action.  C{transformString()} returns the resulting transformed string."""
+        out = []
+        lastE = 0
+        # force preservation of <TAB>s, to minimize unwanted transformation of string, and to
+        # keep string locs straight between transformString and scanString
+        self.keepTabs = True
+        try:
+            for t,s,e in self.scanString( instring ):
+                out.append( instring[lastE:s] )
+                if t:
+                    if isinstance(t,ParseResults):
+                        out += t.asList()
+                    elif isinstance(t,list):
+                        out += t
+                    else:
+                        out.append(t)
+                lastE = e
+            out.append(instring[lastE:])
+            out = [o for o in out if o]
+            return "".join(map(_ustr,_flatten(out)))
+        except ParseBaseException:
+            if ParserElement.verbose_stacktrace:
+                raise
+            else:
+                # catch and re-raise exception from here, clears out pyparsing internal stack trace
+                exc = sys.exc_info()[1]
+                raise exc
+
+    def searchString( self, instring, maxMatches=_MAX_INT ):
+        """Another extension to C{scanString}, simplifying the access to the tokens found
+           to match the given parse expression.  May be called with optional
+           C{maxMatches} argument, to clip searching after 'n' matches are found.
+        """
+        try:
+            return ParseResults([ t for t,s,e in self.scanString( instring, maxMatches ) ])
+        except ParseBaseException:
+            if ParserElement.verbose_stacktrace:
+                raise
+            else:
+                # catch and re-raise exception from here, clears out pyparsing internal stack trace
+                exc = sys.exc_info()[1]
+                raise exc
+
+    def __add__(self, other ):
+        """Implementation of + operator - returns And"""
+        if isinstance( other, basestring ):
+            other = Literal( other )
+        if not isinstance( other, ParserElement ):
+            warnings.warn("Cannot combine element of type %s with ParserElement" % type(other),
+                    SyntaxWarning, stacklevel=2)
+            return None
+        return And( [ self, other ] )
+
+    def __radd__(self, other ):
+        """Implementation of + operator when left operand is not a C{ParserElement}"""
+        if isinstance( other, basestring ):
+            other = Literal( other )
+        if not isinstance( other, ParserElement ):
+            warnings.warn("Cannot combine element of type %s with ParserElement" % type(other),
+                    SyntaxWarning, stacklevel=2)
+            return None
+        return other + self
+
+    def __sub__(self, other):
+        """Implementation of - operator, returns C{And} with error stop"""
+        if isinstance( other, basestring ):
+            other = Literal( other )
+        if not isinstance( other, ParserElement ):
+            warnings.warn("Cannot combine element of type %s with ParserElement" % type(other),
+                    SyntaxWarning, stacklevel=2)
+            return None
+        return And( [ self, And._ErrorStop(), other ] )
+
+    def __rsub__(self, other ):
+        """Implementation of - operator when left operand is not a C{ParserElement}"""
+        if isinstance( other, basestring ):
+            other = Literal( other )
+        if not isinstance( other, ParserElement ):
+            warnings.warn("Cannot combine element of type %s with ParserElement" % type(other),
+                    SyntaxWarning, stacklevel=2)
+            return None
+        return other - self
+
+    def __mul__(self,other):
+        """Implementation of * operator, allows use of C{expr * 3} in place of
+           C{expr + expr + expr}.  Expressions may also me multiplied by a 2-integer
+           tuple, similar to C{{min,max}} multipliers in regular expressions.  Tuples
+           may also include C{None} as in:
+            - C{expr*(n,None)} or C{expr*(n,)} is equivalent
+              to C{expr*n + ZeroOrMore(expr)}
+              (read as "at least n instances of C{expr}")
+            - C{expr*(None,n)} is equivalent to C{expr*(0,n)}
+              (read as "0 to n instances of C{expr}")
+            - C{expr*(None,None)} is equivalent to C{ZeroOrMore(expr)}
+            - C{expr*(1,None)} is equivalent to C{OneOrMore(expr)}
+
+           Note that C{expr*(None,n)} does not raise an exception if
+           more than n exprs exist in the input stream; that is,
+           C{expr*(None,n)} does not enforce a maximum number of expr
+           occurrences.  If this behavior is desired, then write
+           C{expr*(None,n) + ~expr}
+
+        """
+        if isinstance(other,int):
+            minElements, optElements = other,0
+        elif isinstance(other,tuple):
+            other = (other + (None, None))[:2]
+            if other[0] is None:
+                other = (0, other[1])
+            if isinstance(other[0],int) and other[1] is None:
+                if other[0] == 0:
+                    return ZeroOrMore(self)
+                if other[0] == 1:
+                    return OneOrMore(self)
+                else:
+                    return self*other[0] + ZeroOrMore(self)
+            elif isinstance(other[0],int) and isinstance(other[1],int):
+                minElements, optElements = other
+                optElements -= minElements
+            else:
+                raise TypeError("cannot multiply 'ParserElement' and ('%s','%s') objects", type(other[0]),type(other[1]))
+        else:
+            raise TypeError("cannot multiply 'ParserElement' and '%s' objects", type(other))
+
+        if minElements < 0:
+            raise ValueError("cannot multiply ParserElement by negative value")
+        if optElements < 0:
+            raise ValueError("second tuple value must be greater or equal to first tuple value")
+        if minElements == optElements == 0:
+            raise ValueError("cannot multiply ParserElement by 0 or (0,0)")
+
+        if (optElements):
+            def makeOptionalList(n):
+                if n>1:
+                    return Optional(self + makeOptionalList(n-1))
+                else:
+                    return Optional(self)
+            if minElements:
+                if minElements == 1:
+                    ret = self + makeOptionalList(optElements)
+                else:
+                    ret = And([self]*minElements) + makeOptionalList(optElements)
+            else:
+                ret = makeOptionalList(optElements)
+        else:
+            if minElements == 1:
+                ret = self
+            else:
+                ret = And([self]*minElements)
+        return ret
+
+    def __rmul__(self, other):
+        return self.__mul__(other)
+
+    def __or__(self, other ):
+        """Implementation of | operator - returns C{MatchFirst}"""
+        if isinstance( other, basestring ):
+            other = Literal( other )
+        if not isinstance( other, ParserElement ):
+            warnings.warn("Cannot combine element of type %s with ParserElement" % type(other),
+                    SyntaxWarning, stacklevel=2)
+            return None
+        return MatchFirst( [ self, other ] )
+
+    def __ror__(self, other ):
+        """Implementation of | operator when left operand is not a C{ParserElement}"""
+        if isinstance( other, basestring ):
+            other = Literal( other )
+        if not isinstance( other, ParserElement ):
+            warnings.warn("Cannot combine element of type %s with ParserElement" % type(other),
+                    SyntaxWarning, stacklevel=2)
+            return None
+        return other | self
+
+    def __xor__(self, other ):
+        """Implementation of ^ operator - returns C{Or}"""
+        if isinstance( other, basestring ):
+            other = Literal( other )
+        if not isinstance( other, ParserElement ):
+            warnings.warn("Cannot combine element of type %s with ParserElement" % type(other),
+                    SyntaxWarning, stacklevel=2)
+            return None
+        return Or( [ self, other ] )
+
+    def __rxor__(self, other ):
+        """Implementation of ^ operator when left operand is not a C{ParserElement}"""
+        if isinstance( other, basestring ):
+            other = Literal( other )
+        if not isinstance( other, ParserElement ):
+            warnings.warn("Cannot combine element of type %s with ParserElement" % type(other),
+                    SyntaxWarning, stacklevel=2)
+            return None
+        return other ^ self
+
+    def __and__(self, other ):
+        """Implementation of & operator - returns C{Each}"""
+        if isinstance( other, basestring ):
+            other = Literal( other )
+        if not isinstance( other, ParserElement ):
+            warnings.warn("Cannot combine element of type %s with ParserElement" % type(other),
+                    SyntaxWarning, stacklevel=2)
+            return None
+        return Each( [ self, other ] )
+
+    def __rand__(self, other ):
+        """Implementation of & operator when left operand is not a C{ParserElement}"""
+        if isinstance( other, basestring ):
+            other = Literal( other )
+        if not isinstance( other, ParserElement ):
+            warnings.warn("Cannot combine element of type %s with ParserElement" % type(other),
+                    SyntaxWarning, stacklevel=2)
+            return None
+        return other & self
+
+    def __invert__( self ):
+        """Implementation of ~ operator - returns C{NotAny}"""
+        return NotAny( self )
+
+    def __call__(self, name):
+        """Shortcut for C{setResultsName}, with C{listAllMatches=default}::
+             userdata = Word(alphas).setResultsName("name") + Word(nums+"-").setResultsName("socsecno")
+           could be written as::
+             userdata = Word(alphas)("name") + Word(nums+"-")("socsecno")
+
+           If C{name} is given with a trailing C{'*'} character, then C{listAllMatches} will be
+           passed as C{True}.
+           """
+        return self.setResultsName(name)
+
+    def suppress( self ):
+        """Suppresses the output of this C{ParserElement}; useful to keep punctuation from
+           cluttering up returned output.
+        """
+        return Suppress( self )
+
+    def leaveWhitespace( self ):
+        """Disables the skipping of whitespace before matching the characters in the
+           C{ParserElement}'s defined pattern.  This is normally only used internally by
+           the pyparsing module, but may be needed in some whitespace-sensitive grammars.
+        """
+        self.skipWhitespace = False
+        return self
+
+    def setWhitespaceChars( self, chars ):
+        """Overrides the default whitespace chars
+        """
+        self.skipWhitespace = True
+        self.whiteChars = chars
+        self.copyDefaultWhiteChars = False
+        return self
+
+    def parseWithTabs( self ):
+        """Overrides default behavior to expand C{<TAB>}s to spaces before parsing the input string.
+           Must be called before C{parseString} when the input grammar contains elements that
+           match C{<TAB>} characters."""
+        self.keepTabs = True
+        return self
+
+    def ignore( self, other ):
+        """Define expression to be ignored (e.g., comments) while doing pattern
+           matching; may be called repeatedly, to define multiple comment or other
+           ignorable patterns.
+        """
+        if isinstance( other, Suppress ):
+            if other not in self.ignoreExprs:
+                self.ignoreExprs.append( other.copy() )
+        else:
+            self.ignoreExprs.append( Suppress( other.copy() ) )
+        return self
+
+    def setDebugActions( self, startAction, successAction, exceptionAction ):
+        """Enable display of debugging messages while doing pattern matching."""
+        self.debugActions = (startAction or _defaultStartDebugAction,
+                             successAction or _defaultSuccessDebugAction,
+                             exceptionAction or _defaultExceptionDebugAction)
+        self.debug = True
+        return self
+
+    def setDebug( self, flag=True ):
+        """Enable display of debugging messages while doing pattern matching.
+           Set C{flag} to True to enable, False to disable."""
+        if flag:
+            self.setDebugActions( _defaultStartDebugAction, _defaultSuccessDebugAction, _defaultExceptionDebugAction )
+        else:
+            self.debug = False
+        return self
+
+    def __str__( self ):
+        return self.name
+
+    def __repr__( self ):
+        return _ustr(self)
+
+    def streamline( self ):
+        self.streamlined = True
+        self.strRepr = None
+        return self
+
+    def checkRecursion( self, parseElementList ):
+        pass
+
+    def validate( self, validateTrace=[] ):
+        """Check defined expressions for valid structure, check for infinite recursive definitions."""
+        self.checkRecursion( [] )
+
+    def parseFile( self, file_or_filename, parseAll=False ):
+        """Execute the parse expression on the given file or filename.
+           If a filename is specified (instead of a file object),
+           the entire file is opened, read, and closed before parsing.
+        """
+        try:
+            file_contents = file_or_filename.read()
+        except AttributeError:
+            f = open(file_or_filename, "rb")
+            file_contents = f.read()
+            f.close()
+        try:
+            return self.parseString(file_contents, parseAll)
+        except ParseBaseException:
+            # catch and re-raise exception from here, clears out pyparsing internal stack trace
+            exc = sys.exc_info()[1]
+            raise exc
+
+    def getException(self):
+        return ParseException("",0,self.errmsg,self)
+
+    def __getattr__(self,aname):
+        if aname == "myException":
+            self.myException = ret = self.getException();
+            return ret;
+        else:
+            raise AttributeError("no such attribute " + aname)
+
+    def __eq__(self,other):
+        if isinstance(other, ParserElement):
+            return self is other or self.__dict__ == other.__dict__
+        elif isinstance(other, basestring):
+            try:
+                self.parseString(_ustr(other), parseAll=True)
+                return True
+            except ParseBaseException:
+                return False
+        else:
+            return super(ParserElement,self)==other
+
+    def __ne__(self,other):
+        return not (self == other)
+
+    def __hash__(self):
+        return hash(id(self))
+
+    def __req__(self,other):
+        return self == other
+
+    def __rne__(self,other):
+        return not (self == other)
+
+
+class Token(ParserElement):
+    """Abstract C{ParserElement} subclass, for defining atomic matching patterns."""
+    def __init__( self ):
+        super(Token,self).__init__( savelist=False )
+
+    def setName(self, name):
+        s = super(Token,self).setName(name)
+        self.errmsg = "Expected " + self.name
+        return s
+
+
+class Empty(Token):
+    """An empty token, will always match."""
+    def __init__( self ):
+        super(Empty,self).__init__()
+        self.name = "Empty"
+        self.mayReturnEmpty = True
+        self.mayIndexError = False
+
+
+class NoMatch(Token):
+    """A token that will never match."""
+    def __init__( self ):
+        super(NoMatch,self).__init__()
+        self.name = "NoMatch"
+        self.mayReturnEmpty = True
+        self.mayIndexError = False
+        self.errmsg = "Unmatchable token"
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        exc = self.myException
+        exc.loc = loc
+        exc.pstr = instring
+        raise exc
+
+
+class Literal(Token):
+    """Token to exactly match a specified string."""
+    def __init__( self, matchString ):
+        super(Literal,self).__init__()
+        self.match = matchString
+        self.matchLen = len(matchString)
+        try:
+            self.firstMatchChar = matchString[0]
+        except IndexError:
+            warnings.warn("null string passed to Literal; use Empty() instead",
+                            SyntaxWarning, stacklevel=2)
+            self.__class__ = Empty
+        self.name = '"%s"' % _ustr(self.match)
+        self.errmsg = "Expected " + self.name
+        self.mayReturnEmpty = False
+        self.mayIndexError = False
+
+    # Performance tuning: this routine gets called a *lot*
+    # if this is a single character match string  and the first character matches,
+    # short-circuit as quickly as possible, and avoid calling startswith
+    #~ @profile
+    def parseImpl( self, instring, loc, doActions=True ):
+        if (instring[loc] == self.firstMatchChar and
+            (self.matchLen==1 or instring.startswith(self.match,loc)) ):
+            return loc+self.matchLen, self.match
+        #~ raise ParseException( instring, loc, self.errmsg )
+        exc = self.myException
+        exc.loc = loc
+        exc.pstr = instring
+        raise exc
+_L = Literal
+
+class Keyword(Token):
+    """Token to exactly match a specified string as a keyword, that is, it must be
+       immediately followed by a non-keyword character.  Compare with C{Literal}::
+         Literal("if") will match the leading C{'if'} in C{'ifAndOnlyIf'}.
+         Keyword("if") will not; it will only match the leading C{'if'} in C{'if x=1'}, or C{'if(y==2)'}
+       Accepts two optional constructor arguments in addition to the keyword string:
+       C{identChars} is a string of characters that would be valid identifier characters,
+       defaulting to all alphanumerics + "_" and "$"; C{caseless} allows case-insensitive
+       matching, default is C{False}.
+    """
+    DEFAULT_KEYWORD_CHARS = alphanums+"_$"
+
+    def __init__( self, matchString, identChars=DEFAULT_KEYWORD_CHARS, caseless=False ):
+        super(Keyword,self).__init__()
+        self.match = matchString
+        self.matchLen = len(matchString)
+        try:
+            self.firstMatchChar = matchString[0]
+        except IndexError:
+            warnings.warn("null string passed to Keyword; use Empty() instead",
+                            SyntaxWarning, stacklevel=2)
+        self.name = '"%s"' % self.match
+        self.errmsg = "Expected " + self.name
+        self.mayReturnEmpty = False
+        self.mayIndexError = False
+        self.caseless = caseless
+        if caseless:
+            self.caselessmatch = matchString.upper()
+            identChars = identChars.upper()
+        self.identChars = set(identChars)
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        if self.caseless:
+            if ( (instring[ loc:loc+self.matchLen ].upper() == self.caselessmatch) and
+                 (loc >= len(instring)-self.matchLen or instring[loc+self.matchLen].upper() not in self.identChars) and
+                 (loc == 0 or instring[loc-1].upper() not in self.identChars) ):
+                return loc+self.matchLen, self.match
+        else:
+            if (instring[loc] == self.firstMatchChar and
+                (self.matchLen==1 or instring.startswith(self.match,loc)) and
+                (loc >= len(instring)-self.matchLen or instring[loc+self.matchLen] not in self.identChars) and
+                (loc == 0 or instring[loc-1] not in self.identChars) ):
+                return loc+self.matchLen, self.match
+        #~ raise ParseException( instring, loc, self.errmsg )
+        exc = self.myException
+        exc.loc = loc
+        exc.pstr = instring
+        raise exc
+
+    def copy(self):
+        c = super(Keyword,self).copy()
+        c.identChars = Keyword.DEFAULT_KEYWORD_CHARS
+        return c
+
+    def setDefaultKeywordChars( chars ):
+        """Overrides the default Keyword chars
+        """
+        Keyword.DEFAULT_KEYWORD_CHARS = chars
+    setDefaultKeywordChars = staticmethod(setDefaultKeywordChars)
+
+class CaselessLiteral(Literal):
+    """Token to match a specified string, ignoring case of letters.
+       Note: the matched results will always be in the case of the given
+       match string, NOT the case of the input text.
+    """
+    def __init__( self, matchString ):
+        super(CaselessLiteral,self).__init__( matchString.upper() )
+        # Preserve the defining literal.
+        self.returnString = matchString
+        self.name = "'%s'" % self.returnString
+        self.errmsg = "Expected " + self.name
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        if instring[ loc:loc+self.matchLen ].upper() == self.match:
+            return loc+self.matchLen, self.returnString
+        #~ raise ParseException( instring, loc, self.errmsg )
+        exc = self.myException
+        exc.loc = loc
+        exc.pstr = instring
+        raise exc
+
+class CaselessKeyword(Keyword):
+    def __init__( self, matchString, identChars=Keyword.DEFAULT_KEYWORD_CHARS ):
+        super(CaselessKeyword,self).__init__( matchString, identChars, caseless=True )
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        if ( (instring[ loc:loc+self.matchLen ].upper() == self.caselessmatch) and
+             (loc >= len(instring)-self.matchLen or instring[loc+self.matchLen].upper() not in self.identChars) ):
+            return loc+self.matchLen, self.match
+        #~ raise ParseException( instring, loc, self.errmsg )
+        exc = self.myException
+        exc.loc = loc
+        exc.pstr = instring
+        raise exc
+
+class Word(Token):
+    """Token for matching words composed of allowed character sets.
+       Defined with string containing all allowed initial characters,
+       an optional string containing allowed body characters (if omitted,
+       defaults to the initial character set), and an optional minimum,
+       maximum, and/or exact length.  The default value for C{min} is 1 (a
+       minimum value < 1 is not valid); the default values for C{max} and C{exact}
+       are 0, meaning no maximum or exact length restriction. An optional
+       C{exclude} parameter can list characters that might be found in
+       the input C{bodyChars} string; useful to define a word of all printables
+       except for one or two characters, for instance.
+    """
+    def __init__( self, initChars, bodyChars=None, min=1, max=0, exact=0, asKeyword=False, excludeChars=None ):
+        super(Word,self).__init__()
+        if excludeChars:
+            initChars = ''.join([c for c in initChars if c not in excludeChars])
+            if bodyChars:
+                bodyChars = ''.join([c for c in bodyChars if c not in excludeChars])
+        self.initCharsOrig = initChars
+        self.initChars = set(initChars)
+        if bodyChars :
+            self.bodyCharsOrig = bodyChars
+            self.bodyChars = set(bodyChars)
+        else:
+            self.bodyCharsOrig = initChars
+            self.bodyChars = set(initChars)
+
+        self.maxSpecified = max > 0
+
+        if min < 1:
+            raise ValueError("cannot specify a minimum length < 1; use Optional(Word()) if zero-length word is permitted")
+
+        self.minLen = min
+
+        if max > 0:
+            self.maxLen = max
+        else:
+            self.maxLen = _MAX_INT
+
+        if exact > 0:
+            self.maxLen = exact
+            self.minLen = exact
+
+        self.name = _ustr(self)
+        self.errmsg = "Expected " + self.name
+        self.mayIndexError = False
+        self.asKeyword = asKeyword
+
+        if ' ' not in self.initCharsOrig+self.bodyCharsOrig and (min==1 and max==0 and exact==0):
+            if self.bodyCharsOrig == self.initCharsOrig:
+                self.reString = "[%s]+" % _escapeRegexRangeChars(self.initCharsOrig)
+            elif len(self.bodyCharsOrig) == 1:
+                self.reString = "%s[%s]*" % \
+                                      (re.escape(self.initCharsOrig),
+                                      _escapeRegexRangeChars(self.bodyCharsOrig),)
+            else:
+                self.reString = "[%s][%s]*" % \
+                                      (_escapeRegexRangeChars(self.initCharsOrig),
+                                      _escapeRegexRangeChars(self.bodyCharsOrig),)
+            if self.asKeyword:
+                self.reString = r"\b"+self.reString+r"\b"
+            try:
+                self.re = re.compile( self.reString )
+            except:
+                self.re = None
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        if self.re:
+            result = self.re.match(instring,loc)
+            if not result:
+                exc = self.myException
+                exc.loc = loc
+                exc.pstr = instring
+                raise exc
+
+            loc = result.end()
+            return loc, result.group()
+
+        if not(instring[ loc ] in self.initChars):
+            #~ raise ParseException( instring, loc, self.errmsg )
+            exc = self.myException
+            exc.loc = loc
+            exc.pstr = instring
+            raise exc
+        start = loc
+        loc += 1
+        instrlen = len(instring)
+        bodychars = self.bodyChars
+        maxloc = start + self.maxLen
+        maxloc = min( maxloc, instrlen )
+        while loc < maxloc and instring[loc] in bodychars:
+            loc += 1
+
+        throwException = False
+        if loc - start < self.minLen:
+            throwException = True
+        if self.maxSpecified and loc < instrlen and instring[loc] in bodychars:
+            throwException = True
+        if self.asKeyword:
+            if (start>0 and instring[start-1] in bodychars) or (loc<instrlen and instring[loc] in bodychars):
+                throwException = True
+
+        if throwException:
+            #~ raise ParseException( instring, loc, self.errmsg )
+            exc = self.myException
+            exc.loc = loc
+            exc.pstr = instring
+            raise exc
+
+        return loc, instring[start:loc]
+
+    def __str__( self ):
+        try:
+            return super(Word,self).__str__()
+        except:
+            pass
+
+
+        if self.strRepr is None:
+
+            def charsAsStr(s):
+                if len(s)>4:
+                    return s[:4]+"..."
+                else:
+                    return s
+
+            if ( self.initCharsOrig != self.bodyCharsOrig ):
+                self.strRepr = "W:(%s,%s)" % ( charsAsStr(self.initCharsOrig), charsAsStr(self.bodyCharsOrig) )
+            else:
+                self.strRepr = "W:(%s)" % charsAsStr(self.initCharsOrig)
+
+        return self.strRepr
+
+
+class Regex(Token):
+    """Token for matching strings that match a given regular expression.
+       Defined with string specifying the regular expression in a form recognized by the inbuilt Python re module.
+    """
+    compiledREtype = type(re.compile("[A-Z]"))
+    def __init__( self, pattern, flags=0):
+        """The parameters C{pattern} and C{flags} are passed to the C{re.compile()} function as-is. See the Python C{re} module for an explanation of the acceptable patterns and flags."""
+        super(Regex,self).__init__()
+
+        if isinstance(pattern, basestring):
+            if len(pattern) == 0:
+                warnings.warn("null string passed to Regex; use Empty() instead",
+                        SyntaxWarning, stacklevel=2)
+
+            self.pattern = pattern
+            self.flags = flags
+
+            try:
+                self.re = re.compile(self.pattern, self.flags)
+                self.reString = self.pattern
+            except sre_constants.error:
+                warnings.warn("invalid pattern (%s) passed to Regex" % pattern,
+                    SyntaxWarning, stacklevel=2)
+                raise
+
+        elif isinstance(pattern, Regex.compiledREtype):
+            self.re = pattern
+            self.pattern = \
+            self.reString = str(pattern)
+            self.flags = flags
+
+        else:
+            raise ValueError("Regex may only be constructed with a string or a compiled RE object")
+
+        self.name = _ustr(self)
+        self.errmsg = "Expected " + self.name
+        self.mayIndexError = False
+        self.mayReturnEmpty = True
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        result = self.re.match(instring,loc)
+        if not result:
+            exc = self.myException
+            exc.loc = loc
+            exc.pstr = instring
+            raise exc
+
+        loc = result.end()
+        d = result.groupdict()
+        ret = ParseResults(result.group())
+        if d:
+            for k in d:
+                ret[k] = d[k]
+        return loc,ret
+
+    def __str__( self ):
+        try:
+            return super(Regex,self).__str__()
+        except:
+            pass
+
+        if self.strRepr is None:
+            self.strRepr = "Re:(%s)" % repr(self.pattern)
+
+        return self.strRepr
+
+
+class QuotedString(Token):
+    """Token for matching strings that are delimited by quoting characters.
+    """
+    def __init__( self, quoteChar, escChar=None, escQuote=None, multiline=False, unquoteResults=True, endQuoteChar=None):
+        """
+           Defined with the following parameters:
+            - quoteChar - string of one or more characters defining the quote delimiting string
+            - escChar - character to escape quotes, typically backslash (default=None)
+            - escQuote - special quote sequence to escape an embedded quote string (such as SQL's "" to escape an embedded ") (default=None)
+            - multiline - boolean indicating whether quotes can span multiple lines (default=False)
+            - unquoteResults - boolean indicating whether the matched text should be unquoted (default=True)
+            - endQuoteChar - string of one or more characters defining the end of the quote delimited string (default=None => same as quoteChar)
+        """
+        super(QuotedString,self).__init__()
+
+        # remove white space from quote chars - wont work anyway
+        quoteChar = quoteChar.strip()
+        if len(quoteChar) == 0:
+            warnings.warn("quoteChar cannot be the empty string",SyntaxWarning,stacklevel=2)
+            raise SyntaxError()
+
+        if endQuoteChar is None:
+            endQuoteChar = quoteChar
+        else:
+            endQuoteChar = endQuoteChar.strip()
+            if len(endQuoteChar) == 0:
+                warnings.warn("endQuoteChar cannot be the empty string",SyntaxWarning,stacklevel=2)
+                raise SyntaxError()
+
+        self.quoteChar = quoteChar
+        self.quoteCharLen = len(quoteChar)
+        self.firstQuoteChar = quoteChar[0]
+        self.endQuoteChar = endQuoteChar
+        self.endQuoteCharLen = len(endQuoteChar)
+        self.escChar = escChar
+        self.escQuote = escQuote
+        self.unquoteResults = unquoteResults
+
+        if multiline:
+            self.flags = re.MULTILINE | re.DOTALL
+            self.pattern = r'%s(?:[^%s%s]' % \
+                ( re.escape(self.quoteChar),
+                  _escapeRegexRangeChars(self.endQuoteChar[0]),
+                  (escChar is not None and _escapeRegexRangeChars(escChar) or '') )
+        else:
+            self.flags = 0
+            self.pattern = r'%s(?:[^%s\n\r%s]' % \
+                ( re.escape(self.quoteChar),
+                  _escapeRegexRangeChars(self.endQuoteChar[0]),
+                  (escChar is not None and _escapeRegexRangeChars(escChar) or '') )
+        if len(self.endQuoteChar) > 1:
+            self.pattern += (
+                '|(?:' + ')|(?:'.join(["%s[^%s]" % (re.escape(self.endQuoteChar[:i]),
+                                               _escapeRegexRangeChars(self.endQuoteChar[i]))
+                                    for i in range(len(self.endQuoteChar)-1,0,-1)]) + ')'
+                )
+        if escQuote:
+            self.pattern += (r'|(?:%s)' % re.escape(escQuote))
+        if escChar:
+            self.pattern += (r'|(?:%s.)' % re.escape(escChar))
+            charset = ''.join(set(self.quoteChar[0]+self.endQuoteChar[0])).replace('^',r'\^').replace('-',r'\-')
+            self.escCharReplacePattern = re.escape(self.escChar)+("([%s])" % charset)
+        self.pattern += (r')*%s' % re.escape(self.endQuoteChar))
+
+        try:
+            self.re = re.compile(self.pattern, self.flags)
+            self.reString = self.pattern
+        except sre_constants.error:
+            warnings.warn("invalid pattern (%s) passed to Regex" % self.pattern,
+                SyntaxWarning, stacklevel=2)
+            raise
+
+        self.name = _ustr(self)
+        self.errmsg = "Expected " + self.name
+        self.mayIndexError = False
+        self.mayReturnEmpty = True
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        result = instring[loc] == self.firstQuoteChar and self.re.match(instring,loc) or None
+        if not result:
+            exc = self.myException
+            exc.loc = loc
+            exc.pstr = instring
+            raise exc
+
+        loc = result.end()
+        ret = result.group()
+
+        if self.unquoteResults:
+
+            # strip off quotes
+            ret = ret[self.quoteCharLen:-self.endQuoteCharLen]
+
+            if isinstance(ret,basestring):
+                # replace escaped characters
+                if self.escChar:
+                    ret = re.sub(self.escCharReplacePattern,"\g<1>",ret)
+
+                # replace escaped quotes
+                if self.escQuote:
+                    ret = ret.replace(self.escQuote, self.endQuoteChar)
+
+        return loc, ret
+
+    def __str__( self ):
+        try:
+            return super(QuotedString,self).__str__()
+        except:
+            pass
+
+        if self.strRepr is None:
+            self.strRepr = "quoted string, starting with %s ending with %s" % (self.quoteChar, self.endQuoteChar)
+
+        return self.strRepr
+
+
+class CharsNotIn(Token):
+    """Token for matching words composed of characters *not* in a given set.
+       Defined with string containing all disallowed characters, and an optional
+       minimum, maximum, and/or exact length.  The default value for C{min} is 1 (a
+       minimum value < 1 is not valid); the default values for C{max} and C{exact}
+       are 0, meaning no maximum or exact length restriction.
+    """
+    def __init__( self, notChars, min=1, max=0, exact=0 ):
+        super(CharsNotIn,self).__init__()
+        self.skipWhitespace = False
+        self.notChars = notChars
+
+        if min < 1:
+            raise ValueError("cannot specify a minimum length < 1; use Optional(CharsNotIn()) if zero-length char group is permitted")
+
+        self.minLen = min
+
+        if max > 0:
+            self.maxLen = max
+        else:
+            self.maxLen = _MAX_INT
+
+        if exact > 0:
+            self.maxLen = exact
+            self.minLen = exact
+
+        self.name = _ustr(self)
+        self.errmsg = "Expected " + self.name
+        self.mayReturnEmpty = ( self.minLen == 0 )
+        self.mayIndexError = False
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        if instring[loc] in self.notChars:
+            #~ raise ParseException( instring, loc, self.errmsg )
+            exc = self.myException
+            exc.loc = loc
+            exc.pstr = instring
+            raise exc
+
+        start = loc
+        loc += 1
+        notchars = self.notChars
+        maxlen = min( start+self.maxLen, len(instring) )
+        while loc < maxlen and \
+              (instring[loc] not in notchars):
+            loc += 1
+
+        if loc - start < self.minLen:
+            #~ raise ParseException( instring, loc, self.errmsg )
+            exc = self.myException
+            exc.loc = loc
+            exc.pstr = instring
+            raise exc
+
+        return loc, instring[start:loc]
+
+    def __str__( self ):
+        try:
+            return super(CharsNotIn, self).__str__()
+        except:
+            pass
+
+        if self.strRepr is None:
+            if len(self.notChars) > 4:
+                self.strRepr = "!W:(%s...)" % self.notChars[:4]
+            else:
+                self.strRepr = "!W:(%s)" % self.notChars
+
+        return self.strRepr
+
+class White(Token):
+    """Special matching class for matching whitespace.  Normally, whitespace is ignored
+       by pyparsing grammars.  This class is included when some whitespace structures
+       are significant.  Define with a string containing the whitespace characters to be
+       matched; default is C{" \\t\\r\\n"}.  Also takes optional C{min}, C{max}, and C{exact} arguments,
+       as defined for the C{Word} class."""
+    whiteStrs = {
+        " " : "<SPC>",
+        "\t": "<TAB>",
+        "\n": "<LF>",
+        "\r": "<CR>",
+        "\f": "<FF>",
+        }
+    def __init__(self, ws=" \t\r\n", min=1, max=0, exact=0):
+        super(White,self).__init__()
+        self.matchWhite = ws
+        self.setWhitespaceChars( "".join([c for c in self.whiteChars if c not in self.matchWhite]) )
+        #~ self.leaveWhitespace()
+        self.name = ("".join([White.whiteStrs[c] for c in self.matchWhite]))
+        self.mayReturnEmpty = True
+        self.errmsg = "Expected " + self.name
+
+        self.minLen = min
+
+        if max > 0:
+            self.maxLen = max
+        else:
+            self.maxLen = _MAX_INT
+
+        if exact > 0:
+            self.maxLen = exact
+            self.minLen = exact
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        if not(instring[ loc ] in self.matchWhite):
+            #~ raise ParseException( instring, loc, self.errmsg )
+            exc = self.myException
+            exc.loc = loc
+            exc.pstr = instring
+            raise exc
+        start = loc
+        loc += 1
+        maxloc = start + self.maxLen
+        maxloc = min( maxloc, len(instring) )
+        while loc < maxloc and instring[loc] in self.matchWhite:
+            loc += 1
+
+        if loc - start < self.minLen:
+            #~ raise ParseException( instring, loc, self.errmsg )
+            exc = self.myException
+            exc.loc = loc
+            exc.pstr = instring
+            raise exc
+
+        return loc, instring[start:loc]
+
+
+class _PositionToken(Token):
+    def __init__( self ):
+        super(_PositionToken,self).__init__()
+        self.name=self.__class__.__name__
+        self.mayReturnEmpty = True
+        self.mayIndexError = False
+
+class GoToColumn(_PositionToken):
+    """Token to advance to a specific column of input text; useful for tabular report scraping."""
+    def __init__( self, colno ):
+        super(GoToColumn,self).__init__()
+        self.col = colno
+
+    def preParse( self, instring, loc ):
+        if col(loc,instring) != self.col:
+            instrlen = len(instring)
+            if self.ignoreExprs:
+                loc = self._skipIgnorables( instring, loc )
+            while loc < instrlen and instring[loc].isspace() and col( loc, instring ) != self.col :
+                loc += 1
+        return loc
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        thiscol = col( loc, instring )
+        if thiscol > self.col:
+            raise ParseException( instring, loc, "Text not in expected column", self )
+        newloc = loc + self.col - thiscol
+        ret = instring[ loc: newloc ]
+        return newloc, ret
+
+class LineStart(_PositionToken):
+    """Matches if current position is at the beginning of a line within the parse string"""
+    def __init__( self ):
+        super(LineStart,self).__init__()
+        self.setWhitespaceChars( ParserElement.DEFAULT_WHITE_CHARS.replace("\n","") )
+        self.errmsg = "Expected start of line"
+
+    def preParse( self, instring, loc ):
+        preloc = super(LineStart,self).preParse(instring,loc)
+        if instring[preloc] == "\n":
+            loc += 1
+        return loc
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        if not( loc==0 or
+            (loc == self.preParse( instring, 0 )) or
+            (instring[loc-1] == "\n") ): #col(loc, instring) != 1:
+            #~ raise ParseException( instring, loc, "Expected start of line" )
+            exc = self.myException
+            exc.loc = loc
+            exc.pstr = instring
+            raise exc
+        return loc, []
+
+class LineEnd(_PositionToken):
+    """Matches if current position is at the end of a line within the parse string"""
+    def __init__( self ):
+        super(LineEnd,self).__init__()
+        self.setWhitespaceChars( ParserElement.DEFAULT_WHITE_CHARS.replace("\n","") )
+        self.errmsg = "Expected end of line"
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        if loc<len(instring):
+            if instring[loc] == "\n":
+                return loc+1, "\n"
+            else:
+                #~ raise ParseException( instring, loc, "Expected end of line" )
+                exc = self.myException
+                exc.loc = loc
+                exc.pstr = instring
+                raise exc
+        elif loc == len(instring):
+            return loc+1, []
+        else:
+            exc = self.myException
+            exc.loc = loc
+            exc.pstr = instring
+            raise exc
+
+class StringStart(_PositionToken):
+    """Matches if current position is at the beginning of the parse string"""
+    def __init__( self ):
+        super(StringStart,self).__init__()
+        self.errmsg = "Expected start of text"
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        if loc != 0:
+            # see if entire string up to here is just whitespace and ignoreables
+            if loc != self.preParse( instring, 0 ):
+                #~ raise ParseException( instring, loc, "Expected start of text" )
+                exc = self.myException
+                exc.loc = loc
+                exc.pstr = instring
+                raise exc
+        return loc, []
+
+class StringEnd(_PositionToken):
+    """Matches if current position is at the end of the parse string"""
+    def __init__( self ):
+        super(StringEnd,self).__init__()
+        self.errmsg = "Expected end of text"
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        if loc < len(instring):
+            #~ raise ParseException( instring, loc, "Expected end of text" )
+            exc = self.myException
+            exc.loc = loc
+            exc.pstr = instring
+            raise exc
+        elif loc == len(instring):
+            return loc+1, []
+        elif loc > len(instring):
+            return loc, []
+        else:
+            exc = self.myException
+            exc.loc = loc
+            exc.pstr = instring
+            raise exc
+
+class WordStart(_PositionToken):
+    """Matches if the current position is at the beginning of a Word, and
+       is not preceded by any character in a given set of C{wordChars}
+       (default=C{printables}). To emulate the C{\b} behavior of regular expressions,
+       use C{WordStart(alphanums)}. C{WordStart} will also match at the beginning of
+       the string being parsed, or at the beginning of a line.
+    """
+    def __init__(self, wordChars = printables):
+        super(WordStart,self).__init__()
+        self.wordChars = set(wordChars)
+        self.errmsg = "Not at the start of a word"
+
+    def parseImpl(self, instring, loc, doActions=True ):
+        if loc != 0:
+            if (instring[loc-1] in self.wordChars or
+                instring[loc] not in self.wordChars):
+                exc = self.myException
+                exc.loc = loc
+                exc.pstr = instring
+                raise exc
+        return loc, []
+
+class WordEnd(_PositionToken):
+    """Matches if the current position is at the end of a Word, and
+       is not followed by any character in a given set of C{wordChars}
+       (default=C{printables}). To emulate the C{\b} behavior of regular expressions,
+       use C{WordEnd(alphanums)}. C{WordEnd} will also match at the end of
+       the string being parsed, or at the end of a line.
+    """
+    def __init__(self, wordChars = printables):
+        super(WordEnd,self).__init__()
+        self.wordChars = set(wordChars)
+        self.skipWhitespace = False
+        self.errmsg = "Not at the end of a word"
+
+    def parseImpl(self, instring, loc, doActions=True ):
+        instrlen = len(instring)
+        if instrlen>0 and loc<instrlen:
+            if (instring[loc] in self.wordChars or
+                instring[loc-1] not in self.wordChars):
+                #~ raise ParseException( instring, loc, "Expected end of word" )
+                exc = self.myException
+                exc.loc = loc
+                exc.pstr = instring
+                raise exc
+        return loc, []
+
+
+class ParseExpression(ParserElement):
+    """Abstract subclass of ParserElement, for combining and post-processing parsed tokens."""
+    def __init__( self, exprs, savelist = False ):
+        super(ParseExpression,self).__init__(savelist)
+        if isinstance( exprs, list ):
+            self.exprs = exprs
+        elif isinstance( exprs, basestring ):
+            self.exprs = [ Literal( exprs ) ]
+        else:
+            try:
+                self.exprs = list( exprs )
+            except TypeError:
+                self.exprs = [ exprs ]
+        self.callPreparse = False
+
+    def __getitem__( self, i ):
+        return self.exprs[i]
+
+    def append( self, other ):
+        self.exprs.append( other )
+        self.strRepr = None
+        return self
+
+    def leaveWhitespace( self ):
+        """Extends C{leaveWhitespace} defined in base class, and also invokes C{leaveWhitespace} on
+           all contained expressions."""
+        self.skipWhitespace = False
+        self.exprs = [ e.copy() for e in self.exprs ]
+        for e in self.exprs:
+            e.leaveWhitespace()
+        return self
+
+    def ignore( self, other ):
+        if isinstance( other, Suppress ):
+            if other not in self.ignoreExprs:
+                super( ParseExpression, self).ignore( other )
+                for e in self.exprs:
+                    e.ignore( self.ignoreExprs[-1] )
+        else:
+            super( ParseExpression, self).ignore( other )
+            for e in self.exprs:
+                e.ignore( self.ignoreExprs[-1] )
+        return self
+
+    def __str__( self ):
+        try:
+            return super(ParseExpression,self).__str__()
+        except:
+            pass
+
+        if self.strRepr is None:
+            self.strRepr = "%s:(%s)" % ( self.__class__.__name__, _ustr(self.exprs) )
+        return self.strRepr
+
+    def streamline( self ):
+        super(ParseExpression,self).streamline()
+
+        for e in self.exprs:
+            e.streamline()
+
+        # collapse nested And's of the form And( And( And( a,b), c), d) to And( a,b,c,d )
+        # but only if there are no parse actions or resultsNames on the nested And's
+        # (likewise for Or's and MatchFirst's)
+        if ( len(self.exprs) == 2 ):
+            other = self.exprs[0]
+            if ( isinstance( other, self.__class__ ) and
+                  not(other.parseAction) and
+                  other.resultsName is None and
+                  not other.debug ):
+                self.exprs = other.exprs[:] + [ self.exprs[1] ]
+                self.strRepr = None
+                self.mayReturnEmpty |= other.mayReturnEmpty
+                self.mayIndexError  |= other.mayIndexError
+
+            other = self.exprs[-1]
+            if ( isinstance( other, self.__class__ ) and
+                  not(other.parseAction) and
+                  other.resultsName is None and
+                  not other.debug ):
+                self.exprs = self.exprs[:-1] + other.exprs[:]
+                self.strRepr = None
+                self.mayReturnEmpty |= other.mayReturnEmpty
+                self.mayIndexError  |= other.mayIndexError
+
+        return self
+
+    def setResultsName( self, name, listAllMatches=False ):
+        ret = super(ParseExpression,self).setResultsName(name,listAllMatches)
+        return ret
+
+    def validate( self, validateTrace=[] ):
+        tmp = validateTrace[:]+[self]
+        for e in self.exprs:
+            e.validate(tmp)
+        self.checkRecursion( [] )
+
+    def copy(self):
+        ret = super(ParseExpression,self).copy()
+        ret.exprs = [e.copy() for e in self.exprs]
+        return ret
+
+class And(ParseExpression):
+    """Requires all given C{ParseExpression}s to be found in the given order.
+       Expressions may be separated by whitespace.
+       May be constructed using the C{'+'} operator.
+    """
+
+    class _ErrorStop(Empty):
+        def __init__(self, *args, **kwargs):
+            super(Empty,self).__init__(*args, **kwargs)
+            self.leaveWhitespace()
+
+    def __init__( self, exprs, savelist = True ):
+        super(And,self).__init__(exprs, savelist)
+        self.mayReturnEmpty = True
+        for e in self.exprs:
+            if not e.mayReturnEmpty:
+                self.mayReturnEmpty = False
+                break
+        self.setWhitespaceChars( exprs[0].whiteChars )
+        self.skipWhitespace = exprs[0].skipWhitespace
+        self.callPreparse = True
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        # pass False as last arg to _parse for first element, since we already
+        # pre-parsed the string as part of our And pre-parsing
+        loc, resultlist = self.exprs[0]._parse( instring, loc, doActions, callPreParse=False )
+        errorStop = False
+        for e in self.exprs[1:]:
+            if isinstance(e, And._ErrorStop):
+                errorStop = True
+                continue
+            if errorStop:
+                try:
+                    loc, exprtokens = e._parse( instring, loc, doActions )
+                except ParseSyntaxException:
+                    raise
+                except ParseBaseException:
+                    pe = sys.exc_info()[1]
+                    raise ParseSyntaxException(pe)
+                except IndexError:
+                    raise ParseSyntaxException( ParseException(instring, len(instring), self.errmsg, self) )
+            else:
+                loc, exprtokens = e._parse( instring, loc, doActions )
+            if exprtokens or exprtokens.keys():
+                resultlist += exprtokens
+        return loc, resultlist
+
+    def __iadd__(self, other ):
+        if isinstance( other, basestring ):
+            other = Literal( other )
+        return self.append( other ) #And( [ self, other ] )
+
+    def checkRecursion( self, parseElementList ):
+        subRecCheckList = parseElementList[:] + [ self ]
+        for e in self.exprs:
+            e.checkRecursion( subRecCheckList )
+            if not e.mayReturnEmpty:
+                break
+
+    def __str__( self ):
+        if hasattr(self,"name"):
+            return self.name
+
+        if self.strRepr is None:
+            self.strRepr = "{" + " ".join( [ _ustr(e) for e in self.exprs ] ) + "}"
+
+        return self.strRepr
+
+
+class Or(ParseExpression):
+    """Requires that at least one C{ParseExpression} is found.
+       If two expressions match, the expression that matches the longest string will be used.
+       May be constructed using the C{'^'} operator.
+    """
+    def __init__( self, exprs, savelist = False ):
+        super(Or,self).__init__(exprs, savelist)
+        self.mayReturnEmpty = False
+        for e in self.exprs:
+            if e.mayReturnEmpty:
+                self.mayReturnEmpty = True
+                break
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        maxExcLoc = -1
+        maxMatchLoc = -1
+        maxException = None
+        for e in self.exprs:
+            try:
+                loc2 = e.tryParse( instring, loc )
+            except ParseException:
+                err = sys.exc_info()[1]
+                if err.loc > maxExcLoc:
+                    maxException = err
+                    maxExcLoc = err.loc
+            except IndexError:
+                if len(instring) > maxExcLoc:
+                    maxException = ParseException(instring,len(instring),e.errmsg,self)
+                    maxExcLoc = len(instring)
+            else:
+                if loc2 > maxMatchLoc:
+                    maxMatchLoc = loc2
+                    maxMatchExp = e
+
+        if maxMatchLoc < 0:
+            if maxException is not None:
+                raise maxException
+            else:
+                raise ParseException(instring, loc, "no defined alternatives to match", self)
+
+        return maxMatchExp._parse( instring, loc, doActions )
+
+    def __ixor__(self, other ):
+        if isinstance( other, basestring ):
+            other = Literal( other )
+        return self.append( other ) #Or( [ self, other ] )
+
+    def __str__( self ):
+        if hasattr(self,"name"):
+            return self.name
+
+        if self.strRepr is None:
+            self.strRepr = "{" + " ^ ".join( [ _ustr(e) for e in self.exprs ] ) + "}"
+
+        return self.strRepr
+
+    def checkRecursion( self, parseElementList ):
+        subRecCheckList = parseElementList[:] + [ self ]
+        for e in self.exprs:
+            e.checkRecursion( subRecCheckList )
+
+
+class MatchFirst(ParseExpression):
+    """Requires that at least one C{ParseExpression} is found.
+       If two expressions match, the first one listed is the one that will match.
+       May be constructed using the C{'|'} operator.
+    """
+    def __init__( self, exprs, savelist = False ):
+        super(MatchFirst,self).__init__(exprs, savelist)
+        if exprs:
+            self.mayReturnEmpty = False
+            for e in self.exprs:
+                if e.mayReturnEmpty:
+                    self.mayReturnEmpty = True
+                    break
+        else:
+            self.mayReturnEmpty = True
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        maxExcLoc = -1
+        maxException = None
+        for e in self.exprs:
+            try:
+                ret = e._parse( instring, loc, doActions )
+                return ret
+            except ParseException, err:
+                if err.loc > maxExcLoc:
+                    maxException = err
+                    maxExcLoc = err.loc
+            except IndexError:
+                if len(instring) > maxExcLoc:
+                    maxException = ParseException(instring,len(instring),e.errmsg,self)
+                    maxExcLoc = len(instring)
+
+        # only got here if no expression matched, raise exception for match that made it the furthest
+        else:
+            if maxException is not None:
+                raise maxException
+            else:
+                raise ParseException(instring, loc, "no defined alternatives to match", self)
+
+    def __ior__(self, other ):
+        if isinstance( other, basestring ):
+            other = Literal( other )
+        return self.append( other ) #MatchFirst( [ self, other ] )
+
+    def __str__( self ):
+        if hasattr(self,"name"):
+            return self.name
+
+        if self.strRepr is None:
+            self.strRepr = "{" + " | ".join( [ _ustr(e) for e in self.exprs ] ) + "}"
+
+        return self.strRepr
+
+    def checkRecursion( self, parseElementList ):
+        subRecCheckList = parseElementList[:] + [ self ]
+        for e in self.exprs:
+            e.checkRecursion( subRecCheckList )
+
+
+class Each(ParseExpression):
+    """Requires all given C{ParseExpression}s to be found, but in any order.
+       Expressions may be separated by whitespace.
+       May be constructed using the C{'&'} operator.
+    """
+    def __init__( self, exprs, savelist = True ):
+        super(Each,self).__init__(exprs, savelist)
+        self.mayReturnEmpty = True
+        for e in self.exprs:
+            if not e.mayReturnEmpty:
+                self.mayReturnEmpty = False
+                break
+        self.skipWhitespace = True
+        self.initExprGroups = True
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        if self.initExprGroups:
+            opt1 = [ e.expr for e in self.exprs if isinstance(e,Optional) ]
+            opt2 = [ e for e in self.exprs if e.mayReturnEmpty and e not in opt1 ]
+            self.optionals = opt1 + opt2
+            self.multioptionals = [ e.expr for e in self.exprs if isinstance(e,ZeroOrMore) ]
+            self.multirequired = [ e.expr for e in self.exprs if isinstance(e,OneOrMore) ]
+            self.required = [ e for e in self.exprs if not isinstance(e,(Optional,ZeroOrMore,OneOrMore)) ]
+            self.required += self.multirequired
+            self.initExprGroups = False
+        tmpLoc = loc
+        tmpReqd = self.required[:]
+        tmpOpt  = self.optionals[:]
+        matchOrder = []
+
+        keepMatching = True
+        while keepMatching:
+            tmpExprs = tmpReqd + tmpOpt + self.multioptionals + self.multirequired
+            failed = []
+            for e in tmpExprs:
+                try:
+                    tmpLoc = e.tryParse( instring, tmpLoc )
+                except ParseException:
+                    failed.append(e)
+                else:
+                    matchOrder.append(e)
+                    if e in tmpReqd:
+                        tmpReqd.remove(e)
+                    elif e in tmpOpt:
+                        tmpOpt.remove(e)
+            if len(failed) == len(tmpExprs):
+                keepMatching = False
+
+        if tmpReqd:
+            missing = ", ".join( [ _ustr(e) for e in tmpReqd ] )
+            raise ParseException(instring,loc,"Missing one or more required elements (%s)" % missing )
+
+        # add any unmatched Optionals, in case they have default values defined
+        matchOrder += [e for e in self.exprs if isinstance(e,Optional) and e.expr in tmpOpt]
+
+        resultlist = []
+        for e in matchOrder:
+            loc,results = e._parse(instring,loc,doActions)
+            resultlist.append(results)
+
+        finalResults = ParseResults([])
+        for r in resultlist:
+            dups = {}
+            for k in r.keys():
+                if k in finalResults.keys():
+                    tmp = ParseResults(finalResults[k])
+                    tmp += ParseResults(r[k])
+                    dups[k] = tmp
+            finalResults += ParseResults(r)
+            for k,v in dups.items():
+                finalResults[k] = v
+        return loc, finalResults
+
+    def __str__( self ):
+        if hasattr(self,"name"):
+            return self.name
+
+        if self.strRepr is None:
+            self.strRepr = "{" + " & ".join( [ _ustr(e) for e in self.exprs ] ) + "}"
+
+        return self.strRepr
+
+    def checkRecursion( self, parseElementList ):
+        subRecCheckList = parseElementList[:] + [ self ]
+        for e in self.exprs:
+            e.checkRecursion( subRecCheckList )
+
+
+class ParseElementEnhance(ParserElement):
+    """Abstract subclass of C{ParserElement}, for combining and post-processing parsed tokens."""
+    def __init__( self, expr, savelist=False ):
+        super(ParseElementEnhance,self).__init__(savelist)
+        if isinstance( expr, basestring ):
+            expr = Literal(expr)
+        self.expr = expr
+        self.strRepr = None
+        if expr is not None:
+            self.mayIndexError = expr.mayIndexError
+            self.mayReturnEmpty = expr.mayReturnEmpty
+            self.setWhitespaceChars( expr.whiteChars )
+            self.skipWhitespace = expr.skipWhitespace
+            self.saveAsList = expr.saveAsList
+            self.callPreparse = expr.callPreparse
+            self.ignoreExprs.extend(expr.ignoreExprs)
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        if self.expr is not None:
+            return self.expr._parse( instring, loc, doActions, callPreParse=False )
+        else:
+            raise ParseException("",loc,self.errmsg,self)
+
+    def leaveWhitespace( self ):
+        self.skipWhitespace = False
+        self.expr = self.expr.copy()
+        if self.expr is not None:
+            self.expr.leaveWhitespace()
+        return self
+
+    def ignore( self, other ):
+        if isinstance( other, Suppress ):
+            if other not in self.ignoreExprs:
+                super( ParseElementEnhance, self).ignore( other )
+                if self.expr is not None:
+                    self.expr.ignore( self.ignoreExprs[-1] )
+        else:
+            super( ParseElementEnhance, self).ignore( other )
+            if self.expr is not None:
+                self.expr.ignore( self.ignoreExprs[-1] )
+        return self
+
+    def streamline( self ):
+        super(ParseElementEnhance,self).streamline()
+        if self.expr is not None:
+            self.expr.streamline()
+        return self
+
+    def checkRecursion( self, parseElementList ):
+        if self in parseElementList:
+            raise RecursiveGrammarException( parseElementList+[self] )
+        subRecCheckList = parseElementList[:] + [ self ]
+        if self.expr is not None:
+            self.expr.checkRecursion( subRecCheckList )
+
+    def validate( self, validateTrace=[] ):
+        tmp = validateTrace[:]+[self]
+        if self.expr is not None:
+            self.expr.validate(tmp)
+        self.checkRecursion( [] )
+
+    def __str__( self ):
+        try:
+            return super(ParseElementEnhance,self).__str__()
+        except:
+            pass
+
+        if self.strRepr is None and self.expr is not None:
+            self.strRepr = "%s:(%s)" % ( self.__class__.__name__, _ustr(self.expr) )
+        return self.strRepr
+
+
+class FollowedBy(ParseElementEnhance):
+    """Lookahead matching of the given parse expression.  C{FollowedBy}
+    does *not* advance the parsing position within the input string, it only
+    verifies that the specified parse expression matches at the current
+    position.  C{FollowedBy} always returns a null token list."""
+    def __init__( self, expr ):
+        super(FollowedBy,self).__init__(expr)
+        self.mayReturnEmpty = True
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        self.expr.tryParse( instring, loc )
+        return loc, []
+
+
+class NotAny(ParseElementEnhance):
+    """Lookahead to disallow matching with the given parse expression.  C{NotAny}
+    does *not* advance the parsing position within the input string, it only
+    verifies that the specified parse expression does *not* match at the current
+    position.  Also, C{NotAny} does *not* skip over leading whitespace. C{NotAny}
+    always returns a null token list.  May be constructed using the '~' operator."""
+    def __init__( self, expr ):
+        super(NotAny,self).__init__(expr)
+        #~ self.leaveWhitespace()
+        self.skipWhitespace = False  # do NOT use self.leaveWhitespace(), don't want to propagate to exprs
+        self.mayReturnEmpty = True
+        self.errmsg = "Found unwanted token, "+_ustr(self.expr)
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        try:
+            self.expr.tryParse( instring, loc )
+        except (ParseException,IndexError):
+            pass
+        else:
+            #~ raise ParseException(instring, loc, self.errmsg )
+            exc = self.myException
+            exc.loc = loc
+            exc.pstr = instring
+            raise exc
+        return loc, []
+
+    def __str__( self ):
+        if hasattr(self,"name"):
+            return self.name
+
+        if self.strRepr is None:
+            self.strRepr = "~{" + _ustr(self.expr) + "}"
+
+        return self.strRepr
+
+
+class ZeroOrMore(ParseElementEnhance):
+    """Optional repetition of zero or more of the given expression."""
+    def __init__( self, expr ):
+        super(ZeroOrMore,self).__init__(expr)
+        self.mayReturnEmpty = True
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        tokens = []
+        try:
+            loc, tokens = self.expr._parse( instring, loc, doActions, callPreParse=False )
+            hasIgnoreExprs = ( len(self.ignoreExprs) > 0 )
+            while 1:
+                if hasIgnoreExprs:
+                    preloc = self._skipIgnorables( instring, loc )
+                else:
+                    preloc = loc
+                loc, tmptokens = self.expr._parse( instring, preloc, doActions )
+                if tmptokens or tmptokens.keys():
+                    tokens += tmptokens
+        except (ParseException,IndexError):
+            pass
+
+        return loc, tokens
+
+    def __str__( self ):
+        if hasattr(self,"name"):
+            return self.name
+
+        if self.strRepr is None:
+            self.strRepr = "[" + _ustr(self.expr) + "]..."
+
+        return self.strRepr
+
+    def setResultsName( self, name, listAllMatches=False ):
+        ret = super(ZeroOrMore,self).setResultsName(name,listAllMatches)
+        ret.saveAsList = True
+        return ret
+
+
+class OneOrMore(ParseElementEnhance):
+    """Repetition of one or more of the given expression."""
+    def parseImpl( self, instring, loc, doActions=True ):
+        # must be at least one
+        loc, tokens = self.expr._parse( instring, loc, doActions, callPreParse=False )
+        try:
+            hasIgnoreExprs = ( len(self.ignoreExprs) > 0 )
+            while 1:
+                if hasIgnoreExprs:
+                    preloc = self._skipIgnorables( instring, loc )
+                else:
+                    preloc = loc
+                loc, tmptokens = self.expr._parse( instring, preloc, doActions )
+                if tmptokens or tmptokens.keys():
+                    tokens += tmptokens
+        except (ParseException,IndexError):
+            pass
+
+        return loc, tokens
+
+    def __str__( self ):
+        if hasattr(self,"name"):
+            return self.name
+
+        if self.strRepr is None:
+            self.strRepr = "{" + _ustr(self.expr) + "}..."
+
+        return self.strRepr
+
+    def setResultsName( self, name, listAllMatches=False ):
+        ret = super(OneOrMore,self).setResultsName(name,listAllMatches)
+        ret.saveAsList = True
+        return ret
+
+class _NullToken(object):
+    def __bool__(self):
+        return False
+    __nonzero__ = __bool__
+    def __str__(self):
+        return ""
+
+_optionalNotMatched = _NullToken()
+class Optional(ParseElementEnhance):
+    """Optional matching of the given expression.
+       A default return string can also be specified, if the optional expression
+       is not found.
+    """
+    def __init__( self, exprs, default=_optionalNotMatched ):
+        super(Optional,self).__init__( exprs, savelist=False )
+        self.defaultValue = default
+        self.mayReturnEmpty = True
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        try:
+            loc, tokens = self.expr._parse( instring, loc, doActions, callPreParse=False )
+        except (ParseException,IndexError):
+            if self.defaultValue is not _optionalNotMatched:
+                if self.expr.resultsName:
+                    tokens = ParseResults([ self.defaultValue ])
+                    tokens[self.expr.resultsName] = self.defaultValue
+                else:
+                    tokens = [ self.defaultValue ]
+            else:
+                tokens = []
+        return loc, tokens
+
+    def __str__( self ):
+        if hasattr(self,"name"):
+            return self.name
+
+        if self.strRepr is None:
+            self.strRepr = "[" + _ustr(self.expr) + "]"
+
+        return self.strRepr
+
+
+class SkipTo(ParseElementEnhance):
+    """Token for skipping over all undefined text until the matched expression is found.
+       If C{include} is set to true, the matched expression is also parsed (the skipped text
+       and matched expression are returned as a 2-element list).  The C{ignore}
+       argument is used to define grammars (typically quoted strings and comments) that
+       might contain false matches.
+    """
+    def __init__( self, other, include=False, ignore=None, failOn=None ):
+        super( SkipTo, self ).__init__( other )
+        self.ignoreExpr = ignore
+        self.mayReturnEmpty = True
+        self.mayIndexError = False
+        self.includeMatch = include
+        self.asList = False
+        if failOn is not None and isinstance(failOn, basestring):
+            self.failOn = Literal(failOn)
+        else:
+            self.failOn = failOn
+        self.errmsg = "No match found for "+_ustr(self.expr)
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        startLoc = loc
+        instrlen = len(instring)
+        expr = self.expr
+        failParse = False
+        while loc <= instrlen:
+            try:
+                if self.failOn:
+                    try:
+                        self.failOn.tryParse(instring, loc)
+                    except ParseBaseException:
+                        pass
+                    else:
+                        failParse = True
+                        raise ParseException(instring, loc, "Found expression " + str(self.failOn))
+                    failParse = False
+                if self.ignoreExpr is not None:
+                    while 1:
+                        try:
+                            loc = self.ignoreExpr.tryParse(instring,loc)
+                            # print "found ignoreExpr, advance to", loc
+                        except ParseBaseException:
+                            break
+                expr._parse( instring, loc, doActions=False, callPreParse=False )
+                skipText = instring[startLoc:loc]
+                if self.includeMatch:
+                    loc,mat = expr._parse(instring,loc,doActions,callPreParse=False)
+                    if mat:
+                        skipRes = ParseResults( skipText )
+                        skipRes += mat
+                        return loc, [ skipRes ]
+                    else:
+                        return loc, [ skipText ]
+                else:
+                    return loc, [ skipText ]
+            except (ParseException,IndexError):
+                if failParse:
+                    raise
+                else:
+                    loc += 1
+        exc = self.myException
+        exc.loc = loc
+        exc.pstr = instring
+        raise exc
+
+class Forward(ParseElementEnhance):
+    """Forward declaration of an expression to be defined later -
+       used for recursive grammars, such as algebraic infix notation.
+       When the expression is known, it is assigned to the C{Forward} variable using the '<<' operator.
+
+       Note: take care when assigning to C{Forward} not to overlook precedence of operators.
+       Specifically, '|' has a lower precedence than '<<', so that::
+          fwdExpr << a | b | c
+       will actually be evaluated as::
+          (fwdExpr << a) | b | c
+       thereby leaving b and c out as parseable alternatives.  It is recommended that you
+       explicitly group the values inserted into the C{Forward}::
+          fwdExpr << (a | b | c)
+    """
+    def __init__( self, other=None ):
+        super(Forward,self).__init__( other, savelist=False )
+
+    def __lshift__( self, other ):
+        if isinstance( other, basestring ):
+            other = Literal(other)
+        self.expr = other
+        self.mayReturnEmpty = other.mayReturnEmpty
+        self.strRepr = None
+        self.mayIndexError = self.expr.mayIndexError
+        self.mayReturnEmpty = self.expr.mayReturnEmpty
+        self.setWhitespaceChars( self.expr.whiteChars )
+        self.skipWhitespace = self.expr.skipWhitespace
+        self.saveAsList = self.expr.saveAsList
+        self.ignoreExprs.extend(self.expr.ignoreExprs)
+        return None
+
+    def leaveWhitespace( self ):
+        self.skipWhitespace = False
+        return self
+
+    def streamline( self ):
+        if not self.streamlined:
+            self.streamlined = True
+            if self.expr is not None:
+                self.expr.streamline()
+        return self
+
+    def validate( self, validateTrace=[] ):
+        if self not in validateTrace:
+            tmp = validateTrace[:]+[self]
+            if self.expr is not None:
+                self.expr.validate(tmp)
+        self.checkRecursion([])
+
+    def __str__( self ):
+        if hasattr(self,"name"):
+            return self.name
+
+        self._revertClass = self.__class__
+        self.__class__ = _ForwardNoRecurse
+        try:
+            if self.expr is not None:
+                retString = _ustr(self.expr)
+            else:
+                retString = "None"
+        finally:
+            self.__class__ = self._revertClass
+        return self.__class__.__name__ + ": " + retString
+
+    def copy(self):
+        if self.expr is not None:
+            return super(Forward,self).copy()
+        else:
+            ret = Forward()
+            ret << self
+            return ret
+
+class _ForwardNoRecurse(Forward):
+    def __str__( self ):
+        return "..."
+
+class TokenConverter(ParseElementEnhance):
+    """Abstract subclass of C{ParseExpression}, for converting parsed results."""
+    def __init__( self, expr, savelist=False ):
+        super(TokenConverter,self).__init__( expr )#, savelist )
+        self.saveAsList = False
+
+class Upcase(TokenConverter):
+    """Converter to upper case all matching tokens."""
+    def __init__(self, *args):
+        super(Upcase,self).__init__(*args)
+        warnings.warn("Upcase class is deprecated, use upcaseTokens parse action instead",
+                       DeprecationWarning,stacklevel=2)
+
+    def postParse( self, instring, loc, tokenlist ):
+        return list(map( string.upper, tokenlist ))
+
+
+class Combine(TokenConverter):
+    """Converter to concatenate all matching tokens to a single string.
+       By default, the matching patterns must also be contiguous in the input string;
+       this can be disabled by specifying C{'adjacent=False'} in the constructor.
+    """
+    def __init__( self, expr, joinString="", adjacent=True ):
+        super(Combine,self).__init__( expr )
+        # suppress whitespace-stripping in contained parse expressions, but re-enable it on the Combine itself
+        if adjacent:
+            self.leaveWhitespace()
+        self.adjacent = adjacent
+        self.skipWhitespace = True
+        self.joinString = joinString
+        self.callPreparse = True
+
+    def ignore( self, other ):
+        if self.adjacent:
+            ParserElement.ignore(self, other)
+        else:
+            super( Combine, self).ignore( other )
+        return self
+
+    def postParse( self, instring, loc, tokenlist ):
+        retToks = tokenlist.copy()
+        del retToks[:]
+        retToks += ParseResults([ "".join(tokenlist._asStringList(self.joinString)) ], modal=self.modalResults)
+
+        if self.resultsName and len(retToks.keys())>0:
+            return [ retToks ]
+        else:
+            return retToks
+
+class Group(TokenConverter):
+    """Converter to return the matched tokens as a list - useful for returning tokens of C{ZeroOrMore} and C{OneOrMore} expressions."""
+    def __init__( self, expr ):
+        super(Group,self).__init__( expr )
+        self.saveAsList = True
+
+    def postParse( self, instring, loc, tokenlist ):
+        return [ tokenlist ]
+
+class Dict(TokenConverter):
+    """Converter to return a repetitive expression as a list, but also as a dictionary.
+       Each element can also be referenced using the first token in the expression as its key.
+       Useful for tabular report scraping when the first column can be used as a item key.
+    """
+    def __init__( self, exprs ):
+        super(Dict,self).__init__( exprs )
+        self.saveAsList = True
+
+    def postParse( self, instring, loc, tokenlist ):
+        for i,tok in enumerate(tokenlist):
+            if len(tok) == 0:
+                continue
+            ikey = tok[0]
+            if isinstance(ikey,int):
+                ikey = _ustr(tok[0]).strip()
+            if len(tok)==1:
+                tokenlist[ikey] = _ParseResultsWithOffset("",i)
+            elif len(tok)==2 and not isinstance(tok[1],ParseResults):
+                tokenlist[ikey] = _ParseResultsWithOffset(tok[1],i)
+            else:
+                dictvalue = tok.copy() #ParseResults(i)
+                del dictvalue[0]
+                if len(dictvalue)!= 1 or (isinstance(dictvalue,ParseResults) and dictvalue.keys()):
+                    tokenlist[ikey] = _ParseResultsWithOffset(dictvalue,i)
+                else:
+                    tokenlist[ikey] = _ParseResultsWithOffset(dictvalue[0],i)
+
+        if self.resultsName:
+            return [ tokenlist ]
+        else:
+            return tokenlist
+
+
+class Suppress(TokenConverter):
+    """Converter for ignoring the results of a parsed expression."""
+    def postParse( self, instring, loc, tokenlist ):
+        return []
+
+    def suppress( self ):
+        return self
+
+
+class OnlyOnce(object):
+    """Wrapper for parse actions, to ensure they are only called once."""
+    def __init__(self, methodCall):
+        self.callable = _trim_arity(methodCall)
+        self.called = False
+    def __call__(self,s,l,t):
+        if not self.called:
+            results = self.callable(s,l,t)
+            self.called = True
+            return results
+        raise ParseException(s,l,"")
+    def reset(self):
+        self.called = False
+
+def traceParseAction(f):
+    """Decorator for debugging parse actions."""
+    f = _trim_arity(f)
+    def z(*paArgs):
+        thisFunc = f.func_name
+        s,l,t = paArgs[-3:]
+        if len(paArgs)>3:
+            thisFunc = paArgs[0].__class__.__name__ + '.' + thisFunc
+        sys.stderr.write( ">>entering %s(line: '%s', %d, %s)\n" % (thisFunc,line(l,s),l,t) )
+        try:
+            ret = f(*paArgs)
+        except Exception:
+            exc = sys.exc_info()[1]
+            sys.stderr.write( "<<leaving %s (exception: %s)\n" % (thisFunc,exc) )
+            raise
+        sys.stderr.write( "<<leaving %s (ret: %s)\n" % (thisFunc,ret) )
+        return ret
+    try:
+        z.__name__ = f.__name__
+    except AttributeError:
+        pass
+    return z
+
+#
+# global helpers
+#
+def delimitedList( expr, delim=",", combine=False ):
+    """Helper to define a delimited list of expressions - the delimiter defaults to ','.
+       By default, the list elements and delimiters can have intervening whitespace, and
+       comments, but this can be overridden by passing C{combine=True} in the constructor.
+       If C{combine} is set to True, the matching tokens are returned as a single token
+       string, with the delimiters included; otherwise, the matching tokens are returned
+       as a list of tokens, with the delimiters suppressed.
+    """
+    dlName = _ustr(expr)+" ["+_ustr(delim)+" "+_ustr(expr)+"]..."
+    if combine:
+        return Combine( expr + ZeroOrMore( delim + expr ) ).setName(dlName)
+    else:
+        return ( expr + ZeroOrMore( Suppress( delim ) + expr ) ).setName(dlName)
+
+def countedArray( expr, intExpr=None ):
+    """Helper to define a counted list of expressions.
+       This helper defines a pattern of the form::
+           integer expr expr expr...
+       where the leading integer tells how many expr expressions follow.
+       The matched tokens returns the array of expr tokens as a list - the leading count token is suppressed.
+    """
+    arrayExpr = Forward()
+    def countFieldParseAction(s,l,t):
+        n = t[0]
+        arrayExpr << (n and Group(And([expr]*n)) or Group(empty))
+        return []
+    if intExpr is None:
+        intExpr = Word(nums).setParseAction(lambda t:int(t[0]))
+    else:
+        intExpr = intExpr.copy()
+    intExpr.setName("arrayLen")
+    intExpr.addParseAction(countFieldParseAction, callDuringTry=True)
+    return ( intExpr + arrayExpr )
+
+def _flatten(L):
+    ret = []
+    for i in L:
+        if isinstance(i,list):
+            ret.extend(_flatten(i))
+        else:
+            ret.append(i)
+    return ret
+
+def matchPreviousLiteral(expr):
+    """Helper to define an expression that is indirectly defined from
+       the tokens matched in a previous expression, that is, it looks
+       for a 'repeat' of a previous expression.  For example::
+           first = Word(nums)
+           second = matchPreviousLiteral(first)
+           matchExpr = first + ":" + second
+       will match C{"1:1"}, but not C{"1:2"}.  Because this matches a
+       previous literal, will also match the leading C{"1:1"} in C{"1:10"}.
+       If this is not desired, use C{matchPreviousExpr}.
+       Do *not* use with packrat parsing enabled.
+    """
+    rep = Forward()
+    def copyTokenToRepeater(s,l,t):
+        if t:
+            if len(t) == 1:
+                rep << t[0]
+            else:
+                # flatten t tokens
+                tflat = _flatten(t.asList())
+                rep << And( [ Literal(tt) for tt in tflat ] )
+        else:
+            rep << Empty()
+    expr.addParseAction(copyTokenToRepeater, callDuringTry=True)
+    return rep
+
+def matchPreviousExpr(expr):
+    """Helper to define an expression that is indirectly defined from
+       the tokens matched in a previous expression, that is, it looks
+       for a 'repeat' of a previous expression.  For example::
+           first = Word(nums)
+           second = matchPreviousExpr(first)
+           matchExpr = first + ":" + second
+       will match C{"1:1"}, but not C{"1:2"}.  Because this matches by
+       expressions, will *not* match the leading C{"1:1"} in C{"1:10"};
+       the expressions are evaluated first, and then compared, so
+       C{"1"} is compared with C{"10"}.
+       Do *not* use with packrat parsing enabled.
+    """
+    rep = Forward()
+    e2 = expr.copy()
+    rep << e2
+    def copyTokenToRepeater(s,l,t):
+        matchTokens = _flatten(t.asList())
+        def mustMatchTheseTokens(s,l,t):
+            theseTokens = _flatten(t.asList())
+            if  theseTokens != matchTokens:
+                raise ParseException("",0,"")
+        rep.setParseAction( mustMatchTheseTokens, callDuringTry=True )
+    expr.addParseAction(copyTokenToRepeater, callDuringTry=True)
+    return rep
+
+def _escapeRegexRangeChars(s):
+    #~  escape these chars: ^-]
+    for c in r"\^-]":
+        s = s.replace(c,_bslash+c)
+    s = s.replace("\n",r"\n")
+    s = s.replace("\t",r"\t")
+    return _ustr(s)
+
+def oneOf( strs, caseless=False, useRegex=True ):
+    """Helper to quickly define a set of alternative Literals, and makes sure to do
+       longest-first testing when there is a conflict, regardless of the input order,
+       but returns a C{MatchFirst} for best performance.
+
+       Parameters:
+        - strs - a string of space-delimited literals, or a list of string literals
+        - caseless - (default=False) - treat all literals as caseless
+        - useRegex - (default=True) - as an optimization, will generate a Regex
+          object; otherwise, will generate a C{MatchFirst} object (if C{caseless=True}, or
+          if creating a C{Regex} raises an exception)
+    """
+    if caseless:
+        isequal = ( lambda a,b: a.upper() == b.upper() )
+        masks = ( lambda a,b: b.upper().startswith(a.upper()) )
+        parseElementClass = CaselessLiteral
+    else:
+        isequal = ( lambda a,b: a == b )
+        masks = ( lambda a,b: b.startswith(a) )
+        parseElementClass = Literal
+
+    if isinstance(strs,(list,tuple)):
+        symbols = list(strs[:])
+    elif isinstance(strs,basestring):
+        symbols = strs.split()
+    else:
+        warnings.warn("Invalid argument to oneOf, expected string or list",
+                SyntaxWarning, stacklevel=2)
+
+    i = 0
+    while i < len(symbols)-1:
+        cur = symbols[i]
+        for j,other in enumerate(symbols[i+1:]):
+            if ( isequal(other, cur) ):
+                del symbols[i+j+1]
+                break
+            elif ( masks(cur, other) ):
+                del symbols[i+j+1]
+                symbols.insert(i,other)
+                cur = other
+                break
+        else:
+            i += 1
+
+    if not caseless and useRegex:
+        #~ print (strs,"->", "|".join( [ _escapeRegexChars(sym) for sym in symbols] ))
+        try:
+            if len(symbols)==len("".join(symbols)):
+                return Regex( "[%s]" % "".join( [ _escapeRegexRangeChars(sym) for sym in symbols] ) )
+            else:
+                return Regex( "|".join( [ re.escape(sym) for sym in symbols] ) )
+        except:
+            warnings.warn("Exception creating Regex for oneOf, building MatchFirst",
+                    SyntaxWarning, stacklevel=2)
+
+
+    # last resort, just use MatchFirst
+    return MatchFirst( [ parseElementClass(sym) for sym in symbols ] )
+
+def dictOf( key, value ):
+    """Helper to easily and clearly define a dictionary by specifying the respective patterns
+       for the key and value.  Takes care of defining the C{Dict}, C{ZeroOrMore}, and C{Group} tokens
+       in the proper order.  The key pattern can include delimiting markers or punctuation,
+       as long as they are suppressed, thereby leaving the significant key text.  The value
+       pattern can include named results, so that the C{Dict} results can include named token
+       fields.
+    """
+    return Dict( ZeroOrMore( Group ( key + value ) ) )
+
+def originalTextFor(expr, asString=True):
+    """Helper to return the original, untokenized text for a given expression.  Useful to
+       restore the parsed fields of an HTML start tag into the raw tag text itself, or to
+       revert separate tokens with intervening whitespace back to the original matching
+       input text. Simpler to use than the parse action C{L{keepOriginalText}}, and does not
+       require the inspect module to chase up the call stack.  By default, returns a
+       string containing the original parsed text.
+
+       If the optional C{asString} argument is passed as C{False}, then the return value is a
+       C{ParseResults} containing any results names that were originally matched, and a
+       single token containing the original matched text from the input string.  So if
+       the expression passed to C{L{originalTextFor}} contains expressions with defined
+       results names, you must set C{asString} to C{False} if you want to preserve those
+       results name values."""
+    locMarker = Empty().setParseAction(lambda s,loc,t: loc)
+    endlocMarker = locMarker.copy()
+    endlocMarker.callPreparse = False
+    matchExpr = locMarker("_original_start") + expr + endlocMarker("_original_end")
+    if asString:
+        extractText = lambda s,l,t: s[t._original_start:t._original_end]
+    else:
+        def extractText(s,l,t):
+            del t[:]
+            t.insert(0, s[t._original_start:t._original_end])
+            del t["_original_start"]
+            del t["_original_end"]
+    matchExpr.setParseAction(extractText)
+    return matchExpr
+
+def ungroup(expr):
+    """Helper to undo pyparsing's default grouping of And expressions, even
+       if all but one are non-empty."""
+    return TokenConverter(expr).setParseAction(lambda t:t[0])
+
+# convenience constants for positional expressions
+empty       = Empty().setName("empty")
+lineStart   = LineStart().setName("lineStart")
+lineEnd     = LineEnd().setName("lineEnd")
+stringStart = StringStart().setName("stringStart")
+stringEnd   = StringEnd().setName("stringEnd")
+
+_escapedPunc = Word( _bslash, r"\[]-*.$+^?()~ ", exact=2 ).setParseAction(lambda s,l,t:t[0][1])
+_printables_less_backslash = "".join([ c for c in printables if c not in  r"\]" ])
+_escapedHexChar = Regex(r"\\0?[xX][0-9a-fA-F]+").setParseAction(lambda s,l,t:unichr(int(t[0][1:],16)))
+_escapedOctChar = Regex(r"\\0[0-7]+").setParseAction(lambda s,l,t:unichr(int(t[0][1:],8)))
+_singleChar = _escapedPunc | _escapedHexChar | _escapedOctChar | Word(_printables_less_backslash,exact=1)
+_charRange = Group(_singleChar + Suppress("-") + _singleChar)
+_reBracketExpr = Literal("[") + Optional("^").setResultsName("negate") + Group( OneOrMore( _charRange | _singleChar ) ).setResultsName("body") + "]"
+
+_expanded = lambda p: (isinstance(p,ParseResults) and ''.join([ unichr(c) for c in range(ord(p[0]),ord(p[1])+1) ]) or p)
+
+def srange(s):
+    r"""Helper to easily define string ranges for use in Word construction.  Borrows
+       syntax from regexp '[]' string range definitions::
+          srange("[0-9]")   -> "0123456789"
+          srange("[a-z]")   -> "abcdefghijklmnopqrstuvwxyz"
+          srange("[a-z$_]") -> "abcdefghijklmnopqrstuvwxyz$_"
+       The input string must be enclosed in []'s, and the returned string is the expanded
+       character set joined into a single string.
+       The values enclosed in the []'s may be::
+          a single character
+          an escaped character with a leading backslash (such as \- or \])
+          an escaped hex character with a leading '\x' (\x21, which is a '!' character)
+            (\0x## is also supported for backwards compatibility)
+          an escaped octal character with a leading '\0' (\041, which is a '!' character)
+          a range of any of the above, separated by a dash ('a-z', etc.)
+          any combination of the above ('aeiouy', 'a-zA-Z0-9_$', etc.)
+    """
+    try:
+        return "".join([_expanded(part) for part in _reBracketExpr.parseString(s).body])
+    except:
+        return ""
+
+def matchOnlyAtCol(n):
+    """Helper method for defining parse actions that require matching at a specific
+       column in the input text.
+    """
+    def verifyCol(strg,locn,toks):
+        if col(locn,strg) != n:
+            raise ParseException(strg,locn,"matched token not at column %d" % n)
+    return verifyCol
+
+def replaceWith(replStr):
+    """Helper method for common parse actions that simply return a literal value.  Especially
+       useful when used with C{transformString()}.
+    """
+    def _replFunc(*args):
+        return [replStr]
+    return _replFunc
+
+def removeQuotes(s,l,t):
+    """Helper parse action for removing quotation marks from parsed quoted strings.
+       To use, add this parse action to quoted string using::
+         quotedString.setParseAction( removeQuotes )
+    """
+    return t[0][1:-1]
+
+def upcaseTokens(s,l,t):
+    """Helper parse action to convert tokens to upper case."""
+    return [ tt.upper() for tt in map(_ustr,t) ]
+
+def downcaseTokens(s,l,t):
+    """Helper parse action to convert tokens to lower case."""
+    return [ tt.lower() for tt in map(_ustr,t) ]
+
+def keepOriginalText(s,startLoc,t):
+    """DEPRECATED - use new helper method C{originalTextFor}.
+       Helper parse action to preserve original parsed text,
+       overriding any nested parse actions."""
+    try:
+        endloc = getTokensEndLoc()
+    except ParseException:
+        raise ParseFatalException("incorrect usage of keepOriginalText - may only be called as a parse action")
+    del t[:]
+    t += ParseResults(s[startLoc:endloc])
+    return t
+
+def getTokensEndLoc():
+    """Method to be called from within a parse action to determine the end
+       location of the parsed tokens."""
+    import inspect
+    fstack = inspect.stack()
+    try:
+        # search up the stack (through intervening argument normalizers) for correct calling routine
+        for f in fstack[2:]:
+            if f[3] == "_parseNoCache":
+                endloc = f[0].f_locals["loc"]
+                return endloc
+        else:
+            raise ParseFatalException("incorrect usage of getTokensEndLoc - may only be called from within a parse action")
+    finally:
+        del fstack
+
+def _makeTags(tagStr, xml):
+    """Internal helper to construct opening and closing tag expressions, given a tag name"""
+    if isinstance(tagStr,basestring):
+        resname = tagStr
+        tagStr = Keyword(tagStr, caseless=not xml)
+    else:
+        resname = tagStr.name
+
+    tagAttrName = Word(alphas,alphanums+"_-:")
+    if (xml):
+        tagAttrValue = dblQuotedString.copy().setParseAction( removeQuotes )
+        openTag = Suppress("<") + tagStr("tag") + \
+                Dict(ZeroOrMore(Group( tagAttrName + Suppress("=") + tagAttrValue ))) + \
+                Optional("/",default=[False]).setResultsName("empty").setParseAction(lambda s,l,t:t[0]=='/') + Suppress(">")
+    else:
+        printablesLessRAbrack = "".join( [ c for c in printables if c not in ">" ] )
+        tagAttrValue = quotedString.copy().setParseAction( removeQuotes ) | Word(printablesLessRAbrack)
+        openTag = Suppress("<") + tagStr("tag") + \
+                Dict(ZeroOrMore(Group( tagAttrName.setParseAction(downcaseTokens) + \
+                Optional( Suppress("=") + tagAttrValue ) ))) + \
+                Optional("/",default=[False]).setResultsName("empty").setParseAction(lambda s,l,t:t[0]=='/') + Suppress(">")
+    closeTag = Combine(_L("</") + tagStr + ">")
+
+    openTag = openTag.setResultsName("start"+"".join(resname.replace(":"," ").title().split())).setName("<%s>" % tagStr)
+    closeTag = closeTag.setResultsName("end"+"".join(resname.replace(":"," ").title().split())).setName("</%s>" % tagStr)
+    openTag.tag = resname
+    closeTag.tag = resname
+    return openTag, closeTag
+
+def makeHTMLTags(tagStr):
+    """Helper to construct opening and closing tag expressions for HTML, given a tag name"""
+    return _makeTags( tagStr, False )
+
+def makeXMLTags(tagStr):
+    """Helper to construct opening and closing tag expressions for XML, given a tag name"""
+    return _makeTags( tagStr, True )
+
+def withAttribute(*args,**attrDict):
+    """Helper to create a validating parse action to be used with start tags created
+       with C{makeXMLTags} or C{makeHTMLTags}. Use C{withAttribute} to qualify a starting tag
+       with a required attribute value, to avoid false matches on common tags such as
+       C{<TD>} or C{<DIV>}.
+
+       Call C{withAttribute} with a series of attribute names and values. Specify the list
+       of filter attributes names and values as:
+        - keyword arguments, as in C{(align="right")}, or
+        - as an explicit dict with C{**} operator, when an attribute name is also a Python
+          reserved word, as in C{**{"class":"Customer", "align":"right"}}
+        - a list of name-value tuples, as in ( ("ns1:class", "Customer"), ("ns2:align","right") )
+       For attribute names with a namespace prefix, you must use the second form.  Attribute
+       names are matched insensitive to upper/lower case.
+
+       To verify that the attribute exists, but without specifying a value, pass
+       C{withAttribute.ANY_VALUE} as the value.
+       """
+    if args:
+        attrs = args[:]
+    else:
+        attrs = attrDict.items()
+    attrs = [(k,v) for k,v in attrs]
+    def pa(s,l,tokens):
+        for attrName,attrValue in attrs:
+            if attrName not in tokens:
+                raise ParseException(s,l,"no matching attribute " + attrName)
+            if attrValue != withAttribute.ANY_VALUE and tokens[attrName] != attrValue:
+                raise ParseException(s,l,"attribute '%s' has value '%s', must be '%s'" %
+                                            (attrName, tokens[attrName], attrValue))
+    return pa
+withAttribute.ANY_VALUE = object()
+
+opAssoc = _Constants()
+opAssoc.LEFT = object()
+opAssoc.RIGHT = object()
+
+def operatorPrecedence( baseExpr, opList ):
+    """Helper method for constructing grammars of expressions made up of
+       operators working in a precedence hierarchy.  Operators may be unary or
+       binary, left- or right-associative.  Parse actions can also be attached
+       to operator expressions.
+
+       Parameters:
+        - baseExpr - expression representing the most basic element for the nested
+        - opList - list of tuples, one for each operator precedence level in the
+          expression grammar; each tuple is of the form
+          (opExpr, numTerms, rightLeftAssoc, parseAction), where:
+           - opExpr is the pyparsing expression for the operator;
+              may also be a string, which will be converted to a Literal;
+              if numTerms is 3, opExpr is a tuple of two expressions, for the
+              two operators separating the 3 terms
+           - numTerms is the number of terms for this operator (must
+              be 1, 2, or 3)
+           - rightLeftAssoc is the indicator whether the operator is
+              right or left associative, using the pyparsing-defined
+              constants opAssoc.RIGHT and opAssoc.LEFT.
+           - parseAction is the parse action to be associated with
+              expressions matching this operator expression (the
+              parse action tuple member may be omitted)
+    """
+    ret = Forward()
+    lastExpr = baseExpr | ( Suppress('(') + ret + Suppress(')') )
+    for i,operDef in enumerate(opList):
+        opExpr,arity,rightLeftAssoc,pa = (operDef + (None,))[:4]
+        if arity == 3:
+            if opExpr is None or len(opExpr) != 2:
+                raise ValueError("if numterms=3, opExpr must be a tuple or list of two expressions")
+            opExpr1, opExpr2 = opExpr
+        thisExpr = Forward()#.setName("expr%d" % i)
+        if rightLeftAssoc == opAssoc.LEFT:
+            if arity == 1:
+                matchExpr = FollowedBy(lastExpr + opExpr) + Group( lastExpr + OneOrMore( opExpr ) )
+            elif arity == 2:
+                if opExpr is not None:
+                    matchExpr = FollowedBy(lastExpr + opExpr + lastExpr) + Group( lastExpr + OneOrMore( opExpr + lastExpr ) )
+                else:
+                    matchExpr = FollowedBy(lastExpr+lastExpr) + Group( lastExpr + OneOrMore(lastExpr) )
+            elif arity == 3:
+                matchExpr = FollowedBy(lastExpr + opExpr1 + lastExpr + opExpr2 + lastExpr) + \
+                            Group( lastExpr + opExpr1 + lastExpr + opExpr2 + lastExpr )
+            else:
+                raise ValueError("operator must be unary (1), binary (2), or ternary (3)")
+        elif rightLeftAssoc == opAssoc.RIGHT:
+            if arity == 1:
+                # try to avoid LR with this extra test
+                if not isinstance(opExpr, Optional):
+                    opExpr = Optional(opExpr)
+                matchExpr = FollowedBy(opExpr.expr + thisExpr) + Group( opExpr + thisExpr )
+            elif arity == 2:
+                if opExpr is not None:
+                    matchExpr = FollowedBy(lastExpr + opExpr + thisExpr) + Group( lastExpr + OneOrMore( opExpr + thisExpr ) )
+                else:
+                    matchExpr = FollowedBy(lastExpr + thisExpr) + Group( lastExpr + OneOrMore( thisExpr ) )
+            elif arity == 3:
+                matchExpr = FollowedBy(lastExpr + opExpr1 + thisExpr + opExpr2 + thisExpr) + \
+                            Group( lastExpr + opExpr1 + thisExpr + opExpr2 + thisExpr )
+            else:
+                raise ValueError("operator must be unary (1), binary (2), or ternary (3)")
+        else:
+            raise ValueError("operator must indicate right or left associativity")
+        if pa:
+            matchExpr.setParseAction( pa )
+        thisExpr << ( matchExpr | lastExpr )
+        lastExpr = thisExpr
+    ret << lastExpr
+    return ret
+
+dblQuotedString = Regex(r'"(?:[^"\n\r\\]|(?:"")|(?:\\x[0-9a-fA-F]+)|(?:\\.))*"').setName("string enclosed in double quotes")
+sglQuotedString = Regex(r"'(?:[^'\n\r\\]|(?:'')|(?:\\x[0-9a-fA-F]+)|(?:\\.))*'").setName("string enclosed in single quotes")
+quotedString = Regex(r'''(?:"(?:[^"\n\r\\]|(?:"")|(?:\\x[0-9a-fA-F]+)|(?:\\.))*")|(?:'(?:[^'\n\r\\]|(?:'')|(?:\\x[0-9a-fA-F]+)|(?:\\.))*')''').setName("quotedString using single or double quotes")
+unicodeString = Combine(_L('u') + quotedString.copy())
+
+def nestedExpr(opener="(", closer=")", content=None, ignoreExpr=quotedString.copy()):
+    """Helper method for defining nested lists enclosed in opening and closing
+       delimiters ("(" and ")" are the default).
+
+       Parameters:
+        - opener - opening character for a nested list (default="("); can also be a pyparsing expression
+        - closer - closing character for a nested list (default=")"); can also be a pyparsing expression
+        - content - expression for items within the nested lists (default=None)
+        - ignoreExpr - expression for ignoring opening and closing delimiters (default=quotedString)
+
+       If an expression is not provided for the content argument, the nested
+       expression will capture all whitespace-delimited content between delimiters
+       as a list of separate values.
+
+       Use the C{ignoreExpr} argument to define expressions that may contain
+       opening or closing characters that should not be treated as opening
+       or closing characters for nesting, such as quotedString or a comment
+       expression.  Specify multiple expressions using an C{L{Or}} or C{L{MatchFirst}}.
+       The default is L{quotedString}, but if no expressions are to be ignored,
+       then pass C{None} for this argument.
+    """
+    if opener == closer:
+        raise ValueError("opening and closing strings cannot be the same")
+    if content is None:
+        if isinstance(opener,basestring) and isinstance(closer,basestring):
+            if len(opener) == 1 and len(closer)==1:
+                if ignoreExpr is not None:
+                    content = (Combine(OneOrMore(~ignoreExpr +
+                                    CharsNotIn(opener+closer+ParserElement.DEFAULT_WHITE_CHARS,exact=1))
+                                ).setParseAction(lambda t:t[0].strip()))
+                else:
+                    content = (empty.copy()+CharsNotIn(opener+closer+ParserElement.DEFAULT_WHITE_CHARS
+                                ).setParseAction(lambda t:t[0].strip()))
+            else:
+                if ignoreExpr is not None:
+                    content = (Combine(OneOrMore(~ignoreExpr +
+                                    ~Literal(opener) + ~Literal(closer) +
+                                    CharsNotIn(ParserElement.DEFAULT_WHITE_CHARS,exact=1))
+                                ).setParseAction(lambda t:t[0].strip()))
+                else:
+                    content = (Combine(OneOrMore(~Literal(opener) + ~Literal(closer) +
+                                    CharsNotIn(ParserElement.DEFAULT_WHITE_CHARS,exact=1))
+                                ).setParseAction(lambda t:t[0].strip()))
+        else:
+            raise ValueError("opening and closing arguments must be strings if no content expression is given")
+    ret = Forward()
+    if ignoreExpr is not None:
+        ret << Group( Suppress(opener) + ZeroOrMore( ignoreExpr | ret | content ) + Suppress(closer) )
+    else:
+        ret << Group( Suppress(opener) + ZeroOrMore( ret | content )  + Suppress(closer) )
+    return ret
+
+def indentedBlock(blockStatementExpr, indentStack, indent=True):
+    """Helper method for defining space-delimited indentation blocks, such as
+       those used to define block statements in Python source code.
+
+       Parameters:
+        - blockStatementExpr - expression defining syntax of statement that
+            is repeated within the indented block
+        - indentStack - list created by caller to manage indentation stack
+            (multiple statementWithIndentedBlock expressions within a single grammar
+            should share a common indentStack)
+        - indent - boolean indicating whether block must be indented beyond the
+            the current level; set to False for block of left-most statements
+            (default=True)
+
+       A valid block must contain at least one C{blockStatement}.
+    """
+    def checkPeerIndent(s,l,t):
+        if l >= len(s): return
+        curCol = col(l,s)
+        if curCol != indentStack[-1]:
+            if curCol > indentStack[-1]:
+                raise ParseFatalException(s,l,"illegal nesting")
+            raise ParseException(s,l,"not a peer entry")
+
+    def checkSubIndent(s,l,t):
+        curCol = col(l,s)
+        if curCol > indentStack[-1]:
+            indentStack.append( curCol )
+        else:
+            raise ParseException(s,l,"not a subentry")
+
+    def checkUnindent(s,l,t):
+        if l >= len(s): return
+        curCol = col(l,s)
+        if not(indentStack and curCol < indentStack[-1] and curCol <= indentStack[-2]):
+            raise ParseException(s,l,"not an unindent")
+        indentStack.pop()
+
+    NL = OneOrMore(LineEnd().setWhitespaceChars("\t ").suppress())
+    INDENT = Empty() + Empty().setParseAction(checkSubIndent)
+    PEER   = Empty().setParseAction(checkPeerIndent)
+    UNDENT = Empty().setParseAction(checkUnindent)
+    if indent:
+        smExpr = Group( Optional(NL) +
+            #~ FollowedBy(blockStatementExpr) +
+            INDENT + (OneOrMore( PEER + Group(blockStatementExpr) + Optional(NL) )) + UNDENT)
+    else:
+        smExpr = Group( Optional(NL) +
+            (OneOrMore( PEER + Group(blockStatementExpr) + Optional(NL) )) )
+    blockStatementExpr.ignore(_bslash + LineEnd())
+    return smExpr
+
+alphas8bit = srange(r"[\0xc0-\0xd6\0xd8-\0xf6\0xf8-\0xff]")
+punc8bit = srange(r"[\0xa1-\0xbf\0xd7\0xf7]")
+
+anyOpenTag,anyCloseTag = makeHTMLTags(Word(alphas,alphanums+"_:"))
+commonHTMLEntity = Combine(_L("&") + oneOf("gt lt amp nbsp quot").setResultsName("entity") +";").streamline()
+_htmlEntityMap = dict(zip("gt lt amp nbsp quot".split(),'><& "'))
+replaceHTMLEntity = lambda t : t.entity in _htmlEntityMap and _htmlEntityMap[t.entity] or None
+
+# it's easy to get these comment structures wrong - they're very common, so may as well make them available
+cStyleComment = Regex(r"/\*(?:[^*]*\*+)+?/").setName("C style comment")
+
+htmlComment = Regex(r"<!--[\s\S]*?-->")
+restOfLine = Regex(r".*").leaveWhitespace()
+dblSlashComment = Regex(r"\/\/(\\\n|.)*").setName("// comment")
+cppStyleComment = Regex(r"/(?:\*(?:[^*]*\*+)+?/|/[^\n]*(?:\n[^\n]*)*?(?:(?<!\\)|\Z))").setName("C++ style comment")
+
+javaStyleComment = cppStyleComment
+pythonStyleComment = Regex(r"#.*").setName("Python style comment")
+_noncomma = "".join( [ c for c in printables if c != "," ] )
+_commasepitem = Combine(OneOrMore(Word(_noncomma) +
+                                  Optional( Word(" \t") +
+                                            ~Literal(",") + ~LineEnd() ) ) ).streamline().setName("commaItem")
+commaSeparatedList = delimitedList( Optional( quotedString.copy() | _commasepitem, default="") ).setName("commaSeparatedList")
+
+
+if __name__ == "__main__":
+
+    def test( teststring ):
+        try:
+            tokens = simpleSQL.parseString( teststring )
+            tokenlist = tokens.asList()
+            print (teststring + "->"   + str(tokenlist))
+            print ("tokens = "         + str(tokens))
+            print ("tokens.columns = " + str(tokens.columns))
+            print ("tokens.tables = "  + str(tokens.tables))
+            print (tokens.asXML("SQL",True))
+        except ParseBaseException:
+            err = sys.exc_info()[1]
+            print (teststring + "->")
+            print (err.line)
+            print (" "*(err.column-1) + "^")
+            print (err)
+        print()
+
+    selectToken    = CaselessLiteral( "select" )
+    fromToken      = CaselessLiteral( "from" )
+
+    ident          = Word( alphas, alphanums + "_$" )
+    columnName     = delimitedList( ident, ".", combine=True ).setParseAction( upcaseTokens )
+    columnNameList = Group( delimitedList( columnName ) )#.setName("columns")
+    tableName      = delimitedList( ident, ".", combine=True ).setParseAction( upcaseTokens )
+    tableNameList  = Group( delimitedList( tableName ) )#.setName("tables")
+    simpleSQL      = ( selectToken + \
+                     ( '*' | columnNameList ).setResultsName( "columns" ) + \
+                     fromToken + \
+                     tableNameList.setResultsName( "tables" ) )
+
+    test( "SELECT * from XYZZY, ABC" )
+    test( "select * from SYS.XYZZY" )
+    test( "Select A from Sys.dual" )
+    test( "Select AA,BB,CC from Sys.dual" )
+    test( "Select A, B, C from Sys.dual" )
+    test( "Select A, B, C from Sys.dual" )
+    test( "Xelect A, B, C from Sys.dual" )
+    test( "Select A, B, C frox Sys.dual" )
+    test( "Select" )
+    test( "Select ^^^ frox Sys.dual" )
+    test( "Select A, B, C from Sys.dual, Table2   " )
diff --git a/astropy/extern/pytest.py b/astropy/extern/pytest.py
index cda3fd2..39c82f5 100644
--- a/astropy/extern/pytest.py
+++ b/astropy/extern/pytest.py
@@ -1,2414 +1,2598 @@
 #! /usr/bin/env python
 
 sources = """
-eNrsvWuXI1dyIDa7a6+8sLWS7LXs9UrrJMq9mclGoauanIewBMc9zW6pJQ7Zh90tcU+xDGYBWaic
-AjLRmYmuKo2o4+/+Ef7gH+NP/uR/4F/ieN1n3gRQTXJGPsdFdhWQeR9x48aNGxE3bsT/+s+/e/uT
-5M0fb+7Gs1W1HM9mRVm0s9nbf/bmr4fDYQTPlkW5jJ68fBEl8aauFtt5XjdxlJWLKJ5XZbNd03f4
-WObzNl9E74osus7vbqp60aQRNDIYvP3nb/4Ae2jaxdt/8fp//2c/+Umx3lR1GzV3zWAwX2VNE71q
-F0l18RtoI50MIvjB7tfZdd5EbbU5XuXv8lW0uWuvqjJaAxgreJG9y4pVdrHKowy+lFHWtnVxsW3z
-EbWAP9wRDqG9ytcRVL4s6qaNsvk8b5qx6mlAHxb5ZaQwkDT56lJAwR/8CuhZFHN4GU0R9LHAYVde
-5i1CIfVHUZmtc6uVtr4zX/BnDU1BlwQlVKLiukB+O883bfSC3j6r66p2K9dZ0eTREzVqKpEMAdOA
-6AlMyXa1iMqqFSRED5ph9CByu6jzdlsDRgcDqAOw4DSkg7f/2Zs/xAmbV4t8jL/e/uev/92lnrbN
-3cBM4CiqmvEma68Gg4ttsQJcz+p8U0Nb+GcwwN+r4gK+Q4tSYjwDRHATSYwF4lEUS8E4VSTxFDru
-0sRNnW02eR1ldbUFInzJJIFARly2oQkNzucIUHaDRa0pkScMHw0Y5lAeJqq4SwbwFIfH7/rnlspe
-FqscUW4qQCcz9TRUHshzVZR5WflVzIvj6LRbs9uL04MQk0stIXp6fbdRpITEk9m4nUQPaiAihZdR
-mtrEn7/VeK5gudU2lpnODPqmXAS/2E2U+b4mECYsoJsw1ZEK/XWLJCM1MyogI4k2VVEyY6iiptrW
-85wGqmgHfzZMFFhrvKrm2SpR8NtzaIijuCToNuP5VT6/TlIXu0fR119/DSzt7iJHWomusnoBdLwq
-rnNkTtFNXtQL5LjF3KtXlFSgaYHrZlgGltMZksI8g57G280ia/nzebSo8uaXTn0cRQhuH7EbRiTh
-CMZdV7DK2rsEv4+iL6oyV7+HjMZLAKpobOoYWtRwuV2tGK27Z0TW3CueAZmby6qmEWMjanIQbO6U
-J8puT3++rKt1pDiX4nvcgCkDjY4i4uH0ApZcubBARTx1GCRWGqjaApGFJPPUQZUzD+7P0B4b7J5t
-BnyKtql+nH5vfFrtxo3qvCpXd0FkHulVawpKUxlQeQaohflw5kKRkgOFhVU9FNwn62WzcyztdgNT
-flMAsSHwUB6EjbKlHawJjalnFFewbBjbV0AO8y3jAyCg5Y9g2JuBtVr8YckCepfVBMLZRB5AE7DZ
-lu252rme1/C+s3X9nbtzZWrvusTS0VW1WiA8lzNiNQ2JWJez5aq6gG/UBvCBm6tifgW8fFOD+FKA
-/BXNQfABjpK/y1ZbYAOLcb84M+KufKnG2/5o26WC48tZYPfTm5MqE9iUeCtTwFtl7eFYBWXIVpv0
-ILTtUglrTYC8lSNZ+KQEzFiPbmytWlheuDa9nS9It8NhGtzAvCZRYHDBEBxxbf3KZhj64YH8Ymha
-IQ7BNAMfModDIBXIVNP+HH34IVBr460wRSsowS/yWO0vFmbVT4y1QdqvYYltWqC3bBVli0UhH2mW
-IihToBTeDAI4bahpoNbtqlXsW/qHNsJM3JCDQx6A981dknbKyQaY0Ej9CSOMMC5cohzp+jb+bvP5
-7AAEQrH3Qd5/3IW8Hw8VluDNA9yNj8hCCArlSh6z2VmHWcdNdgnYSMqqPK7z+bZuinfQB1D1MS6G
-FJZBjeyNdAPkv7HsQ8Fxm/VYVGNsmeAQCAx0RQOKxDbvA1Bakc3hXnvPqmiYXHEPaiJSzEYR0i0M
-BcHPYD9RO1LTNwYoDzN3dm7mCWvWSyQaw0kUPJ682NEnTKNj3EjKRZJAvZFLGWfw6DxNnYoi+v9N
-fhcQ+lnmg02LN0uWP2BPqeYwibDf5GW0bXDmXjZ386qzJRI8at97XWfz/CKbXz8rAfqu7pZF2BJs
-6jm+RyzALq/qGD0ct7eivMQ9BtniYIcyRw111HT1gtUh+ujtODUrS4rh84atyo7bixnvlJYU8WZ5
-NY4ejz+mffnx+KfRorgEumwiUEFyxlNekhiQI6FbNdfA+gpaBWYvaMYwNBBNt1A3u6i2LUv41WqL
-3GEUgYZmtQCCC+rysM2jQIvsomdLtkfQty3X+YpgmTp1jy3EyAZnFE57BnAlds0jQg7DT1wSiB40
-kweLT1Fl9JtnvcIC4eFpesC2fh9pd1vXuGGardNenlqI74xbb+ydzf/3sd0rPcusE55he9sPKb62
-wOKh/V56HqjHvipGerIrzDPz2Q+DI9npvU0DoVvyIJGSgAuQnPN6ld2RqIxNDp3dqsDlB8JxiG6+
-Mm95SFmxwmYMrnFpK7ElgxZBKVvliwh5Ub12BRb44XV7g8oQgk/vG9ru4RvWEGHcl0g1ewuKooYu
-W955xxq+dIyb6CZxufutxcdmDgZEITXoHwknmeHQp69h63SbEgNGAVwajQ0gAt+OEI40sBH5tiKD
-W8ZgjrbH8li2fTIbRdCctzW5CJlGt0HaUQUcktP8KawWH6Gx969Zw2KR2TKgidJ0fBrBTpohl7B0
-YGUTzW6THTxxFJ24S2Cvdq7pzayi8XuzpEKZA3YqNLR96uZbVNml9QACLcNzuXC3h34j52ykSneZ
-Y52VyzyB1x2TdvIClvEtUc4o+luUquizR2cdMKKH1mYGin2+rUFOK+Zkw2urDezJzUaYgzZaRADU
-2KoluFvnQBXlcoKPQHYBQU7JPtsGzxaiLwD9BJVTl/7MsOQsItwR00B2YqParRABra2qm+gmjxZV
-GQPPyIDZkK2KebmhntQRFQsUkRiLFhYI4x6qNDmcFefjWtjEGMo1aD9J4kkcWMOM38LBqoa4zrPr
-8AZ4RoQ0gdos2HbNYXo8jqx+VSwWebljgSBDwpHYm7cYR/CAB3UlEED0Rgjt5bOZR/YgQr0Tqy42
-52pk6woInm1YxK5QDYPZDorvHUrvbmakWw47EA075G6ffDR3TX4bsLt7dYJ9P4dN0BGHmzYgi3Ug
-vyzt7QR39RCEOdL6OKAhUPX4l7/8pdHV5KzB51OOWbkDhpI6A/vayt/YjMpyUWX14gXOVr3toGUv
-4qTPIUDf0S6HUfQcjcoPapBRcaU9aL4pI/qNAutl6YmnfJo3ojYtwsaHBwpfYi/UaBI06nXD7TuS
-jxT3RR8lgnl6V4J6q6Vw6Rf6bAx0lGzTbFdo/kHOVaESE10Vyys8i8BTVj0IPiPllWTLnkVuHZzi
-32eia7myf5/W1l54qx/fFtmq+PuceeKyeJeX6qy39Ubg7pjALIA14Ilr0l6MohjUnjK/bX1mRwcS
-CbCUABO8uUIaQF0XmD9KP93NVP3cFTloYTSprOBii8GS2NwUf48FIo8om3bsW2ZhAJZslMNCn+yt
-BFUMHc63rTzGFT5l+mHalS+W9CJPYMmstotcV+hTtAwBKMmQz2GRFNVBAO2euqDLeC/ukMjfkYE7
-K++AfNcXRUkSM1Zl3UP2eLJ723IWbAcuP6ITfN4YaONHAHDPaKvji/xYi5+GdAAwEObzeg0tLlzI
-COpsBdtzgxhUrgLSiRpbEAOOXKG2bNYUWjZ1ZQ1qBEmdr6t3LJMAyNuS9p68oUIXRdvwgcoiz1ZO
-c3TygYcXJDUq2ykxOcDbIz28NGw6BGBulaHJJSUx+N9arKnzXtRDV2e0ll1CCqMSPiPozNSa0oSm
-OJOd1ZFYJGfXxpWnlrJqiZwCVm0Vp5ElhekfrKKKjqmg3Xja079QmdX1rbafTIUGe6raGoRTP6wh
-YHvW1zQNmvNY8FH8+9YYr4JnD56vSQEbqOYG17ltCWPbY7OFnSXR7fOOlo7tyljNZqiW9gevYPmB
-jpc0qwK+n6T+IKQXdo6hzQhahIcd4MlKqHkxyEK5sitfltNVtr5YZNHthOb0dqxlxfQ+DAmXyxz2
-0QyIHsfWRLTw/BUP4gwu+ehyW86JAdHqQ5HV2CeVZXdkd/UC2nSXgXQ9Ip4lRjpbliWrIK5aBMey
-4mUwOJe+xMpiTRTJetwCIKXDTgGNGR6pEP/icRIfc5t5QWjgQ0M0TDBanbZgFnIjnKdo1XiXp7us
-8oZaZR6VpJS6CvG8zporIuUdMj+QTEuGAgbAN3Px5KzyzKBLUKUZIfNnXW8cluYvtLjKMHe8NtoL
-z/yuavjDby/Ojk/PbaMTnXZUwNZBp90xVCIELKN4ObGNR85k4YTXuWnTAamqiyXumjDTADRsvyA3
-1gV8Z2mRR2Lqsgm/tijNxgj5i8AQf/udq3KOjHE+L9G7D8+TvEGJW8rCOYSn81mUofJ8gbtvFd1U
-9bWcdntV2Z2FNNsIFPEMRrIEZKxxo5MDtUU+r6DvqiZ3F3Hs2BReQ0zay7wkOBvXD4xo5yp7R/rj
-1SM6vYnyt1uQNds7tyF0zUHAkQdAO668BmwQEMWqeseCXSySzhv0dRA8+gYU6g2tWS3I9ugmRIZM
-GKWZtqwdEjN3xT/cjMndp8lbWfzMn8/OO0a8VXenuXRH0Hm/quZ4uN49ereJg/ytsCTM0SosI0Pv
-l2N1Lnc5luPXGWG93+CNxwoyfBqkADE7ncKH+1d7PFWQhjZdbz27JKXP1uxJNSfFIfvaQI2P5KX1
-BvSJJO4dEUoFvXDHwbHGv0T/SESlcY58ptjfi/KyCntJNuSkCnxyhrZTYO1qXWi9z8zyVb7a0BSX
-2btimWkx2GOrioHMSF9vQbFB00Dcq+ptN1rRYAuur2UcRV/8asyHqcoxUUzodfEOVvQHUfRqe0FD
-hheKBD2LnIOLY3KoUzXW2R1zAD6tIyO/7mhs7wEAa9iUii+mHir9Beeb9AnFliAFbZydno+iJwBU
-jZCGzJ3e0ae4Euu68bpZxszpu0pnAIYw4VsdNLrx3e3hWNSXMWlbYlTMaDRR3LPGWCp0KMUd/ySK
-vYNbwLAAB4C571AMFYMMMfKRtaeret0atqEKv4OUio8ssyG/0lKHOUsxYo6jZu89AXWoMXoA29DF
-Ki+nfAwaJQ5ooPSKRdSAkDr+KHP0ulPLqb4jF7YpyYb9QoYRjchsykcwrgRJcmWsGozFcJo3ym46
-0mZt0xhKza5nqTp1cqd1xJ6C5LM3b5EvmjZEofZUcLsXxG7ewELNVKdaoU+aKkBCUMSzlZLQzyID
-tn2Rg9SEzpVhqZat+DTvTbsw8zBmVX6mQZvpqegQo2lZ88Txb6qiJG2z6bzFP9pK7zAhmZCOcZ9q
-WGvPW1uBFWh1daaJzK5x3hFs0U5lSK+uLQbGBAio2G+5dwmmNApaRfQc0ii8jtQCx+6shYd++UAc
-pFb4q08Wilrqat3oFeOedSrnEHfhjV2dxfKfss1TSozih0EZT0MJhb+Cz2hl/hx2eERKYjeGNmUB
-Ne161kgjjk5l+WPBwG5YbmB+gCe1d6t8OlxV5XLoChLZRUM2PinYXrAWNOWljpoweiDt4iu4WaR0
-18ZboMryZ0077hPuKa8GdUKf1ck/esN6Cp9bDwc0iXBA/0Dz+A9l9Q9oNnxnSSZcytPdeHwTVHhz
-ZbSOElauOgc2EblXbJVR36j3IHE3RLeM2Sl3bfCn9H4ZHLZTLMsKVK6wFlpISygDxtxYHDzoQapx
-JTx8onekL6hq0vXj2sfCkv6Nmlha/2tekjuqqz7PTs6NDatbIU2Fb7rLObVwf7lGxvWcDan54hnv
-7YlF7+ajInr6HaZ5+WtRvfpgUb760HX8XwOnxg0/V2Ag49l7BhfmMGQ4cDWuDn/o4y54SjtyuVva
-NRHCKkWtx4ZvWxa4S/+TgVHgETiVx7w/2x2NRpgOWwi0P4444SjXiudi02Md5y/ZLFDVjTk1OmKb
-hX+gxXc7VtXNbJ3V1zme3gw/5RrYtvX0Wb93/R6OrCmSue6hTJjPSg2TmVr9eIWYt3gMkadXcayp
-7tfziJTu0QggH90CAjy8l0/uzoyGrVIdQMnhv63mXRZL9HXEyeKifAmDjvo815buRTp1ahzwvyPR
-hrs7Pk1/+APkoBeuCxCumD6H212ddwHoA8JaPSf+cvoYFh1jIY2OWZ3Qx+mpJz7RWrX8lGT12sSm
-fDn6HVMcz6PwgalxZOIZW+RCHmnYo8SCUjt7a5/uro7VdQv3PNZn2r+7O0Llhaeo3IVcloDlsm25
-bbPGBh/YkkgWUmMk6nHjVq3aPtvckEjkahiq3dRzkbNEAmRvT7AP3qpswXDmTKty/UO2PCOb8/SY
-ZU1thBlFe3XJS8WUiZsSC1xE242aXtJtxkFdysLfHkc14zzk3b1Bj42048vBg4HiJ3YH1ptPopNJ
-X62H08hiF32eVlaRrpNVoQ4JucmAK32dXxa3+rDB2lEeosNJNHQXe+eYX6GsqwWa01ncBbd5f9fD
-qNOR+MFIkYfGWaxTShMqu7k4BqG5si+Fl70w9qkR8NSu4GHc9AUqJ/alXBJnSmyQvkbS5pT/jIgI
-s5X4rna4CbXpLgvXguI3+7Fp0V8HIVJW4xvCfx/KV2uPW4pjcZ07Ng9bXKksv/78VvUhYPWoreNm
-syraJP6mjC2iJYnHxrctpzwU4M5OJ+7lE6IDZFzc96R/+q0OHkYuLVinZoK9wHmDDZ+HqfBsEeO2
-/MhHoiUGeLelT3YH0GXf1/kdPUVplpAgJxiitF3iJ1Bbog9gZv/nYbfuuMFABWlnSyDjIjSEZboY
-4E1iKt2cYeHz0FJnEyUohLOZOAk2s1kcXvvODA3tCtDRJ+rbp8OuQTfMaZhuX5N7tHFc4cgRaJS/
-yNkBBfj+xV3HEce0QDbRJNVn6iM5mIN2ySwjsR3GuIkBxnpaWRTNcluQ3Exc5l1eo6tQSbIj2h7G
-Yf0TFDAJOeFtqZ5tzukNpx05vVROYef4+YnyRLEMUjsU36Noxw+54o34AtkowrghfWdR7qQ+OD49
-QWqlaB3iEaiB7BnLrsnVtnXsRjf/zTdkjKbm+1rVQQv6X4vBYUMHmvJHMIZA59l6qrRBZHA3dQGS
-cK948zkvfrGZuoxBa2wz41Egwp0r1zhaR2DLYjNlQcYaZNbkgNBeeNYn1xXfl509/5wfXcTpzu+R
-EdA7bvzmdsPI8jk5QVf435BTZX+XjjJ/TFcg+vsxNyB2iH5GLwVGmQxpWxvSjR5Qib0FQS8VzrWh
-TOp4RLOpRVT/wve7l52pR4KyasptOKUueJOq9TwlmigBuyNaW2IF79r0e5e009lKe4Bd502TLcmB
-mdyTkSPwfLiBR/oZvGlBLQU+zWN5Q5+QAdsbuhgWXZ/JH+Mw0R0zY/jxdsNilcM+J1y4x+ZtExda
-vgU2D1HEA6She86tU9eaXhEqpH/vJN+3uhJ3oekaaWIZWU2P7MHKjIfE5Mn3kHY/7oq2HdhsL3H+
-zRKspUvraTNuwa4wpWLpKOPOAaaPshsUJx1f5MjsV9RXlzjEGvLlq57bx0qrD3iZ4g5dbnBvlr2a
-m09DV5iJXsvNINRsz17iagXOFQpzHqwXi3Zt9vmbPm7w0GfasCzyvvuZ6z7mE72hp7F7IPfVFrTA
-dfDaVKdF07vnq2agoF3QKulYgdX5icPcgZbrTNRKB2S+XcN8setJZo65vbtecu6fMCSyFaU2u0Iu
-1eEIdBplG7KD0oKSE2iavTtmfKFBxC/dXIdFCzKnHnpDLhwGMcMPPvgAlq7y7EIndAqSlzTIdUUB
-+Q/RpmooKkQ6POwelnMYlMgQRqZnfSqiN1JfnLJPM0ILAAvZBBxAreJaafDcU1Gtd8wz2HvQ5fQ8
-Mm2ayy7kx5+tsOpk3zlMY7yTzTmIK7mBfgeKBs4POfegIvhJ9FHAAj3G+/2LPIm37eXxL+KuLfOg
-UxcvIkR7w/y0qMZqYH9HUnKiPNG88Dtt1Uq5pLXiVGGz62yTqH4r1hhg5+rAORyKb4K5T3y4d8uD
-xhzoZ2304OTW3O7XHuDkFak8grFZD6rEmHWdTcbYd02gwArdEtjGe5hp3ZjUpaymr8BwSGM5ztmV
-5EFNLjpB8zLTXpdcbWpMJ72RKvqIeuLHZnCXnfO9W1QtNuMr4J4H5XIYRhSnYcsWC3ljBakckV2R
-bGxNvpkOj4edIyhpTRuyu9Xs8waLTsV76WbnaPsIWxla3J50BBUFlbf33sCLDXS8GUVdURnekjIs
-DTqza9hqYGZZB8xRBBrOov6DQLWLBLlyCAtmh7W+DbxL8mZb0Z93nf8dPBObCkmN75baWNe7tw9m
-9+qxq7CRbhc2a2NnYUuFnjIcq+C5a5hQUzcc+nEEeBR059ff3+/6aMtEZBB8ToJ04pYJk4u4ZDjP
-+vlBe8FGjkl4AofsGzLcRShnWiOQrlWb5/10I+7KhpVZ1Q9jZD2AK+VfXh9Ke4BgMgklaksyjaVp
-B9AQiCxCHbAkLY1OnfzxN+VHEtDqegbJQ+xMjXWCbn/tFtTn+OZLoDUGB4/jDWAdnwA2l+DfQ1Fu
-mdB9Fdrvu2/V+GcJBjkh3W4hGLO9F4fP8ICqf3Uzt7yoVgtxjoBmpvDPrXHUxwx4d+8M2Z6VvpHL
-612b0b5hHz7kw4drDyF08HFkc0+9JkbRkE2qPf12majTxT6uaZHK5H7t9xDYPmFeSW14Q5//kRF7
-+E3ZZR+7Yq+GBnt4eQHe4U+OteswTmr7gRpbmMdylBVOGT56wn55/qf00lj+5NOhHOIo0jGrUfmW
-Tqptu5HIqXmGIUhd974jCRKXlVbJddbyHSyMuxHliwJdsSKKkEaxjHXtdbNUepoCVhMbDqBZUpBe
-mmn3riqe2R2fejHVqTX4fTYpbEVLiBJDkjUTsaZqLDuxHkZY292B5GzisLnduUfea4c8hOHYbMSl
-SuUuchjU5FTiAS0bGm1k99xhumyWDw8uM/KjGwaPUyXGoh5utxEyQiJMMJHeMVnPcZ+yIzYpnmTn
-4pSPcOCDx9GniEEMsXRTLHwbqOdkQrX6b5TZM8Ed9B/4CR5gLPc4qz0MDNP+Q0AT7AIwzEA3u7vy
-AfUa2A3JHkTYGwT8wManjq75QupAgtrNr/QJd5Kpex+yR8pNO3aRsNxEt616RezLvS4S6X7aSsIv
-x41+aHyZ8HqtqjjZHV1cl3NMMdaQ7Aub3u2V2L29qe8eWgYQ3Yp3dSwU3LWnLK5f9cB7pQYrGJsc
-NAYpfB/gpcpuqNW0mYNSeaJsSO9HEXwf6CCioAmWqNyHEsVB+LdQeebTwPl4U6lrQKGp2I0qp2U1
-M6rJgbo1Iuksqovf0C2yuXahstFEwpV1gdry0FV+HQYZIbsdVEMbYKXDcu3JOQHlrXuOBFxcrGfY
-WcyunzuLYjnq7aDCB5dUI/DL8vWsOd1VLRdOwBKu6CbpiLvOg25x6Afagn5S3Z64U8BcbjDUUdHQ
-Xp64TrDq55Yht+Z2rJo0kyxngoF9RAFzuxdyb5ZvA9M+GLz9l2/+eLa5w7vz499sQay4Xa/e/sHr
-f/vnP/kJUxcxS3wtwcDRjhz99Rsoefz1rz8XcXFENLdtJJrHX20XDfr4A3qQyBcUtW3JkTZBPqjR
-bj8eDH6VNaBzkacdRZJiIqbF/FUFstDn2c0qvxsPKMBwJ4dN1ahPdW7ltVEf8ZQN9qgjxRcej78m
-gD6Cv7jeAJiLggIK6CWB1u6rOvnZT9OBrAAdS9AugNfFr2q3Gp0vPIl3VeTgPaASmJpocEtO+yrh
-W3LCa/V1i7/GGUJODbM0xuLNJtMO+xgNmkb8dznFRMC9Urk2NtsL2ApUAIuiBJGrWGiwyIG2wcBh
-Vb3gKHzQDE7v6fjECkPCtQoJzLkxDHcxjqK/yimaC3DsbDWnQGUDCUu9uAM5r0C6vqNDiDzDe+yU
-SAW6p5shLTTwGuGEBcTgYAnqD1qZQ1F0/JlET+FTNJlMo6Pbv4j+AX4/od+fwe+zo9vHJ8fw+efP
-n5/z92cnJ/jk+fPnn50Pgl5fVOz0hMudnkDJ5+eD2SpfZqsZ9zqNkpPbk78YRfD7Cf0G/V5KCN6g
-CE0AFHx8gkUQBNFk4RlCgU8RDPOUOsXH3Cu80M3C5M5qJJYzRVogMx+DxJyi2ixUuqowVoV8wThw
-QXcwXJZYdESh4lKcOwf2QVhWrW6iTzhVVnYrMJyHoYPOb1MTtMpG3TmIr06dQbHymqi1rJDoVXT2
-vzxozoG5Ptip2evicco2BKcnwMUiXznQ2A9k7NYTAZA23ouipO95M882OfrsW7oXMMRVskaBxuXu
-qO/C4tGvxsu62m7sa1Sk9n4yJUIIXh7UQzq6fXDy+GtEgRXkoivxh6p9bFdTt3QdrI+BFeBh7WoU
-CR+xximiB+8Hs2yx4AQIyQYQqJM60chQ2qOH6BDDYx0q7VJ2jQI9xUyNsWkuPj5Wew3s1hmJKNNh
-01Z1DmrPAvqeDuEd6vfuhViMOfMuq6dDfqWiKU07YbkxLsZ0OK9zjJdIfR1Dg3KLUzY1ykyEIaQ4
-biE6xuyBl93we0G2yvSADdx/P9TQAgrkyukfuDgxf06fA2vMDIdNNkN31pTjLZ2TwSeZNcEnxTrB
-x2Me21ieKzFWvhpKk9JIPVD382oJ20IipUZeWxYCUr+BzWq7LMp1VmZLTB+WL4sGT8ut5t1hgJDY
-OxBL9uNXKJYxMZkwGzwYMxBc7VZvu+HblhpChoxAg7fLVT5D+Gg2yH6hbC88P8AWb9HcuMrQU3S8
-uUM9fmhxSJlGAA5tYHGSxuemOjoxTPVH084jaCUei+uCSqiGpZRgIPPi3L4MGbiqJVL9SGjLdm/g
-N8jFOC0gBu8GeQlkOhB8nUeYpCSR8qlv2uw0U4KASA5mqoZnKVWXX/iD5zMBiPbcl8Tw1zS5jjHd
-XBegwS4cz1t9s8IUI2eBhkoZ9FSw0rAXvDBuDoHdQyQ1sZ3Z55IwwkVeLOS2x3AyGVpIsVaumteJ
-7aKljG48ei/co66LmgWonsnJyC6dBpCllHkSFMd6ZOF2p8OxGOBNV54Bnoox3AC2+w4l7Klah4wL
-oNLFluX8mNyMzfVxy4+BQQxdFDQDwe7UYNyLgvxwhjTQN2M2kTycRqedykgZyFh66h+JYVuPa4yy
-OB4ieL4P1uGyNaPDW2x/SFfTuLpKrBo4vpIxdoQdnkGh7UTM61Nu+lju9JFatuGISdsSVid5qa3u
-hqFo/WqZEEL6pYomx8NLvPegxq5cNbyTRIADCjKYCp8aTIJMng67FdWoAxgOgW5dbeq/zZPEsB1S
-wK26DqnC4jVC7GCOUksyfJptgJUCTkB7D2VZteZUavf4QGRLa0silAAcID+3+fo4fhhu1B8dNJJ4
-oqdydAnhRJhbkLznFYh88/bHJHMbcpcGQnO695TOuLyD1MbQo61AU5DXsfDynYNXS+d3Mnjd2Q84
-eGmzM3hnIfujJ8zs5IsO3FL8vaB2F3uTY8C195mwPRP1ngy1d15U1bOYWo3PD5ogZ8CK00Yum9sV
-BlydzZqjYwSNQ02zS4mN/Y6jli7r+Ca84tFNomGA3zntmy9nfzE5f99dyDmD9WHeh0W8tALKDZsa
-scXhvhoK3wb4QFiaQ9aGqBT1lmQ9zJjOsO8gORkcCxEdi7C8pWhs6DmHtq3hBGOrUhghXgyP2jyr
-F9VNF2r2unVkT4FhsGOHYJHHL5ivDDy8JwTWxP6+vEF9oAe1EyJmH6H2wgeUdl21X+wakEzne43I
-7ksRsCrnU4Zw3b1Ugcb+HZRxb1yHJsyH3d/M3w/b/q7YhwmVX8XeR/Jb8mLzNxKbp2slO2szPgi0
-LEuq/g59ZdBlOmHlxS3DUGKnI8OddYoYejvsYe+WFsRD72FHXES1OUy7KGskpS8yZhXHgx91/ES3
-RZvPqOAMtSf0vIQ/Y/yV9DZ8CSp8c+W2jJNSUDidbTMCLZ9yFfIhkkuxcjR10G0Jo7xLLbQrzpsx
-EnRiq/cg3N7EI8qbiOb7aedmRSANhjEMHNyaQZ7grdqE0OaWwoezRb4iOvQrHofnwaj627WyOTg6
-pC1yD3ybifjCxp/8Ek1TguXp8HR8MjSDGtKghr/81MKSW99QPYGXdDkLvQvo50OPdHlhTq1FOupo
-YMBJpASPyi2BXEJeC8PwVH+EZKqwFTALDB+MP7pEIcGfFFM2HSvLtdyePEm7qJmvqia0NJSpedZs
-16AM60ir8pi5W26zLP8VY32G3pfDYzTSqWDkC7IwYu9K0HGoFYB8+1+8+SN0J7Fum7z9V68f/8FP
-ftI5pIR1N1KmsMFATvxV1AOS9AYSY4FXnbk/U99xE0mMBWLKqUEFTSzpV9A5uoYldpgGyzWgkQjM
-eJRGig2FceDI/MWaE5ioHM+U5gRT+UhZa11RTOSSEnQ0blCU0kRLafj+ziJabGsVhBr5kRt/2ktN
-fNuTeomOw9EYnrtjG4uXt1T27sZ5QU9vR5wX6YA+7HlxG7ZLSXppeECNf+j53XWu3R5Fr2sOp/su
-K4vVKuMkyhyT6TrnJLI0G1aq7cKK/OvfZMOuE93zD56sbI7u9Do+c3/cbHws8Zm1FR6rxipGMxLr
-trwuQfSN0/1Xk1U3oo3nwVvIgRHdLw6b1YsGLnScFn9y9qBBTWeYKpJmtROWxDmGhRYnG5i2k9sH
-t5/GyCCCvbG6p/oFmjEX7XQ4a7pxd7tTc1QBT9LoU3G1zW5xpQYu6pCR+hbNxIld8vij9NGjx13d
-4jemvFv8uEjDsfPQMxd2w3g8Hse4K3KE4vT4N55OaW5WUlJg60oeBm6iXqaPPz7pujFlxISOiT2h
-XQ5qEu5VPlKVuILP7CS1GDXyXEJJqpuQ2veJ0882ea0vQDbRTcFBcnRMXEm2Qd4rmQS0cCNB0bqN
-1VBiyV2BLg0tLGY+SJ+jk0RbRSXwnVpSrVocEjguojmSwD0qjw0teUrLJcEdOfUGjRO53iO1Q6ga
-lAdD+XKQRzbomdHj8c8w5YbLcI9giO+K/MYajMpMxTkgZSvSW0lqHhM9MNqnata8t7hh9LyjgP/w
-8vRnJ/apVaMtbGzWfzt486fKNXM803561Wrx9r98/X8+69tSxdVqQM5C4kJQK9dOOpgeRRnG8dnc
-YcswWQPHC3Sse1KVfsW80w+JPtOheDerjDOfDQYoFrZXMEvLq/zW27iJUenwqCxp9Z7H4dFRR626
-nbvx8iVWQT9TpgIl+xfhH9X738LEdwKy4sPoAuMjU6Ex73UvLqOnsvdYQgOWpTxuZfQU3Tz4PB1L
-berq9k6zQpMqhhKq8tNbcemRWPK6USzC1SW6z1NksLKcWDy82EKj0YcKlA+x2lMrFZwEtYrq7Qqg
-oSSt2Bms0XdVsaAT3a3OwsMeSSCY48AZChJOuvAk7uifUjwrQQNjmzJw8PACLd0KMp9YKTFws8/b
-q2rBY72klS2pcrhX5BnZtq1QqGIfqZocpEpsD5v7klaSlaqaMmU0OQf98vNvqBTWUWV1gotBaNDG
-IYqABi0yX2r6iBzeAQFT9HAdlZ/aY2QQRwOShhrAbzUgggVsy8I5EGmu+V13KmczLAvNUOAtnZ2X
-WmLvAqAhLnSd30E5xirA/CudVGvEDJE6gpatzjlmFDVGd1qQeRSXxdyd7+jmCrQNAwoGqiWE+7Ms
-K6asoP78yjRC4dhgghUgWQ1vAWFzylBEmwuhkDJXD8SRVRMTBuXEgMrAq7M1RR97mpCzL29XnNlw
-VVXXHNdUd8sNEfzYgwZ/GiWwT+MFtQokVvjIDqsU2A2dkdpoUeUN5jXGSzqY31HcDqUHDLoVbrHA
-29zYoE43UUb0goczgs8KR7gT3lHGZlI7bVw+lQ0R0QZLtikWec1eixe5pJKiaVWrakUmGLz0urpj
-DAfJS6JoLWoSEYC8spL3ooy3DMGWzalGtluiO9kjbKF6h0FcFixeaBLkMb7KJRaZzFok8nxeLnSM
-/XW12KooeOTMih+oIS+bl41p515diU+TuqpaAo0wLYoA/Pnw+mbhXwFCSwuLR53a3s6hFjBV8F/p
-SlRAfxtYcRZNqA6NGmtz6kaFdkJO6MoaG2fQwnkgHnQgClFPU0wLanm4iRL7czIi/zJ3quCLc7fO
-YrMdPo4uLsCdrgrg0LDi7whNzIFx67BbqXNaXxyPV6rzNMUNxx910SvgKj3Lni8B0h6Fwf+OvMZS
-3eDNboHcF00TlM9spDlN7gX19B3e3UyWVghPVRDGsa4rd0a6Go+K++kQAnIkJLZg3E5RnqHOUypI
-IoWBGmGVuk/Hao2dd23y2EhvnCt+7aPUDtDhE14ovacF1JRyAycYY8k8TbrrLnXvMXtjm4QCrVkB
-p8yAJahl4KjQlEHGY9WwHJmuqmKeW2F5LErxacQ/MZG6/WnZneG6B0GoYEr9FI/aToOtSImzk/Od
-sRc5fTFvLmQxR34tdUPNUgpVyuJGmNOAjIBfHx58J37QJA/qNNaWRGe4linAXp7K5dCjjrmOq4uk
-QC/IJxT+QE1TEFmwexsVbwBoOaX02+WWPNKQvNmm4sA8hdL6VgIF8wFFukVJMSFpWasbT1gbg20g
-z0k5UTr2JSmlbZ0p+XisdFZL1dKxLxSqi0bdI1NZaDGGexfnHBXFJEV6p++8+hWOQC5ZrY4pcA9d
-YmHbEGVO47MWArvp39CwJN3Va8fPdKXEnUy//Fjf1Z5G8ScI3qdxaGtjVr2v8LwiJVQ0XQuKp/BE
-Z9NIsOMUeTA+TtIwB+Wg+JL/sWtktDXf+xoY2SDy3HJKSv0AGgKEx2tFL7bJovMIc3gT6Nq+LM3Z
-ZuJteU8q0Akr7kEEvyZpL+HgjvjgVbtukzN7Rs/TfSQBoO6eZO7l8AmWeb3N57PfycRqpJfAMm3z
-SQ+XDBhaEn+STd4ZvPuUOHxHWrQ2MkQ9lnO4B4e+DBOBDvgbP6hNoPEkVYaK5aq6oAfIytnoYqdk
-7dCESsdAmNe5Vc36UtkKfti5CDJA6J2hP3Do/98e6u4twhkrSUvWVKM+ax47aAicyFoJQVwnz3/K
-CNqxGXLa+S/0qFIGjosFI9DqJeU3tYtvEy3JSn6KdzHrgxazFD1oJMKPXdFEwVOnTrngIMkComxu
-nAj3sQ5vUW2a3lvCDE/Mm0/IEfmIzxfm21ayYuH9RrKFGZmjCWYcQMXTISB7mwu7JrtxSNWIH3dQ
-Q0+7m9LjIG565hYje9D/w54zMUS1qTHq4Nfl9U5vas0OZzOV03a2yi9b7NB6VBfLqxa7100fkBXK
-ET06a/JQ71CiVwe2KY2YW36/Vmg4U8aNkmYCh6M7mMT9Dkl3SWjWqiKA1AJ+Ui4OWbxQ7NCFq0jA
-u/pDMYxuKRGFOfJogmJYl7YD8lYfZdsQ6KziHu0GA2QJBVmzPti7gq3CgRXsrt7AkosTPIeN+XCS
-7/LY4GOgnDiN1VR9WR8yU1/W//9E/SiTBGjZNUeDIzRwvCmz+s4+7ZlOB9d5vslWmD2V8Ezm/0ZZ
-guHTBrN94U3fMvqtHM2A6Au0Bj+TKEaqs5gKfpCE9VjuRfkOs4FDueQfvVKpFPtuXIAWRCnSBtp3
-kiF9UqMneoiqupTFNgTrQmaXvuzhTM3H9ADiCWzueykoMFmmU339Mg4j734/uwnzfhuTgfH9thX8
-YG9Ov/tNZcB2XiFrtXgNRaWyGn5VBJbDYfT/ZLEQ+k98meFhZ49NrQXxanvRV/F4Z8Vfb1d9FT/c
-WfGz4l1fxUe7e6x6x/hgZ8WX1U1e94DaD2uYD/Ac/V4YAQEcZAT4Ju2U7WUENMxwS4yBbun7MBVr
-xe5dsEG2g8DHIxlwPxs5uD0aATQoI7Ha+33yJRKaaZ6+v9DMI/unxd+slWJMWU+z1QojPh6kAUtZ
-19pRVfvNOtaJkIUq8TDCFtL4+xov7rcr+lBMbV3292wGEV+qADMghy2nXJAN9MvG7zim0G/txXhZ
-xhNui4f/XWD+nOJJ7Mja2Y6wm3hKa6Y+Y4P03/AVyIAsK5cjkdxci592BqdXCMsBF5BMa538L1kH
-v5m7SrNe/iqJeD2sPFigjQ6PCxHFbg18cibVzmkAYalfwRtMB2fNx8OpBgJk91EcMnV0NJOsn233
-XN/SncUPmumDZkRGSIFxpCBID+qcW/Aa6OH7JjFAxinWPKOeehxeIfp1Gq51z2nFevHOyTQtBybV
-wuGHqIT1T1sQa1THAj00gQpdix58LfYgbNGDscX7ogydgXajbHEwzt4LaVRpsQdtYfth8qBJu9ZD
-5rO25RCvGARU6UBuxzHAxNelAfh0Z75zNzSLhYZde+M+6yHI0y5D+rFPUsXMRDizzkKYfFSiVGW7
-J9khZLqv9WC656l7hN0YY7z/VqI8f1N+R1ynBllzFAUO9FgI+ktxcDpABpKiv5tTgOAGTKWZm/Ku
-C+DsPh7bSyQHKee/kzP4zlzKSJOu+d4ZfGqdpRfsRal95tDxJm+MD7GSR0bsgcyRwxuKEgpjbu27
-T3oCklgdsHi4GuGZAMarmc2GfH4XBwRROdf0Z1HV7MzljqM8HIa+bKanU4nF3Yza95vtH3a6fVid
-PDtk57Te/544ABl6vsqPC71K2aEDoNuuVsYFg2w/6tCBrmkcdO5AJQ/xAaFgHkFmgW9Sp1yQWRxF
-TbHerIrLuyjm+yWsc0Q3V0DX8nmKntKxPQcJN2hwYsf4iKkWYFPV5rDDndu4Tn2z5SHy/bSbfnG8
-Tu09Ojv96eT48bk1Mkq4Zl9UzJpIj/ITq6rlteJyPepjv2OPahNlCB+swc6jFKuD9ICMqMwJg9d+
-fvfmAk3VxbI8kKqh5CFU/f23wL1nJqFZBCLHPzCJ/r4R8rk6BvgVcekoxRmNca2uSrDpsnEQYJRy
-NgSTv0/XXm8x1XW12O2mBV2cu+V3OWYd4JQFLYR8sgLbiu2g9XsWCYQgPyuaeVYfdL4rRf/pkmSH
-DtUtepz2AwaI5Q4ZHTnbQtldp5/0voMBeJh2io2xJxk/uwRzBAMdD0b17Y2Wuh13nO90bFTrYfBM
-N6IUJEU5oTQk/vp1LRZeNXbjxcuKTbuotq1KFseho1AiIBUPiX1uuT/n6sKja5agMc+vckz7LNim
-yLkybHVY2zXa8GO+NYkXPOg7hlv3C6i0Fc+pgEVrQqjkwYydx0iMcqVdtinLuMbCqOsGzGWD9kSi
-R2NPdPhB0LC4e6130qc6d0/peecG6Zml7naoKjDPwW3XMlz66jVTQF7XigLMrVuJfBQpauihVqT5
-o/f/AdnyycsX0aOIEhFGmwqEmAYevn+DRI1aUtUSvZxZNVfVdsWhrSSFw0QuHeK+0CEBISxpI0be
-H6cWTRyx1DVcVq00AUuSPwy6xl2BQWL34N2Fhkn6NXxMJ4eTvUOKcnfN4kLfh8bUbSafzO5F2hZB
-Sq6HTqpdE76RUIh5sw3rs2ap44acDBOfSEd0H5nCohXwN8OLWiSwIKfvZv4eUo/s2Ye3XPNFgUHI
-ibfhzfU2WhScNoQioUbRq+1yiVovZsMNtYfX21GJFo5jXUy4yC+rOlfCEr6ULBzHx2W1zpbFPB2G
-1rGMla9WSK6ZdbNM3HziLnXJu+4lIpXl3RCUm2nZSTd+JEQqiU2hX049mrQXdoFd1HmkwtrrRch5
-GNUeSdN/YaUy17Rwpsx7xu7X1tDzWKuYJrM2Frvl7BveUofygdVOF3UH4StYt5hB2L5OyBIXLktS
-N5Kh7kWmJkcCKVXQiwc17Ze3o9QJAH6r5+57igIUdYU3XzsiuOS9cxRTinENWqUdxQrLYTwxTFoW
-RZ98ohxA1X6e9sgJ2IxkNKe8ezxz+W3LpuCJaceTE3xzMpqboJqjNrsK3UStj9jR929ZL71tz05/
-JhFM1M0veCjSFgp6v2O5Y/d2EdopfkSW7YsFg0FBN5JpNtB0E+NlwKKczeKJxByRq9Am7MVl0r3w
-8VP9dhl4+5F+e5UEwkTFFGKF9TCWDYfQR/QhtoUw/VT4nrwjbpuk3YfJpfj8Yz1gnidemUtubqnr
-Yoydj+0SBb7vtI3nkPCQKp+4ryzG8PjhRw8/BtpaVVmLDTAFwrQNifW49W7VuEwpIWoZHdBFVW2a
-WKpxCdi8RhFG9D4dRY/Dbxh4uysMCnSGLcK4z2kMH7uwxFf5alXFZ/ieSODK6TVebq/5PPaKsADv
-3v5Xb/41Bl+hnAB0Y+DtH77+P9aUZWpA3ykDB+7oK2LFzHAo95MbS21EFkGMz4k3oDEMopUbSgd5
-UY3hc9hA16jvFcAbyo8eC70DE2nxzhEFcKUXQ6SARGcVo5BWSObxiG13hIm4bK0IbFA0lHTBv05e
-Bi8pure6qwbHJY4v0bBpZ5T/0Wxqvclo7Zo9mWh1ig8rTKlVi/I1mK+mv+qmlMhn3s1vRmXIkPBF
-1b5Qk5gvZIP7+uuvI8Zx6gtvmxtjzeTU9cQZKXDhmOgtX1AYtgRKoiFlc7MtFmJJhk+du/3UiLoK
-TAOg9BLoQ9jeJfSA84So30MuVFHuyquhhW5ObOMN3wpXxalwyDaE5mqMWKhDL/3wmFrWmwMxBSU5
-L89SY2q5D1M6rY/CFD3QpP6yaorbl5jIg5fTGD9jBjeL8OdXgEkhTYy4NeJGca3OpyceCudXnOYL
-cd9cFRsM/GFCe1HALmLMlIvHwZ77LlpndxjwQ2K6cEiZDEN5XuCkusZcfoXqq1z5n+P+jcJbBx7P
-hWi+rRsKPTK2R6E/AyGyPIvAFYsE/xh8L9VbghheC26d6ANeNm6dMYZjQcG2gRkZ5tNVtr5YZNHt
-JLrlSUfx6RqjZ05Cl4a8QuFbQmEqqpoxzSiJr7ALjyJaeA4lHVKT1o9d2YrbmGEssusdS4xPB2F1
-ZcC11xfVqpijyHntLjQp3AuN6mikXFtqzsutIVlf4+u2UmlJVguPZ1OSWlwDkkQKs9cRIEi3KsQM
-U5YNWC9EAg1uNNKXhSwHMBi2A5tYybKLplqBXjg99RcWZ73y8GXCD/ECY7wmZBLhlH/OKNIOI1P9
-uRTUOz6BmgfFuoWP/H73J4pPJpcFmd0kgSTRRzwmnhUjQzRR/Cim6FWrm+wOo5VxE9Sqt6pXRhV0
-YslId0A3K8A7VvSvy68WfFwotuhwMQ7tT0VhHNuyFR+pfOO52WY1ZmpUCY3yDetFSTweg/CRfliC
-JJBoaEeR56W7fxK4gw71i/5o8yzRbty9uavTMnsH2rGIj/jyNNLbNNARt3n22FGu8Jnu2+WITu9q
-v+v2LtuK273awPTmh/1zsx4A9HAweP7qV0xn3DoLh7iv6L0OBUJvuzMZtwDJtB9yM1YsSwkrVdUF
-bexsQ7jM5hQbUoIBcyguWm5MuSg8cMYYi6mtMq6vY+660R0l/AZh69dFQyFZWIzgZ5xy2mOrHNO0
-QmYpEYZTcdiocw4BuJamkOvOZggY6HaNDlwF5Mn5veCDBcZTor26UfKB+p5OHEd/9OhrfX7ff0hr
-R4nBmhQiKnQ+25eseGfzRhrWbZvQ36CoEKwhD0sVcZeX3bPPv/zy5f1bX/U03zNoB42Log4hUVWF
-SuNXsxevPnvxVWLaSdLxmkwGTlM4wYe09dWzv9zbFqhjTdvsas1qwK0akgP4EGwv0nxIP//ibxLg
-uBZ8dhQ1ClaMbdnmHLU8XnAqYgxsiitUh6XlRUo8QXGhsYGfnkvgOVq1eFdP5FkQHDHcH84YcIWq
-tgTIFxSFTwxIHEbPrnFT1de4NeuaFMcwu85L0wToEBJE2oFNb37zrK4xBJ7evjnRpVsflNuKG0EL
-vFxKz6wtVbE0CkRITi53ghpjTcOYd7cZFGpQHbJqjaM3DWYkvgFGIymJM/wKnHXTI027pmeVajKk
-dlg1aGBWNLgpBinqZSmORkybqNGU1Q5pu7QZuuAQjp4+3Q23h/GU/JMzN7Wm5g/SHXNVwM/8ZpF4
-CVE66LBjzqLgwbbidF/rNDygBUrJ2MnRiLIaiQY7I1Kz9vq3KCGJ0oqkT3ElNxSchbRqjx6Hu2+H
-DMkxtTzO15v2TgKgN0guep+19OHu2as9ULa274v4d5U1V70hu/Bl0qMpzGb5W22AoR3ctrmcyqmC
-51n5WB5z+b32AW7mdLzCa3oes+O2HnfeqXGeIuU3j12+1wuwSiaKtlCm46mUsRtYtfsa0GPGxNFm
-oLoNZAp6o+m2Yil8pIwDYmIqE8NjDLlNNERRVZG7cOpeEPSxtbiXh3hSIzVIK8dYIb0Fo6JW+yvF
-DKnj+K8xFtzvfIfLsDnIuqAUHZEoxjGHNNoOU3Q7S0wNQzXj6OP2mCyNfF29MxkD59PTkSS1mkla
-Eftc20wd1sKobjgxsJTNlpXQBSXznQLBsb0DNNexgxu7H2WXGUk6E0xDT7mboSd7UywknLtuCLZg
-bmjRSxesV5JZBJrBIQatIyGrjDiuVag0yqgrtmMQ/yMpHoVrmOVFdRMM4xIkAYdjz69AdEk+/vgX
-MgUpdFnNW9yNT35+cjI4zHyjUv9cbdtiNa7XiHlXAwzf2HOn2/l2yLWlfhvMGpB9uA1gF6ZcLO1C
-zw6LEE5erz1IDt31RjCiPYFz2K0XPx2CPHK1La8pk8FPH3/8+Be/CHOzq/x2USzFqxGbYLsL5zHA
-eNEdm3FHUQlqLqIiY4uYGiCjIMMhvcjSBIP2QTUsOgZprrLTYZgwTTkq1t3O2bNyNmPIYL9QNVyi
-wadW5hCoZVCbJh3PxsTV60ZRWLMNiyWfVRjdGiP5RVfwDzOpiy/Fg5o6HUYPNJgjO86qUjkoWVVc
-X8Q7HDeZMZ0GAoNssZ1LMj4mmlzSvtBOUDyMeksoGWt6CuiNVGC7WWRtnkBj1nAw8dHK9zftJldC
-GZ2JHUNK95kVYcrYzi6prnSYa1ezUErBZbUCUQVZtrpemdXLLTv0U1N3eD+tqLbcAHrbtc1kMvCG
-l00eNdU6f4RlHrXVo+wRLR08p3cL3t7uEDMpKningvfjVCjq4D1Y/8eqi9L4wXUUm9rW+cH1VGVa
-JW1wkwNdpKuRuCZOQx6ElJEa6kgPYOSANWJ3CW4Elu/FHZ64eDLHkNtSTem6fkNDR4yK1auYwjvf
-dDaC2K4vhSicDjQVrBPmB0UJ3LdY6PD/7InC7jXXN7s2ow06FF3fjJu8laj0iQuTi6uDsh611OQZ
-jeE8xLrDQc9ZV22aA7ZicvNtyZCBDMb3kRnHPcdBDFs8Zvd9d4EhxHrUeJkUUMOlnDstsZCAmiwF
-A1ZXr879YOH2O7ym6izWQJxwdz5UVU3JZha8kk2+iUdR1xQP6yWgLWvt2Ol8+CBR3TQPEmwG/uj5
-b3ySEh6OEfaNXmVWkSR3hI8e121yMp2QwHCDFpoYC8VibPIPwbxgA8RK9akCD0x8uMzgB9ZtYiwM
-bLXFIJCkxGNnyutrFKeRpYPTbV+O1StXfx0XeJWWPRiSgG9TAInRFMddKpS7xDSAs5NzX+50mpBp
-723EPVPhJvGmb3qINKtmlN3AoaZ9RTg0Ir02wktLYAozin4wlOuRqjeuMWcHLeFw2cuIHJOOTye9
-24nDk2XNm+9xHGYNveDtaxJzh5m95ayYnPdBrnHpcNj+XhWx9DLgMOEg393bKBRK3wMR/XsPUlFw
-A3LBNkkHDL8g+hX5zGT+8NIQOsnUkHMQN0O/BxoQpQxaraIYq8WoNzimTJSPYeGDbDZWh77TU1TF
-t3hohLezEHzyssIY9lRE8sYQA5WbW8hJ8Cip1+wcMNR0GYVtuTOnAYo920zNMsVurFNUu5ZwtzN2
-ZTDeFfj83IaFMYpm2CQG6GGj8O0CWLegrIDoMZJQDjzuID0+HUX8L+yNofaUooGmVa2z4rxnI7ZG
-q4v2FZQB6oIPT3tWmBuvkALI1GTxl6oTP8ZEROFOxDW6c3a9S08/QloDzWtbar8JPqHPKX2fNpOM
-u7zb6zZ+FOB0ppCOcfWINvYuiFBo0qd4qZ1RX5vFBnZPyEMkss1gx2vo0JPG+TIYHoMcKnB0rCQh
-KULnU6arIfk0ruMedlBSWVjHZKXz/EGw7n18aqAlz5gUeedtmN1EHVOOsM+pyBSgv4eO3rC8ZSic
-V2WLjGiEDh5NccHWNRBNVMowhhueUWJEl2hBMtG1sL8dxkD7Bk2x8l31WX1eYfZVPn96/sWv8Wwc
-JCR4nPbLXrYMtMMJiFDkWaG8tKxXxWqxrVeKgmgX6O5xBR3k6sNETIdQrBJVOQ2dg+mQLbqU5yKK
-mKMcNTXeXGmctPOhDQrNGztcuVR+YZy8bbnI69Ud5QUjmzEfMAboT0UVwhNnSjNpXKMoAXh/f5SW
-i60VstNSEnCV8w+X2r4OqQvbKrjRqabFowYzPgEhBs3iWJz3XzwLpgpju0PLf1uaGUXkACrfjnFF
-MYvabiht9aLPjo1InJ52DdjSq2XsDpCCdj+S0lrQGIflKYEbS3ww5TpeqorNHdm78oWDrV0aNh8+
-zJNN2n9k67oyHuQtWTsaleVZIzz3Vny3urGuyX8rv7n10CJVw2XHgGHi3ClsJpjfWVC+1zHztGe/
-oUZtF8Bb7cqYpCHlwWo4SBKhKbodUT97musjHg2mO2LrRAkJyKUDf7kSo9Q2RGu13NPJU/IxuGdc
-0qcF0mK73qiDSMyjd1GUHS/KTTG/NnypKAEmgg1PDZGX2IB55uKbnebinYc13OsYARTYLgm8+9ty
-19dm7/0woCOIOfc/6BtPmHBRb75I6iAocK4mFIddp1ZnL/LSkfdOD0HEU7JJOxvJxoDOl4UZ9EXW
-ZkqwufEFGypIRcwEdfxW4wuyQWETwVxptiNF0VzctXmTYJPpIRZF4/iAWT6bJqL6wz3nWt1u8b5Z
-X6/3h5MQiVhhpwMqdQ9Dg1S1O2wrDeGIbs8stTktL+cVqpVJ7/nJ2gma2Q18IbfDXTAPpfMZsx0g
-rY7bGedZVaBo1jxwfIa4CJfZr37qKhZT9NVDKWADlu44fT45xA+S87PTkg4Hs9WuiM++fvHqdUgT
-w1uwKFQvCor5QGLXI2hQOMHCTpXaXuEu80iIehxoDQ0FqwzWVaF82EiKQRYSIuA9Yw4HKwl67sgu
-c4gZhIuyY1vGmv6xMDZi5eysGCUXOoOwSpOsBR3CUjrGIdxVW7Hb4B0S/yyL7JB0Czj2T8BKLW5y
-guB6rrPc2o4R/QaSnezWs1hAewGLhRagwkQZOO+wJJlwHZsz7RM4NmpjjFO9gEPgWZpEwEkYp/Qr
-o8o2IqPzhfSgpPBKtTLa4SJPlwkd/cvWYQ8CZPWDQLLaDUqTt0bhGbHyE1KjoVxA6WGHA6U080ZJ
-uyO1Eyu9UbeUWAmYU0PFOMVxw51jHewMj9XFYxUfW26xxjlVYjuhKZACK+DZnelZX8Vc5KiPIvfs
-09Z1z90AvfvEwy1W7dgs8OH+vF33azRBEyC33A3VpDn1iy/+9snnP0RvErgQaSM1/Vq38gLO4tYN
-PMs3q2KPNsvzucJcn74Hs3vUvFp0r88cdEFshzuQ6d25LLZis1ivxm9ZvG+uivkVGZFgl2JfOvs6
-VDPu0/zNIJQ9zuk4tDSzQwwR2ZwExHubIDLXBLEv2SxnY5N8s46N3GqiaQMt2JYaDjyBPeWNuoyt
-oH65B2qvt83d5nqp0Qf875qiCYdYl6WKvLxrr/COSja/zpa5PsTA5NlkM0KrtbtjcbNj8qqXL9oa
-pnPaY9M4GwPPx0PoeruBrXTRCPE0Lbq7axLKSn39ery569gbb65gYzPnhcjWaAzH7BCFERxcQeor
-E4WFLNSR4InOdskhCDkwhpBBkaVHNJAqXoR1HKqItsokQqeXSY1hE5qcw5V0PehdtAVVEUf83WNi
-wJuF27xPoSkag5lEmtX2pkOz2blQkYAUW7OEAgdB2nfxVeOPW7jfQBS75kYOc8jwBoqqh6B9p/OX
-B57Xs1nasGBxCwUVzV5yrlVZjokSl+WilB59ILER4M3ZybmXP1uiUUkXcmlUFR8CK+9E/+KzrpJi
-tZ5AAWdXQu9Nc26x85L4BhcBJ0Z0r4nzqQWseLKU0pGjS9Rlmy/Rm1rtXqCqk8Iq3uRVc6zOYqkJ
-T9fxrogDGCSm7L0N3vU95yG6FxaDoYBoIA/qaL1tiANkpRoEBcOhdtL3uzketoXu2KDJOVPd/Xa1
-+ENqiQ3OOxbS1w713OvtYCQqm1Cvz6WsLYKvUBJP5tZQp+MtQ6Lf+PMo/SjeNnL3BGHySNOy5XT4
-OxSBQW3nrEvO56D9YXGJ1UN7j1PnNSaZ55d0bQrmcrNtH2G3AOx2QxMEa4TLNDsJyVKfg/RjhMov
-vnz2xWvPmq0WLgi3smgZZ8ORa9zo2Uy6yJsMwjyUNxq936eB/UWpwTiq3j3GoYJd9yo9biftG921
-a/WCIq6Xsqpj3Fbs0CBn5wFDf7bOG/s8N79tp3GsLosfAIRqgf52HLJ6PGIa9qHDT+iERP7aaqfr
-8dnm9jfVJuAsrKYUWhkPzaHiQS7+RyhOK9GsmYNyPxJhaZ1d58hs5fA1/yFn17Xi7RoR02GfS23H
-UV0qejMPYsSims9m8XmHjp2jMWcigPqHvedX2PFRdANSHfml03pG95n2irxyGny1xrRVfW5FVJmu
-ZtJUbdCip6YBAy63FSzt+TUpctS6P246ap1SUGN1sTvAJ/HF2fHHk3PsK4lhTHPKt7G5q0Ieo067
-VHfiO8nRQZK8taKT/08YAQ2VrUOb/YtzTEKCcl0P2KZxffUp30AdZ4LCNnZ3Uj/YO6m9Q398Pjjg
-/kbTWLSqb8dJM3tsvMTkd7TJma6CIncTFDR5FyFQQtEE9AIR8CQ5+CBM4zvMijvv+Ju98Ew6vKdX
-NC2Pq4wuos1BfKrWkYZ8UaGC1eTbRSUKWc8FFid8KsfzRulM4SDIdvRiCl7+tAVif4BMOYcHK7DO
-ZDAGIN+odEQtndKiL2xBz5lPvto/A2EzfYACjNHyrkE4LXP9OzTXb9AePKs2bdNnf8C40RyhkZwN
-sZEtxanBsDYYJYP9YtS528i7kZNLWFS+ICoXSyj6L/JGbq2rkaPIpg7yQEbRGkNRviOhTTmxS4xa
-A0uD8fDCEhyB32wvdLt8ceslO1C9fPHyme2A/Q4JItvgnFKGr3eWxK1xdhYzftj93n0MHIIeOw1j
-3/iMrPBnml6QmZJ7D3XkzYvlO4l94QaPjXOAsDlF5dmWaGLO3TvIqsBNVrTeWVvgAJMb70R8oNkP
-nkBqaPaeQZJm1CIjP+kaOsKgwPgCe4MZeBAceHcIOI6wrg7W5usF0uKY2WydU1jD1tae7pNT0Z2p
-UfdqOL13Fid5kVNADGaTrM3VO4xzmRMQ4rLalgvbMCe2fl4XrkHAcvl6+eT1X7lO0KTEkybGENg6
-gjt7rVan1LKEFS2egbRnsRLXXjVsC8zQfyKrXYPdPCvFwkYjGIkVrtHxd53SeI4xAe5QEFuAybvI
-0LEQW1AxOtBWSeehHEUoNH6MIo2x6rAKlp/fLaFwr97nugoHjGIbJklzlz3sFbj3dE6fvr3fXVx2
-6NUbJ4Cdl++KuirPYrQUx+fq/sh/jIO6TRyzaFJKS5zK3n3YsxnSJKu0c6GrEP1Bf2h+yIWd/G41
-yK/+06vXz3791Zdfvo7P++L+9EsgwbtZu50tFPrO6nwM20QSP3hFsH0FsD2IRxakYsfbzRHY8kuR
-N7jp8xBSsgWKOmdxjFuAM2OwMJ99/VpPmhBhRy/tufq9gxSgYUMKk/BcMVhJHI/SQdii1UMNdByw
-WKC4AIW4pR50dxbNbWq0X4qqx2YnzHtILQab6SWsQxedV1643mQvuxdBXsonm3Ry0A7Ra8LeyQh2
-KiFPnj599mrHVSB7GdgB52X54c6DXtWo/q3z9gqNwfw0dW/IXVUYQr+meDqT/oPaW28h/9WXv35m
-LeGdS9erO8S6n3314m+fDf31gW+YlP2xAXiJuFBaUHsjtN7IKI8U1z+i7TBbSTQ1bW3E0BdI3n6U
-OF4KbhsSUm8GrzfIMTyceUds3E4MEnGOMilskeYkzEFPIvI0FOP4Fhl82zZb9M/S3kO2j2LYadNa
-c0rJkhZRdMLP5N7EzdjD8JBov3IdHvEpSzP4Dh1ydskxLy05xgmDCTJ73lzRUfIBqMGTQtA7FR6q
-bU2SW8++LgkrZOCOsMog9/g2yEuKaTV25jgNUWLYPK/xLbiim7JTFDalfRX3Sd57iJenNs6z63zG
-kXahD1mlsE/V+WVxOwXli85sjmN3QkaUGX360S7hFujkeoYn36wJnP788S9OTtIJafntTRUtsrsm
-NK2gk7zd2j4N7MKqwgEvaZbQ5p85sdZcQ1l2W6y3a5DR8DgZlUKpjedLTbNds8zJd+G0kphdYsM8
-9HE3s3S+oehttQUch66xwVuRhwDClgAQ8PAYK7p7pZJ+OYBJ/72W96cnJywfJR3AOU4Cd1PIURoL
-EC5VyOVty/F6SQ5J2EGQJHM5dGMcpQ7AJCCXKv5a0G4LDV04uRGlnXvEejSpQ5KL8gwv7qk2znuj
-PBp33x3y3sD1jNy2jBFFSYIZITayKFCeFnUHy0m0iACZ7BpZ00Ir/pkMxxxBQWXiky70FeHF30Gf
-WChzry4fhY7GuQ1v6oMHE1Bw52mOAxTmFeAvI6zpCXlHfHpAlASsN8xwg1O7ZVJWA2M/WUYk5e+u
-pdeHp+kP5T0b9pTVu4B40wcaKpjvrPOsJG85YDB02W3L+0+2BCUyhGlNCFPB5+QepjlDRVx3cJB8
-yN4WNm1u0cUX9/BrvrUlg3Gmix3+PC4VZa1D44wtSt5gj9Fi+u7w8I1Y2nGyxdGDIPFUifXdhoKt
-cyRFjCzc0YhVImHV6CiKrSs2obMIVdK5ikN0hb0dFEhANyG3G3oqI8sFGp8x3maqVmiRHvFRECzt
-6ySNmqLdSl5mupCgPJ00sjlbUYi0OYwZViCESnS+m0LYOhO6NAMsXHJ1hloqmmtk/U2ekyx1lcO6
-dEQo+Negwp7VQPjPKebjTdiO70OlaE3cmmiMSTGGBXSTy64caEg7n5K1uKb7omUBwp2VOotbTMc9
-97UVFaElkWZs19Zy+Fak6UEi7h0QZfgeNgdOjAJtL/FuSZ0ESCp1VjZMak6unJZwMvAEmMnvY0th
-ozs8+2SqhKLomMDpUX0pFitJEf1M4iA1vsUgnKtL5d0td0F7S2NYTj2ph9URZd6RddGScdEk7ePj
-9hSDafbzxD4eThPaXBcbR9Dk83lsLV8cpuD3k5siOb7hT2uPVxoKerCxNXrdcUjxsori1WV8/ykQ
-91taIBwJcRfooNxfVFm9oKxZ9XbT7onPsaOtCfEOAJ3O48l3x8HLKPo7jlxA3/DwfbchZOAJOZTB
-wqrUwQLGyBdvBtv+8ObVs6/ic5vFQUvb21GEQZVXh1k7wiJUf39fPEFLCvYVCmq51yZqtRyLABwb
-fDT1PJJT0y1ZRcxGyIG/6/nZBH6pgDfHMR1bwV/4rZruRyP6zJd0W3bh5HAXqL98FQDaYaahFkUE
-SACsURRsN5GGR5EfvjCQ8ycNdO/r9FslTHY0bl9H99+rBLr2lWwN90SSekloQmiLY1kCmV5leBEA
-lvMSd3Q6IqPClzhjNC9+cEQHVZcyf5T64pBrsfuiKBINfM9AimH3YQJVxLIDwiZyMg/rFlOnGMGq
-LypSwljb1dk6yhHXrk6GXSpzdnKOhz+rzVXGyenkIefci9P+GMID2wGM3cx0hJThbIjBndJQBGhO
-ZCVpbLBr3KjTwdt//ebfUE41ObVUfjFv/+hNghaAK+CRx6v8HboQbC+OlcB5BTv3CuVA1PPf/vGb
-P8I2ispU/5M3f47VixL9ImF7Q/XiKl9tdJ3/+s0fzzZIee34qqqu0UL69r95/WdDyhoX4SP3EJEt
-pVwj2qy2y6LEjKtyTEgn8ZipcLy5I6lCDnNVyTGbUAZH0fEP9QNt6YQCnDz7h2x8wO60ONpZtlgQ
-ihIezDors6WOsA3DQvsfqWEyWpAEsgVfRkGTJ0XpgTYQ9ajNUVvRuyJDVxqMF9VW1JLTuhYvuWd2
-HUnpYo0Dm3ZWSww8QnXoqoL8BYscfyrGWL4buc4WebRcVRdkZs7eZcUKl08k6jFJ7ndj7OCRzLju
-h6x2sHkThRRNJIMXmR9dFzKJVkd5aKsNEw+atUlAXZg0K/Y45muk53zGeTgdVJCzRtMZnskaQP7D
-l8VSDM4j6kiUJCt1mblrH+pzfFnUjUnZR7HFgwDCYicYuU8fOIm6KnhgHJiYrIIlRooCc9xBBhAL
-F+G0pBap4SkevKLHxxz0SWO4xIOCQp4KRjgzMhEbThRvM0AD337LLY91V99+Sy3YL6C1BASp9Ntv
-d88ZrntBh5WpRwiDuAb79qspwfIehubsp/DaXIxUyYqsjJVs+GCWozzLoU+8h8xriu7WbUsCDjtZ
-VdUmOOPEqfZNuGq8d2hslXYGoiaDPOUu8rx0iF65u+OiF8aopq2l4ynoiFYbHwVRfeQlfYtmW+4H
-UinjuWWuKNg8BM122xT8IeoSOWM4fFKlMnqs8ElnonAE1eZ8PZVsBPkidSbG6jU4Lz/svmGBQ4Tz
-o+0cpqMALtWNF6ZkDRFMUlvBd+9asdR3yVnX2k/MquSMOVSBLjQKqFGkmBk97qd0g7ZMyFMGgZnc
-0f9GfIUA8jo/rupFXusNhZoGUj8mWWncYSYGQiaRfuo7ABpaViqYdpfBSuB9aUInwfFWkJ00AyOg
-4AW/sqXj4wJGxpSv4upcVjZIvF7djRKqof8arx5kAXLgWzqGIeimwImvaLTQh2StrvVWNmeiNSwh
-OKgDKWKmbcsq9w1b7Hr5SJ1RaHLyFjV2aXf0PLIQqZruDoWPLLQ9oKlDWdPxF3jDC2Ah61boXv6T
-8o6EMEzvPeDwSvmCHFeJZbsSA22G0CXujQ0dutH9QpFkV9VyiXjgvcfFQGAkdLiWyJeqtjGsnvGx
-Z6PbCckGuIzkPaib+M1q6SaPfoN323QBAJoYMpbrtiXFOA95wn+CcCmmvRMyUN5yC6wmvG1ocJrI
-VEAvR4n60W2X1G5FDgJrCI2Kn377rX47Vis8FfFGOyg85RdfUXMOpQa6+x1sSXInm3d/2NeJmlWS
-wh93k9rcqdHi0FnT2LPisoi99y0S2bHoPF6ojq8sosiz+ZVxMCUkyPU+u4E8xBu4Tb2KL3IOpytB
-ZW4yjJzB+pVE5bJa51XLbJisqouKdHXO0EhL3irdYbghxO1ja24dXAeGlpWjMKgxASbHly6wxiNr
-YVIGILmdqeOpcSKJLZ6+ybSMdwBOvGEv2EiUKpwafvY4DymylheyQ8hjt3Pd1L5el3mZ1zBnM/wG
-SnDeZljX6laViJI1tFGAtpAi0QIa25o1Q9R62PPIBelHMEcQMLA9Kyn4x1u+3n7AWwt+GtHGZrtm
-IZaSBQabwPsEC0oe7sn6M9jJqIl03KcOzJRUqnrJb1uPArSuxo4oqmID5Lt5hNPwqM2zelHduCKu
-lg+ZYejtAW1L89WWrCbzbANrAD+xDVjru7aIxKxab8gSKmdC8ZehvYlpWgL+o3OZBamBCkU6JUja
-zZSkNGFLKCXMYT+EJbY4bqvji/wYMWJ1kSh+WHACl4DNtGBEYaT/NUhQmNEWtSLmlDr2FcmXjaSV
-FU7m/kw2dxMk68m33pwpfH+rBiGs5KKqVnlWTnQ6uLKCdVHTUTRLq47arY63rWsBHVbok8m+le1T
-XoJkiznMVQhIi7AaEGxBOSakk1sYJgXblqXcWII/q3yXlONQYhLgW0a6/dZHITE8qvLtt/0tm1Kd
-hvWNKJYtCcxvv8WyuxpUM9e/2hxVKAj2t9++N+0qwjV0ESA7Ux5jVakWuwQsqVtpVw7Sr5LbOMOp
-Gjoal9EDQZY4y7V5SXfD6FQA2HsdWlYq3apCGrszaAGBNioihWO1FzRh64qxJF3nInbydGATIZkI
-FyKdF02+VaZ1pNO8Hr+Gzyxqfiu79EAd8xvWZ1WX2i+QTCJlT+1v/ikA9KK8rL7tXZdmDPdYmX16
-gTIjyZYa4vBcR/L1kuuv5vPQ9QZVCNC2NleYI7y6dK4g0sB+jNMCAZaMCr8j0Vp6YxbXtWcI11Gm
-HbKjpsao3uUPUtI1kIzImIdOEVtb57q5qhRfRK8iUeFEK/+hcWvpwCSnFtr+LvGs+Qj1x8M0d0Ph
-u9BJNKuNgb7awLaSX+L9P3Q46Bwk5LebVVZmOnge1y8a3PlAlr7MihXHEKCBQOlaZlX4qx1riiLT
-V0pYt1q2Hb9M4utComWhXxen5RWnaJWkV+lKElrzgowXaGlu6MpbVpoH1NCHRfkhboocY0zVzhuQ
-oMjaa6IGIhvEJjjyYI1GWzRg63SftNkv6CQ9albFsr1a3Y3YkEe5AxBbHHLTb0KF32y263WmUnL/
-COvZ0FxRXq62OegkHFdNxMDEOZwUljnjmF/ZKv3RSJEhmF3lGWhDSZ9VUU8So2tRNEArd7ilg5pM
-VXFYldhMGGYzuI75VDolRYk4QZdtm6wCwPqPURtYVjXMKUh3dbvCWyI1CdXv8voCw61RDNZLMuXa
-vfZ1uG9jUYOYCV0k6gG3ZJ9y4WkpnZgilWW4XbM9BN0UFSqkFQu4H4PGFtWcOOiPu01IL3K2iNYn
-WmKJ/O3OoXIYXahMHmIIYEFCmrMmq6eD34Fdi/y6jLsCn3a16Fq0ihb5xdYyof54Bi46apupE/V8
-IefLeGThHeWrKJd3EWZ+leP8ZYWSjKrc3ZWl/W3Z6cFpuNuoXSNg6RU8EQoT0HxxdwsbVTVKOZVw
-t61rcd/jRtF/DxtEBhNuUJWPdHlu8+2/efMn5K6CZjntbPLfvqH625LN5mSWk5t02abgin/65o+U
-1CrU+Pa/e/1//yG7mwD3m1fvhP+gtCJFGokuv1UHJeZ0lDmg3PnihjH+74CYPYKIgejGcwpdx4Ve
-C+sAQbweRfj7OTT0uSichxzAL+tqu1GetjV6L9OTZCjmNIlNTw/NyXoyPD6W8RzLWIbmehYffU+H
-IDDAwsQ7TMOROgPnxCemLDrwTIc+fnAnR7ebbtvoTjUdSln1ei+M6BfSB6AF2xALfzhubzHWGZrm
-3mX1dAiEMfQB1sASYdhxBJBqdYtsoZEWw2Mg0NJ7nROJI8RUB9ek7wMdMRJzU91SlPqhG4sIbw5T
-2TGjaOziMegh9hkX+XXAhj7QsZoS3SmHgILxUggoYMVxyumVGFSlF6AwXbQchY2i46JV95uB48gr
-V6JLwu5UAAcCJQeQxMVfN7KtwP0agOricTDga7O0YkAYlsKJvZ6kSY6Ay1xB57nf1MqoQ7ngc/va
-LIVFsotQ0kvz1S3Igu80MvIuXemolFCgEqHY6ZXpfi+KpSpmI1X2vHZv6Cmmi8nTftjGVk/Qh8KL
-4AOV9cRS3C2UkFqCeoSJru9yXyooooa+4i8PbIKUWugtbcW/TKTkGCBBS8Nz7umQ+Caq5psSdBU6
-inumLKyp5wQpRWUYAKYChkjM81vO0IKILqpOpbG8GHTsSJ2SzsjZE3SlkoUSxOq7e5UJJhDULyki
-3x4qeMwD9wLfGtYZhnkzQ8IIVZjaGdr3orh5tOrvIokCaySwjFTrqZd4jCOx+JM9/pJcNZ9KCAK3
-0lfPXn751evZm89ePH/erWm/7WBOrRz3qrgCNlWJj/Immdd++qdCbhdaOB3RgxM1yOg4Oj0BtnQU
-ff3117/szIiXvc1flRq+s2LC7Z0HrnhhARWPZPjg5KNF9IASASfFw1OGIxC2sMBsgaf+HbXwKgov
-orQHFGxYJnHM7rWzRXF5CZIctiUE178CPWpfYgQSewJTieYx/KYcHnIDrkA74EwGxvNM8o9ezWge
-TJwVC4txPiMe1D/Cs+GbL559/fLZ09fPPoueff302cvXL778YsKo3xPvYlMnDlTca3re35uKXID3
-QS+y+fUYzcJZO9OHPsmHh4xA9jR/uwptRDvC8qi4TtsNrEOLxUt8vrHD0xU3twPqs1p6WfUEk6fd
-5bLhnZZv7g/PhCzOh97eojdmBxDZbJD/2JsNG3D9bvduLzgWPB9sK4sdEx+mnr0oYhxDSwbA0fFA
-5JmxwVel7HPpn8Woy1W2bKaq+Weff/7i5asXr0bdWF6zqpyROkMxY0bKLIHcyUWOSFs/ImpUBEse
-rRudVPlsdgNZigeDhKEUkWymy7NWor466NxBlm6jApAO+5weMJsYGjzQ5GgP1g+fy3Tw9r9/8yf6
-iIKsC6tq+fbfvn4u6l6CN1UvVmzQ1IlQxD9DzBG4dHD1i90nkxBgHLawUKlgjAL4vfS3roENdJqh
-Bl3p7OLd26NCxcfHugYI9F29CRUZXcJScWzl6crSsIgreLqU9jVcZ6hF5ce4c5PvvuANmh53VKSg
-k7AZ3tTTdPSbgY6bQJ6PeNeIbayqJkxOs0LHuZLCvie3MLOi61CMQFVORXdU18OVbT6m2nRLxb50
-A1XkRjpdb9LtQIUbQO0pihokPlxsac9dWEm2eZnZg/uKPn9eLXW30n7qVwtfwUg6jaaHuWHbQACx
-uSOf2cRCDhsdtNmbhjwaC+idXE8YZLQD5+7xGfNT4o9MXFnIzmOfbM+vcBFO+aQdjy/ogYChQpWf
-0UO8YmXCnDKnQkpT7/iJflm3TnBdPkhZkIDIVU4nllhY5je6RSxmt6buepkiU+m+E3iPO+6KUxxl
-XEW/C0VUC4C8W0Jzm7QD6nXLu2X97Ny6a7LX2tfRFDIcvUjuweHlNsBlnJzFoc7cQOYOAG7kQ4N2
-hd+BJdXEMd8MX/I+pi0HagHy4Xe/tcBfoJ6lQBtzLCuOsQ5opqE+ccSXvKaIki6/cBNi4mn3DDhc
-rTMQw7pm0YwPRuaUYmJVlUvLCOsFDaZMADNQThqlmth1VYsppevOpzbIadBaoXpjVYC1s7ST79Tv
-XfrG4sGeTPo1GDJoLvNKpz3jzW/vkNVILKamasbsxuMwNKFBXSsYM8lqU7kpuAuaBuHP1Z5ZsvNi
-9Pg22ANPJ258WwLjBrOzYcByNI4PxYeY3rBXVkhp8BKX2+IfHnSM9xzZTQUci3kvckJMc2bFfif7
-5IKE0Pg29kO6MArk9rdAbBDjxI7XrXzd30ocu3V24MCqZcWgsmuxbPo9IJa3GIdhc7+Gzh6fpx2u
-oZeBIuN9dOT6zffTUEkHR72Y2o0Ra+aHz4eBmDe7xknq6bzOmqtDrAfi2uCitReYVzuBAfY3ebAQ
-E0HkgTXoJKJ4H/S7B2PanuqxKY0Bi09JKWBU+m2HV3VZGxcEhUDk8w5v6+dr0thwfrOYMEZcC1y6
-m8Exc4s/iDlstRokaFj/w5t/hYdchIK3/+71/zYgzWogOhQ8LiuTfYl2YfF2f/Elnh5U7GOELixY
-TbSo5q4ZwasR11e7NwfQfsZhK9Clz46scEDaPKCIMe6JNRJFBDhI3FyA8EmsB7O9JutOTTbR3r8e
-pR/ZW20YSfoWHTee80Hild/98cOPyAhmauy1x6d78wjifjI8e9CcywJL7j+w9x5TN+b5YDC7ATkD
-iQUaA9B+S0UeT5iAJJkGt/lR6OHpz/VTig7HTx/bDbz+7MVX8vhnPw8+/6l+SmFzRxQ4R2V+uSDB
-4JeD7xxq/jW6Q7rCKNolVtnfF5xv/F2B6qy2njoriC6rqCQ80csvX734WhaMjlya4eWmS86GnLOD
-VExF4kjd5I+iJ+iIup1jkCc2QRtv1mZ7IdB6q844U+FfDpAz5b8cHpd6ecyVYT6+sylKWJoWtr24
-55aiQGl3hqFsWG7MFU834LMXzWwRFOnFyDIrLRIhPFSGoE2gss0NuQ0D6AirhuKxuhGNrQZlYyir
-XaGNneykFvLO8BjisJg/AIMoX0yGxJPJ+o5Zo+m0ZPimvC6rm/IZFniwwIWLz/3gdlSREIQHUAnz
-2UTaH0X8YNSzSH8bGz4KKquKqRT3LGmdgmnC6Z5rcTMBdH2XdvfpDm54uARvCKH6nZWU0IqWy3OD
-Dtj7Eo2Tv3Zm7sSRBE6kmJWyz+nzAUr1uQFtaU75R5wgqLOZPle4gsVN+WQcBbqPNLDnxIfRpwzC
-UYA23FhYUthf1B1yGnHcBlAaLyJOGqlOOsJJwpVVTWoJq0l7chE5T0NoCZg0sEF4I8cuDrPrDXvV
-TdQo8NnhvXYlq4++ALI3vM3Don7Zk6wII45g/0AW0iHdhoM36HqVIZdH3izRpLrSbj+jwo+HiNW9
-4df627b30zP60B88d3eqBMZg92yen2Mca5DLHnDiSyRxI0txRJN0L5mwu2Bu70G8r4J4+mdv/lQd
-ALBygWblbVus3v756//nz0hWfQPfiraQTVWXMl6Bvn3/V2zpeKJKqt3PMoLI32bsFkKnRvSqJjlV
-3MOjTO1kdLEK3iJ46nwFhHm6sHJxp4OwaggHR+wVt6lziUtCmhEF9tCjqHOS5ekiPyYaxpstFCuA
-TxJusoZukGNsD3GKjHhDo4BAVyqiiZIiKNpfhlfB+P4Txgg9ij5DVL1QsOQgHTgjlLjGZNDVR6na
-Iz2xPhsZiO7ucGHKAGoVYlb+Bb6jqEEAaL6+yBc4BO2Vjv2Ku/kIxnCDOZElWCG8kksgdZ5bN/km
-0Tflb0fw6zvCxDflP4oTPPuUY0RybJXczheil7K3IHSI7ukWjA1Ks7m7W5iJtgtqK7Oc1TdRwulc
-Z3ibBpO98zct8CRpKnBR6FfOaaNbITsRPrNvE+hLR80GUKluqPLZM0gm4+WY6vEWyQ7gKLOiI0Hj
-SnpHEUY5W2FooVi0deLSko6LP08xViIbavjxNDoZ9EW05qt0U13SgntM4QCH1ChMjWocNF8q7Ki+
-Uh2DYk8G/fHgOIKZgkchrQChDik/L7drusZr0+QZQTg576bSnpN8+ttA3kDupuPzwWYuqvVdb61j
-v5YdRRRLHBL3LuBHwGKzw4+S4ba8yFa4JwKLQcYKi0B4sX1nJLVF6wVZenDSHkaFFaxcpq9cuI5i
-Bo9Y9TjirKbxN6Vn5LPpdep0fzah7s7JgcqbloenP51Au5gr9eEutdaD4+GpHwye4Ufc/5zPEbKb
-mfIZsoHBrRvzwEqSGxhGKguDuY3hQDhflxUGXWP+DayFGcs/DhyHJN0TKDzneh2vKOSufuUcOmEU
-bTtGfvzbmFwx3YffhR7+oy+NOf5Mq12HQQwIYRrnD0aOqeUG1gGj8og8m4h5GHqeX+MYT6zv87K1
-HjkHDeGhwlN/tJ2lqFpG+ALZ3dByjKgHdeMAeYmKM0HEnrsJegMpZOkDYU9GsWHp8gD1VjVz4jsN
-YYv6zC16iFiOAe4PqUOqnR6fYuqihlL7lfmZQ8zEYzo4+87HmTDvUMHAkLvphfUwuq94CGdUAnFA
-SFCA7iCwPpD+Md6NIsCNQU0HJ6pVU2KqpkSdFQIpsyVKppNuJb5k40uETjZyQwrDSFKEi48GWqS2
-Xk+tL4OwcuCUhg8SQzFwaXDfZUHJJFQ0ntxBC6qpMMbnBreyqm4e0ady0ahN/KZYkDX4FyfIj38K
-vxA71SaFT4+Bk8Gj+VVWN3LxTjzVTiNORpzVlA9QAqshjDMxuYMAXFTjJsOTzU2dMPjr7BYDuU4x
-Hwd1/OixrBcaWE9demcqU8VjhFL3J42o61ewYum8E/6P+chTyvG9S9OX2DYLQPlbvKtH57TZ+mKR
-RbcTW0m8HUErBd7maLcYz0PcIhry/OmvY6ZYVaD4l/0V8HWqYdpVEt4K9O5mqbOGOIoeRrbf0F47
-ncaBVH+U2xLRxL7+8sCmtv7tmXxMZ7oFRaRdYceg2elKPzywO1kVs/ztzGlvd8et12f7Xt3tHyLO
-oNMVPbg3JsXpb0Mn6OMNKz/c7j1ShIZbYWC8XULIg5Mw/uAkAs0WZQ+NmDj0OtkqZRG2zmy0hcjP
-aLzPudi2idkAncWJc0ebYhySFjyhM7q80fE9QbF1N/4YVOesWDXizjjG3YHzg2Y63NEVxWkij7k7
-fRQ1Tj27pxyfdb2FzweDgSXpW7BPgin2ROr8jNLMc4gajFK1zFGZb3AIi6zNRlbMFOUchjZJ1RWy
-VOUrY+vhafQpbA8f/mLSi8zPCCOUFM44SGJyevHUHGEerJJi/cTnA3u/PROe7Qn0shf2sBa9/31l
-ktv5F+Y5Ic/lJR623OQ5O2kOTNQvuoZOSRNWebZQ10DbWi7W456XzdscNj4OyqMMBQXuggWm5gMV
-mrJ86Z7WRVmss5WrJHuoYpkHby+cwIRR/BB0JsOQEzhCClJJGQiQgv4+ryuclaVySUP1lHWBcpkn
-0F+itsF0RNMnS9s9QMH3Z8U5eozQe/jcpxbjSofZ/thK+1qQInTSPUjUUhFJGHR710qe6ZPIKzzA
-R8zCtmxwGPfxsljNijURRUl4xi29OLe0+EvaJ2mQlkzJaNRDljdC5szHplMLae7tLAvNunxX06BO
-j23UHhcBlcNVxwM49vG8B7c+fh++B4IZyyF6D6PZR/Xk2Hvp4lu/9uEUib4uNpbC3HFktBRB5f4O
-IK2Ki3GJH2g+HBe0e+XN9oB2GpK7IN0wHIol7RM/Jv3L/sdavx1aeNKSuH6LtID4QkMOVn9Qx3uu
-yCTFSPU30r1592McdmFW06fBxdSB7XMkIqToDCNNUwxZChc38rdZtrQC3deZBEtjcT6gWZyZns9H
-Ai3rvhq6Tw6D7iui4h8QPMahhkODF4jzcgR74PcUAY/uIf6F6Lk9lJQJTIsfgLZIdcxLhx+QWnnZ
-KqLRtYMzobX5Zxq5jcoGRn0BnLb7My0rivlVhlruad2bJ/InTx0ACfJ7Q8jj3Qei1/a9YeznT5ao
-jTdIRiT4qPQjxBSm9IgN6liEW8T4LvLqbEIFeaZRslPP6fFDJGaqJ3vqvKoxfvJMlGFq6CHV09Tg
-Kjd2BYFPwh7fSOEzVOA5PjUuRDlsmgTWF49R2QY+fpx2TYnEAXdaEdXe6RvGOlkSQ5WPo/eq9rBT
-TYZvG7OUBeuxa9XzrWVeTXNlXOV64feDt//+zZ93j0DrXB8dvv0fX/9f//InPzGud9ZZpx2xyDtA
-VdEsgqehysnJO24Ilu13wv/Qc8MIVh8HK9nTgA8OyI5Fx+DrRixzCdY6OznvyyXap7f2ezj4emyg
-3+EnZxd1dQ2ai9Ifz3E7z9rowcnt4lN01wnuAgKr8b8bgTioR7CLii4tNfo5hqvFBO3kDHBJ3/xk
-qmHMVdua7GiX3NDldrXiZ6FzLCm9N6PszqRxukv+gB5O6LtOwUKTS307XJMs3SLcmVjuBfK5Pfnw
-dK9Ont79BwpdqNGljCFf5GxlxWNdlpH3pK8lt8UdkxCETTLdYQzMDOYmqubzbR0tOJitxQzE1kun
-yOH8n/NqpkMgYMDNnHL5DD8BZf/TYScnNkO1k+it3gUno+hS2S3oZnNg8noObuylNCe7B9IY+j3g
-vcrctlV8Ogx5MGkX1J7G8RWeCKqeRiBT4TBh0VA6gqok9ygQjJOPRtGJMK8Ox1L+cQio8hUZCvfW
-2Jhhqk4ogH/8KSJgTb4kTon10XBg8NLDuqEx3ZJi4eZB1vgAhEcHGHg8in5GB4zEMUAkaRG19nY3
-/A0AqKO89MAD29TB8Fijs566JEQwD95Gb/797r7efvD6X5ywr/rzQgUDW+eLgtzW0V1JEM1nQhzg
-iI+SNKPBuMk1BYJVWcaevHo9HpCtScxukpEtstGOMZLoHusW/VfGA9u/yNp+s6Yd7N2KFcpwR+7b
-rW1c7d601WTvmE0ymXUI4hOih5+Ooscy20fRqzyPrtp2M3n06GK7bMa/oZOzcVUvHxVNs81PP/6L
-n4ur8O2mpkU1/FVVrb7c4JXnXxUlf3hTZvUdf/ycjkXw04vLZ7f06LNibsdoEm/Nz4umfQoqDpb4
-Sw7MXtVS4z8V+WqBH56yDkQf8UpVpxWM24Bvv9iu8c+rlr5pNxx6tr1o5sCyWyoHHDEMC759jWdI
-cmF71rTrlkf8XByEPssvCRLcvuUzGzpplPkq5w5hwopl2e3lyXapXkXDl6j64YfnFYH8d+h1w2ij
-rwVdHhl+hRJKt6nX9R3b0wnq+u45Zz6U3oFcqCUiI/PpOVBet6lnt/mc5oASvOEnmAQC6SUMk6YZ
-zQo8Gyw+KwwhTcz4Ljc6KLaJcubO8ECOXLn5ai5tQ6UQkYXee1Wm+UiNGFo0MyhKbVJA8O5dErre
-qsUtDQH32mkI2z+8IQO+xfAOhMs6MCzp9hKUH2P59D5ABVvB8mhBYMlewtIkJkyTttCzP+QlnRKz
-x5fmPyhtII8kltcj9Vv67XQ47Ny8zbbkBNbjjExlXOtFV18OyBs1ObbbMgd5m0nvsF1DQ4gETrnH
-1bhX8s4j/0/fCzKhVgN5U6UKu/lhSkXnUEwwO3FCaHCkq/+XvXfbciNHEgRrX+ac5c7ZnXnYeZhz
-dtbL1VF0Sh7UJVU3tqgppVKZpVOZko4unVkbGc1kkB4R3iLpFJ1URFRW9o/s037A/to+zQes3QAY
-4HCSISmres5une4UAw4YAIPBYDDYxZ+0dsKUhUO5XRZG/rXqDTW3xnpnaeZOFBOxA4PykhxYrtFM
-FBNpUfxmmGvT8S4lfRMbSaiDlNP+YTovuJGzMIbg+0nyanN2BscU211G4KGKCk0lG9GOdVZ3+Qgj
-QqI4POS/hxSho2eCT8Cgs+r0FC7JMLyR+CPjyujsFOiDvxKR1r+ScPF+tySbEdLQV7RfG9rArlUR
-Vbvhmd6P2ctqAhciRDwjrfP+MJRBhlFijq+jWojpmdY+hfZszuLrDtnvpEny4IHxJ2f7+baHVmdP
-o4IbiaIIvTINFDNYurgam+/G1Mhl+3Lt6VF8uWVg6KDrOYdTf6TCuvubgaeA5WdBYx8z0i5juMc/
-L9fPVwlQ5V/lSJPC7yoq/We/9BFwOSj9lSr9+tV5ebrG0gcPVPFLW/zwoSp+NCUAt1QRyBVYdKiK
-vkH7Oii7qcq+KN9j0W1V9OWsqlamXH/4pqJeDlTRk3dYMhyqomfVmkt/qUu/5rl4JU+oSNf6iqfm
-lVCth7rWi+qCpqHn8bTGorL2imAoXIpcQ39ZUPHCHzWXsiVDik52G5QbG0srQLHegdfd4j0SEHz6
-V6/8jVkJv9QsGZRiXyYMVMj/ucdp8U/M790JaSvhYSgha+ASfTYrxnNkZacbHZRYXVol2FDLycnc
-JTgwDf+if11TE1iFzyBxb/OFgRtozj1DVws+By6KZErWBpShbmxM0IIsLX2tetsmsfgH6xPL4Lle
-oFy1bip4LmAYMHtqblUXWbtUh4o+Xu6ySRXVslhppkWhZ8We3hbbZdUXPweJVWHMO00H5ud6vonO
-NmHNR6BEHzvCSsf7oA+kbkx3kfb2VI0K9qDJ6BOjT5m15L76al8z9smY6XIxBWmTHZJJcO1pT2Yz
-dyZ2I/rNMU9VikSRNgVh20Qqpw/UzdtTyDxMGZTqkP02kLCdZLtqCcDH2xArSHjCEIwsLwNC4vdt
-F5A+JEZ1/6SaBmuouhAp3gf+bGxjrwS+uBECNbTkcxDfu5av/5RyqkiMqpAiDTj2YBWW6cGKw8zA
-55rzjiCD5rTgUEDCAqern+Y6GkmDqrVcHiVm6mMHO9hOyzckP2eFQscGJ4aehUB90X48YsYXISoX
-GTOh0FJrPRjY7Rh5O6N6vagbqEFEyC62cJRgtUXzYSMdzZdaNuT3XSzt2+dba+jrQRcTW00TTAv0
-Xu2RJ5rgYh6kUbXEpf5Lucyoh2pZ8wj6/CRN9sqNJ7LLoGMqiXUsXfSCEIGj+mp+Us04ipuV+Y6q
-pbt4H2/h56kxLE6tYbGfUMV0sL9BSjinwLbe7owRnZwoAPDDOwxDFdGDMg3KDWEn5w/3yIecnXkS
-DGyoaOEaZjnhXIZqZT/ugGnF7TYP4chGlLHs43Lle8RS1oKnJmnBx7wPNnvZtRW37piO5kd0xfR8
-NVuf5TiGVKOBIj09Cq/LXjPaUL3LfHilolDsz9pYgSycDdMLVpq3waKSokapt7hOH/kTClHPV9FL
-bRA4mjka+VQgNxMYrOtote8Ij0/mWAKmVZy0rlmtBG3jNKJpI81wFwlJkAjGBs4hxZNI/kN/t1zs
-0yxNbvEBFBoM1+h4k/bSD1gz0fDLotG9Tce14+QMSHrmRndEv/px9i0IDTk0F8ZWwAAL1sGfuRkF
-sdpmB1uFEtVW8/OCVOG93ra4D/sxYPwx9Ke4rzSzB9O8xubDNxuz98pFFYoVe0oP1LTvyxDsvuOP
-QTx62gAE7hpxEYCrxikppH0jBfRaxIDryQCNGfU6H378N87+D5GNf+bzvnHW6wX8u9DrYxcARmXS
-JAaPiaE9CFjiUxnnjcYs0B1lhjNqPzXo7x/1mmLrNBkQ8J80lA2/LjcOHcohzLEZIkYKQfcUPyO6
-QaC812gpp4Ien5V4Fxkw+EC0XNRHphnG4HF9hZB5MuYcM21624bu1Y6usuSGotRwBiPy94diRZqb
-+/ffBj/S6UhdhuvhgQA2I4qtl4/VAAy0NX2HsZ3aMB2H0BIEAKMYIMZRJ/8RdOjB2AvjWDn9FGSY
-3hQcXxdPXsMd6OEYTR+DnDDK0xbUvL2Y1p8INR+Omz2QgxPib2TjS+E8JBBgCLdNGoM9kplzuMmq
-/Q78jsPueOY7jl4KvGX6o/hbP+NBe/Pmov6Ep6ETnwFp3y9+PEAU4K+ftKi+3ENr3SoQQ22KOht5
-u9v3PEYtt5hQEcHFdZF6Lqw5w/SFRktINxdXbrSJaXNt1ditMk1+fOzCqowqH6JcFAAc9yyQVlz8
-H0YOGrQ0o/yqqy1W6E/Wl3yz/boaT3vtw/WVuQQ7QFwg7HJZVLrAfoNDtLF/+8IoYrAJQGwIwb4k
-bblhOKbN30gIpjuXh4RPuGkb2HIbt897l1AX37DX9Yr7VGD2W8gbCaUUM08D+JGyN6Pl4nhhI5C2
-vxIYU65gLXKKI1lO1qNRN09+/Cm275Vo84moBYc9MmP+OYkm7Ch8V/C/q/eFiErTq9tgCcs9HzD3
-OVh+7mNDGCO9yBmuWNde8HPy9/eASMj7CN/CppSZqHUnip2J8JwG7F5nt0JZdd/bwymFuUXcXPeT
-68djOFfjjSC+PFs4xMMfakp0Avio56IW3EPrHadGv98nGnMmSC3YF+mYzC9Qmmiq3eyRuM2LmJ1I
-hnpsxrGktc2kmo2q09O6WPvtXHlP544ZcSUZrCBUGsJVB71aTNRhfzS7xtE+nthIIlYEdmzHW1lk
-1I6gQckR+4EmY9TU8TPrg3RXnXfpm//cNJq3OaVvvP6P/5H9BOrNkoznydmCw4VQlMRYIIyS7Sgp
-xoSBWfd1jPvlVSfmckf53jxD/nm1gMv5EvPpGvN9VbSPX8DHZCQjMySOHNKeboy7bc01xp/ROiKN
-U+zkvConRT3MUglXylnP2MICf9NlLm2LOG0zQbvWNpXZN8+/eNLSKycySzFz3npVzWKhXzGgCSYn
-6NIAuhhEHdcY38hi1aGiGXVXO6XUEdeR8emaI5JeicUt2hRIxHcFWxm+ajsw7Ijm2oVzCIORmOR1
-UhzrkbLW1Wubx9xSSafRc1u3aH7WSgWLqoUQdmQTZyJZVGPjXsAL88WTFy+fPH6EGT+Ld5sS9iym
-foOh+na+28YzH5+Vkw8cDbX9gMGEnq+vcAGs5R/9ZYPVhIGIttrFm5RUc98KjD3ROCUK/uN/oGjJ
-Lq8e/dlfVdWaYsKndgD7ZeqTbhpZvdUGt0a7jUp2gclrLPKZMa6mJt3J7jeA55ImyO72LVH1lStV
-6O5JXyL+nqZTy362GKNtcZfqortULPR5HL6Z1y/tdF3LEUZ0EpfBOpt71pFzWnV7GmSNTIKjyawY
-L3BrsI5u3t8spkohAYOWG1UkfDXcqnyZMxrEXzG6IN61RBmoqrf6zrJ9DaW2fHAAX1IBMNk/QgXt
-8QELgNyeUgT2YdB4GbiTExyudTFeLUbjk2qzHs1L4GmLMxcBTKHTIIy/Ed+Ecfj7OPM2YVuzvswB
-/2mtQ1sxS+1OmyZIN4wZcaqVSLxzY8m4T6pH6bptVGYBqFrU1sPH56qYV++LjJHZaaaeQhTWfFBY
-zz/yNDYdVIvZFWnDcYLkVayPILQ4EUgSUPsGXNN1OGyjz0N2OR9jjkg8qkBYoBBnPJhDyvYpzTOO
-3TWtJASvgPf69ehSht//cJRRMjVYs5GAshjxMGaSvkFFEKxULktKSoGW1uWCrtvx0J+mI3d/otyX
-pc7kFokjGgapgCkOqaGh5Go5NB0OVa/D4P2c/OXgUoByNK6HGkqDJ5p6UZsydhD5V/EQMVV7MZss
-Nc6Ww6aFh/gGmxgqXZBGEeBO4ADGkMxo2D6WiK6wz1jKQQ7TAoctB8Q/HmmMoKHwJuosji3P8YEW
-RbWpWwB1D7o2dAyHCu0nTzh6NBTNKe5JP55MgfAH/+2LY3GGHh1JenCQ9iLIppuPsaRq2noNNdlF
-aXVdjFfT6mKhyTUGx8X3FwCyA05BgqnPAw7xqfcdi6l6EJET00pgX3NuJSsZuEQJM4xVSDkU+iaS
-H78umMMo95zR253aDfCw9vaDbxcsqs/z232iDZpehzpcv/Y3DJyp1HNLXXeacs/2SdAJIuneKDsD
-Ojm7G7ALrGj5uj4O0q36jNTs3vJsAXL8NN0W2CQYRGpu45TlEk6SK0kJyMksCIdpxzsE6/W0WK04
-FV6Wfvvo5bOnz74aJGgC5wFvjzufwmDZXzVy/RMUoD5kg3TXPvdUkn+A4FasZpSZ4QUzrdI5G21r
-n2FnV9Um2eA0Dcc7fP5fe9+T4N96ehiDz+aXzrt/ePPvrYZivHr77uD1//2/cVZ1eUuCO/jkfAz7
-fy55wldvTchNuJqg7ODGYvJk1Ozg5GlD8jCpOurDKBR1ZtNbE6P7sYt9dAfJN/CP9fvPej99lAKE
-ZoPOIeqaOdL3zLdKKI7rP8S2Qt05u12lovjTkz9/+/zlF0++e/EyDdOsk/iEbrdMt7x95qQLOivf
-gzhljGDchb2fhLSQPvL0CMBw6xKhgQBFeDysC7K9Rx1EsZrjIgQAnmCqOfyWzDF8KQ0Ag+AWkwJ1
-BvyJ5NfuYRdF10Vxhny8Aeg1J7jnHChmQNxwQA3n47fs28ux9niq/N8Q1pjy1p1wRMa1YCjb1BRW
-g1IOHwJmYIVhGOLy0li+9FDHLYgvH1KVqI2tpslTMT16+ad9Fo9mgUTPK4dgty+biMCD5HCeEG3f
-tfnr8a973X7QwpulnuQhzWGFMReiuhAar0t3Vp9XF4k0STK5DeYmZxCOAUShQ5DDKfBxhU6+fYNi
-2UDQO5z9Weo6Nj9Z+4Fs3+56+NpFjTaGW+8G94z5FL+M5pje3bvpOB0DT7Mv8Afbk81Pq6Z2wykQ
-LmwoeqHU2beUPimLp8Z2wqk32dCDhRT4K5zyUILCkbd1OoCJ3w38Ey7MifMHxV37B/UA74IC6qSa
-TSNBkaAtQsf3unX8S28nbiIXy1CVfqcTWRu4z17xljUJuaKXRRTKytMrip6YSZBNb1WFn+G+cNdY
-WWD5xqoo3EzRWma76mjaGqrbQgIh9MjriPYMRgxiMEVCdEITAFTAjg7vDjhL5SD1VHKqrZfcz5+e
-hjQ4vGvDZCNCOUeECb1ZMEwymFKRZQGxJsQkIdMT08JJY+TrkyspzaRprqsFdOt6NdojadTboRNz
-82/eyXwMNIKVoXjZXJjgXZVq4Dq7WdhGLb46e8xlazhHb2EaIGwMUdtLgwvpe7qrxntg6ArUGzJ+
-OULych0b7TL6uWDso9bQifMrSisRqIlHXIw6Q/rh52TFDttysirnQyQ2DY13+h5LYl7i0DLCfkNj
-jdzOxzTuVyf/0jcGHb29dNON4wBv1hOlnNDsVIBY3sEd7L1BUMqV2eDuluv/VatIBrLCeIEu/m45
-MAo9h+Rj3litbtPEvUDyTe7V4FUdQyrG+pkT35q/fCoXq2l6nYQzHY419rlWHcjRpMNRF5XwKszr
-RBkjDrtejq9QhY5dcAOd8EcmkyG4f2bigM4NtuHf3JtHL26t5s4WPUvlGa/w8ONPKuscVomrEUyL
-/mY5RR0vhWSyw3DP9ay4p694BVqsNVWb+h21HbZOb+AS/82Yg8MnIxj008C/++2F4fFxK3dcBgPm
-YpcDWMSrXhseNrDNPMe7Vbl98OUYifeKRjmgmoMfsOoXxaSiqj9Igow6OcQtUWHGojFrFsbJDz+A
-tGX35Q8/JHhDnRXrStmCJckTEYQH7oaeuGd0W/QHDatfz6oLek3X78Rsz2IEzyygMVJ5SIokvFxg
-BMKkawB1vflhrhEzNWoi2Tt/+MHr4gdTpxG642fPgo26M0nIyz10he2Fz1Ji0oGGeQEIIQNvPaWK
-iqtADaOTaD7InYZnSCi0R2QxrazyJhxZveC8kysHiN0SCi4uxxujln2k+ZMCJGYRz3YI8xh321bH
-OEdSNaOqJgWetTfCS1N22QtJwKjKtiAsSg3GSnoMuDzD3D34yMTNbUgFeldy+9sustvfj2CRpTBy
-c+MMKlgkmelht36LzzyU/lredEpRvE+AC8HNv20XOfXGFWCNWg5WxengByCFVVm85zSKnI92XHNs
-dcvtHwCBsB0HHq0Pf+CD1JuTy29P2rfqdA3j5DFNYSVJ71DWmsnwnZtuhI6vPHv0zZNQo09JUQu/
-Ow/KvRgUWoG7bPjUAyiohJnjXP8CA/JhMbsEXGME3zUi+KQwOEZk2DWiQEL+GukZ/YEG07keR9Qi
-SUTW5DspOkYMRZy4sH80DBWgezHPw386seC69A8Glg3C+jFYlCwuTBU44dWoOGQ2jUr1O7VGayJP
-9ifV8iprmAtOKZVh14yw2+CC6QOfnA7w/ygoN2NgqpkipZf3g5K3ppaHfY54xpWU848eZiiyr3FS
-GZglLng74VMxKpDQOsd/K6rwJeqCEtNPp9zzbdMxVD/kgLSkapP2XnCprYHTxQ1SIos3U+OQU03N
-KRaJXM0BhA3JRpvRwqlJvw+ZfqM2JdPD6tGr4HWqx5vwnYDUxr32sN14dlBqcle9tW7TDwMDIwD3
-3QJfEKvA4y1/lhPZHrc22x5rnA8UvqfSjrh+vPLIoOIjaodyXs2mxYrvJArxHi/gmE+91iVjEI3A
-jK1dmXMlC3qxPCbX/KTXHq1925C5tw9AqrSks37fEQkDwoG4W8uF4WvcKuRqby/MfSaEKlzUsdxb
-VBSNS2X94kNkEofnoQu7f3vhiRK4Ak6K+EZefyRXnjl14TxvuTPYs7q/39FjhqHj1w2YtVenLvW6
-f6LETiJoBXeUEhnieGbZb8KZQIv5cn3FexwER3kGLKatx5iGatQCFiSeRtjL6soDvKY3ghbYwRkY
-iLtQhOPEjZpppAht9I53n5beWYdriMccre/Byqw0n3pJFo8Tt32z2QEY+m9dPiQbPMHGlpz42MNL
-FitaCBV4ysgsvfPLw4hhhB5Wer3Iut0KFk7vsGA/aaIE4bqJS5zBFcYbdzMwkm6BD2pkcsBWxjBL
-eSA9JMdfbyri+m8H7i4DMj2f2fhdZmpRvNl3Ou9+9eY/mDfcJdpWnZSLd93X/3uH33Hrzcm8XNvw
-w0b2r5t2wTwBAwJqrN6XeHH33nJzMnQXDrFZzVxGZHyfN6HiCUh/Uax5+pfz2Wo5kdTKGGLmNpfc
-5s/0UKU+4t/w6WPee9fy7iP2AWgX0Pr0e2imrJ9zAzt3eW/r0ntb17wpmobqTZFkZ3dzvloWw5QN
-46GSsZA/6rKxOADqAp10j8M3xxrIXAzK/4oPpBSeH5bHIba5Tq3Gv6PRHEZWsswWPNTIusIlbIlP
-rRx5Xdfvi2lD1ovrZ+0wUL2BEfgbKvORqYIdUDBf7qv/usDOxxicflZk3YtbXe184l6E/NctWGMu
-yLpmkXmNi5VqD6czPcBhf6v+yLzHBVemYsSvdHGhXsPxqkSs8fxZyuMf5YfxYgO5kRAipP/9bEKV
-3Gus/rper1r4jY6qLoq3OlO98IBZdaZsTb0WcMBPI9bIXp3JrKr1m+S0mEUrOhX+qrq8KqcsTtIf
-WQ+zerzAylnKxiRproanPeEZIHAedloURzL4u49sIzfQe1usgNTWoR4OoYsBuT0iLNXFp6NHRIos
-v7nAHnXZ9ePYKsIFF3a5Ywk6VD4aa27GzHRWnpjt/ApYQrF6geAitl+qDSxeiUJMSzsRI1QxIZrb
-9njv1x71GhSMJDtwFuLEzS780m9hLL8Uu69imkbfeGlpQmCmE8NoyUhthab961r7lQZDoBUZ1QWc
-IENKDcJx38NTkiiV0IJ83VP1rcN5kFtR4CMa75be9lNGLp6sEgLXYTz3ZB1cE6IYbyN54gY6ApN1
-XtAfoYF8Rwx+9vFiNYmelv1ZtThDwZMci8kEHs1w6S+gplVZ1EeHd4/pb9z5s2oSc3PdpgV2/eGu
-cUH2MUWhWEcsQ+OINqMPNs4tq4itBU5mXRn8ZOuLIIQn9n/RNwCc+XIQSYXtAlFxEhwOjtWp9Yry
-utAv+9psTg4YTUoHdXJ4+FDICNNcebyt13mXvflfAWMjmJlBATVfveu9/sMtdpfs/BEEEriQO10x
-EpY4cbCWkluyDI/LXfc7nA1JuUbmSaUzEnYuysVn90YY6m6CMlJtrTMCZxwSK6hyGjGGFYAMwpZG
-YFvrjW1+Q/xuRFcBWOhpCdc7ZL11FspKMOGqzk8ni/UsB9rYyNMRCkyoY8JyIMPJepbdzaV2//XT
-54+/+vbps1f/R55+f+fOnfTm70z2TjTRzy/KKdyKKKccwOtvFkvYURlI1PC/lEObJb3kaHDPy4Eg
-jRNq3bEHiWPD9CGLGRJ7TTHLZzBnja4tmRJdBNQw8umN5MtHX3/9+aPHf1Irw32Vi3UGOCkW78sV
-sEhiRI+ff/3mm2evQCT+3R3hc/6xdSP57rvv6N4ICzytLurEG7E8OCQn1dmmRk+IdbdO6vGiPL2C
-W81JudZcmgfyILl/x2c7ZoC/u6OxLNj1kcpct4HpTofHuaGO6ao7KsgrYMp61xNghxe0UGMY+Igy
-rmScTxXq5bSDRAMPfAI3MvEt+DDb1OdeQhsMGUGJeRrZTljSdpKPTt5BeThWOkkhPjvXE2tSpbSe
-NKI1Jr3SlgQ1XuXoW6O9t3d/afeu5Q39EiXYq6yZ4yPrijPJUff7y7snRwf1HJPGTqqp2EhRiDjo
-57iXRKy1CUqzmGHdmXd7QkOPnr16itYaDLJA6/faXFPZ6QVRHozuFqdD6YSzbXCaLdOEZndlBsFL
-JCcI9AzMHJoJ+dnRJSHhUgAgsEtE792tyWUFsrMHELBrepMYJj9miJVB8uXzl0++evn8zbMvRt/+
-8enrJ3nE22WB8s8sqg7NPrub9zwoL598kUd9ZlZKE+aDuBeA+OrlkyfPYgMBwaNYtAD5LAbkr42B
-3UiuihnuwjiU+wGUz79+E0EJQDmZbYoWGL+OwGgOBF8LN6vlrA3Kb3ZAESTdSCZX4zac/DaA0brC
-F+f6guwD+f2+QGg3RYGo0JhrEtkNIRL7J0YTduAJ1kjMQRA+hPPXoW729NnrJ7DBX//ZVnz1+ovR
-8zevX7x5Pfrjo2dffP0Eej68e9f7/uTly+cv9ed7XlQeYbGOm/rDkHwVw+SrYv1qPf0j/ZmFcLft
-03YI3sg97QaxsJrbPIbjr5oVpCdkWL3+hZWu606IsMy1/1Vy5/LOqdIJvLLgXgPnc+HKGK4ELHMH
-OhllcVrxy3UveZh8du+3v/ld8NzoNCKco5zqBNlNdKYnhuHZnGH5Vqj7z8BOPiZkNKDagxZP36Ae
-lWWidpPMbNOKbDs2ywyr+DaT9tmyxHF0+Yzo9pqnhv+mip9Daen1k5ffQEs4ArrTzfyk22xBVno7
-/NoNaIlECcAWZLnP2t3gGsVKb5nRSB0jqM7ITmYgrw4/u4MW8tMhnAjMqIfA2IXbDoE9x5/TkI8O
-ge0KMxwC9ySONgQGyGxpCGws3vZz6vc+9PsS+r0P/X5F/d6Hfv/M/d7/rLUt9Hsf+n3B/d6Hfh9j
-v/eh32+p3/tt/ZLx/l18FEY3W+jsBOSGt0OAUFIWquFvhXZGIlKImbT4VsOmgasYWy6RCAgHY8dJ
-uVO8SU/QTMDcPe2DU2vaKCc32gsvB8VIigWIOlAS2nK0yo9G/yRwWlIJ2aENjcBprt+X66fPs31S
-Pbt2wFn7wmGrTZA+Kdg3zvygyREAGJErqZS5vp29+RHmmZRiPJLMT5C17FM3d2o+wf0k3axPD3+X
-BmBG0r2n6uSQSZvZbOuVwasNk2UGggJ8lKeoJyu5WQgJ2FuEv8ZWNvfAD2Ls95MI4U7mDt8jOWWf
-Gb3MSY8dVeyNm0YQPttYHoYWslE7O8Om2iKp/ROqc8TQbrN4u6guFjKuAQduyGKhc9Et4+KIQvJG
-MmDUE22x4cbADXrxF3qzkowHlvpxJdVqo1pSsl4Vy8n5eAX1yrXd9ZbM5O8Al7jZLSFGd7ymU59w
-1R2c3m0rTn+0riSNErIz5GRozYYZoiheFj7A1+WJ2g032PmV6k+qxbRkfer5mHVnCKKXPBgmzX5R
-AsCptic2uYGJ7S7Gi3VyL7mV3LuJAGG3zDCjBckn2LwFOrcv+2iknKj2gubezWd7AzH/awDQbZJD
-De0wudcChFpl7c16ye3bSeZ35RPqs+QjASAKiRzoY3IzedYJg+s1cithGyFNOpZm22Rft25bENay
-UgFWYS4aRmygbh5Zazsd5hT5SAU8pS7XG8kGwBEigA5XVcU+0eMFB4uw0IGekcQp9kbuQ1uCCFZO
-NjOohWqogt14eVOMxSLQASJz1nSUpAhPb8KV+MGT46/ZFKyfRFTKAPARuTq127MTGPnxfrulJ2/1
-Qj6RD5q4vGWR6XRJ/kFGOmhOmEusyDEyeR1lVhZjVE23iEAv5U7c3J33Eds8ayGF2s0TeqJCmSWr
-o5FKgvOXbVLiJmAWsDnEzCSbFvn6Qbj1u71K2KM9GDAjqxeqQ1fF+7K4YB8kMuJG9eh5hZey6qyc
-dMLZWQnHKOv0+yJ6KTxIPqNvGtmYz6ecNNNWmgOMocqqNKUskuHCBSQpda/YqdIJvaXHnpHe8Nie
-0BhanpKsPRTJ2ocF5TbvHtRdMeUhSyhU4UEfNo1x46B2q0O0LWtCYQAiNEyLa4V/UcNFXDbkUfr7
-RShReoYH0W9+ouegR3H7MUNeFWrQZltWy3XdDD++TVBsik2T8QIbYYAMiSRySANAXgaivH0gSuOB
-dUcNlWsDM6s4ZrxJqH1Rc9JKYK6LggMy0ikGO5p5OfLMWvFI1fTy8tLkxZ1XFARoPFnTVY0c2zF9
-bsUmkPSI7gbzX1WOpIXg3/LYLZksEXJh082OVE8f7DMTdeY1o3pgumy50wnK4cSBI9KM7tA2v5Xc
-De3t9Jh50t5ZExKlRMUXFcO3qEAXbY2oGXytgwqudd1TQyvJYg7Ke3L7ayvnPlJJF4RDHZ3gxTRQ
-2N358k6jvmhVXbPYCff2gt0jUHsBXEs/JkXhtWlXt8FeFR8A+uWTLyL26HrEwHCuDxYV5tvhkpbq
-+oBJ874dMmu9PhD0X3fips043UAMSebOb5urdj1l799EFPsAmSkYn5344NrzVarh+FGPEWMCxhM5
-qvFSA8dEDfdhDJQvpjh1QWHp+PGx7rTKAIY1WjWWp3iNaP6o8byA03barutrU3UFjFrBgkrqr7j0
-Ph2vxxGxxwAPAlFAZeRQ8M8OibExlow6cmPgpY8avaPZyWnjZZZr+WcL6gob508nbldCx7088spX
-6IK/i97WPAFPKKwlWsaAePGtmCpMuI/OriepxnOUeo/y+Nqjx3+iSQ95c9+h50iMhUg6tkb1N+Ls
-KNXv4iUSlXXmJXyxHsOOJk18P2xNDEm3vtfSmnhpozmwr8Tr/H5Lczg4Go3pHVA3/m1Ywx5Kpsbv
-fPBlTQHW4JaNfhjcARqlbMUkIBINxdFTk4AQaptNfazejTaN4FbBCHF7bzsMhWEFJMTw/e1AVhE0
-hHj+7Z2wRojn30U7CbHNRP3H5y9fo/0s7ZD+ZFSfY7xyspkiXvf4+fOXX2Ty+RVZQG1WmnsBwy9m
-03pEPjHd7+BQJZgtkeSz7p9tjWPVzatvHn39NWDr8ev9+/q6OF3v7O51tdxZ5yVqg3bW+rxar6t5
-dPSPnz979fzrJ6NXj5FmRp+/+fLLJy9hWb58vv9sphevyr+gHEUYbx3F9OLxZlVXqxfiQrWzgRJk
-u7nljP1vt7WpV8wccbJ2YbYM6ZvxZTnfzLmRNw3lEOUJ6XBRmzadogRZaERG6SZXcHX57F6/2VKI
-Ny4zAD7dk2sLyJam3mgj1wJ1nqLR93Dbyvd2jcF18WqCzOPzzelpsaLuvo8YIeQGzsnVqjjNcAC9
-xosFlvqaqqax5AddnWS+cbSoa/qrzUmNZscUtY7PZrYLnK7Pc+U6TQ8NRMkgtYyXypHPKsvEwPt7
-zD66qcmES9z46MIKx/i0rJez8VU/hoU+b6j+n3Pvz+/gyny303l3883/gva1s+qsj8FeoaN3t17/
-P//jL34Rd6f6Ql59AY/fcvWsWdQuB4qFL6KAE8s03PbJoBr+6xdjE87qdN7U4C4qCZCxqPb2Ojyo
-BwdTY75uu8g10Ft3czumngJcr9vhmvpioztelojUjMwaRI0pSICiydtZ8b6Y4cu8MV3WIvENtsPE
-82pe1evZFWyyF0/hHCViYrPse/37t2XZ6v7yqlsnJmqvbLsbSKl0rqK4oXwEjNGIvibZIYWaT8qo
-I9aaZOmOf2cqBgm1ggp31TMonrhDbto/HVG040lF1yLKgXha4uuj7ZIMRQ7vBmY71HoQODMFUMPL
-1aTa3s8Q+4m6+dOYW5TpFgApkODfaDU//NEWowLBTsOikru4pTGpF8DM+8TIei0xifVoGRJvLHwF
-y2DFJ0Ui5Ch5xjNDlJZOXUqDLCRY9xP3iKVd86PnYkc3mt6N0zq9/HJx/P3ULKezxACyXWK0IyRH
-sqSwvetHIOIN0ILID6quxhd0q7O1mVZWrB8UBuIjtKERpSQDq8Z2UDQWKkadLtqHJDlFDSjxumq8
-ZNEk7m5ZbweHxwYUIkVxWLaWmrTxRjJPC12V9LSRuGRDZ6Z8PXJtjrcM0jZLH7Be5WEaW14ByjZk
-I9rHaEejrckXHlM4XczEpoX2O7BML4oqtlnM4AY/ZbuyFPjkhFPDNMqrNGKvI+MyPzl+pqdO8+H8
-A5IbHpZ7ALPR9bu2FTrcIivvtYZEJyxShlIM1jgKA3ZFn6hU30hq49XZ+zCuyp4uTzdA9jgpplPK
-Q2ajgsPBAzL4ml8mTA85vXOcbM6SG7/77Pd3f31327C6Zjrd8A2mueRBU8aJBAVmQeGKzvM+JefN
-TFXH0ljBFBFmmgIKg2WeY49aiouP6STKSbnOpBhdYNbFWbW6Ggq4vEHgQ3wklPo0RHWbkMR75muY
-eY9jawHwcDA23FANUi7r1v2ICUApprIBAlRD2UupHnro5286KAdezmdnxeLd4ev3/4Wdq4TeTsnc
-jGLyudjqq3I8K/+Cf0MzjsKzhh+1uePVnZMrCQUvcaskCrsEJ4C7dzbpYZySM+Cnb1fFWxQ95M/x
-OpkXK0DC5jIpNv3k3p07v29Na4cmnZ1OzB/14RAdUu8okXST1RHBzX3mt9rs0lcaGgO/S7Luk0pN
-Az8Bd9lXdbKmPRUC6nXc5m4dlxmNqJjlTwyXz7/sM9UzE6v+mwLOISzK8JbkieJ7BgI0wTdH3Q+J
-BIigsbkd0K7HWVtRlAhoJiB3J53qcXyG570LsSUF6rhECyyppWQItjRWVndS59pzo9HJE9aPPzXf
-0eFiUE7eXvFJGEgMpulRF3YKBf06DsPBTOj8pgd+jqGRuYlKaJy8lztQWhW9VrEXuTFAa1AdlFm7
-6fFZpmJFSSY5BOJp8ltucS2BCPzYZ1timHiwWgOW1ZslvrWOz/ga1rOZMjM/wgGHVOF1od80DxcJ
-QfXstuSW65vZcnBvKBbroTgeyL0PvRAdmE6Da/CkpOk91cPMtxJ9RfxQ7EL+CVPTAr2ZMFoGQE+S
-1vpRtcwVNmUz2Flvd6wdc/J7gZZajUjSBwcr3CUmhtLB9KEL45iUEuULunU7dxjjP11bBjKNEFae
-AA3/SD121R7uDhIXlaSraR6+IAmYD3qPwSdJqfiTfZL6IxxASNzw/5rlX3N1EErbouQJqYZJASOu
-jtuWaZOlac+t1A2KTLvCkFSUfY9PTJtoRGaBhZnFnvFnUFiB4cpMLXE6vOh7pcKxcYM4gjPsbs85
-6zlZoTvOxycnq3w8WVWLq3k+nk4xrnSO4R+LdT6Gy21+kp9Mq/ykPMvJmyB30lr3BKStt+821brI
-T6rpVQ6QgJeuq0U+GVOggXxSoMSYTzDFES4I/GemIcCfFPwGyufoSJBPp/kUZILp6SKfliv4//f5
-FP5c58U8JzFUt2Y1Mgz0tFrgf1bznG5mWHR+Nz+/l59/lp/fz89/nZ//Jkc3/RwRrUGUeUlN8nJ+
-lpeL5WadY3bCtyfTfDY+gZHMijOkhVmZ0+yRh6Kcp0DMx8t8Pl692xRFDnPY5BivJ+dwNTDbRQVo
-WVQ8+EXFA9TtF1U9WZXLdS4bBtpUS44ZlHO8hnyZg9yav8vrXKqq5hzePa/ncMXLgXwW6P5dvi3w
-nwpGWq+vZvDH5gT+f5mT0bduvqaVW09z1BfRgq9Pq2qdg0C8Joyxzex6la/X+SbfzPLL+dIjgjFs
-SPwPLwIh83yVo5ppWlzmFHk0r8fQ6P14xe16Eq22m3d75DZ6LCxNnkRwxHufS+GdC6k8T67YGr/P
-6SAiT/8YQPfS3cZGeAs77PY6baH6uEOE3LMi2Gp84Q8TpNV/wSw24+SkumTrWYyqKq9cUGzEOb4P
-G/tayj3F993FZLbBmxYQP4CdXZlkbtVmDbS5JV4dQIahhNpVLmXpEX6YgUcPo3AmwNBQT13C/e49
-V0HNMwcKknlsjaAnic3MqZqj1tv9oXgqhcCIGS+Y137/02Q8OS98kczle6c0Fj/+BJdWJIQp3FRZ
-x1SdmulUC78ZD4kCAEyNK5PrywwZdSjmd6ipXlHaLe88YV8kO0V2mzF/oDkg/iU6feTXqJwAadUd
-7O6AyZOFb+WKS4P6f8pzsMLg4FihW/PuuU2RSumA8UO9sbhJMeatRNCu8qL+rc2Fw/sRgDkOtV1/
-Kq4iugNcAGA7IuOTNAo9z1dVKCw3+zvzNp0BYuWXtrCe5akHp9Uv47rK2wgyVHT2JnESkqCmateJ
-wOLcAm7NGaZM2t/MN5RFDn6JWeqwt05mRB+spj11kFnFQPuQhWN4tkZ1fEwSYQbEQyz3XJxkK0b3
-55E0OA5eD1y2AvgauWfwjsA6anAo+YmvlpX//LFh+daxNUgfWsimNostW/zI0wNK0BY85CLE7wHx
-LD1DXOAAfVxAiVGNyj5Y453I3iRpshGxvnErV+zLeN/yjQAPZ7Ihk656W03Ak1sg1HYTOKtvBmB7
-wVU8AsYN4dZQM9y2DqGnBxha6CF0B1cQGWDuLn38ok9o60XM8GStjLcbVmvKB6IVaLE3Zkq73AIc
-bSl722Zw20zAIHgbYg7jiGnyIoQk916BeyuGlqhR8YizeVICjJZlj67EbVkI03fodhjnmA0wDx1K
-HCiLHR281c0ltrFvWC1koap60QQkTi1IUDjPvq86MRX6NRzAag1n7T6dpkmo97PGo3QFt4OxnYq6
-LVwNbLj1ZLKxtVeFUnrM+iCfW/9NYAwk1/M22HEFdd4W3jglRC78XbdrBu8dkz//KFQNUsgxxaE0
-mJgHrHsu6UaDqKt4yf57i5pWNzmoh+lBnXadciI49DjhgaYni6kYNalsSxYvdOCBzFFyKAGSYgAA
-pVLW8lTj3KBuJAkW0gD93Xzj2+PVRYZ0dLz1xRegm5DMl7e6A0DPreRK7j90b7ADMregKFaPkLdT
-VcYtblEo+kfg90xCticvyLNmJxa1ARUBuvD6k3FYIvR7PYGbzPtitSqnwOpojCLbFbXGrdbOOcHZ
-610OsJ+ra3EJcTomc0uKXZ16kgZDMiwotUui9C6dpgHZyYr0DnTt5osyagzg9kwqBFI40PW6GxVf
-u6yvoCt3V9+pxZ+7NE4/+w5nnKA2KBFtUHKSmGt9cjKtkpPyDCTmBHU5HKZqeopmSQlViIywWyYw
-uYQGmbw9mSakUEneJRgCbb6UXH4JKS7QAYpeSdC5NAaLlRm4ZqgmToyyIlmvk02CigUzfSDb3vFH
-MT16CmHZ6iOYHtdtTS0Q5CAyBE8acEVuRhMezMLr+Hp70kQ9EBnTSMXc8Do7rAUQt7IqEokh0GIf
-1vAF4FT1Q1EYm/8BO0K+NMAfv0J94z92ezn+8cCWzmzZQ1t2RmUhpF/Z70CE0ijtprZwWdWNZoGm
-AT2Mi9PRqrik2KN9zFyNFikA6K/m4FXzwYxvwH31qTQSxZO54lJSt5bnCQZyxJmROZT4HT/evpcQ
-ZsO6peCUg7vDoWDXRbn3tVH+8SZg3MNjZgBHB+lQ0oc9Ki9ZZpJuUJ2OXWKhDJDB3vXf/M8mWPxq
-s1gUq3e3X3/zWw4VDyyonJhUhnSNgSoULX65qtYVfEiII6P2WLzhKc6nb82Irv/zoiOGdH1jnIZ5
-+7ie8cJ4CRttv5TgSg09LmddSysDipGeKwXt23KpP+Pf6jMPoFpxtUGi/1bVistyraHg3/z5p07n
-RueGjNdkUqZcVp86Wn2OkQndH+NTqDOMpjH3QtlPNyteGZXOvJEQm6PSl4t1GLfehb9/pmLfm5j0
-GKX/WYJ59DiBwHqzvE14sJ0m2bPhHY6JAGJAP4Wt/SHBoR284a4o0baqzd1q2zbOg71iRk+NnOfS
-8+LWwkIVQrpPR46n7FbxlqVBwwnXmDnA9xzjdvFIYyL6VKe7sKGOxWRn6gNX05q66xbwweFsPD+Z
-jpPLQXJpEdVTFVcFWnOo0P4E3SBQG+k1AmMbKvDXP+1FTfxaWx/UIQAQiO0fKnq6uWfiv0cDW0M4
-s0J9gBvU+lH4ZQz0zH/Yd4h0MID1w3x/8CvtddqCKN+51793WicHh7+TCCfeauHqWOTm1M/FebHI
-pesg660EnCdT0Ez+kOWXv/oj2lhIZci5X+Efr/APWKUmoFM44MkRbgek/roYr6bVxWIEGzOzD7rP
-YIwuw0/kXQFNvNYOsrMMl3K015Wf3jzl3BiZcyPjHLwLECUpj+3AJrztlzqlsmk3q84YR8FKDqkJ
-/3aj41LzVy5mV7Q3GF7LMIZ2PM1sqSTPRlvD2CQir4WjjG2RDtkGlLwPmbdIy5QWJCUQpkv8TA8a
-8PO4Y/UWyz7nktPbnKrapNXxHrBYOvB62NHMkAc3day/iSkPVQI8uvQ01yxc7RhtLgEMSDSZJOGO
-wMJRN0DJxyzexMxoC+Vt3ScU+SFs7PdEkx/hb2y7qTMucVbX/DfxA7IFsOvv8O1fiaQBx+QfxKJC
-GSNIedSbkYNxjvbmJ1VdHGJqqpjiIaWIJ9jzE/oPepimvp2t9I2i0DLs3ECRj8TCKT3Cn56+ePHk
-i3R3TmJ0nOb/77AI9dQTJBmxceJkdup2HT5E28zLEnOdWpqlR4bitZUWHG4dPuIDpGU9apdAeYwZ
-zcdvCzWiIYPGLof4H3t6YhYR5/sU52oCh/8ZCsE0t5TCx65ZDey0RK+XBr3imwK24GHK/M212uEh
-tzC88TyGMZAXFgsTA4agESHj4GEN8T/2fDGN3Tv3y6IGafP2E1LMmfxTyVg5KCzeCx93d6QbbMCE
-D7e2ocrD1Tfh58V9zD4BxaJkUhZAGqSXYs448VSnagQDci+DIrdxmb/qlpp3pvNiXsn9KchhRkxg
-6BZCRdEcE+XhpamP/8m2xIuJmp+LYhwRKykus2igpD8VVycVjPUp2gmtNst1S1DESNuWTh3OjReI
-tz46GwkK2rOryKMVXEqWwfR3mtzZOAPcf8M/B5gxboTCDEZ80TiIlGrIYnxvu7OPAGMES1RIsR/l
-sjySY9ZQPm8KzDFbP3TteAMz7J7N2lDPxu8LHBYJnsoSwVt16YKNC2wTegvv7KHznhrDBNvUPZeT
-3016UPfp/0gWP+pqg+/u8dHgs2NPJgvHgA81COXooD5OKAFJ8oLt0l2AQD8qxFG3nHaPc/xRX9Um
-WjGWvMejDYo5BRk+EXQj4TMNs/l8XBcvmb1a85rOfsZMLca1ihJVkhh5n99oeymTEMc8U5m/t2Rx
-J0OSMNvYZs1h8xrUwOn/kCSimeFNfwDXjTSEbrP2qMngNLaQvx1QrToxyjXJdjxE7dCyWK2vMn3h
-hKaTijW8KdeUOxZLN/s0k6xP3Exkj33aGTFFxvkH08CFD0GLnvNtdspyVzRJ4eF+iB49MUEzkA5Y
-MBCowvQpF6Tl/OayaD4gAzyUX2MJi2AToreYldKxbSod94IDkIDJn/pqr8vdtC3m7DrFyNoeqj6R
-bOk0Hi5IauTxE6O5H8zQhBaiBI3hbIKOSaQ1XB5fotwITAJ3pBLXe3vPhpp8sdb1SV6KOIzJatyI
-R6SGSHtoJX5Jycq4IMGvOVxExmfFjo24DRPlqSMy2gITPxVjZDh8h8LjVVJrmaWJ2BygX5qS2Fj3
-x6lEWfbZ2dFI9zRaXvmdmZs3LMtLt5XsPT9yvW/+z+yG3OAqTxxXpAO3paHZj0OnIrMB8O143OGi
-jDY/J305abDkAiFG/dl4VlcYEZHDZjO6KOKA4ItWq4Zl4/P9vLgittjrG9itqZID1Yc/qd04gLFw
-Gq9hBkRop34Hj0QKYhtkXqasL+Vfiql5FijFBjIpA5Mzq2rjHx0NZkxBgQs43vF1WTkAwhAqdEwk
-UuCo12gbWk4ko+65l9EZbuSb8czOnVJCM/qRQpJD+CeZY5gVfICelhjoAm1+THwIX96n2cC8UMQv
-+md93EPjxJkzlovzYkVGrtR+rACy215/D5WYhwO6nx0+lOdKlzfa2CyT7x9cZy3zH+vYlAOKS47O
-oECa1aSkzNsSL5hx4G5OQd5jd5iYn97IqLUlmPHsYnxV25uPHAm55Tu544hBP45HyS+vF3ODG9tU
-xJQusDYqgAY6LQOxwpQGJ+Pr0t5Cg3LcUfiv2WJdtKAWWircQxZITOHK6auZ7oKUztAHbL0JW8BQ
-FDIJ9qxTQl6cl5NzijaKgb+CNavPYWTjkzArgNmIFF6DzD4novX21qbE9941QIVrO0wI5pGQ2Tu+
-LOKMfKBKtjA/O9ulXN7018go7pgi5hQ31xtZ8XhSccUf8kRfgBTVKKbL60f3ljbu23Icykq6K3m7
-XttwxSbbayW/tuULbdHbUKyERxQaR8KDjLZL/qxWvmrLKmDs9/5IqRkCpQOfpzG57UNkwIaDvG79
-c4lVap6h0KC7h4njGZKywQbJXn8PyYsUq0YEtiP35Co96mg0TXOLs7BQQ1y5uMmRHBOq18fcq9kv
-CkyrKGpreJo+hvMyoEa7cZsihQVvtIk4U2DBrBbpiuuA0wZ6HTT29BZpJyLNiOrFl2daNnMomuw4
-ta7HCKziTX7AEddwTmll9Xuz5uYd1ggZLYyaNQZ80eWFEH7LRdfh+N66IdOfFQue7PCg3s75G9yf
-cw1YtPVaDoEGTWubka0RsLYwchP4ag99jqf38OD0OMEVpxI2Ll7ukbbh2FWjsc404fdcuQyQbEvG
-E2Oy+6EbgZVjyUHJbr96i99XOFcKkhM7kEj7ClI8xaL+8SdlAT6d2m82j5T8neMg1JuZmRHs9PEE
-pU5b0wQ7ZUsnadX3zg0uMzYZOScsIG88GIIP63ysUrXWHE5nGqa08J6z+3p8oV+KSx5l56UySDlZ
-S6rbkS4UTlvRqaOCSMsc0N8zz622pt5vy2pJr1z2iTJYSzOEoRpB4AbB47BYwGuAGRUzBbN0qluc
-shu5rHZziT1aacwXh2En6nuGSVAxWzeMKLOg0DwepDDXzMJT/m+ZXtvgebzBTC0umgQZRj9jyrUL
-42dTD0lj1DbXkJRqe/mJU5fjSpqsA6pg9LpWsfAQDcq6BsX4iylTcG5Mbq6R4fJjuQQAiL23sy1B
-MS2mI8fZ8ECWauwzJX/08ZCcnI+RHGLHqZvFurqAX3XWAB0lI1NbZItGm31xbV6fhN0Om6COBvac
-o0q9SJqwpkNk6xrauRhLiTbypwOHdXMcBAhu8xXrUdyJkhBqDc/GY+cw8JskAtDaqiWmmak29ezK
-B9/X/Da2vmZHqRX90LWUINvnBeC8PHUpFEO9FPB7fsacUihPlCDCXexvv1YzPfQPgLNCkA5EPomZ
-6unc6KuCes5uQtO+btiLDaFJNgHVDI6j76V4HBhznmrW2/1AjKNhc5zou7C9rMVb6nlIhDP4Re+B
-Wa/lBblzA/bFR/wP2qOeIXnOcqEdISc5QntUPJ8Il7CNjK4QZA4jkoUNs/BGilslrMSJj2DXKFdq
-vt3WTpOklXIm2AAbMZxwtpuaTacVXYp0W+/U7oKEKoa4yyuM0VRE/fXbwrhyE3qMp1/7v6MDrHhm
-JyP92iitfiQbh6CHNtRr01c2bwb54eFY+ZlVAVm4HjZWK2a6OgeyL+tz1Pwln73F7D6n47cUoHeG
-YRMkdoNsxVoaoofzasoSKkXPk67UcwZlhKIoauT8tLq9KCdiCzwasaaXBt01oLtm2F+SOqBt1OTv
-xnyIFciYJY5j2rFqB4ZkdCaoKYCzzlDGjn6fXJbrrGHMEekW47HP58UUdcX4anq2Gs/JmL1OskWV
-EJFgsNP6Nhtkl0Xd20GdNkkmbLu68uzXWmizMdB+5NJmYvfgsHl3iyZebAtx0Jm73eEksYh2G64d
-TI6yLozxTaXZZXIBH9ar8uyswOD3CtEWB+flNIjuw1HLnpieOx3s0Wm2oCp+k+TPQFYZ4SfVdz8o
-5XVH+wViUsgdSGnv7kuig+onICWuiwEwoG6dbOoN2ssQKMkisqYXJWpo6AZfBEjhVp7K6wAFrC6A
-TlaFeReAEol4Yp7QOQsnUDkxL5uJs+Z8g/OyJv8XwqtYY+CdVMgCz51iMQFa6WNwdDMgtvnEDrgd
-eUZIXBCg7oD37YF4wxQQq4R/X7GIttFcg1eAthCvQJR7Msnw/itm/NyGazPZrPBNZ3Z1uH2VvpFV
-MrrUPxh2K/7F2BVVxx1gXzYoXSTlUbSvHurd4No4EY4jKHHzlH97HezEwxG36DCOtLtLBiyGHzXm
-lLC6DoIGK3ddbgZ0I+EqMbA13auBws7LMwyMMhoZM6ERXuAX9rmN3TSQlBMMlEVZIZKu67KbHKp4
-7cQXtSJZBAx55pKdIiQlh76l12tg0ziRWRxgCr9u8R5tZjB7SIV2tpNzkHXgfL8kGbJuWmIBHyPM
-ACcTQD1tgfWUPgbmV97k0gmmd1a5OyXlsBmW2PrMORQKyF28APWRVLD24g6fbV4vCKQjRl4S1sAo
-beeYNqirVrCrb/Z+FHPXURjFnL8g77dVjPVMP+oWYhuQStS1st2akarrsxQpwMkDAdSGYqHZgxUR
-rKbTA9Iiv9uUqJ8ra5PvOW4lYClFhqC3jW8Tj4h+d+fNfzBedoYnvrv7+vIf2M+u3ixptUkdCJ9v
-XxI3MjawLOTKa2+/4WLHcFV81o9yPdvpUbbaLGh4Xc/UwHMpg622KciXrF4PU9NAOZdJJEGdbYJc
-yvA1k+znkwJ5LF/rrhI8vGj604Qh+Y9n7AFGLyv0y7yXsWMYDB7EC3pjFw8ewaQy2035zMR7mjn7
-euwsqDg+nQLOLhmEEATKz6vu1puiEQJwLXWKMmekA4GGAefkE9f0nK5uNfE0EVoVNCFXjtNtrJL7
-IGmM0V6exwgDR0vJvjmcUQXxfUoZr75H393Un2dt7/mSFRPRWy0kYwY0sqd8X5r2ro1PWiaNzlwE
-RLnOwELLYUwLyyMyo7I4VgMf1yIws5GGHJ795Hl4ngC1SFfGYZWpTQODaV9VGwmiTZRGCaeBzfOZ
-HxlLP3m0uMIM5iX3p8G51OXsaVubsHKGQmDAGYlSdG7xkvX4cnlKhgvA0hQ8Hi8dZSzDETg8FTCf
-+hJ4HcisZmX28Zclk0FakiH91z5UfCcChLAmX1r4gHvLpbq40MC4QJbek4UvjcAViFnWPMpxv0Dy
-Ymj9a4hJZprcste5bIhF3xm5iPHyDeBdtqg5rCP3H9Fs+q757IjP6nr8J3h5dKFW2t7xzqvZVB5f
-WmxRPWNPCt1vYeuTmkd8UlWz1rc8/MiNuVdzMV9Ui78UGCyOLucMQiX8G9eAGxOaNmKJvg5tm0lV
-5gBgUPRNETZvqKr0nEfSpte5nhOD78AQc14w9v/bVVlB8hZpc3T3OE9ekVBIcl1EHcgX4CPJoKsa
-9qvTU6D05FZyH5Oup/+c5sex1ka1l6p+BmjchUsgEmm6T1woHonEs7d7ps+3j5FVgIyqxewqu2lH
-Orh37ENXzCJLaTj2JIRNDIIVsIcVu9J9v0hbjCyBCeB/DuqtVQ7q9o8HmupltGgIgFHTOAwE3hJ7
-eSsAc1nisMJ+/irJixGSKAW47FZ1d2DwWMHJhoevK6GIB10+LKHU7VgucuEskMGZJzWqgEFCWzfD
-1FgBYLP+yKQc0ZHn9ohu5EPB/xhADXXe1AtIEtuwNmcy8Y6gI53d1WAzHh2Nm2MOi3qXLxNHBmrm
-92Gas2r8rRDVnhdLcWXB0b7lmbiaOeqDuGQ8TvJ8mY5wW2QhAeQJg5r2onDaE/k29p7bZ0bpMBYJ
-JO21zUi8llo78PHdyJh0bSReJ9Tnlr6FJv3YpM6uKNzC5kzkaEN+UIuWQ1VohuPY06HqNfWBowA0
-XkTNbfCToX3KqsNCRzd8HRdTL6w+2GYDZk/Q5Sr22mTdaffAr6lr5dVBgr6gygluuWqwARxgZ0+H
-7oZzB0tIQrRfmixQ0VAVuFfowjX0pS+B0WWp2aUmMvX7RjBoufDbesGyySWdnRGwEgukLb3zjVfu
-QfjkOKISEJQQHRFP9eUVMVdyVOffClERCKqO+Pq29OKj2rEVEwDF3LYVRarJBdPV1GgLIxjVBGur
-MXVvkLSDV6lwIfgWkB49e/765Ztnx0R1HpxgYXa4VY1GHOCdTHaMGK68rD6KDm9gzKX1mu4idKPE
-azfGgaP0SsZYCy75o83CXEfrDeV47gTvxUI7zYpdr+slCdlqSn25hfp5tUwkkTZ3nht4lccnZHrJ
-X40X9QyfecoFPnVVF2YxONF3USeXaNgbyNtLe604EpI/ZldXZGHMLVCVzd44zXn1GuC2GMs6/3a9
-aJ5xrP+2utvUOLjX9XrxTaB93XF97LdWJm0qxO4nnYgpND/4Xn/Ag4ajnNrgMGzSumROo9bIh7QP
-Le291N4EWHOlH/Iiaxy34fYXevcgdzGs6zA/j7HZiysrX/bgeHHr+OvMfhu223lgcJrv6863Y8t9
-ovE0d67AkFhXFrbOHzGL9xqEusB3XzHwPLlqBOTiN2t817Wh0K4XgMUfJ4Y3aQ51z9Anl8796ZL+
-QxsyGkIlFr7FgnH+VN/Rf148evUqDdBAysgAFYaX3Oan1Q8Jq9Ye9Ex22JocF6AYIwwqFN3QIZoN
-JuxrsvxpZqbjR3ugOXAaShF8h7/TC6pGgm/98emz1wN69u4errrymogHHh7O7IeVNoEY5TejI7TO
-qdNes4l/ZxFOz740MJDaDwiH6JFocFF84fbFKrhzL4Nti1H0RoLCxkKxW2Td88nKwvouCovxfh1Y
-uIqnX8aAcSbBNlg5x18spnBwpl8+evo1BnRo66B+Fe1AXvWvOfMnHzRYerjtmnhHbrAYqwereDHq
-RuuLvopQR0lDWCpUZJT6hnwU8xcmG0BTEImM8T8i5e41cNwpecKKOrN3L2KxEKEHP6RCo4bbdPjL
-JXoNWJSKoBfjXsuq9mLoNRLf2vhiPOjkIFuipqynZ72L6LnLy33mYrmxndDllhldXntK8qA03HKG
-RWeffmd2BXrCIAp6kZj0JHE1PeY9QIm9qssjhofJHVteMGnjc2zFpBebAzEZBp7TmAy//YyYxIPR
-xoxhcvJRoZVuoarNuxg6e16uxDcAat713C5ItHQfXd6jWACeRvUj7Py4szVXzw31am/LyAIxefgQ
-nyPq9RS4Vp5kKcE8nJe1sUxIfH0N/iXpSk0oDWPWwliYQ9EwxeEprtUyakzQJQJhZgB7KkuTelVU
-Q6eoPZsSN68z4enGLcuhjRS179FjHjW1oXQF1EBdwvdmvBzxP0CDaKhHeeU/A6xQ7RybquCg2gkH
-vngOONRAnGL9Q5xq0mfKmDRtpi+zySEyHAZX7eX4eGP7F7TMNHPfccLtksVcnBtPZupKeZemZ8i7
-gdQbTt4Csgd5yTUMxS1f1GqKROmBk/FIbsrtk/uhGF/PKzFo01FRLQCyZhfaCESuICT7KdspDON0
-5WUbp0+BJsSPMDtSIQq8EzxtZqdZbOZ5YpwkrVsw8yw8CyO9eWycQ/ZIbnKxR4TLdMubgWKG+OPo
-94PjHccABlhMjg6mGEprcDAdRALQ2kC0W+YC6H93781/MSZJvLnwAg3otnnG3332+r998YtfxDNA
-w/UDVT8c1Vv4zMpYrZFRUQ57do1KN+QdZ8WCqza73KzLmWlo3yLt1TNPPmdz50emAXHQTgdPnvX5
-qtqcnVMoeO12ASMsLrVV9mZVbPUpbsTCv5zImyKpPeT3+qT9jdg6tYpXsen9n8qimacQCym/A6eN
-6/PF4ulp8pjyMTt3g+qUAKB7JFz8H2eXPfZvKLAWXIYvr0yEmTFgQpRllLKQSy/7SfIa/pRAKRYo
-mehSc3k4eozULaZf/GJ6ssHnpJtmKDex2WNK6oc8yl1MV2iAmJwUs+oCO4OL1fuqnNK5srEJ/y7E
-lPM9TpxHQS5IzfFk/uwfA+orgwbGNmpuZHoRSJeCTPsIKsZzbDzOGe4RU8Y/gHsl6+jNukIz3AkZ
-EwGWMRQMwkNwz9eU7m9ZmGDiZM5jtMFj1RlAglpIyBRLxnWC+0FoUOMQje8dWmS9zPIRObwHAuZ0
-OBK3huExMmoCMBpBi9HIDUSwgLAUzjnrh7wXNpdyNMK6aLGLcXcYcaHdrlSCAw/qMVZhzJ9fmXcy
-IlXpCCCrzsvaAptXRrl+Wk789U4uzqtaDQUjwhLCw1WWHbOAq/8GLXOth07NC2wGMl7BV3IHwGAs
-1pSIs4nx1BQxkRH7l/SeTAZ2OWw6etxgG6zTcgUjn2HsFQpqb7tlQDR+7MEOf5hk/X4/J0ObPIGf
-rHlEEwsxm55WRY1maKflAh3UriReh/SAxmFxiCXKPQgwN+u0SOiDZLKF3wZHGNX9ak32+yhma1w+
-RvLBHPLoWA1oLqfoEMEuAlRNltXsqhnQDDLm98XsijEcJS9M/4Mhl1ZksAXkNV6QUTfQ69KkbpRt
-b0idjpQ17brTYLFzhCD5g3ASigR5juh1QL5/smqhczj6lusYTWSeRpZOCCiQ7TWmvagICyzNVlW1
-pqERpr2U6tM6OEcwhgRHpG20boR64A1MDcJPthFVsH8FgrNUtqjZFjbWd8yyjS02jgDCnplGW0Ax
-LZjtkXkCunp21/iVZxl7MFPyOC2jKjbb4OMcmCw5L4FDw46/IjQxB8ajQ0MBDo37C/1eljbFLy1T
-FxXL5pzcZntg1ksGqWfh8L/Fgk+aq2SwCgI5LzgQOd9MXMYs/5VIBLF+WTtMD8IgcDWl2OWKMI/5
-qvJXpGkvII18QpBrEqV3hu+NpHxsuHH0mCo+9vN84Vil7eO+2WPHnT3NU+wLAX7uNHO1OfQFhGcx
-qLemG5R4GxQgK7vSrLnver6eL5hb9KFcPfe5Ced8tkbuA64OMh7VQt3Vz6ty4lIfepQS0kj4kCht
-txhY6un6Wle8t0l7unjfjUKRGhgWtZ2sbuBd4QS1pGTejE+AyK+lbQws5qbJuv+1K5izA8mBX+8f
-tKZ7UGcHq17XRlz2pquSG+vt2RPlRkAdk5nZgjbLssqx7CoiC/a1ZvBNJ2UOqY4gBaRxVRazqW7Y
-caVQ2/o3PzW3NpQUM5KW7XXjEV/I4BgoCvaJF/+pUzi6+dFE5GNrVK1uYCZmmLLeHclNy0SIWUWz
-k0kaP9PMGsM1G9wAuWQ2O0RzVMKT8SlVBm447Lr9QBMzNJAB+k9so8xfzLB+H0NQikF29wEO72E3
-drQxq95VecJRz+Wyq0bxGEq+opsV2hORzg55MBY33lVNyPYVZe1kRWbDvtO7+V7X2tn5DW4kbkRv
-a/iq8F6syaJRBEvHQycjER3WSeUE3CyuSQUUKgnvAdcggm9I2svY2QQLXq3n6+xIr+hxbxdJwFC3
-LzL3sv8Cy7peFpPR32RhLdLRhX20xWhRdmxT/ZKFa9yzHOcZzCXz2I4AVOcYYv6Z9XUQ5oGByto4
-QV1tVhSyoHtAr4ZUt856Rk9hLYmRk1v7750uBIx46JvMPNT24v56n3gpovwPeufR7zn1/76nuv2E
-8OYqCeLtUuN11hV7aIiFEXX2/34u0H/LCNpyFnIa0md2Vj0eHFcLpTq2LTdbKgS1jW2zB5IJrjen
-KEJ7bGaputdMhB37kknE0JgYb2ySpAAxKjd+y7tnbfyrZd0aqMc3D48I2zc4uMdkw/o7FN4wGBHF
-ATHndh3T8tO90yMgfcrFtfwR83eaSYgaKm2eSfeiuGlZ25QeSKN5NRyqtXY9xK/P673ezJ5NR3hC
-ULjQ0aw4pax9qmiFAbexewv62hlrwj3Z7sPT+F8wtiHNWGKDfhAUms6QcWOEmUjMpC1M4np5dLYJ
-aGpX0YDMBn60mO6zeaHavhvXkEAQzrjhaUMSWVQKa9J2RNxqo2w9AvtyG9BuZC9YClKr3tm5g1Xl
-3q6wbJEt180w+XuXjq0uO57p4ePzcLdnY/U8X+2zUs9X//9C/SyLBGjZtkYUpix5Q0H41WPPcNh5
-WxTLMQWWIjyT9r82imD4tRxjTB56JP5RXmZA9AVaSzBhcBepTjEV8ubJbb2nGDlijfWyfw1q9aTa
-T84cgV1IiJpopI9W+Noco6omZbEKQZnlNulLT2fofvb2IJ7I4b6TgiKL5Tq1uVm7ceRd73/bCfN6
-B5Mb44cdK/hDH05/+0NF8goJWZvN6yiqJ7vh8zKyHfaj/0fTqdB/FsoMtxpnbE9tiFebk7aGh1sb
-frOZtTW8ubXhF+X7toa3t/dYtc7xYGvDF9VFsWoZavtY43yA1+jvwghowFFGgF96jbqtjICmGYfE
-GGjWvg5TUTt254aNsh0cfDeXCbezkb3h0QwAoMxEwft78iUSmmmdPl5o5pn92+Jvaqc4VRam1ECv
-wL1uwFLX13aYOBrbVB3qQUihSgyMEEKv+7HKi+udiuEohvou+3dWg4gpVYQZkL2Wn3IyxgbaZeP3
-Yw57rzfj6aI7YFg8/Z8i6+dVz7qerD22gnYz6IAfR2DM+ug/selzRJYVo2gkN1/jZ01h6VPD4z7u
-8+2g2cQvGo6P37G/S8et/BUmabTkCisHU9TR4WshothvgSVH0uyYJhCX+s14G2HrgvW4NbSDANk9
-78ZUHY2bybidbbdEJLCddQ/q4UGdkxJSxpibEfT26pwhBABa+L6KKL4aNSnKFsd3iP3ci7e65rJi
-u+7WxXSQI4uqcHgTL2HtyxbFGrVRQ48toEHXtAVf0x0Im7ZgbPqhKENboO0om+6Nsw9CGjWa7kBb
-XH+YHdS9pvaQ+azWHGKEzMhV2l8VmkcfxsQm0TD4UD9t2Cv/OBoc3j3uRNCw7WzcpT0EedpnSD/3
-Q6qomQhn6i2EyQd1EFp3T7JDTHW/spNpPqfuEHa7GFfpxwMkd/z1E3EdDG+ZJ5EHPRaCvhL7pj1k
-IKn6t3kFiB7AVJu5KZ+6MJztz2M7iWSvy/nf5Am+sZYy06ypvvcmr30qJCOCNZlLKOC8MyE28kjO
-BsiUgZKSXMIycQzt5gJkXfPAEuAqxzcBzlWV8vtdNyKIyrtmuIqmZWMttzzl4TRGZgp2OY1Y3AwQ
-db3V/rTLHY7Vi2tEek71/e/EAUjR87I4tL4fNp8qhaq2Fhik+zGPDuSQsde7A9XcxwSEvHOizAK/
-9Lx6UWZxg8P3s2cCb/ZxDaQn7mMP1LSVaYfPGwj4busXAxNPWh6P+9zZ+uCgOugNdt/1mV/E3WD+
-5pdqu/bl2WLPtYea+6z9xx8UO18WYqvY7/fxH4xIFHDXmGHSIUUoZuJaG0v1Mc1xbvwJxF3RQ4C7
-urK6lKximlptxXo4yPcWWybo4tivv816aQ/LJYAQM1yKMF9txfR3PjiFIL8o68l4tdcrqFT9t0uS
-DTo0WVFw2feYINbbZ3ZkkQp1t70R0vcGBqCw16iGwXfM/NluVuKx2HTy0ncwW+q237BQc4HeXGH0
-5RNvLeg8wjGLwv3r3+uDZmzrKm7WmOKRvEYzuAShYyXFJiWxCx3+lI1wYbwC/cu7C9uW1YJtHXDQ
-PGk2VRtczK6F6AVBf2d3e40Kxq/7S6qgaE0Ilcx8s9qmLugoz+lGKEvfVpbrRrVuRI9O6+bxg6j6
-bfted/tc6nkOmlTecLM8UpfCBlXFMxM3j12l3gsvodbR3lCAdU814S8SQw0t1Io0f+PD/wcS2KMX
-T5PbyZMF4DdZwrV6XUPhhwPkBB9mIa3cKy879TlmmiAkSvzbgUktgeHmQxIQwhIYXeT93Z6iCQlZ
-kJ4B0hlEmsuPSNIIGYOJRHy1LGom6dfwszfYn+w9UhQHL8WFPobGjMtPSGbXIm1FkOzfbKMuq9PV
-xGEmFGIYZsf61Co18/mmWUikOTntUoywklMcrQoSWJDTN6OApTbTFZGJyQtFvA09vNfJtORkJBQS
-LElebc7O8G5YLYA/RuChGzheNYXjKOv9k+IUIwOIsIQf0b4bDvPDQ/57CFupXPSiiUFkwuyEIAFY
-5/VZZjJoDyIkZnOCh+42JkCfoyobfY+SqntpuW8IpVJYH4obuD6h4AjrE11hG4neMDlz7E5EAOYw
-5mOa/MpNnD1LEEdGE+ZUZHDzXp/07W2s18dovyYnziX5eIX7HepHtjxnK447K12GUY5Z7MK9SXeO
-LLW9yNIUSCWLQw49LLFJAIyfBuXSrt1HygOIBTmBdWwOicqlmkhWmO73C5XWl+od3TlGpWKaJA8e
-GFtJc6j3WoQFBMPqThWYCpNxsNZ04OAEwkKoeUXNDObwUJEiuv6tbmA2Sde7Gl/y5fRyfXT3NwMv
-cB4WisiF0t7fWPjYfmbEjoufkW+HskGnU5LvLq0Gajm66DZXYlYjk0xQnIZdgIjTrOka8WsX/jny
-9TOXvSG7jHifLdAFu+ti/2Yp9JHcRFg4pl+nPf2NWG7WaxZmp2Ief8aJcO8EdU4Z3JltWwK27usa
-JX5vwMYnOyikxnf8T4ox3Lv12a37QFuzarxGAEyBsGwpsR6/3aWZl6ulUghDZ0AXVbWsu9KMa8AJ
-licYFP9untyLf+HB667m48vsCCHCvI9pDvf9sXTPi9ms6h7hdyKBc6/X7tnmLT9dnhMW4Nu7+2/+
-HQcqeffr1//6P1CWpg7GBSbsm8wk45nNN0gOdS+u1ueYxA0rj0YU2RRfnrtIb93jjh8AZUKhclgs
-wAp58gZzmREDgDs1bCPA85SDO9ZeU9OKIMAhP5lPkSVF66j8Vtt2AiuMUVSgVEX1BI4VOqNPrpLu
-kqaVHM4lvmRXJ+W7quEs4pyIlM2313GHdzCJTFKpLavlhkITCyZuJjZvDQb7wExQkpCml1xUq7d1
-591v3vx7jbd3v339fz3kRZHpvqAuvgFGe4aRlU7GdTlJMMxLaRNac5gEOF1hvfqdbNJL/ljNoHby
-p1Xxtpgl9+7cuX94787dO7R+OtZNVZs/TdQbFxMnhvTzqnqL9XC65xSWsliQGERiPbIJGhm6GHRk
-UwBzVUul8plh+o3kIVLRXXxwu989xlhgtCdns7EkLK2A386NSIYuABhro6qSajbFiD/z6j1lS9ss
-z1ZjuODBinY5IJ3Xq1xhMdzDSJYMlf4dChh/Wp5xpqY55YqWQFVIMguMy8okspyecPRsRMZkvFxj
-fkObAxKGl67ny2mJcaIWb4urJeXUWxWTizEwSZCp18UJAEcCkB4XGAvEiblngEcmTYT1L9jV5Xwm
-it5ZdZZMqwn2nfYEg1Y/9Hp89hoFq7ZkPo2U8evx2T2MGuLiQthvdEVchRYV/JyHqTDxmL4Ty0Ww
-iLrJ2qG92pxIxcxk+1OJvimfqSQ8lGowxpqMEOpIUg4ZpfjNNW0poF48P4adA8UcvKknFkkHDUe+
-VDZJV8bLrMbECTSuXtxyjQeHihYg1qOD+pju1hn3khuweZIOBCpOtdfbGdHCrNoR1j/OFIL2C2ax
-tEaRFL6tWMtAGd/8R0gqlhz4h9dclq1aeStmS4NIDu6o5XrNZCNYjkIgecLjH4ZTDNLetmgOTR0Q
-98C3o842JKLkZ8bb2E1Asq1xtdC/nmccYgy/SCAT/4OZHvyjoHKMcIF6MyB3C7Af2SL9kABkWeZX
-4cLElsSBbqxkP1zIvXe7Hy4ls33kCgO3FANghHvHmx9OLIJ5PHM9rY5bW4R7T5LxNjnbCINh4PNr
-EBLHVXDngjKo40/nJb0PNj6YJOSWaLIeRxplWHOaVNqLdjSalihf0X1dwcWseXAFWLwvVyBvUTTE
-F39+/eTV69EXTz5/81VoY1KsVnJrYCWf/xHTIeDx5PICUMDNrvmAx+5mffq77h5mudwTHKtl1Z9u
-lqcUfBOhGWBD8yNqD2tVEZFUGmGyBodbS6PCrKwaM8ApiiUwuj/CPy+L2fgqOzKCCsgUy/kwGgzg
-DBbAZKPT+EcaGzTCJ5LUg8EzfTGixX5ZsuVypQzb6jgBuutcEkjzrpIckiBdorVTg9LVPUNsbAws
-zHRIcHoGoFNku8R8KCoZUjDddo3g3CW2nJUWkm/wZIKiN3bbFnNY+8zoljRLzZAxmRPP2gy5176l
-j4x1WTA5qkhsVHBtppW6JLFEC9DVj129L1eSweynCC31Taob3qoKydJ2qJduGI5eNE+yirHTXKjH
-WLWFAJrHnN8M/h8NFO40EWckL7TEsAS3WURJTohtEShUZAbCSqPWqpbNmlxQgnwCtWi+E9qBs8Se
-RZc7gng3cEvfDWSbgP25MfVZcOCjBgkZ95JmKgxuODTE1dzTmOOhhSS1sbwabMvWjkizPvZ67WKt
-Xlo9eRh9dF+y1q+OpP4wyzfEtq0RqXwaMvtIZkYsbRBZwJGrCFWIlZ2Wl0OzHVM/25i5P8eDdqh1
-lIqqNWfNwqDRwEjigokOJXA+rjWaA3r28mgLeg7oiiEd0PuY02uTPsxC3CYVuTykwULHENE+jaiC
-M3xC2OVi0UbCe10g2mCwxGN0GPhQrbO1iiISXwCRVgEbazhkxnRt5m9O1AOpx6447uZVgAck9KHL
-TulJSVI7kuWItseOPQV1jEo97zaYqY6VaCJJ4mBDqtViAqPJzCgVGe7F12++evrsVRqLZLFVZLDd
-Uma6NdBUDcBhnfk5dWe+WdLlLN+ewVHGzye10eigXMWgRgwrR4sTNq0Ece1Ztf7Sht9VNPKUWreT
-yY3ku+++A7zXwFjHCWpBtN0l+XBThMJG91mXKenu3VDWFTkGg++HviOyQ7wQ1ZbhNBmckoiOfjto
-ROqTHqJMNVHpYXZIQkaLUC6CTJNR+doeqdA7SqBZVIyOLc2evUYvHzbsO/SKZVagiHq2iwzhnWoB
-U7SEisIPP5NwxEv/bsvxT9Z3c/gPBT75CzBeDjeK/z26OzhuHlvYgFKkHC7TFrnbdU9jBFgZ9hAd
-oK1hR+jzXCjwCGpRDdI4SULNo8+adHS9493OQUlrSkBbxD1BozLy4d0tkmRzYDjzLV5JTeaEDSIY
-Rc0m7jlBqPmTX8Eiko+dpl9TJuwX9kcjvHKORjHWaUfAdQN4saFKRR4oWgeqO9aaEhaYaxJ8dJcJ
-kULgLpH5lyOsuitUJiddzWa0zVg9FeFN0j3X7rVeQ5sd7neQBB/N/IOTtqlUkzqsudsiwxpYu47c
-9qPKuyvycPmmaEB7tdmWlKsFQ/gE6dTbjzmYufSz76Hjpbn3VkEA4VHUu6bdaOEEovanY0WOxstB
-BF5JPhvNvts0pp41aZptnazsHM332A5RaddsGgiTzcIK4WJ+kDkSpFyNvd7O67LlL7SHo+QTZR/I
-D9T7BC8pP9sY69xcsss0c+rA9adclHT1ksRu+LZUrIBpeD2nQPgUc33Aj09jeltLKF0WWsDwA5h5
-j+VI8Otzif7tWyiZC8t8PAFcFqsrjuiO1nbrirMTlGsO8H57XCfFeDW7wtfQZQVXmxPgrc2kOdeZ
-BYYn/1tNAvvCOdAjazCFcMWayht9Ke81LNi4mYsbUdoU9tv0S/aBN6WwvSgfKtUy7BiAE1PlgCAP
-914GkmMlj6sG4d6E+rrRw2+78ouzG6RN9/kfuySfGTVYf2TyJXHxT73rdWX3R7QrGb/flRfkmPHB
-86Xo84iSXWsU0f1As2Z6o+YzlJg5o39WhFXxqWJEABpO7HbpHwbtIpSAFGlRMNZnq6qoH7wbg2dJ
-yq4NaK6WRbmZNvplXlYfSUUUC+FnW099ZdRxHIfZRAbxybAefDfADE+PD1RvA2LQbPe2j+t6cyiR
-ttcaDOaSgsrJL4dCYrHAiqQooqXbc4KiaJc97o00ZFaNxKbyqhpPb0qC09Y0idYcL/juJxUmKYuL
-mi8eeC67ay6d0k2smLyPKX43loL4W01xWjlGZHgw8Rg1m7m/ORTnclUk0Q3Gb0bLDmHoffOyl81F
-r2YafIMx2DGoSSZNc830DJtTGZr1iHee9+otpo1bB0pwsfwYCqzwzNX6b9c7/xpqCP5A4XDdTzSx
-wfWD7p1ye/e4dGcyMjOmoJX31NIPXiB0/OZqXZ5ejQojOMocrJUzU0FEeS4JcinnDFMzOnQSRYeO
-Pldkw5li5r10m9BoKnIamFRL3uilqkyZ4Wggv1UUbVBhQWbHeSNvKwf+HdqDZCnxBdy3bs5PZb28
-OZQh/dd90IpJmypBrw5ZL8Nup2SwmYx6KP82n6dcWrHx4ipbFWGAfp32lUyTBZCxzPh+EbvnND1O
-nj57/eTls0dfU2rah8bdhDPFbml9OtvU53pX2o3ukqjo18O69RGr3vaK5ZJOGItEFWDG3MTZaAHd
-Yck+xb5G7NK4qxcMzwCBko9cx3LHGnn7JzSlBmqExzRPd4sk+kod1T8ii1QyjxHvmh7rESkV2wJV
-mxtNtyVaMA7WHJnYJBJcZhaFig1bgarH0DagddHWtnU0siI211pkXaKa1lmfbCKnGY65t80GhUjA
-ZGmZNR4dZkprpcRu/10Rx81b4O1FoGEVMI0zcBicmRaC2URH/OO415TjuZMh/5PzjZItFNntQh+l
-HadtkqHzH+rhUI58Vx61oKewzMHrkor8J6qUUeZJo0bZ4gvCXsbaqGrnxl4KlRvGV6PXx9xmotkd
-ouI1SDzq6zxwJ8uDlxq4wkunZeyuyrGxm7ILa3OhJIJ9uIXzdXkBF2ebh0bsWM1dvL5t8qIkJjFK
-xNzKyk2xJY+aYTkhjeha/gw2AkODOvwj5lMcM7dSnaO1vPtrd64cpPZNTf4sUzGqhdkccPZE9m6h
-FK5qAL08sUVmGg0CSx/YdYBzzeBpeLB6iCor7jXXk1bHmdkswVAvzstZ4SHTZztcaA4ts4rLahm8
-GFkkGw0tF8iSNNKz4P2QvmSY760ZMIozWO3xfCHoM6x1VdTRsyNc0bY0siY5VvRRv7W9VrbKgLzn
-dsGFpnK1BBZ1SpNDofAkVFW5MK/TFp17nLAM1Qsu5ujCFsdOobhc4J6pmJFS+Hra72xWmsZRGh9G
-SNiyM4mL27ki87BJnZtpwvFzf2Rqd/Y4Rq1oYzTLNuOb4VPcJ0n5fgUhVjUkWiX4U0kx+CdZuDFG
-QNim+txlbXdSHKr4glwEmcdR9OdCVc1DB/oMSRVoYhFyZMAP1EfA8qTaLNbH+6DrkhM3isWKzQmM
-rm0wEtRl8ZCOurbTLuU7D7wV+QSx1pKt1rbGiBLtgecRU56GpY1SsKm2eBIEG8R+RTZv/2jY3epa
-4cflHBdlHrfIXc61ASlZqCCw1Dcbs94s6Jph+oopa61Nk6llkKE1mIGFlEYe1x20Tc/wSlvghglA
-KUG6b0/p9J5Cw8yRagWhVQkavlk1Bmc78Y5b+x5KHcKmUp/tJbYB43wiZrl4QlrzQx66liXU73ZF
-mm58PmnWM7jyLOSsOMZ+/FlqMhsvigtaI7FBbVyPCVosSss/oQZP/IWtGzmmuEWIB0JVCb1doRDQ
-tPQghGsC6bl4vQ5XW3flCvdtBJExkzyqC2ixv4PM3s4YZl9xK7rl/P64eO8khukDN/HESE82B5KX
-DNH3mbjZuPg4CTQYEXCMvqdCCLIqeQZuU9TOKMVhQ3pb0nd9Has/xXDcPayhY7je+EyNqCAfkgm/
-tqtBhBJgaJIvnlS3hokzNZnjXo/oXGN3h5DAtmpSSDadqMtlUy5tkUXFigCdEuvzNNdptdLDw4cp
-uhCqWZ6iqnwWc79qTv1QT12JqR20fML9ymcWCVANb1HnRIo1Dfv3XWHI1YWu1T0HBTNUsYKVrKWM
-u0BT/yU+cE3Fl7kUwO0Sfr5HS6uOVb1oaxVaMxAzluP1eZ+Ulb0GlCO8BROlKCCh2QsBykhxJrLA
-VsGB6zcdxJrMl7h0IrEZWDzfUDJF7GRgojUQPHVzk6GbS/75rLgUhaYj+fLULo4dxMjTaAMEu3x4
-97qjwntgDq7NSV282+BgcBeizyq7l9Kj9mRV0Pt1cgoUc24DVjqtRthVG2V0jCxFw/E07lja8bWg
-g+soCQNwgfGfp6nwHi7YY5sfkbOIutU4UPjw2exvKDwMqZ18rrfTOOo8bJiO4rJEv/FpQZFCGOQp
-ei+OcY6H4s9mvdpXGzZBIu92tEY4o3zuk2o+x7sGqb0NPbEEh1jHlgCP9fjjGRGayfiOd5li6vAp
-ibeVgsU+w0R2sp2giRFRrq3OIvY+JGgmLEUeYmRlHBgjXzhP/Cy01SEVEn6hObBVT7LB+gmVvQce
-QC9ymGL+3e/e/Cf0saZ7zMj6MYMI9O73r3+4wx7sX5aUxVxF4MF4WhsxCzGKHrRm47c0FYxTQhAl
-cslJHr163e+8xmz3HOwlkbwTieu7mk0BPdAFANggH+dwBcrf3fwcw6qFju52Ms4n2wQaaOYOzVti
-VlIgAmStUHONzTzjsH8Zvx9LEFmsY7zTyQnwQZLdy5Nf58m9ngne8aookvP1ejm4fftkc1b3/4Vj
-MFSrs9tkV333/u9/y+cIhiMih/b086qaPV/CuZZ+Xi74B6W94Z9fj+cn0zH+enr65JKKvoBLY8Ni
-I/0a6BrzIWING0VRWvwZEzTjD0mYSD8B3U0oL0Hiw6/PNnP859Wa/rKXWyoDPklu71QPDub4WPDr
-azxA5AI3wqh8POMvRVHwRXFKI0Eql98vaRPQLItZwR1yzMpmL482Z+ZTkr7AqwL++LKiIX+LKjlG
-G/0Jq0nw8URqgnq9uuKtRaNeXX3JUoX0DuRCkIi23K8vgQaboJ6AyENrQJlC8ReGtaMhwjRpmTE9
-GK8Gv0QYDCFNjCjsIYme68xc4MbGFqFnr5EUu5iISKH3Wo1pPZyr8KisYV/SlllRcLqmxE+hkKy3
-sB3ByCVC1oAQ/v6A3PBVyI49x6UkEazAwQRdTMw9BxWFwsElDSc2wT4jbJiYCSB4A5yC1cE2LhWe
-QMgLibO1XBAVoxqmaSjrT8YYnSwMNbQjaqcL2PnBwfckhKeOt8e9vgdkAXuB718UwOhsqCUQNtoC
-4kmTPv3rXn7aIitJ0KRrxsWTf/8/FbJuUUnUOopEZMJuVaencD+BsY1UhLfrxeDyQ2yFEbk8ocUR
-V7TfXiPamlmoWMy1yOFt6jczR4gfqKEX3iqGSOTNb+/obPQha6iVqDjIM4ZF1gA6bYvo5gK6bQ/n
-hnYZ+4Rz82d55/iakd3Slshu6bUiu3U4+V61AlF2iS8uNonc5+X6+SoB0v5rmuvC7yoq/We/9BGw
-Sij9lSr9+tV5eYqpJ9MHD1TxS1v88KEqxoR+UHYr9VP1QdFh6iXho6Y3Uz+/HhTdVkVfzqpqZcr1
-B0ypB2UHqujJOywZDlXRs2rNpb/UpV/zXLySJ1Ska33FU/NKqNZDXetFdUHT0PN4WmNRWXtFmOeT
-SpF49ZcFFS/8UXMpP9SknZ86nQ0Kn42lFaBY78DrziQLTf/VK39jVsIvNUsGpdiXiZcdHiLc47T4
-Jz403DFrK+GJmrC4A/f0s1kxniM/PN3M4HgFaGfMlpmV4AZPth2/jTRppOsSPkj/6qdIEK7LyYgP
-MlFw+xLFDdStzzBsJh8mF0UyrRZdtDp8jzoEVCGX6OPqGd33Nd/ZJvb4p7OLmpz5ychsoHVjKThf
-lsZVYneYf6NEdqjgyMqT6rrBQvxA6a0Ze/2+yFQv9rpgr8nqZhfouEmltU3ii0a0P8JKx/ugD0R3
-VGym+2ZG9EPUf0r0KU/y3Pcnb1pQMRz/BMjSyZjpcjEFkZW9dkj61b7udu4SR0DkR8BEMUyRKNKm
-NG2bSOX0gbqke3k9HrKfmDawpq01QsJ24vGqJXoRb0OKCh7aaTOYb9r9BnXMebSoP6mmMU2y7HS+
-CvjAKXFCNAJAhECdYYfmIGGuHNQhSL4cE0KAVLn9ZgqclHPYsFlqZh34zujqCQUkM9DjYTnNe50t
-VK2F+ygxUx872MF2Wr7B3A+4NVDCBieGOmSgvmg//uOpEcTwY9RqxEwyZAVbuEWwkqIasfbY86WW
-GDmtLJZSIlnvg69lohJ/vXmd/QS07E0NVAMi1ahaGn9q6qFa1jyC/oQGhbJWaOhL7byOqSTWsXTh
-c45qOaqv5icV4lrLc0fV0t3Mj7fwagzsSP8nllghHmwH+2cBDefUi+dmSxuZjetGtlcalBvCTq4e
-0v+HnIt5NHPt6OMz16qV/bjD43rZxmXTbbP18jPd7++42+Kt2pL6p9nLrm23dXe4PNMrXH5106UH
-b95zHu+hstgTJ31QdKaH4fW53wOov8O0Bd3+fIzVycLGMJJNpRkZCEWktlHKLq7TR2aE0tDz1T5Z
-a5l9Adug1wLpR6IXDdq4RngOMnsSML2deSRbqZfRSYCHPMNdNGTMmAkbOIcU9SnyH/q77aKeGXvm
-SLJJ+JL20g9YM9H3y6LRBaynLe44mf0wsVezI/rVj/NqQWjIjrkwtgIGWLAO/szNKIivNjvYKl2o
-tmmQnynNe9sNCfbitpTpyZ/ivmLJHhzyGpsPX3DM3isXVShD7CkqUNMgYz0dBX57LmoHECSqj5/3
-XDVOSSHtmyO/13LmX+/Ab8wokmVz77O+cdB/iJD7Mx/u8ZT0f096fezMjdDmIbDK9RdX7HQVlWGT
-vjOoFUuNUfupQX//qNcUW6fJgID/pKFsJMFjeOjAJzxwqOtmxOigezJRiG4QCocTtjT+rDqJuHM0
-AAYfyJELMske2STitq8QMk/G5v2WNr1tQ/dqR1cZsWHzkwtG5O8PxYo070dcs38+/EinI3WrrYcH
-AtiMKLZePlYDMGxFNDKRi/fBdByCd8h5TwOEcdSufwQdejD2wjhWTj8FGaY3BcfXxZPXcAd62JDw
-Y5ATc2xpQQ3mOf9EqPlw3OyBHJwQfysXZP2MxgAsT4ZwWx+MVGb0Jqv2O2jY0Xnd8cx3HL3Yhe2P
-rfN+voP25s1F/QlPQyc+p0EWYi2qL/dQP7cKxFAbT9hl5BVu3/N45DKzE8HFlYp6LivxrnHqPrq5
-uHKjFkyba6vGbjVn8uNjF9ZpZj9IS+jFog6kFWuGpLzJt9ulQoX+ZH3JN9uvq3Ho9KWH62tlCXaA
-uEDY5bKodIH9BodoY/9KMJksBpsAxIYQ7EtJPM/b0rT5GwnBdOfykPAJN20DW27j9nnvEuriG/Ya
-urbwkeajwOy3kDeSx5gIyuj4KXhgWXO4VzJ8ZeJtV/cbw65G2vuuTV5Pca0i+16JNp+IWsJ88j8b
-0XxM4vq9uPu+Z8XPfRIIr+N89sLo6nq1DhLT+3RGJVFWhE2DfPVkGeJD8KxEiPnC7OnfZCj2r983
-AwmFQEACEhDNOCNhZUltr4uO7v56cHivVf0gxirC7ho4aJjtKJx8+rz2H6dzj9GBGm6EGEzW9lzy
-u/sxtjcB2+GiFnqA1jsOJ85Cry2XWjBtgumaFPJN7Z49ebMt/BSNnhbVUI+tz2XtbSbVbFSdntbF
-2m/nytUwi4sRV5LBCkKlIZA+8NTa+Ob5o9k1jvbxxEYSsTqwYzveyomjdgfxxFO+vUGT/2rq+JnV
-TrqrzrvBm/9swoIgn56OZ9WiWBdzNL0v3v3j6//2737xixu/TG5v6tXtk3Jxu1i8lyAYnY6JgT4k
-Q54/vHr+5uXjJ6/+0OIucDKui9/cN3/9ZVae2KR586U1O4LDkk2590hjJP2HRkJuWPLL7V10MPWj
-FmO0K/EYHK/PI7GPTAUbw02Atkqt0ca3km7fjL57fVBehmMbyAm2cHwynt2TZN5WtQfAA2zdjj7N
-E4qQaFw2XKDELdRtdoXM5cjADQLn1qPl27OGEcHWyAytoH1stnTk8m7Y3WslKL3sknw2yDYrRs4S
-OQZzJ0nGosy1VHEkLeJDODbgNssvt4WBm1K1ZM2GuGLFipqGdMWzbFhPcTskZI5B6dbChalDhlNM
-iAnZFiyibo37E4AS22FRzLWl7ghXkEIINNzEJSBKLMZ1KwCfBHpRF9Igm2lqspmm1tq64T/0cJhk
-n+XJHc9oCLCVSpRAizq4yPcGifcnyleNQKvl5O2sCIR+xZn6lO2rwNS3k7JMMf9psajRyP4EeXKk
-IUOk3AZ1hky0Py2QrtHeMGMWSyXTgiBkhkf2YonTTZ7YFwSUIgH7A941edxXrNbwZv8hw2UHVD3e
-jhsiuW96Z4Op17GRWuEKRqRv9H6mpQCi7Bi4C//w5Nnrl3/+g0RrkmnR19zqZ3qddw/e/E+U/ZRJ
-7N3w9f/5n0xCWfbpQwF8eQVTGsBJvCyn1ikSP0yL98WsWpIf7WZdzoAc1+h2J9xlUwN2oBFsYnS2
-oxCB479cHRrvyHpzIlXrDoKjwxHIJUlenxeUthZaHuK2RQ9KmFdyAt1dsBXraQmtkO4PH7Ip/pwT
-xdRo+boSZ4hkMkYXBhhsBVfelcuw21FQK/b7FFpG3HYieXEpdiQCAb7q58hVuWMxQfrd/v3+b7sd
-4yloPQMZEZ3ODczuS4GtAcfkQ9m/aS/fgC8YO9ETZg/XAobmU13TlEK2COj+o1k5rkW8S02NlMIu
-90fmjy63A3oxzQTRmTPpx+v58MeuVOgOTA8/0e0SBgR7pR7+KL6H4wl7y1YJRrZi+WqFbrFudbFi
-t15PARQwNPgxwD/yKIBlVZeX6Fy6qLo1JXZmsmAgPHoCQz8HXJAz+XdBypuWq25CFUa4W5DjDbiU
-++vKaiGQ5dVArV43h8Gg8fQFjp/McdblSTkr11cmNxELkYf3+ncw9CB6ZYME6cgqR4tr9I4Z41J4
-06ecz2+LYonpiIF1nwKR0oKbfoQhdSm3dEKDo5+5K0bJfgbCYutn9vT1P0vvHGwdw7yh8mddLQ9n
-uHu99VrBdmBw4gKNkH60DA/VPNUERTv5H2FZqg7MR3dj6cJ4SO6I1e/Lx4GppNq9LWezrjoivXb4
-EX8PqJZq9WW1eltM0cez22x1Sh/xOWGg6nHrnwz1CL37k5bt0TUQudLAFKsBPFqWvPu6Xk1XHHQH
-ICT6r9/j00X5WMrdRGzlgfus+n6BrnIkXnZjbdTnYBDI8PZaZqgXW+P6/eJi0g3XCrkofRm8er/4
-9vFjdpV/gX35bTcrtdJe2/+Xu3frciNJ0sT66GV1IO1qL7odPUWD4kREEQkyWb2j2ZxGVbN56aam
-iiyRyemeycoFkUAgMzaRAIgAmJnd23P0qEf9Cb3r3+hNv0VuN3fzSwTAmt6RjvrMFJHhd3dzc3Nz
-s89MChRuKYpnWLJZstX9Dv4bFjLVPdvBcNv7iun+FD0QPESG/jK84jGc5UeX5O0MuotnP7ym6YSE
-PdMpDUPW5K4hAT6Zn0XEE87jlXuPSbpYXI7zqFLPscNZuhR2EXPofQa3/LyrBOVQRezd/rXhxnmq
-iJ9DFcVgucCU87bWXA5VDFz+GlKh5G2TofP4RRl0LW9pUeVQ5TCOu7ylNXmiXJBDld0to9JB2SiH
-Kj321Ya517J1fzgJcukKAJ2EfSPG5nzK0xWEuVpqyMNJS9YQlLb2rx2lvWy6eOy4macrSGQMNztQ
-EiKoosgHwU3IoGg1F4AJFkX4r0OYJ2dN7fZqubsBLuKNW/K7RFVCEO3zVAs2UbNZuCHMgv0jBThR
-ZZ8s72MmItkhUef1D+ogr38+N5YyUt3wCcIIz38wd0SfliSvS1Qlfm2uWZaJ5EEJP1GVUoAV9TYs
-5SdqejOyeHXXMqGcqBkD6KbGLdk50d8MqPRMrq9N1AXMrY4uCnmigEvUVAc62rxlLShRNwB3WLq6
-5nEDKtHr1Aq8dlv2ASfq/HWDd/n0qCXRL9DRACfq/IZr1zegZ0nNkksMighaZp4qYhODQvrwiAqF
-54Z3YoQFUuwe1meuJIRo8TBRSxRmJ8J1MlnAJoaMsF6ud9uj1W5r/smuqoUNw5rXq/0ijoigqxTT
-46DwyfzD6WS9BUgGyaSFAbOmr9+mxBVVjjNp3gC0E5YLi0kmLem8eE6JeUc5l0nLYttZXDQsqTIl
-i756ke8vajJ5E0QxXH4H0RQ2uV9YArxgqIXNSZDXOwGaeoyMKdH7oBaV15ehXJia23qGQndLDYm8
-+tSYwE15vclTayeJJzZXSMTNDegU4CS/qSbL7O5m8fhqe7PInOxOJG0SDqBpbNdkNaVTZA01B8Tp
-FcF0vVqTyzC7lx/S9cE/ue3MDukq+xvRSuTp7C5d85bGkFhqY3IhTg8ukYtVcId9kJlP6AoP0ZwL
-0CfMdlMjmeS4FhDjC1wx4e8pIIFNjQySfa4nYpSr7PDaF8I0kVoFuHdDEOE8kX/I0YVPbCZ9h+ZO
-JgtCYzaDL9XIYPJkIZ3BkyEqhFuLVkeVo/TgbOksdJkohLfgFNnYYYXX5NMXbz+c5u0FOINf5OW7
-d91FIIMuct8g2bQXoQyO1P5U9j598+Ffjm1gLdZaf/vhv38QamGfDp8Of5H3Pv3qw79y0HNS4NkH
-wERqudZn/rUeX30//frDfw3VhDqoT89P/7f/7Gc/c/Bw/GsFqJT3TQTxhi80t/Xy66fo8mVj/TRg
-Q7XES3OW5xgeIjcMNQGfLo8Z+IS5N0QFvWlAb4t1PYsD2Qe6uKK/nTTXkD17/Cp7/MPrF9nDGXjm
-r8GNO/W20tnAD+/ePn/5/v349OW771+/eXb6MtM4qAhHSe7/Ix7P0EzNDL0JNstq8fXT4dt1tfyB
-+li0GkJEzTDC9CBb14F3X0szfBJuK2mL+jXIjo4PKv98sWqq32IZLloGYGLJOVoRIeHsZsf/lsGK
-goxAqLgigkp5cZ/VMxWJw9Xc+/Tiw7+R3XGzWhpeijqDTy9P5/8an3Uy9VUecW5W02v4LSj6E9B3
-D7NMGzhYelZR6Dic1Xis6iw2AGRqEdxNFfCSY3E3P35UeT9+zLgKGNrnGhFVrip+Nwd5s9pYRGSA
-RF3N6vm9IGVSOEZ8walNQfAKhXfGz/XGXPNPeuqd2TY4bIsFOEAjEzMHCig1LDurFmHZ/YVMg4Cs
-XvDTVEsAwqAZLPGlzZiRF96IADW0Ws5GAdZ60FZU7IDG7ht8eucGwMXyKp1zejWrN5yOGZ4ZKsZV
-rKfspIUItxdVtlvOVgCiiiCsWyQZpCO5ceBTpA0NCy8vBNNcmY0AFPbxI3f840eKeDABDSRUNqtI
-tITX93k2sUYYQDF+6ASGeKUO4R17JqayZoIfw2xh6+TEKP1YrjKy4hoKxROGHU4BxtF0m0OQy3Bo
-EDYXMaTrP0DUYZoymAcP34y+93rL1dZ0AlwokfwhaBKZEqn6Hb+gTPjahLs8A/jYzQxUWLwHHgOV
-gZnTY17PbGoY12XVFeIniknAdaUCLjDlp5Kmt2CJ5hv5+Kj9e/an6waMFaZlIgtpCAHKGdZilufj
-R1OR+Wl4x8ePWNHHjwNgn2zk0gsAahw1AIStM5KmmgVRr7qrzeLZWUI+vph9RuyQRBBYWjjfEoQG
-Qy/KVJTwU0zGJHKOR6YFGGMz5bneUfgA225ZppdKxT/TnaReeIXaoqa6E40ZYrRkHWuFe6hKLRc+
-lvOC6TUKwBr8qQAgl/QiGeb0uV7tmsV9ar2C+OZu1qL4FzyWNlPbYGWCSPLpQON7lqKdhAJHsOhA
-Kr3thKcIrY05KP1FjDeQsoYgCxK7MGbzkHmrN4PeJtcjUW1BcGUxZEoNwqSfiX8cNuHRVrr/+2nL
-pygY14AXy3J+sCwzQ15VgAHE9BGSBxhfsTdTFJN7P11IU4dTxD9iHpkY3Hx6dAAnvI6FEogHgSWo
-0AMLUmjY89lIWKAf9GjCMtQhzsfHj1whn79kowjB5a7MSWwu9xtwN5jMcLtOd5sNVJxshCjB+g2C
-9RHVjEVts9lkBn6E5oi2oOyqD65Zb2EFstNBc3rhP7kdDB/FprBKpvTmW2qifx/Zso9UiTPfPpQM
-/Hhjulwd7DVcui8lfjW/8R7YusOsGUZb24qhUT+lE/yvZjqBYCjBm43453dWJsssmEkUesJrMv0N
-SPkgq/DlY8FY8k0nF5d4ys3kc8VdCcOA8m5zGdj+FX6enail4m9qQwLJ4FDUgEm+bR0mCVQexd+u
-NnjVMuWMfLYyfJbNccSibYYVaa/LK2vCpoNX+LE2WN7TretZcmJX0v5US2UrtD01v30sWpljaHKQ
-9XHgoZsNdoempIvjmRaiewFMJki+oZQJswjf7XHuhNQM4f0xdCUr1/DyaItisWY7mV6bvAA2gaic
-GAIEIikYblKbHc5iVDWfg7i8Wy4qFT33frWD27WRsDdVdG+2FxVsCP3F9awjSlEgO7nw6CwBRKcK
-ZyMsvZQ82C2aec5CyTi2CZkhKZuYzRADYDgZoX1YwDQ6h5UcUtItSh1r3OxZbHC/17reUSdEU0Vk
-bQhwP5ndM8+cgYMFWO0RRqBZ0VnVmO05owATh0xq0EErziQP+Whq1fY6hIU5dmUddVT2SCiIc7Ry
-hnSoTrtfbd6ylXvgne7Tqw//SnRQl9WSIjZ8+s3ps/+cNFCsXUWGZrbSojqaSwzTI4iQTNAErMvF
-WClsiQz7yylae9bRZbtaoyVjoUR4xNdkHk8BSiRIL5qx2RHA0zXBsDluWnBBDa19YTJB3seeL0kN
-YcYvzPxU02sjsW1Gx2VLYO+LwA8L6iIgBPDHXt+Du0TkMQDAoFQ3zFBb5SZXz0me361W17u1Fj5J
-ZXeNATwLmStzjq9WW2Ln6uhagysm+ZVeDfGPojwDiBXJLR9LH547H+Y0mjNp4NyIQmd3w/VuU8FY
-UZ6CRbnD5YBKzl3XzBKOWUWmF1HqwoBy0ULbqNBPm83UhV+FezvnCybPbH+yx/WcCKG07bXXX9hg
-NgFYRuGHbVqbw2Vy6cdZXN/PKQKDK0nej/lXZpXDzUwuPLI2xFPdClFdAbCN9NgUOkfChTy6dwqW
-FDLSHIsvgp1l/leczibbiYtyxc4Ms93NunGay6dlIiu6OlhHB0gbZP8ulZF9IMgPhH0gIIeXF/5h
-N4kiR1eR3BsTpPeCAfEiNDh74iPHnXZEocOPYEYVco/yDndrU31VpKjR60TrVEqkAeJuY+J74nEh
-3fQnPB6FzUcb4Ga9iLiTOFWVQ8Nx4HtR0t7LY89GpDl+JAI+BxV6pIxfzX+HHCGpyK1/Yz7I3Aql
-MpKDicmGYwxCSVU9761gMptRHKwCQ3oIeMblZrVDGEz8CKInfgFfnIvdJZkus8MNJgxdPf2jI3u6
-gLPvlCKYNEaqhug7rD6ieGDqtarZjvq6HHgImLvnqA8zqWLqwPPDqM+x19zE2sOIKsgmW44FRjpg
-YpwSDaM9/JYMXzri4naZSlB4KFQvbVQF+0kpYqV8SHge28jtufnXfE68v28MkYBdW8FDEueBIfaz
-LHPf8xhcTuBxcix+BdbD4NxlLJ10ocfmE7BNKePMQzQJKcJ0JqsnvU+//fDP4R3WGrZ/en367b8h
-weLCjGx5NAMtQ4P49kxWuPtNgaNme28+wu5phr3ieZm9Wy2X99kP88nSNH91U8/MPdl3+jk6yr5/
-fWoO8CnYG84S7j79J8Onhml9ftrvmRQMNwrynbLhH3jG+eeiuHffoqg+CSdgOqrZJTy7aS7VUWKL
-D/cW8mVSvgJ7giMmUBGTRD/8RFMPvGs0lzqogeHp7fFaHzYnNpRIYVse6LYeHQ9s7fZt4z29yv9u
-A75u+x2liSIiVS4FMpJwevSjPaqt8zs2/VrN23w+HXoPb1yVnYOGBjpZUOFRZeYiGTAo6BVEsxj5
-kSwTzUgtEnoVqpLC/K+rm//1IuJe0jXETpqpobvFhhahObPNnp+ZQudeSItttUk9Ek11eIWgvnAo
-ZwqFQM2/37+DJx+KRRGw8aqK5s4F9wIzjqh40Mw9hK4LaILCZAfD9Go3SW3VEIGLipZJ3LKJvdRN
-WwaO5FBpq/ey1VMZARXpYVlXOlqoOUVQ+EhqguYE0bp0e/QAsO7t6rpaWg9mjuVZY0CuQEmdjJiL
-CcMpGFB06o2SzaDEqAIoSQTc4OZt/XT/+KdQHTsVsFCT5K2ocE1LKIHKg/oT6TqE5pPz67qEh3Ah
-beSG10rBqwrc4YEA4B6cpy7bAhTgde085tb6LaO1P7rPS39W0pqU5ABmO7MIU5SVuLKHm/yh22Vl
-mZ4IxVzwx7m/SO1KFzuuZUtFP6nzWCX2nFb74G63PWRxU7SD06c3yWNKGlAHpHd0u0o5LJ6tFPmv
-D0lA8Dve27swYy9aiyZ1jGNrJtQ6nRSpyuUaOpBbjNqQkL+g8GtUaRkE4oCo975yLCBSUUKRezlz
-qrRmyo1UfOGLlk2L95hUVzhfQG/7utO6kVBta0p+Ae2Zi9r23i4OWgCmaE7WzlM/HToJLkhPNAlT
-CgQ66Z6FL1iQA0I3JOdht6zu1mwFTI77qmeJKTGH55YiFcDQIah2Os+YkZXgJ9Mr/D47enpynuq8
-LdO+0D95DK3tQcdaFODU5RyQ4B42OSIeSwl9P28nBxztydExKORIQ1OmcER8SFC3mR2TsVtao+5A
-CGxAcfWiEPJJxIHS8wd5CQEDN6D20cuUyPrXLVkfZBeLyfKaYhymgiSeHBic6kG05WuSNCFwIhjd
-npF9On6CSYNv53mLVtfkOYapjRrxWZwNdM8NDesGze6L8gB0OC12+JM1MjfL4zJFVP2TrC+qrjRd
-0aHzt1ArHTrJ8C4u/QvebFo7DL1K9viA1g7Zc0gHcHqbXQK/y9ZwTUxe3MthTG1JtpgIbKbpjEbK
-VaVvkd6xFErx9s7tCXl4Syq8gj7YNRdrZcqKWE22R9lx6kYanpcH3E3bAHg5d9ElJ5WHIWOJ2pet
-9TouscH1PDDg6RBqO811uP1AC6Fa3H8FTt48VW/o/mn1IC2X0MN6wI9njZ0VgK6PrvYcxsDrRe/T
-//zhv7JeEkR5n/7m9H948rOfoSHJeDzfgasZRMwmReKleMY2CQg89qcY0B2p/kOlnu064dem63tB
-HXQ4Zr2eJTWLpNOQrQN1DiQBTvnh/vmr8ds33/3dGIJ0TpoM/h2/+u7Zb3ptXhI2h2nxCX0h0YIM
-VEUTRQBg3h0ddI5GGrq52W3RcomNbq9WixkZ3TLmLfqUzDeTSzTEcbYdq6apLxbwDl0vZxWHcw7M
-iGU6pqvdkuChnrTpB77CVzUAMWfg+pNYp9cwRw7CW8xguqkU8ptcumROGN8QnE7mIDd9jPLie9gE
-6YFe/KLLMlpqmpSY38PXREctLpwF2oaMA16esrse+D30JQh7Okc1FltzKUSu3mzLPRWf3YnEguiz
-/jvn+QGNma3HzrhD5Ux9yHBYFPgxJSKDmSJ2K32cUqx4W+NJq3sNmMZJLpCJ5JA76UQmjUOnJQeS
-EN3TF349dHByow1J8yfkOppVZWKFQee1p0apobAfy0TU7epuSx4PNo/ajNUnuxURJuyAs1LvyxGV
-CrrPXMu3Mz7p2A9YCZqrlanbMjXLpialbfUAIPx9mmO/G6iXrpfbcs+4SZPcvvKmVpPDUFy1ltO8
-IKnkuGwzvn1tVvLOBZmFYg084BiOTHyCTEbBnq5a98vWDuKIsaQZMvUCqY1+QlhLNTmLatn6/rEQ
-jWpMNKoFlsSoDUNmqp5ldWuB1PkkKuNEy+HV9GJ1J6a287BTtpgy4MR9nbDBc0XkTOOzjmxvzbQv
-xFFHG+4uKoL5U3c3U9XN6nM1GyZtFd3g4aAb2IlzgyWmhfmyX2bWWheWOBh0C5uioo+0HyLVCXV9
-w8mJOk1yK+uDoke6xvbF0iulTLj2LVa4UmsjcmyMSCBGtheVOXOqUW7OYLRMxF/ME/Msz77KfpFe
-0omRTtb3YGWFVqjR4vqvyNQMe3BjQ3l2i0KpWQfsjxVgwqWlom5K6G8VIGZO4g0n45/lYRvAHsNZ
-QUM2txy8/1nlphV4Met5x9ahbvGfjzL5l7oX8Ob2jcRnCa3Nn30ZwOaVOkZVm8m/uMeCZIpAX49I
-iEivxhcylDOe2EeHTWv7xIh3+o2bHrnJW4wm9lhMzhPzb1sH7N3pVSY3H88CGO0KcEKwid3NhSGw
-ggTpGV0dnpQH8CEO0eI6vgET5CLqd5l6RNV7OjkLVNlPmIpCnRQZCqs8Gc16QjOR3Zj7wc1kEfI/
-nrpNdQk6ZW8GgVs7QqL+DBMX5slSnbIkyWfNDhr3xiWm63NgDempfpD9/ve/hzbBxnpnLl5o6X5R
-bcm+2pRHl+DsqtptjCheT7PbyX2TDYfDdBWT+6yCvptquBJbsslOjqJQDcWT7JfycGZOFHvilCk9
-gZYsuMhqh54KONy+UvE+yI6HaLVIOxqPFdneMkc+JjlcEyEcN/v3M77flNAPe/qsSTzhUANmP/rE
-eXSMLuyRTOUA0WKlOWllo+M0yvgABzNfLRarW6AbYhaAXgvzCkDa9+i2CxbW7AqB4sJUhzhWfcqb
-3RoOlJoIjw4ZQmvyPnn48rHut2vFrivTpwnADuOtvp9WntLk9G0wK2m5j1V639NNs/awCpW7rfKZ
-mMCcB68zn3b19Dq7mpj/bFfM1/UJAb0CqzPwa2icgwj4LZk+X66SHVBOLbkZ7t3d3UkePfPb08Fc
-LTO27ZUKwjck73//PkPVdga7cb9yO6DywracVEcX7+8Nl6LlHGRvP1ebuaE9/tNpj8tUO7wiQdef
-qj0KO6t1h8o+qyjqtN5lYLlk2caj1LVEz2d4KCQI0GYf1g0+xIB2qe26ba90chhoBoe9TULOR5tj
-iW6e9UxIi/g3C3W4BR5CrGp4fyLeEr8iqT7oo+5isZpeO3+wxCOSYd+xMHcH2Pc/LnOnTVHbhio5
-OXfzh61IYVZADqX1IqDbBxQswpXptWnLYWFdtjI70vpzqzTgWz/FYEl4VFopL75BSR0kxFEV/on7
-es6f7UusIdFldrkDLJCJiHsESMAZ4TzxNx9w6nrTgFfR8sjdx4ZZ9n530QAgwXLLc08CAXrDTHwd
-yOq22qSaE8wEI8PW5LpxYdJvDE8KO3GP54NhsLsbk9HwtAvSQMHGu9kttjVxqA5JwRzwF4SwTSjW
-pGDeQF3rDSAzGA7PoDK2wp7Pq4hLNlm1nQ7X629/klBMdzePAChByKA85Jqgtjd7OosiK+HiyfVA
-ChrtUFcNTdhKBk7WATurwBdIK5mVg316siNubdHxwaI2VE8loYfIWwkY9hj9MPB6t5jcXMwm2d2J
-jVJyZ46hSTPL4xAlCW/psDq2G2929bbyHJtkuEF5y4VZAza0K1h2thuW64iD9MAPYPcIeNgg69/1
-4xhK8ZB0odQj2cVqspm9hpeAzW6dwor4KbEu975vuhgzB9j6/rjkCK9JjZedHArkY37ap1AM1FKN
-8gAL3p6+i8nlyD07DbmmzRgS4uwzc+IbQdGIIfV2ZESdsSmK0ak6+DNXOaMXG2LQQ4xvxP0UDuzv
-DDCyBJ2R4W1bgLapJwtXgrjpzGz1hbm3REyZ1vsxHrAQ94DZKjkNm00M1usYU6vNtxdlbWkMHZC0
-qb2klNoV6kl8H7Cz02714rKQzzSin8LfxXHJdwHqsC8zLQf2XdvWMJwLrPVYOjjwUhN2jOyo1//l
-w9kRFDa5URzxQpXxK1nCZHKMAv94HGb1NYGJOU0Yq8pskxcfiClg3z77Bq1zzICTpm/pR41UXZtM
-V2fnJ1Wxi8+Z2nUsQLWzKooW5d5cmfu4fUlbcoB7L2JHShgP1KF3TCImI8YbKsqz6GqzqY4ArtNc
-7ZdbZoIZRvLgeKTA2eGsYog+PrP9SFDNZeJGdVLdsUtB9GxoUuhwjhdC6rLRtLP+VzY7TOS/D+5I
-UYECmQb4F1s2YgSSiwm88OKI4EYEPhAYytpuTN+ssrrFyVNTi297tLTSZJkoJD0duUEmMtmtaH8n
-MgFsMmWBX4lrA2brfrMBgsn+wr2ttz5FTVfxMxsqHEH8D15TU6pGsWAOIlyBNdc3o+zrk4TWAqTI
-9f3XeaOvCUT5sCpFmSGvbLDhSegy6upBcPhsXa2/fvI0U2HMIITlbQUHUL5lMbqjki0dNkwzR4hK
-QP7oy4pE5PnkugKRLbpRIxmayVIB2vrj9T3UJ/fqdVPtZiuOh5dQd7B3pkwEh6u5QKfSM6HR81Dh
-FJTWcYkgH+S/iXvqh3o77iVqgsWdTsz0D/G/Xg+K44EytGoGLVvI0VXvQe9Btt5dLOopwng2V0ZG
-ne4cjFxjcvSUUDKO+F9CLkHSbka+lrlNKgmkEGU3IlYuTtnKvBxiIJl9dqtlkIEHhwPueaCrpbsf
-hP818gbOFwsbE9DINRn4f260eLapIS5y8MhAxikrwrJQbXpNTpb3gCC3MxvsM6jQyC3Sk5Ma324F
-ZAq0ywlMqNUTsUz2GMOivj8NVQKwYDswfmKd/26NNxCzoxBV+P3pt6HseehR1vgLQwT0ZfJN4+6I
-WmFF0VOFCoqWxp0san8FLsY9cSa28UnA9EjRzzv9LmgBcrJCuw2Udl2Jwlig7bFSQRMBvZJfVA4t
-cWbfGfp9B4Mqy+uJEkgF6OSJUh1Ei8HeanBa4E6BqBAH9AYD9yJgST5vhmqzICxykpPBzEmBSHJJ
-dEbfYHC8yhlIkILmSw6G50nYS+iQzx/tMXt07EVJbXzsiVat6HjgqgD1ZGONz5Jq0ddvW4xmAfMk
-AdlrB4TL5Tl/2mYxCTVGSk7gMNhqD8s7A1h6aAqmJmQYxIoZ0DXivsEIE5DHlMps33YxWPHURPEE
-afMqjM0RON+ovCe9pG0vL2RaPRQ+lqJiTUzY/cdSNxAPPkOYlUyXPBLa4URWfeab2nIuHJEbuz+D
-2w2BZETbKpqs106/F5CVraT/Y//Xu8vLexHOBasFgJhqcF7brS83aPoxENYCrxTU4I/MQmJiovrJ
-dknPjvBZTrYzQfNkNTie+k3f8utQgXoSeT/Je05gBac9FKq7tdn928lFE5iriU3lcBHakYtwGu9M
-K62Dfhkf1Y/wCSGW0HwzugScltT0JBjryHyKLZHqZquV4UaUD6wsYUoBIAI9v6xgw2UOnjgyW8YM
-wSWUjG1Ao5QqkefEdzfo2tPSi5i8JSuUGi7l1rLHds4rNB5DsfG4F1cOQzUc2fxf0ZAfzLg0vyv3
-e2z9Qes/wGZkIAbyEC2knVjrgtVl31giaBJvPLj+Rv54Sa9TGJIFum7EvVlXfbKyZesLLz9A4l9H
-2fF5O4UrTwNL5M5L5oQIrtWrJdHsGV/Dz83AXvD+jR1feATWkQldOqIXudq9x/HyVInZJqnyBd7J
-hGPIq6B7vF7NE4XsM4K4IBf1sBqqz6ybKA8aQXNWn3v8tggZrjObH57Cj/BN057qD7JnM5LN+eEG
-4W9hhE1lOvhyeInKy8mSm0Jrj0nD0NZDjwGIaSs/r3kEdO4DC/H33qfvPkCQYA5y+en70//jv6HI
-wRz1Eqd3s1rQ4ypGja1mLlIqUPNEThCGvRn2eqbr2dV2uz55/Hh9v66HlGG42lzi348liC7E570i
-qI5rhOrAoLz/LvPwOnoKMmzleSp0uiHEAX0R4eMvczpxJFwu4zbpkLgcORcQ4YpSietQpEakb5bF
-ecAcjd5OELl91wHY5WoxI9QwHasdLO+5BwyipOCONBQ1FgbgFsYNytkVVM4LhVcwJwRICi99gTJc
-wW8dszNXAVzH570Au0614+LpKrLFClwK1EFFhupzR6WiO4jqtAlelfK1o0YKIB/Vx58RpS+cjDXJ
-c2s0sZCmqMC5tOTC1bChiCMPMdgIe8IRbLLgaQK7Q2ne2PATrYrAVkGNZdtY+6aIocjxWEN2utow
-SSpidD+iNxu4Nk3rALKz3hiKvRvZdKJ/Fa+cFUOc4TxDSPwZ7yTcekYCLcwnujFAeeXNxYHER+Ds
-gpnHY5fX+XcOMjVVdh5g/qW+SBRilZywNsJvV3o6ZFTmk1QgToxDVqNZtWSAJ2brknWmD4PszmOj
-9FXci9xEOzbkIYGYoYm33qF+BVjoCx0JHO1aUE/AORuP230JJNN1haO1NZR+7xvraxhCkLvOesCZ
-XA/ccvBdf3tfyDQMbJW+B572hiJqJJqBK49HrUQySKopKBWJgx7623OixXi6c0TgGoJpvMt+PoK5
-BGCXDYDQQtwWIM2wKpzbBC4JUjv3FjO4PzP2KNSahRhMVvwOcbqhg4Q4j/A1KdGIDGL6ZkrBQqA/
-8CdCgZ+0wtEGGOMx+M7AmyQ9Zel++Q4leiWBYyUG0ewu+C0tf9gMHzY5Y035o4jFNCNShOyOq2oj
-oARCg2J1XBhYNlV90JxR1kM9oRqiCZlAdgM7SXiBMbdkhzHyt3qSmARmc5KPVF3wC95SzBKqZ2cf
-ohTRaNl7fpinZX/XCUXIj+Rzrw1FImbef4719td8UU+acNW5X+miX7bUwliHVhxoH9CXkEY7eYTs
-xULTJA5ZzT7hOTY261jsBStOi3tY1j6OcpZR3yw6tCMLZYuWZWcTLHi21Z+jGJ0HlTNMpu8tnzwv
-81/arZ/h+zs9vgfU1M/4jX0R2z76NaSKe3Ntj8uk+7qR+xeTP9Tw0LK6WUNYE0JTsM7k5t9U/BEY
-4G55vVzdLj0wcuHu0mqavTupgqAsg0c/kg7CE61bTrA16SzIgRJVlQl7MxANv6JayqLD6Cqi7KDN
-ADm8E3UALHCp3+HjFVacPtlT2gZ4crsfZF7W7Ka+vOJnYQlc1LTJVpcRLyj3RwfaF3HEYkN1Cd+9
-fSyJajkAHc5hkCdXYu9qiMYDwxFTICt6hjyS23y9JZwOkzhb7S4W1RG0CZ4nV8geUhteA96gEyYM
-EAUttzf1fqU7UsgbH8COBDP8xYKfT5db0CvxCyvfXcjKFe+js+wWTHelPiAw0A7qiDjmatVMN96r
-vr2j4R0HfylJEj6AKaoUJbdV6axnEwk5W3FCAp7brCIkqhDnUEThL8CGCW8L6QP6gLtKpAzTeCE1
-P1/befbvEPit5CdWff6bBfPOf7ch9DWB5IYz35/LfCwCABIzy+ar3+279L5z+phAqA9hyOJJuFM3
-zbu2HQwXfT4q78rERdiIbzQavo2qOfHuox4+Z5vEIL0S4a5lWKmhPBqZIxZkBMnUcli7/sFxDXQp
-Z65dwrsy7C3PElJUG3BMgvnK4nqAK8oWVnhHHGQpCj6TqtAP/KM4DkXq6OqoBPNI9pBHkSDvsvfp
-zYd/xqDPn95++L81gAs0LZdfPOjA2sSebxbGBYpaFU9FINIUdJSwo1XwU1f7ICwoUnTOnckJ0R7z
-9JC5UuwVsN6hqGRrI36ZuwkoiYHD5pC1yZXWtIfHhOgChuv73qcfPvy3OnKvqfW6msEr9Kf/5fRX
-//xnP+uJqPQKU16ZFBePdALuhsDCNzs4YGwESjyLqCqJy9oTa5lLPNezetvIKnDMrWY7A3dByGN+
-VpsNeA/Ce84ElPeLBb+LmiPtcjlZ0BUMJhfckXbNrhnS0qJtTIVOAIDzPqs35PGApv2m9GRJiu9e
-IipxAq3nZrJprpwqys2Cj3bz8vevT9+fPjv98H788vfPX/5w+vrtG7NcX7cpYMxUIQJRw9oWerTl
-P5YAeYBhDjxrZGAPJlPaCBlTwssI1ZouwGmxdsV0DTTYu6X/mXPDP36CrYh++ImyBKPM/fJMRIY3
-1zNIKgLw7XcvT//22Xeu3LBaNrtNVeSkGsyD7BRyO5GdqCqR/eW7d+nshvI0GuG65shPQM9+3CeT
-dEKS13qCAaw0rXvtUSXmv77oSYWnV/Vi1l52jOmFIwp9V6I0ZoIuh5bCNihTm2uPNpvE0FBuxw6y
-CzD9Qx8ol0tVYqRTFORevwW3460V1D0RErJdgy2a4UrAwXhHM1sCY0143UY5rF5vIQaUukGpAqPM
-/XCLO0Ts5fxWr6UtM5wvds2VWp75LKhsiOZmK38FbS5zbzmOIvvMduunhWTxsPm4YWBSo8z9cKSV
-6CxWpEu09whymR497eiRyWKjjjjF+lx6QduHetG/vVDGrY5TWbOItEvTXBFUwkajGUKyR5Z7hVyr
-/RdGU3xleQuYrih+UrYUnnMMBObLHIeF0sqUAdhJSoAGK2hlIWT9gF6jPX6skaT1opa5ONjvr5aL
-+yKBguzNMQ4qdT44ykghfzPVhtDfqjupJJmkMA3iVOGn48S3p963MUosrsOK3dxO6i1FlmaWAx+q
-zciUgl9++HYM295gIA06os1cUP5CeOIge+IRv84dUaNp5HevX71//Zs3z757+aLQecvUIotkQNz7
-d6cv331vCvvlAPHx6V8doFWOqnPz49foO3KQDuLlnbmWA3m9moDnQ0FZ/ckZZNOb2aDLd9zizLDD
-g6EOI9TKX4YgOp30vAG4bU/CFD2eu4X6i+zJ3f80D+9rqgoLAYTFT3rtm1wzonxzkR/MJQSPmP7S
-YXk6t42roGN/wP2L+QdoHoR/jH3E4KTHH5X2dH/Jwyrob/KMCPMQgitCQAUiEUvK71AxU7iFGPAK
-DDJ5R5XDihrUooKqOLiTSqg7EYbIGy4VHVRyUF2Fp7U1F662SOjemFiS5rHsi+vwBWMNWvUo3v0R
-hDiw9I8//ES73Pwc7SVq2SJoWJ3xvU/vPvwLDMmzGk4na4AJ/fT+9H8d/OxnXZcOdyeBOZv7MJ+o
-za9XcnV8j/ZVr9+2QnhifskVleol/IOyX2bF1wO5etBynVZ329dvCymn7TDgYKC4ROSlDZsoCWap
-HiwJoXsHcYpmKWs03vycgbP7Gt98jPHSTHfAO/rD6aujv8qDs1h6O4z6p67gNDIwW7Zz0jbXv4bb
-d8dU01Rxrp8+V18wT3TAWJN9QKqAKK4X9/IsApDPEFcoxDbfMz09jOVqCIMVqH98cpLB5agGd+1j
-+g33KiOD0h9wa/qTvSW/eE607my8+ANeIFaPcV4n4nnRHFEgQyB0dzsgC682vkCPEHMjQmxph8jd
-eXWL8AAYEQZHkISJajCcKdehriQDPNrgtCI8Cv+0qmDBIQr8nL2TNoAR8RoBnrgbZvF8tmlDF0/s
-Zh6e8o+itOgQ0GRos7rM0NsQvGNakLiQJ8soRnZAmrO7frmnGlvk554ZtBi5ef3EAb+Czua3F4/C
-85srH2XmZoIjApbN23LUx00ZONbFsimNwtbEv8IoNWbB5nwTN20V3tD9WzmveyqM82oxMylKKUyK
-N0XrZ1LneQCGdZuoDzFd9ClIH/bZIYEyAQ6jQg8t8sN5+z7lhRMi0/eh9CzYOshtEbBmkMWGCf1Z
-PcPwzagE4DFk21tzk/u2X8ZSgaUvQyw++CMvVUBBvEoo8s2qz8vdYkGKfPPx7fjdC0CgLltutt6N
-wLukzGfRG0D4EE6rm5ftUaHj5faGeD4AI+jtOyOXvTIc6jWYk3djX0jP9XTYe/0ga6HS/4T91x1R
-hDlbcbSKKH441obLOl1Uk2W2Ww9Y3CSYPG93os8eu8qVSZbkTQiTdus82MVNb4SIAmN25c17U1XX
-xZNOW4n0FH/h9HItSUhD6Yy6NMPhutpcpo98WATM4QDKOOj9alNfwg0n1JqlEWmAZa/beXfZyY0S
-K0YVWlIuo4PQJJLY4F+akpcyzi+Mn12T3ImBLsR0fl/s5vMKpgFgSYDbwU88wdXBot4bIwApPLsV
-maK+Moe3ChfIajXP5j0dcxqPR5s+E4EV5RNDNrZTuZjtu0Oe0sz94Q9mezBqEK+ikQpsSXIJyXlE
-uZYIGVeqAnnC90eoxR2BXsbRpRmMXibb+kKdkHq0iHjUQBEAgwaQc2oREngaCe5KlZeiWyABK5HQ
-rFazDt9WZPVzX4+553na9agLn0ccJcULQ5/8c2eEXdFDKgk1+MOcfXN4Oat6LdgHAHygLjcWCo4o
-q/01WbVmg/z2LwC2KJBv7Iqb3AgNFIwJDv8Zno04LnF+tsUcmQ8y3DDz2chFDgh8Vflloqu+8svG
-yb18iaGoZ68Cka6MV4hFfl1g350eIJKqyY2qNlQYUAYwOKFfwQVbRjGyNQTsVjDnrMdsfLNCv9H0
-xYrcR81/OSJ34bVa+pGLwipjbHnPCiMhQmBrgJ3luTDriWBOi+n+QCmwo8MOxIAM6r7JAbJYSWhz
-+K1oPt6LTALaHtkTZlhDu7L81k60wXe/mC5AAC2miwbfQ8F5VR4CohgdHpsvNujKCqof0PtYfN8Q
-AkSek0Eh4+B08GzFl+XHCKnDf/jGAzvcwfZBuxINrg8+OBXbJrrI2uyEoG9G8Dh4E5VHcFYF+f3g
-RuFlPNGed+9DJ/RF03Wsb9A/A7pUhNPafVjLvAJRroYwadsiFRPNrUDPzsWIVCA35ixbzQr4pCiK
-qkoC6IOxn3vMe8zaUpgpAX2gCZspmwB2LByGmF+hyIe15+W+exT4/k0WoJK9pw71Y80s+RJ7XN30
-B44/nAe+wBJ0HgrcRphi9UMvMb19PD5037k2e8viv0lymkXrBFyKcyT0415h/5VROsu7A3//fBQ1
-z0nJ5mkIkiPRvFc4piBLPO7yvGvWgoTaAkG32+A7e7OcrJsr00EmiwYi1d8YgdnIYCIAB4RhmlMK
-eOgufSnKw5Yy1X/svYRA2s6Yzb16UfAvJaKeXpkTl3IyAA0+whMXQP6LX169OMbJf/XiaYBqA9bO
-yyWIaZPszYfvvmMVFBR5khXojrABaO+t58HNcGG8teplSeoq8IplM8wng+PB0/CKoYIIAg4UQd/W
-DGXKWCiyI31km8RpbyaKNXJmvvjXTX1XzVisd20tx6Hqjv4UnV4kJqzWEp8YbUma6DEFNmBxqCIH
-DiN9AGLh8KlkObbG09z6WW4+KpNT9RbksoCuVFlYO0p0WUCD6rLgDMWZ8LPKJjMV55SU3LMIMl09
-AGIFq6KhWlUuIGLHqtZgCX2xhxdRfiThWZJarkhqItZ40qJ7jEEnlZcnsJkcd1hKseIqWQUiQPvE
-0AK7iTl2E8P/DrpiP7lp2zdFEaEzHclig31AqC39KVNrKC9+bWfZCQmua966e7JQS4EmK4cshYgU
-3U/yHevfvna089zaPf0nXDvc4DJjYMDxk9fO1zcD34pfdAMxCHhU6kXXfLdq7PbSaEKXKA3rvr80
-WtQlSsMcRCp0cD64qVrERJPCBw9IyihmWzUZHPxZ4uRvZfBWJzrA56AOVOkiFA1KNlNdrV13InnD
-UXOKTlsm2Vewq33VJgOG2zCQVlpWw29GEWObrKebgex7m0kQXMA0gPTiamApUk83wVHupDBvYXoe
-TA+LeO0CpRUkyYVsNc/8G4hd3ICmAr8/7ftR5PQumqJ6upMFvqLR1CWM2UPYCpUxyUXooS3UhwdX
-w5TQjqu9nKqmkGTcQ3vsjOFUS20xGBoytbMoY9sVvGvSLd4UKxNd327MxRUQF56UBw7Mujtuqlgz
-v4jF9J8upLuL6n9kMunXyyO8gNz3PbEd5WW6ajJ672qZAdIk1gPTH8jnw+y1ufQtFTr9jZn4ORSI
-Wv2PWCKzXhtklTVbVajac4qBFUQe2i1nAP4PXBNUdNkLJ+tnBcQL0PcXRkacbMufJNw7OV6L+R1S
-/ELsp+wQ4xwsMlu72ziHmQuXo172EsIMMDxfMISdE+5S6gwbvJQpqx/dwxb5qUVuomGEsqYNgX6g
-qES1pHto7+W9hDRv/vvTLkMdgobMSxiMQJtzc5aoWDRzvmE1Z4mKRbcYu+qZOlzgd+I59/9DAoAl
-qejQT53C8ZTy1tkjEiSVQom3Uks+kWzQ0RvvKruYRaJ7JDkkdURtvelY6JHe+V8iFvxTiZf/SQUQ
-IgJRI+7fjv4+BHgsbDA0LLcyZ8vx64T+dvJJqQktJXU1jFJoV8N4XwgajrSJdH5H+96e8vZd3Mz0
-7oKOe9CKzSpQhdNDK1GYEQbILR1itEnsREceDMB8UWX0TgrQkgMiGhu8HHTi+AYj2jKGRM3mk01G
-rxH02G9O46oyxz/JIK7qKfjHX+42FMBma75fXtEN9aKaTuDgBhFgt13d4Ls1ePyBM14D2jpTkUQK
-NGLMZtJcYcjAHvkzYyQ0dg2sFvfxSY/SIQdPD15jOEDWW1adbziSLckyOHcEZMnKepCqePx9gXly
-6JLi4i3fGv3RiBtbxkTHb7Z3/OYchlmJ1PqmzXpTTWFy3suqEu47MQhz4sI7vTxh90sVf8gcxfct
-gVxcbBh8x7JGLCESoTMlVZZQ/JZNH3odD+bk9UCIDaMsX25zbUqq68vffPguT7wQB7kem78fw4e8
-9+n0w78Gw2R0gLERDz99OP2//ktrnOybJPd+TQL8M8lMsBqebM//NkM/U6+H7tBou7CRkxC834Bt
-bAcuRhZgiGOsLwbA3VQI4r5GkZSK1w0EgVk3ZEUyNgmG9sfV3XoxWSLUQaF+O+keNxZlbsjKwmYi
-qnoDaQvetNXNRTUDSAKLAQv9NkLzZA3c4Gp1W33GEJwQVlNCNm6vzCZ25hvNSfbj8o8D858/4ZH6
-4/IfcINLsLHt7QprhRGanThjjHSod4mRIXUfwfzdVG6fGBF4XkjGy2jx16q7yc3anFdZMfxcN0Zo
-f44n1CCjvyzBFWXJ/VoAKD2sTO1qQYYI31Qb6CBId6G1mUoE+4QnWAYZrgBbE8oR4VN0H2AQ5ioz
-D6DwN5Pbsex6vXBgyZHnpWA32YhPD3gR3MJgPBqMs0mUY2ac5vsfegKsip6xtqWzJxwZD2F6CSBV
-ko5Pzj3hdkFHewNsvcj/mCOcuf/xT6mP/xCh8XhQp10mhdSRo+NzcPjPf4Qgf4/gAuvBk3A0Fw4c
-A/gp1zDGJ+rv6XKrPkWQxPFQAcA2GG0Myss1Q/8SKlbgMTD1WZYfoMHF7PhsH2THVuxkVcuCAVXK
-OBf3JY5UJKlSzZMyAfRiIZKyRzDLuen3V9ggli6PjsFDTEJdw4wFxh/RnP0pnDPmY6mMiSED+E96
-kIkkGsIZ5oA5wEmQjnYQWFuX/iHvniIzN25qojmRWl2OkSyJQFPYWD2Cj2MBHr3DokieM+3mRKF0
-kiw+TBYKfesPfRu7aS7ZZgdKmT2WfNvqQNZPm711ea2qdvu/PLvYAPixRRk5zx42gKrw8Mnd7Btw
-90jDulFfXbyvQVbP7Ai6eNJcOcu+wrAfYRCQA/z6bHyAOVUEQZA56GNCn+giOLbDu3Si6XhNchQC
-L8L6fBiHFHeWdi2wOy4q7AGtJuMCdWPT+b3eSsxDHYpxmELSdySHmsbhyzdvX7457ViEZN8gkgtK
-60bAMGuTrabTnTVMEllsUxEe94BkgzCqPNWjotch7EaFV53+L83l5Jv+sJdc7E6iV6278DUDviqN
-55N6kVi8lnNHb6UpXrWAxmx0lwwMRUFQNIP8pp/yZLNe6y2VMyJGIS0Bvl3SGBVsUTMxRo04FkHA
-4O2nL5I1i01uNkADAhngn3CJCCfys5kcuEASOvP9133l/Ubh5OQeMLY7AWpj0d9WCVZXQcO9NhPb
-p4PsL1EuQk5hxLotTKk+b/r/wXSsLzjgbf0Ak+49/VCjUV99ksG+9j797Yd/MWYsHoJO//S709f/
-OwKzZz8Q2DpeoY3MioL4PUjd292aTNF2FHwSMtg4LaSWifw2OZJI0rcTEXz88WKQIM5wikQ4Wbwz
-nJ2ySZdvVsvr6p4cNgSexn2yiDacvTfdbROAK4XUZiEghyYX4ndzzBBKH09mM3q6LiiOLC/U5Wa1
-W7vgsoaj4peiT5EdFnyDxo9DV0d+dARzBhsjDl86wbkc9ZvtalONt2Yb9yHab7M1n8xVSwriRzSw
-b7E7gSA6VEQTvb0ybS53wPjhKkVw++a2sF7sLusld5rHZHptZIWiTySC0wRtAyD+qE8d0fb72KEC
-0ZbGXxm6gse/r8ZMZHnp8lL3Lheri6Nme78gK3wwJIAwZRRRTxMhI+RZWuzsJJ7oUTdd9/qnpsr+
-IOoNoc1WceskmR3WuN0N7c1vv7B576JL9qReZzSlTm8oFArCa5HGzAW3ob+HRIZDTU7qHUp9lQpC
-jc+Tntemi2MCIFuF6eEEakgFaDJzhrbskmcoYxtiCoSe+0N1WEwW6Im9zq0ZeWhy47LYNlTVxVdr
-i7CyHnrhgWQCWctY+bPHU0eLjWpbvCUX/ZvJ5towfLUN+ro90wDCviPCFZYz4rlADvmra1UH7pjt
-Q5RH8mJBc2iVCfQHFVqAyl5mvblh0oYTvySFx4mu7Fe6Y7kpdmy259nx4Ol5md3i0b+AZ1hQw94S
-LFIjppEQKHKDalXdOd39ASpGxNr7eHTM8QBX6Mrjvj8dUg1w4/mVxYLbXA8NnYDORa+FDQEiAAx4
-RWgcRo1FgRuC0OO+66vWH22HcyqeZydckVuzfLpaLMwhlZ/o/ASHZ77RD8PLngMnMB/wX/P3a/Z3
-MJ/kp6r0Fc+NSX1lpyn/jUQpMp/tb1UKmOzCHhAnmf6T8Mn+5FEsp435MCNKNffKT4bWtupJH9aR
-sjA1i7MTLQ6hzoJ6fHVzIzF7MsMrGgsRbA3eseoh1eL1ZX0PvRmjM4OR2YBYpwj9CZB+kAQA7o4h
-gUjmZRuStb8XGggqtptkpOoZmv573s4uZVw3GCeK8Pvw1A0NcFSthiuoov5tOHEB5LXw+yJfOxr5
-SvKEHAdJD89WDstIGGrcY4qyi1KLBKxaX8iXteFUEBDaYmBi9GIM6tU3R24/QhqlqoeG+kFIHYLL
-Tr2lkCUAZB4HB1hPtg7WjdccRB049HItFqRe58kH/Wo4X96AXAZttAR98sOXtV5YFN9XFMmdq69W
-q+uhJUWZWEBiIwGiCJyRtlcjPeEjnveApBP1JJaJu/J9IkNHfUA74U7hdEBgIOBP57tFBkQtW0bW
-HzIldQXOYaVnbaApyp+RJoCjFb6X2ANlj2U7NUTXrnxnyAahOD2APdfIAwDPM1XCO3JNTqc39R1A
-/KEwRSGTQRB7DuHMZ9WmBt/9wCjANYqlYDYMqQFsVsIwzNmNAEkHQ5H/IePGsJVSM2hupjsjbt/Q
-FPQxS79sw9rG5IIWhsnGViaOiV7XYdeHPcfD0Zrf4ISOx7Seeeimp8LaxWPiTtlzpLNjrUhOFEtW
-zcjSirGFI0EOxaM71Cbnyb6Mw05iiSGoRCDEbfYX2ddPDa3YGq080SEEmvysAXB3TwJKBy9js8um
-4vRKRMlUaM6/G3JFRqcNF4s5/aDJ+tgf7s3QvwfKjX32AJo5QLSZJ4LvdKF7ucg4+jA7QAAObL7E
-TdPagph+YPfaGtXNYcfb4+6EzbjQO3qpBTd7jnF35viWSc4RfWVxx2HcaCp5k9nOey4nPID0m7Pn
-acncn1xO4UMQsYJgj/GMYwun7cr8RazcGupNF7sZs/ckTI4laY5DZ2SmDeAq158rsVwAh3hz74Jx
-UkW+ocr0auKMdcD3FD+oJcK/h+C7tPHcxCSOS2hmi5qSJRXrQk5aohu0CKgJrsjxDX3lJUdHgMLD
-CGI71QAdfYnq+T0Eg2NVyxnrvEA8SYRC5FbNP2cnR1+fJ/Xhav1O2gKpeCvarmCmWDf8sNMeBiYW
-TzoKUlK8jmjxPOTYIJgpxs1wHvXDM/CJPOsHm8LG+f6iEF9S6kvCfHm+MYq3aNbxILu7uzP3xq1c
-EcGK1hyoDPZ0D1AeE7hHbGbogp+ykqfzD0c9nkRipPNAlxy9wOBVxubHOfbiofcCUtTBhL06zo7P
-KUj1wOOQ6blU9kGgbQSFbxz5AUC4p5PplRn8t/tmM5oUQrgY4wuCDbEdztADs0ebKhM0jHpRb+99
-MV7ieGssdZhRp1Y/tzrQcJtTYX/fTvspo3wb/hx/mN177O/eBzz5T/yvGM29M4p7lgrWHhkKIAHA
-qJKTlooCw/ndLHTd+rxA5fqYtYRWtrSBOdUh1EWNUZx0DTDhdWHggmKJpPJcRDiSV5zoIoD6Q5tD
-YjTg0e8LqEnPC7wJUjQuCerhXwVj/WdCPMfoiO7Zg2OktQpG6F2uLMv8K8A/rp+iJP6z95JmOOYD
-b349xCvR51U9gzDEs9WNiDEcQ62qrhHozkgSLvCLIQwd+OVBVgBDEVPcxT1QysaQ77RiB4qJIYQf
-7tEsCSQdsCaDV4RvSy8QDIoTnhQltxCOGzPI/vin0pc3QM8wXTQYks9tyJvNylbgntPDCBTQpByW
-XM/QRVhx/Lxa+jD8Ce8iUwi6gFW2xTIE/kp52kMZ8lITnVTLtIiQlIykqzZgmgeDENQPEe9+bs79
-cb/LJ4heR0UhoO5cLdIN3/HbbQE6O58GIkUnpAA1Jd3bM/PPeTp2t8SH9lyPFkN4ZSquq/vRYnJz
-MZtkMMwT/O9QHZ7l2cnT85THkuwuO0M6hop/K9ZHdYdCCGvxEUyEN45c5SPbwshHnPHvyLo38NXv
-kQ1NKwcBXVg4Yk7pSQBmX5h+xHlR61DqbAR7ApkJsA5+QlVwXnoGDebqvWzm1WbMTxUF9xAwlZoB
-966Mnk0gshT/VCWQl44UX/UfHk2NI1XrKKzczBqsBSyLjJHZs14p/0FJiaxmKEB9VKvnzI98qc0+
-BgsK90GsGCWr46Nno2ecvhRg14UlU70frlHHzXkHdtZG9vXLlnrldNdWZvAUTpKhX0ZhoeQJC3VD
-TVK+l9K+5seP6ZXgolghB1jtbMYFz+w/bM4eNudgU0VtSR3DOgB0VOp6r3sjGzhTdTP2Mpd6R/KD
-moJdaCnR8JJbc6loRn9UvTgBRvynFmdI6VSKv8CW3r9PeE+TTL9V3gmGWOGVC50U6E6OYd1MPUxf
-GXoR0ieugxO4hptqc8nPZ/xOg1oGzDO0z5xX6FaErrVBn5I3QNpO2I0Rlx26b19yFYxOEv/+7ypN
-HiAYnwl6US9Vn+JDBr7KrHdpLF0dLjcLwaJ+J3H3Ffo1hIKxNp/s1DLRdgVv1voP1Qw3fA46sFzA
-L8nKBDvDjM7VHKbFEqFTkN+i4Tx6u4rd/8rMqxEJNzrSeHKRKcocRRGhq9r6ntouKJKPufThS4dv
-EsaL/v5+uZ2kjPi+LDIIOZtgJ3iuyXxVAoSAAhgDroKtB5qlbLb9MuqNHgUhin9fN/hylOohX2hN
-2TFLD8GFs61XMQwwmwuhEcoNN3ny47LflrOayan+cIN+M8gN5ArtvBHSdWTZwyaZcHtVgz0TnWPo
-CwWcd0Los/TcDj005HI7IYcpFlq+sJ3fvn5zepJRKIIMHo5BQQEdf5zB7Z58+0CueGx2LnhWTVLY
-ybtl/WlXZfL8iNv83lzeVU9Z2RAXzh5m1TB6Ly2jSLR2upUZUB8Zn68EYimCGObNZDm5NLzOfGzq
-GXB0G9cuFdRQufaCgdseABG+KGFWrjhSyJjz4UQrZUwF02voNemKMYW6GihygK2adTXyKTyYrVcN
-xqqbLMB2YoBweOvN6mKC/nTymE/2U6EJ6wNwrbutKCQqKqcZMIzpljTwkU7X3etgccxvd7fTIy7N
-raYNEijIais42Bw1qkGxVXMZ3sxWt8vDFkly/7+9TsN/0oUKRr1nrYLcP225wkoc3iWKuOEJ3K2P
-alGh8IY9SwvR8rrRL0nS7Bdl35eGz/fscyK5KT8QJ3QjKkOE/lHPvfKtV5G2RuxXgIu5QS1aPtC5
-yy+uZoy1oCrnkHrUwu/dbXa5O2bLz5OasKCW1jlrbc1P8GbOTyp/Yn1qCg+vUE8ktSC0edg++ALZ
-1L18ah65rG69140QZaTzmVhXD4oJCWPCl6dQs6zsy8i8Y843HbwIgSkZWLGu3CUYlBXWWiH2tE7u
-TKjdiMJgNc826NSKoRjPBnEv/ini3m4+VzOauPRTE01MkLUV6FitQ+sTq6qXV0wvUQpWoGuFWmGT
-fYroJU6LWuBoLYmepJ58RbjBvHlHw35+WYY8YKm4h1Ybrk/tN2QUpA9o4aZB0T1s1c/9JQxNU5jk
-OZTIvnRy3Vl58PzaIvEUd6+9V1Cm5sAVSJfdz6V19tQamK21W4JB0LS6MOKWDW6GN8VO4D68ewd4
-bb5NO/jRYc2h+gIR6+Um+9wCmUdyDr2wqXdDtBUzZSiBnPVaXhXtkDDIGl187Td/XXVW+3s43W0L
-ZZSo2hmp31HsFF2bqi4W17xmly3tJhHNDm5iXzNmXsAqA1sjp5wypXYYtlTBT39+LL/1Bn3edpvK
-3GR9chpkrHFYrJaX/SDQgQQv3WwUP39FNrrv2Mb5u9XqerfWXrfpB2FzaSA/WIJUdi8asT/7IBun
-HrwdfH1MlcCJ6oF1Wq+WuxtUkONzcZN+22KfZnSP9HybzazlZdtblFUpmzlQYwcHrCIYccJT/6R+
-BPYT4Ksps0vGZOX+iU8a8qdNPL26QaMZ73gtykS9iYSdneH9hSfikIavHEbkJYQVeKYDkeF/PdQj
-VzQkS0JD0tFblD0AA3Tz+94g6+OTL33cNZNLCtECKP4YoqWf1lt+Sc9jTrq9kOE4ATBBE9pDr90t
-XdxfPZ6GLlECk4GQgIhiH0qrkgkCq/HPCOVNyhIOlPwVxHIXF9yR7U6YQTN9zeSd+LDa8ngl9N6t
-vhXdohe1jrytkCa8wQRHJxfsk9bukbd3O2pTY2VwkP6Py9Ciwas81QDEuJoF2uF4KLaah83Jw1k/
-e8gevW5pw0l8BJ7wQj7OQDnYZl90JWo1rkAJzVn0ojYdjQkmjXvXbTCyu7mc3KNHtypeLz+vriuS
-Ih9b+Q8eYFbr3WKyEZcXbYZRL8no4uKe7zt41emT62MfhCpCxppAqAZ82Fkiqg72tQmQCsUdY4xd
-QL/8odneINEV/lPeA8S+8SZx6PxysXVXx7hu3EVmfPz1LwLLueCS0yFIBi+IsaEGH1F3/vkkx1lR
-JoRhetVDzzj9/gof0fvwrkwxf4UkgTkvFhVF1zggIujDTcZuQaaqZSbliXwoOKjTYGDnyrKXtBlp
-M72Qp9KzhzN4KM3qA7Rotkz+sMmxVMrctttWJUb7MmOVd3Sii0aocHnEmnus0g2bjanC+2iXnYt9
-XMVpC56iqU5YyhH5XMojLi5Xl5mHpoKW8EWB7QquWIHRb/gJMnkHx3x6MwHMEoR1pe3aHh/p7Mn5
-wAMxgVeP6MBSq0ll0pase0BpuAbPiMPbKdKfsCqeyHBvGSb8oPcgQ2+b7DWYQ5m/x7Pdzc09VQYs
-tQwUPSGfZq782vnvwZ154hQ7kIJR2qpmDe8uArJguBEGgdutPTxgDutjEibi7OxvR+qXryECy5B6
-pucmIWx4BgYkQCEN0k+2YME/YhnYWh5wZiZYmixldEDJzLVDKc4XJ60kKb3U/RuEr+zQNzassdXz
-v2FADyYG7xFNsCf3+z+KTT5GjhEri8TLqPBL52lTOMmzBHgUcrr6XFnHyH6XrqqeK9OTLkAbkkkl
-68iWSmdUTpnWHsR+M1SoTip/FoWilBVJ6jZl3eDsXJGbd7/lJiUiOIoN4vVu28APh76vqKGpUfA8
-oqEjTSMRabvbDmfvRZWzpU5Ch69fIsJ7KX6RDTHcrWdw3msOCabRpjDYabprLa2Fdx2UOhI9D6uX
-v/f7CTEPte5ArkF2LjGSqjm2wL0CbHGsY/zE+p7JMQDGm0fHSQ5NTir1+cHeSYFjUmKXdhmiIBGo
-PaNumjs0TEtpNdk7FGVU5YfVodJMWU46r27n8sw2Znse1ZK8kLJ2hUyw/u+h1kU5wxdBB8bj6pND
-YweLrAPcYwpLIqDZwlL0lzmkOnY2bUgpQH92lhAJW4rw351lcN9KAfijLbcfCyEnpiZPbqaKzkJY
-fVSqxS7jS92GfJdKt1LLqnWlRIphDa+dAV3cUMsVVxCXhMTCf5hxboHsxRp7CcOfoWY8l0PbmxXU
-+ddb300XSv9cpCl72CdJjhwGeizoMjUj1kXh0DRQYwc4Z3davCDTQ2UsCDgvAK3TZJ8nG6yjx/B2
-+AcpvZvtbBgYDBQtrrmodCtFcq3nqh/xpUelRe3Y1xBbK4p9x3AAPOkpuCD9AOuGjwxgLFny1khE
-iZJjW8ytG8Fv0fKZy6lqeoGR2elPu7wqS0RdMrVnbvQnR6rAeW9P5nNaeo+T2UlyojWkgy1aI9E3
-IaPj1CxasIWt01hrBu1bvApsh4cvAqr08RKCkNTNttHXARuwdLF4b1b06d5QtgHuj0OXcwbl8rN3
-gIDDcuwMLnOh8oF29uQmWQRApTBK3yhzI2vJM7a6h20UMI/yiOymqlLqKPvekBj8FCp20+fNhbLk
-b+z4RcrxJsXLSYP28tEnL5ebNPin0BPp51Mz5U9LMtdY62n8r4n8Mm/RXIb7aaomdDy9qqbXsGlW
-W3amrgR43Xz1NQDmg9WEMjUAqIT6GqNbpVUlLho6KUPAiKv0HcixgbTLWafjLXWMFCjhIfo31X3i
-+LRXOD2PYFxqCfAA7U/syOxJkno5MNevxH3fQb7PWk7X/hE7MN9MjLS33aB2Hx7l5E6sqK30xUNE
-LXEgAwCPNsgcQtZnEBK2AMQaOPTBephEWNc/1OsiLJGEKkhSEtBQr11w4j6VZybfOQEdJNmRKL3A
-7UGPT4LCDCy/hsEM6HoRjAkVpWkC7RjAXZlmncISYq4Bsok1nGijobbBeTA+TIdd9bBSYQ/9Jpr2
-eQYTppj0M89sf12yZ79W7qAvEv1iZ6RQTeMevfCRH8Gs/JNLHLcCG/zw5uxhloRrI3JYq6jXFWQx
-vhc4sbBebovA7akMyMO6iX3BuMgHKHHiGvoIopfRqWmXRcPLWZ4dot+BazOFoZBgWDXr04KL67MZ
-RhzAt5kpwfkLzkbbPTbbobAEWYCSnY3M3LVvDdQoTrn0cJhlP/hKAIyOQSZBlTsQGf+XXnzwXQmy
-rs11oqJ4wverHfreYkQAfJep7sx+agAmZFPRU79bDsgNAY3R+NdODFwQUFquAcMPsf0mwiuy+QTe
-siA6C/gKTCeO6qwB01WlGqVO/IddA6g3Jr0S4EGM6bLdoRPxZrccOliFE2hHZuYEIkRYjEG8GiN2
-E4oYNLMuqYkroWk/USWCheCG/FpRkw/wg97uCEqmuxAORKb1BNgYTm01mV7Zrpl13JDOGgO3mGXT
-44VoHF4XLshS2ywwIu+SSE2MyxQFy2+oDOjCaUTtmjWBwdAVYKttEWNaFu8GVihYvUaTHa0nUlw4
-Pbyw7I0GAW4ACF3RKcBJRtMzM4sjM8nP6LDTcZKiueEF44VIjYfeVzcVoqAIfiQR3GwIO2S5wvox
-y2b1uQbtMhZKzbV7wuLIPoh6dk+u7l5nhpp7dLwUOZ7U9VykGLcrUYZZeBoMryzMz0GJlMmSik0+
-jzojBBk5I4g3IPiDAeY4ygCW3FdrdDSA0DBN9W1kIMSSr923KTU25KEuxGdUi0lQ6mGRIwXZXaKe
-Tt1hDMKWmzGWrdDyiYaPHI606E0fdn/fPiBEMxZqh+sZ+HADoPPrF9/Dr8DQio4qvP6AmMrZNQir
-y28OmcSRF/rI6rPRJJ35F7vy/CRlsEXyqf8krnBg24CSQCfBoi1ov+BPWaQEYBJ3338lGdq7aWeJ
-oZXKO+Xx5qw+b6/HgiC5essWmUKyOKFhMiPHSl9uZsGtno2c2MhytPoSSAzqYWqAXmtKIClRnpig
-RIHou5Eo4eGNOpGi48DHo8fGGRtC2CRUtE+26s5EB4SMsqQAYOjhqWpmUNag+vWmXm08nS8IfjDV
-Zs8ZHghHFR7gVJ5fVEGdn/2dkSuYl6BTKfrwSR/07vLEFYZsshjDFiVcjdS+GQTHiL3KOK7ArzWI
-1AHeURvsx4xCJaDJjZ52OkCq7lbq2QnVARtMzCwvSVaCWannNcmK2Xq3MdwSBTuSynw8ktUy38Lj
-xBo8tJbZx3r2Ec99OWQyNpGoZzYglz2Kwk4R7jQ4ehG9Ad4xCmdS0hznEDQSFyxbTCBDIBn4zMtK
-vBBGC8Lc4cR8/OiJGx8/OjfT9NnH3MSq11h/i4BK7jx0V1VYJ484dMn0Q62O9py+zGrrlS87eZRB
-aCFHA7jbQi1IA+hmD5HMhFjEdOZA9F7/NZVuyfEQ4wPQcCWcRwwoQcG2+okLd9slGfVtGBvIsUZV
-fMbBToL7dz1zp1B0HHaptExBPJ4zXaGtBziT02O0qC09rSHrOVIajhTTt7AbjXOHoiO75T4f39Dh
-cROO+ieqAGGlOr2NrwZK4F2wVEZZk1bFak+AMAcWflu0ZS4TJzVUh2B+jxp56OWOJtx5ZAhRYC5n
-PmUqMVXGRlFW27YILXFZ3+8eDJ7ZN4G5wlFVTJzhodoYrD29OJRfjbEByRzYjPbjx4jtIPjkRAVt
-ooK3Eyyp2djKYYzIMUSH+XA4LB33ottBs8OLreGdUNNsRRavE+hBCh/m40cXSGG1uh7QtcD2EZkw
-Y76iveMyNCoyM8SQYWZFQ1B1l0ebZVFMAFwOZRFdpL0F8Bke40Ou7D1PPepYIQF71KbkiuDTlRWn
-TfIgyVOv6y4VHsq0eUqe0qJahZyCR9eFYmgeeKUG8mMArkLpmwYSx5h95DCk58V/CLVMDpBHtdoJ
-y8OojMLYnQtfjM5OYnHIqGBln8odPfGixB7ZsFZ6/WOleZsZB77nyYZk1H3vZmy3im+K4SntA+D7
-li6IiUyqC5LmtW37hTU7djAcZhzJaALRP09OsqfDJ0k5o62X0lxbV9O4KOhKSgpKiocY9/TWWXUb
-aeygvjgkLRYrNPhWS/8AKSrROdr2BShtDEshE4uf0FMf6auzrwH4F8FdmcJpHG+LBNb2stPiGwxj
-k7RgeKslS7Rfug6BPVh9A236ioKydfopkEWil62RLMw0raY1qosYSqlufPa6j04kpkXL/m4sinSi
-S4h40tw3wIgR+lNvM0vSqLWVSXP+pYd1jzqgDonYHkp5E7U/PgQr4GuIEjK5shb1jNvG/oFCIa2I
-aA60Jt1jQMqKLbljpHvnuu1dMVIHQBuAeiLrGdd5rnwTOI3itnM6OLlYbQZcKAk/TAwD8I/wbYPu
-nZxI90J4ulhEPNkdDLYCjN7sHKLNVWi+W8hdni62gg6EszoRvv+YmnPPIkuM75xoLNKhU0m4456s
-70+QA558HOvwPd+b/7wQCOiPKdSS6aaacKSxidXBgEw3dLW8efb9ywJkwo8fD9XnUtcGmVfP7//u
-71uxSJMaTb7hTvxqvvKB6pPkIqfcGXUECwrZ8IQ7lgYwS7Oxs5RkaA4HLyGW5UZOqUZ9i3eEAg/A
-ZyYeyt6xqRGSDgWn5MiWhIOEM/7xIzZkpPe/sIU/fpRWzWe6rMFHbBvE/OXM/CUtmw8uKGQU7NKr
-yp0PfijzZkXXi2Z30QBPXrLpuaEDVZH0kyJSbSoiG2SkMrCQOqXtE9e0KVfVn8m9wAj3n+vVrjFb
-jh5PXD1eNZgINL5cHVkllq0R+0EVtpWHiYPy/IpCz0urHcp6Hz9KTR8/DsxfSJv0k1ZZXWNwc25w
-LtDy38wGKM2n1D6qIglQPFvU82p6P11Ucta0dE1W8SRDYQ6fquBKChc7qcskQy2FOiiYEMvOvejh
-LonvQk5EjgSfvFqwt6nKhpI3WzjeVpNrcyX7Vvm/mBzQQ4kkqoTygUPKwO4SQCx23O2c0q8qQB9V
-3Wi366E7P2Y6k/4caNRDRUOzZ9sbV11gdRJAMXR7TJBVoVnS+g/wIJLWqs2qResQUnAOqJZoOTQN
-Lbn27C/hXrQCoUgDo9OGVd6J6lkNxGxuU1d4nkW6DeBwFoLOilS9CI5U37PoHEX9XYOx6+JaQ+Xs
-dsWR+ziqXWsJUjqTNgTeObe3q16ggOSstXrORrC/IOKjVEzy5UYPiu+rYD4A6v2PH4PZNFxDOkzv
-xobWMcKS96QwWxm+DNIEsrbZTIDMLBRpzFE0D9gTdSIUpQ7bLZ4FeZtwpy/tKWsmnR6Jckm4QHgu
-RE6WVkeT/mHkaSnSxjtQCcHdiq8A65ceSZz02D5POSWi0lowQfnsNOfZbgMWAYv7kP92DDc1Lyj+
-LFBRBap1sorz+8PL5jQiHU0M1yvN0laLGalJQibt8KXXaHhkY/Wqwjdr1C5rTwZXQe4YQwfirWd1
-qu918uBpbTmjypgkC9+3YaAkxbKDTOOXhng0pGhjbfkABVGz6zjaUPugWvYSRnVu2PzMLZdEfgwg
-oOcULiDq4m45W8XwX5uq8V2s1MFKYisyd88eFz9h4EFhX/0O1pDQUyK0lquFhZ90JZ5zbFAQRaug
-2N1PUbTwwO66j13u0Z2/ZtSbTET49ERx4kHT1KrC6rVfbHbL6yUiWdHZTMp4ap5NNuC3Z+vsnemC
-3sF/+yeyyemS3JFlzhwn8k/m8O7hnWmaIuvGXIf0w3Xkh7ZHxnCkpv3AusYQk+50tWDdeasY2X77
-SwE3eM0H3mv8eaT6w+2P+F/PoQ0xXNr8nPq/9J+CUJB4uPnG2uKojnqISdEJ0CZ3ucjh0Xsaw5c7
-XQsdiO3Pw58nm4bx8tuDcWigouDwbJFntSume1RVpc5bo18okcIOtD3yhc2SjvnVAQel6SUJDUV5
-++r1CFBprYQ3XxkmnX7U46ddOcwGfp2PTKU/LoP472Sk8bABKoEAY/S8aPOU6TpAwswFyNbFr8/O
-tvgWtL06zwmhvlqsMzRcMIPt9xJI3Pq9zDTA/nipsOO0Fvhq6VRNQHME1n27mazHvP+0z5X+Xsh9
-dKwbwOjo3HCcUAT+99wP2en8gCdhe13YVRtSFxAWTpIBJlSGsyfn3qtWLxYi4pJRASMezeoNWWUj
-avrC3G/ExGd7Swn1aigwTb/b1FtrLPe52lwAwrEYv0P1dA/rcxLrvfz9Hu30Di7BoE9MyAEXSIfm
-SXCCAJOtkyeE/KCj7HnvH8cVIo5w5g333Nerp+uiqeBOc7iHMUraQSS25Gx2dNAQAun9F3zjLbjc
-gIkmifPH654er+wSsjTsP2wMI2BGQj0zTQ3iatPQBnGFEeiNhp1SWQfZ5aaqlgFilbvPQl1yDx+P
-zd/jMVqX9lMDNsktfVNgWyZTO77WTwDy2j8zXkUPGzwOTC9YsWiXHaYeJ33QEbBJsL3E4dgRhPOb
-IYpgR2hir+zISwxgGbGYMCSfcx7uCR6gRGTUL4C+o/EwEaMP7M4gCOpiuyq8ftmOhMma+Vt4smK+
-lMP40bEZvIsZzEcJHkkNHligokcYBfxUvLxb4+OcRSEcZF+RqdNXX13fonuVQsChlzFUbE8IaPTC
-zND1Y6c4Bg0Mt/arqO6eAOLQETnJGLGPr6NoMACKpFuTynrv13N2dGHcnKfDf4vOExerz2YTiksJ
-nNieeRw4LJDRBPiTQZB4VnycnDh9+jfffEOqH56Lv682qxf15xqOn/AOPBwO4Z/jx0+o/FsM/4De
-DC76pwX1uSAvF9Kgb1dHF9URXxIoJFjYi7YODCQ/NOz21C+98CTQt2+ovlWiVyBAXdTbDZik2g7i
-sK21VNgdVK4W5tQQSjt+fKdn4sC+GzF7T6cPrududMjwnwERbGYQo6Dh2KBwnTW3NIrrwSyFbm0M
-FjI7fC368+JJ2d8/ImtsNbZgrlf1DEKOjFQARdZo+Q+1PN/vsA/PiXTjPapCr/vOHg1CZYEZn77y
-QbziADspDsZJ2aCoY0AbBpa5bwjhBv4ujlWoLTp/NggxM0ZeGVkdma8W0ebWd9eUuCfML6g5flgi
-Wd+vul1rFGAev0clLg6pxAip9SKEHlesGghhzOOXBslHs8FjvgxCWMCbzayeLfPT7KYy28vmBjWH
-9FUpmnEnThbfBtWQDWHdEL6pmfjVveEPqEbXW4w1dRENJPUoXeGL/AOYQQqYZtpnFkPi4YkA6Gvq
-VPjzdxD+BxDI7qJ2Zk64EVHCnXMkpg6IQO1LngFKM1SXD7LcSCc6BNgabhH5w6Z4uHnYlLk5QDW0
-BsJqkFSak5dGSahqg+yaGvOstV+8fpG9eXuavXv2+v3LvrVc9bfwPjyJeIsHho9RBjOC9PnqsGJt
-VCsfQGk8htB+mxYTZFfKwrssq1uTObl06VgKXIfX5J0a7VfbtWq2lU3qR8E1hBZN2qx3LkZqaA6d
-znQj7H/dNLsLFdrCYnSjv1B6Kcyaf/r9h//CTJDZ/JdGZrz89Hen/+y/+9nP4CC4mDT11LCRy0sx
-g6VHJzibAFdxhqYp4B0IEKubxxDHCdynDCO8qtCDEfiNc45FlvHsh9cnWWEkH7Dz3aFfpeGkq6yB
-djDw3bfKyt18NFP6HSal33tgiCPTf+j++9MXbz+cDloeVC92l4dkBIRYI+iNfHglKIXqoL6RRBcr
-2Oi3q81CexRAFi6cyJUeEvaef1u2i9bWLVeFg4cRjAPWk28Ma3O3NOei89tvAKt67z4XAxpiKOHe
-szarI5vRz6BhELXt4BY05S2K0yyEsLA1aVU46Qna6oBQmBkq3/onXJ3X4dJT5JpWWvW4ZGpNjYF1
-s7xQ4ggchPIPvB38CQ0c30ogALtzYFOwyWEDAdzN4Yxr0rC8h1tjpt+3JxBznnZbztxuILafYPSD
-4gnGqUJ/52Y7W+0UiqX5u9oQJAjCem+nw+xDgzr+LXk0L+7hJgAhqo+Oh8fOEh9/MMlg6Fn6BdjO
-K3qlZ88pivqkkfpkxp9aPoE23PvpjX/dgPpmw5ZXcJing1C4cjkqA0KzFkWp6FhsC7DuIARnGHeR
-tsNFpN6l+byfZSSQWmPve7pVW8bPe/jbA7MKocrsYQMPD5m/GcYpxMYxSxYeYqs/5/k4B7EGElLG
-e/4TbaCJt8Qv6nexAwy6ZHYa6a28hdEPtozUyvVF56Ik9Nr8kr4KGBrs1VvQwILpJxO4+NSvwdh4
-A7bLmZBx0ZTegxjLp4llRNhsWyqY+MChr8OZD+RaLC2s26+KGbQV5/6Gvn+PXTjQm2vfXoXHt62A
-W7WwyqgOfb9iKB5XCULpbau9HRlOF9VkU5T7sgn4FlbqQ1brFXB8JiAAQYazy5xhtFGx7CNYEss6
-ekGEmZp4N4CXUkDhFQQW3NVbVGHYKg2LvZ0swL/WIgle4ktK5G57gREPNZqGW25rdJTo6yTFiAj/
-GcZnWH4xN3sBsmIYF9Np5hjMpMqkPRE6zsPW30yWhgBBg2/ncZA9GWRHx2F8g/B6tpdczqzJ7kl9
-fh6Gn2k3SxLVmRcIuZswDVVgwBUYcD6w/FnSffioFvoZ2NkPKAmgBRQZoak8flSL6D+pP+AYBPUf
-iPEgyEoL6Llr3tedJI86DwIsOvdK31IjcaBaHtNxqNpqx9FpidUGduGKjKGLSSNwFRoAbEu1HTjr
-xcA0D4qjoGer9OPZ2BVQnNUGqUqGK4jXM2FPK7nM9OChkR8Q4SApsYN9O4MBsEfPwGk94VXZCGtH
-i/qaBmmbDR4sFMOGsNpuEHsYpt1t5/TQiB9J3x5uB3wPdmItsB/OkrnJcBKoPkNJEM0KUoznmCl3
-xyeo60g2HeJcosMttPYIX3SwO7HkZDrsnXGFPFarvdq6S5M1DvcUtfXz+aVOrtb6dNaed4ZySWZR
-6QpcZooS8Jy7AjECxOEYlju6dMB109IEvLmvSbWPr0FITqW4ZekAjyF2Wxz9SOh/7gjfMbBYScvh
-hRDhVW8fKL5aV8s8FLvRTWuUzVvFNkeFe4Q2mILYYgnqD6jMiJpEZy2A11QIUG8Xu+YqaS9P1WK6
-A2f9AbzRulcGH6ZgHhCfmkbS0E0PSneujQ3tQ+/bDNjWS9mUT+6r2ZhcNQTX7WI3n1cbZ+AYui1T
-pXB1xx+JWRQQd1hN/jNcTNuIyWd/hxayfv+SCPmmB/PaDzXtPgay6A1p1r1RwNzmkxyIML910Rnn
-oDNcW7MkN6NQxz8dYSY8NQZZHxvsl3vm4ycRt7NLtouyn6ZhxKR5Cg4Cn5gdCTNXB8YfMHrzqZ3R
-QyMv3737skYg9trBpwntzvf3oHvc3wJa52PebDapMIpUFxAAoAKBppR02P692Sam1cKuKJlivf3N
-+PWbV28DZGWXS37++SmS0cJp2PxP4TVPYQShATOhINuOIQWuBv2X379895vs2Xcv351mz9+9Ps3M
-ama/e/buzes3vwFV9+vnLzMYV/bi5a8//KYvcih1lKoBczszerDRwA+96CohqgBaxQFlG1j3V28A
-nMoS0x6MfDQb//T3H/6lGLXRP9Xm09np/3mOGvKsmNUNiGfouycXJsQrAkUrOoyws5/Y5AEDkt9s
-ocWAEko7Sy3JF9P3QbZq5M9N1QtMP/hPQA3soRnefIn3PzER4T97rSZ678lubZC9/P3r0/Hbv6Gc
-TiSWfCiujf16pgCEyOm/Xa2u3wETp/3LGB2T2YzQSQBLpLGC1+VmtVsTimxDAg5+Kfrr+0V9wXwK
-Pw1dDfnR0XJ1tF2tFs3RankEhi4+6PwE3yhG/WZr+jXebnbglglvlKO+YXZQbrWEUn17y0scl2Bs
-Mir6ZnGnq8/o+LsCOLll9sOz09+i8301mcH17XJF+gBCf4JnppsZ2hJx90tvIsh8D6JMepaTD9hV
-uL682iqbbAvvBetqiOQtAIRtJ9eVu++TWpaecGVBxhBbF73PlZEQE1S0eZJleF+8MQdgsCXC7HBq
-NmRtNLkgn3umijGeGePxcENWVf3VtK8uKomKwk9ggruYGMGx/z/CvKKvALyuru/7/qxaCBiuQRwr
-fKn6B0x7trm0yVY4k5TWlw+/QsuAHbS/hB3UWibAuNmAo/XMagrgk6pE5zCV0ObhAhjWZbxWWE06
-NxldjulPQ4GcHf4LHCGMWqjQ7ZzBu1cf2fi7CiMdqs7tpFqzcWcAQXXSHeOLzAriG0SOT9W5mHEG
-lhKsFAa0M0NHrM7jqloygY9TDp/yFHSM2C7u1Z07oH2pODAMAefM2Rl3/zzWubuZyR5uiq++ergp
-lbU/TcrMEqBe+NaZ9FzgYmghnWotVPnvAKerDTZalrcJVL0hrTlaJlrrCvdncw2yAvSWouQJhFmb
-Dfpl//BNlOUzUIrNkkS/sDk9P0Q7PF9bQgYPmAbrlQCeGKs9ClW1mPsK0gPbTksnWqynlRUzWAf8
-3Mg5435biDKSZFQnZWPRyAAzFVaVDtKCOlKGYQXsGFQ9RZlyPJSJsitBLmy8+ROYHJ535qa6rEFK
-KqREsBWhUsvtjKigaWR9M0pUOQiEY3iAHQkAmHYoCrlYuK8JjJInIiYMijodLVVqkLvlvmGqauXB
-wm3tYMVsaBJYtyg2Gn2Prc3JrMcQm/1xfWuFmtaAQua3UEi4byUGHxtWIVFC1/oR5HIDtZqtVjyB
-R1af387ZTDxoHnwxJrYHnX3XcT9vK7R/BDs3IxpNJ/DHbeUDp5jZBcnofl3pgKEYcxkRkTYrgMpe
-grGJNRsdkGmuKoCPgI/FRox0EQ2ZrIDMDu89DdeqmzGiI4JKKRMt01VrcSQWfP3ArB3IgMzxy+Zh
-gXNWNu0G6z5JDT3Exs64BO4kKri5jZzHnsIfLjMPUwkS9JVTOEJKGAG2Ued9cCKo04DxiuN3CoE/
-Ilx4vgb2Ut5pCVQhRICG+ArRhm5HOBUuPV00LW4CF5tqcn1A6MfYmRPmgyP24rYitzDTIrlyJj1h
-BhHTuK7u/YVYpHGv7bCn8enFsSdZ+knPngdviQF/O+L9coATWW2zkeCh80vs4bovlrbjFkUUJ56a
-EaBwadWmQ2tsuTpSCgvP7jc2xL29AjUeV5YMeo2g7iPJgsLlkzKGD1/OBnYlgojauCZn9cl5+vRX
-izMaJYwolD7IzE7RB9Sl75+dPv9tf6CCB5dtjpOVOc8KHMVAzdGAm2XRtsNLRpp9/tuXz//m5Ttp
-GWRmqrY097Gjb/pd3Wh3nfEG9ra7jc4mks+93lSAcyQ8xD8KYF3b97rfuXje++CEkOxVesCCVkWW
-nlN840PeAN0yfIJojZ1EFfl5Zm6rtUJgD2xx9m88QrrvItSyi3u0EijchTSxn7c98kO642b1kgIy
-hJMxpUsThJ85cbNRnvslh2inNivO+hl5tqES8q50ltauS8rK2l+GH5eC2QtVBoHE2qd6oXDm6Ozz
-HzxUcIAFxgU4HsiaJpgrWLCn1RnQKxAf0vqM70zqc0htUYZA+veg9UMRtaUCzpCuAf6a1WHp7c2a
-E4DCbtanQS7dhMvb622qu/FqtzUDqvA24SSj4sfZozIrfrx9BA4qfCHbLd9VjZEFO3Qy5jJpKsS1
-G4Bgxr9mu80kZYVuCmDDW/+zVAGqLP4ZWF5zzXAS8E8/A79sjPSMFlJXGeWFBwo/r1Qb5JWBgL0g
-//RiODUVz2eTuueIT+SmAnRYxg6wo423ek64Qw3a80GeeKdLcziNdjUxQDNsFiiUdFaVci1AVz6S
-b3S53t0A18KLfHdFWNmZyXqOwUu2hSmaPjHkoV0UMI6M//EqQC/5uUQtEw2cwJiJqWMEWLH1aoug
-LPucpa/vSGBkv6luVuYqJHDyhOoHyFA3a9iqdHtVEhPEE1knOkb5r8yNZ2HuGdWy2ZnJqgyb6fNO
-Vi3z/VSqsFDl0U01MBY7fvLkENsw7vpIeju8uQZGg60SQFMdKDlYcW24PN7Thi9f/v71+9MDjMNi
-IQBvnhJwg6ENBU6s2V0AS3NZ5WL6AuPlgD+zBR3IGBjJXFAXq8lMXx1hyvldicTipr5AO7wZV1OH
-nMbOCP1QExKwDodIEGn5jGAM2nWmlzjD9ArqhGDrk8Ut3IDxwwH6ZIKq5T+/BBzF7T4GRWHkQBrk
-wNfvYO0pfrd29z9viKHDjb0d8BsD5CnWXSHOx6vFzHQkbe1BaTJranWNWGQ2DsMJN/SUjNqKi6pa
-Ii0AvC5Gx8JxJuAYbkidSMFhTY+5LlEoxjzcZIiJHV2x5TXU5EAXMXqcScYQt77dqPaYLz2oF7GD
-oT6XHdiFqsMJnQHBqwTPIy7Gd7AQFOObWFS4DBh7Hf47DCJDRuVBz9heGlLbLJw4xrhVVOYldlaR
-Mrh1oGoVhmUfcWBAQaZh8Oij+f4wfDVqK49MN6rNH4IFCIN86gaPhBrsH0PE0hXmLCE9Jw1TDtkZ
-MLuLWaD6tMY6CPtpHRRvAzN8pHO59fuekyEUdhgnlXB1fVSD7QrdGdH0g+T+iHjBzyguIvb05tRp
-q88/Scx5JSZRml22H5B2tEqvWkg1Ax6Or5QT18iYbRCcbU2BAoKJWQfrjNOAB8hwWd0WZjwj8//l
-wZMZeC1j02U5XDCUht+2GOEQTGW1RIyJ/m47P/qrPlzzby/6EaYbjDRpI+OmYR3T/FZBfacILg0T
-EYG62aIxlfr1G1FRfBhoqdIV2vry6RxwEhGLbMRF/BpFODi02vX9nI19sVi60i/upiHH2vRzu7qL
-K4QwAcvaDKStSktrtmmuIvarhopIAH29rEloNmfyWU58MT/3h8FjVb47X7CUuRG38s7F3N5t/1H1
-m/LtDbBswtucn3bNh1HCRgzsItL2YWQxoTZyr03AcfwEzm74FLm3eeKSDnTEud3kXMvZEelE9Fwk
-hFNVxfq+tRJHMAm5ds2XEXMF4psZWYKExERtsUGTqfC9Ah5jsl0C36EeCISYH7S+CUuLvU5kwHBy
-Yq0XGDG29IbjY/F4yXcKL4xA6YYXAKVQLciORgFh09ZAGw9W0nBBFM0K/mMkOGhqTjQoWQiIdnZ3
-DmZySzwm2PZX4ym0N0vvrGG7wFtrNFLfNSM2JOsGLEWkzO2VWg8kuZOgC0IWqPNwNlSY9wvWbN+E
-e9X9/3jOqXG7ARDMsklSvyQCBp4G8ONx0jNz+CbFKJ0QcoyLh2gaUFAUuA4xj7sl6JqpUZhybiCb
-3VLj3IanzwOOPwk3LJN1qaBPORBn4wmaSqlL1QaH1QMVABSVRhRKyEd/xtbgbRrthTlqMqFzYxe8
-2KVYjQ3kM+qKwRNKkGpyaGijuEYYCaUmYIPpewA4Wi9BhTc2iTR4b2rNEci2jcEx6B3zcjQHk7cQ
-KV5XYcTps/V58ghxPSm+WnT08LjFgZexBrBJH/HFCrN4m/Axsb9oJOkh8D0wNQiVydwRG3eHs9fh
-phCjlg3EITT/LlaXlNRPPi9wMXxk+Hpga35AguVjIMrHEh8gcTGEzGfH59H0Biziqw65p14aIp+a
-PYzD9CcmPzpitgehbfPz5Dq2tIHtw4jUbOqW/EW1Q5rqJnR+C5zbDCxAfCBxUVuKm8n1U32inf+c
-RnUSGXREZr53ImGkXALN0ouwxYwn0Ipw0bKtHeigjVDFQwwCD/qXS26Otn1wtU/iAif1iGK1zrU9
-F1VneD2lMxu7inCtjjrcGpzZ0udlvI3Mf/XhyPslfsjxtsSU3twicByhKF8fomSKbl5yFj4wwnf/
-6LOfI8UcldWaNLM5UK1d3axT/qK+Mjp+U0buxQvQd1WN+C1UieHm/1G8yV1zau3J+kKb8seyl04d
-js30Abo5TxntKK1zDk/MennEG1FCwal4o6BgJye3z6t6ZhZwAq7w2asXWk/erOCUFXu7bJL1ITqo
-2WaT9RZDc5sxA6u7ITjjzH7PQvvXB6jSBO6ewVUCoIfArZJP71AIG4Pd3hK8DxJ2VsnAFBb2F4yA
-oBMVp/TLYdjnjkXw1JjtCnc/Qi1jLfq1iAxpxIbQ9SDinjqiXrAzoFh6c7QK6IS7FsnT/nzNVrFL
-xAED57HurfunjNqKfzhcK/uA4IWRQvr2jbwfPECI1KulyKaI5FKxigOQcTGskNpb8RG88AvM7cyV
-HgOiQbOemRlp3U9+XBLkr1RuZeRosI0/Wt+DUsW+NNmpbvOtTZnDGVmAOKMKzv02VSX+LNNiAOGM
-CnNIAKOEq37kl3oNgNl/7NatnoSIitxhQfn9Uy+lTVGSHwIM6VNSupNQdqtiop0Az7UHIYqb3S57
-L7YgbtvZUE+uyqVVNBmiw/AvsLwekEPb7+FpO764x1kSw2NcpEgdE9zmKNdwfFPdrOzzZmwxRAWG
-3TZDdvNhZs/EqRJhzVwV+HQh7CqLWRUgP1XLz+SGZH7UG0MBga+G+XyW//B3p799+wa8t/Jz57TU
-VGvSgHuwGGf++sL7T4O2PrczI+SA1eNnwgtRlQ6yPDcijAKDvD3LTUZszfwb4Yaab/2Bl+K0oajA
-213wsTn8ASclmI6RPysjb3LUhDrxa586UzwhzDH1XE4pf+V+peNIbjf3psC2TTbVvFer2hKyjjkT
-DdN26PYHn6ktNUVHrb7iWYGW35NMTrY6N5cvSjTrcqalUXrY09MSVygywmaaUG9bd8sinH1PmyEr
-xCvdpmnG+6Tk0dFCumrgLyk5lpOUfH+ceiTqE8GpWV8/bctnKFHnYztKUDqYyeurrd0nZPBRfxAG
-RlDW39Cd9fEQd4H/RjSHHqyfppKWKzgjwHNyCP/RKwa5LedN7q35sd1X86eDwF9o1VTj+cycUKhj
-X0y2oOBDX4nbevn10350D8I2hrcT36b9eIhV6U9Po09kV2YGb64DRtDf6BFS2iXQLxxzMzA5K8l2
-Hk28NAtEkzMzUYlqKE1VYz60VINQMLub9ZgS2N5uvj7EmEebpGHBFktnpwNjsoHMBHExmq+T5j4f
-4PFoVr3E98QWOCisjA1vIfAucWFz8XjYWOud1TzDN0mgUTBCma81tI4aOPFdC2CQzIPM2OEPRFzB
-GjgWYsiINowDTbJHhoh9FrG+v7CcvJkaOWZLkl0oloMPLe93GysJy1L4aVsS9DQetrbmNMhopKbS
-DzOmKgs6E7sDenJaFMHEd8oOSEmCjJp+Le4zjIkF7Zg/GUyEUQvM1RRMpjIWAcDDJ6jntpII1rDU
-fQULMCQwdfDiH1D1ZT8ojBRSoS9RvZxBHEqEgqC+1E1WDS+HKiSxqTCFH93SZuT4PCg7Lv7SRnMN
-TtU8JLNSYESOBn+xfzxqBNz6BAQFkQm8RQTkigphZDAcRQBbgSmBBOxF5LpvOFMRveWngnpjk2IY
-wAglYN1H35FflWUreYZTyesXhMRzXQrsXjAY0E8mThh330E0/HX85vpwU/612KYDwjK+fVqNTNm1
-zlh5HGc+sXjjqRWwEO/Xu53jl7b1MfPMOVonuIVk+0fTvmsw7JQzW/gq8VbgHfR4cxovdzcX1aaa
-jeHZV/w7bV1H/UEANVetGQR2s1qB3eBI26SFijutahs9bHKzHutBFnG+By0avAdiHw3a7OXcTAFY
-PMmD710Z5ExYkvqL+8BCi3hfVGddM6NhPog6qnSyd4G7gyT5Xnd35HF37m3klLbX9WGdWxXt2ZPz
-facEnUp9Zk19WXZl9LCe3C7HHmUQbB88X4J36BgOPJC8jp8Mn/zZNqjPK2PGiAHHwRk0Y9E0W1N3
-jrDD9EjYL32r6eomtKEia4U+l9X4SsvPq2sMLpnGsfYPUjt/2unPSKY2hJMiYvZ5KaiFge2ZzGua
-Y+KoQNiNpt3/M1w5dyHft148B7TLce6JP642tAYyR4aDPB3+ogVnDdBu8vX9+n4Mngu14XAAkp6X
-hN31l7/AzceMSeRvw0cA7rQqyiTAPrdu6jz6y19kF/WWBBOC6almfkc8uR6if5rLgTn3+8ma78iV
-SAY+W1WELXm72lyD1FIbhomSC1Xy7c99vHiGEkvcomDih/6Fy4wQDTW5Mb2eXNWI/5Ubkb6MYOkh
-LxxoJbyVjPSikNuGotJXjJO9MaUB1ItKWOu+Xlpmf1G1yOxiHP76zenLd2+efQdzemTq+qsjqpiO
-IXjfRjR1JnvReWZF2+WiXg2biZEdwb0QBjNwMS8i091OMPwAykUjG3hmuIovO3QOAXfpyOVgFCg8
-8GGuaXq3e6bBUiqQADtdClsrk1JBZXtcwRWmsiAYK5gUOa2aFMoycmkMNuhhk+0bLTnmyUH0IAhg
-IeBc8hKesE/3hjJqfZx3776oFZUX+2gmz+44rGhwbAfd9awdzVxQGXnfhTzryWY76iux6Cd1EOIF
-VMvwGdyDvt6ifRRF8byCEJSz1Ra2m3htwyGKfTTrplcm4atuqtEDlgmmnoe00qpG4CsldJyCsVXr
-If4B+heYxL79DDJWNUurGcRCQowjbMQzMaE4yhbVNjeS1OUS4M22MPjewY7He4DlPIC5YHR2ZOKx
-YXoE+Krms3hrwFjh7wP9mgSURwgnQ591+QM9BNdDeCaoZxI88eQkFTzRogSYApH5wCIF2+yhIvhu
-vmrnuR3/kOLp6l2ZQbi+xeLnhqtHHSrsMAKgZ3a9/SY73tcrejS7oTWemKNrWWmi93pGz2mdaBtu
-YsHXt8XZV7EZjiHo85n8i7ZxnuAzsNf27bmSrOvXQwotHfermnE7YPPYBfOvx5Gnu+gqB9bf5rZK
-OzbwSTOS2zr8SN07mMd0WFWdxP4G7ZyDk3GLjoTftOgxsYrkhrE46FAXDy+hGKGE/TXQXCQUrvg9
-WV4eJrCPA2lqwEX0a6GZsLbFElqDvRb53XurrA80ervmJGvzC/0YPbE9gZ/Ul9ETr8XJQvoMv22/
-4Q9LEon2w5dzobMRWwxJtVFGS3z/D3tvuuRGkq2J6Z/MoDGNzGQmk/5FIS8HAIkMMsnq230xharL
-y2J1pzWLLHHp6p5kNhoJRGaiE0CACCCXXu4D6FX0Ry+iV9CzyM/mfnyJAJJVd8ZmpLJuZiDC9+X4
-8bN8x6XkV1FSqd+lpDdq6RMMVCrYhse8EIzC4JSWt82tEKdSRdTCUxH7WF9dhJllOWJBGNgzYgix
-4LNSxbK+3Ry/0bhXNFYjQZFhUTmtAnx+GjAiOmgrJSBrWyoAYleQNen8rmcVC0d56iYxtkynadV6
-TB79SP3zZHyLnXga12NrFyE9d3KJXnpocrmwaBwZP0VVFFf6K3XJ1GQK1rGNw32o8QQoTy9n2Fet
-rnnqzS5nqL3kZCFWAG+uJYPxLLVhufiGJlx8LdCGyx/IaBtXgi/Oos8pFCleIVEsTel5c3l+prqi
-6UGMSHIfDsJebyCNclvW8zBaG+6uXNT11VZkJUT+7NXq057GoFiaHic1bsAqQRmGat1igAlqKEgM
-EcyhGY2IGP/pIBO8HszT+5nRtLCBIZKWoe2r7QYRyxB0Ij3UdWOMq/WyvAHrxSO0Cn4aSw4DNaRL
-yspIJRkPVXz7zqHd226OTlSw+6WhVDQ9vqenImAeB7QXBFDTmlmWOHjYYzxL0e7KS0KgWdTwePZU
-i5kUJzCzgoUneWqwL2Ga2sXteMLM+OCzFpvlmGSFS62NC50q5yz7VEwZYJhmG5dB6rpna+tws/jC
-5U9WA3IgtolT79OJ5Erw1lGyy3Bp3afLbvUKb2oT3xtHC2yBQN+xXVpa9ACF6wWbb6AsEOfZtOTT
-xw//ToOffzp9///87wTjLhjmFKeUbJMNq2Cx28kSa5DB6djPrO8VXyiyeVmuQhD3loe8bbW88rqs
-+oTrbn637L4ltU/kNzgKQLV7TofYah2gCxgcXRXJtFAfToo/6HqL3cIQUg+f37989/7dd8+PX738
-NgNLeXyJkta3H354jy+fqpevAcD/7Zu35vUzev3h3fNfv5R3X7ZaaHG5Lhz6noZ3+uPJ+PAvzw//
-0+j0483Dfwiwu2ug4RkS3nwFv+E2yGAmW5AVztYIAi4IKRCqfmO43KUyImeQ1y2qDpSMDPBBh21Q
-tSjo924nfwjGey9+9w7+jKbj9aSCp7+ah8u/i638QdAgGn6smGtAJV7btoYj2OPiwYDuQDXZ6r2S
-pUXRN3UB1EaYNeBWVTtP2g8fPsYRewj+xTqP5V5ditUdDJL5/XDEADNtOiYOes3I+xfFsjC7E3KL
-SgyWkTmfSA6Q0WRVHjj/SKPz38LgHR7CkkSEevCETiPy12Hv0wkNeP22kHaUAAH6MQFLjjekZaEo
-eIj+gwwN3cpwENocUTfR6MPFGPU4HQThHV+P18P2cruIq/W6YnpB82WIpI0xwCWpHj5pavz4HFwa
-qNWmxkwEKdB4wprNBeA41W5gQyd1Y5yuFmxFrCNGRgVglJt+djNew5SjRRTAtKUakFo1LOyBVeNE
-RvXxG7RTmGtkQ9wGlUH1iroDL8WsmRS2JlcJJl5kr4Del4tg8r3mrO6AJuwaQ6ptYyjOBmKbmFlb
-gXUfqC4sprC5rmZkk2HGaHIF8XvzmmFoHx6SaLnt6qXjsK3WIMWpCNrAImmUvU/Jz8WNetbFqBGH
-GIi3mPbypmmw1gxuoOWVWr9oaeE8AqRtmCg1GQBtpLGtOhBqcm4o3zUFgEPKODO7EpSdO9cWhrsm
-tb+qDr0wrKMyprkQYiV2x+PmVWjdoaTz8iLsel2XvZ5D5gxyl+uxWSPufKITeVaxUHu7xC7rIxCl
-sSsIdMGHn6zmYQYIrd1jU+wQ/umL42G5HtqnPkZ9G36HYcnY8334TjulC9gdlMVFD/nvXtFJhOUK
-fRcAwGxhVuHsDC5Kdy3rAIAmGjTQuSXhkbcOJ2B6iXwINgYi1InPu3VtmJYzFTjt3RVga5VLj80B
-Ju1iPV7Y2E+NeADidu68501CCX5Dgnz6UFgkYk8fFSmn7u/fFNZylCrv/vgDYbFPfQt9M5B2VKO8
-Fj8PJ/wDxIVKqK4WFTquoEnYBG0zur2To9OcYeN9M7YwAlcb2UZQpoCh3wOIGxUGsKyfG8d3hk3+
-bXF3Vo7X02OgzOvtKnDSMamgnUo09BLzmWqOsf27xv6Kyx/NpIIulznkv/v2QfHZQSd+hib7y89c
-Ew0POioknzS57+/Be7VcLgOh3oSLBuBFJVt7d1cZwvXydrZJXLHjtQG3MrhLDbLJeAvBkN6tzAFX
-bjFEGxf0hZV+okPg/M6XE9qV/7VZ+oM9t1QNtkbi7mqxNhLDZCi9hbNAvrti9hNI1FEvEXcvKoKY
-7biIwZ5TpG52taNytB/hSjhPtjzNX9gG/ywhnIcRer14xwnnT5J5TM6Hks7qSJUL0ucCzvpnwAac
-0xiYfbaZgcsocgLu2t4S3Aw0MoFBFpuBEuNvOyOTxIpxrFaaBCeysJQAFnacxz+Aw7L9MasDlfFL
-SVTHxaA1JRXhH8KKwY6E91bywwDi4g6oAcSpzBBHJjojQdBjoVZUnpPZo6PTkKIfL6fFbeL0UYV4
-UlH0Oqwf/ZEsDUQ/GM6Qn5KyhvLg2wFyGykks7kVrFLWBJLKnjyFA7VxOb29g0Oqp4xYejuf5P/p
-M2HIG28uleAHW0kZ0ZfROdCNKMb9OfXbfEPkBblGjezFA3HHVsmSvJ9m4lnMbOZmvp0WZtm42pwx
-Lhfca7kzgVMrGq0KtiDuvrRLa5NdEafeEBI22tIrTofT+mFd3t7V6rUI/SnhkkgYthV7BNNDowev
-qoENdrzQZ0GwNw4R5eBYVZG4aDmXp6nAOJ5iiEIYpN2E+6ZvGq4LhpZJfk7RVR3tpdSlrrU52fpx
-Ru27mID3D9pJi5yuCWb/Gbq1ueuqcUGNDbjSpvWGLoQniVDd2MgqkDKhkD5HTPfvq+YCCYAfaCQ6
-FnsslBKDHxBzumw0ir5UWInVkr4GI9YocDPe9igBrFQQArxG+euMESjcfXyzLgrSMNsrG+BHY2aT
-ARGB0dZ2XZgj6hghZ0DFbYjJAvgbdOCu8qZAs+QCBqAcS7my0szzDzlzAkO/g0E2zrbL2adtQUje
-hBeOjk1mWFFIeVlwuf4miILpcXkuvQwBxvqeFnlgrEBphlJ4WAahbNFOo8FvdqMH+GcsKddwDqpA
-PSFwGUc3evOX7OHOA128vTnKkytfUNB0BSjFRf6UyBIBg7l6bsZVZmF6ECKsht7Y9Y51QZTxiuKb
-BijNhIfE1sa6yQIgvALql97j+FIC2lsUBfTSx3OJ4/59jxANOMLe5m3TB6bxL3ALxInwPac5dgBn
-YTL5xCm/Y/PcREr5JClnybZ9N7MtOyYOIarRvG4HpgeTrTmgF7gh05R7gnGFNMkOyTSIPUyiL4Zp
-khXpliGU8mi8moHAtdt+mj8B0Sm7oOJ2eVDB6nSky3yOLiNtR8BGqzs53BFrFQBM8jzvKex66mWq
-GLU3kNYAKfS7JwR+Xt0D1R2cVNYq6KVEPLAAHf1gSDsYTJPXurXZpkOI6CwaLAHTju1sESQBz61t
-GFmyhs2qc1XggJyYp3UP812dLxsytKTgwM5C30eu7DaAwY6bqVvFFIfreJSBVS54Rsp+1XNRfLKn
-AYYoaIzJiSn6eGL1koPiq/29kZJZBM09lqNewSXqY7i+1HkhOfAXq5XcWSBf9ZFAnTPXyLrOWZAT
-8jK2pejsl+Pqsnadwsdu1zayr9ukoW/RXDxlr+qSiC15cyqET5n9pZgqvwvYBFS7xXdU8Ca38hkc
-wUbFLcZCl3eeSewWVbD+rnLZw1MErCE404x8lhJAwwqScl3ghafLmU6enPalgJMj9fz0tCGYgjQm
-vfD8ptu0TbsYSLOMWjchyXTtN0d0cZu4wTVK4dywep6wIvYMaELdwHMpvYbKq2TXwZyiasZzhbvd
-5FIAXpr9bYBRDfmzKtuuUC8DFQfIN2OUhzCGalliGSFv61lNYkNiFMUwcC5ZEZEkoW7pYVFpxEJV
-LN76AxaVcnLcoxj7FD/744cqmDoD51siWLGBM416z7ec1xesGsK+77XMh0mGLoojpheqjQPMpMdY
-PgK5DY4B/hQW5xfJT+EQy1DSV0XdVuvtsrDmLHYrkIS8liYiK8GbxPAyfjaw9LybFwmAdD2aLMkC
-DAWsPjiusYT2vFxetJuc7ikYh9+HSL5PoBQk27Fyb3I3kPDCuNOm480YBx5iJdBtzosQI7CIs803
-Xq+grWnc93SfN2eUBVwSTKvWm4RPAqeQBHtYWtkc/qDxzAfd7nKQqgoxI/rNPjJkNEbBKIeJ/riv
-uwvCecV/eb/opQTYlcHSknu9vYx3FRsEFNPd0p1HorDQfE03V7t1ub24zJz81RoxwGxfbmFOQTY6
-uwbYEjiBpuBMZ0UBVr6s20L2rlbJE1rCL9mqJVL5921UVlMHs/mGnIHyjm3SAvS3+oOiUmbytrdd
-wsEl1bocGnEYVLzvBneJtGk9yU1fl5tjMbgrpmzsOzZL2Wy8jb6j6RmsJSjUhxUgfwG10w3hrP5B
-Vaux4rBtbkZ6kVoOfacpLwo+k/cKc5SbRKIT7dVAeQV0L6B4vFl7AffYMI2onQSpEVglFGuJSQ/X
-wPEEUMgRcggN0ID/VAup26v3rfV51s7ICjPMbU1wRylIFW1mwQPu3f9giKNvsQykVx8BIxDTEqPI
-Fam5su98dYJOap/zyZbE8MNaQSncq1RelTlhF60rWfq1sIQbKwvsQHsphXBeUxZDGFrJ5XfvHI2z
-T72dIvF7ixGt9MoX4vOQmWPu9vY2Q8Mgcbge0SoEIcjq7pswmqBEZuDgR35AFORKalnGdTF3BZgf
-m5JFaXUTaNIMkuG4EV963kq8Ri90s2/nYLBTAn7gqp+1H2ugz63ZeV01/HSp7OV2xLXA1oUgiawx
-ksqIXRIEZhFgQWrJYBpdIdf7fa73VEOcjOSOgCifOBjoiP24HU0MF85PzSNorzlz6jIvaLAmVsNa
-L48X4m/Vu3iBGaOglo9ESgziwJABGENps0kWQlXjTQNOrYLc0VDwn4HTuGGT5AZKhkIo/13MwIDh
-zDyAQZ456JIlVj5DECo39SGIymlz6Wy4Wcgmpg0rR38sIxNL5PtJySTXfeRkkseFQrP96EUga3aN
-wRYfZ5+2Ziiyal7e+OPr0D7hSAt0XRzV3MP1HKmiMVO7n/317709QAtl82GuE+mMOdBPU/7+vy3u
-ajz9bUG7NpeqIgVvGrYiVlIGg96VJWFzgagGuBP74ulpZH+lZxt8ecKJ175u8s0qzNCpMOJjkUED
-xm+KgSrFr54B7LCUwsy5/YBXcm+zihlfTAJ4MysFfGQOFvBJ1ezCcEnA1GYzl83ZaAauoARYjQ5V
-HZYnVR0AFAHF0N2zWs1crF/Gs+Gd+I8E50IAgeofxgmjnWFwdAx9X19xYlbbowFihnQVhuekstoB
-DGAQM0ybN4mBpFOgWbOHyIeMgI6AaXEGBPgzB/kSwirHNuRa4M6OINbRQpshJHxFIihkYV7FijKJ
-B7jL4sMk8c09vDxxnRHwgA0qDT/8BtC7XJmOdcg3QeKMKWCQEnAmOqLN6yBucUqioWfrUWhp6ixw
-9UpxVh3i0RBxT5LRivK9er4eSoKEbCFaJWB0v1qhCTd6RDyYWleIejynqNJeyyFz+RAUyJ+m50KF
-jKlgI1omJ4pGFtieUPVsZcYWKEpk5ytihcOOi7PmKpZWq3nQaymw+nIhbZhBt2HFAtxOrShWtib1
-p74EvmFxWFAvISVLZf6qSFvKAf0EZygONeBoVT+FYAOETbWVLM6qYVBbZPzZUH1k3qmppA4Po++r
-taOt+j4Io9CmxXYaiZcnwINTdEQRgOS8etu0GjgCbSIH0c3Zcgo3I29vC8XckNd0IhS4XrrYvk0I
-XOCSUMSqsAhZKYlQScgfry/SIXGkPF5h4PRhEvnxEdONEI0A/mhMDAZm4ymn9PgpZz+Rpw4FK+WK
-VopFfvQyI4Sp6N+ZvteVUVs156M/Qw+upWayD/Vky8ll5ztGAzCDixIXR7rSacUzHahyd1nSxRcC
-jQAu1R2Ijh6se0iUpcRYyuUfmJE/AeJ2kjc/eQIQtBKWF7gNs/patlzyegIwOBwdsF6mvQPb55wt
-lQQQi8ob1J87dHuzUQx11BMop5e0AAioTI0k75zsjTZV4pQxbyPiAjM1GIQQo7RDEltEKA2pH/DM
-ZQ+2NgVCrclST2oaUd+d0kwfITUu93ezYj7NblO3K75ZxPkOJAij4coh3OIYIzzxTqTTryrTufj6
-Qe5a8zvUS1nxPhiOWd+JNA9jt5CQJVrDkW9Mwg9+n11dDxHQlNsdYtHhpUYdL1g7SDBfWukuFkA5
-cIDi3FxJJ1ddACs+CuaU7x8IVgAl9LP2bGmYytkUF+2Dtez5WJkgLBbWcG34sg2EaBmSsDm7HWS3
-XC9CcRz1+qnoekMRsuN1oJ+dnZN2yqwGQ2IDJql5xWJkn4B9a1q2iYBtAj1lh4yb3oDagpdhtHXq
-1rQmRtkMWxQtBhXaOuiQZ1HoMbCRrM/C+iuWOTE84Hqiz7qEnftQW2Jrvi/uk8Dox7xb4jwd2UEa
-eoLtAE1VVsfnjEgKyP3n6zH1LTgTNvrwDq7C0dDrtUYAGVB1rzYak39T33s1pAbf+r/WzkDKy8TN
-ijlMzJhcmx2D3tk8O7d+ZLLQA4Sp1QkHd8rHZxVFPsw7vVOwnGN8fm9Mkbsxg3rL4FqQOIxBwR7X
-hvvZMDDtGLBBYROM2QadygHBb5AXKIEhOKCIg6zz2VWRic95djObz1FXCzY4puYgr9lbE4QlAZC2
-KUuhKNN4stnC/YeKngEpR8RpCkQXSla3Zt1AixHwGkRwmxIk02aI4cBcg5whtGIOiuC+kld7pAcj
-+I+coXUwrkjyIuTZQu5mHqYYmoxQFkD2FoyE1aOEmh3xIEKklRqJbLIZaUsIMJSb1mudXHNt+J5w
-gLADJ09PQTkCnfjht78efXv89uWL92/e/iGFC+svZLObMFqb6XbvdB+QHM5v0kfhlc07fcuVYz/F
-ISgDMiuaYOjQzRYUGiSqQQojeM2IZ17czqpN5QtRiU0FwbPHYaQtWmh7pPhcFvkE5CFgWvhuyXVp
-UNuEukuuh1Yl1X5s2GDSS/Va9fpm4ra5HDN0Z1UgKJW4uo4K9/ax5kn13Xldt3GA8SzArZipi9Q+
-Vj26lNqsdbc2yPwoiwfbjB67p8WiMg9YO2Bo+lbcH/Mx+qbisrXjLPeSiWAhylbbNqe2VABlIUxP
-TNjb0cCMZE2Goh5+Dbh4Jrthe6nt977RY93D7ElKCC16lqDhJ4Oj02QMSM8Eef9p4EVs1TLl2vHz
-ybu4pGwl9OYeOoDcDrSOH9Sfci+hDEcDTcHgSi5TGIia5O4u9ceMqLPxWSLaDa/v45qA2ed1HU00
-xyKZwcV/P1Ru7n5dq5yKK0DomxZ7Sa7ilpD0Ki6gWXoVl7NDjnI5rkYMxpYEEPRuObsELaau2x2R
-RFOzoYUyaq2f3J723RJrQL/z+5CEviMb0PGEGI1vK7IJIOAh9Olrd3ttMkZA5aQ1JqxbaLpOdGdH
-FGEZHgppjh/cgEAV6QGxnXShqAKXnp9z6GoXZYNM01myS9Vad7LUUYmXvp+KpruSss2pWp+33+MO
-QKnWyo08xuOdQFdsDLC7897/39w+Pyc/1n1FpmHAC5lhKqFXv69TAsH7LLhPf/zwP2PoNQ6mO1lM
-ARjs0+h9/t8j9mOrpXEbGZZRfroovArYEa2J3BcJhoFhevvZD8c/vGS/Z6oKAvRoIwha+VsKgMNI
-toRLDXhlcMh2TA4McjTO4HoPIAtiLJ6zlTPyAFxB/pJylsvvSPUKL0lqiZcPhQfJoPBipuTEm3Sr
-NJVcowR1mXWK9bqjPKbZxlhOdswMTOEhdwAHRVWVCwgAOhS7weJLrI2TZKuUi7SE4HwsI0TQ2EQ4
-4Qp/YS17JGm3R803V9otosNjtWMVjQlvJP2s8+H9d4e/6vg2V9KyYZaKuWyWw2Uxnyfs2k37wMNk
-PB8tixsENE0kkmDNqmSzPlzUZv897UCJBQo8taxaM6gwHgC3YeEVYDB0hCxgw7/Kng3M4QQIdHfP
-QMJtRisLRrJPn5/CyNQrgXmMRzLIDPmUHP2D7M8Ee7cY3/Fpdl1oOcQelmI19dEA5vatoSM8i0Eg
-XO4kBWeVcUvkDusJI+FKORiMVZUDMEW7y7FwPJJzZSiTmjL8PAhM4YP926VU/Uz+4jKUVeEBIEDg
-LjaPCgsxRA83aK6t2BM2SrYylP2kq3QNtmZduR8LIESz51FgZCD/o6qIJtn+DLz8Mfad+dd/TdNk
-/vVf0yrAAXE9rTYNLsrBiA3A6ERpI1VP+rZBfdsGRt5F0u+TUnOjLgiGFzm1Dph1+acPzUmn5f0E
-DCe/RS27KYMPuW+SFlfQqclFnteQh1vAG7Pr78x+9v5uVeiFgw5bn/704X+As5RN4D6N34//1//u
-v3MRUFuuwex9N0WTX3qUul6bNqj9T9atlMSM+aet2VBBPKr4M9yu+S272oB7uPmdodFSJeAVksFJ
-5N5KOIgwe9JVxXNHoKIAJXgkLRqNOr0ai1lKneu03Ug4lCwcLNnMlkiUjdTCTk23LXpbkOfaQepl
-i22Flsdj24yUcTW3SvrvBreljCrjZBYMxQOpCYlK8SlliGZeo/DlU/yJoLyJ7sPdB0qIqjBtiLdz
-YKfsZ4I7SyrDzBkkLxRbo+8P2deh5IUyJjW0yssVenkyO00rfHU3Z3VCaSgsMfHvNuXqmPzKNAIJ
-jY0Zs4vN5egSghXsGiLVabdjwbZjCP827FPztYsL4WxeBPYKyNzLt0j4clsrgPdu154iSjVtDtaJ
-5t+mps3nn9c02Ia3e+rEPGWVbV6FMURh9vGhppFMNEcTjB8L/x6Y1Um6mC0y8yvAD2ZjTpCyKvQB
-LNj2D45niYBs0kssZNqqXsgkUzBX6GOlnUO+epUG4JmYXLU6HIxHREVDrJC7Xp2EDIdL9bx7i7AB
-d5GxUFpafb96msrHgIRd0+luQS6HPcPZ8BMuEv6hl8ppszURj1C9UsgNvvk3ag06zNkVq6dG8tUW
-Ps9hQXQ5XVMUcU7Z8w2McZ2ECWN/+V2rRBzkZehgGLsjNa4QZiRSQM31zgHULnNz/EuxNI9kgqhe
-1Owkun8XG3vzDnIZvkzb8bQsUiGwjfKsWvEv46qwfK1J4/2uaUOYx6V35f4awfTNmQmwpSaN97um
-XDp1vZS1LsHvwePWsZ0wTzCH7GYBdrPwjryRDJEBARC8s/EINs4oCvFXM7wkCqjznAHBXvxAV7un
-+S8wDivOanlj6uEvLiIW3UUJrMzz9I9GI2BgbSeqTqtFQB3guxJ5cfQVDmw/+75YlOs7Zli94g3n
-kLgfg0l691k/EwIJjHIGdnBwZuKVzTxk/xHfj4bwr0AZ0jITzw+BJgLVewa+lzemjQoMG4LLkv8t
-9XwE7ml09ya1pLJzKDfAoBieqm8FHwmgAw3eA0nPQOoVEEPzAe4/Z3+W0MuJC+48AQYE5cWhtKg0
-UKGap4h5NO/ULWtWYXu6t/Edy49CT83WGbH3O/NB83zMrtkC+JhuAi4nQJKRFMhYQx7DVQsQjlci
-JESI9PuU2RZ3s3ayTJyGe5YHeVLlwXJEk6Zzk+5iXp6J1f+8nFSJJYNJ0ic4+w7D9sCer8G2IDBE
-o+zDjFyLR/DTcEKhl5lKQYANgURnnnn+1rj+MFuyXVwgVu0YODg/URgHHW+v2w1oQBVGbgOfOBBG
-jzUKV9JdwCQTiw2nq2PUOLSSw/LM0QI1Iz3A2BIbQ00MUZ1tAoU/0o3upOT5oanR8R9NC+Cwxy2V
-QqLC1YAbEhYCwGmOwIHJHetMiEZyAwfQrcrRJSQ2RFKcICtBgtwPSwc5Dr080lnE7UX/R3r8jE2P
-m/feW54b/zNs+9kC9/1/+V1f51zbRAZ695Gg1pcHj1hk3GIOb/eQPFsSuLLAaSzMZXExpt1MahJw
-bXt2xUcmQosDy+eb/FSoiepkHU2XOuYt6jaoolBIADnoC9obY2o1COjH0vm49Is0r2uLpCy6SEit
-CQMu8A78VYWgqlXnwu89EPw6qbTHKd8kTZaAoAG4I1kLncCBquGNKddpr1nMI1bT6m5IAWc4JnXg
-HDTejFBNmAr/d5v2x2G+QHIm1H3gOk8o/VUYilh/w/75n1Vz/Nu0ymfmJDjrRkQI+eBxZ5382HeF
-IpNXs0B3BkzkcxQ8hZMnFh6d+xylY4QQxc81pymdjLU1iVu3V05w5srxWluILSBsAAzSU2/AZawb
-OeknWqsg8IATyGzWaz/bnKlJ2jnWrCiXYxBL6KhcIA4N9CYmjTocmZ0387urPY1tYdWqytWSNVkz
-RHsUim0Dnhr8d/3soH6WkAfmiKAjvvtQG2IptTHZWEK0sGo7AYk/AJ7dMWNQTFm96pa5srKqWqHN
-c2DcVHdAjUZUvEUuUTjbMEXTcuJNzi7zWxfZJAGmaOftocVd+3T24d9LBMR1MQHQ3E+T9//Hv6PQ
-jTZwtQtfxhBZFGJPQIULUYbUBWrEaIylH8aCYc1AiI/1dtcgJK8UFrjVJ/zItb/lwNrW5IdU0azn
-xvu4WV8Ma8tS9IfZn/4Epwzody/MnZYo3J/+NLBCk7HpCvfPGeOhup2z5LYgCjOOufHRInrJ+EBK
-TP2uKLLLzWY1ePzYzGGVU+yyvFxfPJ7PziCQ1WPJk19uFhJVA/xTHR4E2A5ww7gtsyJANamjIE/7
-v9SXFpoG3Uq6is6nhG0ElMu2h1/peLn2W4WRPBkQqcOK2o6Pqg9IYegkAqWElrmJWuAWYhuieERc
-DuBnijeM2V8KcMxXRVOtN2b9mBLCNdIVZW6iFMiSy8+eHzqlmDRHEOOEf+04BGm8T3QGWfDm71RQ
-8BZ5R8MNJpnCMC67AIn96U+QK+Ik//Qnjp41u7iAORxn33JlZi3wgPjLhUd/IRDkjLzqLYy5swA1
-0wKfRsXtaj6boKRNWGCvJEOrvHQddy3x3jfwwnMx9PQZrrAFUQm6nTuaF7TqsxsTtyEe2zwcN+93
-TXpOFodEW6MEN7kG0uGa7tuW3e1hNlYhThzQDcXLtj9PQrzAc1zsZrUyO/5gnU1nU7Femm4NiY+X
-NFgQ4C7qeXt3DfJptthgKjDlHLUWGgzm2Le0niKQ01kMhkfLMgpjTQaclNH0ip8C+wouDu/39Bhg
-j3EtMK386Cegyjna97KMP/In6XFI/2q63KtZIzW0QNVYbXzLcIn0zum7ew+lp0XzKpBdF8xejFCy
-/7TtgURFJi7z6ai5N2nby3QPEyG3iXGzN8+Uq/VXHOH0af6Pn9vIqEGB9VBQgjv1ederbzV0wc+t
-0zu5R7lyaMpDnsTgUmnSKIZ7zRMudfWZPCgNzLkzNvS1IBw76yYMnMVrKuE2W0mQmO5N7kYuhmoO
-Vfu4RKFzs969715P+hkQN+sXBK0lL228DrnmsgbE8lEEJLW+07v3oI6nO/A4rNJwyJI9Z9Y1kWw0
-4kdJOxrZ1E7Aii8CCmJbTUzciYLrFu4qQuz3iUy4nBJrtPVp+uF/kjvK1lAyePhUvP+//xe6pExn
-1QTMk+4o0hzHnivBIHB6yLx21paMbQZfRmQjuq4EweSDW8tqegZaTwTYXI+X1TmFyViM11fAraLC
-VFrHAYo5uyQfSVrNVyaiikwcqCXtYCfLltbzvY62IhqMdjvyrWMtIW3qSFLBqxl8Ts/K6R1gNJA9
-KQT/uDb7T7Lm780/L8YsUfLI5qyCRGBj4/YR3t2jvL2WD+BXF0XUofVzWquVHcS6Tl8Rj9sZKk7e
-rj+YD9IYDxl0OHG+AXx+emnFgwC+KEFMDaYIRGUu1u4E9QbiFX5UahB73or3N+PPc50UBKiXgx7Q
-ak7m1rFOv9byBmoDFCedeG2B93NfKQL/3YaB0nAGYz8WYLNIXympb0nuDx864DYeYgN7S77L+fsk
-9KGuR74QIpeyiTubclp2EtSYxwhKzxH/zFwIxxXgTrnsOWTu9eRnyq9EhkhCH/lrI4AxSIYnARlD
-cgg7JvmHFS6cTiIqCOartfqAr90Q7VYvTIE1pDb1dgdIqW8n5PjW5Pi3bqptmd1p0ejzrH7n63VG
-Tpbl47UmJ8Th1U0AsHboxfkxPXZxaEIYLn95++X0s0S2AEdbp+5UV7NVhKdN3YNPQQZ811Awr6i9
-yoSVv6M43U4YwxFJyjq1uIbURpXU1bXH2muqX/Ls14QgdbIVqAeBpcWsp2Suj4wxnk55iQlk5Pgm
-Rk0/MOcaBNQ1HOvGrKXZeK65UlifJrfhJ25A/ToFWYxJgWAQYNZSzMsbLVq/cYvaYk3alyDxdb86
-XoPqJcm7glmnCmm+jSRvScmXIi7ig08hpqMcU4XHfphqhm8l5/wp26/fvH85yI6XymDKWYS9lVgE
-HHu4Xevg1ja84Wo+viPQWwoZMfi4/Lhsp9vAuwoPljbrFec9dCiEng1Rx9ZLhK4mQ3+V3c1BP2sC
-zI10kzWFD3a3l4O/f1heLc1WqRu8hsFae+NqxonuJ2p9Ng/FfuHi0z21MaUSIzhIjcme8ds5sloM
-XN0ZuW12ctoTyYNdos74ecoBNHyyUkMtqD5FWcJlz0V+58Xc+CmF6lLfyXHgFYkcUpOxhD5MOHUr
-PTGQpG5iolb6GqhgSG9X6P+7exykA8N2e48+EFNYIYQvdqSuJ7dNa+xeXfmwLLgz70htWDMDfgeo
-iq3NyypH9OmB1P68JguuPdkA7/c+JyHD9jazVF1yQY5AvvaNSuXzeHlzPjXPDcFGJC6Hr4gXHDt0
-PsgDuwC6Mo9G7tLs8Us1cUZS4UFcyJPWP+triVmZKNNKhI3Hqz77UVOQdNDvuADyykyLPoeccmC5
-ClEThIwFQcZMubmjkl7KEGxQzAkxD0N9tg7SDE2qU17w9z4gukNQBjKx++y+dbj6HKu3N2q0IlIS
-EL/X20A+cmJLYe0rw153fAcipkEiJgfzPrNQObKRvM35zhvE0SsmV3aHjGYSc6kaYbMZCsC7/Ts7
-nInZpjrq0gjd69gaB34DspX+eZYAq6fJXm1MU383XkfmO2pEbQ31RjBu03uMakNYxnr3ElUr9KO5
-Ut5jlHKIkF5d297evu3sShFqOGXoevvzs8FyCCfIzY2UXR9JTc+Meq7lIBu0A5/Vsl6wPaJVTVQV
-F+LuG4A1WVEbPCfTj6Ibmq0lTILr2xB0jCEe9t1cU7Ouhhad3yy6aULm6bxb/lKuihwjU5yPCQIQ
-bmoomrBB0yqX3CdEMyKHnOn4LbfB+Ze4Irohheu79MwLmnYK43nUa306//DvEU4DUc3KxaJcfrp4
-v8kJSkNJqgMgDRV5D4asWDNZHE0xxsSoBF0vdIIihXdIh2L43s58tryCv9PZGv6gHWZtwI0Av5Pl
-K4zzpqMnmdIit/C6sHRaYTAvPiPbtNwkc3rBnlXMqxzlBBW43yAepbaMTIP5iv3m+iLMmwLRM+8J
-x62+KWhCPvS9EGlOPqP/0q9k02tHIaqfzNahd/crSA8Jgtcpv3OIEbZXYZTUz86oqvsVIIn9Isza
-p4Y1lSHCKVzduc3ilzQqgMCKWrGfXd0EbrAkP+bjFUyPCcI8QiVEXMUkdhcLaj1X0lpKnJDqpoT3
-e9i1K5TRk8GzU1gXHbPaOzUHurQ/idvVeKo2Nvvk2eA0fczv2YVIS5SQY9dApgYG4cmi28sSUPon
-RF6z8bU5r9B7A+YepSRZ1wtxbtbSHoYHgCPM8guI9Tq+QfcGaG/PvB2ZNTgpDZOdfZ0d1TJYXYQQ
-BGE8MUu97I88TU14bgn/673YubPS8PlUkakHf5Ei4CdV6+RnAqvy+s3L1+9B2ORevP/2+G0Nprjo
-wIgnTJx6tf2RnFc39c1GBwS8NyaCq99raBVkI24yc1B4dj+f1zhYAD+xgZ7vPccaA3fXt+jtGjnJ
-kvSA0v1g1jo47DrsCrHwqC7HgH5s+TaKeAbzFcAhZ5TVWXUIG2PGSR41VzKdXVumpAQX3JqjAcW3
-6GaJiXrWlHxbYBEQwpgKg4DRd8+uak7VwHLFnqEAwIq+EHAE1Qd4NRNzdletikm3I1k7PUHrdAdy
-JpEEu/LONwa3Jy4bhfc8hquusfzpM9rKOV1TpSjVUn7lN5RfJtq5Mjx+08jCd4o3iRUxzgw2eZ8W
-6+Jds/Vb3Xb93u+A/pLoRQL1BBqP6I5gg63bnXVnSwhBKxblwDXu1RdTmusC+RzalpuffoPNi/Sq
-UOG2mp3QlAeEhZfHrS2dkaj1+A42VjH1rbrBnR1gTi5m4MeOfbeuVDWhqlXXl8WNXfbDjhkj3Ltp
-M1tiLsdTseA0Z+aws+5EPRoT2OdanAjQp5LcNPFiBylkXuJtkbKr/wrM6p/1BumwEp0t3KE+dJLn
-PKaApqapM3wBU1JgBQQrGwwttDOdtQABh92FhylZ511yvp+rro+tLuOLsHtix+dHIEkPsPhCYEYH
-WkhjC6Aea2DD8OTpw5cWY/tZgMF1sSjBCMlmBQdDQG8cTy6x1GiK4OybBPwgoCnCUrUgRGYEOusP
-nWTQIE4sAQo+LjtNkB/+HMSFNolNqCU0qHsKSxITA2Y+KerTdV4GPYUkYHZytl2uZpOruYyrG5Se
-N5ph3846u9eX5c+IM2YHB1YGU605tLifnd9/DcJaEA2G2f5FGGcUvptVYpYUUptNycmiRcKv3YU0
-Cf3leM3j1797/qpLuWLZXpvjGmH1HEvH1D0GhEtHO0sQz0NdjT71NBV4HHIXY22VtOr337783QAj
-ZrDH6mRdVtXhtLieTQrYHYkgRpNydReVrPGyYIj1PReEagkYMHVEjBnpMvO1xXRO8FwkGQxI35Xr
-tlahEX4/n1IPvas11IufMT6GGWpEE7KyLKA+fCqiX5TXxR/NiQS4hfYU6ms2V9BTsVQSvjAzeQOL
-AYlUUCCPuojYBq2kI+/wiIxGMMqydfePUj2xqSj6B7pKdwXiE7FgsFXxrRijQWWqEvMiFWPuymtJ
-tD5ojUG/Id0BP/t9+kO5RQtRYElm53cu2rZchM30YfC0cmlGj+ZmDOz+IKZlyUAaXrSmPre6B82h
-FmcrwwZQrPEyHM7ESRBelK5uDE37q8g7s0F29Pck9yGXjC7HDLbSHrMY6yRSHBkoBFMkNkotMOFq
-HoMzKfKghESOzoror3rY4bI6asHRYuMPZrzH6/Fkk1h2D4WB4ELh1kaRdLxk3wTJgFPj8Oq2bC/D
-SVV8Og0y2JR01/aBBk++oBxhBomsC+lthmO7+ah7hH9c8S4/ZGDmEoE+2S93CxDKOgqGWdYASCzB
-m7Ag670JlGGcdR52IBnHWiY4OOA71BKEbGrYZ37DAOMYUOe5gcn2SWLdsHI5v8ss4vwF9G3jrYZG
-jvi71xh+olh3ZZF1A6W7lq1ylJQd1Prmcja5ZMgqyILGUPZWKJTQHVUlLU9k5jtcRSdv2nxKwWsD
-t1CwRBER9HZBbj5YD5gccqslWh1xMmiMxEUr8ZpJ6yLOkOXHPAqqphJhSGX78+TwCEMHMbpkEJRa
-ZXvk0jjbQAkD7hc33DPpU69m3SF4x73xIYD5WmJuCBswscNQBTez5bOnbRgskayCgqiDrqti2EuC
-3VCua0qTOEhLUxqaeXDtPS3ZD4l3KpOMeoMPDZV8ghCkLsPg1EdZ4GS6fp269VklCy5xW8l44DZI
-KXkrTYtqs+8+GutdBJyJ8NZe+7pm1g33IUHBxu523YNXUCGADVyit2/MoeEtWLUTpxEzwSKWWIEm
-fys8WfHcPgO/DkNAFnBdl65A9vRGjmNVUxAlqbR2Ys1ymGzXIR9ypuywSZvZxQFOgaNAWmRuudnk
-fW/yI3r+clreVA2rKlEu1PpUt4BI5tm4ikI6zKfkWDMlDIR0Mh4KLDIehyXXgp9zFNp3ZVv3skcB
-pm1awg5lPIlxNXGrwdiemrN+GUeRmKdnxjowc4rgnopXAumzaaSYuqY2FyX+DLAkNzNKBKhUjAKq
-SqakNfsOYjgdkpOgyBcAshbjvcAJLBtqFoR/Wc23lePw6S6WXvYi2hr62xdHH94oEIRL4NIDXQzC
-RwylFF8SYUvmJxfVMsKnwVJswsEeYWq1wTRn+zwsUgce6vyccLumReyBvJDSEivBIn8UBsI3zBqH
-PDTTBocSc1vrgq5BuqT0TPFQezpSFL/1szvgMf8izhC0ynrcdvkZe4LewvlbL7KB+lJzfdtKJVS3
-6PF0WquhUMO3LG40f0Pj1sEMHTD7tByr5Rv3kp/iG/n1SCtAVBMni9U+TQSIW9Zrdw/NFc2stUdH
-vbz53FCYwXySr4kfpOngn5+Dv4ZFClPUz1TfADNUdK9u3qEW1en5prbPdZ3QHci+8nvwmTQRG2/K
-cq13baR4zNREiMos8NMTfqJwqUOlncPYyyxUxeDLKXKKbm8VUk5oeEWOKZ5k37pYKTmFlWLApa8L
-l1V7NYLoWwxc2OtHoez0LcuyJCjmxdO+oAZB49ken+/4SBa67hJrGpAYxWIahAEFBJj9msqwKuY+
-ty7nlaHoBUyAb8fD8e4qOB0neHFMNTMIREphbKERS+VtQTpSrNN8okTTG7jUCrKLOREQrdo/EUxW
-uECrq1mVdc/upBl9nEmH7IsR2tkeLhybs3OYHZR54QRMxoCIPsYDZbq5ZMCrYrwGvtbc4ECsT/Wm
-QsgAmg1nyrNv6d1AQOV9vFCIzKUrxjdmpcFRjaQO/PVBsu+kpnMz8/M07bdqlt/BDjG3RTPVuDFk
-T8A+oB3QgxhYKUFvHLcbkuPwC0dScRGe+Re8GdQ5rcJHhOoig8hO8v5TEVY4Fr0HL2gzaP82Q8xV
-fPEGmi3yTTp918U5qNL5IIFSELJPzpxxRSSuVjUntG849AgWrWyejFp4lYZJqgNhxiwxaDJQo6ES
-jZjfdSHpsL64BL4GAFaUiPK8QiyCs8wslqMmlrVdk9pi2fUAhmvgm0jF06yyAeRUiA1DsDD+a6Yx
-Qx5L/6O3nYdmmAPcj9UG9x8FUiAZCKHaAbC89ZkAf24dKzBt+hm7IPKuJktQRIQAI9DohFfdSJ2O
-LU3P7b3NDY4p0/nBU4e6JyuSABL6xya6B2hbKxY3owSdZrPLJweeOyVslkl31eudRsFkojGOlcCk
-/4F2QDvTlkorHaavSzlqDHaIWK1a6ezSfe5yTfRjPsKld/LOdDGuM6xPyvgv0mkmL3a7DxqMkgMx
-vHCBePQPPeksc764ndMr2+XTxegxEZkxxErv4mrHO76hjofBxVAMTrS5bANB4ORAY0nUc0BZhf5S
-VNTqevlNyFlxi0Ha/SiTJtGj13qntAX1LNNAaztrA77jeLZany4//G+CazIWlC6zHRFU9tPs/f/1
-I9qlv6UXmU2SPX/3Hk4bge9agnoSdZiC2lRpjEi4OfGjSbQs5QdE79iUhkezLxYreVyM1+amOXfm
-8BawZbPeTjYKvkUewSmiaoVxJqPuiV3/dmNoLzhB/UiyJxSEVxmZJcJqRguNKnu4nN26b2ChmLcC
-Ca0WY4KkVnwAf3j+/jejF2++/+HNa1PmyOSGqPUUfG1ZsgWkQmDdnR6qx/gcdzmCv0zGqIihGduA
-Uc4doMODA4d5go+jETZXzjvT+X7Wvig2o834wrbzD+9fvns/ev/813DwLFY5f++CXKt9SJ/bGkdd
-sUaAn9Ne3a3uRtqOpu0DU8JZh4naLScDDmXcfx5fj9txNgqN2E4Bw3CKyUoluUaUltCuJ+5n+0F1
-+KAy/3D3wL4XCuxDCRgFB/5KNHBwnjO/+1hnq/XDH16MXv7+PRSTm07BME3aMCyj0bQ4216MRtjU
-rF22Me3758evMDEkVc2AH1hSq/X25Y9vj9+/HL1++eOr49cv3yU6cTIgbUL3aT/7JR1uKfulZ/3s
-qeXeLPgebWJzHflNWV5FlpwENptBTFiWfzMVqHjXk+XmTrw5lohWFYV18cQ4hKlHbnugtP27B/cx
-4lw2Ahr+Cos+XxrqRQwCfs/NNe98dgEr1jSo26aVMELr0zBgvGsWP3lIVlOOqKJM1unoSASH8IpL
-mp0zHQ76X1Uuxhm1wOmDKL5ORdFKsU8jHnn45CeU+M2q2XjZJFWpoJr7zgI6Lny+Jlsosx77mYLb
-BhmXF2/+8MhJRlex8wKdlR6CjA2+bXUZwZG5st5EOpo9lFRnwp+0uDqfUlwJuL8z1dKTKD3h0z9l
-il6Lr1w3f9zO82lz2KrzaRQVA3uxIln85OTpaVgkfKM+/PAHPACOX738Nmlj6NNxCrAxgoNuhNS+
-XcNznS95jKIc3fPlfdw9saDz5clArwxL0k0/vrD9ePfmw9sXL1MYiN9imHeAsDC0Zrwho6KZMiFt
-moWExR60SdSVqORYgXyQFjrIhdF6BRZ7z4w90Gqg2cpYbWkOS/Fyu6NiEFvcG5uD7Liilo4ZGdvQ
-mG/iO4TZv3BPnW1QCXC+DGbE8BsFwbGRuhBB7SZjc4PfzjMUlJ8VJL4hPgVPc6yWokuNl0FxDAxs
-WjW5m8yLPBU1MkmO67cWqeQtR080t9a/wg6fZTPNjwYPBY+CiQGFHVFxtTF7u9erLSPWlDQv27rt
-XGuWmTgwmi76zV3q3oAEBg2sZnAbBxn3lABn0909yN6jCQfCWltU+mxuTucqm8+uCr0GQdYip7Vh
-qXOKa6aEqgcoFVqUFXDVF+DU6xuFUOjbAdqdkgCJ4/ZIoVpOeCD8QJ8oveRxLCjlzmGdj+emaUhm
-/DSqNDm9UByLSngYJ2ji3QTLsMFYb0AAKm3GGGwUKqw8V8WZo1OE3cIjc/8smyy2Q9B0eAaW2Qxa
-mY2vy9m05e2sydVdBrMK5U7FCO4G7LtmZC2EdkvlfF7eoCR7eT1ez8bLzQAmUDdrjEvCVIXi4/nN
-+A7oCKD3zIsNuRXOptTnNysOUQo2RhBwjkdAT8GmXMxM0h/evDv+fafi3xmZmUKpBZKNS9PNuzwI
-UjckOmX4RgzFhC9HYDdvgx2RVzvcHeDaH5BWt9utY0hbXTbanlQFC9/jMDc1LK5AmmSrTZ7Yb97V
-nNZFhGBgGPec7popwAI4bflO9fL3x+/ep4nGQfZyhuJVmGTVRyXMHs9BcnLHlpVZN5So64WJik/E
-aAE5zWxj5u3MHDNXZl2c3aFGYnkIAw6aiTw7Xmb1hc3xBp8R8sxN0ZnPrXICyTbPKiyn1l4ulPYE
-x6FJ30PrBunN0nPjwUVt6OzSjAfQPTL2skPWR/o1v6spTA4/06k1E4S/zFYU6iaZRRZ1naNjMN3P
-X7x4+a4GFUMTcfR8QBM/23JFq8MtUHNS7Wpb7WnlQWfRqhMccVu3iJsMK/bslC+ScM1UaDyTcPPa
-7dVXpepj53W5mUnEDQpWea6nAkbl0B+VfnbcWWQXJWvNUPqqCgReYqzIH59OYgRt6Hq52kDkoTzP
-/SByI6gMlrAbb3AWnXgExqRMXhmCuRSyX8tbSI20bwgoCYrouwGPzDnq6qaO/7Auz8Znc9jY7+7M
-WXFLMer5yNh4Blp7XDoSlBQ9HQFtaGTPVRyusOE4ambCy96+HAyBV/OkebIl7Qztj6K+3J/AsjrF
-QIBYeUrn5Lu7xHdvxUByKXJ1FmBkgDgK1+9xdjOrLs2fSbmdT7M/byuKr4F3EqyIYxNOkdfuZ2db
-CAcI5MXQdXO50kFdgRqBZIL9D+Z3SJU5nOuz/OmjPt8HTPk3WN9ZgWcuFD8p17BDFKE7ADLvtSHX
-eMEBrJEMITR8WdzIAPkdjg5Tkyq33YHxBx/zKPaA7PX1Aphf6YUYNsCqht7liZJpTWDZel6J3OQc
-SDF3gRwpFyHzhZqiQYROFfW/VU8VZSlFWSgSlD0AsRl863U0RCDW3xeTyyXC3NwhXzfFm6lcz+iv
-aFR5+Rv2HhSq3Rc9Wgl9MLKfFC3LaYPYD3hK8I7GVUFRhXEtmV1kFgGPE9/w8uw35U2BwkW0lOoI
-zLvhbjfzgrHiMnACwo0NvOtxdmmWJEbQNdRT7pJjikoMNvNcRLzszWfh2Rd51oUQRmLhxeG71X40
-JZbXRU4zt8CahuAK1VUDmuP7LpMCb0W62KNIgdo3Z20PLvz4TcDPmUN6D04OjnRIuB+jckAnziXa
-SqI1yBJmGmwjxxmxf9BrT5RmhnyTMnE5qGMDzZToL6Y+M80Y39jj6lq7vfTtIg9GkgP9iXQeL3Jd
-RX9tCtKPmEN/ctVtfzVv92niVFJWreTT7WKF2+N8VRNhJgjw6kEIvH0NAu2P64/Ldo6hks3Bsd2c
-H/7KzDF9SnyQ0HKpc9YJo9+bId2U2vuUOKmH58uH2h2VFq65OJI02zpde0PngtouySWyvQ6W4cvl
-9WxdLmH9B+sxPJCB2ZUDQKJ1s7gcLqfA0TzNf8kiUDIKQtMkc5E3N1rTpWf5Ud+uKlD+rc1dOiN8
-SFY1scMsS8PMWg8VA4mu8ZVbvIrfvu5nr0F38zoejs26gBxjiGQAtfNW9gZEMSwaI/lVwaI6iOux
-XZHTi3A0ZmgFMiuvEVaPhQBhxTWij3DIZa2w1KEL7U+QGi/uMKSBFeWMEtsqGnlzJ4/hXuZCvFvx
-JGk3Z+zzTKHLtxfc+0g6AlIjy3YSl3HMhwuKPcHCOTunoHS41jfFfL5z3Lh/e48cez/zrmtiFR2P
-GG5CIBKKB8TtZl4/NOkf5kGAul36UJZ/ir51PYY7opmO+bYCH4sxoaOa0uHMIAQR3EviooXnMck6
-VHlrhneoSuL3WBC2ZGsoJGrBBTJgD7j/vYSK0TQXDgzY2c5NoZ+Ry4cIXGaVlch8C8MV0CVVGLsR
-o1SQBYITMttCHzYUVJFjG5YH1DjjXQ2iPXe3M0lHxBPDv49Ys4jGW4h/uppNuz7saarPXEoYu74S
-h2VJwMMj1JvvZSImdCWY9fADbZ07pt5OCmeayS525FmsVxR7570VL2JvtcHisrE6tV25mRQ/8F0j
-87HexXyE+ycgmyGnHXFDPiNk+drxZqwiqv8qspeqP33qroQHhJjD0SRJcmgewRHa0JUpKBKRV/WW
-PMBIgVoO2tMDLc2vTJ6opSeDL09FhaPYjDAp8xjbpeIyMPuXg1NANIEiiOvY3Ruk3MKSIPTB+arX
-4HgIixdNPfIXZnWAZ2EvZvjGQMUR/9GsPQiQqMULdS1xBHMXM0Q7ITyaDPeo45pa2Xlm3QI5inLF
-QCGWfgZKegCTzddbRACBykbV+BwwhTn8zKzM5UWNjUsOxi1i6GJh+g0ZWZIjv7m/jOLXvL/5AwB/
-mRu2+m7o3qwalWs/SGa7C5Sni1+QdKGXIv+DvxnpRZeEhiW9NteI1lrQHUSzXxfdcoWe/ABTXAH0
-zQoCy4Ad8chFueGQYGjOCynEOcScKhcFLnVTSq8XltNk4ghYnSwfXxdVtFHTOOKcKYx7PY3kQk5n
-BeGbzATlus9pnfLEHGhmgodxeujdyezUDUvwAzzSfBNHLqtWdy3LH5PpGYZxM6twuxyv7wxFALr6
-Vw6OvMlfm7IGAJ63AauDvn1/TDCC5tO/eu8/vNuewdtD/+3z6RTePjJvW39vtc5my3IV1fUvs82b
-NST7m8pqXv6+xLd/9N8+X2KR/0G9ffXucnaOjfrqK/X6rX399dfqtbRJvZLGq1ffg8W8efdQvft2
-dg2vHqtX383Lci3v9YfvS6zlwQNDQw+yopqMV+zxLkBGuB834u4PeV5+gizDoSrGzAO9/UK/fUWd
-9d68xFc61a+p794bTPW1TvWD4Vuhn7qjxxW8mnkTX/GSoIXmLQl8vfRbTW8JQQDnviUGQaCDp8hN
-htC74IuTcj4qz8+rQpkvvTNXE/TokDw6zDJY/G7XFUYGsSSXSN3sdlfhvHnalKCNYb+BYxlZeVmg
-GcevdYE9oSRXxb6luRx4yZEfntnw5HI2x4CDMKxwhIzwzQgKqLCTwTGJncc0yd63bJraAdI0AhK1
-amzOzHFGcz0t2JegN/ACEziUL9/Z4bsZcMLgCZo6QB+a9A89+QDKtBKwBXDUQii8QSQBJQckuOaU
-eZOxurkXLqkJcPETFbVYaIwJ+GFjrsWsCGNBEtz7xuegqhsvtSAYooXj5q5YdHS+3SA2thTpGmO4
-O4DtBUdVGET82VWyVv4LER6BZR+NDKv7z6u7kbxv95LQ5a6sdq0BcJuKwgAA43W7p3z4UWAxst0I
-zz9zf/Y8ne12eOJH9AR0SGaF4vkBjjWqCH3iwzADSBJvV2s0iYwVvn7ynHHUkZxv1iksA1OdBFTA
-xHmV0iK32Y7z2zev349YSIM72mSv05W+d2sDlA3TWQUy22lKapA3GLKksIBggB8N0fTONKCXHQYe
-6TXzlkBqnQvkbHKgyWzuO8N3sh7bjBL6dGVfZ0/CiwIPFqThbpubQdut95S9ml0sVLRPQOsNgGDN
-mf4faetg3J28c6jd3RNc9adC0IYxXRs+SWpzUZMJeZHI0q481QocXMInphkD839W3UAD9L2NYkta
-k9qWJvPYUlNO6IuO3+JTARnVKevBepHTBslEztHXQp8K+CZ5IKTctAo6Hao6ey7wbvYCRofNMBy6
-PZlc4F4suNeIeKtvfHRIIUuGA7cD/tZsMwxRCXblNNJ5Y3rTiRyRPTnoHPnnYq0NJmj16ntdLiM0
-UGGNqev7/O79jg7bFbRHdRXDx9CpTqvENLSXNp3oxqtBmpSktb6FJ/FdLIsztGdN9nRgUg6nJIam
-dchLtYVFuyXs+SZLNxOq7NWtXD1etB6VhzZYcZ3NUwC2v0a9Eax7SeRxHAfZB/S81ThaJKEBjxIO
-HTyFGIOmTnLZRLMz9CK+9Mg+W3zgaU5DICK+pcDT5tKGEeKRWABkq5CX77anvv5YmDdQDrtYVGaS
-LpY28Mgq8ED9NYhqH8L7hzAQYGSrB0BcnHTtYaw2x8dJs3hvQ71IrCGuLXsr0TkNUXR6vVNuUNSD
-RB6IyeuF8eI4gbUde4Ge8554BWS+iFFq124tsO9lMYfoqG3J2uYqXP2cQrsXPIxherEVY05sbX85
-Lruu3KwKHmvbec2t+YNg2T6z9TmHBTLocklgyNdmuPJ0bjXY0MwulEbHQxc7AlH2NGqx6jyzo2kD
-DxSXWY2eaMfZoeEhJH7odZ1TJPvvGN+dfXAjoAvsZw1rSMmwRoAPt0ivJrH1XZPb0/33ra7HFlad
-2MdTDOqzWkfYVw9QGufqBzFb1dbw3NWlSPgQF/c2HRIu3QDy2gn38uRKtnFDVg0RXq5STSAB3SgY
-Sh+5h6vzWR7rkLOJgro198Xl8hxdroo7yzWaG0LX/O4hM2MeYEcK0A+k66pbEfcJrF14VX5rHiF7
-xbtEcuKtAtBqel5mzvUvs+UbErziYPRFTARgN6qOXvKkoAT3X3HgNMVBm+5Nk6HOz6PJF8WyWM8m
-Iw2JErCmZuP/Bm2qPA7Ct9Vh0Saqi0xjPGLBsgPFIRDrYxkE1W67KPgMXHoI3BbkturHC8tRg1wO
-GpOwF8K+jIiDlXA1+GPki5r4Zb6oLmLFBtoHWbPjsbjb5sxxwU+CGJptkgqPEy79tO5E9tl5BnZb
-TkeGoZmBJ0S3jsNIZAzXHN3pyOWXEdR6CWqSKMmtzsTHFE3TRoG++7LoYM+2ywlC3ytuRGFjrkbW
-5L+vyb7lbXDFylxtPPg1c9EDCyKzFrnNMkvuBDNXRYtyYPvmNnRxIZWhdBwk74YksMQU6IDXwL3Y
-q+PzrhTbx/oxJq5WR+o+tnmwgJBoFZEdoGIB2n45foFMqmTK1qi6sI72MdmXUhQZXFhSLxxVrKgC
-m6bqoqfNxmJewAohUataww0UtxPOhAyNFGSGxjTkNOZnAohOzzn3yWn29TB7lsA/HXEdCOYEEQzD
-4uK7ZFO+MDdMpoUCxHzeUpwX4zXOV7k2yyhzGxZM1IqNGLotBPQojw5Wm2UQgGWrrd9wQsTxe2xO
-X3AwwaYOM3Xy2JR9NbXQSn9CE8jn8S7A4vXQfDe7RTFQttwuzsxU5p50stosnA+cKy1kMJSeAnJY
-op6LZEl+h5LzGIRHqgjPjNcu9lvAOYspAGMaizUKei+CdM6aSKBgrZxUerUT9Acz5m3MA+JiXPR1
-Cx9AtxoK4Qi8u0opV04stwRyZhVHmp/aEGYnVsVKT6E1eO2cTQH9D1TFJ9C1PjXu1CNpspyOz1/e
-rrpQIp/dckjjgFppsC04eUeuPfaDmx7N2r+YY+6NhOombboXxKgaXeNqr7sqIwOIeJg+U4LLHrhJ
-GN3kHjDrPbrk2dLMNY/2Qw1JJEU+GbYopok6kJcryvVGM5BymgErNowWs91T5pAb6TSJgw8FybA2
-QIzNVRKz7Au09zr3f2B7KgQgAwt+w0b2wSh7vTmczNaTLZI+0BEVxVRb47Pg8toXWvrNiXQVs4Qj
-LfR4tlwi55MQkjYw3ua0huO9r8oIzut6/shliali85jxwmSDCo/TufZT6TMneVHg9R3dFYgpDpQS
-c25SA6uguYzQeQdEJookmWaZsVLFNlCiHdMAWqUuBvCO3H9m2Ve8XOOJh6lD0K8qLWEf1cU35Iw1
-TB98jRfArgVWyw7SAtu5try7AW91f3XFyWCbt3asUC8NzpZiKlMcIG3Adj9TtAxHZ7sg86OAm21Y
-TV519TdXbxEzoWw6BObRISCzSKcAmtAkoaiscc0JPhk6C942oE0fqbsaE7ER7lH5Ee9VKQK/N91v
-9TqTTH1dSy99+5V2P8i6uhX9+AxEUQYfgWDTo+VMd4uzElpujX1O8Kmm7/PifMPyEHkMuk254aNq
-9eziUrLZ52Q+/Fp7Heo+qDL8Xw8tr20L+twNXfquEadBUf2RbqtC1jUj75nr+WNt2bE+UkQ10uA/
-BnHtzWli/k2MAKTP4ZviIdYXmDC410NRIOuN31L8tvg92IKDrlKSpMCd4TVLfHMoZbDPiYThewN9
-G7bNwaIHUdhtnySFP1ss4rsp11PbGv69X4s4cZ4Iae9GSBNhzmAzmu+pEzJqt0oPEt6h3NJ9ez9o
-P4x+PKIyL6lOeNl2tKP9sL5m6u0gPQq1FUsUwB3VJurlAtsPqq7sUrva+xmE7SMzVFuaGmRoV8hF
-uE0j66qvZrGvxtC+bRQlchVeGm8r7iVNtCfBFpT5rs8fl399AFXC09+x81J8P3NPIXVydMWVFwks
-7RWCZZYbD3U1NtCGBPlkc+tOzV496rYvAMaydXykrUTcThAtrCfYammC67ogtj+QlbRXyQvUT5qa
-FfKx3pzkNC3hWoWUNTPlOq1aW38kRGcB35f5ODC/IvTMxosAHk5Yes1ZC0WGRy0xS04kFFxs6VoF
-lNWZaGMxaKetDnrwPxW0MnehuPbmCgvDC5pXrZIMw5WjvhhPNtVUzgwm07crd42moc1RBoFPZJwN
-YaMqnzKF4vG7RfCGrdThpQz+aXghBQ4BNDojZrqg2bNNSGJveebwKZ45XUB084MmWFMBLim4LN0t
-PJYtzaxJH/Vh9w7RIheJ2x9tF+KvEuyV6kqcN6oicUHkbbUOhElukZtewB1Reny6lzhRX3vVajuZ
-nZ7anbwOWpLeV4k5CwxKJIS87zFwjv6JoA+SYPW5f6HiM827TIXOFu3+Ttsi6On77QrsYcyc+reh
-e2R2G/uzi2BXkM/MbT1BkkQfIrTo3Z19HUIX0umCLDzJ9nAJLFEx6zrXKNbHElxaDYG4r3qx7jrL
-YopPf/7wP5rlQr751fXyZvLp6v03/ycC+bbM70Oz/BdAPABAZgooiDp0OzqmvtuesWYj+7FcX82W
-Fy/KFcWKRk+9d9fLH19wMRgsWoLOASwWxUMw6TQCMAQrQ6RYcAqD3YF3FLOLxmsF2CuYvtszdoUk
-9ybpjTg0EZRSq3Vw+Pn/tQ6yF2OKYwEigGqDoRXQOB1cF4FUYnyGKb4/xOgMJk/3QitMTK8rCLFh
-Y+GIscLMG1SzIg5aBO0MPrjZYnMIVkI/rf1sao+IA7TGAKWExcVspIGAsPaXA3DnF5CBcVipsLem
-qy+X1i0qAcW9XSOXck0TaWhizFiYJCDPWAfA9iYTSsSu/de2GPPRPmuY2WqTiFUr1i4wN4B2+h/N
-0UFnR1fa0LfV9oOaerq7L9z4QXQFsM+G14RZZ9Y3QFmD5dikNDuimOpVQmsCKcwS8TRma7tyqhwD
-YBqeeDZFsD5TOfhnUsyzCXuMY8gMhFlSgAZ28bErAQTHCtxcubBh9vQJhsQBQV7FjgaERnCDdhAX
-6LBvmEzzE93OoTyMbySV7Anoi70mfsXFjwJt2t6pV9tN/RJKIOzCcmkA1vWCedollEaPDVZYTl66
-LY+5gr1xZ5V92IFIwI8Le0hJYYUlYOjwU3pJp9PGu8Ke+6v1zFCSNjj9QHtA7AlZdljCx0cOdW3o
-Nnc3tYlTcSvMIFhBCWT0E0kDKQVvDdtKZeGjJl7LpMqbYEI+Yz400ICdl7RZO9T3VTRDjxxtMDuq
-xmuDO0orD1VGi0UxBTCe7OVmvbyrnRrtQymt67uZb+1Oe3gU0jx53bKUiGi6JWbonnwAQQTMQbri
-AxOcs56/evXmx5ffjl785vlbQBdvj7LDxx8/Dv8h/9dHD9rZwXg6VUGIwUZ7WcAhDEYDiJqzQTDS
-Vn14Uho/v55H5uug7Vc++s2bd4CdHqTMOv886LBLsFk2pgfMhXTN3+HJKU+s57bLo0KQ7Z57v1mT
-IbrHNQP8EnORTxZTgAXptmGsDj9lh4dcnwKxvAYMkZm2NoRCOjkLk8xnBNI2L3qAzq6SFWvZPNfR
-vf2ae0neniNmzYGVkz6aRw4UgW/FbZjjOnjj/4VpD46/Cvwa5rfQMJ1/AEnYx4//0PHc9yCROGOD
-QQEwmKOzMZp9rSssA+NRlTcFvxt6k6d8sie4bTded0QumM+q8Xy5XXSDPQp87GzpO1BPyM9GVbkj
-j0YnivCVWjYKvekVdcqRCsPXXa6ueijI+rQFU7EK9FTjMzmyi1uzKcwZtjZbzrCuF9vZtMxu8m+E
-jdqUQN5mxPfwkmgPwM1X0NVh7iAd+j8BMoMKdHBZgibL5GcMavMky+pxx8NnPyBIyomFfzCdwT1b
-CQwPwE1hRZOSUH4rDwEiObtUf7xDe9nHMKRjMj+3PCgiHQn6dyDX4lDQ0nhoOyPaIHXrIQUb/bT/
-hMkzdxWJTd2li0NuY1U7vg9+Blw7ji/nDhl6F0kLorCY/fe4ozipC1h48xqeVcfbwm/ELxPE4Oau
-y7m1trqftSER8oNw5TB3OLzctXs7GeVUeGO4+xeV7WZ3tpzMt1P6cn1IplC9XaHCdM2X4+qylkeH
-j16ESNVoiGhJvMHDh1c3QbMnZEI5Bt8Hws2WO6kMBA5C9hxil193QEuwXYTRWWfL6WwyxigW6LMj
-fK9vG+uDOIsKSAqsqAVkOVduqV7aW4NBKzjELzebldn4sKVAGPgYTunHkOExwrEAmfUz/K3mgvc3
-5Y5KKLM7BR1BkX/LoohEe+Skeg2pK+6d25age6nXUXn2Z8DkIbC20QhUIrRsnAixpxMze3x1A1g0
-XZxmd63zU463SDolKfyUtPDcawWD2beD0/c6C+J0a4YCe/HsDlwGgujobSnFZvPKMEX4ONgd+dQB
-Wnd1E/GyHZ2fEwG97ZiiknnSFFV8zQRainY40darmybB1OqMRs9cNzgKZNdvkz9MoRx2E+eGluNo
-RpYzkByuzHDcmmfNxAMflbhXYfnmGyr9/B10dXPiRhfcYkxPKJXz5/AbxnNnGsdPvbqUhrjLIoIA
-YHpG/WoD/CyzHm1ERXDJkXoqEE+s4I8dx4qmpmFm6ksLskqg9rM/+2cRr2AOq2MeA0ILUgIXnADp
-msbzzrOsY0hhh4Kv0hniNRClX3C0juE0BO0HFiM0MkehChVLIUwpvGtAp4nHMswNxpReT4u1NMJb
-zLlPcO/KLWJJU5q7gJITjfZz3JNA/+zk+XOJ808lzY2EeR26b9B0Db0jn3nSeDt45t1mIoR57Yd7
-WYUWiq5Vck3HJGazyy5NB07V/mY2tD02GiPThDqmuS7ZbtvGoqmww6PTfWK5SpGo0+V8sRAC9Gac
-MF9jbEEgd0kLwVSsQTs3iePK/e507gE031TUyQAApeyv2eA0KVaRUfUOi7ogLG50a8+SeL7gINlZ
-YHTONHecjk5QCPPJqUISYWwUOjOT3tJg1am43+LTPjHWNxyvF+kiqRWuHeQ22yhj5JgU5+3iofsh
-elM++F0nbh9yKHP4IaFBww9+xPhlUdsZC/RDgVJtIS47bkLm52PHZncPAUYcb1VdqzhBgG1hznss
-xMaYRwu4cvudlHMBWoHlEMWnOBpwVlWdMBJFOt40266kLM4CnHo2QwKSuEFV4on5xTTMEkRtygaJ
-T3sRPfVuQuama1gVSKkNkfig99niFKXrRSoOn9OVCaMilSjeXDWdVDZ2xfbRlZcbDBxPQw5hMJf2
-rurHk0aLFdtwqSS5gzCp3yAboDtoCyq00DGfK6XAdH7V0kpdeRBw3WI7YkoVeHD2lxTKQ6b80SGJ
-DAACtwaDgmrR2vsygZjnUIirlZBCm6tFPQ3dfZmPR8RR1ZCdlWI1LRZxVZfjNYY9mK+yRbG5LKea
-jJEkUuyFFtN44wfCSkjT4rJZbjibTxfjW7Mcdc8OglVlUswW24VTc5HAAfqFJVRZV5Mq3KL8xQkl
-Dqhd1y6A9LV779BvUP8pSoQRR6xGxTsNkGqhK9A0sItbCtLkJIUAW2i+cB54J8G1HgGz3kmXLH1r
-GgeldT60YwFNV6INr7skJ4rERwdscpagGVaMxC136Q9AIwheL4Yaz0vDKd+M51fg/wdcidU6HkLj
-5LCa2XCVBw6a6CgYQSuaP/CpqTeu2DdvufR6caYV1AnSFooVmUgwtoEkIQ4PRtsLymFVQJehfvtZ
-IPnP8XUv0WSnVDuoU0ge+LyEraNNoUfgYJkWm2K9QAfD4kZmO/Nmmwye8KCpXV0kyERHv2JdiRRT
-fqudSignkVI2iXUakgwcR6YbV7AKmAnvpAJxre5yxEPPm6NnevvuplxfVVrvinvG+7hvu12D4yj0
-yVZioOXaZqYg0FKMoxf+QPcCiPHPN+hQWuen98drIcUn+6lt/CmNSq8FPP4hGsBovFqP8FQk5azs
-yplVoq/DO1PqnhSLxNxuxHp4w0klLWchsHY1wdWnxWybYT4Z6Rt11UB6dTPNfn/wh8MHi8MH0/cP
-fjN48P3gwbu2r1qDbIsrzOTKs0YoPxheBbw5ESoEYT2cVmKcwVtDKkgFCzzxebHBiN/khWhIm5mY
-d9dLsekSI2xzVs7Hf5nN7zy4U9+Wh1jQq+KOrNYUGZmheNZLfNK95bMEydYtyiQ562mAP6Aos75b
-QIjmTbGwRQKsyiBiH7nyVGLNt1PypMGHx4ji6hVm1CtE9bSKK2ML7DrWlXb9LfpMF8JIhIrxlGKW
-i+m8ejF6/urV8EXW0WvFXN5BdY9xYwz7B5q+7fIKeSOOu1CV8+vC3SKBKTDsqGhG4NWnbUl+rVVl
-Vkjr+NWrl79+/spq/TsPs79lH7PH2SD7Kvs6+yb7uMk+LrOPt0/O4J9J9nHdEQFOZnaa6VRZwc0D
-ZtwrjDrlvTKM2KK8LrqUo9c6fvfj8etv3/wowcy1zQAPTcuwVhcj1POOprPqCs1hconkse780Vy1
-Dv9y+nHw8WPvm5M/Dk4fgQbbJDnuaX01Hv+oXuK5mM+LizFwTF4DT1iKUa2EddC8lOmrbbFSXFNR
-0rfOoBPB0wd9yCkMbrXapQLt4ERKMDzGwcO4oHPQzA16XBUB/JKmtFr5OnV4TejJLJzN0V4FY0Gp
-bNyLXQ2ScXP4dQ8wOzS0Axpa+ABRR5h0by5Hm3J0Xtnx72fj6XS8GcIpyd2Ppqh5CjA/LmX8CozX
-Fz6Vx6ydB9U/P6iwTdWqb9NKEA8pKJHrNy+ffyv5PFJdrahbZldRhOxwVVE/ud1Rx/HcpQJhExZk
-bQL2GqbA+ewsx7cNK43kP8Oa5UR1KbGrNIYenInHx49g4/HYX6ZYRn6xLrer7lGwLm1JnccPKh5T
-P32i8N2G19hdbvYJmFb7ZfYGHvxMHNZbWqXLScVoaUjIErfUInKddguJ3sWLKVmbt5Q4p7eckJMb
-PH7sF95TlgnPt2bxkD5UHftMB8zeQ4ESaDY1mjnaJTgL7YYTflsVrOyEgK+g1Ja4n1AobtE+Rckw
-W312XehN6+x5uRAwTOHH8LinsnFb0GOAH2WrBPhy+8NPpJpB4BPyS0lNxleFubmVGIQhYma3GnlS
-WurWbZvsntodLZQzrZ06ToHa3phljRDsSlECdohQUSQ/FMF05/BQGjNsG+YTl8I2jBqL6xRa01SO
-tNCVQ3mCgkRCq8a9qdRleQhJDjF1J12Smo7mopaHKmkn4p464oS5BhCcfa28v+KdYtff8EGV5Xn+
-tbP3loXeA7vI29HZnNaCx0l8rB52P04f9fDvu0e9rJs/hAPWbUfPqaHBWmgVmwQZHu28IIRyDFX0
-2JfclWiPeUPOFGaDr2aFkkkfbxANnKVyWTVbzOaA2cQBrLbLCYUDN+cwh/PF49FPp6Sh2AerxIWa
-J/MZ4A56ZuRkukSsmq8DALOMCfjZ3EygsiEZISHNCCy1SRMQmnSYvN46Us6hVKIhQ/MEhAp9dBIs
-YBMnKXwNXhmU3ldGT5g6c1nIoXupZjU2jqBVoUx7HG3uv5QZ5H4mb9xUdnmTgQlxGW0H2HbVdkoa
-6ydnKuvR10ib4cwJrNmZ2TBn03F2O0Dt0q2rthdYorERGXyy99zrdEm3JDYwmxNpy/BJj3QVXnki
-DfON2RqUalqeoAZnCHYMiGyNGQzlth87ERptjYne7NwWQnV3RiaVZE/fNtnHRondY1P6EcluUaAM
-jwdsVtiVNyxs9qyaYtxKW1ZfB9sdgR6VZiWNKwY5Wp9navjjCwTh9+bmMzUFVj4JQUd5Zm0sJ0tY
-Z5OruYTNI6BGnF1BWKvTd9ipppimULBS8VwvE3OtRPHitSXGnlYK/+OLQ4xB4CsN6yecy5NtyhXL
-JHsLHIww6088dNvrPlgTjIFnPZkdZH03r3sfoqJAVhtbZQXOCkhGDWslOIDEitZ75WjjAz09kC8P
-uDddPXw3XXZrqo9a0fCwYQUs/sEQqxZ4Gi66iinTMBs0VGEHezVbBVqB9ZMCW7UxaF+o4IaNddKB
-o5a4fZPoNGw4OcTLBoKV1fPCoKDO2JUoMQl8QIy55beEC/RK9daKNhwHf5rz2S37LhJCYJGdGdJs
-6DOogwiLH4nnDRxbKKtU7vQcL0RJvQB6JGsTQzdvCEqeFDEDlvIQ5WDfv3z37vmvX76LDVcuy/mU
-WJSCgiTmSSke2gTYNCfmO9gBdl7EBZLXXMIFJKSfeNELAwCq7QAtS1uWxA2BtPcwTYFA6EEhrVjm
-ntRkBY5fqVDaYRhHirhdgAw/BxuKdWySRalyEr7DleC83C6nnV54ofa5nkAvQCQltsrShbdfPn1i
-/vunQfsnlw2+Dl67UXFPWhBpeSpWTZxHoJbvmffm6BemK08H+2ZocygMMnq3kcVlJHq7hwIjmSeG
-wkUU10aiW20DcTNDcWXCSw9OSfoMtwwy//jw9pV/IhIBEiLeofSGazoxZZ0qGopcd6kdQflmYfie
-kNajHITTU8hl4EsweD1AmzJ37zUjhp9ip83kiaXU6dpX2df0wrnCBlPhaoQV1uyNVRsgJXBuQ5uu
-zlH+LGX6DM0EFzqUNLUbpGWz8/pyG4p9MAUWI3RGTFMnfax2DtcdxpgnI7JUImRQalbJpOzQKa8W
-yHYFwWt5ecCi6KB8rVFGBQuF8unr9R0dqnbNWr+PrIvzevh1BkX3/BVkuANcQdA5bMBpBHNUJwiB
-rBaeKpKEtGuHYQsW5pBZDQOilVvoHrQ1wuB4xbBz0wm6TsjmYpGEHDPtEIyefVfBKNxMEvvVscxU
-nVeRFzWFTCt22vUBV2HpFtnlsQBC+OtmQ6nA1k2x9NyChxxjBOUQyt5NXU2W4Ldn0kccLACdOAMx
-31zEyt8wNAMSHbCxN9fVwEWCEuha4hgU9dnx8+LKt1aIruaorMcK9IiTg1Ri7CkpOfmPiYM8BH5M
-LPDp1Mq6Z3cZezWYe6UProYrxWwE0wOwphdL+nHkB4XmIDS9uAk7oQ/V0voMAP001HBimgF78Azc
-uNzawFlNGmSuZIaQp3zoc74wRzy+sehIvjDxK6ZD0sbEVGyVj6fTCPOWLm6+hweSMnQnAjuYfvYk
-jWO2qlkSds2tEguucTGteE+22/qd32zbZCcevxLbn/Q+Zd7iP6Q3LK8atMjFjoeWso1WsnrCokUe
-nybustXBxJ1es/kthqWaTlN3ePBaLyHK2PxcxKwxb4I1mZQdRS1YnSuHzWR41Kc1OzyKCByk5J0C
-LIFezIaHK3JwQZx0KMasWfv+4rxYlmB4CTdWQ2QBEAR/zm/GdxXZhXflGlae+zzK0qSd38GZhu78
-xWK83MwmNdbMLDAyLemjBAFudBTKGpsPR5IKhNtOqwyCTRQctnSVRJvpKUA+8IB3x8u7henkN4Y6
-/3lbSZU+9fRklziRolHvNQF8nM/HCbYOJypQF0JCpYzAJJ1eaiVQvWZHP8RMmkU1rAMvic0Y8FPC
-PQSsBVI4ELpjiiAoVxpdAPMJvpmz5u+TozzV1PMW59Jh/idbQimctahqULZPi3BN8Cjdp2Vm/q5S
-+7DCuHjwFaK2TuZbWGY9CaC2LiqzSU1NHru1dSbbliGCEjq9yD2IF2kE0nGQGTKNoByAGkIWmHQz
-KiRc+w6R/HYJXh9LyoxWFGZ0sB+sSNHSz+2yrv/bJY2A2K3OMbgGFbSz01Rsutsmg+chaTIMOr2f
-YxRsQPuuqePky4F3V5sX4+V2lZaaEjlc3mHvKrqe1c4yAV9Vl2iHdwaW67fAnaAQen73xRdf1AuO
-6HZGQ94LhCAhb1Ypa3bA6ttWcs3Ey0E1fEJU/gn6OYG6cF55PJpiZQ0zjHFacQW/w8JEJm1lw7EB
-/oH4FpoZOivLK0PepodnZhjRzxDfXG4W8wPw359cHj47rEyBh1/mz/IjVYb+7+nTJ0f0cPRPT+Xl
-n7eLjGJj+EPc8j1sqYe79FEwNXxMmOnACywPXi9rN2vB2uXS1oO3rSq7K7Tfc3zsHxzlTwWUphq4
-VoK07vCQDspD+za0gVWJO/59fRLyJRMvTQqGb0J1eodipxUs2mlZYAx7vFkCKQNHlMqZXvBfFeGX
-yVRi/A+iTqR67IkuaOEGYgt6ifm3TV1UCVWx0RYzZwIkoUnPDq/NkXC7mGdoFkDNywSZEy0OkmuC
-6+oT72G745/rKcKHqqHPEm4m2v2fv8W4lMpyw60YZj++eOdITy8HwkiSZaCwpLZpRIfUZf3++1f3
-Kk68BmwZ+g5/fq6kKglRm/XNg6ThvZ0MDi7GoIh03gsgF+vypTJ0CWfLBXRhgspqGNaUwI6lb7CL
-YqGdFi61D9eZlV71ms9X6JUVNzWJQtFwpBFEBR3SYIDADZBtLMwVwMxmKjxUV4YL8YEXEP2OIo/3
-0gAZqvHYcGyPZ0cDCKb+oGEaKBMGE7kFsN7FF9590RAvThQoKEUICgz5eBpmZOzhrq2GO+AHx4l2
-GUAmu5b1Xf0hLtAC7XTYZodNHW3G2D/crIvFPlAYZiBWZjQxvNcDdC8Dvo4MgyxdZ4fb3eYe7eJ2
-ZU5rw7hIfE1AKcbBiLCGryWCLIRvW5C5Y9VNQS3LUu5CrCVYxZITu55yPDaZaLGOYMhoSYV2TvnD
-F/h+UzjHrYwsn3K2nf72zfvnr1711LUHMjCJWFQXw06H78TR/QdrRCmBoMuhv50+RzlVlWADZ9nF
-FkMygbYS77WWL5yCXPasgMAiGYS5/OaLb1oBtefaDxcAF92W28vhvLwgk9XqImW8149uERHHAOU/
-MhVkh687rb3Jf3SYguoOTV3QMADVvZHu7rfFXeI4Q/7VZ/rjXUJNcRPPm8WkTYpPYFEtnLWt729b
-eQ7AfcHaT8mN4Brjed8CeScni3KZclfEekJzJZAKQcCdbsP4gfhvSqKkDlYQyIVELpaIr6FoJnev
-I10DWQC4VNGVdtWzyv1GRe/USSf295y+iIaqfoRUqALX7gvb7tTuR2wLcOWFW6IZvvFsDntoWdwA
-wfDbadZifTvNx2JT/LSmmjJ+pqZa32++odUdvQtDLvGOex54g8OCtG/IMypvHePNAHgJsnNGAbXi
-c6xjlRRrGHvCeUax1hbxGPCLKSyQhSauHIkRQlbh8G1auAkWKSNLMtFlHdpkx2EPGPFEdUFdcuAD
-UAb79Hxc1qQ5uRXpg/Pwwm8nR4PT01QXPNc1ajed8FqOde2iHacnFxI4kxSwjlxeCGNlV+MsmMwp
-eEK1lDgzElenpohYJ08QiLV7c5Qc7ZqcncYz+r8NiLv/H+HuHkBKqDfyV4824A00m7A4cFk0LL76
-7Du0qDZdg8Y0RGyp1TP+V4rdssccOMWV6vzPMLRocWXdcMgA+qhmVJcZuPHCWbmdbECfS/z1NUK5
-Xs9A06IcgJLmqFIHqZksD5oLu9KLLRnOyz3M9Pga5dE+yNqpcwbfQ3azn3GaiDJzZ1T1A6uWceJ9
-cw+rkKu3S2u2H+tTTTVgVKoVbW4AKucswQbziXU5b//ctfvWW+4i9e53r7Oj/Bn6jfAclWDlOwWD
-PhDUmJs8Bbefwj2mS3gd5vIEd9+gPF6GT74ArU9pRvbMpEP/4352tsXoAWbdb8EpuZTKZlJtUBaw
-TtiIPM8jeynKYdkMME/qpAzj3MITm0RlfTjOrHrSKhw6+5vJ6TGnOnope372q7ceQV1JG/T3BZrt
-rc0iGZ8BMjOH5oHIKabF5U2FexmmgPyCYIDQPMxcfyMbhj3BvbVnDexxJGxfhJTt/kuwXTe8g3b2
-qPGMbIO89Yuh+LLYVvWDNkWBe/27MvtItKKLrHnnFJAM+UFtNjwHGxFW5XrTKNqsik/bYjlBCCWg
-JJXCkuRCKSKHwPDPwBYagneAqI/0/iL9c7E/qFkgxsGryTL0C5tclrNJUX+IKf8O0xe8o4beuTOw
-VGRvtO9efw+XfrMnzOteIF3ZLtFyR+x1DGsDbcLD5BVMwQ8KMsWDBzETD5RdeTqHZiaQ06IcwqIE
-4aFSLNDFyZNLwi3CHbyzyFVDJpIq78WigP1P3VhIiN1BfLysizbLZhBNe8wf8zplFYQLQtAJI6sB
-s7bwlorJaK3Fpji4Juw6NddR4a3Idm/dqT3+IS3IFoFGW76KLBchb9Jozpbv4OQC071d4K9pDxqd
-C9InMYh80U4NFFECbyRlE4fOLhozJAn1I2ABMfuLUQ+FZu2PIWTBtKT6BpCbbkAw+6Hdde8+4EL/
-WXilJJvU6X0xrGVO6trrFX6/8/gzaooZnj3BmMg45cLpuTA668aZmI/M1gYjL9PcM3MviQwEk2qe
-V+XFS45Fw8g6AUhby9YkQdDwB8Pps/DdqcmsU+9sbXVj3DbJ7wVoCvOS1TKgsnA3AgEXFJBos+lq
-SeimDCME1sEsa5n64i02I1PmYD08YDB0mWEMKzzg1jwMhpeYrbR7gQzGMPMGBq2ugRq30ZCdDevp
-u5cbBmKYqSGpyVko43pSG0rFQ0nJyHVU5DBLuZOYr+UKw7W2GwVANhkoHasB8zm2Uru+vPgvMD2c
-TyYL+3F4jb1QVZJHlSng2vewUuc7ggKdGbYQeBLL6rtZM+cg11Xj8ebKgmN32eerQV8uDeRotYJj
-5VlXNehRjXFK+r8OWU9dsB2BaOIzC1lwr9Jk5Pt6OPu2s/37FVbjG0fKJd3je/Rij0ZmiegXyHLA
-UMN82XCH+Q94qIODYZJw0owNdYbjH17WpjWzumfay2I+JzgQ+12xQP46GVLDQfa3MAwniB67YWJS
-/lgP5U2JUSptQXdoVs2EzbDkJfDO2ifT8K2zabnov7w1Y4anIlwNMPqjmY9uo69hAcclF5CjE+M7
-spmg6iN7E1fHLmykJasFhDbv0MsT/3thQ5kZmrsxZyedR2g2jIfACwDCzBEO87Xh3xKwCFJIvjTf
-39+tEBbbvnz56uX3hiUZvX7z7cskorlSNMvJ0JXcvZ0C7P+vAOTuG8omYLn9O4rGYQZ0XOKaxYyH
-CgR4AQlL3e2I5L/T76BJNWitzfCdz2cT0AR2tks+pOGH2Cl14m3cIZUeJgNl0MgVDIWgiSs+ouHT
-yAYMThU1W4IYA4qDHIBLuZhVqGuG32zP3iGEhSt6YrX7NHa57bXq0IkE8UJMkvD+4n7g4bVOAY7k
-AcjHXoFGqWwgDfgQo2YgjaGHVjq0AaaU2QsvMho2gvTOJ9qedjyfKzcqlFUQ1xaohaYuPOt96he8
-fAaCo+AxVzcn8PI0pgpQrNzKL6Km92ock08gCwhpjjy392l+VdyFvlCmg4EeI4d3sQPLXPCpQYBB
-osdqAmpZw+yy1BFYngKiXJPLxFNzjx0DU3tWbG4Kc4RahCpxuDxgbMtLc1m5hpiocKVGKRoFlENt
-L5Uxo+yiR4aaUES67GwEN7sgR8IzUtSZ71UJMXYMSV2XgNo/6DqLHGu9FyAPPQL7m78d9vDp3SP8
-mz/6xvz969P+3wWISBaLMvQzu3XcR6O+z9ouke5GaJG1ZwbbbajE8DyddGyQpIFj0CJpjLTDTTMT
-HNp70Dr/fATzLDMH0AKtoR6k7L4gsQiP4yUaxQPE6ePYncwDwcRTZAe0QojcR1DxDsc4fD4Z/OqU
-NNonvwqCXxzw/W1SzrcL37R+8qQ/OepPnvYnz/qTL/uTX/Rv/7E/+SXw9VCDXwxEfnrYEU17aNMP
-PCI1H7O2+xi6rUs+KwidU23kJTwHwmkAh3wCZXe++f1xQnx8vuSO8sDTOjqqEy6YskBg/01NLA5L
-k93KIN3aublqjM+q4VEvLQywyyvnY0qYlRDfyFPIcGt+f4/WOElirSxbpQ40hK4X9eBQKJVURcSy
-yUSn5Uy/T6+P/+3mgE/3sDX1u81fs9JKWHX/+kUHAUi/xDa/6ySWN4dhKTc2Cn0xZfvNdTEpZtcg
-FDXLnTft5EnQkoUiSbkiwGwZR5tiPwtSaPcvsaUPa0YX9wsUmYxd9HPug4BH27U0aqmf3B9gj/uC
-u9Cae9AkGfRIOJmqVhuh1ianIRgyJD9L4/i0Uf4lnV72da04kVgHdGFE3Tn4QpvzelqiGWme5+Da
-cjleVaDIvBkv4WtNQdWGzvcFSvE2hdakomMj98ScI30IkLyeXVxuasoCYdtsg2IzkuttytXh3PAj
-c+c2A/aC7El5M5sUNSV1S9BameokXz+TN+ZOul6Y8cnsPQFdcXo1JTk/U2yRYadQkczxQKvAn+d+
-c3mQXRUFmPrdhd4AaQPtEJidLbXlcO7tJQOOGI8+bdMas+v7bs4DFoZyUhaHttIn4/cJupHKDzdT
-OEcgiuQUtMdkW+55FVNMPZ5RuU7Dco5t1RXhkDtfE8HQ58hzItDP8MejTjZoKhzX6b4lf9tpLIsv
-q/uW9qK5NLkv71vcvzYXpy+8+xb5RXOR7ka9b4FvmwuU+/bO4hBX/Ek91+yxX6IPaCw0uRF/4jkO
-/T6q3USqjZ5oo6md4sCHyGYlXALBd49gUK3fHvkZRC15ii15RZvjF/jjt83NIkFIU3ua2Yt7HP5p
-zFQo2dG0HUsnlI+kKUlSWpKiC4HsJHHGOwZisCfvQ5W7H7tve7H7G/Js9iYNgnYwyZgQym7XfbEI
-wNrjTh54y/z8t3I69DpQUifrmqoFYs8adG3IKBKRHzY9wvYZZ5W9vidv67Tu4WptnRr7HixLdQnO
-7shuDJCNUFnx1HE8gDM57KPiCpkOTHO+ndN3aO3sXMMMXhYEvXQzRoNkZE/QPchedAxDpr0LgQkp
-dRHTYjy3diuoaMVQFtB4Mxx4QcH4FpvskD6jOxfwWaoQ52kL+2e81uwTeyuPgSE0/VBslFYoOY6q
-XJKgiJW7SnpSldLA7NzUgcKUGbT/3156IiqS7P46kmk5qVGRwGrcW0Gy2ywhYvrAAUc7tm3BjB69
-oU2bQCf0kr0o/+Xu/fgCwnPaq4qPTM4Z69xnAzJCiSEoK9TxXKJuohV/qMnBrQOqkWKOgqnadmGi
-ToQRhewlFxDUhljEgdsSNreY+3kStd1MDimtuW498UcZV7MsMSkwqBrSdOLDQ2cdgp7AmnIkDqla
-5pltstJ32/vLd5I3DGRmguba2+F+bd0h/6mX/ej+paU/+0l+PkPqs/dYiFbm32DaakRCn99Up176
-t2jtXqx2vQiLo0qmt1GCXqR3EunyMgb3VR/MSZgOPA21dp7E+jPLiXW+iT9a3iv1ETERh2FA6MSM
-tOU20U7ZRVbVHhcAlrMLDduU/hHkhhx94HeTO0oY0zphpbmcNDtph0yS7TeL8aB2Gr6P6NzSVaQO
-L0xbUxGAqtmyBrViZQz+hPjQNrEZFmUxMGi0zebuPDJtRQMCPI7TCr7kgomasaPLUApO3MfGZu3V
-fmxR0PLW/clFKyGSUVsAzJmtuhz2bFpc000o3WfTj/cU4ESnsGmHKHVB9xtXwrzpwDMGiJN5h7fS
-+ccpRV5CCZ21QapqoFZCzvwEf0ffIjeMfTWk4ZBvMLqiaJodte573e9FmRovv+jnvYvxwUQxudZ5
-WWfepd727YD3Pl8S8V/dJV3L5ogKwJ/Q2cUsvum8wCi2FbOjgnsCxpCLEiXm52Xg8CxTU+0k+7rk
-eNJcQYmxU5y0S5c6PtYev7xuZpgTJFvnx2Vj7XYsDekNfqqKJ3QBvdpn9AhDLrIeK5ZdLqH3GUKs
-n1PAEjpVDepMg9jZSqNngRHZIIQ9+/D21UAckiFCZmWu+lf5stgABttjcKZCx+TN2lDDx9NZtVHv
-/JLewsqbIen+8OH420F2Pn0y/eXZ+dPD6fnZPx4+eXb05PBX02dHh2e/LCbnxT/943g8HXv5WZGW
-PT36hcZzgxMu++3MdNadDurzO3PITLfzYsCiEvXpFdi3veAj5DnuW9PZ1VVdEtMEqP3Jk7oE35ol
-Z1I8efLs0PTm6S/N4+DLZ4OjL7NHT0y2rPs9SHrM+zfmMINk2v74B8JXmBUVFfoBV/BUyjsyQ5Qd
-fTn48peDL3/llWfevy6vubwmOyexBREvwZ/fGsTFdfUtHzqDDhg+hGlNIvOvVU5aaJkMNnuw0aRU
-/JtUEE8lHsS1x4DVgB4iOv30pAPxh/bEkCFpi6dje13jn9EOhOWhoKaf1WZlEX5sd0fxq6HNwKvB
-r86pBBFn11yUIiKYMnBZXsod4+F0zyaX5d9Pe/uNjCoCZWjpcMUeQK2pBsU1YWxjtHXVsYXRPtaT
-TXXAMJUZNYRtADFSokGE/jAdeX0L8p7Wlsw3i7rCIeXInvp+wZz1tK5o5ODrCl5wNGyK2n0zgfMe
-jXX9OrCM0wRGD2dXZT3Mjp7gf58RAGw0AtAUihSH6ewbHVtctdKPLu4siitTnqEZGH0PxNzmOJiY
-C8SH9y+cETFIlccgW/gMIkooZ2KX0gFzwEP+f2b+P+D/97LuyaPDU3zKHxo64wUqj61XYrU6ZyBL
-twDprC7yOVXzF3C0iVTnB6BEgxKY+bMpESgecJP6XmxshehlBu/+UdSzdBR1cM5YTsdrXD8XCz+S
-ugQHTeHp3EyAY2mO6EcnTnOadXHrm3W21YlYLrMOGnEO2r1oafloQ+w8fPi1Rs9xSEN2sTlYHgfH
-E5+MsCRuOVY9VOJOVXL4x1JUlKrZUo4+dPXpPlE+F4TDx0vUN8FIm03ttulgSKtDtG5MGncw8XWL
-TrPsys4bJrFBEAgViVG9csFQg8ARwwDP6MmpB6hs7rmhFJ9LC4Yqeazbmq3zML+IIvnZlGa1L8CY
-6HJ8XVAwJUGvMmvpCwXdDTN6QoMAjIOHtyTqI1uqt10wa4t2htMJEQrJyamLV49vItKKby17n5ms
-+RQ0W1iQKI787zjfaxBsm2ZJSqc5ajl3f45qdpJQYJ0GWx5awVcH8VypvTJYj5ZBq4ZzsB4zddJA
-Xwk0X6HrYuC3YwtpdNiBrL63Dr5pdtXxMr7G5QeSZDqs0zdK33mBciunonpxH0qBE7Utqouaqmx6
-V3693I5O9+rifo2qFy8nyk1IKes6hbxIje0gHuRPfnn49J/em4P8yS8GR0f5L/7pV//47Jf/KZmB
-D6z7d4wCz5BshbiS8Wo98niSvTuESANNS4LdkwJqGHmApFc41le7vENBWrTUV3ss9doGCxGF2z55
-qmFxvd6+oTM7X70SlzuwwjD8BJtgPKhQpGX+fh17cP6/zX1blxtHkt6++PgY3ovPPtp+KBVNo0oE
-imxqNKOBBc5SFDVLe0aSNeSOfVptsBqo7q4hgAJRQLMxF9s/xP/HT/43/gGOW96zCiA1Wq9mpEZV
-5T0jIyMjI75QnGJkr6iRmTP05Xq7fPW3s80B9QYFRjZFvWl9/Xb18tN//Rd/gbu9ggJCWXOUYJIE
-5rUtr5Hj77blnL3wMdd+K0hOtN0Lt9wczC/STshTg2rSNYpb7Ds5IKarmjJHi1VJeVuyb5DIvpRg
-Vi4k5ibLTEr0pf1W0eIWeSIjhQ4X1eX+mpspZ1z6UJhyhuOx9BUxlUmymaZkOjvDcCapK0jhQEzT
-RQ1SS3mQRsG2eqnHCzdm6YCNcpXalVu9SMc3Keyg4zEWnMYbAJTS7qYpp4i0Bo1gnBlS0VnM3FBb
-utowHG+srjPN6lo3y/01zBc9c8glXIWBdLmqdiVM2DTFKUuDz9zQqtwuD+NlUy4EDoQLT7IVQgKM
-S8ZOy93BcmYKCa+S6Qwq6Rk7K5/pCWMmdLSVcugQNyWHLG+uaFiJVDcHxh2A1o66mkvU914NpRwn
-NpHtuykwG9oBqUVJRdjER/4LTKr0rUCIYRxkZ2XNVwSWPaMllM1mNCdwUFnOZrLIePxg/p2PBYJ9
-7LXbdH0l6QoehoKqnPgiskR+L0DyJU/C1GufpdOhkOzoSc4iIkaNs6LDU1UzykfeutPEWF9dqchT
-2kSSaxnfbxHzRP4Ad1zDz+/X83eLKf6laL344/s1RpHxAv/Q5M9mUiR6yW4O7nNaSBhZOAdldB5E
-wyKVgK4UPMuLhlzIof4sH+k+Ndv6mvD7gu4SbRZ0iGirHfVxm0lnLQ0PVCroZTIM+IfCnZuxduhk
-1yTYbaURc+VXqnow+DsZgVW5fQMNOaCWxCaj/VoxHorCB7+MfH5TtnRlxu8xILmeN/vQEkxqMV82
-reOXH+kaXtcc79jAU6t6FblHnb7hlhjssRW0KmHu/b67i0KIYeLEinN1dprSsGGwBns6/1Ks9qAA
-2o/UXoT0zXsRWizjPhsbhSxK0xbVMZcWKDmgU36WxGQrJ511gtvpTB7+l6Ub70oT7SVlepCk0IHA
-7ZYvCdji3BlnZJQBYXG1q3INW+UWzoKzgGLNWMPWimUEH7qKipB/2FgiGr9obubuHRNC3RQvq+0K
-sbx/ywQnOq53JsIl0a5IPNBf+cVUT+HqlQcTZMLRy2JP9+CxrTZZkk5REBEeT6wUiB3ZRZu6+dJz
-JpgLmMJ6LIgsyqJ0DQdiLwSBsPYCUv9x19zRXyga9sr5Fdc0Sf2WDXx3ca+7eFr2HMexwyCZgtxu
-iyqRfKSHIFdym14xYzy2Ln2ZJinrIa1gfBuKu5OCLJ7dbzm4PfvKY47cV1OlSXJ//PgnOjbZBmO1
-YKMt21bpP/vrwhNaJr+rF7sb5XyvRyj5Dx3zCNNo8203W2pLLzJz4eAr+saEbFw8JRf4auFT3Uwl
-wzEtKK2iOTV5cnaQKSQ+qUjmgVvLJDJiMGRnn7aJjJkp78Qx6yd3vMn12wTCLaXLRGCaifxLABEK
-LpGlVg3WjgLtEHb0C17YfRxy4mpDRddp89coY5FWzPDSV2NKdjBZ1vGpsDK00HZNs2yBIK4hO4Vr
-lE5NUldJhMWPVPd6+POSTK6VAQynwt1ctqqheHHzBx8lU6yHaOGA2JWUOwW0idWjJQoao894rumV
-jCOqq+YRtHfdV0TufKAqcIQXSufs1WibsUUuWcIW0zs7cYGWvGmc19YRo2sy9uiyPzFCKPyCo+OY
-un90S3alzNy6fYaX77k5S45JZDBFoSkppJZgDE7oLMeKjpGavPKCJQmjidM/UsNjfqfYTIAqYlOu
-x1A8+TOk2JgtCW7EXKNKdorvGN07GOLvJVfaER61E4e9bfMY6Q7uJdMP+Qfy3ZbLmlR1MjztYb0r
-70hHcNM0b9oPLtpeT8KgDI/JZO7UrMgIszkNTzRFJbQmhPtNbTI3Pzi79Ap32xojTTBJ4Ltipr7Y
-cgC+EpOkzK5EpVVLh/fzurEErrvdi28yo537Fs2AMz+KTDR6sCpMieSJfwTkk5wNLeZmILGWe1wS
-RK4BlOR7Hxk5Uy2TC7/GSyf+jrc7SP02RJ7gbpAFKIowDIzj4vZeV2tY8nMcpCwCmxNYoHgYPTS4
-UcsWtU1w+2DRMQspl5gFtoquyNY8+CnfKKmwpphnkvqBWjQn4JEjFM3uZRoZDm7bwFNowauZRHUj
-uFylkJSu5IFx2tBRjJDRgVVM2EXro4rP4xXhVoG9h8bQWHsSrPos7dVNxXd5cACDVEcbx2Ruz288
-nTVXGqv5/pbhWpVBIMq+GXwN4ov5Bcx3+3KJaw9vw8gAjVkjH2rgvR77/nJUxTxkOjCIFNeP/j1S
-a1f1uaOuGLXZ/1xuq/JNgJBD8M2Qsxseh66sUU2jiD3ovBM7OihL7noj4hl+IfEstjnx/fe39OUf
-eMuACZCr8Pvt5Pu1iGnMdzT/gnrIVCKjwMp8vxkvRUfotYwKZE/CXmDAGJ2DTQf4xreLN8kOuZaL
-pNSV2AmV1LHax4T2XbnKcAWHdpjn2SwV6wt712gufxdsXdbWhHHf5IiK6N8mtVpC/D1WbeqHDuTy
-zyXLhTWHUOxIFeVIB5KHm23oBHvkDhLMoEyfkZsgUaGIYmSF4KDLGdEjIP0jePbH6jU2Sd5RLdwc
-GLi361d/gzKqFYvxbfPy9z+n66TBqkG7UFnZ6BdsR54lnbA4oSIs+0IF2laOZQMJXk1QpsMiIYUX
-FwkHiHrFgQgwrK2KNULhJEjEqa9vqu0AIz+sEN+EwYNJaQ7chn1m2VO43C5rEwNDwmTZ11btoWXb
-IjzfWPdcpFmDA7V6oywZEKNLfeRxUUkY/j7+jRC80Y0XfsTSFWRJsN8B85EcX+zr5WLetLunFJTh
-GX4fJU9hEVw/Y6uDL59/8eqXfJegluhvbtdit/wtIfmpygr4gG++KPWuzA7e3EI7GMAOsWmaqysY
-MCseRLZp2rbG8BFsQ59bMy0UKcbJdSUWQow4t2y31S2HfZlG+wTC1B1ehkK+6dnjz3KVDR36dEbT
-bSf5o0ePYJsv78QubvrTR8UjB8xxXb2bzbI5Opj7PvDkDxlBbsR7CSLawsqed4RD4ELngdk6W3TQ
-xPpeD1iv+oa/Y765vNr4vtk0Tk8myTiX5WJ+UyLOveM5aJewZWOg4cOhbyHKRftg9n3YlNJsp8V2
-GKOjl9+IuKjLD4HX1d24xHu9v83xCtxubS/4tZd5lEgBMShUisVr2otLs8YAubdipoPYxtEok3In
-htEQkBkJ+xolfPZLmv02QXEWDaMF15vx0b1wGnoYoopJx3QU28aKYdOmnnFQ0YqH4+3QdPYiecCi
-rpv9tMrccaLPf75RsgdmSQ3HHBwUG8q/CMIwDxW6NbeYQrRW5ODFEQEJ1gHdECG9yb1U+g93ALRn
-s18qoj1XC6Sk3HYvuKrvCOFexQGsNFYVArhQkB2y731H4WtQl+qdC0n7KWLo0mEpxMp9Az8SenE0
-yVCW9nnlrGJZhdpxryRIAy7SzE8aCyUd5FEze9KUJkNE1oDJsqeRkcoNr7KQ4lGNt1oEK4E4S2c4
-bR32dgjZdfoCTWnhU4gc71C09I1D4ppeq9ex7ga2/QIV7obB+AFR4Y9DUmAYKjtMxleoKHh+Byu4
-VUEruiJS6Ur87OUS42YfoKl2MSfEoqLQIV54Np3uKHERDPsHkNbIIMJi7AZa29gBQsXF0AD/dGlu
-o/DxbYrbWJF23DFQIydhDfyMFi+KG5M5jDCC4k+lkCw1Q0QzsleLxrqRDd4MD67w7s7jOcwBe+GG
-2HJboSskUBWqj+UuO9LzjxaDCOYaX2rf2XSLSoDtq3SUH7MRp3yi7pAQ4tWCzln4ZZTnPZFIxBcb
-kRqRnsudtB+tu5NqtdmxhZHZKj5cNDCra6jqikd/OGLZGCUfR6vTKXL1tYXikHxYi4ydY7RtNv3A
-Ad1CLT8pRChSjXGD53PqlQP4RO9wn/ZCgxLRleuDsnTDZFoPFY+fttRBnLjx4hrBr6qNIwaQH2ye
-fJ78JEahhim/+Pofnv5KRcTDs7XiZaRqSe15M6WC0P2T7jnsjzHaP/8YI1YFXpsOh3lHYeKrw2F8
-kZMr3Qsb/SfkcHCJWhd1ubEwWvvVGxNQr3+SJWLxv4/PNk+qTCSqaAc2jAjsN2RfHkQfpqCRFQeB
-ZnAJZZYZn3VOM2M7cG4mYRFQ6ehcgd1BrLDNgQxNoc8NR4iwZo97YseENQMbS2WJ8EOqAO+3x6vh
-yGqOHzbO2xqswtTCCuNvmERmGWLoLpkeVCVVO2Dn7fV0CO9rBokLeurzeQqSSr3FAFRUiMKoIJ2+
-NoSFgguP0yudmqqbglGPiIfm3Rt9fF2pMlJ1gAOyIAPm1X5Heu8g9J4rRTMDxM6MV8T+zH+AEWbQ
-+n43rpDx5R4z5BY6F0+xyeRk9kRaQc9xsUYmLOUviw7a9PkpqUl1pLFTJi7pmDluyg+ZN+GHP2TW
-8LZGz9p4DGLnvHJnr3/mcG7/bNPHpv3hKuxM7MwvXTyZoPZnsh75w2kLktMCT2SBZWux0YxCjZpn
-imnEIe1R+MHZH5ywbG155x95qrcrZ3mqlRmZvfedJz0J1R1KjmqRNZ7Azacf0vUSaiYdWRLDVfWJ
-lDIqn1UcJTrEoYIAw9s16He6ZMVE3Y6MtOlZOFtWqDroXnTrkvp8y1Vpf7dKJovQfQSLriO9FD/K
-L96PPjyVlzAS0vGh3gs/n0AMMg+seUL0BN5paaMdhRsgN9aa6DXCup8knXBS1rKXrKgai0xCw84H
-9CSD9ansHUsX3YyXY14kL66SQ7NnJ2eMqRsKLYhjQDF8XEc0HYVRAa4Sn1voCDKubNwZFvj/A+eW
-zaVHGkKxypW4WA565JoWka+y7I/ovdVioMRq21Y0XKG75J0CVg81Ju6NcERSjoaz1kIGRkena3U4
-VZDcS5dlH6XOweAOpXfOEjXHUM3D+YZ/O/U6ODp4rrdb8/LLF99ld3Sgt+blN/w2JvPfWaxChG3V
-OFh3y11j59MBmac6tXcCongulkf1Dg7JPItuBF+QaPFTb2Q9zlrIelQVosUhj0ug5plyHEW5c4vJ
-ax0H11QWsuhlXVbG1XYAcbpppcVEymqs8o6cd16yLlV1J69ztJad+5k1e1doqr7sGGWRMULuSKSg
-jnuk878KT32Wcow98OPRvbZVa2u41U3NUDINfashEyLwfDI+u6CAGdsaYz6UNe2ScFilwEpu/XQ/
-EmjYuqvG9EPXGpxDarU29EHw/fxOOegbLsQO/2eTi4tAt6c1mo5bvTiTYzZL2CBdciQaodGeIbQV
-jsZ+vqMgJHKpPob+3NYY4MN2bXSYPXBItu51RR3HaA0zz9rqLftrQvJiJtHTZ+qzleNyrUpT1Byx
-/CT7V7HJVsXHY8oBd7xcdwZg1sbV3exYxGdDFEHbu4cWWrWvEJCl4daMqd1mE5XravxMF8z2yGJd
-GIMU7ZVPCQneRZNLsmUf3w6jscF/zCDejJuO9qHrHfuLlDsr/GhvkO3OqRhxFR3u5lb16fPHCMvz
-80n6Y9fE9yhk6IXGiz96z4YCUULOCaWxr+gPkP5nqPfVmmzsQBhEle6PV5sbUEksXkkSYo/h96n5
-6bNnz3/TX7OfhTT9kbTHWHmE33n4BeQM1yp3OA/extb2tmFEPWOvRab/gkYoNj0Z5+hE6sVMbFVP
-eLHFcJLINcRZ8SkygcUe40nCB+RObbcWyu6fuiTPTOnMmfPuMfHjaHp2fSrZn+3u6TRNgn1jYcyS
-8JDQbIkHZx3WInJpNTrxBsOcDJixn3yN4lyedTfrwxpjNUfvcrLJycKBY6XYRlHs10hAEPKVMhub
-OOWgcZWyDmOYDtQumas5eEdmie4pFk8hKhf7oXUeNC2DKyiLTvneXnlFRrsiLH319a/R2Ba9p+tl
-p5AiQ94tosjNiZ2NLlHOQsPckVqvduIgBoKRVRzBh8ElcHExPCGsXPKdjiCYy2nPum3Eg80p1/hy
-zHPv8TX+ijlNkzBNHCyzVrovhDk6mivfVFkXa8GC8TtODQeMC18nAwRAIjilYwIMZHr6Zsloy+Za
-KzhvZ2SLK/SLz8CzUOkp8e6nvkOCE3VW+QAqBCetICPViNFvFwNdE/IZCbayJfd7be2Vid6GVHKN
-BPrGSKy4nrgEPBNJfooQ3pX3758//RKysG8XdgNzcUxmrcOJtJmMYdG1Ap1M5jeMaKGQvtkCtvv+
-Ok/uIb/F2DUtmYZuZQwqMsWwJkWNxDRxRgWngGg6xeaTwbb+7uSuCIzTGo+OnPB1YBOcVfNUJRV7
-Oy4zWKP4BXYPtL9Ke5mxTkZ31xMxrtYVasrKbTc9nBjJp6aJOjG+pS5YVd6tlmTOMk06L86BqJPx
-GBLi3bm5Pj+R22fShZHdrlHiXp6bk9YR5DQ+hVSVH4knk37YK7RVIDIuQJkCOvIRnLBYG5iqF6pM
-4Zk5aGXqZT+KEzdMyTDmQK1WjUZcy2MqBMg6GNx7dPb4k598+tOfffbzE3799GcDdPt4/PjTn4r/
-zuaNKvjsp58yzvBPkrOfTT79VOPDFZvDgKNitZtGBdX65R5GfETBL8+KT4pH6OgImy9aZuNRq1zW
-12sK8kkKyFauphfVRx99RE04++TscfK75ma9PlgDcvbTxz9Lfl0ekkefIhbyJ48Jr3q2qObNtoRd
-vaW2uGDYDhQ2x88aPvrFMFHYXPhiVS8QerMmMxfYx2q+UkKu+u6mQlsXSqYheutWSmNIb6TRinVx
-5Fm+lEjfSwSSQXcBF9jSzNXwvyUfZ7/49nMg/CcESfoAnxgd6wmGL4cXj37BaRAHlxLlv0hcjfiQ
-vqPJwZPv3z1IHny/+MPjPyUPzr9fTC5UmchFnxQf5/9umHcC/NWOyHRPR94qET0A3b/YC54WHi/3
-VmGDF0Vh2nRvRnN1BnNF//xuv1KfHiX/cb+EyU3OPp08/gwmH3j+zUMDkYmijxJv9OhFETMppPqU
-czC2JaGRBrddrL3F1OcsmYRXNJQIg1eR+PJwOIlpGUuDqsvpUUEXJhSQZtLb9zBrJy01y4wefYPl
-Qqo98vQTeExq3rfDwTGQY+qrB24cwyymdAFWsY3CzEnwYXghkp4qn1/SaebRoAfAGB9mqOmZrWqK
-Dz87VOVWCvFBjP+RAYwH92Yf8A8wmHu0zlG4gJMBnes+sCgDodwxTiGccrkul4ffVxzxGEeHGBkt
-yhKxla8FkBWZVyqrFDbzgdyd0YmacW4JvBgNvwmtDb9hlVZA5aHUziRXri7r62YvRkdKDlPuQwIf
-zNXMUHwTKOJrmkMFoLKj+yr5BkWLlkIwnOFIdhNCGFMWWQOjZHj/cqhVe4vycDz9AtI/5vQksE4T
-JwlwOuo3eXXvtxOQFvY7FhUdLSawi3SSklYESjlihWlomsr224glYNP+qxuBCetneWVP91ICIsR6
-UFP6xMkwMunjlSDeM9TzyeTTi6BVOFPYAiMyzbQ4lGGiEc/KCId65NQ3Sh6N6H/OqVPnf8KFu+NE
-1Y5BxB38oLo6MKtVecbpU6FcdqLaMvrlpNPDqBODtODbq2z46uVX4898HyWG09MFuIC4/HGYdxah
-Db2lFIokHQO4bzYHXPgzp7VuZSrNmIMjdtZp1+uUG8HBctKYjae3etyP0Lzk7ebVXxtoTUL4fPvy
-f33BCJ/KN4P5F2vMRoTpREY8CkNSwQXJzQDwPHHaC4A+yT+y6UH0ZLfgXzOCgwcP2g1F6ECBCJCC
-B0j4jH64KfOBjdNFJZn7fw/U7hT8OkZhOOvx/7iq1xbi1HxZlev9hvhe4ADyYr2o7iJ3K66FABSY
-WcsLIZfM1sTPHMjMnkljZGx8KyNrcY+GVqIEkakFGoi5ORazct2sD6uGQgx9Q4TyS0JXTef7dgdz
-LcSTjgR/deoqj7gQhkR3D37iB6GrN+4z8OClogZj/FP8630TVC83Cov+FIFSZ7EP1pG816NkqkcI
-T5F4bKd1R5Y1qYOjqAYL8nevWL8zqcK0o1ws1o32oMOfwazgS40mQylMdg2Aa27KCWF0vq03jD2K
-WLOwtqPRnNFwBs32xDgBIx+ToSe3MqHJL8wuNsGvk2S/rt/uK9ZcipG8ZGBkVJPeasgETnWEWarf
-EEUzHq4KEWByUpMnug6SMbl4pGh0+GhQtlhU5ETXUYqt1cL0DB5crx1CDSaUO6H0stTlrltkSqo/
-Kmxie+UEE9KxdGotl6jG1iMokFpbrWGdb0shEtXuPNJw02wevyOGSXZxRb1GtV9WPzgbcU8C7Qf3
-1qZcZ/V8DE9k5IYWYL6NGyRmbx1GLxy3u8NSkY1rWOBxIgtn16vAWsvE9LkVnn0dlaYxEwlg1vz+
-9YGnijmspwnXbMzhag9EM24aeBEnsV7iUoh8YfBTIBSEg6BU9lpRRReOXYR2SNzsNDD2AdE0dZcL
-mxh135ki885ycNAVUl7mNDmaR0ACTSYerUwVF3eLMxkFWB5mLjtHc807yxSG3Hb9uZ611c6hPbav
-DPg3h1tpZOGJXagEQXLlBNfKhEPC0B2FKUAfcRUwmS87CoSH1GaVFPSfTFDthQSbl8PBDcal7NwK
-JjrCxGVpaXlOeLHnDKevlSyqchee6P0ZH3OdiFY2RWkVL0PQUw7bjX9R/qB3eXx/Ple4JlkErDPv
-2Lj1DkfGW0oasui387gR3/WEz8YEHdE7OWuJ7ZisJTe1SwwYigKRvPCjcglv4R/93FLCqhzjmAJs
-TIpDXozOvDWqufGln0Vq8pmtattMX6oqKm5vQHTfw8Rs5brMkjPfq0v/WK0kW91YI00uW9iL9HDi
-xw8yKUKEY5RlazVLxYySIhOMm3fAh/NHrBAdc1g5fHN2UdStmL702bbY7qiUfI5uflSlIkg4qVfb
-22qRhsfejXWsiJBs4QrESk6Nkb1aqFqWlaXqbafxif7WjuYQUx3Y3y0R2ltXlhNDZyVF9CSkEG3p
-yTWZwA0MGZbsYoriVUsFcLna1Oaamd/tnBar44bdcj6D2JNCL7zpwGvG79cCB3GeYpIJYZ1a1+aU
-7yIXhOxofnRRj31Xu6+/HeHpkafwmegBMsa7sRSkpORkPSjFk2RQrLloCnifa5U2myCX4LVlFf6u
-3C5arWfQmE4K8YhecqWeKjQWZ3XNKgXZG7HQ+R5tNuKnWtzBHmOilYPqZRKo8lA8lJ9eCtVuKmrV
-LGKlmGaIcoAfDC8CCYHQ7splXFalYUbHqQYVAgvy6kAjAbzNQUt8VEfxDWqDcIYJyHvXy+ayXMro
-u8wJB1Y1uxUkLaVYx/unfbtHO25yFYLz1OyyusIgFb4nDXuNIBGTQsjMIFsQrMoD7VQxHVNg3PMO
-9ev7liOIrRvMtFlWuwrNfcqrKnlXUqC5BbxCRHSbgEQxM79JWNUt506tAyH3EEYVJECqJV7fsMFi
-R1uoMMzFEOiHFnFiOJpPkvy2Sn6Hrsc4HRj+HEtCA3bnLEUhhbfIDBdJUXQ4/Yr3uO86ldsbI15X
-jceGZIbuQRBX/RYNNTI0PmKgQg+QZLM7o0DGW/p8Xl/kETXFmQ1OB8951x51Rtc6m113SC3VjuRJ
-UnfHScLziAyAcZ46hxPmBUfC4706ag8aaS5ytGnasUMGVWEB59hO7OiDs8lFEHyvZ/VujhycLWhN
-OlTAqVAqv+jEIiZUzKHp0jAnOoTXDmbgeJyeGhdY+EI4xtGuIkYhZdBuS8k9XJGMu9o2K1kJzIS7
-NFk2Kz1HbnuhNjqMayK8QZh7xvWFI34PCGg3FKMkFXmHjA4+JivUKESp3fYuEzfHlUtyKIPGlMpP
-++OC3Z1QgTMikV7f5e/tDyZHr0dwtAK2iAFIkMERhyW+9IvU0fj5NUbBW6LWbDpISLgRi0GXQbEo
-PB9QXws+p0KnUcqg2I+nRTmur7TPYWig24HFwne52hsSq8UrCC8+9GKjUO9C9xS7A+eBUSbk/Iiz
-RpaiYhI+34hRrSQmy1bs5EdT+xWb8xMgILrI8ZcuBgc0EmGVXWEHbYFFjQKxBzsyRNppNm5nd0Fs
-utcEDac2q8LBYWpTZWV2oRGoXcp/PnnUx1EWm5izWoT2kCtieZbhzSWhklZrDLQ7Scrbpl6IAaSI
-oSQJbRPkRrDfWznLqytELAXJ5RKknSWIKa0sLUY4JWAHJZEwsrFTt7qE4g5alxBb18eN17AvxK4Q
-TFsFamf7c8jGVg3S6czkDnRNHLfdqdLNe0L9xCG6Z8WtV94W4j3rAfij8FyvVaKT3JsYABdHQUOM
-40MIDS58Rl+Udvg0BZspcxjFnpQCSnvRuVQsiF02LU98HVpk+eRunm626qLVeeeOc/vFiQx28+Za
-uIDTrM1BPmSBnKBydLLkGXu6zgQ5Yga7FE9o5lYBabRn6iAuc3X3Dk026KTlNZvnw2u1cHg/dZzx
-1xoiylwGOTwk7PGVHMAIkaztyBZXDPsbndoMhOtLS9jZmrowVa3r5rVCZytxj+IF1XYmp8YJZ141
-UYffTdPuZGSDFGYJOvh1OoOGaotdnaoTdcz+T31zq7SrE8S7DmqDP5ZvsLOUFtWSHBeF0ZxL0otB
-73qhXVbpQlaLb+QKJNCG3DRL1Gaw+YI6YyKWc6l4T1v0KDAiQBCOWZ2KamFjbp0QRTb93LQ5ub99
-QuGn7HJHua3oqa/Djhl4ZzesKGsYFKC8WF4wKTOwO0fj6FXbOHn9XebeJKZD0PUqbUW5QK/k27pM
-zKWTqCzhCJ7bxdF6cqPEYhIvB+36bUzPieYmhgTyLoWkaDsd6mZNY0p/Jsn9zba5Ts6FSi6Scwoy
-02xhUrbBE7Tpwgurallt+PYEJqHT9dKbpwDchRW/TpqplweGzzHjyTD6lXdkZ8tSCqA6jZRpB1RE
-SUeCzgW3RvowMrUUkErH53IKldQrQgJmRJqAX8ILJwUiHirx2JjHMhb5O1owVuAQUgWDvIhLiu4s
-CUtcLhnwZVSxh8dc8rOHcd23FfnT4qbS7i9lOhVIui3Ck9ETlG8HeWGngCVi3KP6brtfsOZsh47x
-pF5EM+N5uQGeYKvQRMep7bUogSEJ730RNdGKBW2S7gZRPTfAq/Qt60guwFpbqW6l9q9YhQFaoxoB
-a3HzqgBUscifLk0olYNEkID22Yd2z2RMMzOfBD1JkDcan6PTCsDrmnJhnbolSML9LXJo9+XIh5bq
-aHpwqpL6XRALZXakr7zcHVrppsgjaCjHaVFMwbuIUZNciamMFrsc6Rx5zA5q151e/ZLbYdMB4Bkq
-RopMrrp1aX25e7nUum7naM7R1XxBs+BtJYuGKrPuWiIToCOvtVneq0lSgpndtIugvgdBYyPnK+lu
-4PzIZdjwyvqGwSNSjyHdE/ZQaZt1YhVGK4SlJNm9um331c8/8ZlPvd6x4zhFRDTsm7gwApfR2Xpd
-VQtxWkTHQ/s8fYkI2ppDaRGistgRfIUhj/N0PQewo3A/5IsNlEn5CzRdXlWSqhcnKHb29KbGusAJ
-cfOjuDiknN8DhVdbUtRyo9p9i6K4bhW5PF1fExIOhS6hC5JrpJ+dd8bzpGiOnQs1SHQx+JXHUpjo
-ugG4AaN2GxqiHmpzlJiUivvn1TVHrYEfwt/PrfCvaCMiEWDxpw4Cm17ExahCTGCGskkgcEl1B7wz
-eq+EX7HO4ZHCVjo8IubAC6WV3A693dcUHfNgR1Eeuryz8q3KzBbm4YFpqYLGzaWMWll+tCFG3fnE
-VnVh3lTSpnkcp45UCdLc7LR9wtmFT8tiQonOyA9y0+CV84n1VevbQFaOsKWjrVk0nn2Jmt7jY6sl
-wkCGUWPBe/vUzO3Uj2zhjLR32mK6UlPHq0GQfG2K48DhVmP5q9tWLoi/iNdO6uuxVwdOFcYK7cqB
-lVGmz5PbmBmoggKg8l7hKYU1X3FYM/R6XkzUsmlNWNOR0nbqN8O0Cw/VHittq68RNeQDzlJz5Yxj
-B6oFpxhFxiQ/zTD0Hn+U+w51kjf3yUDyYnIlcrhEALIK+Boj0RO2EadDa6018JfLSl2qNwgBtZG7
-LdrpBHXJVxj6MpXmcKMI1lyqa+IuWI2nKLurhpAFpOpndvODo1ezra/FLjLCb/qYh2PYoqKpRBby
-jBIEIKFOGb5RJ7NbS1jMfZusMEQhoTuKjktZBRHc4/zdIoDKtbvs2WGSaDijSNK2Ztzz49UWerwz
-odATmGCi0YVWZBCSOe3rl1W1ttRUcLzEvcjELcPuHSqCPUd4cRCM2FaBrL0IHwJrvKxga2SPwoEF
-4ikmIwppqAZKpg65R8s7b99xFbRCkxbEyt2ILjRMkjs10jQsCsG9Fg9HOl0v+NKxXrvQelJjFNjP
-urKMaJ/EG5OGme5GCe7U7j/DniK2OBl4woJCP0wcbzsm9u5m2+yvb1BJQnC5r1+z6RhP/+vXlgi5
-XCaZ0jyJL6hEVAR+Yl1JoqaceOqi6L8zdZT7Sg/hRfjsVebHclIY0KWxVI/NqXsh5J6xOucjaL7j
-x+AY9for2rUEPq1v4UWvigYboYaJnJ5pdeY9gr1zc8b7zPs0Cu8KpIudMFLW4Epavwg2qm778w6H
-sek6d1zrd4J1YcyyJ5E7b8fUqGPnzTsuR5Zx9LJttVQXJsJd25tldScSCJu5hz3T8bQWG75+lmIs
-+58ojS7dcBW612SAHl1SnY3qKEmbsEdLO9+xQQQHot5ky3J1uSiTu0mi0TrlTlaJYBjWOacZujhu
-6GGTQ8cSte9sZ5ZOYKYm/ui9bbAS6NYUJgD1sREtyWm3yv0rmJvvdAsKioKHoxpGxVuP0eIyhI6R
-tpM9nHQjqp2ydi5JN3Irj6FjSdlT9asA2WdJyruHqZfdDdISliBd1hTPLYhbvOkVIukCLc8yTgfx
-6R9xfIWYJTt9iG0m9EEXG4XOjVCKQxz27s4xgo8Rp7XVv36NyV6/Fk6N1q3VgkQfsWENNQCWT2K2
-qEBKnVNkGOymjrtHJrSWbyIZm2HhlsceflZRfctEx2N2bFzjdp1dO/t1TNHpjukJVgrOsNuTbgbU
-nelwBppt+6benDQPzhCafvBEMvob+oiCFGSb3bNGDOrgVSezx1j1rhQ0m5EW/LKcv7mpFxWihrjB
-tGN7tiWhmob4zEhIG5MfMR/zjDs6xKLT7Cmsvmdor3d/qwRUNKW0hRK+v3bUZLARK5MIdRxV8Qru
-XK837X5CHnGukWgqcHnR05Aqz7M4vhhETFedXAGPhnfutQsHlqKsxzHyyXjZdJfOI1bvw6lC2QU/
-M+O00uYx27pNN/4+w6XW+gYNeqUfixfrWsEIdNq/DVmvMJQ2S862mnf4bXq0pLOcq4IubDSCP/xJ
-4ngDi9pvyDMiExvekUbHV9AHHQbk8j6PQxYE5tDhSHaPoJKooqWFGzUWhCKVpIiVFTOHHwzebl/9
-pbp1XDdt9bZ9+W//OUNWbPdr0pkk7b6GvwnqrncVu4xjUh+ZYkfXSAahQoKYW4AVDvYDFE9/EZQH
-UZS3u2w2WyHIInK52WxEUWNHxPNkcH4Dq/0l31FrHm/MS1j9hy1Tir9RMlRZHF0gjJZ6727PUBWi
-bBNqKEFyWC8QstMSalQB3rwps+p2f9nu6t1+V0lsdS6U45u5rNuXP7HSx3RRAZXPZnT1PZuJ+Dtx
-WR/yJaeRLG/nPGzFu5tqnQeF6y5yHY/VM7DKvxNSWJXbNwVsCQi0E5s0Uk9zgN/JIISD5ZnLpLCv
-xOMld4UhL33B8PRanfjLal0R9J03wtcV3khZOfruRiExEMEMiQJ+UquHMdN+pDiWFGBZQ8qiufwd
-egpwhhjns1qP6b3Gv5BvHXwxrE+w+furxYROX/xNXHrvFk9D5RTskywpWeQ+fAl7yTLh0mtS7Wwl
-jKGoLyVFjGq9OqN9ilHTrgL227xbHyMon54mJ3dc1eD3/VirTb6BjfaryMuh224yu0f/idTl5Oio
-ThnS2Y1z8jlDitwUDgnLJczUTNiqPOqV5A6t/tq78tzG6zyxyXWTUgJrLxVAecPBdQKPQ3NCexBf
-CDmi18qaMJIul9WqZWB6xWYr7avNQid0hEEuy7VVVFtjUJXlIamv181WwocbdFWuOwyhQovt7e7V
-v1JbJjvJlcu3+5f/5xlvm+pVwqOPZYtZ+tUelllwCzF4qcEor5sGvYAIiNN2Miw5wOVtua0RF8gU
-zAZ/hBzcuQ3jvis/G3cHNnd7jsOvRrHwDPfSsGcUudd6YJCb9JoIaCkXHewub9WG8TAwKsZYwHCH
-dIdFkAFzkN53aXDdhBYq01SSpwaJ4RGjNEzTeo3wOTDdnKbeHYpUbq0i1b/l6t/ua4pUc1LllDhW
-9aKSYEsnVb0dWuWriltYSdwtrIkHdH4Dw5+6oBMjJMwSyADayp9NWdwYwjvkW3sR3eDgTji/KNG0
-lnb+8pBQGUl2lZewGhYwlV7P0+x5TjjlsJW3OcobG0wGB6EryZH9lxytdatF0T3XSx5sbBlJzW3n
-CMARdW+GwWSwRoFO2vFec1rCvVUnXejcom7RzI/6q6ybeho75sE/dZK654csCIKGWqd8glBKxtu8
-pzG7y6FVJMH1hOQZb9/uUpLrBg4R+2kYZCd8EyCnpp5jav7RTs8lOfD2GxqQBCRr/C+qgOip3NW3
-1fAiKJB7qucAL3jWOw75nWGZD6nAh1jOQy7k4brpnRPkm1TesL/zLv3oXD3kY7d40aDGar7nkG8O
-DZm7B7TJ3jMFORh6cRQ71zZSgZCPp94HYi0Cu4zu2ejvDHIAVkaQ7zSCjGUP+1ZNKNPXJW7gCqu5
-xOAOyo8Kdr+vvmQpjfVmbJ1kYD+MxdLAt0Fs0QQRt3I6/ujbcEo8YjxfIIM+Bfe6eneF23vTFguE
-RGPLKM7oB0O7x7SRopUV5YOpor++EigGEBo45EWwiFXHoTFXC4poT8WP5EtBYeMTz0nXxxRUt6xy
-/pKs82WDflWi9WN2QBYiL2WX/E5eCUmoOl2kROeWXt2PZqo0kgi5NPVqqOUjl4YW1eX+mlSEzmsi
-Y341cYJbrQ5kioaRmcmqyjXMIBmIYmSniSBh4A0MnDYlqa+948axeRvf26fnVt0XBKDhhLmWdlrW
-6SBEKmvZbSaGbBOxVh/pBudan8e1omWts+j069bEFYAndQXpjg8nHhi3e77XtHWsGJ4FVl9BtDrL
-0i+ff/vd82dPXz7/ciIsnEz7q5Li6akdRJkfePyaHDjdZegYA0YbofR4MEDEBhjrxrn5GqVxg19K
-P1W/1LVZ7DyrE8OgyVafdgDhmAF+gInTOHqAXeAdCwynFXiXWvPIMkp82uibmjvr1cRRl+Irvq2K
-JND3MuVW2Qqb1sQuqOyWYq6BE5lAfXVPufR6RsbHcOTZt7K+zWmMnwsWpUyty2rHLCUteEhoXCWx
-zFEsdRum5vGPJf4qdWN4UHLUG6GfdIpnOW/WTNarNOx9ASwOjWJGkm7kvS8Iw8kArfrcshOTSHFR
-WkExiBnjqsFOA85HLZurK43o1uxhJYNUeQPL2pgZmlKeTH1seEzNNuKnpkZhiE+DpIrz8/hZZuv9
-Ss7d1YKQKn1o53IXQ9aZ77eRsK2u7pgMpqK3N/SlS3Iwbdu9Ew1/U6gZ/S3vLxQUOWgRajH0aDlX
-1RLcy177MV7vuR6VLWos6diqGmRemos5eGU8MbB4W8NxQ7jhfxgKsxpOkuEdCcC80vC5Hf6JtMyY
-dkT5A48V4TZ+N0wbeI/kzguqt+NRgSumdVVbMlIfTSPjFwPP9saXf7iSl0uqTCPFJeLWs3FI4O9g
-zzXZiHrbyD1lnPKBRbJlvDTrAcod+aAj0dYJsMrjKe6pcLq6qu+UryM9jPg8THCEEZ9PjQzuDBoi
-T1DuyckDEB16LqSvx5zCWY3U3klfJkphded4Q8aP/bDoM4m461tWRwfkBw4DrXB3xgxb35H29OOP
-ebEGNv2602FSnwgsg1H8GS2UTBgYpskNu0K1eUMTIUF675VuITtUduc+sBGmy+n3WxScO6vjbreV
-sjGgsN27erdUkKVdo3q8n1yoKi5au8g3hDUHDJ9URSrY590cvaRzVxRTFrHYb5XCtt2KUJl9onjx
-9cvn33399FfPv/vum++eJGpkAh58FjSRz1kzY4DqeEPHiP/4Kco6I337q1e/fPG1Zd864fjjgpE/
-8jgl+W+RuTqc0VE3UuKBH0+ZygeM9OkP1W0ABb/wijBYbHuMDr3br0vCcBN/pjbBeBviWOb4dPnZ
-r8vt5dJNzxY8eLbxpqB3euh05w/8ooJkJLHIiBM6QxiVAkQXPP+JpiUbmnywA59f5Mq2nbMH1aiL
-pGVzTSYaGsl9UdVw2keJx7swuidcUPkOVBoAic55qDAkLD7HtvlecoZ4dFUrwX/lyoytQvC+3IHL
-09yPm6EIfTJJncgoiuR8kXAShL810TGlPzTuSmr4WPeya5rcPZKZSpp6xpmeMNu5JF0BRjUCi+uZ
-HLmQUtEhrVOQnK7I9M/BfrQia8uitL2Kus5W061tHQjjYs4j75otxzdsjxAh5ULa08aBm8AFQg5D
-CkgKy/YvV/GaqrwkRxE83nlru89QQ82GORR8DmJ/ry/wFjn2EAlOVHi909k7pVBUoaaVu+kB/URx
-r7wNzM8YZnIvI3EAYcvZb5axq3P+qiV9fDyhSXysDU7XDh9XRf5hCDRarYcTvOn7U1yxQQPjnac7
-CtviseFIUcFBvqOsQ4XXnLHiunlDyyQh85gDk8CnOKPooaReqolxFZ4oIzIE4IMemfSl76GzTikm
-4l7f35+Y7HV+v0W95X2aJcxYXMMe+66EU+4iP0b4x0bArywizZwsz+tLCFIORJwl7fjE+lTcxdkR
-IYQLAkGkKIoEzk2XzXLho3q7tfZz9m5FVDf7TUmeTH0W7EQg7lWI9RStFJy9hZOs4dmESl0S3Mvl
-XXfG+gfNWC761DcPpoTfKuKMz/A75uheH6+mwRV2PXw+jAgBsldKIzLn1OJ8UWHHQaYPjNhpUih0
-Y7XOrNEl2zv6yAKbdaLgse7IopQrXibSSUH9USEoNePYFzbYS43knLonsAd8BAvnh5C9mQAc9Sj3
-PlIN6q2Th8n9hSRBtsG/nMmNkaiXX5EmFCA/TyWP+Ji5VQRo5UwYslkT77bWes/Nmif8M+fq5kgz
-8k08MDabx51ixBnnNS0CnSOGjxHx5VWgNbCTqqidrMOkSIISuDHGII3at9eK1hoBPCqnU8JbIJsL
-rlqOBWl0RG8xZhKpfdPCv2BDJavypMZE55NP7KUhZ87Nstwh8D0Gox6Pk28PuxuoUyJjYxEqwUhV
-lsdQZyiM3HBz2Bxmdp3+HnmsvUEBXqNVw5EIzzHx+H4L/7+g1krhXSV9cuF2nggZuqwd3qkQZRZr
-e6H3SNJPkkcJXakFh319k/r9wDG9tHxKnAw4fCUc+y9rDTgwifYb20xhAcRsubqr5vsdWqfkg95D
-tb2MTzgMMfHa+AqFrzSnkjrAQZWS5mqJMRXWtLTb/Acuf2BMdXvTuWbjahdlZbj2EV2UYzwc1DXL
-VqyFii68jdU5Z5vNRxT9ec8xhtb2R7i2TW8SzIdKlgh2L7vImQBnJ9Umh99i16jr/kw1IO9yVD2L
-uQs8+iEc7Z5EPMO5E+8UL+qZTE+A4hBT1hErJGH1vlaHUVwzKT53kV5iUxnTF91Dqxg2G0HTDpbR
-SvYyqwlsEDVq2j61tTKiaQ2a08xLjiWwrBAJAEtR1tpQ0psycXDeLqt5iZowNrER1sKRDq4bQVbC
-CH7beiFmnugef4BTwhHiVtZAn0dO9L3Jx2cxNN392r/8czyAMK4CQRHAcMXpT8IxkZWxo7AaTiZD
-tJGxdVZh3doLnh8L4534CIWps2izOAHloAVDsOiZlCA4rscOa0xt91ugMRKaMqvQ/JST5KnjQ2Pi
-jlB/QhlF7cI6mWT5ZIKsBFWAJ/SKC8h7pZAdmtg5Trr1esHePV7gxZ4+IkpYtZiZVaO6iT7O85sS
-I6Oen00u0HAaLUgYHR+b58cGYW2o7+OqyJobOw3rO5/Q2QC/5xfx8Xfh+53+e1FfteFHs8T+hpWZ
-uiaRyrhIORNCroj2gqyvljrOY5rlEcuWe2LlFMaMcGYpM60Zn+XJxyAiJOngKLkLQ6VSkNqXeae4
-7Oy91V0tmtJR4rhbWevMeS9iSvddWJp6l5eqAgpg9whYxyh5HJMfxDZ5xuek2DWiSqH22+hVYygH
-qU10Jvkz34jOj/vptBom9HFM3BDp6k11uGzK7YJuvbb7TQCCTd4zmCFIOVtVq2YQ7aF1T5LHU5Ag
-kYWTrGqZmQbpKziS+v2TUbxZQInKhYzNLbYZBioiXK74YcyO3RzqmzwgpY5ah/l7jrQRGToTeW2R
-e0atHz0yK3y6kkzIu7fzbdneFCtYS0EoZOv4hyKiI6zDGKT/Sep6oepKCcuivT5lx9f2yyFrUc07
-Ki/Gd7ywd9GCzFi7OmW5t2cXI6Vy0jcFkGQNR7lFsypr98LNzZIwdBLBC9CVlwoHdYMI3kn6MB2v
-Ma4bAukyVnvEIgYFP/5pttnvv8ct9mGaU6APp07PtEnpUoGdJp+P1dk53rM8rD1+QQc0H7NzwYBN
-NDT9CDaSBo6LZ91anIk6RXLqEFefxr5HDTTR51CZphO0aOeKCC7SAB2DykWTHRcmQ9g2Hj0sysFr
-tCirYA29qsZnDXEC4/tCfaMROxNxwp4eKuB2W3mT8i39LzzcD1wsnV3pBJqSSxi83HXX3XvhUfQF
-5vCryM8nn3ri+olxOaxohLRqxcOAd6FaYhQ5goWVzjHMbuN4VhFImbvIaZml+POLvPe68w63ls3i
-Ek+462Ef9tFdH6ZLIGd0mUS5ViHsYkN2susmwDCiMbAQNNSoaD1ArGOSqGteupQwRgP51dMXv3r1
-3fPfpPmgQy3RWUV/LxVeU4cNt3MH6SyVbbXpOewESqTwnrQrvBJv1bpGn9ucUi+N28zfukOJpNnj
-9Gl5kooOqEfk2B+VdviG5cchHTKr6iEcs0LPpR2R09OHTEr05hlN0Lt0ZVqW6KEL7k5iX/6wC0r3
-TTxZvZP/A5popJPjpZc78ZRvrt6jeGX7cWIN2gysp5KTafoEeva/xva6o9pK3ibmShlDlpvCfTog
-XFyV6zgdqfwBtUtx52NUSUw53G48whQfsVX6yfjsoseOVZJFVjafvYJrK9oEZwsFiRi7YUrGHfdR
-xngfDiTkqcTbgrYSkltTczBMRR/njjHk9nZPLC8Lt01MKB4umCIcL3yrdkv4bcHyl8yMvF1bag4L
-48owsqVnxqj4GiGwluukWm12B0w7Yjf8ynXCjwBRGfmAcrnozi4YVVcEP2iA6mV6fyGKadTBQJ58
-hK3Jc99OF7kjX3pRfh+KH3hM40T5kBV8n1Qg94vHuAUAdS24Lrpl9amn964qsPqK8W+o9AMvb/2c
-Af17Vpzu7mbbarqkODmGafkm7o0DcxCYdiFR9Yh36fgNH9/eeHeO8Rrw+ry622wDwO7eKlYMd5qs
-8uObKZAWB8Iwo4Mu6IyXGlbiWEac20N6AUSpnTCXiOxjz5RYb2wRj+KmUYDd2a3tIYXrIXTuucWR
-8W6awwhe6jhwvy3o/3xti4Nwawfxyl4eNnyiGFm+umFwLDyn3Eqz9f2iJNMngWUXShBI+xlqpJWB
-YATq7GDfXN5FxIdDXS0XyaFndXCKu8Hg7e2rv/EC8rx99/L//huG+dhU2zGfGMkf6iF7cloBNVYV
-OmTX7aodJa9fw3sY7devSWVBj1cLeNLBwDXouYTv6sbz+IEgHkexOcbSVwsYw0ALWFgHNlgKAxQw
-ako66sYUuFqQQ9WhFTwBCz2AnfD1qNrjSDgwCDhEAXkX2iE//yOU9Md104Md0Pq9mFEMqHTEsaCm
-KHwrwADpd+q3ifAKEBcACUwPz5TrDRCzCPvbwQZwgjfFojZNjO//uxIkFrzhrLZk3GGGAbXX5eLA
-QRCpkIcaIhMjwKj9BzkydFsDGELy1G50GqIOakgeHA3jOtoBCmAoZIoTqUPsdBR5tVBF2gvNfIcy
-OIEONvOMS1chzzgpz3CHvzxnxTt6PxLNQDDlYYXC6uSjBf+2uE5MTv19vcnOU0iKzBySpxdeRlcW
-DQ5wWshV20eWSr8WyDGYh/oV59ot9utGUht/WBIdy+XS34I1BgLvBRhq51iSatebQkLjdAU4xBFJ
-dQxDZ7I6vXdlxfJcRt13Z/ztsQqKFIkL5xQCCZxn6/yCoBk7EC7R9dTvxJUlpkuS4mWFnBUEna8w
-g9ncEStCu7XCAqDy8GZlPW9wvU3TVy+/Gn9mnZivFCyEP2hYlNdCvEldX9dNxzArZ9q73YtvMi8g
-lwpaJDE/eYE4ZKnGiBdgF1g3VPCb3UKm8Ksvs3XzrgMiBWlfogA6o5tTVKXoF6cIz2TXah6u/5Pa
-d3rr9MgGrTNfTmxdRDcj6NrPgnBWEc1yN5h+sL2JaCnMzo2/xmhknh+8H34tgASZ2xwkYLzRtD19
-iaqf/dI8eOpUQgfqnZXhj2P3I71ov/EdJUrq2hUn3L3wRFoV10XyO5KV48Ni9iNrtn0OQyx0pucw
-UA1Yti2lUZ15HC4eqBg+FsyhHftsK4DaDPNZ1lF5ZFfV+jchHTLmUJRDD5FbLXvUGG9xyDuer4Zj
-XEX6hAYMQxTmhjkLMOV8vl/t0VpKtkuEI0L3OswUhTR3o8MFC8D9bHM8fxuJ3DrrKfK7EK7Meblm
-LSpWN9LillmoBN1KqzSgTdF/6bQj15JdpiWKr+BNmbulWUShU3hEhMvMlpDMbmlaPk288gjqdhNv
-UKyWc3684Oh5jprfmzaflLXQ0scmheb3ZJLtSyHuzCMVRcWHRYVi/m2JrhFit5DlH0Qa3oyEMVw/
-YEbcQe++/tWLisZOxLAu+5J4y/DIDIPUU3Zmrd/zRxfJg0T/HnWCajur/vzMynV2EYVy56+xGejl
-LQq821TWJX8qOgnnXXy7D/jC45AemzNpENxM8sebdEK0MDMjM1NW16rUSXi2w5eeulXvJ5KEg8Co
-5hcqY3xXwW4L+ns2ZFUEMm3SQsTxkP0GaYM43YA8lku+FTP20bCWc2yBettmdBhsw/uOMY6E+YsU
-1bnw2GwxzDHp6WB00iJ2iP6wkINO/fvq+KLWpQaGVzGIXx4dDz/dx/3tFREMpK+SE8wbX1gIZMGe
-jdwT8LqQ/GRx34Mf8/22rW8rVf+IdOxb2Bgpbnec69nW4QwHjGtmhXcKFKT7XUVh3azCg2Ii5hvI
-448ZQ0ZDzmpeKyZ8bqhZw0qiigmf4cE3iYIeVTV1eNszQntUTAxni2VKSvYBVc2VVuI9a3JShdzh
-Q5uj0cQ/tPMfZl35PjJGnCzev6tW7IQoBwgiKJwoL51G+r1U7k6xsVGI+uEfWQhB7oStEo5eqQeH
-lEH8DBOXNGjhWaMuAzWb8Q6aYTBWEwEiTdNqXRKWihG9G8HoIeRYg5720GA/0oGVdBMDswdiDxmL
-pbwt6yWWmtzWpb5HKPBwIiOWv36tuDrOVDsw2C7SD8yXqQjYmJyuTwrVahvET+mCuKeZr4PJO8fj
-avHew0HQciqaITodnNFYPP4nMiKeqGjpEaIRmCgM+tUiUQICuh20goIrGsLTxvirL3NPuSopu6ER
-ORnlCVARtTrVTmV0abaqyfjVdpRiH+dMNi3THLUCVzdLMW6oqlDKj6h4pNRUlnZAz3pcjeqVbWjE
-lMEq21i3bXHt7d2rv4KpmuFxr0TW//bw6mf6km6wOcRAFilDGF7v7e9f/Ut1s7hZXL79w8v//Zd8
-q0jbDHFmXBqXew5IT6qHb7/8YkSaFHH1/ZI+V9tjYXj8uDt//gtD6MJ7IXPv2wqynAjLTSTHGiRr
-bGQMFjIGqGRi8zsfmZuiXG3QMFzDA3P4J4xZwTHRhhNJDCOc5YV+/6dTIL6N1lUHSVP9s082vXDP
-3y4uX6xvmzekTh9C1pqehpoP6OZp1pp821b7RYNEwQhW0NJqS2wVhwoIfZlAQSYGHHl/WVCbWrgP
-0Pl0//0lwfSJLaNqdTpDqDCj22azoevK9SF58Y1h/W40uqstexsi4yYzQXyGsb+aIeS6s0nrqLH4
-23hsS+sHA0/v0X3M0/eLljLUmxFoCb/IwptET6ygnYO5KqTpFvHfR/cR0a3GVDWjUBXjSEt0mOnE
-Y/XTxTAclRHeE1S1uHOdvfhmbPZzXEq4M19d5dYQyf0a0h+Qtr2kMppotUKB0LXkzSOhCb2QqSet
-cexkQ90LTiHhW218NlX1nXBlHzthHzlbO6dH0w17mRmi9faoPjk7OF7Gy+Yl3H9C6BpjzROE22h2
-NPkzHEjMCaTb3/C004YV4kkHMPNRGvoCtkk3UFYrnqs4Qfl7FkGEfQmE/cXi8j/v611ce4kHB9sP
-jBCFU2X+KuZt7dGsfKHS4lHVwBSWl80tBjqS4VFq8moRUWmweeI73A/Gewlc7wNuD1sdsYgB9iPO
-74RV2Vboao/6ldumxjBF0Cp1E45xdzGoCSyDZo8yv1UIhwtEn/wVyNgMUrmEVYmbVEtxZB2mdRJ3
-9h060xzNeAfdXM3haDq2R5p3GTTbpsxO3gqFEOwxLKDUNgR9miyaOVHYq3V1tyHjPU1maleCwbza
-L9mGp8Hlgq1fFVYxr2Sa9jCl2+UBazJBrSTOQJd9XBgIcKR4cU/bPBLeXarQg05J+MRwLI/7YmuH
-uWfyw85n9T3bXbqToN15/Nh2waHcLkTxtsWlse+ABxZ1FFfLZEfK3VAYGHKbHLAV8BWI2f4JBT8D
-M+NdBMsoorkCPKbukLhY1qq8Qwdp4wGejP1gJEZBXTOeI6Y7ry9AGgBpiWMe0ZVTGkT4BXL10buc
-BoynZ3F3Ne4rDyi0kvZwfnJOZ5tCS+RwDmC8YRiCt3989dc6PNpqA6eet396uf8XfL5p9xs6lNAK
-2Da3NXGPnTLASSA1bWk1qwg4ALTYSCrTyPCkQ06kqs5VswYOu8E40okktV6ZuAPUtL+HMV0ejTrw
-XqEGWE6augFOaIZ4NGyEVAYwxO4raBwyUBnhOEzPTggRHY7cgUFX8MjorkxgKtdwdFpLHRgNDN9B
-++olBaSDcxaM8AuKc7Rv9yh2OCVcMtYpTIvaS4bco2FoxsrqFjdWD003Yqwoy//9un67r8bK5nOM
-hwv24zS9cdWEa7pFv96X2xJIr6IQSZcVFxePEX4PmMGyuYYT66Z+V25h73hyVpwhJ6dOUPvD5qfx
-6OswixjDl+YrF/TJzJ4y+Nea3dUba2ZV8N9Rst6vLhEk2g/XrIq2/L5Mbb4YpArx4iFJ8GbMU6ze
-QHMiQYdDrr3xFRcFScCqjhmWw/ieU92NiP9ItcGoeIgNgmOh2kHwy29m6PSCZlruVZ1ZMVnKw4VG
-QsHob5zY6npUIgdUyUAxsiOLozgpgDwrf1Q17+Ok68+ha2UVlCgTqt6HjNoqz9UsqQ9R9xdNAr3B
-uXUqOOaCTBm5ufRI6RRsga4Gd1OUROcexyArZ1ZxO4u2w5RCQ+vqnU6UBjuyYpqGmixsFJ/JS4mc
-4rR4b9ROa7OREdtRVDB7v3GimPjxxgTq/BzGHaTABnpRcCPE0GKFxsV8Ka6uaocz5mQ3XPwQ8ozI
-xgmtVEXP62VV2+fQ7EGYrTCPQQlR3T9XHCr/taa9c4vicMKWch73HdoSkK1XJbxx9v/E7A/MfTju
-5iIhwIh2f2lVIBFXXTbAs25YQfKSVGVKicHRjSkQ62uHdl/PWN4xjXZvCgQ6S4YAJFhjloGf7DQi
-mqIqfX+Zpeff//YC9yKU1QyTvrMKU8ThzG8hO0tsP7GVnOjE8t9f/S1qoak3cxjTar+rl2//x8t/
-9lckkXH0WQGyRzN0jCuY0El8d4P68nFbXuF1+Rw1sHiCw/2xZHlsMHi6XCbP8Bt79fHCAhbdbDFs
-2oLd9OinQgFfVBh5d3tgH8MB39MwhBtf3Ku1xYIA3fDxCWdXlzuJ1CvtIVGOw98yjggCfYrMR7+B
-Mq4r8bdkue+Lsq3n1OKMpzLvlP1AOseWgig6PXv8mc8ezFcW5OXBTbTZ7teIoYfn2vUus/KMrTwP
-P/OthBb1fMcW8NYtBZyZ47cUmLrg757lMI80dwfHO349QgWcw/cLG5Jv7+dGw3d4EVRPnYSZA3Jl
-M4ss1h0qH6F1sAzbLGgZVOOynR6ADWM2Y3pwkkExemRzJRF3eTQNdeQNRcxWExVJ9zSOumUb2lhk
-f1Ij3QK61pM3F3tTjZovf87pLZ/qHQhGfxYj0hUlIshERcd0NcXZEs7nilhrkqdlmWg3R5ovV6Y1
-6Z5M/RXmh1SobnF9lPN5s10IBiN1athKGwJzZTKoy7jnnIQXRKe9o3g4yxgaG25aa2JjdxFWU7Sk
-aR34UG/I0q0ujl32EBhwUo4nvtevapfVAQ3odz6hTBddgAmQ7tcvk7be7Zl3c7h05ubJioyjLhHS
-cl11w2DYrDsUDoS/Im3Om3b3dI6RPJnTGqZr5IPkKad9Ccz5ISceE2gjTmhsu7H0hPBNDLooDAuH
-9oRtDFWMe5EIKKTLFva1OaYauHiH+9W4pCqrdtxcjcsxF/Ex7RrjXTOmJTaGMsbWOsF/XlIcdngl
-pI/VAOelUNsgsHCzGB+UqNSF7zZbl7UV4D7b3jRLOtu2ezgOzxGx0PT3K0RvdMYiuVpWd/UlHNzh
-GL1iz3k4VpOLpJGqSOJTUyutQUCJkrrpyjD3eMPUspac8smKDrrH1z0yKpDQskqcncAc+RJ3qjZj
-a4Gwc7/ksK3E14toeuFhv6VxrhbPhGKeE11CYbhgQWbB+oAmhSjjqY/t/6JBhUHlWQ02PhVSlknE
-dQdn8lTMW5eBtkbqtxlCvjeO7e2S60FQUHwjNy1RbYMlAAS1o7HZm2X6FK9rexYnSYVMqcSkWmL6
-/MLQLdISYek2CZCvS1BHBSp6FlyE6dmj4pHdd1wFmWnkiPqXF7pAU1QeiGVSJotl8nCqWOTuuaFU
-gVCRtImAjHC3qTGSWMyYxRVyQ8cTteG73+39+f3WV/cq4u7QSFprRK8rhIFzh62rORbdvNfyoWEi
-poU1+vR9yhJySzADY6bAWzm7Ps6x0/KFLKS3/3Nf/D8FV4fQ
+eNrsvWuTI0lyILbHk446nHgkpRP1Op5yUGpm5jQKXdUzsw/cYFa9Pd1kk/No68fu0GpK6Cwgqyq3
+gEx0ZqKrisuh6RfI7H6Bfo5MZvqmPyR/xTMjAVTPzC5lpprpKiAzHh4eHh7uHh7u/9sffff2J8nr
+P1vfjmfL6mI8mxVl0c5mb//F678dDocRPLsoyovo0fNnURKv62qxmed1E0dZuYjieVU2mxV9h49l
+Pm/zRfSuyKKr/Pa6qhdNGkEjg8HbP3r9x9hD0y7e/stX/8e/+MlPitW6qtuouW0Gg/kya5roZbtI
+qrPfQhvpZBDBD3a/yq7yJmqr9eEyf5cvo/Vte1mV0QrAWMKL7F1WLLOzZR5l8KWMsrati7NNm4+o
+BfzhjnAI7WW+iqDyeVE3bZTN53nTjFVPA/qwyM8jhYGkyZfnAgr+4FdAz6KYw8toiqCPBQ678kXe
+IhRSfxSV2Sq3WmnrW/MFf1bQFHRJUEIlKq4L5DfzfN1Gz+jtk7quardynRVNHj1So6YSyRAwDYie
+wJRslouorFpBQnSvGUb3IreLOm83NWB0MIA6AAtOQzp4+5+9/hOcsHm1yMf46+1//uo/XeppW98O
+zASOoqoZr7P2cnBeV6uoKJs1TKLq8/HXs18/evHoxV+/HMnnv3vy97/5+sXnLweDs02xhKmZ1fm6
+hq7xz2CAv5fFGXwHAKTEeAZ44waTGAvEoyiWgnGqKOgxwNkloes6W6/zOsrqagM0+5wpCMcUcdmG
+5j84/SPA8DUWtWZQnjB8hB+YcnmYqOIu1cBTHB6/6ycFKnteLHOcIVMBOpmpp6HyQM3LoszLyq9i
+XhxGx92a3V6cHoT2XOIKkd+r27WiPKS1zMbtJLpXA80pvIzS1F4r+VuN5wpWZ21jmcnSoG/KRfCL
+3USZ72oCYcICuglTHYnWX+ZIMlIzowIykmhdFSXzkSpqqk09z2mginbwZ81EgbXGy2qeLRMFvz2H
+hjiKc4JuPZ5f5vOrJHWxexB98803wAFvz3KklegyqxdAx8viKkdeFl3nRb1ABl3MvXpFSQWaFph0
+hmVgOZ0gKcwz6Gm8WS+ylj+fRosqb37p1MdRhOD2EbtmRBKOYNx1BausvU3w+yj6qipz9XvIaDwH
+oIrGpo6hRQ3nm+WS0bp9RmTNveQZkLk5r2oaMTaiJgfB5k55ouz29GfiWIrRKZbFDZgy0OgoIpZP
+L2DJlQsLVMRTh59ipYGqLRBZSDJPHVQ58+D+DO2xwWbbZsCnaFfrx+n3xqfVbtyozqtyeRtE5oFe
+taagNJUBlWeAWpgPZy4UKTlQWFjVQ8Fttb5oZKm/y+rp02zZ5H3DajdrmP3rAugOxwFVQUwpW9r7
+mtDwBg7qYWHG0EccAW6bvI1e1RtoBGZM9YC1uS2hMChdsCBSLpymRBLSIDTR9WUOI67zBr714PES
+WuH5vgSCnG94RgAHxIAQEfZ2ZK1X/RjKwPYPIyYGj8tYPbG5D0Dt8hxd7b6ud77MLpror6yN/G41
+9HbvzbkUBhAIkScT1dKp2s+f1vCis6H/xt3PM7Wjn2Pp6LJaLhBH5zNiwA3Jqeezi2V1Bt+oDeCO
+15fF/BJ2OJyFpgAhNpqD9Ah8Nn+XLTfAHBfjfplwxF35oqEnFJAwQgXH57OATKC3bFUmsFXzBq+A
+t8raw7EKypCtNulBSBihEhanAKE1R/L0mQUQiR7d2OJlsDCQY3nyQHA1D4dpcFv3mkQxygVDcMS1
+9SubjeqHe3LRoWmF+CbTDHzIHL6JVCBTTVJL9OGHQKaNx2wUraAatMhjtetamFU/yEtQZaqB26xb
+oLdsGWWLRSEfaZY0B2kGAZw21DRQ62bZKpYj/UMb4a3NkINDHoD39W2SdsqJWJDQSP0JI4wwLlyi
+HOn6Nv5u8vlsDwRCsfdB3n/chrwfDxWWOsID3I6PyEIIqipKSrXZWWffipvsHLCRlFV5WOfzTd0U
+76APoOpDXAwpLIMa2RtpTLgnxLI7B8dt1mNRjbFlgkMgMNAVDahXm7wPQGnF3iffY0deFg1TLu7M
+TUSKLlZbbmBUOJIMtju9Se67HRflfLlZ5J0tWG27/la17xYMYANoQC8np4Y6EMj6AknV8C+FBejc
+E9876p1pd4w7WLlIEqg6cknyBB6dpqlTUTSxv8tvAzoYi+CwW7LkwOIgbGbVHKiHB7ppkGSeN7fz
+qrMJEzxqw31VZ/P8LJtfPSkB+q4qnUXYEmA4x/eICJC0VB1jRcF9tSjPcXNDfjzYoltTQx0ji3rB
+wgt99La6mnVXtdOwpKDKjtuzGW/Rlkj1+uJyHD0cf0zU8XD8SbQozmFBNBFohDnjKS9J/shxhVk1
+V8BzC1p+ZhNqxjA00BQ2UDc7qzYtK1zVcoNsaRSBwmy1AFIcWmJAvkD9Amm0RxawR9AnD9T5kmCZ
+OnUPLcTIzmr0f3sGkAV0jVtCDsNPXRKI7jWTe4vPUIP3m2c1zwLh/nG6hzxxF+VjU9e4U5s9216h
+WqfqjFtLFB2p4w8hZyi116wTnmFb3gjZIWxJyUP7ndTutupoxmS2cHUrZj67YXBESr2paiB0Sx4k
+UhJwASJ7Xi+zW5LRscmhs00WuPyAMYfo5oV5y0PKiiU2Y3CNS1vJSxm0CDryMl9EyIvqlSsp4XZA
+6/YadVMEn943JGfAN6whWoAvCmv2FpSBDV22vOWPNXzpGHfvdeJy9xuLj80cDIh9wKB/JJxkhkOf
+4i6Y+vskWXuBS6PtB2TvmxHCkQY2It90Z3DLGMzRclweirxBVrwImvO2Jhch0+gmSDuqgENymj+F
+rRQHaKr/W1btWFa37JmirR0eR7CTZsglLJOEsmhnN8kWnjiKjtwlYIExirKmJfvYFCc4zL40+ZlF
+NfbU+Osc9l4WTnCLJlLUTePKxNkChgxiJp5gtG2dWxLsAdkvoAbv/0CdRMkR4rK1tyjHiDVWChrb
+smxmV2flRT6Dft6LiRbKnrRV96MN37J9QNvQYcm6sfMS2tOogBYRFd1WuYVeJmi1hSV7m6HlrsFQ
+3eJOkEA9ZlOWft6iqUq6DVBq2m/Cl05G0WwEfB7PU4ITYG87I0HrNuNf/490OJW/naOjl7dlm90E
+5EaGzhYh7luSRg6S/OR9UEyIPYGSp2bmw/vwCaF5AnCc8jrsWkn1qnSUlctiscjLLYIFqQfFuSNE
+iHUIjwlRUQBBSG/I0F4+m3nEDKLcOzH2Y3OuPrKqgB7YtElsE/VQWOhBTaJDIt1NlZTrYQeiYWcy
+7QOx5rbJbwLHMV6dYN+kqNlCYdMGZMIO5Oelva3hIgxBmCOtjQMUR9XjX/7yl0ZZlSMof307pw0d
+MJT0G9hfl/4Ga1SnsyqrF89wtupNBy07ESd9DgH6jno9jKKneNZwrwZZGTn8vebbMqLfKDifl56Y
+zGfCI2rTImx8uKcQKKZTjSZBo1433L4jgUlxXwRToqCn/yWorVuKn36hj0xBV8rWzWaJ9i8UuypU
+pqLL4uISj6jwrN6YoumknVeSLQMXuXX8jn+fiM7n6iB92mN75q1+fFtky+Ifct4RL4p3qOWLCOGN
+wN2qgVkAa8Bz+6Q9G0UxqF9lftPGnuBE51QJsJSAQHV9iTSAOvdWFok/t0UO2iBNKiva2GKwJDY3
+xd9jgcgjyqYd+6ZpGIAlo3X5eKgSVDF0ON+08hhX+JTph2lXvlhSlDyBJYNmGF2hT+EzBKAkVD6e
+R1JU50Mk7OmCLuM9u0Uif0cW/qy8BfJdnRUlSe5YlXUg2c7I8G/Le7AduPyI/EB4Y8AzXdr1WxLM
+Ds/yQy0GG9IBwECpyOsVtLhwISOos+Wyum4Qg8rhRDpRYwtiAOSQsQtYRbY90FhatvVlDWomSZ2v
+qncscgLIm5L2nryhQmdF2/A52yLPlk5zdAqGJ0okrirjsZIpH+jhpWHbKQBzo2xeLinJiceNxZo6
+70VN7RXbElJclUgZQWem1pQmNO0cqeFPYpGcXRtXnlrKqiXyFVm2VZxCie46wyqq6JgK2o2nPf0L
+lVld32g7zlRosKeqrck49cOaCrZnfU3ToFmRBR/Fv2+MES14+OJ5LBWwgWpuAMKb1QWbQZsN7CyJ
+bp93tHRsV8ZqNkO1tFCSsVvQNZNmWcD3o9QfhPTCLla0GUGL8LADPFkrNS8GWShXhvXzcrrMVmeL
+LLqZ0JzejLWsmN6FIeFymcM+mgHR49iaiBaev+JBnMElH51vyjkxIFp9KLIaO6myOI/srp5Bm+4y
+kK5HxLPEWGjLsmSdxFWL4FjWxAwG59KXWHusiSJZj1sApHTYKaAxwzMl4l88TuJjbjPPCA18aooG
+Ekar0xbMQm6E8xStK+/ydNuxhKFWmUclKaWuYj6vs+aSSHmLzA8k05LBggHwzW08Ocs8M+gSVBnl
+mvizrjcOS/NnWlxlmDvOPO2ZdwygavjDb89ODo9PbeMXHfdUwNYX+c2WoRIhYBnFy4ltPHAmCye8
+zk2bDkhVXVzgrgkzjUr4GuXGuoDvLC3ySExdPkqoLUqzMcIK/DT63XfOllGMzCFBXqKPKB6oeYMS
+b6WF45BBB9QoQ+X5AnffKrqu6is57veqspcTqdXRKm8zGMkFIGOFG52cKC7yeQV9VzV5QYmpZF14
+DTFpX+Qlwdm47oFEO5fZO9IfLx/QmVWUv92ArNneug2hxxYCjjwA2mkDxgw2/3Ys6cUi6bxBFxjB
+o+wtbm9kCQLZHr3HyKAKozTTlrVDYuau+IebMRk/mryVxc/8+eS0Y0xcdneac3cEnffLao7eBV3f
+A5s4yA0PS8IcLcMyMvR+PlYHk+djOX+eEdb7LSV4vCHDp0EKELPjKXy4e7WHUwVpaNP11rNLUvqM
+z55Uc1QespoN1PhIXlqtQZ9I4t4RoVTQC3ccHGv8S3SbRVQan9kniv09K8+rsPNsQ67OwCdnaH4E
+1q7Whdb7zCxf5ss1TXGZvSsuMi0Ge2xVMZAZ6estKDZoGoh7Vb3NWisabEn2tYyD6KtfjfkIWfmr
+iim/Lt7Biv4gil5uzmjI6LMlJGhVJ/3TxsUh+VmqGqvsljkAnxrSYYPuaGzvAQBr2ECKL6YeKv0F
+5x8tEIotQQraODk+HUWPAKgaISUzS4A2LZO8OKTruvGquYh9k+cWGMKEb3XQ6Ma3t4djUV/GpG01
+KGslcUajieKeNcZSoUMp7vgnUewdIAOGBTgAzH2HYqgYZIiRj6w9XdXr1rANVfgdpFR8ZJkN+ZWW
+OsyZjhFzHDV750msQ43RPdiGzpZ5OeXj2ChxQAOlVyyiBoTUcciZozOmWk71LfkVbnPYcEUjMpvy
+UZArQZJcGasGYzGc5o2ym7JI6zaGUrPrcKxOv9xpHbEDKflvzlvki6YNUag9FdzuBbFL/h2Z6lQr
+9ElTBUgIini2UhL6WWTAts9ykJrQ5zYs1dIBAc970y7MPIxZlZ9p0GZ6KjrEaJ0sKJ44/m1VlKRt
+Np23+Gdc+zZPZEIyIR0TPtWw1p63tgIr0OrqRBOZXeO0I9iincqQXl1bDIwJEFCx23LvEkxpFLSK
+6DmkUXgdqQWO3VkLD69rAHGQWuGvPlkoaqmrdaNXjHvmqpxU3IU3dnUWy4HMNk8pMYofBmU8DSUU
+fgGf0cr8BezwiJTEbgxtygJq2vXwkUYcncpySIOBXbPcwPwAT4xvl/l0uKzKi6ErSGRnDdn4pGB7
+xlrQlJc6asLoDLWNr+BmkZKXlrdAleXPPex0DWMG1Al9Vh4I6A7sKXxuPRzQJMIB/SPN4z+W1T+i
+2fCdJZlwKU934/FNUOHNldE6Sli56hzYROTmsVFGfaPeg8TdEN0yZqfctcGf0vtlcNhOcVFWoHKF
+tdBCWkIZMObG4uBBD1KNK+HhE70jfUVVk64/2S4WlvRv1MTS+l/zktxSXfV5cnRqbFjdCmkqfNNd
+zqmF+/MVMq6nbEjNF094b08sejcfFdHT7zDNy1+L6tUHi/LVh+59kBVwatzwcwUGMp6dZ3BhDkOG
+A1fj6vCHPu6Cx7wjl7ulXRMhrFLUemz4NmWBu/Q/GxgFHoFTXRnwZ7uj0QjTYQuB9gsSZyDl0/FU
+bHqs4/w1mwWqujGnRgdss/APtPjKz7K6nq2y+irH05vhZ1wD27aePum/XrCDI2uKZK67LxPms1LD
+ZKZWP14h5i0eQ+TpVRxrqvv1PDOlezQCyEe3gACP3gH8yXutXELIouRs2mjzKtXZlPgF2BrgeXGB
+7pg4j1yUL83QKaDny9K9eqkOlAMugiT1cHeHx+kPf7YcdBR2AcLF1OcTvK3zLgB9QFgL68hfaR/D
+emQspNEhaxr6pD31JCtaxo4rVcfFV7l58Ip3Pa/0/Kdhv6PwwapxY+LpW+RCK2nY9cQCWXvFa+f3
+ri7W9Z/3XPtnliO8P1zlNahWQ+e+VeN6mVue5qzZwQe2OJIl1RiTLM9zFksD/jjw3vY15wZFglfD
+Ue2nnmufJUIgO3yEffHWZguSM2eulcsisvEZ2ainhyybaqPNKNqpe54rJk7cl1jmItqs1TSTLjQO
+6l4WHne4qxlnI++yEnp4pB3fDx4MFD+yO7DefBodTfpq3Z9GFg9xzeQ4q2S/ttlM2tHbCnWoyE0G
+rgDU+Xlxow8nrB3oPjqoREOXA3TcAhTKulqjOc3FXXOT93c9jDodid+MFLmvXL+K004pTajsFuMY
+kObKHhVe/sLtp0YgVFuFh3HTF6io2Jfy8JspMUP6GkmbU/4zIiLMluJz2+Eq1Ka7LFyLi9/sx6ZF
+fx2ESFmNbwj/fShfrY3vQhyi69yxkdjiTWXdR8hvVB8CVo+aO27Wy6JN4m/L2CJakpBsfNtyzX0B
+7uR44t6bITogV1bqe9I//VYH9yOXFqxTNsFe4HzChs/DVHi2iIFb/u8j0SoDPNzSP7sD6LLxq/yW
+nqL0S0iQEw9R8s7xE6g50Qcws//LsFt33GC8i7SzNZAxEhrCMl0M8GYxlW5OsPBpaKmzSRMUyNlM
+nAqb2SwOr31nhoZ2BejoU/Xts2HXABzmNEy3r8it2zi6cLwSNOKf5eywAnz/7LbjuGNaIBtqkuoz
++JEc5EG7ZMaRECFj3MQAYz2tLIrmYlOQnE1c5l1eo2tRSQIl2irGYX0VFDaJXOJtqZ4tz+kNpx05
+vVROYef42ZHyXLEMWFsU5YNtDsHkujfia3ajCKPV9J1duZN67/D4CKmVYsSIB6EGsmcs2yZX2+Kx
+G938t9+S8Zqa72tVx77ofy0GijUdgMofwRgCnWerqdIekcFd1wWIx73izRe8+MXG6jIGreHNjAeC
+CHmuXOOoIoEti82aBRl3kFmTw0J75lmrXId8X6D2/Hl+dBGnO78HRmrveMWbWxkjy0flCO9x/Jac
+MPu7dJT/Q7q60d+PubmxRfQzeiwwymRI29qQbiKBCu0tCHqpcK4Na1LHI5p1LSK7c5fB2pl6JCir
+ptziU2qDN6la+VOiiRKwO6K1JVbwrk2/t0k7na20B9hV3jTZBTk8kzszcgSeDzd+TT+DNy2opcCn
+fyxv6BM1YHtDF8NiG2Dyx+hfdDfOGIq83bBY5rDPCRfusZHbxIWWcoHNQxTxAGnojnPr1LWmV4QK
+6d87+fettMRdaLpGmlhGVtMje7Ay4yExefI9pN2Pu6JtBzbbq5x/swRr6dR62owbsStMqZBMyhi0
+hz2k7MZWSsdnOTL7JfXVJQ4xkXz9sufWtNLuA16puEOXa9ybZa/m5tPQ1Wui13I9CDXbs5e4WoFz
+5cKcH+vFol2hff6mjyc89Jk2LAu+767mupsFLmdp5cA5wHuxAS1wlYf8Djotmt493zYDBe2CVknH
+aqzOWxzmDrRcZ6JWOiDzbRzmi13PM3Ms7l2DEj+BhCGRrSi12RVyqQ5HoNMr2/AdlBaUnEDT7F2/
+4gsQIn7p5josWpA59dAbcvkwiBl+8MEHsHSVJxg6rVNoxqRBrisKyF9F66qhMBrpsNPaGQhRVyFm
+YNwZZAgj07M+RdEbqS9O2acfoQWAhWwCDqBWca00eE6qqNY7FhrsPBhzeh6ZNs3lGPL7z5ZYdbLr
+3KYx3szm3MSV3EC/A0UD54ecgVAR/DT6KGCWHmNcgkWexJv2/PDncdemudcpjRfMor1mflpUYzWw
+35CUnCjPNS9eUVu1Ui5prXBn2OwqWyeq34o1Bti5OnAOh+LLYO5B7+8Nc68xDgBZG907ujFRCbTH
+OHlRKg9ibNaDKjHmXWeTMXZeE2+yQjcGtvXuZ283dnYpq+krMBzSWA5zdj25V5NLT9DMzLTXJVeb
+GtNJb4SNPqKe+DEl3GXnfO8WVYvN+Ba450e5HJ4RxWnYssVC3lihUUdkVyQbW5Ovp8PDYefISlrT
+huxuNfsQwqJT8Xa63jraPsJWhha3Jx38RUHl7b3X8GINHa9HUVdUhrekDEuDzuwathqYWdYBcxSB
+hrOo/+BQ7SJBrhzCgtlhrW8D73K/2Vb0523nhXvPxLpCUuO7qDbW9e7tg9mxinsKG+l2YbM2dha2
+VOgpw7EKnruGCTV1w6Ef/4BHQXeE/f39to+2TCQJweckSCdumTC5iAuH86yfH7RnbOSYhCdwyL4k
+w22EcqI1AulatXnaTzfi3mxYmVV9P0bWA7hS/uX1vrQHCCaTUKK2JNNYmnYADYHIItQeS9LS6NQJ
+IH9TficBra5nkDzEztRYJ+72125Bfe5vvgRaY3Dw+N4A1vEhYHMJ/t0X5ZYJ3Veh/b77Vo1/lmCQ
+E9LtFoIx29tx+AQPqPpXN3PLs2q5EGcKaGYK/9waB33MgHf3zpDtWekbubzethntGvb+Q95/uPYQ
+QgcfBzb31GtiFA3ZpNrTb5eJOl3s4poWqUzu1n4Pge0S5pXUhjf6+R8ZsYffll32sTOKhzfY/csL
+8A5/cqxd+3FS22/U2MI8lqOscMrw0ROuzPNXpZfG8ief9uUQB5EOfY7Kt3RSbdq1hL/NM4zZ6roD
+Hkhwu6y0Sq6ylu9sYZyOKF8U6LoVUWQ3Comta6+aC6WnKWA1seEAmguK9Uwz7d5txTO7w2Mvkj+1
+Br9PJoWtaAlRYii1ZiLWVI1lJzbECGu7O5CcTew3t1v3yDvtkPswHJuNuFSp3EX2g5qcSjygZUOj
+jeyOO0yXzfLhwXlGfnfD4HGqRKLUw+02QkZIhAkm0jsm6znuU3bEJsWT7Fyc+BEOfPAw+gwxiIGW
+rouFbwP1nEyoVv8NNHsmuIP+Az/BA4zlDme1+4Fh2r8PaIJdAIYZ6GZ7Vz6gXgPbIdmBCHuDgB/Y
++NTRtbgbSjC++aU+4U4ydU9E9ki5mWe7XJFb6aZVr4h9uddLIt1PW0m86rjRD40vE8XEkoqT7UHq
+dTnHFGMNyb7g6d12id3bnvquomUA0a14V81C0XB7ylIAKHngvVKDFYxN9hqDFL4L8FJlO9Rq2sxB
+qTxRNqT3owi+P7QXUdAESxjzfYliL/xbqDzxaeB0vK7UtaHQVGxHldOymhnV5EDdMpGsKNXZb+nW
+2Vy7UNloIuHKunBtue0qvw6DjJDdDqqhDbDSYbx2pC6B8ta9SAIuLlYz7CxmF9CtRbEc9bZX4b1L
+qhH4Zfk615zutpYLJ8AJV3RzvcRd50G3OPQDbUE/qW5P3Ckkc8+4aGgvT1xnWPVzw5BbcztWTZpJ
+ljPBwD6igLnZCbk3yzeBaR8M3v6r1382W9/iXfvxbzcgVtyslm//+NWDv/zJT5i6iFnia4mejnbk
+6G9fQ8nDb778QsTFEdEcxmqk6B9/s1k0eCcA0INEvqAobxccIRTkgxrt9uPB4FcZhnQkTzuKPMVE
+TIv5RQWy0BfZ9TK/HQ8oMHInc1LVqE91bmVTUh/xlA32qAPFFx6OvyGAPoK/uN4AmLOCAhDoJYHW
+7ss6+ekn6UBWwFfZyiZ+LoDXyy9rtxqdLzyKt1XkYD+gEpiaaHBLjvsq4Vtywmv19Yy/xRlCTg2z
+NMbizTrTXvwYIpNG/JucYijgXqlcG5vNGQb+loAXRQkiV7HQYJEDbYOBxqp6wVH7oBmc3uPxkRW2
+hGsVElB0bRjuYhxFf5NT9Bfg2NlyToHNBhJOe3ELcl6BdH1LhxB5hvfeKR8PdE83SVpo4BXCCQuI
+wcES1B+0Moei6PgziR7Dp2gymUYHN7+I/hF+P6Lfn8Pvk4Obh0eH8PlnT5+e8vcnR0f45OnTp5+f
+DoJeX1Ts+IjLHR9Byaeng9kyv8iWM+51GiVHN0e/GEXw+xH9Bv1eSgjeoAhNABR8eIRFEATRZOEZ
+QoFPEQzzlDrFx9wrvNDNwuTOaiSWE0VaIDMfgsScotosVLqsMLaFfMG4cUF3MFyWWHREoeVSnDsH
+9kFYVq2uo085QVt2IzCchqGDzm9SE+TKRt0piK9OnUGx9JqotayQ6FV08r/ea06Bud7bqtnr4nHK
+NgSnJ8DFIl860NgPZOzWEwGQNt6zoqTveTPP1jn67Fu6FzDEZbJCgcbl7qjvwuLRr8YXdbVZ29eu
+SO39dEqEELxsqId0cHPv6OE3iAIrKEZX4g9V+9iuZo7lkF3AhpO4EzAGroDntsuRKmMNWR0B8t4w
+yxYLzh6RULRdpY7SKFHyo4foHMPjHipNU3aQAr3GTI2xaS4+PFT7DuzcGYkr02HTVnUOKtAC+p4O
+4R3q+u5lWoxXg3c3hvxKRWKadkKLY0yN6XBe5xhrkfo6hAblBqhscJTsCsNPccxDdJLZAS+75PeC
+bJXpARt2gt1QQwsonKsLAMDRaSPg1Emw3sxw2HwzdGdNOeHSmRl8klkTfFKcFHw85rGN5bkSaeWr
+oTopjeQDdb+oLmCLSKTUyGvLQkDqN7Bebi6KcpWV2QVmpMsvigZPzq3m3WGAwNg7EEsO5FcoojEx
+mRAdPBgzEFz5Vm/b4duUGkKGjECDtxfLfIbw0WyQLUPZYXh+gEXeoOlxmaHX6Hh9izr90OKWMo0A
+HNrD4iSNT011dGiY6o+mnQfQSjwWNwaVow9LKSFB5sW5uRkydlUXSPUjoS3b1YHfIEfjxJQYgBxk
+J5DvQAh2HmGGl0TKp76Zs9NMCcIiOZupB+K/1teCvhnDHzyHCsC859skVkGKFK7cUa8KUG8Xjluu
+vnZhipEnQUOlDL4qWHrYC94+NyfE7gmTmukOOXDJMcZvLhZyFWQ4mQytMVpLWU30xPbfUhY5Hr0X
+O1LXRbUD9NLkaGSXTgPIUpo+SZFjPbJwu9PhWKzzpivPOk/FGG4A232H4vdULUzGBZDtYsNKQEw+
+yOYuuuXkwCCGbhOagWB3ajDubUJ+OEMa6Jsxm0juT6PjTmWkDOQ0PfUPxOqtxzVGQR1PGDzHCOvk
+OaC/KZwMr7PmBrvseFWTHZUH2RGFeAqFuBMxvsNGiQ0dyo0/UtrWHH9pU8J6JR+25e0wlINArRPC
+SL/M0eR4tIm3ItTglSOHd84IcEBBBlMhVINJkMnTYbeiGnUAxSHQrYtP/Xd9khg2SArfVdchRVl8
+SogfzCmw/fBxtgbmCjgB3T6U+deaVKnd4yGRXVibFKEE4ADpus1Xh/H9cKP+6KCRxBNMlRtMCCfC
+3YL0Pa9ACpy3Pyad25C7NBCa030i92vaEejRkqApyOtYmPnWwaul83sZvO7sBxy8tNkZvLOQ/dET
+ZrYyRgduKf5eULuLvckxfNv7TNiOiXpfjto7Mapyum8+CT1QxWEjl71tCyauTmzNgTJCxAGr2dHE
+xnrHfUuXdTwWXvKgJtEwwOec9s2Xk19MTt9393FOZn2Yd2ERr7KAmsMGSGxxuKuGwrcBPhDcZp81
+IcpFvSEhbwYyKMO+hdRkcCw9dOzEioIwphv606HFazjBCK0UjIgXwYM2z+pFdd2Fmn1xHaFTYBhs
+2RlY1vEL5ksDD+8FgaWwuy9vUB/oQW2FiNlGqL3wsaVdV+0T2wYk0/leI7L7UgSsyvmUIdx2J1VI
+FqI+yrgzrkMT5sPub+Lvh21/N+zDhMrSYu8f+Q35tvkbiM3LtbqdtRkfD1pGJlV/i6Iy6DKdsNbi
+lmEosdOR4c460Qy9Hfawd0v94aH3sCMuotocpl2UNZIZGRmziu7Bjzreo5uizWdUcIZqE/pjwp8x
+/kp6Gz4HZb65dFvGSSko8s6mGYG+T5kX+WjJpVg5sNrrDoVR46UWWhvnzRgJOrEVfRBqr+MRZYFE
+o/60c98ikEzDmAj2bs0gT/BWrUNoc0vhw9kiXxId+hUPw/NgdPzNShkbHOXRFrUHvvVEPGTjT3+J
+RirB8nR4PD4amkENaVDDX35mYcmtb6iewEu6nIXeBRTzoUe6vDCn1iIddTQv4CRSgkfllkAuIa+F
+YXg6P0IyVdgK2AOG98YfnaOQ4E+KKZuOlT1b7lQepV3UzJdVE1oayug8azYrUIJ1vFZ5zNwtt1mW
+/4qxPkOfzOEhmutUSPMF2RqxdyXoONQKQL79L17/KTqZWHdQ3v7rVw//+Cc/6RxdwrobKaPYYCB+
+ACoWAkl6A4m8wKvO3Kqpb7mJJMYCMWXmoIImIvVL6BwdxhI7eIPlMNBIHGc8YCOFhoI7cHz/YsVp
+UFSqbEqWggmBpKy1riiyMmcPbtxQKVbCvYZv9SyixaZWoayRH7lRrL0Mzzc9CZzokBzN4rk7trH4
+fktl78acFzr1ZsTZlfbow54Xt2G7lGTphgfU+IeeN17nMu5B9Kq+lXzLZbFcZpyLmiM1XeWcEpdm
+w8pYXljxg/37bdh1onv+wVOezdHJXkd57o++jY8lyrO2x2PVWEV6RmLdlFcliL5xuvvCsupGtPA8
+eDc5MKK7hWyzetHAhQ7Z4k9P7jWo6QxTRdJFKUviFINLi+sNTNvRzb2bz2JkEMHeWN1T/QLNmOt3
+Oig23cO72ao5qjAoafSZOOBmN7hSA9d3yDp9g/bhxC55+FH64MHDrm7xW1PeLX5YpOEwe+ivC7th
+PB6PY9wVOc5xevhbT6c09y0pxbF1UQ/DOVEv04cfH3WdmzJiQofEntAeBzUJ9yq7qkp/wad3kqCM
+GnkqASnV/UjtEcXJdJu81tcim+i64NA5OrKupOwgn5ZMwlx4yURx3cZqKLFkwEBHhxYWMx+vz9F1
+ApOVAt+pJXGsxSGB4yKaIwnno7Lh0JKn5F4SIpITeNA4kes9UDuEqkHZNJSHB/lpg54ZPRz/FBN3
+uAz3AIb4rsivrcGo/FacSVK2Ir2VpOYx0QOjfapmzXuLG0bPO0obAC+Pf3pkn1812rLG9vy3g9d/
+oROyzrT3XrVcvP03r/7PJ31bqjhgDciFSBwLauXwSUfUlJkWj7uxZZisgZv7VfekKv2KeacfWH2m
+A/qulxnnTxsMUCxsL2GWLi7zG2/jJkalg6yypNV7MkeJSH216mbuRt2XCAb9TJkKSMZWyiIqvf8a
+Jr4T1hUfRmcYZZkKjXmve3YePZa9xxIasCxlgyujx+j8wSfrWGpdVze3mhWahDNIkfL0Rhx9JCK9
+bpRy/FJ1ifnzGBmsLCcWD8820Gj0oQLlQ6z22EooJ6GuonqzBGjO8mV1jZ3BGn1XFQs6293oXD7s
+pwSCOQ6coSDhpAtP4o7+MUW5EjQwtimPBw8v0NKNIPORlVgDN/u8vawWPNZzWtmScId7RZ6RbdoK
+hSr2nKrJbarE9rC5r2klWYm3Kd9Gk3MoMD+Lh0rIHVVWJ7gYhAZtHKIIaNAi86Wmj8jhHRAwxSDX
+sf2pPUYGcTQgaagB/FYDIljAtiycA5Hmmt91p3I2w7LQDIXjalQyBGqJ/QyAhrjQVX4L5RirAPOv
+dGquETNE6ghatjrnSFLUGN10QeZRnBdzd76j60vQNgwoGNOWEO7PsqyYsoL680vTCAVpgwlWgGQ1
+vAWEzSnPEW0unOG6VsH2bGLCUJ0Ylhl4dbaimGSPE3IB5u2K8yMuq+qKo57qbrkhgh970OBPowT2
+aby2VoHECh/ZjZXCvaGLUhstqrwpY/SJKTGC6K04I0oPGIor3GKBd7yxQZ20oozoBQ9nBJ8VjnAn
+vMXc3Bekdtq4fCwbIqINlmxTLPKafRnPcklIRdOqVtWSTDB4FXZ5yxgOkpfE1lrUJCIAeWUl70UZ
+bxmCLZtTjWxnRXeyR9hC9Q5DuyxYvNAkyGN8mUuEMpm1SOT5vFzoSP2rarFRsfHIxRU/UENeTjAb
+085tuxKfJnVVtQQaYVoUAfjz4dX1wr8YhJYWFo86tb2dQy1gquC/0pWogP7mJS6Xwho12xJ/u4Eo
+dGWNDUqJHQgdHYhN1NMU04JaHm66xf7Mjsi/zE0r+OLcuLPYbIePo7MLcKfLAjg0rPhbQhNzYNw6
+7FbqnNYXR+mV6jxNccNRSV30CrhKz7LnS4C0R2HwvyU7slQ3eLNbIKdG0wRlRRtpTpN7oT59N3g3
+H6YV2FMVhHGs6sqdka7Go6KBOoSAHInSqoeieYryDHUeU0ESKQzUOiU7yDFjtcZOuzZ5bKQ3+hW/
+9lFqh+3wCS+UJNQCakoZhhOMvGSeJt11l7q3m72xTULh16wwVGbAEuoycFRoyiDjsWpYHkyXVTHP
+rWA9FqX4NOKfmEjd/uTuznDdgyBUMKV+ikdtx8FWpMTJ0enWiIycBJk3F7KYI7+WuqFmKREr5YIj
+zGlARsCv9w/JE99rknt1GmtLojNcyxRgL0/lfOhRx1xH20VSoBfkHQp/oKYpiCzYvaOK9wK0nFL6
+7XJLHmlI9m1TcWCeQml9V4FC/IAi3aKkmJC0rNWNR6yNwTaQ56ScKB37nJTSts6UfDxWOqulaumI
+GArVRaNul6lcthjhvYtzjpViUiu90zdh/QoHIJcsl4cUzoeutrBtiPKv8VkLgd30b2hYkm7wteMn
+ulLiTqZffqxvcE+j+FME77M4tLUxq95VeF6REiqargXFY3iic3Ik2HGKPBgfJ2mYg3LIfMki2TUy
+2prvXQ2MbBB5ajkjpX5YDQHC47WiF9tk0XmEmcAJdG1fluZsM/GmvCMV6NwWdyCCL0naSzjkIz54
+2a7a5MSe0dN0F0kAqNsnmXvZf4JlXm/y+ez3MrEa6SWwTNt80sMlA4aWxJ9kk70Gb0QlDt+RFq2N
+DFGP5RzuwQExw0SgwwDH92oTfjxJlaHiYlmd0QNk5Wx0sRO7dmhCJWkgzOsMrWZ9qRwGP+xcBBkg
+9M7Q7zn0/28PdfsW4YyVpCVrqlGfNY8dNAROZK00Ia5z5z9nBG3ZDDl5/Vd6VCkDx8WCcWn1kvKb
+2sa3iZZkJT/GG5r1XotZiu41EuHHrmii4KlTp1xwkGQBUTY3Tqf7UAe9qNZN791hhifmzSfkgHzA
+5wvzTSu5tfDWI9nCjMzRBPMQoOLpEJC9zYVdkt3opGrEDzuooafdTelhEDc9c4vxPuj/Yc+ZGKLa
+1Bh18Ovyeqc3tWaHs5nKjDtb5uctdmg9qouLyxa7103vkUDKET06a3Jf71CiVwe2KY2YW36/Vmg4
+U8aNkmYCh6NbmMTdDkm3SWjWqiKA1AJ+VC72WbxQbN+Fq0jAu/NDkY1uKD2FOfJogmJYl7YD8lYf
+ZdsQ6NzkHu0Gw2YJBVmzPti5gq3CgRXsrt7AkosTPIeN+XCSL/HY4GP4nDiN1VR9Xe8zU1/X//9E
+/SiTBGjZNkeDAzRwvC6z+tY+7ZlOB1d5vs6WmIOV8Ezm/0ZZguHTGnOAYVbfMvqdHM2A6Au0Bj+T
+KEaqs5gKfpC091juWfkOc4pDueSfvFKpFPtuXIAW1KBJYaB9JxnSRzV6ooeoqktZbEOwrmZ26cse
+ztR8TPcgnsDmvpOCApNlOtUXMeMw8u72s50w77YxGRjfb1vBD/bm9PvfVAZs5xWyVovXUFQqq+FX
+RWA57Ef/jxYLof/Elxnud/bY1FoQLzdnfRUPt1b8crPsq/jh1oqfF+/6Kj7Y3mPVO8Z7Wys+r67z
+ugfUfljDfIDn6A/CCAjgICPAN2mnbC8joGGGW2IMdEvfhalYK3bngg2yHQQ+HsmA+9nI3u3RCKBB
+GYnV3h+SL5HQTPP0/YVmHtk/L/5mrRRjynqcLZcYB3IvDVjKutaOqtpt1rFOhCxUiYcRtpDG39d4
+cbdd0Ydiauuyf2AziPhSBZgBOWw55YJsoF82fseRhn5nL8bzMp5wWzz87wLz5xRPYkfWzrYE48RT
+WjP1GRuk/y6/va7qRUCWveI3SG6uxU87g9MrhGWPC0imtU5WmKyD38xdpVkvf5X0vB5W7i3QRofH
+hYhitwY+OZFqpzSAsNSv4A0mibPm4/5UAwGy+ygOmTo6mknWz7Z7rm/pzuJ7zfReMyIjpMA4UhCk
+e3XOLXgN9PB9ky4g48RrnlFPPQ6vEP06Dde647RivXjrZJqWA5Nq4fBDVML6py2INapjgR6aQIWu
+RQ++FjsQtujB2OJ9UYbOQNtRttgbZ++FNKq02IG2sP0wudekXesh81nbcohXDAKqdCDj4xhg4uvS
+AHy6NRu6G5PFQsO2vXGX9RDkaZch/dgnqWJmIpxZZyFMPip9qrLdk+wQMt3XejDd89Qdwm6Mkd9/
+J7Gfvy2/I65Tg6w5igIHeiwE/bU4OO0hA0nR388pQHADptLMTXnXBXC2H4/tJJK9lPPfyxl8Zy5l
+pEnXfO8MPrXO0gv2otQ+c+h4kzfGh1jJIyP2QOZ44g3FDoUxt/bdJz0BSawOWDxcjfBMAOPUzGZD
+Pr+LA4KonGv6s6hqduZyy1EeDkNfNtPTqcTibp7tu832DzvdPqxO9h2yc1rv/0AcgAw9L/LDQq9S
+dugA6DbLpXHBINuPOnSgaxp7nTtQyX18QCiYR5BZ4JvUKRdkFgdRU6zWy+L8Nor5fgnrHNH1JdC1
+fJ6ip3Rsz0HCDRqc2DE+YqoF2FS1ORhx5zauU99seYh8PxmnXxyvU3uPTo4/mRw+PLVGRmnY7IuK
+WRPpUX5qVbW8VlyuR33sduxRbaIM4YM12HqUYnWQ7pEnlTlh8NrP799coKm6uCj3pGoouQ9Vf/8t
+cOeZSWgWgcjxD0yiv2+EfK4OAX5FXDp2cUZjXKmrEmy6bBwEGKWcDcHk79O111tMdVUttrtpQRen
+bvltjll7OGVBCyGfrMC2Yjto/YFFAiHIz4tmntV7ne9K0X++JNmhQ3WLHqd9jwFiuX1GR862UHbb
+6Se972AAHqadYmPsScbPLsEcwUDHg1F9e6Olbscd5zsdJdV6GDzTjSgxSVFOKDmJv35di4VXjd14
+8bJi0y6qTatSyHHoKJQISMVDYp9b7s+5uvDomiVozPPLHJNBC7Yphq4MWx3Wdo02/JhvTeIFD/qO
+Qdj9AiqZxVMqYNGaECp5MGPnMRKjXGmXbcoyrrEw6roBc9mgPZHo0dgTHX4QNCxuX+udpKrO3VN6
+3rlBemKpux2qCsxzcNu1DJe+es0UkNe1ogBz61YiH0WKGnqoFWn+4P1/QLZ89PxZ9CCi9ITRugIh
+poGH798gUaOWVLVEL2dWzWW1WXJoK0nsMJFLh7gvdEhACEvaiJH3x6lFEwcsdQ0vqlaagCXJHwZd
+467AILF78O5CwyT9Cj6mk/3J3iFFubtmcaHvQ2PqNpNPZncibYsgJQNEJwGvCdtIKMRs2ob1WbPU
+cUNOholPpCO6j0xh0Qr4m+FFLRJYkNN384EPqUf27MNbrvmiwHDkxNvw5nobLQpOJkIRUKPo5ebi
+ArVezJEbag+vt6MSLRzHuphwlp9Xda6EJXwpuTkOD8tqlV0U83QYWscyVr5aIRloVs1F4mYZd6lL
+3nUvEanc74ag3PzLThLyAyFSSXcK/XJC0qQ9swtso84Dgd4sQs7OqPZImv4zK8G5poUTZd4zdr+2
+hp7HWsU0+bax2A3n5PCWOpQPrHa6qDsIX8G6wbzC9nVClrhwWZK6kQx1LzI1ORJIqYJe3Ktpv7wZ
+pU4o8Bs9d99TFKCoK7z52rHBJRueo5hScGvQKu0oVlgO44lhKrMo+vRT5QCq9vO0R07AZiTPOWXj
+45nLb1o2BU9MO56c4JuT0dwE1Ry12VXoJmp9xI6+f8N66U17cvxTiWCibn7BQ5G2UND7Pcsd27eL
+0E7xI7JsXywYDAq6kUyzgaabGC8DFuVsFk8k5ohchTZhL86T7oWPT/Tbi8Dbj/TbyyQQJiqmECus
+h7FsOIQ+og+xLYTpE+F78o64bZJ2Hybn4vOP9YB5Hnllzrm5C10XY+x8bJco8H2nbTyHhIdU+ch9
+ZTGGh/c/uv8x0NayylpsgCkQpm1IrMetd6PGZUoJUcvogC6qat3EUo1LwOY1ijCS9/Eoehh+w8Db
+XWFQoBNsEcZ9SmP42IUlvsyXyyo+wfdEApdOr/HF5orPYy8JC/Du7X/5+t9i8BVKBkA3Bt7+yav/
+a0W5pwb0nXJx4I6+JFbMDIcyQrmx1EZkEcT4nHgDGsMgWhmjdJAX1Rg+hw10hfpeAbyh/Oih0Dsw
+kRbvHFEAV3oxRApIdK4xCmmFZB6P2HZHmIjL1orABkVD6Rf86+Rl8JKie6u7anBc4vgSDZt2Rlkh
+zabWm6LWrtmTn1Yn+7DClFq1KHOD+Wr6q65LiXzm3fxmVIYMCV9V7TM1iflCNrhvvvkmYhynvvC2
+vjbWTE5oT5yRAheOid7yBYVhS6AkGlLW15tiIZZk+NS520+NqKvANADKK4E+hO1tQg84Y4j6PeRC
+FWW0vBxa6OYUN97wrXBVnBSHbENorsaIhTr00g+PqYt6vSemoCRn6LnQmLrYhSmd4Edhih5oUn9e
+NcXNc0zhwctpjJ8xr5tF+PNLwKSQJkbcGnGjuFbn0yMPhfNLTv6FuG8uizUG/jChvShgFzFmysrj
+YM99F62yWwz4ITFdOKRMhqE8z3BSXWMuv0L1Va78z3H/RuGtA4/nQjTf1A2FHhnbo9CfgRBZnkXg
+ikWCfwy+L9RbghheC26d6ANejm6dO4ZjQcG2gZkY5tNltjpbZNHNJLrhSUfx6QqjZ05Cl4a8QuFb
+QmEqqpoxzSiJr7ALjyJaeA4l7VOT1o9d2YrbmGEssqstS4xPB2F1ZcC1V2fVspijyHnlLjSTACsM
+jepopFxbas7WrSFZXeHrtlL5SJYLj2dT6lpcA5JOCnPaESBItyrEDFOWDVgvRAINbjTSl4UsBzAY
+tgObWMmys6Zagl44PfYXFue/8vBlwg/xAmO8JmQS4USAzijSDiNT/bkU1Ds+gZoHxbqFj/x+9yeK
+TyaXBZndJIHU0Qc8Jp4VI0M0UfwgpuhVy+vsFqOVcRPUqreql0YVdGLJSHdAN0vAO1b0r8svF3xc
+KLbocDEO7U9FYRybshUfqXztudlmNeZvVJmM8jXrRUk8HoPwkX5YgiSQaGhHkeelu3sSuIMO9Yv+
+aPMs0W7cvbmr0zJ7B9qxiI/48jTS2zTQEbd58tBRrvCZ7tvliE7var/r9i7bitu92sD05of9c7Me
+APRwMHj68ldMZ9w6C4e4r+i9DgVCb7szubcAybQfcjNWLEsJK1XVBW3sbEM4z+YUG1KCAXMoLlpu
+TLkoPHCmGIupLTOur2PuutEdJfwGYevLoqGQLCxG8DNORO2xVY5pWiGzlAjDqThs1DmHAFxJU8h1
+ZzMEDHS7RgeuAvLkTF/wwQLjMdFe3Sj5QH1PJ46jP3r0tT6/7z+ktaPEYE0KERU6n+1LYby1eSMN
+67ZN6G9QVAjWkIelirjLy+7JF19//fzurS97mu8ZtIPGRVGHkKiqQqXxy9mzl58/e5GYdpJ0vCKT
+gdMUTvA+bb148tc72wJ1rGmbba1ZDbhVQ3IAH4LtRJoP6Rdf/V0CHNeCz46iRsGKsS3bnKOWxzNO
+UIyBTXGF6rC0vEiJJyguNDbw03MJPEerFu/qiTwLgiOG+8MZA65Q1ZYA+Yyi8IkBicPo2TWuq/oK
+t2Zdk+IYZld5aZoAHUKCSDuw6c1vntU1hsDT2zenvHTrg3JbcSNogZdL6Zm1pSqWRoEIycnlVlBj
+rGkY8+4mg0INqkNWrXH0usE8xdfAaCRRcYZfgbOue6Rp1/Sskk6G1A6rBg3MigY3xSBFvSzF0Yhp
+EzWastohbZc2QxccwtHTp7vh9jCekn9y5ibZ1PxBumOuCviZXy8SLyFKBx12zFkUPNhWnO5q3UnG
+2MnWiLIaiQZbI1Kz9vprlJBEaUXSp7iSawrOQlq1R4/D7bdDhuSYWh7mq3V7KwHQGyQXvc9a+nD3
+7NUeKFvbd0X8u8yay96QXfgy6dEUZrP8rTbA0A5u21yO5VTB86x8KI+5/E77ADdzPF7iNT2P2XFb
+Dzvv1DiPkfKbhy7f6wVYpRVFWyjT8VTK2A0s210N6DFjOmkzUN0GMgW90XRbsRQ+UsYBMTGVieEx
+htwmGqKoqshdOIkvCPrYWtzLQzypkRqklWOskN6CUVGr/ZVihtRx/NcYC+53vsNl2BxkXVCKDkgU
+45hDGm37KbqdJaaGoZpx9HF7TJZGvqremUyB8+nxSJJazSStiH2ubaYOa2FUN5wYWMpmy0rogpL5
+ToHg2N4BmuvYwY3dj7LLjCSdCSanpyzO0JO9KRYSzl03BFswN7TopQvWK8ksAs3gEIPWkZBVRhzX
+KlQaZdQV2zGI/5EUj8I1zPKiug6GcQmSgMOx55cguiQff/xzmYIUuqzmLe7GRz87OhrsZ75RqX8u
+N22xHNcrxLyrAYZv7LnT7Xzb59pSvw1mBcje3wawDVMulrahZ4tFCCev1x4kh+56IxjRnsA57FaL
+T4Ygj1xuyivKZPDJw48f/vznYW52md8sigvxasQm2O7CeQwwXnTHZtxRVIKai6jI2CKmBsgoyHBI
+L7I0waB9UA2LjkGay+x4GCZMU46Kdbdz9qyczRgy2C9UDZdo8KmVOQRqGdSmScezMXH1ulEU1mzD
+YsnnFUa3xkh+0SX8w5zq4ktxr6ZOh9E9DebIjrOqVA5KVhXXZ/EWx01mTMeBwCAbbOecjI+JJpe0
+L7QTFA+j3hJKxpqeAnojFdisF1mbJ9CYNRxMfLT0/U27yZVQRmdix5DSfWZFmDK2s0uqKx3m2tUs
+lFJwXi1BVEGWra5XZvXFhh36qalbvJ9WVBtuAL3t2mYyGXjDyyYPmmqVP8AyD9rqQfaAlg6e07sF
+b262iJkUFbxTwftxKhR18B6s/2PVRWl87zqKTW3qfO96qjKtkja4yYEu0tVIXBOnIQ9CykgNdaQH
+MHLAGrG7BDcCy/fsFk9cPJljyG2ppnRdv6GhI0bF6lVM4Z2vOxtBbNeXQhROB5oK1gnzg6IE7lss
+dPh/9kRh95qr622b0Rodiq6ux03eSlT6xIXJxdVeWY9aavKExnAaYt3hoOesqzbNHlsxufm2ZMhA
+BuP7yIzjnuMghi0es/u+u8AQYj1qvEwKqOFSzp2WWEhATZaCAaurV6d+sHD7HV5TdRZrIE64Ox+q
+qqZkMwteySZfx6Ooa4qH9RLQlrV27HQ+vJeobpp7CTYDf/T8Nz5JCQ/HCPtGrzKrSJI7wkeP6zY5
+mU5IYLhGC02MhWIxNvmHYF6wAWKl+lSBByY+XGbwA+s2MRYGttpiEEhS4rEz5fU1itPI0sHpti/H
+6pWrv44LvErHHgxJwLcpgMRoiuMuFcpdYhrAydGpL3c6Tci09zbinqlwk3jTN91HmlUzym7gUNO+
+IhwakV4b4aUlMIUZRT8YyvVI1RvXmLODlnC47HlEjkmHx5Pe7cThybLmzfc4DrOGXvB2NYm5w8ze
+clJMTvsg17h0OGx/r4pYehlwmHCQ7+5sFAql74GI/r0HqSi4Ablgm6QDhl8Q/Yp8ZjJ/eGkInWRq
+yDmIm6HfAw2IUgYtl1GM1WLUGxxTJsrHsPBBNhurQ9/pMariGzw0wttZCD55WWEMeyoieWOIgcrN
+LeQkeJTUa3YOGGq6jMK23JnTAMWebaZmmWLX1imqXUu42wm7MhjvCnx+asPCGEUzbBID9LBR+HYB
+rFtQVkD0GEkoBx53kB4ejyL+F/bGUHtK0UDTqtZJcdqzEVuj1UX7CsoAdcH7xz0rzI1XSAFkarL4
+S9WJH2MionAn4hrdObvepqcfIK2B5rUptd8En9DnlL5Pm0nGXd7tdRs/CHA6U0jHuHpAG3sXRCg0
+6VO81M6or81iA9sn5D4S2Xqw5TV06EnjfBkMj0H2FTg6VpKQFKHzKdPVkHwa13EPOyipLKxjstJ5
+/iBY9y4+NdCSZ0yKvPM2zG6ijilH2OdUZArQ30NHb1jeMhTOq7JFRjRCB4+mOGPrGogmKmUYww3P
+KDGiS7Qgmeha2N8WY6B9g6ZY+q76rD4vMfsqnz89/epLPBsHCQkep/2yly0DbXECIhR5VigvLetl
+sVxs6qWiINoFuntcQQe5+jAR0yEUy0RVTkPnYDpkiy7luYgi5ihHTY03Vxon7Xxog0LzxhZXLpVf
+GCdvUy7yenlLecHIZswHjAH6U1GF8MSZ0kwa1yhKAN7fH6XlYmuF7LSUBFzl/MOltqtD6sK2Cq51
+qmnxqMGMT0CIQbM4Fuf9F8+CqcLY7tDy35ZmRhE5gMq3Q1xRzKI2a0pbveizYyMSp8ddA7b0ahm7
+A6Sg3Y+ktBY0xmF5SuDGEh9MuY6XqmJ9S/aufOFga5uGzYcP82Sd9h/Zuq6Me3lL1o5GZXnWCM+9
+Ed+tbqxr8t/Kr288tEjVcNkxYJg4dwqbCeZ3FpTvdMw87tlvqFHbBfBGuzImaUh5sBoOkkRoim5G
+1M+O5vqIR4Ppjtg6UUICcunAX67EKLUN0Votd3TylHwM7hmX9GmBtNis1uogEvPonRVlx4tyXcyv
+DF8qSoCJYMNTQ+QlNmCeufh6q7l462EN9zpGAAW2cwLv7rbc1ZXZez8M6Ahizv0rfeMJEy7qzRdJ
+HQQFztWE4rDr1OrsRV468t7pIYh4StZpZyNZG9D5sjCDvsjaTAk2175gQwWpiJmgjt9qfEY2KGwi
+mCvNdqQomrPbNm8SbDLdx6JoHB8wy2fTRFR/uONcq9st3jfr6/XucBIiESvsdECl7mBokKp2h22l
+IRzR7ZkLbU7Ly3mFamXSe36ycoJmdgNfyO1wF8x96XzGbAdIq+N2xnlWFSiaNQ8cnyEuwmV2q5+6
+isUUffVQCtiApVtOn4/28YPk/Oy0pMPBbLUr4pNvnr18FdLE8BYsCtWLgmI+kNj1ABoUTrCwU6W2
+l7jLPBCiHgdaQ0PBMoN1VSgfNpJikIWECHjHmMPBSoKeO7LL7GMG4aLs2Jaxpn8ojI1YOTsrRsmZ
+ziCs0iRrQYewlI5xCLfVRuw2eIfEP8siOyTdAo79E7BSi5ucILie6yy3tmNEv4FkK7v1LBbQXsBi
+oQWoMFEGzjssSSZcx+ZMuwSOtdoY41Qv4BB4liYRcBLGKX1hVNlGZHS+kB6UFF6qVkZbXOTpMqGj
+f9k67F6ALH8QSJbbQWny1ig8I1Z+Qmo0lAsoPexwoJRm3ihpd6R2YqU36pYSKwFzaqgYpzhuuHOs
+g53hsbp4rOJjyy3WOKdKbCc0BVJgBTy7Mz3rq5iLHPVR5J592rruuRugd5d4uMGqHZsFPtydt+tu
+jSZoAuSWu6GaNKd+9tWvH33xQ/QmgQuRNlLTr3UrL+Asbt3As3yzKvZoszyfK8z16Xswu0fNy0X3
++sxeF8S2uAOZ3p3LYks2i/Vq/JbF+/qymF+SEQl2Kfals69DNeM+zd8MQtnjnI5DSzPbxxCRzUlA
+vLMJInNNELuSzXI2Nsk369jIrSaaNtCCbanhwBPYU96oy9gK6uc7oPZ6W9+ury40+oD/XVE04RDr
+slSR57ftJd5RyeZX2UWuDzEweTbZjNBq7e5Y3OyYvOrli7aG6Zz22DTOxsDz8RC63qxhK100QjxN
+i+7umoSyUl+/Hq9vO/bG60vY2Mx5IbI1GsMhO0RhBAdXkHphorCQhToSPNHZLjkEIQfGEDIosvSI
+BlLFi7COQxXRVplE6PQyqTFsQpNzuJKuB72LtqAq4oi/O0wMeLNwk/cpNEVjMJNIs9retG82Oxcq
+EpBia5ZQ4CBI+y6+avxxC3cbiGLX3Mh+DhneQFH1ELRvdf7ywPN6NksbFixuoaCi2UvOtSrLMVHi
+slyU0qMPJDYCvDk5OvXyZ0s0KulCLo2q4kNg5Z3oX3zWVVKs1iMo4OxK6L1pzi22XhJf4yLgxIju
+NXE+tYAVT5ZSOnJ0ibps8wv0pla7F6jqpLCKN3nVHKqzWGrC03W8K+IABokpO2+Dd33PeYjuhcVg
+KCAayL06Wm0a4gBZqQZBwXConfT9bo6HbaFbNmhyzlR3v10tfp9aYoPzjoX0tUM993o7GInKJtTr
+cylri+ArlMSTuTXU6XjLkOg3/jxKP4q3jdw9QZg80rRsOR3+DkVgUJs565LzOWh/WFxi9dDe49R5
+hUnm+SVdm4K5XG/aB9gtALtZ0wTBGuEyzVZCstTnIP0YofKrr5989cqzZquFC8KtLFrG2XDkGjd6
+NpMu8iaDMA/ljUbv92lgf1FqMI6qd49xqGDbvUqP20n7RnftWr0s/2RVut9nBEpIsBiZpBO/TveE
+HZ829mlvftNO41hdJd8DRNUC/e24a/X4yzTsYYef0EWJvLnVPtjj0c3tr6t1wJVYTTi0Mh6aI8e9
+LgAcoLCtBLdmDqr/SESpVXaVIyuWo9n8h5x718a3bURMpX0OtxaBSBW3LXZzt2lCip0OQjYve58f
+WoLJsPeUCzs4iK5B9iPvdVr16GTTXpLvToOvVpjcqs/5iCrTBU6asjXa/dR0YFjmtgIGML8idY9a
+98dHB7JTCn2srn8HuCm+ODn8eHKKfSUxjGlOWTnWt1XIr9Rpl+pOfFc6Om6St1YM8/8Z46ShSrZv
+s784xVQlKP31gG0a1xek8jXUcSYobIl3J/WDnZPaO/SHp4M9bnk0jUWz+g6dNLPDEkxbwZY2OR9W
+UDBvguIo7zUESijmgKyDkRqlpBAfhGl8i/FxaySAXQtvp+80LY/LjK6rzUHIqlaRhnxRoRrW5JtF
+JWpbzzUXJ8gqR/1GGS7MMqSaXkzBK6K22OwPkCln/5AG1skNRgrke5eOQKYTX/QFN+g5GcqXu2cg
+bMwPUIAxbd42CKdl1H+HRv01Wo1n1bpt+qwUGF2a4ziSSyI2sqFoNhj8BmNpsPeMOp0befd2cgme
+ytdI5foJxQhG3sitdfV2FOzUcR9IMlqvKMp3JNopV3eJZGtgaTBqXljOI/CbzZlul693PWc3q+fP
+nj+x3bTfIUFka5xTygP2zpLLNc5OYsYPO+m7j4FD0GOnYewbn5Gt/kTTCzJTcgKijrx5sTwssS/c
+6LFxDiM2p9g9mxIN0bl7U1kVuM6K1juRCxxzcuOduBA0+8FzSg3NzpNK0p9aZORHXXNIGBQYX2Bv
+MAMPggPv9gHHEenV8dt8tUBaHDObrXMKftjaOtZdMi+6MzXqXiCn987iJF9zCpvBbJJ1vnqLCS9z
+wkacV5tyYZvv5ESA14VrNrAcw54/evU3rqs0qfqkrzEEtibhzl6rlS61LGFFi/8g7Vms6rWXDVsM
+M/SyyGrXrDfPSrHD0QhGYqtrdJRepzSedkyAOxTEFmDyzjJ0P8QWVCQPtGjSqSnHGgqNH2NNY0Q7
+rILl57cXULhXO3QdigOmszWTpLnxHvYd3HmGp8/o3u/GLrv96o0TwM7Ld0VdlScx2pPjU3XL5D/G
+QR0njlk0KaUlTnjvPuzZDGmSVXK60IWJ/tBAND/k6E7euRrkl3//8tWTL198/fWr+LQvOlC/BBK8
+wbXdJUOh76TOx7BNJPG9lwTbC4DtXjyyIBVr33aOwPZhis/BTZ+GkJItUNQ5iWPcApwZg4X55JtX
+etKECDv6ac8F8S2kAA0bUpiE54rBSuJ4lA7Cdq8eaqBDg8UCxQUoxC31oLuzaG5SowVT7D02TmF2
+RGox2EwvYe276LzywvUmO9m9CPJSPlmnk712iF5D91ZGsFUJefT48ZOXWy4M2cvADksvyw93HvS9
+RvVvlbeXaDLmp6l7j+6ywkD7NUXdmfQf5954C/lvvv7yibWEty5dr+4Q637+4tmvnwz99YFvmJT9
+sQF4iThaWlB7I7TeyCgPFNc/oO0wW0rMNW2TxAAZSN5+LDleCm4bEnhvBq/XyDE8nHkHcdxODBJx
+jjIpbJHmvMxBTyLyNBTjKBgZfNs0G/Ti0j5Gtidj2LXTWnNKyZIWUXTCz+QExc3Yw/CQaL9y3SLx
+KUsz+A7ddrbJMc8tOcYJlgkye95c0oHzHqjB80TQOxUeqk1NklvPvi5pLWTgjrDKIPd4QMhLinw1
+duY4DVFi2Iiv8S24ovu0UxQ2pX0VHUree4iXpzbOs6t8xvF4oQ9ZpbBP1fl5cTMF5YtOdg5jd0JG
+lD99+tE24Rbo5GqG5+OsCRz/7OHPj47SCWn57XUVLbLbJjStoJO83dieD+zoqoIGX9As4clA5kRk
+cw1l2U2x2qxARsNDZ1QKpTaeQjXNZsUyJ9+Y00pido4N89DH3fzT+ZpivNUWcBzgxgZvSX4ECFsC
+QMDDQ6zo7pVK+uUwJ/23X96fnpzgfZSaAOc4CdxgIXdqLEC4VIGZNy1H9SU5JGE3QpLM5WiOcZQ6
+AJOAXKoobUH7LTR05mRQlHbuEBHSJBhJzsoTvN6n2jjtjQVpnIK3yHsD139y0zJGFCUJZoTYyKJA
+2VzUTS0nHSMCZHJwZE0LrfgnNxyZBAWViU+60FeE14MHfWKhzL26ohQ6QOc2vKkPHlBAwa1nPg5Q
+mH2Av4ywpifkHfApAlESsN4www1O7YZJWQ2MvWkZkZTlu5Ze7x+nP5SPbdifVu8C4nMfaKhgvrPK
+s5J86oDB0JW4De8/2QUokSFMa0KYCj4ndzDNGSriuoO95EP2ybBpc4OOwLiHX/HdLhmMM13sFuhx
+qShrHRpnbFGKB3uMFtN3h4dvxNKOky3uIASJp0qsbtcUkp3jLWL84Y5GrNINq0ZHUWxdxAmdRaiS
+zoUdoivsba9wA7oJuQPRUxlZLtD4jPE2U7VCi/SAj4JgaV8ladQU7UayN9O1BeUPpZHNOY1CpM3B
+zrACIVRi+F0XwtaZ0KUZYOGS0TPUUtFcIetv8pxkqcsc1qUjQsG/BhX2rAbCf0qRIa/DdnwfKkVr
+4vxEY0yKMSyg61x25UBD2kWVrMU13SotCxDurARb3GI67rnVragILYk0Y9u2lv23Ik0PEpdvj1jE
+d7A5cPoUaPsCb6DUSYCkUmdlw6Tm5PBpCScDT4CZ/CG2FDa6w7NPp0ooig4JnB7VlyK2khTRzyT2
+UuNbDNW5PFc+4HJjtLc0Bu/Uk7pfHVHmHVkXLRlnTdI+PGyPMeRmP0/s4+E0oc1VsXYETT6nx9by
+xX4Kfj+5KZLjOAC09niloaAHG1uj1x0HHi+rKF6ex3efAnHSpQXC8RK3gQ7K/VmV1QvKrVVv1u2O
+KB5b2poQ7wDQ6TyePHwcvIyi33B8A/qGh+/bDSEDT8ihPBdWpQ4WMJK+eDXY9ofXL5+8iE9tFgct
+bW5GEYZeXu5n7QiLUP39ffUILSnYVyj05U6bqNVyLAJwbPDR1PNITk03ZBUxGyGHB6/nJxP4pcLi
+HMZ0bAV/4bdquh+N6Flf0p3ahZPpXaD++mUAaIeZhloUESABsEZRsN1EGh5FfpDDQGagNNC9r9Nv
+lDDZ0bh9Hd1/r9Ls2he3NdwTSf0lAQyhLY54CWR6meF1AVjOF7ij0xEZFT7HGaN58UMoOqg6l/mj
+BBn7XJ7dFWuRaOB7hlsMOxkTqCKW7RFckVN+WHedOsUIVn2dkdLK2g7R1lGOuHh18vBSmZOjUzz8
+Wa4vM05hJw85M1+c9kcaHtiOYOxupuOoDGdDDAGVhuJEc7orSXaDXeNGnQ7e/tvX/44yr8mppfKL
+efunrxO0AFwCjzxc5u/QhWBzdqgEzkvYuZcoB6Ke//bPXv8ptlFUpvqfv/5LrF6U6D0J2xuqF5f5
+cq3r/Fev/2y2Rsprx5dVdYUW0rf/9av//R7llovwkXuIyJZSrhGtl5uLosS8rHJMSCfxmM9wvL4l
+qUIOc1XJMZtQBgfR4Q/1A23ptAOcYvuHbHzATrc42lm2WBCKEh7MKiuzCx2HG4aF9j9Sw2S0IAlk
+C76ygiZPiuUDbSDqUZujtqJ3RYauNBhVqq2oJad1LV5yz+w6ktL1Gwc27ayWGHiE6tBVBfkLFjn8
+TIyxfINylS3y6GJZnZGZOXuXFUtcPpGoxyS5346xgwcy47ofstrB5k0UUjSRDF5kfnRdyCSmHWWr
+rdZMPGjWJgF1YZKx2OOYr5Ce8xln63RQQc4aTWd4JrcAeRmfFxdicB5RR6IkWQnOzI38UJ/j86Ju
+TGI/ikAeBBAWO8HIffrASWxWwQPjwERuFSwxUhSY4w4ygFi4CCcvre2xM1VgE/TukONDaTSXeFpQ
+yFNBCydRlhuGNHkY+odAUP7yhdk3WfOd1Pn55I3Q86f8t6oXef3ZG+6EdyyZ/aqc58o94QxALMkn
+nAyVRD2gAUn3E4w+xaOaRK8qXBcusmQkI2paM9LJ+naCQANIVHdsUASiHsjyipfxkMfPvVKfvTHy
+oPSKaCKzB6OHl2KoHyhInegG+juDotgTlfxapgTvJS3JMI73Eug6Gxmx2M1JKfvYMckakzcya34v
+j+kPoF9ROdAq0HZLFyok8O+hNQCpBiq2IIr2xp5mTTHoQPgRbV+g34ilwEopF5iw8TYAEIO7eifU
+IXtSnQ7UZXLuGOUT3mbobocicdIIFWXnLiMgh5KM0J3V5EyDFJ+Vt5xbCiQLKcjcGAf55o1A9ubN
+gHV9ETEpp5VKVcMALtCtmCvxoFRNAOqmxTv0qG/KhFNr2AsIy8BC0LdrkeqautPtzBE3WOE7VuIs
+WYO0PfNVG8X7sLzHiubsEPTK3FNWucOsBLJsYeS9XV30gD5xSLx50VXXTUnAYSfLqloHWSuJBLs4
+q2q8d2h8/BNiE+ySepbnpewuA/vyCa5oEUAUZ2zpGBj6Ib7ER65UHffsvs0JyHknjMrolVtmwYLN
+sNBst01BH2IukbO8/edUKqNnGHsUJApFUI05O9vigMicebF6DU7LDyufWeAQ3fxoEprpKIBLdf+M
+CVlDBJPUVvDdu+Qv9V1q1rV207IqOWNJoEBXNQXUKFJCAz3uJ3SDtkzIUwaRL0bk5yY+eQB5nR/S
+vqwFN2oaSP2QdJJxh5cYCJlE+qlvD2hoWanQ9l1BRtJgSBM6JZW3guwUNhiPCK/bli25aRQwMqZ8
+FeXqvLJBGhuZRgukUA39RHn1IAsQx4rSMcBCNwVOfEWjhT4kh3ytRcY5E61hCcFB7UkRM32GozJR
+sWW8l4/UGSUKIK9sc/7jjp5HFiJV092+8NFJSA9oyvnBdPwV3rcEWMiKHIqS8Qh2WVR2SihI7ZR5
+viAHceLYrmT+5g13CVsn3k5Ut31FY1xWFxeIB956XAwERkKH2Il8qWobw+oZuxc0up2QDI7LSN7n
+iwS/WS1d59FvUXLWBZSgi+W6bUkx0BzwBif/CcKlmPZWyBZ5k1tgNeFtQ4PTRKYCehNLDJ5uu2Te
+UuQgsIbQqPjpmzf67Vit8PTNGzcD4GN+8YKacyg10N3vYUuSCAm8+ystSKUM/XE3qfWtGi0OnTX6
+HSsui/iWjEUiWxadxwvVMbFFFHk2vzSO3IQEuWxrN5CHeAO3qVfxWc7BrSXE03WGcWxYb5AYeVbr
+vGqZDdPpxaIimxjnS6Ulb5XuMNwQ4naxNbcOrgNDy8ohH4T/AJPjy01Y44G1MCkfl9yV1tENOa3L
+Bk+5ZVrGWwAn3rATbCRKFdwQP3uch7RUy9vfIeSx27lualevF3mZ1zBnM/zWJKu8zbCu1a0qESUr
+aKMAZSFFogU0gi5EFhjopmEPPxekH8HsR8DA9qyk4B9v+Xr7AW8t+GlEG5vtAolYsnS7EfkguVL3
+DHYyaiId96kDMyWVql7ym9ajAK2qsfKpKjZAvusHOA0P2jyrF9W1K+Jq+ZAZht4e0IY7X27IOjnP
+1rAG8BOftWiTki0iMavWG7Jt18H2JqZpSb+BTpwWpAYqFOmUIGk3U5LShC2hlDCH/RCW2OKwrQ7P
+8kPEiNVFovhhwemUAmcTBSMK826sQILC/NKoFTGn1JHojK0At4cq0I5lG3LnTOFbWX4mwkrOqmqZ
+Z+VEJ2csK1gXNbl8sLTqaN3KjcS6ftNhhT6Z7FrZPuUlSLbFYqQDslqE1YBgC8oxIZ3cLzFF34ZN
+eVmEougy3yblOJSYBPiWkW7f+CgkhkdV3rzpb9mU6jSsbx6ybElgvnmDZbc1qGauf7U5qlAQ7Ddv
+3pt2FeEaugiQnSmPkeNUi10CFusU7cpB+lVyG+cbVkPHQxz09JElznJtXpJxkk7fgL3XoWWlkh8r
+pLHbkBYQaKMiUjhUe0ETtq4YQ9JVLmInTwc2EZKJLFupMicineb1+BV8ZlFTmUkHyp3GsD6rutR+
+hmQSqXOL/uYfA0DPyvPqTe+6NGO4w8rs0wuUGUm21BCH5zqSPZtc7DWfN+bhaA2KO5lu7au+NLAf
+41ROgCWjwu9JtJbemMV17RnCdZRph8yoqTm86vIHKekaSEZkzEPno42tc11fVoovoveeqHCilf/Q
+uLV0YJJTC33OJdHl2VXhx8M0d0PB9NAZO6vNQVi1hm0lP8eTCXTs6RzY5TfrZVZmOpQl1y8a3PlA
+lj7PiiXH6qCBQOlaZlX4qx35jfJEVEpYt1q2HSxNGvpCYteh/yQnyZbLByplttKVJNDtGRkv0NDc
+0NXSrDQPqKEPi/JD3BQ54p+qnTcgQZG118TwRDaITXAc0BqNtmi/1sl3abNf8Mlbsywu2svl7YgN
+eZTJA7HFAXD9JlQw3GazWmX1rcVcfyyaK8rz5SYHnYSjHIoYmDhOAMIyZxyBL1umPxopMgSzyzwD
+bUhTIfEA9M0JbBwyXYy4RdEA1dzyMQ43ggOsxHrC0Jthdgyp0j2pTMQTugzcZPuATeAQ9YKLqobZ
+BTmvbpd4L6sm8fpdXp9hGESKjXxORl27174Od20xahAzoZBEPeCW7HNlOhHFA0yktww3braMoGOw
+QoW0YgH3Y1DbopoTL/1xNwzpRU7z0Q5Fiy2Rv905VC7aC5VhR0wCLFJIc9Zk9XTwe7BwkSelcRDi
+cy857lzkZxvLmPrjmbro0G2mvBXyhXh04OGF5zyjos/eRpiRWRwOLiqUaVTl7v4s7W/KTg9Ow91G
+7RoBm6/giVCYgA6M+1zYvKpRyim+u21dicMsN4oes9ggMphwg6p8pMtzm2//3es/JwcxNNBp967/
+5jXV35RsQCcDndxdzdYFV/yL13+q5Fehxrf/7av/50/YwQu437x6J/wH5RYp0kjWh406MjHnpMwB
+5ZYlN4xxuQfE9hFEDBA5nlNISS70SlgHiOT1KMLfT6GhL0T13Mfl5aKuNmvl216jnwA9SYZiWJOc
+EfTQ8gkZHh7KeA5lLENzIZLPwKdDEB1gYeKtweFIHYZzQiJTFl3mpkMfP7ino6Nbt210YJwOpax6
+vRNG9MTqA9CCbYiFPxy3NxiDEI1077J6OgTCGPoAa2CJMOzIHUi1ukW21UiL4TEQaOmdTozEB2Oq
+g97S94GO5Io5424oe8TQjf6Fd/XZH0R8Slw8Bn0yP+ciXwas6QMdHS3RnXLQNRgvBV0DVhynnPaM
+QVUaAorVRcvRESlqNdp3vx04rvMShKAk7E6Nswu5qyQu/roRpwXuVwBUF4+DAV9UpxUDYrEUTuz1
+JE1yZGrmChIJCpmWMu+MSFS0L6pTIDK7CCWjNV/dgiwCTyMj+dIlqkoJBSpBkZ32nG7Uo4CqYqlS
+Zc9P/pqeYhqnPO2HbWz1BH0ovAg+UG1PLBXeQgkpKKhRmKwXLvelgiJq6KAa8sAmSKmF9xOsuLSJ
+lBwDJGhzeMo97RNRSNV8XYLWQodyT5StNfXcjqWoDAPAVMAQiXk3BTK0JaJTuFNpLC8GHYtSp6Qz
+cva9XqokvgSx+u5eHoQJBEVMisi3+woe88C9MruCdYaBFc2QMCYcplyH9r24iR6t+rtIosAaCSwj
+1XrqJQTk2Ef+ZI+/JufoxxL0w6304snzr1+8mr3+/NnTp92a9tsO5tTKcYMzKGBTlZAsb5J57adl
+K+Q+r4XTET04UoOMDqPjI2BLB9E333zzy86MeFkV/VWp4TspJtzeaeBSJRZQEYCG944+WkT3KEF3
+Utw/ZjgCAUMLzOJ57N8KDa+i8CJKe0DBhmUSx+zQPlsU5+cgyWFbQnD9K9Cj9guM+WNPYCrxc4bf
+lsN97pwWaBGcycB4nkn+0asZDYWJs2JhMc5nxIP6R3gyfP3Vk2+eP3n86snn0ZNvHj95/urZ119N
+GPU7Isys68SBintNT/t7U7FC8Ab2WTa/GqOBOGtn+vgn+XCfEcie5m9XoY1oSyAsFUlts4Z1aLF4
+iYg5dni64uZ2ogtWS8+rniQPtLucN7zTcqyM4YmQxenQ21v0xuwAIpsN8h97s2FTrt/tzu0Fx4In
+hW1lsWPiw9SzF7ePo9bJADgeJYg8Mzb9qlSaLv2zGHW+zC6aqWr+yRdfPHv+8tnLUTd63qwqZ6TO
+UJSmkTJLIHdykSPS1o+IGhUzlkfrxgNW3pvd0LHiyyCBX0Ukm+nyrJWorw46t5Cl26gApMOxp3vM
+JobsDzQ52oH1/ecyHbz9717/uT6sIOvCsrp4+9+/+kLUPfgGGwhqAfkh6VJ03cOz1JNRAhcQ8gCx
+/mQcem/A4ULJ2dpVA7+XFtc1s4FmM9QDUJq7OPv2KFLx4aGuAWJ9V3tCdUaXsBQdW4W6tPQs4g2e
+RqV9DxUWcf8mJAreoOlxR1EKOg2b4U09fUe/Geh4JeQJiXf82OaqasLkNEt0pCspKUNyA/q8aDwU
+m1OVU1FVVVgGZSWNqTbdDrMvu0EViQRB1wp1O1DhGlB7jAIHCRFnG9p5jbu1Wmz24F7Q5y+qC92t
+tJ/61cJXn5JOo+l+btk2EEBs7shnNrGQA0cHbfbWIY/GAnonExsG9+3AuX18xgiV+CMT1xay9tgn
+3fNLdPue8sk7HmfQAwFDJRI4oYd4tdGEF2Z+hZSm3vET/bJunaDWfLCyIDGRqxxPLOGwzK91i1jM
+bk3dsTRFptJ9J+Ald9wVqjjKv4o6GYpkGAB5u5zmNmkHsuyWd8s+8LrXXZPV1r4GqpDhaEdy/xQv
+lQIu4+QkDnXmJhJwAHAjjhq0K/wOLNkmjjkiwwXvZtp+oBYgH4b32wz8BerZC7RJx7LlGBuBZhrq
+E0daymuK5OryCzddLZ5+z4DD1To/OKxrFtD4eGROCWCWVXlhmWK9YN2Up2MGKkqjFBS7rmoRJCYK
+GGmDnAZtFqo3VghYR0s72Yj93qVvLB7sySRHhCGD/jKvdFJC3vx2DlmNxGJqqmbMbj0OQxMa1LWC
+scqsNpXbgrugaRD+XO2YJTtrTY+vgz3wdOLGlSYwrjF3IiYKQBP5UHyK6Q17aYVUB5tre0IgHneM
+dxzcTQUci3kvckJMc2LlXCAr5YJE0fgm9kMpMQok6oJAbBDj5GzQrXzT30ocu3W24MCqZcV+s2ux
+hPo9IJa3GP9kfbeGTh6eph2uoZeBIuNddOT60ffTUEnHR72Y2o4Ra+aHT4eBWFPbxklK6rzOmst9
+bAji6uCitReYl1uBAfY3ubcQQ0HkgTXoJIJ5H/S7x2PaquqxKY0Bi09JKWBU+m2HV3VZGxcEhUDk
+8w5v6+dr0thwfr2YMEZcO1y6ncExc4s/iDlcvBok6Fn/w+t/jUddhIK3/+OrP/o3pF8NxOcdHpeV
+yY1Gu7B4vz/7Gs8QKvY5QpcWrCZaVHPbjODViOur3ZsD1z/hcDHo4mdHNNkjqSVQxBj3xBqJIgIc
+JG6mTvgkNoTZTsN1pyYbau9eD1TXPaoNI0mfpPM1cLZWvGq/O27/AZnCTI2dVvl0Z5ZP3E+GJ/ea
+U1lgyd0H9t5j6uYaGAxm1yBnILFAYwDa76jIwwkTkCSx4TY/Cj08/pl+SlEZ5akp+6vXL/9+BHJc
+vlq3t9F8ES3q4h0wB/Rkgoa+fPL5s9dfYiy6VRNtSgogUWQqN9VDG5BXnz97wc0/PAo//unPgs8/
+0U8pGvaI4mGphE5nJHf8cvCds1i+RO9LV9Yl40f2DwUIouu6elegtqxNtM4CpbsxKsdW9Pzrl8++
+kfWoAxJneJfqnFOh5+yPFVOROFIBOqLoEfq9buYYu43t3MZ5ttmcCbTeoja+W/iX415N+S9HvaZe
+HnJlmO7vbIIVjqlleS+dgaWHUDatYSgVnhtKyVM9+IBH83IERXoxotJSS1wID5UhaBOobDNbbsMA
+OsKqoTDLbqByq0HZd8pqW8RyJzWxhbwTPOvYL5QXwCC6HZMhsXwy8WPKeDqSGb4ur8rqunyCBe4t
+kC/gcz9mJVUkBOEpV8JsPJH2RxE/GPXwgN/Fhk2DRqxCpcU9HCMWThRPONd7Lb4sgK7v0q4Y0MEN
+D5fgDSFUv7MyklpBsHlu0N+bExI1mPjm6toKkeLcY8rMFTwS8IkUs1K2UX0IQXl+16CMzSmtkBPb
+eDbThxeXsLgpTZSjn/eRBvac+DD6lEE4CtCGG+KuE5isZ8+2KGvEUS1APT2TvHjqZKUbUtW230kt
+4TppT7YxLzVfF0MB4wk2CG/kmMfhe72B7boJWwU+O4BfuiWYbvQVrADD5jyE6pc96cgwphD2DxQi
+HdI9PHiDrl4ZMnxk0zItXbm6n2fhx30E+N4Ai/1t2zv3CX3oD4+9PRkKY7DrC8DPMVI9SID3OAEu
+UruR2jhmUbqTTJyFhD+DQW7vTbzfglT871//hTp9YJ0Grdmbtli+/ctX8b8nEfk1fCvaQjZbXcq4
+JPrHCr9iA8sjVVLtipbtRf42Y7cQelSiczeJx+Klbkdy4WC3CJ463AEdgu7NnN3qmMsawsEBu+St
+61yio5BCRvFF9CjqnFQIiieA2cfxgg2FLOADjOusoYvsGGJEPDIj3ugo/teliquipAsK7pnhjTS+
+hoVRgg6izxFVzxQsOUgNzggljDnZkfU5rnaMT6zPRjbiaFBUmNICW4WYxX+F7yhIGACar87yBQ5B
+O8djv+L1PoIxXGOidIlNCq/kLkqd59aFwkn0bfm7Efz6jjDxbflP4ovPru2YgABbJe/3hajD7KoI
+HaKXvAVjg0J07u4iZqLtgtq4LY4CTZRwjucZXupJUmDI9E0LQkmaClwU6ZlTWOlWyDyFz+xLDfru
+U7POMLQWX5Tlg2+QWMYXY6rHWyd7n6Msi14MjSsBHkQY1HCJkcRiMRIQy5bse/x5iqFR2T7Ej6fR
+0aAvgD3f6JvqkhbcY4r+OaRGYWpU46BwU2FH45bqGAN/MugP/8gBCxU8CmkFCHtI+Xm5WdFtYpsm
+TwjCyWnasdXMSW79XSBNKHfTcThh6xrV+q631qFfyw4ajCX2CXMZcGJgcdrhR8lwU55lS9wggcUg
+l4VFIIzZvrqS2iI35culSbsfFVZuApm+cuF6qRk8YtXDiJMZx9+Wnm3Rptep0/3JhLo7Je8tb1ru
+H38ygXYxRfL9bdq0B8f9Yz/3A8OPuP8ZH19k1zPlsGQDg/s4pn+WnFYwjFQWBnMbw4Fwvs4rjLHI
+/BtYCzOWfxo43lC6J1CETvU6XlKEbf3KOevCoPl2Soz4dzH5gboPvws9/CdfNHOcqZbbzqAYEMI0
+zh+MHDNJDqxzTeWOeTIRqzT0PL/CMR5Z3+dlaz1yzjfCQ4Wn/mg7S1G1jPAFkjmiwRpRD2rIHsIT
+FWeCiD1fF3RFUsjS59CewGLD0uUB6q1q5sj3WMIW9VFfdB+xHAPcH1KHVDs9PMZMZQ1l8izzE4eY
+icd0cPadjzNh3qGCgSF3s4rrYXRf8RBOqATigJCgAN1CYH0g/VO8HUWAG4OaDk5Uq6bEVE2JOqIE
+UmYDmEwnXY58zkaZCD185HoWRo2lQBsfDbR8bb2eWl8GYU3BKQ0fJGRq4O7irjuLkjisaDy5gxZU
+U2FI3zVuZVXdPKBP5aJRm/h1sSAj9M+PkB9/Ar8QO9U6hU8PgZPBo/llVjdy/0/c5I4jzj2uIhZy
+fDeEcSaWfhCAi2rcZHiguq4TBn+V3WDc5imm36GOHzyU9UID66lL70xlqniIUOr+pBF19wtWLB2z
+wv8xn7RKOb7+afoSk2oBKH+LVwbpeDhbnS2y6GZia4w3I2ilwKsk7QbDiog3RkMOR/11zBSrChTu
+tr8Cvk41TNtKwluB3t0sdZIgR+vDRBZr2mun0ziQ2ZNS2SKaUombSg9sauvfnsnBdaZbUETaFXYM
+mp2u9MM9u5NVMcvfzpz2tnfcen2279Xd7iHiDDpd0YM7Y1I8Dtd0cD9es/LD7d4hI3C4FQbG2yWE
+PDjn6g9OItBsUfbQiEk7oXMrU9Jw66hIm4v8BOa7PJttW5kN0EmcOFfFKdQiacETOhrMGx1lFBRb
+d+OPQXXOimUjvpRj3B04HXCmoy5dUrgoctS71Sdg49Szh8qpHbkInw4GlmxvQTsJ5tAc2JvWiTA+
+TyqWDaVnfepN5IVJCOlffuckVufneJJxnVNAnpvWitBMV8op0cgyzxbqImdbyyV53DiyeZvD7sEB
+dpS2XeBWUmA6S9BDKTOe7mlVlAXo8q6m6U0eCw54/+AIdiiKBYKOYBg+AkdIAScpawdOwz/kdYV7
+2oVyJ0MdjwXq8iJPoL9E7SXpiDY/WR/u6QS+PylO0duD3sPnPt0Sl0v0WfSxlSq5IG3iqHsIqEUL
+2qbp/q2VcNYn2pd4+I6Yhb3N4DDuYwixmhVrIoqS8Iz7YnFqqcLntNnQIC3BjNGohyxvCB2CMuQa
+Bmnu/SoLzbp8V1ynTg9t1B4WAbnd1WkDOPbxvAO3Pn7vvweCGcsheg+j2Uf15NB76eJbv/bhFLG4
+LtaW1tlxQrS0KeXADiAti7NxiR9oPhz3sTvlmveAdhqS2xzdkBqKJe3awyf9y/7HWr8dWnjUksx7
+g7SA+EJrCFa/V8c7LrkkxUj1N9K9eTdcHHZhVtNnwcXUge0LJCKk6AyjRlM8WAr9NvL3KjZXAt3X
+mQQ+Y5k4IJ6fmJ5PRwItK5Aauk/3g+4FUfEPCB7jUMOhwQvEbDmAPfB7ylEHd5ChQvTc7kvKBKbF
+D0DlojrmpcMPSDc7bxXR6NrBmdAq8RON3EZl0KO+AE7bdZmWFcXvKkMt97TuzRP5gqcOgAT5nSHk
+8e4C0Wv7zjD28ydLXsXbHyMSfFTKHmIKU3rEVmkswi1ihBZ5dTKhgjzTKDCq5/T4PhIz1ZM9dV7V
+GAt5JholNXSf6mlqcDUEu4LAJyGMr6XwCWrBHGsaF6Kc2EwC64vHqBTsjx+mXXscccCtpji1d/rW
+pU5m0VDlw+i9qt3vVJPh2xYhZQZ66JrGfJOTV9Nc+lb5kfj94O1/eP2X3XPEOtfnb2//p1f/97/6
+yU+M25x1YGhHH/JOIVU8iuCRovIg8mz2wbL9DvQfej4OwerjYCV7GvDBHhnl6GB51Yh5K8FaJ0en
+ffl3+5S/fp8BXxkM9Dv89OSsrq5Ac1FK2Clu51kb3Tu6WXyGvjDBXUBgNb5zIxAH9Qi2UdG5pYs+
+xdCzCfpN4PH6OX3zExCHMVdtajJGnXND55vlkp+FDoOk9M4szFsTLeou+QO6D6HfOQX+TM71/W5N
+snQPcGsyxmfI53bkkNS9Ormtd1vlu1CjvxZDvsjZVIlnoywj70j5TC6HWyYhCJtkh8R4lhnMTVTN
+55s6WnBgWosZiMGUjmLDOXPn1UwHMcDgmTnlvxp+Wm/Kz4adPPIM1Vait3oXnIyi85HEbaW7yYHJ
+6zn9sJfSnOK+Io2h8wDeiczti5ifDUM+Qdp9tKdxfIXHaqqnEchUOExYNJRaoCrJ4QgE4+SjUXQk
+zKvDsZTzGQKqHC6Gwr01NmaY3hYK4B9/ighYk2OM08h9NBwYvPSwbmhMt6RYuHmQNT4A4dEBBh6O
+op/SKR1xDBBJWkStvd0NfwsA6jgtPfDANrU3PNborKcuCRHMb6PX/2F7V28/ePUvj9jN/Gmhonmt
+8kVBHufo/yN45nMVjlDExzGazzQ64ZRKzPfo5avxgExNEnVYkhhGNtYxyBFdQd2gD4h79dfafbOm
+HezciRXGcEPu26xtVG3fs9Vcb5lMsph16OFTIodPRtFDmeyD6GWeR5dtu548eHC2uWjGv6XTp3FV
+XzwommaTH3/8i5+JG+7NuqY1NfxVVS2/XuNt5V8VJX94XWb1LX/8go4W8NOz8yc39OjzYm4HWRJP
+yC+Kpn0MGg6W+H/Ze9cmN44sUWzDH26E4Rv2tSPsDzfi+tYUtxdVJBp8SDOj6SW4Q1GURjESyeBj
+pXFPLwYNVHdjCaBAFMDuHo32t/oX+JMj/NXnlZknHwWgSWlmb9iKGXahKvNk5smTJ0+ePI+vOMZ6
+vZIaf5hWswk+POEjED2iN1QEBQMv4Ndnmzn+ebWmX9aUhd5tTpsxcOw1lQOGmO4Lfn2N9zDiaz1s
+1vM1j/hLMbL5ojqjnuDuLc+s56RRVrOKG4QJm54v4lYeb87Npyx/gSc/fPiypi5/h5YrjDb6OSW/
+j/wlCigxqNera9ZJU69X119yslBpHciFIBEZuacvgfJiUE+vqjHNAeVExCeYBOrSCxgmTTNqFXg2
+WHo2GEKaGLIbNlr8rQtjKD3CSy1Oe3YmiT9xaTIRKfTeqDLNR+mk0GkzhKIEk2J7x24g5JlqpS3b
+A241AoTw9wfkuq/43Z79UpduC3I8gvJ9LF/epFNJKFgeFQgs2EtcmcLFWbIKerYpPKObVraasvwH
+hQ3kkcTyWoR+dbwd5HnkNDvakCFVi3UvlfGVF/FxOSFurMhoXIscZLElrcNuDYAQCZylkquVkn6u
+ma7JhjK0JCwIaiLVsFRhUznMQupdLAlmj7wYGByqyh+09p+UiUOxXSZG/lrthhpbNN9FXrgdxYTc
+QK8UEgOnazS1xJxYFIoZxhr7zOWkbmJDA7WRchZIzMwFB3KWxRB8P8tebc7PYZti28UEPNRQoblh
+FLjY5nJy4ZmhR0gUh4f8e0DBNUoTNwI6XdRnZ3BGhu4NxZUYZ0YnmkD3+ZVItP6JhF/vd0iySVQN
+fSXbtVEJ7FxVSa0b7un9lM2pJnAhQsrmCLTO68NQBhkXiX27Dkgh5lta+RTahDmrqXtkA5Nn2cOH
+xhWcDdLbLiudTYqKTiR6InSoNFBMZ+ncaoyoo6GRt/XV2lOj+HLLkaGDrufXTe2RBuv+r448/Svf
+Chobk6H29sI1/vl0/XyVAVX+RbY0efl9TW//xX/7GLgcvP0H9fabVxfTszW+ffhQvX5pXz96pF4/
+nhCAO+oVyBX46lC9+hZt1ODdbfXui+l7fHVXvfpyVtcr815/+LamVg7Uq6fv8M1goF49q9f89hf6
+7Tc8Fu/NU3qlS33FQ/PeUKlHutSL+pKGocfxdYOvpo33CrrCb5Fr6C8Ler3we81v2RogRwe2DcqN
+0dQKUCx34DW3eI8EBJ/+zXv/xsyE/9ZMGbzFtkwcp5D/c4uT6p+Z37sd0hbCzVCizcAZ+nxWjebI
+ys42OqqwOrNKRNyWnZO5S7BhGv5Ff11VExOF9yBxHfOFgVtoEj1D3wXeBy6rbFIvumtONjcyZlxB
+wpW+1rxtk1j8jfWpZfBcLtCtWr8P3BcwjpfdNbdqi6xtp0NFHw93xbhOKlmsNNOiz7NiT7nF/le1
+xbdBYpmX8vzSMfa5nG/msk1Y8xEo4cOOsdDJPugDqRszV+TlnppRwR5UGf7E6FOGIj1fe7WvKfh4
+xHS5mIC0yb7EJLiW2gnZjJ2J3Yh+c0w5lSNR5LEgbKtI4fyhOnl7+phHOYNSDbLvAxK2k2xXLRH0
+eBliAYkvGIKR6WVASPy+6QLShwSZ7p/Wk2AOVRMixfvAn41s2JTAzzVBoIaWfA7ie67y8Z+yR1WZ
+0RRSkADHHqy+Mj9YcYQY+NxwChFk0Od0aoQXJCwgkP500tOBRCKq1nJ5kpipjR3sYDst35JUmzUK
+HRscGLrqAfUl2/GIGS+E6L3ImBlFhVrrzsBqx9DZBZUrky6WBhEhu9jCUYLZFs2HDVI0X2rZkK93
+8W3f3t5aY1kPupipappgWqDrao880YwVUxoN6yVO9Z+ny4JaqJcN96DPN9Jk8xvdkF0FDdObVMPS
+RBnE+Bs21/PTesYB2KzMd1wv3cH7ZAs/z41xbm6Nc/3cKKaB/e1RwjEF9ul2ZQxp50QBgO/doRvq
+Fd0nU6dcF3Zy/nCNfMje2cuCjg0ULdzAKiccy0DN7MdtMK243eZym1iI0pd93JZ8F1NKO/C1yTrw
+MdeDcSu7luLWFdPR/IiOmJ6/Y+utHId/iioo0tO98Jos40BBzS4T3JWK8LA/a2MFsnA2zBRYa94G
+k0qKGqXe4jJ95E8oRD1fJQ+1QeRn5mjkl4DcTGCwrqPVvCPcPpljCZhWcdK6N7UStA2xiJaNNMJd
+JCQBGBgbOIYcdyL5h363HOzzIs/u8AZEx3vdT3Reycv8A+ZMNPwyaXRu0yHpOLsCkp450R3TUz/N
+vgWhIYfml6kZMMCCefBHbnpBrDZuYKtQoupqfl6RKrwst8VU2I8B48PAH+K+0sweTPMGiw/vbMza
+my7qUKzYU3qgqn1fhmAXGL8P4hXTBiBweUiLAFw0TUkh7RspoGwRA24mA0QjKjsfvv1He/+HyMY/
+834f7fV6Av8m9PrEBVdRSTGJwWOOZw8CvvGpjFNAY0LnjrLCGbbvGvT7Bz2nWDvPjgj4jxrKhm+X
+o02H0gFzfIOEjULQPAWkSC4QeF9GNWVX0P2zEu+iAAYfiJaL5thUw/g2rq0QMg/G7GOmTrmt617p
+5CxLcifK7WYwIr8/FCtS3Zy//zr4kUaH6jDcDA4EsOlRar58rAZgoK5pO4yb1IbpNIQWR3qMBIAY
+R538R9ChB2MvjGPh/Kcgw/y24PimePIq7kAPxz/6GOSEEZS2oObt5aT5iVDz4bjZAzk4IP5GJr4U
+EkNi+IVw26QxWCOF2YdjVu034DccNscj37H1UlAr0x7FtvoZN9rbtxfNT7gbOvEZkPbHxQ8HiAJ8
++lGL6ss9tNatAjGUpoCxibu7ffdj1HKLCRURXFoXqcfCmjPMP2i0hHRyce+NNjGP51b13SrT5OFj
+J1alRPkQ5aIA4EBigbTiYugwctCgJQ7Qq462WKA/Xl/xyfabejQp27vrK3MJdoC4QNjld0npAtsN
+NtFo/faFUaRgE4BUF4J1Sdpyw3BMnb+SEExnLg8JP+GijbDlFm6f1y6hLr1gb+oU91OB2W8ib2WU
+E8xcDeBHSsSMloujhY3u2X5LYEy5grnoUYzG6Xg9HHZ72Q8/pta9Em1+ImrBbg9Nn39OogkbCu8V
+/O/qfiGh0vTKRixhuecF5j4by8+9bQhjpBs5wxWbxotbTj7zHhCJVp/gW1iVUgu1rkSxMxGeE8Eu
+O7sVyqr5cg+fFOYWaXPdn1w/nsK56m8C8dPzhUM8/FBDoh3ARz2/asE91N6xa/T7faIxZ4LUgn2R
+jsn8AqWJWO1mt8RtTsTsQzLQfTN+Ja11xvVsWJ+dNdXar+felzrty5ALSWcFoVIRjjro1GIi+vq9
+2dWP9v6kepKwIrB9O9nKIpN2BBElJ+wHYsaoqeNn1gfppjrv8jf/OTaat0mhb73+n/8X9hNoNksy
+nidfCw65QZEGKbxGNQmTfJ2Jl72F2fR1ePrldSflcUcJ2zxD/nm9gMP5EhPiGvN99Wofv4CPSSZG
+Zkic76M9Uxg325omjD+jdUSeptjxRT0dV82gyCXkJycsYwsLfKbDXN4Wzdmmcna1bRayb59/8bSl
+Vc5BlmPqu/WqnqXCp2brusa8Al3qQBcDlOMc4x1ZqjgUNL3uap+UJuE6Mjpbc1TPa7G4RZsCiaau
+YCvDV20Hhg3RWLuwD2EsEkZBaWKmplpEX2XMTWcSkVsq6UQttzWL5metVLCoWwhhRzpwJpJFPTLu
+BTwxXzx98fLpk8eYsrN6t5nCmsWsbdBV3853W3/mo/Pp+AN7Q3U/oDOh4+srnABr+Ue/bKyaMJjP
+Vrt4k01q7luBsSMaZzPBP/4HCj/sUuLRz/6qrtcUbz23HdgvyZ40E6XlVgvcGu1GhewEk9NY4jNj
+XA1NmpPVbwDPJcOPXe1bItYrV6rQ25O+JNw9TaOW/WwxRtviLtVFd6lULPE0fDOuX9jhuppDDHEs
+HoNNMfesI+c063Y3KKIkgMPxrBotcGmwjm7e3ywmSiEBnZYTVSIENJyqfJkzGSBfMbogZrQEGajr
+t/rMsn0OpbR8cABf0gtgsr+DAtrjAyYAuT1l9+tDp/EwcK9HcLjU5Wi1GI5O6816OJ8CT1ucuyha
+Cp0GYfyN+Cb0w1/HhbcI26r1ZQz4p7UMLcUityttkiHdMGbEp1ai2c6NJeM+WRql6bZemQmgYklb
+Dx+fq2pev68KRmYnzhqFKJRcp9bzjxyNTQP1YnZN2nAcIDkV6y0ILU4EkgSlvgXHdB1S2ujzkF3O
+R5jeEbcqEBYajHTGnTmkRJ1SveDQXZNawtgKeK9djy6l+/0PRxnlQYM5GwooixEPYyZfGxQEwUql
+oaSED2hpPV3QcTsdPtM05M5PlLZyqpOwJWJxhjEqYIgDqmgouV4OTIMD1epA7s+9Gzc8FaAgjROi
++hIxRVMulWLgCzIhny7Gsw1Q+nJ0XiF7o9mcjNajbLOY4eRKJoL31eraJO/NisP378uU8RbewJlk
+jaZtiqKKAYo+u3f7Mw4B6IZtcsMayA+zB2kTLw2NQpR8kZL2QUo0nYQTM0z0GIhn0j1J2dSxg8y/
+Bb1NDkt3OL3ZtvBQH+MYbl2IhgLgnYIAgmGd0bB/JFFhgc/wcJDDtsBhywkJD4BrjKCh8CrqPI5P
+z+GRFlW9aVoAdQ+6NnIOhxvtZ085AjW8mlPYl346OwPhD/7ti2N1gR4tWX5wkJcJZNPJz1iSxbZu
+A73skmt1XY1Wk/pyoZdrCo7LESAAhAOcgQTXXAQc8qfmOyym604kJAYrgX7DeZusZOSSLcyQaCkP
+Q98EMuTbFbMZ9zxf/HaffgM8LL19498Fi8rz+Hbv6Eex16UO+a/9LQNnMnXd1DSdWO7bPgjaQSVT
+HWV4QCdvpwFwcSXtvqa3w3yrPic3q3d6voBzzCTfFtcl6ERutBGUoBN20mvJZsgJMQiHeccTApr1
+pFqtOItfkX/3+OWzr599dZShCaAHvD12fQ6dZX/dxPFXUID6oA3SXfvYc0kgAoJrtZpRdocXzLSm
+ztlqW/0CG7uuN9kGh2k43uHzfyr/SAef1t3TGLzGXzrv/v7Nf7QamtHq7buD1//xv3BaeLlLy+bV
++GIE638uKc5Xb03EUTiaoezk+mJybTTs4OVpg3phPnjUB1I468Jm5iZG90MX2+geZd/CHxv3oCh/
+/CgFEI0GnWPUMXuoz9lv1aEgrf8R2xJ15u52lYrm90//8N3zl188/f7FyzzMEE/iI7odM93y8pmT
+Lux8+h7ESWME5BQW/Sykhfyxp0cBhttMERqIHITHw6Yi3wPUwVSrOU5CAOApprHDb9kco7dSBzCQ
+bjWuUGfCn0h+7x52UXRfVOfIxyNArykOzYjzqJgOccUjqjgfvWXfZg41yEPlf0NYI8qJd8oBKdeC
+oWLTUFgRypZ8CJiBGYZuiCAXTV9+qOM2pKcPqUrU5lbT5qnYHr/8/T6TR6NAoueZQ7Dbp02OAEfZ
+4Twj2r5PqwfZBv560O0HNbxR6kEe0hhWGHMiqQui/rpUas1FfZlJlayQ03DP5B3CPoAodAjnEAqe
+XKOTc9+gWBYQtA57f5G7hs0ja3+Q7dtVD1+7qNHHkO3d4Jw1n+CX4Rwz03snPadjEWFW4B+FKgDu
+9ny0AFl71Z/UsXbHKVAubTh7odTZd5SCqUhn9XbCqTfY0IOHLjBWOOSBxMQjb/P8CAZ+P/DPuDQ7
+zm8Vd+0fNEd4FhZQp/VskogJBXUROt5XrtNfyp24SRysw6uEe53E3MB5/pqXrGT4Sh+WUSibnl1T
+8MhCYox6syr8DNeFO8bLBMs3VsXhYkqWMstVx+fWUN0SEgihR2JHtIfQYxCDKRCkE5oAoAJ2fEjn
+IpAvjnJPJanqevnO/OFpSEeH909MlHBEKOeZMJFHK4ZJBmMqsC4g1kTYJGR6Ylo4aAz8fXotbwup
+2tPFArp1rRrtmVQqd+gE3fjjM5mPgShWG4qX8cQE98pUAufZjcJWavFV2mMsW6NZehMTgbAhVG0r
+ERfSegpXjNfAwL1Qd+j45ZiO3bZho11HPx+M/dQaOXJ+TakpAjX5kF+jzpQe/Hyv2GBbvlflfInE
+pqHxSt9jSsxNJFqG2G9orNKz4zGV+/Xpv/aNQUu5l24+2g7wZD1WuhnNTgWI5R3cwN4LBKVcGQ2u
+bjn+X7eKZCArjBYY4sBNBwbh54iEzBvr1V0auBdHP+ZeEa/qGFIx1t80JkaiedVRFuN0Mwv7OWxp
+7G+ugMu2pCNxV7XwKcwLRRknDrtejrDw+gCb4Ao6YZAMpEBw/8KEAY0bTMPfnjeGMm2p5/aV3RCO
+XG6+GTNI+GT23X4euI+/vTQsNG1EjyM1YC53+ZclnPa1XWM0IF7S3qHFkdmXI6SNa+rlEZU8+hMW
+/aIa11T0T5LDoskOkeJqTCo04ikfZX/6Ewgzluz/9KcMD4Czal0rU7Mseypy5pE7AGfult6++q2G
+1W9m9SVd1utraDaXMXJdEUwjaRQkixHK7hjfMOsaQF1vfJgOxAyNqkiCzT/9yWviT6ZMFBnkZ09g
+jaopSaDLLXSFq4S3XmIxgnZ/AQghA28+pYgK20AVk4OI7/vOQhYdysQJUUfrgrwBJ2Yv2E5Eogep
+ViLNpcVkYzOzj7B8WoFAKtLPDlkZo3rb4hhGSYoWVNRkqbPmTHgmKa7KkASMJmoLwpLUYIywR4DL
+c0yvg3dYXN1GbKBrK7e+7SS79f0YJlleJg5GnJ8FX0lSeVit3+EtEmWuliujqei1x8CF4GDdtoqc
+9uAasEY1j1bV2dGfgBRW0+o9ZzrklLGjhiO3203lIRAIm4ngzvXoT7xPeWNyqelJuVWfraGf3KcJ
+zCQd66eNZjJ8pKUDl+Mrzx5/+zRUmFPe0spvzoPyIAWFZuA+21WVAAV1HHMc65+hQz4sZpeAa4wP
+vEYEn1YGx4gMO0cUp8ifIz2i31JnOjfjiHrHT4hyfORDv4uB7NiX9kdkBwHNi/Uf/umkQvfSHwxb
+G0QNZLC4eV+aIj/8qDkqB+SmXql2J9YmTsS1/rheXheRNeKEsg12TQ+7ERfMH/rkdID/o5DfjIGJ
+ZoqUGd4Ped6aFR7WOeIZZ1L2P7r3oLjBxgfmyExxxcsJb6JRP4O3XP5VTI0XPZeUU34y4Zbvmoah
++CHHuyVNltT3YldtDcsuXpYSt7yTuOWj4VEWRCJXswFhRTIBZ7Rw9tA/hkw/Kk357rB48qR1k+Lp
+Kixyk1a2bA8KjnsHpRJ3xVvLxm4eGHcBuO8W+IJYBR4P0bMeke1Ja7Xtkcx5Q+FjIK2Im0dDT3Qq
+3aN2KBf1bFKhhG7cAhjxHi/gkFJl65QxiCjuY2tTZl8pglYsj+lpflK2x4Lf1mVu7QOQKjVpr9+3
+R8KAsCNOUXNp+BrXCrna28v+ZjlBk5gQqnBRx3Lv0Ktk2Cvrdh8ikzg8d13Y/dtLT5TAGXBSxLdy
+uSLp7MyuC/t5y5nB7tX9/bYe0w0dHu+IWXt95rKj+ztKaieCWnBGmSJDHM0s+804WWc1X66veY2D
+4Ci3bNWkdRvTUM2p24LE3QhbWV17gNekgm+BHeyBgbgLr7CfuFALjRShDZMTcNtu6e11OIe4zdH8
+HqzMTPOulxXpMHTbF5vtgKH/1ulDssEdbGTJibc9PGSxHoNQgbuMjNLbvzyMGEboYaUsE/N2J5g4
+vcKC9aSJEoTrGJc4gmsMZ+5GYCTdCu+r6EafjZhhlHL/eEh+xd5QJLKA7bg7DMjwfGbjN1moSfFG
+3+m8+4c3/8lckS7RdOt0unjXff1fO3xN2mxO59O1jW5sZP8mNjvmARgQUGL1fooHd++qtEd29MIh
+NquZS1qM198mEj0B6S+qNQ//aj5bLceS/Rgj2NzlN3f5M90DqY/4Gz59zHXqWq5V5Podr91bb1YP
+zZD1bWlgRi/XWV26zuqaKztTUV3ZkezsTs7Xy2qQs909FDIG+MddtkUHQF2gk+5JeKXXAJmLvfpf
+8P6Rov/D9DjExvPUals8HM6hZ1OW2YJ7EJlXOIQt8SaTA7vr8n2xHCjKtPrTdgPVGxjgP9JID00R
+bIBiBXNb/dcVNj7C2Pezquhe3ulq3xZ34eJfHsEc84uiayaZ57haqfqwO9P9Fra36g/NdVdwZKqG
+fAmWFuo1HK9IwtjPH6XcrVH2GS/0kOsJIULa38/kVMm9xqiw67Wqhd9kr5qqequTyQsPmNXnypTV
+qwEb/CRh7OyVGc/qRl/5TapZsqDTkK/qq+vphMVJ+lGUmDTkBRYucrbVyHuqe9rRngEC52GfSPFT
+g999ZBs9A73cYmSjlg61cAhNHJFXJcJSTfx09IhIkek3B9jjLnuWnNg45YILO92p/B8q24215mJm
+OpuemuX8ClhCtXqB4BKmVaoOTN4UhZiWeiJGqNeEaK5b8tpvPOo1KBhK7uEixIkbXfil38JYfiFm
+VdUkT16h0tSEwEwjhtGSDdgKPQfWjXZbDbpAMzJsKthBBpR5hMPKh7skUSqhBfm6p+pbh+Mgr6XA
+BTXdLF2d54xc3Fklwq7DeM+TdXBOiGK8heSJG+hnTMZvQXuEBnJNMfjZx0nWpJFa9mf14hwFT/Jb
+Jgt7tHKlX0BNq2nVHB/eP6HfuPJn9TjlRbtNC+zaw1XjYvhjAkQxPliGtgdtNhVs+zqtE6YMOJh1
+bfBTrC+DCKHY/mXfAHDWwUGgFja7Q8VJsDk4VqfmK8nrQrfvG7M52WA0KR002eHhIyEjTKLl8bay
+8654878CxoYwMoMCqr56V76+vsPemJ3fgUACB3KnK0bCEh8R1lJyTZbhcbqbfoeTLSnPy15W63yH
+y+tP3kqiDc3g8Jrk0SD7hL0tnaeME1MwqeXpNXGdy+nikwdDDMY3RjGrsfYTgbsQSSZUOE+Yqwpk
+BmHfJmBb+4ptnk189USnCaCVyRROiDi4pgjFLcBZ3fTOxov1rAfktZHbJ5S5UE2F74GSx+tZcb8n
+pfuvv37+5Kvvvn726v/o5X+8d+9efvszk14UnQh6l9MJHKwo6R3A628WS1iUBQjl8F/OwdeyMjs+
+euBlaZDKGdXu2L3IcXL6UKRMfb2qmIY0GLNG15ZUji5Gaxib9Vb25eNvvvn88ZPfq5nhtqaLdQE4
+qRbvpyvgssTLnjz/5s23z16BVP3ZPWGV/s53K/v+++/p6AkTPKkvm8zrsdxZZKf1+aZBX411t8ma
+0WJ6dg0Ho9PpWjN67sjD7NN7PucyHfzsnsayYNdHKjPuCNOdDvdzQw3TaXlYkd3+hFW3p8BRL2mi
+RtDxIeWEKXhtQLkeLUJR4gOrQV5ArA8+zDbNhZdyB4NaUOqgKB8LC+tOeNLpRShTyEpnUcSb62Zs
+jZ6U4pR6tMa0XPq+v8HTIH2L6ntr9xd27Vr20p+iEHxdxFlIrHPKcfePV/dPjw+aOWa1HdcTsWKi
+IHbQzkmZJeypCUr8mmHdm3dLoaHHz159jcYPDLJC+/TGnHTZKwdRHvTuDids6YSjjTjNlmFCtfsy
+guAykzMYeiZgDs2E/OL4ipBwJQAQ2BWi9/7W7LcC2ZkUCNg1XWsMsh8KxMpR9uXzl0+/evn8zbMv
+ht/97uvXT3sJf5QFilCzpEa1+OR+r/SgvHz6RS/p1bJSyjQfxIMAxFcvnz59luoIyC7VogXIJykg
+f4k6diu7rma4CtNQPg2gfP7NmwRKAMrpbFO1wPhlAkbcEbxw3KyWszYov9oBRZB0Kxtfj9pw8usA
+RusMX17oM7YP5Df7AqHVlASigneuSeo3hEjsnxhN2IAnmyMxB2ECEc5fBrra189eP4UF/voPtuCr
+118Mn795/eLN6+HvHj/74pun0PLh/fve96cvXz5/qT8/8OIGCYt13NTvhmTUGGRfVetX68nv6GcR
+wt22TtsheD33FCTEwhqu8wS2v3pWkaqRYZX9SyugN50QYYWr/w/Zvat7Z0qt8MqCew2czwVUY7gS
+Us1t6JS6jvOeX63Rk/CTB7/+1WfBjaVTqnASdSoT5F/RuagYhmcZhu+3Qt1/BHbwKSEjgmo3Wtx9
+g3L0rhDNneSOm9RkHrJZFljEt2q0N59T7EeX94huGe8a/rUsfg6lpddPX34LNWEL6E4289NuXINs
+6XZ43hvQEisTgC3Itp4VxMFJjPXmMqKh2kZQI1KczkBeHXxyD23YJwPYEZhRD4CxC7cdAHtO38gh
+Hx0A2xVmOADuSRxtAAyQ2dIA2Fi67ufU7qfQ7kto91No9ytq91No9w/c7qeftNaFdj+Fdl9wu59C
+u0+w3U+h3e+o3U/b2iXz+vt4r4yOwNDYKcgNbwcAYUp5sga/FtphcXCCp2v0eM3MedReQrVmqnKC
+oD0EcxyOrFqA7AJvQvuOVoHQ6KQETkv2Itu1gZEgzZH8av3182Kf5NKuHrDKvrDMehNkbAoWgjNJ
+iJc4ACP6IzUzl7ejNw9hakt5jXuMeQThyV5/c6PmExw48s367PCzPAAzlOY99SdHadrMZlvPAF5p
+GCxzBJTIk0wiaBcW3xpYKhS/py645BAhxGEPDP7sWzHca/goxWl/Ennbidfh7SXnDzS9l9HqvqNC
+PjpUBLG8jZ1iaE+btMozHKktrNs/o/JHzPI2i7eL+nIh/TriKBJFKo4v+khcHlN84EQ6jmas7Ttc
+H7hCmb7PNzPJeGABH2dSXWeiElNScFXL8cVoBeWma8sPLAHK7wCXyAYsiSZ5gaZgn6TVcZtueWvO
+xbSuJacTvCOLTbR9w3RVFLwLr+ub6alaJ7fYE5XKj+vFZMra14sRa9oQRJk9HGRxu7jZ41Dbs6zc
+wsAHl6PFOnuQ3cke3EaAsI5mmF6DRBGs3gKd60/7aNKcqfqC5vL2s72BmP8iALpOdqihHWYPWoBQ
+raK9WpndvZsVflM+oT7LPhIAopDIgT5mt7NnnTDSX5ToCesIadKGNdsm5rp524KwlpkKsApj0TBS
+HXXjKFrr6ZiryEdq4CnNdL2R1AQcrgHocFXX7KA8WnDkBgsd6BlJnAKB9HxoS5C2puPNDEqhxqli
+n1peFCOxH3SAyPg1H2Y5wtOLcCVO6eSFaxYFqyIRldIBvHKuz+zy7AQmgbze7ujBWxWQT+RHMS7v
+WGQ6tZG/ZZHGmrP3EityjEzuUtnfCJXYMauC1zF399VQVLMg1TFvH2XZeuMAX7F8mXA403sx26wk
+oNBnhmXtrWDrcp3fQwrSQODfPZNHDtXhw0JIpvh6s5ii8urpgv7ddgED/7I8VOGmR7UOef/Jyz6a
+s04oWsp4Ok0EB4l7FfZHlbCHITP1RBSyiZEzezD1VNe7nw8FIfJqQK6ib2ZUNc7EbBtcVapJRY1H
+yZCzLdJRLCuMRwushCEaJJbFIS0LXMAg2do7lDzZR70q2kZHqzM9QH0NHUqHdmGHjiCMMosGbYg9
+PTt7gBCsQbYBd6jAKXS5Co+yewmXFbmUB7Z125W1J8jvUD8qh3E5RfqHShXd6d8Jp9CqlZTj6Z5s
+5MYqnY9U7QRhPoenOMJAzXPvy3tRedHFuWopI++3l2yXj2deWMf6CiIJr00ntw32qvoA0C+ffpEw
+hNY9hmV8c7CoZt0Ol3QbNwdM+trtkFlX8oGg/7ITN21W0QZiSDL3fh3P2s1UhDfY8/4b3O0Carbo
+O7ox1pRa0nBPq/fwVG8JVRH1d17BfjRpVw616UaC/UXBgkLqV1qow3h0Ppf22gmCBWDwugH9MfPk
+laaIxuQcEyljVEcKatN1h+ciaUSNZgxn0TUdl/J3ItQzRbtVJ21kQAYOcuMnX6EJ/i46P3MfOKYo
+jGhpAZL5d3JvPeY2OrvuJ6K7CXU54bGrx09+T4Me8Jq9R3dTGLqOtDBR8TfiPCfF7+MxA9U55lp0
+sR7Bhkpq2X5Ym/iMrv2gpTaxyKg6cKXMa/zTluqwH0SV6VJIV/51WMLuNabEZz74aUPxsOAchnb9
+3ABaKGzFJCASDY/R84+AEGrjqj5W7yerJnCrYIS4fbAdhsKwAhJi+NPtQFYJNIR4/vW9sESI58+S
+jYTYZqL+3fOXr9Eek1ZIfzxsLjC8NhnQENt78vz5yy8K+fyKzGE2K83IgANXs0kzJB+L7vewVxLM
+lsDnRfcPtsSJaubVt4+/+Qaw9eT1/m19U52tdzb3ul7uLPMS9QU7S31er9f1PNn7J8+fvXr+zdPh
+qydIM8PP33z55dOXMC1fPt9/NJPLV9M/o3hEGG/txeTyyWbV1KsX4pKzs4KST7s9yxn7322r06yY
+OeJg7cRs6dK3o6vpfDPnSt4wxMFmqAVvR25oOkRpEFeLavbJg74uFddDfxRjQnZsB/IFjuQkURpj
+KkEJ3DZNWWbcdqvyTgNvoS+x288wLiMLJy1AtI+tpcI2YOkB8yCCqTzZCieBis+fP//GzY3UejVG
+Jvb55uysWpF3zkDdZLbPWUvtXdC3Dm93nhAu/uI5cr+XRfsSLE92dqQNP4pQEkc/JWcxrrawASdA
+bemHlT5lbKfXq+qsQOBldHmBb5WmIWki+UFHXxlLeshKFfpqc9qgvTJFk2MhjK0BJ+uLnvK5pjsH
+YlkgqY6WygOQQyWwuhSF4D9iVtRNQ4Zb4v9Hqh2Q1ybTBgTR634KC33mnP0/9Lyf32eH2f1O593t
+N/8TGubO6vM+BmGFht7def1//fd/93dpP6wv5GoY8PgdFy/iV+2yv5gGIwo44U3k7x+pIek1VuFs
+UxexMndRS2SNRb23u+JBc3QwMXbvtomeBnrnfs/2qVSAm3U7XFNeLHNHyykitSBjBjE/FiTAq/Hb
+WfW+muF9vLF51segW2x9iYLJvG7Ws2tYQC++BoFJTJbRnvtB/9O7Mm1Nf3ndbTITTVeW1C2kVBKg
+UK5UzgXGVESpo1yX6BLf8/1gx1e8IicTefxdqOAlVAsK3Fc3oihaDbhq/2xIUYjHNR1IKTfj2RQv
+Im2TZB5yeD8w1qHaR4EXVAA1PNaO6+3tDLCdZHwA6nNa5eAAkC4T/iaL+XGTtlgeCHYiO0pu4o7G
+pJ4AM+5TI9S3xArWvWVIvLDwQqyAGR9TIHZyy+Q8qIUhSkunLtVCERKse8Q1YmnXPJQupnNU9X6a
+1ukSmF+nr1LNdDpzDSDbJYZJQnIkcwvbur4PIt4ANYj8oOhqdEkneVuaaWUF68sxEB+hkT6Ikh+s
+ouWgaCyMQuQ09D4kyXVqQIm7VnSpRYO4v2W+HRzuG1CIvErDsqXUoI0b05Dsq4bDrkrGGiVU2dCe
+KV+PXZ2TLZ201fKHbLvzKE9NrwBly7EhrWM0ttE25AuPKZwtZmL4QusdWKYX3RTrLGZ92ETZmiwH
+PjnmlDXR+zpPGPVIv8wjx7X01KE+nL9HcsPNcg9gNup919ZCT11k5WVrqHLCImVOxSCKwzDSV1J/
+qdpGUgPR8n0YkGVPX6lbIHucVpMJZUyw0bph46E0EGR3YVrA/bPKTjfn2a3PPvnN/V/e39atrhlO
+N7wBi6c8qMo4kWC9LChc037ep6TBhSnqWBorFRPCTCygMFjmOXarpXj1mOZhOp6uC3mNji/r6rxe
+XQ8EXC8i8AF66kp56qI6NkpCQPM1zAjIQbkAeNgZG6eoASmX70b8UAtAKaawAQJUQ1lVqRy69vfe
+dFAOvJrPzqvFu8PXo//KXllCb2dkk0bB/FzM89V0NJv+GX9DNQ7fs4aHxhzmm87ptYRol4BXEh1d
+ohr0O51iXGKAk3Pgp29X1VsUPeTnaJ3NqxUgYXOVVZt+9uDevd+0pttDQ85OJ+XI+miAnqz3lEi6
+KZqE4OY+syq+uPIVxcYK8IpMAKVQbAUo4K76qkwRm1YhoLLjFndrv0xv5E5ZfmIYe37qGMH8mYkh
+/20F+xC+KvCU5Inie0YQNIExh90PCSGIoLG67dCuK2tbULRFsP+P5OykU1COznG/d7G55IXaLtEY
+S0opGYLti5UBnpS58diod3IF+cOP0SUCHgym47fXvBMGEoOpetyFlULRwk7CODJj2r9xziQ8WOEG
+KjF1emXPgdJ3DmsVtJErA7SI6uCdtZYenRcqyJRkuEMg3u1NyymuJYKBHzRtS/ATD1ZrpLNms8Qr
++NE5H8NKm8Gz8EMjcCwWnhd6pnG4EAqqZbcktxzfzJKDc0O1WA/E3UDOfeh76MB0Iq7Bg5KqD1QL
+M99g9BXxQ7ks/GdMmQv0ZuJvGQClJNP1w3EZzlDkeclGsbNyd5wes/l7QZr6RnCLw/kcrHChmPhL
+B5NHLgRkNpUIYdCsW7yDFAvq2ncg1ght9TIg4x+oxa5axt2jzEU06Wqyhy9IBeaDXmbwSbI9/mhv
+In8HexDSN/xfc/0bThBCaZuXXkbXAKSDER/HG8zULYpqu8JwVpQYkDdNmwNERoEvC4s948igsALd
+lZFa+nR40UdLhWPj/3AM29j90nnpOXGhO+qNTk9XvdF4VS+u573RZIIhn3sYOrJa90Zwvu2d9k4n
+de90et4jN4KeE9i6pyBwvX23qddV77SeXPcAErDTdb3ojUcUpKA3rlBo7I0x+xBOCPwz0xDgJwXO
+gfdzdDjoTSa9CYgFk7NFbzJdwf/f9ybwc92r5j2SRHVtvjKAjp7VC/xnNe/R4QxfXdzvXTzoXXzS
+u/i0d/HL3sWveuji30NEaxDT3pSq9Kbz8950sdyse5g48e3ppDcbnUJPZtU50sJs2qPRIxtFUU+B
+mI+Wvflo9W5TVT0Yw6aHsX56HOoGRruoAS2Lmju/qLmDuv6ibsar6XLdkwUDdeolxxvqcayH3rIH
+omvvXa/pSVFVnSOv95o5nPJ6QD4L9Puevq3wTw09bdbXM/ixOYX/L3tkAq6rr2nm1pMeqoxowtdn
+db3ugUy8JoyxBe161Vuve5veZta7mi89IhjBgsR/eBIImRerHmqaJtVVj6KW9poRVHo/WnG9UiLd
+dnvdkvxFT4SlyfUX9njvrSk8diGV97Jrts3vc6aGhK0KBt+9cgeyIR7EDrsp0wu93SLk0kphq9Gl
+300QWP8VE8yMstP6im1pMSKr3GhmIyvR8ZHYWNtSWig+8nJevQksXDiroBZQ8qzVmzXQ5pZYdwAZ
+uhIqWPktC5DwYDqe3I/CkQBDQ1X1FI5477kIKp85yJCMY2v0Pck5ZjbWHiq+3Q/FUyl8Rsr40hh5
++J/Go/FF5UtlLhU9ZZj44Uc4tyIhTOCwymqm+swMp1741bhL5Pk/MS5Pri3TZVSjmOdQWb2ijFje
+fsI+S3aI7F5jfmBEYPwlan3k16ifAIHVbexugwEZz88YjFODVwCUgmCFgcWxQLfh1XOXopzSBuOH
+iWOJE4s6iaBd60XtW1Mbh/djAHMSKrx+X10n1Ac4AcB2RMwngRRanq/qUF6O2zv3Fp0BYuWXtpCg
+0zMPTquXxk31twlkDIcqtntMnoQmKKtqdhLQCpraTsc5tciJPjvDzIZoJsN3TWSwQMG5QYxYTd+P
+ZFHcoth67+vphGb/AmbeRkFEgY4jXLqe8jLlF4Jdn2vcUqaz+CVl+stma4WRsbCYdhBCrpgC7UMW
+1uQZZTfpPkkYHJBD8b3nWSVrPskIjqXCSXBT4VIqwNfEmYaXHpZRnUMRU1zErKDp9w3fb+1btMag
+hnAPQ1XCS449naOEhcHdNLHKPCCeVXCIC+ygjwt4Y9SwsuDWeP6yp1YabOL8EGkAFJ80/r28SlAK
+IMt3aapst9PGIGl3QHruZiAU3A7AlsGxPwHGdeHOQHP2tgahpYcY/+gRNAdnHelgzx0w2UyE0FYm
+jC1lroyTHRaLBRHRQLRYmDKlXW0Bjna35bYR3DUDMAjehpjDNGJipoeQ5IwtcO+k0JI0QB9yRk/K
+0tEy7cmZuCsTYdoOvR3TrDkC88ihxIGy2NERZt1YUgv7ltV4VqqoF69AgumCqIbj7PtqGlOg38BO
+r+Zw1u5KaqqEOkYbjpnO+rYztlFR7YWzgRW3boE2APiqUgqWWR8OAtZtFBgDHSB4GeyplQj6KXF8
+4XfTroV8cEIRA4ahGpLioikOpcGkHG/d1Uw3GeldBXX273biG3Jquof7WSrAPGWqxy0eS8lutgfB
+2nrBLsppHsqUermbHTSD/KDJu0opQ2AUzu1EpYhZJXyy00L7LchWU46VQNIaAKBszlpujLYtakby
+cCEJ0u/4OnOPCybp0vHJ1sttgG7CVl/d6R4BOu5k13LOo/OR7ZA57Z0kW8GthYoyLpFDwKt/hO2G
+Kdi25AXC1tzMojYgYkAXHvMKjruE3r6nIHW9r1ar6QQ4LfVRZNiq0bjVikh3QPBal/3z52qaAzAp
+XZo5DaaOiKWkCpEsFEq9lCn9Uic2ijxdkX6F1AusEEDNyMWKVSWkWCE1QjcppndZL0Oqha7WHYgX
+O6PoBt0ZZaj1ykTrlZ1mRn2RnU7q7HR6DieDDHVWHIdrcoYWWBkVSPSwO81gcBl1Mnt7OslIcZS9
+yzDG23wp6QQzUtCgqyxdCKFLbQoWK21wzlAjnhmlTLZeZ5sMFShm+EC25clH8Vy69WHR7iN4Lpdt
+Tb8Q5GkyBE/KfkVuRukfjMJr+GZr0sR6EBHXCOVc8SYrrAUQ17KqIImc0GIKF7m6UGHUVHgIA3aE
+fOkIH/4B9ar/2C17+OOhfTuz7x7Zd+f0LoT0D/Y7EKFUyru5fbmsm6haoFFBv+rqbLiqrig+ax+T
+Z6PxDQD6i9n31XgwYR9wXy1kDUXBZo7ylPiu5SaGgRxzcmYOt37Pz0ngJc3ZsA4t2OXg6CJuVSoT
+gK9187c3AePuWAsDONlJh5I+rFG5tDODdJ3qdOwUC2WACPiu/+Z/NAH1V5vFolq9u/v6//yMw+kD
+C5qOTTZFOkVBEYqov1zV6xo+ZMSRUUsuMQAoFmpguMmmp1MkVAkJCs827Kmxy5vYz8bT6CUsvP2y
+lCv1+2g661raOaK48j2lmH47XerP+Ft95g7UKy52lOnfqlh1NV1rKPibP//Y6dzq3JL+muTOlP/r
+p47wz75f9sfoDMoMkpnVvfD/k82KZ0plWI9ydHMk/+liHcb6dykDnql8ASaOP2Y2eJZh7kFOurDe
+LO8SHmyjWfFscI8jQ4BY0M9hqX9IQG0Hb7ArsrYtatPJ2rrR/rBXnO2JkftcxmBcavhShd3u0xbk
+KflVjGqpEDlnGwsP+N7DQGXc09SJYaJThNjw0GKtNPGBq2FN3OkP+OJgNpqfTkbZ1VF2ZRFVqoKr
+Cg1ZVDoEgm4QqO0To2Dihgr8+c/LpHVja+2DJgQAArL9oSLOm2Mv/j0+siWEUyvUB7hBXSeFrMbg
+2PzD3r/kR0cwf5gjEZ7yMu6vBJ6+96D/4KzJDg4/kzgv3mzh7Fjk9qidy4tq0ZOmg0S8EqSfrGAL
++SHTL7/6Q1pYSGXIyV/hj1f4A2YpBnQGGz45e+6A1F9Xo9WkvlwMYWEW9iL7GfTRZUVK3Kegddva
+QXZG8fIeTZXl0Run7CNDs48UnBZ4AaIlZX8+sjl4+1Od5dnUm9XnjKNgJgdUhZ9d7/it+dUTizNa
+GwyvpRsD2584wyzJt8na0DcJQWzhKDtjpEM2fyUPW+YtUjOnCckJhGkSP9NFDjyedKwaZdnn/Ht6
+mVNRm0c73QK+lga8FnZUM+TBVR3rjzHloUqAJ6eexlqEs52izSWAAQmnkLzgCVjY6wiUfCzSVcyI
+tlDe1nVSXcGuGVb2W6LBD/EZ626agt84g3P+TfyAbCDs/Dt8+0ckqcB5DI5SsbGM/adcZsJ5BG0d
+0NT+tG6qQ0znlVJE5BVqQrDlp/QPelHnvomxtI2i0DJs3ECRj8TCKaXE779+8eLpF/nuPM45Fqf/
+d1iE+toTLBmxaeJkdupWHV7A22zVEmSeapqpR4bi1ZUaHF8ePuLFq2U9apXA+xQzmo/eVqpHAwaN
+TQ7wH7t7YuYV5/aV5moCh/8MhGDiJaXwsWtUR3ZYombMg1bxigNrcDdl/OaY7fDQszC8/jyBPpAD
+GgsTRwxBI0L6wd0a4D92fzGV3f3+y6oBafPuU1LUmZxd2Uj5ZizeCx93Z6ZbbLiFF9a2ospd1jfx
+9sVzzt5IpaKIUuZE6qSXls/4L9VnqgdH5FkHr9zCZf6qa2remc+reS3nqSDvGzGBgZsIFWV0RJSH
+h6ai3HJz1xo0ZEU4lYygRTJmyO+r69Mauvk1mkatNst1S1TIRN2WRh26je+LNzU6eQvK2LPrxPUZ
+nEeWbuQ7DQxtMA1uOnJIAhaM5F+ZfojzHdlC64osvJfbvZsEGONWImKKwSy/6yWy8Rp656WA2Xib
+R64eL1uGXdrkFM1s9L7CbpG4qewuvAmXJtiUwlahe//OHprviTHDsFWdaQA5GuUHTZ/+RxL4cVdb
+uHdPjo8+OfEksbAPeFuEUI4PmpOMUrVkL9gQ3wVH9EOfHHenk+5JDx+a68YEZcY373FDg9ecrA0v
+CrqJ0KGGxXw+aqqXzFStMVFnP9OtFmtiRYkqnY4YCWy0dZhJHWTuyszvLfnuyWwmzMu2WXPIwIga
+OFEikkSZgmnaA7iupyF0m99IDQaHsYX8k6zG9tIA/ODgRBZS/nCzoIQfdBtk4D7KZQYkA/UAtVHL
+arW+LvSBFqCMa9Yo51xSznAsPe1TTTJxcTWRbfapZ8Qg6edvTQUXggctpS62mYDLWZQV63T+RGep
+lCAbSB8seAhU2VQoP6fdWcxh1HxALnsoTyMJLWKT1LeY65JYYAqdlMEGS8Dkp1Yd6Pdu2BZzdp5S
+C8hu2j45bmk0HfFOSvTS21K88kzXhBaSSwdvToOGSWQ2+wnefLkeQMOkbkUqca23t2yoyRebXZvk
+AIrdGK9GUZAt1UVK0bgSl69sZby74GkOB53R+dYdbwcmpmeOyGgJjP30mInu8BkNN3JJd2amJmFi
+gS5/SiJk3SKnd2XZamdDQ93ScHntN2ZO9jAtL91SsnqEhPog/s+shp7BVS9z/Je29paKZj0OnArO
+ZhSw/XHbmDKG/Zz086QhkwOKOEsUo1lTYwhODk7O6KJgDoIvmq0Gpo0liYvqmthi2TewW9NXB6oV
+f1C7cQB94dRqgwKI0A79Hm6+FCo4yIZNaXSmf64m5hpiKral2TSwsLOqPH7oaDAjCr1cgSCBt9nK
+txK6UKPPJ5ECxxZHm9vpWLIcX3hZtuHEvxnN7NgpTTejHykkO4Q/2RxDFeGFN4b3rMgGzoTe8M8T
+NBoYFx4hqv55H9fQKHNmotPFRbUi42GqP1IA2SOyv4fKzcMBnf8OH8n1qMvlbWzBya0SjsuW+QPF
+aAhk67lq0L6wHk8pG7pEZWYcuJNZkIvabSbm0esZ1bYEM5pdjq4be7KSLaFn+U7PccSgHcej5Mlr
+xZwQRzY9NKVwbIyKIUKnZSBWbNPgpH9dWltoqI8rCv+aJdZFM1ihpcpdnIFsFs6cPvrpJkipDW3A
+0huzhQ1F8pOQ2jpN5+XFdHyRLapqgsHzgjlrLqBno9MwK4NZiBS5hKxcx6JV9+aGru3WALV+iwOC
+cWTkTkDWvDAiH6iSLcxjZ7s8zYv+BlneHVPEPO/mICUznk70rvhDL9NHLUU1iuny/JFw2sZ9W7ZD
+mUl35G/XmxuuGLO9VvJrm77Qxr8NxUp4RKFxKDzIaNPkZ73yVWdWwWO/94dKjREoNXg/TcltHyID
+RrEHdO2fS6xS4wyFBt08DBz3kJwNREj2+ltIXqS4NSKw7bknV+lel6mA0Oa8aGGhBrp2gboTmTxU
+q0+4VbNeFJhWUdSW8DSJDOdlQI124cYihQVvtJU4UmDBrIDpikuG0zZ6DURreou0k5BmRMnjyzMt
+izkUTXbsWjdjBFa7Jw+wxUVOP62sfm/WHJ9hjZDRwqhZN8EHXZ4I4bf86iYc35s3ZPqzasGDHRw0
+2zl/xP05o4NFW9myCUQ0rW1StgYX28LITUyxPTRHVgXiweBkYZzZ2XjNufvfyFeuQbugScZXxXIO
+ILGW7DJGZGJEhwErwpLPl115zRZXunCYFHootReRdhcEeIrQ/sOPytZ9MrHfbAov+d3DTqjrODMi
+WOSjMQqctqSJFcxGVVKr720Z/M6Ye/Sg+LRhB0fogg/rYqTS3jYcpGgS5gzxbsrbmhrxYQLPjsaZ
+ks9jI/wGYrAzykfnFJLcKFsKB3ThzRfGRlebDodotlFms9GanOz6Gjmh+49LGmaRqjKHORlPitu+
+L9SEts6lDvQiNXsw96W5RrYl9Tpf1ku6vbNXrwEhmS4MVA8CbxPuh50CPH6YXjEzMnSjczz4GGRS
+i+nLI9RovNgNO1Df00/ixNmyYZCgBUVb8iCFmYQW3vXGluG1dV5SZPgjtbhIqIbtWJJXzWo27I23
+vrFhLuHRy7ANASF9NfYkliQ5PzNjllFcZCvk2W5zkmWliderMqArniDXRCpmSESb/mhh2WE3rTug
+Hm4yBsmWOcQlHC5W553m4CYGx0YHEkAiZbfANhnVpJoMHRtHwUOKCbfhH30czvhihOSXEhvcINb1
+JTw1RQQ6SbamtMhQUZ19Z8bc58neMohBHR/Z/ZwKlYmkc7FDbeuM27EYi5O25Ua7K+sgOY5UNqLU
+bpy+TXqXEWrNBoV77GHgdWvYv9XKQbvvp/WmmV374Puav6fm1yxWNaMfOpcSkB8T45BjI6bIwoQ2
+of4NOAnfCU9o40JJKWQQ/spuNXdEvwvYmwTpQOTjlMkjnO9ON9MZCDB4LqOWi9tQta8rlqkuxGQT
+UM3RSfLyGbcfYxZVz/ZI0YG9YbOm5N2XPZSma+pxSJA8eKIb1qJsuY7v3IJ18RH/QX3Up2TPWf61
+PeTU7GjXi/sh4RKWkdGJgoBl5M+wYhGevHGphIUI+BRWjXLFZwbfOI2ZVj6aYBVsDHLKaaQaNklX
+dClSfLNTiw2SuBg0L68xzFeVjPfQFgmYq5BlAz3tb5kQZWRS0dj8QL9+JCSHoEc2WnDsAt2L40Rx
+d+xhgVUeRTgfNtwvpt69ALKfNheo4cw+eYuJ+M5GbynG8wzDbkjsD1mKjVREx/XVhMVxCsAoTalr
+G7rIpUB85FS2uruYjsWmejhkjTZ1umtAd023vyS1R1uvyY+Q+RAryhNStNENoUYE9jpDGTvafXo1
+XReRZUyiWZRR5vNqgjpxvB0+X43m5BTQZMWizohIMHBCc5cN26dVU+6gTptyFZZdU3vCWQttRh3t
+Jw6nJvYTdptXt9w4iI0mdrpwp1gcJL6i1YZzB4OjDC0jvDuKm8wu4cN6NT0/rzBRhkK0xcHFdBJE
+h+LAd09Ny50Otug0eFAUv0nWcCCrgvCT64MuvOV5R4sQYlLIHWzUCT4ciq6tn4EAuq6OgAF1GziT
+bdD4iECdkrEk0stGwqIbusGbD1IsTs/kFoRinldAJ6vK3H/AG4mYY0wFOKcrUDkxL5vXteHslfNp
+Q35FhFexb8EDuJAF7jvVYgy00se8AaZDbDuLDXA98jCRuDJA3QHv2wPxhikgVgn/vgIVbcy5BM8A
+LSGegST3ZJLh9VfN+FoR52a8WeHd1ez6cPssfSuzxEz1aLQ6N60cUSBd9A2l4rgC7A0OJR+lrJz2
+dieMNB4k8KKQECYaqEWSPauLz8fkxugUZiXYdCiSv2UH++ehl2t0GL3a46gA7sT3PnNKkt4EIauV
+BzVXA5KTYKnoNE4qACDOi+k5xuQZDo3N1hAVHQt7I8meMrgKMozRRslnsq5rspsdqmwBxFK1rl1k
+E7kJlEUm1CjygiX1G2DT+PVZHGBKzG71Hg2YOMTMGCGCmASiwRWJn01sFgcskDADTFAAldoc7mv6
+GJgheYPLx5iBXCWRldzXpltieDXnKDwgsvEENMdSwJrsO3y2OR4hkI5Y3EmgC6PXnmOisq6awa5W
+QvgRAlxDYQx9/oLbhi1iDIz6Sc8cW4HOva6Wbdb0VB3q5ZUCnD0UQG0oFpo9WBHBajo9IJXnu80U
+9ZjTxiQeTxtSWEqRLuhl47slIKLf3Xvzn4zjo2Gn7+6/Pv57dn1sNkuabVKbwue7V8TIjBkyy8dy
+Id6PvB4ZrooO/FHefzud+labBXWv61ljeF59sNQ2FbnzNetBbioo/z4JYqnqs1cfXviSC0NWIXvm
+E+F1hvuexH5iSP79Ijvh0eUTPZkrRfbNg86DZEJmCOJEJZhUltM5b7eF3TVL9tZUWwVtH84wHKQX
+AKkqZO7MLHa6FPNrRExGYmRk2VN84EvrCzrtcbgqkXMVCCFTjg5vDML7IJyM0FWBewcdRnPVvtnP
+UWvxx5wS6v0R3ahzf3yNVQ1IzmtEa72QPC1QyQoGfQpkrqpfrNfLo7t3hYLr1fld1Ao367uGmPsY
+VjJXvk43QT7NqUNlT8RQOTQBTciWTzTAgzADsROiOjsyym02ebFbdDxlvGXpCVJgnoc7FdCh9IwW
+qghw1i/WuCwzcWNzCth1vZGI8UTYlGgddhWWThLj6ZMQ9sEzsI8fM5laEuoH9K+95flepAppyxch
+PuAcdKUOQtQxfiGT7MnWV0aAC8Q2a1bmWGIgyTG0/g1kJzNMrll2riJZ6XsjLDFevgXqk/VrdvDE
+eUo0pX4IBQ6YwNcN+Ce4sXURedruPy/q2URurlpseD0jWcomYWHr7Zt7fFrXs9Y7UPzIlblVc9Bf
+1Is/Vxi8kA77DELlHR01gBsTKjnhK7AOrc9J9eYAYJz+TRVWj1RfesxDqVN2buZh4nuXpDxLjIfG
+dtVYkE9I6hzfP+llr0hSJGGvNcn1Mafm1hX79dkZUHp2J/u0hH/yf8l7J6naRlWYq3aO0CgOp0DE
+1Hyf8GHcE0mxYNdMn08zQ6tQGdaL2XVx2/b06MGJD10xiyKn7hC33bAaD6QtYA8rdnH84yJvTeeW
+4z8HzdYiB037xwNN9dJbvMrG4HocrgNPnWV7PjlzguIw135KNUnVEpIoBVzt1k33yOCxboC8gW7c
+G8rZ0OVNEd66FcuvXNgRZHDmSpAK6KBa0WKYGOsJrNYfmiw4OkDhHlGofCj4jwEUqQcnXuCY1IK1
+adiJdwQN2ctOhc10ED2ujmlVml2OZhzBKU45xTRnrwW2QlRrXizsleVL+5Jn4vIPPnEAIOkn+SZN
+hiSEhATQyxjUpEzCac8NHq09t85M7LuRhH3Jy7YRiV9ZawM+vqMkXjdG4k1Cz25pW2jSj5Xr7LHC
+JWz2RI4K5QcbadlUhWY4tQJtql5VHzgKQKNF0kwJPxnap0RPLHR0w9t9MZHD4kfbbOfsDrpcpW6v
+rJvzHvg1Za1YfJShj65yU9TOVVIaO9jpdH4rlEcaS2BOlFhsP/f7yFWG5SYB+KVJV5YMLIIriE5n
+A18mExhdPhu5HFqmfN+ICy26AVsumEw5z7NrBxZiMbWldT4cyykILzaH9AbEJ0RHIq7A8ppYLoUV
+4GeFqAQEVUY8s1ta8VHtmI0JV2MO5opO1eCC4WoatS8TGNVkbIsxzW+Q4IO7r3Ai+GyQHz97/vrl
+m2cnRIsenGBidjipDYechoAMkYxwrnzWPooOb2HErPWaTih0RMSTOkbxo+OzsX+rYavcLMxxtNlQ
+1vlOcCsttBMX7HpNL0n0VkPqywnSTwBn4r60OUfdwtM/XlSTvcBqtGjwMIn5zeoM4yrJZGQVOU42
+2RWaSQdSOLQwagyt5MzPmHWgnpxdmuLhlBGULRbHLgiBnivPwti/uN1trx0c8soyTfs6IAFOi/3W
+yrFNgdRhpZOwJ+fb5Jt3+CjyNlTrGrpNeozC6dyifF37kNCuGfb6zZoTfTmYmNq0/bs/v7v7tos9
+CUqw7ShyyE3YYMTm7OG2pHnbxf8S850WrvbBknXw3MvncY9ltVuoDCZmC1m0s+bODqDqZ+eWMX49
+vY7ioPEVN14DW03bzeLeqDhn8B6Ogqb76XA3W0POXDm3sCv6h+AkQ9ekwuZYMM7P7Hv658XjV6/y
+AA+kEgxwYdjDXb6K/ZBwdu3B5mSFrMmhA15jpEd1VLqlI3UbTNjbZ/lpRqbDiHugOWAdygN8Rr9X
+BkUTQc9+9/Wz10d0Td49XHXlChG3Ltxm2T8tj4EYzTejI7TmafIyruKfSYR5s48RdKTxA/EheiQK
+XxJfuGKxCC7Wq2ClYvTCoaAwmih2F21Kn6wsrO+TsBjvN4GFs3j2ZQoYJ69sg9XjuJfVBPbC/MvH
+X3+DITXaGmheJRsQK4AbjvzpB3WWbmu7Js6U6yzGSMIiXmzA4fqyryIDUpIalu8UGeW+4R/FXiZ7
+XQ+agsiRKqYoN7BhyT4dx5XSy1gRZ9buZSoGJbTgh5qISrhFh08ut3DAolTkwhT3WtaNF7swyrVs
+47pxp7ODYomasFKPehfRc5NX+4zFcmM7oKstI7q68ZDkrmfg7Xntg86/N4sBHYNw5GUiIwEJUXEA
+AQ9QZk/gcjfhIXDHShcE2nAlWxHohSpBBIZx/jQCw28/PQJxG7Qxeph4fAxoFVqoOPMOdM7alwux
+CE/Vu54TCAmC7qPLqpUKeBQVP8bGTzr+zUOgYb2lLubtO7JPzB49wsuFZj0BHtXLipxgHs6njTE+
+yHztC/6SfLgmoIixXGEszOHVIMfuKR7V0mtM/yYSXGEAewpIk9tXjIXOUBc2Id7dFMLBjXOaQxup
+Xd9j3ADUu4ayFHo2DPh7HJ9IvBPQXJocj4DlfwJYodK9zHNkmGiXIPjiuQNRBXEN9rdsKkmf6W5+
+EifHsxlBCuwGFy17eBVj2xe0zDQr37Gf7ZK8XLQfT0LqyvsuDc+Qd4TUW066ArIH6chVDIUrX7CK
+BaD8wEl0JCX17N33oZhmz2sxd9OxZy0AsnUX2ggErCAQ/hmbJAzSdOWls6dPgQbDj+M7VIEavP06
+j1MSLTZwpDeuotY5mlkV7nyJ1jzuzYGLOMNKLtaKcCwu245Slgfiw/Fvjk52cH8MY5kdH0wwdNnR
+weQoEebXhvvdMhZA/7sHb/53Y3XEiwuPu4Bum8j+3Sev/58v/u7v0inG4bCBuhuOnS58ZmUM08hu
+qAdrdo3KMuQd59WCi8ZNbtbTmalobxbtWbGXfc7G0I9NBeKgnQ5uOOuLVb05v6AA/NopA3pYXWmb
+7c2q2upZHWUguBrLDaFkuaHn9Wn7ja917RXfatP6P0+rOAsmvqSsGpyUUCxMvz7LnrDDpnVGqM8I
+AHqKwsn+SXFVsvdDhaXg7Ht1beLsjAATou2ihJj89qqfZa/hp4SLsUDJgJeqyzXQE6Ruse7i+8/T
+DV4O3TZduY3VnlDKSORR7hi6QhvD7LSa1ZfYmM23B/vKxqaTvBRrzfc4cO4FOSjF/Sn80T8B1NcG
+DYxt1LHI8BKQrgSZ9kpT7OPYtJzGeoaYMt4D3CrZTm/WNRrpjsmqB7CMAXEQHoJ7vqZkksvKhGwn
+u2mjxR2pxgASlEJCpog6rhFcD0KDGodomu/QIvNlpo/I4T0QMCchkug9DI+R0RAASlo4HLqOCBYQ
+lsI551qR2794KodDLItGuejSyIgLTXOlEGx4UI6xCn3+/NrcehGpSkMAWTU+bSyweW2U4mfTsT/f
+2eVF3aiuYNxdQng4y7JiFnDQ36DxrfXfaXiCTUdGK/hKzgLo2GwNgziFHA9NEROZuH9Jt8NkS9eD
+RUeXEmyOTXdY2Qwj0FDqANssA6L+Ywu2+4Os6Pf7PTKb6WXwyDpCNJgQy+hJXTVo+nU2XaD72rVE
+LZEW0JQ1DXGKcg8C7Jl5WmT0QfIkw7PBEcbOv16TdT8K2RqXT5B8gHWRjzmgeTpBdwl2INAZN82q
+mgHNIGN+X82uGcNJ8sKkSxh4akXmV0BeowXZbQO9Lk2yTVn2htRpS1nTqjsLJruHECRrEw5CkSCP
+Ec3hyDNQZi30k0c3ex2piozNyG4JAQWyvca0FxtigW+LVV2vqWuE6V52G29/gxDHZkPASBoc9zeq
+HQW84AVMFcJPthIVsL8CwVkKW9Rsi9Dru23ZyhYbxwBhzzy2LaCYFszy8D2N1SW6xq/cq9iNmTIG
+ahlVsdmIj3N4tuxiChwaVvw1oYk5MG4dGsqqovWFXjFLm0CapqmLemSzT26zJDDzJZ3Uo3D432KP
+J9VVqmEFgfwTHIgen0xcnjJfMy2CWH/aOEwfhaHwGkrgzAVhHPNV7c9IrO2XSj4hKP9z/B5lYmQz
+jOMnVPCJn10N+yp1n/TNGjvp7GlsYi8E8HMnzpDn0BcQnsWgXpquU+JQUIGs7N4W8borfa1eMLbk
+Bbe6r3MDNuEC4hG6Msh4VA11Vr+op2OX79KjlJBGwqstqbvFXFIP19ex4rlN6tPB+34SipTA4LDt
+ZHULzwqnqBMlZxy8zEN+LXVTYDEDUNH9p65gznakB/x6/9A93YOmOFiVXRvh2huuSp2tl2cpyo2A
+OsYzswRtDm+VwdsVRBbsK8vgm075HVIdQQpI43pazSa6Yse9hdLW+/lrc2pDSbEgadkeNx7zgQy2
+gapij3lxkTqDrZuvSEQ+tibS6gRmIqcpW9yhnLRMsJxVMiecJE801axpW1zhFiX0PiS3N8ST8ThV
+5mrY7aZ9QxOjMpAB+k9tpcKfzLB8HwNxinl19yF271E3tbUxq95VeMwB5uWwq3rxBN58RScrtAMi
+nR3yYHwd3aqb6PgrStXKiszIWtM7+d7Udtm5Bm4kqkS5NYhXeC7WZBG9gqnjrpOVhw5upTIxbhY3
+pAKKGoXngBsQwbck7RXsJIIvXq3n6+JYz+hJuYskoKvbJ5lb2X+CZV6vqvHwrzKxFuno4D7cYoIo
+KzZWvxThHJeW4zyDsRQe2xGAah9DzD+zngvCPDBcWxsnaOrNigIadA/ojpDKNkVp9BTWLhg5ubXm
+3ukQwIiHtskgQy0vbq/8iaciyf+gde79nkP/b3uo23cIb6wkLKmpxuOse+2hIRVM1Vnz+xlY/z0j
+aMteyMlfn9lRldw5LhZKdWwpbpZUCGob22Z/IhNicE4xhvZYzFJ0r5EIO/Ylk4TZMDHe1CBJAWJU
+bnyX98Ba7NfLpjWMj2/snRC2b3Hoj/GG9XcovGGoIooSYvbtJqXlp3OnR0B6l0tr+RPG7DSSEDX0
+Nt6THiRx0zK3OV2QJvOYOFRr7XqIX5/Xe62ZNZsPcYegoKnDWXVGuRHVqxWGHcfmLegbJwcK12S7
+R070X9C3AY1YIqR+EBQazoBxY4SZRESlLUwiZhRtzGKXgKZWFXXILODHi8k+ixeK7btwDQkEQZ0j
+vxmSyJJSWEzbCXGrjbJ1D+zNbUC7ibVgKUjNemfnClaFy11B2xJLrlt0sztZl7atLruR6e7j9XC3
+tJF8nq/2mannq/9/on6WSQK0bJsjCmKWvaFUBOqyZzDovK2q5YjCThGeSfvfGEUwPC1H6PBNl8Q/
+yM0MiL5Aaxg6BpMprTVTId+cni33NQaHWGO54t+CUqUU+9GZI7DrB1ET9fTxCm+bU1QVUxarEJyp
+RIK+9HAG7rHcg3gSm/tOCkpMlmvUZsDtppF3s/+2E+bNNibXxw/bVvBBb05//U1FsisJWZvF6yiq
+lNXw+TSxHPaj/8eTidB/EcoMd6I9tlQL4tXmtK3i4daK325mbRVvb634xfR9W8W721usW8d4sLXi
+i/qyWrV0tb2vaT7Ac/Q3YQTU4SQjwC9lVLaVEdAw05AYA3HpmzAVtWJ3Ltgk28HOd3sy4HY2sjc8
+GgEAlJEoeH9LvkRCM83TxwvNPLJ/X/xNrRSnysLEIujNt9cJWMr62g4TFWObqkNdCClUiYERQii7
+H6u8uNmuGPZioM+yf2M1iJhSJZgB2Wv5KT5TbKBdNn4/4gwAejGeLbpHDIuH/2Ni/rziRdeTtUdW
+0I5DCPhRAUasj/49B2NJyLISpgXJzdf4WVNY+hT5z6c9thw0m/5Gw/HxO/JX6aiVv8IgjZZcYeVg
+gjo6vC1EFPs18M2xVDuhAaSlftPfKDJdMB93BrYTILv3uilVR3QyGbWz7Zb4Arax7kEzOGh6pISU
+PvZMD8q9GmcIAYAWvq/ija+GMUXZ1+kVYj+X6Vo3nFas1906mQ5yYlIVDm/jIax92pJYozqq66kJ
+NOiatOBrsgNhkxaMTT4UZWgLtB1lk71x9kFIo0qTHWhL6w+Lg6aMtYfMZ7XmEINgJo7S/qzQOPrQ
+JzaJhs6H+mnDXvnh+Ojw/kkngYZte+Mu7SHI0z5D+rkvUkXNRDhTdyFMPqiD0Lp7kh1SqvuVHUx8
+nbpD2O1ilKQfDpDc8elH4joYwbKXJS70WAj6Suyb9pCBpOhf5xYguQFTaeamvOtCd7Zfj+0kkr0O
+53+VK/hoLmWkRay+9wavfSokX4I1mcsoHL0zITbySI8NkCkPJ6X6hGniCNvxBBRdc8ES4KqHdwKc
+sSvn+7tuQhCVe81wFk3NaC63XOXhMIZmCHY6jVgch3u62Wz/tNMd9tWLUkR6TvX9b8QBSNHzsjq0
+vh82qywFsrYWGKT7MZcO5JCx170DldzHBIS8c5LMAr+UXrkks7jFwf3ZM4EX+6gB0hP3sYdq2Mq0
+w+cNBHy39YuBiTst98d97my9cFANlHuks2d+kXaD+asfqu3cT88Xe849lNxn7j9+o9h5s5CaxX6/
+j38wklDAXVOGSYcUhJiJa20s1Uc0xrnxJxB3RQ8B7ujK6lKyiom12or1cBzvLbZM0MSJX36b9dIe
+lksAIWW4lGC+2orpb7xxCkF+MW3Go9Vet6BS9N8vSUZ0aHKm4LTvMUAst8/oyCIVym67I6TvEQbg
+ZRkVw1A5ZvxsNyvhV0zyV9N2MFpqth9ZqLkAbe5l8uYTTy3oPMLRh8L165/rg2ps6ypu1pjokrxG
+CzgEoWMlRRolsQsd/pSNcGW8Av3Duwu3VjSCbR0+0FxpxqoNfs2uhegFQb+L+2VUwPh1f0kFFK0J
+oZKZb9HY7AQd5TkdBab0bWW5bFLrRvTotG4eP0iq37avdbfOpZznoEnvIzfLY3UojKgqnZ853naV
+ei88hFpHe0MB1j3VBLvIDDW0UCvS/K0P/w8ksMcvvs7uZk8XgN9sCcfqdQMvPxwg5/AwE2nlXrnZ
+aS4wmQQhUaLZHpnsERhZPiQBISyB0UXe3y0VTUjIgvwckM4g8p48JPJCSB9MXOHrZdUwSb+Gx/Jo
+f7L3SFEcvBQX+hgaMy4/IZndiLQVQbJ/s42hrHZXE1WZUIhBlR3rU7MUZzXOi5BIe+S0S0HAppwA
+aVWRwIKcPg7xlds8WEQmJmsU8baG0sVOppxvhGJ4Zdmrzfk5ng3rBfDHBDx0A8ejpnAcZb1/Wp1h
+ZAARlvAj2nfDZn54yL8HsJSmizKZ+0MGzE4IEk513pwXJo/4UYLEbGb00N3GRNhzVGXD51FqeS85
++S2hVAriQ4H/1qcUHGF9qgtsI9FbJi2OXYkIwGzGvE2TX7mJmGcJ4thowpyKDE7e69O+PY2VfYzd
+a9LeXJGPV7jeoXxiyXPi5rSz0lUYs5jFLlybdOYoctuKTE2FVLI45EDCEpsEwPiZTq7s3H2kPIBY
+kB1Yx+aQGFyqiiR+6f5xoZIMU7njeyeoVMyz7OFDYytpNvWyRVhAMKzuVGGoMO8Ga02PHJxAWAg1
+r6iZwXQdKlJE1z/VHZlF0vWOxld8OL1aH9//lQSKMD5S8FJELpT2/srCx/Y9I7Vd/Ix8O5QNOp0p
++e7SbKCWo4tuc1NMXGRSDYrTsAsQcVbErhG/VNGcE58/cZ8viquE/9kCnbC7HRe2t8ihmew2QsNu
+/TIv9TfiukUZvyzOxEL+nDPl3gvKnDG4c1t3Cgj7VJeY4vcINt7awUuqfM//pHjDgzuf3PkUyGtW
+j9YIgIkQZi4n7uPXuzLjcqVUjmFoDEijrpdNV6pxCdjEehlGub/fyx6kv3DndVPz0VVxjBBh3Cc0
+hk/9vnQvqtms7h7jd6KCC6/V7vnmLd9eXhAW4Nu7T9/8B45V8u6Xr/+H/45yMXX4xRGF9qVZMClH
+RjObmJB8615QNrd+BysNhxSuFC+hu0h63ZNtRMm6W9y1Kf9MMwYOT9vl6XXWlSRxh3MJ7Njt2Ii9
+kuuQU2JiNI4sx200d8n+TJiHsxpQcUn7PkklHSWgSLoox/ZfXTew2VBKRBvPe0ryrtukb5l8QRS1
+7tqmgOsY9aeN+jKm+EDcFMLpZW8wRxtxvV6GaWeBsiYcv7KJqpuaBAWwM55PkBe3llP5u/ic7MMv
+JHvbsl5uKMSxdPJ2ZrPiYPARTD4lYy+zy3r1tum8+9Wb/6iH9O7Xrw/+SVNI9oKa+BYY/zlGejod
+NdNxhmFnpjb7NodtgN0e8/N0inGZ/a6e4Qz+flW9rWbZg3v3Pj18cO/+PSIiHXunbsxPE4XHxehJ
+4eGirt9iORzuBQXFrBYkltExA5kW9QxdHjqyQoHZK+ypFGqY3CN7hKR8Hy8AP+2eYGwyYhCz2UjS
+q9bA/+dGRESXBIz9UddZPZtgBKJ5/Z4StG2W56sRHDiBrLscF89rVY7UGH5iKFOGlxAdCkd/Nj3n
+jE9zymwtgbNw3SwwLCyvk+XklKNwIzLGo+UaUz3ZjJXQvXw9X06mGLdq8ba6XlIav1U1vhwBywYZ
+f12dAnAkAGlxgbFJnNh9Dnjk9Ymw/hWbuprPRPE8q8+zST3GtvNSMGj1Va9H569R0GtLFRQGJBqu
+R+cPMIqJi1Nhv9GRdRVaePD1IibuRLHhXirTwSLptmu79mpzKgULk2BQpSWn7KuSY1GKQR8bMopo
+Eik/pJfixxfbdkC5dPYNOwYKfXhbDyyRvBpEEClsUrqMlkWDaRmoX2Xako47h4ofINbjg+aEzvoF
+t9IzYHtZfiRQcahluTPChpm1Yyx/UigE7RdcY2mNNCmcXLWWjjK++UdIKpYc+MGrLtNWr7wZs2+D
+yBJu3+dycSoTfI9CKXnm4w/DKY7yclt0iVgnxS3waa2zDYkoiZr+RqsJSLY1zhf6+/OIQ4zhFwms
+4n8ww4M/CipHHxeotwNytwD7iSXSDwlApmV+HU5Makoc6Ggm++FE7r3a/fAthW2jpzBwRzEARri3
+vfnhzRKYxz3X0zK5uUW4DyR1cMzZhhicA6+DgxA9roDbF5SBH3+6mNJ9ZfTBpEy3RFOUHPCUYc1p
+UHmZbGg4maKQR/oDBRcWSw1HksX76QqEPorO+OIPr5++ej384unnb74KbV6q1UpOMax09D9iWgXc
+nlyiAQoA2jUfcNvdrM8+6+5hJswtwbY6rfuTzfKMgoEiNANsYB6S9rlWNZJIyREmfXC4tTQqzMqq
+VQOcolgCvfsd/HlZzUbXxbERVECmWM4HyeAE5zABJtedxj/S2FEUzpGkHgzm6YsRLfbUkqCXCxVY
+V8ct0E33JN01ryrJRQnSJVpfRZRudkBN7CrIOZ3S8RBweL81PwSp2l0iQBSeDHGYjnTNeaJLjLqY
+TuRTmbArnDZmONWk0EMpUzdu/4yKEdH98MrPMEbpaHKdOTCoABlwbF4el2ndXaM6EilyUxFTT3HT
+tkY7izg21nMS4d4rSGxZ5s4MKXd5bom2oKkfunqdryTf2o8J2uybFDy89BXGpO5Ak8Ig7L1o1oQq
+UtKBUKOx2gsBxNumXw3+jwYY92LEGUkOLU0sAW8WSRIW4l0ECiMZgbDmpDWuZdsmc5Ugn0At4ntQ
+23E+ARTJ6U4g3nXcEmuEbJN+oGdMmRYc2CleeOI+Eycl4ooDQ1wxj5jAoayFJLUzgOpsC6tI8AYf
+e2W7mKynVg8eem/vcb3xsjo/kYTJTN8A67ZG3PJpyKwjGRmxyKPEBA5dQShCrPFsejUwyzH3c6OZ
+83g6KImaRymoanM2LwyKDYwkLejoUAkXo0ajOaBnLxW4oOeAjizSAN3/Ob09afssxG1SlsuaGkx0
+ChHtw0gqcMMrkl0uJG0kvNeBpA0GS1BGJ4IX8Tq3rGiJ8IaTkiODfABb1IiO4fzNiY4gRdkZx9W8
+CvCAhD5wuTQ9qUtKJ9Iw0fLYsaagjLky6HUjZqpjQZpImdjZkGq12MFoMiPKRSZ88c2br75+9ipP
+RerYKoLYZilj3hpoqgHgMM98XbwzOy7phpZvz2Er4+uhxmiIUE5jUEOG1UOLGjYdBfHvWb3+0oYX
+VjTyNdVuJ5Nb2ffffw94b4CxjjLUqmi7UvJRpwiMUfNFlynp/v1QdhYpCHMKhL4xskK8ENyW4cQM
+TslTx78+iiIRSgtJppqpZDfRx6OkVmK6CPJiJuV1u6VC6yjRFkmxPDU1e7aaPMzYsPbQKr5LyG6x
+BO7tagFTtISKwg9fA3FET/+szPFd1vd78A8FdvkzMF4Op4r/Ht8/Oom3LaxACV8Ol3mLHO+apz4C
+rAJbSHbQlrA99HkuvPAIalEf5WmShJLHn8R0dLPt3Y5BSWtKQFukPV2TMvLh/S2SZNwxHPkWr6uY
+OWGFBEZRU4prThBqfvItX0LyscP0S8qA/Zf94RCPsMNhinXaHnDZAF6qq1KQO4rWjw4qHq3UCRw+
+usOESCFwlij8oxUW3RUKlFPEFjNaZqzuSvAmaZ5Ll63H2rjB/TaS4KMZf7DTxko6KcOawC0yrIG1
+a8tt36q8syJ3l0+KBrRXmm1luVjQhZ8g+Xv7Ngcjl3b23XS0/OTPggDCrai8oV1s5QSi9qtxRY7G
+i0MEXkmKm8wVHBuLz2KaZlsuKzsnE1K2Q1TaOpvmwmTrsEK4mFcUjgQpq2RZ7jwuW/5CazhJPkn2
+gfxA3XfwlPI1kLE+7kn2nDhnEBx/pospHb0kTR3eVVUrYBpey7nJi3zEl1kjuqvLKPkXWvjwhZq5
+ZOZI9+sLiW7uW2CZA8t8NAZcVqtrjliP1oTrmrMvTNccwP7uqMmq0Wp2jZeoyxqONqfAW+OkQDcZ
+BYZf/2sNAtvCMdClbTCEcMZi5Y0+lJeRhZ66ACdI07FRcGzTL9kL45zCEqN8qFTVsGIATkqVA4I8
+nHsZSA8LeVw1CGcn1NdNbn7blV+cvSGPwwP80CX5zKjB+kOTD4pf/1jerCm7PpJNSf/9prwgzowP
+Hi9F10eU7JqjhO4HqsXpm+JrLTHjRv+zBKviXcWIANSd1OnS3wzaRSgBKdKiYKzPVmNJP3/XB89S
+ll030ByvSHIzbdTMvKw5loIoFsJjW0t9ZalykoYZI4P4ZFgOvhtghqenO6qXATFotuvbxzU/7kqi
+7o06g7myoHD2i4GQWCpwJCmKaOr2HKCo6WWNez0NmVWUplVuadPJWklw2pr00ZobBt/9FMckZfGr
++AYF92V3zKVdOsaKyWKZ43djCYnPaoiT2jEiw4OJx6jRzP3FoTiXKyKJfDA+NVqKCEPvm5vCYi56
+NVPhW4wxj0FbCqna00zPsDmVS1r3eOd+rwza2rh1oAQXS5KBwAr3XK3/dq3z00BD8DsKm+t+oolN
+HhA075Tbu/ulG5OemT4Ftbyrln5wA6HjU9fr6dn1sDKCo4zBWnEzFSSU55Lul3LqMDWjwypRdOjI
+dE02qjlmFsy3CY2mIKe5ybXkjV64ylQbtgbyy0XRBhUWZFbdi7LQcmDjgd1IlhI/wX3r9jgyTtmL
+uzKgf90HrZi0qSD07JB1Nqx2Sm1bSK8H8je+nnJp00aL62JVhQkIdBJbMr0WQMbS44+L1Dkn9qj5
++tnrpy+fPf6GEu0+Mu40nPd2S+2z2aa50KvSLnSXJEbfHjatl1jNtlssl1RDGx9KAB1zEmcjCHT3
+JXsXexuxS+OubjA8gwZKrnITSyBrxO7v0JT6KAr/aa7uFlny1jupf0QWqWQeI97FHvkJKRXrAlWb
+E023JRoydtZsmVilTOezj6FixVag6jK0DWhbPvtZe29kRmwuucS8JDWtsz7ZWE4K7HO5zaaFSMBk
+oZlFlw4zpbVSYrd/r4j95iXw9jLQsAqYaA8cBHumhWAW0TE/nJSxHM+NDPhPj0+UbPHIbiV6K+04
+bZN0nX+oi0PZ8t37pIcAhZ0ObpdUZENRpQwLTxo1yhZfEPYy8iZVO7f2UqjcMr4oZR9zt4lmN7Dj
+uBXrPHAly4WX6rjCS6el767IibHDshNrc71kgn04hfNxeQEHZ5tnR+xizVm8uWvyvmQm8UvCfMvK
+TakpT5p1OSGN6Fp+BguBoUEZfkj5TKfMt1Tj6Argfu3OBYTUvmnIX2ciRrowmgPODsneO5SiVnWg
+7GX2lRlGRGD5QzsPsK8ZPA0OVo9QZcWt9vSg1XZmFkvQ1cuL6azykOmzHX5pNi0zi8t6GdwYWSQb
+DS2/kCmJ0s/g+ZC+FJjPLg6IxRm69ri+EPQZ1rqqmuTeEc5oW5pck/wreanfWl8rW6VD3nW74EJT
+uZoCizqlyaFQfxKKa7owt9MWnXvssAzVC57m6MK+Tu1CabnAXVMxI6Xw/LTe2Uw1T6M03Y2QsGVl
+Ehe3Y0XmYZNWx2nQ8XN/aEp39thGrWhjNMs2o53hU9wmSfl+ASFW1SWaJfippBj8SfZxjBEQtqk8
+N9nYlZSGKq4wl0FmdRT9+aUq5qEDHaKkCFSxCDk24I/UR8DyuN4s1if7oOuKE1OKxYrNeYyue9AT
+1GVxl467ttEu5XMPvDF5B7HWl63Wu8YoE+2L5wlTnsjSRinYVF3cCYIFYr8im7c/IjteXSr8uJzj
+pMzTFr7LuTZIJQsVBJb7ZmPWOwZdPUxbKWWttWkypQwytAYzsJDSyOOyR23DM7zSvnDdBKCUAJ7D
+p8Z6T6Fh5kiNgtCqBA3vrKLO2Ua87dbeh1KDsKjUZ3uIjWBcjMXMF3dIa37IXdeyhHpuV6Tpyhfj
+uJzBlWchZ8UxjlNQ5CZz86K6pDkSG9ToeEzQdtnEWjd5TOGLEA+EqjK6u0IhILb0IIRrAildPGKH
+q62rcoXrNoHIlEkelQW02Ocgc7kzhtlX3EouOb89fr13ksb8oRt4ZqQnm+PJS/bo+2Dcjg4+TgIN
+egQco++pEIKsUZ6B2wS1M0pxGElvS/quj2PNT9Eddw6LdAw3658pkRTkQzLh23bViVACDE38xTPr
+ziBzpiZzXOsJnWvq7BAS2FZNCsmmY3W4jOXSFllUrAjQybG5yHs6bVh+ePgoR5dENcozVJXPUu5c
+8dAP9dCVmNpByydcr7xnkQAVeZ8eWadULGnYv+9aQ64zdKwuHRTMwMUKVrKWMu4Hsf5LfOpixZc5
+FMDpEh7fo6VVx6petLUKzRmIGcvR+qJPysoygnKMp2CiFAUkNHshQAUpzkQW2Co4cPnY4SxmvsSl
+M4k9weL5hpJFYiNHJhoFwVMnN+m6OeRfzKorUWg6kp+e2cmxnRh6Gm2AYKcPz173VPgSzDG2OW2q
+dxvsDK5C9IFld1W61B6vKrq/zs6AYi5sQE6n1QibaqOMjpGlqDuexh3fdnwt6NFNlIQBuMD4z9NU
+eBcX7JjNl8hFQt1qHCh8+Gz2NxAehtROvubbaRx1HtKF6mqKzuETDJN3hj6Qy2qFKS2RMkY4yENx
+kOM4k6vNQtLaH0ET7H1KVINx/cb1fI7nDVJ9G5pqdHmDMFvF2IaSNxxN9ilU3azrQ2d9kE02K20D
+q91ctXO4y1PvXd0kVr9FiombMV1bPUfqTkmmhjCbuLxRqGQwRiZxjvpFaN9Daif8QnTElkDZBstn
+9O498A26xYPhdN599uZ/Qz9vOvsMrS81iE3vfvP6T/fYi/7LKWV2V1GJMMbYRkxJjHIILeD4/k0F
+KJWwTJkcjLLHr173O68vgAVyAJxMcnFkru16NgH0QBMAYIO8n+M2KJ978zhq1p3Q2d4OxvmFm/gD
+cT7VXkscT4oIgewYSq6xmmdQ9q+j9yMJrItljIc8OSI+zIoHveyXvexBaaIxvKqq7GK9Xh7dvXu6
+OW/6/8rBKOrV+V2yxb7/6W9+zXsPhmgip/r887qePV/CXph/Pl3wA6UC4sdvRvPTyQifvj57ekWv
+voCDZmTlkX8DdI45IrGEjSwpNf6ASavxQZJI0iOgO4byEqRE/PpsM8c/r9b0yx6I6R3wVnK9p3Kw
+maf7gl9f46Yjh74hRirkEX8pyoUvqjPqCVK5PL+kRUCjrGYVN8hxPONWHm/Ozacsf4HHC3z4sqYu
+f4dqPEYb/YTZJPi4i8WgXq+ueWlRr1fXX7IkIq0DuRAkoi339CXQYAzqKYhJNAeUPRWfMNQfdRGG
+SdOMKdN4Nvj2wmAIaWJIoSBJXF0X5tA3MvYLpT16UjxnIiKF3htVpvlw7srDaQPrkpbMigL2xacE
+Cg9lPZZtD4YuObQGhPD3B+S6r8Kb7NkvJb0seA/imMCr8iadSkLhgJuGE5sAqAk2TMwEELwBTsEq
+ZBurCzdB5IXE2VoOlYpRDfI8PB+MRxixLQy/tCOSqQti+sEBCSWsqY5ByK2+B2QBe4HvX1TA6Gz4
+KRBQ2oIESpU+/XW3RW3RpiSQ1A1jBcrf/0+F8VvUEsmPQjOZUGT12RmcaaBvQxX17mZxyfywY2GU
+Mk9occSVbLeMItCZiUrFoUts3qZ8nE1DfEcNvfBSMUQi94R7R6yjD0WkiqLXQe41fGWNpvO2KHcu
+yN32EHdoy7FPiDt/lPdObhjtLm+JdpffKNpdhxMS1isQZZd4S2MT630+XT9fZUDaf8l7+uX3Nb39
+F//tY2CV8PYf1NtvXl1MzzAdZ/7woXr90r5+9Ei9xiSH8O5O7qcvhFeHuZeYkKrezv2cg/Dqrnr1
+5ayuV+a9/oBpBuHdgXr19B2+GQzUq2f1mt/+Qr/9hsfivXlKr3Spr3ho3hsq9UiXelFf0jD0OL5u
+8NW08V5h7lN6i8Srvyzo9cLvNb/ly52882Ons0HhM5paAYrlDrzmTALV/N+892/MTPhvzZTBW2zL
+xBAPNxFucVL9M28abpu1hXBHzVjcgePe+awazZEfnm1msL0CtHNmy8xKcIFn27bfKHUc6ceED9Jf
+fX0JwvV0POSNTJTivkRxC/XxMwwlypvJZZVN6kUXLRXfo94B1c5T9Iv1DPX7mu9sE3v83dlFki78
+BG02+LyxLpwvp8a9YnfqA6N4dqjgaNPj+qYBS/zg8a1ZjP22yLwvdSNhj8nqZBfoxUkNtk3iS0b5
+P8ZCJ/ugD0R3VIbm+2aL9MP2/5ToU97nPd8HPba6Yjj+DlDk4xHT5WICIqsEEUHpV/vH27FL7AGR
+HwET1SBHoshjadpWkcL5Q3VI93KdPGLfMm2UTUtriITtxONVSwQlXoYUKT207WYw37b7Guo4/GiF
+f1pPUtpnWel8FPCBUzKJZNSABIE6YxDNQcL8QahDkBxCJuwAqX/7cVqgnPP6sClrYZ3+zunoCS9I
+ZqALx+mkV3a2ULUW7pPETG3sYAfbafkWcz/g1kAJGxwY6p2B+pLt+BeuRhDDj0lLEzPIkBVs4RbB
+TIpqxNpwz5daYuRUu/iWkut6H3wtE73x55vn2U/Kyx7YQDUgUg3rpfHBphbqZcM96I+pUyhrhcbB
+VM9rmN6kGpYmfM5RL4fN9fy0Rlxree64XrqT+ckWXo3BJel/Yr0V4sE2sH9m1HBMZTpfXR5le26i
+DLjUKdeFnVw9pP8P2Rd7yWy+w4/P5qtm9uM2j5tlYJdFt80+7BRVWS0mU9ucfVs8XFvSIcWt7Fp2
+W1eHy729wulXJ126JOc15/Eeepe6FqUPis50N7w297s09VeYtrrbn4+xOlnYGEa/qTUjA6GI1DZK
+2cVl+siMUBp6vtonky+zL2AbdFsg7UjEo6M2rhHug8yeBEy5M7dmK/UyOgnwgEe4i4aM6TNhA8eQ
+oz5F/qHfbQf1wthAJxJwwpe8zD9gzkTfL5NGB7BSW+lRVnFo3R7Njumpn+bVgtCQHfPL1AwYYME8
++CM3vSC+GjewVbpQdfMgZ1XeK7cbH+zFbSn7lT/EfcWSPTjkDRYf3uCYtTdd1KEMsaeoQFX7vsBA
+W4Ffn1+1A6DvSk2c3O+5aJqSQto3W37ZsuffbMOPRpTIPLr3Xh9t9B8i5P7Mm3u0sesJ/JvQ6xNn
+ooR2EoElrz+5YturqAyr9J0Rrlh3DNt3Dfr9g55TrJ1nRwT8Rw1lI0kvw00H7/9hw6Gm46jVQfNk
+1pBcIBRCJ6xpfGB1YnXnnAAMPpAjF2TGPbSJ1W1bIWQxYTC50KVOua3rXunkLCM2bM52wYj8/lCs
+SPV+wp3758OPNDpUp9pmcCCATY9S8+VjNQDDlkdDEz15H0ynIXibnHc1QBhH7fpH0KEHYy+MY+H8
+pyDD/Lbg+KZ48iruQA8bH34MclLOMC2owdzvPxFqPhw3eyAHB8TfpguymEZjAJYnQ7itF0YqW3zM
+qv0GIts7rzke+Y6tF5uw7bFF38+30d6+vWh+wt3Qic95kJlZi+rLPdTPrQIxlMYddpm4hdt3Px66
+bPVEcGmloh7LSjxynLqPTi7uvVEL5vHcqr5bzZk8fOzEOs3sB2kJBQCr/wJpxZohKQ/07basUKA/
+Xl/xyfabehQ6iunu+lpZgh0gLhB2+V1SusB2g000Wr8SgKZIwSYAqS4E65LU3obhmDp/JSGYzlwe
+En7CRRthyy3cPq9dQl16wd5A1xZe0nwUmP0m8lb2BDNjGR0/BRycNhwilmxlmXjb1f3GsCuYC3K0
+Qyc0crT74cfUuleizU9ELdjtoenzz0k0YUOelxEZs6jvIUUv97xc3Gev+Ll3AuF1dFtmGF3TrNae
+jUYTnLzpTZIVYVWyCy79wEQ+BM9KhJgvjJ7+ZgOxf/1jHHwoBAISkICIY5OEhcnGxH91fP+XR4cP
+WtUPYqwi7C7CQWS2o3Cyh3swM6W0jfBPrnNP0YHqboIYTCb7nuS89+NybwK2w69a6AFq79ic+v0+
+0b2zXGrBtAnAi+YaKLTE2j278xZb+CkaPS3qge5bn9+11xnXs2F9dtZUa7+ee6+6WV0OuZB0VhAq
+FYH0gac2xp/P782ufrT3J9WThNWB7dvJVk6ctDtIJ7/y7Q1i/qup42dWO+mmOu+O3vxnE0oE+fRk
+NKsX1bqao+l99e4fX//f/+Hv/u7WL7K7m2Z193S6uFst3kvgjE7HxE0fkCHPb189f/PyydNXv21x
+FzgdNdWvPjW//jybntrEffOlNTuCzZJNufdIpSTth0ZCrlvy5NYuOqX6kY4xQpZ4GY7WF4l4SaaA
+jfsmQFul1mTlO1m3b3rfvTkoL+uzDf4ESzg9GM/uSbKRq9JHwANs2Y7ezTOKqmhcNlxwxS3UbVaF
+jOXYwA2C7TbD5dvzyIhgazSHVtA+Nlsacrk67Oq1EpSedknIG2TgFSNniTaD+Zska1LhaqrYkxbx
+IRwbpJvll7vCwM1bNWVxRZyxakVVQ7riUUbWU1wPCZnjVrq5cKHtkOFUY2JCtgaLqFtjBQWgxHZY
+FHNt6T7CGbSJnjzBQIKopOJitwLwSaBMup0GaWVzk1Y2t9bWkf/Qo0FWfNLL7nlGQ4CtXCILWtTB
+Qb48yryfKF9FwVmn47ezKhD6FWfqU8axCnMBj6fTHHOwVosGjexPkScnKjJEyofQFMhE+5MK6Rrt
+DQtmsfRmUhGEwvDIMpVM3qSQfUFAKXqw3+Fdg8d1xWoNb/Qf0l12WtX9Val4yeXT2xtMuY6N7gpH
+MCJ9o/czNQUQZdTAVfjbp89ev/zDbyXCkwyLvvasfqbs/L/MvVuTG0mWJtaSTCYZpF1ptas1Pegh
+GjQuIopIkMnqvQy2s7rZvMxQUzcVk9OzyspFIoFAZjSRCBABMBNd2/OsX6Bn/Su96TfoJ8jPzf34
+JQJg9cxIbW1FZITfwv348ePn8p2Pv37/32AGViKxj2fn/8+/lKS2FNMHAvh6bz5pbE7idTW3OY/h
+xbz8VC7rNcbe7rbV0pDjFsLumLvsGjM7ppLZxBBsh7CC0z/uT2CeoIlmd81Fmx40h4ejIZcsO78t
+MTrS1DyBbQvpls13cZZj9GJdVKYW0P3JV+SKf0fJZRrwfN1wMEQ2m64wJNOI5eapy/LbU62iJd7S
+MsxtL5GbF/EmoRHDV/08vSp/LSSNPx39anT6fNCTUEEbGkgz0es9ghTDiIZtJhmDKEdf2Nt3g1mV
+kaAgpbqWMDSjGkhVxHnhpkcvltW0YfmuLyX6iNU8msgfA6pnCEaq8Uznzqcf7udnPw24wGAsPfwJ
+r5dmQGazNGc/cfDhdEYRtnUGcFgkYG0gjtYtLxQcNNu5acpwNPNjDH8Mkw2s66Z6gOjSVT1oMOkz
+0QU1QqPHZvDnmB4Mif4HRsybV5tBhgUmsF2A5Y3pKfU34OWCRtb7sVq+wdAMBryn72H86I+zra6r
+ZbXdS0IjkiJPno+eAV4hhHIbEdLR1RBcriE8ZgpL4X0+Jp7+UJZryIlsePfCUCkuuPTDHGmAWb4z
+HBz+HLrHINovjbTY+ppCff3X3DshtAM2HGh/tvX6ZAnb11uvjdkP1ByHTUNLP1mOB3qeegayHf8P
+Z5mLjuWlu7IMzHhQ8EiVH/HLsRRS9T5Uy+VAnZFePXgJv8dYStV6U28+lHMI8hzEtRb4EuwJY1WO
+av9JqIfp3f9o3h4DaZEKjeWxGsCLdUW7b+CVdI+D7kwTDBns9/h2Vb3k5+5DbOGxe636/h5i5VC+
+HKTqqNfBIIDjHbXMplxqjZtPq/vZIFwrYKP4Zvzu0+r3L19SbP330Jdfd7dRK+3VNW+gcktVPMSS
+3ZKz7tfw37CSae7FDj63faz43p+iRwKiyHhhhlc8hcP85IbCnUF58eL7tzSd8OLAdErHUDS5a0iC
+T5ZnGXHMZbx67/CVrhbX4zKq1ksccJauhUPEEnqfwTV/0FWDSqgq9nL/1nDjQaqKX0JVxYy9wJQH
+bb25EqoaxPw1pEMZtE2GLuNXZaS2QUuPqoSqh8nkxZjWDBL1ghKq7m4V1Q7qRiVU7YmvNxx4Pdv4
+h3FQSjcAkCYcHDEx59Mg3UBYqqWFQThpyRaC2tYBtqO2V0xXjyM3B+kGEgXDzQ6UhLCrKPNBRhTy
+KKoXgjDBogj/dQzz5KKp3V6udnfARbzvlvLupaohMPiDVA/2pWazcEWYB/tHKvBLVXy62sdMRIrD
+S13WP6iDsv753FjKSA3DJwgjPP/RXBJ9WpKy7qWq8Ttzz7JMZBDU8F+qWgqxotqGtfyXmt6MLF4+
+tEwov9SMAZRTk5bi/NLfDKj1TK6vfakrmGsdXRQGiQrupaY6UNIOWtaCXuoO4BJLd9dB3IF66Q2q
+hrDdln3AL3X5qsHLfPqr5aVfoaMDfqnLG65d3YGiJTVL7mVQRSA2B6kq9mVQSR8eUaXw3PBOjLBC
+it3D+iyUhBAtHr7UEoXZiXCdTFawL/WQWlciWga9Bl5JNf+OuVar9W57Uu+25p/stlzafLCDqj4s
+NolYW6cYKWe7T5YfzabrLeA8SCEtYJhxvv0uJQKpelxI8xuYiLBeWE0Kaenp1Ut6Oeio5wpp+W47
+j6uGNVWhZNU3rwaHq5pC3gRRMpnfQ1qHzcCvLJlmMOfDZhyU9U6Vppogs0uMPmhFlfXlMpcv576a
+oyDf0kKirD6JpnD7Xm8GqbWTl2NbKiTi5g70FCAd3JXTVfZwt3x6u71bZu4+QCRtXhxB09ivKWpq
+p8gaWg6I06uC7/VqTW/C4l55eK+Fiel9Z3F4r4p/K5qOQbq4e6/5VWNILLUxuRK/Dy6myzq4Fz/K
+zCOMr4e00jnoKOa7mZF2BrgWkGwM4jvh7xnAi82MXJN9qqbi6auc+9oXwnSRWgW4y0M240Gi/IjT
+HI9tIX0v50EmK0JntoAvKcnHDJKVdAFPLikRwy1aHVWP3gfnVWelm0QlvFmnyMZ+Vnj1Pn/13fvz
+QXsFLuBXef3DD91VoICusm+QbNqrUAFHan8qeh+/ev/fT2yGL1aF/+b9//QoVO0+H305+nLQ+/jb
+9//M4dlJhRfvAWipRVWQ+aoCNCV//N37fwHNhHqtjy/P//f//Be/cJhz/KsGeMx9E+HGodnnvlp9
++RzjyGzSoQYcs1Z4Ec8GA8xTMTAMNYHjLhYStIsezJVBhhIYbb6uQsdGAA719Xt5fzttPkDx7Omb
+7On3b19lj+cQ7r+G2PCUwaazg+9/+O7l63fvJuevf/jm7bcvzl9nGpAVcTEJU+CMv2dkpmaOIQqb
+Vbn88vnou3W5+p7GmLd6V0TdMNT1MFtXQchgSzd8Em5L6YvGNcxOTo+q/3JZN+VfYR2uWgQIZck5
+qomQcHaz03/NCEhBQSBUXBFBx7zeZ9VcpQRxLfc+vnr/z2V33NUrw0tRD/Hx9fl/+c/RVpSpp2IZ
+uqtnH+C3wPlPQYc+InjLgJ6HsldopAxayQm2JhPVeL4BaFWLKW/aAjsRGUMNp7+6UmWvrjJuAr7x
+U4V4LbclW+VB8Cw3FqMZQFrrebXYC5InJYhE+1BlKkLMKVgxP1WbejUe95QV23Y4astOOEQXFjMZ
+Cro1rDsvl2Hdw5VMh4D1nrPhqyUlYtAN1vjcbsyX594XASZpuZqfBejvQV9RtSM62zdo2OcOIIDz
+Nl1ydjuvNvweC7ww5IyrWM04BAwxd6/LbLea1wDpigCxWyQZpCO5eqCh0yarBbMOAUeXZkcAhV1d
+8cCvrigHwxTUm9DYvCQZE2z7i2xqXTyAYvxkDlhRBoQX+Lk44poJfgqzhb1TiKSMY1Vn5CPmg8Pe
+4RRgZk+3OQQXDT8NEvkiqnX1R8iDTFMG8+Chp9HzXm9Vb80gIEATyR/SOJGjkmrfMQ4qhKYs3O4Z
+gNNu5qAf4z3wFKgMnKie8npmM8PBbsqupENRlgRuK5UCgik/9Wp2D35uvguRn0fgwP50w4BvhWmZ
+ykIaQoB6hrWY5bm6Mg2Zn4Z3XF1hQ1dXQ+Cj7ELTC+BvHDUAQK5zwaaWBa+vfKjM4tlZQoa+nH9C
+ZJJEWlpaON/PhD6G7NVUldBZTMEkLo9Hpjm4ejPludFRQgPbr3gtsPH2U12x7d58OyG01psmW1Yf
+SkTprWbEZ59iGfrtufnYLCxYAPoJznw7BZTXlRx5rJdMPA0eAak8cXrqqM1CV2rLLusOXGbTESF1
+UBDu7DJFROgfwGSkKScAqPAXCMBr0qRjWOanqt41y32KioI88G4tozwh/C1t7sUBvfh+Ti0J2Q8s
+RTthB8Fv0TFZeJsczzZaG0Mi/iLG21p5gJDXjF0Ys6XJpdebQY/16C9RfUES6ogs1UeY9xcSE4hd
+eLSVHv9h2vIpCr5ryItlzyPYZuaT6xJwj5g+QvIAhzOO4Ipylx+mC+nqeIr4M+aRicHNp0cHIHfo
+nDGB0BJ4vwo9sHiHzkyfjNwHKlGPJiybH+F8XF1xgywVkF8mJOG7NfLBbAvg9ptyOsftOtttNtBw
+shOiBBsrCR5X1DJWtd1m0znEThrBAUId+J0dg+vWW1iBKXVwpF6aVO4H02yx+6+SdL35lpbo3ye2
+7hNV48L3iSWnRt6YrlQHew2X7nOJX81vvAe27ohtRtHWtsJxNE4ZBP+rmU4grkqSayOU+oOVyTIL
+Zl4KPeEtnv6WjAJ8N1oyfn7TycUl73Qz/VTyUMJ0qbzbXAH2+YWfF2O1VPxMbUggGfwU9cEkdbd+
+Jol5HsXf1xu8CZp65pCvDZ9lDyTx4ptjQzrS9Na67ekkH35OEpZCde96lpwwmPS51bJijf625reP
+vytzDF0Osz5+eBhahMOhKenieKaH6LYCkwnyeCj7wizCc3ucO9E5w5QGmOKTdX94pbVVsZoRuGYf
+TFkA2EAkUkyVAtkjDDepzA5n4a5cLECI362WpcoyvK93cPk3cv+mjK719vqEHWGMvJ51RGYKZCeX
+Rp4lgOhU4WKEH5iSUrtFMy9AKpnvNyEzJGUTsxli0A8nI7R/FjCNzs9KflIyFEwda9ztRRxkcDCi
+wFEnZJ1FNPHpEk6iPfPMOQSVgKMi4SKaFTVyewWpSlDNe8ykBgO04kzykI+mVm2vY1iYY1c2OEkV
+j4SCuEQrZ0inNLX71ZYtWrkH3jQ/vnn/z0RFdlOu6A708S/PX/zXpCBj5S8yNLOVluXJQnK9nkAm
+aYJjYFUz5pVh72vYX04P3LPBPdt6jc6buRLhEVOUeTwlZZFkxui5Z78ArPUEPee4ac4VNZz4tSkE
+ZZ968TMVpGO/NvNTzj4YiW1zdlq0JEC/DmLPoC0Cf4AY9PUeQkSiKAkAQ6W2YYbaGr/jCyQd8F/X
+9YfdWgufpEj8gIlOc5krc47X9ZbYuTq61hB+SrG0tyP8Iy8uAFZGSsvDwockH4wG9DUX0sGlEYUu
+Hkbr3aaEb0V5ChblAZcDGrl0QzNLOGHFnV5EaQsT70ULbbNnP282M5emFrQJXC6YPLP9yQXZC5yE
+2nbU3nhhg9kXwDJyP73V2hwu0xs/H+V6v6CsE64mRXwOvjCrHG5mCluStSGe6laI2grAfGTEptIl
+Ei6U0aNTUKxQkOZY4i/sLPO/Emg33U5dNjAO4Jjv7taN06c+LxJFMbzDBnfAu2H2F6mCHPdBsS8c
+9wElvLLwD4eG5AMMjxl43wTve8EH8SI0OHsSF8iDdkShU65gQZWakMqOdmvTfJmnqNEbROtUSnYF
+4m4T4nsSZSLD9Cc8/gpbjjbA3XoZcScJJCtGhuPA87ygvTeIozmR5tiGBXwOGvRIGZ+a/444K1Q+
+sDGdg2HmVihVkIJqTDH8xiB9VtnzLBjT+bxGd7Mc05gIYMjNpt4h9Cc+BNETn0D80fXuhry1OcgI
+X4xcO/2TE3u6QIDzjLK2NEaqhoxDrD6ivGnKmNZsz/q6HgRFmLvnWR9mUuURAqPIWZ9z1LmJtYcR
+NZBNt9lN9alcsWaaGKdkAGlPOSafLwNxucpMIyg85GqUNpOEfaTUw1I/JDyPbQzsufnv+Zx4t28M
+kYArX86fJPESIxxnUQz8aGuIsgHb6URCKWxQxaUrqHSh+tt8ArZvirjwCD1W8vA9k9Wz3se/ev9P
+wExsffk/vj3/639BgsW1+bLVyRy0DA1i+jNZ4e43FU6a7d48hN3TjHr5yyL7oV6t9tn3i+nKdH97
+V83NPdkPdDo5yb55e24O8Bm4WM4TIU79Z6Pnhml9et7vmTeYlhXkOxW2MPTiES57vZffffON2Twv
+/+rFD++ghUf/vi82BlcwSm+UiIam85tj47O75kadL7b66GAlX1Dle7EnTeILqmJe0Q//pWkHTDDN
+jc7uYBh9e7Lbx83Y5lTJbc9D3deT06Ft3Zph3pEnwe83EPR3OGKcyCTS71JGJ8krSD/aUwK7AGwz
+rnrRFvzqYIx4N6vinHE1UNSCXo8aM7fLgGvBqCCtx5mfBjTRjbQieWuhKanM/7q2+V8vnfAN3U3s
+pJkWuntsaBGaC9vt5YWpdOnl9tiWm5Q9a6bzTATthZ9yoeAY1Pz74zt68qFalD4c76/o9p3zKLDg
+GVUPutlDDr+AJijHePCZXuvmVVszROCit2USt7zjIHXTloFzOtTk6r1slVdGakV6WFWlTrVqjhaU
+SJLqoQVh1a7cHj0CtXxbfyhXNpSbE6FWmJks0Fwn0w3ji9EMnD46lUnJblCMVJmkJH1wcB23Acs/
+/SnU0c4ENdW88lZUuKYllEAPQuOJFCBC88n5dUPCkzmXPgaG10rF2xJwAYAA4HI8SN3ABTHBG9pl
+zK21gaN1PHrMK39W0uqV5AfMd2YRZihAcWOPN4PHbpcVRXoiFHPBH5f+IrVrYux3rVoa+lmDxyZx
+5LTaRw+7zbrFXdEOTp/eJKQpaUAdkN7R7Rrl/IC2UeS/PjYD4RB5bgLCjL20NZrUMQGwmVAbfJOn
+Gpe76VCuNmpDQvmc8tBRo0WQkWRV3gcas4BIRTNFcfbMqdLqKvelAgqQt2xavNykhsLlAno7NJzW
+jYS6XFPzM2jP3N62e7s46LWYojlZO08ndewkuGxF0STMKCPqtHsWPmNBjshhkZyH3ap8WLPnMiEY
+qJElpsQcnltK2QCfDhnJ02UmDDEFP5le4ffFyfPxZWrwtk77Qv/sb2jtDwbWohWnIQ8AEu9xM0Do
+Z6mhL+3t5IBfOz45BS0dqW2KFKCKj43qNrNjMnZLa/ih6+V09YFyMPoINpBUvFxtLUMo4nSOiCzV
+ceJzGbyobkCRtE5nihwfmaHrUbTdK5IyIXskOAlfDMKm0Jgkg/BlGcM3Z8As9Q0vXkP9DSin5LMC
+0khG36OHA4sFvs2X/RTDYzWzKXcKyxp8ZDQF8hGjsMdHASOmHc9zCmOsGgxoyIsjwPy0cOR97uDM
+XIpPixTp98dZX7R0aeqno/FvoFU6GpPZeNz7zzA3tQ4YRpUc8RG9HcMZkGJBxjB7GTdGa3YtXjAe
+ZWL9ksw7kYdOk4NHCum7rnd4hncNqxnwRFG8y+VeRR+bnKu1Hh2KrE2xJ9lp6t4cnupH3KDb8JK5
+dN4lzRXHAZmJxprdHzuu2oESIfA96hC9Oz2NuP9AV6J6PHxRT96P1Wjolmy1NS1X5eNGwHa/xs4K
+ZBqIFBCcdcIbBafVbjtaZrKPl0zeF+NTz3IVsevex//l/X9nA1qIlD/+9Xn2F7/4BTrVTCaLHUQF
+QsZ0UqreSGB0k4BAZH/OIV0Nqz+WyoTZCb83W+8FddLh2PV6lnYtkFJDfh80OBCA+M33+5dvJt99
++/V/mECS1mmTwb+TN1+/+MteW0CLLWF6fEZPSKIiF2JRwBEAnKeaAP2rEQLv7nZb9OJit+jbejkn
+t2jGPMbwn8VmeoNOSc7PpW6a6noJNvlqNS85nXfg6C3TMat3K4IHe9amFvkCLYwAYs+JC8axKrNh
+0gjSm8xhuqkWMrCBDMkcWb6rPh3XQWl6GJVF2+AU6YGsn5GOAL1WzZv4AIGniYFaqcoCrUPBIS9P
+0d0O/B75Epo97qMW8625C+Mx0WyLAw1fPIgYg+jDvs338ojOzNbjmOmRiqU/5nNYtvgxdTMAl00c
+Vvp8vr+tyFywTWQZD9qxpUAkk1Nz3IlMG6fOS35I4saS1nPoT4d4RNqQNH9CrmfzskisMKj6DrQo
+LeT2YZHIul4+bCkmxZZRm7H8aLciwsQdcfjqfXlGtYLhM9fyfa7HHfsBG0HXvaJVZm7Y7aawvR6R
+COGQwtwfBqrjq9W2OPDdpEBvX3nTqilhKK5ci3iQk5hzWrQ5Ir81K/ngkgxDtQaMWYYjE58g91nw
+LSzX/aJ1gPjFWNN8Mo0CqY1+QlpTNTnLctVq9lmKIjkmGtUDi3bUhyEz1c6qvLdA+nwSFfFLy+HV
+9GJzY9PaZTgoW005s+K+TvgjuipypvFZR37IZtqXEkqlnZiXJcE8qruxaequ/lTOR0m/TffxcNAN
+7cS5jyWmheWyX2fWcxmWOPjoFjZFVZ/okFFqE9r6il8n2jSvW1kfVD3RLbYvll4p5c52aLHClVob
+kWNjRAJxOL4uzZlTng3MGYxemviLeeIgG2RfZL9KL+nUSCfrPXicoUdutLi+RZ264WB77GiQ3aOU
+a9YBx2MFmHBpqaqbEvpbJQhakHjDr/HP4rgNYI/hLKdPNtcmFIetTtdK0Fj0smPr0LD4zyeZ/EvD
+C3hz+0bis4TW5u99GcD/lwZGTZvJv95jRXLLoKcnJESkV+MzGcoFT+yT46a1fWIESODOTY+oBixE
+F8eUJueJ+bdtA/bu7DaTq5TnDY0+Fjgh2MXu7toQWE6C9JyuDs+KI/gQp+hxA9+AO3YejbtI2Y71
+nk7OAjX2M6YiVydFhsIqT0azntJMZHfmfnA3XYb8j6duU96AKt2bQeDWjpBoPKM2F3vgkPmz7Ndi
+bjMM2TLsInVv1wczV6l3GPSAs6COYnMDG/qrEM0Z3NKUhl8fElbMkfo6wsTbm5w2IREQZDdmfOhJ
+G7TvqImR97lvF/zY2gzMpK6ymx1E2k9lh1KULxcEevS1i7fgtmMEeDPPqxN3hI6y7N3uuoEo39WW
++QCtITpzT4Oc9vflJtWdBCIbtlOR5/G1eX9nJj4cxB7xiA1J7u5MwW0NtfBWZ5btbmfuLCQaJ4nk
+Ufa3f/u32d10f02YuIQ7SzqBDbS13kC4s7kDM2SDbVA1QVS7QWTncjsbrde/+Vl8jI5bjwDohZBB
+cQxnb9AiAPd9CdSTu0ciQonbgTdoXqahGpqwjQyz23K3MXfMCsIp9oEru9YLqPjQ9GRHlwwLaA0O
+YeGNIgnsQc72hlQeJuhGjCfycnp3PZ9mD2ObWOBhaE7/Zj6Iswokgv3C5tjtsdmZu4Tnly+fG9S3
+CaT40jKyK1h09hvW60hd8sjPOfUErtPDrP/Qj9OexJ+kK6UUpV3J6P04389IT3dQx+3SQhzhlfbj
+ipMyJi8pdnIo94b5adXhmFvBiJ0BerNVAC2nN2dOUzjiljYTeBEXn5szaFKtzHW02p4Z6d9cjlaY
+UKaDP3OTc1KyEYMeYUoSHqdwYH9ngDsQiPmGt20BL6KaLl0N4qZzs9WX033ED5mynqIABEjlzFYp
+5s1sYnC+xDQ4Xeem7Qz957WnqLwptCf/szhK285Ou33WFaGQP8QrhL/zU/CKcgP2DXqrobVt2BZG
+CwGincgAh97bhMcNx5n0f/14fgKVTekMYj687EKs2Ew490hS8LCof3lLzGnCrUpmm4JQIKsGeGLO
+v0I78mKVdtJI66FSbW0y3Zydn1TDLqVeatdBa4aPtLMqSvDi1OTMfdy+pC05xL0XsaN3yLkSTL98
+YBIxBTFFSF5cnF4GLhKb8gTA8MoG9g4xwQyx9zmFIHB2OKsYAIvPbD95S3OTUFKMywd2fo00veYN
+Hc7xQkhbNgFu1v/CFoeJ/I+BTjSqkCPTgPA4y0aMQHI9BaU8fhHkkRhL1nm7MX0HoPIeJ09NLapj
+aWmlyyJRSUZ65j4yUchuRfs7UQiANqkI/EpI3lisW80GBJP9K2cOadUezupYM4p3xAcz6YECPHU7
+FF+7ICkN+B58dZZ9GfdLUuR6/+WgsVAhVgMMq5IXGfLKhvK0hxFPCqkE9EXZulx/+ex5pjIPQda5
++xIOoMGWxeiORrZ02DDNnGBQLYVTrkoSkRfTDyWIbEA/Md2ayVI5lfqT9R7aEzz3dVPu5jWnsOrH
+Wn0OLpKJ4AQT1xgTdSE0ehl6twW1dSYRKAfl7+KR+tmZTnuJlmBxZ1Mz/SP8rzeC/HSojO3NsGUL
+ObrqPeo9yta762U1Q5C85tbIqLOdw2ZqTImeEkomEf9LyCVI2s2Zrxhok0oCKUSZ+sQw6e7HzMsh
+a4nZZ/daBhl6aA4QXQLXa7r7QcZOI2/gfLGwYU7h+r7JIHxpo8WzTQWpTAO9ENkTawrFVn16XU5X
+e4Bl2pkN9qk0/Iyiejw5qfFNjSBToCk1cPZTWn2Z7AlmMnx37nlAwSY1C7YDAziraXZrvIGYHYWY
+ne/OfxPKnsceZY2/MERAnyffNO6OqHPLUsJDoYK8pXMni9pfQYRcT2LhbEYBhWME9PODVuVafIcs
+1w6uhV1XojAWaHusVNBEQIaN69JBkM2taqjfdyCDsryeKIFUgDFKKNVBfgccrYZ+BO4UiApxDl5w
+xcwDluTzZmg2CzKZJjkZzJxUiCSXxGD0DQa/V7mtC9DFYsX5qzwJewUD8vmjPWZPTr3Eho0fOt3q
+STUZuiYgbrex/gJJT62337U4TkHIfgIQ034QLpcXpmS7xVeoMVJyAmeuVXtYVGZgnNMUTF3IZxAr
+ZpTEiPsGX5gAFKW3zPbtEIMVT00UT5C2iCOafuAmrsqOe0n/Ll7ItHoo1G97rpW+ftt9iOdDI8xK
+pkv0uvZzIkcM80xtOZdAxH27P4PbDcV4R9sqmqy3Tr8XkJVtpP9j/3e7m5u9COcCNQA4IhWEWezW
+Nxu01g2FtUBoJ3X4I7OQmJiofTI369kRPsuv7UzQPFkNjqd+07f8KlSgjiM/fUzIFzsuaD/T8mFt
+dv92et0EHgZN6CEVCafxzrTSOui40Q5ygtruWELzPR8SaDDS0rPgW8/Mo9h4XLGem3syonzgGANT
+CvHNGKNgBRuuc/TEkesaFgguoWQfBY1SqsZgQHx3g07oLaOIyVuKQq3RSm4tB9wdvEqTCVSbTHpx
+4/CphiOb/+cNeWxPCvO7dL8nNnKp+iNsRo4jplimXPqJtS7YXPaVJYIm4YWA62/kj9crhMTEhAcw
+dCPuzbvak5UtOr2nmwuqc5KdXrZTuPI2tURONnnwaR4TwbV6Nie6veBr+KX5sFe8f2PnZ/4C63KP
+br2Ru3gFk8+GL1qSMjHbJFW+wjuZcAzx9AVxknZBvUhUsmYECZbLq1E5Uo9ZN1Ec9QXNRXXp8ds8
+ZLjO03F0Dj/wofoce6o/yl7MSTZnww2iN8IXNqUZ4OvRDSovpyvuCg1004bxYkceAxBvJBqiT0CX
+Pi4GP7en1MSa0iZoJJNmQC5Y1YCDZjGWUQ9yXYHrqRgU6K/Jprq53Q7lr2W52PIn8nGPLTdwXX7G
+437YWknACl/EXE5Dv+oJwqGhax09ODl1WgUZItAi3ljArmhmk503tuqmSmBmEywBGjs19Fz1FOvp
+CJbU1f2KGH8wO8luPFcQdPiz9lFb/0LXuBQtj9nTtEv9rvWp0N2bOqW5SUj1e7hTZTN72K7ocpCu
+1Wu/DHgLnKz95FT3GpmkrHk4BFlTAGUQxSNtq27cB7h3htDlr1y+K4qbkRIJLyExPUtdS4lD9akJ
+56IzMLw70zQ8K1IrxF5M1nyOK5+XKwtZl9mQRPJ1CmLWOOM5bXLDzvraZJ70alMGceYEboJgctJe
+1ksnakifULpPvGKY9RcgCDT892hCf5rnNPa+w3fl8vb5s8LSAYJX7a7F+b4PKBtgfwNXcfj3up7v
+4V8yFG+gt369AeGqjyNYTZdYxK0jY0f7fXMXHASoiQGLt4Zl+N6NUJZdgxNntTBmKFXE3r8CfEaN
+yGQkG+JDyDUUrbmlXzMLS83zl+5K0uE2wZeYwOEEHiBlBCI5P41lcjiV4XT2rBrqitVhe5U2Xdp6
+bsxMDTVhrbDD7PTZ818VcMTADySZF+/Oe0fGJR1wJ6mX8/Z5KdrjiIItF/bSddTq/cfzwJqPR1qb
+PKs3gJyJ2h9TfcwlTmDuTsTogjIeGjKgr8aWgR3inH4awHYkAFFUcjclQNlvSx0wD7W2mEH7Do5J
+UDFRbK7zfgPDzCqBrElfjdeiaPWtl6V/1Nsk8b6f5TIR5phLTJ7wRXLIbcBBLu8/6hfJ53j/6kcq
+qKicYDL0i0PenfGNzt34xG2IVnOYYrmfQ3eeA9if5/z15zh+kRHJSKXuiKbz0/BT6NT7IsFuXYA/
+qK9iJiUxZohf1jfVDCioXi334Bw0B0x90k48H/0Kz0JM9s4VT0eodSIV6Jb9j/gP6tyJq6BVqdc2
+qQ2bCmaURtidNluOTfH9+eB4Pzn1Hdtd+tCUrsGjX/I9Diyn6MtVg47fXVzAqwqt1jtDdZiBAmA5
+GT8X/apn002EDjBodmvwuuU7PHniUkZD75HEBtnHxzjLA2C/GcsUTkk0vvcjxUifpqIvzvi2xz42
+5z2Pu+TbW6mPA2sPjmZxLIBIl8rK8HFXzT4Y9mX+g/5jwMBKa3q2vnUcX+o7zz4KacHciXPaBmzH
+NiTIZ2sfXBNBNQbqFf8Ao9uXg0kewMZ+eHgwt+iBV9DqHgc/AlwkHotSvwg83Oz//mOGV3Lfdpjw
+A/A/xPYWac5zZZkeZt99KjcLQ4f8pzsri7B9Xik1zOdqC5ak24g3oOwuPB/8vQXIVu5sKJ6cxvHU
+zmsLf6Q84gXvUgqPtEteV8yLd0wLIJwz2huZFuKLq7mojImZsVs7EtPjOfqvCKsAfJ3ex6/f9yBy
+kjK9f/zm/P/8HxGZrcep33EmN/WSZu1hjUGlhMeIy1wvENgalbIMhDjq9ZrSEMB2ux4/fbrer6sR
+FRjVmxv8+yk13uvlswLiDQG87QOCtw2z58+e/UXmIbj1FIhs7cVrdgZjhrnPTkfPBxx5Sonvcwbx
+HPJ3wUYZohx9BvDAeaHOLahSYTIaPmL4W4lhu7khuJ8qQD43ZyRByCq7NYYe8ggYUVNhX+psKVgZ
+UPwYRHKgpX8w8ijFIcGBo7Foeo0WkZw9B+cXrgEwbi96AZCx6sfOmwY/xQbcG2iDqozU445GxRIf
+tWlfeE3K044WEbk+bo8fI2RzOBlrso6sMU+AdEUVLqUnl1qRDwNHHnhUJBaGsy1mgaMfDofeed+G
+j2hVBMPU3ZES39qXlDH6muVao2wy3BDfsoneXqwr2hFpWgfERXMELaqHM/ue6J/NTMrNggtcZpi1
+icVB2nX19R9y84jsb1BfxcdTdXDFm1DhycSVddgew0xNlZ0HmH9pLzIssIOLiK2UX0d5vSCPMo+k
+AYGFGLFU4NRxPrisbUvWmR4MswdPKUlPJb7aTbTjQB4CnPk0wT84NrASK31mJKWjXYvwDqC3k0n7
+wSKFPpT4tbaFwh99Y9Ebwnw0brAeijq3AzZD9JLf7nOZhqFt0sc00OHgRI1EM2BA9KiVSAZJNQWh
+N0HgH+zbw1nilxbw88ERgesIpvEh++UZzCUA+m0gIwHkGATSDJvCuU3g0SG182ixgPszY4yGUHkz
+juwMFtoEBkjphxC2MGVoYMWKmdItq9L0RCjQu9bcBEHCmRh0cehNkp6y9Lh8nZNeSeBYiY8Q/RnC
+JI0eNwPGGPW/IjZ6GGkiZHdWT5YmoAQyl2J1XBlYNjV91JxR0WNDwRuiCZlAjoMfJ8LgmVtyxDwF
+nD9LTAKzOSlHjiPwCzwTzRIqJ261Qty6ICeNBmlLmhuEIuQn8rjXhh4WM++/j/X213xZTZtw1Xlc
+6aqft9TCWEdWHGj/oM8hjXbyCNmLhSRMHLKafYJzcxwksTyYuSIt7nka3D4XOeubRYd+ZKFs1aLo
+7IIFz7b2ByhGD4LGGTPdxx9KnpeDX9utn6E3O7myB9TUz1i3u4yR0/wWUtW9ubbHZRIQyMj9y+kf
+K3BbNPdcyHFH+FQWnsf8m0pGBx+4W31Y1fcrLzONcHfpNc3enVRBuOaBCy1JB+GJ1i0n2JZ0EeRA
+iaaKRPQWiIZfUCtF3qFGjyg76DNII9OJ4wS3axp36AqKDadP9pTtHhxY98PMK8pKZdQ/S27Npk22
+uol4QXE4geWh9HMWE7RL+O4dYknUyhGowC4hTXIlDq6GWEDNfIIU45x6T+QiX20J+cy8nNe762V5
+An2CFvYW2UNqw2ugQ0ShgA9EQcvtTb1f6Y4U8sZHsCMBWGO5ZGdksgOxZojvLhQzivfReXYPgbDS
+HhAY+Nro9IhbTCHq+cjbOxrecfCXkiThAQR2SlXC7ZDBehGGULLVxBfw3KaOEEhDfGsRhT8DbS+8
+LaQP6CPuKknjuCCwVewMbufZv0Pgs4IdlvX5bxbMO//dhtDXBJIbLvyAdvMwDyDdzCybp/6wH9L7
+zrfGKqE+hJ+NJ+FB3TQf2nYwXPT5qHwoEhdhI77R1/BtVM2Jdx/1cNnbJAYZlQh3LZ+V+pQnZ+aI
+BRlBCrUc1m58cFwDXcqZa5fwoQhHy7OEFNUGxZdgvrK4HoSdiiwV3hFn3IwyEaYa9LNAKo5Dadu6
+BiqZ3ZIj5K9IkHfR+/jt+/+KM4B8/O79/60R7KBrufziQQexG/Z8szh2UNWqeErKKIIJRTiRSM+d
+O671YVhRpOgBD2ZA6Y2wTA+ZKyXig1gYSlG7NuKXuZuAfhg47ACKNgOlNe3hMSG6gNF63/v4/ft/
+CRpqwwHgAB6ZVj+Uc/Dp/vi/nv/2n/ziFz0Rld7gmzfmDbCLT9UczFTZ/RQzNm52cMDYJOl4FlFT
+Gbfck9iTGzzXs2rbyCpwAtZmOwfAByhjfpabDRhZwDtyCq5wyyV7GZsj7WY1XdIVDCYXTAy7ZteM
+aGkx0qTEkHpI+jOvNoQfgIHypvZ0RTpvBTuYVH/zz7vpprl1qig3Cz7c3+u/fXv+7vzF+ft3k9d/
++/L19+dvv/vWLNeXbQoYM1WI6diwtoVcoPmPFWA+Yc4rL7YX2IMplA7pxTfhZYRaTVfgd7F2xQwN
+NNi7lf+YS8M//gvbEP3wX8oSnGXulxdwMbr7MIdXeZB05YfX53/z4mtXb1Sumt2mzAekGhwExd+d
+v/ru/XmiOFFVovjrH35IFzeUp1Go1xWnAQV69n0OzKsxSV5gZ1xtPVr3+qNGzH990ZMqz26r5by9
+7gTf544o9F2J3jETdCW0FIb+jOaMvPfcRkAqczt2mF1DIB0iirhSqhEjnaIg9/Y7w1rM9hVB3RMh
+oRhkdTcziRyMdzSzJQh9BC8PlwU+0zcoVeEscz/c4o4w58bgXq+lrTNaLHfNrVqexTxobITBW7W/
+graUubecRmke57v181yKeGjH3DEwqbPM/XCklRgsNqRrtI8ISpkRPe8YkSliU9A5xfpCRkHbh0bR
+v79WtnrHqWyQQRogZKEIKhHx0IzgtUeWB4Vcq/0XRpN/YXkLBIIoflK0VF5wQizmy5yUj94VqXCq
+cUqAhphiFW9jUTXeYnR7rJGk9aKeuTpEw4N7Sp7IfuHNMX5U6nxwlJHK+MJUG6Z8UcNJvZJJCt9B
+0lJ8dJp49tx7NkGJxQ1YsZv7abUFWcLsNGI58KDcnJla8MvwN+3XXkEmWcyqRke0mQsqnwtPBCfP
+nh/2bUtH1Gg6+f3bN+/e/uW3L75+/SrXZYvUIotkQNz79+evf/jGVPbrAYb28393hFY5as7Nj9+i
+79xDOojXD+ZaDuT1Zgo4AjkV9SdnmM3u5sPANSj5vwE7ixjqMEKt/GUIohPyxvsAt+1JmCLjuVuo
+f5U9e/i3i/C+ppqwGIhYfdxr3+SaEQ0214OjuYTkoaC/dI7Gzm3jGujYH3D/Yv4BmgfhHxM/U0QS
+P4dqe7q/5GEVjDd5RoRlCBMfMTADkYgl5R9QMZO7hRjyCgwzsaPKYUUdalFBNRzcSSXvsQhDhC2T
+ShUvJait3NPamgtXKrlZ9E0sSfO3HMrn9RnfGvTqUbz7I0htZekff/gv7XKzOdp7qWWLoGN1xvc+
+/vD+n2J+xno0m64BJ/3ju/P/Y/iLX3RdOtydBOZs4eOcoza/quXq+A6jld5+14phjuWlVFSrl0Db
+gFiUL4dy9aDlOi8ftm+/y6We9sOAg4GSVBLmGWyiJJq3MlhSZpYdJK2cp2K7ePNzAS7ua3wHE0ye
+a4YDWGPvz9+c/LsBMETOxxpwGhn4KBqquo3TR0I8sJ2etmn/HVzEO2adZo1L/fxp+4wpo7PGxsKD
+z5q5O2fXe7GQQD4NSC0Zprc5MD09c1mb3RoaYV3qT8/GGdyTKsBBO6XfcMUy4ij9AReoP9kL86uX
+RPbO3Ysf4F2iforzOhVIg+aEElwDzbuLAjl7tbEIskcsjDSxpc0i1+j6HnH3MCkgfkESMrPBNPfc
+hrqdDPGUg4OLgB79g6uEBZ9u9nSnQZf4EcIwrGoZhlk8n4Ouy1m1AETFqd3Xo3P+kRcWdhG6DINB
+VxnC+ADsRAsqKbJn+Yoz+0GaybtxOauNrfLLszCSbMH3YztO/OA3MNjB/fWT8Cjnxs8yc0nBLwLu
+zTv0rI/7M3AZjsVU+grbEv8KExWaBVvwpdz0lXuf7l/Qed0TJxm41ps3Sj9MOjhF6xfS5mUQGHaf
+aA9dSPWBSA8OuSSBXgHOpVx/WuSm+927FLxFmPanD7XnwdZBxouuq8Ms9lHoz6t5tq93pA/gb8i2
+9+ZS95t+EQsIlr4MsfhA2LxUAQXxKqH0Ny8/rXbLJen0zcPvJj+8gmwcRcsl17scePeVxTwyB4Q2
+cVrdQcoPpnW5vU+8HEJ08fYHI6K9MRzqLcRpd4NKysj1dNgr/jBrodJ/wPHrgSjCnNecsCzgg7sV
+tobLOluW01W2Ww9Z8qSoEW93IhgOY9AUSZbkTQiTdus82MVNb4SIAmN25c17U5Yf8medbhPpKf7M
+6eVWkvDOMhh1f4bDtd7cpI98WAQsgdkHNhh1U+PE15vqBi47oQItDfUKLHvdzruLTm6UWDFq0JJy
+ER2E5iWJDf79KXk/4/LC+Bnzw50YdxJZCCrJxaKEaQC8T+B28JNjEO3BokyPETIznt2KTFF1OQCz
+hctlWi+yhVP23nEEo30/F9kV5RNDNnZQA3Hed4c8vTNXiT+a7cFwvLyKRiqwNSmKe8BfNNASIQM2
+lyBP+IH+lcT5k5EcY1nA/2W6ra7VCam/FqGEG6gCiTEg4Qv1CC94GglHWtWXqlsgASuR0KyW8w7Q
+KGT1C1+lecBS7UbUBXwrCEQCb6BP/oXzxy7JpkpCDf4wZ98CjGhlrwVUEMPf3T3Hxi4SZbUbllVv
+I75s5P1riEQN5Bu74qY0Yu4G3wSH/xzPRvwuQRWz1RyZDzPcMIv5mcuiFIBAsZGiq73i876TR/ka
+CpbzN4FIV8QrxCK/rnDoeg/Yw+X0TjUb6g6oAPie0K/gri1fcWZbCNitgLlbKKr4ZoWATOmLFeEy
+mf9ST3w8xXMQpm7CJuM8O55DRkKEwN4AlNrDBtMTwZwW3/sfSrm9XbKAIAJdcqSyvtCW8HvRfLwX
+eQe02dsTHlkju7Jsdifa4LtfTBcggOazZYOmUUCFEptAlK/MY/P5BjGiQAsEKiAb7hpia4plGXQz
+DqcWz1Y0Mj/FGD/+w/cj2OEOtrbtUpS5Pqr/TNyc6CJri1M2IfMFTwPzqNjDWSvkj4M7BSN5oj/v
+3ofobsum61jfYKgGDCkPp7X7sJZ5xZi7EUzaNk+lxXUr0LNzcUYqkDtzltXzHB4piqKmksmEwO/P
+2fWesuIUZkrQFGnC5so9gBF7RiGYdijyYeuD4tA9CkB1pkvQzu5pQP1YSUsgXR5XN+OB4w/ngS+w
+hEmPArcRplj90EtMbx+PDz12bs3esvhvkpzm0ToBl+ISCVW5V9k3OMpgeXfg71+eRd3zq2T39AlS
+ItG9VzmmIEs87vK8a9Afqz3d1Gy3QZN7s5qum1szQCYLQ4t35Z0RmI0MJgJwQBimO6WLh+HSk7w4
+bilT48fRSzrI7ZzZ3JtXOf9SIuo5RLhTSUZ2RXs8cQHkv/jkzatTnPw3r54HcLHg+LxagZg2zb59
+//XXrIKCKs+yHCMTNuUnHXML38g43Ly1qlVB6iqAm2KPzGfD0+Hz8IqhElYDwDIFwVacI4RBRmVH
++vH8idPeTBRr5Mx88a+76qGcs1ivkJkmoeqO/hSdXiQm1CgmI3YfuJU0kV0FNmB+rCIHDiN9AGLl
+0Gqymlg/au79YmAeKu9TZRZyRUBXqpytHSW6IqBBdUVwhuJC+FgVk5mKS8qbwaWPYDU5ArsUm6JP
+tapciGuPVa3BEvpiDy+i/Ejinia1XJHURKxx3KJ7jLM5qIBPYDMD3GEpxYprpA5EgPaJoQV2E3Pq
+Job/HXblwXTTdmiKIkJnOpLFBleBUFv6c6bWUF5seGfZCQmua966R6LhjdB75ZilEJGi2zrfsf7t
+a0c7z63d83/EtcMNLjMGvhw/e+18fTPwrdi4G4hBwKNSxl3z3Kqx22ujN12iNqz74droXJeoDXMQ
+qdAhDuGubBETzRs+eEBSRjHbqsng4M8SJ38rg7c60SGagzrSNeWhaFCwx2q9dsOJ5A1HzSk6bZlk
+X8Gu9lWbDBhuw0BaaVkNvxtFjG2ynu4Gih/sJkFwAdMA0oubgaVImW6Co9xJYd7C9Dz8Wxbx2gVK
+K0hSNFm9yPwbiF3cgKaCEEAdBpIPyC6aonq6kwVho9HUJfzaQwQLVTDJRcjQFurDg6thSmgneKuZ
+6gpJxtnc47gMp1pKx6NQbxq+e1uDXZNu8SXc+1vM9/QV2425wwIOw7PiyG+0QZCbMlbSL2OJ/efL
+6+7O+p+YYvrV6gTvIvu+J8Gj6Ey3TocsBNkcsB1YiUBUH2VvtwiFpfXUYElu4l7/E9bIbCwH+WrN
+6xK1fE5HUAM21241hwR7wEBBW5e9cmJ/lkNOPn2V4ewD023xs+R8J9Jrib9DoF+KV5X9xLgES8/W
+GzcuYebClahWvYRcQ5B3WkaETRRuWBoMu8EUKV8gPcIWUapFhKLPCMVOlJj04A5ITdRKeoT2it5L
+CPbmvz/vXtQhc8i8hAn/tJM3F4mqRTPnu1tzkahadKGxq56pcwZ+Jyy7/z+SBSxJRed/6kCOp5S3
+zgHpIKkfSphNLflEYkLHaLxb7XIeSfGREJFUF7WNpmOhz/TO/xwJ4R9L0vwHlUWICESjeHg7+vsQ
+QLOww9Dd3IqfLcevk//bySelMbSU1NUxCqRdHePVIeg4UizS+R3te3vKWxO5mendNR33oCCbl6AV
+J5srUZgRBihYHRAZJaW0Iw9OcnRdZmQyhfQNQyKadd00FaSPA/U4mmNEccZpR7LFdJORYYLs/uY0
+Lktz/JMM4pqeQdT8zW5DSWK35vnNLV1Wr8vZFA5uEAF22/oOTdgQBwgheg0o7kxD1+V2Syl2Z5tp
+cwuHOu0VwJdEjEQMGCyX+/ikR0GRuOMXgWGGMSO/Yy06lETLCcoyOHcE88p6e5Cq+Pv7Av7kMjhI
+4Lc8a/RDI25sOe8YPrOjY/NzmMo00vCbPiuAzTWT805WlXKrEYMwJy6Y7MWa3S9Ujl9zFO9bkqW6
+/Kto0rL+LCHav/MqVU5RbNamB70O2znFQhCOw1k2WG0H2qtUtzf49v3Xg4SxOCj11Pz9FB4Meh/P
+3/8P4K6MYTEW2fTj+/P/67+1Lsu+o3LvdyTLv5DCBLbhifn8bzPyC/V6GCSNbgwbOQkhJg7Yxnbo
+8lBDni7Mp83g6JsSE6WtUSSl6lUDiVbXnMZgYl4Y2p+UD+YysUIAhFz9dtI9biwq3JDDhS1EVPUt
+vFvypi3vrss5ABXYPCswbiM0T9fADW7r+/JTuWGAZAFo3d6aTew8OZpx9uPqp6H5z5/wSP1x9Xe4
+wSWh9/a+xlbhC81OnHMeMmh3hTiweozgFG8at9ZGTO4mJOMVtKhs5cP0bm3OqywffaoaI7S/xBNq
+mNFfluDyouBxAao+hOqJPyu0ggwRnqk+MGyQ7kJrM5WYUAOssZzIp4T8FVCPCJ8y6AKDMFeZRZBu
+bjO9n8iu1wsHTh2DQSGITjar8iNeBLcwiJ6LqLpEOWbGab7/jmDrJUuO7eni2eWl/bwlwZPKq9Px
+pSfcLjU49OCnAYFLew//lHr4dxFGj5dOpMu7kAZycnoJMACDH82XZ0/gAuuBlnDGVMbEBVSVD/CN
+z9TfM0Ril0dR2p/4UwMobPjaOPENtwzjS2hbgcfA1GfZ4AhlLhZHC35QHHuxk1WucoZZKeJSPJY4
+G7C8lWaeFQn4FwuclD2BWR6YcX+BHWLt4uQU4sYamH/IfXM6vizijB4hMYzb0nCEBROfDJBA6Y9M
+vKJPuMASMAc4CTLQDgJrG9LfDbqnyMyNm5poTqRVV+JMlkQAK2w+XEHNsbCP3mGRJ8+Zds+iUDpJ
+Vh8lK4UR98eaye6aG3bfgVpmjyXNXB3Z69IecF2xrKrf/q8vrjeQYMhij1xmjzHFzuNnD/OvIPIj
+DfZGY3U5tYdZNbdf0MWTFiqE9g2m1gwTbR4R7WdRnRfUEECe07OUapFLd4K+dGLseF0ySLTG3c8X
+IwF7d0D7zumuBYynLTtNstdk7t1uxDp/1KD1pZHbZHnmsE5lq3Mkh5rG0etvv3v97XnHIiTH9ohQ
++QE0ygi4dVbPZjvroySy2KaknFdDkg3kZuS3ozLEIxhHiVed/q/N5eSr/qiXXOxOole9uxSxQ74q
+TRbTaplYvJZzR2+lGV61gMZsBtUMfEZBUDQf+VU/Fd9mY9lbGmecjFx6AtS7pF8quKVm4pcacSwC
+hsHbT18kaxab3GyABgQKwD/hEhF65CczOXCBJMzm/Zd9FQhHKdvlHjCxOwFaY9HfNgkOWEHHvTZv
+2+fD7N+gXIScwoh1W5hSL9XGH8zAbJqNtnGAd/eBcaivUU99ksGx9j7+zft/OmGEHsJS//j78//5
+v/jPAKk9+57Q1/EKbWRWFMT3IHVvd2vyStut0IEGCthcqKSWiaI5OVtnMuITcX3weycKLUi+UmUO
+DgrVqw/lniI3BLLGPer5E4iZfbnUOVL1dPmDOSosGA632pvttgmsllw6teiRI1MKob/BwdPcI5Ce
+vKufPLUZTqo7dESE/6Ryw4ozsXkN3Zh/GMz7gDN5G9gzNlTdYUufA/esqluB5E31gKYQXuVvppsP
+5aZVADG0skbnAHMWAvT9blvvmjIKQSRNIZQF1g7/+q+oPgHPmh8BKA81Crg89Es77c4Qf84BDs3U
+1df6AFH6WEPY8IV5olRagUITsqAJocOYE3qb61YOPmrXeKnAAIMdWtSUE6V0M2KC4nbsNZZUgyma
+oIs55xnGSjnO2Vlf3vZlygXHOjHvsLFz8SEuzHTNakxICofRnVlVQMah1rPFdGZe7N2QaYZRb+Dq
+cVYbzFSTs4YY/g8/EQIHRgQHSVNAHxTpQQKy60l6oFs3QZkuOETDL4L9YT540yuzuIW5MK1mgu6D
+OsAteuxJLvHpLVgWTYuGY1FKH4AHG2cWdIwBx2DcuLwlHfnQFAzCcqXNh5F5Jmuf8w+Hq3eH+wI+
+w+OJ2Bip3Sipj/0sApOfNpQNtcdC6Y5yUlU2GdGUByLVxNnehqe4fBFcpKeJzaqTqtUfUPXHSzk2
+fdHGG7PSFfYiKTmgX5R9bJ+ghp1uQNuDOfjiBKOOEG0MUDHMaMOAky/NMvwyEwynY1+Pg0h3DKoo
+chaaLjGVHKybIyIeGX4QrbUoW2KZ2RJA00pNqDUyTfF7pIuooR2FDm31aHlvjYGVkG03bJ/U5dvq
+EyqiYVLRTx56QFtynAVouiL4ti35p+K2zXJoV2YTOlmJsq6aVduEVwPvBrwolOWctoUMRI/S1ztV
+FIiA6WKQDgpB+gYerOOmLec9oyFqxC0icmEPwLFCPXHqIMljFma5V8GjSehyO5tsOYOkVWSkMKfQ
+s1lQgh6n/Yu56onDcmbu9b6+/sPEYoUq3xQ+2kNdN+fuw5PKvCaQtFy8SYifsOtK4Jg7Lw+GJWE6
+STMgGgCmR+hzqhxz67UBf9iMaQ58+mf1cklKf2QUOXNt9GMZYfIe1RFmtQD14SYvhl5yCjsDmGxB
+p9kww5CQRvq6yXQ+p32cYx4i0VfcbOrdms508xAmB5/kfUo2veSzEh+OXBuDkxNhu+BWZP6idTN/
+hXtgimRw1m/M8VROtmZzGqqamyGZR7f1vTSDD5EEWvx3b8vlmqroGwPXhqR0eOJf77P1cncDVqf1
+ujTUZvYefwN/ovkIIx3lfXVymL4hvdBZH75ADeTi0o2CuhcOyCWc3EHowXjs4qmL623WBxY/3T+R
+CMqv4QB0ICYOJEcEzckX5lYA0/3FhK8IgyIc4M2yvj5ptvslhVOCR6jh0ys0LXhXCEY9tjeJzkHy
+Kdw2T3n/HPOgRqOhbVzGvZPUdlzn9txu7377md17Bw4FBnmD0RtndkfJ4hEyleydLtco/T2iXTHS
+9KzkavVUGgiZ5jN/s7pM73A+5WaE07ZrCvFIEMul1MjKb3xOQwjKcXnrYSxWHc/c12wl7kN1Kl2p
+HvIvWNySwC7+U+K7vDlls3HpTyjPJq0/2uHR7JH3eQBqZ/R1z6YDlNwQyBTrNcVYkCX9Bbe2IKc3
+6ZubYEkRyihYqEJgECoxukfEQHaEMLduc7V+TRassW7st3pgA1Pt1OzYi9Ph88siu0ddzhKkX7Cr
+3xP6pRWH+Jg2LEQPTg+fZD2J5Ds9o8CcqTmeIEzbPX8+Ui1kXpo25ByQoQ2k9mb7VA13dLu9Wzo4
+X9SVYNJE15bY7Lj94rOXrUVePx1m6q/nw2w0GpklxCsQyWhTkp9ghdR4lLDoQG2kg1H3l4vcBV/9
+SI0rk2/TFMsismCp4B9MtfwXZJTGBu6mq+kNii0sCn1DD2y1Xu+3+goDuRYhibXqzSbeE+wzvPc2
+Dh7SAjCPQLPonmvp4Cc7TQMe2WAsc+NWZEBND7Ixd6JesZhiqqm2CKXaPKMf5jh6CczcPMB/zd9v
++TpkHslP1agIhubtG0vWg78kjldvzGP7W9WCc3JphQz4DvMnLxjBBv/JTKuTE91kEnWaS/ZHwxa2
+6t7trpJMwSKr0T6iPBCY2BiTV3JO37XZ+NY4LHGn2PSIWvE5+XqPmiMMKp5MkLGQNgRQtuEV5FRy
+5wkIml6xEUXdejkjUVHhNBSuHSuFCuqQezOpmj0kPCdIbZThQkd41Wr+ha7qm6IS1hdeFn8s8jTq
+JEZ7lhMHbnKAYaz65hVFnFNh84mwG272wvznkiOM7d8dX/mFVAyPJ6R7lM1yggmiKwNPGQBggci8
+vYUk6iS6XMuTtRnu9bQpLS4+eOBCBQDNX+vU77ze1PRI2AjE7ldbSmMIyY3ihGHr6dZBPTPVgeQO
+QtNAi5Up31wCo7odLVZ3oJeFPoq0qceli+40VyipAdu/resPdKHQX3UDQlb9wUjED/vcT9rEuwgr
+juy2kTUAIOc7Tm5oqp3p5TjjVQl2XEvVYBG5228SBTraA6oMNzK/B6A2ShXgIB4ozqBlRwt1QKHk
+JdPFtfda1KQ+mMQjFbZhBzVCBIjBzhAVgvd7kNyuE8zlbpoEH9OKsGnuqgcABScFK2xP1KO9BO3X
+vNxUnzAZtucw7DrFWjAbhhABaDcRP+J8yoHgg0+R/+GZAiH8tmWw6s525jZ5R1PQf5nIAa0+DF/n
+tDBMNrYxUWN4Qwf2EI4c5SDrmo8TKmrtQYjmIdJ7vUl8Ew/KHnGdA2vFfsWYEXMVzb1pWdmbUu7o
+kInZG9YBk4dY0s1Eb6b3CDaCNUZgNF1ObwCW98vnhmJsi04j3n7NMOXZFKM0sZhgCSCJzF6bCUIO
+kSbTojml7wi3CCO8bZdN2uWRDSTfg4boJeT5eQiQXW2m0kCJ1CdGwHQ0WzaJIprSrM43LiZCT7/w
+hvMNbKdcj0wprSDPTIDJuUgosrqgil2aTy0GHGllUqEqAjRjXdjNOHB4bZ3q7nDg7UlEw25cHtGU
+WmuBeq1F47RbfRUoxDo2Wl1eFTt4L2iePyDtKuthxfCpRaA58CBIv0c5XPBwZtvatjZ/EVHZ+KLZ
+cjfnkycJ9Gn3GefTNuLmBpLEVJ9KcbgGSK9phdYRasj3r5/dTl2MAXACfKCWCP8eAfrCxgO6kKSU
+YaAgKjpXVK0L+3WFQE5C4QmGbVOyeyHKlOoNNaVRvqBUB7QZE82zGxfqRMvVnE31IFfF5Cm9mn8u
+xidfXibdeNT6jduyQnor2u4XQ4k72R+tPadlLFd1VKRX8TpizOaIEx1ioRj5z2GCjS7AzHPRDzaF
+GPLbd4ZXYuRjPZnW680WJPM44RrkvplNZ7eGfn/TC0CluKVUmC6drIQmN0EXnU2zpRGEsuwjQ01N
+mQnyXLWstntfUm7Yq1ynMAL8LOe3cmn9B0KCpMo+hc36qQBY6YV+GDo7vYzcZVc1Q3clvyyVIZHL
+u6F2Xb8aEl5tT3rdPPguvwOxhghDc+V4k6ldKZ5o1Wobw615/Q9dtlg5+16KkJK7c1CSTI3sS8lb
+hieIL4IlQ5DxJkQZaiXRnX8VivXHCQEUM4Y7px/OG9x6viLMkoqr8IXcP2+comT/ex8lzXC8Sb/9
+3QiF/k91Nc82RsKt7+Q05LzCZflBfCdcMkRDEzoZ4qMsh90ugWjLPRDJxpDtTMxbU0MD3+9RfQcH
+JtiKwQz0m8JLjoinkncYi5zNuRSH2U9/KvxjC+7ZIKqBexLfjICgN45fOWfSMCsbdCk8l9sZuayD
+TlgpV76yIhFmbyrBELDJtvzewPyoTHt6b15qopNylT5pkgesDNUmEfbwwIL2IQv0L83xMel3BceT
+b6Bced2Fou2Q5Ftsuyds5+DVhVCxHbTsBfCB6dFemH8uk2WWoKOJAu+XIzAY5h/K/dlyenc9n2bw
+mWP870idbMXF+PllKl5fdpedIZ1XMLiWMz+lkFFUc8ixIQmImIWmnI1UrXaNhI8AKCz1zI3pzA7s
+zD/F/Xuj/gh46n+IvTsFhnSW1rxT3WwnM464LN6hCl2MYAOhMAE+w09oCtx/PC9gcxtdNYtyM2G7
+Qs4jBEzSZsijU75dd9J7i4ZeQQ5aJSOc5HcwXPVMOa5Jb0VkCoNUsPzTjUs1MtSsvxPPB9o/U190
+Fn6YWTGgA1a06RNFU4lvQ1Qeh2YaYcNQqx4QF7LSNm8HrCgME3EelZSKJvdGrzY9ySEQA2umRj9a
+o16cyw7tXJ5Zg6et9cb3yIu1QFKgX0TZXcVYiQqbgEGjUty27mtj/My8CcEL/e1Mk+bgQbNhV0fI
+oSkNPYjuj5uLx80lhEJQl9LOqEokkE8M8ozb8gbbTVaMhwm9nMkP6hi4gtDsoSYMx7yvN/Pm7Cc1
+5DEcN39yATMwVDZ+QSKzVs9UZ7jFfyYQqArWKfzzOe8eU68J3VSlIuWBxJ9+Aa89vgTav+Oiui8u
+rR+RDu0w/+Fh0v1nq0KlzUa8RR/JbMY3bcw8DeZNdldBSBN6xG3wC27hrtzclOJbUlrdAZYZWZv9
+LWIcIORPMKak5ohYBQ7jjOuO3LPP8VKODnb/Vu8aTZ7n4m5A1h8pGm8geCqz3rUzXRuuNJOm6Pvp
+9vEGg6zVFUXZB+0zwpuxbiuMZBO42B+nbCLeBVg81R/LOXK/AajCBoLiT+7vOHrm+ofk+K4TboQe
+NeQ5XDEmc6wn2K3N3UWsuVhkJH1pQSEcWnyhcBaEe4w6RqggCZquQVlqeuJTrZ0oKXG3kosMSVLf
+OSVHNRd6NAX58TRMpO/2q+00FQH1eckWydEcB8F0QP7mknMRdOPl2lxUwNUK3dI2234RjUZ/BWVm
++qZq0PCWGiErK0zdCQufgTKhbVSx7y+HUaAP2B13Of5x1W8rWc5Funu8QdAB5F6iHnGh3Ok2suxx
+k3xB7sEsU6CXBpx/08a699II78EtktAmmPI+s5+/evvt+Tij7G5m1EZCns5uYeBPM9DcEDAKbNun
+ZiuDt+w0lYNmt6o+7spMrLe47/f1bqNGyoqkuHL2OCtHkb3bEcSj9cbci9V0Ky+8PjJqf0ezREcM
+XrazedhUcziBbKrwVJ54hYsE0UExxzAPJ1aYfwDToCtI1+6+LhQm4FHVW8XFR+YIHGsdnaGq2Qf4
+UFJy4xv6ukCvByeHIQVztQEj5LpuKnY/N7M7xFiC9aa+niJ+iThwkMdjGDL4CKBM7kt07SKtOmM1
+8+DJdBApo50mAdbT/M71Jxfm+pxMhmNLKGXpMcF+qqJit9tyupnX96socRM/P7B+g6DcwFvCsJH/
+71dx9I+xjMFnp1cyKPRZixnWddkG8JJytJxBLqmBZNFy/vO2v0hfi5wtkq4N/bzo+xecy6O4xYzt
+8GliU2UGCV5BlVuJzO/BqQDtU0DupMC5wVCXLj67GQnkO7KdlNnj4Mbsniq/WMu2PDBhUVfysf4L
+b9r8V8XPbE/N3/EN6lmkHoQqEzuiQ4ZW9iNnp03Ar17/4R9LaLbuje1i86q8t7eg1CA6De361oCf
+5a7XGFvjPArwp2Iq5Luz4FslXjrBjxEc4GunTIF7jHVFcQFI3QwBmjcfD/HSHH1M3Rhy9ZyVDybB
+wOQnm0/lnFZzkMx4QzMTFG3NdqOIo9VKHZORXqMUoFzXErXmzvHJNB3ryjlJ7P4Yp6zmzF2p7KCj
+Y7+8LMMg4OS4gesNt+fzKWRRvgHaMvGg3gFu7pf+HD6qyUvKHEthnzuz7rw+enJtlXh+uxfeqyhT
+c8z0pysePhx08dQCmE21W4GL16y8NkKdTXONF9xO3HbUWARw3X4kDGCnYMuhlmheqgv4S5vHKpKv
+yB6irOToA2jq0AsCaGmxodtPwnTbdF+3z/xF1UXt79Fst9XOpqqfM/U7Sp2pW1PNxWKi1+2qpd8k
+oPXRXRzqxswLuLRgb4SxUKS0JaOWJtjg7Wd1X28Q58ScpOYC7pPTMGNFybJe3fSDPHfcVbnZRBrD
+ILwh7UEqDaAzGegvY8LTh+nWaXHIPS19tnuHrBzw0VfK9wWgWPCt+F/fX8ZWDWeHgFh1Dknlh8Fp
+gti4au7maG+nh7vGiCyYKBJyiWGiyH5a6fg5I4839PZaPodlEOfBGkxUWqRrdUJAhu68OlFtiEZ3
+FyYLj693qD/aI+6Pqg5R5R9KOnSe2uMCNOP1erecbiQ4Q7srVCtyTrjes3CEclGfQiz7wIAJPxWi
+60njvkLsRYpEKlqESBwCojeNzErAARBIjo8wHMmbrZFDb+EoI2ljUjVO6JmcfvmrAFA8EIg6zp3A
+XyF2aICztRpm6J5SrnZ3aDW0bDkvEmcnmY3QfqONfhixbh7lD0Vqn9qAdszBdkTe+MebjINWTP2V
+rU80Qynk3c0KR1QUvaRDRZtfgpjjLh7PwRiXVUdc8m2dweNmgLVSLo3djhwxjon5VrHYzjnkjUlv
+dcJ6SWzSfXYUsH7YCcQmIcBpC6ye1iTXnFEIp5gGcbm6fCD00rckuQwcO3DFcsyRyAahpJCO5fQO
+IqCFLe/R9iyaF88uhx6+Heh0KTlfWhSkOumMmwfwCrkFz1XB2x4ynrApwQ8INhQHkMVxEfCnupyL
+exRZVL00GCgKV9sAYcfU/uUZa8ss3mAytoAcyATdxkXahbA8IKvDezAxNJKcEr+a4kVapPVq4TJ5
+2BDA/oTDuvEz7JYlT0/IMCeswIs1aEFcQp7PgWCE7xOeA0fYNLUZF4JLzQmAAiy67lQNWbcMRRKS
+g7lXc2RP0Ii12dblH5oPZhHYaJtBMo0dgtuwWRFLJuPmHlG+DgiH2HHUhOnvvkaEoOsKLSeYEwSH
+6+PXoR+MnYhDvjDkD5N0g9Fx5XjBtg+QFOMsLG72Aw+b6tjlckG0P9ADR4GpJkYTj1qLYA7xwoNY
+8x6d/qGJgWYgb7ELa0zEKgp/X1QdcYmqFcuU7Tf6b9ITp8ag2uoMDkpPRK83WUGGm6rZMktiPZVk
+w10u3xlCfn4wT3KAReDwCp0flPz0C6Snk63ecwTWCAQVjTkWVQGgC0wBeZa5L2spM7FyyjbKxkhl
+sJ+upkwLzxHDxghIOBygJ4T7AGJo0F3wJlPB9AB2SDiQjdZG2otRYh5nMEa3Et60Ko+5xk7laLee
+W1lNHnolaf68cvTIK+V9nVfYe+PXsWuGgWh6Hf1yaqH8VUmWmmiR0n+aKC/LFi1leMbO1CJMZrfl
+7ANs2nrLYTbl3Dkk+XILhyRrYnSByt68HwKqm+9AdAHQJxLhwA5W+KFF2EHai7wNVVANLOAjfMD9
+dblPHG2SD8ObRzD4W/o/QmaNQ1y8C6deDiz1WwnscjkM5i3WrP4Jh7bcTde5kdtACYMaB7oBe9Sm
+J9HscAy1deFngBijHc0+QTzWFpCFGRjREPbZs8BfH9bGFIQ1/mO1zsPayYC2JFUBPXll/WRpPL5C
+4tbN36HwwJ4RmgAJa2i6vJ/uCblWcm0EIHCPND+aEEBSXjBkGyI6NXzTANQkbPupj/vIpMLDxBB2
+Ifd+S/wg0yJ/kNrlaV4qBeXvRNeH6JIaLe/WZozYuQUCCW5AmmrkIgTulpp6JIfU0IoIRCrYckAl
+eGNOb/8Okngo0uei8N2Yj4PwbhXubTPR9nFe3D/v8q52tK96O3dIdO1zZN72ymAlm+gl+hGA3O3u
+EADXVDLYIxj7AZDPulMPfXuVLw8y6NpqsMX4EpTCp4a8CdgSxW4hWey970eMOccmH34vZlW6kZTJ
+whxTkKzdprwAArm6UqA2zdWVxAKdPB996Y9D2zE0E9X1rQejuJmnZ7VddHN3Lc8vnV3S0e2c2Cv7
+nQfaSKUVRGU8gp34MqC4pAQufpbO2YM7usFF3+ow/1BP2+G9i9zE994Na3qevP7XSPTBZ3wHOXcn
+ZFWz+YKkkiRv2uXQyFCh/7MFroIYO4JtlMSEpllaF9cdAs0GywNE+GKOGWE8rE0OKFaB0z4iFsFp
+QhFgHc6YtXBjsnbkm+oTaGZ51OYG+739JIJ2BdA7st2VjvMzPjvpWlGjC0XXt9OmJGjNfb2zu5c0
+onCrXjUQD+2kaKXiyqbXcIszZbcE2cUzBuweYW1rcD5ip2vDSsi5CFsGsC9GDnXooXKBAyxPi/RF
+uLegxhDUP+9VEzdCszVWNYL54478VlEL1oSHd1AzPYTwQ2QiLA4qMUMZmpn+jZnPdb1CHC3QGdjV
+RAxXbwTX5HFllgXxzOleSfx9W6MHF7QFq/nJfZnGuw1vs5azV1tEVxUrL6KNuRUnJbiimti8TMSD
+88E5xWipIX8YrLcis9R6mx01tjNKWkF4RpMVzREvHC9IE9ga4XvIMLEpMVpbg9eaVkdA4Ksa28ci
+m/pThTCwUCk16U4NzInTEDhm7zCF7WDC72LsYBDurQxUAfwrnNuNwhTmITocX19jdG4Lmv1sL7ko
+MVq4ZiszQn2LhhE09HZL0MCUrOETWPjmgFq7Fzo5sbRBB/ZcwMpRmaVVvDjZyB7Mms/3oACe8SCZ
+gzGQFwBrIHK0pKYjsGzFJjv00o4hdymnVfSJq1GERZhgzEGRm5/DAieRbxX29WU4GMdGOtpzgphp
+9gtMaiPjEH8+ueXJMiYcNRjqvd/sri3gr3/GkLIDfzYjSPDxoOF/9RQK44m8RyV+BSICgApQJrZs
+rV6jZ2iJmNq/aQMEa1ew8Q2dhhCLES3xrSnjCypiMdMeYUbTJf1QNFRCviElgpshe3myk0SginRX
+6QOpuktVNK/z4BtIxqjmEPm5SQJf9pTyMSGqhEFrWqYxry58/VNxGQfqVHIN9g2GCnqzDbUD6JRv
+0HCX9Mg2pTu14zxz8XFWhdZZY2QVAZ0qgOaiuhweucaREizs1gJ4uGEULaKjFHGy4XRO0UD+3ZPl
+8Wp+pnY8sV31JBACc+cKMMRYByV3FigiTlFIRHzUSDr0UAbd0d0hw+ljeAdmjW9rRDZXmOoiPchX
+FpRzE+OCVMvMwoPm15uqxqS/bnOY0cJUGznInIuEp75j+zwbYSh9wX8wgiXzHzTWYOSHjEHvNU8C
+xbNz71BgXQoA96VBFgZ7BFt1gJPUOGIS4QHABX6zZ5xoAI9H/4XonLPBMS29VPOxO5clWv0G+UoF
+s2KOfs61sN5tDIdFWZ0EbR8EAS/OkC8D3PBX2VU1v0KZUASPjE3P1dwmLbDiSTgoJDMQfp1YoLID
+XKOIB3maccE4aUSYAcDndS5lxPZ2A6llcWaurjxh1Fyrg0t8eMwz97EGCEHPB17mjn6n74GF8qhD
+10w73XkWoaRGSLsFfN5xpTyhcjkpIEoLWkEiwGhSSA0h1CI+CUeCdirbilU1JdDuo1PTsCWcRxRb
+KMFlP6G1atM0oUkA8/E53qiqzznBWKDEqubu1IpOxy6tu6mIZ3qmG7TtAGtyysAWa4xn2GBlYUpN
+mOL6NnJesEa7znC29wdWMZYfUQ47/gwG0pjgbIaYX6ZX15bfUFLPHYvLINdm+WJZT7eIDQRufpsi
+IQDwIGQS5Jsv7Bgun8Bay9cVRwXb+G1yfZ3AwVOGWpMC1yu8VApUllYmBdiusoClsmLdb6ZrwYjW
+zernuSjaJroDxJVnkohf2DppyGm+QU9c3AES526TypllXUMs0izg0PhJMthMp95DQkZ6k0j5gfdd
+VwHVjRUqgbeNdqexTffH49Cwc0HDHV2Df065ZODbzRZyPl5mT7APTONZBM1ZeDPpnuNsm3I9zPpP
+Bexse08zUdUjyTT2+01F3qson5eb6xozVzlYJsoB3+dX0hIDiqT9JyhZkE1M4W1aUY7A4XAXaSzH
+IQ6JqDG1AwY8k20z5AmIALt0fXVUhZeKZN/JIH5X0qlVodqFRjlbYsoTM9Qln9a5KzkiBT4tsRqv
+zJNsTkxqq6qBu5b5wC7ZPOhEYaV11UoQmxn2sR3ZBXDPxProPgmBhexOBE8Zq0+2qyHgVXBm3HHk
+PY/J3lR0L3gLlh48A7XfxS9FZ53k3IwkqZMcCjNLYdtt7zEDaQL407wxuwxYqtlpFjdfVDjIJR83
+cH/mbyviJsKpCVTtYPrjjfnrs+wZ5TmgeQH4qrMEfFUKgkLa+Cp7lhZ/6HbZf9xkJyc8Zjv9siDH
+iFHUDlfthTOoSg2zm01Zhplcf8YeokxD8S4wzycT1Cp42gTzOBZZJeO2ecmZzPs/rrpIoU9h+E8k
+OzMmeu2aH6/i4wZiiaE3VrpakoZ5N58+TGxE83E8WZK40c2RVbnw5LDc5Oe4xI9dRcehig9GnHfr
+WFb0PNxG7UUKjq4Ch4xlRwkoR7gwAPTqclvn3rjsQMLXWmIwpDh+PIf5WKwEU/HJqfl4B5/MW5bS
+NbDtlCaHHuWv2SfRxk1wPmnIysLpWJztlc8OVGRPycHx2szQh6cqx5+5v3Fvv43aJu4H+UdR+J5m
+HGPADijQAKYnuTdv+cpobqKks+WcPM9H/xpNItf1J7Pt4C4OeRsp3Z+614AdYioZR1DNy4fveOzE
+9q+++or8KHku/rdyU7+qPlVNkKgb/jcajeCf06fPqP53CPdAmd9YCTB1Xueo8CY316m5w55clyes
+wiAEuXAUbQMYSnno2O2dX3twJDC2r6i9OjEq0IleV9sNKBPsACX/CykrwuGgETt/KMZCaadPH/RM
+HDn2BeQD7hz00e08nB3z+S+ACDZzgBBoxGpfoVmTcDyYlZBTDHvgzo9fi/4if6YzgrZ9kSgUJhMb
+BXVbzSn5sfUyMVs/2h8wWD9zcgCZY5FPMHXuNCisyrK8mwEiSbO7Jm8A610s3EELfI9sBpxm/PSp
+IZjr3exDSVlwbtcffvWc0+I8rZpmVz49/bf/hh/QfDmupe89NvfxaLetlsJtk1ntYcfGDKPnmzua
+yPvrB+xd4NujBhRqv2+6adDNvtnqPT5DPOmzzPMgjAFuqRhUVR9Njv1hKvng0MbHo8UET5WG9NNe
+GXHskURYISIMc1bqjk14pKnwm273BQzCKt+hwRw/qUDI4WoZCnHqUIMtM+Hvlw7JlwewN+tZkfCJ
+n1fz1eA8uysNI7KlQSiTsWZNDWGnGEdFrvO/CZqRGzzFrpmJr/eGk5pzovSYEXsxRjSQdIbsAnby
+RRP2VGaaaZ9Z9LPBsxOuoOr8/PsfIILrgSxqeBJdkS+MLHBGlPDgHM5oAAIie+kpx4JAUGgO8gUa
+eU2Dua1BNzB43OSPN4+bYmBEDR2NgTElIMViTAn6HlNcyjD7wGn6tELy1dtX2bffnWc/vHj77rXL
+eOBv4UNO5fEWD9yOYq56lqUlEVvF4X3hrUt1DQCUG+477MjVsnEyq/LeFE4uXRqpgdvwunxQX/vF
+dq267TxQJAR8DZeepFq2czFSn2Yjf3IzjCgJTyMHS+7VIRNaeilANjXSKR1C06aaWTgf67cHxGoK
+Tea7u7u9Dj/w8SzCUFL+trem9jDr9HZDQdb1BzVgusiRw4gNS3LIE4chjrlkUxEIdNhKKkWk7xcI
+qKqoyLI3+QQ1a1xODqgjOx4pmAJnrhickwtz9B1N2tABb4oLNOqhIic9L3bZhi3LAP2h8XiOwaT1
+rN3Us01nF/njNeF5y9mMEQOb3U/xq8ZtYBtcuteLgbRZV50H9zJYLzDcODwBEJx/+lORhtvGUjKl
+NjZH+18DO+X3bZjePBQp1g7s3d7bz0ArpmkOI6pagYslWuvY5U2tyNC6SxYHfDZbXDVtvMHBNHSS
+4IPjhUllkgA4DKMBG233LuC2RMmlPpVWR9PvUlQwiZJbRJuZzzmOxp4JvVavEN4R1jfBPkMCbfFn
+F0ajUHZT9kSb7svOFTmW9FsQ052Pvm7bj5npAqtrDeRyI3ehe+ZXHMAX+248MuVGE8m/64CXil6H
+LzbSTuiHHWcHGliYFkkU1Jn/h2JqNdhYDJuSBqfiKGCLKOxIn/GEzV4BK9RFv/ACM/y07HClASXu
+yWkyxphS2VSXR+cwUumL4mmcuESL0Uzm5J4OXhPkuIZ3DAp25ek1i3nyfPScQftk1WmWm6Q7uwaT
+jfjA4exMqRhha+NwMBs7xBdP+eizdqDTH9rHFEqB77uEnm7+GCu8GzjrETu/VYtw/c02RjsIq3BW
+GUaz+A7Z0d2Eypz5DCkZCPM5Qc+g4upMNqMSzVhILJtupkjJps2HChLKA1ILDtn5h6AbllXvPYb4
+iczqP3udbnYjuaQM1ZiUKjotCNG6qDu+jpIN1tBI7R+tTIcqzCPi8XLLAOA6jLXoL+2/lAyJalwF
++rOzhsB+SBX+u7MOilZSAf5oK+1vugGdRQIwYJrorITNR7VaUHE/lyD9XH9upVZl60oJygIDVdkZ
+0NXNKXobXwi5JrzMfWQ5lxrO0AuqbJ4Dd4UjkWVQEpHBNqJeX/QZTxekv7xP9mq471uYXa8wXo76
+NjouauOJacOIZP1hUE+UWnFVaRFq2lLDLKhvnYGj+qplaMIWNJ8g0m2f7TRYz2byQ+xRurjM65m+
+tEBZSXyOdfIwuhwdL935l3G6ScsAvNyD7F6fypvIjly2HvoRqa8j4RseXLaCR6E+KJZgyPThU3EO
+RkVUcVqngAp43Al2MRcbBmh3EqxOPpppjbyui9ZMifzZkiaR/qsNgp6NyZtvF6Tny2kH79sv7JlP
+YB/Wl49yPuGpWscufiNR6/sSA8YWNSrtNhzSXCR077cmJwAqN6clYVSZy9jVVeQSiFkNpw3JY9Cm
+jAdClXS4vnhnL/cJIMzghh+l7lbATPaVlw47habn3gK75G/FMQ1St1UbWqnSY+tKTs4Yu0mvxQkT
+da0y5ebndYliXBSsFV7rQmQb0/g7DBwgu8swQ0/KReYxA+RKlq0hmjgyxECwshEIifADL2uQ/9X2
+cXgllouJgw2N05GHCvrW23RLFvIjog8PBB1iHXRzS+BaBBfqaHSdoZC+wsD/huO0CjSvePFUdQUm
+1bmBRX2acwExAi8u224bqzpmy8BGlCCuXL8xIWlObt6AtGMxv4WEiSO2xc2CUIol7OWGWah/j1sZ
+ZuLWyQ/KLNr8spILD0TpPEd8kQcOHt8zKwG0TikzIKs2GUFcTL/hpazfEvdO6ahg+D/c4WFzhjWu
+pqZTjB2Dc+jDqr7HY2iKOefBkP00CJTrpf2eIkoUpOTAP61TxWQnx6e0ogUgQHubcdVL3wlN3auC
+6a3u7nZb/FQCjgdPSoi+h8ixcrYppw1HjZYPXkzBg7e6+MRf12dFdpKdHlhYOPTyE2rvq8x3bGtC
+51iSHPjo/drcM3drkh686SraOIieGv97RGBR00iOtm37k7TAqR3K+Yb4AIbwbz6yjdRQzyoMVWQz
+tDtj/Hu0tzcVZ+Eoch6TLzMWh/U9MDgvTIUHVi20+EBiApx1LtwQuzpujFYPHYyPpelCpQNNIgOQ
+dJWD/8Z1yXeoe9zjUZwH7lrek+U8SPnsJdSbpM5DAU0NcuxRZjdTOXljdQn3WlFaWvDL4eNsGnT/
+++BTSOw49vMeQajJlgK1d2t0KaBUE+DBIK4HUmR0bv7z0kh1b47AgkuvKqbFs4LhkXdRZ8bVpofq
+DlrPPfVEcYCk0ymUEPuaFJdeboufQy9tHx5Ri87eeGAfNjbzeYJFYH6cZt+A6IsQeToQmj+HiMKO
+2GF6Hzd2GkAbncoVNDVAefeUc7fpaCwJRlWSCGYqbx0SvpUW20YjXv/pJSZAAiwhluajZkBiDHTg
+4AJ82s0dRhQ29m+/W1PSvXJYuZaWyIOKXdqmiy3G07vtYXgKAykAr+cMdi0XNOinam49zaONyvN3
+PbiT7JodSilIDQ5fvrmdziGoCDzvlCs0qzVncPOIRGs9G/YXIz2dpeXArhnkmj4mGF1bfqnvLXIb
+1brqpB3mUQtGHOEeU2YoiaxPJsFhpINmC6AJdpwIu5E5oSGIQyInoSXfSvPwpjFUF8wuG5lrIiVk
++4HhbZTrASV7Ux8In/z4TK0F93/G/6pFnEIEI21twdfDP0J8FAp05JcUiAiy4DLkqy700LkinfvU
+aYTzxW4pwaMUSSmufGh2nArTYZ7joFVWEC6X6ixCdKCaEFQ5Xu/HKEmMr1wA0ubD6Bvzn1ekz6k3
+V6lcSCDwMllNbdDv1RU7aVAr37745nU+Go2Kq6t0DGV0rsaM8IIGiw2KTBp8+TFHbBjCxwupDDxQ
+osR3vNTNTbDO4oocy9XOX5KwbMxlGq5QAfN1afbCG09CUneQdDQUxVpi84JiJHonJRRFgSZA1Ouk
+Lurrt/1hrDsoQjw7h1faFm9KWAo6QNVTnCTCWfVrfRMR5U3yzqrQMCFH33zibGWclMnlFhJfF+Te
+Tp2ECYUhdXcCAsnzAviBTlFSRsIhJfyWPcdxU1xdYa9XV9m/si1dXckQzGOK34SHOBDQLhpuf3Ul
+wzAP5mDOuoNoCozq1uem15QT3Dgmmo9bQcZpdtcNHKkr9n4wW1U1JOO8p5yyJe1sPojpw8wwfw8U
+bu2zXyJ7qs1xvlKhI7jCGPB+deUtQwFf11iHc1GJwr15CUfUNPMRAoGXRSpeCgcob6oGhIipY+YS
+x62+SUEDuKMA2ZDPCWUSx64XM7Sy+kT++GbNP1X1rjFDJYQgOyEBRA68BH66qk9shL6LdIAJpQbb
+6pN/rnU7J1wlAKMy0u7VlbR0dTWEmQV+TT+Jdq+ufITxDS4qnotm3kEDPaP+EWfBrAv8XlaLcraf
+LS1sT8vQhBzHIBNSmH0Fno6gGJe2zGtoJVdodiLidELkaNFGcphnA6IZpJ+kxpoDKlUxgs4lqe++
+nH7YlIvfKNB0UwJG2C6ipEQOxw8Kv6kgOboaRvuxBi5dZ1T9QsZzJKbqQUdOLT5KTlalm4xlTf88
+QrW7lz427wPAhSFEBlUg28kUwAHYyNRPquT6lg2Sv4Gq4BtlWiFwchmxMk4VB2eDzLbxdIdWebuC
+bgkS4KgqNVK3xxah2FveknaMmpfL1mX3AtokbRXEmrf4bh24hfiCMt/0rDMgB7l5Z2ebYhoOvFeE
+hYUXqA3cK0qUPaHkPMGZmecp9voCcU3cgQHZOWFCQU1aIvCKvaBdl9sty81Ea2RJD0QWwa4zZyuI
++ahr3WZkqqtW693WYaPwNTJEjXPOOAIPyJmk0XaJGGIIAEhRZNMVDsN2z4B/ft4z1G93BZeZj7LT
+V2H0IPbTOrbsup7vjxSWvdt8JDEdx148P4g4UEFHaltWGdg3rAgWdBgLta2SIQTeMo/ot6dYAl+v
+iIF1GI4kDFyFVXdNZrNbbj33I71XUm3ENkItrlKDqQUL3uBWXqYuQv7XrOt1HliaEttZDXScNimM
+pgiumKQlVYoFOB5sT+c7wDxEzk6vzLqwrcmibE3lYBQ2twUdPgZshWwl27odrMcSRyJW3gNt6Lrv
+3K0xCnxlOO8aT8ZCvUK0FeWSpL5k4BhjO82I7RwvrNZXzkKut22M3L+pDtW9tPgst7n4C8jOz5qa
+Ie4QM9GE+VroRYTNp5VGGhaJ0BAZ44+xFgVmUefYAjzHLeI5UVmJ1LeX4dalFRO9Wlj/ApCeaoUe
+6E95BP6d5IC5sMBhoCv4vFkXR0s7ml86oPGJQj0cp/1vLPThhddKC8BiWv74hxMKH8HU06mF1hIX
+cQcR4YvdMqoBPpLKlIt+1nuX/7H4M+VOoKODkqfCrzogew7bmgD6X34C4UY8xX9cEXJDp6jq25/5
+IcAdULAdTk7x86TYaHf3sfm+LF6KJ7NYSPvYzGC9EbxZf389ynK4LE1N6X0DHtjmo6UyVLgrZ7fT
+VTVrsqeZuSNOV7v1ERnqAgnVYUig3n7otHtFp4sJtGPmtbOpiLdiINbuOtZJqVOjGfMlEdSV83Ld
+/Kb9zP2MsbhuOw6Xvp6c/tAbnXpTeP4HKBi4vLWKpQLr6/n3HdUiu6TnTPtnvrXfjG23mtd5920h
+3sqBqlE2fgAA5sPLxHJMIGFSJzHmSLt/uPYM5+qBg3jKnB3AOWmonkUToewiHCpDecDcT7cMtJJ/
+oRA+5JmMwm8G58fihKED+pim9nHTwlnW8plDmRjlkI4RwnHCPOjFlwp9F6UOY9OZNjYdZeD2U2S7
+VsQTr70RDWOWaIC8HvzqDz/HLYE/8KH78s4je0hDF7NKOD1h/PI4f4A2s3ivHVtwtwKXqpXPyql7
+ztKIh0zhxRRgGtY2V/P+r30nXNymjzdf2UyXxJLZYTdxMIcB1OSnG2kB4OhWEBrzarEo0bsuKulc
+y8h0T640gPXIx3aWl6ObkXn2TqzZq5J111PllyP+cOhVS1JV5qhR3APou5yTjgKmZnwidlUPBLgQ
+pNqDtC6cP7oVsNibkKWAVXmvd56QiG7RFsm+8l/olorAlVpbidRvtTYz1OQD9W/EVMEnQWkznWS5
+ZFcEwNIVYCTOC2ewSrgnW1GH20K7VDKdh7u5hdc1fO2F8u18nYrTz4rvJyYCUwno3MtAijCjgbte
+c+M2BrFu2Bzh1theJ44vcxAjdtWZvGbu7foRf1T9HaFb16Vf3BzGWzgBAJqQIHqyh3H2wPhb0Rcr
+Dk8fJN+muRG8aeVvMkj892J8cnrJlzX0tZC9yMbMVVYyelC5HTQZJgBebQ9F9T5C1ds2dNZo9AVx
+wREVbIzOUod/Q6nQ00d7MiUjLsswm6jzGU481Dvju5Z6vLR5H/2JHrM8QdhsWe4P5MlpcJIzPrng
+mjlAUxLvx8k7EZLuqhxtGM8shi+XITnss2R2dmxlya1omL2BIfFBi+L5elNOP/QSNJNAGbYG43CX
+pbJ4KjxPbwuw460/6TFwZRzu7suLCSTL9gB4IyPpbIFQFxmxC/Z1zQxbBlwk55xbTs9thDMZp6yj
+rdt3sP8EkVkbuRsJTrPJYVz1yRncIdX8CYcYM5qgg3OxZYr2duA8Hgh8xsmJhVa82GKUx/b2coAL
+Alf8DHGxDSfr96L4uOj8+QE4q795hsI78XgYegdCx0mGLQmSKvzRkXDK7GAhHYuRp7pFhiZxJLF1
+Awfk2D//CkBNXBOmiPorPKmWpVVR0s+wgB0glvEh/TrOS/vt23rLk8Jfv73Xsb8WCDGhbGdS8RZg
+qIAP9VakWbAXNp6UNOgivbR8zW/Ia0ZNXDsQpIflmAKCTI05BhG1zUikr7X2LrWpV60BsnmfIL9h
+5D8PnYX9Kn1A0orQIRAbf0ViBqOyoQ/dHN+wO4gDeUbbEPbIlrJXlKZABUwsMDCmKRVggUprYLMH
+gN0JZW0s3NN2Mj/5DQ8UVe38la8MXXFAPX8A2fOJ6MxVF9wQdjP82tZxgteAdm5rXPLZE6c9Ikfu
+LXjzU3gdounwOBAKz7oiwz0APxTMDuh4CEcN4kWeINJBz7rLtbRh3hD+v1jc0BHHwvdAc426dACX
+MzTxCbNkLUoVbEjeUQr/n7su23q+rZfzxiMEsiRamlEpBl9JkMmmXJafwLWPAh0Bkbqa7ZbTjTZU
+vlhlDH9tU0vZRitqB7BN7q4RMbL6QPZHxik8gbonopYH10Kuym8hIYN5eoLOcHM12mUdZ+UwS2r2
+9W7tMkZ5av0T3X4m/tBT8dF+ilTv0D/Np5dLrug7Sdp01Pj2nXVdQk9e6lRHrqWXDCmpvlsDaiNP
+En0PRbiJz4sdLzgt6Uxx8FLmXQoR1k01yspRVNH5EivoGEVg6OSEwgKPh0NRvdEjrjx99vs1HcM4
+NycqO1lDTp7eR0PYqdtn86Gjf2wLPTSXeDDwd1ebkJCD4FQQwcxVwHQDUgxjVPDCTCbEFhNekGeJ
+hy1l4YhPlocXrRGyPl59qIt2OOot2SVFB5jKMpmIuYyygzdluVovdzdmtlvyfgMjKDeGK0DRljLU
+EaiOU32QfD0xDGPC21N8NS/yvvhkOkx5007eVzuvXxQ6gaT+3hENXRTb4kkn+mlYXnrXV6YFNygd
+fsoRrWbwnnNJgBFFiPIUMY6JQNW6sUOWK2AVncWRDg+pMV0c71flGfkCfzQaVX9VO4ynGNZp2RxA
+dIKLmsT/nR4Dg6QreNHRyhrOTrte3ljWJNjqXc72OsmcK6dZt3MKpnY96oqCUIlHSpPSup5Y3Xbr
+hAXtqDoj1MY/8Ur48GZoCj4UiOwFOOO14HlHXgQul+tOfxbUWXBxLkKnJt5IATdW2Vv8cR85hODr
+iiN28wW7w6Vi0n3fEAdC+egRWdNQqgU0I8mK5TyQ8VZZgUhczTJzIkG6K5RS+EyRdIqlbVB8lu9L
+jn7AqAfKvopYkOWyvo+qY/cuJS6DKiG/mwijK+eCs4DPfYMIPXMWK8XqUzwogtuN+upLP4l0JR0+
+XesIUZ5aMewRbjKaPf75sEvw3ZgUA+VrncABJhbtFet9CvPNfsp6NK82aEQrGHzeMw6TaiCpYQH7
+6BrDnZ7202oW20mQmGWtcrGEUBb63kQTF6c1iRYYszQxUUjcnYqFMWuEt8aQvCzxMVl5OX1w9q2o
+kDyAwTZEJXL/Du1oMUmB9K1tJO59h1gEtSShjmYzK0GEi41sgDSl6rJBfIiD+SA9mB/aEkoqvkVY
+UpIIpTVum7VIO4k8I0gCikQ5l0syHRq9S1NVxenBuL45WU7T1Fc+bM2VZ2Pp76IaV09O0+67MEIp
+D1c9+weHvPTHbUQueQe8FCOpaRUzgp1E7SkAOb8yvNh4K+FH/2nPH3BbeobaikBg9rrEnDM+9nO5
+P3NGjDSuwsMlJPIZxakthbpUFyn5UQ5fz5+Rj0PS2uJR6iHg0TU1vOKpq1KTWQnpJojWihEfePYa
+7xpoRPkRujWbk0nOJMD8xyx1ug32aPDVRPv76X5o09XafRbMnbeka0yLLOchxW6Yz9ygw/KmBKVu
+RVlf53XZZAJMqj30oKcTgcD0UCWmN3Cbh92J6anVh2sfIamKLkGgWYcfdkZJb0ERb1DzKTpjgo+3
+ZN1WFwmNAWMXMQR/0fMvQo92yfX4WIz1gSHw5eamJLg4TLI8bkv/a4scyv+bGlR6M6dKquR0yrKH
+g0xH1nXeQ8GEt8Sb5YljW/e3YNOSV7880+gg3liCyXCNtVZITV4q5q99XpSXN+Vcft6aKOwgP0xg
+x7TlMksDwSTm9xAMTDsqS/vVL+0KdfC7I8rQrmtFizjefbHphUKL5FlFoAqRBURxq8GJ/LWWEh2J
+RZ0xzhZuhdzppc1tafukJgmAIKokb1BKBQXRjjYwo3dgQdqMfL67PLnpHl5x+9nKrTpPZF3jBocW
+Gw5tG59xvaSAn9B3uujFAqoobyGJXbXYkyGV1hx/e4doAy6kEPnpYQmQe6cXX9xcjC+JjUuxCUkZ
+GEbcDEnrNTR8C7P6hMNiKN2JjXlyAxqi5BQg4MWJSZpTMP8j0k8Ik3003Ir2ntVxtpU7DUmAkphW
+tOns72rGv4PzGAbrBwUZ+cjPrqpt3Qga2Jzy+gdWsPAjRazkejIvIx9dmywLP6bZqO1KsOHPWpuh
+Ep/Bjo+Y5+gCqvR+JzA432sfRyBpDsKxF2EjOgcrxmhqQgbHdRF4s9xHZyIr7BDWb5XdVjcQ4gWQ
+H0W4hjrjoqxiLqNV6RimdwXD9cfMpBWiApGeHc5GnuvmAo+XABwOFMeIHxZ7HYCzSDefIiaId8tN
+aQQ7c5PLl0WbNLPS8UbB7drdIif1ZkKw4CjMcXS9gCpx7Mm4F93m2kdqteh8+eIeOjQZLTVGulak
+U5BCgRAKWJq2OXtT9TT7nSqhRHnUMNgnxZH3Ztn75pRQlf2+6ZNFY2tLCX3GKMms6pb0bnncZOue
+f5SwcTEmSWgiyth6lJt/ES4A4dzDpE8oY5RZX9Qt3HyfzIfzwwySEVcw9cuIAUy4kWTud2cRuK7N
+4fMWDN+b3XrbEhydqtuSikk4z11pTesko5APBCk9xfExRxPqwsjfHyTRGb8qEo1aTSjh5KNZkTUx
+0Xq0z5CDs9c+YfS2VexiYgnVg5Yd0SoXnynG2zEZtjLdLcWYQY0F2C5afy+pClx2dzWEy8DCEqcV
+p5aHIjXarEAhpI++g99Us0wSkZHaYDLhzWaI/M4cH6ygBhz6HTgn329q5SYUbx1roj5uz6VNRSqd
+yaG1aY/ndf4InkpQWAdwkaNkUgboYfUS/8Uy7lEN2KNCfhQtF4s0Rqo5VpmQ+BS9uEw20BUO7O2H
+EbPlcbdCLun8B9fdVkVmp87TJq2WZdAvtbd/cOUNnLMjvW5HUHcr7uxnBpHzjdSzWcaEy6VQtcxk
+2uqt2dgP0ZrsoHgY8Nwkvv4zruFJNXOcPTymCsw5otr1YPS84LEIBy52T0yKe4rE/1/u3nTJjexK
+E6x/bYZum26zsbGxml8uRHEAkAjnkpoqWZSQKorJTNGUSdLIoJaOjIIQgEcEFAgAhAOMgFTqB5jf
+8xbzZvMUc9Z7z10cACn1Yp0mMRzud1/OPfcs33ETbVf5zK9t50fmka2q28Wn6hA4PzLg8yyPaQBj
+L8Q2uNkzeVZyhd2MT5tZSd7lpeHWEFrmAZWyvidIK0dwYVspSnwidN3pyuCkGKSJ6TsNhb+ts0qd
+SVpMyxpZ2wa87LC2MDXXDIn4ITIf5XiSgTvcIQ4WgZ9x5hO7UAcOJ5wF43sbD5dYu4b3Tbn3162s
+2YJDW8Vr6VMsLyAKtvGHWDIMckYNVIiryNcZ1UIgB4ljrU6RQkd5bPHPgL2MCtm1+Xj/xN4nLLGN
+ikljhBqAbK2KQSDihN1eEg5oXqH/NIY1XrByCu3hEB0Fg0RYjUXW6zVHM8TftXfQOKteXCE7xXLJ
+f0dkHIkxlOBM4MCpCyvPgrLHxoDoLo0WRpem6k7vTcFqi2KYUu4zSXzuXZESgDlJ0kuCzumy2wUj
+QnOjJSsjmo33moZE8tcYW1p0g8qhLJC0SnW1F+hyoNaGMFebCO7oqIib5zROFJvrbrG6cSqzNjaj
+DcUiy1tH5YxquaCgchjNQtKC2TrkdrS9qLI8g7gWQfpqNMF1K/gVkZjpIMFZUvt+iX0w4oTA7AKz
+0Nj3mnS/NudPzGQ1i/nDusyvku4XcFDF7e/9TcRvbnmaKrvpcgx3doAske7ZFOsmxLn5bDdVtE+n
+0D4K4jBgZ9XIbaYIgHdDgCt/nEicLn+kGIdFNl8ilQsvcIT0L5fbTl18Gq28qdmRuW+p19m05oC2
+obvZqhrNjPtoIIRgoq82hjYlhqAb3q3wGJkMh+1gaILy7M/SZNHY5+YsTu70wTnte8HQs74b/uR+
+0nJbyTTiJ75X2bIfsTbR2hBKF5eiQEYrQmBeeyn2VdjBVmSvGDneu9jJ8Hs1usNH34uext8Wtjk2
+a+QmURjHoSbpNN5WMzmHLhsFtKZFRbFh5SgGFstUjSOiP3suUL1PkuwFviRp58/8+J4cm2znQfyl
+5jznGEy5GM2u4N60vr5lrIwF20IQ1CYGMcgiSIsyDQMw17zHmrU+06v5YkUhhoE4eDsTWc3qQ4+8
+59eD4quky1QKj111Rz+8RHQxm0Rv6tl0DM0nQYegMLmjhNw1KVazlHpileuUXAQKnmAwUys4uNoT
+L+2nPoU8QNwAjdOB+8dWE4kA0nbbxDZsvE2u+xYXkg7GnubMd7RCR1g5V8a9bmZGtMo0PVk+3UWj
+jG9oCHHX0kMcH8mlIMl43PgwnUx8ZuG5r49cC8+CETs5P1St6hqUrt+WGYWn+Ya42k+C6s/7ptwD
+GhLV/OhpovSnJjxyw9JKp8tslR0NbdytWqevT0fY1RkdtQftHH93d7Al7MyE9KovWjQiYH1jsXax
+WowmDhKCFHf+Wi9nsiMqPy++IjmrPT0C5nBcZ7XGe1gpaa+QHUvFBoPiSUpZiEbdEw26Z4Wv3JzV
+jZnRSRQLm8arcWkgLYECQkXpPRAJUuZ66LAQUEUa9/SEZNjkfpVv5nnO3EPkHdm2p14QdQP2mm1f
+ypeKFjissV+YaBxZm2HM5gbtM5UOruOB1jg7cM9o4Ii9+x9s3ByKsJUImlFLZd+NVyRnCysCIN4Y
+szrNfoDAzhrWzvLXpJk9O/IV7V8V8OO/4cI4SlbGV3pvyK+Io89eEkdftiaODhg2i6Wh0CTCdB/t
+H76jneN3dNgAqpmrJmjx2XGPohNGZ/bhxLlavI0YVj2ryUY9DSbLXugjTy5MiLerrGo49myQ5mKe
+1sffffj3cMEYzhZXJfz/4+9P/93//nd/h2cP8sLjAt5dkTGslDWaoagNhbgTYalXQHjH1eoxDFyN
+eCEwhdcVujG38NI5vYWzjsCKyXvm+dtXJ0WXJSMIZUxQweiNivWg2G/7C2PiAi9hkL6nT3l4QnTS
+GUD7sfnvT7958+G034BPfbG5OiQhCg/hNBqEBgWYi9z92tfVbLZAVIq7xWo2aYdJJHMmVb5L1Hp5
+dgCUAwwk0sBFHdyNqB84n6KAX277GGZK1Q4/cASPLivzm8EoNEyJwLNFMmL9Cl1zgZ1iWbj4zRlT
+TQp3NF83iUkU+QMBher1ykNsBFpCVv82lXH2oD4vSKTSPpHiggaH6GL1ullqw7oBrgy9KdQ/lXrQ
+c2GA38p2CAc0Ca0Bk+52Dm4KMcirKV6nRFVR0SZtDa8xobA7Hd1tHYf36Zz9MbDxFB3Q1ICiXk8W
+m3XfSDGA2VwxwAjiiKzHZfEBNzS5XqA9O4KVb4u327fb46fl08hpWpYMTKc+sQk+MJuLO0EmGG/q
+9eJWUN1aQr1pxJ85OhH61TauN3lCP4FqJUZXKMkLTa2UEPp8HULiiHGDzEplOYK+UIS02H9q19Ke
+XoatyxuYhEmcNcgweJ+v1eUJ0x4uaRRSoauyeFCTgDHcDK6PwWZw5h9qNRHqb6HvnWGHTDbhw8n+
+gN6hdsEtflX9DGn/SG1m2B8VbO0QTIwFHBVmQMrLBfmmD7ZreC9y/XoYETTcq3cr4CQw0pUscNUr
+LDFO3QrRBwpdxt26F7iIBfqsYNpQgOdzRQNvpexYQqMU34vqlXSHRTn8TCFIv+b3P1ATGsh7Ezlv
+2quIRIbmnbtIZVKGFY1whD9TCEmu19XehpQI0ruKoQbSZJvlhIqmQoOGBzPg6UyTg6AbAecW5KNf
+OdLRijQ1Ag95OUWVFCS/XVBczilH1XVFAom9G81uCL/J+WyhyVxYHDoDUyxPwrYTeYKfblaNrTh8
+YNTWUY4QFRRmFvsHJL97KRj1WAXh7DDFECLVy0ZoIMEj2daO5rAA8TbkxrFfPOkXx08PsaDYuVzO
+XGC0k+n5eYN1Y8M1LbkD7V6YaGTckQ53+o4+63ezfurG9dN3ox+tJAaZd1PDZhz40kxiHNVxjvA6
+qJAmwoPHVHDmGFs/Xz3wLvuOOjjvEQeDj9Dk3OuFkLWZA9XRmB2Hqit2mJyWOVtFs4yxidnwzqfb
+pWLG4gXuwUqJowsjhW4KmJ0YPVdkL4zhqzNgKCv7sC7WNiStMxjOzGfm4qWpYHjo0Og0BiDy3cgD
+s6MS0MEK8BxpWwoy7ppVx2hdS5101fbiMJWOYH87tZ3YQzDdbjtnL256ybfYeDt0fcBAjV0rSQo/
+GJ4DtWcoM6JFlwPPdChRxx+fcC0pmTctaSyR66faHhGcGjUn5ZygwcEZ1xUlqd2rjbs0W2K5J6sr
+X84vc3I1lmeTtoIzNITNzRfgE7daR62j4oU0pYZfzn5sVqWXDrxuujVBalSOz4arqUvLqafYXrvM
+yMyiFnG0rv9Lv/A9AZM0Zp8LnCFpDu32wewo8OmkSPmEpnnZyLalYSsbmDYcAkteffnRKgNWk9dZ
+5lrhM6E2dbapr7Mh27hY+t51HNhbhI3YPTNkh4LjwH5O1K6ab3qYe7eJn+L+sVSKjfUyUoFJNRtt
+q8mQwx5KsuJig5BwPnZKbPzFheLVPUIIdt0VAz0cRf0ZT6arBO3/9DkWZYXtyw0uDhAtXHtPcS8j
+XvTWBsyRXuDYdkYdXISdu45nZ9CxYumM7f2I3mZDOPzXWpiZYIEo0sMK27094/FFixtriyZo/5rG
+HrPkKToIwsXsl7BQdST8EaGHV82EHit5+e7d51UCR8fhp4nAwG9R9ri/BooCRGmLyai6Xcy9QCSz
+K+FoQxuErajrIwwe/ZgVF5isNP7fv/lu+Or1t28iK1WfSh//9isS2CIYwZK7LX+6QfXEd9KowoAi
+bzvELwQF8vKHl+++K55///LdafHi3avTAmaz+O3zd69fvf6ueP3m9NWLlwX2q/jm5S8/fOcQ6rmh
+XMygaGPvESiVXqS6ThUF8Cz2OVnfydWDDshX4Zj2qEPJouzjf/7wnzRcNP+pVh/PTv+fIUnICTZi
+RICUF1s9uHtwz1uSoJWcZwUwXDGJKWyYPCsoD68jI53lmvQNtL1fLGr9ieY/Y/drVemTGA3pT/IK
+Z++rOd0G1f9KfvI3HwobtSKcQAIR9IuXv3t1Onzza07pGWRNR8zbMCxnjKYQ8v1Xi8XNOyTpYk7D
+jnOjyWRBXmVdcrNUNuxqtdgsWZNfM7tDb7rt5XY2vRCqRa9KX0Ln+Hi+OF4vFrP6eDE/Rr1ZaNo0
+Io3FoE1ItcP1aoMxhSZo0N4G0of5FnPM1XZ3vszhiVjRg27bgYtQPlR9vH1++itrw3m1YOkAhejF
+ARvfEu55Kc3vBQPhQZUCOKUjiZNODlceXiyEwy2LNxjPcT26qfztn4W07MOlEzK83Mwo9Avrk3SJ
+OSPyYCtl88gueQ3HYbRB4uR4htaM5zW6ICWmhgJRRC9FUm4vxm1zbckUFL9ykFjtf8BxpRAqCAyO
+oF3BqDq/TCmhG9pTC4/9lr49X125z45V0y+NepDUQLsh1IOVOSFo2wqjzE+c3ABfmUJsCiiEN49k
+wG/lcGkMdGxqduIZ8k9YgZIc/0WKEBu7ZgNGB+WxJbsvMJGo2tSex0UX6xewWhtHjlkqwnqr0/tE
+h1AxO2ovwskitmY4mY6hPBXuSVENidCBoIOvkquFcbHcL0mfeAG1FBxZeKF9/+RMmn+eSuD9yBQP
+Vt2HDx+sej4gzZAHZeIWoJ34xpEM4NUSjj34ijTV/o7NmzHQTGDowWXo9NaR4Ddea34t81pL9NPm
+CuhS9YsuSjFV5NOLPdwlGbbL/QgtUfQ1rhSXJML/lGuqppR1FXUvlJ3QDPDo43xl0GuGZo8mYVp9
+qAe2Ncb6PsHsu573miM8CALG2ZNzggocNqCoKbtjGqkbSx0NbyqcVT5Iu9yQSEZk+mDK6ebivbqB
+cjPBLiSy+dMMDdC7miPaioSlOfCsgl0jy9tBpsh+xCqjOnagwM3txB8pWqqRC6AbiHRhNDgC5jq5
+me/rpilW1RfW1zOYMQdUhPN20orcwvm9gxC2VlswZLDY3MPNnWNqGGkT+eBMSDepKd63pK9nA59a
+FyU5xSQou+hYh1ut+wRVriG9vaStl1QfBprb2Xbr73VHiIzkMAWs0XiEP+DdHULLwwWG3NNhdJEz
+2gYhIAWaAONxodN6FEUb6iR5pMlAKsHH6i7CkomaDViQg0ftTy2l2mqAdby7royZIzXV2e8jTjve
+1u0NS5fBA1aP1g+6NGa9HchZ4ZJiGq4WSTttb/1J1JXqVnoeB+J/vNo8yH1Qk1b5wog1oXKNKIk/
+76MTwZwGgnOYai3UC0KQGSVsWQ4uJIfNBZ8JsDrZ0DtBh4hKh7jd9j+OMbQfrSCNcYfjQZXYwDhY
+I0e4y6I/9BOicVNtw4mYpcaZWJPr9jg9vVADAm+F+8mPXmC+iKnTqQ+Nd0aI6cqzDRsJ1Z5mBPfG
+7t19sbTmlk/8juJqNBKS1uq+Y228Pj3ZQUEQBRFHK/Hu0155OYzYS/ZYksLS5dgXV9OBJiHm8kkm
+dtZ80ncz4aNn+Tk5m56c509/MzmDQcakwkiHYHS67dfPf3j5w/PTF79qOyipYMKi4is4z7rUi74Z
+o75UK6xtr5noaLUvfvXyxa9fvtOaKeIcFduD+9jx1+1dzchvmqRjb3bXsbOKnQawvJoeoYPVpBEO
+N93rYePScW+jR122VfkOi/ynvBxNZwhArSEMyVoA6ASvNSIQYvrCrwKjt8USq8tb5uzfeBzmbddC
+7e2iHo0L1Pg602I/b1L5B47ZLkBhPBhjvjQhgOCJHw0T94FjFwpg8Fm7kDB3KJK873nXBN8kYzQe
+TkMcyDo51fJDPTPwnHz2heoPuYWwuTj5KvR1TjPEFZ2i8uIMbBWyD3l5xvfw9QV+bRCG4PcfUOpH
+LGpDAZIgXwL+QnSuMPf6dikfcIXdLk+jVIHTnkvbaq2q++Fisx4viKddGc6o++PkUa/o/nj3qAfM
+vFzINvN35GC7QyYDl0ko0MdFk6fJZjVaZ+KoQAaqOIJS0CJQlCWPSbg0TaCPEeoE6zkGdkS7WlYv
+SYvqijCtFhul1Y6g9aA8RoB1Mp517p6jscocEl7Q23SrAxsPRHRSk3Ufpkl3ulZHw+hmE2VHE9ws
+jTEeNV/+HJiEMAfJ5Zr9rOgiv7sgKuwMkp6TP+26G/i3ZQjSRAUwfhn/9SLA4PMLDc6jEjjByneG
+j7EYZ7sOSksAG9TYv23vSIxHgJgWsFCAdx7zsmEg8NslbtUoWgOa8sOXTMM4/TXceGZwz6jmCLy7
+roDMtGUnm5rlfqpFGN/t6KYamY49ffLkEEsxafpAW1ve3iChoVofEb2f9rLAAUDl6Z5Wvnz5u1fv
+Tw8EAAyZALp5ItYE3jJZOw3XQILVxhjLSNJ8Ur2YfkOItxjYXNBpu71Cgh3DBXW2GE3qANfdhaFg
+trieXpBV3kSKmcaUxo0IP5gBieFsXHCGRMoHjDFK12W9pAnG11hmDzEvZnd4A6YXB8iTFUWFfn5O
+/G6/+4oACoE72Q/lO1R6jt4tTXgT28VIz+pvB6JjIDSnZaP9B1rALWYTaEje9oO/6agFsLsz2Dji
+oVizYpmkFRcYPAvXAkaQoWhz1M9WRqLI4kS69GCLpSwVKKY0HBJkUFHnxucIUpB/PytnOjkMTTVI
+npPY43Ie4O+pVQy3uddweSCW0Dc4IzOAJQHXvkg9EqJ1mokgT6kOk6hOFiMUITKjwGdJfpQzNud2
+MXYy9k6c36tXOj1qrFnK6ORBolXsllPiBHConKiMlD6W7pex1qgpPxHdpLSwCw6mBNOZGzwt1Gj/
+wCLWpghliddz1kzlkJ2BozubRKJPZ7rTR++TvkgyBaflJITj1ls/f3VrP8AkhA9RCxjfYWBtPIcY
+bfZeorQy358B71x20yxqXQ+nTlN54UkiUUziONLNB6TrrZGrumAofelOKJSLw6h5skGcQgYeguhf
+NM80DHSAlPPqrgv9GcD/ewcPpoo531OaLlXd65W5qODiNoUNoMTAXBCsSXuzvjz+WRtPHDZXChGT
+fDZ5crF5c8mXYvYjafGiftFOkDBx+BphYXlsl+lGWrf8Ms6t4oe8jB3gUN5Fwm+AdOmH5WP0Q3GT
+4PnPF+jK64wvrzp9BjUZSJawROU4Di12ub0Ue2LKli/0s5sJa3wK7Vwv7tMCOegjdKSpSLeAXdVS
+ROwBtMVqhKt9NZ8yJw4H/VmHiW3nPOyG9NW4B33GVHYQV2nnZK7v139V+ZC/uQJheIR2iL4YXgwy
+Zmgjdi7OmKCxGYahDq0mrskTKWQICNGgt4vNVPGySe0H50YPpETQYsciw/GaIpbbxkL8gskwy0u5
+4cC9Sq57bF4SLyYJ1+sisb43gaVk2SK6ahArjWYruC9GudUIKLGKODlxJhE4YkFwnTSEXvD53gSC
+ZVSB8gIW+6qasXGOTylbgwxHRPIjGYnf68qPgUalNWNSm0qW1Qo1exqOo3uGuDBX1ZzOHjEvtrg/
+zdU6MMmgXqStU7KD39QDsU7rZbDYAhKCfTXzQUvuJGqCLgsSpHjDrBCeY/+c7RvwoLj/icd8bsOv
+QMPiCCx+JPUjtLCMA7Q5zL1Y0cV5CGtCsueQKVUqrAPlmiWZer19KH6rDeVoOn2OKDwgX9sgKUH0
+OowEMvwMg8kYSTEXGx1WRy4MthiikCqZIqmtfJhRrA0V3mSSvFwtPk0nbAPITfBO4lAOFeNgISMG
+VN/7UeA+DNKsBDxHX7vpoPF7xslyQzedowAQA+BwL4MxhLNOLCOj8y44z/UMjkZppncAWwRwf2fL
+8+xZ4VvSfTjb0cKnDc7AgltAVUbQkcoK010khKv9rJ7kuyC3yFwnTCK4Ydb+Bugu03W3HcUgmi2u
++FM7q5yQbKSi+KrvSj5iDvIxrr7HGsYoc63ExGdPz5PhjWjBwx0MznQOq3kMm5W6GQ5M5/hY6Nti
+Ptt2zrPz2FCHoIAFo2lrCifVdWlsq7DpHQp9rXZ4dcxacV2GbEWQft7W7AX36iQxB0mMhO8zYVdN
+fY6rEgoTyVQka6+pHmygjLALHhwFpwqvplk4PREMZGO5ZqWQLiwtl/ZCBaXx5dYEgkVLdbM6/BzI
+3166heBfewLKXklVQMF2GLO2Lovd2E8kKYZx2E1HzmLVJL4Pzzf3OhHpcV4rg4ONQQLx6naZ8zsN
+xdjZGOlu8Nu+qIFoUQ2vrcGPO746M+9st2GdAFIGy34thzB8GLhQhox3k5VWx8fidH4sm1CWLLz5
+tBDlhoOBHn1aTCcwgSNCcv72mzqIlYVHqVrqFaOiDed9BVtstISZJbRWOmTRsYdDkMr7IracPSJh
+qI9EO12TL6cc0TGnNUSLvzn6LWQstHaHS0bzoaUBK29j6OmwzTsmIRCANovqo0CZGPH2JCpFGUXg
+bmKnhYRySr25neFD3cabo5EL7z4MyXN2vCaL1JnigI5LX/eW/SW9djweddfxPcgfEt5z22nX2xkZ
+p2UT64Rv2AH6qlZ2CIKmhhpaZyP6AqaOaSDc5tEdnaoJzNZYin/y4/xB/SMf7Sdsc5GzPNSqPeMn
+cK7xONXhQIVOnHAumTHhBsC7JmGPJBS+44wLOA/rNIWEE8TziGtugHEdkcaiKCBxjb25Q0X1boHu
+SREJRKXBKhD9SysnbTEMI2Ec2cNVm5ORsJtsKr1A57mjOLaF22l7L77IpbvRMHpe41Wrkg6VcYQX
+XJkPTGGNBumIH15saZTU2pkmKRHXRLc9TlUOb6vbhdOppmZKnKHcbajk9i0lDuyqKuXx4IYhBxPD
+ZznYrAh8qpp/Yt8neJiuYAVEDiLw+qzz9venv3rzGl3GOufeU6qulix2D5A5zsL5RaVTTQZGdxPg
+jdDU8hNDlphC+0Wn07NY4zd3Zx1ISLXB3yReBbxr94MvXlpKAr7NhZy45VsalGg4BuGoDILBiUOh
+Ete2T9yp7hdwwr3QAy6cuX9x7oqrm3K92mJc5yaW1pJtK4rLxQAcLYHeu01x+HHcUFJyStuboeOD
+RYll8E3b8rEdopuuWJtohyUtUNmL1Tgj/nY+nt149ANph86QzHSTJJquoZrGaPN2liBvciywfDLX
+gqc5zVSbF5wZ9eWzpnSwEm06Md5EWQUMXtts7fZ4s4Kcg3Y/kqRa1P6ntDTQ7bZk8oCi66dojHpH
+Wwi+IX4CKq9+Zqq9fJbL92xvvsQAZr7A4wY9P0v8J9KlEclyhDy7VS+fum16+SxFhsCY2tXwcgKH
+Hon1Z6M1yhTJ5+NuOv/qWTtxICK1GNZV3o1C+3zkr2ZxILanJdURB/R5lrzeMdarLxzr1WeNNVvv
+QYPh6gTUlv0PyEwuajyb7kEXdiX8K0eD99tkc7sccslMcB14wo6URIs9AkJCFJxRZVeNJ8lusm+X
+2TEsPLvBTfG8z8XK8nK5MwqfMUCkDFmLaFUmy17FhAxtMrg0igox6vqA2rxJ9ZKUxhkIMCpETKsx
+nigfeXBBfFA7+6zFpVsVZGZ0uez3QnK43F64U6seA8+2ZmY2vr2gk7LQNp4GPDEwLwXv8DlRlEX4
+pzmqSkRVS7KDHhYWNSb1twx4UjnPoAixGAy93qOjkI0H6ZI82xYURhrrgZ+C3SIgEXCDR5u0Qtgd
+dKGKyrnD6/N8TpFCq6JtUBhKjnaFoAl9Lr4X6fh5gipy1prOJ4s7BpGStkzroiqvSgrEy+bbUGAO
+27ihzsSzvL8rGoTWUd+g17p0CWYKrfTJojIFICDBiZ+faEGtrxfhikKgkIpQe9BAP0YJoS8Rt29X
+GSpWOVE3sWvIbDOuUsFQxGQCzSf5PROyXuPyjIdS5i9cq6ZJkWGRhhP7ssWJ/W57RIx/TvXPD1a9
+f1bjfwS0Jj2wE1z1ds0zFd5OOp6ZvOHYMZMErxwIMehN0/zAOEuKxgFuWLLt43HbVxg3yptwPMyo
+UwKmhm6Jw/nm9qJaVZMhqsDVgdaVddzuR8h+1VIwd1eLBRpmDqzRXyzftBLJwYO6A/Ox7BcJ5Ttq
+EHQeqQE6CvznlzAEaFKmyu/7XpQyY6obTu6RQ3IJ3pjG+moGZaefNNSIre8jfxL9FLo13rNL43mw
+kXMCcd+GZcdJsc+enO87JfhUagtpauu0GwOQ5ehuPgxWBqMk9iVs3RBPd2QLnz4pn/zNNmhIK1PC
+iOTsE3rbFsKGF0tuzjE1mBWm7V5oll7dxkZqbLnRlrwWzmr+aXGDookG2PDwIHXjZ70qgW3G/MAk
+BItYnIq6XEPftUzHNU8xqVfIiSfDHv6MZ84LH/bNl4wB73Iae6aPixXPgY4RUJBn5U8bYO0QXKiz
+3C63Q3QNmQKFQ0z6DkdH6/zjT2nzCWHSiwHQEUSXrbrJEjArAMs8/sefFhdTDicnqEjVJGxIcOEY
+wOjDzQXO/Xa25Hv21dKOTxYVQ3li7EbkWqZAMIlz4UJ+8ZPmuqwWpX25qqqLetLu/XW1umIs2L/A
+xWWuqTjbZXijhWEl81upyy4iKWogf/mWAxfJXpS7lNWCYp9g+SQya0ztYhzBzQl46QneMHYx8xot
+abMuOYcz2Wzg0b+pGnh0Nfl/9fr05bvXz7/HIT3G29kxF8xnH9odEGK+7DWSPNNuzDvHbsvpoqxH
+wLCi0yh2pu+gVVKD7J0BDyKAHotXERhXm8PAY64oZM+OVB4cgxilAx0OLYkJDL41V8R27nQUbSxM
+c0WF7XHwz0S9MuA3ekTWOSRtOhqwvBAJeV9v2d1ST7+jKEiJArCphULG6yDoyqDRaMLr40nsrJYU
+afCs+1IyhLxC1NzA3BTGgvOo3h3TLIE4DdqGF/uiBmJMiGoemycE8OZrMlCjIu6uF3BbmyzWuN3U
+F39EwULRN7EOZiaDQADF2A7rAHPL47XS6Okl91hsOJ1BUExJP1AahYPYdq+RsasmebcTtVxRoxXi
+AnHNqWnLcTGr1p1aYgHBUlzU1eHxlL40LC1qcbRn6ocDLUIMXXitPjjYV/x9oLeaQi3pwikIiUB/
+kN/nskQ9zHQieBrtk5N2bwf2A2RIzDpmOWjuAOsidN42O8/v+AerE0gR7MpitMbIIT8Bqp40qOu6
+EYF5i0P118XTfa1i1eUtz/EIjq55ZRd90LJGTaYdbNeiYtZrcOE2ZAZ5h82qCulM57O2cSdDZ3Cv
+7dtzPXZvWJKHezVJ21VNpB40Ot0VysH2o5Nvoi8cSX+TMzLv2MjTENjFZfySm3cwjdlh7XaSOnw0
+Uw75TFt0oPSmAYeDishuGId1j2VJ9zLSGP6wvwQei4wzH73P5lfND7Wxr1X1JYtVx8KANU2WrjXc
+awmaQjDL9kBjCwL55IyusR2DJ64l+MhtGTyJgkBrm/HZtZuiJeuSyNQf2y/oOhuINZcWmyR0i8+n
+lFdJUq3fp+Q3ZukzuFcuoErAvDA4xsk5L2+X2+CI5YpoBB1j9rG5ugQJzXHEihtxYFQYZsEJlpcZ
+7dPqfv3qjUUz47EaKjZQqi14FjEiMrjkEssJ2NyZC8D4JGzlO9v2nAJB4lFF63TkmE5o1WrEOA1E
+/ctsDJO9KCmfRs7wRHvuhSG9/NCUemGx6EBhirqqbuxX7hLUBAXr8Ry4EaYYHQxSgkBGDOYrwywD
+bGdXMjRecooYAUI211wglubWsl89fjOO2w4+xeePBMM7V0IoQ+PPOWwwWSGD2LRGe767vDBTU9H8
+oFY6ZQjy4a43mMY4o9t5GK6Au1vcNvXVVeTEUuHsNerNnqV6NUuPs5o1ZJWwDKBa9xREhBuKYkqC
+6NiNMcWM/+SkUBQmytP7G2OkUQNjfDSg7cvNmnDoCEokP9RNY0yr9Xpxh5alT8la+1kqroxUjj6p
+KB6NOD5Woh46h25v+zkCum+Cft+veXpC/11DwAIO6CBgp11rZr6gwaMe01lKhm1BEoZC44ans2da
+LKQ4g4QWLTzN04BoitPUru5HY2HGT75osTmOSVe41rpzoXPlkuWQijkDDtN07TNoXZ/Z2iY0NLlw
+hZO1Aw+S2iSpD+lEdiUE6yjbZby0HtJlv3qVN3WJPxsdDY2tUMmymTta9IAk+pUYtJAskOYZWvLx
+xw//wULafzw/Hf6eofoVmZ5j0bLdOLAKDp+fTd1OCjwd+4VzfpMLRTFbLJYxUH8rwFN3quUGQP5F
+3Wcof/jdcpIP8ucytzCVu/zAyr8fNF5PXcjjD9P76bwl4odXlNjIHqi4D8BRfTOF7SRl4TNlS4qJ
+gwCsblz98PxqfrlotRzFYS1Z4nI6jEDee17l2modkfcgHro1S+PIfID1pDhpLfEoJIhHej59+f70
+/bfPX33/8psC/S/oJcmI3314e0ovn5mXrzG8xLs37+D1V/z6w/vn373Udz9ttcgYd1V5NEgLN/av
+Z6PjPz0//s/D8x/vHv5DhCXfEKpAQhTAV3Q5b6P0aLxBKed0RaD0itizReEZ8Odz45ogoMMb0rQY
+6R7i1Q7aqJkyoQi6nfIh2nW++M17/DOcjFbjGp/+DA/Xf1EPjKOoQTz8VLHUQDrPtmsNLsvp5ZaW
+/aJGoKGKIF15Acqm4NiwtgBuI84a8tmmnWfthw8f04g9RNd0m8fx3T7FcouDBL8fDgXwqC0xxXu7
+I0FcVfMK6ArmVg0iLiM4WXnvFDxZdRAsYmijRdzj4B0f45KkiAnoRJ+PENEUC4J5C4wf4QppJwko
+YAQlEJn3WtRDFKOR0KiIFeP7JA1CW+I9Zxp9fDsiBVSHQKFHn0arQXu+uU2rDboCveD5AvLuYl5I
+SaaHT3Y1fnSJjjLcagwLryIgbDxjH5fNY32M/PO4aYjztaJljfPuKbgACsHUL+5GK5xxMt9C1EBf
+/+5FI6QVF42nss3hRKyXoW/kjjAiJoPpFXcHXyptZ/U25FqgPRpbd5Df7m0090FzllskCfvGkGuD
+IwXpDB7nqyUaaKLOxUFcI+lnCxYYo/ENBpcuG4ahfXzMMvG2r5fP8bZZghw2JWqDyNJJaTBh5yk/
+6kWXgpgcU5ToatIrd02Ds/3wA62vzPIluxTvK6Jto0S5yUCkLQu11sE4qDMgfJ84OiERxilsStTS
+7l1bFIudjSRMdeTa41zcKc2V0iq1SB/tXoXOx047ry/irjd1Oeg5Zi4w92I1gjXijyc+kKe1SOM3
+c+qyPQFJjLzEuCty9ulqHhQIGNx9BcUO8J++erIuVgP31KeQhINvKWaeYCYM3ls4A8VexLKk6IH8
+PShYjvKKsVcL4undwiqcXuANb9tyriFk0MIDXToKnriASQIhl8SGUGMwfKKiJTinl8liaqL6vb9B
+qLfFPOBykLu8Wo1uXWCynUgSCljgcRcgocZiYg0Ef6gcMHagSEu0ap/vNBfX8jRX3ucjV8TFPgt9
+N2Ag3agmeR2cI034BwxaltG53dbk0kQGdGOyZOn2zp6elxLFIDT6i8PDtYlrRC0QmkU+wKBmcXTV
+5rnxbGfc5F9X24vFaDV5hZR5tVlG7luQCttpZFovKR9U84rav2/sb6T84VQr6EqZA/l7aB8Mmx11
+4m/Q5HD5wf0WWNBhpfm0yf1wD35Wy/UuECt8pGjEATVCwffbGgjXy/vpOiMbSNcGXifxEnhSjEcb
+jM31fgkH3GJD8QOloJ84sW1i948CSbfyv4alf3LglmpAZclcuh1KS2aYgNI7IBRiu2vhPpFEPe1l
+gkImRTCvnRZxcuAUmYtd46g8PYxwZTxyW4HKMm5DeJYwcMiQ/KGC40TyZ8k8JZdDyWb1pMpHkPTR
+kMMzYI1uixInYLqeoh8ycQJe3tBSIBayjsFBVmOHBQWH99YxmRXjWa08Cc5kEfEGLuw0T3gAx2WH
+Y9YERxSWkqlOiiHbUy4iPIQNg51oHUhkFeBuVffsdz0NLIWJycHQLc4+yN/ImSl+ZlKjxTMOvz1F
+KF47aYVRdzelEDIUnHdtYZ6PtDQqow5LWE+BH6dgfSsKwFEXs+pyvdfSTkeFYZKmj56ex+fLq/mk
+um82sCPBcsug/qs7rUX9N3XYmEMynIwZawY38Fgvm9fVUBc9AYUMpsQpajkDfQhtNKUtHAkd7jvL
+nIGHpnJnauWBnnzOgCrwYrGYJ3RZcSuVfZ5D9pK4/vW1kWhRKzkj+e96p1FUAujVgr4RSIleEIfu
+SkVYfMtsScFPmCyR/MM8zzaTCjaEr80bZUvBvZY/7SS1OX1MwS5aQijGswp+X8R5MISMFzgPirNx
+696uFvfbRlUjI6Jl3HAZLLoWL3h+2Om1bvGkxYgqCDIYhVWUYGwe+NiUSatWcrUC9REF0FXrIIb7
+7WaclkMnAVsyNk3zS4qu6Wovt1l9c0s2wJSM1mM3E0kjaicvc74CwQ4Emrzeds3AkBoNHcgjZS4C
+VSOuDdnbHpPvlvDbFCoxqtiH2GXxtxlDXS9aN1bm1NKvgWH8NQe3r7tWHN1siou2a4EV0YpRYPF9
+yb8Cv4Gar+uYCI/PLj9jGCWqFcE0VzfVqu5TOPrE4VK+os/tdglbbLKd86s2G//DdPyZqiZsAaIs
+f+lFixIJm2s/VHyAUXWwPF0TKXPrM+wOmULCCLN6lbKbttVp2wQmuJdGVU6bomltkZNqtqO7GDyt
+qVt2woGSNwLDT9XORUNh2Zyzat6YcaZB3ZN89CKfSfFDXWuDtRsajiO/RxIWToA01AlAaPGheMQg
++3lx2HpVVWyZ4jPUmwsqB1Yw4cOTjT6s3T4VU5NpDAzFLV4vaPXX5a4g5OyvyqtfJEZMnOSHsnyR
+gfDRCXA2m/n046biuA4MPCJ+mLCnSUlwXekeI4iPYAslEValWJNp7DpNWymyddIdLps7KWMro0nn
+Ak/IbqATjArAVMCeIaZIFcoQs0goJ/CXrWkvI0seJ77RJ1+4glja0kmTQpdEPkEZ19HXczeqCwe+
+xiq87ng0x+jPISJ/eFA6+ks194sOf3E4/rYJSvkeK2mL6kNZMc1sFGRC85GBgiHbxmOBauDgOKj3
+xfWnBmH/ogeAh9LD8ynedbiFpFd1Na+nJI4lT4slMhQMs4mRN7CVMvN0zjV5CnjIT4LQp1LCo5cV
+Ttgi32jTqiNpVpu+Rrc10Yu8liXiPlaTskCNLGuYBQiMSrrYFjUqLfzuFlUyfvyBsIhooQbndZs/
+CGP3gqhLmojeS5pXHukzTqafJOW3eg1KU+onTTnNtg1fa618QUhqhNftyARsvAGu/JaGIM+tjSlq
+nz0Hla2wAD+Q6CeDPPuR2PjMFsCIjZZT1B9128/KJ6gJEvd/ojsP6Gbo+R74nMhW2p4TGi63ytET
+6Djeh8qy7JnIMNzLXDGG+BPtRtuFsHvK083qz4iZgh6KKxNSWuMJOSSq/i6L9nC0OxTFWkiIc6th
+lpRPN7IpxRswdaFhn7OzQW6jj4qTk+MaDeiNVxfkQYEgXqvXdXxGFqMJHIF1HXoGNd+XKao21f85
+XJPNVwwEyllx16exf71Udt+KglmkfbbNkjNCKnlUoBcGut/riWnnvProTnEKNLQzsjal6BNJ6mVH
+JTTzUoiEcLmgqRYVZF5Zb/XMAa8Z6Jco4/3hrV/5d8CyzavG3jnYMMaycMXY7Nej+rpxQ+DHbte1
+sm8bZRlA8g/KOSj4JOo8tDsVAZIh/TeOdriluHYVOVnAsHv9jO7Gw+p+iMtA3wU+EBuyXAn3qM8e
+h+xB8zfJNGUf1Qy0vwncsarostCVTGdPzvtawNlT8/zsfEdMJG1Mb++lxqTdtY/xDNBR62Y0QL79
+wFVV95nbz07thR/WAG9B1UURVWgaeCmlt6PyOtt1tJ+rdyOoo+RofK2QabsdLIknijjqutgsSZ+N
+FUdYciOSIwtq+WJBZcSXkoDQUkNSOGOhj1EEXZYtNi09KioPHWyKJZlidKnnnBK+MAUhp8/h+JHq
+usmj5Z4pVurRwqPeC12lrPCmgbIfKvIJAxNgF9XdP4i4KnHi8mOsH5HeRueAfIqLC4uUp3iIdSj5
+q6Fuy9VmXjkrQLcVWLPYSBOJZ5FNAkxTmA1N+7ezKr53XjqMfKdoupzeG8S91l6t3uVt+S1n+R44
+/82STvo8ZdICSJ4hIenJtLWXIGKEKgmEDqLxiDgI6lJ7tphftXdhzXCQr3BQE0UtYzGxKNu1lB3e
+yIIQuDDa+pPRekQrAWMwsVwgiDynoMnT9S+CXmFb86Ff8n1eX3AWdIqDVq3WGa84SaEJDrD1dTnC
+QYsmSLrdleCXNUEl9Xd7abLZMge5HmT647/uL4jmlf514k2/thHZOlrrKixyYp2uYcyQhHt5j/eJ
+18uDCHyK9fVqsbm6LrwizVmj4Wxfb2oSipHt0mxb4JE4QX2UEyo5RaFtC4sEnbY+5s3nYp2Y2G71
+XbR3qEMuOEBf0QrDXGUNwGvzyVUbRy3X2y5DH7ONlJ5iaXh1kplEt6i8cxcLQV8v1uZCLu4mI1jK
+sPHW9nZqZ7CRwnEflgjuieTXNkSyhidnI5GScLB+RnqJfQWhdxj6lL3qAG8BidS4pdeA1hkR4ogE
+y2btRezsjmkkMxOUP6J5WbWSyyELaMYYiIRgBcmQWJWlbhE3ozuETHRn6ARUcBlVVHIOfsmbWSMF
+9D7/pEqjeorkrNccBCvSSjHnKhWZuXLvQq8bm9Q9l+MNax0HjVohvOmZvCZzxjPHVjIPaxGFHlUW
+2fP3cpY9ZUNZglLsxOHfvvc0zj319moAP1sg7WSeoc5ShgyOufv7+4IsPBXyY8irEMU/y+0v4ijF
+GpxJgiqGMdGITWrkYVfVzBcAP9YL1S41TCCkyUyWRkuetTKvCQcF9u0MLS8XCBG87BftxxbLewM7
+r2uGn2+5vdKNuBX9+yhkiVldVve6T6YhLAIuSMut5fF9SrvfZ3ZP7QiVld0RGD2cBoOgQB63k4mR
+wuVp9wi6e9eMuywLGr1CzLA2K3mU+Ds7HZajk7BfjkROjILQmAEYYWnTcREHsqCrD55aFTtEY0Wj
+AmFLgE3SKzFbfJIO4XaKlmgX8ICW1XDQZUusQ4bAWHV42xA5BMnKCG7BO646uol5w+rRn4oA1aMk
+Lmu34E5zfY7oTvP4CFeuH70EW9StMTYI+riBoSjq2eIuHF8P6I1HWqTYH6LB8nAYQHcPTdGUqd0v
+/vyX3n68G7f5KNeZdgYO9PMc4ozqdXcUtG9zmSpyCOZxK1KbjGjQu7okXC6UHSF34l48O08Mae1s
+ozdpPPFWiavfnBaW3NoTPpYYNGT8JhQAW5FdBLeVSqlgzt0HkhEEm1XtsVMSIJvZ2Bsldr0Rn1RP
+r4BLQqa2mPps3tg+AiPgmBTk0tsRAVfdQUgrVC5uv2rU8SbmNKbtZZQ2gjgPT+Ld9yA5pqODZJDB
+nshabQZgFaysAdaTC2lHILiRNYY1V1WDd6+LdcZeiTMzI+4h7+LNpuhniXIvCqCQ+gRZVYD49Tm/
+OWt8lXH9S4IeKA+rVvFZNNx9dm6QJDRyC/KkdSYIODLi/CNsAL8rjSmwjevNXxGZalSzB1o2tLed
+nkexq4B3obBLwxuvqUdawjVpRqdUCOr5eqAJTvLqiWBZoNeUuNGS5vbBxLmyNSMJJpX2Wh4SMgQ/
+Ir40P/gmiFyNO9ExN0kg0sjEjqsX3bIY2hnZYajWVs46Lc5Z5TkabebBLp7IbNcHuRPG3EUUjWCq
+BRAxtqhrPu2DGEfDuF6OWqCVhasib+qMdBOdWSWKkKdK/VYDCTNtlYBEg6i2LGp/Q/WJfb6lhzZo
+nL2nNo626ftJHNU+L66zwPMyAQF6sKeCiGAa1Nvm1SAR7TM5mFBO5xO8EQV7W0nkmvE6QjyvZOlS
++9aJmZ1LwjEs4yJ0pWSCJxJfvLrKB8rT8mSFodceJApDI+cboaoJ+rEzMdrRjiaSMuCjuOmZxcKn
+gJNuJSvFAR0HmQmxWy0OhKA3ldFYteTjP4MAKKxhso/tZOtR5eY7xaGBwSVJiydd+bSKiYJUuTtf
+8IUXA40hIuIWRUYPVj0iylpiKt0KT8jEIYxgqhlHhl25GNSPyosAK0SRrlsuey1BADYJDNwsy96D
+KncpRm4KxcjlnTSfO3xrcwGMbUAzMoXNGiNEVKZBgnfJtmrrOnPKwNuEuOBMnZzEiNq8QzJbRCkN
+qx3ozBUX5DbHQG/I0kxqmi9OgfbOHiENYC/baTWbFPe5W5XcKNJ8Rxp/GbhxjLQ8oriPshP59KsX
++Vxy7WB/29mWFGROrI8Wh875Lc/DuC2kZInXcOLcmEFgOWRXN4PT7MrtD7Hk8LKOI3ix2kOC5bLK
+d7AIRIjkcHBPgavo+KaL2PxPozkV2DiCycES+kV7OgemcjqhRftgpXs+VSIoi0U1fAK+bI3R1wYs
+ZC7uT4p7qZdAoJ729iqIeA+OBypvpytBv7i4ZEUVLBCguhHftHsRUxy/iKPbtZIzkV0VB9GNovRm
+B4QY3YvJqqvb0JoU8jluUbI+OPR1juOdWt4x4GkTsZ8LbGO46MzwTMXAtGz28BlYHxTLCvYaYwSm
+5ga5M3boRmkQCLkjbG9dHl8yJLlYJn/DLnPnooNibU/06EKcDL5dbYzXhHU3j2x4Xz94PeRG36Ea
+NE7BTt/BIZwwMCifYM8Q5oZMz30YiTSGaRMSdibBHMvRRc1BkstO7xwN+yRGTTCmxPLAoN4L1iMm
+juMwCY4GsERrwUkfIVQ1boOReNVwOSgFjvIiLSBzY846m95UhSKJFHfohIiKW7QQgpqjvLC7xoSS
+hZihExFJcabReL3BSxEXPUX6TvEPOBptLGbdwLrBFlPQBzHfviBUTzxFVyhtiM3ioyKkr4xVkijF
+GNOpFKQ3iq2VvR0Ftpr7OYoJhSJl6BwUxEUj4ZQqsZqnCY5rbzPyZhFoxjdpVkH55rqAcfEAUQfO
+np2jpgQ78fbX3w2/efXu5YvTN+9+n4MpDxcy7CaKzgrd7p0fgtkm+SH9ebzR4J29+iovkGMbjHmb
+k1cIkvV6g9oNlt8QhdHwARReo7qf1uvIQJh5V5RCB2xH3ryFt0eO+RU5UEQeIk5GLpxSl8VYz+i+
+9M7o9FPtx8Abs5Kq12pWPjMLLuXA0F3UkbhUDkpDhXuHmPbk+u6xNNo0wHQW0FYszO3qEBMfW0pj
+1qarHGZ+VKSDDaMnrrmp/CyI8xCxNH0n+085GXt98dnaaZbPEpRQIcaW3DWnsVRE2mKIaUrY29PA
+ggVQ6LD5NcK0Qnbghbntn33Np7oHxZOcKFqVLlHDz06enmdjPgcG0odPgyxip6NZrDyTn72ga8pW
+RokeYL7olcEq/FEXqpcVzvD0xFIwvKfrFEbyJ73Qa/0pK+oNfuaEYSbrGxXCvca4F5mOZprjgDVR
+GnBYkAjpflOrvL4rAoydVAeJs9KWsEgrLWC3SCstZ49w5XpUDwUbNItnG9xz9klfoK77PZHDc7Nh
+JTVmrZ/dn/f9EtsBxhr2IYvEygahozEzGt/UbCDAcHLkKtru9tpsmUCaSmdZ2LTQbJ0EUkKg9jo8
+PRyAp/TBDwhWkR8Q10kfjjHybPpbDl3jotwh6PR29lq1VajMVX+Q8Ta3dFdTtiVV68v2e9oBLNWZ
+vDFaRroT+JIdeNs23vz/p9vnl+wefagcNY6/pDPMJfSa93VOSvg5C04Dql3WKG2eL9Bd3LmVop3a
+rIJ9ixbcI3LVqNZjRWRFW5/RvHIudq3IWhFKwmB9yDQOR7W9NsIXmAP4t9SvjPgibTBIXXHLWvk1
+o2nIlGM6X/f6WLoFd9AUrdbHf/3wv1LAVRb6luPbCQJcfhyelv+OwJdbLQucLEDI+hNmRDIaZGUy
+pvJfFJX4LQa96xdvX719KRgXXBVGyLM2INzCDUegEyh5DgyBuJvIVnQgB4U2hCEXZ0S1lS/FyJu4
+HqmgfMk5F/NvWQONL1l4S9ctA2ssUVnUSstLefkeDZV8IkHyvOhUq1WH/ILIsklNrHXiKTOywcfS
+ARoUU1Wp64Pc1/1gybXdxSl0VaroQONeP9YRYi9MXjMotLhyhk2atNvj5sMlfkPhWajakYmGSHcw
+WJ4fTr89/lknNDnTlg1MM8u3GqoelsN1NZtlzPqhfejxM5oN59UdIYpnEkmMe1syrA8X8D56zwte
+w53jxtBVC4OK44GASA5MBwfDxsXEi8fPi69OYCsjkur2KxT0w2gV0Uj2+fMzHJlmXbiM8VAHWaAL
+s6N/VPyR4VtvR1s5vz9VVvJygKFcQ308gKV7C5RTZtHTF4onKZ3kKPQ6bpnccT3Gh4+GXMuhePOm
+HITb21+Og5XTnEugxWbK6PNJ5AkQ7d8up+oX+peWoa6KAPQII2eKdVhcCBA92qClNeLPmGi5ykja
+la/SN9hZtYXWW0k4GRkFQbgLP5qKeJLdz8hWiyLewr/ha54m+Dd8zauABsTgyax3+KZHI3aCtjdG
+KWt60ncN6rs2CIA8kf6QlG7g/spo8sSbdtCwLTx9eE46reAnYhGGLfJI/NGHMrTISyvoNORil3vM
+Iy2QjdkNd2a/ON0uK7twyIHu4x8+/Hs8S8UC8OPo9Onf/93f+bjnLd9g8YackMUzP2pdr6ENZv+z
+cS8ngTH/uIENFQWETD+jPEHeiqcROv/DbwYAqhUDRjN4GeQ7jccUZ8966gTeGFwUgt0PtUXDYafX
+YDDMqUubtpuIw7KFO4CmpGyiFm5qum1VX6ME2w1Sr7jd1GR4PXLNyNmWS6u0/35wW8amNE3mAIYC
+QLKYqFQfc/Z48JrETR/TTxxLg+k+4yJ97CVVZFGYIjPtMBPe0nIZpt4e+9awNfbGVHwdy5o4Y1ZR
+bbyOsZdn0/O83tt2c9okhsfCMhP/fr1YvmK3Ogvi43CmrtbXw2uMFrRviEyn/Y5FE5cB/rtjn8LX
+Li2Ei1kVmW3QdUa/JeKm+0aVQyBPCFRvpmkzNNKEf3c1bTb7sqbhNrw/UAsYqOdc82qKHI6zTw8N
+jRSiORxT1Hj89whWJ2ufNsTMLxEHX0CNUK5s0CCoYNc/PJ6XYvsI6eVJtmoQsxAKlgoD3eCUEMaa
+lTgIZAO5GrVWFBCQi8ZgXdtek0yQhsv0vHtPMA7bxGYqL5//vHp2lU8RgRFurluxxyXcGfWJFon8
+sEvlfLdRlYxQsxrMDz78m7SG/AXdirVTo/kaC5+VuCC6kq63o5mSshcaVtM6iROm+AX7VokCFujQ
+4TB2h2ZcMc5XonKb2Z1TAYMJN8c/VXPEsB1ELxp2Et+/q7W7eUe5gC+z5kwthyWLbKM+m1b8clRX
+jq+FNMHvhjbEeXx6X+53FBMGzkyE34Y0we+GcvnUDVI2ekSfosOxZztxnnAOxcsEzYfxHTtjAZFB
+kRe+c2F11t42jHDEC7okanCCGSPrFS/e8tXuWfl/USB0mtXFHdQjX3xISr6LMupfgLyQjEbEwLpO
+1J1Wi4FT0HUncWLpGzzzfvFDdbtYbYVhDYoHziFzP0bL/O5X/UIJJDLKBZoD4plJVzZ4KP6Z3g8H
++K8C1/IyU8cXBZ4i2DR0Pb2DNpqgDhjdnd2PuedDguVkLClSxBrLjsUaGRSSnelFUsg5B5GJnU1D
+US7lu0ChX6pM5fzNNNxL5VDehxfe5ELcTJgbM2u7LVHKQEJhu9MAmlxqzcLEhGNFEZ8fuWlN/e7e
+Z/A4fUX3Ojw2Iw353nzYPK4P05uJowLhN/1thSBy01vkr7oZWKUIcUhTEMOPeYDbD7ARtURMSCFI
+PqfMtnoBtrNl0ox9ZnmYJ1cebhOyLruEdFezxYU6ZcwW49zqpST5VSku3bhtqecIRd6NjAI5+6Bg
+j+8h/gQOLXb+MykYRyOSNM2KwA2elihly7ZLCqSqPWOJ5zoJCbHj7VV7B2pUTSFd0VUR1QIji9eW
+9eaAZGo747WmAmNIFotUHhx5WDPRKYrdtAYqB8R+uo5ML4iedccLmR+eGhsYGlqATIhRBoSIZV6+
+jwsBIZ2H6FDmSYMQyKFKBhCcrfb0koggkzovYMuQRv/D7jubXvee7kVdfYRywI98jEqXyHOVH7+A
+dBAJ+GzCIe3t/fWUYXpLpOG/P2HYBwqdoxSfBwvdWB4+UpFpiyU07kP2TcrAnyOTdAv33NsRb3jW
+8KA34lc3ctpTdA/kVkP7rJrUhp2iY0lXB96SWoYriuUbmIO/kMU4pTaDQJ5InR/nYZHwurFIzmKL
+xNSWdtAC7+BfUwjpxW0u+k5g4l6gHjD5d1n7MtxnCEjKpl1neCxbHH7Odd7bLaFSu3dzreWYb+j+
+gr40oXvXaD0knW4udPB93qNKuAvNmdHNIugBB8oJjNjib9S/8LNpTigIMPlgTqLjcMi0Us4mfxzq
+j0NXKPGnDQt0b7BlOWrRxzt7qHGgjwNO2xHB3tLnhgOXD8/GmtQhPygnOpb1BG4sxBUQNwAH6Vkw
+4DrWOy8BT6xCRJEmx5gZ1mu/WF+YSdo71qKh1pOSSuiYXCjJjVQ+kMacn3ITgfnd156dbRGtsMnV
+0jXZMEQHFEptQ84cdl+UHTXnGnUIjgjmAroPrdWc0XizQSzG66w3Y1RWIFTdVniHaiKaYb/MjUlc
+3YoN1CNLtOSAGg65XAGbSQ6jRmtoHz6sAXkzvRCpZBXScx/qM6yTJR9uMh86GL2PFx/+owYmXlVj
+RH/+OD79v/8Dx4Jm/DxkiFxYUUE848i3io5dqXKnKfIzxXNehOGlBKUOlRJUb3eFQv/axAtw+pHf
+Su3vqD2Vh4Nj1bro7Um+AItOQJhFK/Cw+MMf8OhBffUV3NGZ7P3hDydOCDSCrkj/vDklmQ9IltIV
+NJ5Vo1WXctOjA2jT8cGUlPp9VRXX6/Xy5PHjCbC4JQc8Kherq8ez6QUGmHysecrr9a1Gu2J0RXV1
+Q1sIaZi0ZVpFIDVNZOVZ/5/sZYenwbaSb7mzCUNVITlz7ZFXZ8bC032rKTS44Ft1RPFsSAqr0OqK
+/HywlNi2OlML3l5cQwzjSMsB3YfpZjL9U4VYC6ZorvUO1g+UEK+RriqnM6VgllJ/9sKQZtV4d2RP
+SfjnjodCp3tI56SI3vyFC4reEkMJLGKWUyTMI6Y1tLIVF+4Pf8BcCXv5hz9IVMvp1RXO4aj4RiqD
+tSADEi4XGf1bxdIXZN9gYcy8DS9MC34aVvfL2XRMkkPli4OSCPzCpOv4u0rwfgeDPFNT3ZALi1uQ
+lGDbuad5Uau+uDFpG9KxLeNxC343pJdkaajSFUmks2sgH0bxc9uyvz3C2xogkSO+tgTZDmdUmEF4
+TosdVqvw6A9WxWQ6UWusyQZIfLqk0SKCdlEv2LsrlLeLBYpQgYnkaLQ4EWzOvqP1feKn2X+J7fbE
+Gz6yc5WM0Ct5iuxFpDi69PNjBCUnteC0ymOYwBkkivVg8lE+aY9j+tfQ5V7DGmmgBabGeh3a9pMy
+8HpxJ+m7Bw9loBUMKtBdF81eCjxz+LQdACzGJjuzyXB3b/LWs/keUtU5zzd3Hc150P9cwyKW//il
+jUwaFFlDRSX4U192vfnWQBfC3Da9F4Yslh6teyCTGN00IY3hwlcy4VpXX8iD0ShdeuPJUKsj0Rrv
+4lCNsqYyrs+1xpfp3pV+5FIo8NhUgZYods4Edjz0QvakXyBxc55d2Fp2vqc7km+uCblDzA4Dgq22
+SdidHE93FHBYC+CQNXsprGsm2XAoj5p2OHSpvWCWXkQUxLWambgzAwev3FUSESIkMvFyyqzR1sfJ
+h/+kd5QNUDJ8+Fid/v3/wZeUybQeo7nVliPASkzYBRo4To6F1y7amrEtWNoEWMXXFXdb4fg40a1l
+OblALS7hpa5G8/qSg7pIfCg2wNbW8fbVmdHkGhwt4Csz4XHGHqOUd7CXgWvr5SooVzuCZuvot46z
+7HSpE/GFrGb0Gr5YTLYIvcH2sWhH/wn2n2YtT+GfFyMRMwVkc1pjIrQZ8vuILvRJ3l4rxGNsiu7t
+o0FIWqdlPkl1t+Gdl7YzVpy9Bn+AD9qYAOh1MPbeHXJ+BmnVBwS/yBTMFwqrLjuc4v3QzNLi8AD8
+COOHUix+kYHXDIj+eoFODjMKWIcs/2Kz8nDfkwVDOqB3+Iov3ARatQ+8ZldsgJJciy9H2PupczTU
+yYv0NbPFCO/bjjkI5vh7+mg651gJhSaQ0A0ynByoq1eqgwQbGTivT/uaaKR3zk9knkb8wk3E2nT6
+XruQFmWoRsL/7uP4prR2Ux8sHGtWAmvqe1aD4IcOQh7EINfBZu9K/j7LwHhkEj8eFdO5xJ31YrLo
+ZM4hGUIsvSRAP7gKj2oEUvPZS8zc6+nPnE+UDpFGLwt3RWg+nZ0HDwdhLgVhqmgrMtRfdtQ78BFb
+1Inj86h5kOTdbdqUo4rt9R3qyCYl3I1HM7ds27mKlGo6eonqCa36JwP44ChaKQ3ehTaTDLHpZR7r
+JBtgaXqZG7DhULsyrG+mS9LU09bYjVGCM5OfAaj7w5LoXCcTJInyNY4+fu3GWNuWjirYNnewtz9e
+1H+jTmP130D1/7X77brpTplkcci+/jZUdA696DeEns4uFQ/BOUbs7UEQRA167GN8xciCIYELy+kX
+mWxRSACbuoNzk4QG4O7hpygDvdtRsCzPg8pE2renONtOHMMhS4mboVq5jSapr2tHjK/2UASO7WzB
+Ko1ECeZMjuX6wI3R2B/Nc1iXotS2V36VoaIRl6r0SjM3RzEaTSayZBVGd3SXBpQ4AjbjbjVawu1v
+DWsTKLO94eF6h9zABzHtLoh2O+bnopot7qzu6s5vEl3B/iWSDf+rEzSoWVXjS1Q3UMeKvsK+5QrZ
+fbPPShyyL1X0KpyWCSZBOoGhG6nuw1wzQgta713efv3m9OVJ8WpujCm9teg7DdMyEhuHRnffNtyz
+lrPRlvHAOZrOyY/zH+ftfBtklxKr0hbF/axH7tXYswET8CSrOgGZ7H4O+sUuLPFE+d9Q+Mn+9r58
+9+7NuxO4E9zMYas0Dd6OwVoF4wrjxHd9sz53D8X+S1NzT138v8wInuTGZOeSj4+MDKZ/Z+i32dl5
+T6V4bol6x4iJxBYKyUoDteD6DGWJl70U+W0QjuivKdSW+l6Pl6BI4rl3WSPZw0lSt/ITg0maJiZp
+ZagAjob0fkloCPvHQTswaLcP6ANfM2pCOKeONPXkftca+6yufJhX0pn3rJdvmIGwA1zFxuUVnT75
++2HqcF6zBTeebAiJ/jknodwbdrNoXQZkSDAPD40gGPKM5e58Zp53xGHSkEWhpYtCfZJjUhkZ3rD4
+yTPnnRBusSEEUy5yko8G1foXe9GFlUny4VYGtx/FZoIqgdKzPulKZZBCy3T+HHPekSE7BpRRMhYF
+hIRyS08lg5QxHqua9FIeQUNuHeUZmlynlqvFGkOKSZuHQ4pXw2auX9y3Tv4uTGZ65t4c9jq+VZ+5
+UsSSQSIDdELnQqFBqnIq6PYsL52bdilSlCjmaTW+cTtkONVwdPWQmi3AKIG4yRu6jWGb2oB0Q3K9
+Ve8F+I04f/bnRUMoj/FoiTz5b0apu4P1Z9Aamq3MDM9vGdUdIXSbPRxMrdiP3ZXKHuOUAwI47Lr2
+9g5tZ1eLMMOpQ9c7nJ+NlkM8QX5utOxmDGE7M+a5kYPcoWn7opb1ou2RrGqmqrQQ998AREAdbPCS
+zaiqbmwXmjHLb25D1DGBfzl0c01gXQ2Ah3O0ZpLRH3jPtz8tllVJQXsuRwyIijc1EnW4eJK1Tx4S
+oimTQ8n06p20wfue+SK6MYXr+/TCC0I7lfF82mt9vPzwHwlqhzAeF7e3i/nHq9P/7THD7BitTwSy
+Y4KS4pBVKyGLwwnF3Rku0G4COzEnJ4oO6yOB7+3MpvMb/DuZrvAPGTo3xiKK4IxFXiOolzawHJSW
+QEY0Rey0yrdZ9QXZJot1NqdRgQbhAEuSE9TomkfovNb0OI93rgbSq6s4bw5SFN4zqmVzU8gtYxB6
+KPOcfEH/tV/ZpjeOQlI/u45g7z6vIDskBOVpMCkwfOJBhXHSMLtgTB9WgCYOi4C1zw3bVYYKp2h1
+ly5LWNKwQgKrKvp+cXMXucizRkKOV7Tt5ygPCUYrocxmkQxF8Bu4mTdS4oyUOKcOOsBxxGAun518
+dY7rogOrvdNwoGv7syiGO0/Vnc0+++rkPH/MH9iFROOakYs3AEhHHhfZotvzBQYyGTN5LUaf4Lwi
+9yice5KSFKKU8mvpACMeRFX3yG3Ay5D/ELa3B2+HsAbHC2Cyi6+Lp40MVpcAVVG4z8xSr/hXmaZd
+6JYZbIaD2LmLBfD5XBHUQ79YsfBXVevlZwq59PrNy9enFNLOvTj95tU7++aXH97/vpezSKIvxWUF
+HWHzm/l6usIw2uPFCnHk+5k8jGleFzfT+QTNMOYV3rfRCINR06H+H15+8+rDD5m8onIZ0RWdpG0Y
+fyJ07c7pgJmDzZzRjaOvOW/umgeZ/JHolkv04GRnfIudC8HA7RJJgGMtsPj7ssbhUP2VDQxQRCRo
+JDruvyO//cTdn2UdnO4t7EyEHvAoPGrbVV+PELnecZkcupKNJAIo+4KzensuZbpgnPTR8lCT6SfH
+Qi0QTKDhICNhM/luU6Ke8yzZVFQExqLnwmDNoX9TAw8Q2ay5Ex/Bs8k1Cg/M5kjdMDEXW4Ss7HY0
+a6enSMuefSg0JGxX32nQWP7X8QfQ5sV4OOwF7GFTY+XTF7RVcvqmalGmpfIqbKi8zLRzCTeSXSOL
+3zlwMFUkiFnU5ENabIv3zbZvbdvt+7AD9kumFxn8Jmw8IfOipY1td9EFYjfbTNSXBHncg/oCpfku
+sNexazn8DBsML/KrwsRP3O2TahyiXGgQ2tramfFmRYG+6R1urGoS+nMgMAcCNl1NEZGD+u48K8ss
+kpnt+ry6c8t+0IExor2bN7BnVng0UdttOOEHnVUn6dGIgZpX6j5ELtbs2E3XUEyh85Jui5xHzc/R
+oear3kk+KFBngze+D50sV0IpsKl56oxf0IgcGReNc4CGRta31hlIoYv/bYAH3OQNfXmYc38YF0PH
+lwBE1YI3DCmVH2D1gqKMHn6VxxbhiVZ4stPJ08cvLUEpdVCpq+p2geaHLmvFvEM1Gl9TqckU4dk3
+jrhXxIXFperg1GAEOqsPnWwUOEmswWV+nHd2+dWFc5AWukvIwy3hQT1QtJOZGDRzy1Gfrvcv6hl4
+EtjJxWa+nI5vZjquflB6wWjGfbvo7F9fjndkPl5cm0R1zbWW2OJ+cfn5axDXgupbYPtXccBo/A6r
+BJYUUZv1QpIli0Re++tzFsTQ88GvXv/m+fddzpWytm0JVEfVS3A0qHuEWL2edi5QmYB17UTh4Kmg
+41C6mOrWtFW/++blb06IOxYH9vFqUdfHk+rTFNhplDulZY8Xy21SskX+wyG2t3IUAWYADc0RMRLM
+3iLUbfM5IXORZTAwfVeFA1bhx7FX5JR6GAgCsF76TLGNYKgJF81J3pD6yKlIHpFBF38LJxIisLpT
+qG/ZXMWBplJZVCTM5B0uBiJSUYEy6ioQPGll/foHT90dhmM25VM9CW86jJzQVbBiQrWiVqV3eArv
+V5hK4EUuaOhN0JJkffAaw35juiN5Dvv0+8WGbMMVb52k1BhYSK/tMH0UDXMxh9HjuRkhu58bnCS2
+Xl9a2cPquYXFEo59AhynHRUMX4byxxejmzugYX9WaWxxUjz9S5bb0EsFL8XSy6Jg8TXJyySKWwwD
+y2yTWVDKxTxGX3LiOTlqBLklk7v6cUfK6pgFxotLPsD4jlaj8TqzzB4qwyCF4i2No54FyX4RJUPO
+DMOL0txJ2UGGs7r6eB5lcCn5bh1CpJ79hHPEGRhYi9O7DK/cZuPuMXJ7Lbv6WCDlFwRRLG75GwR/
+txGLYBkjlLoG2qOCnJ82UoJR0XnYwWRAl1ACwECWyGeYJYjZysBy2TYM0dkxQog0MNs+TWwbtpjP
+toWLDnKFfVsHq2EnB/ztawoVVK26usi6kUmAlfxKRKs91Pnuejq+FrA9zEKmWu4WqJTPH00LXp7E
+vHekik65a/MZ9bMLssXRblUk0NsHFvxgdSLkT1qt4UaZcyFTKSnaCP8grY8OxnYpsyQEpkmEa8P/
+PDt+SmHexDdiGZ3IPtsjn8ZbLoobV1Tc4MCkz4KabYfwnfQmtL6XawjcCNZoAEhhZe6m86+etXGw
+VO6L6qsOOamrGTOLnWOpM5SmMevmUBoZoUjtPat3iIl3LpOO+g5vOS75jMCTfYaT8xBkRZLZ+m3q
+1heVrIjqbSPTwdsfp5StNKnq9aH7aGR3EXIiyksH7evCrAO3oQEcR/423WMXH8YauSYnn5Qjo1uv
+aSdNI2XCRayRXSF/Kz5Z6Zy+QA8uICC3eD3XrmD2/EZO+FEJeKeVNk4sLIfxZhXzHRfG6px1rV0a
+4Bw2EqYlZlaazTgbkJ/ifswni7t6x6rKlIu1PrMtYJJ5MaqT8DuzCTuiTBjtJJ9MhoKKTMdhLrXQ
+55JUCl3d1r3iUYTGnZf/YxlPUkRg2mo4tudw1s/TiD+z/Mw4qAJJEd1L6QqgfYZGqiFubnNx4i/A
+SvMzY0R+RgGqcNCx00aw7zDe3jG7A6s8AcG2KTYXnsC6oaZRqK7lbFN7jp7vXvllr6KsQbh9afTx
+jYE7uUauPNIUEVDMQEsJJQ+uZHnyIYgTeCoqxSU8OSDOuJtiyZNA9x8Mo+xxj70DIe3XvEw9EhBy
+WuYlRMZP0j/8RlnT+LQwb+RRxezWquJ7jy0pP1Uy1oEKl+Rt/WKLTOaf1PeDl1lP2q4/U6fvezyA
+m2U0WF9usu9buYTm2jyaTBpVEmb45tWdZXB43DqUoYNWqY5ldYzjQQJTeqO/HlmNh2ni+HZ5SBMR
+nVvU7t1juKM96RePnvbK3QeHgTuXo3zFDCFPh/z8EvxFKlK5on5h+oZwx6oa9vOOtZhOz9aNfW7q
+hO1A8fOwB19IFKnxUJZvvW/jJ+Cj1UoG7rsOOX8sTxzbemDUcf3i4nIgUlScrSw9JSfEmkgnNrxm
+v5lAlO88yoxgwokt8NbXxduquxthqEQBLu31k7ij9prleBKS69JxX3GDsPHiLiCXfCILXX+LhQZk
+RrGaRDGbEezpsKYKghJc6FaLWQ0kvcIJCM2MJDhpjcfjmG6OuWZGUaM55jg2Ym6cQVgpSnXCJ040
+ucNbrYI4wZFAQPvhkQBZ8QZt7mZ10b3YajP6NJMelLxAR3Ex14vH5uISZ4eEXDQB4xEGcxjRiTJZ
+XwvgXTVaIWMLVziU43O9uehXCFwlmcriG353ovEwAg4MCUdQMb2BlYZnNZE6hOZAUb4Xk85g5md5
+2u/0Kr/BHQLXRZhq2hi6J3Af8A7oYcDCnGRXgxN6ioDJafiVJamliMA6Dd+cNHlp40dyR2V7zU72
+AlRzmAMq+gBm0GWw7ndAzJ0h3k6arQJNPn1X1SXqzuUgwVIIslPPnFHNJK5RF6e0bzAICBavbJmM
+RiSlHZPUBBlPWVLodaRGAyMbgd9N8UOpvrQEuQeMg2LgdwYJXueWSjJTKwqucWPB4huBA3YS2nCl
+E22yIb5cDATFGFDha6EyAxnN8GOwoQcw0BHIz3JNO5CjwLAYhHEtMSqGc+pACAMb2jVvm5r6SMq+
+ZlNVgn9BK9XkjDfd2OmmzeOiQ9Qy0m6PDMEd6p4tWQjIUD/r5CpgjcFE4kxCc57NrpwdzsW/GneX
+vd55wk4nY5zqfVnlg+3AduaDsC5tVNUu5+jtQg5YtvLZtfvS5YZg9XKIa+/0HXQxrTOuT8v479Jp
+ITBup57ssJqOJPHKB9LhPwgEtML70nbOr2yfzxZjx0TFxpdTuHzRaqdrPtDH4+huqDYm1p53B0GQ
+5EhlWdpzxFmVAnMQ6/rT/BcxbyUtRoH3o0KbxI9B672eFjWyotFwxr2K+sHj2Wp9vP7w9wpiNFJI
+PtiOBCv9cXr6//2WDOff8YvCJSmevz/F80ax+uaokSS1pUK01RYQFu9O8giJ5gv9gaGH1gvg0tyL
+26U+3o5WcNeceXt9h860Xm3Ga4PVpI/otVG34iC5SffU8WCzBtqLXlq/ZfETycLrgu0myf4QjTLq
+4uF8eu+/oQll2YqEtFaSicJadVJ8+/z0V8MXb354++Y1lDmE3EPIzpEj5wsx0TQYzPvTY/UUXGhb
+EkzJeES6GJ6xNdrhbDGEBHqYwBN+HA6puXreQef7RfuqWg/XoyvXzt+fvnx/Ojx9/h0ePLfLUr53
+UbTVPubPbRtswTBHCJbVXm6X26E1nWmHKLR41lGidsuLgWMx9x9Hn0btNBvHdW3nUKAkxXhpknwi
+3KLYlCftZ/tBffyghn+ke2iAjAX2sQQK4YV/n56rz/EMf/epzlbr7e9fDF/+7hSLKaFTMEzd4XBS
+XWyuMO4EHDrtMcnr2zAQlPj0+avvKTWmNe3AH1RUq/Xu5W/fvTp9OXz98rffv3r98n2mF2cnrFHo
+PusX/8SnW85m6at+8cwxcA5qk3cx3Eh+tVjcJNabb1++/erJMwGlLjCUt4jChRrUsvvZaHMvyKRF
+oooFOgykyf6FqL/9S4BzMpRcLowj/YqLvpwDFWNGgdGu4MJ3Ob3ClQsN6rZ5RQzJ8LTda2qWPAXw
+dRMJC2Vs6/kIyUSSCYrL2scLPY76X9c+UCO3wKuGOEhYzSGXqU9DGXn8FCZkb9pu2zSbrp2sNdX4
+BqFXAyEbY0B61FKu2AwKlmW/MMD7KO2Ss4qSo9LLn5+plwWfmQF0Di1OVNc4tUZ0dC6d25NaPWpJ
+Tb4GWWOrywkHocGbvFAvO4naE+ECcjbzjTjsTfMn7byc7AaoupwkIXSoF0sWy4/Pnp3HReI37sPb
+39NB8Or7l99kzQtDes7ReIZ44A2J6rcbeK/LuYxRkqN7Of8cv1Qq6HJ+dmJXhiPt0I+fuH68f/Ph
+3YuXOTeDbxaoe0esDaA1ozXbE02N9eiuWcgY62GbVHNJ+o4lSgp5oaOEmAxXcLH3YOzxaEPabezU
+5nBoqjvelouhKAPB2BwVr2pu6Ujg8IHG/CK9S8D+xRvrdE36gMt5NCPAd1SMwciaQ0KyHI/gLr+Z
+FSQyv6hYkMP8Cp3qVC2HyBvNo+IEDRxaNd6OZ1WZC32bJcfNW4u1846zZ5rb6Frhhs+xm/Bjh3NC
+QMHUlsKNqPoEwd7uNcIoZpQmu5dt03ZutMjMHBi7Lvy7u9S9Q1kM2VZN8VaO0u4Jo0xzdxv7GQ3D
+UXFKVh6EKuXiVhQzOLXrYja9qezaRGmMnuLAcpcctNGIXY9IbnS7qJHrvkKv5NBuhON6n5ApKouY
+JPiXFmoliUfKJ/T5BNA8nkXl3CWu/9EMmkbkJ0xjStNTjQS2pKfH8cMmbsdUhos0fYciUm0zBZjk
+OIiLS1McHKkqDlceWvrn2Gg1L8Km4zOy1DBoi2L0aTGdtIIdN77ZFjjbWO5E7eLu0ARsygZFZNq0
+mM0WdyTrnn8araaj+foEJ9A2a0RLBaoiAfPsbrRF+oLwQ7NqzX6R0wn3+c1S4i+jGRJG05QRsFOw
+XtxOIenbN+9f/a5Ty++CLU+x1IrIyTV0c1tGETgHTL+AraR4bvRyiKb0LgIau+Xj3QLFAhHJ9VTA
++Yq0zWWkHUhdqPADDnmo4fYGpU2u2uxJ/uZ9wyleJRAMwNiXfBfNIS7gKSx3rpe/e/X+NE9MjoqX
+UxLA4iSbPhpx92iGkpWtGFsW3VjmbhcmqUYJZAZvDtM1zNsFHD83sC4utqSzmB/jgKPuoixezYvm
+wmZ0wy8YOueu6sxmTn1B5FxmFZdT6yAfUHey09Dk76lNg/RmHnj20KIG+juH8UB6yPZgbsj6RL9m
+24bC9FCETq2EIPxpuuRgWNksuqibPDWj6X7+4sXL9w2wHpa4kzMEWQG6lgsNL5Id0PuihjUeYQHw
+Fy85jSjgalZZFPBnX53LJROvoAZLaBzvXLe3+qZUe+a8XqynGnuHw/Be2nnAITkOh6RfvOrcFlcL
+a61K0Mds440MxsjQPjma1CgaiPpiucbAZGVZhmEoh1gZrl9Pb9CxdRxQF0iZvUdEE6k0v5Hh0Bp5
+0zDMExbR9wOemHs01c0j8Ha1uBhdzHBXv9/CQXFPdKuQ82IdGHAdcBPJkFHyfESspKE7VGm44obT
+qMGEL3qHsjUMYy+TFgierCt3OIr2xs+BqSiUKFWeU0mF7i/phdxwlVKK3qcVDBgBmuL1+6q4m9bX
+8Ge82MwmxR83NUfaoYsKVSTRTSfEgPfJpXlIMgQg6nDjsuGqkRShuEL8EWZbIskSqPqr8tmjvlwS
+oPw7qu+iogMXixc3akPljpDGB20oLbx2BMqkQ4gNn1d3OkBhh5OTFFKVrjs4/ughn0Qh0b2+ukWO
+WHuhdg+4qrF3ZaZkXhNUtp1XJjelhGItfShYzsW4grEa6STB1srHNstTxcZwaBwozp1+1Ay5Cnsa
+osEWTqvx9ZxAerbE1E3ouqp3Nv6rCldZ/sDzA/8r+bsverwe+uICz3HK2shQorc0rQqOl05rCXYR
+LAIZJymDL39l8avFXUXyRzKn6iCXv17PKkG6K9ApiDY2Mq6vimtYkiZCONBQvWaOOOp6IRfLaNnD
+B2XYb8ui+77SUtQMDPlmwV5XedPoYvGpKnn+bqmmATpIdc2wlvS+KwQhWJc+hjHRofbdRTsIH/Dq
+TcTSwTl9ADPHwccP5VWO+Ny5JnM7MhmZ43yjBeWoYA4Qex1I2WDg1zk7mKMmThAmxn6B+mCyKX57
+wNi19vvuu6UejaREA1UBPt3luoYKuxSsQoGjf3zTbf981u7zxJmkon0pJ5vbJW2Sy2VDxKkoUHQA
+LPDuNYq8f1z9OG+XFJ0djo/N+vL4ZzDH/CnzQeNP5k5bL64+hSFdL6xPKvNTDy/nD62TKi9cuDuy
+vNu5YgdD54Njz9lRsr2KluHL+afpajHH9R+tx/hYRn5XjwGRy9ciScf7KfI1z8p/EukoWw6R/RLc
+5eFSC136qnzad6sK9YMruE4XjHEp2ihxoxVBGaz1WHWQ6ZrcutXX+N3rfvEa1Tuv0+FYryrMMcLI
+Jli7bOVgQAzbYnGev69EiodxfjZLdo1RvgaGVmG/ygY59kjJEFV8kucm4iHXtSKChy62P0Nqgvjl
+mAZXlLdc5Cjmh3TyFV7NWMIwE3aY+swK0Kl4QtPWvthcSe8TAQkKlBzzybzGKzliSCKKdtDFJQep
+pLW+rmazveMm/Tt45MQnWnbdLobRc4rxJkQiYThB2m7w+iGkf1hGASv3qUxFNKoq2dUIr4kwHbNN
+jZ4YjBCDpeOZwbgitJfUkYtOZRZ3mPJWAvpQL5jrE1nYXEymiKhFd8iISZD+9zJaSGguHhi4s70z
+Q79gxxCVuUxrJ5T5BocrokumMHEuJoGhyArHbNtFnm4kq2L3NyoPqXEhuxqle/6GB0mHzBnjv49E
+90gWXoThupxOuiF0a67PUkokx4USxI1ZE8jwKPWW25lKCn0JqGrkrbMV6u0FcdBMccRjf2O7osSH
+7536FgerDReXC+hrjc9hUsJAmDuZj9U+5iPePxHZjPnthBsKGSHH3Y7WIzx8lnz4/CwxqWo+fZou
+hkeMoyPRZVl4CI/oHg10ZYI6RuJYgyWPUFioscP29FCB8zPMg7/OTn56rhodw1rA51RgzrzFZm64
+CyripyfniG+CxTC3sb8XRLGVFSEghMtlb4dbIi5asgIpX8CqQL/DXsrojZB6E3YlrDkMlGqFC00t
+8YRyHxPEOyA+koBrtPGNndi8cE6DEmK9FtgQRzcj9T0C4WI0GioRKhvWo0vEQ5ZYTdNFqS8azF9K
+tHtRGxgXYgDIx5zd+uGWO0xfy76WDwhaBvdr8x3o3bQeLlZhsNx2lywj6AtbRZBNBP9DvwX3xZZE
+Nie9ttRIhlzYHULiX1XdxZL8+hFiuUYgnCWGWUIj46GP+SShAcnWF1Oo58gKg3TREodSer24nF3W
+j4gzKqLxVVUnGzSPgS6ZAivRBFs1VGNRQKLprLR9zquZx3CQwQQP0vTYu7PpuR+W6Af6q4XWj1JW
+ozpblz8lszOM4warcDMfrbZAFZCe/lkip6/L14v1CeL+rdEOoe9ev2KMu6L9X4LXH95vLuDlcfjy
++WQCLx/By9ZfWq2L6XyxTOr55XT9ZgWp/s1khHe/QwuI9r+GL5/Psbz/07z8/v319BKb8/Ofm7fv
+9O3XX5u30hrzRhpt3vxA9vLth+bVN9NP8OaxefPtbLFYyWv7/ocFVvDgARDNo6Kqx6OlOMArjhFt
+wLXKUzHLy4+QYzAwhcC408uf2JffUxeDFy/xjU3zHXU4eIFpvrZp3i7usHe2e69qeDMNprjmuecF
+Fcw9vp2HjaWXjCJAs9xSSyBUvnO0MiDnPtTqeDEbLi4v68qYL72Hiwc5dWgeG1QdTX43q5pilzjC
+ygRter+vcNkibU7QRlpCF/Whk4lFKnH62hTGF0vyVRxams9BVxj9EdgNU/BAksTDqOJBMaQ3Qyyg
+pk5GhyF1ntJke99yaRoHyFICTNRqsDmDQ4unelKJO0HvJAid4JG9Qn+HbxFLkrxBc8fkQ0j/MLj9
+k9wqA12AByoGvjxJpJzsg4SXmEW5y1odbn1zbgJe61QHraYZIwZ/WMOlVzRdIibCW93oEnVxo7kV
+9k4WY97RtQiGLjdrQu/WIn1jgHdDYGF0VsVBpJ9dI0+VvxjPFRny4RAY2X9Zbof6vt3Lgqv7stqN
+FsBtLopCFIxW7Z7x4ydxxNB1Iz7l4HYceDu77fAkjN+LiJDC8KTzg/xoUhH5xceBEIgO3i9XZBKZ
+t08Js5SC9k4kfL3KYRpAlRr2gRKXdU5V3BZbzm/evD4dihiGdjVkb1KInvr1gUqFybRGqewkJxco
+d1ix5DCAcJAfDcjuDhrQK44jz/SGucvgyc4UGDc72Gwz9y1wmKKshlEi167i6+JJ7lpQcBrpNtwB
+2n7N54zV3ILhokMi2mz9g+sO+v/UmgjTDpXdw+3untHKP1eiNkhp2+BJVmtLGkvMS4SWd+a5VdTQ
+Mj6DZpzA/0VFgw2wNzOO3ersaVuW1FNLoZzYJ52+pScDsaQT0Xf1Es8NlnpcksOFPRnoTfZQyHlr
+VXxC1E3GXOjkHISIj5sBvLg7nXyobiq4txPp1t7t+KAiLowGbg/sLWwzCs2KxuU80uXO9NCJkhA9
+JTQeu+lSrTvsz5rV9LZcdeOnwnambu7z+9M9HXYr6IDqaoGR4ZOdVwk0tJe3j+imq0Gb1EhvvXkn
+814ibQPas2JjOrQnx5OSglF7BKbGwpLdEvd8XeSbiVX2mlauHS9ej8ZRG021LmY54NrvSDOE614T
+BVzHUfGBHHAtnhbLYBysdTGdIKg21Mmem2RbRs7E1wHZF8sOOtF5CFSIN1dY2lLbMCRcEgd87BTv
++t31NNQTKwOHSmAfMQsm6WruwqMsI0fU71AY+xDfP8SBQAtbOwDq52RrjyPKeV5OmyV7G+slYo3x
+nMVlic9pjPXT651Lg5IeZPJgqOog2JhEM2zs2AtyoA8EKSjVJWxSt3YbAX2vqxnGhG1r1rZU4euX
+FNa34GEKz0utGEliZ/jLh2dQOawKGWvXecuxhYPgWD/Y+pLD4Rl0pSS01msLTHk+txlsbGYXS+Pj
+oUsdwViAFq3YdF5Y0rwhBwnGnM5Okqo3w0NM/DDouqTI9t8zv3v74EfAFtgvdqwhI60aIk7cbX41
+qaHvin2fPn/f2npcYfWZezyn0EPLVYKB9YDkbr5+FKjVbQvLXV+rLI/wcO/zgevyDWCXnXgvj290
+G+/IaqHBF8tcE1gUN4yGMkTwkepClsd546yT0HO7++JzBV4uN9XWcY1wQ+jC7x4xM/CAO1IBfzBd
+19yMpE9o1SKr8ht4xOy17BLNSbcKBK3pBZkl1y+n8zcsYqXB6Kt4CDFvTB297EnBCT5/xaHHlISW
++myajHV+GU2+qubVajoeWmSUiDWFjf8rsp0KOIjQJkeEmKQQgsYExELkB4ZDYNbHMQim3W5RyBk4
+D5C3Hbht3U8XlqcGpR40kLAXo78MmYPVoDr0YxiKm+RleVtfpSoMtgBS2+KR+tyWwnHhT0Yamq6z
+qo0zKf286UQO2XkBeJtPhsDQTNENotvEYWQyxmuO73Ts9ytIar0MNcmU5Fdn5mOOplnjv9CHWbWs
+F5v5mCDvDTdiMDKXQ2fX37dk3/E2tGJ1rtYBDBtc9NBGCNaitFlnyZ9gcFV0UAeub35DV1daGYnC
+UcYOJEGEpkgHggYexF69uuxqsX2qnyL3WoWj7WNbBgsJiVUGuQGqblGfr8cvkkmTzFgT1VfO2z4l
++1qKIYO3jtQrR5WqpNBqqb7qWcOwlBdwgkjSmzZwA9X9WDIRQ6MFwdBAQ85TfiaC6gwcdJ+cF18P
+iq8yOKhDqYMwnTDOYlxcepfclS/OjZPpIAEpX7AUZ9VoRfO1WGFIHr9h0QitWqsp261iH5XJweqy
+nEQg2Wbr7zghmu+uSUAfV2QoURhTHwaFOZJcyr6Zc2x+ONMZKPR0e1Dxdsy+nd6TfKiYb24vYI7L
+QHRZr2+9Z5wvLeY8jBIDczhqX6rISX/HYvUUpEeriA+T1z50XcRSqxWAgB6rIQr5NKLYzllHkMRt
+Ma7tNmBgEOHY25QHZcm0G5p2BIJy7ShEAgjvK2Wx9PK6OdI5p1KyjNaaQT2pKtF7KhGi++h0guiA
+qC0+w671uXHnAa3T5fTq8uX9soslyqGupzcNqBMTu4Kzl+dGfiC6AvKs/RLOvzcaaZwV6kFUo3r4
+iVZ70x2aOEMCzAy5FVr2yGbi6Gb3AKz35PbnSoP7H++HBlrJuny2aTHcFHegXCw51xvLWeoxhzza
+IFnMbk/B6Te0aTInIkmYcW2gfFuqZC46lHQfxBC8FVMqAihDE37gL/tolb1aH4+nq/GGaCIqkKpq
+Ys3xRaL5KZRmhs1JFBnTjHst9ng6nxNLlJGe7uDI4RjHc79vyogO8mbGyWdJqeLuMZOFKTYVAQv0
+KUxlD6PsDULWd3KJYG450lbMpEk7eAjLfsTeOyhLMSQJmgVjZYrdQYn2TAOqnLoUfzzx/5kWP5fl
+mk48Th1BgtV50fuwKTyjZGzgBvFrugD2LbBGPpEX2N61FVwaZKuHqytNhtu8tWeFBmlotgy3mWMN
+eQO2+4WhZTQ6m1u2QIrY3B2rKaiu+UobLGIhlLsOgVlyCOgs8ilAVjRZoCpnX3NGT0Bn0d0GVe1D
+c4kTIjakPao/0r2qRdD3XRdfu840U9/W0stfi7XdD4qubUU/PQNJxiFHIJr2WAHU9vZigS13Nj9n
+9NTQ91l1uRZBiT5G3ebc+NG0enp1rdncczYffW28J3Uf1AX9r0dG164FfemGLX3fiPOgmP5ot00h
+q4aRDyz2wrF27FifKKIZaXQgu4R7MJwm8G9mBDB9id8MD7G6ooTRhR+LQiFw+pYDuqXv0QwclZia
+JAf+jK9FFFxiKSeHnEgUfThSxFHbPG56FETe9UlThLMlsr+7xWriWiO/D2uRJGYWIW0bj5AlwpLB
+ZYTvuRMyabdJj6LfgV7fQ5M/bD+OfjqiOi+5TgTZ9rSj/bC5Zu7tSX4UGivWsIB7qs3UKwW2H9Rd
+3aVutfcLjOPHlqiuNDPI2K6Yi/CbRtdV38xif59KWMbX5dgpf5TqgzTBNj1IBOlOiQ1aAPjx+HH+
+5wdYJT79hQZGi+8X/immXJ7m+PISKae7Xoigcx0gtqb225igHK/v/Ynaa0bsDqXGVLYNrrTRYOIZ
+gkb1RNswT4x9F9RgCLOyyit7ufqrpmZJPG4wJyVPS7yOMWXDTPlOm9Y2HxfJOSF3aTkq4FeCu7nz
+kkAHF5XecA5jkfExzIyUlyNFl16+ciHV9RbcVAyZcRsmAN1SFd/MXzY+BXNFhdHlLajWiJPxOtJc
+jN5W9pYzxckMzc59o3loS5JP0BPbbmPMqTqkWrFMfXsbvREjdnypg38eX1aRe0A10FAYMmz2dB2T
+33uZOXpKZ84WkNwKsQnOvkBKii5S29uAncszctpHexC+J5zJ28zNkLcL814Z1st0Jc2bVJG5PMq2
+WkWCJr/IoRd4f9Qenx8karRXYrPazqbn524nr6KW5PdVZs4iK5TltiT3qdCh4JLcFlGJ9AkuW2TA
+El625LwLLlqxL0a7v9cgCXt6ulmiEQ3MaXhT+ozMfmN/cRHiKfKFuZ2jSJboY3gXu7uLr2OwQz5d
+iL1nuR8tgTlpc33nduoCqASf1oImHqqTbLrqigjj4x8//C+wXNhlv/40vxt/vDn9xf9LEMAt+H0M
+y/8WiQeiy0wQN9HGeSd/1febC1GHFL9drG6m86sXiyUHliYHvvef5r99IcVQZGmNWIeAWRxLAdJZ
+7GCMdEYYs+gzhruD7i+wi0YrA/WraMCbC/GQZO8n7Y36OzHIUqt1dPzl/7WOihcjjoGB4oF6TWEZ
+yKodPRqRVFJshwm9P6bIDpCne2W1LNDrGsNzuDg6auEwDQYVVsRRi0Gh0TW3uF0fo2nRX9d+sdEn
+IAJeYwhhIqJksewgJFn3y0O/ywvMIMitXNg76OrLufOayoB4b1bEpXziiQSamDIWkARlHasIEh8y
+kbTsU/jaFQMf3bMFpq3XmcC2aiKDc4P4qP8MRwefHV1tQ99V249q6tnuvvDjh5EZ0KgbXzOaHaxv
+BMFGc7PxAnZENbGrhNcEUZg5gW1MV27l1CVFzwSeeDohGD+oHN02OWDaWBzJKdwGYTAZnAO3+MQH
+ASNrRd6vUtigePaEwumgkK8WDwUGKbgj44kr8uMHJhN+kjc6lkexkbSSAyGAqdfMr/jYU6hpOzj1
+crNuXkIZTF5cLjugeINIoG4J5fFmoxVWsvNuK2CucG9snSKQOpAI/2lhDzgprrAMQB19yi/pfNp0
+V7hzf7maAiVpo7cQtgdFophlj/l8euRw1wZ+c3dzmzgX8QIGwQlRMGOYSBvIKWRruFYasyAz8VZe
+tbiLJuQL5sPiD7h5ydvCY30/T2bokacNsKMaXD2ko7zySJ10e1tNEKmneLlezbeNU2NdLLV1fT/z
+rf1pj5/GNE9ftxwlYpruiBl5Lx9h+AE4SJdyYKJX1/Pvv3/z25ffDF/86vk7hCVvD4vjxz/+OPiH
+8r88etAujkaTiYlgjIbd8woPYbQ0IDCdNcGUtppjm/L4hfU8gq8n7bDy4a/evEfU9Shl0fmXk454
+DMOygR4IF9KFv4Ozc5nYwKtXRoXB3gOvf1iTMejHJ4EEZuaiHN9OEC2k28axOv5YHB9LfQbe8hNC
+i0ytiSIW0ilF0ASfCXobXvQQ1t0kq1a6eT4l9/ZP0kv2DR0Ka46snPYRHiXEBL1Vr2KJCBGM/0+g
+PTT+JmpsnN8hxnT+AaVkP/74D53A7w8Tqa82Ghsggzm8GJGt2KqmMiiW1eKukneDYPKMy/aYtu06
+6I7KDMtpPZrNN7fdaI8iHzudh/7VY3bOMVXuyWNBixLYpZYLWQ+94k55UgF83fXypkeCrI8btC+r
+UYc1utAju7qHTQFn2Aq2HLCuV5vpZFHclb9QNmq9QPI2Zb5HlkT7BH2CFY8d5w7TkdMUAjaYEAnX
+C9RyQX5BrYYnXVaPOwGi+xGDVXrcRegM7dla0XkQhYoqGi8Y/7cOgCGys8v1pzu0V/wYh4PM5peW
+R0Xkw0j/BuVaEkdaG49tF6Abom49omDDv+4/ZfLgrqKBrbt8cShdoGvP9+HPiGun8ZXcMUPvo3Bh
+/BbYf487hpO6woU3a+BZbawu+sb8MuMPrrddyW012f2ijYmIH8QrB9zh6HLX7u1llHOxkfHuX9Wu
+m93pfDzbTPjLp2M2k+rtCzNma74e1deNPDp+DKJLmkZjNEzmDR4+vLmLmj1mu8sROkww0rbeSXUg
+aBCK5xj4/FMHNQib2zi063Q+mY5HFPeCHH2U7w0NakN4Z1UPaYE1t4DN7RYbrpf31slJKzrEr9fr
+JWx83FIoDHyMp/RjzPCYUFqQzIYZ/q3hgvdvxoeVAWj3CjqiIv+tSGIZHZCT6wVSV312bleC7aVd
+R4uLPyJUD2O4DYeoEuFl40WIPZtY2OObO4Sr6dI0+2tdmHK0IdKpSfGnpsXnXisazL4bnH7QWRSn
+OxMV3IsXW/QziEKrt7UUly0oA4oIEbI7+qmDtO7mLuFlOza/JEJ624GisnnyFFUd1BRxinc409ab
+u12CqeUFjx5cNySCZDdsUzhMsRx2nebGltNoJlY1mByvzHjcwrNl4pGPytyrqHz4RgrBcAfd3J35
+0UVfGugJp/JOIGHDZO6gcQmyc5QSiLsuIgwdZmc0rDaC1YL16KIxoh+P1lOjeGKJf9w41jw1O2am
+ubQoq0Z5v/hjeBbJCpZAPPAYEVqUEvhwBkTXLNJ3WRQdIIUdDtzKZ0jQQJJ+4dE6wtMQtR9UjNLI
+koQqXOz/3967brlxZWli88fLy+m5eM1Pr+W1QpHmBEIEgpmUVFLBAtUsiqqmm7pYIru6J5kNRgKR
+mVEEECACyEtd2vPfT+An8Qv4wbxv534iEklJ7Rl7NNPFBHDuZ5999tmXb3P6U04N6/FplrFAuKF8
+1Jt5tVGDcIi5cBnubbMjoGkuc+txcubRbo17MuhfnD1/KHP+uay5lzFv/JgP3q6Jc+WLTBoeB8f1
+GzZCCa9D/yxbyYiCZ5V6plMROOzqlMaTrtpBajAWyRODg6ZcNr6NaWG3rI9tb9Pc2Oj4dJ88sKpJ
+sulKvVAJgXYzKVhsKCshsruo92AsS6Hem8h1ZT5n2T1Q6PuaOhkj3pT+VI9Po2oVtarOZdGVtsWs
+buddEu4XXiR3NhjcM/0T56sTDcJyc1pJjChrCt+Z0RBr9Pi0pN/q/T752beS65f4IpsVrgwet/gv
+U66ZmORtcqm76X1jgfsDo26fSBp0/KCSivo/uNnmV1XnZDRCEKdY1Y2Y6nQIRZ4Po6HNOwQFcXpV
+DbThhNC3lXCeixKbsiQt8cntTlLdCzgKaoc5PmfYwLuqzfwcFfFc1eK7EvNG80DsxUUJWeKWTIkn
+8El4mGaItpsbFj7NA37qvITgpQuiCpa0nZTkonfF4hinywMThyvpqg3jJi1VPDw1jVY2jN92QZdX
+W0o6z0uOCTRX+q3q5qImjxU9cNVJ9ARRUXdAOrm3NxYyaFE0v3TKqezcrtUo7c69ZO0a+pFKWqkK
+6z/FoCESK4gdi6gFIDxXb1HILNr5XmZs8wIbMb0ygGh/t2Sn4bevyPEERGoN5M5OqZsDBSF/WW4o
+J8JinSyr7WUzt9kYayKVv9ByHh58T1mJZQ6kbdEb1ov5srwBcrRnduhRFZSol7ulMXOxwgHnRS20
+ycBmVXRE5RejlDjkcV2Z1NNX5nsDmUP2T2VEmEquazK88wJZIzQNwgAHdKSwTMFaCPSTlgfnoXMT
+XNkrAPTOtmQ1t751sKzOI70WOHRLteFMl/VEgfroUFzOIjxDq5Fk5Kb8IVoEMSIGuPGiAUn5uly8
+w6BBlEq01XGEg1OXVa0TXB4aPKNjbwW1av7Q5abOutLcHHLJ87DSGvtEbQtnl4wUKHXqSUzRQ/n5
+vHbEFDAQBOBh4mn+C/o6jwzZGNUOuwySh64softIOS8JXizzalttlhR8WF2r3U6c3WaHJ7poOqmL
+FZkUBFhtWqXFVJ+tk8rQKIFRNgqF6rMMWkfhG++QCkQIz2Iputa3BcGkF/35Np1zd91s3rW23ZXO
+jPPjvuM2Aw7z10dHSSmaO4cZw02LCY5OVgR7FsiMf7lFx9aynz8fZ4ScueznjvHnDCpOC3T9Y5KA
+abneTOlWZOOsOpW1NqJv/DdT7J0UqsTMaaR+5MCpTg6Mh8DG9IRPnwMR20D4FABwslUj67WHCef9
+wT+OHixHD+avHvzt+MG34wc/pa5pDast31El0552QvkBZBWM9CR8EcICMVaJMsFvgVWwCRZl4vNq
+S7nCOUIRWBtszE9XK+XTpZyw4a5clH+qF7cOTqrry8Mi6Lvqlr3WLDZSk3rWKXwyuJG7hNjWDekk
+peqpB1pgcWb7bYFJnbfVUjeJWCzjQHyUzmOFbbmdi0cdPhxBlKhXCaNOI9ZM27Az8cDuEl351N9Q
+PHWlBAnfMB4zzEoz2ctn06cvX06eJZlNK/B4PziUdDIg/qGlb7d6R7KRpGNom8VVZV6RKBSAOKos
+I/jV+13DMa9tCxRy8OLly+e/f/pSW/2zj5O/JG+SR8k4+TJ5knyVvNkmb1bJm5ujM/yfWfJmkykF
+TgInDSbVtPjywB13GuNJOV+BILZsrqoB18gPXvz0hxffff39H1QWdNtnQJbmAESriynZeafzun1H
+7jCFSvCxyf4JnlqjP52+Gb95k3918k/j04dowYYiL3LbXk3XP5mXZC8Wi+qiRInJGeCJaDHatRId
+bFkK5qpHbBmuuSk1t2ycBej13hwKTpzbru8ygWa0kSpTnoDnUcbQBVrmxrl0xcjAbClt165NHb9m
+2GVRzhbkr0IpoqxqMou7BqTWzYDePaDqONAMLbT4AyYjEda9vZxum+l5q9d/mJTzebmd4C0p0w+2
+qH8LqD6RMv2KgtdHLpenqtmD9m8etDSmdj3UZVVuD9VQpNbfPn/6tarnsOp2zdOCU8U5tX2q4nnK
+uIOJ073LDeIhrNjbBP01oMFFfVbQtz2UxvqfSQc5cV+W2lUNhv8wLh5v3qCPxyOXTKmN4mLT7NaD
+Y48udUvZowetrKlbPtL43Y7XNF0Z9gm6Vrtt5mMHsyZMBK5GZbcTS93SU1A0bjEiMpM2hMTfhcQU
+7c0hJanpkBNJcuNHj9zGc8sz4ekOiIftoda1L3wAzh4plNCyacOgk1+C8dDuueF3bSXGTkwFi0Zt
+lRQUG6UjOuQkGnDU66vKPrTGn1caQccU+dO/7rltOhb8pwc6pbtE3HP9wS1kDYOBKdQnS2tSvqvg
+5dZQjoZAmN3ZcJVqpIZuU/Z7SjNbKQejnRtJgcfeW2VD2O2WoQT9ELGjQH+oFNPZaKQGM0lB+CRS
+oCpDN/aAR9PXjhqhaYfreA0pDa217n2trpoRFhlR6SzekrUd/U2tRlbRLJCeMhWguUGAnH29vL+U
+k6Lpb/KgTYqieGL8vRWh5+gXeTM9WzAtOJLEm/bjwZv5w5z+/elhngyKj/GCNcfRCWro8RZahy5B
+IKOdVwxtThmMHrmau4b8Ma85mAIO+LquLJ30iy1BiItWLmnrZb1AoCfJa7VbzThRONzDkuuXrke3
+nKUNpTloIy72PFvUCFbouJGz6xKLaq4NAN0yZhhncz3DzibshEQ8w/PUZkuA79IBdR06soJDuUVg
+Q4sIvAr/aDRYKCbOYtgbQhlc3jVGz4Q7S1skoTul6g4fR7SqcKU9rjbzX8wNcj+XNxmqhLyphfHB
+HPUExHdVT0oN1i0uXNbhr4E1w7gTaLczODBn8zK5GZN16cZ0m3ueaOJEhj/pd+5VvKUbVhvA4STe
+MjnK2VbhtKe0Ya4zW49RzdYnWIszQT8GgsOmCsC59Y9ZAGHb4aJXn+tGuO9sCqVU9fhrU2JsLLV7
+6Eo/Zd0tKZTxz0NxKxyob0TZ7Hg1hWCXuq2hnYl3inZU3pU45hjWOPgwV8M/PCPkfmdvPtBSoPWT
+mItUdlanetKMtZ69W6hseozuSLur0Ne67B16qznVKTZsmXiuVpG9tlTxKmpLOXtqLfwfno0ocYFr
+NOzecGlPHVPpWG2yQ+DohNl941HY3uDBhiEOHO/J5DAZmn3d+xJVBmTrYFtVUbJCltEhWinwQBZF
+u6NybOcDe3uwXuFJb3b3+DtM2dDUkKyi/mUjBlj6hzKvarRqfOhaQpkNwcFL5U8w7zgqOArqnw3Y
+1hi98fkGbjxYJxletSztQ6FTf+AcEK8OEFJW7uRPIZuxaVElMnDBMhZa3lJSoNOqQyu24zjG05zX
+NxK7yOiBVXIGrBmTSF9XAuBPzPMary3SVVrh9JJkxNJ6ISxJkrJAt+jJWB5VMSMA84T0YN8+/+mn
+p79//lPouHLZLOYsolScO7GIavHIJ0CXOYHf0Q8wexY2yFFzkRAQn3/SQ8/PD2gdBxxZ3LMkHAiW
+vYdrCmZJ9xo5CHXuUUuWF/gVy7DtXk7bDSfirlCHX6APxSZ0yeJSBSvf8Ulw3uxW8yz3H9Su1OPZ
+BZilhF5ZduPp88dH8N9vx+nPbhtjHZxxk+GerSBq5B15L706Cp/5nnWvjz+DqTwe71shlfwZ7PSu
+E46rlcjvXgpKcB5ZCpNo3HYS3dk+ENc1qSsjUXp4S/LP+Mpg94/XP750b0RmQIqJZ1wepKYTaOvU
+4qEkdTd2IKi8LEDu8Xk96UGkPGdiRrmEMtsj7KlI984wQmgqCdqM3liWOd2OVXYtvXiviMOUT41I
+Yf3RWJ1ZVbzgNvLpyo6LT2KuzzhMDKEjTVPaoy2rz7vb7Wn2wRxFDD8YMc6d7Gs1G20yAaZnJ7JY
+IRJQOqhk1mR8y1sEsltjTlshDySKjPRrvToqJBSuZz+vb/lS1TSr4z6SAe3r6EmCTecuBYF0QBSE
+k6MBnAYwR12KEKyqoasCTUjauQw79DDHytYyEMS5hu4hXyPKqldNsuvMmzrDoSuPJJKY+YRQUu3b
+FlfhehY5r0Zk5u6cjpxUK+xacadfH0oVmm+xX54oIJR83e8o5fm6WSK9jOBjSUxCegjL3816mqww
+bg/KBxIsAp0YBzHXXUTr3yifAzEd9LGH56oXIsEF7F7CxBXd1enn5TvXWyF4mpOxnjqwV5wDpCJr
+z0U5yL9kCXKE8pjywOdbKxmc3SYS1QDvShd4jSgFDgLMAL3plSd9GcRBkTsIby8dwsyPoVrpmAHk
+n8ANZzAMPINnGMZlaIN2NeqQuVY7RDLlx67ki3sk6xuqjtQvwvyq+YStMSEXWxflfB7g4fLDzY3w
+IFZG4UToBzNMjuI4ZusOktA0t44QXC8xreVMpqn9nTtsPWSjHn+nfH/i51Rki/8QP7BCNeSRSxP3
+PWV7vWTtDQuIPLxNzGMro8JZ3u9+S7ms5vPYGx6j1htMTbY4V2rWUDahnqBkZnELMeeqy2Y2OR4y
+zU6OAwaHJeWkoEhgEzPIcFWBIYizjJPTAu27xHmxatDxEl+swGQREIQ+Lq7L25b9wgfqGdacuzLK
+CsoubvFOo3D+almutvWsw5tZFEYwkiFpEPBFx5muafh4JVkZdNO4ycA7RN5ly09J8pmeI+SDLPig
+XN0uYZJfAXf+465VXbrc09Fd0kYqi3reB/BxvigjYh1tlGcuxIKWMYKKZHmMErhfONEfUyVbRAXR
+QUhiWyJ+in+GULQgDodKdyrhZfKKowtQPYVvZrz5hxwozz3lDnGuTD6A6Ei4hPEWtQaU7DMioglZ
+pfuMDPbvXewctpRMD3/FdK+zxQ7JLFdZ1zZVC4cUenLErZ1x2dYCEbaQ5UF4kBBpANJxmACbJlAO
+RA1hD0x+GVUqm/sdKvndCqM+VlyZvChgdWgeYkixtZ+7Vdf8dyteAeW3uqCMHNzQnZPmZuPThgpO
+hCRUGGf5L7EKOt/9APo4+XTsvNUWVbnareNaU2aHq1uaXcvPs85dZuCr9pL88M7Qc/0GpRNSQi9u
+P/roo27FEb/OeMlzTwniy2at5c2OWH27Vj0z6XHQTo6Yyx9RnBOaCxetI6NZoiwIw5TclSj4J2pM
+6aS1bjh0wD9UsYWwQ2dN8w7Y23x0BstIcYb0zeV2uTjE+P3Z5eiTUQsNjj4tPimOrTbs/x4/Pjrm
+P45/+1h9+cfdMuG8Ge4SH7gRtjzDu+xRuDVyTcB20ANWFi9P0n4rWNqsdD/02mqT28qOew6v/cPj
+4rECpWnHZpSorRuN+KIc6W99H1ircOa+12e+XDJzysRg+Gbcp3MpZgce0c6bqiW2gy9LZGUYiNIa
+1wv510oLLGwqsv6HwSRiM3ZUF0y4ntqCv6T6u74pWgWtZoMjBncCFuFNT0ZXcCXcLBcJuQXw8BKF
+zEkeB1GakL6GLHvo6bj3eozxkWnog5SbkXH/y4+YSKlptjKKSfKHZz8Z1pMXyBhZs4wcls02veiQ
+dlv/8O3LezWnogZ0G/Yb/vzc0qpEVG06Ng+L+u92dji4KNEQaaIXUC82kEelHxIungsUwoSddQis
+MYWdaN/wFIVKO1u5lI42idZe5f33K85Kq5v6VKHkONILokIBabhAGAYoPhbwBIDdjKWOGqjlInzg
+JabM43TleRwgwxo8DZzG4/jRIIKpu2hUBtvExSRpAb136QvnvQjMSwp5BkqlBEWBvJz7FQV7eKC7
+kQm4iXOCU4aQyWZkQ9O/jwu0JD8d8dkRV0ddMYwPB7pY7gOFAQuxhtWk1F8PKLwM5Tp2DNJ8XQJu
+73b3SKubNdzWILiopJyIUkyLEWANX6m0s5jzbcnuju0gBrWsSHmAeZiQilVNmnos8BgqMbFOccmY
+pHw/p+LjZ/T9tjKBWwl7PhXiO/3196+evnyZW88erCAsYtleTLJM3sTB+4d6JC2BQpejeDv7HpVS
+bUQMrJOLHaVrQmslvWu1XDhHvexZhUlHEsyN+dVHXx143F56Hy0RLjpVr5fRorlgl9X2Iua8Nwxe
+EYHEgO0/hA6S0XfZwd7sP7hM0XRHri7kGEDm3sB293fVbeQ6I/nVFfrDU8JDMRsvhwXKRtUnSFRL
+423rxtu2TgDwUGHtx/RG+Ixxom+RvXOQRbOKhStSP767EmqFMBnPoGf9UP03Z1VSRh14eiGlF4vk
+3rB4pkwvU1NDXQCGVPGTdp1r436voXdutBP7R05fBEvVvUJWqgIz7gs97tjpJ2wLDOXFVyIsX1kv
+8AytqmtkGO44gRa7xwk/Vtvq5w0V2viFhqpjv+WF1nX1LoFd0hv33IsGR4LU33BkVHHwgl4GKEuw
+nzMpqC05RwdWqWZBsGecZ1Jr7QiPgX6BxjxdaOTJEVkhEhVGP8aVm+iRMtUsk0LWcUx6HfaAEY90
+5/WlLnwEypCYnjerjjInN0r7YCK86LeT4/HpaWwKTugaj5tveFuPdWVSJMc3FwsYlxT0jlxdKMFK
+U2PtbeYcI6EOLHVmoK6ObRGLTo4ikHp39ii62h01s947+v8bEHf/FeHuHkBKZDdyqcd24PUsm0gc
+RBY9xNdd/Q4rqi7XYzH1EVs67Yz/hWK37LEHxnBlTf4XWFryuNJhOOwAfdyxqqsEw3jxrtzNtmjP
+Zfn6iqBcr2q0tFgBQFF3VNUHm5m0DFoocSUPPRnOmz3c9OQZ5fA+rJp1BYPvobvZzzlNqTIL41T1
+g5iWaeNddw9tkOv2S+v3HxtyTx1gVNYoUhkAGec0w0b3iU2zSH/p3l3vLfOQ+unvv0uOi08obkT2
+qEEv3zk69KGiBl7y9OjdzvEdM2C8Dng84dvXa0/I8OgjtPo0sLJnUI7ij4fJ2Y6yBwDd7zAouVGd
+1apbry0UnWgQRVEE/lJcQ4sZ6J6UxRzjDOEpn0TL+7BMtHlSGxyy/d3k7DXnPvKYP7/E1euIoIEq
+6833GbntbYBIyjNEZpbUPJg5BUbcXLd0lnELOC4IF4jcw+D5G/gw7AnubUfW4BknxvaRz9nuT4Jp
+1/KO0+Rh7x2Zor71o4mKZdGjGnpjCpL6um9liZE4CB6y8J0xQArkB48ZZA5xImybzbZXtdlW73fV
+akYQSshJWgtLUhrljBwKhr9GX2hM3oGqPrb7K+2fyf3Bw0I1Dj1NVn5c2OyyqWdV9yVmxXfAXOiN
+6kfn1uipKNFo33z3LT764UzA17mnXdmtyHNH+euAaINjosvkJW7BDxZkigMPAhuPnN2KdPbdTLCm
+RjlEokTloWVY4IeTo5fEV4S5eOsgVENtJHeeh6qA/W/dUElI0yF8vGRAPsuwiDAe+Ae+jnkFEUEo
+dMLAawBoi16pVIxpLXTFIZrQdArPUSVbse/eJuu8/rEs6haRR2u5ij0XsW7UaU63b+DkPNe9u8Bf
+4xE0di0sH8UgclU7HVBEEbyRmE8cBbvYmCFRqB8FFhCKv5T1UPGs/TGENJiW6r4H5GbgMcyh73ed
+3wdc6F9EVoqKSVn+0aRTOOkar9P4/e7jD+gpFHj2BGNi55QLY+ei7Kxb42I+haONTl4w3DN4lwQO
+glEzz8vm4rnkohFkHQ+k7UD3pJKg0QeB0xfluzGT6aDeeqNtYzI2Vd9J0OTXZa9lRGWRaXgKLmwg
+MmaYasPopgIjhN7BomuZu+otcSOz3MFyumAodRkIhi1dcBtZBpAl6rUdXqAWY5I4C0Ne18iNU3Jk
+F8d6/t2pjQsxSawl6ahZWc71bDZUHU9USUGu4yYnSSycBH5t1pSuNe1VAOliaHRsxyLn6E41fTn5
+X3B7pJ7aLJrH6IpmYXXJEVXQwJUbYWXd7wQKdAZiIcokWtQ3uwb3oPTVEfFm2sJrdzWUp8FQPRo4
+0GqN18onA2tADzucU+L/Zew9dSF+BMoSn2jIgnu1plZ+aC/nUE92eL/GOmLj2Lhkz/ges9hjkEkk
++wWJHLjUuF863WHxA13qGGAYZZy8YxO7wosfnneWhV3ds+xltVgwHIj+3RKBXDqZ8MBR97cEgRNV
+jwO/MBt/dITytqEslbqhW3KrFsYGInmDsrMdkwlyaz1vlsPnN7BmdCvi04CyP8J+DHpjDSu8LqWB
+goIYf2KfCe4+8DcxfdyFjbQSs4DizXfY5Vn+vdCpzIDnbuHu5PuI3IbpEniGQJgFwWF+B/JbBBZB
+NVKs4PdXt2uCxdZfPn/5/FsQSabfff/18yiiuWVoVjfDQNXO71Rg//8FIHffVDaeyO2+UWwcZkTH
+ZalZufFwgwgvoNJSDzKl+c+GGblUo9Ualu98Uc/QEpjtVnJJ4wflp5SFxzhjkx4VQ2PQ1DSMjZCL
+K/1Jjk9TnTA41lS9QjUGNoc1EJdyWbdka8bP4s+eMcLCO/5LzO7zMOQ2P+hCJ1KIF8olid4v5gNd
+XpsY4EjhgXzslWiU20bWQH+EqBnEY/iPg3hqAyqpds9/yNiwEWx3PrH9acvFwgqjIl0FS22eWWhu
+0rPep3+Fly9AcJw85t31CX55GnIFbFa9yi+CoecdgcknWAWVNMdO2Pu8eFfd+rFQMEHPjlHgd2EA
+y0LhU6MCg1WP7QzNsiDsitYRRZ4Ks1xzyMRjeMeWKNSeVdvrCq5QjVClAi4PBdvyEh4rV5gTFZ/U
+pEXjhHJk7eU2aq6u7MjYE6lIV9lW4WZXHEh4xoY6+L1tMMcOsNRNg6j944HxyNHeex7y0EP0v/nL
+KKe/fnpI/xYPv4J///x4+FcFRKSIxXL0g9NaDsmp74OOS2C7UbxI+zOj7zZ2AjJPFs8NEnVw9Eak
+BqPGYbZZGA6fPRydez+iexbsAY7AtlCPY35fWFgpj0MSDfIB0vZJ7k6RgXDjObMDeSEE4SNkeMdr
+HH8+GX9xyhbtky+85BeH8n6bNYvd0nWtnx0NZ8fD2ePh7JPh7NPh7LPhzW+Gs89Rrsce3GYw89PH
+mbK0+z79KCPy8KlqOqTUbQOOWSHonHarvsS/PeU0gkMeYdvZV//wIqI+Pl/JRGXhmY6Ou5QL0BYq
+7L/qyMWhebKhDLatncNTozxrJ8d5XBmgyauQa0oJKz6+kWOQkdH8wz1GYzSJnbpsq7RnITSz6AaH
+Iq2k1USom4xMWt3p95n1i19vD+R290fTfdpcmlWjRKr7548yAiD9lMb8UxYhb0nD0mx1FvpqLv6b
+m2pW1VeoFAVyl0M7O/JGsrRYUmExYPGM40OxnwcpjvtzGunHHatL5wWbjOYu+iXPgSej3UUandxP
+vR/wjLuKO9+be9ynGXRYOLuqtlvFraEmMAy1JL/I4OS2seJLsjx50qlOZNGBQhjJdo6x0HBfzxty
+Iy2KAkNbLst1i4bM63KFv3Y01G75fl+SFm9b2ZZUCmyUmcA9MsQEyZv64nLb0RYq2+otqc1Yr7dt
+1qMFyCMLEzaD/oISSXldz6qOlgYNWq2gO1VvmKhv4E26WcL6JPqdQKE4eUdLJs6URgTiFBmSJR9o
+68Xz3G8vD5N3VYWufrd+NEDcQdsHZhdPbXU553vpgAPBY8jHtMPt+r6H81CUoVJU1KEH8Zvx2wjf
+iNXHlyneI5hFco7WY/Ytd6KKOaee7Kh6TiM5h77qFuNQb74+hmHfI0+ZQX9CHx5mybivcaLTfVv+
+OuttSx6r+7b2rL819V7et7l/7m/OfvDu2+RH/U2aF/W+Df7Y36B6b9/ZHOGKH3VLzY74pewBvY1G
+D+LPvMdx3sedh8gao6Pa6BunCuAjZLMGH4EYu8cwqDpuj+MMgpE8ppG85MPxGX34u/5hsSKkbzz9
+4sU9Lv84Ziq2bHjaHaTj60finCSqLYnxBU93ErnjjQAx3lP24c7Nh7tfe2H4G8ls+iWNinZ0yZgx
+yu7A/KIRgO2IO/WHHJlf/lXOl16GLWXJALpWEHvaoWvLTpGE/LDNGdunTFr9fI++1pnu8WmtgxqH
+DixLe4nB7iRujEmMsKrSrWNkAONyOCTDFQkdVOZ8t+DfcbT1uQ0zeFkx9NJ1SQ7JJJ5QeJB+6IBA
+ZkcXohDS2E3Mq3Kh/VbI0EqpLHDwsBz0QKH8FttkxD9TOBfKWVYjJtIWz0+5scUniVYuUSCEeVhi
+lG1QMhJVs2JFkRh3Le1J26gBJufQBylTahz/r689USaS5P42knkz6zCRIDXubSC52y0hEPowAMcO
+bNuhGz1FQ8OY0Cb0XKIof3f7qrzA9Jz6qeIik0vFrvBZj41wYUzKin08VVk3yYvft+TQ0UHTSLUg
+xVTnuKhQFmBEkXgpDXi9ERaxF7ZEw60Wbp1Ib9ezEZeF59aRu8pEzYrEVINe11gmCy8Pu+oE7QTa
+lSNySXUKz+KTFX/b3l+/E31hkDDjDVe/Dvcb6x36n27djz2/uPZnP83PB2h99l4LZZX5FbatQyX0
+4UM15qVfY7R7idrdKizJKhk/RhF+ET9JbMtLBNzX+gFuwnjiaew1OwrtZ1oSy74Kf9SyV+xHwkSc
++AmhIzuSqtdEGvOLbNs9HgCiZ1c8bNu4V5BZcoqBv5vdccGQ1ylRWtqJi5N6yVSx/XYxXNSs5/cp
+31t2F7HLi8p2dISgarqtcadamZI/ET60LgzLYnkMjHt9s2U6D2Gs5EBA13HcwBclmGAYd0wZW6GN
+e9M7rL3GTyPyRn5wf3ZxEFHJWEcA3Zm1uRzPbFxdM4gY3ev5m3sqcIJbGMahjLpo+w07Edl07DgD
+hMWcy9uy+Ycllb6ECxpvg1jXyK0UO3ML/JVii8wyDq0l9Zd8S9kVlaXZcOuhM/08qNT7+KU477sE
+HyoUsmu7rtjMBzzboV7w/MM1Ef/FPdJt3RxzAfzHD3YB4psvKspi24o4qnBP0Bly2ZDG/LzxAp7V
+1rR3sn275XDTTEORtbMkaVMudn1sHHl50y8wR1i2XZ/IRvvtaB6Sj3+uiccPAX23z+oxhlzgPVat
+BtJC/gFKrF9SweIHVY27XIMk2MpGz0InsrEPe/b6x5djFZCMGTJbeOq/K1bVFjHYHmEwFQUmbzfA
+DR/N63Zrfee29CNSXk2s+/XrF1+Pk/P50fzzs/PHo/n52W9GR58cH42+mH9yPDr7vJqdV7/9TVnO
+S6e+GNKSx8ef2XhueMMlf1fDZM3tYP38E1wy892iGouqxPrpJfq3PZMr5CmdW5js+l1XERgC9n50
+1FXgayA5KHF09MkIZvP4c/hz/Okn4+NPk4dHUC0ZfIuaHvj+e7jMsJjtf/wD4yvUVcuNviYKnqv2
+jmGJkuNPx59+Pv70C6c9+P675kra6/NzUr4gKkrwl/cGMXldXc+HbJyh44NfFgrB/2rjpIaWSfCw
+ewdNtUr/Rg3Ec5UP4soRwDpADwmdfn6SYf6hPTFkWNvi2Ni+64jPSD1lua+oGSadVUWFH/rdcf5q
+HDPKavgpO1VJxCU0l7SIBKaMUpZT8o71MLZnqKXl99N8v5WxmiAdWjxdsQNQC92QusbPbUy+rnZu
+YfKPdXRTGTqmiqBGsA2oRooMiNEf5lNnbl7d086W5WXR1TiWnOpb321Yqp52NU0SfFfDS8mGzVm7
+r2d435OzrtsHtXEaweiR6lZbHyfHR/TfByQAm04RNIUzxVE5/Y2dW9wapZtd3HgUt9Ae8AzKvodq
+brgOZvCAeP3qmXEiRq1yibqFD2CijHKm/FIydAccyf8l8H9j+b88GZw8HJ3SX8XHwGecROWh90po
+VpcK7OnmIZ11ZT7nbv6EgTaB6fwQjWjYggh/uiQBxSNu0tDJjW0hesHi3T+LehLPoo7BGat5uSH6
+uVi6mdRVctAYns71DCWW/ox+fOP0l9lUN65bZ2rdiM0qyciJc5zmAWm5aEMSPDx6YqPnGKQhTWwG
+lsfA8YQ3I5LEjeSqx07MrcoB/9SKlaWqXqmrj0J9BkdWzAXj8AmJui4Ycbepu306BNJqRN6NUecO
+Yb6G6GyR3fLzxk3sUQRiR8qp3grBsBZBMoYhntHRqQOoDO9cX4svrXlLFb3Wdc86eFi+CDL56ZJA
+7Ut0JrosrypOpqTQq4CWPrKgu3FHT3gRUHBw8JaU+Ui36hwXqnrAJ8PYhBiF5OTU5KunbwLWSt9q
+8T6BqsUcLVvUkDIcub/Tfm9QsQ3DUiWN5ejAhPtLVrOTiAHr1DvyOAp5OqjIlc4ng45oGR90SA46
+YqZLG+gagRZrCl304nZ0I70BO1jVjdahb/pDdZyK3xH5oSaZL+v4i9INXuDaVlBRt7qPtMCR3pbt
+RUdXurxpv1tvx7d7e3G/QXWrlyPtRrSUXZMiWaTDd5Au8qPPR49/+wou8qPPxsfHxWe//eI3n3z+
+H6MV5MK6/8Q48QzrVlgqKdebqSOT7D0hQhroIwkJT/K4YRABEqdw6q+TvH1FWkDq6z1IvXPAioni
+a58j1ai5PN83dWb25UsVcodeGCBPiAvGg5ZUWvDvkzCCU3GKoX2ihmbPMJbr/eL1v5+ub1FvUGBm
+U9Sb1hfvl6/+r//xX/0rvO0VFBDKmsMEiySwr215gRx/uylnHIWPtXYbQXKi61645frW/EXaCfnU
+oJp0heIWx04eENNVQ5mhx6qUvCo5NkhkXyowLeeSc5NlJiX60n2raHGDPJGRQrN5dba74GHKG5d+
+KEw72Wgkc0VMZZJsJim5zk4xnUnqClK4EJN0XoPUUt7KoOBaPdPrhRezTMBGuUrtzq1ZpKPLFG7Q
+0QgbTuMDAEppt5OUS0RGg04wzg6p7Cxmb2gsXWPIRmtr6kyzutf1YncB+0WfOeUSnsJAulxW2xI2
+bJLilqXBzzzQqtwsbkeLppwLHAg3ngyWCAkwKhk7LXcXy9kpJLxKtjPopGftrHpmJoyZ0DFWqqFT
+3JScsrw5p2UlUl3fMu4AjHbYNVyivnsNlGrsOUT276bEbOgHpA4lNWETH8UvMKnSbwVCDOMiOydr
+tiSw7CkdocF0SnsCD5XFdCqHjNcP9t/5sUCwj50Om67PpVzBy1BQl2NfRJbM7wVIvhRJmHrjs3Q6
+lJIdI8lZRMSscVZ2eOpqSvUoWneSGO+rc5V5SrtIci+jBy1insg/wB1X8Oeb1ex6PsF/KVsv/vFm
+hVlkvMQ/tPnTqTSJUbLrW/dzWkgaWXgHDeg9iI5FqgCZFDzPi4ZCyKH/QT7Uc2o29QXh9wXTJdos
+6BHRVlua42Ygk7U0PNCpoJfJMuA/lO7crLVDJ9smwWkrjZgrv1LXBwd/IyuwLDfvYCC3qCWxyWi3
+UoyHsvDBX0Y+vyxbMpnx95iQXO+b/WgJNrWYLZrWicuPTA3NNXdP7MBTq3oduU+dvuWWHOyxE7Qs
+Ye/9ubuHQohh7OSKc3V2mtJwYHAGeyb/Srz2oAG6j9RdhPTNdxF6LOM9G1uFQZSmLapjLi1QckCn
+/FkKk6+cTNZJbqcrefhflm68q0x0llTpYZLCBIKwWzYSsMe5s87IKAPC4m6X5Qquyg28BacBxZq1
+hqsV2wh+6GoqQv7hYIlo/KZ5mNtrJoS6KV5VmyVief+BCU50XNcmwyXRrkg8MF/5i6me0tWrCCao
+hKs3iH06hI9ttR4k6QQFEeHxxEqB2JFdtKlbLz1hgjmFLaxHgsiiPEpX8CD2UhAIay+g9F+2zQ39
+C03DXTk7557GqT+yAz9c3Jsuvpa9wHGcMEimILfbokqkHukhKJTcplesGM+tS79MkpT1kFYyvjXl
+3UlBFh88aDm5PcfKY43cV1OlSfJg9PhTnZtsjblacNCWb6vMn+N14RN6Jl/X8+2lCr7XK5T8Lx37
+CNvobReCWFYgEyrrbIKsGw4vDXOsmcZoJN/fWf+8vkFc17AB9YOj7HQHntryk9BOuP3qhGFBdm+e
+UBB+NffpfqqK4a4WVFZRvSIfeb0IERGnVkT70O1lHNkz2LTjz9pEds20t+eu9R84tCX7YwLxmsoN
+RGSbigROEBUKsJHlZg0XjyJ1BjLFKbOWPh49dvWxom21OXyUtckopmh21qiWHWyetYwqsQ0d9W3T
+LFogiAuoTgkjZVLj1FVTYfNDNb2eG2JBTt/KBYdLoTwhl2UmceT8g4/TKf5LdHRB8EvKrYL6xO7R
+Fwbd4ae81/SVrCMqzGYRvHk9V8QOfag6cMQnKudIC+gdskE+XcIl17s7cZGa4nmcr61HTtdm7BA0
+YGzEYPgLHq8jmv6dQoEr5+aW/Ru+vKd4IDXGkcUUlaqUkF6CNdhjspytOkZq8pWXrkkYTZz+kRoe
+83eKzQS4JjblegzFk4BDio15s6AowD2qYvtEr5HlwxB/L7nSnXTUjh32tsljpHtwmEw+5D+od1Uu
+alIWyvK0t6tteUNaisumedd+cNP2eRIGZXjMQPZO7YqsMDv08EZTXkRrQ3jeNCZje8Ldpa/wvq8x
+1wWTBH5XTNUvtiSCX4lT1MDuRJVVR4clirqxRL6b7YvvB0Y/+AM6Ig/8PDbR/MWqMfUoSPxHKL8l
+bXAztwIJ1jzjkkB6DaQlW55k5Uy3TC78NZq9+He0LyH12yB9gvxBPqgoRDE0j4scfFGt4MjPcJEG
+EeCewAfGQwmixY361qhrgscHh45ZSLnAKnBVdOXW5sVP2aalEqtinXHqp4rRnIBXjnA8u49pZDl4
+bAeeSg2+mkpeOQLsVSpRmUoeuMdljmqG3B6sZsIpWj+qDEFeE24XOHsYDK21J0Orn2W8eqj4XR48
+AaHUnYNjMrf3N17O2iuNFv1gw4CxSmhF6XsAvwYZzvwGZttducCzh/Y4coFj1sjPKvher31/O1pa
+piXTqUmkuX788aE6u2rOHX3FqM3+72xTle8CjB4CkIaa3QA9ZDRHRZEi9mDyTvbqoC2xNkfEM/yF
+xLPY5cQW+B/ol7/nKwM2QIzxD9rxm5WIacx3NP+CfshZY0CpndnCGm9F5wi23BrkTsJZYMoaXYOd
+F9jm3MWb5IZciSkrdSV2wkV14gawoG2tVxXOd6sZ7PN0mor/h31rNGd/DK4u62rCzHPySEb8cVNa
+HSH+PdZt6icv5PZPpMqptYfQ7FA15UgHUoeHbegEZ+QuEuygbJ+Rm6BQoYhiaCUBIfOQaDKQ/hG+
++2P1NQ5JvqNeeDiwcO9Xr/8dyqhWNsj3zas//ZYMWgfLBj1T5WRjZLKd+5a00hIGi8Dwc5XqW4W2
+HUj6bAJTzYqEVG7cJDwg6iWnQsDEuirbCSW0IBGnvrisNgeYe2KJCCsMX0xqe+A2HLXLscrlZlGb
+LBySqMs2nLW3LXs34fvGsrSRbg8e1Oob5UuBKGHqR14XVYQB+OO/EYY4BhLDH7FyBfky7LbAfKTG
+73b1Yj5r2u1TSgvxDH8fJk/hEFw8Y7+Hr5//7vXv2ZqhjuhPVyvxnP6BsARVZwX8gN/8rtS3MoeY
+8wjtdARbRMdpzs9Rm2EyUgzWTdvWmMCCvfhza6eFIsU9uq7ER4kx7xbtprrixDOT6JxAmLpBcyzU
+mxw//iJX1TCkUFc003aKHx0dwTVf3ohn3uQ3R8WRAye5qq6n08EMQ9z9KHyKyIxgR6JlhIi2sKrn
+HQkZuNFZ4DjPPiW0sX7cBfarfsO/Y9HBfNrY4m0GpzeTZJyzcj67LBFp34ldtFvYsDtS9ijzfVS5
+aR9Ovw8dU4btjNhOpHSn+R0xH3X7IfS7ss5LxtkHmxyN8PZoe+G3vcrDRBqIgbFSNmAzXjyaNabo
+vRJHIURXjua5FKsc5mNAZiTsa5jw2y9pdpsExVl0zRZkcUZo9xJ66GWIqkYd51UcG6umzZh61kHl
+S85Gm8xM9jR5yKKuW32/ztx1op9/uVWyF2ZBA8canJYb2j8NEkFnCl+bR0xJYisKMeOchAQsgYGQ
+UN7UXij9h7sAOrbabxXxpqs5UlJuBzic1zeEsa8yEVYaLQshZCjND3kYX1MCHdSleu9C0n6KGLpw
+WAqxct/FkIReXE1y1aV7XoXLWH6pduYtSROBh3TgF40lsw7qqJ3da0uTDLE9YLPsbWSsdMOrLKx6
+VOMt58FJIM7SmdBbJ97NoLouX6AzL/wUYtc7FC1z46S8Ztbq69h0g+gCASt3E3H8jLz0d4NiYCIs
+O1HHN6goeH4DJ7hVaTO6cmLpTvzq5QIzd9/CUO1m9siGRclLvARxutydxEVA8B9AWkODSYvZI+hs
+4wQIlxeTE/znS3NrhdBvU9zayvXjroFaOUms4Fe0eFHcnc1hhJE8AtQKyVJTxFQjj7loth254M3y
+4Anvnjy+wxy4GR6ILbcVukOCdaH+WO6yc03/almQYK/xSx29m25QCbB5nQ7zu7zUqZ6oOySJeTWn
+dxb+MszznlwoEg2OWJFIz+VWxo/+5Um1XG/Zx8lcFR8uGpjTlam+4vkn7vCtjJKPo9XpFLn6xkKZ
+UD5sRMbTMjo2m37ggW7hpu+VpBSpxgTi8zv13IGcou/wnvaSkxLRlatb5WuHxbQeKp7BbaHTSPHg
+JTiDv6rWjhhAkbh58mXyaYxCDVN+8d3fP32pcvLh21rxMlK1pPa+mVZB6P60ew/7s5z27z9mqVWp
+3yZZlnc0JtFCnEgYObnSvXDYQUIhD2eodVHGjbnR2i/fmZR+/ZssOZP/Q3y3eVNlI1FFe2ADmcB9
+Qx7uQf5jSltZcRpqhrdQjqHxXecyU/ZE52ESGgK1juEdOB1EK1vfkqsrzLnhHBXW7vFM7Ky0ZmFj
+pSwRPqMO0L49WmZDazh+4jrvarAaUwcrzABiCpljiMnDZHtQlVRtgZ23F5MMvq8Zpi6Yqc/nKU0r
+zRZTYFEjCiWDdPraFRcaLjxOr3Rqqm9Khz0kHpp3X/Txc6XaSNUDDsiCXKiXuy3pvYPkf64UzQwQ
+JzNaEvsz/wOMcACj7w8kCxlf7jFDHqFjeIptJhezN9JKu46HNbJhKf8y76BNn5+SmlTnOttn45KO
+neOh/Jx9E374c3YNrTV610YjEDtnlbt7/TuHe/uLbR8HF4SnsLOws79keFKp7maY1o7OI/+w34Hk
+ssATWWDZWGx0QMlOzWfKqkRZ1mYo/ODuH+xxbG155194qzdL53iqkxnZvfvuk96E6gYlR3XIGk/g
+5tcP6XoJt5OeLInhqvpFShVV1CyuEj3iUEGACfYajHxdsGKibodG2vR8rC0/WJ32L3p1SX++76yM
+v1slM4jQfQQNr6O8ND/MT+9HH57KSxgJ6fhQ74U/70EMsg+seUL8Br5p6aIdhhcgD9ba6BUCy+8l
+nXBR1rKXrKgaiUxCy84P9GQA51N5XJYuvhofx7xIXpwnt82Ow6wxq28otCCSAmURckPhdB5IBflK
+fG6uc9i4snFnYuL/Fzi3XC490hCKVa7ExXLQketaRNHScj9i/FiLqRqrTVvRcoUBmzcK2j3UmLgW
+4YikHE2orYUMzM9OZnV4VZDcS8ayj1LnYXCD0jtXibpjqOHhfsP/dep1cHXwXW+P5tXXL34c3NCD
+3tqXn/jbmMx/Y7EKEbbV4ODcLbaNXU+nhJ7o0t4LiDLKWDHdW3gk8y66OYRBosWfenP7cdVCzqPq
+ED0OeV0CNc+EMzmKzS0mr3U8XFM5yKKXdVkZd9sBBeqWlRETKau1yjtq3njFulTVnbzO0Vp23mfW
+7p2js/yiY5VFxgi5I5GCeu6Rzv88fPVZyjHGAIjnF9tUra3hVpaaTCplvteQSVJ4Mh4dn1LKjk2N
+WSfKmm5JeKxSaie3f7KPBBq27q6xfOb6o3NSr9YGXwh+P7lREAGGCzHkwPH49DTQ7WmNphPYL+Hs
+WM0SNkiXHMmHaLRnCK6Fq7GbbSkNihjVRzCfqxpTjNjBlQ6zBw7J3r2uqOM4rWHlaVu954hRKF5M
+JX/7VP1s1ThbqdYUNUc8P8n/VXyyVfPxrHbAHc9WnSmgtXN1NzsW8dkQRTD27qWFUe0qhIRpeDQj
+Gre5RMVcjT+TgdleWewLs6Civ/I+Scm7aHJBvuyjqyyanfzXTCPOyO3oH7racsRKubUSoPam+e7c
+iiF30RHwbnWfPn+MwEC/Hae/dk9sRyFHL3Re/NVnlglICgUnlMa/oj9F+y/Q7+sV+diBMIgq3V+v
+Nzelk3i8kiTEMcv36fnps2fPf+rv2a9Cmv5I2btYeYTfeQgKFI7XqoA8D2DH1va2YU4/469Frv+C
+hyg+PQOu0YkVjJXYq54Qa4tsnIgZ4rj4DJnAfIcZLeEH5E5ttxbKnp8ykg9M68yZ8+418TN5en59
+qtgvZnvaT5NgWyyMWxI+EpoN8eBBh7eIGK2Ge1owzMuAGfveZhTHeNY9rA8bjDUcfcvJJScHB56V
+4htF2WcjKUkoVspcbBKUg85VyjuMgUJQu2RMc/AduSW6r1h8hahaHIfW+dC0HK6gLXrle3flOTnt
+irD0zXfforMtxm/Xi04hRZa8W0QRy4ldjYwox6Fj7lCdV7twkIXByCqO4MPwFni4GCARTi5Fb0cw
+1OW1Z1kb8WGzjxlfnnmuHV8jwJjXNAnTxMEG1kn3hTBHR3PuuyrrZi1gMv6OS8MD49TXyQABkAhO
+5ZgAA5mefrNktEVzoRWcV1PyxRX6xc/As1DpCY/6swae9X5AgpP3VsUAKgwprSAj1YjRbxcHuifk
+M5LuZUMAANrbayB6G1LJNZJqHHPB4nniFvBNJPUpR3lX3b99/vRrqMKxXTgNrMVZobUOJzJmcobF
+0AoMMpldMqaGwhpnD9hu+3WeHCK/xew5LbmGbmQNKnLFsDZFrcQkcVYFt4BoOsXhk8O2/t2pXREc
+qLUeHTXh1wOb4KyeJ6qo+Ntxm8EZxV/g9kD/q7SXGetiZLsei3O17lBTVm6H6eHGSD21TTSJ0RVN
+weryZrkgd5ZJ0mk4B6JORiMoiLZzYz7fk9sPZApDe1zDxDWem5fWHdht/AqpKj8X0EDmYZ/QVsHY
+uBBpCmrJx5DCZm1orF6wNIWo5uClqS/7caR4YEqGMQ9qdWo05lseUyFA1YODw6Pjx598+tlvPv/i
+t3v89ZvPDzDs4/Hjz34j8Tvrd6rh4998xkjHnybHn48/+0wj1BXr2wPOy9WuG5XW6/c7WPEhpd88
+Lj4pjjDQES5f9MzGp1a5qC9WlGaUFJCtmKbn1UcffURDOP7k+HHyx+Zytbq1FuT4N48/T74tb5Oj
+zxCN+ZPHhJg9nVezZlPCrd7SWFw4bgeMmzN4ZUdfZYlCB8MvlvUcwT9rcnOBe6xmkxJy1evLCn1d
+qJgGCa5baY1BxYcUD08ngCLLF5JrfIFQNhgu4EJrmr3K/in5ePDVD18C4T8hUNSH+InxuZ5gAnX4
+4ugrLoNIvFQo/ypxNeIZ/Y4uB0/eXD9MHr6Z//nxX5OHJ2/m41PVJnLRJ8XH+f+c5Z0Qg7UjMh3q
+3F8lxvVj+BdHwdPB4+PeKnTyoijMmA6ntFfHsFf03x93S/XTUfK/7hawucnxZ+PHX8DmA8+/fGRA
+OlH0UeKNXr0oZicldZ9wDUbXJDzUwNrF2lssfcKSSWiioUKYPovEl0fZOKZlLA2uL5dHBV1YUGCi
+SW/fw6ydsjQss3r0GxwXUu1RpJ8AdNLwfsgO7oJZprl68Mox1GQqF6Al2zjQXAQ/ZKci6an2+Ut6
+zRwd9EAo44cpanqmy5oy1E9vq3Ijjfgwyv/CEMoHh9MP+A8YzCGdcxQu4GVA77oPbMqAOHesUwjo
+XK7Kxe2fKs65jKtDjIwOZYnozhcCCYvMK5VTCpf5gdjO6EXNSLsEn4yO34QXh79hl1ZK50x6Z5Ir
+l2f1RbMTpyMlh6nwIQEw5m6mKL4JGPIF7aGCcNmSvUp+g6ZFSyEo0vAkuwxBlKmKnIFhkj04y7Rq
+b17e3l1+DuUfc3kSWCeJUwQ4Hc2borp3mzFIC7sti4qOFhPYRTpOSSsCrdzhhWlomtr2x4gt4ND+
+0c0Bhf2zvLIju5TAGLEe1LQ+dioMTfl4J4g4Df18Mv7sNBgV7hSOwIhMUy0ODbDQkHdliEs9dPob
+JkdD+n/Oq1PXf8KNu+tE3Y5AxD34WX11oGar9kzQp8LZ7MTVZfzNcWeEUScKasHWq0H2+tU3oy/8
+GCUG9NMNuJC8/GOWdzahHb2lFcplHYPYb9a3ePCnzmjdzlSZEadn7OzT7tdpN4LE5ZQxF09v93gf
+oXvJ+/Xrf2vAPQlj9P2r//NvGWNUxWYw/2KN2ZBQpciJR6FYKrggsQwAz5OgvQBqlOIjmx5MUQ4L
+/pYRHDyA0m4wRAcKRIAUPEjEZ/SHWzI/sJHCqCVj//dg9fZB0GMUhuOe+I/zemVhXs0WVbnarYnv
+BQEgL1bz6iZiW3E9BKDBgXW8EHLJXE38mVOp2TupnYxFhpDtpBjtVlBiuw7oDr2vRDMi+w2EEYt9
+LKblqlndLhvKfPQ9Uc/vCfQ1ne3aLRCAUFQ6FFjYiatR4kYYqd19DUpwhO7exNTAB68UDRjTsuK/
+3m8CNuYmh9E/RRDeWRasV1v5Xq+S6R6RRUUMsiPZHQHXlA7epxpByL/SYvMeSBdmHBpY19i/Cbl0
+tqnXjGmKGLZwYqNZotEdBp3xxOUAMyqT+yZ3k9DuFeZuGuOvY1ZEis+7lGSoVVPQGsEYHmkEgqq/
+IQJlgF2Vc8DUpLGaPkhk5OaRFjF+o0FRYV5RTJzXim7mFb0W8UBDDcYilmByfAfDI/PtW40L+/at
+QkzRUSGtbVJu4alcktEbqo7Xt2MUOsdvBe9MN6PLf+my1+IHr+CTtwmGnl/XiwV6THHGbH4I2yoR
+DK1HtCQevTyURXCEhXn7VnqRNXj7Nq4Bx+XSTdgnLKBE3kOlZaat7rKJU1H9o8J6to98QIgdZ77W
+UpYabD2EBmm01Qq41qaUoFE17jwycDNsJp873Kzs5op6hUrMQf3weMgzCXQ5PFt95AygsLjswSdy
+2UN/tjBohNGP4GhFLlf7bGErY3WeJJHDDCiVSQQtuRs+ScJF7TODHY+JaimvId39rehvkWyI2gXQ
+bpADwat3kxxje73eKuRK9O/dlFY6MaRt0TfMmxnqehCpt2g2F4+k6CNVt7jcLheHDMcwUl8+eevA
+ZSE+wBoDX/SXT3Hz3HXCirWZNPn2GSgXwYQQ1G+5unXsJR/4q7qE+btYZd89/fY5rMI1ZsyEH+Vj
+3QKH2aHLEkZrGG+TW4ruYIiKt2+RU0Nhvc5DzunNqXt0JYu/DNLRCDdOQ0pjd/ChKIq869R696kF
+Yu1Rm3UjkTzDJOm5jlJrGpCU0JvN39/e8rllNuUZefRl7NzND8XoYwZ4Guc3vZxGgU2GmYWBayDS
+CZWy7w3VdOG4/Oj9Xm816vwtQtXqKRc2Z9JzZ/aUd7ZTmDPTDpwhR+uY+0Aq8WoNVHPxiE9TUbI2
+wM4NTtAT+cby8qKIdH+vp0CkDiNi1+FACuFcRo1wYXF5lgxjrgjsOlBxviUyv5kGtPZGYe75zyJB
+p5HerJaC+ZN3tc1VQQRzxBgDICvyp8Jgj0gyhs+ujIAbMtlQgMHCV+WmRn5iyjGQKgHNSjlVRjNl
+uIDhdYbGv7dvh3jeYTrAF2D53r5F1sW/ODIRjX6sXbNlgdEs649ZeXKjoABs6f0OxB20vjkCDtdv
+zp05tGp8sMpQB6M1kAOW5OifbI0rm5FkhDeCMIg7wEZcX4h5Zpd50sG1xB7IyL2rRKw1qVonjKDF
+VcJ/1QoF0RYOHjAqJiIwwnmH7K4sNezUqV5J1uHvVEPE5WaRWGJvHdFHO4yI/RstfjWxWwy4sQKX
+PfXzBQpj5j/65Q6RE+KyB1TguGcFuU4GBeZkzr41arhxvjmI9OTfVGpsU+1soVgACS872JiNmNGt
+p+a9pvQvNUry4Y8N0tSy33uRGY79zGamRIi9js/ZWu1SMaWiUxIGY25f8MPJERtKRpzwEr85Pi3q
+Vlzi+nze7DB1Kj7D8F/qUhEkvDyqDXCNNFSHrS11Q4RkC/dNrJ6qMbJXB1U/Z+WoerJIfKN/sPPM
+xFSK9u/WK9o7V1ZwU2cnRVQZopCu6ZPrSoW3PzIsEQEUxauRChR8ta6N+wl/t3VGrDQO9shZDWFv
+Cn3hbQe6H7xZCUzMSYpFxoSBbLnTUL3TXLD7o/URuiL2uxJd/LscFUi8hc9EPzhg8dsynNDDmu0j
+lOmWwfJmokEUbZSychEUG3xtRYtcl5t5q/WPGutNIaHRl9ypZyKJZYBesapRBAtsdLZDX664Ygtv
+sMdYaOmg/ZkCqj2UreVPr4QaNzW1bOaxVswwRGnIHwwvaun63dblIi7o0zJjQGWDisI5RXuh8xBa
+eTFCB9XU7FnRIMxpAsLyxaI5Kxey+i5zwoVVw24FYU8/HK3HEkoWIGZMz6pzTJ/jR9hxNJk85AqD
+Iy+eRcvylm6qmO45cPq7RrvbruXchiA2oUl/UW0rfLKV51VyXVIKzDl8hbkabAIShS28iNkEJnKd
+pRvFpyWhjRJQ3QLNuuzI3DEWagxrcXKG2xbxozjPWJL8oUr+iJAEuB30zISWLqxXJb0sKdn5Bpnh
+HJ+DcTAAQZXwQypz+2JEM/ZoZEgmc1UqeOo36MA1QKdEBjD1gIrW22NKsb6hn0/q0zyiqTy2QSvh
+c951Rx2TuXe97U72p8aRPEnq7gxu+JiTBTBBlSf1w+NTztHJd3XUTzwyXORok7Tjhgy6wgZOcJw4
+0YfH49MgLWjP6V3foYKiMAA5ljawswfHG+LrWpjlhJ6bmSlmOdElfO1gi45G6b4ZzPWA/DWPTh2x
+TKmCDm9MDvGEMj5z2yzlZDBT7lg1OB9TzJagGeSA24xAOTtL5mDsKhBdUyLmQxJ2JdO0pb2wkHBa
+HlXvzXCCl8epurcxgZS0IXdVMLVDOAfbTHwuVWoz8qn6GCEy0c/+oGu1Y867RmHAJZWLdkpNpvHj
+enOHN7CebGRCN64pwv85ihUVdZ7VWZHC+138Rw1oTuGFnPtGtxk1OonuECW73S+te32uQ5zDeIAO
+6Cd2HdEvfOwWH9GpS83ztQLZDKPh7AmcBD7gUPMjrho50Yr3+OwotulSmBzpcZIfTeyvOHqI8Ecx
+Ipd/6eKbIPVFOHBXnlVbDlKrQFzGTkSTdkap2NVdzKzuS4SWU3tx4uIwtRk2YDUaQfam+ifjo76T
+PV/HYmMjtIfMFduzeMAZgSBXK8wsPk7Kq6aei7+1SLckYG0S5A62BucwKc/PUcUNAtEZCFELkH5a
+OVqsrSYcGSXoMJC607eyefMELfPmxg2p5TPsy8ZLxO5nJZQsDFZjJyqZ9MDUDvR/VNPt0q27R//E
+Ibp3xe1Xvi0kWN/LF4Iyeb1ShfaKpmS8bVwFndEAP4SZCITPaL+MjhDK4E5mDqPYk9Jr6aBdl4oF
+INCm5bGvmoscn9yt081WXXBM7zlzYn+xJ4Ndv7sQLuAMa30rPwwCcUPV6GTJUw6snwpQzRSEct7Q
+gdsFlNGB8AdxUa57dughRg84b9i8H96ohcP7peOMv9aIdMZa6/CQcUQq2gg6Nb1N49Xiynr/olOX
+gXB9GQljO9AUJmp03bxW6Gwp0Zh8oNrO4jQ44czLJoovsG7araxsUMIcQQcuU1fQyJAxpwz1UI+J
+iuo3t0u7OwHY7KA2+MeCInCO0rxaUJy0MJoTKXp60Hte6JZVKpbl/HsxSwVKlstmgUoS9pYyVtPW
+sgsXPXqRCO6M48WrkujYEH97pM1OvzRjTh5snlC+PbvdYW7rj+qLcGIGTd7No8yKC5W/Qhy9mJQ5
+jwQn/+nVBjl1/VvmcOz0HSgpvMW16w3msCjVjLAIyXvFMrpcaONdn7FFe4yg6rkq5zFtKjq7GYrI
+u9SeolN1iJ31mSn9M04erDfNRXIiRHOanFCKq2YDe7QJPhVFceqllbbcw3zHJVMwdxbW27YAWorV
+y06ZiVcHuJPjRDjA15unGGC/dkogPYm0aSeURcFHkm4Gtin9NplYak6lSXQZhyrqNSHpeiJDwF9C
+s5ZKYRAqHNfbx3MeSqhGZDdDy2Ptb+hsWSmNSBkNoiWePjI5U5YDMXPgl1HVIr5QCQEE1hyomXNP
+wt/wVJWtVukbbGmf3DGhfTv9FIcrLTD7BioQN7s56+62ZAlFBScGQMzKNbAPW4knWlZ9XqiAIRfv
++yLqPBpLJyfTDTIew/E1RvKhmOBaW61vlfYt5MIrrVWNwEi5dVVqvFhWZJdelLZActvA+GzoHc+Z
+VfM9nzw9oZHvJJ/50+lAg1E5tx7okr7lwQaZufvl0Ae96xh68ACT/l14HeX7qI1u1vjsjLTwi20+
+Sx7yN+h6E7GnucdIm5uxypycjyMKNwqHzORxL9o2VSGKrKUqWtx6qGvkMX/PbXd59ZeYwM0aActS
+CaKEfpRpqfVfAYuFVug7igJOLemLvQVfroNonkbLoBTZY512sh3kndIfYZOJmGgP7TTo72Ew2Mhr
+T6YbRH5zGza2vDaj+Eo+l+cdCgfSfpdz4kZGR4WtJIPDum131W8/8flbvdoyakbiKBQ5ARmiNtJL
+f1VVc4nYxqhr+3V/hukDNBPUAk1lcTz4FZY8fqXoPYALjechv9gowVS/wLiNZSWlekHSYi9hb2ss
+K1WYNCQKCkYWiB1QeLUh7TMPqt21+DDQo6J4z4sLggGjvE1kBbpA+tl6L07vrHPqcuhBUivCX3ms
+hEluHiC7cMoCQ0M0Q+2wFJOZ8fo+v+CUXfCHXCEnVvZtdISRBNz4p87BnZ7GpbhCnKQyuYcQtam6
+AfYcNZ7hr9hndkdjS50bFmug1WwpJrD3u5pSA9/aSewzlz1Xvt+huSU9MEQt1NC6uZRRK/eWNgTo
+PBnbijesm0rZNI+DdJJiQ4Y72O8qci76/aqYPMpTCgJfN2hX37O/anUViOoRtnTnaOaN50Sjtvfu
+tdUCaSAmqbVg8WFi9nbip/VxVtp7+zFdqa3j0yAw5jbF0XPLybtAv7pj5Yb4FwlZTH2t+vKWS4WJ
+krtqYGdU6cvkKuY1rnBQqL3X+EhiPVwc0xEhH+ZjdWxak9N5qHSv+pss7QKDttdKByppOCH5AXep
+OXfWsQPSh0sMI2uS7+c6fMg/ivVF6RWM0RxIXvzKRNSX9GdWA981W4Gs5XLokrYC/nJWKc+BBvHv
+1mL5optOIOd89aUvU2kON4wAbaa6J56CNXhKMb5sCFZFun5mDz94+TWb+kI8ZyP8po95ON47KpVU
+5CBPqUCAkOy04bv9Mru1hMXct4iG9mOCthWNm3J9Iqzb2fU8wAm3p+x56pJoOMUFdfT0HoiBdkPk
+mwmFntA/l5xZRZdBaRzoXj+rqpWlNIMXLN5FJmkjTu+2opwPmFsBBCN2yCCXNgLHwR7PKrgaOZz6
+wEIwFr8YBbNWAyXThNzX641377jqYqFJC1/qZkjmFVPkRq00LYtKX1FLeDc97udsAq1XLq6o9BhF
+NbUMqBFdmISir5Lxpjofv4VW2Ar/JfxFHjdP3hL6s70ijAKNqRboMQVHDMPScQcSk74bamya3cUl
+am0QPTziSexIFsmXXXFQ5EJsiaCLRTJQzkQSSC/paIEfWQZW1PsTT54X/RZgx1Sh1CheeuRe00Ss
+JuVQXphYiBhNuOYt943WuZ/B8J2wKcfz2ecIrrv0fnMLzdYqlXaEmsbywKfTnfc8DBw7IN9T9xkU
+Wj5kip0YfNbiSlm/CfY8b/vrZllsu04cXJKtAAUZ3/VxxILv+GN13Nx5h6lnEYd+3FQLZf4R7txe
+LqobkWA4kCKcmU5GOF+zMV2asZykojS6cHP96FmTl370SHUOqqMl7ecfbe1ky+4dZCcq14NFuTyb
+l8nNONFQx2JhViLcm1Wa57RDp32pLO1AhNaFe+y2QE8tncJUbfydVujgJJANGDYA1ckRLct+NvL+
+E8zDd6YFDUUzL6AaZzol3f00RouLEHdLxk5OgzKNqHbLuvmk3NDtPAYtKG1P1F8FyE4L0i8+Sr3q
+boarsAWZsqZ4HkHcLVCfECkXaIkWcTqIb/+Qk9PE3P3ph9hlQj/oZqO44xFKcYjDlg6cuIk+ASE0
+WPGBsqKi0NmwK7S7SJJ/bHbspYteapIwwk8JAR2gz/Yieft2NPr+h1cYCcW9ieVKtZqiKjO141zj
+bq8O4JNS0xZmRdwF7JIALmIKVbfqHr4Z4Y25auwZzPmSTPQtaW8UrfadXOSX2bJIVVPHtkYipeq8
+s+QqbgXz0z6ji7gV440/K0V7mSh1s+vLHd/IX3lr7JNjn1uz1O5hDfem2bTv6vVeO+QsoZkHbzEH
+ziGaAgiydngJK0WhD4n1Y1GJI/xcQXY6JVvLWTl7d1nPK0TNch1dY2KX9UgxA/HvE+FOWPwOf0bP
+26hDst3PwceaO52ZBxv1RkFPXVuuZIcKR1MKspTy0VEaCZWv58YNjdVhVhQ26zo/pwIXG30Qq/Y8
+z3qu0emGjV/61yx85xr3OLEiVb07Rww56Zvp0pPUmn24VSh+4s9891ll85iz57o7/wzDhdfaTguz
+0h+LF6taweh0OmRm/MjLZMxSs61mHcHdHi3pKieqoVMbjefPfz04eL95/a+VYXfVtNX79tWf/lvG
+K9rsVqQzStpdTYgHm3q7rRhgBIv6sERbMqMZeCK4mxBmw0IrcoB/oHn6FxHZEEJ/sx1Mp0tE2MUj
+Pp0OKWX4kA68rO1PQOqv2C6vGZxx9mH1J45MKT6HSaaqOLpQWFn1vSteQFeYYoEgowmPyfoC8Zot
+oUw14G27cjpvd2fttt7utqwuUY1yckuXb/nyM3b6mAw10Pl0St4F06mI72P33OOhdAbJ74Wcl624
+vqxWedC4niL38Vh9Bj7xN0IKy3LzrgB+iChrsU0j9Txndx8fhFjgvHMDaewbCWvKXWHOK19wbhKt
+Tv19taoI99Rb4YsKLXJWjT7bMBQGIpgiUcCfNOosFq+BFMfXJLAbKFk0Z3/E8A+uEDv21uixvDf4
+F/JbB1MI+5PELP3dYkFnLh2hGm7ztFROwz7JkpJIXA4WwEgXCbdek+CzkRy2CvODS8So1uszOqcY
+NYEIu5k316u7CMqnp/HeE1c9+HO/a9Sm3oEN9a7Iy6HbbjI7pP+J9OXU6OhOuTXag3PqOUuK3BQe
+OYsF7NRU2Kp81CfJXVr9a+/Jcwev68Q21y1KBawnlKBBGQ6uC3gcWgpaCisdPaGWn4sMk1RusPP6
+Bo3ZKowyzVVGNcyvsK1XBQ4NHaukprNFL4TYMWJoRfB7UHDZcs4TxcQrHe7P8hwsE+MnlyurqbbG
+fF2L26S+WDUbTgBZGeBu7jzMzkVH+f329f+gLmSOsywX73ev/o9v+FJWXyW8t4Tew8+T8x1CUPg2
+noNXGuf4omkwcIwwnu041XKrMTgQXc40zM6dBErvYgfGkAjVn417yxv7qRM5rrFkWNOqgdbScH6U
+Gt76wHhr6QUR6UKMSYy7YPWGCZcw7dJI0NYzshMS9sQMxONtGpj0GD5IiqcGD+WIsVImab1CJDfY
+dC5Tb2+LVCyDke7fc/fvdzWlQturcyoc63pe3afrTWa1rzpu4bRWGiWJF3R2CcufutAvQyTPEogB
+xso/m7Z4MASoy54RIh7Cu5iA5FFqai17x9ltQm0kg/O8hDOBR9WbeTp4nlMiDBAX2hxlmjUWg5fG
+udQY/EOO/tnVvOje6wUvNo6MXgxt5wrAG3BnlsFUsFaBnrLxWXNZwotTT0mY3LxukanQfJUHWc9g
+R7z4+25S9/6Ql0YwUOsZzW7Ro03eM5jtWWY12W5vF1VInvHxbc+kuB5ghv6AWVCdUIaAnJp6hqX5
+j3ZyIsXh/rikBUlAesf/RQ0LfSoRpC87DRrkmeo9QJPZiuIiqmSAbT6iBh9hO4+4kUerpndPkHtS
+e1n/5F360bV6yMce8bxBldBsxzlFHRoy9hn0hN8xBTkgrXGYVNfFVWW5GE28H4i1CK4/xvlj4DzI
+GtgZ5RShFeRkKXB71ZTG4KJEIUElAygJPk4i5+AO/OZrlgRZMcUeYAY/xniFHfh+ni26eaK4QLez
+9jigwkMGjAcy6DMCrKpru7+6KaA9rKdbOdthMgaYz+R433RMhB2MNcSZTX0ONGYxqOogVjM0m/g4
+tcp4Lc86Paditmgwfi6PGV28sSUEJqlrqq9dBblaKV3uQJQAFBRM4d5y6f4oXwmFDaWui+zrOFYo
+A/ZAtUZCLLemvsq0SOeS5Lw6212QSs/5mk4FfzV2kjEub8l7cDPYluQI5/rSkGDVopYlTQShBY1e
+8ECWor62jQfHHonsapGeWH2fErALtBh4olvxDCD3Kh/qzUB8D8cS3zDUA861/o17RX9r5wzrr1uT
+Bwc+Kauvuz5c+MDAQbAp2daJKnGXDvV0kH79/Icfnz97+ur512O5EWzDgbqQlE3CY/8UAeyeasd/
+MzoIpXeDBSKuwh7kjrFxmMZ9tKn8RP2lLJWxJ7guDIsmkkPaAdBkFvghFk7jqBZ2gzcsf+zX4E1q
+7SOLPPFto9/U3llfuU73+BUbCCMFtCms3Cj3bjOamE3QHinWslWA5lf3YU5fT8lfHF5pu1bOt3lA
+8ueCJTPT66LaMktJC14SWlcpLHsUK92GpXn9Y4W/Sd2cU1QcVV0YaJ/iG8/bNVP1PA1nXwCLQz+m
+oZQbet8XhC1mgMF9btmJlaW4KJ2gGPSRCeBxwVXpRy3qKxNE9Kb3sP1BSL2EY208Q00rTyZ+LhMs
+zW79+5ZG2YqfmKQ99Ov4Vaar3VJUBdWcsIj9VATlNob4RDYGC25htttE0o67CQHJDStqfaFfugQT
+C8DkWksTaof/wPcNNuD57gm2iV49x1tAklPavCDG+73gtbJFpSu9itWAzJfGsAZfmXgdbN5W0lxS
+3os/Z8K8snGS3ZB8zScPP7fZX0lRjmWHVD+IaxLu40/DjIHvTJ68ZKVwgmLwBLWudk5W6qNJZP1i
+yR+89eU/XLWlS7qKZoozzLzCHjpB0Iq92+To610sh8pD6IMb5QAHGdpDlEXyg45CGydJOK+pxDzD
+A+68vlEBtPRhyE9ugs6MBBLr7BbOwiGcCdUe770E0eXnRvpmzCWcE0njHfdVohLWdO4eyOixWTFZ
+K8ka7zvIRxfkZy4DnXJ3xwyr35IS+OOP+cAGoRl60mFRnwgsv1/8M9ooOSEwpJibOox685YmQoL0
+vde6BRdS2ZP7wEGYKadvNihMd3bH024r5ScAfw2Tbb1dKGzirlW9e57cqGou2rvIPISLCEyftFEq
+YfXNDEPvvZhI5diM81YlbBe6CJXZr4wX3716/uN3T18+//HH7398kqiVCfjwcTBEfntNjdewE2If
+I/67X1bWu+mHl69//+I7yyl5nFCaTcnzMvR4JYXhUdRBdYX6AvRiuqRXrQrlI7PAI2XUoAROXhMG
+N3AHIsVmu1uVhDcoYWltgjmjJD7QCc3zq1+UG8JntsqzFw6+d7wt6N0eevH5Cz+voBhJMbLiBPkR
+ZlYCcQbfhKLMGWSmHtzCJ6e5ClHg6kE3yh62aC7o5lFuM828qudD0j56dq9D4YIqBKTSqFr09kOd
+JOFGOg7ph8kxYidWrSSwF8sfe3ag2d+BdtTcj4ehCH08Tp3sXorkfDFxHKRwNxmeZT607kpy+FjP
+smub3DuSmUqaej6ynoDbeSRdIUYNApvr2Ryxq6kMx9bLSF5c5IHp4JRuDJSSHEo7OKzrvTXZ2E6a
+sC7mjXLdbDhHb3sHEVItpD3to7kOIlnkgaTsa9i2byNGe1h5tuB0DdXcO9sRT6aAMsxD4Ut4CvSG
+dG+QY2dIcKIl7N3O3i2Fpgq1rTxNDz0qCqbmXWB+xbCSa1PFBYQrZ7dexDwA+Fct7ePHPYbET93g
+xe3wcdXknzOg0WqVjdGk+Ne4soMWxntjdzS2wafDHU0Fj/uOtm4rtKfGmuvmDS2ThOxjDkwCP8UZ
+RQ8l9VJNjKvwRhmRwa9+6JFJX/keOuuUYiIoCf3zicleJw9a1GU+oF3CisUF3LHXJbx05/ldhH/X
+CvidRaSZveV5becghUEk5lU5IrrPZc0e4paQJ5PjLuaPUDTcF8gqRVEk8LQ6axZzH6TeHVg/8+/W
+X3Vz6JREztTn0tjwgX/Oonq0nqaVXrS3cRJHPNdP6UtyWLrs7cb4OaHDzmmf1ufhhOCIReLx7wS9
+jd5108fOaXGFo2fPs4icINepDGLgPGycX0RpgbqeWLhBD1l96d9gcumZDcM9pQTHlcSO8+aQkyL9
+yCKh9WbhreqoolQ4XiXSfMHwo2JWarYh7bm7vNJ4GlL3jfeQH3nh9hLOPdOPo5Tl2Ue6QW158ih5
+MJciyJj4L2fhYxTu1VeUDQ3In/tSV3zN3C4C7H6mKxEH6HawWEX32vrPC+aN3TxvSkGstwwp6PG/
+GG1brCrqu+l11GI+AASaMq8L+SpQWNhFVdJrVqFSIl7JexzjzUYLPe6TC62lwVd6OiHEDvIo4a7l
+RZJGl/oKzbukhU4L396HOl4Vi4+FTsaf2GdGnrvrRbnF/BDwyE1Go+QHSrjGL96E/IpVgaHqLI/h
+FlEW1mx9u76d2n361/Nd4w0a8AatBo7UeYKFRw9a+P+nNFppvKulT07dyROFw5Q1ZAI1ohyLbRyD
+HiH+SXKUkIUv4JHasPvmwHFetUJSnAq4fECr1VmtISvG0XnjmCl7hjh+VzfVbLdF35v8oPc9b5/v
+Pd5hTLyDiPl+YtUcJko9PHGUxV53HYi4Sol0vsD8JCtiDG3+IczDHbRterLzlJEKR3l9x0z5Srs0
+r/nhbm+9qT3eJ84Wm1BaKQq27ahuhaJhFcxxgx7G02gGOuQwJWUANwEoQsBdWQesPFInn49PuyN7
+O6NxUoUZJ3wBWRQf3kUvF4f7pW4vOzlsXLZQXrUrH8FJAWHUq62+edUNQU0XnnjlKGSMDCFWobzn
+vUuc+COcpplNgvVQG5fmUYRcVHgoe9FevYmWpNg2yldkoAaQdwWWH8e25+jn3D+HkhAV905Ckbyk
+qLI9AWpLTKtLFxe9ah5ovSmlPZXmcxfZKbaVMcXiIXposXsbevGwpF5ySGGN0MGUvkT7Y7dWRXTz
+QteuWckJUhYVIn9gKyo6AVp6VyYOdORZNStRZcruXnIRcPqWi0aQ1DCx8aZWQacIh3ELz8kPFZzv
+Kj46jmF571a+5dgJ98JkMQQ9AsvVyxvIq97RbGbjMdxCx45yM+xbo1bwRyt29ghl4uPosLgA1aAD
+Q0kZBtKCoEjf9apnanuAHGluwmK50XwflcO+60Nr4q5Qf0FZRR1yPh4P8vEYWQnqiveYFTeQ98qM
+W3T3dC6dejXnDD5eXuaeOSIqYDWfmlOjpomYBLPLEtPAnxyPT9GVH92PEoqJx+H5CY9Ybe7HpCuy
+5sFOwv5OxvTEw9/z0/j6uxltnPl7Ke6111CzwPmGnZm+xpHOuEm5CKFWRM1FrnsLnQY6HeQRt6hD
+kZLCxDfOLg3MaEbHefIxCHRJenAnuQtDpVaQ2hd5eP/KZejcvdVNLSr1YeKEF1rnzPlehMpuo2ma
+elZu1QFl5TwC1jFMHscEOfGTn/JzN2ZvViXUfRu1SYdSq7pEp1J/4Htg+mnBnVHDhj6OiRsiVr6r
+bs+acjMn8+hmtw4g+ClaDCsEJafLatkcRGdoGdTyeAkSJAbhJqtepmZA2lZLbzT/HRsfFlCiCplk
+35zNAMOGCIcvrv6DX7UHdqiY9IDTOnrN8nuutBEZOgt5YxGDtFak37Er/BaWSsi7N7NN2V4WSzhL
+8CzofKyjiOg8rWAN0r+Tvl6ovlLCnmkv9rnxtS99yFrU8O6UF+M3Xji7aENmrV3jgzyoOKROKR61
+SQmKrODhPW+WZe1aZt0qCUOlEQIX2UZVjrtLhLhP0kfpaIXJKhGbmzNFRNynUPDjP801++YNXrGP
+0pzSDDl9en5wSukO7DT5cqQ0HfGZ5WHvcUsu0HzMIQqz0NHS9CNOSRl43B93K+PG6s3PpcOsHrT2
+Pdq8sdYayDbtoQw9UURwmgZoNtQu+na5sDbCtvHpYVEO2lujrIJNOaobnzXECYwNy9r0FXsTccGe
+Gaqnra1qS9md4ysPpwcPS+dUOoHhxFqHXgDuubsX+EhfWiC/i/xk/Jknru+ZFchKsUqnVqJd+Baq
+JUOaI1hY5Ryv/jYOFxSBgLqJvJZZij85zXvt4jd4taznZ/jCXWV9WGU3fRhMgZzR5Tvnug9xuBc5
+Wa+aAHOM1sCCS1GrovUAsYlJoa596dKGGX3xN09fvHz94/Of0vygQy3R2UX/LBW+WkcAgGOsdo7K
+plr3PHYCbV5oUO9K7sZXte7R5zb79EvrNvWv7lAiaXa4fVqepKYD6hE59lelHTaU/TqkQ/53PYRj
+TuiJjCPyevqQTYm6KGD8QpeuTMsSPXTB00lsGx7HL3W7bFDIBAXPoC9POr679XIryBDN+T2aV05C
+e/ag/QV7OtmbpvegZ//X2F13p7aSr4mZUsaQi69wnw68HlflOkqHqn5A7dLcyQhVEhPOIR7Pb8dP
+bFV+PDo+7XF4lmKRk81vr8D6SJfgdK4gTGP2wGTUYT00hnF4kFCYG18L2p1MjN/mYZhIEENyw0VS
+0c+5aw6tebcptj8Ir1EsKOFSWCJcP/xW3Z7wt5WWo2Tm5N3i0nPYGHeG6Xo9/1fF5wiBuVwl1XK9
+vcWyQwaKqFyYiAgKmZEXqJaL7u4ikXXlE4UBqFmmD+aiqEadDNTJhziaPPcdvI3Vg+r7qTiA5zRO
+IiE50Q9IJfKgeIxXAlDbnPsi47lPTb2WxsBdMMbPodOoofjQvVEPO4yEcdefiL4ivO9sN1+XGO+0
+lr2LB3fBLgRegUhWPQJfOnrHD7p3ns043gM6CVQ3600A2d/bxVKwGJfhY298J4+mSxdIjhPkWAf9
+7FZwkOOSluMMc2Iv9ikQbGoMcrm7h+Lvs0E0lctGgfkPruxQPDwrYdTYFa6Z50MQ5hpUT4cHbUH/
+nw3yuDxXdrrBwavbNb8+hlboeJjGD980VzJsbRSWYvrVsOhC0IKXwWBBZlf2Oo1g4N3a5uabiKhx
+W1eLeXLb83TkEjcHB++vXv87Lx/Y++tXr/4nBqlZV5sRvy4p0O4RhwxbyXaWFQIJ1O2yHSZv38L3
+sNpv35J6gz6ez+GTgvExCREk0WA35NzPBJ+5E1NmJHO1AF0MJIaF0WFD/TCwBmP+pMNuLIzzOUXq
+3baCg2GhXjB4hF5Vex2x1TGCcaG0dD7XQBL5X6Clv6yaHsyL1p/FlFLQpUNORTdBQV0BXci8U39M
+hLOBeBZIYHp5JtxvgCZHeQEcTAsnd1wsadzYYFZclyDdoDW02pDbjlkG1HSX81tO10qNPNLYqZgd
+St1NyKth2hrZEoqn9qDTEI5Sw1XhapgY5Q4wC0MhE9xInX6ro8nzuWrSPmjmd2iDC+hEVM+4dZWN
+UWCsDoyHRwDMwFXRnu9nqTqQfBNwQuF08jOE/7a4Tkym/VO9HpykUBQZOhRPT72KrtwaPPa0QKwu
+lkEq85ojx2Ae6nec6/jr7xopbQKvScwsFwv/ctaQHHwXYBquu4pU294SkjarKxUrrkiqs606m9UZ
+Ji4nlvcyGic+5d8eq4RpkbSUTiPoT2N/tt46CPayBcGT0VLcSZxbIr0UKV5VyFlBBPoGK5hrf1Vd
+nwfoK2iFUSgq6etX34y+sF7X5wrYxF80bMobIVpdVxd107HMKkr7Zvvi+4GXrE8lNJPsxD7OmwGW
+m/AB7ALihw5+2s5lC7/5erBqrjugfZD2JUGps7o5ZVyL/uI04Tl5W8PD87/X+PYfnV7ZYHTmlz1H
+F9HjCHL+syDVXUQL3Z0oI7jeROgUZufmZmQsPQ9wwU/NGGDPzGwOEjDeaNmeuURV1X5rHvR8KplL
+9c3KuNgxW0ovDHT8RomSeoCfaG4vfK1WxUWR/JFk5fiymPvI2m2fwxALneo9DNQIlh9MadRsHoeL
+p1SHHwvm0I5Hv5VccYr1LE+qPHKral2dkA45fijKoQ8RC5i9aoxFmvGN56vsGHOUfkJnhwyFuSxn
+AaaczXbLHXpWyXWJMFoYs4mVoukK3MyRwQFwf7Y5nn+NRCzUeov8KYQnc1auWOOK3Q21uGUOKsEa
+0ykNaFN0Zbrs0A1eMCifoYHQ2zL3SrOIQpfwiAiPmS0hmdvSjHySeO0RDPQ6PqBYLyf88ZQzazom
+AW/bfFLWQksfmxSa35GzvS+FuDuPVBQVH+YVivlXJQbTiI/DIP8g0vB2JEwh/QE74i56t6lYHypa
+OxHDunxR4iPDJzMsUk/bA+v8nhydYppj9Xcfjpxd69iqdXwa9SrmX2M70MtbFKq76axL/lR0Eu67
+AAbc4hceh1RlLGxeUw7aVb+nkbSSum7nFjp8X4qTQkJqxlm+5fhN7lUZ6wqQq5KaoMti0p3S0JCG
+WpSszxIWlGYClA8d4N7q52LKgTbWyY2dRe+GjHVpB0/EJxHZlKCQu1b2gXLLFVOKj6r/VN19wKax
+pXDp3PekimFU88S8BAA+cHXvPW4wqdVlbr7xb/RAYOu5bT0prAv9UaZ8CH/Mdpu2vqpU/0NSkm/g
+9sKxJHHWZLt7M+I0HpglGgUWmJHxuqK8jFbjQTMRfwxkxHd5N0ZzRmvaEJ88N1e0SdYR1R74XAl+
+i0eosT6oA2eBUwxEZblwt1jwo2If0NVMqQ7u2ZNTKjzXHzocDYf/oZP/MHfJ+wgCcbK4/1St5B9R
+DhCkALEuqqlLpP1Szn5noZfs3T03l54aR+fVZ6QLW7Bwa/cIGLZc4VWy5QvjFhHFiLjjqAa1E3aE
+uNOKH7x1DuJPobjAQqyBnCumfLOfz+kThSPzqwOjUfg3SckC177CrG9RLkDzcuro/dUqSZsDzBpt
+UrWkaVqtSkILMu+ARlCoCH7ZYAQ+Moin1DspSg7MLY3rxGhD5VVZU26B5KoutVGjwJeSrHv+9q26
+vZAAuRn2AZXVwHoDwi/GvYHiZMsp1KiVDjulNUjZvYBmVmiSt3RlnKBACtAnhraKLHduo2IqnRcn
+Uxj4uqa8c6nP5/deacJmVBlZMRDjmJb58X9ei416j7tW+x7r7OkTLC2MBeJr5fZiklfCIMZ3tEnT
+otY1vc/GffN17mmmpWQ3gCkXozoBdqnWRduljCLS1tOZcPOOVuy3sKmmhdA73e2VWS7vk2JUX0qF
+FBVsfWVfjzRrUVtcTe31amjTtMEq8djK2CL4+5vX/wZ2c4rP6RJv7fe3rz83STjWtzF0VKoQpiZ9
+/6fX/72y3K7nZ+///Or//tdstSUJge5QPJJnu4sLrdr54evfDYnhSpD81/RztbkrBZif8+uXN8jC
+FO6F2A+3CVTZE66fqJI1dNbayBrMZQ1QiceukD5iP6WXW6OTvsb55rxrmC+HkxFmYykMKzzIC/39
+X/eB/jdabZ2dUM3Pfk724rb/MD97sbpq3pG5IoOqNX3KNKvQw9MsPfmhrXbzBomCYedgpNWG2Dku
+FRD6IoGGTPJFisSzMHL1uyyA1NTz948E0yeOjLrV5Qyhwo5umvWazMGr2+TF9+bKcdNAnm8k+Slc
+GOSyiZ9h7c+nmIrBkV50xm3822AdyOgPDjy9UrcEqO23lrLZ2xEYCX8xCC21Hk+jG4sZL5Tpfp3d
+R7cU0V3HVGHDUNXliJH0Du0EUvbLxYBXlUPkE1RluXs9ePH9yMgReJRQIjg/z60lEvsl0h+Qtn2k
+BrTR6oQCoetHE6+EJvRCtp608rFHKU0veECG32rHv4nqbw+XiJhy5A61iPPwN9Owj5khWu+O6nsR
+BZqBeNt8hPsfd11rzHWZ02hWNP4F3pHm4dgd97nfm9BKLacTJ/rYJn2JIi1RrniuMojl92yCiPoM
+iPp387P/bVdv45phfE11BRql12VLHrXp3XXZWtWiisEAi5ZnzRXmQJP1UTaIah5RRbFf6DVeBiN8
+v2F9HzY/a3UyM06TEUEhIHRZkKeXdLuUV02NGcxgVDoByqZCe9oczkCzw4eG1QjnKUVwhCUI9gwr
+u4AjiTdUi94nBw7H2os1+5G1aY7+1AfdLM1hZzrhT5p3eZbbPuVO3QolEJwxnJ7U9sB9msybGZHY
+61V1sybPSE1n6kqCxTzfLdhBqsHzgqNfFlYzr2WbdrClm8Ut9mTy3Um2kC7nwzAD6VAx4p6xeXS4
+PVM5T52W8BOjGD0+7TPBB7Wn8oddz5r7YHvmboKOq/KTatqqCmI9diOKsc3PjPMMfGA5R7G1gVxH
+uZvQBuhqSpHwCocOZGxfz4Y/AzfjKwTbKKK1Anyz7kTU2NayvMFIdROKn4yS49AMwgAHNUMsYrmT
++hREARCVOBEa2fPSIK82kKsPpucMYDQ5jscN8lx5QWGUdIHzJ+fRti60OA6PAEYIhyV4/5fX/1Zn
+Tlyu4cnz/q+v/tN/x4+bdremFwmdgE1zVRP32CrvpgRK031Ws16C066LA6ryOw2fORTNq/pcNqt3
+1e0as7cnUtT6ymQPoaH9Lazp4s7cIfdKGMJC0sRNU0Q7xKthYxoz5ChOX2EUkffPENdhcrxHYvZw
+5W4Z/Qbfi+7JBKZyAe+mlfSBKQLxOxhfvaBclfDIghV+QcnPdu0OZQ6nhTNGJ4ZtUXdJxjPKQh9h
+1vG4eblouxHsRoVc7Fb1+101Ug61I3xZcECtmY2rPF2Ri8LFrtyUQHoV5U07q7i5wl4sw1GBGSya
+C3iuruvrcgN3x5Pj4hg5OU2Cxh8OP82jSgTYRcxBTvuVC17swN4ygh3Tu7t8Z+2sSl4+TFa75RnC
+uvtJ0lXTVgCe6c2Xg1QjXu4zSZmOdYrlOxjOIEyaHnLtta+1KEj8VX1MsR1G5J3oaUQCd6o1pspE
+kBZcCzUOAkx/N0X1MPrAueZRc2IGKS8XemAFq28lXrFXJfI6lQqUmT5yONw3aGfoNGl+VDf3iZb2
+99B1YQtalA1V34eM2mrPVSupH6JxR5oEZpcVXFAdF4AuBW9ckCkjgMceKe0D8tA14G6KygQ9LoYg
+O7Wa29q0jdoN0aQFlYScVtW1Lp8Gl7Pin4awLLwan99Li1xiv3yQNGTr3pGBbinNn331OGmI/OSE
+kqfgBGYMAmEDsyh4EGJwWqITN7skKGt7NmWmdsnNZ1BnSEYI9AYWlbBXVd2kmbmOsFphPgYtRG0P
+3HFofNCa/s7bilOaW8YBvILodkAOX5XwjSMKJOaqYEaEeXnx/UEgHu3uzOpA8jK7HIF33XCF5BWp
+zJQygzOsU7rmtw4Zv52y6GMG7VoqBM5MWyiM506h0RSljEipqHXfnQ3Skzd/OMVrCcU2w69vrMYU
+cTj7W8glE7tabGUnBgv98+t/j9poms0M1rTabevF+//91X/zb0g44xzVkoUC3f0x72hCr/LtJerN
+R215jkbAGWpi8TGHV2XJotnBwdPFInmGv3FkJR8s4NbNBvMgzjlUkv5UEP7zCvNzb245zvOA7URs
+XmTfC3W2WCYgEyg/drZ1uZV83jIekuo4STZjuyBUroh/9DdQxkUlMbAsAv6ubOsZjXjAW5l3ioEg
+qONIQSqdHD/+wmcP5leW6eWDW2i92a0Q1xCfuKvtwKozsuo8+sL3kZzXsy1HGljWCng+x60VWLrg
+3z0PbV5png6ud9xMQg2cwO+nNkzizq+NAQbwRdA9TRJ2DsiVPWUGselQ+wh3hG3YPlmLoBuX7fSA
+nhiXKDODvRy3MUqeO4lAGKAV0RE9FDFbQ1Qk3TM4mpbtK2WR/V6DdBvoOk/eXuxMN2q//D2nb/mB
+78Bi+rsYEbSoEMFYKjomExVXS7ieK22tSLSWY6LDSWm/XPHWlHsy8U+Ynw+lusLzUc5mzWYuuJg0
+qayVMQRu4RRDPuCZcxE+EJ1+pRJlLmtofOXprIm75GnYTdGSxvXAh99Dlm5NceSyh8BRlmo88SOv
+1bisCWiQxZMxVTrtArGAct++Stp6u2PeTVy0Ym6eLMm/7QxhRldVt0OmzbpD4UD4K9LmrGm3T2eY
+mpc5rWG6Rj5InnLZV8CcH3HhEQFp4obGrhtLZQi/iU8e5VDiXL1wjaG2cScSAeVj2sC9NsNSBy4G
+5W45KqnLqh0156NyxE18TLfGaNuM6IiNoI2RdU7wPxQZ6CshfewGOC/G2+5AYOFhMWYrUamLjG+u
+LusqwHu2vWwW9Mxtd/AyniGKpJnvN4io6axFcr6obuozeMPDi3rJ6AXwwqZQVCNVkcSntlZGg947
+JU3TlWEO+cLUspY8+MkREqbHZh9ZFShoJaSc7sEc2Zg7UZexdUAYYEFq2N74q3m0vPCwP9A6V/Nn
+QjHPiS6hMTywILNgf0CTQpTx0nfd/6JMhUXlXQ0uPpUjmknEDb1n8lTMW7eBzljqb7OEbD+O3e1S
+62HQUPwiNyNRY4MjAAS1pbXZmWP6FM22PYeTpEKmVGJSLTF9/sLQLdIS4Rs3CZCvS1B3ClT0WbAp
+JsdHxZE9dzwFAzPIIc0vL3SDpqk8EMukTRbL5MO+YpF754ZSBcJ30iUCMsLNusY0gDHvTFfIDQN8
+1IXv/m7fz/c7X92niKdDK2mdEX2uEJrPXbau4Vh0c6/jQ8tETAt79Ol7nyPktmAWxmyBd3K2fZxj
+q+ULOUjv/9Ou+H8AENJEAQ==
 """
 
 import sys
diff --git a/astropy/io/__init__.py b/astropy/io/__init__.py
index b062db1..29db62b 100644
--- a/astropy/io/__init__.py
+++ b/astropy/io/__init__.py
@@ -1,5 +1,5 @@
 # Licensed under a 3-clause BSD style license - see LICENSE.rst
 """
 This subpackage contains modules and packages for interpreting data storage
-formats used in astropy.
+formats used by and in astropy.
 """
diff --git a/astropy/io/ascii/__init__.py b/astropy/io/ascii/__init__.py
index f6fcc2b..b67a2d3 100644
--- a/astropy/io/ascii/__init__.py
+++ b/astropy/io/ascii/__init__.py
@@ -1,7 +1,7 @@
 """ An extensible ASCII table reader and writer.
 
 """
-## 
+##
 ## Redistribution and use in source and binary forms, with or without
 ## modification, are permitted provided that the following conditions are met:
 ##     * Redistributions of source code must retain the above copyright
@@ -12,7 +12,7 @@
 ##     * Neither the name of the Smithsonian Astrophysical Observatory nor the
 ##       names of its contributors may be used to endorse or promote products
 ##       derived from this software without specific prior written permission.
-## 
+##
 ## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 ## ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 ## WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
@@ -21,7 +21,7 @@
 ## (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 ## LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 ## ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS  
+## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 ## SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ##
 ## Copyright: Smithsonian Astrophysical Observatory (2010)
@@ -31,11 +31,11 @@ from __future__ import absolute_import
 
 from .core import (InconsistentTableError,
                    NoType, StrType, NumType, FloatType, IntType, AllType,
-                   Column, Keyword,
+                   Column,
                    BaseInputter, ContinuationLinesInputter,
                    BaseHeader,
                    BaseData,
-                   BaseOutputter, NumpyOutputter, TableOutputter,
+                   BaseOutputter, TableOutputter,
                    BaseReader,
                    BaseSplitter, DefaultSplitter, WhitespaceSplitter,
                    convert_numpy,
@@ -49,10 +49,12 @@ from .cds import Cds
 from .latex import Latex, AASTex, latexdicts
 from .ipac import Ipac
 from .daophot import Daophot
-from .memory import Memory
+from .sextractor import SExtractor
 from .fixedwidth import (FixedWidth, FixedWidthNoHeader,
                          FixedWidthTwoLine, FixedWidthSplitter,
                          FixedWidthHeader, FixedWidthData)
 from .ui import (set_guess, get_reader, read, get_writer, write)
 
 from .version import version as __version__
+
+from . import connect
diff --git a/astropy/io/ascii/basic.py b/astropy/io/ascii/basic.py
index 20eb810..43a1acb 100644
--- a/astropy/io/ascii/basic.py
+++ b/astropy/io/ascii/basic.py
@@ -1,4 +1,4 @@
-"""Asciitable: an extensible ASCII table reader and writer.
+"""An extensible ASCII table reader and writer.
 
 basic.py:
   Basic table read / write functionality for simple character
@@ -8,7 +8,7 @@ basic.py:
 :Author: Tom Aldcroft (aldcroft at head.cfa.harvard.edu)
 """
 
-## 
+##
 ## Redistribution and use in source and binary forms, with or without
 ## modification, are permitted provided that the following conditions are met:
 ##     * Redistributions of source code must retain the above copyright
@@ -19,7 +19,7 @@ basic.py:
 ##     * Neither the name of the Smithsonian Astrophysical Observatory nor the
 ##       names of its contributors may be used to endorse or promote products
 ##       derived from this software without specific prior written permission.
-## 
+##
 ## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 ## ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 ## WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
@@ -28,7 +28,7 @@ basic.py:
 ## (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 ## LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 ## ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS  
+## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 ## SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 import re
@@ -42,7 +42,7 @@ class Basic(core.BaseReader):
     configurable.
     ::
 
-        rdr = asciitable.get_reader(Reader=asciitable.Basic)
+        rdr = ascii.get_reader(Reader=ascii.Basic)
         rdr.header.splitter.delimiter = ' '
         rdr.data.splitter.delimiter = ' '
         rdr.header.start_line = 0
@@ -52,7 +52,7 @@ class Basic(core.BaseReader):
         rdr.data.comment = r'\s*#'
 
     Example table::
-    
+
       # Column definition is the first uncommented line
       # Default delimiter is the space character.
       apples oranges pears
@@ -106,8 +106,11 @@ class CommentedHeaderHeader(core.BaseHeader):
 
 
 class CommentedHeader(core.BaseReader):
-    """Read a file where the column names are given in a line that begins with the
-    header comment character.  The default delimiter is the <space> character.::
+    """Read a file where the column names are given in a line that begins with
+    the header comment character. `header_start` can be used to specify the
+    line index of column names, and it can be a negative index (for example -1
+    for the last commented line).  The default delimiter is the <space>
+    character.::
 
       # col1 col2 col3
       # Comment line
@@ -130,7 +133,7 @@ class CommentedHeader(core.BaseReader):
 
 
 class Tab(Basic):
-    """Read a tab-separated file.  Unlike the :class:`Basic` reader, whitespace is 
+    """Read a tab-separated file.  Unlike the :class:`Basic` reader, whitespace is
     not stripped from the beginning and end of lines.  By default whitespace is
     still stripped from the beginning and end of individual column values.
 
@@ -145,7 +148,7 @@ class Tab(Basic):
         self.header.splitter.delimiter = '\t'
         self.data.splitter.delimiter = '\t'
         # Don't strip line whitespace since that includes tabs
-        self.header.splitter.process_line = None  
+        self.header.splitter.process_line = None
         self.data.splitter.process_line = None
         # Don't strip data value whitespace since that is significant in TSV tables
         self.data.splitter.process_val = None
@@ -184,7 +187,7 @@ class RdbHeader(core.BaseHeader):
 
     def get_cols(self, lines):
         """Initialize the header Column objects from the table ``lines``.
-        
+
         This is a specialized get_cols for the RDB type:
         Line 0: RDB col names
         Line 1: RDB col definitions
@@ -201,10 +204,10 @@ class RdbHeader(core.BaseHeader):
 
         if len(self.names) != len(raw_types):
             raise ValueError('RDB header mismatch between number of column names and column types')
-        
+
         if any(not re.match(r'\d*(N|S)$', x, re.IGNORECASE) for x in raw_types):
             raise ValueError('RDB types definitions do not all match [num](N|S): %s' % raw_types)
-        
+
         self._set_cols_from_names()
         for col, raw_type in zip(self.cols, raw_types):
             col.raw_type = raw_type
@@ -214,9 +217,8 @@ class RdbHeader(core.BaseHeader):
         lines.append(self.splitter.join([x.name for x in self.cols]))
         rdb_types = []
         for col in self.cols:
-            if issubclass(col.type, core.NumType):
-                rdb_types.append('N')
-            else:
-                rdb_types.append('S')
-        lines.append(self.splitter.join(rdb_types))
+            # Check if dtype.kind is string or unicode.  See help(np.core.numerictypes)
+            rdb_type = 'S' if col.dtype.kind in ('S', 'U') else 'N'
+            rdb_types.append(rdb_type)
 
+        lines.append(self.splitter.join(rdb_types))
diff --git a/astropy/io/ascii/cds.py b/astropy/io/ascii/cds.py
index 7eda272..8e0b882 100644
--- a/astropy/io/ascii/cds.py
+++ b/astropy/io/ascii/cds.py
@@ -1,4 +1,4 @@
-"""Asciitable: an extensible ASCII table reader and writer.
+"""An extensible ASCII table reader and writer.
 
 cds.py:
   Classes to read CDS / Vizier table format
@@ -131,11 +131,13 @@ class CdsHeader(core.BaseHeader):
                 col.start = int(re.sub(r'[-\s]', '', match.group('start') or match.group('end'))) - 1
                 col.end = int(match.group('end'))
                 col.units = match.group('units')
-                col.descr = match.group('descr')
+                if col.units == '---':
+                    col.units = None  # "---" is the marker for no units in CDS table
+                col.description = match.group('descr').strip()
                 col.raw_type = match.group('format')
                 col.type = self.get_col_type(col)
 
-                match = re.match(r'\? (?P<equal> =)? (?P<nullval> \S*)', col.descr, re.VERBOSE)
+                match = re.match(r'\? (?P<equal> =)? (?P<nullval> \S*)', col.description, re.VERBOSE)
                 if match:
                     if issubclass(col.type, core.FloatType):
                         fillval = 'nan'
@@ -152,7 +154,7 @@ class CdsHeader(core.BaseHeader):
                 cols.append(col)
             else:  # could be a continuation of the previous col's description
                 if cols:
-                    cols[-1].descr += line.strip()
+                    cols[-1].description += line.strip()
                 else:
                     raise ValueError('Line "%s" not parsable as CDS header' % line)
 
@@ -196,8 +198,16 @@ class Cds(core.BaseReader):
     """Read a CDS format table.  See http://vizier.u-strasbg.fr/doc/catstd.htx.
     Example::
 
-      Table: Spitzer-identified YSOs: Addendum
+      Table: Table name here
       = ==============================================================================
+      Catalog reference paper
+          Bibliography info here
+      ================================================================================
+      ADC_Keywords: Keyword ; Another keyword ; etc
+
+      Description:
+          Catalog description here.
+      ================================================================================
       Byte-by-byte Description of file: datafile3.txt
       --------------------------------------------------------------------------------
          Bytes Format Units  Label  Explanations
@@ -207,19 +217,37 @@ class Cds(core.BaseReader):
          8-  9 I2     min    RAm    Minute of Right Ascension (J2000)
         11- 15 F5.2   s      RAs    Second of Right Ascension (J2000)
       --------------------------------------------------------------------------------
+      Note (1): A CDS file can contain sections with various metadata.
+                Notes can be multiple lines.
+      Note (2): Another note.
+      --------------------------------------------------------------------------------
         1 03 28 39.09
+        2 04 18 24.11
+
+    **About parsing the CDS format**
+
+    The CDS format consists of a table description and the table data.  These
+    can be in separate files as a ``ReadMe`` file plus data file(s), or
+    combined in a single file.  Different subsections within the description
+    are separated by lines of dashes or equal signs ("------" or "======").
+    The table which specifies the column information must be preceded by a line
+    starting with "Byte-by-byte Description of file:".
+
+    In the case where the table description is combined with the data values,
+    the data must be in the last section and must be preceded by a section
+    delimiter line (dashes or equal signs only).
 
     **Basic usage**
 
-    Use the ``asciitable.read()`` function as normal, with an optional ``readme``
+    Use the ``ascii.read()`` function as normal, with an optional ``readme``
     parameter indicating the CDS ReadMe file.  If not supplied it is assumed that
     the header information is at the top of the given table.  Examples::
 
-      >>> import asciitable
-      >>> table = asciitable.read("t/cds.dat")
-      >>> table = asciitable.read("t/vizier/table1.dat", readme="t/vizier/ReadMe")
-      >>> table = asciitable.read("t/cds/multi/lhs2065.dat", readme="t/cds/multi/ReadMe")
-      >>> table = asciitable.read("t/cds/glob/lmxbrefs.dat", readme="t/cds/glob/ReadMe")
+      >>> from astropy.io import ascii
+      >>> table = ascii.read("t/cds.dat")
+      >>> table = ascii.read("t/vizier/table1.dat", readme="t/vizier/ReadMe")
+      >>> table = ascii.read("t/cds/multi/lhs2065.dat", readme="t/cds/multi/ReadMe")
+      >>> table = ascii.read("t/cds/glob/lmxbrefs.dat", readme="t/cds/glob/ReadMe")
 
     **Using a reader object**
 
@@ -231,7 +259,7 @@ class Cds(core.BaseReader):
     have header information for the given table.
 
       >>> readme = "t/vizier/ReadMe"
-      >>> r = asciitable.get_reader(asciitable.Cds, readme=readme)
+      >>> r = ascii.get_reader(ascii.Cds, readme=readme)
       >>> table = r.read("t/vizier/table1.dat")
       >>> # table5.dat has the same ReadMe file
       >>> table = r.read("t/vizier/table5.dat")
@@ -239,7 +267,7 @@ class Cds(core.BaseReader):
     If no ``readme`` parameter is specified, then the header
     information is assumed to be at the top of the given table.
 
-      >>> r = asciitable.get_reader(asciitable.Cds)
+      >>> r = ascii.get_reader(ascii.Cds)
       >>> table = r.read("t/cds.dat")
       >>> #The following gives InconsistentTableError, since no
       >>> #readme file was given and table1.dat does not have a header.
diff --git a/astropy/io/ascii/connect.py b/astropy/io/ascii/connect.py
new file mode 100644
index 0000000..6bd1bf2
--- /dev/null
+++ b/astropy/io/ascii/connect.py
@@ -0,0 +1,130 @@
+# This file connects the readers/writers to the astropy.table.Table class
+
+
+
+from ...table import io_registry
+
+__all__ = []
+
+
+# Generic
+# =======
+
+
+def read_asciitable(filename, **kwargs):
+    from .ui import read
+    return read(filename, **kwargs)
+
+io_registry.register_reader('ascii', read_asciitable)
+
+
+def write_asciitable(table, filename, **kwargs):
+    from .ui import write
+    return write(table, filename, **kwargs)
+
+io_registry.register_writer('ascii', write_asciitable)
+
+
+# IPAC
+# ====
+
+def read_ipac(filename, **kwargs):
+    from .ipac import Ipac
+    from .ui import read
+    if 'guess' not in kwargs:
+        kwargs['guess'] = False
+    return read(filename, Reader=Ipac, **kwargs)
+
+io_registry.register_reader('ipac', read_ipac)
+
+
+# CDS
+# ===
+
+
+def read_cds(filename, **kwargs):
+    from .cds import Cds
+    from .ui import read
+    if 'guess' not in kwargs:
+        kwargs['guess'] = False
+    return read(filename, Reader=Cds, **kwargs)
+
+io_registry.register_reader('cds', read_cds)
+
+
+# DAOPhot
+# =======
+
+def read_daophot(filename, **kwargs):
+    from .daophot import Daophot
+    from .ui import read
+    if 'guess' not in kwargs:
+        kwargs['guess'] = False
+    return read(filename, Reader=Daophot, **kwargs)
+
+io_registry.register_reader('daophot', read_daophot)
+
+# SExtractor
+# =======
+
+def read_sextractor(filename, **kwargs):
+    from .sextractor import SExtractor
+    from .ui import read
+    if 'guess' not in kwargs:
+        kwargs['guess'] = False
+    return read(filename, Reader=SExtractor, **kwargs)
+
+io_registry.register_reader('sextractor', read_sextractor)
+
+# LaTeX
+# =====
+
+def read_latex(filename, **kwargs):
+    from .latex import Latex
+    from .ui import read
+    if 'guess' not in kwargs:
+        kwargs['guess'] = False
+    return read(filename, Reader=Latex, **kwargs)
+
+io_registry.register_reader('latex', read_latex)
+
+
+def write_latex(table, filename, **kwargs):
+    from .latex import Latex
+    from .ui import write
+    write(table, filename, Writer=Latex, **kwargs)
+
+io_registry.register_writer('latex', write_latex)
+
+
+def is_latex(origin, args, kwargs):
+    return isinstance(args[0], basestring) and args[0].endswith('.tex')
+
+io_registry.register_identifier('latex', is_latex)
+
+
+# RDB
+# ===
+
+def read_rdb(filename, **kwargs):
+    from .basic import Rdb
+    from .ui import read
+    if 'guess' not in kwargs:
+        kwargs['guess'] = False
+    return read(filename, Reader=Rdb, **kwargs)
+
+io_registry.register_reader('rdb', read_rdb)
+
+
+def write_rdb(table, filename, **kwargs):
+    from .basic import Rdb
+    from .ui import write
+    write(table, filename, Writer=Rdb, **kwargs)
+
+io_registry.register_writer('rdb', write_rdb)
+
+
+def is_rdb(origin, args, kwargs):
+    return isinstance(args[0], basestring) and args[0].endswith('.rdb')
+
+io_registry.register_identifier('rdb', is_rdb)
diff --git a/astropy/io/ascii/core.py b/astropy/io/ascii/core.py
index c5f48f5..c16147e 100644
--- a/astropy/io/ascii/core.py
+++ b/astropy/io/ascii/core.py
@@ -1,4 +1,4 @@
-""" Asciitable: an extensible ASCII table reader and writer.
+""" An extensible ASCII table reader and writer.
 
 core.py:
   Core base classes and functions for reading and writing tables.
@@ -6,7 +6,7 @@ core.py:
 :Copyright: Smithsonian Astrophysical Observatory (2010)
 :Author: Tom Aldcroft (aldcroft at head.cfa.harvard.edu)
 """
-## 
+##
 ## Redistribution and use in source and binary forms, with or without
 ## modification, are permitted provided that the following conditions are met:
 ##     * Redistributions of source code must retain the above copyright
@@ -17,7 +17,7 @@ core.py:
 ##     * Neither the name of the Smithsonian Astrophysical Observatory nor the
 ##       names of its contributors may be used to endorse or promote products
 ##       derived from this software without specific prior written permission.
-## 
+##
 ## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 ## ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 ## WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
@@ -26,7 +26,7 @@ core.py:
 ## (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 ## LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 ## ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS  
+## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 ## SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 import os
@@ -35,9 +35,10 @@ import re
 import csv
 import itertools
 import numpy
+from contextlib import contextmanager
 
 from ...table import Table
-
+from ...utils.data import get_readable_fileobj
 
 class InconsistentTableError(ValueError):
     pass
@@ -78,33 +79,31 @@ except NameError:
                 return True
         return False
 
-class Keyword(object):
-    """Table keyword"""
-    def __init__(self, name, value, units=None, comment=None, format=None):
-        self.name = name
-        self.value = value
-        self.units = units
-        self.comment = comment
-        self.format = format
 
 class NoType(object):
     pass
 
+
 class StrType(NoType):
     pass
 
+
 class NumType(NoType):
     pass
 
+
 class FloatType(NumType):
     pass
 
+
 class IntType(NumType):
     pass
 
+
 class AllType(StrType, FloatType, IntType):
     pass
 
+
 class Column(object):
     """Table column.
 
@@ -122,20 +121,12 @@ class Column(object):
         self.type = NoType
         self.str_vals = []
         self.fill_values = {}
-        self.formatter = None
-    
-    def __iter__(self):
-        '''iterate over formated column values
-        
-        Each value is paased through self.formatter.
-        If str(self.formatter(value)) is found in the fill_values specification,
-        the corresponding fill_value is returned, otherwise the formated value.
-        '''
-        for val in self.data:
-            yield self.fill_values.get(str(self.formatter(val)).strip(), self.formatter(val))
+
 
 class BaseInputter(object):
-    """Get the lines from the table input and return a list of lines.  The input table can be one of:
+    """
+    Get the lines from the table input and return a list of lines.  The input
+    table can be one of:
 
     * File name
     * String (newline separated) with all header and data lines (must have at least 2 lines)
@@ -144,15 +135,16 @@ class BaseInputter(object):
     """
     def get_lines(self, table):
         """Get the lines from the ``table`` input.
-        
+
         :param table: table input
         :returns: list of lines
         """
         try:
-            if hasattr(table, 'read'):
-                table = table.read()
-            elif '\n' not in table and '\r' not in table + '':
-                table = open(table, 'r').read()
+
+            if hasattr(table, 'read') or ('\n' not in table and '\r' not in table + ''):
+                with get_readable_fileobj(table) as file_obj:
+                    table = file_obj.read()
+
             lines = table.splitlines()
         except TypeError:
             try:
@@ -178,6 +170,7 @@ class BaseInputter(object):
         characters if a row is split into lines."""
         return lines
 
+
 class BaseSplitter(object):
     """Base splitter that uses python's split method to do the work.
 
@@ -194,11 +187,11 @@ class BaseSplitter(object):
 
       reader.header.splitter.process_val = lambda x: x.lstrip()
       reader.data.splitter.process_val = None
-      
-    :param delimiter: one-character string used to separate fields 
+
+    :param delimiter: one-character string used to separate fields
     """
     delimiter = None
-    
+
     def process_line(self, line):
         """Remove whitespace at the beginning or end of line.  This is especially useful for
         whitespace-delimited files to prevent spurious columns at the beginning or end."""
@@ -224,7 +217,7 @@ class BaseSplitter(object):
         else:
             delimiter = self.delimiter
         return delimiter.join(str(x) for x in vals)
-    
+
 
 class DefaultSplitter(BaseSplitter):
     """Default class to split strings into columns using python csv.  The class
@@ -233,7 +226,7 @@ class DefaultSplitter(BaseSplitter):
     Typical usage::
 
       # lines = ..
-      splitter = asciitable.DefaultSplitter()
+      splitter = ascii.DefaultSplitter()
       for col_vals in splitter(lines):
           for col_val in col_vals:
                ...
@@ -251,10 +244,10 @@ class DefaultSplitter(BaseSplitter):
     escapechar = None
     quoting = csv.QUOTE_MINIMAL
     skipinitialspace = True
-    
+
     def process_line(self, line):
         """Remove whitespace at the beginning or end of line.  This is especially useful for
-        whitespace-delimited files to prevent spurious columns at the beginning or end. 
+        whitespace-delimited files to prevent spurious columns at the beginning or end.
         If splitting on whitespace then replace unquoted tabs with space first"""
         if self.delimiter == '\s':
             line = _replace_tab_with_space(line, self.escapechar, self.quotechar)
@@ -292,7 +285,7 @@ class DefaultSplitter(BaseSplitter):
                 yield [self.process_val(x) for x in vals]
             else:
                 yield vals
-            
+
     def join(self, vals):
         if self.delimiter is None:
             delimiter = ' '
@@ -310,10 +303,13 @@ class DefaultSplitter(BaseSplitter):
                                          )
         self.csv_writer_out.seek(0)
         self.csv_writer_out.truncate()
-        self.csv_writer.writerow(vals)        
+        if self.process_val:
+            vals = [self.process_val(x) for x in vals]
+        self.csv_writer.writerow(vals)
 
         return self.csv_writer_out.getvalue()
-    
+
+
 def _replace_tab_with_space(line, escapechar, quotechar):
     """Replace tab with space within ``line`` while respecting quoted substrings"""
     newline = []
@@ -328,12 +324,24 @@ def _replace_tab_with_space(line, escapechar, quotechar):
         newline.append(char)
     return ''.join(newline)
 
+
 def _get_line_index(line_or_func, lines):
+    """Return the appropriate line index, depending on ``line_or_func`` which
+    can be either a function, a positive or negative int, or None.
+    """
+
     if hasattr(line_or_func, '__call__'):
         return line_or_func(lines)
+    elif line_or_func:
+        if line_or_func >= 0:
+            return line_or_func
+        else:
+            n_lines = sum(1 for line in lines)
+            return n_lines + line_or_func
     else:
         return line_or_func
 
+
 class BaseHeader(object):
     """Base table header reader
 
@@ -352,11 +360,11 @@ class BaseHeader(object):
     names = None
     include_names = None
     exclude_names = None
-    write_spacer_lines = ['ASCIITABLE_WRITE_SPACER_LINE']
+    write_spacer_lines = ['ASCII_TABLE_WRITE_SPACER_LINE']
 
     def __init__(self):
         self.splitter = self.__class__.splitter_class()
-       
+
     def _set_cols_from_names(self):
         # Filter full list of non-null column names with the include/exclude lists
         names = set(self.names)
@@ -364,7 +372,7 @@ class BaseHeader(object):
             names.intersection_update(self.include_names)
         if self.exclude_names is not None:
             names.difference_update(self.exclude_names)
-            
+
         self.cols = [Column(name=x, index=i) for i, x in enumerate(self.names) if x in names]
 
     def get_cols(self, lines):
@@ -387,7 +395,8 @@ class BaseHeader(object):
                 try:
                     first_data_vals = next(self.data.get_str_vals())
                 except StopIteration:
-                    raise InconsistentTableError('No data lines found so cannot autogenerate column names')
+                    raise InconsistentTableError('No data lines found so cannot autogenerate '
+                                                 'column names')
                 n_data_cols = len(first_data_vals)
                 self.names = [self.auto_format % i for i in range(1, n_data_cols+1)]
 
@@ -400,7 +409,7 @@ class BaseHeader(object):
                 raise ValueError('No header line found in table')
 
             self.names = next(self.splitter([line]))
-        
+
         self._set_cols_from_names()
 
     def process_lines(self, lines):
@@ -464,13 +473,12 @@ class BaseData(object):
     end_line = None
     comment = None
     splitter_class = DefaultSplitter
-    write_spacer_lines = ['ASCIITABLE_WRITE_SPACER_LINE']
+    write_spacer_lines = ['ASCII_TABLE_WRITE_SPACER_LINE']
     formats = {}
-    default_formatter = str
     fill_values = []
     fill_include_names = None
     fill_exclude_names = None
-    
+
     def __init__(self):
         self.splitter = self.__class__.splitter_class()
 
@@ -506,7 +514,7 @@ class BaseData(object):
 
     def masks(self, cols):
         """Set fill value for each column and then apply that fill value
-        
+
         In the first step it is evaluated with value from ``fill_values`` applies to
         which column using ``fill_include_names`` and ``fill_exclude_names``.
         In the second step all replacements are done for the appropriate columns.
@@ -514,7 +522,7 @@ class BaseData(object):
         if self.fill_values:
             self._set_fill_values(cols)
             self._set_masks(cols)
-    
+
     def _set_fill_values(self, cols):
         """Set the fill values of the individual cols based on fill_values of BaseData
 
@@ -527,7 +535,7 @@ class BaseData(object):
             #if input is only one <fill_spec>, then make it a list
             try:
                 self.fill_values[0] + ''
-                self.fill_values = [ self.fill_values ] 
+                self.fill_values = [self.fill_values]
             except TypeError:
                 pass
             # Step 1: Set the default list of columns which are affected by fill_values
@@ -536,26 +544,29 @@ class BaseData(object):
                 colnames.intersection_update(self.fill_include_names)
             if self.fill_exclude_names is not None:
                 colnames.difference_update(self.fill_exclude_names)
-        
+
             # Step 2a: Find out which columns are affected by this tuple
-            # iterate over reversed order, so last condition is set first and overwritten by earlier conditions
+            # iterate over reversed order, so last condition is set first and
+            # overwritten by earlier conditions
             for replacement in reversed(self.fill_values):
                 if len(replacement) < 2:
-                    raise ValueError("Format of fill_values must be (<bad>, <fill>, <optional col1>, ...)")
+                    raise ValueError("Format of fill_values must be "
+                                     "(<bad>, <fill>, <optional col1>, ...)")
                 elif len(replacement) == 2:
                     affect_cols = colnames
                 else:
                     affect_cols = replacement[2:]
-                
+
                 for i, key in ((i, x) for i, x in enumerate(self.header.colnames) if x in affect_cols):
                     cols[i].fill_values[replacement[0]] = str(replacement[1])
 
     def _set_masks(self, cols):
-        """Replace string values in col.str_vales and set masks"""
+        """Replace string values in col.str_vals and set masks"""
         if self.fill_values:
             for col in (col for col in cols if col.fill_values):
-                col.mask = [False] * len(col.str_vals)
-                for i, str_val in ((i, x) for i, x in enumerate(col.str_vals) if x in col.fill_values):
+                col.mask = numpy.zeros(len(col.str_vals), dtype=numpy.bool)
+                for i, str_val in ((i, x) for i, x in enumerate(col.str_vals)
+                                   if x in col.fill_values):
                     col.str_vals[i] = col.fill_values[str_val]
                     col.mask[i] = True
 
@@ -568,28 +579,33 @@ class BaseData(object):
         while len(lines) < data_start_line:
             lines.append(itertools.cycle(self.write_spacer_lines))
 
-        formatters = []
-        for col in self.cols:
-            formatter = self.formats.get(col.name, self.default_formatter)
-            if not hasattr(formatter, '__call__'):
-                formatter = _format_func(formatter)
-            col.formatter = formatter
-
-        for vals in izip(*self.cols):
-            lines.append(self.splitter.join(vals))
+        with self._set_col_formats(self.cols, self.formats):
+            col_str_iters = [col.iter_str_vals() for col in self.cols]
+            for vals in izip(*col_str_iters):
+                lines.append(self.splitter.join(vals))
 
+    @contextmanager
+    def _set_col_formats(self, cols, formats):
+        """
+        Context manager to save the internal column formats in `cols` and
+        override with any custom `formats`.
+        """
+        orig_formats = [col.format for col in cols]
+        for col in cols:
+            if col.name in formats:
+                col.format = formats[col.name]
 
-def _format_func(format_str):
-    def func(val):
-        return format_str % val
-    return func
+        yield  # execute the nested context manager block
 
+        # Restore the original column format values
+        for col, orig_format in izip(cols, orig_formats):
+            col.format = orig_format
 
 class DictLikeNumpy(dict):
     """Provide minimal compatibility with numpy rec array API for BaseOutputter
     object::
-      
-      table = asciitable.read('mytable.dat', numpy=False)
+
+      table = ascii.read('mytable.dat', numpy=False)
       table.field('x')    # List of elements in column 'x'
       table.dtype.names   # get column names in order
       table[1]            # returns row 1 as a list
@@ -648,7 +664,7 @@ def convert_numpy(numpy_type):
     float, str) that is produced by the converter function.
     """
 
-    # Infer converter type from an instance of numpy_type. 
+    # Infer converter type from an instance of numpy_type.
     type_name = numpy.array([], dtype=numpy_type).dtype.name
     if 'int' in type_name:
         converter_type = IntType
@@ -658,7 +674,7 @@ def convert_numpy(numpy_type):
         converter_type = StrType
     else:
         converter_type = AllType
-    
+
     def converter(vals):
         return numpy.array(vals, numpy_type)
     return converter, converter_type
@@ -683,7 +699,7 @@ class BaseOutputter(object):
                     raise ValueError()
                 if issubclass(converter_type, col.type):
                     converters_out.append((converter_func, converter_type))
-                    
+
         except (ValueError, TypeError):
             raise ValueError('Error: invalid format for converters, see documentation\n%s' %
                              converters)
@@ -707,55 +723,6 @@ class BaseOutputter(object):
                 except IndexError:
                     raise ValueError('Column %s failed to convert' % col.name)
 
-class NumpyOutputter(BaseOutputter):
-    """Output the table as a numpy.rec.recarray
-
-    Missing or bad data values are handled at two levels.  The first is in
-    the data reading step where if ``data.fill_values`` is set then any
-    occurences of a bad value are replaced by the correspond fill value.
-    At the same time a boolean list ``mask`` is created in the column object.
-
-    The second stage is when converting to numpy arrays which by default generates
-    masked arrays, if ``data.fill_values`` is set and plain arrays if it is not.
-    In the rare case that plain arrays are needed set ``auto_masked`` (default = True) and
-    ``default_masked`` (default = False) to control this behavior as follows:
-
-    ===========  ==============  ===========  ============
-    auto_masked  default_masked  fill_values  output
-    ===========  ==============  ===========  ============
-    --            True           --           masked_array
-    --            False          None         array
-    True          --             dict(..)     masked_array
-    False         --             dict(..)     array
-    ===========  ==============  ===========  ============
-
-    To set these values use::
-    
-      Outputter = asciitable.NumpyOutputter()
-      Outputter.default_masked = True
-    
-    """
-
-    auto_masked_array = True
-    default_masked_array = False
-
-    default_converters = [convert_numpy(numpy.int),
-                          convert_numpy(numpy.float),
-                          convert_numpy(numpy.str)]
-
-    def __call__(self, cols):
-        self._convert_vals(cols)
-        recarr = numpy.rec.fromarrays([x.data for x in cols], names=[x.name for x in cols])
-        if self.default_masked_array or (self.auto_masked_array and
-                                         any(col.fill_values for col in cols)):
-            maarr = recarr.view(numpy.ma.MaskedArray)
-            for col in cols:
-                if col.fill_values:
-                    maarr[col.name] = numpy.ma.masked_where(col.mask, maarr[col.name])
-            return maarr
-        else:
-            return recarr
-
 
 class TableOutputter(BaseOutputter):
     """Output the table as an astropy.table.Table object.
@@ -771,7 +738,18 @@ class TableOutputter(BaseOutputter):
 
     def __call__(self, cols):
         self._convert_vals(cols)
-        out = Table([x.data for x in cols], names=[x.name for x in cols])
+
+        # XXX: Maybe replace the logic below with an explicit masked arg in read()
+        masked = any(col.fill_values for col in cols)
+
+        out = Table([x.data for x in cols], names=[x.name for x in cols], masked=masked)
+        for col, out_col in zip(cols, out.columns.values()):
+            if masked and hasattr(col, 'mask'):
+                out_col.data.mask = col.mask
+            for attr in ('format', 'units', 'description'):
+                if hasattr(col, attr):
+                    setattr(out_col, attr, getattr(col, attr))
+
         # To Do: add support for column and table metadata
         return out
 
@@ -795,7 +773,6 @@ class BaseReader(object):
         self.inputter = BaseInputter()
         self.outputter = TableOutputter()
         self.meta = {}                  # Placeholder for storing table metadata 
-        self.keywords = []              # Placeholder for storing table Keywords
         # Data and Header instances benefit from a little cross-coupling.  Header may need to
         # know about number of data columns for auto-column name generation and Data may
         # need to know about header (e.g. for fixed-width tables where widths are spec'd in header.
@@ -826,7 +803,7 @@ class BaseReader(object):
         except TypeError:
             # Not a string.
             pass
-            
+
         # Same from __init__.  ??? Do these need to be here?
         self.data.header = self.header
         self.header.data = self.data
@@ -839,13 +816,13 @@ class BaseReader(object):
         self.data.splitter.cols = cols
 
         for i, str_vals in enumerate(self.data.get_str_vals()):
-            if len(str_vals) != n_data_cols:                
+            if len(str_vals) != n_data_cols:
                 str_vals = self.inconsistent_handler(str_vals, n_data_cols)
-                
+
                 #if str_vals is None, we skip this row
                 if str_vals is None:
                     continue
-                
+
                 #otherwise, we raise an error only if it is still inconsistent
                 if len(str_vals) != n_data_cols:
                     errmsg = ('Number of header columns (%d) inconsistent with '
@@ -859,23 +836,23 @@ class BaseReader(object):
                 col.str_vals.append(str_vals[col.index])
 
         self.data.masks(cols)
-        self.table = self.outputter(cols)
+        table = self.outputter(cols)
         self.cols = self.header.cols
 
-        return self.table
-    
+        return table
+
     def inconsistent_handler(self, str_vals, ncols):
         """Adjust or skip data entries if a row is inconsistent with the header.
-        
+
         The default implementation does no adjustment, and hence will always trigger
-        an exception in read() any time the number of data entries does not match 
+        an exception in read() any time the number of data entries does not match
         the header.
-        
+
         Note that this will *not* be called if the row already matches the header.
 
         :param str_vals: A list of value strings from the current row of the table.
         :param ncols: The expected number of entries from the table header.
-        :returns: 
+        :returns:
             list of strings to be parsed into data entries in the output table. If
             the length of this list does not match ``ncols``, an exception will be
             raised in read().  Can also be None, in which case the row will be
@@ -896,21 +873,17 @@ class BaseReader(object):
             comment_lines = []
         return comment_lines
 
-    def write(self, table=None):
+    def write(self, table):
         """Write ``table`` as list of strings.
 
-        :param table: asciitable Reader object
+        :param table: input table data (astropy.table.Table object)
         :returns: list of strings corresponding to ASCII table
         """
-        if table is None:
-            table = self
-
         # link information about the columns to the writer object (i.e. self)
         self.header.cols = table.cols
-        self.data.cols = self.header.cols
-        self.data.masks(self.data.cols)
+        self.data.cols = table.cols
 
-        # Write header and data to lines list 
+        # Write header and data to lines list
         lines = []
         self.header.write(lines)
         self.data.write(lines)
@@ -929,16 +902,22 @@ class ContinuationLinesInputter(BaseInputter):
     """
 
     continuation_char = '\\'
+    replace_char = ' '
+    # If no_continue is not None then lines matching this regex are not subject
+    # to line continuation.  The initial use case here is Daophot.  In this
+    # case the continuation character is just replaced with replace_char.
+    no_continue = None
 
     def process_lines(self, lines):
-        striplines = (x.strip() for x in lines)
-        lines = [x for x in striplines if len(x) > 0]
+        re_no_continue = re.compile(self.no_continue) if self.no_continue else None
 
         parts = []
         outlines = []
         for line in lines:
+            if re_no_continue and re_no_continue.match(line):
+                line = line.replace(self.continuation_char, self.replace_char)
             if line.endswith(self.continuation_char):
-                parts.append(line.rstrip(self.continuation_char))
+                parts.append(line.replace(self.continuation_char, self.replace_char))
             else:
                 parts.append(line)
                 outlines.append(''.join(parts))
@@ -954,7 +933,7 @@ class WhitespaceSplitter(DefaultSplitter):
         in_quote = False
         lastchar = None
         for char in line:
-            if char == self.quotechar and (self.escapechar is None or 
+            if char == self.quotechar and (self.escapechar is None or
                                            lastchar != self.escapechar):
                 in_quote = not in_quote
             if char == '\t' and not in_quote:
@@ -964,7 +943,7 @@ class WhitespaceSplitter(DefaultSplitter):
 
         return ''.join(newline)
 
-extra_reader_pars = ('Reader', 'Inputter', 'Outputter', 
+extra_reader_pars = ('Reader', 'Inputter', 'Outputter',
                      'delimiter', 'comment', 'quotechar', 'header_start',
                      'data_start', 'data_end', 'converters',
                      'data_Splitter', 'header_Splitter',
@@ -1023,8 +1002,8 @@ def _get_reader(Reader, Inputter=None, Outputter=None, **kwargs):
 
     return reader
 
-extra_writer_pars = ('delimiter', 'comment', 'quotechar', 'formats',
-                     'names', 'include_names', 'exclude_names', 
+extra_writer_pars = ('delimiter', 'comment', 'quotechar', 'formats', 'strip_whitespace',
+                     'names', 'include_names', 'exclude_names',
                      'fill_values', 'fill_include_names',
                      'fill_exclude_names')
 
@@ -1047,6 +1026,16 @@ def _get_writer(Writer, **kwargs):
         writer.data.splitter.quotechar = kwargs['quotechar']
     if 'formats' in kwargs:
         writer.data.formats = kwargs['formats']
+    if 'strip_whitespace' in kwargs:
+        if kwargs['strip_whitespace']:
+            # Restore the default SplitterClass process_val method which strips
+            # whitespace.  This may have been changed in the Writer
+            # initialization (e.g. Rdb and Tab)
+            Class = writer.data.splitter.__class__
+            obj = writer.data.splitter
+            writer.data.splitter.process_val = Class.process_val.__get__(obj, Class)
+        else:
+            writer.data.splitter.process_val = None
     if 'names' in kwargs:
         writer.header.names = kwargs['names']
     if 'include_names' in kwargs:
@@ -1060,5 +1049,3 @@ def _get_writer(Writer, **kwargs):
     if 'fill_exclude_names' in kwargs:
         writer.data.fill_exclude_names = kwargs['fill_exclude_names']
     return writer
-
-    
diff --git a/astropy/io/ascii/daophot.py b/astropy/io/ascii/daophot.py
index 7e23013..efe0d43 100644
--- a/astropy/io/ascii/daophot.py
+++ b/astropy/io/ascii/daophot.py
@@ -1,4 +1,4 @@
-"""Asciitable: an extensible ASCII table reader and writer.
+"""An extensible ASCII table reader and writer.
 
 daophot.py:
   Classes to read DAOphot table format
@@ -31,8 +31,11 @@ daophot.py:
 ## SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 import re
+import numpy as np
 from . import core
 from . import basic
+from . import fixedwidth
+from ...utils import OrderedDict
 
 class Daophot(core.BaseReader):
     """Read a DAOphot file.
@@ -54,36 +57,45 @@ class Daophot(core.BaseReader):
       14       138.538   256.405   15.461      0.003         34.85955       4        \\
       -0.032      0.802       0     No_error
 
-    The keywords defined in the #K records are available via the Daophot reader object::
+    The keywords defined in the #K records are available via output table
+    ``meta`` attribute::
 
-      reader = asciitable.get_reader(Reader=asciitable.Daophot)
-      data = reader.read('t/daophot.dat')
-      for keyword in reader.keywords:
-          print keyword.name, keyword.value, keyword.units, keyword.format
-    
+      data = ascii.read('t/daophot.dat')
+      for keyword in data.meta['keywords']:
+          print keyword['name'], keyword['value'], keyword['units'], keyword['format']
+
+    The units and formats are available in the output table columns::
+
+      for colname in data.colnames:
+           col = data[colname]
+           print colname, col.units, col.format
     """
-    
+
     def __init__(self):
         core.BaseReader.__init__(self)
         self.header = DaophotHeader()
         self.inputter = core.ContinuationLinesInputter()
-        self.data.splitter.delimiter = ' '
+        self.inputter.no_continue = r'\s*#'
+        self.data.splitter = fixedwidth.FixedWidthSplitter()
         self.data.start_line = 0
         self.data.comment = r'\s*#'
-    
+
     def read(self, table):
-        output = core.BaseReader.read(self, table)
-        reader = core._get_reader(Reader=basic.NoHeader, comment=r'(?!#K)', 
-                                  names = ['temp1','keyword','temp2','value','unit','format'])
-        headerkeywords = reader.read(self.comment_lines)
-
-        for line in headerkeywords:
-            self.keywords.append(core.Keyword(line['keyword'], line['value'], 
-                                              units=line['unit'], format=line['format']))
-        self.table = output
+        out = core.BaseReader.read(self, table)
+
+        # Read keywords as a table embedded in the header comments
+        if len(self.comment_lines) > 0:
+            names = ('temp1', 'name', 'temp2', 'value', 'units', 'format')
+            reader = core._get_reader(Reader=basic.NoHeader, comment=r'(?!#K)', names=names)
+            headerkeywords = reader.read(self.comment_lines)
+
+            out.meta['keywords'] = OrderedDict()
+            for headerkeyword in headerkeywords:
+                keyword_dict = dict((x, headerkeyword[x]) for x in ('value', 'units', 'format'))
+                out.meta['keywords'][headerkeyword['name']] = keyword_dict
         self.cols = self.header.cols
 
-        return self.table
+        return out
 
     def write(self, table=None):
         raise NotImplementedError
@@ -104,18 +116,73 @@ class DaophotHeader(core.BaseHeader):
         :returns: list of table Columns
         """
 
-        self.names = []
-        re_name_def = re.compile(r'#N([^#]+)#')
+        # Parse a series of column defintion lines like below.  There may be several
+        # such blocks in a single file (where continuation characters have already been
+        # stripped).
+        # #N ID    XCENTER   YCENTER   MAG         MERR          MSKY           NITER    
+        # #U ##    pixels    pixels    magnitudes  magnitudes    counts         ##       
+        # #F %-9d  %-10.3f   %-10.3f   %-12.3f     %-14.3f       %-15.7g        %-6d     
+        coldef_lines = ['', '', '']
+        starts = ('#N ', '#U ', '#F ')
+        col_width = []
+        col_len_def = re.compile(r'[0-9]+')
+        re_colformat_def = re.compile(r'#F([^#]+)')
         for line in lines:
             if not line.startswith('#'):
-                break                   # End of header lines
+                break # End of header lines
             else:
-                match = re_name_def.search(line)
-                if match:
-                    self.names.extend(match.group(1).split())
+                formatmatch = re_colformat_def.search(line)
+                if formatmatch:
+                    form = formatmatch.group(1).split()
+                    width = ([int(col_len_def.search(s).group()) for s in form])
+                    # original data format might be shorter than 80 characters
+                    # and filled with spaces
+                    width[-1] = 80 - sum(width[:-1])
+                    col_width.extend(width)
+                for i, start in enumerate(starts):
+                    if line.startswith(start):
+                        line_stripped = line[2:]
+                        coldef_lines[i] = coldef_lines[i] + line_stripped
+                        break
         
+        # At this point colddef_lines has three lines corresponding to column
+        # names, units, and format.  Get the column names by splitting the
+        # first line on whitespace.
+        self.names = coldef_lines[0].split()
         if not self.names:
             raise core.InconsistentTableError('No column names found in DAOphot header')
-        
+
+        ends = np.cumsum(col_width)
+        starts = ends - col_width
+
+        # If there wasn't a #U defined (not sure of DAOphot specification), then
+        # replace the empty line with the right number of ## indicators, which matches
+        # the DAOphot "no unit" tag.
+        for i, coldef_line in enumerate(coldef_lines):
+            if not coldef_line:
+                coldef_lines[i] = '## ' * len(self.names)
+
+        # Read the three lines as a basic table.
+        reader = core._get_reader(Reader=basic.Basic, comment=None)
+        reader.header.comment = None
+        coldefs = reader.read(coldef_lines)
+
+        # Create the list of io.ascii column objects
         self._set_cols_from_names()
 
+        # Set units and format as needed.
+        for col in self.cols:
+            if coldefs[col.name][0] != '##':
+                col.units = coldefs[col.name][0]
+            if coldefs[col.name][1] != '##':
+                col.format = coldefs[col.name][1]
+
+        # Set column start and end positions.  Also re-index the cols because
+        # the FixedWidthSplitter does NOT return the ignored cols (as is the
+        # case for typical delimiter-based splitters)
+        for i, col in enumerate(self.cols):
+            col.start = starts[col.index]
+            col.end = ends[col.index]
+            col.index = i
+        
+        self.n_data_cols = len(self.cols)
\ No newline at end of file
diff --git a/astropy/io/ascii/fixedwidth.py b/astropy/io/ascii/fixedwidth.py
index 51e93ff..1e1c90e 100644
--- a/astropy/io/ascii/fixedwidth.py
+++ b/astropy/io/ascii/fixedwidth.py
@@ -1,4 +1,4 @@
-"""Asciitable: an extensible ASCII table reader and writer.
+"""An extensible ASCII table reader and writer.
 
 fixedwidth.py:
   Read or write a table with fixed width columns.
@@ -230,19 +230,14 @@ class FixedWidthData(core.BaseData):
     splitter_class = FixedWidthSplitter
 
     def write(self, lines):
-        formatters = []
-        for col in self.cols:
-            formatter = self.formats.get(col.name, self.default_formatter)
-            if not hasattr(formatter, '__call__'):
-                formatter = core._format_func(formatter)
-            col.formatter = formatter
-            
-        vals_list = []
-        # Col iterator does the formatting defined above so each val is a string
-        # and vals is a tuple of strings for all columns of each row
-        for vals in izip(*self.cols):
-            vals_list.append(vals)
-            
+        with self._set_col_formats(self.cols, self.formats):
+            vals_list = []
+            # Col iterator does the formatting defined above so each val is a string
+            # and vals is a tuple of strings for all columns of each row
+            col_str_iters = [col.iter_str_vals() for col in self.cols]
+            for vals in izip(*col_str_iters):
+                vals_list.append(vals)
+
         for i, col in enumerate(self.cols):
             col.width = max([len(vals[i]) for vals in vals_list])
             if self.header.start_line is not None:
@@ -336,7 +331,7 @@ class FixedWidthNoHeader(FixedWidth):
       1.2hello there3 
       2.4many words 7 
 
-    This class is just a convenience wrapper around :class:`~asciitable.FixedWidth`
+    This class is just a convenience wrapper around the ``FixedWidth`` reader
     but with ``header.start_line = None`` and ``data.start_line = 0``.
 
     See the :ref:`fixed_width_gallery` for specific usage examples.
diff --git a/astropy/io/ascii/ipac.py b/astropy/io/ascii/ipac.py
index 10db2e5..eea5a88 100644
--- a/astropy/io/ascii/ipac.py
+++ b/astropy/io/ascii/ipac.py
@@ -1,4 +1,4 @@
-"""Asciitable: an extensible ASCII table reader and writer.
+"""An extensible ASCII table reader and writer.
 
 ipac.py:
   Classes to read IPAC table format
@@ -50,6 +50,18 @@ class Ipac(core.BaseReader):
       |-----ra---|----dec---|---sao---|------v---|----sptype--------|
         2.09708   29.09056     73765    2.06000   B8IVpMnHg
 
+    Parameters
+    ----------
+    definition : str, optional
+        Specify the convention for characters in the data table that occur
+        directly below the pipe (`|`) symbol in the header column definition:
+
+          * 'ignore' - Any character beneath a pipe symbol is ignored (default)
+          * 'right' - Character is associated with the column to the right
+          * 'left' - Character is associated with the column to the left
+
+    Notes
+    -----
     Caveats:
 
     * Data type, Units, and Null value specifications are ignored.
@@ -59,10 +71,11 @@ class Ipac(core.BaseReader):
 
     Overcoming these limitations would not be difficult, code contributions
     welcome from motivated users.
+
     """
-    def __init__(self):
+    def __init__(self, definition='ignore'):
         core.BaseReader.__init__(self)
-        self.header = IpacHeader()
+        self.header = IpacHeader(definition=definition)
         self.data = IpacData()
 
     def write(self, table=None):
@@ -75,6 +88,7 @@ class IpacHeader(core.BaseHeader):
     comment = r'\\'
     splitter_class = core.BaseSplitter
     col_type_map = {'int': core.IntType,
+                    'integer': core.IntType,
                     'long': core.IntType,
                     'double': core.FloatType,
                     'float': core.FloatType,
@@ -88,11 +102,15 @@ class IpacHeader(core.BaseHeader):
                     'r': core.FloatType,
                     'c': core.StrType}
 
-    def __init__(self):
+    def __init__(self, definition='ignore'):
         self.splitter = self.__class__.splitter_class()
         self.splitter.process_line = None
         self.splitter.process_val = None
         self.splitter.delimiter = '|'
+        if definition in ['ignore', 'left', 'right']:
+            self.ipac_definition = definition
+        else:
+            raise ValueError("definition should be one of ignore/left/right")
 
     def process_lines(self, lines):
         """Generator to yield IPAC header lines, i.e. those starting and ending with
@@ -133,17 +151,25 @@ class IpacHeader(core.BaseHeader):
             if len(header_vals) > 2:
                 col.units = header_vals[2][i].strip() # Can't strip dashes here
             if len(header_vals) > 3:
+                # The IPAC null value corresponds to the io.ascii bad_value.
+                # In this case there isn't a fill_value defined, so just put
+                # in the minimal entry that is sure to convert properly to the
+                # required type.
+                #
+                # Strip spaces but not dashes (not allowed in NULL row per
+                # https://github.com/astropy/astropy/issues/361)
                 null = header_vals[3][i].strip()
-                if null.lower() != 'null':
-                    col.null = null  # Can't strip dashes here
-                    if issubclass(col.type, core.FloatType):
-                        fillval = 'nan'
-                    else:
-                        fillval = '-999'
-                    self.data.fill_values.append((col.null, fillval, col.name))
+                fillval = '' if issubclass(col.type, core.StrType) else '0'
+                self.data.fill_values.append((null, fillval, col.name))
             start = col.end + 1
             cols.append(col)
 
+            # Correct column start/end based on definition
+            if self.ipac_definition == 'right':
+                col.start -= 1
+            elif self.ipac_definition == 'left':
+                col.end += 1
+
         # Standard column name filtering (include or exclude names)
         self.names = [x.name for x in cols]
         names = set(self.names)
@@ -163,4 +189,3 @@ class IpacData(core.BaseData):
     """IPAC table data reader"""
     splitter_class = fixedwidth.FixedWidthSplitter
     comment = r'[|\\]'
-
diff --git a/astropy/io/ascii/latex.py b/astropy/io/ascii/latex.py
index 5ce7c3d..809587d 100644
--- a/astropy/io/ascii/latex.py
+++ b/astropy/io/ascii/latex.py
@@ -1,4 +1,4 @@
-"""Asciitable: an extensible ASCII table reader and writer.
+"""An extensible ASCII table reader and writer.
 
 latex.py:
   Classes to read and write LaTeX tables
@@ -7,7 +7,7 @@ latex.py:
 :Author: Tom Aldcroft (aldcroft at head.cfa.harvard.edu)
 """
 
-## 
+##
 ## Redistribution and use in source and binary forms, with or without
 ## modification, are permitted provided that the following conditions are met:
 ##     * Redistributions of source code must retain the above copyright
@@ -18,7 +18,7 @@ latex.py:
 ##     * Neither the name of the Smithsonian Astrophysical Observatory nor the
 ##       names of its contributors may be used to endorse or promote products
 ##       derived from this software without specific prior written permission.
-## 
+##
 ## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 ## ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 ## WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
@@ -27,7 +27,7 @@ latex.py:
 ## (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 ## LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 ## ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS  
+## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 ## SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 import re
@@ -36,18 +36,20 @@ from . import core
 latexdicts ={'AA':  {'tabletype': 'table',
                  'header_start': r'\hline \hline', 'header_end': r'\hline',
                  'data_end': r'\hline'},
-             'doublelines': {'tabletype': 'table', 
+             'doublelines': {'tabletype': 'table',
                  'header_start': r'\hline \hline', 'header_end': r'\hline\hline',
                  'data_end': r'\hline\hline'},
              'template': {'tabletype': 'tabletype', 'caption': 'caption',
-                 'col_align': 'col_align', 'preamble': 'preamble', 'header_start': 'header_start',
-                 'header_end': 'header_end', 'data_start': 'data_start',
-                 'data_end': 'data_end', 'tablefoot': 'tablefoot', 'units': {'col1': 'unit of col1', 'col2': 'unit of col2'}}
-            }
+                          'col_align': 'col_align', 'preamble': 'preamble',
+                          'header_start': 'header_start',
+                          'header_end': 'header_end', 'data_start': 'data_start',
+                          'data_end': 'data_end', 'tablefoot': 'tablefoot',
+                          'units': {'col1': 'unit of col1', 'col2': 'unit of col2'}}
+             }
 
 def add_dictval_to_list(adict, key, alist):
     '''add a value from a dictionary to a list
-   
+
     :param adict: dictionary
     :param key: key of value
     :param list: list where value should be added
@@ -60,7 +62,7 @@ def add_dictval_to_list(adict, key, alist):
 
 def find_latex_line(lines, latex):
     '''Find the first line which matches a patters
-    
+
     :param lines: list of strings
     :param latex: search pattern
     :returns: line number or None, if no match was found
@@ -75,14 +77,14 @@ def find_latex_line(lines, latex):
 
 class LatexHeader(core.BaseHeader):
     header_start = r'\begin{tabular}'
-    
+
     def start_line(self, lines):
         line = find_latex_line(lines, self.header_start)
         if line:
             return line + 1
         else:
             return None
-    
+
     def write(self, lines):
         if not 'col_align' in self.latex.keys():
             self.latex['col_align'] = len(self.cols) * 'c'
@@ -95,21 +97,22 @@ class LatexHeader(core.BaseHeader):
         add_dictval_to_list(self.latex, 'header_start', lines)
         lines.append(self.splitter.join([x.name for x in self.cols]))
         if 'units' in self.latex.keys():
-            lines.append(self.splitter.join([self.latex['units'].get(x.name, ' ') for x in self.cols]))
+            lines.append(self.splitter.join([self.latex['units'].get(x.name, ' ')
+                                             for x in self.cols]))
         add_dictval_to_list(self.latex, 'header_end', lines)
-                
 
-    
+
+
 class LatexData(core.BaseData):
     data_start = None
     data_end = r'\end{tabular}'
-    
+
     def start_line(self, lines):
         if self.data_start:
             return find_latex_line(lines, self.data_start)
         else:
             return self.header.start_line(lines) + 1
-    
+
     def end_line(self, lines):
         if self.data_end:
             return find_latex_line(lines, self.data_end)
@@ -141,121 +144,125 @@ class LatexSplitter(core.BaseSplitter):
         else:
             raise core.InconsistentTableError(r'Lines in LaTeX table have to end with \\')
         return line
-    
+
     def process_val(self, val):
         """Remove whitespace and {} at the beginning or end of value."""
         val = val.strip()
         if val and (val[0] == '{') and (val[-1] == '}'):
             val = val[1:-1]
         return val
-    
+
     def join(self, vals):
         '''Join values together and add a few extra spaces for readability'''
         delimiter = ' ' + self.delimiter + ' '
-        return delimiter.join(str(x) for x in vals) + r' \\'
+        return delimiter.join(x.strip() for x in vals) + r' \\'
 
 class Latex(core.BaseReader):
-    '''Write and read LaTeX tables.
-    
-    This class implements some LaTeX specific commands.
-    Its main purpose is to write out a table in a form that LaTeX
-    can compile. It is beyond the scope of this class to implement every possible 
-    LaTeX command, instead the focus is to generate a syntactically valid LaTeX
-    tables.
-    This class can also read simple LaTeX tables (one line per table row,
-    no ``\multicolumn`` or similar constructs), specifically, it can read the 
-    tables that it writes.
-    
+    r'''Write and read LaTeX tables.
+
+    This class implements some LaTeX specific commands.  Its main
+    purpose is to write out a table in a form that LaTeX can compile. It
+    is beyond the scope of this class to implement every possible LaTeX
+    command, instead the focus is to generate a syntactically valid
+    LaTeX tables.
+
+    This class can also read simple LaTeX tables (one line per table
+    row, no ``\multicolumn`` or similar constructs), specifically, it
+    can read the tables that it writes.
+
     Reading a LaTeX table, the following keywords are accepted:
-    
-    **ignore_latex_commands** : 
+
+    **ignore_latex_commands** :
         Lines starting with these LaTeX commands will be treated as comments (i.e. ignored).
-            
-    When writing a LaTeX table, the some keywords can customize the format.
-    Care has to be taken here, because python interprets ``\\`` in a string as an escape character.
-    In order to pass this to the output either format your strings as raw strings with the ``r`` specifier
-    or use a double ``\\\\``.
+
+    When writing a LaTeX table, the some keywords can customize the
+    format.  Care has to be taken here, because python interprets ``\\``
+    in a string as an escape character.  In order to pass this to the
+    output either format your strings as raw strings with the ``r``
+    specifier or use a double ``\\\\``.
+
     Examples::
-    
+
         caption = r'My table \label{mytable}'
         caption = 'My table \\\\label{mytable}'
-    
+
     **latexdict** : Dictionary of extra parameters for the LaTeX output
-        * tabletype : used for first and last line of table. 
-            The default is ``\\begin{table}``.
-            The following would generate a table, which spans the whole page in a two-column document::
-                
-                asciitable.write(data, sys.stdout, Writer = asciitable.Latex,
-                             latexdict = {'tabletype': 'table*'})
+
+        * tabletype : used for first and last line of table.
+            The default is ``\\begin{table}``.  The following would generate a table,
+            which spans the whole page in a two-column document::
+
+                ascii.write(data, sys.stdout, Writer = ascii.Latex,
+                            latexdict = {'tabletype': 'table*'})
 
         * col_align : Alignment of columns
             If not present all columns will be centered.
 
         * caption : Table caption (string or list of strings)
-            This will appear above the table as it is the standard in many scientific publications.
-            If you prefer a caption below the table, just write the full LaTeX command as
+            This will appear above the table as it is the standard in
+            many scientific publications.  If you prefer a caption below
+            the table, just write the full LaTeX command as
             ``latexdict['tablefoot'] = r'\caption{My table}'``
 
         * preamble, header_start, header_end, data_start, data_end, tablefoot: Pure LaTeX
-            Each one can be a string or a list of strings. These strings will be inserted into the table
-            without any further processing. See the examples below.
+            Each one can be a string or a list of strings. These strings
+            will be inserted into the table without any further
+            processing. See the examples below.
 
         * units : dictionary of strings
-            Keys in this dictionary should be names of columns. If present,
-            a line in the LaTeX table directly below the column names is 
-            added, which contains the values of the dictionary. Example::
-            
-              import asciitable
-              import asciitable.latex
-              import sys
+            Keys in this dictionary should be names of columns. If
+            present, a line in the LaTeX table directly below the column
+            names is added, which contains the values of the
+            dictionary. Example::
+
+              from astropy.io import ascii
               data = {'name': ['bike', 'car'], 'mass': [75,1200], 'speed': [10, 130]}
-              asciitable.write(data, sys.stdout, Writer = asciitable.Latex,
+              ascii.write(data, Writer=ascii.Latex,
                                latexdict = {'units': {'mass': 'kg', 'speed': 'km/h'}})
-            
+
             If the column has no entry in the `units` dictionary, it defaults
             to `' '`.
-                
-        Run the following code to see where each element of the dictionary is inserted in the
-        LaTeX table::
-        
-            import asciitable
-            import asciitable.latex
-            import sys
+
+        Run the following code to see where each element of the
+        dictionary is inserted in the LaTeX table::
+
+            from astropy.io import ascii
             data = {'cola': [1,2], 'colb': [3,4]}
-            asciitable.write(data, sys.stdout, Writer = asciitable.Latex,
-                             latexdict = asciitable.latex.latexdicts['template'])
-                             
-        Some table styles are predefined in the dictionary ``asciitable.latex.latexdicts``. The following generates
-        in table in style preferred by A&A and some other journals::
-        
-            asciitable.write(data, sys.stdout, Writer = asciitable.Latex,
-                             latexdict = asciitable.latex.latexdicts['AA'])
-                             
-        As an example, this generates a table, which spans all columns and is centered on the page::
-        
-            asciitable.write(data, sys.stdout, Writer = asciitable.Latex,
-                             col_align = '|lr|',
-                             latexdict = {'preamble': r'\begin{center}', 'tablefoot': r'\end{center}',
-                                          'tabletype': 'table*'})
-    
-    **caption** : Set table caption 
+            ascii.write(data, Writer=ascii.Latex, latexdict=ascii.latex.latexdicts['template'])
+
+        Some table styles are predefined in the dictionary
+        ``ascii.latex.latexdicts``. The following generates in table in
+        style preferred by A&A and some other journals::
+
+            ascii.write(data, Writer=ascii.Latex, latexdict=ascii.latex.latexdicts['AA'])
+
+        As an example, this generates a table, which spans all columns
+        and is centered on the page::
+
+            ascii.write(data, Writer=ascii.Latex, col_align='|lr|',
+                        latexdict={'preamble': r'\begin{center}',
+                                   'tablefoot': r'\end{center}',
+                                   'tabletype': 'table*'})
+
+    **caption** : Set table caption
         Shorthand for::
-    
+
             latexdict['caption'] = caption
-    
-    **col_align** : Set the column alignment. 
-        If not present this will be auto-generated for centered columns. Shorthand for::
-        
+
+    **col_align** : Set the column alignment.
+        If not present this will be auto-generated for centered
+        columns. Shorthand for::
+
             latexdict['col_align'] = col_align
-    
+
     '''
-    
+
     def __init__(self, ignore_latex_commands = ['hline', 'vspace', 'tableline'], latexdict = {}, caption ='', col_align = None):
 
         core.BaseReader.__init__(self)
         self.header = LatexHeader()
         self.data = LatexData()
-        
+
         self.header.splitter = LatexSplitter()
         self.data.splitter = LatexSplitter()
         self.data.header = self.header
@@ -270,7 +277,7 @@ class Latex(core.BaseReader):
         self.latex.update(latexdict)
         if caption: self.latex['caption'] = caption
         if col_align: self.latex['col_align'] = col_align
-        
+
         self.ignore_latex_commands = ignore_latex_commands
         self.header.comment = '%|' + '|'.join([r'\\' + command for command in self.ignore_latex_commands])
         self.data.comment = self.header.comment
@@ -284,7 +291,7 @@ class Latex(core.BaseReader):
 
 class AASTexHeader(LatexHeader):
     '''In a `deluxetable` some header keywords differ from standard LaTeX.
-    
+
     This header is modified to take that into account.
     '''
     header_start = r'\tablehead'
@@ -324,9 +331,9 @@ class AASTexData(LatexData):
 
 class AASTexHeaderSplitter(LatexSplitter):
     '''extract column names from a `deluxetable`
-    
+
     This splitter expects the following LaTeX code **in a single line**:
-    
+
         \tablehead{\colhead{col1} & ... & \colhead{coln}}
     '''
     def process_line(self, line):
@@ -348,14 +355,14 @@ class AASTexHeaderSplitter(LatexSplitter):
 
 class AASTex(Latex):
     '''Write and read AASTeX tables.
-    
+
     This class implements some AASTeX specific commands.
     AASTeX is used for the AAS (American Astronomical Society)
     publications like ApJ, ApJL and AJ.
-    
-    It derives from :class:`~asciitable.Latex` and accepts the same keywords (see :class:`~asciitable.Latex` for documentation).
-    However, the keywords ``header_start``, ``header_end``, ``data_start`` and ``data_end`` in 
-    ``latexdict`` have no effect.
+
+    It derives from the ``Latex`` reader and accepts the same
+    keywords.  However, the keywords ``header_start``, ``header_end``,
+    ``data_start`` and ``data_end`` in ``latexdict`` have no effect.
     '''
 
     def __init__(self, **kwargs):
diff --git a/astropy/io/ascii/memory.py b/astropy/io/ascii/memory.py
deleted file mode 100644
index fdfa0cb..0000000
--- a/astropy/io/ascii/memory.py
+++ /dev/null
@@ -1,303 +0,0 @@
-"""Asciitable: an extensible ASCII table reader and writer.
-
-memory.py:
-  Classes to read table from in-memory data structure into
-  asciitable format.  This is used for writing tables.
-
-:Copyright: Smithsonian Astrophysical Observatory (2011)
-:Author: Tom Aldcroft (aldcroft at head.cfa.harvard.edu)
-"""
-
-## 
-## Redistribution and use in source and binary forms, with or without
-## modification, are permitted provided that the following conditions are met:
-##     * Redistributions of source code must retain the above copyright
-##       notice, this list of conditions and the following disclaimer.
-##     * Redistributions in binary form must reproduce the above copyright
-##       notice, this list of conditions and the following disclaimer in the
-##       documentation and/or other materials provided with the distribution.
-##     * Neither the name of the Smithsonian Astrophysical Observatory nor the
-##       names of its contributors may be used to endorse or promote products
-##       derived from this software without specific prior written permission.
-## 
-## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-## ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-## WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-## DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
-## DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-## (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-## LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-## ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS  
-## SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-from . import core
-from . import basic
-from .core import io, next, izip, any
-import numpy
-
-class Memory(core.BaseReader):
-    """Read a table from a data object in memory.  Several input data formats are supported:
-
-    **Output of asciitable.read()**::
-
-      table = asciitable.get_reader(Reader=asciitable.Daophot)
-      data = table.read('t/daophot.dat')
-      mem_data_from_table = asciitable.read(table, Reader=asciitable.Memory)
-      mem_data_from_data = asciitable.read(data, Reader=asciitable.Memory)
-
-    **Numpy structured array**::
-
-      data = numpy.zeros((2,), dtype=[('col1','i4'), ('col2','f4'), ('col3', 'a10')])
-      data[:] = [(1, 2., 'Hello'), (2, 3., "World")]
-      mem_data = asciitable.read(data, Reader=asciitable.Memory)
-      
-    **Numpy masked structured array**::
-
-      data = numpy.ma.zeros((2,), dtype=[('col1','i4'), ('col2','f4'), ('col3', 'a10')])
-      data[:] = [(1, 2., 'Hello'), (2, 3., "World")]
-      data['col2'] = ma.masked
-      mem_data = asciitable.read(data, Reader=asciitable.Memory)
-      
-      In the current version all masked values will be converted to nan.
-
-    **Sequence of sequences**::
-    
-      data = [[1, 2,   3      ],
-              [4, 5.2, 6.1    ],
-              [8, 9,   'hello']]
-      mem_data = asciitable.read(data, Reader=asciitable.Memory, names=('c1','c2','c3'))
-
-    **Dict of sequences**::
-
-      data = {'c1': [1, 2, 3],
-              'c2': [4, 5.2, 6.1],
-              'c3': [8, 9, 'hello']}
-      mem_data = asciitable.read(data, Reader=asciitable.Memory, names=('c1','c2','c3'))
-
-    """
-    def __init__(self):
-        self.header = MemoryHeader()
-        self.data = MemoryData()
-        self.inputter = MemoryInputter()
-        self.outputter = core.TableOutputter()
-        self.meta = {}                  # Placeholder for storing table metadata 
-        self.keywords = []              # Table Keywords
-
-    def read(self, table):
-        self.data.header = self.header
-        self.header.data = self.data
-
-        self.lines = self.inputter.get_lines(table, self.header.names)
-        self.data.get_data_lines(self.lines)
-        self.header.get_cols(self.lines)
-        cols = self.header.cols         # header.cols corresponds to *output* columns requested
-        n_data_cols = len(self.header.names) # header.names corresponds to *all* header columns in table
-        self.data.splitter.cols = cols
-
-        for i, str_vals in enumerate(self.data.get_str_vals()):
-            if len(list(str_vals)) != n_data_cols:
-                errmsg = ('Number of header columns (%d) inconsistent with '
-                          'data columns (%d) at data line %d\n'
-                          'Header values: %s\n'
-                          'Data values: %s' % (len(cols), len(str_vals), i,
-                                               [x.name for x in cols], str_vals))
-                raise core.InconsistentTableError(errmsg)
-
-            for col in cols:
-                col.str_vals.append(str_vals[col.index])
-
-        self.data.masks(cols)
-        self.cols = cols
-        if hasattr(table, 'keywords'):
-            self.keywords = table.keywords
-
-        self.outputter.default_converters = [((lambda vals: vals), core.IntType),
-                                             ((lambda vals: vals), core.FloatType),
-                                             ((lambda vals: vals), core.StrType)]
-        self.table = self.outputter(cols)
-        self.cols = self.header.cols
-
-        return self.table
-
-    def write(self, table=None):
-        """Not available for the Memory class (raises NotImplementedError)"""
-        raise NotImplementedError
-
-
-class MemoryInputter(core.BaseInputter):
-    """Get the lines from the table input and return an iterable object that contains the data lines.
-
-    The input table can be one of:
-
-    * asciitable Reader object
-    * NumPy structured array
-    * List of lists
-    * Dict of lists
-    """
-    def get_lines(self, table, names):
-        """Get the lines from the ``table`` input.
-        
-        :param table: table input
-        :param names: list of column names (only used for dict of lists to set column order)
-        :returns: list of lines
-
-        """
-        try:  
-            # If table is dict-like this will return the first key.
-            # If table is list-like this will return the first row.
-            first_row_or_key = next(iter(table))
-        except TypeError:
-            # Not iterable, is it an asciitable Reader instance?
-            if isinstance(table, core.BaseReader):
-                lines = table.table
-            else:
-                # None of the possible choices so raise exception
-                raise TypeError('Input table must be iterable or else be a Reader object')
-        else:
-            # table is iterable, now see if it is dict-like or list-like
-            try:
-                # If first_row_or_key is a row (in the case that table is
-                # list-like) then this will raise exception
-                table[first_row_or_key]
-            except (TypeError, IndexError, ValueError):
-                # Table is list-like (python list-of-lists or numpy recarray)
-                lines = table
-            else:
-                # Table is dict-like.  Turn this into a DictLikeNumpy that has
-                # an API similar to a numpy recarray.
-                lines = core.DictLikeNumpy(table)
-                if names is None:
-                    lines.dtype.names = sorted(lines.keys())
-                else:
-                    lines.dtype.names = names
-
-        # ``lines`` could now be one of the following iterable objects:
-        # - NumPy recarray
-        # - DictLikeNumpy object
-        # - Python list of lists
-        return lines
-
-def get_val_type(val):
-    """Get the asciitable data type corresponding to ``val``.  Try a series
-    of possibilities, organized roughly by expected frequencies of types in
-    data tables.
-    """
-    # Try native python types
-    if isinstance(val, float):
-        return core.FloatType
-    elif isinstance(val, int):
-        return core.IntType
-    elif isinstance(val, str):
-        return core.StrType
-    elif isinstance(val, core.long):
-        return core.IntType
-    elif isinstance(val, core.unicode):
-        return core.StrType
-        
-    # Not a native Python type so try a NumPy type
-    try:
-        type_name = val.dtype.name
-    except AttributeError:
-        pass
-    else:
-        if 'int' in type_name:
-            return core.IntType
-        elif 'float' in type_name:
-            return core.FloatType
-        elif 'string' in type_name:
-            return core.StrType
-
-    # Nothing matched
-    raise TypeError("Memory: could not infer type for data value '%s'" % val)
-    
-def get_lowest_type(type_set):
-    """Return the lowest common denominator among a set of asciitable Types,
-    in order StrType, FloatType, IntType.  
-    """
-    if core.StrType in type_set:
-        return core.StrType
-    elif core.FloatType in type_set:
-        return core.FloatType
-    elif core.IntType in type_set:
-        return core.IntType
-
-    raise ValueError("Type_set '%s' does not have expected values" % type_set)
-        
-
-class MemoryHeader(core.BaseHeader):
-    """Memory table header reader"""
-    def __init__(self):
-        pass
-
-    def get_cols(self, lines):
-        """Initialize the header Column objects from the table ``lines``.
-
-        Based on the previously set Header attributes find or create the column names.
-        Sets ``self.cols`` with the list of Columns.  This list only includes the actual
-        requested columns after filtering by the include_names and exclude_names
-        attributes.  See ``self.names`` for the full list.
-
-        :param lines: list of table lines
-        :returns: list of table Columns
-        """
-
-        if self.names is None:
-            # No column names supplied so first try to get them from NumPy structured array
-            try:
-                self.names = lines.dtype.names
-            except AttributeError:
-                # Still no col names available so auto-generate them
-                try:
-                    first_data_vals = next(iter(lines))
-                except StopIteration:
-                    raise core.InconsistentTableError(
-                        'No data lines found so cannot autogenerate column names')
-                n_data_cols = len(first_data_vals)
-                self.names = [self.auto_format % i for i in range(1, n_data_cols+1)]
-
-        self._set_cols_from_names()
-
-        # ``lines`` could be one of: NumPy recarray, Python
-        # list of lists. If NumPy recarray then set col.type accordingly.  In
-        # the other two cases convert the data values to strings so the usual
-        # data converter processing will get the correct type.
-        if isinstance(lines, numpy.ndarray):
-            for col in self.cols:
-                type_name = lines[col.name].dtype.name
-                if 'int' in type_name:
-                    col.type = core.IntType
-                elif 'float' in type_name:
-                    col.type = core.FloatType
-                elif 'str' in type_name:
-                    col.type = core.StrType
-        else:
-            # lines is a list of lists
-            col_types = {}
-            col_indexes = [col.index for col in self.cols]
-            for vals in lines:
-                for col_index in col_indexes:
-                    val = vals[col_index]
-                    col_type_set = col_types.setdefault(col_index, set())
-                    col_type_set.add(get_val_type(val))
-            for col in self.cols:
-                col.type = get_lowest_type(col_types[col.index])
-
-
-class MemorySplitter(core.BaseSplitter):
-    """Splitter for data already in memory.  It is assumed that ``lines`` are
-    iterable and that each line (aka row) is also an iterable object that
-    provides the column values for that row."""
-    def __call__(self, lines):
-        for vals in lines:
-            yield vals
-
-class MemoryData(core.BaseData):
-    """Memory table data reader.  Same as the BaseData reader but with a
-    special splitter and a "pass-thru" process_lines function."""
-
-    splitter_class = MemorySplitter
-
-    def process_lines(self, lines):
-        return lines
-
diff --git a/astropy/io/ascii/setup_package.py b/astropy/io/ascii/setup_package.py
index 007413e..21b78b6 100644
--- a/astropy/io/ascii/setup_package.py
+++ b/astropy/io/ascii/setup_package.py
@@ -19,19 +19,28 @@ def get_package_data():
                                    't/cds/multi/lhs2065.dat',
                                    't/cds2.dat',
                                    't/commented_header.dat',
+                                   't/commented_header2.dat',
                                    't/continuation.dat',
                                    't/daophot.dat',
+                                   't/daophot2.dat',
+                                   't/sextractor.dat',
+                                   't/daophot.dat.gz',
                                    't/fill_values.txt',
                                    't/ipac.dat',
+                                   't/ipac.dat.bz2',
                                    't/latex1.tex',
+                                   't/latex1.tex.gz',
                                    't/latex2.tex',
                                    't/nls1_stackinfo.dbout',
                                    't/no_data_cds.dat',
                                    't/no_data_daophot.dat',
+                                   't/no_data_sextractor.dat',
                                    't/no_data_ipac.dat',
                                    't/no_data_with_header.dat',
                                    't/no_data_without_header.dat',
                                    't/short.rdb',
+                                   't/short.rdb.bz2',
+                                   't/short.rdb.gz',
                                    't/short.tab',
                                    't/simple.txt',
                                    't/simple2.txt',
diff --git a/astropy/io/ascii/sextractor.py b/astropy/io/ascii/sextractor.py
new file mode 100644
index 0000000..02aca7a
--- /dev/null
+++ b/astropy/io/ascii/sextractor.py
@@ -0,0 +1,124 @@
+""" sextractor.py:
+  Classes to read SExtractor table format
+
+Built on daophot.py:
+:Copyright: Smithsonian Astrophysical Observatory (2011)
+:Author: Tom Aldcroft (aldcroft at head.cfa.harvard.edu)
+"""
+
+##
+## Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions are met:
+##     * Redistributions of source code must retain the above copyright
+##       notice, this list of conditions and the following disclaimer.
+##     * Redistributions in binary form must reproduce the above copyright
+##       notice, this list of conditions and the following disclaimer in the
+##       documentation and/or other materials provided with the distribution.
+##     * Neither the name of the Smithsonian Astrophysical Observatory nor the
+##       names of its contributors may be used to endorse or promote products
+##       derived from this software without specific prior written permission.
+##
+## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+## ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+## WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+## DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+## DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+## (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+## LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+## ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+## SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import re
+from . import core
+
+
+class SExtractor(core.BaseReader):
+    """Read a SExtractor file.
+       SExtractor is a package for faint-galaxy photometry.
+       Bertin & Arnouts 1996, A&A Supp. 317, 393.
+       http://www.astromatic.net/software/sextractor
+
+    Example::
+
+      # 1 NUMBER
+      # 2 ALPHA_J2000
+      # 3 DELTA_J2000
+      # 4 FLUX_RADIUS
+      # 7 MAG_AUTO
+      1 32.23222 10.1211 0.8 1.2 1.4 18.1
+      2 38.12321 -88.1321 2.2 2.4 3.1 17.0
+
+    Note the skipped numbers since flux_radius has 3 columns.  The three FLUX_RADIUS
+    columns will be named FLUX_RADIUS, FLUX_RADIUS_1, FLUX_RADIUS_2
+    """
+
+    def __init__(self):
+        core.BaseReader.__init__(self)
+        self.header = SExtractorHeader()
+        self.inputter = core.ContinuationLinesInputter()
+        self.data.splitter.delimiter = ' '
+        self.data.start_line = 0
+        self.data.comment = r'\s*#'  # Comments embedded in the data start with #
+
+    def read(self, table):
+        output = core.BaseReader.read(self, table)
+        self.table = output
+        self.cols = self.header.cols
+
+        return self.table
+
+    def write(self, table=None):
+        raise NotImplementedError
+
+
+class SExtractorHeader(core.BaseHeader):
+    """Read the header from a file produced by SExtractor."""
+    def __init__(self):
+        core.BaseHeader.__init__(self)
+        self.comment = r'^\s*#\s*\S\D.*'  # Find lines that dont have "# digit"
+
+    def get_cols(self, lines):
+        """Initialize the header Column objects from the table ``lines`` for a SExtractor
+        header.  The SExtractor header is specialized so that we just copy the entire BaseHeader
+        get_cols routine and modify as needed.
+
+        :param lines: list of table lines
+        :returns: list of table Columns
+        """
+
+        # This assumes that the columns are listed in order, one per line with a
+        # header comment string of the format: "# 1 ID"
+        # However, some may be missing and must be inferred from skipped column numbers
+        columns = {}
+        re_name_def = re.compile(r'^\s*#\s*([0-9]+).*')  # E.g. '# 1 ID'
+        for line in lines:
+            if not line.startswith('#'):
+                break                   # End of header lines
+            else:
+                match = re_name_def.search(line)
+                if match:
+                    words = match.group(0).strip().strip('#').split()
+                    colnumber = int(words[0]) # First string is the column number
+                    colname = words[1]   # second string is the column name
+                    columns[colnumber] = colname
+        # Handle skipped column numbers
+        colnumbers = sorted(columns.iterkeys())
+        previous_column = 0
+        for n in colnumbers:
+            if n != previous_column + 1:
+                for c in range(previous_column+1,n):
+                    column_name = columns[previous_column]+"_%d" % (c-previous_column)
+                    columns[c] = column_name
+            previous_column = n
+
+        # Add the columns in order to self.names
+        colnumbers = sorted(columns.iterkeys())
+        self.names = []
+        for n in colnumbers:
+            self.names.append(columns[n])
+
+        if not self.names:
+            raise core.InconsistentTableError('No column names found in SExtractor header')
+
+        self._set_cols_from_names()
diff --git a/astropy/io/ascii/tests/common.py b/astropy/io/ascii/tests/common.py
index e0f0c5c..e6ab97d 100644
--- a/astropy/io/ascii/tests/common.py
+++ b/astropy/io/ascii/tests/common.py
@@ -1,12 +1,17 @@
 from __future__ import absolute_import
-
 import os
+from distutils import version
+import numpy as np
+
+
 from ... import ascii
 
-__all__ = ['raises',
+__all__ = ['raises', 'numpy_lt_1p5'
            'assert_equal', 'assert_almost_equal', 'assert_true',
            'setup_function', 'teardown_function', 'has_isnan']
 
+numpy_lt_1p5 = version.LooseVersion(np.__version__) < version.LooseVersion('1.5')
+
 CWD = os.getcwd()
 TEST_DIR = os.path.dirname(__file__)
 
diff --git a/astropy/io/ascii/tests/t/commented_header.dat b/astropy/io/ascii/tests/t/commented_header.dat
index ef11cd9..d4a6371 100644
--- a/astropy/io/ascii/tests/t/commented_header.dat
+++ b/astropy/io/ascii/tests/t/commented_header.dat
@@ -1,3 +1,4 @@
 # a b c
+# A comment line
 1 2 3
 4 5 6
diff --git a/astropy/io/ascii/tests/t/commented_header2.dat b/astropy/io/ascii/tests/t/commented_header2.dat
new file mode 100644
index 0000000..a0f8093
--- /dev/null
+++ b/astropy/io/ascii/tests/t/commented_header2.dat
@@ -0,0 +1,5 @@
+# A comment line
+# Another comment line
+# a b c
+1 2 3
+4 5 6
diff --git a/astropy/io/ascii/tests/t/daophot.dat b/astropy/io/ascii/tests/t/daophot.dat
index ed363eb..f46667c 100644
--- a/astropy/io/ascii/tests/t/daophot.dat
+++ b/astropy/io/ascii/tests/t/daophot.dat
@@ -33,13 +33,13 @@
 #
 #N ID    XCENTER   YCENTER   MAG         MERR          MSKY           NITER    \
 #U ##    pixels    pixels    magnitudes  magnitudes    counts         ##       \
-#F %-9d  %-10.3f   %-10.3f   %-12.3f     %-14.3f       %-15.7g        %-6d     
+#F %-9d  %-10.3f   %-10.3f   %-12.3f     %-14.3f       %-15.7g        %-6d      
 #
 #N         SHARPNESS   CHI         PIER  PERROR                                \
 #U         ##          ##          ##    perrors                               \
-#F         %-23.3f     %-12.3f     %-6d  %-13s                                 
+#F         %-23.3f     %-12.3f     %-6d  %-13s                                  
 #
 14       138.538   256.405   15.461      0.003         34.85955       4        \
-         -0.032      0.802       0     No_error                              
+           -0.032      0.802       0     No_error                               
 18       18.114    280.170   22.329      0.206         30.12784       4        \
-         -2.544      1.104       0     No_error      
+           -2.544      1.104       0     No_error                               
diff --git a/astropy/io/ascii/tests/t/daophot.dat.gz b/astropy/io/ascii/tests/t/daophot.dat.gz
new file mode 100644
index 0000000..6d74933
Binary files /dev/null and b/astropy/io/ascii/tests/t/daophot.dat.gz differ
diff --git a/astropy/io/ascii/tests/t/daophot2.dat b/astropy/io/ascii/tests/t/daophot2.dat
new file mode 100644
index 0000000..36e0012
--- /dev/null
+++ b/astropy/io/ascii/tests/t/daophot2.dat
@@ -0,0 +1,31 @@
+#N IMAGE               XINIT     YINIT     ID    COORDS                 LID    \
+#U imagename           pixels    pixels    ##    filename               ##     \
+#F %-23s               %-10.3f   %-10.3f   %-6d  %-23s                  %-6d    
+#
+#N XCENTER    YCENTER    XSHIFT  YSHIFT  XERR    YERR            CIER CERROR   \
+#U pixels     pixels     pixels  pixels  pixels  pixels          ##   cerrors  \
+#F %-14.3f    %-11.3f    %-8.3f  %-8.3f  %-8.3f  %-15.3f         %-5d %-9s      
+#
+#N MSKY           STDEV          SSKEW          NSKY   NSREJ     SIER SERROR   \
+#U counts         counts         counts         npix   npix      ##   serrors  \
+#F %-18.7g        %-15.7g        %-15.7g        %-7d   %-9d      %-5d %-9s      
+#
+#N ITIME          XAIRMASS       IFILTER                OTIME                  \
+#U timeunit       number         name                   timeunit               \
+#F %-18.7g        %-15.7g        %-23s                  %-23s                   
+#
+#N RAPERT   SUM           AREA       FLUX          MAG    MERR   PIER PERROR   \
+#U scale    counts        pixels     counts        mag    mag    ##   perrors  \
+#F %-12.2f  %-14.7g       %-11.7g    %-14.7g       %-7.3f %-6.3f %-5d %-9s      
+#
+n8q624e8q12_cal.fits[1]76.102    2.280     1     test.stars             1      \
+   76.150     2.182      0.048   -0.098  0.016   0.014          108  BadPixels \
+   0.5378259      0.1369367      0.1002712      604    176      0    NoError   \
+   1407.892       INDEF          F160W                  INDEF                  \
+   4.00     0.            0.         0.            INDEF  INDEF 301  OffImage   
+n8q624e8q12_cal.fits[1]81.730    3.167     2     test.stars             2      \
+   76.150     2.182      -5.580  -0.985  0.016   0.014          108  BadPixels \
+   0.5378259      0.1369367      0.1002712      604    176      0    NoError   \
+   1407.892       INDEF          F160W                  INDEF                  \
+   4.00     0.            0.         0.            INDEF  INDEF 301  OffImage   
+
diff --git a/astropy/io/ascii/tests/t/ipac.dat b/astropy/io/ascii/tests/t/ipac.dat
index fff863c..453928e 100644
--- a/astropy/io/ascii/tests/t/ipac.dat
+++ b/astropy/io/ascii/tests/t/ipac.dat
@@ -7,6 +7,6 @@
 |     ra   |    dec   |   sai   |-----v2---|    sptype        |
 |    real  |   real   |   int   |    real  |     char         |
 |    unit  |   unit   |   unit  |    unit  |     ergs         |
-|    null  |   null   |   null  |    null  |     -999         |
-   2.09708   29.09056     73765    2.06000   B8IVpMnHg
+|    null  |   null   |   -999  |    null  |     -999         |
+   null      29.09056     -999    2.06000    -999
 12345678901234567890123456789012345678901234567890123456789012345
diff --git a/astropy/io/ascii/tests/t/ipac.dat.bz2 b/astropy/io/ascii/tests/t/ipac.dat.bz2
new file mode 100644
index 0000000..a1dd341
Binary files /dev/null and b/astropy/io/ascii/tests/t/ipac.dat.bz2 differ
diff --git a/astropy/io/ascii/tests/t/latex1.tex.gz b/astropy/io/ascii/tests/t/latex1.tex.gz
new file mode 100644
index 0000000..da586f2
Binary files /dev/null and b/astropy/io/ascii/tests/t/latex1.tex.gz differ
diff --git a/astropy/io/ascii/tests/t/no_data_daophot.dat b/astropy/io/ascii/tests/t/no_data_daophot.dat
index bea716b..3fb49ef 100644
--- a/astropy/io/ascii/tests/t/no_data_daophot.dat
+++ b/astropy/io/ascii/tests/t/no_data_daophot.dat
@@ -1,7 +1,7 @@
 #K MERGERAD   = INDEF                   scaleunit  %-23.7g  
 #N ID    XCENTER   YCENTER   MAG         MERR          MSKY           NITER    \
 #U ##    pixels    pixels    magnitudes  magnitudes    counts         ##       \
-#F %-9d  %-10.3f   %-10.3f   %-12.3f     %-14.3f       %-15.7g        %-6d     #
+#F %-9d  %-10.3f   %-10.3f   %-12.3f     %-14.3f       %-15.7g        %-6d     
 #N         SHARPNESS   CHI         PIER  PERROR                                \
 #U         ##          ##          ##    perrors                               \
-#F         %-23.3f     %-12.3f     %-6d  %-13s                                 #
+#F         %-23.3f     %-12.3f     %-6d  %-13s                                 
diff --git a/astropy/io/ascii/tests/t/no_data_sextractor.dat b/astropy/io/ascii/tests/t/no_data_sextractor.dat
new file mode 100644
index 0000000..a9da39b
--- /dev/null
+++ b/astropy/io/ascii/tests/t/no_data_sextractor.dat
@@ -0,0 +1,5 @@
+# 1 NUMBER        Galaxy ID number
+# 2 FLUX_ISO   
+# 3 FLUXERR_ISO   
+# 4 VALUES        Note column 5 is missing
+# 6 FLAG
diff --git a/astropy/io/ascii/tests/t/sextractor.dat b/astropy/io/ascii/tests/t/sextractor.dat
new file mode 100644
index 0000000..cd57b78
--- /dev/null
+++ b/astropy/io/ascii/tests/t/sextractor.dat
@@ -0,0 +1,8 @@
+# 1 NUMBER        Galaxy ID number
+# 2 FLUX_ISO   
+# 3 FLUXERR_ISO   
+# 4 VALUES        Note column 5 is missing
+# 6 FLAG
+1 0.02580616000000000 0.03974229000000000 1.6770000000000000 0.2710000000000000 0
+2 5.72769100000000009 0.20643300000000001 2.6250000000000000 2.5219999999999998 0
+3 88.31933999999999685 0.59369850000000002 5.9249999999999998 4.7140000000000004 0
diff --git a/astropy/io/ascii/tests/t/short.rdb.bz2 b/astropy/io/ascii/tests/t/short.rdb.bz2
new file mode 100644
index 0000000..9e6c495
Binary files /dev/null and b/astropy/io/ascii/tests/t/short.rdb.bz2 differ
diff --git a/astropy/io/ascii/tests/t/short.rdb.gz b/astropy/io/ascii/tests/t/short.rdb.gz
new file mode 100644
index 0000000..92172ff
Binary files /dev/null and b/astropy/io/ascii/tests/t/short.rdb.gz differ
diff --git a/astropy/io/ascii/tests/test_cds_header_from_readme.py b/astropy/io/ascii/tests/test_cds_header_from_readme.py
index 89c397d..779ea54 100644
--- a/astropy/io/ascii/tests/test_cds_header_from_readme.py
+++ b/astropy/io/ascii/tests/test_cds_header_from_readme.py
@@ -1,6 +1,7 @@
+from ....tests.helper import pytest
 from ... import ascii as asciitable
 
-from .common import (raises,
+from .common import (raises, numpy_lt_1p5,
                      assert_equal, assert_almost_equal, assert_true,
                      setup_function, teardown_function, has_isnan)
 
@@ -40,6 +41,7 @@ def test_glob_header():
         assert_equal(table['BibCode'][-2], '2005A&A...432..235R')
 
 
+ at pytest.mark.xfail('numpy_lt_1p5')
 def test_header_from_readme():
     r = asciitable.Cds("t/vizier/ReadMe")
     table = r.read("t/vizier/table1.dat")
diff --git a/astropy/io/ascii/tests/test_compressed.py b/astropy/io/ascii/tests/test_compressed.py
new file mode 100644
index 0000000..5539b2c
--- /dev/null
+++ b/astropy/io/ascii/tests/test_compressed.py
@@ -0,0 +1,28 @@
+import os
+import numpy as np
+
+from ....tests.helper import pytest
+from .. import read
+from .common import numpy_lt_1p5
+
+ROOT = os.path.abspath(os.path.dirname(__file__))
+
+
+ at pytest.mark.parametrize('filename', ['t/daophot.dat.gz', 't/latex1.tex.gz',
+                                      't/short.rdb.gz'])
+def test_gzip(filename):
+    t_comp = read(os.path.join(ROOT, filename))
+    t_uncomp = read(os.path.join(ROOT, filename.replace('.gz', '')))
+    assert t_comp.dtype.names == t_uncomp.dtype.names
+    assert np.all(t_comp._data == t_uncomp._data)
+
+
+ at pytest.mark.parametrize('filename', ['t/short.rdb.bz2', 't/ipac.dat.bz2'])
+def test_bzip2(filename):
+    # Can't read IPAC file with numpy 1.4
+    if numpy_lt_1p5 and filename == 't/ipac.dat.bz2':
+        return
+    t_comp = read(os.path.join(ROOT, filename))
+    t_uncomp = read(os.path.join(ROOT, filename.replace('.bz2', '')))
+    assert t_comp.dtype.names == t_uncomp.dtype.names
+    assert np.all(t_comp._data == t_uncomp._data)
diff --git a/astropy/io/ascii/tests/test_connect.py b/astropy/io/ascii/tests/test_connect.py
new file mode 100644
index 0000000..2ce78cf
--- /dev/null
+++ b/astropy/io/ascii/tests/test_connect.py
@@ -0,0 +1,84 @@
+import os
+from ....tests.helper import pytest
+
+from ....table import Table, Column
+
+from .common import numpy_lt_1p5
+ROOT = os.path.abspath(os.path.dirname(__file__))
+
+
+ at pytest.mark.parametrize('filename', ['t/cds.dat', 't/ipac.dat',
+                                      't/daophot.dat', 't/latex1.tex'])
+def test_read_generic(filename):
+    if numpy_lt_1p5 and filename in ['t/cds.dat', 't/ipac.dat']:
+        return
+    Table.read(os.path.join(ROOT, filename), format='ascii')
+
+
+def test_write_generic(tmpdir):
+    t = Table()
+    t.add_column(Column('a', [1,2,3]))
+    t.add_column(Column('b', ['a', 'b', 'c']))
+    t.write(str(tmpdir.join("test")), format='ascii')
+
+
+ at pytest.mark.xfail('numpy_lt_1p5')
+def test_read_ipac():
+    Table.read(os.path.join(ROOT, 't/ipac.dat'), format='ipac')
+
+
+ at pytest.mark.xfail('numpy_lt_1p5')
+def test_read_cds():
+    Table.read(os.path.join(ROOT, 't/cds.dat'), format='cds')
+
+
+def test_read_dapphot():
+    Table.read(os.path.join(ROOT, 't/daophot.dat'), format='daophot')
+
+
+def test_read_latex():
+    Table.read(os.path.join(ROOT, 't/latex1.tex'), format='latex')
+
+
+def test_read_latex_noformat():
+    Table.read(os.path.join(ROOT, 't/latex1.tex'))
+
+
+def test_write_latex(tmpdir):
+    t = Table()
+    t.add_column(Column('a', [1,2,3]))
+    t.add_column(Column('b', ['a', 'b', 'c']))
+    path = str(tmpdir.join("data.tex"))
+    t.write(path, format='latex')
+
+
+def test_write_latex_noformat(tmpdir):
+    t = Table()
+    t.add_column(Column('a', [1,2,3]))
+    t.add_column(Column('b', ['a', 'b', 'c']))
+    path = str(tmpdir.join("data.tex"))
+    t.write(path)
+
+
+def test_read_rdb():
+    Table.read(os.path.join(ROOT, 't/short.rdb'), format='rdb')
+
+
+def test_read_rdb_noformat():
+    Table.read(os.path.join(ROOT, 't/short.rdb'))
+
+
+def test_write_rdb(tmpdir):
+    t = Table()
+    t.add_column(Column('a', [1,2,3]))
+    t.add_column(Column('b', ['a', 'b', 'c']))
+    path = str(tmpdir.join("data.rdb"))
+    t.write(path, format='rdb')
+
+
+def test_write_rdb_noformat(tmpdir):
+    t = Table()
+    t.add_column(Column('a', [1,2,3]))
+    t.add_column(Column('b', ['a', 'b', 'c']))
+    path = str(tmpdir.join("data.rdb"))
+    t.write(path)
diff --git a/astropy/io/ascii/tests/test_ipac_definitions.py b/astropy/io/ascii/tests/test_ipac_definitions.py
new file mode 100644
index 0000000..c1e8dd4
--- /dev/null
+++ b/astropy/io/ascii/tests/test_ipac_definitions.py
@@ -0,0 +1,32 @@
+from ..ui import read
+from ..ipac import Ipac
+
+DATA = '''
+|   a  |   b   |
+| char | char  |
+ABBBBBBABBBBBBBA
+'''
+
+def test_ipac_default():
+    # default should be ignore
+    table = read(DATA, Reader=Ipac)
+    assert table['a'][0] == 'BBBBBB'
+    assert table['b'][0] == 'BBBBBBB'
+
+
+def test_ipac_ignore():
+    table = read(DATA, Reader=Ipac, definition='ignore')
+    assert table['a'][0] == 'BBBBBB'
+    assert table['b'][0] == 'BBBBBBB'
+    
+    
+def test_ipac_left():
+    table = read(DATA, Reader=Ipac, definition='left')
+    assert table['a'][0] == 'BBBBBBA'
+    assert table['b'][0] == 'BBBBBBBA'
+    
+    
+def test_ipac_right():
+    table = read(DATA, Reader=Ipac, definition='right')
+    assert table['a'][0] == 'ABBBBBB'
+    assert table['b'][0] == 'ABBBBBBB'
\ No newline at end of file
diff --git a/astropy/io/ascii/tests/test_memory.py b/astropy/io/ascii/tests/test_memory.py
deleted file mode 100644
index f1add61..0000000
--- a/astropy/io/ascii/tests/test_memory.py
+++ /dev/null
@@ -1,70 +0,0 @@
-import re
-import glob
-import numpy as np
-from ... import ascii as asciitable
-
-from .common import (raises,
-                     assert_equal, assert_almost_equal, assert_true,
-                     setup_function, teardown_function)
-
-
-def _test_values_equal(data, mem_data):
-    for colname in data.dtype.names:
-        matches = data[colname] == mem_data[colname]
-        assert(matches.all())
-
-
-def test_memory_from_table():
-    table = asciitable.get_reader(Reader=asciitable.Daophot)
-    data = table.read('t/daophot.dat')
-
-    mem_table = asciitable.get_reader(Reader=asciitable.Memory)
-    mem_data = mem_table.read(data)
-    assert(data.dtype.names == mem_data.dtype.names)
-    _test_values_equal(data, mem_data)
-
-    mem_data = mem_table.read(mem_table)
-    assert(data.dtype.names == mem_data.dtype.names)
-    _test_values_equal(data, mem_data)
-
-
-def test_memory_from_LOL():
-    data = [[1, 2, 3], [4, 5.2, 6.1], [8, 9, 'hello']]
-    mem_table = asciitable.get_reader(Reader=asciitable.Memory)
-    mem_data = mem_table.read(data)
-    print(mem_data.dtype.names)
-    assert(mem_data.dtype.names == ('col1', 'col2', 'col3'))
-    assert(mem_data[0][0] == 1)
-    assert(mem_data[0][1] == 2)
-    assert(mem_data[0][2] == '3')
-    assert((mem_data['col2'] == np.array([2, 5.2, 9])).all())
-    assert((mem_data['col3'] == np.array([3, 6.1, 'hello'])).all())
-
-
-def test_memory_from_LOL2():
-    data = [[1, 2, 3], [4, 5.2, 6.1], [8, 9, 'hello']]
-    mem_table = asciitable.get_reader(Reader=asciitable.Memory,
-                                      names=('c1', 'c2', 'c3'))
-    mem_data = mem_table.read(data)
-    print(mem_data.dtype.names)
-    assert(mem_data.dtype.names == ('c1', 'c2', 'c3'))
-    assert(mem_data[0][0] == 1)
-    assert(mem_data[0][1] == 2)
-    assert(mem_data[0][2] == '3')
-    assert((mem_data['c2'] == np.array([2, 5.2, 9])).all())
-    assert((mem_data['c3'] == np.array([3, 6.1, 'hello'])).all())
-
-
-def test_memory_from_DOL():
-    data = {'c1': [1, 2, 3],
-            'c2': [4, 5.2, 6.1],
-            'c3': [8, 9, 'hello']}
-    mem_table = asciitable.get_reader(Reader=asciitable.Memory,
-                                      names=sorted(data.keys()))
-    mem_data = mem_table.read(data)
-    assert(mem_data.dtype.names == ('c1', 'c2', 'c3'))
-    assert(mem_data[0][0] == 1)
-    assert(mem_data[0][1] == 4)
-    assert(mem_data[0][2] == '8')
-    assert((mem_data['c2'] == np.array([4, 5.2, 6.1])).all())
-    assert((mem_data['c3'] == np.array([8, 9, 'hello'])).all())
diff --git a/astropy/io/ascii/tests/test_read.py b/astropy/io/ascii/tests/test_read.py
index 4b8e283..8e604d9 100644
--- a/astropy/io/ascii/tests/test_read.py
+++ b/astropy/io/ascii/tests/test_read.py
@@ -3,15 +3,20 @@ import glob
 import math
 
 import numpy as np
+
+from ....tests.helper import pytest
 from ... import ascii as asciitable
 
-from .common import (raises,
+from .common import (raises, numpy_lt_1p5,
                      assert_equal, assert_almost_equal, assert_true,
                      setup_function, teardown_function, has_isnan)
 
 
 def test_read_all_files():
     for testfile in get_testfiles():
+        if testfile.get('skip'):
+            print('\n\n******** SKIPPING %s' % testfile['name'])
+            continue
         print('\n\n******** READING %s' % testfile['name'])
         for guess in (True, False):
             test_opts = testfile['opts'].copy()
@@ -25,6 +30,9 @@ def test_read_all_files():
 
 def test_guess_all_files():
     for testfile in get_testfiles():
+        if testfile.get('skip'):
+            print('\n\n******** SKIPPING %s' % testfile['name'])
+            continue
         if not testfile['opts'].get('guess', True):
             continue
         print('\n\n******** READING %s' % testfile['name'])
@@ -39,22 +47,17 @@ def test_guess_all_files():
 
 
 def test_daophot_header_keywords():
-    reader = asciitable.get_reader(Reader=asciitable.Daophot)
-    table = reader.read('t/daophot.dat')
+    table = asciitable.read('t/daophot.dat', Reader=asciitable.Daophot)
     expected_keywords = (('NSTARFILE', 'test.nst.1', 'filename', '%-23s'),
                          ('REJFILE', 'hello world', 'filename', '%-23s'),
                          ('SCALE', '1.',  'units/pix', '%-23.7g'),)
 
+    keywords = table.meta['keywords']  # Ordered dict of keyword structures
     for name, value, units, format_ in expected_keywords:
-        for keyword in reader.keywords:
-            if keyword.name == name:
-                assert_equal(keyword.value, value)
-                assert_equal(keyword.units, units)
-                assert_equal(keyword.format, format_)
-                break
-        else:
-            raise ValueError('Keyword not found')
-
+        keyword = keywords[name]
+        assert_equal(keyword['value'], value)
+        assert_equal(keyword['units'], units)
+        assert_equal(keyword['format'], format_)
 
 
 @raises(asciitable.InconsistentTableError)
@@ -85,8 +88,6 @@ def test_missing_file():
 
 def test_set_names():
     names = ('c1','c2','c3', 'c4', 'c5', 'c6')
-    include_names = ('c1', 'c3')
-    exclude_names = ('c4', 'c5', 'c6')
     data = asciitable.read('t/simple3.txt', names=names, delimiter='|')
     assert_equal(data.dtype.names, names)
 
@@ -105,6 +106,18 @@ def test_set_exclude_names():
     assert_equal(data.dtype.names, ('obsid', 'redshift', 'X', 'rad'))
 
 
+def test_include_names_daophot():
+    include_names = ('ID', 'MAG', 'PIER')
+    data = asciitable.read('t/daophot.dat', include_names=include_names)
+    assert_equal(data.dtype.names, include_names)
+
+
+def test_exclude_names_daophot():
+    exclude_names = ('ID', 'YCENTER', 'MERR', 'NITER', 'CHI', 'PERROR')
+    data = asciitable.read('t/daophot.dat', exclude_names=exclude_names)
+    assert_equal(data.dtype.names, ('XCENTER', 'MAG', 'MSKY', 'SHARPNESS', 'PIER'))
+
+
 def test_custom_process_lines():
     def process_lines(lines):
         bars_at_ends = re.compile(r'^\| | \|$', re.VERBOSE)
@@ -117,6 +130,7 @@ def test_custom_process_lines():
     assert_equal(len(data), 3)
 
 
+ at pytest.mark.xfail('numpy_lt_1p5')
 def test_custom_process_line():
     def process_line(line):
         line_out = re.sub(r'^\|\s*', '', line.strip())
@@ -173,7 +187,7 @@ def test_from_string():
 
 def test_from_filelike():
     f = 't/simple.txt'
-    table = open(f)
+    table = open(f, 'rb')
     testfile = get_testfiles(f)
     data = asciitable.read(table, **testfile['opts'])
     assert_equal(data.dtype.names, testfile['cols'])
@@ -195,16 +209,18 @@ def test_comment_lines():
     assert_equal(table.comment_lines, ['# first comment', '  # second comment'])
 
 
+ at pytest.mark.xfail('numpy_lt_1p5')
 def test_fill_values():
     f = 't/fill_values.txt'
     testfile = get_testfiles(f)
     data = asciitable.read(f, fill_values=('a','1'), **testfile['opts'])
-    assert_true((data.mask['a']==[False,True]).all())
-    assert_true((data.data['a']==[1,1]).all())
-    assert_true((data.mask['b']==[False,True]).all())
-    assert_true((data.data['b']==[2,1]).all())
+    assert_true((data['a'].mask==[False,True]).all())
+    assert_true((data['a']==[1,1]).all())
+    assert_true((data['b'].mask==[False,True]).all())
+    assert_true((data['b']==[2,1]).all())
 
 
+ at pytest.mark.xfail('numpy_lt_1p5')
 def test_fill_values_col():
     f = 't/fill_values.txt'
     testfile = get_testfiles(f)
@@ -212,6 +228,7 @@ def test_fill_values_col():
     check_fill_values(data)
 
 
+ at pytest.mark.xfail('numpy_lt_1p5')
 def test_fill_values_include_names():
     f = 't/fill_values.txt'
     testfile = get_testfiles(f)
@@ -220,6 +237,7 @@ def test_fill_values_include_names():
     check_fill_values(data)
 
 
+ at pytest.mark.xfail('numpy_lt_1p5')
 def test_fill_values_exclude_names():
     f = 't/fill_values.txt'
     testfile = get_testfiles(f)
@@ -228,22 +246,29 @@ def test_fill_values_exclude_names():
     check_fill_values(data)
 
 
+ at pytest.mark.xfail('numpy_lt_1p5')
 def check_fill_values(data):
     """compare array column by column with expectation """
-    assert_true((data.mask['a']==[False,False]).all())
-    assert_true((data.data['a']==['1','a']).all())
-    assert_true((data.mask['b']==[False,True]).all())
-    assert_true((data.data['b']==[2,1]).all())        
+    assert_true((data['a'].mask==[False,False]).all())
+    assert_true((data['a']==['1','a']).all())
+    assert_true((data['b'].mask==[False,True]).all())
+    # Check that masked value is "do not care" in comparison
+    assert_true((data['b']==[2, -999]).all())
+    data['b'].mask = False  # explicitly unmask for comparison
+    assert_true((data['b']==[2,1]).all())
 
 
+ at pytest.mark.xfail('numpy_lt_1p5')
 def test_fill_values_list():
     f = 't/fill_values.txt'
     testfile = get_testfiles(f)
     data = asciitable.read(f, fill_values=[('a','42'),('1','42','a')],
                            **testfile['opts'])
-    assert_true((data.data['a']==[42,42]).all())
+    data['a'].mask = False  # explicitly unmask for comparison
+    assert_true((data['a']==[42,42]).all())
 
 
+ at pytest.mark.xfail('numpy_lt_1p5')
 def test_masking_Cds():
     f = 't/cds.dat'
     testfile = get_testfiles(f)
@@ -253,6 +278,18 @@ def test_masking_Cds():
     assert_true(not data['Fit'].mask[0])
 
 
+ at pytest.mark.xfail('numpy_lt_1p5')
+def test_null_Ipac():
+    f = 't/ipac.dat'
+    testfile = get_testfiles(f)
+    data = asciitable.read(f, **testfile['opts'])
+    mask = np.array([(True, False, True, False, True),
+                     (False, False, False, False, False)],
+                    dtype=[('ra', '|b1'), ('dec', '|b1'), ('sai', '|b1'),
+                           ('v2', '|b1'), ('sptype', '|b1')])
+    assert np.all(data.mask == mask)
+
+
 def test_set_guess_kwarg():
     """Read a file using guess with one of the typical guess_kwargs explicitly set."""
     data = asciitable.read('t/space_delim_no_header.dat',
@@ -296,12 +333,16 @@ def get_testfiles(name=None):
                   'Fit'),
          'name': 't/cds.dat',
          'nrows': 1,
-         'opts': {'Reader': asciitable.Cds,
-                  'Outputter': asciitable.NumpyOutputter}},
+         'skip': numpy_lt_1p5,
+         'opts': {'Reader': asciitable.Cds}},
         {'cols': ('a', 'b', 'c'),
          'name': 't/commented_header.dat',
          'nrows': 2,
          'opts': {'Reader': asciitable.CommentedHeader}},
+        {'cols': ('a', 'b', 'c'),
+         'name': 't/commented_header2.dat',
+         'nrows': 2,
+         'opts': {'Reader': asciitable.CommentedHeader, 'header_start': -1}},
         {'cols': ('col1', 'col2', 'col3', 'col4', 'col5'),
          'name': 't/continuation.dat',
          'nrows': 2,
@@ -322,9 +363,57 @@ def get_testfiles(name=None):
          'nrows': 2,
          'requires_numpy': True,
          'opts': {'Reader': asciitable.Daophot}},
+        {'cols': ('IMAGE',
+                  'XINIT',
+                  'YINIT',
+                  'ID',
+                  'COORDS',
+                  'LID',
+                  'XCENTER',
+                  'YCENTER',
+                  'XSHIFT',
+                  'YSHIFT',
+                  'XERR',
+                  'YERR',
+                  'CIER',
+                  'CERROR',
+                  'MSKY',
+                  'STDEV',
+                  'SSKEW',
+                  'NSKY',
+                  'NSREJ',
+                  'SIER',
+                  'SERROR',
+                  'ITIME',
+                  'XAIRMASS',
+                  'IFILTER',
+                  'OTIME',
+                  'RAPERT',
+                  'SUM',
+                  'AREA',
+                  'FLUX',
+                  'MAG',
+                  'MERR',
+                  'PIER',
+                  'PERROR'),
+         'name': 't/daophot2.dat',
+         'nrows': 2,
+         'requires_numpy': True,
+         'opts': {'Reader': asciitable.Daophot}},
+        {'cols': ('NUMBER',
+                  'FLUX_ISO',
+                  'FLUXERR_ISO',
+                  'VALUES',
+                  'VALUES_1',
+                  'FLAG'),
+         'name': 't/sextractor.dat',
+         'nrows': 3,
+         'requires_numpy': True,
+         'opts': {'Reader': asciitable.SExtractor}},
         {'cols': ('ra', 'dec', 'sai', 'v2', 'sptype'),
          'name': 't/ipac.dat',
          'nrows': 2,
+         'skip': numpy_lt_1p5,
          'opts': {'Reader': asciitable.Ipac}},
         {'cols': ('col0',
                   'objID',
@@ -346,6 +435,7 @@ def get_testfiles(name=None):
                   'detlim90',
                   'fBlim90'),
          'name': 't/nls1_stackinfo.dbout',
+         'skip': numpy_lt_1p5,
          'nrows': 58,
          'opts': {'data_start': 2, 'delimiter': '|', 'guess': False}},
         {'cols': ('Index',
@@ -361,6 +451,7 @@ def get_testfiles(name=None):
                   'AK',
                   'Fit'),
          'name': 't/no_data_cds.dat',
+         'skip': numpy_lt_1p5,
          'nrows': 0,
          'opts': {'Reader': asciitable.Cds}},
         {'cols': ('ID',
@@ -378,9 +469,20 @@ def get_testfiles(name=None):
          'nrows': 0,
          'requires_numpy': True,
          'opts': {'Reader': asciitable.Daophot}},
+        {'cols': ('NUMBER',
+                  'FLUX_ISO',
+                  'FLUXERR_ISO',
+                  'VALUES',
+                  'VALUES_1',
+                  'FLAG'),
+         'name': 't/no_data_sextractor.dat',
+         'nrows': 0,
+         'requires_numpy': True,
+         'opts': {'Reader': asciitable.SExtractor}},
         {'cols': ('ra', 'dec', 'sai', 'v2', 'sptype'),
          'name': 't/no_data_ipac.dat',
          'nrows': 0,
+         'skip': numpy_lt_1p5,
          'opts': {'Reader': asciitable.Ipac}},
         {'cols': ('a', 'b', 'c'),
          'name': 't/no_data_with_header.dat',
diff --git a/astropy/io/ascii/tests/test_types.py b/astropy/io/ascii/tests/test_types.py
index 3e2bb11..9377bf5 100644
--- a/astropy/io/ascii/tests/test_types.py
+++ b/astropy/io/ascii/tests/test_types.py
@@ -10,13 +10,13 @@ try:
 except ImportError:
     import io
 
+from ....tests.helper import pytest
 from ... import ascii as asciitable
 
-from .common import (raises,
+from .common import (raises, numpy_lt_1p5,
                      assert_equal, assert_almost_equal, assert_true,
                      setup_function, teardown_function)
 
-
 def test_types_from_dat():
     converters = {'a': [asciitable.convert_numpy(np.float)],
                   'e': [asciitable.convert_numpy(np.str)]}
@@ -25,18 +25,11 @@ def test_types_from_dat():
                           Reader=asciitable.Basic,
                           converters=converters)
 
-    reader = asciitable.get_reader(Reader=asciitable.Memory)
-    reader.read(dat)
-
-    print('dat=%s' % repr(dat))
-    print('reader.table=%s' % repr(reader.table))
-    print('types=%s' % repr([x.type for x in reader.cols]))
-
-    assert_true(issubclass(reader.cols[0].type, asciitable.FloatType))
-    assert_true(issubclass(reader.cols[1].type, asciitable.IntType))
-    assert_true(issubclass(reader.cols[2].type, asciitable.StrType))
-    assert_true(issubclass(reader.cols[3].type, asciitable.FloatType))
-    assert_true(issubclass(reader.cols[4].type, asciitable.StrType))
+    assert dat['a'].dtype.kind == 'f'
+    assert dat['b'].dtype.kind == 'i'
+    assert dat['c'].dtype.kind in ('S', 'U')
+    assert dat['d'].dtype.kind == 'f'
+    assert dat['e'].dtype.kind in ('S', 'U')
 
 
 def test_rdb_write_types():
@@ -48,6 +41,7 @@ def test_rdb_write_types():
     assert_equal(outs[1], 'N\tN\tS\tN')
 
 
+ at pytest.mark.xfail('numpy_lt_1p5')
 def test_ipac_read_types():
     table = r"""\
 |     ra   |    dec   |   sai   |-----v2---|    sptype        |
diff --git a/astropy/io/ascii/tests/test_write.py b/astropy/io/ascii/tests/test_write.py
index b4dca9b..4c059c2 100644
--- a/astropy/io/ascii/tests/test_write.py
+++ b/astropy/io/ascii/tests/test_write.py
@@ -16,12 +16,13 @@ test_defs = [
          out="""\
 ID XCENTER YCENTER MAG MERR MSKY NITER SHARPNESS CHI PIER PERROR
 14 138.538 256.405 15.461 0.003 34.85955 4 -0.032 0.802 0 No_error
-18 18.114 280.17 22.329 0.206 30.12784 4 -2.544 1.104 0 No_error
+18 18.114 280.170 22.329 0.206 30.12784 4 -2.544 1.104 0 No_error
 """
          ),
     dict(kwargs=dict(formats={'XCENTER': '%12.1f',
-                              'YCENTER': lambda x: round(x, 1)},
-                     include_names=['XCENTER', 'YCENTER']),
+                              'YCENTER': '{0:.1f}'},
+                     include_names=['XCENTER', 'YCENTER'],
+                     strip_whitespace=False),
          out="""\
 XCENTER YCENTER
 "       138.5" 256.4
@@ -33,27 +34,27 @@ XCENTER YCENTER
 ID	XCENTER	YCENTER	MAG	MERR	MSKY	NITER	SHARPNESS	PIER	PERROR
 N	N	N	N	N	N	N	N	N	S
 14	138.538	256.405	15.461	0.003	34.85955	4	-0.032	0	No_error
-18	18.114	280.17	22.329	0.206	30.12784	4	-2.544	0	No_error
+18	18.114	280.170	22.329	0.206	30.12784	4	-2.544	0	No_error
 """
          ),   
     dict(kwargs=dict(Writer=asciitable.Tab),
          out="""\
 ID	XCENTER	YCENTER	MAG	MERR	MSKY	NITER	SHARPNESS	CHI	PIER	PERROR
 14	138.538	256.405	15.461	0.003	34.85955	4	-0.032	0.802	0	No_error
-18	18.114	280.17	22.329	0.206	30.12784	4	-2.544	1.104	0	No_error
+18	18.114	280.170	22.329	0.206	30.12784	4	-2.544	1.104	0	No_error
 """
          ),   
     dict(kwargs=dict(Writer=asciitable.NoHeader),
          out="""\
 14 138.538 256.405 15.461 0.003 34.85955 4 -0.032 0.802 0 No_error
-18 18.114 280.17 22.329 0.206 30.12784 4 -2.544 1.104 0 No_error
+18 18.114 280.170 22.329 0.206 30.12784 4 -2.544 1.104 0 No_error
 """
          ),   
     dict(kwargs=dict(Writer=asciitable.CommentedHeader),
          out="""\
 # ID XCENTER YCENTER MAG MERR MSKY NITER SHARPNESS CHI PIER PERROR
 14 138.538 256.405 15.461 0.003 34.85955 4 -0.032 0.802 0 No_error
-18 18.114 280.17 22.329 0.206 30.12784 4 -2.544 1.104 0 No_error
+18 18.114 280.170 22.329 0.206 30.12784 4 -2.544 1.104 0 No_error
 """
          ),   
     dict(kwargs=dict(Writer=asciitable.Latex),
@@ -62,7 +63,7 @@ ID	XCENTER	YCENTER	MAG	MERR	MSKY	NITER	SHARPNESS	CHI	PIER	PERROR
 \\begin{tabular}{ccccccccccc}
 ID & XCENTER & YCENTER & MAG & MERR & MSKY & NITER & SHARPNESS & CHI & PIER & PERROR \\\\
 14 & 138.538 & 256.405 & 15.461 & 0.003 & 34.85955 & 4 & -0.032 & 0.802 & 0 & No_error \\\\
-18 & 18.114 & 280.17 & 22.329 & 0.206 & 30.12784 & 4 & -2.544 & 1.104 & 0 & No_error \\\\
+18 & 18.114 & 280.170 & 22.329 & 0.206 & 30.12784 & 4 & -2.544 & 1.104 & 0 & No_error \\\\
 \\end{tabular}
 \\end{table}
 """
@@ -73,7 +74,7 @@ ID & XCENTER & YCENTER & MAG & MERR & MSKY & NITER & SHARPNESS & CHI & PIER & PE
 \\tablehead{\\colhead{ID} & \\colhead{XCENTER} & \\colhead{YCENTER} & \\colhead{MAG} & \\colhead{MERR} & \\colhead{MSKY} & \\colhead{NITER} & \\colhead{SHARPNESS} & \\colhead{CHI} & \\colhead{PIER} & \\colhead{PERROR}}
 \\startdata
 14 & 138.538 & 256.405 & 15.461 & 0.003 & 34.85955 & 4 & -0.032 & 0.802 & 0 & No_error \\\\
-18 & 18.114 & 280.17 & 22.329 & 0.206 & 30.12784 & 4 & -2.544 & 1.104 & 0 & No_error \\\\
+18 & 18.114 & 280.170 & 22.329 & 0.206 & 30.12784 & 4 & -2.544 & 1.104 & 0 & No_error \\\\
 \\enddata
 \\end{deluxetable}
 """
@@ -85,7 +86,7 @@ ID & XCENTER & YCENTER & MAG & MERR & MSKY & NITER & SHARPNESS & CHI & PIER & PE
 \\tablehead{\\colhead{ID} & \\colhead{XCENTER} & \\colhead{YCENTER} & \\colhead{MAG} & \\colhead{MERR} & \\colhead{MSKY} & \\colhead{NITER} & \\colhead{SHARPNESS} & \\colhead{CHI} & \\colhead{PIER} & \\colhead{PERROR}\\\\ \\colhead{ } & \\colhead{[pixel]} & \\colhead{ } & \\colhead{[mag]} & \\colhead{ } & \\colhead{ } & \\colhead{ } & \\colhead{ } & \\colhead{ } & \\colhead{ } & \\colhead{ }}
 \\startdata
 14 & 138.538 & 256.405 & 15.461 & 0.003 & 34.85955 & 4 & -0.032 & 0.802 & 0 & No_error \\\\
-18 & 18.114 & 280.17 & 22.329 & 0.206 & 30.12784 & 4 & -2.544 & 1.104 & 0 & No_error \\\\
+18 & 18.114 & 280.170 & 22.329 & 0.206 & 30.12784 & 4 & -2.544 & 1.104 & 0 & No_error \\\\
 \\enddata
 \\end{deluxetable}
 """
@@ -97,9 +98,9 @@ ID & XCENTER & YCENTER & MAG & MERR & MSKY & NITER & SHARPNESS & CHI & PIER & PE
 \\caption{Mag values \\label{tab1}}
 \\begin{tabular}{|lcccccccccc|}
 ID & XCENTER & YCENTER & MAG & MERR & MSKY & NITER & SHARPNESS & CHI & PIER & PERROR \\\\
-  & [pixel] &   & [mag] &   &   &   &   &   &   &   \\\\
+ & [pixel] &  & [mag] &  &  &  &  &  &  &  \\\\
 14 & 138.538 & 256.405 & 15.461 & 0.003 & 34.85955 & 4 & -0.032 & 0.802 & 0 & No_error \\\\
-18 & 18.114 & 280.17 & 22.329 & 0.206 & 30.12784 & 4 & -2.544 & 1.104 & 0 & No_error \\\\
+18 & 18.114 & 280.170 & 22.329 & 0.206 & 30.12784 & 4 & -2.544 & 1.104 & 0 & No_error \\\\
 \\hline
 \\hline
 \\end{tabular}
@@ -115,11 +116,11 @@ preamble
 \\begin{tabular}{col_align}
 header_start
 ID & XCENTER & YCENTER & MAG & MERR & MSKY & NITER & SHARPNESS & CHI & PIER & PERROR \\\\
-  &   &   &   &   &   &   &   &   &   &   \\\\
+ &  &  &  &  &  &  &  &  &  &  \\\\
 header_end
 data_start
 14 & 138.538 & 256.405 & 15.461 & 0.003 & 34.85955 & 4 & -0.032 & 0.802 & 0 & No_error \\\\
-18 & 18.114 & 280.17 & 22.329 & 0.206 & 30.12784 & 4 & -2.544 & 1.104 & 0 & No_error \\\\
+18 & 18.114 & 280.170 & 22.329 & 0.206 & 30.12784 & 4 & -2.544 & 1.104 & 0 & No_error \\\\
 data_end
 \\end{tabular}
 tablefoot
diff --git a/astropy/io/ascii/ui.py b/astropy/io/ascii/ui.py
index 267194d..09e218f 100644
--- a/astropy/io/ascii/ui.py
+++ b/astropy/io/ascii/ui.py
@@ -1,4 +1,4 @@
-"""asciitable: an extensible ASCII table reader and writer.
+"""An extensible ASCII table reader and writer.
 
 ui.py:
   Provides the main user functions for reading and writing tables.
@@ -40,8 +40,8 @@ from . import core
 from . import basic
 from . import cds
 from . import daophot
+from . import sextractor
 from . import ipac
-from . import memory
 from .core import next, izip, any
 from . import latex
 
@@ -94,7 +94,7 @@ def read(table, guess=None, **kwargs):
 
     :param table: input table (file name, list of strings, or single newline-separated string)
     :param guess: try to guess the table format (default=True)
-    :param Reader: Reader class (default= :class:`~asciitable.Basic`)
+    :param Reader: Reader class (default=``ascii.Basic``)
     :param Inputter: Inputter class
     :param Outputter: Outputter class
     :param delimiter: column delimiter string
@@ -118,10 +118,7 @@ def read(table, guess=None, **kwargs):
     # Provide a simple way to choose between the two common outputters.  If an
     # Outputter is supplied in kwargs that will take precedence.
     new_kwargs = {}
-    if 'fill_values' not in kwargs:
-        new_kwargs['Outputter'] = core.TableOutputter
-    else:
-        new_kwargs['Outputter'] = core.NumpyOutputter
+    new_kwargs['Outputter'] = core.TableOutputter
     new_kwargs.update(kwargs)
 
     if guess is None:
@@ -210,6 +207,7 @@ def _get_guess_kwargs_list():
                          dict(Reader=basic.Tab),
                          dict(Reader=cds.Cds),
                          dict(Reader=daophot.Daophot),
+                         dict(Reader=sextractor.SExtractor),
                          dict(Reader=ipac.Ipac),
                          dict(Reader=latex.Latex),
                          dict(Reader=latex.AASTex)
@@ -222,23 +220,26 @@ def _get_guess_kwargs_list():
     return guess_kwargs_list
 
 extra_writer_pars = ('delimiter', 'comment', 'quotechar', 'formats',
-                     'names', 'include_names', 'exclude_names')
+                     'names', 'include_names', 'exclude_names', 'strip_whitespace')
 
 def get_writer(Writer=None, **kwargs):
     """Initialize a table writer allowing for common customizations.  Most of the
     default behavior for various parameters is determined by the Writer class.
 
-    :param Writer: Writer class (default= :class:`~asciitable.Basic` )
+    :param Writer: Writer class (default=``ascii.Basic``)
     :param delimiter: column delimiter string
     :param write_comment: string defining a comment line in table
     :param quotechar: one-character string to quote fields containing special characters
     :param formats: dict of format specifiers or formatting functions
+    :param strip_whitespace: strip surrounding whitespace from column values (default=True)
     :param names: list of names corresponding to each data column
     :param include_names: list of names to include in output (default=None selects all names)
     :param exclude_names: list of names to exlude from output (applied after ``include_names``)
     """
     if Writer is None:
         Writer = basic.Basic
+    if 'strip_whitespace' not in kwargs:
+        kwargs['strip_whitespace'] = True
     writer = core._get_writer(Writer, **kwargs)
     return writer
 
@@ -248,23 +249,29 @@ def write(table, output=sys.stdout,  Writer=None, **kwargs):
 
     :param table: input table (Reader object, NumPy struct array, list of lists, etc)
     :param output: output [filename, file-like object] (default = sys.stdout)
-    :param Writer: Writer class (default= :class:`~asciitable.Basic` )
+    :param Writer: Writer class (default=``ascii.Basic``)
     :param delimiter: column delimiter string
     :param write_comment: string defining a comment line in table
     :param quotechar: one-character string to quote fields containing special characters
     :param formats: dict of format specifiers or formatting functions
+    :param strip_whitespace: strip surrounding whitespace from column values (default=True)
     :param names: list of names corresponding to each data column
     :param include_names: list of names to include in output (default=None selects all names)
     :param exclude_names: list of names to exlude from output (applied after ``include_names``)
     """
 
     table = Table(table, names=kwargs.get('names'))
-    reader_kwargs = dict((key, val) for key, val in kwargs.items()
-                         if key in ('names', 'include_names', 'exclude_names'))
-    if not isinstance(table, core.BaseReader) or reader_kwargs:
-        reader = get_reader(Reader=memory.Memory, **reader_kwargs)
-        reader.read(table)
-        table = reader
+
+    names = set(table.colnames)
+    if 'include_names' in kwargs:
+        names.intersection_update(kwargs['include_names'])
+    if 'exclude_names' in kwargs:
+        names.difference_update(kwargs['exclude_names'])
+    if names != set(table.colnames):
+        remove_names = set(table.colnames) - set(names)
+        table.remove_columns(remove_names)
+
+    table.cols = table.columns.values()
 
     writer = get_writer(Writer=Writer, **kwargs)
     lines = writer.write(table)
diff --git a/astropy/io/fits/__init__.py b/astropy/io/fits/__init__.py
index b752604..679adce 100644
--- a/astropy/io/fits/__init__.py
+++ b/astropy/io/fits/__init__.py
@@ -12,7 +12,6 @@ standard, see the NASA/Science Office of Standards and Technology
 publication, NOST 100-2.0.
 """
 
-import os
 
 from . import py3compat
 
diff --git a/astropy/io/fits/card.py b/astropy/io/fits/card.py
index c497bd8..591d231 100644
--- a/astropy/io/fits/card.py
+++ b/astropy/io/fits/card.py
@@ -24,7 +24,9 @@ FIX_FP_TABLE = maketrans('de', 'DE')
 FIX_FP_TABLE2 = maketrans('dD', 'eE')
 
 
-BLANK_CARD = ' ' * 80
+CARD_LENGTH = 80
+BLANK_CARD = ' ' * CARD_LENGTH
+KEYWORD_LENGTH = 8  # The max length for FITS-standard keywords
 
 
 class Undefined:
@@ -229,11 +231,11 @@ class CardList(list):
 
     @deprecated('3.1', alternative=':meth:`Header.index`')
     def index(self, card):
-        return self._header.cards.index(card)
+        return self._header._cards.index(card)
 
     @deprecated('3.1', alternative=':meth:`Header.count`')
     def count(self, card):
-        return self._header.cards.count(card)
+        return self._header._cards.count(card)
 
     @deprecated('3.1', alternative=':meth:`Header.index`', pending=False)
     def index_of(self, key, backward=False):
@@ -299,10 +301,10 @@ class CardList(list):
 
 
 class Card(_Verify):
-    length = 80
+    length = CARD_LENGTH
 
     # String for a FITS standard compliant (FSC) keyword.
-    _keywd_FSC_RE = re.compile(r'^[A-Z0-9_-]{0,8}$')
+    _keywd_FSC_RE = re.compile(r'^[A-Z0-9_-]{0,%d}$' % KEYWORD_LENGTH)
     # This will match any printable ASCII character excluding '='
     _keywd_hierarch_RE = re.compile(r'^(?:HIERARCH )?(?:^[ -<>-~]+ ?)+$', re.I)
 
@@ -382,13 +384,13 @@ class Card(_Verify):
     _rvkc_identifier = r'[a-zA-Z_]\w*'
     _rvkc_field = _rvkc_identifier + r'(\.\d+)?'
     _rvkc_field_specifier_s = r'%s(\.%s)*' % ((_rvkc_field,) * 2)
-    _rvkc_field_specifier_val = (r'(?P<keyword>%s): (?P<val>%s\s*)' %
+    _rvkc_field_specifier_val = (r'(?P<keyword>%s): (?P<val>%s)' %
                                  (_rvkc_field_specifier_s, _numr_FSC))
-    _rvkc_keyword_val = r'\'%s\'' % _rvkc_field_specifier_val
+    _rvkc_keyword_val = r'\'(?P<rawval>%s)\'' % _rvkc_field_specifier_val
     _rvkc_keyword_val_comm = (r' +%s *(/ *(?P<comm>[ -~]*))?$' %
                               _rvkc_keyword_val)
 
-    _rvkc_field_specifier_val_RE = re.compile(_rvkc_field_specifier_val)
+    _rvkc_field_specifier_val_RE = re.compile(_rvkc_field_specifier_val + '$')
 
     # regular expression to extract the key and the field specifier from a
     # string that is being used to index into a card list that contains
@@ -412,6 +414,7 @@ class Card(_Verify):
         self._keyword = None
         self._value = None
         self._comment = None
+        self._rawvalue = None
         self._image = None
 
         # This attribute is set to False when creating the card from a card
@@ -479,7 +482,8 @@ class Card(_Verify):
             # should be strictly disallowed.
             keyword = keyword.rstrip()
             keyword_upper = keyword.upper()
-            if len(keyword) <= 8 and self._keywd_FSC_RE.match(keyword_upper):
+            if (len(keyword) <= KEYWORD_LENGTH and
+                self._keywd_FSC_RE.match(keyword_upper)):
                 # For keywords with length > 8 they will be HIERARCH cards,
                 # and can have arbitrary case keywords
                 if keyword_upper == 'END':
@@ -597,6 +601,12 @@ class Card(_Verify):
                                  'keyword cards')
 
     @property
+    def rawvalue(self):
+        if self._rawvalue is None and self.value:
+            self._rawvalue = self.value
+        return self._rawvalue
+
+    @property
     def comment(self):
         """Get the comment attribute from the card image if not already set."""
 
@@ -774,6 +784,8 @@ class Card(_Verify):
             if eq_idx < 0 or eq_idx > 9:
                 return False
             keyword, rest = image.split('=', 1)
+            if keyword in self._commentary_keywords:
+                return False
             match = self._rvkc_keyword_val_comm_RE.match(rest)
             if match:
                 field_specifier = match.group('keyword')
@@ -781,11 +793,14 @@ class Card(_Verify):
                                           field_specifier))
                 self._field_specifier = field_specifier
                 self._value = _int_or_float(match.group('val'))
+                self._rawvalue = match.group('rawval')
                 return True
         elif len(args) == 2:
             keyword, value = args
             if not isinstance(keyword, basestring):
                 return False
+            if keyword in self._commentary_keywords:
+                return False
             match = self._rvkc_keyword_name_RE.match(keyword)
             if match and isinstance(value, (int, float)):
                 field_specifier = match.group('field_specifier')
@@ -802,19 +817,20 @@ class Card(_Verify):
                                               field_specifier))
                     self._field_specifier = field_specifier
                     self._value = _int_or_float(match.group('val'))
+                    self._rawvalue = value
                     return True
 
     def _parse_keyword(self):
         if self._check_if_rvkc(self._image):
             return self._keyword
 
-        keyword = self._image[:8].strip()
+        keyword = self._image[:KEYWORD_LENGTH].strip()
         keyword_upper = keyword.upper()
         value_indicator = self._image.find('= ')
 
         special = self._commentary_keywords + ['CONTINUE']
 
-        if keyword_upper in special or 0 <= value_indicator <= 8:
+        if keyword_upper in special or 0 <= value_indicator <= KEYWORD_LENGTH:
             # The value indicator should appear in byte 8, but we are flexible
             # and allow this to be fixed
             if value_indicator >= 0:
@@ -829,6 +845,7 @@ class Card(_Verify):
             # This is valid HIERARCH card as described by the HIERARCH keyword
             # convention:
             # http://fits.gsfc.nasa.gov/registry/hierarch_keyword.html
+            self._hierarch = True
             return self._image.split('=', 1)[0][9:].rstrip()
         else:
             warnings.warn('The following header keyword is invalid or follows '
@@ -843,7 +860,7 @@ class Card(_Verify):
         # for commentary cards, no need to parse further
         # Likewise for invalid cards
         if self.keyword.upper() in self._commentary_keywords or self._invalid:
-            return self._image[8:].rstrip()
+            return self._image[KEYWORD_LENGTH:].rstrip()
 
         if self._check_if_rvkc(self._image):
             return self._value
@@ -951,8 +968,8 @@ class Card(_Verify):
             # The equal sign may not be any higher than column 10; anything
             # past that must be considered part of the card value
             if delim_index is None:
-                keyword = image[:8]
-                valuecomment = image[8:]
+                keyword = image[:KEYWORD_LENGTH]
+                valuecomment = image[KEYWORD_LENGTH:]
             elif delim_index > 10 and image[:9] != 'HIERARCH ':
                 keyword = image[:8]
                 valuecomment = image[8:]
@@ -1011,13 +1028,13 @@ class Card(_Verify):
     def _format_keyword(self):
         if self.keyword:
             if self.field_specifier:
-                return '%-8s' % self.keyword.split('.', 1)[0]
+                return '%-*s' % (KEYWORD_LENGTH, self.keyword.split('.', 1)[0])
             elif self._hierarch:
                 return 'HIERARCH %s ' % self.keyword
             else:
-                return '%-8s' % self.keyword
+                return '%-*s' % (KEYWORD_LENGTH, self.keyword)
         else:
-            return ' ' * 8
+            return ' ' * KEYWORD_LENGTH
 
     def _format_value(self):
         # value string
@@ -1044,7 +1061,7 @@ class Card(_Verify):
             value = _format_value(value)
 
         # For HIERARCH cards the value should be shortened to conserve space
-        if not self.field_specifier and len(self.keyword) > 8:
+        if not self.field_specifier and len(self.keyword) > KEYWORD_LENGTH:
             value = value.strip()
 
         return value
@@ -1124,7 +1141,7 @@ class Card(_Verify):
         words = _words_group(value, value_length)
         for idx, word in enumerate(words):
             if idx == 0:
-                headstr = '%-8s= ' % self.keyword
+                headstr = '%-*s= ' % (KEYWORD_LENGTH, self.keyword)
             else:
                 headstr = 'CONTINUE  '
             value = value_format % word
@@ -1147,7 +1164,7 @@ class Card(_Verify):
         same type.
         """
 
-        maxlen = Card.length - len(self.keyword) - 1
+        maxlen = Card.length - KEYWORD_LENGTH
         value = self._format_value()
         output = []
         idx = 0
diff --git a/astropy/io/fits/column.py b/astropy/io/fits/column.py
index ce66dac..fe5e522 100644
--- a/astropy/io/fits/column.py
+++ b/astropy/io/fits/column.py
@@ -988,7 +988,7 @@ def _makep(input, desp_output, format, nrows=None):
     if format.dtype == 'a':
         _nbytes = 1
     else:
-        _nbytes = np.array([], dtype=np.typeDict[format.dtype]).itemsize
+        _nbytes = np.array([], dtype=format.dtype).itemsize
 
     for idx in range(nrows):
         if idx < len(input):
diff --git a/astropy/io/fits/diff.py b/astropy/io/fits/diff.py
index 7b57f4b..e15ff96 100644
--- a/astropy/io/fits/diff.py
+++ b/astropy/io/fits/diff.py
@@ -301,7 +301,7 @@ class FITSDiff(_BaseDiff):
         if self.ignore_comments:
             ignore_comments = ' '.join(sorted(self.ignore_comments))
             self._writeln(u' Keyword(s) whose comments are not to be compared:'
-                          '\n%s' % wrapper.fill(ignore_keywords))
+                          '\n%s' % wrapper.fill(ignore_comments))
         if self.ignore_fields:
             ignore_fields = ' '.join(sorted(self.ignore_fields))
             self._writeln(u' Table column(s) not to be compared:\n%s' %
@@ -1025,6 +1025,11 @@ class TableDataDiff(_BaseDiff):
             self.diff_rows = (len(self.a), len(self.b))
             return
 
+        # If the tables contain no rows there's no data to compare, so we're
+        # done at this point. (See ticket #178)
+        if len(self.a) == len(self.b) == 0:
+            return
+
         # Like in the old fitsdiff, compare tables on a column by column basis
         # The difficulty here is that, while FITS column names are meant to be
         # case-insensitive, PyFITS still allows, for the sake of flexibility,
@@ -1119,10 +1124,10 @@ class TableDataDiff(_BaseDiff):
                                ind=self._indent + 1)
 
         if self.diff_rows:
-            self._writeln(' Table rows differ:')
-            self._writeln('  a: %s' % self.diff_rows[0])
-            self._writeln('  b: %s' % self.diff_rows[1])
-            self._writeln(' No further data comparison performed.')
+            self._writeln(u' Table rows differ:')
+            self._writeln(u'  a: %s' % self.diff_rows[0])
+            self._writeln(u'  b: %s' % self.diff_rows[1])
+            self._writeln(u' No further data comparison performed.')
             return
 
         if not self.diff_values:
@@ -1177,7 +1182,7 @@ def report_diff_values(fileobj, a, b, ind=0):
             report_diff_values(fileobj, a[idx], b[idx], ind=ind + 1)
 
         if num_diffs:
-            fileobj.write(indent('  ...and at %d more indices.\n' %
+            fileobj.write(indent(u'  ...and at %d more indices.\n' %
                           (num_diffs - 3), ind))
         return
 
@@ -1206,7 +1211,7 @@ def report_diff_keyword_attr(fileobj, attr, diffs, keyword, ind=0):
                 dup = ''
             else:
                 dup = '[%d]' % (idx + 1)
-            fileobj.write(indent(' Keyword %-8s%s has different %s:\n' %
+            fileobj.write(indent(u' Keyword %-8s%s has different %s:\n' %
                           (keyword, dup, attr), ind))
             report_diff_values(fileobj, val[0], val[1], ind=ind + 1)
 
diff --git a/astropy/io/fits/fitsrec.py b/astropy/io/fits/fitsrec.py
index 2fdeafa..4483a4b 100644
--- a/astropy/io/fits/fitsrec.py
+++ b/astropy/io/fits/fitsrec.py
@@ -178,6 +178,7 @@ class FITS_rec(np.recarray):
         self._nfields = len(self.dtype.names)
         self._convert = [None] * len(self.dtype.names)
         self._heapoffset = 0
+        self._heapsize = 0
         self._file = None
         self._buffer = None
         self._coldefs = None
@@ -193,6 +194,7 @@ class FITS_rec(np.recarray):
         if isinstance(obj, FITS_rec):
             self._convert = obj._convert
             self._heapoffset = obj._heapoffset
+            self._heapsize = obj._heapsize
             self._file = obj._file
             self._buffer = obj._buffer
             self._coldefs = obj._coldefs
@@ -207,6 +209,7 @@ class FITS_rec(np.recarray):
             self._convert = [None] * len(obj.dtype.names)
 
             self._heapoffset = getattr(obj, '_heapoffset', 0)
+            self._heapsize = getattr(obj, '_heapsize', 0)
             self._file = getattr(obj, '_file', None)
             self._buffer = getattr(obj, '_buffer', None)
 
@@ -362,6 +365,7 @@ class FITS_rec(np.recarray):
                 self._get_scale_factors(indx)
 
             # for P format
+            buff = None
             if isinstance(recformat, _FormatP):
                 dummy = _VLF([None] * len(self), dtype=recformat.dtype)
                 for i in range(len(self)):
@@ -373,10 +377,24 @@ class FITS_rec(np.recarray):
                             return _array_from_file(self._file, dtype=dtype,
                                                     count=count, sep='')
                     else:  # There must be a _buffer or something is wrong
-                        buff = self._buffer[_offset:]
+                        # Sometimes the buffer is already a Numpy array; in
+                        # particular this can occur in compressed HDUs.
+                        # Hypothetically other cases as well.
+                        if buff is None:
+                            buff = self._buffer
+                        if not isinstance(buff, np.ndarray):
+                            # Go ahead and great a single ndarray from the
+                            # buffer if it is not already one; we will then
+                            # take slices from it.  This is more efficient than
+                            # the previous approach that created separate
+                            # arrays for each VLA.
+                            buff = np.fromstring(buff, dtype=np.uint8)
+
                         def get_pdata(dtype, count):
-                            return np.fromstring(buff, dtype=dtype,
-                                                 count=count, sep='')
+                            dtype = np.dtype(dtype)
+                            nbytes = count * dtype.itemsize
+                            slc = slice(_offset, _offset + nbytes)
+                            return buff[slc].view(dtype=dtype)
 
                     if recformat.dtype == 'a':
                         count = field[i, 0]
@@ -546,7 +564,6 @@ class FITS_rec(np.recarray):
                 widths.append(f[1])
             loc.append(loc[-1] + super(FITS_rec, self).field(idx).itemsize)
 
-        self._heapsize = 0
         for indx in range(len(self.dtype.names)):
             recformat = self._coldefs._recformats[indx]
             field = super(FITS_rec, self).field(indx)
@@ -564,10 +581,20 @@ class FITS_rec(np.recarray):
             # add the location offset of the heap area for each
             # variable length column
             if isinstance(recformat, _FormatP):
+                # Reset the heapsize and recompute it starting from the first P
+                # column
+                if indx == 0:
+                    self._heapsize = 0
+
                 field[:] = 0  # reset
                 npts = map(len, self._convert[indx])
+
+                # Irritatingly, this can return a different dtype than just
+                # doing np.dtype(recformat.dtype); but this returns the results
+                # that we want.  For example if recformat.dtype is 'a' we want
+                # an array of characters.
+                dtype = np.array([], dtype=recformat.dtype).dtype
                 field[:len(npts), 0] = npts
-                dtype = np.array([], dtype=recformat.dtype)
                 field[1:, 1] = (np.add.accumulate(field[:-1, 0]) *
                                 dtype.itemsize)
                 field[:, 1][:] += self._heapsize
diff --git a/astropy/io/fits/hdu/base.py b/astropy/io/fits/hdu/base.py
index 938730b..f3b3132 100644
--- a/astropy/io/fits/hdu/base.py
+++ b/astropy/io/fits/hdu/base.py
@@ -17,7 +17,7 @@ from ..file import _File
 from ..header import Header, HEADER_END_RE, BLOCK_SIZE, _pad_length
 from ..util import (_is_int, _is_pseudo_unsigned, _unsigned_zero,
                     itersubclasses, encode_ascii, decode_ascii,
-                    _get_array_memmap)
+                    _get_array_mmap)
 from ..verify import _Verify, _ErrList
 
 from ....utils import lazyproperty
@@ -113,7 +113,7 @@ class _BaseHDU(object):
             elif 'CHECKSUM' in self._header:
                 self._output_checksum = True
 
-        self.name = ''
+        self._name = ''
 
     @property
     def header(self):
@@ -124,13 +124,23 @@ class _BaseHDU(object):
         self._header = value
 
     @property
+    def name(self):
+        return self._name
+
+    @name.setter
+    def name(self, value):
+        if not isinstance(value, basestring):
+            raise TypeError("'name' attribute must be a string")
+        self._name = value
+
+    @property
     def is_image(self):
         return (
             self.name == 'PRIMARY' or
-            ('XTENSION' in self.header and
-             (self.header['XTENSION'] == 'IMAGE' or
-              (self.header['XTENSION'] == 'BINTABLE' and
-               'ZIMAGE' in self.header and self.header['ZIMAGE'] == True))))
+            ('XTENSION' in self._header and
+             (self._header['XTENSION'] == 'IMAGE' or
+              (self._header['XTENSION'] == 'BINTABLE' and
+               'ZIMAGE' in self._header and self._header['ZIMAGE'] == True))))
 
     @property
     def _data_loaded(self):
@@ -493,7 +503,7 @@ class _BaseHDU(object):
         datloc = self._datLoc
         datsize = self._datSpan
 
-        if self.header._modified:
+        if self._header._modified:
             # Seek to the original header location in the file
             self._file.seek(hdrloc)
             # This should update hdrloc with he header location in the new file
@@ -522,12 +532,12 @@ class _BaseHDU(object):
                     # Of course, if we're copying the data to a new file we
                     # don't care about flushing the original mmap; instead just
                     # read it into the new file
-                    memmap_array = None
+                    array_mmap = None
                 else:
-                    memmap_array = _get_array_memmap(self.data)
+                    array_mmap = _get_array_mmap(self.data)
 
-                if memmap_array is not None:
-                    memmap_array.flush()
+                if array_mmap is not None:
+                    array_mmap.flush()
                 else:
                     self._file.seek(self._datLoc)
                     datloc, datsize = self._writedata(fileobj)
@@ -689,6 +699,34 @@ class _ValidHDU(_BaseHDU, _Verify):
     Base class for all HDUs which are not corrupted.
     """
 
+    def __init__(self, data=None, header=None, name=None, **kwargs):
+        super(_ValidHDU, self).__init__(data=data, header=header)
+        if name is not None:
+            self.name = name
+
+        if header and not hasattr(self, '_extver'):
+            self._extver = header.get('EXTVER', 1)
+
+    @property
+    def name(self):
+        # Convert the value to a string to be flexible in some pathological
+        # cases (see ticket #96)
+        if self._header and 'EXTNAME' in self._header:
+            self._name = str(self._header['EXTNAME'])
+        return self._name
+
+    @name.setter
+    def name(self, value):
+        if not isinstance(value, basestring):
+            raise TypeError("'name' attribute must be a string")
+        if not EXTENSION_NAME_CASE_SENSITIVE():
+            value = value.upper()
+        if self._header:
+            if 'EXTNAME' in self._header:
+                self._header['EXTNAME'] = value
+            else:
+                self._header.append(('EXTNAME', value, 'extension name'))
+
     @classmethod
     def match_header(cls, header):
         """
@@ -832,7 +870,7 @@ class _ValidHDU(_BaseHDU, _Verify):
         if 'extname' in self._header and savecomment:
             comment = None
 
-        self._header.set('extname', value, comment, before, after)
+        self._header.set('EXTNAME', value, comment, before, after)
         self.name = value
 
     def update_ext_version(self, value, comment=None, before=None,
@@ -924,6 +962,19 @@ class _ValidHDU(_BaseHDU, _Verify):
                             self.run_option(option=option, err_text=err_text,
                                             fix=fix, fix_text="Deleted."))
 
+
+        # Verify that the EXTNAME keyword exists and is a string
+        if 'EXTNAME' in self._header:
+            if not isinstance(self._header['EXTNAME'], basestring):
+                err_text = 'The EXTNAME keyword must have a string value.'
+                fix_text = 'Converted the EXTNAME keyword to a string value.'
+
+                def fix(header=self._header):
+                    header['EXTNAME'] = str(header['EXTNAME'])
+
+                errs.append(self.run_option(option, err_text=err_text,
+                                            fix_text=fix_text, fix=fix))
+
         # verify each card
         for card in self._header.cards:
             errs.append(card._verify(option))
@@ -1402,38 +1453,6 @@ class ExtensionHDU(_ValidHDU):
 
     _extension = ''
 
-    def __init__(self, data=None, header=None, name=None, **kwargs):
-        super(ExtensionHDU, self).__init__(data=data, header=header)
-        if header:
-            if name is None:
-                if not self.name and 'EXTNAME' in header:
-                    self.name = header['EXTNAME']
-            else:
-                self.name = name
-
-            if not hasattr(self, '_extver'):
-                if 'EXTVER' in header:
-                    self._extver = header['EXTVER']
-                else:
-                    self._extver = 1
-
-    def __setattr__(self, attr, value):
-        """
-        Set an HDU attribute.
-        """
-
-        if attr == 'name' and value:
-            if not isinstance(value, basestring):
-                raise TypeError("'name' attribute must be a string")
-            if not EXTENSION_NAME_CASE_SENSITIVE():
-                value = value.upper()
-            if 'EXTNAME' in self._header:
-                self._header['EXTNAME'] = value
-            else:
-                self._header.append(('EXTNAME', value, 'extension name'))
-
-        super(ExtensionHDU, self).__setattr__(attr, value)
-
     @classmethod
     def match_header(cls, header):
         """
@@ -1469,6 +1488,7 @@ class ExtensionHDU(_ValidHDU):
                        0, option, errs)
         self.req_cards('GCOUNT', naxis + 4, lambda v: (_is_int(v) and v == 1),
                        1, option, errs)
+
         return errs
 # For backwards compatilibity, though this needs to be deprecated
 # TODO: Mark this as deprecated
diff --git a/astropy/io/fits/hdu/compressed.py b/astropy/io/fits/hdu/compressed.py
index a9310fb..dede32f 100644
--- a/astropy/io/fits/hdu/compressed.py
+++ b/astropy/io/fits/hdu/compressed.py
@@ -1,8 +1,11 @@
 # Licensed under a 3-clause BSD style license - see PYFITS.rst
 
+import operator
 import sys
 import warnings
 
+from functools import reduce
+
 import numpy as np
 
 from .base import DELAYED, ExtensionHDU
@@ -10,7 +13,8 @@ from .image import _ImageBaseHDU, ImageHDU
 from .table import BinTableHDU
 from ..column import Column, ColDefs, _FormatP, _makep
 from ..fitsrec import FITS_rec
-from ..header import Header
+from ..header import Header, BLOCK_SIZE, _pad_length
+from ..util import _is_pseudo_unsigned, _unsigned_zero
 
 from ....utils import lazyproperty
 
@@ -30,6 +34,10 @@ DEFAULT_HCOMP_SMOOTH = 0
 DEFAULT_BLOCK_SIZE = 32
 DEFAULT_BYTE_PIX = 4
 
+# CFITSIO version-specific features
+if COMPRESSION_SUPPORTED:
+    CFITSIO_SUPPORTS_GZIPDATA = compression.CFITSIO_VERSION >= 3.28
+
 
 class CompImageHeader(Header):
     """
@@ -56,8 +64,9 @@ class CompImageHeader(Header):
         # update the underlying header (_table_header) unless the update
         # was made to a card that describes the data.
 
-        if (keyword not in ('XTENSION', 'BITPIX', 'PCOUNT', 'GCOUNT',
-                            'TFIELDS', 'ZIMAGE', 'ZBITPIX', 'ZCMPTYPE') and
+        if (keyword not in ('SIMPLE', 'XTENSION', 'BITPIX', 'PCOUNT', 'GCOUNT',
+                            'TFIELDS', 'EXTEND', 'ZIMAGE', 'ZBITPIX',
+                            'ZCMPTYPE') and
             keyword[:4] not in ('ZVAL') and
             keyword[:5] not in ('NAXIS', 'TTYPE', 'TFORM', 'ZTILE', 'ZNAME')
             and keyword[:6] not in ('ZNAXIS')):
@@ -86,7 +95,9 @@ class CompImageHDU(BinTableHDU):
                  tileSize=None,
                  hcompScale=DEFAULT_HCOMP_SCALE,
                  hcompSmooth=DEFAULT_HCOMP_SMOOTH,
-                 quantizeLevel=DEFAULT_QUANTIZE_LEVEL):
+                 quantizeLevel=DEFAULT_QUANTIZE_LEVEL,
+                 do_not_scale_image_data=False,
+                 uint=False, scale_back=False, **kwargs):
         """
         Parameters
         ----------
@@ -266,11 +277,28 @@ class CompImageHDU(BinTableHDU):
             self.updateHeaderData(header, name, compressionType, tileSize,
                                   hcompScale, hcompSmooth, quantizeLevel)
 
+        # TODO: A lot of this should be passed on to an internal image HDU o
+        # something like that, see ticket #88
+        self._do_not_scale_image_data = do_not_scale_image_data
+        self._uint = uint
+        self._scale_back = scale_back
+
+        self._axes = [self._header.get('ZNAXIS' + str(axis + 1), 0)
+                      for axis in xrange(self._header.get('ZNAXIS', 0))]
+
         # store any scale factors from the table header
-        self._bzero = self._header.get('BZERO', 0)
-        self._bscale = self._header.get('BSCALE', 1)
+        if do_not_scale_image_data:
+            self._bzero = 0
+            self._bscale = 1
+        else:
+            self._bzero = self._header.get('BZERO', 0)
+            self._bscale = self._header.get('BSCALE', 1)
         self._bitpix = self._header['ZBITPIX']
 
+        self._orig_bzero = self._bzero
+        self._orig_bscale = self._bscale
+        self._orig_bitpix = self._bitpix
+
     @classmethod
     def match_header(cls, header):
         card = header.cards[0]
@@ -352,10 +380,10 @@ class CompImageHDU(BinTableHDU):
 
         image_hdu = ImageHDU(data=self.data, header=self._header)
         self._image_header = CompImageHeader(self._header, image_hdu.header)
+        self._axes = image_hdu._axes
         del image_hdu
 
         # Update the extension name in the table header
-
         if not name and not 'EXTNAME' in self._header:
             name = 'COMPRESSED_IMAGE'
 
@@ -432,20 +460,35 @@ class CompImageHDU(BinTableHDU):
             # 'UNCOMPRESSED_DATA', 'ZSCALE', and 'ZZERO' columns.
             ncols = 4
 
-            # Set up the second column for the table that will hold
-            # any uncompressable data.
-            self._header.set('TTYPE2', 'UNCOMPRESSED_DATA',
-                             'label for field 2', after='TFORM1')
-
-            if self._image_header['BITPIX'] == -32:
-                tform2 = '1PE'
+            # CFITSIO 3.28 and up automatically use the GZIP_COMPRESSED_DATA
+            # store floating point data that couldn't be quantized, instead
+            # of the UNCOMPRESSED_DATA column.  There's no way to control
+            # this behavior so the only way to determine which behavior will
+            # be employed is via the CFITSIO version
+
+            if CFITSIO_SUPPORTS_GZIPDATA:
+                ttype2 = 'GZIP_COMPRESSED_DATA'
+                # The required format for the GZIP_COMPRESSED_DATA is actually
+                # missing from the standard docs, but CFITSIO suggests it
+                # should be 1PB, which is logical.
+                tform2 = '1PB'
             else:
-                tform2 = '1PD'
+                ttype2 = 'UNCOMPRESSED_DATA'
+                if self._image_header['BITPIX'] == -32:
+                    tform2 = '1PE'
+                else:
+                    tform2 = '1PD'
+
+            # Set up the second column for the table that will hold any
+            # uncompressable data.
+            self._header.set('TTYPE2', ttype2, 'label for field 2',
+                             after='TFORM1')
 
             self._header.set('TFORM2', tform2,
                              'data format of field: variable length array',
                              after='TTYPE2')
-            col2 = Column(name=self._header['TTYPE2'], format=tform2)
+
+            col2 = Column(name=ttype2, format=tform2)
 
             # Set up the third column for the table that will hold
             # the scale values for quantized data.
@@ -517,9 +560,11 @@ class CompImageHDU(BinTableHDU):
         # Verify that any input tile size parameter is the appropriate
         # size to match the HDU's data.
 
+        naxis = self._image_header['NAXIS']
+
         if not tileSize:
             tileSize = []
-        elif len(tileSize) != self._image_header['NAXIS']:
+        elif len(tileSize) != naxis:
             warnings.warn('Provided tile size not appropriate for the data.  '
                           'Default tile size will be used.')
             tileSize = []
@@ -527,24 +572,28 @@ class CompImageHDU(BinTableHDU):
         # Set default tile dimensions for HCOMPRESS_1
 
         if compressionType == 'HCOMPRESS_1':
-            if self._image_header['NAXIS'] != 2:
-                raise ValueError('Hcompress can only be used with '
-                                 '2-dimensional images.')
-            elif self._image_header['NAXIS1'] < 4 or \
-            self._image_header['NAXIS2'] < 4:
+            if (self._image_header['NAXIS1'] < 4 or
+                self._image_header['NAXIS2'] < 4):
                 raise ValueError('Hcompress minimum image dimension is '
                                  '4 pixels')
-            elif tileSize and (tileSize[0] < 4 or tileSize[1] < 4):
-                # user specified tile size is too small
-                raise ValueError('Hcompress minimum tile dimension is '
-                                 '4 pixels')
+            elif tileSize:
+                if tileSize[0] < 4 or tileSize[1] < 4:
+                    # user specified tile size is too small
+                    raise ValueError('Hcompress minimum tile dimension is '
+                                     '4 pixels')
+                major_dims = len(filter(lambda x: x > 1, tileSize))
+                if major_dims > 2:
+                    raise ValueError(
+                        'HCOMPRESS can only support 2-dimensional tile sizes.'
+                        'All but two of the tileSize dimensions must be set '
+                        'to 1.')
 
             if tileSize and (tileSize[0] == 0 and tileSize[1] == 0):
                 #compress the whole image as a single tile
                 tileSize[0] = self._image_header['NAXIS1']
                 tileSize[1] = self._image_header['NAXIS2']
 
-                for i in range(2, self._image_header['NAXIS']):
+                for i in range(2, naxis):
                     # set all higher tile dimensions = 1
                     tileSize[i] = 1
             elif not tileSize:
@@ -574,6 +623,11 @@ class CompImageHDU(BinTableHDU):
                             break
                     else:
                         tileSize.append(17)
+
+                for i in range(2, naxis):
+                    # set all higher tile dimensions = 1
+                    tileSize.append(1)
+
             # check if requested tile size causes the last tile to have
             # less than 4 pixels
 
@@ -611,30 +665,31 @@ class CompImageHDU(BinTableHDU):
         # write the ZNAXISn and ZTILEn cards to the table header.
         nrows = 1
 
-        for idx in range(0, self._image_header['NAXIS']):
+        for idx, axis in enumerate(self._axes):
             naxis = 'NAXIS' + str(idx + 1)
             znaxis = 'ZNAXIS' + str(idx + 1)
             ztile = 'ZTILE' + str(idx + 1)
 
-            if tileSize:
+            if tileSize and len(tileSize) >= idx + 1:
                 ts = tileSize[idx]
-            elif not ztile in self._header:
-                # Default tile size
-                if not idx:
-                    ts = self._image_header['NAXIS1']
-                else:
-                    ts = 1
             else:
-                ts = self._header[ztile]
+                if not ztile in self._header:
+                    # Default tile size
+                    if not idx:
+                        ts = self._image_header['NAXIS1']
+                    else:
+                        ts = 1
+                else:
+                    ts = self._header[ztile]
+                tileSize.append(ts)
 
-            naxisn = self._image_header[naxis]
-            nrows = nrows * ((naxisn - 1) // ts + 1)
+            nrows = nrows * ((axis - 1) // ts + 1)
 
             if image_header and naxis in image_header:
-                self._header.set(znaxis, naxisn, image_header.comments[naxis],
+                self._header.set(znaxis, axis, image_header.comments[naxis],
                                  after=last_znaxis)
             else:
-                self._header.set(znaxis, naxisn,
+                self._header.set(znaxis, axis,
                                  'length of original image axis',
                                  after=last_znaxis)
 
@@ -647,27 +702,7 @@ class CompImageHDU(BinTableHDU):
         # rows in the table.
         self._header.set('NAXIS2', nrows, 'number of rows in table')
 
-        # Create the record array to be used for the table data.
         self.columns = cols
-        compData = np.rec.array(None, formats=','.join(cols._recformats),
-                                names=cols.names, shape=nrows)
-        self.compData = compData.view(FITS_rec)
-        self.compData._coldefs = self.columns
-        self.compData.formats = self.columns.formats
-
-        # Set up and initialize the variable length columns.  There will
-        # either be one (COMPRESSED_DATA) or two (COMPRESSED_DATA,
-        # UNCOMPRESSED_DATA) depending on whether we have floating point
-        # data or not.  Note: the ZSCALE and ZZERO columns are fixed
-        # length columns.
-        for idx in range(min(2, len(cols))):
-            self.columns._arrays[idx] = \
-                np.rec.recarray.field(self.compData, idx)
-            np.rec.recarray.field(self.compData, idx)[0:] = 0
-            self.compData._convert[idx] = \
-                _makep(self.columns._arrays[idx],
-                       np.rec.recarray.field(self.compData, idx),
-                       self.columns._recformats[idx])
 
         # Set the compression parameters in the table header.
 
@@ -739,7 +774,8 @@ class CompImageHDU(BinTableHDU):
                 bytepix = DEFAULT_BYTE_PIX
 
             self._header.set('ZVAL2', bytepix,
-                             'bytes per pixel (1, 2, 4, or 8)', after='ZNAME2')
+                             'bytes per pixel (1, 2, 4, or 8)',
+                             after='ZNAME2')
             afterCard = 'ZVAL2'
             idx = 3
         elif compressionType == 'HCOMPRESS_1':
@@ -864,250 +900,72 @@ class CompImageHDU(BinTableHDU):
     @lazyproperty
     def data(self):
         # The data attribute is the image data (not the table data).
+        data = compression.decompress_hdu(self)
 
-        # First we will get the table data (the compressed
-        # data) from the file, if there is any.
-        self.compData = super(BinTableHDU, self).data
-
-        # Now that we have the compressed data, we need to uncompress
-        # it into the image data.
-        dataList = []
-        naxesList = []
-        tileSizeList = []
-        zvalList = []
-        uncompressedDataList = []
-
-        # Set up an array holding the integer value that represents
-        # undefined pixels.  This could come from the ZBLANK column
-        # from the table, or from the ZBLANK header card (if no
-        # ZBLANK column (all null values are the same for each tile)),
-        # or from the BLANK header card.
-        if not 'ZBLANK' in self.compData.names:
-            if 'ZBLANK' in self._header:
-                nullDvals = np.array(self._header['ZBLANK'],
-                                     dtype='int32')
-                cn_zblank = -1  # null value is a constant
-            elif 'BLANK' in self._header:
-                nullDvals = np.array(self._header['BLANK'],
-                                     dtype='int32')
-                cn_zblank = -1  # null value is a constant
-            else:
-                cn_zblank = 0  # no null value given so don't check
-                nullDvals = np.array(0, dtype='int32')
-        else:
-            cn_zblank = 1  # null value supplied as a column
-            nullDvals = self.compData.field('ZBLANK')
-
-        # Set up an array holding the linear scale factor values
-        # This could come from the ZSCALE column from the table, or
-        # from the ZSCALE header card (if no ZSCALE column (all
-        # linear scale factor values are the same for each tile)).
-
-        if 'BSCALE' in self._header:
-            self._bscale = self._header['BSCALE']
-            del self._header['BSCALE']
-        else:
-            self._bscale = 1.
-
-        if not 'ZSCALE' in self.compData.names:
-            if 'ZSCALE' in self._header:
-                zScaleVals = np.array(self._header['ZSCALE'],
-                                      dtype='float64')
-                cn_zscale = -1  # scale value is a constant
-            else:
-                cn_zscale = 0  # no scale factor given so don't scale
-                zScaleVals = np.array(1.0, dtype='float64')
-        else:
-            cn_zscale = 1  # scale value supplied as a column
-            zScaleVals = self.compData.field('ZSCALE')
-
-        # Set up an array holding the zero point offset values
-        # This could come from the ZZERO column from the table, or
-        # from the ZZERO header card (if no ZZERO column (all
-        # zero point offset values are the same for each tile)).
-
-        if 'BZERO' in self._header:
-            self._bzero = self._header['BZERO']
-            del self._header['BZERO']
-        else:
-            self._bzero = 0.
-
-        if not 'ZZERO' in self.compData.names:
-            if 'ZZERO' in self._header:
-                zZeroVals = np.array(self._header['ZZERO'],
-                                     dtype='float64')
-                cn_zzero = -1  # zero value is a constant
-            else:
-                cn_zzero = 0  # no zero value given so don't scale
-                zZeroVals = np.array(1.0, dtype='float64')
-        else:
-            cn_zzero = 1  # zero value supplied as a column
-            zZeroVals = self.compData.field('ZZERO')
-
-        # Is uncompressed data supplied in a column?
-        if not 'UNCOMPRESSED_DATA' in self.compData.names:
-            cn_uncompressed = 0  # no uncompressed data supplied
-        else:
-            cn_uncompressed = 1  # uncompressed data supplied as column
-
-        # Take the compressed data out of the array and put it into
-        # a list as character bytes to pass to the decompression
-        # routine.
-        # TODO: I wonder if maybe a lot of this couldn't be done in C by
-        # running directly over the array data and not copying it like this
-        for row in self.compData:
-            dataList.append(row.field('COMPRESSED_DATA').tostring())
-
-            # If we have a column with uncompressed data then create
-            # a list of lists of the data in the coulum.  Each
-            # underlying list contains the uncompressed data for a
-            # pixel in the tile.  There are one of these lists for
-            # each tile in the image.
-            if 'UNCOMPRESSED_DATA' in self.compData.names:
-                tileUncDataList = []
-
-                for byte in row.field('UNCOMPRESSED_DATA'):
-                    tileUncDataList.append(byte)
-
-                uncompressedDataList.append(tileUncDataList)
-
-        # Calculate the total number of elements (pixels) in the
-        # resulting image data array.  Create a list of the number
-        # of pixels along each axis in the image and a list of the
-        # number of pixels along each axis in the compressed tile.
-        nelem = 1
-
-        for idx in range(self._header['ZNAXIS']):
-            naxesList.append(self._header['ZNAXIS' + str(idx + 1)])
-            tileSizeList.append(self._header['ZTILE' + str(idx + 1)])
-            nelem = nelem * self._header['ZNAXIS' + str(idx + 1)]
-
-        # Create a list for the compression parameters.  The contents
-        # of the list is dependent on the compression type.
-
-        if self._header['ZCMPTYPE'] == 'RICE_1':
-            idx = 1
-            blockSize = DEFAULT_BLOCK_SIZE
-            bytePix = DEFAULT_BYTE_PIX
-
-            while True:
-                zname = 'ZNAME' + str(idx)
-                if zname not in self._header:
-                    break
-                zval = 'ZVAL' + str(idx)
-                if self._header[zname] == 'BLOCKSIZE':
-                    blockSize = self._header[zval]
-                if self._header[zname] == 'BYTEPIX':
-                    bytePix = self._header[zval]
-                idx += 1
-
-            zvalList.append(blockSize)
-            zvalList.append(bytePix)
-        elif self._header['ZCMPTYPE'] == 'HCOMPRESS_1':
-            idx = 1
-            hcompSmooth = DEFAULT_HCOMP_SMOOTH
-
-            while True:
-                zname = 'ZNAME' + str(idx)
-                if zname not in self._header:
-                    break
-                zval = 'ZVAL' + str(idx)
-                if self._header[zname] == 'SMOOTH':
-                    hcompSmooth = self._header[zval]
-                idx += 1
-
-            zvalList.append(hcompSmooth)
-
-        # Treat the NOISEBIT and SCALE parameters separately because
-        # they are floats instead of integers
-
-        quantizeLevel = DEFAULT_QUANTIZE_LEVEL
-
-        if self._header['ZBITPIX'] < 0:
-            idx = 1
-
-            while True:
-                zname = 'ZNAME' + str(idx)
-                if zname not in self._header:
-                    break
-                zval = 'ZVAL' + str(idx)
-                if self._header[zname] == 'NOISEBIT':
-                    quantizeLevel = self._header[zval]
-                idx += 1
-
-        hcompScale = DEFAULT_HCOMP_SCALE
-
-        if self._header['ZCMPTYPE'] == 'HCOMPRESS_1':
-            idx = 1
-
-            while True:
-                zname = 'ZNAME' + str(idx)
-                if zname not in self._header:
-                    break
-                zval = 'ZVAL' + str(idx)
-                if self._header[zname] == 'SCALE':
-                    hcompScale = self._header[zval]
-                idx += 1
+        # Scale the data if necessary
+        if (self._orig_bzero != 0 or self._orig_bscale != 1):
+            new_dtype = self._dtype_for_bitpix()
+            data = np.array(data, dtype=new_dtype)
 
-        # Create an array to hold the decompressed data.
-        naxesList.reverse()
-        data = np.empty(shape=naxesList,
-                   dtype=_ImageBaseHDU.NumCode[self._header['ZBITPIX']])
-        naxesList.reverse()
-
-        # Call the C decompression routine to decompress the data.
-        # Note that any errors in this routine will raise an
-        # exception.
-        status = compression.decompressData(dataList,
-                                            self._header['ZNAXIS'],
-                                            naxesList, tileSizeList,
-                                            zScaleVals, cn_zscale,
-                                            zZeroVals, cn_zzero,
-                                            nullDvals, cn_zblank,
-                                            uncompressedDataList,
-                                            cn_uncompressed,
-                                            quantizeLevel,
-                                            hcompScale,
-                                            zvalList,
-                                            self._header['ZCMPTYPE'],
-                                            self._header['ZBITPIX'], 1,
-                                            nelem, 0.0, data)
+            zblank = None
 
-        # Scale the data if necessary
-        if (self._bzero != 0 or self._bscale != 1):
-            if self.header['BITPIX'] == -32:
-                data = np.array(data, dtype=np.float32)
+            if 'ZBLANK' in self.compData.columns.names:
+                zblank = self.compData['ZBLANK']
             else:
-                data = np.array(data, dtype=np.float64)
+                if 'ZBLANK' in self._header:
+                    zblank = np.array(self._header['ZBLANK'], dtype='int32')
+                elif 'BLANK' in self._header:
+                    zblank = np.array(self._header['BLANK'], dtype='int32')
 
-            if cn_zblank:
-                blanks = (data == nullDvals)
+            if zblank is not None:
+                blanks = (data == zblank)
 
             if self._bscale != 1:
                 np.multiply(data, self._bscale, data)
             if self._bzero != 0:
                 data += self._bzero
 
-            if cn_zblank:
+            if zblank is not None:
                 data = np.where(blanks, np.nan, data)
+
+        # Right out of _ImageBaseHDU.data
+        self._update_header_scale_info(data.dtype)
+
         return data
 
     @data.setter
-    def data(self, value):
-        if (value is not None) and (not isinstance(value, np.ndarray) or
-             value.dtype.fields is not None):
+    def data(self, data):
+        if (data is not None) and (not isinstance(data, np.ndarray) or
+             data.dtype.fields is not None):
                 raise TypeError('CompImageHDU data has incorrect type:%s; '
                                 'dtype.fields = %s' %
-                                (type(value), value.dtype.fields))
+                                (type(data), data.dtype.fields))
 
     @lazyproperty
     def compData(self):
-        # In order to create the compressed data we will reference the
-        # image data.  Referencing the image data will cause the
-        # compressed data to be read from the file.
-        data = self.data
+        # First we will get the table data (the compressed
+        # data) from the file, if there is any.
+        compData = super(BinTableHDU, self).data
+        if isinstance(compData, np.rec.recarray):
+            del self.data
+            return compData
+        else:
+            # This will actually set self.compData with the pre-allocated space
+            # for the compression data; this is something I might do away with
+            # in the future
+            self.updateCompressedData()
+
         return self.compData
 
+    @property
+    def shape(self):
+        """
+        Shape of the image array--should be equivalent to ``self.data.shape``.
+        """
+
+        # Determine from the values read from the header
+        return tuple(reversed(self._axes))
+
     @lazyproperty
     def header(self):
         # The header attribute is the header for the image data.  It
@@ -1127,7 +985,7 @@ class CompImageHDU(BinTableHDU):
         # Delete cards that are related to the table.  And move
         # the values of those cards that relate to the image from
         # their corresponding table cards.  These include
-        # ZBITPIX -> BITPIX, ZNAXIS -> NAXIS, and ZNAXISn -> NAXISn.
+        # nnnZBITPIX -> BITPIX, ZNAXIS -> NAXIS, and ZNAXISn -> NAXISn.
         try:
             del self._image_header['ZIMAGE']
         except KeyError:
@@ -1141,14 +999,8 @@ class CompImageHDU(BinTableHDU):
         try:
             del self._image_header['ZBITPIX']
             _bitpix = self._header['ZBITPIX']
-            self._image_header['BITPIX'] = (self._header['ZBITPIX'],
+            self._image_header['BITPIX'] = (_bitpix,
                                             self._header.comments['ZBITPIX'])
-
-            if (self._bzero != 0 or self._bscale != 1):
-                if _bitpix > 16:  # scale integers to Float64
-                    self._image_header['BITPIX'] = -64
-                elif _bitpix > 0:  # scale integers to Float32
-                    self._image_header['BITPIX'] = -32
         except KeyError:
             pass
 
@@ -1201,6 +1053,24 @@ class CompImageHDU(BinTableHDU):
             except KeyError:
                 pass
 
+        # Add the appropriate BSCALE and BZERO keywords if the data is scaled;
+        # though these will be removed again as soon as the data is read
+        # (unless do_not_scale_image_data=True)
+        if 'GCOUNT' in self._image_header:
+            after = 'GCOUNT'
+        else:
+            after = None
+        if 'BSCALE' in self._header:
+            self._image_header.set('BSCALE', self._header['BSCALE'],
+                                   self._header.comments['BSCALE'],
+                                   after=after)
+            after = 'BSCALE'
+
+        if 'BZERO' in self._header:
+            self._image_header.set('BZERO', self._header['BZERO'],
+                                   self._header.comments['BZERO'],
+                                   after=after)
+
         try:
             del self._image_header['ZEXTEND']
             self._image_header.set('EXTEND', self._header['ZEXTEND'],
@@ -1238,18 +1108,6 @@ class CompImageHDU(BinTableHDU):
             except KeyError:
                 break
 
-        # delete the keywords BSCALE and BZERO
-
-        try:
-            del self._image_header['BSCALE']
-        except KeyError:
-            pass
-
-        try:
-            del self._image_header['BZERO']
-        except KeyError:
-            pass
-
         # Move the ZHECKSUM and ZDATASUM cards to the image header
         # as CHECKSUM and DATASUM
         try:
@@ -1341,204 +1199,119 @@ class CompImageHDU(BinTableHDU):
         Compress the image data so that it may be written to a file.
         """
 
-        naxesList = []
-        tileSizeList = []
-        zvalList = []
+        tilesizes = []
 
         # Check to see that the image_header matches the image data
-        if self._header.get('NAXIS', 0) != len(self.data.shape) or \
-           self._header.get('BITPIX', 0) != \
-           _ImageBaseHDU.ImgCode[self.data.dtype.name]:
+        image_bitpix = _ImageBaseHDU.ImgCode[self.data.dtype.name]
+
+        if (self.header.get('NAXIS', 0) != len(self.data.shape) or
+            self.header.get('BITPIX', 0) != image_bitpix or
+            self._header.get('ZNAXIS', 0) != len(self.data.shape) or
+            self._header.get('ZBITPIX', 0) != image_bitpix or
+            self.shape != self.data.shape):
             self.updateHeaderData(self.header)
 
         # Create lists to hold the number of pixels along each axis of
         # the image data and the number of pixels in each tile of the
         # compressed image.
         for idx in range(self._header['ZNAXIS']):
-            naxesList.append(self._header['ZNAXIS' + str(idx + 1)])
-            tileSizeList.append(self._header['ZTILE' + str(idx + 1)])
-
-        # Indicate if the linear scale factor is from a column, a single
-        # scale value, or not given.
-        if 'ZSCALE' in self.compData.names:
-            cn_zscale = 1  # there is a scaled column
-        elif 'ZSCALE' in self._header:
-            cn_zscale = -1  # scale value is a constant
-        else:
-            cn_zscale = 0  # no scale value given so don't scale
-
-        # Indicate if the zero point offset value is from a column, a
-        # single value, or not given.
-        if 'ZZERO' in self.compData.names:
-            cn_zzero = 1  # there is a scaled column
-        elif 'ZZERO' in self._header:
-            cn_zzero = -1  # zero value is a constant
-        else:
-            cn_zzero = 0  # no zero value given so don't scale
+            tilesizes.append(self._header['ZTILE' + str(idx + 1)])
 
-        # Indicate if there is a UNCOMPRESSED_DATA column in the
-        # compressed data table.
-        if 'UNCOMPRESSED_DATA' in self.compData.names:
-            cn_uncompressed = 1  # there is a uncompressed data column
+        # put data in machine native byteorder on little endian machines
+        # for handing off to the compression code
+        if sys.byteorder == 'little':
+            swap_types = ('>',)
         else:
-            cn_uncompressed = 0  # there is no uncompressed data column
-
-        # Create a list for the compression parameters.  The contents
-        # of the list is dependent on the compression type.
+            swap_types = ('>', '=')
+
+        # TODO: This is copied right out of _ImageBaseHDU._writedata_internal;
+        # it would be cool if we could use an internal ImageHDU and use that to
+        # write to a buffer for compression or something. See ticket #88
+        # deal with unsigned integer 16, 32 and 64 data
+        old_data = self.data
+        if _is_pseudo_unsigned(self.data.dtype):
+            # Convert the unsigned array to signed
+            self.data = np.array(
+                self.data - _unsigned_zero(self.data.dtype),
+                dtype='<i%d' % self.data.dtype.itemsize)
+            should_swap = False
+        else:
+            byteorder = self.data.dtype.str[0]
+            should_swap = (byteorder in swap_types)
 
-        # TODO: I'm pretty sure most of this is repeated almost exactly a
-        # little bit above; take a closer look at whether we can pare this
-        # down a bit.
+        if should_swap:
+            self.data.byteswap(True)
 
+        # Estimate memory needed for the compressed data and allocate it;
+        # CFITSIO will handle growing allocated memory if necessary, after
+        # which the pyfits.compression module will updating self.compData to
+        # use the newly reallocated buffer
         if self._header['ZCMPTYPE'] == 'RICE_1':
-            idx = 1
-            blockSize = DEFAULT_BLOCK_SIZE
-            bytePix = DEFAULT_BYTE_PIX
-
-            while True:
-                zname = 'ZNAME' + str(idx)
-                if zname not in self._header:
-                    break
-                zval = 'ZVAL' + str(idx)
-                if self._header[zname] == 'BLOCKSIZE':
-                    blockSize = self._header[zval]
-                if self._header[zname] == 'BYTEPIX':
-                    bytePix = self._header[zval]
-                idx += 1
-
-            zvalList.append(blockSize)
-            zvalList.append(bytePix)
-        elif self._header['ZCMPTYPE'] == 'HCOMPRESS_1':
-            idx = 1
-            hcompSmooth = DEFAULT_HCOMP_SMOOTH
-
-            while True:
-                zname = 'ZNAME' + str(idx)
-                if zname not in self._header:
-                    break
-                zval = 'ZVAL' + str(idx)
-                if self._header[zname] == 'SMOOTH':
-                    hcompSmooth = self._header[zval]
-                idx += 1
-
-            zvalList.append(hcompSmooth)
-
-        # Treat the NOISEBIT and SCALE parameters separately because
-        # they are floats instead of integers
-
-        quantizeLevel = DEFAULT_QUANTIZE_LEVEL
-
-        if self._header['ZBITPIX'] < 0:
-            idx = 1
-
-            while True:
-                zname = 'ZNAME' + str(idx)
-                if zname not in self._header:
-                    break
-                zval = 'ZVAL' + str(idx)
-                if self._header[zname] == 'NOISEBIT':
-                    quantizeLevel = self._header[zval]
-                idx += 1
-
-        hcompScale = DEFAULT_HCOMP_SCALE
-
-        if self._header['ZCMPTYPE'] == 'HCOMPRESS_1':
-            idx = 1
-
-            while True:
-                zname = 'ZNAME' + str(idx)
-                if zname not in self._header:
-                    break
-                zval = 'ZVAL' + str(idx)
-                if self._header[zname] == 'SCALE':
-                    hcompScale = self._header[zval]
-                idx += 1
-
-        # Indicate if the null value is a constant or if no null value
-        # is provided.
-        if 'ZBLANK' in self._header:
-            cn_zblank = -1  # null value is a constant
-            zblank = self._header['ZBLANK']
+            rice_blocksize = self._header['ZVAL1']
         else:
-            cn_zblank = 0  # no null value so don't use
-            zblank = 0
-
-        if 'BSCALE' in self._header and self.data.dtype.str[1] == 'f':
-            # If this is scaled data (ie it has a BSCALE value and it is
-            # floating point data) then pass in the BSCALE value so the C
-            # code can unscale it before compressing.
-            cn_bscale = self._header['BSCALE']
+            rice_blocksize = 0
+        maxtilelen = reduce(operator.mul, tilesizes, 1)
+        nrows = self._header['NAXIS2']
+        tbsize = self._header['NAXIS1'] * nrows
+        max_elem = compression.calc_max_elem(self._header['ZCMPTYPE'],
+                                             maxtilelen,
+                                             self._header['ZBITPIX'],
+                                             rice_blocksize)
+        dataspan = tbsize + (nrows * max_elem)
+        if dataspan < BLOCK_SIZE:
+            # We must a full FITS block at a minimum
+            dataspan = BLOCK_SIZE
         else:
-            cn_bscale = 1.0
-
-        if 'BZERO' in self._header and self.data.dtype.str[1] == 'f':
-            cn_bzero = self._header['BZERO']
-        else:
-            cn_bzero = 0.0
-
-        # put data in machine native byteorder on little endian machines
-
-        byteswapped = False
-
-        if self.data.dtype.str[0] == '>' and sys.byteorder == 'little':
-            byteswapped = True
-            self.data = self.data.byteswap(True)
-            self.data.dtype = self.data.dtype.newbyteorder('<')
+            # Still make sure to pad out to a multiple of 2880 byte blocks
+            # otherwise CFITSIO can get read errors when it tries to read
+            # a partial block that goes past the end of the file
+            dataspan += _pad_length(dataspan)
+        self.compData = np.empty((dataspan,), dtype=np.byte)
+        self.compData[:tbsize] = 0
+
+        self._header['PCOUNT'] = 0
+        if 'THEAP' in self._header:
+            del self._header['THEAP']
+        self._theap = tbsize
 
         try:
             # Compress the data.
-            status, compDataList, scaleList, zeroList, uncompDataList = \
-               compression.compressData(self.data,
-                                        self._header['ZNAXIS'],
-                                        naxesList, tileSizeList,
-                                        cn_zblank, zblank,
-                                        cn_bscale, cn_bzero, cn_zscale,
-                                        cn_zzero, cn_uncompressed,
-                                        quantizeLevel,
-                                        hcompScale,
-                                        zvalList,
-                                        self._header['ZCMPTYPE'],
-                                        self.header['BITPIX'], 1,
-                                        self.data.size)
+            # The current implementation of compress_hdu assumes the empty
+            # compressed data table has already been initialized in
+            # self.compData, and writes directly to it
+            # compress_hdu returns the size of the heap for the written
+            # compressed image table
+            heapsize = compression.compress_hdu(self)
         finally:
             # if data was byteswapped return it to its original order
-            if byteswapped:
-                self.data = self.data.byteswap(True)
-                self.data.dtype = self.data.dtype.newbyteorder('>')
-
-        if status != 0:
-            raise RuntimeError('Unable to write compressed image')
-
-        # Convert the compressed data from a list of byte strings to
-        # an array and set it in the COMPRESSED_DATA field of the table.
-        colDType = 'uint8'
-
-        if self._header['ZCMPTYPE'] == 'PLIO_1':
-            colDType = 'i2'
-
-        for idx in xrange(len(compDataList)):
-            self.compData[idx].setfield('COMPRESSED_DATA',
-                                        np.fromstring(compDataList[idx],
-                                                      dtype=colDType))
-
-        # Convert the linear scale factor values from a list to an
-        # array and set it in the ZSCALE field of the table.
-        if cn_zscale > 0:
-            for idx in xrange(len(scaleList)):
-                self.compData[idx].setfield('ZSCALE', scaleList[idx])
-
-        # Convert the zero point offset values from a list to an
-        # array and set it in the ZZERO field of the table.
-        if cn_zzero > 0:
-            for idx in xrange(len(zeroList)):
-                self.compData[idx].setfield('ZZERO', zeroList[idx])
-
-        # Convert the uncompressed data values from a list to an
-        # array and set it in the UNCOMPRESSED_DATA field of the table.
-        if cn_uncompressed > 0:
-            for idx in xrange(len(uncompDataList)):
-                self.compData[idx].setfield('UNCOMPRESSED_DATA',
-                                            uncompDataList[idx])
+            if should_swap:
+                self.data.byteswap(True)
+            self.data = old_data
+
+        # Chances are not all the space allocated for the compressed data was
+        # needed.  If not, go ahead and truncate the array:
+        dataspan = tbsize + heapsize
+        if len(self.compData) > dataspan:
+            if self.compData.flags.owndata:
+                self.compData.resize(dataspan)
+            else:
+                # Need to copy to a new array; this generally shouldn't happen
+                # at all though there are some contrived cases (such as in one
+                # of the regression tests) where it can happen.
+                self.compData = np.resize(self.compData, (dataspan,))
+
+        dtype = np.rec.format_parser(','.join(self.columns._recformats),
+                                     self.columns.names, None).dtype
+        # CFITSIO will write the compressed data in big-endian order
+        dtype = dtype.newbyteorder('>')
+        buf = self.compData
+        compData = buf[:self._theap].view(dtype=dtype, type=np.rec.recarray)
+        self.compData = compData.view(FITS_rec)
+        self.compData._coldefs = self.columns
+        self.compData._heapoffset = self._theap
+        self.compData._heapsize = heapsize
+        self.compData._buffer = buf
+        self.compData.formats = self.columns.formats
 
         # Update the table header cards to match the compressed data.
         self.updateHeader()
@@ -1591,7 +1364,8 @@ class CompImageHDU(BinTableHDU):
                 bytepix = DEFAULT_BYTE_PIX
 
             self._header.set('ZVAL2', bytepix,
-                             'bytes per pixel (1, 2, 4, or 8)', after='ZNAME2')
+                             'bytes per pixel (1, 2, 4, or 8)',
+                             after='ZNAME2')
 
     def scale(self, type=None, option='old', bscale=1, bzero=0):
         """
@@ -1637,19 +1411,15 @@ class CompImageHDU(BinTableHDU):
             _zero = bzero
         else:
             if option == 'old':
-                _scale = self._bscale
-                _zero = self._bzero
+                _scale = self._orig_bscale
+                _zero = self._orig_bzero
             elif option == 'minmax':
                 if isinstance(_type, np.floating):
                     _scale = 1
                     _zero = 0
                 else:
-
-                    # flat the shape temporarily to save memory
-                    dims = self.data.shape
-                    self.data.shape = self.data.size
-                    min = np.minimum.reduce(self.data)
-                    max = np.maximum.reduce(self.data)
+                    min = np.minimum.reduce(self.data.flat)
+                    max = np.maximum.reduce(self.data.flat)
                     self.data.shape = dims
 
                     if _type == np.uint8:  # uint8 case
@@ -1663,41 +1433,56 @@ class CompImageHDU(BinTableHDU):
 
         # Do the scaling
         if _zero != 0:
-            self.data += -_zero  # 0.9.6.3 to avoid out of range error for
-                                 # BZERO = +32768
+            self.data += -_zero
+            self.header['BZERO'] = _zero
+        else:
+            # Delete from both headers
+            for header in (self.header, self._header):
+                try:
+                    del header['BZERO']
+                except KeyError:
+                    pass
 
         if _scale != 1:
             self.data /= _scale
+            self.header['BSCALE'] = _scale
+        else:
+            for header in (self.header, self._header):
+                try:
+                    del header['BSCALE']
+                except KeyError:
+                    pass
 
         if self.data.dtype.type != _type:
             self.data = np.array(np.around(self.data), dtype=_type)  # 0.7.7.1
-        #
+
         # Update the BITPIX Card to match the data
-        #
-        self.header['BITPIX'] = _ImageBaseHDU.ImgCode[self.data.dtype.name]
+        self._bitpix = _ImageBaseHDU.ImgCode[self.data.dtype.name]
+        self._bzero = self.header.get('BZERO', 0)
+        self._bscale = self.header.get('BSCALE', 1)
+        # Update BITPIX for the image header specificially
+        # TODO: Make this more clear by using self._image_header, but only once
+        # this has been fixed so that the _image_header attribute is guaranteed
+        # to be valid
+        self.header['BITPIX'] = self._bitpix
 
-        #
         # Update the table header to match the scaled data
-        #
         self.updateHeaderData(self.header)
 
-        #
-        # Set the BSCALE/BZERO header cards
-        #
-        if _zero != 0:
-            self.header['BZERO'] = _zero
-        else:
-            del self.header['BZERO']
-
-        if _scale != 1:
-            self.header['BSCALE'] = _scale
-        else:
-            del self.header['BSCALE']
+        # Since the image has been manually scaled, the current
+        # bitpix/bzero/bscale now serve as the 'original' scaling of the image,
+        # as though the original image has been completely replaced
+        self._orig_bitpix = self._bitpix
+        self._orig_bzero = self._bzero
+        self._orig_bscale = self._bscale
 
     # TODO: Fix this class so that it doesn't actually inherit from
     # BinTableHDU, but instead has an internal BinTableHDU reference
     def _prewriteto(self, checksum=False, inplace=False):
-        self.updateCompressedData()
+        if self._scale_back:
+            self.scale(_ImageBaseHDU.NumCode[self._orig_bitpix])
+        if self._data_loaded and self.data is not None:
+            self.updateCompressedData()
         # Doesn't call the super's _prewriteto, since it calls
         # self.data._scale_back(), which is meaningless here.
         return ExtensionHDU._prewriteto(self, checksum=checksum,
@@ -1735,6 +1520,55 @@ class CompImageHDU(BinTableHDU):
 
         return size
 
+    # TODO: This was copied right out of _ImageBaseHDU; get rid of it once we
+    # find a way to rewrite this class as either a subclass or wrapper for an
+    # ImageHDU
+    def _dtype_for_bitpix(self):
+        """
+        Determine the dtype that the data should be converted to depending on
+        the BITPIX value in the header, and possibly on the BSCALE value as
+        well.  Returns None if there should not be any change.
+        """
+
+        bitpix = self._orig_bitpix
+        # Handle possible conversion to uints if enabled
+        if self._uint and self._orig_bscale == 1:
+            for bits, dtype in ((16, np.dtype('uint16')),
+                                (32, np.dtype('uint32')),
+                                (64, np.dtype('uint64'))):
+                if bitpix == bits and self._orig_bzero == 1 << (bits - 1):
+                    return dtype
+
+        if bitpix > 16:  # scale integers to Float64
+            return np.dtype('float64')
+        elif bitpix > 0:  # scale integers to Float32
+            return np.dtype('float32')
+
+    def _update_header_scale_info(self, dtype=None):
+        if (not self._do_not_scale_image_data and
+            not (self._orig_bzero == 0 and self._orig_bscale == 1)):
+            for keyword in ['BSCALE', 'BZERO']:
+                # Make sure to delete from both the image header and the table
+                # header; later this will be streamlined
+                for header in (self.header, self._header):
+                    try:
+                        del header[keyword]
+                        # Since _update_header_scale_info can, currently, be
+                        # called *after* _prewriteto(), replace these with
+                        # blank cards so the header size doesn't change
+                        header.append()
+                    except KeyError:
+                        pass
+
+            if dtype is None:
+                dtype = self._dtype_for_bitpix()
+            if dtype is not None:
+                self.header['BITPIX'] = _ImageBaseHDU.ImgCode[dtype.name]
+
+            self._bzero = 0
+            self._bscale = 1
+            self._bitpix = self.header['BITPIX']
+
     def _calculate_datasum(self, blocking):
         """
         Calculate the value for the ``DATASUM`` card in the HDU.
diff --git a/astropy/io/fits/hdu/groups.py b/astropy/io/fits/hdu/groups.py
index 86b2497..eec53d8 100644
--- a/astropy/io/fits/hdu/groups.py
+++ b/astropy/io/fits/hdu/groups.py
@@ -387,7 +387,7 @@ class GroupsHDU(PrimaryHDU, _TableLikeHDU):
             except KeyError:
                 pass
 
-        if isinstance(self.data, GroupData):
+        if self._data_loaded and isinstance(self.data, GroupData):
             self._header.set('GROUPS', True,
                              after='NAXIS' + str(len(self._axes)))
             self._header.set('PCOUNT', len(self.data.parnames), after='GROUPS')
diff --git a/astropy/io/fits/hdu/hdulist.py b/astropy/io/fits/hdu/hdulist.py
index 3e41eea..7d78a6a 100644
--- a/astropy/io/fits/hdu/hdulist.py
+++ b/astropy/io/fits/hdu/hdulist.py
@@ -16,8 +16,8 @@ from .table import _TableBaseHDU
 from ..file import PYTHON_MODES, _File
 from ..header import BLOCK_SIZE, _pad_length
 from ..util import (_is_int, _tmp_name, isfile, fileobj_name, fileobj_closed,
-                    fileobj_mode, ignore_sigint, _get_array_memmap, indent)
-from ..verify import _Verify, _ErrList, VerifyError
+                    fileobj_mode, ignore_sigint, _get_array_mmap, indent)
+from ..verify import _Verify, _ErrList, VerifyError, VerifyWarning
 
 
 def fitsopen(name, mode='readonly', memmap=None, save_backup=False, **kwargs):
@@ -491,7 +491,9 @@ class HDUList(list, _Verify):
             name = hdu.name
             if isinstance(name, str):
                 name = name.strip().upper()
-            if name == _key and (_ver is None or _ver == hdu._extver):
+            # 'PRIMARY' should always work as a reference to the first HDU
+            if ((name == _key or (_key == 'PRIMARY' and idx == 0)) and
+                (_ver is None or _ver == hdu._extver)):
                 found = idx
                 nfound += 1
 
@@ -558,7 +560,7 @@ class HDUList(list, _Verify):
             for hdu in self:
                 if verbose:
                     try:
-                        extver = str(hdu.header['extver'])
+                        extver = str(hdu._header['extver'])
                     except KeyError:
                         extver = ''
 
@@ -910,7 +912,7 @@ class HDUList(list, _Verify):
 
             # reset the modification attributes after updating
             for hdu in self:
-                hdu.header._modified = False
+                hdu._header._modified = False
         finally:
             for hdu in self:
                 hdu._postwriteto()
@@ -943,7 +945,7 @@ class HDUList(list, _Verify):
             if sys.platform.startswith('win'):
                 # Collect a list of open mmaps to the data; this well be used
                 # later.  See below.
-                mmaps = [(idx, _get_array_memmap(hdu.data), hdu.data)
+                mmaps = [(idx, _get_array_mmap(hdu.data), hdu.data)
                          for idx, hdu in enumerate(self) if hdu._data_loaded]
 
             hdulist.__file.close()
@@ -953,9 +955,9 @@ class HDUList(list, _Verify):
                 # Close all open mmaps to the data.  This is only necessary on
                 # Windows, which will not allow a file to be renamed or deleted
                 # until all handles to that file have been closed.
-                for idx, map, arr in mmaps:
-                    if map is not None:
-                        map.base.close()
+                for idx, mmap, arr in mmaps:
+                    if mmap is not None:
+                        mmap.close()
 
             os.remove(self.__file.name)
 
@@ -976,7 +978,7 @@ class HDUList(list, _Verify):
                 # Need to update the _file attribute and close any open mmaps
                 # on each HDU
                 if (hdu._data_loaded and
-                    _get_array_memmap(hdu.data) is not None):
+                    _get_array_mmap(hdu.data) is not None):
                     del hdu.data
                 hdu._file = ffo
 
@@ -1021,7 +1023,7 @@ class HDUList(list, _Verify):
         self._resize = False
         self._truncate = False
         for hdu in self:
-            hdu.header._modified = False
+            hdu._header._modified = False
             hdu._new = False
             hdu._file = ffo
 
@@ -1038,7 +1040,7 @@ class HDUList(list, _Verify):
             # determine if any of the HDU is resized
             for hdu in self:
                 # Header:
-                nbytes = len(str(hdu.header))
+                nbytes = len(str(hdu._header))
                 if nbytes != (hdu._datLoc - hdu._hdrLoc):
                     self._resize = True
                     self._truncate = False
@@ -1050,7 +1052,7 @@ class HDUList(list, _Verify):
                 if not hdu._data_loaded or hdu.data is None:
                     continue
 
-                nbytes = hdu.data.nbytes
+                nbytes = hdu.size
                 nbytes = nbytes + _pad_length(nbytes)
                 if nbytes != hdu._datSpan:
                     self._resize = True
diff --git a/astropy/io/fits/hdu/image.py b/astropy/io/fits/hdu/image.py
index 1f8678c..7d6216a 100644
--- a/astropy/io/fits/hdu/image.py
+++ b/astropy/io/fits/hdu/image.py
@@ -155,6 +155,10 @@ class _ImageBaseHDU(_ValidHDU):
         raise NotImplementedError
 
     @property
+    def is_image(self):
+        return True
+
+    @property
     def section(self):
         """
         Access a section of the image array without loading the entire array
@@ -796,7 +800,8 @@ class PrimaryHDU(_ImageBaseHDU):
             data=data, header=header,
             do_not_scale_image_data=do_not_scale_image_data, uint=uint,
             scale_back=scale_back)
-        self.name = 'PRIMARY'
+
+        self._name = 'PRIMARY'
         self._extver = 1
 
         # insert the keywords EXTEND
diff --git a/astropy/io/fits/hdu/table.py b/astropy/io/fits/hdu/table.py
index 130eec7..338ead6 100644
--- a/astropy/io/fits/hdu/table.py
+++ b/astropy/io/fits/hdu/table.py
@@ -73,8 +73,20 @@ class _TableLikeHDU(_ValidHDU):
         names = [n for idx, n in enumerate(columns.names)
                  if not columns[idx]._phantom]
         dtype = np.rec.format_parser(formats, names, None).dtype
-        raw_data = self._get_raw_data(columns._shape, dtype, self._datLoc)
-        data = raw_data.view(np.rec.recarray)
+
+        # TODO: Details related to variable length arrays need to be dealt with
+        # specifically in the BinTableHDU class, since they're a detail
+        # specific to FITS binary tables
+        if (_FormatP in [type(r) for r in recformats] and
+            self._datSpan > self._theap):
+            # We have a heap; include it in the raw_data
+            raw_data = self._get_raw_data(self._datSpan, np.byte, self._datLoc)
+            data = raw_data[:self._theap].view(dtype=dtype,
+                                               type=np.rec.recarray)
+        else:
+            raw_data = self._get_raw_data(columns._shape, dtype, self._datLoc)
+            data = raw_data.view(np.rec.recarray)
+
         self._init_tbdata(data)
         return data.view(self._data_type)
 
@@ -165,7 +177,7 @@ class _TableBaseHDU(ExtensionHDU, _TableLikeHDU):
 
                 self._header['NAXIS1'] = self.data.itemsize
                 self._header['NAXIS2'] = self.data.shape[0]
-                self._header['TFIELDS'] = self.data._nfields
+                self._header['TFIELDS'] = len(self.data._coldefs)
 
                 self.columns = self.data._coldefs
                 self.update()
@@ -267,7 +279,7 @@ class _TableBaseHDU(ExtensionHDU, _TableLikeHDU):
         if self._data_loaded and self.data is not None:
             self.data._scale_back()
             # check TFIELDS and NAXIS2
-            self._header['TFIELDS'] = self.data._nfields
+            self._header['TFIELDS'] = len(self.data._coldefs)
             self._header['NAXIS2'] = self.data.shape[0]
 
             # calculate PCOUNT, for variable length tables
@@ -429,13 +441,11 @@ class TableHDU(_TableBaseHDU):
             # We need to pad the data to a block length before calculating
             # the datasum.
 
-            if self.size > 0:
-                d = np.append(np.fromstring(self.data, dtype='ubyte'),
-                              np.fromstring(_pad_length(self.size) * ' ',
-                                            dtype='ubyte'))
+            d = np.append(self.data.view(dtype='ubyte'),
+                          np.fromstring(_pad_length(self.size) * ' ',
+                                        dtype='ubyte'))
 
-            cs = self._compute_checksum(np.fromstring(d, dtype='ubyte'),
-                                        blocking=blocking)
+            cs = self._compute_checksum(d, blocking=blocking)
             return cs
         else:
             # This is the case where the data has not been read from the file
@@ -502,14 +512,13 @@ class BinTableHDU(_TableBaseHDU):
                             data.field(i)[:] = data.field(i).byteswap()
         data.dtype = data.dtype.newbyteorder('>')
 
-        dout = np.fromstring(data, dtype='ubyte')
+        dout = data.view(dtype='ubyte')
 
         for i in range(data._nfields):
             if isinstance(data._coldefs._recformats[i], _FormatP):
                 for coldata in data.field(i):
                     if len(coldata) > 0:
-                        dout = np.append(dout,
-                                         np.fromstring(coldata, dtype='ubyte'))
+                        dout = np.append(dout, coldata.view(dtype='ubyte'))
 
         cs = self._compute_checksum(dout, blocking=blocking)
         return cs
@@ -539,6 +548,7 @@ class BinTableHDU(_TableBaseHDU):
         return size
 
     def _binary_table_byte_swap(self, fileobj):
+        to_swap = []
         swapped = []
         nbytes = 0
         if sys.byteorder == 'little':
@@ -548,27 +558,26 @@ class BinTableHDU(_TableBaseHDU):
         try:
             if not fileobj.simulateonly:
                 for idx in range(self.data._nfields):
-                    coldata = self.data.field(idx)
-                    if isinstance(coldata, chararray.chararray):
+                    field = np.rec.recarray.field(self.data, idx)
+                    if isinstance(field, chararray.chararray):
                         continue
+                    recformat = self.data.columns._recformats[idx]
                     # only swap unswapped
+                    if field.itemsize > 1 and field.dtype.str[0] in swap_types:
+                        to_swap.append(field)
                     # deal with var length table
-                    field = np.rec.recarray.field(self.data, idx)
-                    if isinstance(coldata, _VLF):
+                    if isinstance(recformat, _FormatP):
+                        coldata = self.data.field(idx)
                         for jdx, c in enumerate(coldata):
                             if (not isinstance(c, chararray.chararray) and
                                 c.itemsize > 1 and
                                 c.dtype.str[0] in swap_types):
-                                swapped.append(c)
-                            if (field[jdx:jdx + 1].dtype.str[0] in swap_types):
-                                swapped.append(field[jdx:jdx + 1])
-                    else:
-                        if (coldata.itemsize > 1 and
-                            self.data.dtype.descr[idx][1][0] in swap_types):
-                            swapped.append(field)
+                                to_swap.append(c)
 
-                for obj in swapped:
+                while to_swap:
+                    obj = to_swap.pop()
                     obj.byteswap(True)
+                    swapped.append(obj)
 
                 fileobj.writearray(self.data)
 
@@ -580,7 +589,7 @@ class BinTableHDU(_TableBaseHDU):
             nbytes = self.data._gap
 
             for idx in range(self.data._nfields):
-                if isinstance(self.data._coldefs._recformats[idx], _FormatP):
+                if isinstance(self.data.columns._recformats[idx], _FormatP):
                     field = self.data.field(idx)
                     for jdx in range(len(field)):
                         coldata = field[jdx]
@@ -711,7 +720,7 @@ class BinTableHDU(_TableBaseHDU):
                         exist.append(f)
 
         if exist:
-            raise IOError('  '.join(["File '%s' already exists."
+            raise IOError('  '.join(["File '%s' already exists." % f
                                      for f in exist]))
 
         # Process the data
diff --git a/astropy/io/fits/header.py b/astropy/io/fits/header.py
index adad244..bd52836 100644
--- a/astropy/io/fits/header.py
+++ b/astropy/io/fits/header.py
@@ -11,7 +11,7 @@ import re
 import sys
 import warnings
 
-from .card import Card, CardList, _pad, BLANK_CARD
+from .card import Card, CardList, _pad, BLANK_CARD, KEYWORD_LENGTH
 from .file import _File, PYTHON_MODES
 from .util import (encode_ascii, decode_ascii, fileobj_mode,
                    fileobj_is_binary)
@@ -127,7 +127,17 @@ class Header(object):
             key = key.upper()
             # Special case for commentary cards
             return _HeaderCommentaryCards(self, key)
-        return self._cards[self._cardindex(key)].value
+        if isinstance(key, tuple):
+            keyword = key[0]
+        else:
+            keyword = key
+        card = self._cards[self._cardindex(key)]
+        if (card.field_specifier is not None and
+            keyword == card.keyword.split('.', 1)[0]):
+            # This is RVKC; if only the top-level keyword was specified return
+            # the raw value, not the parsed out float value
+            return card.rawvalue
+        return card.value
 
     def __setitem__(self, key, value):
         if isinstance(key, slice) or self._haswildcard(key):
@@ -520,7 +530,16 @@ class Header(object):
             A string representing a FITS header.
         """
 
-        s = sep.join(str(card) for card in self._cards)
+        lines = []
+        for card in self._cards:
+            s = str(card)
+            # Cards with CONTINUE cards may be longer than 80 chars; so break
+            # them into multiple lines
+            while s:
+                lines.append(s[:Card.length])
+                s = s[Card.length:]
+
+        s = sep.join(lines)
         if endcard:
             s += sep + _pad('END')
         if padding:
@@ -610,21 +629,21 @@ class Header(object):
                 fileobj.close()
 
     @classmethod
-    def fromtextfile(cls, fileobj):
+    def fromtextfile(cls, fileobj, endcard=False):
         """
         Equivalent to ``Header.fromfile(fileobj, sep='\\n', endcard=False,
         padding=False)``.
         """
 
-        return cls.fromfile(fileobj, sep='\n', endcard=False, padding=False)
+        return cls.fromfile(fileobj, sep='\n', endcard=endcard, padding=False)
 
-    def totextfile(self, fileobj, clobber=False):
+    def totextfile(self, fileobj, endcard=False, clobber=False):
         """
         Equivalent to ``Header.tofile(fileobj, sep='\\n', endcard=False,
         padding=False, clobber=clobber)``.
         """
 
-        self.tofile(fileobj, sep='\n', endcard=False, padding=False,
+        self.tofile(fileobj, sep='\n', endcard=endcard, padding=False,
                     clobber=clobber)
 
     def clear(self):
@@ -770,7 +789,8 @@ class Header(object):
         # Don't try to make a temporary card though if they keyword looks like
         # it might be a HIERARCH card or is otherwise invalid--this step is
         # only for validating RVKCs.
-        if (len(keyword) <= 8 and Card._keywd_FSC_RE.match(keyword) and
+        if (len(keyword) <= KEYWORD_LENGTH and
+            Card._keywd_FSC_RE.match(keyword) and
             keyword not in self._keyword_indices):
             new_card = Card(keyword, value, comment)
             new_keyword = new_card.keyword
@@ -1564,7 +1584,7 @@ class Header(object):
             # Returns the index into _cards for the n-th card with the given
             # keyword (where n is 0-based)
             if keyword and keyword not in self._keyword_indices:
-                if len(keyword) > 8:
+                if len(keyword) > KEYWORD_LENGTH or '.' in keyword:
                     raise KeyError("Keyword %r not found." % keyword)
                 # Great--now we have to check if there's a RVKC that starts
                 # with the given keyword, making failed lookups fairly
@@ -1716,8 +1736,9 @@ class Header(object):
         """
 
         # The maximum value in each card can be the maximum card length minus
-        # the key length minus a space (or just minus one if the key is blank)
-        maxlen = Card.length - len(keyword) - 1
+        # the maximum key length (which can include spaces if they key length
+        # less than 8
+        maxlen = Card.length - KEYWORD_LENGTH
         valuestr = str(value)
 
         if len(valuestr) <= maxlen:
@@ -1774,7 +1795,8 @@ class Header(object):
                     pass
 
         for name in ('SIMPLE', 'XTENSION', 'BITPIX', 'NAXIS', 'EXTEND',
-                     'PCOUNT', 'GCOUNT', 'GROUPS', 'BSCALE', 'TFIELDS'):
+                     'PCOUNT', 'GCOUNT', 'GROUPS', 'BSCALE', 'BZERO',
+                     'TFIELDS'):
             try:
                 del self[name]
             except KeyError:
@@ -2012,10 +2034,10 @@ class _HeaderComments(_CardAccessor):
     def __repr__(self):
         """Returns a simple list of all keywords and their comments."""
 
-        keyword_width = 8
+        keyword_length = KEYWORD_LENGTH
         for card in self._header._cards:
-            keyword_width = max(keyword_width, len(card.keyword))
-        return '\n'.join('%*s  %s' % (keyword_width, c.keyword, c.comment)
+            keyword_length = max(keyword_length, len(card.keyword))
+        return '\n'.join('%*s  %s' % (keyword_length, c.keyword, c.comment)
                          for c in self._header._cards)
 
     def __getitem__(self, item):
diff --git a/astropy/io/fits/setup_package.py b/astropy/io/fits/setup_package.py
index e6a34da..30e002e 100644
--- a/astropy/io/fits/setup_package.py
+++ b/astropy/io/fits/setup_package.py
@@ -9,27 +9,60 @@ from astropy import setup_helpers
 
 
 def get_extensions():
-    if setup_helpers.get_compiler_option() != 'msvc':
-        extra_compile_args = ['-Wno-unused-function',
-                              '-Wno-strict-prototypes']
+    # 'numpy' will be replaced with the proper path to the numpy includes
+    include_dirs = ['numpy']
+    library_dirs = []
+    libraries = []
+    source_files = [os.path.relpath(fname) for fname in
+                    glob(os.path.join(os.path.dirname(__file__),
+                                      'src', '*.c'))]
+    extra_compile_args = []
+
+    if not setup_helpers.use_system_library('cfitsio'):
+        if setup_helpers.get_compiler_option() == 'msvc':
+            # These come from the CFITSIO vcc makefile
+            extra_compile_args = [
+                    '/D', '"WIN32"',
+                    '/D', '"_WINDOWS"',
+                    '/D', '"_MBCS"',
+                    '/D', '"_USRDLL"',
+                    '/D', '"_CRT_SECURE_NO_DEPRECATE"']
+        else:
+            # All of these switches are to silence warnings from compiling CFITSIO
+            extra_compile_args = ['-Wno-unused-variable', '-Wno-parentheses',
+                                  '-Wno-uninitialized', '-Wno-format',
+                                  '-Wno-strict-prototypes', '-Wno-unused',
+                                  '-Wno-comments', '-Wno-switch']
+
+        cfitsio_path = os.path.join('cextern', 'cfitsio')
+        cfitsio_files = glob(os.path.join(cfitsio_path, '*.c'))
+        include_dirs.append(cfitsio_path)
+        source_files.extend(cfitsio_files)
     else:
-        extra_compile_args = []
+        setup_helpers.pkg_config(['cfitsio'], ['cfitsio'], include_dirs,
+                                 library_dirs, libraries)
+
     return [
         Extension(
             'astropy.io.fits.compression',
-            [os.path.relpath(x) for x in
-             glob(os.path.join(os.path.dirname(__file__), 'src/*.c'))],
-            include_dirs=[setup_helpers.get_numpy_include_path()],
-            extra_compile_args=extra_compile_args)
+            source_files,
+            include_dirs=include_dirs,
+            extra_compile_args=extra_compile_args,
+            libraries=libraries,
+            library_dirs=library_dirs)
     ]
 
 
 def get_package_data():
     # Installs the testing data files
     return {
-        'astropy.io.fits.tests': ['data/*.fits']}
+        'astropy.io.fits.tests': [os.path.join('data', '*.fits')]}
+
+
+def get_external_libraries():
+    return ['cfitsio']
 
 
 def get_legacy_alias():
     return setup_helpers.add_legacy_alias(
-        'pyfits', 'astropy.io.fits', '3.1', {'__svn_revision__': '1357'})
+        'pyfits', 'astropy.io.fits', '3.2.dev', {'__svn_revision__': '1927'})
diff --git a/astropy/io/fits/src/compress.c b/astropy/io/fits/src/compress.c
deleted file mode 100644
index e8672f8..0000000
--- a/astropy/io/fits/src/compress.c
+++ /dev/null
@@ -1,335 +0,0 @@
-/* $Id$
-*/
-
-/*****************************************************************************/
-/*                                                                           */
-/* This file, compress.c, contains the code required to compress and         */
-/* uncompress data using the GZIP_1 compression format.                      */
-/*                                                                           */
-/* Copyright (C) 2004 Association of Universities for Research in Astronomy  */
-/* (AURA)                                                                    */
-/*                                                                           */
-/* Redistribution and use in source and binary forms, with or without        */
-/* modification, are permitted provided that the following conditions are    */
-/* met:                                                                      */
-/*                                                                           */
-/*    1. Redistributions of source code must retain the above copyright      */
-/*      notice, this list of conditions and the following disclaimer.        */
-/*                                                                           */
-/*    2. Redistributions in binary form must reproduce the above             */
-/*      copyright notice, this list of conditions and the following          */
-/*      disclaimer in the documentation and/or other materials provided      */
-/*      with the distribution.                                               */
-/*                                                                           */
-/*    3. The name of AURA and its representatives may not be used to         */
-/*      endorse or promote products derived from this software without       */
-/*      specific prior written permission.                                   */
-/*                                                                           */
-/* THIS SOFTWARE IS PROVIDED BY AURA ``AS IS'' AND ANY EXPRESS OR IMPLIED    */
-/* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF      */
-/* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE                  */
-/* DISCLAIMED. IN NO EVENT SHALL AURA BE LIABLE FOR ANY DIRECT, INDIRECT,    */
-/* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,      */
-/* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS     */
-/* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND    */
-/* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR     */
-/* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE    */
-/* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH          */
-/* DAMAGE.                                                                   */
-/*                                                                           */
-/* This file was copied and heavily modified from the FITSIO software that   */
-/* was written by William Pence at the High Energy Astrophysic Science       */
-/* Archive Research Center (HEASARC) at the NASA Goddard Space Flight Center.*/
-/* That software contained the following copyright and warranty notices:     */
-/*                                                                           */
-/* 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."                                             */
-/*                                                                           */
-/* This code calls routines from and links to the ZLIB compression library   */
-/* that was written by Jean-loup Gailly and Mark Adler.  This package is     */
-/* normally destributed with Python 2.5.  That software containes the        */
-/* following copyright and warranty notices:     */
-/*                                                                           */
-/*  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 at gzip.org          madler at 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).              */
-/*                                                                           */
-/*****************************************************************************/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "zlib.h"  
-
-int _astropy_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 _astropy_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 _astropy_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 into memory.  Fill whatever amount of memory has
-  already been allocated, then realloc more memory, using the supplied
-  input function, if necessary.
-*/
-{
-    int err; 
-    uLong uncomprLen;
-    Byte *uncompr;
-    z_stream d_stream;   /* decompression stream */
-    uLong bytes_out_so_far = 0;  /* Keeps track of the number of bytes put in
-                                    the output buffer so far */
-
-
-    if (*status > 0) 
-        return(*status); 
-
-    /* Allocate memory as a temporary buffer in which to uncompress. */
-    uncomprLen = *buffsize;
-    uncompr = (Byte*)malloc(*buffsize);
-
-    d_stream.zalloc = (alloc_func)0;
-    d_stream.zfree = (free_func)0;
-    d_stream.opaque = (voidpf)0;
-
-    d_stream.next_in = (unsigned char*)inmemptr;
-    d_stream.avail_in = inmemsize;
-
-    /* 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)
-    {
-        /* free temporary output data buffer */
-        free(uncompr);
-        return(*status = 414);
-    }
-
-    for (;;)
-    {
-        /* Output to the temporary buffer.  This will overwrite the
-           previous data each time. */
-        d_stream.next_out = uncompr;
-        d_stream.avail_out = uncomprLen;
-
-        err = _astropy_inflate(&d_stream, Z_NO_FLUSH);
-
-        if (err != Z_OK && err != Z_STREAM_END)
-        {
-            /* free temporary output data buffer */
-            free(uncompr);
-            return(*status = 414);
-        }
-
-        if (d_stream.total_out > *buffsize)
-        {
-            /* OK, we need more memory for the output so reallocate it */
-            *buffsize = d_stream.total_out;
-            *buffptr = mem_realloc(*buffptr,*buffsize);
-
-            if (*buffptr == NULL)
-            {
-                /* free temporary output data buffer */
-                free(uncompr);
-                return(*status = 414);
-            }
-        }
-
-        /* copy from the temporary buffer into the output memory buffer */
-        memcpy((char *) *buffptr + bytes_out_so_far, (char *) uncompr,
-               d_stream.total_out-bytes_out_so_far);
-        bytes_out_so_far = d_stream.total_out;
-
-        if (err == Z_STREAM_END) break;  /* We reached the end of the input */
-    }
-
-    /* Set the output file size to be the total output data */
-    *filesize = d_stream.total_out;
-
-    /* End the decompression */
-    err = _astropy_inflateEnd(&d_stream);
-
-    /* free temporary output data buffer */
-    free(uncompr);
-
-    if (err != Z_OK)
-    {
-        return(*status = 414);
-    }
-    
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int _astropy_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;
-    uLong comprLen;
-    Byte *compr;
-
-    z_stream c_stream;  /* compression stream */
-
-    uLong bytes_out_so_far = 0;  /* Keeps track of the number of bytes put in
-                                    the output buffer so far */
-
-    if (*status > 0)
-        return(*status);
-
-    /* Allocate memory as a temporary buffer in which to compress. */
-    comprLen = *buffsize;
-    compr = (Byte*)malloc(*buffsize);
-
-    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 */
-    err = deflateInit2(&c_stream, Z_DEFAULT_COMPRESSION, 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;
-
-    for (;;)
-    {
-        /* Output to the temporary buffer.  This will overwrite the
-           previous data each time. */
-        c_stream.next_out = compr;
-        c_stream.avail_out = comprLen;
-
-        err = _astropy_deflate(&c_stream, Z_FINISH);
-
-        if (err != Z_OK && err != Z_STREAM_END)
-        {
-            /* free temporary output data buffer */
-            free(compr);
-            return(*status = 413);
-        }
-
-        if (c_stream.total_out > *buffsize)
-        {
-            /* OK, we need more memory for the output so reallocate it */
-            *buffsize = c_stream.total_out;
-            *buffptr = mem_realloc(*buffptr,*buffsize);
-
-            if (*buffptr == NULL)
-            {
-                /* free temporary output data buffer */
-                free(compr);
-                return(*status = 413);
-            }
-        }
-
-        /* copy from the temporary buffer into the output memory buffer */
-        memcpy((char *) *buffptr + bytes_out_so_far, (char *) compr,
-               c_stream.total_out-bytes_out_so_far);
-        bytes_out_so_far = c_stream.total_out;
-
-        if (err == Z_STREAM_END) break;  /* We reached the end of the input */
-    }
-
-    /* Set the output file size to be the total output data */
-    *filesize = c_stream.total_out;
-
-    /* End the compression */
-    err = _astropy_deflateEnd(&c_stream);
-
-    /* free temporary output data buffer */
-    free(compr);
-
-    if (err != Z_OK)
-    {
-        return(*status = 413);
-    }
-     
-    return(*status);
-}
-
diff --git a/astropy/io/fits/src/compressionmodule.c b/astropy/io/fits/src/compressionmodule.c
index 79eefec..44e9273 100644
--- a/astropy/io/fits/src/compressionmodule.c
+++ b/astropy/io/fits/src/compressionmodule.c
@@ -1,30 +1,33 @@
-/* $Id$ 
-*/
-
 /* "compression module */
 
 /*****************************************************************************/
 /*                                                                           */
-/* The compression software is a python module implemented in C that, when    */
-/* accessed through the astropy module, supports the storage of compressed    */
+/* The compression software is a python module implemented in C that, when   */
+/* accessed through the astropy module, supports the storage of compressed   */
 /* images in FITS binary tables.  An n-dimensional image is divided into a   */
-/* rectabgular grid of subimages or 'tiles'.  Each tile is then compressed   */
+/* 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.    */
 /* The default tiling pattern treates each row of a 2-dimensional image      */
 /* (or higher dimensional cube) as a tile, such that each tile contains      */
 /* NAXIS1 pixels.                                                            */
 /*                                                                           */
-/* This module contains two functions that are callable from python.  The    */
-/* first is compressData.  This function takes a numpy.ndarray object        */
-/* containing the uncompressed image data and returns a list of byte streams */
-/* in which each element of the list holds the compressed data for a single  */
-/* tile of the image.  The second function is decompressData.  It takes a    */
-/* list of byte streams that hold the compressed data for each tile in the   */
-/* image.  It returns a list containing the decompressed data for each tile  */
-/* in the image.                                                             */
+/* This module contains three functions that are callable from python.  The  */
+/* first is compress_hdu.  This function takes an                            */
+/* astropy.io.fits.CompImageHDU object containing the uncompressed image     */
+/* data and returns the compressed data for all tiles into the .compData     */
+/* attribute of that HDU.                                                    */
+/*                                                                           */
+/* The second function is decompress_hdu.  It takes an                       */
+/* astropy.io.fits.CompImageHDU object that already has compressed data in   */
+/* its .compData attribute. It returns the decompressed image data into the  */
+/* HDU's .data attribute.                                                    */
 /*                                                                           */
-/* Copyright (C) 2004 Association of Universities for Research in Astronomy  */
+/* Finally, the utility function calc_max_elm is used internally by the      */
+/* CompImageHDU class to estimate how much memory to allocate for the        */
+/* compressed data when compressing an image.                                */
+/*                                                                           */
+/* Copyright (C) 2012 Association of Universities for Research in Astronomy  */
 /* (AURA)                                                                    */
 /*                                                                           */
 /* Redistribution and use in source and binary forms, with or without        */
@@ -91,1056 +94,901 @@
 
 /* Include the Python C API */
 
-#include "Python.h"
+#include <math.h>
+
+#include <Python.h>
 #include <numpy/arrayobject.h>
-#include "fitsio.h"
-#include "string.h"
+#include <fitsio2.h>
+#include <string.h>
+#include "compressionmodule.h"
 
 /* Some defines for Python3 support--bytes objects should be used where */
 /* strings were previously used                                         */
 #if PY_MAJOR_VERSION >= 3
-#define PyString_AsString PyBytes_AsString
-#define PyString_FromStringAndSize PyBytes_FromStringAndSize
-#define PyString_Size PyBytes_Size
+#define IS_PY3K
 #endif
 
-/* Function to get the input long values from the input list */
-
-static long* get_long_array(PyObject* data, const char* description,
-                            int* data_size)
-{
-   int    i;
-   int    size;
-   long*  out;
-   int    seq;
-   char   errMsg[80];
-
-   seq = PyList_Check(data);
-
-   if (!seq)
-   {
-      strncpy(errMsg,description,79);
-      strncat(errMsg," argument must be a list.",79-strlen(errMsg));
-      PyErr_SetString(PyExc_TypeError,errMsg);
-      return NULL;
-   }
-
-   size = PyList_Size(data);
-
-   if (size < 0)
-   {
-      strncpy(errMsg,description,79);
-      strncat(errMsg," list has invalid size.",79-strlen(errMsg));
-      PyErr_SetString(PyExc_ValueError,errMsg);
-      return NULL;
-   }
-
-   if (data_size)
-   {
-      *data_size = size;
-   }
-
-   out = (long*) PyMem_Malloc(size * sizeof(long));
-
-   if(!out)
-   {
-      PyErr_NoMemory();
-      return NULL;
-   }
-
-   for (i = 0; i < size; i++)
-   {
-      out[i] = PyLong_AsLong(PyList_GetItem(data, i));
-   }
-
-   if ( PyErr_Occurred())
-   {
-      PyMem_Free(out);
-      out = NULL;
-   }
-
-   return out;
-}
-
-
-/* Function to get the input character arrays from the input list */
-
-static unsigned char** get_char_array(PyObject* data, const char* description,
-                                      int* data_size, int** dataLen)
-{
-   int             i;
-   int             size;
-   unsigned char** out;
-   int             seq;
-   char            errMsg[80];
-
-   seq = PyList_Check(data);
-
-   if (!seq)
-   {
-      strncpy(errMsg,description,79);
-      strncat(errMsg," argument must be a list.",79-strlen(errMsg));
-      PyErr_SetString(PyExc_TypeError,errMsg);
-      return NULL;
-   }
-
-   size = PyList_Size(data);
-
-   if ( size < 0)
-   {
-      strncpy(errMsg,description,79);
-      strncat(errMsg," list has invalid size.",79-strlen(errMsg));
-      PyErr_SetString(PyExc_ValueError,errMsg);
-      return NULL;
-   }
-
-   if (data_size)
-   {
-      *data_size = size;
-   }
-
-   out = (unsigned char**) PyMem_Malloc(size * sizeof(char*));
-
-   if(!out)
-   {
-      PyErr_NoMemory();
-      return NULL;
-   }
-
-   *dataLen = (int*) PyMem_Malloc(size * sizeof(int));
-
-   if(!(*dataLen))
-   {
-      PyMem_Free(out);
-      PyErr_NoMemory();
-      return NULL;
-   }
-
-   for (i = 0; i < size; i++)
-   {
-      out[i] = (unsigned char*)PyString_AsString(PyList_GetItem(data,i));
-      (*dataLen)[i] = PyString_Size(PyList_GetItem(data,i));
-   }
-
-   if (PyErr_Occurred())
-   {
-      PyMem_Free(out);
-      PyMem_Free(*dataLen);
-      out = NULL;
-   }
-
-   return out;
-}
-
-/* Function to get the input float values from the input list */
-
-static float* get_float_array(PyObject* data, const char* description,
-                              int* data_size)
-{
-   int    i;
-   int    size;
-   float* out;
-   int    seq;
-   char   errMsg[80];
-
-   seq = PyList_Check(data);
-
-   if (!seq)
-   {
-      strncpy(errMsg,description,79);
-      strncat(errMsg," argument must be a list.",79-strlen(errMsg));
-      PyErr_SetString(PyExc_TypeError,errMsg);
-      return NULL;
-   }
-
-   size = PyList_Size(data);
-
-   if (size < 0)
-   {
-      strncpy(errMsg,description,79);
-      strncat(errMsg," list has invalid size.",79-strlen(errMsg));
-      PyErr_SetString(PyExc_ValueError,errMsg);
-      return NULL;
-   }
-
-   if (data_size)
-   {
-      *data_size = size;
-   }
-
-   out = (float*) PyMem_Malloc(size * sizeof(float));
-
-   if(!out)
-   {
-      PyErr_NoMemory();
-      return NULL;
-   }
-
-   for (i = 0; i < size; i++)
-   {
-      out[i] = PyFloat_AsDouble(PyList_GetItem(data, i));
-   }
-
-   if ( PyErr_Occurred())
-   {
-      PyMem_Free(out);
-      out = NULL;
-   }
-
-   return out;
-}
-
-/* Function to get the input double values from the input list */
-
-static double* get_double_array(PyObject* data, const char* description,
-                                int* data_size)
-{
-   int     i;
-   int     size;
-   double* out;
-   int     seq;
-   char    errMsg[80];
-
-   seq = PyList_Check(data);
-
-   if (!seq)
-   {
-      strncpy(errMsg,description,79);
-      strncat(errMsg," argument must be a list.",79-strlen(errMsg));
-      PyErr_SetString(PyExc_TypeError,errMsg);
-      return NULL;
-   }
-
-   size = PyList_Size(data);
-
-   if (size < 0)
-   {
-      strncpy(errMsg,description,79);
-      strncat(errMsg," list has invalid size.",79-strlen(errMsg));
-      PyErr_SetString(PyExc_ValueError,errMsg);
-      return NULL;
-   }
-
-   if (data_size)
-   {
-      *data_size = size;
-   }
-
-   out = (double*) PyMem_Malloc(size * sizeof(double));
-
-   if(!out)
-   {
-      PyErr_NoMemory();
-      return NULL;
-   }
+#ifdef IS_PY3K
+#define PyString_FromString PyUnicode_FromString
+#define PyInt_AsLong PyLong_AsLong
+#endif
 
-   for (i = 0; i < size; i++)
-   {
-      out[i] = PyFloat_AsDouble(PyList_GetItem(data, i));
-   }
 
-   if ( PyErr_Occurred())
-   {
-      PyMem_Free(out);
-      out = NULL;
-   }
+/* These defaults mirror the defaults in astropy.io.fits.hdu.compressed */
+#define DEFAULT_COMPRESSION_TYPE "RICE_1"
+#define DEFAULT_QUANTIZE_LEVEL 16.0
+#define DEFAULT_HCOMP_SCALE 0
+#define DEFAULT_HCOMP_SMOOTH 0
+#define DEFAULT_BLOCK_SIZE 32
+#define DEFAULT_BYTE_PIX 4
 
-   return out;
-}
 
 /* Report any error based on the status returned from cfitsio. */
-
-void processStatusErr(int status)
+void process_status_err(int status)
 {
-   PyObject* exceptType;
-   char      errMsg[81];
-   char      defErrMsg[81];
+   PyObject* except_type;
+   char      err_msg[81];
+   char      def_err_msg[81];
 
-   errMsg[0] = '\0';
-   defErrMsg[0] = '\0';
+   err_msg[0] = '\0';
+   def_err_msg[0] = '\0';
 
    switch (status)
    {
       case MEMORY_ALLOCATION:
-         exceptType = PyExc_MemoryError;
+         except_type = PyExc_MemoryError;
          break;
       case OVERFLOW_ERR:
-         exceptType = PyExc_OverflowError;
+         except_type = PyExc_OverflowError;
          break;
       case BAD_COL_NUM:
-         strcpy(defErrMsg,"bad column number");
-         exceptType = PyExc_ValueError;
+         strcpy(def_err_msg, "bad column number");
+         except_type = PyExc_ValueError;
          break;
       case BAD_PIX_NUM:
-         strcpy(defErrMsg,"bad pixel number");
-         exceptType = PyExc_ValueError;
+         strcpy(def_err_msg, "bad pixel number");
+         except_type = PyExc_ValueError;
          break;
       case NEG_AXIS:
-         strcpy(defErrMsg,"negative axis number");
-         exceptType = PyExc_ValueError;
+         strcpy(def_err_msg, "negative axis number");
+         except_type = PyExc_ValueError;
          break;
       case BAD_DATATYPE:
-         strcpy(defErrMsg,"bad data type");
-         exceptType = PyExc_TypeError;
+         strcpy(def_err_msg, "bad data type");
+         except_type = PyExc_TypeError;
          break;
       case NO_COMPRESSED_TILE:
-         strcpy(defErrMsg,"no compressed or uncompressed data for tile.");
-         exceptType = PyExc_ValueError;
+         strcpy(def_err_msg, "no compressed or uncompressed data for tile.");
+         except_type = PyExc_ValueError;
          break;
       default:
-         exceptType = PyExc_RuntimeError;
+         except_type = PyExc_RuntimeError;
    }
 
-   if (_astropy_ffgmsg(errMsg))
+   if (fits_read_errmsg(err_msg))
    {
-      PyErr_SetString(exceptType,errMsg);
+      PyErr_SetString(except_type, err_msg);
    }
-   else if (*defErrMsg)
+   else if (*def_err_msg)
    {
-      PyErr_SetString(exceptType,defErrMsg);
+      PyErr_SetString(except_type, def_err_msg);
    }
    else
    {
-      PyErr_SetString(exceptType, "unknown error.");
+      PyErr_SetString(except_type, "unknown error.");
    }
 }
 
-/* Wrapper for the _astropy_fits_write_img() function */
-
-PyObject* compression_compressData(PyObject* self, PyObject* args)
-{
-   int             status;
-   PyObject*       naxesObj;
-   PyObject*       tileSizeObj;
-   PyObject*       zvalObj;
-   PyObject*       outList;
-   PyObject*       outScale;
-   PyObject*       outZero;
-   PyObject*       outUncompressed;
-   PyObject*       uncompressedTileDataList;
-   PyObject*       returnTuple = NULL;
-   long*           tileSize = 0;
-   long*           zval = 0;
-   int             i;
-   int             loop;
-   int             numzVals;
-   char*           compressTypeStr = "";
-   int             datatype;
-   int             bitpix;
-   int             firstelem;
-   int             naxis;
-   int             ntiles;
-   int             ii;
-   int             zblank;
-   int             cn_zblank;
-   int             cn_zscale;
-   int             cn_zzero;
-   int             cn_uncompressed;
-   double          cn_bscale;
-   double          cn_bzero;
-   double          quantize_level;
-   double          hcomp_scale;
-   long*           naxes = 0;
-   long            nelem;
-
-   FITSfile        fileParms;
-   fitsfile        theFile;
-
-   PyArrayObject*  array;
-
-   status = 0;
-
-   /* Get Python arguments */
-
-   if (!PyArg_ParseTuple(args, "O!iOOiiddiiiddOsiil:compression.compressData",
-                         &PyArray_Type, &array, &naxis, &naxesObj,
-                         &tileSizeObj, &cn_zblank, &zblank, &cn_bscale, 
-                         &cn_bzero, &cn_zscale, &cn_zzero, &cn_uncompressed,
-                         &quantize_level, &hcomp_scale, &zvalObj,
-                         &compressTypeStr, &bitpix, &firstelem, &nelem))
-   {
-      PyErr_SetString(PyExc_TypeError,"Couldn't parse agruments");
-      return NULL;
-   }
-
-   /* Determine the data type based on the bitpix value from the header */
 
-   switch (bitpix)
-   {
-      case BYTE_IMG:
-         datatype = TBYTE;
-         break;
-      case SHORT_IMG:
-         datatype = TSHORT;
-         break;
-      case LONG_IMG:
-         datatype = TINT;
-         break;
-      case LONGLONG_IMG:
-         datatype = TLONGLONG;
-         break;
-      case FLOAT_IMG:
-         datatype = TFLOAT;
-         break;
-      case DOUBLE_IMG:
-         datatype = TDOUBLE;
-         break;
-      default:
-         PyErr_SetString(PyExc_ValueError,"Invalid value for BITPIX");
-         return NULL;
+void bitpix_to_datatypes(int bitpix, int* datatype, int* npdatatype) {
+    /* Given a FITS BITPIX value, returns the appropriate CFITSIO type code and
+       Numpy type code for that BITPIX into datatype and npdatatype
+       respectively.
+     */
+    switch (bitpix) {
+        case BYTE_IMG:
+            *datatype = TBYTE;
+            *npdatatype = NPY_INT8;
+            break;
+        case SHORT_IMG:
+            *datatype = TSHORT;
+            *npdatatype = NPY_INT16;
+            break;
+        case LONG_IMG:
+            *datatype = TINT;
+            *npdatatype = NPY_INT32;
+            break;
+        case LONGLONG_IMG:
+            *datatype = TLONGLONG;
+            *npdatatype = NPY_LONGLONG;
+            break;
+        case FLOAT_IMG:
+            *datatype = TFLOAT;
+            *npdatatype = NPY_FLOAT;
+            break;
+        case DOUBLE_IMG:
+            *datatype = TDOUBLE;
+            *npdatatype = NPY_DOUBLE;
+            break;
+        default:
+            PyErr_Format(PyExc_ValueError, "Invalid value for BITPIX: %d",
+                         bitpix);
    }
 
-   /* Initialize allocated array pointers to zero so we can free them */
-   /* without allocating memory for them.                             */
-
-   theFile.Fptr = &fileParms;
-   (theFile.Fptr)->c_zscale = 0;
-   (theFile.Fptr)->c_zzero = 0;
-   (theFile.Fptr)->ucDataLen = 0;
-   (theFile.Fptr)->ucData = 0;
-   (theFile.Fptr)->dataLen = 0;
-   (theFile.Fptr)->data = 0;
-
-   /* The loop allows you to break out if there is an error */
-
-   for (loop = 0; loop == 0; loop++)
-   {
-      /* Convert the NAXISn, ZTILEn, and ZVALn lists into a C type arrays */
-
-      naxes = get_long_array(naxesObj, "ZNAXISn", NULL);
+   return;
+}
 
-      if (!naxes)
-      {
-         break;
-      }
 
-      tileSize = get_long_array(tileSizeObj, "ZTILEn", NULL);
 
-      if (!tileSize)
-      {
-         break;
-      }
+int compress_type_from_string(char* zcmptype) {
+    if (0 == strcmp(zcmptype, "RICE_1")) {
+        return RICE_1;
+    } else if (0 == strcmp(zcmptype, "GZIP_1")) {
+        return GZIP_1;
+    } else if (0 == strcmp(zcmptype, "PLIO_1")) {
+        return PLIO_1;
+    } else if (0 == strcmp(zcmptype, "HCOMPRESS_1")) {
+        return HCOMPRESS_1;
+    } else {
+        PyErr_Format(PyExc_ValueError, "Unrecognized compression type: %s",
+                     zcmptype);
+        return -1;
+    }
+}
 
-      zval = get_long_array(zvalObj, "ZVALn", &numzVals);
 
-      if (!zval)
-      {
-         break;
-      }
+// TODO: It might be possible to simplify these further by making the
+// conversion function (eg. PyString_AsString) an argument to a macro or
+// something, but I'm not sure yet how easy it is to generalize the error
+// handling
+int get_header_string(PyObject* header, char* keyword, char** val, char* def) {
+    PyObject* keystr;
+    PyObject* keyval;
+#ifdef IS_PY3K
+    PyObject* tmp;  // Temp pointer to decoded bytes object
+#endif
+    int retval;
+
+    keystr = PyString_FromString(keyword);
+    keyval = PyObject_GetItem(header, keystr);
+
+    if (keyval != NULL) {
+#ifdef IS_PY3K
+        // FITS header values should always be ASCII, but Latin1 is on the
+        // safe side
+        tmp = PyUnicode_AsLatin1String(keyval);
+        *val = PyBytes_AsString(tmp);
+        Py_DECREF(tmp);
+#else
+        *val = PyString_AsString(keyval);
+#endif
+        retval = 0;
+    }
+    else {
+        PyErr_Clear();
+        *val = def;
+        retval = 1;
+    }
+
+    Py_DECREF(keystr);
+    Py_XDECREF(keyval);
+    return retval;
+}
 
-      /* Set up the fitsfile object */
-      /* Store the compression type and compression parameters */
 
-      (theFile.Fptr)->hcomp_smooth = 0;
-      (theFile.Fptr)->rice_blocksize = 32;
-      (theFile.Fptr)->rice_bytepix = 4;
+int get_header_int(PyObject* header, char* keyword, int* val, int def) {
+    PyObject* keystr;
+    PyObject* keyval;
+    int retval;
 
-      if (strcmp(compressTypeStr, "RICE_1") == 0)
-      {
-         (theFile.Fptr)->compress_type = RICE_1;
+    keystr = PyString_FromString(keyword);
+    keyval = PyObject_GetItem(header, keystr);
 
-         if (numzVals > 0)
-         {
-            (theFile.Fptr)->rice_blocksize = zval[0];
+    if (keyval != NULL) {
+        *val = (int) PyInt_AsLong(keyval);
+        retval = 0;
+    }
+    else {
+        PyErr_Clear();
+        *val = def;
+        retval = 1;
+    }
 
-            if (numzVals > 1)
-            {
-               (theFile.Fptr)->rice_bytepix = zval[1];
- 
-            }
-         }
-      }
-      else if (strcmp(compressTypeStr, "GZIP_1") == 0)
-      {
-         (theFile.Fptr)->compress_type = GZIP_1;
-
-      }
-      else if (strcmp(compressTypeStr, "HCOMPRESS_1") == 0)
-      {
-         (theFile.Fptr)->compress_type = HCOMPRESS_1;
-
-         if (numzVals > 0)
-         {
-           (theFile.Fptr)->hcomp_smooth = zval[1];
-         }
-      }
-      else if (strcmp(compressTypeStr, "PLIO_1") == 0)
-      {
-         (theFile.Fptr)->compress_type = PLIO_1;
-
-      }
-      else
-      {
-         (theFile.Fptr)->compress_type = 0;
-      }
-
-      (theFile.Fptr)->zndim = naxis;
-      (theFile.Fptr)->maxtilelen = 1;
-      (theFile.Fptr)->zbitpix = bitpix;
-      (theFile.Fptr)->cn_zblank = cn_zblank;
-      (theFile.Fptr)->zblank = zblank;
-      (theFile.Fptr)->cn_bscale = cn_bscale;
-      (theFile.Fptr)->cn_bzero = cn_bzero;
-      (theFile.Fptr)->cn_zscale = cn_zscale;
-      (theFile.Fptr)->cn_zzero = cn_zzero;
-      (theFile.Fptr)->quantize_level = quantize_level;
-      (theFile.Fptr)->hcomp_scale = hcomp_scale;
-
-      /* Initialize arrays */
-
-      for (ii = 0; ii < MAX_COMPRESS_DIM; ii++)
-      {
-         ((theFile.Fptr)->tilesize)[ii] = 1;
-         ((theFile.Fptr)->znaxis)[ii] = 1;
-      }
-
-      ntiles = 1;
-
-      for (ii = 0; ii < naxis; ii++)
-      {
-         ((theFile.Fptr)->znaxis)[ii] = naxes[ii];
-         ((theFile.Fptr)->tilesize)[ii] = tileSize[ii];
-         (theFile.Fptr)->maxtilelen *= tileSize[ii];
-         ntiles *= (naxes[ii] - 1) / tileSize[ii] + 1;
-      }
-
-      (theFile.Fptr)->maxelem = _astropy_imcomp_calc_max_elem(
-                                 (theFile.Fptr)->compress_type,
-                                 (theFile.Fptr)->maxtilelen,
-                                 (theFile.Fptr)->zbitpix,
-                                 (theFile.Fptr)->rice_blocksize);
-
-      if (cn_zscale > 0)
-      {
-         (theFile.Fptr)->c_zscale = 
-                         (double*)PyMem_Malloc(ntiles * sizeof(double));
-         (theFile.Fptr)->c_zzero = 
-                         (double*)PyMem_Malloc(ntiles * sizeof(double));
-
-         if(!(theFile.Fptr)->c_zzero)
-         {
-            PyErr_NoMemory();
-            break;
-         }
-      }
+    Py_DECREF(keystr);
+    Py_XDECREF(keyval);
+    return retval;
+}
 
-      (theFile.Fptr)->cn_uncompressed = cn_uncompressed;
 
-      if (cn_uncompressed > 0)
-      {
-         (theFile.Fptr)->ucDataLen = 
-                          (int*)PyMem_Malloc(ntiles * sizeof(int));
-         (theFile.Fptr)->ucData =
-                          (void**)PyMem_Malloc(ntiles * sizeof(double*));
+int get_header_long(PyObject* header, char* keyword, long* val, long def) {
+    PyObject* keystr;
+    PyObject* keyval;
+    int retval;
 
-         if(!(theFile.Fptr)->ucData)
-         {
-            PyErr_NoMemory();
-            break;
-         }
-
-         for (i = 0; i < ntiles; i++)
-         {
-            (theFile.Fptr)->ucDataLen[i] = 0;
-            (theFile.Fptr)->ucData[i] = 0;
-         }
-      }
-
-      (theFile.Fptr)->dataLen = 
-                         (int*) PyMem_Malloc(ntiles * sizeof(int));
-      (theFile.Fptr)->data =
-                         (unsigned char**) PyMem_Malloc(ntiles*sizeof(char*));
-
-      if(!(theFile.Fptr)->data)
-      {
-         PyErr_NoMemory();
-         break;
-      }
-
-      for (i = 0; i < ntiles; i++)
-      {
-         (theFile.Fptr)->dataLen[i] = 0;
-         (theFile.Fptr)->data[i] = 0;
-      }
-
-      status = _astropy_fits_write_img(&theFile, datatype, firstelem,
-                                      nelem, (void*)array->data, &status);
-
-      if (status == 0)
-      {
-         outList = PyList_New(0);
-         outScale = PyList_New(0);
-         outZero = PyList_New(0);
-         outUncompressed = PyList_New(0);
-
-         for ( i = 0; i < ntiles; i++)
-         {
-            PyList_Append(outList, PyString_FromStringAndSize(
-                          (const char*)((theFile.Fptr)->data[i]),
-                          (theFile.Fptr)->dataLen[i]));
-            free((theFile.Fptr)->data[i]);
-
-            if (cn_zscale > 0)
-            {
-               PyList_Append(outScale, 
-                             PyFloat_FromDouble((theFile.Fptr)->c_zscale[i]));
-               PyList_Append(outZero, 
-                             PyFloat_FromDouble((theFile.Fptr)->c_zzero[i]));
-            }
+    keystr = PyString_FromString(keyword);
+    keyval = PyObject_GetItem(header, keystr);
 
-            if (cn_uncompressed > 0)
-            {
-               uncompressedTileDataList = PyList_New(0);
-   
-               for (ii = 0; ii < (theFile.Fptr)->ucDataLen[i]; ii++)
-               {
-                   PyList_Append(uncompressedTileDataList, 
-                   PyFloat_FromDouble(
-                               ((double**)((theFile.Fptr)->ucData))[i][ii]));
-               }
-
-               free((theFile.Fptr)->ucData[i]);
-               PyList_Append(outUncompressed, uncompressedTileDataList);
-            }
-         }
-      }
-      else
-      {
-         processStatusErr(status);
-         break;
-      }
-
-      returnTuple = PyTuple_New(5);
-      PyTuple_SetItem(returnTuple, 0, Py_BuildValue("i",status));
-      PyTuple_SetItem(returnTuple, 1, outList);
-      PyTuple_SetItem(returnTuple, 2, outScale);
-      PyTuple_SetItem(returnTuple, 3, outZero);
-      PyTuple_SetItem(returnTuple, 4, outUncompressed);
-   }
-   
-   /* Free any allocated memory */
-
-   PyMem_Free((theFile.Fptr)->dataLen);
-   PyMem_Free((theFile.Fptr)->data);
-   PyMem_Free((theFile.Fptr)->c_zscale);
-   PyMem_Free((theFile.Fptr)->c_zzero);
-   PyMem_Free((theFile.Fptr)->ucData);
-   PyMem_Free((theFile.Fptr)->ucDataLen);
-   PyMem_Free(naxes);
-   PyMem_Free(tileSize);
-   PyMem_Free(zval);
-
-   if (loop == 0)
-   {
-      /* Error has occurred */
+    if (keyval != NULL) {
+        *val = PyLong_AsLong(keyval);
+        retval = 0;
+    }
+    else {
+        PyErr_Clear();
+        *val = def;
+        retval = 1;
+    }
 
-      return NULL;
-   }
-   else
-   {
-      return returnTuple;
-   }
+    Py_DECREF(keystr);
+    Py_XDECREF(keyval);
+    return retval;
 }
 
-/* Wrapper for the _astropy_fits_read_img() function */
-
-PyObject* compression_decompressData(PyObject* self, PyObject* args)
-{
-   int             status;
-   int             nUcTiles = 0;
-   int*            inDataLen = 0;
-   int             naxis;
-   int             numzVals;
-   int*            numUncompressedVals = 0;
-   int             cn_zblank;
-   int             cn_zscale;
-   int             cn_zzero;
-   int             cn_uncompressed;
-   int             bitpix;
-   int             datatype;
-   int             firstelem;
-   int             anynul;
-   long            nelem;
-   long*           naxes = 0;
-   long*           tileSize = 0;
-   long*           zval = 0;
-   double          nulval;
-   double*         bscale;
-   double*         bzero;
-   double          quantize_level;
-   double          hcomp_scale;
-   long*           nullDVals;
-   unsigned char** inData = 0;
-   void**          uncompressedData = 0;
-   int             i;
-   int             ii;
-   char*           compressTypeStr = "";
-
-   PyObject*       inDataObj;
-   PyObject*       naxesObj;
-   PyObject*       tileSizeObj;
-   PyObject*       uncompressedDataObj;
-   PyObject*       zvalObj;
-
-   FITSfile        fileParms;
-   fitsfile        theFile;
-
-   PyArrayObject*  bscaleArray;
-   PyArrayObject*  bzeroArray;
-   PyArrayObject*  nullDvalsArray;
-   PyArrayObject*  decompDataArray;
-
-   PyArrayObject*  bscaleArray1 = 0;
-   PyArrayObject*  bzeroArray1 = 0;
-   PyArrayObject*  nullDvalsArray1 = 0;
-
-   /* Get Python arguments */
-
-   if (!PyArg_ParseTuple(args, 
-                         "OiOOO!iO!iO!iOiddOsiildO!:compression.decompressData",
-                         &inDataObj, 
-                         &naxis, &naxesObj, &tileSizeObj, &PyArray_Type, 
-                         &bscaleArray, &cn_zscale, &PyArray_Type, &bzeroArray,
-                         &cn_zzero, &PyArray_Type, &nullDvalsArray, 
-                         &cn_zblank, &uncompressedDataObj,
-                         &cn_uncompressed, &quantize_level, &hcomp_scale,
-                         &zvalObj, &compressTypeStr, &bitpix, &firstelem,
-                         &nelem, &nulval, &PyArray_Type, &decompDataArray))
-   {
-      PyErr_SetString(PyExc_TypeError,"Couldn't parse arguments");
-      return NULL;
-   }
-
-   /* Convert the input lists into C type arrays */
-
-   inData = get_char_array(inDataObj, "Compressed Data", NULL, &inDataLen);
 
-   if (!inData)
-   {
-      goto error;
-   }
+int get_header_float(PyObject* header, char* keyword, float* val,
+                     float def) {
+    PyObject* keystr;
+    PyObject* keyval;
+    int retval;
+
+    keystr = PyString_FromString(keyword);
+    keyval = PyObject_GetItem(header, keystr);
+
+    if (keyval != NULL) {
+        *val = (float) PyFloat_AsDouble(keyval);
+        retval = 0;
+    }
+    else {
+        PyErr_Clear();
+        *val = def;
+        retval = 1;
+    }
+
+    Py_DECREF(keystr);
+    Py_XDECREF(keyval);
+    return retval;
+}
 
-   naxes = get_long_array(naxesObj, "ZNAXISn", NULL);
 
-   if (!naxes)
-   {
-      goto error;
-   }
+int get_header_double(PyObject* header, char* keyword, double* val,
+                      double def) {
+    PyObject* keystr;
+    PyObject* keyval;
+    int retval;
+
+    keystr = PyString_FromString(keyword);
+    keyval = PyObject_GetItem(header, keystr);
+
+    if (keyval != NULL) {
+        *val = PyFloat_AsDouble(keyval);
+        retval = 0;
+    }
+    else {
+        PyErr_Clear();
+        *val = def;
+        retval = 1;
+    }
+
+    Py_DECREF(keystr);
+    Py_XDECREF(keyval);
+    return retval;
+}
 
-   tileSize = get_long_array(tileSizeObj, "ZTILEn", NULL);
 
-   if (!tileSize)
-   {
-      goto error;
-   }
+int get_header_longlong(PyObject* header, char* keyword, long long* val,
+                        long long def) {
+    PyObject* keystr;
+    PyObject* keyval;
+    int retval;
+
+    keystr = PyString_FromString(keyword);
+    keyval = PyObject_GetItem(header, keystr);
+
+    if (keyval != NULL) {
+        *val = PyLong_AsLongLong(keyval);
+        retval = 0;
+    }
+    else {
+        PyErr_Clear();
+        *val = def;
+        retval = 1;
+    }
+
+    Py_DECREF(keystr);
+    Py_XDECREF(keyval);
+    return retval;
+}
 
-   if (cn_zzero != 1)
-   {
-      bzero = (double*)bzeroArray->data;
-   }
-   else
-   {
-      bzeroArray1 = (PyArrayObject*)PyArray_ContiguousFromObject(
-                     (PyObject*)bzeroArray, PyArray_DOUBLE, 1, 1);
-      bzero = (double*)bzeroArray1->data;
-   }
 
-   if (cn_zscale != 1)
-   {
-      bscale = (double*)bscaleArray->data;
-   }
-   else
-   {
-      bscaleArray1 = (PyArrayObject*)PyArray_ContiguousFromObject(
-                      (PyObject*)bscaleArray, PyArray_DOUBLE, 1, 1);
-      bscale = (double*)bscaleArray1->data;
-   }
+void* compression_realloc(void* ptr, size_t size) {
+    // This realloc()-like function actually just mallocs the requested
+    // size and copies from the original memory address into the new one, and
+    // returns the newly malloc'd address.
+    // This is generally less efficient than an actual realloc(), but the
+    // problem with using realloc in this case is that when it succeeds it will
+    // free() the original memory, which may still be in use by the ndarray
+    // using that memory as its data buffer.  This seems like the least hacky
+    // way around that for now.
+    // I'm open to other ideas though.
+    void* tmp;
+    tmp = malloc(size);
+    memcpy(tmp, ptr, size);
+    return tmp;
+}
 
-   if (cn_zblank != 1)
-   {
-      nullDVals = (long*)nullDvalsArray->data;
-   }
-   else
-   {
-      nullDvalsArray1 = (PyArrayObject*)PyArray_ContiguousFromObject(
-                         (PyObject*)nullDvalsArray, PyArray_LONG, 1, 1);
-      nullDVals = (long*)nullDvalsArray1->data;
-   }
 
-   zval = get_long_array(zvalObj, "ZVALn", &numzVals);
+void tcolumns_from_header(fitsfile* fileptr, PyObject* header,
+                          tcolumn** columns) {
+    // Creates the array of tcolumn structures from the table column keywords
+    // read from the astropy.io.fits.Header object; caller is responsible for
+    // freeing the memory allocated for this array
+
+    tcolumn* column;
+    char tkw[9];
+    unsigned int idx;
+
+    int tfields;
+    char* ttype;
+    char* tform;
+    int dtcode;
+    long trepeat;
+    long twidth;
+    long long totalwidth;
+    int status = 0;
+
+    get_header_int(header, "TFIELDS", &tfields, 0);
+
+    *columns = column = PyMem_New(tcolumn, (size_t) tfields);
+    if (column == NULL) {
+        return;
+    }
+
+
+    for (idx = 1; idx <= tfields; idx++, column++) {
+        /* set some invalid defaults */
+        column->ttype[0] = '\0';
+        column->tbcol = 0;
+        column->tdatatype = -9999; /* this default used by cfitsio */
+        column->trepeat = 1;
+        column->strnull[0] = '\0';
+        column->tform[0] = '\0';
+        column->twidth = 0;
+
+        snprintf(tkw, 9, "TTYPE%u", idx);
+        get_header_string(header, tkw, &ttype, "");
+        strncpy(column->ttype, ttype, 69);
+        column->ttype[69] = '\0';
+
+        snprintf(tkw, 9, "TFORM%u", idx);
+        get_header_string(header, tkw, &tform, "");
+        strncpy(column->tform, tform, 9);
+        column->tform[9] = '\0';
+        fits_binary_tform(tform, &dtcode, &trepeat, &twidth, &status);
+        if (status != 0) {
+            process_status_err(status);
+            return;
+        }
+
+        column->tdatatype = dtcode;
+        column->trepeat = trepeat;
+        column->twidth = twidth;
+
+        snprintf(tkw, 9, "TSCAL%u", idx);
+        get_header_double(header, tkw, &(column->tscale), 1.0);
+
+        snprintf(tkw, 9, "TZERO%u", idx);
+        get_header_double(header, tkw, &(column->tzero), 0.0);
+
+        snprintf(tkw, 9, "TNULL%u", idx);
+        get_header_longlong(header, tkw, &(column->tnull), NULL_UNDEFINED);
+    }
+
+    fileptr->Fptr->tableptr = *columns;
+    fileptr->Fptr->tfield = tfields;
+
+    // This routine from CFITSIO calculates the byte offset of each column
+    // and stores it in the column->tbcol field
+    ffgtbc(fileptr, &totalwidth, &status);
+    if (status != 0) {
+        process_status_err(status);
+    }
+
+    return;
+}
 
-   if (!zval)
-   {
-      goto error;
-   }
 
-   switch (bitpix)
-   {
-      case BYTE_IMG:
-         datatype = TBYTE;
-         break;
-      case SHORT_IMG:
-         datatype = TSHORT;
-         break;
-      case LONG_IMG:
-         datatype = TINT;
-         break;
-      case LONGLONG_IMG:
-         datatype = TLONGLONG;
-         break;
-      case FLOAT_IMG:
-         datatype = TFLOAT;
 
-         if (cn_uncompressed == 1)
-         {
-            nUcTiles = PyList_Size(uncompressedDataObj);
-            uncompressedData = (void**) PyMem_Malloc(nUcTiles*sizeof(float*));
+void configure_compression(fitsfile* fileptr, PyObject* header) {
+    /* Configure the compression-related elements in the fitsfile struct
+       using values in the FITS header. */
 
-            if (!uncompressedData)
-            {
-               goto error;
-            }
+    FITSfile* Fptr;
 
-            numUncompressedVals = PyMem_Malloc(nUcTiles*sizeof(int));
+    int tfields;
+    tcolumn* columns;
 
-            if (!numUncompressedVals)
-            {
-               goto error;
-            }
+    char keyword[9];
+    char* zname;
+    int znaxis;
+    char* tmp;
 
-            for (i = 0; i < nUcTiles; i++)
-            {
-                uncompressedData[i] = 
-                       get_float_array(PyList_GetItem(uncompressedDataObj, i),
-                                       "Uncompressed Data",
-                                       &numUncompressedVals[i]);
-
-                if (!uncompressedData[i])
-                {
-                   goto error;
-                }
-            }
-         }
-         break;
-      case DOUBLE_IMG:
-         datatype = TDOUBLE;
+    unsigned int idx;
 
-         if (cn_uncompressed == 1)
-         {
-            nUcTiles = PyList_Size(uncompressedDataObj);
-            uncompressedData = (void**) PyMem_Malloc(nUcTiles*sizeof(double*));
+    Fptr = fileptr->Fptr;
+    tfields = Fptr->tfield;
+    columns = Fptr->tableptr;
 
-            if (!uncompressedData)
-            {
-               goto error;
-            }
+    // Get the ZBITPIX header value; if this is missing we're in trouble
+    if (0 != get_header_int(header, "ZBITPIX", &(Fptr->zbitpix), 0)) {
+        return;
+    }
 
-            numUncompressedVals = PyMem_Malloc(nUcTiles*sizeof(int));
+    // By default assume there is no ZBLANK column and check for ZBLANK or
+    // BLANK in the header
+    Fptr->cn_zblank = Fptr->cn_zzero = Fptr->cn_zscale = -1;
+    Fptr->cn_uncompressed = 0;
+#ifdef CFITSIO_SUPPORTS_GZIPDATA
+    Fptr->cn_gzip_data = 0;
+#endif
 
-            if (!numUncompressedVals)
-            {
-               goto error;
+    // Check for a ZBLANK, ZZERO, ZSCALE, and
+    // UNCOMPRESSED_DATA/GZIP_COMPRESSED_DATA columns in the compressed data
+    // table
+    for (idx = 0; idx < tfields; idx++) {
+        if (0 == strncmp(columns[idx].ttype, "UNCOMPRESSED_DATA", 18)) {
+            Fptr->cn_uncompressed = idx + 1;
+#ifdef CFITSIO_SUPPORTS_GZIPDATA
+        } else if (0 == strncmp(columns[idx].ttype,
+                                "GZIP_COMPRESSED_DATA", 21)) {
+            Fptr->cn_gzip_data = idx + 1;
+#endif
+        } else if (0 == strncmp(columns[idx].ttype, "ZSCALE", 7)) {
+            Fptr->cn_zscale = idx + 1;
+        } else if (0 == strncmp(columns[idx].ttype, "ZZERO", 6)) {
+            Fptr->cn_zzero = idx + 1;
+        } else if (0 == strncmp(columns[idx].ttype, "ZBLANK", 7)) {
+            Fptr->cn_zblank = idx + 1;
+        }
+    }
+
+    Fptr->zblank = 0;
+    if (Fptr->cn_zblank < 1) {
+        // No ZBLANK column--check the ZBLANK and BLANK heard keywords
+        if(0 != get_header_int(header, "ZBLANK", &(Fptr->zblank), 0)) {
+            // ZBLANK keyword not found
+            get_header_int(header, "BLANK", &(Fptr->zblank), 0);
+        }
+    }
+
+    Fptr->zscale = 1.0;
+    if (Fptr->cn_zscale < 1) {
+        if (0 != get_header_double(header, "ZSCALE", &(Fptr->zscale), 1.0)) {
+            Fptr->cn_zscale = 0;
+        }
+    }
+    Fptr->cn_bscale = Fptr->zscale;
+
+    Fptr->zzero = 0.0;
+    if (Fptr->cn_zzero < 1) {
+        if (0 != get_header_double(header, "ZZERO", &(Fptr->zzero), 0.0)) {
+            Fptr->cn_zzero = 0;
+        }
+    }
+    Fptr->cn_bzero = Fptr->zzero;
+
+    get_header_string(header, "ZCMPTYPE", &tmp, DEFAULT_COMPRESSION_TYPE);
+    strncpy(Fptr->zcmptype, tmp, 11);
+    Fptr->zcmptype[strlen(tmp)] = '\0';
+
+    Fptr->compress_type = compress_type_from_string(Fptr->zcmptype);
+    if (PyErr_Occurred()) {
+        return;
+    }
+
+    get_header_int(header, "ZNAXIS", &znaxis, 0);
+    Fptr->zndim = znaxis;
+
+    if (znaxis > MAX_COMPRESS_DIM) {
+        // The CFITSIO compression code currently only supports up to 6
+        // dimensions by default.
+        znaxis = MAX_COMPRESS_DIM;
+    }
+
+    Fptr->maxtilelen = 1;
+    for (idx = 1; idx <= znaxis; idx++) {
+        snprintf(keyword, 9, "ZNAXIS%u", idx);
+        get_header_long(header, keyword, Fptr->znaxis + idx - 1, 0);
+        snprintf(keyword, 9, "ZTILE%u", idx);
+        get_header_long(header, keyword, Fptr->tilesize + idx - 1, 0);
+        Fptr->maxtilelen *= Fptr->tilesize[idx - 1];
+    }
+
+    // Set some more default compression options
+    Fptr->rice_blocksize = DEFAULT_BLOCK_SIZE;
+    Fptr->rice_bytepix = DEFAULT_BYTE_PIX;
+    Fptr->quantize_level = DEFAULT_QUANTIZE_LEVEL;
+    Fptr->hcomp_smooth = DEFAULT_HCOMP_SMOOTH;
+    Fptr->hcomp_scale = DEFAULT_HCOMP_SCALE;
+
+    // Now process the ZVALn keywords
+    idx = 1;
+    while (1) {
+        snprintf(keyword, 9, "ZNAME%u", idx);
+        // Assumes there are no gaps in the ZNAMEn keywords; this same
+        // assumption was made in the Python code.  This could be done slightly
+        // more flexibly by using a wildcard slice of the header
+        if (0 != get_header_string(header, keyword, &zname, "")) {
+            break;
+        }
+        snprintf(keyword, 9, "ZVAL%u", idx);
+        if (Fptr->compress_type == RICE_1) {
+            if (0 == strcmp(zname, "BLOCKSIZE")) {
+                get_header_int(header, keyword, &(Fptr->rice_blocksize),
+                               DEFAULT_BLOCK_SIZE);
+            } else if (0 == strcmp(zname, "BYTEPIX")) {
+                get_header_int(header, keyword, &(Fptr->rice_bytepix),
+                               DEFAULT_BYTE_PIX);
             }
-
-            for (i = 0; i < nUcTiles; i++)
-            {
-                uncompressedData[i] = 
-                       get_double_array(PyList_GetItem(uncompressedDataObj, i),
-                                        "Uncompressed Data",
-                                        &numUncompressedVals[i]);
-
-                if (!uncompressedData[i])
-                {
-                   goto error;
-                }
+        } else if (Fptr->compress_type == HCOMPRESS_1) {
+            if (0 == strcmp(zname, "SMOOTH")) {
+                get_header_int(header, keyword, &(Fptr->hcomp_smooth),
+                               DEFAULT_HCOMP_SMOOTH);
+            } else if (0 == strcmp(zname, "SCALE")) {
+                get_header_float(header, keyword, &(Fptr->hcomp_scale),
+                                 DEFAULT_HCOMP_SCALE);
             }
-         }
-         break;
-      default:
-         PyErr_SetString(PyExc_ValueError,"Invalid value for BITPIX");
-         return NULL;
-   }
-
-   /* Set up the fitsfile object */
-
-   theFile.Fptr = &fileParms;
-
-   (theFile.Fptr)->rice_blocksize = 32;
-   (theFile.Fptr)->hcomp_smooth = 0;
-   (theFile.Fptr)->rice_bytepix = 4;
-
-   if (strcmp(compressTypeStr, "RICE_1") == 0)
-   {
-      (theFile.Fptr)->compress_type = RICE_1;
-
-      if (numzVals > 0)
-      {
-         (theFile.Fptr)->rice_blocksize = zval[0];
+        } else if (Fptr->zbitpix < 0 && 0 == strcmp(zname, "NOISEBIT")) {
+             get_header_float(header, keyword, &(Fptr->quantize_level),
+                              DEFAULT_QUANTIZE_LEVEL);
+        }
+
+        idx++;
+    }
+
+
+    Fptr->compressimg = 1;
+    Fptr->maxelem = imcomp_calc_max_elem(Fptr->compress_type,
+                                         Fptr->maxtilelen,
+                                         Fptr->zbitpix,
+                                         Fptr->rice_blocksize);
+    Fptr->cn_compressed = 1;
+    return;
+}
 
-         if (numzVals > 1)
-         {
-            (theFile.Fptr)->rice_bytepix = zval[1];
-         }
-      }
-   }
-   else if (strcmp(compressTypeStr, "GZIP_1") == 0)
-   {
-      (theFile.Fptr)->compress_type = GZIP_1;
-   }
-   else if (strcmp(compressTypeStr, "HCOMPRESS_1") == 0)
-   {
-      (theFile.Fptr)->compress_type = HCOMPRESS_1;
 
-      if (numzVals > 0)
-      {
-        (theFile.Fptr)->hcomp_smooth = zval[1];
-      }
-   }
-   else if (strcmp(compressTypeStr, "PLIO_1") == 0)
-   {
-      (theFile.Fptr)->compress_type = PLIO_1;
-   }
-   else
-   {
-      (theFile.Fptr)->compress_type = 0;
-   }
+void open_from_hdu(fitsfile** fileptr, void** buf, size_t* bufsize,
+                   PyObject* hdu, tcolumn* columns) {
+    PyObject* header = NULL;
+    PyArrayObject* data = NULL;
+    PyArrayObject* base;
+    PyArrayObject* tmp;
+    FITSfile* Fptr;
+
+    int status = 0;
+    long long rowlen;
+    long long nrows;
+    long long heapsize;
+    long long theap;
+
+    header = PyObject_GetAttrString(hdu, "_header");
+    if (header == NULL) {
+        goto fail;
+    }
+
+    data = (PyArrayObject*) PyObject_GetAttrString(hdu, "compData");
+    if (data == NULL) {
+        goto fail;
+    }
+
+
+    get_header_longlong(header, "NAXIS1", &rowlen, 0);
+    get_header_longlong(header, "NAXIS2", &nrows, 0);
+
+    // The PCOUNT keyword contains the number of bytes in the table heap
+    get_header_longlong(header, "PCOUNT", &heapsize, 0);
+
+    // The THEAP keyword gives the offset of the heap from the beginning of
+    // the HDU data portion; normally this offset is 0 but it can be set
+    // to something else with THEAP
+    get_header_longlong(header, "THEAP", &theap, 0);
+
+
+    // Walk the array data bases until we find the lowest ndarray base; for
+    // CompImageHDUs there should always be at least one contiguous byte array
+    // allocated for the table and its heap
+    if (!PyObject_TypeCheck(data, &PyArray_Type)) {
+        PyErr_SetString(PyExc_TypeError,
+                        "CompImageHDU.compData must be a numpy.ndarray");
+        goto fail;
+    }
+
+    tmp = base = data;
+    while (PyObject_TypeCheck((PyObject*) tmp, &PyArray_Type)) {
+        base = tmp;
+        *bufsize = (size_t) PyArray_NBYTES(base);
+        tmp = (PyArrayObject*) PyArray_BASE(base);
+        if (tmp == NULL) {
+            break;
+        }
+    }
+
+    *buf = PyArray_DATA(base);
+
+    fits_create_memfile(fileptr, buf, bufsize, 0, compression_realloc,
+                        &status);
+    if (status != 0) {
+        process_status_err(status);
+        goto fail;
+    }
+
+    Fptr = (*fileptr)->Fptr;
+
+    // Now we have some fun munging some of the elements in the fitsfile struct
+    Fptr->open_count = 1;
+    Fptr->hdutype = BINARY_TBL;  /* This is a binary table HDU */
+    Fptr->lasthdu = 1;
+    Fptr->headstart[0] = 0;
+    Fptr->headend = 0;
+    Fptr->datastart = 0;  /* There is no header, data starts at 0 */
+    Fptr->origrows = Fptr->numrows = nrows;
+    Fptr->rowlength = rowlen;
+    if (theap != 0) {
+        Fptr->heapstart = theap;
+    } else {
+        Fptr->heapstart = rowlen * nrows;
+    }
+
+    Fptr->heapsize = heapsize;
+
+    // Configure the array of table column structs from the Astropy header
+    // instead of allowing CFITSIO to try to read from the header
+    tcolumns_from_header(*fileptr, header, &columns);
+    if (PyErr_Occurred()) {
+        goto fail;
+    }
+
+    // If any errors occur in this function they'll bubble up from here to
+    // compression_decompress_hdu
+    configure_compression(*fileptr, header);
+
+fail:
+    Py_XDECREF(header);
+    Py_XDECREF(data);
+    return;
+}
 
-   (theFile.Fptr)->zndim = naxis;
-   (theFile.Fptr)->maxtilelen = 1;
-   (theFile.Fptr)->zbitpix = bitpix;
-   (theFile.Fptr)->data = inData;
-   (theFile.Fptr)->dataLen = inDataLen;
 
-   (theFile.Fptr)->bscale = bscale;
-   (theFile.Fptr)->cn_zscale = cn_zscale;
-   (theFile.Fptr)->quantize_level = quantize_level;
-   (theFile.Fptr)->hcomp_scale = hcomp_scale;
 
-   if (cn_zscale == -1)
-   {
-      (theFile.Fptr)->zscale = bscale[0];
-      (theFile.Fptr)->cn_bscale = bscale[0];
-   }
-   else
-   {
-      (theFile.Fptr)->zscale = 1.0;
-      (theFile.Fptr)->cn_bscale = 1.0;
-   }
+PyObject* compression_compress_hdu(PyObject* self, PyObject* args)
+{
+    PyObject* hdu;
+    PyObject* retval = NULL;
+    tcolumn* columns = NULL;
+
+    void* orig_outbuf;
+    size_t orig_outbufsize;
+    void* outbuf;
+    size_t outbufsize;
+
+    PyArrayObject* indata;
+    PyArrayObject* tmp;
+    long znaxis;
+    int datatype;
+    int npdatatype;
+    unsigned long long heapsize;
+
+    fitsfile* fileptr;
+    int status = 0;
+
+    if (!PyArg_ParseTuple(args, "O:compression.compress_hdu", &hdu))
+    {
+        PyErr_SetString(PyExc_TypeError, "Couldn't parse arguments");
+        return NULL;
+    }
+
+    // For HDU compression never use CFITSIO to write directly to the file;
+    // although there's nothing wrong with CFITSIO, right now that would cause
+    // too much confusion to Astropy's internal book keeping.
+    // We just need to get the compressed bytes and Astropy will handle the
+    // writing of them.
+    open_from_hdu(&fileptr, &outbuf, &outbufsize, hdu, columns);
+    if (PyErr_Occurred()) {
+        return NULL;
+    }
+    orig_outbuf = outbuf;
+    orig_outbufsize = outbufsize;
+
+    bitpix_to_datatypes(fileptr->Fptr->zbitpix, &datatype, &npdatatype);
+    if (PyErr_Occurred()) {
+        return NULL;
+    }
+
+    indata = (PyArrayObject*) PyObject_GetAttrString(hdu, "data");
+
+    fits_write_img(fileptr, datatype, 1, PyArray_SIZE(indata), indata->data,
+                   &status);
+    if (status != 0) {
+        process_status_err(status);
+        goto fail;
+    }
+
+    fits_flush_buffer(fileptr, 1, &status);
+    if (status != 0) {
+        process_status_err(status);
+        goto fail;
+    }
+
+    // It's possible that between calls to fits_write_img and fits_flush_buffer
+    // the size of the output buffer was insufficient and the buffer had to be
+    // reallocated.  The address and size of the new buffer should be in
+    // outbuf and outbufsize.  We need to create a new PyArrayObject using the
+    // new buffer and size
+    if (orig_outbuf != outbuf || orig_outbufsize != outbufsize) {
+        // It's possible, albeit unlikely, that realloc can return a block of
+        // memory with the same address but different size.
+        znaxis = (long) outbufsize;  // The output array is just one dimension.
+        tmp = (PyArrayObject*) PyArray_SimpleNewFromData(1, &znaxis, NPY_UBYTE,
+                                                         outbuf);
+        PyObject_SetAttrString(hdu, "compData", (PyObject*) tmp);
+        Py_DECREF(tmp);
+    }
+
+    heapsize = (unsigned long long) fileptr->Fptr->heapsize;
+
+    retval = PyLong_FromUnsignedLongLong(heapsize);
+
+fail:
+    if (fileptr != NULL) {
+        status = 1; // Disable header-related errors
+        fits_close_file(fileptr, &status);
+        if (status != 1) {
+            process_status_err(status);
+            retval = NULL;
+        }
+    }
+
+    if (columns != NULL) {
+        PyMem_Free(columns);
+    }
+    Py_XDECREF(indata);
+
+    // Clear any messages remaining in CFITSIO's error stack
+    fits_clear_errmsg();
+
+    return retval;
+}
 
-   (theFile.Fptr)->bzero = bzero;
-   (theFile.Fptr)->cn_zzero = cn_zzero;
 
-   if (cn_zzero == -1)
-   {
-      (theFile.Fptr)->zzero = bzero[0];
-      (theFile.Fptr)->cn_bzero = bzero[0];
-   }
-   else
-   {
-      (theFile.Fptr)->zzero = 0.0;
-      (theFile.Fptr)->cn_bzero = 0.0;
-   }
+PyObject* compression_decompress_hdu(PyObject* self, PyObject* args)
+{
+    PyObject* hdu;
+    tcolumn* columns = NULL;
+
+    void* inbuf;
+    size_t inbufsize;
+
+    PyArrayObject* outdata;
+    int datatype;
+    int npdatatype;
+    int zndim;
+    long* znaxis;
+    long arrsize;
+    unsigned int idx;
+
+    fitsfile* fileptr;
+    int anynul = 0;
+    int status = 0;
+
+    if (!PyArg_ParseTuple(args, "O:compression.decompress_hdu", &hdu))
+    {
+        PyErr_SetString(PyExc_TypeError, "Couldn't parse arguments");
+        return NULL;
+    }
+
+    open_from_hdu(&fileptr, &inbuf, &inbufsize, hdu, columns);
+    if (PyErr_Occurred()) {
+        return NULL;
+    }
+
+    bitpix_to_datatypes(fileptr->Fptr->zbitpix, &datatype, &npdatatype);
+    if (PyErr_Occurred()) {
+        return NULL;
+    }
+
+    zndim = fileptr->Fptr->zndim;
+    znaxis = (long*) PyMem_Malloc(sizeof(long) * zndim);
+    arrsize = 1;
+    for (idx = 0; idx < zndim; idx++) {
+        znaxis[zndim - idx - 1] = fileptr->Fptr->znaxis[idx];
+        arrsize *= fileptr->Fptr->znaxis[idx];
+    }
+
+    /* Create and allocate a new array for the decompressed data */
+    outdata = (PyArrayObject*) PyArray_SimpleNew(zndim, znaxis, npdatatype);
+
+    fits_read_img(fileptr, datatype, 1, arrsize, NULL, outdata->data, &anynul,
+                  &status);
+    if (status != 0) {
+        process_status_err(status);
+        outdata = NULL;
+        goto fail;
+    }
+
+fail:
+    if (fileptr != NULL) {
+        status = 1;// Disable header-related errors
+        fits_close_file(fileptr, &status);
+        if (status != 1) {
+            process_status_err(status);
+            outdata = NULL;
+        }
+    }
+
+    if (columns != NULL) {
+        PyMem_Free(columns);
+    }
+    PyMem_Free(znaxis);
+
+    // Clear any messages remaining in CFITSIO's error stack
+    fits_clear_errmsg();
+
+    return (PyObject*) outdata;
+}
 
-   (theFile.Fptr)->blank = nullDVals;
-   (theFile.Fptr)->cn_zblank = cn_zblank;
 
-   if (cn_zblank == -1)
-   {
-      (theFile.Fptr)->zblank = nullDVals[0];
-   }
-   else
-   {
-      (theFile.Fptr)->zblank = 0;
-   }
+PyObject* compression_calc_max_elem(PyObject* self, PyObject* args) {
+    char* zcmptype;
+    long maxtilelen;
+    int zbitpix;
+    int rice_blocksize;
 
-   /* Initialize arrays */
+    if (!PyArg_ParseTuple(args, "slii:compression.calc_max_elem", &zcmptype,
+                          &maxtilelen, &zbitpix, &rice_blocksize)) {
+        PyErr_SetString(PyExc_TypeError, "Couldn't parse arguments");
+        return NULL;
+    }
 
-   for (ii = 0; ii < MAX_COMPRESS_DIM; ii++)
-   {
-      ((theFile.Fptr)->tilesize)[ii] = 1;
-      ((theFile.Fptr)->znaxis)[ii] = 1;
-   }
+    return PyLong_FromLong(
+        (long) imcomp_calc_max_elem(compress_type_from_string(zcmptype),
+                                    maxtilelen, zbitpix, rice_blocksize));
+}
 
-   for (ii = 0; ii < naxis; ii++)
-   {
-      ((theFile.Fptr)->znaxis)[ii] = naxes[ii];
-      ((theFile.Fptr)->tilesize)[ii] = tileSize[ii];
-      (theFile.Fptr)->maxtilelen *= tileSize[ii];
-   }
 
-   (theFile.Fptr)->cn_uncompressed = cn_uncompressed;
+/* CFITSIO version float as returned by fits_get_version() */
+static double cfitsio_version;
 
-   if (cn_uncompressed == 1)
-   {
-       (theFile.Fptr)->ucData = uncompressedData;
-       (theFile.Fptr)->ucDataLen = numUncompressedVals;
-   }
 
-   /* Call the C function */
+void compression_module_init(PyObject* module) {
+    /* Python version-indendependent initialization routine for the
+       compression module */
+    PyObject* tmp;
+    float version_tmp;
 
-   status = 0;
-   status = _astropy_fits_read_img(&theFile, datatype, firstelem,
-                                  nelem, &nulval, decompDataArray->data,
-                                  &anynul, &status);
+    fits_get_version(&version_tmp);
+    cfitsio_version = (double) version_tmp;
+    /* The conversion to double can lead to some rounding errors; round to the
+       nearest 3 decimal places, which should be accurate for any past or
+       current CFITSIO version. This is why relying on floats for version
+       comparison isn't generally a bright idea... */
+    cfitsio_version = floor((1000 * version_tmp + 0.5)) / 1000;
 
-   if (status != 0)
-   {
-      processStatusErr(status);
-   }
+    tmp = PyFloat_FromDouble(cfitsio_version);
+    PyObject_SetAttrString(module, "CFITSIO_VERSION", tmp);
+    Py_XDECREF(tmp);
 
-   error:
-      PyMem_Free(inData);
-      PyMem_Free(inDataLen);
-      PyMem_Free(naxes);
-      PyMem_Free(tileSize);
-      PyMem_Free(zval);
-
-      if (cn_uncompressed == 1)
-      {
-         for (i = 0; i < nUcTiles; i++)
-         {
-             PyMem_Free(uncompressedData[i]);
-         }
-
-         PyMem_Free(uncompressedData);
-         PyMem_Free(numUncompressedVals);
-      }
-
-      if (bscaleArray1 != 0)
-      {
-         Py_DECREF(bscaleArray1);
-      }
-
-      if (bzeroArray1 != 0)
-      {
-         Py_DECREF(bzeroArray1);
-      }
-
-      if (nullDvalsArray1 != 0)
-      {
-         Py_DECREF(nullDvalsArray1);
-      }
-   
-      if (status != 0)
-      {
-         return NULL;
-      }
-      else
-      {
-         return Py_BuildValue("i",status);
-      }
+    return;
 }
 
 
 /* Method table mapping names to wrappers */
 static PyMethodDef compression_methods[] =
 {
-   {"decompressData", compression_decompressData, METH_VARARGS},
-   {"compressData", compression_compressData, METH_VARARGS},
-   {NULL,NULL}
+   {"compress_hdu", compression_compress_hdu, METH_VARARGS},
+   {"decompress_hdu", compression_decompress_hdu, METH_VARARGS},
+   {"calc_max_elem", compression_calc_max_elem, METH_VARARGS},
+   {NULL, NULL}
 };
 
-#if PY_MAJOR_VERSION >=3
+#ifdef IS_PY3K
 static struct PyModuleDef compressionmodule = {
     PyModuleDef_HEAD_INIT,
     "compression",
@@ -1152,15 +1000,24 @@ static struct PyModuleDef compressionmodule = {
 PyObject *
 PyInit_compression(void)
 {
-    PyObject *module = PyModule_Create(&compressionmodule);
+    PyObject* module = PyModule_Create(&compressionmodule);
+    compression_module_init(module);
+
+    /* Needed to use Numpy routines */
+    /* Note -- import_array() is a macro that behaves differently in Python2.x
+     * vs. Python 3. See the discussion at:
+     * https://groups.google.com/d/topic/astropy-dev/6_AesAsCauM/discussion
+     */
     import_array();
     return module;
 }
 #else
 PyMODINIT_FUNC initcompression(void)
 {
-   Py_InitModule4("compression", compression_methods, "compression module",
-                  NULL, PYTHON_API_VERSION);
+   PyObject* module = Py_InitModule4("compression", compression_methods,
+                                     "astropy.io.fits.compression module",
+                                     NULL, PYTHON_API_VERSION);
+   compression_module_init(module);
    import_array();
 }
 #endif
diff --git a/astropy/io/fits/src/compressionmodule.h b/astropy/io/fits/src/compressionmodule.h
new file mode 100644
index 0000000..a8a7c2d
--- /dev/null
+++ b/astropy/io/fits/src/compressionmodule.h
@@ -0,0 +1,53 @@
+#ifndef _COMPRESSIONMODULE_H
+#define _COMPRESSIONMODULE_H
+
+/* Some defines for Python3 support--bytes objects should be used where */
+/* strings were previously used                                         */
+#if PY_MAJOR_VERSION >= 3
+#define IS_PY3K
+#endif
+
+#ifdef IS_PY3K
+#define PyString_FromString PyUnicode_FromString
+#define PyInt_AsLong PyLong_AsLong
+#endif
+
+
+/* CFITSIO version-specific feature support */
+#ifndef CFITSIO_MAJOR
+    // Define a minimized version
+    #define CFITSIO_MAJOR 0
+    #ifdef _MSC_VER
+        #pragma warning ( "CFITSIO_MAJOR not defined; your CFITSIO version may be too old; compile at your own risk" )
+    #else
+        #warning "CFITSIO_MAJOR not defined; your CFITSIO version may be too old; compile at your own risk"
+    #endif
+#endif
+
+#ifndef CFITSIO_MINOR
+    #define CFITSIO_MINOR 0
+#endif
+
+
+#if CFITSIO_MAJOR >= 3
+    #if CFITSIO_MINOR >= 28
+        #define CFITSIO_SUPPORTS_GZIPDATA
+    #else
+        #ifdef _MSC_VER
+            #pragma warning ( "GZIP_COMPRESSED_DATA columns not supported" )
+        #else
+            #warning "GZIP_COMPRESSED_DATA columns not supported"
+        #endif
+    #endif
+#endif
+
+
+/* These defaults mirror the defaults in pyfits.hdu.compressed */
+#define DEFAULT_COMPRESSION_TYPE "RICE_1"
+#define DEFAULT_QUANTIZE_LEVEL 16.0
+#define DEFAULT_HCOMP_SCALE 0
+#define DEFAULT_HCOMP_SMOOTH 0
+#define DEFAULT_BLOCK_SIZE 32
+#define DEFAULT_BYTE_PIX 4
+
+#endif
diff --git a/astropy/io/fits/src/crc32.h b/astropy/io/fits/src/crc32.h
deleted file mode 100644
index 1d72ad2..0000000
--- a/astropy/io/fits/src/crc32.h
+++ /dev/null
@@ -1,514 +0,0 @@
-/* $Id$
-*/
-
-/*****************************************************************************/
-/*                                                                           */
-/* This file, zlib.h, contains the include information required to compress  */
-/* and uncompress data using the GZIP_1 compression format.                  */
-/*                                                                           */
-/* Copyright (C) 2004 Association of Universities for Research in Astronomy  */
-/* (AURA)                                                                    */
-/*                                                                           */
-/* Redistribution and use in source and binary forms, with or without        */
-/* modification, are permitted provided that the following conditions are    */
-/* met:                                                                      */
-/*                                                                           */
-/*    1. Redistributions of source code must retain the above copyright      */
-/*      notice, this list of conditions and the following disclaimer.        */
-/*                                                                           */
-/*    2. Redistributions in binary form must reproduce the above             */
-/*      copyright notice, this list of conditions and the following          */
-/*      disclaimer in the documentation and/or other materials provided      */
-/*      with the distribution.                                               */
-/*                                                                           */
-/*    3. The name of AURA and its representatives may not be used to         */
-/*      endorse or promote products derived from this software without       */
-/*      specific prior written permission.                                   */
-/*                                                                           */
-/* THIS SOFTWARE IS PROVIDED BY AURA ``AS IS'' AND ANY EXPRESS OR IMPLIED    */
-/* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF      */
-/* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE                  */
-/* DISCLAIMED. IN NO EVENT SHALL AURA BE LIABLE FOR ANY DIRECT, INDIRECT,    */
-/* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,      */
-/* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS     */
-/* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND    */
-/* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR     */
-/* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE    */
-/* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH          */
-/* DAMAGE.                                                                   */
-/*                                                                           */
-/* This code was copied and heavily modified from the ZLIB compression       */
-/* library that was written by Jean-loup Gailly and Mark Adler.  That        */
-/* software containes the following copyright and warranty notices:          */
-/*                                                                           */
-/*  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 at gzip.org          madler at 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).              */
-/*                                                                           */
-/*****************************************************************************/
-
-/* This code was copied unmodified from ZLIB crc32.h -- tables for rapid CRC */
-/* calculation                                                               */
-
-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
-  }
-};
diff --git a/astropy/io/fits/src/deflate.h b/astropy/io/fits/src/deflate.h
deleted file mode 100644
index bfd3e8c..0000000
--- a/astropy/io/fits/src/deflate.h
+++ /dev/null
@@ -1,399 +0,0 @@
-/* $Id$
-*/
-
-/*****************************************************************************/
-/*                                                                           */
-/* This file, zlib.h, contains the include information required to compress  */
-/* and uncompress data using the GZIP_1 compression format.                  */
-/*                                                                           */
-/* Copyright (C) 2004 Association of Universities for Research in Astronomy  */
-/* (AURA)                                                                    */
-/*                                                                           */
-/* Redistribution and use in source and binary forms, with or without        */
-/* modification, are permitted provided that the following conditions are    */
-/* met:                                                                      */
-/*                                                                           */
-/*    1. Redistributions of source code must retain the above copyright      */
-/*      notice, this list of conditions and the following disclaimer.        */
-/*                                                                           */
-/*    2. Redistributions in binary form must reproduce the above             */
-/*      copyright notice, this list of conditions and the following          */
-/*      disclaimer in the documentation and/or other materials provided      */
-/*      with the distribution.                                               */
-/*                                                                           */
-/*    3. The name of AURA and its representatives may not be used to         */
-/*      endorse or promote products derived from this software without       */
-/*      specific prior written permission.                                   */
-/*                                                                           */
-/* THIS SOFTWARE IS PROVIDED BY AURA ``AS IS'' AND ANY EXPRESS OR IMPLIED    */
-/* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF      */
-/* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE                  */
-/* DISCLAIMED. IN NO EVENT SHALL AURA BE LIABLE FOR ANY DIRECT, INDIRECT,    */
-/* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,      */
-/* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS     */
-/* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND    */
-/* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR     */
-/* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE    */
-/* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH          */
-/* DAMAGE.                                                                   */
-/*                                                                           */
-/* This code was copied and heavily modified from the ZLIB compression       */
-/* library that was written by Jean-loup Gailly and Mark Adler.  That        */
-/* software containes the following copyright and warranty notices:          */
-/*                                                                           */
-/*  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 at gzip.org          madler at 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).              */
-/*                                                                           */
-/*****************************************************************************/
-
-/* This code was copied unmodified from ZLIB deflate.h -- internal           */
-/* compression state                                                         */
-
-#ifndef DEFLATE_H
-#define DEFLATE_H
-
-#include "zutil.h"
-
-/* ===========================================================================
- * 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 */
diff --git a/astropy/io/fits/src/fits_hcompress.c b/astropy/io/fits/src/fits_hcompress.c
deleted file mode 100644
index 4b01b27..0000000
--- a/astropy/io/fits/src/fits_hcompress.c
+++ /dev/null
@@ -1,1851 +0,0 @@
-/* $Id$
-*/
-
-/*****************************************************************************/
-/*                                                                           */
-/* This file, fits_hcompress.c, contains the code required to compress       */
-/* data using the HCOMPRESS_1 compression format.                            */
-/*                                                                           */
-/* Copyright (C) 2004 Association of Universities for Research in Astronomy  */
-/* (AURA)                                                                    */
-/*                                                                           */
-/* Redistribution and use in source and binary forms, with or without        */
-/* modification, are permitted provided that the following conditions are    */
-/* met:                                                                      */
-/*                                                                           */
-/*    1. Redistributions of source code must retain the above copyright      */
-/*      notice, this list of conditions and the following disclaimer.        */
-/*                                                                           */
-/*    2. Redistributions in binary form must reproduce the above             */
-/*      copyright notice, this list of conditions and the following          */
-/*      disclaimer in the documentation and/or other materials provided      */
-/*      with the distribution.                                               */
-/*                                                                           */
-/*    3. The name of AURA and its representatives may not be used to         */
-/*      endorse or promote products derived from this software without       */
-/*      specific prior written permission.                                   */
-/*                                                                           */
-/* THIS SOFTWARE IS PROVIDED BY AURA ``AS IS'' AND ANY EXPRESS OR IMPLIED    */
-/* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF      */
-/* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE                  */
-/* DISCLAIMED. IN NO EVENT SHALL AURA BE LIABLE FOR ANY DIRECT, INDIRECT,    */
-/* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,      */
-/* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS     */
-/* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND    */
-/* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR     */
-/* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE    */
-/* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH          */
-/* DAMAGE.                                                                   */
-/*                                                                           */
-/* This file was copied intact from the FITSIO software that was written by  */
-/* William Pence at the High Energy Astrophysic Science Archive Research     */
-/* Center (HEASARC) at the NASA Goddard Space Flight Center.  That software  */
-/* contained the following copyright and warranty notices:                   */
-/*                                                                           */
-/* 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."                                             */
-/*                                                                           */
-/*****************************************************************************/
-
-/*  #########################################################################
-These routines to apply the H-compress compression algorithm to a 2-D Fits
-image were written by R. White at the STScI and were obtained from the STScI at
-http://www.stsci.edu/software/hcompress.html
-
-This source file is a concatination of the following sources files in the
-original distribution 
- htrans.c 
- digitize.c 
- encode.c 
- qwrite.c 
- doencode.c 
- bit_output.c 
- qtree_encode.c
-
-The following modifications have been made to the original code:
-
-  - commented out redundant "include" statements
-  - added the noutchar global variable 
-  - changed all the 'extern' declarations to 'static', since all the routines are in
-    the same source file
-  - changed the first parameter in encode (and in lower level routines from a file stream
-    to a char array
-  - modifid the encode routine to return the size of the compressed array of bytes
-  - changed calls to printf and perror to call the CFITSIO ffpmsg routine
-  - modified the mywrite routine, and lower level byte writing routines,  to copy 
-    the output bytes to a char array, instead of writing them to a file stream
-  - replace "exit" statements with "return" statements
-  - changed the function declarations to the more modern ANSI C style
-
- ############################################################################  */
- 
-#include <stdio.h>
-#include <string.h>
-#include <math.h>
-#include <stdlib.h>
-#include "fitsio.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 _astropy_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 */
-
-  noutmax = *nbytes;  /* input value is the allocated size of the array */
-  *nbytes = 0;  /* reset */
-
-  stat = encode(output, nbytes, a, nx, ny, scale);
-
-  *status = stat;
-  return(*status);
-}
-/* ---------------------------------------------------------------------- */
-int _astropy_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 */
-  noutmax = *nbytes;  /* input value is the allocated size of the array */
-  *nbytes = 0;  /* reset */
-
-  stat = encode64(output, nbytes, a, nx, ny, scale);
-
-  *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<<log2n) ) {
-		log2n += 1;
-	}
-	/*
-	 * get temporary storage for shuffling elements
-	 */
-	tmp = (int *) malloc(((nmax+1)/2)*sizeof(int));
-	if(tmp == (int *) NULL) {
-	        _astropy_ffpmsg("htrans: insufficient memory");
-		return(DATA_COMPRESSION_ERR);
-	}
-	/*
-	 * set up rounding and shifting masks
-	 */
-	shift = 0;
-	mask  = -2;
-	mask2 = mask << 1;
-	prnd  = 1;
-	prnd2 = prnd << 1;
-	nrnd2 = prnd2 - 1;
-	/*
-	 * do log2n reductions
-	 *
-	 * We're indexing a as a 2-D array with dimensions (nx,ny).
-	 */
-	nxtop = nx;
-	nytop = ny;
-
-	for (k = 0; k<log2n; k++) {
-		oddx = nxtop % 2;
-		oddy = nytop % 2;
-		for (i = 0; i<nxtop-oddx; i += 2) {
-			s00 = i*ny;				/* s00 is index of a[i,j]	*/
-			s10 = s00+ny;			/* s10 is index of a[i+1,j]	*/
-			for (j = 0; j<nytop-oddy; j += 2) {
-				/*
-				 * Divide h0,hx,hy,hc by 2 (1 the first time through).
-				 */
-				h0 = (a[s10+1] + a[s10] + a[s00+1] + a[s00]) >> 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<nytop-oddy; j += 2) {
-				h0 = (a[s00+1] + a[s00]) << (1-shift);
-				hy = (a[s00+1] - a[s00]) << (1-shift);
-				a[s00+1] = ( (hy>=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<nxtop; i++) {
-			shuffle(&a[ny*i],nytop,1,tmp);
-		}
-		for (j = 0; j<nytop; j++) {
-			shuffle(&a[j],nxtop,ny,tmp);
-		}
-		/*
-		 * image size reduced by 2 (round up if odd)
-		 */
-		nxtop = (nxtop+1)>>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<<log2n) ) {
-		log2n += 1;
-	}
-	/*
-	 * get temporary storage for shuffling elements
-	 */
-	tmp = (LONGLONG *) malloc(((nmax+1)/2)*sizeof(LONGLONG));
-	if(tmp == (LONGLONG *) NULL) {
-	        _astropy_ffpmsg("htrans64: insufficient memory");
-		return(DATA_COMPRESSION_ERR);
-	}
-	/*
-	 * set up rounding and shifting masks
-	 */
-	shift = 0;
-	mask  = (LONGLONG) -2;
-	mask2 = mask << 1;
-	prnd  = (LONGLONG) 1;
-	prnd2 = prnd << 1;
-	nrnd2 = prnd2 - 1;
-	/*
-	 * do log2n reductions
-	 *
-	 * We're indexing a as a 2-D array with dimensions (nx,ny).
-	 */
-	nxtop = nx;
-	nytop = ny;
-
-	for (k = 0; k<log2n; k++) {
-		oddx = nxtop % 2;
-		oddy = nytop % 2;
-		for (i = 0; i<nxtop-oddx; i += 2) {
-			s00 = i*ny;				/* s00 is index of a[i,j]	*/
-			s10 = s00+ny;			/* s10 is index of a[i+1,j]	*/
-			for (j = 0; j<nytop-oddy; j += 2) {
-				/*
-				 * Divide h0,hx,hy,hc by 2 (1 the first time through).
-				 */
-				h0 = (a[s10+1] + a[s10] + a[s00+1] + a[s00]) >> 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<nytop-oddy; j += 2) {
-				h0 = (a[s00+1] + a[s00]) << (1-shift);
-				hy = (a[s00+1] - a[s00]) << (1-shift);
-				a[s00+1] = ( (hy>=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<nxtop; i++) {
-			shuffle64(&a[ny*i],nytop,1,tmp);
-		}
-		for (j = 0; j<nytop; j++) {
-			shuffle64(&a[j],nxtop,ny,tmp);
-		}
-		/*
-		 * image size reduced by 2 (round up if odd)
-		 */
-		nxtop = (nxtop+1)>>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; i<n; i += 2) {
-		*p1 = *p2;
-		p1 += n2;
-		p2 += (n2+n2);
-	}
-	/*
-	 * put odd elements into 2nd half
-	 */
-	pt = tmp;
-	for (i = 1; i<n; i += 2) {
-		*p1 = *pt;
-		p1 += n2;
-		pt += 1;
-	}
-}
-/* ######################################################################### */
-static void
-shuffle64(LONGLONG a[], int n, int n2, LONGLONG tmp[])
-{
-
-/* 
-LONGLONG a[];	 array to shuffle					
-int n;		 number of elements to shuffle	
-int n2;		 second dimension					
-LONGLONG tmp[];	 scratch storage					
-*/
-
-int i;
-LONGLONG *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; i<n; i += 2) {
-		*p1 = *p2;
-		p1 += n2;
-		p2 += (n2+n2);
-	}
-	/*
-	 * put odd elements into 2nd half
-	 */
-	pt = tmp;
-	for (i = 1; i<n; i += 2) {
-		*p1 = *pt;
-		p1 += n2;
-		pt += 1;
-	}
-}
-/* ######################################################################### */
-/* ######################################################################### */
-/* Copyright (c) 1993 Association of Universities for Research 
- * in Astronomy. All rights reserved. Produced under National   
- * Aeronautics and Space Administration Contract No. NAS5-26555.
- */
-/* digitize.c	digitize H-transform
- *
- * Programmer: R. White		Date: 11 March 1991
- */
-
-/* ######################################################################### */
-static void  
-digitize(int a[], int nx, int ny, int scale)
-{
-int d, *p;
-
-	/*
-	 * round to multiple of scale
-	 */
-	if (scale <= 1) return;
-	d=(scale+1)/2-1;
-	for (p=a; p <= &a[nx*ny-1]; p++) *p = ((*p>0) ? (*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
-	 */
-	signbits = (unsigned char *) malloc((nel+7)/8);
-	if (signbits == (unsigned char *) NULL) {
-		_astropy_ffpmsg("encode: insufficient memory");
-		return(DATA_COMPRESSION_ERR);
-	}
-	nsign = 0;
-	bits_to_go = 8;
-	signbits[0] = 0;
-	for (i=0; i<nel; i++) {
-		if (a[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<nel; i++) {
-		q = (j>=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<<nbitplanes[q]) ) {
-                        nbitplanes[q] += 1;
-                }
-        }
-*/
-
-	/*
-	 * write nbitplanes
-	 */
-	if (0 == qwrite(outfile, (char *) nbitplanes, sizeof(nbitplanes))) {
-	        *nlength = noutchar;
-		_astropy_ffpmsg("encode: output buffer too small");
-		return(DATA_COMPRESSION_ERR);
-        }
-	 
-	/*
-	 * write coded array
-	 */
-	stat = doencode(outfile, a, nx, ny, nbitplanes);
-	/*
-	 * write sign bits
-	 */
-
-	if (nsign > 0) {
-
-	   if ( 0 == qwrite(outfile, (char *) signbits, nsign)) {
-	        free(signbits);
-	        *nlength = noutchar;
-		_astropy_ffpmsg("encode: output buffer too small");
-		return(DATA_COMPRESSION_ERR);
-          }
-	} 
-	
-	free(signbits);
-	*nlength = noutchar;
-
-        if (noutchar >= noutmax) {
-		_astropy_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 *) malloc((nel+7)/8);
-	if (signbits == (unsigned char *) NULL) {
-		_astropy_ffpmsg("encode64: insufficient memory");
-		return(DATA_COMPRESSION_ERR);
-	}
-	nsign = 0;
-	bits_to_go = 8;
-	signbits[0] = 0;
-	for (i=0; i<nel; i++) {
-		if (a[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<nel; i++) {
-                q = (j>=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)<<nbitplanes[q]) ) {
-			nbitplanes[q] += 1;
-		}
-	}
-*/
-
-	/*
-	 * write nbitplanes
-	 */
-
-	if (0 == qwrite(outfile, (char *) nbitplanes, sizeof(nbitplanes))) {
-	        *nlength = noutchar;
-		_astropy_ffpmsg("encode: output buffer too small");
-		return(DATA_COMPRESSION_ERR);
-        }
-	 
-	/*
-	 * write coded array
-	 */
-	stat = doencode64(outfile, a, nx, ny, nbitplanes);
-	/*
-	 * write sign bits
-	 */
-
-	if (nsign > 0) {
-
-	   if ( 0 == qwrite(outfile, (char *) signbits, nsign)) {
-	        free(signbits);
-	        *nlength = noutchar;
-		_astropy_ffpmsg("encode: output buffer too small");
-		return(DATA_COMPRESSION_ERR);
-          }
-	} 
-
-	free(signbits);
-	*nlength = noutchar;
-
-        if (noutchar >= noutmax) {
-		_astropy_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<<n)-1) ); */
-        buffer2 |= ( bits & (*(mask+n)) );
-	bits_to_go2 -= n;
-	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 += 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<<bits_to_go2,outfile); */
-
-	        outfile[noutchar] = (buffer2<<bits_to_go2);
-		if (noutchar < noutmax) noutchar++;
-
-		/* count the garbage bits too */
-		bitcount += bits_to_go2;
-	}
-}
-/* ######################################################################### */
-/* ######################################################################### */
-/* Copyright (c) 1993 Association of Universities for Research 
- * in Astronomy. All rights reserved. Produced under National   
- * Aeronautics and Space Administration Contract No. NAS5-26555.
- */
-/* qtree_encode.c	Encode values in quadrant of 2-D array using binary
- *					quadtree coding for each bit plane.  Assumes array is
- *					positive.
- *
- * Programmer: R. White		Date: 15 May 1991
- */
-
-/*
- * Huffman code values and number of bits in each code
- */
-static int code[16] =
-	{
-	0x3e, 0x00, 0x01, 0x08, 0x02, 0x09, 0x1a, 0x1b,
-	0x03, 0x1c, 0x0a, 0x1d, 0x0b, 0x1e, 0x3f, 0x0c
-	};
-static int ncode[16] =
-	{
-	6,    3,    3,    4,    3,    4,    5,    5,
-	3,    5,    4,    5,    4,    5,    6,    4
-	};
-
-/*
- * variables for bit output to buffer when Huffman coding
- */
-static int bitbuffer, bits_to_go3;
-
-/*
- * macros to write out 4-bit nybble, Huffman code for this value
- */
-
-
-/* ######################################################################### */
-static int
-qtree_encode(char *outfile, int a[], int n, int nqx, int nqy, int nbitplanes)
-{
-
-/*
-int 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, bmax, nqmax, nqx2, nqy2, nx, ny;
-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<<log2n)) {
-		log2n += 1;
-	}
-	/*
-	 * initialize buffer point, max buffer size
-	 */
-	nqx2 = (nqx+1)/2;
-	nqy2 = (nqy+1)/2;
-	bmax = (nqx2*nqy2+1)/2;
-	/*
-	 * We're indexing A as a 2-D array with dimensions (nqx,nqy).
-	 * Scratch is 2-D with dimensions (nqx/2,nqy/2) rounded up.
-	 * Buffer is used to store string of codes for output.
-	 */
-	scratch = (unsigned char *) malloc(2*bmax);
-	buffer = (unsigned char *) malloc(bmax);
-	if ((scratch == (unsigned char *) NULL) ||
-		(buffer  == (unsigned char *) NULL)) {
-		_astropy_ffpmsg("qtree_encode: insufficient memory");
-		return(DATA_COMPRESSION_ERR);
-	}
-	/*
-	 * now encode each bit plane, starting with the top
-	 */
-	for (bit=nbitplanes-1; bit >= 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<log2n; k++) {
-			qtree_reduce(scratch,ny,nx,ny,scratch);
-			nx = (nx+1)>>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<<bits_to_go3)-1),
-					bits_to_go3);
-			} else {
-				/*
-				 * have to write a zero nybble if there are no 1's in array
-				 */
-				output_huffman(outfile,0);
-			}
-		} else {
-			if (bits_to_go3>0) {
-				/*
-				 * put out the last few bits
-				 */
-				output_nbits(outfile, bitbuffer & ((1<<bits_to_go3)-1),
-					bits_to_go3);
-			}
-			for (i=b-1; i>=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<<log2n)) {
-		log2n += 1;
-	}
-	/*
-	 * initialize buffer point, max buffer size
-	 */
-	nqx2 = (nqx+1)/2;
-	nqy2 = (nqy+1)/2;
-	bmax = (( nqx2)* ( nqy2)+1)/2;
-	/*
-	 * We're indexing A as a 2-D array with dimensions (nqx,nqy).
-	 * Scratch is 2-D with dimensions (nqx/2,nqy/2) rounded up.
-	 * Buffer is used to store string of codes for output.
-	 */
-	scratch = (unsigned char *) malloc(2*bmax);
-	buffer = (unsigned char *) malloc(bmax);
-	if ((scratch == (unsigned char *) NULL) ||
-		(buffer  == (unsigned char *) NULL)) {
-		_astropy_ffpmsg("qtree_encode64: insufficient memory");
-		return(DATA_COMPRESSION_ERR);
-	}
-	/*
-	 * now encode each bit plane, starting with the top
-	 */
-	for (bit=nbitplanes-1; bit >= 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<log2n; k++) {
-			qtree_reduce(scratch,ny,nx,ny,scratch);
-			nx = (nx+1)>>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<<bits_to_go3)-1),
-					bits_to_go3);
-			} else {
-				/*
-				 * have to write a zero nybble if there are no 1's in array
-				 */
-				output_huffman(outfile,0);
-			}
-		} else {
-			if (bits_to_go3>0) {
-				/*
-				 * put out the last few bits
-				 */
-				output_nbits(outfile, bitbuffer & ((1<<bits_to_go3)-1),
-					bits_to_go3);
-			}
-			for (i=b-1; i>=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;
-	b1 = b0<<1;
-	b2 = b0<<2;
-	b3 = b0<<3;
-	k = 0;							/* k is index of b[i/2,j/2]	*/
-	for (i = 0; i<nx-1; i += 2) {
-		s00 = n*i;					/* s00 is index of a[i,j]	*/
-		s10 = s00+n;				/* s10 is index of a[i+1,j]	*/
-		for (j = 0; j<ny-1; j += 2) {
-			b[k] = ( ( a[s10+1]     & b0)
-				   | ((a[s10  ]<<1) & b1)
-				   | ((a[s00+1]<<2) & b2)
-				   | ((a[s00  ]<<3) & b3) ) >> 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<ny-1; j += 2) {
-			b[k] = ( ((a[s00+1]<<2) & b2)
-				   | ((a[s00  ]<<3) & b3) ) >> 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;
-	b1 = b0<<1;
-	b2 = b0<<2;
-	b3 = b0<<3;
-	k = 0;							/* k is index of b[i/2,j/2]	*/
-	for (i = 0; i<nx-1; i += 2) {
-		s00 = n*i;					/* s00 is index of a[i,j]	*/
-		s10 = s00+n;				/* s10 is index of a[i+1,j]	*/
-		for (j = 0; j<ny-1; j += 2) {
-			b[k] = (unsigned char) (( ( a[s10+1]     & b0)
-				   | ((a[s10  ]<<1) & b1)
-				   | ((a[s00+1]<<2) & b2)
-				   | ((a[s00  ]<<3) & b3) ) >> 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<ny-1; j += 2) {
-			b[k] = (unsigned char) (( ((a[s00+1]<<2) & b2)
-				   | ((a[s00  ]<<3) & b3) ) >> 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<nx-1; i += 2) {
-		s00 = n*i;					/* s00 is index of a[i,j]	*/
-		s10 = s00+n;				/* s10 is index of a[i+1,j]	*/
-		for (j = 0; j<ny-1; j += 2) {
-			b[k] =	(a[s10+1] != 0)
-				| ( (a[s10  ] != 0) << 1)
-				| ( (a[s00+1] != 0) << 2)
-				| ( (a[s00  ] != 0) << 3);
-			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  ] != 0) << 1)
-				  | ( (a[s00  ] != 0) << 3);
-			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<ny-1; j += 2) {
-			b[k] =  ( (a[s00+1] != 0) << 2)
-				  | ( (a[s00  ] != 0) << 3);
-			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  ] != 0) << 3);
-			k += 1;
-		}
-	}
-}
-
-/* ######################################################################### */
-static void
-write_bdirect(char *outfile, int a[], int n,int nqx, int nqy, unsigned char scratch[], int bit)
-{
-
-	/*
-	 * Write the direct bitmap warning code
-	 */
-	output_nybble(outfile,0x0);
-	/*
-	 * Copy A to scratch array (again!), packing 4 bits/nybble
-	 */
-	qtree_onebit(a,n,nqx,nqy,scratch,bit);
-	/*
-	 * write to outfile
-	 */
-/*
-int i;
-        for (i = 0; i < ((nqx+1)/2) * ((nqy+1)/2); i++) {
-                output_nybble(outfile,scratch[i]);
-        }
-*/
-        output_nnybble(outfile, ((nqx+1)/2) * ((nqy+1)/2), scratch);
-
-}
-/* ######################################################################### */
-static void
-write_bdirect64(char *outfile, LONGLONG a[], int n,int nqx, int nqy, unsigned char scratch[], int bit)
-{
-
-	/*
-	 * Write the direct bitmap warning code
-	 */
-	output_nybble(outfile,0x0);
-	/*
-	 * Copy A to scratch array (again!), packing 4 bits/nybble
-	 */
-	qtree_onebit64(a,n,nqx,nqy,scratch,bit);
-	/*
-	 * write to outfile
-	 */
-/*
-int i;
-        for (i = 0; i < ((nqx+1)/2) * ((nqy+1)/2); i++) {
-                output_nybble(outfile,scratch[i]);
-        }
-*/
-        output_nnybble(outfile, ((nqx+1)/2) * ((nqy+1)/2), scratch);
-}
diff --git a/astropy/io/fits/src/fits_hdecompress.c b/astropy/io/fits/src/fits_hdecompress.c
deleted file mode 100644
index c970642..0000000
--- a/astropy/io/fits/src/fits_hdecompress.c
+++ /dev/null
@@ -1,2685 +0,0 @@
-/* $Id$
-*/
-
-/*****************************************************************************/
-/*                                                                           */
-/* This file, fits_hdecompress.c, contains the code required to uncompress   */
-/* data using the HCOMPRESS_1 compression format.                            */
-/*                                                                           */
-/* Copyright (C) 2004 Association of Universities for Research in Astronomy  */
-/* (AURA)                                                                    */
-/*                                                                           */
-/* Redistribution and use in source and binary forms, with or without        */
-/* modification, are permitted provided that the following conditions are    */
-/* met:                                                                      */
-/*                                                                           */
-/*    1. Redistributions of source code must retain the above copyright      */
-/*      notice, this list of conditions and the following disclaimer.        */
-/*                                                                           */
-/*    2. Redistributions in binary form must reproduce the above             */
-/*      copyright notice, this list of conditions and the following          */
-/*      disclaimer in the documentation and/or other materials provided      */
-/*      with the distribution.                                               */
-/*                                                                           */
-/*    3. The name of AURA and its representatives may not be used to         */
-/*      endorse or promote products derived from this software without       */
-/*      specific prior written permission.                                   */
-/*                                                                           */
-/* THIS SOFTWARE IS PROVIDED BY AURA ``AS IS'' AND ANY EXPRESS OR IMPLIED    */
-/* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF      */
-/* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE                  */
-/* DISCLAIMED. IN NO EVENT SHALL AURA BE LIABLE FOR ANY DIRECT, INDIRECT,    */
-/* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,      */
-/* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS     */
-/* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND    */
-/* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR     */
-/* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE    */
-/* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH          */
-/* DAMAGE.                                                                   */
-/*                                                                           */
-/* This file was copied intact from the FITSIO software that was written by  */
-/* William Pence at the High Energy Astrophysic Science Archive Research     */
-/* Center (HEASARC) at the NASA Goddard Space Flight Center.  That software  */
-/* contained the following copyright and warranty notices:                   */
-/*                                                                           */
-/* 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."                                             */
-/*                                                                           */
-/*****************************************************************************/
-
-/*  #########################################################################
-These routines to apply the H-compress decompression algorithm to a 2-D Fits
-image were written by R. White at the STScI and were obtained from the STScI at
-http://www.stsci.edu/software/hcompress.html
-
-This source file is a concatination of the following sources files in the
-original distribution 
-  hinv.c 
-  hsmooth.c 
-  undigitize.c 
-  decode.c 
-  dodecode.c 
-  qtree_decode.c 
-  qread.c 
-  bit_input.c
-
-
-The following modifications have been made to the original code:
-
-  - commented out redundant "include" statements
-  - added the nextchar global variable 
-  - changed all the 'extern' declarations to 'static', since all the routines are in
-    the same source file
-  - changed the first parameter in decode (and in lower level routines from a file stream
-    to a char array
-  - modified the myread routine, and lower level byte reading routines,  to copy 
-    the input bytes to a char array, instead of reading them from a file stream
-  - changed the function declarations to the more modern ANSI C style
-  - changed calls to printf and perror to call the CFITSIO ffpmsg routine
-  - replace "exit" statements with "return" statements
-
- ############################################################################  */
- 
-#include <stdio.h>
-#include <math.h>
-#include <stdlib.h>
-#include <string.h>
-#include "fitsio.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 _astropy_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 */
-
-	stat = decode(input, a, nx, ny, scale);
-        *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 _astropy_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 */
-
-	stat = decode64(input, a, nx, ny, scale);
-        *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<<log2n) ) {
-		log2n += 1;
-	}
-	/*
-	 * get temporary storage for shuffling elements
-	 */  
-	tmp = (int *) malloc(((nmax+1)/2)*sizeof(int));
-	if (tmp == (int *) NULL) {
-		_astropy_ffpmsg("hinv: insufficient memory");
-		return(DATA_DECOMPRESSION_ERR);
-	}
-	/*
-	 * set up masks, rounding parameters
-	 */
-	shift  = 1;
-	bit0   = 1 << (log2n - 1);
-	bit1   = bit0 << 1;
-	bit2   = bit0 << 2;
-	mask0  = -bit0;
-	mask1  = mask0 << 1;
-	mask2  = mask0 << 2;
-	prnd0  = bit0 >> 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<<log2n;
-	for (k = log2n-1; k>=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<nxtop; i++) {
-			unshuffle(&a[ny*i],nytop,1,tmp);
-		}
-		for (j = 0; j<nytop; j++) {
-			unshuffle(&a[j],nxtop,ny,tmp);
-		}
-		/*
-		 * smooth by interpolating coefficients if SMOOTH != 0
-		 */
-		if (smooth) hsmooth(a,nxtop,nytop,ny,scale);
-		oddx = nxtop % 2;
-		oddy = nytop % 2;
-		for (i = 0; i<nxtop-oddx; i += 2) {
-			s00 = ny*i;				/* s00 is index of a[i,j]	*/
-			s10 = s00+ny;			/* s10 is index of a[i+1,j]	*/
-			for (j = 0; j<nytop-oddy; j += 2) {
-				h0 = a[s00  ];
-				hx = a[s10  ];
-				hy = a[s00+1];
-				hc = a[s10+1];
-				/*
-				 * round hx and hy to multiple of bit1, hc to multiple of bit0
-				 * h0 is already a multiple of bit2
-				 */
-				hx = (hx + ((hx >= 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<nytop-oddy; j += 2) {
-				h0 = a[s00  ];
-				hy = a[s00+1];
-				hy = ((hy >= 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<<log2n) ) {
-		log2n += 1;
-	}
-	/*
-	 * get temporary storage for shuffling elements
-	 */  
-	tmp = (LONGLONG *) malloc(((nmax+1)/2)*sizeof(LONGLONG));
-	if (tmp == (LONGLONG *) NULL) {
-		_astropy_ffpmsg("hinv64: insufficient memory");
-		return(DATA_DECOMPRESSION_ERR);
-	}
-	/*
-	 * set up masks, rounding parameters
-	 */
-	shift  = 1;
-	bit0   = ((LONGLONG) 1) << (log2n - 1);
-	bit1   = bit0 << 1;
-	bit2   = bit0 << 2;
-	mask0  = -bit0;
-	mask1  = mask0 << 1;
-	mask2  = mask0 << 2;
-	prnd0  = bit0 >> 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<<log2n;
-	for (k = log2n-1; k>=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<nxtop; i++) {
-			unshuffle64(&a[ny*i],nytop,1,tmp);
-		}
-		for (j = 0; j<nytop; j++) {
-			unshuffle64(&a[j],nxtop,ny,tmp);
-		}
-		/*
-		 * smooth by interpolating coefficients if SMOOTH != 0
-		 */
-		if (smooth) hsmooth64(a,nxtop,nytop,ny,scale);
-		oddx = nxtop % 2;
-		oddy = nytop % 2;
-		for (i = 0; i<nxtop-oddx; i += 2) {
-			s00 = ny*i;				/* s00 is index of a[i,j]	*/
-			s10 = s00+ny;			/* s10 is index of a[i+1,j]	*/
-			for (j = 0; j<nytop-oddy; j += 2) {
-				h0 = a[s00  ];
-				hx = a[s10  ];
-				hy = a[s00+1];
-				hc = a[s10+1];
-				/*
-				 * round hx and hy to multiple of bit1, hc to multiple of bit0
-				 * h0 is already a multiple of bit2
-				 */
-				hx = (hx + ((hx >= 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<nytop-oddy; j += 2) {
-				h0 = a[s00  ];
-				hy = a[s00+1];
-				hy = ((hy >= 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<n; i++) {
-		*pt = *p1;
-		p1 += n2;
-		pt += 1;
-	}
-	/*
-	 * distribute 1st half of array to even elements
-	 */
-	p2 = &a[ n2*(nhalf-1) ];		/* pointer to a[i]			*/
-	p1 = &a[(n2*(nhalf-1))<<1];		/* pointer to a[2*i]		*/
-	for (i=nhalf-1; 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<n; i += 2) {
-		*p1 = *pt;
-		p1 += (n2+n2);
-		pt += 1;
-	}
-}
-/*  ############################################################################  */
-static void
-unshuffle64(LONGLONG a[], int n, int n2, LONGLONG tmp[])
-/*
-LONGLONG a[];	 array to shuffle					
-int n;		 number of elements to shuffle	
-int n2;		 second dimension					
-LONGLONG tmp[];	 scratch storage					
-*/
-{
-int i;
-int nhalf;
-LONGLONG *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<n; i++) {
-		*pt = *p1;
-		p1 += n2;
-		pt += 1;
-	}
-	/*
-	 * distribute 1st half of array to even elements
-	 */
-	p2 = &a[ n2*(nhalf-1) ];		/* pointer to a[i]			*/
-	p1 = &a[(n2*(nhalf-1))<<1];		/* pointer to a[2*i]		*/
-	for (i=nhalf-1; 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<n; i += 2) {
-		*p1 = *pt;
-		p1 += (n2+n2);
-		pt += 1;
-	}
-}
-
-/*  ############################################################################  */
-/*  ############################################################################  */
-
-/* Copyright (c) 1993 Association of Universities for Research 
- * in Astronomy. All rights reserved. Produced under National   
- * Aeronautics and Space Administration Contract No. NAS5-26555.
- */
-/* hsmooth.c	Smooth H-transform image by adjusting coefficients toward
- *				interpolated values
- *
- * Programmer: R. White		Date: 13 April 1992
- */
-
-/*  ############################################################################  */
-static void 
-hsmooth(int a[], int nxtop, int nytop, int ny, int scale)
-/*
-int 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, diff, dmax, dmin, s, smax;
-int hm, h0, hp, hmm, hpm, hmp, hpp, hx2, hy2;
-int 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<nxtop-2; i += 2) {
-		s00 = ny*i;				/* s00 is index of a[i,j]	*/
-		s10 = s00+ny;			/* s10 is index of a[i+1,j]	*/
-		for (j = 0; j<nytop; j += 2) {
-			/*
-			 * hp is h0 (mean value) in next x zone, hm is h0 in previous x zone
-			 */
-			hm = a[s00-ny2];
-			h0 = a[s00];
-			hp = a[s00+ny2];
-			/*
-			 * diff = 8 * hx slope that would match h0 in neighboring zones
-			 */
-			diff = hp-hm;
-			/*
-			 * monotonicity constraints on diff
-			 */
-			dmax = max( min( (hp-h0), (h0-hm) ), 0 ) << 2;
-			dmin = min( max( (hp-h0), (h0-hm) ), 0 ) << 2;
-			/*
-			 * if monotonicity would set slope = 0 then don't change hx.
-			 * note dmax>=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<nxtop; i += 2) {
-		s00 = ny*i+2;
-		s10 = s00+ny;
-		for (j = 2; j<nytop-2; j += 2) {
-			hm = a[s00-2];
-			h0 = a[s00];
-			hp = a[s00+2];
-			diff = hp-hm;
-			dmax = max( min( (hp-h0), (h0-hm) ), 0 ) << 2;
-			dmin = min( max( (hp-h0), (h0-hm) ), 0 ) << 2;
-			if (dmin < dmax) {
-				diff = max( min(diff, dmax), dmin);
-				s = diff-(a[s00+1]<<3);
-				s = (s>=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<nxtop-2; i += 2) {
-		s00 = ny*i+2;
-		s10 = s00+ny;
-		for (j = 2; j<nytop-2; j += 2) {
-			/*
-			 * ------------------    y
-			 * | hmp |    | hpp |    |
-			 * ------------------    |
-			 * |     | h0 |     |    |
-			 * ------------------    -------x
-			 * | hmm |    | hpm |
-			 * ------------------
-			 */
-			hmm = a[s00-ny2-2];
-			hpm = a[s00+ny2-2];
-			hmp = a[s00-ny2+2];
-			hpp = a[s00+ny2+2];
-			h0  = a[s00];
-			/*
-			 * diff = 64 * hc value that would match h0 in neighboring zones
-			 */
-			diff = hpp + hmm - hmp - hpm;
-			/*
-			 * 2 times x,y slopes in this zone
-			 */
-			hx2 = a[s10  ]<<1;
-			hy2 = a[s00+1]<<1;
-			/*
-			 * monotonicity constraints on diff
-			 */
-			m1 = min(max(hpp-h0,0)-hx2-hy2, max(h0-hpm,0)+hx2-hy2);
-			m2 = min(max(h0-hmp,0)-hx2+hy2, max(hmm-h0,0)+hx2+hy2);
-			dmax = min(m1,m2) << 4;
-			m1 = max(min(hpp-h0,0)-hx2-hy2, min(h0-hpm,0)+hx2-hy2);
-			m2 = max(min(h0-hmp,0)-hx2+hy2, min(hmm-h0,0)+hx2+hy2);
-			dmin = max(m1,m2) << 4;
-			/*
-			 * if monotonicity would set slope = 0 then don't change hc.
-			 * note dmax>=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<nxtop-2; i += 2) {
-		s00 = ny*i;				/* s00 is index of a[i,j]	*/
-		s10 = s00+ny;			/* s10 is index of a[i+1,j]	*/
-		for (j = 0; j<nytop; j += 2) {
-			/*
-			 * hp is h0 (mean value) in next x zone, hm is h0 in previous x zone
-			 */
-			hm = a[s00-ny2];
-			h0 = a[s00];
-			hp = a[s00+ny2];
-			/*
-			 * diff = 8 * hx slope that would match h0 in neighboring zones
-			 */
-			diff = hp-hm;
-			/*
-			 * monotonicity constraints on diff
-			 */
-			dmax = max( min( (hp-h0), (h0-hm) ), 0 ) << 2;
-			dmin = min( max( (hp-h0), (h0-hm) ), 0 ) << 2;
-			/*
-			 * if monotonicity would set slope = 0 then don't change hx.
-			 * note dmax>=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<nxtop; i += 2) {
-		s00 = ny*i+2;
-		s10 = s00+ny;
-		for (j = 2; j<nytop-2; j += 2) {
-			hm = a[s00-2];
-			h0 = a[s00];
-			hp = a[s00+2];
-			diff = hp-hm;
-			dmax = max( min( (hp-h0), (h0-hm) ), 0 ) << 2;
-			dmin = min( max( (hp-h0), (h0-hm) ), 0 ) << 2;
-			if (dmin < dmax) {
-				diff = max( min(diff, dmax), dmin);
-				s = diff-(a[s00+1]<<3);
-				s = (s>=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<nxtop-2; i += 2) {
-		s00 = ny*i+2;
-		s10 = s00+ny;
-		for (j = 2; j<nytop-2; j += 2) {
-			/*
-			 * ------------------    y
-			 * | hmp |    | hpp |    |
-			 * ------------------    |
-			 * |     | h0 |     |    |
-			 * ------------------    -------x
-			 * | hmm |    | hpm |
-			 * ------------------
-			 */
-			hmm = a[s00-ny2-2];
-			hpm = a[s00+ny2-2];
-			hmp = a[s00-ny2+2];
-			hpp = a[s00+ny2+2];
-			h0  = a[s00];
-			/*
-			 * diff = 64 * hc value that would match h0 in neighboring zones
-			 */
-			diff = hpp + hmm - hmp - hpm;
-			/*
-			 * 2 times x,y slopes in this zone
-			 */
-			hx2 = a[s10  ]<<1;
-			hy2 = a[s00+1]<<1;
-			/*
-			 * monotonicity constraints on diff
-			 */
-			m1 = min(max(hpp-h0,0)-hx2-hy2, max(h0-hpm,0)+hx2-hy2);
-			m2 = min(max(h0-hmp,0)-hx2+hy2, max(hmm-h0,0)+hx2+hy2);
-			dmax = min(m1,m2) << 4;
-			m1 = max(min(hpp-h0,0)-hx2-hy2, min(h0-hpm,0)+hx2-hy2);
-			m2 = max(min(h0-hmp,0)-hx2+hy2, min(hmm-h0,0)+hx2+hy2);
-			dmin = max(m1,m2) << 4;
-			/*
-			 * if monotonicity would set slope = 0 then don't change hc.
-			 * note dmax>=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 nel, 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) {
-		_astropy_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	*/
-	
-	nel = (*nx) * (*ny);
-
-	/* 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 nel, 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) {
-		_astropy_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	*/
-	
-	nel = (*nx) * (*ny);
-
-	/* 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; i<nel; i++) a[i] = 0;
-	/*
-	 * Initialize bit input
-	 */
-	start_inputing_bits();
-	/*
-	 * read bit planes for each quadrant
-	 */
-	stat = qtree_decode(infile, &a[0],          ny, nx2,  ny2,  nbitplanes[0]);
-        if (stat) return(stat);
-	
-	stat = qtree_decode(infile, &a[ny2],        ny, nx2,  ny/2, nbitplanes[1]);
-        if (stat) return(stat);
-	
-	stat = qtree_decode(infile, &a[ny*nx2],     ny, nx/2, ny2,  nbitplanes[1]);
-        if (stat) return(stat);
-	
-	stat = qtree_decode(infile, &a[ny*nx2+ny2], ny, nx/2, ny/2, nbitplanes[2]);
-        if (stat) return(stat);
-	
-	/*
-	 * make sure there is an EOF symbol (nybble=0) at end
-	 */
-	if (input_nybble(infile) != 0) {
-		_astropy_ffpmsg("dodecode: bad bit plane values");
-		return(DATA_DECOMPRESSION_ERR);
-	}
-	/*
-	 * now get the sign bits
-	 * Re-initialize bit input
-	 */
-	start_inputing_bits();
-	for (i=0; i<nel; i++) {
-                if (a[i]) {
-                        /* tried putting the input_bit code in-line here, instead of */
-                        /* calling the function, but it made no difference in the speed */
-                        if (input_bit(infile)) a[i] = -a[i];
-                }
-	}
-	return(0);
-}
-/*  ############################################################################  */
-static int
-dodecode64(unsigned char *infile, LONGLONG a[], int nx, int ny, unsigned char nbitplanes[3])
-
-/* LONGLONG 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; i<nel; i++) a[i] = 0;
-	/*
-	 * Initialize bit input
-	 */
-	start_inputing_bits();
-	/*
-	 * read bit planes for each quadrant
-	 */
-	stat = qtree_decode64(infile, &a[0],          ny, nx2,  ny2,  nbitplanes[0]);
-        if (stat) return(stat);
-	
-	stat = qtree_decode64(infile, &a[ny2],        ny, nx2,  ny/2, nbitplanes[1]);
-        if (stat) return(stat);
-	
-	stat = qtree_decode64(infile, &a[ny*nx2],     ny, nx/2, ny2,  nbitplanes[1]);
-        if (stat) return(stat);
-	
-	stat = qtree_decode64(infile, &a[ny*nx2+ny2], ny, nx/2, ny/2, nbitplanes[2]);
-        if (stat) return(stat);
-	
-	/*
-	 * make sure there is an EOF symbol (nybble=0) at end
-	 */
-	if (input_nybble(infile) != 0) {
-		_astropy_ffpmsg("dodecode64: bad bit plane values");
-		return(DATA_DECOMPRESSION_ERR);
-	}
-	/*
-	 * now get the sign bits
-	 * Re-initialize bit input
-	 */
-	start_inputing_bits();
-	for (i=0; i<nel; i++) {
-                if (a[i]) {
-			if (input_bit(infile) != 0) a[i] = -a[i];
-		}
-	}
-	return(0);
-}
-
-/*  ############################################################################  */
-/*  ############################################################################  */
-/* Copyright (c) 1993 Association of Universities for Research 
- * in Astronomy. All rights reserved. Produced under National   
- * Aeronautics and Space Administration Contract No. NAS5-26555.
- */
-/* qtree_decode.c	Read stream of codes from infile and construct bit planes
- *					in quadrant of 2-D array using binary quadtree coding
- *
- * Programmer: R. White		Date: 7 May 1991
- */
-
-/*  ############################################################################  */
-static int
-qtree_decode(unsigned char *infile, int a[], int n, int nqx, int nqy, int nbitplanes)
-
-/*
-char *infile;
-int 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<<log2n)) {
-		log2n += 1;
-	}
-	/*
-	 * allocate scratch array for working space
-	 */
-	nqx2=(nqx+1)/2;
-	nqy2=(nqy+1)/2;
-	scratch = (unsigned char *) malloc(nqx2*nqy2);
-	if (scratch == (unsigned char *) NULL) {
-		_astropy_ffpmsg("qtree_decode: insufficient memory");
-		return(DATA_DECOMPRESSION_ERR);
-	}
-	/*
-	 * now decode each bit plane, starting at the top
-	 * A is assumed to be initialized to zero
-	 */
-	for (bit = nbitplanes-1; bit >= 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) {
-			_astropy_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<<log2n;
-			for (k = 1; k<log2n; k++) {
-				/*
-				 * this somewhat cryptic code generates the sequence
-				 * n[k-1] = (n[k]+1)/2 where n[log2n]=nqx or nqy
-				 */
-				c = c>>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<<log2n)) {
-		log2n += 1;
-	}
-	/*
-	 * allocate scratch array for working space
-	 */
-	nqx2=(nqx+1)/2;
-	nqy2=(nqy+1)/2;
-	scratch = (unsigned char *) malloc(nqx2*nqy2);
-	if (scratch == (unsigned char *) NULL) {
-		_astropy_ffpmsg("qtree_decode64: insufficient memory");
-		return(DATA_DECOMPRESSION_ERR);
-	}
-	/*
-	 * now decode each bit plane, starting at the top
-	 * A is assumed to be initialized to zero
-	 */
-	for (bit = nbitplanes-1; bit >= 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) {
-			_astropy_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<<log2n;
-			for (k = 1; k<log2n; k++) {
-				/*
-				 * this somewhat cryptic code generates the sequence
-				 * n[k-1] = (n[k]+1)/2 where n[log2n]=nqx or nqy
-				 */
-				c = c>>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<nx-1; i += 2) {
-
-  /* Note:
-     Unlike the case in qtree_bitins, this code runs faster on a 32-bit linux
-     machine using the s10 intermediate variable, rather that using s00+n.
-     Go figure!
-  */
-		s00 = n*i;					/* s00 is index of b[i,j]	*/
-		s10 = s00+n;				/* s10 is index of b[i+1,j]	*/
-		for (j = 0; j<ny-1; j += 2) {
-
-                    switch (b[s00]) {
-                    case(0):
-                        b[s10+1] = 0;
-                        b[s10  ] = 0;
-                        b[s00+1] = 0;
-                        b[s00  ] = 0;
-
-                        break;
-                    case(1):
-                        b[s10+1] = 1;
-                        b[s10  ] = 0;
-                        b[s00+1] = 0;
-                        b[s00  ] = 0;
-
-                        break;
-                    case(2):
-                        b[s10+1] = 0;
-                        b[s10  ] = 1;
-                        b[s00+1] = 0;
-                        b[s00  ] = 0;
-
-                        break;
-                    case(3):
-                        b[s10+1] = 1;
-                        b[s10  ] = 1;
-                        b[s00+1] = 0;
-                        b[s00  ] = 0;
-
-                        break;
-                    case(4):
-                        b[s10+1] = 0;
-                        b[s10  ] = 0;
-                        b[s00+1] = 1;
-                        b[s00  ] = 0;
-
-                        break;
-                    case(5):
-                        b[s10+1] = 1;
-                        b[s10  ] = 0;
-                        b[s00+1] = 1;
-                        b[s00  ] = 0;
-
-                        break;
-                    case(6):
-                        b[s10+1] = 0;
-                        b[s10  ] = 1;
-                        b[s00+1] = 1;
-                        b[s00  ] = 0;
-
-                        break;
-                    case(7):
-                        b[s10+1] = 1;
-                        b[s10  ] = 1;
-                        b[s00+1] = 1;
-                        b[s00  ] = 0;
-
-                        break;
-                    case(8):
-                        b[s10+1] = 0;
-                        b[s10  ] = 0;
-                        b[s00+1] = 0;
-                        b[s00  ] = 1;
-
-                        break;
-                    case(9):
-                        b[s10+1] = 1;
-                        b[s10  ] = 0;
-                        b[s00+1] = 0;
-                        b[s00  ] = 1;
-                        break;
-                    case(10):
-                        b[s10+1] = 0;
-                        b[s10  ] = 1;
-                        b[s00+1] = 0;
-                        b[s00  ] = 1;
-
-                        break;
-                    case(11):
-                        b[s10+1] = 1;
-                        b[s10  ] = 1;
-                        b[s00+1] = 0;
-                        b[s00  ] = 1;
-
-                        break;
-                    case(12):
-                        b[s10+1] = 0;
-                        b[s10  ] = 0;
-                        b[s00+1] = 1;
-                        b[s00  ] = 1;
-
-                        break;
-                    case(13):
-                        b[s10+1] = 1;
-                        b[s10  ] = 0;
-                        b[s00+1] = 1;
-                        b[s00  ] = 1;
-
-                        break;
-                    case(14):
-                        b[s10+1] = 0;
-                        b[s10  ] = 1;
-                        b[s00+1] = 1;
-                        b[s00  ] = 1;
-
-                        break;
-                    case(15):
-                        b[s10+1] = 1;
-                        b[s10  ] = 1;
-                        b[s00+1] = 1;
-                        b[s00  ] = 1;
-
-                        break;
-                    }
-/*
-                        b[s10+1] =  b[s00]     & 1;
-                        b[s10  ] = (b[s00]>>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<ny-1; j += 2) {
-                        /* not worth converting this to use 16 case statements */
-			b[s00+1] = (b[s00]>>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<nx-1; i += 2) {
-                s00 = n*i;                              /* s00 is index of b[i,j]       */
-
-  /* Note:
-     this code appears to run very slightly faster on a 32-bit linux
-     machine using s00+n rather than the s10 intermediate variable
-  */
-  /*            s10 = s00+n;    */                      /* s10 is index of b[i+1,j]     */
-		for (j = 0; j<ny-1; j += 2) {
-
-                    switch (a[k]) {
-                    case(0):
-                        break;
-                    case(1):
-                        b[s00+n+1] |= plane_val;
-                        break;
-                    case(2):
-                        b[s00+n  ] |= plane_val;
-                        break;
-                    case(3):
-                        b[s00+n+1] |= plane_val;
-                        b[s00+n  ] |= plane_val;
-                        break;
-                    case(4):
-                        b[s00+1] |= plane_val;
-                        break;
-                    case(5):
-                        b[s00+n+1] |= plane_val;
-                        b[s00+1] |= plane_val;
-                        break;
-                    case(6):
-                        b[s00+n  ] |= plane_val;
-                        b[s00+1] |= plane_val;
-                        break;
-                    case(7):
-                        b[s00+n+1] |= plane_val;
-                        b[s00+n  ] |= plane_val;
-                        b[s00+1] |= plane_val;
-                        break;
-                    case(8):
-                        b[s00  ] |= plane_val;
-                        break;
-                    case(9):
-                        b[s00+n+1] |= plane_val;
-                        b[s00  ] |= plane_val;
-                        break;
-                    case(10):
-                        b[s00+n  ] |= plane_val;
-                        b[s00  ] |= plane_val;
-                        break;
-                    case(11):
-                        b[s00+n+1] |= plane_val;
-                        b[s00+n  ] |= plane_val;
-                        b[s00  ] |= plane_val;
-                        break;
-                    case(12):
-                        b[s00+1] |= plane_val;
-                        b[s00  ] |= plane_val;
-                        break;
-                    case(13):
-                        b[s00+n+1] |= plane_val;
-                        b[s00+1] |= plane_val;
-                        b[s00  ] |= plane_val;
-                        break;
-                    case(14):
-                        b[s00+n  ] |= plane_val;
-                        b[s00+1] |= plane_val;
-                        b[s00  ] |= plane_val;
-                        break;
-                    case(15):
-                        b[s00+n+1] |= plane_val;
-                        b[s00+n  ] |= plane_val;
-                        b[s00+1] |= plane_val;
-                        b[s00  ] |= plane_val;
-                        break;
-                    }
-
-/*
-                        b[s10+1] |= ( a[k]     & 1) << bit;
-                        b[s10  ] |= ((a[k]>>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<ny-1; j += 2) {
-
-                    switch (a[k]) {
-                    case(0):
-                        break;
-                    case(1):
-                        break;
-                    case(2):
-                        break;
-                    case(3):
-                        break;
-                    case(4):
-                        b[s00+1] |= plane_val;
-                        break;
-                    case(5):
-                        b[s00+1] |= plane_val;
-                        break;
-                    case(6):
-                        b[s00+1] |= plane_val;
-                        break;
-                    case(7):
-                        b[s00+1] |= plane_val;
-                        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+1] |= plane_val;
-                        b[s00  ] |= plane_val;
-                        break;
-                    case(13):
-                        b[s00+1] |= plane_val;
-                        b[s00  ] |= plane_val;
-                        break;
-                    case(14):
-                        b[s00+1] |= plane_val;
-                        b[s00  ] |= plane_val;
-                        break;
-                    case(15):
-                        b[s00+1] |= plane_val;
-                        b[s00  ] |= plane_val;
-                        break;
-                    }
-
-/*
-                        b[s00+1] |= ((a[k]>>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;
-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<nx-1; i += 2) {
-		s00 = n*i;					/* s00 is index of b[i,j]		*/
-
-  /* Note:
-     this code appears to run very slightly faster on a 32-bit linux
-     machine using s00+n rather than the s10 intermediate variable
-  */
-  /*            s10 = s00+n;    */                      /* s10 is index of b[i+1,j]     */
-		for (j = 0; j<ny-1; j += 2) {
-
-                    switch (a[k]) {
-                    case(0):
-                        break;
-                    case(1):
-                        b[s00+n+1] |= plane_val;
-                        break;
-                    case(2):
-                        b[s00+n  ] |= plane_val;
-                        break;
-                    case(3):
-                        b[s00+n+1] |= plane_val;
-                        b[s00+n  ] |= plane_val;
-                        break;
-                    case(4):
-                        b[s00+1] |= plane_val;
-                        break;
-                    case(5):
-                        b[s00+n+1] |= plane_val;
-                        b[s00+1] |= plane_val;
-                        break;
-                    case(6):
-                        b[s00+n  ] |= plane_val;
-                        b[s00+1] |= plane_val;
-                        break;
-                    case(7):
-                        b[s00+n+1] |= plane_val;
-                        b[s00+n  ] |= plane_val;
-                        b[s00+1] |= plane_val;
-                        break;
-                    case(8):
-                        b[s00  ] |= plane_val;
-                        break;
-                    case(9):
-                        b[s00+n+1] |= plane_val;
-                        b[s00  ] |= plane_val;
-                        break;
-                    case(10):
-                        b[s00+n  ] |= plane_val;
-                        b[s00  ] |= plane_val;
-                        break;
-                    case(11):
-                        b[s00+n+1] |= plane_val;
-                        b[s00+n  ] |= plane_val;
-                        b[s00  ] |= plane_val;
-                        break;
-                    case(12):
-                        b[s00+1] |= plane_val;
-                        b[s00  ] |= plane_val;
-                        break;
-                    case(13):
-                        b[s00+n+1] |= plane_val;
-                        b[s00+1] |= plane_val;
-                        b[s00  ] |= plane_val;
-                        break;
-                    case(14):
-                        b[s00+n  ] |= plane_val;
-                        b[s00+1] |= plane_val;
-                        b[s00  ] |= plane_val;
-                        break;
-                    case(15):
-                        b[s00+n+1] |= plane_val;
-                        b[s00+n  ] |= plane_val;
-                        b[s00+1] |= plane_val;
-                        b[s00  ] |= plane_val;
-                        break;
-                    }
-
-/*
-                        b[s10+1] |= ((LONGLONG) ( a[k]     & 1)) << bit;
-                        b[s10  ] |= ((((LONGLONG)a[k])>>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<ny-1; j += 2) {
-
-                    switch (a[k]) {
-                    case(0):
-                        break;
-                    case(1):
-                        break;
-                    case(2):
-                        break;
-                    case(3):
-                        break;
-                    case(4):
-                        b[s00+1] |= plane_val;
-                        break;
-                    case(5):
-                        b[s00+1] |= plane_val;
-                        break;
-                    case(6):
-                        b[s00+1] |= plane_val;
-                        break;
-                    case(7):
-                        b[s00+1] |= plane_val;
-                        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+1] |= plane_val;
-                        b[s00  ] |= plane_val;
-                        break;
-                    case(13):
-                        b[s00+1] |= plane_val;
-                        b[s00  ] |= plane_val;
-                        break;
-                    case(14):
-                        b[s00+1] |= plane_val;
-                        b[s00  ] |= plane_val;
-                        break;
-                    case(15):
-                        b[s00+1] |= plane_val;
-                        b[s00  ] |= plane_val;
-                        break;
-                    }
-
-/*
-                        b[s00+1] |= ((((LONGLONG)a[k])>>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)
-{
-/*int i; */
-
-	/*
-	 * read bit image packed 4 pixels/nybble
-	 */
-/*
-        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)
-{
-/*int i; */
-
-	/*
-	 * read bit image packed 4 pixels/nybble
-	 */
-/*
-        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<<c);
-	}
-	/*
-	 * get the next bit
-	 */
-	c = input_bit(infile) | (c<<1);
-	if (c < 13) {
-		/*
-		 * OK, 4 bits is enough
-		 */
-		switch (c) {
-			case  8 : return(3);
-			case  9 : return(5);
-			case 10 : return(10);
-			case 11 : return(12);
-			case 12 : return(15);
-		}
-	}
-	/*
-	 * get yet another bit
-	 */
-	c = input_bit(infile) | (c<<1);
-	if (c < 31) {
-		/*
-		 * OK, 5 bits is enough
-		 */
-		switch (c) {
-			case 26 : return(6);
-			case 27 : return(7);
-			case 28 : return(9);
-			case 29 : return(11);
-			case 30 : return(13);
-		}
-	}
-	/*
-	 * need the 6th bit
-	 */
-	c = input_bit(infile) | (c<<1);
-	if (c == 62) {
-		return(0);
-	} else {
-		return(14);
-	}
-}
-
-/*  ############################################################################  */
-/*  ############################################################################  */
-/* Copyright (c) 1993 Association of Universities for Research 
- * in Astronomy. All rights reserved. Produced under National   
- * Aeronautics and Space Administration Contract No. NAS5-26555.
- */
-/* qread.c	Read binary data
- *
- * Programmer: R. White		Date: 11 March 1991
- */
-
-static int readint(unsigned char *infile)
-{
-int a,i;
-unsigned char b[4];
-
-	/* Read integer A one byte at a time from infile.
-	 *
-	 * This is portable from Vax to Sun since it eliminates the
-	 * need for byte-swapping.
-         *
-         *  This routine is only called to read the first 3 values
-         *  in the compressed file, so it doesn't have to be
-         *  super-efficient
-	 */
-	for (i=0; i<4; i++) qread(infile,(char *) &b[i],1);
-	a = b[0];
-	for (i=1; i<4; i++) a = (a<<8) + b[i];
-	return(a);
-}
-
-/*  ############################################################################  */
-static LONGLONG readlonglong(unsigned char *infile)
-{
-int i;
-LONGLONG a;
-unsigned char b[8];
-
-	/* Read integer A one byte at a time from infile.
-	 *
-	 * This is portable from Vax to Sun since it eliminates the
-	 * need for byte-swapping.
-         *
-         *  This routine is only called to read the first 3 values
-         *  in the compressed file, so it doesn't have to be
-         *  super-efficient
-	 */
-	for (i=0; i<8; i++) qread(infile,(char *) &b[i],1);
-	a = b[0];
-	for (i=1; i<8; i++) a = (a<<8) + b[i];
-	return(a);
-}
-
-/*  ############################################################################  */
-static void qread(unsigned char *file,char buffer[], int n)
-{
-    /*
-     * read n bytes from file into buffer
-     *
-     */
-
-    memcpy(buffer, &file[nextchar], n);
-    nextchar += 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.
- */
-
-/* BIT INPUT ROUTINES */
-
-/* THE BIT BUFFER */
-
-static int buffer2;			/* Bits waiting to be input	*/
-static int bits_to_go;			/* Number of bits still in buffer */
-
-/* INITIALIZE BIT INPUT */
-
-/*  ############################################################################  */
-static void start_inputing_bits(void)
-{
-	/*
-	 * Buffer starts out with no bits in it
-	 */
-	bits_to_go = 0;
-}
-
-/*  ############################################################################  */
-/* INPUT A BIT */
-
-static int input_bit(unsigned char *infile)
-{
-	if (bits_to_go == 0) {			/* Read the next byte if no	*/
-
-		buffer2 = infile[nextchar];
-		nextchar++;
-		
-		bits_to_go = 8;
-	}
-	/*
-	 * Return the next bit
-	 */
-	bits_to_go -= 1;
-	return((buffer2>>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<<n)-1) ); */
-        return( (buffer2>>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 );
-}
diff --git a/astropy/io/fits/src/fitsio.c b/astropy/io/fits/src/fitsio.c
deleted file mode 100644
index 97a8f96..0000000
--- a/astropy/io/fits/src/fitsio.c
+++ /dev/null
@@ -1,5849 +0,0 @@
-/* $Id$
-*/
-
-/*****************************************************************************/
-/*                                                                           */
-/* This file, fitsio.c, contains the core of a set of FITSIO routines that   */
-/* are used to compress and uncompress image data in FITS binary tables.     */
-/* The code was copied and modified from the FITSIO software written at      */
-/* HEASRC.  The goal for the astropyComp module was to take this code nearly  */
-/* intact.  In FITSIO, interaction with the FITS file is accomplished        */
-/* directly within the FITSIO code.  With astropyComp, interaction with the   */
-/* FITS file is accomplished from within astropy.  This may make some of the  */
-/* constructs within the FISTIO code seem confusing when viewed from the     */
-/* perspective of astropyComp.  It should be noted that the FITSfile          */
-/* structure acts as the interface to the file in both cases.  In FITSIO it  */
-/* contains the file handle in order to access the file, and in astropyComp   */
-/* it holds the file data, either compressed or uncompressed.                */
-/*                                                                           */
-/* Copyright (C) 2004 Association of Universities for Research in Astronomy  */
-/* (AURA)                                                                    */
-/*                                                                           */
-/* Redistribution and use in source and binary forms, with or without        */
-/* modification, are permitted provided that the following conditions are    */
-/* met:                                                                      */
-/*                                                                           */
-/*    1. Redistributions of source code must retain the above copyright      */
-/*      notice, this list of conditions and the following disclaimer.        */
-/*                                                                           */
-/*    2. Redistributions in binary form must reproduce the above             */
-/*      copyright notice, this list of conditions and the following          */
-/*      disclaimer in the documentation and/or other materials provided      */
-/*      with the distribution.                                               */
-/*                                                                           */
-/*    3. The name of AURA and its representatives may not be used to         */
-/*      endorse or promote products derived from this software without       */
-/*      specific prior written permission.                                   */
-/*                                                                           */
-/* THIS SOFTWARE IS PROVIDED BY AURA ``AS IS'' AND ANY EXPRESS OR IMPLIED    */
-/* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF      */
-/* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE                  */
-/* DISCLAIMED. IN NO EVENT SHALL AURA BE LIABLE FOR ANY DIRECT, INDIRECT,    */
-/* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,      */
-/* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS     */
-/* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND    */
-/* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR     */
-/* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE    */
-/* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH          */
-/* DAMAGE.                                                                   */
-/*                                                                           */
-/* This file contains source code that was copied and modified from the      */
-/* FITSIO software that was written by William Pence at the High Energy      */
-/* Astrophysic Science Archive Research Center (HEASARC) at the NASA Goddard */
-/* Space Flight Center.  That software contained the following copyright and */
-/* warranty notices:                                                         */
-/*                                                                           */
-/* 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 <math.h>
-#include <stdlib.h>
-#include <limits.h>
-#include <string.h>
-#include "fitsio.h"
-
-/*****************************************************************************/
-/*                                                                           */
-/* The following code was copied and modified from the FITSIO source code    */
-/* file fitscore.c.                                                          */
-/*                                                                           */
-/*****************************************************************************/
-
-#define GetMesg    4 /* pop and return the message */
-#define PutMesg    5 /* put a new message */
-
-static int imcomp_nullfloats(float *fdata, long tilelen, int *idata,
-    int nullcheck, float nullflagval, int nullval, int *status);
-static int imcomp_nullscalefloats(float *fdata, long tilelen, int *idata,
-    double scale, double zero, int nullcheck, float nullflagval, int nullval,
-    int *status);
-static int imcomp_nulldoubles(double *fdata, long tilelen, int *idata,
-    int nullcheck, double nullflagval, int nullval, int *status);
-static int imcomp_nullscaledoubles(double *fdata, long tilelen, int *idata,
-    double scale, double zero, int nullcheck, double nullflagval, int nullval,
-    int *status);
-static int fits_write_compressed_pixels(fitsfile *fptr,
-            int  datatype, LONGLONG  fpixel, LONGLONG npixels,
-            int nullcheck,  void *array, void *nulval,
-            int  *status);
-static 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);
-static 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);
-static 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);
-static int imcomp_decompress_tile (fitsfile *infptr,
-          int nrow, int tilesize, int datatype, int nullcheck,
-          void *nulval, void *buffer, char *bnullarray, int *anynul,
-          int *status);
-static 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);
-static 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);
-
-/*--------------------------------------------------------------------------*/
-static void ffxmsg( int action,
-                    char *errmsg)
-/*
-  general routine to get or put an error message to the error buffer.
-
-  Action Code:
-   GetMesg    4  pop and return the message
-   PutMesg    5  add a new message to the buffer
-
-*/
-{
-    static char errbuff[81];  /* error buffer */
-    static int firstTime = 1;
-
-    if (firstTime)
-    {
-        firstTime = 0;
-        errbuff[0] = '\0';
-    }
-
-    if (action == GetMesg)  /* pop and return oldest message from stack */
-    {                            /* ignoring markers */
-        strcpy(errmsg, errbuff);   /* copy message to output */
-    }
-    else if (action == PutMesg)  /* add new message to stack */
-    {
-        strncpy(errbuff, errmsg, 80);
-    }
-
-    return;
-}
-/*--------------------------------------------------------------------------*/
-void _astropy_ffpmsg(const char *err_message)
-/*
-  put message in error buffer
-*/
-{
-    ffxmsg(PutMesg, (char *)err_message);
-    return;
-}
-/*--------------------------------------------------------------------------*/
-int _astropy_ffgmsg(char *err_message)
-/*
-  get the error message from the error buffer
-*/
-{
-    ffxmsg(GetMesg, err_message);
-    return(*err_message);
-}
-/*--------------------------------------------------------------------------*/
-static 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);
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/* The following code was copied and modified from the FITSIO source code    */
-/* file swapproc.c.                                                          */
-/*                                                                           */
-/*****************************************************************************/
-
-/*---------------------------------------------------------------------------*/
-static 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 )
-*/
-{
-    register char *cvalues;
-    register long ii;
-
-    union u_tag {
-        char cvals[2];   /* equivalence an array of 4 bytes with */
-        short sval;      /* a short */
-    } u;
-
-    cvalues = (char *) svalues;      /* copy the initial pointer value */
-
-    for (ii = 0; ii < nvals;)
-    {
-        u.sval = svalues[ii++];  /* copy next short to temporary buffer */
-
-        *cvalues++ = u.cvals[1]; /* copy the 2 bytes to output in turn */
-        *cvalues++ = u.cvals[0];
-    }
-    return;
-}
-/*--------------------------------------------------------------------------*/
-static void ffswap4(INT32BIT *ivalues, /* IO - pointer to floats 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 )
-*/
-{
-    register char *cvalues;
-    register long ii;
-
-    union u_tag {
-        char cvals[4];      /* equivalence an array of 4 bytes with */
-        INT32BIT ival;      /* a float */
-    } u;
-
-    cvalues = (char *) ivalues;   /* copy the initial pointer value */
-
-    for (ii = 0; ii < nvals;)
-    {
-        u.ival = ivalues[ii++];  /* copy next float to buffer */
-
-        *cvalues++ = u.cvals[3]; /* copy the 4 bytes in turn */
-        *cvalues++ = u.cvals[2];
-        *cvalues++ = u.cvals[1];
-        *cvalues++ = u.cvals[0];
-    }
-    return;
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/* The following code was copied and modified from the FITSIO source code    */
-/* file getcolb.c.                                                           */
-/*                                                                           */
-/*****************************************************************************/
-
-/*---------------------------------------------------------------------------*/
-static 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.
-*/
-{
-    int nullcheck = 1;
-    unsigned char nullvalue;
-
-    nullvalue = nulval;  /* set local variable */
-
-    fits_read_compressed_pixels(fptr, TBYTE, firstelem, nelem,
-            nullcheck, &nullvalue, array, NULL, anynul, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-static 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 */
-           memcpy(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);
-}
-/*--------------------------------------------------------------------------*/
-static 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);
-}
-/*---------------------------------------------------------------------------*/
-static 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)
-                    {
-                        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);
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/* The following code was copied and modified from the FITSIO source code    */
-/* file getcold.c.                                                           */
-/*                                                                           */
-/*****************************************************************************/
-
-/*---------------------------------------------------------------------------*/
-static 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.
-*/
-{
-    int nullcheck = 1;
-    double nullvalue;
-
-    nullvalue = nulval;  /* set local variable */
-
-    fits_read_compressed_pixels(fptr, TDOUBLE, firstelem, nelem,
-            nullcheck, &nullvalue, array, NULL, anynul, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-static 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);
-}
-/*--------------------------------------------------------------------------*/
-static 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);
-}
-/*---------------------------------------------------------------------------*/
-static 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);
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/* The following code was copied and modified from the FITSIO source code    */
-/* file getcole.c.                                                           */
-/*                                                                           */
-/*****************************************************************************/
-
-/*---------------------------------------------------------------------------*/
-static 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.
-*/
-{
-    int nullcheck = 1;
-    float nullvalue;
-
-    nullvalue = nulval;  /* set local variable */
-
-    fits_read_compressed_pixels(fptr, TFLOAT, firstelem, nelem,
-            nullcheck, &nullvalue, array, NULL, anynul, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-static 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);
-}
-/*--------------------------------------------------------------------------*/
-static 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);
-}
-/*---------------------------------------------------------------------------*/
-static 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);
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/* The following code was copied and modified from the FITSIO source code    */
-/* file getcoli.c.                                                           */
-/*                                                                           */
-/*****************************************************************************/
-
-/*---------------------------------------------------------------------------*/
-static 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.
-*/
-{
-    int nullcheck = 1;
-    short nullvalue;
-
-    nullvalue = nulval;  /* set local variable */
-    
-    fits_read_compressed_pixels(fptr, TSHORT, firstelem, nelem,
-            nullcheck, &nullvalue, array, NULL, anynul, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-static 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);
-}
-/*--------------------------------------------------------------------------*/
-static 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 */
-        {
-            memcpy(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);
-}
-/*---------------------------------------------------------------------------*/
-static 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);
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/* The following code was copied and modified from the FITSIO source code    */
-/* file getcolk.c.                                                           */
-/*                                                                           */
-/*****************************************************************************/
-
-/*--------------------------------------------------------------------------*/
-static 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.
-*/
-{
-    int nullcheck = 1;
-    int nullvalue;
-
-    nullvalue = nulval;  /* set local variable */
-
-    fits_read_compressed_pixels(fptr, TINT, firstelem, nelem,
-            nullcheck, &nullvalue, array, NULL, anynul, status);
-    return(*status);
-}
-
-/*--------------------------------------------------------------------------*/
-static 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);
-}
-/*--------------------------------------------------------------------------*/
-static 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);
-}
-/*--------------------------------------------------------------------------*/
-static 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);
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/* The following code was copied and modified from the FITSIO source code    */
-/* file getcolj.c.                                                           */
-/*                                                                           */
-/*****************************************************************************/
-
-/*---------------------------------------------------------------------------*/
-static 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.
-*/
-{
-    int nullcheck = 1;
-    long nullvalue;
-
-    nullvalue = nulval;  /* set local variable */
-
-    fits_read_compressed_pixels(fptr, TLONG, firstelem, nelem,
-            nullcheck, &nullvalue, array, NULL, anynul, status);
-    return(*status);
-}
-
-/*--------------------------------------------------------------------------*/
-static 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);
-}
-/*--------------------------------------------------------------------------*/
-static 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);
-}
-/*---------------------------------------------------------------------------*/
-static 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;
-
-  Process the array of data in reverse order, to handle the case where
-  the input data is 4-bytes and the output is  8-bytes and the conversion
-  is being done in place in the same array.
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 0.)      /* no scaling */
-        {
-            for (ii = ntodo - 1; ii >= 0; ii--)
-                output[ii] = (long) input[ii];   /* copy input to output */
-        }
-        else             /* must scale the data */
-        {
-            for (ii = ntodo - 1; ii >= 0; 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 = ntodo - 1; ii >= 0; 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 = ntodo - 1; ii >= 0; 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);
-}
-/*---------------------------------------------------------------------------*/
-static 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.
-*/
-{
-    int nullcheck = 1;
-    LONGLONG nullvalue;
-
-    nullvalue = nulval;  /* set local variable */
-
-    fits_read_compressed_pixels(fptr, TLONGLONG, firstelem, nelem,
-            nullcheck, &nullvalue, array, NULL, anynul, status);
-    return(*status);
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/* The following code was copied and modified from the FITSIO source code    */
-/* file getcol.c.                                                            */
-/*                                                                           */
-/*****************************************************************************/
-
-/*---------------------------------------------------------------------------*/
-int _astropy_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 == 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 == 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 == 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);
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/* The following code was copied and modified from the FITSIO source code    */
-/* file putcolb.c.                                                           */
-/*                                                                           */
-/*****************************************************************************/
-
-/*--------------------------------------------------------------------------*/
-static 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).
-*/
-{
-    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.
-    */
-
-    fits_write_compressed_pixels(fptr, TBYTE, firstelem, nelem,
-            0, array, &nullvalue, status);
-    return(*status);
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/* The following code was copied and modified from the FITSIO source code    */
-/* file putcold.c.                                                           */
-/*                                                                           */
-/*****************************************************************************/
-
-/*--------------------------------------------------------------------------*/
-static 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).
-*/
-{
-    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.
-    */
-
-    fits_write_compressed_pixels(fptr, TDOUBLE, firstelem, nelem,
-            0, array, &nullvalue, status);
-    return(*status);
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/* The following code was copied and modified from the FITSIO source code    */
-/* file putcole.c.                                                           */
-/*                                                                           */
-/*****************************************************************************/
-
-/*--------------------------------------------------------------------------*/
-static 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)
-*/
-{
-    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.
-    */
-
-    fits_write_compressed_pixels(fptr, TFLOAT, firstelem, nelem,
-            0, array, &nullvalue, status);
-    return(*status);
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/* The following code was copied and modified from the FITSIO source code    */
-/* file putcoli.c.                                                            */
-/*                                                                           */
-/*****************************************************************************/
-
-/*--------------------------------------------------------------------------*/
-static 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).
-*/
-{
-    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.
-    */
-
-    fits_write_compressed_pixels(fptr, TSHORT, firstelem, nelem,
-            0, array, &nullvalue, status);
-    return(*status);
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/* The following code was copied and modified from the FITSIO source code    */
-/* file putcolk.c.                                                            */
-/*                                                                           */
-/*****************************************************************************/
-
-/*--------------------------------------------------------------------------*/
-static 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).
-*/
-{
-    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.
-    */
-
-    fits_write_compressed_pixels(fptr, TINT, firstelem, nelem,
-            0, array, &nullvalue, status);
-        return(*status);
-    return(*status);
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/* The following code was copied and modified from the FITSIO source code    */
-/* file putcolj.c.                                                            */
-/*                                                                           */
-/*****************************************************************************/
-
-/*--------------------------------------------------------------------------*/
-static 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 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.
-    */
-
-    fits_write_compressed_pixels(fptr, TLONG, firstelem, nelem,
-            0, array, &nullvalue, status);
-    return(*status);
-}
-/* ======================================================================== */
-/*      the following routines support the 'long long' data type            */
-/* ======================================================================== */
-
-/*--------------------------------------------------------------------------*/
-static 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).
-*/
-{
-    /*
-      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.
-    */
-
-    _astropy_ffpmsg("writing to compressed image is not supported");
-
-    return(*status = DATA_COMPRESSION_ERR);
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/* The following code was copied and modified from the FITSIO source code    */
-/* file putcol.c.                                                            */
-/*                                                                           */
-/*****************************************************************************/
-
-/*--------------------------------------------------------------------------*/
-int _astropy_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 == TSHORT)
-    {
-      ffppri(fptr, group, firstelem, nelem, (short *) array, status);
-    }
-    else if (datatype == TINT)
-    {
-      ffpprk(fptr, group, firstelem, nelem, (int *) 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);
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/* The following code was copied and modified from the FITSIO source code    */
-/* file imcompress.c.                                                        */
-/*                                                                           */
-/*****************************************************************************/
-
-#define NULL_VALUE -2147483647 /* value used to represent undefined pixels */
-#define N_RESERVED_VALUES 1   /* 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 */
-
-/* nearest integer function */
-# define NINT(x)  ((x >= 0.) ? (int) (x + 0.5) : (int) (x - 0.5))
-
-/* ######################################################################## */
-/* ###                 Image Compression Routines                       ### */
-/* ######################################################################## */
-
-/*--------------------------------------------------------------------------*/
-int _astropy_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)
-    {
-        /* 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 */
-
-        if (zbitpix == 16 || zbitpix == 8)
-            return(nx * sizeof(short) / 1.3);
-        else
-            return(nx * sizeof(int) / 2);
-    }
-    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));
-}
-/*--------------------------------------------------------------------------*/
-static int imcomp_compress_tile (
-    fitsfile *outfptr,
-    long row,
-    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 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 most cases.
-*/
-{
-    int *idata, *itemp;         /* quantized integer data */
-    short *cbuf;        /* compressed data */
-    short *sbuff;
-    int clen;           /* size of cbuf */
-    size_t gzip_clen;
-    int flag = 1; /* true by default; only = 0 if float data couldn't be */
-                  /* quantized                                           */
-    int iminval = 0, imaxval = 0;  /* min and max quantized integers */
-    double bscale[1] = {1.}, bzero[1] = {0.};   /* scaling parameters */
-    double scale, zero;
-    int  nelem = 0;             /* number of bytes */
-    size_t gzip_nelem = 0;
-    long ii, hcomp_len;
-    LONGLONG *lldata;
-    unsigned char *usbbuff;
-    int ihcompscale, cn_zblank, zbitpix, nullval, flagval, gotnulls;
-    int intlength;  /* size of integers to be compressed */
-    float floatnull, hcompscale;
-    float fminval, fmaxval, delta, zeropt, *fdata, *ftemp;
-    double doublenull, noise3;
-
-    if (*status > 0)
-        return(*status);
-
-    idata = (int *) tiledata;
-    hcompscale = (outfptr->Fptr)->hcomp_scale;
-    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;
-
-    /* =================================================================== */
-    /*  Convert input tile array in place to 4 or 8-byte ints for          */
-    /*  compression, if needed.  Do null value substitution if needed      */
-    /*  Note that the calling routine must have allocated the array big    */
-    /*  enough to be able to do this.                                      */
-
-    if (datatype == TSHORT)
-    {
-       /* datatype of input array is TSHORT.  We only support writing this 
-          datatype to a FITS image with BITPIX = 16 and with BZERO = 0 and 
-          BSCALE = 1.  */
-
-       if (zbitpix != SHORT_IMG || scale != 1.0 || zero != 0.0) {
-           _astropy_ffpmsg("Datatype conversion/scaling is not supported when writing to compressed images");
-           return(*status = DATA_COMPRESSION_ERR);
-       }
-
-       sbuff = (short *) tiledata;
-
-       if (((outfptr->Fptr)->compress_type == RICE_1 || 
-            (outfptr->Fptr)->compress_type == GZIP_1))
-       {
-           /* don't have to convert to int if using gzip 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 {
-           /* 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 = *(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 */
-               for (ii = tilelen - 1; ii >= 0; ii--)
-                   idata[ii] = (int) sbuff[ii];
-           }
-       }
-    }
-    else if (datatype == TINT || (datatype == TLONG && sizeof(long) == 4))
-    {
-       /* 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.) {
-           _astropy_ffpmsg("Implicit datatype conversion is not supported when writing to compressed images");
-           return(*status = DATA_COMPRESSION_ERR);
-       }
-
-       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;
-                  }
-               }
-       }
-    }
-    else if (datatype == TBYTE)
-    {
-       /* 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.) {
-           _astropy_ffpmsg("Implicit datatype conversion is not supported when writing to compressed images");
-           return(*status = DATA_COMPRESSION_ERR);
-       }
-
-       usbbuff = (unsigned char *) tiledata;
-
-       if (((outfptr->Fptr)->compress_type == RICE_1 ||
-            (outfptr->Fptr)->compress_type == GZIP_1))
-       {
-           /* don't have to convert to int if using gzip 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 */
-               for (ii = tilelen - 1; ii >= 0; ii--)
-                   idata[ii] = (int) usbbuff[ii];
-           }
-       }
-    }
-    else if (datatype == TLONG && sizeof(long) == 8)
-    {
-           _astropy_ffpmsg("Integer*8 Long datatype is not supported when writing to compressed images");
-           return(*status = DATA_COMPRESSION_ERR);
-    }
-    else if (datatype == TFLOAT)
-    {
-           intlength = 4;
-
-          /* 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 (scaled) integers.     */
-          if ((outfptr->Fptr)->cn_zscale > 0) {
-            if (nullcheck == 1)
-              floatnull = *(float *) (nullflagval);
-            else
-              floatnull = FLOATNULLVALUE;  /* NaNs are represented by this, by
-                                              default */
-
-            if ((outfptr->Fptr)->quantize_level < 0)  {
-
-              /* negative value represents the absolute quantization level. */
-              /* We don't have to calculate the noise in the image, so do */
-              /* this simple linear scaling in line (here) for efficiency, */
-              /* instead of calling fits_quantize_float */
-
-              delta = ((outfptr->Fptr)->quantize_level) * -1.;
-
-              fdata = tiledata;
-              gotnulls = 0;
-
-              /* set min and max value = first valid pixel value */
-              ftemp = fdata;
-              fminval = 0;
-              fmaxval = 0;
-              for (ii = 0; ii < tilelen; ftemp++, ii++) {
-                  if (*fdata != floatnull) {
-                      fminval = *ftemp;
-                      fmaxval = *ftemp;
-                      break;
-                  }
-              }
-
-              /* find min and max values */
-              ftemp = fdata;
-              for (ii = 0; ii < tilelen; ftemp++, ii++) {
-                  if (*ftemp == floatnull) {
-                      gotnulls = 1;
-                  } else if (*ftemp < fminval) {
-                      fminval = *ftemp;
-                  } else if (*ftemp > fmaxval) {
-                      fmaxval = *ftemp;
-                  }
-              }
-
-              /* check that the range of quantized levels is not > range of int
-              */
-              if ((fmaxval - fminval) / delta > 2. * 2147483647. -
-                  N_RESERVED_VALUES ) {
-                  flag = 0;                     /* don't quantize */
-              } else {
-
-                  flag = 1;
-                  if (!gotnulls) {   /* 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 ((fmaxval - fminval) / delta < 2147483647. - 
-                          N_RESERVED_VALUES ) {
-                          zeropt = fminval;
-                          ftemp = fdata;
-                          itemp = idata;
-                          for (ii = 0;  ii < tilelen;  ftemp++, itemp++, ii++) {
-                              *itemp = (int) (((*ftemp - zeropt) / delta) + 
-                                              0.5f);
-                          }
-                       } else {
-                          /* center the quantized levels around zero */
-                          zeropt = (fminval + fmaxval) / 2.;
-                          for (ii = 0;  ii < tilelen;  ii++) {
-                              idata[ii] = NINT((fdata[ii] - zeropt) / delta);
-                          }
-                      }
-                  } else {
-                      /* data contains null values; shift the range to be */
-                      /* close to the value used to represent null values */
-                     zeropt = fminval - delta*(NULL_VALUE + N_RESERVED_VALUES);
-
-                      for (ii = 0;  ii < tilelen;  ii++) {
-                          if (fdata[ii] != floatnull) {
-                              idata[ii] = NINT ((fdata[ii] - zeropt) / delta);
-                          } else  {
-                              idata[ii] = NULL_VALUE;
-                          }
-                      }
-                 }
-
-                 /* calc min and max values of the integer array */
-
-                 bscale[0] = delta;
-                 bzero[0]  = zeropt;
-              }
-            } else {
-                /* quantize level is positive, so we have to calculate the */
-                /* noise quantize the float values into integers */
-                flag = _astropy_fits_quantize_float ((float *) tiledata, tilenx,
-                   tileny, nullcheck, floatnull,
-                   (outfptr->Fptr)->quantize_level, idata,
-                   bscale, bzero, &iminval, &imaxval);
-            }
-          }
-          else  /* 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 (datatype == TDOUBLE)
-    {
-           intlength = 4;
-
-          /* 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 */
-            flag = _astropy_fits_quantize_double ((double *) tiledata, tilenx,
-               tileny, nullcheck, doublenull, (outfptr->Fptr)->quantize_level,
-               idata, bscale, bzero, &iminval, &imaxval);
-          }
-          else  /* input double 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
-    {
-          _astropy_ffpmsg("unsupported datatype (imcomp_compress_tile)");
-          return(*status = BAD_DATATYPE);
-    }
-
-    /* ==================================================================== */
-
-    if (flag)   /* we can now compress the int array */
-    {
-        /* allocate buffer for the compressed tile bytes */
-        clen = (outfptr->Fptr)->maxelem;
-        cbuf = (short *) calloc (clen, sizeof (unsigned char));
-
-        if (cbuf == NULL)
-        {
-            _astropy_ffpmsg("Out of memory. (imcomp_compress_tile)");
-            return (*status = MEMORY_ALLOCATION);
-        }
-
-    /* =================================================================== */
-
-        /* Compress the integer data, then write the compressed bytes */
-        if ( (outfptr->Fptr)->compress_type == RICE_1)
-        {
-            if (intlength == 2) {
-                nelem = _astropy_fits_rcomp_short ((short *)idata, tilelen,
-                       (unsigned char *) cbuf,
-                       clen, (outfptr->Fptr)->rice_blocksize);
-            } else if (intlength == 1) {
-                nelem = _astropy_fits_rcomp_byte ((signed char *)idata, tilelen,
-                       (unsigned char *) cbuf,
-                       clen, (outfptr->Fptr)->rice_blocksize);
-            } else {
-                nelem = _astropy_fits_rcomp (idata, tilelen,
-                       (unsigned char *) cbuf,
-                       clen, (outfptr->Fptr)->rice_blocksize);
-            }
-
-                /* Write the compressed byte stream. */
-
-                (outfptr->Fptr)->dataLen[row-1] = nelem;
-                (outfptr->Fptr)->data[row-1] = (unsigned char *)cbuf;
-
-        }
-        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 */
-                   _astropy_ffpmsg("data out of range for PLIO compression (0 - 2**24)");
-                   return(*status = DATA_COMPRESSION_ERR);
-                }
-              }
-
-                nelem = _astropy_pl_p2li (idata, 1, cbuf, tilelen);
-
-                /* Write the compressed byte stream. */
-
-                (outfptr->Fptr)->dataLen[row-1] = nelem*2;
-                (outfptr->Fptr)->data[row-1] = (unsigned char *)cbuf;
-        }
-        else if ( (outfptr->Fptr)->compress_type == GZIP_1)
-        {
-
-#if BYTESWAPPED
-           if (intlength == 2)
-               ffswap2((short *) idata, tilelen);
-           else if (intlength == 4)
-               ffswap4(idata, tilelen);
-#endif
-
-           gzip_clen = clen;
-           if (intlength == 2) {
-                 _astropy_compress2mem_from_mem(
-                 (char *) idata, tilelen * sizeof(short),
-                 (char **) &cbuf, (size_t *) &gzip_clen, realloc,
-                 &gzip_nelem, status);
-           } else if (intlength == 1) {
-                _astropy_compress2mem_from_mem((char *) idata, 
-                 tilelen * sizeof(unsigned char),
-                 (char **) &cbuf, (size_t *) &gzip_clen, realloc,
-                 &gzip_nelem, status);
-           } else {
-                _astropy_compress2mem_from_mem(
-                 (char *) idata, tilelen * sizeof(int),
-                 (char **) &cbuf, (size_t *) &gzip_clen, realloc,
-                 &gzip_nelem, status);
-           }
-
-                /* Write the compressed byte stream. */
-
-                (outfptr->Fptr)->dataLen[row-1] = gzip_nelem;
-                (outfptr->Fptr)->data[row-1] = (unsigned char *)cbuf;
-        }
-        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.) {
-               _astropy_fits_img_stats_int(idata, tilenx, tileny, nullcheck,
-                        nullval, 0,0,0,0,0,0,&noise3,status);
-
-                hcompscale = hcompscale * noise3;
-
-            } else if (hcompscale < 0.) {
-
-                hcompscale = hcompscale * -1.0;
-            }
-
-            ihcompscale = (int) (hcompscale + 0.5);
-
-            hcomp_len = clen;  /* allocated size of the buffer */
-
-            if (zbitpix == BYTE_IMG || zbitpix == SHORT_IMG) {
-                _astropy_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 */
-                lldata = (LONGLONG *) idata;
-
-                for (ii = tilelen - 1; ii >= 0; ii--) {
-                    lldata[ii] = idata[ii];;
-                }
-
-                _astropy_fits_hcompress64(lldata, tilenx, tileny,
-                  ihcompscale, (char *) cbuf, &hcomp_len, status);
-            }
-
-            /* Write the compressed byte stream. */
-
-            (outfptr->Fptr)->dataLen[row-1] = hcomp_len;
-            (outfptr->Fptr)->data[row-1] = (unsigned char *)cbuf;
-        }
-
-        if (nelem < 0)  /* error condition */
-        {
-            free (cbuf); cbuf = 0;
-            _astropy_ffpmsg
-                ("error compressing row of the image (imcomp_compress_tile)");
-            return (*status = DATA_COMPRESSION_ERR);
-        }
-
-        if ((outfptr->Fptr)->cn_zscale > 0)
-        {
-              /* write the linear scaling parameters */
-              (outfptr->Fptr)->c_zscale[row-1] = bscale[0];
-              (outfptr->Fptr)->c_zzero[row-1] = bzero[0];
-        }
-    }
-    else     /* floating point data couldn't be quantized */
-    {
-         /* Write the original floating point data. */
-
-         if ((outfptr->Fptr)->cn_uncompressed > 0)
-         {
-             (outfptr->Fptr)->ucDataLen[row-1] = tilelen;
-             (outfptr->Fptr)->ucData[row-1] = (void*)malloc(
-                                                       tilelen*sizeof(double));
-
-             if (datatype == TFLOAT)
-             {
-                 for(ii=0; ii < tilelen; ii++)
-                 {
-                    ((double**)((outfptr->Fptr)->ucData))[row-1][ii] =
-                                                        ((float*)tiledata)[ii];
-                 }
-             }
-             else if (datatype == TDOUBLE)
-             {
-                 for(ii=0; ii < tilelen; ii++)
-                 {
-                    ((double**)((outfptr->Fptr)->ucData))[row-1][ii] =
-                                                       ((double*)tiledata)[ii];
-                 }
-             }
-         }
-         else
-         {
-             _astropy_ffpmsg("There is no UNCOMPRESSED_DATA column in the table.");
-             return(*status = BAD_COL_NUM);
-         }
-
-    }
-
-    return (*status);
-}
-/*---------------------------------------------------------------------------*/
-static 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);
-}
-/*---------------------------------------------------------------------------*/
-static 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);
-}
-/*---------------------------------------------------------------------------*/
-static 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);
-}
-/*---------------------------------------------------------------------------*/
-static 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);
-}
-/*---------------------------------------------------------------------------*/
-static 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);
-}
-/*---------------------------------------------------------------------------*/
-static 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);
-}
-/*---------------------------------------------------------------------------*/
-static 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);
-}
-/*---------------------------------------------------------------------------*/
-static 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 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];
-    int ii, i5, i4, i3, i2, i1, i0, ndim, irow, pixlen;
-    int buffpixsiz;
-    void *buffer;
-    char *bnullarray = 0; //, card[FLEN_CARD];
-
-    if (*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
-    {
-        _astropy_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) { 
-         /* 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
-    {
-        _astropy_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)
-    {
-            _astropy_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); buffer = 0;
-            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];
-
-              memset(buffer, 0, pixlen * thistilesize[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); buffer = 0;
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-static 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 */
-    naxis = (fptr->Fptr)->zndim;
-
-    for ( ii = 0; ii < (fptr->Fptr)->zndim; ii++)
-    {
-        naxes[ii] = ((fptr->Fptr)->znaxis)[ii];
-    }
-    /* calc the cumulative number of pixels in each successive dimension */
-
-    /* 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
-    {
-        _astropy_ffpmsg("only 1D, 2D, or 3D images are currently supported");
-        return(*status = DATA_COMPRESSION_ERR);
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-static 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                     ### */
-/* ######################################################################## */
-
-/*---------------------------------------------------------------------------*/
-static 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.
-*/
-{
-    int 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];
-    int ii, i5, i4, i3, i2, i1, i0, ndim, irow, pixlen, tilenul;
-    void *buffer;
-    char *bnullarray = 0;
-    double testnullval = 0.;
-
-    if (*status > 0)
-        return(*status);
-
-    /* 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
-    {
-        _astropy_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)
-    {
-        _astropy_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)
-        {
-            _astropy_ffpmsg("Out of memory (fits_read_compress_img)");
-            free(buffer); buffer = 0;
-            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); bnullarray = 0;
-            }
-            free(buffer); buffer = 0;
-            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];
-
-              /* 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 */
-              /* 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); bnullarray = 0;
-    }
-    free(buffer); buffer = 0;
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-static 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 */
-    naxis = (fptr->Fptr)->zndim;
-
-    for ( ii = 0; ii < (fptr->Fptr)->zndim; ii++)
-    {
-        naxes[ii] = ((fptr->Fptr)->znaxis)[ii];
-    }
-    /* 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
-    {
-        _astropy_ffpmsg("only 1D, 2D, or 3D images are currently supported");
-        return(*status = DATA_DECOMPRESSION_ERR);
-    }
-
-    return(*status);
-}
-///*--------------------------------------------------------------------------*/
-static 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);
-}
-/*--------------------------------------------------------------------------*/
-static 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 */
-{
-    static int *idata = 0;     /* this variable must persist */
-    int tiledatatype, pixlen;          /* uncompressed integer data */
-    LONGLONG *lldata = 0;
-    size_t idatalen, tilebytesize;
-    int ii, tnull = 0;        /* value in the data which represents nulls */
-    short *sbuf;
-    int blocksize;
-    double bscale, bzero, dummy = 0;    /* scaling parameters */
-    long nelem = 0;      /* number of bytes */
-    int smooth, nx, ny, scale;  /* hcompress parameters */
-
-    if (*status > 0)
-       return(*status);
-
-    nelem = (infptr->Fptr)->dataLen[nrow-1];
-
-    if (nelem == 0)  /* tile was not compressed; read uncompressed data */
-    {
-        if ((infptr->Fptr)->cn_uncompressed < 1 )
-        {
-            return (*status = NO_COMPRESSED_TILE);
-        }
-
-        /* no compressed data, so simply read the uncompressed data */
-        /* directly from the UNCOMPRESSED_DATA column, then return */
-
-        for (ii = 0; ii < ((infptr->Fptr)->ucDataLen)[nrow-1]; ii++)
-        {
-            if (datatype == TFLOAT)
-            {
-                ((float*)buffer)[ii] =
-                              ((float**)((infptr->Fptr)->ucData))[nrow-1][ii];
-            }
-            else if (datatype == TDOUBLE)
-            {
-                ((double*)buffer)[ii] =
-                             ((double**)((infptr->Fptr)->ucData))[nrow-1][ii];
-            }
-        }
-
-        ((infptr->Fptr)->dataLen)[nrow-1] = ((infptr->Fptr)->ucDataLen)[nrow-1];
-
-        return(*status);
-    }
-
-    /* **************************************************************** */
-
-    if (nullcheck == 2)
-    {
-        for (ii = 0; ii < tilelen; ii++)  /* initialize the null array */
-            bnullarray[ii] = 0;
-    }
-
-    if (anynul)
-       *anynul = 0;
-
-    /* get linear scaling and offset values, if they exist */
-
-    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 */
-        bscale = ((infptr->Fptr)->bscale)[nrow-1];
-        bzero = ((infptr->Fptr)->bzero)[nrow-1];
-
-        /* 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 */
-        tnull = ((infptr->Fptr)->blank)[nrow-1];
-    }
-
-    /* ************************************************************* */
-
-    /* allocate memory for the uncompressed array of tile integers */
-
-    if ((infptr->Fptr)->compress_type == HCOMPRESS_1 &&
-          ((infptr->Fptr)->zbitpix != BYTE_IMG &&
-           (infptr->Fptr)->zbitpix != SHORT_IMG) ) {
-
-           /*  must allocate 8 bytes per pixel of scratch space */
-           lldata = (LONGLONG*) malloc (tilelen * sizeof (LONGLONG));
-           idata = (int *) lldata;
-    } else if ( (infptr->Fptr)->compress_type == RICE_1 &&
-               (infptr->Fptr)->zbitpix == BYTE_IMG &&
-               (infptr->Fptr)->rice_bytepix == 1) {
-
-           /*  must allocate 1 byte per pixel of scratch space */
-           idatalen = tilelen;
-           idata = (int *) malloc (idatalen);
-    } else if ( (infptr->Fptr)->compress_type == RICE_1 &&
-               (infptr->Fptr)->zbitpix == SHORT_IMG &&
-               (infptr->Fptr)->rice_bytepix == 2) {
-
-           /*  must allocate 2 bytes per pixel of scratch space */
-           idatalen = tilelen * sizeof(short);
-           idata = (int *) malloc (idatalen);
-     } else if ( (infptr->Fptr)->compress_type == GZIP_1 &&
-               (infptr->Fptr)->zbitpix == SHORT_IMG ) {
-
-           /*  must allocate 2 bytes per pixel of scratch space */
-           idatalen = tilelen * sizeof(short);
-           idata = (int *) malloc (idatalen);
-    } else if ((infptr->Fptr)->compress_type == GZIP_1 &&
-               (infptr->Fptr)->zbitpix == BYTE_IMG ) {
-
-           /*  must allocate 1 byte per pixel of scratch space */
-           idatalen = tilelen * sizeof(char);
-           idata = (int *) malloc (idatalen);
-    } else {
-           /* all other cases have int pixels */
-           idatalen = tilelen * sizeof(int);
-           idata = (int*) malloc (idatalen);
-    }
-
-    if (idata == NULL)
-    {
-            _astropy_ffpmsg("Out of memory for idata. (imcomp_decompress_tile)");
-            return (*status = MEMORY_ALLOCATION);
-    }
-
-    /* ************************************************************* */
-    /*    call the algorithm-specific code to uncompress the tile */
-
-    /* default uncomopressed pixels have int data type */
-    tiledatatype = TINT;
-
-    if ((infptr->Fptr)->compress_type == RICE_1)
-    {
-
-        /* uncompress the data */
-        blocksize = (infptr->Fptr)->rice_blocksize;
-
-         if ((infptr->Fptr)->rice_bytepix == 1 ) {
-            if ((*status = _astropy_fits_rdecomp_byte (
-                ((infptr->Fptr)->data)[nrow-1],
-                ((infptr->Fptr)->dataLen)[nrow-1],
-                (unsigned char *)idata,
-                tilelen, blocksize)))
-            {
-                free(idata);
-                return (*status);
-            }
-            tiledatatype = TBYTE;
-        } else if ((infptr->Fptr)->rice_bytepix == 2 ) {
-            if ((*status = _astropy_fits_rdecomp_short (
-                ((infptr->Fptr)->data)[nrow-1],
-                ((infptr->Fptr)->dataLen)[nrow-1],
-                (unsigned short *)idata,
-                tilelen, blocksize)))
-            {
-                free(idata);
-                return (*status);
-            }
-            tiledatatype = TSHORT;
-        } else {
-            if ((*status = _astropy_fits_rdecomp (
-                ((infptr->Fptr)->data)[nrow-1],
-                ((infptr->Fptr)->dataLen)[nrow-1],
-                (unsigned int *)idata,
-                tilelen, blocksize)))
-            {
-                free(idata);
-                return (*status);
-            }
-            tiledatatype = TINT;
-        }
-
-    }
-
-    /* ************************************************************* */
-
-    else if ((infptr->Fptr)->compress_type == HCOMPRESS_1)
-    {
-        /* uncompress the data */
-        smooth = (infptr->Fptr)->hcomp_smooth;
-
-        if ( ((infptr->Fptr)->zbitpix == BYTE_IMG ||
-               (infptr->Fptr)->zbitpix == SHORT_IMG) )  {
-
-            if ((*status = _astropy_fits_hdecompress(
-                                          ((infptr->Fptr)->data)[nrow-1],
-                                            smooth, idata, &nx, &ny,
-                                            &scale, status)))
-            {
-                free(idata); idata = 0;
-                return (*status);
-            }
-
-        } else {
-
-            /* idata must have been allocated twice as large for this to work */
-            if ((*status = _astropy_fits_hdecompress64(
-                                            ((infptr->Fptr)->data)[nrow-1],
-                                              smooth, lldata, &nx, &ny,
-                &scale, status)))
-            {
-                free(idata); idata = 0;
-                return (*status);
-            }
-        }
-
-    }
-
-    /* ************************************************************* */
-
-    else if ((infptr->Fptr)->compress_type == PLIO_1)
-    {
-        nelem = ((infptr->Fptr)->dataLen)[nrow-1];
-        nelem = nelem/2;
-
-        sbuf = ((short *)(((infptr->Fptr)->data)[nrow-1]));
-
-#if BYTESWAPPED
-        ffswap2(sbuf, nelem); /* reverse order of bytes */
-#endif
-
-        _astropy_pl_l2pi (sbuf, 1, idata, tilelen);  /* uncompress the data */
-
-    }
-
-    /* ************************************************************* */
-
-    else if ((infptr->Fptr)->compress_type == GZIP_1)
-    {
-        /* uncompress the data */
-
-        if (_astropy_uncompress2mem_from_mem
-                                    ((char *)((infptr->Fptr)->data)[nrow-1],
-                                     ((infptr->Fptr)->dataLen)[nrow-1],
-             (char **) &idata, &idatalen, realloc, &tilebytesize, status))
-        {
-            _astropy_ffpmsg("_astropy_uncompress2mem_from_mem returned with an error");
-            free(idata); idata = 0;
-            return (*status);
-        }
-
-        if (tilebytesize == tilelen * 2) {
-            /* this is a short I*2 array */
-            tiledatatype = TSHORT;
-
-#if BYTESWAPPED
-            ffswap2((short *) idata, tilelen);
-#endif
-
-        } else if (tilebytesize == tilelen * 4) {
-            /* this is a int I*4 array */
-            tiledatatype = TINT;
-
-#if BYTESWAPPED
-         ffswap4(idata, tilelen); /* reverse order of bytes */
-#endif
-
-        } else if (tilebytesize == tilelen) {
-
-            /* this is an unsigned char I*1 array */
-            tiledatatype = TBYTE;
-
-        } else {
-            _astropy_ffpmsg("error: uncompressed tile has wrong size");
-            free(idata);
-            return (*status = DATA_DECOMPRESSION_ERR);
-        }
-    }
-
-    /* ************************************************************* */
-    else
-    {
-        _astropy_ffpmsg("unknown compression algorithm");
-        free(idata); idata = 0;
-        return (*status = DATA_DECOMPRESSION_ERR);
-    }
-
-    /* ************************************************************* */
-    /* 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 (tiledatatype == TINT)
-          fffi4i2(idata, tilelen, bscale, bzero, nullcheck, tnull,
-           *(short *) nulval, bnullarray, anynul,
-          (short *) buffer, status);
-        else if (tiledatatype == TSHORT)
-        {
-          fffi2i2((short *)idata, tilelen, bscale, bzero, nullcheck, tnull,
-           *(short *) nulval, bnullarray, anynul,
-          (short *) buffer, status);
-        }
-        else if (tiledatatype == TBYTE)
-          fffi1i2((unsigned char *)idata, tilelen, bscale, bzero, nullcheck,
-           tnull, *(short *) nulval, bnullarray, anynul,
-           (short *) buffer, status);
-    }
-    else if (datatype == TINT)
-    {
-        pixlen = sizeof(int);
-        if (tiledatatype == TINT)
-          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, tnull,
-           *(int *) nulval, bnullarray, anynul,
-           (int *) buffer, status);
-        else if (tiledatatype == TBYTE)
-          fffi1int((unsigned char *)idata, tilelen, bscale, bzero, nullcheck,
-           tnull, *(int *) nulval, bnullarray, anynul,
-           (int *) buffer, status);
-    }
-    else if (datatype == TLONG)
-    {
-        pixlen = sizeof(long);
-        if (tiledatatype == TINT)
-          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, tnull,
-           *(long *) nulval, bnullarray, anynul,
-            (long *) buffer, status);
-        else if (tiledatatype == TBYTE)
-          fffi1i4((unsigned char *)idata, tilelen, bscale, bzero, nullcheck,
-            tnull, *(long *) nulval, bnullarray, anynul,
-            (long *) buffer, status);
-    }
-    else if (datatype == TFLOAT)
-    {
-        pixlen = sizeof(float);
-        if (tiledatatype == TINT)
-          fffi4r4(idata, tilelen, bscale, bzero, nullcheck, tnull,
-           *(float *) nulval, bnullarray, anynul,
-            (float *) buffer, status);
-        else if (tiledatatype == TSHORT)
-          fffi2r4((short *)idata, tilelen, bscale, bzero, nullcheck, tnull,
-           *(float *) nulval, bnullarray, anynul,
-            (float *) buffer, status);
-        else if (tiledatatype == TBYTE)
-          fffi1r4((unsigned char *)idata, tilelen, bscale, bzero, nullcheck,
-            tnull, *(float *) nulval, bnullarray, anynul,
-            (float *) buffer, status);
-    }
-    else if (datatype == TDOUBLE)
-    {
-        pixlen = sizeof(double);
-        if (tiledatatype == TINT)
-          fffi4r8(idata, tilelen, bscale, bzero, nullcheck, tnull,
-           *(double *) nulval, bnullarray, anynul,
-            (double *) buffer, status);
-        else if (tiledatatype == TSHORT)
-          fffi2r8((short *)idata, tilelen, bscale, bzero, nullcheck, tnull,
-           *(double *) nulval, bnullarray, anynul,
-            (double *) buffer, status);
-        else if (tiledatatype == TBYTE)
-          fffi1r8((unsigned char *)idata, tilelen, bscale, bzero, nullcheck,
-            tnull, *(double *) nulval, 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, tnull,
-           *(unsigned char *) nulval, bnullarray, anynul,
-            (unsigned char *) buffer, status);
-        else if (tiledatatype == TBYTE)
-          fffi1i1((unsigned char *)idata, tilelen, bscale, bzero, nullcheck,
-            tnull, *(unsigned char *) nulval, bnullarray, anynul,
-            (unsigned char *) buffer, status);
-    }
-    else
-    {
-         *status = BAD_DATATYPE;
-    }
-
-    free(idata); idata = 0;
-
-    return (*status);
-}
-/*--------------------------------------------------------------------------*/
-static 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 */
-        }
-        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;
-             /* offset to byte within the row */
-             if (inc[0] > 0)
-                imgpix = imgfpix[0] + im1;
-             else
-                imgpix = imgdim[0] - 1 - imgfpix[0] + im1;
-             /* 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;
-               /* 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);
-}
-
-/*--------------------------------------------------------------------------*/
-static 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 */
-        }
-        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;
-             /* offset to byte within the row */
-             if (inc[0] > 0)
-                imgpix = imgfpix[0] + im1;
-             else
-                imgpix = imgdim[0] - 1 - imgfpix[0] + im1;
-             /* 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;
-               /* 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);
-}
-
-
-
-
-
diff --git a/astropy/io/fits/src/fitsio.h b/astropy/io/fits/src/fitsio.h
deleted file mode 100644
index 8a2f963..0000000
--- a/astropy/io/fits/src/fitsio.h
+++ /dev/null
@@ -1,509 +0,0 @@
-/* $Id$
-*/
-
-/*****************************************************************************/
-/*                                                                           */
-/* This file, fitsio.h, contains the header information for the core of a    */
-/* set of FITSIO routines that are used to compress and uncompress image     */
-/* data in FITS binary tables.  The code was copied and modified from the    */
-/* FITSIO software written at HEASRC.  The goal for the astropyComp module    */
-/* was to take this code nearly intact.  In FITSIO, interaction with the     */
-/* FITS file is accomplished directly within the FITSIO code.  With          */
-/* astropyComp, interaction with the FITS file is accomplished from within    */
-/* astropy.  This may make some of the constructs within the FISTIO code seem */
-/* confusing when viewed from the perspective of astropyComp.  It should be   */
-/* noted that the FITSfile structure acts as the interface to the file in    */
-/* both cases.  In FITSIO it contains the file handle in order to access the */
-/* file, and in astropyComp it holds the file data, either compressed or      */
-/* uncompressed.                                                             */
-/*                                                                           */
-/* Copyright (C) 2004 Association of Universities for Research in Astronomy  */
-/* (AURA)                                                                    */
-/*                                                                           */
-/* Redistribution and use in source and binary forms, with or without        */
-/* modification, are permitted provided that the following conditions are    */
-/* met:                                                                      */
-/*                                                                           */
-/*    1. Redistributions of source code must retain the above copyright      */
-/*      notice, this list of conditions and the following disclaimer.        */
-/*                                                                           */
-/*    2. Redistributions in binary form must reproduce the above             */
-/*      copyright notice, this list of conditions and the following          */
-/*      disclaimer in the documentation and/or other materials provided      */
-/*      with the distribution.                                               */
-/*                                                                           */
-/*    3. The name of AURA and its representatives may not be used to         */
-/*      endorse or promote products derived from this software without       */
-/*      specific prior written permission.                                   */
-/*                                                                           */
-/* THIS SOFTWARE IS PROVIDED BY AURA ``AS IS'' AND ANY EXPRESS OR IMPLIED    */
-/* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF      */
-/* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE                  */
-/* DISCLAIMED. IN NO EVENT SHALL AURA BE LIABLE FOR ANY DIRECT, INDIRECT,    */
-/* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,      */
-/* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS     */
-/* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND    */
-/* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR     */
-/* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE    */
-/* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH          */
-/* DAMAGE.                                                                   */
-/*                                                                           */
-/* This file contains source code that was copied and modified from the      */
-/* FITSIO software that was written by William Pence at the High Energy      */
-/* Astrophysic Science Archive Research Center (HEASARC) at the NASA Goddard */
-/* Space Flight Center.  That software contained the following copyright and */
-/* warranty notices:                                                         */
-/*                                                                           */
-/* 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
-
-#include <stdio.h>
-
-/* 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 <sys/types.h>  /* apparently needed on debian linux systems */
-#endif                    /* to define off_t                           */
-
-#include <stdlib.h>  /* apparently needed to define size_t with gcc 2.8.1 */
-#include <limits.h>  /* 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 the 2nd test, below,         */
-/*  i.e, "(defined(linux) && defined(__off_t_defined))" */
-#if defined(_OFF_T) || (defined(linux) && defined(__off_t_defined)) || defined(_MIPS_SZLONG) || defined(__APPLE__) || defined(_AIX)
-#    define OFF_T off_t
-#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(__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  
-
-#define TBIT          1  /* codes for FITS table data types */
-#define TBYTE        11
-#define TSBYTE       12
-#define TLOGICAL     14
-#define TUSHORT      20
-#define TSHORT       21
-#define TUINT        30
-#define TINT         31
-#define TULONG       40
-#define TLONG        41
-#define TFLOAT       42
-#define TLONGLONG    81
-#define TDOUBLE      82
-
-#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
-
-/* 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
- 
-/* Image compression algorithm types */
-#define MAX_COMPRESS_DIM     6
-#define RICE_1      11
-#define GZIP_1      21
-#define PLIO_1      31
-#define HCOMPRESS_1 41
-#define NOCOMPRESS  0
-
-#ifndef TRUE
-#define TRUE 1
-#endif
-
-#ifndef FALSE
-#define FALSE 0
-#endif
-
-
-typedef struct      /* structure used to store basic FITS file information */
-{
-    unsigned char** data;  /* Compressed data */
-    int* dataLen;          /* Length of compressed data */
-    double* c_zscale;        /* Scale factors for zscale column */
-    double* c_zzero;         /* Zero values for zzero column */
-    void** ucData;           /* Uncompressed data for failure to quantize */
-    int* ucDataLen;          /* Length of uncompressed data */
-    int compress_type;      /* type of compression algorithm */
-    int zbitpix;            /* FITS data type of image (BITPIX) */
-    int zndim;              /* dimension of image */
-    long znaxis[MAX_COMPRESS_DIM];  /* length of each axis */
-    long tilesize[MAX_COMPRESS_DIM]; /* size of compression tiles */
-    long maxtilelen;        /* max number of pixels in each image tile */
-    long maxelem;		/* maximum length of variable length arrays */
-    int cn_uncompressed;    /* column number for UNCOMPRESSED_DATA column */
-    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* bscale;        /* BSCALE value for each tile in the image */
-    double* bzero;         /* BZERO value for each tile in the image */
-    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 in header */
-    long* blank;          /* value for null pixels for each tile in the image */
-    int zblank;             /* value for null pixels, if not a column */
-    int rice_blocksize;     /* first compression parameter */
-    int rice_bytepix;       /* 2nd compression parameter: bytes/pixel */
-    float quantize_level;   /* floating point quantization level */
-    float hcomp_scale;      /* 1st hcompress compression parameter */
-    int hcomp_smooth;       /* 2nd hcompress compression parameter */
-} FITSfile;
-
-typedef struct         /* structure used to store basic HDU information */
-{
-    FITSfile *Fptr;   /* pointer to FITS file structure */
-}fitsfile;
-
-/* error status codes */
-
-#define OVERFLOW_ERR      -11  /* overflow during datatype conversion */
-#define MEMORY_ALLOCATION 113  /* Could not allocate memory */
-#define BAD_COL_NUM       302  /* column number < 1 or > tfields */
-#define BAD_PIX_NUM       321  /* first pixel number greater than last pixel */
-#define NEG_AXIS          323  /* illegal axis length < 1 */
-#define BAD_DATATYPE      410  /* bad keyword datatype code */
-# 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 */
-
-/* ======================================================================= */
-/* 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)
-                               /*  SUN Solaris7 in 64-bit mode */
-#define BYTESWAPPED FALSE
-#define MACHINE NATIVE
-#define LONGSIZE 64
-
-#elif defined(__ia64__)  || defined(__x86_64__)
-                  /*  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__) /* IBM 64-bit AIX powerpc*/
-                              /* could also test for __ppc64__ or __PPC64 */
-#define BYTESWAPPED FALSE
-#define MACHINE NATIVE
-#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
-
-#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 maxvalue(A,B) ((A) > (B) ? (A) : (B))
-#define minvalue(A,B) ((A) < (B) ? (A) : (B))
-
-#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 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 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
-
-/*---------------- utility routines -------------*/
-
-void _astropy_ffpmsg(const char *err_message);
-int  _astropy_ffgmsg(char *err_message);
-int  _astropy_ffgpv(fitsfile *fptr, int  datatype, LONGLONG firstelem,
-          LONGLONG nelem, void *nulval, void *array, int *anynul, int  *status);
-int  _astropy_ffppr(fitsfile *fptr, int datatype, LONGLONG  firstelem,
-          LONGLONG nelem, void *array, int *status);
-
-/*--------------------- group template parser routines ------------------*/
-
-int _astropy_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 *noise3, int *status);
-
-/* H-compress routines */
-int _astropy_fits_hcompress(int *a, int nx, int ny, int scale, char *output, 
-    long *nbytes, int *status);
-int _astropy_fits_hcompress64(LONGLONG *a, int nx, int ny, int scale,
-    char *output, long *nbytes, int *status);
-int _astropy_fits_hdecompress(unsigned char *input, int smooth, int *a, int *nx, 
-    int *ny, int *scale, int *status);
-int _astropy_fits_hdecompress64(unsigned char *input, int smooth, LONGLONG *a,
-    int *nx, int *ny, int *scale, int *status);
-
-
-/*  image compression routines */
-
-int _astropy_imcomp_calc_max_elem (int comptype, int nx, int zbitpix,
-                                  int blocksize);
-
-
-/*  image decompression routines */
-int _astropy_fits_quantize_float (float fdata[], long nx, long ny, int nullcheck,
-         float in_null_value,
-         float quantize_level, int idata[], double *bscale, double *bzero,
-         int *iminval, int *imaxval);
-int _astropy_fits_quantize_double (double fdata[], long nx, long ny,
-         int nullcheck, double in_null_value,
-         float quantize_level, int idata[], double *bscale, double *bzero,
-         int *iminval, int *imaxval);
-int _astropy_fits_rcomp(int a[], int nx, unsigned char *c, int clen,int nblock);
-int _astropy_fits_rcomp_short(short a[], int nx, unsigned char *c, int clen,
-                             int nblock);
-int _astropy_fits_rcomp_byte(signed char a[], int nx, unsigned char *c, int clen,
-                            int nblock);
-int _astropy_fits_rdecomp (unsigned char *c, int clen, unsigned int array[],
-                          int nx, int nblock);
-int _astropy_fits_rdecomp_short (unsigned char *c, int clen,
-                                unsigned short array[], int nx, int nblock);
-int _astropy_fits_rdecomp_byte (unsigned char *c, int clen,
-                               unsigned char array[], int nx, int nblock);
-int _astropy_pl_p2li (int *pxsrc, int xs, short *lldst, int npix);
-int _astropy_pl_l2pi (short *ll_src, int xs, int *px_dst, int npix);
-
-int _astropy_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 _astropy_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);
-
-/* Translate the long names for some routines to their actual short names */
-
-#define _astropy_fits_read_img  _astropy_ffgpv
-#define _astropy_fits_write_img _astropy_ffppr
-#define fits_write_img_usht    ffpprui
-
-#endif
-
diff --git a/astropy/io/fits/src/inffast.c b/astropy/io/fits/src/inffast.c
deleted file mode 100644
index e9eb8c9..0000000
--- a/astropy/io/fits/src/inffast.c
+++ /dev/null
@@ -1,411 +0,0 @@
-/* $Id$
-*/
-
-/*****************************************************************************/
-/*                                                                           */
-/* This file, inffast.c, contains the code required to compress and          */
-/* uncompress data using the GZIP_1 compression format.                      */
-/*                                                                           */
-/* Copyright (C) 2004 Association of Universities for Research in Astronomy  */
-/* (AURA)                                                                    */
-/*                                                                           */
-/* Redistribution and use in source and binary forms, with or without        */
-/* modification, are permitted provided that the following conditions are    */
-/* met:                                                                      */
-/*                                                                           */
-/*    1. Redistributions of source code must retain the above copyright      */
-/*      notice, this list of conditions and the following disclaimer.        */
-/*                                                                           */
-/*    2. Redistributions in binary form must reproduce the above             */
-/*      copyright notice, this list of conditions and the following          */
-/*      disclaimer in the documentation and/or other materials provided      */
-/*      with the distribution.                                               */
-/*                                                                           */
-/*    3. The name of AURA and its representatives may not be used to         */
-/*      endorse or promote products derived from this software without       */
-/*      specific prior written permission.                                   */
-/*                                                                           */
-/* THIS SOFTWARE IS PROVIDED BY AURA ``AS IS'' AND ANY EXPRESS OR IMPLIED    */
-/* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF      */
-/* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE                  */
-/* DISCLAIMED. IN NO EVENT SHALL AURA BE LIABLE FOR ANY DIRECT, INDIRECT,    */
-/* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,      */
-/* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS     */
-/* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND    */
-/* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR     */
-/* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE    */
-/* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH          */
-/* DAMAGE.                                                                   */
-/*                                                                           */
-/* This code was copied and heavily modified from the ZLIB compression       */
-/* library that was written by Jean-loup Gailly and Mark Adler.  That        */
-/* software containes the following copyright and warranty notices:          */
-/*                                                                           */
-/*  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 at gzip.org          madler at 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).              */
-/*                                                                           */
-/*****************************************************************************/
-
-/* This code was copied unmodified from ZLIB inffast.c -- fast decoding      */
-
-#include "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 */
diff --git a/astropy/io/fits/src/inffast.h b/astropy/io/fits/src/inffast.h
deleted file mode 100644
index 69adfa1..0000000
--- a/astropy/io/fits/src/inffast.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/* $Id$
-*/
-
-/*****************************************************************************/
-/*                                                                           */
-/* This file, zlib.h, contains the include information required to compress  */
-/* and uncompress data using the GZIP_1 compression format.                  */
-/*                                                                           */
-/* Copyright (C) 2004 Association of Universities for Research in Astronomy  */
-/* (AURA)                                                                    */
-/*                                                                           */
-/* Redistribution and use in source and binary forms, with or without        */
-/* modification, are permitted provided that the following conditions are    */
-/* met:                                                                      */
-/*                                                                           */
-/*    1. Redistributions of source code must retain the above copyright      */
-/*      notice, this list of conditions and the following disclaimer.        */
-/*                                                                           */
-/*    2. Redistributions in binary form must reproduce the above             */
-/*      copyright notice, this list of conditions and the following          */
-/*      disclaimer in the documentation and/or other materials provided      */
-/*      with the distribution.                                               */
-/*                                                                           */
-/*    3. The name of AURA and its representatives may not be used to         */
-/*      endorse or promote products derived from this software without       */
-/*      specific prior written permission.                                   */
-/*                                                                           */
-/* THIS SOFTWARE IS PROVIDED BY AURA ``AS IS'' AND ANY EXPRESS OR IMPLIED    */
-/* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF      */
-/* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE                  */
-/* DISCLAIMED. IN NO EVENT SHALL AURA BE LIABLE FOR ANY DIRECT, INDIRECT,    */
-/* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,      */
-/* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS     */
-/* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND    */
-/* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR     */
-/* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE    */
-/* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH          */
-/* DAMAGE.                                                                   */
-/*                                                                           */
-/* This code was copied and heavily modified from the ZLIB compression       */
-/* library that was written by Jean-loup Gailly and Mark Adler.  That        */
-/* software containes the following copyright and warranty notices:          */
-/*                                                                           */
-/*  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 at gzip.org          madler at 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).              */
-/*                                                                           */
-/*****************************************************************************/
-
-/* This code was copied unmodified from ZLIB inffast.h                       */
-
-void ZLIB_INTERNAL inflate_fast OF((z_streamp strm, unsigned start));
diff --git a/astropy/io/fits/src/inffixed.h b/astropy/io/fits/src/inffixed.h
deleted file mode 100644
index dec7acb..0000000
--- a/astropy/io/fits/src/inffixed.h
+++ /dev/null
@@ -1,162 +0,0 @@
-/* $Id$
-*/
-
-/*****************************************************************************/
-/*                                                                           */
-/* This file, zlib.h, contains the include information required to compress  */
-/* and uncompress data using the GZIP_1 compression format.                  */
-/*                                                                           */
-/* Copyright (C) 2004 Association of Universities for Research in Astronomy  */
-/* (AURA)                                                                    */
-/*                                                                           */
-/* Redistribution and use in source and binary forms, with or without        */
-/* modification, are permitted provided that the following conditions are    */
-/* met:                                                                      */
-/*                                                                           */
-/*    1. Redistributions of source code must retain the above copyright      */
-/*      notice, this list of conditions and the following disclaimer.        */
-/*                                                                           */
-/*    2. Redistributions in binary form must reproduce the above             */
-/*      copyright notice, this list of conditions and the following          */
-/*      disclaimer in the documentation and/or other materials provided      */
-/*      with the distribution.                                               */
-/*                                                                           */
-/*    3. The name of AURA and its representatives may not be used to         */
-/*      endorse or promote products derived from this software without       */
-/*      specific prior written permission.                                   */
-/*                                                                           */
-/* THIS SOFTWARE IS PROVIDED BY AURA ``AS IS'' AND ANY EXPRESS OR IMPLIED    */
-/* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF      */
-/* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE                  */
-/* DISCLAIMED. IN NO EVENT SHALL AURA BE LIABLE FOR ANY DIRECT, INDIRECT,    */
-/* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,      */
-/* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS     */
-/* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND    */
-/* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR     */
-/* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE    */
-/* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH          */
-/* DAMAGE.                                                                   */
-/*                                                                           */
-/* This code was copied and heavily modified from the ZLIB compression       */
-/* library that was written by Jean-loup Gailly and Mark Adler.  That        */
-/* software containes the following copyright and warranty notices:          */
-/*                                                                           */
-/*  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 at gzip.org          madler at 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).              */
-/*                                                                           */
-/*****************************************************************************/
-
-/* This code was copied unmodified from ZLIB inffixed.h -- table for         */
-/* decoding fixed codes                                                      */
-
-    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}
-    };
diff --git a/astropy/io/fits/src/inflate.h b/astropy/io/fits/src/inflate.h
deleted file mode 100644
index 34b640c..0000000
--- a/astropy/io/fits/src/inflate.h
+++ /dev/null
@@ -1,181 +0,0 @@
-/* $Id$
-*/
-
-/*****************************************************************************/
-/*                                                                           */
-/* This file, zlib.h, contains the include information required to compress  */
-/* and uncompress data using the GZIP_1 compression format.                  */
-/*                                                                           */
-/* Copyright (C) 2004 Association of Universities for Research in Astronomy  */
-/* (AURA)                                                                    */
-/*                                                                           */
-/* Redistribution and use in source and binary forms, with or without        */
-/* modification, are permitted provided that the following conditions are    */
-/* met:                                                                      */
-/*                                                                           */
-/*    1. Redistributions of source code must retain the above copyright      */
-/*      notice, this list of conditions and the following disclaimer.        */
-/*                                                                           */
-/*    2. Redistributions in binary form must reproduce the above             */
-/*      copyright notice, this list of conditions and the following          */
-/*      disclaimer in the documentation and/or other materials provided      */
-/*      with the distribution.                                               */
-/*                                                                           */
-/*    3. The name of AURA and its representatives may not be used to         */
-/*      endorse or promote products derived from this software without       */
-/*      specific prior written permission.                                   */
-/*                                                                           */
-/* THIS SOFTWARE IS PROVIDED BY AURA ``AS IS'' AND ANY EXPRESS OR IMPLIED    */
-/* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF      */
-/* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE                  */
-/* DISCLAIMED. IN NO EVENT SHALL AURA BE LIABLE FOR ANY DIRECT, INDIRECT,    */
-/* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,      */
-/* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS     */
-/* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND    */
-/* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR     */
-/* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE    */
-/* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH          */
-/* DAMAGE.                                                                   */
-/*                                                                           */
-/* This code was copied and heavily modified from the ZLIB compression       */
-/* library that was written by Jean-loup Gailly and Mark Adler.  That        */
-/* software containes the following copyright and warranty notices:          */
-/*                                                                           */
-/*  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 at gzip.org          madler at 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).              */
-/*                                                                           */
-/*****************************************************************************/
-
-/* This code was copied unmodifiedfrom ZLIB inflate.h -- internal inflate    */
-/* state definition                                                          */
-
-/* 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 */
-};
diff --git a/astropy/io/fits/src/inftrees.c b/astropy/io/fits/src/inftrees.c
deleted file mode 100644
index c2119be..0000000
--- a/astropy/io/fits/src/inftrees.c
+++ /dev/null
@@ -1,401 +0,0 @@
-/* $Id$
-*/
-
-/*****************************************************************************/
-/*                                                                           */
-/* This file, inffast.c, contains the code required to compress and          */
-/* uncompress data using the GZIP_1 compression format.                      */
-/*                                                                           */
-/* Copyright (C) 2004 Association of Universities for Research in Astronomy  */
-/* (AURA)                                                                    */
-/*                                                                           */
-/* Redistribution and use in source and binary forms, with or without        */
-/* modification, are permitted provided that the following conditions are    */
-/* met:                                                                      */
-/*                                                                           */
-/*    1. Redistributions of source code must retain the above copyright      */
-/*      notice, this list of conditions and the following disclaimer.        */
-/*                                                                           */
-/*    2. Redistributions in binary form must reproduce the above             */
-/*      copyright notice, this list of conditions and the following          */
-/*      disclaimer in the documentation and/or other materials provided      */
-/*      with the distribution.                                               */
-/*                                                                           */
-/*    3. The name of AURA and its representatives may not be used to         */
-/*      endorse or promote products derived from this software without       */
-/*      specific prior written permission.                                   */
-/*                                                                           */
-/* THIS SOFTWARE IS PROVIDED BY AURA ``AS IS'' AND ANY EXPRESS OR IMPLIED    */
-/* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF      */
-/* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE                  */
-/* DISCLAIMED. IN NO EVENT SHALL AURA BE LIABLE FOR ANY DIRECT, INDIRECT,    */
-/* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,      */
-/* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS     */
-/* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND    */
-/* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR     */
-/* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE    */
-/* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH          */
-/* DAMAGE.                                                                   */
-/*                                                                           */
-/* This code was copied and heavily modified from the ZLIB compression       */
-/* library that was written by Jean-loup Gailly and Mark Adler.  That        */
-/* software containes the following copyright and warranty notices:          */
-/*                                                                           */
-/*  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 at gzip.org          madler at 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).              */
-/*                                                                           */
-/*****************************************************************************/
-
-/* This code was copied unmodified from ZLIB inftrees.c -- generate Huffman  */
-/* trees for efficient decoding                                              */
-
-#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;
-}
diff --git a/astropy/io/fits/src/inftrees.h b/astropy/io/fits/src/inftrees.h
deleted file mode 100644
index defa497..0000000
--- a/astropy/io/fits/src/inftrees.h
+++ /dev/null
@@ -1,128 +0,0 @@
-/* $Id$
-*/
-
-/*****************************************************************************/
-/*                                                                           */
-/* This file, zlib.h, contains the include information required to compress  */
-/* and uncompress data using the GZIP_1 compression format.                  */
-/*                                                                           */
-/* Copyright (C) 2004 Association of Universities for Research in Astronomy  */
-/* (AURA)                                                                    */
-/*                                                                           */
-/* Redistribution and use in source and binary forms, with or without        */
-/* modification, are permitted provided that the following conditions are    */
-/* met:                                                                      */
-/*                                                                           */
-/*    1. Redistributions of source code must retain the above copyright      */
-/*      notice, this list of conditions and the following disclaimer.        */
-/*                                                                           */
-/*    2. Redistributions in binary form must reproduce the above             */
-/*      copyright notice, this list of conditions and the following          */
-/*      disclaimer in the documentation and/or other materials provided      */
-/*      with the distribution.                                               */
-/*                                                                           */
-/*    3. The name of AURA and its representatives may not be used to         */
-/*      endorse or promote products derived from this software without       */
-/*      specific prior written permission.                                   */
-/*                                                                           */
-/* THIS SOFTWARE IS PROVIDED BY AURA ``AS IS'' AND ANY EXPRESS OR IMPLIED    */
-/* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF      */
-/* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE                  */
-/* DISCLAIMED. IN NO EVENT SHALL AURA BE LIABLE FOR ANY DIRECT, INDIRECT,    */
-/* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,      */
-/* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS     */
-/* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND    */
-/* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR     */
-/* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE    */
-/* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH          */
-/* DAMAGE.                                                                   */
-/*                                                                           */
-/* This code was copied and heavily modified from the ZLIB compression       */
-/* library that was written by Jean-loup Gailly and Mark Adler.  That        */
-/* software containes the following copyright and warranty notices:          */
-/*                                                                           */
-/*  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 at gzip.org          madler at 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).              */
-/*                                                                           */
-/*****************************************************************************/
-
-/* This code was copied unmodified from ZLIB inftrees.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));
diff --git a/astropy/io/fits/src/pliocomp.c b/astropy/io/fits/src/pliocomp.c
deleted file mode 100644
index 853bc69..0000000
--- a/astropy/io/fits/src/pliocomp.c
+++ /dev/null
@@ -1,403 +0,0 @@
-/* $Id$
-*/
-
-/*****************************************************************************/
-/*                                                                           */
-/* This file, pliocomp.c, contains the code required to compress and         */
-/* uncompress data using the PLIO_1 compression format.                      */
-/*                                                                           */
-/* Copyright (C) 2004 Association of Universities for Research in Astronomy  */
-/* (AURA)                                                                    */
-/*                                                                           */
-/* Redistribution and use in source and binary forms, with or without        */
-/* modification, are permitted provided that the following conditions are    */
-/* met:                                                                      */
-/*                                                                           */
-/*    1. Redistributions of source code must retain the above copyright      */
-/*      notice, this list of conditions and the following disclaimer.        */
-/*                                                                           */
-/*    2. Redistributions in binary form must reproduce the above             */
-/*      copyright notice, this list of conditions and the following          */
-/*      disclaimer in the documentation and/or other materials provided      */
-/*      with the distribution.                                               */
-/*                                                                           */
-/*    3. The name of AURA and its representatives may not be used to         */
-/*      endorse or promote products derived from this software without       */
-/*      specific prior written permission.                                   */
-/*                                                                           */
-/* THIS SOFTWARE IS PROVIDED BY AURA ``AS IS'' AND ANY EXPRESS OR IMPLIED    */
-/* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF      */
-/* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE                  */
-/* DISCLAIMED. IN NO EVENT SHALL AURA BE LIABLE FOR ANY DIRECT, INDIRECT,    */
-/* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,      */
-/* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS     */
-/* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND    */
-/* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR     */
-/* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE    */
-/* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH          */
-/* DAMAGE.                                                                   */
-/*                                                                           */
-/* This file was copied intact from the FITSIO software that was written by  */
-/* William Pence at the High Energy Astrophysic Science Archive Research     */
-/* Center (HEASARC) at the NASA Goddard Space Flight Center.  That software  */
-/* contained the following copyright and warranty notices:                   */
-/*                                                                           */
-/* 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."                                             */
-/*                                                                           */
-/*****************************************************************************/
-
-/* stdlib is needed for the abs function */
-#include <stdlib.h>
-/*
-   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 _astropy_pl_p2li (int *pxsrc, int xs, short *lldst, int npix);
-int _astropy_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 _astropy_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 */
-    static int zero, v, x1, hi, ip, dv, xe, np, op, iz, nv, 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 _astropy_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 */
-    static int data, sw0001, otop, i__, lllen, i1, i2, x1, x2, ip, xe, np,
-             op, pv, opcode, llfirt;
-    static 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_ */
-
diff --git a/astropy/io/fits/src/quantize.c b/astropy/io/fits/src/quantize.c
deleted file mode 100644
index 2b26b39..0000000
--- a/astropy/io/fits/src/quantize.c
+++ /dev/null
@@ -1,2511 +0,0 @@
-/* $Id$
-*/
-
-/*****************************************************************************/
-/*                                                                           */
-/* This file, quantize.c, contains the code required to quantize a floating  */
-/* point value.                                                              */
-/*                                                                           */
-/* Copyright (C) 2004 Association of Universities for Research in Astronomy  */
-/* (AURA)                                                                    */
-/*                                                                           */
-/* Redistribution and use in source and binary forms, with or without        */
-/* modification, are permitted provided that the following conditions are    */
-/* met:                                                                      */
-/*                                                                           */
-/*    1. Redistributions of source code must retain the above copyright      */
-/*      notice, this list of conditions and the following disclaimer.        */
-/*                                                                           */
-/*    2. Redistributions in binary form must reproduce the above             */
-/*      copyright notice, this list of conditions and the following          */
-/*      disclaimer in the documentation and/or other materials provided      */
-/*      with the distribution.                                               */
-/*                                                                           */
-/*    3. The name of AURA and its representatives may not be used to         */
-/*      endorse or promote products derived from this software without       */
-/*      specific prior written permission.                                   */
-/*                                                                           */
-/* THIS SOFTWARE IS PROVIDED BY AURA ``AS IS'' AND ANY EXPRESS OR IMPLIED    */
-/* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF      */
-/* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE                  */
-/* DISCLAIMED. IN NO EVENT SHALL AURA BE LIABLE FOR ANY DIRECT, INDIRECT,    */
-/* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,      */
-/* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS     */
-/* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND    */
-/* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR     */
-/* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE    */
-/* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH          */
-/* DAMAGE.                                                                   */
-/*                                                                           */
-/* This file was copied intact from the FITSIO software that was written by  */
-/* William Pence at the High Energy Astrophysic Science Archive Research     */
-/* Center (HEASARC) at the NASA Goddard Space Flight Center.  That software  */
-/* contained the following copyright and warranty notices:                   */
-/*                                                                           */
-/* 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."                                             */
-/*                                                                           */
-/*****************************************************************************/
-
-/*
-  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 <stdio.h>
-# include <stdlib.h>
-# include <math.h>
-# include <limits.h>
-# include <float.h>
-
-#include "fitsio.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 N_RESERVED_VALUES 1   /* 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 */
-
-/* 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 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_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 double quick_select_double(double arr[], int n);
-/*---------------------------------------------------------------------------*/
-int _astropy_fits_quantize_float (float fdata[], long nxpix, long nypix,
-        int nullcheck, 
-	float in_null_value, float qlevel, int idata[], double *bscale,
-	double *bzero, int *iminval, int *imaxval) {
-
-/* arguments:
-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
-int noise_bits      i: quantization level (number of bits)
-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, intflag, nshift, itemp, anynulls = 0;
-	long i, nx, ngood = 0;
-	double stdev;	/* mean and RMS of differences */
-	float minval = 0., maxval = 0.;  /* min & max of fdata */
-	double delta;		/* bscale, 1 in idata = delta in fdata */
-	double zeropt;	        /* bzero */
-	double temp;
-
-	nx = nxpix * nypix;
-	if (nx <= 1) {
-	    *bscale = 1.;
-	    *bzero  = 0.;
-	    return (0);
-	}
-
-        *iminval = INT32_MAX;
-        *imaxval = INT32_MIN;
-
-	/* Check to see if data are "floating point integer." */
-        /* This also catches the case where all the pixels are null */
-
-        /* Since idata and fdata may point to the same memory location, */
-	/* we cannot write to idata unless we are sure we don't need   */
-	/* the corresponding float value any more */
-	
-	intflag = 1;		/* initial value */
-	for (i = 0;  i < nx;  i++) {
-            if (nullcheck && fdata[i] == in_null_value) {
-                anynulls = 1;
-            }
-	    else if (fdata[i] > INT32_MAX || 
-                     fdata[i] < NULL_VALUE + N_RESERVED_VALUES) {
-		intflag = 0;	/* not integer */
-		break;
-	    }
-            else {
-  	        itemp = (int)(fdata[i] + 0.5f);
-
-	        if (itemp != fdata[i]) {
-		    intflag = 0;	/* not integer */
-		    break;
-                }
-	    }
-	}
-
-        if (intflag) { /* data are "floating point integer" */
-	  for (i = 0;  i < nx;  i++) {
-            if (nullcheck && fdata[i] == in_null_value) {
-                idata[i] = NULL_VALUE;
-                anynulls = 1;
-            }
-            else {
-  	        idata[i] = (int)(fdata[i] + 0.5);
-                *iminval = minvalue(idata[i], *iminval);
-                *imaxval = maxvalue(idata[i], *imaxval);
-	    }
-	  }
-	}
-
-	if (intflag) {  /* data are "floating point integer" */
-            if (anynulls) {
-                /* Shift the range of values so they lie close to NULL_VALUE. */
-                /* This will make the compression more efficient.             */
-                /* Maximum allowed shift is 2^31 - 1 = 2147483646 */
-                /* Can't use 2147483647 because OSF says this is not a legal number */
-
-                if (*iminval >= 0) {
-		   nshift = -(NULL_VALUE + 1) - N_RESERVED_VALUES;
-		} else {
-                  nshift = *iminval - NULL_VALUE - N_RESERVED_VALUES;
-                }
-
-                for (i = 0;  i < nx;  i++) {
-                    if (idata[i] != NULL_VALUE) {
-                        idata[i] -= nshift;
-                    }
-                }
-                *iminval = *iminval - nshift;
-                *imaxval = *imaxval - nshift;
-  	        *bscale = 1.;
-	        *bzero = (double) nshift;
-            }
-            else {
-                /* there were no null values, so no need to shift the range */
-  	        *bscale = 1.;
-	        *bzero = 0.;
-            }
-	    return (1);
-	}
-
-	/* ************************************************************ */
-        /* data are not "floating point integer"; need to quantize them */
-
-        if (qlevel >= 0.) {
-
-	    /* estimate background noise using 3rd order absolute pixel differences */
-	    FnNoise3_float(fdata, nxpix, nypix, nullcheck, in_null_value, &ngood,
-	        &minval, &maxval, &stdev, &status);      
-
-	    /* substitute sigma-clipping if median is zero */
-	    if (stdev == 0.0) {
-
-		FnNoise1_float(fdata, nxpix, nypix, nullcheck, in_null_value, 
-		&stdev, &status);       
-	    }
-
-	    if (qlevel == 0.)
-	        delta = stdev / 16.;  /* default quantization */
-	    else
-	        delta = stdev / qlevel;
-
-	    if (delta == 0)
-	        return (0);   /* Zero variance in differences!  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, 0,
-	        &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 (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 ((maxval - minval) / delta < 2147483647. - N_RESERVED_VALUES )
-            {
-                zeropt = minval;
-            }
-            else
-            {
-                /* center the quantized levels around zero */
-                zeropt = (minval + maxval) / 2.;
-            }
-
-       	    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);
-
-	    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 _astropy_fits_quantize_double (double fdata[], long nxpix, long nypix,
-        int nullcheck, 
-	double in_null_value, float qlevel, int idata[], double *bscale,
-	double *bzero, int *iminval, int *imaxval) {
-
-/* arguments:
-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
-int noise_bits      i: quantization level (number of bits)
-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, intflag, nshift, itemp, anynulls = 0;
-	long i, nx, ngood = 0;
-	double stdev;	/* mean and RMS of differences */
-	double minval = 0., maxval = 0.;  /* min & max of fdata */
-	double delta;		/* bscale, 1 in idata = delta in fdata */
-	double zeropt;	        /* bzero */
-	double temp;
-
-	nx = nxpix * nypix;
-	if (nx <= 1) {
-	    *bscale = 1.;
-	    *bzero  = 0.;
-	    return (0);
-	}
-
-        *iminval = INT32_MAX;
-        *imaxval = INT32_MIN;
-
-	/* Check to see if data are "floating point integer." */
-        /* This also catches the case where all the pixels are null */
-
-        /* Since idata and fdata may point to the same memory location, */
-	/* we cannot write to idata unless we are sure we don't need   */
-	/* the corresponding float value any more */
-	
-	intflag = 1;		/* initial value */
-	for (i = 0;  i < nx;  i++) {
-            if (nullcheck && fdata[i] == in_null_value) {
-                anynulls = 1;
-            }
-	    else if (fdata[i] > INT32_MAX || 
-                     fdata[i] < NULL_VALUE + N_RESERVED_VALUES) {
-		intflag = 0;	/* not integer */
-		break;
-	    }
-            else {
-  	        itemp = (int)(fdata[i] + 0.5);
-
-	        if (itemp != fdata[i]) {
-		    intflag = 0;	/* not integer */
-		    break;
-                }
-	    }
-	}
-
-        if (intflag) { /* data are "floating point integer" */
-	  for (i = 0;  i < nx;  i++) {
-            if (nullcheck && fdata[i] == in_null_value) {
-                idata[i] = NULL_VALUE;
-                anynulls = 1;
-            }
-            else {
-  	        idata[i] = (int)(fdata[i] + 0.5);
-                *iminval = minvalue(idata[i], *iminval);
-                *imaxval = maxvalue(idata[i], *imaxval);
-	    }
-	  }
-	}
-
-	if (intflag) {  /* data are "floating point integer" */
-            if (anynulls) {
-                /* Shift the range of values so they lie close to NULL_VALUE. */
-                /* This will make the compression more efficient.             */
-                /* Maximum allowed shift is 2^31 - 1 = 2147483646 */
-                /* Can't use 2147483647 because OSF says this is not a legal number */
-
-                if (*iminval >= 0) {
-		   nshift = -(NULL_VALUE + 1) - N_RESERVED_VALUES;
-		} else {
-                  nshift = *iminval - NULL_VALUE - N_RESERVED_VALUES;
-                }
-
-                for (i = 0;  i < nx;  i++) {
-                    if (idata[i] != NULL_VALUE) {
-                        idata[i] -= nshift;
-                    }
-                }
-                *iminval = *iminval - nshift;
-                *imaxval = *imaxval - nshift;
-  	        *bscale = 1.;
-	        *bzero = (double) nshift;
-            }
-            else {
-                /* there were no null values, so no need to shift the range */
-  	        *bscale = 1.;
-	        *bzero = 0.;
-            }
-	    return (1);
-	}
-
-	/* ************************************************************ */
-        /* data are not "floating point integer"; need to quantize them */
-
-        if (qlevel >= 0.) {
-
-	    /* estimate background noise using 3rd order absolute pixel differences */
-	    FnNoise3_double(fdata, nxpix, nypix, nullcheck, in_null_value, &ngood,
-	        &minval, &maxval, &stdev, &status);      
-
-	    /* substitute sigma-clipping if median is zero */
-	    if (stdev == 0.0) {
-
-		FnNoise1_double(fdata, nxpix, nypix, nullcheck, in_null_value, 
-		&stdev, &status);       
-	    }
-
-	    if (qlevel == 0.)
-	        delta = stdev / 16.;  /* default quantization */
-	    else
-	        delta = stdev / qlevel;
-
-	    if (delta == 0)
-	        return (0);   /* Zero variance in differences!  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, 0,
-	        &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 (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 ((maxval - minval) / delta < 2147483647. - N_RESERVED_VALUES )
-            {
-                zeropt = minval;
-            }
-            else
-            {
-                /* center the quantized levels around zero */
-                zeropt = (minval + maxval) / 2.;
-            }
-
-       	    for (i = 0;  i < nx;  i++) {
-	        temp = (fdata[i] - zeropt) / delta;
-	        idata[i] = NINT (temp);
-            }
-        }
-        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);
-
-	    for (i = 0;  i < nx;  i++) {
-                if (fdata[i] != in_null_value) {
-	            temp = (fdata[i] - zeropt) / delta;
-	            idata[i] = NINT (temp);
-                }
-                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 */
-}
-/*--------------------------------------------------------------------------*/
-static 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 *noise3,     /* 3rd order estimate of noise in image background level */
-	int *status)        /* error status */
-
-/*
-    Compute statistics of the input short integer image.
-*/
-{
-	long ngood = 0;
-	short minval = 0, maxval = 0;
-	double xmean = 0., xsigma = 0., xnoise = 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) {
-		FnNoise3_short(array, nx, ny, nullcheck, nullvalue, 
-			&ngood, &minval, &maxval, &xnoise, status);
-
-		if (ngoodpix) *ngoodpix = ngood;
-		if (minvalue) *minvalue= minval;
-		if (maxvalue) *maxvalue = maxval;
-		*noise3  = xnoise;
-	}
-	return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int _astropy_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 *noise3,     /* 3rd order estimate of noise in image background level */
-	int *status)        /* error status */
-
-/*
-    Compute statistics of the input short integer image.
-*/
-{
-	long ngood = 0;
-	int minval = 0, maxval = 0;
-	double xmean = 0., xsigma = 0., xnoise = 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) {
-		FnNoise3_int(array, nx, ny, nullcheck, nullvalue, 
-			&ngood, &minval, &maxval, &xnoise, status);
-
-		if (ngoodpix) *ngoodpix = ngood;
-		if (minvalue) *minvalue= minval;
-		if (maxvalue) *maxvalue = maxval;
-		*noise3  = xnoise;
-	}
-	return(*status);
-}
-/*--------------------------------------------------------------------------*/
-static 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 *noise3,     /* 3rd order estimate of noise in image background level */
-	int *status)        /* error status */
-
-/*
-    Compute statistics of the input short integer image.
-*/
-{
-	long ngood;
-	float minval, maxval;
-	double xmean = 0., xsigma = 0., xnoise = 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) {
-		FnNoise3_float(array, nx, ny, nullcheck, nullvalue, 
-			&ngood, &minval, &maxval, &xnoise, status);
-
-		if (ngoodpix) *ngoodpix = ngood;
-		if (minvalue) *minvalue= minval;
-		if (maxvalue) *maxvalue = maxval;
-		*noise3  = xnoise;
-	}
-	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 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_MIN;
-	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 */
-        differences = 0;
-        diffs = 0;
-	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] = fabs((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 (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_MIN;
-	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 */
-        differences = 0;
-        diffs = 0;
-	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++;
-		    }
-
-		    /* 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_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 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
-
-
diff --git a/astropy/io/fits/src/ricecomp.c b/astropy/io/fits/src/ricecomp.c
deleted file mode 100644
index 34d72f7..0000000
--- a/astropy/io/fits/src/ricecomp.c
+++ /dev/null
@@ -1,1448 +0,0 @@
-/* $Id$
-*/
-
-/*****************************************************************************/
-/*                                                                           */
-/* This file, ricecomp.c, contains the code required to compress and         */
-/* uncompress data using the RICE_1 compression format.                      */
-/*                                                                           */
-/* Copyright (C) 2004 Association of Universities for Research in Astronomy  */
-/* (AURA)                                                                    */
-/*                                                                           */
-/* Redistribution and use in source and binary forms, with or without        */
-/* modification, are permitted provided that the following conditions are    */
-/* met:                                                                      */
-/*                                                                           */
-/*    1. Redistributions of source code must retain the above copyright      */
-/*      notice, this list of conditions and the following disclaimer.        */
-/*                                                                           */
-/*    2. Redistributions in binary form must reproduce the above             */
-/*      copyright notice, this list of conditions and the following          */
-/*      disclaimer in the documentation and/or other materials provided      */
-/*      with the distribution.                                               */
-/*                                                                           */
-/*    3. The name of AURA and its representatives may not be used to         */
-/*      endorse or promote products derived from this software without       */
-/*      specific prior written permission.                                   */
-/*                                                                           */
-/* THIS SOFTWARE IS PROVIDED BY AURA ``AS IS'' AND ANY EXPRESS OR IMPLIED    */
-/* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF      */
-/* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE                  */
-/* DISCLAIMED. IN NO EVENT SHALL AURA BE LIABLE FOR ANY DIRECT, INDIRECT,    */
-/* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,      */
-/* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS     */
-/* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND    */
-/* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR     */
-/* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE    */
-/* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH          */
-/* DAMAGE.                                                                   */
-/*                                                                           */
-/* This file was copied intact from the FITSIO software that was written by  */
-/* William Pence at the High Energy Astrophysic Science Archive Research     */
-/* Center (HEASARC) at the NASA Goddard Space Flight Center.  That software  */
-/* contained the following copyright and warranty notices:                   */
-/*                                                                           */
-/* 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."                                             */
-/*                                                                           */
-/*****************************************************************************/
-
-/*
-  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 <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-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 "fitsio.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);
-
-/* this routine used to be called 'rcomp'  (WDP)  */
-/*---------------------------------------------------------------------------*/
-
-int _astropy_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<<fsbits;
-
-    /*
-     * Set up buffer pointers
-     */
-    buffer->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) {
-        _astropy_ffpmsg("_astropy_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) {
-        _astropy_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<nx; i += nblock) {
-	/* last block may be shorter */
-	if (nx-i < nblock) thisblock = nx-i;
-	/*
-	 * Compute differences of adjacent pixels and map them to unsigned values.
-	 * Note that this may overflow the integer variables -- that's
-	 * OK, because we can recover when decompressing.  If we were
-	 * compressing shorts or bytes, would want to do this arithmetic
-	 * with short/byte working variables (though diff will still be
-	 * passed as an int.)
-	 *
-	 * compute sum of mapped pixel values at same time
-	 * use double precision for sum to allow 32-bit integer inputs
-	 */
-	pixelsum = 0.0;
-	for (j=0; j<thisblock; j++) {
-	    nextpix = a[i+j];
-	    pdiff = nextpix - lastpix;
-	    diff[j] = (unsigned int) ((pdiff<0) ? ~(pdiff<<1) : (pdiff<<1));
-	    pixelsum += diff[j];
-	    lastpix = nextpix;
-	}
-
-	/*
-	 * compute number of bits to split from sum
-	 */
-	dpsum = (pixelsum - (thisblock/2) - 1)/thisblock;
-	if (dpsum < 0) dpsum = 0.0;
-	psum = ((unsigned int) 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) {
-                _astropy_ffpmsg("rice_encode: end of buffer");
-                free(diff);
-		return(-1);
-	    }
-	    for (j=0; j<thisblock; j++) {
-		if (output_nbits(buffer, diff[j], bbits) == EOF) {
-                    _astropy_ffpmsg("rice_encode: end of buffer");
-                    free(diff);
-		    return(-1);
-		}
-	    }
-	} else if (fs == 0 && pixelsum == 0) {
-	    /*
-	     * special low entropy case when FS = 0 and pixelsum=0 (all
-	     * pixels in block are zero.)
-	     * Output a 0 and return
-	     */
-	    if (output_nbits(buffer, 0, fsbits) == EOF) {
-                _astropy_ffpmsg("rice_encode: end of buffer");
-                free(diff);
-		return(-1);
-	    }
-	} else {
-	    /* normal case: not either very high or very low entropy */
-	    if (output_nbits(buffer, fs+1, fsbits) == EOF) {
-                _astropy_ffpmsg("rice_encode: end of buffer");
-                free(diff);
-		return(-1);
-	    }
-	    fsmask = (1<<fs) - 1;
-	    /*
-	     * local copies of bit buffer to improve optimization
-	     */
-	    lbitbuffer = buffer->bitbuffer;
-	    lbits_to_go = buffer->bits_to_go;
-	    for (j=0; j<thisblock; j++) {
-		v = diff[j];
-		top = v >> 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) {
-                 _astropy_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 _astropy_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<<fsbits;
-
-    /*
-     * Set up buffer pointers
-     */
-    buffer->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) {
-        _astropy_ffpmsg("_astropy_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) {
-        _astropy_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<nx; i += nblock) {
-	/* last block may be shorter */
-	if (nx-i < nblock) thisblock = nx-i;
-	/*
-	 * Compute differences of adjacent pixels and map them to unsigned values.
-	 * Note that this may overflow the integer variables -- that's
-	 * OK, because we can recover when decompressing.  If we were
-	 * compressing shorts or bytes, would want to do this arithmetic
-	 * with short/byte working variables (though diff will still be
-	 * passed as an int.)
-	 *
-	 * compute sum of mapped pixel values at same time
-	 * use double precision for sum to allow 32-bit integer inputs
-	 */
-	pixelsum = 0.0;
-	for (j=0; j<thisblock; j++) {
-	    nextpix = a[i+j];
-	    pdiff = nextpix - lastpix;
-	    diff[j] = (unsigned int) ((pdiff<0) ? ~(pdiff<<1) : (pdiff<<1));
-	    pixelsum += diff[j];
-	    lastpix = nextpix;
-	}
-	/*
-	 * compute number of bits to split from sum
-	 */
-	dpsum = (pixelsum - (thisblock/2) - 1)/thisblock;
-	if (dpsum < 0) dpsum = 0.0;
-/*	psum = ((unsigned int) dpsum ) >> 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) {
-	    /* 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) {
-                _astropy_ffpmsg("rice_encode: end of buffer");
-                free(diff);
-		return(-1);
-	    }
-	    for (j=0; j<thisblock; j++) {
-		if (output_nbits(buffer, diff[j], bbits) == EOF) {
-                    _astropy_ffpmsg("rice_encode: end of buffer");
-                    free(diff);
-		    return(-1);
-		}
-	    }
-	} else if (fs == 0 && pixelsum == 0) {
-	    /*
-	     * special low entropy case when FS = 0 and pixelsum=0 (all
-	     * pixels in block are zero.)
-	     * Output a 0 and return
-	     */
-	    if (output_nbits(buffer, 0, fsbits) == EOF) {
-                _astropy_ffpmsg("rice_encode: end of buffer");
-                free(diff);
-		return(-1);
-	    }
-	} else {
-	    /* normal case: not either very high or very low entropy */
-	    if (output_nbits(buffer, fs+1, fsbits) == EOF) {
-                _astropy_ffpmsg("rice_encode: end of buffer");
-                free(diff);
-		return(-1);
-	    }
-	    fsmask = (1<<fs) - 1;
-	    /*
-	     * local copies of bit buffer to improve optimization
-	     */
-	    lbitbuffer = buffer->bitbuffer;
-	    lbits_to_go = buffer->bits_to_go;
-	    for (j=0; j<thisblock; j++) {
-		v = diff[j];
-		top = v >> 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) {
-                 _astropy_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 _astropy_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<<fsbits;
-
-    /*
-     * Set up buffer pointers
-     */
-    buffer->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) {
-        _astropy_ffpmsg("_astropy_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) {
-        _astropy_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<nx; i += nblock) {
-	/* last block may be shorter */
-	if (nx-i < nblock) thisblock = nx-i;
-	/*
-	 * Compute differences of adjacent pixels and map them to unsigned values.
-	 * Note that this may overflow the integer variables -- that's
-	 * OK, because we can recover when decompressing.  If we were
-	 * compressing shorts or bytes, would want to do this arithmetic
-	 * with short/byte working variables (though diff will still be
-	 * passed as an int.)
-	 *
-	 * compute sum of mapped pixel values at same time
-	 * use double precision for sum to allow 32-bit integer inputs
-	 */
-	pixelsum = 0.0;
-	for (j=0; j<thisblock; j++) {
-	    nextpix = a[i+j];
-	    pdiff = nextpix - lastpix;
-	    diff[j] = (unsigned int) ((pdiff<0) ? ~(pdiff<<1) : (pdiff<<1));
-	    pixelsum += diff[j];
-	    lastpix = nextpix;
-	}
-	/*
-	 * compute number of bits to split from sum
-	 */
-	dpsum = (pixelsum - (thisblock/2) - 1)/thisblock;
-	if (dpsum < 0) dpsum = 0.0;
-/*	psum = ((unsigned int) dpsum ) >> 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) {
-                _astropy_ffpmsg("rice_encode: end of buffer");
-                free(diff);
-		return(-1);
-	    }
-	    for (j=0; j<thisblock; j++) {
-		if (output_nbits(buffer, diff[j], bbits) == EOF) {
-                    _astropy_ffpmsg("rice_encode: end of buffer");
-                    free(diff);
-		    return(-1);
-		}
-	    }
-	} else if (fs == 0 && pixelsum == 0) {
-	    /*
-	     * special low entropy case when FS = 0 and pixelsum=0 (all
-	     * pixels in block are zero.)
-	     * Output a 0 and return
-	     */
-	    if (output_nbits(buffer, 0, fsbits) == EOF) {
-                _astropy_ffpmsg("rice_encode: end of buffer");
-                free(diff);
-		return(-1);
-	    }
-	} else {
-	    /* normal case: not either very high or very low entropy */
-	    if (output_nbits(buffer, fs+1, fsbits) == EOF) {
-                _astropy_ffpmsg("rice_encode: end of buffer");
-                free(diff);
-		return(-1);
-	    }
-	    fsmask = (1<<fs) - 1;
-	    /*
-	     * local copies of bit buffer to improve optimization
-	     */
-	    lbitbuffer = buffer->bitbuffer;
-	    lbits_to_go = buffer->bits_to_go;
-	    for (j=0; j<thisblock; j++) {
-		v = diff[j];
-		top = v >> 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) {
-                 _astropy_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<<lbits_to_go)-1); */
-	lbitbuffer |= (bits>>(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<<n)-1) ); */
-    lbitbuffer |= ( bits & *(mask+n) );
-    lbits_to_go -= n;
-    while (lbits_to_go <= 0) {
-	/*
-	 * bitbuffer full, put out top 8 bits
-	 */
-	putcbuf((lbitbuffer>>(-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<<buffer->bits_to_go,buffer);
-	
-/*	if (putcbuf(buffer->bitbuffer<<buffer->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 <stdio.h>
-#include <stdlib.h>
-*/
-
-/*---------------------------------------------------------------------------*/
-/* this routine used to be called 'rdecomp'  (WDP)  */
-
-int _astropy_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;
-static int *nonzero_count = (int *)NULL;
-
-   /*
-     * 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<<fsbits;
-
-    if (nonzero_count == (int *) NULL) {
-	/*
-	 * nonzero_count is lookup table giving number of bits
-	 * in 8-bit values not including leading zeros
-	 */
-
-        /*  NOTE!!!  This memory never gets freed  */
-	nonzero_count = (int *) malloc(256*sizeof(int));
-	if (nonzero_count == (int *) NULL) {
-            _astropy_ffpmsg("rdecomp: insufficient memory");
-	    return 1;
-	}
-	nzero = 8;
-	k = 128;
-	for (i=255; i>=0; ) {
-	    for ( ; i>=k; i--) nonzero_count[i] = nzero;
-	    k = k/2;
-	    nzero--;
-	}
-    }
-    /*
-     * Decode in blocks of nblock pixels
-     */
-
-    /* first 4 bytes of input buffer contain the value of the first */
-    /* 4 byte integer value, without any encoding */
-    
-    lastpix = 0;
-    bytevalue = c[0];
-    lastpix = lastpix | (bytevalue<<24);
-    bytevalue = c[1];
-    lastpix = lastpix | (bytevalue<<16);
-    bytevalue = c[2];
-    lastpix = lastpix | (bytevalue<<8);
-    bytevalue = c[3];
-    lastpix = lastpix | bytevalue;
-
-    c += 4;  
-    cend = c + clen - 4;
-
-    b = *c++;		    /* bit buffer			*/
-    nbits = 8;		    /* number of bits remaining in b	*/
-    for (i = 0; i<nx; ) {
-	/* get the FS value from first fsbits */
-	nbits -= fsbits;
-	while (nbits < 0) {
-	    b = (b<<8) | (*c++);
-	    nbits += 8;
-	}
-	fs = (b >> nbits) - 1;
-
-	b &= (1<<nbits)-1;
-	/* loop over the next block */
-	imax = i + nblock;
-	if (imax > nx) imax = nx;
-	if (fs<0) {
-	    /* low-entropy case, all zero differences */
-	    for ( ; i<imax; i++) array[i] = lastpix;
-	} else if (fs==fsmax) {
-	    /* high-entropy case, directly coded pixel values */
-	    for ( ; i<imax; i++) {
-		k = bbits - nbits;
-		diff = b<<k;
-		for (k -= 8; k >= 0; k -= 8) {
-		    b = *c++;
-		    diff |= b<<k;
-		}
-		if (nbits>0) {
-		    b = *c++;
-		    diff |= b>>(-k);
-		    b &= (1<<nbits)-1;
-		} else {
-		    b = 0;
-		}
-		/*
-		 * undo mapping and differencing
-		 * Note that some of these operations will overflow the
-		 * unsigned int arithmetic -- that's OK, it all works
-		 * out to give the right answers in the output file.
-		 */
-		if ((diff & 1) == 0) {
-		    diff = diff>>1;
-		} else {
-		    diff = ~(diff>>1);
-		}
-		array[i] = diff+lastpix;
-		lastpix = array[i];
-	    }
-	} else {
-	    /* normal case, Rice coding */
-	    for ( ; i<imax; i++) {
-		/* count number of leading zeros */
-		while (b == 0) {
-		    nbits += 8;
-		    b = *c++;
-		}
-		nzero = nbits - nonzero_count[b];
-		nbits -= nzero+1;
-		/* flip the leading one-bit */
-		b ^= 1<<nbits;
-		/* get the FS trailing bits */
-		nbits -= fs;
-		while (nbits < 0) {
-		    b = (b<<8) | (*c++);
-		    nbits += 8;
-		}
-		diff = (nzero<<fs) | (b>>nbits);
-		b &= (1<<nbits)-1;
-
-		/* undo mapping and differencing */
-		if ((diff & 1) == 0) {
-		    diff = diff>>1;
-		} else {
-		    diff = ~(diff>>1);
-		}
-		array[i] = diff+lastpix;
-		lastpix = array[i];
-	    }
-	}
-	if (c > cend) {
-            _astropy_ffpmsg("decompression error: hit end of compressed byte stream");
-	    return 1;
-	}
-    }
-    if (c < cend) {
-        _astropy_ffpmsg("decompression warning: unused bytes at end of compressed buffer");
-    }
-    return 0;
-}
-/*---------------------------------------------------------------------------*/
-/* this routine used to be called 'rdecomp'  (WDP)  */
-
-int _astropy_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;
-static int *nonzero_count = (int *)NULL;
-
-   /*
-     * 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<<fsbits;
-
-    if (nonzero_count == (int *) NULL) {
-	/*
-	 * nonzero_count is lookup table giving number of bits
-	 * in 8-bit values not including leading zeros
-	 */
-
-        /*  NOTE!!!  This memory never gets freed  */
-	nonzero_count = (int *) malloc(256*sizeof(int));
-	if (nonzero_count == (int *) NULL) {
-            _astropy_ffpmsg("rdecomp: insufficient memory");
-	    return 1;
-	}
-	nzero = 8;
-	k = 128;
-	for (i=255; i>=0; ) {
-	    for ( ; i>=k; i--) nonzero_count[i] = nzero;
-	    k = k/2;
-	    nzero--;
-	}
-    }
-    /*
-     * Decode in blocks of nblock pixels
-     */
-
-    /* first 2 bytes of input buffer contain the value of the first */
-    /* 2 byte integer value, without any encoding */
-    
-    lastpix = 0;
-    bytevalue = c[0];
-    lastpix = lastpix | (bytevalue<<8);
-    bytevalue = c[1];
-    lastpix = lastpix | bytevalue;
-
-    c += 2;  
-    cend = c + clen - 2;
-
-    b = *c++;		    /* bit buffer			*/
-    nbits = 8;		    /* number of bits remaining in b	*/
-    for (i = 0; i<nx; ) {
-	/* get the FS value from first fsbits */
-	nbits -= fsbits;
-	while (nbits < 0) {
-	    b = (b<<8) | (*c++);
-	    nbits += 8;
-	}
-	fs = (b >> nbits) - 1;
-
-	b &= (1<<nbits)-1;
-	/* loop over the next block */
-	imax = i + nblock;
-	if (imax > nx) imax = nx;
-	if (fs<0) {
-	    /* low-entropy case, all zero differences */
-	    for ( ; i<imax; i++) array[i] = lastpix;
-	} else if (fs==fsmax) {
-	    /* high-entropy case, directly coded pixel values */
-	    for ( ; i<imax; i++) {
-		k = bbits - nbits;
-		diff = b<<k;
-		for (k -= 8; k >= 0; k -= 8) {
-		    b = *c++;
-		    diff |= b<<k;
-		}
-		if (nbits>0) {
-		    b = *c++;
-		    diff |= b>>(-k);
-		    b &= (1<<nbits)-1;
-		} else {
-		    b = 0;
-		}
-   
-		/*
-		 * undo mapping and differencing
-		 * Note that some of these operations will overflow the
-		 * unsigned int arithmetic -- that's OK, it all works
-		 * out to give the right answers in the output file.
-		 */
-		if ((diff & 1) == 0) {
-		    diff = diff>>1;
-		} else {
-		    diff = ~(diff>>1);
-		}
-		array[i] = diff+lastpix;
-		lastpix = array[i];
-	    }
-	} else {
-	    /* normal case, Rice coding */
-	    for ( ; i<imax; i++) {
-		/* count number of leading zeros */
-		while (b == 0) {
-		    nbits += 8;
-		    b = *c++;
-		}
-		nzero = nbits - nonzero_count[b];
-		nbits -= nzero+1;
-		/* flip the leading one-bit */
-		b ^= 1<<nbits;
-		/* get the FS trailing bits */
-		nbits -= fs;
-		while (nbits < 0) {
-		    b = (b<<8) | (*c++);
-		    nbits += 8;
-		}
-		diff = (nzero<<fs) | (b>>nbits);
-		b &= (1<<nbits)-1;
-
-		/* undo mapping and differencing */
-		if ((diff & 1) == 0) {
-		    diff = diff>>1;
-		} else {
-		    diff = ~(diff>>1);
-		}
-		array[i] = diff+lastpix;
-		lastpix = array[i];
-	    }
-	}
-	if (c > cend) {
-            _astropy_ffpmsg("decompression error: hit end of compressed byte stream");
-	    return 1;
-	}
-    }
-    if (c < cend) {
-        _astropy_ffpmsg("decompression warning: unused bytes at end of compressed buffer");
-    }
-    return 0;
-}
-/*---------------------------------------------------------------------------*/
-/* this routine used to be called 'rdecomp'  (WDP)  */
-
-int _astropy_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;
-static int *nonzero_count = (int *)NULL;
-
-   /*
-     * 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<<fsbits;
-
-    if (nonzero_count == (int *) NULL) {
-	/*
-	 * nonzero_count is lookup table giving number of bits
-	 * in 8-bit values not including leading zeros
-	 */
-
-        /*  NOTE!!!  This memory never gets freed  */
-	nonzero_count = (int *) malloc(256*sizeof(int));
-	if (nonzero_count == (int *) NULL) {
-            _astropy_ffpmsg("rdecomp: insufficient memory");
-	    return 1;
-	}
-	nzero = 8;
-	k = 128;
-	for (i=255; i>=0; ) {
-	    for ( ; i>=k; i--) nonzero_count[i] = nzero;
-	    k = k/2;
-	    nzero--;
-	}
-    }
-    /*
-     * Decode in blocks of nblock pixels
-     */
-
-    /* first byte of input buffer contain the value of the first */
-    /* byte integer value, without any encoding */
-    
-    lastpix = c[0];
-    c += 1;  
-    cend = c + clen - 1;
-
-    b = *c++;		    /* bit buffer			*/
-    nbits = 8;		    /* number of bits remaining in b	*/
-    for (i = 0; i<nx; ) {
-	/* get the FS value from first fsbits */
-	nbits -= fsbits;
-	while (nbits < 0) {
-	    b = (b<<8) | (*c++);
-	    nbits += 8;
-	}
-	fs = (b >> nbits) - 1;
-
-	b &= (1<<nbits)-1;
-	/* loop over the next block */
-	imax = i + nblock;
-	if (imax > nx) imax = nx;
-	if (fs<0) {
-	    /* low-entropy case, all zero differences */
-	    for ( ; i<imax; i++) array[i] = lastpix;
-	} else if (fs==fsmax) {
-	    /* high-entropy case, directly coded pixel values */
-	    for ( ; i<imax; i++) {
-		k = bbits - nbits;
-		diff = b<<k;
-		for (k -= 8; k >= 0; k -= 8) {
-		    b = *c++;
-		    diff |= b<<k;
-		}
-		if (nbits>0) {
-		    b = *c++;
-		    diff |= b>>(-k);
-		    b &= (1<<nbits)-1;
-		} else {
-		    b = 0;
-		}
-   
-		/*
-		 * undo mapping and differencing
-		 * Note that some of these operations will overflow the
-		 * unsigned int arithmetic -- that's OK, it all works
-		 * out to give the right answers in the output file.
-		 */
-		if ((diff & 1) == 0) {
-		    diff = diff>>1;
-		} else {
-		    diff = ~(diff>>1);
-		}
-		array[i] = diff+lastpix;
-		lastpix = array[i];
-	    }
-	} else {
-	    /* normal case, Rice coding */
-	    for ( ; i<imax; i++) {
-		/* count number of leading zeros */
-		while (b == 0) {
-		    nbits += 8;
-		    b = *c++;
-		}
-		nzero = nbits - nonzero_count[b];
-		nbits -= nzero+1;
-		/* flip the leading one-bit */
-		b ^= 1<<nbits;
-		/* get the FS trailing bits */
-		nbits -= fs;
-		while (nbits < 0) {
-		    b = (b<<8) | (*c++);
-		    nbits += 8;
-		}
-		diff = (nzero<<fs) | (b>>nbits);
-		b &= (1<<nbits)-1;
-
-		/* undo mapping and differencing */
-		if ((diff & 1) == 0) {
-		    diff = diff>>1;
-		} else {
-		    diff = ~(diff>>1);
-		}
-		array[i] = diff+lastpix;
-		lastpix = array[i];
-	    }
-	}
-	if (c > cend) {
-            _astropy_ffpmsg("decompression error: hit end of compressed byte stream");
-	    return 1;
-	}
-    }
-    if (c < cend) {
-        _astropy_ffpmsg("decompression warning: unused bytes at end of compressed buffer");
-    }
-    return 0;
-}
diff --git a/astropy/io/fits/src/ricecomp.h b/astropy/io/fits/src/ricecomp.h
deleted file mode 100644
index d9da609..0000000
--- a/astropy/io/fits/src/ricecomp.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/* $Id$
-*/
-
-/*****************************************************************************/
-/*                                                                           */
-/* This file, ricecomp.h, contains the code required to compress and         */
-/* uncompress data using the RICE_1 compression format.                      */
-/*                                                                           */
-/* Copyright (C) 2004 Association of Universities for Research in Astronomy  */
-/* (AURA)                                                                    */
-/*                                                                           */
-/* Redistribution and use in source and binary forms, with or without        */
-/* modification, are permitted provided that the following conditions are    */
-/* met:                                                                      */
-/*                                                                           */
-/*    1. Redistributions of source code must retain the above copyright      */
-/*      notice, this list of conditions and the following disclaimer.        */
-/*                                                                           */
-/*    2. Redistributions in binary form must reproduce the above             */
-/*      copyright notice, this list of conditions and the following          */
-/*      disclaimer in the documentation and/or other materials provided      */
-/*      with the distribution.                                               */
-/*                                                                           */
-/*    3. The name of AURA and its representatives may not be used to         */
-/*      endorse or promote products derived from this software without       */
-/*      specific prior written permission.                                   */
-/*                                                                           */
-/* THIS SOFTWARE IS PROVIDED BY AURA ``AS IS'' AND ANY EXPRESS OR IMPLIED    */
-/* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF      */
-/* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE                  */
-/* DISCLAIMED. IN NO EVENT SHALL AURA BE LIABLE FOR ANY DIRECT, INDIRECT,    */
-/* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,      */
-/* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS     */
-/* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND    */
-/* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR     */
-/* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE    */
-/* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH          */
-/* DAMAGE.                                                                   */
-/*                                                                           */
-/* This file contains source code that was copied and modified from the      */
-/* FITSIO software that was written by William Pence at the High Energy      */
-/* Astrophysic Science Archive Research Center (HEASARC) at the NASA Goddard */
-/* Space Flight Center.  That software contained the following copyright and */
-/* warranty notices:                                                         */
-/*                                                                           */
-/* 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."                                             */
-/*                                                                           */
-/*****************************************************************************/
-
-/* buffer.h: structure for compression to buffer rather than to a file, 
- *           including bit I/O buffer
- *
- * R. White, 19 June 1998
- */
-
-
-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 buffree(mf)		(free(mf->start), free(mf))
-#define bufused(mf)		(mf->current - mf->start)
-#define bufreset(mf)	(mf->current = mf->start)
-
-/*
- * getcbuf, putcbuf macros for character IO to buffer
- * putcbuf returns EOF on end of buffer, else returns 0
- */
-#define getcbuf(mf) ((mf->current >= mf->end) ? EOF : *(mf->current)++)
-#define putcbuf(c,mf) \
-	((mf->current >= mf->end) ? \
-	EOF :\
-	((*(mf->current)++ = c), 0))
diff --git a/astropy/io/fits/src/trees.c b/astropy/io/fits/src/trees.c
deleted file mode 100644
index 65bd4b9..0000000
--- a/astropy/io/fits/src/trees.c
+++ /dev/null
@@ -1,1284 +0,0 @@
-/* $Id$
-*/
-
-/*****************************************************************************/
-/*                                                                           */
-/* This file, inffast.c, contains the code required to compress and          */
-/* uncompress data using the GZIP_1 compression format.                      */
-/*                                                                           */
-/* Copyright (C) 2004 Association of Universities for Research in Astronomy  */
-/* (AURA)                                                                    */
-/*                                                                           */
-/* Redistribution and use in source and binary forms, with or without        */
-/* modification, are permitted provided that the following conditions are    */
-/* met:                                                                      */
-/*                                                                           */
-/*    1. Redistributions of source code must retain the above copyright      */
-/*      notice, this list of conditions and the following disclaimer.        */
-/*                                                                           */
-/*    2. Redistributions in binary form must reproduce the above             */
-/*      copyright notice, this list of conditions and the following          */
-/*      disclaimer in the documentation and/or other materials provided      */
-/*      with the distribution.                                               */
-/*                                                                           */
-/*    3. The name of AURA and its representatives may not be used to         */
-/*      endorse or promote products derived from this software without       */
-/*      specific prior written permission.                                   */
-/*                                                                           */
-/* THIS SOFTWARE IS PROVIDED BY AURA ``AS IS'' AND ANY EXPRESS OR IMPLIED    */
-/* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF      */
-/* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE                  */
-/* DISCLAIMED. IN NO EVENT SHALL AURA BE LIABLE FOR ANY DIRECT, INDIRECT,    */
-/* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,      */
-/* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS     */
-/* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND    */
-/* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR     */
-/* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE    */
-/* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH          */
-/* DAMAGE.                                                                   */
-/*                                                                           */
-/* This code was copied and heavily modified from the ZLIB compression       */
-/* library that was written by Jean-loup Gailly and Mark Adler.  That        */
-/* software containes the following copyright and warranty notices:          */
-/*                                                                           */
-/*  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 at gzip.org          madler at 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).              */
-/*                                                                           */
-/*****************************************************************************/
-
-/* This code was copied unmodified from ZLIB trees.c -- output deflated data */
-/* using Huffman coding                                                      */
-
-#include "deflate.h"
-
-#ifdef DEBUG
-#  include <ctype.h>
-#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<<extra_lbits[code]); n++) {
-            _length_code[length++] = (uch)code;
-        }
-    }
-    Assert (length == 256, "tr_static_init: length != 256");
-    /* Note that the length 255 (match length 258) can be represented
-     * in two different ways: code 284 + 5 bits or code 285, so we
-     * overwrite length_code[255] to use the best encoding:
-     */
-    _length_code[length-1] = (uch)code;
-
-    /* Initialize the mapping dist (0..32K) -> dist code (0..29) */
-    dist = 0;
-    for (code = 0 ; code < 16; code++) {
-        base_dist[code] = dist;
-        for (n = 0; n < (1<<extra_dbits[code]); n++) {
-            _dist_code[dist++] = (uch)code;
-        }
-    }
-    Assert (dist == 256, "tr_static_init: dist != 256");
-    dist >>= 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 <stdio.h>
-#  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<<MAX_BITS)-1,
-            "inconsistent bit counts");
-    Tracev((stderr,"\ngen_codes: max_code %d ", max_code));
-
-    for (n = 0;  n <= max_code; n++) {
-        int len = tree[n].Len;
-        if (len == 0) continue;
-        /* Now reverse the bits */
-        tree[n].Code = bi_reverse(next_code[len]++, len);
-
-        Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ",
-             n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1));
-    }
-}
-
-/* ===========================================================================
- * Construct one Huffman tree and assigns the code bit strings and lengths.
- * Update the total bit length for the current block.
- * IN assertion: the field freq is set for all tree elements.
- * OUT assertions: the fields len and code are set to the optimal bit length
- *     and corresponding code. The length opt_len is updated; static_len is
- *     also updated if stree is not null. The field max_code is set.
- */
-local void build_tree(s, desc)
-    deflate_state *s;
-    tree_desc *desc; /* the tree descriptor */
-{
-    ct_data *tree         = desc->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++);
-    }
-}
diff --git a/astropy/io/fits/src/trees.h b/astropy/io/fits/src/trees.h
deleted file mode 100644
index eb93b5a..0000000
--- a/astropy/io/fits/src/trees.h
+++ /dev/null
@@ -1,202 +0,0 @@
-/* $Id$
-*/
-
-/*****************************************************************************/
-/*                                                                           */
-/* This file, zlib.h, contains the include information required to compress  */
-/* and uncompress data using the GZIP_1 compression format.                  */
-/*                                                                           */
-/* Copyright (C) 2004 Association of Universities for Research in Astronomy  */
-/* (AURA)                                                                    */
-/*                                                                           */
-/* Redistribution and use in source and binary forms, with or without        */
-/* modification, are permitted provided that the following conditions are    */
-/* met:                                                                      */
-/*                                                                           */
-/*    1. Redistributions of source code must retain the above copyright      */
-/*      notice, this list of conditions and the following disclaimer.        */
-/*                                                                           */
-/*    2. Redistributions in binary form must reproduce the above             */
-/*      copyright notice, this list of conditions and the following          */
-/*      disclaimer in the documentation and/or other materials provided      */
-/*      with the distribution.                                               */
-/*                                                                           */
-/*    3. The name of AURA and its representatives may not be used to         */
-/*      endorse or promote products derived from this software without       */
-/*      specific prior written permission.                                   */
-/*                                                                           */
-/* THIS SOFTWARE IS PROVIDED BY AURA ``AS IS'' AND ANY EXPRESS OR IMPLIED    */
-/* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF      */
-/* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE                  */
-/* DISCLAIMED. IN NO EVENT SHALL AURA BE LIABLE FOR ANY DIRECT, INDIRECT,    */
-/* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,      */
-/* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS     */
-/* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND    */
-/* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR     */
-/* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE    */
-/* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH          */
-/* DAMAGE.                                                                   */
-/*                                                                           */
-/* This code was copied and heavily modified from the ZLIB compression       */
-/* library that was written by Jean-loup Gailly and Mark Adler.  That        */
-/* software containes the following copyright and warranty notices:          */
-/*                                                                           */
-/*  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 at gzip.org          madler at 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).              */
-/*                                                                           */
-/*****************************************************************************/
-
-/* This code was copied unmodified from ZLIB 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
-};
-
diff --git a/astropy/io/fits/src/zlib.c b/astropy/io/fits/src/zlib.c
deleted file mode 100644
index 2192b7d..0000000
--- a/astropy/io/fits/src/zlib.c
+++ /dev/null
@@ -1,3224 +0,0 @@
-/* $Id$
-*/
-
-/*****************************************************************************/
-/*                                                                           */
-/* This file, zlib.c, contains the code  required to compress and            */
-/* uncompress data using the GZIP_1 compression format.                      */
-/*                                                                           */
-/* Copyright (C) 2004 Association of Universities for Research in Astronomy  */
-/* (AURA)                                                                    */
-/*                                                                           */
-/* Redistribution and use in source and binary forms, with or without        */
-/* modification, are permitted provided that the following conditions are    */
-/* met:                                                                      */
-/*                                                                           */
-/*    1. Redistributions of source code must retain the above copyright      */
-/*      notice, this list of conditions and the following disclaimer.        */
-/*                                                                           */
-/*    2. Redistributions in binary form must reproduce the above             */
-/*      copyright notice, this list of conditions and the following          */
-/*      disclaimer in the documentation and/or other materials provided      */
-/*      with the distribution.                                               */
-/*                                                                           */
-/*    3. The name of AURA and its representatives may not be used to         */
-/*      endorse or promote products derived from this software without       */
-/*      specific prior written permission.                                   */
-/*                                                                           */
-/* THIS SOFTWARE IS PROVIDED BY AURA ``AS IS'' AND ANY EXPRESS OR IMPLIED    */
-/* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF      */
-/* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE                  */
-/* DISCLAIMED. IN NO EVENT SHALL AURA BE LIABLE FOR ANY DIRECT, INDIRECT,    */
-/* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,      */
-/* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS     */
-/* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND    */
-/* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR     */
-/* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE    */
-/* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH          */
-/* DAMAGE.                                                                   */
-/*                                                                           */
-/* This code was copied and heavily modified from the ZLIB compression       */
-/* library that was written by Jean-loup Gailly and Mark Adler.  That        */
-/* software containes the following copyright and warranty notices:          */
-/*                                                                           */
-/*  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 at gzip.org          madler at 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).              */
-/*                                                                           */
-/*****************************************************************************/
-
-/* The following came from ZLIB source file deflate.c                        */
-
-#include "deflate.h"
-
-const char deflate_copyright[] =
-   " deflate 1.2.5.f Copyright 1995-2010 Jean-loup Gailly and Mark Adler ";
-
-static uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));
-static uLong ZEXPORT crc32   OF((uLong crc, const Bytef *buf, uInt len));
-
-
-/* ===========================================================================
- *  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)<<s->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 _astropy_deflateInit_(strm, level, version, stream_size)
-    z_streamp strm;
-    int level;
-    const char *version;
-    int stream_size;
-{
-    return _astropy_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 */
-}
-
-static int ZEXPORT deflateReset (z_streamp strm);
-
-/* ========================================================================= */
-int ZEXPORT _astropy_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;
-    }
-    else if (windowBits > 15) {
-        wrap = 2;       /* write gzip wrapper instead */
-        windowBits -= 16;
-    }
-    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);
-        _astropy_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);
-}
-
-/* ========================================================================= */
-static 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 =
-        s->wrap == 2 ? crc32(0L, Z_NULL, 0) :
-        adler32(0L, Z_NULL, 0);
-    s->last_flush = Z_NO_FLUSH;
-
-    _tr_init(s);
-    lm_init(s);
-
-    return Z_OK;
-}
-
-/* =========================================================================
- * 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 _astropy_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) {
-        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
-        {
-            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);
-        }
-    }
-    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;
-    }
-
-    /* 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 */
-    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
-    {
-        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 _astropy_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;
-}
-
-/* ===========================================================================
- * 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);
-    }
-    else if (strm->state->wrap == 2) {
-        strm->adler = crc32(strm->adler, strm->next_in, len);
-    }
-    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;
-}
-
-/* The following came from ZLIB source file inflate.c                        */
-
-#include "zutil.h"
-#include "inftrees.h"
-#include "inflate.h"
-#include "inffast.h"
-
-/* 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));
-
-static 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;
-}
-
-static 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;
-        if (windowBits < 48)
-            windowBits &= 15;
-    }
-
-    /* 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 _astropy_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 _astropy_inflateInit_(strm, version, stream_size)
-z_streamp strm;
-const char *version;
-int stream_size;
-{
-    return _astropy_inflateInit2_(strm, DEF_WBITS, version, stream_size);
-}
-
-local void fixedtables(state)
-struct inflate_state FAR *state;
-{
-#   include "inffixed.h"
-    state->lencode = lenfix;
-    state->lenbits = 9;
-    state->distcode = distfix;
-    state->distbits = 5;
-}
-
-/*
-   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(): */
-
-#  define UPDATE(check, buf, len) \
-    (state->flags ? crc32(check, buf, len) : adler32(check, buf, len))
-
-/* check macros for header crc */
-#  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)
-
-/* 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))
-
-int ZEXPORT _astropy_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 */
-    unsigned char hbuf[4];      /* buffer for gzip header crc calculation */
-    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);
-            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 */
-                ((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;
-            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;
-        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;
-        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;
-            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 ((
-                     state->flags ? hold :
-                     REVERSE(hold)) != state->check) {
-                    strm->msg = (char *)"incorrect data check";
-                    state->mode = BAD;
-                    break;
-                }
-                INITBITS();
-                Tracev((stderr, "inflate:   check matches trailer\n"));
-            }
-            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"));
-            }
-            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 _astropy_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;
-}
-
-
-/*
-   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;
-}
-
-/* The following came from ZLIB source file zutil.c                          */
-
-#include "zutil.h"
-
-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) */
-""};
-
-#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
-
-#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 */
-
-
-/* The following came from ZLIB source file crc32.c                          */
-
-#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 <limits.h>
-#    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);
-
-
-/* ========================================================================
- * Tables of CRC-32s of all single-byte values, made by make_crc_table().
- */
-#include "crc32.h"
-
-/* ========================================================================= */
-#define DO1_ crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8)
-#define DO8_ DO1_; DO1_; DO1_; DO1_; DO1_; DO1_; DO1_; DO1_
-
-/* ========================================================================= */
-static 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;
-}
-
-/* ========================================================================= */
-static uLong ZEXPORT crc32_combine(crc1, crc2, len2)
-    uLong crc1;
-    uLong crc2;
-    z_off_t len2;
-{
-    return crc32_combine_(crc1, crc2, len2);
-}
-
-static uLong ZEXPORT crc32_combine64(crc1, crc2, len2)
-    uLong crc1;
-    uLong crc2;
-    z_off64_t len2;
-{
-    return crc32_combine_(crc1, crc2, len2);
-}
-
-/* The following came from ZLIB source file adler32.c                        */
-
-#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
-
-/* ========================================================================= */
-static 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);
-}
-
-/* ========================================================================= */
-static uLong ZEXPORT adler32_combine(adler1, adler2, len2)
-    uLong adler1;
-    uLong adler2;
-    z_off_t len2;
-{
-    return adler32_combine_(adler1, adler2, len2);
-}
-
-static uLong ZEXPORT adler32_combine64(adler1, adler2, len2)
-    uLong adler1;
-    uLong adler2;
-    z_off64_t len2;
-{
-    return adler32_combine_(adler1, adler2, len2);
-}
-
diff --git a/astropy/io/fits/src/zlib.h b/astropy/io/fits/src/zlib.h
deleted file mode 100644
index 0e9b7ad..0000000
--- a/astropy/io/fits/src/zlib.h
+++ /dev/null
@@ -1,574 +0,0 @@
-/* $Id$
-*/
-
-/*****************************************************************************/
-/*                                                                           */
-/* This file, zlib.h, contains the include information required to compress  */
-/* and uncompress data using the GZIP_1 compression format.                  */
-/*                                                                           */
-/* Copyright (C) 2004 Association of Universities for Research in Astronomy  */
-/* (AURA)                                                                    */
-/*                                                                           */
-/* Redistribution and use in source and binary forms, with or without        */
-/* modification, are permitted provided that the following conditions are    */
-/* met:                                                                      */
-/*                                                                           */
-/*    1. Redistributions of source code must retain the above copyright      */
-/*      notice, this list of conditions and the following disclaimer.        */
-/*                                                                           */
-/*    2. Redistributions in binary form must reproduce the above             */
-/*      copyright notice, this list of conditions and the following          */
-/*      disclaimer in the documentation and/or other materials provided      */
-/*      with the distribution.                                               */
-/*                                                                           */
-/*    3. The name of AURA and its representatives may not be used to         */
-/*      endorse or promote products derived from this software without       */
-/*      specific prior written permission.                                   */
-/*                                                                           */
-/* THIS SOFTWARE IS PROVIDED BY AURA ``AS IS'' AND ANY EXPRESS OR IMPLIED    */
-/* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF      */
-/* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE                  */
-/* DISCLAIMED. IN NO EVENT SHALL AURA BE LIABLE FOR ANY DIRECT, INDIRECT,    */
-/* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,      */
-/* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS     */
-/* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND    */
-/* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR     */
-/* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE    */
-/* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH          */
-/* DAMAGE.                                                                   */
-/*                                                                           */
-/* This code was copied and heavily modified from the ZLIB compression       */
-/* library that was written by Jean-loup Gailly and Mark Adler.  That        */
-/* software containes the following copyright and warranty notices:          */
-/*                                                                           */
-/*  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 at gzip.org          madler at 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
-
-/* The following was copied from ZLIB zconf.h                                */
-
-#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 _astropy_deflate               z_deflate
-#  define _astropy_deflateEnd            z_deflateEnd
-#  define _astropy_deflateInit2_         z_deflateInit2_
-#  define _astropy_deflateInit_          z_deflateInit_
-#  define gz_error              z_gz_error
-#  define gz_intmax             z_gz_intmax
-#  define gz_strwinerror        z_gz_strwinerror
-
-#  define _astropy_inflate               z_inflate
-#  define _astropy_inflateEnd            z_inflateEnd
-#  define _astropy_inflateInit2_         z_inflateInit2_
-#  define _astropy_inflateInit_          z_inflateInit_
-#  define inflate_copyright     z_inflate_copyright
-#  define inflate_fast          z_inflate_fast
-#  define inflate_table         z_inflate_table
-#  define zcalloc               z_zcalloc
-#  define zcfree                z_zcfree
-
-/* 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 <windows.h>
-     /* 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
-
-#ifdef HAVE_UNISTD_H    /* may be set to #if 1 by ./configure */
-#  define Z_HAVE_UNISTD_H
-#endif
-
-#ifdef STDC
-#  include <sys/types.h>    /* 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 <unistd.h>       /* for SEEK_* and off_t */
-#  ifdef VMS
-#    include <unixio.h>     /* 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(_astropy_deflateInit_,"DEIN")
-  #pragma map(_pyfist_deflateInit2_,"DEIN2")
-  #pragma map(_astropy_deflateEnd,"DEEND")
-  #pragma map(_astropy_inflateInit_,"ININ")
-  #pragma map(_astropy_inflateInit2_,"ININ2")
-  #pragma map(_astropy_inflateEnd,"INEND")
-  #pragma map(inflate_table,"INTABL")
-  #pragma map(inflate_fast,"INFA")
-  #pragma map(inflate_copyright,"INCOPY")
-#endif
-
-/* The following was copied from ZLIB zlib.h                                 */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define ZLIB_VERSION "1.2.5.f-astropy-mods-v1"
-#define ZLIB_VERNUM 0x125f
-
-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;
-
-                        /* 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_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 */
-
-ZEXTERN int ZEXPORT _astropy_deflate OF((z_streamp strm, int flush));
-
-ZEXTERN int ZEXPORT _astropy_deflateEnd OF((z_streamp strm));
-
-ZEXTERN int ZEXPORT _astropy_inflate OF((z_streamp strm, int flush));
-
-ZEXTERN int ZEXPORT _astropy_inflateEnd OF((z_streamp strm));
-
-typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *));
-typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned));
-
-                        /* checksum functions */
-
-                        /* 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 _astropy_deflateInit_ OF((z_streamp strm, int level,
-                                     const char *version, int stream_size));
-ZEXTERN int ZEXPORT _astropy_inflateInit_ OF((z_streamp strm,
-                                     const char *version, int stream_size));
-ZEXTERN int ZEXPORT _astropy_deflateInit2_ OF((z_streamp strm, int  level,
-                                      int  method,
-                                      int windowBits, int memLevel,
-                                      int strategy, const char *version,
-                                      int stream_size));
-ZEXTERN int ZEXPORT _astropy_inflateInit2_ OF((z_streamp strm, int  windowBits,
-                                      const char *version, int stream_size));
-
-#define deflateInit(strm, level) \
-        _astropy_deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream))
-#define inflateInit(strm) \
-        _astropy_inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream))
-#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
-        _astropy_deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
-                      (strategy),           ZLIB_VERSION, sizeof(z_stream))
-#define inflateInit2(strm, windowBits) \
-        _astropy_inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream))
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* ZLIB_H */
diff --git a/astropy/io/fits/src/zutil.h b/astropy/io/fits/src/zutil.h
deleted file mode 100644
index 30ba0e8..0000000
--- a/astropy/io/fits/src/zutil.h
+++ /dev/null
@@ -1,339 +0,0 @@
-/* $Id$
-*/
-
-/*****************************************************************************/
-/*                                                                           */
-/* This file, zlib.h, contains the include information required to compress  */
-/* and uncompress data using the GZIP_1 compression format.                  */
-/*                                                                           */
-/* Copyright (C) 2004 Association of Universities for Research in Astronomy  */
-/* (AURA)                                                                    */
-/*                                                                           */
-/* Redistribution and use in source and binary forms, with or without        */
-/* modification, are permitted provided that the following conditions are    */
-/* met:                                                                      */
-/*                                                                           */
-/*    1. Redistributions of source code must retain the above copyright      */
-/*      notice, this list of conditions and the following disclaimer.        */
-/*                                                                           */
-/*    2. Redistributions in binary form must reproduce the above             */
-/*      copyright notice, this list of conditions and the following          */
-/*      disclaimer in the documentation and/or other materials provided      */
-/*      with the distribution.                                               */
-/*                                                                           */
-/*    3. The name of AURA and its representatives may not be used to         */
-/*      endorse or promote products derived from this software without       */
-/*      specific prior written permission.                                   */
-/*                                                                           */
-/* THIS SOFTWARE IS PROVIDED BY AURA ``AS IS'' AND ANY EXPRESS OR IMPLIED    */
-/* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF      */
-/* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE                  */
-/* DISCLAIMED. IN NO EVENT SHALL AURA BE LIABLE FOR ANY DIRECT, INDIRECT,    */
-/* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,      */
-/* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS     */
-/* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND    */
-/* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR     */
-/* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE    */
-/* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH          */
-/* DAMAGE.                                                                   */
-/*                                                                           */
-/* This code was copied and heavily modified from the ZLIB compression       */
-/* library that was written by Jean-loup Gailly and Mark Adler.  That        */
-/* software containes the following copyright and warranty notices:          */
-/*                                                                           */
-/*  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 at gzip.org          madler at 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).              */
-/*                                                                           */
-/*****************************************************************************/
-
-/* This code was copied unmodified from ZLIB zutil.h -- internal interface   */
-/* and configuration of the compression library                              */
-
-#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 <stddef.h>
-#  endif
-#  include <string.h>
-#  include <stdlib.h>
-#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 <alloc.h>
-#    endif
-#  else /* MSC or DJGPP */
-#    include <malloc.h>
-#  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 <malloc.h>
-#  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 <unix.h> /* 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 <stdio.h>
-   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 */
diff --git a/astropy/io/fits/tests/__init__.py b/astropy/io/fits/tests/__init__.py
index e28a9ab..fb696a8 100644
--- a/astropy/io/fits/tests/__init__.py
+++ b/astropy/io/fits/tests/__init__.py
@@ -4,6 +4,7 @@ from __future__ import division  # confidence high
 import os
 import shutil
 import tempfile
+import warnings
 
 from ... import fits
 
@@ -21,7 +22,13 @@ class FitsTestCase(object):
         fits.STRIP_HEADER_WHITESPACE.set(True)
         fits.USE_MEMMAP.set(True)
 
+        # Ignore deprecation warnings--this only affects Python 2.5 and 2.6,
+        # since deprecation warnings are ignored by defualt on 2.7
+        warnings.simplefilter('ignore')
+        warnings.simplefilter('always', UserWarning)
+
     def teardown(self):
+        warnings.resetwarnings()
         if hasattr(self, 'temp_dir') and os.path.exists(self.temp_dir):
             shutil.rmtree(self.temp_dir)
 
diff --git a/astropy/io/fits/tests/data/zerowidth.fits b/astropy/io/fits/tests/data/zerowidth.fits
index d2465ce..d47101f 100644
--- a/astropy/io/fits/tests/data/zerowidth.fits
+++ b/astropy/io/fits/tests/data/zerowidth.fits
@@ -1,3 +1,27 @@
-SIMPLE  =                    T / Standard FITS file                             BITPIX  =                    8                                                  NAXIS   =                    2                                                  NAXIS1  =            777777701 / Signature code for UV data in table            NAXIS2  =                    0 / No data in primary array                       EXTEND  =                    T / All data in tables                             BLOCKED =                    T / Tape may be blocked                            HISTORY FILLM / Image created by user 1111 at 08-FEB-2011   11:02:48            HISTORY FILLM OUTNAME='COMA        '   OUTCLASS='CH 0  '                        HISTORY FILLM OUTSEQ=    1   OUTDISK=  2                                        HISTORY FILLM INFILE='COMA:A_CONFIG/AK462_'                                     HISTORY FILLM NFILES=    0                                                      HISTORY FILLM BAND = '4', QUAL =     0,  CALC = '    '                          HISTORY FILLM VLAMODE ='  '                                                     HISTORY FILLM / Control program ID =                                            HISTORY FILLM / VLA conf. = A                                                   HISTORY FILLM / correlator mode = 2CD                                           HISTORY FILLM / AP options =                                                    HISTORY FILLM /TIMERANG = beginning to  999/00:00:00.00                         HISTORY FILLM  TIMERANG =   0.000000E+00  9.990000E+02  / days                  HISTORY FILLM BCHAN =    1 ECHAN =    1 / Spectral channels                     HISTORY FILLM CPARM(1) =  0.000 / Integration (sec)                             HISTORY FILLM CPARM(3) =   3. / Max. IF stat. to pass                           HISTORY FILLM CPARM(4) =   0. / .lt. 0 => no shadow flag                        HISTORY FILLM CPARM(6) =   0. / Subarray                                        HISTORY FILLM CPARM(7) =     0.000 / FQ entry tolerance                         HISTORY FILLM CPARM(8) =   5.00 / CL table time increment                       HISTORY FILLM CPARM(9) =   0.00 / TY table time increment                       HISTORY FILLM  Opacity correction in CL table weighted average of weather       HISTORY FILLM     and season.  weight for weather = 0.50                        HISTORY FILLM  Gain curve correction in CL table read from file:                HISTORY FILLM     standard system VLA antenna gains file                        HISTORY FILLM     with variation as function of antenna and band                HISTORY FILLM / Telescope = VLA      Program = AK462                            HISTORY FILLM / Weighted with nominal sensitivities                             HISTORY FILLM / Data compressed, weighting info reduced                         HISTORY FILLM RELEASE = '31DEC08'                                               HISTORY SPLIT RELEASE ='31DEC08 '  /********* Start 08-FEB-2011   13:16:44      HISTORY SPLIT INNAME='COMA        '   INCLASS='CH 0  '                          HISTORY SPLIT INSEQ=    1   INDISK=  2                                          HISTORY SPLIT OUTNAME='1251+278    '   OUTCLASS='SPLIT '                        HISTORY SPLIT OUTSEQ=    1   OUTDISK=  2                                        HISTORY SPLIT /TIMERANG = beginning to end                                      HISTORY SPLIT STOKES = '    ' / Stokes type                                     HISTORY SPLIT BIF =   1, EIF =   1/ IF range                                    HISTORY SPLIT BCHAN =   1, ECHAN =   1/ Chan range                              HISTORY SPLIT SUBARRAY =   0                                                    HISTORY SPLIT / Weights not calibrated                                          HISTORY SPLIT /       190 Visibilities written                                  ORIGIN  = 'AIPSlocalhost    SARATOGA             31DEC08'    /                  DATE    = '2011-02-08'   / File written on Greenwich yyyy-mm-dd                 HISTORY AIPS   IMNAME='1251+278    ' IMCLASS='SPLIT ' IMSEQ=   1     /          HISTORY AIPS   USERNO= 1111            /                                        COMMENT   FITS (Flexible Image Transport System) format is defined in 'AstronomyCOMMENT   and Astrophysics', volume 376, page 359; bibcode: 2001A&A...376..359H          / Where baseline = 256*ant1 + ant2 + (array#-1)/100                    HISTORY AIPS   SORT ORDER = 'TB'                                                              / Where T means TIME (IAT)                                                      / Where B means BASELINE NUM                                      HISTORY AIPS   IPIECE= 1 NPIECE= 1     / piece number                           HISTORY AIPS   FIRSTVIS=           1     / first vis #                          HISTORY AIPS   LASTVIS =         190     / last vis #                           END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             XTENSION= 'BINTABLE'           / Extension type                                 BITPIX  =                    8 / Binary data                                    NAXIS   =                    2 / Table is a matrix                              NAXIS1  =                   24 / Width of table in bytes                        NAXIS2  =                    1 / Number of entries in table                     PCOUNT  =                    0 / Random parameter count                         GCOUNT  =                    1 / Group count                                    TFIELDS =                    5 / Number of fields in each row                   EXTNAME = 'AIPS FQ '           / AIPS table file                                EXTVER  =                    1 / Version number of table                        TFORM1  = '1J      '           / FORTRAN format of field  1                     TTYPE1  = 'FRQSEL          '   / Type (heading) of field  1                     TUNIT1  = '        '           / Physical units of field  1                     TFORM2  = '1D      '           / FORTRAN format of field  2                     TTYPE2  = 'IF FREQ         '   / Type (heading) of field  2                     TUNIT2  = 'HZ      '           / Physical units of field  2                     TFORM3  = '1E      '           / FORTRAN format of field  3                     TTYPE3  = 'CH WIDTH        '   / Type (heading) of field  3                     TUNIT3  = 'HZ      '           / Physical units of field  3                     TFORM4  = '1E      '           / FORTRAN format of field  4                     TTYPE4  = 'TOTAL BANDWIDTH '   / Type (heading) of field  4                     TUNIT4  = 'HZ      '           / Physical units of field  4                     TFORM5  = '1J      '           / FORTRAN format of field  5                     TTYPE5  = 'SIDEBAND        '   / Type (heading) of field  5                     TUNIT5  = '        '           / Physical units of field  5                     NO_IF   =            1                                                          END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        IŽN\IŽN\                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           XTENSION= 'BINTABLE'           / Extension type                                 BITPIX  =                    8 / Binary data                                    NAXIS   =                    2 / Table is a matrix                              NAXIS1  =                   70 / Width of table in bytes                        NAXIS2  =                   29 / Number of entries in table                     PCOUNT  =                    0 / Random parameter count                         GCOUNT  =                    1 / Group count                                    TFIELDS =                   11 / Number of fields in each row                   EXTNAME = 'AIPS AN '           / AIPS table file                                EXTVER  =                    1 / Version number of table                        TFORM1  = '8A      '           / FORTRAN format of field  1                     TTYPE1  = 'ANNAME          '   / Type (heading) of field  1                     TUNIT1  = '        '           / Physical units of field  1                     TFORM2  = '3D      '           / FORTRAN format of field  2                     TTYPE2  = 'STABXYZ         '   / Type (heading) of field  2                     TUNIT2  = 'METERS  '           / Physical units of field  2                     TFORM3  = '0D      '           / FORTRAN format of field  3                     TTYPE3  = 'ORBPARM         '   / Type (heading) of field  3                     TUNIT3  = '        '           / Physical units of field  3                     TFORM4  = '1J      '           / FORTRAN format of field  4                     TTYPE4  = 'NOSTA           '   / Type (heading) of field  4                     TUNIT4  = '        '           / Physical units of field  4                     TFORM5  = '1J      '           / FORTRAN format of field  5                     TTYPE5  = 'MNTSTA          '   / Type (heading) of field  5                     TUNIT5  = '        '           / Physical units of field  5                     TFORM6  = '1E      '           / FORTRAN format of field  6                     TTYPE6  = 'STAXOF          '   / Type (heading) of field  6                     TUNIT6  = 'METERS  '           / Physical units of field  6                     TFORM7  = '1A      '           / FORTRAN format of field  7                     TTYPE7  = 'POLTYA          '   / Type (heading) of field  7                     TUNIT7  = '        '           / Physical units of field  7                     TFORM8  = '1E      '           / FORTRAN format of field  8                     TTYPE8  = 'POLAA           '   / Type (heading) of field  8                     TUNIT8  = 'DEGREES '           / Physical units of field  8                     TFORM9  = '2E      '           / FORTRAN format of field  9                     TTYPE9  = 'POLCALA         '   / Type (heading) of field  9                     TUNIT9  = '        '           / Physical units of field  9                     TFORM10 = '1A      '           / FORTRAN format of field 10                     TTYPE10 = 'POLTYB          '   / Type (heading) of field 10                     TUNIT10 = '        '           / physical units of field 10                     TFORM11 = '1E      '           / FORTRAN format of field 11                     TTYPE11 = 'POLAB           '   / Type (heading) of field 11                     TUNIT11 = 'DEGREES '           / physical units of field 11                     TFORM12 = '2E      '           / FORTRAN format of field 12                     TTYPE12 = 'POLCALB         '   / Type (heading) of field 12                     TUNIT12 = '        '           / physical units of field 12                     ARRAYX  =  -0.16011853650000000D+07                                             ARRAYY  =  -0.50419775470000003D+07                                             ARRAYZ  =   0.35548758700000001D+07                                             GSTIA0  =   0.15366985882155805D+03                                             DEGPDY  =   0.36098564497481129D+03                                             FREQ    =   0.73799999999999955D+08                                             RDATE   = '1998-02-24'                                                          POLARX  =   0.00000000000000000D+00                                             POLARY  =   0.00000000000000000D+00                                             UT1UTC  =   0.00000000000000000D+00                                             DATUTC  =   0.00000000000000000D+00                                             TIMSYS  = 'IAT     '                                                            ARRNAM  = 'VLA     '                                                            NUMORB  =            0                                                          NOPCAL  =            2                                                          FREQID  =           -1                                                          IATUTC  =   0.00000000000000000D+00                                             END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             VLA:_W16@=°Ï~–ÖÀ”—ø!qøÀ†ù‚a+       9¼œóR            L            VLA:_N16À‰bu2À_=ëwxíd@’x„Ê©Áã           R            L            VLA:_N48À´—Crs‚À‰¼‹¯Éö@¾oþ‡vy       º%	WR            L            VLA:_W8 @c,•JüóÀyF×ÀkìE­Ûa       <c¨R            L            VLA:_N56ÀºÖáe­%ÀÃ³žpj@ÃÒe)ˆ       ;
u¸R            L            VLA:_E16 at wøxG@–ƒù$á:ŸÀ`ÊÒÁ       :<œóR            L            VLA:_OUT                                   R            L            VLA:_N8 ÀnrT¦xUsÀCžlzpâ@v‘¤]       <
u¸R            L            VLA:_E8 @\žj°fê¬@{jøÕŒÆtÀe.ÇäÄ„   	    ¼œ¯ºR            L            VLA:_W40@¢µþ8Öñ6À¸Îo1±À«½ä6žÙÝ   
+SIMPLE  =                    T / Standard FITS file                             BITPIX  =                    8 /                                                NAXIS   =                    2 /                                                NAXIS1  =            777777701 / Signature code for UV data in table            NAXIS2  =                    0 / No data in primary array                       EXTEND  =                    T / All data in tables                             BLOCKED =                    T / Tape may be blocked                            HISTORY FILLM / Image created by user 1111 at 08-FEB-2011   11:02:48            HISTORY FILLM OUTNAME='COMA        '   OUTCLASS='CH 0  '                        HISTORY FILLM OUTSEQ=    1   OUTDISK=  2                                        HISTORY FILLM INFILE='COMA:A_CONFIG/AK462_'                                     HISTORY FILLM NFILES=    0                                                      HISTORY FILLM BAND = '4', QUAL =     0,  CALC = '    '                          HISTORY FILLM VLAMODE ='  '                                                     HISTORY FILLM / Control program ID =                                            HISTORY FILLM / VLA conf. = A                                                   HISTORY FILLM / correlator mode = 2CD                                           HISTORY FILLM / AP options =                                                    HISTORY FILLM /TIMERANG = beginning to  999/00:00:00.00                         HISTORY FILLM  TIMERANG =   0.000000E+00  9.990000E+02  / days                  HISTORY FILLM BCHAN =    1 ECHAN =    1 / Spectral channels                     HISTORY FILLM CPARM(1) =  0.000 / Integration (sec)                             HISTORY FILLM CPARM(3) =   3. / Max. IF stat. to pass                           HISTORY FILLM CPARM(4) =   0. / .lt. 0 => no shadow flag                        HISTORY FILLM CPARM(6) =   0. / Subarray                                        HISTORY FILLM CPARM(7) =     0.000 / FQ entry tolerance                         HISTORY FILLM CPARM(8) =   5.00 / CL table time increment                       HISTORY FILLM CPARM(9) =   0.00 / TY table time increment                       HISTORY FILLM  Opacity correction in CL table weighted average of weather       HISTORY FILLM     and season.  weight for weather = 0.50                        HISTORY FILLM  Gain curve correction in CL table read from file:                HISTORY FILLM     standard system VLA antenna gains file                        HISTORY FILLM     with variation as function of antenna and band                HISTORY FILLM / Telescope = VLA      Program = AK462                            HISTORY FILLM / Weighted with nominal sensitivities                             HISTORY FILLM / Data compressed, weighting info reduced                         HISTORY FILLM RELEASE = '31DEC08'                                               HISTORY SPLIT RELEASE ='31DEC08 '  /********* Start 08-FEB-2011   13:16:44      HISTORY SPLIT INNAME='COMA        '   INCLASS='CH 0  '                          HISTORY SPLIT INSEQ=    1   INDISK=  2                                          HISTORY SPLIT OUTNAME='1251+278    '   OUTCLASS='SPLIT '                        HISTORY SPLIT OUTSEQ=    1   OUTDISK=  2                                        HISTORY SPLIT /TIMERANG = beginning to end                                      HISTORY SPLIT STOKES = '    ' / Stokes type                                     HISTORY SPLIT BIF =   1, EIF =   1/ IF range                                    HISTORY SPLIT BCHAN =   1, ECHAN =   1/ Chan range                              HISTORY SPLIT SUBARRAY =   0                                                    HISTORY SPLIT / Weights not calibrated                                          HISTORY SPLIT /       190 Visibilities written                                  ORIGIN  = 'AIPSlocalhost    SARATOGA             31DEC08'    /                  DATE    = '2011-02-08'   / File written on Greenwich yyyy-mm-dd                 HISTORY AIPS   IMNAME='1251+278    ' IMCLASS='SPLIT ' IMSEQ=   1     /          HISTORY AIPS   USERNO= 1111            /                                        COMMENT   FITS (Flexible Image Transport System) format is defined in 'AstronomyCOMMENT   and Astrophysics', volume 376, page 359; bibcode: 2001A&A...376..359H          / Where baseline = 256*ant1 + ant2 + (array#-1)/100                    HISTORY AIPS   SORT ORDER = 'TB'                                                              / Where T means TIME (IAT)                                                      / Where B means BASELINE NUM                                      HISTORY AIPS   IPIECE= 1 NPIECE= 1     / piece number                           HISTORY AIPS   FIRSTVIS=           1     / first vis #                          HISTORY AIPS   LASTVIS =         190     / last vis #                           END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             XTENSION= 'BINTABLE'           / Extension type                                 BITPIX  =                    8 / Binary data                                    NAXIS   =                    2 / Table is a matrix                              NAXIS1  =                   24 / Width of table in bytes                        NAXIS2  =                    1 / Number of entries in table                     PCOUNT  =                    0 / Random parameter count                         GCOUNT  =                    1 / Group count                                    TFIELDS =                    5 / Number of fields in each row                   EXTNAME = 'AIPS FQ '           / AIPS table file                                EXTVER  =                    1 / Version number of table                        TFORM1  = '1J      '           / FORTRAN format of field  1                     TTYPE1  = 'FRQSEL          '   / Type (heading) of field  1                     TUNIT1  = '        '           / Physical units of field  1                     TFORM2  = '1D      '           / FORTRAN format of field  2                     TTYPE2  = 'IF FREQ         '   / Type (heading) of field  2                     TUNIT2  = 'HZ      '           / Physical units of field  2                     TFORM3  = '1E      '           / FORTRAN format of field  3                     TTYPE3  = 'CH WIDTH        '   / Type (heading) of field  3                     TUNIT3  = 'HZ      '           / Physical units of field  3                     TFORM4  = '1E      '           / FORTRAN format of field  4                     TTYPE4  = 'TOTAL BANDWIDTH '   / Type (heading) of field  4                     TUNIT4  = 'HZ      '           / Physical units of field  4                     TFORM5  = '1J      '           / FORTRAN format of field  5                     TTYPE5  = 'SIDEBAND        '   / Type (heading) of field  5                     TUNIT5  = '        '           / Physical units of field  5                     NO_IF   =            1                                                          END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        IŽN\IŽN\                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           XTENSION= 'BINTABLE'           / Extension type                                 BITPIX  =                    8 / Binary data                                    NAXIS   =                    2 / Table is a matrix                              NAXIS1  =                   70 / Width of table in bytes                        NAXIS2  =                   29 / Number of entries in table                     PCOUNT  =                    0 / Random parameter count                         GCOUNT  =                    1 / Group count                                    TFIELDS =                   12 / Number of fields in each row                   EXTNAME = 'AIPS AN '           / AIPS table file                                EXTVER  =                    1 / Version number of table                        TFORM1  = '8A      '           / FORTRAN format of field  1                     TTYPE1  = 'ANNAME          '   / Type (heading) of field  1                     TUNIT1  = '        '           / Physical units of field  1                     TFORM2  = '3D      '           / FORTRAN format of field  2                     TTYPE2  = 'STABXYZ         '   / Type (heading) of field  2                     TUNIT2  = 'METERS  '           / Physical units of field  2                     TFORM3  = '0D      '           / FORTRAN format of field  3                     TTYPE3  = 'ORBPARM         '   / Type (heading) of field  3                     TUNIT3  = '        '           / Physical units of field  3                     TFORM4  = '1J      '           / FORTRAN format of field  4                     TTYPE4  = 'NOSTA           '   / Type (heading) of field  4                     TUNIT4  = '        '           / Physical units of field  4                     TFORM5  = '1J      '           / FORTRAN format of field  5                     TTYPE5  = 'MNTSTA          '   / Type (heading) of field  5                     TUNIT5  = '        '           / Physical units of field  5                     TFORM6  = '1E      '           / FORTRAN format of field  6                     TTYPE6  = 'STAXOF          '   / Type (heading) of field  6                     TUNIT6  = 'METERS  '           / Physical units of field  6                     TFORM7  = '1A      '           / FORTRAN format of field  7                     TTYPE7  = 'POLTYA          '   / Type (heading) of field  7                     TUNIT7  = '        '           / Physical units of field  7                     TFORM8  = '1E      '           / FORTRAN format of field  8                     TTYPE8  = 'POLAA           '   / Type (heading) of field  8                     TUNIT8  = 'DEGREES '           / Physical units of field  8                     TFORM9  = '2E      '           / FORTRAN format of field  9                     TTYPE9  = 'POLCALA         '   / Type (heading) of field  9                     TUNIT9  = '        '           / Physical units of field  9                     TFORM10 = '1A      '           / FORTRAN format of field 10                     TTYPE10 = 'POLTYB          '   / Type (heading) of field 10                     TUNIT10 = '        '           / physical units of field 10                     TFORM11 = '1E      '           / FORTRAN format of field 11                     TTYPE11 = 'POLAB           '   / Type (heading) of field 11                     TUNIT11 = 'DEGREES '           / physical units of field 11                     TFORM12 = '2E      '           / FORTRAN format of field 12                     TTYPE12 = 'POLCALB         '   / Type (heading) of field 12                     TUNIT12 = '        '           / physical units of field 12                     ARRAYX  =  -0.16011853650000000D+07                                             ARRAYY  =  -0.50419775470000003D+07                                             ARRAYZ  =   0.35548758700000001D+07                                             GSTIA0  =   0.15366985882155805D+03                                             DEGPDY  =   0.36098564497481129D+03                                             FREQ    =   0.73799999999999955D+08                                             RDATE   = '1998-02-24'                                                          POLARX  =   0.00000000000000000D+00                                             POLARY  =   0.00000000000000000D+00                                             UT1UTC  =   0.00000000000000000D+00                                             DATUTC  =   0.00000000000000000D+00                                             TIMSYS  = 'IAT     '                                                            ARRNAM  = 'VLA     '                                                            NUMORB  =            0                                                          NOPCAL  =            2                                                          FREQID  =           -1                                                          IATUTC  =   0.00000000000000000D+00                                             END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             VLA:_W16@=°Ï~–ÖÀ”—ø!qøÀ†ù‚a+       9¼œóR            L            VLA:_N16À‰bu2À_=ëwxíd@’x„Ê©Áã           R            L            VLA:_N48À´—Crs‚À‰¼‹¯Éö@¾oþ‡vy       º%	WR            L            VLA:_W8 @c,•JüóÀyF×ÀkìE­Ûa       <c¨R            L            VLA:_N56ÀºÖáe­%ÀÃ³žpj@ÃÒe)ˆ       ;
u¸R            L            VLA:_E16 at wøxG@–ƒù$á:ŸÀ`ÊÒÁ       :<œóR            L            VLA:_OUT                                   R            L            VLA:_N8 ÀnrT¦xUsÀCžlzpâ@v‘¤]       <
u¸R            L            VLA:_E8 @\žj°fê¬@{jøÕŒÆtÀe.ÇäÄ„   	    ¼œ¯ºR            L            VLA:_W40@¢µþ8Öñ6À¸Îo1±À«½ä6žÙÝ   
     8¼œóR            L            VLA:_N24À™ñÈhãü Àp6‚¹¿[º@£,éòSÊ…       ;gÖ@R            L            VLA:_W32@™ 6J¢*À°éðØD®ñÀ¢á\Æ™|       º…™×R            L            VLA:_W56@°£å€%=ÀÆ¿
ÖÐLÀ¸¹øç40„   
    :÷ŽR            L            VLA:_E64@¯æùÐ@Î_:.$ôÀ·f{ɯ÷8       º
u¸R            L            VLA:_N64ÀÀá[,Y,À•°;n3@Èì]!ݳ       ;.Ü/R            L            VLA:_E24@‡éÕ%SíT@¦’æ7†¦ÉÀ‘SxŒ‚       »ˆŒLR            L            VLA:_W64@´å/Ë'‰ñÀËÈ-‡¸‹ÁÀ¿q*2áÆ       ºû{ñR            L            VLA:_E48@£“–¨_†@‰÷‡æåÀ¬_:Á 9       ºó R            L            VLA:_N40À®KOOLµÀ‚Òcςݶ@¶BóA at b       »iáR            L            VLA:_E40@œ³û¡ aÈ@»YÈO|À¤Òg_åý       ;†•TR            L            VLA:_E56@©T1y@È'	7Ô]+À²ŸsºÝÚ       ¹ÜrR            L            VLA:_E72@²ùó2새@Ò¤‘Ī`À¼käuÂÄ       ;~¾R            L            VLA:_W24@k’v!ÞÀ¤¦ΝϰÀ— Ÿ|B5‡       º-xR            L            VLA:_N32À¤Š&o.ýÒÀyªps(@®[E ¹oÚ       :ÄxÖR            L            VLA:_W72@¹ˆI
-Å ÌÀÑ ŒÊ3ÐLÀÃ
½’¥(       »iÍ:R            L            VLA:_W48@©–M^¹]ºÀÀõ@Äp½À²öÕÍq0Ÿ       ºÈfÅR            L            VLA:_N72ÀĨ¶«ïƒ„À™ÍÑ©u@΁nF¯¥È       ¸{{ñR            L            VLA:_E32@“•®,½~@²}ŸèläÀœc¤zÉ,       »BÜR            L            VPT:_OUT                                   R            L                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
\ No newline at end of file
+Å ÌÀÑ ŒÊ3ÐLÀÃ
½’¥(       »iÍ:R            L            VLA:_W48@©–M^¹]ºÀÀõ@Äp½À²öÕÍq0Ÿ       ºÈfÅR            L            VLA:_N72ÀĨ¶«ïƒ„À™ÍÑ©u@΁nF¯¥È       ¸{{ñR            L            VLA:_E32@“•®,½~@²}ŸèläÀœc¤zÉ,       »BÜR            L            VPT:_OUT                                   R            L                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              XTENSION= 'BINTABLE'           / Extension type                                 BITPIX  =                    8 / Binary data                                    NAXIS   =                    2 / Table is a matrix                              NAXIS1  =                   48 / Width of table in bytes                        NAXIS2  =                   20 / Number of entries in table                     PCOUNT  =                    0 / Random parameter count                         GCOUNT  =                    1 / Group count                                    TFIELDS =                   11 / Number of fields in each row                   EXTNAME = 'AIPS WX '           / AIPS table file                                EXTVER  =                    1 / Version number of table                        TFORM1  = '1D      '           / FORTRAN format of field  1                     TTYPE1  = 'TIME            '   / Type (heading) of field  1                     TUNIT1  = 'DAYS    '           / Physical units of field  1                     TFORM2  = '1E      '           / FORTRAN format of field  2                     TTYPE2  = 'TIME_INTERVAL   '   / Type (heading) of field  2                     TUNIT2  = 'DAYS    '           / Physical units of field  2                     TFORM3  = '1J      '           / FORTRAN format of field  3                     TTYPE3  = 'ANTENNA_NO      '   / Type (heading) of field  3                     TUNIT3  = '        '           / Physical units of field  3                     TFORM4  = '1J      '           / FORTRAN format of field  4                     TTYPE4  = 'SUBARRAY        '   / Type (heading) of field  4                     TUNIT4  = '        '           / Physical units of field  4                     TFORM5  = '1E      '           / FORTRAN format of field  5                     TTYPE5  = 'TEMPERATURE     '   / Type (heading) of field  5                     TUNIT5  = 'CENTIGRA'           / Physical units of field  5                     TFORM6  = '1E      '           / FORTRAN format of field  6                     TTYPE6  = 'PRESSURE        '   / Type (heading) of field  6                     TUNIT6  = 'MILLIBAR'           / Physical units of field  6                     TFORM7  = '1E      '           / FORTRAN format of field  7                     TTYPE7  = 'DEWPOINT        '   / Type (heading) of field  7                     TUNIT7  = 'CENTIGRA'           / Physical units of field  7                     TFORM8  = '1E      '           / FORTRAN format of field  8                     TTYPE8  = 'WIND_VELOCITY   '   / Type (heading) of field  8                     TUNIT8  = 'M/SEC   '           / Physical units of field  8                     TFORM9  = '1E      '           / FORTRAN format of field  9                     TTYPE9  = 'WIND_DIRECTION  '   / Type (heading) of field  9                     TUNIT9  = 'DEGREES '           / Physical units of field  9                     TFORM10 = '1E      '           / FORTRAN format of field 10                     TTYPE10 = 'WVR_H2O         '   / Type (heading) of field 10                     TUNIT10 = '        '           / physical units of field 10                     TFORM11 = '1E      '           / FORTRAN format of field 11                     TTYPE11 = 'IONOS_ELECTRON  '   / Type (heading) of field 11                     TUNIT11 = '        '           / physical units of field 11                     OBSCODE = 'AK462   '                                                            RDATE   = '1998-02-24'                                                          TABREV  =            3                                                          END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ?Â{B^©·=8ò¹Ö       @¥
xDE,À¥
x at q™˜Cƒ
+<        ?Â
FÏ8ò¹Ö       @¥
xDE,À¥
x at a™˜C†èô        ?‚Ø-[çÁ8ò¹Ö       @¥
xDEÈÀ¡¯(@ŽfdC†uÀ        ?†£µ 8ò¹Ö       @¥
xDEÈÀ¡¯(@„ÌÌC‹Qè        ?ŠmüE8ò¹Ö       @¥
xDEÈÀžPØ@k34CÞ´        ?ÂŽ8ãg0ˆ8ò¹Ö       @¥
xDEÈÀ—”4 at ffdC‰è        ?Â’ÊÀHÊ8ò¹Ö       @¥
xDE,À—”4@„  C†ÿü        ?™™™ryN8ò¹Ö       @¥
xDEÈÀžPØ@X  C„¬        ?d€Ë‘8ò¹Ö       @¡¯(DEÈÀ¡¯(@q™˜Cˆúà        ?¡/h$©Ó8ò¹Ö       @¡¯(DEÈÀ¡¯(@S34CõÀ        ?¤úO}Â8ò¹Ö       @¡¯(DEÈÀ¡¯(@vfdC„¨ô        ?¬/ò™8ò¹Ö       @¡¯(DEÈÀ¡¯(@`  C†^´        ?°[‰
+Û8ò¹Ö       @žPØDE,À¡¯(@~fdC=p        ?·ðÔ;;`8ò¹Ö       @žPØDEÈÀ¡¯(@’fdC‚:à        ?»»»”S¡8ò¹Ö       @žPØDEÈÀ¡¯(@‘™˜C„¨ô        ?ÂÃQŠF„&8ò¹Ö       @šò„DEÈÀ¡¯(@)™˜C‡¡D        ?ÂÇqŸœh8ò¹Ö       @šò„DEÈÀ¡¯(@¤ÌÌC‚:à        ?Âβ@QÌì8ò¹Ö       @šò„DEÈÀ¡¯(@ŽfdC€n        ?ÂÒ}'ªå/8ò¹Ö       @—”4DEÈÀ¡¯(@€ÌÌC‰Ê<        ?Ã-‚Ø+c8ò¹Ö       @—”4DEÈÀ¨kÈ@…™˜CŠ=l                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        XTENSION= 'BINTABLE'           / Extension type                                 BITPIX  =                    8 / Binary data                                    NAXIS   =                    2 / Table is a matrix                              NAXIS1  =                   28 / Width of table in bytes                        NAXIS2  =                   45 / Number of entries in table                     PCOUNT  =                    0 / Random parameter count                         GCOUNT  =                    1 / Group count                                    TFIELDS =                    7 / Number of fields in each row                   EXTNAME = 'AIPS OF '           / AIPS table file                                EXTVER  =                    1 / Version number of table                        TFORM1  = '1E      '           / FORTRAN format of field  1                     TTYPE1  = 'TIME            '   / Type (heading) of field  1                     TUNIT1  = 'DAYS    '           / Physical units of field  1                     TFORM2  = '1J      '           / FORTRAN format of field  2                     TTYPE2  = 'SOURCE ID       '   / Type (heading) of field  2                     TUNIT2  = '        '           / Physical units of field  2                     TFORM3  = '1J      '           / FORTRAN format of field  3                     TTYPE3  = 'ANTENNA NO.     '   / Type (heading) of field  3                     TUNIT3  = '        '           / Physical units of field  3                     TFORM4  = '1J      '           / FORTRAN format of field  4                     TTYPE4  = 'SUBARRAY        '   / Type (heading) of field  4                     TUNIT4  = '        '           / Physical units of field  4                     TFORM5  = '1J      '           / FORTRAN format of field  5                     TTYPE5  = 'FREQ ID         '   / Type (heading) of field  5                     TUNIT5  = '        '           / Physical units of field  5                     TFORM6  = '1J      '           / FORTRAN format of field  6                     TTYPE6  = 'ANT FLAG        '   / Type (heading) of field  6                     TUNIT6  = '        '           / Physical units of field  6                     TFORM7  = '1J      '           / FORTRAN format of field  7                     TTYPE7  = 'STATUS 1        '   / Type (heading) of field  7                     TUNIT7  = '        '           / Physical units of field  7                     NO_IF   =            1                                                          NO_POL  =            1                                                          ANNAME  = 'VLA     '                                                            OBSCODE = 'AK462   '                                                            RDATE   = '1998-02-24'                                                          REVISION=            2                                                          END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             >Ú      
+            >Ú                  >Ú                  >Ú               D   >Ú                  >Ú                  >Ú                  >Ú                  >øj               @   >Á                   >Á               @   >5               @   >Sp                   >Sp                  >Sp               @   >qÇ               @   >               @   >ÌÍ               @   >ë$               @   >	{               @   >'Ò               @   >d               @   >‚Ø               @   >¿‡                  >¿‡               @   >ÝÞ                   >ÝÞ               @   >Œ               @   >8ä               @   >u’               @   >“é               @   >l      	            >l                  >l                  >l               D   >l                  >l                  >l                  >l      	            >l                  >l                  >l               D   >l                  >l                  >l                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      XTENSION= 'BINTABLE'           / Extension type                                 BITPIX  =                    8 / Binary data                                    NAXIS   =                    2 / Table is a matrix                              NAXIS1  =                   32 / Width of table in bytes                        NAXIS2  =                  190 / Number of entries in table                     PCOUNT  =                    0 / Random parameter count                         GCOUNT  =                    1 / Group count                                    TFIELDS =                    8 / Number of fields in each row                   EXTNAME = 'AIPS UV '           / AIPS table file                                EXTVER  =                    1 / Version number of table                        TFORM1  = '1E      '           / FORTRAN format of field  1                     TTYPE1  = 'UU---SIN        '   / Type (heading) of field  1                     TUNIT1  = 'SECONDS '           / physical units of field  1                     TSCAL1  =  1.3550135501355D-08 / scale to physical units in field  1            TFORM2  = '1E      '           / FORTRAN format of field  2                     TTYPE2  = 'VV---SIN        '   / Type (heading) of field  2                     TUNIT2  = 'SECONDS '           / physical units of field  2                     TSCAL2  =  1.3550135501355D-08 / scale to physical units in field  2            TFORM3  = '1E      '           / FORTRAN format of field  3                     TTYPE3  = 'WW---SIN        '   / Type (heading) of field  3                     TUNIT3  = 'SECONDS '           / physical units of field  3                     TSCAL3  =  1.3550135501355D-08 / scale to physical units in field  3            TFORM4  = '1E      '           / FORTRAN format of field  4                     TTYPE4  = 'BASELINE        '   / Type (heading) of field  4                     TUNIT4  = '        '           / physical units of field  4                     TFORM5  = '1E      '           / FORTRAN format of field  5                     TTYPE5  = 'DATE            '   / Type (heading) of field  5                     TUNIT5  = 'DAYS    '           / physical units of field  5                     TZERO5  =  2.4508685000000D+06 / offset to physical units in field  5           TFORM6  = '1E      '           / FORTRAN format of field  6                     TTYPE6  = 'WEIGHT          '   / Type (heading) of field  6                     TUNIT6  = '        '           / physical units of field  6                     TFORM7  = '1E      '           / FORTRAN format of field  7                     TTYPE7  = 'SCALE           '   / Type (heading) of field  7                     TUNIT7  = '        '           / physical units of field  7                     TFORM8  = '2I      '           / FORTRAN format of field  8                     TTYPE8  = 'VISIBILITIES    '   / Type (heading) of field  8                     TUNIT8  = 'JY      '           / physical units of field  8                     TDIM8   = '(2,1,1,1,1,1)'                                                                                                                                       1CTYP8  = 'COMPLEX '           / 1=real,2=imag,3=weight                         1CRVL8  =    1.00000000000E+00 /                                                1CDLT8  =      1.000000000E+00 /                                                1CRPX8  =      1.000000000E+00 /                                                1CROT8  =      0.000000000E+00 /                                                2CTYP8  = 'STOKES  '           / -1=RR, -2=LL, -3=RL, -4=LR                     2CRVL8  =   -2.00000000000E+00 /                                                2CDLT8  =     -1.000000000E+00 /                                                2CRPX8  =      1.000000000E+00 /                                                2CROT8  =      0.000000000E+00 /                                                3CTYP8  = 'FREQ    '           / Frequency in Hz.                               3CRVL8  =    7.38000000000E+07 /                                                3CDLT8  =      1.165771500E+06 /                                                3CRPX8  =      1.000000000E+00 /                                                3CROT8  =      0.000000000E+00 /                                                4CTYP8  = 'IF      '           / Freq. group no. in CH table                    4CRVL8  =    1.00000000000E+00 /                                                4CDLT8  =      1.000000000E+00 /                                                4CRPX8  =      1.000000000E+00 /                                                4CROT8  =      0.000000000E+00 /                                                5CTYP8  = 'RA      '           / Right Ascension in deg.                        5CRVL8  =    1.92941554167E+02 /                                                5CDLT8  =      1.000000000E+00 /                                                5CRPX8  =      1.000000000E+00 /                                                5CROT8  =      0.000000000E+00 /                                                6CTYP8  = 'DEC     '           / Declination in deg.                            6CRVL8  =    2.78966361111E+01 /                                                6CDLT8  =      1.000000000E+00 /                                                6CRPX8  =      1.000000000E+00 /                                                6CROT8  =      0.000000000E+00 /                                                OBJECT  = '1251+278'           / Source name                                    TELESCOP= 'VLA     '           /                                                INSTRUME= 'VLA     '           /                                                OBSERVER= 'AK462   '           /                                                DATE-OBS= '1998-02-24'         / Obs start date YYYY-MM-DD                      DATE-MAP= '2011-02-08'         / Last processing date YYYY-MM-DD                BSCALE  =    1.00000000000E+00 / REAL = TAPE * BSCALE + BZERO                   BZERO   =    0.00000000000E+00 /                                                BUNIT   = 'UNCALIB '           / Units of flux                                  EQUINOX =      1.950000000E+03 / Epoch of RA DEC                                COMMENT / IEEE not-a-number used for blanked f.p. pixels                        VELREF  =                    3 / >256 RADIO, 1 LSR 2 HEL 3 OBS                  ALTRPIX =      1.000000000E+00 / Altenate FREQ/VEL ref pixel                    OBSRA   =    1.92941554167E+02 / Antenna pointing RA                            OBSDEC  =    2.78966361111E+01 / Antenna pointing DEC                           HISTORY AIPS   SORT ORDER = 'TB'                                                              / Where T means TIME (IAT)                                                      / Where B means BASELINE NUM                                      HISTORY AIPS   IMNAME='1251+278    ' IMCLASS='SPLIT ' IMSEQ=   1     /          HISTORY AIPS   USERNO= 1111            /                                        HISTORY AIPS   IPIECE= 1 NPIECE= 1     / piece number                           HISTORY AIPS   FIRSTVIS=           1     / first vis #                          HISTORY AIPS   LASTVIS =         190     / last vis #                           END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             C5oàAC—‡D'¯E!  >lB¬7þÆ_€™”D ãNB/…ÜEMÅDƒ@ >lAÍ0×7R¹gø¨’C¨cA¿§’D›ðÃEA  >lA½õó7ì°øL×CéÂ$BvDØ_²E¸Ð >lAÇHª7Ô+k!ì€DýBë EäMC  >lA„W*6Ž>)å€ÃJ~:Áp‘•Ä<oöEQ  >lA¸øÐ7 ¤ø¤lÝÄâڏE€=¯EÐ >lB‡«7cîj€ÏôCÝœ/ÄñËE:@E€Ð >lB	ù07I¦U¹€D&Ãlû)E*ÏDÃ@ >lA«Oo7Vn“€h‚Ä
Å;²E wEa  >lAÒªÒ6\·ø^ÄJÅfŽE³£‡E°Ð >lAÕ—n6¼4¤€ªìÚ˜ÍŹøEƒ›E¨Ð >lAô†7'Š€WîDø‡DáAEL>3DF€ >lAÐ_67r8½q€D7çˆBý¿„E¼ºE  >lAõßú6b*I€Z‰DZCœ E"áÌD€ >lA.ÛY7¦«ÂøIiD¦	±Df?(E3Ì£EÀÐ >lAŸkn6ƒ@s¦€E0céE6€õEkVEq  >lB)95b´^€ÅNqMÅ^½mÅ}8¦EÐØ >lB5d6	ͤøSTEâüE»¶EZýåD£@ >lBàŸ6#ð€FŽCç¬Aý?óDÕ³D@ >lCý7_N”PøÃVQÁ;·œÄÏØE À >lBðÚ‡7¾x#€©IÏ
+4Á§U(Ä„ÖÛE!p >lBü¬«6á6IáF€CÃCAØ
+;D´?ÃC…  >lB§ËÑ7­}0€ sC¿÷
AÚŽD±ÀÒE Ð >lBê‡:6'Ð/Ù_€CƒÓ'Däa¾ÅV¶óE!  >lC7 at X6Xʉ€à¡Ã‚ä?D )Å{ŸE!  >lC.ð-7Veú€C½”Ãy4¢E
+ªDÁ@ >lBÙ4Ü6ã–D*ÃøD:kE<u©Å‹”ÑE à >lCÉ6qrÓ6€DwnwEf×%ÅžÁRE!` >lCh^6zzU†øCõP½E}ÅuBÊE!P >lC*Ä6ÉÊðøß±Dáj‹Dß•E"yÇDB€ >lCD6è:¿Â»øD
+‹BåL“DçðœE   >lCß»6ž$[€ÈÏD-1C•çdDò:ÀD€ >lB]´6wãCi¬€ď[µÄc0ÊÅ
+7E!€ >lBÊ!T6•477U€Å%ëÅ5½^ÅA‘œE ð >lCVð6…ê€`ÅCOÅ]ùÖÅSt:E!° >lC?¸6dÂ瀻@E	‹þEøE19yD¡@ >lCAÕÑ5áˆ
+'€C™cƒAŸd&DŒªÇD€ >lBœ¸}6Ñy©þ¡øC0ïA+Õ˜D w°D‚à >lB¤i‘7ï7~ôø.uÀ”ÖàÃK½C‚  >lBZ]µ8%É¿õ€DS‚ÜBkªAECiÃD  >lB˜šÔ7;o<ñ‘øD5péDèV¾ÄØ[4D‚@ >lBîz£6}ún€8CHTÚDê)ÄÉD‚  >lBã©7	VRøÍB¥ê7CŒnPô
+„D€À >lBUp5¦U€*FD–ù3E>p)Å, HDÀ >lB­ÍË6G·øâÞDµzçEhÑ¥ÅRùJD‚À >lB°7h6ãÈáß;øDn/´ExÅ
+¹qD‚  >lBÉîJ6™«øÌ­D§¦áDÛ D_Á¶DA  >lB«é6ÆÖ%Â(ø¸!ÐÂ¥ü–ÃïKD  >lBÊÙÊ6ìu€x¦Cf§	C†eCi at iD  >lBB{6ŠZí€Ä+0Ä[FÊÃûöíDƒ  >lBƒ†7	—Wø¦0Å+Å3ÂÞÄ®…Dà >lCœù4í`˜‚ŠøÅ&8zÅ[ÿVÄÑÕÁDƒ` >lBù¼6“øÄÙTQÅýŸÄ`?D€  >lBü@¯6nT—TøþÁò´Ãñ»¼EAp >lB˜5…8AÑ$øӍCk/ËAt\ÛDW¯¯C†  >lBJ(y7‘^ÞøR€DÑBø.Dú(¾E@Ð >lBG%6²æø¶£CÑ~PDåÙ-Å2‚ýEA  >lBÜÇ;69ÿ€i‡ÂÔäWDïÄ؏REA  >lBÒÃ@6ôñÒø>PC_ÑêÂxD¹­hDÁ€ >lB‚×ê6Qvúø¯ÓDa@¥E=1aÅrõ¬E@à >lB çL5Ë#{
+Ù€D"Eg’ÝÅŒ§WEA` >lB£#6b at g€»‘D!}óE9GÅQÔEAP >lBºñX5ëÆ[€bîDÍÿÁDÞ¢Dü‹¢DC  >lBŸ&~6T!];€CÇk÷BÍÕ DŸˆ°E À >lB»Ë^7‚€¶D[„C	§D©ÒÔD  >lB\6¹–þ€\ÄwáÖÄ`AëÄ˨‚EA€ >lBs…î8
{Ç€FKÅW†Å5¦Å]¦E@ð >lC@%6±Ù‡«€Å9dêÅ]>Å/@DEA° >lBæúï55NYƒO€Dÿ­1E<gE
ƒD¡€ >lB量6•$ 8øBÐãh@ÂÔOC½£¢C‹€ >lBTo8L¢g	ã€Ä'€¡Â@´ÛÅK×EQp >lB”616äffø²fÄ	n®ÄæÿEK†E¸ >lBç$6‚t¸ø¢>ÁÂ_[Ä
+:ÒDœ cE€¸ >lBÝS7VÆ
€r Bº'¦Ã‡£Dz|òDÂà >lB‰CÝ7Ší5”€Ä€øÅ=ÄSET¾4Eap >lB¨Ìí6føS øÄŸyÉÅh%ÐE{6E°¸ >lB«$Ã5wv`€ÄB-xÅÌ:E2×]E¨¸ >lBÄ#6MÇ€jpD½§þDÜ÷½DÀ³DEÀ >lB¦ö7
À{ù€C†ëB»wIDF3‚Ep >lBÅÜ7š„!-°€CËWüC‹rDZÇÊDÀ >lBX7v_&€"úÄW2PÄ]ö!ď9“E¸À >lBy7µÍøsE+¤E4n³DþL]Eqp >lC˜6‚7ø۝Å19Å\«+ÅÌE¸Ø >lBòQ4Üÿø–SDïUnE©uDÝœD¢à >lBôý®6…
+ÿ€ÚDABYeE3 KC†€ >lBDÙT7KTþx€D#‹DçÁçÄù.#C‰  >lB™Ïi7Ëa5DøC ½ŸDÀ{ÄYnõCˆ  >lB’Õ'6P»J€–A5ÞCŠõÄ«!Cƒ  >lB6Oc7ðøEéDŽLE>%½Å=	ÀC‡  >lB`1¶6±ôV€»ÐD¬‡ÿEh‡:ÅcbÁC‹  >lBcNc6%€ö€*CD\IåE-¤Å"èCŠ€ >lB‚<é6Èïhø
Ä°™ÈÄÜ4éĐ³ÊC€ >lB]À_6¤s~øºàÃ#¨#¯JÃÎÃcC„  >lB‚ÔÍ7Ô@øü×"ÈfÀÃ÷ëòC  >lAº˜7ìtÿøÄ=ãÄ\pxÄ?¡UCŒ  >lB)§í6‘Ê€uÍÅ¤‰Å4
IÄÎãuC‡€ >lB´86KS¾üøÅ*±íÅ\IÁÄò¨°C€ >lB êê6ØæZçá€ÄâG8ÅH
+Ä®3.C‚€ >lB¢±”6BQ,â€Âð—DàùlÅ—Ë®EQ  >lBÖúç6j¬Ó\ëøÄ!m¦Cü_	Åi\EQ  >lBÍ:A7$_7žiøD>Å•Ã]òEYëDÁ  >lB~Ðw6Q@®øßHC´ßE:Á€Å¸EPà >lBœ­„6’dJbŽ€DrñEe"üÅË1†EQ` >lBžÚE6¬o£ö€BÕf¿EÉfŧšEQP >lB¶6¾$®øëFE´'DâýdE{Z0DC@ >lBšø66 0ø¢
Dj‡C
èÛELØ·E Ð >lB¶ÜË6•ºÉø4D†–OC£ˆ­EQýÉD@ >lBw7hó@3øøÄ¿YxÄjnÅbè EQ€ >lBm ¯6Ã7mY]€Å=ÌÅ7q‡Å9EPð >lBû¶W6Îmh€"3Å[1Å_­ÿÅ–*REQ° >lBàê6Wa;øneE!ŠßE¬HE…ñD¡  >lBãe€6›3–¡øD[³D¡á©ÄŒv¨E€ >lC [`6V$*îøD ³¢DÅ;*Ä«X“DÂ@ >lBÇ$6U+{(³€ÃñúÄ”‰”D€å]Ea  >lBôØ6xà€žD5„äDéLÄÍ—`E° >lBø>6ÒöøTiCbû+D
2ÃÃô^¶E¨ >lC;Ö6Üõ.1tøE/«EaûhÄPô²DD€ >lBò-!6®Ò€£DLu#Dò¶‡ÄÅ}JE  >lCá¸5ªàjøDo¬EíËÄ»3'D€ >lBK9X5Ȫ³€ЬİPÅ*ýD™]yEÀ >lB¹HN6Œåõ€[UE5‡PE“÷é*ºEq  >lCD­¥5ô	å5\€ÅS”´Å¨ZBP®XEØ >lC/½@5£ŸRøEcE”ÄõéD¢@ >lC1­Ë5¹H‘šs€Bê¿}CfÃwRD  >lB¾å7/ýCFøÄ{Ý0Å5ŸE®Ea  >lB鼚5a»ø‹pDœpKEE—Å-E€° >lBìû063ëøûÄD<~Dè{ÄÉŽVE€¨ >lCÈ6 Ÿ)·øDÀ±|E
+“Cñ>DD  >lBç0¥6û¥½z€C’2áD!©»ÃäˆE  >lCfa6‡4€¯ïC×}ñDOóÛúñùD  >lBB:56a.€
+êÄ]EKÄ´yBÎmE€À >lB°à6œ]‹øÙ<E°cEVýhDDWôEq  >lC;Á‹6E¿˜€Å2½ÇÅ9àÄ…ñ6E€Ø >lC'ÄR5ű7€øDò^ìE28)D÷hD¢  >lC)žW62,O¯€DŒšE,â_ÅøDÁÀ >lB‘7«Óø)”D«CEWCÛÅ<wùDÂÀ >lB“¿5±à:€
+•DYrmEêEÄèp at D  >lB¨–¯6 ²^/€D²„Dþ»¦D¼tDA€ >lB†_5ȝK°øÃ/õívCQ%¾DÁ  >lB©[M6h*©ø CœÎD	@ÚÂý©?D€ >lAðáC7 ›#ø°¾Ä?í[Đ¾ùÃØÑDà  >lB[*6é<&™'øÅ
ZgÅEP¨Ä
äDÁà >lBé6¡Fº¯ˆøÅ+gËÅm Ä¤Ó DÃ` >lBÐMm6¼hBÔÜøDã²ôE ‹iD@»<D À >lBÒ™ú5ŒòøÎCt
›D)…ñÄdEa` >lB´ël6Ì×€ý¡Ã
+ÉÄàfD›_EaP >lBÏQÿ6¬ÌøU EP
+E– Äé_¶DC€ >lB°™6†ôTæKøD¢{PEC Å#1TE à >lBÐCÉ6ÌÚ3€D³ÎEO2–ÅBD€ >lB%7ï-øĘÄì‘=ÅuAÛE
!kEa€ >lB‡»6í/F€ÅS§¯Å¹ƒD«0E`ð >lCVä5¶ÿ`‡¯€ÅqµÅÍ7¿D‡jÐEa° >lC ;6 d>,€E8&ÂE¦¶äÄËàRD¡À >lC~60%%
+€CùŒ2D¢³,Đ²E¨° >lBÒ2¶6ˆË;–€E.äE«P×ÅÜDE€ >lB²òÉ6«÷¦íYøDÀýEnŠÅIŠUE` >lBÓ'Û6
¶0`øDÒOÈEy”ÅDeCD€ >lB*u7 €_ÀʼnxŏѬE3zlE°À >lBˆè”5¨á¢Û€Ebè‰EÎJBÄ÷âEq` >lCT at 5Œ™‹€ï6Å€zöÅâh~DÔÓE°Ø >lCÛ\64ø‹xøEGgœE»ç¢ÅI*D¢À >lCJD5Ko毙øE_]E‚¤Ä¥’DE@ >lB͹6Ç»IêøD‚™÷E§ôÅJ|EP >lBñ÷õ6°»-­øD“ì»E(:|ÄøJÔD@ >lB,,6¶bá€Ä̯äÅNIÂDÖu&E¨À >lBœã
+6Q£7ø…/EC·E¥wÄNĸEqP >lC&‰H6gPÍøBTÅaÄgŹ»³D:@E¨Ø >lCÎe6ŽgøE(6E“:×Ĉ¢D¢  >lCr×5Ä­!ø"EDœ$ÄDÑ@HD:ãDB  >lBÍþá6·áFýõ€ÄŠÑÿĺ8Ä%qœD À >lB7L	€5D$­D[ùYCÃŒDF  >lB…6qå‘ 
+€ÄQ^”Ä‹åªÃø¾©DCÀ >lC
Ç6¹«9ÓøĤÊÄÜ^šÄCéÌDFÀ >lBý]ö6$6~€ª"ÃƵÀĶYÃkû!DA@ >lC ë6$R¦€ˆC
+–!C9(B¤¢<D  >lB,ÜÜ7„ººøtÄ+ÚÄF‡7ðGE€ >lBš7ojãøÅjÅ.’ùÄ›2œE ð >lC'K5Ïø~¶Å wkÅVÏqľ÷ØE° >lC{ñ6–IæYIøDÍÒ4E	ͺDu«D¡  >lC"M5ᛁƒ/€Ãã¤Ä=ÇV¸D  >lAà)7H"ŸŽøÄóJÅ# qĐèxDÀ >lBmò6ö\€	
ÅÎ	ÅK<éÄ´­´DÀ >lBTd6`„¦€$RļoÄüveÄ`pdD@ >lBVö 5—EÄ€©ÙDº¾!DùâWD^%”Eq€ >lBØð¾6ˆF¬½LøÄöØéÅ%-£Ä’ØEÀØ >lBÁØ6ßUTTjøDƒ¼FD°WÙDÅD£  >lBÃûÏ6–|Í;€Ãðk"Ä ñàÏïEq° >lCMÄB6œ¢Á2€ÃÜhÄûÂÁD¡à >lCP	¤7iùøYÄf9EÄšnÄëD£` >lC9ã¦6 ~£¯4ø                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
\ No newline at end of file
diff --git a/astropy/io/fits/tests/test_core.py b/astropy/io/fits/tests/test_core.py
index 3aee7fa..b186513 100644
--- a/astropy/io/fits/tests/test_core.py
+++ b/astropy/io/fits/tests/test_core.py
@@ -544,6 +544,19 @@ class TestStreamingFunctions(FitsTestCase):
             shdu = self._make_streaming_hdu(f)
             shdu.write(arr)
 
+    def test_fix_invalid_extname(self, capsys):
+        phdu = fits.PrimaryHDU()
+        ihdu = fits.ImageHDU()
+        ihdu.header['EXTNAME'] = 12345678
+        hdul = fits.HDUList([phdu, ihdu])
+
+        pytest.raises(fits.VerifyError, hdul.writeto, self.temp('temp.fits'),
+                      output_verify='exception')
+        hdul.writeto(self.temp('temp.fits'), output_verify='fix')
+        with fits.open(self.temp('temp.fits')):
+            assert hdul[1].name == '12345678'
+            assert hdul[1].header['EXTNAME'] == '12345678'
+
     def _make_streaming_hdu(self, fileobj):
         hd = fits.Header()
         hd['SIMPLE'] = (True, 'conforms to FITS standard')
diff --git a/astropy/io/fits/tests/test_diff.py b/astropy/io/fits/tests/test_diff.py
index 325f8e4..769f960 100644
--- a/astropy/io/fits/tests/test_diff.py
+++ b/astropy/io/fits/tests/test_diff.py
@@ -165,11 +165,35 @@ class TestDiff(FitsTestCase):
         assert not diff.identical
         assert diff.diff_keyword_values == {'C': [(3, 5)]}
 
+        report = diff.report()
+        assert 'Keyword B        has different values' not in report
+        assert 'Keyword C        has different values' in report
+
         # Test case-insensitivity
         diff = HeaderDiff(ha, hb, ignore_keywords=['b'])
         assert not diff.identical
         assert diff.diff_keyword_values == {'C': [(3, 5)]}
 
+    def test_ignore_keyword_comments(self):
+        ha = Header([('A', 1, 'A'), ('B', 2, 'B'), ('C', 3, 'C')])
+        hb = ha.copy()
+        hb.comments['B'] = 'D'
+        hb.comments['C'] = 'E'
+        diff = HeaderDiff(ha, hb, ignore_comments=['*'])
+        assert diff.identical
+        diff = HeaderDiff(ha, hb, ignore_comments=['B'])
+        assert not diff.identical
+        assert diff.diff_keyword_comments == {'C': [('C', 'E')]}
+
+        report = diff.report()
+        assert 'Keyword B        has different comments' not in report
+        assert 'Keyword C        has different comments' in report
+
+        # Test case-insensitivity
+        diff = HeaderDiff(ha, hb, ignore_comments=['b'])
+        assert not diff.identical
+        assert diff.diff_keyword_comments == {'C': [('C', 'E')]}
+
     def test_trivial_identical_images(self):
         ia = np.arange(100).reshape((10, 10))
         ib = np.arange(100).reshape((10, 10))
@@ -184,6 +208,24 @@ class TestDiff(FitsTestCase):
         assert diff.identical
         assert diff.diff_total == 0
 
+    def test_identical_comp_image_hdus(self):
+        """Regression test for #189.
+
+        For this test we mostly just care that comparing to compressed images
+        does not crash, and returns the correct results.  Two compressed images
+        will be considered identical if the decompressed data is the same.
+        Obviously we test whether or not the same compression was used by
+        looking for (or ignoring) header differences.
+        """
+
+        data = np.arange(100.0).reshape((10, 10))
+        hdu = fits.CompImageHDU(data=data)
+        hdu.writeto(self.temp('test.fits'))
+        hdula = fits.open(self.temp('test.fits'))
+        hdulb = fits.open(self.temp('test.fits'))
+        diff = FITSDiff(hdula, hdulb)
+        assert diff.identical
+
     def test_different_dimensions(self):
         ia = np.arange(100).reshape((10, 10))
         ib = np.arange(100) - 1
@@ -239,6 +281,23 @@ class TestDiff(FitsTestCase):
         assert diff.diff_ratio == 0
         assert diff.diff_total == 0
 
+    def test_diff_empty_tables(self):
+        """
+        Regression test for #178.
+
+        Ensure that diffing tables containing empty data doesn't crash.
+        """
+
+        c1 = Column('D', format='J')
+        c2 = Column('E', format='J')
+        thdu = new_table([c1, c2], nrows=0)
+
+        hdula = fits.HDUList([thdu])
+        hdulb = fits.HDUList([thdu])
+
+        diff = FITSDiff(hdula, hdulb)
+        assert diff.identical
+
     def test_ignore_table_fields(self):
         c1 = Column('A', format='L', array=[True, False])
         c2 = Column('B', format='X', array=[[0], [1]])
diff --git a/astropy/io/fits/tests/test_groups.py b/astropy/io/fits/tests/test_groups.py
index 80c168a..4397321 100644
--- a/astropy/io/fits/tests/test_groups.py
+++ b/astropy/io/fits/tests/test_groups.py
@@ -1,5 +1,9 @@
 from __future__ import with_statement
 
+import os
+import time
+import shutil
+
 import numpy as np
 from numpy import char as chararray
 
@@ -8,6 +12,7 @@ from .test_table import comparerecords
 from ....io import fits
 from ....tests.helper import pytest
 
+
 class TestGroupsFunctions(FitsTestCase):
     def test_open(self):
         with fits.open(self.data('random_groups.fits')) as hdul:
@@ -33,6 +38,30 @@ class TestGroupsFunctions(FitsTestCase):
             assert ghdu.data[0].data.shape == naxes[::-1]
             assert ghdu.data[0].parnames == parameters
 
+    def test_open_groups_in_update_mode(self):
+        """
+        Test that opening a file containing a groups HDU in update mode and
+        then immediately closing it does not result in any unnecessary file
+        modifications.
+
+        Similar to
+        test_image.TestImageFunctions.test_open_scaled_in_update_mode().
+        """
+
+        # Copy the original file before making any possible changes to it
+        shutil.copy(self.data('random_groups.fits'),
+                    self.temp('random_groups.fits'))
+        mtime = os.stat(self.temp('random_groups.fits')).st_mtime
+
+        time.sleep(1)
+
+        fits.open(self.temp('random_groups.fits'), mode='update',
+                  memmap=False).close()
+
+        # Ensure that no changes were made to the file merely by immediately
+        # opening and closing it.
+        assert mtime == os.stat(self.temp('random_groups.fits')).st_mtime
+
     def test_parnames_round_trip(self):
         """
         Regression test for #130.  Ensures that opening a random groups file in
@@ -40,13 +69,19 @@ class TestGroupsFunctions(FitsTestCase):
         the parameter names.
         """
 
+        # Because this test tries to update the random_groups.fits file, let's
+        # make a copy of it first (so that the file doesn't actually get
+        # modified in the off chance that the test fails
+        shutil.copy(self.data('random_groups.fits'),
+                    self.temp('random_groups.fits'))
+
         parameters = ['UU', 'VV', 'WW', 'BASELINE', 'DATE']
-        with fits.open(self.data('random_groups.fits'), mode='update') as h:
+        with fits.open(self.temp('random_groups.fits'), mode='update') as h:
             assert h[0].parnames == parameters
             h.flush()
         # Open again just in read-only mode to ensure the parnames didn't
         # change
-        with fits.open(self.data('random_groups.fits')) as h:
+        with fits.open(self.temp('random_groups.fits')) as h:
             assert h[0].parnames == parameters
             h.writeto(self.temp('test.fits'))
 
diff --git a/astropy/io/fits/tests/test_hdulist.py b/astropy/io/fits/tests/test_hdulist.py
index ddedcc6..fe1ec6f 100644
--- a/astropy/io/fits/tests/test_hdulist.py
+++ b/astropy/io/fits/tests/test_hdulist.py
@@ -5,6 +5,7 @@ import io
 import os
 import shutil
 import warnings
+import sys
 
 import numpy as np
 
@@ -621,6 +622,10 @@ class TestHDUListFunctions(FitsTestCase):
                         assert (hdul[idx].data == hdul2[idx].data).all()
 
         for filename in glob.glob(os.path.join(self.data_dir, '*.fits')):
+            if sys.platform == 'win32' and filename == 'zerowidth.fits':
+                # Running this test on this file causes a crash in some
+                # versions of Numpy on Windows.  See PyFITS ticket #174
+                continue
             test_fromstring(filename)
 
         # Test that creating an HDUList from something silly raises a TypeError
diff --git a/astropy/io/fits/tests/test_header.py b/astropy/io/fits/tests/test_header.py
index 33e90ce..8a33bff 100644
--- a/astropy/io/fits/tests/test_header.py
+++ b/astropy/io/fits/tests/test_header.py
@@ -188,6 +188,27 @@ class TestOldApiHeaderFunctions(FitsTestCase):
         assert h.ascard['FOO'].cardimage == fooimg
         assert h.ascard['BAR'].cardimage == barimg
 
+    def test_cardlist_list_methods(self):
+        """Regression test for #190."""
+
+        header = fits.Header()
+        header.update('A', 'B', 'C')
+        header.update('D', 'E', 'F')
+        # The old header.update method won't let you append a duplicate keyword
+        header.append(('D', 'G', 'H'))
+
+        assert header.ascardlist().index(header.cards['A']) == 0
+        assert header.ascardlist().index(header.cards['D']) == 1
+        assert header.ascardlist().index(header.cards[('D', 1)]) == 2
+
+        # Since the original CardList class really only works on card objects
+        # the count method is mostly useless since cards didn't used to compare
+        # equal sensibly
+        assert header.ascardlist().count(header.cards['A']) == 1
+        assert header.ascardlist().count(header.cards['D']) == 1
+        assert header.ascardlist().count(header.cards[('D', 1)]) == 1
+        assert header.ascardlist().count(fits.Card('A', 'B', 'C')) == 0
+
 
 class TestHeaderFunctions(FitsTestCase):
     """Test Header and Card objects."""
@@ -380,17 +401,17 @@ class TestHeaderFunctions(FitsTestCase):
                          "column 8)")
             err_text2 = ("Card 'ABC' is not FITS standard (invalid value "
                          "string: a6")
-            assert len(w) == 2
-            assert err_text1 in str(w[0].message)
-            assert err_text2 in str(w[1].message)
+            assert len(w) == 4
+            assert err_text1 in str(w[1].message)
+            assert err_text2 in str(w[2].message)
 
     def test_fix_invalid_equal_sign(self):
         c = fits.Card.fromstring('abc= a6')
         with warnings.catch_warnings(record=True) as w:
             c.verify('fix')
             fix_text = "Fixed 'ABC' card to meet the FITS standard."
-            assert len(w) == 2
-            assert fix_text in str(w[0].message)
+            assert len(w) == 4
+            assert fix_text in str(w[1].message)
         assert str(c) == _pad("ABC     = 'a6      '")
 
     def test_long_string_value(self):
@@ -404,6 +425,49 @@ class TestHeaderFunctions(FitsTestCase):
             "CONTINUE  '&' / comment long comment long comment long comment long comment     "
             "CONTINUE  '&' / long comment                                                    ")
 
+    def test_long_string_repr(self):
+        """Regression test for #193
+
+        Ensure that the __repr__() for cards represented with CONTINUE cards is
+        split across multiple lines (broken at each *physical* card).
+        """
+
+        header = fits.Header()
+        header['TEST1'] = ('Regular value', 'Regular comment')
+        header['TEST2'] = ('long string value ' * 10, 'long comment ' * 10)
+        header['TEST3'] = ('Regular value', 'Regular comment')
+
+        assert (repr(header).splitlines() ==
+            [str(fits.Card('TEST1', 'Regular value', 'Regular comment')),
+             "TEST2   = 'long string value long string value long string value long string &' ",
+             "CONTINUE  'value long string value long string value long string value long &'  ",
+             "CONTINUE  'string value long string value long string value &'                  ",
+             "CONTINUE  '&' / long comment long comment long comment long comment long        ",
+             "CONTINUE  '&' / comment long comment long comment long comment long comment     ",
+             "CONTINUE  '&' / long comment                                                    ",
+             str(fits.Card('TEST3', 'Regular value', 'Regular comment'))])
+
+    def test_blank_keyword_long_value(self):
+        """Regression test for #194
+
+        Test that a blank keyword ('') can be assigned a too-long value that is
+        continued across multiple cards with blank keywords, just like COMMENT
+        and HISTORY cards.
+        """
+
+        value = 'long string value ' * 10
+        header = fits.Header()
+        header[''] = value
+
+        assert len(header) == 3
+        assert ' '.join(header['']) == value.rstrip()
+
+        # Ensure that this works like other commentary keywords
+        header['COMMENT'] = value
+        header['HISTORY'] = value
+        assert header['COMMENT'] == header['HISTORY']
+        assert header['COMMENT'] == header['']
+
     def test_long_string_from_file(self):
         c = fits.Card('abc', 'long string value ' * 10, 'long comment ' * 10)
         hdu = fits.PrimaryHDU()
@@ -1410,12 +1474,12 @@ class TestHeaderFunctions(FitsTestCase):
         hdul = fits.open(self.temp('test.fits'))
         with warnings.catch_warnings(record=True) as w:
             hdul.writeto(self.temp('temp.fits'), output_verify='warn')
-            assert len(w) == 3
+            assert len(w) == 5
             # The first two warnings are just the headers to the actual warning
             # message (HDU 0, Card 4).  I'm still not sure things like that
             # should be output as separate warning messages, but that's
             # something to think about...
-            msg = str(w[2].message)
+            msg = str(w[3].message)
             assert '(invalid value string: 5.0022221e-07)' in msg
 
     def test_leading_zeros(self):
@@ -1717,6 +1781,16 @@ class TestHeaderFunctions(FitsTestCase):
                 pytest.raises(ValueError, header.set, 'Just som', 'foo')
                 pytest.raises(ValueError, header.set, 'AAAAAAAA', 'foo')
 
+    def test_fix_hierarch_with_invalid_value(self, capsys):
+        """
+        Regression test for #172.  Ensures that when fixing a hierarch card it
+        remains a hierarch card.
+        """
+
+        c = fits.Card.fromstring('HIERARCH ESO DET CHIP PXSPACE = 5e6')
+        c.verify('fix')
+        assert str(c) == _pad('HIERARCH ESO DET CHIP PXSPACE = 5E6')
+
 
 class TestRecordValuedKeywordCards(FitsTestCase):
     """
@@ -1847,11 +1921,15 @@ class TestRecordValuedKeywordCards(FitsTestCase):
 
     def test_get_rvkc_by_keyword(self):
         """
-        Returning a RVKC just via the keyword name should return the floating
-        point value of the first card with that keyword.
+        Returning a RVKC just via the keyword name should return the full value
+        string of the first card with that keyword.
+
+        This test was changed to reflect the requirement in ticket
+        #184--previously it required _test_header['DP1'] to return the parsed
+        float value.
         """
 
-        assert self._test_header['DP1'] == 2.0
+        assert self._test_header['DP1'] == 'NAXIS: 2'
 
     def test_get_rvkc_by_keyword_and_field_specifier(self):
         """
@@ -1999,3 +2077,66 @@ class TestRecordValuedKeywordCards(FitsTestCase):
         cl = self._test_header['DP1.AXIS.*']
         assert cl.cards[0].value == 1.0
         assert isinstance(cl.cards[0].value, float)
+
+    def test_overly_permissive_parsing(self):
+        """
+        Regression test for #183.
+
+        Ensures that cards with standard commentary keywords are never treated
+        as RVKCs.  Also ensures that cards not stricly matching the RVKC
+        pattern are not treated as such.
+        """
+
+        h = fits.Header()
+        h['HISTORY'] = 'AXIS.1: 2'
+        h['HISTORY'] = 'AXIS.2: 2'
+        assert 'HISTORY.AXIS' not in h
+        assert 'HISTORY.AXIS.1' not in h
+        assert 'HISTORY.AXIS.2' not in h
+        assert h['HISTORY'] == ['AXIS.1: 2', 'AXIS.2: 2']
+
+        # This is an example straight out of the ticket where everything after
+        # the '2012' in the date value was being ignored, allowing the value to
+        # successfully be parsed as a "float"
+        h = fits.Header()
+        h['HISTORY'] = 'Date: 2012-09-19T13:58:53.756061'
+        assert 'HISTORY.Date' not in h
+        assert (str(h.cards[0]) ==
+                _pad('HISTORY Date: 2012-09-19T13:58:53.756061'))
+
+        c = fits.Card.fromstring(
+            "        'Date: 2012-09-19T13:58:53.756061'")
+        assert c.keyword == ''
+        assert c.value == "'Date: 2012-09-19T13:58:53.756061'"
+        assert c.field_specifier is None
+
+        h = fits.Header()
+        h['FOO'] = 'Date: 2012-09-19T13:58:53.756061'
+        assert 'FOO.Date' not in h
+        assert (str(h.cards[0]) ==
+                _pad("FOO     = 'Date: 2012-09-19T13:58:53.756061'"))
+
+    def test_overly_aggressive_rvkc_lookup(self):
+        """
+        Regression test for #184.
+
+        Ensures that looking up a RVKC by keyword only (without the
+        field-specifier) in a header returns the full string value of that card
+        without parsing it as a RVKC.  Also ensures that a full field-specifier
+        is required to match a RVKC--a partial field-specifier that doesn't
+        explicitly match any record-valued keyword should result in a KeyError.
+        """
+
+        c1 = fits.Card.fromstring("FOO     = 'AXIS.1: 2'")
+        c2 = fits.Card.fromstring("FOO     = 'AXIS.2: 4'")
+        h = fits.Header([c1, c2])
+        assert h['FOO'] == 'AXIS.1: 2'
+        assert h[('FOO', 1)] == 'AXIS.2: 4'
+        assert h['FOO.AXIS.1'] == 2.0
+        assert h['FOO.AXIS.2'] == 4.0
+        assert 'FOO.AXIS' not in h
+        assert 'FOO.AXIS.' not in h
+        assert 'FOO.' not in h
+        pytest.raises(KeyError, lambda: h['FOO.AXIS'])
+        pytest.raises(KeyError, lambda: h['FOO.AXIS.'])
+        pytest.raises(KeyError, lambda: h['FOO.'])
diff --git a/astropy/io/fits/tests/test_image.py b/astropy/io/fits/tests/test_image.py
index bcfb337..a1cc7cd 100644
--- a/astropy/io/fits/tests/test_image.py
+++ b/astropy/io/fits/tests/test_image.py
@@ -82,6 +82,34 @@ class TestImageFunctions(FitsTestCase):
         finally:
             r.close()
 
+    def test_primary_with_extname(self):
+        """Regression test for #151.
+
+        Tests that the EXTNAME keyword works with Primary HDUs as well, and
+        interacts properly with the .name attribute.  For convenience
+        hdulist['PRIMARY'] will still refer to the first HDU even if it has an
+        EXTNAME not equal to 'PRIMARY'.
+        """
+
+        prihdr = fits.Header([('EXTNAME', 'XPRIMARY'), ('EXTVER', 1)])
+        hdul = fits.HDUList([fits.PrimaryHDU(header=prihdr)])
+        assert 'EXTNAME' in hdul[0].header
+        assert hdul[0].name == 'XPRIMARY'
+        assert hdul[0].name == hdul[0].header['EXTNAME']
+
+        info = [(0, 'XPRIMARY', 'PrimaryHDU', 5, (), 'uint8', '')]
+        assert hdul.info(output=False) == info
+
+        assert hdul['PRIMARY'] is hdul['XPRIMARY']
+        assert hdul['PRIMARY'] is hdul[('XPRIMARY', 1)]
+
+        hdul[0].name = 'XPRIMARY2'
+        assert hdul[0].header['EXTNAME'] == 'XPRIMARY2'
+
+        hdul.writeto(self.temp('test.fits'))
+        with fits.open(self.temp('test.fits')) as hdul:
+            assert hdul[0].name == 'XPRIMARY2'
+
     def test_io_manipulation(self):
         # Get a keyword value.  An extension can be referred by name or by
         # number.  Both extension and keyword names are case insensitive.
@@ -232,13 +260,14 @@ class TestImageFunctions(FitsTestCase):
         with warnings.catch_warnings(record=True) as w:
             hdu.verify()
             text = "HDUList's 0th element is not a primary HDU."
-            assert len(w) == 1
-            assert text in str(w[0].message)
+            assert len(w) == 3
+            assert text in str(w[1].message)
 
+        with warnings.catch_warnings(record=True) as w:
             hdu.writeto(self.temp('test_new2.fits'), 'fix')
             text = ("HDUList's 0th element is not a primary HDU.  "
                     "Fixed by inserting one as 0th HDU.")
-            assert len(w) == 2
+            assert len(w) == 3
             assert text in str(w[1].message)
 
     def test_section(self):
@@ -533,12 +562,31 @@ class TestImageFunctions(FitsTestCase):
     def test_comp_image_hcompression_1_invalid_data(self):
         """
         Tests compression with the HCOMPRESS_1 algorithm with data that is
-        not 2D (and thus should not work).
+        not 2D and has a non-2D tile size.
         """
 
         pytest.raises(ValueError, fits.CompImageHDU,
                       np.zeros((2, 10, 10), dtype=np.float32), name='SCI',
-                      compressionType='HCOMPRESS_1', quantizeLevel=16)
+                      compressionType='HCOMPRESS_1', quantizeLevel=16,
+                      tileSize=[2, 10, 10])
+
+    def test_comp_image_hcompress_image_stack(self):
+        """
+        Regression test for #171.
+
+        Tests that data containing more than two dimensions can be
+        compressed with HCOMPRESS_1 so long as the user-supplied tile size can
+        be flattened to two dimensions.
+        """
+
+        cube = np.arange(300, dtype=np.float32).reshape((3, 10, 10))
+        hdu = fits.CompImageHDU(data=cube, name='SCI',
+                                compressionType='HCOMPRESS_1',
+                                quantizeLevel=16, tileSize=[5, 5, 1])
+        hdu.writeto(self.temp('test.fits'))
+
+        with fits.open(self.temp('test.fits')) as hdul:
+            assert (hdul['SCI'].data == cube).all()
 
     def test_disable_image_compression(self):
         with warnings.catch_warnings():
@@ -554,6 +602,26 @@ class TestImageFunctions(FitsTestCase):
         with fits.open(self.data('comp.fits')) as hdul:
             assert isinstance(hdul[1], fits.CompImageHDU)
 
+    def test_open_comp_image_in_update_mode(self):
+        """
+        Regression test for #167.
+
+        Similar to test_open_scaled_in_update_mode(), but specifically for
+        compressed images.
+        """
+
+        # Copy the original file before making any possible changes to it
+        shutil.copy(self.data('comp.fits'), self.temp('comp.fits'))
+        mtime = os.stat(self.temp('comp.fits')).st_mtime
+
+        time.sleep(1)
+
+        fits.open(self.temp('comp.fits'), mode='update').close()
+
+        # Ensure that no changes were made to the file merely by immediately
+        # opening and closing it.
+        assert mtime == os.stat(self.temp('comp.fits')).st_mtime
+
     def test_do_not_scale_image_data(self):
         hdul = fits.open(self.data('scale.fits'),
                            do_not_scale_image_data=True)
@@ -640,6 +708,55 @@ class TestImageFunctions(FitsTestCase):
         hdul = fits.open(self.temp('test_new.fits'))
         hdul.close()
 
+    def test_rewriting_large_scaled_image_compressed(self):
+        """
+        Regression test for #88 1.
+
+        Identical to test_rewriting_large_scaled_image() but with a compressed
+        image.
+        """
+
+        with fits.open(self.data('fixed-1890.fits'),
+                       do_not_scale_image_data=True) as hdul:
+            chdu = fits.CompImageHDU(data=hdul[0].data,
+                                     header=hdul[0].header)
+            chdu.writeto(self.temp('fixed-1890-z.fits'))
+
+        hdul = fits.open(self.temp('fixed-1890-z.fits'))
+        orig_data = hdul[1].data
+        with ignore_warnings():
+            hdul.writeto(self.temp('test_new.fits'), clobber=True)
+        hdul.close()
+        hdul = fits.open(self.temp('test_new.fits'))
+        assert (hdul[1].data == orig_data).all()
+        hdul.close()
+
+        # Just as before, but this time don't touch hdul[0].data before writing
+        # back out--this is the case that failed in #84
+        hdul = fits.open(self.temp('fixed-1890-z.fits'))
+        with ignore_warnings():
+            hdul.writeto(self.temp('test_new.fits'), clobber=True)
+        hdul.close()
+        hdul = fits.open(self.temp('test_new.fits'))
+        assert (hdul[1].data == orig_data).all()
+        hdul.close()
+
+        # Test opening/closing/reopening a scaled file in update mode
+        hdul = fits.open(self.temp('fixed-1890-z.fits'),
+                           do_not_scale_image_data=True)
+        hdul.writeto(self.temp('test_new.fits'), clobber=True,
+                     output_verify='silentfix')
+        hdul.close()
+        hdul = fits.open(self.temp('test_new.fits'))
+        orig_data = hdul[1].data
+        hdul.close()
+        hdul = fits.open(self.temp('test_new.fits'), mode='update')
+        hdul.close()
+        hdul = fits.open(self.temp('test_new.fits'))
+        assert (hdul[1].data == orig_data).all()
+        hdul = fits.open(self.temp('test_new.fits'))
+        hdul.close()
+
     def test_image_update_header(self):
         """
         Regression test for #105.
@@ -686,7 +803,7 @@ class TestImageFunctions(FitsTestCase):
         time.sleep(1)
 
         hdul = fits.open(self.temp('scale.fits'), 'update')
-        hdul[0].data
+        orig_data = hdul[0].data
         hdul.close()
 
         # Now the file should be updated with the rescaled data
@@ -696,6 +813,7 @@ class TestImageFunctions(FitsTestCase):
         assert hdul[0].header['BITPIX'] == -32
         assert 'BZERO' not in hdul[0].header
         assert 'BSCALE' not in hdul[0].header
+        assert (orig_data == hdul[0].data).all()
 
         # Try reshaping the data, then closing and reopening the file; let's
         # see if all the changes are preseved properly
@@ -709,6 +827,59 @@ class TestImageFunctions(FitsTestCase):
         assert 'BZERO' not in hdul[0].header
         assert 'BSCALE' not in hdul[0].header
 
+    def test_open_scaled_in_update_mode_compressed(self):
+        """
+        Regression test for #88 2.
+
+        Identical to test_open_scaled_in_update_mode() but with a compressed
+        version of the scaled image.
+        """
+
+        # Copy+compress the original file before making any possible changes to
+        # it
+        with fits.open(self.data('scale.fits'),
+                       do_not_scale_image_data=True) as hdul:
+            chdu = fits.CompImageHDU(data=hdul[0].data,
+                                       header=hdul[0].header)
+            chdu.writeto(self.temp('scale.fits'))
+        mtime = os.stat(self.temp('scale.fits')).st_mtime
+
+        time.sleep(1)
+
+        fits.open(self.temp('scale.fits'), mode='update').close()
+
+        # Ensure that no changes were made to the file merely by immediately
+        # opening and closing it.
+        assert mtime == os.stat(self.temp('scale.fits')).st_mtime
+
+        # Insert a slight delay to ensure the mtime does change when the file
+        # is changed
+        time.sleep(1)
+
+        hdul = fits.open(self.temp('scale.fits'), 'update')
+        hdul[1].data
+        hdul.close()
+
+        # Now the file should be updated with the rescaled data
+        assert mtime != os.stat(self.temp('scale.fits')).st_mtime
+        hdul = fits.open(self.temp('scale.fits'), mode='update')
+        assert hdul[1].data.dtype == np.dtype('float32')
+        assert hdul[1].header['BITPIX'] == -32
+        assert 'BZERO' not in hdul[1].header
+        assert 'BSCALE' not in hdul[1].header
+
+        # Try reshaping the data, then closing and reopening the file; let's
+        # see if all the changes are preseved properly
+        hdul[1].data.shape = (42, 10)
+        hdul.close()
+
+        hdul = fits.open(self.temp('scale.fits'))
+        assert hdul[1].shape == (42, 10)
+        assert hdul[1].data.dtype == np.dtype('float32')
+        assert hdul[1].header['BITPIX'] == -32
+        assert 'BZERO' not in hdul[1].header
+        assert 'BSCALE' not in hdul[1].header
+
     def test_scale_back(self):
         """A simple test for #120--the scale_back feature for image HDUs."""
 
@@ -732,3 +903,73 @@ class TestImageFunctions(FitsTestCase):
 
         with fits.open(self.temp('scale.fits')) as hdul:
             assert (hdul[0].data[1:] == orig_data[1:]).all()
+
+    def test_scale_back_compressed(self):
+        """
+        Regression test for #88 3.
+
+        Identical to test_scale_back() but uses a compressed image.
+        """
+
+        # Create a compressed version of the scaled image
+        with fits.open(self.data('scale.fits'),
+                       do_not_scale_image_data=True) as hdul:
+            chdu = fits.CompImageHDU(data=hdul[0].data,
+                                     header=hdul[0].header)
+            chdu.writeto(self.temp('scale.fits'))
+
+        with fits.open(self.temp('scale.fits'), mode='update',
+                       scale_back=True) as hdul:
+            orig_bitpix = hdul[1].header['BITPIX']
+            orig_bzero = hdul[1].header['BZERO']
+            orig_bscale = hdul[1].header['BSCALE']
+            orig_data = hdul[1].data.copy()
+            hdul[1].data[0] = 0
+
+        with fits.open(self.temp('scale.fits'),
+                       do_not_scale_image_data=True) as hdul:
+            assert hdul[1].header['BITPIX'] == orig_bitpix
+            assert hdul[1].header['BZERO'] == orig_bzero
+            assert hdul[1].header['BSCALE'] == orig_bscale
+
+            zero_point = int(math.floor(-orig_bzero / orig_bscale))
+            assert (hdul[1].data[0] == zero_point).all()
+
+        with fits.open(self.temp('scale.fits')) as hdul:
+            assert (hdul[1].data[1:] == orig_data[1:]).all()
+            # Extra test to ensure that after everything the data is still the
+            # same as in the original uncompressed version of the image
+            with fits.open(self.data('scale.fits')) as hdul2:
+                # Recall we made the same modification to the data in hdul
+                # above
+                hdul2[0].data[0] = 0
+                assert (hdul[1].data == hdul2[0].data).all()
+
+    @pytest.mark.skipif("sys.platform.startswith('win')")
+    def test_insufficient_compression_allocation(self):
+        """
+        Test the scenario where not enough space is allocated to hold the
+        compressed data, and a realloc is necessary.
+
+        For some reason this test *sometimes* breaks Jenkins when run on
+        Windows. It passes when the test suite is run outside Jenkins. I intend
+        to track down the cause of this but in the meantime it's disabled on
+        Windows.  See Astropy #507.
+        """
+
+        data = np.arange(10000, dtype='int32').reshape(100, 100)
+        hdu = fits.CompImageHDU(data=data)
+        old_compress_hdu = fits.compression.compress_hdu
+
+        def hacked_compress_hdu(hdu):
+            # Long enough to hold the table, but not enough for the full heap
+            hdu.compData = np.zeros((2880,), dtype=np.uint8)
+            return old_compress_hdu(hdu)
+
+        fits.compression.compress_hdu = hacked_compress_hdu
+
+        try:
+            hdu.updateCompressedData()
+            assert (data == fits.compression.decompress_hdu(hdu)).all()
+        finally:
+            fits.compression.compress_hdu = old_compress_hdu
diff --git a/astropy/io/fits/tests/test_table.py b/astropy/io/fits/tests/test_table.py
index 662325b..c5101f6 100644
--- a/astropy/io/fits/tests/test_table.py
+++ b/astropy/io/fits/tests/test_table.py
@@ -1578,12 +1578,19 @@ class TestTableFunctions(FitsTestCase):
         assert 'ORBPARM' not in tbhdu.data.names
         # Verify that some of the data columns are still correctly accessible
         # by name
+        assert tbhdu.data[0]['ANNAME'] == 'VLA:_W16'
         assert comparefloats(
             tbhdu.data[0]['STABXYZ'],
             np.array([499.85566663, -1317.99231554, -735.18866164],
                      dtype=np.float64))
         assert tbhdu.data[0]['NOSTA'] == 1
         assert tbhdu.data[0]['MNTSTA'] == 0
+        assert tbhdu.data[-1]['ANNAME'] == 'VPT:_OUT'
+        assert comparefloats(
+            tbhdu.data[-1]['STABXYZ'],
+            np.array([0.0, 0.0, 0.0], dtype=np.float64))
+        assert tbhdu.data[-1]['NOSTA'] == 29
+        assert tbhdu.data[-1]['MNTSTA'] == 0
         hdul.writeto(self.temp('newtable.fits'))
         hdul.close()
         hdul = fits.open(self.temp('newtable.fits'))
@@ -1591,12 +1598,19 @@ class TestTableFunctions(FitsTestCase):
         # Verify that the previous tests still hold after writing
         assert 'ORBPARM' in tbhdu.columns.names
         assert 'ORBPARM' not in tbhdu.data.names
+        assert tbhdu.data[0]['ANNAME'] == 'VLA:_W16'
         assert comparefloats(
             tbhdu.data[0]['STABXYZ'],
             np.array([499.85566663, -1317.99231554, -735.18866164],
                      dtype=np.float64))
         assert tbhdu.data[0]['NOSTA'] == 1
         assert tbhdu.data[0]['MNTSTA'] == 0
+        assert tbhdu.data[-1]['ANNAME'] == 'VPT:_OUT'
+        assert comparefloats(
+            tbhdu.data[-1]['STABXYZ'],
+            np.array([0.0, 0.0, 0.0], dtype=np.float64))
+        assert tbhdu.data[-1]['NOSTA'] == 29
+        assert tbhdu.data[-1]['MNTSTA'] == 0
         hdul.close()
 
     def test_string_column_padding(self):
diff --git a/astropy/io/fits/tests/test_uint.py b/astropy/io/fits/tests/test_uint.py
index 9ab6ff1..83d876e 100644
--- a/astropy/io/fits/tests/test_uint.py
+++ b/astropy/io/fits/tests/test_uint.py
@@ -63,3 +63,20 @@ class TestUintFunctions(FitsTestCase):
             assert (hdul[0].section[:1] == hdul[0].data[:1]).all()
             hdul.close()
             hdul1.close()
+
+    def test_uint_compressed(self):
+        hdu = fits.CompImageHDU(np.array([-3, -2, -1, 0, 1, 2, 3]))
+        hdu.scale('int32', '', bzero=2**31)
+        hdu.writeto(self.temp('temp.fits'))
+        with fits.open(self.temp('temp.fits'), uint=True) as hdul:
+            assert hdul[1].data.dtype == np.uint32
+            assert (hdul[1].data ==
+                    np.array([(2**32)-3, (2**32)-2, (2**32)-1, 0, 1, 2, 3],
+                             dtype=np.uint32)).all()
+            hdul.writeto(self.temp('temp2.fits'))
+            with fits.open(self.temp('temp2.fits'), uint=True) as hdul2:
+                assert (hdul[1].data == hdul2[1].data).all()
+                # TODO: Enable these lines if CompImageHDUs ever grow .section
+                # support
+                #assert_equal(hdul[1].section[:1].dtype.name, 'uint32')
+                #assert_true((hdul[1].section[:1] == hdul[1].data[:1]).all())
diff --git a/astropy/io/fits/util.py b/astropy/io/fits/util.py
index b06f590..b49d868 100644
--- a/astropy/io/fits/util.py
+++ b/astropy/io/fits/util.py
@@ -2,6 +2,7 @@
 
 import functools
 import itertools
+import mmap
 import os
 import signal
 import tempfile
@@ -11,8 +12,6 @@ import warnings
 
 import numpy as np
 
-from numpy import memmap as Memmap
-
 
 def itersubclasses(cls, _seen=None):
     """
@@ -515,17 +514,17 @@ def _tmp_name(input):
     return fn
 
 
-def _get_array_memmap(array):
+def _get_array_mmap(array):
     """
-    If the array has a numpy.memmap as one of its bases, return the memmap
-    base; otherwise return None.
+    If the array has an mmap.mmap at base of its base chain, return the mmap
+    object; otherwise return None.
     """
 
-    if isinstance(array, Memmap):
+    if isinstance(array, mmap.mmap):
         return array
 
     base = array
     while hasattr(base, 'base') and base.base is not None:
-        if isinstance(base.base, Memmap):
+        if isinstance(base.base, mmap.mmap):
             return base.base
         base = base.base
diff --git a/astropy/io/fits/verify.py b/astropy/io/fits/verify.py
index cdcc8df..eb0f3a9 100644
--- a/astropy/io/fits/verify.py
+++ b/astropy/io/fits/verify.py
@@ -73,7 +73,7 @@ class _Verify(object):
                 # Each line contains a single issue that was fixed--issue a
                 # separate warning for each of those issues
                 warnings.warn(line, VerifyWarning)
-            warnings.warn(u'Note: PyFITS uses zero-based indexing.\n')
+            warnings.warn(u'Note: Astropy uses zero-based indexing.\n')
         if opt == 'exception' and x:
             raise VerifyError('\n' + x)
 
diff --git a/astropy/io/misc/__init__.py b/astropy/io/misc/__init__.py
new file mode 100644
index 0000000..20888ad
--- /dev/null
+++ b/astropy/io/misc/__init__.py
@@ -0,0 +1,7 @@
+# Licensed under a 3-clause BSD style license - see LICENSE.rst
+"""
+This package contains miscellaneous utility functions for data
+input/output with astropy.
+"""
+
+from .pickle_helpers import *
diff --git a/astropy/io/misc/connect.py b/astropy/io/misc/connect.py
new file mode 100644
index 0000000..4188405
--- /dev/null
+++ b/astropy/io/misc/connect.py
@@ -0,0 +1,10 @@
+# This file connects any readers/writers defined in io.misc to the
+# astropy.table.Table class
+
+from ...table import io_registry
+
+from .hdf5 import read_table_hdf5, write_table_hdf5, is_hdf5
+
+io_registry.register_reader('hdf5', read_table_hdf5)
+io_registry.register_writer('hdf5', write_table_hdf5)
+io_registry.register_identifier('hdf5', is_hdf5)
diff --git a/astropy/io/misc/hdf5.py b/astropy/io/misc/hdf5.py
new file mode 100644
index 0000000..4aa6a05
--- /dev/null
+++ b/astropy/io/misc/hdf5.py
@@ -0,0 +1,197 @@
+# Licensed under a 3-clause BSD style license - see LICENSE.rst
+"""
+This package contains functions for reading and writing HDF5 tables that are
+not meant to be used directly, but instead are available as readers/writers in
+`astropy.table`. See :ref:`table_io` for more details.
+"""
+
+from __future__ import print_function
+
+import os
+
+import numpy as np
+
+from ... import log
+
+HDF5_SIGNATURE = '\x89HDF\r\n\x1a\n'
+
+__all__ = ['read_table_hdf5', 'write_table_hdf5']
+
+
+def is_hdf5(origin, args, kwargs):
+
+    if isinstance(args[0], basestring):
+        if os.path.exists(args[0]):
+            with open(args[0], 'rb') as f:
+                if f.read(8) == HDF5_SIGNATURE:
+                    return True
+                else:
+                    return False
+        elif args[0].endswith('.hdf5') or args[0].endswith('.h5'):
+            return True
+
+    try:
+        import h5py
+    except ImportError:
+        return False
+    else:
+        return isinstance(args[0], (h5py.highlevel.File, h5py.highlevel.Group))
+
+
+def read_table_hdf5(input, path=None):
+    """
+    Read a Table object from an HDF5 file
+
+    This requires `h5py <http://alfven.org/wp/hdf5-for-python/>`_ to be
+    installed.
+
+    Parameters
+    ----------
+    input : str or `h5py.highlevel.File` or `h5py.highlevel.Group`
+        If a string, the filename to read the table from. If an h5py object,
+        either the file or the group object to read the table from.
+    path : str
+        The path from which to read the table inside the HDF5 file.
+        This should be relative to the input file or group.
+    """
+
+    try:
+        import h5py
+    except ImportError:
+        raise Exception("h5py is required to read and write HDF5 files")
+
+    if path is None:
+        raise ValueError("table path should be set via the path= argument")
+    elif path.endswith('/'):
+        raise ValueError("table path should end with table name, not /")
+
+    if '/' in path:
+        group, name = path.rsplit('/', 1)
+    else:
+        group, name = None, path
+
+    if isinstance(input, (h5py.highlevel.File, h5py.highlevel.Group)):
+        f, g = None, input
+        if group:
+            try:
+                g = g[group]
+            except KeyError:
+                raise IOError("Group {0} does not exist".format(group))
+    else:
+        f = h5py.File(input, 'r')
+        try:
+            g = f[group] if group else f
+        except KeyError:
+            raise IOError("Group {0} does not exist".format(group))
+
+    # Check whether table exists
+    if name not in g.keys():
+        raise IOError("Table {0} does not exist".format(path))
+
+    # Read the table from the file
+    dset = g[name]
+
+    # Create a Table object
+    from ...table import Table
+    table = Table(np.array(dset))
+
+    # Read the meta-data from the file
+    table.meta.update(dset.attrs)
+
+    if f is not None:
+        f.close()
+
+    return table
+
+
+def write_table_hdf5(table, output, path=None, compression=False,
+               append=False, overwrite=False):
+    """
+    Write a Table object to an HDF5 file
+
+    This requires `h5py <http://alfven.org/wp/hdf5-for-python/>`_ to be
+    installed.
+
+    Parameters
+    ----------
+    output : str or `h5py.highlevel.File` or `h5py.highlevel.Group`
+        If a string, the filename to write the table to. If an h5py object,
+        either the file or the group object to write the table to.
+    compression : bool
+        Whether to compress the table inside the HDF5 file.
+    path : str
+        The path to which to write the table inside the HDF5 file.
+        This should be relative to the input file or group.
+    append : bool
+        Whether to append the table to an existing HDF5 file.
+    overwrite : bool
+        Whether to overwrite any existing file without warning.
+    """
+
+    try:
+        import h5py
+    except ImportError:
+        raise Exception("h5py is required to read and write HDF5 files")
+
+    if path is None:
+        raise ValueError("table path should be set via the path= argument")
+    elif path.endswith('/'):
+        raise ValueError("table path should end with table name, not /")
+
+    if '/' in path:
+        group, name = path.rsplit('/', 1)
+    else:
+        group, name = None, path
+
+    if isinstance(output, h5py.highlevel.File) or \
+       isinstance(output, h5py.highlevel.Group):
+        f, g = None, output
+        if group:
+            try:
+                g = g[group]
+            except KeyError:
+                g = g.create_group(group)
+    else:
+        if os.path.exists(output) and not append:
+            if overwrite:
+                os.remove(output)
+            else:
+                raise IOError("File exists: {0}".format(output))
+
+        # Open the file for appending or writing
+        f = h5py.File(output, 'a' if append else 'w')
+
+        if group:
+            if append:
+                if group in f.keys():
+                    g = f[group]
+                else:
+                    g = f.create_group(group)
+            else:
+                g = f.create_group(group)
+        else:
+            g = f
+
+    # Check whether table already exists
+    if name in g.keys():
+        raise IOError("Table {0} already exists".format(path))
+
+    # Write the table to the file
+    dset = g.create_dataset(name, data=table._data, compression=compression)
+
+    # Write the meta-data to the file
+    for key in table.meta:
+
+        if isinstance(table.meta[key], basestring):
+            # Use np.string_ to ensure that fixed-length attributes are used.
+            dset.attrs[key] = np.string_(table.meta[key])
+        else:
+            try:
+                dset.attrs[key] = table.meta[key]
+            except TypeError:
+                log.warn("Attribute `{0}` of type {1} cannot be written to "
+                         "HDF5 files - skipping".format(key,
+                         type(table.meta[key])))
+
+    if f is not None:
+        f.close()
diff --git a/astropy/io/misc/pickle_helpers.py b/astropy/io/misc/pickle_helpers.py
new file mode 100644
index 0000000..62b4ae4
--- /dev/null
+++ b/astropy/io/misc/pickle_helpers.py
@@ -0,0 +1,120 @@
+# Licensed under a 3-clause BSD style license - see LICENSE.rst
+"""
+This module contains simple input/output related functionality that is not
+part of a larger framework or standard.
+"""
+
+__all__ = ['fnpickle', 'fnunpickle']
+
+
+def fnunpickle(fileorname, number=0, usecPickle=True):
+    """ Unpickle pickled objects from a specified file and return the contents.
+
+    Parameters
+    ----------
+    fileorname : str or `file`-like
+        The file name or file from which to unpickle objects. If a file object,
+        it should have been opened in binary mode.
+    number : int
+        If 0, a single object will be returned (the first in the file). If >0,
+        this specifies the number of objects to be unpickled, and a list will
+        be returned with exactly that many objects. If <0, all objects in the
+        file will be unpickled and returned as a list.
+    usecPickle : bool
+        If True, the :mod:`cPickle` module is to be used in place of
+        :mod:`pickle` (cPickle is faster). This only applies for python 2.x.
+
+    Raises
+    ------
+    EOFError
+        If `number` is >0 and there are fewer than `number` objects in the
+        pickled file.
+
+    Returns
+    -------
+    contents : obj or list
+        If `number` is 0, this is a individual object - the first one unpickled
+        from the file. Otherwise, it is a list of objects unpickled from the
+        file.
+
+    """
+    import sys
+
+    if usecPickle and sys.version_info[0] < 3:  # pragma: py2
+        import cPickle as pickle
+    else:
+        import pickle
+
+    if isinstance(fileorname, basestring):
+        f = open(fileorname, 'rb')
+        close = True
+    else:
+        f = fileorname
+        close = False
+
+    try:
+        if number > 0:  # get that number
+            res = []
+            for i in range(number):
+                res.append(pickle.load(f))
+        elif number < 0:  # get all objects
+            res = []
+            eof = False
+            while not eof:
+                try:
+                    res.append(pickle.load(f))
+                except EOFError:
+                    eof = True
+        else:  # number==0
+            res = pickle.load(f)
+    finally:
+        if close:
+            f.close()
+
+    return res
+
+
+def fnpickle(object, fileorname, usecPickle=True, protocol=None, append=False):
+    """Pickle an object to a specified file.
+
+    Parameters
+    ----------
+    object
+        The python object to pickle.
+    fileorname : str or `file`-like
+        The filename or file into which the `object` should be pickled. If a
+        file object, it should have been opened in binary mode.
+    usecPickle : bool
+        If True (default), the :mod:`cPickle` module is to be used in place of
+        :mod:`pickle` (cPickle is faster). This only applies for python 2.x.
+    protocol : int or None
+        Pickle protocol to use - see the :mod:`pickle` module for details on
+        these options. If None, the most recent protocol will be used.
+    append : bool
+        If True, the object is appended to the end of the file, otherwise the
+        file will be overwritten (if a file object is given instead of a
+        file name, this has no effect).
+
+    """
+    import sys
+
+    if usecPickle and sys.version_info[0] < 3:  # pragma: py2
+        import cPickle as pickle
+    else:
+        import pickle
+
+    if protocol is None:
+        protocol = pickle.HIGHEST_PROTOCOL
+
+    if isinstance(fileorname, basestring):
+        f = open(fileorname, 'ab' if append else 'wb')
+        close = True
+    else:
+        f = fileorname
+        close = False
+
+    try:
+        pickle.dump(object, f, protocol=protocol)
+    finally:
+        if close:
+            f.close()
diff --git a/astropy/io/misc/tests/__init__.py b/astropy/io/misc/tests/__init__.py
new file mode 100644
index 0000000..9dce85d
--- /dev/null
+++ b/astropy/io/misc/tests/__init__.py
@@ -0,0 +1 @@
+# Licensed under a 3-clause BSD style license - see LICENSE.rst
diff --git a/astropy/io/misc/tests/test_hdf5.py b/astropy/io/misc/tests/test_hdf5.py
new file mode 100644
index 0000000..5983261
--- /dev/null
+++ b/astropy/io/misc/tests/test_hdf5.py
@@ -0,0 +1,351 @@
+# Licensed under a 3-clause BSD style license - see LICENSE.rst
+
+from __future__ import print_function
+
+import numpy as np
+
+from ....tests.helper import pytest
+from ....table import Table, Column
+from .... import log
+
+try:
+    import h5py
+except ImportError:
+    HAS_H5PY = False
+else:
+    HAS_H5PY = True
+
+
+ALL_DTYPES = [np.uint8, np.uint16, np.uint32, np.uint64, np.int8,
+              np.int16, np.int32, np.int64, np.float32, np.float64,
+              np.bool, '|S3']
+
+
+def _default_values(dtype):
+    if dtype == np.bool:
+        return [0, 1, 1]
+    elif dtype == '|S3':
+        return ['abc', 'def', 'ghi']
+    else:
+        return [1, 2, 3]
+
+
+ at pytest.mark.skipif('not HAS_H5PY')
+def test_write_nopath(tmpdir):
+    test_file = str(tmpdir.join('test.hdf5'))
+    t1 = Table()
+    t1.add_column(Column('a', [1, 2, 3]))
+    with pytest.raises(ValueError) as exc:
+        t1.write(test_file)
+    assert exc.value.args[0] == "table path should be set via the path= argument"
+
+
+ at pytest.mark.skipif('not HAS_H5PY')
+def test_read_nopath(tmpdir):
+    test_file = str(tmpdir.join('test.hdf5'))
+    t1 = Table()
+    t1.add_column(Column('a', [1, 2, 3]))
+    t1.write(test_file, path='the_table')
+    with pytest.raises(ValueError) as exc:
+        Table.read(test_file)
+    assert exc.value.args[0] == "table path should be set via the path= argument"
+
+
+ at pytest.mark.skipif('not HAS_H5PY')
+def test_write_invalid_path(tmpdir):
+    test_file = str(tmpdir.join('test.hdf5'))
+    t1 = Table()
+    t1.add_column(Column('a', [1, 2, 3]))
+    with pytest.raises(ValueError) as exc:
+        t1.write(test_file, path='test/')
+    assert exc.value.args[0] == "table path should end with table name, not /"
+
+
+ at pytest.mark.skipif('not HAS_H5PY')
+def test_read_invalid_path(tmpdir):
+    test_file = str(tmpdir.join('test.hdf5'))
+    t1 = Table()
+    t1.add_column(Column('a', [1, 2, 3]))
+    t1.write(test_file, path='the_table')
+    with pytest.raises(ValueError) as exc:
+        Table.read(test_file, path='test/')
+    assert exc.value.args[0] == "table path should end with table name, not /"
+
+
+ at pytest.mark.skipif('not HAS_H5PY')
+def test_read_missing_group(tmpdir):
+    test_file = str(tmpdir.join('test.hdf5'))
+    f = h5py.File(test_file, 'w')
+    f.close()
+    with pytest.raises(IOError) as exc:
+        Table.read(test_file, path='test/path/table')
+    assert exc.value.args[0] == "Group test/path does not exist"
+
+
+ at pytest.mark.skipif('not HAS_H5PY')
+def test_read_missing_table(tmpdir):
+    test_file = str(tmpdir.join('test.hdf5'))
+    f = h5py.File(test_file, 'w')
+    f.create_group('test').create_group('path')
+    f.close()
+    with pytest.raises(IOError) as exc:
+        Table.read(test_file, path='test/path/table')
+    assert exc.value.args[0] == "Table test/path/table does not exist"
+
+
+ at pytest.mark.skipif('not HAS_H5PY')
+def test_read_missing_group_fileobj(tmpdir):
+    test_file = str(tmpdir.join('test.hdf5'))
+    f = h5py.File(test_file, 'w')
+    with pytest.raises(IOError) as exc:
+        Table.read(f, path='test/path/table')
+    assert exc.value.args[0] == "Group test/path does not exist"
+
+
+ at pytest.mark.skipif('not HAS_H5PY')
+def test_read_write_simple(tmpdir):
+    test_file = str(tmpdir.join('test.hdf5'))
+    t1 = Table()
+    t1.add_column(Column('a', [1, 2, 3]))
+    t1.write(test_file, path='the_table')
+    t2 = Table.read(test_file, path='the_table')
+    assert np.all(t2['a'] == [1, 2, 3])
+
+
+ at pytest.mark.skipif('not HAS_H5PY')
+def test_read_write_existing_table(tmpdir):
+    test_file = str(tmpdir.join('test.hdf5'))
+    t1 = Table()
+    t1.add_column(Column('a', [1, 2, 3]))
+    t1.write(test_file, path='the_table')
+    with pytest.raises(IOError) as exc:
+        t1.write(test_file, path='the_table', append=True)
+    assert exc.value.args[0] == "Table the_table already exists"
+
+
+ at pytest.mark.skipif('not HAS_H5PY')
+def test_read_write_memory(tmpdir):
+    output_file = h5py.File('test', driver='core', backing_store=False)
+    t1 = Table()
+    t1.add_column(Column('a', [1, 2, 3]))
+    t1.write(output_file, path='the_table')
+    t2 = Table.read(output_file, path='the_table')
+    assert np.all(t2['a'] == [1, 2, 3])
+
+
+ at pytest.mark.skipif('not HAS_H5PY')
+def test_read_write_existing(tmpdir):
+    test_file = str(tmpdir.join('test.hdf5'))
+    f = h5py.File(test_file, 'w')
+    f.close()
+    t1 = Table()
+    t1.add_column(Column('a', [1, 2, 3]))
+    with pytest.raises(IOError) as exc:
+        t1.write(test_file, path='the_table')
+    assert exc.value.args[0].startswith("File exists:")
+
+
+ at pytest.mark.skipif('not HAS_H5PY')
+def test_read_write_existing_overwrite(tmpdir):
+    test_file = str(tmpdir.join('test.hdf5'))
+    f = h5py.File(test_file, 'w')
+    f.close()
+    t1 = Table()
+    t1.add_column(Column('a', [1, 2, 3]))
+    t1.write(test_file, path='the_table', overwrite=True)
+    t2 = Table.read(test_file, path='the_table')
+    assert np.all(t2['a'] == [1, 2, 3])
+
+
+ at pytest.mark.skipif('not HAS_H5PY')
+def test_read_write_existing_append(tmpdir):
+    test_file = str(tmpdir.join('test.hdf5'))
+    f = h5py.File(test_file, 'w')
+    f.close()
+    t1 = Table()
+    t1.add_column(Column('a', [1, 2, 3]))
+    t1.write(test_file, path='the_table_1', append=True)
+    t1.write(test_file, path='the_table_2', append=True)
+    t2 = Table.read(test_file, path='the_table_1')
+    assert np.all(t2['a'] == [1, 2, 3])
+    t3 = Table.read(test_file, path='the_table_2')
+    assert np.all(t3['a'] == [1, 2, 3])
+
+
+ at pytest.mark.skipif('not HAS_H5PY')
+def test_read_write_existing_append_groups(tmpdir):
+    test_file = str(tmpdir.join('test.hdf5'))
+    f = h5py.File(test_file, 'w')
+    f.create_group('test_1')
+    f.close()
+    t1 = Table()
+    t1.add_column(Column('a', [1, 2, 3]))
+    t1.write(test_file, path='test_1/the_table_1', append=True)
+    t1.write(test_file, path='test_2/the_table_2', append=True)
+    t2 = Table.read(test_file, path='test_1/the_table_1')
+    assert np.all(t2['a'] == [1, 2, 3])
+    t3 = Table.read(test_file, path='test_2/the_table_2')
+    assert np.all(t3['a'] == [1, 2, 3])
+
+
+ at pytest.mark.skipif('not HAS_H5PY')
+def test_read_fileobj(tmpdir):
+
+    test_file = str(tmpdir.join('test.hdf5'))
+
+    t1 = Table()
+    t1.add_column(Column('a', [1, 2, 3]))
+    t1.write(test_file, path='the_table')
+
+    import h5py
+    input_file = h5py.File(test_file, 'r')
+
+    t2 = Table.read(input_file, path='the_table')
+    assert np.all(t2['a'] == [1, 2, 3])
+
+
+ at pytest.mark.skipif('not HAS_H5PY')
+def test_read_filobj_path(tmpdir):
+
+    test_file = str(tmpdir.join('test.hdf5'))
+
+    t1 = Table()
+    t1.add_column(Column('a', [1, 2, 3]))
+    t1.write(test_file, path='path/to/data/the_table')
+
+    import h5py
+    input_file = h5py.File(test_file, 'r')
+
+    t2 = Table.read(input_file, path='path/to/data/the_table')
+    assert np.all(t2['a'] == [1, 2, 3])
+
+
+ at pytest.mark.skipif('not HAS_H5PY')
+def test_read_filobj_group_path(tmpdir):
+
+    test_file = str(tmpdir.join('test.hdf5'))
+
+    t1 = Table()
+    t1.add_column(Column('a', [1, 2, 3]))
+    t1.write(test_file, path='path/to/data/the_table')
+
+    import h5py
+    input_file = h5py.File(test_file, 'r')['path/to']
+
+    t2 = Table.read(input_file, path='data/the_table')
+    assert np.all(t2['a'] == [1, 2, 3])
+
+
+ at pytest.mark.skipif('not HAS_H5PY')
+def test_write_fileobj(tmpdir):
+
+    test_file = str(tmpdir.join('test.hdf5'))
+
+    import h5py
+    output_file = h5py.File(test_file, 'w')
+
+    t1 = Table()
+    t1.add_column(Column('a', [1, 2, 3]))
+    t1.write(output_file, path='the_table')
+    output_file.close()
+
+    t2 = Table.read(test_file, path='the_table')
+    assert np.all(t2['a'] == [1, 2, 3])
+
+
+ at pytest.mark.skipif('not HAS_H5PY')
+def test_write_filobj_group(tmpdir):
+
+    test_file = str(tmpdir.join('test.hdf5'))
+
+    import h5py
+    output_file = h5py.File(test_file, 'w')
+
+    t1 = Table()
+    t1.add_column(Column('a', [1, 2, 3]))
+    t1.write(output_file, path='path/to/data/the_table')
+    output_file.close()
+
+    t2 = Table.read(test_file, path='path/to/data/the_table')
+    assert np.all(t2['a'] == [1, 2, 3])
+
+
+ at pytest.mark.skipif('not HAS_H5PY')
+ at pytest.mark.parametrize(('dtype'), ALL_DTYPES)
+def test_preserve_single_dtypes(tmpdir, dtype):
+
+    test_file = str(tmpdir.join('test.hdf5'))
+
+    values = _default_values(dtype)
+
+    t1 = Table()
+    t1.add_column(Column('a', np.array(values, dtype=dtype)))
+    t1.write(test_file, path='the_table')
+
+    t2 = Table.read(test_file, path='the_table')
+
+    assert np.all(t2['a'] == values)
+    assert t2['a'].dtype == dtype
+
+
+ at pytest.mark.skipif('not HAS_H5PY')
+def test_preserve_all_dtypes(tmpdir):
+
+    test_file = str(tmpdir.join('test.hdf5'))
+
+    t1 = Table()
+
+    for dtype in ALL_DTYPES:
+        values = _default_values(dtype)
+        t1.add_column(Column(str(dtype), np.array(values, dtype=dtype)))
+
+    t1.write(test_file, path='the_table')
+
+    t2 = Table.read(test_file, path='the_table')
+
+    for dtype in ALL_DTYPES:
+        values = _default_values(dtype)
+        assert np.all(t2[str(dtype)] == values)
+        assert t2[str(dtype)].dtype == dtype
+
+
+ at pytest.mark.skipif('not HAS_H5PY')
+def test_preserve_meta(tmpdir):
+
+    test_file = str(tmpdir.join('test.hdf5'))
+
+    t1 = Table()
+    t1.add_column(Column('a', [1, 2, 3]))
+
+    t1.meta['a'] = 1
+    t1.meta['b'] = 'hello'
+    t1.meta['c'] = 3.14159
+    t1.meta['d'] = True
+    t1.meta['e'] = np.array([1, 2, 3])
+
+    t1.write(test_file, path='the_table')
+
+    t2 = Table.read(test_file, path='the_table')
+
+    for key in t1.meta:
+        assert np.all(t1.meta[key] == t2.meta[key])
+
+
+ at pytest.mark.skipif('not HAS_H5PY')
+def test_skip_meta(tmpdir):
+
+    test_file = str(tmpdir.join('test.hdf5'))
+
+    t1 = Table()
+    t1.add_column(Column('a', [1, 2, 3]))
+
+    t1.meta['a'] = 1
+    t1.meta['b'] = 'hello'
+    t1.meta['c'] = 3.14159
+    t1.meta['d'] = True
+    t1.meta['e'] = np.array([1, 2, 3])
+    t1.meta['f'] = str
+
+    with log.log_to_list() as warning_list:
+        t1.write(test_file, path='the_table')
+    assert warning_list[0].message == "Attribute `f` of type {0} cannot be written to HDF5 files - skipping".format(type(t1.meta['f']))
diff --git a/astropy/io/misc/tests/test_pickle_helpers.py b/astropy/io/misc/tests/test_pickle_helpers.py
new file mode 100644
index 0000000..2612fde
--- /dev/null
+++ b/astropy/io/misc/tests/test_pickle_helpers.py
@@ -0,0 +1,105 @@
+# Licensed under a 3-clause BSD style license - see LICENSE.rst
+from .. import fnpickle, fnunpickle
+
+
+def test_fnpickling_simple(tmpdir):
+    """
+    Tests the `fnpickle` and `fnupickle` functions' basic operation by
+    pickling and unpickling a string, using both a filename and a
+    file.
+    """
+    fn = str(tmpdir.join('test1.pickle'))
+
+    obj1 = 'astring'
+    fnpickle(obj1, fn)
+    res = fnunpickle(fn)
+    assert obj1 == res
+
+    #try without cPickle
+    fnpickle(obj1, fn, usecPickle=False)
+    res = fnunpickle(fn, usecPickle=False)
+    assert obj1 == res
+
+    #now try with a file-like object instead of a string
+    with open(fn, 'wb') as f:
+        fnpickle(obj1, f)
+    with open(fn, 'rb') as f:
+        res = fnunpickle(f)
+        assert obj1 == res
+
+    #same without cPickle
+    with open(fn, 'wb') as f:
+        fnpickle(obj1, f, usecPickle=False)
+    with open(fn, 'rb') as f:
+        res = fnunpickle(f, usecPickle=False)
+        assert obj1 == res
+
+
+class ToBePickled(object):
+    def __init__(self, item):
+        self.item = item
+
+    def __eq__(self, other):
+        if isinstance(other, ToBePickled):
+            return self.item == other.item
+        else:
+            return False
+
+
+def test_fnpickling_class(tmpdir):
+    """
+    Tests the `fnpickle` and `fnupickle` functions' ability to pickle
+    and unpickle custom classes.
+    """
+    fn = str(tmpdir.join('test2.pickle'))
+
+    obj1 = 'astring'
+    obj2 = ToBePickled(obj1)
+    fnpickle(obj2, fn)
+    res = fnunpickle(fn)
+    assert res == obj2
+
+
+def test_fnpickling_protocol(tmpdir):
+    """
+    Tests the `fnpickle` and `fnupickle` functions' ability to pickle
+    and unpickle pickle files from all protcols.
+    """
+    import pickle
+
+    obj1 = 'astring'
+    obj2 = ToBePickled(obj1)
+
+    for p in range(pickle.HIGHEST_PROTOCOL + 1):
+        fn = str(tmpdir.join('testp%i.pickle' % p))
+        fnpickle(obj2, fn, protocol=p)
+        res = fnunpickle(fn)
+        assert res == obj2
+
+
+def test_fnpickling_many(tmpdir):
+    """
+    Tests the `fnpickle` and `fnupickle` functions' ability to pickle
+    and unpickle multiple objects from a single file.
+    """
+    from ....tests.helper import pytest
+
+    fn = str(tmpdir.join('test3.pickle'))
+
+    #now try multiples
+    obj3 = 328.3432
+    obj4 = 'blahblahfoo'
+    fnpickle(obj3, fn)
+    fnpickle(obj4, fn, append=True)
+
+    res = fnunpickle(fn, number=-1)
+    assert len(res) == 2
+    assert res[0] == obj3
+    assert res[1] == obj4
+
+    fnpickle(obj4, fn, append=True)
+    res = fnunpickle(fn, number=2)
+    assert len(res) == 2
+
+    with pytest.raises(EOFError):
+        fnunpickle(fn, number=5)
diff --git a/astropy/io/vo/__init__.py b/astropy/io/vo/__init__.py
deleted file mode 100644
index 0db3061..0000000
--- a/astropy/io/vo/__init__.py
+++ /dev/null
@@ -1,16 +0,0 @@
-# Licensed under a 3-clause BSD style license - see LICENSE.rst
-"""
-This package reads and writes data formats used by the Virtual
-Observatory (VO) initiative, particularly the VOTable XML format.
-"""
-
-from .table import parse, parse_single_table, validate
-from .exceptions import (VOWarning, VOTableChangeWarning,
-    VOTableSpecWarning, UnimplementedWarning, IOWarning,
-    VOTableSpecError)
-
-__all__ = [
-    'parse', 'parse_single_table', 'validate', 'VOWarning',
-    'VOTableChangeWarning', 'VOTableSpecWarning',
-    'UnimplementedWarning', 'IOWarning', 'VOTableSpecError'
-    ]
diff --git a/astropy/io/vo/converters.py b/astropy/io/vo/converters.py
deleted file mode 100644
index ddef294..0000000
--- a/astropy/io/vo/converters.py
+++ /dev/null
@@ -1,1150 +0,0 @@
-"""
-This module handles the conversion of various VOTABLE datatypes
-to/from TABLEDATA_ and BINARY_ formats.
-"""
-
-from __future__ import division, absolute_import
-
-# STDLIB
-import re
-from struct import unpack as struct_unpack
-from struct import pack as struct_pack
-
-# THIRD-PARTY
-import numpy as np
-
-# ASTROPY
-from ...utils.xml.writer import xml_escape_cdata
-
-# LOCAL
-from .exceptions import (vo_raise, vo_warn, warn_or_raise, W01,
-    W30, W31, W39, W46, W47, W49, E01, E02, E03, E04, E05, E06)
-from .util import IS_PY3K
-
-
-__all__ = ['get_converter', 'Converter']
-
-
-pedantic_array_splitter = re.compile(r" +")
-array_splitter = re.compile(r"\s+|(?:\s*,\s*)")
-"""
-A regex to handle splitting values on either whitespace or commas.
-
-SPEC: Usage of commas is not actually allowed by the spec, but many
-files in the wild use them.
-"""
-
-_zero_int = b'\0\0\0\0'
-_empty_bytes = b''
-_zero_byte = b'\0'
-
-
-class Converter(object):
-    """
-    The base class for all converters.  Each subclass handles
-    converting a specific VOTABLE data type to/from the TABLEDATA_ and
-    BINARY_ on-disk representations.
-
-    Parameters
-    ----------
-    field : `~astropy.io.vo.table.Field`
-        object describing the datatype
-
-    config : dict
-        The parser configuration dictionary
-
-    pos : tuple
-        The position in the XML file where the FIELD object was
-        found.  Used for error messages.
-
-    """
-    def __init__(self, field, config={}, pos=None):
-        pass
-
-    @staticmethod
-    def _parse_length(read):
-        return struct_unpack(">I", read(4))[0]
-
-    @staticmethod
-    def _write_length(length):
-        return struct_pack(">I", int(length))
-
-    def parse(self, value, config={}, pos=None):
-        """
-        Convert the string *value* from the TABLEDATA_ format into an
-        object with the correct native in-memory datatype and mask flag.
-
-        Parameters
-        ----------
-        value : str
-            value in TABLEDATA format
-
-        Returns
-        -------
-        native : tuple (value, mask)
-            The value as a Numpy array or scalar, and *mask* is True
-            if the value is missing.
-        """
-        raise NotImplementedError(
-            "This datatype must implement a 'parse' method.")
-
-    def parse_scalar(self, value, config={}, pos=None):
-        """
-        Parse a single scalar of the underlying type of the converter.
-        For non-array converters, this is equivalent to parse.  For
-        array converters, this is used to parse a single
-        element of the array.
-
-        Parameters
-        ----------
-        value : str
-            value in TABLEDATA format
-
-        Returns
-        -------
-        native : tuple (value, mask)
-            The value as a Numpy array or scalar, and *mask* is True
-            if the value is missing.
-        """
-        return self.parse(value, config, pos)
-
-    def output(self, value, mask):
-        """
-        Convert the object *value* (in the native in-memory datatype)
-        to a unicode string suitable for serializing in the TABLEDATA_
-        format.
-
-        Parameters
-        ----------
-        value : native type corresponding to this converter
-            The value
-
-        mask : bool
-            If `True`, will return the string representation of a
-            masked value.
-
-        Returns
-        -------
-        tabledata_repr : unicode
-        """
-        raise NotImplementedError(
-            "This datatype must implement a 'output' method.")
-
-    def binparse(self, read):
-        """
-        Reads some number of bytes from the BINARY_ format
-        representation by calling the function *read*, and returns the
-        native in-memory object representation for the datatype
-        handled by *self*.
-
-        Parameters
-        ----------
-        read : function
-            A function that given a number of bytes, returns a byte
-            string.
-
-        Returns
-        -------
-        native : tuple (value, mask)
-            The value as a Numpy array or scalar, and *mask* is True
-            if the value is missing.
-        """
-        raise NotImplementedError(
-            "This datatype must implement a 'binparse' method.")
-
-    def binoutput(self, value, mask):
-        """
-        Convert the object *value* in the native in-memory datatype to
-        a string of bytes suitable for serialization in the BINARY_
-        format.
-
-        Parameters
-        ----------
-        value : native type corresponding to this converter
-            The value
-
-        mask : bool
-            If `True`, will return the string representation of a
-            masked value.
-
-        Returns
-        -------
-        bytes : byte string
-            The binary representation of the value, suitable for
-            serialization in the BINARY_ format.
-        """
-        raise NotImplementedError(
-            "This datatype must implement a 'binoutput' method.")
-
-
-class Char(Converter):
-    """
-    Handles the char datatype. (7-bit unsigned characters)
-
-    Missing values are not handled for string or unicode types.
-    """
-    default = _empty_bytes
-
-    def __init__(self, field, config={}, pos=None):
-        Converter.__init__(self, field, config, pos)
-
-        if field.arraysize is None:
-            vo_warn(W47, (), config, pos)
-            field.arraysize = '1'
-
-        if field.arraysize == '*':
-            self.format = 'O'
-            self.binparse = self._binparse_var
-            self.binoutput = self._binoutput_var
-            self.arraysize = '*'
-        else:
-            if field.arraysize.endswith('*'):
-                field.arraysize = field.arraysize[:-1]
-            try:
-                self.arraysize = int(field.arraysize)
-            except ValueError:
-                vo_raise(E01, (field.arraysize, 'char', field.ID), config)
-            self.format = 'S%d' % self.arraysize
-            self.binparse = self._binparse_fixed
-            self.binoutput = self._binoutput_fixed
-            self._struct_format = ">%ds" % self.arraysize
-
-        if config.get('pedantic'):
-            self.parse = self._ascii_parse
-        else:
-            self.parse = self._str_parse
-
-    def _ascii_parse(self, value, config={}, pos=None):
-        if self.arraysize != '*' and len(value) > self.arraysize:
-            vo_warn(W46, ('char', self.arraysize), config, pos)
-        return value.encode('ascii'), False
-
-    def _str_parse(self, value, config={}, pos=None):
-        if self.arraysize != '*' and len(value) > self.arraysize:
-            vo_warn(W46, ('char', self.arraysize), config, pos)
-        return value.encode('utf-8'), False
-
-    def output(self, value, mask):
-        if mask:
-            return u''
-        if not isinstance(value, str):
-            value = value.decode('ascii')
-        return xml_escape_cdata(value)
-
-    def _binparse_var(self, read):
-        length = self._parse_length(read)
-        return read(length), False
-
-    def _binparse_fixed(self, read):
-        s = struct_unpack(self._struct_format, read(self.arraysize))[0]
-        end = s.find(_zero_byte)
-        if end != -1:
-            return s[:end], False
-        return s, False
-
-    def _binoutput_var(self, value, mask):
-        if mask or value is None or value == u'':
-            return _zero_int
-        return self._write_length(len(value)) + value
-
-    def _binoutput_fixed(self, value, mask):
-        if mask:
-            value = _empty_bytes
-        return struct_pack(self._struct_format, value)
-
-
-class UnicodeChar(Converter):
-    """
-    Handles the unicodeChar data type. UTF-16-BE.
-
-    Missing values are not handled for string or unicode types.
-    """
-    default = u''
-
-    def __init__(self, field, config={}, pos=None):
-        Converter.__init__(self, field, config, pos)
-
-        if field.arraysize is None:
-            vo_warn(W47, (), config, pos)
-            field.arraysize = '1'
-
-        if field.arraysize == '*':
-            self.format = 'O'
-            self.binparse = self._binparse_var
-            self.binoutput = self._binoutput_var
-            self.arraysize = '*'
-        else:
-            try:
-                self.arraysize = int(field.arraysize)
-            except ValueError:
-                vo_raise(E01, (field.arraysize, 'unicode', field.ID), config)
-            self.format = 'U%d' % self.arraysize
-            self.binparse = self._binparse_fixed
-            self.binoutput = self._binoutput_fixed
-            self._struct_format = ">%ds" % (self.arraysize * 2)
-
-    def parse(self, value, config={}, pos=None):
-        if self.arraysize != '*' and len(value) > self.arraysize:
-            vo_warn(W46, ('unicodeChar', self.arraysize), config, pos)
-        return value, False
-
-    def output(self, value, mask):
-        if mask:
-            return u''
-        return xml_escape_cdata(value)
-
-    def _binparse_var(self, read):
-        length = self._parse_length(read)
-        return read(length * 2).decode('utf_16_be'), False
-
-    def _binparse_fixed(self, read):
-        s = struct_unpack(self._struct_format, read(self.arraysize * 2))[0]
-        s = s.decode('utf_16_be')
-        end = s.find('\0')
-        if end != -1:
-            return s[:end], False
-        return s, False
-
-    def _binoutput_var(self, value, mask):
-        if mask or value is None or value == '':
-            return _zero_int
-        encoded = value.encode('utf_16_be')
-        return self._write_length(len(encoded) / 2) + encoded
-
-    def _binoutput_fixed(self, value, mask):
-        if mask:
-            value = u''
-        return struct_pack(self._struct_format, value.encode('utf_16_be'))
-
-
-class Array(Converter):
-    """
-    Handles both fixed and variable-lengths arrays.
-    """
-    def __init__(self, field, config={}, pos=None):
-        Converter.__init__(self, field, config, pos)
-
-        if config.get('pedantic'):
-            self._splitter = self._splitter_pedantic
-        else:
-            self._splitter = self._splitter_lax
-
-    def parse_scalar(self, value, config={}, pos=0):
-        return self._base.parse_scalar(value, config, pos)
-
-    @staticmethod
-    def _splitter_pedantic(value, config={}, pos=None):
-        return pedantic_array_splitter.split(value)
-
-    @staticmethod
-    def _splitter_lax(value, config={}, pos=None):
-        if ',' in value:
-            vo_warn(W01, (), config, pos)
-        return array_splitter.split(value)
-
-
-class VarArray(Array):
-    """
-    Handles variable lengths arrays (i.e. where *arraysize* is '*').
-    """
-    format = 'O'
-
-    def __init__(self, field, base, arraysize, config={}, pos=None):
-        Array.__init__(self, field, config)
-
-        self._base = base
-        self.default = np.array([], dtype=self._base.format)
-
-    def output(self, value, mask):
-        output = self._base.output
-        result = [output(x, m) for x, m in np.broadcast(value, mask)]
-        return u' '.join(result)
-
-    def binparse(self, read):
-        length = self._parse_length(read)
-
-        result = []
-        result_mask = []
-        binparse = self._base.binparse
-        for i in xrange(length):
-            val, mask = binparse(read)
-            result.append(val)
-            result_mask.append(mask)
-        return (np.array(result),
-                np.array(result_mask, dtype='bool'))
-
-    def binoutput(self, value, mask):
-        if value is None or len(value) == 0:
-            return _zero_int
-
-        length = len(value)
-        result = [self._write_length(length)]
-        binoutput = self._base.binoutput
-        for x, m in zip(value, mask):
-            result.append(binoutput(x, m))
-        return _empty_bytes.join(result)
-
-
-class ArrayVarArray(VarArray):
-    """
-    Handles an array of variable-length arrays, i.e. where *arraysize*
-    ends in '*'.
-    """
-    def parse(self, value, config={}, pos=None):
-        if value.strip() == '':
-            return np.array([]), True
-
-        parts = self._splitter(value, config, pos)
-        items = self._base._items
-        parse_parts = self._base.parse_parts
-        if len(parts) % items != 0:
-            vo_raise(E02, (items, len(parts)), config, pos)
-        result = []
-        result_mask = []
-        for i in xrange(0, len(parts), items):
-            value, mask = parse_parts(parts[i:i+items], config, pos)
-            result.append(value)
-            result_mask.append(mask)
-        return np.array(result), np.array(result_mask, dtype='bool')
-
-
-class ScalarVarArray(VarArray):
-    """
-    Handles a variable-length array of numeric scalars.
-    """
-    def parse(self, value, config={}, pos=None):
-        if value.strip() == '':
-            return np.array([]), True
-
-        parts = self._splitter(value, config, pos)
-
-        parse = self._base.parse
-        result = []
-        result_mask = []
-        for x in parts:
-            value, mask = parse(x, config, pos)
-            result.append(value)
-            result_mask.append(mask)
-        return (np.array(result, dtype=self._base.format),
-                np.array(result_mask, dtype='bool'))
-
-
-class NumericArray(Array):
-    """
-    Handles a fixed-length array of numeric scalars.
-    """
-    vararray_type = ArrayVarArray
-
-    def __init__(self, field, base, arraysize, config={}, pos=None):
-        Array.__init__(self, field, config, pos)
-
-        self._base = base
-        self._arraysize = arraysize
-        self.format = "%s%s" % (tuple(arraysize), base.format)
-
-        self._items = 1
-        for dim in arraysize:
-            self._items *= dim
-
-        self._memsize = np.dtype(self.format).itemsize
-        self._bigendian_format = '>' + self.format
-
-        self.default = (
-            np.ones(arraysize, dtype=self._base.format) *
-            self._base.default)
-
-    def parse(self, value, config={}, pos=None):
-        parts = self._splitter(value, config, pos)
-        if len(parts) != self._items:
-            warn_or_raise(E02, E02, (self._items, len(parts)), config, pos)
-        if config.get('pedantic'):
-            return self.parse_parts(parts, config, pos)
-        else:
-            if len(parts) == self._items:
-                pass
-            elif len(parts) > self._items:
-                parts = parts[:self._items]
-            else:
-                parts = (parts +
-                         ([self._base.default] * (self._items - len(parts))))
-            return self.parse_parts(parts, config, pos)
-
-    def parse_parts(self, parts, config={}, pos=None):
-        base_parse = self._base.parse
-        result = []
-        result_mask = []
-        for x in parts:
-            value, mask = base_parse(x, config, pos)
-            result.append(value)
-            result_mask.append(mask)
-        result = np.array(result, dtype=self._base.format).reshape(
-            self._arraysize)
-        result_mask = np.array(result_mask, dtype='bool').reshape(
-            self._arraysize)
-        return result, result_mask
-
-    def output(self, value, mask):
-        base_output = self._base.output
-        value = np.asarray(value)
-        mask = np.asarray(mask)
-        return u' '.join(base_output(x, m) for x, m in
-                         zip(value.flat, mask.flat))
-
-    def binparse(self, read):
-        result = np.fromstring(read(self._memsize),
-                               dtype=self._bigendian_format)[0]
-        result_mask = self._base.is_null(result)
-        return result, result_mask
-
-    def binoutput(self, value, mask):
-        filtered = self._base.filter_array(value, mask)
-        if filtered.dtype.byteorder != '>':
-            filtered = filtered.byteswap()
-        return filtered.tostring()
-
-
-class Numeric(Converter):
-    """
-    The base class for all numeric data types.
-    """
-    array_type = NumericArray
-    vararray_type = ScalarVarArray
-    null = None
-
-    def __init__(self, field, config={}, pos=None):
-        Converter.__init__(self, field, config, pos)
-
-        self._memsize = np.dtype(self.format).itemsize
-        self._bigendian_format = '>' + self.format
-        if field.values.null is not None:
-            self.null = np.asarray(field.values.null, dtype=self.format)
-            self.default = self.null
-            self.is_null = self._is_null
-        else:
-            self.is_null = np.isnan
-
-    def binparse(self, read):
-        result = np.fromstring(read(self._memsize),
-                               dtype=self._bigendian_format)
-        return result[0], self.is_null(result[0])
-
-    def _is_null(self, value):
-        return value == self.null
-
-
-class FloatingPoint(Numeric):
-    """
-    The base class for floating-point datatypes.
-    """
-    default = np.nan
-
-    def __init__(self, field, config={}, pos=None):
-        Numeric.__init__(self, field, config, pos)
-
-        precision = field.precision
-        if precision is None:
-            self._output_format = u'%g'
-        elif precision.startswith("E"):
-            self._output_format = u"%%.%dE" % (int(precision[1:]))
-        elif precision.startswith("F"):
-            self._output_format = u"%%.%dg" % (int(precision[1:]))
-        else:
-            self._output_format = u"%%.%dg" % (int(precision))
-
-        self.nan = np.array(np.nan, self.format)
-
-        if self.null is None:
-            self._null_output = u'NaN'
-            self._null_binoutput = self.binoutput(self.nan, False)
-            self.filter_array = self._filter_nan
-        else:
-            self._null_output = self.output(np.asarray(self.null), False)
-            self._null_binoutput = self.binoutput(np.asarray(self.null), False)
-            self.filter_array = self._filter_null
-
-        if config.get('pedantic'):
-            self.parse = self._parse_pedantic
-        else:
-            self.parse = self._parse_permissive
-
-    def _parse_pedantic(self, value, config={}, pos=None):
-        if value.strip() == '':
-            return self.null, True
-        f = float(value)
-        return f, self.is_null(f)
-
-    def _parse_permissive(self, value, config={}, pos=None):
-        try:
-            f = float(value)
-            return f, self.is_null(f)
-        except ValueError:
-            # IRSA VOTables use the word 'null' to specify empty values,
-            # but this is not defined in the VOTable spec.
-            if value.strip() != '':
-                vo_warn(W30, value, config, pos)
-            return self.null, True
-
-    def output(self, value, mask):
-        if mask:
-            return self._null_output
-        if np.isfinite(value):
-            return self._output_format % value
-        elif np.isnan(value):
-            return u'NaN'
-        elif np.isposinf(value):
-            return u'+InF'
-        elif np.isneginf(value):
-            return u'-InF'
-        # Should never raise
-        vo_raise("Invalid floating point value '%s'" % value)
-
-    def binoutput(self, value, mask):
-        if mask:
-            return self._null_binoutput
-
-        if value.dtype.byteorder != '>':
-            value = value.byteswap()
-        return value.tostring()
-
-    def _filter_nan(self, value, mask):
-        return np.where(mask, np.nan, value)
-
-    def _filter_null(self, value, mask):
-        return np.where(mask, self.null, value)
-
-
-class Double(FloatingPoint):
-    """
-    Handles the double datatype.  Double-precision IEEE
-    floating-point.
-    """
-    format = 'f8'
-
-
-class Float(FloatingPoint):
-    """
-    Handles the float datatype.  Single-precision IEEE floating-point.
-    """
-    format = 'f4'
-
-
-class Integer(Numeric):
-    """
-    The base class for all the integral datatypes.
-    """
-    default = 0
-
-    def __init__(self, field, config={}, pos=None):
-        Numeric.__init__(self, field, config, pos)
-
-    def parse(self, value, config={}, pos=None):
-        mask = False
-        if isinstance(value, basestring):
-            value = value.lower()
-            if value == '':
-                warn_or_raise(W49, W49, (), config, pos)
-                if self.null is not None:
-                    value = self.null
-                else:
-                    value = self.default
-            elif value == 'nan':
-                mask = True
-                if self.null is None:
-                    warn_or_raise(W31, W31, (), config, pos)
-                    value = self.default
-                else:
-                    value = self.null
-            elif value.startswith('0x'):
-                value = int(value[2:], 16)
-            else:
-                value = int(value, 10)
-        else:
-            value = int(value)
-        if self.null is not None and value == self.null:
-            mask = True
-        return value, mask
-
-    def output(self, value, mask):
-        if mask:
-            if self.null is None:
-                warn_or_raise(W31, W31)
-                return u'NaN'
-            return unicode(self.null)
-        return unicode(value)
-
-    def binoutput(self, value, mask):
-        if mask:
-            if self.null is None:
-                vo_raise(W31)
-            else:
-                value = self.null
-        if value.dtype.byteorder != '>':
-            value = value.byteswap()
-        return value.tostring()
-
-    def filter_array(self, value, mask):
-        if np.any(mask):
-            if self.null is not None:
-                return np.where(mask, self.null, value)
-            else:
-                vo_raise(W31)
-        return value
-
-
-class UnsignedByte(Integer):
-    """
-    Handles the unsignedByte datatype.  Unsigned 8-bit integer.
-    """
-    format = 'u1'
-
-
-class Short(Integer):
-    """
-    Handles the short datatype.  Signed 16-bit integer.
-    """
-    format = 'i2'
-
-
-class Int(Integer):
-    """
-    Handles the int datatype.  Signed 32-bit integer.
-    """
-    format = 'i4'
-
-
-class Long(Integer):
-    """
-    Handles the long datatype.  Signed 64-bit integer.
-    """
-    format = 'i8'
-
-
-class ComplexArrayVarArray(VarArray):
-    """
-    Handles an array of variable-length arrays of complex numbers.
-    """
-    def __init__(self, field, base, arraysize, config={}, pos=None):
-        VarArray.__init__(self, field, base, arraysize, config, pos)
-
-    def parse(self, value, config={}, pos=None):
-        if value.strip() == '':
-            return np.array([]), True
-
-        parts = self._splitter(value, config, pos)
-        items = self._base._items
-        parse_parts = self._base.parse_parts
-        if len(parts) % items != 0:
-            vo_raise(E02, (items, len(parts)), config, pos)
-        result = []
-        result_mask = []
-        for i in xrange(0, len(parts), items):
-            value, mask = parse_parts(parts[i:i + items], config, pos)
-            result.append(value)
-            result_mask.append(mask)
-        return np.array(result), np.array(result_mask, dtype='bool')
-
-
-class ComplexVarArray(VarArray):
-    """
-    Handles a variable-length array of complex numbers.
-    """
-    def __init__(self, field, base, arraysize, config={}, pos=None):
-        VarArray.__init__(self, field, base, arraysize, config, pos)
-
-    def parse(self, value, config={}, pos=None):
-        if value.strip() == '':
-            return np.array([]), True
-
-        parts = self._splitter(value, config, pos)
-        parse_parts = self._base.parse_parts
-        result = []
-        result_mask = []
-        for i in xrange(0, len(parts), 2):
-            value = [float(x) for x in parts[i:i + 2]]
-            value, mask = parse_parts(value, config, pos)
-            result.append(value)
-            result_mask.append(mask)
-        return (np.array(result, dtype=self._base.format),
-                np.array(result_mask, dtype='bool'))
-
-
-class ComplexArray(NumericArray):
-    """
-    Handles a fixed-size array of complex numbers.
-    """
-    vararray_type = ComplexArrayVarArray
-
-    def __init__(self, field, base, arraysize, config={}, pos=None):
-        NumericArray.__init__(self, field, base, arraysize, config, pos)
-        self._items *= 2
-
-    def parse(self, value, config={}, pos=None):
-        parts = self._splitter(value, config, pos)
-        if parts == ['']:
-            parts = []
-        return self.parse_parts(parts, config, pos)
-
-    def parse_parts(self, parts, config={}, pos=None):
-        if len(parts) != self._items:
-            vo_raise(E02, (self._items, len(parts)), config, pos)
-        base_parse = self._base.parse_parts
-        result = []
-        result_mask = []
-        for i in xrange(0, self._items, 2):
-            value = [float(x) for x in parts[i:i + 2]]
-            value, mask = base_parse(value, config, pos)
-            result.append(value)
-            result_mask.append(mask)
-        result = np.array(
-            result, dtype=self._base.format).reshape(self._arraysize)
-        result_mask = np.array(
-            result_mask, dtype='bool').reshape(self._arraysize)
-        return result, result_mask
-
-
-class Complex(FloatingPoint, Array):
-    """
-    The base class for complex numbers.
-    """
-    array_type = ComplexArray
-    vararray_type = ComplexVarArray
-    default = np.nan
-
-    def __init__(self, field, config={}, pos=None):
-        FloatingPoint.__init__(self, field, config, pos)
-        Array.__init__(self, field, config, pos)
-
-        self._output_format = self._output_format + " " + self._output_format
-
-    def parse(self, value, config={}, pos=None):
-        if value.strip() == '':
-            return np.nan, True
-        splitter = self._splitter
-        parts = [float(x) for x in splitter(value, config, pos)]
-        if len(parts) != 2:
-            vo_raise(E03, (value,), config, pos)
-        return self.parse_parts(parts, config, pos)
-    _parse_permissive = parse
-    _parse_pedantic = parse
-
-    def parse_parts(self, parts, config={}, pos=None):
-        value = complex(*parts)
-        return value, self.is_null(value)
-
-    def output(self, value, mask):
-        if mask:
-            if self.null is None:
-                return u'NaN'
-            else:
-                value = self.null
-        return self._output_format % (value.real, value.imag)
-
-
-class FloatComplex(Complex):
-    """
-    Handle floatComplex datatype.  Pair of single-precision IEEE
-    floating-point numbers.
-    """
-    format = 'c8'
-
-
-class DoubleComplex(Complex):
-    """
-    Handle doubleComplex datatype.  Pair of double-precision IEEE
-    floating-point numbers.
-    """
-    format = 'c16'
-
-
-class BitArray(NumericArray):
-    """
-    Handles an array of bits.
-    """
-    vararray_type = ArrayVarArray
-
-    def __init__(self, field, base, arraysize, config={}, pos=None):
-        NumericArray.__init__(self, field, base, arraysize, config, pos)
-
-        self._bytes = ((self._items - 1) // 8) + 1
-
-    @staticmethod
-    def _splitter_pedantic(value, config={}, pos=None):
-        return list(re.sub('\s', '', value))
-
-    @staticmethod
-    def _splitter_lax(value, config={}, pos=None):
-        if ',' in value:
-            vo_warn(W01, (), config, pos)
-        return list(re.sub('\s|,', '', value))
-
-    def output(self, value, mask):
-        value = np.asarray(value)
-        mapping = {False: u'0', True: u'1'}
-        return u''.join(mapping[x] for x in value.flat)
-
-    def binparse(self, read):
-        data = read(self._bytes)
-        results = []
-        for byte in data:
-            if not IS_PY3K:
-                byte = ord(byte)
-            for bit_no in range(7, -1, -1):
-                bit = byte & (1 << bit_no)
-                bit = (bit != 0)
-                results.append(bit)
-                if len(results) == self._items:
-                    break
-            if len(results) == self._items:
-                break
-
-        result = np.array(results, dtype='b1').reshape(self._arraysize)
-        result_mask = np.zeros(self._arraysize, dtype='b1')
-        return result, result_mask
-
-    def binoutput(self, value, mask):
-        if np.any(mask):
-            vo_warn(W39)
-
-        value = value.flat
-        bit_no = 7
-        byte = 0
-        bytes = []
-        for v in value:
-            if v:
-                byte |= 1 << bit_no
-            if bit_no == 0:
-                bytes.append(byte)
-                bit_no = 7
-                byte = 0
-            else:
-                bit_no -= 1
-        if bit_no != 7:
-            bytes.append(byte)
-
-        assert len(bytes) == self._bytes
-
-        return struct_pack("%sB" % len(bytes), *bytes)
-
-
-class Bit(Converter):
-    """
-    Handles the bit datatype.
-    """
-    format = 'b1'
-    array_type = BitArray
-    vararray_type = ScalarVarArray
-    default = False
-    binary_one = b'\x08'
-    binary_zero = b'\0'
-
-    def __init__(self, field, config={}, pos=None):
-        Converter.__init__(self, field, config, pos)
-
-    def parse(self, value, config={}, pos=None):
-        mapping = {'1': True, '0': False}
-        if value is False or value.strip() == '':
-            warn_or_raise(W49, W49, (), config, pos)
-            return False, True
-        else:
-            try:
-                return mapping[value], False
-            except KeyError:
-                vo_raise(E04, (value,), config, pos)
-
-    def output(self, value, mask):
-        if mask:
-            vo_warn(W39)
-
-        if value:
-            return u'1'
-        else:
-            return u'0'
-
-    def binparse(self, read):
-        data = read(1)
-        return (ord(data) & 0x8) != 0, False
-
-    def binoutput(self, value, mask):
-        if mask:
-            vo_warn(W39)
-
-        if value:
-            return self.binary_one
-        return self.binary_zero
-
-
-class BooleanArray(NumericArray):
-    """
-    Handles an array of boolean values.
-    """
-    vararray_type = VarArray
-
-    def __init__(self, field, base, arraysize, config={}, pos=None):
-        NumericArray.__init__(self, field, base, arraysize, config, pos)
-
-    def binparse(self, read):
-        data = read(self._items)
-        binparse = self._base.binparse_value
-        result = []
-        result_mask = []
-        for char in data:
-            if not IS_PY3K:
-                char = ord(char)
-            value, mask = binparse(char)
-            result.append(value)
-            result_mask.append(mask)
-        result = np.array(result, dtype='b1').reshape(
-            self._arraysize)
-        result_mask = np.array(result_mask, dtype='b1').reshape(
-            self._arraysize)
-        return result, result_mask
-
-    def binoutput(self, value, mask):
-        binoutput = self._base.binoutput
-        value = np.asarray(value)
-        mask = np.asarray(mask)
-        result = [binoutput(x, m)
-                  for x, m in np.broadcast(value.flat, mask.flat)]
-        return _empty_bytes.join(result)
-
-
-class Boolean(Converter):
-    """
-    Handles the boolean datatype.
-    """
-    format = 'b1'
-    array_type = BooleanArray
-    vararray_type = VarArray
-    default = False
-    binary_question_mark = b'?'
-    binary_true = b'T'
-    binary_false = b'F'
-
-    def __init__(self, field, config={}, pos=None):
-        Converter.__init__(self, field, config, pos)
-
-    def parse(self, value, config={}, pos=None):
-        if value is False:
-            return False, True
-        mapping = {'TRUE'  : (True, False),
-                   'FALSE' : (False, False),
-                   '1'     : (True, False),
-                   '0'     : (False, False),
-                   'T'     : (True, False),
-                   'F'     : (False, False),
-                   '\0'    : (False, True),
-                   ' '     : (False, True),
-                   '?'     : (False, True),
-                   ''      : (False, True)}
-        try:
-            return mapping[value.upper()]
-        except KeyError:
-            vo_raise(E05, (value,), config, pos)
-
-    def output(self, value, mask):
-        if mask:
-            return u'?'
-        if value:
-            return u'T'
-        return u'F'
-
-    def binparse(self, read):
-        value = ord(read(1))
-        return self.binparse_value(value)
-
-    _binparse_mapping = {
-        ord('T')  : (True, False),
-        ord('t')  : (True, False),
-        ord('1')  : (True, False),
-        ord('F')  : (False, False),
-        ord('f')  : (False, False),
-        ord('0')  : (False, False),
-        ord('\0') : (False, True),
-        ord(' ')  : (False, True),
-        ord('?')  : (False, True)}
-
-    def binparse_value(self, value):
-        try:
-            return self._binparse_mapping[value]
-        except KeyError:
-            vo_raise(E05, (value,))
-
-    def binoutput(self, value, mask):
-        if mask:
-            return self.binary_question_mark
-        if value:
-            return self.binary_true
-        return self.binary_false
-
-
-converter_mapping = {
-    'double'        : Double,
-    'float'         : Float,
-    'bit'           : Bit,
-    'boolean'       : Boolean,
-    'unsignedByte'  : UnsignedByte,
-    'short'         : Short,
-    'int'           : Int,
-    'long'          : Long,
-    'floatComplex'  : FloatComplex,
-    'doubleComplex' : DoubleComplex,
-    'char'          : Char,
-    'unicodeChar'   : UnicodeChar }
-
-
-def get_converter(field, config={}, pos=None):
-    """
-    Get an appropriate converter instance for a given field.
-
-    Parameters
-    ----------
-    field : astropy.io.vo.tree.Field
-
-    config : dict, optional
-        Parser configuration dictionary
-
-    pos : tuple
-        Position in the input XML file.  Used for error messages.
-
-    Returns
-    -------
-    converter : astropy.io.vo.converters.Converter
-    """
-    if field.datatype not in converter_mapping:
-        vo_raise(E06, (field.datatype, field.ID), config)
-
-    cls = converter_mapping[field.datatype]
-    converter = cls(field, config, pos)
-
-    arraysize = field.arraysize
-
-    # With numeric datatypes, special things need to happen for
-    # arrays.
-    if (field.datatype not in ('char', 'unicodeChar') and
-        arraysize is not None):
-        if arraysize[-1] == '*':
-            arraysize = arraysize[:-1]
-            last_x = arraysize.rfind('x')
-            if last_x == -1:
-                arraysize = ''
-            else:
-                arraysize = arraysize[:last_x]
-            fixed = False
-        else:
-            fixed = True
-
-        if arraysize != '':
-            arraysize = [int(x) for x in arraysize.split("x")]
-            arraysize.reverse()
-        else:
-            arraysize = []
-
-        if arraysize != []:
-            converter = converter.array_type(
-                field, converter, arraysize, config)
-
-        if not fixed:
-            converter = converter.vararray_type(
-                field, converter, arraysize, config)
-
-    return converter
diff --git a/astropy/io/vo/exceptions.py b/astropy/io/vo/exceptions.py
deleted file mode 100644
index d57ba3f..0000000
--- a/astropy/io/vo/exceptions.py
+++ /dev/null
@@ -1,1382 +0,0 @@
-# -*- coding: utf-8 -*-
-u"""
-.. _warnings:
-
-Warnings
---------
-
-.. note::
-    Most of the following warnings indicate violations of the VOTable
-    specification.  They should be reported to the authors of the
-    tools that produced the VOTable file.
-
-    To control the warnings emitted, use the standard Python
-    :mod:`warnings` module.  Most of these are of the type
-    `VOTableSpecWarning`.
-
-{warnings}
-
-.. _exceptions:
-
-Exceptions
-----------
-
-.. note::
-
-    This is a list of many of the fatal exceptions emitted by vo.table
-    when the file does not conform to spec.  Other exceptions may be
-    raised due to unforeseen cases or bugs in vo.table itself.
-
-{exceptions}
-"""
-
-from __future__ import division, absolute_import
-
-# STDLIB
-import io
-import re
-from warnings import warn
-
-# LOCAL
-from .util import IS_PY3K
-
-
-__all__ = [
-    'warn_or_raise', 'vo_raise', 'vo_reraise', 'vo_warn',
-    'warn_unknown_attrs', 'parse_vowarning', 'VOWarning',
-    'VOTableChangeWarning', 'VOTableSpecWarning',
-    'UnimplementedWarning', 'IOWarning', 'VOTableSpecError']
-
-
-MAX_WARNINGS = 10
-
-
-def _format_message(message, name, config={}, pos=None):
-    if pos is None:
-        pos = ('?', '?')
-    filename = config.get('filename', '?')
-    return '%s:%s:%s: %s: %s' % (filename, pos[0], pos[1], name, message)
-
-
-def _suppressed_warning(warning, config, stacklevel=2):
-    warning_class = type(warning)
-    config.setdefault('_warning_counts', {}).setdefault(warning_class, 0)
-    config['_warning_counts'][warning_class] += 1
-    message_count = config['_warning_counts'][warning_class]
-    if message_count <= MAX_WARNINGS:
-        if message_count == MAX_WARNINGS:
-            warning.formatted_message += \
-                ' (suppressing further warnings of this type...)'
-        warn(warning, stacklevel=stacklevel+1)
-
-
-def warn_or_raise(warning_class, exception_class=None, args=(), config={},
-                  pos=None, stacklevel=1):
-    """
-    Warn or raise an exception, depending on the pedantic setting.
-    """
-    if config.get('pedantic'):
-        if exception_class is None:
-            exception_class = warning_class
-        vo_raise(exception_class, args, config, pos)
-    else:
-        vo_warn(warning_class, args, config, pos, stacklevel=stacklevel+1)
-
-
-def vo_raise(exception_class, args=(), config={}, pos=None):
-    """
-    Raise an exception, with proper position information if available.
-    """
-    raise exception_class(args, config, pos)
-
-
-def vo_reraise(exc, config={}, pos=None, additional=''):
-    """
-    Raise an exception, with proper position information if available.
-
-    Restores the original traceback of the exception, and should only
-    be called within an "except:" block of code.
-    """
-    message = _format_message(str(exc), exc.__class__.__name__, config, pos)
-    if message.split()[0] == str(exc).split()[0]:
-        message = str(exc)
-    if len(additional):
-        message += ' ' + additional
-    exc.args = (message,)
-    raise exc
-
-
-def vo_warn(warning_class, args=(), config={}, pos=None, stacklevel=1):
-    """
-    Warn, with proper position information if available.
-    """
-    warning = warning_class(args, config, pos)
-    _suppressed_warning(warning, config, stacklevel=stacklevel+1)
-
-
-def warn_unknown_attrs(element, attrs, config, pos, good_attr=[], stacklevel=1):
-    for attr in attrs:
-        if attr not in good_attr:
-            vo_warn(W48, (attr, element), config, pos, stacklevel=stacklevel+1)
-
-
-_warning_pat = re.compile(
-    (r":?(?P<nline>[0-9?]+):(?P<nchar>[0-9?]+): " +
-     r"((?P<warning>[WE]\d+): )?(?P<rest>.*)$"))
-
-
-def parse_vowarning(line):
-    """
-    Parses the vo warning string back into its parts.
-    """
-    result = {}
-    match = _warning_pat.search(line)
-    if match:
-        result['warning'] = warning = match.group('warning')
-        if warning is not None:
-            result['is_warning'] = (warning[0].upper() == 'W')
-            result['is_exception'] = (warning[0].upper() == 'E')
-            result['number'] = int(match.group('warning')[1:])
-            result['doc_url'] = "vo/api_exceptions.html#%s" % warning.lower()
-        else:
-            result['is_warning'] = False
-            result['is_exception'] = False
-            result['is_other'] = True
-            result['number'] = None
-            result['doc_url'] = None
-        result['nline'] = int(match.group('nline'))
-        result['nchar'] = int(match.group('nchar'))
-        result['message'] = match.group('rest')
-        result['is_something'] = True
-    else:
-        result['warning'] = None
-        result['is_warning'] = False
-        result['is_exception'] = False
-        result['is_other'] = False
-        result['is_something'] = False
-
-    return result
-
-
-class VOWarning(Warning):
-    """
-    The base class of all VO warnings and exceptions.
-
-    Handles the formatting of the message with a warning or exception
-    code, filename, line and column number.
-    """
-    default_args = ()
-
-    def __init__(self, args, config={}, pos=None):
-        msg = self.message % args
-        self.formatted_message = _format_message(
-            msg, self.__class__.__name__, config, pos)
-        Warning.__init__(self, self.formatted_message)
-
-    def __str__(self):
-        return self.formatted_message
-
-    @classmethod
-    def get_short_name(cls):
-        if len(cls.default_args):
-            return cls.message % cls.default_args
-        return cls.message
-
-
-class VOTableChangeWarning(VOWarning, SyntaxWarning):
-    """
-    A change has been made to the input XML file.
-    """
-    pass
-
-
-class VOTableSpecWarning(VOWarning, SyntaxWarning):
-    """
-    The input XML file violates the spec, but there is an obvious workaround.
-    """
-    pass
-
-
-class UnimplementedWarning(VOWarning, SyntaxWarning):
-    """
-    A feature of the VOTABLE_ spec is not implemented.
-    """
-    pass
-
-
-class IOWarning(VOWarning, RuntimeWarning):
-    """
-    A network or IO error occurred, but was recovered using the cache.
-    """
-    pass
-
-
-class VOTableSpecError(VOWarning, ValueError):
-    """
-    The input XML file violates the spec and there is no good workaround.
-    """
-    pass
-
-
-class W01(VOTableSpecWarning):
-    """
-    The VOTable spec states:
-
-        If a cell contains an array or complex number, it should be
-        encoded as multiple numbers separated by whitespace.
-
-    Many VOTable files in the wild use commas as a separator instead,
-    and ``vo.table`` supports this convention when not in
-    :ref:`pedantic-mode`.
-
-    `vo.table` always outputs files using only spaces, regardless of
-    how they were input.
-
-    **References**: `1.1
-    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#toc-header-35>`__,
-    `1.2
-    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:TABLEDATA>`__
-    """
-
-    message = "Array uses commas rather than whitespace"
-
-
-class W02(VOTableSpecWarning):
-    """
-    XML ids must match the following regular expression::
-
-        ^[A-Za-z_][A-Za-z0-9_\.\-]*$
-
-    The VOTable 1.1 says the following:
-
-        According to the XML standard, the attribute ``ID`` is a
-        string beginning with a letter or underscore (``_``), followed
-        by a sequence of letters, digits, or any of the punctuation
-        characters ``.`` (dot), ``-`` (dash), ``_`` (underscore), or
-        ``:`` (colon).
-
-    However, this is in conflict with the XML standard, which says
-    colons may not be used.  VOTable 1.1's own schema does not allow a
-    colon here.  Therefore, ``vo.table`` disallows the colon.
-
-    VOTable 1.2 corrects this error in the specification.
-
-    **References**: `1.1
-    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:name>`__,
-    `XML Names <http://www.w3.org/TR/REC-xml/#NT-Name>`__
-    """
-
-    message = "%s attribute '%s' is invalid.  Must be a standard XML id"
-    default_args = ('x', 'y')
-
-
-class W03(VOTableChangeWarning):
-    """
-    The VOTable 1.1 spec says the following about ``name`` vs. ``ID``
-    on ``FIELD`` and ``VALUE`` elements:
-
-        ``ID`` and ``name`` attributes have a different role in
-        VOTable: the ``ID`` is meant as a *unique identifier* of an
-        element seen as a VOTable component, while the ``name`` is
-        meant for presentation purposes, and need not to be unique
-        throughout the VOTable document. The ``ID`` attribute is
-        therefore required in the elements which have to be
-        referenced, but in principle any element may have an ``ID``
-        attribute. ... In summary, the ``ID`` is different from the
-        ``name`` attribute in that (a) the ``ID`` attribute is made
-        from a restricted character set, and must be unique throughout
-        a VOTable document whereas names are standard XML attributes
-        and need not be unique; and (b) there should be support in the
-        parsing software to look up references and extract the
-        relevant element with matching ``ID``.
-
-    It is further recommended in the VOTable 1.2 spec:
-
-        While the ``ID`` attribute has to be unique in a VOTable
-        document, the ``name`` attribute need not. It is however
-        recommended, as a good practice, to assign unique names within
-        a ``TABLE`` element. This recommendation means that, between a
-        ``TABLE`` and its corresponding closing ``TABLE`` tag,
-        ``name`` attributes of ``FIELD``, ``PARAM`` and optional
-        ``GROUP`` elements should be all different.
-
-    Since ``vo.table`` requires a unique identifier for each of its
-    columns, ``ID`` is used for the column name when present.
-    However, when ``ID`` is not present, (since it is not required by
-    the specification) ``name`` is used instead.  However, ``name``
-    must be cleansed by replacing invalid characters (such as
-    whitespace) with underscores.
-
-    .. note::
-        This warning does not indicate that the input file is invalid
-        with respect to the VOTable specification, only that the
-        column names in the record array may not match exactly the
-        ``name`` attributes specified in the file.
-
-    **References**: `1.1
-    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:name>`__,
-    `1.2
-    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:name>`__
-    """
-
-    message = "Implictly generating an ID from a name '%s' -> '%s'"
-    default_args = ('x', 'y')
-
-
-class W04(VOTableSpecWarning):
-    """
-    The ``content-type`` attribute must use MIME content-type syntax as
-    defined in `RFC 2046 <http://tools.ietf.org/html/rfc2046>`__.
-
-    The current check for validity is somewhat over-permissive.
-
-    **References**: `1.1
-    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:link>`__,
-    `1.2
-    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:link>`__
-    """
-
-    message = "content-type '%s' must be a valid MIME content type"
-    default_args = ('x',)
-
-
-class W05(VOTableSpecWarning):
-    """
-    The attribute must be a valid URI as defined in `RFC 2396
-    <http://www.ietf.org/rfc/rfc2396.txt>`_.
-    """
-
-    message = "'%s' is not a valid URI"
-    default_args = ('x',)
-
-
-class W06(VOTableSpecWarning):
-    """
-    This warning is emitted when a ``ucd`` attribute does not match
-    the syntax of a `unified content descriptor
-    <http://vizier.u-strasbg.fr/doc/UCD.htx>`__.
-
-    If the VOTable version is 1.2 or later, the UCD will also be
-    checked to ensure it conforms to the controlled vocabulary defined
-    by UCD1+.
-
-    **References**: `1.1
-    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:ucd>`__,
-    `1.2
-    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:ucd>`__
-    """
-
-    message = "Invalid UCD '%s': %s"
-    default_args = ('x', 'explanation')
-
-
-class W07(VOTableSpecWarning):
-    """
-    As astro year field is a Besselian or Julian year matching the
-    regular expression::
-
-        ^[JB]?[0-9]+([.][0-9]*)?$
-
-    Defined in this XML Schema snippet::
-
-        <xs:simpleType  name="astroYear">
-          <xs:restriction base="xs:token">
-            <xs:pattern  value="[JB]?[0-9]+([.][0-9]*)?"/>
-          </xs:restriction>
-        </xs:simpleType>
-    """
-
-    message = "Invalid astroYear in %s: '%s'"
-    default_args = ('x', 'y')
-
-
-class W08(VOTableSpecWarning):
-    """
-    To avoid local-dependent number parsing differences, ``vo.table``
-    may require a string or unicode string where a numeric type may
-    make more sense.
-    """
-
-    if IS_PY3K:
-        message = "'%s' must be a str or bytes object"
-    else:
-        message = "'%s' must be a str or unicode object"
-    default_args = ('x',)
-
-
-class W09(VOTableSpecWarning):
-    """
-    The VOTable specification uses the attribute name ``ID`` (with
-    uppercase letters) to specify unique identifiers.  Some
-    VOTable-producing tools use the more standard lowercase ``id``
-    instead.  ``vo.table`` accepts ``id`` and emits this warning when
-    not in ``pedantic`` mode.
-
-    **References**: `1.1
-    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:name>`__,
-    `1.2
-    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:name>`__
-    """
-
-    message = "ID attribute not capitalized"
-
-
-class W10(VOTableSpecWarning):
-    """
-    The parser has encountered an element that does not exist in the
-    specification, or appears in an invalid context.  Check the file
-    against the VOTable schema (with a tool such as `xmllint
-    <http://xmlsoft.org/xmllint.html>`__.  If the file validates
-    against the schema, and you still receive this warning, this may
-    indicate a bug in ``vo.table``.
-
-    **References**: `1.1
-    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#ToC54>`__,
-    `1.2
-    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#ToC58>`__
-    """
-
-    message = "Unknown tag '%s'.  Ignoring"
-    default_args = ('x',)
-
-
-class W11(VOTableSpecWarning):
-    """
-    Earlier versions of the VOTable specification used a ``gref``
-    attribute on the ``LINK`` element to specify a `GLU reference
-    <http://aladin.u-strasbg.fr/glu/>`__.  New files should
-    specify a ``glu:`` protocol using the ``href`` attribute.
-
-    Since ``vo.table`` does not currently support GLU references, it
-    likewise does not automatically convert the ``gref`` attribute to
-    the new form.
-
-    **References**: `1.1
-    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:link>`__,
-    `1.2
-    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:link>`__
-    """
-
-    message = "The gref attribute on LINK is deprecated in VOTable 1.1"
-
-
-class W12(VOTableChangeWarning):
-    """
-    In order to name the columns of the Numpy record array, each
-    ``FIELD`` element must have either an ``ID`` or ``name`` attribute
-    to derive a name from.  Strictly speaking, according to the
-    VOTable schema, the ``name`` attribute is required.  However, if
-    ``name`` is not present by ``ID`` is, and *pedantic mode* is off,
-    ``vo.table`` will continue without a ``name`` defined.
-
-    **References**: `1.1
-    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:name>`__,
-    `1.2
-    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:name>`__
-    """
-
-    message = (
-        "'%s' element must have at least one of 'ID' or 'name' attributes")
-    default_args = ('x',)
-
-
-class W13(VOTableSpecWarning):
-    """
-    Some VOTable files in the wild use non-standard datatype names.  These
-    are mapped to standard ones using the following mapping::
-
-       string        -> char
-       unicodeString -> unicodeChar
-       int16         -> short
-       int32         -> int
-       int64         -> long
-       float32       -> float
-       float64       -> double
-
-    **References**: `1.1
-    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:datatypes>`__,
-    `1.2
-    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:datatypes>`__
-    """
-
-    message = "'%s' is not a valid VOTable datatype, should be '%s'"
-    default_args = ('x', 'y')
-
-
-# W14: Deprecated
-
-
-class W15(VOTableSpecWarning):
-    """
-    The ``name`` attribute is required on every ``FIELD`` element.
-    However, many VOTable files in the wild omit it and provide only
-    an ``ID`` instead.  In this case, when *pedantic mode* is off,
-    ``vo.table`` will copy the ``name`` attribute to a new ``ID``
-    attribute.
-
-    **References**: `1.1
-    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:name>`__,
-    `1.2
-    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:name>`__
-    """
-
-    message = "%s element missing required 'name' attribute"
-    default_args = ('x',)
-
-# W16: Deprecated
-
-
-class W17(VOTableSpecWarning):
-    """
-    A ``DESCRIPTION`` element can only appear once within its parent
-    element.
-
-    According to the schema, it may only occur once (`1.1
-    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#ToC54>`__,
-    `1.2
-    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#ToC58>`__)
-
-    However, it is a `proposed extension
-    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:addesc>`__
-    to VOTable 1.2.
-    """
-
-    message = "%s element contains more than one DESCRIPTION element"
-    default_args = ('x',)
-
-
-class W18(VOTableSpecWarning):
-    """
-    The number of rows explicitly specified in the ``nrows`` attribute
-    does not match the actual number of rows (``TR`` elements) present
-    in the ``TABLE``.  This may indicate truncation of the file, or an
-    internal error in the tool that produced it.  If *pedantic mode*
-    is off, parsing will proceed, with the loss of some performance.
-
-    **References:** `1.1
-    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#ToC10>`__,
-    `1.2
-    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#ToC10>`__
-    """
-
-    message = 'TABLE specified nrows=%s, but table contains %s rows'
-    default_args = ('x', 'y')
-
-
-class W19(VOTableSpecWarning):
-    """
-    The column fields as defined using ``FIELD`` elements do not match
-    those in the headers of the embedded FITS file.  If *pedantic
-    mode* is off, the embedded FITS file will take precedence.
-    """
-
-    message = (
-        'The fields defined in the VOTable do not match those in the ' +
-        'embedded FITS file')
-
-
-class W20(VOTableSpecWarning):
-    """
-    If no version number is explicitly given in the VOTable file, the
-    parser assumes it is written to the VOTable 1.1 specification.
-    """
-
-    message = 'No version number specified in file.  Assuming %s'
-    default_args = ('1.1',)
-
-
-class W21(UnimplementedWarning):
-    """
-    Unknown issues may arise using ``vo.table`` with VOTable files
-    from a version other than 1.1 or 1.2.
-    """
-
-    message = (
-        'vo.table is designed for VOTable version 1.1 and 1.2, but ' +
-        'this file is %s')
-    default_args = ('x',)
-
-
-class W22(VOTableSpecWarning):
-    """
-    Version 1.0 of the VOTable specification used the ``DEFINITIONS``
-    element to define coordinate systems.  Version 1.1 now uses
-    ``COOSYS`` elements throughout the document.
-
-    **References:** `1.1
-    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:definitions>`__,
-    `1.2
-    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:definitions>`__
-    """
-
-    message = 'The DEFINITIONS element is deprecated in VOTable 1.1.  Ignoring'
-
-
-class W23(IOWarning):
-    """
-    Raised when the VO service database can not be updated (possibly
-    due to a network outage).  This is only a warning, since an older
-    and possible out-of-date VO service database was available
-    locally.
-    """
-
-    message = "Unable to update service information for '%s'"
-    default_args = ('x',)
-
-
-class W24(VOWarning, FutureWarning):
-    """
-    The VO catalog database retrieved from the www is designed for a
-    newer version of vo.table.  This may cause problems or limited
-    features performing service queries.  Consider upgrading vo.table
-    to the latest version.
-    """
-
-    message = "The VO catalog database is for a later version of vo.table"
-
-
-class W25(IOWarning):
-    """
-    A VO service query failed due to a network error or malformed
-    arguments.  Another alternative service may be attempted.  If all
-    services fail, an exception will be raised.
-    """
-
-    message = "'%s' failed with: %s"
-    default_args = ('service', '...')
-
-
-class W26(VOTableSpecWarning):
-    """
-    The given element was not supported inside of the given element
-    until the specified VOTable version, however the version declared
-    in the file is for an earlier version.  These attributes may not
-    be written out to the file.
-    """
-
-    message = "'%s' inside '%s' added in VOTable %s"
-    default_args = ('child', 'parent', 'X.X')
-
-
-class W27(VOTableSpecWarning):
-    """
-    The ``COOSYS`` element was deprecated in VOTABLE version 1.2 in
-    favor of a reference to the Space-Time Coordinate (STC) data
-    model (see `utype
-    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:utype>`__
-    and the IVOA note `referencing STC in VOTable
-    <http://ivoa.net/Documents/latest/VOTableSTC.html>`__.
-    """
-
-    message = "COOSYS deprecated in VOTable 1.2"
-
-
-class W28(VOTableSpecWarning):
-    """
-    The given attribute was not supported on the given element until the
-    specified VOTable version, however the version declared in the file is
-    for an earlier version.  These attributes may not be written out to
-    the file.
-    """
-
-    message = "'%s' on '%s' added in VOTable %s"
-    default_args = ('attribute', 'element', 'X.X')
-
-
-class W29(VOTableSpecWarning):
-    """
-    Some VOTable files specify their version number in the form "v1.0",
-    when the only supported forms in the spec are "1.0".
-
-    **References**: `1.1
-    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#ToC54>`__,
-    `1.2
-    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#ToC58>`__
-    """
-
-    message = "Version specified in non-standard form '%s'"
-    default_args = ('v1.0',)
-
-
-class W30(VOTableSpecWarning):
-    """
-    Some VOTable files write missing floating-point values in non-standard
-    ways, such as "null" and "-".  In non-pedantic mode, any non-standard
-    floating-point literals are treated as missing values.
-
-    **References**: `1.1
-    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:datatypes>`__,
-    `1.2
-    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:datatypes>`__
-    """
-
-    message = "Invalid literal for float '%s'.  Treating as empty."
-    default_args = ('x',)
-
-
-class W31(VOTableSpecWarning):
-    """
-    Since NaN's can not be represented in integer fields directly, a null
-    value must be specified in the FIELD descriptor to support reading
-    NaN's from the tabledata.
-
-    **References**: `1.1
-    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:datatypes>`__,
-    `1.2
-    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:datatypes>`__
-    """
-
-    message = "NaN given in an integral field without a specified null value"
-
-
-class W32(VOTableSpecWarning):
-    """
-    Each field in a table must have a unique ID.  If two or more fields
-    have the same ID, some will be renamed to ensure that all IDs are
-    unique.
-
-    From the VOTable 1.2 spec:
-
-        The ``ID`` and ``ref`` attributes are defined as XML types
-        ``ID`` and ``IDREF`` respectively. This means that the
-        contents of ``ID`` is an identifier which must be unique
-        throughout a VOTable document, and that the contents of the
-        ``ref`` attribute represents a reference to an identifier
-        which must exist in the VOTable document.
-
-    **References**: `1.1
-    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:name>`__,
-    `1.2
-    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:name>`__
-    """
-
-    message = "Duplicate ID '%s' renamed to '%s' to ensure uniqueness"
-    default_args = ('x', 'x_2')
-
-
-class W33(VOTableChangeWarning):
-    """
-    Each field in a table must have a unique name.  If two or more
-    fields have the same name, some will be renamed to ensure that all
-    names are unique.
-
-    **References**: `1.1
-    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:name>`__,
-    `1.2
-    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:name>`__
-    """
-
-    message = "Column name '%s' renamed to '%s' to ensure uniqueness"
-    default_args = ('x', 'x_2')
-
-
-class W34(VOTableSpecWarning):
-    """
-    The attribute requires the value to be a valid XML token, as
-    defined by `XML 1.0
-    <http://www.w3.org/TR/2000/WD-xml-2e-20000814#NT-Nmtoken>`__.
-    """
-
-    message = "'%s' is an invalid token for attribute '%s'"
-    default_args = ('x', 'y')
-
-
-class W35(VOTableSpecWarning):
-    """
-    The ``name`` and ``value`` attributes are required on all ``INFO``
-    elements.
-
-    **References:** `1.1
-    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#ToC54>`__,
-    `1.2
-    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#ToC32>`
-    """
-
-    message = "'%s' attribute required for INFO elements"
-    default_args = ('x',)
-
-
-class W36(VOTableSpecWarning):
-    """
-    If the field specifies a ``null`` value, that value must conform
-    to the given ``datatype``.
-
-    **References:** `1.1
-    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:values>`__,
-    `1.2
-    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:values>`
-    """
-
-    message = "null value '%s' does not match field datatype, setting to 0"
-    default_args = ('x',)
-
-
-class W37(UnimplementedWarning):
-    """
-    The 3 datatypes defined in the VOTable specification and supported by
-    vo.table are ``TABLEDATA``, ``BINARY`` and ``FITS``.
-
-    **References:** `1.1
-    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:data>`__,
-    `1.2
-    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:data>`
-    """
-
-    message = "Unsupported data format '%s'"
-    default_args = ('x',)
-
-
-class W38(VOTableSpecWarning):
-    """
-    The only encoding for local binary data supported by the VOTable
-    specification is base64.
-    """
-
-    message = "Inline binary data must be base64 encoded, got '%s'"
-    default_args = ('x',)
-
-
-class W39(VOTableSpecWarning):
-    """
-    Bit values do not support masking.  This warning is raised upon
-    setting masked data in a bit column.
-
-    **References**: `1.1
-    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:datatypes>`__,
-    `1.2
-    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:datatypes>`__
-    """
-
-    message = "Bit values can not be masked"
-
-
-class W40(VOTableSpecWarning):
-    """
-    This is a terrible hack to support Simple Image Access Protocol
-    results from `<archive.noao.edu>`__.  It creates a field for the
-    coordinate projection type of type "double", which
-    actually contains character data.  We have to hack the field
-    to store character data, or we can't read it in.  A warning
-    will be raised when this happens.
-    """
-
-    message = "'cprojection' datatype repaired"
-
-
-class W41(VOTableSpecWarning):
-    """
-    An XML namespace was specified on the ``VOTABLE`` element, but the
-    namespace does not match what is expected for a ``VOTABLE`` file.
-
-    The ``VOTABLE`` namespace is::
-
-      http://www.ivoa.net/xml/VOTable/vX.X
-
-    where "X.X" is the version number.
-
-    Some files in the wild set the namespace to the location of the
-    VOTable schema, which is not correct and will not pass some
-    validating parsers.
-    """
-
-    message = (
-        "An XML namespace is specified, but is incorrect.  Expected " +
-        "'%s', got '%s'")
-    default_args = ('x', 'y')
-
-
-class W42(VOTableSpecWarning):
-    """
-    The root element should specify a namespace.
-
-    The ``VOTABLE`` namespace is::
-
-        http://www.ivoa.net/xml/VOTable/vX.X
-
-    where "X.X" is the version number.
-    """
-
-    message = "No XML namespace specified"
-
-
-class W43(VOTableSpecWarning):
-    """
-    Referenced elements should be defined before referees.  From the
-    VOTable 1.2 spec:
-
-       In VOTable1.2, it is further recommended to place the ID
-       attribute prior to referencing it whenever possible.
-    """
-
-    message = "%s ref='%s' which has not already been defined"
-    default_args = ('element', 'x',)
-
-
-class W44(VOTableSpecWarning):
-    """
-    ``VALUES`` elements that reference another element should not have
-    their own content.
-
-    From the VOTable 1.2 spec:
-
-        The ``ref`` attribute of a ``VALUES`` element can be used to
-        avoid a repetition of the domain definition, by referring to a
-        previously defined ``VALUES`` element having the referenced
-        ``ID`` attribute. When specified, the ``ref`` attribute
-        defines completely the domain without any other element or
-        attribute, as e.g. ``<VALUES ref="RAdomain"/>``
-    """
-
-    message = "VALUES element with ref attribute has content ('%s')"
-    default_args = ('element',)
-
-
-class W45(VOWarning, ValueError):
-    """
-    The ``content-role`` attribute on the ``LINK`` element must be one of
-    the following::
-
-        query, hints, doc, location
-
-    **References**: `1.1
-    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#ToC54>`__,
-    `1.2
-    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#ToC58>`__
-    """
-
-    message = "content-role attribute '%s' invalid"
-    default_args = ('x',)
-
-
-class W46(VOTableSpecWarning):
-    """
-    The given char or unicode string is too long for the specified
-    field length.
-    """
-
-    message = "%s value is too long for specified length of %s"
-    default_args = ('char or unicode', 'x')
-
-
-class W47(VOTableSpecWarning):
-    """
-    If no arraysize is specified on a char field, the default of '1'
-    is implied, but this is rarely what is intended.
-    """
-
-    message = "Missing arraysize indicates length 1"
-
-
-class W48(VOTableSpecWarning):
-    """
-    The attribute is not defined in the specification.
-    """
-
-    message = "Unknown attribute '%s' on %s"
-    default_args = ('attribute', 'element')
-
-
-class W49(VOTableSpecWarning):
-    """
-    Empty cell illegal for integer fields.
-
-    If a \"null\" value was specified for the cell, it will be used
-    for the value, otherwise, 0 will be used.
-    """
-
-    message = "Empty cell illegal for integer fields."
-
-
-class W50(VOTableSpecWarning):
-    """
-    Invalid unit string as defined in the `Standards for Astronomical
-    Catalogues, Version 2.0
-    <http://cdsarc.u-strasbg.fr/doc/catstd-3.2.htx>`_.
-    """
-
-    message = "Invalid unit string '%s'"
-    default_args = ('x',)
-
-
-class E01(VOWarning, ValueError):
-    """
-    The size specifier for a ``char`` or ``unicode`` field must be
-    only a number followed, optionally, by an asterisk.
-    Multi-dimensional size specifiers are not supported for these
-    datatypes.
-
-    Strings, which are defined as a set of characters, can be
-    represented in VOTable as a fixed- or variable-length array of
-    characters::
-
-        <FIELD name="unboundedString" datatype="char" arraysize="*"/>
-
-    A 1D array of strings can be represented as a 2D array of
-    characters, but given the logic above, it is possible to define a
-    variable-length array of fixed-length strings, but not a
-    fixed-length array of variable-length strings.
-    """
-
-    message = "Invalid size specifier '%s' for a %s field (in field '%s')"
-    default_args = ('x', 'char/unicode', 'y')
-
-
-class E02(VOWarning, ValueError):
-    """
-    The number of array elements in the data does not match that specified
-    in the FIELD specifier.
-    """
-
-    message = (
-        "Incorrect number of elements in array. " +
-        "Expected multiple of %s, got %s")
-    default_args = ('x', 'y')
-
-
-class E03(VOWarning, ValueError):
-    """
-    Complex numbers should be two values separated by whitespace.
-
-    **References**: `1.1
-    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:datatypes>`__,
-    `1.2
-    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:datatypes>`__
-    """
-
-    message = "'%s' does not parse as a complex number"
-    default_args = ('x',)
-
-
-class E04(VOWarning, ValueError):
-    """
-    A ``bit`` array should be a string of '0's and '1's.
-
-    **References**: `1.1
-    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:datatypes>`__,
-    `1.2
-    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:datatypes>`__
-    """
-
-    message = "Invalid bit value '%s'"
-    default_args = ('x',)
-
-
-class E05(VOWarning, ValueError):
-    """
-    A ``boolean`` value should be one of the following strings (case
-    insensitive) in the ``TABLEDATA`` format::
-
-        'TRUE', 'FALSE', '1', '0', 'T', 'F', '\\0', ' ', '?'
-
-    and in ``BINARY`` format::
-
-        'T', 'F', '1', '0', '\\0', ' ', '?'
-
-    **References**: `1.1
-    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:datatypes>`__,
-    `1.2
-    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:datatypes>`__
-    """
-
-    message = "Invalid boolean value '%s'"
-    default_args = ('x',)
-
-
-class E06(VOWarning, ValueError):
-    """
-    The supported datatypes are::
-
-        double, float, bit, boolean, unsignedByte, short, int, long,
-        floatComplex, doubleComplex, char, unicodeChar
-
-    The following non-standard aliases are also supported, but in
-    these case :ref:`W13 <W13>` will be raised::
-
-        string        -> char
-        unicodeString -> unicodeChar
-        int16         -> short
-        int32         -> int
-        int64         -> long
-        float32       -> float
-        float64       -> double
-
-    **References**: `1.1
-    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:datatypes>`__,
-    `1.2
-    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:datatypes>`__
-    """
-
-    message = "Unknown datatype '%s' on field '%s'"
-    default_args = ('x', 'y')
-
-# E07: Deprecated
-
-
-class E08(VOWarning, ValueError):
-    """
-    The ``type`` attribute on the ``VALUES`` element must be either
-    ``legal`` or ``actual``.
-
-    **References**: `1.1
-    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:values>`__,
-    `1.2
-    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:values>`__
-    """
-
-    message = "type must be 'legal' or 'actual', but is '%s'"
-    default_args = ('x',)
-
-
-class E09(VOWarning, ValueError):
-    """
-    The ``MIN``, ``MAX`` and ``OPTION`` elements must always have a
-    ``value`` attribute.
-
-    **References**: `1.1
-    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:values>`__,
-    `1.2
-    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:values>`__
-    """
-
-    message = "'%s' must have a value attribute"
-    default_args = ('x',)
-
-
-class E10(VOWarning, ValueError):
-    """
-    From VOTable 1.1 and later, ``FIELD`` and ``PARAM`` elements must have
-    a ``datatype`` field.
-
-    **References**: `1.1
-    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#elem:FIELD>`__,
-    `1.2
-    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#elem:FIELD>`__
-    """
-
-    message = "'datatype' attribute required on all '%s' elements"
-    default_args = ('FIELD',)
-
-
-class E11(VOWarning, ValueError):
-    """
-    The precision attribute is meant to express the number of significant
-    digits, either as a number of decimal places (e.g. ``precision="F2"`` or
-    equivalently ``precision="2"`` to express 2 significant figures
-    after the decimal point), or as a number of significant figures
-    (e.g. ``precision="E5"`` indicates a relative precision of 10-5).
-
-    It is validated using the following regular expression::
-
-        [EF]?[1-9][0-9]*
-
-    **References**: `1.1
-    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:form>`__,
-    `1.2
-    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:form>`__
-    """
-
-    message = "precision '%s' is invalid"
-    default_args = ('x',)
-
-
-class E12(VOWarning, ValueError):
-    """
-    The width attribute is meant to indicate to the application the
-    number of characters to be used for input or output of the
-    quantity.
-
-    **References**: `1.1
-    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:form>`__,
-    `1.2
-    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:form>`__
-    """
-
-    message = "width must be a positive integer, got '%s'"
-    default_args = ('x',)
-
-
-class E13(VOWarning, ValueError):
-    u"""
-    From the VOTable 1.2 spec:
-
-        A table cell can contain an array of a given primitive type,
-        with a fixed or variable number of elements; the array may
-        even be multidimensional. For instance, the position of a
-        point in a 3D space can be defined by the following::
-
-            <FIELD ID="point_3D" datatype="double" arraysize="3"/>
-
-        and each cell corresponding to that definition must contain
-        exactly 3 numbers. An asterisk (\*) may be appended to
-        indicate a variable number of elements in the array, as in::
-
-            <FIELD ID="values" datatype="int" arraysize="100*"/>
-
-        where it is specified that each cell corresponding to that
-        definition contains 0 to 100 integer numbers. The number may
-        be omitted to specify an unbounded array (in practice up to
-        =~2×10⁹ elements).
-
-        A table cell can also contain a multidimensional array of a
-        given primitive type. This is specified by a sequence of
-        dimensions separated by the ``x`` character, with the first
-        dimension changing fastest; as in the case of a simple array,
-        the last dimension may be variable in length. As an example,
-        the following definition declares a table cell which may
-        contain a set of up to 10 images, each of 64×64 bytes::
-
-            <FIELD ID="thumbs" datatype="unsignedByte" arraysize="64×64×10*"/>
-
-    **References**: `1.1
-    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:dim>`__,
-    `1.2
-    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:dim>`__
-    """
-
-    message = "Invalid arraysize attribute '%s'"
-    default_args = ('x',)
-
-
-class E14(VOWarning, ValueError):
-    """
-    All ``PARAM`` elements must have a ``value`` attribute.
-
-    **References**: `1.1
-    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#elem:FIELD>`__,
-    `1.2
-    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#elem:FIELD>`__
-    """
-
-    message = "value attribute is required for all PARAM elements"
-
-
-class E15(VOWarning, ValueError):
-    """
-    All ``COOSYS`` elements must have an ``ID`` attribute.
-
-    Note that the VOTable 1.1 specification says this attribute is
-    optional, but its corresponding schema indicates it is required.
-
-    In VOTable 1.2, the ``COOSYS`` element is deprecated.
-    """
-
-    message = "ID attribute is required for all COOSYS elements"
-
-
-class E16(VOTableSpecWarning):
-    """
-    The ``system`` attribute on the ``COOSYS`` element must be one of the
-    following::
-
-      'eq_FK4', 'eq_FK5', 'ICRS', 'ecl_FK4', 'ecl_FK5', 'galactic',
-      'supergalactic', 'xy', 'barycentric', 'geo_app'
-
-    **References**: `1.1
-    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#elem:COOSYS>`__
-    """
-
-    message = "Invalid system attribute '%s'"
-    default_args = ('x',)
-
-
-class E17(VOWarning, ValueError):
-    """
-    ``extnum`` attribute must be a positive integer.
-
-    **References**: `1.1
-    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#ToC54>`__,
-    `1.2
-    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#ToC58>`__
-    """
-
-    message = "extnum must be a positive integer"
-
-
-class E18(VOWarning, ValueError):
-    """
-    The ``type`` attribute of the ``RESOURCE`` element must be one of
-    "results" or "meta".
-
-    **References**: `1.1
-    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#ToC54>`__,
-    `1.2
-    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#ToC58>`__
-    """
-
-    message = "type must be 'results' or 'meta', not '%s'"
-    default_args = ('x',)
-
-
-class E19(VOWarning, ValueError):
-    """
-    Raised either when the file doesn't appear to be XML, or the root
-    element is not VOTABLE.
-    """
-
-    message = "File does not appear to be a VOTABLE"
-
-
-class E20(VOTableSpecError):
-    """
-    The table had only *x* fields defined, but the data itself has more
-    columns than that.
-    """
-
-    message = "Data has more columns than are defined in the header (%s)"
-    default_args = ('x',)
-
-
-class E21(VOWarning, ValueError):
-    """
-    The table had *x* fields defined, but the data itself has only *y*
-    columns.
-    """
-
-    message = "Data has fewer columns (%s) than are defined in the header (%s)"
-    default_args = ('x', 'y')
-
-
-def _get_warning_and_exception_classes(prefix):
-    classes = []
-    for key, val in globals().iteritems():
-        if re.match(prefix + "[0-9]{2}", key):
-            classes.append((key, val))
-    classes.sort()
-    return classes
-
-
-def _build_doc_string():
-    from textwrap import dedent
-
-    def generate_set(prefix):
-        classes = _get_warning_and_exception_classes(prefix)
-
-        out = io.StringIO()
-
-        for name, cls in classes:
-            out.write(u".. _%s:\n\n" % name)
-            msg = "%s: %s" % (cls.__name__, cls.get_short_name())
-            if not isinstance(msg, unicode):
-                msg = msg.decode('utf-8')
-            out.write(msg)
-            out.write(u'\n')
-            out.write(u'~' * len(msg))
-            out.write(u'\n\n')
-            doc = cls.__doc__
-            if not isinstance(doc, unicode):
-                doc = doc.decode('utf-8')
-            out.write(dedent(doc))
-            out.write(u'\n\n')
-
-        return out.getvalue()
-
-    warnings = generate_set(u'W')
-    exceptions = generate_set(u'E')
-
-    return {u'warnings': warnings,
-            u'exceptions': exceptions}
-
-__doc__ = __doc__.format(**_build_doc_string())
-
-__all__.extend([x[0] for x in _get_warning_and_exception_classes(u'W')])
-__all__.extend([x[0] for x in _get_warning_and_exception_classes(u'E')])
diff --git a/astropy/io/vo/setup_package.py b/astropy/io/vo/setup_package.py
deleted file mode 100755
index 0e5b811..0000000
--- a/astropy/io/vo/setup_package.py
+++ /dev/null
@@ -1,29 +0,0 @@
-from distutils.core import Extension
-from os.path import join
-
-from astropy import setup_helpers
-
-
-def get_extensions(build_type='release'):
-    VO_DIR = 'astropy/io/vo/src'
-
-    return [Extension(
-        "astropy.io.vo.tablewriter",
-        [join(VO_DIR, "tablewriter.c")],
-        include_dirs=[VO_DIR])]
-
-
-def get_package_data():
-    return {
-        'astropy.io.vo': [
-            'data/ucd1p-words.txt', 'data/*.xsd', 'data/*.dtd'],
-        'astropy.io.vo.tests': [
-            'data/*.xml', 'data/*.gz', 'data/*.json', 'data/*.fits',
-            'data/*.txt'],
-        'astropy.io.vo.validator': [
-            'urls/*.dat.gz']}
-
-
-def get_legacy_alias():
-    return setup_helpers.add_legacy_alias(
-        'vo', 'astropy.io.vo', '0.8')
diff --git a/astropy/io/vo/src/tablewriter.c b/astropy/io/vo/src/tablewriter.c
deleted file mode 100644
index 523d20a..0000000
--- a/astropy/io/vo/src/tablewriter.c
+++ /dev/null
@@ -1,389 +0,0 @@
-/******************************************************************************
- * C extension code for vo.table.
- *
- * Everything in this file has an alternate Python implementation and
- * is included for performance reasons only.
- *
- * This contains a write_tabledata function to quickly write out a Numpy array
- * in TABLEDATA format.
- *
- ******************************************************************************/
-
-#include <Python.h>
-
-/******************************************************************************
- * Convenience macros and functions
- ******************************************************************************/
-#undef  CLAMP
-#define CLAMP(x, low, high)  (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x)))
-
-static Py_ssize_t
-next_power_of_2(Py_ssize_t n)
-{
-    /* Calculate the next-highest power of two */
-    n--;
-    n |= n >> 1;
-    n |= n >> 2;
-    n |= n >> 4;
-    n |= n >> 8;
-    n |= n >> 16;
-    n++;
-
-    return n;
-}
-
-/******************************************************************************
- * Python version compatibility macros
- ******************************************************************************/
-#if PY_MAJOR_VERSION >= 3
-#  define IS_PY3K
-#endif
-
-#ifndef Py_TYPE
-#  define Py_TYPE(o) ((o)->ob_type)
-#endif
-
-/******************************************************************************
- * Write TABLEDATA
- ******************************************************************************/
-
-#define CHAR Py_UNICODE
-
-/*
- * Reallocate the write buffer to the requested size
- */
-static int
-_buffer_realloc(
-        CHAR** buffer, Py_ssize_t* buffer_size, CHAR** x, Py_ssize_t req_size)
-{
-    Py_ssize_t  n       = req_size;
-    CHAR *      new_mem = NULL;
-
-    if (req_size < *buffer_size) {
-        return 0;
-    }
-
-    /* Calculate the next-highest power of two */
-    n = next_power_of_2(n);
-
-    if (n < req_size) {
-        PyErr_SetString(PyExc_MemoryError, "Out of memory for XML text.");
-        return -1;
-    }
-
-    new_mem = realloc((void *)*buffer, n * sizeof(CHAR));
-    if (new_mem == NULL) {
-        PyErr_SetString(PyExc_MemoryError, "Out of memory for XML text.");
-        return -1;
-    }
-
-    *x = (CHAR *)new_mem + (*x - *buffer);
-    *buffer = new_mem;
-    *buffer_size = n;
-
-    return 0;
-}
-
-/*
- * Write *indent* spaces to the buffer
- */
-static int
-_write_indent(CHAR** buffer, Py_ssize_t* buffer_size,
-              CHAR** x, Py_ssize_t indent)
-{
-    if (_buffer_realloc(buffer, buffer_size, x,
-                        (*x - *buffer + indent))) {
-        return 1;
-    }
-
-    for (; indent; --indent) {
-        *(*x)++ = ' ';
-    }
-
-    return 0;
-}
-
-/*
- * Write a string into a buffer.
- */
-static int
-_write_string(CHAR** buffer, Py_ssize_t* buffer_size,
-              CHAR** x, const CHAR* src, const Py_ssize_t len) {
-    if (_buffer_realloc(buffer, buffer_size, x,
-                        (*x - *buffer + len))) {
-        return 1;
-    }
-
-    while (*src != (CHAR)0) {
-        *(*x)++ = *src++;
-    }
-
-    return 0;
-}
-
-/*
- * Write an 8-bit ascii-encoded C string to a Unicode string.
- */
-static int
-_write_cstring(CHAR** buffer, Py_ssize_t* buffer_size,
-               CHAR** x, const char* src, const Py_ssize_t len) {
-    if (_buffer_realloc(buffer, buffer_size, x,
-                        (*x - *buffer + len))) {
-        return 1;
-    }
-
-    while (*src != (char)0) {
-        *(*x)++ = *src++;
-    }
-
-    return 0;
-}
-
-/*
- * Write a TABLEDATA element tree to the given write method.
- *
- * The Python arguments are:
- *
- * *write_method* (callable): A Python callable that takes a unicode
- *    string and writes it to a file or buffer.
- *
- * *array* (numpy structured array): A Numpy record array containing
- *    the data
- *
- * *mask* (numpy array): A Numpy array which is True everywhere a
- *    value is missing.  Must have the same shape as *array*.
- *
- * *converters* (list of callables): A sequence of methods which
- *    convert from the native data types in the columns of *array* to
- *    a unicode string in VOTABLE XML format.  Must have the same
- *    length as the number of columns in *array*.
- *
- * *write_null_values* (boolean): When True, write null values in
- *    their entirety in the table.  When False, just write empty <TD/>
- *    elements when the data is null or missing.
- *
- * *indent* (integer): The number of spaces to indent the table.
- *
- * *buf_size* (integer): The size of the write buffer.
- *
- * Returns None.
- */
-static PyObject*
-write_tabledata(PyObject* self, PyObject *args, PyObject *kwds)
-{
-    /* Inputs */
-    PyObject* write_method = NULL;
-    PyObject* array = NULL;
-    PyObject* mask = NULL;
-    PyObject* converters = NULL;
-    int write_null_values = 0;
-    Py_ssize_t indent = 0;
-    Py_ssize_t buf_size = (Py_ssize_t)1 << 8;
-
-    /* Output buffer */
-    CHAR* buf = NULL;
-    CHAR* x;
-
-    Py_ssize_t nrows = 0;
-    Py_ssize_t ncols = 0;
-    Py_ssize_t i, j;
-    int write_full;
-    int all;
-    PyObject* numpy_module = NULL;
-    PyObject* numpy_all_method = NULL;
-    PyObject* array_row = NULL;
-    PyObject* mask_row = NULL;
-    PyObject* array_val = NULL;
-    PyObject* mask_val = NULL;
-    PyObject* converter = NULL;
-    PyObject* all_masked_obj = NULL;
-    PyObject* str_val = NULL;
-    PyObject* tmp = NULL;
-    CHAR* str_tmp = NULL;
-    Py_ssize_t str_len = 0;
-    PyObject* result = 0;
-
-    if (!PyArg_ParseTuple(args, "OOOOinn:write_tabledata",
-                          &write_method, &array, &mask, &converters,
-                          &write_null_values, &indent, &buf_size)) {
-        goto exit;
-    }
-
-    if (!PyCallable_Check(write_method)) goto exit;
-    if (!PySequence_Check(array)) goto exit;
-    if (!PySequence_Check(mask)) goto exit;
-    if (!PyList_Check(converters)) goto exit;
-    indent = CLAMP(indent, (Py_ssize_t)0, (Py_ssize_t)80);
-    buf_size = CLAMP(buf_size, (Py_ssize_t)1 << 8, (Py_ssize_t)1 << 24);
-
-    if ((numpy_module = PyImport_ImportModule("numpy")) == NULL) goto exit;
-    if ((numpy_all_method = PyObject_GetAttrString(numpy_module, "all"))
-        == NULL) goto exit;
-
-    if ((nrows = PySequence_Size(array)) == -1) goto exit;
-    if ((ncols = PyList_Size(converters)) == -1) goto exit;
-
-    if ((buf = malloc((size_t)buf_size * sizeof(CHAR))) == NULL) goto exit;
-
-    for (i = 0; i < nrows; ++i) {
-        if ((array_row = PySequence_GetItem(array, i)) == NULL) goto exit;
-        if ((mask_row = PySequence_GetItem(mask, i)) == NULL) goto exit;
-
-        x = buf;
-        if (_write_indent(&buf, &buf_size, &x, indent)) goto exit;
-        if (_write_cstring(&buf, &buf_size, &x, " <TR>\n", 6)) goto exit;
-
-        for (j = 0; j < ncols; ++j) {
-            if ((converter = PyList_GET_ITEM(converters, j)) == NULL) goto exit;
-            if ((array_val = PySequence_GetItem(array_row, j)) == NULL) goto exit;
-            if ((mask_val = PySequence_GetItem(mask_row, j)) == NULL) goto exit;
-
-            if (write_null_values) {
-                write_full = 1;
-            } else {
-                if (mask_val == Py_False) {
-                    write_full = 1;
-                } else if (mask_val == Py_True) {
-                    write_full = 0;
-                } else {
-                    if ((all_masked_obj =
-                         PyObject_CallFunctionObjArgs(numpy_all_method, mask_val, NULL))
-                        == NULL) goto exit;
-                    if ((all = PyObject_IsTrue(all_masked_obj)) == -1) {
-                        Py_DECREF(all_masked_obj);
-                        goto exit;
-                    }
-                    Py_DECREF(all_masked_obj);
-
-                    write_full = !all;
-                }
-            }
-
-            if (write_full) {
-                if (_write_indent(&buf, &buf_size, &x, indent)) goto exit;
-                if (_write_cstring(&buf, &buf_size, &x, "  <TD>", 6)) goto exit;
-
-                if ((str_val =
-                     PyObject_CallFunctionObjArgs(converter, array_val, mask_val, NULL))
-                    == NULL) goto exit;
-                if ((str_tmp = PyUnicode_AsUnicode(str_val)) == NULL) {
-                    Py_DECREF(str_val);
-                    goto exit;
-                }
-                str_len = PyUnicode_GetSize(str_val);
-                if (_write_string(&buf, &buf_size, &x, str_tmp, str_len)) {
-                    Py_DECREF(str_val);
-                    goto exit;
-                }
-
-                Py_DECREF(str_val);
-
-                if (_write_cstring(&buf, &buf_size, &x, "</TD>\n", 6)) goto exit;
-            } else {
-                if (_write_indent(&buf, &buf_size, &x, indent)) goto exit;
-                if (_write_cstring(&buf, &buf_size, &x, "  <TD/>\n", 8)) goto exit;
-            }
-
-            Py_DECREF(array_val); array_val = NULL;
-            Py_DECREF(mask_val);  mask_val = NULL;
-        }
-
-        Py_DECREF(array_row); array_row = NULL;
-        Py_DECREF(mask_row);  mask_row = NULL;
-
-        if (_write_indent(&buf, &buf_size, &x, indent)) goto exit;
-        if (_write_cstring(&buf, &buf_size, &x, " </TR>\n", 7)) goto exit;
-
-        /* NULL-terminate the string */
-        *x = (CHAR)0;
-        if ((tmp = PyObject_CallFunction(write_method, "u#", buf, x - buf))
-            == NULL) goto exit;
-        Py_DECREF(tmp);
-    }
-
-    Py_INCREF(Py_None);
-    result = Py_None;
-
- exit:
-    Py_XDECREF(numpy_module);
-    Py_XDECREF(numpy_all_method);
-
-    Py_XDECREF(array_row);
-    Py_XDECREF(mask_row);
-    Py_XDECREF(array_val);
-    Py_XDECREF(mask_val);
-
-    free(buf);
-
-    return result;
-}
-
-/******************************************************************************
- * Module setup
- ******************************************************************************/
-
-static PyMethodDef module_methods[] =
-{
-    {"write_tabledata", (PyCFunction)write_tabledata, METH_VARARGS,
-     "Fast C method to write tabledata"},
-    {NULL}  /* Sentinel */
-};
-
-struct module_state {
-    void* none;
-};
-
-#ifdef IS_PY3K
-static int module_traverse(PyObject* m, visitproc visit, void* arg)
-{
-    return 0;
-}
-
-static int module_clear(PyObject* m)
-{
-    return 0;
-}
-
-static struct PyModuleDef moduledef = {
-    PyModuleDef_HEAD_INIT,
-    "tablewriter",
-    "Fast way to write VOTABLE TABLEDATA",
-    sizeof(struct module_state),
-    module_methods,
-    NULL,
-    module_traverse,
-    module_clear,
-    NULL
-};
-
-#  define INITERROR return NULL
-
-PyMODINIT_FUNC
-PyInit_tablewriter(void)
-#else /* Not PY3K */
-#  define INITERROR return
-
-#  ifndef PyMODINIT_FUNC  /* declarations for DLL import/export */
-#    define PyMODINIT_FUNC void
-#  endif
-
-PyMODINIT_FUNC
-inittablewriter(void)
-#endif
-{
-    PyObject* m;
-
-#ifdef IS_PY3K
-    m = PyModule_Create(&moduledef);
-#else
-    m = Py_InitModule3("tablewriter", module_methods,
-                       "Fast way to write VOTABLE TABLEDATA");
-#endif
-
-    if (m == NULL)
-        INITERROR;
-
-#ifdef IS_PY3K
-    return m;
-#endif
-}
diff --git a/astropy/io/vo/table.py b/astropy/io/vo/table.py
deleted file mode 100644
index 85c7335..0000000
--- a/astropy/io/vo/table.py
+++ /dev/null
@@ -1,234 +0,0 @@
-"""
-This file contains a contains the high-level functions to read a
-VOTable file.
-"""
-
-from __future__ import division, absolute_import
-
-# STDLIB
-import io
-import sys
-import warnings
-
-# LOCAL
-from . import exceptions
-from . import tree
-from ...utils.xml import iterparser
-from ...config import ConfigurationItem
-
-
-__all__ = ['parse', 'parse_single_table', 'validate']
-
-
-PEDANTIC = ConfigurationItem(
-    'pedantic',
-    True,
-    'When True, treat fixable violations of the VOTable spec as exceptions.')
-
-
-def parse(source, columns=None, invalid='exception', pedantic=None,
-          chunk_size=tree.DEFAULT_CHUNK_SIZE, table_number=None,
-          filename=None,
-          _debug_python_based_parser=False):
-    """
-    Parses a VOTABLE_ xml file (or file-like object), and returns a `~astropy.io.vo.tree.VOTable` object.
-
-    Parameters
-    ----------
-    source : str or readable file-like object
-        Path or file object containing a VOTABLE_ xml file.
-
-    columns : sequence of str, optional
-        List of field names to include in the output.  The default is
-        to include all fields.
-
-    invalid : str, optional
-        One of the following values:
-
-            - 'exception': throw an exception when an invalid value is
-              encountered (default)
-
-            - 'mask': mask out invalid values
-
-    pedantic : bool, optional
-        When `True`, raise an error when the file violates the spec,
-        otherwise issue a warning.  Warnings may be controlled using
-        the standard Python mechanisms.  See the `warnings`
-        module in the Python standard library for more information.
-        When not provided, uses the configuration setting
-        `astropy.io.vo.pedantic`, which defaults to True.
-
-    chunk_size : int, optional
-        The number of rows to read before converting to an array.
-        Higher numbers are likely to be faster, but will consume more
-        memory.
-
-    table_number : int, optional
-        The number of table in the file to read in.  If `None`, all
-        tables will be read.  If a number, 0 refers to the first table
-        in the file, and only that numbered table will be parsed and
-        read in.
-
-    filename : str, optional
-        A filename, URL or other identifier to use in error messages.
-        If *filename* is None and *source* is a string (i.e. a path),
-        then *source* will be used as a filename for error messages.
-        Therefore, *filename* is only required when source is a
-        file-like object.
-
-    Returns
-    -------
-    votable : `astropy.io.vo.tree.VOTableFile` object
-
-    See also
-    --------
-    astropy.io.vo.exceptions : The exceptions this function may raise.
-    """
-    invalid = invalid.lower()
-    assert invalid in ('exception', 'mask')
-
-    if pedantic is None:
-        pedantic = PEDANTIC()
-
-    config = {
-        'columns'      :      columns,
-        'invalid'      :      invalid,
-        'pedantic'     :     pedantic,
-        'chunk_size'   :   chunk_size,
-        'table_number' : table_number,
-        'filename'     :     filename}
-
-    if filename is None and isinstance(source, basestring):
-        config['filename'] = source
-
-    with iterparser.get_xml_iterator(
-        source,
-        _debug_python_based_parser=_debug_python_based_parser) as iterator:
-        return tree.VOTableFile(
-            config=config, pos=(1, 1)).parse(iterator, config)
-
-
-def parse_single_table(source, **kwargs):
-    """
-    Parses a VOTABLE_ xml file (or file-like object), reading and returning only the first `~astropy.io.vo.tree.Table` instance.
-
-    See `parse` for a description of the keyword arguments.
-
-    Returns
-    -------
-    votable : `astropy.io.vo.tree.Table` object
-    """
-    if kwargs.get('table_number') is None:
-        kwargs['table_number'] = 0
-
-    votable = parse(source, **kwargs)
-
-    return votable.get_first_table()
-
-
-def validate(filename, output=sys.stdout, xmllint=False):
-    """
-    Prints a validation report for the given file.
-
-    Parameters
-    ----------
-    filename : str path
-        Path to a VOTABLE_ xml file.
-
-    output : writable file-like object, optional
-        Where to output the report.  Defaults to `sys.stdout`.
-        If `None`, the output will be returned as a string.
-
-    xmllint : bool, optional
-        When `True`, also send the file to `xmllint` for schema and
-        DTD validation.  Requires that `xmllint` is installed.  The
-        default is `False`.
-
-    Returns
-    -------
-    is_valid : bool or str
-        Returns `True` if no warnings were found.  If `output` is
-        `None`, the return value will be a string.
-    """
-    import textwrap
-    from . import converters, unit, xmlutil
-    from ...utils.console import print_code_line, color_print
-
-    return_as_str = False
-    if output is None:
-        output = io.StringIO()
-
-    lines = []
-    votable = None
-
-    # This is a special variable used by the Python warnings
-    # infrastructure to keep track of warnings that have already been
-    # seen.  Since we want to get every single warning out of this, we
-    # have to delete all of them first.
-    for module in (exceptions, converters, tree, unit, xmlutil):
-        if hasattr(module, '__warningregistry__'):
-            del module.__warningregistry__
-
-    with io.open(filename, 'rb') as input:
-        with warnings.catch_warnings(record=True) as warning_lines:
-            warnings.resetwarnings()
-            warnings.simplefilter("always", exceptions.VOWarning, append=True)
-            try:
-                votable = parse(input, pedantic=False, filename=filename)
-            except ValueError as e:
-                lines.append(str(e))
-    lines = [str(x.message) for x in warning_lines] + lines
-
-    output.write(u"Validation report for {0}\n\n".format(filename))
-
-    if len(lines):
-        xml_lines = iterparser.xml_readlines(filename)
-
-        for warning in lines:
-            w = exceptions.parse_vowarning(warning)
-
-            if not w['is_something']:
-                output.write(warning)
-                output.write(u'\n\n')
-            else:
-                line = xml_lines[w['nline'] - 1]
-                warning = w['warning']
-                if warning.startswith('W'):
-                    color = 'yellow'
-                else:
-                    color = 'red'
-                color_print(
-                    u'{0:d}: '.format(w['nline']), '',
-                    warning, color,
-                    u': ', '',
-                    textwrap.fill(
-                        w['message'],
-                        initial_indent=u'          ',
-                        subsequent_indent=u'  ').lstrip(),
-                    file=output)
-                print_code_line(line, w['nchar'], file=output)
-            output.write(u'\n')
-    else:
-        output.write(u'astropy.io.vo found no violations.\n\n')
-
-    success = 0
-    if xmllint:
-        from ...utils.xml import validate
-
-        if votable is None:
-            version = "1.1"
-        else:
-            version = votable.version
-        success, stdout, stderr = validate.validate_schema(
-            filename, version)
-
-        if success != 0:
-            output.write(
-                u'xmllint schema violations:\n\n')
-            output.write(stderr)
-        else:
-            output.write(u'xmllint passed\n')
-
-    if return_as_str:
-        return output.getvalue()
-    return len(lines) == 0 and success == 0
diff --git a/astropy/io/vo/tests/converter_test.py b/astropy/io/vo/tests/converter_test.py
deleted file mode 100644
index 9d3edb0..0000000
--- a/astropy/io/vo/tests/converter_test.py
+++ /dev/null
@@ -1,179 +0,0 @@
-# THIRD-PARTY
-import numpy as np
-
-# LOCAL
-from .. import converters
-from .. import exceptions
-from .. import tree
-from ....tests.helper import raises
-
-
- at raises(exceptions.E13)
-def test_invalid_arraysize():
-    field = tree.Field(
-        None, name='broken', datatype='char', arraysize='foo')
-    converters.get_converter(field)
-
-
-def test_oversize_char(recwarn):
-    config = {'pedantic': True}
-    field = tree.Field(
-        None, name='c', datatype='char',
-        config=config)
-    c = converters.get_converter(field, config=config)
-    w = recwarn.pop(exceptions.W47)
-
-    c.parse(u"XXX")
-    w = recwarn.pop(exceptions.W46)
-
-
-def test_char_mask():
-    config = {'pedantic': True}
-    field = tree.Field(
-        None, name='c', datatype='char',
-        config=config)
-    c = converters.get_converter(field, config=config)
-    assert c.output("Foo", True) == ''
-
-
-def test_oversize_unicode(recwarn):
-    config = {'pedantic': True}
-    field = tree.Field(
-        None, name='c2', datatype='unicodeChar',
-        config=config)
-    c = converters.get_converter(field, config=config)
-
-    c.parse(u"XXX")
-    w = recwarn.pop(exceptions.W46)
-
-
-def test_unicode_mask():
-    config = {'pedantic': True}
-    field = tree.Field(
-        None, name='c', datatype='unicodeChar',
-        config=config)
-    c = converters.get_converter(field, config=config)
-    assert c.output(u"Foo", True) == u''
-
-
- at raises(exceptions.E02)
-def test_wrong_number_of_elements():
-    config = {'pedantic': True}
-    field = tree.Field(
-        None, name='c', datatype='int', arraysize='2x3*',
-        config=config)
-    c = converters.get_converter(field, config=config)
-    c.parse("2 3 4 5 6")
-
-
- at raises(ValueError)
-def test_float_mask():
-    config = {'pedantic': True}
-    field = tree.Field(
-        None, name='c', datatype='float',
-        config=config)
-    c = converters.get_converter(field, config=config)
-    assert c.parse('') == (c.null, True)
-    c.parse('null')
-
-
-def test_float_mask_permissive():
-    config = {'pedantic': False}
-    field = tree.Field(
-        None, name='c', datatype='float',
-        config=config)
-    c = converters.get_converter(field, config=config)
-    assert c.parse('null') == (c.null, True)
-
-
- at raises(exceptions.E02)
-def test_complex_array_vararray():
-    config = {'pedantic': True}
-    field = tree.Field(
-        None, name='c', datatype='floatComplex', arraysize='2x3*',
-        config=config)
-    c = converters.get_converter(field, config=config)
-    c.parse("2 3 4 5 6")
-
-
-def test_complex_array_vararray2():
-    config = {'pedantic': True}
-    field = tree.Field(
-        None, name='c', datatype='floatComplex', arraysize='2x3*',
-        config=config)
-    c = converters.get_converter(field, config=config)
-    x = c.parse("")
-    assert len(x[0]) == 0
-
-
-def test_complex_array_vararray():
-    config = {'pedantic': True}
-    field = tree.Field(
-        None, name='c', datatype='doubleComplex', arraysize='2x3*',
-        config=config)
-    c = converters.get_converter(field, config=config)
-    x = c.parse("1 2 3 4 5 6 7 8 9 10 11 12")
-    assert len(x) == 2
-    assert np.all(x[0][0][0] == complex(1, 2))
-
-
-def test_complex_vararray():
-    config = {'pedantic': True}
-    field = tree.Field(
-        None, name='c', datatype='doubleComplex', arraysize='*',
-        config=config)
-    c = converters.get_converter(field, config=config)
-    x = c.parse("1 2 3 4")
-    assert len(x) == 2
-    assert x[0][0] == complex(1, 2)
-
-
- at raises(exceptions.E03)
-def test_complex():
-    config = {'pedantic': True}
-    field = tree.Field(
-        None, name='c', datatype='doubleComplex',
-        config=config)
-    c = converters.get_converter(field, config=config)
-    x = c.parse("1 2 3")
-
-
- at raises(exceptions.E04)
-def test_bit():
-    config = {'pedantic': True}
-    field = tree.Field(
-        None, name='c', datatype='bit',
-        config=config)
-    c = converters.get_converter(field, config=config)
-    x = c.parse("T")
-
-
-def test_bit_mask(recwarn):
-    config = {'pedantic': True}
-    field = tree.Field(
-        None, name='c', datatype='bit',
-        config=config)
-    c = converters.get_converter(field, config=config)
-    c.output(True, True)
-    recwarn.pop(exceptions.W39)
-
-
- at raises(exceptions.E05)
-def test_boolean():
-    config = {'pedantic': True}
-    field = tree.Field(
-        None, name='c', datatype='boolean',
-        config=config)
-    c = converters.get_converter(field, config=config)
-    c.parse('YES')
-
-
- at raises(exceptions.E06)
-def test_invalid_type():
-    config = {'pedantic': True}
-    field = tree.Field(
-        None, name='c', datatype='foobar',
-        config=config)
-    c = converters.get_converter(field, config=config)
-
-
diff --git a/astropy/io/vo/tests/data/regression.bin.tabledata.truth.xml b/astropy/io/vo/tests/data/regression.bin.tabledata.truth.xml
deleted file mode 100644
index b2512a1..0000000
--- a/astropy/io/vo/tests/data/regression.bin.tabledata.truth.xml
+++ /dev/null
@@ -1,303 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Produced with astropy.io.vo version testing
-     http://www.astropy.org/ -->
-<VOTABLE version="1.1" xmlns="http://www.ivoa.net/xml/VOTable/v1.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.ivoa.net/xml/VOTable/v1.1">
- <DESCRIPTION>
-  The VOTable format is an XML standard for the interchange of data
-  represented as a set of tables. In this context, a table is an
-  unordered set of rows, each of a uniform format, as specified in the
-  table metadata. Each row in a table is a sequence of table cells,
-  and each of these contains either a primitive data type, or an array
-  of such primitives. VOTable is derived from the Astrores format [1],
-  itself modeled on the FITS Table format [2]; VOTable was designed to
-  be closer to the FITS Binary Table format.
- </DESCRIPTION>
- <COOSYS ID="J2000" equinox="J2000" system="eq_FK5"/>
- <PARAM ID="wrong_arraysize" arraysize="0" datatype="float" name="wrong_arraysize" value=""/>
- <PARAM ID="INPUT" arraysize="*" datatype="float" name="INPUT" ucd="phys.size;instr.tel" unit="deg" value="0 0">
-  <DESCRIPTION>
-   This is the most interesting parameter in the world, and it drinks
-   Dos Equis
-  </DESCRIPTION>
- </PARAM>
- <INFO ID="QUERY_STATUS" name="QUERY_STATUS" value="OK"/>
- <RESOURCE type="results">
-  <DESCRIPTION>
-   This is a resource description
-  </DESCRIPTION>
-  <PARAM ID="awesome" arraysize="*" datatype="float" name="INPUT" unit="deg" value="0 0"/>
-  <PARAM ID="empty_value" arraysize="*" datatype="char" name="empty_value" value=""/>
-  <LINK href="http://www.foo.com/"/>
-  <TABLE ID="main_table" nrows="5">
-   <DESCRIPTION>
-    This describes the table.
-   </DESCRIPTION>
-   <FIELD ID="string_test" arraysize="*" datatype="char" name="string test"/>
-   <FIELD ID="string_test_2" arraysize="10" datatype="char" name="fixed string test"/>
-   <FIELD ID="unicode_test" arraysize="*" datatype="unicodeChar" name="unicode_test"/>
-   <FIELD ID="fixed_unicode_test" arraysize="10" datatype="unicodeChar" name="unicode test"/>
-   <FIELD ID="string_array_test" arraysize="4" datatype="char" name="string array test"/>
-   <FIELD ID="unsignedByte" datatype="unsignedByte" name="unsignedByte"/>
-   <FIELD ID="short" datatype="short" name="short"/>
-   <FIELD ID="int" datatype="int" name="int">
-    <VALUES ID="int_nulls" null="123456789">
-     <MIN inclusive="no" value="-1000"/>
-     <MAX inclusive="yes" value="1000"/>
-     <OPTION name="bogus" value="whatever"/>
-    </VALUES>
-   </FIELD>
-   <FIELD ID="long" datatype="long" name="long">
-    <VALUES ref="int_nulls"/>
-    <LINK href="http://www.long-integers.com/"/>
-   </FIELD>
-   <FIELD ID="double" datatype="double" name="double"/>
-   <FIELD ID="float" datatype="float" name="float"/>
-   <FIELD ID="array" arraysize="2x2*" datatype="long" name="array">
-    <VALUES null="-1"/>
-   </FIELD>
-   <FIELD ID="bit" datatype="bit" name="bit"/>
-   <FIELD ID="bitarray" arraysize="2x3" datatype="bit" name="bitarray"/>
-   <FIELD ID="bitvararray" arraysize="*" datatype="bit" name="bitvararray"/>
-   <FIELD ID="bitvararray2" arraysize="2x3x*" datatype="bit" name="bitvararray2"/>
-   <FIELD ID="floatComplex" datatype="floatComplex" name="floatComplex"/>
-   <FIELD ID="doubleComplex" datatype="doubleComplex" name="doubleComplex"/>
-   <FIELD ID="doubleComplexArray" arraysize="*" datatype="doubleComplex" name="doubleComplexArray"/>
-   <FIELD ID="doubleComplexArrayFixed" arraysize="2" datatype="doubleComplex" name="doubleComplexArrayFixed"/>
-   <FIELD ID="boolean" datatype="boolean" name="boolean"/>
-   <FIELD ID="booleanArray" arraysize="4" datatype="boolean" name="booleanArray"/>
-   <FIELD ID="nulls" datatype="int" name="nulls">
-    <VALUES null="-9"/>
-   </FIELD>
-   <FIELD ID="nulls_array" arraysize="2x2" datatype="int" name="nulls_array">
-    <VALUES null="-9"/>
-   </FIELD>
-   <FIELD ID="precision1" datatype="double" name="precision1" precision="E3" width="10"/>
-   <FIELD ID="precision2" datatype="double" name="precision2" precision="F3"/>
-   <FIELD ID="doublearray" arraysize="*" datatype="double" name="doublearray">
-    <VALUES null="-1.0"/>
-   </FIELD>
-   <FIELD ID="bitarray2" arraysize="16" datatype="bit" name="bitarray2"/>
-   <PARAM ID="INPUT2" arraysize="*" datatype="float" name="INPUT2" unit="deg" value="0 0">
-    <DESCRIPTION>
-     This is the most interesting parameter in the world, and it
-     drinks Dos Equis
-    </DESCRIPTION>
-   </PARAM>
-   <GROUP>
-    <PARAMref ref="awesome"/>
-   </GROUP>
-   <GROUP>
-    <DESCRIPTION>
-     This should warn of a second description.
-    </DESCRIPTION>
-    <FIELDref ref="boolean"/>
-    <GROUP>
-     <PARAMref ref="awesome"/>
-     <PARAM ID="OUTPUT" datatype="float" name="OUTPUT" value="42"/>
-    </GROUP>
-    <PARAM ID="INPUT3" arraysize="*" datatype="float" name="INPUT3" unit="deg" value="0 0">
-     <DESCRIPTION>
-      This is the most interesting parameter in the world, and it
-      drinks Dos Equis
-     </DESCRIPTION>
-    </PARAM>
-   </GROUP>
-   <LINK href="http://tabledata.org/"/>
-   <DATA>
-    <TABLEDATA>
-     <TR>
-      <TD>String & test</TD>
-      <TD>Fixed stri</TD>
-      <TD>Ceçi n'est pas un pipe</TD>
-      <TD>Ceçi n'est</TD>
-      <TD>ab c</TD>
-      <TD>128</TD>
-      <TD>4096</TD>
-      <TD>268435456</TD>
-      <TD>922337203685477</TD>
-      <TD>1</TD>
-      <TD>1</TD>
-      <TD/>
-      <TD>1</TD>
-      <TD>101101</TD>
-      <TD>1 1 1</TD>
-      <TD/>
-      <TD/>
-      <TD/>
-      <TD/>
-      <TD>0 0 0 0</TD>
-      <TD>T</TD>
-      <TD>T T T T</TD>
-      <TD>0</TD>
-      <TD/>
-      <TD>1.333E+00</TD>
-      <TD>1.33</TD>
-      <TD/>
-      <TD>1111000011110000</TD>
-     </TR>
-     <TR>
-      <TD>String &amp; test</TD>
-      <TD>0123456789</TD>
-      <TD>வணக்கம்</TD>
-      <TD>வணக்கம்</TD>
-      <TD>0123</TD>
-      <TD>0</TD>
-      <TD>0</TD>
-      <TD>2147483647</TD>
-      <TD/>
-      <TD>0</TD>
-      <TD>0</TD>
-      <TD>42 32 12 32</TD>
-      <TD>0</TD>
-      <TD>010011</TD>
-      <TD>0 0 0 0 0</TD>
-      <TD>0 1 0 0 1 0 1 0 1 0 1 0</TD>
-      <TD>0 0</TD>
-      <TD>0 0</TD>
-      <TD>0 0 0 0</TD>
-      <TD>0 -1 -1 -1</TD>
-      <TD>F</TD>
-      <TD>T T F T</TD>
-      <TD/>
-      <TD>0 1 2 3</TD>
-      <TD>1.000E+00</TD>
-      <TD>1</TD>
-      <TD>0 1 +InF -InF NaN 0 -1</TD>
-      <TD>0000000000000000</TD>
-     </TR>
-     <TR>
-      <TD>XXXX</TD>
-      <TD>XXXX</TD>
-      <TD>XXXX</TD>
-      <TD>0123456789</TD>
-      <TD></TD>
-      <TD>233</TD>
-      <TD>-4096</TD>
-      <TD>-268435456</TD>
-      <TD>-1152921504606846976</TD>
-      <TD>+InF</TD>
-      <TD>+InF</TD>
-      <TD>12 34 56 78 87 65 43 21</TD>
-      <TD>1</TD>
-      <TD>111000</TD>
-      <TD>1 0 1 0 1</TD>
-      <TD>1 1 1 1 1 1</TD>
-      <TD>0 -1</TD>
-      <TD>0 -1</TD>
-      <TD>0 0 0 0</TD>
-      <TD>0 0 0 0</TD>
-      <TD>T</TD>
-      <TD>T T ? T</TD>
-      <TD>2</TD>
-      <TD>-9 0 -9 1</TD>
-      <TD>1.000E+34</TD>
-      <TD>1e+34</TD>
-      <TD/>
-      <TD>0000000000000000</TD>
-     </TR>
-     <TR>
-      <TD></TD>
-      <TD></TD>
-      <TD></TD>
-      <TD></TD>
-      <TD></TD>
-      <TD>255</TD>
-      <TD>-1</TD>
-      <TD>268435455</TD>
-      <TD>1152921504606846975</TD>
-      <TD/>
-      <TD>+InF</TD>
-      <TD>-1 23</TD>
-      <TD>0</TD>
-      <TD>000000</TD>
-      <TD/>
-      <TD/>
-      <TD/>
-      <TD/>
-      <TD/>
-      <TD>0 0 0 0</TD>
-      <TD>F</TD>
-      <TD/>
-      <TD/>
-      <TD>0 -9 1 -9</TD>
-      <TD/>
-      <TD/>
-      <TD/>
-      <TD>0000000000000000</TD>
-     </TR>
-     <TR>
-      <TD></TD>
-      <TD></TD>
-      <TD></TD>
-      <TD></TD>
-      <TD></TD>
-      <TD>0</TD>
-      <TD>0</TD>
-      <TD/>
-      <TD/>
-      <TD>-InF</TD>
-      <TD/>
-      <TD>31 -1</TD>
-      <TD>0</TD>
-      <TD>000000</TD>
-      <TD/>
-      <TD/>
-      <TD/>
-      <TD/>
-      <TD/>
-      <TD>0 0 0 0</TD>
-      <TD/>
-      <TD/>
-      <TD/>
-      <TD/>
-      <TD/>
-      <TD/>
-      <TD/>
-      <TD>0000000000000000</TD>
-     </TR>
-    </TABLEDATA>
-   </DATA>
-  </TABLE>
-  <RESOURCE type="results">
-   <TABLE nrows="1" ref="main_table">
-    <DESCRIPTION>
-     This is a referenced table
-    </DESCRIPTION>
-    <DATA>
-     <TABLEDATA>
-      <TR>
-       <TD>String & test</TD>
-       <TD>Fixed stri</TD>
-       <TD>Ceçi n'est pas un pipe</TD>
-       <TD>Ceçi n'est</TD>
-       <TD>ab c</TD>
-       <TD>128</TD>
-       <TD>4096</TD>
-       <TD>268435456</TD>
-       <TD>922337203685477</TD>
-       <TD>1</TD>
-       <TD>1</TD>
-       <TD/>
-       <TD>1</TD>
-       <TD>101101</TD>
-       <TD>1 1 1</TD>
-       <TD/>
-       <TD/>
-       <TD/>
-       <TD/>
-       <TD>0 0 0 0</TD>
-       <TD>T</TD>
-       <TD>T T T T</TD>
-       <TD>0</TD>
-       <TD/>
-       <TD>1.333E+00</TD>
-       <TD>1.33</TD>
-       <TD/>
-       <TD>1111000011110000</TD>
-      </TR>
-     </TABLEDATA>
-    </DATA>
-   </TABLE>
-  </RESOURCE>
- </RESOURCE>
-</VOTABLE>
diff --git a/astropy/io/vo/tests/data/regression.xml b/astropy/io/vo/tests/data/regression.xml
deleted file mode 100644
index 7741536..0000000
--- a/astropy/io/vo/tests/data/regression.xml
+++ /dev/null
@@ -1,297 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<!DOCTYPE VOTABLE SYSTEM "http://us-vo.org/xml/VOTable.dtd">
-<VOTABLE version="1.1"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:noNamespaceSchemaLocation="http://www.ivoa.net/xml/VOTable/v1.1"
- xmlns="http://www.ivoa.net/xml/VOTable/v1.1">
-<DESCRIPTION > <!-- This should get word-wrapped -->
-The VOTable format is an XML standard for the interchange of data represented as a set of tables. In this context, a table is an unordered set of rows, each of a uniform format, as specified in the table metadata. Each row in a table is a sequence of table cells, and each of these contains either a primitive data type, or an array of such primitives. VOTable is derived from the Astrores format [1], itself modeled on the FITS Table format [2]; VOTable was designed to be closer to the FITS Binary Table format.
-</DESCRIPTION>
-<COOSYS ID="J2000" system="eq_FK5" equinox="J2000"/>
-<PARAM datatype="float" name="wrong_arraysize" value="0.000000,0.000000" arraysize="0"/>
-<PARAM datatype="float" name="INPUT" value="0.000000,0.000000" arraysize="*" unit="deg" ucd="phys.size;instr.tel">
-  <DESCRIPTION>This is the most interesting parameter in the world, and it drinks Dos Equis</DESCRIPTION>
-</PARAM>
-<INFO name="QUERY_STATUS" value="OK"/>
-<RESOURCE type="results">
-<DESCRIPTION>
-  This is a resource description
-</DESCRIPTION>
-<PARAM ID="awesome" datatype="float" name="INPUT" value="0.000000,0.000000" arraysize="*" unit="deg"></PARAM>
-<PARAM ID="empty_value" name="empty_value" arraysize="*" datatype="char" value=""/>
-<LINK href="http://www.foo.com/" gref="DECPRECATED">
-  <DESCRIPTION>Really, this link is totally bogus.</DESCRIPTION>
-</LINK>
-<TABLE ID="main_table">
-<DESCRIPTION>
-  This describes the table.
-</DESCRIPTION>
-<GROUP>
-  <PARAMref ref="awesome"/>
-</GROUP>
-<PARAM datatype="float" name="INPUT2" value="0.000000,0.000000" arraysize="*" unit="deg">
-  <DESCRIPTION>This is the most interesting parameter in the world, and it drinks Dos Equis</DESCRIPTION>
-</PARAM>
-<FIELD id="string_test" name="string test" datatype="char" arraysize="*"></FIELD>
-<FIELD ID="string_test" name="fixed string test" datatype="char" arraysize="10"/>
-<FIELD ID="unicode_test" name="unicode_test" datatype="unicodeChar" arraysize="*"/>
-<FIELD ID="fixed_unicode_test" name="unicode test" datatype="unicodeString" arraysize="10"/>
-<LINK href="http://tabledata.org/"/>
-<FIELD ID="string_array_test" name="string array test" datatype="string" arraysize="4*"/>
-<FIELD ID="unsignedByte" name="unsignedByte" datatype="unsignedByte"/>
-<FIELD ID="short" name="short" datatype="short"/>
-<FIELD ID="int" name="int" datatype="int">
-  <VALUES null="123456789" ID="int_nulls">
-    <MIN value="-1000" inclusive="no"/>
-    <MAX value="1000" inclusive="yes"/>
-    <OPTION name="bogus" value="whatever"/>
-  </VALUES>
-  <IGNORE_ME/>
-</FIELD>
-<FIELD ID="long" name="long" datatype="long">
-  <LINK href="http://www.long-integers.com/"/>
-  <VALUES ref="int_nulls"/>
-</FIELD>
-<FIELD ID="double" name="double" datatype="double"/>
-<FIELD ID="float" name="float" datatype="float">
-  <VALUES null=""/>
-</FIELD>
-<FIELD ID="array" name="array" datatype="long" arraysize="2x2*">
-  <VALUES null="-1"/>
-</FIELD>
-<FIELD ID="bit" name="bit" datatype="bit"/>
-<FIELD ID="bitarray" name="bitarray" datatype="bit" arraysize="2x3"/>
-<FIELD ID="bitvararray" name="bitvararray" datatype="bit" arraysize="*"/>
-<FIELD ID="bitvararray2" name="bitvararray2" datatype="bit" arraysize="2x3x*"/>
-<FIELD ID="floatComplex" name="floatComplex" datatype="floatComplex"/>
-<FIELD ID="doubleComplex" name="doubleComplex" datatype="doubleComplex"/>
-<FIELD ID="doubleComplexArray" name="doubleComplexArray" datatype="doubleComplex" arraysize="*"/>
-<FIELD ID="doubleComplexArrayFixed" name="doubleComplexArrayFixed" datatype="doubleComplex" arraysize="2"/>
-<FIELD ID="boolean" name="boolean" datatype="boolean"/>
-<FIELD ID="booleanArray" name="booleanArray" datatype="boolean" arraysize="4"/>
-<FIELD ID="nulls" name="nulls" datatype="int">
-  <VALUES null="-9"/>
-</FIELD>
-<FIELD ID="nulls_array" name="nulls_array" datatype="int" arraysize="2x2">
-  <VALUES null="-9"/>
-</FIELD>
-<FIELD ID="precision1" name="precision1" datatype="double" precision="E3" width="10"/>
-<FIELD ID="precision2" name="precision2" datatype="double" precision="F3"/>
-<FIELD ID="doublearray" name="doublearray" datatype="double" arraysize="*">
-  <VALUES null="-1"/>
-</FIELD>
-<FIELD ID="bitarray2" name="bitarray2" datatype="bit" arraysize="16"/>
-<GROUP>
-  <DESCRIPTION>
-    This is just a group to make sure we can round-trip them.
-  </DESCRIPTION>
-  <DESCRIPTION>
-    This should warn of a second description.
-  </DESCRIPTION>
-  <FIELDref ref="boolean"/>
-  <GROUP>
-    <PARAMref ref="awesome"/>
-    <PARAM datatype="float" name="OUTPUT" value="42"/>
-  </GROUP>
-  <PARAM datatype="float" name="INPUT3" value="0.000000,0.000000" arraysize="*" unit="deg">
-    <DESCRIPTION>This is the most interesting parameter in the world, and it drinks Dos Equis</DESCRIPTION>
-  </PARAM>
-</GROUP>
-<DATA>
-<TABLEDATA>
-<TR>
-  <TD>String & test</TD>
-  <TD>Fixed string long test</TD> <!-- Should truncate -->
-  <TD>Ceçi n'est pas un pipe</TD> <!-- French, n'est-ce pas? -->
-  <TD>Ceçi n'est pas un pipe</TD>
-  <TD>ab cd</TD>
-  <TD>128</TD>
-  <TD>4096</TD>
-  <TD>268435456</TD>
-  <TD>922337203685477</TD>
-  <TD>1.0</TD>
-  <TD encoding="base64">P4AAAA==</TD>
-  <TD>   </TD>
-  <TD>1</TD>
-  <TD>1 0 1 1 0 1</TD>
-  <TD>1 1 1</TD>
-  <TD/>
-  <TD/>
-  <TD/>
-  <TD/>
-  <TD>0 0 0 0</TD>
-  <TD>True</TD>
-  <TD>True True True True</TD>
-  <TD>0</TD>
-  <TD/>
-  <TD>1.333333333333333333333333333333333</TD>
-  <TD>1.333333333333333333333333333333333</TD>
-  <TD/>
-  <TD>1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0</TD>
-</TR>
-<TR>
-  <TD><![CDATA[String & test]]></TD> <!-- Test that & is treated literally inside CDATA -->
-  <TD>0123456789A</TD>
-  <TD>வணக்கம்</TD>
-  <TD>வணக்கம்</TD>
-  <TD>0123456789A</TD>
-  <TD>256</TD> <!-- should overflow to 0 -->
-  <TD>65536</TD> <!-- should overflow to 0-->
-  <TD>2147483647</TD> <!-- overflowing here would raise a Numpy exception -->
-  <TD></TD>
-  <TD>1.0e-325</TD> <!-- underflow to 0 -->
-  <TD>1.0e-46</TD> <!-- underflow to 0 -->
-  <TD>42 32, 12 32</TD>
-  <TD>0</TD>
-  <TD>0 1 0 0 1 1</TD>
-  <TD>0 0 0 0 0</TD>
-  <TD>0 1 0 0 1 0 1 0 1 0 1 0</TD>
-  <TD>0 0</TD>
-  <TD>0 0</TD>
-  <TD>0 0 0 0</TD>
-  <TD>0 -1 -1 -1</TD>
-  <TD>FaLsE</TD>
-  <TD>true true falSE TRUE</TD>
-  <TD>-9</TD>
-  <TD>0 1 2 3</TD>
-  <TD>1.0</TD>
-  <TD>1.0</TD>
-  <TD>0 1 Inf -Inf NaN 0 -1</TD>
-  <TD/>
-</TR>
-<TR>
-  <TD>XXXX </TD>
-  <TD> XXXX </TD> <!-- Shouldn't output extra 0 bytes even though field is wider than string -->
-  <TD> XXXX </TD>
-  <TD>0123456789A</TD>
-  <TD/>
-  <TD>-23</TD> <!-- negative, should wrap around to positive -->
-  <TD>-4096</TD> <!-- negative, perfectly valid -->
-  <TD>-268435456</TD> <!-- negative, perfectly valid -->
-  <TD>-1152921504606846976</TD>  <!-- negative, perfectly valid -->
-  <TD>1.0E309</TD>
-  <TD>1.0E45</TD>
-  <TD>12 34 56 78 87 65 43 21</TD>
-  <TD>1</TD>
-  <TD>1 1 1 0 0 0</TD>
-  <TD>1 0 1 0 1</TD>
-  <TD>1 1 1 1 1 1</TD>
-  <TD>0 -1</TD>
-  <TD>0 -1</TD>
-  <TD>0 0 0 0</TD>
-  <TD>0 0 0 0</TD>
-  <TD>true</TD>
-  <TD>true True ? true</TD>
-  <TD>2</TD>
-  <TD>-9 0 -9 1</TD>
-  <TD>1e34</TD>
-  <TD>1e34</TD>
-  <TD/>
-  <TD/>
-</TR>
-<TR>
-  <TD/>
-  <TD/>
-  <TD/>
-  <TD/>
-  <TD/>
-  <TD>0xff</TD> <!-- hex -->
-  <TD>0xffff</TD> <!-- hex - negative value -->
-  <TD>0xfffffff</TD>
-  <TD>0xfffffffffffffff</TD>
-  <TD>NaN</TD>
-  <TD>+Inf</TD>
-  <TD>NaN, 23</TD>
-  <TD>0</TD>
-  <TD/>
-  <TD/>
-  <TD/>
-  <TD/>
-  <TD>NaN Inf</TD>
-  <TD/>
-  <TD>0 0 0 0</TD>
-  <TD>false</TD>
-  <TD/>
-  <TD/>
-  <TD>0 -9 1 -9</TD>
-  <TD/>
-  <TD/>
-  <TD/>
-  <TD/>
-</TR>
-<TR>
-  <TD/>
-  <TD/>
-  <TD/>
-  <TD/>
-  <TD/>
-  <TD>0x100</TD> <!-- hex, overflow -->
-  <TD>0x10000</TD> <!-- hex, overflow -->
-  <TD/>
-  <TD/>
-  <TD>-Inf</TD>
-  <TD/>
-  <TD>31, -1</TD>
-  <TD/>
-  <TD/>
-  <TD/>
-  <TD/>
-  <TD/>
-  <TD/>
-  <TD/>
-  <TD>0 0 0 0</TD>
-  <TD/>
-  <TD/>
-  <TD>-9</TD>
-  <TD/>
-  <TD/>
-  <TD/>
-  <TD/>
-  <TD/>
-</TR>
-</TABLEDATA>
-</DATA>
-</TABLE>
-<RESOURCE>
- <TABLE ref="main_table">
-   <DESCRIPTION>
-     This is a referenced table
-   </DESCRIPTION>
-   <DATA>
-<TABLEDATA>
-<TR>
-  <TD>String & test</TD>
-  <TD>Fixed string long test</TD> <!-- Should truncate -->
-  <TD>Ceçi n'est pas un pipe</TD> <!-- French, n'est-ce pas? -->
-  <TD>Ceçi n'est pas un pipe</TD>
-  <TD>ab cd</TD>
-  <TD>128</TD>
-  <TD>4096</TD>
-  <TD>268435456</TD>
-  <TD>922337203685477</TD>
-  <TD>1.0</TD>
-  <TD encoding="base64">P4AAAA==</TD>
-  <TD>   </TD>
-  <TD>1</TD>
-  <TD>1 0 1 1 0 1</TD>
-  <TD>1 1 1</TD>
-  <TD/>
-  <TD/>
-  <TD/>
-  <TD/>
-  <TD>0 0 0 0</TD>
-  <TD>True</TD>
-  <TD>True True True True</TD>
-  <TD>0</TD>
-  <TD/>
-  <TD>1.333333333333333333333333333333333</TD>
-  <TD>1.333333333333333333333333333333333</TD>
-  <TD/>
-  <TD>1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0</TD>
-</TR>
-</TABLEDATA>
-</DATA>
-</TABLE>
-</RESOURCE>
-</RESOURCE>
-</VOTABLE>
diff --git a/astropy/io/vo/tests/data/validation.txt b/astropy/io/vo/tests/data/validation.txt
deleted file mode 100644
index b79bf4e..0000000
--- a/astropy/io/vo/tests/data/validation.txt
+++ /dev/null
@@ -1,199 +0,0 @@
-Validation report for /home/mdboom/Work/builds/astropy/build/lib.linux-x86_64-2.7/astropy/io/vo/tests/data/regression.xml
-
-11: W01: Array uses commas rather than whitespace
-<PARAM datatype="float" name="wrong_arraysize" value="0.000000,0.0000…
-^
-
-11: E02: Incorrect number of elements in array. Expected multiple of
-  0, got 2
-<PARAM datatype="float" name="wrong_arraysize" value="0.000000,0.0000…
-^
-
-12: W01: Array uses commas rather than whitespace
-<PARAM datatype="float" name="INPUT" value="0.000000,0.000000" arrays…
-^
-
-20: W01: Array uses commas rather than whitespace
-<PARAM ID="awesome" datatype="float" name="INPUT" value="0.000000,0.0…
-^
-
-22: W11: The gref attribute on LINK is deprecated in VOTable 1.1
-<LINK href="http://www.foo.com/" gref="DECPRECATED">
-^
-
-23: W10: Unknown tag 'DESCRIPTION'.  Ignoring
-  <DESCRIPTION>Really, this link is totally bogus.</DESCRIPTION>
-  ^
-
-32: W01: Array uses commas rather than whitespace
-<PARAM datatype="float" name="INPUT2" value="0.000000,0.000000" array…
-^
-
-35: W09: ID attribute not capitalized
-<FIELD id="string_test" name="string test" datatype="char" arraysize=…
-^
-
-38: W13: 'unicodeString' is not a valid VOTable datatype, should be
-  'unicodeChar'
-<FIELD ID="fixed_unicode_test" name="unicode test" datatype="unicodeS…
-^
-
-40: W13: 'string' is not a valid VOTable datatype, should be 'char'
-<FIELD ID="string_array_test" name="string array test" datatype="stri…
-^
-
-47: W48: Unknown attribute 'value' on OPTION
-    <OPTION name="bogus" value="whatever"/>
-    ^
-
-49: W10: Unknown tag 'IGNORE_ME'.  Ignoring
-  <IGNORE_ME/>
-  ^
-
-89: W17: GROUP element contains more than one DESCRIPTION element
-    This should warn of a second description.
-^
-
-96: W01: Array uses commas rather than whitespace
-  <PARAM datatype="float" name="INPUT3" value="0.000000,0.000000" arr…
-  ^
-
-36: W32: Duplicate ID 'string_test' renamed to 'string_test_2' to
-  ensure uniqueness
-<FIELD ID="string_test" name="fixed string test" datatype="char" arra…
-^
-
-104: W46: char value is too long for specified length of 10
-  <TD>Fixed string long test</TD> <!-- Should truncate -->
-      ^
-
-106: W46: unicodeChar value is too long for specified length of 10
-  <TD>Ceçi n'est pas un pipe</TD>
-      ^
-
-107: W46: char value is too long for specified length of 4
-  <TD>ab cd</TD>
-      ^
-
-126: E02: Incorrect number of elements in array. Expected multiple of
-  4, got 1
-  <TD/>
-  ^
-
-126: W49: Empty cell illegal for integer fields.
-  <TD/>
-  ^
-
-134: W46: char value is too long for specified length of 10
-  <TD>0123456789A</TD>
-      ^
-
-137: W46: char value is too long for specified length of 4
-  <TD>0123456789A</TD>
-      ^
-
-141: W49: Empty cell illegal for integer fields.
-  <TD></TD>
-  ^
-
-144: W01: Array uses commas rather than whitespace
-  <TD>42 32, 12 32</TD>
-      ^
-
-160: E02: Incorrect number of elements in array. Expected multiple of
-  16, got 0
-  <TD/>
-  ^
-
-160: W49: Empty cell illegal for integer fields.
-  <TD/>
-  ^
-
-160: W49: Empty cell illegal for integer fields.
-  <TD/>
-  ^
-
-160: W49: Empty cell illegal for integer fields.
-  <TD/>
-  ^
-
-160: W49: Empty cell illegal for integer fields.
-  <TD/>
-  ^
-
-160: W49: Empty cell illegal for integer fields.
-  <TD/>
-  ^
-
-160: W49: Empty cell illegal for integer fields.
-  <TD/>
-  ^
-
-160: W49: Empty cell illegal for integer fields.
-  <TD/>
-  ^
-
-160: W49: Empty cell illegal for integer fields. (suppressing further
-  warnings of this type...)
-  <TD/>
-  ^
-
-166: W46: unicodeChar value is too long for specified length of 10
-  <TD>0123456789A</TD>
-      ^
-
-190: E02: Incorrect number of elements in array. Expected multiple of
-  16, got 0
-  <TD/>
-  ^
-
-204: W01: Array uses commas rather than whitespace
-  <TD>NaN, 23</TD>
-      ^
-
-206: E02: Incorrect number of elements in array. Expected multiple of
-  6, got 0
-  <TD/>
-  ^
-
-214: E02: Incorrect number of elements in array. Expected multiple of
-  4, got 1
-  <TD/>
-  ^
-
-220: E02: Incorrect number of elements in array. Expected multiple of
-  16, got 0
-  <TD/>
-  ^
-
-234: W01: Array uses commas rather than whitespace
-  <TD>31, -1</TD>
-      ^
-
-236: E02: Incorrect number of elements in array. Expected multiple of
-  6, got 0
-  <TD/>
-  ^
-
-244: E02: Incorrect number of elements in array. Expected multiple of
-  4, got 1
-  <TD/>
-  ^
-
-246: E02: Incorrect number of elements in array. Expected multiple of
-  4, got 1 (suppressing further warnings of this type...)
-  <TD/>
-  ^
-
-264: W46: char value is too long for specified length of 10
-  <TD>Fixed string long test</TD> <!-- Should truncate -->
-      ^
-
-266: W46: unicodeChar value is too long for specified length of 10
-  <TD>Ceçi n'est pas un pipe</TD>
-      ^
-
-267: W46: char value is too long for specified length of 4
-  <TD>ab cd</TD>
-      ^
-
diff --git a/astropy/io/vo/tests/tree_test.py b/astropy/io/vo/tests/tree_test.py
deleted file mode 100644
index 09e6e7a..0000000
--- a/astropy/io/vo/tests/tree_test.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# THIRD-PARTY
-import numpy as np
-
-# LOCAL
-from .. import converters
-from .. import exceptions
-from .. import tree
-from ....tests.helper import raises
-
-
- at raises(exceptions.W07)
-def test_check_astroyear_fail():
-    config = {'pedantic': True}
-    field = tree.Field(None, name='astroyear')
-    tree.check_astroyear('X2100', field, config)
-
-
- at raises(exceptions.W08)
-def test_string_fail():
-    config = {'pedantic': True}
-    tree.check_string(42, 'foo', config)
-
-
-
diff --git a/astropy/io/vo/tests/unit_test.py b/astropy/io/vo/tests/unit_test.py
deleted file mode 100644
index 5ea4dc3..0000000
--- a/astropy/io/vo/tests/unit_test.py
+++ /dev/null
@@ -1,54 +0,0 @@
-from .. import unit
-
-
-def test_units():
-    strings = [
-        # These first few are from the spec document itself
-        ('mW/m2'       , True),
-        ('0.1nm'       , True),
-        ('solMass3/2'  , False),
-        ('[solMass]'   , True),
-        ('0.1 nm'      , False),
-        ('km/s'        , True),
-        ('km / s'      , False),
-        ('km s-1.'     , False),
-        ('10pix/nm'    , True),
-        ('pix/0.1nm'   , False),
-        ('pix/(0.1nm)' , False),
-        ('1.5x10+11m'  , True),
-        ('kW.h'        , True),
-        ('kWh'         , False),
-        ('m2'          , True),
-        ('uarcsec'     , True),
-
-        # These are additional tests
-        ('w'                  , False),
-        ('+1.0m/s'            , True),
-        ('1.0x10+11m/s+10+11' , True),
-        ('mm'                 , True),
-        ('Om'                 , False)
-        ]
-
-    def run(args):
-        s, correct = args
-        print s, correct
-        assert unit.is_unit(s) == correct
-
-    for s, correct in strings:
-        yield run, (s, correct)
-
-
-def test_basic_units():
-    def run(args):
-        prefix, u = args
-        print prefix, u
-        assert unit.is_unit(prefix + u)
-        assert unit.is_unit('[' + prefix + u + ']')
-
-    for u in unit.unit_names:
-        yield run, ('', u)
-
-    for p in unit.unit_prefixes:
-        for u in unit.unit_names:
-            yield run, (p, u)
-
diff --git a/astropy/io/vo/tests/vo_test.py b/astropy/io/vo/tests/vo_test.py
deleted file mode 100644
index 24db211..0000000
--- a/astropy/io/vo/tests/vo_test.py
+++ /dev/null
@@ -1,795 +0,0 @@
-"""
-This is a set of regression tests for vo.
-"""
-
-from __future__ import absolute_import, print_function
-
-# STDLIB
-import difflib
-from distutils import version
-import glob
-import io
-import os
-import shutil
-import subprocess
-import sys
-import tempfile
-import warnings
-
-# THIRD-PARTY
-from numpy.testing import assert_array_equal
-import numpy as np
-
-# LOCAL
-from ..table import parse, parse_single_table, validate
-from .. import tree
-from ..util import IS_PY3K
-from ..exceptions import VOTableSpecError, VOWarning
-from ..xmlutil import validate_schema
-from ....config import get_data_filename, get_data_fileobj, get_data_filenames
-from ....tests.helper import pytest, raises
-from ....utils.compat import gzip
-
-numpy_has_complex_bug = (
-    version.LooseVersion(np.__version__) < version.LooseVersion('1.5')
-    )
-
-join = os.path.join
-
-
-# Update this to use py.test's tmpdir functionality
-def setup_module():
-    global TMP_DIR
-    TMP_DIR = tempfile.mkdtemp()
-
-
-def teardown_module():
-    shutil.rmtree(TMP_DIR)
-
-
-def assert_validate_schema(filename):
-    if sys.platform.startswith('win'):
-        return
-
-    try:
-        rc, stdout, stderr = validate_schema(filename, '1.1')
-    except OSError:
-        # If xmllint is not installed, we want the test to pass anyway
-        return
-    assert rc == 0, 'File did not validate against VOTable schema'
-
-
-def test_parse_single_table():
-    table = parse_single_table(
-        get_data_filename('data/regression.xml'),
-        pedantic=False)
-    assert isinstance(table, tree.Table)
-    assert len(table.array) == 5
-
-
-def test_parse_single_table2():
-    table2 = parse_single_table(
-        get_data_filename('data/regression.xml'),
-        table_number=1,
-        pedantic=False)
-    assert isinstance(table2, tree.Table)
-    assert len(table2.array) == 1
-    assert len(table2.array.dtype.names) == 28
-
-
- at raises(IndexError)
-def test_parse_single_table3():
-    table2 = parse_single_table(
-        get_data_filename('data/regression.xml'),
-        table_number=2, pedantic=False)
-
-
-def _test_regression(_python_based=False):
-    # Read the VOTABLE
-    votable = parse(
-        get_data_filename('data/regression.xml'),
-        pedantic=False,
-        _debug_python_based_parser=_python_based)
-    table = votable.get_first_table()
-
-    assert table.array.dtype == [
-        (('string test', 'string_test'), '|O8'),
-        (('fixed string test', 'string_test_2'), '|S10'),
-        ('unicode_test', '|O8'),
-        (('unicode test', 'fixed_unicode_test'), '<U10'),
-        (('string array test', 'string_array_test'), '|S4'),
-        ('unsignedByte', '|u1'),
-        ('short', '<i2'),
-        ('int', '<i4'),
-        ('long', '<i8'),
-        ('double', '<f8'),
-        ('float', '<f4'),
-        ('array', '|O8'),
-        ('bit', '|b1'),
-        ('bitarray', '|b1', (3, 2)),
-        ('bitvararray', '|O8'),
-        ('bitvararray2', '|O8'),
-        ('floatComplex', '<c8'),
-        ('doubleComplex', '<c16'),
-        ('doubleComplexArray', '|O8'),
-        ('doubleComplexArrayFixed', '<c16', (2,)),
-        ('boolean', '|b1'),
-        ('booleanArray', '|b1', (4,)),
-        ('nulls', '<i4'),
-        ('nulls_array', '<i4', (2, 2)),
-        ('precision1', '<f8'),
-        ('precision2', '<f8'),
-        ('doublearray', '|O8'),
-        ('bitarray2', '|b1', (16,))
-        ]
-
-    votable.to_xml(join(TMP_DIR, "regression.tabledata.xml"),
-                   _debug_python_based_parser=_python_based)
-    assert_validate_schema(join(TMP_DIR, "regression.tabledata.xml"))
-    votable.get_first_table().format = 'binary'
-    # Also try passing a file handle
-    with open(join(TMP_DIR, "regression.binary.xml"), "wb") as fd:
-        votable.to_xml(fd, _debug_python_based_parser=_python_based)
-    assert_validate_schema(join(TMP_DIR, "regression.binary.xml"))
-    # Also try passing a file handle
-    with open(join(TMP_DIR, "regression.binary.xml"), "rb") as fd:
-        votable2 = parse(fd, pedantic=False,
-                         _debug_python_based_parser=_python_based)
-    votable2.get_first_table().format = 'tabledata'
-    votable2.to_xml(join(TMP_DIR, "regression.bin.tabledata.xml"),
-                    _astropy_version="testing",
-                    _debug_python_based_parser=_python_based)
-    assert_validate_schema(join(TMP_DIR, "regression.bin.tabledata.xml"))
-
-    with io.open(
-        get_data_filename('data/regression.bin.tabledata.truth.xml'),
-        'rt', encoding='utf-8') as fd:
-        truth = fd.readlines()
-    with io.open(
-        join(TMP_DIR, "regression.bin.tabledata.xml"),
-        'rt', encoding='utf-8') as fd:
-        output = fd.readlines()
-
-    # If the lines happen to be different, print a diff
-    # This is convenient for debugging
-    for line in difflib.unified_diff(truth, output):
-        sys.stdout.write(
-            line.
-            encode('unicode_escape').
-            replace('\\n', '\n'))
-
-    assert truth == output
-
-    # Test implicit gzip saving
-    votable2.to_xml(
-        join(TMP_DIR, "regression.bin.tabledata.xml.gz"),
-        _astropy_version="testing",
-        _debug_python_based_parser=_python_based)
-    with gzip.GzipFile(
-        join(TMP_DIR, "regression.bin.tabledata.xml.gz"), 'rb') as gzfd:
-        output = gzfd.readlines()
-    output = [x.decode('utf-8').rstrip() for x in output]
-    truth = [x.rstrip() for x in truth]
-
-    assert truth == output
-
-
-def test_regression():
-    _test_regression(False)
-
-
-def test_regression_python_based_parser():
-    _test_regression(True)
-
-
-class TestFixups:
-    def setup_class(self):
-        self.table = parse(
-            get_data_filename('data/regression.xml'),
-            pedantic=False).get_first_table()
-        self.array = self.table.array
-        self.mask = self.table.mask
-
-    def test_implicit_id(self):
-        assert_array_equal(self.array['string_test_2'],
-                           self.array['fixed string test'])
-
-
-class TestReferences:
-    def setup_class(self):
-        self.votable = parse(
-            get_data_filename('data/regression.xml'),
-            pedantic=False)
-        self.table = self.votable.get_first_table()
-        self.array = self.table.array
-        self.mask = self.table.mask
-
-    def test_fieldref(self):
-        fieldref = self.table.groups[1].entries[0]
-        assert isinstance(fieldref, tree.FieldRef)
-        assert fieldref.get_ref().name == 'boolean'
-        assert fieldref.get_ref().datatype == 'boolean'
-
-    def test_paramref(self):
-        paramref = self.table.groups[0].entries[0]
-        assert isinstance(paramref, tree.ParamRef)
-        assert paramref.get_ref().name == 'INPUT'
-        assert paramref.get_ref().datatype == 'float'
-
-    def test_iter_fields_and_params_on_a_group(self):
-        assert len(list(self.table.groups[1].iter_fields_and_params())) == 2
-
-    def test_iter_groups_on_a_group(self):
-        assert len(list(self.table.groups[1].iter_groups())) == 1
-
-    def test_iter_groups(self):
-        # Because of the ref'd table, there are more logical groups
-        # than actually exist in the file
-        assert len(list(self.votable.iter_groups())) == 6
-
-    def test_ref_table(self):
-        tables = list(self.votable.iter_tables())
-        for x, y in zip(tables[0].array[0], tables[1].array[0]):
-            assert_array_equal(x, y)
-
-    def test_iter_coosys(self):
-        assert len(list(self.votable.iter_coosys())) == 1
-
-
-def test_select_columns_by_index():
-    columns = [0, 5, 13]
-    table = parse(
-        get_data_filename('data/regression.xml'),
-        pedantic=False, columns=columns).get_first_table()
-    array = table.array
-    mask = table.mask
-    assert array['string_test'][0] == b"String & test"
-    columns = ['string_test', 'unsignedByte', 'bitarray']
-    for c in columns:
-        assert not np.all(mask[c])
-    assert np.all(mask['unicode_test'])
-
-
-def test_select_columns_by_name():
-    columns = ['string_test', 'unsignedByte', 'bitarray']
-    table = parse(
-        get_data_filename('data/regression.xml'),
-        pedantic=False, columns=columns).get_first_table()
-    array = table.array
-    mask = table.mask
-    assert array['string_test'][0] == b"String & test"
-    for c in columns:
-        assert not np.all(mask[c])
-    assert np.all(mask['unicode_test'])
-
-
-class TestParse:
-    def setup_class(self):
-        self.table = parse(
-            get_data_filename('data/regression.xml'),
-            pedantic=False).get_first_table()
-        self.array = self.table.array
-        self.mask = self.table.mask
-
-    def test_string_test(self):
-        assert issubclass(self.array['string_test'].dtype.type,
-                          np.object_)
-        assert_array_equal(
-            self.array['string_test'],
-            [b'String & test', b'String & test', b'XXXX',
-             b'', b''])
-
-    def test_fixed_string_test(self):
-        assert issubclass(self.array['string_test_2'].dtype.type,
-                          np.string_)
-        assert_array_equal(
-            self.array['string_test_2'],
-            [b'Fixed stri', b'0123456789', b'XXXX', b'', b''])
-
-    def test_unicode_test(self):
-        assert issubclass(self.array['unicode_test'].dtype.type,
-                          np.object_)
-        assert_array_equal(self.array['unicode_test'],
-                           [u"Ce\xe7i n'est pas un pipe",
-                            u'\u0bb5\u0ba3\u0b95\u0bcd\u0b95\u0bae\u0bcd',
-                            u'XXXX', u'', u''])
-
-    def test_fixed_unicode_test(self):
-        assert issubclass(self.array['fixed_unicode_test'].dtype.type,
-                          np.unicode_)
-        assert_array_equal(self.array['fixed_unicode_test'],
-                           [u"Ce\xe7i n'est",
-                            u'\u0bb5\u0ba3\u0b95\u0bcd\u0b95\u0bae\u0bcd',
-                            u'0123456789', u'', u''])
-
-    def test_unsignedByte(self):
-        assert issubclass(self.array['unsignedByte'].dtype.type,
-                          np.uint8)
-        assert_array_equal(self.array['unsignedByte'],
-                           [128, 0, 233, 255, 0])
-        assert not np.any(self.mask['unsignedByte'])
-
-    def test_short(self):
-        assert issubclass(self.array['short'].dtype.type,
-                          np.int16)
-        assert_array_equal(self.array['short'],
-                           [4096, 0, -4096, -1, 0])
-        assert not np.any(self.mask['short'])
-
-    def test_int(self):
-        assert issubclass(self.array['int'].dtype.type,
-                          np.int32)
-        assert_array_equal(
-            self.array['int'],
-            [268435456, 2147483647, -268435456, 268435455, 123456789])
-        assert_array_equal(self.mask['int'],
-                           [False, False, False, False, True])
-
-    def test_long(self):
-        assert issubclass(self.array['long'].dtype.type,
-                          np.int64)
-        assert_array_equal(
-            self.array['long'],
-            [922337203685477, 123456789, -1152921504606846976,
-             1152921504606846975, 123456789])
-        assert_array_equal(self.mask['long'],
-                           [False, True, False, False, True])
-
-    def test_double(self):
-        assert issubclass(self.array['double'].dtype.type,
-                          np.float64)
-        assert_array_equal(self.array['double'],
-                           [1.0, 0.0, np.inf, np.nan, -np.inf])
-        assert_array_equal(self.mask['double'],
-                           [False, False, False, True, False])
-
-    def test_float(self):
-        assert issubclass(self.array['float'].dtype.type,
-                          np.float32)
-        assert_array_equal(self.array['float'],
-                           [1.0, 0.0, np.inf, np.inf, np.nan])
-        assert_array_equal(self.mask['float'],
-                           [False, False, False, False, True])
-
-    def test_array(self):
-        assert issubclass(self.array['array'].dtype.type,
-                          np.object_)
-        match = [[],
-                 [[42, 32], [12, 32]],
-                 [[12, 34], [56, 78], [87, 65], [43, 21]],
-                 [[-1, 23]],
-                 [[31, -1]]]
-        for a, b in zip(self.array['array'], match):
-            # assert issubclass(a.dtype.type, np.int64)
-            # assert a.shape[1] == 2
-            for a0, b0 in zip(a, b):
-                assert issubclass(a0.dtype.type, np.int64)
-                assert_array_equal(a0, b0)
-        assert self.mask['array'][3][0][0]
-        assert self.mask['array'][4][0][1]
-
-    def test_bit(self):
-        assert issubclass(self.array['bit'].dtype.type,
-                          np.bool_)
-        assert_array_equal(self.array['bit'],
-                           [True, False, True, False, False])
-
-    def test_bit_mask(self):
-        assert_array_equal(self.mask['bit'],
-                           [False, False, False, False, True])
-
-    def test_bitarray(self):
-        assert issubclass(self.array['bitarray'].dtype.type,
-                          np.bool_)
-        self.array['bitarray'].shape == (5, 3, 2)
-        assert_array_equal(self.array['bitarray'],
-                           [[[ True, False],
-                             [ True,  True],
-                             [False,  True]],
-
-                            [[False,  True],
-                             [False, False],
-                             [ True,  True]],
-
-                            [[ True,  True],
-                             [ True, False],
-                             [False, False]],
-
-                            [[False, False],
-                             [False, False],
-                             [False, False]],
-
-                            [[False, False],
-                             [False, False],
-                             [False, False]]])
-
-    def test_bitarray_mask(self):
-        assert_array_equal(self.mask['bitarray'],
-                           [[[False, False],
-                             [False, False],
-                             [False, False]],
-
-                            [[False, False],
-                             [False, False],
-                             [False, False]],
-
-                            [[False, False],
-                             [False, False],
-                             [False, False]],
-
-                            [[ True,  True],
-                             [ True,  True],
-                             [ True,  True]],
-
-                            [[ True,  True],
-                             [ True,  True],
-                             [ True,  True]]])
-
-    def test_bitvararray(self):
-        assert issubclass(self.array['bitvararray'].dtype.type,
-                          np.object_)
-        match = [[ True,  True,  True],
-                 [False, False, False, False, False],
-                 [ True, False,  True, False,  True],
-                 [], []]
-        for a, b in zip(self.array['bitvararray'], match):
-            assert_array_equal(a, b)
-        match_mask = [[False, False, False],
-                      [False, False, False, False, False],
-                      [False, False, False, False, False],
-                      True, True]
-        for a, b in zip(self.mask['bitvararray'], match_mask):
-            assert_array_equal(a, b)
-
-    def test_bitvararray2(self):
-        assert issubclass(self.array['bitvararray2'].dtype.type,
-                          np.object_)
-        match = [[],
-
-                 [[[False,  True],
-                   [False, False],
-                   [ True, False]],
-                  [[ True, False],
-                   [ True, False],
-                   [ True, False]]],
-
-                 [[[ True,  True],
-                   [ True,  True],
-                   [ True,  True]]],
-
-                 [],
-
-                 []]
-        for a, b in zip(self.array['bitvararray2'], match):
-            for a0, b0 in zip(a, b):
-                assert a0.shape == (3, 2)
-                assert issubclass(a0.dtype.type, np.bool_)
-                assert_array_equal(a0, b0)
-
-    @pytest.mark.xfail('numpy_has_complex_bug')
-    def test_floatComplex(self):
-        assert issubclass(self.array['floatComplex'].dtype.type,
-                          np.complex64)
-        assert_array_equal(self.array['floatComplex'],
-                           [np.nan+0j, 0+0j, 0+-1j, np.nan+0j, np.nan+0j])
-        assert_array_equal(self.mask['floatComplex'],
-                           [True, False, False, True, True])
-
-    @pytest.mark.xfail('numpy_has_complex_bug')
-    def test_doubleComplex(self):
-        assert issubclass(self.array['doubleComplex'].dtype.type,
-                          np.complex128)
-        assert_array_equal(
-            self.array['doubleComplex'],
-            [np.nan+0j, 0+0j, 0+-1j, np.nan+(np.inf*1j), np.nan+0j])
-        assert_array_equal(self.mask['doubleComplex'],
-                           [True, False, False, True, True])
-
-    @pytest.mark.xfail('numpy_has_complex_bug')
-    def test_doubleComplexArray(self):
-        assert issubclass(self.array['doubleComplexArray'].dtype.type,
-                          np.object_)
-        assert ([len(x) for x in self.array['doubleComplexArray']] ==
-                [0, 2, 2, 0, 0])
-
-    def test_boolean(self):
-        assert issubclass(self.array['boolean'].dtype.type,
-                          np.bool_)
-        assert_array_equal(self.array['boolean'],
-                           [True, False, True, False, False])
-
-    def test_boolean_mask(self):
-        assert_array_equal(self.mask['boolean'],
-                           [False, False, False, False, True])
-
-    def test_boolean_array(self):
-        assert issubclass(self.array['booleanArray'].dtype.type,
-                          np.bool_)
-        assert_array_equal(self.array['booleanArray'],
-                           [[ True,  True,  True,  True],
-                            [ True,  True, False,  True],
-                            [ True,  True, False,  True],
-                            [False, False, False, False],
-                            [False, False, False, False]])
-
-    def test_boolean_array_mask(self):
-        assert_array_equal(self.mask['booleanArray'],
-                           [[False, False, False, False],
-                            [False, False, False, False],
-                            [False, False,  True, False],
-                            [ True,  True,  True,  True],
-                            [ True,  True,  True,  True]])
-
-    def test_nulls(self):
-        assert_array_equal(self.array['nulls'],
-                           [0, -9, 2, -9, -9])
-        assert_array_equal(self.mask['nulls'],
-                           [False, True, False, True, True])
-
-    def test_nulls_array(self):
-        assert_array_equal(self.array['nulls_array'],
-                           [[[-9, -9], [-9, -9]],
-                            [[0, 1], [2, 3]],
-                            [[-9, 0], [-9, 1]],
-                            [[0, -9], [1, -9]],
-                            [[-9, -9], [-9, -9]]])
-        assert_array_equal(self.mask['nulls_array'],
-                           [[[ True,  True],
-                             [ True,  True]],
-
-                            [[False, False],
-                             [False, False]],
-
-                            [[ True, False],
-                             [ True, False]],
-
-                            [[False,  True],
-                             [False,  True]],
-
-                            [[ True,  True],
-                             [ True,  True]]])
-
-    def test_double_array(self):
-        assert issubclass(self.array['doublearray'].dtype.type,
-                          np.object_)
-        assert len(self.array['doublearray'][0]) == 0
-        assert_array_equal(self.array['doublearray'][1],
-                           [0, 1, np.inf, -np.inf, np.nan, 0, -1])
-        assert_array_equal(self.mask['doublearray'][1],
-                           [False, False, False, False, False, False, True])
-
-    def test_bit_array2(self):
-        assert_array_equal(self.array['bitarray2'][0],
-                           [True, True, True, True,
-                            False, False, False, False,
-                            True, True, True, True,
-                            False, False, False, False])
-
-    def test_bit_array2_mask(self):
-        assert not np.any(self.mask['bitarray2'][0])
-        assert np.all(self.mask['bitarray2'][1:])
-
-
-class TestThroughTableData(TestParse):
-    def setup_class(self):
-        votable = parse(
-            get_data_filename('data/regression.xml'),
-            pedantic=False)
-        votable.to_xml(join(TMP_DIR, "test_through_tabledata.xml"))
-        self.table = parse(join(TMP_DIR, "test_through_tabledata.xml"),
-                           pedantic=False).get_first_table()
-        self.array = self.table.array
-        self.mask = self.table.mask
-
-    def test_schema(self):
-        assert_validate_schema(join(TMP_DIR, "test_through_tabledata.xml"))
-
-
-class TestThroughBinary(TestParse):
-    def setup_class(self):
-        votable = parse(
-            get_data_filename('data/regression.xml'),
-            pedantic=False)
-        votable.get_first_table().format = 'binary'
-        votable.to_xml(join(TMP_DIR, "test_through_binary.xml"))
-        self.table = parse(join(TMP_DIR, "test_through_binary.xml"),
-                           pedantic=False).get_first_table()
-        self.array = self.table.array
-        self.mask = self.table.mask
-
-    # Masked values in bit fields don't roundtrip through the binary
-    # representation -- that's not a bug, just a limitation, so
-    # override the mask array checks here.
-    def test_bit_mask(self):
-        assert not np.any(self.mask['bit'])
-
-    def test_bitarray_mask(self):
-        assert not np.any(self.mask['bitarray'])
-
-    def test_bit_array2_mask(self):
-        assert not np.any(self.mask['bitarray2'])
-
-
-def table_from_scratch():
-    from ..tree import VOTableFile, Resource, Table, Field
-
-    # Create a new VOTable file...
-    votable = VOTableFile()
-
-    # ...with one resource...
-    resource = Resource()
-    votable.resources.append(resource)
-
-    # ... with one table
-    table = Table(votable)
-    resource.tables.append(table)
-
-    # Define some fields
-    table.fields.extend([
-            Field(votable, ID="filename", datatype="char"),
-            Field(votable, ID="matrix", datatype="double", arraysize="2x2")])
-
-    # Now, use those field definitions to create the numpy record arrays, with
-    # the given number of rows
-    table.create_arrays(2)
-
-    # Now table.array can be filled with data
-    table.array[0] = ('test1.xml', [[1, 0], [0, 1]])
-    table.array[1] = ('test2.xml', [[0.5, 0.3], [0.2, 0.1]])
-
-    # Now write the whole thing to a file.
-    # Note, we have to use the top-level votable file object
-    out = io.StringIO()
-    votable.to_xml(out)
-
-
-def test_open_files():
-    def test_file(filename):
-        parse(filename, pedantic=False)
-
-    for filename in get_data_filenames('data', '*.xml'):
-        yield test_file, filename
-
-
- at raises(VOTableSpecError)
-def test_too_many_columns():
-    votable = parse(
-        get_data_filename('data/too_many_columns.xml.gz'),
-        pedantic=False)
-
-
-def test_build_from_scratch():
-    # Create a new VOTable file...
-    votable = tree.VOTableFile()
-
-    # ...with one resource...
-    resource = tree.Resource()
-    votable.resources.append(resource)
-
-    # ... with one table
-    table = tree.Table(votable)
-    resource.tables.append(table)
-
-    # Define some fields
-    table.fields.extend([
-        tree.Field(votable, ID="filename", datatype="char"),
-        tree.Field(votable, ID="matrix", datatype="double", arraysize="2x2")])
-
-    # Now, use those field definitions to create the numpy record arrays, with
-    # the given number of rows
-    table.create_arrays(2)
-
-    # Now table.array can be filled with data
-    table.array[0] = ('test1.xml', [[1, 0], [0, 1]])
-    table.array[1] = ('test2.xml', [[0.5, 0.3], [0.2, 0.1]])
-
-    # Now write the whole thing to a file.
-    # Note, we have to use the top-level votable file object
-    votable.to_xml(os.path.join(TMP_DIR, "new_votable.xml"))
-
-    votable = parse(os.path.join(TMP_DIR, "new_votable.xml"))
-
-    table = votable.get_first_table()
-    assert_array_equal(
-        table.mask, np.array([(False, [[False, False], [False, False]]),
-                              (False, [[False, False], [False, False]])],
-                             dtype=[('filename', '?'),
-                                    ('matrix', '?', (2, 2))]))
-
-
-def test_validate():
-    output = io.StringIO()
-
-    # We can't test xmllint, because we can't rely on it being on the
-    # user's machine.
-    result = validate(get_data_filename('data/regression.xml'),
-                      output, xmllint=False)
-
-    assert result == False
-
-    output.seek(0)
-    output = output.readlines()
-
-    # Uncomment to generate new groundtruth
-    # with io.open('validation.txt', 'wt', encoding='utf-8') as fd:
-    #     fd.write(u''.join(output))
-
-    with io.open(
-        get_data_filename('data/validation.txt'),
-        'rt', encoding='utf-8') as fd:
-        truth = fd.readlines()
-
-    truth = truth[1:]
-    output = output[1:]
-
-    for line in difflib.unified_diff(truth, output):
-        if IS_PY3K:
-            sys.stdout.write(
-                line.replace('\\n', '\n'))
-        else:
-            sys.stdout.write(
-                line.encode('unicode_escape').
-                replace('\\n', '\n'))
-
-    assert truth == output
-
-
-def test_gzip_filehandles():
-    votable = parse(
-        get_data_filename('data/regression.xml'),
-        pedantic=False)
-
-    with open(join(TMP_DIR, "regression.compressed.xml"), 'wb') as fd:
-        votable.to_xml(
-            fd,
-            compressed=True,
-            _astropy_version="testing")
-
-    with open(join(TMP_DIR, "regression.compressed.xml"), 'rb') as fd:
-        votable = parse(
-            fd,
-            pedantic=False)
-
-
-def test_from_scratch_example():
-    with warnings.catch_warnings(record=True) as warning_lines:
-        warnings.resetwarnings()
-        warnings.simplefilter("always", VOWarning, append=True)
-        try:
-            _run_test_from_scratch_example()
-        except ValueError as e:
-            lines.append(str(e))
-
-    assert len(warning_lines) == 0
-
-
-def _run_test_from_scratch_example():
-    from astropy.io.vo.tree import VOTableFile, Resource, Table, Field
-
-    # Create a new VOTable file...
-    votable = VOTableFile()
-
-    # ...with one resource...
-    resource = Resource()
-    votable.resources.append(resource)
-
-    # ... with one table
-    table = Table(votable)
-    resource.tables.append(table)
-
-    # Define some fields
-    table.fields.extend([
-        Field(votable, name="filename", datatype="char", arraysize="*"),
-        Field(votable, name="matrix", datatype="double", arraysize="2x2")])
-
-    # Now, use those field definitions to create the numpy record arrays, with
-    # the given number of rows
-    table.create_arrays(2)
-
-    # Now table.array can be filled with data
-    table.array[0] = ('test1.xml', [[1, 0], [0, 1]])
-    table.array[1] = ('test2.xml', [[0.5, 0.3], [0.2, 0.1]])
-
-    assert table.array[0][0] == 'test1.xml'
-
-
diff --git a/astropy/io/vo/tree.py b/astropy/io/vo/tree.py
deleted file mode 100644
index 3bdb36b..0000000
--- a/astropy/io/vo/tree.py
+++ /dev/null
@@ -1,3061 +0,0 @@
-# TODO: Test FITS parsing
-
-from __future__ import division, absolute_import
-
-from .util import IS_PY3K
-
-# STDLIB
-import codecs
-import io
-import re
-if IS_PY3K:
-    string_types = (str, bytes)
-else:
-    string_types = (str, unicode)
-
-# THIRD-PARTY
-import numpy as np
-
-# LOCAL
-from .. import fits
-from ... import __version__ as astropy_version
-from ...utils.collections import HomogeneousList
-from ...utils.xml.writer import XMLWriter
-
-from . import converters
-from .exceptions import (warn_or_raise, vo_warn, vo_raise, vo_reraise,
-    warn_unknown_attrs,
-    W06, W07, W08, W09, W10, W11, W12, W13, W15, W17, W18, W19, W20,
-    W21, W22, W26, W27, W28, W29, W32, W33, W35, W36, W37, W38, W40,
-    W41, W42, W43, W44, W45, E06, E08, E09, E10, E11, E12, E13,
-    E14, E15, E16, E17, E18, E19, E20, E21)
-from . import ucd as ucd_mod
-from .unit import check_unit
-from . import util
-from . import xmlutil
-
-try:
-    from . import tablewriter
-    _has_c_tabledata_writer = True
-except ImportError:
-    _has_c_tabledata_writer = False
-
-
-__all__ = [
-    'Link', 'Info', 'Values', 'Field', 'Param', 'CooSys',
-    'FieldRef', 'ParamRef', 'Group', 'Table', 'Resource',
-    'VOTableFile'
-    ]
-
-
-# The default number of rows to read in each chunk before converting
-# to an array.
-DEFAULT_CHUNK_SIZE = 256
-RESIZE_AMOUNT = 1.5
-
-######################################################################
-# FACTORY FUNCTIONS
-
-
-def _lookup_by_id_factory(iterator, element_name, doc):
-    """
-    Creates a function useful for looking up an element by ID.
-
-    Parameters
-    ----------
-    iterator : generator
-        A generator that iterates over some arbitrary set of elements
-
-    element_name : str
-        The XML element name of the elements being iterated over (used
-        for error messages only).
-
-    doc : str
-        A docstring to apply to the generated function.
-
-    Returns
-    -------
-    factory : function
-        A function that looks up an element by ID
-    """
-    def lookup_by_id(self, ref, before=None):
-        """
-        Given an XML id *ref*, finds the first element in the iterator
-        with the attribute ID == *ref*.  If *before* is provided, will
-        stop searching at the object *before*.  This is important,
-        since "forward references" are not allowed in the VOTABLE
-        format.
-        """
-        for element in getattr(self, iterator)():
-            if element is before:
-                if element.ID == ref:
-                    vo_raise(
-                        "%s references itself" % element_name,
-                        element._config, element._pos, KeyError)
-                break
-            if element.ID == ref:
-                return element
-        raise KeyError(
-            "No %s with ID '%s' found before the referencing %s" %
-            (element_name, ref, element_name))
-
-    lookup_by_id.__doc__ = doc
-    return lookup_by_id
-
-
-def _lookup_by_id_or_name_factory(iterator, element_name, doc):
-    """
-    Like `_lookup_by_id_factory`, but also looks in the "name" attribute.
-    """
-    def lookup_by_id(self, ref, before=None):
-        """
-        Given an key *ref*, finds the first element in the iterator
-        with the attribute ID == *ref* or name == *ref*.  If *before*
-        is provided, will stop searching at the object *before*.  This
-        is important, since "forward references" are not allowed in
-        the VOTABLE format.
-        """
-        for element in getattr(self, iterator)():
-            if element is before:
-                if ref in (element.ID, element.name):
-                    vo_raise(
-                        "%s references itself" % element_name,
-                        element._config, element._pos, KeyError)
-                break
-            if ref in (element.ID, element.name):
-                return element
-        raise KeyError(
-            "No %s with ID or name '%s' found before the referencing %s" %
-            (element_name, ref, element_name))
-
-    lookup_by_id.__doc__ = doc
-    return lookup_by_id
-
-
-######################################################################
-# ATTRIBUTE CHECKERS
-def check_astroyear(year, field, config={}, pos=None):
-    """
-    Raises a `~astropy.io.vo.exceptions.VOTableSpecError` if *year* is
-    not a valid astronomical year as defined by the VOTABLE standard.
-
-    Parameters
-    ----------
-    year : str
-        An astronomical year string
-
-    field : str
-        The name of the field this year was found in (used for error
-        message)
-
-    config, pos : optional
-        Information about the source of the value
-    """
-    if (year is not None and
-        re.match(ur"^[JB]?[0-9]+([.][0-9]*)?$", year) is None):
-        warn_or_raise(W07, W07, (field, year), config, pos)
-        return False
-    return True
-
-
-def check_string(string, attr_name, config={}, pos=None):
-    """
-    Raises a `~astropy.io.vo.exceptions.VOTableSpecError` if
-    *string* is not a string or Unicode string.
-
-    Parameters
-    ----------
-    string : str
-        An astronomical year string
-
-    field : str
-        The name of the field this year was found in (used for error
-        message)
-
-    config, pos : optional
-        Information about the source of the value
-    """
-    if string is not None and not isinstance(string, string_types):
-        warn_or_raise(W08, W08, attr_name, config, pos)
-        return False
-    return True
-
-
-def resolve_id(ID, id, config={}, pos=None):
-    if ID is None and id is not None:
-        warn_or_raise(W09, W09, (), config, pos)
-        return id
-    return ID
-
-
-def check_ucd(ucd, config={}, pos=None):
-    """
-    Warns or raises a `~astropy.io.vo.exceptions.VOTableSpecError`
-    if *ucd* is not a valid `unified content descriptor`_ string as
-    defined by the VOTABLE standard.
-
-    Parameters
-    ----------
-    ucd : str
-        A UCD string.
-
-    config, pos : optional
-        Information about the source of the value
-    """
-    if config.get('version_1_1_or_later'):
-        try:
-            ucd_mod.parse_ucd(
-                ucd,
-                check_controlled_vocabulary=config.get(
-                    'version_1_2_or_later', False),
-                has_colon=config.get('version_1_2_or_later', False))
-        except ValueError as e:
-            # This weird construction is for Python 3 compatibility
-            if config.get('pedantic'):
-                vo_raise(W06, (ucd, unicode(e)), config, pos)
-            else:
-                vo_warn(W06, (ucd, unicode(e)), config, pos)
-                return False
-    return True
-
-
-######################################################################
-# PROPERTY MIXINS
-class _IDProperty(object):
-    @property
-    def ID(self):
-        """
-        The XML ID_ of the element.  May be ``None`` or a string
-        conforming to XML ID_ syntax.
-        """
-        return self._ID
-
-    @ID.setter
-    def ID(self, ID):
-        xmlutil.check_id(ID, 'ID', self._config, self._pos)
-        self._ID = ID
-
-    @ID.deleter
-    def ID(self):
-        self._ID = None
-
-
-class _NameProperty(object):
-    @property
-    def name(self):
-        """An optional name for the element."""
-        return self._name
-
-    @name.setter
-    def name(self, name):
-        xmlutil.check_token(name, 'name', self._config, self._pos)
-        self._name = name
-
-    @name.deleter
-    def name(self):
-        self._name = None
-
-
-class _XtypeProperty(object):
-    @property
-    def xtype(self):
-        """Extended data type information."""
-        return self._xtype
-
-    @xtype.setter
-    def xtype(self, xtype):
-        if xtype is not None and not self._config.get('version_1_2_or_later'):
-            warn_or_raise(
-                W28, W28, ('xtype', self._element_name, '1.2'),
-                self._config, self._pos)
-        check_string(xtype, 'xtype', self._config, self._pos)
-        self._xtype = xtype
-
-    @xtype.deleter
-    def xtype(self):
-        self._xtype = None
-
-
-class _UtypeProperty(object):
-    _utype_in_v1_2 = False
-
-    @property
-    def utype(self):
-        """The usage-specific or `unique type`_ of the element."""
-        return self._utype
-
-    @utype.setter
-    def utype(self, utype):
-        if (self._utype_in_v1_2 and
-            utype is not None and
-            not self._config.get('version_1_2_or_later')):
-            warn_or_raise(
-                W28, W28, ('utype', self._element_name, '1.2'),
-                self._config, self._pos)
-        check_string(utype, 'utype', self._config, self._pos)
-        self._utype = utype
-
-    @utype.deleter
-    def utype(self):
-        self._utype = None
-
-
-class _UcdProperty(object):
-    _ucd_in_v1_2 = False
-
-    @property
-    def ucd(self):
-        """The `unified content descriptor`_ for the element."""
-        return self._ucd
-
-    @ucd.setter
-    def ucd(self, ucd):
-        if ucd is not None and ucd.strip() == '':
-            ucd = None
-        if ucd is not None:
-            if (self._ucd_in_v1_2 and
-                not self._config.get('version_1_2_or_later')):
-                warn_or_raise(
-                    W28, W28, ('ucd', self._element_name, '1.2'),
-                    self._config, self._pos)
-            check_ucd(ucd, self._config, self._pos)
-        self._ucd = ucd
-
-    @ucd.deleter
-    def ucd(self):
-        self._ucd = None
-
-
-class _DescriptionProperty(object):
-    @property
-    def description(self):
-        """
-        An optional string describing the element.  Corresponds to the
-        DESCRIPTION_ element.
-        """
-        return self._description
-
-    @description.setter
-    def description(self, description):
-        self._description = description
-
-    @description.deleter
-    def description(self):
-        self._description = None
-
-
-######################################################################
-# ELEMENT CLASSES
-class Element(object):
-    """
-    A base class for all classes that represent XML elements in the
-    VOTABLE file.
-    """
-    def _add_unknown_tag(self, iterator, tag, data, config, pos):
-        warn_or_raise(W10, W10, tag, config, pos)
-
-    def _ignore_add(self, iterator, tag, data, config, pos):
-        warn_unknown_attrs(tag, data.iterkeys(), config, pos)
-
-    def _add_definitions(self, iterator, tag, data, config, pos):
-        if config.get('version_1_1_or_later'):
-            warn_or_raise(W22, W22, (), config, pos)
-        warn_unknown_attrs(tag, data.iterkeys(), config, pos)
-
-
-class SimpleElement(Element):
-    """
-    A base class for simple elements, such as FIELD, PARAM and INFO
-    that don't require any special parsing or outputting machinery.
-    """
-    def __init__(self):
-        Element.__init__(self)
-
-    def parse(self, iterator, config):
-        for start, tag, data, pos in iterator:
-            if start and tag != self._element_name:
-                self._add_unknown_tag(iterator, tag, data, config, pos)
-            elif tag == self._element_name:
-                break
-
-        return self
-
-    def to_xml(self, w, **kwargs):
-        w.element(self._element_name,
-                  attrib=w.object_attrs(self, self._attr_list))
-
-
-class SimpleElementWithContent(SimpleElement):
-    """
-    A base class for simple elements, such as FIELD, PARAM and INFO
-    that don't require any special parsing or outputting machinery.
-    """
-    def __init__(self):
-        SimpleElement.__init__(self)
-
-        self._content = None
-
-    def to_xml(self, w, **kwargs):
-        w.element(self._element_name, self._content,
-                  attrib=w.object_attrs(self, self._attr_list))
-
-    @property
-    def content(self):
-        """The content of the element."""
-        return self._content
-
-    @content.setter
-    def content(self, content):
-        check_string(content, 'content', self._config, self._pos)
-        self._content = content
-
-    @content.deleter
-    def content(self):
-        self._content = None
-
-
-class Link(SimpleElement, _IDProperty):
-    """
-    LINK_ elements: used to reference external documents and servers through a URI.
-
-    The keyword arguments correspond to setting members of the same
-    name, documented below.
-    """
-    _attr_list = ['ID', 'content_role', 'content_type', 'title', 'value',
-                  'href', 'action']
-    _element_name = 'LINK'
-
-    def __init__(self, ID=None, title=None, value=None, href=None, action=None,
-                 id=None, config={}, pos=None, **kwargs):
-        self._config = config
-        self._pos = pos
-
-        SimpleElement.__init__(self)
-
-        content_role = kwargs.get('content-role') or kwargs.get('content_role')
-        content_type = kwargs.get('content-type') or kwargs.get('content_type')
-
-        if 'gref' in kwargs:
-            warn_or_raise(W11, W11, (), config, pos)
-
-        self.ID           = resolve_id(ID, id, config, pos)
-        self.content_role = content_role
-        self.content_type = content_type
-        self.title        = title
-        self.value        = value
-        self.href         = href
-        self.action       = action
-
-        warn_unknown_attrs(
-            'LINK', kwargs.iterkeys(), config, pos,
-            ['content-role', 'content_role', 'content-type', 'content_type',
-             'gref'])
-
-    @property
-    def content_role(self):
-        """
-        Defines the MIME role of the referenced object.  Must be one of:
-
-          None, 'query', 'hints', 'doc' or 'location'
-        """
-        return self._content_role
-
-    @content_role.setter
-    def content_role(self, content_role):
-        if content_role not in (None, 'query', 'hints', 'doc', 'location'):
-            vo_warn(W45, (content_role,), self._config, self._pos)
-        self._content_role = content_role
-
-    @content_role.deleter
-    def content_role(self):
-        self._content_role = None
-
-    @property
-    def content_type(self):
-        """Defines the MIME content type of the referenced object."""
-        return self._content_type
-
-    @content_type.setter
-    def content_type(self, content_type):
-        xmlutil.check_mime_content_type(content_type, self._config, self._pos)
-        self._content_type = content_type
-
-    @content_type.deleter
-    def content_type(self):
-        self._content_type = None
-
-    @property
-    def href(self):
-        """
-        A URI to an arbitrary protocol.  The vo package only supports
-        http and anonymous ftp.
-        """
-        return self._href
-
-    @href.setter
-    def href(self, href):
-        xmlutil.check_anyuri(href, self._config, self._pos)
-        self._href = href
-
-    @href.deleter
-    def href(self):
-        self._href = None
-
-
-class Info(SimpleElementWithContent, _IDProperty, _XtypeProperty,
-           _UtypeProperty):
-    """
-    INFO_ elements: arbitrary key-value pairs for extensions to the standard.
-
-    The keyword arguments correspond to setting members of the same
-    name, documented below.
-    """
-    _element_name = 'INFO'
-    _attr_list_11 = ['ID', 'name', 'value']
-    _attr_list_12 = _attr_list_11 + ['xtype', 'ref', 'unit', 'ucd', 'utype']
-    _utype_in_v1_2 = True
-
-    def __init__(self, ID=None, name=None, value=None, id=None, xtype=None,
-                 ref=None, unit=None, ucd=None, utype=None,
-                 config={}, pos=None, **extra):
-        self._config = config
-        self._pos = pos
-
-        SimpleElementWithContent.__init__(self)
-
-        self.ID      = (resolve_id(ID, id, config, pos) or
-                        xmlutil.fix_id(name, config, pos))
-        self.name    = name
-        self.value   = value
-        self.xtype   = xtype
-        self.ref     = ref
-        self.unit    = unit
-        self.ucd     = ucd
-        self.utype   = utype
-
-        if config.get('version_1_2_or_later'):
-            self._attr_list = self._attr_list_12
-        else:
-            self._attr_list = self._attr_list_11
-            if xtype is not None:
-                warn_unknown_attrs('INFO', ['xtype'], config, pos)
-            if ref is not None:
-                warn_unknown_attrs('INFO', ['ref'], config, pos)
-            if unit is not None:
-                warn_unknown_attrs('INFO', ['unit'], config, pos)
-            if ucd is not None:
-                warn_unknown_attrs('INFO', ['ucd'], config, pos)
-            if utype is not None:
-                warn_unknown_attrs('INFO', ['utype'], config, pos)
-
-        warn_unknown_attrs('INFO', extra.iterkeys(), config, pos)
-
-    @property
-    def name(self):
-        """[*required*] The key of the key-value pair."""
-        return self._name
-
-    @name.setter
-    def name(self, name):
-        if name is None:
-            warn_or_raise(W35, W35, ('name'), self._config, self._pos)
-        xmlutil.check_token(name, 'name', self._config, self._pos)
-        self._name = name
-
-    @property
-    def value(self):
-        """
-        [*required*] The value of the key-value pair.  (Always stored
-        as a string or unicode string).
-        """
-        return self._value
-
-    @value.setter
-    def value(self, value):
-        if value is None:
-            warn_or_raise(W35, W35, ('value'), self._config, self._pos)
-        check_string(value, 'value', self._config, self._pos)
-        self._value = value
-
-    @property
-    def content(self):
-        """The content inside the INFO element."""
-        return self._content
-
-    @content.setter
-    def content(self, content):
-        check_string(content, 'content', self._config, self._pos)
-        self._content = content
-
-    @content.deleter
-    def content(self):
-        self._content = None
-
-    @property
-    def ref(self):
-        """
-        Refer to another INFO_ element by ID_, defined previously in
-        the document.
-        """
-        return self._ref
-
-    @ref.setter
-    def ref(self, ref):
-        if ref is not None and not self._config.get('version_1_2_or_later'):
-            warn_or_raise(W28, W28, ('ref', 'INFO', '1.2'),
-                          self._config, self._pos)
-        xmlutil.check_id(ref, 'ref', self._config, self._pos)
-        # TODO: actually apply the reference
-        # if ref is not None:
-        #     try:
-        #         other = self._votable.get_values_by_id(ref, before=self)
-        #     except KeyError:
-        #         vo_raise(
-        #             "VALUES ref='%s', which has not already been defined." %
-        #             self.ref, self._config, self._pos, KeyError)
-        #     self.null = other.null
-        #     self.type = other.type
-        #     self.min = other.min
-        #     self.min_inclusive = other.min_inclusive
-        #     self.max = other.max
-        #     self.max_inclusive = other.max_inclusive
-        #     self._options[:] = other.options
-        self._ref = ref
-
-    @ref.deleter
-    def ref(self):
-        self._ref = None
-
-    @property
-    def unit(self):
-        """A string specifying the units_ for the INFO_."""
-        return self._unit
-
-    @unit.setter
-    def unit(self, unit):
-        if unit is not None and not self._config.get('version_1_2_or_later'):
-            warn_or_raise(W28, W28, ('unit', 'INFO', '1.2'),
-                          self._config, self._pos)
-        check_unit(unit, 'unit', self._config, self._pos)
-        self._unit = unit
-
-    @unit.deleter
-    def unit(self):
-        self._unit = None
-
-
-class Values(Element, _IDProperty):
-    """
-    VALUES_ element: used within FIELD_ and PARAM_ elements to define the domain of values.
-
-    The keyword arguments correspond to setting members of the same
-    name, documented below.
-    """
-    def __init__(self, votable, field, ID=None, null=None, ref=None,
-                 type="legal", id=None, config={}, pos=None, **extras):
-        self._config  = config
-        self._pos = pos
-
-        Element.__init__(self)
-
-        self._votable = votable
-        self._field   = field
-        self.ID       = resolve_id(ID, id, config, pos)
-        self.null     = null
-        self._ref     = ref
-        self.type     = type
-
-        self.min           = None
-        self.max           = None
-        self.min_inclusive = True
-        self.max_inclusive = True
-        self._options      = []
-
-        warn_unknown_attrs('VALUES', extras.iterkeys(), config, pos)
-
-    @property
-    def null(self):
-        """
-        For integral datatypes, *null* is used to define the value
-        used for missing values.
-        """
-        return self._null
-
-    @null.setter
-    def null(self, null):
-        if null is not None and isinstance(null, string_types):
-            try:
-                null_val = self._field.converter.parse_scalar(
-                    null, self._config, self._pos)[0]
-            except:
-                warn_or_raise(W36, W36, null, self._config, self._pos)
-                null_val = self._field.converter.parse_scalar(
-                    '0', self._config, self._pos)[0]
-        else:
-            null_val = null
-        self._null = null_val
-
-    @null.deleter
-    def null(self):
-        self._null = None
-
-    @property
-    def type(self):
-        """
-        [*required*] Defines the applicability of the domain defined
-        by this VALUES_ element.  Must be one of the following
-        strings:
-
-          - 'legal': The domain of this column applies in general to
-            this datatype. (default)
-
-          - 'actual': The domain of this column applies only to the
-            data enclosed in the parent table.
-        """
-        return self._type
-
-    @type.setter
-    def type(self, type):
-        if type not in ('legal', 'actual'):
-            vo_raise(E08, type, self._config, self._pos)
-        self._type = type
-
-    @property
-    def ref(self):
-        """
-        Refer to another VALUES_ element by ID_, defined previously in
-        the document, for MIN/MAX/OPTION information.
-        """
-        return self._ref
-
-    @ref.setter
-    def ref(self, ref):
-        xmlutil.check_id(ref, 'ref', self._config, self._pos)
-        if ref is not None:
-            try:
-                other = self._votable.get_values_by_id(ref, before=self)
-            except KeyError:
-                warn_or_raise(W43, W43, ('VALUES', self.ref), self._config,
-                              self._pos)
-                ref = None
-            else:
-                self.null = other.null
-                self.type = other.type
-                self.min = other.min
-                self.min_inclusive = other.min_inclusive
-                self.max = other.max
-                self.max_inclusive = other.max_inclusive
-                self._options[:] = other.options
-        self._ref = ref
-
-    @ref.deleter
-    def ref(self):
-        self._ref = None
-
-    @property
-    def min(self):
-        """
-        The minimum value of the domain.  See :attr:`min_inclusive`.
-        """
-        return self._min
-
-    @min.setter
-    def min(self, min):
-        if hasattr(self._field, 'converter') and min is not None:
-            self._min = self._field.converter.parse(min)[0]
-        else:
-            self._min = min
-
-    @min.deleter
-    def min(self):
-        self._min = None
-
-    @property
-    def min_inclusive(self):
-        """When `True`, the domain includes the minimum value."""
-        return self._min_inclusive
-
-    @min_inclusive.setter
-    def min_inclusive(self, inclusive):
-        if inclusive == 'yes':
-            self._min_inclusive = True
-        elif inclusive == 'no':
-            self._min_inclusive = False
-        else:
-            self._min_inclusive = bool(inclusive)
-
-    @min_inclusive.deleter
-    def min_inclusive(self):
-        self._min_inclusive = True
-
-    @property
-    def max(self):
-        """
-        The maximum value of the domain.  See :attr:`max_inclusive`.
-        """
-        return self._max
-
-    @max.setter
-    def max(self, max):
-        if hasattr(self._field, 'converter') and max is not None:
-            self._max = self._field.converter.parse(max)[0]
-        else:
-            self._max = max
-
-    @max.deleter
-    def max(self):
-        self._max = None
-
-    @property
-    def max_inclusive(self):
-        """When `True`, the domain includes the maximum value."""
-        return self._max_inclusive
-
-    @max_inclusive.setter
-    def max_inclusive(self, inclusive):
-        if inclusive == 'yes':
-            self._max_inclusive = True
-        elif inclusive == 'no':
-            self._max_inclusive = False
-        else:
-            self._max_inclusive = bool(inclusive)
-
-    @max_inclusive.deleter
-    def max_inclusive(self):
-        self._max_inclusive = True
-
-    @property
-    def options(self):
-        """
-        A list of string key-value tuples defining other OPTION
-        elements for the domain.  All options are ignored -- they are
-        stored for round-tripping purposes only.
-        """
-        return self._options
-
-    def parse(self, iterator, config):
-        if self.ref is not None:
-            for start, tag, data, pos in iterator:
-                if start:
-                    warn_or_raise(W44, W44, tag, config, pos)
-                else:
-                    if tag != 'VALUES':
-                        warn_or_raise(W44, W44, tag, config, pos)
-                    break
-        else:
-            for start, tag, data, pos in iterator:
-                if start:
-                    if tag == 'MIN':
-                        if 'value' not in data:
-                            vo_raise(E09, 'MIN', config, pos)
-                        self.min = data['value']
-                        self.min_inclusive = data.get('inclusive', 'yes')
-                        warn_unknown_attrs(
-                            'MIN', data.iterkeys(), config, pos,
-                            ['value', 'inclusive'])
-                    elif tag == 'MAX':
-                        if 'value' not in data:
-                            vo_raise(E09, 'MAX', config, pos)
-                        self.max = data['value']
-                        self.max_inclusive = data.get('inclusive', 'yes')
-                        warn_unknown_attrs(
-                            'MAX', data.iterkeys(), config, pos,
-                            ['value', 'inclusive'])
-                    elif tag == 'OPTION':
-                        if 'value' not in data:
-                            vo_raise(E09, 'OPTION', config, pos)
-                        xmlutil.check_token(
-                            data.get('name'), 'name', config, pos)
-                        self.options.append(
-                            (data.get('name'), data.get('value')))
-                        warn_unknown_attrs(
-                            'OPTION', data.iterkeys(), config, pos,
-                            ['data', 'name'])
-                elif tag == 'VALUES':
-                    break
-
-        return self
-
-    def is_defaults(self):
-        # If there's nothing meaningful or non-default to write,
-        # don't write anything.
-        return (self.ref is None and self.null is None and self.ID is None and
-                self.max is None and self.min is None and self.options == [])
-
-    def to_xml(self, w, **kwargs):
-        def yes_no(value):
-            if value:
-                return u'yes'
-            return u'no'
-
-        if self.is_defaults():
-            return
-
-        if self.ref is not None:
-            w.element(u'VALUES', attrib=w.object_attrs(self, [u'ref']))
-        else:
-            with w.tag(u'VALUES',
-                       attrib=w.object_attrs(
-                           self, [u'ID', u'null', u'ref'])):
-                if self.min is not None:
-                    w.element(
-                        u'MIN',
-                        value=self._field.converter.output(self.min, False),
-                        inclusive=yes_no(self.min_inclusive))
-                if self.max is not None:
-                    w.element(
-                        u'MAX',
-                        value=self._field.converter.output(self.max, False),
-                        inclusive=yes_no(self.max_inclusive))
-                for name, value in self.options:
-                    w.element(
-                        u'OPTION',
-                        name=name,
-                        value=value)
-
-
-class Field(SimpleElement, _IDProperty, _NameProperty, _XtypeProperty,
-            _UtypeProperty, _UcdProperty):
-    """
-    FIELD_ element: describes the datatype of a particular column of data.
-
-    The keyword arguments correspond to setting members of the same
-    name, documented below.
-
-    If *ID* is provided, it is used for the column name in the
-    resulting recarray of the table.  If no *ID* is provided, *name*
-    is used instead.  If neither is provided, an exception will be
-    raised.
-    """
-    _attr_list_11 = ['ID', 'name', 'datatype', 'arraysize', 'ucd',
-                     'unit', 'width', 'precision', 'utype', 'ref']
-    _attr_list_12 = _attr_list_11 + ['xtype']
-    _element_name = 'FIELD'
-
-    def __init__(self, votable, ID=None, name=None, datatype=None,
-                 arraysize=None, ucd=None, unit=None, width=None,
-                 precision=None, utype=None, ref=None, type=None, id=None,
-                 xtype=None,
-                 config={}, pos=None, **extra):
-        self._config = config
-        self._pos = pos
-
-        SimpleElement.__init__(self)
-
-        if config.get('version_1_2_or_later'):
-            self._attr_list = self._attr_list_12
-        else:
-            self._attr_list = self._attr_list_11
-            if xtype is not None:
-                warn_unknown_attrs(self._element_name, ['xtype'], config, pos)
-
-        # TODO: REMOVE ME ----------------------------------------
-        # This is a terrible hack to support Simple Image Access
-        # Protocol results from archive.noao.edu.  It creates a field
-        # for the coordinate projection type of type "double", which
-        # actually contains character data.  We have to hack the field
-        # to store character data, or we can't read it in.  A warning
-        # will be raised when this happens.
-        if (not config.get('pedantic') and name == 'cprojection' and
-            ID == 'cprojection' and ucd == 'VOX:WCS_CoordProjection' and
-            datatype == 'double'):
-            datatype = 'char'
-            arraysize = '3'
-            vo_warn(W40, (), config, pos)
-        # ----------------------------------------
-
-        self.description = None
-        self._votable = votable
-
-        self.ID = (resolve_id(ID, id, config, pos) or
-                   xmlutil.fix_id(name, config, pos))
-        self.name = name
-        if name is None:
-            if (self._element_name == 'PARAM' and
-                not config.get('version_1_1_or_later')):
-                pass
-            else:
-                warn_or_raise(W15, W15, self._element_name, config, pos)
-            self.name = self.ID
-
-        if self._ID is None and name is None:
-            vo_raise(W12, self._element_name, config, pos)
-
-        datatype_mapping = {
-            'string'        : 'char',
-            'unicodeString' : 'unicodeChar',
-            'int16'         : 'short',
-            'int32'         : 'int',
-            'int64'         : 'long',
-            'float32'       : 'float',
-            'float64'       : 'double'}
-
-        if datatype in datatype_mapping:
-            warn_or_raise(W13, W13, (datatype, datatype_mapping[datatype]),
-                          config, pos)
-            datatype = datatype_mapping[datatype]
-
-        self.ref        = ref
-        self.datatype   = datatype
-        self.arraysize  = arraysize
-        self.ucd        = ucd
-        self.unit       = unit
-        self.width      = width
-        self.precision  = precision
-        self.utype      = utype
-        self.type       = type
-        self._links     = HomogeneousList(Link)
-        self.title      = self.name
-        self.values     = Values(self._votable, self)
-        self.xtype      = xtype
-
-        self._setup(config, pos)
-
-        warn_unknown_attrs(self._element_name, extra.iterkeys(), config, pos)
-
-    @classmethod
-    def uniqify_names(cls, fields):
-        """
-        Make sure that all names and titles in a list of fields are
-        unique, by appending numbers if necessary.
-        """
-        unique = {}
-        for field in fields:
-            i = 2
-            new_id = field.ID
-            while new_id in unique:
-                new_id = field.ID + "_%d" % i
-                i += 1
-            if new_id != field.ID:
-                vo_warn(W32, (field.ID, new_id), field._config, field._pos)
-            field.ID = new_id
-            unique[new_id] = field.ID
-
-        for field in fields:
-            i = 2
-            if field.name is None:
-                new_name = field.ID
-                implicit = True
-            else:
-                new_name = field.name
-                implicit = False
-            if new_name != field.ID:
-                while new_name in unique:
-                    new_name = field.name + " %d" % i
-                    i += 1
-
-            if (not implicit and
-                new_name != field.name):
-                vo_warn(W33, (field.name, new_name), field._config, field._pos)
-            field._unique_name = new_name
-            unique[new_name] = field.name
-
-    def _setup(self, config, pos):
-        if self.values._ref is not None:
-            self.values.ref = self.values._ref
-        self.converter = converters.get_converter(self, config, pos)
-
-    @property
-    def datatype(self):
-        """
-        [*required*] The datatype of the column.  Valid values (as
-        defined by the spec) are:
-
-          'boolean', 'bit', 'unsignedByte', 'short', 'int', 'long',
-          'char', 'unicodeChar', 'float', 'double', 'floatComplex', or
-          'doubleComplex'
-
-        Many VOTABLE files in the wild use 'string' instead of 'char',
-        so that is also a valid option, though 'string' will always be
-        converted to 'char' when writing the file back out.
-        """
-        return self._datatype
-
-    @datatype.setter
-    def datatype(self, datatype):
-        if datatype is None:
-            if self._config.get('version_1_1_or_later'):
-                warn_or_raise(E10, E10, self._element_name, self._config,
-                              self._pos)
-            datatype = 'char'
-        if datatype not in converters.converter_mapping:
-            vo_raise(E06, (datatype, self.ID), self._config, self._pos)
-        self._datatype = datatype
-
-    @property
-    def precision(self):
-        """
-        Along with :attr:`width`, defines the `numerical accuracy`_
-        associated with the data.  These values are used to limit the
-        precision when writing floating point values back to the XML
-        file.  Otherwise, it is purely informational -- the Numpy
-        recarray containing the data itself does not use this
-        information.
-        """
-        return self._precision
-
-    @precision.setter
-    def precision(self, precision):
-        if precision is not None and not re.match(ur"^[FE]?[0-9]+$", precision):
-            vo_raise(E11, precision, self._config, self._pos)
-        self._precision = precision
-
-    @precision.deleter
-    def precision(self):
-        self._precision = None
-
-    @property
-    def width(self):
-        """
-        Along with :attr:`precision`, defines the `numerical
-        accuracy`_ associated with the data.  These values are used to
-        limit the precision when writing floating point values back to
-        the XML file.  Otherwise, it is purely informational -- the
-        Numpy recarray containing the data itself does not use this
-        information.
-        """
-        return self._width
-
-    @width.setter
-    def width(self, width):
-        if width is not None:
-            width = int(width)
-            if width <= 0:
-                vo_raise(E12, width, self._config, self._pos)
-        self._width = width
-
-    @width.deleter
-    def width(self):
-        self._width = None
-
-    # ref on FIELD and PARAM behave differently than elsewhere -- here
-    # they're just informational, such as to refer to a coordinate
-    # system.
-    @property
-    def ref(self):
-        """
-        On FIELD_ elements, ref is used only for informational
-        purposes, for example to refer to a COOSYS_ element.
-        """
-        return self._ref
-
-    @ref.setter
-    def ref(self, ref):
-        xmlutil.check_id(ref, 'ref', self._config, self._pos)
-        self._ref = ref
-
-    @ref.deleter
-    def ref(self):
-        self._ref = None
-
-    @property
-    def unit(self):
-        """A string specifying the units_ for the FIELD_."""
-        return self._unit
-
-    @unit.setter
-    def unit(self, unit):
-        check_unit(unit, 'unit', self._config, self._pos)
-        self._unit = unit
-
-    @unit.deleter
-    def unit(self):
-        self._unit = None
-
-    @property
-    def arraysize(self):
-        """
-        Specifies the size of the multidimensional array if this
-        FIELD_ contains more than a single value.
-
-        See `multidimensional arrays`_.
-        """
-        return self._arraysize
-
-    @arraysize.setter
-    def arraysize(self, arraysize):
-        if (arraysize is not None and
-            not re.match(ur"^([0-9]+x)*[0-9]*[*]?(s\W)?$", arraysize)):
-            vo_raise(E13, arraysize, self._config, self._pos)
-        self._arraysize = arraysize
-
-    @arraysize.deleter
-    def arraysize(self):
-        self._arraysize = None
-
-    @property
-    def type(self):
-        """
-        The type attribute on FIELD_ elements is reserved for future
-        extensions.
-        """
-        return self._type
-
-    @type.setter
-    def type(self, type):
-        self._type = type
-
-    @type.deleter
-    def type(self):
-        self._type = None
-
-    @property
-    def values(self):
-        """
-        A :class:`Values` instance (or ``None``) defining the domain
-        of the column.
-        """
-        return self._values
-
-    @values.setter
-    def values(self, values):
-        assert values is None or isinstance(values, Values)
-        self._values = values
-
-    @values.deleter
-    def values(self):
-        self._values = None
-
-    @property
-    def links(self):
-        """
-        A list of :class:`Link` instances used to reference more
-        details about the meaning of the FIELD_.  This is purely
-        informational and is not used by the `astropy.io.vo` package.
-        """
-        return self._links
-
-    def parse(self, iterator, config):
-        for start, tag, data, pos in iterator:
-            if start:
-                if tag == 'VALUES':
-                    self.values.__init__(
-                        self._votable, self, config=config, pos=pos, **data)
-                    self.values.parse(iterator, config)
-                elif tag == 'LINK':
-                    link = Link(config=config, pos=pos, **data)
-                    self.links.append(link)
-                    link.parse(iterator, config)
-                elif tag == 'DESCRIPTION':
-                    warn_unknown_attrs(
-                        'DESCRIPTION', data.iterkeys(), config, pos)
-                elif tag != self._element_name:
-                    self._add_unknown_tag(iterator, tag, data, config, pos)
-            else:
-                if tag == 'DESCRIPTION':
-                    if self.description is not None:
-                        warn_or_raise(
-                            W17, W17, self._element_name, config, pos)
-                    self.description = data or None
-                elif tag == self._element_name:
-                    break
-
-        if self.description is not None:
-            self.title = " ".join(x.strip() for x in
-                                  self.description.split("\n"))
-        else:
-            self.title = self.name
-
-        self._setup(config, pos)
-
-        return self
-
-    def to_xml(self, w, **kwargs):
-        with w.tag(self._element_name,
-                   attrib=w.object_attrs(self, self._attr_list)):
-            if self.description is not None:
-                w.element(u'DESCRIPTION', self.description, wrap=True)
-            if not self.values.is_defaults():
-                self.values.to_xml(w, **kwargs)
-            for link in self.links:
-                link.to_xml(w, **kwargs)
-
-
-class Param(Field):
-    """
-    PARAM_ element: constant-valued columns in the data.
-
-    :class:`Param` objects are a subclass of :class:`Field`, and have
-    all of its methods and members.  Additionally, it defines :attr:`value`.
-    """
-    _attr_list_11 = Field._attr_list_11 + ['value']
-    _attr_list_12 = Field._attr_list_12 + ['value']
-    _element_name = 'PARAM'
-
-    def __init__(self, votable, ID=None, name=None, value=None, datatype=None,
-                 arraysize=None, ucd=None, unit=None, width=None,
-                 precision=None, utype=None, type=None, id=None, config={},
-                 pos=None, **extra):
-        self._value = value
-        Field.__init__(self, votable, ID=ID, name=name, datatype=datatype,
-                       arraysize=arraysize, ucd=ucd, unit=unit,
-                       precision=precision, utype=utype, type=type,
-                       id=id, config=config, pos=pos, **extra)
-
-    @property
-    def value(self):
-        """
-        [*required*] The constant value of the parameter.  Its type is
-        determined by the :attr:`~Field.datatype` member.
-        """
-        return self._value
-
-    @value.setter
-    def value(self, value):
-        if value is None:
-            value = ""
-        if ((IS_PY3K and isinstance(value, unicode)) or
-            (not IS_PY3K and isinstance(value, string_types))):
-            self._value = self.converter.parse(
-                value, self._config, self._pos)[0]
-        else:
-            self._value = value
-
-    def _setup(self, config, pos):
-        Field._setup(self, config, pos)
-        self.value = self._value
-
-    def to_xml(self, w, **kwargs):
-        tmp_value = self._value
-        self._value = self.converter.output(tmp_value, False)
-        # We must always have a value
-        if self._value is None:
-            self._value = u""
-        Field.to_xml(self, w, **kwargs)
-        self._value = tmp_value
-
-
-class CooSys(SimpleElement):
-    """
-    COOSYS_ element: defines a coordinate system.
-
-    The keyword arguments correspond to setting members of the same
-    name, documented below.
-    """
-    _attr_list = ['ID', 'equinox', 'epoch', 'system']
-    _element_name = 'COOSYS'
-
-    def __init__(self, ID=None, equinox=None, epoch=None, system=None, id=None,
-                 config={}, pos=None, **extra):
-        self._config = config
-        self._pos = pos
-
-        if config.get('version_1_2_or_later'):
-            warn_or_raise(W27, W27, (), config, pos)
-
-        SimpleElement.__init__(self)
-
-        self.ID      = resolve_id(ID, id, config, pos)
-        self.equinox = equinox
-        self.epoch   = epoch
-        self.system  = system
-
-        warn_unknown_attrs('COOSYS', extra.iterkeys(), config, pos)
-
-    @property
-    def ID(self):
-        """
-        [*required*] The XML ID of the COOSYS_ element, used for
-        cross-referencing.  May be ``None`` or a string conforming to
-        XML ID_ syntax.
-        """
-        return self._ID
-
-    @ID.setter
-    def ID(self, ID):
-        if self._config.get('version_1_1_or_later'):
-            if ID is None:
-                vo_raise(E15, (), self._config, self._pos)
-        xmlutil.check_id(ID, 'ID', self._config, self._pos)
-        self._ID = ID
-
-    @property
-    def system(self):
-        """
-        Specifies the type of coordinate system.  Valid choices are:
-
-          'eq_FK4', 'eq_FK5', 'ICRS', 'ecl_FK4', 'ecl_FK5', 'galactic',
-          'supergalactic', 'xy', 'barycentric', or 'geo_app'
-        """
-        return self._system
-
-    @system.setter
-    def system(self, system):
-        if system not in ('eq_FK4', 'eq_FK5', 'ICRS', 'ecl_FK4', 'ecl_FK5',
-                          'galactic', 'supergalactic', 'xy', 'barycentric',
-                          'geo_app'):
-            warn_or_raise(E16, E16, system, self._config, self._pos)
-        self._system = system
-
-    @system.deleter
-    def system(self):
-        self._system = None
-
-    @property
-    def equinox(self):
-        """
-        A parameter required to fix the equatorial or ecliptic systems
-        (as e.g. "J2000" as the default "eq_FK5" or "B1950" as the
-        default "eq_FK4").
-        """
-        return self._equinox
-
-    @equinox.setter
-    def equinox(self, equinox):
-        check_astroyear(equinox, 'equinox', self._config, self._pos)
-        self._equinox = equinox
-
-    @equinox.deleter
-    def equinox(self):
-        self._equinox = None
-
-    @property
-    def epoch(self):
-        """
-        Specifies the epoch of the positions.  It must be a string
-        specifying an astronomical year.
-        """
-        return self._epoch
-
-    @epoch.setter
-    def epoch(self, epoch):
-        check_astroyear(epoch, 'epoch', self._config, self._pos)
-        self._epoch = epoch
-
-    @epoch.deleter
-    def epoch(self):
-        self._epoch = None
-
-
-class FieldRef(SimpleElement, _UtypeProperty, _UcdProperty):
-    """
-    FIELDref_ element: used inside of GROUP_ elements to refer to remote FIELD_ elements.
-    """
-    _attr_list_11 = ['ref']
-    _attr_list_12 = _attr_list_11 + ['ucd', 'utype']
-    _element_name = "FIELDref"
-    _utype_in_v1_2 = True
-    _ucd_in_v1_2 = True
-
-    def __init__(self, table, ref, ucd=None, utype=None, config={}, pos=None,
-                 **extra):
-        """
-        *table* is the :class:`Table` object that this :class:`FieldRef`
-        is a member of.
-
-        *ref* is the ID to reference a :class:`Field` object defined
-        elsewhere.
-        """
-        self._config = config
-        self._pos = pos
-
-        SimpleElement.__init__(self)
-        self._table = table
-        self.ref    = ref
-        self.ucd    = ucd
-        self.utype  = utype
-
-        if config.get('version_1_2_or_later'):
-            self._attr_list = self._attr_list_12
-        else:
-            self._attr_list = self._attr_list_11
-            if ucd is not None:
-                warn_unknown_attrs(self._element_name, ['ucd'], config, pos)
-            if utype is not None:
-                warn_unknown_attrs(self._element_name, ['utype'], config, pos)
-
-    @property
-    def ref(self):
-        """The ID_ of the FIELD_ that this FIELDref_ references."""
-        return self._ref
-
-    @ref.setter
-    def ref(self, ref):
-        xmlutil.check_id(ref, 'ref', self._config, self._pos)
-        self._ref = ref
-
-    @ref.deleter
-    def ref(self):
-        self._ref = None
-
-    def get_ref(self):
-        """
-        Lookup the :class:`Field` instance that this :class:`FieldRef`
-        references.
-        """
-        for field in self._table._votable.iter_fields_and_params():
-            if isinstance(field, Field) and field.ID == self.ref:
-                return field
-        vo_raise(
-            "No field named '%s'" % self.ref,
-            self._config, self._pos, KeyError)
-
-
-class ParamRef(SimpleElement, _UtypeProperty, _UcdProperty):
-    """
-    PARAMref_ element: used inside of GROUP_ elements to refer to remote PARAM_ elements.
-
-    The keyword arguments correspond to setting members of the same
-    name, documented below.
-
-    It contains the following publicly-accessible members:
-
-      *ref*: An XML ID refering to a <PARAM> element.
-    """
-    _attr_list_11 = ['ref']
-    _attr_list_12 = _attr_list_11 + ['ucd', 'utype']
-    _element_name = "PARAMref"
-    _utype_in_v1_2 = True
-    _ucd_in_v1_2 = True
-
-    def __init__(self, table, ref, ucd=None, utype=None, config={}, pos=None):
-        self._config = config
-        self._pos = pos
-
-        Element.__init__(self)
-        self._table = table
-        self.ref    = ref
-        self.ucd    = ucd
-        self.utype  = utype
-
-        if config.get('version_1_2_or_later'):
-            self._attr_list = self._attr_list_12
-        else:
-            self._attr_list = self._attr_list_11
-            if ucd is not None:
-                warn_unknown_attrs(self._element_name, ['ucd'], config, pos)
-            if utype is not None:
-                warn_unknown_attrs(self._element_name, ['utype'], config, pos)
-
-    @property
-    def ref(self):
-        """The ID_ of the PARAM_ that this PARAMref_ references."""
-        return self._ref
-
-    @ref.setter
-    def ref(self, ref):
-        xmlutil.check_id(ref, 'ref', self._config, self._pos)
-        self._ref = ref
-
-    @ref.deleter
-    def ref(self):
-        self._ref = None
-
-    def get_ref(self):
-        """
-        Lookup the :class:`Param` instance that this :class:`PARAMref`
-        references.
-        """
-        for param in self._table._votable.iter_fields_and_params():
-            if isinstance(param, Param) and param.ID == self.ref:
-                return param
-        vo_raise(
-            "No params named '%s'" % self.ref,
-            self._config, self._pos, KeyError)
-
-
-class Group(Element, _IDProperty, _NameProperty, _UtypeProperty,
-            _UcdProperty, _DescriptionProperty):
-    """
-    GROUP_ element: groups FIELD_ and PARAM_ elements.
-
-    This information is currently ignored by the vo package---that is
-    the columns in the recarray are always flat---but the grouping
-    information is stored so that it can be written out again to the
-    XML file.
-
-    The keyword arguments correspond to setting members of the same
-    name, documented below.
-    """
-
-    def __init__(self, table, ID=None, name=None, ref=None, ucd=None,
-                 utype=None, id=None, config={}, pos=None, **extra):
-        self._config     = config
-        self._pos        = pos
-
-        Element.__init__(self)
-        self._table = table
-
-        self.ID          = (resolve_id(ID, id, config, pos)
-                            or xmlutil.fix_id(name, config, pos))
-        self.name        = name
-        self.ref         = ref
-        self.ucd         = ucd
-        self.utype       = utype
-        self.description = None
-
-        self._entries = HomogeneousList(
-            (FieldRef, ParamRef, Group, Param))
-
-        warn_unknown_attrs('GROUP', extra.iterkeys(), config, pos)
-
-    @property
-    def ref(self):
-        """
-        Currently ignored, as it's not clear from the spec how this is
-        meant to work.
-        """
-        return self._ref
-
-    @ref.setter
-    def ref(self, ref):
-        xmlutil.check_id(ref, 'ref', self._config, self._pos)
-        self._ref = ref
-
-    @ref.deleter
-    def ref(self):
-        self._ref = None
-
-    @property
-    def entries(self):
-        """
-        [read-only] A list of members of the GROUP_.  This list may
-        only contain objects of type :class:`Param`, :class:`Group`,
-        :class:`ParamRef` and :class:`FieldRef`.
-        """
-        return self._entries
-
-    def _add_fieldref(self, iterator, tag, data, config, pos):
-        fieldref = FieldRef(self._table, config=config, pos=pos, **data)
-        self.entries.append(fieldref)
-
-    def _add_paramref(self, iterator, tag, data, config, pos):
-        paramref = ParamRef(self._table, config=config, pos=pos, **data)
-        self.entries.append(paramref)
-
-    def _add_param(self, iterator, tag, data, config, pos):
-        if isinstance(self._table, VOTableFile):
-            votable = self._table
-        else:
-            votable = self._table._votable
-        param = Param(votable, config=config, pos=pos, **data)
-        self.entries.append(param)
-        param.parse(iterator, config)
-
-    def _add_group(self, iterator, tag, data, config, pos):
-        group = Group(self._table, config=config, pos=pos, **data)
-        self.entries.append(group)
-        group.parse(iterator, config)
-
-    def parse(self, iterator, config):
-        tag_mapping = {
-            'FIELDref'    : self._add_fieldref,
-            'PARAMref'    : self._add_paramref,
-            'PARAM'       : self._add_param,
-            'GROUP'       : self._add_group,
-            'DESCRIPTION' : self._ignore_add}
-
-        for start, tag, data, pos in iterator:
-            if start:
-                tag_mapping.get(tag, self._add_unknown_tag)(
-                    iterator, tag, data, config, pos)
-            else:
-                if tag == 'DESCRIPTION':
-                    if self.description is not None:
-                        warn_or_raise(W17, W17, 'GROUP', config, pos)
-                    self.description = data or None
-                elif tag == 'GROUP':
-                    break
-        return self
-
-    def to_xml(self, w, **kwargs):
-        with w.tag(
-            u'GROUP',
-            attrib=w.object_attrs(
-                self, [u'ID', u'name', u'ref', u'ucd', u'utype'])):
-            if self.description is not None:
-                w.element(u"DESCRIPTION", self.description, wrap=True)
-            for entry in self.entries:
-                entry.to_xml(w, **kwargs)
-
-    def iter_fields_and_params(self):
-        """
-        Recursively iterate over all :class:`Param` elements in this
-        :class:`Group`.
-        """
-        for entry in self.entries:
-            if isinstance(entry, Param):
-                yield entry
-            elif isinstance(entry, Group):
-                for field in entry.iter_fields_and_params():
-                    yield field
-
-    def iter_groups(self):
-        """
-        Recursively iterate over all sub-:class:`Group` instances in
-        this :class:`Group`.
-        """
-        for entry in self.entries:
-            if isinstance(entry, Group):
-                yield entry
-                for group in entry.iter_groups():
-                    yield group
-
-
-class Table(Element, _IDProperty, _NameProperty, _UcdProperty,
-            _DescriptionProperty):
-    """
-    TABLE_ element: optionally contains data.
-
-    It contains the following publicly-accessible members, all of
-    which are mutable:
-
-        *array*: A Numpy recarray of the data itself, where each row
-        is a row of votable data, and columns are named and typed
-        based on the <FIELD> elements of the table.
-
-        *mask*: A Numpy recarray of only boolean values, set to *True*
-        wherever a value is undefined.
-
-    If the Table contains no data, (for example, its enclosing
-    :class:`Resource` has :attr:`~Resource.type` == 'meta') *array*
-    and *mask* will be zero-length arrays.
-
-    .. note::
-        In a future version of the vo package, the *array* and *mask*
-        elements will likely be combined into a single Numpy masked
-        record array.  However, there are a number of deficiencies the
-        current implementation of Numpy that prevent this.
-
-    The keyword arguments correspond to setting members of the same
-    name, documented below.
-    """
-    def __init__(self, votable, ID=None, name=None, ref=None, ucd=None,
-                 utype=None, nrows=None, id=None, config={}, pos=None,
-                 **extra):
-        self._config = config
-        self._pos = pos
-        self._empty = False
-
-        Element.__init__(self)
-        self._votable = votable
-
-        self.ID = (resolve_id(ID, id, config, pos)
-                   or xmlutil.fix_id(name, config, pos))
-        self.name = name
-        xmlutil.check_id(ref, 'ref', config, pos)
-        self._ref = ref
-        self.ucd = ucd
-        self.utype = utype
-        if nrows is not None:
-            nrows = int(nrows)
-            assert nrows >= 0
-        self._nrows = nrows
-        self.description = None
-        self.format = 'tabledata'
-
-        self._fields = HomogeneousList(Field)
-        self._params = HomogeneousList(Param)
-        self._groups = HomogeneousList(Group)
-        self._links  = HomogeneousList(Link)
-        self._infos  = HomogeneousList(Info)
-
-        self.array = np.array([])
-        self.mask  = np.array([])
-
-        warn_unknown_attrs('TABLE', extra.iterkeys(), config, pos)
-
-    @property
-    def ref(self):
-        return self._ref
-
-    @ref.setter
-    def ref(self, ref):
-        """
-        Refer to another TABLE, previously defined, by the *ref* ID_
-        for all metadata (FIELD_, PARAM_ etc.) information.
-        """
-        # When the ref changes, we want to verify that it will work
-        # by actually going and looking for the referenced table.
-        # If found, set a bunch of properties in this table based
-        # on the other one.
-        xmlutil.check_id(ref, 'ref', self._config, self._pos)
-        if ref is not None:
-            try:
-                table = self._votable.get_table_by_id(ref, before=self)
-            except KeyError:
-                warn_or_raise(
-                    W43, W43, ('TABLE', self.ref), self._config, self._pos)
-                ref = None
-            else:
-                self._fields = table.fields
-                self._params = table.params
-                self._groups = table.groups
-                self._links  = table.links
-        else:
-            del self._fields[:]
-            del self._params[:]
-            del self._groups[:]
-            del self._links[:]
-        self._ref = ref
-
-    @ref.deleter
-    def ref(self):
-        self._ref = None
-
-    @property
-    def format(self):
-        """
-        [*required*] The serialization format of the table.  Must be
-        one of:
-
-          'tabledata' (TABLEDATA_), 'binary' (BINARY_), 'fits' (FITS_).
-
-        Note that the 'fits' format, since it requires an external
-        file, can not be written out.  Any file read in with 'fits'
-        format will be read out, by default, in 'tabledata' format.
-        """
-        return self._format
-
-    @format.setter
-    def format(self, format):
-        format = format.lower()
-        if format == 'fits':
-            vo_raise("fits format can not be written out, only read.",
-                     self._config, self._pos, NotImplementedError)
-        if format not in ('tabledata', 'binary'):
-            vo_raise("Invalid format '%s'" % format,
-                     self._config, self._pos)
-        self._format = format
-
-    @property
-    def nrows(self):
-        """
-        [*immutable*] The number of rows in the table, as specified in
-        the XML file.
-        """
-        return self._nrows
-
-    @property
-    def fields(self):
-        """
-        A list of :class:`Field` objects describing the types of each
-        of the data columns.
-        """
-        return self._fields
-
-    @property
-    def params(self):
-        """
-        A list of parameters (constant-valued columns) for the
-        table.  Must contain only :class:`Param` objects.
-        """
-        return self._params
-
-    @property
-    def groups(self):
-        """
-        A list of :class:`Group` objects describing how the columns
-        and parameters are grouped.  Currently this information is
-        only kept around for round-tripping and informational
-        purposes.
-        """
-        return self._groups
-
-    @property
-    def links(self):
-        """
-        A list of :class:`Link` objects (pointers to other documents
-        or servers through a URI) for the table.
-        """
-        return self._links
-
-    @property
-    def infos(self):
-        """
-        A list of :class:`Info` objects for the table.  Allows for
-        post-operational diagnostics.
-        """
-        return self._infos
-
-    def is_empty(self):
-        """
-        Returns True if this table doesn't contain any real data
-        because it was skipped over by the parser (through use of the
-        `table_number` kwarg).
-        """
-        return self._empty
-
-    def create_arrays(self, nrows=0, config={}):
-        """
-        Create new arrays to hold the data based on the current set of
-        fields, and store them in the *array* and *mask* member
-        variables.  Any data in existing arrays will be lost.
-
-        *nrows*, if provided, is the number of rows to allocate.
-        """
-        if nrows is None:
-            nrows = 0
-
-        fields = self.fields
-
-        if len(fields) == 0:
-            array = np.recarray((nrows,), dtype='O')
-            mask = np.zeros((nrows,), dtype='b')
-        else:
-            # for field in fields: field._setup(config)
-            Field.uniqify_names(fields)
-
-            dtype = []
-            for x in fields:
-                if IS_PY3K:
-                    if x._unique_name == x.ID:
-                        id = x.ID
-                    else:
-                        id = (x._unique_name, x.ID)
-                else:
-                    if x._unique_name == x.ID:
-                        id = x.ID.encode('utf-8')
-                    else:
-                        id = (x._unique_name.encode('utf-8'), x.ID.encode('utf-8'))
-                dtype.append((id, x.converter.format))
-
-            array = np.recarray((nrows,), dtype=np.dtype(dtype))
-            descr_mask = []
-            for d in array.dtype.descr:
-                new_type = (d[1][1] == 'O' and 'O') or 'bool'
-                if len(d) == 2:
-                    descr_mask.append((d[0], new_type))
-                elif len(d) == 3:
-                    descr_mask.append((d[0], new_type, d[2]))
-            mask = np.zeros((nrows,), dtype=descr_mask)
-
-        self.array = array
-        self.mask = mask
-
-    def _resize_strategy(self, size):
-        """
-        Return a new (larger) size based on size, used for
-        reallocating an array when it fills up.  This is in its own
-        function so the resizing strategy can be easily replaced.
-        """
-        # Once we go beyond 0, make a big step -- after that use a
-        # factor of 1.5 to help keep memory usage compact
-        if size == 0:
-            return 512
-        return int(np.ceil(size * RESIZE_AMOUNT))
-
-    def _add_field(self, iterator, tag, data, config, pos):
-        field = Field(self._votable, config=config, pos=pos, **data)
-        self.fields.append(field)
-        field.parse(iterator, config)
-
-    def _add_param(self, iterator, tag, data, config, pos):
-        param = Param(self._votable, config=config, pos=pos, **data)
-        self.params.append(param)
-        param.parse(iterator, config)
-
-    def _add_group(self, iterator, tag, data, config, pos):
-        group = Group(self, config=config, pos=pos, **data)
-        self.groups.append(group)
-        group.parse(iterator, config)
-
-    def _add_link(self, iterator, tag, data, config, pos):
-        link = Link(config=config, pos=pos, **data)
-        self.links.append(link)
-        link.parse(iterator, config)
-
-    def parse(self, iterator, config):
-        columns = config.get('columns')
-
-        # If we've requested to read in only a specific table, skip
-        # all others
-        table_number = config.get('table_number')
-        current_table_number = config.get('_current_table_number')
-        skip_table = False
-        if current_table_number is not None:
-            config['_current_table_number'] += 1
-            if (table_number is not None and
-                table_number != current_table_number):
-                skip_table = True
-                self._empty = True
-
-        if self.ref is not None:
-            # This table doesn't have its own datatype descriptors, it
-            # just references those from another table.
-
-            # This is to call the property setter to go and get the
-            # referenced information
-            self.ref = self.ref
-
-            for start, tag, data, pos in iterator:
-                if start:
-                    if tag == 'DATA':
-                        warn_unknown_attrs(
-                            'DATA', data.iterkeys(), config, pos)
-                        break
-                else:
-                    if tag == 'TABLE':
-                        return self
-                    elif tag == 'DESCRIPTION':
-                        if self.description is not None:
-                            warn_or_raise(W17, W17, 'RESOURCE', config, pos)
-                        self.description = data or None
-        else:
-            tag_mapping = {
-                'FIELD'       : self._add_field,
-                'PARAM'       : self._add_param,
-                'GROUP'       : self._add_group,
-                'LINK'        : self._add_link,
-                'DESCRIPTION' : self._ignore_add}
-
-            for start, tag, data, pos in iterator:
-                if start:
-                    if tag == 'DATA':
-                        warn_unknown_attrs(
-                            'DATA', data.iterkeys(), config, pos)
-                        break
-
-                    tag_mapping.get(tag, self._add_unknown_tag)(
-                        iterator, tag, data, config, pos)
-                else:
-                    if tag == 'DESCRIPTION':
-                        if self.description is not None:
-                            warn_or_raise(W17, W17, 'RESOURCE', config, pos)
-                        self.description = data or None
-                    elif tag == 'TABLE':
-                        # For error checking purposes
-                        Field.uniqify_names(self.fields)
-                        return self
-
-        self.create_arrays(nrows=self._nrows, config=config)
-        fields = self.fields
-        names = [x.ID for x in fields]
-        # Deal with a subset of the columns, if requested.
-        if not columns:
-            colnumbers = range(len(fields))
-        else:
-            if isinstance(columns, string_types):
-                columns = [columns]
-            columns = np.asarray(columns)
-            if issubclass(columns.dtype.type, np.integer):
-                if np.any(columns < 0) or np.any(columns > len(fields)):
-                    raise ValueError(
-                        "Some specified column numbers out of range")
-                colnumbers = columns
-            elif issubclass(columns.dtype.type, np.character):
-                try:
-                    colnumbers = [names.index(x) for x in columns]
-                except ValueError:
-                    raise ValueError(
-                        "Columns '%s' not found in fields list" % columns)
-            else:
-                raise TypeError("Invalid columns list")
-
-        if not skip_table:
-            for start, tag, data, pos in iterator:
-                if start:
-                    if tag == 'TABLEDATA':
-                        warn_unknown_attrs(
-                            'TABLEDATA', data.iterkeys(), config, pos)
-                        self.array, self.mask = self._parse_tabledata(
-                            iterator, colnumbers, fields, config)
-                        break
-                    elif tag == 'BINARY':
-                        warn_unknown_attrs(
-                            'BINARY', data.iterkeys(), config, pos)
-                        self.array, self.mask = self._parse_binary(
-                            iterator, colnumbers, fields, config)
-                        break
-                    elif tag == 'FITS':
-                        warn_unknown_attrs(
-                            'FITS', data.iterkeys(), config, pos, ['extnum'])
-                        try:
-                            extnum = int(data.get('extnum', 0))
-                            if extnum < 0:
-                                raise ValueError()
-                        except ValueError:
-                            vo_raise(E17, (), config, pos)
-                        self.array, self.mask = self._parse_fits(
-                            iterator, extnum, config)
-                        break
-                    else:
-                        warn_or_raise(W37, W37, tag, config, pos)
-                        break
-
-        for start, tag, data, pos in iterator:
-            if not start and tag == 'DATA':
-                break
-
-        for start, tag, data, pos in iterator:
-            if tag == 'INFO':
-                if start:
-                    if not config.get('version_1_2_or_later'):
-                        warn_or_raise(
-                            W26, W26, ('INFO', 'TABLE', '1.2'), config, pos)
-                    info = Info(config=config, pos=pos, **data)
-                    self.infos.append(info)
-                    info.parse(iterator, config)
-                else:
-                    info.content = data
-            elif not start and tag == 'TABLE':
-                break
-
-        return self
-
-    def _parse_tabledata(self, iterator, colnumbers, fields, config):
-        # Since we don't know the number of rows up front, we'll
-        # reallocate the record array to make room as we go.  This
-        # prevents the need to scan through the XML twice.  The
-        # allocation is by factors of 1.5.
-        invalid = config.get('invalid', 'exception')
-
-        array = self.array
-        mask = self.mask
-        # Need to have only one reference so that we can resize the
-        # array
-        del self.array
-        del self.mask
-
-        parsers = [field.converter.parse for field in fields]
-        binparsers = [field.converter.binparse for field in fields]
-
-        numrows = 0
-        alloc_rows = len(array)
-        colnumbers_bits = [i in colnumbers for i in range(len(fields))]
-        row_default = [x.converter.default for x in fields]
-        mask_default = [True] * len(fields)
-        array_chunk = []
-        mask_chunk = []
-        chunk_size = config.get('chunk_size', DEFAULT_CHUNK_SIZE)
-        for start, tag, data, pos in iterator:
-            if tag == 'TR':
-                # Now parse one row
-                row = row_default[:]
-                row_mask = mask_default[:]
-                i = 0
-                for start, tag, data, pos in iterator:
-                    if start:
-                        binary = (data.get('encoding', None) == 'base64')
-                        warn_unknown_attrs(
-                            tag, data.iterkeys(), config, pos, ['encoding'])
-                    else:
-                        if tag == 'TD':
-                            if i >= len(fields):
-                                vo_raise(E20, len(fields), config, pos)
-
-                            if colnumbers_bits[i]:
-                                try:
-                                    if binary:
-                                        import base64
-                                        rawdata = base64.b64decode(
-                                            data.encode('ascii'))
-                                        buf = io.BytesIO(rawdata)
-                                        buf.seek(0)
-                                        try:
-                                            value, mask_value = binparsers[i](
-                                                buf.read)
-                                        except Exception as e:
-                                            vo_reraise(
-                                                e, config, pos,
-                                                "(in row %d, col '%s')" %
-                                                (len(array_chunk),
-                                                 fields[i].ID))
-                                    else:
-                                        try:
-                                            value, mask_value = parsers[i](
-                                                data, config, pos)
-                                        except Exception as e:
-                                            vo_reraise(
-                                                e, config, pos,
-                                                "(in row %d, col '%s')" %
-                                                (len(array_chunk),
-                                                 fields[i].ID))
-                                except Exception as e:
-                                    if invalid == 'exception':
-                                        vo_reraise(e, config, pos)
-                                else:
-                                    row[i] = value
-                                    row_mask[i] = mask_value
-                        elif tag == 'TR':
-                            break
-                        else:
-                            self._add_unknown_tag(
-                                iterator, tag, data, config, pos)
-                        i += 1
-
-                if i < len(fields):
-                    vo_raise(E21, (i, len(fields)), config, pos)
-
-                array_chunk.append(tuple(row))
-                mask_chunk.append(tuple(row_mask))
-
-                if len(array_chunk) == chunk_size:
-                    while numrows + chunk_size > alloc_rows:
-                        alloc_rows = self._resize_strategy(alloc_rows)
-                    if alloc_rows != len(array):
-                        array.resize((alloc_rows,))
-                        mask.resize((alloc_rows,))
-                    array[numrows:numrows + chunk_size] = array_chunk
-                    mask[numrows:numrows + chunk_size] = mask_chunk
-                    numrows += chunk_size
-                    array_chunk = []
-                    mask_chunk = []
-
-            elif not start and tag == 'TABLEDATA':
-                break
-
-        # Now, resize the array to the exact number of rows we need and
-        # put the last chunk values in there.
-        alloc_rows = numrows + len(array_chunk)
-        array.resize((alloc_rows,))
-        mask.resize((alloc_rows,))
-        array[numrows:] = array_chunk
-        mask[numrows:] = mask_chunk
-        numrows += len(array_chunk)
-
-        if (self.nrows is not None and
-            self.nrows >= 0 and
-            self.nrows != numrows):
-            warn_or_raise(W18, W18, (self.nrows, numrows), config, pos)
-        self._nrows = numrows
-
-        return array, mask
-
-    def _parse_binary(self, iterator, colnumbers, fields, config):
-        fields = self.fields
-
-        have_local_stream = False
-        for start, tag, data, pos in iterator:
-            if tag == 'STREAM':
-                if start:
-                    warn_unknown_attrs(
-                        'STREAM', data.iterkeys(), config, pos,
-                        ['type', 'href', 'actuate', 'encoding', 'expires',
-                         'rights'])
-                    if 'href' not in data:
-                        have_local_stream = True
-                        if data.get('encoding', None) != 'base64':
-                            warn_or_raise(
-                                W38, W38, data.get('encoding', None),
-                                config, pos)
-                    else:
-                        href = data['href']
-                        xmlutil.check_anyuri(href, config, pos)
-                        encoding = data.get('encoding', None)
-                else:
-                    buffer = data
-                    break
-
-        if have_local_stream:
-            import base64
-            buffer = base64.b64decode(buffer.encode('ascii'))
-            string_io = io.BytesIO(buffer)
-            string_io.seek(0)
-            read = string_io.read
-        else:
-            if not (href.startswith('http') or
-                    href.startswith('ftp') or
-                    href.startswith('file')):
-                vo_raise(
-                    "The vo package only supports remote data through http, " +
-                    "ftp or file",
-                    self._config, self._pos, NotImplementedError)
-            import urllib2
-            fd = urllib2.urlopen(href)
-            if encoding is not None:
-                if encoding == 'gzip':
-                    from ...utils.compat import gzip
-                    fd = gzip.GzipFile(href, 'rb', fileobj=fd)
-                elif encoding == 'base64':
-                    fd = codecs.EncodedFile(fd, 'base64')
-                else:
-                    vo_raise(
-                        "Unknown encoding type '%s'" % encoding,
-                        self._config, self._pos, NotImplementedError)
-            read = fd.read
-
-        def careful_read(length):
-            result = read(length)
-            if len(result) != length:
-                raise EOFError
-            return result
-
-        array = self.array
-        mask = self.mask
-        # Need to have only one reference so that we can resize the
-        # array
-        del self.array
-        del self.mask
-
-        binparsers = [field.converter.binparse for field in fields]
-
-        numrows = 0
-        alloc_rows = len(array)
-        while True:
-            # Resize result arrays if necessary
-            if numrows >= alloc_rows:
-                alloc_rows = self._resize_strategy(alloc_rows)
-                array.resize((alloc_rows,))
-                mask.resize((alloc_rows,))
-
-            row_data = []
-            row_mask_data = []
-            try:
-                for i, binparse in enumerate(binparsers):
-                    try:
-                        value, value_mask = binparse(careful_read)
-                    except EOFError:
-                        raise
-                    except Exception as e:
-                        vo_reraise(e, config, pos,
-                                   "(in row %d, col '%s')" %
-                                   (numrows, fields[i].ID))
-                    row_data.append(value)
-                    row_mask_data.append(value_mask)
-            except EOFError:
-                break
-
-            row = [x.converter.default for x in fields]
-            row_mask = [False] * len(fields)
-            for i in colnumbers:
-                row[i] = row_data[i]
-                row_mask[i] = row_mask_data[i]
-
-            array[numrows] = tuple(row)
-            mask[numrows] = tuple(row_mask)
-            numrows += 1
-
-        array = np.resize(array, (numrows,))
-        mask = np.resize(mask, (numrows,))
-
-        return array, mask
-
-    def _parse_fits(self, iterator, extnum, config):
-        for start, tag, data, pos in iterator:
-            if tag == 'STREAM':
-                if start:
-                    warn_unknown_attrs(
-                        'STREAM', data.iterkeys(), config, pos,
-                        ['type', 'href', 'actuate', 'encoding', 'expires',
-                         'rights'])
-                    href = data['href']
-                    encoding = data.get('encoding', None)
-                else:
-                    break
-
-        if not (href.startswith('http') or
-                href.startswith('ftp') or
-                href.startswith('file')):
-            vo_raise(
-                "The vo package only supports remote data through http, "
-                "ftp or file",
-                self._config, self._pos, NotImplementedError)
-
-        import urllib2
-        fd = urllib2.urlopen(href)
-        if encoding is not None:
-            if encoding == 'gzip':
-                from ...utils.compat import gzip
-                fd = gzip.GzipFile(href, 'r', fileobj=fd)
-            elif encoding == 'base64':
-                fd = codecs.EncodedFile(fd, 'base64')
-            else:
-                vo_raise(
-                    "Unknown encoding type '%s'" % encoding,
-                    self._config, self._pos, NotImplementedError)
-
-        hdulist = fits.open(fd)
-
-        array = hdulist[int(extnum)].data
-        if array.dtype != self.array.dtype:
-            warn_or_raise(W19, W19, (), self._config, self._pos)
-
-        return array, self.mask
-
-    def to_xml(self, w, **kwargs):
-        with w.tag(
-            u'TABLE',
-            attrib=w.object_attrs(
-                self,
-                (u'ID', u'name', u'ref', u'ucd', u'utype', u'nrows'))):
-
-            if self.description is not None:
-                w.element(u"DESCRIPTION", self.description, wrap=True)
-
-            for element_set in (self.fields, self.params):
-                for element in element_set:
-                    element._setup({}, None)
-
-            if self.ref is None:
-                for element_set in (self.fields, self.params, self.groups,
-                                    self.links):
-                    for element in element_set:
-                        element.to_xml(w, **kwargs)
-
-            if len(self.array):
-                with w.tag(u'DATA'):
-                    if self.format == u'fits':
-                        self.format = u'tabledata'
-
-                    if self.format == u'tabledata':
-                        self._write_tabledata(w, **kwargs)
-                    elif self.format == u'binary':
-                        self._write_binary(w, **kwargs)
-
-            if self.ref is None and kwargs['version_1_2_or_later']:
-                for element in self._infos:
-                    element.to_xml(w, **kwargs)
-
-    def _write_tabledata(self, w, **kwargs):
-        fields = self.fields
-        array = self.array
-        mask = self.mask
-
-        write_null_values = kwargs.get('write_null_values', False)
-        with w.tag(u'TABLEDATA'):
-            w._flush()
-            if (_has_c_tabledata_writer and
-                not kwargs.get('_debug_python_based_parser')):
-                fields = [field.converter.output for field in fields]
-                indent = len(w._tags) - 1
-                tablewriter.write_tabledata(w.write, array, mask, fields,
-                                            write_null_values, indent, 1 << 8)
-            else:
-                write = w.write
-                indent_spaces = w.get_indentation_spaces()
-                tr_start = indent_spaces + u"<TR>\n"
-                tr_end = indent_spaces + u"</TR>\n"
-                td = indent_spaces + u" <TD>%s</TD>\n"
-                td_empty = indent_spaces + u" <TD/>\n"
-                fields = [(i, field.converter.output)
-                          for i, field in enumerate(fields)]
-                for row in xrange(len(array)):
-                    write(tr_start)
-                    array_row = array[row]
-                    mask_row = mask[row]
-                    for i, output in fields:
-                        masked = mask_row[i]
-                        if not np.all(masked) or write_null_values:
-                            try:
-                                val = output(array_row[i], masked)
-                            except Exception as e:
-                                vo_reraise(e,
-                                           additional="(in row %d, col '%s')" %
-                                           (row, fields[i].ID))
-                            write(td % val)
-                        else:
-                            write(td_empty)
-                    write(tr_end)
-
-    def _write_binary(self, w, **kwargs):
-        import base64
-
-        fields = self.fields
-        array = self.array
-        mask = self.mask
-
-        with w.tag(u'BINARY'):
-            with w.tag(u'STREAM', encoding='base64'):
-                fields_basic = [(i, field.converter.binoutput)
-                                for (i, field) in enumerate(fields)]
-
-                data = io.BytesIO()
-                for row in xrange(len(array)):
-                    array_row = array[row]
-                    array_mask = mask[row]
-                    for i, converter in fields_basic:
-                        try:
-                            chunk = converter(array_row[i], array_mask[i])
-                            assert type(chunk) == type(b'')
-                        except Exception as e:
-                            vo_reraise(e,
-                                       additional="(in row %d, col '%s')" %
-                                       (row, fields[i].ID))
-                        data.write(chunk)
-
-                w._flush()
-                w.write(base64.b64encode(data.getvalue()).decode('ascii'))
-
-    def iter_fields_and_params(self):
-        """
-        Recursively iterate over all FIELD and PARAM elements in the
-        TABLE.
-        """
-        for param in self.params:
-            yield param
-        for field in self.fields:
-            yield field
-        for group in self.groups:
-            for field in group.iter_fields_and_params():
-                yield field
-
-    get_field_by_id = _lookup_by_id_factory(
-        'iter_fields_and_params', 'FIELD or PARAM',
-        """
-        Looks up a FIELD or PARAM element by the given ID.
-        """)
-
-    get_field_by_id_or_name = _lookup_by_id_or_name_factory(
-        'iter_fields_and_params', 'FIELD or PARAM',
-        """
-        Looks up a FIELD or PARAM element by the given ID or name.
-        """)
-
-    def iter_groups(self):
-        """
-        Recursively iterate over all GROUP elements in the TABLE.
-        """
-        for group in self.groups:
-            yield group
-            for g in group.iter_groups():
-                yield g
-
-    get_group_by_id = _lookup_by_id_factory(
-        'iter_groups', 'GROUP',
-        """
-        Looks up a GROUP element by the given ID.  Used by the group's
-        "ref" attribute
-        """)
-
-
-class Resource(Element, _IDProperty, _NameProperty, _UtypeProperty,
-               _DescriptionProperty):
-    """
-    RESOURCE_ element: Groups TABLE_ and RESOURCE_ elements.
-
-    The keyword arguments correspond to setting members of the same
-    name, documented below.
-    """
-    def __init__(self, name=None, ID=None, utype=None, type='results',
-                 id=None, config={}, pos=None, **kwargs):
-        self._config           = config
-        self._pos              = pos
-
-        Element.__init__(self)
-        self.name              = name
-        self.ID                = resolve_id(ID, id, config, pos)
-        self.utype             = utype
-        self.type              = type
-        self._extra_attributes = kwargs
-        self.description       = None
-
-        self._coordinate_systems = HomogeneousList(CooSys)
-        self._params             = HomogeneousList(Param)
-        self._infos              = HomogeneousList(Info)
-        self._links              = HomogeneousList(Link)
-        self._tables             = HomogeneousList(Table)
-        self._resources          = HomogeneousList(Resource)
-
-        warn_unknown_attrs('RESOURCE', kwargs.iterkeys(), config, pos)
-
-    @property
-    def type(self):
-        """
-        [*required*] The type of the resource.  Must be either:
-
-          - 'results': This resource contains actual result values
-            (default)
-
-          - 'meta': This resource contains only datatype descriptions
-            (FIELD_ elements), but no actual data.
-        """
-        return self._type
-
-    @type.setter
-    def type(self, type):
-        if type not in ('results', 'meta'):
-            vo_raise(E18, type, self._config, self._pos)
-        self._type = type
-
-    @property
-    def extra_attributes(self):
-        """
-        A dictionary of string keys to string values containing any
-        extra attributes of the RESOURCE_ element that are not defined
-        in the specification.  (The specification explicitly allows
-        for extra attributes here, but nowhere else.)
-        """
-        return self._extra_attributes
-
-    @property
-    def coordinate_systems(self):
-        """
-        A list of coordinate system definitions (COOSYS_ elements) for
-        the RESOURCE_.  Must contain only `CooSys` objects.
-        """
-        return self._coordinate_systems
-
-    @property
-    def infos(self):
-        """
-        A list of informational parameters (key-value pairs) for the
-        resource.  Must only contain `Info` objects.
-        """
-        return self._infos
-
-    @property
-    def params(self):
-        """
-        A list of parameters (constant-valued columns) for the
-        resource.  Must contain only `Param` objects.
-        """
-        return self._params
-
-    @property
-    def links(self):
-        """
-        A list of links (pointers to other documents or servers
-        through a URI) for the resource.  Must contain only `Link`
-        objects.
-        """
-        return self._links
-
-    @property
-    def tables(self):
-        """
-        A list of tables in the resource.  Must contain only
-        `Table` objects.
-        """
-        return self._tables
-
-    @property
-    def resources(self):
-        """
-        A list of nested resources inside this resource.  Must contain
-        only `Resource` objects.
-        """
-        return self._resources
-
-    def _add_table(self, iterator, tag, data, config, pos):
-        table = Table(self._votable, config=config, pos=pos, **data)
-        self.tables.append(table)
-        table.parse(iterator, config)
-
-    def _add_info(self, iterator, tag, data, config, pos):
-        info = Info(config=config, pos=pos, **data)
-        self.infos.append(info)
-        info.parse(iterator, config)
-
-    def _add_param(self, iterator, tag, data, config, pos):
-        param = Param(self._votable, config=config, pos=pos, **data)
-        self.params.append(param)
-        param.parse(iterator, config)
-
-    def _add_coosys(self, iterator, tag, data, config, pos):
-        coosys = CooSys(config=config, pos=pos, **data)
-        self.coordinate_systems.append(coosys)
-        coosys.parse(iterator, config)
-
-    def _add_resource(self, iterator, tag, data, config, pos):
-        resource = Resource(config=config, pos=pos, **data)
-        self.resources.append(resource)
-        resource.parse(self._votable, iterator, config)
-
-    def _add_link(self, iterator, tag, data, config, pos):
-        link = Link(config=config, pos=pos, **data)
-        self.links.append(link)
-        link.parse(iterator, config)
-
-    def parse(self, votable, iterator, config):
-        self._votable = votable
-
-        tag_mapping = {
-            'TABLE'       : self._add_table,
-            'INFO'        : self._add_info,
-            'PARAM'       : self._add_param,
-            'COOSYS'      : self._add_coosys,
-            'RESOURCE'    : self._add_resource,
-            'LINK'        : self._add_link,
-            'DESCRIPTION' : self._ignore_add
-            }
-
-        for start, tag, data, pos in iterator:
-            if start:
-                tag_mapping.get(tag, self._add_unknown_tag)(
-                    iterator, tag, data, config, pos)
-            elif tag == 'DESCRIPTION':
-                if self.description is not None:
-                    warn_or_raise(W17, W17, 'RESOURCE', config, pos)
-                self.description = data or None
-            elif tag == 'INFO':
-                self.infos[-1].content = data
-
-        del self._votable
-
-        return self
-
-    def to_xml(self, w, **kwargs):
-        attrs = w.object_attrs(self, (u'ID', u'type', u'utype'))
-        attrs.update(self.extra_attributes)
-        with w.tag(u'RESOURCE', attrib=attrs):
-            if self.description is not None:
-                w.element(u"DESCRIPTION", self.description, wrap=True)
-            for element_set in (self.coordinate_systems, self.params,
-                                self.infos, self.links, self.tables,
-                                self.resources):
-                for element in element_set:
-                    element.to_xml(w, **kwargs)
-
-    def iter_tables(self):
-        """
-        Recursively iterates over all tables in the resource and
-        nested resources.
-        """
-        for table in self.tables:
-            yield table
-        for resource in self.resources:
-            for table in resource.iter_tables():
-                yield table
-
-    def iter_fields_and_params(self):
-        """
-        Recursively iterates over all FIELD_ and PARAM_ elements in
-        the resource, its tables and nested resources.
-        """
-        for param in self.params:
-            yield param
-        for table in self.tables:
-            for param in table.iter_fields_and_params():
-                yield param
-        for resource in self.resources:
-            for param in resource.iter_fields_and_params():
-                yield param
-
-    def iter_coosys(self):
-        """
-        Recursively iterates over all the COOSYS_ elements in the
-        resource and nested resources.
-        """
-        for coosys in self.coordinate_systems:
-            yield coosys
-        for resource in self.resources:
-            for coosys in resource.iter_coosys():
-                yield coosys
-
-
-class VOTableFile(Element, _IDProperty, _DescriptionProperty):
-    """
-    VOTABLE_ element: represents an entire file.
-
-    The keyword arguments correspond to setting members of the same
-    name, documented below.
-
-    *version* is settable at construction time only, since conformance
-    tests for building the rest of the structure depend on it.
-    """
-
-    def __init__(self, ID=None, id=None, config={}, pos=None, version="1.2"):
-        self._config             = config
-        self._pos                = pos
-
-        Element.__init__(self)
-        self.ID                  = resolve_id(ID, id, config, pos)
-        self.description         = None
-
-        self._coordinate_systems = HomogeneousList(CooSys)
-        self._params             = HomogeneousList(Param)
-        self._infos              = HomogeneousList(Info)
-        self._resources          = HomogeneousList(Resource)
-        self._groups             = HomogeneousList(Group)
-
-        version = str(version)
-        assert version in ("1.0", "1.1", "1.2")
-        self._version            = version
-
-    @property
-    def version(self):
-        """
-        The version of the VOTable specification that the file uses.
-        """
-        return self._version
-
-    @property
-    def coordinate_systems(self):
-        """
-        A list of coordinate system descriptions for the file.  Must
-        contain only `CooSys` objects.
-        """
-        return self._coordinate_systems
-
-    @property
-    def params(self):
-        """
-        A list of parameters (constant-valued columns) that apply to
-        the entire file.  Must contain only `Param` objects.
-        """
-        return self._params
-
-    @property
-    def infos(self):
-        """
-        A list of informational parameters (key-value pairs) for the
-        entire file.  Must only contain `Info` objects.
-        """
-        return self._infos
-
-    @property
-    def resources(self):
-        """
-        A list of resources, in the order they appear in the file.
-        Must only contain `Resource` objects.
-        """
-        return self._resources
-
-    @property
-    def groups(self):
-        """
-        A list of groups, in the order they appear in the file.  Only
-        supported as a child of the VOTABLE element in VOTable 1.2 or
-        later.
-        """
-        return self._groups
-
-    def _add_param(self, iterator, tag, data, config, pos):
-        param = Param(self, config=config, pos=pos, **data)
-        self.params.append(param)
-        param.parse(iterator, config)
-
-    def _add_resource(self, iterator, tag, data, config, pos):
-        resource = Resource(config=config, pos=pos, **data)
-        self.resources.append(resource)
-        resource.parse(self, iterator, config)
-
-    def _add_coosys(self, iterator, tag, data, config, pos):
-        coosys = CooSys(config=config, pos=pos, **data)
-        self.coordinate_systems.append(coosys)
-        coosys.parse(iterator, config)
-
-    def _add_info(self, iterator, tag, data, config, pos):
-        info = Info(config=config, pos=pos, **data)
-        self.infos.append(info)
-        info.parse(iterator, config)
-
-    def _add_group(self, iterator, tag, data, config, pos):
-        if not config.get('version_1_2_or_later'):
-            warn_or_raise(W26, W26, ('GROUP', 'VOTABLE', '1.2'), config, pos)
-        group = Group(self, config=config, pos=pos, **data)
-        self.groups.append(group)
-        group.parse(iterator, config)
-
-    def parse(self, iterator, config):
-        config['_current_table_number'] = 0
-
-        for start, tag, data, pos in iterator:
-            if start:
-                if tag == 'xml':
-                    pass
-                elif tag == 'VOTABLE':
-                    if 'version' not in data:
-                        warn_or_raise(W20, W20, self.version, config, pos)
-                        config['version'] = self.version
-                    else:
-                        config['version'] = self._version = data['version']
-                        if config['version'].lower().startswith('v'):
-                            warn_or_raise(
-                                W29, W29, config['version'], config, pos)
-                            self._version = config['version'] = \
-                                            config['version'][1:]
-                        if config['version'] not in ('1.1', '1.2'):
-                            vo_warn(W21, config['version'], config, pos)
-
-                    if 'xmlns' in data:
-                        correct_ns = ('http://www.ivoa.net/xml/VOTable/v%s' %
-                                      config['version'])
-                        if data['xmlns'] != correct_ns:
-                            vo_warn(
-                                W41, (correct_ns, data['xmlns']), config, pos)
-                    else:
-                        vo_warn(W42, (), config, pos)
-
-                    break
-                else:
-                    vo_raise(E19, (), config, pos)
-        config['version_1_1_or_later'] = \
-            util.version_compare(config['version'], '1.1') >= 0
-        config['version_1_2_or_later'] = \
-            util.version_compare(config['version'], '1.2') >= 0
-
-        tag_mapping = {
-            'PARAM'       : self._add_param,
-            'RESOURCE'    : self._add_resource,
-            'COOSYS'      : self._add_coosys,
-            'INFO'        : self._add_info,
-            'DEFINITIONS' : self._add_definitions,
-            'DESCRIPTION' : self._ignore_add,
-            'GROUP'       : self._add_group}
-
-        for start, tag, data, pos in iterator:
-            if start:
-                tag_mapping.get(tag, self._add_unknown_tag)(
-                    iterator, tag, data, config, pos)
-            elif tag == 'DESCRIPTION':
-                if self.description is not None:
-                    warn_or_raise(W17, W17, 'VOTABLE', config, pos)
-                self.description = data or None
-            elif tag == 'INFO':
-                self.infos[-1].content = data
-        return self
-
-    def to_xml(self, fd, write_null_values=False,
-               compressed=False,
-               _debug_python_based_parser=False,
-               _astropy_version=None):
-        """
-        Write to an XML file.
-
-        Parameters
-        ----------
-        fd : str path or writable file-like object
-           Where to write the file.
-
-        write_null_values : bool, optional
-           When `True`, write the 'null' value (specified in the null
-           attribute of the VALUES element for each FIELD) for empty
-           values.  When False (default), simply write no value.
-
-        compressed : bool, optional
-           When `True`, write to a gzip-compressed file.  (Default:
-           `False`)
-        """
-        kwargs = {
-            'write_null_values': write_null_values,
-            'version': self.version,
-            'version_1_1_or_later':
-                util.version_compare(self.version, u'1.1') >= 0,
-            'version_1_2_or_later':
-                util.version_compare(self.version, u'1.2') >= 0,
-            '_debug_python_based_parser': _debug_python_based_parser}
-
-        with util.convert_to_writable_filelike(
-            fd, compressed=compressed) as fd:
-            w = XMLWriter(fd)
-            version = self.version
-            if _astropy_version is None:
-                lib_version = astropy_version
-            else:
-                lib_version = _astropy_version
-
-            xml_header = u"""
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Produced with astropy.io.vo version %(lib_version)s
-     http://www.astropy.org/ -->\n"""
-            w.write(xml_header.lstrip() % locals())
-
-            with w.tag(u'VOTABLE',
-                       {u'version': version,
-                        u'xmlns:xsi':
-                            u"http://www.w3.org/2001/XMLSchema-instance",
-                        u'xsi:noNamespaceSchemaLocation':
-                            u"http://www.ivoa.net/xml/VOTable/v%s" % version,
-                        u'xmlns':
-                            u"http://www.ivoa.net/xml/VOTable/v%s" % version}):
-                if self.description is not None:
-                    w.element(u"DESCRIPTION", self.description, wrap=True)
-                element_sets = [self.coordinate_systems, self.params,
-                                self.infos, self.resources]
-                if kwargs['version_1_2_or_later']:
-                    element_sets[0] = self.groups
-                for element_set in element_sets:
-                    for element in element_set:
-                        element.to_xml(w, **kwargs)
-
-    def iter_tables(self):
-        """
-        Iterates over all tables in the VOTable file in a "flat" way,
-        ignoring the nesting of resources etc.
-        """
-        for resource in self.resources:
-            for table in resource.iter_tables():
-                yield table
-
-    def get_first_table(self):
-        """
-        Often, you know there is only one table in the file, and
-        that's all you need.  This method returns that first table.
-        """
-        for table in self.iter_tables():
-            if not table.is_empty():
-                return table
-        raise IndexError("No table found in VOTABLE file.")
-
-    get_table_by_id = _lookup_by_id_factory(
-        'iter_tables', 'TABLE',
-        """
-        Looks up a TABLE_ element by the given ID.  Used by the table
-        "ref" attribute.
-        """)
-
-    def get_table_by_index(self, idx):
-        """
-        Get a table by its ordinal position in the file.
-        """
-        for i, table in enumerate(self.iter_tables()):
-            if i == idx:
-                return table
-        raise IndexError("No table at index %d found in VOTABLE file." % idx)
-
-    def iter_fields_and_params(self):
-        """
-        Recursively iterate over all FIELD_ and PARAM_ elements in the
-        VOTABLE_ file.
-        """
-        for resource in self.resources:
-            for field in resource.iter_fields_and_params():
-                yield field
-
-    get_field_by_id = _lookup_by_id_factory(
-        'iter_fields_and_params', 'FIELD',
-        """
-        Looks up a FIELD_ element by the given ID_.  Used by the field's
-        "ref" attribute.
-        """)
-
-    get_field_by_id_or_name = _lookup_by_id_or_name_factory(
-        'iter_fields_and_params', 'FIELD',
-        """
-        Looks up a FIELD_ element by the given ID_ or name.
-        """)
-
-    def iter_values(self):
-        """
-        Recursively iterate over all VALUES_ elements in the VOTABLE_
-        file.
-        """
-        for field in self.iter_fields_and_params():
-            yield field.values
-
-    get_values_by_id = _lookup_by_id_factory(
-        'iter_values', 'VALUES',
-        """
-        Looks up a VALUES_ element by the given ID.  Used by the values
-        "ref" attribute.
-        """)
-
-    def iter_groups(self):
-        """
-        Recursively iterate over all GROUP_ elements in the VOTABLE_
-        file.
-        """
-        for table in self.iter_tables():
-            for group in table.iter_groups():
-                yield group
-
-    get_group_by_id = _lookup_by_id_factory(
-        'iter_groups', 'GROUP',
-        """
-        Looks up a GROUP_ element by the given ID.  Used by the group's
-        "ref" attribute
-        """)
-
-    def iter_coosys(self):
-        """
-        Recursively iterate over all COOSYS_ elements in the VOTABLE_
-        file.
-        """
-        for coosys in self.coordinate_systems:
-            yield coosys
-        for resource in self.resources:
-            for coosys in resource.iter_coosys():
-                yield coosys
-
-    get_coosys_by_id = _lookup_by_id_factory(
-        'iter_coosys', 'COOSYS',
-        """Looks up a COOSYS_ element by the given ID.""")
-
-    def set_all_tables_format(self, format):
-        """
-        Set the output storage format of all tables in the file.
-        """
-        for table in self.iter_tables():
-            table.format = format
diff --git a/astropy/io/vo/ucd.py b/astropy/io/vo/ucd.py
deleted file mode 100644
index 2ee0a43..0000000
--- a/astropy/io/vo/ucd.py
+++ /dev/null
@@ -1,187 +0,0 @@
-"""
-This file contains routines to verify the correctness of UCD strings.
-"""
-
-from __future__ import with_statement, absolute_import
-
-#STDLIB
-import re
-
-#LOCAL
-from ... import config
-
-__all__ = ['parse_ucd', 'check_ucd']
-
-
-class UCDWords:
-    """
-    Manages a list of acceptable UCD words.
-
-    Works by reading in a data file exactly as provided by IVOA.  This
-    file resides in data/ucd1p-words.txt.
-    """
-    def __init__(self):
-        self._primary = set()
-        self._secondary = set()
-        self._descriptions = {}
-        self._capitalization = {}
-
-        with config.get_data_fileobj("data/ucd1p-words.txt") as fd:
-            for line in fd.readlines():
-                type, name, descr = [
-                    x.strip().decode('ascii') for x in line.split(b'|')]
-                name_lower = name.lower()
-                if type in u'QPEV':
-                    self._primary.add(name_lower)
-                if type in u'QSEV':
-                    self._secondary.add(name_lower)
-                self._descriptions[name_lower] = descr
-                self._capitalization[name_lower] = name
-
-    def is_primary(self, name):
-        """
-        Returns True if *name* is a valid primary name.
-        """
-        return name.lower() in self._primary
-
-    def is_secondary(self, name):
-        """
-        Returns True if *name* is a valid secondary name.
-        """
-        return name.lower() in self._secondary
-
-    def get_description(self, name):
-        """
-        Returns the official English description of the given UCD
-        *name*.
-        """
-        return self._descriptions[name.lower()]
-
-    def normalize_capitalization(self, name):
-        """
-        Returns the standard capitalization form of the given name.
-        """
-        return self._capitalization[name.lower()]
-
-_ucd_singleton = None
-
-
-def parse_ucd(ucd, check_controlled_vocabulary=False, has_colon=False):
-    """
-    Parse the UCD into its component parts.
-
-    Parameters
-    ----------
-    ucd : str
-        The UCD string
-
-    check_controlled_vocabulary : bool, optional
-        If `True`, then each word in the UCD will be verified against
-        the UCD1+ controlled vocabulary, (as required by the VOTable
-        specification version 1.2), otherwise not.
-
-    has_colon : bool, optional
-        If `True`, the UCD may contain a colon (as defined in earlier
-        versions of the standard).
-
-    Returns
-    -------
-    parts : list
-        The result is a list of tuples of the form:
-
-            (*namespace*, *word*)
-
-        If no namespace was explicitly specified, *namespace* will be
-        returned as ``'ivoa'`` (i.e., the default namespace).
-
-    Raises
-    ------
-    ValueError : *ucd* is invalid
-    """
-    global _ucd_singleton
-    if _ucd_singleton is None:
-        _ucd_singleton = UCDWords()
-
-    if has_colon:
-        m = re.search(u'[^A-Za-z0-9_.:;\-]', ucd)
-    else:
-        m = re.search(u'[^A-Za-z0-9_.;\-]', ucd)
-    if m is not None:
-        raise ValueError("UCD has invalid character '%s' in '%s'" %
-                         (m.group(0), ucd))
-
-    word_component_re = u'[A-Za-z0-9][A-Za-z0-9\-_]*'
-    word_re = u'%s(\.%s)*' % (word_component_re, word_component_re)
-
-    parts = ucd.split(u';')
-    words = []
-    for i, word in enumerate(parts):
-        colon_count = word.count(u':')
-        if colon_count == 1:
-            ns, word = word.split(u':', 1)
-            if not re.match(word_component_re, ns):
-                raise ValueError("Invalid namespace '%s'" % ns)
-            ns = ns.lower()
-        elif colon_count > 1:
-            raise ValueError("Too many colons in '%s'" % word)
-        else:
-            ns = u'ivoa'
-
-        if not re.match(word_re, word):
-            raise ValueError("Invalid word '%s'" % word)
-
-        if ns == u'ivoa' and check_controlled_vocabulary:
-            if i == 0:
-                if not _ucd_singleton.is_primary(word):
-                    if _ucd_singleton.is_secondary(word):
-                        raise ValueError(
-                            "Secondary word '%s' is not valid as a primary "
-                            "word" % word)
-                    else:
-                        raise ValueError("Unknown word '%s'" % word)
-            else:
-                if not _ucd_singleton.is_secondary(word):
-                    if _ucd_singleton.is_primary(word):
-                        raise ValueError(
-                            "Primary word '%s' is not valid as a secondary "
-                            "word" % word)
-                    else:
-                        raise ValueError("Unknown word '%s'" % word)
-
-        try:
-            normalized_word = _ucd_singleton.normalize_capitalization(word)
-        except KeyError:
-            normalized_word = word
-        words.append((ns, normalized_word))
-
-    return words
-
-
-def check_ucd(ucd, check_controlled_vocabulary=False, has_colon=False):
-    """
-    Returns False if *ucd* is not a valid `unified content descriptor`_.
-
-    Parameters
-    ----------
-    ucd : str
-        The UCD string
-
-    check_controlled_vocabulary : bool, optional
-        If `True`, then each word in the UCD will be verified against
-        the UCD1+ controlled vocabulary, (as required by the VOTable
-        specification version 1.2), otherwise not.
-
-    Returns
-    -------
-    valid : bool
-    """
-    if ucd is None:
-        return True
-
-    try:
-        parse_ucd(ucd,
-                  check_controlled_vocabulary=check_controlled_vocabulary,
-                  has_colon=has_colon)
-    except ValueError:
-        return False
-    return True
diff --git a/astropy/io/vo/unit.py b/astropy/io/vo/unit.py
deleted file mode 100644
index 8ad7253..0000000
--- a/astropy/io/vo/unit.py
+++ /dev/null
@@ -1,56 +0,0 @@
-"""
-Tools to verify the syntax of unit attributes according to the
-`Standards for Astronomical Catalogues, Version 2.0
-<http://cdsarc.u-strasbg.fr/doc/catstd-3.2.htx>`_
-"""
-
-# STDLIB
-import re
-
-# LOCAL
-from .exceptions import warn_or_raise, W50
-
-
-__all__ = ['unit_names', 'unit_prefixes', 'is_unit', 'check_unit']
-
-
-unit_names = u"""
-    - % a A AU arcmin arcsec barn bit byte C cd ct D d deg eV F g h H
-    Hz J Jy K lm lx m mag mas min mol N Ohm Pa pc pix rad Ry s S
-    solLum solMass solRad Sun sr T V W Wb yr
-    """.split()
-
-
-unit_prefixes = u"""
-    d c m u n p f a z y da h k M G T P E Z Y
-    """.split()
-
-
-_unit_name_regex = u'|'.join(u'(?:{0})'.format(x) for x in unit_names)
-_unit_prefix_regex = u'|'.join(u'(?:{0})'.format(x) for x in unit_prefixes)
-
-
-def is_unit(s):
-    """
-    Returns `True` if *s* is a valid unit string as defined by `Standards for Astronomical Catalogues, Version 2.0 <http://cdsarc.u-strasbg.fr/doc/catstd-3.2.htx>`_.
-    """
-    number = ur'[+\-]?[0-9]+(?:\.[0-9]*)?(?:[+\-][0-9]+)?'
-    factor = ur'{0}(?:x{0})?'.format(number)
-    unit = ur'(?:{0})?(?:{1})'.format(_unit_prefix_regex, _unit_name_regex)
-    bracketed_unit = ur'(?:{0})|(?:\[{0}\])'.format(unit)
-    expression = (
-        ur'^(?P<factor>{0})?(?P<unit>{1})(?P<subunit>[/.]{1})?(?P<power>{2})?$'.format(
-        factor, bracketed_unit, number))
-
-    match = re.match(expression, s)
-    return match is not None
-
-
-def check_unit(unit, attr_name, config={}, pos=None):
-    """
-    Raises a `ValueError` if *unit* is not a valid unit as defined by `Standards for Astronomical Catalogues, Version 2.0 <http://cdsarc.u-strasbg.fr/doc/catstd-3.2.htx>`_.
-    """
-    if (unit is not None and not is_unit(unit)):
-        warn_or_raise(W50, W50, unit, config, pos)
-        return False
-    return True
diff --git a/astropy/io/vo/validator/main.py b/astropy/io/vo/validator/main.py
deleted file mode 100644
index bd0efd7..0000000
--- a/astropy/io/vo/validator/main.py
+++ /dev/null
@@ -1,163 +0,0 @@
-"""
-Validates a large collection of web-accessible VOTable files,
-and generates a report as a directory tree of HTML files.
-"""
-from __future__ import print_function
-
-# STDLIB
-import os
-
-# LOCAL
-from ....config import get_data_filename
-from . import html
-from . import result
-
-
-__all__ = ['make_validation_report']
-
-
-
-def get_srcdir():
-    return os.path.dirname(__file__)
-
-
-def get_urls(destdir, s):
-    import gzip
-
-    types = ['good', 'broken', 'incorrect']
-
-    seen = set()
-    urls = []
-    for type in types:
-        filename = get_data_filename(
-            'astropy/io/vo/validator/urls/cone.{0}.dat.gz'.format(type))
-        with gzip.open(filename, 'rb') as fd:
-            for url in fd.readlines():
-                s.next()
-                url = url.strip()
-                if url not in seen:
-                    with result.Result(url, root=destdir) as r:
-                        r['expected'] = type
-                    urls.append(url)
-                seen.add(url)
-
-    return urls
-
-
-def download(args):
-    url, destdir = args
-    with result.Result(url, root=destdir) as r:
-        r.download_xml_content()
-
-
-def validate_vo(args):
-    url, destdir = args
-    with result.Result(url, root=destdir) as r:
-        r.validate_vo()
-
-
-def votlint_validate(args):
-    path_to_stilts_jar, url, destdir = args
-    with result.Result(url, root=destdir) as r:
-        if r['network_error'] is None:
-            r.validate_with_votlint(path_to_stilts_jar)
-
-
-def write_html_result(args):
-    url, destdir = args
-    with result.Result(url, root=destdir) as r:
-        html.write_result(r)
-
-
-def write_subindex(args):
-    subset, destdir, total = args
-    html.write_index_table(destdir, *subset, total=total)
-
-
-def make_validation_report(
-    urls=None, destdir='astropy.io.vo.validator.results', multiprocess=True,
-    stilts=None):
-    """
-    Validates a large collection of web-accessible VOTable files.
-
-    Generates a report as a directory tree of HTML files.
-
-    Parameters
-    ----------
-    urls : list of strings, optional
-        If provided, is a list of HTTP urls to download VOTable files
-        from.  If not provided, a built-in set of ~22,000 urls
-        compiled by HEASARC will be used.
-
-    destdir : path, optional
-        The directory to write the report to.  By default, this is a
-        directory called `astropy.io.vo.validator.results` in the
-        current directory.  If the directory does not exist, it will
-        be created.
-
-    multiprocess : bool, optional
-        If `True` (default), perform validations in parallel using all
-        of the cores on this machine.
-
-    stilts : path, optional
-        To perform validation with `votlint` from the the Java-based
-        `STILTS <http://www.star.bris.ac.uk/~mbt/stilts/>`_ VOTable
-        parser, in addition to `astropy.io.vo`, set this to the path
-        of the `stilts.jar` file.  `java` on the system shell path
-        will be used to run it.
-
-    Notes
-    -----
-    Downloads of each given URL will be performed only once and cached
-    locally in *destdir*.  To refresh the cache, remove *destdir*
-    first.
-    """
-    from ....utils.console import (color_print, ProgressBar, Spinner)
-
-    if stilts is not None:
-        if not os.path.exists(stilts):
-            raise ValueError(
-                '{0} does not exist.'.format(stilts))
-
-    destdir = os.path.abspath(destdir)
-
-    if urls is None:
-        with Spinner('Loading URLs', 'green') as s:
-            urls = get_urls(destdir, s)
-    else:
-        color_print('Marking URLs', 'green')
-        for url in ProgressBar.iterate(urls):
-            with result.Result(url, root=destdir) as r:
-                r['expected'] = type
-
-    args = [(url, destdir) for url in urls]
-
-    color_print('Downloading VO files', 'green')
-    ProgressBar.map(
-        download, args, multiprocess=multiprocess)
-
-    color_print('Validating VO files', 'green')
-    ProgressBar.map(
-        validate_vo, args, multiprocess=multiprocess)
-
-    if stilts is not None:
-        color_print('Validating with votlint', 'green')
-        votlint_args = [(stilts, x, destdir) for x in urls]
-        ProgressBar.map(
-            votlint_validate, votlint_args, multiprocess=multiprocess)
-
-
-    color_print('Generating HTML files', 'green')
-    ProgressBar.map(
-        write_html_result, args, multiprocess=multiprocess)
-
-    with Spinner('Grouping results', 'green') as s:
-        subsets = result.get_result_subsets(urls, destdir, s)
-
-    color_print('Generating index', 'green')
-    html.write_index(subsets, urls, destdir)
-
-    color_print('Generating subindices', 'green')
-    subindex_args = [(subset, destdir, len(urls)) for subset in subsets]
-    ProgressBar.map(
-        write_subindex, subindex_args, multiprocess=multiprocess)
diff --git a/astropy/io/vo/validator/result.py b/astropy/io/vo/validator/result.py
deleted file mode 100644
index 283a662..0000000
--- a/astropy/io/vo/validator/result.py
+++ /dev/null
@@ -1,335 +0,0 @@
-"""
-Contains a class to handle a validation result for a single VOTable
-file.
-"""
-
-from __future__ import absolute_import
-
-# STDLIB
-import hashlib
-import httplib
-import os
-import cPickle as pickle
-import shutil
-import socket
-import subprocess
-import urllib2
-import warnings
-
-# VO
-from .. import table
-from .. import exceptions
-from .. import xmlutil
-from ..util import IS_PY3K
-
-
-class Result:
-    def __init__(self, url, root='results'):
-        self.url = url
-        m = hashlib.md5()
-        m.update(url)
-        self._hash = m.hexdigest()
-        self._root = root
-        self._path = os.path.join(
-            self._hash[0:2], self._hash[2:4], self._hash[4:])
-        if not os.path.exists(self.get_dirpath()):
-            os.makedirs(self.get_dirpath())
-        self.load_attributes()
-
-    def __enter__(self):
-        return self
-
-    def __exit__(self, *args):
-        self.save_attributes()
-
-    def get_dirpath(self):
-        return os.path.join(self._root, self._path)
-
-    def get_htmlpath(self):
-        return self._path
-
-    def get_attribute_path(self):
-        return os.path.join(self.get_dirpath(), "values.dat")
-
-    def get_vo_xml_path(self):
-        return os.path.join(self.get_dirpath(), "vo.xml")
-
-    # ATTRIBUTES
-
-    def load_attributes(self):
-        path = self.get_attribute_path()
-        if os.path.exists(path):
-            try:
-                with open(path, 'rb') as fd:
-                    self._attributes = pickle.load(fd)
-            except:
-                shutil.rmtree(self.get_dirpath())
-                os.makedirs(self.get_dirpath())
-                self._attributes = {}
-        else:
-            self._attributes = {}
-
-    def save_attributes(self):
-        path = self.get_attribute_path()
-        with open(path, 'wb') as fd:
-            pickle.dump(self._attributes, fd)
-
-    def __getitem__(self, key):
-        return self._attributes[key]
-
-    def __setitem__(self, key, val):
-        self._attributes[key] = val
-
-    def __contains__(self, key):
-        return key in self._attributes
-
-    # VO XML
-
-    def download_xml_content(self):
-        path = self.get_vo_xml_path()
-
-        if 'network_error' not in self._attributes:
-            self['network_error'] = None
-
-        if os.path.exists(path):
-            return
-
-        def fail(reason):
-            reason = str(reason)
-            with open(path, 'wb') as fd:
-                fd.write("FAILED: %s\n" % reason)
-            self['network_error'] = reason
-
-        r = None
-        try:
-            if IS_PY3K:
-                r = urllib2.urlopen(self.url.decode('ascii'))
-            else:
-                r = urllib2.urlopen(self.url, timeout=10)
-        except urllib2.URLError as e:
-            if hasattr(e, 'reason'):
-                reason = e.reason
-            else:
-                reason = e.code
-            fail(reason)
-            return
-        except httplib.HTTPException as e:
-            fail("HTTPException: %s" % str(e))
-            return
-        except socket.timeout as e:
-            fail("Timeout")
-            return
-
-        if r is None:
-            fail("Invalid URL")
-            return
-
-        try:
-            content = r.read()
-        except socket.timeout as e:
-            fail("Timeout")
-            return
-        else:
-            r.close()
-
-        with open(path, 'wb') as fd:
-            fd.write(content)
-
-    def get_xml_content(self):
-        path = self.get_vo_xml_path()
-        if not os.path.exists(path):
-            self.download_xml_content()
-        with open(path, 'rb') as fd:
-            content = fd.read()
-        return content
-
-    def validate_vo(self):
-        path = self.get_vo_xml_path()
-        if not os.path.exists(path):
-            self.download_xml_content()
-        self['version'] = ''
-        if self['network_error'] is not None:
-            self['nwarnings'] = 0
-            self['nexceptions'] = 0
-            self['warnings'] = []
-            self['xmllint'] = None
-            self['warning_types'] = set()
-            return
-
-        nexceptions = 0
-        nwarnings = 0
-        t = None
-        lines = []
-        with open(path, 'rb') as input:
-            with warnings.catch_warnings(record=True) as warning_lines:
-                try:
-                    t = table.parse(input, pedantic=False, filename=path)
-                except ValueError as e:
-                    lines.append(str(e))
-                    nexceptions += 1
-        lines = [str(x.message) for x in warning_lines] + lines
-
-        if t is not None:
-            self['version'] = version = t.version
-        else:
-            self['version'] = version = "1.0"
-
-        if 'xmllint' not in self:
-            # Now check the VO schema based on the version in
-            # the file.
-            success, stdout, stderr = xmlutil.validate_schema(path, version)
-            self['xmllint'] = (success == 0)
-            self['xmllint_content'] = stderr
-
-        warning_types = set()
-        for line in lines:
-            w = exceptions.parse_vowarning(line)
-            if w['is_warning']:
-                nwarnings += 1
-            if w['is_exception']:
-                nexceptions += 1
-            warning_types.add(w['warning'])
-
-        self['nwarnings'] = nwarnings
-        self['nexceptions'] = nexceptions
-        self['warnings'] = lines
-        self['warning_types'] = warning_types
-
-    def has_warning(self, warning_code):
-        return warning_code in self['warning_types']
-
-    def match_expectations(self):
-        if self['expected'] == 'good':
-            return (not self['network_error'] and
-                    self['nwarnings'] == 0 and
-                    self['nexceptions'] == 0)
-        elif self['expected'] == 'incorrect':
-            return (not self['network_error'] and
-                    (self['nwarnings'] > 0 or
-                     self['nexceptions'] > 0))
-        elif self['expected'] == 'broken':
-            return self['network_error'] is not None
-
-    def validate_with_votlint(self, path_to_stilts_jar):
-        filename = self.get_vo_xml_path()
-        p = subprocess.Popen(
-            "java -jar %s votlint validate=false %s" %
-            (path_to_stilts_jar, filename),
-            shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
-        stdout, stderr = p.communicate()
-        if len(stdout) or p.returncode:
-            self['votlint'] = False
-        else:
-            self['votlint'] = True
-        self['votlint_content'] = stdout
-
-
-def get_result_subsets(results, root, s=None):
-    all_results      = []
-    not_expected     = []
-    fail_schema      = []
-    schema_mismatch  = []
-    fail_votlint     = []
-    votlint_mismatch = []
-    network_failures = []
-    version_10       = []
-    version_11       = []
-    version_12       = []
-    version_unknown  = []
-    has_warnings     = []
-    warning_set      = {}
-    has_exceptions   = []
-    exception_set    = {}
-
-    for url in results:
-        if s:
-            s.next()
-
-        x = Result(url, root=root)
-        all_results.append(x)
-        if not x.match_expectations():
-            not_expected.append(x)
-        if x['xmllint'] is False:
-            fail_schema.append(x)
-        if (x['xmllint'] is False and
-            x['nwarnings'] == 0 and
-            x['nexceptions'] == 0):
-            schema_mismatch.append(x)
-        if 'votlint' in x and x['votlint'] is False:
-            fail_votlint.append(x)
-            if (x['nwarnings'] == 0 and
-                x['nexceptions'] == 0 and
-                x['network_error'] is None):
-                votlint_mismatch.append(x)
-        if x['network_error'] is not None:
-            network_failures.append(x)
-        version = x['version']
-        if version == '1.0':
-            version_10.append(x)
-        elif version == '1.1':
-            version_11.append(x)
-        elif version == '1.2':
-            version_12.append(x)
-        else:
-            version_unknown.append(x)
-        if x['nwarnings'] > 0:
-            has_warnings.append(x)
-            for warning in x['warning_types']:
-                if (warning is not None and
-                    len(warning) == 3 and
-                    warning.startswith('W')):
-                    warning_set.setdefault(warning, [])
-                    warning_set[warning].append(x)
-        if x['nexceptions'] > 0:
-            has_exceptions.append(x)
-            for exc in x['warning_types']:
-                if exc is not None and len(exc) == 3 and exc.startswith('E'):
-                    exception_set.setdefault(exc, [])
-                    exception_set[exc].append(x)
-
-    warning_set = list(warning_set.items())
-    warning_set.sort()
-    exception_set = list(exception_set.items())
-    exception_set.sort()
-
-    tables = [
-        ('all', u'All tests', all_results),
-        ('unexpected', u'Unexpected', not_expected),
-        ('schema', u'Invalid against schema', fail_schema),
-        ('schema_mismatch', u'Invalid against schema/Passed vo.table',
-         schema_mismatch, ['ul']),
-        ('fail_votlint', u'Failed votlint', fail_votlint),
-        ('votlint_mismatch', u'Failed votlint/Passed vo.table',
-         votlint_mismatch, ['ul']),
-        ('network_failures', u'Network failures', network_failures),
-        ('version1.0', 'Version 1.0', version_10),
-        ('version1.1', 'Version 1.1', version_11),
-        ('version1.2', 'Version 1.2', version_12),
-        ('version_unknown', 'Version unknown', version_unknown),
-        ('warnings', 'Warnings', has_warnings)]
-    for warning_code, warnings in warning_set:
-        if s:
-            s.next()
-
-        warning_class = getattr(exceptions, warning_code, None)
-        if warning_class:
-            warning_descr = warning_class.get_short_name()
-            tables.append(
-                (warning_code,
-                 '%s: %s' % (warning_code, warning_descr),
-                 warnings, ['ul', 'li']))
-    tables.append(
-        ('exceptions', 'Exceptions', has_exceptions))
-    for exception_code, exc in exception_set:
-        if s:
-            s.next()
-
-        exception_class = getattr(exceptions, exception_code, None)
-        if exception_class:
-            exception_descr = exception_class.get_short_name()
-            tables.append(
-                (exception_code,
-                 '%s: %s' % (exception_code, exception_descr),
-                 exc, ['ul', 'li']))
-
-    return tables
diff --git a/astropy/io/vo/voexceptions.py b/astropy/io/vo/voexceptions.py
deleted file mode 100644
index a30f585..0000000
--- a/astropy/io/vo/voexceptions.py
+++ /dev/null
@@ -1,6 +0,0 @@
-import warnings
-warnings.warn(
-    "astropy.io.vo.voexceptions is deprecated.  Use astropy.io.vo.exceptions",
-    DeprecationWarning)
-
-from .exceptions import *
diff --git a/astropy/io/vo/xmlutil.py b/astropy/io/vo/xmlutil.py
deleted file mode 100644
index f616cfe..0000000
--- a/astropy/io/vo/xmlutil.py
+++ /dev/null
@@ -1,121 +0,0 @@
-"""
-Various XML-related utilities
-"""
-
-from __future__ import division, absolute_import
-
-# ASTROPY
-from ...utils.xml import check as xml_check
-from ...utils.xml import validate
-
-# LOCAL
-from .exceptions import (warn_or_raise, vo_warn,
-     W02, W03, W04, W05)
-from ... import config
-
-
-__all__ = [
-    'check_id', 'fix_id', 'check_token', 'check_mime_content_type',
-    'check_anyuri', 'validate_schema'
-    ]
-
-
-def check_id(ID, name='ID', config={}, pos=None):
-    """
-    Raises a `~astropy.io.vo.exceptions.VOTableSpecError` if *ID* is not a valid XML ID_.
-
-    *name* is the name of the attribute being checked (used only for
-    error messages).
-    """
-    if (ID is not None and not xml_check.check_id(ID)):
-        warn_or_raise(W02, W02, (name, ID), config, pos)
-        return False
-    return True
-
-
-def fix_id(ID, config={}, pos=None):
-    """
-    Given an arbitrary string, create one that can be used as an xml id.
-
-    This is rather simplistic at the moment, since it just replaces
-    non-valid characters with underscores.
-    """
-    if ID is None:
-        return None
-    corrected = xml_check.fix_id(ID)
-    if corrected != ID:
-        vo_warn(W03, (ID, corrected), config, pos)
-    return corrected
-
-
-_token_regex = r"(?![\r\l\t ])[^\r\l\t]*(?![\r\l\t ])"
-
-
-def check_token(token, attr_name, config={}, pos=None):
-    """
-    Raises a `ValueError` if *token* is not a valid XML token.
-
-    As defined by XML Schema Part 2.
-    """
-    if (token is not None and not xml_check.check_token(token)):
-        return False
-    return True
-
-
-def check_mime_content_type(content_type, config={}, pos=None):
-    """
-    Raises a `~astropy.io.vo.exceptions.VOTableSpecError` if *content_type* is not a valid MIME content type.
-
-    As defined by RFC 2045 (syntactically, at least).
-    """
-    if (content_type is not None and
-        not xml_check.check_mime_content_type(content_type)):
-        warn_or_raise(W04, W04, content_type, config, pos)
-        return False
-    return True
-
-
-def check_anyuri(uri, config={}, pos=None):
-    """
-    Raises a `~astropy.io.vo.exceptions.VOTableSpecError` if *uri* is not a valid URI.
-
-    As defined in RFC 2396.
-    """
-    if (uri is not None and not xml_check.check_anyuri(uri)):
-        warn_or_raise(W05, W05, uri, config, pos)
-        return False
-    return True
-
-
-def validate_schema(filename, version='1.2'):
-    """
-    Validates the given file against the appropriate VOTable schema.
-
-    Parameters
-    ----------
-    filename : str
-        The path to the XML file to validate
-
-    version : str
-        The VOTABLE version to check, which must be a string \"1.0\",
-        \"1.1\", or \"1.2\".
-
-        For version \"1.0\", it is checked against a DTD, since that
-        version did not have an XML Schema.
-
-    Returns
-    -------
-    returncode, stdout, stderr : int, str, str
-        Returns the returncode from xmllint and the stdout and stderr
-        as strings
-    """
-    assert version in ('1.0', '1.1', '1.2')
-
-    if version in ('1.1', '1.2'):
-        schema_path = config.get_data_filename(
-            'data/VOTable.v{0}.xsd'.format(version))
-    else:
-        schema_path = config.get_data_filename(
-            'data/VOTable.dtd')
-
-    return validate.validate_schema(filename, schema_path)
diff --git a/astropy/io/votable/__init__.py b/astropy/io/votable/__init__.py
new file mode 100644
index 0000000..5cd2579
--- /dev/null
+++ b/astropy/io/votable/__init__.py
@@ -0,0 +1,16 @@
+# Licensed under a 3-clause BSD style license - see LICENSE.rst
+"""
+This package reads and writes data formats used by the Virtual
+Observatory (VO) initiative, particularly the VOTable XML format.
+"""
+
+from .table import (
+    parse, parse_single_table, validate, from_table, is_votable)
+from .exceptions import (
+    VOWarning, VOTableChangeWarning, VOTableSpecWarning, UnimplementedWarning,
+    IOWarning, VOTableSpecError)
+
+__all__ = [
+    'parse', 'parse_single_table', 'validate', 'from_table',
+    'is_votable', 'VOWarning', 'VOTableChangeWarning', 'VOTableSpecWarning',
+    'UnimplementedWarning', 'IOWarning', 'VOTableSpecError']
diff --git a/astropy/io/votable/connect.py b/astropy/io/votable/connect.py
new file mode 100644
index 0000000..69bcedd
--- /dev/null
+++ b/astropy/io/votable/connect.py
@@ -0,0 +1,119 @@
+# Licensed under a 3-clause BSD style license - see LICENSE.rst
+
+from __future__ import print_function
+
+import os
+
+from . import parse, from_table
+from .tree import VOTableFile, Table
+from ...utils import OrderedDict
+from ...table import io_registry
+
+
+def is_votable(origin, args, kwargs):
+    """
+    Reads the header of a file to determine if it is a VOTable file.
+
+    Parameters
+    ----------
+    origin : str or readable file-like object
+        Path or file object containing a VOTABLE_ xml file.
+
+    Returns
+    -------
+    is_votable : bool
+        Returns `True` if the given file is a VOTable file.
+    """
+    from . import is_votable
+    if origin == 'read':
+        if isinstance(args[0], basestring) or hasattr(args[0], 'read'):
+            return is_votable(args[0])
+        elif isinstance(args[0], (VOTableFile, Table)):
+            return True
+        else:
+            return False
+    else:
+        return False
+
+
+def read_table_votable(input, table_id=None):
+    """
+    Read a Table object from an VO table file
+
+    Parameters
+    ----------
+    input : str or `astropy.io.votable.tree.VOTableFile` or `astropy.io.votable.tree.Table`
+        If a string, the filename to read the table from. If a
+        :class:`~astropy.io.votable.tree.VOTableFile` or
+        :class:`~astropy.io.votable.tree.Table` object, the object to extract
+        the table from.
+    table_id : str, optional
+        The ID of the table to read in.
+    """
+    if not isinstance(input, (VOTableFile, Table)):
+        input = parse(input, table_id=table_id)
+
+    # Parse all table objects
+    tables = OrderedDict()
+    if isinstance(input, VOTableFile):
+        for table in input.iter_tables():
+            if table.ID is not None:
+                tables[table.ID] = table
+
+        if len(tables) > 1:
+            if table_id is None:
+                raise ValueError(
+                    "Multiple tables found: table id should be set via "
+                    "the table_id= argument. The available tables are " +
+                    ', '.join(tables.keys()))
+            else:
+                if table_id in tables:
+                    table = tables[table_id]
+                else:
+                    raise ValueError(
+                        "No tables with id={0} found".format(table_id))
+        elif len(tables) == 1:
+            table = tables[tables.keys()[0]]
+        else:
+            raise ValueError("No table found")
+    elif isinstance(input, Table):
+        table = input
+
+    # Convert to an astropy.table.Table object
+    return table.to_table()
+
+
+def write_table_votable(input, output, table_id=None, overwrite=False):
+    """
+    Write a Table object to an VO table file
+
+    Parameters
+    ----------
+    input : Table
+        The table to write out.
+    output : str
+        The filename to write the table to.
+    table_id : str
+        The table ID to use. If this is not specified, the 'ID' keyword in the
+        ``meta`` object of the table will be used.
+    overwrite : bool
+        Whether to overwrite any existing file without warning.
+    """
+
+    # Check if output file already exists
+    if isinstance(output, basestring) and os.path.exists(output):
+        if overwrite:
+            os.remove(output)
+        else:
+            raise IOError("File exists: {0}".format(output))
+
+    # Create a new VOTable file
+    table_file = from_table(input, table_id=table_id)
+
+    # Write out file
+    table_file.to_xml(output)
+
+
+io_registry.register_reader('votable', read_table_votable)
+io_registry.register_writer('votable', write_table_votable)
+io_registry.register_identifier('votable', is_votable)
diff --git a/astropy/io/votable/converters.py b/astropy/io/votable/converters.py
new file mode 100644
index 0000000..b80fbbc
--- /dev/null
+++ b/astropy/io/votable/converters.py
@@ -0,0 +1,1328 @@
+"""
+This module handles the conversion of various VOTABLE datatypes
+to/from TABLEDATA_ and BINARY_ formats.
+"""
+
+from __future__ import division, absolute_import
+
+# STDLIB
+import re
+from struct import unpack as struct_unpack
+from struct import pack as struct_pack
+
+# THIRD-PARTY
+import numpy as np
+from numpy import ma
+
+# ASTROPY
+from ...utils.xml.writer import xml_escape_cdata
+
+# LOCAL
+from .exceptions import (vo_raise, vo_warn, warn_or_raise, W01,
+    W30, W31, W39, W46, W47, W49, E01, E02, E03, E04, E05, E06)
+from .util import IS_PY3K
+
+
+__all__ = ['get_converter', 'Converter', 'table_column_to_votable_datatype']
+
+
+pedantic_array_splitter = re.compile(r" +")
+array_splitter = re.compile(r"\s+|(?:\s*,\s*)")
+"""
+A regex to handle splitting values on either whitespace or commas.
+
+SPEC: Usage of commas is not actually allowed by the spec, but many
+files in the wild use them.
+"""
+
+_zero_int = b'\0\0\0\0'
+_empty_bytes = b''
+_zero_byte = b'\0'
+
+
+def _make_masked_array(data, mask):
+    """
+    Masked arrays of zero length that also have a mask of zero length
+    cause problems in Numpy (at least in 1.6.2).  This function
+    creates a masked array from data and a mask, unless it is zero
+    length.
+    """
+    # np.ma doesn't like setting mask to []
+    if len(data):
+        return ma.array(
+            np.array(data),
+            mask=np.array(mask, dtype='bool'))
+    else:
+        return ma.array(np.array(data))
+
+
+class Converter(object):
+    """
+    The base class for all converters.  Each subclass handles
+    converting a specific VOTABLE data type to/from the TABLEDATA_ and
+    BINARY_ on-disk representations.
+
+    Parameters
+    ----------
+    field : `~astropy.io.votable.table.Field`
+        object describing the datatype
+
+    config : dict
+        The parser configuration dictionary
+
+    pos : tuple
+        The position in the XML file where the FIELD object was
+        found.  Used for error messages.
+
+    """
+    def __init__(self, field, config={}, pos=None):
+        pass
+
+    @staticmethod
+    def _parse_length(read):
+        return struct_unpack(">I", read(4))[0]
+
+    @staticmethod
+    def _write_length(length):
+        return struct_pack(">I", int(length))
+
+    def parse(self, value, config={}, pos=None):
+        """
+        Convert the string *value* from the TABLEDATA_ format into an
+        object with the correct native in-memory datatype and mask flag.
+
+        Parameters
+        ----------
+        value : str
+            value in TABLEDATA format
+
+        Returns
+        -------
+        native : tuple (value, mask)
+            The value as a Numpy array or scalar, and *mask* is True
+            if the value is missing.
+        """
+        raise NotImplementedError(
+            "This datatype must implement a 'parse' method.")
+
+    def parse_scalar(self, value, config={}, pos=None):
+        """
+        Parse a single scalar of the underlying type of the converter.
+        For non-array converters, this is equivalent to parse.  For
+        array converters, this is used to parse a single
+        element of the array.
+
+        Parameters
+        ----------
+        value : str
+            value in TABLEDATA format
+
+        Returns
+        -------
+        native : tuple (value, mask)
+            The value as a Numpy array or scalar, and *mask* is True
+            if the value is missing.
+        """
+        return self.parse(value, config, pos)
+
+    def output(self, value, mask):
+        """
+        Convert the object *value* (in the native in-memory datatype)
+        to a unicode string suitable for serializing in the TABLEDATA_
+        format.
+
+        Parameters
+        ----------
+        value : native type corresponding to this converter
+            The value
+
+        mask : bool
+            If `True`, will return the string representation of a
+            masked value.
+
+        Returns
+        -------
+        tabledata_repr : unicode
+        """
+        raise NotImplementedError(
+            "This datatype must implement a 'output' method.")
+
+    def binparse(self, read):
+        """
+        Reads some number of bytes from the BINARY_ format
+        representation by calling the function *read*, and returns the
+        native in-memory object representation for the datatype
+        handled by *self*.
+
+        Parameters
+        ----------
+        read : function
+            A function that given a number of bytes, returns a byte
+            string.
+
+        Returns
+        -------
+        native : tuple (value, mask)
+            The value as a Numpy array or scalar, and *mask* is True
+            if the value is missing.
+        """
+        raise NotImplementedError(
+            "This datatype must implement a 'binparse' method.")
+
+    def binoutput(self, value, mask):
+        """
+        Convert the object *value* in the native in-memory datatype to
+        a string of bytes suitable for serialization in the BINARY_
+        format.
+
+        Parameters
+        ----------
+        value : native type corresponding to this converter
+            The value
+
+        mask : bool
+            If `True`, will return the string representation of a
+            masked value.
+
+        Returns
+        -------
+        bytes : byte string
+            The binary representation of the value, suitable for
+            serialization in the BINARY_ format.
+        """
+        raise NotImplementedError(
+            "This datatype must implement a 'binoutput' method.")
+
+
+class Char(Converter):
+    """
+    Handles the char datatype. (7-bit unsigned characters)
+
+    Missing values are not handled for string or unicode types.
+    """
+    default = _empty_bytes
+
+    def __init__(self, field, config={}, pos=None):
+        Converter.__init__(self, field, config, pos)
+
+        if field.arraysize is None:
+            vo_warn(W47, (), config, pos)
+            field.arraysize = '1'
+
+        if field.arraysize == '*':
+            self.format = 'O'
+            self.binparse = self._binparse_var
+            self.binoutput = self._binoutput_var
+            self.arraysize = '*'
+        else:
+            if field.arraysize.endswith('*'):
+                field.arraysize = field.arraysize[:-1]
+            try:
+                self.arraysize = int(field.arraysize)
+            except ValueError:
+                vo_raise(E01, (field.arraysize, 'char', field.ID), config)
+            self.format = 'S%d' % self.arraysize
+            self.binparse = self._binparse_fixed
+            self.binoutput = self._binoutput_fixed
+            self._struct_format = ">%ds" % self.arraysize
+
+        if config.get('pedantic'):
+            self.parse = self._ascii_parse
+        else:
+            self.parse = self._str_parse
+
+    def _ascii_parse(self, value, config={}, pos=None):
+        if self.arraysize != '*' and len(value) > self.arraysize:
+            vo_warn(W46, ('char', self.arraysize), config, pos)
+        return value.encode('ascii'), False
+
+    def _str_parse(self, value, config={}, pos=None):
+        if self.arraysize != '*' and len(value) > self.arraysize:
+            vo_warn(W46, ('char', self.arraysize), config, pos)
+        return value.encode('utf-8'), False
+
+    def output(self, value, mask):
+        if mask:
+            return u''
+        if not isinstance(value, str):
+            value = value.decode('ascii')
+        return xml_escape_cdata(value)
+
+    def _binparse_var(self, read):
+        length = self._parse_length(read)
+        return read(length), False
+
+    def _binparse_fixed(self, read):
+        s = struct_unpack(self._struct_format, read(self.arraysize))[0]
+        end = s.find(_zero_byte)
+        if end != -1:
+            return s[:end], False
+        return s, False
+
+    def _binoutput_var(self, value, mask):
+        if mask or value is None or value == u'':
+            return _zero_int
+        return self._write_length(len(value)) + value
+
+    def _binoutput_fixed(self, value, mask):
+        if mask:
+            value = _empty_bytes
+        return struct_pack(self._struct_format, value)
+
+
+class UnicodeChar(Converter):
+    """
+    Handles the unicodeChar data type. UTF-16-BE.
+
+    Missing values are not handled for string or unicode types.
+    """
+    default = u''
+
+    def __init__(self, field, config={}, pos=None):
+        Converter.__init__(self, field, config, pos)
+
+        if field.arraysize is None:
+            vo_warn(W47, (), config, pos)
+            field.arraysize = '1'
+
+        if field.arraysize == '*':
+            self.format = 'O'
+            self.binparse = self._binparse_var
+            self.binoutput = self._binoutput_var
+            self.arraysize = '*'
+        else:
+            try:
+                self.arraysize = int(field.arraysize)
+            except ValueError:
+                vo_raise(E01, (field.arraysize, 'unicode', field.ID), config)
+            self.format = 'U%d' % self.arraysize
+            self.binparse = self._binparse_fixed
+            self.binoutput = self._binoutput_fixed
+            self._struct_format = ">%ds" % (self.arraysize * 2)
+
+    def parse(self, value, config={}, pos=None):
+        if self.arraysize != '*' and len(value) > self.arraysize:
+            vo_warn(W46, ('unicodeChar', self.arraysize), config, pos)
+        return value, False
+
+    def output(self, value, mask):
+        if mask:
+            return u''
+        return xml_escape_cdata(unicode(value))
+
+    def _binparse_var(self, read):
+        length = self._parse_length(read)
+        return read(length * 2).decode('utf_16_be'), False
+
+    def _binparse_fixed(self, read):
+        s = struct_unpack(self._struct_format, read(self.arraysize * 2))[0]
+        s = s.decode('utf_16_be')
+        end = s.find('\0')
+        if end != -1:
+            return s[:end], False
+        return s, False
+
+    def _binoutput_var(self, value, mask):
+        if mask or value is None or value == '':
+            return _zero_int
+        encoded = value.encode('utf_16_be')
+        return self._write_length(len(encoded) / 2) + encoded
+
+    def _binoutput_fixed(self, value, mask):
+        if mask:
+            value = u''
+        return struct_pack(self._struct_format, value.encode('utf_16_be'))
+
+
+class Array(Converter):
+    """
+    Handles both fixed and variable-lengths arrays.
+    """
+    def __init__(self, field, config={}, pos=None):
+        Converter.__init__(self, field, config, pos)
+
+        if config.get('pedantic'):
+            self._splitter = self._splitter_pedantic
+        else:
+            self._splitter = self._splitter_lax
+
+    def parse_scalar(self, value, config={}, pos=0):
+        return self._base.parse_scalar(value, config, pos)
+
+    @staticmethod
+    def _splitter_pedantic(value, config={}, pos=None):
+        return pedantic_array_splitter.split(value)
+
+    @staticmethod
+    def _splitter_lax(value, config={}, pos=None):
+        if ',' in value:
+            vo_warn(W01, (), config, pos)
+        return array_splitter.split(value)
+
+
+class VarArray(Array):
+    """
+    Handles variable lengths arrays (i.e. where *arraysize* is '*').
+    """
+    format = 'O'
+
+    def __init__(self, field, base, arraysize, config={}, pos=None):
+        Array.__init__(self, field, config)
+
+        self._base = base
+        self.default = np.array([], dtype=self._base.format)
+
+    def output(self, value, mask):
+        output = self._base.output
+        result = [output(x, m) for x, m in np.broadcast(value, value.mask)]
+        return u' '.join(result)
+
+    def binparse(self, read):
+        length = self._parse_length(read)
+
+        result = []
+        result_mask = []
+        binparse = self._base.binparse
+        for i in xrange(length):
+            val, mask = binparse(read)
+            result.append(val)
+            result_mask.append(mask)
+
+        return _make_masked_array(result, result_mask), False
+
+    def binoutput(self, value, mask):
+        if value is None or len(value) == 0:
+            return _zero_int
+
+        length = len(value)
+        result = [self._write_length(length)]
+        binoutput = self._base.binoutput
+        for x, m in zip(value, value.mask):
+            result.append(binoutput(x, m))
+        return _empty_bytes.join(result)
+
+
+class ArrayVarArray(VarArray):
+    """
+    Handles an array of variable-length arrays, i.e. where *arraysize*
+    ends in '*'.
+    """
+    def parse(self, value, config={}, pos=None):
+        if value.strip() == '':
+            return ma.array([]), False
+
+        parts = self._splitter(value, config, pos)
+        items = self._base._items
+        parse_parts = self._base.parse_parts
+        if len(parts) % items != 0:
+            vo_raise(E02, (items, len(parts)), config, pos)
+        result = []
+        result_mask = []
+        for i in xrange(0, len(parts), items):
+            value, mask = parse_parts(parts[i:i+items], config, pos)
+            result.append(value)
+            result_mask.append(mask)
+
+        return _make_masked_array(result, result_mask), False
+
+
+class ScalarVarArray(VarArray):
+    """
+    Handles a variable-length array of numeric scalars.
+    """
+    def parse(self, value, config={}, pos=None):
+        if value.strip() == '':
+            return ma.array([]), False
+
+        parts = self._splitter(value, config, pos)
+
+        parse = self._base.parse
+        result = []
+        result_mask = []
+        for x in parts:
+            value, mask = parse(x, config, pos)
+            result.append(value)
+            result_mask.append(mask)
+
+        return _make_masked_array(result, result_mask), False
+
+
+class NumericArray(Array):
+    """
+    Handles a fixed-length array of numeric scalars.
+    """
+    vararray_type = ArrayVarArray
+
+    def __init__(self, field, base, arraysize, config={}, pos=None):
+        Array.__init__(self, field, config, pos)
+
+        self._base = base
+        self._arraysize = arraysize
+        self.format = "%s%s" % (tuple(arraysize), base.format)
+
+        self._items = 1
+        for dim in arraysize:
+            self._items *= dim
+
+        self._memsize = np.dtype(self.format).itemsize
+        self._bigendian_format = '>' + self.format
+
+        self.default = (
+            np.ones(arraysize, dtype=self._base.format) *
+            self._base.default)
+
+    def parse(self, value, config={}, pos=None):
+        parts = self._splitter(value, config, pos)
+        if len(parts) != self._items:
+            warn_or_raise(E02, E02, (self._items, len(parts)), config, pos)
+        if config.get('pedantic'):
+            return self.parse_parts(parts, config, pos)
+        else:
+            if len(parts) == self._items:
+                pass
+            elif len(parts) > self._items:
+                parts = parts[:self._items]
+            else:
+                parts = (parts +
+                         ([self._base.default] * (self._items - len(parts))))
+            return self.parse_parts(parts, config, pos)
+
+    def parse_parts(self, parts, config={}, pos=None):
+        base_parse = self._base.parse
+        result = []
+        result_mask = []
+        for x in parts:
+            value, mask = base_parse(x, config, pos)
+            result.append(value)
+            result_mask.append(mask)
+        result = np.array(result, dtype=self._base.format).reshape(
+            self._arraysize)
+        result_mask = np.array(result_mask, dtype='bool').reshape(
+            self._arraysize)
+        return result, result_mask
+
+    def output(self, value, mask):
+        base_output = self._base.output
+        value = np.asarray(value)
+        mask = np.asarray(mask)
+        return u' '.join(base_output(x, m) for x, m in
+                         zip(value.flat, mask.flat))
+
+    def binparse(self, read):
+        result = np.fromstring(read(self._memsize),
+                               dtype=self._bigendian_format)[0]
+        result_mask = self._base.is_null(result)
+        return result, result_mask
+
+    def binoutput(self, value, mask):
+        filtered = self._base.filter_array(value, mask)
+        if filtered.dtype.byteorder != '>':
+            filtered = filtered.byteswap()
+        return filtered.tostring()
+
+
+class Numeric(Converter):
+    """
+    The base class for all numeric data types.
+    """
+    array_type = NumericArray
+    vararray_type = ScalarVarArray
+    null = None
+
+    def __init__(self, field, config={}, pos=None):
+        Converter.__init__(self, field, config, pos)
+
+        self._memsize = np.dtype(self.format).itemsize
+        self._bigendian_format = '>' + self.format
+        if field.values.null is not None:
+            self.null = np.asarray(field.values.null, dtype=self.format)
+            self.default = self.null
+            self.is_null = self._is_null
+        else:
+            self.is_null = np.isnan
+
+    def binparse(self, read):
+        result = np.fromstring(read(self._memsize),
+                               dtype=self._bigendian_format)
+        return result[0], self.is_null(result[0])
+
+    def _is_null(self, value):
+        return value == self.null
+
+
+class FloatingPoint(Numeric):
+    """
+    The base class for floating-point datatypes.
+    """
+    default = np.nan
+
+    def __init__(self, field, config={}, pos=None):
+        Numeric.__init__(self, field, config, pos)
+
+        precision = field.precision
+        width = field.width
+        format_parts = [u'%']
+
+        if width is not None:
+            format_parts.append(unicode(width))
+
+        if precision is None:
+            format_parts.append(u'g')
+        elif precision.startswith("E"):
+            format_parts.append(u'.%dg' % int(precision[1:]))
+        elif precision.startswith("F"):
+            format_parts.append(u'.%df' % int(precision[1:]))
+        else:
+            format_parts.append(u'.%df' % int(precision))
+
+        self._output_format = u''.join(format_parts)
+
+        self.nan = np.array(np.nan, self.format)
+
+        if self.null is None:
+            self._null_output = u'NaN'
+            self._null_binoutput = self.binoutput(self.nan, False)
+            self.filter_array = self._filter_nan
+        else:
+            self._null_output = self.output(np.asarray(self.null), False)
+            self._null_binoutput = self.binoutput(np.asarray(self.null), False)
+            self.filter_array = self._filter_null
+
+        if config.get('pedantic'):
+            self.parse = self._parse_pedantic
+        else:
+            self.parse = self._parse_permissive
+
+    def _parse_pedantic(self, value, config={}, pos=None):
+        if value.strip() == '':
+            return self.null, True
+        f = float(value)
+        return f, self.is_null(f)
+
+    def _parse_permissive(self, value, config={}, pos=None):
+        try:
+            f = float(value)
+            return f, self.is_null(f)
+        except ValueError:
+            # IRSA VOTables use the word 'null' to specify empty values,
+            # but this is not defined in the VOTable spec.
+            if value.strip() != '':
+                vo_warn(W30, value, config, pos)
+            return self.null, True
+
+    @property
+    def output_format(self):
+        return self._output_format
+
+    def output(self, value, mask):
+        if mask:
+            return self._null_output
+        if np.isfinite(value):
+            return self._output_format % value
+        elif np.isnan(value):
+            return u'NaN'
+        elif np.isposinf(value):
+            return u'+InF'
+        elif np.isneginf(value):
+            return u'-InF'
+        # Should never raise
+        vo_raise("Invalid floating point value '%s'" % value)
+
+    def binoutput(self, value, mask):
+        if mask:
+            return self._null_binoutput
+
+        if value.dtype.byteorder != '>':
+            value = value.byteswap()
+        return value.tostring()
+
+    def _filter_nan(self, value, mask):
+        return np.where(mask, np.nan, value)
+
+    def _filter_null(self, value, mask):
+        return np.where(mask, self.null, value)
+
+
+class Double(FloatingPoint):
+    """
+    Handles the double datatype.  Double-precision IEEE
+    floating-point.
+    """
+    format = 'f8'
+
+
+class Float(FloatingPoint):
+    """
+    Handles the float datatype.  Single-precision IEEE floating-point.
+    """
+    format = 'f4'
+
+
+class Integer(Numeric):
+    """
+    The base class for all the integral datatypes.
+    """
+    default = 0
+
+    def __init__(self, field, config={}, pos=None):
+        Numeric.__init__(self, field, config, pos)
+
+    def parse(self, value, config={}, pos=None):
+        mask = False
+        if isinstance(value, basestring):
+            value = value.lower()
+            if value == '':
+                warn_or_raise(W49, W49, (), config, pos)
+                if self.null is not None:
+                    value = self.null
+                else:
+                    value = self.default
+            elif value == 'nan':
+                mask = True
+                if self.null is None:
+                    warn_or_raise(W31, W31, (), config, pos)
+                    value = self.default
+                else:
+                    value = self.null
+            elif value.startswith('0x'):
+                value = int(value[2:], 16)
+            else:
+                value = int(value, 10)
+        else:
+            value = int(value)
+        if self.null is not None and value == self.null:
+            mask = True
+        return value, mask
+
+    def output(self, value, mask):
+        if mask:
+            if self.null is None:
+                warn_or_raise(W31, W31)
+                return u'NaN'
+            return unicode(self.null)
+        return unicode(value)
+
+    def binoutput(self, value, mask):
+        if mask:
+            if self.null is None:
+                vo_raise(W31)
+            else:
+                value = self.null
+        if value.dtype.byteorder != '>':
+            value = value.byteswap()
+        return value.tostring()
+
+    def filter_array(self, value, mask):
+        if np.any(mask):
+            if self.null is not None:
+                return np.where(mask, self.null, value)
+            else:
+                vo_raise(W31)
+        return value
+
+
+class UnsignedByte(Integer):
+    """
+    Handles the unsignedByte datatype.  Unsigned 8-bit integer.
+    """
+    format = 'u1'
+
+
+class Short(Integer):
+    """
+    Handles the short datatype.  Signed 16-bit integer.
+    """
+    format = 'i2'
+
+
+class Int(Integer):
+    """
+    Handles the int datatype.  Signed 32-bit integer.
+    """
+    format = 'i4'
+
+
+class Long(Integer):
+    """
+    Handles the long datatype.  Signed 64-bit integer.
+    """
+    format = 'i8'
+
+
+class ComplexArrayVarArray(VarArray):
+    """
+    Handles an array of variable-length arrays of complex numbers.
+    """
+    def __init__(self, field, base, arraysize, config={}, pos=None):
+        VarArray.__init__(self, field, base, arraysize, config, pos)
+
+    def parse(self, value, config={}, pos=None):
+        if value.strip() == '':
+            return ma.array([]), False
+
+        parts = self._splitter(value, config, pos)
+        items = self._base._items
+        parse_parts = self._base.parse_parts
+        if len(parts) % items != 0:
+            vo_raise(E02, (items, len(parts)), config, pos)
+        result = []
+        result_mask = []
+        for i in xrange(0, len(parts), items):
+            value, mask = parse_parts(parts[i:i + items], config, pos)
+            result.append(value)
+            result_mask.append(mask)
+
+        return _make_masked_array(result, result_mask), False
+
+
+class ComplexVarArray(VarArray):
+    """
+    Handles a variable-length array of complex numbers.
+    """
+    def __init__(self, field, base, arraysize, config={}, pos=None):
+        VarArray.__init__(self, field, base, arraysize, config, pos)
+
+    def parse(self, value, config={}, pos=None):
+        if value.strip() == '':
+            return ma.array([]), False
+
+        parts = self._splitter(value, config, pos)
+        parse_parts = self._base.parse_parts
+        result = []
+        result_mask = []
+        for i in xrange(0, len(parts), 2):
+            value = [float(x) for x in parts[i:i + 2]]
+            value, mask = parse_parts(value, config, pos)
+            result.append(value)
+            result_mask.append(mask)
+
+        return _make_masked_array(
+            np.array(result, dtype=self._base.format), result_mask), False
+
+
+class ComplexArray(NumericArray):
+    """
+    Handles a fixed-size array of complex numbers.
+    """
+    vararray_type = ComplexArrayVarArray
+
+    def __init__(self, field, base, arraysize, config={}, pos=None):
+        NumericArray.__init__(self, field, base, arraysize, config, pos)
+        self._items *= 2
+
+    def parse(self, value, config={}, pos=None):
+        parts = self._splitter(value, config, pos)
+        if parts == ['']:
+            parts = []
+        return self.parse_parts(parts, config, pos)
+
+    def parse_parts(self, parts, config={}, pos=None):
+        if len(parts) != self._items:
+            vo_raise(E02, (self._items, len(parts)), config, pos)
+        base_parse = self._base.parse_parts
+        result = []
+        result_mask = []
+        for i in xrange(0, self._items, 2):
+            value = [float(x) for x in parts[i:i + 2]]
+            value, mask = base_parse(value, config, pos)
+            result.append(value)
+            result_mask.append(mask)
+        result = np.array(
+            result, dtype=self._base.format).reshape(self._arraysize)
+        result_mask = np.array(
+            result_mask, dtype='bool').reshape(self._arraysize)
+        return result, result_mask
+
+
+class Complex(FloatingPoint, Array):
+    """
+    The base class for complex numbers.
+    """
+    array_type = ComplexArray
+    vararray_type = ComplexVarArray
+    default = np.nan
+
+    def __init__(self, field, config={}, pos=None):
+        FloatingPoint.__init__(self, field, config, pos)
+        Array.__init__(self, field, config, pos)
+
+        self._output_format = self._output_format + " " + self._output_format
+
+    def parse(self, value, config={}, pos=None):
+        if value.strip() == '':
+            return np.nan, True
+        splitter = self._splitter
+        parts = [float(x) for x in splitter(value, config, pos)]
+        if len(parts) != 2:
+            vo_raise(E03, (value,), config, pos)
+        return self.parse_parts(parts, config, pos)
+    _parse_permissive = parse
+    _parse_pedantic = parse
+
+    def parse_parts(self, parts, config={}, pos=None):
+        value = complex(*parts)
+        return value, self.is_null(value)
+
+    def output(self, value, mask):
+        if mask:
+            if self.null is None:
+                return u'NaN'
+            else:
+                value = self.null
+        return self._output_format % (value.real, value.imag)
+
+
+class FloatComplex(Complex):
+    """
+    Handle floatComplex datatype.  Pair of single-precision IEEE
+    floating-point numbers.
+    """
+    format = 'c8'
+
+
+class DoubleComplex(Complex):
+    """
+    Handle doubleComplex datatype.  Pair of double-precision IEEE
+    floating-point numbers.
+    """
+    format = 'c16'
+
+
+class BitArray(NumericArray):
+    """
+    Handles an array of bits.
+    """
+    vararray_type = ArrayVarArray
+
+    def __init__(self, field, base, arraysize, config={}, pos=None):
+        NumericArray.__init__(self, field, base, arraysize, config, pos)
+
+        self._bytes = ((self._items - 1) // 8) + 1
+
+    @staticmethod
+    def _splitter_pedantic(value, config={}, pos=None):
+        return list(re.sub('\s', '', value))
+
+    @staticmethod
+    def _splitter_lax(value, config={}, pos=None):
+        if ',' in value:
+            vo_warn(W01, (), config, pos)
+        return list(re.sub('\s|,', '', value))
+
+    def output(self, value, mask):
+        value = np.asarray(value)
+        mapping = {False: u'0', True: u'1'}
+        return u''.join(mapping[x] for x in value.flat)
+
+    def binparse(self, read):
+        data = read(self._bytes)
+        results = []
+        for byte in data:
+            if not IS_PY3K:
+                byte = ord(byte)
+            for bit_no in range(7, -1, -1):
+                bit = byte & (1 << bit_no)
+                bit = (bit != 0)
+                results.append(bit)
+                if len(results) == self._items:
+                    break
+            if len(results) == self._items:
+                break
+
+        result = np.array(results, dtype='b1').reshape(self._arraysize)
+        result_mask = np.zeros(self._arraysize, dtype='b1')
+        return result, result_mask
+
+    def binoutput(self, value, mask):
+        if np.any(mask):
+            vo_warn(W39)
+
+        value = value.flat
+        bit_no = 7
+        byte = 0
+        bytes = []
+        for v in value:
+            if v:
+                byte |= 1 << bit_no
+            if bit_no == 0:
+                bytes.append(byte)
+                bit_no = 7
+                byte = 0
+            else:
+                bit_no -= 1
+        if bit_no != 7:
+            bytes.append(byte)
+
+        assert len(bytes) == self._bytes
+
+        return struct_pack("%sB" % len(bytes), *bytes)
+
+
+class Bit(Converter):
+    """
+    Handles the bit datatype.
+    """
+    format = 'b1'
+    array_type = BitArray
+    vararray_type = ScalarVarArray
+    default = False
+    binary_one = b'\x08'
+    binary_zero = b'\0'
+
+    def __init__(self, field, config={}, pos=None):
+        Converter.__init__(self, field, config, pos)
+
+    def parse(self, value, config={}, pos=None):
+        mapping = {'1': True, '0': False}
+        if value is False or value.strip() == '':
+            warn_or_raise(W49, W49, (), config, pos)
+            return False, True
+        else:
+            try:
+                return mapping[value], False
+            except KeyError:
+                vo_raise(E04, (value,), config, pos)
+
+    def output(self, value, mask):
+        if mask:
+            vo_warn(W39)
+
+        if value:
+            return u'1'
+        else:
+            return u'0'
+
+    def binparse(self, read):
+        data = read(1)
+        return (ord(data) & 0x8) != 0, False
+
+    def binoutput(self, value, mask):
+        if mask:
+            vo_warn(W39)
+
+        if value:
+            return self.binary_one
+        return self.binary_zero
+
+
+class BooleanArray(NumericArray):
+    """
+    Handles an array of boolean values.
+    """
+    vararray_type = ArrayVarArray
+
+    def __init__(self, field, base, arraysize, config={}, pos=None):
+        NumericArray.__init__(self, field, base, arraysize, config, pos)
+
+    def binparse(self, read):
+        data = read(self._items)
+        binparse = self._base.binparse_value
+        result = []
+        result_mask = []
+        for char in data:
+            if not IS_PY3K:
+                char = ord(char)
+            value, mask = binparse(char)
+            result.append(value)
+            result_mask.append(mask)
+        result = np.array(result, dtype='b1').reshape(
+            self._arraysize)
+        result_mask = np.array(result_mask, dtype='b1').reshape(
+            self._arraysize)
+        return result, result_mask
+
+    def binoutput(self, value, mask):
+        binoutput = self._base.binoutput
+        value = np.asarray(value)
+        mask = np.asarray(mask)
+        result = [binoutput(x, m)
+                  for x, m in np.broadcast(value.flat, mask.flat)]
+        return _empty_bytes.join(result)
+
+
+class Boolean(Converter):
+    """
+    Handles the boolean datatype.
+    """
+    format = 'b1'
+    array_type = BooleanArray
+    vararray_type = ScalarVarArray
+    default = False
+    binary_question_mark = b'?'
+    binary_true = b'T'
+    binary_false = b'F'
+
+    def __init__(self, field, config={}, pos=None):
+        Converter.__init__(self, field, config, pos)
+
+    def parse(self, value, config={}, pos=None):
+        if value is False:
+            return False, True
+        mapping = {'TRUE'  : (True, False),
+                   'FALSE' : (False, False),
+                   '1'     : (True, False),
+                   '0'     : (False, False),
+                   'T'     : (True, False),
+                   'F'     : (False, False),
+                   '\0'    : (False, True),
+                   ' '     : (False, True),
+                   '?'     : (False, True),
+                   ''      : (False, True)}
+        try:
+            return mapping[value.upper()]
+        except KeyError:
+            vo_raise(E05, (value,), config, pos)
+
+    def output(self, value, mask):
+        if mask:
+            return u'?'
+        if value:
+            return u'T'
+        return u'F'
+
+    def binparse(self, read):
+        value = ord(read(1))
+        return self.binparse_value(value)
+
+    _binparse_mapping = {
+        ord('T')  : (True, False),
+        ord('t')  : (True, False),
+        ord('1')  : (True, False),
+        ord('F')  : (False, False),
+        ord('f')  : (False, False),
+        ord('0')  : (False, False),
+        ord('\0') : (False, True),
+        ord(' ')  : (False, True),
+        ord('?')  : (False, True)}
+
+    def binparse_value(self, value):
+        try:
+            return self._binparse_mapping[value]
+        except KeyError:
+            vo_raise(E05, (value,))
+
+    def binoutput(self, value, mask):
+        if mask:
+            return self.binary_question_mark
+        if value:
+            return self.binary_true
+        return self.binary_false
+
+
+converter_mapping = {
+    'double'        : Double,
+    'float'         : Float,
+    'bit'           : Bit,
+    'boolean'       : Boolean,
+    'unsignedByte'  : UnsignedByte,
+    'short'         : Short,
+    'int'           : Int,
+    'long'          : Long,
+    'floatComplex'  : FloatComplex,
+    'doubleComplex' : DoubleComplex,
+    'char'          : Char,
+    'unicodeChar'   : UnicodeChar }
+
+
+def get_converter(field, config={}, pos=None):
+    """
+    Get an appropriate converter instance for a given field.
+
+    Parameters
+    ----------
+    field : astropy.io.votable.tree.Field
+
+    config : dict, optional
+        Parser configuration dictionary
+
+    pos : tuple
+        Position in the input XML file.  Used for error messages.
+
+    Returns
+    -------
+    converter : astropy.io.votable.converters.Converter
+    """
+    if field.datatype not in converter_mapping:
+        vo_raise(E06, (field.datatype, field.ID), config)
+
+    cls = converter_mapping[field.datatype]
+    converter = cls(field, config, pos)
+
+    arraysize = field.arraysize
+
+    # With numeric datatypes, special things need to happen for
+    # arrays.
+    if (field.datatype not in ('char', 'unicodeChar') and
+        arraysize is not None):
+        if arraysize[-1] == '*':
+            arraysize = arraysize[:-1]
+            last_x = arraysize.rfind('x')
+            if last_x == -1:
+                arraysize = ''
+            else:
+                arraysize = arraysize[:last_x]
+            fixed = False
+        else:
+            fixed = True
+
+        if arraysize != '':
+            arraysize = [int(x) for x in arraysize.split("x")]
+            arraysize.reverse()
+        else:
+            arraysize = []
+
+        if arraysize != []:
+            converter = converter.array_type(
+                field, converter, arraysize, config)
+
+        if not fixed:
+            converter = converter.vararray_type(
+                field, converter, arraysize, config)
+
+    return converter
+
+
+numpy_dtype_to_field_mapping = {
+    np.float64().dtype.num    : 'double',
+    np.float32().dtype.num    : 'float',
+    np.bool_().dtype.num      : 'bit',
+    np.uint8().dtype.num      : 'unsignedByte',
+    np.int16().dtype.num      : 'short',
+    np.int32().dtype.num      : 'int',
+    np.int64().dtype.num      : 'long',
+    np.complex64().dtype.num  : 'floatComplex',
+    np.complex128().dtype.num : 'doubleComplex',
+    np.unicode_().dtype.num   : 'unicodeChar'
+}
+
+
+# numpy 1.4.1 doesn't have a "bytes_" type
+if hasattr(np, 'bytes_'):
+    numpy_dtype_to_field_mapping[np.bytes_().dtype.num] = 'char'
+else:
+    numpy_dtype_to_field_mapping[np.str_().dtype.num] = 'char'
+
+
+def _all_bytes(column):
+    for x in column:
+        if not isinstance(x, bytes):
+            return False
+    return True
+
+
+def _all_unicode(column):
+    for x in column:
+        if not isinstance(x, unicode):
+            return False
+    return True
+
+
+def _all_matching_dtype(column):
+    first_dtype = False
+    first_shape = ()
+    for x in column:
+        if not isinstance(x, np.ndarray) or len(x) == 0:
+            continue
+
+        if first_dtype is False:
+            first_dtype = x.dtype
+            first_shape = x.shape[1:]
+        elif first_dtype != x.dtype:
+            return False, ()
+        elif first_shape != x.shape[1:]:
+            first_shape = ()
+    return first_dtype, first_shape
+
+
+def numpy_to_votable_dtype(dtype, shape):
+    """
+    Converts a numpy dtype and shape to a dictionary of attributes for
+    a VOTable FIELD element and correspond to that type.
+
+    Parameters
+    ----------
+    dtype : Numpy dtype instance
+
+    shape : tuple
+
+    Returns
+    -------
+    attributes : dict
+       A dict containing 'datatype' and 'arraysize' keys that can be
+       set on a VOTable FIELD element.
+    """
+    if dtype.num not in numpy_dtype_to_field_mapping:
+        raise TypeError(
+            "{0!r} can not be represented in VOTable".format(dtype))
+
+    if dtype.char == 'S':
+        return {'datatype': 'char',
+                'arraysize': str(dtype.itemsize)}
+    elif dtype.char == 'U':
+        return {'datatype': 'unicodeChar',
+                'arraysize': str(dtype.itemsize // 4)}
+    else:
+        result = {
+            'datatype': numpy_dtype_to_field_mapping[dtype.num]}
+        if len(shape):
+            result['arraysize'] = 'x'.join(str(x) for x in shape)
+
+        return result
+
+
+def table_column_to_votable_datatype(column):
+    """
+    Given a `astropy.table.Column` instance, returns the attributes
+    necessary to create a VOTable FIELD element that corresponds to
+    the type of the column.
+
+    This necessarily must perform some heuristics to determine the
+    type of variable length arrays fields, since they are not directly
+    supported by Numpy.
+
+    If the column has dtype of "object", it performs the following
+    tests:
+
+       - If all elements are byte or unicode strings, it creates a
+         variable-length byte or unicode field, respectively.
+
+       - If all elements are numpy arrays of the same dtype and with a
+         consistent shape in all but the first dimension, it creates a
+         variable length array of fixed sized arrays.  If the dtypes
+         match, but the shapes do not, a variable length array is
+         created.
+
+    If the dtype of the input is not understood, it sets the data type
+    to the most inclusive: a variable length unicodeChar array.
+
+    Parameters
+    ----------
+    column : `astropy.table.Column` instance
+
+    Returns
+    -------
+    attributes : dict
+       A dict containing 'datatype' and 'arraysize' keys that can be
+       set on a VOTable FIELD element.
+    """
+    if column.dtype.char == 'O':
+        if isinstance(column[0], bytes):
+            if _all_bytes(column[1:]):
+                return {'datatype': 'char', 'arraysize': '*'}
+        elif isinstance(column[0], unicode):
+            if _all_unicode(column[1:]):
+                return {'datatype': 'unicodeChar', 'arraysize': '*'}
+        elif isinstance(column[0], np.ndarray):
+            dtype, shape = _all_matching_dtype(column)
+            if dtype is not False:
+                result = numpy_to_votable_dtype(dtype, shape)
+                if 'arraysize' not in result:
+                    result['arraysize'] = '*'
+                else:
+                    result['arraysize'] += '*'
+                return result
+
+        # All bets are off, do the most generic thing
+        return {'datatype': 'unicodeChar', 'arraysize': '*'}
+
+    return numpy_to_votable_dtype(column.dtype, column.shape[1:])
diff --git a/astropy/io/vo/data/VOTable.dtd b/astropy/io/votable/data/VOTable.dtd
similarity index 100%
rename from astropy/io/vo/data/VOTable.dtd
rename to astropy/io/votable/data/VOTable.dtd
diff --git a/astropy/io/vo/data/VOTable.v1.1.xsd b/astropy/io/votable/data/VOTable.v1.1.xsd
similarity index 100%
rename from astropy/io/vo/data/VOTable.v1.1.xsd
rename to astropy/io/votable/data/VOTable.v1.1.xsd
diff --git a/astropy/io/vo/data/VOTable.v1.2.xsd b/astropy/io/votable/data/VOTable.v1.2.xsd
similarity index 100%
rename from astropy/io/vo/data/VOTable.v1.2.xsd
rename to astropy/io/votable/data/VOTable.v1.2.xsd
diff --git a/astropy/io/vo/data/ucd1p-words.txt b/astropy/io/votable/data/ucd1p-words.txt
similarity index 100%
rename from astropy/io/vo/data/ucd1p-words.txt
rename to astropy/io/votable/data/ucd1p-words.txt
diff --git a/astropy/io/votable/exceptions.py b/astropy/io/votable/exceptions.py
new file mode 100644
index 0000000..e815c89
--- /dev/null
+++ b/astropy/io/votable/exceptions.py
@@ -0,0 +1,1382 @@
+# -*- coding: utf-8 -*-
+u"""
+.. _warnings:
+
+Warnings
+--------
+
+.. note::
+    Most of the following warnings indicate violations of the VOTable
+    specification.  They should be reported to the authors of the
+    tools that produced the VOTable file.
+
+    To control the warnings emitted, use the standard Python
+    :mod:`warnings` module.  Most of these are of the type
+    `VOTableSpecWarning`.
+
+{warnings}
+
+.. _exceptions:
+
+Exceptions
+----------
+
+.. note::
+
+    This is a list of many of the fatal exceptions emitted by vo.table
+    when the file does not conform to spec.  Other exceptions may be
+    raised due to unforeseen cases or bugs in vo.table itself.
+
+{exceptions}
+"""
+
+from __future__ import division, absolute_import
+
+# STDLIB
+import io
+import re
+from warnings import warn
+
+# LOCAL
+from .util import IS_PY3K
+
+
+__all__ = [
+    'warn_or_raise', 'vo_raise', 'vo_reraise', 'vo_warn',
+    'warn_unknown_attrs', 'parse_vowarning', 'VOWarning',
+    'VOTableChangeWarning', 'VOTableSpecWarning',
+    'UnimplementedWarning', 'IOWarning', 'VOTableSpecError']
+
+
+MAX_WARNINGS = 10
+
+
+def _format_message(message, name, config={}, pos=None):
+    if pos is None:
+        pos = ('?', '?')
+    filename = config.get('filename', '?')
+    return '%s:%s:%s: %s: %s' % (filename, pos[0], pos[1], name, message)
+
+
+def _suppressed_warning(warning, config, stacklevel=2):
+    warning_class = type(warning)
+    config.setdefault('_warning_counts', {}).setdefault(warning_class, 0)
+    config['_warning_counts'][warning_class] += 1
+    message_count = config['_warning_counts'][warning_class]
+    if message_count <= MAX_WARNINGS:
+        if message_count == MAX_WARNINGS:
+            warning.formatted_message += \
+                ' (suppressing further warnings of this type...)'
+        warn(warning, stacklevel=stacklevel+1)
+
+
+def warn_or_raise(warning_class, exception_class=None, args=(), config={},
+                  pos=None, stacklevel=1):
+    """
+    Warn or raise an exception, depending on the pedantic setting.
+    """
+    if config.get('pedantic'):
+        if exception_class is None:
+            exception_class = warning_class
+        vo_raise(exception_class, args, config, pos)
+    else:
+        vo_warn(warning_class, args, config, pos, stacklevel=stacklevel+1)
+
+
+def vo_raise(exception_class, args=(), config={}, pos=None):
+    """
+    Raise an exception, with proper position information if available.
+    """
+    raise exception_class(args, config, pos)
+
+
+def vo_reraise(exc, config={}, pos=None, additional=''):
+    """
+    Raise an exception, with proper position information if available.
+
+    Restores the original traceback of the exception, and should only
+    be called within an "except:" block of code.
+    """
+    message = _format_message(str(exc), exc.__class__.__name__, config, pos)
+    if message.split()[0] == str(exc).split()[0]:
+        message = str(exc)
+    if len(additional):
+        message += ' ' + additional
+    exc.args = (message,)
+    raise exc
+
+
+def vo_warn(warning_class, args=(), config={}, pos=None, stacklevel=1):
+    """
+    Warn, with proper position information if available.
+    """
+    warning = warning_class(args, config, pos)
+    _suppressed_warning(warning, config, stacklevel=stacklevel+1)
+
+
+def warn_unknown_attrs(element, attrs, config, pos, good_attr=[], stacklevel=1):
+    for attr in attrs:
+        if attr not in good_attr:
+            vo_warn(W48, (attr, element), config, pos, stacklevel=stacklevel+1)
+
+
+_warning_pat = re.compile(
+    (r":?(?P<nline>[0-9?]+):(?P<nchar>[0-9?]+): " +
+     r"((?P<warning>[WE]\d+): )?(?P<rest>.*)$"))
+
+
+def parse_vowarning(line):
+    """
+    Parses the vo warning string back into its parts.
+    """
+    result = {}
+    match = _warning_pat.search(line)
+    if match:
+        result['warning'] = warning = match.group('warning')
+        if warning is not None:
+            result['is_warning'] = (warning[0].upper() == 'W')
+            result['is_exception'] = not result['is_warning']
+            result['number'] = int(match.group('warning')[1:])
+            result['doc_url'] = "vo/api_exceptions.html#%s" % warning.lower()
+        else:
+            result['is_warning'] = False
+            result['is_exception'] = False
+            result['is_other'] = True
+            result['number'] = None
+            result['doc_url'] = None
+        result['nline'] = int(match.group('nline'))
+        result['nchar'] = int(match.group('nchar'))
+        result['message'] = match.group('rest')
+        result['is_something'] = True
+    else:
+        result['warning'] = None
+        result['is_warning'] = False
+        result['is_exception'] = False
+        result['is_other'] = False
+        result['is_something'] = False
+
+    return result
+
+
+class VOWarning(Warning):
+    """
+    The base class of all VO warnings and exceptions.
+
+    Handles the formatting of the message with a warning or exception
+    code, filename, line and column number.
+    """
+    default_args = ()
+
+    def __init__(self, args, config={}, pos=None):
+        msg = self.message % args
+        self.formatted_message = _format_message(
+            msg, self.__class__.__name__, config, pos)
+        Warning.__init__(self, self.formatted_message)
+
+    def __str__(self):
+        return self.formatted_message
+
+    @classmethod
+    def get_short_name(cls):
+        if len(cls.default_args):
+            return cls.message % cls.default_args
+        return cls.message
+
+
+class VOTableChangeWarning(VOWarning, SyntaxWarning):
+    """
+    A change has been made to the input XML file.
+    """
+    pass
+
+
+class VOTableSpecWarning(VOWarning, SyntaxWarning):
+    """
+    The input XML file violates the spec, but there is an obvious workaround.
+    """
+    pass
+
+
+class UnimplementedWarning(VOWarning, SyntaxWarning):
+    """
+    A feature of the VOTABLE_ spec is not implemented.
+    """
+    pass
+
+
+class IOWarning(VOWarning, RuntimeWarning):
+    """
+    A network or IO error occurred, but was recovered using the cache.
+    """
+    pass
+
+
+class VOTableSpecError(VOWarning, ValueError):
+    """
+    The input XML file violates the spec and there is no good workaround.
+    """
+    pass
+
+
+class W01(VOTableSpecWarning):
+    """
+    The VOTable spec states:
+
+        If a cell contains an array or complex number, it should be
+        encoded as multiple numbers separated by whitespace.
+
+    Many VOTable files in the wild use commas as a separator instead,
+    and ``vo.table`` supports this convention when not in
+    :ref:`pedantic-mode`.
+
+    `vo.table` always outputs files using only spaces, regardless of
+    how they were input.
+
+    **References**: `1.1
+    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#toc-header-35>`__,
+    `1.2
+    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:TABLEDATA>`__
+    """
+
+    message = "Array uses commas rather than whitespace"
+
+
+class W02(VOTableSpecWarning):
+    """
+    XML ids must match the following regular expression::
+
+        ^[A-Za-z_][A-Za-z0-9_\.\-]*$
+
+    The VOTable 1.1 says the following:
+
+        According to the XML standard, the attribute ``ID`` is a
+        string beginning with a letter or underscore (``_``), followed
+        by a sequence of letters, digits, or any of the punctuation
+        characters ``.`` (dot), ``-`` (dash), ``_`` (underscore), or
+        ``:`` (colon).
+
+    However, this is in conflict with the XML standard, which says
+    colons may not be used.  VOTable 1.1's own schema does not allow a
+    colon here.  Therefore, ``vo.table`` disallows the colon.
+
+    VOTable 1.2 corrects this error in the specification.
+
+    **References**: `1.1
+    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:name>`__,
+    `XML Names <http://www.w3.org/TR/REC-xml/#NT-Name>`__
+    """
+
+    message = "%s attribute '%s' is invalid.  Must be a standard XML id"
+    default_args = ('x', 'y')
+
+
+class W03(VOTableChangeWarning):
+    """
+    The VOTable 1.1 spec says the following about ``name`` vs. ``ID``
+    on ``FIELD`` and ``VALUE`` elements:
+
+        ``ID`` and ``name`` attributes have a different role in
+        VOTable: the ``ID`` is meant as a *unique identifier* of an
+        element seen as a VOTable component, while the ``name`` is
+        meant for presentation purposes, and need not to be unique
+        throughout the VOTable document. The ``ID`` attribute is
+        therefore required in the elements which have to be
+        referenced, but in principle any element may have an ``ID``
+        attribute. ... In summary, the ``ID`` is different from the
+        ``name`` attribute in that (a) the ``ID`` attribute is made
+        from a restricted character set, and must be unique throughout
+        a VOTable document whereas names are standard XML attributes
+        and need not be unique; and (b) there should be support in the
+        parsing software to look up references and extract the
+        relevant element with matching ``ID``.
+
+    It is further recommended in the VOTable 1.2 spec:
+
+        While the ``ID`` attribute has to be unique in a VOTable
+        document, the ``name`` attribute need not. It is however
+        recommended, as a good practice, to assign unique names within
+        a ``TABLE`` element. This recommendation means that, between a
+        ``TABLE`` and its corresponding closing ``TABLE`` tag,
+        ``name`` attributes of ``FIELD``, ``PARAM`` and optional
+        ``GROUP`` elements should be all different.
+
+    Since ``vo.table`` requires a unique identifier for each of its
+    columns, ``ID`` is used for the column name when present.
+    However, when ``ID`` is not present, (since it is not required by
+    the specification) ``name`` is used instead.  However, ``name``
+    must be cleansed by replacing invalid characters (such as
+    whitespace) with underscores.
+
+    .. note::
+        This warning does not indicate that the input file is invalid
+        with respect to the VOTable specification, only that the
+        column names in the record array may not match exactly the
+        ``name`` attributes specified in the file.
+
+    **References**: `1.1
+    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:name>`__,
+    `1.2
+    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:name>`__
+    """
+
+    message = "Implictly generating an ID from a name '%s' -> '%s'"
+    default_args = ('x', 'y')
+
+
+class W04(VOTableSpecWarning):
+    """
+    The ``content-type`` attribute must use MIME content-type syntax as
+    defined in `RFC 2046 <http://tools.ietf.org/html/rfc2046>`__.
+
+    The current check for validity is somewhat over-permissive.
+
+    **References**: `1.1
+    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:link>`__,
+    `1.2
+    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:link>`__
+    """
+
+    message = "content-type '%s' must be a valid MIME content type"
+    default_args = ('x',)
+
+
+class W05(VOTableSpecWarning):
+    """
+    The attribute must be a valid URI as defined in `RFC 2396
+    <http://www.ietf.org/rfc/rfc2396.txt>`_.
+    """
+
+    message = "'%s' is not a valid URI"
+    default_args = ('x',)
+
+
+class W06(VOTableSpecWarning):
+    """
+    This warning is emitted when a ``ucd`` attribute does not match
+    the syntax of a `unified content descriptor
+    <http://vizier.u-strasbg.fr/doc/UCD.htx>`__.
+
+    If the VOTable version is 1.2 or later, the UCD will also be
+    checked to ensure it conforms to the controlled vocabulary defined
+    by UCD1+.
+
+    **References**: `1.1
+    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:ucd>`__,
+    `1.2
+    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:ucd>`__
+    """
+
+    message = "Invalid UCD '%s': %s"
+    default_args = ('x', 'explanation')
+
+
+class W07(VOTableSpecWarning):
+    """
+    As astro year field is a Besselian or Julian year matching the
+    regular expression::
+
+        ^[JB]?[0-9]+([.][0-9]*)?$
+
+    Defined in this XML Schema snippet::
+
+        <xs:simpleType  name="astroYear">
+          <xs:restriction base="xs:token">
+            <xs:pattern  value="[JB]?[0-9]+([.][0-9]*)?"/>
+          </xs:restriction>
+        </xs:simpleType>
+    """
+
+    message = "Invalid astroYear in %s: '%s'"
+    default_args = ('x', 'y')
+
+
+class W08(VOTableSpecWarning):
+    """
+    To avoid local-dependent number parsing differences, ``vo.table``
+    may require a string or unicode string where a numeric type may
+    make more sense.
+    """
+
+    if IS_PY3K:
+        message = "'%s' must be a str or bytes object"
+    else:
+        message = "'%s' must be a str or unicode object"
+    default_args = ('x',)
+
+
+class W09(VOTableSpecWarning):
+    """
+    The VOTable specification uses the attribute name ``ID`` (with
+    uppercase letters) to specify unique identifiers.  Some
+    VOTable-producing tools use the more standard lowercase ``id``
+    instead.  ``vo.table`` accepts ``id`` and emits this warning when
+    not in ``pedantic`` mode.
+
+    **References**: `1.1
+    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:name>`__,
+    `1.2
+    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:name>`__
+    """
+
+    message = "ID attribute not capitalized"
+
+
+class W10(VOTableSpecWarning):
+    """
+    The parser has encountered an element that does not exist in the
+    specification, or appears in an invalid context.  Check the file
+    against the VOTable schema (with a tool such as `xmllint
+    <http://xmlsoft.org/xmllint.html>`__.  If the file validates
+    against the schema, and you still receive this warning, this may
+    indicate a bug in ``vo.table``.
+
+    **References**: `1.1
+    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#ToC54>`__,
+    `1.2
+    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#ToC58>`__
+    """
+
+    message = "Unknown tag '%s'.  Ignoring"
+    default_args = ('x',)
+
+
+class W11(VOTableSpecWarning):
+    """
+    Earlier versions of the VOTable specification used a ``gref``
+    attribute on the ``LINK`` element to specify a `GLU reference
+    <http://aladin.u-strasbg.fr/glu/>`__.  New files should
+    specify a ``glu:`` protocol using the ``href`` attribute.
+
+    Since ``vo.table`` does not currently support GLU references, it
+    likewise does not automatically convert the ``gref`` attribute to
+    the new form.
+
+    **References**: `1.1
+    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:link>`__,
+    `1.2
+    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:link>`__
+    """
+
+    message = "The gref attribute on LINK is deprecated in VOTable 1.1"
+
+
+class W12(VOTableChangeWarning):
+    """
+    In order to name the columns of the Numpy record array, each
+    ``FIELD`` element must have either an ``ID`` or ``name`` attribute
+    to derive a name from.  Strictly speaking, according to the
+    VOTable schema, the ``name`` attribute is required.  However, if
+    ``name`` is not present by ``ID`` is, and *pedantic mode* is off,
+    ``vo.table`` will continue without a ``name`` defined.
+
+    **References**: `1.1
+    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:name>`__,
+    `1.2
+    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:name>`__
+    """
+
+    message = (
+        "'%s' element must have at least one of 'ID' or 'name' attributes")
+    default_args = ('x',)
+
+
+class W13(VOTableSpecWarning):
+    """
+    Some VOTable files in the wild use non-standard datatype names.  These
+    are mapped to standard ones using the following mapping::
+
+       string        -> char
+       unicodeString -> unicodeChar
+       int16         -> short
+       int32         -> int
+       int64         -> long
+       float32       -> float
+       float64       -> double
+
+    **References**: `1.1
+    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:datatypes>`__,
+    `1.2
+    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:datatypes>`__
+    """
+
+    message = "'%s' is not a valid VOTable datatype, should be '%s'"
+    default_args = ('x', 'y')
+
+
+# W14: Deprecated
+
+
+class W15(VOTableSpecWarning):
+    """
+    The ``name`` attribute is required on every ``FIELD`` element.
+    However, many VOTable files in the wild omit it and provide only
+    an ``ID`` instead.  In this case, when *pedantic mode* is off,
+    ``vo.table`` will copy the ``name`` attribute to a new ``ID``
+    attribute.
+
+    **References**: `1.1
+    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:name>`__,
+    `1.2
+    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:name>`__
+    """
+
+    message = "%s element missing required 'name' attribute"
+    default_args = ('x',)
+
+# W16: Deprecated
+
+
+class W17(VOTableSpecWarning):
+    """
+    A ``DESCRIPTION`` element can only appear once within its parent
+    element.
+
+    According to the schema, it may only occur once (`1.1
+    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#ToC54>`__,
+    `1.2
+    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#ToC58>`__)
+
+    However, it is a `proposed extension
+    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:addesc>`__
+    to VOTable 1.2.
+    """
+
+    message = "%s element contains more than one DESCRIPTION element"
+    default_args = ('x',)
+
+
+class W18(VOTableSpecWarning):
+    """
+    The number of rows explicitly specified in the ``nrows`` attribute
+    does not match the actual number of rows (``TR`` elements) present
+    in the ``TABLE``.  This may indicate truncation of the file, or an
+    internal error in the tool that produced it.  If *pedantic mode*
+    is off, parsing will proceed, with the loss of some performance.
+
+    **References:** `1.1
+    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#ToC10>`__,
+    `1.2
+    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#ToC10>`__
+    """
+
+    message = 'TABLE specified nrows=%s, but table contains %s rows'
+    default_args = ('x', 'y')
+
+
+class W19(VOTableSpecWarning):
+    """
+    The column fields as defined using ``FIELD`` elements do not match
+    those in the headers of the embedded FITS file.  If *pedantic
+    mode* is off, the embedded FITS file will take precedence.
+    """
+
+    message = (
+        'The fields defined in the VOTable do not match those in the ' +
+        'embedded FITS file')
+
+
+class W20(VOTableSpecWarning):
+    """
+    If no version number is explicitly given in the VOTable file, the
+    parser assumes it is written to the VOTable 1.1 specification.
+    """
+
+    message = 'No version number specified in file.  Assuming %s'
+    default_args = ('1.1',)
+
+
+class W21(UnimplementedWarning):
+    """
+    Unknown issues may arise using ``vo.table`` with VOTable files
+    from a version other than 1.1 or 1.2.
+    """
+
+    message = (
+        'vo.table is designed for VOTable version 1.1 and 1.2, but ' +
+        'this file is %s')
+    default_args = ('x',)
+
+
+class W22(VOTableSpecWarning):
+    """
+    Version 1.0 of the VOTable specification used the ``DEFINITIONS``
+    element to define coordinate systems.  Version 1.1 now uses
+    ``COOSYS`` elements throughout the document.
+
+    **References:** `1.1
+    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:definitions>`__,
+    `1.2
+    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:definitions>`__
+    """
+
+    message = 'The DEFINITIONS element is deprecated in VOTable 1.1.  Ignoring'
+
+
+class W23(IOWarning):
+    """
+    Raised when the VO service database can not be updated (possibly
+    due to a network outage).  This is only a warning, since an older
+    and possible out-of-date VO service database was available
+    locally.
+    """
+
+    message = "Unable to update service information for '%s'"
+    default_args = ('x',)
+
+
+class W24(VOWarning, FutureWarning):
+    """
+    The VO catalog database retrieved from the www is designed for a
+    newer version of vo.table.  This may cause problems or limited
+    features performing service queries.  Consider upgrading vo.table
+    to the latest version.
+    """
+
+    message = "The VO catalog database is for a later version of vo.table"
+
+
+class W25(IOWarning):
+    """
+    A VO service query failed due to a network error or malformed
+    arguments.  Another alternative service may be attempted.  If all
+    services fail, an exception will be raised.
+    """
+
+    message = "'%s' failed with: %s"
+    default_args = ('service', '...')
+
+
+class W26(VOTableSpecWarning):
+    """
+    The given element was not supported inside of the given element
+    until the specified VOTable version, however the version declared
+    in the file is for an earlier version.  These attributes may not
+    be written out to the file.
+    """
+
+    message = "'%s' inside '%s' added in VOTable %s"
+    default_args = ('child', 'parent', 'X.X')
+
+
+class W27(VOTableSpecWarning):
+    """
+    The ``COOSYS`` element was deprecated in VOTABLE version 1.2 in
+    favor of a reference to the Space-Time Coordinate (STC) data
+    model (see `utype
+    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:utype>`__
+    and the IVOA note `referencing STC in VOTable
+    <http://ivoa.net/Documents/latest/VOTableSTC.html>`__.
+    """
+
+    message = "COOSYS deprecated in VOTable 1.2"
+
+
+class W28(VOTableSpecWarning):
+    """
+    The given attribute was not supported on the given element until the
+    specified VOTable version, however the version declared in the file is
+    for an earlier version.  These attributes may not be written out to
+    the file.
+    """
+
+    message = "'%s' on '%s' added in VOTable %s"
+    default_args = ('attribute', 'element', 'X.X')
+
+
+class W29(VOTableSpecWarning):
+    """
+    Some VOTable files specify their version number in the form "v1.0",
+    when the only supported forms in the spec are "1.0".
+
+    **References**: `1.1
+    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#ToC54>`__,
+    `1.2
+    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#ToC58>`__
+    """
+
+    message = "Version specified in non-standard form '%s'"
+    default_args = ('v1.0',)
+
+
+class W30(VOTableSpecWarning):
+    """
+    Some VOTable files write missing floating-point values in non-standard
+    ways, such as "null" and "-".  In non-pedantic mode, any non-standard
+    floating-point literals are treated as missing values.
+
+    **References**: `1.1
+    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:datatypes>`__,
+    `1.2
+    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:datatypes>`__
+    """
+
+    message = "Invalid literal for float '%s'.  Treating as empty."
+    default_args = ('x',)
+
+
+class W31(VOTableSpecWarning):
+    """
+    Since NaN's can not be represented in integer fields directly, a null
+    value must be specified in the FIELD descriptor to support reading
+    NaN's from the tabledata.
+
+    **References**: `1.1
+    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:datatypes>`__,
+    `1.2
+    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:datatypes>`__
+    """
+
+    message = "NaN given in an integral field without a specified null value"
+
+
+class W32(VOTableSpecWarning):
+    """
+    Each field in a table must have a unique ID.  If two or more fields
+    have the same ID, some will be renamed to ensure that all IDs are
+    unique.
+
+    From the VOTable 1.2 spec:
+
+        The ``ID`` and ``ref`` attributes are defined as XML types
+        ``ID`` and ``IDREF`` respectively. This means that the
+        contents of ``ID`` is an identifier which must be unique
+        throughout a VOTable document, and that the contents of the
+        ``ref`` attribute represents a reference to an identifier
+        which must exist in the VOTable document.
+
+    **References**: `1.1
+    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:name>`__,
+    `1.2
+    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:name>`__
+    """
+
+    message = "Duplicate ID '%s' renamed to '%s' to ensure uniqueness"
+    default_args = ('x', 'x_2')
+
+
+class W33(VOTableChangeWarning):
+    """
+    Each field in a table must have a unique name.  If two or more
+    fields have the same name, some will be renamed to ensure that all
+    names are unique.
+
+    **References**: `1.1
+    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:name>`__,
+    `1.2
+    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:name>`__
+    """
+
+    message = "Column name '%s' renamed to '%s' to ensure uniqueness"
+    default_args = ('x', 'x_2')
+
+
+class W34(VOTableSpecWarning):
+    """
+    The attribute requires the value to be a valid XML token, as
+    defined by `XML 1.0
+    <http://www.w3.org/TR/2000/WD-xml-2e-20000814#NT-Nmtoken>`__.
+    """
+
+    message = "'%s' is an invalid token for attribute '%s'"
+    default_args = ('x', 'y')
+
+
+class W35(VOTableSpecWarning):
+    """
+    The ``name`` and ``value`` attributes are required on all ``INFO``
+    elements.
+
+    **References:** `1.1
+    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#ToC54>`__,
+    `1.2
+    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#ToC32>`
+    """
+
+    message = "'%s' attribute required for INFO elements"
+    default_args = ('x',)
+
+
+class W36(VOTableSpecWarning):
+    """
+    If the field specifies a ``null`` value, that value must conform
+    to the given ``datatype``.
+
+    **References:** `1.1
+    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:values>`__,
+    `1.2
+    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:values>`
+    """
+
+    message = "null value '%s' does not match field datatype, setting to 0"
+    default_args = ('x',)
+
+
+class W37(UnimplementedWarning):
+    """
+    The 3 datatypes defined in the VOTable specification and supported by
+    vo.table are ``TABLEDATA``, ``BINARY`` and ``FITS``.
+
+    **References:** `1.1
+    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:data>`__,
+    `1.2
+    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:data>`
+    """
+
+    message = "Unsupported data format '%s'"
+    default_args = ('x',)
+
+
+class W38(VOTableSpecWarning):
+    """
+    The only encoding for local binary data supported by the VOTable
+    specification is base64.
+    """
+
+    message = "Inline binary data must be base64 encoded, got '%s'"
+    default_args = ('x',)
+
+
+class W39(VOTableSpecWarning):
+    """
+    Bit values do not support masking.  This warning is raised upon
+    setting masked data in a bit column.
+
+    **References**: `1.1
+    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:datatypes>`__,
+    `1.2
+    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:datatypes>`__
+    """
+
+    message = "Bit values can not be masked"
+
+
+class W40(VOTableSpecWarning):
+    """
+    This is a terrible hack to support Simple Image Access Protocol
+    results from `<archive.noao.edu>`__.  It creates a field for the
+    coordinate projection type of type "double", which
+    actually contains character data.  We have to hack the field
+    to store character data, or we can't read it in.  A warning
+    will be raised when this happens.
+    """
+
+    message = "'cprojection' datatype repaired"
+
+
+class W41(VOTableSpecWarning):
+    """
+    An XML namespace was specified on the ``VOTABLE`` element, but the
+    namespace does not match what is expected for a ``VOTABLE`` file.
+
+    The ``VOTABLE`` namespace is::
+
+      http://www.ivoa.net/xml/VOTable/vX.X
+
+    where "X.X" is the version number.
+
+    Some files in the wild set the namespace to the location of the
+    VOTable schema, which is not correct and will not pass some
+    validating parsers.
+    """
+
+    message = (
+        "An XML namespace is specified, but is incorrect.  Expected " +
+        "'%s', got '%s'")
+    default_args = ('x', 'y')
+
+
+class W42(VOTableSpecWarning):
+    """
+    The root element should specify a namespace.
+
+    The ``VOTABLE`` namespace is::
+
+        http://www.ivoa.net/xml/VOTable/vX.X
+
+    where "X.X" is the version number.
+    """
+
+    message = "No XML namespace specified"
+
+
+class W43(VOTableSpecWarning):
+    """
+    Referenced elements should be defined before referees.  From the
+    VOTable 1.2 spec:
+
+       In VOTable1.2, it is further recommended to place the ID
+       attribute prior to referencing it whenever possible.
+    """
+
+    message = "%s ref='%s' which has not already been defined"
+    default_args = ('element', 'x',)
+
+
+class W44(VOTableSpecWarning):
+    """
+    ``VALUES`` elements that reference another element should not have
+    their own content.
+
+    From the VOTable 1.2 spec:
+
+        The ``ref`` attribute of a ``VALUES`` element can be used to
+        avoid a repetition of the domain definition, by referring to a
+        previously defined ``VALUES`` element having the referenced
+        ``ID`` attribute. When specified, the ``ref`` attribute
+        defines completely the domain without any other element or
+        attribute, as e.g. ``<VALUES ref="RAdomain"/>``
+    """
+
+    message = "VALUES element with ref attribute has content ('%s')"
+    default_args = ('element',)
+
+
+class W45(VOWarning, ValueError):
+    """
+    The ``content-role`` attribute on the ``LINK`` element must be one of
+    the following::
+
+        query, hints, doc, location
+
+    **References**: `1.1
+    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#ToC54>`__,
+    `1.2
+    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#ToC58>`__
+    """
+
+    message = "content-role attribute '%s' invalid"
+    default_args = ('x',)
+
+
+class W46(VOTableSpecWarning):
+    """
+    The given char or unicode string is too long for the specified
+    field length.
+    """
+
+    message = "%s value is too long for specified length of %s"
+    default_args = ('char or unicode', 'x')
+
+
+class W47(VOTableSpecWarning):
+    """
+    If no arraysize is specified on a char field, the default of '1'
+    is implied, but this is rarely what is intended.
+    """
+
+    message = "Missing arraysize indicates length 1"
+
+
+class W48(VOTableSpecWarning):
+    """
+    The attribute is not defined in the specification.
+    """
+
+    message = "Unknown attribute '%s' on %s"
+    default_args = ('attribute', 'element')
+
+
+class W49(VOTableSpecWarning):
+    """
+    Empty cell illegal for integer fields.
+
+    If a \"null\" value was specified for the cell, it will be used
+    for the value, otherwise, 0 will be used.
+    """
+
+    message = "Empty cell illegal for integer fields."
+
+
+class W50(VOTableSpecWarning):
+    """
+    Invalid unit string as defined in the `Standards for Astronomical
+    Catalogues, Version 2.0
+    <http://cdsarc.u-strasbg.fr/doc/catstd-3.2.htx>`_.
+    """
+
+    message = "Invalid unit string '%s'"
+    default_args = ('x',)
+
+
+class E01(VOWarning, ValueError):
+    """
+    The size specifier for a ``char`` or ``unicode`` field must be
+    only a number followed, optionally, by an asterisk.
+    Multi-dimensional size specifiers are not supported for these
+    datatypes.
+
+    Strings, which are defined as a set of characters, can be
+    represented in VOTable as a fixed- or variable-length array of
+    characters::
+
+        <FIELD name="unboundedString" datatype="char" arraysize="*"/>
+
+    A 1D array of strings can be represented as a 2D array of
+    characters, but given the logic above, it is possible to define a
+    variable-length array of fixed-length strings, but not a
+    fixed-length array of variable-length strings.
+    """
+
+    message = "Invalid size specifier '%s' for a %s field (in field '%s')"
+    default_args = ('x', 'char/unicode', 'y')
+
+
+class E02(VOWarning, ValueError):
+    """
+    The number of array elements in the data does not match that specified
+    in the FIELD specifier.
+    """
+
+    message = (
+        "Incorrect number of elements in array. " +
+        "Expected multiple of %s, got %s")
+    default_args = ('x', 'y')
+
+
+class E03(VOWarning, ValueError):
+    """
+    Complex numbers should be two values separated by whitespace.
+
+    **References**: `1.1
+    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:datatypes>`__,
+    `1.2
+    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:datatypes>`__
+    """
+
+    message = "'%s' does not parse as a complex number"
+    default_args = ('x',)
+
+
+class E04(VOWarning, ValueError):
+    """
+    A ``bit`` array should be a string of '0's and '1's.
+
+    **References**: `1.1
+    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:datatypes>`__,
+    `1.2
+    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:datatypes>`__
+    """
+
+    message = "Invalid bit value '%s'"
+    default_args = ('x',)
+
+
+class E05(VOWarning, ValueError):
+    """
+    A ``boolean`` value should be one of the following strings (case
+    insensitive) in the ``TABLEDATA`` format::
+
+        'TRUE', 'FALSE', '1', '0', 'T', 'F', '\\0', ' ', '?'
+
+    and in ``BINARY`` format::
+
+        'T', 'F', '1', '0', '\\0', ' ', '?'
+
+    **References**: `1.1
+    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:datatypes>`__,
+    `1.2
+    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:datatypes>`__
+    """
+
+    message = "Invalid boolean value '%s'"
+    default_args = ('x',)
+
+
+class E06(VOWarning, ValueError):
+    """
+    The supported datatypes are::
+
+        double, float, bit, boolean, unsignedByte, short, int, long,
+        floatComplex, doubleComplex, char, unicodeChar
+
+    The following non-standard aliases are also supported, but in
+    these case :ref:`W13 <W13>` will be raised::
+
+        string        -> char
+        unicodeString -> unicodeChar
+        int16         -> short
+        int32         -> int
+        int64         -> long
+        float32       -> float
+        float64       -> double
+
+    **References**: `1.1
+    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:datatypes>`__,
+    `1.2
+    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:datatypes>`__
+    """
+
+    message = "Unknown datatype '%s' on field '%s'"
+    default_args = ('x', 'y')
+
+# E07: Deprecated
+
+
+class E08(VOWarning, ValueError):
+    """
+    The ``type`` attribute on the ``VALUES`` element must be either
+    ``legal`` or ``actual``.
+
+    **References**: `1.1
+    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:values>`__,
+    `1.2
+    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:values>`__
+    """
+
+    message = "type must be 'legal' or 'actual', but is '%s'"
+    default_args = ('x',)
+
+
+class E09(VOWarning, ValueError):
+    """
+    The ``MIN``, ``MAX`` and ``OPTION`` elements must always have a
+    ``value`` attribute.
+
+    **References**: `1.1
+    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:values>`__,
+    `1.2
+    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:values>`__
+    """
+
+    message = "'%s' must have a value attribute"
+    default_args = ('x',)
+
+
+class E10(VOWarning, ValueError):
+    """
+    From VOTable 1.1 and later, ``FIELD`` and ``PARAM`` elements must have
+    a ``datatype`` field.
+
+    **References**: `1.1
+    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#elem:FIELD>`__,
+    `1.2
+    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#elem:FIELD>`__
+    """
+
+    message = "'datatype' attribute required on all '%s' elements"
+    default_args = ('FIELD',)
+
+
+class E11(VOWarning, ValueError):
+    """
+    The precision attribute is meant to express the number of significant
+    digits, either as a number of decimal places (e.g. ``precision="F2"`` or
+    equivalently ``precision="2"`` to express 2 significant figures
+    after the decimal point), or as a number of significant figures
+    (e.g. ``precision="E5"`` indicates a relative precision of 10-5).
+
+    It is validated using the following regular expression::
+
+        [EF]?[1-9][0-9]*
+
+    **References**: `1.1
+    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:form>`__,
+    `1.2
+    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:form>`__
+    """
+
+    message = "precision '%s' is invalid"
+    default_args = ('x',)
+
+
+class E12(VOWarning, ValueError):
+    """
+    The width attribute is meant to indicate to the application the
+    number of characters to be used for input or output of the
+    quantity.
+
+    **References**: `1.1
+    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:form>`__,
+    `1.2
+    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:form>`__
+    """
+
+    message = "width must be a positive integer, got '%s'"
+    default_args = ('x',)
+
+
+class E13(VOWarning, ValueError):
+    u"""
+    From the VOTable 1.2 spec:
+
+        A table cell can contain an array of a given primitive type,
+        with a fixed or variable number of elements; the array may
+        even be multidimensional. For instance, the position of a
+        point in a 3D space can be defined by the following::
+
+            <FIELD ID="point_3D" datatype="double" arraysize="3"/>
+
+        and each cell corresponding to that definition must contain
+        exactly 3 numbers. An asterisk (\*) may be appended to
+        indicate a variable number of elements in the array, as in::
+
+            <FIELD ID="values" datatype="int" arraysize="100*"/>
+
+        where it is specified that each cell corresponding to that
+        definition contains 0 to 100 integer numbers. The number may
+        be omitted to specify an unbounded array (in practice up to
+        =~2×10⁹ elements).
+
+        A table cell can also contain a multidimensional array of a
+        given primitive type. This is specified by a sequence of
+        dimensions separated by the ``x`` character, with the first
+        dimension changing fastest; as in the case of a simple array,
+        the last dimension may be variable in length. As an example,
+        the following definition declares a table cell which may
+        contain a set of up to 10 images, each of 64×64 bytes::
+
+            <FIELD ID="thumbs" datatype="unsignedByte" arraysize="64×64×10*"/>
+
+    **References**: `1.1
+    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#sec:dim>`__,
+    `1.2
+    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#sec:dim>`__
+    """
+
+    message = "Invalid arraysize attribute '%s'"
+    default_args = ('x',)
+
+
+class E14(VOWarning, ValueError):
+    """
+    All ``PARAM`` elements must have a ``value`` attribute.
+
+    **References**: `1.1
+    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#elem:FIELD>`__,
+    `1.2
+    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#elem:FIELD>`__
+    """
+
+    message = "value attribute is required for all PARAM elements"
+
+
+class E15(VOWarning, ValueError):
+    """
+    All ``COOSYS`` elements must have an ``ID`` attribute.
+
+    Note that the VOTable 1.1 specification says this attribute is
+    optional, but its corresponding schema indicates it is required.
+
+    In VOTable 1.2, the ``COOSYS`` element is deprecated.
+    """
+
+    message = "ID attribute is required for all COOSYS elements"
+
+
+class E16(VOTableSpecWarning):
+    """
+    The ``system`` attribute on the ``COOSYS`` element must be one of the
+    following::
+
+      'eq_FK4', 'eq_FK5', 'ICRS', 'ecl_FK4', 'ecl_FK5', 'galactic',
+      'supergalactic', 'xy', 'barycentric', 'geo_app'
+
+    **References**: `1.1
+    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#elem:COOSYS>`__
+    """
+
+    message = "Invalid system attribute '%s'"
+    default_args = ('x',)
+
+
+class E17(VOWarning, ValueError):
+    """
+    ``extnum`` attribute must be a positive integer.
+
+    **References**: `1.1
+    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#ToC54>`__,
+    `1.2
+    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#ToC58>`__
+    """
+
+    message = "extnum must be a positive integer"
+
+
+class E18(VOWarning, ValueError):
+    """
+    The ``type`` attribute of the ``RESOURCE`` element must be one of
+    "results" or "meta".
+
+    **References**: `1.1
+    <http://www.ivoa.net/Documents/VOTable/20040811/REC-VOTable-1.1-20040811.html#ToC54>`__,
+    `1.2
+    <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html#ToC58>`__
+    """
+
+    message = "type must be 'results' or 'meta', not '%s'"
+    default_args = ('x',)
+
+
+class E19(VOWarning, ValueError):
+    """
+    Raised either when the file doesn't appear to be XML, or the root
+    element is not VOTABLE.
+    """
+
+    message = "File does not appear to be a VOTABLE"
+
+
+class E20(VOTableSpecError):
+    """
+    The table had only *x* fields defined, but the data itself has more
+    columns than that.
+    """
+
+    message = "Data has more columns than are defined in the header (%s)"
+    default_args = ('x',)
+
+
+class E21(VOWarning, ValueError):
+    """
+    The table had *x* fields defined, but the data itself has only *y*
+    columns.
+    """
+
+    message = "Data has fewer columns (%s) than are defined in the header (%s)"
+    default_args = ('x', 'y')
+
+
+def _get_warning_and_exception_classes(prefix):
+    classes = []
+    for key, val in globals().iteritems():
+        if re.match(prefix + "[0-9]{2}", key):
+            classes.append((key, val))
+    classes.sort()
+    return classes
+
+
+def _build_doc_string():
+    from textwrap import dedent
+
+    def generate_set(prefix):
+        classes = _get_warning_and_exception_classes(prefix)
+
+        out = io.StringIO()
+
+        for name, cls in classes:
+            out.write(u".. _%s:\n\n" % name)
+            msg = "%s: %s" % (cls.__name__, cls.get_short_name())
+            if not isinstance(msg, unicode):
+                msg = msg.decode('utf-8')
+            out.write(msg)
+            out.write(u'\n')
+            out.write(u'~' * len(msg))
+            out.write(u'\n\n')
+            doc = cls.__doc__
+            if not isinstance(doc, unicode):
+                doc = doc.decode('utf-8')
+            out.write(dedent(doc))
+            out.write(u'\n\n')
+
+        return out.getvalue()
+
+    warnings = generate_set(u'W')
+    exceptions = generate_set(u'E')
+
+    return {u'warnings': warnings,
+            u'exceptions': exceptions}
+
+__doc__ = __doc__.format(**_build_doc_string())
+
+__all__.extend([x[0] for x in _get_warning_and_exception_classes(u'W')])
+__all__.extend([x[0] for x in _get_warning_and_exception_classes(u'E')])
diff --git a/astropy/io/votable/setup_package.py b/astropy/io/votable/setup_package.py
new file mode 100755
index 0000000..97ddeaf
--- /dev/null
+++ b/astropy/io/votable/setup_package.py
@@ -0,0 +1,29 @@
+from distutils.core import Extension
+from os.path import join
+
+from astropy import setup_helpers
+
+
+def get_extensions(build_type='release'):
+    VO_DIR = 'astropy/io/votable/src'
+
+    return [Extension(
+        "astropy.io.votable.tablewriter",
+        [join(VO_DIR, "tablewriter.c")],
+        include_dirs=[VO_DIR])]
+
+
+def get_package_data():
+    return {
+        'astropy.io.votable': [
+            'data/ucd1p-words.txt', 'data/*.xsd', 'data/*.dtd'],
+        'astropy.io.votable.tests': [
+            'data/*.xml', 'data/*.gz', 'data/*.json', 'data/*.fits',
+            'data/*.txt'],
+        'astropy.io.votable.validator': [
+            'urls/*.dat.gz']}
+
+
+def get_legacy_alias():
+    return setup_helpers.add_legacy_alias(
+        'vo', 'astropy.io.votable', '0.8')
diff --git a/astropy/io/votable/src/tablewriter.c b/astropy/io/votable/src/tablewriter.c
new file mode 100644
index 0000000..aa323e6
--- /dev/null
+++ b/astropy/io/votable/src/tablewriter.c
@@ -0,0 +1,396 @@
+/******************************************************************************
+ * C extension code for vo.table.
+ *
+ * Everything in this file has an alternate Python implementation and
+ * is included for performance reasons only.
+ *
+ * This contains a write_tabledata function to quickly write out a Numpy array
+ * in TABLEDATA format.
+ *
+ ******************************************************************************/
+
+#include <Python.h>
+
+/******************************************************************************
+ * Convenience macros and functions
+ ******************************************************************************/
+#undef  CLAMP
+#define CLAMP(x, low, high)  (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x)))
+
+static Py_ssize_t
+next_power_of_2(Py_ssize_t n)
+{
+    /* Calculate the next-highest power of two */
+    n--;
+    n |= n >> 1;
+    n |= n >> 2;
+    n |= n >> 4;
+    n |= n >> 8;
+    n |= n >> 16;
+    n++;
+
+    return n;
+}
+
+/******************************************************************************
+ * Python version compatibility macros
+ ******************************************************************************/
+#if PY_MAJOR_VERSION >= 3
+#  define IS_PY3K
+#endif
+
+#ifndef Py_TYPE
+#  define Py_TYPE(o) ((o)->ob_type)
+#endif
+
+/******************************************************************************
+ * Write TABLEDATA
+ ******************************************************************************/
+
+#define CHAR Py_UNICODE
+
+/*
+ * Reallocate the write buffer to the requested size
+ */
+static int
+_buffer_realloc(
+        CHAR** buffer, Py_ssize_t* buffer_size, CHAR** x, Py_ssize_t req_size)
+{
+    Py_ssize_t  n       = req_size;
+    CHAR *      new_mem = NULL;
+
+    if (req_size < *buffer_size) {
+        return 0;
+    }
+
+    /* Calculate the next-highest power of two */
+    n = next_power_of_2(n);
+
+    if (n < req_size) {
+        PyErr_SetString(PyExc_MemoryError, "Out of memory for XML text.");
+        return -1;
+    }
+
+    new_mem = realloc((void *)*buffer, n * sizeof(CHAR));
+    if (new_mem == NULL) {
+        PyErr_SetString(PyExc_MemoryError, "Out of memory for XML text.");
+        return -1;
+    }
+
+    *x = (CHAR *)new_mem + (*x - *buffer);
+    *buffer = new_mem;
+    *buffer_size = n;
+
+    return 0;
+}
+
+/*
+ * Write *indent* spaces to the buffer
+ */
+static int
+_write_indent(CHAR** buffer, Py_ssize_t* buffer_size,
+              CHAR** x, Py_ssize_t indent)
+{
+    if (_buffer_realloc(buffer, buffer_size, x,
+                        (*x - *buffer + indent))) {
+        return 1;
+    }
+
+    for (; indent; --indent) {
+        *(*x)++ = ' ';
+    }
+
+    return 0;
+}
+
+/*
+ * Write a string into a buffer.
+ */
+static int
+_write_string(CHAR** buffer, Py_ssize_t* buffer_size,
+              CHAR** x, const CHAR* src, const Py_ssize_t len) {
+    if (_buffer_realloc(buffer, buffer_size, x,
+                        (*x - *buffer + len))) {
+        return 1;
+    }
+
+    while (*src != (CHAR)0) {
+        *(*x)++ = *src++;
+    }
+
+    return 0;
+}
+
+/*
+ * Write an 8-bit ascii-encoded C string to a Unicode string.
+ */
+static int
+_write_cstring(CHAR** buffer, Py_ssize_t* buffer_size,
+               CHAR** x, const char* src, const Py_ssize_t len) {
+    if (_buffer_realloc(buffer, buffer_size, x,
+                        (*x - *buffer + len))) {
+        return 1;
+    }
+
+    while (*src != (char)0) {
+        *(*x)++ = *src++;
+    }
+
+    return 0;
+}
+
+/*
+ * Write a TABLEDATA element tree to the given write method.
+ *
+ * The Python arguments are:
+ *
+ * *write_method* (callable): A Python callable that takes a unicode
+ *    string and writes it to a file or buffer.
+ *
+ * *array* (numpy structured array): A Numpy record array containing
+ *    the data
+ *
+ * *mask* (numpy array): A Numpy array which is True everywhere a
+ *    value is missing.  Must have the same shape as *array*.
+ *
+ * *converters* (list of callables): A sequence of methods which
+ *    convert from the native data types in the columns of *array* to
+ *    a unicode string in VOTABLE XML format.  Must have the same
+ *    length as the number of columns in *array*.
+ *
+ * *write_null_values* (boolean): When True, write null values in
+ *    their entirety in the table.  When False, just write empty <TD/>
+ *    elements when the data is null or missing.
+ *
+ * *indent* (integer): The number of spaces to indent the table.
+ *
+ * *buf_size* (integer): The size of the write buffer.
+ *
+ * Returns None.
+ */
+static PyObject*
+write_tabledata(PyObject* self, PyObject *args, PyObject *kwds)
+{
+    /* Inputs */
+    PyObject* write_method = NULL;
+    PyObject* array = NULL;
+    PyObject* mask = NULL;
+    PyObject* converters = NULL;
+    int write_null_values = 0;
+    Py_ssize_t indent = 0;
+    Py_ssize_t buf_size = (Py_ssize_t)1 << 8;
+
+    /* Output buffer */
+    CHAR* buf = NULL;
+    CHAR* x;
+
+    Py_ssize_t nrows = 0;
+    Py_ssize_t ncols = 0;
+    Py_ssize_t i, j;
+    int write_full;
+    int all;
+    PyObject* numpy_module = NULL;
+    PyObject* numpy_all_method = NULL;
+    PyObject* array_row = NULL;
+    PyObject* mask_row = NULL;
+    PyObject* array_val = NULL;
+    PyObject* mask_val = NULL;
+    PyObject* converter = NULL;
+    PyObject* all_masked_obj = NULL;
+    PyObject* str_val = NULL;
+    PyObject* tmp = NULL;
+    CHAR* str_tmp = NULL;
+    Py_ssize_t str_len = 0;
+    PyObject* result = 0;
+
+    if (!PyArg_ParseTuple(args, "OOOOinn:write_tabledata",
+                          &write_method, &array, &mask, &converters,
+                          &write_null_values, &indent, &buf_size)) {
+        goto exit;
+    }
+
+    if (!PyCallable_Check(write_method)) goto exit;
+    if (!PySequence_Check(array)) goto exit;
+    if (!PySequence_Check(mask)) goto exit;
+    if (!PyList_Check(converters)) goto exit;
+    indent = CLAMP(indent, (Py_ssize_t)0, (Py_ssize_t)80);
+    buf_size = CLAMP(buf_size, (Py_ssize_t)1 << 8, (Py_ssize_t)1 << 24);
+
+    if ((numpy_module = PyImport_ImportModule("numpy")) == NULL) goto exit;
+    if ((numpy_all_method = PyObject_GetAttrString(numpy_module, "all"))
+        == NULL) goto exit;
+
+    if ((nrows = PySequence_Size(array)) == -1) goto exit;
+    if ((ncols = PyList_Size(converters)) == -1) goto exit;
+
+    if ((buf = malloc((size_t)buf_size * sizeof(CHAR))) == NULL) goto exit;
+
+    for (i = 0; i < nrows; ++i) {
+        if ((array_row = PySequence_GetItem(array, i)) == NULL) goto exit;
+        if ((mask_row = PySequence_GetItem(mask, i)) == NULL) goto exit;
+
+        x = buf;
+        if (_write_indent(&buf, &buf_size, &x, indent)) goto exit;
+        if (_write_cstring(&buf, &buf_size, &x, " <TR>\n", 6)) goto exit;
+
+        for (j = 0; j < ncols; ++j) {
+            if ((converter = PyList_GET_ITEM(converters, j)) == NULL) goto exit;
+            if ((array_val = PySequence_GetItem(array_row, j)) == NULL) goto exit;
+            if ((mask_val = PySequence_GetItem(mask_row, j)) == NULL) goto exit;
+
+            if (write_null_values) {
+                write_full = 1;
+            } else {
+                if (mask_val == Py_False) {
+                    write_full = 1;
+                } else if (mask_val == Py_True) {
+                    write_full = 0;
+                } else {
+                    if ((all_masked_obj =
+                         PyObject_CallFunctionObjArgs(numpy_all_method, mask_val, NULL))
+                        == NULL) goto exit;
+                    if ((all = PyObject_IsTrue(all_masked_obj)) == -1) {
+                        Py_DECREF(all_masked_obj);
+                        goto exit;
+                    }
+                    Py_DECREF(all_masked_obj);
+
+                    write_full = !all;
+                }
+            }
+
+            if (write_full) {
+                if (_write_indent(&buf, &buf_size, &x, indent)) goto exit;
+
+                if ((str_val =
+                     PyObject_CallFunctionObjArgs(converter, array_val, mask_val, NULL))
+                    == NULL) goto exit;
+                if ((str_tmp = PyUnicode_AsUnicode(str_val)) == NULL) {
+                    Py_DECREF(str_val);
+                    goto exit;
+                }
+
+                str_len = PyUnicode_GetSize(str_val);
+                if (str_len) {
+                    if (_write_cstring(&buf, &buf_size, &x, "  <TD>", 6) ||
+                        _write_string(&buf, &buf_size, &x, str_tmp, str_len) ||
+                        _write_cstring(&buf, &buf_size, &x, "</TD>\n", 6)) {
+                        Py_DECREF(str_val);
+                        goto exit;
+                    }
+                } else {
+                    if (_write_cstring(&buf, &buf_size, &x, "  <TD/>\n", 8)) {
+                        Py_DECREF(str_val);
+                        goto exit;
+                    }
+                }
+
+                Py_DECREF(str_val);
+            } else {
+                if (_write_indent(&buf, &buf_size, &x, indent)) goto exit;
+                if (_write_cstring(&buf, &buf_size, &x, "  <TD/>\n", 8)) goto exit;
+            }
+
+            Py_DECREF(array_val); array_val = NULL;
+            Py_DECREF(mask_val);  mask_val = NULL;
+        }
+
+        Py_DECREF(array_row); array_row = NULL;
+        Py_DECREF(mask_row);  mask_row = NULL;
+
+        if (_write_indent(&buf, &buf_size, &x, indent)) goto exit;
+        if (_write_cstring(&buf, &buf_size, &x, " </TR>\n", 7)) goto exit;
+
+        /* NULL-terminate the string */
+        *x = (CHAR)0;
+        if ((tmp = PyObject_CallFunction(write_method, "u#", buf, x - buf))
+            == NULL) goto exit;
+        Py_DECREF(tmp);
+    }
+
+    Py_INCREF(Py_None);
+    result = Py_None;
+
+ exit:
+    Py_XDECREF(numpy_module);
+    Py_XDECREF(numpy_all_method);
+
+    Py_XDECREF(array_row);
+    Py_XDECREF(mask_row);
+    Py_XDECREF(array_val);
+    Py_XDECREF(mask_val);
+
+    free(buf);
+
+    return result;
+}
+
+/******************************************************************************
+ * Module setup
+ ******************************************************************************/
+
+static PyMethodDef module_methods[] =
+{
+    {"write_tabledata", (PyCFunction)write_tabledata, METH_VARARGS,
+     "Fast C method to write tabledata"},
+    {NULL}  /* Sentinel */
+};
+
+struct module_state {
+    void* none;
+};
+
+#ifdef IS_PY3K
+static int module_traverse(PyObject* m, visitproc visit, void* arg)
+{
+    return 0;
+}
+
+static int module_clear(PyObject* m)
+{
+    return 0;
+}
+
+static struct PyModuleDef moduledef = {
+    PyModuleDef_HEAD_INIT,
+    "tablewriter",
+    "Fast way to write VOTABLE TABLEDATA",
+    sizeof(struct module_state),
+    module_methods,
+    NULL,
+    module_traverse,
+    module_clear,
+    NULL
+};
+
+#  define INITERROR return NULL
+
+PyMODINIT_FUNC
+PyInit_tablewriter(void)
+#else /* Not PY3K */
+#  define INITERROR return
+
+#  ifndef PyMODINIT_FUNC  /* declarations for DLL import/export */
+#    define PyMODINIT_FUNC void
+#  endif
+
+PyMODINIT_FUNC
+inittablewriter(void)
+#endif
+{
+    PyObject* m;
+
+#ifdef IS_PY3K
+    m = PyModule_Create(&moduledef);
+#else
+    m = Py_InitModule3("tablewriter", module_methods,
+                       "Fast way to write VOTABLE TABLEDATA");
+#endif
+
+    if (m == NULL)
+        INITERROR;
+
+#ifdef IS_PY3K
+    return m;
+#endif
+}
diff --git a/astropy/io/votable/table.py b/astropy/io/votable/table.py
new file mode 100644
index 0000000..669769a
--- /dev/null
+++ b/astropy/io/votable/table.py
@@ -0,0 +1,336 @@
+"""
+This file contains a contains the high-level functions to read a
+VOTable file.
+"""
+
+from __future__ import division, absolute_import
+
+# STDLIB
+import io
+import os
+import sys
+import warnings
+
+# LOCAL
+from . import exceptions
+from . import tree
+from ...utils.xml import iterparser
+from ...utils import data
+from ...config import ConfigurationItem
+
+
+__all__ = ['parse', 'parse_single_table', 'from_table', 'writeto', 'validate']
+
+
+PEDANTIC = ConfigurationItem(
+    'pedantic',
+    False,
+    'When True, treat fixable violations of the VOTable spec as exceptions.')
+
+
+def parse(source, columns=None, invalid='exception', pedantic=None,
+          chunk_size=tree.DEFAULT_CHUNK_SIZE, table_number=None,
+          table_id=None, filename=None,
+          _debug_python_based_parser=False):
+    """
+    Parses a VOTABLE_ xml file (or file-like object), and returns a
+    `~astropy.io.votable.tree.VOTable` object.
+
+    Parameters
+    ----------
+    source : str or readable file-like object
+        Path or file object containing a VOTABLE_ xml file.
+
+    columns : sequence of str, optional
+        List of field names to include in the output.  The default is
+        to include all fields.
+
+    invalid : str, optional
+        One of the following values:
+
+            - 'exception': throw an exception when an invalid value is
+              encountered (default)
+
+            - 'mask': mask out invalid values
+
+    pedantic : bool, optional
+        When `True`, raise an error when the file violates the spec,
+        otherwise issue a warning.  Warnings may be controlled using
+        the standard Python mechanisms.  See the `warnings`
+        module in the Python standard library for more information.
+        When not provided, uses the configuration setting
+        `astropy.io.votable.pedantic`, which defaults to True.
+
+    chunk_size : int, optional
+        The number of rows to read before converting to an array.
+        Higher numbers are likely to be faster, but will consume more
+        memory.
+
+    table_number : int, optional
+        The number of table in the file to read in.  If `None`, all
+        tables will be read.  If a number, 0 refers to the first table
+        in the file, and only that numbered table will be parsed and
+        read in.  Should not be used with `table_id`.
+
+    table_id : str, optional
+        The ID of the table in the file to read in.  Should not be
+        used with `table_number`.
+
+    filename : str, optional
+        A filename, URL or other identifier to use in error messages.
+        If *filename* is None and *source* is a string (i.e. a path),
+        then *source* will be used as a filename for error messages.
+        Therefore, *filename* is only required when source is a
+        file-like object.
+
+    Returns
+    -------
+    votable : `astropy.io.votable.tree.VOTableFile` object
+
+    See also
+    --------
+    astropy.io.votable.exceptions : The exceptions this function may raise.
+    """
+    invalid = invalid.lower()
+    assert invalid in ('exception', 'mask')
+
+    if pedantic is None:
+        pedantic = PEDANTIC()
+
+    config = {
+        'columns'      :      columns,
+        'invalid'      :      invalid,
+        'pedantic'     :     pedantic,
+        'chunk_size'   :   chunk_size,
+        'table_number' : table_number,
+        'filename'     :     filename}
+
+    if filename is None and isinstance(source, basestring):
+        config['filename'] = source
+
+    with iterparser.get_xml_iterator(
+        source,
+        _debug_python_based_parser=_debug_python_based_parser) as iterator:
+        return tree.VOTableFile(
+            config=config, pos=(1, 1)).parse(iterator, config)
+
+
+def parse_single_table(source, **kwargs):
+    """
+    Parses a VOTABLE_ xml file (or file-like object), reading and
+    returning only the first `~astropy.io.votable.tree.Table`
+    instance.
+
+    See `parse` for a description of the keyword arguments.
+
+    Returns
+    -------
+    votable : `astropy.io.votable.tree.Table` object
+    """
+    if kwargs.get('table_number') is None:
+        kwargs['table_number'] = 0
+
+    votable = parse(source, **kwargs)
+
+    return votable.get_first_table()
+
+
+def writeto(table, file):
+    """
+    Writes a `astropy.io.vo.VOTableFile` to a VOTABLE_ xml file.
+
+    Parameters
+    ----------
+    table : `astropy.io.vo.VOTableFile` or `astropy.table.Table` instance.
+
+    file : str or writable file-like object
+        Path or file object to write to
+    """
+    from ...table import Table
+    if isinstance(table, Table):
+        table = tree.VOTableFile.from_table(table)
+    elif not isinstance(table, tree.VOTableFile):
+        raise TypeError(
+            "first argument must be astropy.io.vo.VOTableFile or "
+            "astropy.table.Table instance")
+    table.to_xml(file, _debug_python_based_parser=True)
+
+
+def validate(source, output=sys.stdout, xmllint=False, filename=None):
+    """
+    Prints a validation report for the given file.
+
+    Parameters
+    ----------
+    source : str or readable file-like object
+        Path to a VOTABLE_ xml file.
+
+    output : writable file-like object, optional
+        Where to output the report.  Defaults to `sys.stdout`.
+        If `None`, the output will be returned as a string.
+
+    xmllint : bool, optional
+        When `True`, also send the file to `xmllint` for schema and
+        DTD validation.  Requires that `xmllint` is installed.  The
+        default is `False`.  `source` must be a file on the local
+        filesystem in order for `xmllint` to work.
+
+    filename : str, optional
+        A filename to use in the error messages.  If not provided, one
+        will be automatically determined from ``source``.
+
+    Returns
+    -------
+    is_valid : bool or str
+        Returns `True` if no warnings were found.  If `output` is
+        `None`, the return value will be a string.
+    """
+    import textwrap
+    from . import converters, xmlutil
+    from ...utils.console import print_code_line, color_print
+
+    return_as_str = False
+    if output is None:
+        output = io.StringIO()
+
+    lines = []
+    votable = None
+
+    # This is a special variable used by the Python warnings
+    # infrastructure to keep track of warnings that have already been
+    # seen.  Since we want to get every single warning out of this, we
+    # have to delete all of them first.
+    for module in (exceptions, converters, tree, xmlutil):
+        if hasattr(module, '__warningregistry__'):
+            del module.__warningregistry__
+
+    with data.get_readable_fileobj(source, encoding='binary') as fd:
+        content = fd.read()
+    content_buffer = io.BytesIO(content)
+    content_buffer.seek(0)
+
+    if filename is None:
+        if isinstance(source, basestring):
+            filename = source
+        elif hasattr(source, 'name'):
+            filename = source.name
+        elif hasattr(source, 'url'):
+            filename = source.url
+        else:
+            filename = "<unknown>"
+
+    with warnings.catch_warnings(record=True) as warning_lines:
+        warnings.resetwarnings()
+        warnings.simplefilter("always", exceptions.VOWarning, append=True)
+        try:
+            votable = parse(content_buffer, pedantic=False, filename=filename)
+        except ValueError as e:
+            lines.append(str(e))
+    lines = [str(x.message) for x in warning_lines] + lines
+
+    content_buffer.seek(0)
+    output.write(u"Validation report for {0}\n\n".format(filename))
+
+    if len(lines):
+        xml_lines = iterparser.xml_readlines(content_buffer)
+
+        for warning in lines:
+            w = exceptions.parse_vowarning(warning)
+
+            if not w['is_something']:
+                output.write(warning)
+                output.write(u'\n\n')
+            else:
+                line = xml_lines[w['nline'] - 1]
+                warning = w['warning']
+                if w['is_warning']:
+                    color = 'yellow'
+                else:
+                    color = 'red'
+                color_print(
+                    u'{0:d}: '.format(w['nline']), '',
+                    warning or 'EXC', color,
+                    u': ', '',
+                    textwrap.fill(
+                        w['message'],
+                        initial_indent=u'          ',
+                        subsequent_indent=u'  ').lstrip(),
+                    file=output)
+                print_code_line(line, w['nchar'], file=output)
+            output.write(u'\n')
+    else:
+        output.write(u'astropy.io.votable found no violations.\n\n')
+
+    success = 0
+    if xmllint and os.path.exists(filename):
+        from ...utils.xml import validate
+
+        if votable is None:
+            version = "1.1"
+        else:
+            version = votable.version
+        success, stdout, stderr = validate.validate_schema(
+            filename, version)
+
+        if success != 0:
+            output.write(
+                u'xmllint schema violations:\n\n')
+            output.write(stderr)
+        else:
+            output.write(u'xmllint passed\n')
+
+    if return_as_str:
+        return output.getvalue()
+    return len(lines) == 0 and success == 0
+
+
+def from_table(table, table_id=None):
+    """
+    Given an `astropy.table.Table` object, return a
+    `~astropy.io.votable.tree.VOTableFile` file structure containing
+    just that single table.
+
+    Parameters
+    ----------
+    table : `astropy.table.Table` instance
+
+    table_id : str, optional
+        If not `None`, set the given id on the returned
+        `~astropy.tree.Table` instance.
+
+    Returns
+    -------
+    votable : `astropy.io.votable.tree.VOTableFile` instance
+    """
+    return tree.VOTableFile.from_table(table, table_id=table_id)
+
+
+def is_votable(source):
+    """
+    Reads the header of a file to determine if it is a VOTable file.
+
+    Parameters
+    ----------
+    source : str or readable file-like object
+        Path or file object containing a VOTABLE_ xml file.
+
+    Returns
+    -------
+    is_votable : bool
+        Returns `True` if the given file is a VOTable file.
+    """
+    try:
+        with iterparser.get_xml_iterator(source) as iterator:
+            for start, tag, data, pos in iterator:
+                if tag != 'xml':
+                    return False
+                break
+
+            for start, tag, data, pos in iterator:
+                if tag != 'VOTABLE':
+                    return False
+                break
+
+            return True
+    except ValueError:
+        return False
diff --git a/astropy/io/vo/tests/__init__.py b/astropy/io/votable/tests/__init__.py
similarity index 100%
copy from astropy/io/vo/tests/__init__.py
copy to astropy/io/votable/tests/__init__.py
diff --git a/astropy/io/votable/tests/converter_test.py b/astropy/io/votable/tests/converter_test.py
new file mode 100644
index 0000000..8e23067
--- /dev/null
+++ b/astropy/io/votable/tests/converter_test.py
@@ -0,0 +1,204 @@
+# THIRD-PARTY
+import numpy as np
+from numpy.testing import assert_array_equal
+
+# LOCAL
+from .. import converters
+from .. import exceptions
+from .. import tree
+from ....tests.helper import raises
+
+
+ at raises(exceptions.E13)
+def test_invalid_arraysize():
+    field = tree.Field(
+        None, name='broken', datatype='char', arraysize='foo')
+    converters.get_converter(field)
+
+
+def test_oversize_char(recwarn):
+    config = {'pedantic': True}
+    field = tree.Field(
+        None, name='c', datatype='char',
+        config=config)
+    c = converters.get_converter(field, config=config)
+    w = recwarn.pop(exceptions.W47)
+
+    c.parse(u"XXX")
+    w = recwarn.pop(exceptions.W46)
+
+
+def test_char_mask():
+    config = {'pedantic': True}
+    field = tree.Field(
+        None, name='c', datatype='char',
+        config=config)
+    c = converters.get_converter(field, config=config)
+    assert c.output("Foo", True) == ''
+
+
+def test_oversize_unicode(recwarn):
+    config = {'pedantic': True}
+    field = tree.Field(
+        None, name='c2', datatype='unicodeChar',
+        config=config)
+    c = converters.get_converter(field, config=config)
+
+    c.parse(u"XXX")
+    w = recwarn.pop(exceptions.W46)
+
+
+def test_unicode_mask():
+    config = {'pedantic': True}
+    field = tree.Field(
+        None, name='c', datatype='unicodeChar',
+        config=config)
+    c = converters.get_converter(field, config=config)
+    assert c.output(u"Foo", True) == u''
+
+
+ at raises(exceptions.E02)
+def test_wrong_number_of_elements():
+    config = {'pedantic': True}
+    field = tree.Field(
+        None, name='c', datatype='int', arraysize='2x3*',
+        config=config)
+    c = converters.get_converter(field, config=config)
+    c.parse("2 3 4 5 6")
+
+
+ at raises(ValueError)
+def test_float_mask():
+    config = {'pedantic': True}
+    field = tree.Field(
+        None, name='c', datatype='float',
+        config=config)
+    c = converters.get_converter(field, config=config)
+    assert c.parse('') == (c.null, True)
+    c.parse('null')
+
+
+def test_float_mask_permissive():
+    config = {'pedantic': False}
+    field = tree.Field(
+        None, name='c', datatype='float',
+        config=config)
+    c = converters.get_converter(field, config=config)
+    assert c.parse('null') == (c.null, True)
+
+
+ at raises(exceptions.E02)
+def test_complex_array_vararray():
+    config = {'pedantic': True}
+    field = tree.Field(
+        None, name='c', datatype='floatComplex', arraysize='2x3*',
+        config=config)
+    c = converters.get_converter(field, config=config)
+    c.parse("2 3 4 5 6")
+
+
+def test_complex_array_vararray2():
+    config = {'pedantic': True}
+    field = tree.Field(
+        None, name='c', datatype='floatComplex', arraysize='2x3*',
+        config=config)
+    c = converters.get_converter(field, config=config)
+    x = c.parse("")
+    assert len(x[0]) == 0
+
+
+def test_complex_array_vararray():
+    config = {'pedantic': True}
+    field = tree.Field(
+        None, name='c', datatype='doubleComplex', arraysize='2x3*',
+        config=config)
+    c = converters.get_converter(field, config=config)
+    x = c.parse("1 2 3 4 5 6 7 8 9 10 11 12")
+    assert len(x) == 2
+    assert np.all(x[0][0][0] == complex(1, 2))
+
+
+def test_complex_vararray():
+    config = {'pedantic': True}
+    field = tree.Field(
+        None, name='c', datatype='doubleComplex', arraysize='*',
+        config=config)
+    c = converters.get_converter(field, config=config)
+    x = c.parse("1 2 3 4")
+    assert len(x) == 2
+    assert x[0][0] == complex(1, 2)
+
+
+ at raises(exceptions.E03)
+def test_complex():
+    config = {'pedantic': True}
+    field = tree.Field(
+        None, name='c', datatype='doubleComplex',
+        config=config)
+    c = converters.get_converter(field, config=config)
+    x = c.parse("1 2 3")
+
+
+ at raises(exceptions.E04)
+def test_bit():
+    config = {'pedantic': True}
+    field = tree.Field(
+        None, name='c', datatype='bit',
+        config=config)
+    c = converters.get_converter(field, config=config)
+    x = c.parse("T")
+
+
+def test_bit_mask(recwarn):
+    config = {'pedantic': True}
+    field = tree.Field(
+        None, name='c', datatype='bit',
+        config=config)
+    c = converters.get_converter(field, config=config)
+    c.output(True, True)
+    recwarn.pop(exceptions.W39)
+
+
+ at raises(exceptions.E05)
+def test_boolean():
+    config = {'pedantic': True}
+    field = tree.Field(
+        None, name='c', datatype='boolean',
+        config=config)
+    c = converters.get_converter(field, config=config)
+    c.parse('YES')
+
+
+def test_boolean_array():
+    config = {'pedantic': True}
+    field = tree.Field(
+        None, name='c', datatype='boolean', arraysize='*',
+        config=config)
+    c = converters.get_converter(field, config=config)
+    r, mask = c.parse('TRUE FALSE T F 0 1')
+    assert_array_equal(r, [True, False, True, False, False, True])
+
+
+ at raises(exceptions.E06)
+def test_invalid_type():
+    config = {'pedantic': True}
+    field = tree.Field(
+        None, name='c', datatype='foobar',
+        config=config)
+    c = converters.get_converter(field, config=config)
+
+
+def test_precision():
+    config = {'pedantic': True}
+
+    field = tree.Field(
+        None, name='c', datatype='float', precision="E4",
+        config=config)
+    c = converters.get_converter(field, config=config)
+    assert c.output(266.248, False) == '266.2'
+
+    field = tree.Field(
+        None, name='c', datatype='float', precision="F4",
+        config=config)
+    c = converters.get_converter(field, config=config)
+    assert c.output(266.248, False) == '266.2480'
diff --git a/astropy/io/vo/tests/data/irsa-nph-error.xml b/astropy/io/votable/tests/data/irsa-nph-error.xml
similarity index 100%
rename from astropy/io/vo/tests/data/irsa-nph-error.xml
rename to astropy/io/votable/tests/data/irsa-nph-error.xml
diff --git a/astropy/io/vo/tests/data/irsa-nph-m31.xml b/astropy/io/votable/tests/data/irsa-nph-m31.xml
similarity index 100%
rename from astropy/io/vo/tests/data/irsa-nph-m31.xml
rename to astropy/io/votable/tests/data/irsa-nph-m31.xml
diff --git a/astropy/io/votable/tests/data/regression.bin.tabledata.truth.xml b/astropy/io/votable/tests/data/regression.bin.tabledata.truth.xml
new file mode 100644
index 0000000..b956f83
--- /dev/null
+++ b/astropy/io/votable/tests/data/regression.bin.tabledata.truth.xml
@@ -0,0 +1,304 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Produced with astropy.io.votable version testing
+     http://www.astropy.org/ -->
+<VOTABLE version="1.1" xmlns="http://www.ivoa.net/xml/VOTable/v1.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.ivoa.net/xml/VOTable/v1.1">
+ <DESCRIPTION>
+  The VOTable format is an XML standard for the interchange of data
+  represented as a set of tables. In this context, a table is an
+  unordered set of rows, each of a uniform format, as specified in the
+  table metadata. Each row in a table is a sequence of table cells,
+  and each of these contains either a primitive data type, or an array
+  of such primitives. VOTable is derived from the Astrores format [1],
+  itself modeled on the FITS Table format [2]; VOTable was designed to
+  be closer to the FITS Binary Table format.
+ </DESCRIPTION>
+ <COOSYS ID="J2000" equinox="J2000" system="eq_FK5"/>
+ <PARAM ID="wrong_arraysize" arraysize="0" datatype="float" name="wrong_arraysize" value=""/>
+ <PARAM ID="INPUT" arraysize="*" datatype="float" name="INPUT" ucd="phys.size;instr.tel" unit="km.h-1" value="0 0">
+  <DESCRIPTION>
+   This is the most interesting parameter in the world, and it drinks
+   Dos Equis
+  </DESCRIPTION>
+ </PARAM>
+ <INFO ID="QUERY_STATUS" name="QUERY_STATUS" value="OK"/>
+ <RESOURCE type="results">
+  <DESCRIPTION>
+   This is a resource description
+  </DESCRIPTION>
+  <PARAM ID="awesome" arraysize="*" datatype="float" name="INPUT" unit="deg" value="0 0"/>
+  <PARAM ID="empty_value" arraysize="*" datatype="char" name="empty_value" unit="foo" value=""/>
+  <LINK href="http://www.foo.com/"/>
+  <TABLE ID="main_table" nrows="5">
+   <DESCRIPTION>
+    This describes the table.
+   </DESCRIPTION>
+   <FIELD ID="string_test" arraysize="*" datatype="char" name="string test"/>
+   <FIELD ID="string_test_2" arraysize="10" datatype="char" name="fixed string test"/>
+   <FIELD ID="unicode_test" arraysize="*" datatype="unicodeChar" name="unicode_test"/>
+   <FIELD ID="fixed_unicode_test" arraysize="10" datatype="unicodeChar" name="unicode test"/>
+   <FIELD ID="string_array_test" arraysize="4" datatype="char" name="string array test"/>
+   <FIELD ID="unsignedByte" datatype="unsignedByte" name="unsignedByte"/>
+   <FIELD ID="short" datatype="short" name="short"/>
+   <FIELD ID="int" datatype="int" name="int">
+    <VALUES ID="int_nulls" null="123456789">
+     <MIN inclusive="no" value="-1000"/>
+     <MAX inclusive="yes" value="1000"/>
+     <OPTION name="bogus" value="whatever"/>
+    </VALUES>
+   </FIELD>
+   <FIELD ID="long" datatype="long" name="long">
+    <VALUES ref="int_nulls"/>
+    <LINK href="http://www.long-integers.com/"/>
+   </FIELD>
+   <FIELD ID="double" datatype="double" name="double"/>
+   <FIELD ID="float" datatype="float" name="float"/>
+   <FIELD ID="array" arraysize="2x2*" datatype="long" name="array">
+    <VALUES null="-1"/>
+   </FIELD>
+   <FIELD ID="bit" datatype="bit" name="bit"/>
+   <FIELD ID="bitarray" arraysize="2x3" datatype="bit" name="bitarray"/>
+   <FIELD ID="bitvararray" arraysize="*" datatype="bit" name="bitvararray"/>
+   <FIELD ID="bitvararray2" arraysize="2x3x*" datatype="bit" name="bitvararray2"/>
+   <FIELD ID="floatComplex" datatype="floatComplex" name="floatComplex"/>
+   <FIELD ID="doubleComplex" datatype="doubleComplex" name="doubleComplex"/>
+   <FIELD ID="doubleComplexArray" arraysize="*" datatype="doubleComplex" name="doubleComplexArray"/>
+   <FIELD ID="doubleComplexArrayFixed" arraysize="2" datatype="doubleComplex" name="doubleComplexArrayFixed"/>
+   <FIELD ID="boolean" datatype="boolean" name="boolean"/>
+   <FIELD ID="booleanArray" arraysize="4" datatype="boolean" name="booleanArray"/>
+   <FIELD ID="nulls" datatype="int" name="nulls">
+    <VALUES null="-9"/>
+   </FIELD>
+   <FIELD ID="nulls_array" arraysize="2x2" datatype="int" name="nulls_array">
+    <VALUES null="-9"/>
+   </FIELD>
+   <FIELD ID="precision1" datatype="double" name="precision1" precision="E3" width="10"/>
+   <FIELD ID="precision2" datatype="double" name="precision2" precision="F3"/>
+   <FIELD ID="doublearray" arraysize="*" datatype="double" name="doublearray">
+    <VALUES null="-1.0"/>
+   </FIELD>
+   <FIELD ID="bitarray2" arraysize="16" datatype="bit" name="bitarray2"/>
+   <PARAM ID="INPUT2" arraysize="*" datatype="float" name="INPUT2" unit="deg" value="0 0">
+    <DESCRIPTION>
+     This is the most interesting parameter in the world, and it
+     drinks Dos Equis
+    </DESCRIPTION>
+   </PARAM>
+   <GROUP>
+    <PARAMref ref="awesome"/>
+   </GROUP>
+   <GROUP>
+    <DESCRIPTION>
+     This should warn of a second description.
+    </DESCRIPTION>
+    <FIELDref ref="boolean"/>
+    <GROUP>
+     <PARAMref ref="awesome"/>
+     <PARAM ID="OUTPUT" datatype="float" name="OUTPUT" value="42"/>
+    </GROUP>
+    <PARAM ID="INPUT3" arraysize="*" datatype="float" name="INPUT3" unit="deg" value="0 0">
+     <DESCRIPTION>
+      This is the most interesting parameter in the world, and it
+      drinks Dos Equis
+     </DESCRIPTION>
+    </PARAM>
+   </GROUP>
+   <LINK href="http://tabledata.org/"/>
+   <DATA>
+    <TABLEDATA>
+     <TR>
+      <TD>String & test</TD>
+      <TD>Fixed stri</TD>
+      <TD>Ceçi n'est pas un pipe</TD>
+      <TD>Ceçi n'est</TD>
+      <TD>ab c</TD>
+      <TD>128</TD>
+      <TD>4096</TD>
+      <TD>268435456</TD>
+      <TD>922337203685477</TD>
+      <TD>1</TD>
+      <TD>1</TD>
+      <TD/>
+      <TD>1</TD>
+      <TD>101101</TD>
+      <TD>1 1 1</TD>
+      <TD/>
+      <TD/>
+      <TD/>
+      <TD/>
+      <TD>0 0 0 0</TD>
+      <TD>T</TD>
+      <TD>T T T T</TD>
+      <TD>0</TD>
+      <TD/>
+      <TD>      1.33</TD>
+      <TD>1.333</TD>
+      <TD/>
+      <TD>1111000011110000</TD>
+     </TR>
+     <TR>
+      <TD>String &amp; test</TD>
+      <TD>0123456789</TD>
+      <TD>வணக்கம்</TD>
+      <TD>வணக்கம்</TD>
+      <TD>0123</TD>
+      <TD>0</TD>
+      <TD>0</TD>
+      <TD>2147483647</TD>
+      <TD/>
+      <TD>0</TD>
+      <TD>0</TD>
+      <TD>42 32 12 32</TD>
+      <TD>0</TD>
+      <TD>010011</TD>
+      <TD>0 0 0 0 0</TD>
+      <TD>0 1 0 0 1 0 1 0 1 0 1 0</TD>
+      <TD>0 0</TD>
+      <TD>0 0</TD>
+      <TD>0 0 0 0</TD>
+      <TD>0 -1 -1 -1</TD>
+      <TD>F</TD>
+      <TD>T T F T</TD>
+      <TD/>
+      <TD>0 1 2 3</TD>
+      <TD>         1</TD>
+      <TD>1.000</TD>
+      <TD>0 1 +InF -InF NaN 0 -1</TD>
+      <TD>0000000000000000</TD>
+     </TR>
+     <TR>
+      <TD>XXXX</TD>
+      <TD>XXXX</TD>
+      <TD>XXXX</TD>
+      <TD>0123456789</TD>
+      <TD/>
+      <TD>233</TD>
+      <TD>-4096</TD>
+      <TD>-268435456</TD>
+      <TD>-1152921504606846976</TD>
+      <TD>+InF</TD>
+      <TD>+InF</TD>
+      <TD>12 34 56 78 87 65 43 21</TD>
+      <TD>1</TD>
+      <TD>111000</TD>
+      <TD>1 0 1 0 1</TD>
+      <TD>1 1 1 1 1 1</TD>
+      <TD>0 -1</TD>
+      <TD>0 -1</TD>
+      <TD>0 0 0 0</TD>
+      <TD>0 0 0 0</TD>
+      <TD>T</TD>
+      <TD>T T ? T</TD>
+      <TD>2</TD>
+      <TD>-9 0 -9 1</TD>
+      <TD>     1e+34</TD>
+      <TD>9999999999999999455752309870428160.000</TD>
+      <TD/>
+      <TD>0000000000000000</TD>
+     </TR>
+     <TR>
+      <TD/>
+      <TD/>
+      <TD/>
+      <TD/>
+      <TD/>
+      <TD>255</TD>
+      <TD>-1</TD>
+      <TD>268435455</TD>
+      <TD>1152921504606846975</TD>
+      <TD/>
+      <TD>+InF</TD>
+      <TD>-1 23</TD>
+      <TD>0</TD>
+      <TD>000000</TD>
+      <TD/>
+      <TD/>
+      <TD/>
+      <TD/>
+      <TD/>
+      <TD>0 0 0 0</TD>
+      <TD>F</TD>
+      <TD/>
+      <TD/>
+      <TD>0 -9 1 -9</TD>
+      <TD/>
+      <TD/>
+      <TD/>
+      <TD>0000000000000000</TD>
+     </TR>
+     <TR>
+      <TD/>
+      <TD/>
+      <TD/>
+      <TD/>
+      <TD/>
+      <TD>0</TD>
+      <TD>0</TD>
+      <TD/>
+      <TD/>
+      <TD>-InF</TD>
+      <TD/>
+      <TD>31 -1</TD>
+      <TD>0</TD>
+      <TD>000000</TD>
+      <TD/>
+      <TD/>
+      <TD/>
+      <TD/>
+      <TD/>
+      <TD>0 0 0 0</TD>
+      <TD/>
+      <TD/>
+      <TD/>
+      <TD/>
+      <TD/>
+      <TD/>
+      <TD/>
+      <TD>0000000000000000</TD>
+     </TR>
+    </TABLEDATA>
+   </DATA>
+  </TABLE>
+  <RESOURCE type="results">
+   <TABLE nrows="1" ref="main_table">
+    <DESCRIPTION>
+     This is a referenced table
+    </DESCRIPTION>
+    <DATA>
+     <TABLEDATA>
+      <TR>
+       <TD>String & test</TD>
+       <TD>Fixed stri</TD>
+       <TD>Ceçi n'est pas un pipe</TD>
+       <TD>Ceçi n'est</TD>
+       <TD>ab c</TD>
+       <TD>128</TD>
+       <TD>4096</TD>
+       <TD>268435456</TD>
+       <TD>922337203685477</TD>
+       <TD>1</TD>
+       <TD>1</TD>
+       <TD/>
+       <TD>1</TD>
+       <TD>101101</TD>
+       <TD>1 1 1</TD>
+       <TD/>
+       <TD/>
+       <TD/>
+       <TD/>
+       <TD>0 0 0 0</TD>
+       <TD>T</TD>
+       <TD>T T T T</TD>
+       <TD>0</TD>
+       <TD/>
+       <TD>      1.33</TD>
+       <TD>1.333</TD>
+       <TD/>
+       <TD>1111000011110000</TD>
+      </TR>
+     </TABLEDATA>
+    </DATA>
+   </TABLE>
+   <TABLE ID="last_table" nrows="0" ref="main_table"/>
+  </RESOURCE>
+ </RESOURCE>
+</VOTABLE>
diff --git a/astropy/io/votable/tests/data/regression.xml b/astropy/io/votable/tests/data/regression.xml
new file mode 100644
index 0000000..8250562
--- /dev/null
+++ b/astropy/io/votable/tests/data/regression.xml
@@ -0,0 +1,302 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE VOTABLE SYSTEM "http://us-vo.org/xml/VOTable.dtd">
+<VOTABLE version="1.1"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:noNamespaceSchemaLocation="http://www.ivoa.net/xml/VOTable/v1.1"
+ xmlns="http://www.ivoa.net/xml/VOTable/v1.1">
+<DESCRIPTION > <!-- This should get word-wrapped -->
+The VOTable format is an XML standard for the interchange of data represented as a set of tables. In this context, a table is an unordered set of rows, each of a uniform format, as specified in the table metadata. Each row in a table is a sequence of table cells, and each of these contains either a primitive data type, or an array of such primitives. VOTable is derived from the Astrores format [1], itself modeled on the FITS Table format [2]; VOTable was designed to be closer to the FITS Binary Table format.
+</DESCRIPTION>
+<COOSYS ID="J2000" system="eq_FK5" equinox="J2000"/>
+<PARAM datatype="float" name="wrong_arraysize" value="0.000000,0.000000" arraysize="0"/>
+<PARAM datatype="float" name="INPUT" value="0.000000,0.000000" arraysize="*" unit="km/h" ucd="phys.size;instr.tel">
+  <DESCRIPTION>This is the most interesting parameter in the world, and it drinks Dos Equis</DESCRIPTION>
+</PARAM>
+<INFO name="QUERY_STATUS" value="OK"/>
+<RESOURCE type="results">
+<DESCRIPTION>
+  This is a resource description
+</DESCRIPTION>
+<PARAM ID="awesome" datatype="float" name="INPUT" value="0.000000,0.000000" arraysize="*" unit="deg"></PARAM>
+<PARAM ID="empty_value" name="empty_value" arraysize="*" datatype="char" value="" unit="foo"/>
+<LINK href="http://www.foo.com/" gref="DECPRECATED">
+  <DESCRIPTION>Really, this link is totally bogus.</DESCRIPTION>
+</LINK>
+<TABLE ID="main_table">
+<DESCRIPTION>
+  This describes the table.
+</DESCRIPTION>
+<GROUP>
+  <PARAMref ref="awesome"/>
+</GROUP>
+<PARAM datatype="float" name="INPUT2" value="0.000000,0.000000" arraysize="*" unit="deg">
+  <DESCRIPTION>This is the most interesting parameter in the world, and it drinks Dos Equis</DESCRIPTION>
+</PARAM>
+<FIELD id="string_test" name="string test" datatype="char" arraysize="*"></FIELD>
+<FIELD ID="string_test" name="fixed string test" datatype="char" arraysize="10"/>
+<FIELD ID="unicode_test" name="unicode_test" datatype="unicodeChar" arraysize="*"/>
+<FIELD ID="fixed_unicode_test" name="unicode test" datatype="unicodeString" arraysize="10"/>
+<LINK href="http://tabledata.org/"/>
+<FIELD ID="string_array_test" name="string array test" datatype="string" arraysize="4*"/>
+<FIELD ID="unsignedByte" name="unsignedByte" datatype="unsignedByte"/>
+<FIELD ID="short" name="short" datatype="short"/>
+<FIELD ID="int" name="int" datatype="int">
+  <VALUES null="123456789" ID="int_nulls">
+    <MIN value="-1000" inclusive="no"/>
+    <MAX value="1000" inclusive="yes"/>
+    <OPTION name="bogus" value="whatever"/>
+  </VALUES>
+  <IGNORE_ME/>
+</FIELD>
+<FIELD ID="long" name="long" datatype="long">
+  <LINK href="http://www.long-integers.com/"/>
+  <VALUES ref="int_nulls"/>
+</FIELD>
+<FIELD ID="double" name="double" datatype="double"/>
+<FIELD ID="float" name="float" datatype="float">
+  <VALUES null=""/>
+</FIELD>
+<FIELD ID="array" name="array" datatype="long" arraysize="2x2*">
+  <VALUES null="-1"/>
+</FIELD>
+<FIELD ID="bit" name="bit" datatype="bit"/>
+<FIELD ID="bitarray" name="bitarray" datatype="bit" arraysize="2x3"/>
+<FIELD ID="bitvararray" name="bitvararray" datatype="bit" arraysize="*"/>
+<FIELD ID="bitvararray2" name="bitvararray2" datatype="bit" arraysize="2x3x*"/>
+<FIELD ID="floatComplex" name="floatComplex" datatype="floatComplex"/>
+<FIELD ID="doubleComplex" name="doubleComplex" datatype="doubleComplex"/>
+<FIELD ID="doubleComplexArray" name="doubleComplexArray" datatype="doubleComplex" arraysize="*"/>
+<FIELD ID="doubleComplexArrayFixed" name="doubleComplexArrayFixed" datatype="doubleComplex" arraysize="2"/>
+<FIELD ID="boolean" name="boolean" datatype="boolean"/>
+<FIELD ID="booleanArray" name="booleanArray" datatype="boolean" arraysize="4"/>
+<FIELD ID="nulls" name="nulls" datatype="int">
+  <VALUES null="-9"/>
+</FIELD>
+<FIELD ID="nulls_array" name="nulls_array" datatype="int" arraysize="2x2">
+  <VALUES null="-9"/>
+</FIELD>
+<FIELD ID="precision1" name="precision1" datatype="double" precision="E3" width="10"/>
+<FIELD ID="precision2" name="precision2" datatype="double" precision="F3"/>
+<FIELD ID="doublearray" name="doublearray" datatype="double" arraysize="*">
+  <VALUES null="-1"/>
+</FIELD>
+<FIELD ID="bitarray2" name="bitarray2" datatype="bit" arraysize="16"/>
+<GROUP>
+  <DESCRIPTION>
+    This is just a group to make sure we can round-trip them.
+  </DESCRIPTION>
+  <DESCRIPTION>
+    This should warn of a second description.
+  </DESCRIPTION>
+  <FIELDref ref="boolean"/>
+  <GROUP>
+    <PARAMref ref="awesome"/>
+    <PARAM datatype="float" name="OUTPUT" value="42"/>
+  </GROUP>
+  <PARAM datatype="float" name="INPUT3" value="0.000000,0.000000" arraysize="*" unit="deg">
+    <DESCRIPTION>This is the most interesting parameter in the world, and it drinks Dos Equis</DESCRIPTION>
+  </PARAM>
+</GROUP>
+<DATA>
+<TABLEDATA>
+<TR>
+  <TD>String & test</TD>
+  <TD>Fixed string long test</TD> <!-- Should truncate -->
+  <TD>Ceçi n'est pas un pipe</TD> <!-- French, n'est-ce pas? -->
+  <TD>Ceçi n'est pas un pipe</TD>
+  <TD>ab cd</TD>
+  <TD>128</TD>
+  <TD>4096</TD>
+  <TD>268435456</TD>
+  <TD>922337203685477</TD>
+  <TD>1.0</TD>
+  <TD encoding="base64">P4AAAA==</TD>
+  <TD>   </TD>
+  <TD>1</TD>
+  <TD>1 0 1 1 0 1</TD>
+  <TD>1 1 1</TD>
+  <TD/>
+  <TD/>
+  <TD/>
+  <TD/>
+  <TD>0 0 0 0</TD>
+  <TD>True</TD>
+  <TD>True True True True</TD>
+  <TD>0</TD>
+  <TD/>
+  <TD>1.333333333333333333333333333333333</TD>
+  <TD>1.333333333333333333333333333333333</TD>
+  <TD/>
+  <TD>1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0</TD>
+</TR>
+<TR>
+  <TD><![CDATA[String & test]]></TD> <!-- Test that & is treated literally inside CDATA -->
+  <TD>0123456789A</TD>
+  <TD>வணக்கம்</TD>
+  <TD>வணக்கம்</TD>
+  <TD>0123456789A</TD>
+  <TD>256</TD> <!-- should overflow to 0 -->
+  <TD>65536</TD> <!-- should overflow to 0-->
+  <TD>2147483647</TD> <!-- overflowing here would raise a Numpy exception -->
+  <TD></TD>
+  <TD>1.0e-325</TD> <!-- underflow to 0 -->
+  <TD>1.0e-46</TD> <!-- underflow to 0 -->
+  <TD>42 32, 12 32</TD>
+  <TD>0</TD>
+  <TD>0 1 0 0 1 1</TD>
+  <TD>0 0 0 0 0</TD>
+  <TD>0 1 0 0 1 0 1 0 1 0 1 0</TD>
+  <TD>0 0</TD>
+  <TD>0 0</TD>
+  <TD>0 0 0 0</TD>
+  <TD>0 -1 -1 -1</TD>
+  <TD>FaLsE</TD>
+  <TD>true true falSE TRUE</TD>
+  <TD>-9</TD>
+  <TD>0 1 2 3</TD>
+  <TD>1.0</TD>
+  <TD>1.0</TD>
+  <TD>0 1 Inf -Inf NaN 0 -1</TD>
+  <TD/>
+</TR>
+<TR>
+  <TD>XXXX </TD>
+  <TD> XXXX </TD> <!-- Shouldn't output extra 0 bytes even though field is wider than string -->
+  <TD> XXXX </TD>
+  <TD>0123456789A</TD>
+  <TD/>
+  <TD>-23</TD> <!-- negative, should wrap around to positive -->
+  <TD>-4096</TD> <!-- negative, perfectly valid -->
+  <TD>-268435456</TD> <!-- negative, perfectly valid -->
+  <TD>-1152921504606846976</TD>  <!-- negative, perfectly valid -->
+  <TD>1.0E309</TD>
+  <TD>1.0E45</TD>
+  <TD>12 34 56 78 87 65 43 21</TD>
+  <TD>1</TD>
+  <TD>1 1 1 0 0 0</TD>
+  <TD>1 0 1 0 1</TD>
+  <TD>1 1 1 1 1 1</TD>
+  <TD>0 -1</TD>
+  <TD>0 -1</TD>
+  <TD>0 0 0 0</TD>
+  <TD>0 0 0 0</TD>
+  <TD>true</TD>
+  <TD>true True ? true</TD>
+  <TD>2</TD>
+  <TD>-9 0 -9 1</TD>
+  <TD>1e34</TD>
+  <TD>1e34</TD>
+  <TD/>
+  <TD/>
+</TR>
+<TR>
+  <TD/>
+  <TD/>
+  <TD/>
+  <TD/>
+  <TD/>
+  <TD>0xff</TD> <!-- hex -->
+  <TD>0xffff</TD> <!-- hex - negative value -->
+  <TD>0xfffffff</TD>
+  <TD>0xfffffffffffffff</TD>
+  <TD>NaN</TD>
+  <TD>+Inf</TD>
+  <TD>NaN, 23</TD>
+  <TD>0</TD>
+  <TD/>
+  <TD/>
+  <TD/>
+  <TD/>
+  <TD>NaN Inf</TD>
+  <TD/>
+  <TD>0 0 0 0</TD>
+  <TD>false</TD>
+  <TD/>
+  <TD/>
+  <TD>0 -9 1 -9</TD>
+  <TD/>
+  <TD/>
+  <TD/>
+  <TD/>
+</TR>
+<TR>
+  <TD/>
+  <TD/>
+  <TD/>
+  <TD/>
+  <TD/>
+  <TD>0x100</TD> <!-- hex, overflow -->
+  <TD>0x10000</TD> <!-- hex, overflow -->
+  <TD/>
+  <TD/>
+  <TD>-Inf</TD>
+  <TD/>
+  <TD>31, -1</TD>
+  <TD/>
+  <TD/>
+  <TD/>
+  <TD/>
+  <TD/>
+  <TD/>
+  <TD/>
+  <TD>0 0 0 0</TD>
+  <TD/>
+  <TD/>
+  <TD>-9</TD>
+  <TD/>
+  <TD/>
+  <TD/>
+  <TD/>
+  <TD/>
+</TR>
+</TABLEDATA>
+</DATA>
+</TABLE>
+<RESOURCE>
+ <TABLE ref="main_table">
+   <DESCRIPTION>
+     This is a referenced table
+   </DESCRIPTION>
+   <DATA>
+<TABLEDATA>
+<TR>
+  <TD>String & test</TD>
+  <TD>Fixed string long test</TD> <!-- Should truncate -->
+  <TD>Ceçi n'est pas un pipe</TD> <!-- French, n'est-ce pas? -->
+  <TD>Ceçi n'est pas un pipe</TD>
+  <TD>ab cd</TD>
+  <TD>128</TD>
+  <TD>4096</TD>
+  <TD>268435456</TD>
+  <TD>922337203685477</TD>
+  <TD>1.0</TD>
+  <TD encoding="base64">P4AAAA==</TD>
+  <TD>   </TD>
+  <TD>1</TD>
+  <TD>1 0 1 1 0 1</TD>
+  <TD>1 1 1</TD>
+  <TD/>
+  <TD/>
+  <TD/>
+  <TD/>
+  <TD>0 0 0 0</TD>
+  <TD>True</TD>
+  <TD>True True True True</TD>
+  <TD>0</TD>
+  <TD/>
+  <TD>1.333333333333333333333333333333333</TD>
+  <TD>1.333333333333333333333333333333333</TD>
+  <TD/>
+  <TD>1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0</TD>
+</TR>
+</TABLEDATA>
+</DATA>
+</TABLE>
+<TABLE ref="main_table" ID="last_table">
+<DATA>
+<TABLEDATA/> <!-- Add an empty table because it's a useful thing to test -->
+</DATA>
+</TABLE>
+</RESOURCE>
+</RESOURCE>
+</VOTABLE>
diff --git a/astropy/io/vo/tests/data/tb.fits b/astropy/io/votable/tests/data/tb.fits
similarity index 100%
rename from astropy/io/vo/tests/data/tb.fits
rename to astropy/io/votable/tests/data/tb.fits
diff --git a/astropy/io/vo/tests/data/too_many_columns.xml.gz b/astropy/io/votable/tests/data/too_many_columns.xml.gz
similarity index 100%
rename from astropy/io/vo/tests/data/too_many_columns.xml.gz
rename to astropy/io/votable/tests/data/too_many_columns.xml.gz
diff --git a/astropy/io/votable/tests/data/validation.txt b/astropy/io/votable/tests/data/validation.txt
new file mode 100644
index 0000000..d2880d8
--- /dev/null
+++ b/astropy/io/votable/tests/data/validation.txt
@@ -0,0 +1,202 @@
+Validation report for regression.xml
+
+11: W01: Array uses commas rather than whitespace
+<PARAM datatype="float" name="wrong_arraysize" value="0.000000,0.0000…
+^
+
+11: E02: Incorrect number of elements in array. Expected multiple of
+  0, got 2
+<PARAM datatype="float" name="wrong_arraysize" value="0.000000,0.0000…
+^
+
+12: W01: Array uses commas rather than whitespace
+<PARAM datatype="float" name="INPUT" value="0.000000,0.000000" arrays…
+^
+
+20: W01: Array uses commas rather than whitespace
+<PARAM ID="awesome" datatype="float" name="INPUT" value="0.000000,0.0…
+^
+
+21: W50: Invalid unit string 'foo'
+<PARAM ID="empty_value" name="empty_value" arraysize="*" datatype="ch…
+^
+
+22: W11: The gref attribute on LINK is deprecated in VOTable 1.1
+<LINK href="http://www.foo.com/" gref="DECPRECATED">
+^
+
+23: W10: Unknown tag 'DESCRIPTION'.  Ignoring
+  <DESCRIPTION>Really, this link is totally bogus.</DESCRIPTION>
+  ^
+
+32: W01: Array uses commas rather than whitespace
+<PARAM datatype="float" name="INPUT2" value="0.000000,0.000000" array…
+^
+
+35: W09: ID attribute not capitalized
+<FIELD id="string_test" name="string test" datatype="char" arraysize=…
+^
+
+38: W13: 'unicodeString' is not a valid VOTable datatype, should be
+  'unicodeChar'
+<FIELD ID="fixed_unicode_test" name="unicode test" datatype="unicodeS…
+^
+
+40: W13: 'string' is not a valid VOTable datatype, should be 'char'
+<FIELD ID="string_array_test" name="string array test" datatype="stri…
+^
+
+47: W48: Unknown attribute 'value' on OPTION
+    <OPTION name="bogus" value="whatever"/>
+    ^
+
+49: W10: Unknown tag 'IGNORE_ME'.  Ignoring
+  <IGNORE_ME/>
+  ^
+
+89: W17: GROUP element contains more than one DESCRIPTION element
+    This should warn of a second description.
+^
+
+96: W01: Array uses commas rather than whitespace
+  <PARAM datatype="float" name="INPUT3" value="0.000000,0.000000" arr…
+  ^
+
+36: W32: Duplicate ID 'string_test' renamed to 'string_test_2' to
+  ensure uniqueness
+<FIELD ID="string_test" name="fixed string test" datatype="char" arra…
+^
+
+104: W46: char value is too long for specified length of 10
+  <TD>Fixed string long test</TD> <!-- Should truncate -->
+      ^
+
+106: W46: unicodeChar value is too long for specified length of 10
+  <TD>Ceçi n'est pas un pipe</TD>
+      ^
+
+107: W46: char value is too long for specified length of 4
+  <TD>ab cd</TD>
+      ^
+
+126: E02: Incorrect number of elements in array. Expected multiple of
+  4, got 1
+  <TD/>
+  ^
+
+126: W49: Empty cell illegal for integer fields.
+  <TD/>
+  ^
+
+134: W46: char value is too long for specified length of 10
+  <TD>0123456789A</TD>
+      ^
+
+137: W46: char value is too long for specified length of 4
+  <TD>0123456789A</TD>
+      ^
+
+141: W49: Empty cell illegal for integer fields.
+  <TD></TD>
+  ^
+
+144: W01: Array uses commas rather than whitespace
+  <TD>42 32, 12 32</TD>
+      ^
+
+160: E02: Incorrect number of elements in array. Expected multiple of
+  16, got 0
+  <TD/>
+  ^
+
+160: W49: Empty cell illegal for integer fields.
+  <TD/>
+  ^
+
+160: W49: Empty cell illegal for integer fields.
+  <TD/>
+  ^
+
+160: W49: Empty cell illegal for integer fields.
+  <TD/>
+  ^
+
+160: W49: Empty cell illegal for integer fields.
+  <TD/>
+  ^
+
+160: W49: Empty cell illegal for integer fields.
+  <TD/>
+  ^
+
+160: W49: Empty cell illegal for integer fields.
+  <TD/>
+  ^
+
+160: W49: Empty cell illegal for integer fields.
+  <TD/>
+  ^
+
+160: W49: Empty cell illegal for integer fields. (suppressing further
+  warnings of this type...)
+  <TD/>
+  ^
+
+166: W46: unicodeChar value is too long for specified length of 10
+  <TD>0123456789A</TD>
+      ^
+
+190: E02: Incorrect number of elements in array. Expected multiple of
+  16, got 0
+  <TD/>
+  ^
+
+204: W01: Array uses commas rather than whitespace
+  <TD>NaN, 23</TD>
+      ^
+
+206: E02: Incorrect number of elements in array. Expected multiple of
+  6, got 0
+  <TD/>
+  ^
+
+214: E02: Incorrect number of elements in array. Expected multiple of
+  4, got 1
+  <TD/>
+  ^
+
+220: E02: Incorrect number of elements in array. Expected multiple of
+  16, got 0
+  <TD/>
+  ^
+
+234: W01: Array uses commas rather than whitespace
+  <TD>31, -1</TD>
+      ^
+
+236: E02: Incorrect number of elements in array. Expected multiple of
+  6, got 0
+  <TD/>
+  ^
+
+244: E02: Incorrect number of elements in array. Expected multiple of
+  4, got 1
+  <TD/>
+  ^
+
+246: E02: Incorrect number of elements in array. Expected multiple of
+  4, got 1 (suppressing further warnings of this type...)
+  <TD/>
+  ^
+
+264: W46: char value is too long for specified length of 10
+  <TD>Fixed string long test</TD> <!-- Should truncate -->
+      ^
+
+266: W46: unicodeChar value is too long for specified length of 10
+  <TD>Ceçi n'est pas un pipe</TD>
+      ^
+
+267: W46: char value is too long for specified length of 4
+  <TD>ab cd</TD>
+      ^
diff --git a/astropy/io/vo/tests/exception_test.py b/astropy/io/votable/tests/exception_test.py
similarity index 100%
rename from astropy/io/vo/tests/exception_test.py
rename to astropy/io/votable/tests/exception_test.py
diff --git a/astropy/io/votable/tests/table_test.py b/astropy/io/votable/tests/table_test.py
new file mode 100644
index 0000000..01d24b5
--- /dev/null
+++ b/astropy/io/votable/tests/table_test.py
@@ -0,0 +1,109 @@
+"""
+Test the conversion to/from astropy.table
+"""
+
+import os
+import shutil
+import tempfile
+from distutils import version
+
+import numpy as np
+from ....tests.helper import pytest
+
+from ....utils.data import get_pkg_data_filename, get_pkg_data_fileobj
+from ..table import parse, writeto
+from .. import tree
+
+numpy_lt_1p5 = version.LooseVersion(np.__version__) < version.LooseVersion('1.5')
+
+TMP_DIR = None
+def setup_module():
+    global TMP_DIR
+    TMP_DIR = tempfile.mkdtemp()
+
+
+def teardown_module():
+    shutil.rmtree(TMP_DIR)
+
+
+ at pytest.mark.xfail('numpy_lt_1p5')
+def test_table():
+    # Read the VOTABLE
+    votable = parse(
+        get_pkg_data_filename('data/regression.xml'),
+        pedantic=False)
+    table = votable.get_first_table()
+    astropy_table = table.to_table()
+
+    for name in table.array.dtype.names:
+        assert np.all(astropy_table.mask[name] == table.array.mask[name])
+
+    votable2 = tree.VOTableFile.from_table(astropy_table)
+    t = votable2.get_first_table()
+
+    field_types = [
+        ('string_test', {'datatype': 'char', 'arraysize': '*'}),
+        ('string_test_2', {'datatype': 'char', 'arraysize': '10'}),
+        ('unicode_test', {'datatype': 'unicodeChar', 'arraysize': '*'}),
+        ('fixed_unicode_test', {'datatype': 'unicodeChar', 'arraysize': '10'}),
+        ('string_array_test', {'datatype': 'char', 'arraysize': '4'}),
+        ('unsignedByte', {'datatype': 'unsignedByte'}),
+        ('short', {'datatype': 'short'}),
+        ('int', {'datatype': 'int'}),
+        ('long', {'datatype': 'long'}),
+        ('double', {'datatype': 'double'}),
+        ('float', {'datatype': 'float'}),
+        ('array', {'datatype': 'long', 'arraysize': '2*'}),
+        ('bit', {'datatype': 'bit'}),
+        ('bitarray', {'datatype': 'bit', 'arraysize': '3x2'}),
+        ('bitvararray', {'datatype': 'bit', 'arraysize': '*'}),
+        ('bitvararray2', {'datatype': 'bit', 'arraysize': '3x2*'}),
+        ('floatComplex', {'datatype': 'floatComplex'}),
+        ('doubleComplex', {'datatype': 'doubleComplex'}),
+        ('doubleComplexArray', {'datatype': 'doubleComplex', 'arraysize': '*'}),
+        ('doubleComplexArrayFixed', {'datatype': 'doubleComplex', 'arraysize': '2'}),
+        ('boolean', {'datatype': 'bit'}),
+        ('booleanArray', {'datatype': 'bit', 'arraysize': '4'}),
+        ('nulls', {'datatype': 'int'}),
+        ('nulls_array', {'datatype': 'int', 'arraysize': '2x2'}),
+        ('precision1', {'datatype': 'double'}),
+        ('precision2', {'datatype': 'double'}),
+        ('doublearray', {'datatype': 'double', 'arraysize': '*'}),
+        ('bitarray2', {'datatype': 'bit', 'arraysize': '16'})]
+
+    for field, type in zip(t.fields, field_types):
+        name, d = type
+        assert field.ID == name
+        assert field.datatype == d['datatype']
+        if 'arraysize' in d:
+            assert field.arraysize == d['arraysize']
+
+    writeto(votable2, os.path.join(TMP_DIR, "through_table.xml"))
+
+
+ at pytest.mark.xfail('numpy_lt_1p5')
+def test_read_through_table_interface():
+    from ....table import Table
+
+    with get_pkg_data_fileobj('data/regression.xml', encoding='binary') as fd:
+        t = Table.read(fd, format='votable', table_id='main_table')
+
+    assert len(t) == 5
+
+    fn = os.path.join(TMP_DIR, "table_interface.xml")
+    t.write(fn, table_id='FOO', format='votable')
+
+    with open(fn, 'rb') as fd:
+        t2 = Table.read(fd, format='votable', table_id='FOO')
+
+    assert len(t2) == 5
+
+
+ at pytest.mark.xfail('numpy_lt_1p5')
+def test_read_through_table_interface2():
+    from ....table import Table
+
+    with get_pkg_data_fileobj('data/regression.xml', encoding='binary') as fd:
+        t = Table.read(fd, format='votable', table_id='last_table')
+
+    assert len(t) == 0
diff --git a/astropy/io/votable/tests/tree_test.py b/astropy/io/votable/tests/tree_test.py
new file mode 100644
index 0000000..dddb441
--- /dev/null
+++ b/astropy/io/votable/tests/tree_test.py
@@ -0,0 +1,17 @@
+# LOCAL
+from .. import exceptions
+from .. import tree
+from ....tests.helper import raises
+
+
+ at raises(exceptions.W07)
+def test_check_astroyear_fail():
+    config = {'pedantic': True}
+    field = tree.Field(None, name='astroyear')
+    tree.check_astroyear('X2100', field, config)
+
+
+ at raises(exceptions.W08)
+def test_string_fail():
+    config = {'pedantic': True}
+    tree.check_string(42, 'foo', config)
diff --git a/astropy/io/vo/tests/ucd_test.py b/astropy/io/votable/tests/ucd_test.py
similarity index 100%
rename from astropy/io/vo/tests/ucd_test.py
rename to astropy/io/votable/tests/ucd_test.py
diff --git a/astropy/io/vo/tests/util_test.py b/astropy/io/votable/tests/util_test.py
similarity index 100%
rename from astropy/io/vo/tests/util_test.py
rename to astropy/io/votable/tests/util_test.py
diff --git a/astropy/io/votable/tests/vo_test.py b/astropy/io/votable/tests/vo_test.py
new file mode 100644
index 0000000..e25c8ae
--- /dev/null
+++ b/astropy/io/votable/tests/vo_test.py
@@ -0,0 +1,814 @@
+"""
+This is a set of regression tests for vo.
+"""
+
+from __future__ import absolute_import, print_function
+
+# STDLIB
+import difflib
+from distutils import version
+import io
+import os
+import shutil
+import sys
+import tempfile
+import warnings
+
+# THIRD-PARTY
+from numpy.testing import assert_array_equal
+import numpy as np
+
+# LOCAL
+from ..table import parse, parse_single_table, validate
+from .. import tree
+from ..util import IS_PY3K
+from ..exceptions import VOTableSpecError, VOWarning
+from ..xmlutil import validate_schema
+from ....utils.data import get_pkg_data_filename, get_pkg_data_fileobj, get_pkg_data_filenames
+from ....tests.helper import pytest, raises
+from ....utils.compat import gzip
+
+numpy_has_complex_bug = (
+    version.LooseVersion(np.__version__) < version.LooseVersion('1.5')
+    )
+
+# Determine the kind of float formatting in this build of Python
+if hasattr(sys, 'float_repr_style'):
+    legacy_float_repr = (sys.float_repr_style == 'legacy')
+else:
+    legacy_float_repr = sys.platform.startswith('win')
+
+join = os.path.join
+
+
+# Update this to use py.test's tmpdir functionality
+def setup_module():
+    global TMP_DIR
+    TMP_DIR = tempfile.mkdtemp()
+
+
+def teardown_module():
+    shutil.rmtree(TMP_DIR)
+
+
+def assert_validate_schema(filename):
+    if sys.platform.startswith('win'):
+        return
+
+    try:
+        rc, stdout, stderr = validate_schema(filename, '1.1')
+    except OSError:
+        # If xmllint is not installed, we want the test to pass anyway
+        return
+    assert rc == 0, 'File did not validate against VOTable schema'
+
+
+def test_parse_single_table():
+    table = parse_single_table(
+        get_pkg_data_filename('data/regression.xml'),
+        pedantic=False)
+    assert isinstance(table, tree.Table)
+    assert len(table.array) == 5
+
+
+def test_parse_single_table2():
+    table2 = parse_single_table(
+        get_pkg_data_filename('data/regression.xml'),
+        table_number=1,
+        pedantic=False)
+    assert isinstance(table2, tree.Table)
+    assert len(table2.array) == 1
+    assert len(table2.array.dtype.names) == 28
+
+
+ at raises(IndexError)
+def test_parse_single_table3():
+    table2 = parse_single_table(
+        get_pkg_data_filename('data/regression.xml'),
+        table_number=3, pedantic=False)
+
+
+def _test_regression(_python_based=False):
+    # Read the VOTABLE
+    votable = parse(
+        get_pkg_data_filename('data/regression.xml'),
+        pedantic=False,
+        _debug_python_based_parser=_python_based)
+    table = votable.get_first_table()
+
+    assert table.array.dtype == [
+        (('string test', 'string_test'), '|O8'),
+        (('fixed string test', 'string_test_2'), '|S10'),
+        ('unicode_test', '|O8'),
+        (('unicode test', 'fixed_unicode_test'), '<U10'),
+        (('string array test', 'string_array_test'), '|S4'),
+        ('unsignedByte', '|u1'),
+        ('short', '<i2'),
+        ('int', '<i4'),
+        ('long', '<i8'),
+        ('double', '<f8'),
+        ('float', '<f4'),
+        ('array', '|O8'),
+        ('bit', '|b1'),
+        ('bitarray', '|b1', (3, 2)),
+        ('bitvararray', '|O8'),
+        ('bitvararray2', '|O8'),
+        ('floatComplex', '<c8'),
+        ('doubleComplex', '<c16'),
+        ('doubleComplexArray', '|O8'),
+        ('doubleComplexArrayFixed', '<c16', (2,)),
+        ('boolean', '|b1'),
+        ('booleanArray', '|b1', (4,)),
+        ('nulls', '<i4'),
+        ('nulls_array', '<i4', (2, 2)),
+        ('precision1', '<f8'),
+        ('precision2', '<f8'),
+        ('doublearray', '|O8'),
+        ('bitarray2', '|b1', (16,))
+        ]
+
+    votable.to_xml(join(TMP_DIR, "regression.tabledata.xml"),
+                   _debug_python_based_parser=_python_based)
+    assert_validate_schema(join(TMP_DIR, "regression.tabledata.xml"))
+    votable.get_first_table().format = 'binary'
+    # Also try passing a file handle
+    with open(join(TMP_DIR, "regression.binary.xml"), "wb") as fd:
+        votable.to_xml(fd, _debug_python_based_parser=_python_based)
+    assert_validate_schema(join(TMP_DIR, "regression.binary.xml"))
+    # Also try passing a file handle
+    with open(join(TMP_DIR, "regression.binary.xml"), "rb") as fd:
+        votable2 = parse(fd, pedantic=False,
+                         _debug_python_based_parser=_python_based)
+    votable2.get_first_table().format = 'tabledata'
+    votable2.to_xml(join(TMP_DIR, "regression.bin.tabledata.xml"),
+                    _astropy_version="testing",
+                    _debug_python_based_parser=_python_based)
+    assert_validate_schema(join(TMP_DIR, "regression.bin.tabledata.xml"))
+
+    with io.open(
+        get_pkg_data_filename('data/regression.bin.tabledata.truth.xml'),
+        'rt', encoding='utf-8') as fd:
+        truth = fd.readlines()
+    with io.open(
+        join(TMP_DIR, "regression.bin.tabledata.xml"),
+        'rt', encoding='utf-8') as fd:
+        output = fd.readlines()
+
+    # If the lines happen to be different, print a diff
+    # This is convenient for debugging
+    for line in difflib.unified_diff(truth, output):
+        sys.stdout.write(
+            line.
+            encode('unicode_escape').
+            replace('\\n', '\n'))
+
+    assert truth == output
+
+    # Test implicit gzip saving
+    votable2.to_xml(
+        join(TMP_DIR, "regression.bin.tabledata.xml.gz"),
+        _astropy_version="testing",
+        _debug_python_based_parser=_python_based)
+    with gzip.GzipFile(
+        join(TMP_DIR, "regression.bin.tabledata.xml.gz"), 'rb') as gzfd:
+        output = gzfd.readlines()
+    output = [x.decode('utf-8').rstrip() for x in output]
+    truth = [x.rstrip() for x in truth]
+
+    assert truth == output
+
+
+ at pytest.mark.xfail('legacy_float_repr')
+def test_regression():
+    _test_regression(False)
+
+
+ at pytest.mark.xfail('legacy_float_repr')
+def test_regression_python_based_parser():
+    _test_regression(True)
+
+
+class TestFixups:
+    def setup_class(self):
+        self.table = parse(
+            get_pkg_data_filename('data/regression.xml'),
+            pedantic=False).get_first_table()
+        self.array = self.table.array
+        self.mask = self.table.array.mask
+
+    def test_implicit_id(self):
+        assert_array_equal(self.array['string_test_2'],
+                           self.array['fixed string test'])
+
+
+class TestReferences:
+    def setup_class(self):
+        self.votable = parse(
+            get_pkg_data_filename('data/regression.xml'),
+            pedantic=False)
+        self.table = self.votable.get_first_table()
+        self.array = self.table.array
+        self.mask = self.table.array.mask
+
+    def test_fieldref(self):
+        fieldref = self.table.groups[1].entries[0]
+        assert isinstance(fieldref, tree.FieldRef)
+        assert fieldref.get_ref().name == 'boolean'
+        assert fieldref.get_ref().datatype == 'boolean'
+
+    def test_paramref(self):
+        paramref = self.table.groups[0].entries[0]
+        assert isinstance(paramref, tree.ParamRef)
+        assert paramref.get_ref().name == 'INPUT'
+        assert paramref.get_ref().datatype == 'float'
+
+    def test_iter_fields_and_params_on_a_group(self):
+        assert len(list(self.table.groups[1].iter_fields_and_params())) == 2
+
+    def test_iter_groups_on_a_group(self):
+        assert len(list(self.table.groups[1].iter_groups())) == 1
+
+    def test_iter_groups(self):
+        # Because of the ref'd table, there are more logical groups
+        # than actually exist in the file
+        assert len(list(self.votable.iter_groups())) == 9
+
+    def test_ref_table(self):
+        tables = list(self.votable.iter_tables())
+        for x, y in zip(tables[0].array.data[0], tables[1].array.data[0]):
+            assert_array_equal(x, y)
+
+    def test_iter_coosys(self):
+        assert len(list(self.votable.iter_coosys())) == 1
+
+
+def test_select_columns_by_index():
+    columns = [0, 5, 13]
+    table = parse(
+        get_pkg_data_filename('data/regression.xml'),
+        pedantic=False, columns=columns).get_first_table()
+    array = table.array
+    mask = table.array.mask
+    assert array['string_test'][0] == b"String & test"
+    columns = ['string_test', 'unsignedByte', 'bitarray']
+    for c in columns:
+        assert not np.all(mask[c])
+    assert np.all(mask['unicode_test'])
+
+
+def test_select_columns_by_name():
+    columns = ['string_test', 'unsignedByte', 'bitarray']
+    table = parse(
+        get_pkg_data_filename('data/regression.xml'),
+        pedantic=False, columns=columns).get_first_table()
+    array = table.array
+    mask = table.array.mask
+    assert array['string_test'][0] == b"String & test"
+    for c in columns:
+        assert not np.all(mask[c])
+    assert np.all(mask['unicode_test'])
+
+
+class TestParse:
+    def setup_class(self):
+        self.table = parse(
+            get_pkg_data_filename('data/regression.xml'),
+            pedantic=False).get_first_table()
+        self.array = self.table.array
+        self.mask = self.table.array.mask
+
+    def test_string_test(self):
+        assert issubclass(self.array['string_test'].dtype.type,
+                          np.object_)
+        assert_array_equal(
+            self.array['string_test'],
+            [b'String & test', b'String & test', b'XXXX',
+             b'', b''])
+
+    def test_fixed_string_test(self):
+        assert issubclass(self.array['string_test_2'].dtype.type,
+                          np.string_)
+        assert_array_equal(
+            self.array['string_test_2'],
+            [b'Fixed stri', b'0123456789', b'XXXX', b'', b''])
+
+    def test_unicode_test(self):
+        assert issubclass(self.array['unicode_test'].dtype.type,
+                          np.object_)
+        assert_array_equal(self.array['unicode_test'],
+                           [u"Ce\xe7i n'est pas un pipe",
+                            u'\u0bb5\u0ba3\u0b95\u0bcd\u0b95\u0bae\u0bcd',
+                            u'XXXX', u'', u''])
+
+    def test_fixed_unicode_test(self):
+        assert issubclass(self.array['fixed_unicode_test'].dtype.type,
+                          np.unicode_)
+        assert_array_equal(self.array['fixed_unicode_test'],
+                           [u"Ce\xe7i n'est",
+                            u'\u0bb5\u0ba3\u0b95\u0bcd\u0b95\u0bae\u0bcd',
+                            u'0123456789', u'', u''])
+
+    def test_unsignedByte(self):
+        assert issubclass(self.array['unsignedByte'].dtype.type,
+                          np.uint8)
+        assert_array_equal(self.array['unsignedByte'],
+                           [128, 0, 233, 255, 0])
+        assert not np.any(self.mask['unsignedByte'])
+
+    def test_short(self):
+        assert issubclass(self.array['short'].dtype.type,
+                          np.int16)
+        assert_array_equal(self.array['short'],
+                           [4096, 0, -4096, -1, 0])
+        assert not np.any(self.mask['short'])
+
+    def test_int(self):
+        assert issubclass(self.array['int'].dtype.type,
+                          np.int32)
+        assert_array_equal(
+            self.array['int'],
+            [268435456, 2147483647, -268435456, 268435455, 123456789])
+        assert_array_equal(self.mask['int'],
+                           [False, False, False, False, True])
+
+    def test_long(self):
+        assert issubclass(self.array['long'].dtype.type,
+                          np.int64)
+        assert_array_equal(
+            self.array['long'],
+            [922337203685477, 123456789, -1152921504606846976,
+             1152921504606846975, 123456789])
+        assert_array_equal(self.mask['long'],
+                           [False, True, False, False, True])
+
+    def test_double(self):
+        assert issubclass(self.array['double'].dtype.type,
+                          np.float64)
+        assert_array_equal(self.array['double'],
+                           [1.0, 0.0, np.inf, np.nan, -np.inf])
+        assert_array_equal(self.mask['double'],
+                           [False, False, False, True, False])
+
+    def test_float(self):
+        assert issubclass(self.array['float'].dtype.type,
+                          np.float32)
+        assert_array_equal(self.array['float'],
+                           [1.0, 0.0, np.inf, np.inf, np.nan])
+        assert_array_equal(self.mask['float'],
+                           [False, False, False, False, True])
+
+    def test_array(self):
+        assert issubclass(self.array['array'].dtype.type,
+                          np.object_)
+        match = [[],
+                 [[42, 32], [12, 32]],
+                 [[12, 34], [56, 78], [87, 65], [43, 21]],
+                 [[-1, 23]],
+                 [[31, -1]]]
+        for a, b in zip(self.array['array'], match):
+            # assert issubclass(a.dtype.type, np.int64)
+            # assert a.shape[1] == 2
+            for a0, b0 in zip(a, b):
+                assert issubclass(a0.dtype.type, np.int64)
+                assert_array_equal(a0, b0)
+        assert self.array.data['array'][3].mask[0][0]
+        assert self.array.data['array'][4].mask[0][1]
+
+    def test_bit(self):
+        assert issubclass(self.array['bit'].dtype.type,
+                          np.bool_)
+        assert_array_equal(self.array['bit'],
+                           [True, False, True, False, False])
+
+    def test_bit_mask(self):
+        assert_array_equal(self.mask['bit'],
+                           [False, False, False, False, True])
+
+    def test_bitarray(self):
+        assert issubclass(self.array['bitarray'].dtype.type,
+                          np.bool_)
+        self.array['bitarray'].shape == (5, 3, 2)
+        assert_array_equal(self.array['bitarray'],
+                           [[[ True, False],
+                             [ True,  True],
+                             [False,  True]],
+
+                            [[False,  True],
+                             [False, False],
+                             [ True,  True]],
+
+                            [[ True,  True],
+                             [ True, False],
+                             [False, False]],
+
+                            [[False, False],
+                             [False, False],
+                             [False, False]],
+
+                            [[False, False],
+                             [False, False],
+                             [False, False]]])
+
+    def test_bitarray_mask(self):
+        assert_array_equal(self.mask['bitarray'],
+                           [[[False, False],
+                             [False, False],
+                             [False, False]],
+
+                            [[False, False],
+                             [False, False],
+                             [False, False]],
+
+                            [[False, False],
+                             [False, False],
+                             [False, False]],
+
+                            [[ True,  True],
+                             [ True,  True],
+                             [ True,  True]],
+
+                            [[ True,  True],
+                             [ True,  True],
+                             [ True,  True]]])
+
+    def test_bitvararray(self):
+        assert issubclass(self.array['bitvararray'].dtype.type,
+                          np.object_)
+        match = [[ True,  True,  True],
+                 [False, False, False, False, False],
+                 [ True, False,  True, False,  True],
+                 [], []]
+        for a, b in zip(self.array['bitvararray'], match):
+            assert_array_equal(a, b)
+        match_mask = [[False, False, False],
+                      [False, False, False, False, False],
+                      [False, False, False, False, False],
+                      False, False]
+        for a, b in zip(self.array['bitvararray'], match_mask):
+            assert_array_equal(a.mask, b)
+
+    def test_bitvararray2(self):
+        assert issubclass(self.array['bitvararray2'].dtype.type,
+                          np.object_)
+        match = [[],
+
+                 [[[False,  True],
+                   [False, False],
+                   [ True, False]],
+                  [[ True, False],
+                   [ True, False],
+                   [ True, False]]],
+
+                 [[[ True,  True],
+                   [ True,  True],
+                   [ True,  True]]],
+
+                 [],
+
+                 []]
+        for a, b in zip(self.array['bitvararray2'], match):
+            for a0, b0 in zip(a, b):
+                assert a0.shape == (3, 2)
+                assert issubclass(a0.dtype.type, np.bool_)
+                assert_array_equal(a0, b0)
+
+    @pytest.mark.xfail('numpy_has_complex_bug')
+    def test_floatComplex(self):
+        assert issubclass(self.array['floatComplex'].dtype.type,
+                          np.complex64)
+        assert_array_equal(self.array['floatComplex'],
+                           [np.nan+0j, 0+0j, 0+-1j, np.nan+0j, np.nan+0j])
+        assert_array_equal(self.mask['floatComplex'],
+                           [True, False, False, True, True])
+
+    @pytest.mark.xfail('numpy_has_complex_bug')
+    def test_doubleComplex(self):
+        assert issubclass(self.array['doubleComplex'].dtype.type,
+                          np.complex128)
+        assert_array_equal(
+            self.array['doubleComplex'],
+            [np.nan+0j, 0+0j, 0+-1j, np.nan+(np.inf*1j), np.nan+0j])
+        assert_array_equal(self.mask['doubleComplex'],
+                           [True, False, False, True, True])
+
+    @pytest.mark.xfail('numpy_has_complex_bug')
+    def test_doubleComplexArray(self):
+        assert issubclass(self.array['doubleComplexArray'].dtype.type,
+                          np.object_)
+        assert ([len(x) for x in self.array['doubleComplexArray']] ==
+                [0, 2, 2, 0, 0])
+
+    def test_boolean(self):
+        assert issubclass(self.array['boolean'].dtype.type,
+                          np.bool_)
+        assert_array_equal(self.array['boolean'],
+                           [True, False, True, False, False])
+
+    def test_boolean_mask(self):
+        assert_array_equal(self.mask['boolean'],
+                           [False, False, False, False, True])
+
+    def test_boolean_array(self):
+        assert issubclass(self.array['booleanArray'].dtype.type,
+                          np.bool_)
+        assert_array_equal(self.array['booleanArray'],
+                           [[ True,  True,  True,  True],
+                            [ True,  True, False,  True],
+                            [ True,  True, False,  True],
+                            [False, False, False, False],
+                            [False, False, False, False]])
+
+    def test_boolean_array_mask(self):
+        assert_array_equal(self.mask['booleanArray'],
+                           [[False, False, False, False],
+                            [False, False, False, False],
+                            [False, False,  True, False],
+                            [ True,  True,  True,  True],
+                            [ True,  True,  True,  True]])
+
+    def test_nulls(self):
+        assert_array_equal(self.array['nulls'],
+                           [0, -9, 2, -9, -9])
+        assert_array_equal(self.mask['nulls'],
+                           [False, True, False, True, True])
+
+    def test_nulls_array(self):
+        assert_array_equal(self.array['nulls_array'],
+                           [[[-9, -9], [-9, -9]],
+                            [[0, 1], [2, 3]],
+                            [[-9, 0], [-9, 1]],
+                            [[0, -9], [1, -9]],
+                            [[-9, -9], [-9, -9]]])
+        assert_array_equal(self.mask['nulls_array'],
+                           [[[ True,  True],
+                             [ True,  True]],
+
+                            [[False, False],
+                             [False, False]],
+
+                            [[ True, False],
+                             [ True, False]],
+
+                            [[False,  True],
+                             [False,  True]],
+
+                            [[ True,  True],
+                             [ True,  True]]])
+
+    def test_double_array(self):
+        assert issubclass(self.array['doublearray'].dtype.type,
+                          np.object_)
+        assert len(self.array['doublearray'][0]) == 0
+        assert_array_equal(self.array['doublearray'][1],
+                           [0, 1, np.inf, -np.inf, np.nan, 0, -1])
+        assert_array_equal(self.array.data['doublearray'][1].mask,
+                           [False, False, False, False, False, False, True])
+
+    def test_bit_array2(self):
+        assert_array_equal(self.array['bitarray2'][0],
+                           [True, True, True, True,
+                            False, False, False, False,
+                            True, True, True, True,
+                            False, False, False, False])
+
+    def test_bit_array2_mask(self):
+        assert not np.any(self.mask['bitarray2'][0])
+        assert np.all(self.mask['bitarray2'][1:])
+
+
+class TestThroughTableData(TestParse):
+    def setup_class(self):
+        votable = parse(
+            get_pkg_data_filename('data/regression.xml'),
+            pedantic=False)
+        votable.to_xml(join(TMP_DIR, "test_through_tabledata.xml"))
+        self.table = parse(join(TMP_DIR, "test_through_tabledata.xml"),
+                           pedantic=False).get_first_table()
+        self.array = self.table.array
+        self.mask = self.table.array.mask
+
+    def test_schema(self):
+        assert_validate_schema(join(TMP_DIR, "test_through_tabledata.xml"))
+
+
+class TestThroughBinary(TestParse):
+    def setup_class(self):
+        votable = parse(
+            get_pkg_data_filename('data/regression.xml'),
+            pedantic=False)
+        votable.get_first_table().format = 'binary'
+        votable.to_xml(join(TMP_DIR, "test_through_binary.xml"))
+        self.table = parse(join(TMP_DIR, "test_through_binary.xml"),
+                           pedantic=False).get_first_table()
+        self.array = self.table.array
+        self.mask = self.table.array.mask
+
+    # Masked values in bit fields don't roundtrip through the binary
+    # representation -- that's not a bug, just a limitation, so
+    # override the mask array checks here.
+    def test_bit_mask(self):
+        assert not np.any(self.mask['bit'])
+
+    def test_bitarray_mask(self):
+        assert not np.any(self.mask['bitarray'])
+
+    def test_bit_array2_mask(self):
+        assert not np.any(self.mask['bitarray2'])
+
+
+def table_from_scratch():
+    from ..tree import VOTableFile, Resource, Table, Field
+
+    # Create a new VOTable file...
+    votable = VOTableFile()
+
+    # ...with one resource...
+    resource = Resource()
+    votable.resources.append(resource)
+
+    # ... with one table
+    table = Table(votable)
+    resource.tables.append(table)
+
+    # Define some fields
+    table.fields.extend([
+            Field(votable, ID="filename", datatype="char"),
+            Field(votable, ID="matrix", datatype="double", arraysize="2x2")])
+
+    # Now, use those field definitions to create the numpy record arrays, with
+    # the given number of rows
+    table.create_arrays(2)
+
+    # Now table.array can be filled with data
+    table.array[0] = ('test1.xml', [[1, 0], [0, 1]])
+    table.array[1] = ('test2.xml', [[0.5, 0.3], [0.2, 0.1]])
+
+    # Now write the whole thing to a file.
+    # Note, we have to use the top-level votable file object
+    out = io.StringIO()
+    votable.to_xml(out)
+
+
+def test_open_files():
+    def test_file(filename):
+        parse(filename, pedantic=False)
+
+    for filename in get_pkg_data_filenames('data', '*.xml'):
+        yield test_file, filename
+
+
+ at raises(VOTableSpecError)
+def test_too_many_columns():
+    votable = parse(
+        get_pkg_data_filename('data/too_many_columns.xml.gz'),
+        pedantic=False)
+
+
+def test_build_from_scratch():
+    # Create a new VOTable file...
+    votable = tree.VOTableFile()
+
+    # ...with one resource...
+    resource = tree.Resource()
+    votable.resources.append(resource)
+
+    # ... with one table
+    table = tree.Table(votable)
+    resource.tables.append(table)
+
+    # Define some fields
+    table.fields.extend([
+        tree.Field(votable, ID="filename", datatype="char"),
+        tree.Field(votable, ID="matrix", datatype="double", arraysize="2x2")])
+
+    # Now, use those field definitions to create the numpy record arrays, with
+    # the given number of rows
+    table.create_arrays(2)
+
+    # Now table.array can be filled with data
+    table.array[0] = ('test1.xml', [[1, 0], [0, 1]])
+    table.array[1] = ('test2.xml', [[0.5, 0.3], [0.2, 0.1]])
+
+    # Now write the whole thing to a file.
+    # Note, we have to use the top-level votable file object
+    votable.to_xml(os.path.join(TMP_DIR, "new_votable.xml"))
+
+    votable = parse(os.path.join(TMP_DIR, "new_votable.xml"))
+
+    table = votable.get_first_table()
+    assert_array_equal(
+        table.array.mask, np.array([(False, [[False, False], [False, False]]),
+                                    (False, [[False, False], [False, False]])],
+                                    dtype=[('filename', '?'),
+                                           ('matrix', '?', (2, 2))]))
+
+
+def test_validate():
+    output = io.StringIO()
+
+    # We can't test xmllint, because we can't rely on it being on the
+    # user's machine.
+    result = validate(get_pkg_data_filename('data/regression.xml'),
+                      output, xmllint=False)
+
+    assert result == False
+
+    output.seek(0)
+    output = output.readlines()
+
+    # Uncomment to generate new groundtruth
+    # with io.open('validation.txt', 'wt', encoding='utf-8') as fd:
+    #     fd.write(u''.join(output))
+
+    with io.open(
+        get_pkg_data_filename('data/validation.txt'),
+        'rt', encoding='utf-8') as fd:
+        truth = fd.readlines()
+
+    truth = truth[1:]
+    output = output[1:-1]
+
+    for line in difflib.unified_diff(truth, output):
+        if IS_PY3K:
+            sys.stdout.write(
+                line.replace('\\n', '\n'))
+        else:
+            sys.stdout.write(
+                line.encode('unicode_escape').
+                replace('\\n', '\n'))
+
+    assert truth == output
+
+
+def test_gzip_filehandles():
+    votable = parse(
+        get_pkg_data_filename('data/regression.xml'),
+        pedantic=False)
+
+    with open(join(TMP_DIR, "regression.compressed.xml"), 'wb') as fd:
+        votable.to_xml(
+            fd,
+            compressed=True,
+            _astropy_version="testing")
+
+    with open(join(TMP_DIR, "regression.compressed.xml"), 'rb') as fd:
+        votable = parse(
+            fd,
+            pedantic=False)
+
+
+def test_from_scratch_example():
+    with warnings.catch_warnings(record=True) as warning_lines:
+        warnings.resetwarnings()
+        warnings.simplefilter("always", VOWarning, append=True)
+        try:
+            _run_test_from_scratch_example()
+        except ValueError as e:
+            warning_lines.append(str(e))
+
+    assert len(warning_lines) == 0
+
+
+def _run_test_from_scratch_example():
+    from ..tree import VOTableFile, Resource, Table, Field
+
+    # Create a new VOTable file...
+    votable = VOTableFile()
+
+    # ...with one resource...
+    resource = Resource()
+    votable.resources.append(resource)
+
+    # ... with one table
+    table = Table(votable)
+    resource.tables.append(table)
+
+    # Define some fields
+    table.fields.extend([
+        Field(votable, name="filename", datatype="char", arraysize="*"),
+        Field(votable, name="matrix", datatype="double", arraysize="2x2")])
+
+    # Now, use those field definitions to create the numpy record arrays, with
+    # the given number of rows
+    table.create_arrays(2)
+
+    # Now table.array can be filled with data
+    table.array[0] = ('test1.xml', [[1, 0], [0, 1]])
+    table.array[1] = ('test2.xml', [[0.5, 0.3], [0.2, 0.1]])
+
+    assert table.array[0][0] == 'test1.xml'
+
+
+def test_fileobj():
+    # Assert that what we get back is a raw C file pointer
+    # so it will be super fast in the C extension.
+    from ....utils.xml import iterparser
+    filename = get_pkg_data_filename('data/regression.xml')
+    with iterparser._convert_to_fd_or_read_function(filename) as fd:
+        if sys.platform == 'win32':
+            fd()
+        else:
+            if sys.version_info[0] >= 3:
+                assert isinstance(fd, io.FileIO)
+            else:
+                assert isinstance(fd, file)
diff --git a/astropy/io/votable/tree.py b/astropy/io/votable/tree.py
new file mode 100644
index 0000000..0d2b959
--- /dev/null
+++ b/astropy/io/votable/tree.py
@@ -0,0 +1,3279 @@
+# TODO: Test FITS parsing
+
+from __future__ import division, absolute_import
+
+from .util import IS_PY3K
+
+# STDLIB
+import codecs
+import io
+import re
+if IS_PY3K:
+    string_types = (str, bytes)
+else:
+    string_types = (str, unicode)
+
+# THIRD-PARTY
+import numpy as np
+from numpy import ma
+
+# LOCAL
+from .. import fits
+from ... import __version__ as astropy_version
+from ...utils.collections import HomogeneousList
+from ...utils.xml.writer import XMLWriter
+
+from . import converters
+from .exceptions import (warn_or_raise, vo_warn, vo_raise, vo_reraise,
+    warn_unknown_attrs,
+    W06, W07, W08, W09, W10, W11, W12, W13, W15, W17, W18, W19, W20,
+    W21, W22, W26, W27, W28, W29, W32, W33, W35, W36, W37, W38, W40,
+    W41, W42, W43, W44, W45, W50, E06, E08, E09, E10, E11, E12, E13,
+    E14, E15, E16, E17, E18, E19, E20, E21)
+from . import ucd as ucd_mod
+from . import util
+from . import xmlutil
+
+try:
+    from . import tablewriter
+    _has_c_tabledata_writer = True
+except ImportError:
+    _has_c_tabledata_writer = False
+
+
+__all__ = [
+    'Link', 'Info', 'Values', 'Field', 'Param', 'CooSys',
+    'FieldRef', 'ParamRef', 'Group', 'Table', 'Resource',
+    'VOTableFile'
+    ]
+
+
+# The default number of rows to read in each chunk before converting
+# to an array.
+DEFAULT_CHUNK_SIZE = 256
+RESIZE_AMOUNT = 1.5
+
+######################################################################
+# FACTORY FUNCTIONS
+
+
+def _resize(masked, new_size):
+    """
+    Masked arrays can not be resized inplace, and `np.resize` and
+    `ma.resize` are both incompatible with structured arrays.
+    Therefore, we do all this.
+    """
+    new_array = ma.zeros((new_size,), dtype=masked.dtype)
+    length = min(len(masked), new_size)
+    new_array.data[:length] = masked.data[:length]
+    if length != 0:
+        new_array.mask[:length] = masked.mask[:length]
+    return new_array
+
+
+def _lookup_by_id_factory(iterator, element_name, doc):
+    """
+    Creates a function useful for looking up an element by ID.
+
+    Parameters
+    ----------
+    iterator : generator
+        A generator that iterates over some arbitrary set of elements
+
+    element_name : str
+        The XML element name of the elements being iterated over (used
+        for error messages only).
+
+    doc : str
+        A docstring to apply to the generated function.
+
+    Returns
+    -------
+    factory : function
+        A function that looks up an element by ID
+    """
+    def lookup_by_id(self, ref, before=None):
+        """
+        Given an XML id *ref*, finds the first element in the iterator
+        with the attribute ID == *ref*.  If *before* is provided, will
+        stop searching at the object *before*.  This is important,
+        since "forward references" are not allowed in the VOTABLE
+        format.
+        """
+        for element in getattr(self, iterator)():
+            if element is before:
+                if element.ID == ref:
+                    vo_raise(
+                        "%s references itself" % element_name,
+                        element._config, element._pos, KeyError)
+                break
+            if element.ID == ref:
+                return element
+        raise KeyError(
+            "No %s with ID '%s' found before the referencing %s" %
+            (element_name, ref, element_name))
+
+    lookup_by_id.__doc__ = doc
+    return lookup_by_id
+
+
+def _lookup_by_id_or_name_factory(iterator, element_name, doc):
+    """
+    Like `_lookup_by_id_factory`, but also looks in the "name" attribute.
+    """
+    def lookup_by_id(self, ref, before=None):
+        """
+        Given an key *ref*, finds the first element in the iterator
+        with the attribute ID == *ref* or name == *ref*.  If *before*
+        is provided, will stop searching at the object *before*.  This
+        is important, since "forward references" are not allowed in
+        the VOTABLE format.
+        """
+        for element in getattr(self, iterator)():
+            if element is before:
+                if ref in (element.ID, element.name):
+                    vo_raise(
+                        "%s references itself" % element_name,
+                        element._config, element._pos, KeyError)
+                break
+            if ref in (element.ID, element.name):
+                return element
+        raise KeyError(
+            "No %s with ID or name '%s' found before the referencing %s" %
+            (element_name, ref, element_name))
+
+    lookup_by_id.__doc__ = doc
+    return lookup_by_id
+
+
+######################################################################
+# ATTRIBUTE CHECKERS
+def check_astroyear(year, field, config={}, pos=None):
+    """
+    Raises a `~astropy.io.votable.exceptions.VOTableSpecError` if
+    *year* is not a valid astronomical year as defined by the VOTABLE
+    standard.
+
+    Parameters
+    ----------
+    year : str
+        An astronomical year string
+
+    field : str
+        The name of the field this year was found in (used for error
+        message)
+
+    config, pos : optional
+        Information about the source of the value
+    """
+    if (year is not None and
+        re.match(ur"^[JB]?[0-9]+([.][0-9]*)?$", year) is None):
+        warn_or_raise(W07, W07, (field, year), config, pos)
+        return False
+    return True
+
+
+def check_string(string, attr_name, config={}, pos=None):
+    """
+    Raises a `~astropy.io.votable.exceptions.VOTableSpecError` if
+    *string* is not a string or Unicode string.
+
+    Parameters
+    ----------
+    string : str
+        An astronomical year string
+
+    field : str
+        The name of the field this year was found in (used for error
+        message)
+
+    config, pos : optional
+        Information about the source of the value
+    """
+    if string is not None and not isinstance(string, string_types):
+        warn_or_raise(W08, W08, attr_name, config, pos)
+        return False
+    return True
+
+
+def resolve_id(ID, id, config={}, pos=None):
+    if ID is None and id is not None:
+        warn_or_raise(W09, W09, (), config, pos)
+        return id
+    return ID
+
+
+def check_ucd(ucd, config={}, pos=None):
+    """
+    Warns or raises a
+    `~astropy.io.votable.exceptions.VOTableSpecError` if *ucd* is not
+    a valid `unified content descriptor`_ string as defined by the
+    VOTABLE standard.
+
+    Parameters
+    ----------
+    ucd : str
+        A UCD string.
+
+    config, pos : optional
+        Information about the source of the value
+    """
+    if config.get('version_1_1_or_later'):
+        try:
+            ucd_mod.parse_ucd(
+                ucd,
+                check_controlled_vocabulary=config.get(
+                    'version_1_2_or_later', False),
+                has_colon=config.get('version_1_2_or_later', False))
+        except ValueError as e:
+            # This weird construction is for Python 3 compatibility
+            if config.get('pedantic'):
+                vo_raise(W06, (ucd, unicode(e)), config, pos)
+            else:
+                vo_warn(W06, (ucd, unicode(e)), config, pos)
+                return False
+    return True
+
+
+######################################################################
+# PROPERTY MIXINS
+class _IDProperty(object):
+    @property
+    def ID(self):
+        """
+        The XML ID_ of the element.  May be ``None`` or a string
+        conforming to XML ID_ syntax.
+        """
+        return self._ID
+
+    @ID.setter
+    def ID(self, ID):
+        xmlutil.check_id(ID, 'ID', self._config, self._pos)
+        self._ID = ID
+
+    @ID.deleter
+    def ID(self):
+        self._ID = None
+
+
+class _NameProperty(object):
+    @property
+    def name(self):
+        """An optional name for the element."""
+        return self._name
+
+    @name.setter
+    def name(self, name):
+        xmlutil.check_token(name, 'name', self._config, self._pos)
+        self._name = name
+
+    @name.deleter
+    def name(self):
+        self._name = None
+
+
+class _XtypeProperty(object):
+    @property
+    def xtype(self):
+        """Extended data type information."""
+        return self._xtype
+
+    @xtype.setter
+    def xtype(self, xtype):
+        if xtype is not None and not self._config.get('version_1_2_or_later'):
+            warn_or_raise(
+                W28, W28, ('xtype', self._element_name, '1.2'),
+                self._config, self._pos)
+        check_string(xtype, 'xtype', self._config, self._pos)
+        self._xtype = xtype
+
+    @xtype.deleter
+    def xtype(self):
+        self._xtype = None
+
+
+class _UtypeProperty(object):
+    _utype_in_v1_2 = False
+
+    @property
+    def utype(self):
+        """The usage-specific or `unique type`_ of the element."""
+        return self._utype
+
+    @utype.setter
+    def utype(self, utype):
+        if (self._utype_in_v1_2 and
+            utype is not None and
+            not self._config.get('version_1_2_or_later')):
+            warn_or_raise(
+                W28, W28, ('utype', self._element_name, '1.2'),
+                self._config, self._pos)
+        check_string(utype, 'utype', self._config, self._pos)
+        self._utype = utype
+
+    @utype.deleter
+    def utype(self):
+        self._utype = None
+
+
+class _UcdProperty(object):
+    _ucd_in_v1_2 = False
+
+    @property
+    def ucd(self):
+        """The `unified content descriptor`_ for the element."""
+        return self._ucd
+
+    @ucd.setter
+    def ucd(self, ucd):
+        if ucd is not None and ucd.strip() == '':
+            ucd = None
+        if ucd is not None:
+            if (self._ucd_in_v1_2 and
+                not self._config.get('version_1_2_or_later')):
+                warn_or_raise(
+                    W28, W28, ('ucd', self._element_name, '1.2'),
+                    self._config, self._pos)
+            check_ucd(ucd, self._config, self._pos)
+        self._ucd = ucd
+
+    @ucd.deleter
+    def ucd(self):
+        self._ucd = None
+
+
+class _DescriptionProperty(object):
+    @property
+    def description(self):
+        """
+        An optional string describing the element.  Corresponds to the
+        DESCRIPTION_ element.
+        """
+        return self._description
+
+    @description.setter
+    def description(self, description):
+        self._description = description
+
+    @description.deleter
+    def description(self):
+        self._description = None
+
+
+######################################################################
+# ELEMENT CLASSES
+class Element(object):
+    """
+    A base class for all classes that represent XML elements in the
+    VOTABLE file.
+    """
+    def _add_unknown_tag(self, iterator, tag, data, config, pos):
+        warn_or_raise(W10, W10, tag, config, pos)
+
+    def _ignore_add(self, iterator, tag, data, config, pos):
+        warn_unknown_attrs(tag, data.iterkeys(), config, pos)
+
+    def _add_definitions(self, iterator, tag, data, config, pos):
+        if config.get('version_1_1_or_later'):
+            warn_or_raise(W22, W22, (), config, pos)
+        warn_unknown_attrs(tag, data.iterkeys(), config, pos)
+
+
+class SimpleElement(Element):
+    """
+    A base class for simple elements, such as FIELD, PARAM and INFO
+    that don't require any special parsing or outputting machinery.
+    """
+    def __init__(self):
+        Element.__init__(self)
+
+    def parse(self, iterator, config):
+        for start, tag, data, pos in iterator:
+            if start and tag != self._element_name:
+                self._add_unknown_tag(iterator, tag, data, config, pos)
+            elif tag == self._element_name:
+                break
+
+        return self
+
+    def to_xml(self, w, **kwargs):
+        w.element(self._element_name,
+                  attrib=w.object_attrs(self, self._attr_list))
+
+
+class SimpleElementWithContent(SimpleElement):
+    """
+    A base class for simple elements, such as FIELD, PARAM and INFO
+    that don't require any special parsing or outputting machinery.
+    """
+    def __init__(self):
+        SimpleElement.__init__(self)
+
+        self._content = None
+
+    def to_xml(self, w, **kwargs):
+        w.element(self._element_name, self._content,
+                  attrib=w.object_attrs(self, self._attr_list))
+
+    @property
+    def content(self):
+        """The content of the element."""
+        return self._content
+
+    @content.setter
+    def content(self, content):
+        check_string(content, 'content', self._config, self._pos)
+        self._content = content
+
+    @content.deleter
+    def content(self):
+        self._content = None
+
+
+class Link(SimpleElement, _IDProperty):
+    """
+    LINK_ elements: used to reference external documents and servers through a URI.
+
+    The keyword arguments correspond to setting members of the same
+    name, documented below.
+    """
+    _attr_list = ['ID', 'content_role', 'content_type', 'title', 'value',
+                  'href', 'action']
+    _element_name = 'LINK'
+
+    def __init__(self, ID=None, title=None, value=None, href=None, action=None,
+                 id=None, config={}, pos=None, **kwargs):
+        self._config = config
+        self._pos = pos
+
+        SimpleElement.__init__(self)
+
+        content_role = kwargs.get('content-role') or kwargs.get('content_role')
+        content_type = kwargs.get('content-type') or kwargs.get('content_type')
+
+        if 'gref' in kwargs:
+            warn_or_raise(W11, W11, (), config, pos)
+
+        self.ID           = resolve_id(ID, id, config, pos)
+        self.content_role = content_role
+        self.content_type = content_type
+        self.title        = title
+        self.value        = value
+        self.href         = href
+        self.action       = action
+
+        warn_unknown_attrs(
+            'LINK', kwargs.iterkeys(), config, pos,
+            ['content-role', 'content_role', 'content-type', 'content_type',
+             'gref'])
+
+    @property
+    def content_role(self):
+        """
+        Defines the MIME role of the referenced object.  Must be one of:
+
+          None, 'query', 'hints', 'doc' or 'location'
+        """
+        return self._content_role
+
+    @content_role.setter
+    def content_role(self, content_role):
+        if content_role not in (None, 'query', 'hints', 'doc', 'location'):
+            vo_warn(W45, (content_role,), self._config, self._pos)
+        self._content_role = content_role
+
+    @content_role.deleter
+    def content_role(self):
+        self._content_role = None
+
+    @property
+    def content_type(self):
+        """Defines the MIME content type of the referenced object."""
+        return self._content_type
+
+    @content_type.setter
+    def content_type(self, content_type):
+        xmlutil.check_mime_content_type(content_type, self._config, self._pos)
+        self._content_type = content_type
+
+    @content_type.deleter
+    def content_type(self):
+        self._content_type = None
+
+    @property
+    def href(self):
+        """
+        A URI to an arbitrary protocol.  The vo package only supports
+        http and anonymous ftp.
+        """
+        return self._href
+
+    @href.setter
+    def href(self, href):
+        xmlutil.check_anyuri(href, self._config, self._pos)
+        self._href = href
+
+    @href.deleter
+    def href(self):
+        self._href = None
+
+    def to_table_column(self, column):
+        meta = {}
+        for key in self._attr_list:
+            val = getattr(self, key, None)
+            if val is not None:
+                meta[key] = val
+
+        column.meta.setdefault('links', [])
+        column.meta['links'].append(meta)
+
+    @classmethod
+    def from_table_column(cls, d):
+        return cls(**d)
+
+
+class Info(SimpleElementWithContent, _IDProperty, _XtypeProperty,
+           _UtypeProperty):
+    """
+    INFO_ elements: arbitrary key-value pairs for extensions to the standard.
+
+    The keyword arguments correspond to setting members of the same
+    name, documented below.
+    """
+    _element_name = 'INFO'
+    _attr_list_11 = ['ID', 'name', 'value']
+    _attr_list_12 = _attr_list_11 + ['xtype', 'ref', 'unit', 'ucd', 'utype']
+    _utype_in_v1_2 = True
+
+    def __init__(self, ID=None, name=None, value=None, id=None, xtype=None,
+                 ref=None, unit=None, ucd=None, utype=None,
+                 config={}, pos=None, **extra):
+        self._config = config
+        self._pos = pos
+
+        SimpleElementWithContent.__init__(self)
+
+        self.ID      = (resolve_id(ID, id, config, pos) or
+                        xmlutil.fix_id(name, config, pos))
+        self.name    = name
+        self.value   = value
+        self.xtype   = xtype
+        self.ref     = ref
+        self.unit    = unit
+        self.ucd     = ucd
+        self.utype   = utype
+
+        if config.get('version_1_2_or_later'):
+            self._attr_list = self._attr_list_12
+        else:
+            self._attr_list = self._attr_list_11
+            if xtype is not None:
+                warn_unknown_attrs('INFO', ['xtype'], config, pos)
+            if ref is not None:
+                warn_unknown_attrs('INFO', ['ref'], config, pos)
+            if unit is not None:
+                warn_unknown_attrs('INFO', ['unit'], config, pos)
+            if ucd is not None:
+                warn_unknown_attrs('INFO', ['ucd'], config, pos)
+            if utype is not None:
+                warn_unknown_attrs('INFO', ['utype'], config, pos)
+
+        warn_unknown_attrs('INFO', extra.iterkeys(), config, pos)
+
+    @property
+    def name(self):
+        """[*required*] The key of the key-value pair."""
+        return self._name
+
+    @name.setter
+    def name(self, name):
+        if name is None:
+            warn_or_raise(W35, W35, ('name'), self._config, self._pos)
+        xmlutil.check_token(name, 'name', self._config, self._pos)
+        self._name = name
+
+    @property
+    def value(self):
+        """
+        [*required*] The value of the key-value pair.  (Always stored
+        as a string or unicode string).
+        """
+        return self._value
+
+    @value.setter
+    def value(self, value):
+        if value is None:
+            warn_or_raise(W35, W35, ('value'), self._config, self._pos)
+        check_string(value, 'value', self._config, self._pos)
+        self._value = value
+
+    @property
+    def content(self):
+        """The content inside the INFO element."""
+        return self._content
+
+    @content.setter
+    def content(self, content):
+        check_string(content, 'content', self._config, self._pos)
+        self._content = content
+
+    @content.deleter
+    def content(self):
+        self._content = None
+
+    @property
+    def ref(self):
+        """
+        Refer to another INFO_ element by ID_, defined previously in
+        the document.
+        """
+        return self._ref
+
+    @ref.setter
+    def ref(self, ref):
+        if ref is not None and not self._config.get('version_1_2_or_later'):
+            warn_or_raise(W28, W28, ('ref', 'INFO', '1.2'),
+                          self._config, self._pos)
+        xmlutil.check_id(ref, 'ref', self._config, self._pos)
+        # TODO: actually apply the reference
+        # if ref is not None:
+        #     try:
+        #         other = self._votable.get_values_by_id(ref, before=self)
+        #     except KeyError:
+        #         vo_raise(
+        #             "VALUES ref='%s', which has not already been defined." %
+        #             self.ref, self._config, self._pos, KeyError)
+        #     self.null = other.null
+        #     self.type = other.type
+        #     self.min = other.min
+        #     self.min_inclusive = other.min_inclusive
+        #     self.max = other.max
+        #     self.max_inclusive = other.max_inclusive
+        #     self._options[:] = other.options
+        self._ref = ref
+
+    @ref.deleter
+    def ref(self):
+        self._ref = None
+
+    @property
+    def unit(self):
+        """A string specifying the units_ for the INFO_."""
+        return self._unit
+
+    @unit.setter
+    def unit(self, unit):
+        if unit is None:
+            self._unit = None
+            return
+
+        from ... import units as u
+
+        if not self._config.get('version_1_2_or_later'):
+            warn_or_raise(W28, W28, ('unit', 'INFO', '1.2'),
+                          self._config, self._pos)
+
+        unit = u.Unit(unit, format='cds', parse_strict='silent')
+        if isinstance(unit, u.UnrecognizedUnit):
+            warn_or_raise(W50, W50, (unit.to_string(),),
+                          self._config, self._pos)
+        self._unit = unit
+
+    @unit.deleter
+    def unit(self):
+        self._unit = None
+
+    def to_xml(self, w, **kwargs):
+        attrib = w.object_attrs(self, self._attr_list)
+        if 'unit' in attrib:
+            attrib['unit'] = self.unit.to_string('cds')
+        w.element(self._element_name, self._content,
+                  attrib=attrib)
+
+
+class Values(Element, _IDProperty):
+    """
+    VALUES_ element: used within FIELD_ and PARAM_ elements to define the domain of values.
+
+    The keyword arguments correspond to setting members of the same
+    name, documented below.
+    """
+    def __init__(self, votable, field, ID=None, null=None, ref=None,
+                 type="legal", id=None, config={}, pos=None, **extras):
+        self._config  = config
+        self._pos = pos
+
+        Element.__init__(self)
+
+        self._votable = votable
+        self._field   = field
+        self.ID       = resolve_id(ID, id, config, pos)
+        self.null     = null
+        self._ref     = ref
+        self.type     = type
+
+        self.min           = None
+        self.max           = None
+        self.min_inclusive = True
+        self.max_inclusive = True
+        self._options      = []
+
+        warn_unknown_attrs('VALUES', extras.iterkeys(), config, pos)
+
+    @property
+    def null(self):
+        """
+        For integral datatypes, *null* is used to define the value
+        used for missing values.
+        """
+        return self._null
+
+    @null.setter
+    def null(self, null):
+        if null is not None and isinstance(null, string_types):
+            try:
+                null_val = self._field.converter.parse_scalar(
+                    null, self._config, self._pos)[0]
+            except:
+                warn_or_raise(W36, W36, null, self._config, self._pos)
+                null_val = self._field.converter.parse_scalar(
+                    '0', self._config, self._pos)[0]
+        else:
+            null_val = null
+        self._null = null_val
+
+    @null.deleter
+    def null(self):
+        self._null = None
+
+    @property
+    def type(self):
+        """
+        [*required*] Defines the applicability of the domain defined
+        by this VALUES_ element.  Must be one of the following
+        strings:
+
+          - 'legal': The domain of this column applies in general to
+            this datatype. (default)
+
+          - 'actual': The domain of this column applies only to the
+            data enclosed in the parent table.
+        """
+        return self._type
+
+    @type.setter
+    def type(self, type):
+        if type not in ('legal', 'actual'):
+            vo_raise(E08, type, self._config, self._pos)
+        self._type = type
+
+    @property
+    def ref(self):
+        """
+        Refer to another VALUES_ element by ID_, defined previously in
+        the document, for MIN/MAX/OPTION information.
+        """
+        return self._ref
+
+    @ref.setter
+    def ref(self, ref):
+        xmlutil.check_id(ref, 'ref', self._config, self._pos)
+        if ref is not None:
+            try:
+                other = self._votable.get_values_by_id(ref, before=self)
+            except KeyError:
+                warn_or_raise(W43, W43, ('VALUES', self.ref), self._config,
+                              self._pos)
+                ref = None
+            else:
+                self.null = other.null
+                self.type = other.type
+                self.min = other.min
+                self.min_inclusive = other.min_inclusive
+                self.max = other.max
+                self.max_inclusive = other.max_inclusive
+                self._options[:] = other.options
+        self._ref = ref
+
+    @ref.deleter
+    def ref(self):
+        self._ref = None
+
+    @property
+    def min(self):
+        """
+        The minimum value of the domain.  See :attr:`min_inclusive`.
+        """
+        return self._min
+
+    @min.setter
+    def min(self, min):
+        if hasattr(self._field, 'converter') and min is not None:
+            self._min = self._field.converter.parse(min)[0]
+        else:
+            self._min = min
+
+    @min.deleter
+    def min(self):
+        self._min = None
+
+    @property
+    def min_inclusive(self):
+        """When `True`, the domain includes the minimum value."""
+        return self._min_inclusive
+
+    @min_inclusive.setter
+    def min_inclusive(self, inclusive):
+        if inclusive == 'yes':
+            self._min_inclusive = True
+        elif inclusive == 'no':
+            self._min_inclusive = False
+        else:
+            self._min_inclusive = bool(inclusive)
+
+    @min_inclusive.deleter
+    def min_inclusive(self):
+        self._min_inclusive = True
+
+    @property
+    def max(self):
+        """
+        The maximum value of the domain.  See :attr:`max_inclusive`.
+        """
+        return self._max
+
+    @max.setter
+    def max(self, max):
+        if hasattr(self._field, 'converter') and max is not None:
+            self._max = self._field.converter.parse(max)[0]
+        else:
+            self._max = max
+
+    @max.deleter
+    def max(self):
+        self._max = None
+
+    @property
+    def max_inclusive(self):
+        """When `True`, the domain includes the maximum value."""
+        return self._max_inclusive
+
+    @max_inclusive.setter
+    def max_inclusive(self, inclusive):
+        if inclusive == 'yes':
+            self._max_inclusive = True
+        elif inclusive == 'no':
+            self._max_inclusive = False
+        else:
+            self._max_inclusive = bool(inclusive)
+
+    @max_inclusive.deleter
+    def max_inclusive(self):
+        self._max_inclusive = True
+
+    @property
+    def options(self):
+        """
+        A list of string key-value tuples defining other OPTION
+        elements for the domain.  All options are ignored -- they are
+        stored for round-tripping purposes only.
+        """
+        return self._options
+
+    def parse(self, iterator, config):
+        if self.ref is not None:
+            for start, tag, data, pos in iterator:
+                if start:
+                    warn_or_raise(W44, W44, tag, config, pos)
+                else:
+                    if tag != 'VALUES':
+                        warn_or_raise(W44, W44, tag, config, pos)
+                    break
+        else:
+            for start, tag, data, pos in iterator:
+                if start:
+                    if tag == 'MIN':
+                        if 'value' not in data:
+                            vo_raise(E09, 'MIN', config, pos)
+                        self.min = data['value']
+                        self.min_inclusive = data.get('inclusive', 'yes')
+                        warn_unknown_attrs(
+                            'MIN', data.iterkeys(), config, pos,
+                            ['value', 'inclusive'])
+                    elif tag == 'MAX':
+                        if 'value' not in data:
+                            vo_raise(E09, 'MAX', config, pos)
+                        self.max = data['value']
+                        self.max_inclusive = data.get('inclusive', 'yes')
+                        warn_unknown_attrs(
+                            'MAX', data.iterkeys(), config, pos,
+                            ['value', 'inclusive'])
+                    elif tag == 'OPTION':
+                        if 'value' not in data:
+                            vo_raise(E09, 'OPTION', config, pos)
+                        xmlutil.check_token(
+                            data.get('name'), 'name', config, pos)
+                        self.options.append(
+                            (data.get('name'), data.get('value')))
+                        warn_unknown_attrs(
+                            'OPTION', data.iterkeys(), config, pos,
+                            ['data', 'name'])
+                elif tag == 'VALUES':
+                    break
+
+        return self
+
+    def is_defaults(self):
+        # If there's nothing meaningful or non-default to write,
+        # don't write anything.
+        return (self.ref is None and self.null is None and self.ID is None and
+                self.max is None and self.min is None and self.options == [])
+
+    def to_xml(self, w, **kwargs):
+        def yes_no(value):
+            if value:
+                return u'yes'
+            return u'no'
+
+        if self.is_defaults():
+            return
+
+        if self.ref is not None:
+            w.element(u'VALUES', attrib=w.object_attrs(self, [u'ref']))
+        else:
+            with w.tag(u'VALUES',
+                       attrib=w.object_attrs(
+                           self, [u'ID', u'null', u'ref'])):
+                if self.min is not None:
+                    w.element(
+                        u'MIN',
+                        value=self._field.converter.output(self.min, False),
+                        inclusive=yes_no(self.min_inclusive))
+                if self.max is not None:
+                    w.element(
+                        u'MAX',
+                        value=self._field.converter.output(self.max, False),
+                        inclusive=yes_no(self.max_inclusive))
+                for name, value in self.options:
+                    w.element(
+                        u'OPTION',
+                        name=name,
+                        value=value)
+
+    def to_table_column(self, column):
+        # Have the ref filled in here
+        ref = self.ref
+
+        meta = {}
+        for key in [u'ID', u'null']:
+            val = getattr(self, key, None)
+            if val is not None:
+                meta[key] = val
+        if self.min is not None:
+            meta['min'] = {
+                'value': self.min,
+                'inclusive': self.min_inclusive}
+        if self.max is not None:
+            meta['max'] = {
+                'value': self.max,
+                'inclusive': self.max_inclusive}
+        if len(self.options):
+            meta['options'] = dict(self.options)
+
+        column.meta['values'] = meta
+
+    def from_table_column(self, column):
+        if not 'values' in column.meta:
+            return
+
+        meta = column.meta['values']
+        for key in [u'ID', u'null']:
+            val = meta.get(key, None)
+            if val is not None:
+                setattr(self, key, val)
+        if 'min' in meta:
+            self.min = meta['min']['value']
+            self.min_inclusive = meta['min']['inclusive']
+        if 'max' in meta:
+            self.max = meta['max']['value']
+            self.max_inclusive = meta['max']['inclusive']
+        if 'options' in meta:
+            self._options = meta['options'].items()
+
+
+class Field(SimpleElement, _IDProperty, _NameProperty, _XtypeProperty,
+            _UtypeProperty, _UcdProperty):
+    """
+    FIELD_ element: describes the datatype of a particular column of data.
+
+    The keyword arguments correspond to setting members of the same
+    name, documented below.
+
+    If *ID* is provided, it is used for the column name in the
+    resulting recarray of the table.  If no *ID* is provided, *name*
+    is used instead.  If neither is provided, an exception will be
+    raised.
+    """
+    _attr_list_11 = ['ID', 'name', 'datatype', 'arraysize', 'ucd',
+                     'unit', 'width', 'precision', 'utype', 'ref']
+    _attr_list_12 = _attr_list_11 + ['xtype']
+    _element_name = 'FIELD'
+
+    def __init__(self, votable, ID=None, name=None, datatype=None,
+                 arraysize=None, ucd=None, unit=None, width=None,
+                 precision=None, utype=None, ref=None, type=None, id=None,
+                 xtype=None,
+                 config={}, pos=None, **extra):
+        self._config = config
+        self._pos = pos
+
+        SimpleElement.__init__(self)
+
+        if config.get('version_1_2_or_later'):
+            self._attr_list = self._attr_list_12
+        else:
+            self._attr_list = self._attr_list_11
+            if xtype is not None:
+                warn_unknown_attrs(self._element_name, ['xtype'], config, pos)
+
+        # TODO: REMOVE ME ----------------------------------------
+        # This is a terrible hack to support Simple Image Access
+        # Protocol results from archive.noao.edu.  It creates a field
+        # for the coordinate projection type of type "double", which
+        # actually contains character data.  We have to hack the field
+        # to store character data, or we can't read it in.  A warning
+        # will be raised when this happens.
+        if (not config.get('pedantic') and name == 'cprojection' and
+            ID == 'cprojection' and ucd == 'VOX:WCS_CoordProjection' and
+            datatype == 'double'):
+            datatype = 'char'
+            arraysize = '3'
+            vo_warn(W40, (), config, pos)
+        # ----------------------------------------
+
+        self.description = None
+        self._votable = votable
+
+        self.ID = (resolve_id(ID, id, config, pos) or
+                   xmlutil.fix_id(name, config, pos))
+        self.name = name
+        if name is None:
+            if (self._element_name == 'PARAM' and
+                not config.get('version_1_1_or_later')):
+                pass
+            else:
+                warn_or_raise(W15, W15, self._element_name, config, pos)
+            self.name = self.ID
+
+        if self._ID is None and name is None:
+            vo_raise(W12, self._element_name, config, pos)
+
+        datatype_mapping = {
+            'string'        : 'char',
+            'unicodeString' : 'unicodeChar',
+            'int16'         : 'short',
+            'int32'         : 'int',
+            'int64'         : 'long',
+            'float32'       : 'float',
+            'float64'       : 'double'}
+
+        if datatype in datatype_mapping:
+            warn_or_raise(W13, W13, (datatype, datatype_mapping[datatype]),
+                          config, pos)
+            datatype = datatype_mapping[datatype]
+
+        self.ref        = ref
+        self.datatype   = datatype
+        self.arraysize  = arraysize
+        self.ucd        = ucd
+        self.unit       = unit
+        self.width      = width
+        self.precision  = precision
+        self.utype      = utype
+        self.type       = type
+        self._links     = HomogeneousList(Link)
+        self.title      = self.name
+        self.values     = Values(self._votable, self)
+        self.xtype      = xtype
+
+        self._setup(config, pos)
+
+        warn_unknown_attrs(self._element_name, extra.iterkeys(), config, pos)
+
+    @classmethod
+    def uniqify_names(cls, fields):
+        """
+        Make sure that all names and titles in a list of fields are
+        unique, by appending numbers if necessary.
+        """
+        unique = {}
+        for field in fields:
+            i = 2
+            new_id = field.ID
+            while new_id in unique:
+                new_id = field.ID + "_%d" % i
+                i += 1
+            if new_id != field.ID:
+                vo_warn(W32, (field.ID, new_id), field._config, field._pos)
+            field.ID = new_id
+            unique[new_id] = field.ID
+
+        for field in fields:
+            i = 2
+            if field.name is None:
+                new_name = field.ID
+                implicit = True
+            else:
+                new_name = field.name
+                implicit = False
+            if new_name != field.ID:
+                while new_name in unique:
+                    new_name = field.name + " %d" % i
+                    i += 1
+
+            if (not implicit and
+                new_name != field.name):
+                vo_warn(W33, (field.name, new_name), field._config, field._pos)
+            field._unique_name = new_name
+            unique[new_name] = field.name
+
+    def _setup(self, config, pos):
+        if self.values._ref is not None:
+            self.values.ref = self.values._ref
+        self.converter = converters.get_converter(self, config, pos)
+
+    @property
+    def datatype(self):
+        """
+        [*required*] The datatype of the column.  Valid values (as
+        defined by the spec) are:
+
+          'boolean', 'bit', 'unsignedByte', 'short', 'int', 'long',
+          'char', 'unicodeChar', 'float', 'double', 'floatComplex', or
+          'doubleComplex'
+
+        Many VOTABLE files in the wild use 'string' instead of 'char',
+        so that is also a valid option, though 'string' will always be
+        converted to 'char' when writing the file back out.
+        """
+        return self._datatype
+
+    @datatype.setter
+    def datatype(self, datatype):
+        if datatype is None:
+            if self._config.get('version_1_1_or_later'):
+                warn_or_raise(E10, E10, self._element_name, self._config,
+                              self._pos)
+            datatype = 'char'
+        if datatype not in converters.converter_mapping:
+            vo_raise(E06, (datatype, self.ID), self._config, self._pos)
+        self._datatype = datatype
+
+    @property
+    def precision(self):
+        """
+        Along with :attr:`width`, defines the `numerical accuracy`_
+        associated with the data.  These values are used to limit the
+        precision when writing floating point values back to the XML
+        file.  Otherwise, it is purely informational -- the Numpy
+        recarray containing the data itself does not use this
+        information.
+        """
+        return self._precision
+
+    @precision.setter
+    def precision(self, precision):
+        if precision is not None and not re.match(ur"^[FE]?[0-9]+$", precision):
+            vo_raise(E11, precision, self._config, self._pos)
+        self._precision = precision
+
+    @precision.deleter
+    def precision(self):
+        self._precision = None
+
+    @property
+    def width(self):
+        """
+        Along with :attr:`precision`, defines the `numerical
+        accuracy`_ associated with the data.  These values are used to
+        limit the precision when writing floating point values back to
+        the XML file.  Otherwise, it is purely informational -- the
+        Numpy recarray containing the data itself does not use this
+        information.
+        """
+        return self._width
+
+    @width.setter
+    def width(self, width):
+        if width is not None:
+            width = int(width)
+            if width <= 0:
+                vo_raise(E12, width, self._config, self._pos)
+        self._width = width
+
+    @width.deleter
+    def width(self):
+        self._width = None
+
+    # ref on FIELD and PARAM behave differently than elsewhere -- here
+    # they're just informational, such as to refer to a coordinate
+    # system.
+    @property
+    def ref(self):
+        """
+        On FIELD_ elements, ref is used only for informational
+        purposes, for example to refer to a COOSYS_ element.
+        """
+        return self._ref
+
+    @ref.setter
+    def ref(self, ref):
+        xmlutil.check_id(ref, 'ref', self._config, self._pos)
+        self._ref = ref
+
+    @ref.deleter
+    def ref(self):
+        self._ref = None
+
+    @property
+    def unit(self):
+        """A string specifying the units_ for the FIELD_."""
+        return self._unit
+
+    @unit.setter
+    def unit(self, unit):
+        if unit is None:
+            self._unit = None
+            return
+
+        from ... import units as u
+
+        unit = u.Unit(unit, format='cds', parse_strict='silent')
+        if isinstance(unit, u.UnrecognizedUnit):
+            warn_or_raise(
+                W50, W50, (unit.to_string(),),
+                self._config, self._pos)
+        self._unit = unit
+
+    @unit.deleter
+    def unit(self):
+        self._unit = None
+
+    @property
+    def arraysize(self):
+        """
+        Specifies the size of the multidimensional array if this
+        FIELD_ contains more than a single value.
+
+        See `multidimensional arrays`_.
+        """
+        return self._arraysize
+
+    @arraysize.setter
+    def arraysize(self, arraysize):
+        if (arraysize is not None and
+            not re.match(ur"^([0-9]+x)*[0-9]*[*]?(s\W)?$", arraysize)):
+            vo_raise(E13, arraysize, self._config, self._pos)
+        self._arraysize = arraysize
+
+    @arraysize.deleter
+    def arraysize(self):
+        self._arraysize = None
+
+    @property
+    def type(self):
+        """
+        The type attribute on FIELD_ elements is reserved for future
+        extensions.
+        """
+        return self._type
+
+    @type.setter
+    def type(self, type):
+        self._type = type
+
+    @type.deleter
+    def type(self):
+        self._type = None
+
+    @property
+    def values(self):
+        """
+        A :class:`Values` instance (or ``None``) defining the domain
+        of the column.
+        """
+        return self._values
+
+    @values.setter
+    def values(self, values):
+        assert values is None or isinstance(values, Values)
+        self._values = values
+
+    @values.deleter
+    def values(self):
+        self._values = None
+
+    @property
+    def links(self):
+        """
+        A list of :class:`Link` instances used to reference more
+        details about the meaning of the FIELD_.  This is purely
+        informational and is not used by the `astropy.io.votable`
+        package.
+        """
+        return self._links
+
+    def parse(self, iterator, config):
+        for start, tag, data, pos in iterator:
+            if start:
+                if tag == 'VALUES':
+                    self.values.__init__(
+                        self._votable, self, config=config, pos=pos, **data)
+                    self.values.parse(iterator, config)
+                elif tag == 'LINK':
+                    link = Link(config=config, pos=pos, **data)
+                    self.links.append(link)
+                    link.parse(iterator, config)
+                elif tag == 'DESCRIPTION':
+                    warn_unknown_attrs(
+                        'DESCRIPTION', data.iterkeys(), config, pos)
+                elif tag != self._element_name:
+                    self._add_unknown_tag(iterator, tag, data, config, pos)
+            else:
+                if tag == 'DESCRIPTION':
+                    if self.description is not None:
+                        warn_or_raise(
+                            W17, W17, self._element_name, config, pos)
+                    self.description = data or None
+                elif tag == self._element_name:
+                    break
+
+        if self.description is not None:
+            self.title = " ".join(x.strip() for x in
+                                  self.description.split("\n"))
+        else:
+            self.title = self.name
+
+        self._setup(config, pos)
+
+        return self
+
+    def to_xml(self, w, **kwargs):
+        attrib = w.object_attrs(self, self._attr_list)
+        if 'unit' in attrib:
+            attrib['unit'] = self.unit.to_string('cds')
+        with w.tag(self._element_name, attrib=attrib):
+            if self.description is not None:
+                w.element(u'DESCRIPTION', self.description, wrap=True)
+            if not self.values.is_defaults():
+                self.values.to_xml(w, **kwargs)
+            for link in self.links:
+                link.to_xml(w, **kwargs)
+
+    def to_table_column(self, column):
+        """
+        Sets the attributes of a given `astropy.table.Column` instance
+        to match the information in this `Field`.
+        """
+        for key in ['ucd', 'width', 'precision', 'utype', 'xtype']:
+            val = getattr(self, key, None)
+            if val is not None:
+                column.meta[key] = val
+        if not self.values.is_defaults():
+            self.values.to_table_column(column)
+        for link in self.links:
+            link.to_table_column(column)
+        if self.description is not None:
+            column.description = self.description
+        if self.unit is not None:
+            # TODO: Use units framework when it's available
+            column.units = self.unit
+        if isinstance(self.converter, converters.FloatingPoint):
+            column.format = self.converter.output_format
+
+    @classmethod
+    def from_table_column(cls, votable, column):
+        """
+        Restores a `Field` instance from a given
+        `astropy.table.Column` instance.
+        """
+        kwargs = {}
+        for key in ['ucd', 'width', 'precision', 'utype', 'xtype']:
+            val = column.meta.get(key, None)
+            if val is not None:
+                kwargs[key] = val
+        # TODO: Use the unit framework when available
+        if column.units is not None:
+            kwargs['unit'] = column.units
+        kwargs['name'] = column.name
+        result = converters.table_column_to_votable_datatype(column)
+        kwargs.update(result)
+
+        field = cls(votable, **kwargs)
+
+        if column.description is not None:
+            field.description = column.description
+        field.values.from_table_column(column)
+        if 'links' in column.meta:
+            for link in column.meta['links']:
+                field.links.append(Link.from_table_column(link))
+
+        # TODO: Parse format into precision and width
+        return field
+
+
+class Param(Field):
+    """
+    PARAM_ element: constant-valued columns in the data.
+
+    :class:`Param` objects are a subclass of :class:`Field`, and have
+    all of its methods and members.  Additionally, it defines :attr:`value`.
+    """
+    _attr_list_11 = Field._attr_list_11 + ['value']
+    _attr_list_12 = Field._attr_list_12 + ['value']
+    _element_name = 'PARAM'
+
+    def __init__(self, votable, ID=None, name=None, value=None, datatype=None,
+                 arraysize=None, ucd=None, unit=None, width=None,
+                 precision=None, utype=None, type=None, id=None, config={},
+                 pos=None, **extra):
+        self._value = value
+        Field.__init__(self, votable, ID=ID, name=name, datatype=datatype,
+                       arraysize=arraysize, ucd=ucd, unit=unit,
+                       precision=precision, utype=utype, type=type,
+                       id=id, config=config, pos=pos, **extra)
+
+    @property
+    def value(self):
+        """
+        [*required*] The constant value of the parameter.  Its type is
+        determined by the :attr:`~Field.datatype` member.
+        """
+        return self._value
+
+    @value.setter
+    def value(self, value):
+        if value is None:
+            value = ""
+        if ((IS_PY3K and isinstance(value, unicode)) or
+            (not IS_PY3K and isinstance(value, string_types))):
+            self._value = self.converter.parse(
+                value, self._config, self._pos)[0]
+        else:
+            self._value = value
+
+    def _setup(self, config, pos):
+        Field._setup(self, config, pos)
+        self.value = self._value
+
+    def to_xml(self, w, **kwargs):
+        tmp_value = self._value
+        self._value = self.converter.output(tmp_value, False)
+        # We must always have a value
+        if self._value is None:
+            self._value = u""
+        Field.to_xml(self, w, **kwargs)
+        self._value = tmp_value
+
+
+class CooSys(SimpleElement):
+    """
+    COOSYS_ element: defines a coordinate system.
+
+    The keyword arguments correspond to setting members of the same
+    name, documented below.
+    """
+    _attr_list = ['ID', 'equinox', 'epoch', 'system']
+    _element_name = 'COOSYS'
+
+    def __init__(self, ID=None, equinox=None, epoch=None, system=None, id=None,
+                 config={}, pos=None, **extra):
+        self._config = config
+        self._pos = pos
+
+        if config.get('version_1_2_or_later'):
+            warn_or_raise(W27, W27, (), config, pos)
+
+        SimpleElement.__init__(self)
+
+        self.ID      = resolve_id(ID, id, config, pos)
+        self.equinox = equinox
+        self.epoch   = epoch
+        self.system  = system
+
+        warn_unknown_attrs('COOSYS', extra.iterkeys(), config, pos)
+
+    @property
+    def ID(self):
+        """
+        [*required*] The XML ID of the COOSYS_ element, used for
+        cross-referencing.  May be ``None`` or a string conforming to
+        XML ID_ syntax.
+        """
+        return self._ID
+
+    @ID.setter
+    def ID(self, ID):
+        if self._config.get('version_1_1_or_later'):
+            if ID is None:
+                vo_raise(E15, (), self._config, self._pos)
+        xmlutil.check_id(ID, 'ID', self._config, self._pos)
+        self._ID = ID
+
+    @property
+    def system(self):
+        """
+        Specifies the type of coordinate system.  Valid choices are:
+
+          'eq_FK4', 'eq_FK5', 'ICRS', 'ecl_FK4', 'ecl_FK5', 'galactic',
+          'supergalactic', 'xy', 'barycentric', or 'geo_app'
+        """
+        return self._system
+
+    @system.setter
+    def system(self, system):
+        if system not in ('eq_FK4', 'eq_FK5', 'ICRS', 'ecl_FK4', 'ecl_FK5',
+                          'galactic', 'supergalactic', 'xy', 'barycentric',
+                          'geo_app'):
+            warn_or_raise(E16, E16, system, self._config, self._pos)
+        self._system = system
+
+    @system.deleter
+    def system(self):
+        self._system = None
+
+    @property
+    def equinox(self):
+        """
+        A parameter required to fix the equatorial or ecliptic systems
+        (as e.g. "J2000" as the default "eq_FK5" or "B1950" as the
+        default "eq_FK4").
+        """
+        return self._equinox
+
+    @equinox.setter
+    def equinox(self, equinox):
+        check_astroyear(equinox, 'equinox', self._config, self._pos)
+        self._equinox = equinox
+
+    @equinox.deleter
+    def equinox(self):
+        self._equinox = None
+
+    @property
+    def epoch(self):
+        """
+        Specifies the epoch of the positions.  It must be a string
+        specifying an astronomical year.
+        """
+        return self._epoch
+
+    @epoch.setter
+    def epoch(self, epoch):
+        check_astroyear(epoch, 'epoch', self._config, self._pos)
+        self._epoch = epoch
+
+    @epoch.deleter
+    def epoch(self):
+        self._epoch = None
+
+
+class FieldRef(SimpleElement, _UtypeProperty, _UcdProperty):
+    """
+    FIELDref_ element: used inside of GROUP_ elements to refer to remote FIELD_ elements.
+    """
+    _attr_list_11 = ['ref']
+    _attr_list_12 = _attr_list_11 + ['ucd', 'utype']
+    _element_name = "FIELDref"
+    _utype_in_v1_2 = True
+    _ucd_in_v1_2 = True
+
+    def __init__(self, table, ref, ucd=None, utype=None, config={}, pos=None,
+                 **extra):
+        """
+        *table* is the :class:`Table` object that this :class:`FieldRef`
+        is a member of.
+
+        *ref* is the ID to reference a :class:`Field` object defined
+        elsewhere.
+        """
+        self._config = config
+        self._pos = pos
+
+        SimpleElement.__init__(self)
+        self._table = table
+        self.ref    = ref
+        self.ucd    = ucd
+        self.utype  = utype
+
+        if config.get('version_1_2_or_later'):
+            self._attr_list = self._attr_list_12
+        else:
+            self._attr_list = self._attr_list_11
+            if ucd is not None:
+                warn_unknown_attrs(self._element_name, ['ucd'], config, pos)
+            if utype is not None:
+                warn_unknown_attrs(self._element_name, ['utype'], config, pos)
+
+    @property
+    def ref(self):
+        """The ID_ of the FIELD_ that this FIELDref_ references."""
+        return self._ref
+
+    @ref.setter
+    def ref(self, ref):
+        xmlutil.check_id(ref, 'ref', self._config, self._pos)
+        self._ref = ref
+
+    @ref.deleter
+    def ref(self):
+        self._ref = None
+
+    def get_ref(self):
+        """
+        Lookup the :class:`Field` instance that this :class:`FieldRef`
+        references.
+        """
+        for field in self._table._votable.iter_fields_and_params():
+            if isinstance(field, Field) and field.ID == self.ref:
+                return field
+        vo_raise(
+            "No field named '%s'" % self.ref,
+            self._config, self._pos, KeyError)
+
+
+class ParamRef(SimpleElement, _UtypeProperty, _UcdProperty):
+    """
+    PARAMref_ element: used inside of GROUP_ elements to refer to remote PARAM_ elements.
+
+    The keyword arguments correspond to setting members of the same
+    name, documented below.
+
+    It contains the following publicly-accessible members:
+
+      *ref*: An XML ID refering to a <PARAM> element.
+    """
+    _attr_list_11 = ['ref']
+    _attr_list_12 = _attr_list_11 + ['ucd', 'utype']
+    _element_name = "PARAMref"
+    _utype_in_v1_2 = True
+    _ucd_in_v1_2 = True
+
+    def __init__(self, table, ref, ucd=None, utype=None, config={}, pos=None):
+        self._config = config
+        self._pos = pos
+
+        Element.__init__(self)
+        self._table = table
+        self.ref    = ref
+        self.ucd    = ucd
+        self.utype  = utype
+
+        if config.get('version_1_2_or_later'):
+            self._attr_list = self._attr_list_12
+        else:
+            self._attr_list = self._attr_list_11
+            if ucd is not None:
+                warn_unknown_attrs(self._element_name, ['ucd'], config, pos)
+            if utype is not None:
+                warn_unknown_attrs(self._element_name, ['utype'], config, pos)
+
+    @property
+    def ref(self):
+        """The ID_ of the PARAM_ that this PARAMref_ references."""
+        return self._ref
+
+    @ref.setter
+    def ref(self, ref):
+        xmlutil.check_id(ref, 'ref', self._config, self._pos)
+        self._ref = ref
+
+    @ref.deleter
+    def ref(self):
+        self._ref = None
+
+    def get_ref(self):
+        """
+        Lookup the :class:`Param` instance that this :class:`PARAMref`
+        references.
+        """
+        for param in self._table._votable.iter_fields_and_params():
+            if isinstance(param, Param) and param.ID == self.ref:
+                return param
+        vo_raise(
+            "No params named '%s'" % self.ref,
+            self._config, self._pos, KeyError)
+
+
+class Group(Element, _IDProperty, _NameProperty, _UtypeProperty,
+            _UcdProperty, _DescriptionProperty):
+    """
+    GROUP_ element: groups FIELD_ and PARAM_ elements.
+
+    This information is currently ignored by the vo package---that is
+    the columns in the recarray are always flat---but the grouping
+    information is stored so that it can be written out again to the
+    XML file.
+
+    The keyword arguments correspond to setting members of the same
+    name, documented below.
+    """
+
+    def __init__(self, table, ID=None, name=None, ref=None, ucd=None,
+                 utype=None, id=None, config={}, pos=None, **extra):
+        self._config     = config
+        self._pos        = pos
+
+        Element.__init__(self)
+        self._table = table
+
+        self.ID          = (resolve_id(ID, id, config, pos)
+                            or xmlutil.fix_id(name, config, pos))
+        self.name        = name
+        self.ref         = ref
+        self.ucd         = ucd
+        self.utype       = utype
+        self.description = None
+
+        self._entries = HomogeneousList(
+            (FieldRef, ParamRef, Group, Param))
+
+        warn_unknown_attrs('GROUP', extra.iterkeys(), config, pos)
+
+    @property
+    def ref(self):
+        """
+        Currently ignored, as it's not clear from the spec how this is
+        meant to work.
+        """
+        return self._ref
+
+    @ref.setter
+    def ref(self, ref):
+        xmlutil.check_id(ref, 'ref', self._config, self._pos)
+        self._ref = ref
+
+    @ref.deleter
+    def ref(self):
+        self._ref = None
+
+    @property
+    def entries(self):
+        """
+        [read-only] A list of members of the GROUP_.  This list may
+        only contain objects of type :class:`Param`, :class:`Group`,
+        :class:`ParamRef` and :class:`FieldRef`.
+        """
+        return self._entries
+
+    def _add_fieldref(self, iterator, tag, data, config, pos):
+        fieldref = FieldRef(self._table, config=config, pos=pos, **data)
+        self.entries.append(fieldref)
+
+    def _add_paramref(self, iterator, tag, data, config, pos):
+        paramref = ParamRef(self._table, config=config, pos=pos, **data)
+        self.entries.append(paramref)
+
+    def _add_param(self, iterator, tag, data, config, pos):
+        if isinstance(self._table, VOTableFile):
+            votable = self._table
+        else:
+            votable = self._table._votable
+        param = Param(votable, config=config, pos=pos, **data)
+        self.entries.append(param)
+        param.parse(iterator, config)
+
+    def _add_group(self, iterator, tag, data, config, pos):
+        group = Group(self._table, config=config, pos=pos, **data)
+        self.entries.append(group)
+        group.parse(iterator, config)
+
+    def parse(self, iterator, config):
+        tag_mapping = {
+            'FIELDref'    : self._add_fieldref,
+            'PARAMref'    : self._add_paramref,
+            'PARAM'       : self._add_param,
+            'GROUP'       : self._add_group,
+            'DESCRIPTION' : self._ignore_add}
+
+        for start, tag, data, pos in iterator:
+            if start:
+                tag_mapping.get(tag, self._add_unknown_tag)(
+                    iterator, tag, data, config, pos)
+            else:
+                if tag == 'DESCRIPTION':
+                    if self.description is not None:
+                        warn_or_raise(W17, W17, 'GROUP', config, pos)
+                    self.description = data or None
+                elif tag == 'GROUP':
+                    break
+        return self
+
+    def to_xml(self, w, **kwargs):
+        with w.tag(
+            u'GROUP',
+            attrib=w.object_attrs(
+                self, [u'ID', u'name', u'ref', u'ucd', u'utype'])):
+            if self.description is not None:
+                w.element(u"DESCRIPTION", self.description, wrap=True)
+            for entry in self.entries:
+                entry.to_xml(w, **kwargs)
+
+    def iter_fields_and_params(self):
+        """
+        Recursively iterate over all :class:`Param` elements in this
+        :class:`Group`.
+        """
+        for entry in self.entries:
+            if isinstance(entry, Param):
+                yield entry
+            elif isinstance(entry, Group):
+                for field in entry.iter_fields_and_params():
+                    yield field
+
+    def iter_groups(self):
+        """
+        Recursively iterate over all sub-:class:`Group` instances in
+        this :class:`Group`.
+        """
+        for entry in self.entries:
+            if isinstance(entry, Group):
+                yield entry
+                for group in entry.iter_groups():
+                    yield group
+
+
+class Table(Element, _IDProperty, _NameProperty, _UcdProperty,
+            _DescriptionProperty):
+    """
+    TABLE_ element: optionally contains data.
+
+    It contains the following publicly-accessible and mutable
+    attribute:
+
+        *array*: A Numpy masked array of the data itself, where each
+        row is a row of votable data, and columns are named and typed
+        based on the <FIELD> elements of the table.  The mask is
+        parallel to the data array, except for variable-length fields.
+        For those fields, the numpy array's column type is "object"
+        (``"O"``), and another masked array is stored there.
+
+    If the Table contains no data, (for example, its enclosing
+    :class:`Resource` has :attr:`~Resource.type` == 'meta') *array*
+    will have zero-length.
+
+    The keyword arguments correspond to setting members of the same
+    name, documented below.
+    """
+    def __init__(self, votable, ID=None, name=None, ref=None, ucd=None,
+                 utype=None, nrows=None, id=None, config={}, pos=None,
+                 **extra):
+        self._config = config
+        self._pos = pos
+        self._empty = False
+
+        Element.__init__(self)
+        self._votable = votable
+
+        self.ID = (resolve_id(ID, id, config, pos)
+                   or xmlutil.fix_id(name, config, pos))
+        self.name = name
+        xmlutil.check_id(ref, 'ref', config, pos)
+        self._ref = ref
+        self.ucd = ucd
+        self.utype = utype
+        if nrows is not None:
+            nrows = int(nrows)
+            assert nrows >= 0
+        self._nrows = nrows
+        self.description = None
+        self.format = 'tabledata'
+
+        self._fields = HomogeneousList(Field)
+        self._params = HomogeneousList(Param)
+        self._groups = HomogeneousList(Group)
+        self._links  = HomogeneousList(Link)
+        self._infos  = HomogeneousList(Info)
+
+        self.array = ma.array([])
+
+        warn_unknown_attrs('TABLE', extra.iterkeys(), config, pos)
+
+    @property
+    def ref(self):
+        return self._ref
+
+    @ref.setter
+    def ref(self, ref):
+        """
+        Refer to another TABLE, previously defined, by the *ref* ID_
+        for all metadata (FIELD_, PARAM_ etc.) information.
+        """
+        # When the ref changes, we want to verify that it will work
+        # by actually going and looking for the referenced table.
+        # If found, set a bunch of properties in this table based
+        # on the other one.
+        xmlutil.check_id(ref, 'ref', self._config, self._pos)
+        if ref is not None:
+            try:
+                table = self._votable.get_table_by_id(ref, before=self)
+            except KeyError:
+                warn_or_raise(
+                    W43, W43, ('TABLE', self.ref), self._config, self._pos)
+                ref = None
+            else:
+                self._fields = table.fields
+                self._params = table.params
+                self._groups = table.groups
+                self._links  = table.links
+        else:
+            del self._fields[:]
+            del self._params[:]
+            del self._groups[:]
+            del self._links[:]
+        self._ref = ref
+
+    @ref.deleter
+    def ref(self):
+        self._ref = None
+
+    @property
+    def format(self):
+        """
+        [*required*] The serialization format of the table.  Must be
+        one of:
+
+          'tabledata' (TABLEDATA_), 'binary' (BINARY_), 'fits' (FITS_).
+
+        Note that the 'fits' format, since it requires an external
+        file, can not be written out.  Any file read in with 'fits'
+        format will be read out, by default, in 'tabledata' format.
+        """
+        return self._format
+
+    @format.setter
+    def format(self, format):
+        format = format.lower()
+        if format == 'fits':
+            vo_raise("fits format can not be written out, only read.",
+                     self._config, self._pos, NotImplementedError)
+        if format not in ('tabledata', 'binary'):
+            vo_raise("Invalid format '%s'" % format,
+                     self._config, self._pos)
+        self._format = format
+
+    @property
+    def nrows(self):
+        """
+        [*immutable*] The number of rows in the table, as specified in
+        the XML file.
+        """
+        return self._nrows
+
+    @property
+    def fields(self):
+        """
+        A list of :class:`Field` objects describing the types of each
+        of the data columns.
+        """
+        return self._fields
+
+    @property
+    def params(self):
+        """
+        A list of parameters (constant-valued columns) for the
+        table.  Must contain only :class:`Param` objects.
+        """
+        return self._params
+
+    @property
+    def groups(self):
+        """
+        A list of :class:`Group` objects describing how the columns
+        and parameters are grouped.  Currently this information is
+        only kept around for round-tripping and informational
+        purposes.
+        """
+        return self._groups
+
+    @property
+    def links(self):
+        """
+        A list of :class:`Link` objects (pointers to other documents
+        or servers through a URI) for the table.
+        """
+        return self._links
+
+    @property
+    def infos(self):
+        """
+        A list of :class:`Info` objects for the table.  Allows for
+        post-operational diagnostics.
+        """
+        return self._infos
+
+    def is_empty(self):
+        """
+        Returns True if this table doesn't contain any real data
+        because it was skipped over by the parser (through use of the
+        `table_number` kwarg).
+        """
+        return self._empty
+
+    def create_arrays(self, nrows=0, config={}):
+        """
+        Create a new array to hold the data based on the current set
+        of fields, and store them in the *array* and member variable.
+        Any data in the existing array will be lost.
+
+        *nrows*, if provided, is the number of rows to allocate.
+        """
+        if nrows is None:
+            nrows = 0
+
+        fields = self.fields
+
+        if len(fields) == 0:
+            array = np.recarray((nrows,), dtype='O')
+            mask = np.zeros((nrows,), dtype='b')
+        else:
+            # for field in fields: field._setup(config)
+            Field.uniqify_names(fields)
+
+            dtype = []
+            for x in fields:
+                if IS_PY3K:
+                    if x._unique_name == x.ID:
+                        id = x.ID
+                    else:
+                        id = (x._unique_name, x.ID)
+                else:
+                    if x._unique_name == x.ID:
+                        id = x.ID.encode('utf-8')
+                    else:
+                        id = (x._unique_name.encode('utf-8'),
+                              x.ID.encode('utf-8'))
+                dtype.append((id, x.converter.format))
+
+            array = np.recarray((nrows,), dtype=np.dtype(dtype))
+            descr_mask = []
+            for d in array.dtype.descr:
+                new_type = (d[1][1] == 'O' and 'O') or 'bool'
+                if len(d) == 2:
+                    descr_mask.append((d[0], new_type))
+                elif len(d) == 3:
+                    descr_mask.append((d[0], new_type, d[2]))
+            mask = np.zeros((nrows,), dtype=descr_mask)
+
+        self.array = ma.array(array, mask=mask)
+
+    def _resize_strategy(self, size):
+        """
+        Return a new (larger) size based on size, used for
+        reallocating an array when it fills up.  This is in its own
+        function so the resizing strategy can be easily replaced.
+        """
+        # Once we go beyond 0, make a big step -- after that use a
+        # factor of 1.5 to help keep memory usage compact
+        if size == 0:
+            return 512
+        return int(np.ceil(size * RESIZE_AMOUNT))
+
+    def _add_field(self, iterator, tag, data, config, pos):
+        field = Field(self._votable, config=config, pos=pos, **data)
+        self.fields.append(field)
+        field.parse(iterator, config)
+
+    def _add_param(self, iterator, tag, data, config, pos):
+        param = Param(self._votable, config=config, pos=pos, **data)
+        self.params.append(param)
+        param.parse(iterator, config)
+
+    def _add_group(self, iterator, tag, data, config, pos):
+        group = Group(self, config=config, pos=pos, **data)
+        self.groups.append(group)
+        group.parse(iterator, config)
+
+    def _add_link(self, iterator, tag, data, config, pos):
+        link = Link(config=config, pos=pos, **data)
+        self.links.append(link)
+        link.parse(iterator, config)
+
+    def parse(self, iterator, config):
+        columns = config.get('columns')
+
+        # If we've requested to read in only a specific table, skip
+        # all others
+        table_number = config.get('table_number')
+        current_table_number = config.get('_current_table_number')
+        skip_table = False
+        if current_table_number is not None:
+            config['_current_table_number'] += 1
+            if (table_number is not None and
+                table_number != current_table_number):
+                skip_table = True
+                self._empty = True
+
+        table_id = config.get('table_id')
+        if table_id is not None:
+            if table_id != self.ID:
+                skip_table = True
+                self._empty = True
+
+        if self.ref is not None:
+            # This table doesn't have its own datatype descriptors, it
+            # just references those from another table.
+
+            # This is to call the property setter to go and get the
+            # referenced information
+            self.ref = self.ref
+
+            for start, tag, data, pos in iterator:
+                if start:
+                    if tag == 'DATA':
+                        warn_unknown_attrs(
+                            'DATA', data.iterkeys(), config, pos)
+                        break
+                else:
+                    if tag == 'TABLE':
+                        return self
+                    elif tag == 'DESCRIPTION':
+                        if self.description is not None:
+                            warn_or_raise(W17, W17, 'RESOURCE', config, pos)
+                        self.description = data or None
+        else:
+            tag_mapping = {
+                'FIELD'       : self._add_field,
+                'PARAM'       : self._add_param,
+                'GROUP'       : self._add_group,
+                'LINK'        : self._add_link,
+                'DESCRIPTION' : self._ignore_add}
+
+            for start, tag, data, pos in iterator:
+                if start:
+                    if tag == 'DATA':
+                        warn_unknown_attrs(
+                            'DATA', data.iterkeys(), config, pos)
+                        break
+
+                    tag_mapping.get(tag, self._add_unknown_tag)(
+                        iterator, tag, data, config, pos)
+                else:
+                    if tag == 'DESCRIPTION':
+                        if self.description is not None:
+                            warn_or_raise(W17, W17, 'RESOURCE', config, pos)
+                        self.description = data or None
+                    elif tag == 'TABLE':
+                        # For error checking purposes
+                        Field.uniqify_names(self.fields)
+                        return self
+
+        self.create_arrays(nrows=self._nrows, config=config)
+        fields = self.fields
+        names = [x.ID for x in fields]
+        # Deal with a subset of the columns, if requested.
+        if not columns:
+            colnumbers = range(len(fields))
+        else:
+            if isinstance(columns, string_types):
+                columns = [columns]
+            columns = np.asarray(columns)
+            if issubclass(columns.dtype.type, np.integer):
+                if np.any(columns < 0) or np.any(columns > len(fields)):
+                    raise ValueError(
+                        "Some specified column numbers out of range")
+                colnumbers = columns
+            elif issubclass(columns.dtype.type, np.character):
+                try:
+                    colnumbers = [names.index(x) for x in columns]
+                except ValueError:
+                    raise ValueError(
+                        "Columns '%s' not found in fields list" % columns)
+            else:
+                raise TypeError("Invalid columns list")
+
+        if not skip_table:
+            for start, tag, data, pos in iterator:
+                if start:
+                    if tag == 'TABLEDATA':
+                        warn_unknown_attrs(
+                            'TABLEDATA', data.iterkeys(), config, pos)
+                        self.array = self._parse_tabledata(
+                            iterator, colnumbers, fields, config)
+                        break
+                    elif tag == 'BINARY':
+                        warn_unknown_attrs(
+                            'BINARY', data.iterkeys(), config, pos)
+                        self.array = self._parse_binary(
+                            iterator, colnumbers, fields, config)
+                        break
+                    elif tag == 'FITS':
+                        warn_unknown_attrs(
+                            'FITS', data.iterkeys(), config, pos, ['extnum'])
+                        try:
+                            extnum = int(data.get('extnum', 0))
+                            if extnum < 0:
+                                raise ValueError()
+                        except ValueError:
+                            vo_raise(E17, (), config, pos)
+                        self.array = self._parse_fits(
+                            iterator, extnum, config)
+                        break
+                    else:
+                        warn_or_raise(W37, W37, tag, config, pos)
+                        break
+
+        for start, tag, data, pos in iterator:
+            if not start and tag == 'DATA':
+                break
+
+        for start, tag, data, pos in iterator:
+            if tag == 'INFO':
+                if start:
+                    if not config.get('version_1_2_or_later'):
+                        warn_or_raise(
+                            W26, W26, ('INFO', 'TABLE', '1.2'), config, pos)
+                    info = Info(config=config, pos=pos, **data)
+                    self.infos.append(info)
+                    info.parse(iterator, config)
+                else:
+                    info.content = data
+            elif not start and tag == 'TABLE':
+                break
+
+        return self
+
+    def _parse_tabledata(self, iterator, colnumbers, fields, config):
+        # Since we don't know the number of rows up front, we'll
+        # reallocate the record array to make room as we go.  This
+        # prevents the need to scan through the XML twice.  The
+        # allocation is by factors of 1.5.
+        invalid = config.get('invalid', 'exception')
+
+        # Need to have only one reference so that we can resize the
+        # array
+        array = self.array
+        del self.array
+
+        parsers = [field.converter.parse for field in fields]
+        binparsers = [field.converter.binparse for field in fields]
+
+        numrows = 0
+        alloc_rows = len(array)
+        colnumbers_bits = [i in colnumbers for i in range(len(fields))]
+        row_default = [x.converter.default for x in fields]
+        mask_default = [True] * len(fields)
+        array_chunk = []
+        mask_chunk = []
+        chunk_size = config.get('chunk_size', DEFAULT_CHUNK_SIZE)
+        for start, tag, data, pos in iterator:
+            if tag == 'TR':
+                # Now parse one row
+                row = row_default[:]
+                row_mask = mask_default[:]
+                i = 0
+                for start, tag, data, pos in iterator:
+                    if start:
+                        binary = (data.get('encoding', None) == 'base64')
+                        warn_unknown_attrs(
+                            tag, data.iterkeys(), config, pos, ['encoding'])
+                    else:
+                        if tag == 'TD':
+                            if i >= len(fields):
+                                vo_raise(E20, len(fields), config, pos)
+
+                            if colnumbers_bits[i]:
+                                try:
+                                    if binary:
+                                        import base64
+                                        rawdata = base64.b64decode(
+                                            data.encode('ascii'))
+                                        buf = io.BytesIO(rawdata)
+                                        buf.seek(0)
+                                        try:
+                                            value, mask_value = binparsers[i](
+                                                buf.read)
+                                        except Exception as e:
+                                            vo_reraise(
+                                                e, config, pos,
+                                                "(in row %d, col '%s')" %
+                                                (len(array_chunk),
+                                                 fields[i].ID))
+                                    else:
+                                        try:
+                                            value, mask_value = parsers[i](
+                                                data, config, pos)
+                                        except Exception as e:
+                                            vo_reraise(
+                                                e, config, pos,
+                                                "(in row %d, col '%s')" %
+                                                (len(array_chunk),
+                                                 fields[i].ID))
+                                except Exception as e:
+                                    if invalid == 'exception':
+                                        vo_reraise(e, config, pos)
+                                else:
+                                    row[i] = value
+                                    row_mask[i] = mask_value
+                        elif tag == 'TR':
+                            break
+                        else:
+                            self._add_unknown_tag(
+                                iterator, tag, data, config, pos)
+                        i += 1
+
+                if i < len(fields):
+                    vo_raise(E21, (i, len(fields)), config, pos)
+
+                array_chunk.append(tuple(row))
+                mask_chunk.append(tuple(row_mask))
+
+                if len(array_chunk) == chunk_size:
+                    while numrows + chunk_size > alloc_rows:
+                        alloc_rows = self._resize_strategy(alloc_rows)
+                    if alloc_rows != len(array):
+                        array = _resize(array, alloc_rows)
+                    array[numrows:numrows + chunk_size] = array_chunk
+                    array.mask[numrows:numrows + chunk_size] = mask_chunk
+                    numrows += chunk_size
+                    array_chunk = []
+                    mask_chunk = []
+
+            elif not start and tag == 'TABLEDATA':
+                break
+
+        # Now, resize the array to the exact number of rows we need and
+        # put the last chunk values in there.
+        alloc_rows = numrows + len(array_chunk)
+
+        array = _resize(array, alloc_rows)
+        array[numrows:] = array_chunk
+        if alloc_rows != 0:
+            array.mask[numrows:] = mask_chunk
+        numrows += len(array_chunk)
+
+        if (self.nrows is not None and
+            self.nrows >= 0 and
+            self.nrows != numrows):
+            warn_or_raise(W18, W18, (self.nrows, numrows), config, pos)
+        self._nrows = numrows
+
+        return array
+
+    def _parse_binary(self, iterator, colnumbers, fields, config):
+        fields = self.fields
+
+        have_local_stream = False
+        for start, tag, data, pos in iterator:
+            if tag == 'STREAM':
+                if start:
+                    warn_unknown_attrs(
+                        'STREAM', data.iterkeys(), config, pos,
+                        ['type', 'href', 'actuate', 'encoding', 'expires',
+                         'rights'])
+                    if 'href' not in data:
+                        have_local_stream = True
+                        if data.get('encoding', None) != 'base64':
+                            warn_or_raise(
+                                W38, W38, data.get('encoding', None),
+                                config, pos)
+                    else:
+                        href = data['href']
+                        xmlutil.check_anyuri(href, config, pos)
+                        encoding = data.get('encoding', None)
+                else:
+                    buffer = data
+                    break
+
+        if have_local_stream:
+            import base64
+            buffer = base64.b64decode(buffer.encode('ascii'))
+            string_io = io.BytesIO(buffer)
+            string_io.seek(0)
+            read = string_io.read
+        else:
+            if not (href.startswith('http') or
+                    href.startswith('ftp') or
+                    href.startswith('file')):
+                vo_raise(
+                    "The vo package only supports remote data through http, " +
+                    "ftp or file",
+                    self._config, self._pos, NotImplementedError)
+            import urllib2
+            fd = urllib2.urlopen(href)
+            if encoding is not None:
+                if encoding == 'gzip':
+                    from ...utils.compat import gzip
+                    fd = gzip.GzipFile(href, 'rb', fileobj=fd)
+                elif encoding == 'base64':
+                    fd = codecs.EncodedFile(fd, 'base64')
+                else:
+                    vo_raise(
+                        "Unknown encoding type '%s'" % encoding,
+                        self._config, self._pos, NotImplementedError)
+            read = fd.read
+
+        def careful_read(length):
+            result = read(length)
+            if len(result) != length:
+                raise EOFError
+            return result
+
+        # Need to have only one reference so that we can resize the
+        # array
+        array = self.array
+        del self.array
+
+        binparsers = [field.converter.binparse for field in fields]
+
+        numrows = 0
+        alloc_rows = len(array)
+        while True:
+            # Resize result arrays if necessary
+            if numrows >= alloc_rows:
+                alloc_rows = self._resize_strategy(alloc_rows)
+                array = _resize(array, alloc_rows)
+
+            row_data = []
+            row_mask_data = []
+            try:
+                for i, binparse in enumerate(binparsers):
+                    try:
+                        value, value_mask = binparse(careful_read)
+                    except EOFError:
+                        raise
+                    except Exception as e:
+                        vo_reraise(e, config, pos,
+                                   "(in row %d, col '%s')" %
+                                   (numrows, fields[i].ID))
+                    row_data.append(value)
+                    row_mask_data.append(value_mask)
+            except EOFError:
+                break
+
+            row = [x.converter.default for x in fields]
+            row_mask = [False] * len(fields)
+            for i in colnumbers:
+                row[i] = row_data[i]
+                row_mask[i] = row_mask_data[i]
+
+            array[numrows] = tuple(row)
+            array.mask[numrows] = tuple(row_mask)
+            numrows += 1
+
+        array = _resize(array, numrows)
+
+        return array
+
+    def _parse_fits(self, iterator, extnum, config):
+        for start, tag, data, pos in iterator:
+            if tag == 'STREAM':
+                if start:
+                    warn_unknown_attrs(
+                        'STREAM', data.iterkeys(), config, pos,
+                        ['type', 'href', 'actuate', 'encoding', 'expires',
+                         'rights'])
+                    href = data['href']
+                    encoding = data.get('encoding', None)
+                else:
+                    break
+
+        if not (href.startswith('http') or
+                href.startswith('ftp') or
+                href.startswith('file')):
+            vo_raise(
+                "The vo package only supports remote data through http, "
+                "ftp or file",
+                self._config, self._pos, NotImplementedError)
+
+        import urllib2
+        fd = urllib2.urlopen(href)
+        if encoding is not None:
+            if encoding == 'gzip':
+                from ...utils.compat import gzip
+                fd = gzip.GzipFile(href, 'r', fileobj=fd)
+            elif encoding == 'base64':
+                fd = codecs.EncodedFile(fd, 'base64')
+            else:
+                vo_raise(
+                    "Unknown encoding type '%s'" % encoding,
+                    self._config, self._pos, NotImplementedError)
+
+        hdulist = fits.open(fd)
+
+        array = hdulist[int(extnum)].data
+        if array.dtype != self.array.dtype:
+            warn_or_raise(W19, W19, (), self._config, self._pos)
+
+        return array
+
+    def to_xml(self, w, **kwargs):
+        with w.tag(
+            u'TABLE',
+            attrib=w.object_attrs(
+                self,
+                (u'ID', u'name', u'ref', u'ucd', u'utype', u'nrows'))):
+
+            if self.description is not None:
+                w.element(u"DESCRIPTION", self.description, wrap=True)
+
+            for element_set in (self.fields, self.params):
+                for element in element_set:
+                    element._setup({}, None)
+
+            if self.ref is None:
+                for element_set in (self.fields, self.params, self.groups,
+                                    self.links):
+                    for element in element_set:
+                        element.to_xml(w, **kwargs)
+
+            if len(self.array):
+                with w.tag(u'DATA'):
+                    if self.format == u'fits':
+                        self.format = u'tabledata'
+
+                    if self.format == u'tabledata':
+                        self._write_tabledata(w, **kwargs)
+                    elif self.format == u'binary':
+                        self._write_binary(w, **kwargs)
+
+            if self.ref is None and kwargs['version_1_2_or_later']:
+                for element in self._infos:
+                    element.to_xml(w, **kwargs)
+
+    def _write_tabledata(self, w, **kwargs):
+        fields = self.fields
+        array = self.array
+
+        write_null_values = kwargs.get('write_null_values', False)
+        with w.tag(u'TABLEDATA'):
+            w._flush()
+            if (_has_c_tabledata_writer and
+                not kwargs.get('_debug_python_based_parser')):
+                fields = [field.converter.output for field in fields]
+                indent = len(w._tags) - 1
+                tablewriter.write_tabledata(
+                    w.write, array.data, array.mask, fields, write_null_values,
+                    indent, 1 << 8)
+            else:
+                write = w.write
+                indent_spaces = w.get_indentation_spaces()
+                tr_start = indent_spaces + u"<TR>\n"
+                tr_end = indent_spaces + u"</TR>\n"
+                td = indent_spaces + u" <TD>%s</TD>\n"
+                td_empty = indent_spaces + u" <TD/>\n"
+                fields = [(i, field.converter.output)
+                          for i, field in enumerate(fields)]
+                for row in xrange(len(array)):
+                    write(tr_start)
+                    array_row = array.data[row]
+                    mask_row = array.mask[row]
+                    for i, output in fields:
+                        data = array_row[i]
+                        masked = mask_row[i]
+                        if (not np.all(masked) or
+                            write_null_values):
+                            try:
+                                val = output(data, masked)
+                            except Exception as e:
+                                vo_reraise(e,
+                                           additional="(in row %d, col '%s')" %
+                                           (row, self.fields[i].ID))
+                            if len(val):
+                                write(td % val)
+                            else:
+                                write(td_empty)
+                        else:
+                            write(td_empty)
+                    write(tr_end)
+
+    def _write_binary(self, w, **kwargs):
+        import base64
+
+        fields = self.fields
+        array = self.array
+
+        with w.tag(u'BINARY'):
+            with w.tag(u'STREAM', encoding='base64'):
+                fields_basic = [(i, field.converter.binoutput)
+                                for (i, field) in enumerate(fields)]
+
+                data = io.BytesIO()
+                for row in xrange(len(array)):
+                    array_row = array.data[row]
+                    array_mask = array.mask[row]
+                    for i, converter in fields_basic:
+                        try:
+                            chunk = converter(array_row[i], array_mask[i])
+                            assert type(chunk) == type(b'')
+                        except Exception as e:
+                            vo_reraise(e,
+                                       additional="(in row %d, col '%s')" %
+                                       (row, fields[i].ID))
+                        data.write(chunk)
+
+                w._flush()
+                w.write(base64.b64encode(data.getvalue()).decode('ascii'))
+
+    def to_table(self):
+        """
+        Convert this VO Table to an `astropy.table.Table` instance.
+
+        .. warning::
+
+           Variable-length array fields may not be restored
+           identically when round-tripping through the
+           `astropy.table.Table` instance.
+        """
+        from ...table import Table
+
+        meta = {}
+        for key in [u'ID', u'name', u'ref', u'ucd', u'utype', u'description']:
+            val = getattr(self, key, None)
+            if val is not None:
+                meta[key] = val
+
+        table = Table(self.array, meta=meta)
+
+        for field in self.fields:
+            column = table[field.ID]
+            field.to_table_column(column)
+
+        return table
+
+    @classmethod
+    def from_table(cls, votable, table):
+        """
+        Create a `Table` instance from a given `astropy.table.Table`
+        instance.
+        """
+        kwargs = {}
+        for key in [u'ID', u'name', u'ref', u'ucd', u'utype']:
+            val = table.meta.get(key)
+            if val is not None:
+                kwargs[key] = val
+        new_table = cls(votable, **kwargs)
+        if 'description' in table.meta:
+            new_table.description = table.meta['description']
+
+        for colname in table.colnames:
+            column = table[colname]
+            new_table.fields.append(Field.from_table_column(votable, column))
+
+        new_table.array = ma.array(np.asarray(table), mask=table.mask)
+
+        return new_table
+
+    def iter_fields_and_params(self):
+        """
+        Recursively iterate over all FIELD and PARAM elements in the
+        TABLE.
+        """
+        for param in self.params:
+            yield param
+        for field in self.fields:
+            yield field
+        for group in self.groups:
+            for field in group.iter_fields_and_params():
+                yield field
+
+    get_field_by_id = _lookup_by_id_factory(
+        'iter_fields_and_params', 'FIELD or PARAM',
+        """
+        Looks up a FIELD or PARAM element by the given ID.
+        """)
+
+    get_field_by_id_or_name = _lookup_by_id_or_name_factory(
+        'iter_fields_and_params', 'FIELD or PARAM',
+        """
+        Looks up a FIELD or PARAM element by the given ID or name.
+        """)
+
+    def iter_groups(self):
+        """
+        Recursively iterate over all GROUP elements in the TABLE.
+        """
+        for group in self.groups:
+            yield group
+            for g in group.iter_groups():
+                yield g
+
+    get_group_by_id = _lookup_by_id_factory(
+        'iter_groups', 'GROUP',
+        """
+        Looks up a GROUP element by the given ID.  Used by the group's
+        "ref" attribute
+        """)
+
+
+
+class Resource(Element, _IDProperty, _NameProperty, _UtypeProperty,
+               _DescriptionProperty):
+    """
+    RESOURCE_ element: Groups TABLE_ and RESOURCE_ elements.
+
+    The keyword arguments correspond to setting members of the same
+    name, documented below.
+    """
+    def __init__(self, name=None, ID=None, utype=None, type='results',
+                 id=None, config={}, pos=None, **kwargs):
+        self._config           = config
+        self._pos              = pos
+
+        Element.__init__(self)
+        self.name              = name
+        self.ID                = resolve_id(ID, id, config, pos)
+        self.utype             = utype
+        self.type              = type
+        self._extra_attributes = kwargs
+        self.description       = None
+
+        self._coordinate_systems = HomogeneousList(CooSys)
+        self._params             = HomogeneousList(Param)
+        self._infos              = HomogeneousList(Info)
+        self._links              = HomogeneousList(Link)
+        self._tables             = HomogeneousList(Table)
+        self._resources          = HomogeneousList(Resource)
+
+        warn_unknown_attrs('RESOURCE', kwargs.iterkeys(), config, pos)
+
+    @property
+    def type(self):
+        """
+        [*required*] The type of the resource.  Must be either:
+
+          - 'results': This resource contains actual result values
+            (default)
+
+          - 'meta': This resource contains only datatype descriptions
+            (FIELD_ elements), but no actual data.
+        """
+        return self._type
+
+    @type.setter
+    def type(self, type):
+        if type not in ('results', 'meta'):
+            vo_raise(E18, type, self._config, self._pos)
+        self._type = type
+
+    @property
+    def extra_attributes(self):
+        """
+        A dictionary of string keys to string values containing any
+        extra attributes of the RESOURCE_ element that are not defined
+        in the specification.  (The specification explicitly allows
+        for extra attributes here, but nowhere else.)
+        """
+        return self._extra_attributes
+
+    @property
+    def coordinate_systems(self):
+        """
+        A list of coordinate system definitions (COOSYS_ elements) for
+        the RESOURCE_.  Must contain only `CooSys` objects.
+        """
+        return self._coordinate_systems
+
+    @property
+    def infos(self):
+        """
+        A list of informational parameters (key-value pairs) for the
+        resource.  Must only contain `Info` objects.
+        """
+        return self._infos
+
+    @property
+    def params(self):
+        """
+        A list of parameters (constant-valued columns) for the
+        resource.  Must contain only `Param` objects.
+        """
+        return self._params
+
+    @property
+    def links(self):
+        """
+        A list of links (pointers to other documents or servers
+        through a URI) for the resource.  Must contain only `Link`
+        objects.
+        """
+        return self._links
+
+    @property
+    def tables(self):
+        """
+        A list of tables in the resource.  Must contain only
+        `Table` objects.
+        """
+        return self._tables
+
+    @property
+    def resources(self):
+        """
+        A list of nested resources inside this resource.  Must contain
+        only `Resource` objects.
+        """
+        return self._resources
+
+    def _add_table(self, iterator, tag, data, config, pos):
+        table = Table(self._votable, config=config, pos=pos, **data)
+        self.tables.append(table)
+        table.parse(iterator, config)
+
+    def _add_info(self, iterator, tag, data, config, pos):
+        info = Info(config=config, pos=pos, **data)
+        self.infos.append(info)
+        info.parse(iterator, config)
+
+    def _add_param(self, iterator, tag, data, config, pos):
+        param = Param(self._votable, config=config, pos=pos, **data)
+        self.params.append(param)
+        param.parse(iterator, config)
+
+    def _add_coosys(self, iterator, tag, data, config, pos):
+        coosys = CooSys(config=config, pos=pos, **data)
+        self.coordinate_systems.append(coosys)
+        coosys.parse(iterator, config)
+
+    def _add_resource(self, iterator, tag, data, config, pos):
+        resource = Resource(config=config, pos=pos, **data)
+        self.resources.append(resource)
+        resource.parse(self._votable, iterator, config)
+
+    def _add_link(self, iterator, tag, data, config, pos):
+        link = Link(config=config, pos=pos, **data)
+        self.links.append(link)
+        link.parse(iterator, config)
+
+    def parse(self, votable, iterator, config):
+        self._votable = votable
+
+        tag_mapping = {
+            'TABLE'       : self._add_table,
+            'INFO'        : self._add_info,
+            'PARAM'       : self._add_param,
+            'COOSYS'      : self._add_coosys,
+            'RESOURCE'    : self._add_resource,
+            'LINK'        : self._add_link,
+            'DESCRIPTION' : self._ignore_add
+            }
+
+        for start, tag, data, pos in iterator:
+            if start:
+                tag_mapping.get(tag, self._add_unknown_tag)(
+                    iterator, tag, data, config, pos)
+            elif tag == 'DESCRIPTION':
+                if self.description is not None:
+                    warn_or_raise(W17, W17, 'RESOURCE', config, pos)
+                self.description = data or None
+            elif tag == 'INFO':
+                self.infos[-1].content = data
+
+        del self._votable
+
+        return self
+
+    def to_xml(self, w, **kwargs):
+        attrs = w.object_attrs(self, (u'ID', u'type', u'utype'))
+        attrs.update(self.extra_attributes)
+        with w.tag(u'RESOURCE', attrib=attrs):
+            if self.description is not None:
+                w.element(u"DESCRIPTION", self.description, wrap=True)
+            for element_set in (self.coordinate_systems, self.params,
+                                self.infos, self.links, self.tables,
+                                self.resources):
+                for element in element_set:
+                    element.to_xml(w, **kwargs)
+
+    def iter_tables(self):
+        """
+        Recursively iterates over all tables in the resource and
+        nested resources.
+        """
+        for table in self.tables:
+            yield table
+        for resource in self.resources:
+            for table in resource.iter_tables():
+                yield table
+
+    def iter_fields_and_params(self):
+        """
+        Recursively iterates over all FIELD_ and PARAM_ elements in
+        the resource, its tables and nested resources.
+        """
+        for param in self.params:
+            yield param
+        for table in self.tables:
+            for param in table.iter_fields_and_params():
+                yield param
+        for resource in self.resources:
+            for param in resource.iter_fields_and_params():
+                yield param
+
+    def iter_coosys(self):
+        """
+        Recursively iterates over all the COOSYS_ elements in the
+        resource and nested resources.
+        """
+        for coosys in self.coordinate_systems:
+            yield coosys
+        for resource in self.resources:
+            for coosys in resource.iter_coosys():
+                yield coosys
+
+
+class VOTableFile(Element, _IDProperty, _DescriptionProperty):
+    """
+    VOTABLE_ element: represents an entire file.
+
+    The keyword arguments correspond to setting members of the same
+    name, documented below.
+
+    *version* is settable at construction time only, since conformance
+    tests for building the rest of the structure depend on it.
+    """
+
+    def __init__(self, ID=None, id=None, config={}, pos=None, version="1.2"):
+        self._config             = config
+        self._pos                = pos
+
+        Element.__init__(self)
+        self.ID                  = resolve_id(ID, id, config, pos)
+        self.description         = None
+
+        self._coordinate_systems = HomogeneousList(CooSys)
+        self._params             = HomogeneousList(Param)
+        self._infos              = HomogeneousList(Info)
+        self._resources          = HomogeneousList(Resource)
+        self._groups             = HomogeneousList(Group)
+
+        version = str(version)
+        assert version in ("1.0", "1.1", "1.2")
+        self._version            = version
+
+    @property
+    def version(self):
+        """
+        The version of the VOTable specification that the file uses.
+        """
+        return self._version
+
+    @property
+    def coordinate_systems(self):
+        """
+        A list of coordinate system descriptions for the file.  Must
+        contain only `CooSys` objects.
+        """
+        return self._coordinate_systems
+
+    @property
+    def params(self):
+        """
+        A list of parameters (constant-valued columns) that apply to
+        the entire file.  Must contain only `Param` objects.
+        """
+        return self._params
+
+    @property
+    def infos(self):
+        """
+        A list of informational parameters (key-value pairs) for the
+        entire file.  Must only contain `Info` objects.
+        """
+        return self._infos
+
+    @property
+    def resources(self):
+        """
+        A list of resources, in the order they appear in the file.
+        Must only contain `Resource` objects.
+        """
+        return self._resources
+
+    @property
+    def groups(self):
+        """
+        A list of groups, in the order they appear in the file.  Only
+        supported as a child of the VOTABLE element in VOTable 1.2 or
+        later.
+        """
+        return self._groups
+
+    def _add_param(self, iterator, tag, data, config, pos):
+        param = Param(self, config=config, pos=pos, **data)
+        self.params.append(param)
+        param.parse(iterator, config)
+
+    def _add_resource(self, iterator, tag, data, config, pos):
+        resource = Resource(config=config, pos=pos, **data)
+        self.resources.append(resource)
+        resource.parse(self, iterator, config)
+
+    def _add_coosys(self, iterator, tag, data, config, pos):
+        coosys = CooSys(config=config, pos=pos, **data)
+        self.coordinate_systems.append(coosys)
+        coosys.parse(iterator, config)
+
+    def _add_info(self, iterator, tag, data, config, pos):
+        info = Info(config=config, pos=pos, **data)
+        self.infos.append(info)
+        info.parse(iterator, config)
+
+    def _add_group(self, iterator, tag, data, config, pos):
+        if not config.get('version_1_2_or_later'):
+            warn_or_raise(W26, W26, ('GROUP', 'VOTABLE', '1.2'), config, pos)
+        group = Group(self, config=config, pos=pos, **data)
+        self.groups.append(group)
+        group.parse(iterator, config)
+
+    def parse(self, iterator, config):
+        config['_current_table_number'] = 0
+
+        for start, tag, data, pos in iterator:
+            if start:
+                if tag == 'xml':
+                    pass
+                elif tag == 'VOTABLE':
+                    if 'version' not in data:
+                        warn_or_raise(W20, W20, self.version, config, pos)
+                        config['version'] = self.version
+                    else:
+                        config['version'] = self._version = data['version']
+                        if config['version'].lower().startswith('v'):
+                            warn_or_raise(
+                                W29, W29, config['version'], config, pos)
+                            self._version = config['version'] = \
+                                            config['version'][1:]
+                        if config['version'] not in ('1.1', '1.2'):
+                            vo_warn(W21, config['version'], config, pos)
+
+                    if 'xmlns' in data:
+                        correct_ns = ('http://www.ivoa.net/xml/VOTable/v%s' %
+                                      config['version'])
+                        if data['xmlns'] != correct_ns:
+                            vo_warn(
+                                W41, (correct_ns, data['xmlns']), config, pos)
+                    else:
+                        vo_warn(W42, (), config, pos)
+
+                    break
+                else:
+                    vo_raise(E19, (), config, pos)
+        config['version_1_1_or_later'] = \
+            util.version_compare(config['version'], '1.1') >= 0
+        config['version_1_2_or_later'] = \
+            util.version_compare(config['version'], '1.2') >= 0
+
+        tag_mapping = {
+            'PARAM'       : self._add_param,
+            'RESOURCE'    : self._add_resource,
+            'COOSYS'      : self._add_coosys,
+            'INFO'        : self._add_info,
+            'DEFINITIONS' : self._add_definitions,
+            'DESCRIPTION' : self._ignore_add,
+            'GROUP'       : self._add_group}
+
+        for start, tag, data, pos in iterator:
+            if start:
+                tag_mapping.get(tag, self._add_unknown_tag)(
+                    iterator, tag, data, config, pos)
+            elif tag == 'DESCRIPTION':
+                if self.description is not None:
+                    warn_or_raise(W17, W17, 'VOTABLE', config, pos)
+                self.description = data or None
+            elif tag == 'INFO':
+                self.infos[-1].content = data
+        return self
+
+    def to_xml(self, fd, write_null_values=False,
+               compressed=False,
+               _debug_python_based_parser=False,
+               _astropy_version=None):
+        """
+        Write to an XML file.
+
+        Parameters
+        ----------
+        fd : str path or writable file-like object
+           Where to write the file.
+
+        write_null_values : bool, optional
+           When `True`, write the 'null' value (specified in the null
+           attribute of the VALUES element for each FIELD) for empty
+           values.  When False (default), simply write no value.
+
+        compressed : bool, optional
+           When `True`, write to a gzip-compressed file.  (Default:
+           `False`)
+        """
+        kwargs = {
+            'write_null_values': write_null_values,
+            'version': self.version,
+            'version_1_1_or_later':
+                util.version_compare(self.version, u'1.1') >= 0,
+            'version_1_2_or_later':
+                util.version_compare(self.version, u'1.2') >= 0,
+            '_debug_python_based_parser': _debug_python_based_parser}
+
+        with util.convert_to_writable_filelike(
+            fd, compressed=compressed) as fd:
+            w = XMLWriter(fd)
+            version = self.version
+            if _astropy_version is None:
+                lib_version = astropy_version
+            else:
+                lib_version = _astropy_version
+
+            xml_header = u"""
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Produced with astropy.io.votable version %(lib_version)s
+     http://www.astropy.org/ -->\n"""
+            w.write(xml_header.lstrip() % locals())
+
+            with w.tag(u'VOTABLE',
+                       {u'version': version,
+                        u'xmlns:xsi':
+                            u"http://www.w3.org/2001/XMLSchema-instance",
+                        u'xsi:noNamespaceSchemaLocation':
+                            u"http://www.ivoa.net/xml/VOTable/v%s" % version,
+                        u'xmlns':
+                            u"http://www.ivoa.net/xml/VOTable/v%s" % version}):
+                if self.description is not None:
+                    w.element(u"DESCRIPTION", self.description, wrap=True)
+                element_sets = [self.coordinate_systems, self.params,
+                                self.infos, self.resources]
+                if kwargs['version_1_2_or_later']:
+                    element_sets[0] = self.groups
+                for element_set in element_sets:
+                    for element in element_set:
+                        element.to_xml(w, **kwargs)
+
+    def iter_tables(self):
+        """
+        Iterates over all tables in the VOTable file in a "flat" way,
+        ignoring the nesting of resources etc.
+        """
+        for resource in self.resources:
+            for table in resource.iter_tables():
+                yield table
+
+    def get_first_table(self):
+        """
+        Often, you know there is only one table in the file, and
+        that's all you need.  This method returns that first table.
+        """
+        for table in self.iter_tables():
+            if not table.is_empty():
+                return table
+        raise IndexError("No table found in VOTABLE file.")
+
+    get_table_by_id = _lookup_by_id_factory(
+        'iter_tables', 'TABLE',
+        """
+        Looks up a TABLE_ element by the given ID.  Used by the table
+        "ref" attribute.
+        """)
+
+    def get_table_by_index(self, idx):
+        """
+        Get a table by its ordinal position in the file.
+        """
+        for i, table in enumerate(self.iter_tables()):
+            if i == idx:
+                return table
+        raise IndexError("No table at index %d found in VOTABLE file." % idx)
+
+    def iter_fields_and_params(self):
+        """
+        Recursively iterate over all FIELD_ and PARAM_ elements in the
+        VOTABLE_ file.
+        """
+        for resource in self.resources:
+            for field in resource.iter_fields_and_params():
+                yield field
+
+    get_field_by_id = _lookup_by_id_factory(
+        'iter_fields_and_params', 'FIELD',
+        """
+        Looks up a FIELD_ element by the given ID_.  Used by the field's
+        "ref" attribute.
+        """)
+
+    get_field_by_id_or_name = _lookup_by_id_or_name_factory(
+        'iter_fields_and_params', 'FIELD',
+        """
+        Looks up a FIELD_ element by the given ID_ or name.
+        """)
+
+    def iter_values(self):
+        """
+        Recursively iterate over all VALUES_ elements in the VOTABLE_
+        file.
+        """
+        for field in self.iter_fields_and_params():
+            yield field.values
+
+    get_values_by_id = _lookup_by_id_factory(
+        'iter_values', 'VALUES',
+        """
+        Looks up a VALUES_ element by the given ID.  Used by the values
+        "ref" attribute.
+        """)
+
+    def iter_groups(self):
+        """
+        Recursively iterate over all GROUP_ elements in the VOTABLE_
+        file.
+        """
+        for table in self.iter_tables():
+            for group in table.iter_groups():
+                yield group
+
+    get_group_by_id = _lookup_by_id_factory(
+        'iter_groups', 'GROUP',
+        """
+        Looks up a GROUP_ element by the given ID.  Used by the group's
+        "ref" attribute
+        """)
+
+    def iter_coosys(self):
+        """
+        Recursively iterate over all COOSYS_ elements in the VOTABLE_
+        file.
+        """
+        for coosys in self.coordinate_systems:
+            yield coosys
+        for resource in self.resources:
+            for coosys in resource.iter_coosys():
+                yield coosys
+
+    get_coosys_by_id = _lookup_by_id_factory(
+        'iter_coosys', 'COOSYS',
+        """Looks up a COOSYS_ element by the given ID.""")
+
+    def set_all_tables_format(self, format):
+        """
+        Set the output storage format of all tables in the file.
+        """
+        for table in self.iter_tables():
+            table.format = format
+
+    @classmethod
+    def from_table(cls, table, table_id=None):
+        """
+        Create a `VOTableFile` instance from a given
+        `astropy.table.Table` instance.
+
+        Parameters
+        ----------
+        table_id : str, optional
+            Set the given ID attribute on the returned Table instance.
+        """
+        votable_file = cls()
+        resource = Resource()
+        votable = Table.from_table(votable_file, table)
+        if table_id is not None:
+            votable.ID = table_id
+        resource.tables.append(votable)
+        votable_file.resources.append(resource)
+        return votable_file
diff --git a/astropy/io/votable/ucd.py b/astropy/io/votable/ucd.py
new file mode 100644
index 0000000..a9b4ed1
--- /dev/null
+++ b/astropy/io/votable/ucd.py
@@ -0,0 +1,188 @@
+"""
+This file contains routines to verify the correctness of UCD strings.
+"""
+
+from __future__ import with_statement, absolute_import
+
+#STDLIB
+import re
+
+#LOCAL
+from ...utils import data
+
+__all__ = ['parse_ucd', 'check_ucd']
+
+
+class UCDWords:
+    """
+    Manages a list of acceptable UCD words.
+
+    Works by reading in a data file exactly as provided by IVOA.  This
+    file resides in data/ucd1p-words.txt.
+    """
+    def __init__(self):
+        self._primary = set()
+        self._secondary = set()
+        self._descriptions = {}
+        self._capitalization = {}
+
+        with data.get_pkg_data_fileobj(
+                "data/ucd1p-words.txt", encoding='ascii') as fd:
+            for line in fd.readlines():
+                type, name, descr = [
+                    x.strip() for x in line.split(u'|')]
+                name_lower = name.lower()
+                if type in u'QPEV':
+                    self._primary.add(name_lower)
+                if type in u'QSEV':
+                    self._secondary.add(name_lower)
+                self._descriptions[name_lower] = descr
+                self._capitalization[name_lower] = name
+
+    def is_primary(self, name):
+        """
+        Returns True if *name* is a valid primary name.
+        """
+        return name.lower() in self._primary
+
+    def is_secondary(self, name):
+        """
+        Returns True if *name* is a valid secondary name.
+        """
+        return name.lower() in self._secondary
+
+    def get_description(self, name):
+        """
+        Returns the official English description of the given UCD
+        *name*.
+        """
+        return self._descriptions[name.lower()]
+
+    def normalize_capitalization(self, name):
+        """
+        Returns the standard capitalization form of the given name.
+        """
+        return self._capitalization[name.lower()]
+
+_ucd_singleton = None
+
+
+def parse_ucd(ucd, check_controlled_vocabulary=False, has_colon=False):
+    """
+    Parse the UCD into its component parts.
+
+    Parameters
+    ----------
+    ucd : str
+        The UCD string
+
+    check_controlled_vocabulary : bool, optional
+        If `True`, then each word in the UCD will be verified against
+        the UCD1+ controlled vocabulary, (as required by the VOTable
+        specification version 1.2), otherwise not.
+
+    has_colon : bool, optional
+        If `True`, the UCD may contain a colon (as defined in earlier
+        versions of the standard).
+
+    Returns
+    -------
+    parts : list
+        The result is a list of tuples of the form:
+
+            (*namespace*, *word*)
+
+        If no namespace was explicitly specified, *namespace* will be
+        returned as ``'ivoa'`` (i.e., the default namespace).
+
+    Raises
+    ------
+    ValueError : *ucd* is invalid
+    """
+    global _ucd_singleton
+    if _ucd_singleton is None:
+        _ucd_singleton = UCDWords()
+
+    if has_colon:
+        m = re.search(u'[^A-Za-z0-9_.:;\-]', ucd)
+    else:
+        m = re.search(u'[^A-Za-z0-9_.;\-]', ucd)
+    if m is not None:
+        raise ValueError("UCD has invalid character '%s' in '%s'" %
+                         (m.group(0), ucd))
+
+    word_component_re = u'[A-Za-z0-9][A-Za-z0-9\-_]*'
+    word_re = u'%s(\.%s)*' % (word_component_re, word_component_re)
+
+    parts = ucd.split(u';')
+    words = []
+    for i, word in enumerate(parts):
+        colon_count = word.count(u':')
+        if colon_count == 1:
+            ns, word = word.split(u':', 1)
+            if not re.match(word_component_re, ns):
+                raise ValueError("Invalid namespace '%s'" % ns)
+            ns = ns.lower()
+        elif colon_count > 1:
+            raise ValueError("Too many colons in '%s'" % word)
+        else:
+            ns = u'ivoa'
+
+        if not re.match(word_re, word):
+            raise ValueError("Invalid word '%s'" % word)
+
+        if ns == u'ivoa' and check_controlled_vocabulary:
+            if i == 0:
+                if not _ucd_singleton.is_primary(word):
+                    if _ucd_singleton.is_secondary(word):
+                        raise ValueError(
+                            "Secondary word '%s' is not valid as a primary "
+                            "word" % word)
+                    else:
+                        raise ValueError("Unknown word '%s'" % word)
+            else:
+                if not _ucd_singleton.is_secondary(word):
+                    if _ucd_singleton.is_primary(word):
+                        raise ValueError(
+                            "Primary word '%s' is not valid as a secondary "
+                            "word" % word)
+                    else:
+                        raise ValueError("Unknown word '%s'" % word)
+
+        try:
+            normalized_word = _ucd_singleton.normalize_capitalization(word)
+        except KeyError:
+            normalized_word = word
+        words.append((ns, normalized_word))
+
+    return words
+
+
+def check_ucd(ucd, check_controlled_vocabulary=False, has_colon=False):
+    """
+    Returns False if *ucd* is not a valid `unified content descriptor`_.
+
+    Parameters
+    ----------
+    ucd : str
+        The UCD string
+
+    check_controlled_vocabulary : bool, optional
+        If `True`, then each word in the UCD will be verified against
+        the UCD1+ controlled vocabulary, (as required by the VOTable
+        specification version 1.2), otherwise not.
+
+    Returns
+    -------
+    valid : bool
+    """
+    if ucd is None:
+        return True
+
+    try:
+        parse_ucd(ucd,
+                  check_controlled_vocabulary=check_controlled_vocabulary,
+                  has_colon=has_colon)
+    except ValueError:
+        return False
+    return True
diff --git a/astropy/io/vo/util.py b/astropy/io/votable/util.py
similarity index 100%
rename from astropy/io/vo/util.py
rename to astropy/io/votable/util.py
diff --git a/astropy/io/vo/validator/__init__.py b/astropy/io/votable/validator/__init__.py
similarity index 100%
rename from astropy/io/vo/validator/__init__.py
rename to astropy/io/votable/validator/__init__.py
diff --git a/astropy/io/vo/validator/html.py b/astropy/io/votable/validator/html.py
similarity index 100%
rename from astropy/io/vo/validator/html.py
rename to astropy/io/votable/validator/html.py
diff --git a/astropy/io/votable/validator/main.py b/astropy/io/votable/validator/main.py
new file mode 100644
index 0000000..5064873
--- /dev/null
+++ b/astropy/io/votable/validator/main.py
@@ -0,0 +1,163 @@
+"""
+Validates a large collection of web-accessible VOTable files,
+and generates a report as a directory tree of HTML files.
+"""
+from __future__ import print_function
+
+# STDLIB
+import os
+
+# LOCAL
+from ....utils.data import get_pkg_data_filename
+from . import html
+from . import result
+
+
+__all__ = ['make_validation_report']
+
+
+
+def get_srcdir():
+    return os.path.dirname(__file__)
+
+
+def get_urls(destdir, s):
+    import gzip
+
+    types = ['good', 'broken', 'incorrect']
+
+    seen = set()
+    urls = []
+    for type in types:
+        filename = get_pkg_data_filename(
+            'urls/cone.{0}.dat.gz'.format(type))
+        with gzip.open(filename, 'rb') as fd:
+            for url in fd.readlines():
+                s.next()
+                url = url.strip()
+                if url not in seen:
+                    with result.Result(url, root=destdir) as r:
+                        r['expected'] = type
+                    urls.append(url)
+                seen.add(url)
+
+    return urls
+
+
+def download(args):
+    url, destdir = args
+    with result.Result(url, root=destdir) as r:
+        r.download_xml_content()
+
+
+def validate_vo(args):
+    url, destdir = args
+    with result.Result(url, root=destdir) as r:
+        r.validate_vo()
+
+
+def votlint_validate(args):
+    path_to_stilts_jar, url, destdir = args
+    with result.Result(url, root=destdir) as r:
+        if r['network_error'] is None:
+            r.validate_with_votlint(path_to_stilts_jar)
+
+
+def write_html_result(args):
+    url, destdir = args
+    with result.Result(url, root=destdir) as r:
+        html.write_result(r)
+
+
+def write_subindex(args):
+    subset, destdir, total = args
+    html.write_index_table(destdir, *subset, total=total)
+
+
+def make_validation_report(
+    urls=None, destdir='astropy.io.votable.validator.results',
+    multiprocess=True, stilts=None):
+    """
+    Validates a large collection of web-accessible VOTable files.
+
+    Generates a report as a directory tree of HTML files.
+
+    Parameters
+    ----------
+    urls : list of strings, optional
+        If provided, is a list of HTTP urls to download VOTable files
+        from.  If not provided, a built-in set of ~22,000 urls
+        compiled by HEASARC will be used.
+
+    destdir : path, optional
+        The directory to write the report to.  By default, this is a
+        directory called `astropy.io.votable.validator.results` in the
+        current directory.  If the directory does not exist, it will
+        be created.
+
+    multiprocess : bool, optional
+        If `True` (default), perform validations in parallel using all
+        of the cores on this machine.
+
+    stilts : path, optional
+        To perform validation with `votlint` from the the Java-based
+        `STILTS <http://www.star.bris.ac.uk/~mbt/stilts/>`_ VOTable
+        parser, in addition to `astropy.io.votable`, set this to the
+        path of the `stilts.jar` file.  `java` on the system shell
+        path will be used to run it.
+
+    Notes
+    -----
+    Downloads of each given URL will be performed only once and cached
+    locally in *destdir*.  To refresh the cache, remove *destdir*
+    first.
+    """
+    from ....utils.console import (color_print, ProgressBar, Spinner)
+
+    if stilts is not None:
+        if not os.path.exists(stilts):
+            raise ValueError(
+                '{0} does not exist.'.format(stilts))
+
+    destdir = os.path.abspath(destdir)
+
+    if urls is None:
+        with Spinner('Loading URLs', 'green') as s:
+            urls = get_urls(destdir, s)
+    else:
+        color_print('Marking URLs', 'green')
+        for url in ProgressBar.iterate(urls):
+            with result.Result(url, root=destdir) as r:
+                r['expected'] = type
+
+    args = [(url, destdir) for url in urls]
+
+    color_print('Downloading VO files', 'green')
+    ProgressBar.map(
+        download, args, multiprocess=multiprocess)
+
+    color_print('Validating VO files', 'green')
+    ProgressBar.map(
+        validate_vo, args, multiprocess=multiprocess)
+
+    if stilts is not None:
+        color_print('Validating with votlint', 'green')
+        votlint_args = [(stilts, x, destdir) for x in urls]
+        ProgressBar.map(
+            votlint_validate, votlint_args, multiprocess=multiprocess)
+
+
+    color_print('Generating HTML files', 'green')
+    ProgressBar.map(
+        write_html_result, args, multiprocess=multiprocess)
+
+    with Spinner('Grouping results', 'green') as s:
+        subsets = result.get_result_subsets(urls, destdir, s)
+
+    color_print('Generating index', 'green')
+    html.write_index(subsets, urls, destdir)
+
+    color_print('Generating subindices', 'green')
+    subindex_args = [(subset, destdir, len(urls)) for subset in subsets]
+    ProgressBar.map(
+        write_subindex, subindex_args, multiprocess=multiprocess)
diff --git a/astropy/io/votable/validator/result.py b/astropy/io/votable/validator/result.py
new file mode 100644
index 0000000..8fec8e4
--- /dev/null
+++ b/astropy/io/votable/validator/result.py
@@ -0,0 +1,341 @@
+"""
+Contains a class to handle a validation result for a single VOTable
+file.
+"""
+
+from __future__ import absolute_import
+
+# STDLIB
+import hashlib
+import httplib
+import os
+import cPickle as pickle
+import shutil
+import socket
+import subprocess
+import urllib2
+import warnings
+
+# VO
+from .. import table
+from .. import exceptions
+from .. import xmlutil
+from ..util import IS_PY3K
+
+
+class Result:
+    def __init__(self, url, root='results'):
+        self.url = url
+        m = hashlib.md5()
+        m.update(url)
+        self._hash = m.hexdigest()
+        self._root = root
+        self._path = os.path.join(
+            self._hash[0:2], self._hash[2:4], self._hash[4:])
+        if not os.path.exists(self.get_dirpath()):
+            os.makedirs(self.get_dirpath())
+        self.load_attributes()
+
+    def __enter__(self):
+        return self
+
+    def __exit__(self, *args):
+        self.save_attributes()
+
+    def get_dirpath(self):
+        return os.path.join(self._root, self._path)
+
+    def get_htmlpath(self):
+        return self._path
+
+    def get_attribute_path(self):
+        return os.path.join(self.get_dirpath(), "values.dat")
+
+    def get_vo_xml_path(self):
+        return os.path.join(self.get_dirpath(), "vo.xml")
+
+    # ATTRIBUTES
+
+    def load_attributes(self):
+        path = self.get_attribute_path()
+        if os.path.exists(path):
+            try:
+                with open(path, 'rb') as fd:
+                    self._attributes = pickle.load(fd)
+            except:
+                shutil.rmtree(self.get_dirpath())
+                os.makedirs(self.get_dirpath())
+                self._attributes = {}
+        else:
+            self._attributes = {}
+
+    def save_attributes(self):
+        path = self.get_attribute_path()
+        with open(path, 'wb') as fd:
+            pickle.dump(self._attributes, fd)
+
+    def __getitem__(self, key):
+        return self._attributes[key]
+
+    def __setitem__(self, key, val):
+        self._attributes[key] = val
+
+    def __contains__(self, key):
+        return key in self._attributes
+
+    # VO XML
+
+    def download_xml_content(self):
+        path = self.get_vo_xml_path()
+
+        if 'network_error' not in self._attributes:
+            self['network_error'] = None
+
+        if os.path.exists(path):
+            return
+
+        def fail(reason):
+            reason = str(reason)
+            with open(path, 'wb') as fd:
+                fd.write("FAILED: %s\n" % reason)
+            self['network_error'] = reason
+
+        r = None
+        try:
+            if IS_PY3K:
+                r = urllib2.urlopen(self.url.decode('ascii'))
+            else:
+                r = urllib2.urlopen(self.url, timeout=10)
+        except urllib2.URLError as e:
+            if hasattr(e, 'reason'):
+                reason = e.reason
+            else:
+                reason = e.code
+            fail(reason)
+            return
+        except httplib.HTTPException as e:
+            fail("HTTPException: %s" % str(e))
+            return
+        except socket.timeout as e:
+            fail("Timeout")
+            return
+
+        if r is None:
+            fail("Invalid URL")
+            return
+
+        try:
+            content = r.read()
+        except socket.timeout as e:
+            fail("Timeout")
+            return
+        else:
+            r.close()
+
+        with open(path, 'wb') as fd:
+            fd.write(content)
+
+    def get_xml_content(self):
+        path = self.get_vo_xml_path()
+        if not os.path.exists(path):
+            self.download_xml_content()
+        with open(path, 'rb') as fd:
+            content = fd.read()
+        return content
+
+    def validate_vo(self):
+        path = self.get_vo_xml_path()
+        if not os.path.exists(path):
+            self.download_xml_content()
+        self['version'] = ''
+        if self['network_error'] is not None:
+            self['nwarnings'] = 0
+            self['nexceptions'] = 0
+            self['warnings'] = []
+            self['xmllint'] = None
+            self['warning_types'] = set()
+            return
+
+        nexceptions = 0
+        nwarnings = 0
+        t = None
+        lines = []
+        with open(path, 'rb') as input:
+            with warnings.catch_warnings(record=True) as warning_lines:
+                try:
+                    t = table.parse(input, pedantic=False, filename=path)
+                except ValueError as e:
+                    lines.append(str(e))
+                    nexceptions += 1
+        lines = [str(x.message) for x in warning_lines] + lines
+
+        if t is not None:
+            self['version'] = version = t.version
+        else:
+            self['version'] = version = "1.0"
+
+        if 'xmllint' not in self:
+            # Now check the VO schema based on the version in
+            # the file.
+            success, stdout, stderr = xmlutil.validate_schema(path, version)
+            self['xmllint'] = (success == 0)
+            self['xmllint_content'] = stderr
+
+        warning_types = set()
+        for line in lines:
+            w = exceptions.parse_vowarning(line)
+            if w['is_warning']:
+                nwarnings += 1
+            if w['is_exception']:
+                nexceptions += 1
+            warning_types.add(w['warning'])
+
+        self['nwarnings'] = nwarnings
+        self['nexceptions'] = nexceptions
+        self['warnings'] = lines
+        self['warning_types'] = warning_types
+
+    def has_warning(self, warning_code):
+        return warning_code in self['warning_types']
+
+    def match_expectations(self):
+        if self['expected'] == 'good':
+            return (not self['network_error'] and
+                    self['nwarnings'] == 0 and
+                    self['nexceptions'] == 0)
+        elif self['expected'] == 'incorrect':
+            return (not self['network_error'] and
+                    (self['nwarnings'] > 0 or
+                     self['nexceptions'] > 0))
+        elif self['expected'] == 'broken':
+            return self['network_error'] is not None
+
+    def validate_with_votlint(self, path_to_stilts_jar):
+        filename = self.get_vo_xml_path()
+        p = subprocess.Popen(
+            "java -jar %s votlint validate=false %s" %
+            (path_to_stilts_jar, filename),
+            shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+        stdout, stderr = p.communicate()
+        if len(stdout) or p.returncode:
+            self['votlint'] = False
+        else:
+            self['votlint'] = True
+        self['votlint_content'] = stdout
+
+
+def get_result_subsets(results, root, s=None):
+    all_results      = []
+    correct          = []
+    not_expected     = []
+    fail_schema      = []
+    schema_mismatch  = []
+    fail_votlint     = []
+    votlint_mismatch = []
+    network_failures = []
+    version_10       = []
+    version_11       = []
+    version_12       = []
+    version_unknown  = []
+    has_warnings     = []
+    warning_set      = {}
+    has_exceptions   = []
+    exception_set    = {}
+
+    for url in results:
+        if s:
+            s.next()
+
+        x = Result(url, root=root)
+        all_results.append(x)
+        if (x['nwarnings'] == 0 and
+            x['nexceptions'] == 0 and
+            x['xmllint'] is True):
+            correct.append(x)
+        if not x.match_expectations():
+            not_expected.append(x)
+        if x['xmllint'] is False:
+            fail_schema.append(x)
+        if (x['xmllint'] is False and
+            x['nwarnings'] == 0 and
+            x['nexceptions'] == 0):
+            schema_mismatch.append(x)
+        if 'votlint' in x and x['votlint'] is False:
+            fail_votlint.append(x)
+            if (x['nwarnings'] == 0 and
+                x['nexceptions'] == 0 and
+                x['network_error'] is None):
+                votlint_mismatch.append(x)
+        if x['network_error'] is not None:
+            network_failures.append(x)
+        version = x['version']
+        if version == '1.0':
+            version_10.append(x)
+        elif version == '1.1':
+            version_11.append(x)
+        elif version == '1.2':
+            version_12.append(x)
+        else:
+            version_unknown.append(x)
+        if x['nwarnings'] > 0:
+            has_warnings.append(x)
+            for warning in x['warning_types']:
+                if (warning is not None and
+                    len(warning) == 3 and
+                    warning.startswith('W')):
+                    warning_set.setdefault(warning, [])
+                    warning_set[warning].append(x)
+        if x['nexceptions'] > 0:
+            has_exceptions.append(x)
+            for exc in x['warning_types']:
+                if exc is not None and len(exc) == 3 and exc.startswith('E'):
+                    exception_set.setdefault(exc, [])
+                    exception_set[exc].append(x)
+
+    warning_set = list(warning_set.items())
+    warning_set.sort()
+    exception_set = list(exception_set.items())
+    exception_set.sort()
+
+    tables = [
+        ('all', u'All tests', all_results),
+        ('correct', u'Correct', correct),
+        ('unexpected', u'Unexpected', not_expected),
+        ('schema', u'Invalid against schema', fail_schema),
+        ('schema_mismatch', u'Invalid against schema/Passed vo.table',
+         schema_mismatch, ['ul']),
+        ('fail_votlint', u'Failed votlint', fail_votlint),
+        ('votlint_mismatch', u'Failed votlint/Passed vo.table',
+         votlint_mismatch, ['ul']),
+        ('network_failures', u'Network failures', network_failures),
+        ('version1.0', 'Version 1.0', version_10),
+        ('version1.1', 'Version 1.1', version_11),
+        ('version1.2', 'Version 1.2', version_12),
+        ('version_unknown', 'Version unknown', version_unknown),
+        ('warnings', 'Warnings', has_warnings)]
+    for warning_code, warnings in warning_set:
+        if s:
+            s.next()
+
+        warning_class = getattr(exceptions, warning_code, None)
+        if warning_class:
+            warning_descr = warning_class.get_short_name()
+            tables.append(
+                (warning_code,
+                 '%s: %s' % (warning_code, warning_descr),
+                 warnings, ['ul', 'li']))
+    tables.append(
+        ('exceptions', 'Exceptions', has_exceptions))
+    for exception_code, exc in exception_set:
+        if s:
+            s.next()
+
+        exception_class = getattr(exceptions, exception_code, None)
+        if exception_class:
+            exception_descr = exception_class.get_short_name()
+            tables.append(
+                (exception_code,
+                 '%s: %s' % (exception_code, exception_descr),
+                 exc, ['ul', 'li']))
+
+    return tables
diff --git a/astropy/io/vo/validator/urls/cone.big.dat.gz b/astropy/io/votable/validator/urls/cone.big.dat.gz
similarity index 100%
rename from astropy/io/vo/validator/urls/cone.big.dat.gz
rename to astropy/io/votable/validator/urls/cone.big.dat.gz
diff --git a/astropy/io/vo/validator/urls/cone.broken.dat.gz b/astropy/io/votable/validator/urls/cone.broken.dat.gz
similarity index 100%
rename from astropy/io/vo/validator/urls/cone.broken.dat.gz
rename to astropy/io/votable/validator/urls/cone.broken.dat.gz
diff --git a/astropy/io/vo/validator/urls/cone.good.dat.gz b/astropy/io/votable/validator/urls/cone.good.dat.gz
similarity index 100%
rename from astropy/io/vo/validator/urls/cone.good.dat.gz
rename to astropy/io/votable/validator/urls/cone.good.dat.gz
diff --git a/astropy/io/vo/validator/urls/cone.incorrect.dat.gz b/astropy/io/votable/validator/urls/cone.incorrect.dat.gz
similarity index 100%
rename from astropy/io/vo/validator/urls/cone.incorrect.dat.gz
rename to astropy/io/votable/validator/urls/cone.incorrect.dat.gz
diff --git a/astropy/io/votable/voexceptions.py b/astropy/io/votable/voexceptions.py
new file mode 100644
index 0000000..29c310b
--- /dev/null
+++ b/astropy/io/votable/voexceptions.py
@@ -0,0 +1,7 @@
+import warnings
+warnings.warn(
+    "astropy.io.votable.voexceptions is deprecated. "
+    "Use astropy.io.votable.exceptions",
+    DeprecationWarning)
+
+from .exceptions import *
diff --git a/astropy/io/vo/volint.py b/astropy/io/votable/volint.py
similarity index 100%
rename from astropy/io/vo/volint.py
rename to astropy/io/votable/volint.py
diff --git a/astropy/io/votable/xmlutil.py b/astropy/io/votable/xmlutil.py
new file mode 100644
index 0000000..79930bd
--- /dev/null
+++ b/astropy/io/votable/xmlutil.py
@@ -0,0 +1,124 @@
+"""
+Various XML-related utilities
+"""
+
+from __future__ import division, absolute_import
+
+# ASTROPY
+from ...utils.xml import check as xml_check
+from ...utils.xml import validate
+
+# LOCAL
+from .exceptions import (warn_or_raise, vo_warn,
+     W02, W03, W04, W05)
+from ...utils import data
+
+
+__all__ = [
+    'check_id', 'fix_id', 'check_token', 'check_mime_content_type',
+    'check_anyuri', 'validate_schema'
+    ]
+
+
+def check_id(ID, name='ID', config={}, pos=None):
+    """
+    Raises a `~astropy.io.votable.exceptions.VOTableSpecError` if *ID*
+    is not a valid XML ID_.
+
+    *name* is the name of the attribute being checked (used only for
+    error messages).
+    """
+    if (ID is not None and not xml_check.check_id(ID)):
+        warn_or_raise(W02, W02, (name, ID), config, pos)
+        return False
+    return True
+
+
+def fix_id(ID, config={}, pos=None):
+    """
+    Given an arbitrary string, create one that can be used as an xml id.
+
+    This is rather simplistic at the moment, since it just replaces
+    non-valid characters with underscores.
+    """
+    if ID is None:
+        return None
+    corrected = xml_check.fix_id(ID)
+    if corrected != ID:
+        vo_warn(W03, (ID, corrected), config, pos)
+    return corrected
+
+
+_token_regex = r"(?![\r\l\t ])[^\r\l\t]*(?![\r\l\t ])"
+
+
+def check_token(token, attr_name, config={}, pos=None):
+    """
+    Raises a `ValueError` if *token* is not a valid XML token.
+
+    As defined by XML Schema Part 2.
+    """
+    if (token is not None and not xml_check.check_token(token)):
+        return False
+    return True
+
+
+def check_mime_content_type(content_type, config={}, pos=None):
+    """
+    Raises a `~astropy.io.votable.exceptions.VOTableSpecError` if
+    *content_type* is not a valid MIME content type.
+
+    As defined by RFC 2045 (syntactically, at least).
+    """
+    if (content_type is not None and
+        not xml_check.check_mime_content_type(content_type)):
+        warn_or_raise(W04, W04, content_type, config, pos)
+        return False
+    return True
+
+
+def check_anyuri(uri, config={}, pos=None):
+    """
+    Raises a `~astropy.io.votable.exceptions.VOTableSpecError` if
+    *uri* is not a valid URI.
+
+    As defined in RFC 2396.
+    """
+    if (uri is not None and not xml_check.check_anyuri(uri)):
+        warn_or_raise(W05, W05, uri, config, pos)
+        return False
+    return True
+
+
+def validate_schema(filename, version='1.2'):
+    """
+    Validates the given file against the appropriate VOTable schema.
+
+    Parameters
+    ----------
+    filename : str
+        The path to the XML file to validate
+
+    version : str
+        The VOTABLE version to check, which must be a string \"1.0\",
+        \"1.1\", or \"1.2\".
+
+        For version \"1.0\", it is checked against a DTD, since that
+        version did not have an XML Schema.
+
+    Returns
+    -------
+    returncode, stdout, stderr : int, str, str
+        Returns the returncode from xmllint and the stdout and stderr
+        as strings
+    """
+    assert version in ('1.0', '1.1', '1.2')
+
+    if version in ('1.1', '1.2'):
+        schema_path = data.get_pkg_data_filename(
+            'data/VOTable.v{0}.xsd'.format(version))
+    else:
+        schema_path = data.get_pkg_data_filename(
+            'data/VOTable.dtd')
+
+    return validate.validate_schema(filename, schema_path)
diff --git a/astropy/logger.py b/astropy/logger.py
index 8704f9b..bb05292 100644
--- a/astropy/logger.py
+++ b/astropy/logger.py
@@ -10,6 +10,7 @@ import warnings
 from contextlib import contextmanager
 
 from .config import ConfigurationItem
+from . import config
 from .utils.compat import inspect_getmodule
 from .utils.console import color_print
 from .utils.misc import find_current_module
@@ -56,8 +57,10 @@ LOG_TO_FILE = ConfigurationItem('log_to_file', True,
                                 "Whether to always log messages to a log "
                                 "file")
 
-LOG_FILE_PATH = ConfigurationItem('log_file_path', '~/.astropy/astropy.log',
-                                  "The file to log messages to")
+LOG_FILE_PATH = ConfigurationItem('log_file_path', '',
+                                  "The file to log messages to. When '', "
+                                  "it defaults to a file 'astropy.log' in "
+                                  "the astropy config directory.")
 
 LOG_FILE_LEVEL = ConfigurationItem('log_file_level', 'INFO',
                                    "Threshold for logging messages to "
@@ -286,10 +289,11 @@ class AstropyLogger(Logger):
         except NameError:
             ip = None
 
+        if self.exception_logging_enabled():
+            raise LoggingError("Exception logging has already been enabled")
+
         if ip is None:
             #standard python interpreter
-            if self.exception_logging_enabled():
-                raise LoggingError("Exception logging has already been enabled")
             self._excepthook_orig = sys.excepthook
             sys.excepthook = self._excepthook
         else:
@@ -326,10 +330,11 @@ class AstropyLogger(Logger):
         except NameError:
             ip = None
 
+        if not self.exception_logging_enabled():
+            raise LoggingError("Exception logging has not been enabled")
+
         if ip is None:
             #standard python interpreter
-            if not self.exception_logging_enabled():
-                raise LoggingError("Exception logging has not been enabled")
             if sys.excepthook != self._excepthook:
                 raise LoggingError("Cannot disable exception logging: "
                                    "sys.excepthook was not set by this logger, "
@@ -338,11 +343,7 @@ class AstropyLogger(Logger):
             self._excepthook_orig = None
         else:
             #IPython has its own way of dealing with exceptions
-            if not self.exception_logging_enabled():
-                raise LoggingError("Astropy exception logging has not been "
-                                   "enabled in this IPython session")
-            else:
-                ip.set_custom_exc(tuple(), None)
+            ip.set_custom_exc(tuple(), None)
 
     def enable_color(self):
         '''
@@ -375,7 +376,7 @@ class AstropyLogger(Logger):
     @contextmanager
     def log_to_file(self, filename, filter_level=None, filter_origin=None):
         '''
-        Context manager to temporarily log messages to a file
+        Context manager to temporarily log messages to a file.
 
         Parameters
         ----------
@@ -423,7 +424,7 @@ class AstropyLogger(Logger):
     @contextmanager
     def log_to_list(self, filter_level=None, filter_origin=None):
         '''
-        Context manager to temporarily log messages to a list
+        Context manager to temporarily log messages to a list.
 
         Parameters
         ----------
@@ -499,10 +500,28 @@ class AstropyLogger(Logger):
         # Set up the main log file handler if requested (but this might fail if
         # configuration directory or log file is not writeable).
         if LOG_TO_FILE() and not os.environ.get('ASTROPY_TESTS_RUNNING'):
+            log_file_path = LOG_FILE_PATH()
+
+            # "None" as a string because it comes from config
+            try:
+                _ASTROPY_TEST_
+                testing_mode = True
+            except NameError:
+                testing_mode = False
+
+            if log_file_path == '' or testing_mode:
+                log_file_path = os.path.join(
+                    config.get_config_dir(), "astropy.log")
+            else:
+                log_file_path = os.path.expanduser(log_file_path)
+
             try:
-                fh = FileHandler(os.path.expanduser(LOG_FILE_PATH()))
+                fh = FileHandler(log_file_path)
             except IOError:
-                pass
+                warnings.warn(
+                    "log file {0!r} could not be opened for writing".format(
+                        log_file_path),
+                    RuntimeWarning)
             else:
                 formatter = logging.Formatter(LOG_FILE_FORMAT())
                 fh.setFormatter(formatter)
diff --git a/astropy/nddata/__init__.py b/astropy/nddata/__init__.py
index fb62f84..70eb3df 100644
--- a/astropy/nddata/__init__.py
+++ b/astropy/nddata/__init__.py
@@ -11,7 +11,9 @@ be easily provided by a single array.
 from astropy import setup_helpers
 
 from .nddata import *
+from .nduncertainty import *
+from .flag_collection import *
 
-if not setup_helpers.is_in_build_mode():
+if not _ASTROPY_SETUP_:
     from .convolution.convolve import convolve,convolve_fft
     from .convolution.make_kernel import make_kernel
diff --git a/astropy/nddata/convolution/boundary_extend.c b/astropy/nddata/convolution/boundary_extend.c
index bbd2b51..6125b79 100644
--- a/astropy/nddata/convolution/boundary_extend.c
+++ b/astropy/nddata/convolution/boundary_extend.c
@@ -1,12 +1,11 @@
-/* Generated by Cython 0.16 on Tue Jun 19 01:38:31 2012 */
+/* Generated by Cython 0.15.1 on Mon Dec 24 15:34:31 2012 */
 
 #define PY_SSIZE_T_CLEAN
 #include "Python.h"
 #ifndef Py_PYTHON_H
     #error Python headers needed to compile C extensions, please install development version of Python.
-#elif PY_VERSION_HEX < 0x02040000
-    #error Cython requires Python 2.4+.
 #else
+
 #include <stddef.h> /* For offsetof */
 #ifndef offsetof
 #define offsetof(type, member) ( (size_t) & ((type*)0) -> member )
@@ -35,22 +34,10 @@
   #define PY_LONG_LONG LONG_LONG
 #endif
 
-#ifndef Py_HUGE_VAL
-  #define Py_HUGE_VAL HUGE_VAL
-#endif
-
-#ifdef PYPY_VERSION
-#define CYTHON_COMPILING_IN_PYPY 1
-#define CYTHON_COMPILING_IN_CPYTHON 0
-#else
-#define CYTHON_COMPILING_IN_PYPY 0
-#define CYTHON_COMPILING_IN_CPYTHON 1
-#endif
-
-#if CYTHON_COMPILING_IN_PYPY
-  #define __Pyx_PyCFunction_Call PyObject_Call
-#else
-  #define __Pyx_PyCFunction_Call PyCFunction_Call
+#if PY_VERSION_HEX < 0x02040000
+  #define METH_COEXIST 0
+  #define PyDict_CheckExact(op) (Py_TYPE(op) == &PyDict_Type)
+  #define PyDict_Contains(d,o)   PySequence_Contains(d,o)
 #endif
 
 #if PY_VERSION_HEX < 0x02050000
@@ -63,9 +50,6 @@
   #define PyNumber_Index(o)    PyNumber_Int(o)
   #define PyIndex_Check(o)     PyNumber_Check(o)
   #define PyErr_WarnEx(category, message, stacklevel) PyErr_Warn(category, message)
-  #define __PYX_BUILD_PY_SSIZE_T "i"
-#else
-  #define __PYX_BUILD_PY_SSIZE_T "n"
 #endif
 
 #if PY_VERSION_HEX < 0x02060000
@@ -99,25 +83,13 @@
   #define PyBUF_F_CONTIGUOUS (0x0040 | PyBUF_STRIDES)
   #define PyBUF_ANY_CONTIGUOUS (0x0080 | PyBUF_STRIDES)
   #define PyBUF_INDIRECT (0x0100 | PyBUF_STRIDES)
-  #define PyBUF_RECORDS (PyBUF_STRIDES | PyBUF_FORMAT | PyBUF_WRITABLE)
-  #define PyBUF_FULL (PyBUF_INDIRECT | PyBUF_FORMAT | PyBUF_WRITABLE)
 
-  typedef int (*getbufferproc)(PyObject *, Py_buffer *, int);
-  typedef void (*releasebufferproc)(PyObject *, Py_buffer *);
 #endif
 
 #if PY_MAJOR_VERSION < 3
   #define __Pyx_BUILTIN_MODULE_NAME "__builtin__"
-  #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) \
-          PyCode_New(a, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)
 #else
   #define __Pyx_BUILTIN_MODULE_NAME "builtins"
-  #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) \
-          PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)
-#endif
-
-#if PY_MAJOR_VERSION < 3 && PY_MINOR_VERSION < 6
-  #define PyUnicode_FromString(s) PyUnicode_Decode(s, strlen(s), "UTF-8", "strict")
 #endif
 
 #if PY_MAJOR_VERSION >= 3
@@ -129,17 +101,6 @@
   #define Py_TPFLAGS_HAVE_NEWBUFFER 0
 #endif
 
-
-#if PY_VERSION_HEX > 0x03030000 && defined(PyUnicode_GET_LENGTH)
-  #define CYTHON_PEP393_ENABLED 1
-  #define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_LENGTH(u)
-  #define __Pyx_PyUnicode_READ_CHAR(u, i) PyUnicode_READ_CHAR(u, i)
-#else
-  #define CYTHON_PEP393_ENABLED 0
-  #define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_SIZE(u)
-  #define __Pyx_PyUnicode_READ_CHAR(u, i) ((Py_UCS4)(PyUnicode_AS_UNICODE(u)[i]))
-#endif
-
 #if PY_MAJOR_VERSION >= 3
   #define PyBaseString_Type            PyUnicode_Type
   #define PyStringObject               PyUnicodeObject
@@ -207,6 +168,15 @@
   #define __Pyx_PyInt_AsHash_t   PyInt_AsSsize_t
 #endif
 
+
+#if PY_MAJOR_VERSION >= 3
+  #define __Pyx_PyNumber_Divide(x,y)         PyNumber_TrueDivide(x,y)
+  #define __Pyx_PyNumber_InPlaceDivide(x,y)  PyNumber_InPlaceTrueDivide(x,y)
+#else
+  #define __Pyx_PyNumber_Divide(x,y)         PyNumber_TrueDivide(x,y)
+  #define __Pyx_PyNumber_InPlaceDivide(x,y)  PyNumber_InPlaceTrueDivide(x,y)
+#endif
+
 #if (PY_MAJOR_VERSION < 3) || (PY_VERSION_HEX >= 0x03010300)
   #define __Pyx_PySequence_GetSlice(obj, a, b) PySequence_GetSlice(obj, a, b)
   #define __Pyx_PySequence_SetSlice(obj, a, b, value) PySequence_SetSlice(obj, a, b, value)
@@ -248,14 +218,6 @@
   #define __Pyx_DOCSTR(n)  (n)
 #endif
 
-#if PY_MAJOR_VERSION >= 3
-  #define __Pyx_PyNumber_Divide(x,y)         PyNumber_TrueDivide(x,y)
-  #define __Pyx_PyNumber_InPlaceDivide(x,y)  PyNumber_InPlaceTrueDivide(x,y)
-#else
-  #define __Pyx_PyNumber_Divide(x,y)         PyNumber_TrueDivide(x,y)
-  #define __Pyx_PyNumber_InPlaceDivide(x,y)  PyNumber_InPlaceTrueDivide(x,y)
-#endif
-
 #ifndef __PYX_EXTERN_C
   #ifdef __cplusplus
     #define __PYX_EXTERN_C extern "C"
@@ -305,7 +267,7 @@
 #   else
 #     define CYTHON_UNUSED
 #   endif
-# elif defined(__ICC) || (defined(__INTEL_COMPILER) && !defined(_MSC_VER))
+# elif defined(__ICC) || defined(__INTEL_COMPILER)
 #   define CYTHON_UNUSED __attribute__ ((__unused__))
 # else
 #   define CYTHON_UNUSED
@@ -330,7 +292,7 @@ static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t);
 static CYTHON_INLINE size_t __Pyx_PyInt_AsSize_t(PyObject*);
 
 #define __pyx_PyFloat_AsDouble(x) (PyFloat_CheckExact(x) ? PyFloat_AS_DOUBLE(x) : PyFloat_AsDouble(x))
-#define __pyx_PyFloat_AsFloat(x) ((float) __pyx_PyFloat_AsDouble(x))
+
 
 #ifdef __GNUC__
   /* Test for GCC > 2.95 */
@@ -355,6 +317,7 @@ static int __pyx_clineno = 0;
 static const char * __pyx_cfilenm= __FILE__;
 static const char *__pyx_filename;
 
+
 #if !defined(CYTHON_CCOMPLEX)
   #if defined(__cplusplus)
     #define CYTHON_CCOMPLEX 1
@@ -364,6 +327,7 @@ static const char *__pyx_filename;
     #define CYTHON_CCOMPLEX 0
   #endif
 #endif
+
 #if CYTHON_CCOMPLEX
   #ifdef __cplusplus
     #include <complex>
@@ -371,53 +335,18 @@ static const char *__pyx_filename;
     #include <complex.h>
   #endif
 #endif
+
 #if CYTHON_CCOMPLEX && !defined(__cplusplus) && defined(__sun__) && defined(__GNUC__)
   #undef _Complex_I
   #define _Complex_I 1.0fj
 #endif
 
-
 static const char *__pyx_f[] = {
   "boundary_extend.pyx",
   "numpy.pxd",
 };
-#define IS_UNSIGNED(type) (((type) -1) > 0)
-struct __Pyx_StructField_;
-#define __PYX_BUF_FLAGS_PACKED_STRUCT (1 << 0)
-typedef struct {
-  const char* name; /* for error messages only */
-  struct __Pyx_StructField_* fields;
-  size_t size;     /* sizeof(type) */
-  size_t arraysize[8]; /* length of array in each dimension */
-  int ndim;
-  char typegroup; /* _R_eal, _C_omplex, Signed _I_nt, _U_nsigned int, _S_truct, _P_ointer, _O_bject */
-  char is_unsigned;
-  int flags;
-} __Pyx_TypeInfo;
-typedef struct __Pyx_StructField_ {
-  __Pyx_TypeInfo* type;
-  const char* name;
-  size_t offset;
-} __Pyx_StructField;
-typedef struct {
-  __Pyx_StructField* field;
-  size_t parent_offset;
-} __Pyx_BufFmt_StackElem;
-typedef struct {
-  __Pyx_StructField root;
-  __Pyx_BufFmt_StackElem* head;
-  size_t fmt_offset;
-  size_t new_count, enc_count;
-  size_t struct_alignment;
-  int is_complex;
-  char enc_type;
-  char new_packmode;
-  char enc_packmode;
-  char is_valid_array;
-} __Pyx_BufFmt_Context;
-
 
-/* "numpy.pxd":722
+/* "numpy.pxd":719
  * # in Cython to enable them only on the right systems.
  * 
  * ctypedef npy_int8       int8_t             # <<<<<<<<<<<<<<
@@ -426,7 +355,7 @@ typedef struct {
  */
 typedef npy_int8 __pyx_t_5numpy_int8_t;
 
-/* "numpy.pxd":723
+/* "numpy.pxd":720
  * 
  * ctypedef npy_int8       int8_t
  * ctypedef npy_int16      int16_t             # <<<<<<<<<<<<<<
@@ -435,7 +364,7 @@ typedef npy_int8 __pyx_t_5numpy_int8_t;
  */
 typedef npy_int16 __pyx_t_5numpy_int16_t;
 
-/* "numpy.pxd":724
+/* "numpy.pxd":721
  * ctypedef npy_int8       int8_t
  * ctypedef npy_int16      int16_t
  * ctypedef npy_int32      int32_t             # <<<<<<<<<<<<<<
@@ -444,7 +373,7 @@ typedef npy_int16 __pyx_t_5numpy_int16_t;
  */
 typedef npy_int32 __pyx_t_5numpy_int32_t;
 
-/* "numpy.pxd":725
+/* "numpy.pxd":722
  * ctypedef npy_int16      int16_t
  * ctypedef npy_int32      int32_t
  * ctypedef npy_int64      int64_t             # <<<<<<<<<<<<<<
@@ -453,7 +382,7 @@ typedef npy_int32 __pyx_t_5numpy_int32_t;
  */
 typedef npy_int64 __pyx_t_5numpy_int64_t;
 
-/* "numpy.pxd":729
+/* "numpy.pxd":726
  * #ctypedef npy_int128     int128_t
  * 
  * ctypedef npy_uint8      uint8_t             # <<<<<<<<<<<<<<
@@ -462,7 +391,7 @@ typedef npy_int64 __pyx_t_5numpy_int64_t;
  */
 typedef npy_uint8 __pyx_t_5numpy_uint8_t;
 
-/* "numpy.pxd":730
+/* "numpy.pxd":727
  * 
  * ctypedef npy_uint8      uint8_t
  * ctypedef npy_uint16     uint16_t             # <<<<<<<<<<<<<<
@@ -471,7 +400,7 @@ typedef npy_uint8 __pyx_t_5numpy_uint8_t;
  */
 typedef npy_uint16 __pyx_t_5numpy_uint16_t;
 
-/* "numpy.pxd":731
+/* "numpy.pxd":728
  * ctypedef npy_uint8      uint8_t
  * ctypedef npy_uint16     uint16_t
  * ctypedef npy_uint32     uint32_t             # <<<<<<<<<<<<<<
@@ -480,7 +409,7 @@ typedef npy_uint16 __pyx_t_5numpy_uint16_t;
  */
 typedef npy_uint32 __pyx_t_5numpy_uint32_t;
 
-/* "numpy.pxd":732
+/* "numpy.pxd":729
  * ctypedef npy_uint16     uint16_t
  * ctypedef npy_uint32     uint32_t
  * ctypedef npy_uint64     uint64_t             # <<<<<<<<<<<<<<
@@ -489,7 +418,7 @@ typedef npy_uint32 __pyx_t_5numpy_uint32_t;
  */
 typedef npy_uint64 __pyx_t_5numpy_uint64_t;
 
-/* "numpy.pxd":736
+/* "numpy.pxd":733
  * #ctypedef npy_uint128    uint128_t
  * 
  * ctypedef npy_float32    float32_t             # <<<<<<<<<<<<<<
@@ -498,7 +427,7 @@ typedef npy_uint64 __pyx_t_5numpy_uint64_t;
  */
 typedef npy_float32 __pyx_t_5numpy_float32_t;
 
-/* "numpy.pxd":737
+/* "numpy.pxd":734
  * 
  * ctypedef npy_float32    float32_t
  * ctypedef npy_float64    float64_t             # <<<<<<<<<<<<<<
@@ -507,7 +436,7 @@ typedef npy_float32 __pyx_t_5numpy_float32_t;
  */
 typedef npy_float64 __pyx_t_5numpy_float64_t;
 
-/* "numpy.pxd":746
+/* "numpy.pxd":743
  * # The int types are mapped a bit surprising --
  * # numpy.int corresponds to 'l' and numpy.long to 'q'
  * ctypedef npy_long       int_t             # <<<<<<<<<<<<<<
@@ -516,7 +445,7 @@ typedef npy_float64 __pyx_t_5numpy_float64_t;
  */
 typedef npy_long __pyx_t_5numpy_int_t;
 
-/* "numpy.pxd":747
+/* "numpy.pxd":744
  * # numpy.int corresponds to 'l' and numpy.long to 'q'
  * ctypedef npy_long       int_t
  * ctypedef npy_longlong   long_t             # <<<<<<<<<<<<<<
@@ -525,7 +454,7 @@ typedef npy_long __pyx_t_5numpy_int_t;
  */
 typedef npy_longlong __pyx_t_5numpy_long_t;
 
-/* "numpy.pxd":748
+/* "numpy.pxd":745
  * ctypedef npy_long       int_t
  * ctypedef npy_longlong   long_t
  * ctypedef npy_longlong   longlong_t             # <<<<<<<<<<<<<<
@@ -534,7 +463,7 @@ typedef npy_longlong __pyx_t_5numpy_long_t;
  */
 typedef npy_longlong __pyx_t_5numpy_longlong_t;
 
-/* "numpy.pxd":750
+/* "numpy.pxd":747
  * ctypedef npy_longlong   longlong_t
  * 
  * ctypedef npy_ulong      uint_t             # <<<<<<<<<<<<<<
@@ -543,7 +472,7 @@ typedef npy_longlong __pyx_t_5numpy_longlong_t;
  */
 typedef npy_ulong __pyx_t_5numpy_uint_t;
 
-/* "numpy.pxd":751
+/* "numpy.pxd":748
  * 
  * ctypedef npy_ulong      uint_t
  * ctypedef npy_ulonglong  ulong_t             # <<<<<<<<<<<<<<
@@ -552,7 +481,7 @@ typedef npy_ulong __pyx_t_5numpy_uint_t;
  */
 typedef npy_ulonglong __pyx_t_5numpy_ulong_t;
 
-/* "numpy.pxd":752
+/* "numpy.pxd":749
  * ctypedef npy_ulong      uint_t
  * ctypedef npy_ulonglong  ulong_t
  * ctypedef npy_ulonglong  ulonglong_t             # <<<<<<<<<<<<<<
@@ -561,7 +490,7 @@ typedef npy_ulonglong __pyx_t_5numpy_ulong_t;
  */
 typedef npy_ulonglong __pyx_t_5numpy_ulonglong_t;
 
-/* "numpy.pxd":754
+/* "numpy.pxd":751
  * ctypedef npy_ulonglong  ulonglong_t
  * 
  * ctypedef npy_intp       intp_t             # <<<<<<<<<<<<<<
@@ -570,7 +499,7 @@ typedef npy_ulonglong __pyx_t_5numpy_ulonglong_t;
  */
 typedef npy_intp __pyx_t_5numpy_intp_t;
 
-/* "numpy.pxd":755
+/* "numpy.pxd":752
  * 
  * ctypedef npy_intp       intp_t
  * ctypedef npy_uintp      uintp_t             # <<<<<<<<<<<<<<
@@ -579,7 +508,7 @@ typedef npy_intp __pyx_t_5numpy_intp_t;
  */
 typedef npy_uintp __pyx_t_5numpy_uintp_t;
 
-/* "numpy.pxd":757
+/* "numpy.pxd":754
  * ctypedef npy_uintp      uintp_t
  * 
  * ctypedef npy_double     float_t             # <<<<<<<<<<<<<<
@@ -588,7 +517,7 @@ typedef npy_uintp __pyx_t_5numpy_uintp_t;
  */
 typedef npy_double __pyx_t_5numpy_float_t;
 
-/* "numpy.pxd":758
+/* "numpy.pxd":755
  * 
  * ctypedef npy_double     float_t
  * ctypedef npy_double     double_t             # <<<<<<<<<<<<<<
@@ -597,7 +526,7 @@ typedef npy_double __pyx_t_5numpy_float_t;
  */
 typedef npy_double __pyx_t_5numpy_double_t;
 
-/* "numpy.pxd":759
+/* "numpy.pxd":756
  * ctypedef npy_double     float_t
  * ctypedef npy_double     double_t
  * ctypedef npy_longdouble longdouble_t             # <<<<<<<<<<<<<<
@@ -614,6 +543,7 @@ typedef npy_longdouble __pyx_t_5numpy_longdouble_t;
  * cdef inline int int_max(int a, int b): return a if a >= b else b
  */
 typedef __pyx_t_5numpy_float_t __pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t;
+
 #if CYTHON_CCOMPLEX
   #ifdef __cplusplus
     typedef ::std::complex< float > __pyx_t_float_complex;
@@ -634,10 +564,9 @@ typedef __pyx_t_5numpy_float_t __pyx_t_7astropy_6nddata_11convolution_15boundary
     typedef struct { double real, imag; } __pyx_t_double_complex;
 #endif
 
-
 /*--- Type declarations ---*/
 
-/* "numpy.pxd":761
+/* "numpy.pxd":758
  * ctypedef npy_longdouble longdouble_t
  * 
  * ctypedef npy_cfloat      cfloat_t             # <<<<<<<<<<<<<<
@@ -646,7 +575,7 @@ typedef __pyx_t_5numpy_float_t __pyx_t_7astropy_6nddata_11convolution_15boundary
  */
 typedef npy_cfloat __pyx_t_5numpy_cfloat_t;
 
-/* "numpy.pxd":762
+/* "numpy.pxd":759
  * 
  * ctypedef npy_cfloat      cfloat_t
  * ctypedef npy_cdouble     cdouble_t             # <<<<<<<<<<<<<<
@@ -655,7 +584,7 @@ typedef npy_cfloat __pyx_t_5numpy_cfloat_t;
  */
 typedef npy_cdouble __pyx_t_5numpy_cdouble_t;
 
-/* "numpy.pxd":763
+/* "numpy.pxd":760
  * ctypedef npy_cfloat      cfloat_t
  * ctypedef npy_cdouble     cdouble_t
  * ctypedef npy_clongdouble clongdouble_t             # <<<<<<<<<<<<<<
@@ -664,7 +593,7 @@ typedef npy_cdouble __pyx_t_5numpy_cdouble_t;
  */
 typedef npy_clongdouble __pyx_t_5numpy_clongdouble_t;
 
-/* "numpy.pxd":765
+/* "numpy.pxd":762
  * ctypedef npy_clongdouble clongdouble_t
  * 
  * ctypedef npy_cdouble     complex_t             # <<<<<<<<<<<<<<
@@ -672,9 +601,12 @@ typedef npy_clongdouble __pyx_t_5numpy_clongdouble_t;
  * cdef inline object PyArray_MultiIterNew1(a):
  */
 typedef npy_cdouble __pyx_t_5numpy_complex_t;
+
+
 #ifndef CYTHON_REFNANNY
   #define CYTHON_REFNANNY 0
 #endif
+
 #if CYTHON_REFNANNY
   typedef struct {
     void (*INCREF)(void*, PyObject*, int);
@@ -687,21 +619,8 @@ typedef npy_cdouble __pyx_t_5numpy_complex_t;
   static __Pyx_RefNannyAPIStruct *__Pyx_RefNanny = NULL;
   static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname); /*proto*/
   #define __Pyx_RefNannyDeclarations void *__pyx_refnanny = NULL;
-#ifdef WITH_THREAD
-  #define __Pyx_RefNannySetupContext(name, acquire_gil) \
-          if (acquire_gil) { \
-              PyGILState_STATE __pyx_gilstate_save = PyGILState_Ensure(); \
-              __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__); \
-              PyGILState_Release(__pyx_gilstate_save); \
-          } else { \
-              __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__); \
-          }
-#else
-  #define __Pyx_RefNannySetupContext(name, acquire_gil) \
-          __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__)
-#endif
-  #define __Pyx_RefNannyFinishContext() \
-          __Pyx_RefNanny->FinishContext(&__pyx_refnanny)
+  #define __Pyx_RefNannySetupContext(name)           __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__)
+  #define __Pyx_RefNannyFinishContext()           __Pyx_RefNanny->FinishContext(&__pyx_refnanny)
   #define __Pyx_INCREF(r)  __Pyx_RefNanny->INCREF(__pyx_refnanny, (PyObject *)(r), __LINE__)
   #define __Pyx_DECREF(r)  __Pyx_RefNanny->DECREF(__pyx_refnanny, (PyObject *)(r), __LINE__)
   #define __Pyx_GOTREF(r)  __Pyx_RefNanny->GOTREF(__pyx_refnanny, (PyObject *)(r), __LINE__)
@@ -712,7 +631,7 @@ typedef npy_cdouble __pyx_t_5numpy_complex_t;
   #define __Pyx_XGIVEREF(r) do { if((r) != NULL) {__Pyx_GIVEREF(r);}} while(0)
 #else
   #define __Pyx_RefNannyDeclarations
-  #define __Pyx_RefNannySetupContext(name, acquire_gil)
+  #define __Pyx_RefNannySetupContext(name)
   #define __Pyx_RefNannyFinishContext()
   #define __Pyx_INCREF(r) Py_INCREF(r)
   #define __Pyx_DECREF(r) Py_DECREF(r)
@@ -723,25 +642,43 @@ typedef npy_cdouble __pyx_t_5numpy_complex_t;
   #define __Pyx_XGOTREF(r)
   #define __Pyx_XGIVEREF(r)
 #endif /* CYTHON_REFNANNY */
-#define __Pyx_CLEAR(r)    do { PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);} while(0)
-#define __Pyx_XCLEAR(r)   do { if((r) != NULL) {PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);}} while(0)
 
 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/
 
 static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact,
     Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found); /*proto*/
 
-static void __Pyx_RaiseDoubleKeywordsError(const char* func_name, PyObject* kw_name); /*proto*/
+static void __Pyx_RaiseDoubleKeywordsError(
+    const char* func_name, PyObject* kw_name); /*proto*/
 
-static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[], \
-    PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args, \
-    const char* function_name); /*proto*/
+static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[],     PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args,     const char* function_name); /*proto*/
 
 static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
     const char *name, int exact); /*proto*/
 
-static CYTHON_INLINE int  __Pyx_GetBufferAndValidate(Py_buffer* buf, PyObject* obj,
-    __Pyx_TypeInfo* dtype, int flags, int nd, int cast, __Pyx_BufFmt_StackElem* stack);
+/* Run-time type information about structs used with buffers */
+struct __Pyx_StructField_;
+
+typedef struct {
+  const char* name; /* for error messages only */
+  struct __Pyx_StructField_* fields;
+  size_t size;     /* sizeof(type) */
+  char typegroup; /* _R_eal, _C_omplex, Signed _I_nt, _U_nsigned int, _S_truct, _P_ointer, _O_bject */
+} __Pyx_TypeInfo;
+
+typedef struct __Pyx_StructField_ {
+  __Pyx_TypeInfo* type;
+  const char* name;
+  size_t offset;
+} __Pyx_StructField;
+
+typedef struct {
+  __Pyx_StructField* field;
+  size_t parent_offset;
+} __Pyx_BufFmt_StackElem;
+
+
+static CYTHON_INLINE int  __Pyx_GetBufferAndValidate(Py_buffer* buf, PyObject* obj, __Pyx_TypeInfo* dtype, int flags, int nd, int cast, __Pyx_BufFmt_StackElem* stack);
 static CYTHON_INLINE void __Pyx_SafeReleaseBuffer(Py_buffer* info);
 
 static CYTHON_INLINE long __Pyx_mod_long(long, long); /* proto */
@@ -754,10 +691,10 @@ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject
 static CYTHON_INLINE long __Pyx_div_long(long, long); /* proto */
 
 static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); /*proto*/
-
 #define __Pyx_BufPtrStrided1d(type, buf, i0, s0) (type)((char*)buf + i0 * s0)
 #define __Pyx_BufPtrStrided2d(type, buf, i0, s0, i1, s1) (type)((char*)buf + i0 * s0 + i1 * s1)
 #define __Pyx_BufPtrStrided3d(type, buf, i0, s0, i1, s1, i2, s2) (type)((char*)buf + i0 * s0 + i1 * s1 + i2 * s2)
+
 static CYTHON_INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index);
 
 static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(Py_ssize_t expected);
@@ -765,30 +702,16 @@ static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(Py_ssize_t expected);
 static CYTHON_INLINE void __Pyx_RaiseNoneNotIterableError(void);
 
 static void __Pyx_UnpackTupleError(PyObject *, Py_ssize_t index); /*proto*/
-
-typedef struct {
-  Py_ssize_t shape, strides, suboffsets;
-} __Pyx_Buf_DimInfo;
-typedef struct {
-  size_t refcount;
-  Py_buffer pybuffer;
-} __Pyx_Buffer;
-typedef struct {
-  __Pyx_Buffer *rcbuffer;
-  char *data;
-  __Pyx_Buf_DimInfo diminfo[8];
-} __Pyx_LocalBuf_ND;
-
 #if PY_MAJOR_VERSION < 3
-    static int __Pyx_GetBuffer(PyObject *obj, Py_buffer *view, int flags);
-    static void __Pyx_ReleaseBuffer(Py_buffer *view);
+static int __Pyx_GetBuffer(PyObject *obj, Py_buffer *view, int flags);
+static void __Pyx_ReleaseBuffer(Py_buffer *view);
 #else
-    #define __Pyx_GetBuffer PyObject_GetBuffer
-    #define __Pyx_ReleaseBuffer PyBuffer_Release
+#define __Pyx_GetBuffer PyObject_GetBuffer
+#define __Pyx_ReleaseBuffer PyBuffer_Release
 #endif
 
-static Py_ssize_t __Pyx_zeros[] = {0, 0, 0, 0, 0, 0, 0, 0};
-static Py_ssize_t __Pyx_minusones[] = {-1, -1, -1, -1, -1, -1, -1, -1};
+Py_ssize_t __Pyx_zeros[] = {0, 0, 0};
+Py_ssize_t __Pyx_minusones[] = {-1, -1, -1};
 
 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, long level); /*proto*/
 
@@ -804,6 +727,7 @@ static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, long level);
     #define __Pyx_CREAL(z) ((z).real)
     #define __Pyx_CIMAG(z) ((z).imag)
 #endif
+
 #if defined(_WIN32) && defined(__cplusplus) && CYTHON_CCOMPLEX
     #define __Pyx_SET_CREAL(z,x) ((z).real(x))
     #define __Pyx_SET_CIMAG(z,y) ((z).imag(y))
@@ -924,38 +848,15 @@ static CYTHON_INLINE signed PY_LONG_LONG __Pyx_PyInt_AsSignedLongLong(PyObject *
 
 static int __Pyx_check_binary_version(void);
 
-#if !defined(__Pyx_PyIdentifier_FromString)
-#if PY_MAJOR_VERSION < 3
-  #define __Pyx_PyIdentifier_FromString(s) PyString_FromString(s)
-#else
-  #define __Pyx_PyIdentifier_FromString(s) PyUnicode_FromString(s)
-#endif
-#endif
-
 static PyTypeObject *__Pyx_ImportType(const char *module_name, const char *class_name, size_t size, int strict);  /*proto*/
 
 static PyObject *__Pyx_ImportModule(const char *name); /*proto*/
 
-typedef struct {
-    int code_line;
-    PyCodeObject* code_object;
-} __Pyx_CodeObjectCacheEntry;
-struct __Pyx_CodeObjectCache {
-    int count;
-    int max_count;
-    __Pyx_CodeObjectCacheEntry* entries;
-};
-static struct __Pyx_CodeObjectCache __pyx_code_cache = {0,0,NULL};
-static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line);
-static PyCodeObject *__pyx_find_code_object(int code_line);
-static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object);
-
-static void __Pyx_AddTraceback(const char *funcname, int c_line,
-                               int py_line, const char *filename); /*proto*/
+static void __Pyx_AddTraceback(const char *funcname, int __pyx_clineno,
+                               int __pyx_lineno, const char *__pyx_filename); /*proto*/
 
 static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); /*proto*/
 
-
 /* Module declarations from 'cpython.buffer' */
 
 /* Module declarations from 'cpython.ref' */
@@ -974,14 +875,23 @@ static PyTypeObject *__pyx_ptype_5numpy_flatiter = 0;
 static PyTypeObject *__pyx_ptype_5numpy_broadcast = 0;
 static PyTypeObject *__pyx_ptype_5numpy_ndarray = 0;
 static PyTypeObject *__pyx_ptype_5numpy_ufunc = 0;
+static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew1(PyObject *); /*proto*/
+static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew2(PyObject *, PyObject *); /*proto*/
+static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew3(PyObject *, PyObject *, PyObject *); /*proto*/
+static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew4(PyObject *, PyObject *, PyObject *, PyObject *); /*proto*/
+static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew5(PyObject *, PyObject *, PyObject *, PyObject *, PyObject *); /*proto*/
 static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *, char *, char *, int *); /*proto*/
+static CYTHON_INLINE void __pyx_f_5numpy_set_array_base(PyArrayObject *, PyObject *); /*proto*/
+static CYTHON_INLINE PyObject *__pyx_f_5numpy_get_array_base(PyArrayObject *); /*proto*/
+
+/* Module declarations from 'cython.cython.view' */
 
 /* Module declarations from 'cython' */
 
 /* Module declarations from 'astropy.nddata.convolution.boundary_extend' */
 static CYTHON_INLINE int __pyx_f_7astropy_6nddata_11convolution_15boundary_extend_int_max(int, int); /*proto*/
 static CYTHON_INLINE int __pyx_f_7astropy_6nddata_11convolution_15boundary_extend_int_min(int, int); /*proto*/
-static __Pyx_TypeInfo __Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t = { "DTYPE_t", NULL, sizeof(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t), { 0 }, 0, 'R', 0, 0 };
+static __Pyx_TypeInfo __Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t = { "DTYPE_t", NULL, sizeof(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t), 'R' };
 #define __Pyx_MODULE_NAME "astropy.nddata.convolution.boundary_extend"
 int __pyx_module_is_main_astropy__nddata__convolution__boundary_extend = 0;
 
@@ -989,11 +899,6 @@ int __pyx_module_is_main_astropy__nddata__convolution__boundary_extend = 0;
 static PyObject *__pyx_builtin_ValueError;
 static PyObject *__pyx_builtin_range;
 static PyObject *__pyx_builtin_RuntimeError;
-static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_convolve1d_boundary_extend(CYTHON_UNUSED PyObject *__pyx_self, PyArrayObject *__pyx_v_f, PyArrayObject *__pyx_v_g); /* proto */
-static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_2convolve2d_boundary_extend(CYTHON_UNUSED PyObject *__pyx_self, PyArrayObject *__pyx_v_f, PyArrayObject *__pyx_v_g); /* proto */
-static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_4convolve3d_boundary_extend(CYTHON_UNUSED PyObject *__pyx_self, PyArrayObject *__pyx_v_f, PyArrayObject *__pyx_v_g); /* proto */
-static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags); /* proto */
-static void __pyx_pf_5numpy_7ndarray_2__releasebuffer__(PyArrayObject *__pyx_v_self, Py_buffer *__pyx_v_info); /* proto */
 static char __pyx_k_1[] = "Convolution kernel must have odd dimensions";
 static char __pyx_k_5[] = "ndarray is not C contiguous";
 static char __pyx_k_7[] = "ndarray is not Fortran contiguous";
@@ -1001,11 +906,10 @@ static char __pyx_k_9[] = "Non-native byte order not supported";
 static char __pyx_k_11[] = "unknown dtype code in numpy.pxd (%d)";
 static char __pyx_k_12[] = "Format string allocated too short, see comment in numpy.pxd";
 static char __pyx_k_15[] = "Format string allocated too short.";
-static char __pyx_k_19[] = "convolve1d_boundary_extend";
-static char __pyx_k_20[] = "/Users/erik/src/astropy/astropy/nddata/convolution/boundary_extend.pyx";
-static char __pyx_k_21[] = "astropy.nddata.convolution.boundary_extend";
-static char __pyx_k_24[] = "convolve2d_boundary_extend";
-static char __pyx_k_27[] = "convolve3d_boundary_extend";
+static char __pyx_k_17[] = "astropy.nddata.convolution.boundary_extend";
+static char __pyx_k_18[] = "convolve1d_boundary_extend";
+static char __pyx_k_19[] = "convolve2d_boundary_extend";
+static char __pyx_k_20[] = "convolve3d_boundary_extend";
 static char __pyx_k__B[] = "B";
 static char __pyx_k__H[] = "H";
 static char __pyx_k__I[] = "I";
@@ -1018,45 +922,16 @@ static char __pyx_k__f[] = "f";
 static char __pyx_k__g[] = "g";
 static char __pyx_k__h[] = "h";
 static char __pyx_k__i[] = "i";
-static char __pyx_k__j[] = "j";
-static char __pyx_k__k[] = "k";
 static char __pyx_k__l[] = "l";
 static char __pyx_k__q[] = "q";
 static char __pyx_k__Zd[] = "Zd";
 static char __pyx_k__Zf[] = "Zf";
 static char __pyx_k__Zg[] = "Zg";
-static char __pyx_k__ii[] = "ii";
-static char __pyx_k__jj[] = "jj";
-static char __pyx_k__kk[] = "kk";
 static char __pyx_k__np[] = "np";
-static char __pyx_k__nx[] = "nx";
-static char __pyx_k__ny[] = "ny";
-static char __pyx_k__nz[] = "nz";
-static char __pyx_k__bot[] = "bot";
-static char __pyx_k__iii[] = "iii";
-static char __pyx_k__jjj[] = "jjj";
-static char __pyx_k__ker[] = "ker";
-static char __pyx_k__kkk[] = "kkk";
-static char __pyx_k__nkx[] = "nkx";
-static char __pyx_k__nky[] = "nky";
-static char __pyx_k__nkz[] = "nkz";
-static char __pyx_k__top[] = "top";
-static char __pyx_k__val[] = "val";
-static char __pyx_k__wkx[] = "wkx";
-static char __pyx_k__wky[] = "wky";
-static char __pyx_k__wkz[] = "wkz";
-static char __pyx_k__conv[] = "conv";
 static char __pyx_k__DTYPE[] = "DTYPE";
 static char __pyx_k__dtype[] = "dtype";
 static char __pyx_k__empty[] = "empty";
-static char __pyx_k__fixed[] = "fixed";
 static char __pyx_k__float[] = "float";
-static char __pyx_k__iimax[] = "iimax";
-static char __pyx_k__iimin[] = "iimin";
-static char __pyx_k__jjmax[] = "jjmax";
-static char __pyx_k__jjmin[] = "jjmin";
-static char __pyx_k__kkmax[] = "kkmax";
-static char __pyx_k__kkmin[] = "kkmin";
 static char __pyx_k__numpy[] = "numpy";
 static char __pyx_k__range[] = "range";
 static char __pyx_k____main__[] = "__main__";
@@ -1067,11 +942,10 @@ static PyObject *__pyx_kp_s_1;
 static PyObject *__pyx_kp_u_11;
 static PyObject *__pyx_kp_u_12;
 static PyObject *__pyx_kp_u_15;
+static PyObject *__pyx_n_s_17;
+static PyObject *__pyx_n_s_18;
 static PyObject *__pyx_n_s_19;
-static PyObject *__pyx_kp_s_20;
-static PyObject *__pyx_n_s_21;
-static PyObject *__pyx_n_s_24;
-static PyObject *__pyx_n_s_27;
+static PyObject *__pyx_n_s_20;
 static PyObject *__pyx_kp_u_5;
 static PyObject *__pyx_kp_u_7;
 static PyObject *__pyx_kp_u_9;
@@ -1080,44 +954,14 @@ static PyObject *__pyx_n_s__RuntimeError;
 static PyObject *__pyx_n_s__ValueError;
 static PyObject *__pyx_n_s____main__;
 static PyObject *__pyx_n_s____test__;
-static PyObject *__pyx_n_s__bot;
-static PyObject *__pyx_n_s__conv;
 static PyObject *__pyx_n_s__dtype;
 static PyObject *__pyx_n_s__empty;
 static PyObject *__pyx_n_s__f;
-static PyObject *__pyx_n_s__fixed;
 static PyObject *__pyx_n_s__float;
 static PyObject *__pyx_n_s__g;
-static PyObject *__pyx_n_s__i;
-static PyObject *__pyx_n_s__ii;
-static PyObject *__pyx_n_s__iii;
-static PyObject *__pyx_n_s__iimax;
-static PyObject *__pyx_n_s__iimin;
-static PyObject *__pyx_n_s__j;
-static PyObject *__pyx_n_s__jj;
-static PyObject *__pyx_n_s__jjj;
-static PyObject *__pyx_n_s__jjmax;
-static PyObject *__pyx_n_s__jjmin;
-static PyObject *__pyx_n_s__k;
-static PyObject *__pyx_n_s__ker;
-static PyObject *__pyx_n_s__kk;
-static PyObject *__pyx_n_s__kkk;
-static PyObject *__pyx_n_s__kkmax;
-static PyObject *__pyx_n_s__kkmin;
-static PyObject *__pyx_n_s__nkx;
-static PyObject *__pyx_n_s__nky;
-static PyObject *__pyx_n_s__nkz;
 static PyObject *__pyx_n_s__np;
 static PyObject *__pyx_n_s__numpy;
-static PyObject *__pyx_n_s__nx;
-static PyObject *__pyx_n_s__ny;
-static PyObject *__pyx_n_s__nz;
 static PyObject *__pyx_n_s__range;
-static PyObject *__pyx_n_s__top;
-static PyObject *__pyx_n_s__val;
-static PyObject *__pyx_n_s__wkx;
-static PyObject *__pyx_n_s__wky;
-static PyObject *__pyx_n_s__wkz;
 static PyObject *__pyx_int_15;
 static PyObject *__pyx_k_tuple_2;
 static PyObject *__pyx_k_tuple_3;
@@ -1128,12 +972,6 @@ static PyObject *__pyx_k_tuple_10;
 static PyObject *__pyx_k_tuple_13;
 static PyObject *__pyx_k_tuple_14;
 static PyObject *__pyx_k_tuple_16;
-static PyObject *__pyx_k_tuple_17;
-static PyObject *__pyx_k_tuple_22;
-static PyObject *__pyx_k_tuple_25;
-static PyObject *__pyx_k_codeobj_18;
-static PyObject *__pyx_k_codeobj_23;
-static PyObject *__pyx_k_codeobj_26;
 
 /* "astropy/nddata/convolution/boundary_extend.pyx":8
  * ctypedef np.float_t DTYPE_t
@@ -1147,7 +985,7 @@ static CYTHON_INLINE int __pyx_f_7astropy_6nddata_11convolution_15boundary_exten
   int __pyx_r;
   __Pyx_RefNannyDeclarations
   int __pyx_t_1;
-  __Pyx_RefNannySetupContext("int_max", 0);
+  __Pyx_RefNannySetupContext("int_max");
   if ((__pyx_v_a >= __pyx_v_b)) {
     __pyx_t_1 = __pyx_v_a;
   } else {
@@ -1174,7 +1012,7 @@ static CYTHON_INLINE int __pyx_f_7astropy_6nddata_11convolution_15boundary_exten
   int __pyx_r;
   __Pyx_RefNannyDeclarations
   int __pyx_t_1;
-  __Pyx_RefNannySetupContext("int_min", 0);
+  __Pyx_RefNannySetupContext("int_min");
   if ((__pyx_v_a <= __pyx_v_b)) {
     __pyx_t_1 = __pyx_v_a;
   } else {
@@ -1189,72 +1027,6 @@ static CYTHON_INLINE int __pyx_f_7astropy_6nddata_11convolution_15boundary_exten
   return __pyx_r;
 }
 
-/* Python wrapper */
-static PyObject *__pyx_pw_7astropy_6nddata_11convolution_15boundary_extend_1convolve1d_boundary_extend(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static PyMethodDef __pyx_mdef_7astropy_6nddata_11convolution_15boundary_extend_1convolve1d_boundary_extend = {__Pyx_NAMESTR("convolve1d_boundary_extend"), (PyCFunction)__pyx_pw_7astropy_6nddata_11convolution_15boundary_extend_1convolve1d_boundary_extend, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(0)};
-static PyObject *__pyx_pw_7astropy_6nddata_11convolution_15boundary_extend_1convolve1d_boundary_extend(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
-  PyArrayObject *__pyx_v_f = 0;
-  PyArrayObject *__pyx_v_g = 0;
-  static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__f,&__pyx_n_s__g,0};
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("convolve1d_boundary_extend (wrapper)", 0);
-  __pyx_self = __pyx_self;
-  {
-    PyObject* values[2] = {0,0};
-    if (unlikely(__pyx_kwds)) {
-      Py_ssize_t kw_args;
-      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
-      switch (pos_args) {
-        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
-        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
-        case  0: break;
-        default: goto __pyx_L5_argtuple_error;
-      }
-      kw_args = PyDict_Size(__pyx_kwds);
-      switch (pos_args) {
-        case  0:
-        values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__f);
-        if (likely(values[0])) kw_args--;
-        else goto __pyx_L5_argtuple_error;
-        case  1:
-        values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__g);
-        if (likely(values[1])) kw_args--;
-        else {
-          __Pyx_RaiseArgtupleInvalid("convolve1d_boundary_extend", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 18; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-        }
-      }
-      if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "convolve1d_boundary_extend") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 18; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-      }
-    } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
-      goto __pyx_L5_argtuple_error;
-    } else {
-      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
-      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
-    }
-    __pyx_v_f = ((PyArrayObject *)values[0]);
-    __pyx_v_g = ((PyArrayObject *)values[1]);
-  }
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("convolve1d_boundary_extend", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 18; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-  __pyx_L3_error:;
-  __Pyx_AddTraceback("astropy.nddata.convolution.boundary_extend.convolve1d_boundary_extend", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return NULL;
-  __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_f), __pyx_ptype_5numpy_ndarray, 1, "f", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 18; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_g), __pyx_ptype_5numpy_ndarray, 1, "g", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 19; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_r = __pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_convolve1d_boundary_extend(__pyx_self, __pyx_v_f, __pyx_v_g);
-  goto __pyx_L0;
-  __pyx_L1_error:;
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
 /* "astropy/nddata/convolution/boundary_extend.pyx":18
  * 
  * @cython.boundscheck(False)  # turn off bounds-checking for entire function
@@ -1263,7 +1035,11 @@ static PyObject *__pyx_pw_7astropy_6nddata_11convolution_15boundary_extend_1conv
  * 
  */
 
-static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_convolve1d_boundary_extend(CYTHON_UNUSED PyObject *__pyx_self, PyArrayObject *__pyx_v_f, PyArrayObject *__pyx_v_g) {
+static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_convolve1d_boundary_extend(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static PyMethodDef __pyx_mdef_7astropy_6nddata_11convolution_15boundary_extend_convolve1d_boundary_extend = {__Pyx_NAMESTR("convolve1d_boundary_extend"), (PyCFunction)__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_convolve1d_boundary_extend, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(0)};
+static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_convolve1d_boundary_extend(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyArrayObject *__pyx_v_f = 0;
+  PyArrayObject *__pyx_v_g = 0;
   int __pyx_v_nx;
   int __pyx_v_nkx;
   int __pyx_v_wkx;
@@ -1278,14 +1054,18 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_convo
   __pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t __pyx_v_bot;
   __pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t __pyx_v_ker;
   __pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t __pyx_v_val;
-  __Pyx_LocalBuf_ND __pyx_pybuffernd_conv;
-  __Pyx_Buffer __pyx_pybuffer_conv;
-  __Pyx_LocalBuf_ND __pyx_pybuffernd_f;
-  __Pyx_Buffer __pyx_pybuffer_f;
-  __Pyx_LocalBuf_ND __pyx_pybuffernd_fixed;
-  __Pyx_Buffer __pyx_pybuffer_fixed;
-  __Pyx_LocalBuf_ND __pyx_pybuffernd_g;
-  __Pyx_Buffer __pyx_pybuffer_g;
+  Py_buffer __pyx_bstruct_conv;
+  Py_ssize_t __pyx_bstride_0_conv = 0;
+  Py_ssize_t __pyx_bshape_0_conv = 0;
+  Py_buffer __pyx_bstruct_g;
+  Py_ssize_t __pyx_bstride_0_g = 0;
+  Py_ssize_t __pyx_bshape_0_g = 0;
+  Py_buffer __pyx_bstruct_f;
+  Py_ssize_t __pyx_bstride_0_f = 0;
+  Py_ssize_t __pyx_bshape_0_f = 0;
+  Py_buffer __pyx_bstruct_fixed;
+  Py_ssize_t __pyx_bstride_0_fixed = 0;
+  Py_ssize_t __pyx_bshape_0_fixed = 0;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   int __pyx_t_1;
@@ -1320,33 +1100,70 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_convo
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("convolve1d_boundary_extend", 0);
-  __pyx_pybuffer_fixed.pybuffer.buf = NULL;
-  __pyx_pybuffer_fixed.refcount = 0;
-  __pyx_pybuffernd_fixed.data = NULL;
-  __pyx_pybuffernd_fixed.rcbuffer = &__pyx_pybuffer_fixed;
-  __pyx_pybuffer_conv.pybuffer.buf = NULL;
-  __pyx_pybuffer_conv.refcount = 0;
-  __pyx_pybuffernd_conv.data = NULL;
-  __pyx_pybuffernd_conv.rcbuffer = &__pyx_pybuffer_conv;
-  __pyx_pybuffer_f.pybuffer.buf = NULL;
-  __pyx_pybuffer_f.refcount = 0;
-  __pyx_pybuffernd_f.data = NULL;
-  __pyx_pybuffernd_f.rcbuffer = &__pyx_pybuffer_f;
-  __pyx_pybuffer_g.pybuffer.buf = NULL;
-  __pyx_pybuffer_g.refcount = 0;
-  __pyx_pybuffernd_g.data = NULL;
-  __pyx_pybuffernd_g.rcbuffer = &__pyx_pybuffer_g;
+  static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__f,&__pyx_n_s__g,0};
+  __Pyx_RefNannySetupContext("convolve1d_boundary_extend");
+  __pyx_self = __pyx_self;
+  {
+    PyObject* values[2] = {0,0};
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  0:
+        values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__f);
+        if (likely(values[0])) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+        case  1:
+        values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__g);
+        if (likely(values[1])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("convolve1d_boundary_extend", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 18; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "convolve1d_boundary_extend") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 18; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+    } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
+      goto __pyx_L5_argtuple_error;
+    } else {
+      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+    }
+    __pyx_v_f = ((PyArrayObject *)values[0]);
+    __pyx_v_g = ((PyArrayObject *)values[1]);
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("convolve1d_boundary_extend", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 18; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("astropy.nddata.convolution.boundary_extend.convolve1d_boundary_extend", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_bstruct_fixed.buf = NULL;
+  __pyx_bstruct_conv.buf = NULL;
+  __pyx_bstruct_f.buf = NULL;
+  __pyx_bstruct_g.buf = NULL;
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_f), __pyx_ptype_5numpy_ndarray, 1, "f", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 18; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_g), __pyx_ptype_5numpy_ndarray, 1, "g", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 19; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_f.rcbuffer->pybuffer, (PyObject*)__pyx_v_f, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 18; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_f, (PyObject*)__pyx_v_f, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 18; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
-  __pyx_pybuffernd_f.diminfo[0].strides = __pyx_pybuffernd_f.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_f.diminfo[0].shape = __pyx_pybuffernd_f.rcbuffer->pybuffer.shape[0];
+  __pyx_bstride_0_f = __pyx_bstruct_f.strides[0];
+  __pyx_bshape_0_f = __pyx_bstruct_f.shape[0];
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_g.rcbuffer->pybuffer, (PyObject*)__pyx_v_g, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 18; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_g, (PyObject*)__pyx_v_g, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 18; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
-  __pyx_pybuffernd_g.diminfo[0].strides = __pyx_pybuffernd_g.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_g.diminfo[0].shape = __pyx_pybuffernd_g.rcbuffer->pybuffer.shape[0];
+  __pyx_bstride_0_g = __pyx_bstruct_g.strides[0];
+  __pyx_bshape_0_g = __pyx_bstruct_g.shape[0];
 
   /* "astropy/nddata/convolution/boundary_extend.pyx":21
  *                                np.ndarray[DTYPE_t, ndim=1] g):
@@ -1370,9 +1187,9 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_convo
     __Pyx_Raise(__pyx_t_2, 0, 0, 0);
     __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
     {__pyx_filename = __pyx_f[0]; __pyx_lineno = 22; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    goto __pyx_L3;
+    goto __pyx_L6;
   }
-  __pyx_L3:;
+  __pyx_L6:;
 
   /* "astropy/nddata/convolution/boundary_extend.pyx":24
  *         raise ValueError("Convolution kernel must have odd dimensions")
@@ -1455,12 +1272,12 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_convo
   __pyx_t_2 = PyInt_FromLong(__pyx_v_nx); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 29; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
   __pyx_t_4 = PyList_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 29; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_4);
+  __Pyx_GOTREF(((PyObject *)__pyx_t_4));
   PyList_SET_ITEM(__pyx_t_4, 0, __pyx_t_2);
   __Pyx_GIVEREF(__pyx_t_2);
   __pyx_t_2 = 0;
   __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 29; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_GOTREF(((PyObject *)__pyx_t_2));
   PyTuple_SET_ITEM(__pyx_t_2, 0, ((PyObject *)__pyx_t_4));
   __Pyx_GIVEREF(((PyObject *)__pyx_t_4));
   __pyx_t_4 = 0;
@@ -1470,7 +1287,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_convo
   __Pyx_GOTREF(__pyx_t_7);
   if (PyDict_SetItem(__pyx_t_4, ((PyObject *)__pyx_n_s__dtype), __pyx_t_7) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 29; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-  __pyx_t_7 = PyObject_Call(__pyx_t_3, ((PyObject *)__pyx_t_2), ((PyObject *)__pyx_t_4)); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 29; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_7 = PyEval_CallObjectWithKeywords(__pyx_t_3, ((PyObject *)__pyx_t_2), ((PyObject *)__pyx_t_4)); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 29; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_7);
   __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
   __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
@@ -1479,10 +1296,11 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_convo
   __pyx_t_8 = ((PyArrayObject *)__pyx_t_7);
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_fixed.rcbuffer->pybuffer, (PyObject*)__pyx_t_8, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 1, 0, __pyx_stack) == -1)) {
-      __pyx_v_fixed = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf = NULL;
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_fixed, (PyObject*)__pyx_t_8, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 1, 0, __pyx_stack) == -1)) {
+      __pyx_v_fixed = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_fixed.buf = NULL;
       {__pyx_filename = __pyx_f[0]; __pyx_lineno = 29; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    } else {__pyx_pybuffernd_fixed.diminfo[0].strides = __pyx_pybuffernd_fixed.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_fixed.diminfo[0].shape = __pyx_pybuffernd_fixed.rcbuffer->pybuffer.shape[0];
+    } else {__pyx_bstride_0_fixed = __pyx_bstruct_fixed.strides[0];
+      __pyx_bshape_0_fixed = __pyx_bstruct_fixed.shape[0];
     }
   }
   __pyx_t_8 = 0;
@@ -1504,12 +1322,12 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_convo
   __pyx_t_7 = PyInt_FromLong(__pyx_v_nx); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 30; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_7);
   __pyx_t_2 = PyList_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 30; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_GOTREF(((PyObject *)__pyx_t_2));
   PyList_SET_ITEM(__pyx_t_2, 0, __pyx_t_7);
   __Pyx_GIVEREF(__pyx_t_7);
   __pyx_t_7 = 0;
   __pyx_t_7 = PyTuple_New(1); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 30; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_7);
+  __Pyx_GOTREF(((PyObject *)__pyx_t_7));
   PyTuple_SET_ITEM(__pyx_t_7, 0, ((PyObject *)__pyx_t_2));
   __Pyx_GIVEREF(((PyObject *)__pyx_t_2));
   __pyx_t_2 = 0;
@@ -1519,7 +1337,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_convo
   __Pyx_GOTREF(__pyx_t_3);
   if (PyDict_SetItem(__pyx_t_2, ((PyObject *)__pyx_n_s__dtype), __pyx_t_3) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 30; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  __pyx_t_3 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_t_7), ((PyObject *)__pyx_t_2)); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 30; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_3 = PyEval_CallObjectWithKeywords(__pyx_t_4, ((PyObject *)__pyx_t_7), ((PyObject *)__pyx_t_2)); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 30; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_3);
   __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
   __Pyx_DECREF(((PyObject *)__pyx_t_7)); __pyx_t_7 = 0;
@@ -1528,10 +1346,11 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_convo
   __pyx_t_9 = ((PyArrayObject *)__pyx_t_3);
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_conv.rcbuffer->pybuffer, (PyObject*)__pyx_t_9, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 1, 0, __pyx_stack) == -1)) {
-      __pyx_v_conv = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_conv.rcbuffer->pybuffer.buf = NULL;
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_conv, (PyObject*)__pyx_t_9, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 1, 0, __pyx_stack) == -1)) {
+      __pyx_v_conv = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_conv.buf = NULL;
       {__pyx_filename = __pyx_f[0]; __pyx_lineno = 30; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    } else {__pyx_pybuffernd_conv.diminfo[0].strides = __pyx_pybuffernd_conv.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_conv.diminfo[0].shape = __pyx_pybuffernd_conv.rcbuffer->pybuffer.shape[0];
+    } else {__pyx_bstride_0_conv = __pyx_bstruct_conv.strides[0];
+      __pyx_bshape_0_conv = __pyx_bstruct_conv.shape[0];
     }
   }
   __pyx_t_9 = 0;
@@ -1557,7 +1376,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_convo
  *             bot = 0.
  */
     __pyx_t_12 = __pyx_v_i;
-    __pyx_t_6 = npy_isnan((*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_pybuffernd_f.rcbuffer->pybuffer.buf, __pyx_t_12, __pyx_pybuffernd_f.diminfo[0].strides)));
+    __pyx_t_6 = npy_isnan((*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_bstruct_f.buf, __pyx_t_12, __pyx_bstride_0_f)));
     if (__pyx_t_6) {
 
       /* "astropy/nddata/convolution/boundary_extend.pyx":42
@@ -1624,7 +1443,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_convo
  *                     ker = g[<unsigned int>(wkx + ii - i)]
  */
         __pyx_t_15 = __pyx_v_iii;
-        __pyx_v_val = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_pybuffernd_f.rcbuffer->pybuffer.buf, __pyx_t_15, __pyx_pybuffernd_f.diminfo[0].strides));
+        __pyx_v_val = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_bstruct_f.buf, __pyx_t_15, __pyx_bstride_0_f));
 
         /* "astropy/nddata/convolution/boundary_extend.pyx":49
  *                 iii = int_min(int_max(ii, 0), nx - 1)
@@ -1644,7 +1463,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_convo
  *                     bot += ker
  */
           __pyx_t_16 = ((unsigned int)((__pyx_v_wkx + __pyx_v_ii) - __pyx_v_i));
-          __pyx_v_ker = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_pybuffernd_g.rcbuffer->pybuffer.buf, __pyx_t_16, __pyx_pybuffernd_g.diminfo[0].strides));
+          __pyx_v_ker = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_bstruct_g.buf, __pyx_t_16, __pyx_bstride_0_g));
 
           /* "astropy/nddata/convolution/boundary_extend.pyx":51
  *                 if not npy_isnan(val):
@@ -1663,9 +1482,9 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_convo
  *             if bot != 0.:
  */
           __pyx_v_bot = (__pyx_v_bot + __pyx_v_ker);
-          goto __pyx_L9;
+          goto __pyx_L12;
         }
-        __pyx_L9:;
+        __pyx_L12:;
       }
 
       /* "astropy/nddata/convolution/boundary_extend.pyx":54
@@ -1690,8 +1509,8 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_convo
           {__pyx_filename = __pyx_f[0]; __pyx_lineno = 55; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         }
         __pyx_t_17 = __pyx_v_i;
-        *__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_17, __pyx_pybuffernd_fixed.diminfo[0].strides) = (__pyx_v_top / __pyx_v_bot);
-        goto __pyx_L10;
+        *__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_17, __pyx_bstride_0_fixed) = (__pyx_v_top / __pyx_v_bot);
+        goto __pyx_L13;
       }
       /*else*/ {
 
@@ -1704,10 +1523,10 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_convo
  */
         __pyx_t_18 = __pyx_v_i;
         __pyx_t_19 = __pyx_v_i;
-        *__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_19, __pyx_pybuffernd_fixed.diminfo[0].strides) = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_pybuffernd_f.rcbuffer->pybuffer.buf, __pyx_t_18, __pyx_pybuffernd_f.diminfo[0].strides));
+        *__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_19, __pyx_bstride_0_fixed) = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_bstruct_f.buf, __pyx_t_18, __pyx_bstride_0_f));
       }
-      __pyx_L10:;
-      goto __pyx_L6;
+      __pyx_L13:;
+      goto __pyx_L9;
     }
     /*else*/ {
 
@@ -1720,9 +1539,9 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_convo
  */
       __pyx_t_20 = __pyx_v_i;
       __pyx_t_21 = __pyx_v_i;
-      *__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_21, __pyx_pybuffernd_fixed.diminfo[0].strides) = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_pybuffernd_f.rcbuffer->pybuffer.buf, __pyx_t_20, __pyx_pybuffernd_f.diminfo[0].strides));
+      *__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_21, __pyx_bstride_0_fixed) = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_bstruct_f.buf, __pyx_t_20, __pyx_bstride_0_f));
     }
-    __pyx_L6:;
+    __pyx_L9:;
   }
 
   /* "astropy/nddata/convolution/boundary_extend.pyx":62
@@ -1744,7 +1563,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_convo
  *             bot = 0.
  */
     __pyx_t_22 = __pyx_v_i;
-    __pyx_t_6 = (!npy_isnan((*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_22, __pyx_pybuffernd_fixed.diminfo[0].strides))));
+    __pyx_t_6 = (!npy_isnan((*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_22, __pyx_bstride_0_fixed))));
     if (__pyx_t_6) {
 
       /* "astropy/nddata/convolution/boundary_extend.pyx":64
@@ -1811,7 +1630,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_convo
  *                 if not npy_isnan(val):
  */
         __pyx_t_23 = __pyx_v_iii;
-        __pyx_v_val = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_23, __pyx_pybuffernd_fixed.diminfo[0].strides));
+        __pyx_v_val = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_23, __pyx_bstride_0_fixed));
 
         /* "astropy/nddata/convolution/boundary_extend.pyx":71
  *                 iii = int_min(int_max(ii, 0), nx - 1)
@@ -1821,7 +1640,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_convo
  *                     top += val * ker
  */
         __pyx_t_24 = ((unsigned int)((__pyx_v_wkx + __pyx_v_ii) - __pyx_v_i));
-        __pyx_v_ker = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_pybuffernd_g.rcbuffer->pybuffer.buf, __pyx_t_24, __pyx_pybuffernd_g.diminfo[0].strides));
+        __pyx_v_ker = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_bstruct_g.buf, __pyx_t_24, __pyx_bstride_0_g));
 
         /* "astropy/nddata/convolution/boundary_extend.pyx":72
  *                 val = fixed[iii]
@@ -1850,9 +1669,9 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_convo
  *                 conv[i] = top / bot
  */
           __pyx_v_bot = (__pyx_v_bot + __pyx_v_ker);
-          goto __pyx_L16;
+          goto __pyx_L19;
         }
-        __pyx_L16:;
+        __pyx_L19:;
       }
 
       /* "astropy/nddata/convolution/boundary_extend.pyx":75
@@ -1877,8 +1696,8 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_convo
           {__pyx_filename = __pyx_f[0]; __pyx_lineno = 76; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         }
         __pyx_t_25 = __pyx_v_i;
-        *__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_pybuffernd_conv.rcbuffer->pybuffer.buf, __pyx_t_25, __pyx_pybuffernd_conv.diminfo[0].strides) = (__pyx_v_top / __pyx_v_bot);
-        goto __pyx_L17;
+        *__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_bstruct_conv.buf, __pyx_t_25, __pyx_bstride_0_conv) = (__pyx_v_top / __pyx_v_bot);
+        goto __pyx_L20;
       }
       /*else*/ {
 
@@ -1891,10 +1710,10 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_convo
  */
         __pyx_t_26 = __pyx_v_i;
         __pyx_t_27 = __pyx_v_i;
-        *__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_pybuffernd_conv.rcbuffer->pybuffer.buf, __pyx_t_27, __pyx_pybuffernd_conv.diminfo[0].strides) = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_26, __pyx_pybuffernd_fixed.diminfo[0].strides));
+        *__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_bstruct_conv.buf, __pyx_t_27, __pyx_bstride_0_conv) = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_26, __pyx_bstride_0_fixed));
       }
-      __pyx_L17:;
-      goto __pyx_L13;
+      __pyx_L20:;
+      goto __pyx_L16;
     }
     /*else*/ {
 
@@ -1907,9 +1726,9 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_convo
  */
       __pyx_t_28 = __pyx_v_i;
       __pyx_t_29 = __pyx_v_i;
-      *__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_pybuffernd_conv.rcbuffer->pybuffer.buf, __pyx_t_29, __pyx_pybuffernd_conv.diminfo[0].strides) = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_28, __pyx_pybuffernd_fixed.diminfo[0].strides));
+      *__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_bstruct_conv.buf, __pyx_t_29, __pyx_bstride_0_conv) = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_28, __pyx_bstride_0_fixed));
     }
-    __pyx_L13:;
+    __pyx_L16:;
   }
 
   /* "astropy/nddata/convolution/boundary_extend.pyx":82
@@ -1933,19 +1752,19 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_convo
   __Pyx_XDECREF(__pyx_t_7);
   { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;
     __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);
-    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_conv.rcbuffer->pybuffer);
-    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_f.rcbuffer->pybuffer);
-    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_fixed.rcbuffer->pybuffer);
-    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_g.rcbuffer->pybuffer);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_conv);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_g);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_f);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_fixed);
   __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
   __Pyx_AddTraceback("astropy.nddata.convolution.boundary_extend.convolve1d_boundary_extend", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   goto __pyx_L2;
   __pyx_L0:;
-  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_conv.rcbuffer->pybuffer);
-  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_f.rcbuffer->pybuffer);
-  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_fixed.rcbuffer->pybuffer);
-  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_g.rcbuffer->pybuffer);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_conv);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_g);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_f);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_fixed);
   __pyx_L2:;
   __Pyx_XDECREF((PyObject *)__pyx_v_fixed);
   __Pyx_XDECREF((PyObject *)__pyx_v_conv);
@@ -1954,72 +1773,6 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_convo
   return __pyx_r;
 }
 
-/* Python wrapper */
-static PyObject *__pyx_pw_7astropy_6nddata_11convolution_15boundary_extend_3convolve2d_boundary_extend(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static PyMethodDef __pyx_mdef_7astropy_6nddata_11convolution_15boundary_extend_3convolve2d_boundary_extend = {__Pyx_NAMESTR("convolve2d_boundary_extend"), (PyCFunction)__pyx_pw_7astropy_6nddata_11convolution_15boundary_extend_3convolve2d_boundary_extend, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(0)};
-static PyObject *__pyx_pw_7astropy_6nddata_11convolution_15boundary_extend_3convolve2d_boundary_extend(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
-  PyArrayObject *__pyx_v_f = 0;
-  PyArrayObject *__pyx_v_g = 0;
-  static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__f,&__pyx_n_s__g,0};
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("convolve2d_boundary_extend (wrapper)", 0);
-  __pyx_self = __pyx_self;
-  {
-    PyObject* values[2] = {0,0};
-    if (unlikely(__pyx_kwds)) {
-      Py_ssize_t kw_args;
-      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
-      switch (pos_args) {
-        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
-        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
-        case  0: break;
-        default: goto __pyx_L5_argtuple_error;
-      }
-      kw_args = PyDict_Size(__pyx_kwds);
-      switch (pos_args) {
-        case  0:
-        values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__f);
-        if (likely(values[0])) kw_args--;
-        else goto __pyx_L5_argtuple_error;
-        case  1:
-        values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__g);
-        if (likely(values[1])) kw_args--;
-        else {
-          __Pyx_RaiseArgtupleInvalid("convolve2d_boundary_extend", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 86; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-        }
-      }
-      if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "convolve2d_boundary_extend") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 86; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-      }
-    } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
-      goto __pyx_L5_argtuple_error;
-    } else {
-      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
-      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
-    }
-    __pyx_v_f = ((PyArrayObject *)values[0]);
-    __pyx_v_g = ((PyArrayObject *)values[1]);
-  }
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("convolve2d_boundary_extend", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 86; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-  __pyx_L3_error:;
-  __Pyx_AddTraceback("astropy.nddata.convolution.boundary_extend.convolve2d_boundary_extend", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return NULL;
-  __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_f), __pyx_ptype_5numpy_ndarray, 1, "f", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 86; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_g), __pyx_ptype_5numpy_ndarray, 1, "g", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 87; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_r = __pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_2convolve2d_boundary_extend(__pyx_self, __pyx_v_f, __pyx_v_g);
-  goto __pyx_L0;
-  __pyx_L1_error:;
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
 /* "astropy/nddata/convolution/boundary_extend.pyx":86
  * 
  * @cython.boundscheck(False)  # turn off bounds-checking for entire function
@@ -2028,7 +1781,11 @@ static PyObject *__pyx_pw_7astropy_6nddata_11convolution_15boundary_extend_3conv
  * 
  */
 
-static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_2convolve2d_boundary_extend(CYTHON_UNUSED PyObject *__pyx_self, PyArrayObject *__pyx_v_f, PyArrayObject *__pyx_v_g) {
+static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_1convolve2d_boundary_extend(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static PyMethodDef __pyx_mdef_7astropy_6nddata_11convolution_15boundary_extend_1convolve2d_boundary_extend = {__Pyx_NAMESTR("convolve2d_boundary_extend"), (PyCFunction)__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_1convolve2d_boundary_extend, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(0)};
+static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_1convolve2d_boundary_extend(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyArrayObject *__pyx_v_f = 0;
+  PyArrayObject *__pyx_v_g = 0;
   int __pyx_v_nx;
   int __pyx_v_ny;
   int __pyx_v_nkx;
@@ -2051,14 +1808,26 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_2conv
   __pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t __pyx_v_bot;
   __pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t __pyx_v_ker;
   __pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t __pyx_v_val;
-  __Pyx_LocalBuf_ND __pyx_pybuffernd_conv;
-  __Pyx_Buffer __pyx_pybuffer_conv;
-  __Pyx_LocalBuf_ND __pyx_pybuffernd_f;
-  __Pyx_Buffer __pyx_pybuffer_f;
-  __Pyx_LocalBuf_ND __pyx_pybuffernd_fixed;
-  __Pyx_Buffer __pyx_pybuffer_fixed;
-  __Pyx_LocalBuf_ND __pyx_pybuffernd_g;
-  __Pyx_Buffer __pyx_pybuffer_g;
+  Py_buffer __pyx_bstruct_conv;
+  Py_ssize_t __pyx_bstride_0_conv = 0;
+  Py_ssize_t __pyx_bstride_1_conv = 0;
+  Py_ssize_t __pyx_bshape_0_conv = 0;
+  Py_ssize_t __pyx_bshape_1_conv = 0;
+  Py_buffer __pyx_bstruct_g;
+  Py_ssize_t __pyx_bstride_0_g = 0;
+  Py_ssize_t __pyx_bstride_1_g = 0;
+  Py_ssize_t __pyx_bshape_0_g = 0;
+  Py_ssize_t __pyx_bshape_1_g = 0;
+  Py_buffer __pyx_bstruct_f;
+  Py_ssize_t __pyx_bstride_0_f = 0;
+  Py_ssize_t __pyx_bstride_1_f = 0;
+  Py_ssize_t __pyx_bshape_0_f = 0;
+  Py_ssize_t __pyx_bshape_1_f = 0;
+  Py_buffer __pyx_bstruct_fixed;
+  Py_ssize_t __pyx_bstride_0_fixed = 0;
+  Py_ssize_t __pyx_bstride_1_fixed = 0;
+  Py_ssize_t __pyx_bshape_0_fixed = 0;
+  Py_ssize_t __pyx_bshape_1_fixed = 0;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   int __pyx_t_1;
@@ -2113,33 +1882,70 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_2conv
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("convolve2d_boundary_extend", 0);
-  __pyx_pybuffer_fixed.pybuffer.buf = NULL;
-  __pyx_pybuffer_fixed.refcount = 0;
-  __pyx_pybuffernd_fixed.data = NULL;
-  __pyx_pybuffernd_fixed.rcbuffer = &__pyx_pybuffer_fixed;
-  __pyx_pybuffer_conv.pybuffer.buf = NULL;
-  __pyx_pybuffer_conv.refcount = 0;
-  __pyx_pybuffernd_conv.data = NULL;
-  __pyx_pybuffernd_conv.rcbuffer = &__pyx_pybuffer_conv;
-  __pyx_pybuffer_f.pybuffer.buf = NULL;
-  __pyx_pybuffer_f.refcount = 0;
-  __pyx_pybuffernd_f.data = NULL;
-  __pyx_pybuffernd_f.rcbuffer = &__pyx_pybuffer_f;
-  __pyx_pybuffer_g.pybuffer.buf = NULL;
-  __pyx_pybuffer_g.refcount = 0;
-  __pyx_pybuffernd_g.data = NULL;
-  __pyx_pybuffernd_g.rcbuffer = &__pyx_pybuffer_g;
+  static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__f,&__pyx_n_s__g,0};
+  __Pyx_RefNannySetupContext("convolve2d_boundary_extend");
+  __pyx_self = __pyx_self;
+  {
+    PyObject* values[2] = {0,0};
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  0:
+        values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__f);
+        if (likely(values[0])) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+        case  1:
+        values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__g);
+        if (likely(values[1])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("convolve2d_boundary_extend", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 86; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "convolve2d_boundary_extend") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 86; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+    } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
+      goto __pyx_L5_argtuple_error;
+    } else {
+      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+    }
+    __pyx_v_f = ((PyArrayObject *)values[0]);
+    __pyx_v_g = ((PyArrayObject *)values[1]);
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("convolve2d_boundary_extend", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 86; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("astropy.nddata.convolution.boundary_extend.convolve2d_boundary_extend", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_bstruct_fixed.buf = NULL;
+  __pyx_bstruct_conv.buf = NULL;
+  __pyx_bstruct_f.buf = NULL;
+  __pyx_bstruct_g.buf = NULL;
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_f), __pyx_ptype_5numpy_ndarray, 1, "f", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 86; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_g), __pyx_ptype_5numpy_ndarray, 1, "g", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 87; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_f.rcbuffer->pybuffer, (PyObject*)__pyx_v_f, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 86; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_f, (PyObject*)__pyx_v_f, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 86; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
-  __pyx_pybuffernd_f.diminfo[0].strides = __pyx_pybuffernd_f.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_f.diminfo[0].shape = __pyx_pybuffernd_f.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_f.diminfo[1].strides = __pyx_pybuffernd_f.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_f.diminfo[1].shape = __pyx_pybuffernd_f.rcbuffer->pybuffer.shape[1];
+  __pyx_bstride_0_f = __pyx_bstruct_f.strides[0]; __pyx_bstride_1_f = __pyx_bstruct_f.strides[1];
+  __pyx_bshape_0_f = __pyx_bstruct_f.shape[0]; __pyx_bshape_1_f = __pyx_bstruct_f.shape[1];
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_g.rcbuffer->pybuffer, (PyObject*)__pyx_v_g, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 86; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_g, (PyObject*)__pyx_v_g, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 86; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
-  __pyx_pybuffernd_g.diminfo[0].strides = __pyx_pybuffernd_g.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_g.diminfo[0].shape = __pyx_pybuffernd_g.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_g.diminfo[1].strides = __pyx_pybuffernd_g.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_g.diminfo[1].shape = __pyx_pybuffernd_g.rcbuffer->pybuffer.shape[1];
+  __pyx_bstride_0_g = __pyx_bstruct_g.strides[0]; __pyx_bstride_1_g = __pyx_bstruct_g.strides[1];
+  __pyx_bshape_0_g = __pyx_bstruct_g.shape[0]; __pyx_bshape_1_g = __pyx_bstruct_g.shape[1];
 
   /* "astropy/nddata/convolution/boundary_extend.pyx":89
  *                                np.ndarray[DTYPE_t, ndim=2] g):
@@ -2169,9 +1975,9 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_2conv
     __Pyx_Raise(__pyx_t_4, 0, 0, 0);
     __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
     {__pyx_filename = __pyx_f[0]; __pyx_lineno = 90; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    goto __pyx_L3;
+    goto __pyx_L6;
   }
-  __pyx_L3:;
+  __pyx_L6:;
 
   /* "astropy/nddata/convolution/boundary_extend.pyx":92
  *         raise ValueError("Convolution kernel must have odd dimensions")
@@ -2283,7 +2089,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_2conv
   __pyx_t_6 = PyInt_FromLong(__pyx_v_ny); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 100; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_6);
   __pyx_t_7 = PyList_New(2); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 100; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_7);
+  __Pyx_GOTREF(((PyObject *)__pyx_t_7));
   PyList_SET_ITEM(__pyx_t_7, 0, __pyx_t_4);
   __Pyx_GIVEREF(__pyx_t_4);
   PyList_SET_ITEM(__pyx_t_7, 1, __pyx_t_6);
@@ -2291,7 +2097,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_2conv
   __pyx_t_4 = 0;
   __pyx_t_6 = 0;
   __pyx_t_6 = PyTuple_New(1); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 100; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_6);
+  __Pyx_GOTREF(((PyObject *)__pyx_t_6));
   PyTuple_SET_ITEM(__pyx_t_6, 0, ((PyObject *)__pyx_t_7));
   __Pyx_GIVEREF(((PyObject *)__pyx_t_7));
   __pyx_t_7 = 0;
@@ -2301,7 +2107,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_2conv
   __Pyx_GOTREF(__pyx_t_4);
   if (PyDict_SetItem(__pyx_t_7, ((PyObject *)__pyx_n_s__dtype), __pyx_t_4) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 100; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  __pyx_t_4 = PyObject_Call(__pyx_t_5, ((PyObject *)__pyx_t_6), ((PyObject *)__pyx_t_7)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 100; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_4 = PyEval_CallObjectWithKeywords(__pyx_t_5, ((PyObject *)__pyx_t_6), ((PyObject *)__pyx_t_7)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 100; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_4);
   __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
   __Pyx_DECREF(((PyObject *)__pyx_t_6)); __pyx_t_6 = 0;
@@ -2310,10 +2116,11 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_2conv
   __pyx_t_8 = ((PyArrayObject *)__pyx_t_4);
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_fixed.rcbuffer->pybuffer, (PyObject*)__pyx_t_8, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack) == -1)) {
-      __pyx_v_fixed = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf = NULL;
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_fixed, (PyObject*)__pyx_t_8, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack) == -1)) {
+      __pyx_v_fixed = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_fixed.buf = NULL;
       {__pyx_filename = __pyx_f[0]; __pyx_lineno = 100; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    } else {__pyx_pybuffernd_fixed.diminfo[0].strides = __pyx_pybuffernd_fixed.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_fixed.diminfo[0].shape = __pyx_pybuffernd_fixed.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_fixed.diminfo[1].strides = __pyx_pybuffernd_fixed.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_fixed.diminfo[1].shape = __pyx_pybuffernd_fixed.rcbuffer->pybuffer.shape[1];
+    } else {__pyx_bstride_0_fixed = __pyx_bstruct_fixed.strides[0]; __pyx_bstride_1_fixed = __pyx_bstruct_fixed.strides[1];
+      __pyx_bshape_0_fixed = __pyx_bstruct_fixed.shape[0]; __pyx_bshape_1_fixed = __pyx_bstruct_fixed.shape[1];
     }
   }
   __pyx_t_8 = 0;
@@ -2337,7 +2144,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_2conv
   __pyx_t_6 = PyInt_FromLong(__pyx_v_ny); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 101; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_6);
   __pyx_t_5 = PyList_New(2); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 101; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_5);
+  __Pyx_GOTREF(((PyObject *)__pyx_t_5));
   PyList_SET_ITEM(__pyx_t_5, 0, __pyx_t_4);
   __Pyx_GIVEREF(__pyx_t_4);
   PyList_SET_ITEM(__pyx_t_5, 1, __pyx_t_6);
@@ -2345,7 +2152,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_2conv
   __pyx_t_4 = 0;
   __pyx_t_6 = 0;
   __pyx_t_6 = PyTuple_New(1); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 101; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_6);
+  __Pyx_GOTREF(((PyObject *)__pyx_t_6));
   PyTuple_SET_ITEM(__pyx_t_6, 0, ((PyObject *)__pyx_t_5));
   __Pyx_GIVEREF(((PyObject *)__pyx_t_5));
   __pyx_t_5 = 0;
@@ -2355,7 +2162,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_2conv
   __Pyx_GOTREF(__pyx_t_4);
   if (PyDict_SetItem(__pyx_t_5, ((PyObject *)__pyx_n_s__dtype), __pyx_t_4) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 101; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  __pyx_t_4 = PyObject_Call(__pyx_t_7, ((PyObject *)__pyx_t_6), ((PyObject *)__pyx_t_5)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 101; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_4 = PyEval_CallObjectWithKeywords(__pyx_t_7, ((PyObject *)__pyx_t_6), ((PyObject *)__pyx_t_5)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 101; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_4);
   __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
   __Pyx_DECREF(((PyObject *)__pyx_t_6)); __pyx_t_6 = 0;
@@ -2364,10 +2171,11 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_2conv
   __pyx_t_9 = ((PyArrayObject *)__pyx_t_4);
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_conv.rcbuffer->pybuffer, (PyObject*)__pyx_t_9, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack) == -1)) {
-      __pyx_v_conv = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_conv.rcbuffer->pybuffer.buf = NULL;
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_conv, (PyObject*)__pyx_t_9, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack) == -1)) {
+      __pyx_v_conv = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_conv.buf = NULL;
       {__pyx_filename = __pyx_f[0]; __pyx_lineno = 101; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    } else {__pyx_pybuffernd_conv.diminfo[0].strides = __pyx_pybuffernd_conv.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_conv.diminfo[0].shape = __pyx_pybuffernd_conv.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_conv.diminfo[1].strides = __pyx_pybuffernd_conv.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_conv.diminfo[1].shape = __pyx_pybuffernd_conv.rcbuffer->pybuffer.shape[1];
+    } else {__pyx_bstride_0_conv = __pyx_bstruct_conv.strides[0]; __pyx_bstride_1_conv = __pyx_bstruct_conv.strides[1];
+      __pyx_bshape_0_conv = __pyx_bstruct_conv.shape[0]; __pyx_bshape_1_conv = __pyx_bstruct_conv.shape[1];
     }
   }
   __pyx_t_9 = 0;
@@ -2405,7 +2213,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_2conv
  */
       __pyx_t_14 = __pyx_v_i;
       __pyx_t_15 = __pyx_v_j;
-      __pyx_t_2 = npy_isnan((*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_pybuffernd_f.rcbuffer->pybuffer.buf, __pyx_t_14, __pyx_pybuffernd_f.diminfo[0].strides, __pyx_t_15, __pyx_pybuffernd_f.diminfo[1].strides)));
+      __pyx_t_2 = npy_isnan((*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_bstruct_f.buf, __pyx_t_14, __pyx_bstride_0_f, __pyx_t_15, __pyx_bstride_1_f)));
       if (__pyx_t_2) {
 
         /* "astropy/nddata/convolution/boundary_extend.pyx":114
@@ -2511,7 +2319,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_2conv
  */
             __pyx_t_20 = __pyx_v_iii;
             __pyx_t_21 = __pyx_v_jjj;
-            __pyx_v_val = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_pybuffernd_f.rcbuffer->pybuffer.buf, __pyx_t_20, __pyx_pybuffernd_f.diminfo[0].strides, __pyx_t_21, __pyx_pybuffernd_f.diminfo[1].strides));
+            __pyx_v_val = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_bstruct_f.buf, __pyx_t_20, __pyx_bstride_0_f, __pyx_t_21, __pyx_bstride_1_f));
 
             /* "astropy/nddata/convolution/boundary_extend.pyx":125
  *                         jjj = int_min(int_max(jj, 0), ny - 1)
@@ -2532,7 +2340,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_2conv
  */
               __pyx_t_22 = ((unsigned int)((__pyx_v_wkx + __pyx_v_ii) - __pyx_v_i));
               __pyx_t_23 = ((unsigned int)((__pyx_v_wky + __pyx_v_jj) - __pyx_v_j));
-              __pyx_v_ker = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_pybuffernd_g.rcbuffer->pybuffer.buf, __pyx_t_22, __pyx_pybuffernd_g.diminfo[0].strides, __pyx_t_23, __pyx_pybuffernd_g.diminfo[1].strides));
+              __pyx_v_ker = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_bstruct_g.buf, __pyx_t_22, __pyx_bstride_0_g, __pyx_t_23, __pyx_bstride_1_g));
 
               /* "astropy/nddata/convolution/boundary_extend.pyx":128
  *                             ker = g[<unsigned int>(wkx + ii - i),
@@ -2551,9 +2359,9 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_2conv
  *                 if bot != 0.:
  */
               __pyx_v_bot = (__pyx_v_bot + __pyx_v_ker);
-              goto __pyx_L13;
+              goto __pyx_L16;
             }
-            __pyx_L13:;
+            __pyx_L16:;
           }
         }
 
@@ -2580,8 +2388,8 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_2conv
           }
           __pyx_t_24 = __pyx_v_i;
           __pyx_t_25 = __pyx_v_j;
-          *__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_24, __pyx_pybuffernd_fixed.diminfo[0].strides, __pyx_t_25, __pyx_pybuffernd_fixed.diminfo[1].strides) = (__pyx_v_top / __pyx_v_bot);
-          goto __pyx_L14;
+          *__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_24, __pyx_bstride_0_fixed, __pyx_t_25, __pyx_bstride_1_fixed) = (__pyx_v_top / __pyx_v_bot);
+          goto __pyx_L17;
         }
         /*else*/ {
 
@@ -2596,10 +2404,10 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_2conv
           __pyx_t_27 = __pyx_v_j;
           __pyx_t_28 = __pyx_v_i;
           __pyx_t_29 = __pyx_v_j;
-          *__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_28, __pyx_pybuffernd_fixed.diminfo[0].strides, __pyx_t_29, __pyx_pybuffernd_fixed.diminfo[1].strides) = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_pybuffernd_f.rcbuffer->pybuffer.buf, __pyx_t_26, __pyx_pybuffernd_f.diminfo[0].strides, __pyx_t_27, __pyx_pybuffernd_f.diminfo[1].strides));
+          *__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_28, __pyx_bstride_0_fixed, __pyx_t_29, __pyx_bstride_1_fixed) = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_bstruct_f.buf, __pyx_t_26, __pyx_bstride_0_f, __pyx_t_27, __pyx_bstride_1_f));
         }
-        __pyx_L14:;
-        goto __pyx_L8;
+        __pyx_L17:;
+        goto __pyx_L11;
       }
       /*else*/ {
 
@@ -2614,9 +2422,9 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_2conv
         __pyx_t_31 = __pyx_v_j;
         __pyx_t_32 = __pyx_v_i;
         __pyx_t_33 = __pyx_v_j;
-        *__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_32, __pyx_pybuffernd_fixed.diminfo[0].strides, __pyx_t_33, __pyx_pybuffernd_fixed.diminfo[1].strides) = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_pybuffernd_f.rcbuffer->pybuffer.buf, __pyx_t_30, __pyx_pybuffernd_f.diminfo[0].strides, __pyx_t_31, __pyx_pybuffernd_f.diminfo[1].strides));
+        *__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_32, __pyx_bstride_0_fixed, __pyx_t_33, __pyx_bstride_1_fixed) = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_bstruct_f.buf, __pyx_t_30, __pyx_bstride_0_f, __pyx_t_31, __pyx_bstride_1_f));
       }
-      __pyx_L8:;
+      __pyx_L11:;
     }
   }
 
@@ -2651,7 +2459,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_2conv
  */
       __pyx_t_34 = __pyx_v_i;
       __pyx_t_35 = __pyx_v_j;
-      __pyx_t_2 = (!npy_isnan((*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_34, __pyx_pybuffernd_fixed.diminfo[0].strides, __pyx_t_35, __pyx_pybuffernd_fixed.diminfo[1].strides))));
+      __pyx_t_2 = (!npy_isnan((*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_34, __pyx_bstride_0_fixed, __pyx_t_35, __pyx_bstride_1_fixed))));
       if (__pyx_t_2) {
 
         /* "astropy/nddata/convolution/boundary_extend.pyx":142
@@ -2757,7 +2565,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_2conv
  */
             __pyx_t_36 = __pyx_v_iii;
             __pyx_t_37 = __pyx_v_jjj;
-            __pyx_v_val = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_36, __pyx_pybuffernd_fixed.diminfo[0].strides, __pyx_t_37, __pyx_pybuffernd_fixed.diminfo[1].strides));
+            __pyx_v_val = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_36, __pyx_bstride_0_fixed, __pyx_t_37, __pyx_bstride_1_fixed));
 
             /* "astropy/nddata/convolution/boundary_extend.pyx":154
  *                         val = fixed[iii, jjj]
@@ -2768,7 +2576,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_2conv
  */
             __pyx_t_38 = ((unsigned int)((__pyx_v_wkx + __pyx_v_ii) - __pyx_v_i));
             __pyx_t_39 = ((unsigned int)((__pyx_v_wky + __pyx_v_jj) - __pyx_v_j));
-            __pyx_v_ker = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_pybuffernd_g.rcbuffer->pybuffer.buf, __pyx_t_38, __pyx_pybuffernd_g.diminfo[0].strides, __pyx_t_39, __pyx_pybuffernd_g.diminfo[1].strides));
+            __pyx_v_ker = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_bstruct_g.buf, __pyx_t_38, __pyx_bstride_0_g, __pyx_t_39, __pyx_bstride_1_g));
 
             /* "astropy/nddata/convolution/boundary_extend.pyx":155
  *                         ker = g[<unsigned int>(wkx + ii - i),
@@ -2797,9 +2605,9 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_2conv
  *                     conv[i, j] = top / bot
  */
               __pyx_v_bot = (__pyx_v_bot + __pyx_v_ker);
-              goto __pyx_L24;
+              goto __pyx_L27;
             }
-            __pyx_L24:;
+            __pyx_L27:;
           }
         }
 
@@ -2826,8 +2634,8 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_2conv
           }
           __pyx_t_40 = __pyx_v_i;
           __pyx_t_41 = __pyx_v_j;
-          *__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_pybuffernd_conv.rcbuffer->pybuffer.buf, __pyx_t_40, __pyx_pybuffernd_conv.diminfo[0].strides, __pyx_t_41, __pyx_pybuffernd_conv.diminfo[1].strides) = (__pyx_v_top / __pyx_v_bot);
-          goto __pyx_L25;
+          *__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_bstruct_conv.buf, __pyx_t_40, __pyx_bstride_0_conv, __pyx_t_41, __pyx_bstride_1_conv) = (__pyx_v_top / __pyx_v_bot);
+          goto __pyx_L28;
         }
         /*else*/ {
 
@@ -2842,10 +2650,10 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_2conv
           __pyx_t_43 = __pyx_v_j;
           __pyx_t_44 = __pyx_v_i;
           __pyx_t_45 = __pyx_v_j;
-          *__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_pybuffernd_conv.rcbuffer->pybuffer.buf, __pyx_t_44, __pyx_pybuffernd_conv.diminfo[0].strides, __pyx_t_45, __pyx_pybuffernd_conv.diminfo[1].strides) = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_42, __pyx_pybuffernd_fixed.diminfo[0].strides, __pyx_t_43, __pyx_pybuffernd_fixed.diminfo[1].strides));
+          *__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_bstruct_conv.buf, __pyx_t_44, __pyx_bstride_0_conv, __pyx_t_45, __pyx_bstride_1_conv) = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_42, __pyx_bstride_0_fixed, __pyx_t_43, __pyx_bstride_1_fixed));
         }
-        __pyx_L25:;
-        goto __pyx_L19;
+        __pyx_L28:;
+        goto __pyx_L22;
       }
       /*else*/ {
 
@@ -2860,9 +2668,9 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_2conv
         __pyx_t_47 = __pyx_v_j;
         __pyx_t_48 = __pyx_v_i;
         __pyx_t_49 = __pyx_v_j;
-        *__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_pybuffernd_conv.rcbuffer->pybuffer.buf, __pyx_t_48, __pyx_pybuffernd_conv.diminfo[0].strides, __pyx_t_49, __pyx_pybuffernd_conv.diminfo[1].strides) = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_46, __pyx_pybuffernd_fixed.diminfo[0].strides, __pyx_t_47, __pyx_pybuffernd_fixed.diminfo[1].strides));
+        *__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_bstruct_conv.buf, __pyx_t_48, __pyx_bstride_0_conv, __pyx_t_49, __pyx_bstride_1_conv) = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_46, __pyx_bstride_0_fixed, __pyx_t_47, __pyx_bstride_1_fixed));
       }
-      __pyx_L19:;
+      __pyx_L22:;
     }
   }
 
@@ -2887,19 +2695,19 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_2conv
   __Pyx_XDECREF(__pyx_t_7);
   { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;
     __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);
-    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_conv.rcbuffer->pybuffer);
-    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_f.rcbuffer->pybuffer);
-    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_fixed.rcbuffer->pybuffer);
-    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_g.rcbuffer->pybuffer);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_conv);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_g);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_f);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_fixed);
   __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
   __Pyx_AddTraceback("astropy.nddata.convolution.boundary_extend.convolve2d_boundary_extend", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   goto __pyx_L2;
   __pyx_L0:;
-  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_conv.rcbuffer->pybuffer);
-  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_f.rcbuffer->pybuffer);
-  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_fixed.rcbuffer->pybuffer);
-  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_g.rcbuffer->pybuffer);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_conv);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_g);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_f);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_fixed);
   __pyx_L2:;
   __Pyx_XDECREF((PyObject *)__pyx_v_fixed);
   __Pyx_XDECREF((PyObject *)__pyx_v_conv);
@@ -2908,72 +2716,6 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_2conv
   return __pyx_r;
 }
 
-/* Python wrapper */
-static PyObject *__pyx_pw_7astropy_6nddata_11convolution_15boundary_extend_5convolve3d_boundary_extend(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static PyMethodDef __pyx_mdef_7astropy_6nddata_11convolution_15boundary_extend_5convolve3d_boundary_extend = {__Pyx_NAMESTR("convolve3d_boundary_extend"), (PyCFunction)__pyx_pw_7astropy_6nddata_11convolution_15boundary_extend_5convolve3d_boundary_extend, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(0)};
-static PyObject *__pyx_pw_7astropy_6nddata_11convolution_15boundary_extend_5convolve3d_boundary_extend(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
-  PyArrayObject *__pyx_v_f = 0;
-  PyArrayObject *__pyx_v_g = 0;
-  static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__f,&__pyx_n_s__g,0};
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("convolve3d_boundary_extend (wrapper)", 0);
-  __pyx_self = __pyx_self;
-  {
-    PyObject* values[2] = {0,0};
-    if (unlikely(__pyx_kwds)) {
-      Py_ssize_t kw_args;
-      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
-      switch (pos_args) {
-        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
-        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
-        case  0: break;
-        default: goto __pyx_L5_argtuple_error;
-      }
-      kw_args = PyDict_Size(__pyx_kwds);
-      switch (pos_args) {
-        case  0:
-        values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__f);
-        if (likely(values[0])) kw_args--;
-        else goto __pyx_L5_argtuple_error;
-        case  1:
-        values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__g);
-        if (likely(values[1])) kw_args--;
-        else {
-          __Pyx_RaiseArgtupleInvalid("convolve3d_boundary_extend", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 169; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-        }
-      }
-      if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "convolve3d_boundary_extend") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 169; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-      }
-    } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
-      goto __pyx_L5_argtuple_error;
-    } else {
-      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
-      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
-    }
-    __pyx_v_f = ((PyArrayObject *)values[0]);
-    __pyx_v_g = ((PyArrayObject *)values[1]);
-  }
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("convolve3d_boundary_extend", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 169; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-  __pyx_L3_error:;
-  __Pyx_AddTraceback("astropy.nddata.convolution.boundary_extend.convolve3d_boundary_extend", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return NULL;
-  __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_f), __pyx_ptype_5numpy_ndarray, 1, "f", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 169; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_g), __pyx_ptype_5numpy_ndarray, 1, "g", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 170; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_r = __pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_4convolve3d_boundary_extend(__pyx_self, __pyx_v_f, __pyx_v_g);
-  goto __pyx_L0;
-  __pyx_L1_error:;
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
 /* "astropy/nddata/convolution/boundary_extend.pyx":169
  * 
  * @cython.boundscheck(False)  # turn off bounds-checking for entire function
@@ -2982,7 +2724,11 @@ static PyObject *__pyx_pw_7astropy_6nddata_11convolution_15boundary_extend_5conv
  * 
  */
 
-static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_4convolve3d_boundary_extend(CYTHON_UNUSED PyObject *__pyx_self, PyArrayObject *__pyx_v_f, PyArrayObject *__pyx_v_g) {
+static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_2convolve3d_boundary_extend(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static PyMethodDef __pyx_mdef_7astropy_6nddata_11convolution_15boundary_extend_2convolve3d_boundary_extend = {__Pyx_NAMESTR("convolve3d_boundary_extend"), (PyCFunction)__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_2convolve3d_boundary_extend, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(0)};
+static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_2convolve3d_boundary_extend(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyArrayObject *__pyx_v_f = 0;
+  PyArrayObject *__pyx_v_g = 0;
   int __pyx_v_nx;
   int __pyx_v_ny;
   int __pyx_v_nz;
@@ -3013,14 +2759,34 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_4conv
   __pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t __pyx_v_bot;
   __pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t __pyx_v_ker;
   __pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t __pyx_v_val;
-  __Pyx_LocalBuf_ND __pyx_pybuffernd_conv;
-  __Pyx_Buffer __pyx_pybuffer_conv;
-  __Pyx_LocalBuf_ND __pyx_pybuffernd_f;
-  __Pyx_Buffer __pyx_pybuffer_f;
-  __Pyx_LocalBuf_ND __pyx_pybuffernd_fixed;
-  __Pyx_Buffer __pyx_pybuffer_fixed;
-  __Pyx_LocalBuf_ND __pyx_pybuffernd_g;
-  __Pyx_Buffer __pyx_pybuffer_g;
+  Py_buffer __pyx_bstruct_conv;
+  Py_ssize_t __pyx_bstride_0_conv = 0;
+  Py_ssize_t __pyx_bstride_1_conv = 0;
+  Py_ssize_t __pyx_bstride_2_conv = 0;
+  Py_ssize_t __pyx_bshape_0_conv = 0;
+  Py_ssize_t __pyx_bshape_1_conv = 0;
+  Py_ssize_t __pyx_bshape_2_conv = 0;
+  Py_buffer __pyx_bstruct_g;
+  Py_ssize_t __pyx_bstride_0_g = 0;
+  Py_ssize_t __pyx_bstride_1_g = 0;
+  Py_ssize_t __pyx_bstride_2_g = 0;
+  Py_ssize_t __pyx_bshape_0_g = 0;
+  Py_ssize_t __pyx_bshape_1_g = 0;
+  Py_ssize_t __pyx_bshape_2_g = 0;
+  Py_buffer __pyx_bstruct_f;
+  Py_ssize_t __pyx_bstride_0_f = 0;
+  Py_ssize_t __pyx_bstride_1_f = 0;
+  Py_ssize_t __pyx_bstride_2_f = 0;
+  Py_ssize_t __pyx_bshape_0_f = 0;
+  Py_ssize_t __pyx_bshape_1_f = 0;
+  Py_ssize_t __pyx_bshape_2_f = 0;
+  Py_buffer __pyx_bstruct_fixed;
+  Py_ssize_t __pyx_bstride_0_fixed = 0;
+  Py_ssize_t __pyx_bstride_1_fixed = 0;
+  Py_ssize_t __pyx_bstride_2_fixed = 0;
+  Py_ssize_t __pyx_bshape_0_fixed = 0;
+  Py_ssize_t __pyx_bshape_1_fixed = 0;
+  Py_ssize_t __pyx_bshape_2_fixed = 0;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   int __pyx_t_1;
@@ -3097,33 +2863,70 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_4conv
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("convolve3d_boundary_extend", 0);
-  __pyx_pybuffer_fixed.pybuffer.buf = NULL;
-  __pyx_pybuffer_fixed.refcount = 0;
-  __pyx_pybuffernd_fixed.data = NULL;
-  __pyx_pybuffernd_fixed.rcbuffer = &__pyx_pybuffer_fixed;
-  __pyx_pybuffer_conv.pybuffer.buf = NULL;
-  __pyx_pybuffer_conv.refcount = 0;
-  __pyx_pybuffernd_conv.data = NULL;
-  __pyx_pybuffernd_conv.rcbuffer = &__pyx_pybuffer_conv;
-  __pyx_pybuffer_f.pybuffer.buf = NULL;
-  __pyx_pybuffer_f.refcount = 0;
-  __pyx_pybuffernd_f.data = NULL;
-  __pyx_pybuffernd_f.rcbuffer = &__pyx_pybuffer_f;
-  __pyx_pybuffer_g.pybuffer.buf = NULL;
-  __pyx_pybuffer_g.refcount = 0;
-  __pyx_pybuffernd_g.data = NULL;
-  __pyx_pybuffernd_g.rcbuffer = &__pyx_pybuffer_g;
+  static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__f,&__pyx_n_s__g,0};
+  __Pyx_RefNannySetupContext("convolve3d_boundary_extend");
+  __pyx_self = __pyx_self;
+  {
+    PyObject* values[2] = {0,0};
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  0:
+        values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__f);
+        if (likely(values[0])) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+        case  1:
+        values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__g);
+        if (likely(values[1])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("convolve3d_boundary_extend", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 169; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "convolve3d_boundary_extend") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 169; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+    } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
+      goto __pyx_L5_argtuple_error;
+    } else {
+      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+    }
+    __pyx_v_f = ((PyArrayObject *)values[0]);
+    __pyx_v_g = ((PyArrayObject *)values[1]);
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("convolve3d_boundary_extend", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 169; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("astropy.nddata.convolution.boundary_extend.convolve3d_boundary_extend", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_bstruct_fixed.buf = NULL;
+  __pyx_bstruct_conv.buf = NULL;
+  __pyx_bstruct_f.buf = NULL;
+  __pyx_bstruct_g.buf = NULL;
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_f), __pyx_ptype_5numpy_ndarray, 1, "f", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 169; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_g), __pyx_ptype_5numpy_ndarray, 1, "g", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 170; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_f.rcbuffer->pybuffer, (PyObject*)__pyx_v_f, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES, 3, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 169; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_f, (PyObject*)__pyx_v_f, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES, 3, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 169; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
-  __pyx_pybuffernd_f.diminfo[0].strides = __pyx_pybuffernd_f.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_f.diminfo[0].shape = __pyx_pybuffernd_f.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_f.diminfo[1].strides = __pyx_pybuffernd_f.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_f.diminfo[1].shape = __pyx_pybuffernd_f.rcbuffer->pybuffer.shape[1]; __pyx_pybuffernd_f.diminfo[2].strides = __pyx_pybuffernd_f.rcbuffer->pybuffer.strides[2]; __pyx_pybuffernd_f.diminfo[2].shape = __pyx_pybuffernd_f.rcbuffer->pybuffer.shape[2];
+  __pyx_bstride_0_f = __pyx_bstruct_f.strides[0]; __pyx_bstride_1_f = __pyx_bstruct_f.strides[1]; __pyx_bstride_2_f = __pyx_bstruct_f.strides[2];
+  __pyx_bshape_0_f = __pyx_bstruct_f.shape[0]; __pyx_bshape_1_f = __pyx_bstruct_f.shape[1]; __pyx_bshape_2_f = __pyx_bstruct_f.shape[2];
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_g.rcbuffer->pybuffer, (PyObject*)__pyx_v_g, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES, 3, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 169; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_g, (PyObject*)__pyx_v_g, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES, 3, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 169; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
-  __pyx_pybuffernd_g.diminfo[0].strides = __pyx_pybuffernd_g.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_g.diminfo[0].shape = __pyx_pybuffernd_g.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_g.diminfo[1].strides = __pyx_pybuffernd_g.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_g.diminfo[1].shape = __pyx_pybuffernd_g.rcbuffer->pybuffer.shape[1]; __pyx_pybuffernd_g.diminfo[2].strides = __pyx_pybuffernd_g.rcbuffer->pybuffer.strides[2]; __pyx_pybuffernd_g.diminfo[2].shape = __pyx_pybuffernd_g.rcbuffer->pybuffer.shape[2];
+  __pyx_bstride_0_g = __pyx_bstruct_g.strides[0]; __pyx_bstride_1_g = __pyx_bstruct_g.strides[1]; __pyx_bstride_2_g = __pyx_bstruct_g.strides[2];
+  __pyx_bshape_0_g = __pyx_bstruct_g.shape[0]; __pyx_bshape_1_g = __pyx_bstruct_g.shape[1]; __pyx_bshape_2_g = __pyx_bstruct_g.shape[2];
 
   /* "astropy/nddata/convolution/boundary_extend.pyx":172
  *                                np.ndarray[DTYPE_t, ndim=3] g):
@@ -3159,9 +2962,9 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_4conv
     __Pyx_Raise(__pyx_t_5, 0, 0, 0);
     __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
     {__pyx_filename = __pyx_f[0]; __pyx_lineno = 173; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    goto __pyx_L3;
+    goto __pyx_L6;
   }
-  __pyx_L3:;
+  __pyx_L6:;
 
   /* "astropy/nddata/convolution/boundary_extend.pyx":175
  *         raise ValueError("Convolution kernel must have odd dimensions")
@@ -3302,7 +3105,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_4conv
   __pyx_t_8 = PyInt_FromLong(__pyx_v_nz); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 186; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_8);
   __pyx_t_9 = PyList_New(3); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 186; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_9);
+  __Pyx_GOTREF(((PyObject *)__pyx_t_9));
   PyList_SET_ITEM(__pyx_t_9, 0, __pyx_t_5);
   __Pyx_GIVEREF(__pyx_t_5);
   PyList_SET_ITEM(__pyx_t_9, 1, __pyx_t_7);
@@ -3313,7 +3116,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_4conv
   __pyx_t_7 = 0;
   __pyx_t_8 = 0;
   __pyx_t_8 = PyTuple_New(1); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 186; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_8);
+  __Pyx_GOTREF(((PyObject *)__pyx_t_8));
   PyTuple_SET_ITEM(__pyx_t_8, 0, ((PyObject *)__pyx_t_9));
   __Pyx_GIVEREF(((PyObject *)__pyx_t_9));
   __pyx_t_9 = 0;
@@ -3323,7 +3126,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_4conv
   __Pyx_GOTREF(__pyx_t_7);
   if (PyDict_SetItem(__pyx_t_9, ((PyObject *)__pyx_n_s__dtype), __pyx_t_7) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 186; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-  __pyx_t_7 = PyObject_Call(__pyx_t_6, ((PyObject *)__pyx_t_8), ((PyObject *)__pyx_t_9)); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 186; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_7 = PyEval_CallObjectWithKeywords(__pyx_t_6, ((PyObject *)__pyx_t_8), ((PyObject *)__pyx_t_9)); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 186; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_7);
   __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
   __Pyx_DECREF(((PyObject *)__pyx_t_8)); __pyx_t_8 = 0;
@@ -3332,10 +3135,11 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_4conv
   __pyx_t_10 = ((PyArrayObject *)__pyx_t_7);
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_fixed.rcbuffer->pybuffer, (PyObject*)__pyx_t_10, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 3, 0, __pyx_stack) == -1)) {
-      __pyx_v_fixed = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf = NULL;
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_fixed, (PyObject*)__pyx_t_10, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 3, 0, __pyx_stack) == -1)) {
+      __pyx_v_fixed = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_fixed.buf = NULL;
       {__pyx_filename = __pyx_f[0]; __pyx_lineno = 186; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    } else {__pyx_pybuffernd_fixed.diminfo[0].strides = __pyx_pybuffernd_fixed.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_fixed.diminfo[0].shape = __pyx_pybuffernd_fixed.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_fixed.diminfo[1].strides = __pyx_pybuffernd_fixed.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_fixed.diminfo[1].shape = __pyx_pybuffernd_fixed.rcbuffer->pybuffer.shape[1]; __pyx_pybuffernd_fixed.diminfo[2].strides = __pyx_pybuffernd_fixed.rcbuffer->pybuffer.strides[2]; __pyx_pybuffernd_fixed.diminfo[2].shape = __pyx_pybuffernd_fixed.rcbuffer->pybuffer.shape[2];
+    } else {__pyx_bstride_0_fixed = __pyx_bstruct_fixed.strides[0]; __pyx_bstride_1_fixed = __pyx_bstruct_fixed.strides[1]; __pyx_bstride_2_fixed = __pyx_bstruct_fixed.strides[2];
+      __pyx_bshape_0_fixed = __pyx_bstruct_fixed.shape[0]; __pyx_bshape_1_fixed = __pyx_bstruct_fixed.shape[1]; __pyx_bshape_2_fixed = __pyx_bstruct_fixed.shape[2];
     }
   }
   __pyx_t_10 = 0;
@@ -3361,7 +3165,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_4conv
   __pyx_t_6 = PyInt_FromLong(__pyx_v_nz); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 187; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_6);
   __pyx_t_5 = PyList_New(3); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 187; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_5);
+  __Pyx_GOTREF(((PyObject *)__pyx_t_5));
   PyList_SET_ITEM(__pyx_t_5, 0, __pyx_t_7);
   __Pyx_GIVEREF(__pyx_t_7);
   PyList_SET_ITEM(__pyx_t_5, 1, __pyx_t_8);
@@ -3372,7 +3176,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_4conv
   __pyx_t_8 = 0;
   __pyx_t_6 = 0;
   __pyx_t_6 = PyTuple_New(1); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 187; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_6);
+  __Pyx_GOTREF(((PyObject *)__pyx_t_6));
   PyTuple_SET_ITEM(__pyx_t_6, 0, ((PyObject *)__pyx_t_5));
   __Pyx_GIVEREF(((PyObject *)__pyx_t_5));
   __pyx_t_5 = 0;
@@ -3382,7 +3186,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_4conv
   __Pyx_GOTREF(__pyx_t_8);
   if (PyDict_SetItem(__pyx_t_5, ((PyObject *)__pyx_n_s__dtype), __pyx_t_8) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 187; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-  __pyx_t_8 = PyObject_Call(__pyx_t_9, ((PyObject *)__pyx_t_6), ((PyObject *)__pyx_t_5)); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 187; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_8 = PyEval_CallObjectWithKeywords(__pyx_t_9, ((PyObject *)__pyx_t_6), ((PyObject *)__pyx_t_5)); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 187; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_8);
   __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
   __Pyx_DECREF(((PyObject *)__pyx_t_6)); __pyx_t_6 = 0;
@@ -3391,10 +3195,11 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_4conv
   __pyx_t_11 = ((PyArrayObject *)__pyx_t_8);
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_conv.rcbuffer->pybuffer, (PyObject*)__pyx_t_11, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 3, 0, __pyx_stack) == -1)) {
-      __pyx_v_conv = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_conv.rcbuffer->pybuffer.buf = NULL;
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_conv, (PyObject*)__pyx_t_11, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 3, 0, __pyx_stack) == -1)) {
+      __pyx_v_conv = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_conv.buf = NULL;
       {__pyx_filename = __pyx_f[0]; __pyx_lineno = 187; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    } else {__pyx_pybuffernd_conv.diminfo[0].strides = __pyx_pybuffernd_conv.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_conv.diminfo[0].shape = __pyx_pybuffernd_conv.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_conv.diminfo[1].strides = __pyx_pybuffernd_conv.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_conv.diminfo[1].shape = __pyx_pybuffernd_conv.rcbuffer->pybuffer.shape[1]; __pyx_pybuffernd_conv.diminfo[2].strides = __pyx_pybuffernd_conv.rcbuffer->pybuffer.strides[2]; __pyx_pybuffernd_conv.diminfo[2].shape = __pyx_pybuffernd_conv.rcbuffer->pybuffer.shape[2];
+    } else {__pyx_bstride_0_conv = __pyx_bstruct_conv.strides[0]; __pyx_bstride_1_conv = __pyx_bstruct_conv.strides[1]; __pyx_bstride_2_conv = __pyx_bstruct_conv.strides[2];
+      __pyx_bshape_0_conv = __pyx_bstruct_conv.shape[0]; __pyx_bshape_1_conv = __pyx_bstruct_conv.shape[1]; __pyx_bshape_2_conv = __pyx_bstruct_conv.shape[2];
     }
   }
   __pyx_t_11 = 0;
@@ -3444,7 +3249,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_4conv
         __pyx_t_18 = __pyx_v_i;
         __pyx_t_19 = __pyx_v_j;
         __pyx_t_20 = __pyx_v_k;
-        __pyx_t_4 = npy_isnan((*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_pybuffernd_f.rcbuffer->pybuffer.buf, __pyx_t_18, __pyx_pybuffernd_f.diminfo[0].strides, __pyx_t_19, __pyx_pybuffernd_f.diminfo[1].strides, __pyx_t_20, __pyx_pybuffernd_f.diminfo[2].strides)));
+        __pyx_t_4 = npy_isnan((*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_bstruct_f.buf, __pyx_t_18, __pyx_bstride_0_f, __pyx_t_19, __pyx_bstride_1_f, __pyx_t_20, __pyx_bstride_2_f)));
         if (__pyx_t_4) {
 
           /* "astropy/nddata/convolution/boundary_extend.pyx":201
@@ -3589,7 +3394,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_4conv
                 __pyx_t_27 = __pyx_v_iii;
                 __pyx_t_28 = __pyx_v_jjj;
                 __pyx_t_29 = __pyx_v_kkk;
-                __pyx_v_val = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_pybuffernd_f.rcbuffer->pybuffer.buf, __pyx_t_27, __pyx_pybuffernd_f.diminfo[0].strides, __pyx_t_28, __pyx_pybuffernd_f.diminfo[1].strides, __pyx_t_29, __pyx_pybuffernd_f.diminfo[2].strides));
+                __pyx_v_val = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_bstruct_f.buf, __pyx_t_27, __pyx_bstride_0_f, __pyx_t_28, __pyx_bstride_1_f, __pyx_t_29, __pyx_bstride_2_f));
 
                 /* "astropy/nddata/convolution/boundary_extend.pyx":216
  *                                 kkk = int_min(int_max(kk, 0), nz - 1)
@@ -3611,7 +3416,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_4conv
                   __pyx_t_30 = ((unsigned int)((__pyx_v_wkx + __pyx_v_ii) - __pyx_v_i));
                   __pyx_t_31 = ((unsigned int)((__pyx_v_wky + __pyx_v_jj) - __pyx_v_j));
                   __pyx_t_32 = ((unsigned int)((__pyx_v_wkz + __pyx_v_kk) - __pyx_v_k));
-                  __pyx_v_ker = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_pybuffernd_g.rcbuffer->pybuffer.buf, __pyx_t_30, __pyx_pybuffernd_g.diminfo[0].strides, __pyx_t_31, __pyx_pybuffernd_g.diminfo[1].strides, __pyx_t_32, __pyx_pybuffernd_g.diminfo[2].strides));
+                  __pyx_v_ker = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_bstruct_g.buf, __pyx_t_30, __pyx_bstride_0_g, __pyx_t_31, __pyx_bstride_1_g, __pyx_t_32, __pyx_bstride_2_g));
 
                   /* "astropy/nddata/convolution/boundary_extend.pyx":220
  *                                             <unsigned int>(wky + jj - j),
@@ -3630,9 +3435,9 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_4conv
  *                     if bot != 0.:
  */
                   __pyx_v_bot = (__pyx_v_bot + __pyx_v_ker);
-                  goto __pyx_L17;
+                  goto __pyx_L20;
                 }
-                __pyx_L17:;
+                __pyx_L20:;
               }
             }
           }
@@ -3661,8 +3466,8 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_4conv
             __pyx_t_33 = __pyx_v_i;
             __pyx_t_34 = __pyx_v_j;
             __pyx_t_35 = __pyx_v_k;
-            *__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_33, __pyx_pybuffernd_fixed.diminfo[0].strides, __pyx_t_34, __pyx_pybuffernd_fixed.diminfo[1].strides, __pyx_t_35, __pyx_pybuffernd_fixed.diminfo[2].strides) = (__pyx_v_top / __pyx_v_bot);
-            goto __pyx_L18;
+            *__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_33, __pyx_bstride_0_fixed, __pyx_t_34, __pyx_bstride_1_fixed, __pyx_t_35, __pyx_bstride_2_fixed) = (__pyx_v_top / __pyx_v_bot);
+            goto __pyx_L21;
           }
           /*else*/ {
 
@@ -3679,10 +3484,10 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_4conv
             __pyx_t_39 = __pyx_v_i;
             __pyx_t_40 = __pyx_v_j;
             __pyx_t_41 = __pyx_v_k;
-            *__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_39, __pyx_pybuffernd_fixed.diminfo[0].strides, __pyx_t_40, __pyx_pybuffernd_fixed.diminfo[1].strides, __pyx_t_41, __pyx_pybuffernd_fixed.diminfo[2].strides) = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_pybuffernd_f.rcbuffer->pybuffer.buf, __pyx_t_36, __pyx_pybuffernd_f.diminfo[0].strides, __pyx_t_37, __pyx_pybuffernd_f.diminfo[1].strides, __pyx_t_38, __pyx_pybuffernd_f.diminfo[2].strides));
+            *__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_39, __pyx_bstride_0_fixed, __pyx_t_40, __pyx_bstride_1_fixed, __pyx_t_41, __pyx_bstride_2_fixed) = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_bstruct_f.buf, __pyx_t_36, __pyx_bstride_0_f, __pyx_t_37, __pyx_bstride_1_f, __pyx_t_38, __pyx_bstride_2_f));
           }
-          __pyx_L18:;
-          goto __pyx_L10;
+          __pyx_L21:;
+          goto __pyx_L13;
         }
         /*else*/ {
 
@@ -3699,9 +3504,9 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_4conv
           __pyx_t_45 = __pyx_v_i;
           __pyx_t_46 = __pyx_v_j;
           __pyx_t_47 = __pyx_v_k;
-          *__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_45, __pyx_pybuffernd_fixed.diminfo[0].strides, __pyx_t_46, __pyx_pybuffernd_fixed.diminfo[1].strides, __pyx_t_47, __pyx_pybuffernd_fixed.diminfo[2].strides) = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_pybuffernd_f.rcbuffer->pybuffer.buf, __pyx_t_42, __pyx_pybuffernd_f.diminfo[0].strides, __pyx_t_43, __pyx_pybuffernd_f.diminfo[1].strides, __pyx_t_44, __pyx_pybuffernd_f.diminfo[2].strides));
+          *__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_45, __pyx_bstride_0_fixed, __pyx_t_46, __pyx_bstride_1_fixed, __pyx_t_47, __pyx_bstride_2_fixed) = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_bstruct_f.buf, __pyx_t_42, __pyx_bstride_0_f, __pyx_t_43, __pyx_bstride_1_f, __pyx_t_44, __pyx_bstride_2_f));
         }
-        __pyx_L10:;
+        __pyx_L13:;
       }
     }
   }
@@ -3749,7 +3554,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_4conv
         __pyx_t_48 = __pyx_v_i;
         __pyx_t_49 = __pyx_v_j;
         __pyx_t_50 = __pyx_v_k;
-        __pyx_t_4 = (!npy_isnan((*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_48, __pyx_pybuffernd_fixed.diminfo[0].strides, __pyx_t_49, __pyx_pybuffernd_fixed.diminfo[1].strides, __pyx_t_50, __pyx_pybuffernd_fixed.diminfo[2].strides))));
+        __pyx_t_4 = (!npy_isnan((*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_48, __pyx_bstride_0_fixed, __pyx_t_49, __pyx_bstride_1_fixed, __pyx_t_50, __pyx_bstride_2_fixed))));
         if (__pyx_t_4) {
 
           /* "astropy/nddata/convolution/boundary_extend.pyx":235
@@ -3894,7 +3699,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_4conv
                 __pyx_t_51 = __pyx_v_iii;
                 __pyx_t_52 = __pyx_v_jjj;
                 __pyx_t_53 = __pyx_v_kkk;
-                __pyx_v_val = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_51, __pyx_pybuffernd_fixed.diminfo[0].strides, __pyx_t_52, __pyx_pybuffernd_fixed.diminfo[1].strides, __pyx_t_53, __pyx_pybuffernd_fixed.diminfo[2].strides));
+                __pyx_v_val = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_51, __pyx_bstride_0_fixed, __pyx_t_52, __pyx_bstride_1_fixed, __pyx_t_53, __pyx_bstride_2_fixed));
 
                 /* "astropy/nddata/convolution/boundary_extend.pyx":252
  *                                 ker = g[<unsigned int>(wkx + ii - i),
@@ -3906,7 +3711,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_4conv
                 __pyx_t_54 = ((unsigned int)((__pyx_v_wkx + __pyx_v_ii) - __pyx_v_i));
                 __pyx_t_55 = ((unsigned int)((__pyx_v_wky + __pyx_v_jj) - __pyx_v_j));
                 __pyx_t_56 = ((unsigned int)((__pyx_v_wkz + __pyx_v_kk) - __pyx_v_k));
-                __pyx_v_ker = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_pybuffernd_g.rcbuffer->pybuffer.buf, __pyx_t_54, __pyx_pybuffernd_g.diminfo[0].strides, __pyx_t_55, __pyx_pybuffernd_g.diminfo[1].strides, __pyx_t_56, __pyx_pybuffernd_g.diminfo[2].strides));
+                __pyx_v_ker = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_bstruct_g.buf, __pyx_t_54, __pyx_bstride_0_g, __pyx_t_55, __pyx_bstride_1_g, __pyx_t_56, __pyx_bstride_2_g));
 
                 /* "astropy/nddata/convolution/boundary_extend.pyx":253
  *                                         <unsigned int>(wky + jj - j),
@@ -3935,9 +3740,9 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_4conv
  *                         conv[i, j, k] = top / bot
  */
                   __pyx_v_bot = (__pyx_v_bot + __pyx_v_ker);
-                  goto __pyx_L32;
+                  goto __pyx_L35;
                 }
-                __pyx_L32:;
+                __pyx_L35:;
               }
             }
           }
@@ -3966,8 +3771,8 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_4conv
             __pyx_t_57 = __pyx_v_i;
             __pyx_t_58 = __pyx_v_j;
             __pyx_t_59 = __pyx_v_k;
-            *__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_pybuffernd_conv.rcbuffer->pybuffer.buf, __pyx_t_57, __pyx_pybuffernd_conv.diminfo[0].strides, __pyx_t_58, __pyx_pybuffernd_conv.diminfo[1].strides, __pyx_t_59, __pyx_pybuffernd_conv.diminfo[2].strides) = (__pyx_v_top / __pyx_v_bot);
-            goto __pyx_L33;
+            *__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_bstruct_conv.buf, __pyx_t_57, __pyx_bstride_0_conv, __pyx_t_58, __pyx_bstride_1_conv, __pyx_t_59, __pyx_bstride_2_conv) = (__pyx_v_top / __pyx_v_bot);
+            goto __pyx_L36;
           }
           /*else*/ {
 
@@ -3984,10 +3789,10 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_4conv
             __pyx_t_63 = __pyx_v_i;
             __pyx_t_64 = __pyx_v_j;
             __pyx_t_65 = __pyx_v_k;
-            *__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_pybuffernd_conv.rcbuffer->pybuffer.buf, __pyx_t_63, __pyx_pybuffernd_conv.diminfo[0].strides, __pyx_t_64, __pyx_pybuffernd_conv.diminfo[1].strides, __pyx_t_65, __pyx_pybuffernd_conv.diminfo[2].strides) = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_60, __pyx_pybuffernd_fixed.diminfo[0].strides, __pyx_t_61, __pyx_pybuffernd_fixed.diminfo[1].strides, __pyx_t_62, __pyx_pybuffernd_fixed.diminfo[2].strides));
+            *__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_bstruct_conv.buf, __pyx_t_63, __pyx_bstride_0_conv, __pyx_t_64, __pyx_bstride_1_conv, __pyx_t_65, __pyx_bstride_2_conv) = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_60, __pyx_bstride_0_fixed, __pyx_t_61, __pyx_bstride_1_fixed, __pyx_t_62, __pyx_bstride_2_fixed));
           }
-          __pyx_L33:;
-          goto __pyx_L25;
+          __pyx_L36:;
+          goto __pyx_L28;
         }
         /*else*/ {
 
@@ -4004,9 +3809,9 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_4conv
           __pyx_t_69 = __pyx_v_i;
           __pyx_t_70 = __pyx_v_j;
           __pyx_t_71 = __pyx_v_k;
-          *__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_pybuffernd_conv.rcbuffer->pybuffer.buf, __pyx_t_69, __pyx_pybuffernd_conv.diminfo[0].strides, __pyx_t_70, __pyx_pybuffernd_conv.diminfo[1].strides, __pyx_t_71, __pyx_pybuffernd_conv.diminfo[2].strides) = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_66, __pyx_pybuffernd_fixed.diminfo[0].strides, __pyx_t_67, __pyx_pybuffernd_fixed.diminfo[1].strides, __pyx_t_68, __pyx_pybuffernd_fixed.diminfo[2].strides));
+          *__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_bstruct_conv.buf, __pyx_t_69, __pyx_bstride_0_conv, __pyx_t_70, __pyx_bstride_1_conv, __pyx_t_71, __pyx_bstride_2_conv) = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_15boundary_extend_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_66, __pyx_bstride_0_fixed, __pyx_t_67, __pyx_bstride_1_fixed, __pyx_t_68, __pyx_bstride_2_fixed));
         }
-        __pyx_L25:;
+        __pyx_L28:;
       }
     }
   }
@@ -4031,19 +3836,19 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_4conv
   __Pyx_XDECREF(__pyx_t_9);
   { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;
     __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);
-    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_conv.rcbuffer->pybuffer);
-    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_f.rcbuffer->pybuffer);
-    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_fixed.rcbuffer->pybuffer);
-    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_g.rcbuffer->pybuffer);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_conv);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_g);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_f);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_fixed);
   __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
   __Pyx_AddTraceback("astropy.nddata.convolution.boundary_extend.convolve3d_boundary_extend", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   goto __pyx_L2;
   __pyx_L0:;
-  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_conv.rcbuffer->pybuffer);
-  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_f.rcbuffer->pybuffer);
-  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_fixed.rcbuffer->pybuffer);
-  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_g.rcbuffer->pybuffer);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_conv);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_g);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_f);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_fixed);
   __pyx_L2:;
   __Pyx_XDECREF((PyObject *)__pyx_v_fixed);
   __Pyx_XDECREF((PyObject *)__pyx_v_conv);
@@ -4052,18 +3857,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_15boundary_extend_4conv
   return __pyx_r;
 }
 
-/* Python wrapper */
-static int __pyx_pw_5numpy_7ndarray_1__getbuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags); /*proto*/
-static int __pyx_pw_5numpy_7ndarray_1__getbuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags) {
-  int __pyx_r;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__getbuffer__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_5numpy_7ndarray___getbuffer__(((PyArrayObject *)__pyx_v_self), ((Py_buffer *)__pyx_v_info), ((int)__pyx_v_flags));
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-/* "numpy.pxd":193
+/* "numpy.pxd":190
  *         # experimental exception made for __getbuffer__ and __releasebuffer__
  *         # -- the details of this may change.
  *         def __getbuffer__(ndarray self, Py_buffer* info, int flags):             # <<<<<<<<<<<<<<
@@ -4071,7 +3865,8 @@ static int __pyx_pw_5numpy_7ndarray_1__getbuffer__(PyObject *__pyx_v_self, Py_bu
  *             # requirements, and does not yet fullfill the PEP.
  */
 
-static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags) {
+static CYTHON_UNUSED int __pyx_pf_5numpy_7ndarray___getbuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags); /*proto*/
+static CYTHON_UNUSED int __pyx_pf_5numpy_7ndarray___getbuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags) {
   int __pyx_v_copy_shape;
   int __pyx_v_i;
   int __pyx_v_ndim;
@@ -4096,13 +3891,13 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("__getbuffer__", 0);
+  __Pyx_RefNannySetupContext("__getbuffer__");
   if (__pyx_v_info != NULL) {
     __pyx_v_info->obj = Py_None; __Pyx_INCREF(Py_None);
     __Pyx_GIVEREF(__pyx_v_info->obj);
   }
 
-  /* "numpy.pxd":199
+  /* "numpy.pxd":196
  *             # of flags
  * 
  *             if info == NULL: return             # <<<<<<<<<<<<<<
@@ -4113,11 +3908,11 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
   if (__pyx_t_1) {
     __pyx_r = 0;
     goto __pyx_L0;
-    goto __pyx_L3;
+    goto __pyx_L5;
   }
-  __pyx_L3:;
+  __pyx_L5:;
 
-  /* "numpy.pxd":202
+  /* "numpy.pxd":199
  * 
  *             cdef int copy_shape, i, ndim
  *             cdef int endian_detector = 1             # <<<<<<<<<<<<<<
@@ -4126,7 +3921,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
   __pyx_v_endian_detector = 1;
 
-  /* "numpy.pxd":203
+  /* "numpy.pxd":200
  *             cdef int copy_shape, i, ndim
  *             cdef int endian_detector = 1
  *             cdef bint little_endian = ((<char*>&endian_detector)[0] != 0)             # <<<<<<<<<<<<<<
@@ -4135,16 +3930,16 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
   __pyx_v_little_endian = ((((char *)(&__pyx_v_endian_detector))[0]) != 0);
 
-  /* "numpy.pxd":205
+  /* "numpy.pxd":202
  *             cdef bint little_endian = ((<char*>&endian_detector)[0] != 0)
  * 
  *             ndim = PyArray_NDIM(self)             # <<<<<<<<<<<<<<
  * 
  *             if sizeof(npy_intp) != sizeof(Py_ssize_t):
  */
-  __pyx_v_ndim = PyArray_NDIM(__pyx_v_self);
+  __pyx_v_ndim = PyArray_NDIM(((PyArrayObject *)__pyx_v_self));
 
-  /* "numpy.pxd":207
+  /* "numpy.pxd":204
  *             ndim = PyArray_NDIM(self)
  * 
  *             if sizeof(npy_intp) != sizeof(Py_ssize_t):             # <<<<<<<<<<<<<<
@@ -4154,7 +3949,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
   __pyx_t_1 = ((sizeof(npy_intp)) != (sizeof(Py_ssize_t)));
   if (__pyx_t_1) {
 
-    /* "numpy.pxd":208
+    /* "numpy.pxd":205
  * 
  *             if sizeof(npy_intp) != sizeof(Py_ssize_t):
  *                 copy_shape = 1             # <<<<<<<<<<<<<<
@@ -4162,11 +3957,11 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  *                 copy_shape = 0
  */
     __pyx_v_copy_shape = 1;
-    goto __pyx_L4;
+    goto __pyx_L6;
   }
   /*else*/ {
 
-    /* "numpy.pxd":210
+    /* "numpy.pxd":207
  *                 copy_shape = 1
  *             else:
  *                 copy_shape = 0             # <<<<<<<<<<<<<<
@@ -4175,9 +3970,9 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
     __pyx_v_copy_shape = 0;
   }
-  __pyx_L4:;
+  __pyx_L6:;
 
-  /* "numpy.pxd":212
+  /* "numpy.pxd":209
  *                 copy_shape = 0
  * 
  *             if ((flags & pybuf.PyBUF_C_CONTIGUOUS == pybuf.PyBUF_C_CONTIGUOUS)             # <<<<<<<<<<<<<<
@@ -4187,37 +3982,37 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
   __pyx_t_1 = ((__pyx_v_flags & PyBUF_C_CONTIGUOUS) == PyBUF_C_CONTIGUOUS);
   if (__pyx_t_1) {
 
-    /* "numpy.pxd":213
+    /* "numpy.pxd":210
  * 
  *             if ((flags & pybuf.PyBUF_C_CONTIGUOUS == pybuf.PyBUF_C_CONTIGUOUS)
  *                 and not PyArray_CHKFLAGS(self, NPY_C_CONTIGUOUS)):             # <<<<<<<<<<<<<<
  *                 raise ValueError(u"ndarray is not C contiguous")
  * 
  */
-    __pyx_t_2 = (!PyArray_CHKFLAGS(__pyx_v_self, NPY_C_CONTIGUOUS));
+    __pyx_t_2 = (!PyArray_CHKFLAGS(((PyArrayObject *)__pyx_v_self), NPY_C_CONTIGUOUS));
     __pyx_t_3 = __pyx_t_2;
   } else {
     __pyx_t_3 = __pyx_t_1;
   }
   if (__pyx_t_3) {
 
-    /* "numpy.pxd":214
+    /* "numpy.pxd":211
  *             if ((flags & pybuf.PyBUF_C_CONTIGUOUS == pybuf.PyBUF_C_CONTIGUOUS)
  *                 and not PyArray_CHKFLAGS(self, NPY_C_CONTIGUOUS)):
  *                 raise ValueError(u"ndarray is not C contiguous")             # <<<<<<<<<<<<<<
  * 
  *             if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS)
  */
-    __pyx_t_4 = PyObject_Call(__pyx_builtin_ValueError, ((PyObject *)__pyx_k_tuple_6), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 214; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = PyObject_Call(__pyx_builtin_ValueError, ((PyObject *)__pyx_k_tuple_6), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 211; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_4);
     __Pyx_Raise(__pyx_t_4, 0, 0, 0);
     __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-    {__pyx_filename = __pyx_f[1]; __pyx_lineno = 214; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    goto __pyx_L5;
+    {__pyx_filename = __pyx_f[1]; __pyx_lineno = 211; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    goto __pyx_L7;
   }
-  __pyx_L5:;
+  __pyx_L7:;
 
-  /* "numpy.pxd":216
+  /* "numpy.pxd":213
  *                 raise ValueError(u"ndarray is not C contiguous")
  * 
  *             if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS)             # <<<<<<<<<<<<<<
@@ -4227,46 +4022,46 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
   __pyx_t_3 = ((__pyx_v_flags & PyBUF_F_CONTIGUOUS) == PyBUF_F_CONTIGUOUS);
   if (__pyx_t_3) {
 
-    /* "numpy.pxd":217
+    /* "numpy.pxd":214
  * 
  *             if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS)
  *                 and not PyArray_CHKFLAGS(self, NPY_F_CONTIGUOUS)):             # <<<<<<<<<<<<<<
  *                 raise ValueError(u"ndarray is not Fortran contiguous")
  * 
  */
-    __pyx_t_1 = (!PyArray_CHKFLAGS(__pyx_v_self, NPY_F_CONTIGUOUS));
+    __pyx_t_1 = (!PyArray_CHKFLAGS(((PyArrayObject *)__pyx_v_self), NPY_F_CONTIGUOUS));
     __pyx_t_2 = __pyx_t_1;
   } else {
     __pyx_t_2 = __pyx_t_3;
   }
   if (__pyx_t_2) {
 
-    /* "numpy.pxd":218
+    /* "numpy.pxd":215
  *             if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS)
  *                 and not PyArray_CHKFLAGS(self, NPY_F_CONTIGUOUS)):
  *                 raise ValueError(u"ndarray is not Fortran contiguous")             # <<<<<<<<<<<<<<
  * 
  *             info.buf = PyArray_DATA(self)
  */
-    __pyx_t_4 = PyObject_Call(__pyx_builtin_ValueError, ((PyObject *)__pyx_k_tuple_8), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 218; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = PyObject_Call(__pyx_builtin_ValueError, ((PyObject *)__pyx_k_tuple_8), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 215; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_4);
     __Pyx_Raise(__pyx_t_4, 0, 0, 0);
     __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-    {__pyx_filename = __pyx_f[1]; __pyx_lineno = 218; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    goto __pyx_L6;
+    {__pyx_filename = __pyx_f[1]; __pyx_lineno = 215; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    goto __pyx_L8;
   }
-  __pyx_L6:;
+  __pyx_L8:;
 
-  /* "numpy.pxd":220
+  /* "numpy.pxd":217
  *                 raise ValueError(u"ndarray is not Fortran contiguous")
  * 
  *             info.buf = PyArray_DATA(self)             # <<<<<<<<<<<<<<
  *             info.ndim = ndim
  *             if copy_shape:
  */
-  __pyx_v_info->buf = PyArray_DATA(__pyx_v_self);
+  __pyx_v_info->buf = PyArray_DATA(((PyArrayObject *)__pyx_v_self));
 
-  /* "numpy.pxd":221
+  /* "numpy.pxd":218
  * 
  *             info.buf = PyArray_DATA(self)
  *             info.ndim = ndim             # <<<<<<<<<<<<<<
@@ -4275,7 +4070,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
   __pyx_v_info->ndim = __pyx_v_ndim;
 
-  /* "numpy.pxd":222
+  /* "numpy.pxd":219
  *             info.buf = PyArray_DATA(self)
  *             info.ndim = ndim
  *             if copy_shape:             # <<<<<<<<<<<<<<
@@ -4284,7 +4079,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
   if (__pyx_v_copy_shape) {
 
-    /* "numpy.pxd":225
+    /* "numpy.pxd":222
  *                 # Allocate new buffer for strides and shape info.
  *                 # This is allocated as one block, strides first.
  *                 info.strides = <Py_ssize_t*>stdlib.malloc(sizeof(Py_ssize_t) * <size_t>ndim * 2)             # <<<<<<<<<<<<<<
@@ -4293,7 +4088,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
     __pyx_v_info->strides = ((Py_ssize_t *)malloc((((sizeof(Py_ssize_t)) * ((size_t)__pyx_v_ndim)) * 2)));
 
-    /* "numpy.pxd":226
+    /* "numpy.pxd":223
  *                 # This is allocated as one block, strides first.
  *                 info.strides = <Py_ssize_t*>stdlib.malloc(sizeof(Py_ssize_t) * <size_t>ndim * 2)
  *                 info.shape = info.strides + ndim             # <<<<<<<<<<<<<<
@@ -4302,7 +4097,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
     __pyx_v_info->shape = (__pyx_v_info->strides + __pyx_v_ndim);
 
-    /* "numpy.pxd":227
+    /* "numpy.pxd":224
  *                 info.strides = <Py_ssize_t*>stdlib.malloc(sizeof(Py_ssize_t) * <size_t>ndim * 2)
  *                 info.shape = info.strides + ndim
  *                 for i in range(ndim):             # <<<<<<<<<<<<<<
@@ -4313,49 +4108,49 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     for (__pyx_t_6 = 0; __pyx_t_6 < __pyx_t_5; __pyx_t_6+=1) {
       __pyx_v_i = __pyx_t_6;
 
-      /* "numpy.pxd":228
+      /* "numpy.pxd":225
  *                 info.shape = info.strides + ndim
  *                 for i in range(ndim):
  *                     info.strides[i] = PyArray_STRIDES(self)[i]             # <<<<<<<<<<<<<<
  *                     info.shape[i] = PyArray_DIMS(self)[i]
  *             else:
  */
-      (__pyx_v_info->strides[__pyx_v_i]) = (PyArray_STRIDES(__pyx_v_self)[__pyx_v_i]);
+      (__pyx_v_info->strides[__pyx_v_i]) = (PyArray_STRIDES(((PyArrayObject *)__pyx_v_self))[__pyx_v_i]);
 
-      /* "numpy.pxd":229
+      /* "numpy.pxd":226
  *                 for i in range(ndim):
  *                     info.strides[i] = PyArray_STRIDES(self)[i]
  *                     info.shape[i] = PyArray_DIMS(self)[i]             # <<<<<<<<<<<<<<
  *             else:
  *                 info.strides = <Py_ssize_t*>PyArray_STRIDES(self)
  */
-      (__pyx_v_info->shape[__pyx_v_i]) = (PyArray_DIMS(__pyx_v_self)[__pyx_v_i]);
+      (__pyx_v_info->shape[__pyx_v_i]) = (PyArray_DIMS(((PyArrayObject *)__pyx_v_self))[__pyx_v_i]);
     }
-    goto __pyx_L7;
+    goto __pyx_L9;
   }
   /*else*/ {
 
-    /* "numpy.pxd":231
+    /* "numpy.pxd":228
  *                     info.shape[i] = PyArray_DIMS(self)[i]
  *             else:
  *                 info.strides = <Py_ssize_t*>PyArray_STRIDES(self)             # <<<<<<<<<<<<<<
  *                 info.shape = <Py_ssize_t*>PyArray_DIMS(self)
  *             info.suboffsets = NULL
  */
-    __pyx_v_info->strides = ((Py_ssize_t *)PyArray_STRIDES(__pyx_v_self));
+    __pyx_v_info->strides = ((Py_ssize_t *)PyArray_STRIDES(((PyArrayObject *)__pyx_v_self)));
 
-    /* "numpy.pxd":232
+    /* "numpy.pxd":229
  *             else:
  *                 info.strides = <Py_ssize_t*>PyArray_STRIDES(self)
  *                 info.shape = <Py_ssize_t*>PyArray_DIMS(self)             # <<<<<<<<<<<<<<
  *             info.suboffsets = NULL
  *             info.itemsize = PyArray_ITEMSIZE(self)
  */
-    __pyx_v_info->shape = ((Py_ssize_t *)PyArray_DIMS(__pyx_v_self));
+    __pyx_v_info->shape = ((Py_ssize_t *)PyArray_DIMS(((PyArrayObject *)__pyx_v_self)));
   }
-  __pyx_L7:;
+  __pyx_L9:;
 
-  /* "numpy.pxd":233
+  /* "numpy.pxd":230
  *                 info.strides = <Py_ssize_t*>PyArray_STRIDES(self)
  *                 info.shape = <Py_ssize_t*>PyArray_DIMS(self)
  *             info.suboffsets = NULL             # <<<<<<<<<<<<<<
@@ -4364,25 +4159,25 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
   __pyx_v_info->suboffsets = NULL;
 
-  /* "numpy.pxd":234
+  /* "numpy.pxd":231
  *                 info.shape = <Py_ssize_t*>PyArray_DIMS(self)
  *             info.suboffsets = NULL
  *             info.itemsize = PyArray_ITEMSIZE(self)             # <<<<<<<<<<<<<<
  *             info.readonly = not PyArray_ISWRITEABLE(self)
  * 
  */
-  __pyx_v_info->itemsize = PyArray_ITEMSIZE(__pyx_v_self);
+  __pyx_v_info->itemsize = PyArray_ITEMSIZE(((PyArrayObject *)__pyx_v_self));
 
-  /* "numpy.pxd":235
+  /* "numpy.pxd":232
  *             info.suboffsets = NULL
  *             info.itemsize = PyArray_ITEMSIZE(self)
  *             info.readonly = not PyArray_ISWRITEABLE(self)             # <<<<<<<<<<<<<<
  * 
  *             cdef int t
  */
-  __pyx_v_info->readonly = (!PyArray_ISWRITEABLE(__pyx_v_self));
+  __pyx_v_info->readonly = (!PyArray_ISWRITEABLE(((PyArrayObject *)__pyx_v_self)));
 
-  /* "numpy.pxd":238
+  /* "numpy.pxd":235
  * 
  *             cdef int t
  *             cdef char* f = NULL             # <<<<<<<<<<<<<<
@@ -4391,17 +4186,17 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
   __pyx_v_f = NULL;
 
-  /* "numpy.pxd":239
+  /* "numpy.pxd":236
  *             cdef int t
  *             cdef char* f = NULL
  *             cdef dtype descr = self.descr             # <<<<<<<<<<<<<<
  *             cdef list stack
  *             cdef int offset
  */
-  __Pyx_INCREF(((PyObject *)__pyx_v_self->descr));
-  __pyx_v_descr = __pyx_v_self->descr;
+  __Pyx_INCREF(((PyObject *)((PyArrayObject *)__pyx_v_self)->descr));
+  __pyx_v_descr = ((PyArrayObject *)__pyx_v_self)->descr;
 
-  /* "numpy.pxd":243
+  /* "numpy.pxd":240
  *             cdef int offset
  * 
  *             cdef bint hasfields = PyDataType_HASFIELDS(descr)             # <<<<<<<<<<<<<<
@@ -4410,7 +4205,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
   __pyx_v_hasfields = PyDataType_HASFIELDS(__pyx_v_descr);
 
-  /* "numpy.pxd":245
+  /* "numpy.pxd":242
  *             cdef bint hasfields = PyDataType_HASFIELDS(descr)
  * 
  *             if not hasfields and not copy_shape:             # <<<<<<<<<<<<<<
@@ -4426,7 +4221,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
   }
   if (__pyx_t_1) {
 
-    /* "numpy.pxd":247
+    /* "numpy.pxd":244
  *             if not hasfields and not copy_shape:
  *                 # do not call releasebuffer
  *                 info.obj = None             # <<<<<<<<<<<<<<
@@ -4438,26 +4233,26 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __Pyx_GOTREF(__pyx_v_info->obj);
     __Pyx_DECREF(__pyx_v_info->obj);
     __pyx_v_info->obj = Py_None;
-    goto __pyx_L10;
+    goto __pyx_L12;
   }
   /*else*/ {
 
-    /* "numpy.pxd":250
+    /* "numpy.pxd":247
  *             else:
  *                 # need to call releasebuffer
  *                 info.obj = self             # <<<<<<<<<<<<<<
  * 
  *             if not hasfields:
  */
-    __Pyx_INCREF(((PyObject *)__pyx_v_self));
-    __Pyx_GIVEREF(((PyObject *)__pyx_v_self));
+    __Pyx_INCREF(__pyx_v_self);
+    __Pyx_GIVEREF(__pyx_v_self);
     __Pyx_GOTREF(__pyx_v_info->obj);
     __Pyx_DECREF(__pyx_v_info->obj);
-    __pyx_v_info->obj = ((PyObject *)__pyx_v_self);
+    __pyx_v_info->obj = __pyx_v_self;
   }
-  __pyx_L10:;
+  __pyx_L12:;
 
-  /* "numpy.pxd":252
+  /* "numpy.pxd":249
  *                 info.obj = self
  * 
  *             if not hasfields:             # <<<<<<<<<<<<<<
@@ -4467,7 +4262,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
   __pyx_t_1 = (!__pyx_v_hasfields);
   if (__pyx_t_1) {
 
-    /* "numpy.pxd":253
+    /* "numpy.pxd":250
  * 
  *             if not hasfields:
  *                 t = descr.type_num             # <<<<<<<<<<<<<<
@@ -4476,7 +4271,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
     __pyx_v_t = __pyx_v_descr->type_num;
 
-    /* "numpy.pxd":254
+    /* "numpy.pxd":251
  *             if not hasfields:
  *                 t = descr.type_num
  *                 if ((descr.byteorder == '>' and little_endian) or             # <<<<<<<<<<<<<<
@@ -4491,7 +4286,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     }
     if (!__pyx_t_2) {
 
-      /* "numpy.pxd":255
+      /* "numpy.pxd":252
  *                 t = descr.type_num
  *                 if ((descr.byteorder == '>' and little_endian) or
  *                     (descr.byteorder == '<' and not little_endian)):             # <<<<<<<<<<<<<<
@@ -4511,23 +4306,23 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     }
     if (__pyx_t_1) {
 
-      /* "numpy.pxd":256
+      /* "numpy.pxd":253
  *                 if ((descr.byteorder == '>' and little_endian) or
  *                     (descr.byteorder == '<' and not little_endian)):
  *                     raise ValueError(u"Non-native byte order not supported")             # <<<<<<<<<<<<<<
  *                 if   t == NPY_BYTE:        f = "b"
  *                 elif t == NPY_UBYTE:       f = "B"
  */
-      __pyx_t_4 = PyObject_Call(__pyx_builtin_ValueError, ((PyObject *)__pyx_k_tuple_10), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 256; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyObject_Call(__pyx_builtin_ValueError, ((PyObject *)__pyx_k_tuple_10), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 253; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_4);
       __Pyx_Raise(__pyx_t_4, 0, 0, 0);
       __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      {__pyx_filename = __pyx_f[1]; __pyx_lineno = 256; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      goto __pyx_L12;
+      {__pyx_filename = __pyx_f[1]; __pyx_lineno = 253; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      goto __pyx_L14;
     }
-    __pyx_L12:;
+    __pyx_L14:;
 
-    /* "numpy.pxd":257
+    /* "numpy.pxd":254
  *                     (descr.byteorder == '<' and not little_endian)):
  *                     raise ValueError(u"Non-native byte order not supported")
  *                 if   t == NPY_BYTE:        f = "b"             # <<<<<<<<<<<<<<
@@ -4537,10 +4332,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_BYTE);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__b;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":258
+    /* "numpy.pxd":255
  *                     raise ValueError(u"Non-native byte order not supported")
  *                 if   t == NPY_BYTE:        f = "b"
  *                 elif t == NPY_UBYTE:       f = "B"             # <<<<<<<<<<<<<<
@@ -4550,10 +4345,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_UBYTE);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__B;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":259
+    /* "numpy.pxd":256
  *                 if   t == NPY_BYTE:        f = "b"
  *                 elif t == NPY_UBYTE:       f = "B"
  *                 elif t == NPY_SHORT:       f = "h"             # <<<<<<<<<<<<<<
@@ -4563,10 +4358,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_SHORT);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__h;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":260
+    /* "numpy.pxd":257
  *                 elif t == NPY_UBYTE:       f = "B"
  *                 elif t == NPY_SHORT:       f = "h"
  *                 elif t == NPY_USHORT:      f = "H"             # <<<<<<<<<<<<<<
@@ -4576,10 +4371,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_USHORT);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__H;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":261
+    /* "numpy.pxd":258
  *                 elif t == NPY_SHORT:       f = "h"
  *                 elif t == NPY_USHORT:      f = "H"
  *                 elif t == NPY_INT:         f = "i"             # <<<<<<<<<<<<<<
@@ -4589,10 +4384,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_INT);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__i;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":262
+    /* "numpy.pxd":259
  *                 elif t == NPY_USHORT:      f = "H"
  *                 elif t == NPY_INT:         f = "i"
  *                 elif t == NPY_UINT:        f = "I"             # <<<<<<<<<<<<<<
@@ -4602,10 +4397,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_UINT);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__I;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":263
+    /* "numpy.pxd":260
  *                 elif t == NPY_INT:         f = "i"
  *                 elif t == NPY_UINT:        f = "I"
  *                 elif t == NPY_LONG:        f = "l"             # <<<<<<<<<<<<<<
@@ -4615,10 +4410,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_LONG);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__l;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":264
+    /* "numpy.pxd":261
  *                 elif t == NPY_UINT:        f = "I"
  *                 elif t == NPY_LONG:        f = "l"
  *                 elif t == NPY_ULONG:       f = "L"             # <<<<<<<<<<<<<<
@@ -4628,10 +4423,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_ULONG);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__L;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":265
+    /* "numpy.pxd":262
  *                 elif t == NPY_LONG:        f = "l"
  *                 elif t == NPY_ULONG:       f = "L"
  *                 elif t == NPY_LONGLONG:    f = "q"             # <<<<<<<<<<<<<<
@@ -4641,10 +4436,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_LONGLONG);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__q;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":266
+    /* "numpy.pxd":263
  *                 elif t == NPY_ULONG:       f = "L"
  *                 elif t == NPY_LONGLONG:    f = "q"
  *                 elif t == NPY_ULONGLONG:   f = "Q"             # <<<<<<<<<<<<<<
@@ -4654,10 +4449,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_ULONGLONG);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__Q;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":267
+    /* "numpy.pxd":264
  *                 elif t == NPY_LONGLONG:    f = "q"
  *                 elif t == NPY_ULONGLONG:   f = "Q"
  *                 elif t == NPY_FLOAT:       f = "f"             # <<<<<<<<<<<<<<
@@ -4667,10 +4462,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_FLOAT);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__f;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":268
+    /* "numpy.pxd":265
  *                 elif t == NPY_ULONGLONG:   f = "Q"
  *                 elif t == NPY_FLOAT:       f = "f"
  *                 elif t == NPY_DOUBLE:      f = "d"             # <<<<<<<<<<<<<<
@@ -4680,10 +4475,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_DOUBLE);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__d;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":269
+    /* "numpy.pxd":266
  *                 elif t == NPY_FLOAT:       f = "f"
  *                 elif t == NPY_DOUBLE:      f = "d"
  *                 elif t == NPY_LONGDOUBLE:  f = "g"             # <<<<<<<<<<<<<<
@@ -4693,10 +4488,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_LONGDOUBLE);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__g;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":270
+    /* "numpy.pxd":267
  *                 elif t == NPY_DOUBLE:      f = "d"
  *                 elif t == NPY_LONGDOUBLE:  f = "g"
  *                 elif t == NPY_CFLOAT:      f = "Zf"             # <<<<<<<<<<<<<<
@@ -4706,10 +4501,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_CFLOAT);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__Zf;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":271
+    /* "numpy.pxd":268
  *                 elif t == NPY_LONGDOUBLE:  f = "g"
  *                 elif t == NPY_CFLOAT:      f = "Zf"
  *                 elif t == NPY_CDOUBLE:     f = "Zd"             # <<<<<<<<<<<<<<
@@ -4719,10 +4514,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_CDOUBLE);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__Zd;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":272
+    /* "numpy.pxd":269
  *                 elif t == NPY_CFLOAT:      f = "Zf"
  *                 elif t == NPY_CDOUBLE:     f = "Zd"
  *                 elif t == NPY_CLONGDOUBLE: f = "Zg"             # <<<<<<<<<<<<<<
@@ -4732,10 +4527,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_CLONGDOUBLE);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__Zg;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":273
+    /* "numpy.pxd":270
  *                 elif t == NPY_CDOUBLE:     f = "Zd"
  *                 elif t == NPY_CLONGDOUBLE: f = "Zg"
  *                 elif t == NPY_OBJECT:      f = "O"             # <<<<<<<<<<<<<<
@@ -4745,37 +4540,37 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_OBJECT);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__O;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
     /*else*/ {
 
-      /* "numpy.pxd":275
+      /* "numpy.pxd":272
  *                 elif t == NPY_OBJECT:      f = "O"
  *                 else:
  *                     raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t)             # <<<<<<<<<<<<<<
  *                 info.format = f
  *                 return
  */
-      __pyx_t_4 = PyInt_FromLong(__pyx_v_t); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 275; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyInt_FromLong(__pyx_v_t); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 272; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_4);
-      __pyx_t_8 = PyNumber_Remainder(((PyObject *)__pyx_kp_u_11), __pyx_t_4); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 275; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_8 = PyNumber_Remainder(((PyObject *)__pyx_kp_u_11), __pyx_t_4); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 272; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(((PyObject *)__pyx_t_8));
       __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 275; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      __Pyx_GOTREF(__pyx_t_4);
+      __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 272; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(((PyObject *)__pyx_t_4));
       PyTuple_SET_ITEM(__pyx_t_4, 0, ((PyObject *)__pyx_t_8));
       __Pyx_GIVEREF(((PyObject *)__pyx_t_8));
       __pyx_t_8 = 0;
-      __pyx_t_8 = PyObject_Call(__pyx_builtin_ValueError, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 275; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_8 = PyObject_Call(__pyx_builtin_ValueError, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 272; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_8);
       __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
       __Pyx_Raise(__pyx_t_8, 0, 0, 0);
       __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-      {__pyx_filename = __pyx_f[1]; __pyx_lineno = 275; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      {__pyx_filename = __pyx_f[1]; __pyx_lineno = 272; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     }
-    __pyx_L13:;
+    __pyx_L15:;
 
-    /* "numpy.pxd":276
+    /* "numpy.pxd":273
  *                 else:
  *                     raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t)
  *                 info.format = f             # <<<<<<<<<<<<<<
@@ -4784,7 +4579,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
     __pyx_v_info->format = __pyx_v_f;
 
-    /* "numpy.pxd":277
+    /* "numpy.pxd":274
  *                     raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t)
  *                 info.format = f
  *                 return             # <<<<<<<<<<<<<<
@@ -4793,11 +4588,11 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
     __pyx_r = 0;
     goto __pyx_L0;
-    goto __pyx_L11;
+    goto __pyx_L13;
   }
   /*else*/ {
 
-    /* "numpy.pxd":279
+    /* "numpy.pxd":276
  *                 return
  *             else:
  *                 info.format = <char*>stdlib.malloc(_buffer_format_string_len)             # <<<<<<<<<<<<<<
@@ -4806,7 +4601,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
     __pyx_v_info->format = ((char *)malloc(255));
 
-    /* "numpy.pxd":280
+    /* "numpy.pxd":277
  *             else:
  *                 info.format = <char*>stdlib.malloc(_buffer_format_string_len)
  *                 info.format[0] = '^' # Native data types, manual alignment             # <<<<<<<<<<<<<<
@@ -4815,7 +4610,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
     (__pyx_v_info->format[0]) = '^';
 
-    /* "numpy.pxd":281
+    /* "numpy.pxd":278
  *                 info.format = <char*>stdlib.malloc(_buffer_format_string_len)
  *                 info.format[0] = '^' # Native data types, manual alignment
  *                 offset = 0             # <<<<<<<<<<<<<<
@@ -4824,17 +4619,17 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
     __pyx_v_offset = 0;
 
-    /* "numpy.pxd":284
+    /* "numpy.pxd":281
  *                 f = _util_dtypestring(descr, info.format + 1,
  *                                       info.format + _buffer_format_string_len,
  *                                       &offset)             # <<<<<<<<<<<<<<
  *                 f[0] = 0 # Terminate format string
  * 
  */
-    __pyx_t_9 = __pyx_f_5numpy__util_dtypestring(__pyx_v_descr, (__pyx_v_info->format + 1), (__pyx_v_info->format + 255), (&__pyx_v_offset)); if (unlikely(__pyx_t_9 == NULL)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 282; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_9 = __pyx_f_5numpy__util_dtypestring(__pyx_v_descr, (__pyx_v_info->format + 1), (__pyx_v_info->format + 255), (&__pyx_v_offset)); if (unlikely(__pyx_t_9 == NULL)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 279; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __pyx_v_f = __pyx_t_9;
 
-    /* "numpy.pxd":285
+    /* "numpy.pxd":282
  *                                       info.format + _buffer_format_string_len,
  *                                       &offset)
  *                 f[0] = 0 # Terminate format string             # <<<<<<<<<<<<<<
@@ -4843,7 +4638,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
     (__pyx_v_f[0]) = 0;
   }
-  __pyx_L11:;
+  __pyx_L13:;
 
   __pyx_r = 0;
   goto __pyx_L0;
@@ -4868,16 +4663,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
   return __pyx_r;
 }
 
-/* Python wrapper */
-static void __pyx_pw_5numpy_7ndarray_3__releasebuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info); /*proto*/
-static void __pyx_pw_5numpy_7ndarray_3__releasebuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info) {
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__releasebuffer__ (wrapper)", 0);
-  __pyx_pf_5numpy_7ndarray_2__releasebuffer__(((PyArrayObject *)__pyx_v_self), ((Py_buffer *)__pyx_v_info));
-  __Pyx_RefNannyFinishContext();
-}
-
-/* "numpy.pxd":287
+/* "numpy.pxd":284
  *                 f[0] = 0 # Terminate format string
  * 
  *         def __releasebuffer__(ndarray self, Py_buffer* info):             # <<<<<<<<<<<<<<
@@ -4885,22 +4671,23 @@ static void __pyx_pw_5numpy_7ndarray_3__releasebuffer__(PyObject *__pyx_v_self,
  *                 stdlib.free(info.format)
  */
 
-static void __pyx_pf_5numpy_7ndarray_2__releasebuffer__(PyArrayObject *__pyx_v_self, Py_buffer *__pyx_v_info) {
+static CYTHON_UNUSED void __pyx_pf_5numpy_7ndarray_1__releasebuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info); /*proto*/
+static CYTHON_UNUSED void __pyx_pf_5numpy_7ndarray_1__releasebuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info) {
   __Pyx_RefNannyDeclarations
   int __pyx_t_1;
-  __Pyx_RefNannySetupContext("__releasebuffer__", 0);
+  __Pyx_RefNannySetupContext("__releasebuffer__");
 
-  /* "numpy.pxd":288
+  /* "numpy.pxd":285
  * 
  *         def __releasebuffer__(ndarray self, Py_buffer* info):
  *             if PyArray_HASFIELDS(self):             # <<<<<<<<<<<<<<
  *                 stdlib.free(info.format)
  *             if sizeof(npy_intp) != sizeof(Py_ssize_t):
  */
-  __pyx_t_1 = PyArray_HASFIELDS(__pyx_v_self);
+  __pyx_t_1 = PyArray_HASFIELDS(((PyArrayObject *)__pyx_v_self));
   if (__pyx_t_1) {
 
-    /* "numpy.pxd":289
+    /* "numpy.pxd":286
  *         def __releasebuffer__(ndarray self, Py_buffer* info):
  *             if PyArray_HASFIELDS(self):
  *                 stdlib.free(info.format)             # <<<<<<<<<<<<<<
@@ -4908,11 +4695,11 @@ static void __pyx_pf_5numpy_7ndarray_2__releasebuffer__(PyArrayObject *__pyx_v_s
  *                 stdlib.free(info.strides)
  */
     free(__pyx_v_info->format);
-    goto __pyx_L3;
+    goto __pyx_L5;
   }
-  __pyx_L3:;
+  __pyx_L5:;
 
-  /* "numpy.pxd":290
+  /* "numpy.pxd":287
  *             if PyArray_HASFIELDS(self):
  *                 stdlib.free(info.format)
  *             if sizeof(npy_intp) != sizeof(Py_ssize_t):             # <<<<<<<<<<<<<<
@@ -4922,7 +4709,7 @@ static void __pyx_pf_5numpy_7ndarray_2__releasebuffer__(PyArrayObject *__pyx_v_s
   __pyx_t_1 = ((sizeof(npy_intp)) != (sizeof(Py_ssize_t)));
   if (__pyx_t_1) {
 
-    /* "numpy.pxd":291
+    /* "numpy.pxd":288
  *                 stdlib.free(info.format)
  *             if sizeof(npy_intp) != sizeof(Py_ssize_t):
  *                 stdlib.free(info.strides)             # <<<<<<<<<<<<<<
@@ -4930,14 +4717,14 @@ static void __pyx_pf_5numpy_7ndarray_2__releasebuffer__(PyArrayObject *__pyx_v_s
  * 
  */
     free(__pyx_v_info->strides);
-    goto __pyx_L4;
+    goto __pyx_L6;
   }
-  __pyx_L4:;
+  __pyx_L6:;
 
   __Pyx_RefNannyFinishContext();
 }
 
-/* "numpy.pxd":767
+/* "numpy.pxd":764
  * ctypedef npy_cdouble     complex_t
  * 
  * cdef inline object PyArray_MultiIterNew1(a):             # <<<<<<<<<<<<<<
@@ -4952,9 +4739,9 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew1(PyObject *__
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("PyArray_MultiIterNew1", 0);
+  __Pyx_RefNannySetupContext("PyArray_MultiIterNew1");
 
-  /* "numpy.pxd":768
+  /* "numpy.pxd":765
  * 
  * cdef inline object PyArray_MultiIterNew1(a):
  *     return PyArray_MultiIterNew(1, <void*>a)             # <<<<<<<<<<<<<<
@@ -4962,7 +4749,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew1(PyObject *__
  * cdef inline object PyArray_MultiIterNew2(a, b):
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = PyArray_MultiIterNew(1, ((void *)__pyx_v_a)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 768; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyArray_MultiIterNew(1, ((void *)__pyx_v_a)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 765; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -4980,7 +4767,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew1(PyObject *__
   return __pyx_r;
 }
 
-/* "numpy.pxd":770
+/* "numpy.pxd":767
  *     return PyArray_MultiIterNew(1, <void*>a)
  * 
  * cdef inline object PyArray_MultiIterNew2(a, b):             # <<<<<<<<<<<<<<
@@ -4995,9 +4782,9 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew2(PyObject *__
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("PyArray_MultiIterNew2", 0);
+  __Pyx_RefNannySetupContext("PyArray_MultiIterNew2");
 
-  /* "numpy.pxd":771
+  /* "numpy.pxd":768
  * 
  * cdef inline object PyArray_MultiIterNew2(a, b):
  *     return PyArray_MultiIterNew(2, <void*>a, <void*>b)             # <<<<<<<<<<<<<<
@@ -5005,7 +4792,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew2(PyObject *__
  * cdef inline object PyArray_MultiIterNew3(a, b, c):
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = PyArray_MultiIterNew(2, ((void *)__pyx_v_a), ((void *)__pyx_v_b)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 771; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyArray_MultiIterNew(2, ((void *)__pyx_v_a), ((void *)__pyx_v_b)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 768; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -5023,7 +4810,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew2(PyObject *__
   return __pyx_r;
 }
 
-/* "numpy.pxd":773
+/* "numpy.pxd":770
  *     return PyArray_MultiIterNew(2, <void*>a, <void*>b)
  * 
  * cdef inline object PyArray_MultiIterNew3(a, b, c):             # <<<<<<<<<<<<<<
@@ -5038,9 +4825,9 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew3(PyObject *__
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("PyArray_MultiIterNew3", 0);
+  __Pyx_RefNannySetupContext("PyArray_MultiIterNew3");
 
-  /* "numpy.pxd":774
+  /* "numpy.pxd":771
  * 
  * cdef inline object PyArray_MultiIterNew3(a, b, c):
  *     return PyArray_MultiIterNew(3, <void*>a, <void*>b, <void*> c)             # <<<<<<<<<<<<<<
@@ -5048,7 +4835,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew3(PyObject *__
  * cdef inline object PyArray_MultiIterNew4(a, b, c, d):
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = PyArray_MultiIterNew(3, ((void *)__pyx_v_a), ((void *)__pyx_v_b), ((void *)__pyx_v_c)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 774; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyArray_MultiIterNew(3, ((void *)__pyx_v_a), ((void *)__pyx_v_b), ((void *)__pyx_v_c)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 771; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -5066,7 +4853,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew3(PyObject *__
   return __pyx_r;
 }
 
-/* "numpy.pxd":776
+/* "numpy.pxd":773
  *     return PyArray_MultiIterNew(3, <void*>a, <void*>b, <void*> c)
  * 
  * cdef inline object PyArray_MultiIterNew4(a, b, c, d):             # <<<<<<<<<<<<<<
@@ -5081,9 +4868,9 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew4(PyObject *__
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("PyArray_MultiIterNew4", 0);
+  __Pyx_RefNannySetupContext("PyArray_MultiIterNew4");
 
-  /* "numpy.pxd":777
+  /* "numpy.pxd":774
  * 
  * cdef inline object PyArray_MultiIterNew4(a, b, c, d):
  *     return PyArray_MultiIterNew(4, <void*>a, <void*>b, <void*>c, <void*> d)             # <<<<<<<<<<<<<<
@@ -5091,7 +4878,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew4(PyObject *__
  * cdef inline object PyArray_MultiIterNew5(a, b, c, d, e):
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = PyArray_MultiIterNew(4, ((void *)__pyx_v_a), ((void *)__pyx_v_b), ((void *)__pyx_v_c), ((void *)__pyx_v_d)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 777; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyArray_MultiIterNew(4, ((void *)__pyx_v_a), ((void *)__pyx_v_b), ((void *)__pyx_v_c), ((void *)__pyx_v_d)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 774; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -5109,7 +4896,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew4(PyObject *__
   return __pyx_r;
 }
 
-/* "numpy.pxd":779
+/* "numpy.pxd":776
  *     return PyArray_MultiIterNew(4, <void*>a, <void*>b, <void*>c, <void*> d)
  * 
  * cdef inline object PyArray_MultiIterNew5(a, b, c, d, e):             # <<<<<<<<<<<<<<
@@ -5124,9 +4911,9 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew5(PyObject *__
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("PyArray_MultiIterNew5", 0);
+  __Pyx_RefNannySetupContext("PyArray_MultiIterNew5");
 
-  /* "numpy.pxd":780
+  /* "numpy.pxd":777
  * 
  * cdef inline object PyArray_MultiIterNew5(a, b, c, d, e):
  *     return PyArray_MultiIterNew(5, <void*>a, <void*>b, <void*>c, <void*> d, <void*> e)             # <<<<<<<<<<<<<<
@@ -5134,7 +4921,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew5(PyObject *__
  * cdef inline char* _util_dtypestring(dtype descr, char* f, char* end, int* offset) except NULL:
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = PyArray_MultiIterNew(5, ((void *)__pyx_v_a), ((void *)__pyx_v_b), ((void *)__pyx_v_c), ((void *)__pyx_v_d), ((void *)__pyx_v_e)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 780; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyArray_MultiIterNew(5, ((void *)__pyx_v_a), ((void *)__pyx_v_b), ((void *)__pyx_v_c), ((void *)__pyx_v_d), ((void *)__pyx_v_e)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 777; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -5152,7 +4939,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew5(PyObject *__
   return __pyx_r;
 }
 
-/* "numpy.pxd":782
+/* "numpy.pxd":779
  *     return PyArray_MultiIterNew(5, <void*>a, <void*>b, <void*>c, <void*> d, <void*> e)
  * 
  * cdef inline char* _util_dtypestring(dtype descr, char* f, char* end, int* offset) except NULL:             # <<<<<<<<<<<<<<
@@ -5184,9 +4971,9 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("_util_dtypestring", 0);
+  __Pyx_RefNannySetupContext("_util_dtypestring");
 
-  /* "numpy.pxd":789
+  /* "numpy.pxd":786
  *     cdef int delta_offset
  *     cdef tuple i
  *     cdef int endian_detector = 1             # <<<<<<<<<<<<<<
@@ -5195,7 +4982,7 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
  */
   __pyx_v_endian_detector = 1;
 
-  /* "numpy.pxd":790
+  /* "numpy.pxd":787
  *     cdef tuple i
  *     cdef int endian_detector = 1
  *     cdef bint little_endian = ((<char*>&endian_detector)[0] != 0)             # <<<<<<<<<<<<<<
@@ -5204,7 +4991,7 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
  */
   __pyx_v_little_endian = ((((char *)(&__pyx_v_endian_detector))[0]) != 0);
 
-  /* "numpy.pxd":793
+  /* "numpy.pxd":790
  *     cdef tuple fields
  * 
  *     for childname in descr.names:             # <<<<<<<<<<<<<<
@@ -5212,7 +4999,7 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
  *         child, new_offset = fields
  */
   if (unlikely(((PyObject *)__pyx_v_descr->names) == Py_None)) {
-    PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable"); {__pyx_filename = __pyx_f[1]; __pyx_lineno = 793; __pyx_clineno = __LINE__; goto __pyx_L1_error;} 
+    PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable"); {__pyx_filename = __pyx_f[1]; __pyx_lineno = 790; __pyx_clineno = __LINE__; goto __pyx_L1_error;} 
   }
   __pyx_t_1 = ((PyObject *)__pyx_v_descr->names); __Pyx_INCREF(__pyx_t_1); __pyx_t_2 = 0;
   for (;;) {
@@ -5222,21 +5009,21 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
     __pyx_v_childname = __pyx_t_3;
     __pyx_t_3 = 0;
 
-    /* "numpy.pxd":794
+    /* "numpy.pxd":791
  * 
  *     for childname in descr.names:
  *         fields = descr.fields[childname]             # <<<<<<<<<<<<<<
  *         child, new_offset = fields
  * 
  */
-    __pyx_t_3 = PyObject_GetItem(__pyx_v_descr->fields, __pyx_v_childname); if (!__pyx_t_3) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 794; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = PyObject_GetItem(__pyx_v_descr->fields, __pyx_v_childname); if (!__pyx_t_3) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 791; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_3);
-    if (!(likely(PyTuple_CheckExact(__pyx_t_3))||((__pyx_t_3) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected tuple, got %.200s", Py_TYPE(__pyx_t_3)->tp_name), 0))) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 794; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (!(likely(PyTuple_CheckExact(__pyx_t_3))||((__pyx_t_3) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected tuple, got %.200s", Py_TYPE(__pyx_t_3)->tp_name), 0))) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 791; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_XDECREF(((PyObject *)__pyx_v_fields));
     __pyx_v_fields = ((PyObject*)__pyx_t_3);
     __pyx_t_3 = 0;
 
-    /* "numpy.pxd":795
+    /* "numpy.pxd":792
  *     for childname in descr.names:
  *         fields = descr.fields[childname]
  *         child, new_offset = fields             # <<<<<<<<<<<<<<
@@ -5248,7 +5035,7 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
       if (unlikely(PyTuple_GET_SIZE(sequence) != 2)) {
         if (PyTuple_GET_SIZE(sequence) > 2) __Pyx_RaiseTooManyValuesError(2);
         else __Pyx_RaiseNeedMoreValuesError(PyTuple_GET_SIZE(sequence));
-        {__pyx_filename = __pyx_f[1]; __pyx_lineno = 795; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        {__pyx_filename = __pyx_f[1]; __pyx_lineno = 792; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       }
       __pyx_t_3 = PyTuple_GET_ITEM(sequence, 0); 
       __pyx_t_4 = PyTuple_GET_ITEM(sequence, 1); 
@@ -5256,9 +5043,9 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
       __Pyx_INCREF(__pyx_t_4);
     } else {
       __Pyx_UnpackTupleError(((PyObject *)__pyx_v_fields), 2);
-      {__pyx_filename = __pyx_f[1]; __pyx_lineno = 795; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      {__pyx_filename = __pyx_f[1]; __pyx_lineno = 792; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     }
-    if (!(likely(((__pyx_t_3) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_3, __pyx_ptype_5numpy_dtype))))) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 795; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (!(likely(((__pyx_t_3) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_3, __pyx_ptype_5numpy_dtype))))) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 792; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_XDECREF(((PyObject *)__pyx_v_child));
     __pyx_v_child = ((PyArray_Descr *)__pyx_t_3);
     __pyx_t_3 = 0;
@@ -5266,48 +5053,48 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
     __pyx_v_new_offset = __pyx_t_4;
     __pyx_t_4 = 0;
 
-    /* "numpy.pxd":797
+    /* "numpy.pxd":794
  *         child, new_offset = fields
  * 
  *         if (end - f) - (new_offset - offset[0]) < 15:             # <<<<<<<<<<<<<<
  *             raise RuntimeError(u"Format string allocated too short, see comment in numpy.pxd")
  * 
  */
-    __pyx_t_4 = PyInt_FromLong((__pyx_v_end - __pyx_v_f)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 797; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = PyInt_FromLong((__pyx_v_end - __pyx_v_f)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 794; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_4);
-    __pyx_t_3 = PyInt_FromLong((__pyx_v_offset[0])); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 797; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = PyInt_FromLong((__pyx_v_offset[0])); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 794; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_3);
-    __pyx_t_5 = PyNumber_Subtract(__pyx_v_new_offset, __pyx_t_3); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 797; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = PyNumber_Subtract(__pyx_v_new_offset, __pyx_t_3); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 794; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_5);
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __pyx_t_3 = PyNumber_Subtract(__pyx_t_4, __pyx_t_5); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 797; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = PyNumber_Subtract(__pyx_t_4, __pyx_t_5); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 794; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_3);
     __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
     __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-    __pyx_t_5 = PyObject_RichCompare(__pyx_t_3, __pyx_int_15, Py_LT); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 797; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = PyObject_RichCompare(__pyx_t_3, __pyx_int_15, Py_LT); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 794; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_5);
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 797; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 794; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
     if (__pyx_t_6) {
 
-      /* "numpy.pxd":798
+      /* "numpy.pxd":795
  * 
  *         if (end - f) - (new_offset - offset[0]) < 15:
  *             raise RuntimeError(u"Format string allocated too short, see comment in numpy.pxd")             # <<<<<<<<<<<<<<
  * 
  *         if ((child.byteorder == '>' and little_endian) or
  */
-      __pyx_t_5 = PyObject_Call(__pyx_builtin_RuntimeError, ((PyObject *)__pyx_k_tuple_13), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 798; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyObject_Call(__pyx_builtin_RuntimeError, ((PyObject *)__pyx_k_tuple_13), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 795; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
       __Pyx_Raise(__pyx_t_5, 0, 0, 0);
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      {__pyx_filename = __pyx_f[1]; __pyx_lineno = 798; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      {__pyx_filename = __pyx_f[1]; __pyx_lineno = 795; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       goto __pyx_L5;
     }
     __pyx_L5:;
 
-    /* "numpy.pxd":800
+    /* "numpy.pxd":797
  *             raise RuntimeError(u"Format string allocated too short, see comment in numpy.pxd")
  * 
  *         if ((child.byteorder == '>' and little_endian) or             # <<<<<<<<<<<<<<
@@ -5322,7 +5109,7 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
     }
     if (!__pyx_t_7) {
 
-      /* "numpy.pxd":801
+      /* "numpy.pxd":798
  * 
  *         if ((child.byteorder == '>' and little_endian) or
  *             (child.byteorder == '<' and not little_endian)):             # <<<<<<<<<<<<<<
@@ -5342,23 +5129,23 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
     }
     if (__pyx_t_6) {
 
-      /* "numpy.pxd":802
+      /* "numpy.pxd":799
  *         if ((child.byteorder == '>' and little_endian) or
  *             (child.byteorder == '<' and not little_endian)):
  *             raise ValueError(u"Non-native byte order not supported")             # <<<<<<<<<<<<<<
  *             # One could encode it in the format string and have Cython
  *             # complain instead, BUT: < and > in format strings also imply
  */
-      __pyx_t_5 = PyObject_Call(__pyx_builtin_ValueError, ((PyObject *)__pyx_k_tuple_14), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 802; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyObject_Call(__pyx_builtin_ValueError, ((PyObject *)__pyx_k_tuple_14), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 799; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
       __Pyx_Raise(__pyx_t_5, 0, 0, 0);
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      {__pyx_filename = __pyx_f[1]; __pyx_lineno = 802; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      {__pyx_filename = __pyx_f[1]; __pyx_lineno = 799; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       goto __pyx_L6;
     }
     __pyx_L6:;
 
-    /* "numpy.pxd":812
+    /* "numpy.pxd":809
  * 
  *         # Output padding bytes
  *         while offset[0] < new_offset:             # <<<<<<<<<<<<<<
@@ -5366,16 +5153,16 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
  *             f += 1
  */
     while (1) {
-      __pyx_t_5 = PyInt_FromLong((__pyx_v_offset[0])); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 812; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyInt_FromLong((__pyx_v_offset[0])); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 809; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
-      __pyx_t_3 = PyObject_RichCompare(__pyx_t_5, __pyx_v_new_offset, Py_LT); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 812; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyObject_RichCompare(__pyx_t_5, __pyx_v_new_offset, Py_LT); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 809; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 812; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 809; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
       if (!__pyx_t_6) break;
 
-      /* "numpy.pxd":813
+      /* "numpy.pxd":810
  *         # Output padding bytes
  *         while offset[0] < new_offset:
  *             f[0] = 120 # "x"; pad byte             # <<<<<<<<<<<<<<
@@ -5384,7 +5171,7 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
  */
       (__pyx_v_f[0]) = 120;
 
-      /* "numpy.pxd":814
+      /* "numpy.pxd":811
  *         while offset[0] < new_offset:
  *             f[0] = 120 # "x"; pad byte
  *             f += 1             # <<<<<<<<<<<<<<
@@ -5393,7 +5180,7 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
  */
       __pyx_v_f = (__pyx_v_f + 1);
 
-      /* "numpy.pxd":815
+      /* "numpy.pxd":812
  *             f[0] = 120 # "x"; pad byte
  *             f += 1
  *             offset[0] += 1             # <<<<<<<<<<<<<<
@@ -5404,7 +5191,7 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
       (__pyx_v_offset[__pyx_t_10]) = ((__pyx_v_offset[__pyx_t_10]) + 1);
     }
 
-    /* "numpy.pxd":817
+    /* "numpy.pxd":814
  *             offset[0] += 1
  * 
  *         offset[0] += child.itemsize             # <<<<<<<<<<<<<<
@@ -5414,7 +5201,7 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
     __pyx_t_10 = 0;
     (__pyx_v_offset[__pyx_t_10]) = ((__pyx_v_offset[__pyx_t_10]) + __pyx_v_child->elsize);
 
-    /* "numpy.pxd":819
+    /* "numpy.pxd":816
  *         offset[0] += child.itemsize
  * 
  *         if not PyDataType_HASFIELDS(child):             # <<<<<<<<<<<<<<
@@ -5424,20 +5211,20 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
     __pyx_t_6 = (!PyDataType_HASFIELDS(__pyx_v_child));
     if (__pyx_t_6) {
 
-      /* "numpy.pxd":820
+      /* "numpy.pxd":817
  * 
  *         if not PyDataType_HASFIELDS(child):
  *             t = child.type_num             # <<<<<<<<<<<<<<
  *             if end - f < 5:
  *                 raise RuntimeError(u"Format string allocated too short.")
  */
-      __pyx_t_3 = PyInt_FromLong(__pyx_v_child->type_num); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 820; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyInt_FromLong(__pyx_v_child->type_num); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 817; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_XDECREF(__pyx_v_t);
       __pyx_v_t = __pyx_t_3;
       __pyx_t_3 = 0;
 
-      /* "numpy.pxd":821
+      /* "numpy.pxd":818
  *         if not PyDataType_HASFIELDS(child):
  *             t = child.type_num
  *             if end - f < 5:             # <<<<<<<<<<<<<<
@@ -5447,282 +5234,282 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
       __pyx_t_6 = ((__pyx_v_end - __pyx_v_f) < 5);
       if (__pyx_t_6) {
 
-        /* "numpy.pxd":822
+        /* "numpy.pxd":819
  *             t = child.type_num
  *             if end - f < 5:
  *                 raise RuntimeError(u"Format string allocated too short.")             # <<<<<<<<<<<<<<
  * 
  *             # Until ticket #99 is fixed, use integers to avoid warnings
  */
-        __pyx_t_3 = PyObject_Call(__pyx_builtin_RuntimeError, ((PyObject *)__pyx_k_tuple_16), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 822; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_3 = PyObject_Call(__pyx_builtin_RuntimeError, ((PyObject *)__pyx_k_tuple_16), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 819; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_3);
         __Pyx_Raise(__pyx_t_3, 0, 0, 0);
         __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-        {__pyx_filename = __pyx_f[1]; __pyx_lineno = 822; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        {__pyx_filename = __pyx_f[1]; __pyx_lineno = 819; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         goto __pyx_L10;
       }
       __pyx_L10:;
 
-      /* "numpy.pxd":825
+      /* "numpy.pxd":822
  * 
  *             # Until ticket #99 is fixed, use integers to avoid warnings
  *             if   t == NPY_BYTE:        f[0] =  98 #"b"             # <<<<<<<<<<<<<<
  *             elif t == NPY_UBYTE:       f[0] =  66 #"B"
  *             elif t == NPY_SHORT:       f[0] = 104 #"h"
  */
-      __pyx_t_3 = PyInt_FromLong(NPY_BYTE); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 825; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyInt_FromLong(NPY_BYTE); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 822; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 825; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 822; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 825; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 822; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 98;
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":826
+      /* "numpy.pxd":823
  *             # Until ticket #99 is fixed, use integers to avoid warnings
  *             if   t == NPY_BYTE:        f[0] =  98 #"b"
  *             elif t == NPY_UBYTE:       f[0] =  66 #"B"             # <<<<<<<<<<<<<<
  *             elif t == NPY_SHORT:       f[0] = 104 #"h"
  *             elif t == NPY_USHORT:      f[0] =  72 #"H"
  */
-      __pyx_t_5 = PyInt_FromLong(NPY_UBYTE); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 826; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyInt_FromLong(NPY_UBYTE); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 823; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
-      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 826; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 823; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 826; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 823; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 66;
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":827
+      /* "numpy.pxd":824
  *             if   t == NPY_BYTE:        f[0] =  98 #"b"
  *             elif t == NPY_UBYTE:       f[0] =  66 #"B"
  *             elif t == NPY_SHORT:       f[0] = 104 #"h"             # <<<<<<<<<<<<<<
  *             elif t == NPY_USHORT:      f[0] =  72 #"H"
  *             elif t == NPY_INT:         f[0] = 105 #"i"
  */
-      __pyx_t_3 = PyInt_FromLong(NPY_SHORT); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 827; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyInt_FromLong(NPY_SHORT); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 824; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 827; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 824; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 827; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 824; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 104;
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":828
+      /* "numpy.pxd":825
  *             elif t == NPY_UBYTE:       f[0] =  66 #"B"
  *             elif t == NPY_SHORT:       f[0] = 104 #"h"
  *             elif t == NPY_USHORT:      f[0] =  72 #"H"             # <<<<<<<<<<<<<<
  *             elif t == NPY_INT:         f[0] = 105 #"i"
  *             elif t == NPY_UINT:        f[0] =  73 #"I"
  */
-      __pyx_t_5 = PyInt_FromLong(NPY_USHORT); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 828; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyInt_FromLong(NPY_USHORT); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 825; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
-      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 828; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 825; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 828; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 825; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 72;
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":829
+      /* "numpy.pxd":826
  *             elif t == NPY_SHORT:       f[0] = 104 #"h"
  *             elif t == NPY_USHORT:      f[0] =  72 #"H"
  *             elif t == NPY_INT:         f[0] = 105 #"i"             # <<<<<<<<<<<<<<
  *             elif t == NPY_UINT:        f[0] =  73 #"I"
  *             elif t == NPY_LONG:        f[0] = 108 #"l"
  */
-      __pyx_t_3 = PyInt_FromLong(NPY_INT); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 829; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyInt_FromLong(NPY_INT); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 826; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 829; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 826; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 829; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 826; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 105;
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":830
+      /* "numpy.pxd":827
  *             elif t == NPY_USHORT:      f[0] =  72 #"H"
  *             elif t == NPY_INT:         f[0] = 105 #"i"
  *             elif t == NPY_UINT:        f[0] =  73 #"I"             # <<<<<<<<<<<<<<
  *             elif t == NPY_LONG:        f[0] = 108 #"l"
  *             elif t == NPY_ULONG:       f[0] = 76  #"L"
  */
-      __pyx_t_5 = PyInt_FromLong(NPY_UINT); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 830; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyInt_FromLong(NPY_UINT); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 827; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
-      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 830; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 827; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 830; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 827; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 73;
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":831
+      /* "numpy.pxd":828
  *             elif t == NPY_INT:         f[0] = 105 #"i"
  *             elif t == NPY_UINT:        f[0] =  73 #"I"
  *             elif t == NPY_LONG:        f[0] = 108 #"l"             # <<<<<<<<<<<<<<
  *             elif t == NPY_ULONG:       f[0] = 76  #"L"
  *             elif t == NPY_LONGLONG:    f[0] = 113 #"q"
  */
-      __pyx_t_3 = PyInt_FromLong(NPY_LONG); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 831; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyInt_FromLong(NPY_LONG); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 828; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 831; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 828; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 831; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 828; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 108;
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":832
+      /* "numpy.pxd":829
  *             elif t == NPY_UINT:        f[0] =  73 #"I"
  *             elif t == NPY_LONG:        f[0] = 108 #"l"
  *             elif t == NPY_ULONG:       f[0] = 76  #"L"             # <<<<<<<<<<<<<<
  *             elif t == NPY_LONGLONG:    f[0] = 113 #"q"
  *             elif t == NPY_ULONGLONG:   f[0] = 81  #"Q"
  */
-      __pyx_t_5 = PyInt_FromLong(NPY_ULONG); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 832; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyInt_FromLong(NPY_ULONG); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 829; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
-      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 832; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 829; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 832; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 829; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 76;
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":833
+      /* "numpy.pxd":830
  *             elif t == NPY_LONG:        f[0] = 108 #"l"
  *             elif t == NPY_ULONG:       f[0] = 76  #"L"
  *             elif t == NPY_LONGLONG:    f[0] = 113 #"q"             # <<<<<<<<<<<<<<
  *             elif t == NPY_ULONGLONG:   f[0] = 81  #"Q"
  *             elif t == NPY_FLOAT:       f[0] = 102 #"f"
  */
-      __pyx_t_3 = PyInt_FromLong(NPY_LONGLONG); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 833; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyInt_FromLong(NPY_LONGLONG); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 830; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 833; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 830; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 833; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 830; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 113;
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":834
+      /* "numpy.pxd":831
  *             elif t == NPY_ULONG:       f[0] = 76  #"L"
  *             elif t == NPY_LONGLONG:    f[0] = 113 #"q"
  *             elif t == NPY_ULONGLONG:   f[0] = 81  #"Q"             # <<<<<<<<<<<<<<
  *             elif t == NPY_FLOAT:       f[0] = 102 #"f"
  *             elif t == NPY_DOUBLE:      f[0] = 100 #"d"
  */
-      __pyx_t_5 = PyInt_FromLong(NPY_ULONGLONG); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 834; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyInt_FromLong(NPY_ULONGLONG); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 831; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
-      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 834; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 831; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 834; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 831; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 81;
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":835
+      /* "numpy.pxd":832
  *             elif t == NPY_LONGLONG:    f[0] = 113 #"q"
  *             elif t == NPY_ULONGLONG:   f[0] = 81  #"Q"
  *             elif t == NPY_FLOAT:       f[0] = 102 #"f"             # <<<<<<<<<<<<<<
  *             elif t == NPY_DOUBLE:      f[0] = 100 #"d"
  *             elif t == NPY_LONGDOUBLE:  f[0] = 103 #"g"
  */
-      __pyx_t_3 = PyInt_FromLong(NPY_FLOAT); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 835; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyInt_FromLong(NPY_FLOAT); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 832; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 835; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 832; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 835; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 832; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 102;
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":836
+      /* "numpy.pxd":833
  *             elif t == NPY_ULONGLONG:   f[0] = 81  #"Q"
  *             elif t == NPY_FLOAT:       f[0] = 102 #"f"
  *             elif t == NPY_DOUBLE:      f[0] = 100 #"d"             # <<<<<<<<<<<<<<
  *             elif t == NPY_LONGDOUBLE:  f[0] = 103 #"g"
  *             elif t == NPY_CFLOAT:      f[0] = 90; f[1] = 102; f += 1 # Zf
  */
-      __pyx_t_5 = PyInt_FromLong(NPY_DOUBLE); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 836; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyInt_FromLong(NPY_DOUBLE); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 833; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
-      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 836; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 833; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 836; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 833; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 100;
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":837
+      /* "numpy.pxd":834
  *             elif t == NPY_FLOAT:       f[0] = 102 #"f"
  *             elif t == NPY_DOUBLE:      f[0] = 100 #"d"
  *             elif t == NPY_LONGDOUBLE:  f[0] = 103 #"g"             # <<<<<<<<<<<<<<
  *             elif t == NPY_CFLOAT:      f[0] = 90; f[1] = 102; f += 1 # Zf
  *             elif t == NPY_CDOUBLE:     f[0] = 90; f[1] = 100; f += 1 # Zd
  */
-      __pyx_t_3 = PyInt_FromLong(NPY_LONGDOUBLE); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 837; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyInt_FromLong(NPY_LONGDOUBLE); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 834; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 837; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 834; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 837; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 834; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 103;
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":838
+      /* "numpy.pxd":835
  *             elif t == NPY_DOUBLE:      f[0] = 100 #"d"
  *             elif t == NPY_LONGDOUBLE:  f[0] = 103 #"g"
  *             elif t == NPY_CFLOAT:      f[0] = 90; f[1] = 102; f += 1 # Zf             # <<<<<<<<<<<<<<
  *             elif t == NPY_CDOUBLE:     f[0] = 90; f[1] = 100; f += 1 # Zd
  *             elif t == NPY_CLONGDOUBLE: f[0] = 90; f[1] = 103; f += 1 # Zg
  */
-      __pyx_t_5 = PyInt_FromLong(NPY_CFLOAT); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 838; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyInt_FromLong(NPY_CFLOAT); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 835; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
-      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 838; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 835; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 838; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 835; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 90;
@@ -5731,19 +5518,19 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":839
+      /* "numpy.pxd":836
  *             elif t == NPY_LONGDOUBLE:  f[0] = 103 #"g"
  *             elif t == NPY_CFLOAT:      f[0] = 90; f[1] = 102; f += 1 # Zf
  *             elif t == NPY_CDOUBLE:     f[0] = 90; f[1] = 100; f += 1 # Zd             # <<<<<<<<<<<<<<
  *             elif t == NPY_CLONGDOUBLE: f[0] = 90; f[1] = 103; f += 1 # Zg
  *             elif t == NPY_OBJECT:      f[0] = 79 #"O"
  */
-      __pyx_t_3 = PyInt_FromLong(NPY_CDOUBLE); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 839; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyInt_FromLong(NPY_CDOUBLE); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 836; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 839; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 836; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 839; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 836; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 90;
@@ -5752,19 +5539,19 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":840
+      /* "numpy.pxd":837
  *             elif t == NPY_CFLOAT:      f[0] = 90; f[1] = 102; f += 1 # Zf
  *             elif t == NPY_CDOUBLE:     f[0] = 90; f[1] = 100; f += 1 # Zd
  *             elif t == NPY_CLONGDOUBLE: f[0] = 90; f[1] = 103; f += 1 # Zg             # <<<<<<<<<<<<<<
  *             elif t == NPY_OBJECT:      f[0] = 79 #"O"
  *             else:
  */
-      __pyx_t_5 = PyInt_FromLong(NPY_CLONGDOUBLE); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 840; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyInt_FromLong(NPY_CLONGDOUBLE); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 837; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
-      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 840; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 837; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 840; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 837; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 90;
@@ -5773,19 +5560,19 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":841
+      /* "numpy.pxd":838
  *             elif t == NPY_CDOUBLE:     f[0] = 90; f[1] = 100; f += 1 # Zd
  *             elif t == NPY_CLONGDOUBLE: f[0] = 90; f[1] = 103; f += 1 # Zg
  *             elif t == NPY_OBJECT:      f[0] = 79 #"O"             # <<<<<<<<<<<<<<
  *             else:
  *                 raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t)
  */
-      __pyx_t_3 = PyInt_FromLong(NPY_OBJECT); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 841; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyInt_FromLong(NPY_OBJECT); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 838; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 841; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 838; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 841; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 838; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 79;
@@ -5793,30 +5580,30 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
       }
       /*else*/ {
 
-        /* "numpy.pxd":843
+        /* "numpy.pxd":840
  *             elif t == NPY_OBJECT:      f[0] = 79 #"O"
  *             else:
  *                 raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t)             # <<<<<<<<<<<<<<
  *             f += 1
  *         else:
  */
-        __pyx_t_5 = PyNumber_Remainder(((PyObject *)__pyx_kp_u_11), __pyx_v_t); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 843; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_5 = PyNumber_Remainder(((PyObject *)__pyx_kp_u_11), __pyx_v_t); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 840; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(((PyObject *)__pyx_t_5));
-        __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 843; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-        __Pyx_GOTREF(__pyx_t_3);
+        __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 840; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __Pyx_GOTREF(((PyObject *)__pyx_t_3));
         PyTuple_SET_ITEM(__pyx_t_3, 0, ((PyObject *)__pyx_t_5));
         __Pyx_GIVEREF(((PyObject *)__pyx_t_5));
         __pyx_t_5 = 0;
-        __pyx_t_5 = PyObject_Call(__pyx_builtin_ValueError, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 843; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_5 = PyObject_Call(__pyx_builtin_ValueError, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 840; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_5);
         __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
         __Pyx_Raise(__pyx_t_5, 0, 0, 0);
         __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-        {__pyx_filename = __pyx_f[1]; __pyx_lineno = 843; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        {__pyx_filename = __pyx_f[1]; __pyx_lineno = 840; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       }
       __pyx_L11:;
 
-      /* "numpy.pxd":844
+      /* "numpy.pxd":841
  *             else:
  *                 raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t)
  *             f += 1             # <<<<<<<<<<<<<<
@@ -5828,21 +5615,21 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
     }
     /*else*/ {
 
-      /* "numpy.pxd":848
+      /* "numpy.pxd":845
  *             # Cython ignores struct boundary information ("T{...}"),
  *             # so don't output it
  *             f = _util_dtypestring(child, f, end, offset)             # <<<<<<<<<<<<<<
  *     return f
  * 
  */
-      __pyx_t_11 = __pyx_f_5numpy__util_dtypestring(__pyx_v_child, __pyx_v_f, __pyx_v_end, __pyx_v_offset); if (unlikely(__pyx_t_11 == NULL)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 848; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_11 = __pyx_f_5numpy__util_dtypestring(__pyx_v_child, __pyx_v_f, __pyx_v_end, __pyx_v_offset); if (unlikely(__pyx_t_11 == NULL)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 845; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __pyx_v_f = __pyx_t_11;
     }
     __pyx_L9:;
   }
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "numpy.pxd":849
+  /* "numpy.pxd":846
  *             # so don't output it
  *             f = _util_dtypestring(child, f, end, offset)
  *     return f             # <<<<<<<<<<<<<<
@@ -5871,7 +5658,7 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
   return __pyx_r;
 }
 
-/* "numpy.pxd":964
+/* "numpy.pxd":961
  * 
  * 
  * cdef inline void set_array_base(ndarray arr, object base):             # <<<<<<<<<<<<<<
@@ -5883,9 +5670,9 @@ static CYTHON_INLINE void __pyx_f_5numpy_set_array_base(PyArrayObject *__pyx_v_a
   PyObject *__pyx_v_baseptr;
   __Pyx_RefNannyDeclarations
   int __pyx_t_1;
-  __Pyx_RefNannySetupContext("set_array_base", 0);
+  __Pyx_RefNannySetupContext("set_array_base");
 
-  /* "numpy.pxd":966
+  /* "numpy.pxd":963
  * cdef inline void set_array_base(ndarray arr, object base):
  *      cdef PyObject* baseptr
  *      if base is None:             # <<<<<<<<<<<<<<
@@ -5895,7 +5682,7 @@ static CYTHON_INLINE void __pyx_f_5numpy_set_array_base(PyArrayObject *__pyx_v_a
   __pyx_t_1 = (__pyx_v_base == Py_None);
   if (__pyx_t_1) {
 
-    /* "numpy.pxd":967
+    /* "numpy.pxd":964
  *      cdef PyObject* baseptr
  *      if base is None:
  *          baseptr = NULL             # <<<<<<<<<<<<<<
@@ -5907,7 +5694,7 @@ static CYTHON_INLINE void __pyx_f_5numpy_set_array_base(PyArrayObject *__pyx_v_a
   }
   /*else*/ {
 
-    /* "numpy.pxd":969
+    /* "numpy.pxd":966
  *          baseptr = NULL
  *      else:
  *          Py_INCREF(base) # important to do this before decref below!             # <<<<<<<<<<<<<<
@@ -5916,7 +5703,7 @@ static CYTHON_INLINE void __pyx_f_5numpy_set_array_base(PyArrayObject *__pyx_v_a
  */
     Py_INCREF(__pyx_v_base);
 
-    /* "numpy.pxd":970
+    /* "numpy.pxd":967
  *      else:
  *          Py_INCREF(base) # important to do this before decref below!
  *          baseptr = <PyObject*>base             # <<<<<<<<<<<<<<
@@ -5927,7 +5714,7 @@ static CYTHON_INLINE void __pyx_f_5numpy_set_array_base(PyArrayObject *__pyx_v_a
   }
   __pyx_L3:;
 
-  /* "numpy.pxd":971
+  /* "numpy.pxd":968
  *          Py_INCREF(base) # important to do this before decref below!
  *          baseptr = <PyObject*>base
  *      Py_XDECREF(arr.base)             # <<<<<<<<<<<<<<
@@ -5936,7 +5723,7 @@ static CYTHON_INLINE void __pyx_f_5numpy_set_array_base(PyArrayObject *__pyx_v_a
  */
   Py_XDECREF(__pyx_v_arr->base);
 
-  /* "numpy.pxd":972
+  /* "numpy.pxd":969
  *          baseptr = <PyObject*>base
  *      Py_XDECREF(arr.base)
  *      arr.base = baseptr             # <<<<<<<<<<<<<<
@@ -5948,7 +5735,7 @@ static CYTHON_INLINE void __pyx_f_5numpy_set_array_base(PyArrayObject *__pyx_v_a
   __Pyx_RefNannyFinishContext();
 }
 
-/* "numpy.pxd":974
+/* "numpy.pxd":971
  *      arr.base = baseptr
  * 
  * cdef inline object get_array_base(ndarray arr):             # <<<<<<<<<<<<<<
@@ -5960,9 +5747,9 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_get_array_base(PyArrayObject *__py
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   int __pyx_t_1;
-  __Pyx_RefNannySetupContext("get_array_base", 0);
+  __Pyx_RefNannySetupContext("get_array_base");
 
-  /* "numpy.pxd":975
+  /* "numpy.pxd":972
  * 
  * cdef inline object get_array_base(ndarray arr):
  *     if arr.base is NULL:             # <<<<<<<<<<<<<<
@@ -5972,7 +5759,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_get_array_base(PyArrayObject *__py
   __pyx_t_1 = (__pyx_v_arr->base == NULL);
   if (__pyx_t_1) {
 
-    /* "numpy.pxd":976
+    /* "numpy.pxd":973
  * cdef inline object get_array_base(ndarray arr):
  *     if arr.base is NULL:
  *         return None             # <<<<<<<<<<<<<<
@@ -5987,7 +5774,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_get_array_base(PyArrayObject *__py
   }
   /*else*/ {
 
-    /* "numpy.pxd":978
+    /* "numpy.pxd":975
  *         return None
  *     else:
  *         return <object>arr.base             # <<<<<<<<<<<<<<
@@ -6029,11 +5816,10 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = {
   {&__pyx_kp_u_11, __pyx_k_11, sizeof(__pyx_k_11), 0, 1, 0, 0},
   {&__pyx_kp_u_12, __pyx_k_12, sizeof(__pyx_k_12), 0, 1, 0, 0},
   {&__pyx_kp_u_15, __pyx_k_15, sizeof(__pyx_k_15), 0, 1, 0, 0},
+  {&__pyx_n_s_17, __pyx_k_17, sizeof(__pyx_k_17), 0, 0, 1, 1},
+  {&__pyx_n_s_18, __pyx_k_18, sizeof(__pyx_k_18), 0, 0, 1, 1},
   {&__pyx_n_s_19, __pyx_k_19, sizeof(__pyx_k_19), 0, 0, 1, 1},
-  {&__pyx_kp_s_20, __pyx_k_20, sizeof(__pyx_k_20), 0, 0, 1, 0},
-  {&__pyx_n_s_21, __pyx_k_21, sizeof(__pyx_k_21), 0, 0, 1, 1},
-  {&__pyx_n_s_24, __pyx_k_24, sizeof(__pyx_k_24), 0, 0, 1, 1},
-  {&__pyx_n_s_27, __pyx_k_27, sizeof(__pyx_k_27), 0, 0, 1, 1},
+  {&__pyx_n_s_20, __pyx_k_20, sizeof(__pyx_k_20), 0, 0, 1, 1},
   {&__pyx_kp_u_5, __pyx_k_5, sizeof(__pyx_k_5), 0, 1, 0, 0},
   {&__pyx_kp_u_7, __pyx_k_7, sizeof(__pyx_k_7), 0, 1, 0, 0},
   {&__pyx_kp_u_9, __pyx_k_9, sizeof(__pyx_k_9), 0, 1, 0, 0},
@@ -6042,50 +5828,20 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = {
   {&__pyx_n_s__ValueError, __pyx_k__ValueError, sizeof(__pyx_k__ValueError), 0, 0, 1, 1},
   {&__pyx_n_s____main__, __pyx_k____main__, sizeof(__pyx_k____main__), 0, 0, 1, 1},
   {&__pyx_n_s____test__, __pyx_k____test__, sizeof(__pyx_k____test__), 0, 0, 1, 1},
-  {&__pyx_n_s__bot, __pyx_k__bot, sizeof(__pyx_k__bot), 0, 0, 1, 1},
-  {&__pyx_n_s__conv, __pyx_k__conv, sizeof(__pyx_k__conv), 0, 0, 1, 1},
   {&__pyx_n_s__dtype, __pyx_k__dtype, sizeof(__pyx_k__dtype), 0, 0, 1, 1},
   {&__pyx_n_s__empty, __pyx_k__empty, sizeof(__pyx_k__empty), 0, 0, 1, 1},
   {&__pyx_n_s__f, __pyx_k__f, sizeof(__pyx_k__f), 0, 0, 1, 1},
-  {&__pyx_n_s__fixed, __pyx_k__fixed, sizeof(__pyx_k__fixed), 0, 0, 1, 1},
   {&__pyx_n_s__float, __pyx_k__float, sizeof(__pyx_k__float), 0, 0, 1, 1},
   {&__pyx_n_s__g, __pyx_k__g, sizeof(__pyx_k__g), 0, 0, 1, 1},
-  {&__pyx_n_s__i, __pyx_k__i, sizeof(__pyx_k__i), 0, 0, 1, 1},
-  {&__pyx_n_s__ii, __pyx_k__ii, sizeof(__pyx_k__ii), 0, 0, 1, 1},
-  {&__pyx_n_s__iii, __pyx_k__iii, sizeof(__pyx_k__iii), 0, 0, 1, 1},
-  {&__pyx_n_s__iimax, __pyx_k__iimax, sizeof(__pyx_k__iimax), 0, 0, 1, 1},
-  {&__pyx_n_s__iimin, __pyx_k__iimin, sizeof(__pyx_k__iimin), 0, 0, 1, 1},
-  {&__pyx_n_s__j, __pyx_k__j, sizeof(__pyx_k__j), 0, 0, 1, 1},
-  {&__pyx_n_s__jj, __pyx_k__jj, sizeof(__pyx_k__jj), 0, 0, 1, 1},
-  {&__pyx_n_s__jjj, __pyx_k__jjj, sizeof(__pyx_k__jjj), 0, 0, 1, 1},
-  {&__pyx_n_s__jjmax, __pyx_k__jjmax, sizeof(__pyx_k__jjmax), 0, 0, 1, 1},
-  {&__pyx_n_s__jjmin, __pyx_k__jjmin, sizeof(__pyx_k__jjmin), 0, 0, 1, 1},
-  {&__pyx_n_s__k, __pyx_k__k, sizeof(__pyx_k__k), 0, 0, 1, 1},
-  {&__pyx_n_s__ker, __pyx_k__ker, sizeof(__pyx_k__ker), 0, 0, 1, 1},
-  {&__pyx_n_s__kk, __pyx_k__kk, sizeof(__pyx_k__kk), 0, 0, 1, 1},
-  {&__pyx_n_s__kkk, __pyx_k__kkk, sizeof(__pyx_k__kkk), 0, 0, 1, 1},
-  {&__pyx_n_s__kkmax, __pyx_k__kkmax, sizeof(__pyx_k__kkmax), 0, 0, 1, 1},
-  {&__pyx_n_s__kkmin, __pyx_k__kkmin, sizeof(__pyx_k__kkmin), 0, 0, 1, 1},
-  {&__pyx_n_s__nkx, __pyx_k__nkx, sizeof(__pyx_k__nkx), 0, 0, 1, 1},
-  {&__pyx_n_s__nky, __pyx_k__nky, sizeof(__pyx_k__nky), 0, 0, 1, 1},
-  {&__pyx_n_s__nkz, __pyx_k__nkz, sizeof(__pyx_k__nkz), 0, 0, 1, 1},
   {&__pyx_n_s__np, __pyx_k__np, sizeof(__pyx_k__np), 0, 0, 1, 1},
   {&__pyx_n_s__numpy, __pyx_k__numpy, sizeof(__pyx_k__numpy), 0, 0, 1, 1},
-  {&__pyx_n_s__nx, __pyx_k__nx, sizeof(__pyx_k__nx), 0, 0, 1, 1},
-  {&__pyx_n_s__ny, __pyx_k__ny, sizeof(__pyx_k__ny), 0, 0, 1, 1},
-  {&__pyx_n_s__nz, __pyx_k__nz, sizeof(__pyx_k__nz), 0, 0, 1, 1},
   {&__pyx_n_s__range, __pyx_k__range, sizeof(__pyx_k__range), 0, 0, 1, 1},
-  {&__pyx_n_s__top, __pyx_k__top, sizeof(__pyx_k__top), 0, 0, 1, 1},
-  {&__pyx_n_s__val, __pyx_k__val, sizeof(__pyx_k__val), 0, 0, 1, 1},
-  {&__pyx_n_s__wkx, __pyx_k__wkx, sizeof(__pyx_k__wkx), 0, 0, 1, 1},
-  {&__pyx_n_s__wky, __pyx_k__wky, sizeof(__pyx_k__wky), 0, 0, 1, 1},
-  {&__pyx_n_s__wkz, __pyx_k__wkz, sizeof(__pyx_k__wkz), 0, 0, 1, 1},
   {0, 0, 0, 0, 0, 0, 0}
 };
 static int __Pyx_InitCachedBuiltins(void) {
   __pyx_builtin_ValueError = __Pyx_GetName(__pyx_b, __pyx_n_s__ValueError); if (!__pyx_builtin_ValueError) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 22; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_builtin_range = __Pyx_GetName(__pyx_b, __pyx_n_s__range); if (!__pyx_builtin_range) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 40; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_builtin_RuntimeError = __Pyx_GetName(__pyx_b, __pyx_n_s__RuntimeError); if (!__pyx_builtin_RuntimeError) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 798; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_builtin_RuntimeError = __Pyx_GetName(__pyx_b, __pyx_n_s__RuntimeError); if (!__pyx_builtin_RuntimeError) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 795; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   return 0;
   __pyx_L1_error:;
   return -1;
@@ -6093,7 +5849,7 @@ static int __Pyx_InitCachedBuiltins(void) {
 
 static int __Pyx_InitCachedConstants(void) {
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__Pyx_InitCachedConstants", 0);
+  __Pyx_RefNannySetupContext("__Pyx_InitCachedConstants");
 
   /* "astropy/nddata/convolution/boundary_extend.pyx":22
  * 
@@ -6103,7 +5859,7 @@ static int __Pyx_InitCachedConstants(void) {
  *     assert f.dtype == DTYPE and g.dtype == DTYPE
  */
   __pyx_k_tuple_2 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 22; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_2);
+  __Pyx_GOTREF(((PyObject *)__pyx_k_tuple_2));
   __Pyx_INCREF(((PyObject *)__pyx_kp_s_1));
   PyTuple_SET_ITEM(__pyx_k_tuple_2, 0, ((PyObject *)__pyx_kp_s_1));
   __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_1));
@@ -6117,7 +5873,7 @@ static int __Pyx_InitCachedConstants(void) {
  *     assert f.dtype == DTYPE and g.dtype == DTYPE
  */
   __pyx_k_tuple_3 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 90; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_3);
+  __Pyx_GOTREF(((PyObject *)__pyx_k_tuple_3));
   __Pyx_INCREF(((PyObject *)__pyx_kp_s_1));
   PyTuple_SET_ITEM(__pyx_k_tuple_3, 0, ((PyObject *)__pyx_kp_s_1));
   __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_1));
@@ -6131,347 +5887,95 @@ static int __Pyx_InitCachedConstants(void) {
  *     assert f.dtype == DTYPE and g.dtype == DTYPE
  */
   __pyx_k_tuple_4 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 173; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_4);
+  __Pyx_GOTREF(((PyObject *)__pyx_k_tuple_4));
   __Pyx_INCREF(((PyObject *)__pyx_kp_s_1));
   PyTuple_SET_ITEM(__pyx_k_tuple_4, 0, ((PyObject *)__pyx_kp_s_1));
   __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_1));
   __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_4));
 
-  /* "numpy.pxd":214
+  /* "numpy.pxd":211
  *             if ((flags & pybuf.PyBUF_C_CONTIGUOUS == pybuf.PyBUF_C_CONTIGUOUS)
  *                 and not PyArray_CHKFLAGS(self, NPY_C_CONTIGUOUS)):
  *                 raise ValueError(u"ndarray is not C contiguous")             # <<<<<<<<<<<<<<
  * 
  *             if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS)
  */
-  __pyx_k_tuple_6 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_6)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 214; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_6);
+  __pyx_k_tuple_6 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_6)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 211; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_k_tuple_6));
   __Pyx_INCREF(((PyObject *)__pyx_kp_u_5));
   PyTuple_SET_ITEM(__pyx_k_tuple_6, 0, ((PyObject *)__pyx_kp_u_5));
   __Pyx_GIVEREF(((PyObject *)__pyx_kp_u_5));
   __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_6));
 
-  /* "numpy.pxd":218
+  /* "numpy.pxd":215
  *             if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS)
  *                 and not PyArray_CHKFLAGS(self, NPY_F_CONTIGUOUS)):
  *                 raise ValueError(u"ndarray is not Fortran contiguous")             # <<<<<<<<<<<<<<
  * 
  *             info.buf = PyArray_DATA(self)
  */
-  __pyx_k_tuple_8 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_8)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 218; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_8);
+  __pyx_k_tuple_8 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_8)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 215; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_k_tuple_8));
   __Pyx_INCREF(((PyObject *)__pyx_kp_u_7));
   PyTuple_SET_ITEM(__pyx_k_tuple_8, 0, ((PyObject *)__pyx_kp_u_7));
   __Pyx_GIVEREF(((PyObject *)__pyx_kp_u_7));
   __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_8));
 
-  /* "numpy.pxd":256
+  /* "numpy.pxd":253
  *                 if ((descr.byteorder == '>' and little_endian) or
  *                     (descr.byteorder == '<' and not little_endian)):
  *                     raise ValueError(u"Non-native byte order not supported")             # <<<<<<<<<<<<<<
  *                 if   t == NPY_BYTE:        f = "b"
  *                 elif t == NPY_UBYTE:       f = "B"
  */
-  __pyx_k_tuple_10 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_10)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 256; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_10);
+  __pyx_k_tuple_10 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_10)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 253; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_k_tuple_10));
   __Pyx_INCREF(((PyObject *)__pyx_kp_u_9));
   PyTuple_SET_ITEM(__pyx_k_tuple_10, 0, ((PyObject *)__pyx_kp_u_9));
   __Pyx_GIVEREF(((PyObject *)__pyx_kp_u_9));
   __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_10));
 
-  /* "numpy.pxd":798
+  /* "numpy.pxd":795
  * 
  *         if (end - f) - (new_offset - offset[0]) < 15:
  *             raise RuntimeError(u"Format string allocated too short, see comment in numpy.pxd")             # <<<<<<<<<<<<<<
  * 
  *         if ((child.byteorder == '>' and little_endian) or
  */
-  __pyx_k_tuple_13 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_13)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 798; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_13);
+  __pyx_k_tuple_13 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_13)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 795; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_k_tuple_13));
   __Pyx_INCREF(((PyObject *)__pyx_kp_u_12));
   PyTuple_SET_ITEM(__pyx_k_tuple_13, 0, ((PyObject *)__pyx_kp_u_12));
   __Pyx_GIVEREF(((PyObject *)__pyx_kp_u_12));
   __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_13));
 
-  /* "numpy.pxd":802
+  /* "numpy.pxd":799
  *         if ((child.byteorder == '>' and little_endian) or
  *             (child.byteorder == '<' and not little_endian)):
  *             raise ValueError(u"Non-native byte order not supported")             # <<<<<<<<<<<<<<
  *             # One could encode it in the format string and have Cython
  *             # complain instead, BUT: < and > in format strings also imply
  */
-  __pyx_k_tuple_14 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_14)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 802; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_14);
+  __pyx_k_tuple_14 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_14)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 799; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_k_tuple_14));
   __Pyx_INCREF(((PyObject *)__pyx_kp_u_9));
   PyTuple_SET_ITEM(__pyx_k_tuple_14, 0, ((PyObject *)__pyx_kp_u_9));
   __Pyx_GIVEREF(((PyObject *)__pyx_kp_u_9));
   __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_14));
 
-  /* "numpy.pxd":822
+  /* "numpy.pxd":819
  *             t = child.type_num
  *             if end - f < 5:
  *                 raise RuntimeError(u"Format string allocated too short.")             # <<<<<<<<<<<<<<
  * 
  *             # Until ticket #99 is fixed, use integers to avoid warnings
  */
-  __pyx_k_tuple_16 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_16)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 822; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_16);
+  __pyx_k_tuple_16 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_16)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 819; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_k_tuple_16));
   __Pyx_INCREF(((PyObject *)__pyx_kp_u_15));
   PyTuple_SET_ITEM(__pyx_k_tuple_16, 0, ((PyObject *)__pyx_kp_u_15));
   __Pyx_GIVEREF(((PyObject *)__pyx_kp_u_15));
   __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_16));
-
-  /* "astropy/nddata/convolution/boundary_extend.pyx":18
- * 
- * @cython.boundscheck(False)  # turn off bounds-checking for entire function
- * def convolve1d_boundary_extend(np.ndarray[DTYPE_t, ndim=1] f,             # <<<<<<<<<<<<<<
- *                                np.ndarray[DTYPE_t, ndim=1] g):
- * 
- */
-  __pyx_k_tuple_17 = PyTuple_New(16); if (unlikely(!__pyx_k_tuple_17)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 18; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_17);
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__f));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 0, ((PyObject *)__pyx_n_s__f));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__f));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__g));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 1, ((PyObject *)__pyx_n_s__g));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__g));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__nx));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 2, ((PyObject *)__pyx_n_s__nx));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__nx));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__nkx));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 3, ((PyObject *)__pyx_n_s__nkx));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__nkx));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__wkx));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 4, ((PyObject *)__pyx_n_s__wkx));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__wkx));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__fixed));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 5, ((PyObject *)__pyx_n_s__fixed));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__fixed));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__conv));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 6, ((PyObject *)__pyx_n_s__conv));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__conv));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__i));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 7, ((PyObject *)__pyx_n_s__i));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__i));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__iii));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 8, ((PyObject *)__pyx_n_s__iii));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__iii));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__ii));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 9, ((PyObject *)__pyx_n_s__ii));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__ii));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__iimin));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 10, ((PyObject *)__pyx_n_s__iimin));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__iimin));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__iimax));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 11, ((PyObject *)__pyx_n_s__iimax));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__iimax));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__top));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 12, ((PyObject *)__pyx_n_s__top));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__top));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__bot));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 13, ((PyObject *)__pyx_n_s__bot));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__bot));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__ker));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 14, ((PyObject *)__pyx_n_s__ker));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__ker));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__val));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 15, ((PyObject *)__pyx_n_s__val));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__val));
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_17));
-  __pyx_k_codeobj_18 = (PyObject*)__Pyx_PyCode_New(2, 0, 16, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_k_tuple_17, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_20, __pyx_n_s_19, 18, __pyx_empty_bytes); if (unlikely(!__pyx_k_codeobj_18)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 18; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-
-  /* "astropy/nddata/convolution/boundary_extend.pyx":86
- * 
- * @cython.boundscheck(False)  # turn off bounds-checking for entire function
- * def convolve2d_boundary_extend(np.ndarray[DTYPE_t, ndim=2] f,             # <<<<<<<<<<<<<<
- *                                np.ndarray[DTYPE_t, ndim=2] g):
- * 
- */
-  __pyx_k_tuple_22 = PyTuple_New(24); if (unlikely(!__pyx_k_tuple_22)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 86; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_22);
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__f));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 0, ((PyObject *)__pyx_n_s__f));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__f));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__g));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 1, ((PyObject *)__pyx_n_s__g));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__g));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__nx));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 2, ((PyObject *)__pyx_n_s__nx));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__nx));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__ny));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 3, ((PyObject *)__pyx_n_s__ny));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__ny));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__nkx));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 4, ((PyObject *)__pyx_n_s__nkx));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__nkx));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__nky));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 5, ((PyObject *)__pyx_n_s__nky));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__nky));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__wkx));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 6, ((PyObject *)__pyx_n_s__wkx));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__wkx));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__wky));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 7, ((PyObject *)__pyx_n_s__wky));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__wky));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__fixed));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 8, ((PyObject *)__pyx_n_s__fixed));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__fixed));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__conv));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 9, ((PyObject *)__pyx_n_s__conv));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__conv));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__i));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 10, ((PyObject *)__pyx_n_s__i));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__i));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__j));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 11, ((PyObject *)__pyx_n_s__j));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__j));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__iii));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 12, ((PyObject *)__pyx_n_s__iii));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__iii));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__jjj));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 13, ((PyObject *)__pyx_n_s__jjj));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__jjj));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__ii));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 14, ((PyObject *)__pyx_n_s__ii));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__ii));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__jj));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 15, ((PyObject *)__pyx_n_s__jj));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__jj));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__iimin));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 16, ((PyObject *)__pyx_n_s__iimin));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__iimin));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__iimax));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 17, ((PyObject *)__pyx_n_s__iimax));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__iimax));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__jjmin));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 18, ((PyObject *)__pyx_n_s__jjmin));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__jjmin));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__jjmax));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 19, ((PyObject *)__pyx_n_s__jjmax));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__jjmax));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__top));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 20, ((PyObject *)__pyx_n_s__top));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__top));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__bot));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 21, ((PyObject *)__pyx_n_s__bot));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__bot));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__ker));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 22, ((PyObject *)__pyx_n_s__ker));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__ker));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__val));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 23, ((PyObject *)__pyx_n_s__val));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__val));
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_22));
-  __pyx_k_codeobj_23 = (PyObject*)__Pyx_PyCode_New(2, 0, 24, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_k_tuple_22, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_20, __pyx_n_s_24, 86, __pyx_empty_bytes); if (unlikely(!__pyx_k_codeobj_23)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 86; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-
-  /* "astropy/nddata/convolution/boundary_extend.pyx":169
- * 
- * @cython.boundscheck(False)  # turn off bounds-checking for entire function
- * def convolve3d_boundary_extend(np.ndarray[DTYPE_t, ndim=3] f,             # <<<<<<<<<<<<<<
- *                                np.ndarray[DTYPE_t, ndim=3] g):
- * 
- */
-  __pyx_k_tuple_25 = PyTuple_New(32); if (unlikely(!__pyx_k_tuple_25)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 169; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_25);
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__f));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 0, ((PyObject *)__pyx_n_s__f));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__f));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__g));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 1, ((PyObject *)__pyx_n_s__g));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__g));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__nx));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 2, ((PyObject *)__pyx_n_s__nx));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__nx));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__ny));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 3, ((PyObject *)__pyx_n_s__ny));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__ny));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__nz));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 4, ((PyObject *)__pyx_n_s__nz));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__nz));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__nkx));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 5, ((PyObject *)__pyx_n_s__nkx));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__nkx));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__nky));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 6, ((PyObject *)__pyx_n_s__nky));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__nky));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__nkz));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 7, ((PyObject *)__pyx_n_s__nkz));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__nkz));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__wkx));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 8, ((PyObject *)__pyx_n_s__wkx));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__wkx));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__wky));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 9, ((PyObject *)__pyx_n_s__wky));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__wky));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__wkz));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 10, ((PyObject *)__pyx_n_s__wkz));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__wkz));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__fixed));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 11, ((PyObject *)__pyx_n_s__fixed));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__fixed));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__conv));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 12, ((PyObject *)__pyx_n_s__conv));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__conv));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__i));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 13, ((PyObject *)__pyx_n_s__i));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__i));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__j));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 14, ((PyObject *)__pyx_n_s__j));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__j));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__k));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 15, ((PyObject *)__pyx_n_s__k));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__k));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__iii));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 16, ((PyObject *)__pyx_n_s__iii));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__iii));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__jjj));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 17, ((PyObject *)__pyx_n_s__jjj));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__jjj));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__kkk));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 18, ((PyObject *)__pyx_n_s__kkk));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__kkk));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__ii));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 19, ((PyObject *)__pyx_n_s__ii));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__ii));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__jj));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 20, ((PyObject *)__pyx_n_s__jj));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__jj));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__kk));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 21, ((PyObject *)__pyx_n_s__kk));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__kk));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__iimin));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 22, ((PyObject *)__pyx_n_s__iimin));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__iimin));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__iimax));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 23, ((PyObject *)__pyx_n_s__iimax));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__iimax));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__jjmin));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 24, ((PyObject *)__pyx_n_s__jjmin));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__jjmin));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__jjmax));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 25, ((PyObject *)__pyx_n_s__jjmax));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__jjmax));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__kkmin));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 26, ((PyObject *)__pyx_n_s__kkmin));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__kkmin));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__kkmax));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 27, ((PyObject *)__pyx_n_s__kkmax));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__kkmax));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__top));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 28, ((PyObject *)__pyx_n_s__top));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__top));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__bot));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 29, ((PyObject *)__pyx_n_s__bot));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__bot));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__ker));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 30, ((PyObject *)__pyx_n_s__ker));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__ker));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__val));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 31, ((PyObject *)__pyx_n_s__val));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__val));
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_25));
-  __pyx_k_codeobj_26 = (PyObject*)__Pyx_PyCode_New(2, 0, 32, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_k_tuple_25, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_20, __pyx_n_s_27, 169, __pyx_empty_bytes); if (unlikely(!__pyx_k_codeobj_26)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 169; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_RefNannyFinishContext();
   return 0;
   __pyx_L1_error:;
@@ -6507,18 +6011,12 @@ PyMODINIT_FUNC PyInit_boundary_extend(void)
           Py_FatalError("failed to import 'refnanny' module");
   }
   #endif
-  __Pyx_RefNannySetupContext("PyMODINIT_FUNC PyInit_boundary_extend(void)", 0);
+  __Pyx_RefNannySetupContext("PyMODINIT_FUNC PyInit_boundary_extend(void)");
   if ( __Pyx_check_binary_version() < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_empty_tuple = PyTuple_New(0); if (unlikely(!__pyx_empty_tuple)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_empty_bytes = PyBytes_FromStringAndSize("", 0); if (unlikely(!__pyx_empty_bytes)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  #ifdef __Pyx_CyFunction_USED
-  if (__Pyx_CyFunction_init() < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  #endif
-  #ifdef __Pyx_FusedFunction_USED
-  if (__pyx_FusedFunction_init() < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  #endif
-  #ifdef __Pyx_Generator_USED
-  if (__pyx_Generator_init() < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  #ifdef __pyx_binding_PyCFunctionType_USED
+  if (__pyx_binding_PyCFunctionType_init() < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   #endif
   /*--- Library function declarations ---*/
   /*--- Threads initialization code ---*/
@@ -6554,11 +6052,11 @@ PyMODINIT_FUNC PyInit_boundary_extend(void)
   /*--- Function export code ---*/
   /*--- Type init code ---*/
   /*--- Type import code ---*/
-  __pyx_ptype_5numpy_dtype = __Pyx_ImportType("numpy", "dtype", sizeof(PyArray_Descr), 0); if (unlikely(!__pyx_ptype_5numpy_dtype)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 154; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_ptype_5numpy_flatiter = __Pyx_ImportType("numpy", "flatiter", sizeof(PyArrayIterObject), 0); if (unlikely(!__pyx_ptype_5numpy_flatiter)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 164; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_ptype_5numpy_broadcast = __Pyx_ImportType("numpy", "broadcast", sizeof(PyArrayMultiIterObject), 0); if (unlikely(!__pyx_ptype_5numpy_broadcast)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 168; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_ptype_5numpy_ndarray = __Pyx_ImportType("numpy", "ndarray", sizeof(PyArrayObject), 0); if (unlikely(!__pyx_ptype_5numpy_ndarray)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 177; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_ptype_5numpy_ufunc = __Pyx_ImportType("numpy", "ufunc", sizeof(PyUFuncObject), 0); if (unlikely(!__pyx_ptype_5numpy_ufunc)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 860; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_5numpy_dtype = __Pyx_ImportType("numpy", "dtype", sizeof(PyArray_Descr), 0); if (unlikely(!__pyx_ptype_5numpy_dtype)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 151; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_5numpy_flatiter = __Pyx_ImportType("numpy", "flatiter", sizeof(PyArrayIterObject), 0); if (unlikely(!__pyx_ptype_5numpy_flatiter)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 161; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_5numpy_broadcast = __Pyx_ImportType("numpy", "broadcast", sizeof(PyArrayMultiIterObject), 0); if (unlikely(!__pyx_ptype_5numpy_broadcast)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 165; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_5numpy_ndarray = __Pyx_ImportType("numpy", "ndarray", sizeof(PyArrayObject), 0); if (unlikely(!__pyx_ptype_5numpy_ndarray)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 174; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_5numpy_ufunc = __Pyx_ImportType("numpy", "ufunc", sizeof(PyUFuncObject), 0); if (unlikely(!__pyx_ptype_5numpy_ufunc)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 857; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   /*--- Variable import code ---*/
   /*--- Function import code ---*/
   /*--- Execution code ---*/
@@ -6596,9 +6094,9 @@ PyMODINIT_FUNC PyInit_boundary_extend(void)
  *                                np.ndarray[DTYPE_t, ndim=1] g):
  * 
  */
-  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_7astropy_6nddata_11convolution_15boundary_extend_1convolve1d_boundary_extend, NULL, __pyx_n_s_21); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 18; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_7astropy_6nddata_11convolution_15boundary_extend_convolve1d_boundary_extend, NULL, __pyx_n_s_17); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 18; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
-  if (PyObject_SetAttr(__pyx_m, __pyx_n_s_19, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 18; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s_18, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 18; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
   /* "astropy/nddata/convolution/boundary_extend.pyx":86
@@ -6608,9 +6106,9 @@ PyMODINIT_FUNC PyInit_boundary_extend(void)
  *                                np.ndarray[DTYPE_t, ndim=2] g):
  * 
  */
-  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_7astropy_6nddata_11convolution_15boundary_extend_3convolve2d_boundary_extend, NULL, __pyx_n_s_21); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 86; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_7astropy_6nddata_11convolution_15boundary_extend_1convolve2d_boundary_extend, NULL, __pyx_n_s_17); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 86; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
-  if (PyObject_SetAttr(__pyx_m, __pyx_n_s_24, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 86; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s_19, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 86; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
   /* "astropy/nddata/convolution/boundary_extend.pyx":169
@@ -6620,9 +6118,9 @@ PyMODINIT_FUNC PyInit_boundary_extend(void)
  *                                np.ndarray[DTYPE_t, ndim=3] g):
  * 
  */
-  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_7astropy_6nddata_11convolution_15boundary_extend_5convolve3d_boundary_extend, NULL, __pyx_n_s_21); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 169; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_7astropy_6nddata_11convolution_15boundary_extend_2convolve3d_boundary_extend, NULL, __pyx_n_s_17); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 169; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
-  if (PyObject_SetAttr(__pyx_m, __pyx_n_s_27, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 169; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s_20, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 169; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
   /* "astropy/nddata/convolution/boundary_extend.pyx":1
@@ -6635,7 +6133,7 @@ PyMODINIT_FUNC PyInit_boundary_extend(void)
   if (PyObject_SetAttr(__pyx_m, __pyx_n_s____test__, ((PyObject *)__pyx_t_2)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
 
-  /* "numpy.pxd":974
+  /* "numpy.pxd":971
  *      arr.base = baseptr
  * 
  * cdef inline object get_array_base(ndarray arr):             # <<<<<<<<<<<<<<
@@ -6662,6 +6160,7 @@ PyMODINIT_FUNC PyInit_boundary_extend(void)
 }
 
 /* Runtime support code */
+
 #if CYTHON_REFNANNY
 static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname) {
     PyObject *m = NULL, *p = NULL;
@@ -6702,6 +6201,7 @@ static void __Pyx_RaiseArgtupleInvalid(
 {
     Py_ssize_t num_expected;
     const char *more_or_less;
+
     if (num_found < num_min) {
         num_expected = num_min;
         more_or_less = "at least";
@@ -6743,6 +6243,7 @@ static int __Pyx_ParseOptionalKeywords(
     Py_ssize_t pos = 0;
     PyObject*** name;
     PyObject*** first_kw_arg = argnames + num_pos_args;
+
     while (PyDict_Next(kwds, &pos, &key, &value)) {
         name = first_kw_arg;
         while (*name && (**name != key)) name++;
@@ -6752,7 +6253,7 @@ static int __Pyx_ParseOptionalKeywords(
             #if PY_MAJOR_VERSION < 3
             if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key))) {
             #else
-            if (unlikely(!PyUnicode_Check(key))) {
+            if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key))) {
             #endif
                 goto invalid_keyword_type;
             } else {
@@ -6768,6 +6269,7 @@ static int __Pyx_ParseOptionalKeywords(
                 if (*name) {
                     values[name-argnames] = value;
                 } else {
+                    /* unexpected keyword found */
                     for (name=argnames; name != first_kw_arg; name++) {
                         if (**name == key) goto arg_passed_twice;
                         #if PY_MAJOR_VERSION >= 3
@@ -6832,6 +6334,18 @@ static CYTHON_INLINE int __Pyx_IsLittleEndian(void) {
   unsigned int n = 1;
   return *(unsigned char*)(&n) != 0;
 }
+
+typedef struct {
+  __Pyx_StructField root;
+  __Pyx_BufFmt_StackElem* head;
+  size_t fmt_offset;
+  size_t new_count, enc_count;
+  int is_complex;
+  char enc_type;
+  char new_packmode;
+  char enc_packmode;
+} __Pyx_BufFmt_Context;
+
 static void __Pyx_BufFmt_Init(__Pyx_BufFmt_Context* ctx,
                               __Pyx_BufFmt_StackElem* stack,
                               __Pyx_TypeInfo* type) {
@@ -6850,8 +6364,6 @@ static void __Pyx_BufFmt_Init(__Pyx_BufFmt_Context* ctx,
   ctx->enc_count = 0;
   ctx->enc_type = 0;
   ctx->is_complex = 0;
-  ctx->is_valid_array = 0;
-  ctx->struct_alignment = 0;
   while (type->typegroup == 'S') {
     ++ctx->head;
     ctx->head->field = type->fields;
@@ -6859,6 +6371,7 @@ static void __Pyx_BufFmt_Init(__Pyx_BufFmt_Context* ctx,
     type = type->fields->type;
   }
 }
+
 static int __Pyx_BufFmt_ParseNumber(const char** ts) {
     int count;
     const char* t = *ts;
@@ -6874,17 +6387,12 @@ static int __Pyx_BufFmt_ParseNumber(const char** ts) {
     *ts = t;
     return count;
 }
-static int __Pyx_BufFmt_ExpectNumber(const char **ts) {
-    int number = __Pyx_BufFmt_ParseNumber(ts);
-    if (number == -1) /* First char was not a digit */
-        PyErr_Format(PyExc_ValueError,\
-                     "Does not understand character buffer dtype format string ('%c')", **ts);
-    return number;
-}
+
 static void __Pyx_BufFmt_RaiseUnexpectedChar(char ch) {
   PyErr_Format(PyExc_ValueError,
                "Unexpected format string character: '%c'", ch);
 }
+
 static const char* __Pyx_BufFmt_DescribeTypeChar(char ch, int is_complex) {
   switch (ch) {
     case 'b': return "'char'";
@@ -6903,14 +6411,14 @@ static const char* __Pyx_BufFmt_DescribeTypeChar(char ch, int is_complex) {
     case 'T': return "a struct";
     case 'O': return "Python object";
     case 'P': return "a pointer";
-    case 's': case 'p': return "a string";
     case 0: return "end";
     default: return "unparseable format string";
   }
 }
+
 static size_t __Pyx_BufFmt_TypeCharToStandardSize(char ch, int is_complex) {
   switch (ch) {
-    case '?': case 'c': case 'b': case 'B': case 's': case 'p': return 1;
+    case '?': case 'c': case 'b': case 'B': return 1;
     case 'h': case 'H': return 2;
     case 'i': case 'I': case 'l': case 'L': return 4;
     case 'q': case 'Q': return 8;
@@ -6926,9 +6434,10 @@ static size_t __Pyx_BufFmt_TypeCharToStandardSize(char ch, int is_complex) {
       return 0;
     }
 }
+
 static size_t __Pyx_BufFmt_TypeCharToNativeSize(char ch, int is_complex) {
   switch (ch) {
-    case 'c': case 'b': case 'B': case 's': case 'p': return 1;
+    case 'c': case 'b': case 'B': return 1;
     case 'h': case 'H': return sizeof(short);
     case 'i': case 'I': return sizeof(int);
     case 'l': case 'L': return sizeof(long);
@@ -6945,6 +6454,7 @@ static size_t __Pyx_BufFmt_TypeCharToNativeSize(char ch, int is_complex) {
     }
   }
 }
+
 typedef struct { char c; short x; } __Pyx_st_short;
 typedef struct { char c; int x; } __Pyx_st_int;
 typedef struct { char c; long x; } __Pyx_st_long;
@@ -6955,9 +6465,10 @@ typedef struct { char c; void *x; } __Pyx_st_void_p;
 #ifdef HAVE_LONG_LONG
 typedef struct { char c; PY_LONG_LONG x; } __Pyx_st_longlong;
 #endif
+
 static size_t __Pyx_BufFmt_TypeCharToAlignment(char ch, int is_complex) {
   switch (ch) {
-    case '?': case 'c': case 'b': case 'B': case 's': case 'p': return 1;
+    case '?': case 'c': case 'b': case 'B': return 1;
     case 'h': case 'H': return sizeof(__Pyx_st_short) - sizeof(short);
     case 'i': case 'I': return sizeof(__Pyx_st_int) - sizeof(int);
     case 'l': case 'L': return sizeof(__Pyx_st_long) - sizeof(long);
@@ -6973,57 +6484,21 @@ static size_t __Pyx_BufFmt_TypeCharToAlignment(char ch, int is_complex) {
       return 0;
     }
 }
-/* These are for computing the padding at the end of the struct to align
-   on the first member of the struct. This will probably the same as above,
-   but we don't have any guarantees.
- */
-typedef struct { short x; char c; } __Pyx_pad_short;
-typedef struct { int x; char c; } __Pyx_pad_int;
-typedef struct { long x; char c; } __Pyx_pad_long;
-typedef struct { float x; char c; } __Pyx_pad_float;
-typedef struct { double x; char c; } __Pyx_pad_double;
-typedef struct { long double x; char c; } __Pyx_pad_longdouble;
-typedef struct { void *x; char c; } __Pyx_pad_void_p;
-#ifdef HAVE_LONG_LONG
-typedef struct { PY_LONG_LONG x; char c; } __Pyx_pad_longlong;
-#endif
-static size_t __Pyx_BufFmt_TypeCharToPadding(char ch, int is_complex) {
-  switch (ch) {
-    case '?': case 'c': case 'b': case 'B': case 's': case 'p': return 1;
-    case 'h': case 'H': return sizeof(__Pyx_pad_short) - sizeof(short);
-    case 'i': case 'I': return sizeof(__Pyx_pad_int) - sizeof(int);
-    case 'l': case 'L': return sizeof(__Pyx_pad_long) - sizeof(long);
-#ifdef HAVE_LONG_LONG
-    case 'q': case 'Q': return sizeof(__Pyx_pad_longlong) - sizeof(PY_LONG_LONG);
-#endif
-    case 'f': return sizeof(__Pyx_pad_float) - sizeof(float);
-    case 'd': return sizeof(__Pyx_pad_double) - sizeof(double);
-    case 'g': return sizeof(__Pyx_pad_longdouble) - sizeof(long double);
-    case 'P': case 'O': return sizeof(__Pyx_pad_void_p) - sizeof(void*);
-    default:
-      __Pyx_BufFmt_RaiseUnexpectedChar(ch);
-      return 0;
-    }
-}
+
 static char __Pyx_BufFmt_TypeCharToGroup(char ch, int is_complex) {
   switch (ch) {
-    case 'c': case 'b': case 'h': case 'i':
-    case 'l': case 'q': case 's': case 'p':
-        return 'I';
-    case 'B': case 'H': case 'I': case 'L': case 'Q':
-        return 'U';
-    case 'f': case 'd': case 'g':
-        return (is_complex ? 'C' : 'R');
-    case 'O':
-        return 'O';
-    case 'P':
-        return 'P';
+    case 'c': case 'b': case 'h': case 'i': case 'l': case 'q': return 'I';
+    case 'B': case 'H': case 'I': case 'L': case 'Q': return 'U';
+    case 'f': case 'd': case 'g': return (is_complex ? 'C' : 'R');
+    case 'O': return 'O';
+    case 'P': return 'P';
     default: {
       __Pyx_BufFmt_RaiseUnexpectedChar(ch);
       return 0;
     }
   }
 }
+
 static void __Pyx_BufFmt_RaiseExpected(__Pyx_BufFmt_Context* ctx) {
   if (ctx->head == NULL || ctx->head->field == &ctx->root) {
     const char* expected;
@@ -7048,37 +6523,16 @@ static void __Pyx_BufFmt_RaiseExpected(__Pyx_BufFmt_Context* ctx) {
                  parent->type->name, field->name);
   }
 }
+
 static int __Pyx_BufFmt_ProcessTypeChunk(__Pyx_BufFmt_Context* ctx) {
   char group;
-  size_t size, offset, arraysize = 1;
+  size_t size, offset;
   if (ctx->enc_type == 0) return 0;
-  if (ctx->head->field->type->arraysize[0]) {
-    int i, ndim = 0;
-    if (ctx->enc_type == 's' || ctx->enc_type == 'p') {
-        ctx->is_valid_array = ctx->head->field->type->ndim == 1;
-        ndim = 1;
-        if (ctx->enc_count != ctx->head->field->type->arraysize[0]) {
-            PyErr_Format(PyExc_ValueError,
-                         "Expected a dimension of size %zu, got %zu",
-                         ctx->head->field->type->arraysize[0], ctx->enc_count);
-            return -1;
-        }
-    }
-    if (!ctx->is_valid_array) {
-      PyErr_Format(PyExc_ValueError, "Expected %d dimensions, got %d",
-                   ctx->head->field->type->ndim, ndim);
-      return -1;
-    }
-    for (i = 0; i < ctx->head->field->type->ndim; i++) {
-      arraysize *= ctx->head->field->type->arraysize[i];
-    }
-    ctx->is_valid_array = 0;
-    ctx->enc_count = 1;
-  }
   group = __Pyx_BufFmt_TypeCharToGroup(ctx->enc_type, ctx->is_complex);
   do {
     __Pyx_StructField* field = ctx->head->field;
     __Pyx_TypeInfo* type = field->type;
+
     if (ctx->enc_packmode == '@' || ctx->enc_packmode == '^') {
       size = __Pyx_BufFmt_TypeCharToNativeSize(ctx->enc_type, ctx->is_complex);
     } else {
@@ -7090,21 +6544,22 @@ static int __Pyx_BufFmt_ProcessTypeChunk(__Pyx_BufFmt_Context* ctx) {
       if (align_at == 0) return -1;
       align_mod_offset = ctx->fmt_offset % align_at;
       if (align_mod_offset > 0) ctx->fmt_offset += align_at - align_mod_offset;
-      if (ctx->struct_alignment == 0)
-          ctx->struct_alignment = __Pyx_BufFmt_TypeCharToPadding(ctx->enc_type,
-                                                                 ctx->is_complex);
     }
+
     if (type->size != size || type->typegroup != group) {
       if (type->typegroup == 'C' && type->fields != NULL) {
+        /* special case -- treat as struct rather than complex number */
         size_t parent_offset = ctx->head->parent_offset + field->offset;
         ++ctx->head;
         ctx->head->field = type->fields;
         ctx->head->parent_offset = parent_offset;
         continue;
       }
+
       __Pyx_BufFmt_RaiseExpected(ctx);
       return -1;
     }
+
     offset = ctx->head->parent_offset + field->offset;
     if (ctx->fmt_offset != offset) {
       PyErr_Format(PyExc_ValueError,
@@ -7112,10 +6567,12 @@ static int __Pyx_BufFmt_ProcessTypeChunk(__Pyx_BufFmt_Context* ctx) {
                    (Py_ssize_t)ctx->fmt_offset, (Py_ssize_t)offset);
       return -1;
     }
+
     ctx->fmt_offset += size;
-    if (arraysize)
-      ctx->fmt_offset += (arraysize - 1) * size;
+
     --ctx->enc_count; /* Consume from buffer string */
+
+    /* Done checking, move to next field, pushing or popping struct stack if needed */
     while (1) {
       if (field == &ctx->root) {
         ctx->head = NULL;
@@ -7147,48 +6604,7 @@ static int __Pyx_BufFmt_ProcessTypeChunk(__Pyx_BufFmt_Context* ctx) {
   ctx->is_complex = 0;
   return 0;
 }
-static CYTHON_INLINE PyObject *
-__pyx_buffmt_parse_array(__Pyx_BufFmt_Context* ctx, const char** tsp)
-{
-    const char *ts = *tsp;
-    int i = 0, number;
-    int ndim = ctx->head->field->type->ndim;
-;
-    ++ts;
-    if (ctx->new_count != 1) {
-        PyErr_SetString(PyExc_ValueError,
-                        "Cannot handle repeated arrays in format string");
-        return NULL;
-    }
-    if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL;
-    while (*ts && *ts != ')') {
-        if (isspace(*ts))
-            continue;
-        number = __Pyx_BufFmt_ExpectNumber(&ts);
-        if (number == -1) return NULL;
-        if (i < ndim && (size_t) number != ctx->head->field->type->arraysize[i])
-            return PyErr_Format(PyExc_ValueError,
-                        "Expected a dimension of size %zu, got %d",
-                        ctx->head->field->type->arraysize[i], number);
-        if (*ts != ',' && *ts != ')')
-            return PyErr_Format(PyExc_ValueError,
-                                "Expected a comma in format string, got '%c'", *ts);
-        if (*ts == ',') ts++;
-        i++;
-    }
-    if (i != ndim)
-        return PyErr_Format(PyExc_ValueError, "Expected %d dimension(s), got %d",
-                            ctx->head->field->type->ndim, i);
-    if (!*ts) {
-        PyErr_SetString(PyExc_ValueError,
-                        "Unexpected end of format string, expected ')'");
-        return NULL;
-    }
-    ctx->is_valid_array = 1;
-    ctx->new_count = 1;
-    *tsp = ++ts;
-    return Py_None;
-}
+
 static const char* __Pyx_BufFmt_CheckString(__Pyx_BufFmt_Context* ctx, const char* ts) {
   int got_Z = 0;
   while (1) {
@@ -7203,7 +6619,7 @@ static const char* __Pyx_BufFmt_CheckString(__Pyx_BufFmt_Context* ctx, const cha
           __Pyx_BufFmt_RaiseExpected(ctx);
           return NULL;
         }
-                return ts;
+        return ts;
       case ' ':
       case 10:
       case 13:
@@ -7235,17 +6651,12 @@ static const char* __Pyx_BufFmt_CheckString(__Pyx_BufFmt_Context* ctx, const cha
         {
           const char* ts_after_sub;
           size_t i, struct_count = ctx->new_count;
-          size_t struct_alignment = ctx->struct_alignment;
           ctx->new_count = 1;
           ++ts;
           if (*ts != '{') {
             PyErr_SetString(PyExc_ValueError, "Buffer acquisition: Expected '{' after 'T'");
             return NULL;
           }
-          if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL;
-          ctx->enc_type = 0; /* Erase processed last struct element */
-          ctx->enc_count = 0;
-          ctx->struct_alignment = 0;
           ++ts;
           ts_after_sub = ts;
           for (i = 0; i != struct_count; ++i) {
@@ -7253,19 +6664,10 @@ static const char* __Pyx_BufFmt_CheckString(__Pyx_BufFmt_Context* ctx, const cha
             if (!ts_after_sub) return NULL;
           }
           ts = ts_after_sub;
-          if (struct_alignment) ctx->struct_alignment = struct_alignment;
         }
         break;
       case '}': /* end of substruct; either repeat or move on */
-        {
-          size_t alignment = ctx->struct_alignment;
-          ++ts;
-          if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL;
-          ctx->enc_type = 0; /* Erase processed last struct element */
-          if (alignment && ctx->fmt_offset % alignment) {
-            ctx->fmt_offset += alignment - (ctx->fmt_offset % alignment);
-          }
-        }
+        ++ts;
         return ts;
       case 'x':
         if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL;
@@ -7286,11 +6688,13 @@ static const char* __Pyx_BufFmt_CheckString(__Pyx_BufFmt_Context* ctx, const cha
       case 'c': case 'b': case 'B': case 'h': case 'H': case 'i': case 'I':
       case 'l': case 'L': case 'q': case 'Q':
       case 'f': case 'd': case 'g':
-      case 'O': case 's': case 'p':
+      case 'O':
         if (ctx->enc_type == *ts && got_Z == ctx->is_complex &&
             ctx->enc_packmode == ctx->new_packmode) {
+          /* Continue pooling same type */
           ctx->enc_count += ctx->new_count;
         } else {
+          /* New type */
           if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL;
           ctx->enc_count = ctx->new_count;
           ctx->enc_packmode = ctx->new_packmode;
@@ -7306,18 +6710,20 @@ static const char* __Pyx_BufFmt_CheckString(__Pyx_BufFmt_Context* ctx, const cha
         while(*ts != ':') ++ts;
         ++ts;
         break;
-      case '(':
-        if (!__pyx_buffmt_parse_array(ctx, &ts)) return NULL;
-        break;
       default:
         {
-          int number = __Pyx_BufFmt_ExpectNumber(&ts);
-          if (number == -1) return NULL;
-          ctx->new_count = (size_t)number;
+          int number = __Pyx_BufFmt_ParseNumber(&ts);
+          if (number == -1) { /* First char was not a digit */
+            PyErr_Format(PyExc_ValueError,
+                         "Does not understand character buffer dtype format string ('%c')", *ts);
+            return NULL;
+          }
+          ctx->new_count = (size_t)number; 
         }
     }
   }
 }
+
 static CYTHON_INLINE void __Pyx_ZeroBuffer(Py_buffer* buf) {
   buf->buf = NULL;
   buf->obj = NULL;
@@ -7325,10 +6731,8 @@ static CYTHON_INLINE void __Pyx_ZeroBuffer(Py_buffer* buf) {
   buf->shape = __Pyx_zeros;
   buf->suboffsets = __Pyx_minusones;
 }
-static CYTHON_INLINE int __Pyx_GetBufferAndValidate(
-        Py_buffer* buf, PyObject* obj,  __Pyx_TypeInfo* dtype, int flags,
-        int nd, int cast, __Pyx_BufFmt_StackElem* stack)
-{
+
+static CYTHON_INLINE int __Pyx_GetBufferAndValidate(Py_buffer* buf, PyObject* obj, __Pyx_TypeInfo* dtype, int flags, int nd, int cast, __Pyx_BufFmt_StackElem* stack) {
   if (obj == Py_None || obj == NULL) {
     __Pyx_ZeroBuffer(buf);
     return 0;
@@ -7359,6 +6763,7 @@ fail:;
   __Pyx_ZeroBuffer(buf);
   return -1;
 }
+
 static CYTHON_INLINE void __Pyx_SafeReleaseBuffer(Py_buffer* info) {
   if (info->buf == NULL) return;
   if (info->suboffsets == __Pyx_minusones) info->suboffsets = NULL;
@@ -7372,9 +6777,9 @@ static CYTHON_INLINE long __Pyx_mod_long(long a, long b) {
 }
 
 static CYTHON_INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb) {
-#if CYTHON_COMPILING_IN_CPYTHON
     PyObject *tmp_type, *tmp_value, *tmp_tb;
     PyThreadState *tstate = PyThreadState_GET();
+
     tmp_type = tstate->curexc_type;
     tmp_value = tstate->curexc_value;
     tmp_tb = tstate->curexc_traceback;
@@ -7384,30 +6789,27 @@ static CYTHON_INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyOb
     Py_XDECREF(tmp_type);
     Py_XDECREF(tmp_value);
     Py_XDECREF(tmp_tb);
-#else
-    PyErr_Restore(type, value, tb);
-#endif
 }
+
 static CYTHON_INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb) {
-#if CYTHON_COMPILING_IN_CPYTHON
     PyThreadState *tstate = PyThreadState_GET();
     *type = tstate->curexc_type;
     *value = tstate->curexc_value;
     *tb = tstate->curexc_traceback;
+
     tstate->curexc_type = 0;
     tstate->curexc_value = 0;
     tstate->curexc_traceback = 0;
-#else
-    PyErr_Fetch(type, value, tb);
-#endif
 }
 
+
 #if PY_MAJOR_VERSION < 3
-static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb,
-                        CYTHON_UNUSED PyObject *cause) {
+static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause) {
+    /* cause is unused */
     Py_XINCREF(type);
     Py_XINCREF(value);
     Py_XINCREF(tb);
+    /* First, check the traceback argument, replacing None with NULL. */
     if (tb == Py_None) {
         Py_DECREF(tb);
         tb = 0;
@@ -7417,6 +6819,7 @@ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb,
             "raise: arg 3 must be a traceback or None");
         goto raise_error;
     }
+    /* Next, replace a missing value with None */
     if (value == NULL) {
         value = Py_None;
         Py_INCREF(value);
@@ -7427,11 +6830,13 @@ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb,
     if (!PyType_Check(type))
     #endif
     {
+        /* Raising an instance.  The value should be a dummy. */
         if (value != Py_None) {
             PyErr_SetString(PyExc_TypeError,
                 "instance exception may not have a separate value");
             goto raise_error;
         }
+        /* Normalize to raise <class>, <instance> */
         Py_DECREF(value);
         value = type;
         #if PY_VERSION_HEX < 0x02050000
@@ -7455,6 +6860,7 @@ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb,
             }
         #endif
     }
+
     __Pyx_ErrRestore(type, value, tb);
     return;
 raise_error:
@@ -7463,7 +6869,9 @@ raise_error:
     Py_XDECREF(tb);
     return;
 }
+
 #else /* Python 3+ */
+
 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause) {
     if (tb == Py_None) {
         tb = 0;
@@ -7474,6 +6882,7 @@ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject
     }
     if (value == Py_None)
         value = 0;
+
     if (PyExceptionInstance_Check(type)) {
         if (value) {
             PyErr_SetString(PyExc_TypeError,
@@ -7487,6 +6896,7 @@ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject
             "raise: exception class must be a subclass of BaseException");
         goto bad;
     }
+
     if (cause) {
         PyObject *fixed_cause;
         if (PyExceptionClass_Check(cause)) {
@@ -7509,7 +6919,9 @@ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject
         }
         PyException_SetCause(value, fixed_cause);
     }
+
     PyErr_SetObject(type, value);
+
     if (tb) {
         PyThreadState *tstate = PyThreadState_GET();
         PyObject* tmp_tb = tstate->curexc_traceback;
@@ -7519,6 +6931,7 @@ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject
             Py_XDECREF(tmp_tb);
         }
     }
+
 bad:
     return;
 }
@@ -7570,98 +6983,31 @@ static void __Pyx_UnpackTupleError(PyObject *t, Py_ssize_t index) {
 
 #if PY_MAJOR_VERSION < 3
 static int __Pyx_GetBuffer(PyObject *obj, Py_buffer *view, int flags) {
-    PyObject *getbuffer_cobj;
-
   #if PY_VERSION_HEX >= 0x02060000
-    if (PyObject_CheckBuffer(obj)) return PyObject_GetBuffer(obj, view, flags);
+  if (PyObject_CheckBuffer(obj)) return PyObject_GetBuffer(obj, view, flags);
   #endif
-
-        if (PyObject_TypeCheck(obj, __pyx_ptype_5numpy_ndarray)) return __pyx_pw_5numpy_7ndarray_1__getbuffer__(obj, view, flags);
-
-  #if PY_VERSION_HEX < 0x02060000
-    if (obj->ob_type->tp_dict &&
-        (getbuffer_cobj = PyMapping_GetItemString(obj->ob_type->tp_dict,
-                                             "__pyx_getbuffer"))) {
-        getbufferproc func;
-
-      #if PY_VERSION_HEX >= 0x02070000 && !(PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION == 0)
-        func = (getbufferproc) PyCapsule_GetPointer(getbuffer_cobj, "getbuffer(obj, view, flags)");
-      #else
-        func = (getbufferproc) PyCObject_AsVoidPtr(getbuffer_cobj);
-      #endif
-        Py_DECREF(getbuffer_cobj);
-        if (!func)
-            goto fail;
-
-        return func(obj, view, flags);
-    } else {
-        PyErr_Clear();
+  if (PyObject_TypeCheck(obj, __pyx_ptype_5numpy_ndarray)) return __pyx_pf_5numpy_7ndarray___getbuffer__(obj, view, flags);
+  else {
+  PyErr_Format(PyExc_TypeError, "'%100s' does not have the buffer interface", Py_TYPE(obj)->tp_name);
+  return -1;
     }
-  #endif
-
-    PyErr_Format(PyExc_TypeError, "'%100s' does not have the buffer interface", Py_TYPE(obj)->tp_name);
-
-#if PY_VERSION_HEX < 0x02060000
-fail:
-#endif
-
-    return -1;
 }
 
 static void __Pyx_ReleaseBuffer(Py_buffer *view) {
-    PyObject *obj = view->obj;
-    PyObject *releasebuffer_cobj;
-
-    if (!obj) return;
-
-  #if PY_VERSION_HEX >= 0x02060000
-    if (PyObject_CheckBuffer(obj)) {
-        PyBuffer_Release(view);
-        return;
-    }
-  #endif
-
-        if (PyObject_TypeCheck(obj, __pyx_ptype_5numpy_ndarray)) { __pyx_pw_5numpy_7ndarray_3__releasebuffer__(obj, view); return; }
-
-  #if PY_VERSION_HEX < 0x02060000
-    if (obj->ob_type->tp_dict &&
-        (releasebuffer_cobj = PyMapping_GetItemString(obj->ob_type->tp_dict,
-                                                      "__pyx_releasebuffer"))) {
-        releasebufferproc func;
-
-      #if PY_VERSION_HEX >= 0x02070000 && !(PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION == 0)
-        func = (releasebufferproc) PyCapsule_GetPointer(releasebuffer_cobj, "releasebuffer(obj, view)");
-      #else
-        func = (releasebufferproc) PyCObject_AsVoidPtr(releasebuffer_cobj);
-      #endif
-
-        Py_DECREF(releasebuffer_cobj);
-
-        if (!func)
-            goto fail;
-
-        func(obj, view);
-        return;
-    } else {
-        PyErr_Clear();
-    }
-  #endif
-
-    goto nofail;
-
-#if PY_VERSION_HEX < 0x02060000
-fail:
-#endif
-    PyErr_WriteUnraisable(obj);
-
-nofail:
+  PyObject* obj = view->obj;
+  if (obj) {
+    #if PY_VERSION_HEX >= 0x02060000
+    if (PyObject_CheckBuffer(obj)) {PyBuffer_Release(view); return;}
+    #endif
+    if (PyObject_TypeCheck(obj, __pyx_ptype_5numpy_ndarray)) __pyx_pf_5numpy_7ndarray_1__releasebuffer__(obj, view);
     Py_DECREF(obj);
     view->obj = NULL;
+  }
 }
 
-#endif /*  PY_MAJOR_VERSION < 3 */
+#endif
 
-    static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, long level) {
+static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, long level) {
     PyObject *py_import = 0;
     PyObject *empty_list = 0;
     PyObject *module = 0;
@@ -7687,33 +7033,12 @@ nofail:
         goto bad;
     #if PY_VERSION_HEX >= 0x02050000
     {
-        #if PY_MAJOR_VERSION >= 3
-        if (level == -1) {
-            if (strchr(__Pyx_MODULE_NAME, '.')) {
-                /* try package relative import first */
-                PyObject *py_level = PyInt_FromLong(1);
-                if (!py_level)
-                    goto bad;
-                module = PyObject_CallFunctionObjArgs(py_import,
-                    name, global_dict, empty_dict, list, py_level, NULL);
-                Py_DECREF(py_level);
-                if (!module) {
-                    if (!PyErr_ExceptionMatches(PyExc_ImportError))
-                        goto bad;
-                    PyErr_Clear();
-                }
-            }
-            level = 0; /* try absolute import on failure */
-        }
-        #endif
-        if (!module) {
-            PyObject *py_level = PyInt_FromLong(level);
-            if (!py_level)
-                goto bad;
-            module = PyObject_CallFunctionObjArgs(py_import,
-                name, global_dict, empty_dict, list, py_level, NULL);
-            Py_DECREF(py_level);
-        }
+        PyObject *py_level = PyInt_FromLong(level);
+        if (!py_level)
+            goto bad;
+        module = PyObject_CallFunctionObjArgs(py_import,
+            name, global_dict, empty_dict, list, py_level, NULL);
+        Py_DECREF(py_level);
     }
     #else
     if (level>0) {
@@ -8398,10 +7723,15 @@ static PyTypeObject *__Pyx_ImportType(const char *module_name, const char *class
     PyObject *result = 0;
     PyObject *py_name = 0;
     char warning[200];
+
     py_module = __Pyx_ImportModule(module_name);
     if (!py_module)
         goto bad;
-    py_name = __Pyx_PyIdentifier_FromString(class_name);
+    #if PY_MAJOR_VERSION < 3
+    py_name = PyString_FromString(class_name);
+    #else
+    py_name = PyUnicode_FromString(class_name);
+    #endif
     if (!py_name)
         goto bad;
     result = PyObject_GetAttr(py_module, py_name);
@@ -8417,7 +7747,7 @@ static PyTypeObject *__Pyx_ImportType(const char *module_name, const char *class
             module_name, class_name);
         goto bad;
     }
-    if (!strict && (size_t)((PyTypeObject *)result)->tp_basicsize > size) {
+    if (!strict && ((PyTypeObject *)result)->tp_basicsize > (Py_ssize_t)size) {
         PyOS_snprintf(warning, sizeof(warning),
             "%s.%s size changed, may indicate binary incompatibility",
             module_name, class_name);
@@ -8427,7 +7757,7 @@ static PyTypeObject *__Pyx_ImportType(const char *module_name, const char *class
         if (PyErr_WarnEx(NULL, warning, 0) < 0) goto bad;
         #endif
     }
-    else if ((size_t)((PyTypeObject *)result)->tp_basicsize != size) {
+    else if (((PyTypeObject *)result)->tp_basicsize != (Py_ssize_t)size) {
         PyErr_Format(PyExc_ValueError,
             "%s.%s has the wrong size, try recompiling",
             module_name, class_name);
@@ -8446,7 +7776,12 @@ bad:
 static PyObject *__Pyx_ImportModule(const char *name) {
     PyObject *py_name = 0;
     PyObject *py_module = 0;
-    py_name = __Pyx_PyIdentifier_FromString(name);
+
+    #if PY_MAJOR_VERSION < 3
+    py_name = PyString_FromString(name);
+    #else
+    py_name = PyUnicode_FromString(name);
+    #endif
     if (!py_name)
         goto bad;
     py_module = PyImport_Import(py_name);
@@ -8458,105 +7793,29 @@ bad:
 }
 #endif
 
-static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line) {
-    int start = 0, mid = 0, end = count - 1;
-    if (end >= 0 && code_line > entries[end].code_line) {
-        return count;
-    }
-    while (start < end) {
-        mid = (start + end) / 2;
-        if (code_line < entries[mid].code_line) {
-            end = mid;
-        } else if (code_line > entries[mid].code_line) {
-             start = mid + 1;
-        } else {
-            return mid;
-        }
-    }
-    if (code_line <= entries[mid].code_line) {
-        return mid;
-    } else {
-        return mid + 1;
-    }
-}
-static PyCodeObject *__pyx_find_code_object(int code_line) {
-    PyCodeObject* code_object;
-    int pos;
-    if (unlikely(!code_line) || unlikely(!__pyx_code_cache.entries)) {
-        return NULL;
-    }
-    pos = __pyx_bisect_code_objects(__pyx_code_cache.entries, __pyx_code_cache.count, code_line);
-    if (unlikely(pos >= __pyx_code_cache.count) || unlikely(__pyx_code_cache.entries[pos].code_line != code_line)) {
-        return NULL;
-    }
-    code_object = __pyx_code_cache.entries[pos].code_object;
-    Py_INCREF(code_object);
-    return code_object;
-}
-static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object) {
-    int pos, i;
-    __Pyx_CodeObjectCacheEntry* entries = __pyx_code_cache.entries;
-    if (unlikely(!code_line)) {
-        return;
-    }
-    if (unlikely(!entries)) {
-        entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Malloc(64*sizeof(__Pyx_CodeObjectCacheEntry));
-        if (likely(entries)) {
-            __pyx_code_cache.entries = entries;
-            __pyx_code_cache.max_count = 64;
-            __pyx_code_cache.count = 1;
-            entries[0].code_line = code_line;
-            entries[0].code_object = code_object;
-            Py_INCREF(code_object);
-        }
-        return;
-    }
-    pos = __pyx_bisect_code_objects(__pyx_code_cache.entries, __pyx_code_cache.count, code_line);
-    if ((pos < __pyx_code_cache.count) && unlikely(__pyx_code_cache.entries[pos].code_line == code_line)) {
-        PyCodeObject* tmp = entries[pos].code_object;
-        entries[pos].code_object = code_object;
-        Py_DECREF(tmp);
-        return;
-    }
-    if (__pyx_code_cache.count == __pyx_code_cache.max_count) {
-        int new_max = __pyx_code_cache.max_count + 64;
-        entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Realloc(
-            __pyx_code_cache.entries, new_max*sizeof(__Pyx_CodeObjectCacheEntry));
-        if (unlikely(!entries)) {
-            return;
-        }
-        __pyx_code_cache.entries = entries;
-        __pyx_code_cache.max_count = new_max;
-    }
-    for (i=__pyx_code_cache.count; i>pos; i--) {
-        entries[i] = entries[i-1];
-    }
-    entries[pos].code_line = code_line;
-    entries[pos].code_object = code_object;
-    __pyx_code_cache.count++;
-    Py_INCREF(code_object);
-}
-
 #include "compile.h"
 #include "frameobject.h"
 #include "traceback.h"
-static PyCodeObject* __Pyx_CreateCodeObjectForTraceback(
-            const char *funcname, int c_line,
-            int py_line, const char *filename) {
-    PyCodeObject *py_code = 0;
+
+static void __Pyx_AddTraceback(const char *funcname, int __pyx_clineno,
+                               int __pyx_lineno, const char *__pyx_filename) {
     PyObject *py_srcfile = 0;
     PyObject *py_funcname = 0;
+    PyObject *py_globals = 0;
+    PyCodeObject *py_code = 0;
+    PyFrameObject *py_frame = 0;
+
     #if PY_MAJOR_VERSION < 3
-    py_srcfile = PyString_FromString(filename);
+    py_srcfile = PyString_FromString(__pyx_filename);
     #else
-    py_srcfile = PyUnicode_FromString(filename);
+    py_srcfile = PyUnicode_FromString(__pyx_filename);
     #endif
     if (!py_srcfile) goto bad;
-    if (c_line) {
+    if (__pyx_clineno) {
         #if PY_MAJOR_VERSION < 3
-        py_funcname = PyString_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line);
+        py_funcname = PyString_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, __pyx_clineno);
         #else
-        py_funcname = PyUnicode_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line);
+        py_funcname = PyUnicode_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, __pyx_clineno);
         #endif
     }
     else {
@@ -8567,45 +7826,28 @@ static PyCodeObject* __Pyx_CreateCodeObjectForTraceback(
         #endif
     }
     if (!py_funcname) goto bad;
-    py_code = __Pyx_PyCode_New(
+    py_globals = PyModule_GetDict(__pyx_m);
+    if (!py_globals) goto bad;
+    py_code = PyCode_New(
         0,            /*int argcount,*/
+        #if PY_MAJOR_VERSION >= 3
         0,            /*int kwonlyargcount,*/
+        #endif
         0,            /*int nlocals,*/
         0,            /*int stacksize,*/
         0,            /*int flags,*/
         __pyx_empty_bytes, /*PyObject *code,*/
-        __pyx_empty_tuple, /*PyObject *consts,*/
-        __pyx_empty_tuple, /*PyObject *names,*/
-        __pyx_empty_tuple, /*PyObject *varnames,*/
-        __pyx_empty_tuple, /*PyObject *freevars,*/
-        __pyx_empty_tuple, /*PyObject *cellvars,*/
+        __pyx_empty_tuple,  /*PyObject *consts,*/
+        __pyx_empty_tuple,  /*PyObject *names,*/
+        __pyx_empty_tuple,  /*PyObject *varnames,*/
+        __pyx_empty_tuple,  /*PyObject *freevars,*/
+        __pyx_empty_tuple,  /*PyObject *cellvars,*/
         py_srcfile,   /*PyObject *filename,*/
         py_funcname,  /*PyObject *name,*/
-        py_line,      /*int firstlineno,*/
+        __pyx_lineno,   /*int firstlineno,*/
         __pyx_empty_bytes  /*PyObject *lnotab*/
     );
-    Py_DECREF(py_srcfile);
-    Py_DECREF(py_funcname);
-    return py_code;
-bad:
-    Py_XDECREF(py_srcfile);
-    Py_XDECREF(py_funcname);
-    return NULL;
-}
-static void __Pyx_AddTraceback(const char *funcname, int c_line,
-                               int py_line, const char *filename) {
-    PyCodeObject *py_code = 0;
-    PyObject *py_globals = 0;
-    PyFrameObject *py_frame = 0;
-    py_code = __pyx_find_code_object(c_line ? c_line : py_line);
-    if (!py_code) {
-        py_code = __Pyx_CreateCodeObjectForTraceback(
-            funcname, c_line, py_line, filename);
-        if (!py_code) goto bad;
-        __pyx_insert_code_object(c_line ? c_line : py_line, py_code);
-    }
-    py_globals = PyModule_GetDict(__pyx_m);
-    if (!py_globals) goto bad;
+    if (!py_code) goto bad;
     py_frame = PyFrame_New(
         PyThreadState_GET(), /*PyThreadState *tstate,*/
         py_code,             /*PyCodeObject *code,*/
@@ -8613,9 +7855,11 @@ static void __Pyx_AddTraceback(const char *funcname, int c_line,
         0                    /*PyObject *locals*/
     );
     if (!py_frame) goto bad;
-    py_frame->f_lineno = py_line;
+    py_frame->f_lineno = __pyx_lineno;
     PyTraceBack_Here(py_frame);
 bad:
+    Py_XDECREF(py_srcfile);
+    Py_XDECREF(py_funcname);
     Py_XDECREF(py_code);
     Py_XDECREF(py_frame);
 }
@@ -8650,7 +7894,6 @@ static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) {
     return 0;
 }
 
-
 /* Type Conversion Functions */
 
 static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject* x) {
diff --git a/astropy/nddata/convolution/boundary_fill.c b/astropy/nddata/convolution/boundary_fill.c
index af27b79..3149535 100644
--- a/astropy/nddata/convolution/boundary_fill.c
+++ b/astropy/nddata/convolution/boundary_fill.c
@@ -1,12 +1,11 @@
-/* Generated by Cython 0.16 on Tue Jun 19 01:38:32 2012 */
+/* Generated by Cython 0.15.1 on Mon Dec 24 15:34:28 2012 */
 
 #define PY_SSIZE_T_CLEAN
 #include "Python.h"
 #ifndef Py_PYTHON_H
     #error Python headers needed to compile C extensions, please install development version of Python.
-#elif PY_VERSION_HEX < 0x02040000
-    #error Cython requires Python 2.4+.
 #else
+
 #include <stddef.h> /* For offsetof */
 #ifndef offsetof
 #define offsetof(type, member) ( (size_t) & ((type*)0) -> member )
@@ -35,22 +34,10 @@
   #define PY_LONG_LONG LONG_LONG
 #endif
 
-#ifndef Py_HUGE_VAL
-  #define Py_HUGE_VAL HUGE_VAL
-#endif
-
-#ifdef PYPY_VERSION
-#define CYTHON_COMPILING_IN_PYPY 1
-#define CYTHON_COMPILING_IN_CPYTHON 0
-#else
-#define CYTHON_COMPILING_IN_PYPY 0
-#define CYTHON_COMPILING_IN_CPYTHON 1
-#endif
-
-#if CYTHON_COMPILING_IN_PYPY
-  #define __Pyx_PyCFunction_Call PyObject_Call
-#else
-  #define __Pyx_PyCFunction_Call PyCFunction_Call
+#if PY_VERSION_HEX < 0x02040000
+  #define METH_COEXIST 0
+  #define PyDict_CheckExact(op) (Py_TYPE(op) == &PyDict_Type)
+  #define PyDict_Contains(d,o)   PySequence_Contains(d,o)
 #endif
 
 #if PY_VERSION_HEX < 0x02050000
@@ -63,9 +50,6 @@
   #define PyNumber_Index(o)    PyNumber_Int(o)
   #define PyIndex_Check(o)     PyNumber_Check(o)
   #define PyErr_WarnEx(category, message, stacklevel) PyErr_Warn(category, message)
-  #define __PYX_BUILD_PY_SSIZE_T "i"
-#else
-  #define __PYX_BUILD_PY_SSIZE_T "n"
 #endif
 
 #if PY_VERSION_HEX < 0x02060000
@@ -99,25 +83,13 @@
   #define PyBUF_F_CONTIGUOUS (0x0040 | PyBUF_STRIDES)
   #define PyBUF_ANY_CONTIGUOUS (0x0080 | PyBUF_STRIDES)
   #define PyBUF_INDIRECT (0x0100 | PyBUF_STRIDES)
-  #define PyBUF_RECORDS (PyBUF_STRIDES | PyBUF_FORMAT | PyBUF_WRITABLE)
-  #define PyBUF_FULL (PyBUF_INDIRECT | PyBUF_FORMAT | PyBUF_WRITABLE)
 
-  typedef int (*getbufferproc)(PyObject *, Py_buffer *, int);
-  typedef void (*releasebufferproc)(PyObject *, Py_buffer *);
 #endif
 
 #if PY_MAJOR_VERSION < 3
   #define __Pyx_BUILTIN_MODULE_NAME "__builtin__"
-  #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) \
-          PyCode_New(a, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)
 #else
   #define __Pyx_BUILTIN_MODULE_NAME "builtins"
-  #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) \
-          PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)
-#endif
-
-#if PY_MAJOR_VERSION < 3 && PY_MINOR_VERSION < 6
-  #define PyUnicode_FromString(s) PyUnicode_Decode(s, strlen(s), "UTF-8", "strict")
 #endif
 
 #if PY_MAJOR_VERSION >= 3
@@ -129,17 +101,6 @@
   #define Py_TPFLAGS_HAVE_NEWBUFFER 0
 #endif
 
-
-#if PY_VERSION_HEX > 0x03030000 && defined(PyUnicode_GET_LENGTH)
-  #define CYTHON_PEP393_ENABLED 1
-  #define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_LENGTH(u)
-  #define __Pyx_PyUnicode_READ_CHAR(u, i) PyUnicode_READ_CHAR(u, i)
-#else
-  #define CYTHON_PEP393_ENABLED 0
-  #define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_SIZE(u)
-  #define __Pyx_PyUnicode_READ_CHAR(u, i) ((Py_UCS4)(PyUnicode_AS_UNICODE(u)[i]))
-#endif
-
 #if PY_MAJOR_VERSION >= 3
   #define PyBaseString_Type            PyUnicode_Type
   #define PyStringObject               PyUnicodeObject
@@ -207,6 +168,15 @@
   #define __Pyx_PyInt_AsHash_t   PyInt_AsSsize_t
 #endif
 
+
+#if PY_MAJOR_VERSION >= 3
+  #define __Pyx_PyNumber_Divide(x,y)         PyNumber_TrueDivide(x,y)
+  #define __Pyx_PyNumber_InPlaceDivide(x,y)  PyNumber_InPlaceTrueDivide(x,y)
+#else
+  #define __Pyx_PyNumber_Divide(x,y)         PyNumber_TrueDivide(x,y)
+  #define __Pyx_PyNumber_InPlaceDivide(x,y)  PyNumber_InPlaceTrueDivide(x,y)
+#endif
+
 #if (PY_MAJOR_VERSION < 3) || (PY_VERSION_HEX >= 0x03010300)
   #define __Pyx_PySequence_GetSlice(obj, a, b) PySequence_GetSlice(obj, a, b)
   #define __Pyx_PySequence_SetSlice(obj, a, b, value) PySequence_SetSlice(obj, a, b, value)
@@ -248,14 +218,6 @@
   #define __Pyx_DOCSTR(n)  (n)
 #endif
 
-#if PY_MAJOR_VERSION >= 3
-  #define __Pyx_PyNumber_Divide(x,y)         PyNumber_TrueDivide(x,y)
-  #define __Pyx_PyNumber_InPlaceDivide(x,y)  PyNumber_InPlaceTrueDivide(x,y)
-#else
-  #define __Pyx_PyNumber_Divide(x,y)         PyNumber_TrueDivide(x,y)
-  #define __Pyx_PyNumber_InPlaceDivide(x,y)  PyNumber_InPlaceTrueDivide(x,y)
-#endif
-
 #ifndef __PYX_EXTERN_C
   #ifdef __cplusplus
     #define __PYX_EXTERN_C extern "C"
@@ -305,7 +267,7 @@
 #   else
 #     define CYTHON_UNUSED
 #   endif
-# elif defined(__ICC) || (defined(__INTEL_COMPILER) && !defined(_MSC_VER))
+# elif defined(__ICC) || defined(__INTEL_COMPILER)
 #   define CYTHON_UNUSED __attribute__ ((__unused__))
 # else
 #   define CYTHON_UNUSED
@@ -330,7 +292,7 @@ static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t);
 static CYTHON_INLINE size_t __Pyx_PyInt_AsSize_t(PyObject*);
 
 #define __pyx_PyFloat_AsDouble(x) (PyFloat_CheckExact(x) ? PyFloat_AS_DOUBLE(x) : PyFloat_AsDouble(x))
-#define __pyx_PyFloat_AsFloat(x) ((float) __pyx_PyFloat_AsDouble(x))
+
 
 #ifdef __GNUC__
   /* Test for GCC > 2.95 */
@@ -355,6 +317,7 @@ static int __pyx_clineno = 0;
 static const char * __pyx_cfilenm= __FILE__;
 static const char *__pyx_filename;
 
+
 #if !defined(CYTHON_CCOMPLEX)
   #if defined(__cplusplus)
     #define CYTHON_CCOMPLEX 1
@@ -364,6 +327,7 @@ static const char *__pyx_filename;
     #define CYTHON_CCOMPLEX 0
   #endif
 #endif
+
 #if CYTHON_CCOMPLEX
   #ifdef __cplusplus
     #include <complex>
@@ -371,53 +335,18 @@ static const char *__pyx_filename;
     #include <complex.h>
   #endif
 #endif
+
 #if CYTHON_CCOMPLEX && !defined(__cplusplus) && defined(__sun__) && defined(__GNUC__)
   #undef _Complex_I
   #define _Complex_I 1.0fj
 #endif
 
-
 static const char *__pyx_f[] = {
   "boundary_fill.pyx",
   "numpy.pxd",
 };
-#define IS_UNSIGNED(type) (((type) -1) > 0)
-struct __Pyx_StructField_;
-#define __PYX_BUF_FLAGS_PACKED_STRUCT (1 << 0)
-typedef struct {
-  const char* name; /* for error messages only */
-  struct __Pyx_StructField_* fields;
-  size_t size;     /* sizeof(type) */
-  size_t arraysize[8]; /* length of array in each dimension */
-  int ndim;
-  char typegroup; /* _R_eal, _C_omplex, Signed _I_nt, _U_nsigned int, _S_truct, _P_ointer, _O_bject */
-  char is_unsigned;
-  int flags;
-} __Pyx_TypeInfo;
-typedef struct __Pyx_StructField_ {
-  __Pyx_TypeInfo* type;
-  const char* name;
-  size_t offset;
-} __Pyx_StructField;
-typedef struct {
-  __Pyx_StructField* field;
-  size_t parent_offset;
-} __Pyx_BufFmt_StackElem;
-typedef struct {
-  __Pyx_StructField root;
-  __Pyx_BufFmt_StackElem* head;
-  size_t fmt_offset;
-  size_t new_count, enc_count;
-  size_t struct_alignment;
-  int is_complex;
-  char enc_type;
-  char new_packmode;
-  char enc_packmode;
-  char is_valid_array;
-} __Pyx_BufFmt_Context;
-
 
-/* "numpy.pxd":722
+/* "numpy.pxd":719
  * # in Cython to enable them only on the right systems.
  * 
  * ctypedef npy_int8       int8_t             # <<<<<<<<<<<<<<
@@ -426,7 +355,7 @@ typedef struct {
  */
 typedef npy_int8 __pyx_t_5numpy_int8_t;
 
-/* "numpy.pxd":723
+/* "numpy.pxd":720
  * 
  * ctypedef npy_int8       int8_t
  * ctypedef npy_int16      int16_t             # <<<<<<<<<<<<<<
@@ -435,7 +364,7 @@ typedef npy_int8 __pyx_t_5numpy_int8_t;
  */
 typedef npy_int16 __pyx_t_5numpy_int16_t;
 
-/* "numpy.pxd":724
+/* "numpy.pxd":721
  * ctypedef npy_int8       int8_t
  * ctypedef npy_int16      int16_t
  * ctypedef npy_int32      int32_t             # <<<<<<<<<<<<<<
@@ -444,7 +373,7 @@ typedef npy_int16 __pyx_t_5numpy_int16_t;
  */
 typedef npy_int32 __pyx_t_5numpy_int32_t;
 
-/* "numpy.pxd":725
+/* "numpy.pxd":722
  * ctypedef npy_int16      int16_t
  * ctypedef npy_int32      int32_t
  * ctypedef npy_int64      int64_t             # <<<<<<<<<<<<<<
@@ -453,7 +382,7 @@ typedef npy_int32 __pyx_t_5numpy_int32_t;
  */
 typedef npy_int64 __pyx_t_5numpy_int64_t;
 
-/* "numpy.pxd":729
+/* "numpy.pxd":726
  * #ctypedef npy_int128     int128_t
  * 
  * ctypedef npy_uint8      uint8_t             # <<<<<<<<<<<<<<
@@ -462,7 +391,7 @@ typedef npy_int64 __pyx_t_5numpy_int64_t;
  */
 typedef npy_uint8 __pyx_t_5numpy_uint8_t;
 
-/* "numpy.pxd":730
+/* "numpy.pxd":727
  * 
  * ctypedef npy_uint8      uint8_t
  * ctypedef npy_uint16     uint16_t             # <<<<<<<<<<<<<<
@@ -471,7 +400,7 @@ typedef npy_uint8 __pyx_t_5numpy_uint8_t;
  */
 typedef npy_uint16 __pyx_t_5numpy_uint16_t;
 
-/* "numpy.pxd":731
+/* "numpy.pxd":728
  * ctypedef npy_uint8      uint8_t
  * ctypedef npy_uint16     uint16_t
  * ctypedef npy_uint32     uint32_t             # <<<<<<<<<<<<<<
@@ -480,7 +409,7 @@ typedef npy_uint16 __pyx_t_5numpy_uint16_t;
  */
 typedef npy_uint32 __pyx_t_5numpy_uint32_t;
 
-/* "numpy.pxd":732
+/* "numpy.pxd":729
  * ctypedef npy_uint16     uint16_t
  * ctypedef npy_uint32     uint32_t
  * ctypedef npy_uint64     uint64_t             # <<<<<<<<<<<<<<
@@ -489,7 +418,7 @@ typedef npy_uint32 __pyx_t_5numpy_uint32_t;
  */
 typedef npy_uint64 __pyx_t_5numpy_uint64_t;
 
-/* "numpy.pxd":736
+/* "numpy.pxd":733
  * #ctypedef npy_uint128    uint128_t
  * 
  * ctypedef npy_float32    float32_t             # <<<<<<<<<<<<<<
@@ -498,7 +427,7 @@ typedef npy_uint64 __pyx_t_5numpy_uint64_t;
  */
 typedef npy_float32 __pyx_t_5numpy_float32_t;
 
-/* "numpy.pxd":737
+/* "numpy.pxd":734
  * 
  * ctypedef npy_float32    float32_t
  * ctypedef npy_float64    float64_t             # <<<<<<<<<<<<<<
@@ -507,7 +436,7 @@ typedef npy_float32 __pyx_t_5numpy_float32_t;
  */
 typedef npy_float64 __pyx_t_5numpy_float64_t;
 
-/* "numpy.pxd":746
+/* "numpy.pxd":743
  * # The int types are mapped a bit surprising --
  * # numpy.int corresponds to 'l' and numpy.long to 'q'
  * ctypedef npy_long       int_t             # <<<<<<<<<<<<<<
@@ -516,7 +445,7 @@ typedef npy_float64 __pyx_t_5numpy_float64_t;
  */
 typedef npy_long __pyx_t_5numpy_int_t;
 
-/* "numpy.pxd":747
+/* "numpy.pxd":744
  * # numpy.int corresponds to 'l' and numpy.long to 'q'
  * ctypedef npy_long       int_t
  * ctypedef npy_longlong   long_t             # <<<<<<<<<<<<<<
@@ -525,7 +454,7 @@ typedef npy_long __pyx_t_5numpy_int_t;
  */
 typedef npy_longlong __pyx_t_5numpy_long_t;
 
-/* "numpy.pxd":748
+/* "numpy.pxd":745
  * ctypedef npy_long       int_t
  * ctypedef npy_longlong   long_t
  * ctypedef npy_longlong   longlong_t             # <<<<<<<<<<<<<<
@@ -534,7 +463,7 @@ typedef npy_longlong __pyx_t_5numpy_long_t;
  */
 typedef npy_longlong __pyx_t_5numpy_longlong_t;
 
-/* "numpy.pxd":750
+/* "numpy.pxd":747
  * ctypedef npy_longlong   longlong_t
  * 
  * ctypedef npy_ulong      uint_t             # <<<<<<<<<<<<<<
@@ -543,7 +472,7 @@ typedef npy_longlong __pyx_t_5numpy_longlong_t;
  */
 typedef npy_ulong __pyx_t_5numpy_uint_t;
 
-/* "numpy.pxd":751
+/* "numpy.pxd":748
  * 
  * ctypedef npy_ulong      uint_t
  * ctypedef npy_ulonglong  ulong_t             # <<<<<<<<<<<<<<
@@ -552,7 +481,7 @@ typedef npy_ulong __pyx_t_5numpy_uint_t;
  */
 typedef npy_ulonglong __pyx_t_5numpy_ulong_t;
 
-/* "numpy.pxd":752
+/* "numpy.pxd":749
  * ctypedef npy_ulong      uint_t
  * ctypedef npy_ulonglong  ulong_t
  * ctypedef npy_ulonglong  ulonglong_t             # <<<<<<<<<<<<<<
@@ -561,7 +490,7 @@ typedef npy_ulonglong __pyx_t_5numpy_ulong_t;
  */
 typedef npy_ulonglong __pyx_t_5numpy_ulonglong_t;
 
-/* "numpy.pxd":754
+/* "numpy.pxd":751
  * ctypedef npy_ulonglong  ulonglong_t
  * 
  * ctypedef npy_intp       intp_t             # <<<<<<<<<<<<<<
@@ -570,7 +499,7 @@ typedef npy_ulonglong __pyx_t_5numpy_ulonglong_t;
  */
 typedef npy_intp __pyx_t_5numpy_intp_t;
 
-/* "numpy.pxd":755
+/* "numpy.pxd":752
  * 
  * ctypedef npy_intp       intp_t
  * ctypedef npy_uintp      uintp_t             # <<<<<<<<<<<<<<
@@ -579,7 +508,7 @@ typedef npy_intp __pyx_t_5numpy_intp_t;
  */
 typedef npy_uintp __pyx_t_5numpy_uintp_t;
 
-/* "numpy.pxd":757
+/* "numpy.pxd":754
  * ctypedef npy_uintp      uintp_t
  * 
  * ctypedef npy_double     float_t             # <<<<<<<<<<<<<<
@@ -588,7 +517,7 @@ typedef npy_uintp __pyx_t_5numpy_uintp_t;
  */
 typedef npy_double __pyx_t_5numpy_float_t;
 
-/* "numpy.pxd":758
+/* "numpy.pxd":755
  * 
  * ctypedef npy_double     float_t
  * ctypedef npy_double     double_t             # <<<<<<<<<<<<<<
@@ -597,7 +526,7 @@ typedef npy_double __pyx_t_5numpy_float_t;
  */
 typedef npy_double __pyx_t_5numpy_double_t;
 
-/* "numpy.pxd":759
+/* "numpy.pxd":756
  * ctypedef npy_double     float_t
  * ctypedef npy_double     double_t
  * ctypedef npy_longdouble longdouble_t             # <<<<<<<<<<<<<<
@@ -614,6 +543,7 @@ typedef npy_longdouble __pyx_t_5numpy_longdouble_t;
  * cdef extern from "numpy/npy_math.h":
  */
 typedef __pyx_t_5numpy_float_t __pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t;
+
 #if CYTHON_CCOMPLEX
   #ifdef __cplusplus
     typedef ::std::complex< float > __pyx_t_float_complex;
@@ -634,10 +564,9 @@ typedef __pyx_t_5numpy_float_t __pyx_t_7astropy_6nddata_11convolution_13boundary
     typedef struct { double real, imag; } __pyx_t_double_complex;
 #endif
 
-
 /*--- Type declarations ---*/
 
-/* "numpy.pxd":761
+/* "numpy.pxd":758
  * ctypedef npy_longdouble longdouble_t
  * 
  * ctypedef npy_cfloat      cfloat_t             # <<<<<<<<<<<<<<
@@ -646,7 +575,7 @@ typedef __pyx_t_5numpy_float_t __pyx_t_7astropy_6nddata_11convolution_13boundary
  */
 typedef npy_cfloat __pyx_t_5numpy_cfloat_t;
 
-/* "numpy.pxd":762
+/* "numpy.pxd":759
  * 
  * ctypedef npy_cfloat      cfloat_t
  * ctypedef npy_cdouble     cdouble_t             # <<<<<<<<<<<<<<
@@ -655,7 +584,7 @@ typedef npy_cfloat __pyx_t_5numpy_cfloat_t;
  */
 typedef npy_cdouble __pyx_t_5numpy_cdouble_t;
 
-/* "numpy.pxd":763
+/* "numpy.pxd":760
  * ctypedef npy_cfloat      cfloat_t
  * ctypedef npy_cdouble     cdouble_t
  * ctypedef npy_clongdouble clongdouble_t             # <<<<<<<<<<<<<<
@@ -664,7 +593,7 @@ typedef npy_cdouble __pyx_t_5numpy_cdouble_t;
  */
 typedef npy_clongdouble __pyx_t_5numpy_clongdouble_t;
 
-/* "numpy.pxd":765
+/* "numpy.pxd":762
  * ctypedef npy_clongdouble clongdouble_t
  * 
  * ctypedef npy_cdouble     complex_t             # <<<<<<<<<<<<<<
@@ -672,9 +601,12 @@ typedef npy_clongdouble __pyx_t_5numpy_clongdouble_t;
  * cdef inline object PyArray_MultiIterNew1(a):
  */
 typedef npy_cdouble __pyx_t_5numpy_complex_t;
+
+
 #ifndef CYTHON_REFNANNY
   #define CYTHON_REFNANNY 0
 #endif
+
 #if CYTHON_REFNANNY
   typedef struct {
     void (*INCREF)(void*, PyObject*, int);
@@ -687,21 +619,8 @@ typedef npy_cdouble __pyx_t_5numpy_complex_t;
   static __Pyx_RefNannyAPIStruct *__Pyx_RefNanny = NULL;
   static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname); /*proto*/
   #define __Pyx_RefNannyDeclarations void *__pyx_refnanny = NULL;
-#ifdef WITH_THREAD
-  #define __Pyx_RefNannySetupContext(name, acquire_gil) \
-          if (acquire_gil) { \
-              PyGILState_STATE __pyx_gilstate_save = PyGILState_Ensure(); \
-              __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__); \
-              PyGILState_Release(__pyx_gilstate_save); \
-          } else { \
-              __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__); \
-          }
-#else
-  #define __Pyx_RefNannySetupContext(name, acquire_gil) \
-          __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__)
-#endif
-  #define __Pyx_RefNannyFinishContext() \
-          __Pyx_RefNanny->FinishContext(&__pyx_refnanny)
+  #define __Pyx_RefNannySetupContext(name)           __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__)
+  #define __Pyx_RefNannyFinishContext()           __Pyx_RefNanny->FinishContext(&__pyx_refnanny)
   #define __Pyx_INCREF(r)  __Pyx_RefNanny->INCREF(__pyx_refnanny, (PyObject *)(r), __LINE__)
   #define __Pyx_DECREF(r)  __Pyx_RefNanny->DECREF(__pyx_refnanny, (PyObject *)(r), __LINE__)
   #define __Pyx_GOTREF(r)  __Pyx_RefNanny->GOTREF(__pyx_refnanny, (PyObject *)(r), __LINE__)
@@ -712,7 +631,7 @@ typedef npy_cdouble __pyx_t_5numpy_complex_t;
   #define __Pyx_XGIVEREF(r) do { if((r) != NULL) {__Pyx_GIVEREF(r);}} while(0)
 #else
   #define __Pyx_RefNannyDeclarations
-  #define __Pyx_RefNannySetupContext(name, acquire_gil)
+  #define __Pyx_RefNannySetupContext(name)
   #define __Pyx_RefNannyFinishContext()
   #define __Pyx_INCREF(r) Py_INCREF(r)
   #define __Pyx_DECREF(r) Py_DECREF(r)
@@ -723,25 +642,43 @@ typedef npy_cdouble __pyx_t_5numpy_complex_t;
   #define __Pyx_XGOTREF(r)
   #define __Pyx_XGIVEREF(r)
 #endif /* CYTHON_REFNANNY */
-#define __Pyx_CLEAR(r)    do { PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);} while(0)
-#define __Pyx_XCLEAR(r)   do { if((r) != NULL) {PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);}} while(0)
 
 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/
 
 static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact,
     Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found); /*proto*/
 
-static void __Pyx_RaiseDoubleKeywordsError(const char* func_name, PyObject* kw_name); /*proto*/
+static void __Pyx_RaiseDoubleKeywordsError(
+    const char* func_name, PyObject* kw_name); /*proto*/
 
-static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[], \
-    PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args, \
-    const char* function_name); /*proto*/
+static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[],     PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args,     const char* function_name); /*proto*/
 
 static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
     const char *name, int exact); /*proto*/
 
-static CYTHON_INLINE int  __Pyx_GetBufferAndValidate(Py_buffer* buf, PyObject* obj,
-    __Pyx_TypeInfo* dtype, int flags, int nd, int cast, __Pyx_BufFmt_StackElem* stack);
+/* Run-time type information about structs used with buffers */
+struct __Pyx_StructField_;
+
+typedef struct {
+  const char* name; /* for error messages only */
+  struct __Pyx_StructField_* fields;
+  size_t size;     /* sizeof(type) */
+  char typegroup; /* _R_eal, _C_omplex, Signed _I_nt, _U_nsigned int, _S_truct, _P_ointer, _O_bject */
+} __Pyx_TypeInfo;
+
+typedef struct __Pyx_StructField_ {
+  __Pyx_TypeInfo* type;
+  const char* name;
+  size_t offset;
+} __Pyx_StructField;
+
+typedef struct {
+  __Pyx_StructField* field;
+  size_t parent_offset;
+} __Pyx_BufFmt_StackElem;
+
+
+static CYTHON_INLINE int  __Pyx_GetBufferAndValidate(Py_buffer* buf, PyObject* obj, __Pyx_TypeInfo* dtype, int flags, int nd, int cast, __Pyx_BufFmt_StackElem* stack);
 static CYTHON_INLINE void __Pyx_SafeReleaseBuffer(Py_buffer* info);
 
 static CYTHON_INLINE long __Pyx_mod_long(long, long); /* proto */
@@ -754,10 +691,10 @@ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject
 static CYTHON_INLINE long __Pyx_div_long(long, long); /* proto */
 
 static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); /*proto*/
-
 #define __Pyx_BufPtrStrided1d(type, buf, i0, s0) (type)((char*)buf + i0 * s0)
 #define __Pyx_BufPtrStrided2d(type, buf, i0, s0, i1, s1) (type)((char*)buf + i0 * s0 + i1 * s1)
 #define __Pyx_BufPtrStrided3d(type, buf, i0, s0, i1, s1, i2, s2) (type)((char*)buf + i0 * s0 + i1 * s1 + i2 * s2)
+
 static CYTHON_INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index);
 
 static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(Py_ssize_t expected);
@@ -765,30 +702,16 @@ static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(Py_ssize_t expected);
 static CYTHON_INLINE void __Pyx_RaiseNoneNotIterableError(void);
 
 static void __Pyx_UnpackTupleError(PyObject *, Py_ssize_t index); /*proto*/
-
-typedef struct {
-  Py_ssize_t shape, strides, suboffsets;
-} __Pyx_Buf_DimInfo;
-typedef struct {
-  size_t refcount;
-  Py_buffer pybuffer;
-} __Pyx_Buffer;
-typedef struct {
-  __Pyx_Buffer *rcbuffer;
-  char *data;
-  __Pyx_Buf_DimInfo diminfo[8];
-} __Pyx_LocalBuf_ND;
-
 #if PY_MAJOR_VERSION < 3
-    static int __Pyx_GetBuffer(PyObject *obj, Py_buffer *view, int flags);
-    static void __Pyx_ReleaseBuffer(Py_buffer *view);
+static int __Pyx_GetBuffer(PyObject *obj, Py_buffer *view, int flags);
+static void __Pyx_ReleaseBuffer(Py_buffer *view);
 #else
-    #define __Pyx_GetBuffer PyObject_GetBuffer
-    #define __Pyx_ReleaseBuffer PyBuffer_Release
+#define __Pyx_GetBuffer PyObject_GetBuffer
+#define __Pyx_ReleaseBuffer PyBuffer_Release
 #endif
 
-static Py_ssize_t __Pyx_zeros[] = {0, 0, 0, 0, 0, 0, 0, 0};
-static Py_ssize_t __Pyx_minusones[] = {-1, -1, -1, -1, -1, -1, -1, -1};
+Py_ssize_t __Pyx_zeros[] = {0, 0, 0};
+Py_ssize_t __Pyx_minusones[] = {-1, -1, -1};
 
 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, long level); /*proto*/
 
@@ -804,6 +727,7 @@ static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, long level);
     #define __Pyx_CREAL(z) ((z).real)
     #define __Pyx_CIMAG(z) ((z).imag)
 #endif
+
 #if defined(_WIN32) && defined(__cplusplus) && CYTHON_CCOMPLEX
     #define __Pyx_SET_CREAL(z,x) ((z).real(x))
     #define __Pyx_SET_CIMAG(z,y) ((z).imag(y))
@@ -924,38 +848,15 @@ static CYTHON_INLINE signed PY_LONG_LONG __Pyx_PyInt_AsSignedLongLong(PyObject *
 
 static int __Pyx_check_binary_version(void);
 
-#if !defined(__Pyx_PyIdentifier_FromString)
-#if PY_MAJOR_VERSION < 3
-  #define __Pyx_PyIdentifier_FromString(s) PyString_FromString(s)
-#else
-  #define __Pyx_PyIdentifier_FromString(s) PyUnicode_FromString(s)
-#endif
-#endif
-
 static PyTypeObject *__Pyx_ImportType(const char *module_name, const char *class_name, size_t size, int strict);  /*proto*/
 
 static PyObject *__Pyx_ImportModule(const char *name); /*proto*/
 
-typedef struct {
-    int code_line;
-    PyCodeObject* code_object;
-} __Pyx_CodeObjectCacheEntry;
-struct __Pyx_CodeObjectCache {
-    int count;
-    int max_count;
-    __Pyx_CodeObjectCacheEntry* entries;
-};
-static struct __Pyx_CodeObjectCache __pyx_code_cache = {0,0,NULL};
-static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line);
-static PyCodeObject *__pyx_find_code_object(int code_line);
-static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object);
-
-static void __Pyx_AddTraceback(const char *funcname, int c_line,
-                               int py_line, const char *filename); /*proto*/
+static void __Pyx_AddTraceback(const char *funcname, int __pyx_clineno,
+                               int __pyx_lineno, const char *__pyx_filename); /*proto*/
 
 static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); /*proto*/
 
-
 /* Module declarations from 'cpython.buffer' */
 
 /* Module declarations from 'cpython.ref' */
@@ -974,12 +875,21 @@ static PyTypeObject *__pyx_ptype_5numpy_flatiter = 0;
 static PyTypeObject *__pyx_ptype_5numpy_broadcast = 0;
 static PyTypeObject *__pyx_ptype_5numpy_ndarray = 0;
 static PyTypeObject *__pyx_ptype_5numpy_ufunc = 0;
+static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew1(PyObject *); /*proto*/
+static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew2(PyObject *, PyObject *); /*proto*/
+static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew3(PyObject *, PyObject *, PyObject *); /*proto*/
+static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew4(PyObject *, PyObject *, PyObject *, PyObject *); /*proto*/
+static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew5(PyObject *, PyObject *, PyObject *, PyObject *, PyObject *); /*proto*/
 static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *, char *, char *, int *); /*proto*/
+static CYTHON_INLINE void __pyx_f_5numpy_set_array_base(PyArrayObject *, PyObject *); /*proto*/
+static CYTHON_INLINE PyObject *__pyx_f_5numpy_get_array_base(PyArrayObject *); /*proto*/
+
+/* Module declarations from 'cython.cython.view' */
 
 /* Module declarations from 'cython' */
 
 /* Module declarations from 'astropy.nddata.convolution.boundary_fill' */
-static __Pyx_TypeInfo __Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t = { "DTYPE_t", NULL, sizeof(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t), { 0 }, 0, 'R', 0, 0 };
+static __Pyx_TypeInfo __Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t = { "DTYPE_t", NULL, sizeof(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t), 'R' };
 #define __Pyx_MODULE_NAME "astropy.nddata.convolution.boundary_fill"
 int __pyx_module_is_main_astropy__nddata__convolution__boundary_fill = 0;
 
@@ -987,11 +897,6 @@ int __pyx_module_is_main_astropy__nddata__convolution__boundary_fill = 0;
 static PyObject *__pyx_builtin_ValueError;
 static PyObject *__pyx_builtin_range;
 static PyObject *__pyx_builtin_RuntimeError;
-static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_convolve1d_boundary_fill(CYTHON_UNUSED PyObject *__pyx_self, PyArrayObject *__pyx_v_f, PyArrayObject *__pyx_v_g, float __pyx_v_fill_value); /* proto */
-static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_2convolve2d_boundary_fill(CYTHON_UNUSED PyObject *__pyx_self, PyArrayObject *__pyx_v_f, PyArrayObject *__pyx_v_g, float __pyx_v_fill_value); /* proto */
-static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_4convolve3d_boundary_fill(CYTHON_UNUSED PyObject *__pyx_self, PyArrayObject *__pyx_v_f, PyArrayObject *__pyx_v_g, float __pyx_v_fill_value); /* proto */
-static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags); /* proto */
-static void __pyx_pf_5numpy_7ndarray_2__releasebuffer__(PyArrayObject *__pyx_v_self, Py_buffer *__pyx_v_info); /* proto */
 static char __pyx_k_1[] = "Convolution kernel must have odd dimensions";
 static char __pyx_k_5[] = "ndarray is not C contiguous";
 static char __pyx_k_7[] = "ndarray is not Fortran contiguous";
@@ -999,11 +904,10 @@ static char __pyx_k_9[] = "Non-native byte order not supported";
 static char __pyx_k_11[] = "unknown dtype code in numpy.pxd (%d)";
 static char __pyx_k_12[] = "Format string allocated too short, see comment in numpy.pxd";
 static char __pyx_k_15[] = "Format string allocated too short.";
-static char __pyx_k_19[] = "convolve1d_boundary_fill";
-static char __pyx_k_20[] = "/Users/erik/src/astropy/astropy/nddata/convolution/boundary_fill.pyx";
-static char __pyx_k_21[] = "astropy.nddata.convolution.boundary_fill";
-static char __pyx_k_24[] = "convolve2d_boundary_fill";
-static char __pyx_k_27[] = "convolve3d_boundary_fill";
+static char __pyx_k_17[] = "astropy.nddata.convolution.boundary_fill";
+static char __pyx_k_18[] = "convolve1d_boundary_fill";
+static char __pyx_k_19[] = "convolve2d_boundary_fill";
+static char __pyx_k_20[] = "convolve3d_boundary_fill";
 static char __pyx_k__B[] = "B";
 static char __pyx_k__H[] = "H";
 static char __pyx_k__I[] = "I";
@@ -1016,45 +920,16 @@ static char __pyx_k__f[] = "f";
 static char __pyx_k__g[] = "g";
 static char __pyx_k__h[] = "h";
 static char __pyx_k__i[] = "i";
-static char __pyx_k__j[] = "j";
-static char __pyx_k__k[] = "k";
 static char __pyx_k__l[] = "l";
 static char __pyx_k__q[] = "q";
 static char __pyx_k__Zd[] = "Zd";
 static char __pyx_k__Zf[] = "Zf";
 static char __pyx_k__Zg[] = "Zg";
-static char __pyx_k__ii[] = "ii";
-static char __pyx_k__jj[] = "jj";
-static char __pyx_k__kk[] = "kk";
 static char __pyx_k__np[] = "np";
-static char __pyx_k__nx[] = "nx";
-static char __pyx_k__ny[] = "ny";
-static char __pyx_k__nz[] = "nz";
-static char __pyx_k__bot[] = "bot";
-static char __pyx_k__iii[] = "iii";
-static char __pyx_k__jjj[] = "jjj";
-static char __pyx_k__ker[] = "ker";
-static char __pyx_k__kkk[] = "kkk";
-static char __pyx_k__nkx[] = "nkx";
-static char __pyx_k__nky[] = "nky";
-static char __pyx_k__nkz[] = "nkz";
-static char __pyx_k__top[] = "top";
-static char __pyx_k__val[] = "val";
-static char __pyx_k__wkx[] = "wkx";
-static char __pyx_k__wky[] = "wky";
-static char __pyx_k__wkz[] = "wkz";
-static char __pyx_k__conv[] = "conv";
 static char __pyx_k__DTYPE[] = "DTYPE";
 static char __pyx_k__dtype[] = "dtype";
 static char __pyx_k__empty[] = "empty";
-static char __pyx_k__fixed[] = "fixed";
 static char __pyx_k__float[] = "float";
-static char __pyx_k__iimax[] = "iimax";
-static char __pyx_k__iimin[] = "iimin";
-static char __pyx_k__jjmax[] = "jjmax";
-static char __pyx_k__jjmin[] = "jjmin";
-static char __pyx_k__kkmax[] = "kkmax";
-static char __pyx_k__kkmin[] = "kkmin";
 static char __pyx_k__numpy[] = "numpy";
 static char __pyx_k__range[] = "range";
 static char __pyx_k____main__[] = "__main__";
@@ -1066,11 +941,10 @@ static PyObject *__pyx_kp_s_1;
 static PyObject *__pyx_kp_u_11;
 static PyObject *__pyx_kp_u_12;
 static PyObject *__pyx_kp_u_15;
+static PyObject *__pyx_n_s_17;
+static PyObject *__pyx_n_s_18;
 static PyObject *__pyx_n_s_19;
-static PyObject *__pyx_kp_s_20;
-static PyObject *__pyx_n_s_21;
-static PyObject *__pyx_n_s_24;
-static PyObject *__pyx_n_s_27;
+static PyObject *__pyx_n_s_20;
 static PyObject *__pyx_kp_u_5;
 static PyObject *__pyx_kp_u_7;
 static PyObject *__pyx_kp_u_9;
@@ -1079,45 +953,15 @@ static PyObject *__pyx_n_s__RuntimeError;
 static PyObject *__pyx_n_s__ValueError;
 static PyObject *__pyx_n_s____main__;
 static PyObject *__pyx_n_s____test__;
-static PyObject *__pyx_n_s__bot;
-static PyObject *__pyx_n_s__conv;
 static PyObject *__pyx_n_s__dtype;
 static PyObject *__pyx_n_s__empty;
 static PyObject *__pyx_n_s__f;
 static PyObject *__pyx_n_s__fill_value;
-static PyObject *__pyx_n_s__fixed;
 static PyObject *__pyx_n_s__float;
 static PyObject *__pyx_n_s__g;
-static PyObject *__pyx_n_s__i;
-static PyObject *__pyx_n_s__ii;
-static PyObject *__pyx_n_s__iii;
-static PyObject *__pyx_n_s__iimax;
-static PyObject *__pyx_n_s__iimin;
-static PyObject *__pyx_n_s__j;
-static PyObject *__pyx_n_s__jj;
-static PyObject *__pyx_n_s__jjj;
-static PyObject *__pyx_n_s__jjmax;
-static PyObject *__pyx_n_s__jjmin;
-static PyObject *__pyx_n_s__k;
-static PyObject *__pyx_n_s__ker;
-static PyObject *__pyx_n_s__kk;
-static PyObject *__pyx_n_s__kkk;
-static PyObject *__pyx_n_s__kkmax;
-static PyObject *__pyx_n_s__kkmin;
-static PyObject *__pyx_n_s__nkx;
-static PyObject *__pyx_n_s__nky;
-static PyObject *__pyx_n_s__nkz;
 static PyObject *__pyx_n_s__np;
 static PyObject *__pyx_n_s__numpy;
-static PyObject *__pyx_n_s__nx;
-static PyObject *__pyx_n_s__ny;
-static PyObject *__pyx_n_s__nz;
 static PyObject *__pyx_n_s__range;
-static PyObject *__pyx_n_s__top;
-static PyObject *__pyx_n_s__val;
-static PyObject *__pyx_n_s__wkx;
-static PyObject *__pyx_n_s__wky;
-static PyObject *__pyx_n_s__wkz;
 static PyObject *__pyx_int_15;
 static PyObject *__pyx_k_tuple_2;
 static PyObject *__pyx_k_tuple_3;
@@ -1128,88 +972,6 @@ static PyObject *__pyx_k_tuple_10;
 static PyObject *__pyx_k_tuple_13;
 static PyObject *__pyx_k_tuple_14;
 static PyObject *__pyx_k_tuple_16;
-static PyObject *__pyx_k_tuple_17;
-static PyObject *__pyx_k_tuple_22;
-static PyObject *__pyx_k_tuple_25;
-static PyObject *__pyx_k_codeobj_18;
-static PyObject *__pyx_k_codeobj_23;
-static PyObject *__pyx_k_codeobj_26;
-
-/* Python wrapper */
-static PyObject *__pyx_pw_7astropy_6nddata_11convolution_13boundary_fill_1convolve1d_boundary_fill(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static PyMethodDef __pyx_mdef_7astropy_6nddata_11convolution_13boundary_fill_1convolve1d_boundary_fill = {__Pyx_NAMESTR("convolve1d_boundary_fill"), (PyCFunction)__pyx_pw_7astropy_6nddata_11convolution_13boundary_fill_1convolve1d_boundary_fill, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(0)};
-static PyObject *__pyx_pw_7astropy_6nddata_11convolution_13boundary_fill_1convolve1d_boundary_fill(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
-  PyArrayObject *__pyx_v_f = 0;
-  PyArrayObject *__pyx_v_g = 0;
-  float __pyx_v_fill_value;
-  static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__f,&__pyx_n_s__g,&__pyx_n_s__fill_value,0};
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("convolve1d_boundary_fill (wrapper)", 0);
-  __pyx_self = __pyx_self;
-  {
-    PyObject* values[3] = {0,0,0};
-    if (unlikely(__pyx_kwds)) {
-      Py_ssize_t kw_args;
-      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
-      switch (pos_args) {
-        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
-        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
-        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
-        case  0: break;
-        default: goto __pyx_L5_argtuple_error;
-      }
-      kw_args = PyDict_Size(__pyx_kwds);
-      switch (pos_args) {
-        case  0:
-        values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__f);
-        if (likely(values[0])) kw_args--;
-        else goto __pyx_L5_argtuple_error;
-        case  1:
-        values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__g);
-        if (likely(values[1])) kw_args--;
-        else {
-          __Pyx_RaiseArgtupleInvalid("convolve1d_boundary_fill", 1, 3, 3, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-        }
-        case  2:
-        values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__fill_value);
-        if (likely(values[2])) kw_args--;
-        else {
-          __Pyx_RaiseArgtupleInvalid("convolve1d_boundary_fill", 1, 3, 3, 2); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-        }
-      }
-      if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "convolve1d_boundary_fill") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-      }
-    } else if (PyTuple_GET_SIZE(__pyx_args) != 3) {
-      goto __pyx_L5_argtuple_error;
-    } else {
-      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
-      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
-      values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
-    }
-    __pyx_v_f = ((PyArrayObject *)values[0]);
-    __pyx_v_g = ((PyArrayObject *)values[1]);
-    __pyx_v_fill_value = __pyx_PyFloat_AsFloat(values[2]); if (unlikely((__pyx_v_fill_value == (float)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 17; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-  }
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("convolve1d_boundary_fill", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-  __pyx_L3_error:;
-  __Pyx_AddTraceback("astropy.nddata.convolution.boundary_fill.convolve1d_boundary_fill", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return NULL;
-  __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_f), __pyx_ptype_5numpy_ndarray, 1, "f", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_g), __pyx_ptype_5numpy_ndarray, 1, "g", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 16; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_r = __pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_convolve1d_boundary_fill(__pyx_self, __pyx_v_f, __pyx_v_g, __pyx_v_fill_value);
-  goto __pyx_L0;
-  __pyx_L1_error:;
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
 
 /* "astropy/nddata/convolution/boundary_fill.pyx":15
  * 
@@ -1219,7 +981,12 @@ static PyObject *__pyx_pw_7astropy_6nddata_11convolution_13boundary_fill_1convol
  *                              float fill_value):
  */
 
-static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_convolve1d_boundary_fill(CYTHON_UNUSED PyObject *__pyx_self, PyArrayObject *__pyx_v_f, PyArrayObject *__pyx_v_g, float __pyx_v_fill_value) {
+static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_convolve1d_boundary_fill(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static PyMethodDef __pyx_mdef_7astropy_6nddata_11convolution_13boundary_fill_convolve1d_boundary_fill = {__Pyx_NAMESTR("convolve1d_boundary_fill"), (PyCFunction)__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_convolve1d_boundary_fill, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(0)};
+static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_convolve1d_boundary_fill(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyArrayObject *__pyx_v_f = 0;
+  PyArrayObject *__pyx_v_g = 0;
+  float __pyx_v_fill_value;
   int __pyx_v_nx;
   int __pyx_v_nkx;
   int __pyx_v_wkx;
@@ -1233,14 +1000,18 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_convolv
   __pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t __pyx_v_bot;
   __pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t __pyx_v_ker;
   __pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t __pyx_v_val;
-  __Pyx_LocalBuf_ND __pyx_pybuffernd_conv;
-  __Pyx_Buffer __pyx_pybuffer_conv;
-  __Pyx_LocalBuf_ND __pyx_pybuffernd_f;
-  __Pyx_Buffer __pyx_pybuffer_f;
-  __Pyx_LocalBuf_ND __pyx_pybuffernd_fixed;
-  __Pyx_Buffer __pyx_pybuffer_fixed;
-  __Pyx_LocalBuf_ND __pyx_pybuffernd_g;
-  __Pyx_Buffer __pyx_pybuffer_g;
+  Py_buffer __pyx_bstruct_conv;
+  Py_ssize_t __pyx_bstride_0_conv = 0;
+  Py_ssize_t __pyx_bshape_0_conv = 0;
+  Py_buffer __pyx_bstruct_g;
+  Py_ssize_t __pyx_bstride_0_g = 0;
+  Py_ssize_t __pyx_bshape_0_g = 0;
+  Py_buffer __pyx_bstruct_f;
+  Py_ssize_t __pyx_bstride_0_f = 0;
+  Py_ssize_t __pyx_bshape_0_f = 0;
+  Py_buffer __pyx_bstruct_fixed;
+  Py_ssize_t __pyx_bstride_0_fixed = 0;
+  Py_ssize_t __pyx_bshape_0_fixed = 0;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   int __pyx_t_1;
@@ -1275,33 +1046,79 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_convolv
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("convolve1d_boundary_fill", 0);
-  __pyx_pybuffer_fixed.pybuffer.buf = NULL;
-  __pyx_pybuffer_fixed.refcount = 0;
-  __pyx_pybuffernd_fixed.data = NULL;
-  __pyx_pybuffernd_fixed.rcbuffer = &__pyx_pybuffer_fixed;
-  __pyx_pybuffer_conv.pybuffer.buf = NULL;
-  __pyx_pybuffer_conv.refcount = 0;
-  __pyx_pybuffernd_conv.data = NULL;
-  __pyx_pybuffernd_conv.rcbuffer = &__pyx_pybuffer_conv;
-  __pyx_pybuffer_f.pybuffer.buf = NULL;
-  __pyx_pybuffer_f.refcount = 0;
-  __pyx_pybuffernd_f.data = NULL;
-  __pyx_pybuffernd_f.rcbuffer = &__pyx_pybuffer_f;
-  __pyx_pybuffer_g.pybuffer.buf = NULL;
-  __pyx_pybuffer_g.refcount = 0;
-  __pyx_pybuffernd_g.data = NULL;
-  __pyx_pybuffernd_g.rcbuffer = &__pyx_pybuffer_g;
+  static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__f,&__pyx_n_s__g,&__pyx_n_s__fill_value,0};
+  __Pyx_RefNannySetupContext("convolve1d_boundary_fill");
+  __pyx_self = __pyx_self;
+  {
+    PyObject* values[3] = {0,0,0};
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  0:
+        values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__f);
+        if (likely(values[0])) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+        case  1:
+        values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__g);
+        if (likely(values[1])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("convolve1d_boundary_fill", 1, 3, 3, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+        case  2:
+        values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__fill_value);
+        if (likely(values[2])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("convolve1d_boundary_fill", 1, 3, 3, 2); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "convolve1d_boundary_fill") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+    } else if (PyTuple_GET_SIZE(__pyx_args) != 3) {
+      goto __pyx_L5_argtuple_error;
+    } else {
+      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+      values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+    }
+    __pyx_v_f = ((PyArrayObject *)values[0]);
+    __pyx_v_g = ((PyArrayObject *)values[1]);
+    __pyx_v_fill_value = __pyx_PyFloat_AsDouble(values[2]); if (unlikely((__pyx_v_fill_value == (float)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 17; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("convolve1d_boundary_fill", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("astropy.nddata.convolution.boundary_fill.convolve1d_boundary_fill", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_bstruct_fixed.buf = NULL;
+  __pyx_bstruct_conv.buf = NULL;
+  __pyx_bstruct_f.buf = NULL;
+  __pyx_bstruct_g.buf = NULL;
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_f), __pyx_ptype_5numpy_ndarray, 1, "f", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_g), __pyx_ptype_5numpy_ndarray, 1, "g", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 16; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_f.rcbuffer->pybuffer, (PyObject*)__pyx_v_f, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_f, (PyObject*)__pyx_v_f, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
-  __pyx_pybuffernd_f.diminfo[0].strides = __pyx_pybuffernd_f.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_f.diminfo[0].shape = __pyx_pybuffernd_f.rcbuffer->pybuffer.shape[0];
+  __pyx_bstride_0_f = __pyx_bstruct_f.strides[0];
+  __pyx_bshape_0_f = __pyx_bstruct_f.shape[0];
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_g.rcbuffer->pybuffer, (PyObject*)__pyx_v_g, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_g, (PyObject*)__pyx_v_g, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
-  __pyx_pybuffernd_g.diminfo[0].strides = __pyx_pybuffernd_g.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_g.diminfo[0].shape = __pyx_pybuffernd_g.rcbuffer->pybuffer.shape[0];
+  __pyx_bstride_0_g = __pyx_bstruct_g.strides[0];
+  __pyx_bshape_0_g = __pyx_bstruct_g.shape[0];
 
   /* "astropy/nddata/convolution/boundary_fill.pyx":19
  *                              float fill_value):
@@ -1325,9 +1142,9 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_convolv
     __Pyx_Raise(__pyx_t_2, 0, 0, 0);
     __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
     {__pyx_filename = __pyx_f[0]; __pyx_lineno = 20; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    goto __pyx_L3;
+    goto __pyx_L6;
   }
-  __pyx_L3:;
+  __pyx_L6:;
 
   /* "astropy/nddata/convolution/boundary_fill.pyx":22
  *         raise ValueError("Convolution kernel must have odd dimensions")
@@ -1410,12 +1227,12 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_convolv
   __pyx_t_2 = PyInt_FromLong(__pyx_v_nx); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
   __pyx_t_4 = PyList_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_4);
+  __Pyx_GOTREF(((PyObject *)__pyx_t_4));
   PyList_SET_ITEM(__pyx_t_4, 0, __pyx_t_2);
   __Pyx_GIVEREF(__pyx_t_2);
   __pyx_t_2 = 0;
   __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_GOTREF(((PyObject *)__pyx_t_2));
   PyTuple_SET_ITEM(__pyx_t_2, 0, ((PyObject *)__pyx_t_4));
   __Pyx_GIVEREF(((PyObject *)__pyx_t_4));
   __pyx_t_4 = 0;
@@ -1425,7 +1242,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_convolv
   __Pyx_GOTREF(__pyx_t_7);
   if (PyDict_SetItem(__pyx_t_4, ((PyObject *)__pyx_n_s__dtype), __pyx_t_7) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-  __pyx_t_7 = PyObject_Call(__pyx_t_3, ((PyObject *)__pyx_t_2), ((PyObject *)__pyx_t_4)); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_7 = PyEval_CallObjectWithKeywords(__pyx_t_3, ((PyObject *)__pyx_t_2), ((PyObject *)__pyx_t_4)); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_7);
   __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
   __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
@@ -1434,10 +1251,11 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_convolv
   __pyx_t_8 = ((PyArrayObject *)__pyx_t_7);
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_fixed.rcbuffer->pybuffer, (PyObject*)__pyx_t_8, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 1, 0, __pyx_stack) == -1)) {
-      __pyx_v_fixed = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf = NULL;
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_fixed, (PyObject*)__pyx_t_8, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 1, 0, __pyx_stack) == -1)) {
+      __pyx_v_fixed = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_fixed.buf = NULL;
       {__pyx_filename = __pyx_f[0]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    } else {__pyx_pybuffernd_fixed.diminfo[0].strides = __pyx_pybuffernd_fixed.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_fixed.diminfo[0].shape = __pyx_pybuffernd_fixed.rcbuffer->pybuffer.shape[0];
+    } else {__pyx_bstride_0_fixed = __pyx_bstruct_fixed.strides[0];
+      __pyx_bshape_0_fixed = __pyx_bstruct_fixed.shape[0];
     }
   }
   __pyx_t_8 = 0;
@@ -1459,12 +1277,12 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_convolv
   __pyx_t_7 = PyInt_FromLong(__pyx_v_nx); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 28; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_7);
   __pyx_t_2 = PyList_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 28; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_GOTREF(((PyObject *)__pyx_t_2));
   PyList_SET_ITEM(__pyx_t_2, 0, __pyx_t_7);
   __Pyx_GIVEREF(__pyx_t_7);
   __pyx_t_7 = 0;
   __pyx_t_7 = PyTuple_New(1); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 28; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_7);
+  __Pyx_GOTREF(((PyObject *)__pyx_t_7));
   PyTuple_SET_ITEM(__pyx_t_7, 0, ((PyObject *)__pyx_t_2));
   __Pyx_GIVEREF(((PyObject *)__pyx_t_2));
   __pyx_t_2 = 0;
@@ -1474,7 +1292,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_convolv
   __Pyx_GOTREF(__pyx_t_3);
   if (PyDict_SetItem(__pyx_t_2, ((PyObject *)__pyx_n_s__dtype), __pyx_t_3) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 28; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  __pyx_t_3 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_t_7), ((PyObject *)__pyx_t_2)); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 28; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_3 = PyEval_CallObjectWithKeywords(__pyx_t_4, ((PyObject *)__pyx_t_7), ((PyObject *)__pyx_t_2)); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 28; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_3);
   __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
   __Pyx_DECREF(((PyObject *)__pyx_t_7)); __pyx_t_7 = 0;
@@ -1483,10 +1301,11 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_convolv
   __pyx_t_9 = ((PyArrayObject *)__pyx_t_3);
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_conv.rcbuffer->pybuffer, (PyObject*)__pyx_t_9, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 1, 0, __pyx_stack) == -1)) {
-      __pyx_v_conv = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_conv.rcbuffer->pybuffer.buf = NULL;
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_conv, (PyObject*)__pyx_t_9, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 1, 0, __pyx_stack) == -1)) {
+      __pyx_v_conv = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_conv.buf = NULL;
       {__pyx_filename = __pyx_f[0]; __pyx_lineno = 28; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    } else {__pyx_pybuffernd_conv.diminfo[0].strides = __pyx_pybuffernd_conv.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_conv.diminfo[0].shape = __pyx_pybuffernd_conv.rcbuffer->pybuffer.shape[0];
+    } else {__pyx_bstride_0_conv = __pyx_bstruct_conv.strides[0];
+      __pyx_bshape_0_conv = __pyx_bstruct_conv.shape[0];
     }
   }
   __pyx_t_9 = 0;
@@ -1512,7 +1331,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_convolv
  *             bot = 0.
  */
     __pyx_t_12 = __pyx_v_i;
-    __pyx_t_6 = npy_isnan((*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_pybuffernd_f.rcbuffer->pybuffer.buf, __pyx_t_12, __pyx_pybuffernd_f.diminfo[0].strides)));
+    __pyx_t_6 = npy_isnan((*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_bstruct_f.buf, __pyx_t_12, __pyx_bstride_0_f)));
     if (__pyx_t_6) {
 
       /* "astropy/nddata/convolution/boundary_fill.pyx":40
@@ -1586,7 +1405,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_convolv
  *                     val = f[ii]
  */
           __pyx_v_val = __pyx_v_fill_value;
-          goto __pyx_L9;
+          goto __pyx_L12;
         }
         /*else*/ {
 
@@ -1598,10 +1417,10 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_convolv
  *                     ker = g[<unsigned int>(wkx + ii - i)]
  */
           __pyx_t_15 = __pyx_v_ii;
-          if (__pyx_t_15 < 0) __pyx_t_15 += __pyx_pybuffernd_f.diminfo[0].shape;
-          __pyx_v_val = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_pybuffernd_f.rcbuffer->pybuffer.buf, __pyx_t_15, __pyx_pybuffernd_f.diminfo[0].strides));
+          if (__pyx_t_15 < 0) __pyx_t_15 += __pyx_bshape_0_f;
+          __pyx_v_val = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_bstruct_f.buf, __pyx_t_15, __pyx_bstride_0_f));
         }
-        __pyx_L9:;
+        __pyx_L12:;
 
         /* "astropy/nddata/convolution/boundary_fill.pyx":49
  *                 else:
@@ -1621,7 +1440,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_convolv
  *                     bot += ker
  */
           __pyx_t_16 = ((unsigned int)((__pyx_v_wkx + __pyx_v_ii) - __pyx_v_i));
-          __pyx_v_ker = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_pybuffernd_g.rcbuffer->pybuffer.buf, __pyx_t_16, __pyx_pybuffernd_g.diminfo[0].strides));
+          __pyx_v_ker = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_bstruct_g.buf, __pyx_t_16, __pyx_bstride_0_g));
 
           /* "astropy/nddata/convolution/boundary_fill.pyx":51
  *                 if not npy_isnan(val):
@@ -1640,9 +1459,9 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_convolv
  *                 fixed[i] = top / bot
  */
           __pyx_v_bot = (__pyx_v_bot + __pyx_v_ker);
-          goto __pyx_L10;
+          goto __pyx_L13;
         }
-        __pyx_L10:;
+        __pyx_L13:;
       }
 
       /* "astropy/nddata/convolution/boundary_fill.pyx":53
@@ -1667,8 +1486,8 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_convolv
           {__pyx_filename = __pyx_f[0]; __pyx_lineno = 54; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         }
         __pyx_t_17 = __pyx_v_i;
-        *__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_17, __pyx_pybuffernd_fixed.diminfo[0].strides) = (__pyx_v_top / __pyx_v_bot);
-        goto __pyx_L11;
+        *__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_17, __pyx_bstride_0_fixed) = (__pyx_v_top / __pyx_v_bot);
+        goto __pyx_L14;
       }
       /*else*/ {
 
@@ -1681,10 +1500,10 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_convolv
  */
         __pyx_t_18 = __pyx_v_i;
         __pyx_t_19 = __pyx_v_i;
-        *__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_19, __pyx_pybuffernd_fixed.diminfo[0].strides) = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_pybuffernd_f.rcbuffer->pybuffer.buf, __pyx_t_18, __pyx_pybuffernd_f.diminfo[0].strides));
+        *__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_19, __pyx_bstride_0_fixed) = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_bstruct_f.buf, __pyx_t_18, __pyx_bstride_0_f));
       }
-      __pyx_L11:;
-      goto __pyx_L6;
+      __pyx_L14:;
+      goto __pyx_L9;
     }
     /*else*/ {
 
@@ -1697,9 +1516,9 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_convolv
  */
       __pyx_t_20 = __pyx_v_i;
       __pyx_t_21 = __pyx_v_i;
-      *__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_21, __pyx_pybuffernd_fixed.diminfo[0].strides) = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_pybuffernd_f.rcbuffer->pybuffer.buf, __pyx_t_20, __pyx_pybuffernd_f.diminfo[0].strides));
+      *__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_21, __pyx_bstride_0_fixed) = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_bstruct_f.buf, __pyx_t_20, __pyx_bstride_0_f));
     }
-    __pyx_L6:;
+    __pyx_L9:;
   }
 
   /* "astropy/nddata/convolution/boundary_fill.pyx":61
@@ -1721,7 +1540,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_convolv
  *             bot = 0.
  */
     __pyx_t_22 = __pyx_v_i;
-    __pyx_t_5 = (!npy_isnan((*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_22, __pyx_pybuffernd_fixed.diminfo[0].strides))));
+    __pyx_t_5 = (!npy_isnan((*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_22, __pyx_bstride_0_fixed))));
     if (__pyx_t_5) {
 
       /* "astropy/nddata/convolution/boundary_fill.pyx":63
@@ -1795,7 +1614,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_convolv
  *                     val = fixed[ii]
  */
           __pyx_v_val = __pyx_v_fill_value;
-          goto __pyx_L17;
+          goto __pyx_L20;
         }
         /*else*/ {
 
@@ -1807,10 +1626,10 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_convolv
  *                 if not npy_isnan(val):
  */
           __pyx_t_23 = __pyx_v_ii;
-          if (__pyx_t_23 < 0) __pyx_t_23 += __pyx_pybuffernd_fixed.diminfo[0].shape;
-          __pyx_v_val = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_23, __pyx_pybuffernd_fixed.diminfo[0].strides));
+          if (__pyx_t_23 < 0) __pyx_t_23 += __pyx_bshape_0_fixed;
+          __pyx_v_val = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_23, __pyx_bstride_0_fixed));
         }
-        __pyx_L17:;
+        __pyx_L20:;
 
         /* "astropy/nddata/convolution/boundary_fill.pyx":72
  *                 else:
@@ -1820,7 +1639,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_convolv
  *                     top += val * ker
  */
         __pyx_t_24 = ((unsigned int)((__pyx_v_wkx + __pyx_v_ii) - __pyx_v_i));
-        __pyx_v_ker = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_pybuffernd_g.rcbuffer->pybuffer.buf, __pyx_t_24, __pyx_pybuffernd_g.diminfo[0].strides));
+        __pyx_v_ker = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_bstruct_g.buf, __pyx_t_24, __pyx_bstride_0_g));
 
         /* "astropy/nddata/convolution/boundary_fill.pyx":73
  *                     val = fixed[ii]
@@ -1849,9 +1668,9 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_convolv
  *                 conv[i] = top / bot
  */
           __pyx_v_bot = (__pyx_v_bot + __pyx_v_ker);
-          goto __pyx_L18;
+          goto __pyx_L21;
         }
-        __pyx_L18:;
+        __pyx_L21:;
       }
 
       /* "astropy/nddata/convolution/boundary_fill.pyx":76
@@ -1876,8 +1695,8 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_convolv
           {__pyx_filename = __pyx_f[0]; __pyx_lineno = 77; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         }
         __pyx_t_25 = __pyx_v_i;
-        *__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_pybuffernd_conv.rcbuffer->pybuffer.buf, __pyx_t_25, __pyx_pybuffernd_conv.diminfo[0].strides) = (__pyx_v_top / __pyx_v_bot);
-        goto __pyx_L19;
+        *__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_bstruct_conv.buf, __pyx_t_25, __pyx_bstride_0_conv) = (__pyx_v_top / __pyx_v_bot);
+        goto __pyx_L22;
       }
       /*else*/ {
 
@@ -1890,10 +1709,10 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_convolv
  */
         __pyx_t_26 = __pyx_v_i;
         __pyx_t_27 = __pyx_v_i;
-        *__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_pybuffernd_conv.rcbuffer->pybuffer.buf, __pyx_t_27, __pyx_pybuffernd_conv.diminfo[0].strides) = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_26, __pyx_pybuffernd_fixed.diminfo[0].strides));
+        *__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_bstruct_conv.buf, __pyx_t_27, __pyx_bstride_0_conv) = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_26, __pyx_bstride_0_fixed));
       }
-      __pyx_L19:;
-      goto __pyx_L14;
+      __pyx_L22:;
+      goto __pyx_L17;
     }
     /*else*/ {
 
@@ -1906,9 +1725,9 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_convolv
  */
       __pyx_t_28 = __pyx_v_i;
       __pyx_t_29 = __pyx_v_i;
-      *__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_pybuffernd_conv.rcbuffer->pybuffer.buf, __pyx_t_29, __pyx_pybuffernd_conv.diminfo[0].strides) = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_28, __pyx_pybuffernd_fixed.diminfo[0].strides));
+      *__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_bstruct_conv.buf, __pyx_t_29, __pyx_bstride_0_conv) = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_28, __pyx_bstride_0_fixed));
     }
-    __pyx_L14:;
+    __pyx_L17:;
   }
 
   /* "astropy/nddata/convolution/boundary_fill.pyx":83
@@ -1932,19 +1751,19 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_convolv
   __Pyx_XDECREF(__pyx_t_7);
   { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;
     __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);
-    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_conv.rcbuffer->pybuffer);
-    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_f.rcbuffer->pybuffer);
-    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_fixed.rcbuffer->pybuffer);
-    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_g.rcbuffer->pybuffer);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_conv);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_g);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_f);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_fixed);
   __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
   __Pyx_AddTraceback("astropy.nddata.convolution.boundary_fill.convolve1d_boundary_fill", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   goto __pyx_L2;
   __pyx_L0:;
-  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_conv.rcbuffer->pybuffer);
-  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_f.rcbuffer->pybuffer);
-  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_fixed.rcbuffer->pybuffer);
-  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_g.rcbuffer->pybuffer);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_conv);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_g);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_f);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_fixed);
   __pyx_L2:;
   __Pyx_XDECREF((PyObject *)__pyx_v_fixed);
   __Pyx_XDECREF((PyObject *)__pyx_v_conv);
@@ -1953,82 +1772,6 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_convolv
   return __pyx_r;
 }
 
-/* Python wrapper */
-static PyObject *__pyx_pw_7astropy_6nddata_11convolution_13boundary_fill_3convolve2d_boundary_fill(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static PyMethodDef __pyx_mdef_7astropy_6nddata_11convolution_13boundary_fill_3convolve2d_boundary_fill = {__Pyx_NAMESTR("convolve2d_boundary_fill"), (PyCFunction)__pyx_pw_7astropy_6nddata_11convolution_13boundary_fill_3convolve2d_boundary_fill, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(0)};
-static PyObject *__pyx_pw_7astropy_6nddata_11convolution_13boundary_fill_3convolve2d_boundary_fill(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
-  PyArrayObject *__pyx_v_f = 0;
-  PyArrayObject *__pyx_v_g = 0;
-  float __pyx_v_fill_value;
-  static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__f,&__pyx_n_s__g,&__pyx_n_s__fill_value,0};
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("convolve2d_boundary_fill (wrapper)", 0);
-  __pyx_self = __pyx_self;
-  {
-    PyObject* values[3] = {0,0,0};
-    if (unlikely(__pyx_kwds)) {
-      Py_ssize_t kw_args;
-      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
-      switch (pos_args) {
-        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
-        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
-        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
-        case  0: break;
-        default: goto __pyx_L5_argtuple_error;
-      }
-      kw_args = PyDict_Size(__pyx_kwds);
-      switch (pos_args) {
-        case  0:
-        values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__f);
-        if (likely(values[0])) kw_args--;
-        else goto __pyx_L5_argtuple_error;
-        case  1:
-        values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__g);
-        if (likely(values[1])) kw_args--;
-        else {
-          __Pyx_RaiseArgtupleInvalid("convolve2d_boundary_fill", 1, 3, 3, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 87; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-        }
-        case  2:
-        values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__fill_value);
-        if (likely(values[2])) kw_args--;
-        else {
-          __Pyx_RaiseArgtupleInvalid("convolve2d_boundary_fill", 1, 3, 3, 2); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 87; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-        }
-      }
-      if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "convolve2d_boundary_fill") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 87; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-      }
-    } else if (PyTuple_GET_SIZE(__pyx_args) != 3) {
-      goto __pyx_L5_argtuple_error;
-    } else {
-      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
-      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
-      values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
-    }
-    __pyx_v_f = ((PyArrayObject *)values[0]);
-    __pyx_v_g = ((PyArrayObject *)values[1]);
-    __pyx_v_fill_value = __pyx_PyFloat_AsFloat(values[2]); if (unlikely((__pyx_v_fill_value == (float)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 89; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-  }
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("convolve2d_boundary_fill", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 87; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-  __pyx_L3_error:;
-  __Pyx_AddTraceback("astropy.nddata.convolution.boundary_fill.convolve2d_boundary_fill", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return NULL;
-  __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_f), __pyx_ptype_5numpy_ndarray, 1, "f", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 87; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_g), __pyx_ptype_5numpy_ndarray, 1, "g", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 88; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_r = __pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_2convolve2d_boundary_fill(__pyx_self, __pyx_v_f, __pyx_v_g, __pyx_v_fill_value);
-  goto __pyx_L0;
-  __pyx_L1_error:;
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
 /* "astropy/nddata/convolution/boundary_fill.pyx":87
  * 
  * @cython.boundscheck(False)  # turn off bounds-checking for entire function
@@ -2037,7 +1780,12 @@ static PyObject *__pyx_pw_7astropy_6nddata_11convolution_13boundary_fill_3convol
  *                              float fill_value):
  */
 
-static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_2convolve2d_boundary_fill(CYTHON_UNUSED PyObject *__pyx_self, PyArrayObject *__pyx_v_f, PyArrayObject *__pyx_v_g, float __pyx_v_fill_value) {
+static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_1convolve2d_boundary_fill(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static PyMethodDef __pyx_mdef_7astropy_6nddata_11convolution_13boundary_fill_1convolve2d_boundary_fill = {__Pyx_NAMESTR("convolve2d_boundary_fill"), (PyCFunction)__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_1convolve2d_boundary_fill, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(0)};
+static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_1convolve2d_boundary_fill(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyArrayObject *__pyx_v_f = 0;
+  PyArrayObject *__pyx_v_g = 0;
+  float __pyx_v_fill_value;
   int __pyx_v_nx;
   int __pyx_v_ny;
   int __pyx_v_nkx;
@@ -2058,14 +1806,26 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_2convol
   __pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t __pyx_v_bot;
   __pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t __pyx_v_ker;
   __pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t __pyx_v_val;
-  __Pyx_LocalBuf_ND __pyx_pybuffernd_conv;
-  __Pyx_Buffer __pyx_pybuffer_conv;
-  __Pyx_LocalBuf_ND __pyx_pybuffernd_f;
-  __Pyx_Buffer __pyx_pybuffer_f;
-  __Pyx_LocalBuf_ND __pyx_pybuffernd_fixed;
-  __Pyx_Buffer __pyx_pybuffer_fixed;
-  __Pyx_LocalBuf_ND __pyx_pybuffernd_g;
-  __Pyx_Buffer __pyx_pybuffer_g;
+  Py_buffer __pyx_bstruct_conv;
+  Py_ssize_t __pyx_bstride_0_conv = 0;
+  Py_ssize_t __pyx_bstride_1_conv = 0;
+  Py_ssize_t __pyx_bshape_0_conv = 0;
+  Py_ssize_t __pyx_bshape_1_conv = 0;
+  Py_buffer __pyx_bstruct_g;
+  Py_ssize_t __pyx_bstride_0_g = 0;
+  Py_ssize_t __pyx_bstride_1_g = 0;
+  Py_ssize_t __pyx_bshape_0_g = 0;
+  Py_ssize_t __pyx_bshape_1_g = 0;
+  Py_buffer __pyx_bstruct_f;
+  Py_ssize_t __pyx_bstride_0_f = 0;
+  Py_ssize_t __pyx_bstride_1_f = 0;
+  Py_ssize_t __pyx_bshape_0_f = 0;
+  Py_ssize_t __pyx_bshape_1_f = 0;
+  Py_buffer __pyx_bstruct_fixed;
+  Py_ssize_t __pyx_bstride_0_fixed = 0;
+  Py_ssize_t __pyx_bstride_1_fixed = 0;
+  Py_ssize_t __pyx_bshape_0_fixed = 0;
+  Py_ssize_t __pyx_bshape_1_fixed = 0;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   int __pyx_t_1;
@@ -2122,33 +1882,79 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_2convol
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("convolve2d_boundary_fill", 0);
-  __pyx_pybuffer_fixed.pybuffer.buf = NULL;
-  __pyx_pybuffer_fixed.refcount = 0;
-  __pyx_pybuffernd_fixed.data = NULL;
-  __pyx_pybuffernd_fixed.rcbuffer = &__pyx_pybuffer_fixed;
-  __pyx_pybuffer_conv.pybuffer.buf = NULL;
-  __pyx_pybuffer_conv.refcount = 0;
-  __pyx_pybuffernd_conv.data = NULL;
-  __pyx_pybuffernd_conv.rcbuffer = &__pyx_pybuffer_conv;
-  __pyx_pybuffer_f.pybuffer.buf = NULL;
-  __pyx_pybuffer_f.refcount = 0;
-  __pyx_pybuffernd_f.data = NULL;
-  __pyx_pybuffernd_f.rcbuffer = &__pyx_pybuffer_f;
-  __pyx_pybuffer_g.pybuffer.buf = NULL;
-  __pyx_pybuffer_g.refcount = 0;
-  __pyx_pybuffernd_g.data = NULL;
-  __pyx_pybuffernd_g.rcbuffer = &__pyx_pybuffer_g;
+  static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__f,&__pyx_n_s__g,&__pyx_n_s__fill_value,0};
+  __Pyx_RefNannySetupContext("convolve2d_boundary_fill");
+  __pyx_self = __pyx_self;
+  {
+    PyObject* values[3] = {0,0,0};
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  0:
+        values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__f);
+        if (likely(values[0])) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+        case  1:
+        values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__g);
+        if (likely(values[1])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("convolve2d_boundary_fill", 1, 3, 3, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 87; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+        case  2:
+        values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__fill_value);
+        if (likely(values[2])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("convolve2d_boundary_fill", 1, 3, 3, 2); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 87; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "convolve2d_boundary_fill") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 87; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+    } else if (PyTuple_GET_SIZE(__pyx_args) != 3) {
+      goto __pyx_L5_argtuple_error;
+    } else {
+      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+      values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+    }
+    __pyx_v_f = ((PyArrayObject *)values[0]);
+    __pyx_v_g = ((PyArrayObject *)values[1]);
+    __pyx_v_fill_value = __pyx_PyFloat_AsDouble(values[2]); if (unlikely((__pyx_v_fill_value == (float)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 89; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("convolve2d_boundary_fill", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 87; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("astropy.nddata.convolution.boundary_fill.convolve2d_boundary_fill", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_bstruct_fixed.buf = NULL;
+  __pyx_bstruct_conv.buf = NULL;
+  __pyx_bstruct_f.buf = NULL;
+  __pyx_bstruct_g.buf = NULL;
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_f), __pyx_ptype_5numpy_ndarray, 1, "f", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 87; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_g), __pyx_ptype_5numpy_ndarray, 1, "g", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 88; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_f.rcbuffer->pybuffer, (PyObject*)__pyx_v_f, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 87; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_f, (PyObject*)__pyx_v_f, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 87; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
-  __pyx_pybuffernd_f.diminfo[0].strides = __pyx_pybuffernd_f.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_f.diminfo[0].shape = __pyx_pybuffernd_f.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_f.diminfo[1].strides = __pyx_pybuffernd_f.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_f.diminfo[1].shape = __pyx_pybuffernd_f.rcbuffer->pybuffer.shape[1];
+  __pyx_bstride_0_f = __pyx_bstruct_f.strides[0]; __pyx_bstride_1_f = __pyx_bstruct_f.strides[1];
+  __pyx_bshape_0_f = __pyx_bstruct_f.shape[0]; __pyx_bshape_1_f = __pyx_bstruct_f.shape[1];
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_g.rcbuffer->pybuffer, (PyObject*)__pyx_v_g, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 87; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_g, (PyObject*)__pyx_v_g, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 87; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
-  __pyx_pybuffernd_g.diminfo[0].strides = __pyx_pybuffernd_g.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_g.diminfo[0].shape = __pyx_pybuffernd_g.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_g.diminfo[1].strides = __pyx_pybuffernd_g.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_g.diminfo[1].shape = __pyx_pybuffernd_g.rcbuffer->pybuffer.shape[1];
+  __pyx_bstride_0_g = __pyx_bstruct_g.strides[0]; __pyx_bstride_1_g = __pyx_bstruct_g.strides[1];
+  __pyx_bshape_0_g = __pyx_bstruct_g.shape[0]; __pyx_bshape_1_g = __pyx_bstruct_g.shape[1];
 
   /* "astropy/nddata/convolution/boundary_fill.pyx":91
  *                              float fill_value):
@@ -2178,9 +1984,9 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_2convol
     __Pyx_Raise(__pyx_t_4, 0, 0, 0);
     __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
     {__pyx_filename = __pyx_f[0]; __pyx_lineno = 92; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    goto __pyx_L3;
+    goto __pyx_L6;
   }
-  __pyx_L3:;
+  __pyx_L6:;
 
   /* "astropy/nddata/convolution/boundary_fill.pyx":94
  *         raise ValueError("Convolution kernel must have odd dimensions")
@@ -2292,7 +2098,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_2convol
   __pyx_t_6 = PyInt_FromLong(__pyx_v_ny); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 102; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_6);
   __pyx_t_7 = PyList_New(2); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 102; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_7);
+  __Pyx_GOTREF(((PyObject *)__pyx_t_7));
   PyList_SET_ITEM(__pyx_t_7, 0, __pyx_t_4);
   __Pyx_GIVEREF(__pyx_t_4);
   PyList_SET_ITEM(__pyx_t_7, 1, __pyx_t_6);
@@ -2300,7 +2106,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_2convol
   __pyx_t_4 = 0;
   __pyx_t_6 = 0;
   __pyx_t_6 = PyTuple_New(1); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 102; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_6);
+  __Pyx_GOTREF(((PyObject *)__pyx_t_6));
   PyTuple_SET_ITEM(__pyx_t_6, 0, ((PyObject *)__pyx_t_7));
   __Pyx_GIVEREF(((PyObject *)__pyx_t_7));
   __pyx_t_7 = 0;
@@ -2310,7 +2116,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_2convol
   __Pyx_GOTREF(__pyx_t_4);
   if (PyDict_SetItem(__pyx_t_7, ((PyObject *)__pyx_n_s__dtype), __pyx_t_4) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 102; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  __pyx_t_4 = PyObject_Call(__pyx_t_5, ((PyObject *)__pyx_t_6), ((PyObject *)__pyx_t_7)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 102; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_4 = PyEval_CallObjectWithKeywords(__pyx_t_5, ((PyObject *)__pyx_t_6), ((PyObject *)__pyx_t_7)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 102; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_4);
   __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
   __Pyx_DECREF(((PyObject *)__pyx_t_6)); __pyx_t_6 = 0;
@@ -2319,10 +2125,11 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_2convol
   __pyx_t_8 = ((PyArrayObject *)__pyx_t_4);
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_fixed.rcbuffer->pybuffer, (PyObject*)__pyx_t_8, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack) == -1)) {
-      __pyx_v_fixed = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf = NULL;
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_fixed, (PyObject*)__pyx_t_8, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack) == -1)) {
+      __pyx_v_fixed = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_fixed.buf = NULL;
       {__pyx_filename = __pyx_f[0]; __pyx_lineno = 102; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    } else {__pyx_pybuffernd_fixed.diminfo[0].strides = __pyx_pybuffernd_fixed.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_fixed.diminfo[0].shape = __pyx_pybuffernd_fixed.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_fixed.diminfo[1].strides = __pyx_pybuffernd_fixed.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_fixed.diminfo[1].shape = __pyx_pybuffernd_fixed.rcbuffer->pybuffer.shape[1];
+    } else {__pyx_bstride_0_fixed = __pyx_bstruct_fixed.strides[0]; __pyx_bstride_1_fixed = __pyx_bstruct_fixed.strides[1];
+      __pyx_bshape_0_fixed = __pyx_bstruct_fixed.shape[0]; __pyx_bshape_1_fixed = __pyx_bstruct_fixed.shape[1];
     }
   }
   __pyx_t_8 = 0;
@@ -2346,7 +2153,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_2convol
   __pyx_t_6 = PyInt_FromLong(__pyx_v_ny); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 103; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_6);
   __pyx_t_5 = PyList_New(2); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 103; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_5);
+  __Pyx_GOTREF(((PyObject *)__pyx_t_5));
   PyList_SET_ITEM(__pyx_t_5, 0, __pyx_t_4);
   __Pyx_GIVEREF(__pyx_t_4);
   PyList_SET_ITEM(__pyx_t_5, 1, __pyx_t_6);
@@ -2354,7 +2161,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_2convol
   __pyx_t_4 = 0;
   __pyx_t_6 = 0;
   __pyx_t_6 = PyTuple_New(1); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 103; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_6);
+  __Pyx_GOTREF(((PyObject *)__pyx_t_6));
   PyTuple_SET_ITEM(__pyx_t_6, 0, ((PyObject *)__pyx_t_5));
   __Pyx_GIVEREF(((PyObject *)__pyx_t_5));
   __pyx_t_5 = 0;
@@ -2364,7 +2171,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_2convol
   __Pyx_GOTREF(__pyx_t_4);
   if (PyDict_SetItem(__pyx_t_5, ((PyObject *)__pyx_n_s__dtype), __pyx_t_4) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 103; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  __pyx_t_4 = PyObject_Call(__pyx_t_7, ((PyObject *)__pyx_t_6), ((PyObject *)__pyx_t_5)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 103; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_4 = PyEval_CallObjectWithKeywords(__pyx_t_7, ((PyObject *)__pyx_t_6), ((PyObject *)__pyx_t_5)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 103; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_4);
   __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
   __Pyx_DECREF(((PyObject *)__pyx_t_6)); __pyx_t_6 = 0;
@@ -2373,10 +2180,11 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_2convol
   __pyx_t_9 = ((PyArrayObject *)__pyx_t_4);
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_conv.rcbuffer->pybuffer, (PyObject*)__pyx_t_9, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack) == -1)) {
-      __pyx_v_conv = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_conv.rcbuffer->pybuffer.buf = NULL;
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_conv, (PyObject*)__pyx_t_9, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack) == -1)) {
+      __pyx_v_conv = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_conv.buf = NULL;
       {__pyx_filename = __pyx_f[0]; __pyx_lineno = 103; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    } else {__pyx_pybuffernd_conv.diminfo[0].strides = __pyx_pybuffernd_conv.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_conv.diminfo[0].shape = __pyx_pybuffernd_conv.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_conv.diminfo[1].strides = __pyx_pybuffernd_conv.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_conv.diminfo[1].shape = __pyx_pybuffernd_conv.rcbuffer->pybuffer.shape[1];
+    } else {__pyx_bstride_0_conv = __pyx_bstruct_conv.strides[0]; __pyx_bstride_1_conv = __pyx_bstruct_conv.strides[1];
+      __pyx_bshape_0_conv = __pyx_bstruct_conv.shape[0]; __pyx_bshape_1_conv = __pyx_bstruct_conv.shape[1];
     }
   }
   __pyx_t_9 = 0;
@@ -2414,7 +2222,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_2convol
  */
       __pyx_t_14 = __pyx_v_i;
       __pyx_t_15 = __pyx_v_j;
-      __pyx_t_2 = npy_isnan((*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_pybuffernd_f.rcbuffer->pybuffer.buf, __pyx_t_14, __pyx_pybuffernd_f.diminfo[0].strides, __pyx_t_15, __pyx_pybuffernd_f.diminfo[1].strides)));
+      __pyx_t_2 = npy_isnan((*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_bstruct_f.buf, __pyx_t_14, __pyx_bstride_0_f, __pyx_t_15, __pyx_bstride_1_f)));
       if (__pyx_t_2) {
 
         /* "astropy/nddata/convolution/boundary_fill.pyx":116
@@ -2529,7 +2337,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_2convol
  *                             val = f[ii, jj]
  */
               __pyx_v_val = __pyx_v_fill_value;
-              goto __pyx_L13;
+              goto __pyx_L16;
             }
             /*else*/ {
 
@@ -2542,11 +2350,11 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_2convol
  */
               __pyx_t_22 = __pyx_v_ii;
               __pyx_t_23 = __pyx_v_jj;
-              if (__pyx_t_22 < 0) __pyx_t_22 += __pyx_pybuffernd_f.diminfo[0].shape;
-              if (__pyx_t_23 < 0) __pyx_t_23 += __pyx_pybuffernd_f.diminfo[1].shape;
-              __pyx_v_val = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_pybuffernd_f.rcbuffer->pybuffer.buf, __pyx_t_22, __pyx_pybuffernd_f.diminfo[0].strides, __pyx_t_23, __pyx_pybuffernd_f.diminfo[1].strides));
+              if (__pyx_t_22 < 0) __pyx_t_22 += __pyx_bshape_0_f;
+              if (__pyx_t_23 < 0) __pyx_t_23 += __pyx_bshape_1_f;
+              __pyx_v_val = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_bstruct_f.buf, __pyx_t_22, __pyx_bstride_0_f, __pyx_t_23, __pyx_bstride_1_f));
             }
-            __pyx_L13:;
+            __pyx_L16:;
 
             /* "astropy/nddata/convolution/boundary_fill.pyx":128
  *                         else:
@@ -2567,7 +2375,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_2convol
  */
               __pyx_t_24 = ((unsigned int)((__pyx_v_wkx + __pyx_v_ii) - __pyx_v_i));
               __pyx_t_25 = ((unsigned int)((__pyx_v_wky + __pyx_v_jj) - __pyx_v_j));
-              __pyx_v_ker = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_pybuffernd_g.rcbuffer->pybuffer.buf, __pyx_t_24, __pyx_pybuffernd_g.diminfo[0].strides, __pyx_t_25, __pyx_pybuffernd_g.diminfo[1].strides));
+              __pyx_v_ker = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_bstruct_g.buf, __pyx_t_24, __pyx_bstride_0_g, __pyx_t_25, __pyx_bstride_1_g));
 
               /* "astropy/nddata/convolution/boundary_fill.pyx":131
  *                             ker = g[<unsigned int>(wkx + ii - i),
@@ -2586,9 +2394,9 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_2convol
  *                     fixed[i, j] = top / bot
  */
               __pyx_v_bot = (__pyx_v_bot + __pyx_v_ker);
-              goto __pyx_L14;
+              goto __pyx_L17;
             }
-            __pyx_L14:;
+            __pyx_L17:;
           }
         }
 
@@ -2615,8 +2423,8 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_2convol
           }
           __pyx_t_26 = __pyx_v_i;
           __pyx_t_27 = __pyx_v_j;
-          *__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_26, __pyx_pybuffernd_fixed.diminfo[0].strides, __pyx_t_27, __pyx_pybuffernd_fixed.diminfo[1].strides) = (__pyx_v_top / __pyx_v_bot);
-          goto __pyx_L15;
+          *__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_26, __pyx_bstride_0_fixed, __pyx_t_27, __pyx_bstride_1_fixed) = (__pyx_v_top / __pyx_v_bot);
+          goto __pyx_L18;
         }
         /*else*/ {
 
@@ -2631,10 +2439,10 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_2convol
           __pyx_t_29 = __pyx_v_j;
           __pyx_t_30 = __pyx_v_i;
           __pyx_t_31 = __pyx_v_j;
-          *__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_30, __pyx_pybuffernd_fixed.diminfo[0].strides, __pyx_t_31, __pyx_pybuffernd_fixed.diminfo[1].strides) = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_pybuffernd_f.rcbuffer->pybuffer.buf, __pyx_t_28, __pyx_pybuffernd_f.diminfo[0].strides, __pyx_t_29, __pyx_pybuffernd_f.diminfo[1].strides));
+          *__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_30, __pyx_bstride_0_fixed, __pyx_t_31, __pyx_bstride_1_fixed) = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_bstruct_f.buf, __pyx_t_28, __pyx_bstride_0_f, __pyx_t_29, __pyx_bstride_1_f));
         }
-        __pyx_L15:;
-        goto __pyx_L8;
+        __pyx_L18:;
+        goto __pyx_L11;
       }
       /*else*/ {
 
@@ -2649,9 +2457,9 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_2convol
         __pyx_t_33 = __pyx_v_j;
         __pyx_t_34 = __pyx_v_i;
         __pyx_t_35 = __pyx_v_j;
-        *__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_34, __pyx_pybuffernd_fixed.diminfo[0].strides, __pyx_t_35, __pyx_pybuffernd_fixed.diminfo[1].strides) = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_pybuffernd_f.rcbuffer->pybuffer.buf, __pyx_t_32, __pyx_pybuffernd_f.diminfo[0].strides, __pyx_t_33, __pyx_pybuffernd_f.diminfo[1].strides));
+        *__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_34, __pyx_bstride_0_fixed, __pyx_t_35, __pyx_bstride_1_fixed) = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_bstruct_f.buf, __pyx_t_32, __pyx_bstride_0_f, __pyx_t_33, __pyx_bstride_1_f));
       }
-      __pyx_L8:;
+      __pyx_L11:;
     }
   }
 
@@ -2686,7 +2494,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_2convol
  */
       __pyx_t_36 = __pyx_v_i;
       __pyx_t_37 = __pyx_v_j;
-      __pyx_t_3 = (!npy_isnan((*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_36, __pyx_pybuffernd_fixed.diminfo[0].strides, __pyx_t_37, __pyx_pybuffernd_fixed.diminfo[1].strides))));
+      __pyx_t_3 = (!npy_isnan((*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_36, __pyx_bstride_0_fixed, __pyx_t_37, __pyx_bstride_1_fixed))));
       if (__pyx_t_3) {
 
         /* "astropy/nddata/convolution/boundary_fill.pyx":144
@@ -2801,7 +2609,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_2convol
  *                             val = fixed[ii, jj]
  */
               __pyx_v_val = __pyx_v_fill_value;
-              goto __pyx_L25;
+              goto __pyx_L28;
             }
             /*else*/ {
 
@@ -2814,11 +2622,11 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_2convol
  */
               __pyx_t_38 = __pyx_v_ii;
               __pyx_t_39 = __pyx_v_jj;
-              if (__pyx_t_38 < 0) __pyx_t_38 += __pyx_pybuffernd_fixed.diminfo[0].shape;
-              if (__pyx_t_39 < 0) __pyx_t_39 += __pyx_pybuffernd_fixed.diminfo[1].shape;
-              __pyx_v_val = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_38, __pyx_pybuffernd_fixed.diminfo[0].strides, __pyx_t_39, __pyx_pybuffernd_fixed.diminfo[1].strides));
+              if (__pyx_t_38 < 0) __pyx_t_38 += __pyx_bshape_0_fixed;
+              if (__pyx_t_39 < 0) __pyx_t_39 += __pyx_bshape_1_fixed;
+              __pyx_v_val = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_38, __pyx_bstride_0_fixed, __pyx_t_39, __pyx_bstride_1_fixed));
             }
-            __pyx_L25:;
+            __pyx_L28:;
 
             /* "astropy/nddata/convolution/boundary_fill.pyx":157
  *                             val = fixed[ii, jj]
@@ -2829,7 +2637,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_2convol
  */
             __pyx_t_40 = ((unsigned int)((__pyx_v_wkx + __pyx_v_ii) - __pyx_v_i));
             __pyx_t_41 = ((unsigned int)((__pyx_v_wky + __pyx_v_jj) - __pyx_v_j));
-            __pyx_v_ker = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_pybuffernd_g.rcbuffer->pybuffer.buf, __pyx_t_40, __pyx_pybuffernd_g.diminfo[0].strides, __pyx_t_41, __pyx_pybuffernd_g.diminfo[1].strides));
+            __pyx_v_ker = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_bstruct_g.buf, __pyx_t_40, __pyx_bstride_0_g, __pyx_t_41, __pyx_bstride_1_g));
 
             /* "astropy/nddata/convolution/boundary_fill.pyx":158
  *                         ker = g[<unsigned int>(wkx + ii - i),
@@ -2858,9 +2666,9 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_2convol
  *                     conv[i, j] = top / bot
  */
               __pyx_v_bot = (__pyx_v_bot + __pyx_v_ker);
-              goto __pyx_L26;
+              goto __pyx_L29;
             }
-            __pyx_L26:;
+            __pyx_L29:;
           }
         }
 
@@ -2887,8 +2695,8 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_2convol
           }
           __pyx_t_42 = __pyx_v_i;
           __pyx_t_43 = __pyx_v_j;
-          *__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_pybuffernd_conv.rcbuffer->pybuffer.buf, __pyx_t_42, __pyx_pybuffernd_conv.diminfo[0].strides, __pyx_t_43, __pyx_pybuffernd_conv.diminfo[1].strides) = (__pyx_v_top / __pyx_v_bot);
-          goto __pyx_L27;
+          *__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_bstruct_conv.buf, __pyx_t_42, __pyx_bstride_0_conv, __pyx_t_43, __pyx_bstride_1_conv) = (__pyx_v_top / __pyx_v_bot);
+          goto __pyx_L30;
         }
         /*else*/ {
 
@@ -2903,10 +2711,10 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_2convol
           __pyx_t_45 = __pyx_v_j;
           __pyx_t_46 = __pyx_v_i;
           __pyx_t_47 = __pyx_v_j;
-          *__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_pybuffernd_conv.rcbuffer->pybuffer.buf, __pyx_t_46, __pyx_pybuffernd_conv.diminfo[0].strides, __pyx_t_47, __pyx_pybuffernd_conv.diminfo[1].strides) = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_44, __pyx_pybuffernd_fixed.diminfo[0].strides, __pyx_t_45, __pyx_pybuffernd_fixed.diminfo[1].strides));
+          *__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_bstruct_conv.buf, __pyx_t_46, __pyx_bstride_0_conv, __pyx_t_47, __pyx_bstride_1_conv) = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_44, __pyx_bstride_0_fixed, __pyx_t_45, __pyx_bstride_1_fixed));
         }
-        __pyx_L27:;
-        goto __pyx_L20;
+        __pyx_L30:;
+        goto __pyx_L23;
       }
       /*else*/ {
 
@@ -2921,9 +2729,9 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_2convol
         __pyx_t_49 = __pyx_v_j;
         __pyx_t_50 = __pyx_v_i;
         __pyx_t_51 = __pyx_v_j;
-        *__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_pybuffernd_conv.rcbuffer->pybuffer.buf, __pyx_t_50, __pyx_pybuffernd_conv.diminfo[0].strides, __pyx_t_51, __pyx_pybuffernd_conv.diminfo[1].strides) = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_48, __pyx_pybuffernd_fixed.diminfo[0].strides, __pyx_t_49, __pyx_pybuffernd_fixed.diminfo[1].strides));
+        *__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_bstruct_conv.buf, __pyx_t_50, __pyx_bstride_0_conv, __pyx_t_51, __pyx_bstride_1_conv) = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_48, __pyx_bstride_0_fixed, __pyx_t_49, __pyx_bstride_1_fixed));
       }
-      __pyx_L20:;
+      __pyx_L23:;
     }
   }
 
@@ -2948,19 +2756,19 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_2convol
   __Pyx_XDECREF(__pyx_t_7);
   { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;
     __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);
-    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_conv.rcbuffer->pybuffer);
-    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_f.rcbuffer->pybuffer);
-    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_fixed.rcbuffer->pybuffer);
-    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_g.rcbuffer->pybuffer);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_conv);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_g);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_f);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_fixed);
   __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
   __Pyx_AddTraceback("astropy.nddata.convolution.boundary_fill.convolve2d_boundary_fill", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   goto __pyx_L2;
   __pyx_L0:;
-  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_conv.rcbuffer->pybuffer);
-  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_f.rcbuffer->pybuffer);
-  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_fixed.rcbuffer->pybuffer);
-  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_g.rcbuffer->pybuffer);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_conv);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_g);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_f);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_fixed);
   __pyx_L2:;
   __Pyx_XDECREF((PyObject *)__pyx_v_fixed);
   __Pyx_XDECREF((PyObject *)__pyx_v_conv);
@@ -2969,82 +2777,6 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_2convol
   return __pyx_r;
 }
 
-/* Python wrapper */
-static PyObject *__pyx_pw_7astropy_6nddata_11convolution_13boundary_fill_5convolve3d_boundary_fill(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static PyMethodDef __pyx_mdef_7astropy_6nddata_11convolution_13boundary_fill_5convolve3d_boundary_fill = {__Pyx_NAMESTR("convolve3d_boundary_fill"), (PyCFunction)__pyx_pw_7astropy_6nddata_11convolution_13boundary_fill_5convolve3d_boundary_fill, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(0)};
-static PyObject *__pyx_pw_7astropy_6nddata_11convolution_13boundary_fill_5convolve3d_boundary_fill(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
-  PyArrayObject *__pyx_v_f = 0;
-  PyArrayObject *__pyx_v_g = 0;
-  float __pyx_v_fill_value;
-  static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__f,&__pyx_n_s__g,&__pyx_n_s__fill_value,0};
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("convolve3d_boundary_fill (wrapper)", 0);
-  __pyx_self = __pyx_self;
-  {
-    PyObject* values[3] = {0,0,0};
-    if (unlikely(__pyx_kwds)) {
-      Py_ssize_t kw_args;
-      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
-      switch (pos_args) {
-        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
-        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
-        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
-        case  0: break;
-        default: goto __pyx_L5_argtuple_error;
-      }
-      kw_args = PyDict_Size(__pyx_kwds);
-      switch (pos_args) {
-        case  0:
-        values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__f);
-        if (likely(values[0])) kw_args--;
-        else goto __pyx_L5_argtuple_error;
-        case  1:
-        values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__g);
-        if (likely(values[1])) kw_args--;
-        else {
-          __Pyx_RaiseArgtupleInvalid("convolve3d_boundary_fill", 1, 3, 3, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 172; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-        }
-        case  2:
-        values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__fill_value);
-        if (likely(values[2])) kw_args--;
-        else {
-          __Pyx_RaiseArgtupleInvalid("convolve3d_boundary_fill", 1, 3, 3, 2); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 172; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-        }
-      }
-      if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "convolve3d_boundary_fill") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 172; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-      }
-    } else if (PyTuple_GET_SIZE(__pyx_args) != 3) {
-      goto __pyx_L5_argtuple_error;
-    } else {
-      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
-      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
-      values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
-    }
-    __pyx_v_f = ((PyArrayObject *)values[0]);
-    __pyx_v_g = ((PyArrayObject *)values[1]);
-    __pyx_v_fill_value = __pyx_PyFloat_AsFloat(values[2]); if (unlikely((__pyx_v_fill_value == (float)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 174; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-  }
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("convolve3d_boundary_fill", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 172; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-  __pyx_L3_error:;
-  __Pyx_AddTraceback("astropy.nddata.convolution.boundary_fill.convolve3d_boundary_fill", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return NULL;
-  __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_f), __pyx_ptype_5numpy_ndarray, 1, "f", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 172; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_g), __pyx_ptype_5numpy_ndarray, 1, "g", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 173; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_r = __pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_4convolve3d_boundary_fill(__pyx_self, __pyx_v_f, __pyx_v_g, __pyx_v_fill_value);
-  goto __pyx_L0;
-  __pyx_L1_error:;
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
 /* "astropy/nddata/convolution/boundary_fill.pyx":172
  * 
  * @cython.boundscheck(False)  # turn off bounds-checking for entire function
@@ -3053,7 +2785,12 @@ static PyObject *__pyx_pw_7astropy_6nddata_11convolution_13boundary_fill_5convol
  *                              float fill_value):
  */
 
-static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_4convolve3d_boundary_fill(CYTHON_UNUSED PyObject *__pyx_self, PyArrayObject *__pyx_v_f, PyArrayObject *__pyx_v_g, float __pyx_v_fill_value) {
+static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_2convolve3d_boundary_fill(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static PyMethodDef __pyx_mdef_7astropy_6nddata_11convolution_13boundary_fill_2convolve3d_boundary_fill = {__Pyx_NAMESTR("convolve3d_boundary_fill"), (PyCFunction)__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_2convolve3d_boundary_fill, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(0)};
+static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_2convolve3d_boundary_fill(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyArrayObject *__pyx_v_f = 0;
+  PyArrayObject *__pyx_v_g = 0;
+  float __pyx_v_fill_value;
   int __pyx_v_nx;
   int __pyx_v_ny;
   int __pyx_v_nz;
@@ -3081,14 +2818,34 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_4convol
   __pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t __pyx_v_bot;
   __pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t __pyx_v_ker;
   __pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t __pyx_v_val;
-  __Pyx_LocalBuf_ND __pyx_pybuffernd_conv;
-  __Pyx_Buffer __pyx_pybuffer_conv;
-  __Pyx_LocalBuf_ND __pyx_pybuffernd_f;
-  __Pyx_Buffer __pyx_pybuffer_f;
-  __Pyx_LocalBuf_ND __pyx_pybuffernd_fixed;
-  __Pyx_Buffer __pyx_pybuffer_fixed;
-  __Pyx_LocalBuf_ND __pyx_pybuffernd_g;
-  __Pyx_Buffer __pyx_pybuffer_g;
+  Py_buffer __pyx_bstruct_conv;
+  Py_ssize_t __pyx_bstride_0_conv = 0;
+  Py_ssize_t __pyx_bstride_1_conv = 0;
+  Py_ssize_t __pyx_bstride_2_conv = 0;
+  Py_ssize_t __pyx_bshape_0_conv = 0;
+  Py_ssize_t __pyx_bshape_1_conv = 0;
+  Py_ssize_t __pyx_bshape_2_conv = 0;
+  Py_buffer __pyx_bstruct_g;
+  Py_ssize_t __pyx_bstride_0_g = 0;
+  Py_ssize_t __pyx_bstride_1_g = 0;
+  Py_ssize_t __pyx_bstride_2_g = 0;
+  Py_ssize_t __pyx_bshape_0_g = 0;
+  Py_ssize_t __pyx_bshape_1_g = 0;
+  Py_ssize_t __pyx_bshape_2_g = 0;
+  Py_buffer __pyx_bstruct_f;
+  Py_ssize_t __pyx_bstride_0_f = 0;
+  Py_ssize_t __pyx_bstride_1_f = 0;
+  Py_ssize_t __pyx_bstride_2_f = 0;
+  Py_ssize_t __pyx_bshape_0_f = 0;
+  Py_ssize_t __pyx_bshape_1_f = 0;
+  Py_ssize_t __pyx_bshape_2_f = 0;
+  Py_buffer __pyx_bstruct_fixed;
+  Py_ssize_t __pyx_bstride_0_fixed = 0;
+  Py_ssize_t __pyx_bstride_1_fixed = 0;
+  Py_ssize_t __pyx_bstride_2_fixed = 0;
+  Py_ssize_t __pyx_bshape_0_fixed = 0;
+  Py_ssize_t __pyx_bshape_1_fixed = 0;
+  Py_ssize_t __pyx_bshape_2_fixed = 0;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   int __pyx_t_1;
@@ -3168,33 +2925,79 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_4convol
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("convolve3d_boundary_fill", 0);
-  __pyx_pybuffer_fixed.pybuffer.buf = NULL;
-  __pyx_pybuffer_fixed.refcount = 0;
-  __pyx_pybuffernd_fixed.data = NULL;
-  __pyx_pybuffernd_fixed.rcbuffer = &__pyx_pybuffer_fixed;
-  __pyx_pybuffer_conv.pybuffer.buf = NULL;
-  __pyx_pybuffer_conv.refcount = 0;
-  __pyx_pybuffernd_conv.data = NULL;
-  __pyx_pybuffernd_conv.rcbuffer = &__pyx_pybuffer_conv;
-  __pyx_pybuffer_f.pybuffer.buf = NULL;
-  __pyx_pybuffer_f.refcount = 0;
-  __pyx_pybuffernd_f.data = NULL;
-  __pyx_pybuffernd_f.rcbuffer = &__pyx_pybuffer_f;
-  __pyx_pybuffer_g.pybuffer.buf = NULL;
-  __pyx_pybuffer_g.refcount = 0;
-  __pyx_pybuffernd_g.data = NULL;
-  __pyx_pybuffernd_g.rcbuffer = &__pyx_pybuffer_g;
+  static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__f,&__pyx_n_s__g,&__pyx_n_s__fill_value,0};
+  __Pyx_RefNannySetupContext("convolve3d_boundary_fill");
+  __pyx_self = __pyx_self;
+  {
+    PyObject* values[3] = {0,0,0};
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  0:
+        values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__f);
+        if (likely(values[0])) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+        case  1:
+        values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__g);
+        if (likely(values[1])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("convolve3d_boundary_fill", 1, 3, 3, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 172; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+        case  2:
+        values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__fill_value);
+        if (likely(values[2])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("convolve3d_boundary_fill", 1, 3, 3, 2); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 172; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "convolve3d_boundary_fill") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 172; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+    } else if (PyTuple_GET_SIZE(__pyx_args) != 3) {
+      goto __pyx_L5_argtuple_error;
+    } else {
+      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+      values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+    }
+    __pyx_v_f = ((PyArrayObject *)values[0]);
+    __pyx_v_g = ((PyArrayObject *)values[1]);
+    __pyx_v_fill_value = __pyx_PyFloat_AsDouble(values[2]); if (unlikely((__pyx_v_fill_value == (float)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 174; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("convolve3d_boundary_fill", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 172; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("astropy.nddata.convolution.boundary_fill.convolve3d_boundary_fill", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_bstruct_fixed.buf = NULL;
+  __pyx_bstruct_conv.buf = NULL;
+  __pyx_bstruct_f.buf = NULL;
+  __pyx_bstruct_g.buf = NULL;
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_f), __pyx_ptype_5numpy_ndarray, 1, "f", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 172; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_g), __pyx_ptype_5numpy_ndarray, 1, "g", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 173; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_f.rcbuffer->pybuffer, (PyObject*)__pyx_v_f, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES, 3, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 172; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_f, (PyObject*)__pyx_v_f, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES, 3, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 172; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
-  __pyx_pybuffernd_f.diminfo[0].strides = __pyx_pybuffernd_f.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_f.diminfo[0].shape = __pyx_pybuffernd_f.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_f.diminfo[1].strides = __pyx_pybuffernd_f.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_f.diminfo[1].shape = __pyx_pybuffernd_f.rcbuffer->pybuffer.shape[1]; __pyx_pybuffernd_f.diminfo[2].strides = __pyx_pybuffernd_f.rcbuffer->pybuffer.strides[2]; __pyx_pybuffernd_f.diminfo[2].shape = __pyx_pybuffernd_f.rcbuffer->pybuffer.shape[2];
+  __pyx_bstride_0_f = __pyx_bstruct_f.strides[0]; __pyx_bstride_1_f = __pyx_bstruct_f.strides[1]; __pyx_bstride_2_f = __pyx_bstruct_f.strides[2];
+  __pyx_bshape_0_f = __pyx_bstruct_f.shape[0]; __pyx_bshape_1_f = __pyx_bstruct_f.shape[1]; __pyx_bshape_2_f = __pyx_bstruct_f.shape[2];
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_g.rcbuffer->pybuffer, (PyObject*)__pyx_v_g, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES, 3, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 172; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_g, (PyObject*)__pyx_v_g, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES, 3, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 172; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
-  __pyx_pybuffernd_g.diminfo[0].strides = __pyx_pybuffernd_g.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_g.diminfo[0].shape = __pyx_pybuffernd_g.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_g.diminfo[1].strides = __pyx_pybuffernd_g.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_g.diminfo[1].shape = __pyx_pybuffernd_g.rcbuffer->pybuffer.shape[1]; __pyx_pybuffernd_g.diminfo[2].strides = __pyx_pybuffernd_g.rcbuffer->pybuffer.strides[2]; __pyx_pybuffernd_g.diminfo[2].shape = __pyx_pybuffernd_g.rcbuffer->pybuffer.shape[2];
+  __pyx_bstride_0_g = __pyx_bstruct_g.strides[0]; __pyx_bstride_1_g = __pyx_bstruct_g.strides[1]; __pyx_bstride_2_g = __pyx_bstruct_g.strides[2];
+  __pyx_bshape_0_g = __pyx_bstruct_g.shape[0]; __pyx_bshape_1_g = __pyx_bstruct_g.shape[1]; __pyx_bshape_2_g = __pyx_bstruct_g.shape[2];
 
   /* "astropy/nddata/convolution/boundary_fill.pyx":176
  *                              float fill_value):
@@ -3230,9 +3033,9 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_4convol
     __Pyx_Raise(__pyx_t_5, 0, 0, 0);
     __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
     {__pyx_filename = __pyx_f[0]; __pyx_lineno = 177; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    goto __pyx_L3;
+    goto __pyx_L6;
   }
-  __pyx_L3:;
+  __pyx_L6:;
 
   /* "astropy/nddata/convolution/boundary_fill.pyx":179
  *         raise ValueError("Convolution kernel must have odd dimensions")
@@ -3373,7 +3176,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_4convol
   __pyx_t_8 = PyInt_FromLong(__pyx_v_nz); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 190; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_8);
   __pyx_t_9 = PyList_New(3); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 190; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_9);
+  __Pyx_GOTREF(((PyObject *)__pyx_t_9));
   PyList_SET_ITEM(__pyx_t_9, 0, __pyx_t_5);
   __Pyx_GIVEREF(__pyx_t_5);
   PyList_SET_ITEM(__pyx_t_9, 1, __pyx_t_7);
@@ -3384,7 +3187,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_4convol
   __pyx_t_7 = 0;
   __pyx_t_8 = 0;
   __pyx_t_8 = PyTuple_New(1); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 190; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_8);
+  __Pyx_GOTREF(((PyObject *)__pyx_t_8));
   PyTuple_SET_ITEM(__pyx_t_8, 0, ((PyObject *)__pyx_t_9));
   __Pyx_GIVEREF(((PyObject *)__pyx_t_9));
   __pyx_t_9 = 0;
@@ -3394,7 +3197,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_4convol
   __Pyx_GOTREF(__pyx_t_7);
   if (PyDict_SetItem(__pyx_t_9, ((PyObject *)__pyx_n_s__dtype), __pyx_t_7) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 190; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-  __pyx_t_7 = PyObject_Call(__pyx_t_6, ((PyObject *)__pyx_t_8), ((PyObject *)__pyx_t_9)); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 190; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_7 = PyEval_CallObjectWithKeywords(__pyx_t_6, ((PyObject *)__pyx_t_8), ((PyObject *)__pyx_t_9)); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 190; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_7);
   __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
   __Pyx_DECREF(((PyObject *)__pyx_t_8)); __pyx_t_8 = 0;
@@ -3403,10 +3206,11 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_4convol
   __pyx_t_10 = ((PyArrayObject *)__pyx_t_7);
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_fixed.rcbuffer->pybuffer, (PyObject*)__pyx_t_10, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 3, 0, __pyx_stack) == -1)) {
-      __pyx_v_fixed = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf = NULL;
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_fixed, (PyObject*)__pyx_t_10, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 3, 0, __pyx_stack) == -1)) {
+      __pyx_v_fixed = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_fixed.buf = NULL;
       {__pyx_filename = __pyx_f[0]; __pyx_lineno = 190; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    } else {__pyx_pybuffernd_fixed.diminfo[0].strides = __pyx_pybuffernd_fixed.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_fixed.diminfo[0].shape = __pyx_pybuffernd_fixed.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_fixed.diminfo[1].strides = __pyx_pybuffernd_fixed.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_fixed.diminfo[1].shape = __pyx_pybuffernd_fixed.rcbuffer->pybuffer.shape[1]; __pyx_pybuffernd_fixed.diminfo[2].strides = __pyx_pybuffernd_fixed.rcbuffer->pybuffer.strides[2]; __pyx_pybuffernd_fixed.diminfo[2].shape = __pyx_pybuffernd_fixed.rcbuffer->pybuffer.shape[2];
+    } else {__pyx_bstride_0_fixed = __pyx_bstruct_fixed.strides[0]; __pyx_bstride_1_fixed = __pyx_bstruct_fixed.strides[1]; __pyx_bstride_2_fixed = __pyx_bstruct_fixed.strides[2];
+      __pyx_bshape_0_fixed = __pyx_bstruct_fixed.shape[0]; __pyx_bshape_1_fixed = __pyx_bstruct_fixed.shape[1]; __pyx_bshape_2_fixed = __pyx_bstruct_fixed.shape[2];
     }
   }
   __pyx_t_10 = 0;
@@ -3432,7 +3236,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_4convol
   __pyx_t_6 = PyInt_FromLong(__pyx_v_nz); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 191; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_6);
   __pyx_t_5 = PyList_New(3); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 191; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_5);
+  __Pyx_GOTREF(((PyObject *)__pyx_t_5));
   PyList_SET_ITEM(__pyx_t_5, 0, __pyx_t_7);
   __Pyx_GIVEREF(__pyx_t_7);
   PyList_SET_ITEM(__pyx_t_5, 1, __pyx_t_8);
@@ -3443,7 +3247,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_4convol
   __pyx_t_8 = 0;
   __pyx_t_6 = 0;
   __pyx_t_6 = PyTuple_New(1); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 191; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_6);
+  __Pyx_GOTREF(((PyObject *)__pyx_t_6));
   PyTuple_SET_ITEM(__pyx_t_6, 0, ((PyObject *)__pyx_t_5));
   __Pyx_GIVEREF(((PyObject *)__pyx_t_5));
   __pyx_t_5 = 0;
@@ -3453,7 +3257,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_4convol
   __Pyx_GOTREF(__pyx_t_8);
   if (PyDict_SetItem(__pyx_t_5, ((PyObject *)__pyx_n_s__dtype), __pyx_t_8) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 191; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-  __pyx_t_8 = PyObject_Call(__pyx_t_9, ((PyObject *)__pyx_t_6), ((PyObject *)__pyx_t_5)); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 191; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_8 = PyEval_CallObjectWithKeywords(__pyx_t_9, ((PyObject *)__pyx_t_6), ((PyObject *)__pyx_t_5)); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 191; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_8);
   __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
   __Pyx_DECREF(((PyObject *)__pyx_t_6)); __pyx_t_6 = 0;
@@ -3462,10 +3266,11 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_4convol
   __pyx_t_11 = ((PyArrayObject *)__pyx_t_8);
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_conv.rcbuffer->pybuffer, (PyObject*)__pyx_t_11, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 3, 0, __pyx_stack) == -1)) {
-      __pyx_v_conv = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_conv.rcbuffer->pybuffer.buf = NULL;
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_conv, (PyObject*)__pyx_t_11, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 3, 0, __pyx_stack) == -1)) {
+      __pyx_v_conv = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_conv.buf = NULL;
       {__pyx_filename = __pyx_f[0]; __pyx_lineno = 191; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    } else {__pyx_pybuffernd_conv.diminfo[0].strides = __pyx_pybuffernd_conv.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_conv.diminfo[0].shape = __pyx_pybuffernd_conv.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_conv.diminfo[1].strides = __pyx_pybuffernd_conv.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_conv.diminfo[1].shape = __pyx_pybuffernd_conv.rcbuffer->pybuffer.shape[1]; __pyx_pybuffernd_conv.diminfo[2].strides = __pyx_pybuffernd_conv.rcbuffer->pybuffer.strides[2]; __pyx_pybuffernd_conv.diminfo[2].shape = __pyx_pybuffernd_conv.rcbuffer->pybuffer.shape[2];
+    } else {__pyx_bstride_0_conv = __pyx_bstruct_conv.strides[0]; __pyx_bstride_1_conv = __pyx_bstruct_conv.strides[1]; __pyx_bstride_2_conv = __pyx_bstruct_conv.strides[2];
+      __pyx_bshape_0_conv = __pyx_bstruct_conv.shape[0]; __pyx_bshape_1_conv = __pyx_bstruct_conv.shape[1]; __pyx_bshape_2_conv = __pyx_bstruct_conv.shape[2];
     }
   }
   __pyx_t_11 = 0;
@@ -3515,7 +3320,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_4convol
         __pyx_t_18 = __pyx_v_i;
         __pyx_t_19 = __pyx_v_j;
         __pyx_t_20 = __pyx_v_k;
-        __pyx_t_4 = npy_isnan((*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_pybuffernd_f.rcbuffer->pybuffer.buf, __pyx_t_18, __pyx_pybuffernd_f.diminfo[0].strides, __pyx_t_19, __pyx_pybuffernd_f.diminfo[1].strides, __pyx_t_20, __pyx_pybuffernd_f.diminfo[2].strides)));
+        __pyx_t_4 = npy_isnan((*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_bstruct_f.buf, __pyx_t_18, __pyx_bstride_0_f, __pyx_t_19, __pyx_bstride_1_f, __pyx_t_20, __pyx_bstride_2_f)));
         if (__pyx_t_4) {
 
           /* "astropy/nddata/convolution/boundary_fill.pyx":205
@@ -3671,7 +3476,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_4convol
  *                                     val = f[ii, jj, kk]
  */
                   __pyx_v_val = __pyx_v_fill_value;
-                  goto __pyx_L17;
+                  goto __pyx_L20;
                 }
                 /*else*/ {
 
@@ -3685,12 +3490,12 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_4convol
                   __pyx_t_30 = __pyx_v_ii;
                   __pyx_t_31 = __pyx_v_jj;
                   __pyx_t_32 = __pyx_v_kk;
-                  if (__pyx_t_30 < 0) __pyx_t_30 += __pyx_pybuffernd_f.diminfo[0].shape;
-                  if (__pyx_t_31 < 0) __pyx_t_31 += __pyx_pybuffernd_f.diminfo[1].shape;
-                  if (__pyx_t_32 < 0) __pyx_t_32 += __pyx_pybuffernd_f.diminfo[2].shape;
-                  __pyx_v_val = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_pybuffernd_f.rcbuffer->pybuffer.buf, __pyx_t_30, __pyx_pybuffernd_f.diminfo[0].strides, __pyx_t_31, __pyx_pybuffernd_f.diminfo[1].strides, __pyx_t_32, __pyx_pybuffernd_f.diminfo[2].strides));
+                  if (__pyx_t_30 < 0) __pyx_t_30 += __pyx_bshape_0_f;
+                  if (__pyx_t_31 < 0) __pyx_t_31 += __pyx_bshape_1_f;
+                  if (__pyx_t_32 < 0) __pyx_t_32 += __pyx_bshape_2_f;
+                  __pyx_v_val = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_bstruct_f.buf, __pyx_t_30, __pyx_bstride_0_f, __pyx_t_31, __pyx_bstride_1_f, __pyx_t_32, __pyx_bstride_2_f));
                 }
-                __pyx_L17:;
+                __pyx_L20:;
 
                 /* "astropy/nddata/convolution/boundary_fill.pyx":220
  *                                 else:
@@ -3712,7 +3517,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_4convol
                   __pyx_t_33 = ((unsigned int)((__pyx_v_wkx + __pyx_v_ii) - __pyx_v_i));
                   __pyx_t_34 = ((unsigned int)((__pyx_v_wky + __pyx_v_jj) - __pyx_v_j));
                   __pyx_t_35 = ((unsigned int)((__pyx_v_wkz + __pyx_v_kk) - __pyx_v_k));
-                  __pyx_v_ker = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_pybuffernd_g.rcbuffer->pybuffer.buf, __pyx_t_33, __pyx_pybuffernd_g.diminfo[0].strides, __pyx_t_34, __pyx_pybuffernd_g.diminfo[1].strides, __pyx_t_35, __pyx_pybuffernd_g.diminfo[2].strides));
+                  __pyx_v_ker = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_bstruct_g.buf, __pyx_t_33, __pyx_bstride_0_g, __pyx_t_34, __pyx_bstride_1_g, __pyx_t_35, __pyx_bstride_2_g));
 
                   /* "astropy/nddata/convolution/boundary_fill.pyx":224
  *                                             <unsigned int>(wky + jj - j),
@@ -3731,9 +3536,9 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_4convol
  *                         fixed[i, j, k] = top / bot
  */
                   __pyx_v_bot = (__pyx_v_bot + __pyx_v_ker);
-                  goto __pyx_L18;
+                  goto __pyx_L21;
                 }
-                __pyx_L18:;
+                __pyx_L21:;
               }
             }
           }
@@ -3762,8 +3567,8 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_4convol
             __pyx_t_36 = __pyx_v_i;
             __pyx_t_37 = __pyx_v_j;
             __pyx_t_38 = __pyx_v_k;
-            *__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_36, __pyx_pybuffernd_fixed.diminfo[0].strides, __pyx_t_37, __pyx_pybuffernd_fixed.diminfo[1].strides, __pyx_t_38, __pyx_pybuffernd_fixed.diminfo[2].strides) = (__pyx_v_top / __pyx_v_bot);
-            goto __pyx_L19;
+            *__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_36, __pyx_bstride_0_fixed, __pyx_t_37, __pyx_bstride_1_fixed, __pyx_t_38, __pyx_bstride_2_fixed) = (__pyx_v_top / __pyx_v_bot);
+            goto __pyx_L22;
           }
           /*else*/ {
 
@@ -3780,10 +3585,10 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_4convol
             __pyx_t_42 = __pyx_v_i;
             __pyx_t_43 = __pyx_v_j;
             __pyx_t_44 = __pyx_v_k;
-            *__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_42, __pyx_pybuffernd_fixed.diminfo[0].strides, __pyx_t_43, __pyx_pybuffernd_fixed.diminfo[1].strides, __pyx_t_44, __pyx_pybuffernd_fixed.diminfo[2].strides) = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_pybuffernd_f.rcbuffer->pybuffer.buf, __pyx_t_39, __pyx_pybuffernd_f.diminfo[0].strides, __pyx_t_40, __pyx_pybuffernd_f.diminfo[1].strides, __pyx_t_41, __pyx_pybuffernd_f.diminfo[2].strides));
+            *__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_42, __pyx_bstride_0_fixed, __pyx_t_43, __pyx_bstride_1_fixed, __pyx_t_44, __pyx_bstride_2_fixed) = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_bstruct_f.buf, __pyx_t_39, __pyx_bstride_0_f, __pyx_t_40, __pyx_bstride_1_f, __pyx_t_41, __pyx_bstride_2_f));
           }
-          __pyx_L19:;
-          goto __pyx_L10;
+          __pyx_L22:;
+          goto __pyx_L13;
         }
         /*else*/ {
 
@@ -3800,9 +3605,9 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_4convol
           __pyx_t_48 = __pyx_v_i;
           __pyx_t_49 = __pyx_v_j;
           __pyx_t_50 = __pyx_v_k;
-          *__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_48, __pyx_pybuffernd_fixed.diminfo[0].strides, __pyx_t_49, __pyx_pybuffernd_fixed.diminfo[1].strides, __pyx_t_50, __pyx_pybuffernd_fixed.diminfo[2].strides) = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_pybuffernd_f.rcbuffer->pybuffer.buf, __pyx_t_45, __pyx_pybuffernd_f.diminfo[0].strides, __pyx_t_46, __pyx_pybuffernd_f.diminfo[1].strides, __pyx_t_47, __pyx_pybuffernd_f.diminfo[2].strides));
+          *__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_48, __pyx_bstride_0_fixed, __pyx_t_49, __pyx_bstride_1_fixed, __pyx_t_50, __pyx_bstride_2_fixed) = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_bstruct_f.buf, __pyx_t_45, __pyx_bstride_0_f, __pyx_t_46, __pyx_bstride_1_f, __pyx_t_47, __pyx_bstride_2_f));
         }
-        __pyx_L10:;
+        __pyx_L13:;
       }
     }
   }
@@ -3850,7 +3655,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_4convol
         __pyx_t_51 = __pyx_v_i;
         __pyx_t_52 = __pyx_v_j;
         __pyx_t_53 = __pyx_v_k;
-        __pyx_t_2 = (!npy_isnan((*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_51, __pyx_pybuffernd_fixed.diminfo[0].strides, __pyx_t_52, __pyx_pybuffernd_fixed.diminfo[1].strides, __pyx_t_53, __pyx_pybuffernd_fixed.diminfo[2].strides))));
+        __pyx_t_2 = (!npy_isnan((*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_51, __pyx_bstride_0_fixed, __pyx_t_52, __pyx_bstride_1_fixed, __pyx_t_53, __pyx_bstride_2_fixed))));
         if (__pyx_t_2) {
 
           /* "astropy/nddata/convolution/boundary_fill.pyx":238
@@ -4006,7 +3811,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_4convol
  *                                     val = fixed[ii, jj, kk]
  */
                   __pyx_v_val = __pyx_v_fill_value;
-                  goto __pyx_L33;
+                  goto __pyx_L36;
                 }
                 /*else*/ {
 
@@ -4020,12 +3825,12 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_4convol
                   __pyx_t_54 = __pyx_v_ii;
                   __pyx_t_55 = __pyx_v_jj;
                   __pyx_t_56 = __pyx_v_kk;
-                  if (__pyx_t_54 < 0) __pyx_t_54 += __pyx_pybuffernd_fixed.diminfo[0].shape;
-                  if (__pyx_t_55 < 0) __pyx_t_55 += __pyx_pybuffernd_fixed.diminfo[1].shape;
-                  if (__pyx_t_56 < 0) __pyx_t_56 += __pyx_pybuffernd_fixed.diminfo[2].shape;
-                  __pyx_v_val = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_54, __pyx_pybuffernd_fixed.diminfo[0].strides, __pyx_t_55, __pyx_pybuffernd_fixed.diminfo[1].strides, __pyx_t_56, __pyx_pybuffernd_fixed.diminfo[2].strides));
+                  if (__pyx_t_54 < 0) __pyx_t_54 += __pyx_bshape_0_fixed;
+                  if (__pyx_t_55 < 0) __pyx_t_55 += __pyx_bshape_1_fixed;
+                  if (__pyx_t_56 < 0) __pyx_t_56 += __pyx_bshape_2_fixed;
+                  __pyx_v_val = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_54, __pyx_bstride_0_fixed, __pyx_t_55, __pyx_bstride_1_fixed, __pyx_t_56, __pyx_bstride_2_fixed));
                 }
-                __pyx_L33:;
+                __pyx_L36:;
 
                 /* "astropy/nddata/convolution/boundary_fill.pyx":255
  *                                 ker = g[<unsigned int>(wkx + ii - i),
@@ -4037,7 +3842,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_4convol
                 __pyx_t_57 = ((unsigned int)((__pyx_v_wkx + __pyx_v_ii) - __pyx_v_i));
                 __pyx_t_58 = ((unsigned int)((__pyx_v_wky + __pyx_v_jj) - __pyx_v_j));
                 __pyx_t_59 = ((unsigned int)((__pyx_v_wkz + __pyx_v_kk) - __pyx_v_k));
-                __pyx_v_ker = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_pybuffernd_g.rcbuffer->pybuffer.buf, __pyx_t_57, __pyx_pybuffernd_g.diminfo[0].strides, __pyx_t_58, __pyx_pybuffernd_g.diminfo[1].strides, __pyx_t_59, __pyx_pybuffernd_g.diminfo[2].strides));
+                __pyx_v_ker = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_bstruct_g.buf, __pyx_t_57, __pyx_bstride_0_g, __pyx_t_58, __pyx_bstride_1_g, __pyx_t_59, __pyx_bstride_2_g));
 
                 /* "astropy/nddata/convolution/boundary_fill.pyx":256
  *                                         <unsigned int>(wky + jj - j),
@@ -4066,9 +3871,9 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_4convol
  *                         conv[i, j, k] = top / bot
  */
                   __pyx_v_bot = (__pyx_v_bot + __pyx_v_ker);
-                  goto __pyx_L34;
+                  goto __pyx_L37;
                 }
-                __pyx_L34:;
+                __pyx_L37:;
               }
             }
           }
@@ -4097,8 +3902,8 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_4convol
             __pyx_t_60 = __pyx_v_i;
             __pyx_t_61 = __pyx_v_j;
             __pyx_t_62 = __pyx_v_k;
-            *__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_pybuffernd_conv.rcbuffer->pybuffer.buf, __pyx_t_60, __pyx_pybuffernd_conv.diminfo[0].strides, __pyx_t_61, __pyx_pybuffernd_conv.diminfo[1].strides, __pyx_t_62, __pyx_pybuffernd_conv.diminfo[2].strides) = (__pyx_v_top / __pyx_v_bot);
-            goto __pyx_L35;
+            *__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_bstruct_conv.buf, __pyx_t_60, __pyx_bstride_0_conv, __pyx_t_61, __pyx_bstride_1_conv, __pyx_t_62, __pyx_bstride_2_conv) = (__pyx_v_top / __pyx_v_bot);
+            goto __pyx_L38;
           }
           /*else*/ {
 
@@ -4115,10 +3920,10 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_4convol
             __pyx_t_66 = __pyx_v_i;
             __pyx_t_67 = __pyx_v_j;
             __pyx_t_68 = __pyx_v_k;
-            *__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_pybuffernd_conv.rcbuffer->pybuffer.buf, __pyx_t_66, __pyx_pybuffernd_conv.diminfo[0].strides, __pyx_t_67, __pyx_pybuffernd_conv.diminfo[1].strides, __pyx_t_68, __pyx_pybuffernd_conv.diminfo[2].strides) = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_63, __pyx_pybuffernd_fixed.diminfo[0].strides, __pyx_t_64, __pyx_pybuffernd_fixed.diminfo[1].strides, __pyx_t_65, __pyx_pybuffernd_fixed.diminfo[2].strides));
+            *__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_bstruct_conv.buf, __pyx_t_66, __pyx_bstride_0_conv, __pyx_t_67, __pyx_bstride_1_conv, __pyx_t_68, __pyx_bstride_2_conv) = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_63, __pyx_bstride_0_fixed, __pyx_t_64, __pyx_bstride_1_fixed, __pyx_t_65, __pyx_bstride_2_fixed));
           }
-          __pyx_L35:;
-          goto __pyx_L26;
+          __pyx_L38:;
+          goto __pyx_L29;
         }
         /*else*/ {
 
@@ -4135,9 +3940,9 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_4convol
           __pyx_t_72 = __pyx_v_i;
           __pyx_t_73 = __pyx_v_j;
           __pyx_t_74 = __pyx_v_k;
-          *__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_pybuffernd_conv.rcbuffer->pybuffer.buf, __pyx_t_72, __pyx_pybuffernd_conv.diminfo[0].strides, __pyx_t_73, __pyx_pybuffernd_conv.diminfo[1].strides, __pyx_t_74, __pyx_pybuffernd_conv.diminfo[2].strides) = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_69, __pyx_pybuffernd_fixed.diminfo[0].strides, __pyx_t_70, __pyx_pybuffernd_fixed.diminfo[1].strides, __pyx_t_71, __pyx_pybuffernd_fixed.diminfo[2].strides));
+          *__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_bstruct_conv.buf, __pyx_t_72, __pyx_bstride_0_conv, __pyx_t_73, __pyx_bstride_1_conv, __pyx_t_74, __pyx_bstride_2_conv) = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_fill_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_69, __pyx_bstride_0_fixed, __pyx_t_70, __pyx_bstride_1_fixed, __pyx_t_71, __pyx_bstride_2_fixed));
         }
-        __pyx_L26:;
+        __pyx_L29:;
       }
     }
   }
@@ -4162,19 +3967,19 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_4convol
   __Pyx_XDECREF(__pyx_t_9);
   { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;
     __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);
-    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_conv.rcbuffer->pybuffer);
-    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_f.rcbuffer->pybuffer);
-    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_fixed.rcbuffer->pybuffer);
-    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_g.rcbuffer->pybuffer);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_conv);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_g);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_f);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_fixed);
   __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
   __Pyx_AddTraceback("astropy.nddata.convolution.boundary_fill.convolve3d_boundary_fill", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   goto __pyx_L2;
   __pyx_L0:;
-  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_conv.rcbuffer->pybuffer);
-  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_f.rcbuffer->pybuffer);
-  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_fixed.rcbuffer->pybuffer);
-  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_g.rcbuffer->pybuffer);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_conv);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_g);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_f);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_fixed);
   __pyx_L2:;
   __Pyx_XDECREF((PyObject *)__pyx_v_fixed);
   __Pyx_XDECREF((PyObject *)__pyx_v_conv);
@@ -4183,18 +3988,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_fill_4convol
   return __pyx_r;
 }
 
-/* Python wrapper */
-static int __pyx_pw_5numpy_7ndarray_1__getbuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags); /*proto*/
-static int __pyx_pw_5numpy_7ndarray_1__getbuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags) {
-  int __pyx_r;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__getbuffer__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_5numpy_7ndarray___getbuffer__(((PyArrayObject *)__pyx_v_self), ((Py_buffer *)__pyx_v_info), ((int)__pyx_v_flags));
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-/* "numpy.pxd":193
+/* "numpy.pxd":190
  *         # experimental exception made for __getbuffer__ and __releasebuffer__
  *         # -- the details of this may change.
  *         def __getbuffer__(ndarray self, Py_buffer* info, int flags):             # <<<<<<<<<<<<<<
@@ -4202,7 +3996,8 @@ static int __pyx_pw_5numpy_7ndarray_1__getbuffer__(PyObject *__pyx_v_self, Py_bu
  *             # requirements, and does not yet fullfill the PEP.
  */
 
-static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags) {
+static CYTHON_UNUSED int __pyx_pf_5numpy_7ndarray___getbuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags); /*proto*/
+static CYTHON_UNUSED int __pyx_pf_5numpy_7ndarray___getbuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags) {
   int __pyx_v_copy_shape;
   int __pyx_v_i;
   int __pyx_v_ndim;
@@ -4227,13 +4022,13 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("__getbuffer__", 0);
+  __Pyx_RefNannySetupContext("__getbuffer__");
   if (__pyx_v_info != NULL) {
     __pyx_v_info->obj = Py_None; __Pyx_INCREF(Py_None);
     __Pyx_GIVEREF(__pyx_v_info->obj);
   }
 
-  /* "numpy.pxd":199
+  /* "numpy.pxd":196
  *             # of flags
  * 
  *             if info == NULL: return             # <<<<<<<<<<<<<<
@@ -4244,11 +4039,11 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
   if (__pyx_t_1) {
     __pyx_r = 0;
     goto __pyx_L0;
-    goto __pyx_L3;
+    goto __pyx_L5;
   }
-  __pyx_L3:;
+  __pyx_L5:;
 
-  /* "numpy.pxd":202
+  /* "numpy.pxd":199
  * 
  *             cdef int copy_shape, i, ndim
  *             cdef int endian_detector = 1             # <<<<<<<<<<<<<<
@@ -4257,7 +4052,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
   __pyx_v_endian_detector = 1;
 
-  /* "numpy.pxd":203
+  /* "numpy.pxd":200
  *             cdef int copy_shape, i, ndim
  *             cdef int endian_detector = 1
  *             cdef bint little_endian = ((<char*>&endian_detector)[0] != 0)             # <<<<<<<<<<<<<<
@@ -4266,16 +4061,16 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
   __pyx_v_little_endian = ((((char *)(&__pyx_v_endian_detector))[0]) != 0);
 
-  /* "numpy.pxd":205
+  /* "numpy.pxd":202
  *             cdef bint little_endian = ((<char*>&endian_detector)[0] != 0)
  * 
  *             ndim = PyArray_NDIM(self)             # <<<<<<<<<<<<<<
  * 
  *             if sizeof(npy_intp) != sizeof(Py_ssize_t):
  */
-  __pyx_v_ndim = PyArray_NDIM(__pyx_v_self);
+  __pyx_v_ndim = PyArray_NDIM(((PyArrayObject *)__pyx_v_self));
 
-  /* "numpy.pxd":207
+  /* "numpy.pxd":204
  *             ndim = PyArray_NDIM(self)
  * 
  *             if sizeof(npy_intp) != sizeof(Py_ssize_t):             # <<<<<<<<<<<<<<
@@ -4285,7 +4080,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
   __pyx_t_1 = ((sizeof(npy_intp)) != (sizeof(Py_ssize_t)));
   if (__pyx_t_1) {
 
-    /* "numpy.pxd":208
+    /* "numpy.pxd":205
  * 
  *             if sizeof(npy_intp) != sizeof(Py_ssize_t):
  *                 copy_shape = 1             # <<<<<<<<<<<<<<
@@ -4293,11 +4088,11 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  *                 copy_shape = 0
  */
     __pyx_v_copy_shape = 1;
-    goto __pyx_L4;
+    goto __pyx_L6;
   }
   /*else*/ {
 
-    /* "numpy.pxd":210
+    /* "numpy.pxd":207
  *                 copy_shape = 1
  *             else:
  *                 copy_shape = 0             # <<<<<<<<<<<<<<
@@ -4306,9 +4101,9 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
     __pyx_v_copy_shape = 0;
   }
-  __pyx_L4:;
+  __pyx_L6:;
 
-  /* "numpy.pxd":212
+  /* "numpy.pxd":209
  *                 copy_shape = 0
  * 
  *             if ((flags & pybuf.PyBUF_C_CONTIGUOUS == pybuf.PyBUF_C_CONTIGUOUS)             # <<<<<<<<<<<<<<
@@ -4318,37 +4113,37 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
   __pyx_t_1 = ((__pyx_v_flags & PyBUF_C_CONTIGUOUS) == PyBUF_C_CONTIGUOUS);
   if (__pyx_t_1) {
 
-    /* "numpy.pxd":213
+    /* "numpy.pxd":210
  * 
  *             if ((flags & pybuf.PyBUF_C_CONTIGUOUS == pybuf.PyBUF_C_CONTIGUOUS)
  *                 and not PyArray_CHKFLAGS(self, NPY_C_CONTIGUOUS)):             # <<<<<<<<<<<<<<
  *                 raise ValueError(u"ndarray is not C contiguous")
  * 
  */
-    __pyx_t_2 = (!PyArray_CHKFLAGS(__pyx_v_self, NPY_C_CONTIGUOUS));
+    __pyx_t_2 = (!PyArray_CHKFLAGS(((PyArrayObject *)__pyx_v_self), NPY_C_CONTIGUOUS));
     __pyx_t_3 = __pyx_t_2;
   } else {
     __pyx_t_3 = __pyx_t_1;
   }
   if (__pyx_t_3) {
 
-    /* "numpy.pxd":214
+    /* "numpy.pxd":211
  *             if ((flags & pybuf.PyBUF_C_CONTIGUOUS == pybuf.PyBUF_C_CONTIGUOUS)
  *                 and not PyArray_CHKFLAGS(self, NPY_C_CONTIGUOUS)):
  *                 raise ValueError(u"ndarray is not C contiguous")             # <<<<<<<<<<<<<<
  * 
  *             if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS)
  */
-    __pyx_t_4 = PyObject_Call(__pyx_builtin_ValueError, ((PyObject *)__pyx_k_tuple_6), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 214; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = PyObject_Call(__pyx_builtin_ValueError, ((PyObject *)__pyx_k_tuple_6), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 211; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_4);
     __Pyx_Raise(__pyx_t_4, 0, 0, 0);
     __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-    {__pyx_filename = __pyx_f[1]; __pyx_lineno = 214; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    goto __pyx_L5;
+    {__pyx_filename = __pyx_f[1]; __pyx_lineno = 211; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    goto __pyx_L7;
   }
-  __pyx_L5:;
+  __pyx_L7:;
 
-  /* "numpy.pxd":216
+  /* "numpy.pxd":213
  *                 raise ValueError(u"ndarray is not C contiguous")
  * 
  *             if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS)             # <<<<<<<<<<<<<<
@@ -4358,46 +4153,46 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
   __pyx_t_3 = ((__pyx_v_flags & PyBUF_F_CONTIGUOUS) == PyBUF_F_CONTIGUOUS);
   if (__pyx_t_3) {
 
-    /* "numpy.pxd":217
+    /* "numpy.pxd":214
  * 
  *             if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS)
  *                 and not PyArray_CHKFLAGS(self, NPY_F_CONTIGUOUS)):             # <<<<<<<<<<<<<<
  *                 raise ValueError(u"ndarray is not Fortran contiguous")
  * 
  */
-    __pyx_t_1 = (!PyArray_CHKFLAGS(__pyx_v_self, NPY_F_CONTIGUOUS));
+    __pyx_t_1 = (!PyArray_CHKFLAGS(((PyArrayObject *)__pyx_v_self), NPY_F_CONTIGUOUS));
     __pyx_t_2 = __pyx_t_1;
   } else {
     __pyx_t_2 = __pyx_t_3;
   }
   if (__pyx_t_2) {
 
-    /* "numpy.pxd":218
+    /* "numpy.pxd":215
  *             if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS)
  *                 and not PyArray_CHKFLAGS(self, NPY_F_CONTIGUOUS)):
  *                 raise ValueError(u"ndarray is not Fortran contiguous")             # <<<<<<<<<<<<<<
  * 
  *             info.buf = PyArray_DATA(self)
  */
-    __pyx_t_4 = PyObject_Call(__pyx_builtin_ValueError, ((PyObject *)__pyx_k_tuple_8), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 218; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = PyObject_Call(__pyx_builtin_ValueError, ((PyObject *)__pyx_k_tuple_8), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 215; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_4);
     __Pyx_Raise(__pyx_t_4, 0, 0, 0);
     __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-    {__pyx_filename = __pyx_f[1]; __pyx_lineno = 218; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    goto __pyx_L6;
+    {__pyx_filename = __pyx_f[1]; __pyx_lineno = 215; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    goto __pyx_L8;
   }
-  __pyx_L6:;
+  __pyx_L8:;
 
-  /* "numpy.pxd":220
+  /* "numpy.pxd":217
  *                 raise ValueError(u"ndarray is not Fortran contiguous")
  * 
  *             info.buf = PyArray_DATA(self)             # <<<<<<<<<<<<<<
  *             info.ndim = ndim
  *             if copy_shape:
  */
-  __pyx_v_info->buf = PyArray_DATA(__pyx_v_self);
+  __pyx_v_info->buf = PyArray_DATA(((PyArrayObject *)__pyx_v_self));
 
-  /* "numpy.pxd":221
+  /* "numpy.pxd":218
  * 
  *             info.buf = PyArray_DATA(self)
  *             info.ndim = ndim             # <<<<<<<<<<<<<<
@@ -4406,7 +4201,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
   __pyx_v_info->ndim = __pyx_v_ndim;
 
-  /* "numpy.pxd":222
+  /* "numpy.pxd":219
  *             info.buf = PyArray_DATA(self)
  *             info.ndim = ndim
  *             if copy_shape:             # <<<<<<<<<<<<<<
@@ -4415,7 +4210,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
   if (__pyx_v_copy_shape) {
 
-    /* "numpy.pxd":225
+    /* "numpy.pxd":222
  *                 # Allocate new buffer for strides and shape info.
  *                 # This is allocated as one block, strides first.
  *                 info.strides = <Py_ssize_t*>stdlib.malloc(sizeof(Py_ssize_t) * <size_t>ndim * 2)             # <<<<<<<<<<<<<<
@@ -4424,7 +4219,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
     __pyx_v_info->strides = ((Py_ssize_t *)malloc((((sizeof(Py_ssize_t)) * ((size_t)__pyx_v_ndim)) * 2)));
 
-    /* "numpy.pxd":226
+    /* "numpy.pxd":223
  *                 # This is allocated as one block, strides first.
  *                 info.strides = <Py_ssize_t*>stdlib.malloc(sizeof(Py_ssize_t) * <size_t>ndim * 2)
  *                 info.shape = info.strides + ndim             # <<<<<<<<<<<<<<
@@ -4433,7 +4228,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
     __pyx_v_info->shape = (__pyx_v_info->strides + __pyx_v_ndim);
 
-    /* "numpy.pxd":227
+    /* "numpy.pxd":224
  *                 info.strides = <Py_ssize_t*>stdlib.malloc(sizeof(Py_ssize_t) * <size_t>ndim * 2)
  *                 info.shape = info.strides + ndim
  *                 for i in range(ndim):             # <<<<<<<<<<<<<<
@@ -4444,49 +4239,49 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     for (__pyx_t_6 = 0; __pyx_t_6 < __pyx_t_5; __pyx_t_6+=1) {
       __pyx_v_i = __pyx_t_6;
 
-      /* "numpy.pxd":228
+      /* "numpy.pxd":225
  *                 info.shape = info.strides + ndim
  *                 for i in range(ndim):
  *                     info.strides[i] = PyArray_STRIDES(self)[i]             # <<<<<<<<<<<<<<
  *                     info.shape[i] = PyArray_DIMS(self)[i]
  *             else:
  */
-      (__pyx_v_info->strides[__pyx_v_i]) = (PyArray_STRIDES(__pyx_v_self)[__pyx_v_i]);
+      (__pyx_v_info->strides[__pyx_v_i]) = (PyArray_STRIDES(((PyArrayObject *)__pyx_v_self))[__pyx_v_i]);
 
-      /* "numpy.pxd":229
+      /* "numpy.pxd":226
  *                 for i in range(ndim):
  *                     info.strides[i] = PyArray_STRIDES(self)[i]
  *                     info.shape[i] = PyArray_DIMS(self)[i]             # <<<<<<<<<<<<<<
  *             else:
  *                 info.strides = <Py_ssize_t*>PyArray_STRIDES(self)
  */
-      (__pyx_v_info->shape[__pyx_v_i]) = (PyArray_DIMS(__pyx_v_self)[__pyx_v_i]);
+      (__pyx_v_info->shape[__pyx_v_i]) = (PyArray_DIMS(((PyArrayObject *)__pyx_v_self))[__pyx_v_i]);
     }
-    goto __pyx_L7;
+    goto __pyx_L9;
   }
   /*else*/ {
 
-    /* "numpy.pxd":231
+    /* "numpy.pxd":228
  *                     info.shape[i] = PyArray_DIMS(self)[i]
  *             else:
  *                 info.strides = <Py_ssize_t*>PyArray_STRIDES(self)             # <<<<<<<<<<<<<<
  *                 info.shape = <Py_ssize_t*>PyArray_DIMS(self)
  *             info.suboffsets = NULL
  */
-    __pyx_v_info->strides = ((Py_ssize_t *)PyArray_STRIDES(__pyx_v_self));
+    __pyx_v_info->strides = ((Py_ssize_t *)PyArray_STRIDES(((PyArrayObject *)__pyx_v_self)));
 
-    /* "numpy.pxd":232
+    /* "numpy.pxd":229
  *             else:
  *                 info.strides = <Py_ssize_t*>PyArray_STRIDES(self)
  *                 info.shape = <Py_ssize_t*>PyArray_DIMS(self)             # <<<<<<<<<<<<<<
  *             info.suboffsets = NULL
  *             info.itemsize = PyArray_ITEMSIZE(self)
  */
-    __pyx_v_info->shape = ((Py_ssize_t *)PyArray_DIMS(__pyx_v_self));
+    __pyx_v_info->shape = ((Py_ssize_t *)PyArray_DIMS(((PyArrayObject *)__pyx_v_self)));
   }
-  __pyx_L7:;
+  __pyx_L9:;
 
-  /* "numpy.pxd":233
+  /* "numpy.pxd":230
  *                 info.strides = <Py_ssize_t*>PyArray_STRIDES(self)
  *                 info.shape = <Py_ssize_t*>PyArray_DIMS(self)
  *             info.suboffsets = NULL             # <<<<<<<<<<<<<<
@@ -4495,25 +4290,25 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
   __pyx_v_info->suboffsets = NULL;
 
-  /* "numpy.pxd":234
+  /* "numpy.pxd":231
  *                 info.shape = <Py_ssize_t*>PyArray_DIMS(self)
  *             info.suboffsets = NULL
  *             info.itemsize = PyArray_ITEMSIZE(self)             # <<<<<<<<<<<<<<
  *             info.readonly = not PyArray_ISWRITEABLE(self)
  * 
  */
-  __pyx_v_info->itemsize = PyArray_ITEMSIZE(__pyx_v_self);
+  __pyx_v_info->itemsize = PyArray_ITEMSIZE(((PyArrayObject *)__pyx_v_self));
 
-  /* "numpy.pxd":235
+  /* "numpy.pxd":232
  *             info.suboffsets = NULL
  *             info.itemsize = PyArray_ITEMSIZE(self)
  *             info.readonly = not PyArray_ISWRITEABLE(self)             # <<<<<<<<<<<<<<
  * 
  *             cdef int t
  */
-  __pyx_v_info->readonly = (!PyArray_ISWRITEABLE(__pyx_v_self));
+  __pyx_v_info->readonly = (!PyArray_ISWRITEABLE(((PyArrayObject *)__pyx_v_self)));
 
-  /* "numpy.pxd":238
+  /* "numpy.pxd":235
  * 
  *             cdef int t
  *             cdef char* f = NULL             # <<<<<<<<<<<<<<
@@ -4522,17 +4317,17 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
   __pyx_v_f = NULL;
 
-  /* "numpy.pxd":239
+  /* "numpy.pxd":236
  *             cdef int t
  *             cdef char* f = NULL
  *             cdef dtype descr = self.descr             # <<<<<<<<<<<<<<
  *             cdef list stack
  *             cdef int offset
  */
-  __Pyx_INCREF(((PyObject *)__pyx_v_self->descr));
-  __pyx_v_descr = __pyx_v_self->descr;
+  __Pyx_INCREF(((PyObject *)((PyArrayObject *)__pyx_v_self)->descr));
+  __pyx_v_descr = ((PyArrayObject *)__pyx_v_self)->descr;
 
-  /* "numpy.pxd":243
+  /* "numpy.pxd":240
  *             cdef int offset
  * 
  *             cdef bint hasfields = PyDataType_HASFIELDS(descr)             # <<<<<<<<<<<<<<
@@ -4541,7 +4336,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
   __pyx_v_hasfields = PyDataType_HASFIELDS(__pyx_v_descr);
 
-  /* "numpy.pxd":245
+  /* "numpy.pxd":242
  *             cdef bint hasfields = PyDataType_HASFIELDS(descr)
  * 
  *             if not hasfields and not copy_shape:             # <<<<<<<<<<<<<<
@@ -4557,7 +4352,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
   }
   if (__pyx_t_1) {
 
-    /* "numpy.pxd":247
+    /* "numpy.pxd":244
  *             if not hasfields and not copy_shape:
  *                 # do not call releasebuffer
  *                 info.obj = None             # <<<<<<<<<<<<<<
@@ -4569,26 +4364,26 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __Pyx_GOTREF(__pyx_v_info->obj);
     __Pyx_DECREF(__pyx_v_info->obj);
     __pyx_v_info->obj = Py_None;
-    goto __pyx_L10;
+    goto __pyx_L12;
   }
   /*else*/ {
 
-    /* "numpy.pxd":250
+    /* "numpy.pxd":247
  *             else:
  *                 # need to call releasebuffer
  *                 info.obj = self             # <<<<<<<<<<<<<<
  * 
  *             if not hasfields:
  */
-    __Pyx_INCREF(((PyObject *)__pyx_v_self));
-    __Pyx_GIVEREF(((PyObject *)__pyx_v_self));
+    __Pyx_INCREF(__pyx_v_self);
+    __Pyx_GIVEREF(__pyx_v_self);
     __Pyx_GOTREF(__pyx_v_info->obj);
     __Pyx_DECREF(__pyx_v_info->obj);
-    __pyx_v_info->obj = ((PyObject *)__pyx_v_self);
+    __pyx_v_info->obj = __pyx_v_self;
   }
-  __pyx_L10:;
+  __pyx_L12:;
 
-  /* "numpy.pxd":252
+  /* "numpy.pxd":249
  *                 info.obj = self
  * 
  *             if not hasfields:             # <<<<<<<<<<<<<<
@@ -4598,7 +4393,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
   __pyx_t_1 = (!__pyx_v_hasfields);
   if (__pyx_t_1) {
 
-    /* "numpy.pxd":253
+    /* "numpy.pxd":250
  * 
  *             if not hasfields:
  *                 t = descr.type_num             # <<<<<<<<<<<<<<
@@ -4607,7 +4402,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
     __pyx_v_t = __pyx_v_descr->type_num;
 
-    /* "numpy.pxd":254
+    /* "numpy.pxd":251
  *             if not hasfields:
  *                 t = descr.type_num
  *                 if ((descr.byteorder == '>' and little_endian) or             # <<<<<<<<<<<<<<
@@ -4622,7 +4417,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     }
     if (!__pyx_t_2) {
 
-      /* "numpy.pxd":255
+      /* "numpy.pxd":252
  *                 t = descr.type_num
  *                 if ((descr.byteorder == '>' and little_endian) or
  *                     (descr.byteorder == '<' and not little_endian)):             # <<<<<<<<<<<<<<
@@ -4642,23 +4437,23 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     }
     if (__pyx_t_1) {
 
-      /* "numpy.pxd":256
+      /* "numpy.pxd":253
  *                 if ((descr.byteorder == '>' and little_endian) or
  *                     (descr.byteorder == '<' and not little_endian)):
  *                     raise ValueError(u"Non-native byte order not supported")             # <<<<<<<<<<<<<<
  *                 if   t == NPY_BYTE:        f = "b"
  *                 elif t == NPY_UBYTE:       f = "B"
  */
-      __pyx_t_4 = PyObject_Call(__pyx_builtin_ValueError, ((PyObject *)__pyx_k_tuple_10), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 256; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyObject_Call(__pyx_builtin_ValueError, ((PyObject *)__pyx_k_tuple_10), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 253; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_4);
       __Pyx_Raise(__pyx_t_4, 0, 0, 0);
       __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      {__pyx_filename = __pyx_f[1]; __pyx_lineno = 256; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      goto __pyx_L12;
+      {__pyx_filename = __pyx_f[1]; __pyx_lineno = 253; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      goto __pyx_L14;
     }
-    __pyx_L12:;
+    __pyx_L14:;
 
-    /* "numpy.pxd":257
+    /* "numpy.pxd":254
  *                     (descr.byteorder == '<' and not little_endian)):
  *                     raise ValueError(u"Non-native byte order not supported")
  *                 if   t == NPY_BYTE:        f = "b"             # <<<<<<<<<<<<<<
@@ -4668,10 +4463,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_BYTE);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__b;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":258
+    /* "numpy.pxd":255
  *                     raise ValueError(u"Non-native byte order not supported")
  *                 if   t == NPY_BYTE:        f = "b"
  *                 elif t == NPY_UBYTE:       f = "B"             # <<<<<<<<<<<<<<
@@ -4681,10 +4476,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_UBYTE);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__B;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":259
+    /* "numpy.pxd":256
  *                 if   t == NPY_BYTE:        f = "b"
  *                 elif t == NPY_UBYTE:       f = "B"
  *                 elif t == NPY_SHORT:       f = "h"             # <<<<<<<<<<<<<<
@@ -4694,10 +4489,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_SHORT);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__h;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":260
+    /* "numpy.pxd":257
  *                 elif t == NPY_UBYTE:       f = "B"
  *                 elif t == NPY_SHORT:       f = "h"
  *                 elif t == NPY_USHORT:      f = "H"             # <<<<<<<<<<<<<<
@@ -4707,10 +4502,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_USHORT);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__H;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":261
+    /* "numpy.pxd":258
  *                 elif t == NPY_SHORT:       f = "h"
  *                 elif t == NPY_USHORT:      f = "H"
  *                 elif t == NPY_INT:         f = "i"             # <<<<<<<<<<<<<<
@@ -4720,10 +4515,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_INT);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__i;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":262
+    /* "numpy.pxd":259
  *                 elif t == NPY_USHORT:      f = "H"
  *                 elif t == NPY_INT:         f = "i"
  *                 elif t == NPY_UINT:        f = "I"             # <<<<<<<<<<<<<<
@@ -4733,10 +4528,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_UINT);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__I;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":263
+    /* "numpy.pxd":260
  *                 elif t == NPY_INT:         f = "i"
  *                 elif t == NPY_UINT:        f = "I"
  *                 elif t == NPY_LONG:        f = "l"             # <<<<<<<<<<<<<<
@@ -4746,10 +4541,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_LONG);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__l;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":264
+    /* "numpy.pxd":261
  *                 elif t == NPY_UINT:        f = "I"
  *                 elif t == NPY_LONG:        f = "l"
  *                 elif t == NPY_ULONG:       f = "L"             # <<<<<<<<<<<<<<
@@ -4759,10 +4554,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_ULONG);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__L;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":265
+    /* "numpy.pxd":262
  *                 elif t == NPY_LONG:        f = "l"
  *                 elif t == NPY_ULONG:       f = "L"
  *                 elif t == NPY_LONGLONG:    f = "q"             # <<<<<<<<<<<<<<
@@ -4772,10 +4567,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_LONGLONG);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__q;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":266
+    /* "numpy.pxd":263
  *                 elif t == NPY_ULONG:       f = "L"
  *                 elif t == NPY_LONGLONG:    f = "q"
  *                 elif t == NPY_ULONGLONG:   f = "Q"             # <<<<<<<<<<<<<<
@@ -4785,10 +4580,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_ULONGLONG);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__Q;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":267
+    /* "numpy.pxd":264
  *                 elif t == NPY_LONGLONG:    f = "q"
  *                 elif t == NPY_ULONGLONG:   f = "Q"
  *                 elif t == NPY_FLOAT:       f = "f"             # <<<<<<<<<<<<<<
@@ -4798,10 +4593,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_FLOAT);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__f;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":268
+    /* "numpy.pxd":265
  *                 elif t == NPY_ULONGLONG:   f = "Q"
  *                 elif t == NPY_FLOAT:       f = "f"
  *                 elif t == NPY_DOUBLE:      f = "d"             # <<<<<<<<<<<<<<
@@ -4811,10 +4606,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_DOUBLE);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__d;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":269
+    /* "numpy.pxd":266
  *                 elif t == NPY_FLOAT:       f = "f"
  *                 elif t == NPY_DOUBLE:      f = "d"
  *                 elif t == NPY_LONGDOUBLE:  f = "g"             # <<<<<<<<<<<<<<
@@ -4824,10 +4619,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_LONGDOUBLE);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__g;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":270
+    /* "numpy.pxd":267
  *                 elif t == NPY_DOUBLE:      f = "d"
  *                 elif t == NPY_LONGDOUBLE:  f = "g"
  *                 elif t == NPY_CFLOAT:      f = "Zf"             # <<<<<<<<<<<<<<
@@ -4837,10 +4632,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_CFLOAT);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__Zf;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":271
+    /* "numpy.pxd":268
  *                 elif t == NPY_LONGDOUBLE:  f = "g"
  *                 elif t == NPY_CFLOAT:      f = "Zf"
  *                 elif t == NPY_CDOUBLE:     f = "Zd"             # <<<<<<<<<<<<<<
@@ -4850,10 +4645,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_CDOUBLE);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__Zd;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":272
+    /* "numpy.pxd":269
  *                 elif t == NPY_CFLOAT:      f = "Zf"
  *                 elif t == NPY_CDOUBLE:     f = "Zd"
  *                 elif t == NPY_CLONGDOUBLE: f = "Zg"             # <<<<<<<<<<<<<<
@@ -4863,10 +4658,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_CLONGDOUBLE);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__Zg;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":273
+    /* "numpy.pxd":270
  *                 elif t == NPY_CDOUBLE:     f = "Zd"
  *                 elif t == NPY_CLONGDOUBLE: f = "Zg"
  *                 elif t == NPY_OBJECT:      f = "O"             # <<<<<<<<<<<<<<
@@ -4876,37 +4671,37 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_OBJECT);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__O;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
     /*else*/ {
 
-      /* "numpy.pxd":275
+      /* "numpy.pxd":272
  *                 elif t == NPY_OBJECT:      f = "O"
  *                 else:
  *                     raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t)             # <<<<<<<<<<<<<<
  *                 info.format = f
  *                 return
  */
-      __pyx_t_4 = PyInt_FromLong(__pyx_v_t); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 275; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyInt_FromLong(__pyx_v_t); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 272; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_4);
-      __pyx_t_8 = PyNumber_Remainder(((PyObject *)__pyx_kp_u_11), __pyx_t_4); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 275; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_8 = PyNumber_Remainder(((PyObject *)__pyx_kp_u_11), __pyx_t_4); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 272; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(((PyObject *)__pyx_t_8));
       __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 275; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      __Pyx_GOTREF(__pyx_t_4);
+      __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 272; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(((PyObject *)__pyx_t_4));
       PyTuple_SET_ITEM(__pyx_t_4, 0, ((PyObject *)__pyx_t_8));
       __Pyx_GIVEREF(((PyObject *)__pyx_t_8));
       __pyx_t_8 = 0;
-      __pyx_t_8 = PyObject_Call(__pyx_builtin_ValueError, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 275; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_8 = PyObject_Call(__pyx_builtin_ValueError, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 272; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_8);
       __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
       __Pyx_Raise(__pyx_t_8, 0, 0, 0);
       __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-      {__pyx_filename = __pyx_f[1]; __pyx_lineno = 275; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      {__pyx_filename = __pyx_f[1]; __pyx_lineno = 272; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     }
-    __pyx_L13:;
+    __pyx_L15:;
 
-    /* "numpy.pxd":276
+    /* "numpy.pxd":273
  *                 else:
  *                     raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t)
  *                 info.format = f             # <<<<<<<<<<<<<<
@@ -4915,7 +4710,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
     __pyx_v_info->format = __pyx_v_f;
 
-    /* "numpy.pxd":277
+    /* "numpy.pxd":274
  *                     raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t)
  *                 info.format = f
  *                 return             # <<<<<<<<<<<<<<
@@ -4924,11 +4719,11 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
     __pyx_r = 0;
     goto __pyx_L0;
-    goto __pyx_L11;
+    goto __pyx_L13;
   }
   /*else*/ {
 
-    /* "numpy.pxd":279
+    /* "numpy.pxd":276
  *                 return
  *             else:
  *                 info.format = <char*>stdlib.malloc(_buffer_format_string_len)             # <<<<<<<<<<<<<<
@@ -4937,7 +4732,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
     __pyx_v_info->format = ((char *)malloc(255));
 
-    /* "numpy.pxd":280
+    /* "numpy.pxd":277
  *             else:
  *                 info.format = <char*>stdlib.malloc(_buffer_format_string_len)
  *                 info.format[0] = '^' # Native data types, manual alignment             # <<<<<<<<<<<<<<
@@ -4946,7 +4741,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
     (__pyx_v_info->format[0]) = '^';
 
-    /* "numpy.pxd":281
+    /* "numpy.pxd":278
  *                 info.format = <char*>stdlib.malloc(_buffer_format_string_len)
  *                 info.format[0] = '^' # Native data types, manual alignment
  *                 offset = 0             # <<<<<<<<<<<<<<
@@ -4955,17 +4750,17 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
     __pyx_v_offset = 0;
 
-    /* "numpy.pxd":284
+    /* "numpy.pxd":281
  *                 f = _util_dtypestring(descr, info.format + 1,
  *                                       info.format + _buffer_format_string_len,
  *                                       &offset)             # <<<<<<<<<<<<<<
  *                 f[0] = 0 # Terminate format string
  * 
  */
-    __pyx_t_9 = __pyx_f_5numpy__util_dtypestring(__pyx_v_descr, (__pyx_v_info->format + 1), (__pyx_v_info->format + 255), (&__pyx_v_offset)); if (unlikely(__pyx_t_9 == NULL)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 282; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_9 = __pyx_f_5numpy__util_dtypestring(__pyx_v_descr, (__pyx_v_info->format + 1), (__pyx_v_info->format + 255), (&__pyx_v_offset)); if (unlikely(__pyx_t_9 == NULL)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 279; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __pyx_v_f = __pyx_t_9;
 
-    /* "numpy.pxd":285
+    /* "numpy.pxd":282
  *                                       info.format + _buffer_format_string_len,
  *                                       &offset)
  *                 f[0] = 0 # Terminate format string             # <<<<<<<<<<<<<<
@@ -4974,7 +4769,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
     (__pyx_v_f[0]) = 0;
   }
-  __pyx_L11:;
+  __pyx_L13:;
 
   __pyx_r = 0;
   goto __pyx_L0;
@@ -4999,16 +4794,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
   return __pyx_r;
 }
 
-/* Python wrapper */
-static void __pyx_pw_5numpy_7ndarray_3__releasebuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info); /*proto*/
-static void __pyx_pw_5numpy_7ndarray_3__releasebuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info) {
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__releasebuffer__ (wrapper)", 0);
-  __pyx_pf_5numpy_7ndarray_2__releasebuffer__(((PyArrayObject *)__pyx_v_self), ((Py_buffer *)__pyx_v_info));
-  __Pyx_RefNannyFinishContext();
-}
-
-/* "numpy.pxd":287
+/* "numpy.pxd":284
  *                 f[0] = 0 # Terminate format string
  * 
  *         def __releasebuffer__(ndarray self, Py_buffer* info):             # <<<<<<<<<<<<<<
@@ -5016,22 +4802,23 @@ static void __pyx_pw_5numpy_7ndarray_3__releasebuffer__(PyObject *__pyx_v_self,
  *                 stdlib.free(info.format)
  */
 
-static void __pyx_pf_5numpy_7ndarray_2__releasebuffer__(PyArrayObject *__pyx_v_self, Py_buffer *__pyx_v_info) {
+static CYTHON_UNUSED void __pyx_pf_5numpy_7ndarray_1__releasebuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info); /*proto*/
+static CYTHON_UNUSED void __pyx_pf_5numpy_7ndarray_1__releasebuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info) {
   __Pyx_RefNannyDeclarations
   int __pyx_t_1;
-  __Pyx_RefNannySetupContext("__releasebuffer__", 0);
+  __Pyx_RefNannySetupContext("__releasebuffer__");
 
-  /* "numpy.pxd":288
+  /* "numpy.pxd":285
  * 
  *         def __releasebuffer__(ndarray self, Py_buffer* info):
  *             if PyArray_HASFIELDS(self):             # <<<<<<<<<<<<<<
  *                 stdlib.free(info.format)
  *             if sizeof(npy_intp) != sizeof(Py_ssize_t):
  */
-  __pyx_t_1 = PyArray_HASFIELDS(__pyx_v_self);
+  __pyx_t_1 = PyArray_HASFIELDS(((PyArrayObject *)__pyx_v_self));
   if (__pyx_t_1) {
 
-    /* "numpy.pxd":289
+    /* "numpy.pxd":286
  *         def __releasebuffer__(ndarray self, Py_buffer* info):
  *             if PyArray_HASFIELDS(self):
  *                 stdlib.free(info.format)             # <<<<<<<<<<<<<<
@@ -5039,11 +4826,11 @@ static void __pyx_pf_5numpy_7ndarray_2__releasebuffer__(PyArrayObject *__pyx_v_s
  *                 stdlib.free(info.strides)
  */
     free(__pyx_v_info->format);
-    goto __pyx_L3;
+    goto __pyx_L5;
   }
-  __pyx_L3:;
+  __pyx_L5:;
 
-  /* "numpy.pxd":290
+  /* "numpy.pxd":287
  *             if PyArray_HASFIELDS(self):
  *                 stdlib.free(info.format)
  *             if sizeof(npy_intp) != sizeof(Py_ssize_t):             # <<<<<<<<<<<<<<
@@ -5053,7 +4840,7 @@ static void __pyx_pf_5numpy_7ndarray_2__releasebuffer__(PyArrayObject *__pyx_v_s
   __pyx_t_1 = ((sizeof(npy_intp)) != (sizeof(Py_ssize_t)));
   if (__pyx_t_1) {
 
-    /* "numpy.pxd":291
+    /* "numpy.pxd":288
  *                 stdlib.free(info.format)
  *             if sizeof(npy_intp) != sizeof(Py_ssize_t):
  *                 stdlib.free(info.strides)             # <<<<<<<<<<<<<<
@@ -5061,14 +4848,14 @@ static void __pyx_pf_5numpy_7ndarray_2__releasebuffer__(PyArrayObject *__pyx_v_s
  * 
  */
     free(__pyx_v_info->strides);
-    goto __pyx_L4;
+    goto __pyx_L6;
   }
-  __pyx_L4:;
+  __pyx_L6:;
 
   __Pyx_RefNannyFinishContext();
 }
 
-/* "numpy.pxd":767
+/* "numpy.pxd":764
  * ctypedef npy_cdouble     complex_t
  * 
  * cdef inline object PyArray_MultiIterNew1(a):             # <<<<<<<<<<<<<<
@@ -5083,9 +4870,9 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew1(PyObject *__
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("PyArray_MultiIterNew1", 0);
+  __Pyx_RefNannySetupContext("PyArray_MultiIterNew1");
 
-  /* "numpy.pxd":768
+  /* "numpy.pxd":765
  * 
  * cdef inline object PyArray_MultiIterNew1(a):
  *     return PyArray_MultiIterNew(1, <void*>a)             # <<<<<<<<<<<<<<
@@ -5093,7 +4880,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew1(PyObject *__
  * cdef inline object PyArray_MultiIterNew2(a, b):
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = PyArray_MultiIterNew(1, ((void *)__pyx_v_a)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 768; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyArray_MultiIterNew(1, ((void *)__pyx_v_a)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 765; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -5111,7 +4898,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew1(PyObject *__
   return __pyx_r;
 }
 
-/* "numpy.pxd":770
+/* "numpy.pxd":767
  *     return PyArray_MultiIterNew(1, <void*>a)
  * 
  * cdef inline object PyArray_MultiIterNew2(a, b):             # <<<<<<<<<<<<<<
@@ -5126,9 +4913,9 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew2(PyObject *__
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("PyArray_MultiIterNew2", 0);
+  __Pyx_RefNannySetupContext("PyArray_MultiIterNew2");
 
-  /* "numpy.pxd":771
+  /* "numpy.pxd":768
  * 
  * cdef inline object PyArray_MultiIterNew2(a, b):
  *     return PyArray_MultiIterNew(2, <void*>a, <void*>b)             # <<<<<<<<<<<<<<
@@ -5136,7 +4923,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew2(PyObject *__
  * cdef inline object PyArray_MultiIterNew3(a, b, c):
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = PyArray_MultiIterNew(2, ((void *)__pyx_v_a), ((void *)__pyx_v_b)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 771; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyArray_MultiIterNew(2, ((void *)__pyx_v_a), ((void *)__pyx_v_b)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 768; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -5154,7 +4941,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew2(PyObject *__
   return __pyx_r;
 }
 
-/* "numpy.pxd":773
+/* "numpy.pxd":770
  *     return PyArray_MultiIterNew(2, <void*>a, <void*>b)
  * 
  * cdef inline object PyArray_MultiIterNew3(a, b, c):             # <<<<<<<<<<<<<<
@@ -5169,9 +4956,9 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew3(PyObject *__
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("PyArray_MultiIterNew3", 0);
+  __Pyx_RefNannySetupContext("PyArray_MultiIterNew3");
 
-  /* "numpy.pxd":774
+  /* "numpy.pxd":771
  * 
  * cdef inline object PyArray_MultiIterNew3(a, b, c):
  *     return PyArray_MultiIterNew(3, <void*>a, <void*>b, <void*> c)             # <<<<<<<<<<<<<<
@@ -5179,7 +4966,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew3(PyObject *__
  * cdef inline object PyArray_MultiIterNew4(a, b, c, d):
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = PyArray_MultiIterNew(3, ((void *)__pyx_v_a), ((void *)__pyx_v_b), ((void *)__pyx_v_c)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 774; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyArray_MultiIterNew(3, ((void *)__pyx_v_a), ((void *)__pyx_v_b), ((void *)__pyx_v_c)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 771; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -5197,7 +4984,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew3(PyObject *__
   return __pyx_r;
 }
 
-/* "numpy.pxd":776
+/* "numpy.pxd":773
  *     return PyArray_MultiIterNew(3, <void*>a, <void*>b, <void*> c)
  * 
  * cdef inline object PyArray_MultiIterNew4(a, b, c, d):             # <<<<<<<<<<<<<<
@@ -5212,9 +4999,9 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew4(PyObject *__
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("PyArray_MultiIterNew4", 0);
+  __Pyx_RefNannySetupContext("PyArray_MultiIterNew4");
 
-  /* "numpy.pxd":777
+  /* "numpy.pxd":774
  * 
  * cdef inline object PyArray_MultiIterNew4(a, b, c, d):
  *     return PyArray_MultiIterNew(4, <void*>a, <void*>b, <void*>c, <void*> d)             # <<<<<<<<<<<<<<
@@ -5222,7 +5009,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew4(PyObject *__
  * cdef inline object PyArray_MultiIterNew5(a, b, c, d, e):
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = PyArray_MultiIterNew(4, ((void *)__pyx_v_a), ((void *)__pyx_v_b), ((void *)__pyx_v_c), ((void *)__pyx_v_d)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 777; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyArray_MultiIterNew(4, ((void *)__pyx_v_a), ((void *)__pyx_v_b), ((void *)__pyx_v_c), ((void *)__pyx_v_d)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 774; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -5240,7 +5027,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew4(PyObject *__
   return __pyx_r;
 }
 
-/* "numpy.pxd":779
+/* "numpy.pxd":776
  *     return PyArray_MultiIterNew(4, <void*>a, <void*>b, <void*>c, <void*> d)
  * 
  * cdef inline object PyArray_MultiIterNew5(a, b, c, d, e):             # <<<<<<<<<<<<<<
@@ -5255,9 +5042,9 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew5(PyObject *__
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("PyArray_MultiIterNew5", 0);
+  __Pyx_RefNannySetupContext("PyArray_MultiIterNew5");
 
-  /* "numpy.pxd":780
+  /* "numpy.pxd":777
  * 
  * cdef inline object PyArray_MultiIterNew5(a, b, c, d, e):
  *     return PyArray_MultiIterNew(5, <void*>a, <void*>b, <void*>c, <void*> d, <void*> e)             # <<<<<<<<<<<<<<
@@ -5265,7 +5052,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew5(PyObject *__
  * cdef inline char* _util_dtypestring(dtype descr, char* f, char* end, int* offset) except NULL:
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = PyArray_MultiIterNew(5, ((void *)__pyx_v_a), ((void *)__pyx_v_b), ((void *)__pyx_v_c), ((void *)__pyx_v_d), ((void *)__pyx_v_e)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 780; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyArray_MultiIterNew(5, ((void *)__pyx_v_a), ((void *)__pyx_v_b), ((void *)__pyx_v_c), ((void *)__pyx_v_d), ((void *)__pyx_v_e)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 777; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -5283,7 +5070,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew5(PyObject *__
   return __pyx_r;
 }
 
-/* "numpy.pxd":782
+/* "numpy.pxd":779
  *     return PyArray_MultiIterNew(5, <void*>a, <void*>b, <void*>c, <void*> d, <void*> e)
  * 
  * cdef inline char* _util_dtypestring(dtype descr, char* f, char* end, int* offset) except NULL:             # <<<<<<<<<<<<<<
@@ -5315,9 +5102,9 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("_util_dtypestring", 0);
+  __Pyx_RefNannySetupContext("_util_dtypestring");
 
-  /* "numpy.pxd":789
+  /* "numpy.pxd":786
  *     cdef int delta_offset
  *     cdef tuple i
  *     cdef int endian_detector = 1             # <<<<<<<<<<<<<<
@@ -5326,7 +5113,7 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
  */
   __pyx_v_endian_detector = 1;
 
-  /* "numpy.pxd":790
+  /* "numpy.pxd":787
  *     cdef tuple i
  *     cdef int endian_detector = 1
  *     cdef bint little_endian = ((<char*>&endian_detector)[0] != 0)             # <<<<<<<<<<<<<<
@@ -5335,7 +5122,7 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
  */
   __pyx_v_little_endian = ((((char *)(&__pyx_v_endian_detector))[0]) != 0);
 
-  /* "numpy.pxd":793
+  /* "numpy.pxd":790
  *     cdef tuple fields
  * 
  *     for childname in descr.names:             # <<<<<<<<<<<<<<
@@ -5343,7 +5130,7 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
  *         child, new_offset = fields
  */
   if (unlikely(((PyObject *)__pyx_v_descr->names) == Py_None)) {
-    PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable"); {__pyx_filename = __pyx_f[1]; __pyx_lineno = 793; __pyx_clineno = __LINE__; goto __pyx_L1_error;} 
+    PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable"); {__pyx_filename = __pyx_f[1]; __pyx_lineno = 790; __pyx_clineno = __LINE__; goto __pyx_L1_error;} 
   }
   __pyx_t_1 = ((PyObject *)__pyx_v_descr->names); __Pyx_INCREF(__pyx_t_1); __pyx_t_2 = 0;
   for (;;) {
@@ -5353,21 +5140,21 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
     __pyx_v_childname = __pyx_t_3;
     __pyx_t_3 = 0;
 
-    /* "numpy.pxd":794
+    /* "numpy.pxd":791
  * 
  *     for childname in descr.names:
  *         fields = descr.fields[childname]             # <<<<<<<<<<<<<<
  *         child, new_offset = fields
  * 
  */
-    __pyx_t_3 = PyObject_GetItem(__pyx_v_descr->fields, __pyx_v_childname); if (!__pyx_t_3) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 794; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = PyObject_GetItem(__pyx_v_descr->fields, __pyx_v_childname); if (!__pyx_t_3) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 791; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_3);
-    if (!(likely(PyTuple_CheckExact(__pyx_t_3))||((__pyx_t_3) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected tuple, got %.200s", Py_TYPE(__pyx_t_3)->tp_name), 0))) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 794; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (!(likely(PyTuple_CheckExact(__pyx_t_3))||((__pyx_t_3) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected tuple, got %.200s", Py_TYPE(__pyx_t_3)->tp_name), 0))) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 791; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_XDECREF(((PyObject *)__pyx_v_fields));
     __pyx_v_fields = ((PyObject*)__pyx_t_3);
     __pyx_t_3 = 0;
 
-    /* "numpy.pxd":795
+    /* "numpy.pxd":792
  *     for childname in descr.names:
  *         fields = descr.fields[childname]
  *         child, new_offset = fields             # <<<<<<<<<<<<<<
@@ -5379,7 +5166,7 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
       if (unlikely(PyTuple_GET_SIZE(sequence) != 2)) {
         if (PyTuple_GET_SIZE(sequence) > 2) __Pyx_RaiseTooManyValuesError(2);
         else __Pyx_RaiseNeedMoreValuesError(PyTuple_GET_SIZE(sequence));
-        {__pyx_filename = __pyx_f[1]; __pyx_lineno = 795; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        {__pyx_filename = __pyx_f[1]; __pyx_lineno = 792; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       }
       __pyx_t_3 = PyTuple_GET_ITEM(sequence, 0); 
       __pyx_t_4 = PyTuple_GET_ITEM(sequence, 1); 
@@ -5387,9 +5174,9 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
       __Pyx_INCREF(__pyx_t_4);
     } else {
       __Pyx_UnpackTupleError(((PyObject *)__pyx_v_fields), 2);
-      {__pyx_filename = __pyx_f[1]; __pyx_lineno = 795; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      {__pyx_filename = __pyx_f[1]; __pyx_lineno = 792; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     }
-    if (!(likely(((__pyx_t_3) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_3, __pyx_ptype_5numpy_dtype))))) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 795; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (!(likely(((__pyx_t_3) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_3, __pyx_ptype_5numpy_dtype))))) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 792; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_XDECREF(((PyObject *)__pyx_v_child));
     __pyx_v_child = ((PyArray_Descr *)__pyx_t_3);
     __pyx_t_3 = 0;
@@ -5397,48 +5184,48 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
     __pyx_v_new_offset = __pyx_t_4;
     __pyx_t_4 = 0;
 
-    /* "numpy.pxd":797
+    /* "numpy.pxd":794
  *         child, new_offset = fields
  * 
  *         if (end - f) - (new_offset - offset[0]) < 15:             # <<<<<<<<<<<<<<
  *             raise RuntimeError(u"Format string allocated too short, see comment in numpy.pxd")
  * 
  */
-    __pyx_t_4 = PyInt_FromLong((__pyx_v_end - __pyx_v_f)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 797; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = PyInt_FromLong((__pyx_v_end - __pyx_v_f)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 794; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_4);
-    __pyx_t_3 = PyInt_FromLong((__pyx_v_offset[0])); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 797; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = PyInt_FromLong((__pyx_v_offset[0])); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 794; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_3);
-    __pyx_t_5 = PyNumber_Subtract(__pyx_v_new_offset, __pyx_t_3); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 797; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = PyNumber_Subtract(__pyx_v_new_offset, __pyx_t_3); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 794; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_5);
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __pyx_t_3 = PyNumber_Subtract(__pyx_t_4, __pyx_t_5); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 797; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = PyNumber_Subtract(__pyx_t_4, __pyx_t_5); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 794; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_3);
     __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
     __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-    __pyx_t_5 = PyObject_RichCompare(__pyx_t_3, __pyx_int_15, Py_LT); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 797; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = PyObject_RichCompare(__pyx_t_3, __pyx_int_15, Py_LT); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 794; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_5);
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 797; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 794; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
     if (__pyx_t_6) {
 
-      /* "numpy.pxd":798
+      /* "numpy.pxd":795
  * 
  *         if (end - f) - (new_offset - offset[0]) < 15:
  *             raise RuntimeError(u"Format string allocated too short, see comment in numpy.pxd")             # <<<<<<<<<<<<<<
  * 
  *         if ((child.byteorder == '>' and little_endian) or
  */
-      __pyx_t_5 = PyObject_Call(__pyx_builtin_RuntimeError, ((PyObject *)__pyx_k_tuple_13), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 798; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyObject_Call(__pyx_builtin_RuntimeError, ((PyObject *)__pyx_k_tuple_13), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 795; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
       __Pyx_Raise(__pyx_t_5, 0, 0, 0);
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      {__pyx_filename = __pyx_f[1]; __pyx_lineno = 798; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      {__pyx_filename = __pyx_f[1]; __pyx_lineno = 795; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       goto __pyx_L5;
     }
     __pyx_L5:;
 
-    /* "numpy.pxd":800
+    /* "numpy.pxd":797
  *             raise RuntimeError(u"Format string allocated too short, see comment in numpy.pxd")
  * 
  *         if ((child.byteorder == '>' and little_endian) or             # <<<<<<<<<<<<<<
@@ -5453,7 +5240,7 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
     }
     if (!__pyx_t_7) {
 
-      /* "numpy.pxd":801
+      /* "numpy.pxd":798
  * 
  *         if ((child.byteorder == '>' and little_endian) or
  *             (child.byteorder == '<' and not little_endian)):             # <<<<<<<<<<<<<<
@@ -5473,23 +5260,23 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
     }
     if (__pyx_t_6) {
 
-      /* "numpy.pxd":802
+      /* "numpy.pxd":799
  *         if ((child.byteorder == '>' and little_endian) or
  *             (child.byteorder == '<' and not little_endian)):
  *             raise ValueError(u"Non-native byte order not supported")             # <<<<<<<<<<<<<<
  *             # One could encode it in the format string and have Cython
  *             # complain instead, BUT: < and > in format strings also imply
  */
-      __pyx_t_5 = PyObject_Call(__pyx_builtin_ValueError, ((PyObject *)__pyx_k_tuple_14), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 802; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyObject_Call(__pyx_builtin_ValueError, ((PyObject *)__pyx_k_tuple_14), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 799; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
       __Pyx_Raise(__pyx_t_5, 0, 0, 0);
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      {__pyx_filename = __pyx_f[1]; __pyx_lineno = 802; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      {__pyx_filename = __pyx_f[1]; __pyx_lineno = 799; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       goto __pyx_L6;
     }
     __pyx_L6:;
 
-    /* "numpy.pxd":812
+    /* "numpy.pxd":809
  * 
  *         # Output padding bytes
  *         while offset[0] < new_offset:             # <<<<<<<<<<<<<<
@@ -5497,16 +5284,16 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
  *             f += 1
  */
     while (1) {
-      __pyx_t_5 = PyInt_FromLong((__pyx_v_offset[0])); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 812; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyInt_FromLong((__pyx_v_offset[0])); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 809; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
-      __pyx_t_3 = PyObject_RichCompare(__pyx_t_5, __pyx_v_new_offset, Py_LT); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 812; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyObject_RichCompare(__pyx_t_5, __pyx_v_new_offset, Py_LT); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 809; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 812; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 809; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
       if (!__pyx_t_6) break;
 
-      /* "numpy.pxd":813
+      /* "numpy.pxd":810
  *         # Output padding bytes
  *         while offset[0] < new_offset:
  *             f[0] = 120 # "x"; pad byte             # <<<<<<<<<<<<<<
@@ -5515,7 +5302,7 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
  */
       (__pyx_v_f[0]) = 120;
 
-      /* "numpy.pxd":814
+      /* "numpy.pxd":811
  *         while offset[0] < new_offset:
  *             f[0] = 120 # "x"; pad byte
  *             f += 1             # <<<<<<<<<<<<<<
@@ -5524,7 +5311,7 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
  */
       __pyx_v_f = (__pyx_v_f + 1);
 
-      /* "numpy.pxd":815
+      /* "numpy.pxd":812
  *             f[0] = 120 # "x"; pad byte
  *             f += 1
  *             offset[0] += 1             # <<<<<<<<<<<<<<
@@ -5535,7 +5322,7 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
       (__pyx_v_offset[__pyx_t_10]) = ((__pyx_v_offset[__pyx_t_10]) + 1);
     }
 
-    /* "numpy.pxd":817
+    /* "numpy.pxd":814
  *             offset[0] += 1
  * 
  *         offset[0] += child.itemsize             # <<<<<<<<<<<<<<
@@ -5545,7 +5332,7 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
     __pyx_t_10 = 0;
     (__pyx_v_offset[__pyx_t_10]) = ((__pyx_v_offset[__pyx_t_10]) + __pyx_v_child->elsize);
 
-    /* "numpy.pxd":819
+    /* "numpy.pxd":816
  *         offset[0] += child.itemsize
  * 
  *         if not PyDataType_HASFIELDS(child):             # <<<<<<<<<<<<<<
@@ -5555,20 +5342,20 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
     __pyx_t_6 = (!PyDataType_HASFIELDS(__pyx_v_child));
     if (__pyx_t_6) {
 
-      /* "numpy.pxd":820
+      /* "numpy.pxd":817
  * 
  *         if not PyDataType_HASFIELDS(child):
  *             t = child.type_num             # <<<<<<<<<<<<<<
  *             if end - f < 5:
  *                 raise RuntimeError(u"Format string allocated too short.")
  */
-      __pyx_t_3 = PyInt_FromLong(__pyx_v_child->type_num); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 820; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyInt_FromLong(__pyx_v_child->type_num); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 817; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_XDECREF(__pyx_v_t);
       __pyx_v_t = __pyx_t_3;
       __pyx_t_3 = 0;
 
-      /* "numpy.pxd":821
+      /* "numpy.pxd":818
  *         if not PyDataType_HASFIELDS(child):
  *             t = child.type_num
  *             if end - f < 5:             # <<<<<<<<<<<<<<
@@ -5578,282 +5365,282 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
       __pyx_t_6 = ((__pyx_v_end - __pyx_v_f) < 5);
       if (__pyx_t_6) {
 
-        /* "numpy.pxd":822
+        /* "numpy.pxd":819
  *             t = child.type_num
  *             if end - f < 5:
  *                 raise RuntimeError(u"Format string allocated too short.")             # <<<<<<<<<<<<<<
  * 
  *             # Until ticket #99 is fixed, use integers to avoid warnings
  */
-        __pyx_t_3 = PyObject_Call(__pyx_builtin_RuntimeError, ((PyObject *)__pyx_k_tuple_16), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 822; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_3 = PyObject_Call(__pyx_builtin_RuntimeError, ((PyObject *)__pyx_k_tuple_16), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 819; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_3);
         __Pyx_Raise(__pyx_t_3, 0, 0, 0);
         __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-        {__pyx_filename = __pyx_f[1]; __pyx_lineno = 822; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        {__pyx_filename = __pyx_f[1]; __pyx_lineno = 819; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         goto __pyx_L10;
       }
       __pyx_L10:;
 
-      /* "numpy.pxd":825
+      /* "numpy.pxd":822
  * 
  *             # Until ticket #99 is fixed, use integers to avoid warnings
  *             if   t == NPY_BYTE:        f[0] =  98 #"b"             # <<<<<<<<<<<<<<
  *             elif t == NPY_UBYTE:       f[0] =  66 #"B"
  *             elif t == NPY_SHORT:       f[0] = 104 #"h"
  */
-      __pyx_t_3 = PyInt_FromLong(NPY_BYTE); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 825; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyInt_FromLong(NPY_BYTE); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 822; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 825; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 822; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 825; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 822; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 98;
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":826
+      /* "numpy.pxd":823
  *             # Until ticket #99 is fixed, use integers to avoid warnings
  *             if   t == NPY_BYTE:        f[0] =  98 #"b"
  *             elif t == NPY_UBYTE:       f[0] =  66 #"B"             # <<<<<<<<<<<<<<
  *             elif t == NPY_SHORT:       f[0] = 104 #"h"
  *             elif t == NPY_USHORT:      f[0] =  72 #"H"
  */
-      __pyx_t_5 = PyInt_FromLong(NPY_UBYTE); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 826; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyInt_FromLong(NPY_UBYTE); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 823; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
-      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 826; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 823; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 826; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 823; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 66;
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":827
+      /* "numpy.pxd":824
  *             if   t == NPY_BYTE:        f[0] =  98 #"b"
  *             elif t == NPY_UBYTE:       f[0] =  66 #"B"
  *             elif t == NPY_SHORT:       f[0] = 104 #"h"             # <<<<<<<<<<<<<<
  *             elif t == NPY_USHORT:      f[0] =  72 #"H"
  *             elif t == NPY_INT:         f[0] = 105 #"i"
  */
-      __pyx_t_3 = PyInt_FromLong(NPY_SHORT); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 827; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyInt_FromLong(NPY_SHORT); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 824; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 827; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 824; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 827; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 824; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 104;
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":828
+      /* "numpy.pxd":825
  *             elif t == NPY_UBYTE:       f[0] =  66 #"B"
  *             elif t == NPY_SHORT:       f[0] = 104 #"h"
  *             elif t == NPY_USHORT:      f[0] =  72 #"H"             # <<<<<<<<<<<<<<
  *             elif t == NPY_INT:         f[0] = 105 #"i"
  *             elif t == NPY_UINT:        f[0] =  73 #"I"
  */
-      __pyx_t_5 = PyInt_FromLong(NPY_USHORT); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 828; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyInt_FromLong(NPY_USHORT); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 825; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
-      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 828; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 825; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 828; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 825; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 72;
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":829
+      /* "numpy.pxd":826
  *             elif t == NPY_SHORT:       f[0] = 104 #"h"
  *             elif t == NPY_USHORT:      f[0] =  72 #"H"
  *             elif t == NPY_INT:         f[0] = 105 #"i"             # <<<<<<<<<<<<<<
  *             elif t == NPY_UINT:        f[0] =  73 #"I"
  *             elif t == NPY_LONG:        f[0] = 108 #"l"
  */
-      __pyx_t_3 = PyInt_FromLong(NPY_INT); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 829; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyInt_FromLong(NPY_INT); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 826; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 829; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 826; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 829; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 826; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 105;
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":830
+      /* "numpy.pxd":827
  *             elif t == NPY_USHORT:      f[0] =  72 #"H"
  *             elif t == NPY_INT:         f[0] = 105 #"i"
  *             elif t == NPY_UINT:        f[0] =  73 #"I"             # <<<<<<<<<<<<<<
  *             elif t == NPY_LONG:        f[0] = 108 #"l"
  *             elif t == NPY_ULONG:       f[0] = 76  #"L"
  */
-      __pyx_t_5 = PyInt_FromLong(NPY_UINT); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 830; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyInt_FromLong(NPY_UINT); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 827; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
-      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 830; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 827; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 830; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 827; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 73;
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":831
+      /* "numpy.pxd":828
  *             elif t == NPY_INT:         f[0] = 105 #"i"
  *             elif t == NPY_UINT:        f[0] =  73 #"I"
  *             elif t == NPY_LONG:        f[0] = 108 #"l"             # <<<<<<<<<<<<<<
  *             elif t == NPY_ULONG:       f[0] = 76  #"L"
  *             elif t == NPY_LONGLONG:    f[0] = 113 #"q"
  */
-      __pyx_t_3 = PyInt_FromLong(NPY_LONG); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 831; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyInt_FromLong(NPY_LONG); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 828; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 831; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 828; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 831; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 828; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 108;
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":832
+      /* "numpy.pxd":829
  *             elif t == NPY_UINT:        f[0] =  73 #"I"
  *             elif t == NPY_LONG:        f[0] = 108 #"l"
  *             elif t == NPY_ULONG:       f[0] = 76  #"L"             # <<<<<<<<<<<<<<
  *             elif t == NPY_LONGLONG:    f[0] = 113 #"q"
  *             elif t == NPY_ULONGLONG:   f[0] = 81  #"Q"
  */
-      __pyx_t_5 = PyInt_FromLong(NPY_ULONG); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 832; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyInt_FromLong(NPY_ULONG); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 829; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
-      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 832; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 829; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 832; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 829; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 76;
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":833
+      /* "numpy.pxd":830
  *             elif t == NPY_LONG:        f[0] = 108 #"l"
  *             elif t == NPY_ULONG:       f[0] = 76  #"L"
  *             elif t == NPY_LONGLONG:    f[0] = 113 #"q"             # <<<<<<<<<<<<<<
  *             elif t == NPY_ULONGLONG:   f[0] = 81  #"Q"
  *             elif t == NPY_FLOAT:       f[0] = 102 #"f"
  */
-      __pyx_t_3 = PyInt_FromLong(NPY_LONGLONG); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 833; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyInt_FromLong(NPY_LONGLONG); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 830; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 833; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 830; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 833; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 830; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 113;
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":834
+      /* "numpy.pxd":831
  *             elif t == NPY_ULONG:       f[0] = 76  #"L"
  *             elif t == NPY_LONGLONG:    f[0] = 113 #"q"
  *             elif t == NPY_ULONGLONG:   f[0] = 81  #"Q"             # <<<<<<<<<<<<<<
  *             elif t == NPY_FLOAT:       f[0] = 102 #"f"
  *             elif t == NPY_DOUBLE:      f[0] = 100 #"d"
  */
-      __pyx_t_5 = PyInt_FromLong(NPY_ULONGLONG); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 834; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyInt_FromLong(NPY_ULONGLONG); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 831; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
-      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 834; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 831; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 834; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 831; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 81;
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":835
+      /* "numpy.pxd":832
  *             elif t == NPY_LONGLONG:    f[0] = 113 #"q"
  *             elif t == NPY_ULONGLONG:   f[0] = 81  #"Q"
  *             elif t == NPY_FLOAT:       f[0] = 102 #"f"             # <<<<<<<<<<<<<<
  *             elif t == NPY_DOUBLE:      f[0] = 100 #"d"
  *             elif t == NPY_LONGDOUBLE:  f[0] = 103 #"g"
  */
-      __pyx_t_3 = PyInt_FromLong(NPY_FLOAT); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 835; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyInt_FromLong(NPY_FLOAT); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 832; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 835; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 832; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 835; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 832; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 102;
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":836
+      /* "numpy.pxd":833
  *             elif t == NPY_ULONGLONG:   f[0] = 81  #"Q"
  *             elif t == NPY_FLOAT:       f[0] = 102 #"f"
  *             elif t == NPY_DOUBLE:      f[0] = 100 #"d"             # <<<<<<<<<<<<<<
  *             elif t == NPY_LONGDOUBLE:  f[0] = 103 #"g"
  *             elif t == NPY_CFLOAT:      f[0] = 90; f[1] = 102; f += 1 # Zf
  */
-      __pyx_t_5 = PyInt_FromLong(NPY_DOUBLE); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 836; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyInt_FromLong(NPY_DOUBLE); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 833; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
-      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 836; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 833; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 836; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 833; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 100;
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":837
+      /* "numpy.pxd":834
  *             elif t == NPY_FLOAT:       f[0] = 102 #"f"
  *             elif t == NPY_DOUBLE:      f[0] = 100 #"d"
  *             elif t == NPY_LONGDOUBLE:  f[0] = 103 #"g"             # <<<<<<<<<<<<<<
  *             elif t == NPY_CFLOAT:      f[0] = 90; f[1] = 102; f += 1 # Zf
  *             elif t == NPY_CDOUBLE:     f[0] = 90; f[1] = 100; f += 1 # Zd
  */
-      __pyx_t_3 = PyInt_FromLong(NPY_LONGDOUBLE); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 837; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyInt_FromLong(NPY_LONGDOUBLE); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 834; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 837; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 834; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 837; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 834; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 103;
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":838
+      /* "numpy.pxd":835
  *             elif t == NPY_DOUBLE:      f[0] = 100 #"d"
  *             elif t == NPY_LONGDOUBLE:  f[0] = 103 #"g"
  *             elif t == NPY_CFLOAT:      f[0] = 90; f[1] = 102; f += 1 # Zf             # <<<<<<<<<<<<<<
  *             elif t == NPY_CDOUBLE:     f[0] = 90; f[1] = 100; f += 1 # Zd
  *             elif t == NPY_CLONGDOUBLE: f[0] = 90; f[1] = 103; f += 1 # Zg
  */
-      __pyx_t_5 = PyInt_FromLong(NPY_CFLOAT); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 838; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyInt_FromLong(NPY_CFLOAT); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 835; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
-      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 838; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 835; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 838; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 835; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 90;
@@ -5862,19 +5649,19 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":839
+      /* "numpy.pxd":836
  *             elif t == NPY_LONGDOUBLE:  f[0] = 103 #"g"
  *             elif t == NPY_CFLOAT:      f[0] = 90; f[1] = 102; f += 1 # Zf
  *             elif t == NPY_CDOUBLE:     f[0] = 90; f[1] = 100; f += 1 # Zd             # <<<<<<<<<<<<<<
  *             elif t == NPY_CLONGDOUBLE: f[0] = 90; f[1] = 103; f += 1 # Zg
  *             elif t == NPY_OBJECT:      f[0] = 79 #"O"
  */
-      __pyx_t_3 = PyInt_FromLong(NPY_CDOUBLE); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 839; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyInt_FromLong(NPY_CDOUBLE); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 836; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 839; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 836; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 839; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 836; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 90;
@@ -5883,19 +5670,19 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":840
+      /* "numpy.pxd":837
  *             elif t == NPY_CFLOAT:      f[0] = 90; f[1] = 102; f += 1 # Zf
  *             elif t == NPY_CDOUBLE:     f[0] = 90; f[1] = 100; f += 1 # Zd
  *             elif t == NPY_CLONGDOUBLE: f[0] = 90; f[1] = 103; f += 1 # Zg             # <<<<<<<<<<<<<<
  *             elif t == NPY_OBJECT:      f[0] = 79 #"O"
  *             else:
  */
-      __pyx_t_5 = PyInt_FromLong(NPY_CLONGDOUBLE); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 840; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyInt_FromLong(NPY_CLONGDOUBLE); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 837; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
-      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 840; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 837; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 840; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 837; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 90;
@@ -5904,19 +5691,19 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":841
+      /* "numpy.pxd":838
  *             elif t == NPY_CDOUBLE:     f[0] = 90; f[1] = 100; f += 1 # Zd
  *             elif t == NPY_CLONGDOUBLE: f[0] = 90; f[1] = 103; f += 1 # Zg
  *             elif t == NPY_OBJECT:      f[0] = 79 #"O"             # <<<<<<<<<<<<<<
  *             else:
  *                 raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t)
  */
-      __pyx_t_3 = PyInt_FromLong(NPY_OBJECT); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 841; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyInt_FromLong(NPY_OBJECT); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 838; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 841; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 838; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 841; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 838; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 79;
@@ -5924,30 +5711,30 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
       }
       /*else*/ {
 
-        /* "numpy.pxd":843
+        /* "numpy.pxd":840
  *             elif t == NPY_OBJECT:      f[0] = 79 #"O"
  *             else:
  *                 raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t)             # <<<<<<<<<<<<<<
  *             f += 1
  *         else:
  */
-        __pyx_t_5 = PyNumber_Remainder(((PyObject *)__pyx_kp_u_11), __pyx_v_t); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 843; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_5 = PyNumber_Remainder(((PyObject *)__pyx_kp_u_11), __pyx_v_t); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 840; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(((PyObject *)__pyx_t_5));
-        __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 843; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-        __Pyx_GOTREF(__pyx_t_3);
+        __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 840; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __Pyx_GOTREF(((PyObject *)__pyx_t_3));
         PyTuple_SET_ITEM(__pyx_t_3, 0, ((PyObject *)__pyx_t_5));
         __Pyx_GIVEREF(((PyObject *)__pyx_t_5));
         __pyx_t_5 = 0;
-        __pyx_t_5 = PyObject_Call(__pyx_builtin_ValueError, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 843; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_5 = PyObject_Call(__pyx_builtin_ValueError, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 840; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_5);
         __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
         __Pyx_Raise(__pyx_t_5, 0, 0, 0);
         __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-        {__pyx_filename = __pyx_f[1]; __pyx_lineno = 843; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        {__pyx_filename = __pyx_f[1]; __pyx_lineno = 840; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       }
       __pyx_L11:;
 
-      /* "numpy.pxd":844
+      /* "numpy.pxd":841
  *             else:
  *                 raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t)
  *             f += 1             # <<<<<<<<<<<<<<
@@ -5959,21 +5746,21 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
     }
     /*else*/ {
 
-      /* "numpy.pxd":848
+      /* "numpy.pxd":845
  *             # Cython ignores struct boundary information ("T{...}"),
  *             # so don't output it
  *             f = _util_dtypestring(child, f, end, offset)             # <<<<<<<<<<<<<<
  *     return f
  * 
  */
-      __pyx_t_11 = __pyx_f_5numpy__util_dtypestring(__pyx_v_child, __pyx_v_f, __pyx_v_end, __pyx_v_offset); if (unlikely(__pyx_t_11 == NULL)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 848; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_11 = __pyx_f_5numpy__util_dtypestring(__pyx_v_child, __pyx_v_f, __pyx_v_end, __pyx_v_offset); if (unlikely(__pyx_t_11 == NULL)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 845; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __pyx_v_f = __pyx_t_11;
     }
     __pyx_L9:;
   }
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "numpy.pxd":849
+  /* "numpy.pxd":846
  *             # so don't output it
  *             f = _util_dtypestring(child, f, end, offset)
  *     return f             # <<<<<<<<<<<<<<
@@ -6002,7 +5789,7 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
   return __pyx_r;
 }
 
-/* "numpy.pxd":964
+/* "numpy.pxd":961
  * 
  * 
  * cdef inline void set_array_base(ndarray arr, object base):             # <<<<<<<<<<<<<<
@@ -6014,9 +5801,9 @@ static CYTHON_INLINE void __pyx_f_5numpy_set_array_base(PyArrayObject *__pyx_v_a
   PyObject *__pyx_v_baseptr;
   __Pyx_RefNannyDeclarations
   int __pyx_t_1;
-  __Pyx_RefNannySetupContext("set_array_base", 0);
+  __Pyx_RefNannySetupContext("set_array_base");
 
-  /* "numpy.pxd":966
+  /* "numpy.pxd":963
  * cdef inline void set_array_base(ndarray arr, object base):
  *      cdef PyObject* baseptr
  *      if base is None:             # <<<<<<<<<<<<<<
@@ -6026,7 +5813,7 @@ static CYTHON_INLINE void __pyx_f_5numpy_set_array_base(PyArrayObject *__pyx_v_a
   __pyx_t_1 = (__pyx_v_base == Py_None);
   if (__pyx_t_1) {
 
-    /* "numpy.pxd":967
+    /* "numpy.pxd":964
  *      cdef PyObject* baseptr
  *      if base is None:
  *          baseptr = NULL             # <<<<<<<<<<<<<<
@@ -6038,7 +5825,7 @@ static CYTHON_INLINE void __pyx_f_5numpy_set_array_base(PyArrayObject *__pyx_v_a
   }
   /*else*/ {
 
-    /* "numpy.pxd":969
+    /* "numpy.pxd":966
  *          baseptr = NULL
  *      else:
  *          Py_INCREF(base) # important to do this before decref below!             # <<<<<<<<<<<<<<
@@ -6047,7 +5834,7 @@ static CYTHON_INLINE void __pyx_f_5numpy_set_array_base(PyArrayObject *__pyx_v_a
  */
     Py_INCREF(__pyx_v_base);
 
-    /* "numpy.pxd":970
+    /* "numpy.pxd":967
  *      else:
  *          Py_INCREF(base) # important to do this before decref below!
  *          baseptr = <PyObject*>base             # <<<<<<<<<<<<<<
@@ -6058,7 +5845,7 @@ static CYTHON_INLINE void __pyx_f_5numpy_set_array_base(PyArrayObject *__pyx_v_a
   }
   __pyx_L3:;
 
-  /* "numpy.pxd":971
+  /* "numpy.pxd":968
  *          Py_INCREF(base) # important to do this before decref below!
  *          baseptr = <PyObject*>base
  *      Py_XDECREF(arr.base)             # <<<<<<<<<<<<<<
@@ -6067,7 +5854,7 @@ static CYTHON_INLINE void __pyx_f_5numpy_set_array_base(PyArrayObject *__pyx_v_a
  */
   Py_XDECREF(__pyx_v_arr->base);
 
-  /* "numpy.pxd":972
+  /* "numpy.pxd":969
  *          baseptr = <PyObject*>base
  *      Py_XDECREF(arr.base)
  *      arr.base = baseptr             # <<<<<<<<<<<<<<
@@ -6079,7 +5866,7 @@ static CYTHON_INLINE void __pyx_f_5numpy_set_array_base(PyArrayObject *__pyx_v_a
   __Pyx_RefNannyFinishContext();
 }
 
-/* "numpy.pxd":974
+/* "numpy.pxd":971
  *      arr.base = baseptr
  * 
  * cdef inline object get_array_base(ndarray arr):             # <<<<<<<<<<<<<<
@@ -6091,9 +5878,9 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_get_array_base(PyArrayObject *__py
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   int __pyx_t_1;
-  __Pyx_RefNannySetupContext("get_array_base", 0);
+  __Pyx_RefNannySetupContext("get_array_base");
 
-  /* "numpy.pxd":975
+  /* "numpy.pxd":972
  * 
  * cdef inline object get_array_base(ndarray arr):
  *     if arr.base is NULL:             # <<<<<<<<<<<<<<
@@ -6103,7 +5890,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_get_array_base(PyArrayObject *__py
   __pyx_t_1 = (__pyx_v_arr->base == NULL);
   if (__pyx_t_1) {
 
-    /* "numpy.pxd":976
+    /* "numpy.pxd":973
  * cdef inline object get_array_base(ndarray arr):
  *     if arr.base is NULL:
  *         return None             # <<<<<<<<<<<<<<
@@ -6118,7 +5905,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_get_array_base(PyArrayObject *__py
   }
   /*else*/ {
 
-    /* "numpy.pxd":978
+    /* "numpy.pxd":975
  *         return None
  *     else:
  *         return <object>arr.base             # <<<<<<<<<<<<<<
@@ -6160,11 +5947,10 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = {
   {&__pyx_kp_u_11, __pyx_k_11, sizeof(__pyx_k_11), 0, 1, 0, 0},
   {&__pyx_kp_u_12, __pyx_k_12, sizeof(__pyx_k_12), 0, 1, 0, 0},
   {&__pyx_kp_u_15, __pyx_k_15, sizeof(__pyx_k_15), 0, 1, 0, 0},
+  {&__pyx_n_s_17, __pyx_k_17, sizeof(__pyx_k_17), 0, 0, 1, 1},
+  {&__pyx_n_s_18, __pyx_k_18, sizeof(__pyx_k_18), 0, 0, 1, 1},
   {&__pyx_n_s_19, __pyx_k_19, sizeof(__pyx_k_19), 0, 0, 1, 1},
-  {&__pyx_kp_s_20, __pyx_k_20, sizeof(__pyx_k_20), 0, 0, 1, 0},
-  {&__pyx_n_s_21, __pyx_k_21, sizeof(__pyx_k_21), 0, 0, 1, 1},
-  {&__pyx_n_s_24, __pyx_k_24, sizeof(__pyx_k_24), 0, 0, 1, 1},
-  {&__pyx_n_s_27, __pyx_k_27, sizeof(__pyx_k_27), 0, 0, 1, 1},
+  {&__pyx_n_s_20, __pyx_k_20, sizeof(__pyx_k_20), 0, 0, 1, 1},
   {&__pyx_kp_u_5, __pyx_k_5, sizeof(__pyx_k_5), 0, 1, 0, 0},
   {&__pyx_kp_u_7, __pyx_k_7, sizeof(__pyx_k_7), 0, 1, 0, 0},
   {&__pyx_kp_u_9, __pyx_k_9, sizeof(__pyx_k_9), 0, 1, 0, 0},
@@ -6173,51 +5959,21 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = {
   {&__pyx_n_s__ValueError, __pyx_k__ValueError, sizeof(__pyx_k__ValueError), 0, 0, 1, 1},
   {&__pyx_n_s____main__, __pyx_k____main__, sizeof(__pyx_k____main__), 0, 0, 1, 1},
   {&__pyx_n_s____test__, __pyx_k____test__, sizeof(__pyx_k____test__), 0, 0, 1, 1},
-  {&__pyx_n_s__bot, __pyx_k__bot, sizeof(__pyx_k__bot), 0, 0, 1, 1},
-  {&__pyx_n_s__conv, __pyx_k__conv, sizeof(__pyx_k__conv), 0, 0, 1, 1},
   {&__pyx_n_s__dtype, __pyx_k__dtype, sizeof(__pyx_k__dtype), 0, 0, 1, 1},
   {&__pyx_n_s__empty, __pyx_k__empty, sizeof(__pyx_k__empty), 0, 0, 1, 1},
   {&__pyx_n_s__f, __pyx_k__f, sizeof(__pyx_k__f), 0, 0, 1, 1},
   {&__pyx_n_s__fill_value, __pyx_k__fill_value, sizeof(__pyx_k__fill_value), 0, 0, 1, 1},
-  {&__pyx_n_s__fixed, __pyx_k__fixed, sizeof(__pyx_k__fixed), 0, 0, 1, 1},
   {&__pyx_n_s__float, __pyx_k__float, sizeof(__pyx_k__float), 0, 0, 1, 1},
   {&__pyx_n_s__g, __pyx_k__g, sizeof(__pyx_k__g), 0, 0, 1, 1},
-  {&__pyx_n_s__i, __pyx_k__i, sizeof(__pyx_k__i), 0, 0, 1, 1},
-  {&__pyx_n_s__ii, __pyx_k__ii, sizeof(__pyx_k__ii), 0, 0, 1, 1},
-  {&__pyx_n_s__iii, __pyx_k__iii, sizeof(__pyx_k__iii), 0, 0, 1, 1},
-  {&__pyx_n_s__iimax, __pyx_k__iimax, sizeof(__pyx_k__iimax), 0, 0, 1, 1},
-  {&__pyx_n_s__iimin, __pyx_k__iimin, sizeof(__pyx_k__iimin), 0, 0, 1, 1},
-  {&__pyx_n_s__j, __pyx_k__j, sizeof(__pyx_k__j), 0, 0, 1, 1},
-  {&__pyx_n_s__jj, __pyx_k__jj, sizeof(__pyx_k__jj), 0, 0, 1, 1},
-  {&__pyx_n_s__jjj, __pyx_k__jjj, sizeof(__pyx_k__jjj), 0, 0, 1, 1},
-  {&__pyx_n_s__jjmax, __pyx_k__jjmax, sizeof(__pyx_k__jjmax), 0, 0, 1, 1},
-  {&__pyx_n_s__jjmin, __pyx_k__jjmin, sizeof(__pyx_k__jjmin), 0, 0, 1, 1},
-  {&__pyx_n_s__k, __pyx_k__k, sizeof(__pyx_k__k), 0, 0, 1, 1},
-  {&__pyx_n_s__ker, __pyx_k__ker, sizeof(__pyx_k__ker), 0, 0, 1, 1},
-  {&__pyx_n_s__kk, __pyx_k__kk, sizeof(__pyx_k__kk), 0, 0, 1, 1},
-  {&__pyx_n_s__kkk, __pyx_k__kkk, sizeof(__pyx_k__kkk), 0, 0, 1, 1},
-  {&__pyx_n_s__kkmax, __pyx_k__kkmax, sizeof(__pyx_k__kkmax), 0, 0, 1, 1},
-  {&__pyx_n_s__kkmin, __pyx_k__kkmin, sizeof(__pyx_k__kkmin), 0, 0, 1, 1},
-  {&__pyx_n_s__nkx, __pyx_k__nkx, sizeof(__pyx_k__nkx), 0, 0, 1, 1},
-  {&__pyx_n_s__nky, __pyx_k__nky, sizeof(__pyx_k__nky), 0, 0, 1, 1},
-  {&__pyx_n_s__nkz, __pyx_k__nkz, sizeof(__pyx_k__nkz), 0, 0, 1, 1},
   {&__pyx_n_s__np, __pyx_k__np, sizeof(__pyx_k__np), 0, 0, 1, 1},
   {&__pyx_n_s__numpy, __pyx_k__numpy, sizeof(__pyx_k__numpy), 0, 0, 1, 1},
-  {&__pyx_n_s__nx, __pyx_k__nx, sizeof(__pyx_k__nx), 0, 0, 1, 1},
-  {&__pyx_n_s__ny, __pyx_k__ny, sizeof(__pyx_k__ny), 0, 0, 1, 1},
-  {&__pyx_n_s__nz, __pyx_k__nz, sizeof(__pyx_k__nz), 0, 0, 1, 1},
   {&__pyx_n_s__range, __pyx_k__range, sizeof(__pyx_k__range), 0, 0, 1, 1},
-  {&__pyx_n_s__top, __pyx_k__top, sizeof(__pyx_k__top), 0, 0, 1, 1},
-  {&__pyx_n_s__val, __pyx_k__val, sizeof(__pyx_k__val), 0, 0, 1, 1},
-  {&__pyx_n_s__wkx, __pyx_k__wkx, sizeof(__pyx_k__wkx), 0, 0, 1, 1},
-  {&__pyx_n_s__wky, __pyx_k__wky, sizeof(__pyx_k__wky), 0, 0, 1, 1},
-  {&__pyx_n_s__wkz, __pyx_k__wkz, sizeof(__pyx_k__wkz), 0, 0, 1, 1},
   {0, 0, 0, 0, 0, 0, 0}
 };
 static int __Pyx_InitCachedBuiltins(void) {
   __pyx_builtin_ValueError = __Pyx_GetName(__pyx_b, __pyx_n_s__ValueError); if (!__pyx_builtin_ValueError) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 20; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_builtin_range = __Pyx_GetName(__pyx_b, __pyx_n_s__range); if (!__pyx_builtin_range) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 38; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_builtin_RuntimeError = __Pyx_GetName(__pyx_b, __pyx_n_s__RuntimeError); if (!__pyx_builtin_RuntimeError) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 798; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_builtin_RuntimeError = __Pyx_GetName(__pyx_b, __pyx_n_s__RuntimeError); if (!__pyx_builtin_RuntimeError) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 795; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   return 0;
   __pyx_L1_error:;
   return -1;
@@ -6225,7 +5981,7 @@ static int __Pyx_InitCachedBuiltins(void) {
 
 static int __Pyx_InitCachedConstants(void) {
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__Pyx_InitCachedConstants", 0);
+  __Pyx_RefNannySetupContext("__Pyx_InitCachedConstants");
 
   /* "astropy/nddata/convolution/boundary_fill.pyx":20
  * 
@@ -6235,7 +5991,7 @@ static int __Pyx_InitCachedConstants(void) {
  *     assert f.dtype == DTYPE and g.dtype == DTYPE
  */
   __pyx_k_tuple_2 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 20; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_2);
+  __Pyx_GOTREF(((PyObject *)__pyx_k_tuple_2));
   __Pyx_INCREF(((PyObject *)__pyx_kp_s_1));
   PyTuple_SET_ITEM(__pyx_k_tuple_2, 0, ((PyObject *)__pyx_kp_s_1));
   __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_1));
@@ -6249,7 +6005,7 @@ static int __Pyx_InitCachedConstants(void) {
  *     assert f.dtype == DTYPE and g.dtype == DTYPE
  */
   __pyx_k_tuple_3 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 92; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_3);
+  __Pyx_GOTREF(((PyObject *)__pyx_k_tuple_3));
   __Pyx_INCREF(((PyObject *)__pyx_kp_s_1));
   PyTuple_SET_ITEM(__pyx_k_tuple_3, 0, ((PyObject *)__pyx_kp_s_1));
   __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_1));
@@ -6263,356 +6019,95 @@ static int __Pyx_InitCachedConstants(void) {
  *     assert f.dtype == DTYPE and g.dtype == DTYPE
  */
   __pyx_k_tuple_4 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 177; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_4);
+  __Pyx_GOTREF(((PyObject *)__pyx_k_tuple_4));
   __Pyx_INCREF(((PyObject *)__pyx_kp_s_1));
   PyTuple_SET_ITEM(__pyx_k_tuple_4, 0, ((PyObject *)__pyx_kp_s_1));
   __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_1));
   __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_4));
 
-  /* "numpy.pxd":214
+  /* "numpy.pxd":211
  *             if ((flags & pybuf.PyBUF_C_CONTIGUOUS == pybuf.PyBUF_C_CONTIGUOUS)
  *                 and not PyArray_CHKFLAGS(self, NPY_C_CONTIGUOUS)):
  *                 raise ValueError(u"ndarray is not C contiguous")             # <<<<<<<<<<<<<<
  * 
  *             if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS)
  */
-  __pyx_k_tuple_6 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_6)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 214; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_6);
+  __pyx_k_tuple_6 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_6)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 211; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_k_tuple_6));
   __Pyx_INCREF(((PyObject *)__pyx_kp_u_5));
   PyTuple_SET_ITEM(__pyx_k_tuple_6, 0, ((PyObject *)__pyx_kp_u_5));
   __Pyx_GIVEREF(((PyObject *)__pyx_kp_u_5));
   __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_6));
 
-  /* "numpy.pxd":218
+  /* "numpy.pxd":215
  *             if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS)
  *                 and not PyArray_CHKFLAGS(self, NPY_F_CONTIGUOUS)):
  *                 raise ValueError(u"ndarray is not Fortran contiguous")             # <<<<<<<<<<<<<<
  * 
  *             info.buf = PyArray_DATA(self)
  */
-  __pyx_k_tuple_8 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_8)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 218; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_8);
+  __pyx_k_tuple_8 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_8)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 215; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_k_tuple_8));
   __Pyx_INCREF(((PyObject *)__pyx_kp_u_7));
   PyTuple_SET_ITEM(__pyx_k_tuple_8, 0, ((PyObject *)__pyx_kp_u_7));
   __Pyx_GIVEREF(((PyObject *)__pyx_kp_u_7));
   __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_8));
 
-  /* "numpy.pxd":256
+  /* "numpy.pxd":253
  *                 if ((descr.byteorder == '>' and little_endian) or
  *                     (descr.byteorder == '<' and not little_endian)):
  *                     raise ValueError(u"Non-native byte order not supported")             # <<<<<<<<<<<<<<
  *                 if   t == NPY_BYTE:        f = "b"
  *                 elif t == NPY_UBYTE:       f = "B"
  */
-  __pyx_k_tuple_10 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_10)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 256; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_10);
+  __pyx_k_tuple_10 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_10)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 253; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_k_tuple_10));
   __Pyx_INCREF(((PyObject *)__pyx_kp_u_9));
   PyTuple_SET_ITEM(__pyx_k_tuple_10, 0, ((PyObject *)__pyx_kp_u_9));
   __Pyx_GIVEREF(((PyObject *)__pyx_kp_u_9));
   __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_10));
 
-  /* "numpy.pxd":798
+  /* "numpy.pxd":795
  * 
  *         if (end - f) - (new_offset - offset[0]) < 15:
  *             raise RuntimeError(u"Format string allocated too short, see comment in numpy.pxd")             # <<<<<<<<<<<<<<
  * 
  *         if ((child.byteorder == '>' and little_endian) or
  */
-  __pyx_k_tuple_13 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_13)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 798; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_13);
+  __pyx_k_tuple_13 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_13)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 795; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_k_tuple_13));
   __Pyx_INCREF(((PyObject *)__pyx_kp_u_12));
   PyTuple_SET_ITEM(__pyx_k_tuple_13, 0, ((PyObject *)__pyx_kp_u_12));
   __Pyx_GIVEREF(((PyObject *)__pyx_kp_u_12));
   __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_13));
 
-  /* "numpy.pxd":802
+  /* "numpy.pxd":799
  *         if ((child.byteorder == '>' and little_endian) or
  *             (child.byteorder == '<' and not little_endian)):
  *             raise ValueError(u"Non-native byte order not supported")             # <<<<<<<<<<<<<<
  *             # One could encode it in the format string and have Cython
  *             # complain instead, BUT: < and > in format strings also imply
  */
-  __pyx_k_tuple_14 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_14)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 802; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_14);
+  __pyx_k_tuple_14 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_14)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 799; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_k_tuple_14));
   __Pyx_INCREF(((PyObject *)__pyx_kp_u_9));
   PyTuple_SET_ITEM(__pyx_k_tuple_14, 0, ((PyObject *)__pyx_kp_u_9));
   __Pyx_GIVEREF(((PyObject *)__pyx_kp_u_9));
   __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_14));
 
-  /* "numpy.pxd":822
+  /* "numpy.pxd":819
  *             t = child.type_num
  *             if end - f < 5:
  *                 raise RuntimeError(u"Format string allocated too short.")             # <<<<<<<<<<<<<<
  * 
  *             # Until ticket #99 is fixed, use integers to avoid warnings
  */
-  __pyx_k_tuple_16 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_16)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 822; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_16);
+  __pyx_k_tuple_16 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_16)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 819; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_k_tuple_16));
   __Pyx_INCREF(((PyObject *)__pyx_kp_u_15));
   PyTuple_SET_ITEM(__pyx_k_tuple_16, 0, ((PyObject *)__pyx_kp_u_15));
   __Pyx_GIVEREF(((PyObject *)__pyx_kp_u_15));
   __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_16));
-
-  /* "astropy/nddata/convolution/boundary_fill.pyx":15
- * 
- * @cython.boundscheck(False)  # turn off bounds-checking for entire function
- * def convolve1d_boundary_fill(np.ndarray[DTYPE_t, ndim=1] f,             # <<<<<<<<<<<<<<
- *                              np.ndarray[DTYPE_t, ndim=1] g,
- *                              float fill_value):
- */
-  __pyx_k_tuple_17 = PyTuple_New(17); if (unlikely(!__pyx_k_tuple_17)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_17);
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__f));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 0, ((PyObject *)__pyx_n_s__f));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__f));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__g));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 1, ((PyObject *)__pyx_n_s__g));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__g));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__fill_value));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 2, ((PyObject *)__pyx_n_s__fill_value));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__fill_value));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__nx));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 3, ((PyObject *)__pyx_n_s__nx));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__nx));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__nkx));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 4, ((PyObject *)__pyx_n_s__nkx));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__nkx));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__wkx));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 5, ((PyObject *)__pyx_n_s__wkx));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__wkx));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__fixed));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 6, ((PyObject *)__pyx_n_s__fixed));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__fixed));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__conv));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 7, ((PyObject *)__pyx_n_s__conv));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__conv));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__i));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 8, ((PyObject *)__pyx_n_s__i));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__i));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__iii));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 9, ((PyObject *)__pyx_n_s__iii));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__iii));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__ii));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 10, ((PyObject *)__pyx_n_s__ii));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__ii));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__iimin));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 11, ((PyObject *)__pyx_n_s__iimin));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__iimin));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__iimax));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 12, ((PyObject *)__pyx_n_s__iimax));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__iimax));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__top));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 13, ((PyObject *)__pyx_n_s__top));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__top));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__bot));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 14, ((PyObject *)__pyx_n_s__bot));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__bot));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__ker));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 15, ((PyObject *)__pyx_n_s__ker));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__ker));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__val));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 16, ((PyObject *)__pyx_n_s__val));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__val));
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_17));
-  __pyx_k_codeobj_18 = (PyObject*)__Pyx_PyCode_New(3, 0, 17, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_k_tuple_17, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_20, __pyx_n_s_19, 15, __pyx_empty_bytes); if (unlikely(!__pyx_k_codeobj_18)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-
-  /* "astropy/nddata/convolution/boundary_fill.pyx":87
- * 
- * @cython.boundscheck(False)  # turn off bounds-checking for entire function
- * def convolve2d_boundary_fill(np.ndarray[DTYPE_t, ndim=2] f,             # <<<<<<<<<<<<<<
- *                              np.ndarray[DTYPE_t, ndim=2] g,
- *                              float fill_value):
- */
-  __pyx_k_tuple_22 = PyTuple_New(25); if (unlikely(!__pyx_k_tuple_22)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 87; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_22);
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__f));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 0, ((PyObject *)__pyx_n_s__f));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__f));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__g));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 1, ((PyObject *)__pyx_n_s__g));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__g));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__fill_value));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 2, ((PyObject *)__pyx_n_s__fill_value));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__fill_value));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__nx));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 3, ((PyObject *)__pyx_n_s__nx));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__nx));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__ny));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 4, ((PyObject *)__pyx_n_s__ny));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__ny));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__nkx));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 5, ((PyObject *)__pyx_n_s__nkx));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__nkx));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__nky));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 6, ((PyObject *)__pyx_n_s__nky));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__nky));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__wkx));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 7, ((PyObject *)__pyx_n_s__wkx));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__wkx));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__wky));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 8, ((PyObject *)__pyx_n_s__wky));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__wky));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__fixed));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 9, ((PyObject *)__pyx_n_s__fixed));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__fixed));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__conv));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 10, ((PyObject *)__pyx_n_s__conv));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__conv));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__i));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 11, ((PyObject *)__pyx_n_s__i));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__i));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__j));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 12, ((PyObject *)__pyx_n_s__j));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__j));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__iii));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 13, ((PyObject *)__pyx_n_s__iii));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__iii));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__jjj));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 14, ((PyObject *)__pyx_n_s__jjj));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__jjj));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__ii));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 15, ((PyObject *)__pyx_n_s__ii));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__ii));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__jj));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 16, ((PyObject *)__pyx_n_s__jj));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__jj));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__iimin));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 17, ((PyObject *)__pyx_n_s__iimin));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__iimin));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__iimax));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 18, ((PyObject *)__pyx_n_s__iimax));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__iimax));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__jjmin));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 19, ((PyObject *)__pyx_n_s__jjmin));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__jjmin));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__jjmax));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 20, ((PyObject *)__pyx_n_s__jjmax));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__jjmax));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__top));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 21, ((PyObject *)__pyx_n_s__top));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__top));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__bot));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 22, ((PyObject *)__pyx_n_s__bot));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__bot));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__ker));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 23, ((PyObject *)__pyx_n_s__ker));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__ker));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__val));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 24, ((PyObject *)__pyx_n_s__val));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__val));
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_22));
-  __pyx_k_codeobj_23 = (PyObject*)__Pyx_PyCode_New(3, 0, 25, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_k_tuple_22, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_20, __pyx_n_s_24, 87, __pyx_empty_bytes); if (unlikely(!__pyx_k_codeobj_23)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 87; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-
-  /* "astropy/nddata/convolution/boundary_fill.pyx":172
- * 
- * @cython.boundscheck(False)  # turn off bounds-checking for entire function
- * def convolve3d_boundary_fill(np.ndarray[DTYPE_t, ndim=3] f,             # <<<<<<<<<<<<<<
- *                              np.ndarray[DTYPE_t, ndim=3] g,
- *                              float fill_value):
- */
-  __pyx_k_tuple_25 = PyTuple_New(33); if (unlikely(!__pyx_k_tuple_25)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 172; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_25);
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__f));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 0, ((PyObject *)__pyx_n_s__f));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__f));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__g));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 1, ((PyObject *)__pyx_n_s__g));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__g));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__fill_value));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 2, ((PyObject *)__pyx_n_s__fill_value));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__fill_value));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__nx));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 3, ((PyObject *)__pyx_n_s__nx));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__nx));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__ny));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 4, ((PyObject *)__pyx_n_s__ny));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__ny));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__nz));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 5, ((PyObject *)__pyx_n_s__nz));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__nz));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__nkx));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 6, ((PyObject *)__pyx_n_s__nkx));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__nkx));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__nky));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 7, ((PyObject *)__pyx_n_s__nky));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__nky));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__nkz));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 8, ((PyObject *)__pyx_n_s__nkz));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__nkz));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__wkx));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 9, ((PyObject *)__pyx_n_s__wkx));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__wkx));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__wky));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 10, ((PyObject *)__pyx_n_s__wky));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__wky));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__wkz));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 11, ((PyObject *)__pyx_n_s__wkz));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__wkz));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__fixed));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 12, ((PyObject *)__pyx_n_s__fixed));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__fixed));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__conv));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 13, ((PyObject *)__pyx_n_s__conv));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__conv));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__i));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 14, ((PyObject *)__pyx_n_s__i));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__i));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__j));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 15, ((PyObject *)__pyx_n_s__j));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__j));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__k));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 16, ((PyObject *)__pyx_n_s__k));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__k));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__iii));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 17, ((PyObject *)__pyx_n_s__iii));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__iii));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__jjj));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 18, ((PyObject *)__pyx_n_s__jjj));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__jjj));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__kkk));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 19, ((PyObject *)__pyx_n_s__kkk));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__kkk));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__ii));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 20, ((PyObject *)__pyx_n_s__ii));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__ii));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__jj));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 21, ((PyObject *)__pyx_n_s__jj));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__jj));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__kk));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 22, ((PyObject *)__pyx_n_s__kk));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__kk));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__iimin));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 23, ((PyObject *)__pyx_n_s__iimin));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__iimin));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__iimax));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 24, ((PyObject *)__pyx_n_s__iimax));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__iimax));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__jjmin));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 25, ((PyObject *)__pyx_n_s__jjmin));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__jjmin));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__jjmax));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 26, ((PyObject *)__pyx_n_s__jjmax));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__jjmax));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__kkmin));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 27, ((PyObject *)__pyx_n_s__kkmin));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__kkmin));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__kkmax));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 28, ((PyObject *)__pyx_n_s__kkmax));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__kkmax));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__top));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 29, ((PyObject *)__pyx_n_s__top));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__top));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__bot));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 30, ((PyObject *)__pyx_n_s__bot));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__bot));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__ker));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 31, ((PyObject *)__pyx_n_s__ker));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__ker));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__val));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 32, ((PyObject *)__pyx_n_s__val));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__val));
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_25));
-  __pyx_k_codeobj_26 = (PyObject*)__Pyx_PyCode_New(3, 0, 33, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_k_tuple_25, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_20, __pyx_n_s_27, 172, __pyx_empty_bytes); if (unlikely(!__pyx_k_codeobj_26)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 172; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_RefNannyFinishContext();
   return 0;
   __pyx_L1_error:;
@@ -6648,18 +6143,12 @@ PyMODINIT_FUNC PyInit_boundary_fill(void)
           Py_FatalError("failed to import 'refnanny' module");
   }
   #endif
-  __Pyx_RefNannySetupContext("PyMODINIT_FUNC PyInit_boundary_fill(void)", 0);
+  __Pyx_RefNannySetupContext("PyMODINIT_FUNC PyInit_boundary_fill(void)");
   if ( __Pyx_check_binary_version() < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_empty_tuple = PyTuple_New(0); if (unlikely(!__pyx_empty_tuple)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_empty_bytes = PyBytes_FromStringAndSize("", 0); if (unlikely(!__pyx_empty_bytes)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  #ifdef __Pyx_CyFunction_USED
-  if (__Pyx_CyFunction_init() < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  #endif
-  #ifdef __Pyx_FusedFunction_USED
-  if (__pyx_FusedFunction_init() < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  #endif
-  #ifdef __Pyx_Generator_USED
-  if (__pyx_Generator_init() < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  #ifdef __pyx_binding_PyCFunctionType_USED
+  if (__pyx_binding_PyCFunctionType_init() < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   #endif
   /*--- Library function declarations ---*/
   /*--- Threads initialization code ---*/
@@ -6695,11 +6184,11 @@ PyMODINIT_FUNC PyInit_boundary_fill(void)
   /*--- Function export code ---*/
   /*--- Type init code ---*/
   /*--- Type import code ---*/
-  __pyx_ptype_5numpy_dtype = __Pyx_ImportType("numpy", "dtype", sizeof(PyArray_Descr), 0); if (unlikely(!__pyx_ptype_5numpy_dtype)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 154; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_ptype_5numpy_flatiter = __Pyx_ImportType("numpy", "flatiter", sizeof(PyArrayIterObject), 0); if (unlikely(!__pyx_ptype_5numpy_flatiter)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 164; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_ptype_5numpy_broadcast = __Pyx_ImportType("numpy", "broadcast", sizeof(PyArrayMultiIterObject), 0); if (unlikely(!__pyx_ptype_5numpy_broadcast)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 168; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_ptype_5numpy_ndarray = __Pyx_ImportType("numpy", "ndarray", sizeof(PyArrayObject), 0); if (unlikely(!__pyx_ptype_5numpy_ndarray)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 177; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_ptype_5numpy_ufunc = __Pyx_ImportType("numpy", "ufunc", sizeof(PyUFuncObject), 0); if (unlikely(!__pyx_ptype_5numpy_ufunc)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 860; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_5numpy_dtype = __Pyx_ImportType("numpy", "dtype", sizeof(PyArray_Descr), 0); if (unlikely(!__pyx_ptype_5numpy_dtype)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 151; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_5numpy_flatiter = __Pyx_ImportType("numpy", "flatiter", sizeof(PyArrayIterObject), 0); if (unlikely(!__pyx_ptype_5numpy_flatiter)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 161; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_5numpy_broadcast = __Pyx_ImportType("numpy", "broadcast", sizeof(PyArrayMultiIterObject), 0); if (unlikely(!__pyx_ptype_5numpy_broadcast)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 165; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_5numpy_ndarray = __Pyx_ImportType("numpy", "ndarray", sizeof(PyArrayObject), 0); if (unlikely(!__pyx_ptype_5numpy_ndarray)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 174; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_5numpy_ufunc = __Pyx_ImportType("numpy", "ufunc", sizeof(PyUFuncObject), 0); if (unlikely(!__pyx_ptype_5numpy_ufunc)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 857; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   /*--- Variable import code ---*/
   /*--- Function import code ---*/
   /*--- Execution code ---*/
@@ -6737,9 +6226,9 @@ PyMODINIT_FUNC PyInit_boundary_fill(void)
  *                              np.ndarray[DTYPE_t, ndim=1] g,
  *                              float fill_value):
  */
-  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_7astropy_6nddata_11convolution_13boundary_fill_1convolve1d_boundary_fill, NULL, __pyx_n_s_21); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_7astropy_6nddata_11convolution_13boundary_fill_convolve1d_boundary_fill, NULL, __pyx_n_s_17); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
-  if (PyObject_SetAttr(__pyx_m, __pyx_n_s_19, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s_18, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
   /* "astropy/nddata/convolution/boundary_fill.pyx":87
@@ -6749,9 +6238,9 @@ PyMODINIT_FUNC PyInit_boundary_fill(void)
  *                              np.ndarray[DTYPE_t, ndim=2] g,
  *                              float fill_value):
  */
-  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_7astropy_6nddata_11convolution_13boundary_fill_3convolve2d_boundary_fill, NULL, __pyx_n_s_21); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 87; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_7astropy_6nddata_11convolution_13boundary_fill_1convolve2d_boundary_fill, NULL, __pyx_n_s_17); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 87; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
-  if (PyObject_SetAttr(__pyx_m, __pyx_n_s_24, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 87; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s_19, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 87; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
   /* "astropy/nddata/convolution/boundary_fill.pyx":172
@@ -6761,9 +6250,9 @@ PyMODINIT_FUNC PyInit_boundary_fill(void)
  *                              np.ndarray[DTYPE_t, ndim=3] g,
  *                              float fill_value):
  */
-  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_7astropy_6nddata_11convolution_13boundary_fill_5convolve3d_boundary_fill, NULL, __pyx_n_s_21); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 172; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_7astropy_6nddata_11convolution_13boundary_fill_2convolve3d_boundary_fill, NULL, __pyx_n_s_17); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 172; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
-  if (PyObject_SetAttr(__pyx_m, __pyx_n_s_27, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 172; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s_20, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 172; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
   /* "astropy/nddata/convolution/boundary_fill.pyx":1
@@ -6776,7 +6265,7 @@ PyMODINIT_FUNC PyInit_boundary_fill(void)
   if (PyObject_SetAttr(__pyx_m, __pyx_n_s____test__, ((PyObject *)__pyx_t_2)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
 
-  /* "numpy.pxd":974
+  /* "numpy.pxd":971
  *      arr.base = baseptr
  * 
  * cdef inline object get_array_base(ndarray arr):             # <<<<<<<<<<<<<<
@@ -6803,6 +6292,7 @@ PyMODINIT_FUNC PyInit_boundary_fill(void)
 }
 
 /* Runtime support code */
+
 #if CYTHON_REFNANNY
 static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname) {
     PyObject *m = NULL, *p = NULL;
@@ -6843,6 +6333,7 @@ static void __Pyx_RaiseArgtupleInvalid(
 {
     Py_ssize_t num_expected;
     const char *more_or_less;
+
     if (num_found < num_min) {
         num_expected = num_min;
         more_or_less = "at least";
@@ -6884,6 +6375,7 @@ static int __Pyx_ParseOptionalKeywords(
     Py_ssize_t pos = 0;
     PyObject*** name;
     PyObject*** first_kw_arg = argnames + num_pos_args;
+
     while (PyDict_Next(kwds, &pos, &key, &value)) {
         name = first_kw_arg;
         while (*name && (**name != key)) name++;
@@ -6893,7 +6385,7 @@ static int __Pyx_ParseOptionalKeywords(
             #if PY_MAJOR_VERSION < 3
             if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key))) {
             #else
-            if (unlikely(!PyUnicode_Check(key))) {
+            if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key))) {
             #endif
                 goto invalid_keyword_type;
             } else {
@@ -6909,6 +6401,7 @@ static int __Pyx_ParseOptionalKeywords(
                 if (*name) {
                     values[name-argnames] = value;
                 } else {
+                    /* unexpected keyword found */
                     for (name=argnames; name != first_kw_arg; name++) {
                         if (**name == key) goto arg_passed_twice;
                         #if PY_MAJOR_VERSION >= 3
@@ -6973,6 +6466,18 @@ static CYTHON_INLINE int __Pyx_IsLittleEndian(void) {
   unsigned int n = 1;
   return *(unsigned char*)(&n) != 0;
 }
+
+typedef struct {
+  __Pyx_StructField root;
+  __Pyx_BufFmt_StackElem* head;
+  size_t fmt_offset;
+  size_t new_count, enc_count;
+  int is_complex;
+  char enc_type;
+  char new_packmode;
+  char enc_packmode;
+} __Pyx_BufFmt_Context;
+
 static void __Pyx_BufFmt_Init(__Pyx_BufFmt_Context* ctx,
                               __Pyx_BufFmt_StackElem* stack,
                               __Pyx_TypeInfo* type) {
@@ -6991,8 +6496,6 @@ static void __Pyx_BufFmt_Init(__Pyx_BufFmt_Context* ctx,
   ctx->enc_count = 0;
   ctx->enc_type = 0;
   ctx->is_complex = 0;
-  ctx->is_valid_array = 0;
-  ctx->struct_alignment = 0;
   while (type->typegroup == 'S') {
     ++ctx->head;
     ctx->head->field = type->fields;
@@ -7000,6 +6503,7 @@ static void __Pyx_BufFmt_Init(__Pyx_BufFmt_Context* ctx,
     type = type->fields->type;
   }
 }
+
 static int __Pyx_BufFmt_ParseNumber(const char** ts) {
     int count;
     const char* t = *ts;
@@ -7015,17 +6519,12 @@ static int __Pyx_BufFmt_ParseNumber(const char** ts) {
     *ts = t;
     return count;
 }
-static int __Pyx_BufFmt_ExpectNumber(const char **ts) {
-    int number = __Pyx_BufFmt_ParseNumber(ts);
-    if (number == -1) /* First char was not a digit */
-        PyErr_Format(PyExc_ValueError,\
-                     "Does not understand character buffer dtype format string ('%c')", **ts);
-    return number;
-}
+
 static void __Pyx_BufFmt_RaiseUnexpectedChar(char ch) {
   PyErr_Format(PyExc_ValueError,
                "Unexpected format string character: '%c'", ch);
 }
+
 static const char* __Pyx_BufFmt_DescribeTypeChar(char ch, int is_complex) {
   switch (ch) {
     case 'b': return "'char'";
@@ -7044,14 +6543,14 @@ static const char* __Pyx_BufFmt_DescribeTypeChar(char ch, int is_complex) {
     case 'T': return "a struct";
     case 'O': return "Python object";
     case 'P': return "a pointer";
-    case 's': case 'p': return "a string";
     case 0: return "end";
     default: return "unparseable format string";
   }
 }
+
 static size_t __Pyx_BufFmt_TypeCharToStandardSize(char ch, int is_complex) {
   switch (ch) {
-    case '?': case 'c': case 'b': case 'B': case 's': case 'p': return 1;
+    case '?': case 'c': case 'b': case 'B': return 1;
     case 'h': case 'H': return 2;
     case 'i': case 'I': case 'l': case 'L': return 4;
     case 'q': case 'Q': return 8;
@@ -7067,9 +6566,10 @@ static size_t __Pyx_BufFmt_TypeCharToStandardSize(char ch, int is_complex) {
       return 0;
     }
 }
+
 static size_t __Pyx_BufFmt_TypeCharToNativeSize(char ch, int is_complex) {
   switch (ch) {
-    case 'c': case 'b': case 'B': case 's': case 'p': return 1;
+    case 'c': case 'b': case 'B': return 1;
     case 'h': case 'H': return sizeof(short);
     case 'i': case 'I': return sizeof(int);
     case 'l': case 'L': return sizeof(long);
@@ -7086,6 +6586,7 @@ static size_t __Pyx_BufFmt_TypeCharToNativeSize(char ch, int is_complex) {
     }
   }
 }
+
 typedef struct { char c; short x; } __Pyx_st_short;
 typedef struct { char c; int x; } __Pyx_st_int;
 typedef struct { char c; long x; } __Pyx_st_long;
@@ -7096,9 +6597,10 @@ typedef struct { char c; void *x; } __Pyx_st_void_p;
 #ifdef HAVE_LONG_LONG
 typedef struct { char c; PY_LONG_LONG x; } __Pyx_st_longlong;
 #endif
+
 static size_t __Pyx_BufFmt_TypeCharToAlignment(char ch, int is_complex) {
   switch (ch) {
-    case '?': case 'c': case 'b': case 'B': case 's': case 'p': return 1;
+    case '?': case 'c': case 'b': case 'B': return 1;
     case 'h': case 'H': return sizeof(__Pyx_st_short) - sizeof(short);
     case 'i': case 'I': return sizeof(__Pyx_st_int) - sizeof(int);
     case 'l': case 'L': return sizeof(__Pyx_st_long) - sizeof(long);
@@ -7114,57 +6616,21 @@ static size_t __Pyx_BufFmt_TypeCharToAlignment(char ch, int is_complex) {
       return 0;
     }
 }
-/* These are for computing the padding at the end of the struct to align
-   on the first member of the struct. This will probably the same as above,
-   but we don't have any guarantees.
- */
-typedef struct { short x; char c; } __Pyx_pad_short;
-typedef struct { int x; char c; } __Pyx_pad_int;
-typedef struct { long x; char c; } __Pyx_pad_long;
-typedef struct { float x; char c; } __Pyx_pad_float;
-typedef struct { double x; char c; } __Pyx_pad_double;
-typedef struct { long double x; char c; } __Pyx_pad_longdouble;
-typedef struct { void *x; char c; } __Pyx_pad_void_p;
-#ifdef HAVE_LONG_LONG
-typedef struct { PY_LONG_LONG x; char c; } __Pyx_pad_longlong;
-#endif
-static size_t __Pyx_BufFmt_TypeCharToPadding(char ch, int is_complex) {
-  switch (ch) {
-    case '?': case 'c': case 'b': case 'B': case 's': case 'p': return 1;
-    case 'h': case 'H': return sizeof(__Pyx_pad_short) - sizeof(short);
-    case 'i': case 'I': return sizeof(__Pyx_pad_int) - sizeof(int);
-    case 'l': case 'L': return sizeof(__Pyx_pad_long) - sizeof(long);
-#ifdef HAVE_LONG_LONG
-    case 'q': case 'Q': return sizeof(__Pyx_pad_longlong) - sizeof(PY_LONG_LONG);
-#endif
-    case 'f': return sizeof(__Pyx_pad_float) - sizeof(float);
-    case 'd': return sizeof(__Pyx_pad_double) - sizeof(double);
-    case 'g': return sizeof(__Pyx_pad_longdouble) - sizeof(long double);
-    case 'P': case 'O': return sizeof(__Pyx_pad_void_p) - sizeof(void*);
-    default:
-      __Pyx_BufFmt_RaiseUnexpectedChar(ch);
-      return 0;
-    }
-}
+
 static char __Pyx_BufFmt_TypeCharToGroup(char ch, int is_complex) {
   switch (ch) {
-    case 'c': case 'b': case 'h': case 'i':
-    case 'l': case 'q': case 's': case 'p':
-        return 'I';
-    case 'B': case 'H': case 'I': case 'L': case 'Q':
-        return 'U';
-    case 'f': case 'd': case 'g':
-        return (is_complex ? 'C' : 'R');
-    case 'O':
-        return 'O';
-    case 'P':
-        return 'P';
+    case 'c': case 'b': case 'h': case 'i': case 'l': case 'q': return 'I';
+    case 'B': case 'H': case 'I': case 'L': case 'Q': return 'U';
+    case 'f': case 'd': case 'g': return (is_complex ? 'C' : 'R');
+    case 'O': return 'O';
+    case 'P': return 'P';
     default: {
       __Pyx_BufFmt_RaiseUnexpectedChar(ch);
       return 0;
     }
   }
 }
+
 static void __Pyx_BufFmt_RaiseExpected(__Pyx_BufFmt_Context* ctx) {
   if (ctx->head == NULL || ctx->head->field == &ctx->root) {
     const char* expected;
@@ -7189,37 +6655,16 @@ static void __Pyx_BufFmt_RaiseExpected(__Pyx_BufFmt_Context* ctx) {
                  parent->type->name, field->name);
   }
 }
+
 static int __Pyx_BufFmt_ProcessTypeChunk(__Pyx_BufFmt_Context* ctx) {
   char group;
-  size_t size, offset, arraysize = 1;
+  size_t size, offset;
   if (ctx->enc_type == 0) return 0;
-  if (ctx->head->field->type->arraysize[0]) {
-    int i, ndim = 0;
-    if (ctx->enc_type == 's' || ctx->enc_type == 'p') {
-        ctx->is_valid_array = ctx->head->field->type->ndim == 1;
-        ndim = 1;
-        if (ctx->enc_count != ctx->head->field->type->arraysize[0]) {
-            PyErr_Format(PyExc_ValueError,
-                         "Expected a dimension of size %zu, got %zu",
-                         ctx->head->field->type->arraysize[0], ctx->enc_count);
-            return -1;
-        }
-    }
-    if (!ctx->is_valid_array) {
-      PyErr_Format(PyExc_ValueError, "Expected %d dimensions, got %d",
-                   ctx->head->field->type->ndim, ndim);
-      return -1;
-    }
-    for (i = 0; i < ctx->head->field->type->ndim; i++) {
-      arraysize *= ctx->head->field->type->arraysize[i];
-    }
-    ctx->is_valid_array = 0;
-    ctx->enc_count = 1;
-  }
   group = __Pyx_BufFmt_TypeCharToGroup(ctx->enc_type, ctx->is_complex);
   do {
     __Pyx_StructField* field = ctx->head->field;
     __Pyx_TypeInfo* type = field->type;
+
     if (ctx->enc_packmode == '@' || ctx->enc_packmode == '^') {
       size = __Pyx_BufFmt_TypeCharToNativeSize(ctx->enc_type, ctx->is_complex);
     } else {
@@ -7231,21 +6676,22 @@ static int __Pyx_BufFmt_ProcessTypeChunk(__Pyx_BufFmt_Context* ctx) {
       if (align_at == 0) return -1;
       align_mod_offset = ctx->fmt_offset % align_at;
       if (align_mod_offset > 0) ctx->fmt_offset += align_at - align_mod_offset;
-      if (ctx->struct_alignment == 0)
-          ctx->struct_alignment = __Pyx_BufFmt_TypeCharToPadding(ctx->enc_type,
-                                                                 ctx->is_complex);
     }
+
     if (type->size != size || type->typegroup != group) {
       if (type->typegroup == 'C' && type->fields != NULL) {
+        /* special case -- treat as struct rather than complex number */
         size_t parent_offset = ctx->head->parent_offset + field->offset;
         ++ctx->head;
         ctx->head->field = type->fields;
         ctx->head->parent_offset = parent_offset;
         continue;
       }
+
       __Pyx_BufFmt_RaiseExpected(ctx);
       return -1;
     }
+
     offset = ctx->head->parent_offset + field->offset;
     if (ctx->fmt_offset != offset) {
       PyErr_Format(PyExc_ValueError,
@@ -7253,10 +6699,12 @@ static int __Pyx_BufFmt_ProcessTypeChunk(__Pyx_BufFmt_Context* ctx) {
                    (Py_ssize_t)ctx->fmt_offset, (Py_ssize_t)offset);
       return -1;
     }
+
     ctx->fmt_offset += size;
-    if (arraysize)
-      ctx->fmt_offset += (arraysize - 1) * size;
+
     --ctx->enc_count; /* Consume from buffer string */
+
+    /* Done checking, move to next field, pushing or popping struct stack if needed */
     while (1) {
       if (field == &ctx->root) {
         ctx->head = NULL;
@@ -7288,48 +6736,7 @@ static int __Pyx_BufFmt_ProcessTypeChunk(__Pyx_BufFmt_Context* ctx) {
   ctx->is_complex = 0;
   return 0;
 }
-static CYTHON_INLINE PyObject *
-__pyx_buffmt_parse_array(__Pyx_BufFmt_Context* ctx, const char** tsp)
-{
-    const char *ts = *tsp;
-    int i = 0, number;
-    int ndim = ctx->head->field->type->ndim;
-;
-    ++ts;
-    if (ctx->new_count != 1) {
-        PyErr_SetString(PyExc_ValueError,
-                        "Cannot handle repeated arrays in format string");
-        return NULL;
-    }
-    if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL;
-    while (*ts && *ts != ')') {
-        if (isspace(*ts))
-            continue;
-        number = __Pyx_BufFmt_ExpectNumber(&ts);
-        if (number == -1) return NULL;
-        if (i < ndim && (size_t) number != ctx->head->field->type->arraysize[i])
-            return PyErr_Format(PyExc_ValueError,
-                        "Expected a dimension of size %zu, got %d",
-                        ctx->head->field->type->arraysize[i], number);
-        if (*ts != ',' && *ts != ')')
-            return PyErr_Format(PyExc_ValueError,
-                                "Expected a comma in format string, got '%c'", *ts);
-        if (*ts == ',') ts++;
-        i++;
-    }
-    if (i != ndim)
-        return PyErr_Format(PyExc_ValueError, "Expected %d dimension(s), got %d",
-                            ctx->head->field->type->ndim, i);
-    if (!*ts) {
-        PyErr_SetString(PyExc_ValueError,
-                        "Unexpected end of format string, expected ')'");
-        return NULL;
-    }
-    ctx->is_valid_array = 1;
-    ctx->new_count = 1;
-    *tsp = ++ts;
-    return Py_None;
-}
+
 static const char* __Pyx_BufFmt_CheckString(__Pyx_BufFmt_Context* ctx, const char* ts) {
   int got_Z = 0;
   while (1) {
@@ -7344,7 +6751,7 @@ static const char* __Pyx_BufFmt_CheckString(__Pyx_BufFmt_Context* ctx, const cha
           __Pyx_BufFmt_RaiseExpected(ctx);
           return NULL;
         }
-                return ts;
+        return ts;
       case ' ':
       case 10:
       case 13:
@@ -7376,17 +6783,12 @@ static const char* __Pyx_BufFmt_CheckString(__Pyx_BufFmt_Context* ctx, const cha
         {
           const char* ts_after_sub;
           size_t i, struct_count = ctx->new_count;
-          size_t struct_alignment = ctx->struct_alignment;
           ctx->new_count = 1;
           ++ts;
           if (*ts != '{') {
             PyErr_SetString(PyExc_ValueError, "Buffer acquisition: Expected '{' after 'T'");
             return NULL;
           }
-          if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL;
-          ctx->enc_type = 0; /* Erase processed last struct element */
-          ctx->enc_count = 0;
-          ctx->struct_alignment = 0;
           ++ts;
           ts_after_sub = ts;
           for (i = 0; i != struct_count; ++i) {
@@ -7394,19 +6796,10 @@ static const char* __Pyx_BufFmt_CheckString(__Pyx_BufFmt_Context* ctx, const cha
             if (!ts_after_sub) return NULL;
           }
           ts = ts_after_sub;
-          if (struct_alignment) ctx->struct_alignment = struct_alignment;
         }
         break;
       case '}': /* end of substruct; either repeat or move on */
-        {
-          size_t alignment = ctx->struct_alignment;
-          ++ts;
-          if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL;
-          ctx->enc_type = 0; /* Erase processed last struct element */
-          if (alignment && ctx->fmt_offset % alignment) {
-            ctx->fmt_offset += alignment - (ctx->fmt_offset % alignment);
-          }
-        }
+        ++ts;
         return ts;
       case 'x':
         if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL;
@@ -7427,11 +6820,13 @@ static const char* __Pyx_BufFmt_CheckString(__Pyx_BufFmt_Context* ctx, const cha
       case 'c': case 'b': case 'B': case 'h': case 'H': case 'i': case 'I':
       case 'l': case 'L': case 'q': case 'Q':
       case 'f': case 'd': case 'g':
-      case 'O': case 's': case 'p':
+      case 'O':
         if (ctx->enc_type == *ts && got_Z == ctx->is_complex &&
             ctx->enc_packmode == ctx->new_packmode) {
+          /* Continue pooling same type */
           ctx->enc_count += ctx->new_count;
         } else {
+          /* New type */
           if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL;
           ctx->enc_count = ctx->new_count;
           ctx->enc_packmode = ctx->new_packmode;
@@ -7447,18 +6842,20 @@ static const char* __Pyx_BufFmt_CheckString(__Pyx_BufFmt_Context* ctx, const cha
         while(*ts != ':') ++ts;
         ++ts;
         break;
-      case '(':
-        if (!__pyx_buffmt_parse_array(ctx, &ts)) return NULL;
-        break;
       default:
         {
-          int number = __Pyx_BufFmt_ExpectNumber(&ts);
-          if (number == -1) return NULL;
-          ctx->new_count = (size_t)number;
+          int number = __Pyx_BufFmt_ParseNumber(&ts);
+          if (number == -1) { /* First char was not a digit */
+            PyErr_Format(PyExc_ValueError,
+                         "Does not understand character buffer dtype format string ('%c')", *ts);
+            return NULL;
+          }
+          ctx->new_count = (size_t)number; 
         }
     }
   }
 }
+
 static CYTHON_INLINE void __Pyx_ZeroBuffer(Py_buffer* buf) {
   buf->buf = NULL;
   buf->obj = NULL;
@@ -7466,10 +6863,8 @@ static CYTHON_INLINE void __Pyx_ZeroBuffer(Py_buffer* buf) {
   buf->shape = __Pyx_zeros;
   buf->suboffsets = __Pyx_minusones;
 }
-static CYTHON_INLINE int __Pyx_GetBufferAndValidate(
-        Py_buffer* buf, PyObject* obj,  __Pyx_TypeInfo* dtype, int flags,
-        int nd, int cast, __Pyx_BufFmt_StackElem* stack)
-{
+
+static CYTHON_INLINE int __Pyx_GetBufferAndValidate(Py_buffer* buf, PyObject* obj, __Pyx_TypeInfo* dtype, int flags, int nd, int cast, __Pyx_BufFmt_StackElem* stack) {
   if (obj == Py_None || obj == NULL) {
     __Pyx_ZeroBuffer(buf);
     return 0;
@@ -7500,6 +6895,7 @@ fail:;
   __Pyx_ZeroBuffer(buf);
   return -1;
 }
+
 static CYTHON_INLINE void __Pyx_SafeReleaseBuffer(Py_buffer* info) {
   if (info->buf == NULL) return;
   if (info->suboffsets == __Pyx_minusones) info->suboffsets = NULL;
@@ -7513,9 +6909,9 @@ static CYTHON_INLINE long __Pyx_mod_long(long a, long b) {
 }
 
 static CYTHON_INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb) {
-#if CYTHON_COMPILING_IN_CPYTHON
     PyObject *tmp_type, *tmp_value, *tmp_tb;
     PyThreadState *tstate = PyThreadState_GET();
+
     tmp_type = tstate->curexc_type;
     tmp_value = tstate->curexc_value;
     tmp_tb = tstate->curexc_traceback;
@@ -7525,30 +6921,27 @@ static CYTHON_INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyOb
     Py_XDECREF(tmp_type);
     Py_XDECREF(tmp_value);
     Py_XDECREF(tmp_tb);
-#else
-    PyErr_Restore(type, value, tb);
-#endif
 }
+
 static CYTHON_INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb) {
-#if CYTHON_COMPILING_IN_CPYTHON
     PyThreadState *tstate = PyThreadState_GET();
     *type = tstate->curexc_type;
     *value = tstate->curexc_value;
     *tb = tstate->curexc_traceback;
+
     tstate->curexc_type = 0;
     tstate->curexc_value = 0;
     tstate->curexc_traceback = 0;
-#else
-    PyErr_Fetch(type, value, tb);
-#endif
 }
 
+
 #if PY_MAJOR_VERSION < 3
-static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb,
-                        CYTHON_UNUSED PyObject *cause) {
+static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause) {
+    /* cause is unused */
     Py_XINCREF(type);
     Py_XINCREF(value);
     Py_XINCREF(tb);
+    /* First, check the traceback argument, replacing None with NULL. */
     if (tb == Py_None) {
         Py_DECREF(tb);
         tb = 0;
@@ -7558,6 +6951,7 @@ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb,
             "raise: arg 3 must be a traceback or None");
         goto raise_error;
     }
+    /* Next, replace a missing value with None */
     if (value == NULL) {
         value = Py_None;
         Py_INCREF(value);
@@ -7568,11 +6962,13 @@ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb,
     if (!PyType_Check(type))
     #endif
     {
+        /* Raising an instance.  The value should be a dummy. */
         if (value != Py_None) {
             PyErr_SetString(PyExc_TypeError,
                 "instance exception may not have a separate value");
             goto raise_error;
         }
+        /* Normalize to raise <class>, <instance> */
         Py_DECREF(value);
         value = type;
         #if PY_VERSION_HEX < 0x02050000
@@ -7596,6 +6992,7 @@ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb,
             }
         #endif
     }
+
     __Pyx_ErrRestore(type, value, tb);
     return;
 raise_error:
@@ -7604,7 +7001,9 @@ raise_error:
     Py_XDECREF(tb);
     return;
 }
+
 #else /* Python 3+ */
+
 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause) {
     if (tb == Py_None) {
         tb = 0;
@@ -7615,6 +7014,7 @@ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject
     }
     if (value == Py_None)
         value = 0;
+
     if (PyExceptionInstance_Check(type)) {
         if (value) {
             PyErr_SetString(PyExc_TypeError,
@@ -7628,6 +7028,7 @@ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject
             "raise: exception class must be a subclass of BaseException");
         goto bad;
     }
+
     if (cause) {
         PyObject *fixed_cause;
         if (PyExceptionClass_Check(cause)) {
@@ -7650,7 +7051,9 @@ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject
         }
         PyException_SetCause(value, fixed_cause);
     }
+
     PyErr_SetObject(type, value);
+
     if (tb) {
         PyThreadState *tstate = PyThreadState_GET();
         PyObject* tmp_tb = tstate->curexc_traceback;
@@ -7660,6 +7063,7 @@ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject
             Py_XDECREF(tmp_tb);
         }
     }
+
 bad:
     return;
 }
@@ -7711,98 +7115,31 @@ static void __Pyx_UnpackTupleError(PyObject *t, Py_ssize_t index) {
 
 #if PY_MAJOR_VERSION < 3
 static int __Pyx_GetBuffer(PyObject *obj, Py_buffer *view, int flags) {
-    PyObject *getbuffer_cobj;
-
   #if PY_VERSION_HEX >= 0x02060000
-    if (PyObject_CheckBuffer(obj)) return PyObject_GetBuffer(obj, view, flags);
+  if (PyObject_CheckBuffer(obj)) return PyObject_GetBuffer(obj, view, flags);
   #endif
-
-        if (PyObject_TypeCheck(obj, __pyx_ptype_5numpy_ndarray)) return __pyx_pw_5numpy_7ndarray_1__getbuffer__(obj, view, flags);
-
-  #if PY_VERSION_HEX < 0x02060000
-    if (obj->ob_type->tp_dict &&
-        (getbuffer_cobj = PyMapping_GetItemString(obj->ob_type->tp_dict,
-                                             "__pyx_getbuffer"))) {
-        getbufferproc func;
-
-      #if PY_VERSION_HEX >= 0x02070000 && !(PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION == 0)
-        func = (getbufferproc) PyCapsule_GetPointer(getbuffer_cobj, "getbuffer(obj, view, flags)");
-      #else
-        func = (getbufferproc) PyCObject_AsVoidPtr(getbuffer_cobj);
-      #endif
-        Py_DECREF(getbuffer_cobj);
-        if (!func)
-            goto fail;
-
-        return func(obj, view, flags);
-    } else {
-        PyErr_Clear();
+  if (PyObject_TypeCheck(obj, __pyx_ptype_5numpy_ndarray)) return __pyx_pf_5numpy_7ndarray___getbuffer__(obj, view, flags);
+  else {
+  PyErr_Format(PyExc_TypeError, "'%100s' does not have the buffer interface", Py_TYPE(obj)->tp_name);
+  return -1;
     }
-  #endif
-
-    PyErr_Format(PyExc_TypeError, "'%100s' does not have the buffer interface", Py_TYPE(obj)->tp_name);
-
-#if PY_VERSION_HEX < 0x02060000
-fail:
-#endif
-
-    return -1;
 }
 
 static void __Pyx_ReleaseBuffer(Py_buffer *view) {
-    PyObject *obj = view->obj;
-    PyObject *releasebuffer_cobj;
-
-    if (!obj) return;
-
-  #if PY_VERSION_HEX >= 0x02060000
-    if (PyObject_CheckBuffer(obj)) {
-        PyBuffer_Release(view);
-        return;
-    }
-  #endif
-
-        if (PyObject_TypeCheck(obj, __pyx_ptype_5numpy_ndarray)) { __pyx_pw_5numpy_7ndarray_3__releasebuffer__(obj, view); return; }
-
-  #if PY_VERSION_HEX < 0x02060000
-    if (obj->ob_type->tp_dict &&
-        (releasebuffer_cobj = PyMapping_GetItemString(obj->ob_type->tp_dict,
-                                                      "__pyx_releasebuffer"))) {
-        releasebufferproc func;
-
-      #if PY_VERSION_HEX >= 0x02070000 && !(PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION == 0)
-        func = (releasebufferproc) PyCapsule_GetPointer(releasebuffer_cobj, "releasebuffer(obj, view)");
-      #else
-        func = (releasebufferproc) PyCObject_AsVoidPtr(releasebuffer_cobj);
-      #endif
-
-        Py_DECREF(releasebuffer_cobj);
-
-        if (!func)
-            goto fail;
-
-        func(obj, view);
-        return;
-    } else {
-        PyErr_Clear();
-    }
-  #endif
-
-    goto nofail;
-
-#if PY_VERSION_HEX < 0x02060000
-fail:
-#endif
-    PyErr_WriteUnraisable(obj);
-
-nofail:
+  PyObject* obj = view->obj;
+  if (obj) {
+    #if PY_VERSION_HEX >= 0x02060000
+    if (PyObject_CheckBuffer(obj)) {PyBuffer_Release(view); return;}
+    #endif
+    if (PyObject_TypeCheck(obj, __pyx_ptype_5numpy_ndarray)) __pyx_pf_5numpy_7ndarray_1__releasebuffer__(obj, view);
     Py_DECREF(obj);
     view->obj = NULL;
+  }
 }
 
-#endif /*  PY_MAJOR_VERSION < 3 */
+#endif
 
-    static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, long level) {
+static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, long level) {
     PyObject *py_import = 0;
     PyObject *empty_list = 0;
     PyObject *module = 0;
@@ -7828,33 +7165,12 @@ nofail:
         goto bad;
     #if PY_VERSION_HEX >= 0x02050000
     {
-        #if PY_MAJOR_VERSION >= 3
-        if (level == -1) {
-            if (strchr(__Pyx_MODULE_NAME, '.')) {
-                /* try package relative import first */
-                PyObject *py_level = PyInt_FromLong(1);
-                if (!py_level)
-                    goto bad;
-                module = PyObject_CallFunctionObjArgs(py_import,
-                    name, global_dict, empty_dict, list, py_level, NULL);
-                Py_DECREF(py_level);
-                if (!module) {
-                    if (!PyErr_ExceptionMatches(PyExc_ImportError))
-                        goto bad;
-                    PyErr_Clear();
-                }
-            }
-            level = 0; /* try absolute import on failure */
-        }
-        #endif
-        if (!module) {
-            PyObject *py_level = PyInt_FromLong(level);
-            if (!py_level)
-                goto bad;
-            module = PyObject_CallFunctionObjArgs(py_import,
-                name, global_dict, empty_dict, list, py_level, NULL);
-            Py_DECREF(py_level);
-        }
+        PyObject *py_level = PyInt_FromLong(level);
+        if (!py_level)
+            goto bad;
+        module = PyObject_CallFunctionObjArgs(py_import,
+            name, global_dict, empty_dict, list, py_level, NULL);
+        Py_DECREF(py_level);
     }
     #else
     if (level>0) {
@@ -8539,10 +7855,15 @@ static PyTypeObject *__Pyx_ImportType(const char *module_name, const char *class
     PyObject *result = 0;
     PyObject *py_name = 0;
     char warning[200];
+
     py_module = __Pyx_ImportModule(module_name);
     if (!py_module)
         goto bad;
-    py_name = __Pyx_PyIdentifier_FromString(class_name);
+    #if PY_MAJOR_VERSION < 3
+    py_name = PyString_FromString(class_name);
+    #else
+    py_name = PyUnicode_FromString(class_name);
+    #endif
     if (!py_name)
         goto bad;
     result = PyObject_GetAttr(py_module, py_name);
@@ -8558,7 +7879,7 @@ static PyTypeObject *__Pyx_ImportType(const char *module_name, const char *class
             module_name, class_name);
         goto bad;
     }
-    if (!strict && (size_t)((PyTypeObject *)result)->tp_basicsize > size) {
+    if (!strict && ((PyTypeObject *)result)->tp_basicsize > (Py_ssize_t)size) {
         PyOS_snprintf(warning, sizeof(warning),
             "%s.%s size changed, may indicate binary incompatibility",
             module_name, class_name);
@@ -8568,7 +7889,7 @@ static PyTypeObject *__Pyx_ImportType(const char *module_name, const char *class
         if (PyErr_WarnEx(NULL, warning, 0) < 0) goto bad;
         #endif
     }
-    else if ((size_t)((PyTypeObject *)result)->tp_basicsize != size) {
+    else if (((PyTypeObject *)result)->tp_basicsize != (Py_ssize_t)size) {
         PyErr_Format(PyExc_ValueError,
             "%s.%s has the wrong size, try recompiling",
             module_name, class_name);
@@ -8587,7 +7908,12 @@ bad:
 static PyObject *__Pyx_ImportModule(const char *name) {
     PyObject *py_name = 0;
     PyObject *py_module = 0;
-    py_name = __Pyx_PyIdentifier_FromString(name);
+
+    #if PY_MAJOR_VERSION < 3
+    py_name = PyString_FromString(name);
+    #else
+    py_name = PyUnicode_FromString(name);
+    #endif
     if (!py_name)
         goto bad;
     py_module = PyImport_Import(py_name);
@@ -8599,105 +7925,29 @@ bad:
 }
 #endif
 
-static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line) {
-    int start = 0, mid = 0, end = count - 1;
-    if (end >= 0 && code_line > entries[end].code_line) {
-        return count;
-    }
-    while (start < end) {
-        mid = (start + end) / 2;
-        if (code_line < entries[mid].code_line) {
-            end = mid;
-        } else if (code_line > entries[mid].code_line) {
-             start = mid + 1;
-        } else {
-            return mid;
-        }
-    }
-    if (code_line <= entries[mid].code_line) {
-        return mid;
-    } else {
-        return mid + 1;
-    }
-}
-static PyCodeObject *__pyx_find_code_object(int code_line) {
-    PyCodeObject* code_object;
-    int pos;
-    if (unlikely(!code_line) || unlikely(!__pyx_code_cache.entries)) {
-        return NULL;
-    }
-    pos = __pyx_bisect_code_objects(__pyx_code_cache.entries, __pyx_code_cache.count, code_line);
-    if (unlikely(pos >= __pyx_code_cache.count) || unlikely(__pyx_code_cache.entries[pos].code_line != code_line)) {
-        return NULL;
-    }
-    code_object = __pyx_code_cache.entries[pos].code_object;
-    Py_INCREF(code_object);
-    return code_object;
-}
-static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object) {
-    int pos, i;
-    __Pyx_CodeObjectCacheEntry* entries = __pyx_code_cache.entries;
-    if (unlikely(!code_line)) {
-        return;
-    }
-    if (unlikely(!entries)) {
-        entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Malloc(64*sizeof(__Pyx_CodeObjectCacheEntry));
-        if (likely(entries)) {
-            __pyx_code_cache.entries = entries;
-            __pyx_code_cache.max_count = 64;
-            __pyx_code_cache.count = 1;
-            entries[0].code_line = code_line;
-            entries[0].code_object = code_object;
-            Py_INCREF(code_object);
-        }
-        return;
-    }
-    pos = __pyx_bisect_code_objects(__pyx_code_cache.entries, __pyx_code_cache.count, code_line);
-    if ((pos < __pyx_code_cache.count) && unlikely(__pyx_code_cache.entries[pos].code_line == code_line)) {
-        PyCodeObject* tmp = entries[pos].code_object;
-        entries[pos].code_object = code_object;
-        Py_DECREF(tmp);
-        return;
-    }
-    if (__pyx_code_cache.count == __pyx_code_cache.max_count) {
-        int new_max = __pyx_code_cache.max_count + 64;
-        entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Realloc(
-            __pyx_code_cache.entries, new_max*sizeof(__Pyx_CodeObjectCacheEntry));
-        if (unlikely(!entries)) {
-            return;
-        }
-        __pyx_code_cache.entries = entries;
-        __pyx_code_cache.max_count = new_max;
-    }
-    for (i=__pyx_code_cache.count; i>pos; i--) {
-        entries[i] = entries[i-1];
-    }
-    entries[pos].code_line = code_line;
-    entries[pos].code_object = code_object;
-    __pyx_code_cache.count++;
-    Py_INCREF(code_object);
-}
-
 #include "compile.h"
 #include "frameobject.h"
 #include "traceback.h"
-static PyCodeObject* __Pyx_CreateCodeObjectForTraceback(
-            const char *funcname, int c_line,
-            int py_line, const char *filename) {
-    PyCodeObject *py_code = 0;
+
+static void __Pyx_AddTraceback(const char *funcname, int __pyx_clineno,
+                               int __pyx_lineno, const char *__pyx_filename) {
     PyObject *py_srcfile = 0;
     PyObject *py_funcname = 0;
+    PyObject *py_globals = 0;
+    PyCodeObject *py_code = 0;
+    PyFrameObject *py_frame = 0;
+
     #if PY_MAJOR_VERSION < 3
-    py_srcfile = PyString_FromString(filename);
+    py_srcfile = PyString_FromString(__pyx_filename);
     #else
-    py_srcfile = PyUnicode_FromString(filename);
+    py_srcfile = PyUnicode_FromString(__pyx_filename);
     #endif
     if (!py_srcfile) goto bad;
-    if (c_line) {
+    if (__pyx_clineno) {
         #if PY_MAJOR_VERSION < 3
-        py_funcname = PyString_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line);
+        py_funcname = PyString_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, __pyx_clineno);
         #else
-        py_funcname = PyUnicode_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line);
+        py_funcname = PyUnicode_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, __pyx_clineno);
         #endif
     }
     else {
@@ -8708,45 +7958,28 @@ static PyCodeObject* __Pyx_CreateCodeObjectForTraceback(
         #endif
     }
     if (!py_funcname) goto bad;
-    py_code = __Pyx_PyCode_New(
+    py_globals = PyModule_GetDict(__pyx_m);
+    if (!py_globals) goto bad;
+    py_code = PyCode_New(
         0,            /*int argcount,*/
+        #if PY_MAJOR_VERSION >= 3
         0,            /*int kwonlyargcount,*/
+        #endif
         0,            /*int nlocals,*/
         0,            /*int stacksize,*/
         0,            /*int flags,*/
         __pyx_empty_bytes, /*PyObject *code,*/
-        __pyx_empty_tuple, /*PyObject *consts,*/
-        __pyx_empty_tuple, /*PyObject *names,*/
-        __pyx_empty_tuple, /*PyObject *varnames,*/
-        __pyx_empty_tuple, /*PyObject *freevars,*/
-        __pyx_empty_tuple, /*PyObject *cellvars,*/
+        __pyx_empty_tuple,  /*PyObject *consts,*/
+        __pyx_empty_tuple,  /*PyObject *names,*/
+        __pyx_empty_tuple,  /*PyObject *varnames,*/
+        __pyx_empty_tuple,  /*PyObject *freevars,*/
+        __pyx_empty_tuple,  /*PyObject *cellvars,*/
         py_srcfile,   /*PyObject *filename,*/
         py_funcname,  /*PyObject *name,*/
-        py_line,      /*int firstlineno,*/
+        __pyx_lineno,   /*int firstlineno,*/
         __pyx_empty_bytes  /*PyObject *lnotab*/
     );
-    Py_DECREF(py_srcfile);
-    Py_DECREF(py_funcname);
-    return py_code;
-bad:
-    Py_XDECREF(py_srcfile);
-    Py_XDECREF(py_funcname);
-    return NULL;
-}
-static void __Pyx_AddTraceback(const char *funcname, int c_line,
-                               int py_line, const char *filename) {
-    PyCodeObject *py_code = 0;
-    PyObject *py_globals = 0;
-    PyFrameObject *py_frame = 0;
-    py_code = __pyx_find_code_object(c_line ? c_line : py_line);
-    if (!py_code) {
-        py_code = __Pyx_CreateCodeObjectForTraceback(
-            funcname, c_line, py_line, filename);
-        if (!py_code) goto bad;
-        __pyx_insert_code_object(c_line ? c_line : py_line, py_code);
-    }
-    py_globals = PyModule_GetDict(__pyx_m);
-    if (!py_globals) goto bad;
+    if (!py_code) goto bad;
     py_frame = PyFrame_New(
         PyThreadState_GET(), /*PyThreadState *tstate,*/
         py_code,             /*PyCodeObject *code,*/
@@ -8754,9 +7987,11 @@ static void __Pyx_AddTraceback(const char *funcname, int c_line,
         0                    /*PyObject *locals*/
     );
     if (!py_frame) goto bad;
-    py_frame->f_lineno = py_line;
+    py_frame->f_lineno = __pyx_lineno;
     PyTraceBack_Here(py_frame);
 bad:
+    Py_XDECREF(py_srcfile);
+    Py_XDECREF(py_funcname);
     Py_XDECREF(py_code);
     Py_XDECREF(py_frame);
 }
@@ -8791,7 +8026,6 @@ static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) {
     return 0;
 }
 
-
 /* Type Conversion Functions */
 
 static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject* x) {
diff --git a/astropy/nddata/convolution/boundary_none.c b/astropy/nddata/convolution/boundary_none.c
index 2c715b5..35d6f69 100644
--- a/astropy/nddata/convolution/boundary_none.c
+++ b/astropy/nddata/convolution/boundary_none.c
@@ -1,12 +1,11 @@
-/* Generated by Cython 0.16 on Tue Jun 19 01:38:33 2012 */
+/* Generated by Cython 0.15.1 on Mon Dec 24 15:34:34 2012 */
 
 #define PY_SSIZE_T_CLEAN
 #include "Python.h"
 #ifndef Py_PYTHON_H
     #error Python headers needed to compile C extensions, please install development version of Python.
-#elif PY_VERSION_HEX < 0x02040000
-    #error Cython requires Python 2.4+.
 #else
+
 #include <stddef.h> /* For offsetof */
 #ifndef offsetof
 #define offsetof(type, member) ( (size_t) & ((type*)0) -> member )
@@ -35,22 +34,10 @@
   #define PY_LONG_LONG LONG_LONG
 #endif
 
-#ifndef Py_HUGE_VAL
-  #define Py_HUGE_VAL HUGE_VAL
-#endif
-
-#ifdef PYPY_VERSION
-#define CYTHON_COMPILING_IN_PYPY 1
-#define CYTHON_COMPILING_IN_CPYTHON 0
-#else
-#define CYTHON_COMPILING_IN_PYPY 0
-#define CYTHON_COMPILING_IN_CPYTHON 1
-#endif
-
-#if CYTHON_COMPILING_IN_PYPY
-  #define __Pyx_PyCFunction_Call PyObject_Call
-#else
-  #define __Pyx_PyCFunction_Call PyCFunction_Call
+#if PY_VERSION_HEX < 0x02040000
+  #define METH_COEXIST 0
+  #define PyDict_CheckExact(op) (Py_TYPE(op) == &PyDict_Type)
+  #define PyDict_Contains(d,o)   PySequence_Contains(d,o)
 #endif
 
 #if PY_VERSION_HEX < 0x02050000
@@ -63,9 +50,6 @@
   #define PyNumber_Index(o)    PyNumber_Int(o)
   #define PyIndex_Check(o)     PyNumber_Check(o)
   #define PyErr_WarnEx(category, message, stacklevel) PyErr_Warn(category, message)
-  #define __PYX_BUILD_PY_SSIZE_T "i"
-#else
-  #define __PYX_BUILD_PY_SSIZE_T "n"
 #endif
 
 #if PY_VERSION_HEX < 0x02060000
@@ -99,25 +83,13 @@
   #define PyBUF_F_CONTIGUOUS (0x0040 | PyBUF_STRIDES)
   #define PyBUF_ANY_CONTIGUOUS (0x0080 | PyBUF_STRIDES)
   #define PyBUF_INDIRECT (0x0100 | PyBUF_STRIDES)
-  #define PyBUF_RECORDS (PyBUF_STRIDES | PyBUF_FORMAT | PyBUF_WRITABLE)
-  #define PyBUF_FULL (PyBUF_INDIRECT | PyBUF_FORMAT | PyBUF_WRITABLE)
 
-  typedef int (*getbufferproc)(PyObject *, Py_buffer *, int);
-  typedef void (*releasebufferproc)(PyObject *, Py_buffer *);
 #endif
 
 #if PY_MAJOR_VERSION < 3
   #define __Pyx_BUILTIN_MODULE_NAME "__builtin__"
-  #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) \
-          PyCode_New(a, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)
 #else
   #define __Pyx_BUILTIN_MODULE_NAME "builtins"
-  #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) \
-          PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)
-#endif
-
-#if PY_MAJOR_VERSION < 3 && PY_MINOR_VERSION < 6
-  #define PyUnicode_FromString(s) PyUnicode_Decode(s, strlen(s), "UTF-8", "strict")
 #endif
 
 #if PY_MAJOR_VERSION >= 3
@@ -129,17 +101,6 @@
   #define Py_TPFLAGS_HAVE_NEWBUFFER 0
 #endif
 
-
-#if PY_VERSION_HEX > 0x03030000 && defined(PyUnicode_GET_LENGTH)
-  #define CYTHON_PEP393_ENABLED 1
-  #define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_LENGTH(u)
-  #define __Pyx_PyUnicode_READ_CHAR(u, i) PyUnicode_READ_CHAR(u, i)
-#else
-  #define CYTHON_PEP393_ENABLED 0
-  #define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_SIZE(u)
-  #define __Pyx_PyUnicode_READ_CHAR(u, i) ((Py_UCS4)(PyUnicode_AS_UNICODE(u)[i]))
-#endif
-
 #if PY_MAJOR_VERSION >= 3
   #define PyBaseString_Type            PyUnicode_Type
   #define PyStringObject               PyUnicodeObject
@@ -207,6 +168,15 @@
   #define __Pyx_PyInt_AsHash_t   PyInt_AsSsize_t
 #endif
 
+
+#if PY_MAJOR_VERSION >= 3
+  #define __Pyx_PyNumber_Divide(x,y)         PyNumber_TrueDivide(x,y)
+  #define __Pyx_PyNumber_InPlaceDivide(x,y)  PyNumber_InPlaceTrueDivide(x,y)
+#else
+  #define __Pyx_PyNumber_Divide(x,y)         PyNumber_TrueDivide(x,y)
+  #define __Pyx_PyNumber_InPlaceDivide(x,y)  PyNumber_InPlaceTrueDivide(x,y)
+#endif
+
 #if (PY_MAJOR_VERSION < 3) || (PY_VERSION_HEX >= 0x03010300)
   #define __Pyx_PySequence_GetSlice(obj, a, b) PySequence_GetSlice(obj, a, b)
   #define __Pyx_PySequence_SetSlice(obj, a, b, value) PySequence_SetSlice(obj, a, b, value)
@@ -248,14 +218,6 @@
   #define __Pyx_DOCSTR(n)  (n)
 #endif
 
-#if PY_MAJOR_VERSION >= 3
-  #define __Pyx_PyNumber_Divide(x,y)         PyNumber_TrueDivide(x,y)
-  #define __Pyx_PyNumber_InPlaceDivide(x,y)  PyNumber_InPlaceTrueDivide(x,y)
-#else
-  #define __Pyx_PyNumber_Divide(x,y)         PyNumber_TrueDivide(x,y)
-  #define __Pyx_PyNumber_InPlaceDivide(x,y)  PyNumber_InPlaceTrueDivide(x,y)
-#endif
-
 #ifndef __PYX_EXTERN_C
   #ifdef __cplusplus
     #define __PYX_EXTERN_C extern "C"
@@ -305,7 +267,7 @@
 #   else
 #     define CYTHON_UNUSED
 #   endif
-# elif defined(__ICC) || (defined(__INTEL_COMPILER) && !defined(_MSC_VER))
+# elif defined(__ICC) || defined(__INTEL_COMPILER)
 #   define CYTHON_UNUSED __attribute__ ((__unused__))
 # else
 #   define CYTHON_UNUSED
@@ -330,7 +292,7 @@ static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t);
 static CYTHON_INLINE size_t __Pyx_PyInt_AsSize_t(PyObject*);
 
 #define __pyx_PyFloat_AsDouble(x) (PyFloat_CheckExact(x) ? PyFloat_AS_DOUBLE(x) : PyFloat_AsDouble(x))
-#define __pyx_PyFloat_AsFloat(x) ((float) __pyx_PyFloat_AsDouble(x))
+
 
 #ifdef __GNUC__
   /* Test for GCC > 2.95 */
@@ -355,6 +317,7 @@ static int __pyx_clineno = 0;
 static const char * __pyx_cfilenm= __FILE__;
 static const char *__pyx_filename;
 
+
 #if !defined(CYTHON_CCOMPLEX)
   #if defined(__cplusplus)
     #define CYTHON_CCOMPLEX 1
@@ -364,6 +327,7 @@ static const char *__pyx_filename;
     #define CYTHON_CCOMPLEX 0
   #endif
 #endif
+
 #if CYTHON_CCOMPLEX
   #ifdef __cplusplus
     #include <complex>
@@ -371,53 +335,18 @@ static const char *__pyx_filename;
     #include <complex.h>
   #endif
 #endif
+
 #if CYTHON_CCOMPLEX && !defined(__cplusplus) && defined(__sun__) && defined(__GNUC__)
   #undef _Complex_I
   #define _Complex_I 1.0fj
 #endif
 
-
 static const char *__pyx_f[] = {
   "boundary_none.pyx",
   "numpy.pxd",
 };
-#define IS_UNSIGNED(type) (((type) -1) > 0)
-struct __Pyx_StructField_;
-#define __PYX_BUF_FLAGS_PACKED_STRUCT (1 << 0)
-typedef struct {
-  const char* name; /* for error messages only */
-  struct __Pyx_StructField_* fields;
-  size_t size;     /* sizeof(type) */
-  size_t arraysize[8]; /* length of array in each dimension */
-  int ndim;
-  char typegroup; /* _R_eal, _C_omplex, Signed _I_nt, _U_nsigned int, _S_truct, _P_ointer, _O_bject */
-  char is_unsigned;
-  int flags;
-} __Pyx_TypeInfo;
-typedef struct __Pyx_StructField_ {
-  __Pyx_TypeInfo* type;
-  const char* name;
-  size_t offset;
-} __Pyx_StructField;
-typedef struct {
-  __Pyx_StructField* field;
-  size_t parent_offset;
-} __Pyx_BufFmt_StackElem;
-typedef struct {
-  __Pyx_StructField root;
-  __Pyx_BufFmt_StackElem* head;
-  size_t fmt_offset;
-  size_t new_count, enc_count;
-  size_t struct_alignment;
-  int is_complex;
-  char enc_type;
-  char new_packmode;
-  char enc_packmode;
-  char is_valid_array;
-} __Pyx_BufFmt_Context;
-
 
-/* "numpy.pxd":722
+/* "numpy.pxd":719
  * # in Cython to enable them only on the right systems.
  * 
  * ctypedef npy_int8       int8_t             # <<<<<<<<<<<<<<
@@ -426,7 +355,7 @@ typedef struct {
  */
 typedef npy_int8 __pyx_t_5numpy_int8_t;
 
-/* "numpy.pxd":723
+/* "numpy.pxd":720
  * 
  * ctypedef npy_int8       int8_t
  * ctypedef npy_int16      int16_t             # <<<<<<<<<<<<<<
@@ -435,7 +364,7 @@ typedef npy_int8 __pyx_t_5numpy_int8_t;
  */
 typedef npy_int16 __pyx_t_5numpy_int16_t;
 
-/* "numpy.pxd":724
+/* "numpy.pxd":721
  * ctypedef npy_int8       int8_t
  * ctypedef npy_int16      int16_t
  * ctypedef npy_int32      int32_t             # <<<<<<<<<<<<<<
@@ -444,7 +373,7 @@ typedef npy_int16 __pyx_t_5numpy_int16_t;
  */
 typedef npy_int32 __pyx_t_5numpy_int32_t;
 
-/* "numpy.pxd":725
+/* "numpy.pxd":722
  * ctypedef npy_int16      int16_t
  * ctypedef npy_int32      int32_t
  * ctypedef npy_int64      int64_t             # <<<<<<<<<<<<<<
@@ -453,7 +382,7 @@ typedef npy_int32 __pyx_t_5numpy_int32_t;
  */
 typedef npy_int64 __pyx_t_5numpy_int64_t;
 
-/* "numpy.pxd":729
+/* "numpy.pxd":726
  * #ctypedef npy_int128     int128_t
  * 
  * ctypedef npy_uint8      uint8_t             # <<<<<<<<<<<<<<
@@ -462,7 +391,7 @@ typedef npy_int64 __pyx_t_5numpy_int64_t;
  */
 typedef npy_uint8 __pyx_t_5numpy_uint8_t;
 
-/* "numpy.pxd":730
+/* "numpy.pxd":727
  * 
  * ctypedef npy_uint8      uint8_t
  * ctypedef npy_uint16     uint16_t             # <<<<<<<<<<<<<<
@@ -471,7 +400,7 @@ typedef npy_uint8 __pyx_t_5numpy_uint8_t;
  */
 typedef npy_uint16 __pyx_t_5numpy_uint16_t;
 
-/* "numpy.pxd":731
+/* "numpy.pxd":728
  * ctypedef npy_uint8      uint8_t
  * ctypedef npy_uint16     uint16_t
  * ctypedef npy_uint32     uint32_t             # <<<<<<<<<<<<<<
@@ -480,7 +409,7 @@ typedef npy_uint16 __pyx_t_5numpy_uint16_t;
  */
 typedef npy_uint32 __pyx_t_5numpy_uint32_t;
 
-/* "numpy.pxd":732
+/* "numpy.pxd":729
  * ctypedef npy_uint16     uint16_t
  * ctypedef npy_uint32     uint32_t
  * ctypedef npy_uint64     uint64_t             # <<<<<<<<<<<<<<
@@ -489,7 +418,7 @@ typedef npy_uint32 __pyx_t_5numpy_uint32_t;
  */
 typedef npy_uint64 __pyx_t_5numpy_uint64_t;
 
-/* "numpy.pxd":736
+/* "numpy.pxd":733
  * #ctypedef npy_uint128    uint128_t
  * 
  * ctypedef npy_float32    float32_t             # <<<<<<<<<<<<<<
@@ -498,7 +427,7 @@ typedef npy_uint64 __pyx_t_5numpy_uint64_t;
  */
 typedef npy_float32 __pyx_t_5numpy_float32_t;
 
-/* "numpy.pxd":737
+/* "numpy.pxd":734
  * 
  * ctypedef npy_float32    float32_t
  * ctypedef npy_float64    float64_t             # <<<<<<<<<<<<<<
@@ -507,7 +436,7 @@ typedef npy_float32 __pyx_t_5numpy_float32_t;
  */
 typedef npy_float64 __pyx_t_5numpy_float64_t;
 
-/* "numpy.pxd":746
+/* "numpy.pxd":743
  * # The int types are mapped a bit surprising --
  * # numpy.int corresponds to 'l' and numpy.long to 'q'
  * ctypedef npy_long       int_t             # <<<<<<<<<<<<<<
@@ -516,7 +445,7 @@ typedef npy_float64 __pyx_t_5numpy_float64_t;
  */
 typedef npy_long __pyx_t_5numpy_int_t;
 
-/* "numpy.pxd":747
+/* "numpy.pxd":744
  * # numpy.int corresponds to 'l' and numpy.long to 'q'
  * ctypedef npy_long       int_t
  * ctypedef npy_longlong   long_t             # <<<<<<<<<<<<<<
@@ -525,7 +454,7 @@ typedef npy_long __pyx_t_5numpy_int_t;
  */
 typedef npy_longlong __pyx_t_5numpy_long_t;
 
-/* "numpy.pxd":748
+/* "numpy.pxd":745
  * ctypedef npy_long       int_t
  * ctypedef npy_longlong   long_t
  * ctypedef npy_longlong   longlong_t             # <<<<<<<<<<<<<<
@@ -534,7 +463,7 @@ typedef npy_longlong __pyx_t_5numpy_long_t;
  */
 typedef npy_longlong __pyx_t_5numpy_longlong_t;
 
-/* "numpy.pxd":750
+/* "numpy.pxd":747
  * ctypedef npy_longlong   longlong_t
  * 
  * ctypedef npy_ulong      uint_t             # <<<<<<<<<<<<<<
@@ -543,7 +472,7 @@ typedef npy_longlong __pyx_t_5numpy_longlong_t;
  */
 typedef npy_ulong __pyx_t_5numpy_uint_t;
 
-/* "numpy.pxd":751
+/* "numpy.pxd":748
  * 
  * ctypedef npy_ulong      uint_t
  * ctypedef npy_ulonglong  ulong_t             # <<<<<<<<<<<<<<
@@ -552,7 +481,7 @@ typedef npy_ulong __pyx_t_5numpy_uint_t;
  */
 typedef npy_ulonglong __pyx_t_5numpy_ulong_t;
 
-/* "numpy.pxd":752
+/* "numpy.pxd":749
  * ctypedef npy_ulong      uint_t
  * ctypedef npy_ulonglong  ulong_t
  * ctypedef npy_ulonglong  ulonglong_t             # <<<<<<<<<<<<<<
@@ -561,7 +490,7 @@ typedef npy_ulonglong __pyx_t_5numpy_ulong_t;
  */
 typedef npy_ulonglong __pyx_t_5numpy_ulonglong_t;
 
-/* "numpy.pxd":754
+/* "numpy.pxd":751
  * ctypedef npy_ulonglong  ulonglong_t
  * 
  * ctypedef npy_intp       intp_t             # <<<<<<<<<<<<<<
@@ -570,7 +499,7 @@ typedef npy_ulonglong __pyx_t_5numpy_ulonglong_t;
  */
 typedef npy_intp __pyx_t_5numpy_intp_t;
 
-/* "numpy.pxd":755
+/* "numpy.pxd":752
  * 
  * ctypedef npy_intp       intp_t
  * ctypedef npy_uintp      uintp_t             # <<<<<<<<<<<<<<
@@ -579,7 +508,7 @@ typedef npy_intp __pyx_t_5numpy_intp_t;
  */
 typedef npy_uintp __pyx_t_5numpy_uintp_t;
 
-/* "numpy.pxd":757
+/* "numpy.pxd":754
  * ctypedef npy_uintp      uintp_t
  * 
  * ctypedef npy_double     float_t             # <<<<<<<<<<<<<<
@@ -588,7 +517,7 @@ typedef npy_uintp __pyx_t_5numpy_uintp_t;
  */
 typedef npy_double __pyx_t_5numpy_float_t;
 
-/* "numpy.pxd":758
+/* "numpy.pxd":755
  * 
  * ctypedef npy_double     float_t
  * ctypedef npy_double     double_t             # <<<<<<<<<<<<<<
@@ -597,7 +526,7 @@ typedef npy_double __pyx_t_5numpy_float_t;
  */
 typedef npy_double __pyx_t_5numpy_double_t;
 
-/* "numpy.pxd":759
+/* "numpy.pxd":756
  * ctypedef npy_double     float_t
  * ctypedef npy_double     double_t
  * ctypedef npy_longdouble longdouble_t             # <<<<<<<<<<<<<<
@@ -614,6 +543,7 @@ typedef npy_longdouble __pyx_t_5numpy_longdouble_t;
  * cdef extern from "numpy/npy_math.h":
  */
 typedef __pyx_t_5numpy_float_t __pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t;
+
 #if CYTHON_CCOMPLEX
   #ifdef __cplusplus
     typedef ::std::complex< float > __pyx_t_float_complex;
@@ -634,10 +564,9 @@ typedef __pyx_t_5numpy_float_t __pyx_t_7astropy_6nddata_11convolution_13boundary
     typedef struct { double real, imag; } __pyx_t_double_complex;
 #endif
 
-
 /*--- Type declarations ---*/
 
-/* "numpy.pxd":761
+/* "numpy.pxd":758
  * ctypedef npy_longdouble longdouble_t
  * 
  * ctypedef npy_cfloat      cfloat_t             # <<<<<<<<<<<<<<
@@ -646,7 +575,7 @@ typedef __pyx_t_5numpy_float_t __pyx_t_7astropy_6nddata_11convolution_13boundary
  */
 typedef npy_cfloat __pyx_t_5numpy_cfloat_t;
 
-/* "numpy.pxd":762
+/* "numpy.pxd":759
  * 
  * ctypedef npy_cfloat      cfloat_t
  * ctypedef npy_cdouble     cdouble_t             # <<<<<<<<<<<<<<
@@ -655,7 +584,7 @@ typedef npy_cfloat __pyx_t_5numpy_cfloat_t;
  */
 typedef npy_cdouble __pyx_t_5numpy_cdouble_t;
 
-/* "numpy.pxd":763
+/* "numpy.pxd":760
  * ctypedef npy_cfloat      cfloat_t
  * ctypedef npy_cdouble     cdouble_t
  * ctypedef npy_clongdouble clongdouble_t             # <<<<<<<<<<<<<<
@@ -664,7 +593,7 @@ typedef npy_cdouble __pyx_t_5numpy_cdouble_t;
  */
 typedef npy_clongdouble __pyx_t_5numpy_clongdouble_t;
 
-/* "numpy.pxd":765
+/* "numpy.pxd":762
  * ctypedef npy_clongdouble clongdouble_t
  * 
  * ctypedef npy_cdouble     complex_t             # <<<<<<<<<<<<<<
@@ -672,9 +601,12 @@ typedef npy_clongdouble __pyx_t_5numpy_clongdouble_t;
  * cdef inline object PyArray_MultiIterNew1(a):
  */
 typedef npy_cdouble __pyx_t_5numpy_complex_t;
+
+
 #ifndef CYTHON_REFNANNY
   #define CYTHON_REFNANNY 0
 #endif
+
 #if CYTHON_REFNANNY
   typedef struct {
     void (*INCREF)(void*, PyObject*, int);
@@ -687,21 +619,8 @@ typedef npy_cdouble __pyx_t_5numpy_complex_t;
   static __Pyx_RefNannyAPIStruct *__Pyx_RefNanny = NULL;
   static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname); /*proto*/
   #define __Pyx_RefNannyDeclarations void *__pyx_refnanny = NULL;
-#ifdef WITH_THREAD
-  #define __Pyx_RefNannySetupContext(name, acquire_gil) \
-          if (acquire_gil) { \
-              PyGILState_STATE __pyx_gilstate_save = PyGILState_Ensure(); \
-              __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__); \
-              PyGILState_Release(__pyx_gilstate_save); \
-          } else { \
-              __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__); \
-          }
-#else
-  #define __Pyx_RefNannySetupContext(name, acquire_gil) \
-          __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__)
-#endif
-  #define __Pyx_RefNannyFinishContext() \
-          __Pyx_RefNanny->FinishContext(&__pyx_refnanny)
+  #define __Pyx_RefNannySetupContext(name)           __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__)
+  #define __Pyx_RefNannyFinishContext()           __Pyx_RefNanny->FinishContext(&__pyx_refnanny)
   #define __Pyx_INCREF(r)  __Pyx_RefNanny->INCREF(__pyx_refnanny, (PyObject *)(r), __LINE__)
   #define __Pyx_DECREF(r)  __Pyx_RefNanny->DECREF(__pyx_refnanny, (PyObject *)(r), __LINE__)
   #define __Pyx_GOTREF(r)  __Pyx_RefNanny->GOTREF(__pyx_refnanny, (PyObject *)(r), __LINE__)
@@ -712,7 +631,7 @@ typedef npy_cdouble __pyx_t_5numpy_complex_t;
   #define __Pyx_XGIVEREF(r) do { if((r) != NULL) {__Pyx_GIVEREF(r);}} while(0)
 #else
   #define __Pyx_RefNannyDeclarations
-  #define __Pyx_RefNannySetupContext(name, acquire_gil)
+  #define __Pyx_RefNannySetupContext(name)
   #define __Pyx_RefNannyFinishContext()
   #define __Pyx_INCREF(r) Py_INCREF(r)
   #define __Pyx_DECREF(r) Py_DECREF(r)
@@ -723,25 +642,43 @@ typedef npy_cdouble __pyx_t_5numpy_complex_t;
   #define __Pyx_XGOTREF(r)
   #define __Pyx_XGIVEREF(r)
 #endif /* CYTHON_REFNANNY */
-#define __Pyx_CLEAR(r)    do { PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);} while(0)
-#define __Pyx_XCLEAR(r)   do { if((r) != NULL) {PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);}} while(0)
 
 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/
 
 static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact,
     Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found); /*proto*/
 
-static void __Pyx_RaiseDoubleKeywordsError(const char* func_name, PyObject* kw_name); /*proto*/
+static void __Pyx_RaiseDoubleKeywordsError(
+    const char* func_name, PyObject* kw_name); /*proto*/
 
-static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[], \
-    PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args, \
-    const char* function_name); /*proto*/
+static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[],     PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args,     const char* function_name); /*proto*/
 
 static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
     const char *name, int exact); /*proto*/
 
-static CYTHON_INLINE int  __Pyx_GetBufferAndValidate(Py_buffer* buf, PyObject* obj,
-    __Pyx_TypeInfo* dtype, int flags, int nd, int cast, __Pyx_BufFmt_StackElem* stack);
+/* Run-time type information about structs used with buffers */
+struct __Pyx_StructField_;
+
+typedef struct {
+  const char* name; /* for error messages only */
+  struct __Pyx_StructField_* fields;
+  size_t size;     /* sizeof(type) */
+  char typegroup; /* _R_eal, _C_omplex, Signed _I_nt, _U_nsigned int, _S_truct, _P_ointer, _O_bject */
+} __Pyx_TypeInfo;
+
+typedef struct __Pyx_StructField_ {
+  __Pyx_TypeInfo* type;
+  const char* name;
+  size_t offset;
+} __Pyx_StructField;
+
+typedef struct {
+  __Pyx_StructField* field;
+  size_t parent_offset;
+} __Pyx_BufFmt_StackElem;
+
+
+static CYTHON_INLINE int  __Pyx_GetBufferAndValidate(Py_buffer* buf, PyObject* obj, __Pyx_TypeInfo* dtype, int flags, int nd, int cast, __Pyx_BufFmt_StackElem* stack);
 static CYTHON_INLINE void __Pyx_SafeReleaseBuffer(Py_buffer* info);
 
 static CYTHON_INLINE long __Pyx_mod_long(long, long); /* proto */
@@ -754,10 +691,10 @@ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject
 static CYTHON_INLINE long __Pyx_div_long(long, long); /* proto */
 
 static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); /*proto*/
-
 #define __Pyx_BufPtrStrided1d(type, buf, i0, s0) (type)((char*)buf + i0 * s0)
 #define __Pyx_BufPtrStrided2d(type, buf, i0, s0, i1, s1) (type)((char*)buf + i0 * s0 + i1 * s1)
 #define __Pyx_BufPtrStrided3d(type, buf, i0, s0, i1, s1, i2, s2) (type)((char*)buf + i0 * s0 + i1 * s1 + i2 * s2)
+
 static CYTHON_INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index);
 
 static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(Py_ssize_t expected);
@@ -765,30 +702,16 @@ static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(Py_ssize_t expected);
 static CYTHON_INLINE void __Pyx_RaiseNoneNotIterableError(void);
 
 static void __Pyx_UnpackTupleError(PyObject *, Py_ssize_t index); /*proto*/
-
-typedef struct {
-  Py_ssize_t shape, strides, suboffsets;
-} __Pyx_Buf_DimInfo;
-typedef struct {
-  size_t refcount;
-  Py_buffer pybuffer;
-} __Pyx_Buffer;
-typedef struct {
-  __Pyx_Buffer *rcbuffer;
-  char *data;
-  __Pyx_Buf_DimInfo diminfo[8];
-} __Pyx_LocalBuf_ND;
-
 #if PY_MAJOR_VERSION < 3
-    static int __Pyx_GetBuffer(PyObject *obj, Py_buffer *view, int flags);
-    static void __Pyx_ReleaseBuffer(Py_buffer *view);
+static int __Pyx_GetBuffer(PyObject *obj, Py_buffer *view, int flags);
+static void __Pyx_ReleaseBuffer(Py_buffer *view);
 #else
-    #define __Pyx_GetBuffer PyObject_GetBuffer
-    #define __Pyx_ReleaseBuffer PyBuffer_Release
+#define __Pyx_GetBuffer PyObject_GetBuffer
+#define __Pyx_ReleaseBuffer PyBuffer_Release
 #endif
 
-static Py_ssize_t __Pyx_zeros[] = {0, 0, 0, 0, 0, 0, 0, 0};
-static Py_ssize_t __Pyx_minusones[] = {-1, -1, -1, -1, -1, -1, -1, -1};
+Py_ssize_t __Pyx_zeros[] = {0, 0, 0};
+Py_ssize_t __Pyx_minusones[] = {-1, -1, -1};
 
 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, long level); /*proto*/
 
@@ -804,6 +727,7 @@ static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, long level);
     #define __Pyx_CREAL(z) ((z).real)
     #define __Pyx_CIMAG(z) ((z).imag)
 #endif
+
 #if defined(_WIN32) && defined(__cplusplus) && CYTHON_CCOMPLEX
     #define __Pyx_SET_CREAL(z,x) ((z).real(x))
     #define __Pyx_SET_CIMAG(z,y) ((z).imag(y))
@@ -924,38 +848,15 @@ static CYTHON_INLINE signed PY_LONG_LONG __Pyx_PyInt_AsSignedLongLong(PyObject *
 
 static int __Pyx_check_binary_version(void);
 
-#if !defined(__Pyx_PyIdentifier_FromString)
-#if PY_MAJOR_VERSION < 3
-  #define __Pyx_PyIdentifier_FromString(s) PyString_FromString(s)
-#else
-  #define __Pyx_PyIdentifier_FromString(s) PyUnicode_FromString(s)
-#endif
-#endif
-
 static PyTypeObject *__Pyx_ImportType(const char *module_name, const char *class_name, size_t size, int strict);  /*proto*/
 
 static PyObject *__Pyx_ImportModule(const char *name); /*proto*/
 
-typedef struct {
-    int code_line;
-    PyCodeObject* code_object;
-} __Pyx_CodeObjectCacheEntry;
-struct __Pyx_CodeObjectCache {
-    int count;
-    int max_count;
-    __Pyx_CodeObjectCacheEntry* entries;
-};
-static struct __Pyx_CodeObjectCache __pyx_code_cache = {0,0,NULL};
-static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line);
-static PyCodeObject *__pyx_find_code_object(int code_line);
-static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object);
-
-static void __Pyx_AddTraceback(const char *funcname, int c_line,
-                               int py_line, const char *filename); /*proto*/
+static void __Pyx_AddTraceback(const char *funcname, int __pyx_clineno,
+                               int __pyx_lineno, const char *__pyx_filename); /*proto*/
 
 static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); /*proto*/
 
-
 /* Module declarations from 'cpython.buffer' */
 
 /* Module declarations from 'cpython.ref' */
@@ -974,12 +875,21 @@ static PyTypeObject *__pyx_ptype_5numpy_flatiter = 0;
 static PyTypeObject *__pyx_ptype_5numpy_broadcast = 0;
 static PyTypeObject *__pyx_ptype_5numpy_ndarray = 0;
 static PyTypeObject *__pyx_ptype_5numpy_ufunc = 0;
+static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew1(PyObject *); /*proto*/
+static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew2(PyObject *, PyObject *); /*proto*/
+static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew3(PyObject *, PyObject *, PyObject *); /*proto*/
+static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew4(PyObject *, PyObject *, PyObject *, PyObject *); /*proto*/
+static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew5(PyObject *, PyObject *, PyObject *, PyObject *, PyObject *); /*proto*/
 static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *, char *, char *, int *); /*proto*/
+static CYTHON_INLINE void __pyx_f_5numpy_set_array_base(PyArrayObject *, PyObject *); /*proto*/
+static CYTHON_INLINE PyObject *__pyx_f_5numpy_get_array_base(PyArrayObject *); /*proto*/
+
+/* Module declarations from 'cython.cython.view' */
 
 /* Module declarations from 'cython' */
 
 /* Module declarations from 'astropy.nddata.convolution.boundary_none' */
-static __Pyx_TypeInfo __Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t = { "DTYPE_t", NULL, sizeof(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t), { 0 }, 0, 'R', 0, 0 };
+static __Pyx_TypeInfo __Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t = { "DTYPE_t", NULL, sizeof(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t), 'R' };
 #define __Pyx_MODULE_NAME "astropy.nddata.convolution.boundary_none"
 int __pyx_module_is_main_astropy__nddata__convolution__boundary_none = 0;
 
@@ -987,11 +897,6 @@ int __pyx_module_is_main_astropy__nddata__convolution__boundary_none = 0;
 static PyObject *__pyx_builtin_ValueError;
 static PyObject *__pyx_builtin_range;
 static PyObject *__pyx_builtin_RuntimeError;
-static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_convolve1d_boundary_none(CYTHON_UNUSED PyObject *__pyx_self, PyArrayObject *__pyx_v_f, PyArrayObject *__pyx_v_g); /* proto */
-static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_2convolve2d_boundary_none(CYTHON_UNUSED PyObject *__pyx_self, PyArrayObject *__pyx_v_f, PyArrayObject *__pyx_v_g); /* proto */
-static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_4convolve3d_boundary_none(CYTHON_UNUSED PyObject *__pyx_self, PyArrayObject *__pyx_v_f, PyArrayObject *__pyx_v_g); /* proto */
-static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags); /* proto */
-static void __pyx_pf_5numpy_7ndarray_2__releasebuffer__(PyArrayObject *__pyx_v_self, Py_buffer *__pyx_v_info); /* proto */
 static char __pyx_k_1[] = "Convolution kernel must have odd dimensions";
 static char __pyx_k_5[] = "ndarray is not C contiguous";
 static char __pyx_k_7[] = "ndarray is not Fortran contiguous";
@@ -999,11 +904,10 @@ static char __pyx_k_9[] = "Non-native byte order not supported";
 static char __pyx_k_11[] = "unknown dtype code in numpy.pxd (%d)";
 static char __pyx_k_12[] = "Format string allocated too short, see comment in numpy.pxd";
 static char __pyx_k_15[] = "Format string allocated too short.";
-static char __pyx_k_19[] = "convolve1d_boundary_none";
-static char __pyx_k_20[] = "/Users/erik/src/astropy/astropy/nddata/convolution/boundary_none.pyx";
-static char __pyx_k_21[] = "astropy.nddata.convolution.boundary_none";
-static char __pyx_k_24[] = "convolve2d_boundary_none";
-static char __pyx_k_27[] = "convolve3d_boundary_none";
+static char __pyx_k_17[] = "astropy.nddata.convolution.boundary_none";
+static char __pyx_k_18[] = "convolve1d_boundary_none";
+static char __pyx_k_19[] = "convolve2d_boundary_none";
+static char __pyx_k_20[] = "convolve3d_boundary_none";
 static char __pyx_k__B[] = "B";
 static char __pyx_k__H[] = "H";
 static char __pyx_k__I[] = "I";
@@ -1016,41 +920,15 @@ static char __pyx_k__f[] = "f";
 static char __pyx_k__g[] = "g";
 static char __pyx_k__h[] = "h";
 static char __pyx_k__i[] = "i";
-static char __pyx_k__j[] = "j";
-static char __pyx_k__k[] = "k";
 static char __pyx_k__l[] = "l";
 static char __pyx_k__q[] = "q";
 static char __pyx_k__Zd[] = "Zd";
 static char __pyx_k__Zf[] = "Zf";
 static char __pyx_k__Zg[] = "Zg";
-static char __pyx_k__ii[] = "ii";
-static char __pyx_k__jj[] = "jj";
-static char __pyx_k__kk[] = "kk";
 static char __pyx_k__np[] = "np";
-static char __pyx_k__nx[] = "nx";
-static char __pyx_k__ny[] = "ny";
-static char __pyx_k__nz[] = "nz";
-static char __pyx_k__bot[] = "bot";
-static char __pyx_k__ker[] = "ker";
-static char __pyx_k__nkx[] = "nkx";
-static char __pyx_k__nky[] = "nky";
-static char __pyx_k__nkz[] = "nkz";
-static char __pyx_k__top[] = "top";
-static char __pyx_k__val[] = "val";
-static char __pyx_k__wkx[] = "wkx";
-static char __pyx_k__wky[] = "wky";
-static char __pyx_k__wkz[] = "wkz";
-static char __pyx_k__conv[] = "conv";
 static char __pyx_k__DTYPE[] = "DTYPE";
 static char __pyx_k__dtype[] = "dtype";
-static char __pyx_k__fixed[] = "fixed";
 static char __pyx_k__float[] = "float";
-static char __pyx_k__iimax[] = "iimax";
-static char __pyx_k__iimin[] = "iimin";
-static char __pyx_k__jjmax[] = "jjmax";
-static char __pyx_k__jjmin[] = "jjmin";
-static char __pyx_k__kkmax[] = "kkmax";
-static char __pyx_k__kkmin[] = "kkmin";
 static char __pyx_k__numpy[] = "numpy";
 static char __pyx_k__range[] = "range";
 static char __pyx_k__zeros[] = "zeros";
@@ -1062,11 +940,10 @@ static PyObject *__pyx_kp_s_1;
 static PyObject *__pyx_kp_u_11;
 static PyObject *__pyx_kp_u_12;
 static PyObject *__pyx_kp_u_15;
+static PyObject *__pyx_n_s_17;
+static PyObject *__pyx_n_s_18;
 static PyObject *__pyx_n_s_19;
-static PyObject *__pyx_kp_s_20;
-static PyObject *__pyx_n_s_21;
-static PyObject *__pyx_n_s_24;
-static PyObject *__pyx_n_s_27;
+static PyObject *__pyx_n_s_20;
 static PyObject *__pyx_kp_u_5;
 static PyObject *__pyx_kp_u_7;
 static PyObject *__pyx_kp_u_9;
@@ -1075,40 +952,13 @@ static PyObject *__pyx_n_s__RuntimeError;
 static PyObject *__pyx_n_s__ValueError;
 static PyObject *__pyx_n_s____main__;
 static PyObject *__pyx_n_s____test__;
-static PyObject *__pyx_n_s__bot;
-static PyObject *__pyx_n_s__conv;
 static PyObject *__pyx_n_s__dtype;
 static PyObject *__pyx_n_s__f;
-static PyObject *__pyx_n_s__fixed;
 static PyObject *__pyx_n_s__float;
 static PyObject *__pyx_n_s__g;
-static PyObject *__pyx_n_s__i;
-static PyObject *__pyx_n_s__ii;
-static PyObject *__pyx_n_s__iimax;
-static PyObject *__pyx_n_s__iimin;
-static PyObject *__pyx_n_s__j;
-static PyObject *__pyx_n_s__jj;
-static PyObject *__pyx_n_s__jjmax;
-static PyObject *__pyx_n_s__jjmin;
-static PyObject *__pyx_n_s__k;
-static PyObject *__pyx_n_s__ker;
-static PyObject *__pyx_n_s__kk;
-static PyObject *__pyx_n_s__kkmax;
-static PyObject *__pyx_n_s__kkmin;
-static PyObject *__pyx_n_s__nkx;
-static PyObject *__pyx_n_s__nky;
-static PyObject *__pyx_n_s__nkz;
 static PyObject *__pyx_n_s__np;
 static PyObject *__pyx_n_s__numpy;
-static PyObject *__pyx_n_s__nx;
-static PyObject *__pyx_n_s__ny;
-static PyObject *__pyx_n_s__nz;
 static PyObject *__pyx_n_s__range;
-static PyObject *__pyx_n_s__top;
-static PyObject *__pyx_n_s__val;
-static PyObject *__pyx_n_s__wkx;
-static PyObject *__pyx_n_s__wky;
-static PyObject *__pyx_n_s__wkz;
 static PyObject *__pyx_n_s__zeros;
 static PyObject *__pyx_int_15;
 static PyObject *__pyx_k_tuple_2;
@@ -1120,78 +970,6 @@ static PyObject *__pyx_k_tuple_10;
 static PyObject *__pyx_k_tuple_13;
 static PyObject *__pyx_k_tuple_14;
 static PyObject *__pyx_k_tuple_16;
-static PyObject *__pyx_k_tuple_17;
-static PyObject *__pyx_k_tuple_22;
-static PyObject *__pyx_k_tuple_25;
-static PyObject *__pyx_k_codeobj_18;
-static PyObject *__pyx_k_codeobj_23;
-static PyObject *__pyx_k_codeobj_26;
-
-/* Python wrapper */
-static PyObject *__pyx_pw_7astropy_6nddata_11convolution_13boundary_none_1convolve1d_boundary_none(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static PyMethodDef __pyx_mdef_7astropy_6nddata_11convolution_13boundary_none_1convolve1d_boundary_none = {__Pyx_NAMESTR("convolve1d_boundary_none"), (PyCFunction)__pyx_pw_7astropy_6nddata_11convolution_13boundary_none_1convolve1d_boundary_none, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(0)};
-static PyObject *__pyx_pw_7astropy_6nddata_11convolution_13boundary_none_1convolve1d_boundary_none(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
-  PyArrayObject *__pyx_v_f = 0;
-  PyArrayObject *__pyx_v_g = 0;
-  static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__f,&__pyx_n_s__g,0};
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("convolve1d_boundary_none (wrapper)", 0);
-  __pyx_self = __pyx_self;
-  {
-    PyObject* values[2] = {0,0};
-    if (unlikely(__pyx_kwds)) {
-      Py_ssize_t kw_args;
-      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
-      switch (pos_args) {
-        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
-        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
-        case  0: break;
-        default: goto __pyx_L5_argtuple_error;
-      }
-      kw_args = PyDict_Size(__pyx_kwds);
-      switch (pos_args) {
-        case  0:
-        values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__f);
-        if (likely(values[0])) kw_args--;
-        else goto __pyx_L5_argtuple_error;
-        case  1:
-        values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__g);
-        if (likely(values[1])) kw_args--;
-        else {
-          __Pyx_RaiseArgtupleInvalid("convolve1d_boundary_none", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-        }
-      }
-      if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "convolve1d_boundary_none") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-      }
-    } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
-      goto __pyx_L5_argtuple_error;
-    } else {
-      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
-      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
-    }
-    __pyx_v_f = ((PyArrayObject *)values[0]);
-    __pyx_v_g = ((PyArrayObject *)values[1]);
-  }
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("convolve1d_boundary_none", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-  __pyx_L3_error:;
-  __Pyx_AddTraceback("astropy.nddata.convolution.boundary_none.convolve1d_boundary_none", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return NULL;
-  __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_f), __pyx_ptype_5numpy_ndarray, 1, "f", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_g), __pyx_ptype_5numpy_ndarray, 1, "g", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 16; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_r = __pyx_pf_7astropy_6nddata_11convolution_13boundary_none_convolve1d_boundary_none(__pyx_self, __pyx_v_f, __pyx_v_g);
-  goto __pyx_L0;
-  __pyx_L1_error:;
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
 
 /* "astropy/nddata/convolution/boundary_none.pyx":15
  * 
@@ -1201,7 +979,11 @@ static PyObject *__pyx_pw_7astropy_6nddata_11convolution_13boundary_none_1convol
  * 
  */
 
-static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_convolve1d_boundary_none(CYTHON_UNUSED PyObject *__pyx_self, PyArrayObject *__pyx_v_f, PyArrayObject *__pyx_v_g) {
+static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_convolve1d_boundary_none(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static PyMethodDef __pyx_mdef_7astropy_6nddata_11convolution_13boundary_none_convolve1d_boundary_none = {__Pyx_NAMESTR("convolve1d_boundary_none"), (PyCFunction)__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_convolve1d_boundary_none, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(0)};
+static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_convolve1d_boundary_none(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyArrayObject *__pyx_v_f = 0;
+  PyArrayObject *__pyx_v_g = 0;
   int __pyx_v_nx;
   int __pyx_v_nkx;
   int __pyx_v_wkx;
@@ -1213,14 +995,18 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_convolv
   __pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t __pyx_v_bot;
   __pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t __pyx_v_ker;
   __pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t __pyx_v_val;
-  __Pyx_LocalBuf_ND __pyx_pybuffernd_conv;
-  __Pyx_Buffer __pyx_pybuffer_conv;
-  __Pyx_LocalBuf_ND __pyx_pybuffernd_f;
-  __Pyx_Buffer __pyx_pybuffer_f;
-  __Pyx_LocalBuf_ND __pyx_pybuffernd_fixed;
-  __Pyx_Buffer __pyx_pybuffer_fixed;
-  __Pyx_LocalBuf_ND __pyx_pybuffernd_g;
-  __Pyx_Buffer __pyx_pybuffer_g;
+  Py_buffer __pyx_bstruct_conv;
+  Py_ssize_t __pyx_bstride_0_conv = 0;
+  Py_ssize_t __pyx_bshape_0_conv = 0;
+  Py_buffer __pyx_bstruct_g;
+  Py_ssize_t __pyx_bstride_0_g = 0;
+  Py_ssize_t __pyx_bshape_0_g = 0;
+  Py_buffer __pyx_bstruct_f;
+  Py_ssize_t __pyx_bstride_0_f = 0;
+  Py_ssize_t __pyx_bshape_0_f = 0;
+  Py_buffer __pyx_bstruct_fixed;
+  Py_ssize_t __pyx_bstride_0_fixed = 0;
+  Py_ssize_t __pyx_bshape_0_fixed = 0;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   int __pyx_t_1;
@@ -1254,33 +1040,70 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_convolv
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("convolve1d_boundary_none", 0);
-  __pyx_pybuffer_fixed.pybuffer.buf = NULL;
-  __pyx_pybuffer_fixed.refcount = 0;
-  __pyx_pybuffernd_fixed.data = NULL;
-  __pyx_pybuffernd_fixed.rcbuffer = &__pyx_pybuffer_fixed;
-  __pyx_pybuffer_conv.pybuffer.buf = NULL;
-  __pyx_pybuffer_conv.refcount = 0;
-  __pyx_pybuffernd_conv.data = NULL;
-  __pyx_pybuffernd_conv.rcbuffer = &__pyx_pybuffer_conv;
-  __pyx_pybuffer_f.pybuffer.buf = NULL;
-  __pyx_pybuffer_f.refcount = 0;
-  __pyx_pybuffernd_f.data = NULL;
-  __pyx_pybuffernd_f.rcbuffer = &__pyx_pybuffer_f;
-  __pyx_pybuffer_g.pybuffer.buf = NULL;
-  __pyx_pybuffer_g.refcount = 0;
-  __pyx_pybuffernd_g.data = NULL;
-  __pyx_pybuffernd_g.rcbuffer = &__pyx_pybuffer_g;
+  static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__f,&__pyx_n_s__g,0};
+  __Pyx_RefNannySetupContext("convolve1d_boundary_none");
+  __pyx_self = __pyx_self;
+  {
+    PyObject* values[2] = {0,0};
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  0:
+        values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__f);
+        if (likely(values[0])) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+        case  1:
+        values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__g);
+        if (likely(values[1])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("convolve1d_boundary_none", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "convolve1d_boundary_none") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+    } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
+      goto __pyx_L5_argtuple_error;
+    } else {
+      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+    }
+    __pyx_v_f = ((PyArrayObject *)values[0]);
+    __pyx_v_g = ((PyArrayObject *)values[1]);
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("convolve1d_boundary_none", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("astropy.nddata.convolution.boundary_none.convolve1d_boundary_none", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_bstruct_fixed.buf = NULL;
+  __pyx_bstruct_conv.buf = NULL;
+  __pyx_bstruct_f.buf = NULL;
+  __pyx_bstruct_g.buf = NULL;
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_f), __pyx_ptype_5numpy_ndarray, 1, "f", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_g), __pyx_ptype_5numpy_ndarray, 1, "g", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 16; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_f.rcbuffer->pybuffer, (PyObject*)__pyx_v_f, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_f, (PyObject*)__pyx_v_f, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
-  __pyx_pybuffernd_f.diminfo[0].strides = __pyx_pybuffernd_f.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_f.diminfo[0].shape = __pyx_pybuffernd_f.rcbuffer->pybuffer.shape[0];
+  __pyx_bstride_0_f = __pyx_bstruct_f.strides[0];
+  __pyx_bshape_0_f = __pyx_bstruct_f.shape[0];
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_g.rcbuffer->pybuffer, (PyObject*)__pyx_v_g, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_g, (PyObject*)__pyx_v_g, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
-  __pyx_pybuffernd_g.diminfo[0].strides = __pyx_pybuffernd_g.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_g.diminfo[0].shape = __pyx_pybuffernd_g.rcbuffer->pybuffer.shape[0];
+  __pyx_bstride_0_g = __pyx_bstruct_g.strides[0];
+  __pyx_bshape_0_g = __pyx_bstruct_g.shape[0];
 
   /* "astropy/nddata/convolution/boundary_none.pyx":18
  *                              np.ndarray[DTYPE_t, ndim=1] g):
@@ -1304,9 +1127,9 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_convolv
     __Pyx_Raise(__pyx_t_2, 0, 0, 0);
     __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
     {__pyx_filename = __pyx_f[0]; __pyx_lineno = 19; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    goto __pyx_L3;
+    goto __pyx_L6;
   }
-  __pyx_L3:;
+  __pyx_L6:;
 
   /* "astropy/nddata/convolution/boundary_none.pyx":21
  *         raise ValueError("Convolution kernel must have odd dimensions")
@@ -1389,12 +1212,12 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_convolv
   __pyx_t_2 = PyInt_FromLong(__pyx_v_nx); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 29; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
   __pyx_t_4 = PyList_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 29; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_4);
+  __Pyx_GOTREF(((PyObject *)__pyx_t_4));
   PyList_SET_ITEM(__pyx_t_4, 0, __pyx_t_2);
   __Pyx_GIVEREF(__pyx_t_2);
   __pyx_t_2 = 0;
   __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 29; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_GOTREF(((PyObject *)__pyx_t_2));
   PyTuple_SET_ITEM(__pyx_t_2, 0, ((PyObject *)__pyx_t_4));
   __Pyx_GIVEREF(((PyObject *)__pyx_t_4));
   __pyx_t_4 = 0;
@@ -1404,7 +1227,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_convolv
   __Pyx_GOTREF(__pyx_t_7);
   if (PyDict_SetItem(__pyx_t_4, ((PyObject *)__pyx_n_s__dtype), __pyx_t_7) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 29; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-  __pyx_t_7 = PyObject_Call(__pyx_t_3, ((PyObject *)__pyx_t_2), ((PyObject *)__pyx_t_4)); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 29; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_7 = PyEval_CallObjectWithKeywords(__pyx_t_3, ((PyObject *)__pyx_t_2), ((PyObject *)__pyx_t_4)); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 29; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_7);
   __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
   __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
@@ -1413,10 +1236,11 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_convolv
   __pyx_t_8 = ((PyArrayObject *)__pyx_t_7);
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_fixed.rcbuffer->pybuffer, (PyObject*)__pyx_t_8, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 1, 0, __pyx_stack) == -1)) {
-      __pyx_v_fixed = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf = NULL;
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_fixed, (PyObject*)__pyx_t_8, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 1, 0, __pyx_stack) == -1)) {
+      __pyx_v_fixed = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_fixed.buf = NULL;
       {__pyx_filename = __pyx_f[0]; __pyx_lineno = 29; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    } else {__pyx_pybuffernd_fixed.diminfo[0].strides = __pyx_pybuffernd_fixed.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_fixed.diminfo[0].shape = __pyx_pybuffernd_fixed.rcbuffer->pybuffer.shape[0];
+    } else {__pyx_bstride_0_fixed = __pyx_bstruct_fixed.strides[0];
+      __pyx_bshape_0_fixed = __pyx_bstruct_fixed.shape[0];
     }
   }
   __pyx_t_8 = 0;
@@ -1438,12 +1262,12 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_convolv
   __pyx_t_7 = PyInt_FromLong(__pyx_v_nx); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 30; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_7);
   __pyx_t_2 = PyList_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 30; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_GOTREF(((PyObject *)__pyx_t_2));
   PyList_SET_ITEM(__pyx_t_2, 0, __pyx_t_7);
   __Pyx_GIVEREF(__pyx_t_7);
   __pyx_t_7 = 0;
   __pyx_t_7 = PyTuple_New(1); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 30; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_7);
+  __Pyx_GOTREF(((PyObject *)__pyx_t_7));
   PyTuple_SET_ITEM(__pyx_t_7, 0, ((PyObject *)__pyx_t_2));
   __Pyx_GIVEREF(((PyObject *)__pyx_t_2));
   __pyx_t_2 = 0;
@@ -1453,7 +1277,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_convolv
   __Pyx_GOTREF(__pyx_t_3);
   if (PyDict_SetItem(__pyx_t_2, ((PyObject *)__pyx_n_s__dtype), __pyx_t_3) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 30; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  __pyx_t_3 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_t_7), ((PyObject *)__pyx_t_2)); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 30; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_3 = PyEval_CallObjectWithKeywords(__pyx_t_4, ((PyObject *)__pyx_t_7), ((PyObject *)__pyx_t_2)); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 30; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_3);
   __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
   __Pyx_DECREF(((PyObject *)__pyx_t_7)); __pyx_t_7 = 0;
@@ -1462,10 +1286,11 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_convolv
   __pyx_t_9 = ((PyArrayObject *)__pyx_t_3);
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_conv.rcbuffer->pybuffer, (PyObject*)__pyx_t_9, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 1, 0, __pyx_stack) == -1)) {
-      __pyx_v_conv = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_conv.rcbuffer->pybuffer.buf = NULL;
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_conv, (PyObject*)__pyx_t_9, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 1, 0, __pyx_stack) == -1)) {
+      __pyx_v_conv = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_conv.buf = NULL;
       {__pyx_filename = __pyx_f[0]; __pyx_lineno = 30; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    } else {__pyx_pybuffernd_conv.diminfo[0].strides = __pyx_pybuffernd_conv.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_conv.diminfo[0].shape = __pyx_pybuffernd_conv.rcbuffer->pybuffer.shape[0];
+    } else {__pyx_bstride_0_conv = __pyx_bstruct_conv.strides[0];
+      __pyx_bshape_0_conv = __pyx_bstruct_conv.shape[0];
     }
   }
   __pyx_t_9 = 0;
@@ -1491,7 +1316,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_convolv
  *             bot = 0.
  */
     __pyx_t_12 = __pyx_v_i;
-    __pyx_t_6 = npy_isnan((*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_pybuffernd_f.rcbuffer->pybuffer.buf, __pyx_t_12, __pyx_pybuffernd_f.diminfo[0].strides)));
+    __pyx_t_6 = npy_isnan((*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_bstruct_f.buf, __pyx_t_12, __pyx_bstride_0_f)));
     if (__pyx_t_6) {
 
       /* "astropy/nddata/convolution/boundary_none.pyx":42
@@ -1531,7 +1356,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_convolv
  *                     ker = g[<unsigned int>(wkx + ii - i)]
  */
         __pyx_t_15 = __pyx_v_ii;
-        __pyx_v_val = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_pybuffernd_f.rcbuffer->pybuffer.buf, __pyx_t_15, __pyx_pybuffernd_f.diminfo[0].strides));
+        __pyx_v_val = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_bstruct_f.buf, __pyx_t_15, __pyx_bstride_0_f));
 
         /* "astropy/nddata/convolution/boundary_none.pyx":46
  *             for ii in range(i - wkx, i + wkx + 1):
@@ -1551,7 +1376,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_convolv
  *                     bot += ker
  */
           __pyx_t_16 = ((unsigned int)((__pyx_v_wkx + __pyx_v_ii) - __pyx_v_i));
-          __pyx_v_ker = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_pybuffernd_g.rcbuffer->pybuffer.buf, __pyx_t_16, __pyx_pybuffernd_g.diminfo[0].strides));
+          __pyx_v_ker = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_bstruct_g.buf, __pyx_t_16, __pyx_bstride_0_g));
 
           /* "astropy/nddata/convolution/boundary_none.pyx":48
  *                 if not npy_isnan(val):
@@ -1570,9 +1395,9 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_convolv
  *                 fixed[i] = top / bot
  */
           __pyx_v_bot = (__pyx_v_bot + __pyx_v_ker);
-          goto __pyx_L9;
+          goto __pyx_L12;
         }
-        __pyx_L9:;
+        __pyx_L12:;
       }
 
       /* "astropy/nddata/convolution/boundary_none.pyx":50
@@ -1597,8 +1422,8 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_convolv
           {__pyx_filename = __pyx_f[0]; __pyx_lineno = 51; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         }
         __pyx_t_14 = __pyx_v_i;
-        *__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_14, __pyx_pybuffernd_fixed.diminfo[0].strides) = (__pyx_v_top / __pyx_v_bot);
-        goto __pyx_L10;
+        *__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_14, __pyx_bstride_0_fixed) = (__pyx_v_top / __pyx_v_bot);
+        goto __pyx_L13;
       }
       /*else*/ {
 
@@ -1611,10 +1436,10 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_convolv
  */
         __pyx_t_17 = __pyx_v_i;
         __pyx_t_18 = __pyx_v_i;
-        *__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_18, __pyx_pybuffernd_fixed.diminfo[0].strides) = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_pybuffernd_f.rcbuffer->pybuffer.buf, __pyx_t_17, __pyx_pybuffernd_f.diminfo[0].strides));
+        *__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_18, __pyx_bstride_0_fixed) = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_bstruct_f.buf, __pyx_t_17, __pyx_bstride_0_f));
       }
-      __pyx_L10:;
-      goto __pyx_L6;
+      __pyx_L13:;
+      goto __pyx_L9;
     }
     /*else*/ {
 
@@ -1627,9 +1452,9 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_convolv
  */
       __pyx_t_19 = __pyx_v_i;
       __pyx_t_20 = __pyx_v_i;
-      *__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_20, __pyx_pybuffernd_fixed.diminfo[0].strides) = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_pybuffernd_f.rcbuffer->pybuffer.buf, __pyx_t_19, __pyx_pybuffernd_f.diminfo[0].strides));
+      *__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_20, __pyx_bstride_0_fixed) = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_bstruct_f.buf, __pyx_t_19, __pyx_bstride_0_f));
     }
-    __pyx_L6:;
+    __pyx_L9:;
   }
 
   /* "astropy/nddata/convolution/boundary_none.pyx":58
@@ -1651,7 +1476,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_convolv
  *             bot = 0.
  */
     __pyx_t_21 = __pyx_v_i;
-    __pyx_t_6 = (!npy_isnan((*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_21, __pyx_pybuffernd_fixed.diminfo[0].strides))));
+    __pyx_t_6 = (!npy_isnan((*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_21, __pyx_bstride_0_fixed))));
     if (__pyx_t_6) {
 
       /* "astropy/nddata/convolution/boundary_none.pyx":60
@@ -1691,7 +1516,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_convolv
  *                 if not npy_isnan(val):
  */
         __pyx_t_23 = __pyx_v_ii;
-        __pyx_v_val = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_23, __pyx_pybuffernd_fixed.diminfo[0].strides));
+        __pyx_v_val = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_23, __pyx_bstride_0_fixed));
 
         /* "astropy/nddata/convolution/boundary_none.pyx":64
  *             for ii in range(i - wkx, i + wkx + 1):
@@ -1701,7 +1526,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_convolv
  *                     top += val * ker
  */
         __pyx_t_24 = ((unsigned int)((__pyx_v_wkx + __pyx_v_ii) - __pyx_v_i));
-        __pyx_v_ker = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_pybuffernd_g.rcbuffer->pybuffer.buf, __pyx_t_24, __pyx_pybuffernd_g.diminfo[0].strides));
+        __pyx_v_ker = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_bstruct_g.buf, __pyx_t_24, __pyx_bstride_0_g));
 
         /* "astropy/nddata/convolution/boundary_none.pyx":65
  *                 val = fixed[ii]
@@ -1730,9 +1555,9 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_convolv
  *                 conv[i] = top / bot
  */
           __pyx_v_bot = (__pyx_v_bot + __pyx_v_ker);
-          goto __pyx_L16;
+          goto __pyx_L19;
         }
-        __pyx_L16:;
+        __pyx_L19:;
       }
 
       /* "astropy/nddata/convolution/boundary_none.pyx":68
@@ -1757,8 +1582,8 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_convolv
           {__pyx_filename = __pyx_f[0]; __pyx_lineno = 69; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         }
         __pyx_t_22 = __pyx_v_i;
-        *__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_pybuffernd_conv.rcbuffer->pybuffer.buf, __pyx_t_22, __pyx_pybuffernd_conv.diminfo[0].strides) = (__pyx_v_top / __pyx_v_bot);
-        goto __pyx_L17;
+        *__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_bstruct_conv.buf, __pyx_t_22, __pyx_bstride_0_conv) = (__pyx_v_top / __pyx_v_bot);
+        goto __pyx_L20;
       }
       /*else*/ {
 
@@ -1771,10 +1596,10 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_convolv
  */
         __pyx_t_25 = __pyx_v_i;
         __pyx_t_26 = __pyx_v_i;
-        *__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_pybuffernd_conv.rcbuffer->pybuffer.buf, __pyx_t_26, __pyx_pybuffernd_conv.diminfo[0].strides) = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_25, __pyx_pybuffernd_fixed.diminfo[0].strides));
+        *__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_bstruct_conv.buf, __pyx_t_26, __pyx_bstride_0_conv) = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_25, __pyx_bstride_0_fixed));
       }
-      __pyx_L17:;
-      goto __pyx_L13;
+      __pyx_L20:;
+      goto __pyx_L16;
     }
     /*else*/ {
 
@@ -1787,9 +1612,9 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_convolv
  */
       __pyx_t_27 = __pyx_v_i;
       __pyx_t_28 = __pyx_v_i;
-      *__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_pybuffernd_conv.rcbuffer->pybuffer.buf, __pyx_t_28, __pyx_pybuffernd_conv.diminfo[0].strides) = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_27, __pyx_pybuffernd_fixed.diminfo[0].strides));
+      *__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_bstruct_conv.buf, __pyx_t_28, __pyx_bstride_0_conv) = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_27, __pyx_bstride_0_fixed));
     }
-    __pyx_L13:;
+    __pyx_L16:;
   }
 
   /* "astropy/nddata/convolution/boundary_none.pyx":75
@@ -1813,19 +1638,19 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_convolv
   __Pyx_XDECREF(__pyx_t_7);
   { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;
     __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);
-    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_conv.rcbuffer->pybuffer);
-    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_f.rcbuffer->pybuffer);
-    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_fixed.rcbuffer->pybuffer);
-    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_g.rcbuffer->pybuffer);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_conv);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_g);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_f);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_fixed);
   __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
   __Pyx_AddTraceback("astropy.nddata.convolution.boundary_none.convolve1d_boundary_none", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   goto __pyx_L2;
   __pyx_L0:;
-  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_conv.rcbuffer->pybuffer);
-  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_f.rcbuffer->pybuffer);
-  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_fixed.rcbuffer->pybuffer);
-  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_g.rcbuffer->pybuffer);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_conv);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_g);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_f);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_fixed);
   __pyx_L2:;
   __Pyx_XDECREF((PyObject *)__pyx_v_fixed);
   __Pyx_XDECREF((PyObject *)__pyx_v_conv);
@@ -1834,72 +1659,6 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_convolv
   return __pyx_r;
 }
 
-/* Python wrapper */
-static PyObject *__pyx_pw_7astropy_6nddata_11convolution_13boundary_none_3convolve2d_boundary_none(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static PyMethodDef __pyx_mdef_7astropy_6nddata_11convolution_13boundary_none_3convolve2d_boundary_none = {__Pyx_NAMESTR("convolve2d_boundary_none"), (PyCFunction)__pyx_pw_7astropy_6nddata_11convolution_13boundary_none_3convolve2d_boundary_none, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(0)};
-static PyObject *__pyx_pw_7astropy_6nddata_11convolution_13boundary_none_3convolve2d_boundary_none(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
-  PyArrayObject *__pyx_v_f = 0;
-  PyArrayObject *__pyx_v_g = 0;
-  static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__f,&__pyx_n_s__g,0};
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("convolve2d_boundary_none (wrapper)", 0);
-  __pyx_self = __pyx_self;
-  {
-    PyObject* values[2] = {0,0};
-    if (unlikely(__pyx_kwds)) {
-      Py_ssize_t kw_args;
-      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
-      switch (pos_args) {
-        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
-        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
-        case  0: break;
-        default: goto __pyx_L5_argtuple_error;
-      }
-      kw_args = PyDict_Size(__pyx_kwds);
-      switch (pos_args) {
-        case  0:
-        values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__f);
-        if (likely(values[0])) kw_args--;
-        else goto __pyx_L5_argtuple_error;
-        case  1:
-        values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__g);
-        if (likely(values[1])) kw_args--;
-        else {
-          __Pyx_RaiseArgtupleInvalid("convolve2d_boundary_none", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 79; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-        }
-      }
-      if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "convolve2d_boundary_none") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 79; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-      }
-    } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
-      goto __pyx_L5_argtuple_error;
-    } else {
-      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
-      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
-    }
-    __pyx_v_f = ((PyArrayObject *)values[0]);
-    __pyx_v_g = ((PyArrayObject *)values[1]);
-  }
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("convolve2d_boundary_none", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 79; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-  __pyx_L3_error:;
-  __Pyx_AddTraceback("astropy.nddata.convolution.boundary_none.convolve2d_boundary_none", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return NULL;
-  __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_f), __pyx_ptype_5numpy_ndarray, 1, "f", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 79; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_g), __pyx_ptype_5numpy_ndarray, 1, "g", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 80; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_r = __pyx_pf_7astropy_6nddata_11convolution_13boundary_none_2convolve2d_boundary_none(__pyx_self, __pyx_v_f, __pyx_v_g);
-  goto __pyx_L0;
-  __pyx_L1_error:;
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
 /* "astropy/nddata/convolution/boundary_none.pyx":79
  * 
  * @cython.boundscheck(False)  # turn off bounds-checking for entire function
@@ -1908,7 +1667,11 @@ static PyObject *__pyx_pw_7astropy_6nddata_11convolution_13boundary_none_3convol
  * 
  */
 
-static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_2convolve2d_boundary_none(CYTHON_UNUSED PyObject *__pyx_self, PyArrayObject *__pyx_v_f, PyArrayObject *__pyx_v_g) {
+static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_1convolve2d_boundary_none(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static PyMethodDef __pyx_mdef_7astropy_6nddata_11convolution_13boundary_none_1convolve2d_boundary_none = {__Pyx_NAMESTR("convolve2d_boundary_none"), (PyCFunction)__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_1convolve2d_boundary_none, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(0)};
+static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_1convolve2d_boundary_none(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyArrayObject *__pyx_v_f = 0;
+  PyArrayObject *__pyx_v_g = 0;
   int __pyx_v_nx;
   int __pyx_v_ny;
   int __pyx_v_nkx;
@@ -1925,14 +1688,26 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_2convol
   __pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t __pyx_v_bot;
   __pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t __pyx_v_ker;
   __pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t __pyx_v_val;
-  __Pyx_LocalBuf_ND __pyx_pybuffernd_conv;
-  __Pyx_Buffer __pyx_pybuffer_conv;
-  __Pyx_LocalBuf_ND __pyx_pybuffernd_f;
-  __Pyx_Buffer __pyx_pybuffer_f;
-  __Pyx_LocalBuf_ND __pyx_pybuffernd_fixed;
-  __Pyx_Buffer __pyx_pybuffer_fixed;
-  __Pyx_LocalBuf_ND __pyx_pybuffernd_g;
-  __Pyx_Buffer __pyx_pybuffer_g;
+  Py_buffer __pyx_bstruct_conv;
+  Py_ssize_t __pyx_bstride_0_conv = 0;
+  Py_ssize_t __pyx_bstride_1_conv = 0;
+  Py_ssize_t __pyx_bshape_0_conv = 0;
+  Py_ssize_t __pyx_bshape_1_conv = 0;
+  Py_buffer __pyx_bstruct_g;
+  Py_ssize_t __pyx_bstride_0_g = 0;
+  Py_ssize_t __pyx_bstride_1_g = 0;
+  Py_ssize_t __pyx_bshape_0_g = 0;
+  Py_ssize_t __pyx_bshape_1_g = 0;
+  Py_buffer __pyx_bstruct_f;
+  Py_ssize_t __pyx_bstride_0_f = 0;
+  Py_ssize_t __pyx_bstride_1_f = 0;
+  Py_ssize_t __pyx_bshape_0_f = 0;
+  Py_ssize_t __pyx_bshape_1_f = 0;
+  Py_buffer __pyx_bstruct_fixed;
+  Py_ssize_t __pyx_bstride_0_fixed = 0;
+  Py_ssize_t __pyx_bstride_1_fixed = 0;
+  Py_ssize_t __pyx_bshape_0_fixed = 0;
+  Py_ssize_t __pyx_bshape_1_fixed = 0;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   int __pyx_t_1;
@@ -1985,33 +1760,70 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_2convol
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("convolve2d_boundary_none", 0);
-  __pyx_pybuffer_fixed.pybuffer.buf = NULL;
-  __pyx_pybuffer_fixed.refcount = 0;
-  __pyx_pybuffernd_fixed.data = NULL;
-  __pyx_pybuffernd_fixed.rcbuffer = &__pyx_pybuffer_fixed;
-  __pyx_pybuffer_conv.pybuffer.buf = NULL;
-  __pyx_pybuffer_conv.refcount = 0;
-  __pyx_pybuffernd_conv.data = NULL;
-  __pyx_pybuffernd_conv.rcbuffer = &__pyx_pybuffer_conv;
-  __pyx_pybuffer_f.pybuffer.buf = NULL;
-  __pyx_pybuffer_f.refcount = 0;
-  __pyx_pybuffernd_f.data = NULL;
-  __pyx_pybuffernd_f.rcbuffer = &__pyx_pybuffer_f;
-  __pyx_pybuffer_g.pybuffer.buf = NULL;
-  __pyx_pybuffer_g.refcount = 0;
-  __pyx_pybuffernd_g.data = NULL;
-  __pyx_pybuffernd_g.rcbuffer = &__pyx_pybuffer_g;
+  static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__f,&__pyx_n_s__g,0};
+  __Pyx_RefNannySetupContext("convolve2d_boundary_none");
+  __pyx_self = __pyx_self;
+  {
+    PyObject* values[2] = {0,0};
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  0:
+        values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__f);
+        if (likely(values[0])) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+        case  1:
+        values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__g);
+        if (likely(values[1])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("convolve2d_boundary_none", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 79; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "convolve2d_boundary_none") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 79; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+    } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
+      goto __pyx_L5_argtuple_error;
+    } else {
+      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+    }
+    __pyx_v_f = ((PyArrayObject *)values[0]);
+    __pyx_v_g = ((PyArrayObject *)values[1]);
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("convolve2d_boundary_none", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 79; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("astropy.nddata.convolution.boundary_none.convolve2d_boundary_none", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_bstruct_fixed.buf = NULL;
+  __pyx_bstruct_conv.buf = NULL;
+  __pyx_bstruct_f.buf = NULL;
+  __pyx_bstruct_g.buf = NULL;
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_f), __pyx_ptype_5numpy_ndarray, 1, "f", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 79; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_g), __pyx_ptype_5numpy_ndarray, 1, "g", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 80; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_f.rcbuffer->pybuffer, (PyObject*)__pyx_v_f, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 79; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_f, (PyObject*)__pyx_v_f, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 79; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
-  __pyx_pybuffernd_f.diminfo[0].strides = __pyx_pybuffernd_f.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_f.diminfo[0].shape = __pyx_pybuffernd_f.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_f.diminfo[1].strides = __pyx_pybuffernd_f.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_f.diminfo[1].shape = __pyx_pybuffernd_f.rcbuffer->pybuffer.shape[1];
+  __pyx_bstride_0_f = __pyx_bstruct_f.strides[0]; __pyx_bstride_1_f = __pyx_bstruct_f.strides[1];
+  __pyx_bshape_0_f = __pyx_bstruct_f.shape[0]; __pyx_bshape_1_f = __pyx_bstruct_f.shape[1];
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_g.rcbuffer->pybuffer, (PyObject*)__pyx_v_g, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 79; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_g, (PyObject*)__pyx_v_g, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 79; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
-  __pyx_pybuffernd_g.diminfo[0].strides = __pyx_pybuffernd_g.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_g.diminfo[0].shape = __pyx_pybuffernd_g.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_g.diminfo[1].strides = __pyx_pybuffernd_g.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_g.diminfo[1].shape = __pyx_pybuffernd_g.rcbuffer->pybuffer.shape[1];
+  __pyx_bstride_0_g = __pyx_bstruct_g.strides[0]; __pyx_bstride_1_g = __pyx_bstruct_g.strides[1];
+  __pyx_bshape_0_g = __pyx_bstruct_g.shape[0]; __pyx_bshape_1_g = __pyx_bstruct_g.shape[1];
 
   /* "astropy/nddata/convolution/boundary_none.pyx":82
  *                              np.ndarray[DTYPE_t, ndim=2] g):
@@ -2041,9 +1853,9 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_2convol
     __Pyx_Raise(__pyx_t_4, 0, 0, 0);
     __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
     {__pyx_filename = __pyx_f[0]; __pyx_lineno = 83; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    goto __pyx_L3;
+    goto __pyx_L6;
   }
-  __pyx_L3:;
+  __pyx_L6:;
 
   /* "astropy/nddata/convolution/boundary_none.pyx":85
  *         raise ValueError("Convolution kernel must have odd dimensions")
@@ -2155,7 +1967,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_2convol
   __pyx_t_6 = PyInt_FromLong(__pyx_v_ny); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 96; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_6);
   __pyx_t_7 = PyList_New(2); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 96; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_7);
+  __Pyx_GOTREF(((PyObject *)__pyx_t_7));
   PyList_SET_ITEM(__pyx_t_7, 0, __pyx_t_4);
   __Pyx_GIVEREF(__pyx_t_4);
   PyList_SET_ITEM(__pyx_t_7, 1, __pyx_t_6);
@@ -2163,7 +1975,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_2convol
   __pyx_t_4 = 0;
   __pyx_t_6 = 0;
   __pyx_t_6 = PyTuple_New(1); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 96; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_6);
+  __Pyx_GOTREF(((PyObject *)__pyx_t_6));
   PyTuple_SET_ITEM(__pyx_t_6, 0, ((PyObject *)__pyx_t_7));
   __Pyx_GIVEREF(((PyObject *)__pyx_t_7));
   __pyx_t_7 = 0;
@@ -2173,7 +1985,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_2convol
   __Pyx_GOTREF(__pyx_t_4);
   if (PyDict_SetItem(__pyx_t_7, ((PyObject *)__pyx_n_s__dtype), __pyx_t_4) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 96; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  __pyx_t_4 = PyObject_Call(__pyx_t_5, ((PyObject *)__pyx_t_6), ((PyObject *)__pyx_t_7)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 96; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_4 = PyEval_CallObjectWithKeywords(__pyx_t_5, ((PyObject *)__pyx_t_6), ((PyObject *)__pyx_t_7)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 96; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_4);
   __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
   __Pyx_DECREF(((PyObject *)__pyx_t_6)); __pyx_t_6 = 0;
@@ -2182,10 +1994,11 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_2convol
   __pyx_t_8 = ((PyArrayObject *)__pyx_t_4);
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_fixed.rcbuffer->pybuffer, (PyObject*)__pyx_t_8, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack) == -1)) {
-      __pyx_v_fixed = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf = NULL;
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_fixed, (PyObject*)__pyx_t_8, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack) == -1)) {
+      __pyx_v_fixed = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_fixed.buf = NULL;
       {__pyx_filename = __pyx_f[0]; __pyx_lineno = 96; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    } else {__pyx_pybuffernd_fixed.diminfo[0].strides = __pyx_pybuffernd_fixed.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_fixed.diminfo[0].shape = __pyx_pybuffernd_fixed.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_fixed.diminfo[1].strides = __pyx_pybuffernd_fixed.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_fixed.diminfo[1].shape = __pyx_pybuffernd_fixed.rcbuffer->pybuffer.shape[1];
+    } else {__pyx_bstride_0_fixed = __pyx_bstruct_fixed.strides[0]; __pyx_bstride_1_fixed = __pyx_bstruct_fixed.strides[1];
+      __pyx_bshape_0_fixed = __pyx_bstruct_fixed.shape[0]; __pyx_bshape_1_fixed = __pyx_bstruct_fixed.shape[1];
     }
   }
   __pyx_t_8 = 0;
@@ -2209,7 +2022,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_2convol
   __pyx_t_6 = PyInt_FromLong(__pyx_v_ny); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 97; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_6);
   __pyx_t_5 = PyList_New(2); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 97; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_5);
+  __Pyx_GOTREF(((PyObject *)__pyx_t_5));
   PyList_SET_ITEM(__pyx_t_5, 0, __pyx_t_4);
   __Pyx_GIVEREF(__pyx_t_4);
   PyList_SET_ITEM(__pyx_t_5, 1, __pyx_t_6);
@@ -2217,7 +2030,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_2convol
   __pyx_t_4 = 0;
   __pyx_t_6 = 0;
   __pyx_t_6 = PyTuple_New(1); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 97; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_6);
+  __Pyx_GOTREF(((PyObject *)__pyx_t_6));
   PyTuple_SET_ITEM(__pyx_t_6, 0, ((PyObject *)__pyx_t_5));
   __Pyx_GIVEREF(((PyObject *)__pyx_t_5));
   __pyx_t_5 = 0;
@@ -2227,7 +2040,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_2convol
   __Pyx_GOTREF(__pyx_t_4);
   if (PyDict_SetItem(__pyx_t_5, ((PyObject *)__pyx_n_s__dtype), __pyx_t_4) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 97; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  __pyx_t_4 = PyObject_Call(__pyx_t_7, ((PyObject *)__pyx_t_6), ((PyObject *)__pyx_t_5)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 97; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_4 = PyEval_CallObjectWithKeywords(__pyx_t_7, ((PyObject *)__pyx_t_6), ((PyObject *)__pyx_t_5)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 97; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_4);
   __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
   __Pyx_DECREF(((PyObject *)__pyx_t_6)); __pyx_t_6 = 0;
@@ -2236,10 +2049,11 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_2convol
   __pyx_t_9 = ((PyArrayObject *)__pyx_t_4);
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_conv.rcbuffer->pybuffer, (PyObject*)__pyx_t_9, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack) == -1)) {
-      __pyx_v_conv = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_conv.rcbuffer->pybuffer.buf = NULL;
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_conv, (PyObject*)__pyx_t_9, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack) == -1)) {
+      __pyx_v_conv = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_conv.buf = NULL;
       {__pyx_filename = __pyx_f[0]; __pyx_lineno = 97; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    } else {__pyx_pybuffernd_conv.diminfo[0].strides = __pyx_pybuffernd_conv.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_conv.diminfo[0].shape = __pyx_pybuffernd_conv.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_conv.diminfo[1].strides = __pyx_pybuffernd_conv.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_conv.diminfo[1].shape = __pyx_pybuffernd_conv.rcbuffer->pybuffer.shape[1];
+    } else {__pyx_bstride_0_conv = __pyx_bstruct_conv.strides[0]; __pyx_bstride_1_conv = __pyx_bstruct_conv.strides[1];
+      __pyx_bshape_0_conv = __pyx_bstruct_conv.shape[0]; __pyx_bshape_1_conv = __pyx_bstruct_conv.shape[1];
     }
   }
   __pyx_t_9 = 0;
@@ -2277,7 +2091,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_2convol
  */
       __pyx_t_14 = __pyx_v_i;
       __pyx_t_15 = __pyx_v_j;
-      __pyx_t_2 = npy_isnan((*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_pybuffernd_f.rcbuffer->pybuffer.buf, __pyx_t_14, __pyx_pybuffernd_f.diminfo[0].strides, __pyx_t_15, __pyx_pybuffernd_f.diminfo[1].strides)));
+      __pyx_t_2 = npy_isnan((*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_bstruct_f.buf, __pyx_t_14, __pyx_bstride_0_f, __pyx_t_15, __pyx_bstride_1_f)));
       if (__pyx_t_2) {
 
         /* "astropy/nddata/convolution/boundary_none.pyx":110
@@ -2329,7 +2143,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_2convol
  */
             __pyx_t_20 = __pyx_v_ii;
             __pyx_t_21 = __pyx_v_jj;
-            __pyx_v_val = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_pybuffernd_f.rcbuffer->pybuffer.buf, __pyx_t_20, __pyx_pybuffernd_f.diminfo[0].strides, __pyx_t_21, __pyx_pybuffernd_f.diminfo[1].strides));
+            __pyx_v_val = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_bstruct_f.buf, __pyx_t_20, __pyx_bstride_0_f, __pyx_t_21, __pyx_bstride_1_f));
 
             /* "astropy/nddata/convolution/boundary_none.pyx":115
  *                     for jj in range(j - wky, j + wky + 1):
@@ -2350,7 +2164,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_2convol
  */
               __pyx_t_22 = ((unsigned int)((__pyx_v_wkx + __pyx_v_ii) - __pyx_v_i));
               __pyx_t_23 = ((unsigned int)((__pyx_v_wky + __pyx_v_jj) - __pyx_v_j));
-              __pyx_v_ker = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_pybuffernd_g.rcbuffer->pybuffer.buf, __pyx_t_22, __pyx_pybuffernd_g.diminfo[0].strides, __pyx_t_23, __pyx_pybuffernd_g.diminfo[1].strides));
+              __pyx_v_ker = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_bstruct_g.buf, __pyx_t_22, __pyx_bstride_0_g, __pyx_t_23, __pyx_bstride_1_g));
 
               /* "astropy/nddata/convolution/boundary_none.pyx":118
  *                             ker = g[<unsigned int>(wkx + ii - i),
@@ -2369,9 +2183,9 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_2convol
  *                     fixed[i, j] = top / bot
  */
               __pyx_v_bot = (__pyx_v_bot + __pyx_v_ker);
-              goto __pyx_L13;
+              goto __pyx_L16;
             }
-            __pyx_L13:;
+            __pyx_L16:;
           }
         }
 
@@ -2398,8 +2212,8 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_2convol
           }
           __pyx_t_17 = __pyx_v_i;
           __pyx_t_19 = __pyx_v_j;
-          *__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_17, __pyx_pybuffernd_fixed.diminfo[0].strides, __pyx_t_19, __pyx_pybuffernd_fixed.diminfo[1].strides) = (__pyx_v_top / __pyx_v_bot);
-          goto __pyx_L14;
+          *__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_17, __pyx_bstride_0_fixed, __pyx_t_19, __pyx_bstride_1_fixed) = (__pyx_v_top / __pyx_v_bot);
+          goto __pyx_L17;
         }
         /*else*/ {
 
@@ -2414,10 +2228,10 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_2convol
           __pyx_t_25 = __pyx_v_j;
           __pyx_t_26 = __pyx_v_i;
           __pyx_t_27 = __pyx_v_j;
-          *__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_26, __pyx_pybuffernd_fixed.diminfo[0].strides, __pyx_t_27, __pyx_pybuffernd_fixed.diminfo[1].strides) = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_pybuffernd_f.rcbuffer->pybuffer.buf, __pyx_t_24, __pyx_pybuffernd_f.diminfo[0].strides, __pyx_t_25, __pyx_pybuffernd_f.diminfo[1].strides));
+          *__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_26, __pyx_bstride_0_fixed, __pyx_t_27, __pyx_bstride_1_fixed) = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_bstruct_f.buf, __pyx_t_24, __pyx_bstride_0_f, __pyx_t_25, __pyx_bstride_1_f));
         }
-        __pyx_L14:;
-        goto __pyx_L8;
+        __pyx_L17:;
+        goto __pyx_L11;
       }
       /*else*/ {
 
@@ -2432,9 +2246,9 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_2convol
         __pyx_t_29 = __pyx_v_j;
         __pyx_t_30 = __pyx_v_i;
         __pyx_t_31 = __pyx_v_j;
-        *__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_30, __pyx_pybuffernd_fixed.diminfo[0].strides, __pyx_t_31, __pyx_pybuffernd_fixed.diminfo[1].strides) = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_pybuffernd_f.rcbuffer->pybuffer.buf, __pyx_t_28, __pyx_pybuffernd_f.diminfo[0].strides, __pyx_t_29, __pyx_pybuffernd_f.diminfo[1].strides));
+        *__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_30, __pyx_bstride_0_fixed, __pyx_t_31, __pyx_bstride_1_fixed) = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_bstruct_f.buf, __pyx_t_28, __pyx_bstride_0_f, __pyx_t_29, __pyx_bstride_1_f));
       }
-      __pyx_L8:;
+      __pyx_L11:;
     }
   }
 
@@ -2469,7 +2283,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_2convol
  */
       __pyx_t_32 = __pyx_v_i;
       __pyx_t_33 = __pyx_v_j;
-      __pyx_t_2 = (!npy_isnan((*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_32, __pyx_pybuffernd_fixed.diminfo[0].strides, __pyx_t_33, __pyx_pybuffernd_fixed.diminfo[1].strides))));
+      __pyx_t_2 = (!npy_isnan((*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_32, __pyx_bstride_0_fixed, __pyx_t_33, __pyx_bstride_1_fixed))));
       if (__pyx_t_2) {
 
         /* "astropy/nddata/convolution/boundary_none.pyx":131
@@ -2521,7 +2335,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_2convol
  */
             __pyx_t_36 = __pyx_v_ii;
             __pyx_t_37 = __pyx_v_jj;
-            __pyx_v_val = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_36, __pyx_pybuffernd_fixed.diminfo[0].strides, __pyx_t_37, __pyx_pybuffernd_fixed.diminfo[1].strides));
+            __pyx_v_val = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_36, __pyx_bstride_0_fixed, __pyx_t_37, __pyx_bstride_1_fixed));
 
             /* "astropy/nddata/convolution/boundary_none.pyx":137
  *                         val = fixed[ii, jj]
@@ -2532,7 +2346,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_2convol
  */
             __pyx_t_38 = ((unsigned int)((__pyx_v_wkx + __pyx_v_ii) - __pyx_v_i));
             __pyx_t_39 = ((unsigned int)((__pyx_v_wky + __pyx_v_jj) - __pyx_v_j));
-            __pyx_v_ker = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_pybuffernd_g.rcbuffer->pybuffer.buf, __pyx_t_38, __pyx_pybuffernd_g.diminfo[0].strides, __pyx_t_39, __pyx_pybuffernd_g.diminfo[1].strides));
+            __pyx_v_ker = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_bstruct_g.buf, __pyx_t_38, __pyx_bstride_0_g, __pyx_t_39, __pyx_bstride_1_g));
 
             /* "astropy/nddata/convolution/boundary_none.pyx":138
  *                         ker = g[<unsigned int>(wkx + ii - i),
@@ -2561,9 +2375,9 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_2convol
  *                     conv[i, j] = top / bot
  */
               __pyx_v_bot = (__pyx_v_bot + __pyx_v_ker);
-              goto __pyx_L24;
+              goto __pyx_L27;
             }
-            __pyx_L24:;
+            __pyx_L27:;
           }
         }
 
@@ -2590,8 +2404,8 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_2convol
           }
           __pyx_t_34 = __pyx_v_i;
           __pyx_t_35 = __pyx_v_j;
-          *__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_pybuffernd_conv.rcbuffer->pybuffer.buf, __pyx_t_34, __pyx_pybuffernd_conv.diminfo[0].strides, __pyx_t_35, __pyx_pybuffernd_conv.diminfo[1].strides) = (__pyx_v_top / __pyx_v_bot);
-          goto __pyx_L25;
+          *__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_bstruct_conv.buf, __pyx_t_34, __pyx_bstride_0_conv, __pyx_t_35, __pyx_bstride_1_conv) = (__pyx_v_top / __pyx_v_bot);
+          goto __pyx_L28;
         }
         /*else*/ {
 
@@ -2606,10 +2420,10 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_2convol
           __pyx_t_41 = __pyx_v_j;
           __pyx_t_42 = __pyx_v_i;
           __pyx_t_43 = __pyx_v_j;
-          *__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_pybuffernd_conv.rcbuffer->pybuffer.buf, __pyx_t_42, __pyx_pybuffernd_conv.diminfo[0].strides, __pyx_t_43, __pyx_pybuffernd_conv.diminfo[1].strides) = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_40, __pyx_pybuffernd_fixed.diminfo[0].strides, __pyx_t_41, __pyx_pybuffernd_fixed.diminfo[1].strides));
+          *__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_bstruct_conv.buf, __pyx_t_42, __pyx_bstride_0_conv, __pyx_t_43, __pyx_bstride_1_conv) = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_40, __pyx_bstride_0_fixed, __pyx_t_41, __pyx_bstride_1_fixed));
         }
-        __pyx_L25:;
-        goto __pyx_L19;
+        __pyx_L28:;
+        goto __pyx_L22;
       }
       /*else*/ {
 
@@ -2624,9 +2438,9 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_2convol
         __pyx_t_45 = __pyx_v_j;
         __pyx_t_46 = __pyx_v_i;
         __pyx_t_47 = __pyx_v_j;
-        *__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_pybuffernd_conv.rcbuffer->pybuffer.buf, __pyx_t_46, __pyx_pybuffernd_conv.diminfo[0].strides, __pyx_t_47, __pyx_pybuffernd_conv.diminfo[1].strides) = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_44, __pyx_pybuffernd_fixed.diminfo[0].strides, __pyx_t_45, __pyx_pybuffernd_fixed.diminfo[1].strides));
+        *__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_bstruct_conv.buf, __pyx_t_46, __pyx_bstride_0_conv, __pyx_t_47, __pyx_bstride_1_conv) = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_44, __pyx_bstride_0_fixed, __pyx_t_45, __pyx_bstride_1_fixed));
       }
-      __pyx_L19:;
+      __pyx_L22:;
     }
   }
 
@@ -2651,19 +2465,19 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_2convol
   __Pyx_XDECREF(__pyx_t_7);
   { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;
     __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);
-    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_conv.rcbuffer->pybuffer);
-    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_f.rcbuffer->pybuffer);
-    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_fixed.rcbuffer->pybuffer);
-    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_g.rcbuffer->pybuffer);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_conv);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_g);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_f);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_fixed);
   __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
   __Pyx_AddTraceback("astropy.nddata.convolution.boundary_none.convolve2d_boundary_none", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   goto __pyx_L2;
   __pyx_L0:;
-  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_conv.rcbuffer->pybuffer);
-  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_f.rcbuffer->pybuffer);
-  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_fixed.rcbuffer->pybuffer);
-  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_g.rcbuffer->pybuffer);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_conv);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_g);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_f);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_fixed);
   __pyx_L2:;
   __Pyx_XDECREF((PyObject *)__pyx_v_fixed);
   __Pyx_XDECREF((PyObject *)__pyx_v_conv);
@@ -2672,72 +2486,6 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_2convol
   return __pyx_r;
 }
 
-/* Python wrapper */
-static PyObject *__pyx_pw_7astropy_6nddata_11convolution_13boundary_none_5convolve3d_boundary_none(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static PyMethodDef __pyx_mdef_7astropy_6nddata_11convolution_13boundary_none_5convolve3d_boundary_none = {__Pyx_NAMESTR("convolve3d_boundary_none"), (PyCFunction)__pyx_pw_7astropy_6nddata_11convolution_13boundary_none_5convolve3d_boundary_none, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(0)};
-static PyObject *__pyx_pw_7astropy_6nddata_11convolution_13boundary_none_5convolve3d_boundary_none(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
-  PyArrayObject *__pyx_v_f = 0;
-  PyArrayObject *__pyx_v_g = 0;
-  static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__f,&__pyx_n_s__g,0};
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("convolve3d_boundary_none (wrapper)", 0);
-  __pyx_self = __pyx_self;
-  {
-    PyObject* values[2] = {0,0};
-    if (unlikely(__pyx_kwds)) {
-      Py_ssize_t kw_args;
-      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
-      switch (pos_args) {
-        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
-        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
-        case  0: break;
-        default: goto __pyx_L5_argtuple_error;
-      }
-      kw_args = PyDict_Size(__pyx_kwds);
-      switch (pos_args) {
-        case  0:
-        values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__f);
-        if (likely(values[0])) kw_args--;
-        else goto __pyx_L5_argtuple_error;
-        case  1:
-        values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__g);
-        if (likely(values[1])) kw_args--;
-        else {
-          __Pyx_RaiseArgtupleInvalid("convolve3d_boundary_none", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 152; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-        }
-      }
-      if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "convolve3d_boundary_none") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 152; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-      }
-    } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
-      goto __pyx_L5_argtuple_error;
-    } else {
-      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
-      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
-    }
-    __pyx_v_f = ((PyArrayObject *)values[0]);
-    __pyx_v_g = ((PyArrayObject *)values[1]);
-  }
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("convolve3d_boundary_none", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 152; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-  __pyx_L3_error:;
-  __Pyx_AddTraceback("astropy.nddata.convolution.boundary_none.convolve3d_boundary_none", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return NULL;
-  __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_f), __pyx_ptype_5numpy_ndarray, 1, "f", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 152; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_g), __pyx_ptype_5numpy_ndarray, 1, "g", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 153; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_r = __pyx_pf_7astropy_6nddata_11convolution_13boundary_none_4convolve3d_boundary_none(__pyx_self, __pyx_v_f, __pyx_v_g);
-  goto __pyx_L0;
-  __pyx_L1_error:;
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
 /* "astropy/nddata/convolution/boundary_none.pyx":152
  * 
  * @cython.boundscheck(False)  # turn off bounds-checking for entire function
@@ -2746,7 +2494,11 @@ static PyObject *__pyx_pw_7astropy_6nddata_11convolution_13boundary_none_5convol
  * 
  */
 
-static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_4convolve3d_boundary_none(CYTHON_UNUSED PyObject *__pyx_self, PyArrayObject *__pyx_v_f, PyArrayObject *__pyx_v_g) {
+static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_2convolve3d_boundary_none(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static PyMethodDef __pyx_mdef_7astropy_6nddata_11convolution_13boundary_none_2convolve3d_boundary_none = {__Pyx_NAMESTR("convolve3d_boundary_none"), (PyCFunction)__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_2convolve3d_boundary_none, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(0)};
+static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_2convolve3d_boundary_none(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyArrayObject *__pyx_v_f = 0;
+  PyArrayObject *__pyx_v_g = 0;
   int __pyx_v_nx;
   int __pyx_v_ny;
   int __pyx_v_nz;
@@ -2768,14 +2520,34 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_4convol
   __pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t __pyx_v_bot;
   __pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t __pyx_v_ker;
   __pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t __pyx_v_val;
-  __Pyx_LocalBuf_ND __pyx_pybuffernd_conv;
-  __Pyx_Buffer __pyx_pybuffer_conv;
-  __Pyx_LocalBuf_ND __pyx_pybuffernd_f;
-  __Pyx_Buffer __pyx_pybuffer_f;
-  __Pyx_LocalBuf_ND __pyx_pybuffernd_fixed;
-  __Pyx_Buffer __pyx_pybuffer_fixed;
-  __Pyx_LocalBuf_ND __pyx_pybuffernd_g;
-  __Pyx_Buffer __pyx_pybuffer_g;
+  Py_buffer __pyx_bstruct_conv;
+  Py_ssize_t __pyx_bstride_0_conv = 0;
+  Py_ssize_t __pyx_bstride_1_conv = 0;
+  Py_ssize_t __pyx_bstride_2_conv = 0;
+  Py_ssize_t __pyx_bshape_0_conv = 0;
+  Py_ssize_t __pyx_bshape_1_conv = 0;
+  Py_ssize_t __pyx_bshape_2_conv = 0;
+  Py_buffer __pyx_bstruct_g;
+  Py_ssize_t __pyx_bstride_0_g = 0;
+  Py_ssize_t __pyx_bstride_1_g = 0;
+  Py_ssize_t __pyx_bstride_2_g = 0;
+  Py_ssize_t __pyx_bshape_0_g = 0;
+  Py_ssize_t __pyx_bshape_1_g = 0;
+  Py_ssize_t __pyx_bshape_2_g = 0;
+  Py_buffer __pyx_bstruct_f;
+  Py_ssize_t __pyx_bstride_0_f = 0;
+  Py_ssize_t __pyx_bstride_1_f = 0;
+  Py_ssize_t __pyx_bstride_2_f = 0;
+  Py_ssize_t __pyx_bshape_0_f = 0;
+  Py_ssize_t __pyx_bshape_1_f = 0;
+  Py_ssize_t __pyx_bshape_2_f = 0;
+  Py_buffer __pyx_bstruct_fixed;
+  Py_ssize_t __pyx_bstride_0_fixed = 0;
+  Py_ssize_t __pyx_bstride_1_fixed = 0;
+  Py_ssize_t __pyx_bstride_2_fixed = 0;
+  Py_ssize_t __pyx_bshape_0_fixed = 0;
+  Py_ssize_t __pyx_bshape_1_fixed = 0;
+  Py_ssize_t __pyx_bshape_2_fixed = 0;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   int __pyx_t_1;
@@ -2849,33 +2621,70 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_4convol
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("convolve3d_boundary_none", 0);
-  __pyx_pybuffer_fixed.pybuffer.buf = NULL;
-  __pyx_pybuffer_fixed.refcount = 0;
-  __pyx_pybuffernd_fixed.data = NULL;
-  __pyx_pybuffernd_fixed.rcbuffer = &__pyx_pybuffer_fixed;
-  __pyx_pybuffer_conv.pybuffer.buf = NULL;
-  __pyx_pybuffer_conv.refcount = 0;
-  __pyx_pybuffernd_conv.data = NULL;
-  __pyx_pybuffernd_conv.rcbuffer = &__pyx_pybuffer_conv;
-  __pyx_pybuffer_f.pybuffer.buf = NULL;
-  __pyx_pybuffer_f.refcount = 0;
-  __pyx_pybuffernd_f.data = NULL;
-  __pyx_pybuffernd_f.rcbuffer = &__pyx_pybuffer_f;
-  __pyx_pybuffer_g.pybuffer.buf = NULL;
-  __pyx_pybuffer_g.refcount = 0;
-  __pyx_pybuffernd_g.data = NULL;
-  __pyx_pybuffernd_g.rcbuffer = &__pyx_pybuffer_g;
+  static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__f,&__pyx_n_s__g,0};
+  __Pyx_RefNannySetupContext("convolve3d_boundary_none");
+  __pyx_self = __pyx_self;
+  {
+    PyObject* values[2] = {0,0};
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  0:
+        values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__f);
+        if (likely(values[0])) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+        case  1:
+        values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__g);
+        if (likely(values[1])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("convolve3d_boundary_none", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 152; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "convolve3d_boundary_none") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 152; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+    } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
+      goto __pyx_L5_argtuple_error;
+    } else {
+      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+    }
+    __pyx_v_f = ((PyArrayObject *)values[0]);
+    __pyx_v_g = ((PyArrayObject *)values[1]);
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("convolve3d_boundary_none", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 152; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("astropy.nddata.convolution.boundary_none.convolve3d_boundary_none", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_bstruct_fixed.buf = NULL;
+  __pyx_bstruct_conv.buf = NULL;
+  __pyx_bstruct_f.buf = NULL;
+  __pyx_bstruct_g.buf = NULL;
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_f), __pyx_ptype_5numpy_ndarray, 1, "f", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 152; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_g), __pyx_ptype_5numpy_ndarray, 1, "g", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 153; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_f.rcbuffer->pybuffer, (PyObject*)__pyx_v_f, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES, 3, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 152; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_f, (PyObject*)__pyx_v_f, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES, 3, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 152; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
-  __pyx_pybuffernd_f.diminfo[0].strides = __pyx_pybuffernd_f.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_f.diminfo[0].shape = __pyx_pybuffernd_f.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_f.diminfo[1].strides = __pyx_pybuffernd_f.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_f.diminfo[1].shape = __pyx_pybuffernd_f.rcbuffer->pybuffer.shape[1]; __pyx_pybuffernd_f.diminfo[2].strides = __pyx_pybuffernd_f.rcbuffer->pybuffer.strides[2]; __pyx_pybuffernd_f.diminfo[2].shape = __pyx_pybuffernd_f.rcbuffer->pybuffer.shape[2];
+  __pyx_bstride_0_f = __pyx_bstruct_f.strides[0]; __pyx_bstride_1_f = __pyx_bstruct_f.strides[1]; __pyx_bstride_2_f = __pyx_bstruct_f.strides[2];
+  __pyx_bshape_0_f = __pyx_bstruct_f.shape[0]; __pyx_bshape_1_f = __pyx_bstruct_f.shape[1]; __pyx_bshape_2_f = __pyx_bstruct_f.shape[2];
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_g.rcbuffer->pybuffer, (PyObject*)__pyx_v_g, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES, 3, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 152; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_g, (PyObject*)__pyx_v_g, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES, 3, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 152; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
-  __pyx_pybuffernd_g.diminfo[0].strides = __pyx_pybuffernd_g.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_g.diminfo[0].shape = __pyx_pybuffernd_g.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_g.diminfo[1].strides = __pyx_pybuffernd_g.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_g.diminfo[1].shape = __pyx_pybuffernd_g.rcbuffer->pybuffer.shape[1]; __pyx_pybuffernd_g.diminfo[2].strides = __pyx_pybuffernd_g.rcbuffer->pybuffer.strides[2]; __pyx_pybuffernd_g.diminfo[2].shape = __pyx_pybuffernd_g.rcbuffer->pybuffer.shape[2];
+  __pyx_bstride_0_g = __pyx_bstruct_g.strides[0]; __pyx_bstride_1_g = __pyx_bstruct_g.strides[1]; __pyx_bstride_2_g = __pyx_bstruct_g.strides[2];
+  __pyx_bshape_0_g = __pyx_bstruct_g.shape[0]; __pyx_bshape_1_g = __pyx_bstruct_g.shape[1]; __pyx_bshape_2_g = __pyx_bstruct_g.shape[2];
 
   /* "astropy/nddata/convolution/boundary_none.pyx":155
  *                              np.ndarray[DTYPE_t, ndim=3] g):
@@ -2911,9 +2720,9 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_4convol
     __Pyx_Raise(__pyx_t_5, 0, 0, 0);
     __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
     {__pyx_filename = __pyx_f[0]; __pyx_lineno = 156; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    goto __pyx_L3;
+    goto __pyx_L6;
   }
-  __pyx_L3:;
+  __pyx_L6:;
 
   /* "astropy/nddata/convolution/boundary_none.pyx":158
  *         raise ValueError("Convolution kernel must have odd dimensions")
@@ -3054,7 +2863,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_4convol
   __pyx_t_8 = PyInt_FromLong(__pyx_v_nz); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 172; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_8);
   __pyx_t_9 = PyList_New(3); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 172; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_9);
+  __Pyx_GOTREF(((PyObject *)__pyx_t_9));
   PyList_SET_ITEM(__pyx_t_9, 0, __pyx_t_5);
   __Pyx_GIVEREF(__pyx_t_5);
   PyList_SET_ITEM(__pyx_t_9, 1, __pyx_t_7);
@@ -3065,7 +2874,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_4convol
   __pyx_t_7 = 0;
   __pyx_t_8 = 0;
   __pyx_t_8 = PyTuple_New(1); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 172; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_8);
+  __Pyx_GOTREF(((PyObject *)__pyx_t_8));
   PyTuple_SET_ITEM(__pyx_t_8, 0, ((PyObject *)__pyx_t_9));
   __Pyx_GIVEREF(((PyObject *)__pyx_t_9));
   __pyx_t_9 = 0;
@@ -3075,7 +2884,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_4convol
   __Pyx_GOTREF(__pyx_t_7);
   if (PyDict_SetItem(__pyx_t_9, ((PyObject *)__pyx_n_s__dtype), __pyx_t_7) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 172; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-  __pyx_t_7 = PyObject_Call(__pyx_t_6, ((PyObject *)__pyx_t_8), ((PyObject *)__pyx_t_9)); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 172; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_7 = PyEval_CallObjectWithKeywords(__pyx_t_6, ((PyObject *)__pyx_t_8), ((PyObject *)__pyx_t_9)); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 172; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_7);
   __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
   __Pyx_DECREF(((PyObject *)__pyx_t_8)); __pyx_t_8 = 0;
@@ -3084,10 +2893,11 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_4convol
   __pyx_t_10 = ((PyArrayObject *)__pyx_t_7);
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_fixed.rcbuffer->pybuffer, (PyObject*)__pyx_t_10, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 3, 0, __pyx_stack) == -1)) {
-      __pyx_v_fixed = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf = NULL;
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_fixed, (PyObject*)__pyx_t_10, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 3, 0, __pyx_stack) == -1)) {
+      __pyx_v_fixed = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_fixed.buf = NULL;
       {__pyx_filename = __pyx_f[0]; __pyx_lineno = 172; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    } else {__pyx_pybuffernd_fixed.diminfo[0].strides = __pyx_pybuffernd_fixed.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_fixed.diminfo[0].shape = __pyx_pybuffernd_fixed.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_fixed.diminfo[1].strides = __pyx_pybuffernd_fixed.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_fixed.diminfo[1].shape = __pyx_pybuffernd_fixed.rcbuffer->pybuffer.shape[1]; __pyx_pybuffernd_fixed.diminfo[2].strides = __pyx_pybuffernd_fixed.rcbuffer->pybuffer.strides[2]; __pyx_pybuffernd_fixed.diminfo[2].shape = __pyx_pybuffernd_fixed.rcbuffer->pybuffer.shape[2];
+    } else {__pyx_bstride_0_fixed = __pyx_bstruct_fixed.strides[0]; __pyx_bstride_1_fixed = __pyx_bstruct_fixed.strides[1]; __pyx_bstride_2_fixed = __pyx_bstruct_fixed.strides[2];
+      __pyx_bshape_0_fixed = __pyx_bstruct_fixed.shape[0]; __pyx_bshape_1_fixed = __pyx_bstruct_fixed.shape[1]; __pyx_bshape_2_fixed = __pyx_bstruct_fixed.shape[2];
     }
   }
   __pyx_t_10 = 0;
@@ -3113,7 +2923,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_4convol
   __pyx_t_6 = PyInt_FromLong(__pyx_v_nz); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 173; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_6);
   __pyx_t_5 = PyList_New(3); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 173; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_5);
+  __Pyx_GOTREF(((PyObject *)__pyx_t_5));
   PyList_SET_ITEM(__pyx_t_5, 0, __pyx_t_7);
   __Pyx_GIVEREF(__pyx_t_7);
   PyList_SET_ITEM(__pyx_t_5, 1, __pyx_t_8);
@@ -3124,7 +2934,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_4convol
   __pyx_t_8 = 0;
   __pyx_t_6 = 0;
   __pyx_t_6 = PyTuple_New(1); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 173; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_6);
+  __Pyx_GOTREF(((PyObject *)__pyx_t_6));
   PyTuple_SET_ITEM(__pyx_t_6, 0, ((PyObject *)__pyx_t_5));
   __Pyx_GIVEREF(((PyObject *)__pyx_t_5));
   __pyx_t_5 = 0;
@@ -3134,7 +2944,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_4convol
   __Pyx_GOTREF(__pyx_t_8);
   if (PyDict_SetItem(__pyx_t_5, ((PyObject *)__pyx_n_s__dtype), __pyx_t_8) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 173; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-  __pyx_t_8 = PyObject_Call(__pyx_t_9, ((PyObject *)__pyx_t_6), ((PyObject *)__pyx_t_5)); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 173; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_8 = PyEval_CallObjectWithKeywords(__pyx_t_9, ((PyObject *)__pyx_t_6), ((PyObject *)__pyx_t_5)); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 173; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_8);
   __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
   __Pyx_DECREF(((PyObject *)__pyx_t_6)); __pyx_t_6 = 0;
@@ -3143,10 +2953,11 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_4convol
   __pyx_t_11 = ((PyArrayObject *)__pyx_t_8);
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_conv.rcbuffer->pybuffer, (PyObject*)__pyx_t_11, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 3, 0, __pyx_stack) == -1)) {
-      __pyx_v_conv = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_conv.rcbuffer->pybuffer.buf = NULL;
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_conv, (PyObject*)__pyx_t_11, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 3, 0, __pyx_stack) == -1)) {
+      __pyx_v_conv = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_conv.buf = NULL;
       {__pyx_filename = __pyx_f[0]; __pyx_lineno = 173; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    } else {__pyx_pybuffernd_conv.diminfo[0].strides = __pyx_pybuffernd_conv.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_conv.diminfo[0].shape = __pyx_pybuffernd_conv.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_conv.diminfo[1].strides = __pyx_pybuffernd_conv.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_conv.diminfo[1].shape = __pyx_pybuffernd_conv.rcbuffer->pybuffer.shape[1]; __pyx_pybuffernd_conv.diminfo[2].strides = __pyx_pybuffernd_conv.rcbuffer->pybuffer.strides[2]; __pyx_pybuffernd_conv.diminfo[2].shape = __pyx_pybuffernd_conv.rcbuffer->pybuffer.shape[2];
+    } else {__pyx_bstride_0_conv = __pyx_bstruct_conv.strides[0]; __pyx_bstride_1_conv = __pyx_bstruct_conv.strides[1]; __pyx_bstride_2_conv = __pyx_bstruct_conv.strides[2];
+      __pyx_bshape_0_conv = __pyx_bstruct_conv.shape[0]; __pyx_bshape_1_conv = __pyx_bstruct_conv.shape[1]; __pyx_bshape_2_conv = __pyx_bstruct_conv.shape[2];
     }
   }
   __pyx_t_11 = 0;
@@ -3196,7 +3007,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_4convol
         __pyx_t_18 = __pyx_v_i;
         __pyx_t_19 = __pyx_v_j;
         __pyx_t_20 = __pyx_v_k;
-        __pyx_t_4 = npy_isnan((*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_pybuffernd_f.rcbuffer->pybuffer.buf, __pyx_t_18, __pyx_pybuffernd_f.diminfo[0].strides, __pyx_t_19, __pyx_pybuffernd_f.diminfo[1].strides, __pyx_t_20, __pyx_pybuffernd_f.diminfo[2].strides)));
+        __pyx_t_4 = npy_isnan((*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_bstruct_f.buf, __pyx_t_18, __pyx_bstride_0_f, __pyx_t_19, __pyx_bstride_1_f, __pyx_t_20, __pyx_bstride_2_f)));
         if (__pyx_t_4) {
 
           /* "astropy/nddata/convolution/boundary_none.pyx":187
@@ -3260,7 +3071,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_4convol
                 __pyx_t_27 = __pyx_v_ii;
                 __pyx_t_28 = __pyx_v_jj;
                 __pyx_t_29 = __pyx_v_kk;
-                __pyx_v_val = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_pybuffernd_f.rcbuffer->pybuffer.buf, __pyx_t_27, __pyx_pybuffernd_f.diminfo[0].strides, __pyx_t_28, __pyx_pybuffernd_f.diminfo[1].strides, __pyx_t_29, __pyx_pybuffernd_f.diminfo[2].strides));
+                __pyx_v_val = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_bstruct_f.buf, __pyx_t_27, __pyx_bstride_0_f, __pyx_t_28, __pyx_bstride_1_f, __pyx_t_29, __pyx_bstride_2_f));
 
                 /* "astropy/nddata/convolution/boundary_none.pyx":193
  *                             for kk in range(k - wkz, k + wkz + 1):
@@ -3282,7 +3093,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_4convol
                   __pyx_t_30 = ((unsigned int)((__pyx_v_wkx + __pyx_v_ii) - __pyx_v_i));
                   __pyx_t_31 = ((unsigned int)((__pyx_v_wky + __pyx_v_jj) - __pyx_v_j));
                   __pyx_t_32 = ((unsigned int)((__pyx_v_wkz + __pyx_v_kk) - __pyx_v_k));
-                  __pyx_v_ker = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_pybuffernd_g.rcbuffer->pybuffer.buf, __pyx_t_30, __pyx_pybuffernd_g.diminfo[0].strides, __pyx_t_31, __pyx_pybuffernd_g.diminfo[1].strides, __pyx_t_32, __pyx_pybuffernd_g.diminfo[2].strides));
+                  __pyx_v_ker = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_bstruct_g.buf, __pyx_t_30, __pyx_bstride_0_g, __pyx_t_31, __pyx_bstride_1_g, __pyx_t_32, __pyx_bstride_2_g));
 
                   /* "astropy/nddata/convolution/boundary_none.pyx":197
  *                                             <unsigned int>(wky + jj - j),
@@ -3301,9 +3112,9 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_4convol
  *                         fixed[i, j, k] = top / bot
  */
                   __pyx_v_bot = (__pyx_v_bot + __pyx_v_ker);
-                  goto __pyx_L17;
+                  goto __pyx_L20;
                 }
-                __pyx_L17:;
+                __pyx_L20:;
               }
             }
           }
@@ -3332,8 +3143,8 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_4convol
             __pyx_t_22 = __pyx_v_i;
             __pyx_t_24 = __pyx_v_j;
             __pyx_t_26 = __pyx_v_k;
-            *__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_22, __pyx_pybuffernd_fixed.diminfo[0].strides, __pyx_t_24, __pyx_pybuffernd_fixed.diminfo[1].strides, __pyx_t_26, __pyx_pybuffernd_fixed.diminfo[2].strides) = (__pyx_v_top / __pyx_v_bot);
-            goto __pyx_L18;
+            *__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_22, __pyx_bstride_0_fixed, __pyx_t_24, __pyx_bstride_1_fixed, __pyx_t_26, __pyx_bstride_2_fixed) = (__pyx_v_top / __pyx_v_bot);
+            goto __pyx_L21;
           }
           /*else*/ {
 
@@ -3350,10 +3161,10 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_4convol
             __pyx_t_36 = __pyx_v_i;
             __pyx_t_37 = __pyx_v_j;
             __pyx_t_38 = __pyx_v_k;
-            *__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_36, __pyx_pybuffernd_fixed.diminfo[0].strides, __pyx_t_37, __pyx_pybuffernd_fixed.diminfo[1].strides, __pyx_t_38, __pyx_pybuffernd_fixed.diminfo[2].strides) = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_pybuffernd_f.rcbuffer->pybuffer.buf, __pyx_t_33, __pyx_pybuffernd_f.diminfo[0].strides, __pyx_t_34, __pyx_pybuffernd_f.diminfo[1].strides, __pyx_t_35, __pyx_pybuffernd_f.diminfo[2].strides));
+            *__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_36, __pyx_bstride_0_fixed, __pyx_t_37, __pyx_bstride_1_fixed, __pyx_t_38, __pyx_bstride_2_fixed) = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_bstruct_f.buf, __pyx_t_33, __pyx_bstride_0_f, __pyx_t_34, __pyx_bstride_1_f, __pyx_t_35, __pyx_bstride_2_f));
           }
-          __pyx_L18:;
-          goto __pyx_L10;
+          __pyx_L21:;
+          goto __pyx_L13;
         }
         /*else*/ {
 
@@ -3370,9 +3181,9 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_4convol
           __pyx_t_42 = __pyx_v_i;
           __pyx_t_43 = __pyx_v_j;
           __pyx_t_44 = __pyx_v_k;
-          *__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_42, __pyx_pybuffernd_fixed.diminfo[0].strides, __pyx_t_43, __pyx_pybuffernd_fixed.diminfo[1].strides, __pyx_t_44, __pyx_pybuffernd_fixed.diminfo[2].strides) = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_pybuffernd_f.rcbuffer->pybuffer.buf, __pyx_t_39, __pyx_pybuffernd_f.diminfo[0].strides, __pyx_t_40, __pyx_pybuffernd_f.diminfo[1].strides, __pyx_t_41, __pyx_pybuffernd_f.diminfo[2].strides));
+          *__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_42, __pyx_bstride_0_fixed, __pyx_t_43, __pyx_bstride_1_fixed, __pyx_t_44, __pyx_bstride_2_fixed) = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_bstruct_f.buf, __pyx_t_39, __pyx_bstride_0_f, __pyx_t_40, __pyx_bstride_1_f, __pyx_t_41, __pyx_bstride_2_f));
         }
-        __pyx_L10:;
+        __pyx_L13:;
       }
     }
   }
@@ -3420,7 +3231,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_4convol
         __pyx_t_45 = __pyx_v_i;
         __pyx_t_46 = __pyx_v_j;
         __pyx_t_47 = __pyx_v_k;
-        __pyx_t_4 = (!npy_isnan((*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_45, __pyx_pybuffernd_fixed.diminfo[0].strides, __pyx_t_46, __pyx_pybuffernd_fixed.diminfo[1].strides, __pyx_t_47, __pyx_pybuffernd_fixed.diminfo[2].strides))));
+        __pyx_t_4 = (!npy_isnan((*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_45, __pyx_bstride_0_fixed, __pyx_t_46, __pyx_bstride_1_fixed, __pyx_t_47, __pyx_bstride_2_fixed))));
         if (__pyx_t_4) {
 
           /* "astropy/nddata/convolution/boundary_none.pyx":211
@@ -3484,7 +3295,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_4convol
                 __pyx_t_51 = __pyx_v_ii;
                 __pyx_t_52 = __pyx_v_jj;
                 __pyx_t_53 = __pyx_v_kk;
-                __pyx_v_val = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_51, __pyx_pybuffernd_fixed.diminfo[0].strides, __pyx_t_52, __pyx_pybuffernd_fixed.diminfo[1].strides, __pyx_t_53, __pyx_pybuffernd_fixed.diminfo[2].strides));
+                __pyx_v_val = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_51, __pyx_bstride_0_fixed, __pyx_t_52, __pyx_bstride_1_fixed, __pyx_t_53, __pyx_bstride_2_fixed));
 
                 /* "astropy/nddata/convolution/boundary_none.pyx":219
  *                                 ker = g[<unsigned int>(wkx + ii - i),
@@ -3496,7 +3307,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_4convol
                 __pyx_t_54 = ((unsigned int)((__pyx_v_wkx + __pyx_v_ii) - __pyx_v_i));
                 __pyx_t_55 = ((unsigned int)((__pyx_v_wky + __pyx_v_jj) - __pyx_v_j));
                 __pyx_t_56 = ((unsigned int)((__pyx_v_wkz + __pyx_v_kk) - __pyx_v_k));
-                __pyx_v_ker = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_pybuffernd_g.rcbuffer->pybuffer.buf, __pyx_t_54, __pyx_pybuffernd_g.diminfo[0].strides, __pyx_t_55, __pyx_pybuffernd_g.diminfo[1].strides, __pyx_t_56, __pyx_pybuffernd_g.diminfo[2].strides));
+                __pyx_v_ker = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_bstruct_g.buf, __pyx_t_54, __pyx_bstride_0_g, __pyx_t_55, __pyx_bstride_1_g, __pyx_t_56, __pyx_bstride_2_g));
 
                 /* "astropy/nddata/convolution/boundary_none.pyx":220
  *                                         <unsigned int>(wky + jj - j),
@@ -3525,9 +3336,9 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_4convol
  *                         conv[i, j, k] = top / bot
  */
                   __pyx_v_bot = (__pyx_v_bot + __pyx_v_ker);
-                  goto __pyx_L32;
+                  goto __pyx_L35;
                 }
-                __pyx_L32:;
+                __pyx_L35:;
               }
             }
           }
@@ -3556,8 +3367,8 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_4convol
             __pyx_t_48 = __pyx_v_i;
             __pyx_t_49 = __pyx_v_j;
             __pyx_t_50 = __pyx_v_k;
-            *__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_pybuffernd_conv.rcbuffer->pybuffer.buf, __pyx_t_48, __pyx_pybuffernd_conv.diminfo[0].strides, __pyx_t_49, __pyx_pybuffernd_conv.diminfo[1].strides, __pyx_t_50, __pyx_pybuffernd_conv.diminfo[2].strides) = (__pyx_v_top / __pyx_v_bot);
-            goto __pyx_L33;
+            *__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_bstruct_conv.buf, __pyx_t_48, __pyx_bstride_0_conv, __pyx_t_49, __pyx_bstride_1_conv, __pyx_t_50, __pyx_bstride_2_conv) = (__pyx_v_top / __pyx_v_bot);
+            goto __pyx_L36;
           }
           /*else*/ {
 
@@ -3574,10 +3385,10 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_4convol
             __pyx_t_60 = __pyx_v_i;
             __pyx_t_61 = __pyx_v_j;
             __pyx_t_62 = __pyx_v_k;
-            *__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_pybuffernd_conv.rcbuffer->pybuffer.buf, __pyx_t_60, __pyx_pybuffernd_conv.diminfo[0].strides, __pyx_t_61, __pyx_pybuffernd_conv.diminfo[1].strides, __pyx_t_62, __pyx_pybuffernd_conv.diminfo[2].strides) = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_57, __pyx_pybuffernd_fixed.diminfo[0].strides, __pyx_t_58, __pyx_pybuffernd_fixed.diminfo[1].strides, __pyx_t_59, __pyx_pybuffernd_fixed.diminfo[2].strides));
+            *__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_bstruct_conv.buf, __pyx_t_60, __pyx_bstride_0_conv, __pyx_t_61, __pyx_bstride_1_conv, __pyx_t_62, __pyx_bstride_2_conv) = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_57, __pyx_bstride_0_fixed, __pyx_t_58, __pyx_bstride_1_fixed, __pyx_t_59, __pyx_bstride_2_fixed));
           }
-          __pyx_L33:;
-          goto __pyx_L25;
+          __pyx_L36:;
+          goto __pyx_L28;
         }
         /*else*/ {
 
@@ -3594,9 +3405,9 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_4convol
           __pyx_t_66 = __pyx_v_i;
           __pyx_t_67 = __pyx_v_j;
           __pyx_t_68 = __pyx_v_k;
-          *__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_pybuffernd_conv.rcbuffer->pybuffer.buf, __pyx_t_66, __pyx_pybuffernd_conv.diminfo[0].strides, __pyx_t_67, __pyx_pybuffernd_conv.diminfo[1].strides, __pyx_t_68, __pyx_pybuffernd_conv.diminfo[2].strides) = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_63, __pyx_pybuffernd_fixed.diminfo[0].strides, __pyx_t_64, __pyx_pybuffernd_fixed.diminfo[1].strides, __pyx_t_65, __pyx_pybuffernd_fixed.diminfo[2].strides));
+          *__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_bstruct_conv.buf, __pyx_t_66, __pyx_bstride_0_conv, __pyx_t_67, __pyx_bstride_1_conv, __pyx_t_68, __pyx_bstride_2_conv) = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_none_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_63, __pyx_bstride_0_fixed, __pyx_t_64, __pyx_bstride_1_fixed, __pyx_t_65, __pyx_bstride_2_fixed));
         }
-        __pyx_L25:;
+        __pyx_L28:;
       }
     }
   }
@@ -3621,19 +3432,19 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_4convol
   __Pyx_XDECREF(__pyx_t_9);
   { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;
     __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);
-    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_conv.rcbuffer->pybuffer);
-    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_f.rcbuffer->pybuffer);
-    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_fixed.rcbuffer->pybuffer);
-    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_g.rcbuffer->pybuffer);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_conv);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_g);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_f);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_fixed);
   __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
   __Pyx_AddTraceback("astropy.nddata.convolution.boundary_none.convolve3d_boundary_none", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   goto __pyx_L2;
   __pyx_L0:;
-  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_conv.rcbuffer->pybuffer);
-  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_f.rcbuffer->pybuffer);
-  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_fixed.rcbuffer->pybuffer);
-  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_g.rcbuffer->pybuffer);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_conv);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_g);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_f);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_fixed);
   __pyx_L2:;
   __Pyx_XDECREF((PyObject *)__pyx_v_fixed);
   __Pyx_XDECREF((PyObject *)__pyx_v_conv);
@@ -3642,18 +3453,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_none_4convol
   return __pyx_r;
 }
 
-/* Python wrapper */
-static int __pyx_pw_5numpy_7ndarray_1__getbuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags); /*proto*/
-static int __pyx_pw_5numpy_7ndarray_1__getbuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags) {
-  int __pyx_r;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__getbuffer__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_5numpy_7ndarray___getbuffer__(((PyArrayObject *)__pyx_v_self), ((Py_buffer *)__pyx_v_info), ((int)__pyx_v_flags));
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-/* "numpy.pxd":193
+/* "numpy.pxd":190
  *         # experimental exception made for __getbuffer__ and __releasebuffer__
  *         # -- the details of this may change.
  *         def __getbuffer__(ndarray self, Py_buffer* info, int flags):             # <<<<<<<<<<<<<<
@@ -3661,7 +3461,8 @@ static int __pyx_pw_5numpy_7ndarray_1__getbuffer__(PyObject *__pyx_v_self, Py_bu
  *             # requirements, and does not yet fullfill the PEP.
  */
 
-static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags) {
+static CYTHON_UNUSED int __pyx_pf_5numpy_7ndarray___getbuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags); /*proto*/
+static CYTHON_UNUSED int __pyx_pf_5numpy_7ndarray___getbuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags) {
   int __pyx_v_copy_shape;
   int __pyx_v_i;
   int __pyx_v_ndim;
@@ -3686,13 +3487,13 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("__getbuffer__", 0);
+  __Pyx_RefNannySetupContext("__getbuffer__");
   if (__pyx_v_info != NULL) {
     __pyx_v_info->obj = Py_None; __Pyx_INCREF(Py_None);
     __Pyx_GIVEREF(__pyx_v_info->obj);
   }
 
-  /* "numpy.pxd":199
+  /* "numpy.pxd":196
  *             # of flags
  * 
  *             if info == NULL: return             # <<<<<<<<<<<<<<
@@ -3703,11 +3504,11 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
   if (__pyx_t_1) {
     __pyx_r = 0;
     goto __pyx_L0;
-    goto __pyx_L3;
+    goto __pyx_L5;
   }
-  __pyx_L3:;
+  __pyx_L5:;
 
-  /* "numpy.pxd":202
+  /* "numpy.pxd":199
  * 
  *             cdef int copy_shape, i, ndim
  *             cdef int endian_detector = 1             # <<<<<<<<<<<<<<
@@ -3716,7 +3517,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
   __pyx_v_endian_detector = 1;
 
-  /* "numpy.pxd":203
+  /* "numpy.pxd":200
  *             cdef int copy_shape, i, ndim
  *             cdef int endian_detector = 1
  *             cdef bint little_endian = ((<char*>&endian_detector)[0] != 0)             # <<<<<<<<<<<<<<
@@ -3725,16 +3526,16 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
   __pyx_v_little_endian = ((((char *)(&__pyx_v_endian_detector))[0]) != 0);
 
-  /* "numpy.pxd":205
+  /* "numpy.pxd":202
  *             cdef bint little_endian = ((<char*>&endian_detector)[0] != 0)
  * 
  *             ndim = PyArray_NDIM(self)             # <<<<<<<<<<<<<<
  * 
  *             if sizeof(npy_intp) != sizeof(Py_ssize_t):
  */
-  __pyx_v_ndim = PyArray_NDIM(__pyx_v_self);
+  __pyx_v_ndim = PyArray_NDIM(((PyArrayObject *)__pyx_v_self));
 
-  /* "numpy.pxd":207
+  /* "numpy.pxd":204
  *             ndim = PyArray_NDIM(self)
  * 
  *             if sizeof(npy_intp) != sizeof(Py_ssize_t):             # <<<<<<<<<<<<<<
@@ -3744,7 +3545,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
   __pyx_t_1 = ((sizeof(npy_intp)) != (sizeof(Py_ssize_t)));
   if (__pyx_t_1) {
 
-    /* "numpy.pxd":208
+    /* "numpy.pxd":205
  * 
  *             if sizeof(npy_intp) != sizeof(Py_ssize_t):
  *                 copy_shape = 1             # <<<<<<<<<<<<<<
@@ -3752,11 +3553,11 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  *                 copy_shape = 0
  */
     __pyx_v_copy_shape = 1;
-    goto __pyx_L4;
+    goto __pyx_L6;
   }
   /*else*/ {
 
-    /* "numpy.pxd":210
+    /* "numpy.pxd":207
  *                 copy_shape = 1
  *             else:
  *                 copy_shape = 0             # <<<<<<<<<<<<<<
@@ -3765,9 +3566,9 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
     __pyx_v_copy_shape = 0;
   }
-  __pyx_L4:;
+  __pyx_L6:;
 
-  /* "numpy.pxd":212
+  /* "numpy.pxd":209
  *                 copy_shape = 0
  * 
  *             if ((flags & pybuf.PyBUF_C_CONTIGUOUS == pybuf.PyBUF_C_CONTIGUOUS)             # <<<<<<<<<<<<<<
@@ -3777,37 +3578,37 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
   __pyx_t_1 = ((__pyx_v_flags & PyBUF_C_CONTIGUOUS) == PyBUF_C_CONTIGUOUS);
   if (__pyx_t_1) {
 
-    /* "numpy.pxd":213
+    /* "numpy.pxd":210
  * 
  *             if ((flags & pybuf.PyBUF_C_CONTIGUOUS == pybuf.PyBUF_C_CONTIGUOUS)
  *                 and not PyArray_CHKFLAGS(self, NPY_C_CONTIGUOUS)):             # <<<<<<<<<<<<<<
  *                 raise ValueError(u"ndarray is not C contiguous")
  * 
  */
-    __pyx_t_2 = (!PyArray_CHKFLAGS(__pyx_v_self, NPY_C_CONTIGUOUS));
+    __pyx_t_2 = (!PyArray_CHKFLAGS(((PyArrayObject *)__pyx_v_self), NPY_C_CONTIGUOUS));
     __pyx_t_3 = __pyx_t_2;
   } else {
     __pyx_t_3 = __pyx_t_1;
   }
   if (__pyx_t_3) {
 
-    /* "numpy.pxd":214
+    /* "numpy.pxd":211
  *             if ((flags & pybuf.PyBUF_C_CONTIGUOUS == pybuf.PyBUF_C_CONTIGUOUS)
  *                 and not PyArray_CHKFLAGS(self, NPY_C_CONTIGUOUS)):
  *                 raise ValueError(u"ndarray is not C contiguous")             # <<<<<<<<<<<<<<
  * 
  *             if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS)
  */
-    __pyx_t_4 = PyObject_Call(__pyx_builtin_ValueError, ((PyObject *)__pyx_k_tuple_6), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 214; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = PyObject_Call(__pyx_builtin_ValueError, ((PyObject *)__pyx_k_tuple_6), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 211; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_4);
     __Pyx_Raise(__pyx_t_4, 0, 0, 0);
     __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-    {__pyx_filename = __pyx_f[1]; __pyx_lineno = 214; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    goto __pyx_L5;
+    {__pyx_filename = __pyx_f[1]; __pyx_lineno = 211; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    goto __pyx_L7;
   }
-  __pyx_L5:;
+  __pyx_L7:;
 
-  /* "numpy.pxd":216
+  /* "numpy.pxd":213
  *                 raise ValueError(u"ndarray is not C contiguous")
  * 
  *             if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS)             # <<<<<<<<<<<<<<
@@ -3817,46 +3618,46 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
   __pyx_t_3 = ((__pyx_v_flags & PyBUF_F_CONTIGUOUS) == PyBUF_F_CONTIGUOUS);
   if (__pyx_t_3) {
 
-    /* "numpy.pxd":217
+    /* "numpy.pxd":214
  * 
  *             if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS)
  *                 and not PyArray_CHKFLAGS(self, NPY_F_CONTIGUOUS)):             # <<<<<<<<<<<<<<
  *                 raise ValueError(u"ndarray is not Fortran contiguous")
  * 
  */
-    __pyx_t_1 = (!PyArray_CHKFLAGS(__pyx_v_self, NPY_F_CONTIGUOUS));
+    __pyx_t_1 = (!PyArray_CHKFLAGS(((PyArrayObject *)__pyx_v_self), NPY_F_CONTIGUOUS));
     __pyx_t_2 = __pyx_t_1;
   } else {
     __pyx_t_2 = __pyx_t_3;
   }
   if (__pyx_t_2) {
 
-    /* "numpy.pxd":218
+    /* "numpy.pxd":215
  *             if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS)
  *                 and not PyArray_CHKFLAGS(self, NPY_F_CONTIGUOUS)):
  *                 raise ValueError(u"ndarray is not Fortran contiguous")             # <<<<<<<<<<<<<<
  * 
  *             info.buf = PyArray_DATA(self)
  */
-    __pyx_t_4 = PyObject_Call(__pyx_builtin_ValueError, ((PyObject *)__pyx_k_tuple_8), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 218; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = PyObject_Call(__pyx_builtin_ValueError, ((PyObject *)__pyx_k_tuple_8), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 215; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_4);
     __Pyx_Raise(__pyx_t_4, 0, 0, 0);
     __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-    {__pyx_filename = __pyx_f[1]; __pyx_lineno = 218; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    goto __pyx_L6;
+    {__pyx_filename = __pyx_f[1]; __pyx_lineno = 215; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    goto __pyx_L8;
   }
-  __pyx_L6:;
+  __pyx_L8:;
 
-  /* "numpy.pxd":220
+  /* "numpy.pxd":217
  *                 raise ValueError(u"ndarray is not Fortran contiguous")
  * 
  *             info.buf = PyArray_DATA(self)             # <<<<<<<<<<<<<<
  *             info.ndim = ndim
  *             if copy_shape:
  */
-  __pyx_v_info->buf = PyArray_DATA(__pyx_v_self);
+  __pyx_v_info->buf = PyArray_DATA(((PyArrayObject *)__pyx_v_self));
 
-  /* "numpy.pxd":221
+  /* "numpy.pxd":218
  * 
  *             info.buf = PyArray_DATA(self)
  *             info.ndim = ndim             # <<<<<<<<<<<<<<
@@ -3865,7 +3666,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
   __pyx_v_info->ndim = __pyx_v_ndim;
 
-  /* "numpy.pxd":222
+  /* "numpy.pxd":219
  *             info.buf = PyArray_DATA(self)
  *             info.ndim = ndim
  *             if copy_shape:             # <<<<<<<<<<<<<<
@@ -3874,7 +3675,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
   if (__pyx_v_copy_shape) {
 
-    /* "numpy.pxd":225
+    /* "numpy.pxd":222
  *                 # Allocate new buffer for strides and shape info.
  *                 # This is allocated as one block, strides first.
  *                 info.strides = <Py_ssize_t*>stdlib.malloc(sizeof(Py_ssize_t) * <size_t>ndim * 2)             # <<<<<<<<<<<<<<
@@ -3883,7 +3684,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
     __pyx_v_info->strides = ((Py_ssize_t *)malloc((((sizeof(Py_ssize_t)) * ((size_t)__pyx_v_ndim)) * 2)));
 
-    /* "numpy.pxd":226
+    /* "numpy.pxd":223
  *                 # This is allocated as one block, strides first.
  *                 info.strides = <Py_ssize_t*>stdlib.malloc(sizeof(Py_ssize_t) * <size_t>ndim * 2)
  *                 info.shape = info.strides + ndim             # <<<<<<<<<<<<<<
@@ -3892,7 +3693,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
     __pyx_v_info->shape = (__pyx_v_info->strides + __pyx_v_ndim);
 
-    /* "numpy.pxd":227
+    /* "numpy.pxd":224
  *                 info.strides = <Py_ssize_t*>stdlib.malloc(sizeof(Py_ssize_t) * <size_t>ndim * 2)
  *                 info.shape = info.strides + ndim
  *                 for i in range(ndim):             # <<<<<<<<<<<<<<
@@ -3903,49 +3704,49 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     for (__pyx_t_6 = 0; __pyx_t_6 < __pyx_t_5; __pyx_t_6+=1) {
       __pyx_v_i = __pyx_t_6;
 
-      /* "numpy.pxd":228
+      /* "numpy.pxd":225
  *                 info.shape = info.strides + ndim
  *                 for i in range(ndim):
  *                     info.strides[i] = PyArray_STRIDES(self)[i]             # <<<<<<<<<<<<<<
  *                     info.shape[i] = PyArray_DIMS(self)[i]
  *             else:
  */
-      (__pyx_v_info->strides[__pyx_v_i]) = (PyArray_STRIDES(__pyx_v_self)[__pyx_v_i]);
+      (__pyx_v_info->strides[__pyx_v_i]) = (PyArray_STRIDES(((PyArrayObject *)__pyx_v_self))[__pyx_v_i]);
 
-      /* "numpy.pxd":229
+      /* "numpy.pxd":226
  *                 for i in range(ndim):
  *                     info.strides[i] = PyArray_STRIDES(self)[i]
  *                     info.shape[i] = PyArray_DIMS(self)[i]             # <<<<<<<<<<<<<<
  *             else:
  *                 info.strides = <Py_ssize_t*>PyArray_STRIDES(self)
  */
-      (__pyx_v_info->shape[__pyx_v_i]) = (PyArray_DIMS(__pyx_v_self)[__pyx_v_i]);
+      (__pyx_v_info->shape[__pyx_v_i]) = (PyArray_DIMS(((PyArrayObject *)__pyx_v_self))[__pyx_v_i]);
     }
-    goto __pyx_L7;
+    goto __pyx_L9;
   }
   /*else*/ {
 
-    /* "numpy.pxd":231
+    /* "numpy.pxd":228
  *                     info.shape[i] = PyArray_DIMS(self)[i]
  *             else:
  *                 info.strides = <Py_ssize_t*>PyArray_STRIDES(self)             # <<<<<<<<<<<<<<
  *                 info.shape = <Py_ssize_t*>PyArray_DIMS(self)
  *             info.suboffsets = NULL
  */
-    __pyx_v_info->strides = ((Py_ssize_t *)PyArray_STRIDES(__pyx_v_self));
+    __pyx_v_info->strides = ((Py_ssize_t *)PyArray_STRIDES(((PyArrayObject *)__pyx_v_self)));
 
-    /* "numpy.pxd":232
+    /* "numpy.pxd":229
  *             else:
  *                 info.strides = <Py_ssize_t*>PyArray_STRIDES(self)
  *                 info.shape = <Py_ssize_t*>PyArray_DIMS(self)             # <<<<<<<<<<<<<<
  *             info.suboffsets = NULL
  *             info.itemsize = PyArray_ITEMSIZE(self)
  */
-    __pyx_v_info->shape = ((Py_ssize_t *)PyArray_DIMS(__pyx_v_self));
+    __pyx_v_info->shape = ((Py_ssize_t *)PyArray_DIMS(((PyArrayObject *)__pyx_v_self)));
   }
-  __pyx_L7:;
+  __pyx_L9:;
 
-  /* "numpy.pxd":233
+  /* "numpy.pxd":230
  *                 info.strides = <Py_ssize_t*>PyArray_STRIDES(self)
  *                 info.shape = <Py_ssize_t*>PyArray_DIMS(self)
  *             info.suboffsets = NULL             # <<<<<<<<<<<<<<
@@ -3954,25 +3755,25 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
   __pyx_v_info->suboffsets = NULL;
 
-  /* "numpy.pxd":234
+  /* "numpy.pxd":231
  *                 info.shape = <Py_ssize_t*>PyArray_DIMS(self)
  *             info.suboffsets = NULL
  *             info.itemsize = PyArray_ITEMSIZE(self)             # <<<<<<<<<<<<<<
  *             info.readonly = not PyArray_ISWRITEABLE(self)
  * 
  */
-  __pyx_v_info->itemsize = PyArray_ITEMSIZE(__pyx_v_self);
+  __pyx_v_info->itemsize = PyArray_ITEMSIZE(((PyArrayObject *)__pyx_v_self));
 
-  /* "numpy.pxd":235
+  /* "numpy.pxd":232
  *             info.suboffsets = NULL
  *             info.itemsize = PyArray_ITEMSIZE(self)
  *             info.readonly = not PyArray_ISWRITEABLE(self)             # <<<<<<<<<<<<<<
  * 
  *             cdef int t
  */
-  __pyx_v_info->readonly = (!PyArray_ISWRITEABLE(__pyx_v_self));
+  __pyx_v_info->readonly = (!PyArray_ISWRITEABLE(((PyArrayObject *)__pyx_v_self)));
 
-  /* "numpy.pxd":238
+  /* "numpy.pxd":235
  * 
  *             cdef int t
  *             cdef char* f = NULL             # <<<<<<<<<<<<<<
@@ -3981,17 +3782,17 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
   __pyx_v_f = NULL;
 
-  /* "numpy.pxd":239
+  /* "numpy.pxd":236
  *             cdef int t
  *             cdef char* f = NULL
  *             cdef dtype descr = self.descr             # <<<<<<<<<<<<<<
  *             cdef list stack
  *             cdef int offset
  */
-  __Pyx_INCREF(((PyObject *)__pyx_v_self->descr));
-  __pyx_v_descr = __pyx_v_self->descr;
+  __Pyx_INCREF(((PyObject *)((PyArrayObject *)__pyx_v_self)->descr));
+  __pyx_v_descr = ((PyArrayObject *)__pyx_v_self)->descr;
 
-  /* "numpy.pxd":243
+  /* "numpy.pxd":240
  *             cdef int offset
  * 
  *             cdef bint hasfields = PyDataType_HASFIELDS(descr)             # <<<<<<<<<<<<<<
@@ -4000,7 +3801,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
   __pyx_v_hasfields = PyDataType_HASFIELDS(__pyx_v_descr);
 
-  /* "numpy.pxd":245
+  /* "numpy.pxd":242
  *             cdef bint hasfields = PyDataType_HASFIELDS(descr)
  * 
  *             if not hasfields and not copy_shape:             # <<<<<<<<<<<<<<
@@ -4016,7 +3817,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
   }
   if (__pyx_t_1) {
 
-    /* "numpy.pxd":247
+    /* "numpy.pxd":244
  *             if not hasfields and not copy_shape:
  *                 # do not call releasebuffer
  *                 info.obj = None             # <<<<<<<<<<<<<<
@@ -4028,26 +3829,26 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __Pyx_GOTREF(__pyx_v_info->obj);
     __Pyx_DECREF(__pyx_v_info->obj);
     __pyx_v_info->obj = Py_None;
-    goto __pyx_L10;
+    goto __pyx_L12;
   }
   /*else*/ {
 
-    /* "numpy.pxd":250
+    /* "numpy.pxd":247
  *             else:
  *                 # need to call releasebuffer
  *                 info.obj = self             # <<<<<<<<<<<<<<
  * 
  *             if not hasfields:
  */
-    __Pyx_INCREF(((PyObject *)__pyx_v_self));
-    __Pyx_GIVEREF(((PyObject *)__pyx_v_self));
+    __Pyx_INCREF(__pyx_v_self);
+    __Pyx_GIVEREF(__pyx_v_self);
     __Pyx_GOTREF(__pyx_v_info->obj);
     __Pyx_DECREF(__pyx_v_info->obj);
-    __pyx_v_info->obj = ((PyObject *)__pyx_v_self);
+    __pyx_v_info->obj = __pyx_v_self;
   }
-  __pyx_L10:;
+  __pyx_L12:;
 
-  /* "numpy.pxd":252
+  /* "numpy.pxd":249
  *                 info.obj = self
  * 
  *             if not hasfields:             # <<<<<<<<<<<<<<
@@ -4057,7 +3858,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
   __pyx_t_1 = (!__pyx_v_hasfields);
   if (__pyx_t_1) {
 
-    /* "numpy.pxd":253
+    /* "numpy.pxd":250
  * 
  *             if not hasfields:
  *                 t = descr.type_num             # <<<<<<<<<<<<<<
@@ -4066,7 +3867,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
     __pyx_v_t = __pyx_v_descr->type_num;
 
-    /* "numpy.pxd":254
+    /* "numpy.pxd":251
  *             if not hasfields:
  *                 t = descr.type_num
  *                 if ((descr.byteorder == '>' and little_endian) or             # <<<<<<<<<<<<<<
@@ -4081,7 +3882,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     }
     if (!__pyx_t_2) {
 
-      /* "numpy.pxd":255
+      /* "numpy.pxd":252
  *                 t = descr.type_num
  *                 if ((descr.byteorder == '>' and little_endian) or
  *                     (descr.byteorder == '<' and not little_endian)):             # <<<<<<<<<<<<<<
@@ -4101,23 +3902,23 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     }
     if (__pyx_t_1) {
 
-      /* "numpy.pxd":256
+      /* "numpy.pxd":253
  *                 if ((descr.byteorder == '>' and little_endian) or
  *                     (descr.byteorder == '<' and not little_endian)):
  *                     raise ValueError(u"Non-native byte order not supported")             # <<<<<<<<<<<<<<
  *                 if   t == NPY_BYTE:        f = "b"
  *                 elif t == NPY_UBYTE:       f = "B"
  */
-      __pyx_t_4 = PyObject_Call(__pyx_builtin_ValueError, ((PyObject *)__pyx_k_tuple_10), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 256; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyObject_Call(__pyx_builtin_ValueError, ((PyObject *)__pyx_k_tuple_10), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 253; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_4);
       __Pyx_Raise(__pyx_t_4, 0, 0, 0);
       __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      {__pyx_filename = __pyx_f[1]; __pyx_lineno = 256; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      goto __pyx_L12;
+      {__pyx_filename = __pyx_f[1]; __pyx_lineno = 253; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      goto __pyx_L14;
     }
-    __pyx_L12:;
+    __pyx_L14:;
 
-    /* "numpy.pxd":257
+    /* "numpy.pxd":254
  *                     (descr.byteorder == '<' and not little_endian)):
  *                     raise ValueError(u"Non-native byte order not supported")
  *                 if   t == NPY_BYTE:        f = "b"             # <<<<<<<<<<<<<<
@@ -4127,10 +3928,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_BYTE);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__b;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":258
+    /* "numpy.pxd":255
  *                     raise ValueError(u"Non-native byte order not supported")
  *                 if   t == NPY_BYTE:        f = "b"
  *                 elif t == NPY_UBYTE:       f = "B"             # <<<<<<<<<<<<<<
@@ -4140,10 +3941,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_UBYTE);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__B;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":259
+    /* "numpy.pxd":256
  *                 if   t == NPY_BYTE:        f = "b"
  *                 elif t == NPY_UBYTE:       f = "B"
  *                 elif t == NPY_SHORT:       f = "h"             # <<<<<<<<<<<<<<
@@ -4153,10 +3954,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_SHORT);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__h;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":260
+    /* "numpy.pxd":257
  *                 elif t == NPY_UBYTE:       f = "B"
  *                 elif t == NPY_SHORT:       f = "h"
  *                 elif t == NPY_USHORT:      f = "H"             # <<<<<<<<<<<<<<
@@ -4166,10 +3967,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_USHORT);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__H;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":261
+    /* "numpy.pxd":258
  *                 elif t == NPY_SHORT:       f = "h"
  *                 elif t == NPY_USHORT:      f = "H"
  *                 elif t == NPY_INT:         f = "i"             # <<<<<<<<<<<<<<
@@ -4179,10 +3980,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_INT);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__i;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":262
+    /* "numpy.pxd":259
  *                 elif t == NPY_USHORT:      f = "H"
  *                 elif t == NPY_INT:         f = "i"
  *                 elif t == NPY_UINT:        f = "I"             # <<<<<<<<<<<<<<
@@ -4192,10 +3993,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_UINT);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__I;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":263
+    /* "numpy.pxd":260
  *                 elif t == NPY_INT:         f = "i"
  *                 elif t == NPY_UINT:        f = "I"
  *                 elif t == NPY_LONG:        f = "l"             # <<<<<<<<<<<<<<
@@ -4205,10 +4006,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_LONG);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__l;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":264
+    /* "numpy.pxd":261
  *                 elif t == NPY_UINT:        f = "I"
  *                 elif t == NPY_LONG:        f = "l"
  *                 elif t == NPY_ULONG:       f = "L"             # <<<<<<<<<<<<<<
@@ -4218,10 +4019,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_ULONG);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__L;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":265
+    /* "numpy.pxd":262
  *                 elif t == NPY_LONG:        f = "l"
  *                 elif t == NPY_ULONG:       f = "L"
  *                 elif t == NPY_LONGLONG:    f = "q"             # <<<<<<<<<<<<<<
@@ -4231,10 +4032,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_LONGLONG);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__q;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":266
+    /* "numpy.pxd":263
  *                 elif t == NPY_ULONG:       f = "L"
  *                 elif t == NPY_LONGLONG:    f = "q"
  *                 elif t == NPY_ULONGLONG:   f = "Q"             # <<<<<<<<<<<<<<
@@ -4244,10 +4045,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_ULONGLONG);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__Q;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":267
+    /* "numpy.pxd":264
  *                 elif t == NPY_LONGLONG:    f = "q"
  *                 elif t == NPY_ULONGLONG:   f = "Q"
  *                 elif t == NPY_FLOAT:       f = "f"             # <<<<<<<<<<<<<<
@@ -4257,10 +4058,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_FLOAT);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__f;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":268
+    /* "numpy.pxd":265
  *                 elif t == NPY_ULONGLONG:   f = "Q"
  *                 elif t == NPY_FLOAT:       f = "f"
  *                 elif t == NPY_DOUBLE:      f = "d"             # <<<<<<<<<<<<<<
@@ -4270,10 +4071,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_DOUBLE);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__d;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":269
+    /* "numpy.pxd":266
  *                 elif t == NPY_FLOAT:       f = "f"
  *                 elif t == NPY_DOUBLE:      f = "d"
  *                 elif t == NPY_LONGDOUBLE:  f = "g"             # <<<<<<<<<<<<<<
@@ -4283,10 +4084,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_LONGDOUBLE);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__g;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":270
+    /* "numpy.pxd":267
  *                 elif t == NPY_DOUBLE:      f = "d"
  *                 elif t == NPY_LONGDOUBLE:  f = "g"
  *                 elif t == NPY_CFLOAT:      f = "Zf"             # <<<<<<<<<<<<<<
@@ -4296,10 +4097,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_CFLOAT);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__Zf;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":271
+    /* "numpy.pxd":268
  *                 elif t == NPY_LONGDOUBLE:  f = "g"
  *                 elif t == NPY_CFLOAT:      f = "Zf"
  *                 elif t == NPY_CDOUBLE:     f = "Zd"             # <<<<<<<<<<<<<<
@@ -4309,10 +4110,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_CDOUBLE);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__Zd;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":272
+    /* "numpy.pxd":269
  *                 elif t == NPY_CFLOAT:      f = "Zf"
  *                 elif t == NPY_CDOUBLE:     f = "Zd"
  *                 elif t == NPY_CLONGDOUBLE: f = "Zg"             # <<<<<<<<<<<<<<
@@ -4322,10 +4123,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_CLONGDOUBLE);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__Zg;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":273
+    /* "numpy.pxd":270
  *                 elif t == NPY_CDOUBLE:     f = "Zd"
  *                 elif t == NPY_CLONGDOUBLE: f = "Zg"
  *                 elif t == NPY_OBJECT:      f = "O"             # <<<<<<<<<<<<<<
@@ -4335,37 +4136,37 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_OBJECT);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__O;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
     /*else*/ {
 
-      /* "numpy.pxd":275
+      /* "numpy.pxd":272
  *                 elif t == NPY_OBJECT:      f = "O"
  *                 else:
  *                     raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t)             # <<<<<<<<<<<<<<
  *                 info.format = f
  *                 return
  */
-      __pyx_t_4 = PyInt_FromLong(__pyx_v_t); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 275; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyInt_FromLong(__pyx_v_t); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 272; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_4);
-      __pyx_t_8 = PyNumber_Remainder(((PyObject *)__pyx_kp_u_11), __pyx_t_4); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 275; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_8 = PyNumber_Remainder(((PyObject *)__pyx_kp_u_11), __pyx_t_4); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 272; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(((PyObject *)__pyx_t_8));
       __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 275; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      __Pyx_GOTREF(__pyx_t_4);
+      __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 272; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(((PyObject *)__pyx_t_4));
       PyTuple_SET_ITEM(__pyx_t_4, 0, ((PyObject *)__pyx_t_8));
       __Pyx_GIVEREF(((PyObject *)__pyx_t_8));
       __pyx_t_8 = 0;
-      __pyx_t_8 = PyObject_Call(__pyx_builtin_ValueError, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 275; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_8 = PyObject_Call(__pyx_builtin_ValueError, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 272; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_8);
       __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
       __Pyx_Raise(__pyx_t_8, 0, 0, 0);
       __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-      {__pyx_filename = __pyx_f[1]; __pyx_lineno = 275; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      {__pyx_filename = __pyx_f[1]; __pyx_lineno = 272; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     }
-    __pyx_L13:;
+    __pyx_L15:;
 
-    /* "numpy.pxd":276
+    /* "numpy.pxd":273
  *                 else:
  *                     raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t)
  *                 info.format = f             # <<<<<<<<<<<<<<
@@ -4374,7 +4175,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
     __pyx_v_info->format = __pyx_v_f;
 
-    /* "numpy.pxd":277
+    /* "numpy.pxd":274
  *                     raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t)
  *                 info.format = f
  *                 return             # <<<<<<<<<<<<<<
@@ -4383,11 +4184,11 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
     __pyx_r = 0;
     goto __pyx_L0;
-    goto __pyx_L11;
+    goto __pyx_L13;
   }
   /*else*/ {
 
-    /* "numpy.pxd":279
+    /* "numpy.pxd":276
  *                 return
  *             else:
  *                 info.format = <char*>stdlib.malloc(_buffer_format_string_len)             # <<<<<<<<<<<<<<
@@ -4396,7 +4197,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
     __pyx_v_info->format = ((char *)malloc(255));
 
-    /* "numpy.pxd":280
+    /* "numpy.pxd":277
  *             else:
  *                 info.format = <char*>stdlib.malloc(_buffer_format_string_len)
  *                 info.format[0] = '^' # Native data types, manual alignment             # <<<<<<<<<<<<<<
@@ -4405,7 +4206,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
     (__pyx_v_info->format[0]) = '^';
 
-    /* "numpy.pxd":281
+    /* "numpy.pxd":278
  *                 info.format = <char*>stdlib.malloc(_buffer_format_string_len)
  *                 info.format[0] = '^' # Native data types, manual alignment
  *                 offset = 0             # <<<<<<<<<<<<<<
@@ -4414,17 +4215,17 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
     __pyx_v_offset = 0;
 
-    /* "numpy.pxd":284
+    /* "numpy.pxd":281
  *                 f = _util_dtypestring(descr, info.format + 1,
  *                                       info.format + _buffer_format_string_len,
  *                                       &offset)             # <<<<<<<<<<<<<<
  *                 f[0] = 0 # Terminate format string
  * 
  */
-    __pyx_t_9 = __pyx_f_5numpy__util_dtypestring(__pyx_v_descr, (__pyx_v_info->format + 1), (__pyx_v_info->format + 255), (&__pyx_v_offset)); if (unlikely(__pyx_t_9 == NULL)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 282; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_9 = __pyx_f_5numpy__util_dtypestring(__pyx_v_descr, (__pyx_v_info->format + 1), (__pyx_v_info->format + 255), (&__pyx_v_offset)); if (unlikely(__pyx_t_9 == NULL)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 279; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __pyx_v_f = __pyx_t_9;
 
-    /* "numpy.pxd":285
+    /* "numpy.pxd":282
  *                                       info.format + _buffer_format_string_len,
  *                                       &offset)
  *                 f[0] = 0 # Terminate format string             # <<<<<<<<<<<<<<
@@ -4433,7 +4234,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
     (__pyx_v_f[0]) = 0;
   }
-  __pyx_L11:;
+  __pyx_L13:;
 
   __pyx_r = 0;
   goto __pyx_L0;
@@ -4458,16 +4259,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
   return __pyx_r;
 }
 
-/* Python wrapper */
-static void __pyx_pw_5numpy_7ndarray_3__releasebuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info); /*proto*/
-static void __pyx_pw_5numpy_7ndarray_3__releasebuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info) {
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__releasebuffer__ (wrapper)", 0);
-  __pyx_pf_5numpy_7ndarray_2__releasebuffer__(((PyArrayObject *)__pyx_v_self), ((Py_buffer *)__pyx_v_info));
-  __Pyx_RefNannyFinishContext();
-}
-
-/* "numpy.pxd":287
+/* "numpy.pxd":284
  *                 f[0] = 0 # Terminate format string
  * 
  *         def __releasebuffer__(ndarray self, Py_buffer* info):             # <<<<<<<<<<<<<<
@@ -4475,22 +4267,23 @@ static void __pyx_pw_5numpy_7ndarray_3__releasebuffer__(PyObject *__pyx_v_self,
  *                 stdlib.free(info.format)
  */
 
-static void __pyx_pf_5numpy_7ndarray_2__releasebuffer__(PyArrayObject *__pyx_v_self, Py_buffer *__pyx_v_info) {
+static CYTHON_UNUSED void __pyx_pf_5numpy_7ndarray_1__releasebuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info); /*proto*/
+static CYTHON_UNUSED void __pyx_pf_5numpy_7ndarray_1__releasebuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info) {
   __Pyx_RefNannyDeclarations
   int __pyx_t_1;
-  __Pyx_RefNannySetupContext("__releasebuffer__", 0);
+  __Pyx_RefNannySetupContext("__releasebuffer__");
 
-  /* "numpy.pxd":288
+  /* "numpy.pxd":285
  * 
  *         def __releasebuffer__(ndarray self, Py_buffer* info):
  *             if PyArray_HASFIELDS(self):             # <<<<<<<<<<<<<<
  *                 stdlib.free(info.format)
  *             if sizeof(npy_intp) != sizeof(Py_ssize_t):
  */
-  __pyx_t_1 = PyArray_HASFIELDS(__pyx_v_self);
+  __pyx_t_1 = PyArray_HASFIELDS(((PyArrayObject *)__pyx_v_self));
   if (__pyx_t_1) {
 
-    /* "numpy.pxd":289
+    /* "numpy.pxd":286
  *         def __releasebuffer__(ndarray self, Py_buffer* info):
  *             if PyArray_HASFIELDS(self):
  *                 stdlib.free(info.format)             # <<<<<<<<<<<<<<
@@ -4498,11 +4291,11 @@ static void __pyx_pf_5numpy_7ndarray_2__releasebuffer__(PyArrayObject *__pyx_v_s
  *                 stdlib.free(info.strides)
  */
     free(__pyx_v_info->format);
-    goto __pyx_L3;
+    goto __pyx_L5;
   }
-  __pyx_L3:;
+  __pyx_L5:;
 
-  /* "numpy.pxd":290
+  /* "numpy.pxd":287
  *             if PyArray_HASFIELDS(self):
  *                 stdlib.free(info.format)
  *             if sizeof(npy_intp) != sizeof(Py_ssize_t):             # <<<<<<<<<<<<<<
@@ -4512,7 +4305,7 @@ static void __pyx_pf_5numpy_7ndarray_2__releasebuffer__(PyArrayObject *__pyx_v_s
   __pyx_t_1 = ((sizeof(npy_intp)) != (sizeof(Py_ssize_t)));
   if (__pyx_t_1) {
 
-    /* "numpy.pxd":291
+    /* "numpy.pxd":288
  *                 stdlib.free(info.format)
  *             if sizeof(npy_intp) != sizeof(Py_ssize_t):
  *                 stdlib.free(info.strides)             # <<<<<<<<<<<<<<
@@ -4520,14 +4313,14 @@ static void __pyx_pf_5numpy_7ndarray_2__releasebuffer__(PyArrayObject *__pyx_v_s
  * 
  */
     free(__pyx_v_info->strides);
-    goto __pyx_L4;
+    goto __pyx_L6;
   }
-  __pyx_L4:;
+  __pyx_L6:;
 
   __Pyx_RefNannyFinishContext();
 }
 
-/* "numpy.pxd":767
+/* "numpy.pxd":764
  * ctypedef npy_cdouble     complex_t
  * 
  * cdef inline object PyArray_MultiIterNew1(a):             # <<<<<<<<<<<<<<
@@ -4542,9 +4335,9 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew1(PyObject *__
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("PyArray_MultiIterNew1", 0);
+  __Pyx_RefNannySetupContext("PyArray_MultiIterNew1");
 
-  /* "numpy.pxd":768
+  /* "numpy.pxd":765
  * 
  * cdef inline object PyArray_MultiIterNew1(a):
  *     return PyArray_MultiIterNew(1, <void*>a)             # <<<<<<<<<<<<<<
@@ -4552,7 +4345,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew1(PyObject *__
  * cdef inline object PyArray_MultiIterNew2(a, b):
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = PyArray_MultiIterNew(1, ((void *)__pyx_v_a)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 768; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyArray_MultiIterNew(1, ((void *)__pyx_v_a)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 765; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -4570,7 +4363,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew1(PyObject *__
   return __pyx_r;
 }
 
-/* "numpy.pxd":770
+/* "numpy.pxd":767
  *     return PyArray_MultiIterNew(1, <void*>a)
  * 
  * cdef inline object PyArray_MultiIterNew2(a, b):             # <<<<<<<<<<<<<<
@@ -4585,9 +4378,9 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew2(PyObject *__
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("PyArray_MultiIterNew2", 0);
+  __Pyx_RefNannySetupContext("PyArray_MultiIterNew2");
 
-  /* "numpy.pxd":771
+  /* "numpy.pxd":768
  * 
  * cdef inline object PyArray_MultiIterNew2(a, b):
  *     return PyArray_MultiIterNew(2, <void*>a, <void*>b)             # <<<<<<<<<<<<<<
@@ -4595,7 +4388,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew2(PyObject *__
  * cdef inline object PyArray_MultiIterNew3(a, b, c):
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = PyArray_MultiIterNew(2, ((void *)__pyx_v_a), ((void *)__pyx_v_b)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 771; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyArray_MultiIterNew(2, ((void *)__pyx_v_a), ((void *)__pyx_v_b)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 768; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -4613,7 +4406,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew2(PyObject *__
   return __pyx_r;
 }
 
-/* "numpy.pxd":773
+/* "numpy.pxd":770
  *     return PyArray_MultiIterNew(2, <void*>a, <void*>b)
  * 
  * cdef inline object PyArray_MultiIterNew3(a, b, c):             # <<<<<<<<<<<<<<
@@ -4628,9 +4421,9 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew3(PyObject *__
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("PyArray_MultiIterNew3", 0);
+  __Pyx_RefNannySetupContext("PyArray_MultiIterNew3");
 
-  /* "numpy.pxd":774
+  /* "numpy.pxd":771
  * 
  * cdef inline object PyArray_MultiIterNew3(a, b, c):
  *     return PyArray_MultiIterNew(3, <void*>a, <void*>b, <void*> c)             # <<<<<<<<<<<<<<
@@ -4638,7 +4431,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew3(PyObject *__
  * cdef inline object PyArray_MultiIterNew4(a, b, c, d):
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = PyArray_MultiIterNew(3, ((void *)__pyx_v_a), ((void *)__pyx_v_b), ((void *)__pyx_v_c)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 774; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyArray_MultiIterNew(3, ((void *)__pyx_v_a), ((void *)__pyx_v_b), ((void *)__pyx_v_c)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 771; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -4656,7 +4449,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew3(PyObject *__
   return __pyx_r;
 }
 
-/* "numpy.pxd":776
+/* "numpy.pxd":773
  *     return PyArray_MultiIterNew(3, <void*>a, <void*>b, <void*> c)
  * 
  * cdef inline object PyArray_MultiIterNew4(a, b, c, d):             # <<<<<<<<<<<<<<
@@ -4671,9 +4464,9 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew4(PyObject *__
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("PyArray_MultiIterNew4", 0);
+  __Pyx_RefNannySetupContext("PyArray_MultiIterNew4");
 
-  /* "numpy.pxd":777
+  /* "numpy.pxd":774
  * 
  * cdef inline object PyArray_MultiIterNew4(a, b, c, d):
  *     return PyArray_MultiIterNew(4, <void*>a, <void*>b, <void*>c, <void*> d)             # <<<<<<<<<<<<<<
@@ -4681,7 +4474,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew4(PyObject *__
  * cdef inline object PyArray_MultiIterNew5(a, b, c, d, e):
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = PyArray_MultiIterNew(4, ((void *)__pyx_v_a), ((void *)__pyx_v_b), ((void *)__pyx_v_c), ((void *)__pyx_v_d)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 777; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyArray_MultiIterNew(4, ((void *)__pyx_v_a), ((void *)__pyx_v_b), ((void *)__pyx_v_c), ((void *)__pyx_v_d)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 774; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -4699,7 +4492,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew4(PyObject *__
   return __pyx_r;
 }
 
-/* "numpy.pxd":779
+/* "numpy.pxd":776
  *     return PyArray_MultiIterNew(4, <void*>a, <void*>b, <void*>c, <void*> d)
  * 
  * cdef inline object PyArray_MultiIterNew5(a, b, c, d, e):             # <<<<<<<<<<<<<<
@@ -4714,9 +4507,9 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew5(PyObject *__
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("PyArray_MultiIterNew5", 0);
+  __Pyx_RefNannySetupContext("PyArray_MultiIterNew5");
 
-  /* "numpy.pxd":780
+  /* "numpy.pxd":777
  * 
  * cdef inline object PyArray_MultiIterNew5(a, b, c, d, e):
  *     return PyArray_MultiIterNew(5, <void*>a, <void*>b, <void*>c, <void*> d, <void*> e)             # <<<<<<<<<<<<<<
@@ -4724,7 +4517,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew5(PyObject *__
  * cdef inline char* _util_dtypestring(dtype descr, char* f, char* end, int* offset) except NULL:
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = PyArray_MultiIterNew(5, ((void *)__pyx_v_a), ((void *)__pyx_v_b), ((void *)__pyx_v_c), ((void *)__pyx_v_d), ((void *)__pyx_v_e)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 780; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyArray_MultiIterNew(5, ((void *)__pyx_v_a), ((void *)__pyx_v_b), ((void *)__pyx_v_c), ((void *)__pyx_v_d), ((void *)__pyx_v_e)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 777; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -4742,7 +4535,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew5(PyObject *__
   return __pyx_r;
 }
 
-/* "numpy.pxd":782
+/* "numpy.pxd":779
  *     return PyArray_MultiIterNew(5, <void*>a, <void*>b, <void*>c, <void*> d, <void*> e)
  * 
  * cdef inline char* _util_dtypestring(dtype descr, char* f, char* end, int* offset) except NULL:             # <<<<<<<<<<<<<<
@@ -4774,9 +4567,9 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("_util_dtypestring", 0);
+  __Pyx_RefNannySetupContext("_util_dtypestring");
 
-  /* "numpy.pxd":789
+  /* "numpy.pxd":786
  *     cdef int delta_offset
  *     cdef tuple i
  *     cdef int endian_detector = 1             # <<<<<<<<<<<<<<
@@ -4785,7 +4578,7 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
  */
   __pyx_v_endian_detector = 1;
 
-  /* "numpy.pxd":790
+  /* "numpy.pxd":787
  *     cdef tuple i
  *     cdef int endian_detector = 1
  *     cdef bint little_endian = ((<char*>&endian_detector)[0] != 0)             # <<<<<<<<<<<<<<
@@ -4794,7 +4587,7 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
  */
   __pyx_v_little_endian = ((((char *)(&__pyx_v_endian_detector))[0]) != 0);
 
-  /* "numpy.pxd":793
+  /* "numpy.pxd":790
  *     cdef tuple fields
  * 
  *     for childname in descr.names:             # <<<<<<<<<<<<<<
@@ -4802,7 +4595,7 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
  *         child, new_offset = fields
  */
   if (unlikely(((PyObject *)__pyx_v_descr->names) == Py_None)) {
-    PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable"); {__pyx_filename = __pyx_f[1]; __pyx_lineno = 793; __pyx_clineno = __LINE__; goto __pyx_L1_error;} 
+    PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable"); {__pyx_filename = __pyx_f[1]; __pyx_lineno = 790; __pyx_clineno = __LINE__; goto __pyx_L1_error;} 
   }
   __pyx_t_1 = ((PyObject *)__pyx_v_descr->names); __Pyx_INCREF(__pyx_t_1); __pyx_t_2 = 0;
   for (;;) {
@@ -4812,21 +4605,21 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
     __pyx_v_childname = __pyx_t_3;
     __pyx_t_3 = 0;
 
-    /* "numpy.pxd":794
+    /* "numpy.pxd":791
  * 
  *     for childname in descr.names:
  *         fields = descr.fields[childname]             # <<<<<<<<<<<<<<
  *         child, new_offset = fields
  * 
  */
-    __pyx_t_3 = PyObject_GetItem(__pyx_v_descr->fields, __pyx_v_childname); if (!__pyx_t_3) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 794; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = PyObject_GetItem(__pyx_v_descr->fields, __pyx_v_childname); if (!__pyx_t_3) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 791; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_3);
-    if (!(likely(PyTuple_CheckExact(__pyx_t_3))||((__pyx_t_3) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected tuple, got %.200s", Py_TYPE(__pyx_t_3)->tp_name), 0))) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 794; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (!(likely(PyTuple_CheckExact(__pyx_t_3))||((__pyx_t_3) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected tuple, got %.200s", Py_TYPE(__pyx_t_3)->tp_name), 0))) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 791; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_XDECREF(((PyObject *)__pyx_v_fields));
     __pyx_v_fields = ((PyObject*)__pyx_t_3);
     __pyx_t_3 = 0;
 
-    /* "numpy.pxd":795
+    /* "numpy.pxd":792
  *     for childname in descr.names:
  *         fields = descr.fields[childname]
  *         child, new_offset = fields             # <<<<<<<<<<<<<<
@@ -4838,7 +4631,7 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
       if (unlikely(PyTuple_GET_SIZE(sequence) != 2)) {
         if (PyTuple_GET_SIZE(sequence) > 2) __Pyx_RaiseTooManyValuesError(2);
         else __Pyx_RaiseNeedMoreValuesError(PyTuple_GET_SIZE(sequence));
-        {__pyx_filename = __pyx_f[1]; __pyx_lineno = 795; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        {__pyx_filename = __pyx_f[1]; __pyx_lineno = 792; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       }
       __pyx_t_3 = PyTuple_GET_ITEM(sequence, 0); 
       __pyx_t_4 = PyTuple_GET_ITEM(sequence, 1); 
@@ -4846,9 +4639,9 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
       __Pyx_INCREF(__pyx_t_4);
     } else {
       __Pyx_UnpackTupleError(((PyObject *)__pyx_v_fields), 2);
-      {__pyx_filename = __pyx_f[1]; __pyx_lineno = 795; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      {__pyx_filename = __pyx_f[1]; __pyx_lineno = 792; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     }
-    if (!(likely(((__pyx_t_3) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_3, __pyx_ptype_5numpy_dtype))))) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 795; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (!(likely(((__pyx_t_3) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_3, __pyx_ptype_5numpy_dtype))))) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 792; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_XDECREF(((PyObject *)__pyx_v_child));
     __pyx_v_child = ((PyArray_Descr *)__pyx_t_3);
     __pyx_t_3 = 0;
@@ -4856,48 +4649,48 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
     __pyx_v_new_offset = __pyx_t_4;
     __pyx_t_4 = 0;
 
-    /* "numpy.pxd":797
+    /* "numpy.pxd":794
  *         child, new_offset = fields
  * 
  *         if (end - f) - (new_offset - offset[0]) < 15:             # <<<<<<<<<<<<<<
  *             raise RuntimeError(u"Format string allocated too short, see comment in numpy.pxd")
  * 
  */
-    __pyx_t_4 = PyInt_FromLong((__pyx_v_end - __pyx_v_f)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 797; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = PyInt_FromLong((__pyx_v_end - __pyx_v_f)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 794; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_4);
-    __pyx_t_3 = PyInt_FromLong((__pyx_v_offset[0])); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 797; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = PyInt_FromLong((__pyx_v_offset[0])); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 794; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_3);
-    __pyx_t_5 = PyNumber_Subtract(__pyx_v_new_offset, __pyx_t_3); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 797; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = PyNumber_Subtract(__pyx_v_new_offset, __pyx_t_3); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 794; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_5);
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __pyx_t_3 = PyNumber_Subtract(__pyx_t_4, __pyx_t_5); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 797; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = PyNumber_Subtract(__pyx_t_4, __pyx_t_5); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 794; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_3);
     __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
     __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-    __pyx_t_5 = PyObject_RichCompare(__pyx_t_3, __pyx_int_15, Py_LT); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 797; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = PyObject_RichCompare(__pyx_t_3, __pyx_int_15, Py_LT); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 794; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_5);
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 797; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 794; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
     if (__pyx_t_6) {
 
-      /* "numpy.pxd":798
+      /* "numpy.pxd":795
  * 
  *         if (end - f) - (new_offset - offset[0]) < 15:
  *             raise RuntimeError(u"Format string allocated too short, see comment in numpy.pxd")             # <<<<<<<<<<<<<<
  * 
  *         if ((child.byteorder == '>' and little_endian) or
  */
-      __pyx_t_5 = PyObject_Call(__pyx_builtin_RuntimeError, ((PyObject *)__pyx_k_tuple_13), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 798; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyObject_Call(__pyx_builtin_RuntimeError, ((PyObject *)__pyx_k_tuple_13), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 795; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
       __Pyx_Raise(__pyx_t_5, 0, 0, 0);
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      {__pyx_filename = __pyx_f[1]; __pyx_lineno = 798; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      {__pyx_filename = __pyx_f[1]; __pyx_lineno = 795; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       goto __pyx_L5;
     }
     __pyx_L5:;
 
-    /* "numpy.pxd":800
+    /* "numpy.pxd":797
  *             raise RuntimeError(u"Format string allocated too short, see comment in numpy.pxd")
  * 
  *         if ((child.byteorder == '>' and little_endian) or             # <<<<<<<<<<<<<<
@@ -4912,7 +4705,7 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
     }
     if (!__pyx_t_7) {
 
-      /* "numpy.pxd":801
+      /* "numpy.pxd":798
  * 
  *         if ((child.byteorder == '>' and little_endian) or
  *             (child.byteorder == '<' and not little_endian)):             # <<<<<<<<<<<<<<
@@ -4932,23 +4725,23 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
     }
     if (__pyx_t_6) {
 
-      /* "numpy.pxd":802
+      /* "numpy.pxd":799
  *         if ((child.byteorder == '>' and little_endian) or
  *             (child.byteorder == '<' and not little_endian)):
  *             raise ValueError(u"Non-native byte order not supported")             # <<<<<<<<<<<<<<
  *             # One could encode it in the format string and have Cython
  *             # complain instead, BUT: < and > in format strings also imply
  */
-      __pyx_t_5 = PyObject_Call(__pyx_builtin_ValueError, ((PyObject *)__pyx_k_tuple_14), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 802; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyObject_Call(__pyx_builtin_ValueError, ((PyObject *)__pyx_k_tuple_14), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 799; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
       __Pyx_Raise(__pyx_t_5, 0, 0, 0);
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      {__pyx_filename = __pyx_f[1]; __pyx_lineno = 802; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      {__pyx_filename = __pyx_f[1]; __pyx_lineno = 799; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       goto __pyx_L6;
     }
     __pyx_L6:;
 
-    /* "numpy.pxd":812
+    /* "numpy.pxd":809
  * 
  *         # Output padding bytes
  *         while offset[0] < new_offset:             # <<<<<<<<<<<<<<
@@ -4956,16 +4749,16 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
  *             f += 1
  */
     while (1) {
-      __pyx_t_5 = PyInt_FromLong((__pyx_v_offset[0])); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 812; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyInt_FromLong((__pyx_v_offset[0])); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 809; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
-      __pyx_t_3 = PyObject_RichCompare(__pyx_t_5, __pyx_v_new_offset, Py_LT); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 812; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyObject_RichCompare(__pyx_t_5, __pyx_v_new_offset, Py_LT); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 809; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 812; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 809; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
       if (!__pyx_t_6) break;
 
-      /* "numpy.pxd":813
+      /* "numpy.pxd":810
  *         # Output padding bytes
  *         while offset[0] < new_offset:
  *             f[0] = 120 # "x"; pad byte             # <<<<<<<<<<<<<<
@@ -4974,7 +4767,7 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
  */
       (__pyx_v_f[0]) = 120;
 
-      /* "numpy.pxd":814
+      /* "numpy.pxd":811
  *         while offset[0] < new_offset:
  *             f[0] = 120 # "x"; pad byte
  *             f += 1             # <<<<<<<<<<<<<<
@@ -4983,7 +4776,7 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
  */
       __pyx_v_f = (__pyx_v_f + 1);
 
-      /* "numpy.pxd":815
+      /* "numpy.pxd":812
  *             f[0] = 120 # "x"; pad byte
  *             f += 1
  *             offset[0] += 1             # <<<<<<<<<<<<<<
@@ -4994,7 +4787,7 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
       (__pyx_v_offset[__pyx_t_10]) = ((__pyx_v_offset[__pyx_t_10]) + 1);
     }
 
-    /* "numpy.pxd":817
+    /* "numpy.pxd":814
  *             offset[0] += 1
  * 
  *         offset[0] += child.itemsize             # <<<<<<<<<<<<<<
@@ -5004,7 +4797,7 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
     __pyx_t_10 = 0;
     (__pyx_v_offset[__pyx_t_10]) = ((__pyx_v_offset[__pyx_t_10]) + __pyx_v_child->elsize);
 
-    /* "numpy.pxd":819
+    /* "numpy.pxd":816
  *         offset[0] += child.itemsize
  * 
  *         if not PyDataType_HASFIELDS(child):             # <<<<<<<<<<<<<<
@@ -5014,20 +4807,20 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
     __pyx_t_6 = (!PyDataType_HASFIELDS(__pyx_v_child));
     if (__pyx_t_6) {
 
-      /* "numpy.pxd":820
+      /* "numpy.pxd":817
  * 
  *         if not PyDataType_HASFIELDS(child):
  *             t = child.type_num             # <<<<<<<<<<<<<<
  *             if end - f < 5:
  *                 raise RuntimeError(u"Format string allocated too short.")
  */
-      __pyx_t_3 = PyInt_FromLong(__pyx_v_child->type_num); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 820; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyInt_FromLong(__pyx_v_child->type_num); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 817; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_XDECREF(__pyx_v_t);
       __pyx_v_t = __pyx_t_3;
       __pyx_t_3 = 0;
 
-      /* "numpy.pxd":821
+      /* "numpy.pxd":818
  *         if not PyDataType_HASFIELDS(child):
  *             t = child.type_num
  *             if end - f < 5:             # <<<<<<<<<<<<<<
@@ -5037,282 +4830,282 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
       __pyx_t_6 = ((__pyx_v_end - __pyx_v_f) < 5);
       if (__pyx_t_6) {
 
-        /* "numpy.pxd":822
+        /* "numpy.pxd":819
  *             t = child.type_num
  *             if end - f < 5:
  *                 raise RuntimeError(u"Format string allocated too short.")             # <<<<<<<<<<<<<<
  * 
  *             # Until ticket #99 is fixed, use integers to avoid warnings
  */
-        __pyx_t_3 = PyObject_Call(__pyx_builtin_RuntimeError, ((PyObject *)__pyx_k_tuple_16), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 822; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_3 = PyObject_Call(__pyx_builtin_RuntimeError, ((PyObject *)__pyx_k_tuple_16), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 819; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_3);
         __Pyx_Raise(__pyx_t_3, 0, 0, 0);
         __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-        {__pyx_filename = __pyx_f[1]; __pyx_lineno = 822; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        {__pyx_filename = __pyx_f[1]; __pyx_lineno = 819; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         goto __pyx_L10;
       }
       __pyx_L10:;
 
-      /* "numpy.pxd":825
+      /* "numpy.pxd":822
  * 
  *             # Until ticket #99 is fixed, use integers to avoid warnings
  *             if   t == NPY_BYTE:        f[0] =  98 #"b"             # <<<<<<<<<<<<<<
  *             elif t == NPY_UBYTE:       f[0] =  66 #"B"
  *             elif t == NPY_SHORT:       f[0] = 104 #"h"
  */
-      __pyx_t_3 = PyInt_FromLong(NPY_BYTE); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 825; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyInt_FromLong(NPY_BYTE); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 822; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 825; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 822; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 825; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 822; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 98;
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":826
+      /* "numpy.pxd":823
  *             # Until ticket #99 is fixed, use integers to avoid warnings
  *             if   t == NPY_BYTE:        f[0] =  98 #"b"
  *             elif t == NPY_UBYTE:       f[0] =  66 #"B"             # <<<<<<<<<<<<<<
  *             elif t == NPY_SHORT:       f[0] = 104 #"h"
  *             elif t == NPY_USHORT:      f[0] =  72 #"H"
  */
-      __pyx_t_5 = PyInt_FromLong(NPY_UBYTE); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 826; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyInt_FromLong(NPY_UBYTE); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 823; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
-      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 826; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 823; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 826; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 823; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 66;
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":827
+      /* "numpy.pxd":824
  *             if   t == NPY_BYTE:        f[0] =  98 #"b"
  *             elif t == NPY_UBYTE:       f[0] =  66 #"B"
  *             elif t == NPY_SHORT:       f[0] = 104 #"h"             # <<<<<<<<<<<<<<
  *             elif t == NPY_USHORT:      f[0] =  72 #"H"
  *             elif t == NPY_INT:         f[0] = 105 #"i"
  */
-      __pyx_t_3 = PyInt_FromLong(NPY_SHORT); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 827; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyInt_FromLong(NPY_SHORT); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 824; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 827; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 824; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 827; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 824; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 104;
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":828
+      /* "numpy.pxd":825
  *             elif t == NPY_UBYTE:       f[0] =  66 #"B"
  *             elif t == NPY_SHORT:       f[0] = 104 #"h"
  *             elif t == NPY_USHORT:      f[0] =  72 #"H"             # <<<<<<<<<<<<<<
  *             elif t == NPY_INT:         f[0] = 105 #"i"
  *             elif t == NPY_UINT:        f[0] =  73 #"I"
  */
-      __pyx_t_5 = PyInt_FromLong(NPY_USHORT); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 828; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyInt_FromLong(NPY_USHORT); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 825; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
-      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 828; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 825; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 828; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 825; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 72;
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":829
+      /* "numpy.pxd":826
  *             elif t == NPY_SHORT:       f[0] = 104 #"h"
  *             elif t == NPY_USHORT:      f[0] =  72 #"H"
  *             elif t == NPY_INT:         f[0] = 105 #"i"             # <<<<<<<<<<<<<<
  *             elif t == NPY_UINT:        f[0] =  73 #"I"
  *             elif t == NPY_LONG:        f[0] = 108 #"l"
  */
-      __pyx_t_3 = PyInt_FromLong(NPY_INT); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 829; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyInt_FromLong(NPY_INT); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 826; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 829; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 826; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 829; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 826; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 105;
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":830
+      /* "numpy.pxd":827
  *             elif t == NPY_USHORT:      f[0] =  72 #"H"
  *             elif t == NPY_INT:         f[0] = 105 #"i"
  *             elif t == NPY_UINT:        f[0] =  73 #"I"             # <<<<<<<<<<<<<<
  *             elif t == NPY_LONG:        f[0] = 108 #"l"
  *             elif t == NPY_ULONG:       f[0] = 76  #"L"
  */
-      __pyx_t_5 = PyInt_FromLong(NPY_UINT); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 830; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyInt_FromLong(NPY_UINT); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 827; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
-      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 830; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 827; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 830; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 827; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 73;
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":831
+      /* "numpy.pxd":828
  *             elif t == NPY_INT:         f[0] = 105 #"i"
  *             elif t == NPY_UINT:        f[0] =  73 #"I"
  *             elif t == NPY_LONG:        f[0] = 108 #"l"             # <<<<<<<<<<<<<<
  *             elif t == NPY_ULONG:       f[0] = 76  #"L"
  *             elif t == NPY_LONGLONG:    f[0] = 113 #"q"
  */
-      __pyx_t_3 = PyInt_FromLong(NPY_LONG); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 831; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyInt_FromLong(NPY_LONG); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 828; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 831; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 828; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 831; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 828; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 108;
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":832
+      /* "numpy.pxd":829
  *             elif t == NPY_UINT:        f[0] =  73 #"I"
  *             elif t == NPY_LONG:        f[0] = 108 #"l"
  *             elif t == NPY_ULONG:       f[0] = 76  #"L"             # <<<<<<<<<<<<<<
  *             elif t == NPY_LONGLONG:    f[0] = 113 #"q"
  *             elif t == NPY_ULONGLONG:   f[0] = 81  #"Q"
  */
-      __pyx_t_5 = PyInt_FromLong(NPY_ULONG); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 832; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyInt_FromLong(NPY_ULONG); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 829; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
-      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 832; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 829; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 832; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 829; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 76;
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":833
+      /* "numpy.pxd":830
  *             elif t == NPY_LONG:        f[0] = 108 #"l"
  *             elif t == NPY_ULONG:       f[0] = 76  #"L"
  *             elif t == NPY_LONGLONG:    f[0] = 113 #"q"             # <<<<<<<<<<<<<<
  *             elif t == NPY_ULONGLONG:   f[0] = 81  #"Q"
  *             elif t == NPY_FLOAT:       f[0] = 102 #"f"
  */
-      __pyx_t_3 = PyInt_FromLong(NPY_LONGLONG); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 833; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyInt_FromLong(NPY_LONGLONG); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 830; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 833; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 830; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 833; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 830; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 113;
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":834
+      /* "numpy.pxd":831
  *             elif t == NPY_ULONG:       f[0] = 76  #"L"
  *             elif t == NPY_LONGLONG:    f[0] = 113 #"q"
  *             elif t == NPY_ULONGLONG:   f[0] = 81  #"Q"             # <<<<<<<<<<<<<<
  *             elif t == NPY_FLOAT:       f[0] = 102 #"f"
  *             elif t == NPY_DOUBLE:      f[0] = 100 #"d"
  */
-      __pyx_t_5 = PyInt_FromLong(NPY_ULONGLONG); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 834; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyInt_FromLong(NPY_ULONGLONG); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 831; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
-      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 834; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 831; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 834; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 831; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 81;
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":835
+      /* "numpy.pxd":832
  *             elif t == NPY_LONGLONG:    f[0] = 113 #"q"
  *             elif t == NPY_ULONGLONG:   f[0] = 81  #"Q"
  *             elif t == NPY_FLOAT:       f[0] = 102 #"f"             # <<<<<<<<<<<<<<
  *             elif t == NPY_DOUBLE:      f[0] = 100 #"d"
  *             elif t == NPY_LONGDOUBLE:  f[0] = 103 #"g"
  */
-      __pyx_t_3 = PyInt_FromLong(NPY_FLOAT); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 835; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyInt_FromLong(NPY_FLOAT); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 832; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 835; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 832; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 835; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 832; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 102;
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":836
+      /* "numpy.pxd":833
  *             elif t == NPY_ULONGLONG:   f[0] = 81  #"Q"
  *             elif t == NPY_FLOAT:       f[0] = 102 #"f"
  *             elif t == NPY_DOUBLE:      f[0] = 100 #"d"             # <<<<<<<<<<<<<<
  *             elif t == NPY_LONGDOUBLE:  f[0] = 103 #"g"
  *             elif t == NPY_CFLOAT:      f[0] = 90; f[1] = 102; f += 1 # Zf
  */
-      __pyx_t_5 = PyInt_FromLong(NPY_DOUBLE); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 836; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyInt_FromLong(NPY_DOUBLE); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 833; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
-      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 836; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 833; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 836; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 833; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 100;
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":837
+      /* "numpy.pxd":834
  *             elif t == NPY_FLOAT:       f[0] = 102 #"f"
  *             elif t == NPY_DOUBLE:      f[0] = 100 #"d"
  *             elif t == NPY_LONGDOUBLE:  f[0] = 103 #"g"             # <<<<<<<<<<<<<<
  *             elif t == NPY_CFLOAT:      f[0] = 90; f[1] = 102; f += 1 # Zf
  *             elif t == NPY_CDOUBLE:     f[0] = 90; f[1] = 100; f += 1 # Zd
  */
-      __pyx_t_3 = PyInt_FromLong(NPY_LONGDOUBLE); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 837; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyInt_FromLong(NPY_LONGDOUBLE); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 834; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 837; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 834; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 837; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 834; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 103;
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":838
+      /* "numpy.pxd":835
  *             elif t == NPY_DOUBLE:      f[0] = 100 #"d"
  *             elif t == NPY_LONGDOUBLE:  f[0] = 103 #"g"
  *             elif t == NPY_CFLOAT:      f[0] = 90; f[1] = 102; f += 1 # Zf             # <<<<<<<<<<<<<<
  *             elif t == NPY_CDOUBLE:     f[0] = 90; f[1] = 100; f += 1 # Zd
  *             elif t == NPY_CLONGDOUBLE: f[0] = 90; f[1] = 103; f += 1 # Zg
  */
-      __pyx_t_5 = PyInt_FromLong(NPY_CFLOAT); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 838; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyInt_FromLong(NPY_CFLOAT); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 835; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
-      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 838; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 835; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 838; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 835; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 90;
@@ -5321,19 +5114,19 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":839
+      /* "numpy.pxd":836
  *             elif t == NPY_LONGDOUBLE:  f[0] = 103 #"g"
  *             elif t == NPY_CFLOAT:      f[0] = 90; f[1] = 102; f += 1 # Zf
  *             elif t == NPY_CDOUBLE:     f[0] = 90; f[1] = 100; f += 1 # Zd             # <<<<<<<<<<<<<<
  *             elif t == NPY_CLONGDOUBLE: f[0] = 90; f[1] = 103; f += 1 # Zg
  *             elif t == NPY_OBJECT:      f[0] = 79 #"O"
  */
-      __pyx_t_3 = PyInt_FromLong(NPY_CDOUBLE); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 839; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyInt_FromLong(NPY_CDOUBLE); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 836; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 839; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 836; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 839; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 836; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 90;
@@ -5342,19 +5135,19 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":840
+      /* "numpy.pxd":837
  *             elif t == NPY_CFLOAT:      f[0] = 90; f[1] = 102; f += 1 # Zf
  *             elif t == NPY_CDOUBLE:     f[0] = 90; f[1] = 100; f += 1 # Zd
  *             elif t == NPY_CLONGDOUBLE: f[0] = 90; f[1] = 103; f += 1 # Zg             # <<<<<<<<<<<<<<
  *             elif t == NPY_OBJECT:      f[0] = 79 #"O"
  *             else:
  */
-      __pyx_t_5 = PyInt_FromLong(NPY_CLONGDOUBLE); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 840; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyInt_FromLong(NPY_CLONGDOUBLE); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 837; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
-      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 840; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 837; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 840; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 837; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 90;
@@ -5363,19 +5156,19 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":841
+      /* "numpy.pxd":838
  *             elif t == NPY_CDOUBLE:     f[0] = 90; f[1] = 100; f += 1 # Zd
  *             elif t == NPY_CLONGDOUBLE: f[0] = 90; f[1] = 103; f += 1 # Zg
  *             elif t == NPY_OBJECT:      f[0] = 79 #"O"             # <<<<<<<<<<<<<<
  *             else:
  *                 raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t)
  */
-      __pyx_t_3 = PyInt_FromLong(NPY_OBJECT); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 841; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyInt_FromLong(NPY_OBJECT); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 838; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 841; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 838; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 841; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 838; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 79;
@@ -5383,30 +5176,30 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
       }
       /*else*/ {
 
-        /* "numpy.pxd":843
+        /* "numpy.pxd":840
  *             elif t == NPY_OBJECT:      f[0] = 79 #"O"
  *             else:
  *                 raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t)             # <<<<<<<<<<<<<<
  *             f += 1
  *         else:
  */
-        __pyx_t_5 = PyNumber_Remainder(((PyObject *)__pyx_kp_u_11), __pyx_v_t); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 843; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_5 = PyNumber_Remainder(((PyObject *)__pyx_kp_u_11), __pyx_v_t); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 840; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(((PyObject *)__pyx_t_5));
-        __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 843; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-        __Pyx_GOTREF(__pyx_t_3);
+        __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 840; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __Pyx_GOTREF(((PyObject *)__pyx_t_3));
         PyTuple_SET_ITEM(__pyx_t_3, 0, ((PyObject *)__pyx_t_5));
         __Pyx_GIVEREF(((PyObject *)__pyx_t_5));
         __pyx_t_5 = 0;
-        __pyx_t_5 = PyObject_Call(__pyx_builtin_ValueError, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 843; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_5 = PyObject_Call(__pyx_builtin_ValueError, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 840; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_5);
         __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
         __Pyx_Raise(__pyx_t_5, 0, 0, 0);
         __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-        {__pyx_filename = __pyx_f[1]; __pyx_lineno = 843; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        {__pyx_filename = __pyx_f[1]; __pyx_lineno = 840; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       }
       __pyx_L11:;
 
-      /* "numpy.pxd":844
+      /* "numpy.pxd":841
  *             else:
  *                 raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t)
  *             f += 1             # <<<<<<<<<<<<<<
@@ -5418,21 +5211,21 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
     }
     /*else*/ {
 
-      /* "numpy.pxd":848
+      /* "numpy.pxd":845
  *             # Cython ignores struct boundary information ("T{...}"),
  *             # so don't output it
  *             f = _util_dtypestring(child, f, end, offset)             # <<<<<<<<<<<<<<
  *     return f
  * 
  */
-      __pyx_t_11 = __pyx_f_5numpy__util_dtypestring(__pyx_v_child, __pyx_v_f, __pyx_v_end, __pyx_v_offset); if (unlikely(__pyx_t_11 == NULL)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 848; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_11 = __pyx_f_5numpy__util_dtypestring(__pyx_v_child, __pyx_v_f, __pyx_v_end, __pyx_v_offset); if (unlikely(__pyx_t_11 == NULL)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 845; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __pyx_v_f = __pyx_t_11;
     }
     __pyx_L9:;
   }
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "numpy.pxd":849
+  /* "numpy.pxd":846
  *             # so don't output it
  *             f = _util_dtypestring(child, f, end, offset)
  *     return f             # <<<<<<<<<<<<<<
@@ -5461,7 +5254,7 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
   return __pyx_r;
 }
 
-/* "numpy.pxd":964
+/* "numpy.pxd":961
  * 
  * 
  * cdef inline void set_array_base(ndarray arr, object base):             # <<<<<<<<<<<<<<
@@ -5473,9 +5266,9 @@ static CYTHON_INLINE void __pyx_f_5numpy_set_array_base(PyArrayObject *__pyx_v_a
   PyObject *__pyx_v_baseptr;
   __Pyx_RefNannyDeclarations
   int __pyx_t_1;
-  __Pyx_RefNannySetupContext("set_array_base", 0);
+  __Pyx_RefNannySetupContext("set_array_base");
 
-  /* "numpy.pxd":966
+  /* "numpy.pxd":963
  * cdef inline void set_array_base(ndarray arr, object base):
  *      cdef PyObject* baseptr
  *      if base is None:             # <<<<<<<<<<<<<<
@@ -5485,7 +5278,7 @@ static CYTHON_INLINE void __pyx_f_5numpy_set_array_base(PyArrayObject *__pyx_v_a
   __pyx_t_1 = (__pyx_v_base == Py_None);
   if (__pyx_t_1) {
 
-    /* "numpy.pxd":967
+    /* "numpy.pxd":964
  *      cdef PyObject* baseptr
  *      if base is None:
  *          baseptr = NULL             # <<<<<<<<<<<<<<
@@ -5497,7 +5290,7 @@ static CYTHON_INLINE void __pyx_f_5numpy_set_array_base(PyArrayObject *__pyx_v_a
   }
   /*else*/ {
 
-    /* "numpy.pxd":969
+    /* "numpy.pxd":966
  *          baseptr = NULL
  *      else:
  *          Py_INCREF(base) # important to do this before decref below!             # <<<<<<<<<<<<<<
@@ -5506,7 +5299,7 @@ static CYTHON_INLINE void __pyx_f_5numpy_set_array_base(PyArrayObject *__pyx_v_a
  */
     Py_INCREF(__pyx_v_base);
 
-    /* "numpy.pxd":970
+    /* "numpy.pxd":967
  *      else:
  *          Py_INCREF(base) # important to do this before decref below!
  *          baseptr = <PyObject*>base             # <<<<<<<<<<<<<<
@@ -5517,7 +5310,7 @@ static CYTHON_INLINE void __pyx_f_5numpy_set_array_base(PyArrayObject *__pyx_v_a
   }
   __pyx_L3:;
 
-  /* "numpy.pxd":971
+  /* "numpy.pxd":968
  *          Py_INCREF(base) # important to do this before decref below!
  *          baseptr = <PyObject*>base
  *      Py_XDECREF(arr.base)             # <<<<<<<<<<<<<<
@@ -5526,7 +5319,7 @@ static CYTHON_INLINE void __pyx_f_5numpy_set_array_base(PyArrayObject *__pyx_v_a
  */
   Py_XDECREF(__pyx_v_arr->base);
 
-  /* "numpy.pxd":972
+  /* "numpy.pxd":969
  *          baseptr = <PyObject*>base
  *      Py_XDECREF(arr.base)
  *      arr.base = baseptr             # <<<<<<<<<<<<<<
@@ -5538,7 +5331,7 @@ static CYTHON_INLINE void __pyx_f_5numpy_set_array_base(PyArrayObject *__pyx_v_a
   __Pyx_RefNannyFinishContext();
 }
 
-/* "numpy.pxd":974
+/* "numpy.pxd":971
  *      arr.base = baseptr
  * 
  * cdef inline object get_array_base(ndarray arr):             # <<<<<<<<<<<<<<
@@ -5550,9 +5343,9 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_get_array_base(PyArrayObject *__py
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   int __pyx_t_1;
-  __Pyx_RefNannySetupContext("get_array_base", 0);
+  __Pyx_RefNannySetupContext("get_array_base");
 
-  /* "numpy.pxd":975
+  /* "numpy.pxd":972
  * 
  * cdef inline object get_array_base(ndarray arr):
  *     if arr.base is NULL:             # <<<<<<<<<<<<<<
@@ -5562,7 +5355,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_get_array_base(PyArrayObject *__py
   __pyx_t_1 = (__pyx_v_arr->base == NULL);
   if (__pyx_t_1) {
 
-    /* "numpy.pxd":976
+    /* "numpy.pxd":973
  * cdef inline object get_array_base(ndarray arr):
  *     if arr.base is NULL:
  *         return None             # <<<<<<<<<<<<<<
@@ -5577,7 +5370,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_get_array_base(PyArrayObject *__py
   }
   /*else*/ {
 
-    /* "numpy.pxd":978
+    /* "numpy.pxd":975
  *         return None
  *     else:
  *         return <object>arr.base             # <<<<<<<<<<<<<<
@@ -5619,11 +5412,10 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = {
   {&__pyx_kp_u_11, __pyx_k_11, sizeof(__pyx_k_11), 0, 1, 0, 0},
   {&__pyx_kp_u_12, __pyx_k_12, sizeof(__pyx_k_12), 0, 1, 0, 0},
   {&__pyx_kp_u_15, __pyx_k_15, sizeof(__pyx_k_15), 0, 1, 0, 0},
+  {&__pyx_n_s_17, __pyx_k_17, sizeof(__pyx_k_17), 0, 0, 1, 1},
+  {&__pyx_n_s_18, __pyx_k_18, sizeof(__pyx_k_18), 0, 0, 1, 1},
   {&__pyx_n_s_19, __pyx_k_19, sizeof(__pyx_k_19), 0, 0, 1, 1},
-  {&__pyx_kp_s_20, __pyx_k_20, sizeof(__pyx_k_20), 0, 0, 1, 0},
-  {&__pyx_n_s_21, __pyx_k_21, sizeof(__pyx_k_21), 0, 0, 1, 1},
-  {&__pyx_n_s_24, __pyx_k_24, sizeof(__pyx_k_24), 0, 0, 1, 1},
-  {&__pyx_n_s_27, __pyx_k_27, sizeof(__pyx_k_27), 0, 0, 1, 1},
+  {&__pyx_n_s_20, __pyx_k_20, sizeof(__pyx_k_20), 0, 0, 1, 1},
   {&__pyx_kp_u_5, __pyx_k_5, sizeof(__pyx_k_5), 0, 1, 0, 0},
   {&__pyx_kp_u_7, __pyx_k_7, sizeof(__pyx_k_7), 0, 1, 0, 0},
   {&__pyx_kp_u_9, __pyx_k_9, sizeof(__pyx_k_9), 0, 1, 0, 0},
@@ -5632,47 +5424,20 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = {
   {&__pyx_n_s__ValueError, __pyx_k__ValueError, sizeof(__pyx_k__ValueError), 0, 0, 1, 1},
   {&__pyx_n_s____main__, __pyx_k____main__, sizeof(__pyx_k____main__), 0, 0, 1, 1},
   {&__pyx_n_s____test__, __pyx_k____test__, sizeof(__pyx_k____test__), 0, 0, 1, 1},
-  {&__pyx_n_s__bot, __pyx_k__bot, sizeof(__pyx_k__bot), 0, 0, 1, 1},
-  {&__pyx_n_s__conv, __pyx_k__conv, sizeof(__pyx_k__conv), 0, 0, 1, 1},
   {&__pyx_n_s__dtype, __pyx_k__dtype, sizeof(__pyx_k__dtype), 0, 0, 1, 1},
   {&__pyx_n_s__f, __pyx_k__f, sizeof(__pyx_k__f), 0, 0, 1, 1},
-  {&__pyx_n_s__fixed, __pyx_k__fixed, sizeof(__pyx_k__fixed), 0, 0, 1, 1},
   {&__pyx_n_s__float, __pyx_k__float, sizeof(__pyx_k__float), 0, 0, 1, 1},
   {&__pyx_n_s__g, __pyx_k__g, sizeof(__pyx_k__g), 0, 0, 1, 1},
-  {&__pyx_n_s__i, __pyx_k__i, sizeof(__pyx_k__i), 0, 0, 1, 1},
-  {&__pyx_n_s__ii, __pyx_k__ii, sizeof(__pyx_k__ii), 0, 0, 1, 1},
-  {&__pyx_n_s__iimax, __pyx_k__iimax, sizeof(__pyx_k__iimax), 0, 0, 1, 1},
-  {&__pyx_n_s__iimin, __pyx_k__iimin, sizeof(__pyx_k__iimin), 0, 0, 1, 1},
-  {&__pyx_n_s__j, __pyx_k__j, sizeof(__pyx_k__j), 0, 0, 1, 1},
-  {&__pyx_n_s__jj, __pyx_k__jj, sizeof(__pyx_k__jj), 0, 0, 1, 1},
-  {&__pyx_n_s__jjmax, __pyx_k__jjmax, sizeof(__pyx_k__jjmax), 0, 0, 1, 1},
-  {&__pyx_n_s__jjmin, __pyx_k__jjmin, sizeof(__pyx_k__jjmin), 0, 0, 1, 1},
-  {&__pyx_n_s__k, __pyx_k__k, sizeof(__pyx_k__k), 0, 0, 1, 1},
-  {&__pyx_n_s__ker, __pyx_k__ker, sizeof(__pyx_k__ker), 0, 0, 1, 1},
-  {&__pyx_n_s__kk, __pyx_k__kk, sizeof(__pyx_k__kk), 0, 0, 1, 1},
-  {&__pyx_n_s__kkmax, __pyx_k__kkmax, sizeof(__pyx_k__kkmax), 0, 0, 1, 1},
-  {&__pyx_n_s__kkmin, __pyx_k__kkmin, sizeof(__pyx_k__kkmin), 0, 0, 1, 1},
-  {&__pyx_n_s__nkx, __pyx_k__nkx, sizeof(__pyx_k__nkx), 0, 0, 1, 1},
-  {&__pyx_n_s__nky, __pyx_k__nky, sizeof(__pyx_k__nky), 0, 0, 1, 1},
-  {&__pyx_n_s__nkz, __pyx_k__nkz, sizeof(__pyx_k__nkz), 0, 0, 1, 1},
   {&__pyx_n_s__np, __pyx_k__np, sizeof(__pyx_k__np), 0, 0, 1, 1},
   {&__pyx_n_s__numpy, __pyx_k__numpy, sizeof(__pyx_k__numpy), 0, 0, 1, 1},
-  {&__pyx_n_s__nx, __pyx_k__nx, sizeof(__pyx_k__nx), 0, 0, 1, 1},
-  {&__pyx_n_s__ny, __pyx_k__ny, sizeof(__pyx_k__ny), 0, 0, 1, 1},
-  {&__pyx_n_s__nz, __pyx_k__nz, sizeof(__pyx_k__nz), 0, 0, 1, 1},
   {&__pyx_n_s__range, __pyx_k__range, sizeof(__pyx_k__range), 0, 0, 1, 1},
-  {&__pyx_n_s__top, __pyx_k__top, sizeof(__pyx_k__top), 0, 0, 1, 1},
-  {&__pyx_n_s__val, __pyx_k__val, sizeof(__pyx_k__val), 0, 0, 1, 1},
-  {&__pyx_n_s__wkx, __pyx_k__wkx, sizeof(__pyx_k__wkx), 0, 0, 1, 1},
-  {&__pyx_n_s__wky, __pyx_k__wky, sizeof(__pyx_k__wky), 0, 0, 1, 1},
-  {&__pyx_n_s__wkz, __pyx_k__wkz, sizeof(__pyx_k__wkz), 0, 0, 1, 1},
   {&__pyx_n_s__zeros, __pyx_k__zeros, sizeof(__pyx_k__zeros), 0, 0, 1, 1},
   {0, 0, 0, 0, 0, 0, 0}
 };
 static int __Pyx_InitCachedBuiltins(void) {
   __pyx_builtin_ValueError = __Pyx_GetName(__pyx_b, __pyx_n_s__ValueError); if (!__pyx_builtin_ValueError) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 19; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_builtin_range = __Pyx_GetName(__pyx_b, __pyx_n_s__range); if (!__pyx_builtin_range) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 40; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_builtin_RuntimeError = __Pyx_GetName(__pyx_b, __pyx_n_s__RuntimeError); if (!__pyx_builtin_RuntimeError) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 798; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_builtin_RuntimeError = __Pyx_GetName(__pyx_b, __pyx_n_s__RuntimeError); if (!__pyx_builtin_RuntimeError) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 795; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   return 0;
   __pyx_L1_error:;
   return -1;
@@ -5680,7 +5445,7 @@ static int __Pyx_InitCachedBuiltins(void) {
 
 static int __Pyx_InitCachedConstants(void) {
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__Pyx_InitCachedConstants", 0);
+  __Pyx_RefNannySetupContext("__Pyx_InitCachedConstants");
 
   /* "astropy/nddata/convolution/boundary_none.pyx":19
  * 
@@ -5690,7 +5455,7 @@ static int __Pyx_InitCachedConstants(void) {
  *     assert f.dtype == DTYPE and g.dtype == DTYPE
  */
   __pyx_k_tuple_2 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 19; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_2);
+  __Pyx_GOTREF(((PyObject *)__pyx_k_tuple_2));
   __Pyx_INCREF(((PyObject *)__pyx_kp_s_1));
   PyTuple_SET_ITEM(__pyx_k_tuple_2, 0, ((PyObject *)__pyx_kp_s_1));
   __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_1));
@@ -5704,7 +5469,7 @@ static int __Pyx_InitCachedConstants(void) {
  *     assert f.dtype == DTYPE and g.dtype == DTYPE
  */
   __pyx_k_tuple_3 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 83; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_3);
+  __Pyx_GOTREF(((PyObject *)__pyx_k_tuple_3));
   __Pyx_INCREF(((PyObject *)__pyx_kp_s_1));
   PyTuple_SET_ITEM(__pyx_k_tuple_3, 0, ((PyObject *)__pyx_kp_s_1));
   __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_1));
@@ -5718,329 +5483,95 @@ static int __Pyx_InitCachedConstants(void) {
  *     assert f.dtype == DTYPE and g.dtype == DTYPE
  */
   __pyx_k_tuple_4 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 156; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_4);
+  __Pyx_GOTREF(((PyObject *)__pyx_k_tuple_4));
   __Pyx_INCREF(((PyObject *)__pyx_kp_s_1));
   PyTuple_SET_ITEM(__pyx_k_tuple_4, 0, ((PyObject *)__pyx_kp_s_1));
   __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_1));
   __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_4));
 
-  /* "numpy.pxd":214
+  /* "numpy.pxd":211
  *             if ((flags & pybuf.PyBUF_C_CONTIGUOUS == pybuf.PyBUF_C_CONTIGUOUS)
  *                 and not PyArray_CHKFLAGS(self, NPY_C_CONTIGUOUS)):
  *                 raise ValueError(u"ndarray is not C contiguous")             # <<<<<<<<<<<<<<
  * 
  *             if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS)
  */
-  __pyx_k_tuple_6 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_6)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 214; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_6);
+  __pyx_k_tuple_6 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_6)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 211; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_k_tuple_6));
   __Pyx_INCREF(((PyObject *)__pyx_kp_u_5));
   PyTuple_SET_ITEM(__pyx_k_tuple_6, 0, ((PyObject *)__pyx_kp_u_5));
   __Pyx_GIVEREF(((PyObject *)__pyx_kp_u_5));
   __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_6));
 
-  /* "numpy.pxd":218
+  /* "numpy.pxd":215
  *             if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS)
  *                 and not PyArray_CHKFLAGS(self, NPY_F_CONTIGUOUS)):
  *                 raise ValueError(u"ndarray is not Fortran contiguous")             # <<<<<<<<<<<<<<
  * 
  *             info.buf = PyArray_DATA(self)
  */
-  __pyx_k_tuple_8 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_8)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 218; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_8);
+  __pyx_k_tuple_8 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_8)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 215; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_k_tuple_8));
   __Pyx_INCREF(((PyObject *)__pyx_kp_u_7));
   PyTuple_SET_ITEM(__pyx_k_tuple_8, 0, ((PyObject *)__pyx_kp_u_7));
   __Pyx_GIVEREF(((PyObject *)__pyx_kp_u_7));
   __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_8));
 
-  /* "numpy.pxd":256
+  /* "numpy.pxd":253
  *                 if ((descr.byteorder == '>' and little_endian) or
  *                     (descr.byteorder == '<' and not little_endian)):
  *                     raise ValueError(u"Non-native byte order not supported")             # <<<<<<<<<<<<<<
  *                 if   t == NPY_BYTE:        f = "b"
  *                 elif t == NPY_UBYTE:       f = "B"
  */
-  __pyx_k_tuple_10 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_10)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 256; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_10);
+  __pyx_k_tuple_10 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_10)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 253; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_k_tuple_10));
   __Pyx_INCREF(((PyObject *)__pyx_kp_u_9));
   PyTuple_SET_ITEM(__pyx_k_tuple_10, 0, ((PyObject *)__pyx_kp_u_9));
   __Pyx_GIVEREF(((PyObject *)__pyx_kp_u_9));
   __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_10));
 
-  /* "numpy.pxd":798
+  /* "numpy.pxd":795
  * 
  *         if (end - f) - (new_offset - offset[0]) < 15:
  *             raise RuntimeError(u"Format string allocated too short, see comment in numpy.pxd")             # <<<<<<<<<<<<<<
  * 
  *         if ((child.byteorder == '>' and little_endian) or
  */
-  __pyx_k_tuple_13 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_13)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 798; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_13);
+  __pyx_k_tuple_13 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_13)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 795; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_k_tuple_13));
   __Pyx_INCREF(((PyObject *)__pyx_kp_u_12));
   PyTuple_SET_ITEM(__pyx_k_tuple_13, 0, ((PyObject *)__pyx_kp_u_12));
   __Pyx_GIVEREF(((PyObject *)__pyx_kp_u_12));
   __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_13));
 
-  /* "numpy.pxd":802
+  /* "numpy.pxd":799
  *         if ((child.byteorder == '>' and little_endian) or
  *             (child.byteorder == '<' and not little_endian)):
  *             raise ValueError(u"Non-native byte order not supported")             # <<<<<<<<<<<<<<
  *             # One could encode it in the format string and have Cython
  *             # complain instead, BUT: < and > in format strings also imply
  */
-  __pyx_k_tuple_14 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_14)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 802; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_14);
+  __pyx_k_tuple_14 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_14)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 799; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_k_tuple_14));
   __Pyx_INCREF(((PyObject *)__pyx_kp_u_9));
   PyTuple_SET_ITEM(__pyx_k_tuple_14, 0, ((PyObject *)__pyx_kp_u_9));
   __Pyx_GIVEREF(((PyObject *)__pyx_kp_u_9));
   __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_14));
 
-  /* "numpy.pxd":822
+  /* "numpy.pxd":819
  *             t = child.type_num
  *             if end - f < 5:
  *                 raise RuntimeError(u"Format string allocated too short.")             # <<<<<<<<<<<<<<
  * 
  *             # Until ticket #99 is fixed, use integers to avoid warnings
  */
-  __pyx_k_tuple_16 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_16)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 822; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_16);
+  __pyx_k_tuple_16 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_16)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 819; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_k_tuple_16));
   __Pyx_INCREF(((PyObject *)__pyx_kp_u_15));
   PyTuple_SET_ITEM(__pyx_k_tuple_16, 0, ((PyObject *)__pyx_kp_u_15));
   __Pyx_GIVEREF(((PyObject *)__pyx_kp_u_15));
   __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_16));
-
-  /* "astropy/nddata/convolution/boundary_none.pyx":15
- * 
- * @cython.boundscheck(False)  # turn off bounds-checking for entire function
- * def convolve1d_boundary_none(np.ndarray[DTYPE_t, ndim=1] f,             # <<<<<<<<<<<<<<
- *                              np.ndarray[DTYPE_t, ndim=1] g):
- * 
- */
-  __pyx_k_tuple_17 = PyTuple_New(15); if (unlikely(!__pyx_k_tuple_17)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_17);
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__f));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 0, ((PyObject *)__pyx_n_s__f));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__f));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__g));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 1, ((PyObject *)__pyx_n_s__g));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__g));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__nx));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 2, ((PyObject *)__pyx_n_s__nx));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__nx));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__nkx));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 3, ((PyObject *)__pyx_n_s__nkx));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__nkx));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__wkx));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 4, ((PyObject *)__pyx_n_s__wkx));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__wkx));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__fixed));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 5, ((PyObject *)__pyx_n_s__fixed));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__fixed));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__conv));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 6, ((PyObject *)__pyx_n_s__conv));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__conv));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__i));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 7, ((PyObject *)__pyx_n_s__i));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__i));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__ii));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 8, ((PyObject *)__pyx_n_s__ii));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__ii));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__iimin));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 9, ((PyObject *)__pyx_n_s__iimin));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__iimin));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__iimax));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 10, ((PyObject *)__pyx_n_s__iimax));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__iimax));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__top));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 11, ((PyObject *)__pyx_n_s__top));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__top));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__bot));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 12, ((PyObject *)__pyx_n_s__bot));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__bot));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__ker));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 13, ((PyObject *)__pyx_n_s__ker));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__ker));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__val));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 14, ((PyObject *)__pyx_n_s__val));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__val));
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_17));
-  __pyx_k_codeobj_18 = (PyObject*)__Pyx_PyCode_New(2, 0, 15, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_k_tuple_17, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_20, __pyx_n_s_19, 15, __pyx_empty_bytes); if (unlikely(!__pyx_k_codeobj_18)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-
-  /* "astropy/nddata/convolution/boundary_none.pyx":79
- * 
- * @cython.boundscheck(False)  # turn off bounds-checking for entire function
- * def convolve2d_boundary_none(np.ndarray[DTYPE_t, ndim=2] f,             # <<<<<<<<<<<<<<
- *                              np.ndarray[DTYPE_t, ndim=2] g):
- * 
- */
-  __pyx_k_tuple_22 = PyTuple_New(22); if (unlikely(!__pyx_k_tuple_22)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 79; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_22);
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__f));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 0, ((PyObject *)__pyx_n_s__f));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__f));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__g));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 1, ((PyObject *)__pyx_n_s__g));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__g));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__nx));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 2, ((PyObject *)__pyx_n_s__nx));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__nx));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__ny));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 3, ((PyObject *)__pyx_n_s__ny));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__ny));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__nkx));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 4, ((PyObject *)__pyx_n_s__nkx));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__nkx));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__nky));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 5, ((PyObject *)__pyx_n_s__nky));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__nky));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__wkx));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 6, ((PyObject *)__pyx_n_s__wkx));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__wkx));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__wky));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 7, ((PyObject *)__pyx_n_s__wky));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__wky));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__fixed));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 8, ((PyObject *)__pyx_n_s__fixed));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__fixed));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__conv));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 9, ((PyObject *)__pyx_n_s__conv));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__conv));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__i));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 10, ((PyObject *)__pyx_n_s__i));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__i));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__j));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 11, ((PyObject *)__pyx_n_s__j));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__j));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__ii));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 12, ((PyObject *)__pyx_n_s__ii));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__ii));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__jj));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 13, ((PyObject *)__pyx_n_s__jj));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__jj));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__iimin));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 14, ((PyObject *)__pyx_n_s__iimin));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__iimin));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__iimax));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 15, ((PyObject *)__pyx_n_s__iimax));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__iimax));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__jjmin));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 16, ((PyObject *)__pyx_n_s__jjmin));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__jjmin));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__jjmax));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 17, ((PyObject *)__pyx_n_s__jjmax));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__jjmax));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__top));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 18, ((PyObject *)__pyx_n_s__top));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__top));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__bot));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 19, ((PyObject *)__pyx_n_s__bot));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__bot));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__ker));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 20, ((PyObject *)__pyx_n_s__ker));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__ker));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__val));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 21, ((PyObject *)__pyx_n_s__val));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__val));
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_22));
-  __pyx_k_codeobj_23 = (PyObject*)__Pyx_PyCode_New(2, 0, 22, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_k_tuple_22, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_20, __pyx_n_s_24, 79, __pyx_empty_bytes); if (unlikely(!__pyx_k_codeobj_23)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 79; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-
-  /* "astropy/nddata/convolution/boundary_none.pyx":152
- * 
- * @cython.boundscheck(False)  # turn off bounds-checking for entire function
- * def convolve3d_boundary_none(np.ndarray[DTYPE_t, ndim=3] f,             # <<<<<<<<<<<<<<
- *                              np.ndarray[DTYPE_t, ndim=3] g):
- * 
- */
-  __pyx_k_tuple_25 = PyTuple_New(29); if (unlikely(!__pyx_k_tuple_25)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 152; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_25);
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__f));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 0, ((PyObject *)__pyx_n_s__f));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__f));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__g));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 1, ((PyObject *)__pyx_n_s__g));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__g));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__nx));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 2, ((PyObject *)__pyx_n_s__nx));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__nx));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__ny));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 3, ((PyObject *)__pyx_n_s__ny));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__ny));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__nz));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 4, ((PyObject *)__pyx_n_s__nz));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__nz));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__nkx));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 5, ((PyObject *)__pyx_n_s__nkx));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__nkx));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__nky));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 6, ((PyObject *)__pyx_n_s__nky));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__nky));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__nkz));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 7, ((PyObject *)__pyx_n_s__nkz));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__nkz));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__wkx));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 8, ((PyObject *)__pyx_n_s__wkx));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__wkx));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__wky));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 9, ((PyObject *)__pyx_n_s__wky));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__wky));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__wkz));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 10, ((PyObject *)__pyx_n_s__wkz));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__wkz));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__fixed));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 11, ((PyObject *)__pyx_n_s__fixed));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__fixed));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__conv));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 12, ((PyObject *)__pyx_n_s__conv));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__conv));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__i));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 13, ((PyObject *)__pyx_n_s__i));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__i));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__j));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 14, ((PyObject *)__pyx_n_s__j));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__j));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__k));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 15, ((PyObject *)__pyx_n_s__k));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__k));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__ii));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 16, ((PyObject *)__pyx_n_s__ii));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__ii));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__jj));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 17, ((PyObject *)__pyx_n_s__jj));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__jj));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__kk));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 18, ((PyObject *)__pyx_n_s__kk));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__kk));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__iimin));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 19, ((PyObject *)__pyx_n_s__iimin));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__iimin));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__iimax));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 20, ((PyObject *)__pyx_n_s__iimax));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__iimax));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__jjmin));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 21, ((PyObject *)__pyx_n_s__jjmin));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__jjmin));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__jjmax));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 22, ((PyObject *)__pyx_n_s__jjmax));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__jjmax));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__kkmin));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 23, ((PyObject *)__pyx_n_s__kkmin));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__kkmin));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__kkmax));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 24, ((PyObject *)__pyx_n_s__kkmax));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__kkmax));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__top));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 25, ((PyObject *)__pyx_n_s__top));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__top));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__bot));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 26, ((PyObject *)__pyx_n_s__bot));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__bot));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__ker));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 27, ((PyObject *)__pyx_n_s__ker));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__ker));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__val));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 28, ((PyObject *)__pyx_n_s__val));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__val));
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_25));
-  __pyx_k_codeobj_26 = (PyObject*)__Pyx_PyCode_New(2, 0, 29, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_k_tuple_25, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_20, __pyx_n_s_27, 152, __pyx_empty_bytes); if (unlikely(!__pyx_k_codeobj_26)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 152; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_RefNannyFinishContext();
   return 0;
   __pyx_L1_error:;
@@ -6076,18 +5607,12 @@ PyMODINIT_FUNC PyInit_boundary_none(void)
           Py_FatalError("failed to import 'refnanny' module");
   }
   #endif
-  __Pyx_RefNannySetupContext("PyMODINIT_FUNC PyInit_boundary_none(void)", 0);
+  __Pyx_RefNannySetupContext("PyMODINIT_FUNC PyInit_boundary_none(void)");
   if ( __Pyx_check_binary_version() < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_empty_tuple = PyTuple_New(0); if (unlikely(!__pyx_empty_tuple)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_empty_bytes = PyBytes_FromStringAndSize("", 0); if (unlikely(!__pyx_empty_bytes)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  #ifdef __Pyx_CyFunction_USED
-  if (__Pyx_CyFunction_init() < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  #endif
-  #ifdef __Pyx_FusedFunction_USED
-  if (__pyx_FusedFunction_init() < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  #endif
-  #ifdef __Pyx_Generator_USED
-  if (__pyx_Generator_init() < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  #ifdef __pyx_binding_PyCFunctionType_USED
+  if (__pyx_binding_PyCFunctionType_init() < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   #endif
   /*--- Library function declarations ---*/
   /*--- Threads initialization code ---*/
@@ -6123,11 +5648,11 @@ PyMODINIT_FUNC PyInit_boundary_none(void)
   /*--- Function export code ---*/
   /*--- Type init code ---*/
   /*--- Type import code ---*/
-  __pyx_ptype_5numpy_dtype = __Pyx_ImportType("numpy", "dtype", sizeof(PyArray_Descr), 0); if (unlikely(!__pyx_ptype_5numpy_dtype)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 154; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_ptype_5numpy_flatiter = __Pyx_ImportType("numpy", "flatiter", sizeof(PyArrayIterObject), 0); if (unlikely(!__pyx_ptype_5numpy_flatiter)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 164; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_ptype_5numpy_broadcast = __Pyx_ImportType("numpy", "broadcast", sizeof(PyArrayMultiIterObject), 0); if (unlikely(!__pyx_ptype_5numpy_broadcast)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 168; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_ptype_5numpy_ndarray = __Pyx_ImportType("numpy", "ndarray", sizeof(PyArrayObject), 0); if (unlikely(!__pyx_ptype_5numpy_ndarray)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 177; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_ptype_5numpy_ufunc = __Pyx_ImportType("numpy", "ufunc", sizeof(PyUFuncObject), 0); if (unlikely(!__pyx_ptype_5numpy_ufunc)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 860; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_5numpy_dtype = __Pyx_ImportType("numpy", "dtype", sizeof(PyArray_Descr), 0); if (unlikely(!__pyx_ptype_5numpy_dtype)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 151; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_5numpy_flatiter = __Pyx_ImportType("numpy", "flatiter", sizeof(PyArrayIterObject), 0); if (unlikely(!__pyx_ptype_5numpy_flatiter)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 161; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_5numpy_broadcast = __Pyx_ImportType("numpy", "broadcast", sizeof(PyArrayMultiIterObject), 0); if (unlikely(!__pyx_ptype_5numpy_broadcast)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 165; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_5numpy_ndarray = __Pyx_ImportType("numpy", "ndarray", sizeof(PyArrayObject), 0); if (unlikely(!__pyx_ptype_5numpy_ndarray)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 174; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_5numpy_ufunc = __Pyx_ImportType("numpy", "ufunc", sizeof(PyUFuncObject), 0); if (unlikely(!__pyx_ptype_5numpy_ufunc)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 857; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   /*--- Variable import code ---*/
   /*--- Function import code ---*/
   /*--- Execution code ---*/
@@ -6165,9 +5690,9 @@ PyMODINIT_FUNC PyInit_boundary_none(void)
  *                              np.ndarray[DTYPE_t, ndim=1] g):
  * 
  */
-  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_7astropy_6nddata_11convolution_13boundary_none_1convolve1d_boundary_none, NULL, __pyx_n_s_21); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_7astropy_6nddata_11convolution_13boundary_none_convolve1d_boundary_none, NULL, __pyx_n_s_17); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
-  if (PyObject_SetAttr(__pyx_m, __pyx_n_s_19, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s_18, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
   /* "astropy/nddata/convolution/boundary_none.pyx":79
@@ -6177,9 +5702,9 @@ PyMODINIT_FUNC PyInit_boundary_none(void)
  *                              np.ndarray[DTYPE_t, ndim=2] g):
  * 
  */
-  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_7astropy_6nddata_11convolution_13boundary_none_3convolve2d_boundary_none, NULL, __pyx_n_s_21); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 79; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_7astropy_6nddata_11convolution_13boundary_none_1convolve2d_boundary_none, NULL, __pyx_n_s_17); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 79; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
-  if (PyObject_SetAttr(__pyx_m, __pyx_n_s_24, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 79; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s_19, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 79; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
   /* "astropy/nddata/convolution/boundary_none.pyx":152
@@ -6189,9 +5714,9 @@ PyMODINIT_FUNC PyInit_boundary_none(void)
  *                              np.ndarray[DTYPE_t, ndim=3] g):
  * 
  */
-  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_7astropy_6nddata_11convolution_13boundary_none_5convolve3d_boundary_none, NULL, __pyx_n_s_21); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 152; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_7astropy_6nddata_11convolution_13boundary_none_2convolve3d_boundary_none, NULL, __pyx_n_s_17); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 152; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
-  if (PyObject_SetAttr(__pyx_m, __pyx_n_s_27, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 152; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s_20, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 152; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
   /* "astropy/nddata/convolution/boundary_none.pyx":1
@@ -6204,7 +5729,7 @@ PyMODINIT_FUNC PyInit_boundary_none(void)
   if (PyObject_SetAttr(__pyx_m, __pyx_n_s____test__, ((PyObject *)__pyx_t_2)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
 
-  /* "numpy.pxd":974
+  /* "numpy.pxd":971
  *      arr.base = baseptr
  * 
  * cdef inline object get_array_base(ndarray arr):             # <<<<<<<<<<<<<<
@@ -6231,6 +5756,7 @@ PyMODINIT_FUNC PyInit_boundary_none(void)
 }
 
 /* Runtime support code */
+
 #if CYTHON_REFNANNY
 static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname) {
     PyObject *m = NULL, *p = NULL;
@@ -6271,6 +5797,7 @@ static void __Pyx_RaiseArgtupleInvalid(
 {
     Py_ssize_t num_expected;
     const char *more_or_less;
+
     if (num_found < num_min) {
         num_expected = num_min;
         more_or_less = "at least";
@@ -6312,6 +5839,7 @@ static int __Pyx_ParseOptionalKeywords(
     Py_ssize_t pos = 0;
     PyObject*** name;
     PyObject*** first_kw_arg = argnames + num_pos_args;
+
     while (PyDict_Next(kwds, &pos, &key, &value)) {
         name = first_kw_arg;
         while (*name && (**name != key)) name++;
@@ -6321,7 +5849,7 @@ static int __Pyx_ParseOptionalKeywords(
             #if PY_MAJOR_VERSION < 3
             if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key))) {
             #else
-            if (unlikely(!PyUnicode_Check(key))) {
+            if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key))) {
             #endif
                 goto invalid_keyword_type;
             } else {
@@ -6337,6 +5865,7 @@ static int __Pyx_ParseOptionalKeywords(
                 if (*name) {
                     values[name-argnames] = value;
                 } else {
+                    /* unexpected keyword found */
                     for (name=argnames; name != first_kw_arg; name++) {
                         if (**name == key) goto arg_passed_twice;
                         #if PY_MAJOR_VERSION >= 3
@@ -6401,6 +5930,18 @@ static CYTHON_INLINE int __Pyx_IsLittleEndian(void) {
   unsigned int n = 1;
   return *(unsigned char*)(&n) != 0;
 }
+
+typedef struct {
+  __Pyx_StructField root;
+  __Pyx_BufFmt_StackElem* head;
+  size_t fmt_offset;
+  size_t new_count, enc_count;
+  int is_complex;
+  char enc_type;
+  char new_packmode;
+  char enc_packmode;
+} __Pyx_BufFmt_Context;
+
 static void __Pyx_BufFmt_Init(__Pyx_BufFmt_Context* ctx,
                               __Pyx_BufFmt_StackElem* stack,
                               __Pyx_TypeInfo* type) {
@@ -6419,8 +5960,6 @@ static void __Pyx_BufFmt_Init(__Pyx_BufFmt_Context* ctx,
   ctx->enc_count = 0;
   ctx->enc_type = 0;
   ctx->is_complex = 0;
-  ctx->is_valid_array = 0;
-  ctx->struct_alignment = 0;
   while (type->typegroup == 'S') {
     ++ctx->head;
     ctx->head->field = type->fields;
@@ -6428,6 +5967,7 @@ static void __Pyx_BufFmt_Init(__Pyx_BufFmt_Context* ctx,
     type = type->fields->type;
   }
 }
+
 static int __Pyx_BufFmt_ParseNumber(const char** ts) {
     int count;
     const char* t = *ts;
@@ -6443,17 +5983,12 @@ static int __Pyx_BufFmt_ParseNumber(const char** ts) {
     *ts = t;
     return count;
 }
-static int __Pyx_BufFmt_ExpectNumber(const char **ts) {
-    int number = __Pyx_BufFmt_ParseNumber(ts);
-    if (number == -1) /* First char was not a digit */
-        PyErr_Format(PyExc_ValueError,\
-                     "Does not understand character buffer dtype format string ('%c')", **ts);
-    return number;
-}
+
 static void __Pyx_BufFmt_RaiseUnexpectedChar(char ch) {
   PyErr_Format(PyExc_ValueError,
                "Unexpected format string character: '%c'", ch);
 }
+
 static const char* __Pyx_BufFmt_DescribeTypeChar(char ch, int is_complex) {
   switch (ch) {
     case 'b': return "'char'";
@@ -6472,14 +6007,14 @@ static const char* __Pyx_BufFmt_DescribeTypeChar(char ch, int is_complex) {
     case 'T': return "a struct";
     case 'O': return "Python object";
     case 'P': return "a pointer";
-    case 's': case 'p': return "a string";
     case 0: return "end";
     default: return "unparseable format string";
   }
 }
+
 static size_t __Pyx_BufFmt_TypeCharToStandardSize(char ch, int is_complex) {
   switch (ch) {
-    case '?': case 'c': case 'b': case 'B': case 's': case 'p': return 1;
+    case '?': case 'c': case 'b': case 'B': return 1;
     case 'h': case 'H': return 2;
     case 'i': case 'I': case 'l': case 'L': return 4;
     case 'q': case 'Q': return 8;
@@ -6495,9 +6030,10 @@ static size_t __Pyx_BufFmt_TypeCharToStandardSize(char ch, int is_complex) {
       return 0;
     }
 }
+
 static size_t __Pyx_BufFmt_TypeCharToNativeSize(char ch, int is_complex) {
   switch (ch) {
-    case 'c': case 'b': case 'B': case 's': case 'p': return 1;
+    case 'c': case 'b': case 'B': return 1;
     case 'h': case 'H': return sizeof(short);
     case 'i': case 'I': return sizeof(int);
     case 'l': case 'L': return sizeof(long);
@@ -6514,6 +6050,7 @@ static size_t __Pyx_BufFmt_TypeCharToNativeSize(char ch, int is_complex) {
     }
   }
 }
+
 typedef struct { char c; short x; } __Pyx_st_short;
 typedef struct { char c; int x; } __Pyx_st_int;
 typedef struct { char c; long x; } __Pyx_st_long;
@@ -6524,9 +6061,10 @@ typedef struct { char c; void *x; } __Pyx_st_void_p;
 #ifdef HAVE_LONG_LONG
 typedef struct { char c; PY_LONG_LONG x; } __Pyx_st_longlong;
 #endif
+
 static size_t __Pyx_BufFmt_TypeCharToAlignment(char ch, int is_complex) {
   switch (ch) {
-    case '?': case 'c': case 'b': case 'B': case 's': case 'p': return 1;
+    case '?': case 'c': case 'b': case 'B': return 1;
     case 'h': case 'H': return sizeof(__Pyx_st_short) - sizeof(short);
     case 'i': case 'I': return sizeof(__Pyx_st_int) - sizeof(int);
     case 'l': case 'L': return sizeof(__Pyx_st_long) - sizeof(long);
@@ -6542,57 +6080,21 @@ static size_t __Pyx_BufFmt_TypeCharToAlignment(char ch, int is_complex) {
       return 0;
     }
 }
-/* These are for computing the padding at the end of the struct to align
-   on the first member of the struct. This will probably the same as above,
-   but we don't have any guarantees.
- */
-typedef struct { short x; char c; } __Pyx_pad_short;
-typedef struct { int x; char c; } __Pyx_pad_int;
-typedef struct { long x; char c; } __Pyx_pad_long;
-typedef struct { float x; char c; } __Pyx_pad_float;
-typedef struct { double x; char c; } __Pyx_pad_double;
-typedef struct { long double x; char c; } __Pyx_pad_longdouble;
-typedef struct { void *x; char c; } __Pyx_pad_void_p;
-#ifdef HAVE_LONG_LONG
-typedef struct { PY_LONG_LONG x; char c; } __Pyx_pad_longlong;
-#endif
-static size_t __Pyx_BufFmt_TypeCharToPadding(char ch, int is_complex) {
-  switch (ch) {
-    case '?': case 'c': case 'b': case 'B': case 's': case 'p': return 1;
-    case 'h': case 'H': return sizeof(__Pyx_pad_short) - sizeof(short);
-    case 'i': case 'I': return sizeof(__Pyx_pad_int) - sizeof(int);
-    case 'l': case 'L': return sizeof(__Pyx_pad_long) - sizeof(long);
-#ifdef HAVE_LONG_LONG
-    case 'q': case 'Q': return sizeof(__Pyx_pad_longlong) - sizeof(PY_LONG_LONG);
-#endif
-    case 'f': return sizeof(__Pyx_pad_float) - sizeof(float);
-    case 'd': return sizeof(__Pyx_pad_double) - sizeof(double);
-    case 'g': return sizeof(__Pyx_pad_longdouble) - sizeof(long double);
-    case 'P': case 'O': return sizeof(__Pyx_pad_void_p) - sizeof(void*);
-    default:
-      __Pyx_BufFmt_RaiseUnexpectedChar(ch);
-      return 0;
-    }
-}
+
 static char __Pyx_BufFmt_TypeCharToGroup(char ch, int is_complex) {
   switch (ch) {
-    case 'c': case 'b': case 'h': case 'i':
-    case 'l': case 'q': case 's': case 'p':
-        return 'I';
-    case 'B': case 'H': case 'I': case 'L': case 'Q':
-        return 'U';
-    case 'f': case 'd': case 'g':
-        return (is_complex ? 'C' : 'R');
-    case 'O':
-        return 'O';
-    case 'P':
-        return 'P';
+    case 'c': case 'b': case 'h': case 'i': case 'l': case 'q': return 'I';
+    case 'B': case 'H': case 'I': case 'L': case 'Q': return 'U';
+    case 'f': case 'd': case 'g': return (is_complex ? 'C' : 'R');
+    case 'O': return 'O';
+    case 'P': return 'P';
     default: {
       __Pyx_BufFmt_RaiseUnexpectedChar(ch);
       return 0;
     }
   }
 }
+
 static void __Pyx_BufFmt_RaiseExpected(__Pyx_BufFmt_Context* ctx) {
   if (ctx->head == NULL || ctx->head->field == &ctx->root) {
     const char* expected;
@@ -6617,37 +6119,16 @@ static void __Pyx_BufFmt_RaiseExpected(__Pyx_BufFmt_Context* ctx) {
                  parent->type->name, field->name);
   }
 }
+
 static int __Pyx_BufFmt_ProcessTypeChunk(__Pyx_BufFmt_Context* ctx) {
   char group;
-  size_t size, offset, arraysize = 1;
+  size_t size, offset;
   if (ctx->enc_type == 0) return 0;
-  if (ctx->head->field->type->arraysize[0]) {
-    int i, ndim = 0;
-    if (ctx->enc_type == 's' || ctx->enc_type == 'p') {
-        ctx->is_valid_array = ctx->head->field->type->ndim == 1;
-        ndim = 1;
-        if (ctx->enc_count != ctx->head->field->type->arraysize[0]) {
-            PyErr_Format(PyExc_ValueError,
-                         "Expected a dimension of size %zu, got %zu",
-                         ctx->head->field->type->arraysize[0], ctx->enc_count);
-            return -1;
-        }
-    }
-    if (!ctx->is_valid_array) {
-      PyErr_Format(PyExc_ValueError, "Expected %d dimensions, got %d",
-                   ctx->head->field->type->ndim, ndim);
-      return -1;
-    }
-    for (i = 0; i < ctx->head->field->type->ndim; i++) {
-      arraysize *= ctx->head->field->type->arraysize[i];
-    }
-    ctx->is_valid_array = 0;
-    ctx->enc_count = 1;
-  }
   group = __Pyx_BufFmt_TypeCharToGroup(ctx->enc_type, ctx->is_complex);
   do {
     __Pyx_StructField* field = ctx->head->field;
     __Pyx_TypeInfo* type = field->type;
+
     if (ctx->enc_packmode == '@' || ctx->enc_packmode == '^') {
       size = __Pyx_BufFmt_TypeCharToNativeSize(ctx->enc_type, ctx->is_complex);
     } else {
@@ -6659,21 +6140,22 @@ static int __Pyx_BufFmt_ProcessTypeChunk(__Pyx_BufFmt_Context* ctx) {
       if (align_at == 0) return -1;
       align_mod_offset = ctx->fmt_offset % align_at;
       if (align_mod_offset > 0) ctx->fmt_offset += align_at - align_mod_offset;
-      if (ctx->struct_alignment == 0)
-          ctx->struct_alignment = __Pyx_BufFmt_TypeCharToPadding(ctx->enc_type,
-                                                                 ctx->is_complex);
     }
+
     if (type->size != size || type->typegroup != group) {
       if (type->typegroup == 'C' && type->fields != NULL) {
+        /* special case -- treat as struct rather than complex number */
         size_t parent_offset = ctx->head->parent_offset + field->offset;
         ++ctx->head;
         ctx->head->field = type->fields;
         ctx->head->parent_offset = parent_offset;
         continue;
       }
+
       __Pyx_BufFmt_RaiseExpected(ctx);
       return -1;
     }
+
     offset = ctx->head->parent_offset + field->offset;
     if (ctx->fmt_offset != offset) {
       PyErr_Format(PyExc_ValueError,
@@ -6681,10 +6163,12 @@ static int __Pyx_BufFmt_ProcessTypeChunk(__Pyx_BufFmt_Context* ctx) {
                    (Py_ssize_t)ctx->fmt_offset, (Py_ssize_t)offset);
       return -1;
     }
+
     ctx->fmt_offset += size;
-    if (arraysize)
-      ctx->fmt_offset += (arraysize - 1) * size;
+
     --ctx->enc_count; /* Consume from buffer string */
+
+    /* Done checking, move to next field, pushing or popping struct stack if needed */
     while (1) {
       if (field == &ctx->root) {
         ctx->head = NULL;
@@ -6716,48 +6200,7 @@ static int __Pyx_BufFmt_ProcessTypeChunk(__Pyx_BufFmt_Context* ctx) {
   ctx->is_complex = 0;
   return 0;
 }
-static CYTHON_INLINE PyObject *
-__pyx_buffmt_parse_array(__Pyx_BufFmt_Context* ctx, const char** tsp)
-{
-    const char *ts = *tsp;
-    int i = 0, number;
-    int ndim = ctx->head->field->type->ndim;
-;
-    ++ts;
-    if (ctx->new_count != 1) {
-        PyErr_SetString(PyExc_ValueError,
-                        "Cannot handle repeated arrays in format string");
-        return NULL;
-    }
-    if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL;
-    while (*ts && *ts != ')') {
-        if (isspace(*ts))
-            continue;
-        number = __Pyx_BufFmt_ExpectNumber(&ts);
-        if (number == -1) return NULL;
-        if (i < ndim && (size_t) number != ctx->head->field->type->arraysize[i])
-            return PyErr_Format(PyExc_ValueError,
-                        "Expected a dimension of size %zu, got %d",
-                        ctx->head->field->type->arraysize[i], number);
-        if (*ts != ',' && *ts != ')')
-            return PyErr_Format(PyExc_ValueError,
-                                "Expected a comma in format string, got '%c'", *ts);
-        if (*ts == ',') ts++;
-        i++;
-    }
-    if (i != ndim)
-        return PyErr_Format(PyExc_ValueError, "Expected %d dimension(s), got %d",
-                            ctx->head->field->type->ndim, i);
-    if (!*ts) {
-        PyErr_SetString(PyExc_ValueError,
-                        "Unexpected end of format string, expected ')'");
-        return NULL;
-    }
-    ctx->is_valid_array = 1;
-    ctx->new_count = 1;
-    *tsp = ++ts;
-    return Py_None;
-}
+
 static const char* __Pyx_BufFmt_CheckString(__Pyx_BufFmt_Context* ctx, const char* ts) {
   int got_Z = 0;
   while (1) {
@@ -6772,7 +6215,7 @@ static const char* __Pyx_BufFmt_CheckString(__Pyx_BufFmt_Context* ctx, const cha
           __Pyx_BufFmt_RaiseExpected(ctx);
           return NULL;
         }
-                return ts;
+        return ts;
       case ' ':
       case 10:
       case 13:
@@ -6804,17 +6247,12 @@ static const char* __Pyx_BufFmt_CheckString(__Pyx_BufFmt_Context* ctx, const cha
         {
           const char* ts_after_sub;
           size_t i, struct_count = ctx->new_count;
-          size_t struct_alignment = ctx->struct_alignment;
           ctx->new_count = 1;
           ++ts;
           if (*ts != '{') {
             PyErr_SetString(PyExc_ValueError, "Buffer acquisition: Expected '{' after 'T'");
             return NULL;
           }
-          if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL;
-          ctx->enc_type = 0; /* Erase processed last struct element */
-          ctx->enc_count = 0;
-          ctx->struct_alignment = 0;
           ++ts;
           ts_after_sub = ts;
           for (i = 0; i != struct_count; ++i) {
@@ -6822,19 +6260,10 @@ static const char* __Pyx_BufFmt_CheckString(__Pyx_BufFmt_Context* ctx, const cha
             if (!ts_after_sub) return NULL;
           }
           ts = ts_after_sub;
-          if (struct_alignment) ctx->struct_alignment = struct_alignment;
         }
         break;
       case '}': /* end of substruct; either repeat or move on */
-        {
-          size_t alignment = ctx->struct_alignment;
-          ++ts;
-          if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL;
-          ctx->enc_type = 0; /* Erase processed last struct element */
-          if (alignment && ctx->fmt_offset % alignment) {
-            ctx->fmt_offset += alignment - (ctx->fmt_offset % alignment);
-          }
-        }
+        ++ts;
         return ts;
       case 'x':
         if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL;
@@ -6855,11 +6284,13 @@ static const char* __Pyx_BufFmt_CheckString(__Pyx_BufFmt_Context* ctx, const cha
       case 'c': case 'b': case 'B': case 'h': case 'H': case 'i': case 'I':
       case 'l': case 'L': case 'q': case 'Q':
       case 'f': case 'd': case 'g':
-      case 'O': case 's': case 'p':
+      case 'O':
         if (ctx->enc_type == *ts && got_Z == ctx->is_complex &&
             ctx->enc_packmode == ctx->new_packmode) {
+          /* Continue pooling same type */
           ctx->enc_count += ctx->new_count;
         } else {
+          /* New type */
           if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL;
           ctx->enc_count = ctx->new_count;
           ctx->enc_packmode = ctx->new_packmode;
@@ -6875,18 +6306,20 @@ static const char* __Pyx_BufFmt_CheckString(__Pyx_BufFmt_Context* ctx, const cha
         while(*ts != ':') ++ts;
         ++ts;
         break;
-      case '(':
-        if (!__pyx_buffmt_parse_array(ctx, &ts)) return NULL;
-        break;
       default:
         {
-          int number = __Pyx_BufFmt_ExpectNumber(&ts);
-          if (number == -1) return NULL;
-          ctx->new_count = (size_t)number;
+          int number = __Pyx_BufFmt_ParseNumber(&ts);
+          if (number == -1) { /* First char was not a digit */
+            PyErr_Format(PyExc_ValueError,
+                         "Does not understand character buffer dtype format string ('%c')", *ts);
+            return NULL;
+          }
+          ctx->new_count = (size_t)number; 
         }
     }
   }
 }
+
 static CYTHON_INLINE void __Pyx_ZeroBuffer(Py_buffer* buf) {
   buf->buf = NULL;
   buf->obj = NULL;
@@ -6894,10 +6327,8 @@ static CYTHON_INLINE void __Pyx_ZeroBuffer(Py_buffer* buf) {
   buf->shape = __Pyx_zeros;
   buf->suboffsets = __Pyx_minusones;
 }
-static CYTHON_INLINE int __Pyx_GetBufferAndValidate(
-        Py_buffer* buf, PyObject* obj,  __Pyx_TypeInfo* dtype, int flags,
-        int nd, int cast, __Pyx_BufFmt_StackElem* stack)
-{
+
+static CYTHON_INLINE int __Pyx_GetBufferAndValidate(Py_buffer* buf, PyObject* obj, __Pyx_TypeInfo* dtype, int flags, int nd, int cast, __Pyx_BufFmt_StackElem* stack) {
   if (obj == Py_None || obj == NULL) {
     __Pyx_ZeroBuffer(buf);
     return 0;
@@ -6928,6 +6359,7 @@ fail:;
   __Pyx_ZeroBuffer(buf);
   return -1;
 }
+
 static CYTHON_INLINE void __Pyx_SafeReleaseBuffer(Py_buffer* info) {
   if (info->buf == NULL) return;
   if (info->suboffsets == __Pyx_minusones) info->suboffsets = NULL;
@@ -6941,9 +6373,9 @@ static CYTHON_INLINE long __Pyx_mod_long(long a, long b) {
 }
 
 static CYTHON_INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb) {
-#if CYTHON_COMPILING_IN_CPYTHON
     PyObject *tmp_type, *tmp_value, *tmp_tb;
     PyThreadState *tstate = PyThreadState_GET();
+
     tmp_type = tstate->curexc_type;
     tmp_value = tstate->curexc_value;
     tmp_tb = tstate->curexc_traceback;
@@ -6953,30 +6385,27 @@ static CYTHON_INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyOb
     Py_XDECREF(tmp_type);
     Py_XDECREF(tmp_value);
     Py_XDECREF(tmp_tb);
-#else
-    PyErr_Restore(type, value, tb);
-#endif
 }
+
 static CYTHON_INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb) {
-#if CYTHON_COMPILING_IN_CPYTHON
     PyThreadState *tstate = PyThreadState_GET();
     *type = tstate->curexc_type;
     *value = tstate->curexc_value;
     *tb = tstate->curexc_traceback;
+
     tstate->curexc_type = 0;
     tstate->curexc_value = 0;
     tstate->curexc_traceback = 0;
-#else
-    PyErr_Fetch(type, value, tb);
-#endif
 }
 
+
 #if PY_MAJOR_VERSION < 3
-static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb,
-                        CYTHON_UNUSED PyObject *cause) {
+static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause) {
+    /* cause is unused */
     Py_XINCREF(type);
     Py_XINCREF(value);
     Py_XINCREF(tb);
+    /* First, check the traceback argument, replacing None with NULL. */
     if (tb == Py_None) {
         Py_DECREF(tb);
         tb = 0;
@@ -6986,6 +6415,7 @@ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb,
             "raise: arg 3 must be a traceback or None");
         goto raise_error;
     }
+    /* Next, replace a missing value with None */
     if (value == NULL) {
         value = Py_None;
         Py_INCREF(value);
@@ -6996,11 +6426,13 @@ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb,
     if (!PyType_Check(type))
     #endif
     {
+        /* Raising an instance.  The value should be a dummy. */
         if (value != Py_None) {
             PyErr_SetString(PyExc_TypeError,
                 "instance exception may not have a separate value");
             goto raise_error;
         }
+        /* Normalize to raise <class>, <instance> */
         Py_DECREF(value);
         value = type;
         #if PY_VERSION_HEX < 0x02050000
@@ -7024,6 +6456,7 @@ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb,
             }
         #endif
     }
+
     __Pyx_ErrRestore(type, value, tb);
     return;
 raise_error:
@@ -7032,7 +6465,9 @@ raise_error:
     Py_XDECREF(tb);
     return;
 }
+
 #else /* Python 3+ */
+
 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause) {
     if (tb == Py_None) {
         tb = 0;
@@ -7043,6 +6478,7 @@ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject
     }
     if (value == Py_None)
         value = 0;
+
     if (PyExceptionInstance_Check(type)) {
         if (value) {
             PyErr_SetString(PyExc_TypeError,
@@ -7056,6 +6492,7 @@ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject
             "raise: exception class must be a subclass of BaseException");
         goto bad;
     }
+
     if (cause) {
         PyObject *fixed_cause;
         if (PyExceptionClass_Check(cause)) {
@@ -7078,7 +6515,9 @@ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject
         }
         PyException_SetCause(value, fixed_cause);
     }
+
     PyErr_SetObject(type, value);
+
     if (tb) {
         PyThreadState *tstate = PyThreadState_GET();
         PyObject* tmp_tb = tstate->curexc_traceback;
@@ -7088,6 +6527,7 @@ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject
             Py_XDECREF(tmp_tb);
         }
     }
+
 bad:
     return;
 }
@@ -7139,98 +6579,31 @@ static void __Pyx_UnpackTupleError(PyObject *t, Py_ssize_t index) {
 
 #if PY_MAJOR_VERSION < 3
 static int __Pyx_GetBuffer(PyObject *obj, Py_buffer *view, int flags) {
-    PyObject *getbuffer_cobj;
-
   #if PY_VERSION_HEX >= 0x02060000
-    if (PyObject_CheckBuffer(obj)) return PyObject_GetBuffer(obj, view, flags);
+  if (PyObject_CheckBuffer(obj)) return PyObject_GetBuffer(obj, view, flags);
   #endif
-
-        if (PyObject_TypeCheck(obj, __pyx_ptype_5numpy_ndarray)) return __pyx_pw_5numpy_7ndarray_1__getbuffer__(obj, view, flags);
-
-  #if PY_VERSION_HEX < 0x02060000
-    if (obj->ob_type->tp_dict &&
-        (getbuffer_cobj = PyMapping_GetItemString(obj->ob_type->tp_dict,
-                                             "__pyx_getbuffer"))) {
-        getbufferproc func;
-
-      #if PY_VERSION_HEX >= 0x02070000 && !(PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION == 0)
-        func = (getbufferproc) PyCapsule_GetPointer(getbuffer_cobj, "getbuffer(obj, view, flags)");
-      #else
-        func = (getbufferproc) PyCObject_AsVoidPtr(getbuffer_cobj);
-      #endif
-        Py_DECREF(getbuffer_cobj);
-        if (!func)
-            goto fail;
-
-        return func(obj, view, flags);
-    } else {
-        PyErr_Clear();
+  if (PyObject_TypeCheck(obj, __pyx_ptype_5numpy_ndarray)) return __pyx_pf_5numpy_7ndarray___getbuffer__(obj, view, flags);
+  else {
+  PyErr_Format(PyExc_TypeError, "'%100s' does not have the buffer interface", Py_TYPE(obj)->tp_name);
+  return -1;
     }
-  #endif
-
-    PyErr_Format(PyExc_TypeError, "'%100s' does not have the buffer interface", Py_TYPE(obj)->tp_name);
-
-#if PY_VERSION_HEX < 0x02060000
-fail:
-#endif
-
-    return -1;
 }
 
 static void __Pyx_ReleaseBuffer(Py_buffer *view) {
-    PyObject *obj = view->obj;
-    PyObject *releasebuffer_cobj;
-
-    if (!obj) return;
-
-  #if PY_VERSION_HEX >= 0x02060000
-    if (PyObject_CheckBuffer(obj)) {
-        PyBuffer_Release(view);
-        return;
-    }
-  #endif
-
-        if (PyObject_TypeCheck(obj, __pyx_ptype_5numpy_ndarray)) { __pyx_pw_5numpy_7ndarray_3__releasebuffer__(obj, view); return; }
-
-  #if PY_VERSION_HEX < 0x02060000
-    if (obj->ob_type->tp_dict &&
-        (releasebuffer_cobj = PyMapping_GetItemString(obj->ob_type->tp_dict,
-                                                      "__pyx_releasebuffer"))) {
-        releasebufferproc func;
-
-      #if PY_VERSION_HEX >= 0x02070000 && !(PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION == 0)
-        func = (releasebufferproc) PyCapsule_GetPointer(releasebuffer_cobj, "releasebuffer(obj, view)");
-      #else
-        func = (releasebufferproc) PyCObject_AsVoidPtr(releasebuffer_cobj);
-      #endif
-
-        Py_DECREF(releasebuffer_cobj);
-
-        if (!func)
-            goto fail;
-
-        func(obj, view);
-        return;
-    } else {
-        PyErr_Clear();
-    }
-  #endif
-
-    goto nofail;
-
-#if PY_VERSION_HEX < 0x02060000
-fail:
-#endif
-    PyErr_WriteUnraisable(obj);
-
-nofail:
+  PyObject* obj = view->obj;
+  if (obj) {
+    #if PY_VERSION_HEX >= 0x02060000
+    if (PyObject_CheckBuffer(obj)) {PyBuffer_Release(view); return;}
+    #endif
+    if (PyObject_TypeCheck(obj, __pyx_ptype_5numpy_ndarray)) __pyx_pf_5numpy_7ndarray_1__releasebuffer__(obj, view);
     Py_DECREF(obj);
     view->obj = NULL;
+  }
 }
 
-#endif /*  PY_MAJOR_VERSION < 3 */
+#endif
 
-    static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, long level) {
+static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, long level) {
     PyObject *py_import = 0;
     PyObject *empty_list = 0;
     PyObject *module = 0;
@@ -7256,33 +6629,12 @@ nofail:
         goto bad;
     #if PY_VERSION_HEX >= 0x02050000
     {
-        #if PY_MAJOR_VERSION >= 3
-        if (level == -1) {
-            if (strchr(__Pyx_MODULE_NAME, '.')) {
-                /* try package relative import first */
-                PyObject *py_level = PyInt_FromLong(1);
-                if (!py_level)
-                    goto bad;
-                module = PyObject_CallFunctionObjArgs(py_import,
-                    name, global_dict, empty_dict, list, py_level, NULL);
-                Py_DECREF(py_level);
-                if (!module) {
-                    if (!PyErr_ExceptionMatches(PyExc_ImportError))
-                        goto bad;
-                    PyErr_Clear();
-                }
-            }
-            level = 0; /* try absolute import on failure */
-        }
-        #endif
-        if (!module) {
-            PyObject *py_level = PyInt_FromLong(level);
-            if (!py_level)
-                goto bad;
-            module = PyObject_CallFunctionObjArgs(py_import,
-                name, global_dict, empty_dict, list, py_level, NULL);
-            Py_DECREF(py_level);
-        }
+        PyObject *py_level = PyInt_FromLong(level);
+        if (!py_level)
+            goto bad;
+        module = PyObject_CallFunctionObjArgs(py_import,
+            name, global_dict, empty_dict, list, py_level, NULL);
+        Py_DECREF(py_level);
     }
     #else
     if (level>0) {
@@ -7967,10 +7319,15 @@ static PyTypeObject *__Pyx_ImportType(const char *module_name, const char *class
     PyObject *result = 0;
     PyObject *py_name = 0;
     char warning[200];
+
     py_module = __Pyx_ImportModule(module_name);
     if (!py_module)
         goto bad;
-    py_name = __Pyx_PyIdentifier_FromString(class_name);
+    #if PY_MAJOR_VERSION < 3
+    py_name = PyString_FromString(class_name);
+    #else
+    py_name = PyUnicode_FromString(class_name);
+    #endif
     if (!py_name)
         goto bad;
     result = PyObject_GetAttr(py_module, py_name);
@@ -7986,7 +7343,7 @@ static PyTypeObject *__Pyx_ImportType(const char *module_name, const char *class
             module_name, class_name);
         goto bad;
     }
-    if (!strict && (size_t)((PyTypeObject *)result)->tp_basicsize > size) {
+    if (!strict && ((PyTypeObject *)result)->tp_basicsize > (Py_ssize_t)size) {
         PyOS_snprintf(warning, sizeof(warning),
             "%s.%s size changed, may indicate binary incompatibility",
             module_name, class_name);
@@ -7996,7 +7353,7 @@ static PyTypeObject *__Pyx_ImportType(const char *module_name, const char *class
         if (PyErr_WarnEx(NULL, warning, 0) < 0) goto bad;
         #endif
     }
-    else if ((size_t)((PyTypeObject *)result)->tp_basicsize != size) {
+    else if (((PyTypeObject *)result)->tp_basicsize != (Py_ssize_t)size) {
         PyErr_Format(PyExc_ValueError,
             "%s.%s has the wrong size, try recompiling",
             module_name, class_name);
@@ -8015,7 +7372,12 @@ bad:
 static PyObject *__Pyx_ImportModule(const char *name) {
     PyObject *py_name = 0;
     PyObject *py_module = 0;
-    py_name = __Pyx_PyIdentifier_FromString(name);
+
+    #if PY_MAJOR_VERSION < 3
+    py_name = PyString_FromString(name);
+    #else
+    py_name = PyUnicode_FromString(name);
+    #endif
     if (!py_name)
         goto bad;
     py_module = PyImport_Import(py_name);
@@ -8027,105 +7389,29 @@ bad:
 }
 #endif
 
-static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line) {
-    int start = 0, mid = 0, end = count - 1;
-    if (end >= 0 && code_line > entries[end].code_line) {
-        return count;
-    }
-    while (start < end) {
-        mid = (start + end) / 2;
-        if (code_line < entries[mid].code_line) {
-            end = mid;
-        } else if (code_line > entries[mid].code_line) {
-             start = mid + 1;
-        } else {
-            return mid;
-        }
-    }
-    if (code_line <= entries[mid].code_line) {
-        return mid;
-    } else {
-        return mid + 1;
-    }
-}
-static PyCodeObject *__pyx_find_code_object(int code_line) {
-    PyCodeObject* code_object;
-    int pos;
-    if (unlikely(!code_line) || unlikely(!__pyx_code_cache.entries)) {
-        return NULL;
-    }
-    pos = __pyx_bisect_code_objects(__pyx_code_cache.entries, __pyx_code_cache.count, code_line);
-    if (unlikely(pos >= __pyx_code_cache.count) || unlikely(__pyx_code_cache.entries[pos].code_line != code_line)) {
-        return NULL;
-    }
-    code_object = __pyx_code_cache.entries[pos].code_object;
-    Py_INCREF(code_object);
-    return code_object;
-}
-static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object) {
-    int pos, i;
-    __Pyx_CodeObjectCacheEntry* entries = __pyx_code_cache.entries;
-    if (unlikely(!code_line)) {
-        return;
-    }
-    if (unlikely(!entries)) {
-        entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Malloc(64*sizeof(__Pyx_CodeObjectCacheEntry));
-        if (likely(entries)) {
-            __pyx_code_cache.entries = entries;
-            __pyx_code_cache.max_count = 64;
-            __pyx_code_cache.count = 1;
-            entries[0].code_line = code_line;
-            entries[0].code_object = code_object;
-            Py_INCREF(code_object);
-        }
-        return;
-    }
-    pos = __pyx_bisect_code_objects(__pyx_code_cache.entries, __pyx_code_cache.count, code_line);
-    if ((pos < __pyx_code_cache.count) && unlikely(__pyx_code_cache.entries[pos].code_line == code_line)) {
-        PyCodeObject* tmp = entries[pos].code_object;
-        entries[pos].code_object = code_object;
-        Py_DECREF(tmp);
-        return;
-    }
-    if (__pyx_code_cache.count == __pyx_code_cache.max_count) {
-        int new_max = __pyx_code_cache.max_count + 64;
-        entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Realloc(
-            __pyx_code_cache.entries, new_max*sizeof(__Pyx_CodeObjectCacheEntry));
-        if (unlikely(!entries)) {
-            return;
-        }
-        __pyx_code_cache.entries = entries;
-        __pyx_code_cache.max_count = new_max;
-    }
-    for (i=__pyx_code_cache.count; i>pos; i--) {
-        entries[i] = entries[i-1];
-    }
-    entries[pos].code_line = code_line;
-    entries[pos].code_object = code_object;
-    __pyx_code_cache.count++;
-    Py_INCREF(code_object);
-}
-
 #include "compile.h"
 #include "frameobject.h"
 #include "traceback.h"
-static PyCodeObject* __Pyx_CreateCodeObjectForTraceback(
-            const char *funcname, int c_line,
-            int py_line, const char *filename) {
-    PyCodeObject *py_code = 0;
+
+static void __Pyx_AddTraceback(const char *funcname, int __pyx_clineno,
+                               int __pyx_lineno, const char *__pyx_filename) {
     PyObject *py_srcfile = 0;
     PyObject *py_funcname = 0;
+    PyObject *py_globals = 0;
+    PyCodeObject *py_code = 0;
+    PyFrameObject *py_frame = 0;
+
     #if PY_MAJOR_VERSION < 3
-    py_srcfile = PyString_FromString(filename);
+    py_srcfile = PyString_FromString(__pyx_filename);
     #else
-    py_srcfile = PyUnicode_FromString(filename);
+    py_srcfile = PyUnicode_FromString(__pyx_filename);
     #endif
     if (!py_srcfile) goto bad;
-    if (c_line) {
+    if (__pyx_clineno) {
         #if PY_MAJOR_VERSION < 3
-        py_funcname = PyString_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line);
+        py_funcname = PyString_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, __pyx_clineno);
         #else
-        py_funcname = PyUnicode_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line);
+        py_funcname = PyUnicode_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, __pyx_clineno);
         #endif
     }
     else {
@@ -8136,45 +7422,28 @@ static PyCodeObject* __Pyx_CreateCodeObjectForTraceback(
         #endif
     }
     if (!py_funcname) goto bad;
-    py_code = __Pyx_PyCode_New(
+    py_globals = PyModule_GetDict(__pyx_m);
+    if (!py_globals) goto bad;
+    py_code = PyCode_New(
         0,            /*int argcount,*/
+        #if PY_MAJOR_VERSION >= 3
         0,            /*int kwonlyargcount,*/
+        #endif
         0,            /*int nlocals,*/
         0,            /*int stacksize,*/
         0,            /*int flags,*/
         __pyx_empty_bytes, /*PyObject *code,*/
-        __pyx_empty_tuple, /*PyObject *consts,*/
-        __pyx_empty_tuple, /*PyObject *names,*/
-        __pyx_empty_tuple, /*PyObject *varnames,*/
-        __pyx_empty_tuple, /*PyObject *freevars,*/
-        __pyx_empty_tuple, /*PyObject *cellvars,*/
+        __pyx_empty_tuple,  /*PyObject *consts,*/
+        __pyx_empty_tuple,  /*PyObject *names,*/
+        __pyx_empty_tuple,  /*PyObject *varnames,*/
+        __pyx_empty_tuple,  /*PyObject *freevars,*/
+        __pyx_empty_tuple,  /*PyObject *cellvars,*/
         py_srcfile,   /*PyObject *filename,*/
         py_funcname,  /*PyObject *name,*/
-        py_line,      /*int firstlineno,*/
+        __pyx_lineno,   /*int firstlineno,*/
         __pyx_empty_bytes  /*PyObject *lnotab*/
     );
-    Py_DECREF(py_srcfile);
-    Py_DECREF(py_funcname);
-    return py_code;
-bad:
-    Py_XDECREF(py_srcfile);
-    Py_XDECREF(py_funcname);
-    return NULL;
-}
-static void __Pyx_AddTraceback(const char *funcname, int c_line,
-                               int py_line, const char *filename) {
-    PyCodeObject *py_code = 0;
-    PyObject *py_globals = 0;
-    PyFrameObject *py_frame = 0;
-    py_code = __pyx_find_code_object(c_line ? c_line : py_line);
-    if (!py_code) {
-        py_code = __Pyx_CreateCodeObjectForTraceback(
-            funcname, c_line, py_line, filename);
-        if (!py_code) goto bad;
-        __pyx_insert_code_object(c_line ? c_line : py_line, py_code);
-    }
-    py_globals = PyModule_GetDict(__pyx_m);
-    if (!py_globals) goto bad;
+    if (!py_code) goto bad;
     py_frame = PyFrame_New(
         PyThreadState_GET(), /*PyThreadState *tstate,*/
         py_code,             /*PyCodeObject *code,*/
@@ -8182,9 +7451,11 @@ static void __Pyx_AddTraceback(const char *funcname, int c_line,
         0                    /*PyObject *locals*/
     );
     if (!py_frame) goto bad;
-    py_frame->f_lineno = py_line;
+    py_frame->f_lineno = __pyx_lineno;
     PyTraceBack_Here(py_frame);
 bad:
+    Py_XDECREF(py_srcfile);
+    Py_XDECREF(py_funcname);
     Py_XDECREF(py_code);
     Py_XDECREF(py_frame);
 }
@@ -8219,7 +7490,6 @@ static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) {
     return 0;
 }
 
-
 /* Type Conversion Functions */
 
 static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject* x) {
diff --git a/astropy/nddata/convolution/boundary_wrap.c b/astropy/nddata/convolution/boundary_wrap.c
index 93470ca..c79e206 100644
--- a/astropy/nddata/convolution/boundary_wrap.c
+++ b/astropy/nddata/convolution/boundary_wrap.c
@@ -1,12 +1,11 @@
-/* Generated by Cython 0.16 on Tue Jun 19 01:38:35 2012 */
+/* Generated by Cython 0.15.1 on Mon Dec 24 15:34:37 2012 */
 
 #define PY_SSIZE_T_CLEAN
 #include "Python.h"
 #ifndef Py_PYTHON_H
     #error Python headers needed to compile C extensions, please install development version of Python.
-#elif PY_VERSION_HEX < 0x02040000
-    #error Cython requires Python 2.4+.
 #else
+
 #include <stddef.h> /* For offsetof */
 #ifndef offsetof
 #define offsetof(type, member) ( (size_t) & ((type*)0) -> member )
@@ -35,22 +34,10 @@
   #define PY_LONG_LONG LONG_LONG
 #endif
 
-#ifndef Py_HUGE_VAL
-  #define Py_HUGE_VAL HUGE_VAL
-#endif
-
-#ifdef PYPY_VERSION
-#define CYTHON_COMPILING_IN_PYPY 1
-#define CYTHON_COMPILING_IN_CPYTHON 0
-#else
-#define CYTHON_COMPILING_IN_PYPY 0
-#define CYTHON_COMPILING_IN_CPYTHON 1
-#endif
-
-#if CYTHON_COMPILING_IN_PYPY
-  #define __Pyx_PyCFunction_Call PyObject_Call
-#else
-  #define __Pyx_PyCFunction_Call PyCFunction_Call
+#if PY_VERSION_HEX < 0x02040000
+  #define METH_COEXIST 0
+  #define PyDict_CheckExact(op) (Py_TYPE(op) == &PyDict_Type)
+  #define PyDict_Contains(d,o)   PySequence_Contains(d,o)
 #endif
 
 #if PY_VERSION_HEX < 0x02050000
@@ -63,9 +50,6 @@
   #define PyNumber_Index(o)    PyNumber_Int(o)
   #define PyIndex_Check(o)     PyNumber_Check(o)
   #define PyErr_WarnEx(category, message, stacklevel) PyErr_Warn(category, message)
-  #define __PYX_BUILD_PY_SSIZE_T "i"
-#else
-  #define __PYX_BUILD_PY_SSIZE_T "n"
 #endif
 
 #if PY_VERSION_HEX < 0x02060000
@@ -99,25 +83,13 @@
   #define PyBUF_F_CONTIGUOUS (0x0040 | PyBUF_STRIDES)
   #define PyBUF_ANY_CONTIGUOUS (0x0080 | PyBUF_STRIDES)
   #define PyBUF_INDIRECT (0x0100 | PyBUF_STRIDES)
-  #define PyBUF_RECORDS (PyBUF_STRIDES | PyBUF_FORMAT | PyBUF_WRITABLE)
-  #define PyBUF_FULL (PyBUF_INDIRECT | PyBUF_FORMAT | PyBUF_WRITABLE)
 
-  typedef int (*getbufferproc)(PyObject *, Py_buffer *, int);
-  typedef void (*releasebufferproc)(PyObject *, Py_buffer *);
 #endif
 
 #if PY_MAJOR_VERSION < 3
   #define __Pyx_BUILTIN_MODULE_NAME "__builtin__"
-  #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) \
-          PyCode_New(a, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)
 #else
   #define __Pyx_BUILTIN_MODULE_NAME "builtins"
-  #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) \
-          PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)
-#endif
-
-#if PY_MAJOR_VERSION < 3 && PY_MINOR_VERSION < 6
-  #define PyUnicode_FromString(s) PyUnicode_Decode(s, strlen(s), "UTF-8", "strict")
 #endif
 
 #if PY_MAJOR_VERSION >= 3
@@ -129,17 +101,6 @@
   #define Py_TPFLAGS_HAVE_NEWBUFFER 0
 #endif
 
-
-#if PY_VERSION_HEX > 0x03030000 && defined(PyUnicode_GET_LENGTH)
-  #define CYTHON_PEP393_ENABLED 1
-  #define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_LENGTH(u)
-  #define __Pyx_PyUnicode_READ_CHAR(u, i) PyUnicode_READ_CHAR(u, i)
-#else
-  #define CYTHON_PEP393_ENABLED 0
-  #define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_SIZE(u)
-  #define __Pyx_PyUnicode_READ_CHAR(u, i) ((Py_UCS4)(PyUnicode_AS_UNICODE(u)[i]))
-#endif
-
 #if PY_MAJOR_VERSION >= 3
   #define PyBaseString_Type            PyUnicode_Type
   #define PyStringObject               PyUnicodeObject
@@ -207,6 +168,15 @@
   #define __Pyx_PyInt_AsHash_t   PyInt_AsSsize_t
 #endif
 
+
+#if PY_MAJOR_VERSION >= 3
+  #define __Pyx_PyNumber_Divide(x,y)         PyNumber_TrueDivide(x,y)
+  #define __Pyx_PyNumber_InPlaceDivide(x,y)  PyNumber_InPlaceTrueDivide(x,y)
+#else
+  #define __Pyx_PyNumber_Divide(x,y)         PyNumber_TrueDivide(x,y)
+  #define __Pyx_PyNumber_InPlaceDivide(x,y)  PyNumber_InPlaceTrueDivide(x,y)
+#endif
+
 #if (PY_MAJOR_VERSION < 3) || (PY_VERSION_HEX >= 0x03010300)
   #define __Pyx_PySequence_GetSlice(obj, a, b) PySequence_GetSlice(obj, a, b)
   #define __Pyx_PySequence_SetSlice(obj, a, b, value) PySequence_SetSlice(obj, a, b, value)
@@ -248,14 +218,6 @@
   #define __Pyx_DOCSTR(n)  (n)
 #endif
 
-#if PY_MAJOR_VERSION >= 3
-  #define __Pyx_PyNumber_Divide(x,y)         PyNumber_TrueDivide(x,y)
-  #define __Pyx_PyNumber_InPlaceDivide(x,y)  PyNumber_InPlaceTrueDivide(x,y)
-#else
-  #define __Pyx_PyNumber_Divide(x,y)         PyNumber_TrueDivide(x,y)
-  #define __Pyx_PyNumber_InPlaceDivide(x,y)  PyNumber_InPlaceTrueDivide(x,y)
-#endif
-
 #ifndef __PYX_EXTERN_C
   #ifdef __cplusplus
     #define __PYX_EXTERN_C extern "C"
@@ -305,7 +267,7 @@
 #   else
 #     define CYTHON_UNUSED
 #   endif
-# elif defined(__ICC) || (defined(__INTEL_COMPILER) && !defined(_MSC_VER))
+# elif defined(__ICC) || defined(__INTEL_COMPILER)
 #   define CYTHON_UNUSED __attribute__ ((__unused__))
 # else
 #   define CYTHON_UNUSED
@@ -330,7 +292,7 @@ static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t);
 static CYTHON_INLINE size_t __Pyx_PyInt_AsSize_t(PyObject*);
 
 #define __pyx_PyFloat_AsDouble(x) (PyFloat_CheckExact(x) ? PyFloat_AS_DOUBLE(x) : PyFloat_AsDouble(x))
-#define __pyx_PyFloat_AsFloat(x) ((float) __pyx_PyFloat_AsDouble(x))
+
 
 #ifdef __GNUC__
   /* Test for GCC > 2.95 */
@@ -355,6 +317,7 @@ static int __pyx_clineno = 0;
 static const char * __pyx_cfilenm= __FILE__;
 static const char *__pyx_filename;
 
+
 #if !defined(CYTHON_CCOMPLEX)
   #if defined(__cplusplus)
     #define CYTHON_CCOMPLEX 1
@@ -364,6 +327,7 @@ static const char *__pyx_filename;
     #define CYTHON_CCOMPLEX 0
   #endif
 #endif
+
 #if CYTHON_CCOMPLEX
   #ifdef __cplusplus
     #include <complex>
@@ -371,53 +335,18 @@ static const char *__pyx_filename;
     #include <complex.h>
   #endif
 #endif
+
 #if CYTHON_CCOMPLEX && !defined(__cplusplus) && defined(__sun__) && defined(__GNUC__)
   #undef _Complex_I
   #define _Complex_I 1.0fj
 #endif
 
-
 static const char *__pyx_f[] = {
   "boundary_wrap.pyx",
   "numpy.pxd",
 };
-#define IS_UNSIGNED(type) (((type) -1) > 0)
-struct __Pyx_StructField_;
-#define __PYX_BUF_FLAGS_PACKED_STRUCT (1 << 0)
-typedef struct {
-  const char* name; /* for error messages only */
-  struct __Pyx_StructField_* fields;
-  size_t size;     /* sizeof(type) */
-  size_t arraysize[8]; /* length of array in each dimension */
-  int ndim;
-  char typegroup; /* _R_eal, _C_omplex, Signed _I_nt, _U_nsigned int, _S_truct, _P_ointer, _O_bject */
-  char is_unsigned;
-  int flags;
-} __Pyx_TypeInfo;
-typedef struct __Pyx_StructField_ {
-  __Pyx_TypeInfo* type;
-  const char* name;
-  size_t offset;
-} __Pyx_StructField;
-typedef struct {
-  __Pyx_StructField* field;
-  size_t parent_offset;
-} __Pyx_BufFmt_StackElem;
-typedef struct {
-  __Pyx_StructField root;
-  __Pyx_BufFmt_StackElem* head;
-  size_t fmt_offset;
-  size_t new_count, enc_count;
-  size_t struct_alignment;
-  int is_complex;
-  char enc_type;
-  char new_packmode;
-  char enc_packmode;
-  char is_valid_array;
-} __Pyx_BufFmt_Context;
-
 
-/* "numpy.pxd":722
+/* "numpy.pxd":719
  * # in Cython to enable them only on the right systems.
  * 
  * ctypedef npy_int8       int8_t             # <<<<<<<<<<<<<<
@@ -426,7 +355,7 @@ typedef struct {
  */
 typedef npy_int8 __pyx_t_5numpy_int8_t;
 
-/* "numpy.pxd":723
+/* "numpy.pxd":720
  * 
  * ctypedef npy_int8       int8_t
  * ctypedef npy_int16      int16_t             # <<<<<<<<<<<<<<
@@ -435,7 +364,7 @@ typedef npy_int8 __pyx_t_5numpy_int8_t;
  */
 typedef npy_int16 __pyx_t_5numpy_int16_t;
 
-/* "numpy.pxd":724
+/* "numpy.pxd":721
  * ctypedef npy_int8       int8_t
  * ctypedef npy_int16      int16_t
  * ctypedef npy_int32      int32_t             # <<<<<<<<<<<<<<
@@ -444,7 +373,7 @@ typedef npy_int16 __pyx_t_5numpy_int16_t;
  */
 typedef npy_int32 __pyx_t_5numpy_int32_t;
 
-/* "numpy.pxd":725
+/* "numpy.pxd":722
  * ctypedef npy_int16      int16_t
  * ctypedef npy_int32      int32_t
  * ctypedef npy_int64      int64_t             # <<<<<<<<<<<<<<
@@ -453,7 +382,7 @@ typedef npy_int32 __pyx_t_5numpy_int32_t;
  */
 typedef npy_int64 __pyx_t_5numpy_int64_t;
 
-/* "numpy.pxd":729
+/* "numpy.pxd":726
  * #ctypedef npy_int128     int128_t
  * 
  * ctypedef npy_uint8      uint8_t             # <<<<<<<<<<<<<<
@@ -462,7 +391,7 @@ typedef npy_int64 __pyx_t_5numpy_int64_t;
  */
 typedef npy_uint8 __pyx_t_5numpy_uint8_t;
 
-/* "numpy.pxd":730
+/* "numpy.pxd":727
  * 
  * ctypedef npy_uint8      uint8_t
  * ctypedef npy_uint16     uint16_t             # <<<<<<<<<<<<<<
@@ -471,7 +400,7 @@ typedef npy_uint8 __pyx_t_5numpy_uint8_t;
  */
 typedef npy_uint16 __pyx_t_5numpy_uint16_t;
 
-/* "numpy.pxd":731
+/* "numpy.pxd":728
  * ctypedef npy_uint8      uint8_t
  * ctypedef npy_uint16     uint16_t
  * ctypedef npy_uint32     uint32_t             # <<<<<<<<<<<<<<
@@ -480,7 +409,7 @@ typedef npy_uint16 __pyx_t_5numpy_uint16_t;
  */
 typedef npy_uint32 __pyx_t_5numpy_uint32_t;
 
-/* "numpy.pxd":732
+/* "numpy.pxd":729
  * ctypedef npy_uint16     uint16_t
  * ctypedef npy_uint32     uint32_t
  * ctypedef npy_uint64     uint64_t             # <<<<<<<<<<<<<<
@@ -489,7 +418,7 @@ typedef npy_uint32 __pyx_t_5numpy_uint32_t;
  */
 typedef npy_uint64 __pyx_t_5numpy_uint64_t;
 
-/* "numpy.pxd":736
+/* "numpy.pxd":733
  * #ctypedef npy_uint128    uint128_t
  * 
  * ctypedef npy_float32    float32_t             # <<<<<<<<<<<<<<
@@ -498,7 +427,7 @@ typedef npy_uint64 __pyx_t_5numpy_uint64_t;
  */
 typedef npy_float32 __pyx_t_5numpy_float32_t;
 
-/* "numpy.pxd":737
+/* "numpy.pxd":734
  * 
  * ctypedef npy_float32    float32_t
  * ctypedef npy_float64    float64_t             # <<<<<<<<<<<<<<
@@ -507,7 +436,7 @@ typedef npy_float32 __pyx_t_5numpy_float32_t;
  */
 typedef npy_float64 __pyx_t_5numpy_float64_t;
 
-/* "numpy.pxd":746
+/* "numpy.pxd":743
  * # The int types are mapped a bit surprising --
  * # numpy.int corresponds to 'l' and numpy.long to 'q'
  * ctypedef npy_long       int_t             # <<<<<<<<<<<<<<
@@ -516,7 +445,7 @@ typedef npy_float64 __pyx_t_5numpy_float64_t;
  */
 typedef npy_long __pyx_t_5numpy_int_t;
 
-/* "numpy.pxd":747
+/* "numpy.pxd":744
  * # numpy.int corresponds to 'l' and numpy.long to 'q'
  * ctypedef npy_long       int_t
  * ctypedef npy_longlong   long_t             # <<<<<<<<<<<<<<
@@ -525,7 +454,7 @@ typedef npy_long __pyx_t_5numpy_int_t;
  */
 typedef npy_longlong __pyx_t_5numpy_long_t;
 
-/* "numpy.pxd":748
+/* "numpy.pxd":745
  * ctypedef npy_long       int_t
  * ctypedef npy_longlong   long_t
  * ctypedef npy_longlong   longlong_t             # <<<<<<<<<<<<<<
@@ -534,7 +463,7 @@ typedef npy_longlong __pyx_t_5numpy_long_t;
  */
 typedef npy_longlong __pyx_t_5numpy_longlong_t;
 
-/* "numpy.pxd":750
+/* "numpy.pxd":747
  * ctypedef npy_longlong   longlong_t
  * 
  * ctypedef npy_ulong      uint_t             # <<<<<<<<<<<<<<
@@ -543,7 +472,7 @@ typedef npy_longlong __pyx_t_5numpy_longlong_t;
  */
 typedef npy_ulong __pyx_t_5numpy_uint_t;
 
-/* "numpy.pxd":751
+/* "numpy.pxd":748
  * 
  * ctypedef npy_ulong      uint_t
  * ctypedef npy_ulonglong  ulong_t             # <<<<<<<<<<<<<<
@@ -552,7 +481,7 @@ typedef npy_ulong __pyx_t_5numpy_uint_t;
  */
 typedef npy_ulonglong __pyx_t_5numpy_ulong_t;
 
-/* "numpy.pxd":752
+/* "numpy.pxd":749
  * ctypedef npy_ulong      uint_t
  * ctypedef npy_ulonglong  ulong_t
  * ctypedef npy_ulonglong  ulonglong_t             # <<<<<<<<<<<<<<
@@ -561,7 +490,7 @@ typedef npy_ulonglong __pyx_t_5numpy_ulong_t;
  */
 typedef npy_ulonglong __pyx_t_5numpy_ulonglong_t;
 
-/* "numpy.pxd":754
+/* "numpy.pxd":751
  * ctypedef npy_ulonglong  ulonglong_t
  * 
  * ctypedef npy_intp       intp_t             # <<<<<<<<<<<<<<
@@ -570,7 +499,7 @@ typedef npy_ulonglong __pyx_t_5numpy_ulonglong_t;
  */
 typedef npy_intp __pyx_t_5numpy_intp_t;
 
-/* "numpy.pxd":755
+/* "numpy.pxd":752
  * 
  * ctypedef npy_intp       intp_t
  * ctypedef npy_uintp      uintp_t             # <<<<<<<<<<<<<<
@@ -579,7 +508,7 @@ typedef npy_intp __pyx_t_5numpy_intp_t;
  */
 typedef npy_uintp __pyx_t_5numpy_uintp_t;
 
-/* "numpy.pxd":757
+/* "numpy.pxd":754
  * ctypedef npy_uintp      uintp_t
  * 
  * ctypedef npy_double     float_t             # <<<<<<<<<<<<<<
@@ -588,7 +517,7 @@ typedef npy_uintp __pyx_t_5numpy_uintp_t;
  */
 typedef npy_double __pyx_t_5numpy_float_t;
 
-/* "numpy.pxd":758
+/* "numpy.pxd":755
  * 
  * ctypedef npy_double     float_t
  * ctypedef npy_double     double_t             # <<<<<<<<<<<<<<
@@ -597,7 +526,7 @@ typedef npy_double __pyx_t_5numpy_float_t;
  */
 typedef npy_double __pyx_t_5numpy_double_t;
 
-/* "numpy.pxd":759
+/* "numpy.pxd":756
  * ctypedef npy_double     float_t
  * ctypedef npy_double     double_t
  * ctypedef npy_longdouble longdouble_t             # <<<<<<<<<<<<<<
@@ -614,6 +543,7 @@ typedef npy_longdouble __pyx_t_5numpy_longdouble_t;
  * cdef extern from "numpy/npy_math.h":
  */
 typedef __pyx_t_5numpy_float_t __pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t;
+
 #if CYTHON_CCOMPLEX
   #ifdef __cplusplus
     typedef ::std::complex< float > __pyx_t_float_complex;
@@ -634,10 +564,9 @@ typedef __pyx_t_5numpy_float_t __pyx_t_7astropy_6nddata_11convolution_13boundary
     typedef struct { double real, imag; } __pyx_t_double_complex;
 #endif
 
-
 /*--- Type declarations ---*/
 
-/* "numpy.pxd":761
+/* "numpy.pxd":758
  * ctypedef npy_longdouble longdouble_t
  * 
  * ctypedef npy_cfloat      cfloat_t             # <<<<<<<<<<<<<<
@@ -646,7 +575,7 @@ typedef __pyx_t_5numpy_float_t __pyx_t_7astropy_6nddata_11convolution_13boundary
  */
 typedef npy_cfloat __pyx_t_5numpy_cfloat_t;
 
-/* "numpy.pxd":762
+/* "numpy.pxd":759
  * 
  * ctypedef npy_cfloat      cfloat_t
  * ctypedef npy_cdouble     cdouble_t             # <<<<<<<<<<<<<<
@@ -655,7 +584,7 @@ typedef npy_cfloat __pyx_t_5numpy_cfloat_t;
  */
 typedef npy_cdouble __pyx_t_5numpy_cdouble_t;
 
-/* "numpy.pxd":763
+/* "numpy.pxd":760
  * ctypedef npy_cfloat      cfloat_t
  * ctypedef npy_cdouble     cdouble_t
  * ctypedef npy_clongdouble clongdouble_t             # <<<<<<<<<<<<<<
@@ -664,7 +593,7 @@ typedef npy_cdouble __pyx_t_5numpy_cdouble_t;
  */
 typedef npy_clongdouble __pyx_t_5numpy_clongdouble_t;
 
-/* "numpy.pxd":765
+/* "numpy.pxd":762
  * ctypedef npy_clongdouble clongdouble_t
  * 
  * ctypedef npy_cdouble     complex_t             # <<<<<<<<<<<<<<
@@ -672,9 +601,12 @@ typedef npy_clongdouble __pyx_t_5numpy_clongdouble_t;
  * cdef inline object PyArray_MultiIterNew1(a):
  */
 typedef npy_cdouble __pyx_t_5numpy_complex_t;
+
+
 #ifndef CYTHON_REFNANNY
   #define CYTHON_REFNANNY 0
 #endif
+
 #if CYTHON_REFNANNY
   typedef struct {
     void (*INCREF)(void*, PyObject*, int);
@@ -687,21 +619,8 @@ typedef npy_cdouble __pyx_t_5numpy_complex_t;
   static __Pyx_RefNannyAPIStruct *__Pyx_RefNanny = NULL;
   static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname); /*proto*/
   #define __Pyx_RefNannyDeclarations void *__pyx_refnanny = NULL;
-#ifdef WITH_THREAD
-  #define __Pyx_RefNannySetupContext(name, acquire_gil) \
-          if (acquire_gil) { \
-              PyGILState_STATE __pyx_gilstate_save = PyGILState_Ensure(); \
-              __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__); \
-              PyGILState_Release(__pyx_gilstate_save); \
-          } else { \
-              __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__); \
-          }
-#else
-  #define __Pyx_RefNannySetupContext(name, acquire_gil) \
-          __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__)
-#endif
-  #define __Pyx_RefNannyFinishContext() \
-          __Pyx_RefNanny->FinishContext(&__pyx_refnanny)
+  #define __Pyx_RefNannySetupContext(name)           __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__)
+  #define __Pyx_RefNannyFinishContext()           __Pyx_RefNanny->FinishContext(&__pyx_refnanny)
   #define __Pyx_INCREF(r)  __Pyx_RefNanny->INCREF(__pyx_refnanny, (PyObject *)(r), __LINE__)
   #define __Pyx_DECREF(r)  __Pyx_RefNanny->DECREF(__pyx_refnanny, (PyObject *)(r), __LINE__)
   #define __Pyx_GOTREF(r)  __Pyx_RefNanny->GOTREF(__pyx_refnanny, (PyObject *)(r), __LINE__)
@@ -712,7 +631,7 @@ typedef npy_cdouble __pyx_t_5numpy_complex_t;
   #define __Pyx_XGIVEREF(r) do { if((r) != NULL) {__Pyx_GIVEREF(r);}} while(0)
 #else
   #define __Pyx_RefNannyDeclarations
-  #define __Pyx_RefNannySetupContext(name, acquire_gil)
+  #define __Pyx_RefNannySetupContext(name)
   #define __Pyx_RefNannyFinishContext()
   #define __Pyx_INCREF(r) Py_INCREF(r)
   #define __Pyx_DECREF(r) Py_DECREF(r)
@@ -723,25 +642,43 @@ typedef npy_cdouble __pyx_t_5numpy_complex_t;
   #define __Pyx_XGOTREF(r)
   #define __Pyx_XGIVEREF(r)
 #endif /* CYTHON_REFNANNY */
-#define __Pyx_CLEAR(r)    do { PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);} while(0)
-#define __Pyx_XCLEAR(r)   do { if((r) != NULL) {PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);}} while(0)
 
 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/
 
 static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact,
     Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found); /*proto*/
 
-static void __Pyx_RaiseDoubleKeywordsError(const char* func_name, PyObject* kw_name); /*proto*/
+static void __Pyx_RaiseDoubleKeywordsError(
+    const char* func_name, PyObject* kw_name); /*proto*/
 
-static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[], \
-    PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args, \
-    const char* function_name); /*proto*/
+static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[],     PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args,     const char* function_name); /*proto*/
 
 static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
     const char *name, int exact); /*proto*/
 
-static CYTHON_INLINE int  __Pyx_GetBufferAndValidate(Py_buffer* buf, PyObject* obj,
-    __Pyx_TypeInfo* dtype, int flags, int nd, int cast, __Pyx_BufFmt_StackElem* stack);
+/* Run-time type information about structs used with buffers */
+struct __Pyx_StructField_;
+
+typedef struct {
+  const char* name; /* for error messages only */
+  struct __Pyx_StructField_* fields;
+  size_t size;     /* sizeof(type) */
+  char typegroup; /* _R_eal, _C_omplex, Signed _I_nt, _U_nsigned int, _S_truct, _P_ointer, _O_bject */
+} __Pyx_TypeInfo;
+
+typedef struct __Pyx_StructField_ {
+  __Pyx_TypeInfo* type;
+  const char* name;
+  size_t offset;
+} __Pyx_StructField;
+
+typedef struct {
+  __Pyx_StructField* field;
+  size_t parent_offset;
+} __Pyx_BufFmt_StackElem;
+
+
+static CYTHON_INLINE int  __Pyx_GetBufferAndValidate(Py_buffer* buf, PyObject* obj, __Pyx_TypeInfo* dtype, int flags, int nd, int cast, __Pyx_BufFmt_StackElem* stack);
 static CYTHON_INLINE void __Pyx_SafeReleaseBuffer(Py_buffer* info);
 
 static CYTHON_INLINE long __Pyx_mod_long(long, long); /* proto */
@@ -754,12 +691,12 @@ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject
 static CYTHON_INLINE long __Pyx_div_long(long, long); /* proto */
 
 static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); /*proto*/
-
 #define __Pyx_BufPtrStrided1d(type, buf, i0, s0) (type)((char*)buf + i0 * s0)
-static CYTHON_INLINE int __Pyx_mod_int(int, int); /* proto */
 
+static CYTHON_INLINE int __Pyx_mod_int(int, int); /* proto */
 #define __Pyx_BufPtrStrided2d(type, buf, i0, s0, i1, s1) (type)((char*)buf + i0 * s0 + i1 * s1)
 #define __Pyx_BufPtrStrided3d(type, buf, i0, s0, i1, s1, i2, s2) (type)((char*)buf + i0 * s0 + i1 * s1 + i2 * s2)
+
 static CYTHON_INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index);
 
 static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(Py_ssize_t expected);
@@ -767,30 +704,16 @@ static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(Py_ssize_t expected);
 static CYTHON_INLINE void __Pyx_RaiseNoneNotIterableError(void);
 
 static void __Pyx_UnpackTupleError(PyObject *, Py_ssize_t index); /*proto*/
-
-typedef struct {
-  Py_ssize_t shape, strides, suboffsets;
-} __Pyx_Buf_DimInfo;
-typedef struct {
-  size_t refcount;
-  Py_buffer pybuffer;
-} __Pyx_Buffer;
-typedef struct {
-  __Pyx_Buffer *rcbuffer;
-  char *data;
-  __Pyx_Buf_DimInfo diminfo[8];
-} __Pyx_LocalBuf_ND;
-
 #if PY_MAJOR_VERSION < 3
-    static int __Pyx_GetBuffer(PyObject *obj, Py_buffer *view, int flags);
-    static void __Pyx_ReleaseBuffer(Py_buffer *view);
+static int __Pyx_GetBuffer(PyObject *obj, Py_buffer *view, int flags);
+static void __Pyx_ReleaseBuffer(Py_buffer *view);
 #else
-    #define __Pyx_GetBuffer PyObject_GetBuffer
-    #define __Pyx_ReleaseBuffer PyBuffer_Release
+#define __Pyx_GetBuffer PyObject_GetBuffer
+#define __Pyx_ReleaseBuffer PyBuffer_Release
 #endif
 
-static Py_ssize_t __Pyx_zeros[] = {0, 0, 0, 0, 0, 0, 0, 0};
-static Py_ssize_t __Pyx_minusones[] = {-1, -1, -1, -1, -1, -1, -1, -1};
+Py_ssize_t __Pyx_zeros[] = {0, 0, 0};
+Py_ssize_t __Pyx_minusones[] = {-1, -1, -1};
 
 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, long level); /*proto*/
 
@@ -806,6 +729,7 @@ static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, long level);
     #define __Pyx_CREAL(z) ((z).real)
     #define __Pyx_CIMAG(z) ((z).imag)
 #endif
+
 #if defined(_WIN32) && defined(__cplusplus) && CYTHON_CCOMPLEX
     #define __Pyx_SET_CREAL(z,x) ((z).real(x))
     #define __Pyx_SET_CIMAG(z,y) ((z).imag(y))
@@ -926,38 +850,15 @@ static CYTHON_INLINE signed PY_LONG_LONG __Pyx_PyInt_AsSignedLongLong(PyObject *
 
 static int __Pyx_check_binary_version(void);
 
-#if !defined(__Pyx_PyIdentifier_FromString)
-#if PY_MAJOR_VERSION < 3
-  #define __Pyx_PyIdentifier_FromString(s) PyString_FromString(s)
-#else
-  #define __Pyx_PyIdentifier_FromString(s) PyUnicode_FromString(s)
-#endif
-#endif
-
 static PyTypeObject *__Pyx_ImportType(const char *module_name, const char *class_name, size_t size, int strict);  /*proto*/
 
 static PyObject *__Pyx_ImportModule(const char *name); /*proto*/
 
-typedef struct {
-    int code_line;
-    PyCodeObject* code_object;
-} __Pyx_CodeObjectCacheEntry;
-struct __Pyx_CodeObjectCache {
-    int count;
-    int max_count;
-    __Pyx_CodeObjectCacheEntry* entries;
-};
-static struct __Pyx_CodeObjectCache __pyx_code_cache = {0,0,NULL};
-static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line);
-static PyCodeObject *__pyx_find_code_object(int code_line);
-static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object);
-
-static void __Pyx_AddTraceback(const char *funcname, int c_line,
-                               int py_line, const char *filename); /*proto*/
+static void __Pyx_AddTraceback(const char *funcname, int __pyx_clineno,
+                               int __pyx_lineno, const char *__pyx_filename); /*proto*/
 
 static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); /*proto*/
 
-
 /* Module declarations from 'cpython.buffer' */
 
 /* Module declarations from 'cpython.ref' */
@@ -976,12 +877,21 @@ static PyTypeObject *__pyx_ptype_5numpy_flatiter = 0;
 static PyTypeObject *__pyx_ptype_5numpy_broadcast = 0;
 static PyTypeObject *__pyx_ptype_5numpy_ndarray = 0;
 static PyTypeObject *__pyx_ptype_5numpy_ufunc = 0;
+static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew1(PyObject *); /*proto*/
+static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew2(PyObject *, PyObject *); /*proto*/
+static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew3(PyObject *, PyObject *, PyObject *); /*proto*/
+static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew4(PyObject *, PyObject *, PyObject *, PyObject *); /*proto*/
+static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew5(PyObject *, PyObject *, PyObject *, PyObject *, PyObject *); /*proto*/
 static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *, char *, char *, int *); /*proto*/
+static CYTHON_INLINE void __pyx_f_5numpy_set_array_base(PyArrayObject *, PyObject *); /*proto*/
+static CYTHON_INLINE PyObject *__pyx_f_5numpy_get_array_base(PyArrayObject *); /*proto*/
+
+/* Module declarations from 'cython.cython.view' */
 
 /* Module declarations from 'cython' */
 
 /* Module declarations from 'astropy.nddata.convolution.boundary_wrap' */
-static __Pyx_TypeInfo __Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t = { "DTYPE_t", NULL, sizeof(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t), { 0 }, 0, 'R', 0, 0 };
+static __Pyx_TypeInfo __Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t = { "DTYPE_t", NULL, sizeof(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t), 'R' };
 #define __Pyx_MODULE_NAME "astropy.nddata.convolution.boundary_wrap"
 int __pyx_module_is_main_astropy__nddata__convolution__boundary_wrap = 0;
 
@@ -989,11 +899,6 @@ int __pyx_module_is_main_astropy__nddata__convolution__boundary_wrap = 0;
 static PyObject *__pyx_builtin_ValueError;
 static PyObject *__pyx_builtin_range;
 static PyObject *__pyx_builtin_RuntimeError;
-static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_convolve1d_boundary_wrap(CYTHON_UNUSED PyObject *__pyx_self, PyArrayObject *__pyx_v_f, PyArrayObject *__pyx_v_g); /* proto */
-static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_2convolve2d_boundary_wrap(CYTHON_UNUSED PyObject *__pyx_self, PyArrayObject *__pyx_v_f, PyArrayObject *__pyx_v_g); /* proto */
-static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_4convolve3d_boundary_wrap(CYTHON_UNUSED PyObject *__pyx_self, PyArrayObject *__pyx_v_f, PyArrayObject *__pyx_v_g); /* proto */
-static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags); /* proto */
-static void __pyx_pf_5numpy_7ndarray_2__releasebuffer__(PyArrayObject *__pyx_v_self, Py_buffer *__pyx_v_info); /* proto */
 static char __pyx_k_1[] = "Convolution kernel must have odd dimensions";
 static char __pyx_k_5[] = "ndarray is not C contiguous";
 static char __pyx_k_7[] = "ndarray is not Fortran contiguous";
@@ -1001,11 +906,10 @@ static char __pyx_k_9[] = "Non-native byte order not supported";
 static char __pyx_k_11[] = "unknown dtype code in numpy.pxd (%d)";
 static char __pyx_k_12[] = "Format string allocated too short, see comment in numpy.pxd";
 static char __pyx_k_15[] = "Format string allocated too short.";
-static char __pyx_k_19[] = "convolve1d_boundary_wrap";
-static char __pyx_k_20[] = "/Users/erik/src/astropy/astropy/nddata/convolution/boundary_wrap.pyx";
-static char __pyx_k_21[] = "astropy.nddata.convolution.boundary_wrap";
-static char __pyx_k_24[] = "convolve2d_boundary_wrap";
-static char __pyx_k_27[] = "convolve3d_boundary_wrap";
+static char __pyx_k_17[] = "astropy.nddata.convolution.boundary_wrap";
+static char __pyx_k_18[] = "convolve1d_boundary_wrap";
+static char __pyx_k_19[] = "convolve2d_boundary_wrap";
+static char __pyx_k_20[] = "convolve3d_boundary_wrap";
 static char __pyx_k__B[] = "B";
 static char __pyx_k__H[] = "H";
 static char __pyx_k__I[] = "I";
@@ -1018,45 +922,16 @@ static char __pyx_k__f[] = "f";
 static char __pyx_k__g[] = "g";
 static char __pyx_k__h[] = "h";
 static char __pyx_k__i[] = "i";
-static char __pyx_k__j[] = "j";
-static char __pyx_k__k[] = "k";
 static char __pyx_k__l[] = "l";
 static char __pyx_k__q[] = "q";
 static char __pyx_k__Zd[] = "Zd";
 static char __pyx_k__Zf[] = "Zf";
 static char __pyx_k__Zg[] = "Zg";
-static char __pyx_k__ii[] = "ii";
-static char __pyx_k__jj[] = "jj";
-static char __pyx_k__kk[] = "kk";
 static char __pyx_k__np[] = "np";
-static char __pyx_k__nx[] = "nx";
-static char __pyx_k__ny[] = "ny";
-static char __pyx_k__nz[] = "nz";
-static char __pyx_k__bot[] = "bot";
-static char __pyx_k__iii[] = "iii";
-static char __pyx_k__jjj[] = "jjj";
-static char __pyx_k__ker[] = "ker";
-static char __pyx_k__kkk[] = "kkk";
-static char __pyx_k__nkx[] = "nkx";
-static char __pyx_k__nky[] = "nky";
-static char __pyx_k__nkz[] = "nkz";
-static char __pyx_k__top[] = "top";
-static char __pyx_k__val[] = "val";
-static char __pyx_k__wkx[] = "wkx";
-static char __pyx_k__wky[] = "wky";
-static char __pyx_k__wkz[] = "wkz";
-static char __pyx_k__conv[] = "conv";
 static char __pyx_k__DTYPE[] = "DTYPE";
 static char __pyx_k__dtype[] = "dtype";
 static char __pyx_k__empty[] = "empty";
-static char __pyx_k__fixed[] = "fixed";
 static char __pyx_k__float[] = "float";
-static char __pyx_k__iimax[] = "iimax";
-static char __pyx_k__iimin[] = "iimin";
-static char __pyx_k__jjmax[] = "jjmax";
-static char __pyx_k__jjmin[] = "jjmin";
-static char __pyx_k__kkmax[] = "kkmax";
-static char __pyx_k__kkmin[] = "kkmin";
 static char __pyx_k__numpy[] = "numpy";
 static char __pyx_k__range[] = "range";
 static char __pyx_k____main__[] = "__main__";
@@ -1067,11 +942,10 @@ static PyObject *__pyx_kp_s_1;
 static PyObject *__pyx_kp_u_11;
 static PyObject *__pyx_kp_u_12;
 static PyObject *__pyx_kp_u_15;
+static PyObject *__pyx_n_s_17;
+static PyObject *__pyx_n_s_18;
 static PyObject *__pyx_n_s_19;
-static PyObject *__pyx_kp_s_20;
-static PyObject *__pyx_n_s_21;
-static PyObject *__pyx_n_s_24;
-static PyObject *__pyx_n_s_27;
+static PyObject *__pyx_n_s_20;
 static PyObject *__pyx_kp_u_5;
 static PyObject *__pyx_kp_u_7;
 static PyObject *__pyx_kp_u_9;
@@ -1080,44 +954,14 @@ static PyObject *__pyx_n_s__RuntimeError;
 static PyObject *__pyx_n_s__ValueError;
 static PyObject *__pyx_n_s____main__;
 static PyObject *__pyx_n_s____test__;
-static PyObject *__pyx_n_s__bot;
-static PyObject *__pyx_n_s__conv;
 static PyObject *__pyx_n_s__dtype;
 static PyObject *__pyx_n_s__empty;
 static PyObject *__pyx_n_s__f;
-static PyObject *__pyx_n_s__fixed;
 static PyObject *__pyx_n_s__float;
 static PyObject *__pyx_n_s__g;
-static PyObject *__pyx_n_s__i;
-static PyObject *__pyx_n_s__ii;
-static PyObject *__pyx_n_s__iii;
-static PyObject *__pyx_n_s__iimax;
-static PyObject *__pyx_n_s__iimin;
-static PyObject *__pyx_n_s__j;
-static PyObject *__pyx_n_s__jj;
-static PyObject *__pyx_n_s__jjj;
-static PyObject *__pyx_n_s__jjmax;
-static PyObject *__pyx_n_s__jjmin;
-static PyObject *__pyx_n_s__k;
-static PyObject *__pyx_n_s__ker;
-static PyObject *__pyx_n_s__kk;
-static PyObject *__pyx_n_s__kkk;
-static PyObject *__pyx_n_s__kkmax;
-static PyObject *__pyx_n_s__kkmin;
-static PyObject *__pyx_n_s__nkx;
-static PyObject *__pyx_n_s__nky;
-static PyObject *__pyx_n_s__nkz;
 static PyObject *__pyx_n_s__np;
 static PyObject *__pyx_n_s__numpy;
-static PyObject *__pyx_n_s__nx;
-static PyObject *__pyx_n_s__ny;
-static PyObject *__pyx_n_s__nz;
 static PyObject *__pyx_n_s__range;
-static PyObject *__pyx_n_s__top;
-static PyObject *__pyx_n_s__val;
-static PyObject *__pyx_n_s__wkx;
-static PyObject *__pyx_n_s__wky;
-static PyObject *__pyx_n_s__wkz;
 static PyObject *__pyx_int_15;
 static PyObject *__pyx_k_tuple_2;
 static PyObject *__pyx_k_tuple_3;
@@ -1128,78 +972,6 @@ static PyObject *__pyx_k_tuple_10;
 static PyObject *__pyx_k_tuple_13;
 static PyObject *__pyx_k_tuple_14;
 static PyObject *__pyx_k_tuple_16;
-static PyObject *__pyx_k_tuple_17;
-static PyObject *__pyx_k_tuple_22;
-static PyObject *__pyx_k_tuple_25;
-static PyObject *__pyx_k_codeobj_18;
-static PyObject *__pyx_k_codeobj_23;
-static PyObject *__pyx_k_codeobj_26;
-
-/* Python wrapper */
-static PyObject *__pyx_pw_7astropy_6nddata_11convolution_13boundary_wrap_1convolve1d_boundary_wrap(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static PyMethodDef __pyx_mdef_7astropy_6nddata_11convolution_13boundary_wrap_1convolve1d_boundary_wrap = {__Pyx_NAMESTR("convolve1d_boundary_wrap"), (PyCFunction)__pyx_pw_7astropy_6nddata_11convolution_13boundary_wrap_1convolve1d_boundary_wrap, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(0)};
-static PyObject *__pyx_pw_7astropy_6nddata_11convolution_13boundary_wrap_1convolve1d_boundary_wrap(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
-  PyArrayObject *__pyx_v_f = 0;
-  PyArrayObject *__pyx_v_g = 0;
-  static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__f,&__pyx_n_s__g,0};
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("convolve1d_boundary_wrap (wrapper)", 0);
-  __pyx_self = __pyx_self;
-  {
-    PyObject* values[2] = {0,0};
-    if (unlikely(__pyx_kwds)) {
-      Py_ssize_t kw_args;
-      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
-      switch (pos_args) {
-        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
-        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
-        case  0: break;
-        default: goto __pyx_L5_argtuple_error;
-      }
-      kw_args = PyDict_Size(__pyx_kwds);
-      switch (pos_args) {
-        case  0:
-        values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__f);
-        if (likely(values[0])) kw_args--;
-        else goto __pyx_L5_argtuple_error;
-        case  1:
-        values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__g);
-        if (likely(values[1])) kw_args--;
-        else {
-          __Pyx_RaiseArgtupleInvalid("convolve1d_boundary_wrap", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-        }
-      }
-      if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "convolve1d_boundary_wrap") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-      }
-    } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
-      goto __pyx_L5_argtuple_error;
-    } else {
-      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
-      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
-    }
-    __pyx_v_f = ((PyArrayObject *)values[0]);
-    __pyx_v_g = ((PyArrayObject *)values[1]);
-  }
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("convolve1d_boundary_wrap", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-  __pyx_L3_error:;
-  __Pyx_AddTraceback("astropy.nddata.convolution.boundary_wrap.convolve1d_boundary_wrap", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return NULL;
-  __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_f), __pyx_ptype_5numpy_ndarray, 1, "f", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_g), __pyx_ptype_5numpy_ndarray, 1, "g", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 16; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_r = __pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_convolve1d_boundary_wrap(__pyx_self, __pyx_v_f, __pyx_v_g);
-  goto __pyx_L0;
-  __pyx_L1_error:;
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
 
 /* "astropy/nddata/convolution/boundary_wrap.pyx":15
  * 
@@ -1209,7 +981,11 @@ static PyObject *__pyx_pw_7astropy_6nddata_11convolution_13boundary_wrap_1convol
  * 
  */
 
-static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_convolve1d_boundary_wrap(CYTHON_UNUSED PyObject *__pyx_self, PyArrayObject *__pyx_v_f, PyArrayObject *__pyx_v_g) {
+static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_convolve1d_boundary_wrap(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static PyMethodDef __pyx_mdef_7astropy_6nddata_11convolution_13boundary_wrap_convolve1d_boundary_wrap = {__Pyx_NAMESTR("convolve1d_boundary_wrap"), (PyCFunction)__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_convolve1d_boundary_wrap, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(0)};
+static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_convolve1d_boundary_wrap(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyArrayObject *__pyx_v_f = 0;
+  PyArrayObject *__pyx_v_g = 0;
   int __pyx_v_nx;
   int __pyx_v_nkx;
   int __pyx_v_wkx;
@@ -1224,14 +1000,18 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_convolv
   __pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t __pyx_v_bot;
   __pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t __pyx_v_ker;
   __pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t __pyx_v_val;
-  __Pyx_LocalBuf_ND __pyx_pybuffernd_conv;
-  __Pyx_Buffer __pyx_pybuffer_conv;
-  __Pyx_LocalBuf_ND __pyx_pybuffernd_f;
-  __Pyx_Buffer __pyx_pybuffer_f;
-  __Pyx_LocalBuf_ND __pyx_pybuffernd_fixed;
-  __Pyx_Buffer __pyx_pybuffer_fixed;
-  __Pyx_LocalBuf_ND __pyx_pybuffernd_g;
-  __Pyx_Buffer __pyx_pybuffer_g;
+  Py_buffer __pyx_bstruct_conv;
+  Py_ssize_t __pyx_bstride_0_conv = 0;
+  Py_ssize_t __pyx_bshape_0_conv = 0;
+  Py_buffer __pyx_bstruct_g;
+  Py_ssize_t __pyx_bstride_0_g = 0;
+  Py_ssize_t __pyx_bshape_0_g = 0;
+  Py_buffer __pyx_bstruct_f;
+  Py_ssize_t __pyx_bstride_0_f = 0;
+  Py_ssize_t __pyx_bshape_0_f = 0;
+  Py_buffer __pyx_bstruct_fixed;
+  Py_ssize_t __pyx_bstride_0_fixed = 0;
+  Py_ssize_t __pyx_bshape_0_fixed = 0;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   int __pyx_t_1;
@@ -1266,33 +1046,70 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_convolv
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("convolve1d_boundary_wrap", 0);
-  __pyx_pybuffer_fixed.pybuffer.buf = NULL;
-  __pyx_pybuffer_fixed.refcount = 0;
-  __pyx_pybuffernd_fixed.data = NULL;
-  __pyx_pybuffernd_fixed.rcbuffer = &__pyx_pybuffer_fixed;
-  __pyx_pybuffer_conv.pybuffer.buf = NULL;
-  __pyx_pybuffer_conv.refcount = 0;
-  __pyx_pybuffernd_conv.data = NULL;
-  __pyx_pybuffernd_conv.rcbuffer = &__pyx_pybuffer_conv;
-  __pyx_pybuffer_f.pybuffer.buf = NULL;
-  __pyx_pybuffer_f.refcount = 0;
-  __pyx_pybuffernd_f.data = NULL;
-  __pyx_pybuffernd_f.rcbuffer = &__pyx_pybuffer_f;
-  __pyx_pybuffer_g.pybuffer.buf = NULL;
-  __pyx_pybuffer_g.refcount = 0;
-  __pyx_pybuffernd_g.data = NULL;
-  __pyx_pybuffernd_g.rcbuffer = &__pyx_pybuffer_g;
+  static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__f,&__pyx_n_s__g,0};
+  __Pyx_RefNannySetupContext("convolve1d_boundary_wrap");
+  __pyx_self = __pyx_self;
+  {
+    PyObject* values[2] = {0,0};
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  0:
+        values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__f);
+        if (likely(values[0])) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+        case  1:
+        values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__g);
+        if (likely(values[1])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("convolve1d_boundary_wrap", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "convolve1d_boundary_wrap") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+    } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
+      goto __pyx_L5_argtuple_error;
+    } else {
+      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+    }
+    __pyx_v_f = ((PyArrayObject *)values[0]);
+    __pyx_v_g = ((PyArrayObject *)values[1]);
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("convolve1d_boundary_wrap", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("astropy.nddata.convolution.boundary_wrap.convolve1d_boundary_wrap", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_bstruct_fixed.buf = NULL;
+  __pyx_bstruct_conv.buf = NULL;
+  __pyx_bstruct_f.buf = NULL;
+  __pyx_bstruct_g.buf = NULL;
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_f), __pyx_ptype_5numpy_ndarray, 1, "f", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_g), __pyx_ptype_5numpy_ndarray, 1, "g", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 16; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_f.rcbuffer->pybuffer, (PyObject*)__pyx_v_f, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_f, (PyObject*)__pyx_v_f, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
-  __pyx_pybuffernd_f.diminfo[0].strides = __pyx_pybuffernd_f.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_f.diminfo[0].shape = __pyx_pybuffernd_f.rcbuffer->pybuffer.shape[0];
+  __pyx_bstride_0_f = __pyx_bstruct_f.strides[0];
+  __pyx_bshape_0_f = __pyx_bstruct_f.shape[0];
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_g.rcbuffer->pybuffer, (PyObject*)__pyx_v_g, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_g, (PyObject*)__pyx_v_g, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
-  __pyx_pybuffernd_g.diminfo[0].strides = __pyx_pybuffernd_g.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_g.diminfo[0].shape = __pyx_pybuffernd_g.rcbuffer->pybuffer.shape[0];
+  __pyx_bstride_0_g = __pyx_bstruct_g.strides[0];
+  __pyx_bshape_0_g = __pyx_bstruct_g.shape[0];
 
   /* "astropy/nddata/convolution/boundary_wrap.pyx":18
  *                              np.ndarray[DTYPE_t, ndim=1] g):
@@ -1316,9 +1133,9 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_convolv
     __Pyx_Raise(__pyx_t_2, 0, 0, 0);
     __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
     {__pyx_filename = __pyx_f[0]; __pyx_lineno = 19; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    goto __pyx_L3;
+    goto __pyx_L6;
   }
-  __pyx_L3:;
+  __pyx_L6:;
 
   /* "astropy/nddata/convolution/boundary_wrap.pyx":21
  *         raise ValueError("Convolution kernel must have odd dimensions")
@@ -1401,12 +1218,12 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_convolv
   __pyx_t_2 = PyInt_FromLong(__pyx_v_nx); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 26; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
   __pyx_t_4 = PyList_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 26; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_4);
+  __Pyx_GOTREF(((PyObject *)__pyx_t_4));
   PyList_SET_ITEM(__pyx_t_4, 0, __pyx_t_2);
   __Pyx_GIVEREF(__pyx_t_2);
   __pyx_t_2 = 0;
   __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 26; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_GOTREF(((PyObject *)__pyx_t_2));
   PyTuple_SET_ITEM(__pyx_t_2, 0, ((PyObject *)__pyx_t_4));
   __Pyx_GIVEREF(((PyObject *)__pyx_t_4));
   __pyx_t_4 = 0;
@@ -1416,7 +1233,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_convolv
   __Pyx_GOTREF(__pyx_t_7);
   if (PyDict_SetItem(__pyx_t_4, ((PyObject *)__pyx_n_s__dtype), __pyx_t_7) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 26; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-  __pyx_t_7 = PyObject_Call(__pyx_t_3, ((PyObject *)__pyx_t_2), ((PyObject *)__pyx_t_4)); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 26; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_7 = PyEval_CallObjectWithKeywords(__pyx_t_3, ((PyObject *)__pyx_t_2), ((PyObject *)__pyx_t_4)); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 26; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_7);
   __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
   __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
@@ -1425,10 +1242,11 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_convolv
   __pyx_t_8 = ((PyArrayObject *)__pyx_t_7);
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_fixed.rcbuffer->pybuffer, (PyObject*)__pyx_t_8, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 1, 0, __pyx_stack) == -1)) {
-      __pyx_v_fixed = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf = NULL;
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_fixed, (PyObject*)__pyx_t_8, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 1, 0, __pyx_stack) == -1)) {
+      __pyx_v_fixed = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_fixed.buf = NULL;
       {__pyx_filename = __pyx_f[0]; __pyx_lineno = 26; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    } else {__pyx_pybuffernd_fixed.diminfo[0].strides = __pyx_pybuffernd_fixed.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_fixed.diminfo[0].shape = __pyx_pybuffernd_fixed.rcbuffer->pybuffer.shape[0];
+    } else {__pyx_bstride_0_fixed = __pyx_bstruct_fixed.strides[0];
+      __pyx_bshape_0_fixed = __pyx_bstruct_fixed.shape[0];
     }
   }
   __pyx_t_8 = 0;
@@ -1450,12 +1268,12 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_convolv
   __pyx_t_7 = PyInt_FromLong(__pyx_v_nx); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_7);
   __pyx_t_2 = PyList_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_GOTREF(((PyObject *)__pyx_t_2));
   PyList_SET_ITEM(__pyx_t_2, 0, __pyx_t_7);
   __Pyx_GIVEREF(__pyx_t_7);
   __pyx_t_7 = 0;
   __pyx_t_7 = PyTuple_New(1); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_7);
+  __Pyx_GOTREF(((PyObject *)__pyx_t_7));
   PyTuple_SET_ITEM(__pyx_t_7, 0, ((PyObject *)__pyx_t_2));
   __Pyx_GIVEREF(((PyObject *)__pyx_t_2));
   __pyx_t_2 = 0;
@@ -1465,7 +1283,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_convolv
   __Pyx_GOTREF(__pyx_t_3);
   if (PyDict_SetItem(__pyx_t_2, ((PyObject *)__pyx_n_s__dtype), __pyx_t_3) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  __pyx_t_3 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_t_7), ((PyObject *)__pyx_t_2)); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_3 = PyEval_CallObjectWithKeywords(__pyx_t_4, ((PyObject *)__pyx_t_7), ((PyObject *)__pyx_t_2)); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_3);
   __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
   __Pyx_DECREF(((PyObject *)__pyx_t_7)); __pyx_t_7 = 0;
@@ -1474,10 +1292,11 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_convolv
   __pyx_t_9 = ((PyArrayObject *)__pyx_t_3);
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_conv.rcbuffer->pybuffer, (PyObject*)__pyx_t_9, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 1, 0, __pyx_stack) == -1)) {
-      __pyx_v_conv = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_conv.rcbuffer->pybuffer.buf = NULL;
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_conv, (PyObject*)__pyx_t_9, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 1, 0, __pyx_stack) == -1)) {
+      __pyx_v_conv = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_conv.buf = NULL;
       {__pyx_filename = __pyx_f[0]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    } else {__pyx_pybuffernd_conv.diminfo[0].strides = __pyx_pybuffernd_conv.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_conv.diminfo[0].shape = __pyx_pybuffernd_conv.rcbuffer->pybuffer.shape[0];
+    } else {__pyx_bstride_0_conv = __pyx_bstruct_conv.strides[0];
+      __pyx_bshape_0_conv = __pyx_bstruct_conv.shape[0];
     }
   }
   __pyx_t_9 = 0;
@@ -1503,7 +1322,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_convolv
  *             bot = 0.
  */
     __pyx_t_12 = __pyx_v_i;
-    __pyx_t_6 = npy_isnan((*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_pybuffernd_f.rcbuffer->pybuffer.buf, __pyx_t_12, __pyx_pybuffernd_f.diminfo[0].strides)));
+    __pyx_t_6 = npy_isnan((*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_bstruct_f.buf, __pyx_t_12, __pyx_bstride_0_f)));
     if (__pyx_t_6) {
 
       /* "astropy/nddata/convolution/boundary_wrap.pyx":39
@@ -1574,7 +1393,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_convolv
  *                     ker = g[<unsigned int>(wkx + ii - i)]
  */
         __pyx_t_15 = __pyx_v_iii;
-        __pyx_v_val = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_pybuffernd_f.rcbuffer->pybuffer.buf, __pyx_t_15, __pyx_pybuffernd_f.diminfo[0].strides));
+        __pyx_v_val = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_bstruct_f.buf, __pyx_t_15, __pyx_bstride_0_f));
 
         /* "astropy/nddata/convolution/boundary_wrap.pyx":46
  *                 iii = ii % nx
@@ -1594,7 +1413,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_convolv
  *                     bot += ker
  */
           __pyx_t_16 = ((unsigned int)((__pyx_v_wkx + __pyx_v_ii) - __pyx_v_i));
-          __pyx_v_ker = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_pybuffernd_g.rcbuffer->pybuffer.buf, __pyx_t_16, __pyx_pybuffernd_g.diminfo[0].strides));
+          __pyx_v_ker = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_bstruct_g.buf, __pyx_t_16, __pyx_bstride_0_g));
 
           /* "astropy/nddata/convolution/boundary_wrap.pyx":48
  *                 if not npy_isnan(val):
@@ -1613,9 +1432,9 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_convolv
  *             if bot != 0.:
  */
           __pyx_v_bot = (__pyx_v_bot + __pyx_v_ker);
-          goto __pyx_L9;
+          goto __pyx_L12;
         }
-        __pyx_L9:;
+        __pyx_L12:;
       }
 
       /* "astropy/nddata/convolution/boundary_wrap.pyx":51
@@ -1640,8 +1459,8 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_convolv
           {__pyx_filename = __pyx_f[0]; __pyx_lineno = 52; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         }
         __pyx_t_17 = __pyx_v_i;
-        *__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_17, __pyx_pybuffernd_fixed.diminfo[0].strides) = (__pyx_v_top / __pyx_v_bot);
-        goto __pyx_L10;
+        *__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_17, __pyx_bstride_0_fixed) = (__pyx_v_top / __pyx_v_bot);
+        goto __pyx_L13;
       }
       /*else*/ {
 
@@ -1654,10 +1473,10 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_convolv
  */
         __pyx_t_18 = __pyx_v_i;
         __pyx_t_19 = __pyx_v_i;
-        *__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_19, __pyx_pybuffernd_fixed.diminfo[0].strides) = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_pybuffernd_f.rcbuffer->pybuffer.buf, __pyx_t_18, __pyx_pybuffernd_f.diminfo[0].strides));
+        *__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_19, __pyx_bstride_0_fixed) = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_bstruct_f.buf, __pyx_t_18, __pyx_bstride_0_f));
       }
-      __pyx_L10:;
-      goto __pyx_L6;
+      __pyx_L13:;
+      goto __pyx_L9;
     }
     /*else*/ {
 
@@ -1670,9 +1489,9 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_convolv
  */
       __pyx_t_20 = __pyx_v_i;
       __pyx_t_21 = __pyx_v_i;
-      *__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_21, __pyx_pybuffernd_fixed.diminfo[0].strides) = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_pybuffernd_f.rcbuffer->pybuffer.buf, __pyx_t_20, __pyx_pybuffernd_f.diminfo[0].strides));
+      *__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_21, __pyx_bstride_0_fixed) = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_bstruct_f.buf, __pyx_t_20, __pyx_bstride_0_f));
     }
-    __pyx_L6:;
+    __pyx_L9:;
   }
 
   /* "astropy/nddata/convolution/boundary_wrap.pyx":59
@@ -1694,7 +1513,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_convolv
  *             bot = 0.
  */
     __pyx_t_22 = __pyx_v_i;
-    __pyx_t_6 = (!npy_isnan((*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_22, __pyx_pybuffernd_fixed.diminfo[0].strides))));
+    __pyx_t_6 = (!npy_isnan((*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_22, __pyx_bstride_0_fixed))));
     if (__pyx_t_6) {
 
       /* "astropy/nddata/convolution/boundary_wrap.pyx":61
@@ -1765,7 +1584,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_convolv
  *                 if not npy_isnan(val):
  */
         __pyx_t_23 = __pyx_v_iii;
-        __pyx_v_val = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_23, __pyx_pybuffernd_fixed.diminfo[0].strides));
+        __pyx_v_val = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_23, __pyx_bstride_0_fixed));
 
         /* "astropy/nddata/convolution/boundary_wrap.pyx":68
  *                 iii = ii % nx
@@ -1775,7 +1594,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_convolv
  *                     top += val * ker
  */
         __pyx_t_24 = ((unsigned int)((__pyx_v_wkx + __pyx_v_ii) - __pyx_v_i));
-        __pyx_v_ker = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_pybuffernd_g.rcbuffer->pybuffer.buf, __pyx_t_24, __pyx_pybuffernd_g.diminfo[0].strides));
+        __pyx_v_ker = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_bstruct_g.buf, __pyx_t_24, __pyx_bstride_0_g));
 
         /* "astropy/nddata/convolution/boundary_wrap.pyx":69
  *                 val = fixed[iii]
@@ -1804,9 +1623,9 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_convolv
  *                 conv[i] = top / bot
  */
           __pyx_v_bot = (__pyx_v_bot + __pyx_v_ker);
-          goto __pyx_L16;
+          goto __pyx_L19;
         }
-        __pyx_L16:;
+        __pyx_L19:;
       }
 
       /* "astropy/nddata/convolution/boundary_wrap.pyx":72
@@ -1831,8 +1650,8 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_convolv
           {__pyx_filename = __pyx_f[0]; __pyx_lineno = 73; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         }
         __pyx_t_25 = __pyx_v_i;
-        *__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_pybuffernd_conv.rcbuffer->pybuffer.buf, __pyx_t_25, __pyx_pybuffernd_conv.diminfo[0].strides) = (__pyx_v_top / __pyx_v_bot);
-        goto __pyx_L17;
+        *__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_bstruct_conv.buf, __pyx_t_25, __pyx_bstride_0_conv) = (__pyx_v_top / __pyx_v_bot);
+        goto __pyx_L20;
       }
       /*else*/ {
 
@@ -1845,10 +1664,10 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_convolv
  */
         __pyx_t_26 = __pyx_v_i;
         __pyx_t_27 = __pyx_v_i;
-        *__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_pybuffernd_conv.rcbuffer->pybuffer.buf, __pyx_t_27, __pyx_pybuffernd_conv.diminfo[0].strides) = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_26, __pyx_pybuffernd_fixed.diminfo[0].strides));
+        *__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_bstruct_conv.buf, __pyx_t_27, __pyx_bstride_0_conv) = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_26, __pyx_bstride_0_fixed));
       }
-      __pyx_L17:;
-      goto __pyx_L13;
+      __pyx_L20:;
+      goto __pyx_L16;
     }
     /*else*/ {
 
@@ -1861,9 +1680,9 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_convolv
  */
       __pyx_t_28 = __pyx_v_i;
       __pyx_t_29 = __pyx_v_i;
-      *__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_pybuffernd_conv.rcbuffer->pybuffer.buf, __pyx_t_29, __pyx_pybuffernd_conv.diminfo[0].strides) = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_28, __pyx_pybuffernd_fixed.diminfo[0].strides));
+      *__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_bstruct_conv.buf, __pyx_t_29, __pyx_bstride_0_conv) = (*__Pyx_BufPtrStrided1d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_28, __pyx_bstride_0_fixed));
     }
-    __pyx_L13:;
+    __pyx_L16:;
   }
 
   /* "astropy/nddata/convolution/boundary_wrap.pyx":79
@@ -1887,19 +1706,19 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_convolv
   __Pyx_XDECREF(__pyx_t_7);
   { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;
     __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);
-    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_conv.rcbuffer->pybuffer);
-    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_f.rcbuffer->pybuffer);
-    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_fixed.rcbuffer->pybuffer);
-    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_g.rcbuffer->pybuffer);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_conv);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_g);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_f);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_fixed);
   __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
   __Pyx_AddTraceback("astropy.nddata.convolution.boundary_wrap.convolve1d_boundary_wrap", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   goto __pyx_L2;
   __pyx_L0:;
-  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_conv.rcbuffer->pybuffer);
-  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_f.rcbuffer->pybuffer);
-  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_fixed.rcbuffer->pybuffer);
-  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_g.rcbuffer->pybuffer);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_conv);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_g);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_f);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_fixed);
   __pyx_L2:;
   __Pyx_XDECREF((PyObject *)__pyx_v_fixed);
   __Pyx_XDECREF((PyObject *)__pyx_v_conv);
@@ -1908,72 +1727,6 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_convolv
   return __pyx_r;
 }
 
-/* Python wrapper */
-static PyObject *__pyx_pw_7astropy_6nddata_11convolution_13boundary_wrap_3convolve2d_boundary_wrap(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static PyMethodDef __pyx_mdef_7astropy_6nddata_11convolution_13boundary_wrap_3convolve2d_boundary_wrap = {__Pyx_NAMESTR("convolve2d_boundary_wrap"), (PyCFunction)__pyx_pw_7astropy_6nddata_11convolution_13boundary_wrap_3convolve2d_boundary_wrap, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(0)};
-static PyObject *__pyx_pw_7astropy_6nddata_11convolution_13boundary_wrap_3convolve2d_boundary_wrap(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
-  PyArrayObject *__pyx_v_f = 0;
-  PyArrayObject *__pyx_v_g = 0;
-  static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__f,&__pyx_n_s__g,0};
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("convolve2d_boundary_wrap (wrapper)", 0);
-  __pyx_self = __pyx_self;
-  {
-    PyObject* values[2] = {0,0};
-    if (unlikely(__pyx_kwds)) {
-      Py_ssize_t kw_args;
-      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
-      switch (pos_args) {
-        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
-        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
-        case  0: break;
-        default: goto __pyx_L5_argtuple_error;
-      }
-      kw_args = PyDict_Size(__pyx_kwds);
-      switch (pos_args) {
-        case  0:
-        values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__f);
-        if (likely(values[0])) kw_args--;
-        else goto __pyx_L5_argtuple_error;
-        case  1:
-        values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__g);
-        if (likely(values[1])) kw_args--;
-        else {
-          __Pyx_RaiseArgtupleInvalid("convolve2d_boundary_wrap", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 83; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-        }
-      }
-      if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "convolve2d_boundary_wrap") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 83; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-      }
-    } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
-      goto __pyx_L5_argtuple_error;
-    } else {
-      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
-      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
-    }
-    __pyx_v_f = ((PyArrayObject *)values[0]);
-    __pyx_v_g = ((PyArrayObject *)values[1]);
-  }
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("convolve2d_boundary_wrap", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 83; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-  __pyx_L3_error:;
-  __Pyx_AddTraceback("astropy.nddata.convolution.boundary_wrap.convolve2d_boundary_wrap", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return NULL;
-  __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_f), __pyx_ptype_5numpy_ndarray, 1, "f", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 83; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_g), __pyx_ptype_5numpy_ndarray, 1, "g", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 84; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_r = __pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_2convolve2d_boundary_wrap(__pyx_self, __pyx_v_f, __pyx_v_g);
-  goto __pyx_L0;
-  __pyx_L1_error:;
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
 /* "astropy/nddata/convolution/boundary_wrap.pyx":83
  * 
  * @cython.boundscheck(False)  # turn off bounds-checking for entire function
@@ -1982,7 +1735,11 @@ static PyObject *__pyx_pw_7astropy_6nddata_11convolution_13boundary_wrap_3convol
  * 
  */
 
-static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_2convolve2d_boundary_wrap(CYTHON_UNUSED PyObject *__pyx_self, PyArrayObject *__pyx_v_f, PyArrayObject *__pyx_v_g) {
+static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_1convolve2d_boundary_wrap(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static PyMethodDef __pyx_mdef_7astropy_6nddata_11convolution_13boundary_wrap_1convolve2d_boundary_wrap = {__Pyx_NAMESTR("convolve2d_boundary_wrap"), (PyCFunction)__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_1convolve2d_boundary_wrap, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(0)};
+static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_1convolve2d_boundary_wrap(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyArrayObject *__pyx_v_f = 0;
+  PyArrayObject *__pyx_v_g = 0;
   int __pyx_v_nx;
   int __pyx_v_ny;
   int __pyx_v_nkx;
@@ -2005,14 +1762,26 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_2convol
   __pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t __pyx_v_bot;
   __pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t __pyx_v_ker;
   __pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t __pyx_v_val;
-  __Pyx_LocalBuf_ND __pyx_pybuffernd_conv;
-  __Pyx_Buffer __pyx_pybuffer_conv;
-  __Pyx_LocalBuf_ND __pyx_pybuffernd_f;
-  __Pyx_Buffer __pyx_pybuffer_f;
-  __Pyx_LocalBuf_ND __pyx_pybuffernd_fixed;
-  __Pyx_Buffer __pyx_pybuffer_fixed;
-  __Pyx_LocalBuf_ND __pyx_pybuffernd_g;
-  __Pyx_Buffer __pyx_pybuffer_g;
+  Py_buffer __pyx_bstruct_conv;
+  Py_ssize_t __pyx_bstride_0_conv = 0;
+  Py_ssize_t __pyx_bstride_1_conv = 0;
+  Py_ssize_t __pyx_bshape_0_conv = 0;
+  Py_ssize_t __pyx_bshape_1_conv = 0;
+  Py_buffer __pyx_bstruct_g;
+  Py_ssize_t __pyx_bstride_0_g = 0;
+  Py_ssize_t __pyx_bstride_1_g = 0;
+  Py_ssize_t __pyx_bshape_0_g = 0;
+  Py_ssize_t __pyx_bshape_1_g = 0;
+  Py_buffer __pyx_bstruct_f;
+  Py_ssize_t __pyx_bstride_0_f = 0;
+  Py_ssize_t __pyx_bstride_1_f = 0;
+  Py_ssize_t __pyx_bshape_0_f = 0;
+  Py_ssize_t __pyx_bshape_1_f = 0;
+  Py_buffer __pyx_bstruct_fixed;
+  Py_ssize_t __pyx_bstride_0_fixed = 0;
+  Py_ssize_t __pyx_bstride_1_fixed = 0;
+  Py_ssize_t __pyx_bshape_0_fixed = 0;
+  Py_ssize_t __pyx_bshape_1_fixed = 0;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   int __pyx_t_1;
@@ -2067,33 +1836,70 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_2convol
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("convolve2d_boundary_wrap", 0);
-  __pyx_pybuffer_fixed.pybuffer.buf = NULL;
-  __pyx_pybuffer_fixed.refcount = 0;
-  __pyx_pybuffernd_fixed.data = NULL;
-  __pyx_pybuffernd_fixed.rcbuffer = &__pyx_pybuffer_fixed;
-  __pyx_pybuffer_conv.pybuffer.buf = NULL;
-  __pyx_pybuffer_conv.refcount = 0;
-  __pyx_pybuffernd_conv.data = NULL;
-  __pyx_pybuffernd_conv.rcbuffer = &__pyx_pybuffer_conv;
-  __pyx_pybuffer_f.pybuffer.buf = NULL;
-  __pyx_pybuffer_f.refcount = 0;
-  __pyx_pybuffernd_f.data = NULL;
-  __pyx_pybuffernd_f.rcbuffer = &__pyx_pybuffer_f;
-  __pyx_pybuffer_g.pybuffer.buf = NULL;
-  __pyx_pybuffer_g.refcount = 0;
-  __pyx_pybuffernd_g.data = NULL;
-  __pyx_pybuffernd_g.rcbuffer = &__pyx_pybuffer_g;
+  static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__f,&__pyx_n_s__g,0};
+  __Pyx_RefNannySetupContext("convolve2d_boundary_wrap");
+  __pyx_self = __pyx_self;
+  {
+    PyObject* values[2] = {0,0};
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  0:
+        values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__f);
+        if (likely(values[0])) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+        case  1:
+        values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__g);
+        if (likely(values[1])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("convolve2d_boundary_wrap", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 83; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "convolve2d_boundary_wrap") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 83; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+    } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
+      goto __pyx_L5_argtuple_error;
+    } else {
+      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+    }
+    __pyx_v_f = ((PyArrayObject *)values[0]);
+    __pyx_v_g = ((PyArrayObject *)values[1]);
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("convolve2d_boundary_wrap", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 83; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("astropy.nddata.convolution.boundary_wrap.convolve2d_boundary_wrap", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_bstruct_fixed.buf = NULL;
+  __pyx_bstruct_conv.buf = NULL;
+  __pyx_bstruct_f.buf = NULL;
+  __pyx_bstruct_g.buf = NULL;
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_f), __pyx_ptype_5numpy_ndarray, 1, "f", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 83; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_g), __pyx_ptype_5numpy_ndarray, 1, "g", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 84; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_f.rcbuffer->pybuffer, (PyObject*)__pyx_v_f, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 83; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_f, (PyObject*)__pyx_v_f, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 83; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
-  __pyx_pybuffernd_f.diminfo[0].strides = __pyx_pybuffernd_f.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_f.diminfo[0].shape = __pyx_pybuffernd_f.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_f.diminfo[1].strides = __pyx_pybuffernd_f.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_f.diminfo[1].shape = __pyx_pybuffernd_f.rcbuffer->pybuffer.shape[1];
+  __pyx_bstride_0_f = __pyx_bstruct_f.strides[0]; __pyx_bstride_1_f = __pyx_bstruct_f.strides[1];
+  __pyx_bshape_0_f = __pyx_bstruct_f.shape[0]; __pyx_bshape_1_f = __pyx_bstruct_f.shape[1];
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_g.rcbuffer->pybuffer, (PyObject*)__pyx_v_g, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 83; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_g, (PyObject*)__pyx_v_g, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 83; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
-  __pyx_pybuffernd_g.diminfo[0].strides = __pyx_pybuffernd_g.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_g.diminfo[0].shape = __pyx_pybuffernd_g.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_g.diminfo[1].strides = __pyx_pybuffernd_g.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_g.diminfo[1].shape = __pyx_pybuffernd_g.rcbuffer->pybuffer.shape[1];
+  __pyx_bstride_0_g = __pyx_bstruct_g.strides[0]; __pyx_bstride_1_g = __pyx_bstruct_g.strides[1];
+  __pyx_bshape_0_g = __pyx_bstruct_g.shape[0]; __pyx_bshape_1_g = __pyx_bstruct_g.shape[1];
 
   /* "astropy/nddata/convolution/boundary_wrap.pyx":86
  *                              np.ndarray[DTYPE_t, ndim=2] g):
@@ -2123,9 +1929,9 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_2convol
     __Pyx_Raise(__pyx_t_4, 0, 0, 0);
     __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
     {__pyx_filename = __pyx_f[0]; __pyx_lineno = 87; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    goto __pyx_L3;
+    goto __pyx_L6;
   }
-  __pyx_L3:;
+  __pyx_L6:;
 
   /* "astropy/nddata/convolution/boundary_wrap.pyx":89
  *         raise ValueError("Convolution kernel must have odd dimensions")
@@ -2237,7 +2043,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_2convol
   __pyx_t_6 = PyInt_FromLong(__pyx_v_ny); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 97; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_6);
   __pyx_t_7 = PyList_New(2); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 97; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_7);
+  __Pyx_GOTREF(((PyObject *)__pyx_t_7));
   PyList_SET_ITEM(__pyx_t_7, 0, __pyx_t_4);
   __Pyx_GIVEREF(__pyx_t_4);
   PyList_SET_ITEM(__pyx_t_7, 1, __pyx_t_6);
@@ -2245,7 +2051,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_2convol
   __pyx_t_4 = 0;
   __pyx_t_6 = 0;
   __pyx_t_6 = PyTuple_New(1); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 97; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_6);
+  __Pyx_GOTREF(((PyObject *)__pyx_t_6));
   PyTuple_SET_ITEM(__pyx_t_6, 0, ((PyObject *)__pyx_t_7));
   __Pyx_GIVEREF(((PyObject *)__pyx_t_7));
   __pyx_t_7 = 0;
@@ -2255,7 +2061,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_2convol
   __Pyx_GOTREF(__pyx_t_4);
   if (PyDict_SetItem(__pyx_t_7, ((PyObject *)__pyx_n_s__dtype), __pyx_t_4) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 97; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  __pyx_t_4 = PyObject_Call(__pyx_t_5, ((PyObject *)__pyx_t_6), ((PyObject *)__pyx_t_7)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 97; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_4 = PyEval_CallObjectWithKeywords(__pyx_t_5, ((PyObject *)__pyx_t_6), ((PyObject *)__pyx_t_7)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 97; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_4);
   __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
   __Pyx_DECREF(((PyObject *)__pyx_t_6)); __pyx_t_6 = 0;
@@ -2264,10 +2070,11 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_2convol
   __pyx_t_8 = ((PyArrayObject *)__pyx_t_4);
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_fixed.rcbuffer->pybuffer, (PyObject*)__pyx_t_8, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack) == -1)) {
-      __pyx_v_fixed = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf = NULL;
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_fixed, (PyObject*)__pyx_t_8, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack) == -1)) {
+      __pyx_v_fixed = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_fixed.buf = NULL;
       {__pyx_filename = __pyx_f[0]; __pyx_lineno = 97; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    } else {__pyx_pybuffernd_fixed.diminfo[0].strides = __pyx_pybuffernd_fixed.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_fixed.diminfo[0].shape = __pyx_pybuffernd_fixed.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_fixed.diminfo[1].strides = __pyx_pybuffernd_fixed.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_fixed.diminfo[1].shape = __pyx_pybuffernd_fixed.rcbuffer->pybuffer.shape[1];
+    } else {__pyx_bstride_0_fixed = __pyx_bstruct_fixed.strides[0]; __pyx_bstride_1_fixed = __pyx_bstruct_fixed.strides[1];
+      __pyx_bshape_0_fixed = __pyx_bstruct_fixed.shape[0]; __pyx_bshape_1_fixed = __pyx_bstruct_fixed.shape[1];
     }
   }
   __pyx_t_8 = 0;
@@ -2291,7 +2098,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_2convol
   __pyx_t_6 = PyInt_FromLong(__pyx_v_ny); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 98; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_6);
   __pyx_t_5 = PyList_New(2); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 98; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_5);
+  __Pyx_GOTREF(((PyObject *)__pyx_t_5));
   PyList_SET_ITEM(__pyx_t_5, 0, __pyx_t_4);
   __Pyx_GIVEREF(__pyx_t_4);
   PyList_SET_ITEM(__pyx_t_5, 1, __pyx_t_6);
@@ -2299,7 +2106,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_2convol
   __pyx_t_4 = 0;
   __pyx_t_6 = 0;
   __pyx_t_6 = PyTuple_New(1); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 98; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_6);
+  __Pyx_GOTREF(((PyObject *)__pyx_t_6));
   PyTuple_SET_ITEM(__pyx_t_6, 0, ((PyObject *)__pyx_t_5));
   __Pyx_GIVEREF(((PyObject *)__pyx_t_5));
   __pyx_t_5 = 0;
@@ -2309,7 +2116,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_2convol
   __Pyx_GOTREF(__pyx_t_4);
   if (PyDict_SetItem(__pyx_t_5, ((PyObject *)__pyx_n_s__dtype), __pyx_t_4) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 98; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  __pyx_t_4 = PyObject_Call(__pyx_t_7, ((PyObject *)__pyx_t_6), ((PyObject *)__pyx_t_5)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 98; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_4 = PyEval_CallObjectWithKeywords(__pyx_t_7, ((PyObject *)__pyx_t_6), ((PyObject *)__pyx_t_5)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 98; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_4);
   __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
   __Pyx_DECREF(((PyObject *)__pyx_t_6)); __pyx_t_6 = 0;
@@ -2318,10 +2125,11 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_2convol
   __pyx_t_9 = ((PyArrayObject *)__pyx_t_4);
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_conv.rcbuffer->pybuffer, (PyObject*)__pyx_t_9, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack) == -1)) {
-      __pyx_v_conv = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_conv.rcbuffer->pybuffer.buf = NULL;
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_conv, (PyObject*)__pyx_t_9, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack) == -1)) {
+      __pyx_v_conv = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_conv.buf = NULL;
       {__pyx_filename = __pyx_f[0]; __pyx_lineno = 98; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    } else {__pyx_pybuffernd_conv.diminfo[0].strides = __pyx_pybuffernd_conv.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_conv.diminfo[0].shape = __pyx_pybuffernd_conv.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_conv.diminfo[1].strides = __pyx_pybuffernd_conv.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_conv.diminfo[1].shape = __pyx_pybuffernd_conv.rcbuffer->pybuffer.shape[1];
+    } else {__pyx_bstride_0_conv = __pyx_bstruct_conv.strides[0]; __pyx_bstride_1_conv = __pyx_bstruct_conv.strides[1];
+      __pyx_bshape_0_conv = __pyx_bstruct_conv.shape[0]; __pyx_bshape_1_conv = __pyx_bstruct_conv.shape[1];
     }
   }
   __pyx_t_9 = 0;
@@ -2359,7 +2167,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_2convol
  */
       __pyx_t_14 = __pyx_v_i;
       __pyx_t_15 = __pyx_v_j;
-      __pyx_t_2 = npy_isnan((*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_pybuffernd_f.rcbuffer->pybuffer.buf, __pyx_t_14, __pyx_pybuffernd_f.diminfo[0].strides, __pyx_t_15, __pyx_pybuffernd_f.diminfo[1].strides)));
+      __pyx_t_2 = npy_isnan((*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_bstruct_f.buf, __pyx_t_14, __pyx_bstride_0_f, __pyx_t_15, __pyx_bstride_1_f)));
       if (__pyx_t_2) {
 
         /* "astropy/nddata/convolution/boundary_wrap.pyx":111
@@ -2473,7 +2281,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_2convol
  */
             __pyx_t_20 = __pyx_v_iii;
             __pyx_t_21 = __pyx_v_jjj;
-            __pyx_v_val = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_pybuffernd_f.rcbuffer->pybuffer.buf, __pyx_t_20, __pyx_pybuffernd_f.diminfo[0].strides, __pyx_t_21, __pyx_pybuffernd_f.diminfo[1].strides));
+            __pyx_v_val = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_bstruct_f.buf, __pyx_t_20, __pyx_bstride_0_f, __pyx_t_21, __pyx_bstride_1_f));
 
             /* "astropy/nddata/convolution/boundary_wrap.pyx":122
  *                         jjj = jj % ny
@@ -2494,7 +2302,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_2convol
  */
               __pyx_t_22 = ((unsigned int)((__pyx_v_wkx + __pyx_v_ii) - __pyx_v_i));
               __pyx_t_23 = ((unsigned int)((__pyx_v_wky + __pyx_v_jj) - __pyx_v_j));
-              __pyx_v_ker = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_pybuffernd_g.rcbuffer->pybuffer.buf, __pyx_t_22, __pyx_pybuffernd_g.diminfo[0].strides, __pyx_t_23, __pyx_pybuffernd_g.diminfo[1].strides));
+              __pyx_v_ker = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_bstruct_g.buf, __pyx_t_22, __pyx_bstride_0_g, __pyx_t_23, __pyx_bstride_1_g));
 
               /* "astropy/nddata/convolution/boundary_wrap.pyx":125
  *                             ker = g[<unsigned int>(wkx + ii - i),
@@ -2513,9 +2321,9 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_2convol
  *                 if bot != 0.:
  */
               __pyx_v_bot = (__pyx_v_bot + __pyx_v_ker);
-              goto __pyx_L13;
+              goto __pyx_L16;
             }
-            __pyx_L13:;
+            __pyx_L16:;
           }
         }
 
@@ -2542,8 +2350,8 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_2convol
           }
           __pyx_t_24 = __pyx_v_i;
           __pyx_t_25 = __pyx_v_j;
-          *__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_24, __pyx_pybuffernd_fixed.diminfo[0].strides, __pyx_t_25, __pyx_pybuffernd_fixed.diminfo[1].strides) = (__pyx_v_top / __pyx_v_bot);
-          goto __pyx_L14;
+          *__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_24, __pyx_bstride_0_fixed, __pyx_t_25, __pyx_bstride_1_fixed) = (__pyx_v_top / __pyx_v_bot);
+          goto __pyx_L17;
         }
         /*else*/ {
 
@@ -2558,10 +2366,10 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_2convol
           __pyx_t_27 = __pyx_v_j;
           __pyx_t_28 = __pyx_v_i;
           __pyx_t_29 = __pyx_v_j;
-          *__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_28, __pyx_pybuffernd_fixed.diminfo[0].strides, __pyx_t_29, __pyx_pybuffernd_fixed.diminfo[1].strides) = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_pybuffernd_f.rcbuffer->pybuffer.buf, __pyx_t_26, __pyx_pybuffernd_f.diminfo[0].strides, __pyx_t_27, __pyx_pybuffernd_f.diminfo[1].strides));
+          *__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_28, __pyx_bstride_0_fixed, __pyx_t_29, __pyx_bstride_1_fixed) = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_bstruct_f.buf, __pyx_t_26, __pyx_bstride_0_f, __pyx_t_27, __pyx_bstride_1_f));
         }
-        __pyx_L14:;
-        goto __pyx_L8;
+        __pyx_L17:;
+        goto __pyx_L11;
       }
       /*else*/ {
 
@@ -2576,9 +2384,9 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_2convol
         __pyx_t_31 = __pyx_v_j;
         __pyx_t_32 = __pyx_v_i;
         __pyx_t_33 = __pyx_v_j;
-        *__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_32, __pyx_pybuffernd_fixed.diminfo[0].strides, __pyx_t_33, __pyx_pybuffernd_fixed.diminfo[1].strides) = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_pybuffernd_f.rcbuffer->pybuffer.buf, __pyx_t_30, __pyx_pybuffernd_f.diminfo[0].strides, __pyx_t_31, __pyx_pybuffernd_f.diminfo[1].strides));
+        *__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_32, __pyx_bstride_0_fixed, __pyx_t_33, __pyx_bstride_1_fixed) = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_bstruct_f.buf, __pyx_t_30, __pyx_bstride_0_f, __pyx_t_31, __pyx_bstride_1_f));
       }
-      __pyx_L8:;
+      __pyx_L11:;
     }
   }
 
@@ -2613,7 +2421,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_2convol
  */
       __pyx_t_34 = __pyx_v_i;
       __pyx_t_35 = __pyx_v_j;
-      __pyx_t_2 = (!npy_isnan((*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_34, __pyx_pybuffernd_fixed.diminfo[0].strides, __pyx_t_35, __pyx_pybuffernd_fixed.diminfo[1].strides))));
+      __pyx_t_2 = (!npy_isnan((*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_34, __pyx_bstride_0_fixed, __pyx_t_35, __pyx_bstride_1_fixed))));
       if (__pyx_t_2) {
 
         /* "astropy/nddata/convolution/boundary_wrap.pyx":139
@@ -2727,7 +2535,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_2convol
  */
             __pyx_t_36 = __pyx_v_iii;
             __pyx_t_37 = __pyx_v_jjj;
-            __pyx_v_val = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_36, __pyx_pybuffernd_fixed.diminfo[0].strides, __pyx_t_37, __pyx_pybuffernd_fixed.diminfo[1].strides));
+            __pyx_v_val = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_36, __pyx_bstride_0_fixed, __pyx_t_37, __pyx_bstride_1_fixed));
 
             /* "astropy/nddata/convolution/boundary_wrap.pyx":151
  *                         val = fixed[iii, jjj]
@@ -2738,7 +2546,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_2convol
  */
             __pyx_t_38 = ((unsigned int)((__pyx_v_wkx + __pyx_v_ii) - __pyx_v_i));
             __pyx_t_39 = ((unsigned int)((__pyx_v_wky + __pyx_v_jj) - __pyx_v_j));
-            __pyx_v_ker = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_pybuffernd_g.rcbuffer->pybuffer.buf, __pyx_t_38, __pyx_pybuffernd_g.diminfo[0].strides, __pyx_t_39, __pyx_pybuffernd_g.diminfo[1].strides));
+            __pyx_v_ker = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_bstruct_g.buf, __pyx_t_38, __pyx_bstride_0_g, __pyx_t_39, __pyx_bstride_1_g));
 
             /* "astropy/nddata/convolution/boundary_wrap.pyx":152
  *                         ker = g[<unsigned int>(wkx + ii - i),
@@ -2767,9 +2575,9 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_2convol
  *                     conv[i, j] = top / bot
  */
               __pyx_v_bot = (__pyx_v_bot + __pyx_v_ker);
-              goto __pyx_L24;
+              goto __pyx_L27;
             }
-            __pyx_L24:;
+            __pyx_L27:;
           }
         }
 
@@ -2796,8 +2604,8 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_2convol
           }
           __pyx_t_40 = __pyx_v_i;
           __pyx_t_41 = __pyx_v_j;
-          *__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_pybuffernd_conv.rcbuffer->pybuffer.buf, __pyx_t_40, __pyx_pybuffernd_conv.diminfo[0].strides, __pyx_t_41, __pyx_pybuffernd_conv.diminfo[1].strides) = (__pyx_v_top / __pyx_v_bot);
-          goto __pyx_L25;
+          *__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_bstruct_conv.buf, __pyx_t_40, __pyx_bstride_0_conv, __pyx_t_41, __pyx_bstride_1_conv) = (__pyx_v_top / __pyx_v_bot);
+          goto __pyx_L28;
         }
         /*else*/ {
 
@@ -2812,10 +2620,10 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_2convol
           __pyx_t_43 = __pyx_v_j;
           __pyx_t_44 = __pyx_v_i;
           __pyx_t_45 = __pyx_v_j;
-          *__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_pybuffernd_conv.rcbuffer->pybuffer.buf, __pyx_t_44, __pyx_pybuffernd_conv.diminfo[0].strides, __pyx_t_45, __pyx_pybuffernd_conv.diminfo[1].strides) = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_42, __pyx_pybuffernd_fixed.diminfo[0].strides, __pyx_t_43, __pyx_pybuffernd_fixed.diminfo[1].strides));
+          *__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_bstruct_conv.buf, __pyx_t_44, __pyx_bstride_0_conv, __pyx_t_45, __pyx_bstride_1_conv) = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_42, __pyx_bstride_0_fixed, __pyx_t_43, __pyx_bstride_1_fixed));
         }
-        __pyx_L25:;
-        goto __pyx_L19;
+        __pyx_L28:;
+        goto __pyx_L22;
       }
       /*else*/ {
 
@@ -2830,9 +2638,9 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_2convol
         __pyx_t_47 = __pyx_v_j;
         __pyx_t_48 = __pyx_v_i;
         __pyx_t_49 = __pyx_v_j;
-        *__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_pybuffernd_conv.rcbuffer->pybuffer.buf, __pyx_t_48, __pyx_pybuffernd_conv.diminfo[0].strides, __pyx_t_49, __pyx_pybuffernd_conv.diminfo[1].strides) = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_46, __pyx_pybuffernd_fixed.diminfo[0].strides, __pyx_t_47, __pyx_pybuffernd_fixed.diminfo[1].strides));
+        *__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_bstruct_conv.buf, __pyx_t_48, __pyx_bstride_0_conv, __pyx_t_49, __pyx_bstride_1_conv) = (*__Pyx_BufPtrStrided2d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_46, __pyx_bstride_0_fixed, __pyx_t_47, __pyx_bstride_1_fixed));
       }
-      __pyx_L19:;
+      __pyx_L22:;
     }
   }
 
@@ -2857,19 +2665,19 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_2convol
   __Pyx_XDECREF(__pyx_t_7);
   { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;
     __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);
-    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_conv.rcbuffer->pybuffer);
-    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_f.rcbuffer->pybuffer);
-    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_fixed.rcbuffer->pybuffer);
-    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_g.rcbuffer->pybuffer);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_conv);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_g);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_f);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_fixed);
   __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
   __Pyx_AddTraceback("astropy.nddata.convolution.boundary_wrap.convolve2d_boundary_wrap", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   goto __pyx_L2;
   __pyx_L0:;
-  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_conv.rcbuffer->pybuffer);
-  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_f.rcbuffer->pybuffer);
-  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_fixed.rcbuffer->pybuffer);
-  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_g.rcbuffer->pybuffer);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_conv);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_g);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_f);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_fixed);
   __pyx_L2:;
   __Pyx_XDECREF((PyObject *)__pyx_v_fixed);
   __Pyx_XDECREF((PyObject *)__pyx_v_conv);
@@ -2878,72 +2686,6 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_2convol
   return __pyx_r;
 }
 
-/* Python wrapper */
-static PyObject *__pyx_pw_7astropy_6nddata_11convolution_13boundary_wrap_5convolve3d_boundary_wrap(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static PyMethodDef __pyx_mdef_7astropy_6nddata_11convolution_13boundary_wrap_5convolve3d_boundary_wrap = {__Pyx_NAMESTR("convolve3d_boundary_wrap"), (PyCFunction)__pyx_pw_7astropy_6nddata_11convolution_13boundary_wrap_5convolve3d_boundary_wrap, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(0)};
-static PyObject *__pyx_pw_7astropy_6nddata_11convolution_13boundary_wrap_5convolve3d_boundary_wrap(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
-  PyArrayObject *__pyx_v_f = 0;
-  PyArrayObject *__pyx_v_g = 0;
-  static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__f,&__pyx_n_s__g,0};
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("convolve3d_boundary_wrap (wrapper)", 0);
-  __pyx_self = __pyx_self;
-  {
-    PyObject* values[2] = {0,0};
-    if (unlikely(__pyx_kwds)) {
-      Py_ssize_t kw_args;
-      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
-      switch (pos_args) {
-        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
-        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
-        case  0: break;
-        default: goto __pyx_L5_argtuple_error;
-      }
-      kw_args = PyDict_Size(__pyx_kwds);
-      switch (pos_args) {
-        case  0:
-        values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__f);
-        if (likely(values[0])) kw_args--;
-        else goto __pyx_L5_argtuple_error;
-        case  1:
-        values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__g);
-        if (likely(values[1])) kw_args--;
-        else {
-          __Pyx_RaiseArgtupleInvalid("convolve3d_boundary_wrap", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 166; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-        }
-      }
-      if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "convolve3d_boundary_wrap") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 166; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-      }
-    } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
-      goto __pyx_L5_argtuple_error;
-    } else {
-      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
-      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
-    }
-    __pyx_v_f = ((PyArrayObject *)values[0]);
-    __pyx_v_g = ((PyArrayObject *)values[1]);
-  }
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("convolve3d_boundary_wrap", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 166; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-  __pyx_L3_error:;
-  __Pyx_AddTraceback("astropy.nddata.convolution.boundary_wrap.convolve3d_boundary_wrap", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return NULL;
-  __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_f), __pyx_ptype_5numpy_ndarray, 1, "f", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 166; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_g), __pyx_ptype_5numpy_ndarray, 1, "g", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 167; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_r = __pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_4convolve3d_boundary_wrap(__pyx_self, __pyx_v_f, __pyx_v_g);
-  goto __pyx_L0;
-  __pyx_L1_error:;
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
 /* "astropy/nddata/convolution/boundary_wrap.pyx":166
  * 
  * @cython.boundscheck(False)  # turn off bounds-checking for entire function
@@ -2952,7 +2694,11 @@ static PyObject *__pyx_pw_7astropy_6nddata_11convolution_13boundary_wrap_5convol
  * 
  */
 
-static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_4convolve3d_boundary_wrap(CYTHON_UNUSED PyObject *__pyx_self, PyArrayObject *__pyx_v_f, PyArrayObject *__pyx_v_g) {
+static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_2convolve3d_boundary_wrap(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static PyMethodDef __pyx_mdef_7astropy_6nddata_11convolution_13boundary_wrap_2convolve3d_boundary_wrap = {__Pyx_NAMESTR("convolve3d_boundary_wrap"), (PyCFunction)__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_2convolve3d_boundary_wrap, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(0)};
+static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_2convolve3d_boundary_wrap(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyArrayObject *__pyx_v_f = 0;
+  PyArrayObject *__pyx_v_g = 0;
   int __pyx_v_nx;
   int __pyx_v_ny;
   int __pyx_v_nz;
@@ -2983,14 +2729,34 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_4convol
   __pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t __pyx_v_bot;
   __pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t __pyx_v_ker;
   __pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t __pyx_v_val;
-  __Pyx_LocalBuf_ND __pyx_pybuffernd_conv;
-  __Pyx_Buffer __pyx_pybuffer_conv;
-  __Pyx_LocalBuf_ND __pyx_pybuffernd_f;
-  __Pyx_Buffer __pyx_pybuffer_f;
-  __Pyx_LocalBuf_ND __pyx_pybuffernd_fixed;
-  __Pyx_Buffer __pyx_pybuffer_fixed;
-  __Pyx_LocalBuf_ND __pyx_pybuffernd_g;
-  __Pyx_Buffer __pyx_pybuffer_g;
+  Py_buffer __pyx_bstruct_conv;
+  Py_ssize_t __pyx_bstride_0_conv = 0;
+  Py_ssize_t __pyx_bstride_1_conv = 0;
+  Py_ssize_t __pyx_bstride_2_conv = 0;
+  Py_ssize_t __pyx_bshape_0_conv = 0;
+  Py_ssize_t __pyx_bshape_1_conv = 0;
+  Py_ssize_t __pyx_bshape_2_conv = 0;
+  Py_buffer __pyx_bstruct_g;
+  Py_ssize_t __pyx_bstride_0_g = 0;
+  Py_ssize_t __pyx_bstride_1_g = 0;
+  Py_ssize_t __pyx_bstride_2_g = 0;
+  Py_ssize_t __pyx_bshape_0_g = 0;
+  Py_ssize_t __pyx_bshape_1_g = 0;
+  Py_ssize_t __pyx_bshape_2_g = 0;
+  Py_buffer __pyx_bstruct_f;
+  Py_ssize_t __pyx_bstride_0_f = 0;
+  Py_ssize_t __pyx_bstride_1_f = 0;
+  Py_ssize_t __pyx_bstride_2_f = 0;
+  Py_ssize_t __pyx_bshape_0_f = 0;
+  Py_ssize_t __pyx_bshape_1_f = 0;
+  Py_ssize_t __pyx_bshape_2_f = 0;
+  Py_buffer __pyx_bstruct_fixed;
+  Py_ssize_t __pyx_bstride_0_fixed = 0;
+  Py_ssize_t __pyx_bstride_1_fixed = 0;
+  Py_ssize_t __pyx_bstride_2_fixed = 0;
+  Py_ssize_t __pyx_bshape_0_fixed = 0;
+  Py_ssize_t __pyx_bshape_1_fixed = 0;
+  Py_ssize_t __pyx_bshape_2_fixed = 0;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   int __pyx_t_1;
@@ -3067,33 +2833,70 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_4convol
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("convolve3d_boundary_wrap", 0);
-  __pyx_pybuffer_fixed.pybuffer.buf = NULL;
-  __pyx_pybuffer_fixed.refcount = 0;
-  __pyx_pybuffernd_fixed.data = NULL;
-  __pyx_pybuffernd_fixed.rcbuffer = &__pyx_pybuffer_fixed;
-  __pyx_pybuffer_conv.pybuffer.buf = NULL;
-  __pyx_pybuffer_conv.refcount = 0;
-  __pyx_pybuffernd_conv.data = NULL;
-  __pyx_pybuffernd_conv.rcbuffer = &__pyx_pybuffer_conv;
-  __pyx_pybuffer_f.pybuffer.buf = NULL;
-  __pyx_pybuffer_f.refcount = 0;
-  __pyx_pybuffernd_f.data = NULL;
-  __pyx_pybuffernd_f.rcbuffer = &__pyx_pybuffer_f;
-  __pyx_pybuffer_g.pybuffer.buf = NULL;
-  __pyx_pybuffer_g.refcount = 0;
-  __pyx_pybuffernd_g.data = NULL;
-  __pyx_pybuffernd_g.rcbuffer = &__pyx_pybuffer_g;
+  static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__f,&__pyx_n_s__g,0};
+  __Pyx_RefNannySetupContext("convolve3d_boundary_wrap");
+  __pyx_self = __pyx_self;
+  {
+    PyObject* values[2] = {0,0};
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  0:
+        values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__f);
+        if (likely(values[0])) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+        case  1:
+        values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__g);
+        if (likely(values[1])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("convolve3d_boundary_wrap", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 166; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "convolve3d_boundary_wrap") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 166; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+    } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
+      goto __pyx_L5_argtuple_error;
+    } else {
+      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+    }
+    __pyx_v_f = ((PyArrayObject *)values[0]);
+    __pyx_v_g = ((PyArrayObject *)values[1]);
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("convolve3d_boundary_wrap", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 166; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("astropy.nddata.convolution.boundary_wrap.convolve3d_boundary_wrap", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_bstruct_fixed.buf = NULL;
+  __pyx_bstruct_conv.buf = NULL;
+  __pyx_bstruct_f.buf = NULL;
+  __pyx_bstruct_g.buf = NULL;
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_f), __pyx_ptype_5numpy_ndarray, 1, "f", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 166; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_g), __pyx_ptype_5numpy_ndarray, 1, "g", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 167; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_f.rcbuffer->pybuffer, (PyObject*)__pyx_v_f, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES, 3, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 166; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_f, (PyObject*)__pyx_v_f, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES, 3, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 166; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
-  __pyx_pybuffernd_f.diminfo[0].strides = __pyx_pybuffernd_f.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_f.diminfo[0].shape = __pyx_pybuffernd_f.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_f.diminfo[1].strides = __pyx_pybuffernd_f.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_f.diminfo[1].shape = __pyx_pybuffernd_f.rcbuffer->pybuffer.shape[1]; __pyx_pybuffernd_f.diminfo[2].strides = __pyx_pybuffernd_f.rcbuffer->pybuffer.strides[2]; __pyx_pybuffernd_f.diminfo[2].shape = __pyx_pybuffernd_f.rcbuffer->pybuffer.shape[2];
+  __pyx_bstride_0_f = __pyx_bstruct_f.strides[0]; __pyx_bstride_1_f = __pyx_bstruct_f.strides[1]; __pyx_bstride_2_f = __pyx_bstruct_f.strides[2];
+  __pyx_bshape_0_f = __pyx_bstruct_f.shape[0]; __pyx_bshape_1_f = __pyx_bstruct_f.shape[1]; __pyx_bshape_2_f = __pyx_bstruct_f.shape[2];
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_g.rcbuffer->pybuffer, (PyObject*)__pyx_v_g, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES, 3, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 166; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_g, (PyObject*)__pyx_v_g, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES, 3, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 166; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
-  __pyx_pybuffernd_g.diminfo[0].strides = __pyx_pybuffernd_g.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_g.diminfo[0].shape = __pyx_pybuffernd_g.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_g.diminfo[1].strides = __pyx_pybuffernd_g.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_g.diminfo[1].shape = __pyx_pybuffernd_g.rcbuffer->pybuffer.shape[1]; __pyx_pybuffernd_g.diminfo[2].strides = __pyx_pybuffernd_g.rcbuffer->pybuffer.strides[2]; __pyx_pybuffernd_g.diminfo[2].shape = __pyx_pybuffernd_g.rcbuffer->pybuffer.shape[2];
+  __pyx_bstride_0_g = __pyx_bstruct_g.strides[0]; __pyx_bstride_1_g = __pyx_bstruct_g.strides[1]; __pyx_bstride_2_g = __pyx_bstruct_g.strides[2];
+  __pyx_bshape_0_g = __pyx_bstruct_g.shape[0]; __pyx_bshape_1_g = __pyx_bstruct_g.shape[1]; __pyx_bshape_2_g = __pyx_bstruct_g.shape[2];
 
   /* "astropy/nddata/convolution/boundary_wrap.pyx":169
  *                              np.ndarray[DTYPE_t, ndim=3] g):
@@ -3129,9 +2932,9 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_4convol
     __Pyx_Raise(__pyx_t_5, 0, 0, 0);
     __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
     {__pyx_filename = __pyx_f[0]; __pyx_lineno = 170; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    goto __pyx_L3;
+    goto __pyx_L6;
   }
-  __pyx_L3:;
+  __pyx_L6:;
 
   /* "astropy/nddata/convolution/boundary_wrap.pyx":172
  *         raise ValueError("Convolution kernel must have odd dimensions")
@@ -3272,7 +3075,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_4convol
   __pyx_t_8 = PyInt_FromLong(__pyx_v_nz); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 183; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_8);
   __pyx_t_9 = PyList_New(3); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 183; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_9);
+  __Pyx_GOTREF(((PyObject *)__pyx_t_9));
   PyList_SET_ITEM(__pyx_t_9, 0, __pyx_t_5);
   __Pyx_GIVEREF(__pyx_t_5);
   PyList_SET_ITEM(__pyx_t_9, 1, __pyx_t_7);
@@ -3283,7 +3086,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_4convol
   __pyx_t_7 = 0;
   __pyx_t_8 = 0;
   __pyx_t_8 = PyTuple_New(1); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 183; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_8);
+  __Pyx_GOTREF(((PyObject *)__pyx_t_8));
   PyTuple_SET_ITEM(__pyx_t_8, 0, ((PyObject *)__pyx_t_9));
   __Pyx_GIVEREF(((PyObject *)__pyx_t_9));
   __pyx_t_9 = 0;
@@ -3293,7 +3096,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_4convol
   __Pyx_GOTREF(__pyx_t_7);
   if (PyDict_SetItem(__pyx_t_9, ((PyObject *)__pyx_n_s__dtype), __pyx_t_7) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 183; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-  __pyx_t_7 = PyObject_Call(__pyx_t_6, ((PyObject *)__pyx_t_8), ((PyObject *)__pyx_t_9)); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 183; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_7 = PyEval_CallObjectWithKeywords(__pyx_t_6, ((PyObject *)__pyx_t_8), ((PyObject *)__pyx_t_9)); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 183; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_7);
   __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
   __Pyx_DECREF(((PyObject *)__pyx_t_8)); __pyx_t_8 = 0;
@@ -3302,10 +3105,11 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_4convol
   __pyx_t_10 = ((PyArrayObject *)__pyx_t_7);
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_fixed.rcbuffer->pybuffer, (PyObject*)__pyx_t_10, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 3, 0, __pyx_stack) == -1)) {
-      __pyx_v_fixed = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf = NULL;
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_fixed, (PyObject*)__pyx_t_10, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 3, 0, __pyx_stack) == -1)) {
+      __pyx_v_fixed = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_fixed.buf = NULL;
       {__pyx_filename = __pyx_f[0]; __pyx_lineno = 183; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    } else {__pyx_pybuffernd_fixed.diminfo[0].strides = __pyx_pybuffernd_fixed.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_fixed.diminfo[0].shape = __pyx_pybuffernd_fixed.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_fixed.diminfo[1].strides = __pyx_pybuffernd_fixed.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_fixed.diminfo[1].shape = __pyx_pybuffernd_fixed.rcbuffer->pybuffer.shape[1]; __pyx_pybuffernd_fixed.diminfo[2].strides = __pyx_pybuffernd_fixed.rcbuffer->pybuffer.strides[2]; __pyx_pybuffernd_fixed.diminfo[2].shape = __pyx_pybuffernd_fixed.rcbuffer->pybuffer.shape[2];
+    } else {__pyx_bstride_0_fixed = __pyx_bstruct_fixed.strides[0]; __pyx_bstride_1_fixed = __pyx_bstruct_fixed.strides[1]; __pyx_bstride_2_fixed = __pyx_bstruct_fixed.strides[2];
+      __pyx_bshape_0_fixed = __pyx_bstruct_fixed.shape[0]; __pyx_bshape_1_fixed = __pyx_bstruct_fixed.shape[1]; __pyx_bshape_2_fixed = __pyx_bstruct_fixed.shape[2];
     }
   }
   __pyx_t_10 = 0;
@@ -3331,7 +3135,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_4convol
   __pyx_t_6 = PyInt_FromLong(__pyx_v_nz); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 184; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_6);
   __pyx_t_5 = PyList_New(3); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 184; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_5);
+  __Pyx_GOTREF(((PyObject *)__pyx_t_5));
   PyList_SET_ITEM(__pyx_t_5, 0, __pyx_t_7);
   __Pyx_GIVEREF(__pyx_t_7);
   PyList_SET_ITEM(__pyx_t_5, 1, __pyx_t_8);
@@ -3342,7 +3146,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_4convol
   __pyx_t_8 = 0;
   __pyx_t_6 = 0;
   __pyx_t_6 = PyTuple_New(1); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 184; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_6);
+  __Pyx_GOTREF(((PyObject *)__pyx_t_6));
   PyTuple_SET_ITEM(__pyx_t_6, 0, ((PyObject *)__pyx_t_5));
   __Pyx_GIVEREF(((PyObject *)__pyx_t_5));
   __pyx_t_5 = 0;
@@ -3352,7 +3156,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_4convol
   __Pyx_GOTREF(__pyx_t_8);
   if (PyDict_SetItem(__pyx_t_5, ((PyObject *)__pyx_n_s__dtype), __pyx_t_8) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 184; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-  __pyx_t_8 = PyObject_Call(__pyx_t_9, ((PyObject *)__pyx_t_6), ((PyObject *)__pyx_t_5)); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 184; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_8 = PyEval_CallObjectWithKeywords(__pyx_t_9, ((PyObject *)__pyx_t_6), ((PyObject *)__pyx_t_5)); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 184; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_8);
   __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
   __Pyx_DECREF(((PyObject *)__pyx_t_6)); __pyx_t_6 = 0;
@@ -3361,10 +3165,11 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_4convol
   __pyx_t_11 = ((PyArrayObject *)__pyx_t_8);
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_conv.rcbuffer->pybuffer, (PyObject*)__pyx_t_11, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 3, 0, __pyx_stack) == -1)) {
-      __pyx_v_conv = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_conv.rcbuffer->pybuffer.buf = NULL;
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_conv, (PyObject*)__pyx_t_11, &__Pyx_TypeInfo_nn___pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 3, 0, __pyx_stack) == -1)) {
+      __pyx_v_conv = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_conv.buf = NULL;
       {__pyx_filename = __pyx_f[0]; __pyx_lineno = 184; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    } else {__pyx_pybuffernd_conv.diminfo[0].strides = __pyx_pybuffernd_conv.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_conv.diminfo[0].shape = __pyx_pybuffernd_conv.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_conv.diminfo[1].strides = __pyx_pybuffernd_conv.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_conv.diminfo[1].shape = __pyx_pybuffernd_conv.rcbuffer->pybuffer.shape[1]; __pyx_pybuffernd_conv.diminfo[2].strides = __pyx_pybuffernd_conv.rcbuffer->pybuffer.strides[2]; __pyx_pybuffernd_conv.diminfo[2].shape = __pyx_pybuffernd_conv.rcbuffer->pybuffer.shape[2];
+    } else {__pyx_bstride_0_conv = __pyx_bstruct_conv.strides[0]; __pyx_bstride_1_conv = __pyx_bstruct_conv.strides[1]; __pyx_bstride_2_conv = __pyx_bstruct_conv.strides[2];
+      __pyx_bshape_0_conv = __pyx_bstruct_conv.shape[0]; __pyx_bshape_1_conv = __pyx_bstruct_conv.shape[1]; __pyx_bshape_2_conv = __pyx_bstruct_conv.shape[2];
     }
   }
   __pyx_t_11 = 0;
@@ -3414,7 +3219,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_4convol
         __pyx_t_18 = __pyx_v_i;
         __pyx_t_19 = __pyx_v_j;
         __pyx_t_20 = __pyx_v_k;
-        __pyx_t_4 = npy_isnan((*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_pybuffernd_f.rcbuffer->pybuffer.buf, __pyx_t_18, __pyx_pybuffernd_f.diminfo[0].strides, __pyx_t_19, __pyx_pybuffernd_f.diminfo[1].strides, __pyx_t_20, __pyx_pybuffernd_f.diminfo[2].strides)));
+        __pyx_t_4 = npy_isnan((*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_bstruct_f.buf, __pyx_t_18, __pyx_bstride_0_f, __pyx_t_19, __pyx_bstride_1_f, __pyx_t_20, __pyx_bstride_2_f)));
         if (__pyx_t_4) {
 
           /* "astropy/nddata/convolution/boundary_wrap.pyx":198
@@ -3571,7 +3376,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_4convol
                 __pyx_t_27 = __pyx_v_iii;
                 __pyx_t_28 = __pyx_v_jjj;
                 __pyx_t_29 = __pyx_v_kkk;
-                __pyx_v_val = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_pybuffernd_f.rcbuffer->pybuffer.buf, __pyx_t_27, __pyx_pybuffernd_f.diminfo[0].strides, __pyx_t_28, __pyx_pybuffernd_f.diminfo[1].strides, __pyx_t_29, __pyx_pybuffernd_f.diminfo[2].strides));
+                __pyx_v_val = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_bstruct_f.buf, __pyx_t_27, __pyx_bstride_0_f, __pyx_t_28, __pyx_bstride_1_f, __pyx_t_29, __pyx_bstride_2_f));
 
                 /* "astropy/nddata/convolution/boundary_wrap.pyx":213
  *                                 kkk = kk % nz
@@ -3593,7 +3398,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_4convol
                   __pyx_t_30 = ((unsigned int)((__pyx_v_wkx + __pyx_v_ii) - __pyx_v_i));
                   __pyx_t_31 = ((unsigned int)((__pyx_v_wky + __pyx_v_jj) - __pyx_v_j));
                   __pyx_t_32 = ((unsigned int)((__pyx_v_wkz + __pyx_v_kk) - __pyx_v_k));
-                  __pyx_v_ker = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_pybuffernd_g.rcbuffer->pybuffer.buf, __pyx_t_30, __pyx_pybuffernd_g.diminfo[0].strides, __pyx_t_31, __pyx_pybuffernd_g.diminfo[1].strides, __pyx_t_32, __pyx_pybuffernd_g.diminfo[2].strides));
+                  __pyx_v_ker = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_bstruct_g.buf, __pyx_t_30, __pyx_bstride_0_g, __pyx_t_31, __pyx_bstride_1_g, __pyx_t_32, __pyx_bstride_2_g));
 
                   /* "astropy/nddata/convolution/boundary_wrap.pyx":217
  *                                             <unsigned int>(wky + jj - j),
@@ -3612,9 +3417,9 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_4convol
  *                     if bot != 0.:
  */
                   __pyx_v_bot = (__pyx_v_bot + __pyx_v_ker);
-                  goto __pyx_L17;
+                  goto __pyx_L20;
                 }
-                __pyx_L17:;
+                __pyx_L20:;
               }
             }
           }
@@ -3643,8 +3448,8 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_4convol
             __pyx_t_33 = __pyx_v_i;
             __pyx_t_34 = __pyx_v_j;
             __pyx_t_35 = __pyx_v_k;
-            *__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_33, __pyx_pybuffernd_fixed.diminfo[0].strides, __pyx_t_34, __pyx_pybuffernd_fixed.diminfo[1].strides, __pyx_t_35, __pyx_pybuffernd_fixed.diminfo[2].strides) = (__pyx_v_top / __pyx_v_bot);
-            goto __pyx_L18;
+            *__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_33, __pyx_bstride_0_fixed, __pyx_t_34, __pyx_bstride_1_fixed, __pyx_t_35, __pyx_bstride_2_fixed) = (__pyx_v_top / __pyx_v_bot);
+            goto __pyx_L21;
           }
           /*else*/ {
 
@@ -3661,10 +3466,10 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_4convol
             __pyx_t_39 = __pyx_v_i;
             __pyx_t_40 = __pyx_v_j;
             __pyx_t_41 = __pyx_v_k;
-            *__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_39, __pyx_pybuffernd_fixed.diminfo[0].strides, __pyx_t_40, __pyx_pybuffernd_fixed.diminfo[1].strides, __pyx_t_41, __pyx_pybuffernd_fixed.diminfo[2].strides) = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_pybuffernd_f.rcbuffer->pybuffer.buf, __pyx_t_36, __pyx_pybuffernd_f.diminfo[0].strides, __pyx_t_37, __pyx_pybuffernd_f.diminfo[1].strides, __pyx_t_38, __pyx_pybuffernd_f.diminfo[2].strides));
+            *__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_39, __pyx_bstride_0_fixed, __pyx_t_40, __pyx_bstride_1_fixed, __pyx_t_41, __pyx_bstride_2_fixed) = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_bstruct_f.buf, __pyx_t_36, __pyx_bstride_0_f, __pyx_t_37, __pyx_bstride_1_f, __pyx_t_38, __pyx_bstride_2_f));
           }
-          __pyx_L18:;
-          goto __pyx_L10;
+          __pyx_L21:;
+          goto __pyx_L13;
         }
         /*else*/ {
 
@@ -3681,9 +3486,9 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_4convol
           __pyx_t_45 = __pyx_v_i;
           __pyx_t_46 = __pyx_v_j;
           __pyx_t_47 = __pyx_v_k;
-          *__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_45, __pyx_pybuffernd_fixed.diminfo[0].strides, __pyx_t_46, __pyx_pybuffernd_fixed.diminfo[1].strides, __pyx_t_47, __pyx_pybuffernd_fixed.diminfo[2].strides) = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_pybuffernd_f.rcbuffer->pybuffer.buf, __pyx_t_42, __pyx_pybuffernd_f.diminfo[0].strides, __pyx_t_43, __pyx_pybuffernd_f.diminfo[1].strides, __pyx_t_44, __pyx_pybuffernd_f.diminfo[2].strides));
+          *__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_45, __pyx_bstride_0_fixed, __pyx_t_46, __pyx_bstride_1_fixed, __pyx_t_47, __pyx_bstride_2_fixed) = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_bstruct_f.buf, __pyx_t_42, __pyx_bstride_0_f, __pyx_t_43, __pyx_bstride_1_f, __pyx_t_44, __pyx_bstride_2_f));
         }
-        __pyx_L10:;
+        __pyx_L13:;
       }
     }
   }
@@ -3731,7 +3536,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_4convol
         __pyx_t_48 = __pyx_v_i;
         __pyx_t_49 = __pyx_v_j;
         __pyx_t_50 = __pyx_v_k;
-        __pyx_t_4 = (!npy_isnan((*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_48, __pyx_pybuffernd_fixed.diminfo[0].strides, __pyx_t_49, __pyx_pybuffernd_fixed.diminfo[1].strides, __pyx_t_50, __pyx_pybuffernd_fixed.diminfo[2].strides))));
+        __pyx_t_4 = (!npy_isnan((*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_48, __pyx_bstride_0_fixed, __pyx_t_49, __pyx_bstride_1_fixed, __pyx_t_50, __pyx_bstride_2_fixed))));
         if (__pyx_t_4) {
 
           /* "astropy/nddata/convolution/boundary_wrap.pyx":232
@@ -3888,7 +3693,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_4convol
                 __pyx_t_51 = __pyx_v_iii;
                 __pyx_t_52 = __pyx_v_jjj;
                 __pyx_t_53 = __pyx_v_kkk;
-                __pyx_v_val = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_51, __pyx_pybuffernd_fixed.diminfo[0].strides, __pyx_t_52, __pyx_pybuffernd_fixed.diminfo[1].strides, __pyx_t_53, __pyx_pybuffernd_fixed.diminfo[2].strides));
+                __pyx_v_val = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_51, __pyx_bstride_0_fixed, __pyx_t_52, __pyx_bstride_1_fixed, __pyx_t_53, __pyx_bstride_2_fixed));
 
                 /* "astropy/nddata/convolution/boundary_wrap.pyx":249
  *                                 ker = g[<unsigned int>(wkx + ii - i),
@@ -3900,7 +3705,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_4convol
                 __pyx_t_54 = ((unsigned int)((__pyx_v_wkx + __pyx_v_ii) - __pyx_v_i));
                 __pyx_t_55 = ((unsigned int)((__pyx_v_wky + __pyx_v_jj) - __pyx_v_j));
                 __pyx_t_56 = ((unsigned int)((__pyx_v_wkz + __pyx_v_kk) - __pyx_v_k));
-                __pyx_v_ker = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_pybuffernd_g.rcbuffer->pybuffer.buf, __pyx_t_54, __pyx_pybuffernd_g.diminfo[0].strides, __pyx_t_55, __pyx_pybuffernd_g.diminfo[1].strides, __pyx_t_56, __pyx_pybuffernd_g.diminfo[2].strides));
+                __pyx_v_ker = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_bstruct_g.buf, __pyx_t_54, __pyx_bstride_0_g, __pyx_t_55, __pyx_bstride_1_g, __pyx_t_56, __pyx_bstride_2_g));
 
                 /* "astropy/nddata/convolution/boundary_wrap.pyx":250
  *                                         <unsigned int>(wky + jj - j),
@@ -3929,9 +3734,9 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_4convol
  *                         conv[i, j, k] = top / bot
  */
                   __pyx_v_bot = (__pyx_v_bot + __pyx_v_ker);
-                  goto __pyx_L32;
+                  goto __pyx_L35;
                 }
-                __pyx_L32:;
+                __pyx_L35:;
               }
             }
           }
@@ -3960,8 +3765,8 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_4convol
             __pyx_t_57 = __pyx_v_i;
             __pyx_t_58 = __pyx_v_j;
             __pyx_t_59 = __pyx_v_k;
-            *__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_pybuffernd_conv.rcbuffer->pybuffer.buf, __pyx_t_57, __pyx_pybuffernd_conv.diminfo[0].strides, __pyx_t_58, __pyx_pybuffernd_conv.diminfo[1].strides, __pyx_t_59, __pyx_pybuffernd_conv.diminfo[2].strides) = (__pyx_v_top / __pyx_v_bot);
-            goto __pyx_L33;
+            *__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_bstruct_conv.buf, __pyx_t_57, __pyx_bstride_0_conv, __pyx_t_58, __pyx_bstride_1_conv, __pyx_t_59, __pyx_bstride_2_conv) = (__pyx_v_top / __pyx_v_bot);
+            goto __pyx_L36;
           }
           /*else*/ {
 
@@ -3978,10 +3783,10 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_4convol
             __pyx_t_63 = __pyx_v_i;
             __pyx_t_64 = __pyx_v_j;
             __pyx_t_65 = __pyx_v_k;
-            *__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_pybuffernd_conv.rcbuffer->pybuffer.buf, __pyx_t_63, __pyx_pybuffernd_conv.diminfo[0].strides, __pyx_t_64, __pyx_pybuffernd_conv.diminfo[1].strides, __pyx_t_65, __pyx_pybuffernd_conv.diminfo[2].strides) = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_60, __pyx_pybuffernd_fixed.diminfo[0].strides, __pyx_t_61, __pyx_pybuffernd_fixed.diminfo[1].strides, __pyx_t_62, __pyx_pybuffernd_fixed.diminfo[2].strides));
+            *__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_bstruct_conv.buf, __pyx_t_63, __pyx_bstride_0_conv, __pyx_t_64, __pyx_bstride_1_conv, __pyx_t_65, __pyx_bstride_2_conv) = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_60, __pyx_bstride_0_fixed, __pyx_t_61, __pyx_bstride_1_fixed, __pyx_t_62, __pyx_bstride_2_fixed));
           }
-          __pyx_L33:;
-          goto __pyx_L25;
+          __pyx_L36:;
+          goto __pyx_L28;
         }
         /*else*/ {
 
@@ -3998,9 +3803,9 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_4convol
           __pyx_t_69 = __pyx_v_i;
           __pyx_t_70 = __pyx_v_j;
           __pyx_t_71 = __pyx_v_k;
-          *__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_pybuffernd_conv.rcbuffer->pybuffer.buf, __pyx_t_69, __pyx_pybuffernd_conv.diminfo[0].strides, __pyx_t_70, __pyx_pybuffernd_conv.diminfo[1].strides, __pyx_t_71, __pyx_pybuffernd_conv.diminfo[2].strides) = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_pybuffernd_fixed.rcbuffer->pybuffer.buf, __pyx_t_66, __pyx_pybuffernd_fixed.diminfo[0].strides, __pyx_t_67, __pyx_pybuffernd_fixed.diminfo[1].strides, __pyx_t_68, __pyx_pybuffernd_fixed.diminfo[2].strides));
+          *__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_bstruct_conv.buf, __pyx_t_69, __pyx_bstride_0_conv, __pyx_t_70, __pyx_bstride_1_conv, __pyx_t_71, __pyx_bstride_2_conv) = (*__Pyx_BufPtrStrided3d(__pyx_t_7astropy_6nddata_11convolution_13boundary_wrap_DTYPE_t *, __pyx_bstruct_fixed.buf, __pyx_t_66, __pyx_bstride_0_fixed, __pyx_t_67, __pyx_bstride_1_fixed, __pyx_t_68, __pyx_bstride_2_fixed));
         }
-        __pyx_L25:;
+        __pyx_L28:;
       }
     }
   }
@@ -4025,19 +3830,19 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_4convol
   __Pyx_XDECREF(__pyx_t_9);
   { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;
     __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);
-    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_conv.rcbuffer->pybuffer);
-    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_f.rcbuffer->pybuffer);
-    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_fixed.rcbuffer->pybuffer);
-    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_g.rcbuffer->pybuffer);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_conv);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_g);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_f);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_fixed);
   __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
   __Pyx_AddTraceback("astropy.nddata.convolution.boundary_wrap.convolve3d_boundary_wrap", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   goto __pyx_L2;
   __pyx_L0:;
-  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_conv.rcbuffer->pybuffer);
-  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_f.rcbuffer->pybuffer);
-  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_fixed.rcbuffer->pybuffer);
-  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_g.rcbuffer->pybuffer);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_conv);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_g);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_f);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_fixed);
   __pyx_L2:;
   __Pyx_XDECREF((PyObject *)__pyx_v_fixed);
   __Pyx_XDECREF((PyObject *)__pyx_v_conv);
@@ -4046,18 +3851,7 @@ static PyObject *__pyx_pf_7astropy_6nddata_11convolution_13boundary_wrap_4convol
   return __pyx_r;
 }
 
-/* Python wrapper */
-static int __pyx_pw_5numpy_7ndarray_1__getbuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags); /*proto*/
-static int __pyx_pw_5numpy_7ndarray_1__getbuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags) {
-  int __pyx_r;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__getbuffer__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_5numpy_7ndarray___getbuffer__(((PyArrayObject *)__pyx_v_self), ((Py_buffer *)__pyx_v_info), ((int)__pyx_v_flags));
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-/* "numpy.pxd":193
+/* "numpy.pxd":190
  *         # experimental exception made for __getbuffer__ and __releasebuffer__
  *         # -- the details of this may change.
  *         def __getbuffer__(ndarray self, Py_buffer* info, int flags):             # <<<<<<<<<<<<<<
@@ -4065,7 +3859,8 @@ static int __pyx_pw_5numpy_7ndarray_1__getbuffer__(PyObject *__pyx_v_self, Py_bu
  *             # requirements, and does not yet fullfill the PEP.
  */
 
-static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags) {
+static CYTHON_UNUSED int __pyx_pf_5numpy_7ndarray___getbuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags); /*proto*/
+static CYTHON_UNUSED int __pyx_pf_5numpy_7ndarray___getbuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags) {
   int __pyx_v_copy_shape;
   int __pyx_v_i;
   int __pyx_v_ndim;
@@ -4090,13 +3885,13 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("__getbuffer__", 0);
+  __Pyx_RefNannySetupContext("__getbuffer__");
   if (__pyx_v_info != NULL) {
     __pyx_v_info->obj = Py_None; __Pyx_INCREF(Py_None);
     __Pyx_GIVEREF(__pyx_v_info->obj);
   }
 
-  /* "numpy.pxd":199
+  /* "numpy.pxd":196
  *             # of flags
  * 
  *             if info == NULL: return             # <<<<<<<<<<<<<<
@@ -4107,11 +3902,11 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
   if (__pyx_t_1) {
     __pyx_r = 0;
     goto __pyx_L0;
-    goto __pyx_L3;
+    goto __pyx_L5;
   }
-  __pyx_L3:;
+  __pyx_L5:;
 
-  /* "numpy.pxd":202
+  /* "numpy.pxd":199
  * 
  *             cdef int copy_shape, i, ndim
  *             cdef int endian_detector = 1             # <<<<<<<<<<<<<<
@@ -4120,7 +3915,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
   __pyx_v_endian_detector = 1;
 
-  /* "numpy.pxd":203
+  /* "numpy.pxd":200
  *             cdef int copy_shape, i, ndim
  *             cdef int endian_detector = 1
  *             cdef bint little_endian = ((<char*>&endian_detector)[0] != 0)             # <<<<<<<<<<<<<<
@@ -4129,16 +3924,16 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
   __pyx_v_little_endian = ((((char *)(&__pyx_v_endian_detector))[0]) != 0);
 
-  /* "numpy.pxd":205
+  /* "numpy.pxd":202
  *             cdef bint little_endian = ((<char*>&endian_detector)[0] != 0)
  * 
  *             ndim = PyArray_NDIM(self)             # <<<<<<<<<<<<<<
  * 
  *             if sizeof(npy_intp) != sizeof(Py_ssize_t):
  */
-  __pyx_v_ndim = PyArray_NDIM(__pyx_v_self);
+  __pyx_v_ndim = PyArray_NDIM(((PyArrayObject *)__pyx_v_self));
 
-  /* "numpy.pxd":207
+  /* "numpy.pxd":204
  *             ndim = PyArray_NDIM(self)
  * 
  *             if sizeof(npy_intp) != sizeof(Py_ssize_t):             # <<<<<<<<<<<<<<
@@ -4148,7 +3943,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
   __pyx_t_1 = ((sizeof(npy_intp)) != (sizeof(Py_ssize_t)));
   if (__pyx_t_1) {
 
-    /* "numpy.pxd":208
+    /* "numpy.pxd":205
  * 
  *             if sizeof(npy_intp) != sizeof(Py_ssize_t):
  *                 copy_shape = 1             # <<<<<<<<<<<<<<
@@ -4156,11 +3951,11 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  *                 copy_shape = 0
  */
     __pyx_v_copy_shape = 1;
-    goto __pyx_L4;
+    goto __pyx_L6;
   }
   /*else*/ {
 
-    /* "numpy.pxd":210
+    /* "numpy.pxd":207
  *                 copy_shape = 1
  *             else:
  *                 copy_shape = 0             # <<<<<<<<<<<<<<
@@ -4169,9 +3964,9 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
     __pyx_v_copy_shape = 0;
   }
-  __pyx_L4:;
+  __pyx_L6:;
 
-  /* "numpy.pxd":212
+  /* "numpy.pxd":209
  *                 copy_shape = 0
  * 
  *             if ((flags & pybuf.PyBUF_C_CONTIGUOUS == pybuf.PyBUF_C_CONTIGUOUS)             # <<<<<<<<<<<<<<
@@ -4181,37 +3976,37 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
   __pyx_t_1 = ((__pyx_v_flags & PyBUF_C_CONTIGUOUS) == PyBUF_C_CONTIGUOUS);
   if (__pyx_t_1) {
 
-    /* "numpy.pxd":213
+    /* "numpy.pxd":210
  * 
  *             if ((flags & pybuf.PyBUF_C_CONTIGUOUS == pybuf.PyBUF_C_CONTIGUOUS)
  *                 and not PyArray_CHKFLAGS(self, NPY_C_CONTIGUOUS)):             # <<<<<<<<<<<<<<
  *                 raise ValueError(u"ndarray is not C contiguous")
  * 
  */
-    __pyx_t_2 = (!PyArray_CHKFLAGS(__pyx_v_self, NPY_C_CONTIGUOUS));
+    __pyx_t_2 = (!PyArray_CHKFLAGS(((PyArrayObject *)__pyx_v_self), NPY_C_CONTIGUOUS));
     __pyx_t_3 = __pyx_t_2;
   } else {
     __pyx_t_3 = __pyx_t_1;
   }
   if (__pyx_t_3) {
 
-    /* "numpy.pxd":214
+    /* "numpy.pxd":211
  *             if ((flags & pybuf.PyBUF_C_CONTIGUOUS == pybuf.PyBUF_C_CONTIGUOUS)
  *                 and not PyArray_CHKFLAGS(self, NPY_C_CONTIGUOUS)):
  *                 raise ValueError(u"ndarray is not C contiguous")             # <<<<<<<<<<<<<<
  * 
  *             if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS)
  */
-    __pyx_t_4 = PyObject_Call(__pyx_builtin_ValueError, ((PyObject *)__pyx_k_tuple_6), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 214; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = PyObject_Call(__pyx_builtin_ValueError, ((PyObject *)__pyx_k_tuple_6), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 211; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_4);
     __Pyx_Raise(__pyx_t_4, 0, 0, 0);
     __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-    {__pyx_filename = __pyx_f[1]; __pyx_lineno = 214; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    goto __pyx_L5;
+    {__pyx_filename = __pyx_f[1]; __pyx_lineno = 211; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    goto __pyx_L7;
   }
-  __pyx_L5:;
+  __pyx_L7:;
 
-  /* "numpy.pxd":216
+  /* "numpy.pxd":213
  *                 raise ValueError(u"ndarray is not C contiguous")
  * 
  *             if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS)             # <<<<<<<<<<<<<<
@@ -4221,46 +4016,46 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
   __pyx_t_3 = ((__pyx_v_flags & PyBUF_F_CONTIGUOUS) == PyBUF_F_CONTIGUOUS);
   if (__pyx_t_3) {
 
-    /* "numpy.pxd":217
+    /* "numpy.pxd":214
  * 
  *             if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS)
  *                 and not PyArray_CHKFLAGS(self, NPY_F_CONTIGUOUS)):             # <<<<<<<<<<<<<<
  *                 raise ValueError(u"ndarray is not Fortran contiguous")
  * 
  */
-    __pyx_t_1 = (!PyArray_CHKFLAGS(__pyx_v_self, NPY_F_CONTIGUOUS));
+    __pyx_t_1 = (!PyArray_CHKFLAGS(((PyArrayObject *)__pyx_v_self), NPY_F_CONTIGUOUS));
     __pyx_t_2 = __pyx_t_1;
   } else {
     __pyx_t_2 = __pyx_t_3;
   }
   if (__pyx_t_2) {
 
-    /* "numpy.pxd":218
+    /* "numpy.pxd":215
  *             if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS)
  *                 and not PyArray_CHKFLAGS(self, NPY_F_CONTIGUOUS)):
  *                 raise ValueError(u"ndarray is not Fortran contiguous")             # <<<<<<<<<<<<<<
  * 
  *             info.buf = PyArray_DATA(self)
  */
-    __pyx_t_4 = PyObject_Call(__pyx_builtin_ValueError, ((PyObject *)__pyx_k_tuple_8), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 218; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = PyObject_Call(__pyx_builtin_ValueError, ((PyObject *)__pyx_k_tuple_8), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 215; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_4);
     __Pyx_Raise(__pyx_t_4, 0, 0, 0);
     __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-    {__pyx_filename = __pyx_f[1]; __pyx_lineno = 218; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    goto __pyx_L6;
+    {__pyx_filename = __pyx_f[1]; __pyx_lineno = 215; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    goto __pyx_L8;
   }
-  __pyx_L6:;
+  __pyx_L8:;
 
-  /* "numpy.pxd":220
+  /* "numpy.pxd":217
  *                 raise ValueError(u"ndarray is not Fortran contiguous")
  * 
  *             info.buf = PyArray_DATA(self)             # <<<<<<<<<<<<<<
  *             info.ndim = ndim
  *             if copy_shape:
  */
-  __pyx_v_info->buf = PyArray_DATA(__pyx_v_self);
+  __pyx_v_info->buf = PyArray_DATA(((PyArrayObject *)__pyx_v_self));
 
-  /* "numpy.pxd":221
+  /* "numpy.pxd":218
  * 
  *             info.buf = PyArray_DATA(self)
  *             info.ndim = ndim             # <<<<<<<<<<<<<<
@@ -4269,7 +4064,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
   __pyx_v_info->ndim = __pyx_v_ndim;
 
-  /* "numpy.pxd":222
+  /* "numpy.pxd":219
  *             info.buf = PyArray_DATA(self)
  *             info.ndim = ndim
  *             if copy_shape:             # <<<<<<<<<<<<<<
@@ -4278,7 +4073,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
   if (__pyx_v_copy_shape) {
 
-    /* "numpy.pxd":225
+    /* "numpy.pxd":222
  *                 # Allocate new buffer for strides and shape info.
  *                 # This is allocated as one block, strides first.
  *                 info.strides = <Py_ssize_t*>stdlib.malloc(sizeof(Py_ssize_t) * <size_t>ndim * 2)             # <<<<<<<<<<<<<<
@@ -4287,7 +4082,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
     __pyx_v_info->strides = ((Py_ssize_t *)malloc((((sizeof(Py_ssize_t)) * ((size_t)__pyx_v_ndim)) * 2)));
 
-    /* "numpy.pxd":226
+    /* "numpy.pxd":223
  *                 # This is allocated as one block, strides first.
  *                 info.strides = <Py_ssize_t*>stdlib.malloc(sizeof(Py_ssize_t) * <size_t>ndim * 2)
  *                 info.shape = info.strides + ndim             # <<<<<<<<<<<<<<
@@ -4296,7 +4091,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
     __pyx_v_info->shape = (__pyx_v_info->strides + __pyx_v_ndim);
 
-    /* "numpy.pxd":227
+    /* "numpy.pxd":224
  *                 info.strides = <Py_ssize_t*>stdlib.malloc(sizeof(Py_ssize_t) * <size_t>ndim * 2)
  *                 info.shape = info.strides + ndim
  *                 for i in range(ndim):             # <<<<<<<<<<<<<<
@@ -4307,49 +4102,49 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     for (__pyx_t_6 = 0; __pyx_t_6 < __pyx_t_5; __pyx_t_6+=1) {
       __pyx_v_i = __pyx_t_6;
 
-      /* "numpy.pxd":228
+      /* "numpy.pxd":225
  *                 info.shape = info.strides + ndim
  *                 for i in range(ndim):
  *                     info.strides[i] = PyArray_STRIDES(self)[i]             # <<<<<<<<<<<<<<
  *                     info.shape[i] = PyArray_DIMS(self)[i]
  *             else:
  */
-      (__pyx_v_info->strides[__pyx_v_i]) = (PyArray_STRIDES(__pyx_v_self)[__pyx_v_i]);
+      (__pyx_v_info->strides[__pyx_v_i]) = (PyArray_STRIDES(((PyArrayObject *)__pyx_v_self))[__pyx_v_i]);
 
-      /* "numpy.pxd":229
+      /* "numpy.pxd":226
  *                 for i in range(ndim):
  *                     info.strides[i] = PyArray_STRIDES(self)[i]
  *                     info.shape[i] = PyArray_DIMS(self)[i]             # <<<<<<<<<<<<<<
  *             else:
  *                 info.strides = <Py_ssize_t*>PyArray_STRIDES(self)
  */
-      (__pyx_v_info->shape[__pyx_v_i]) = (PyArray_DIMS(__pyx_v_self)[__pyx_v_i]);
+      (__pyx_v_info->shape[__pyx_v_i]) = (PyArray_DIMS(((PyArrayObject *)__pyx_v_self))[__pyx_v_i]);
     }
-    goto __pyx_L7;
+    goto __pyx_L9;
   }
   /*else*/ {
 
-    /* "numpy.pxd":231
+    /* "numpy.pxd":228
  *                     info.shape[i] = PyArray_DIMS(self)[i]
  *             else:
  *                 info.strides = <Py_ssize_t*>PyArray_STRIDES(self)             # <<<<<<<<<<<<<<
  *                 info.shape = <Py_ssize_t*>PyArray_DIMS(self)
  *             info.suboffsets = NULL
  */
-    __pyx_v_info->strides = ((Py_ssize_t *)PyArray_STRIDES(__pyx_v_self));
+    __pyx_v_info->strides = ((Py_ssize_t *)PyArray_STRIDES(((PyArrayObject *)__pyx_v_self)));
 
-    /* "numpy.pxd":232
+    /* "numpy.pxd":229
  *             else:
  *                 info.strides = <Py_ssize_t*>PyArray_STRIDES(self)
  *                 info.shape = <Py_ssize_t*>PyArray_DIMS(self)             # <<<<<<<<<<<<<<
  *             info.suboffsets = NULL
  *             info.itemsize = PyArray_ITEMSIZE(self)
  */
-    __pyx_v_info->shape = ((Py_ssize_t *)PyArray_DIMS(__pyx_v_self));
+    __pyx_v_info->shape = ((Py_ssize_t *)PyArray_DIMS(((PyArrayObject *)__pyx_v_self)));
   }
-  __pyx_L7:;
+  __pyx_L9:;
 
-  /* "numpy.pxd":233
+  /* "numpy.pxd":230
  *                 info.strides = <Py_ssize_t*>PyArray_STRIDES(self)
  *                 info.shape = <Py_ssize_t*>PyArray_DIMS(self)
  *             info.suboffsets = NULL             # <<<<<<<<<<<<<<
@@ -4358,25 +4153,25 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
   __pyx_v_info->suboffsets = NULL;
 
-  /* "numpy.pxd":234
+  /* "numpy.pxd":231
  *                 info.shape = <Py_ssize_t*>PyArray_DIMS(self)
  *             info.suboffsets = NULL
  *             info.itemsize = PyArray_ITEMSIZE(self)             # <<<<<<<<<<<<<<
  *             info.readonly = not PyArray_ISWRITEABLE(self)
  * 
  */
-  __pyx_v_info->itemsize = PyArray_ITEMSIZE(__pyx_v_self);
+  __pyx_v_info->itemsize = PyArray_ITEMSIZE(((PyArrayObject *)__pyx_v_self));
 
-  /* "numpy.pxd":235
+  /* "numpy.pxd":232
  *             info.suboffsets = NULL
  *             info.itemsize = PyArray_ITEMSIZE(self)
  *             info.readonly = not PyArray_ISWRITEABLE(self)             # <<<<<<<<<<<<<<
  * 
  *             cdef int t
  */
-  __pyx_v_info->readonly = (!PyArray_ISWRITEABLE(__pyx_v_self));
+  __pyx_v_info->readonly = (!PyArray_ISWRITEABLE(((PyArrayObject *)__pyx_v_self)));
 
-  /* "numpy.pxd":238
+  /* "numpy.pxd":235
  * 
  *             cdef int t
  *             cdef char* f = NULL             # <<<<<<<<<<<<<<
@@ -4385,17 +4180,17 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
   __pyx_v_f = NULL;
 
-  /* "numpy.pxd":239
+  /* "numpy.pxd":236
  *             cdef int t
  *             cdef char* f = NULL
  *             cdef dtype descr = self.descr             # <<<<<<<<<<<<<<
  *             cdef list stack
  *             cdef int offset
  */
-  __Pyx_INCREF(((PyObject *)__pyx_v_self->descr));
-  __pyx_v_descr = __pyx_v_self->descr;
+  __Pyx_INCREF(((PyObject *)((PyArrayObject *)__pyx_v_self)->descr));
+  __pyx_v_descr = ((PyArrayObject *)__pyx_v_self)->descr;
 
-  /* "numpy.pxd":243
+  /* "numpy.pxd":240
  *             cdef int offset
  * 
  *             cdef bint hasfields = PyDataType_HASFIELDS(descr)             # <<<<<<<<<<<<<<
@@ -4404,7 +4199,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
   __pyx_v_hasfields = PyDataType_HASFIELDS(__pyx_v_descr);
 
-  /* "numpy.pxd":245
+  /* "numpy.pxd":242
  *             cdef bint hasfields = PyDataType_HASFIELDS(descr)
  * 
  *             if not hasfields and not copy_shape:             # <<<<<<<<<<<<<<
@@ -4420,7 +4215,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
   }
   if (__pyx_t_1) {
 
-    /* "numpy.pxd":247
+    /* "numpy.pxd":244
  *             if not hasfields and not copy_shape:
  *                 # do not call releasebuffer
  *                 info.obj = None             # <<<<<<<<<<<<<<
@@ -4432,26 +4227,26 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __Pyx_GOTREF(__pyx_v_info->obj);
     __Pyx_DECREF(__pyx_v_info->obj);
     __pyx_v_info->obj = Py_None;
-    goto __pyx_L10;
+    goto __pyx_L12;
   }
   /*else*/ {
 
-    /* "numpy.pxd":250
+    /* "numpy.pxd":247
  *             else:
  *                 # need to call releasebuffer
  *                 info.obj = self             # <<<<<<<<<<<<<<
  * 
  *             if not hasfields:
  */
-    __Pyx_INCREF(((PyObject *)__pyx_v_self));
-    __Pyx_GIVEREF(((PyObject *)__pyx_v_self));
+    __Pyx_INCREF(__pyx_v_self);
+    __Pyx_GIVEREF(__pyx_v_self);
     __Pyx_GOTREF(__pyx_v_info->obj);
     __Pyx_DECREF(__pyx_v_info->obj);
-    __pyx_v_info->obj = ((PyObject *)__pyx_v_self);
+    __pyx_v_info->obj = __pyx_v_self;
   }
-  __pyx_L10:;
+  __pyx_L12:;
 
-  /* "numpy.pxd":252
+  /* "numpy.pxd":249
  *                 info.obj = self
  * 
  *             if not hasfields:             # <<<<<<<<<<<<<<
@@ -4461,7 +4256,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
   __pyx_t_1 = (!__pyx_v_hasfields);
   if (__pyx_t_1) {
 
-    /* "numpy.pxd":253
+    /* "numpy.pxd":250
  * 
  *             if not hasfields:
  *                 t = descr.type_num             # <<<<<<<<<<<<<<
@@ -4470,7 +4265,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
     __pyx_v_t = __pyx_v_descr->type_num;
 
-    /* "numpy.pxd":254
+    /* "numpy.pxd":251
  *             if not hasfields:
  *                 t = descr.type_num
  *                 if ((descr.byteorder == '>' and little_endian) or             # <<<<<<<<<<<<<<
@@ -4485,7 +4280,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     }
     if (!__pyx_t_2) {
 
-      /* "numpy.pxd":255
+      /* "numpy.pxd":252
  *                 t = descr.type_num
  *                 if ((descr.byteorder == '>' and little_endian) or
  *                     (descr.byteorder == '<' and not little_endian)):             # <<<<<<<<<<<<<<
@@ -4505,23 +4300,23 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     }
     if (__pyx_t_1) {
 
-      /* "numpy.pxd":256
+      /* "numpy.pxd":253
  *                 if ((descr.byteorder == '>' and little_endian) or
  *                     (descr.byteorder == '<' and not little_endian)):
  *                     raise ValueError(u"Non-native byte order not supported")             # <<<<<<<<<<<<<<
  *                 if   t == NPY_BYTE:        f = "b"
  *                 elif t == NPY_UBYTE:       f = "B"
  */
-      __pyx_t_4 = PyObject_Call(__pyx_builtin_ValueError, ((PyObject *)__pyx_k_tuple_10), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 256; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyObject_Call(__pyx_builtin_ValueError, ((PyObject *)__pyx_k_tuple_10), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 253; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_4);
       __Pyx_Raise(__pyx_t_4, 0, 0, 0);
       __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      {__pyx_filename = __pyx_f[1]; __pyx_lineno = 256; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      goto __pyx_L12;
+      {__pyx_filename = __pyx_f[1]; __pyx_lineno = 253; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      goto __pyx_L14;
     }
-    __pyx_L12:;
+    __pyx_L14:;
 
-    /* "numpy.pxd":257
+    /* "numpy.pxd":254
  *                     (descr.byteorder == '<' and not little_endian)):
  *                     raise ValueError(u"Non-native byte order not supported")
  *                 if   t == NPY_BYTE:        f = "b"             # <<<<<<<<<<<<<<
@@ -4531,10 +4326,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_BYTE);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__b;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":258
+    /* "numpy.pxd":255
  *                     raise ValueError(u"Non-native byte order not supported")
  *                 if   t == NPY_BYTE:        f = "b"
  *                 elif t == NPY_UBYTE:       f = "B"             # <<<<<<<<<<<<<<
@@ -4544,10 +4339,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_UBYTE);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__B;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":259
+    /* "numpy.pxd":256
  *                 if   t == NPY_BYTE:        f = "b"
  *                 elif t == NPY_UBYTE:       f = "B"
  *                 elif t == NPY_SHORT:       f = "h"             # <<<<<<<<<<<<<<
@@ -4557,10 +4352,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_SHORT);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__h;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":260
+    /* "numpy.pxd":257
  *                 elif t == NPY_UBYTE:       f = "B"
  *                 elif t == NPY_SHORT:       f = "h"
  *                 elif t == NPY_USHORT:      f = "H"             # <<<<<<<<<<<<<<
@@ -4570,10 +4365,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_USHORT);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__H;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":261
+    /* "numpy.pxd":258
  *                 elif t == NPY_SHORT:       f = "h"
  *                 elif t == NPY_USHORT:      f = "H"
  *                 elif t == NPY_INT:         f = "i"             # <<<<<<<<<<<<<<
@@ -4583,10 +4378,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_INT);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__i;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":262
+    /* "numpy.pxd":259
  *                 elif t == NPY_USHORT:      f = "H"
  *                 elif t == NPY_INT:         f = "i"
  *                 elif t == NPY_UINT:        f = "I"             # <<<<<<<<<<<<<<
@@ -4596,10 +4391,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_UINT);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__I;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":263
+    /* "numpy.pxd":260
  *                 elif t == NPY_INT:         f = "i"
  *                 elif t == NPY_UINT:        f = "I"
  *                 elif t == NPY_LONG:        f = "l"             # <<<<<<<<<<<<<<
@@ -4609,10 +4404,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_LONG);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__l;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":264
+    /* "numpy.pxd":261
  *                 elif t == NPY_UINT:        f = "I"
  *                 elif t == NPY_LONG:        f = "l"
  *                 elif t == NPY_ULONG:       f = "L"             # <<<<<<<<<<<<<<
@@ -4622,10 +4417,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_ULONG);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__L;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":265
+    /* "numpy.pxd":262
  *                 elif t == NPY_LONG:        f = "l"
  *                 elif t == NPY_ULONG:       f = "L"
  *                 elif t == NPY_LONGLONG:    f = "q"             # <<<<<<<<<<<<<<
@@ -4635,10 +4430,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_LONGLONG);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__q;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":266
+    /* "numpy.pxd":263
  *                 elif t == NPY_ULONG:       f = "L"
  *                 elif t == NPY_LONGLONG:    f = "q"
  *                 elif t == NPY_ULONGLONG:   f = "Q"             # <<<<<<<<<<<<<<
@@ -4648,10 +4443,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_ULONGLONG);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__Q;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":267
+    /* "numpy.pxd":264
  *                 elif t == NPY_LONGLONG:    f = "q"
  *                 elif t == NPY_ULONGLONG:   f = "Q"
  *                 elif t == NPY_FLOAT:       f = "f"             # <<<<<<<<<<<<<<
@@ -4661,10 +4456,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_FLOAT);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__f;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":268
+    /* "numpy.pxd":265
  *                 elif t == NPY_ULONGLONG:   f = "Q"
  *                 elif t == NPY_FLOAT:       f = "f"
  *                 elif t == NPY_DOUBLE:      f = "d"             # <<<<<<<<<<<<<<
@@ -4674,10 +4469,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_DOUBLE);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__d;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":269
+    /* "numpy.pxd":266
  *                 elif t == NPY_FLOAT:       f = "f"
  *                 elif t == NPY_DOUBLE:      f = "d"
  *                 elif t == NPY_LONGDOUBLE:  f = "g"             # <<<<<<<<<<<<<<
@@ -4687,10 +4482,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_LONGDOUBLE);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__g;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":270
+    /* "numpy.pxd":267
  *                 elif t == NPY_DOUBLE:      f = "d"
  *                 elif t == NPY_LONGDOUBLE:  f = "g"
  *                 elif t == NPY_CFLOAT:      f = "Zf"             # <<<<<<<<<<<<<<
@@ -4700,10 +4495,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_CFLOAT);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__Zf;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":271
+    /* "numpy.pxd":268
  *                 elif t == NPY_LONGDOUBLE:  f = "g"
  *                 elif t == NPY_CFLOAT:      f = "Zf"
  *                 elif t == NPY_CDOUBLE:     f = "Zd"             # <<<<<<<<<<<<<<
@@ -4713,10 +4508,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_CDOUBLE);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__Zd;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":272
+    /* "numpy.pxd":269
  *                 elif t == NPY_CFLOAT:      f = "Zf"
  *                 elif t == NPY_CDOUBLE:     f = "Zd"
  *                 elif t == NPY_CLONGDOUBLE: f = "Zg"             # <<<<<<<<<<<<<<
@@ -4726,10 +4521,10 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_CLONGDOUBLE);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__Zg;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
 
-    /* "numpy.pxd":273
+    /* "numpy.pxd":270
  *                 elif t == NPY_CDOUBLE:     f = "Zd"
  *                 elif t == NPY_CLONGDOUBLE: f = "Zg"
  *                 elif t == NPY_OBJECT:      f = "O"             # <<<<<<<<<<<<<<
@@ -4739,37 +4534,37 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     __pyx_t_1 = (__pyx_v_t == NPY_OBJECT);
     if (__pyx_t_1) {
       __pyx_v_f = __pyx_k__O;
-      goto __pyx_L13;
+      goto __pyx_L15;
     }
     /*else*/ {
 
-      /* "numpy.pxd":275
+      /* "numpy.pxd":272
  *                 elif t == NPY_OBJECT:      f = "O"
  *                 else:
  *                     raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t)             # <<<<<<<<<<<<<<
  *                 info.format = f
  *                 return
  */
-      __pyx_t_4 = PyInt_FromLong(__pyx_v_t); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 275; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyInt_FromLong(__pyx_v_t); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 272; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_4);
-      __pyx_t_8 = PyNumber_Remainder(((PyObject *)__pyx_kp_u_11), __pyx_t_4); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 275; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_8 = PyNumber_Remainder(((PyObject *)__pyx_kp_u_11), __pyx_t_4); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 272; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(((PyObject *)__pyx_t_8));
       __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 275; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      __Pyx_GOTREF(__pyx_t_4);
+      __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 272; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(((PyObject *)__pyx_t_4));
       PyTuple_SET_ITEM(__pyx_t_4, 0, ((PyObject *)__pyx_t_8));
       __Pyx_GIVEREF(((PyObject *)__pyx_t_8));
       __pyx_t_8 = 0;
-      __pyx_t_8 = PyObject_Call(__pyx_builtin_ValueError, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 275; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_8 = PyObject_Call(__pyx_builtin_ValueError, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 272; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_8);
       __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
       __Pyx_Raise(__pyx_t_8, 0, 0, 0);
       __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-      {__pyx_filename = __pyx_f[1]; __pyx_lineno = 275; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      {__pyx_filename = __pyx_f[1]; __pyx_lineno = 272; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     }
-    __pyx_L13:;
+    __pyx_L15:;
 
-    /* "numpy.pxd":276
+    /* "numpy.pxd":273
  *                 else:
  *                     raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t)
  *                 info.format = f             # <<<<<<<<<<<<<<
@@ -4778,7 +4573,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
     __pyx_v_info->format = __pyx_v_f;
 
-    /* "numpy.pxd":277
+    /* "numpy.pxd":274
  *                     raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t)
  *                 info.format = f
  *                 return             # <<<<<<<<<<<<<<
@@ -4787,11 +4582,11 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
     __pyx_r = 0;
     goto __pyx_L0;
-    goto __pyx_L11;
+    goto __pyx_L13;
   }
   /*else*/ {
 
-    /* "numpy.pxd":279
+    /* "numpy.pxd":276
  *                 return
  *             else:
  *                 info.format = <char*>stdlib.malloc(_buffer_format_string_len)             # <<<<<<<<<<<<<<
@@ -4800,7 +4595,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
     __pyx_v_info->format = ((char *)malloc(255));
 
-    /* "numpy.pxd":280
+    /* "numpy.pxd":277
  *             else:
  *                 info.format = <char*>stdlib.malloc(_buffer_format_string_len)
  *                 info.format[0] = '^' # Native data types, manual alignment             # <<<<<<<<<<<<<<
@@ -4809,7 +4604,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
     (__pyx_v_info->format[0]) = '^';
 
-    /* "numpy.pxd":281
+    /* "numpy.pxd":278
  *                 info.format = <char*>stdlib.malloc(_buffer_format_string_len)
  *                 info.format[0] = '^' # Native data types, manual alignment
  *                 offset = 0             # <<<<<<<<<<<<<<
@@ -4818,17 +4613,17 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
     __pyx_v_offset = 0;
 
-    /* "numpy.pxd":284
+    /* "numpy.pxd":281
  *                 f = _util_dtypestring(descr, info.format + 1,
  *                                       info.format + _buffer_format_string_len,
  *                                       &offset)             # <<<<<<<<<<<<<<
  *                 f[0] = 0 # Terminate format string
  * 
  */
-    __pyx_t_9 = __pyx_f_5numpy__util_dtypestring(__pyx_v_descr, (__pyx_v_info->format + 1), (__pyx_v_info->format + 255), (&__pyx_v_offset)); if (unlikely(__pyx_t_9 == NULL)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 282; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_9 = __pyx_f_5numpy__util_dtypestring(__pyx_v_descr, (__pyx_v_info->format + 1), (__pyx_v_info->format + 255), (&__pyx_v_offset)); if (unlikely(__pyx_t_9 == NULL)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 279; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __pyx_v_f = __pyx_t_9;
 
-    /* "numpy.pxd":285
+    /* "numpy.pxd":282
  *                                       info.format + _buffer_format_string_len,
  *                                       &offset)
  *                 f[0] = 0 # Terminate format string             # <<<<<<<<<<<<<<
@@ -4837,7 +4632,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  */
     (__pyx_v_f[0]) = 0;
   }
-  __pyx_L11:;
+  __pyx_L13:;
 
   __pyx_r = 0;
   goto __pyx_L0;
@@ -4862,16 +4657,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
   return __pyx_r;
 }
 
-/* Python wrapper */
-static void __pyx_pw_5numpy_7ndarray_3__releasebuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info); /*proto*/
-static void __pyx_pw_5numpy_7ndarray_3__releasebuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info) {
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__releasebuffer__ (wrapper)", 0);
-  __pyx_pf_5numpy_7ndarray_2__releasebuffer__(((PyArrayObject *)__pyx_v_self), ((Py_buffer *)__pyx_v_info));
-  __Pyx_RefNannyFinishContext();
-}
-
-/* "numpy.pxd":287
+/* "numpy.pxd":284
  *                 f[0] = 0 # Terminate format string
  * 
  *         def __releasebuffer__(ndarray self, Py_buffer* info):             # <<<<<<<<<<<<<<
@@ -4879,22 +4665,23 @@ static void __pyx_pw_5numpy_7ndarray_3__releasebuffer__(PyObject *__pyx_v_self,
  *                 stdlib.free(info.format)
  */
 
-static void __pyx_pf_5numpy_7ndarray_2__releasebuffer__(PyArrayObject *__pyx_v_self, Py_buffer *__pyx_v_info) {
+static CYTHON_UNUSED void __pyx_pf_5numpy_7ndarray_1__releasebuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info); /*proto*/
+static CYTHON_UNUSED void __pyx_pf_5numpy_7ndarray_1__releasebuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info) {
   __Pyx_RefNannyDeclarations
   int __pyx_t_1;
-  __Pyx_RefNannySetupContext("__releasebuffer__", 0);
+  __Pyx_RefNannySetupContext("__releasebuffer__");
 
-  /* "numpy.pxd":288
+  /* "numpy.pxd":285
  * 
  *         def __releasebuffer__(ndarray self, Py_buffer* info):
  *             if PyArray_HASFIELDS(self):             # <<<<<<<<<<<<<<
  *                 stdlib.free(info.format)
  *             if sizeof(npy_intp) != sizeof(Py_ssize_t):
  */
-  __pyx_t_1 = PyArray_HASFIELDS(__pyx_v_self);
+  __pyx_t_1 = PyArray_HASFIELDS(((PyArrayObject *)__pyx_v_self));
   if (__pyx_t_1) {
 
-    /* "numpy.pxd":289
+    /* "numpy.pxd":286
  *         def __releasebuffer__(ndarray self, Py_buffer* info):
  *             if PyArray_HASFIELDS(self):
  *                 stdlib.free(info.format)             # <<<<<<<<<<<<<<
@@ -4902,11 +4689,11 @@ static void __pyx_pf_5numpy_7ndarray_2__releasebuffer__(PyArrayObject *__pyx_v_s
  *                 stdlib.free(info.strides)
  */
     free(__pyx_v_info->format);
-    goto __pyx_L3;
+    goto __pyx_L5;
   }
-  __pyx_L3:;
+  __pyx_L5:;
 
-  /* "numpy.pxd":290
+  /* "numpy.pxd":287
  *             if PyArray_HASFIELDS(self):
  *                 stdlib.free(info.format)
  *             if sizeof(npy_intp) != sizeof(Py_ssize_t):             # <<<<<<<<<<<<<<
@@ -4916,7 +4703,7 @@ static void __pyx_pf_5numpy_7ndarray_2__releasebuffer__(PyArrayObject *__pyx_v_s
   __pyx_t_1 = ((sizeof(npy_intp)) != (sizeof(Py_ssize_t)));
   if (__pyx_t_1) {
 
-    /* "numpy.pxd":291
+    /* "numpy.pxd":288
  *                 stdlib.free(info.format)
  *             if sizeof(npy_intp) != sizeof(Py_ssize_t):
  *                 stdlib.free(info.strides)             # <<<<<<<<<<<<<<
@@ -4924,14 +4711,14 @@ static void __pyx_pf_5numpy_7ndarray_2__releasebuffer__(PyArrayObject *__pyx_v_s
  * 
  */
     free(__pyx_v_info->strides);
-    goto __pyx_L4;
+    goto __pyx_L6;
   }
-  __pyx_L4:;
+  __pyx_L6:;
 
   __Pyx_RefNannyFinishContext();
 }
 
-/* "numpy.pxd":767
+/* "numpy.pxd":764
  * ctypedef npy_cdouble     complex_t
  * 
  * cdef inline object PyArray_MultiIterNew1(a):             # <<<<<<<<<<<<<<
@@ -4946,9 +4733,9 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew1(PyObject *__
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("PyArray_MultiIterNew1", 0);
+  __Pyx_RefNannySetupContext("PyArray_MultiIterNew1");
 
-  /* "numpy.pxd":768
+  /* "numpy.pxd":765
  * 
  * cdef inline object PyArray_MultiIterNew1(a):
  *     return PyArray_MultiIterNew(1, <void*>a)             # <<<<<<<<<<<<<<
@@ -4956,7 +4743,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew1(PyObject *__
  * cdef inline object PyArray_MultiIterNew2(a, b):
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = PyArray_MultiIterNew(1, ((void *)__pyx_v_a)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 768; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyArray_MultiIterNew(1, ((void *)__pyx_v_a)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 765; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -4974,7 +4761,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew1(PyObject *__
   return __pyx_r;
 }
 
-/* "numpy.pxd":770
+/* "numpy.pxd":767
  *     return PyArray_MultiIterNew(1, <void*>a)
  * 
  * cdef inline object PyArray_MultiIterNew2(a, b):             # <<<<<<<<<<<<<<
@@ -4989,9 +4776,9 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew2(PyObject *__
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("PyArray_MultiIterNew2", 0);
+  __Pyx_RefNannySetupContext("PyArray_MultiIterNew2");
 
-  /* "numpy.pxd":771
+  /* "numpy.pxd":768
  * 
  * cdef inline object PyArray_MultiIterNew2(a, b):
  *     return PyArray_MultiIterNew(2, <void*>a, <void*>b)             # <<<<<<<<<<<<<<
@@ -4999,7 +4786,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew2(PyObject *__
  * cdef inline object PyArray_MultiIterNew3(a, b, c):
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = PyArray_MultiIterNew(2, ((void *)__pyx_v_a), ((void *)__pyx_v_b)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 771; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyArray_MultiIterNew(2, ((void *)__pyx_v_a), ((void *)__pyx_v_b)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 768; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -5017,7 +4804,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew2(PyObject *__
   return __pyx_r;
 }
 
-/* "numpy.pxd":773
+/* "numpy.pxd":770
  *     return PyArray_MultiIterNew(2, <void*>a, <void*>b)
  * 
  * cdef inline object PyArray_MultiIterNew3(a, b, c):             # <<<<<<<<<<<<<<
@@ -5032,9 +4819,9 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew3(PyObject *__
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("PyArray_MultiIterNew3", 0);
+  __Pyx_RefNannySetupContext("PyArray_MultiIterNew3");
 
-  /* "numpy.pxd":774
+  /* "numpy.pxd":771
  * 
  * cdef inline object PyArray_MultiIterNew3(a, b, c):
  *     return PyArray_MultiIterNew(3, <void*>a, <void*>b, <void*> c)             # <<<<<<<<<<<<<<
@@ -5042,7 +4829,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew3(PyObject *__
  * cdef inline object PyArray_MultiIterNew4(a, b, c, d):
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = PyArray_MultiIterNew(3, ((void *)__pyx_v_a), ((void *)__pyx_v_b), ((void *)__pyx_v_c)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 774; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyArray_MultiIterNew(3, ((void *)__pyx_v_a), ((void *)__pyx_v_b), ((void *)__pyx_v_c)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 771; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -5060,7 +4847,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew3(PyObject *__
   return __pyx_r;
 }
 
-/* "numpy.pxd":776
+/* "numpy.pxd":773
  *     return PyArray_MultiIterNew(3, <void*>a, <void*>b, <void*> c)
  * 
  * cdef inline object PyArray_MultiIterNew4(a, b, c, d):             # <<<<<<<<<<<<<<
@@ -5075,9 +4862,9 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew4(PyObject *__
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("PyArray_MultiIterNew4", 0);
+  __Pyx_RefNannySetupContext("PyArray_MultiIterNew4");
 
-  /* "numpy.pxd":777
+  /* "numpy.pxd":774
  * 
  * cdef inline object PyArray_MultiIterNew4(a, b, c, d):
  *     return PyArray_MultiIterNew(4, <void*>a, <void*>b, <void*>c, <void*> d)             # <<<<<<<<<<<<<<
@@ -5085,7 +4872,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew4(PyObject *__
  * cdef inline object PyArray_MultiIterNew5(a, b, c, d, e):
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = PyArray_MultiIterNew(4, ((void *)__pyx_v_a), ((void *)__pyx_v_b), ((void *)__pyx_v_c), ((void *)__pyx_v_d)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 777; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyArray_MultiIterNew(4, ((void *)__pyx_v_a), ((void *)__pyx_v_b), ((void *)__pyx_v_c), ((void *)__pyx_v_d)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 774; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -5103,7 +4890,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew4(PyObject *__
   return __pyx_r;
 }
 
-/* "numpy.pxd":779
+/* "numpy.pxd":776
  *     return PyArray_MultiIterNew(4, <void*>a, <void*>b, <void*>c, <void*> d)
  * 
  * cdef inline object PyArray_MultiIterNew5(a, b, c, d, e):             # <<<<<<<<<<<<<<
@@ -5118,9 +4905,9 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew5(PyObject *__
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("PyArray_MultiIterNew5", 0);
+  __Pyx_RefNannySetupContext("PyArray_MultiIterNew5");
 
-  /* "numpy.pxd":780
+  /* "numpy.pxd":777
  * 
  * cdef inline object PyArray_MultiIterNew5(a, b, c, d, e):
  *     return PyArray_MultiIterNew(5, <void*>a, <void*>b, <void*>c, <void*> d, <void*> e)             # <<<<<<<<<<<<<<
@@ -5128,7 +4915,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew5(PyObject *__
  * cdef inline char* _util_dtypestring(dtype descr, char* f, char* end, int* offset) except NULL:
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = PyArray_MultiIterNew(5, ((void *)__pyx_v_a), ((void *)__pyx_v_b), ((void *)__pyx_v_c), ((void *)__pyx_v_d), ((void *)__pyx_v_e)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 780; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyArray_MultiIterNew(5, ((void *)__pyx_v_a), ((void *)__pyx_v_b), ((void *)__pyx_v_c), ((void *)__pyx_v_d), ((void *)__pyx_v_e)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 777; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -5146,7 +4933,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew5(PyObject *__
   return __pyx_r;
 }
 
-/* "numpy.pxd":782
+/* "numpy.pxd":779
  *     return PyArray_MultiIterNew(5, <void*>a, <void*>b, <void*>c, <void*> d, <void*> e)
  * 
  * cdef inline char* _util_dtypestring(dtype descr, char* f, char* end, int* offset) except NULL:             # <<<<<<<<<<<<<<
@@ -5178,9 +4965,9 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("_util_dtypestring", 0);
+  __Pyx_RefNannySetupContext("_util_dtypestring");
 
-  /* "numpy.pxd":789
+  /* "numpy.pxd":786
  *     cdef int delta_offset
  *     cdef tuple i
  *     cdef int endian_detector = 1             # <<<<<<<<<<<<<<
@@ -5189,7 +4976,7 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
  */
   __pyx_v_endian_detector = 1;
 
-  /* "numpy.pxd":790
+  /* "numpy.pxd":787
  *     cdef tuple i
  *     cdef int endian_detector = 1
  *     cdef bint little_endian = ((<char*>&endian_detector)[0] != 0)             # <<<<<<<<<<<<<<
@@ -5198,7 +4985,7 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
  */
   __pyx_v_little_endian = ((((char *)(&__pyx_v_endian_detector))[0]) != 0);
 
-  /* "numpy.pxd":793
+  /* "numpy.pxd":790
  *     cdef tuple fields
  * 
  *     for childname in descr.names:             # <<<<<<<<<<<<<<
@@ -5206,7 +4993,7 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
  *         child, new_offset = fields
  */
   if (unlikely(((PyObject *)__pyx_v_descr->names) == Py_None)) {
-    PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable"); {__pyx_filename = __pyx_f[1]; __pyx_lineno = 793; __pyx_clineno = __LINE__; goto __pyx_L1_error;} 
+    PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable"); {__pyx_filename = __pyx_f[1]; __pyx_lineno = 790; __pyx_clineno = __LINE__; goto __pyx_L1_error;} 
   }
   __pyx_t_1 = ((PyObject *)__pyx_v_descr->names); __Pyx_INCREF(__pyx_t_1); __pyx_t_2 = 0;
   for (;;) {
@@ -5216,21 +5003,21 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
     __pyx_v_childname = __pyx_t_3;
     __pyx_t_3 = 0;
 
-    /* "numpy.pxd":794
+    /* "numpy.pxd":791
  * 
  *     for childname in descr.names:
  *         fields = descr.fields[childname]             # <<<<<<<<<<<<<<
  *         child, new_offset = fields
  * 
  */
-    __pyx_t_3 = PyObject_GetItem(__pyx_v_descr->fields, __pyx_v_childname); if (!__pyx_t_3) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 794; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = PyObject_GetItem(__pyx_v_descr->fields, __pyx_v_childname); if (!__pyx_t_3) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 791; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_3);
-    if (!(likely(PyTuple_CheckExact(__pyx_t_3))||((__pyx_t_3) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected tuple, got %.200s", Py_TYPE(__pyx_t_3)->tp_name), 0))) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 794; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (!(likely(PyTuple_CheckExact(__pyx_t_3))||((__pyx_t_3) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected tuple, got %.200s", Py_TYPE(__pyx_t_3)->tp_name), 0))) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 791; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_XDECREF(((PyObject *)__pyx_v_fields));
     __pyx_v_fields = ((PyObject*)__pyx_t_3);
     __pyx_t_3 = 0;
 
-    /* "numpy.pxd":795
+    /* "numpy.pxd":792
  *     for childname in descr.names:
  *         fields = descr.fields[childname]
  *         child, new_offset = fields             # <<<<<<<<<<<<<<
@@ -5242,7 +5029,7 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
       if (unlikely(PyTuple_GET_SIZE(sequence) != 2)) {
         if (PyTuple_GET_SIZE(sequence) > 2) __Pyx_RaiseTooManyValuesError(2);
         else __Pyx_RaiseNeedMoreValuesError(PyTuple_GET_SIZE(sequence));
-        {__pyx_filename = __pyx_f[1]; __pyx_lineno = 795; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        {__pyx_filename = __pyx_f[1]; __pyx_lineno = 792; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       }
       __pyx_t_3 = PyTuple_GET_ITEM(sequence, 0); 
       __pyx_t_4 = PyTuple_GET_ITEM(sequence, 1); 
@@ -5250,9 +5037,9 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
       __Pyx_INCREF(__pyx_t_4);
     } else {
       __Pyx_UnpackTupleError(((PyObject *)__pyx_v_fields), 2);
-      {__pyx_filename = __pyx_f[1]; __pyx_lineno = 795; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      {__pyx_filename = __pyx_f[1]; __pyx_lineno = 792; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     }
-    if (!(likely(((__pyx_t_3) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_3, __pyx_ptype_5numpy_dtype))))) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 795; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (!(likely(((__pyx_t_3) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_3, __pyx_ptype_5numpy_dtype))))) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 792; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_XDECREF(((PyObject *)__pyx_v_child));
     __pyx_v_child = ((PyArray_Descr *)__pyx_t_3);
     __pyx_t_3 = 0;
@@ -5260,48 +5047,48 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
     __pyx_v_new_offset = __pyx_t_4;
     __pyx_t_4 = 0;
 
-    /* "numpy.pxd":797
+    /* "numpy.pxd":794
  *         child, new_offset = fields
  * 
  *         if (end - f) - (new_offset - offset[0]) < 15:             # <<<<<<<<<<<<<<
  *             raise RuntimeError(u"Format string allocated too short, see comment in numpy.pxd")
  * 
  */
-    __pyx_t_4 = PyInt_FromLong((__pyx_v_end - __pyx_v_f)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 797; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = PyInt_FromLong((__pyx_v_end - __pyx_v_f)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 794; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_4);
-    __pyx_t_3 = PyInt_FromLong((__pyx_v_offset[0])); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 797; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = PyInt_FromLong((__pyx_v_offset[0])); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 794; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_3);
-    __pyx_t_5 = PyNumber_Subtract(__pyx_v_new_offset, __pyx_t_3); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 797; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = PyNumber_Subtract(__pyx_v_new_offset, __pyx_t_3); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 794; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_5);
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __pyx_t_3 = PyNumber_Subtract(__pyx_t_4, __pyx_t_5); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 797; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = PyNumber_Subtract(__pyx_t_4, __pyx_t_5); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 794; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_3);
     __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
     __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-    __pyx_t_5 = PyObject_RichCompare(__pyx_t_3, __pyx_int_15, Py_LT); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 797; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = PyObject_RichCompare(__pyx_t_3, __pyx_int_15, Py_LT); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 794; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_5);
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 797; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 794; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
     if (__pyx_t_6) {
 
-      /* "numpy.pxd":798
+      /* "numpy.pxd":795
  * 
  *         if (end - f) - (new_offset - offset[0]) < 15:
  *             raise RuntimeError(u"Format string allocated too short, see comment in numpy.pxd")             # <<<<<<<<<<<<<<
  * 
  *         if ((child.byteorder == '>' and little_endian) or
  */
-      __pyx_t_5 = PyObject_Call(__pyx_builtin_RuntimeError, ((PyObject *)__pyx_k_tuple_13), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 798; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyObject_Call(__pyx_builtin_RuntimeError, ((PyObject *)__pyx_k_tuple_13), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 795; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
       __Pyx_Raise(__pyx_t_5, 0, 0, 0);
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      {__pyx_filename = __pyx_f[1]; __pyx_lineno = 798; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      {__pyx_filename = __pyx_f[1]; __pyx_lineno = 795; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       goto __pyx_L5;
     }
     __pyx_L5:;
 
-    /* "numpy.pxd":800
+    /* "numpy.pxd":797
  *             raise RuntimeError(u"Format string allocated too short, see comment in numpy.pxd")
  * 
  *         if ((child.byteorder == '>' and little_endian) or             # <<<<<<<<<<<<<<
@@ -5316,7 +5103,7 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
     }
     if (!__pyx_t_7) {
 
-      /* "numpy.pxd":801
+      /* "numpy.pxd":798
  * 
  *         if ((child.byteorder == '>' and little_endian) or
  *             (child.byteorder == '<' and not little_endian)):             # <<<<<<<<<<<<<<
@@ -5336,23 +5123,23 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
     }
     if (__pyx_t_6) {
 
-      /* "numpy.pxd":802
+      /* "numpy.pxd":799
  *         if ((child.byteorder == '>' and little_endian) or
  *             (child.byteorder == '<' and not little_endian)):
  *             raise ValueError(u"Non-native byte order not supported")             # <<<<<<<<<<<<<<
  *             # One could encode it in the format string and have Cython
  *             # complain instead, BUT: < and > in format strings also imply
  */
-      __pyx_t_5 = PyObject_Call(__pyx_builtin_ValueError, ((PyObject *)__pyx_k_tuple_14), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 802; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyObject_Call(__pyx_builtin_ValueError, ((PyObject *)__pyx_k_tuple_14), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 799; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
       __Pyx_Raise(__pyx_t_5, 0, 0, 0);
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      {__pyx_filename = __pyx_f[1]; __pyx_lineno = 802; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      {__pyx_filename = __pyx_f[1]; __pyx_lineno = 799; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       goto __pyx_L6;
     }
     __pyx_L6:;
 
-    /* "numpy.pxd":812
+    /* "numpy.pxd":809
  * 
  *         # Output padding bytes
  *         while offset[0] < new_offset:             # <<<<<<<<<<<<<<
@@ -5360,16 +5147,16 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
  *             f += 1
  */
     while (1) {
-      __pyx_t_5 = PyInt_FromLong((__pyx_v_offset[0])); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 812; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyInt_FromLong((__pyx_v_offset[0])); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 809; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
-      __pyx_t_3 = PyObject_RichCompare(__pyx_t_5, __pyx_v_new_offset, Py_LT); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 812; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyObject_RichCompare(__pyx_t_5, __pyx_v_new_offset, Py_LT); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 809; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 812; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 809; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
       if (!__pyx_t_6) break;
 
-      /* "numpy.pxd":813
+      /* "numpy.pxd":810
  *         # Output padding bytes
  *         while offset[0] < new_offset:
  *             f[0] = 120 # "x"; pad byte             # <<<<<<<<<<<<<<
@@ -5378,7 +5165,7 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
  */
       (__pyx_v_f[0]) = 120;
 
-      /* "numpy.pxd":814
+      /* "numpy.pxd":811
  *         while offset[0] < new_offset:
  *             f[0] = 120 # "x"; pad byte
  *             f += 1             # <<<<<<<<<<<<<<
@@ -5387,7 +5174,7 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
  */
       __pyx_v_f = (__pyx_v_f + 1);
 
-      /* "numpy.pxd":815
+      /* "numpy.pxd":812
  *             f[0] = 120 # "x"; pad byte
  *             f += 1
  *             offset[0] += 1             # <<<<<<<<<<<<<<
@@ -5398,7 +5185,7 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
       (__pyx_v_offset[__pyx_t_10]) = ((__pyx_v_offset[__pyx_t_10]) + 1);
     }
 
-    /* "numpy.pxd":817
+    /* "numpy.pxd":814
  *             offset[0] += 1
  * 
  *         offset[0] += child.itemsize             # <<<<<<<<<<<<<<
@@ -5408,7 +5195,7 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
     __pyx_t_10 = 0;
     (__pyx_v_offset[__pyx_t_10]) = ((__pyx_v_offset[__pyx_t_10]) + __pyx_v_child->elsize);
 
-    /* "numpy.pxd":819
+    /* "numpy.pxd":816
  *         offset[0] += child.itemsize
  * 
  *         if not PyDataType_HASFIELDS(child):             # <<<<<<<<<<<<<<
@@ -5418,20 +5205,20 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
     __pyx_t_6 = (!PyDataType_HASFIELDS(__pyx_v_child));
     if (__pyx_t_6) {
 
-      /* "numpy.pxd":820
+      /* "numpy.pxd":817
  * 
  *         if not PyDataType_HASFIELDS(child):
  *             t = child.type_num             # <<<<<<<<<<<<<<
  *             if end - f < 5:
  *                 raise RuntimeError(u"Format string allocated too short.")
  */
-      __pyx_t_3 = PyInt_FromLong(__pyx_v_child->type_num); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 820; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyInt_FromLong(__pyx_v_child->type_num); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 817; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_XDECREF(__pyx_v_t);
       __pyx_v_t = __pyx_t_3;
       __pyx_t_3 = 0;
 
-      /* "numpy.pxd":821
+      /* "numpy.pxd":818
  *         if not PyDataType_HASFIELDS(child):
  *             t = child.type_num
  *             if end - f < 5:             # <<<<<<<<<<<<<<
@@ -5441,282 +5228,282 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
       __pyx_t_6 = ((__pyx_v_end - __pyx_v_f) < 5);
       if (__pyx_t_6) {
 
-        /* "numpy.pxd":822
+        /* "numpy.pxd":819
  *             t = child.type_num
  *             if end - f < 5:
  *                 raise RuntimeError(u"Format string allocated too short.")             # <<<<<<<<<<<<<<
  * 
  *             # Until ticket #99 is fixed, use integers to avoid warnings
  */
-        __pyx_t_3 = PyObject_Call(__pyx_builtin_RuntimeError, ((PyObject *)__pyx_k_tuple_16), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 822; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_3 = PyObject_Call(__pyx_builtin_RuntimeError, ((PyObject *)__pyx_k_tuple_16), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 819; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_3);
         __Pyx_Raise(__pyx_t_3, 0, 0, 0);
         __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-        {__pyx_filename = __pyx_f[1]; __pyx_lineno = 822; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        {__pyx_filename = __pyx_f[1]; __pyx_lineno = 819; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         goto __pyx_L10;
       }
       __pyx_L10:;
 
-      /* "numpy.pxd":825
+      /* "numpy.pxd":822
  * 
  *             # Until ticket #99 is fixed, use integers to avoid warnings
  *             if   t == NPY_BYTE:        f[0] =  98 #"b"             # <<<<<<<<<<<<<<
  *             elif t == NPY_UBYTE:       f[0] =  66 #"B"
  *             elif t == NPY_SHORT:       f[0] = 104 #"h"
  */
-      __pyx_t_3 = PyInt_FromLong(NPY_BYTE); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 825; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyInt_FromLong(NPY_BYTE); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 822; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 825; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 822; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 825; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 822; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 98;
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":826
+      /* "numpy.pxd":823
  *             # Until ticket #99 is fixed, use integers to avoid warnings
  *             if   t == NPY_BYTE:        f[0] =  98 #"b"
  *             elif t == NPY_UBYTE:       f[0] =  66 #"B"             # <<<<<<<<<<<<<<
  *             elif t == NPY_SHORT:       f[0] = 104 #"h"
  *             elif t == NPY_USHORT:      f[0] =  72 #"H"
  */
-      __pyx_t_5 = PyInt_FromLong(NPY_UBYTE); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 826; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyInt_FromLong(NPY_UBYTE); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 823; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
-      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 826; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 823; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 826; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 823; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 66;
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":827
+      /* "numpy.pxd":824
  *             if   t == NPY_BYTE:        f[0] =  98 #"b"
  *             elif t == NPY_UBYTE:       f[0] =  66 #"B"
  *             elif t == NPY_SHORT:       f[0] = 104 #"h"             # <<<<<<<<<<<<<<
  *             elif t == NPY_USHORT:      f[0] =  72 #"H"
  *             elif t == NPY_INT:         f[0] = 105 #"i"
  */
-      __pyx_t_3 = PyInt_FromLong(NPY_SHORT); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 827; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyInt_FromLong(NPY_SHORT); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 824; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 827; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 824; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 827; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 824; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 104;
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":828
+      /* "numpy.pxd":825
  *             elif t == NPY_UBYTE:       f[0] =  66 #"B"
  *             elif t == NPY_SHORT:       f[0] = 104 #"h"
  *             elif t == NPY_USHORT:      f[0] =  72 #"H"             # <<<<<<<<<<<<<<
  *             elif t == NPY_INT:         f[0] = 105 #"i"
  *             elif t == NPY_UINT:        f[0] =  73 #"I"
  */
-      __pyx_t_5 = PyInt_FromLong(NPY_USHORT); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 828; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyInt_FromLong(NPY_USHORT); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 825; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
-      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 828; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 825; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 828; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 825; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 72;
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":829
+      /* "numpy.pxd":826
  *             elif t == NPY_SHORT:       f[0] = 104 #"h"
  *             elif t == NPY_USHORT:      f[0] =  72 #"H"
  *             elif t == NPY_INT:         f[0] = 105 #"i"             # <<<<<<<<<<<<<<
  *             elif t == NPY_UINT:        f[0] =  73 #"I"
  *             elif t == NPY_LONG:        f[0] = 108 #"l"
  */
-      __pyx_t_3 = PyInt_FromLong(NPY_INT); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 829; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyInt_FromLong(NPY_INT); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 826; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 829; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 826; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 829; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 826; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 105;
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":830
+      /* "numpy.pxd":827
  *             elif t == NPY_USHORT:      f[0] =  72 #"H"
  *             elif t == NPY_INT:         f[0] = 105 #"i"
  *             elif t == NPY_UINT:        f[0] =  73 #"I"             # <<<<<<<<<<<<<<
  *             elif t == NPY_LONG:        f[0] = 108 #"l"
  *             elif t == NPY_ULONG:       f[0] = 76  #"L"
  */
-      __pyx_t_5 = PyInt_FromLong(NPY_UINT); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 830; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyInt_FromLong(NPY_UINT); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 827; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
-      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 830; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 827; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 830; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 827; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 73;
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":831
+      /* "numpy.pxd":828
  *             elif t == NPY_INT:         f[0] = 105 #"i"
  *             elif t == NPY_UINT:        f[0] =  73 #"I"
  *             elif t == NPY_LONG:        f[0] = 108 #"l"             # <<<<<<<<<<<<<<
  *             elif t == NPY_ULONG:       f[0] = 76  #"L"
  *             elif t == NPY_LONGLONG:    f[0] = 113 #"q"
  */
-      __pyx_t_3 = PyInt_FromLong(NPY_LONG); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 831; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyInt_FromLong(NPY_LONG); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 828; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 831; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 828; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 831; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 828; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 108;
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":832
+      /* "numpy.pxd":829
  *             elif t == NPY_UINT:        f[0] =  73 #"I"
  *             elif t == NPY_LONG:        f[0] = 108 #"l"
  *             elif t == NPY_ULONG:       f[0] = 76  #"L"             # <<<<<<<<<<<<<<
  *             elif t == NPY_LONGLONG:    f[0] = 113 #"q"
  *             elif t == NPY_ULONGLONG:   f[0] = 81  #"Q"
  */
-      __pyx_t_5 = PyInt_FromLong(NPY_ULONG); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 832; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyInt_FromLong(NPY_ULONG); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 829; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
-      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 832; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 829; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 832; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 829; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 76;
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":833
+      /* "numpy.pxd":830
  *             elif t == NPY_LONG:        f[0] = 108 #"l"
  *             elif t == NPY_ULONG:       f[0] = 76  #"L"
  *             elif t == NPY_LONGLONG:    f[0] = 113 #"q"             # <<<<<<<<<<<<<<
  *             elif t == NPY_ULONGLONG:   f[0] = 81  #"Q"
  *             elif t == NPY_FLOAT:       f[0] = 102 #"f"
  */
-      __pyx_t_3 = PyInt_FromLong(NPY_LONGLONG); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 833; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyInt_FromLong(NPY_LONGLONG); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 830; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 833; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 830; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 833; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 830; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 113;
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":834
+      /* "numpy.pxd":831
  *             elif t == NPY_ULONG:       f[0] = 76  #"L"
  *             elif t == NPY_LONGLONG:    f[0] = 113 #"q"
  *             elif t == NPY_ULONGLONG:   f[0] = 81  #"Q"             # <<<<<<<<<<<<<<
  *             elif t == NPY_FLOAT:       f[0] = 102 #"f"
  *             elif t == NPY_DOUBLE:      f[0] = 100 #"d"
  */
-      __pyx_t_5 = PyInt_FromLong(NPY_ULONGLONG); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 834; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyInt_FromLong(NPY_ULONGLONG); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 831; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
-      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 834; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 831; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 834; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 831; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 81;
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":835
+      /* "numpy.pxd":832
  *             elif t == NPY_LONGLONG:    f[0] = 113 #"q"
  *             elif t == NPY_ULONGLONG:   f[0] = 81  #"Q"
  *             elif t == NPY_FLOAT:       f[0] = 102 #"f"             # <<<<<<<<<<<<<<
  *             elif t == NPY_DOUBLE:      f[0] = 100 #"d"
  *             elif t == NPY_LONGDOUBLE:  f[0] = 103 #"g"
  */
-      __pyx_t_3 = PyInt_FromLong(NPY_FLOAT); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 835; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyInt_FromLong(NPY_FLOAT); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 832; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 835; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 832; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 835; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 832; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 102;
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":836
+      /* "numpy.pxd":833
  *             elif t == NPY_ULONGLONG:   f[0] = 81  #"Q"
  *             elif t == NPY_FLOAT:       f[0] = 102 #"f"
  *             elif t == NPY_DOUBLE:      f[0] = 100 #"d"             # <<<<<<<<<<<<<<
  *             elif t == NPY_LONGDOUBLE:  f[0] = 103 #"g"
  *             elif t == NPY_CFLOAT:      f[0] = 90; f[1] = 102; f += 1 # Zf
  */
-      __pyx_t_5 = PyInt_FromLong(NPY_DOUBLE); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 836; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyInt_FromLong(NPY_DOUBLE); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 833; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
-      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 836; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 833; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 836; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 833; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 100;
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":837
+      /* "numpy.pxd":834
  *             elif t == NPY_FLOAT:       f[0] = 102 #"f"
  *             elif t == NPY_DOUBLE:      f[0] = 100 #"d"
  *             elif t == NPY_LONGDOUBLE:  f[0] = 103 #"g"             # <<<<<<<<<<<<<<
  *             elif t == NPY_CFLOAT:      f[0] = 90; f[1] = 102; f += 1 # Zf
  *             elif t == NPY_CDOUBLE:     f[0] = 90; f[1] = 100; f += 1 # Zd
  */
-      __pyx_t_3 = PyInt_FromLong(NPY_LONGDOUBLE); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 837; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyInt_FromLong(NPY_LONGDOUBLE); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 834; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 837; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 834; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 837; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 834; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 103;
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":838
+      /* "numpy.pxd":835
  *             elif t == NPY_DOUBLE:      f[0] = 100 #"d"
  *             elif t == NPY_LONGDOUBLE:  f[0] = 103 #"g"
  *             elif t == NPY_CFLOAT:      f[0] = 90; f[1] = 102; f += 1 # Zf             # <<<<<<<<<<<<<<
  *             elif t == NPY_CDOUBLE:     f[0] = 90; f[1] = 100; f += 1 # Zd
  *             elif t == NPY_CLONGDOUBLE: f[0] = 90; f[1] = 103; f += 1 # Zg
  */
-      __pyx_t_5 = PyInt_FromLong(NPY_CFLOAT); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 838; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyInt_FromLong(NPY_CFLOAT); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 835; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
-      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 838; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 835; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 838; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 835; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 90;
@@ -5725,19 +5512,19 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":839
+      /* "numpy.pxd":836
  *             elif t == NPY_LONGDOUBLE:  f[0] = 103 #"g"
  *             elif t == NPY_CFLOAT:      f[0] = 90; f[1] = 102; f += 1 # Zf
  *             elif t == NPY_CDOUBLE:     f[0] = 90; f[1] = 100; f += 1 # Zd             # <<<<<<<<<<<<<<
  *             elif t == NPY_CLONGDOUBLE: f[0] = 90; f[1] = 103; f += 1 # Zg
  *             elif t == NPY_OBJECT:      f[0] = 79 #"O"
  */
-      __pyx_t_3 = PyInt_FromLong(NPY_CDOUBLE); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 839; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyInt_FromLong(NPY_CDOUBLE); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 836; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 839; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 836; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 839; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 836; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 90;
@@ -5746,19 +5533,19 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":840
+      /* "numpy.pxd":837
  *             elif t == NPY_CFLOAT:      f[0] = 90; f[1] = 102; f += 1 # Zf
  *             elif t == NPY_CDOUBLE:     f[0] = 90; f[1] = 100; f += 1 # Zd
  *             elif t == NPY_CLONGDOUBLE: f[0] = 90; f[1] = 103; f += 1 # Zg             # <<<<<<<<<<<<<<
  *             elif t == NPY_OBJECT:      f[0] = 79 #"O"
  *             else:
  */
-      __pyx_t_5 = PyInt_FromLong(NPY_CLONGDOUBLE); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 840; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyInt_FromLong(NPY_CLONGDOUBLE); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 837; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
-      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 840; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 837; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 840; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 837; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 90;
@@ -5767,19 +5554,19 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
         goto __pyx_L11;
       }
 
-      /* "numpy.pxd":841
+      /* "numpy.pxd":838
  *             elif t == NPY_CDOUBLE:     f[0] = 90; f[1] = 100; f += 1 # Zd
  *             elif t == NPY_CLONGDOUBLE: f[0] = 90; f[1] = 103; f += 1 # Zg
  *             elif t == NPY_OBJECT:      f[0] = 79 #"O"             # <<<<<<<<<<<<<<
  *             else:
  *                 raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t)
  */
-      __pyx_t_3 = PyInt_FromLong(NPY_OBJECT); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 841; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyInt_FromLong(NPY_OBJECT); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 838; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 841; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 838; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 841; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 838; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
       if (__pyx_t_6) {
         (__pyx_v_f[0]) = 79;
@@ -5787,30 +5574,30 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
       }
       /*else*/ {
 
-        /* "numpy.pxd":843
+        /* "numpy.pxd":840
  *             elif t == NPY_OBJECT:      f[0] = 79 #"O"
  *             else:
  *                 raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t)             # <<<<<<<<<<<<<<
  *             f += 1
  *         else:
  */
-        __pyx_t_5 = PyNumber_Remainder(((PyObject *)__pyx_kp_u_11), __pyx_v_t); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 843; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_5 = PyNumber_Remainder(((PyObject *)__pyx_kp_u_11), __pyx_v_t); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 840; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(((PyObject *)__pyx_t_5));
-        __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 843; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-        __Pyx_GOTREF(__pyx_t_3);
+        __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 840; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __Pyx_GOTREF(((PyObject *)__pyx_t_3));
         PyTuple_SET_ITEM(__pyx_t_3, 0, ((PyObject *)__pyx_t_5));
         __Pyx_GIVEREF(((PyObject *)__pyx_t_5));
         __pyx_t_5 = 0;
-        __pyx_t_5 = PyObject_Call(__pyx_builtin_ValueError, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 843; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_5 = PyObject_Call(__pyx_builtin_ValueError, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 840; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_5);
         __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
         __Pyx_Raise(__pyx_t_5, 0, 0, 0);
         __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-        {__pyx_filename = __pyx_f[1]; __pyx_lineno = 843; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        {__pyx_filename = __pyx_f[1]; __pyx_lineno = 840; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       }
       __pyx_L11:;
 
-      /* "numpy.pxd":844
+      /* "numpy.pxd":841
  *             else:
  *                 raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t)
  *             f += 1             # <<<<<<<<<<<<<<
@@ -5822,21 +5609,21 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
     }
     /*else*/ {
 
-      /* "numpy.pxd":848
+      /* "numpy.pxd":845
  *             # Cython ignores struct boundary information ("T{...}"),
  *             # so don't output it
  *             f = _util_dtypestring(child, f, end, offset)             # <<<<<<<<<<<<<<
  *     return f
  * 
  */
-      __pyx_t_11 = __pyx_f_5numpy__util_dtypestring(__pyx_v_child, __pyx_v_f, __pyx_v_end, __pyx_v_offset); if (unlikely(__pyx_t_11 == NULL)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 848; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_11 = __pyx_f_5numpy__util_dtypestring(__pyx_v_child, __pyx_v_f, __pyx_v_end, __pyx_v_offset); if (unlikely(__pyx_t_11 == NULL)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 845; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __pyx_v_f = __pyx_t_11;
     }
     __pyx_L9:;
   }
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "numpy.pxd":849
+  /* "numpy.pxd":846
  *             # so don't output it
  *             f = _util_dtypestring(child, f, end, offset)
  *     return f             # <<<<<<<<<<<<<<
@@ -5865,7 +5652,7 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
   return __pyx_r;
 }
 
-/* "numpy.pxd":964
+/* "numpy.pxd":961
  * 
  * 
  * cdef inline void set_array_base(ndarray arr, object base):             # <<<<<<<<<<<<<<
@@ -5877,9 +5664,9 @@ static CYTHON_INLINE void __pyx_f_5numpy_set_array_base(PyArrayObject *__pyx_v_a
   PyObject *__pyx_v_baseptr;
   __Pyx_RefNannyDeclarations
   int __pyx_t_1;
-  __Pyx_RefNannySetupContext("set_array_base", 0);
+  __Pyx_RefNannySetupContext("set_array_base");
 
-  /* "numpy.pxd":966
+  /* "numpy.pxd":963
  * cdef inline void set_array_base(ndarray arr, object base):
  *      cdef PyObject* baseptr
  *      if base is None:             # <<<<<<<<<<<<<<
@@ -5889,7 +5676,7 @@ static CYTHON_INLINE void __pyx_f_5numpy_set_array_base(PyArrayObject *__pyx_v_a
   __pyx_t_1 = (__pyx_v_base == Py_None);
   if (__pyx_t_1) {
 
-    /* "numpy.pxd":967
+    /* "numpy.pxd":964
  *      cdef PyObject* baseptr
  *      if base is None:
  *          baseptr = NULL             # <<<<<<<<<<<<<<
@@ -5901,7 +5688,7 @@ static CYTHON_INLINE void __pyx_f_5numpy_set_array_base(PyArrayObject *__pyx_v_a
   }
   /*else*/ {
 
-    /* "numpy.pxd":969
+    /* "numpy.pxd":966
  *          baseptr = NULL
  *      else:
  *          Py_INCREF(base) # important to do this before decref below!             # <<<<<<<<<<<<<<
@@ -5910,7 +5697,7 @@ static CYTHON_INLINE void __pyx_f_5numpy_set_array_base(PyArrayObject *__pyx_v_a
  */
     Py_INCREF(__pyx_v_base);
 
-    /* "numpy.pxd":970
+    /* "numpy.pxd":967
  *      else:
  *          Py_INCREF(base) # important to do this before decref below!
  *          baseptr = <PyObject*>base             # <<<<<<<<<<<<<<
@@ -5921,7 +5708,7 @@ static CYTHON_INLINE void __pyx_f_5numpy_set_array_base(PyArrayObject *__pyx_v_a
   }
   __pyx_L3:;
 
-  /* "numpy.pxd":971
+  /* "numpy.pxd":968
  *          Py_INCREF(base) # important to do this before decref below!
  *          baseptr = <PyObject*>base
  *      Py_XDECREF(arr.base)             # <<<<<<<<<<<<<<
@@ -5930,7 +5717,7 @@ static CYTHON_INLINE void __pyx_f_5numpy_set_array_base(PyArrayObject *__pyx_v_a
  */
   Py_XDECREF(__pyx_v_arr->base);
 
-  /* "numpy.pxd":972
+  /* "numpy.pxd":969
  *          baseptr = <PyObject*>base
  *      Py_XDECREF(arr.base)
  *      arr.base = baseptr             # <<<<<<<<<<<<<<
@@ -5942,7 +5729,7 @@ static CYTHON_INLINE void __pyx_f_5numpy_set_array_base(PyArrayObject *__pyx_v_a
   __Pyx_RefNannyFinishContext();
 }
 
-/* "numpy.pxd":974
+/* "numpy.pxd":971
  *      arr.base = baseptr
  * 
  * cdef inline object get_array_base(ndarray arr):             # <<<<<<<<<<<<<<
@@ -5954,9 +5741,9 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_get_array_base(PyArrayObject *__py
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   int __pyx_t_1;
-  __Pyx_RefNannySetupContext("get_array_base", 0);
+  __Pyx_RefNannySetupContext("get_array_base");
 
-  /* "numpy.pxd":975
+  /* "numpy.pxd":972
  * 
  * cdef inline object get_array_base(ndarray arr):
  *     if arr.base is NULL:             # <<<<<<<<<<<<<<
@@ -5966,7 +5753,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_get_array_base(PyArrayObject *__py
   __pyx_t_1 = (__pyx_v_arr->base == NULL);
   if (__pyx_t_1) {
 
-    /* "numpy.pxd":976
+    /* "numpy.pxd":973
  * cdef inline object get_array_base(ndarray arr):
  *     if arr.base is NULL:
  *         return None             # <<<<<<<<<<<<<<
@@ -5981,7 +5768,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_get_array_base(PyArrayObject *__py
   }
   /*else*/ {
 
-    /* "numpy.pxd":978
+    /* "numpy.pxd":975
  *         return None
  *     else:
  *         return <object>arr.base             # <<<<<<<<<<<<<<
@@ -6023,11 +5810,10 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = {
   {&__pyx_kp_u_11, __pyx_k_11, sizeof(__pyx_k_11), 0, 1, 0, 0},
   {&__pyx_kp_u_12, __pyx_k_12, sizeof(__pyx_k_12), 0, 1, 0, 0},
   {&__pyx_kp_u_15, __pyx_k_15, sizeof(__pyx_k_15), 0, 1, 0, 0},
+  {&__pyx_n_s_17, __pyx_k_17, sizeof(__pyx_k_17), 0, 0, 1, 1},
+  {&__pyx_n_s_18, __pyx_k_18, sizeof(__pyx_k_18), 0, 0, 1, 1},
   {&__pyx_n_s_19, __pyx_k_19, sizeof(__pyx_k_19), 0, 0, 1, 1},
-  {&__pyx_kp_s_20, __pyx_k_20, sizeof(__pyx_k_20), 0, 0, 1, 0},
-  {&__pyx_n_s_21, __pyx_k_21, sizeof(__pyx_k_21), 0, 0, 1, 1},
-  {&__pyx_n_s_24, __pyx_k_24, sizeof(__pyx_k_24), 0, 0, 1, 1},
-  {&__pyx_n_s_27, __pyx_k_27, sizeof(__pyx_k_27), 0, 0, 1, 1},
+  {&__pyx_n_s_20, __pyx_k_20, sizeof(__pyx_k_20), 0, 0, 1, 1},
   {&__pyx_kp_u_5, __pyx_k_5, sizeof(__pyx_k_5), 0, 1, 0, 0},
   {&__pyx_kp_u_7, __pyx_k_7, sizeof(__pyx_k_7), 0, 1, 0, 0},
   {&__pyx_kp_u_9, __pyx_k_9, sizeof(__pyx_k_9), 0, 1, 0, 0},
@@ -6036,50 +5822,20 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = {
   {&__pyx_n_s__ValueError, __pyx_k__ValueError, sizeof(__pyx_k__ValueError), 0, 0, 1, 1},
   {&__pyx_n_s____main__, __pyx_k____main__, sizeof(__pyx_k____main__), 0, 0, 1, 1},
   {&__pyx_n_s____test__, __pyx_k____test__, sizeof(__pyx_k____test__), 0, 0, 1, 1},
-  {&__pyx_n_s__bot, __pyx_k__bot, sizeof(__pyx_k__bot), 0, 0, 1, 1},
-  {&__pyx_n_s__conv, __pyx_k__conv, sizeof(__pyx_k__conv), 0, 0, 1, 1},
   {&__pyx_n_s__dtype, __pyx_k__dtype, sizeof(__pyx_k__dtype), 0, 0, 1, 1},
   {&__pyx_n_s__empty, __pyx_k__empty, sizeof(__pyx_k__empty), 0, 0, 1, 1},
   {&__pyx_n_s__f, __pyx_k__f, sizeof(__pyx_k__f), 0, 0, 1, 1},
-  {&__pyx_n_s__fixed, __pyx_k__fixed, sizeof(__pyx_k__fixed), 0, 0, 1, 1},
   {&__pyx_n_s__float, __pyx_k__float, sizeof(__pyx_k__float), 0, 0, 1, 1},
   {&__pyx_n_s__g, __pyx_k__g, sizeof(__pyx_k__g), 0, 0, 1, 1},
-  {&__pyx_n_s__i, __pyx_k__i, sizeof(__pyx_k__i), 0, 0, 1, 1},
-  {&__pyx_n_s__ii, __pyx_k__ii, sizeof(__pyx_k__ii), 0, 0, 1, 1},
-  {&__pyx_n_s__iii, __pyx_k__iii, sizeof(__pyx_k__iii), 0, 0, 1, 1},
-  {&__pyx_n_s__iimax, __pyx_k__iimax, sizeof(__pyx_k__iimax), 0, 0, 1, 1},
-  {&__pyx_n_s__iimin, __pyx_k__iimin, sizeof(__pyx_k__iimin), 0, 0, 1, 1},
-  {&__pyx_n_s__j, __pyx_k__j, sizeof(__pyx_k__j), 0, 0, 1, 1},
-  {&__pyx_n_s__jj, __pyx_k__jj, sizeof(__pyx_k__jj), 0, 0, 1, 1},
-  {&__pyx_n_s__jjj, __pyx_k__jjj, sizeof(__pyx_k__jjj), 0, 0, 1, 1},
-  {&__pyx_n_s__jjmax, __pyx_k__jjmax, sizeof(__pyx_k__jjmax), 0, 0, 1, 1},
-  {&__pyx_n_s__jjmin, __pyx_k__jjmin, sizeof(__pyx_k__jjmin), 0, 0, 1, 1},
-  {&__pyx_n_s__k, __pyx_k__k, sizeof(__pyx_k__k), 0, 0, 1, 1},
-  {&__pyx_n_s__ker, __pyx_k__ker, sizeof(__pyx_k__ker), 0, 0, 1, 1},
-  {&__pyx_n_s__kk, __pyx_k__kk, sizeof(__pyx_k__kk), 0, 0, 1, 1},
-  {&__pyx_n_s__kkk, __pyx_k__kkk, sizeof(__pyx_k__kkk), 0, 0, 1, 1},
-  {&__pyx_n_s__kkmax, __pyx_k__kkmax, sizeof(__pyx_k__kkmax), 0, 0, 1, 1},
-  {&__pyx_n_s__kkmin, __pyx_k__kkmin, sizeof(__pyx_k__kkmin), 0, 0, 1, 1},
-  {&__pyx_n_s__nkx, __pyx_k__nkx, sizeof(__pyx_k__nkx), 0, 0, 1, 1},
-  {&__pyx_n_s__nky, __pyx_k__nky, sizeof(__pyx_k__nky), 0, 0, 1, 1},
-  {&__pyx_n_s__nkz, __pyx_k__nkz, sizeof(__pyx_k__nkz), 0, 0, 1, 1},
   {&__pyx_n_s__np, __pyx_k__np, sizeof(__pyx_k__np), 0, 0, 1, 1},
   {&__pyx_n_s__numpy, __pyx_k__numpy, sizeof(__pyx_k__numpy), 0, 0, 1, 1},
-  {&__pyx_n_s__nx, __pyx_k__nx, sizeof(__pyx_k__nx), 0, 0, 1, 1},
-  {&__pyx_n_s__ny, __pyx_k__ny, sizeof(__pyx_k__ny), 0, 0, 1, 1},
-  {&__pyx_n_s__nz, __pyx_k__nz, sizeof(__pyx_k__nz), 0, 0, 1, 1},
   {&__pyx_n_s__range, __pyx_k__range, sizeof(__pyx_k__range), 0, 0, 1, 1},
-  {&__pyx_n_s__top, __pyx_k__top, sizeof(__pyx_k__top), 0, 0, 1, 1},
-  {&__pyx_n_s__val, __pyx_k__val, sizeof(__pyx_k__val), 0, 0, 1, 1},
-  {&__pyx_n_s__wkx, __pyx_k__wkx, sizeof(__pyx_k__wkx), 0, 0, 1, 1},
-  {&__pyx_n_s__wky, __pyx_k__wky, sizeof(__pyx_k__wky), 0, 0, 1, 1},
-  {&__pyx_n_s__wkz, __pyx_k__wkz, sizeof(__pyx_k__wkz), 0, 0, 1, 1},
   {0, 0, 0, 0, 0, 0, 0}
 };
 static int __Pyx_InitCachedBuiltins(void) {
   __pyx_builtin_ValueError = __Pyx_GetName(__pyx_b, __pyx_n_s__ValueError); if (!__pyx_builtin_ValueError) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 19; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_builtin_range = __Pyx_GetName(__pyx_b, __pyx_n_s__range); if (!__pyx_builtin_range) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 37; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_builtin_RuntimeError = __Pyx_GetName(__pyx_b, __pyx_n_s__RuntimeError); if (!__pyx_builtin_RuntimeError) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 798; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_builtin_RuntimeError = __Pyx_GetName(__pyx_b, __pyx_n_s__RuntimeError); if (!__pyx_builtin_RuntimeError) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 795; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   return 0;
   __pyx_L1_error:;
   return -1;
@@ -6087,7 +5843,7 @@ static int __Pyx_InitCachedBuiltins(void) {
 
 static int __Pyx_InitCachedConstants(void) {
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__Pyx_InitCachedConstants", 0);
+  __Pyx_RefNannySetupContext("__Pyx_InitCachedConstants");
 
   /* "astropy/nddata/convolution/boundary_wrap.pyx":19
  * 
@@ -6097,7 +5853,7 @@ static int __Pyx_InitCachedConstants(void) {
  *     assert f.dtype == DTYPE and g.dtype == DTYPE
  */
   __pyx_k_tuple_2 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 19; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_2);
+  __Pyx_GOTREF(((PyObject *)__pyx_k_tuple_2));
   __Pyx_INCREF(((PyObject *)__pyx_kp_s_1));
   PyTuple_SET_ITEM(__pyx_k_tuple_2, 0, ((PyObject *)__pyx_kp_s_1));
   __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_1));
@@ -6111,7 +5867,7 @@ static int __Pyx_InitCachedConstants(void) {
  *     assert f.dtype == DTYPE and g.dtype == DTYPE
  */
   __pyx_k_tuple_3 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 87; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_3);
+  __Pyx_GOTREF(((PyObject *)__pyx_k_tuple_3));
   __Pyx_INCREF(((PyObject *)__pyx_kp_s_1));
   PyTuple_SET_ITEM(__pyx_k_tuple_3, 0, ((PyObject *)__pyx_kp_s_1));
   __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_1));
@@ -6125,347 +5881,95 @@ static int __Pyx_InitCachedConstants(void) {
  *     assert f.dtype == DTYPE and g.dtype == DTYPE
  */
   __pyx_k_tuple_4 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 170; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_4);
+  __Pyx_GOTREF(((PyObject *)__pyx_k_tuple_4));
   __Pyx_INCREF(((PyObject *)__pyx_kp_s_1));
   PyTuple_SET_ITEM(__pyx_k_tuple_4, 0, ((PyObject *)__pyx_kp_s_1));
   __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_1));
   __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_4));
 
-  /* "numpy.pxd":214
+  /* "numpy.pxd":211
  *             if ((flags & pybuf.PyBUF_C_CONTIGUOUS == pybuf.PyBUF_C_CONTIGUOUS)
  *                 and not PyArray_CHKFLAGS(self, NPY_C_CONTIGUOUS)):
  *                 raise ValueError(u"ndarray is not C contiguous")             # <<<<<<<<<<<<<<
  * 
  *             if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS)
  */
-  __pyx_k_tuple_6 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_6)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 214; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_6);
+  __pyx_k_tuple_6 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_6)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 211; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_k_tuple_6));
   __Pyx_INCREF(((PyObject *)__pyx_kp_u_5));
   PyTuple_SET_ITEM(__pyx_k_tuple_6, 0, ((PyObject *)__pyx_kp_u_5));
   __Pyx_GIVEREF(((PyObject *)__pyx_kp_u_5));
   __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_6));
 
-  /* "numpy.pxd":218
+  /* "numpy.pxd":215
  *             if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS)
  *                 and not PyArray_CHKFLAGS(self, NPY_F_CONTIGUOUS)):
  *                 raise ValueError(u"ndarray is not Fortran contiguous")             # <<<<<<<<<<<<<<
  * 
  *             info.buf = PyArray_DATA(self)
  */
-  __pyx_k_tuple_8 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_8)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 218; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_8);
+  __pyx_k_tuple_8 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_8)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 215; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_k_tuple_8));
   __Pyx_INCREF(((PyObject *)__pyx_kp_u_7));
   PyTuple_SET_ITEM(__pyx_k_tuple_8, 0, ((PyObject *)__pyx_kp_u_7));
   __Pyx_GIVEREF(((PyObject *)__pyx_kp_u_7));
   __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_8));
 
-  /* "numpy.pxd":256
+  /* "numpy.pxd":253
  *                 if ((descr.byteorder == '>' and little_endian) or
  *                     (descr.byteorder == '<' and not little_endian)):
  *                     raise ValueError(u"Non-native byte order not supported")             # <<<<<<<<<<<<<<
  *                 if   t == NPY_BYTE:        f = "b"
  *                 elif t == NPY_UBYTE:       f = "B"
  */
-  __pyx_k_tuple_10 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_10)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 256; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_10);
+  __pyx_k_tuple_10 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_10)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 253; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_k_tuple_10));
   __Pyx_INCREF(((PyObject *)__pyx_kp_u_9));
   PyTuple_SET_ITEM(__pyx_k_tuple_10, 0, ((PyObject *)__pyx_kp_u_9));
   __Pyx_GIVEREF(((PyObject *)__pyx_kp_u_9));
   __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_10));
 
-  /* "numpy.pxd":798
+  /* "numpy.pxd":795
  * 
  *         if (end - f) - (new_offset - offset[0]) < 15:
  *             raise RuntimeError(u"Format string allocated too short, see comment in numpy.pxd")             # <<<<<<<<<<<<<<
  * 
  *         if ((child.byteorder == '>' and little_endian) or
  */
-  __pyx_k_tuple_13 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_13)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 798; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_13);
+  __pyx_k_tuple_13 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_13)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 795; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_k_tuple_13));
   __Pyx_INCREF(((PyObject *)__pyx_kp_u_12));
   PyTuple_SET_ITEM(__pyx_k_tuple_13, 0, ((PyObject *)__pyx_kp_u_12));
   __Pyx_GIVEREF(((PyObject *)__pyx_kp_u_12));
   __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_13));
 
-  /* "numpy.pxd":802
+  /* "numpy.pxd":799
  *         if ((child.byteorder == '>' and little_endian) or
  *             (child.byteorder == '<' and not little_endian)):
  *             raise ValueError(u"Non-native byte order not supported")             # <<<<<<<<<<<<<<
  *             # One could encode it in the format string and have Cython
  *             # complain instead, BUT: < and > in format strings also imply
  */
-  __pyx_k_tuple_14 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_14)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 802; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_14);
+  __pyx_k_tuple_14 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_14)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 799; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_k_tuple_14));
   __Pyx_INCREF(((PyObject *)__pyx_kp_u_9));
   PyTuple_SET_ITEM(__pyx_k_tuple_14, 0, ((PyObject *)__pyx_kp_u_9));
   __Pyx_GIVEREF(((PyObject *)__pyx_kp_u_9));
   __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_14));
 
-  /* "numpy.pxd":822
+  /* "numpy.pxd":819
  *             t = child.type_num
  *             if end - f < 5:
  *                 raise RuntimeError(u"Format string allocated too short.")             # <<<<<<<<<<<<<<
  * 
  *             # Until ticket #99 is fixed, use integers to avoid warnings
  */
-  __pyx_k_tuple_16 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_16)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 822; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_16);
+  __pyx_k_tuple_16 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_16)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 819; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_k_tuple_16));
   __Pyx_INCREF(((PyObject *)__pyx_kp_u_15));
   PyTuple_SET_ITEM(__pyx_k_tuple_16, 0, ((PyObject *)__pyx_kp_u_15));
   __Pyx_GIVEREF(((PyObject *)__pyx_kp_u_15));
   __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_16));
-
-  /* "astropy/nddata/convolution/boundary_wrap.pyx":15
- * 
- * @cython.boundscheck(False)  # turn off bounds-checking for entire function
- * def convolve1d_boundary_wrap(np.ndarray[DTYPE_t, ndim=1] f,             # <<<<<<<<<<<<<<
- *                              np.ndarray[DTYPE_t, ndim=1] g):
- * 
- */
-  __pyx_k_tuple_17 = PyTuple_New(16); if (unlikely(!__pyx_k_tuple_17)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_17);
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__f));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 0, ((PyObject *)__pyx_n_s__f));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__f));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__g));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 1, ((PyObject *)__pyx_n_s__g));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__g));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__nx));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 2, ((PyObject *)__pyx_n_s__nx));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__nx));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__nkx));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 3, ((PyObject *)__pyx_n_s__nkx));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__nkx));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__wkx));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 4, ((PyObject *)__pyx_n_s__wkx));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__wkx));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__fixed));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 5, ((PyObject *)__pyx_n_s__fixed));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__fixed));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__conv));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 6, ((PyObject *)__pyx_n_s__conv));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__conv));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__i));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 7, ((PyObject *)__pyx_n_s__i));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__i));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__iii));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 8, ((PyObject *)__pyx_n_s__iii));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__iii));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__ii));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 9, ((PyObject *)__pyx_n_s__ii));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__ii));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__iimin));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 10, ((PyObject *)__pyx_n_s__iimin));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__iimin));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__iimax));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 11, ((PyObject *)__pyx_n_s__iimax));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__iimax));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__top));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 12, ((PyObject *)__pyx_n_s__top));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__top));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__bot));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 13, ((PyObject *)__pyx_n_s__bot));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__bot));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__ker));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 14, ((PyObject *)__pyx_n_s__ker));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__ker));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__val));
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 15, ((PyObject *)__pyx_n_s__val));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__val));
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_17));
-  __pyx_k_codeobj_18 = (PyObject*)__Pyx_PyCode_New(2, 0, 16, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_k_tuple_17, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_20, __pyx_n_s_19, 15, __pyx_empty_bytes); if (unlikely(!__pyx_k_codeobj_18)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-
-  /* "astropy/nddata/convolution/boundary_wrap.pyx":83
- * 
- * @cython.boundscheck(False)  # turn off bounds-checking for entire function
- * def convolve2d_boundary_wrap(np.ndarray[DTYPE_t, ndim=2] f,             # <<<<<<<<<<<<<<
- *                              np.ndarray[DTYPE_t, ndim=2] g):
- * 
- */
-  __pyx_k_tuple_22 = PyTuple_New(24); if (unlikely(!__pyx_k_tuple_22)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 83; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_22);
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__f));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 0, ((PyObject *)__pyx_n_s__f));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__f));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__g));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 1, ((PyObject *)__pyx_n_s__g));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__g));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__nx));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 2, ((PyObject *)__pyx_n_s__nx));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__nx));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__ny));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 3, ((PyObject *)__pyx_n_s__ny));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__ny));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__nkx));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 4, ((PyObject *)__pyx_n_s__nkx));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__nkx));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__nky));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 5, ((PyObject *)__pyx_n_s__nky));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__nky));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__wkx));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 6, ((PyObject *)__pyx_n_s__wkx));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__wkx));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__wky));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 7, ((PyObject *)__pyx_n_s__wky));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__wky));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__fixed));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 8, ((PyObject *)__pyx_n_s__fixed));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__fixed));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__conv));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 9, ((PyObject *)__pyx_n_s__conv));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__conv));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__i));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 10, ((PyObject *)__pyx_n_s__i));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__i));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__j));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 11, ((PyObject *)__pyx_n_s__j));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__j));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__iii));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 12, ((PyObject *)__pyx_n_s__iii));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__iii));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__jjj));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 13, ((PyObject *)__pyx_n_s__jjj));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__jjj));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__ii));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 14, ((PyObject *)__pyx_n_s__ii));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__ii));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__jj));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 15, ((PyObject *)__pyx_n_s__jj));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__jj));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__iimin));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 16, ((PyObject *)__pyx_n_s__iimin));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__iimin));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__iimax));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 17, ((PyObject *)__pyx_n_s__iimax));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__iimax));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__jjmin));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 18, ((PyObject *)__pyx_n_s__jjmin));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__jjmin));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__jjmax));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 19, ((PyObject *)__pyx_n_s__jjmax));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__jjmax));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__top));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 20, ((PyObject *)__pyx_n_s__top));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__top));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__bot));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 21, ((PyObject *)__pyx_n_s__bot));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__bot));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__ker));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 22, ((PyObject *)__pyx_n_s__ker));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__ker));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__val));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 23, ((PyObject *)__pyx_n_s__val));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__val));
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_22));
-  __pyx_k_codeobj_23 = (PyObject*)__Pyx_PyCode_New(2, 0, 24, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_k_tuple_22, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_20, __pyx_n_s_24, 83, __pyx_empty_bytes); if (unlikely(!__pyx_k_codeobj_23)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 83; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-
-  /* "astropy/nddata/convolution/boundary_wrap.pyx":166
- * 
- * @cython.boundscheck(False)  # turn off bounds-checking for entire function
- * def convolve3d_boundary_wrap(np.ndarray[DTYPE_t, ndim=3] f,             # <<<<<<<<<<<<<<
- *                              np.ndarray[DTYPE_t, ndim=3] g):
- * 
- */
-  __pyx_k_tuple_25 = PyTuple_New(32); if (unlikely(!__pyx_k_tuple_25)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 166; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_25);
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__f));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 0, ((PyObject *)__pyx_n_s__f));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__f));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__g));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 1, ((PyObject *)__pyx_n_s__g));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__g));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__nx));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 2, ((PyObject *)__pyx_n_s__nx));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__nx));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__ny));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 3, ((PyObject *)__pyx_n_s__ny));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__ny));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__nz));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 4, ((PyObject *)__pyx_n_s__nz));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__nz));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__nkx));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 5, ((PyObject *)__pyx_n_s__nkx));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__nkx));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__nky));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 6, ((PyObject *)__pyx_n_s__nky));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__nky));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__nkz));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 7, ((PyObject *)__pyx_n_s__nkz));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__nkz));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__wkx));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 8, ((PyObject *)__pyx_n_s__wkx));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__wkx));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__wky));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 9, ((PyObject *)__pyx_n_s__wky));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__wky));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__wkz));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 10, ((PyObject *)__pyx_n_s__wkz));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__wkz));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__fixed));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 11, ((PyObject *)__pyx_n_s__fixed));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__fixed));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__conv));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 12, ((PyObject *)__pyx_n_s__conv));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__conv));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__i));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 13, ((PyObject *)__pyx_n_s__i));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__i));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__j));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 14, ((PyObject *)__pyx_n_s__j));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__j));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__k));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 15, ((PyObject *)__pyx_n_s__k));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__k));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__iii));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 16, ((PyObject *)__pyx_n_s__iii));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__iii));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__jjj));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 17, ((PyObject *)__pyx_n_s__jjj));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__jjj));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__kkk));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 18, ((PyObject *)__pyx_n_s__kkk));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__kkk));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__ii));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 19, ((PyObject *)__pyx_n_s__ii));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__ii));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__jj));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 20, ((PyObject *)__pyx_n_s__jj));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__jj));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__kk));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 21, ((PyObject *)__pyx_n_s__kk));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__kk));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__iimin));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 22, ((PyObject *)__pyx_n_s__iimin));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__iimin));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__iimax));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 23, ((PyObject *)__pyx_n_s__iimax));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__iimax));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__jjmin));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 24, ((PyObject *)__pyx_n_s__jjmin));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__jjmin));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__jjmax));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 25, ((PyObject *)__pyx_n_s__jjmax));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__jjmax));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__kkmin));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 26, ((PyObject *)__pyx_n_s__kkmin));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__kkmin));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__kkmax));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 27, ((PyObject *)__pyx_n_s__kkmax));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__kkmax));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__top));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 28, ((PyObject *)__pyx_n_s__top));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__top));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__bot));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 29, ((PyObject *)__pyx_n_s__bot));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__bot));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__ker));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 30, ((PyObject *)__pyx_n_s__ker));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__ker));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__val));
-  PyTuple_SET_ITEM(__pyx_k_tuple_25, 31, ((PyObject *)__pyx_n_s__val));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__val));
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_25));
-  __pyx_k_codeobj_26 = (PyObject*)__Pyx_PyCode_New(2, 0, 32, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_k_tuple_25, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_20, __pyx_n_s_27, 166, __pyx_empty_bytes); if (unlikely(!__pyx_k_codeobj_26)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 166; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_RefNannyFinishContext();
   return 0;
   __pyx_L1_error:;
@@ -6501,18 +6005,12 @@ PyMODINIT_FUNC PyInit_boundary_wrap(void)
           Py_FatalError("failed to import 'refnanny' module");
   }
   #endif
-  __Pyx_RefNannySetupContext("PyMODINIT_FUNC PyInit_boundary_wrap(void)", 0);
+  __Pyx_RefNannySetupContext("PyMODINIT_FUNC PyInit_boundary_wrap(void)");
   if ( __Pyx_check_binary_version() < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_empty_tuple = PyTuple_New(0); if (unlikely(!__pyx_empty_tuple)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_empty_bytes = PyBytes_FromStringAndSize("", 0); if (unlikely(!__pyx_empty_bytes)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  #ifdef __Pyx_CyFunction_USED
-  if (__Pyx_CyFunction_init() < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  #endif
-  #ifdef __Pyx_FusedFunction_USED
-  if (__pyx_FusedFunction_init() < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  #endif
-  #ifdef __Pyx_Generator_USED
-  if (__pyx_Generator_init() < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  #ifdef __pyx_binding_PyCFunctionType_USED
+  if (__pyx_binding_PyCFunctionType_init() < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   #endif
   /*--- Library function declarations ---*/
   /*--- Threads initialization code ---*/
@@ -6548,11 +6046,11 @@ PyMODINIT_FUNC PyInit_boundary_wrap(void)
   /*--- Function export code ---*/
   /*--- Type init code ---*/
   /*--- Type import code ---*/
-  __pyx_ptype_5numpy_dtype = __Pyx_ImportType("numpy", "dtype", sizeof(PyArray_Descr), 0); if (unlikely(!__pyx_ptype_5numpy_dtype)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 154; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_ptype_5numpy_flatiter = __Pyx_ImportType("numpy", "flatiter", sizeof(PyArrayIterObject), 0); if (unlikely(!__pyx_ptype_5numpy_flatiter)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 164; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_ptype_5numpy_broadcast = __Pyx_ImportType("numpy", "broadcast", sizeof(PyArrayMultiIterObject), 0); if (unlikely(!__pyx_ptype_5numpy_broadcast)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 168; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_ptype_5numpy_ndarray = __Pyx_ImportType("numpy", "ndarray", sizeof(PyArrayObject), 0); if (unlikely(!__pyx_ptype_5numpy_ndarray)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 177; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_ptype_5numpy_ufunc = __Pyx_ImportType("numpy", "ufunc", sizeof(PyUFuncObject), 0); if (unlikely(!__pyx_ptype_5numpy_ufunc)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 860; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_5numpy_dtype = __Pyx_ImportType("numpy", "dtype", sizeof(PyArray_Descr), 0); if (unlikely(!__pyx_ptype_5numpy_dtype)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 151; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_5numpy_flatiter = __Pyx_ImportType("numpy", "flatiter", sizeof(PyArrayIterObject), 0); if (unlikely(!__pyx_ptype_5numpy_flatiter)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 161; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_5numpy_broadcast = __Pyx_ImportType("numpy", "broadcast", sizeof(PyArrayMultiIterObject), 0); if (unlikely(!__pyx_ptype_5numpy_broadcast)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 165; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_5numpy_ndarray = __Pyx_ImportType("numpy", "ndarray", sizeof(PyArrayObject), 0); if (unlikely(!__pyx_ptype_5numpy_ndarray)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 174; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_5numpy_ufunc = __Pyx_ImportType("numpy", "ufunc", sizeof(PyUFuncObject), 0); if (unlikely(!__pyx_ptype_5numpy_ufunc)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 857; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   /*--- Variable import code ---*/
   /*--- Function import code ---*/
   /*--- Execution code ---*/
@@ -6590,9 +6088,9 @@ PyMODINIT_FUNC PyInit_boundary_wrap(void)
  *                              np.ndarray[DTYPE_t, ndim=1] g):
  * 
  */
-  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_7astropy_6nddata_11convolution_13boundary_wrap_1convolve1d_boundary_wrap, NULL, __pyx_n_s_21); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_7astropy_6nddata_11convolution_13boundary_wrap_convolve1d_boundary_wrap, NULL, __pyx_n_s_17); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
-  if (PyObject_SetAttr(__pyx_m, __pyx_n_s_19, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s_18, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
   /* "astropy/nddata/convolution/boundary_wrap.pyx":83
@@ -6602,9 +6100,9 @@ PyMODINIT_FUNC PyInit_boundary_wrap(void)
  *                              np.ndarray[DTYPE_t, ndim=2] g):
  * 
  */
-  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_7astropy_6nddata_11convolution_13boundary_wrap_3convolve2d_boundary_wrap, NULL, __pyx_n_s_21); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 83; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_7astropy_6nddata_11convolution_13boundary_wrap_1convolve2d_boundary_wrap, NULL, __pyx_n_s_17); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 83; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
-  if (PyObject_SetAttr(__pyx_m, __pyx_n_s_24, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 83; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s_19, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 83; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
   /* "astropy/nddata/convolution/boundary_wrap.pyx":166
@@ -6614,9 +6112,9 @@ PyMODINIT_FUNC PyInit_boundary_wrap(void)
  *                              np.ndarray[DTYPE_t, ndim=3] g):
  * 
  */
-  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_7astropy_6nddata_11convolution_13boundary_wrap_5convolve3d_boundary_wrap, NULL, __pyx_n_s_21); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 166; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_7astropy_6nddata_11convolution_13boundary_wrap_2convolve3d_boundary_wrap, NULL, __pyx_n_s_17); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 166; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
-  if (PyObject_SetAttr(__pyx_m, __pyx_n_s_27, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 166; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s_20, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 166; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
   /* "astropy/nddata/convolution/boundary_wrap.pyx":1
@@ -6629,7 +6127,7 @@ PyMODINIT_FUNC PyInit_boundary_wrap(void)
   if (PyObject_SetAttr(__pyx_m, __pyx_n_s____test__, ((PyObject *)__pyx_t_2)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
 
-  /* "numpy.pxd":974
+  /* "numpy.pxd":971
  *      arr.base = baseptr
  * 
  * cdef inline object get_array_base(ndarray arr):             # <<<<<<<<<<<<<<
@@ -6656,6 +6154,7 @@ PyMODINIT_FUNC PyInit_boundary_wrap(void)
 }
 
 /* Runtime support code */
+
 #if CYTHON_REFNANNY
 static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname) {
     PyObject *m = NULL, *p = NULL;
@@ -6696,6 +6195,7 @@ static void __Pyx_RaiseArgtupleInvalid(
 {
     Py_ssize_t num_expected;
     const char *more_or_less;
+
     if (num_found < num_min) {
         num_expected = num_min;
         more_or_less = "at least";
@@ -6737,6 +6237,7 @@ static int __Pyx_ParseOptionalKeywords(
     Py_ssize_t pos = 0;
     PyObject*** name;
     PyObject*** first_kw_arg = argnames + num_pos_args;
+
     while (PyDict_Next(kwds, &pos, &key, &value)) {
         name = first_kw_arg;
         while (*name && (**name != key)) name++;
@@ -6746,7 +6247,7 @@ static int __Pyx_ParseOptionalKeywords(
             #if PY_MAJOR_VERSION < 3
             if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key))) {
             #else
-            if (unlikely(!PyUnicode_Check(key))) {
+            if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key))) {
             #endif
                 goto invalid_keyword_type;
             } else {
@@ -6762,6 +6263,7 @@ static int __Pyx_ParseOptionalKeywords(
                 if (*name) {
                     values[name-argnames] = value;
                 } else {
+                    /* unexpected keyword found */
                     for (name=argnames; name != first_kw_arg; name++) {
                         if (**name == key) goto arg_passed_twice;
                         #if PY_MAJOR_VERSION >= 3
@@ -6826,6 +6328,18 @@ static CYTHON_INLINE int __Pyx_IsLittleEndian(void) {
   unsigned int n = 1;
   return *(unsigned char*)(&n) != 0;
 }
+
+typedef struct {
+  __Pyx_StructField root;
+  __Pyx_BufFmt_StackElem* head;
+  size_t fmt_offset;
+  size_t new_count, enc_count;
+  int is_complex;
+  char enc_type;
+  char new_packmode;
+  char enc_packmode;
+} __Pyx_BufFmt_Context;
+
 static void __Pyx_BufFmt_Init(__Pyx_BufFmt_Context* ctx,
                               __Pyx_BufFmt_StackElem* stack,
                               __Pyx_TypeInfo* type) {
@@ -6844,8 +6358,6 @@ static void __Pyx_BufFmt_Init(__Pyx_BufFmt_Context* ctx,
   ctx->enc_count = 0;
   ctx->enc_type = 0;
   ctx->is_complex = 0;
-  ctx->is_valid_array = 0;
-  ctx->struct_alignment = 0;
   while (type->typegroup == 'S') {
     ++ctx->head;
     ctx->head->field = type->fields;
@@ -6853,6 +6365,7 @@ static void __Pyx_BufFmt_Init(__Pyx_BufFmt_Context* ctx,
     type = type->fields->type;
   }
 }
+
 static int __Pyx_BufFmt_ParseNumber(const char** ts) {
     int count;
     const char* t = *ts;
@@ -6868,17 +6381,12 @@ static int __Pyx_BufFmt_ParseNumber(const char** ts) {
     *ts = t;
     return count;
 }
-static int __Pyx_BufFmt_ExpectNumber(const char **ts) {
-    int number = __Pyx_BufFmt_ParseNumber(ts);
-    if (number == -1) /* First char was not a digit */
-        PyErr_Format(PyExc_ValueError,\
-                     "Does not understand character buffer dtype format string ('%c')", **ts);
-    return number;
-}
+
 static void __Pyx_BufFmt_RaiseUnexpectedChar(char ch) {
   PyErr_Format(PyExc_ValueError,
                "Unexpected format string character: '%c'", ch);
 }
+
 static const char* __Pyx_BufFmt_DescribeTypeChar(char ch, int is_complex) {
   switch (ch) {
     case 'b': return "'char'";
@@ -6897,14 +6405,14 @@ static const char* __Pyx_BufFmt_DescribeTypeChar(char ch, int is_complex) {
     case 'T': return "a struct";
     case 'O': return "Python object";
     case 'P': return "a pointer";
-    case 's': case 'p': return "a string";
     case 0: return "end";
     default: return "unparseable format string";
   }
 }
+
 static size_t __Pyx_BufFmt_TypeCharToStandardSize(char ch, int is_complex) {
   switch (ch) {
-    case '?': case 'c': case 'b': case 'B': case 's': case 'p': return 1;
+    case '?': case 'c': case 'b': case 'B': return 1;
     case 'h': case 'H': return 2;
     case 'i': case 'I': case 'l': case 'L': return 4;
     case 'q': case 'Q': return 8;
@@ -6920,9 +6428,10 @@ static size_t __Pyx_BufFmt_TypeCharToStandardSize(char ch, int is_complex) {
       return 0;
     }
 }
+
 static size_t __Pyx_BufFmt_TypeCharToNativeSize(char ch, int is_complex) {
   switch (ch) {
-    case 'c': case 'b': case 'B': case 's': case 'p': return 1;
+    case 'c': case 'b': case 'B': return 1;
     case 'h': case 'H': return sizeof(short);
     case 'i': case 'I': return sizeof(int);
     case 'l': case 'L': return sizeof(long);
@@ -6939,6 +6448,7 @@ static size_t __Pyx_BufFmt_TypeCharToNativeSize(char ch, int is_complex) {
     }
   }
 }
+
 typedef struct { char c; short x; } __Pyx_st_short;
 typedef struct { char c; int x; } __Pyx_st_int;
 typedef struct { char c; long x; } __Pyx_st_long;
@@ -6949,9 +6459,10 @@ typedef struct { char c; void *x; } __Pyx_st_void_p;
 #ifdef HAVE_LONG_LONG
 typedef struct { char c; PY_LONG_LONG x; } __Pyx_st_longlong;
 #endif
+
 static size_t __Pyx_BufFmt_TypeCharToAlignment(char ch, int is_complex) {
   switch (ch) {
-    case '?': case 'c': case 'b': case 'B': case 's': case 'p': return 1;
+    case '?': case 'c': case 'b': case 'B': return 1;
     case 'h': case 'H': return sizeof(__Pyx_st_short) - sizeof(short);
     case 'i': case 'I': return sizeof(__Pyx_st_int) - sizeof(int);
     case 'l': case 'L': return sizeof(__Pyx_st_long) - sizeof(long);
@@ -6967,57 +6478,21 @@ static size_t __Pyx_BufFmt_TypeCharToAlignment(char ch, int is_complex) {
       return 0;
     }
 }
-/* These are for computing the padding at the end of the struct to align
-   on the first member of the struct. This will probably the same as above,
-   but we don't have any guarantees.
- */
-typedef struct { short x; char c; } __Pyx_pad_short;
-typedef struct { int x; char c; } __Pyx_pad_int;
-typedef struct { long x; char c; } __Pyx_pad_long;
-typedef struct { float x; char c; } __Pyx_pad_float;
-typedef struct { double x; char c; } __Pyx_pad_double;
-typedef struct { long double x; char c; } __Pyx_pad_longdouble;
-typedef struct { void *x; char c; } __Pyx_pad_void_p;
-#ifdef HAVE_LONG_LONG
-typedef struct { PY_LONG_LONG x; char c; } __Pyx_pad_longlong;
-#endif
-static size_t __Pyx_BufFmt_TypeCharToPadding(char ch, int is_complex) {
-  switch (ch) {
-    case '?': case 'c': case 'b': case 'B': case 's': case 'p': return 1;
-    case 'h': case 'H': return sizeof(__Pyx_pad_short) - sizeof(short);
-    case 'i': case 'I': return sizeof(__Pyx_pad_int) - sizeof(int);
-    case 'l': case 'L': return sizeof(__Pyx_pad_long) - sizeof(long);
-#ifdef HAVE_LONG_LONG
-    case 'q': case 'Q': return sizeof(__Pyx_pad_longlong) - sizeof(PY_LONG_LONG);
-#endif
-    case 'f': return sizeof(__Pyx_pad_float) - sizeof(float);
-    case 'd': return sizeof(__Pyx_pad_double) - sizeof(double);
-    case 'g': return sizeof(__Pyx_pad_longdouble) - sizeof(long double);
-    case 'P': case 'O': return sizeof(__Pyx_pad_void_p) - sizeof(void*);
-    default:
-      __Pyx_BufFmt_RaiseUnexpectedChar(ch);
-      return 0;
-    }
-}
+
 static char __Pyx_BufFmt_TypeCharToGroup(char ch, int is_complex) {
   switch (ch) {
-    case 'c': case 'b': case 'h': case 'i':
-    case 'l': case 'q': case 's': case 'p':
-        return 'I';
-    case 'B': case 'H': case 'I': case 'L': case 'Q':
-        return 'U';
-    case 'f': case 'd': case 'g':
-        return (is_complex ? 'C' : 'R');
-    case 'O':
-        return 'O';
-    case 'P':
-        return 'P';
+    case 'c': case 'b': case 'h': case 'i': case 'l': case 'q': return 'I';
+    case 'B': case 'H': case 'I': case 'L': case 'Q': return 'U';
+    case 'f': case 'd': case 'g': return (is_complex ? 'C' : 'R');
+    case 'O': return 'O';
+    case 'P': return 'P';
     default: {
       __Pyx_BufFmt_RaiseUnexpectedChar(ch);
       return 0;
     }
   }
 }
+
 static void __Pyx_BufFmt_RaiseExpected(__Pyx_BufFmt_Context* ctx) {
   if (ctx->head == NULL || ctx->head->field == &ctx->root) {
     const char* expected;
@@ -7042,37 +6517,16 @@ static void __Pyx_BufFmt_RaiseExpected(__Pyx_BufFmt_Context* ctx) {
                  parent->type->name, field->name);
   }
 }
+
 static int __Pyx_BufFmt_ProcessTypeChunk(__Pyx_BufFmt_Context* ctx) {
   char group;
-  size_t size, offset, arraysize = 1;
+  size_t size, offset;
   if (ctx->enc_type == 0) return 0;
-  if (ctx->head->field->type->arraysize[0]) {
-    int i, ndim = 0;
-    if (ctx->enc_type == 's' || ctx->enc_type == 'p') {
-        ctx->is_valid_array = ctx->head->field->type->ndim == 1;
-        ndim = 1;
-        if (ctx->enc_count != ctx->head->field->type->arraysize[0]) {
-            PyErr_Format(PyExc_ValueError,
-                         "Expected a dimension of size %zu, got %zu",
-                         ctx->head->field->type->arraysize[0], ctx->enc_count);
-            return -1;
-        }
-    }
-    if (!ctx->is_valid_array) {
-      PyErr_Format(PyExc_ValueError, "Expected %d dimensions, got %d",
-                   ctx->head->field->type->ndim, ndim);
-      return -1;
-    }
-    for (i = 0; i < ctx->head->field->type->ndim; i++) {
-      arraysize *= ctx->head->field->type->arraysize[i];
-    }
-    ctx->is_valid_array = 0;
-    ctx->enc_count = 1;
-  }
   group = __Pyx_BufFmt_TypeCharToGroup(ctx->enc_type, ctx->is_complex);
   do {
     __Pyx_StructField* field = ctx->head->field;
     __Pyx_TypeInfo* type = field->type;
+
     if (ctx->enc_packmode == '@' || ctx->enc_packmode == '^') {
       size = __Pyx_BufFmt_TypeCharToNativeSize(ctx->enc_type, ctx->is_complex);
     } else {
@@ -7084,21 +6538,22 @@ static int __Pyx_BufFmt_ProcessTypeChunk(__Pyx_BufFmt_Context* ctx) {
       if (align_at == 0) return -1;
       align_mod_offset = ctx->fmt_offset % align_at;
       if (align_mod_offset > 0) ctx->fmt_offset += align_at - align_mod_offset;
-      if (ctx->struct_alignment == 0)
-          ctx->struct_alignment = __Pyx_BufFmt_TypeCharToPadding(ctx->enc_type,
-                                                                 ctx->is_complex);
     }
+
     if (type->size != size || type->typegroup != group) {
       if (type->typegroup == 'C' && type->fields != NULL) {
+        /* special case -- treat as struct rather than complex number */
         size_t parent_offset = ctx->head->parent_offset + field->offset;
         ++ctx->head;
         ctx->head->field = type->fields;
         ctx->head->parent_offset = parent_offset;
         continue;
       }
+
       __Pyx_BufFmt_RaiseExpected(ctx);
       return -1;
     }
+
     offset = ctx->head->parent_offset + field->offset;
     if (ctx->fmt_offset != offset) {
       PyErr_Format(PyExc_ValueError,
@@ -7106,10 +6561,12 @@ static int __Pyx_BufFmt_ProcessTypeChunk(__Pyx_BufFmt_Context* ctx) {
                    (Py_ssize_t)ctx->fmt_offset, (Py_ssize_t)offset);
       return -1;
     }
+
     ctx->fmt_offset += size;
-    if (arraysize)
-      ctx->fmt_offset += (arraysize - 1) * size;
+
     --ctx->enc_count; /* Consume from buffer string */
+
+    /* Done checking, move to next field, pushing or popping struct stack if needed */
     while (1) {
       if (field == &ctx->root) {
         ctx->head = NULL;
@@ -7141,48 +6598,7 @@ static int __Pyx_BufFmt_ProcessTypeChunk(__Pyx_BufFmt_Context* ctx) {
   ctx->is_complex = 0;
   return 0;
 }
-static CYTHON_INLINE PyObject *
-__pyx_buffmt_parse_array(__Pyx_BufFmt_Context* ctx, const char** tsp)
-{
-    const char *ts = *tsp;
-    int i = 0, number;
-    int ndim = ctx->head->field->type->ndim;
-;
-    ++ts;
-    if (ctx->new_count != 1) {
-        PyErr_SetString(PyExc_ValueError,
-                        "Cannot handle repeated arrays in format string");
-        return NULL;
-    }
-    if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL;
-    while (*ts && *ts != ')') {
-        if (isspace(*ts))
-            continue;
-        number = __Pyx_BufFmt_ExpectNumber(&ts);
-        if (number == -1) return NULL;
-        if (i < ndim && (size_t) number != ctx->head->field->type->arraysize[i])
-            return PyErr_Format(PyExc_ValueError,
-                        "Expected a dimension of size %zu, got %d",
-                        ctx->head->field->type->arraysize[i], number);
-        if (*ts != ',' && *ts != ')')
-            return PyErr_Format(PyExc_ValueError,
-                                "Expected a comma in format string, got '%c'", *ts);
-        if (*ts == ',') ts++;
-        i++;
-    }
-    if (i != ndim)
-        return PyErr_Format(PyExc_ValueError, "Expected %d dimension(s), got %d",
-                            ctx->head->field->type->ndim, i);
-    if (!*ts) {
-        PyErr_SetString(PyExc_ValueError,
-                        "Unexpected end of format string, expected ')'");
-        return NULL;
-    }
-    ctx->is_valid_array = 1;
-    ctx->new_count = 1;
-    *tsp = ++ts;
-    return Py_None;
-}
+
 static const char* __Pyx_BufFmt_CheckString(__Pyx_BufFmt_Context* ctx, const char* ts) {
   int got_Z = 0;
   while (1) {
@@ -7197,7 +6613,7 @@ static const char* __Pyx_BufFmt_CheckString(__Pyx_BufFmt_Context* ctx, const cha
           __Pyx_BufFmt_RaiseExpected(ctx);
           return NULL;
         }
-                return ts;
+        return ts;
       case ' ':
       case 10:
       case 13:
@@ -7229,17 +6645,12 @@ static const char* __Pyx_BufFmt_CheckString(__Pyx_BufFmt_Context* ctx, const cha
         {
           const char* ts_after_sub;
           size_t i, struct_count = ctx->new_count;
-          size_t struct_alignment = ctx->struct_alignment;
           ctx->new_count = 1;
           ++ts;
           if (*ts != '{') {
             PyErr_SetString(PyExc_ValueError, "Buffer acquisition: Expected '{' after 'T'");
             return NULL;
           }
-          if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL;
-          ctx->enc_type = 0; /* Erase processed last struct element */
-          ctx->enc_count = 0;
-          ctx->struct_alignment = 0;
           ++ts;
           ts_after_sub = ts;
           for (i = 0; i != struct_count; ++i) {
@@ -7247,19 +6658,10 @@ static const char* __Pyx_BufFmt_CheckString(__Pyx_BufFmt_Context* ctx, const cha
             if (!ts_after_sub) return NULL;
           }
           ts = ts_after_sub;
-          if (struct_alignment) ctx->struct_alignment = struct_alignment;
         }
         break;
       case '}': /* end of substruct; either repeat or move on */
-        {
-          size_t alignment = ctx->struct_alignment;
-          ++ts;
-          if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL;
-          ctx->enc_type = 0; /* Erase processed last struct element */
-          if (alignment && ctx->fmt_offset % alignment) {
-            ctx->fmt_offset += alignment - (ctx->fmt_offset % alignment);
-          }
-        }
+        ++ts;
         return ts;
       case 'x':
         if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL;
@@ -7280,11 +6682,13 @@ static const char* __Pyx_BufFmt_CheckString(__Pyx_BufFmt_Context* ctx, const cha
       case 'c': case 'b': case 'B': case 'h': case 'H': case 'i': case 'I':
       case 'l': case 'L': case 'q': case 'Q':
       case 'f': case 'd': case 'g':
-      case 'O': case 's': case 'p':
+      case 'O':
         if (ctx->enc_type == *ts && got_Z == ctx->is_complex &&
             ctx->enc_packmode == ctx->new_packmode) {
+          /* Continue pooling same type */
           ctx->enc_count += ctx->new_count;
         } else {
+          /* New type */
           if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL;
           ctx->enc_count = ctx->new_count;
           ctx->enc_packmode = ctx->new_packmode;
@@ -7300,18 +6704,20 @@ static const char* __Pyx_BufFmt_CheckString(__Pyx_BufFmt_Context* ctx, const cha
         while(*ts != ':') ++ts;
         ++ts;
         break;
-      case '(':
-        if (!__pyx_buffmt_parse_array(ctx, &ts)) return NULL;
-        break;
       default:
         {
-          int number = __Pyx_BufFmt_ExpectNumber(&ts);
-          if (number == -1) return NULL;
-          ctx->new_count = (size_t)number;
+          int number = __Pyx_BufFmt_ParseNumber(&ts);
+          if (number == -1) { /* First char was not a digit */
+            PyErr_Format(PyExc_ValueError,
+                         "Does not understand character buffer dtype format string ('%c')", *ts);
+            return NULL;
+          }
+          ctx->new_count = (size_t)number; 
         }
     }
   }
 }
+
 static CYTHON_INLINE void __Pyx_ZeroBuffer(Py_buffer* buf) {
   buf->buf = NULL;
   buf->obj = NULL;
@@ -7319,10 +6725,8 @@ static CYTHON_INLINE void __Pyx_ZeroBuffer(Py_buffer* buf) {
   buf->shape = __Pyx_zeros;
   buf->suboffsets = __Pyx_minusones;
 }
-static CYTHON_INLINE int __Pyx_GetBufferAndValidate(
-        Py_buffer* buf, PyObject* obj,  __Pyx_TypeInfo* dtype, int flags,
-        int nd, int cast, __Pyx_BufFmt_StackElem* stack)
-{
+
+static CYTHON_INLINE int __Pyx_GetBufferAndValidate(Py_buffer* buf, PyObject* obj, __Pyx_TypeInfo* dtype, int flags, int nd, int cast, __Pyx_BufFmt_StackElem* stack) {
   if (obj == Py_None || obj == NULL) {
     __Pyx_ZeroBuffer(buf);
     return 0;
@@ -7353,6 +6757,7 @@ fail:;
   __Pyx_ZeroBuffer(buf);
   return -1;
 }
+
 static CYTHON_INLINE void __Pyx_SafeReleaseBuffer(Py_buffer* info) {
   if (info->buf == NULL) return;
   if (info->suboffsets == __Pyx_minusones) info->suboffsets = NULL;
@@ -7366,9 +6771,9 @@ static CYTHON_INLINE long __Pyx_mod_long(long a, long b) {
 }
 
 static CYTHON_INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb) {
-#if CYTHON_COMPILING_IN_CPYTHON
     PyObject *tmp_type, *tmp_value, *tmp_tb;
     PyThreadState *tstate = PyThreadState_GET();
+
     tmp_type = tstate->curexc_type;
     tmp_value = tstate->curexc_value;
     tmp_tb = tstate->curexc_traceback;
@@ -7378,30 +6783,27 @@ static CYTHON_INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyOb
     Py_XDECREF(tmp_type);
     Py_XDECREF(tmp_value);
     Py_XDECREF(tmp_tb);
-#else
-    PyErr_Restore(type, value, tb);
-#endif
 }
+
 static CYTHON_INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb) {
-#if CYTHON_COMPILING_IN_CPYTHON
     PyThreadState *tstate = PyThreadState_GET();
     *type = tstate->curexc_type;
     *value = tstate->curexc_value;
     *tb = tstate->curexc_traceback;
+
     tstate->curexc_type = 0;
     tstate->curexc_value = 0;
     tstate->curexc_traceback = 0;
-#else
-    PyErr_Fetch(type, value, tb);
-#endif
 }
 
+
 #if PY_MAJOR_VERSION < 3
-static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb,
-                        CYTHON_UNUSED PyObject *cause) {
+static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause) {
+    /* cause is unused */
     Py_XINCREF(type);
     Py_XINCREF(value);
     Py_XINCREF(tb);
+    /* First, check the traceback argument, replacing None with NULL. */
     if (tb == Py_None) {
         Py_DECREF(tb);
         tb = 0;
@@ -7411,6 +6813,7 @@ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb,
             "raise: arg 3 must be a traceback or None");
         goto raise_error;
     }
+    /* Next, replace a missing value with None */
     if (value == NULL) {
         value = Py_None;
         Py_INCREF(value);
@@ -7421,11 +6824,13 @@ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb,
     if (!PyType_Check(type))
     #endif
     {
+        /* Raising an instance.  The value should be a dummy. */
         if (value != Py_None) {
             PyErr_SetString(PyExc_TypeError,
                 "instance exception may not have a separate value");
             goto raise_error;
         }
+        /* Normalize to raise <class>, <instance> */
         Py_DECREF(value);
         value = type;
         #if PY_VERSION_HEX < 0x02050000
@@ -7449,6 +6854,7 @@ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb,
             }
         #endif
     }
+
     __Pyx_ErrRestore(type, value, tb);
     return;
 raise_error:
@@ -7457,7 +6863,9 @@ raise_error:
     Py_XDECREF(tb);
     return;
 }
+
 #else /* Python 3+ */
+
 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause) {
     if (tb == Py_None) {
         tb = 0;
@@ -7468,6 +6876,7 @@ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject
     }
     if (value == Py_None)
         value = 0;
+
     if (PyExceptionInstance_Check(type)) {
         if (value) {
             PyErr_SetString(PyExc_TypeError,
@@ -7481,6 +6890,7 @@ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject
             "raise: exception class must be a subclass of BaseException");
         goto bad;
     }
+
     if (cause) {
         PyObject *fixed_cause;
         if (PyExceptionClass_Check(cause)) {
@@ -7503,7 +6913,9 @@ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject
         }
         PyException_SetCause(value, fixed_cause);
     }
+
     PyErr_SetObject(type, value);
+
     if (tb) {
         PyThreadState *tstate = PyThreadState_GET();
         PyObject* tmp_tb = tstate->curexc_traceback;
@@ -7513,6 +6925,7 @@ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject
             Py_XDECREF(tmp_tb);
         }
     }
+
 bad:
     return;
 }
@@ -7570,98 +6983,31 @@ static void __Pyx_UnpackTupleError(PyObject *t, Py_ssize_t index) {
 
 #if PY_MAJOR_VERSION < 3
 static int __Pyx_GetBuffer(PyObject *obj, Py_buffer *view, int flags) {
-    PyObject *getbuffer_cobj;
-
   #if PY_VERSION_HEX >= 0x02060000
-    if (PyObject_CheckBuffer(obj)) return PyObject_GetBuffer(obj, view, flags);
+  if (PyObject_CheckBuffer(obj)) return PyObject_GetBuffer(obj, view, flags);
   #endif
-
-        if (PyObject_TypeCheck(obj, __pyx_ptype_5numpy_ndarray)) return __pyx_pw_5numpy_7ndarray_1__getbuffer__(obj, view, flags);
-
-  #if PY_VERSION_HEX < 0x02060000
-    if (obj->ob_type->tp_dict &&
-        (getbuffer_cobj = PyMapping_GetItemString(obj->ob_type->tp_dict,
-                                             "__pyx_getbuffer"))) {
-        getbufferproc func;
-
-      #if PY_VERSION_HEX >= 0x02070000 && !(PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION == 0)
-        func = (getbufferproc) PyCapsule_GetPointer(getbuffer_cobj, "getbuffer(obj, view, flags)");
-      #else
-        func = (getbufferproc) PyCObject_AsVoidPtr(getbuffer_cobj);
-      #endif
-        Py_DECREF(getbuffer_cobj);
-        if (!func)
-            goto fail;
-
-        return func(obj, view, flags);
-    } else {
-        PyErr_Clear();
+  if (PyObject_TypeCheck(obj, __pyx_ptype_5numpy_ndarray)) return __pyx_pf_5numpy_7ndarray___getbuffer__(obj, view, flags);
+  else {
+  PyErr_Format(PyExc_TypeError, "'%100s' does not have the buffer interface", Py_TYPE(obj)->tp_name);
+  return -1;
     }
-  #endif
-
-    PyErr_Format(PyExc_TypeError, "'%100s' does not have the buffer interface", Py_TYPE(obj)->tp_name);
-
-#if PY_VERSION_HEX < 0x02060000
-fail:
-#endif
-
-    return -1;
 }
 
 static void __Pyx_ReleaseBuffer(Py_buffer *view) {
-    PyObject *obj = view->obj;
-    PyObject *releasebuffer_cobj;
-
-    if (!obj) return;
-
-  #if PY_VERSION_HEX >= 0x02060000
-    if (PyObject_CheckBuffer(obj)) {
-        PyBuffer_Release(view);
-        return;
-    }
-  #endif
-
-        if (PyObject_TypeCheck(obj, __pyx_ptype_5numpy_ndarray)) { __pyx_pw_5numpy_7ndarray_3__releasebuffer__(obj, view); return; }
-
-  #if PY_VERSION_HEX < 0x02060000
-    if (obj->ob_type->tp_dict &&
-        (releasebuffer_cobj = PyMapping_GetItemString(obj->ob_type->tp_dict,
-                                                      "__pyx_releasebuffer"))) {
-        releasebufferproc func;
-
-      #if PY_VERSION_HEX >= 0x02070000 && !(PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION == 0)
-        func = (releasebufferproc) PyCapsule_GetPointer(releasebuffer_cobj, "releasebuffer(obj, view)");
-      #else
-        func = (releasebufferproc) PyCObject_AsVoidPtr(releasebuffer_cobj);
-      #endif
-
-        Py_DECREF(releasebuffer_cobj);
-
-        if (!func)
-            goto fail;
-
-        func(obj, view);
-        return;
-    } else {
-        PyErr_Clear();
-    }
-  #endif
-
-    goto nofail;
-
-#if PY_VERSION_HEX < 0x02060000
-fail:
-#endif
-    PyErr_WriteUnraisable(obj);
-
-nofail:
+  PyObject* obj = view->obj;
+  if (obj) {
+    #if PY_VERSION_HEX >= 0x02060000
+    if (PyObject_CheckBuffer(obj)) {PyBuffer_Release(view); return;}
+    #endif
+    if (PyObject_TypeCheck(obj, __pyx_ptype_5numpy_ndarray)) __pyx_pf_5numpy_7ndarray_1__releasebuffer__(obj, view);
     Py_DECREF(obj);
     view->obj = NULL;
+  }
 }
 
-#endif /*  PY_MAJOR_VERSION < 3 */
+#endif
 
-    static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, long level) {
+static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, long level) {
     PyObject *py_import = 0;
     PyObject *empty_list = 0;
     PyObject *module = 0;
@@ -7687,33 +7033,12 @@ nofail:
         goto bad;
     #if PY_VERSION_HEX >= 0x02050000
     {
-        #if PY_MAJOR_VERSION >= 3
-        if (level == -1) {
-            if (strchr(__Pyx_MODULE_NAME, '.')) {
-                /* try package relative import first */
-                PyObject *py_level = PyInt_FromLong(1);
-                if (!py_level)
-                    goto bad;
-                module = PyObject_CallFunctionObjArgs(py_import,
-                    name, global_dict, empty_dict, list, py_level, NULL);
-                Py_DECREF(py_level);
-                if (!module) {
-                    if (!PyErr_ExceptionMatches(PyExc_ImportError))
-                        goto bad;
-                    PyErr_Clear();
-                }
-            }
-            level = 0; /* try absolute import on failure */
-        }
-        #endif
-        if (!module) {
-            PyObject *py_level = PyInt_FromLong(level);
-            if (!py_level)
-                goto bad;
-            module = PyObject_CallFunctionObjArgs(py_import,
-                name, global_dict, empty_dict, list, py_level, NULL);
-            Py_DECREF(py_level);
-        }
+        PyObject *py_level = PyInt_FromLong(level);
+        if (!py_level)
+            goto bad;
+        module = PyObject_CallFunctionObjArgs(py_import,
+            name, global_dict, empty_dict, list, py_level, NULL);
+        Py_DECREF(py_level);
     }
     #else
     if (level>0) {
@@ -8398,10 +7723,15 @@ static PyTypeObject *__Pyx_ImportType(const char *module_name, const char *class
     PyObject *result = 0;
     PyObject *py_name = 0;
     char warning[200];
+
     py_module = __Pyx_ImportModule(module_name);
     if (!py_module)
         goto bad;
-    py_name = __Pyx_PyIdentifier_FromString(class_name);
+    #if PY_MAJOR_VERSION < 3
+    py_name = PyString_FromString(class_name);
+    #else
+    py_name = PyUnicode_FromString(class_name);
+    #endif
     if (!py_name)
         goto bad;
     result = PyObject_GetAttr(py_module, py_name);
@@ -8417,7 +7747,7 @@ static PyTypeObject *__Pyx_ImportType(const char *module_name, const char *class
             module_name, class_name);
         goto bad;
     }
-    if (!strict && (size_t)((PyTypeObject *)result)->tp_basicsize > size) {
+    if (!strict && ((PyTypeObject *)result)->tp_basicsize > (Py_ssize_t)size) {
         PyOS_snprintf(warning, sizeof(warning),
             "%s.%s size changed, may indicate binary incompatibility",
             module_name, class_name);
@@ -8427,7 +7757,7 @@ static PyTypeObject *__Pyx_ImportType(const char *module_name, const char *class
         if (PyErr_WarnEx(NULL, warning, 0) < 0) goto bad;
         #endif
     }
-    else if ((size_t)((PyTypeObject *)result)->tp_basicsize != size) {
+    else if (((PyTypeObject *)result)->tp_basicsize != (Py_ssize_t)size) {
         PyErr_Format(PyExc_ValueError,
             "%s.%s has the wrong size, try recompiling",
             module_name, class_name);
@@ -8446,7 +7776,12 @@ bad:
 static PyObject *__Pyx_ImportModule(const char *name) {
     PyObject *py_name = 0;
     PyObject *py_module = 0;
-    py_name = __Pyx_PyIdentifier_FromString(name);
+
+    #if PY_MAJOR_VERSION < 3
+    py_name = PyString_FromString(name);
+    #else
+    py_name = PyUnicode_FromString(name);
+    #endif
     if (!py_name)
         goto bad;
     py_module = PyImport_Import(py_name);
@@ -8458,105 +7793,29 @@ bad:
 }
 #endif
 
-static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line) {
-    int start = 0, mid = 0, end = count - 1;
-    if (end >= 0 && code_line > entries[end].code_line) {
-        return count;
-    }
-    while (start < end) {
-        mid = (start + end) / 2;
-        if (code_line < entries[mid].code_line) {
-            end = mid;
-        } else if (code_line > entries[mid].code_line) {
-             start = mid + 1;
-        } else {
-            return mid;
-        }
-    }
-    if (code_line <= entries[mid].code_line) {
-        return mid;
-    } else {
-        return mid + 1;
-    }
-}
-static PyCodeObject *__pyx_find_code_object(int code_line) {
-    PyCodeObject* code_object;
-    int pos;
-    if (unlikely(!code_line) || unlikely(!__pyx_code_cache.entries)) {
-        return NULL;
-    }
-    pos = __pyx_bisect_code_objects(__pyx_code_cache.entries, __pyx_code_cache.count, code_line);
-    if (unlikely(pos >= __pyx_code_cache.count) || unlikely(__pyx_code_cache.entries[pos].code_line != code_line)) {
-        return NULL;
-    }
-    code_object = __pyx_code_cache.entries[pos].code_object;
-    Py_INCREF(code_object);
-    return code_object;
-}
-static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object) {
-    int pos, i;
-    __Pyx_CodeObjectCacheEntry* entries = __pyx_code_cache.entries;
-    if (unlikely(!code_line)) {
-        return;
-    }
-    if (unlikely(!entries)) {
-        entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Malloc(64*sizeof(__Pyx_CodeObjectCacheEntry));
-        if (likely(entries)) {
-            __pyx_code_cache.entries = entries;
-            __pyx_code_cache.max_count = 64;
-            __pyx_code_cache.count = 1;
-            entries[0].code_line = code_line;
-            entries[0].code_object = code_object;
-            Py_INCREF(code_object);
-        }
-        return;
-    }
-    pos = __pyx_bisect_code_objects(__pyx_code_cache.entries, __pyx_code_cache.count, code_line);
-    if ((pos < __pyx_code_cache.count) && unlikely(__pyx_code_cache.entries[pos].code_line == code_line)) {
-        PyCodeObject* tmp = entries[pos].code_object;
-        entries[pos].code_object = code_object;
-        Py_DECREF(tmp);
-        return;
-    }
-    if (__pyx_code_cache.count == __pyx_code_cache.max_count) {
-        int new_max = __pyx_code_cache.max_count + 64;
-        entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Realloc(
-            __pyx_code_cache.entries, new_max*sizeof(__Pyx_CodeObjectCacheEntry));
-        if (unlikely(!entries)) {
-            return;
-        }
-        __pyx_code_cache.entries = entries;
-        __pyx_code_cache.max_count = new_max;
-    }
-    for (i=__pyx_code_cache.count; i>pos; i--) {
-        entries[i] = entries[i-1];
-    }
-    entries[pos].code_line = code_line;
-    entries[pos].code_object = code_object;
-    __pyx_code_cache.count++;
-    Py_INCREF(code_object);
-}
-
 #include "compile.h"
 #include "frameobject.h"
 #include "traceback.h"
-static PyCodeObject* __Pyx_CreateCodeObjectForTraceback(
-            const char *funcname, int c_line,
-            int py_line, const char *filename) {
-    PyCodeObject *py_code = 0;
+
+static void __Pyx_AddTraceback(const char *funcname, int __pyx_clineno,
+                               int __pyx_lineno, const char *__pyx_filename) {
     PyObject *py_srcfile = 0;
     PyObject *py_funcname = 0;
+    PyObject *py_globals = 0;
+    PyCodeObject *py_code = 0;
+    PyFrameObject *py_frame = 0;
+
     #if PY_MAJOR_VERSION < 3
-    py_srcfile = PyString_FromString(filename);
+    py_srcfile = PyString_FromString(__pyx_filename);
     #else
-    py_srcfile = PyUnicode_FromString(filename);
+    py_srcfile = PyUnicode_FromString(__pyx_filename);
     #endif
     if (!py_srcfile) goto bad;
-    if (c_line) {
+    if (__pyx_clineno) {
         #if PY_MAJOR_VERSION < 3
-        py_funcname = PyString_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line);
+        py_funcname = PyString_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, __pyx_clineno);
         #else
-        py_funcname = PyUnicode_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line);
+        py_funcname = PyUnicode_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, __pyx_clineno);
         #endif
     }
     else {
@@ -8567,45 +7826,28 @@ static PyCodeObject* __Pyx_CreateCodeObjectForTraceback(
         #endif
     }
     if (!py_funcname) goto bad;
-    py_code = __Pyx_PyCode_New(
+    py_globals = PyModule_GetDict(__pyx_m);
+    if (!py_globals) goto bad;
+    py_code = PyCode_New(
         0,            /*int argcount,*/
+        #if PY_MAJOR_VERSION >= 3
         0,            /*int kwonlyargcount,*/
+        #endif
         0,            /*int nlocals,*/
         0,            /*int stacksize,*/
         0,            /*int flags,*/
         __pyx_empty_bytes, /*PyObject *code,*/
-        __pyx_empty_tuple, /*PyObject *consts,*/
-        __pyx_empty_tuple, /*PyObject *names,*/
-        __pyx_empty_tuple, /*PyObject *varnames,*/
-        __pyx_empty_tuple, /*PyObject *freevars,*/
-        __pyx_empty_tuple, /*PyObject *cellvars,*/
+        __pyx_empty_tuple,  /*PyObject *consts,*/
+        __pyx_empty_tuple,  /*PyObject *names,*/
+        __pyx_empty_tuple,  /*PyObject *varnames,*/
+        __pyx_empty_tuple,  /*PyObject *freevars,*/
+        __pyx_empty_tuple,  /*PyObject *cellvars,*/
         py_srcfile,   /*PyObject *filename,*/
         py_funcname,  /*PyObject *name,*/
-        py_line,      /*int firstlineno,*/
+        __pyx_lineno,   /*int firstlineno,*/
         __pyx_empty_bytes  /*PyObject *lnotab*/
     );
-    Py_DECREF(py_srcfile);
-    Py_DECREF(py_funcname);
-    return py_code;
-bad:
-    Py_XDECREF(py_srcfile);
-    Py_XDECREF(py_funcname);
-    return NULL;
-}
-static void __Pyx_AddTraceback(const char *funcname, int c_line,
-                               int py_line, const char *filename) {
-    PyCodeObject *py_code = 0;
-    PyObject *py_globals = 0;
-    PyFrameObject *py_frame = 0;
-    py_code = __pyx_find_code_object(c_line ? c_line : py_line);
-    if (!py_code) {
-        py_code = __Pyx_CreateCodeObjectForTraceback(
-            funcname, c_line, py_line, filename);
-        if (!py_code) goto bad;
-        __pyx_insert_code_object(c_line ? c_line : py_line, py_code);
-    }
-    py_globals = PyModule_GetDict(__pyx_m);
-    if (!py_globals) goto bad;
+    if (!py_code) goto bad;
     py_frame = PyFrame_New(
         PyThreadState_GET(), /*PyThreadState *tstate,*/
         py_code,             /*PyCodeObject *code,*/
@@ -8613,9 +7855,11 @@ static void __Pyx_AddTraceback(const char *funcname, int c_line,
         0                    /*PyObject *locals*/
     );
     if (!py_frame) goto bad;
-    py_frame->f_lineno = py_line;
+    py_frame->f_lineno = __pyx_lineno;
     PyTraceBack_Here(py_frame);
 bad:
+    Py_XDECREF(py_srcfile);
+    Py_XDECREF(py_funcname);
     Py_XDECREF(py_code);
     Py_XDECREF(py_frame);
 }
@@ -8650,7 +7894,6 @@ static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) {
     return 0;
 }
 
-
 /* Type Conversion Functions */
 
 static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject* x) {
diff --git a/astropy/nddata/convolution/convolve.py b/astropy/nddata/convolution/convolve.py
index c7e9e9e..a0d67a1 100644
--- a/astropy/nddata/convolution/convolve.py
+++ b/astropy/nddata/convolution/convolve.py
@@ -51,7 +51,7 @@ def convolve(array, kernel, boundary=None, fill_value=0.,
 
     This routine differs from `scipy.ndimage.filters.convolve` because
     it includes a special treatment for `NaN` values. Rather than
-    including `NaN`s in the convolution calculation, which causes large
+    including `NaNs` in the convolution calculation, which causes large
     `NaN` holes in the convolved image, `NaN` values are replaced with
     interpolated values using the kernel as an interpolation function.
 
@@ -229,9 +229,9 @@ def convolve_fft(array, kernel, boundary='fill', fill_value=0,
     boundary : {'fill', 'wrap'}
         A flag indicating how to handle boundaries:
 
-            * 'fill' : set values outside the array boundary to fill_value
-                       (default)
-            * 'wrap' : periodic boundary
+            * 'fill': set values outside the array boundary to fill_value
+              (default)
+            * 'wrap': periodic boundary
 
     interpolate_nan : bool
         The convolution will be re-weighted assuming NAN values are meant to be
diff --git a/astropy/nddata/convolution/make_kernel.py b/astropy/nddata/convolution/make_kernel.py
index 9459742..e75c5f4 100644
--- a/astropy/nddata/convolution/make_kernel.py
+++ b/astropy/nddata/convolution/make_kernel.py
@@ -5,7 +5,7 @@ import numpy as np
 def make_kernel(kernelshape, kernelwidth=3, kerneltype='gaussian',
         trapslope=None, normalize_kernel=np.sum, force_odd=False):
     """
-    Create a smoothing kernel for use with `convolve` or `convolve_fft`
+    Create a smoothing kernel for use with `convolve` or `convolve_fft`.
 
     Parameters
     ----------
@@ -28,7 +28,7 @@ def make_kernel(kernelshape, kernelwidth=3, kerneltype='gaussian',
         * 'tophat'
             A flat circle  with radius = `kernelwidth`,
             i.e., kernel = (r < `kernelwidth`)
-        * 'birckwall' or 'airy'
+        * 'brickwall' or 'airy'
             A kernel using the airy function from optics. It requires
             `scipy.special` for the bessel function. See e.g.,
             http://en.wikipedia.org/wiki/Airy_disk.
diff --git a/astropy/nddata/convolution/tests/test_convolve_fft.py b/astropy/nddata/convolution/tests/test_convolve_fft.py
index 3fd1967..9f89663 100644
--- a/astropy/nddata/convolution/tests/test_convolve_fft.py
+++ b/astropy/nddata/convolution/tests/test_convolve_fft.py
@@ -381,7 +381,9 @@ class TestConvolve2D(object):
         print "z: ", z
         print "answer: ", a
         print "ratio: ", z / a
-        assert np.all(np.abs(z - a) < np.spacing(np.where(z > a, z, a)) * 10)
+        # for reasons unknown, the Windows FFT returns an answer for the [0,0]
+        # component that is EXACTLY 10*np.spacing
+        assert np.all(np.abs(z - a) <= np.spacing(np.where(z > a, z, a)) * 10)
 
     @pytest.mark.parametrize(option_names, options)
     def test_unity_3x3_withnan(self, boundary, interpolate_nan, normalize_kernel, ignore_edge_zeros, fft_type):
@@ -491,4 +493,6 @@ class TestConvolve2D(object):
         print "z: ", z
         print "answer: ", a
         print "ratio: ", z / a
-        assert np.all(np.abs(z - a) < np.spacing(np.where(z > a, z, a)) * 10)
+        # for reasons unknown, the Windows FFT returns an answer for the [0,0]
+        # component that is EXACTLY 10*np.spacing
+        assert np.all(np.abs(z - a) <= np.spacing(np.where(z > a, z, a)) * 10)
diff --git a/astropy/nddata/flag_collection.py b/astropy/nddata/flag_collection.py
new file mode 100644
index 0000000..c8bec6c
--- /dev/null
+++ b/astropy/nddata/flag_collection.py
@@ -0,0 +1,41 @@
+import numpy as np
+
+from ..utils.compat.odict import OrderedDict
+from ..utils.misc import isiterable
+
+__all__ = ['FlagCollection']
+
+
+class FlagCollection(OrderedDict):
+    """
+    The purpose of this class is to provide a dictionary for
+    containing arrays of flags for the `NDData` class. Flags should be
+    stored in Numpy arrays that have the same dimensions as the parent
+    data, so the `FlagCollection` class adds shape checking to an
+    ordered dictionary class.
+
+    The `FlagCollection` should be initialized like an `OrderedDict`,
+    but with the addition of a ``shape=`` keyword argument used to
+    pass the NDData shape.
+    """
+
+    def __init__(self, *args, **kwargs):
+
+        if 'shape' in kwargs:
+            self.shape = kwargs.pop('shape')
+            if not isiterable(self.shape):
+                raise ValueError("FlagCollection shape should be an iterable object")
+        else:
+            raise Exception("FlagCollection should be initialized with the shape of the data")
+
+        OrderedDict.__init__(self, *args, **kwargs)
+
+    def __setitem__(self, item, value, **kwargs):
+
+        if isinstance(value, np.ndarray):
+            if value.shape == self.shape:
+                OrderedDict.__setitem__(self, item, value, **kwargs)
+            else:
+                raise ValueError("flags array shape {0:s} does not match data shape {1:s}".format(value.shape, self.shape))
+        else:
+            raise TypeError("flags should be given as a Numpy array")
diff --git a/astropy/nddata/nddata.py b/astropy/nddata/nddata.py
index 754cd66..60b41e8 100644
--- a/astropy/nddata/nddata.py
+++ b/astropy/nddata/nddata.py
@@ -5,35 +5,48 @@ __all__ = ['NDData']
 
 import numpy as np
 
+from ..units import Unit
+from ..logger import log
+
+from .flag_collection import FlagCollection
+from .nduncertainty import IncompatibleUncertaintiesException, NDUncertainty
+from ..utils.compat.odict import OrderedDict
+from ..io import fits
+from ..config import ConfigurationItem
+
+WARN_UNSUPPORTED_CORRELATED = ConfigurationItem(
+    'warn_unsupported_correlated', True,
+    'Whether to issue a warning if NDData arithmetic is performed with '
+    'uncertainties and the uncertainties do not support the propagation '
+    'of correlated uncertainties.'
+    )
+
 
 class NDData(object):
     """A Superclass for array-based data in Astropy.
 
-    The key distinction from raw numpy arrays is the presence of
-    additional metadata such as error arrays, bad pixel masks, units
-    and/or a coordinate system.
+    The key distinction from raw numpy arrays is the presence of additional
+    metadata such as uncertainties, a mask, units, flags, and/or a coordinate system.
 
     Parameters
     -----------
-    data : `~numpy.ndarray`
+    data : `~numpy.ndarray` or `~astropy.nddata.NDData`
         The actual data contained in this `NDData` object.
 
-    error : `~numpy.ndarray`, optional
-        Error of the data. This should be interpreted as a 1-sigma error (e.g,
-        square root of the variance), under the assumption of Gaussian errors.
-        Must be a shape that can be broadcast onto `data`.
-
-         .. warning::
-             The physical interpretation of the `error` array may change in the
-             future, as it has not been intensively discussed. For now assume
-             the above description holds, using an `error` property if
-             necessary, but feel free to use the most convinient internal
-             representation in subclasses
+    uncertainty : `~astropy.nddata.NDUncertainty`, optional
+        Uncertainties on the data.
 
     mask : `~numpy.ndarray`, optional
-        Masking of the data; Should be False/0 (or the empty string) where the
-        data is *valid*.  All other values indicate that the value should be
-        masked. Must be a shape that can be broadcast onto `data`.
+        Mask for the data, given as a boolean Numpy array with a shape
+        matching that of the data. The values must be ``False`` where the
+        data is *valid* and ``True`` when it is not (as for Numpy masked
+        arrays).
+
+    flags : `~numpy.ndarray` or `~astropy.nddata.FlagCollection`, optional
+        Flags giving information about each pixel. These can be specified
+        either as a Numpy array of any type with a shape matching that of the
+        data, or as a `~astropy.nddata.FlagCollection` instance which has a
+        shape matching that of the data.
 
     wcs : undefined, optional
         WCS-object containing the world coordinate system for the data.
@@ -49,27 +62,18 @@ class NDData(object):
         of this particular object.  e.g., creation date, unique identifier,
         simulation parameters, exposure time, telescope name, etc.
 
-    units : undefined, optional
+    units : `astropy.units.UnitBase` instance or str, optional
         The units of the data.
 
-        .. warning::
-            The units scheme is under development. For now, just supply a
-            string when relevant - the units system will likely be compatible
-            with providing strings to initialize itself.
-
     copy : bool, optional
         If True, the array will be *copied* from the provided `data`, otherwise
         it will be referenced if possible (see `numpy.array` :attr:`copy`
         argument for details).
 
-    validate : bool, optional
-        If False, no type or shape-checking or array conversion will occur.
-        Note that if `validate` is False, :attr:`copy` will be ignored.
-
     Raises
     ------
     ValueError
-        If the `error` or `mask` inputs cannot be broadcast (e.g., match
+        If the `uncertainty` or `mask` inputs cannot be broadcast (e.g., match
         shape) onto `data`.
 
     Notes
@@ -96,83 +100,128 @@ class NDData(object):
         >>> x = NDData([[1,2,3], [4,5,6]])
         >>> plt.imshow(x)
     """
-    def __init__(self, data, error=None, mask=None, wcs=None, meta=None,
-                 units=None, copy=True, validate=True):
-        if validate:
-            self.data = np.array(data, subok=True, copy=copy)
 
-            if error is None:
-                self.error = None
-            else:
-                self.error = np.array(error, subok=True, copy=copy)
+    def __init__(self, data, uncertainty=None, mask=None, flags=None, wcs=None,
+                 meta=None, units=None, copy=True):
 
-            if mask is None:
-                self.mask = None
-            else:
-                self.mask = np.array(mask, subok=True, copy=copy)
+        if isinstance(data, self.__class__):
+            self.data = np.array(data.data, subok=True, copy=copy)
 
-            self._validate_mask_and_error()
+            if uncertainty is not None:
+                self.uncertainty = uncertainty
+                log.info("Overwriting NDData's current uncertainty being overwritten with specified uncertainty")
+
+            if mask is not None:
+                self.mask = mask
+                log.info("Overwriting NDData's current mask being overwritten with specified mask")
+
+            if flags is not None:
+                self.flags = flags
+                log.info("Overwriting NDData's current flags being overwritten with specified flag")
+
+            if wcs is not None:
+                self.wcs = wcs
+                log.info("Overwriting NDData's current wcs being overwritten with specified wcs")
+
+            if meta is not None:
+                self.meta = meta
+                log.info("Overwriting NDData's current meta being overwritten with specified meta")
+
+            if units is not None:
+                raise ValueError('To convert to different unit please use .to')
 
-            self.wcs = wcs
-            self.units = units
-            if meta is None:
-                self.meta = {}
-            else:
-                self.meta = dict(meta)  # makes a *copy* of the passed-in meta
         else:
-            self.data = data
-            self.error = error
+            self.data = np.array(data, subok=True, copy=copy)
+
+            self.uncertainty = uncertainty
             self.mask = mask
+            self.flags = flags
             self.wcs = wcs
             self.meta = meta
             self.units = units
 
-    def _validate_mask_and_error(self):
-        """
-        Raises ValueError if they don't match (using ~numpy.broadcast)
-        """
-
-        try:
-            if self.mask is not None:
-                np.broadcast(self.data, self.mask)
-            maskmatch = True
-        except ValueError:
-            maskmatch = False
-
-        try:
-            if self.error is not None:
-                np.broadcast(self.data, self.error)
-            errmatch = True
-        except ValueError:
-            errmatch = False
-
-        if not errmatch and not maskmatch:
-            raise ValueError('NDData error and mask do not match data')
-        elif not errmatch:
-            raise ValueError('NDData error does not match data')
-        elif not maskmatch:
-            raise ValueError('NDData mask does not match data')
+    @property
+    def mask(self):
+        return self._mask
+
+    @mask.setter
+    def mask(self, value):
+        if value is not None:
+            if isinstance(value, np.ndarray):
+                if value.dtype != np.bool_:
+                    raise TypeError("mask must be a boolean Numpy array")
+                else:
+                    if value.shape != self.shape:
+                        raise ValueError("dimensions of mask do not match data")
+                    else:
+                        self._mask = value
+            else:
+                raise TypeError("mask must be a Numpy array")
+        else:
+            self._mask = value
 
     @property
-    def boolmask(self):
-        """
-        The mask as a boolean array (or None if the mask is None).
+    def flags(self):
+        return self._flags
+
+    @flags.setter
+    def flags(self, value):
+        if value is not None:
+            if isinstance(value, np.ndarray):
+                if value.shape != self.shape:
+                    raise ValueError("dimensions of flags do not match data")
+                else:
+                    self._flags = value
+            elif isinstance(value, FlagCollection):
+                if value.shape != self.shape:
+                    raise ValueError("dimensions of FlagCollection does not match data")
+                else:
+                    self._flags = value
+            else:
+                raise TypeError("flags should be a Numpy array or a FlagCollection instance")
+        else:
+            self._flags = value
 
-        This mask is True where the data is *valid*, and False where the data
-        should be *masked*.  This is the opposite of the convention used for
-        `mask`, but allows simple retrieval of the unmasked data points as
-        ``ndd.data[ndd.boolmask]``.
-        """
-        if self.mask is None:
-            return None
-        else:
-            dtchar = self.mask.dtype.char
-            if dtchar == 'U':
-                return self.mask == u''
-            elif dtchar == 'S':
-                return self.mask == b''
+    @property
+    def uncertainty(self):
+        return self._uncertainty
+
+    @uncertainty.setter
+    def uncertainty(self, value):
+        if value is not None:
+            if isinstance(value, NDUncertainty):
+                self._uncertainty = value
+                self._uncertainty.parent_nddata = self
             else:
-                return ~self.mask.astype(bool)
+                raise TypeError("Uncertainty must be an instance of a NDUncertainty object")
+        else:
+            self._uncertainty = value
+
+    @property
+    def meta(self):
+        return self._meta
+
+    @meta.setter
+    def meta(self, value):
+        if value is None:
+            self._meta = OrderedDict()
+        else:
+            try:
+                self._meta = OrderedDict(value)
+            except ValueError:
+                raise TypeError('NDData meta attribute must be dict-like')
+
+
+    @property
+    def units(self):
+        return self._units
+
+    @units.setter
+    def units(self, value):
+        if value is None:
+            self._units = None
+        else:
+            self._units = Unit(value)
 
     @property
     def shape(self):
@@ -211,3 +260,193 @@ class NDData(object):
             return np.ma.masked_array(self.data, self.mask)
         else:
             return self.data
+
+    def __getitem__(self, item):
+
+        new_data = self.data[item]
+
+        if self.uncertainty is not None:
+            new_uncertainty = self.uncertainty[item]
+        else:
+            new_uncertainty = None
+
+        if self.mask is not None:
+            new_mask = self.mask[item]
+        else:
+            new_mask = None
+
+        if self.flags is not None:
+            if isinstance(self.flags, np.ndarray):
+                new_flags = self.flags[item]
+            elif isinstance(self.flags, FlagCollection):
+                raise NotImplementedError('Slicing complex Flags is currently not implemented')
+        else:
+            new_flags = None
+
+        if self.wcs is not None:
+            raise NotImplementedError('Slicing for WCS is not currently implemented')
+        else:
+            new_wcs = None
+
+        return self.__class__(new_data, uncertainty=new_uncertainty, mask=new_mask, flags=new_flags, wcs=new_wcs,
+            meta=self.meta, units=self.units, copy=False)
+
+    def _arithmetic(self, operand, propagate_uncertainties, name, operation):
+        """
+        {name} another dataset (`operand`) to this dataset.
+
+        Parameters
+        ----------
+        operand : `~astropy.nddata.NDData`
+            The second operand in the operation a {operator} b
+        propagate_uncertainties : bool
+            Whether to propagate uncertainties following the propagation rules
+            defined by the class used for the `uncertainty` attribute.
+
+        Returns
+        -------
+        result : `~astropy.nddata.NDData`
+            The resulting dataset
+
+        Notes
+        -----
+        This method requires the datasets to have identical WCS properties,
+        equivalent units, and identical shapes. Flags and meta-data get set to
+        None in the resulting dataset. The unit in the result is the same as
+        the unit in `self`. Uncertainties are propagated, although correlated
+        errors are not supported by any of the built-in uncertainty classes.
+        If uncertainties are assumed to be correlated, a warning is issued by
+        default (though this can be disabled via the
+        `WARN_UNSUPPORTED_CORRELATED` configuration item). Values masked in
+        either dataset before the operation are masked in the resulting
+        dataset.
+        """
+        if self.wcs != operand.wcs:
+            raise ValueError("WCS properties do not match")
+
+        if not (self.units is None and operand.units is None):
+            if (self.units is None or operand.units is None
+                or not self.units.is_equivalent(operand.units)):
+                raise ValueError("operand units do not match")
+
+        if self.shape != operand.shape:
+            raise ValueError("operand shapes do not match")
+
+        if self.units is not None:
+            operand_data = operand.units.to(self.units, operand.data)
+        else:
+            operand_data = operand.data
+        data = operation(self.data, operand_data)
+        result = self.__class__(data)  # in case we are dealing with an inherited type
+
+        if propagate_uncertainties is None:
+            result.uncertainty = None
+        elif self.uncertainty is None and operand.uncertainty is None:
+            result.uncertainty = None
+        elif self.uncertainty is None:
+            result.uncertainty = operand.uncertainty
+        elif operand.uncertainty is None:
+            result.uncertainty = self.uncertainty
+        else:  # both self and operand have uncertainties
+            if WARN_UNSUPPORTED_CORRELATED() and \
+               (not self.uncertainty.support_correlated or \
+               not operand.uncertainty.support_correlated):
+                log.info("The uncertainty classes used do not support the "
+                         "propagation of correlated errors, so uncertainties"
+                         " will be propagated assuming they are uncorrelated")
+            try:
+                method = getattr(self.uncertainty, propagate_uncertainties)
+                result.uncertainty = method(operand, result.data)
+            except IncompatibleUncertaintiesException:
+                raise IncompatibleUncertaintiesException(
+                    "Cannot propagate uncertainties of type {0:s} with uncertainties of "
+                    "type {1:s} for {2:s}".format(
+                        self.uncertainty.__class__.__name__,
+                        operand.uncertainty.__class__.__name__,
+                        name))
+
+        if self.mask is None and operand.mask is None:
+            result.mask = None
+        elif self.mask is None:
+            result.mask = operand.mask
+        elif operand.mask is None:
+            result.mask = self.mask
+        else:  # combine masks as for Numpy masked arrays
+            result.mask = self.mask & operand.mask
+
+        result.flags = None
+        result.wcs = self.wcs
+        result.meta = None
+        result.units = self.units
+
+        return result
+
+    def add(self, operand, propagate_uncertainties=True):
+        if propagate_uncertainties:
+            propagate_uncertainties = "propagate_add"
+        else:
+            propagate_uncertainties = None
+        return self._arithmetic(
+            operand, propagate_uncertainties, "addition", np.add)
+    add.__doc__ = _arithmetic.__doc__.format(name="Add", operator="+")
+
+    def subtract(self, operand, propagate_uncertainties=True):
+        if propagate_uncertainties:
+            propagate_uncertainties = "propagate_subtract"
+        else:
+            propagate_uncertainties = None
+        return self._arithmetic(
+            operand, propagate_uncertainties, "subtraction", np.subtract)
+    subtract.__doc__ = _arithmetic.__doc__.format(name="Subtract", operator="-")
+
+    def multiply(self, operand, propagate_uncertainties=True):
+        if propagate_uncertainties:
+            propagate_uncertainties = "propagate_multiply"
+        else:
+            propagate_uncertainties = None
+        return self._arithmetic(
+            operand, propagate_uncertainties, "multiplication", np.multiply)
+    multiply.__doc__ = _arithmetic.__doc__.format(name="Multiply", operator="*")
+
+    def divide(self, operand, propagate_uncertainties=True):
+        if propagate_uncertainties:
+            propagate_uncertainties = "propagate_divide"
+        else:
+            propagate_uncertainties = None
+        return self._arithmetic(
+            operand, propagate_uncertainties, "division", np.divide)
+    divide.__doc__ = _arithmetic.__doc__.format(name="Divide", operator="/")
+
+    def convert_units_to(self, unit):
+        """
+        Returns a new `NDData` object whose values have been converted
+        to a new unit.
+
+        Parameters
+        ----------
+        unit : `astropy.units.UnitBase` instance or str
+            The unit to convert to.
+
+        Returns
+        -------
+        result : `~astropy.nddata.NDData`
+            The resulting dataset
+
+        Raises
+        ------
+        UnitsException
+            If units are inconsistent.
+        """
+        if self.units is None:
+            raise ValueError("No units specified on source data")
+        data = self.units.to(unit, self.data)
+        result = self.__class__(data)  # in case we are dealing with an inherited type
+
+        result.uncertainty = self.uncertainty
+        result.mask = self.mask
+        result.flags = None
+        result.wcs = self.wcs
+        result.meta = self.meta
+        result.units = unit
+
+        return result
diff --git a/astropy/nddata/nduncertainty.py b/astropy/nddata/nduncertainty.py
new file mode 100644
index 0000000..50af5f9
--- /dev/null
+++ b/astropy/nddata/nduncertainty.py
@@ -0,0 +1,345 @@
+import abc
+
+import numpy as np
+
+__all__ = ['MissingDataAssociationException', 'IncompatibleUncertaintiesException', 'NDUncertainty',
+           'StdDevUncertainty']
+
+
+class IncompatibleUncertaintiesException(Exception):
+    """
+    This exception should be used to indicate cases in which uncertainties with two different classes can not be propagated.
+    """
+    pass
+
+
+class MissingDataAssociationException(Exception):
+    """
+    This exception should be used to indicate that an uncertainty instance has not been associated with a parent `~astropy.nddata.nddata.NDData` object.
+    """
+    pass
+
+
+class NDUncertainty(object):
+    '''
+    This is the base class for uncertainty classes used with NDData. It is
+    implemented as an abstract class and should never be directly
+    instantiated.
+
+    Classes inheriting from NDData should overload the ``propagate_*``
+    methods, keeping the call signature the same. The propagate methods can
+    assume that a `parent_nddata` attribute is present which links to the parent_nddata
+    dataset, and take an `~astropy.nddata.NDData` instance as the positional
+    argument, *not* an `~astropy.nddata.NDUncertainty` instance, because the
+    `~astropy.nddata.NDData` instance can be used to access both the data and
+    the uncertainties (some propagations require the data values).
+    '''
+
+    __metaclass__ = abc.ABCMeta
+
+    # Indicates whether the class supports the propagation of correlated
+    # uncertainties
+    supports_correlated = False
+
+    @property
+    def parent_nddata(self):
+        if self._parent_nddata is None:
+            raise MissingDataAssociationException("uncertainty is not associated with an NDData object")
+        else:
+            return self._parent_nddata
+
+    @parent_nddata.setter
+    def parent_nddata(self, value):
+        self._parent_nddata = value
+
+    @abc.abstractmethod
+    def propagate_add(self, other_nddata, result_data):
+        '''
+        Propagate uncertainties for addition.
+
+        Parameters
+        ----------
+        other_nddata : NDData instance
+            The data for the second other_nddata in a + b
+        result_data : `~numpy.ndarray` instance
+            The data array that is the result of the addition
+
+        Returns
+        -------
+        result_uncertainty : NDUncertainty instance
+            The resulting uncertainty
+
+        Raises
+        ------
+        IncompatibleUncertaintiesException
+            Raised if the method does not know how to add the uncertainties
+        '''
+        pass
+
+    @abc.abstractmethod
+    def propagate_subtract(self, other_nddata, result_data):
+        '''
+        Propagate uncertainties for subtraction.
+
+        Parameters
+        ----------
+        other_nddata : NDData instance
+            The data for the second other_nddata in a + b
+        result_data : `~numpy.ndarray` instance
+            The data array that is the result of the addition
+
+        Returns
+        -------
+        result_uncertainty : NDUncertainty instance
+            The resulting uncertainty
+
+        Raises
+        ------
+        IncompatibleUncertaintiesException
+            Raised if the method does not know how to add the uncertainties
+        '''
+        pass
+
+    @abc.abstractmethod
+    def propagate_multiply(self, other_nddata, result_data):
+        '''
+        Propagate uncertainties for multiplication.
+
+        Parameters
+        ----------
+        other_nddata : NDData instance
+            The data for the second other_nddata in a + b
+        result_data : `~numpy.ndarray` instance
+            The data array that is the result of the addition
+
+        Returns
+        -------
+        result_uncertainty : NDUncertainty instance
+            The resulting uncertainty
+        '''
+        pass
+
+    @abc.abstractmethod
+    def propagate_divide(self, other_nddata, result_data):
+        '''
+        Propagate uncertainties for division.
+
+        Parameters
+        ----------
+        other_nddata : NDData instance
+            The data for the second other_nddata in a + b
+        result_data : `~numpy.ndarray` instance
+            The data array that is the result of the addition
+
+        Returns
+        -------
+        result_uncertainty : NDUncertainty instance
+            The resulting uncertainty
+        '''
+        pass
+
+
+class StdDevUncertainty(NDUncertainty):
+    '''
+    A class for standard deviation uncertaintys
+    '''
+
+    support_correlated = False
+
+    def __init__(self, array=None, copy=True):
+        if array is None:
+            self.array = None
+        elif isinstance(array, StdDevUncertainty):
+            self.array = np.array(array.array, copy=copy, subok=True)
+        else:
+            self.array = np.array(array, copy=copy, subok=True)
+
+
+    @property
+    def parent_nddata(self):
+        try:
+            if self._parent_nddata is None:
+                raise MissingDataAssociationException("Uncertainty is not associated with an NDData object")
+            else:
+                return self._parent_nddata
+        except AttributeError:
+            raise MissingDataAssociationException("Uncertainty is not associated with an NDData object")
+
+
+    @parent_nddata.setter
+    def parent_nddata(self, value):
+        if self.array is None or value is None:
+            self._parent_nddata = value
+        else:
+            if value.shape != self.array.shape:
+                raise ValueError("parent shape does not match array data shape")
+
+    @property
+    def array(self):
+        return self._array
+
+    @array.setter
+    def array(self, value):
+        if value is not None:
+            try:
+                if value.shape != self.parent_nddata.shape:
+                    raise ValueError("array shape does not match parent data shape")
+            except MissingDataAssociationException:
+                pass
+        self._array = value
+
+    def propagate_add(self, other_nddata, result_data):
+        '''
+        Propagate uncertainties for addition.
+
+        Parameters
+        ----------
+        other_nddata : NDData instance
+            The data for the second other_nddata in a + b
+        result_data : `~numpy.ndarray` instance
+            The data array that is the result of the addition
+
+        Returns
+        -------
+        result_uncertainty : NDUncertainty instance
+            The resulting uncertainty
+
+        Raises
+        ------
+        IncompatibleUncertaintiesException
+            Raised if the method does not know how to propagate the uncertainties
+        '''
+
+        if not isinstance(other_nddata.uncertainty, StdDevUncertainty):
+            raise IncompatibleUncertaintiesException
+
+        if self.array is None:
+            raise ValueError("standard deviation values are not set")
+
+        if other_nddata.uncertainty.array is None:
+            raise ValueError("standard deviation values are not set in other_nddata")
+
+        result_uncertainty = StdDevUncertainty()
+        result_uncertainty.array = np.sqrt(self.array ** 2 + other_nddata.uncertainty.array ** 2)
+
+        return result_uncertainty
+
+    def __getitem__(self, item):
+        '''
+            Slice the standard deviation array using standard numpy slicing
+        '''
+
+        new_array = self.array[item]
+        return self.__class__(new_array, copy=False)
+
+    def propagate_subtract(self, other_nddata, result_data):
+        '''
+        Propagate uncertainties for subtraction.
+
+        Parameters
+        ----------
+        other_nddata : NDData instance
+            The data for the second other_nddata in a + b
+        result_data : `~numpy.ndarray` instance
+            The data array that is the result of the addition
+
+        Returns
+        -------
+        result_uncertainty : NDUncertainty instance
+            The resulting uncertainty
+
+        Raises
+        ------
+        IncompatibleUncertaintiesException
+            Raised if the method does not know how to propagate the uncertainties
+        '''
+
+        if not isinstance(other_nddata.uncertainty, StdDevUncertainty):
+            raise IncompatibleUncertaintiesException
+
+        if self.array is None:
+            raise ValueError("standard deviation values are not set")
+
+        if other_nddata.uncertainty.array is None:
+            raise ValueError("standard deviation values are not set in other_nddata")
+
+        result_uncertainty = StdDevUncertainty()
+        result_uncertainty.array = np.sqrt(self.array ** 2 + other_nddata.uncertainty.array ** 2)
+
+        return result_uncertainty
+
+    def propagate_multiply(self, other_nddata, result_data):
+        '''
+        Propagate uncertainties for mutliplication.
+
+        Parameters
+        ----------
+        other_nddata : NDData instance
+            The data for the second other_nddata in a + b
+        result_data : `~numpy.ndarray` instance
+            The data array that is the result of the addition
+
+        Returns
+        -------
+        result_uncertainty : NDUncertainty instance
+            The resulting uncertainty
+
+        Raises
+        ------
+        IncompatibleUncertaintiesException
+            Raised if the method does not know how to propagate the uncertainties
+        '''
+
+        if not isinstance(other_nddata.uncertainty, StdDevUncertainty):
+            raise IncompatibleUncertaintiesException
+
+        if self.array is None:
+            raise ValueError("standard deviation values are not set")
+
+        if other_nddata.uncertainty.array is None:
+            raise ValueError("standard deviation values are not set in other_nddata")
+
+        result_uncertainty = StdDevUncertainty()
+        result_uncertainty.array = np.sqrt((self.array / self.data) ** 2
+                               + (other_nddata.uncertainty.array / other_nddata.data) ** 2) \
+                               * result_data
+
+        return result_uncertainty
+
+    def propagate_divide(self, other_nddata, result_data):
+        '''
+        Propagate uncertainties for division.
+
+        Parameters
+        ----------
+        other_nddata : NDData instance
+            The data for the second other_nddata in a + b
+        result_data : `~numpy.ndarray` instance
+            The data array that is the result of the addition
+
+        Returns
+        -------
+        result_uncertainty : NDUncertainty instance
+            The resulting uncertainty
+
+        Raises
+        ------
+        IncompatibleUncertaintiesException
+            Raised if the method does not know how to propagate the uncertainties
+        '''
+
+        if not isinstance(other_nddata.uncertainty, StdDevUncertainty):
+            raise IncompatibleUncertaintiesException
+
+        if self.array is None:
+            raise ValueError("standard deviation values are not set")
+
+        if other_nddata.uncertainty.array is None:
+            raise ValueError("standard deviation values are not set in other_nddata")
+
+        result_uncertainty = StdDevUncertainty()
+        result_uncertainty.array = np.sqrt((self.array / self.data) ** 2
+                               + (other_nddata.uncertainty.array / other_nddata.data) ** 2) \
+                               * result_data
+
+        return result_uncertainty
diff --git a/astropy/nddata/tests/test_flag_collection.py b/astropy/nddata/tests/test_flag_collection.py
new file mode 100644
index 0000000..9d11490
--- /dev/null
+++ b/astropy/nddata/tests/test_flag_collection.py
@@ -0,0 +1,43 @@
+from ...tests.helper import pytest
+import numpy as np
+
+from .. import FlagCollection
+
+
+def test_init():
+    FlagCollection(shape=(1, 2, 3))
+
+
+def test_init_noshape():
+    with pytest.raises(Exception) as exc:
+        FlagCollection()
+    assert exc.value.args[0] == 'FlagCollection should be initialized with the shape of the data'
+
+
+def test_init_notiterable():
+    with pytest.raises(Exception) as exc:
+        FlagCollection(shape=1.)
+    assert exc.value.args[0] == 'FlagCollection shape should be an iterable object'
+
+
+def test_setitem():
+    f = FlagCollection(shape=(1, 2, 3))
+    f['a'] = np.ones((1, 2, 3)).astype(float)
+    f['b'] = np.ones((1, 2, 3)).astype(int)
+    f['c'] = np.ones((1, 2, 3)).astype(bool)
+    f['d'] = np.ones((1, 2, 3)).astype(str)
+
+
+ at pytest.mark.parametrize(('value'), [1, 1., 'spam', [1, 2, 3], (1., 2., 3.)])
+def test_setitem_invalid_type(value):
+    f = FlagCollection(shape=(1, 2, 3))
+    with pytest.raises(Exception) as exc:
+        f['a'] = value
+    assert exc.value.args[0] == 'flags should be given as a Numpy array'
+
+
+def test_setitem_invalid_shape():
+    f = FlagCollection(shape=(1, 2, 3))
+    with pytest.raises(Exception) as exc:
+        f['a'] = np.ones((3, 2, 1))
+    assert exc.value.args[0] == 'flags array shape (3, 2, 1) does not match data shape (1, 2, 3)'
diff --git a/astropy/nddata/tests/test_nddata.py b/astropy/nddata/tests/test_nddata.py
index 25698aa..0855dcf 100644
--- a/astropy/nddata/tests/test_nddata.py
+++ b/astropy/nddata/tests/test_nddata.py
@@ -1,84 +1,247 @@
 # Licensed under a 3-clause BSD style license - see LICENSE.rst
 
+import numpy as np
 
-def test_nddata_basic():
-    from numpy.random import randn, rand
-    from numpy import ones, dtype
-    from ..nddata import NDData
-    from pytest import raises
+from ..nddata import NDData
+from ..nduncertainty import StdDevUncertainty, IncompatibleUncertaintiesException, NDUncertainty
+from ...tests.helper import pytest, raises
+from ...io import fits
 
-    with raises(TypeError):
+np.random.seed(12345)
+
+
+class FakeUncertainty(NDUncertainty):
+
+    def propagate_add(self, data, final_data):
+        pass
+
+    def propagate_subtract(self, data, final_data):
+        pass
+
+    def propagate_multiply(self, data, final_data):
+        pass
+
+    def propagate_divide(self, data, final_data):
+        pass
+
+
+def test_nddata_empty():
+    with pytest.raises(TypeError):
         NDData()  # empty initializer should fail
 
-    nd1 = NDData(randn(10, 10))
-    assert nd1.shape == (10, 10)
-    assert nd1.size == 100
-    assert nd1.dtype == dtype(float)
+def test_nddata_simple():
+    nd = NDData(np.random.random((10, 10)))
+    assert nd.shape == (10, 10)
+    assert nd.size == 100
+    assert nd.dtype == np.dtype(float)
+
+
+def test_nddata_mask_valid():
+    NDData(np.random.random((10, 10)), mask=np.random.random((10, 10)) > 0.5)
 
-    # now one with error and masks
-    nd2 = NDData(randn(10, 10), rand(10, 10) / 5, ones((10, 10), dtype=bool))
 
-    with raises(ValueError):
-        #mismatched error shape
-        nd3 = NDData(randn(10, 10), rand(10, 9))
+ at pytest.mark.parametrize(('shape'), [(10,), (5, 5), (3, 10, 10)])
+def test_nddata_mask_invalid_shape(shape):
+    with pytest.raises(ValueError) as exc:
+        NDData(np.random.random((10, 10)), mask=np.random.random(shape) > 0.5)
+    assert exc.value.args[0] == 'dimensions of mask do not match data'
 
-    with raises(ValueError):
-        #mismatched mask shape
-        nd4 = NDData(randn(10, 10), mask=ones((10, 9), dtype=float))
 
+def test_nddata_uncertainty_init():
+    u =  StdDevUncertainty(array=np.ones((5, 5)))
+    d = NDData(np.ones((5, 5)), uncertainty=u)
 
-def test_nddata_copy_conv():
-    from numpy.random import randn
-    from numpy import dtype
-    from ..nddata import NDData
 
-    a = randn(10, 10)
+def test_nddata_uncertainty_init_invalid_shape_1():
+    u =  StdDevUncertainty(array=np.ones((6, 6)))
+    with pytest.raises(ValueError) as exc:
+        NDData(np.ones((5, 5)), uncertainty=u)
+    assert exc.value.args[0] == 'parent shape does not match array data shape'
 
-    #check that copy works as expected
-    ndcopy = NDData(a, copy=True)
-    ndref = NDData(a, copy=False)
+
+def test_nddata_uncertainty_init_invalid_shape_2():
+    u =  StdDevUncertainty()
+    NDData(np.ones((5, 5)), uncertainty=u)
+    with pytest.raises(ValueError) as exc:
+        u.array = np.ones((6, 6))
+    assert exc.value.args[0] == 'array shape does not match parent data shape'
+
+
+ at pytest.mark.parametrize(('uncertainty'), [1., 'spam', np.ones((5, 5))])
+def test_nddata_uncertainty_invalid_type(uncertainty):
+    with pytest.raises(TypeError) as exc:
+        NDData(np.ones((5, 5)), uncertainty=uncertainty)
+    assert exc.value.args[0] == 'Uncertainty must be an instance of a NDUncertainty object'
+
+
+def test_nddata_copy():
+    a = np.ones((10, 10))
+    nd_copy = NDData(a, copy=True)
+    nd_ref = NDData(a, copy=False)
     a[0, 0] = 0
-    assert ndref.data[0, 0] == 0
-    assert ndcopy.data[0, 0] != 0
-
-    #conversion
-    nd3 = NDData([[1, 2, 3], [4, 5, 6]])
-    assert nd3.size == 6
-    assert nd3.dtype == dtype(int)
-
-
-def test_boolmask():
-    from numpy.random import rand, randn
-    from numpy import array, arange, all
-    from ..nddata import NDData
-    import random
-    import string
-
-    a = randn(10, 10)
-    bm = randn(10, 10) > 0  # random mask that boolmask should look like
-
-    nd1 = NDData(randn(10, 10), mask=~bm)  # mask False where valid
-    assert all(nd1.boolmask == bm)
-
-    #scalar mask 0 where valid
-    im = arange(100).reshape((10, 10)) + 1
-    im[bm] = 0
-    nd2 = NDData(randn(10, 10), mask=im)
-    assert all(nd2.boolmask == bm)
-
-    #generate a list of random strings
-    strlst = []
-    for N in rand(100) * 9 + 1:
-        sl = [random.choice(string.ascii_letters) for x in range(int(N))]
-        strlst.append(''.join(sl))
-
-    #string mask '' where valid
-    strmsk = array(strlst).reshape((10, 10))
-    strmsk[bm] = ''
-    nd3 = NDData(randn(10, 10), mask=strmsk)
-    assert all(nd3.boolmask == bm)
-    #do it with unicode too for goo measure
-    umsk = array([unicode(s) for s in strlst]).reshape((10, 10))
-    umsk[bm] = ''
-    nd3 = NDData(randn(10, 10), mask=umsk)
-    assert all(nd3.boolmask == bm)
+    assert nd_ref.data[0, 0] == 0
+    assert nd_copy.data[0, 0] == 1
+
+
+def test_nddata_conversion():
+    nd = NDData([[1, 2, 3], [4, 5, 6]])
+    assert nd.size == 6
+    assert nd.dtype == np.dtype(int)
+
+
+def test_nddata_add():
+    d1 = NDData(np.ones((5, 5)))
+    d2 = NDData(np.ones((5, 5)))
+    d3 = d1.add(d2)
+    assert np.all(d3.data == 2.)
+
+
+def test_nddata_add_mismatch_wcs():
+    d1 = NDData(np.ones((5, 5)), wcs=1.)
+    d2 = NDData(np.ones((5, 5)), wcs=2.)
+    with pytest.raises(ValueError) as exc:
+        d1.add(d2)
+    assert exc.value.args[0] == "WCS properties do not match"
+
+
+def test_nddata_add_mismatch_units():
+    d1 = NDData(np.ones((5, 5)), units='Jy')
+    d2 = NDData(np.ones((5, 5)), units='erg/s')
+    with pytest.raises(ValueError) as exc:
+        d1.add(d2)
+    assert exc.value.args[0] == "operand units do not match"
+
+
+def test_nddata_add_mismatch_shape():
+    d1 = NDData(np.ones((5, 5)))
+    d2 = NDData(np.ones((6, 6)))
+    with pytest.raises(ValueError) as exc:
+        d1.add(d2)
+    assert exc.value.args[0] == "operand shapes do not match"
+
+
+def test_nddata_add_uncertainties():
+    u1 = StdDevUncertainty(array=np.ones((5, 5)) * 3)
+    u2 = StdDevUncertainty(array=np.ones((5, 5)))
+    d1 = NDData(np.ones((5, 5)), uncertainty=u1)
+    d2 = NDData(np.ones((5, 5)), uncertainty=u2)
+    d3 = d1.add(d2)
+    assert np.all(d3.data == 2.)
+    assert np.all(d3.uncertainty.array == np.sqrt(10.))
+
+
+def test_nddata_add_uncertainties_mismatch():
+    u1 = StdDevUncertainty(array=np.ones((5, 5)) * 3)
+    u2 = FakeUncertainty()
+    print u2.__class__
+    d1 = NDData(np.ones((5, 5)), uncertainty=u1)
+    d2 = NDData(np.ones((5, 5)), uncertainty=u2)
+    with pytest.raises(IncompatibleUncertaintiesException) as exc:
+        d3 = d1.add(d2)
+    assert exc.value.args[0] == 'Cannot propagate uncertainties of type StdDevUncertainty with uncertainties of type FakeUncertainty for addition'
+
+
+def test_nddata_subtract():
+    d1 = NDData(np.ones((5, 5)))
+    d2 = NDData(np.ones((5, 5)) * 2.)
+    d3 = d1.subtract(d2)
+    assert np.all(d3.data == -1.)
+
+
+def test_nddata_subtract_mismatch_wcs():
+    d1 = NDData(np.ones((5, 5)), wcs=1.)
+    d2 = NDData(np.ones((5, 5)) * 2., wcs=2.)
+    with pytest.raises(ValueError) as exc:
+        d1.subtract(d2)
+    assert exc.value.args[0] == "WCS properties do not match"
+
+
+def test_nddata_subtract_mismatch_units():
+    d1 = NDData(np.ones((5, 5)), units='Jy')
+    d2 = NDData(np.ones((5, 5)) * 2., units='erg/s')
+    with pytest.raises(ValueError) as exc:
+        d1.subtract(d2)
+    assert exc.value.args[0] == "operand units do not match"
+
+
+def test_nddata_subtract_mismatch_shape():
+    d1 = NDData(np.ones((5, 5)))
+    d2 = NDData(np.ones((6, 6)) * 2.)
+    with pytest.raises(ValueError) as exc:
+        d1.subtract(d2)
+    assert exc.value.args[0] == "operand shapes do not match"
+
+
+def test_nddata_subtract_uncertainties():
+    u1 = StdDevUncertainty(array=np.ones((5, 5)) * 3)
+    u2 = StdDevUncertainty(array=np.ones((5, 5)))
+    d1 = NDData(np.ones((5, 5)), uncertainty=u1)
+    d2 = NDData(np.ones((5, 5)) * 2., uncertainty=u2)
+    d3 = d1.subtract(d2)
+    assert np.all(d3.data == -1.)
+    assert np.all(d3.uncertainty.array == np.sqrt(10.))
+
+
+def test_nddata_subtract_uncertainties_mismatch():
+    u1 = StdDevUncertainty(array=np.ones((5, 5)) * 3)
+    u2 = FakeUncertainty()
+    print u2.__class__
+    d1 = NDData(np.ones((5, 5)), uncertainty=u1)
+    d2 = NDData(np.ones((5, 5)) * 2., uncertainty=u2)
+    with pytest.raises(IncompatibleUncertaintiesException) as exc:
+        d3 = d1.subtract(d2)
+    assert exc.value.args[0] == 'Cannot propagate uncertainties of type StdDevUncertainty with uncertainties of type FakeUncertainty for subtraction'
+
+
+def test_convert_units_to():
+    d = NDData(np.ones((5, 5)))
+    d.units = 'km'
+    d1 = d.convert_units_to('m')
+    assert np.all(d1 == np.array(1000.0))
+
+
+ at raises(ValueError)
+def test_invalid_unit():
+    d = NDData(np.ones((5, 5)), units="NotAValidUnit")
+
+def test_simple_slicing():
+    u1 = StdDevUncertainty(array=np.ones((5, 5)) * 3)
+    d1 = NDData(np.ones((5, 5)), uncertainty=u1)
+    assert d1.shape == (5,5)
+    d2 = d1[2:3, 2:3]
+    assert d2.shape == (1,1)
+
+def test_slicing_reference():
+    u1 = StdDevUncertainty(array=np.ones((5, 5)) * 3)
+    d1 = NDData(np.ones((5, 5)), uncertainty=u1)
+    d2 = d1[2:3, 2:3]
+    #asserting that the new nddata contains references to the original nddata
+    assert d2.data.base is d1.data
+    assert d2.uncertainty.array.base is d1.uncertainty.array
+
+
+def test_initializing_from_nddata():
+    d1 = NDData(np.ones((5, 5)))
+    d2 = NDData(d1, copy=False)
+
+    assert d1.data is d2.data
+
+
+def test_initializing_from_nduncertainty():
+    u1 = StdDevUncertainty(np.ones((5, 5)) * 3)
+    u2 = StdDevUncertainty(u1, copy=False)
+
+    assert u1.array is u2.array
+
+def test_meta2ordered_dict():
+    hdr = fits.header.Header()
+    hdr.set('observer', 'Edwin Hubble')
+    hdr.set('exptime', '3600')
+
+    d1 = NDData(np.ones((5, 5)), meta=hdr)
+    assert d1.meta['OBSERVER'] == 'Edwin Hubble'
+
+ at raises(TypeError)
+def test_meta2ordered_dict_fail():
+    hdr = 'this is not a valid header'
+    d1 = NDData(np.ones((5, 5)), meta=hdr)
diff --git a/astropy/setup_helpers.py b/astropy/setup_helpers.py
index 7fdb919..1980592 100644
--- a/astropy/setup_helpers.py
+++ b/astropy/setup_helpers.py
@@ -4,20 +4,27 @@ This module contains a number of utilities for use during
 setup/build/packaging that are useful to astropy as a whole.
 """
 
-from __future__ import absolute_import
+from __future__ import absolute_import, print_function
 
+import errno
 import imp
 import os
 import shutil
+import subprocess
 import sys
 import re
 import shlex
 
 from distutils import log
 from distutils.dist import Distribution
-from distutils.errors import DistutilsError
+from distutils.errors import DistutilsError, DistutilsFileError
 from distutils.core import Extension
-from distutils.log import warn
+from distutils.core import Command
+from distutils.command.build import build as DistutilsBuild
+from distutils.command.install import install as DistutilsInstall
+from distutils.command.build_ext import build_ext as DistutilsBuildExt
+
+from setuptools.command.register import register as SetuptoolsRegister
 
 from .tests.helper import astropy_test
 
@@ -28,16 +35,233 @@ try:
 except ImportError:
     HAVE_CYTHON = False
 
+
 try:
-    from numpy import get_include as get_numpy_include
-    numpy_includes = get_numpy_include()
+    import sphinx
+    from sphinx.setup_command import BuildDoc as SphinxBuildDoc
+    HAVE_SPHINX = True
 except ImportError:
-    numpy_includes = []
+    HAVE_SPHINX = False
 
-try:
-    from sphinx.setup_command import BuildDoc
 
-    class AstropyBuildSphinx(BuildDoc):
+class AstropyBuild(DistutilsBuild):
+    """
+    A custom 'build' command that allows for adding extra build
+    options.
+    """
+    user_options = DistutilsBuild.user_options[:]
+    boolean_options = DistutilsBuild.boolean_options[:]
+    custom_options = []
+
+    def initialize_options(self):
+        DistutilsBuild.initialize_options(self)
+        # Create member variables for all of the custom options that
+        # were added.
+        for option in self.custom_options:
+            setattr(self, option.replace('-', '_'), None)
+
+    @classmethod
+    def add_build_option(cls, name, doc, is_bool=False):
+        """
+        Add a build option.
+
+        Parameters
+        ----------
+        name : str
+            The name of the build option
+
+        doc : str
+            A short description of the option, for the `--help` message.
+
+        is_bool : bool, optional
+            When `True`, the option is a boolean option and doesn't
+            require an associated value.
+        """
+        if name in cls.custom_options:
+            return
+
+        if is_bool:
+            cls.boolean_options.append(name)
+        else:
+            name = name + '='
+        cls.user_options.append((name, None, doc))
+        cls.custom_options.append(name)
+
+
+class AstropyInstall(DistutilsInstall):
+    """
+    A custom 'install' command that allows for adding extra install
+    options.
+    """
+    user_options = DistutilsInstall.user_options[:]
+    boolean_options = DistutilsInstall.boolean_options[:]
+    custom_options = []
+
+    def initialize_options(self):
+        DistutilsInstall.initialize_options(self)
+        # Create member variables for all of the custom options that
+        # were added.
+        for option in self.custom_options:
+            setattr(self, option.replace('-', '_'), None)
+
+    @classmethod
+    def add_install_option(cls, name, doc, is_bool=False):
+        """
+        Add a install option.
+
+        Parameters
+        ----------
+        name : str
+            The name of the install option
+
+        doc : str
+            A short description of the option, for the `--help` message.
+
+        is_bool : bool, optional
+            When `True`, the option is a boolean option and doesn't
+            require an associated value.
+        """
+        if name in cls.custom_options:
+            return
+
+        if is_bool:
+            cls.boolean_options.append(name)
+        else:
+            name = name + '='
+        cls.user_options.append((name, None, doc))
+        cls.custom_options.append(name)
+
+
+class AstropyRegister(SetuptoolsRegister):
+    """Extends the built in 'register' command to support a ``--hidden`` option
+    to make the registered version hidden on PyPI by default.
+
+    The result of this is that when a version is registered as "hidden" it can
+    still be downloaded from PyPI, but it does not show up in the list of
+    actively supported versions under http://pypi.python.org/pypi/astropy, and
+    is not set as the most recent version.
+
+    Although this can always be set through the web interface it may be more
+    convenient to be able to specify via the 'register' command.  Hidden may
+    also be considered a safer default when running the 'register' command,
+    though this command uses distutils' normal behavior if the ``--hidden``
+    option is omitted.
+    """
+
+    user_options = SetuptoolsRegister.user_options + [
+        ('hidden', None, 'mark this release as hidden on PyPI by default')
+    ]
+    boolean_options = SetuptoolsRegister.boolean_options + ['hidden']
+
+    def initialize_options(self):
+        SetuptoolsRegister.initialize_options(self)
+        self.hidden = False
+
+    def build_post_data(self, action):
+        data = SetuptoolsRegister.build_post_data(self, action)
+        if action == 'submit' and self.hidden:
+            data['_pypi_hidden'] = '1'
+        return data
+
+    def _set_config(self):
+        # The original register command is buggy--if you use .pypirc with a
+        # server-login section *at all* the repository you specify with the -r
+        # option will be overwritten with either the repository in .pypirc or
+        # with the default,
+        # If you do not have a .pypirc using the -r option will just crash.
+        # Way to go distutils
+
+        # If we don't set self.repository back to a default value _set_config
+        # can crash if there was a user-supplied value for this option; don't
+        # worry, we'll get the real value back afterwards
+        self.repository = 'pypi'
+        SetuptoolsRegister._set_config(self)
+        options = self.distribution.get_option_dict('register')
+        if 'repository' in options:
+            source, value = options['repository']
+            # Really anything that came from setup.cfg or the command line
+            # should override whatever was in .pypirc
+            self.repository = value
+
+# Need to set the name here so that the commandline options
+# are presented as being related to the "build" command, for example; this
+# only affects the display of the help text, which does not obtain the the
+# command name in the correct way.
+AstropyBuild.__name__ = 'build'
+AstropyInstall.__name__ = 'install'
+AstropyRegister.__name__ = 'register'
+
+
+def wrap_build_ext(basecls=DistutilsBuildExt):
+    """
+    Creates a custom 'build_ext' command that allows for manipulating some of
+    the C extension options at build time.  We use a function to build the
+    class since the base class for build_ext may be different depending on
+    certain build-time parameters (for example, we may use Cython's build_ext
+    instead of the default version in distutils).
+
+    Uses the default distutils.command.build_ext by default.
+    """
+
+    attrs = dict(basecls.__dict__)
+    orig_run = getattr(basecls, 'run', None)
+
+    def run(self):
+        from astropy.version import release
+        # For extensions that require 'numpy' in their include dirs, replace
+        # 'numpy' with the actual paths
+        np_include = get_numpy_include_path()
+        for extension in self.extensions:
+            if 'numpy' in extension.include_dirs:
+                idx = extension.include_dirs.index('numpy')
+                extension.include_dirs.insert(idx, np_include)
+                extension.include_dirs.remove('numpy')
+
+            # Replace .pyx with C-equivalents, unless c files are missing
+            for jdx, src in enumerate(extension.sources):
+                if src.endswith('.pyx'):
+                    pyxfn = src
+                    cfn = src[:-4] + '.c'
+                elif src.endswith('.c'):
+                    pyxfn = src[:-2] + '.pyx'
+                    cfn = src
+
+                if os.path.isfile(pyxfn):
+                    if HAVE_CYTHON and not release:
+                        extension.sources[jdx] = pyxfn
+                    else:
+                        if os.path.isfile(cfn):
+                            extension.sources[jdx] = cfn
+                        else:
+                            msg = (
+                                'Could not find C file {0} for Cython file '
+                                '{1} when building extension {2}. '
+                                'Cython must be installed to build from a '
+                                'git checkout'.format(cfn, pyxfn,
+                                                      extension.name))
+                            raise IOError(errno.ENOENT, msg, cfn)
+
+        if orig_run is not None:
+            # This should always be the case for a correctly implemented
+            # distutils command.
+            orig_run(self)
+
+    attrs['run'] = run
+
+    return type('build_ext', (basecls, object), attrs)
+
+
+for option in [
+        ('enable-legacy',
+         "Install legacy shims", True),
+        ('use-system-libraries',
+         "Use system libraries whenever possible", True)]:
+    AstropyBuild.add_build_option(*option)
+    AstropyInstall.add_install_option(*option)
+
+
+if HAVE_SPHINX:
+    class AstropyBuildSphinx(SphinxBuildDoc):
         """ A version of the ``build_sphinx`` command that uses the
         version of Astropy that is built by the setup ``build`` command,
         rather than whatever is installed on the system - to build docs
@@ -50,17 +274,29 @@ try:
         """
 
         description = 'Build Sphinx documentation for Astropy environment'
-        user_options = BuildDoc.user_options[:]
-        user_options.append(('clean-docs', 'l', 'Clean previously-built docs '
-                                                'before building new ones'))
-        boolean_options = BuildDoc.boolean_options[:]
+        user_options = SphinxBuildDoc.user_options[:]
+        user_options.append(('clean-docs', 'l', 'Completely clean previously '
+                                                'builds, including auotmodapi-'
+                                                'generated files before '
+                                                'building new ones'))
+        user_options.append(('no-intersphinx', 'n', 'Skip intersphinx, even if '
+                                                    'conf.py says to use it'))
+        user_options.append(('open-docs-in-browser', 'o', 'Open the docs in a '
+                                'browser (using the webbrowser module) if the '
+                                'build finishes successfully.'))
+
+        boolean_options = SphinxBuildDoc.boolean_options[:]
         boolean_options.append('clean-docs')
+        boolean_options.append('no-intersphinx')
+        boolean_options.append('open-docs-in-browser')
 
         _self_iden_rex = re.compile(r"self\.([^\d\W][\w]+)", re.UNICODE)
 
         def initialize_options(self):
-            BuildDoc.initialize_options(self)
+            SphinxBuildDoc.initialize_options(self)
             self.clean_docs = False
+            self.no_intersphinx = False
+            self.open_docs_in_browser = False
 
         def finalize_options(self):
             from os.path import isdir
@@ -82,14 +318,16 @@ try:
                         log.info('Not cleaning directory ' + d + ' because '
                                  'not present or not a directory')
 
-            BuildDoc.finalize_options(self)
+            SphinxBuildDoc.finalize_options(self)
 
         def run(self):
-            from os.path import split, join
+            from os.path import split, join, abspath
             from distutils.cmd import DistutilsOptionError
             from subprocess import Popen, PIPE
             from textwrap import dedent
             from inspect import getsourcelines
+            from urllib import pathname2url
+            import webbrowser
 
             # If possible, create the _static dir
             if self.build_dir is not None:
@@ -116,7 +354,7 @@ try:
             #command.  This is needed to get the correct imports for the built
             #version
 
-            runlines, runlineno = getsourcelines(BuildDoc.run)
+            runlines, runlineno = getsourcelines(SphinxBuildDoc.run)
             subproccode = dedent("""
             from sphinx.setup_command import *
 
@@ -141,20 +379,33 @@ try:
                     subproccode[i] = repr(val)
             subproccode = ''.join(subproccode)
 
+            if self.no_intersphinx:
+                #the confoverrides variable in sphinx.setup_command.BuildDoc can
+                #be used to override the conf.py ... but this could well break
+                #if future versions of sphinx change the internals of BuildDoc,
+                #so remain vigilant!
+                subproccode = subproccode.replace('confoverrides = {}',
+                    'confoverrides = {\'intersphinx_mapping\':{}}')
+
             log.debug('Starting subprocess of {0} with python code:\n{1}\n'
                       '[CODE END])'.format(sys.executable, subproccode))
 
             proc = Popen([sys.executable], stdin=PIPE)
             proc.communicate(subproccode)
-            if proc.returncode != 0:
+            if proc.returncode == 0:
+                if self.open_docs_in_browser:
+                    if self.builder == 'html':
+                        absdir = abspath(self.builder_target_dir)
+                        fileurl = 'file://' + pathname2url(join(absdir, 'index.html'))
+                        webbrowser.open(fileurl)
+                    else:
+                        log.warn('open-docs-in-browser option was given, but '
+                                 'the builder is not html! Ignogring.')
+            else:
                 log.warn('Sphinx Documentation subprocess failed with return '
                          'code ' + str(proc.returncode))
 
-except ImportError as e:
-    if 'sphinx' in e.args[0]:  # Sphinx not present
-        AstropyBuildSphinx = None
-    else:
-        raise
+    AstropyBuildSphinx.__name__ = 'build_sphinx'
 
 
 def get_distutils_display_options():
@@ -172,6 +423,11 @@ def get_distutils_display_options():
                              if o[1])
     long_display_opts = set('--' + o[0] for o in Distribution.display_options)
 
+    # Include -h and --help which are not explicitly listed in
+    # Distribution.display_options (as they are handled by optparse)
+    short_display_opts.add('-h')
+    long_display_opts.add('--help')
+
     return short_display_opts.union(long_display_opts)
 
 
@@ -184,6 +440,7 @@ def is_distutils_display_option():
     return bool(set(sys.argv[1:]).intersection(display_options))
 
 
+cmdclassd = {}
 def get_distutils_option(option, commands):
     """ Returns the value of the given distutils option.
 
@@ -209,6 +466,8 @@ def get_distutils_option(option, commands):
     # if the option is set.
     dist = Distribution({'script_name': os.path.basename(sys.argv[0]),
                          'script_args': args})
+    dist.cmdclass.update(cmdclassd)
+
     try:
         dist.parse_config_files()
         dist.parse_command_line()
@@ -233,6 +492,58 @@ def get_distutils_option(option, commands):
         return None
 
 
+def get_distutils_build_option(option):
+    """ Returns the value of the given distutils build option.
+
+    Parameters
+    ----------
+    option : str
+        The name of the option
+
+    Returns
+    -------
+    val : str or None
+        The value of the given distutils build option. If the option
+        is not set, returns None.
+    """
+    return get_distutils_option(option, ['build', 'build_ext', 'build_clib'])
+
+
+def get_distutils_install_option(option):
+    """ Returns the value of the given distutils install option.
+
+    Parameters
+    ----------
+    option : str
+        The name of the option
+
+    Returns
+    -------
+    val : str or None
+        The value of the given distutils build option. If the option
+        is not set, returns None.
+    """
+    return get_distutils_option(option, ['install'])
+
+
+def get_distutils_build_or_install_option(option):
+    """ Returns the value of the given distutils build or install option.
+
+    Parameters
+    ----------
+    option : str
+        The name of the option
+
+    Returns
+    -------
+    val : str or None
+        The value of the given distutils build or install option. If the
+        option is not set, returns None.
+    """
+    return get_distutils_option(option, ['build', 'build_ext', 'build_clib',
+                                         'install'])
+
+
 def get_compiler_option():
     """ Determines the compiler that will be used to build extension modules.
 
@@ -245,8 +556,7 @@ def get_compiler_option():
 
     """
 
-    compiler = get_distutils_option('compiler',
-                                    ['build', 'build_ext', 'build_clib'])
+    compiler = get_distutils_build_option('compiler')
     if compiler is None:
         import distutils.ccompiler
         return distutils.ccompiler.get_default_compiler()
@@ -265,8 +575,7 @@ def get_debug_option():
 
     """
 
-    debug = bool(get_distutils_option(
-        'debug', ['build', 'build_ext', 'build_clib']))
+    debug = bool(get_distutils_build_option('debug'))
 
     try:
         from astropy.version import debug as current_debug
@@ -285,14 +594,19 @@ def update_package_files(srcdir, extensions, package_data, packagenames,
     """ Extends existing extensions, package_data, packagenames and
     package_dirs collections by iterating through all packages in
     ``srcdir`` and locating a ``setup_package.py`` module.  This
-    module can contain any of three functions: ``get_extensions()``,
-    ``get_package_data()``, and ``get_legacy_alias()``.
+    module can contain the following functions: ``get_extensions()``,
+    ``get_package_data()``, ``get_legacy_alias()``,
+    ``get_build_options()``, and ``get_external_libraries()``.
 
     Each of those functions take no arguments.  ``get_extensions``
     returns a list of `distutils.extension.Extension` objects.
     ``get_package_data()`` returns a dict formatted as required by the
     ``package_data`` argument to ``setup()``.  ``get_legacy_alias()``
     should call `add_legacy_alias` and return its result.
+    ``get_build_options()`` returns a list of tuples describing the
+    extra build options to add.  ``get_external_libraries()`` returns
+    a list of libraries that can optionally be built using external
+    dependencies.
 
     The purpose of this function is to allow subpackages to update the
     arguments to the package's ``setup()`` function in its setup.py
@@ -301,31 +615,55 @@ def update_package_files(srcdir, extensions, package_data, packagenames,
     setup.py rather than returning new ones.  See Astropy's own
     ``setup.py`` for example usage and the Astropy development docs
     for more details.
-
     """
 
-    from astropy.version import release
+    # For each of the setup_package.py modules, extract any
+    # information that is needed to install them.  The build options
+    # are extracted first, so that their values will be available in
+    # subsequent calls to `get_extensions`, etc.
+    for setuppkg in iter_setup_packages(srcdir):
+        if hasattr(setuppkg, 'get_build_options'):
+            options = setuppkg.get_build_options()
+            for option in options:
+                AstropyBuild.add_build_option(*option)
+        if hasattr(setuppkg, 'get_external_libraries'):
+            libraries = setuppkg.get_external_libraries()
+            for library in libraries:
+                add_external_library(library)
+
+    # Check if all the legacy packages are needed
+    if get_distutils_build_or_install_option('enable_legacy'):
+        installed = []
+        for setuppkg in iter_setup_packages(srcdir):
+            if hasattr(setuppkg, 'get_legacy_alias'):
+                pkg, dir = setuppkg.get_legacy_alias()
+                if dir is None:
+                    installed.append(pkg)
+                else:
+                    packagenames.append(pkg)
+                    package_dirs[pkg] = dir
+        if len(installed) > 0:
+            print('-' * 60)
+            print("The compatibility packages cannot be installed because the\n"
+                  "following legacy packages are already installed:\n")
+            for pkg in installed:
+                print("    * {0:s}".format(pkg))
+            print("\nThe compatibility packages can only installed if none of"
+                  " the\ncorresponding legacy packages are present.")
+            print('-' * 60)
+            sys.exit(1)
 
-    # For each of the setup_package.py modules, extract any information that is
-    # needed to install them.
     for setuppkg in iter_setup_packages(srcdir):
         # get_extensions must include any Cython extensions by their .pyx
         # filename.
         if hasattr(setuppkg, 'get_extensions'):
             extensions.extend(setuppkg.get_extensions())
-
         if hasattr(setuppkg, 'get_package_data'):
             package_data.update(setuppkg.get_package_data())
-        if hasattr(setuppkg, 'get_legacy_alias'):
-            pkg, dir = setuppkg.get_legacy_alias()
-            if pkg is not None:
-                packagenames.append(pkg)
-                package_dirs[pkg] = dir
 
     # Locate any .pyx files not already specified, and add their extensions in.
     # The default include dirs include numpy to facilitate numerical work.
-    extensions.extend(get_cython_extensions(srcdir, extensions,
-                                            [numpy_includes]))
+    extensions.extend(get_cython_extensions(srcdir, extensions, ['numpy']))
 
     # Now remove extensions that have the special name 'skip_cython', as they
     # exist Only to indicate that the cython extensions shouldn't be built
@@ -333,26 +671,6 @@ def update_package_files(srcdir, extensions, package_data, packagenames,
         if ext.name == 'skip_cython':
             del extensions[i]
 
-    if release or not HAVE_CYTHON:
-        # Replace .pyx with C-equivalents, unless c files are missing
-        for idx, ext in reversed(list(enumerate(extensions))):
-            for jdx, src in enumerate(ext.sources):
-                if src.endswith('.pyx'):
-                    pyxfn = src
-                    cfn = src[:-4] + '.c'
-                elif src.endswith('.c'):
-                    pyxfn = src[:-2] + '.pyx'
-                    cfn = src
-                if os.path.isfile(pyxfn):
-                    if os.path.isfile(cfn):
-                        ext.sources[jdx] = cfn
-                    else:
-                        raise IOError(
-                            'Could not find C file {0} for Cython file {1} '
-                            'when building extension {2}. '
-                            'Cython must be installed to build from a git '
-                            'checkout'.format(cfn, pyxfn, ext.name))
-
     # On Microsoft compilers, we need to pass the '/MANIFEST'
     # commandline argument.  This was the default on MSVC 9.0, but is
     # now required on MSVC 10.0, but it doesn't seeem to hurt to add
@@ -468,19 +786,30 @@ def check_numpy():
     Check that Numpy is installed and it is of the minimum version we
     require.
     """
-    import numpy
 
-    major, minor, rest = numpy.__version__.split(".", 2)
-    if (int(major), int(minor)) < (1, 4):
+    requirement_met = False
+
+    try:
+        import numpy
+    except ImportError:
+        pass
+    else:
+        major, minor, rest = numpy.__version__.split(".", 2)
+        requirement_met = (int(major), int(minor)) >= (1, 4)
+
+    if not requirement_met:
         msg = "numpy version 1.4 or later must be installed to build astropy"
         raise ImportError(msg)
 
+    return numpy
+
 
 def get_numpy_include_path():
     """
     Gets the path to the numpy headers.
     """
-    import numpy
+
+    numpy = check_numpy()
 
     try:
         numpy_include = numpy.get_include()
@@ -511,6 +840,13 @@ def adjust_compiler():
     to.
     """
 
+    from distutils import ccompiler, sysconfig
+    import re
+
+    compiler_mapping = [
+        (b'i686-apple-darwin[0-9]*-llvm-gcc-4.2', 'clang')
+        ]
+
     global _adjusted_compiler
     if _adjusted_compiler:
         return
@@ -519,19 +855,19 @@ def adjust_compiler():
     _adjusted_compiler = True
 
     if 'CC' in os.environ:
-        return
 
-    if get_distutils_option(
-        'compiler', ['build', 'build_ext', 'build_clib']) is not None:
-        return
+        # Check that CC is not set to llvm-gcc-4.2
+        c_compiler = os.environ['CC']
 
-    from distutils import ccompiler, sysconfig
-    import subprocess
-    import re
+        version = get_compiler_version(c_compiler)
 
-    compiler_mapping = [
-        (b'i686-apple-darwin[0-9]*-llvm-gcc-4.2', 'clang')
-        ]
+        for broken, fixed in compiler_mapping:
+            if re.match(broken, version):
+                print("Compiler specified by CC environment variable ({0:s}: {1:s}) will fail to compile Astropy. Please set CC={2:s} and try again. You can do this for example by doing:\n\n    CC={2:s} python setup.py <command>\n\nwhere <command> is the command you ran.".format(c_compiler, version, fixed))
+                sys.exit(1)
+
+    if get_distutils_build_option('compiler'):
+        return
 
     compiler_type = ccompiler.get_default_compiler()
 
@@ -543,53 +879,24 @@ def adjust_compiler():
         # compiler as returned by ccompiler.new_compiler()
         c_compiler = sysconfig.get_config_var('CC')
 
-        process = subprocess.Popen(
-            shlex.split(c_compiler) + ['--version'], stdout=subprocess.PIPE)
-        output = process.communicate()[0].strip()
-        version = output.split()[0]
+        version = get_compiler_version(c_compiler)
+
         for broken, fixed in compiler_mapping:
             if re.match(broken, version):
                 os.environ['CC'] = fixed
                 break
 
+def get_compiler_version(compiler):
 
-def is_in_build_mode():
-    """
-    Determines if the current package is being built.
-
-    Returns
-    -------
-    buildmode : bool
-        True if the current package is in the process of being built.
-
-    See Also
-    --------
-    `set_build_mode`
-    """
-    #_ASTROPY_SETUP_ is added to the builtins in setup.py or astropy/__init__.py
-    return _ASTROPY_SETUP_
-
+    import subprocess
 
-def set_build_mode(val=True):
-    """
-    Sets whether or not the current package is being built.
+    process = subprocess.Popen(
+    shlex.split(compiler) + ['--version'], stdout=subprocess.PIPE)
 
-    Parameters
-    ----------
-    val : bool
-        Whether or not build mode should be activated.
+    output = process.communicate()[0].strip()
+    version = output.split()[0]
 
-    See Also
-    --------
-    `is_in_build_mode`
-    """
-    from sys import version_info
-
-    if version_info[0] >= 3:
-        import builtins
-    else:
-        import __builtin__ as builtins
-    builtins._ASTROPY_SETUP_ = val
+    return version
 
 
 def setup_test_command(package_name):
@@ -667,7 +974,7 @@ def add_legacy_alias(old_package, new_package, equiv_version, extras={}):
 
     For example::
 
-       add_legacy_alias('astropy.io.vo', 'vo')
+       add_legacy_alias('astropy.io.votable', 'vo')
 
     If the legacy package is importable and it is not merely the
     compatibility shim, a warning is printed to the user, and the
@@ -701,6 +1008,11 @@ def add_legacy_alias(old_package, new_package, equiv_version, extras={}):
     """
     import imp
 
+    # If legacy shims have not been enabled at the commandline, simply do
+    # nothing.
+    if not get_distutils_build_or_install_option('enable_legacy'):
+        return (old_package, None)
+
     found_legacy_module = True
     try:
         location = imp.find_module(old_package)
@@ -724,15 +1036,9 @@ def add_legacy_alias(old_package, new_package, equiv_version, extras={}):
     shim_dir = os.path.join(get_legacy_alias_dir(), old_package)
 
     if found_legacy_module and not is_distutils_display_option():
-        warn('-' * 60)
-        warn("The legacy package '{0}' was found.".format(old_package))
-        warn("To install astropy's compatibility layer instead, uninstall")
-        warn("'{0}' and then reinstall astropy.".format(old_package))
-        warn('-' * 60)
-
         if os.path.isdir(shim_dir):
             shutil.rmtree(shim_dir)
-        return (None, None)
+        return (old_package, None)
 
     if extras:
         extras = '\n'.join('{0} = {1!r}'.format(*v) for v in extras.items())
@@ -746,3 +1052,224 @@ def add_legacy_alias(old_package, new_package, equiv_version, extras={}):
         os.path.join(shim_dir, '__init__.py'), content)
 
     return (old_package, shim_dir)
+
+
+def pkg_config(
+        packages, default_libraries, include_dirs, library_dirs,
+        libraries):
+    """
+    Uses pkg-config to update a set of distutils Extension arguments
+    to include the flags necessary to link against the given packages.
+
+    If the pkg-config lookup fails, default_libraries is applied to
+    libraries.
+
+    Parameters
+    ----------
+    packages : list of str
+        A list of pkg-config packages to look up.
+
+    default_libraries : list of str
+        A list of library names to use if the pkg-config lookup fails.
+
+    include_dirs : list of str
+        A list of include directories that will be updated to include
+        the results from pkg-config.
+
+    library_dirs : list of str
+        A list of library directories that will be updated to include
+        the results from pkg-config.
+
+    libraries : list of str
+        A list of library names that will be updated to include the
+        results from pkg-config, or if pkg-config fails, updated from
+        *default_libraries*.
+    """
+    flag_map = {'-I': 'include_dirs', '-L': 'library_dirs', '-l': 'libraries'}
+    command = "pkg-config --libs --cflags {0}".format(' '.join(packages)),
+
+    try:
+        output = subprocess.check_output(command, shell=True)
+    except subprocess.CalledProcessError:
+        libraries.extend(default_libraries)
+    else:
+        for token in output.split():
+            locals()[flag_map.get(token[:2])].append(token[2:])
+
+
+def add_external_library(library):
+    """
+    Add a build option for selecting the internal or system copy of a library.
+
+    Parameters
+    ----------
+    library : str
+        The name of the library.  If the library is `foo`, the build
+        option will be called `--use-system-foo`.
+    """
+    AstropyBuild.add_build_option(
+        'use-system-{0}'.format(library),
+        'Use the system {0} library'.format(library),
+        is_bool=True)
+    AstropyInstall.add_install_option(
+        'use-system-{0}'.format(library),
+        'Use the system {0} library'.format(library),
+        is_bool=True)
+
+
+def use_system_library(library):
+    """
+    Returns `True` if the build configuration indicates that the given
+    library should use the system copy of the library rather than the
+    internal one.
+
+    For the given library `foo`, this will be `True` if
+    `--use-system-foo` or `--use-system-libraries` was provided at the
+    commandline or in `setup.cfg`.
+
+    Parameters
+    ----------
+    library : str
+        The name of the library
+
+    Returns
+    -------
+    use_system : bool
+        `True` if the build should use the system copy of the library.
+    """
+    return (
+        get_distutils_build_or_install_option('use_system_{0}'.format(library))
+        or get_distutils_build_or_install_option('use_system_libraries'))
+
+
+def filter_packages(packagenames):
+    """
+    Removes some packages from the package list that shouldn't be
+    installed on the current version of Python.
+    """
+    if sys.version_info[0] >= 3:
+        exclude = '_py2'
+    else:
+        exclude = '_py3'
+
+    return [x for x in packagenames if not x.endswith(exclude)]
+
+
+class bdist_dmg(Command):
+    """
+    The bdist_dmg command is used to produce the disk image containing the
+    installer, and with a custom background and icon placement.
+    """
+
+    user_options = [
+                    ('background=', 'b', "background image to use (should be 500x500px)"),
+                    ('dist-dir=', 'd', "directory to put final built distributions in")
+                   ]
+    description = "Create a Mac OS X disk image with the package installer"
+
+    def initialize_options(self):
+        self.dist_dir = None
+        self.background = None
+        self.finalized = False
+
+    def finalize_options(self):
+        self.set_undefined_options('bdist', ('dist_dir', 'dist_dir'))
+        self.finalized = True
+
+    def run(self):
+
+        pkg_dir = os.path.join(self.dist_dir, 'pkg')
+
+        # Remove directory if it already exists
+        if os.path.exists(pkg_dir):
+            shutil.rmtree(pkg_dir)
+
+        # First create the package installer with bdist_mpkg
+        mpkg = self.reinitialize_command('bdist_mpkg', reinit_subcommands=1)
+        mpkg.dist_dir = pkg_dir
+        mpkg.ensure_finalized()
+        mpkg.run()
+
+        # Find the name of the pkg file. Since we removed the dist directory
+        # at the start of the script, our pkg should be the only file there.
+        files = os.listdir(pkg_dir)
+        if len(files) != 1:
+            raise DistutilsFileError("Expected a single file in the {pkg_dir} directory".format(pkg_dir=pkg_dir))
+        pkg_file = os.path.basename(files[0])
+        pkg_name = os.path.splitext(pkg_file)[0]
+
+        # Build the docs
+        docs = self.reinitialize_command('build_sphinx', reinit_subcommands=1)
+        docs.ensure_finalized()
+        docs.run()
+
+        # Copy over the docs to the dist directory
+        shutil.copytree(os.path.join(docs.build_dir, 'html'),
+                        os.path.join(pkg_dir, 'Documentation'))
+
+        # Copy over the background to the disk image
+        if self.background is not None:
+            os.mkdir(os.path.join(pkg_dir, '.background'))
+            shutil.copy2(self.background,
+                         os.path.join(pkg_dir, '.background', 'background.png'))
+
+        # Start creating the volume
+        dmg_path = os.path.join(self.dist_dir, pkg_name + '.dmg')
+        dmg_path_tmp = os.path.join(self.dist_dir, pkg_name + '_tmp.dmg')
+        volume_name = pkg_name
+
+        # Remove existing dmg files
+        if os.path.exists(dmg_path):
+            os.remove(dmg_path)
+        if os.path.exists(dmg_path_tmp):
+            os.remove(dmg_path_tmp)
+
+        # Check if a volume is already mounted
+        if os.path.exists('/Volumes/{volume_name}'.format(volume_name=volume_name)):
+            raise DistutilsFileError("A volume named {volume_name} is already mounted - please eject this and try again".format(volume_name=volume_name))
+
+        shell_script = """
+
+        # Create DMG file
+        hdiutil create -volname {volume_name} -srcdir {pkg_dir} -fs HFS+ -fsargs "-c c=64,a=16,e=16" -format UDRW -size 24m {dmg_path_tmp}
+
+        # Mount disk image, and keep reference to device
+        device=$(hdiutil attach -readwrite -noverify -noautoopen {dmg_path_tmp} | egrep '^/dev/' | sed 1q | awk '{{print $1}}')
+
+        echo '
+        tell application "Finder"
+            tell disk "{volume_name}"
+                open
+                set current view of container window to icon view
+                set toolbar visible of container window to false
+                set statusbar visible of container window to false
+                set the bounds of container window to {{100, 100, 600, 600}}
+                set theViewOptions to the icon view options of container window
+                set arrangement of theViewOptions to not arranged
+                set icon size of theViewOptions to 128
+                set the background picture of theViewOptions to file ".background:background.png"
+                set position of item "{pkg_file}" of container window to {{125, 320}}
+                set position of item "Documentation" of container window to {{375, 320}}
+                close
+                open
+                update without registering applications
+                delay 5
+            end tell
+        end tell
+        ' | osascript
+
+        # Eject disk image
+        hdiutil detach ${{device}}
+
+        # Convert to final read-only disk image
+        hdiutil convert {dmg_path_tmp} -format UDZO -imagekey zlib-level=9 -o {dmg_path}
+
+        """.format(volume_name=volume_name, pkg_dir=pkg_dir,
+                   pkg_file=pkg_file, dmg_path_tmp=dmg_path_tmp,
+                   dmg_path=dmg_path)
+
+        # Make the disk image with the above shell script
+        os.system(shell_script)
+
+        # Remove temporary disk image
+        os.remove(dmg_path_tmp)
diff --git a/astropy/sphinx/conf.py b/astropy/sphinx/conf.py
index 58d550c..a2ca3cb 100644
--- a/astropy/sphinx/conf.py
+++ b/astropy/sphinx/conf.py
@@ -4,50 +4,34 @@
 # Astropy shared Sphinx settings.  These settings are shared between
 # astropy itself and affiliated packages.
 #
-# Note that not all possible configuration values are present in this
-# autogenerated file.
+# Note that not all possible configuration values are present in this file.
 #
 # All configuration values have a default; values that are commented out
 # serve to show the default.
 
 import warnings
+from os import path
+
 
 # -- General configuration ----------------------------------------------------
 
 # If your documentation needs a minimal Sphinx version, state it here.
-needs_sphinx = '1.0'
+# Some of the docs require the autodoc special-members option, in 1.1
+needs_sphinx = '1.1'
 
-# Add any Sphinx extension module names here, as strings. They can be
-# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
-# ones.
-extensions = [
-    'sphinx.ext.autodoc',
-    'sphinx.ext.intersphinx',
-    'sphinx.ext.todo',
-    'sphinx.ext.coverage',
-    'sphinx.ext.pngmath',
-    'sphinx.ext.viewcode',
-    'sphinx.ext.inheritance_diagram',
-    'astropy.sphinx.ext.numpydoc',
-    'astropy.sphinx.ext.astropyautosummary',
-    'astropy.sphinx.ext.automodsumm',
-    'astropy.sphinx.ext.automodapi'
-    ]
-
-# Don't show summaries of the members in each class along with the
-# class' docstring
-numpydoc_show_class_members = False
-
-# Set the default role to the "smart" one
-default_role = 'obj'
+# Configuration for intersphinx: refer to the Python standard library.
+intersphinx_mapping = {
+    'python': ('http://docs.python.org/', None),
+    'numpy': ('http://docs.scipy.org/doc/numpy/', None),
+    'scipy': ('http://docs.scipy.org/doc/scipy/reference/', None),
+    'matplotlib': ('http://matplotlib.sourceforge.net/', None),
+    'astropy': ('http://www.astropy.org/', None),
+    'h5py': ('http://h5py.alfven.org/docs-2.1/', None)
+    }
 
-try:
-    import matplotlib.sphinxext.plot_directive
-    extensions += [matplotlib.sphinxext.plot_directive.__name__]
-except ImportError:
-    warnings.warn(
-        "matplotlib's plot_directive could not be imported. " +
-        "Inline plots will not be included in the output")
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+exclude_patterns = ['_build']
 
 # Add any paths that contain templates here, relative to this directory.
 # templates_path = ['_templates']
@@ -61,24 +45,29 @@ source_suffix = '.rst'
 # The master toctree document.
 master_doc = 'index'
 
+# The reST default role (used for this markup: `text`) to use for all
+# documents. Set to the "smart" one.
+default_role = 'obj'
+
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
 #language = None
 
+# This is added to the end of RST files - a good place to put substitutions to
+# be used globally.
+rst_epilog = """
+.. _Astropy: http://astropy.org
+"""
+
+
+# -- Project information ------------------------------------------------------
+
 # There are two options for replacing |today|: either, you set today to some
 # non-false value, then it is used:
 #today = ''
 # Else, today_fmt is used as the format for a strftime call.
 #today_fmt = '%B %d, %Y'
 
-# List of patterns, relative to source directory, that match files and
-# directories to ignore when looking for source files.
-exclude_patterns = ['_build']
-
-# The reST default role (used for this markup: `text`) to use for all
-# documents.
-default_role = 'obj'
-
 # If true, '()' will be appended to :func: etc. cross-reference text.
 #add_function_parentheses = True
 
@@ -91,28 +80,74 @@ default_role = 'obj'
 #show_authors = False
 
 # The name of the Pygments (syntax highlighting) style to use.
-pygments_style = 'sphinx'
+#pygments_style = 'sphinx'
 
 # A list of ignored prefixes for module index sorting.
 #modindex_common_prefix = []
 
 
+# -- Settings for extensions and extension options ----------------------------
+
+# Add any Sphinx extension module names here, as strings. They can be
+# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
+# ones.
+extensions = [
+    'sphinx.ext.autodoc',
+    'sphinx.ext.intersphinx',
+    'sphinx.ext.todo',
+    'sphinx.ext.coverage',
+    'sphinx.ext.pngmath',
+    'sphinx.ext.viewcode',
+    'sphinx.ext.inheritance_diagram',
+    'astropy.sphinx.ext.numpydoc',
+    'astropy.sphinx.ext.astropyautosummary',
+    'astropy.sphinx.ext.automodsumm',
+    'astropy.sphinx.ext.automodapi'
+    ]
+
+try:
+    import matplotlib.sphinxext.plot_directive
+    extensions += [matplotlib.sphinxext.plot_directive.__name__]
+except ImportError:
+    warnings.warn(
+        "matplotlib's plot_directive could not be imported. " +
+        "Inline plots will not be included in the output")
+
+# Don't show summaries of the members in each class along with the
+# class' docstring
+numpydoc_show_class_members = False
+
+autosummary_generate = True
+
+automodapi_toctreedirnm = '_generated'
+
+
 # -- Options for HTML output -------------------------------------------------
 
+# Add any paths that contain custom themes here, relative to this directory.
+html_theme_path = [path.abspath(path.join(path.dirname(__file__), 'themes'))]
+
 # The theme to use for HTML and HTML Help pages.  See the documentation for
 # a list of builtin themes.
-# html_theme = 'default'
+html_theme = 'bootstrap-astropy'
+
+# Custom sidebar templates, maps document names to template names.
+html_sidebars = {'**': ['localtoc.html']}
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+html_favicon = 'astropy_logo.ico'  # included in the bootstrap-astropy theme
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+html_last_updated_fmt = '%d %b %Y'
 
 # Theme options are theme-specific and customize the look and feel of a theme
 # further.  For a list of options available for each theme, see the
 # documentation.
 #html_theme_options = {}
 
-# Add any paths that contain custom themes here, relative to this directory.
-#html_theme_path = []
-
-html_style = 'astropy.css'
-
 # The name for this set of Sphinx documents.  If None, it defaults to
 # "<project> v<release> documentation".
 #html_title = None
@@ -120,17 +155,10 @@ html_style = 'astropy.css'
 # A shorter title for the navigation bar.  Default is the same as html_title.
 #html_short_title = None
 
-# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
-# using the given strftime format.
-#html_last_updated_fmt = '%b %d, %Y'
-
 # If true, SmartyPants will be used to convert quotes and dashes to
 # typographically correct entities.
 #html_use_smartypants = True
 
-# Custom sidebar templates, maps document names to template names.
-#html_sidebars = {}
-
 # Additional templates that should be rendered to pages, maps page names to
 # template names.
 #html_additional_pages = {}
@@ -171,7 +199,7 @@ html_style = 'astropy.css'
 
 # For "manual" documents, if this is true, then toplevel headings are parts,
 # not chapters.
-#latex_use_parts = False
+latex_use_parts = True
 
 # If true, show page references after internal links.
 #latex_show_pagerefs = False
@@ -180,7 +208,45 @@ html_style = 'astropy.css'
 #latex_show_urls = False
 
 # Additional stuff for the LaTeX preamble.
-#latex_preamble = ''
+latex_preamble = r"""
+% Use a more modern-looking monospace font
+\usepackage{inconsolata}
+
+% The enumitem package provides unlimited nesting of lists and enums.
+% Sphinx may use this in the future, in which case this can be removed.
+% See https://bitbucket.org/birkenfeld/sphinx/issue/777/latex-output-too-deeply-nested
+\usepackage{enumitem}
+\setlistdepth{15}
+
+% In the parameters section, place a newline after the Parameters
+% header.  (This is stolen directly from Numpy's conf.py, since it
+% affects Numpy-style docstrings).
+\usepackage{expdlist}
+\let\latexdescription=\description
+\def\description{\latexdescription{}{} \breaklabel}
+
+% Support the superscript Unicode numbers used by the "unicode" units
+% formatter
+\DeclareUnicodeCharacter{2070}{\ensuremath{^0}}
+\DeclareUnicodeCharacter{00B9}{\ensuremath{^1}}
+\DeclareUnicodeCharacter{00B2}{\ensuremath{^2}}
+\DeclareUnicodeCharacter{00B3}{\ensuremath{^3}}
+\DeclareUnicodeCharacter{2074}{\ensuremath{^4}}
+\DeclareUnicodeCharacter{2075}{\ensuremath{^5}}
+\DeclareUnicodeCharacter{2076}{\ensuremath{^6}}
+\DeclareUnicodeCharacter{2077}{\ensuremath{^7}}
+\DeclareUnicodeCharacter{2078}{\ensuremath{^8}}
+\DeclareUnicodeCharacter{2079}{\ensuremath{^9}}
+\DeclareUnicodeCharacter{207B}{\ensuremath{^-}}
+
+% Make the "warning" and "notes" sections use a sans-serif font to
+% make them stand out more.
+\renewenvironment{notice}[2]{
+  \def\py at noticetype{#1}
+  \csname py at noticestart@#1\endcsname
+  \textsf{\textbf{#2}}
+}{\csname py at noticeend@\py at noticetype\endcsname}
+"""
 
 # Documents to append as an appendix to all manuals.
 #latex_appendices = []
@@ -188,34 +254,11 @@ html_style = 'astropy.css'
 # If false, no module index is generated.
 #latex_domain_indices = True
 
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
 
-# -- Options for manual page output ------------------------------------------
-
-# One entry per manual page. List of tuples
-# (source start file, name, description, authors, manual section).
-man_pages = [
-    ('index', 'astropy', u'Astropy Documentation',
-     [u'Erik Tollerud, Thomas Robitaille, Perry Greenfield, ' +
-      u'and the Astropy Collaboration'], 1)
-]
-
-# Example configuration for intersphinx: refer to the Python standard library.
-intersphinx_mapping = {
-    'python': ('http://docs.python.org/', None),
-    'numpy': ('http://docs.scipy.org/doc/numpy/', None),
-    'scipy': ('http://docs.scipy.org/doc/scipy/reference/', None),
-    'matplotlib': ('http://matplotlib.sourceforge.net/', None),
-    'astropy': ('http://www.astropy.org/', None),
-    }
-
-# This is added to the end of RST files - a good place to put substitutions to
-# be used globally.
-rst_epilog = """
-.. _Astropy: http://astropy.org
-"""
-
-
-# -- Settings for extensions --------------------------------------------------
+# -- Options for the linkcheck builder ----------------------------------------
 
-autosummary_generate = True
-automodapi_toctreedirnm = '_generated'
+# A timeout value, in seconds, for the linkcheck builder
+linkcheck_timeout = 60
diff --git a/astropy/sphinx/ext/automodapi.py b/astropy/sphinx/ext/automodapi.py
index cc34a51..132be41 100644
--- a/astropy/sphinx/ext/automodapi.py
+++ b/astropy/sphinx/ext/automodapi.py
@@ -17,15 +17,15 @@ It accepts the following options:
         If present, the inheritance diagram will not be shown even if
         the module/package has classes.
 
-    * ``:subsections: mod1[,mod2,subpkg3]``
-        If present, this generates separate documentation sections for
-        the requested submodules or subpackages.
+    * ``:skip: str``
+        This option results in the
+        specified object being skipped, that is the object will *not* be
+        included in the generated documentation. This option may appear
+        any number of times to skip multiple objects.
 
-    * ``:no-main-section:``
-        If present, the documentation and summary table for the main
-        module or package will not be generated (this would generally be
-        used with ``:subsections:`` if there is nothing of intereset in
-        the package itself.)
+    * ``:no-main-docstr:``
+        If present, the docstring for the module/package will not be generated.
+        The function and class tables will still be used, however.
 
     * ``:headings: str``
         Specifies the characters (in one string) used as the heading
@@ -37,6 +37,7 @@ It accepts the following options:
         top-level section (which usually uses '=').
 
 
+
 This extension also adds a sphinx configuration option
 `automodapi_toctreedirnm`. It must be a string that specifies the name of
 the directory the automodsumm generated documentation ends up in. This
@@ -59,7 +60,7 @@ automod_templ_modheader = """
 {modname} {pkgormod}
 {modhds}{pkgormodhds}
 
-.. automodule:: {modname}
+{automoduleline}
 """
 
 automod_templ_classes = """
@@ -69,6 +70,7 @@ Classes
 .. automodsumm:: {modname}
     :classes-only:
     {toctree}
+    {skips}
 """
 
 automod_templ_funcs = """
@@ -78,6 +80,7 @@ Functions
 .. automodsumm:: {modname}
     :functions-only:
     {toctree}
+    {skips}
 """
 
 automod_templ_inh = """
@@ -132,9 +135,7 @@ def automodapi_replace(sourcestr, app, dotoctree=True, docname=None,
         The string with automodapi entries replaced with the correct
         sphinx markup.
     """
-    import sys
     from os import sep
-    from inspect import ismodule
 
     spl = _automodapirex.split(sourcestr)
     if len(spl) > 1:  # automodsumm is in this document
@@ -153,7 +154,7 @@ def automodapi_replace(sourcestr, app, dotoctree=True, docname=None,
 
         newstrs = [spl[0]]
         for grp in range(len(spl) // 3):
-            basemodnm = spl[grp * 3 + 1]
+            modnm = spl[grp * 3 + 1]
 
             #find where this is in the document for warnings
             if docname is None:
@@ -161,76 +162,70 @@ def automodapi_replace(sourcestr, app, dotoctree=True, docname=None,
             else:
                 location = (docname, spl[0].count('\n'))
 
-            #findall yields an optionname, arguments tuple
-            modops = dict(_automodapiargsrex.findall(spl[grp * 3 + 2]))
-
-            inhdiag = 'no-inheritance-diagram' not in modops
-            modops.pop('no-inheritance-diagram', None)
-            subsecs = modops.pop('subsections', None)
-            nomain = 'no-main-section' in modops
-            modops.pop('no-main-section', None)
-            hds = modops.pop('headings', '-^')
-
+            #initialize default options
+            toskip = []
+            inhdiag = maindocstr = True
+            hds = '-^'
+
+            #look for actual options
+            unknownops = []
+            for opname, args in _automodapiargsrex.findall(spl[grp * 3 + 2]):
+                if opname == 'skip':
+                    toskip.append(args.strip())
+                elif opname == 'no-inheritance-diagram':
+                    inhdiag = False
+                elif opname == 'no-main-docstr':
+                    maindocstr = False
+                elif opname == 'headings':
+                    hds = args
+                else:
+                    unknownops.append(opname)
+
+            # get the two heading chars
             if len(hds) < 2:
-                msg = 'not enough headings (got {0}, need 2), using default -^'
+                msg = 'Not enough headings (got {0}, need 2), using default -^'
                 if warnings:
                     app.warn(msg.format(len(hds)), location)
                 hds = '-^'
             h1, h2 = hds.lstrip()[:2]
 
             #tell sphinx that the remaining args are invalid.
-            if len(modops) > 0 and app is not None:
-                opsstrs = ','.join(modops.keys())
+            if len(unknownops) > 0 and app is not None:
+                opsstrs = ','.join(unknownops)
                 msg = 'Found additional options ' + opsstrs + ' in automodapi.'
-
                 if warnings:
                     app.warn(msg, location)
 
-            # construct the list of modules to document based on the
-            # show-subsections argument
-            modnames = [] if nomain else [basemodnm]
-            if subsecs is not None:
-                for ss in subsecs.replace(' ', '').split(','):
-                    submodnm = basemodnm + '.' + ss
-                    try:
-                        __import__(submodnm)
-                        mod = sys.modules[submodnm]
-                        if ismodule(mod):
-                            modnames.append(mod.__name__)
-                        else:
-                            msg = ('Attempted to add documentation section for '
-                                   '{0}, which is neither module nor package. '
-                                   'Skipping.')
-                            if warnings:
-                                app.warn(msg.format(submodnm), location)
-                    except ImportError:
-                        msg = ('Attempted to add documentation section for '
-                               '{0}, which is not importable. Skipping.')
-                        if warnings:
-                            app.warn(msg.format(submodnm), location)
-
-            for modnm in modnames:
-                ispkg, hascls, hasfuncs = _mod_info(modnm)
-
-                newstrs.append(automod_templ_modheader.format(modname=modnm,
-                    modhds=h1 * len(modnm),
-                    pkgormod='Package' if ispkg else 'Module',
-                    pkgormodhds=h1 * (8 if ispkg else 7)))
-
-                if hasfuncs:
-                    newstrs.append(automod_templ_funcs.format(modname=modnm,
-                        funchds=h2 * 9,
-                        toctree=toctreestr))
-
-                if hascls:
-                    newstrs.append(automod_templ_classes.format(modname=modnm,
-                        clshds=h2 * 7,
-                        toctree=toctreestr))
-
-                if inhdiag and hascls:
-                    # add inheritance diagram if any classes are in the module
-                    newstrs.append(automod_templ_inh.format(
-                        modname=modnm, clsinhsechds=h2 * 25))
+            ispkg, hascls, hasfuncs = _mod_info(modnm, toskip)
+
+            #add automodule directive only if no-main-docstr isn't present
+            if maindocstr:
+                automodline = '.. automodule:: {modname}'.format(modname=modnm)
+            else:
+                automodline = ''
+
+            newstrs.append(automod_templ_modheader.format(modname=modnm,
+                modhds=h1 * len(modnm),
+                pkgormod='Package' if ispkg else 'Module',
+                pkgormodhds=h1 * (8 if ispkg else 7),
+                automoduleline=automodline))
+
+            if hasfuncs:
+                newstrs.append(automod_templ_funcs.format(modname=modnm,
+                    funchds=h2 * 9,
+                    toctree=toctreestr,
+                    skips=':skip: ' + ','.join(toskip) if toskip else ''))
+
+            if hascls:
+                newstrs.append(automod_templ_classes.format(modname=modnm,
+                    clshds=h2 * 7,
+                    toctree=toctreestr,
+                    skips=':skip: ' + ','.join(toskip) if toskip else ''))
+
+            if inhdiag and hascls:
+                # add inheritance diagram if any classes are in the module
+                newstrs.append(automod_templ_inh.format(
+                    modname=modnm, clsinhsechds=h2 * 25))
 
             newstrs.append(spl[grp * 3 + 3])
         return ''.join(newstrs)
@@ -238,7 +233,7 @@ def automodapi_replace(sourcestr, app, dotoctree=True, docname=None,
         return sourcestr
 
 
-def _mod_info(modname):
+def _mod_info(modname, toskip=[]):
     """
     Determines if a module is a module or a package and whether or not
     it has classes or functions.
@@ -250,11 +245,13 @@ def _mod_info(modname):
     from ...utils.misc import find_mod_objs
 
     hascls = hasfunc = False
-    for obj in find_mod_objs(modname, onlylocals=True)[2]:
-        hascls = hascls or isclass(obj)
-        hasfunc = hasfunc or isfunction(obj)
-        if hascls and hasfunc:
-            break
+
+    for localnm, fqnm, obj in zip(*find_mod_objs(modname, onlylocals=True)):
+        if localnm not in toskip:
+            hascls = hascls or isclass(obj)
+            hasfunc = hasfunc or isfunction(obj)
+            if hascls and hasfunc:
+                break
 
     #find_mod_objs has already imported modname
     pkg = sys.modules[modname]
diff --git a/astropy/sphinx/ext/automodsumm.py b/astropy/sphinx/ext/automodsumm.py
index e6ff0a5..eb185d6 100644
--- a/astropy/sphinx/ext/automodsumm.py
+++ b/astropy/sphinx/ext/automodsumm.py
@@ -11,8 +11,8 @@ but can be used independently.
 =======================
 
 This directive will produce an "autosummary"-style table for public
-attributesof a specified module. See the `sphinx.ext.autosummary`
-extensionfor details on this process. The main difference from the
+attributes of a specified module. See the `sphinx.ext.autosummary`
+extension for details on this process. The main difference from the
 `autosummary` directive is that `autosummary` requires manually inputting
 all attributes that appear in the table, while this captures the entries
 automatically.
@@ -34,6 +34,11 @@ options:
         functions. This cannot be used at the same time with
         ``:classes-only:`` .
 
+    * ``:skip: obj1, [obj2, obj3, ...]``
+        If present, specifies that the listed objects should be skipped
+        and not have their documentation generated, nor be includded in
+        the summary table.
+
 
 ===========================
 `automod-diagram` directive
@@ -60,6 +65,17 @@ from ...utils.misc import find_mod_objs
 from .astropyautosummary import AstropyAutosummary
 
 
+def _str_list_converter(argument):
+    """
+    A directive option conversion function that converts the option into a list
+    of strings. Used for 'skip' option.
+    """
+    if argument is None:
+        return []
+    else:
+        return [s.strip() for s in argument.split(',')]
+
+
 class Automodsumm(AstropyAutosummary):
     required_arguments = 1
     optional_arguments = 0
@@ -68,6 +84,7 @@ class Automodsumm(AstropyAutosummary):
     option_spec = dict(Autosummary.option_spec)
     option_spec['functions-only'] = flag
     option_spec['classes-only'] = flag
+    option_spec['skip'] = _str_list_converter
 
     def run(self):
         from inspect import isclass, isfunction
@@ -86,21 +103,35 @@ class Automodsumm(AstropyAutosummary):
             # Be sure to respect functions-only and classes-only.
             funconly = 'functions-only' in self.options
             clsonly = 'classes-only' in self.options
+
+            skipmap = {}
+            if 'skip' in self.options:
+                skipnames = set(self.options['skip'])
+                for lnm, fqnm in zip(localnames, fqns):
+                    if lnm in skipnames:
+                        skipnames.remove(lnm)
+                        skipmap[fqnm] = lnm
+                if len(skipnames) > 0:
+                    self.warn('Tried to skip objects {objs} in module {mod}, '
+                              'but they were not present.  Ignoring.'.format(
+                              objs=skipnames, mod=self.arguments[0]))
+
             if funconly and not clsonly:
                 cont = []
                 for nm, obj in zip(fqns, objs):
-                    if isfunction(obj):
+                    if nm not in skipmap and isfunction(obj):
                         cont.append('~' + nm)
             elif clsonly:
                 cont = []
                 for nm, obj in zip(fqns, objs):
-                    if isclass(obj):
+                    if nm not in skipmap and isclass(obj):
                         cont.append('~' + nm)
             else:
                 if clsonly and funconly:
                     self.warning('functions-only and classes-only both '
                                  'defined. Skipping.')
-                cont = ['~' + objname for objname in fqns]
+                cont = ['~' + nm for nm in fqns if nm not in skipmap]
+
             self.content = cont
 
             #can't use super because Sphinx/docutils has trouble
@@ -291,7 +322,8 @@ def generate_automodsumm_docs(lines, srcfn, suffix='.rst', warn=None,
     # Create our own templating environment - here we use Astropy's
     # templates rather than the default autosummary templates, in order to
     # allow docstrings to be shown for methods.
-    template_dirs = [os.path.join(base_path, '_templates')]
+    template_dirs = [os.path.join(os.path.dirname(__file__), 'templates'),
+                     os.path.join(base_path, '_templates')]
     if builder is not None:
         # allow the user to override the templates
         template_loader = BuiltinTemplateLoader()
@@ -375,7 +407,8 @@ def generate_automodsumm_docs(lines, srcfn, suffix='.rst', warn=None,
                           if x in include_public or not x.startswith('_')]
                 return public, items
 
-            def get_members_class(obj, typ, include_public=[], include_base=False):
+            def get_members_class(obj, typ, include_public=[],
+                                  include_base=False):
                 """
                 typ = None -> all
                 include_base -> include attrs that are from a base class
@@ -448,7 +481,10 @@ def generate_automodsumm_docs(lines, srcfn, suffix='.rst', warn=None,
             # astropy.config.logging_helper (which is at
             # astropy/config/logging_helper.py) then the reference file is set
             # to ../config/references.txt
-            mod_name_dir = mod_name.replace('.', '/').split('/', 1)[1]
+            if '.' in mod_name:
+                mod_name_dir = mod_name.replace('.', '/').split('/', 1)[1]
+            else:
+                mod_name_dir = mod_name
             if not os.path.isdir(os.path.join(path, '..', mod_name_dir)) \
                and os.path.isdir(os.path.join(path, '..', mod_name_dir.rsplit('/', 1)[0])):
                 mod_name_dir = mod_name_dir.rsplit('/', 1)[0]
diff --git a/astropy/sphinx/ext/edit_on_github.py b/astropy/sphinx/ext/edit_on_github.py
new file mode 100644
index 0000000..b7b6c42
--- /dev/null
+++ b/astropy/sphinx/ext/edit_on_github.py
@@ -0,0 +1,162 @@
+# Licensed under a 3-clause BSD style license - see LICENSE.rst
+"""
+This extension makes it easy to edit documentation on github.
+
+It adds links associated with each docstring that go to the
+corresponding view source page on Github.  From there, the user can
+push the "Edit" button, edit the docstring, and submit a pull request.
+
+It has the following configuration parameters:
+
+edit_on_github_project:
+    The name of the github project, in the form
+    "username/projectname".
+
+edit_on_github_branch:
+    The name of the branch to edit.  If this is a released version,
+    this should be a git tag referring to that version.  For a
+    dev version, it often makes sense for it to be "master".  It
+    may also be a git hash.
+
+edit_on_github_source_root:
+    The location within the source tree of the root of the
+    Python package.  Defaults to "lib".
+
+edit_on_github_doc_root:
+    The location within the source tree of the root of the
+    documentation source.  Defaults to "doc", but it may make sense to
+    set it to "doc/source" if the project uses a separate source
+    directory.
+
+edit_on_github_docstring_message:
+    The phrase displayed in the links to edit a docstring.  Defaults
+    to "[edit on github]".
+
+edit_on_github_page_message:
+    The phrase displayed in the links to edit a RST page.  Defaults
+    to "[edit this page on github]".
+
+edit_on_github_help_message:
+    The phrase displayed as a tooltip on the edit links.  Defaults to
+    "Push the Edit button on the next page"
+
+edit_on_github_skip_regex:
+    When the path to the .rst file matches this regular expression,
+    no "edit this page on github" link will be added.  Default to
+    "_.*".
+"""
+import inspect
+import os
+import re
+import sys
+
+from docutils import nodes
+
+from sphinx import addnodes
+
+
+def import_object(modname, name):
+    """
+    Import the object given by *modname* and *name* and return it.
+    If not found, or the import fails, returns None.
+    """
+    try:
+        __import__(modname)
+        mod = sys.modules[modname]
+        obj = mod
+        for part in name.split('.'):
+            obj = getattr(obj, part)
+        return obj
+    except:
+        return None
+
+
+def doctree_read(app, doctree):
+    # Get the configuration parameters
+    if app.config.edit_on_github_project == 'REQUIRED':
+        raise ValueError(
+            "The edit_on_github_project configuration variable must be "
+            "provided in the conf.py")
+
+    source_root = app.config.edit_on_github_source_root
+    if source_root != '' and not source_root.endswith('/'):
+        source_root += '/'
+    doc_root = app.config.edit_on_github_doc_root
+    if doc_root != '' and not doc_root.endswith('/'):
+        doc_root += '/'
+    url = 'http://github.com/%s/tree/%s/' % (
+        app.config.edit_on_github_project,
+        app.config.edit_on_github_branch)
+
+    docstring_message = app.config.edit_on_github_docstring_message
+    page_message = app.config.edit_on_github_page_message
+
+    # Handle the "edit this page" link
+    doc_path = os.path.relpath(doctree.get('source'), app.builder.srcdir)
+    if not re.match(app.config.edit_on_github_skip_regex, doc_path):
+        path = url + doc_root + doc_path
+        section = nodes.section()
+        para = nodes.paragraph()
+        section += para
+        onlynode = addnodes.only(expr='html')
+        para += onlynode
+        onlynode += nodes.reference(
+            reftitle=app.config.edit_on_github_help_message, refuri=path)
+        onlynode[0] += nodes.inline(
+            '', page_message, classes=['edit-on-github'])
+        doctree += section
+
+    # Handle the docstring-editing links
+    for objnode in doctree.traverse(addnodes.desc):
+        if objnode.get('domain') != 'py':
+            continue
+        names = set()
+        for signode in objnode:
+            if not isinstance(signode, addnodes.desc_signature):
+                continue
+            modname = signode.get('module')
+            if not modname:
+                continue
+            fullname = signode.get('fullname')
+            if fullname in names:
+                # only one link per name, please
+                continue
+            names.add(fullname)
+            obj = import_object(modname, fullname)
+            anchor = None
+            if obj is not None:
+                try:
+                    lines, lineno = inspect.getsourcelines(obj)
+                except:
+                    pass
+                else:
+                    anchor = '#L%d' % lineno
+            if anchor:
+                path = '%s%s%s.py%s' % (
+                    url, source_root, modname.replace('.', '/'), anchor)
+                onlynode = addnodes.only(expr='html')
+                onlynode += nodes.reference(
+                    reftitle=app.config.edit_on_github_help_message,
+                    refuri=path)
+                onlynode[0] += nodes.inline(
+                    '', '', nodes.raw('', ' ', format='html'),
+                    nodes.Text(docstring_message),
+                    classes=['edit-on-github', 'viewcode-link'])
+                signode += onlynode
+
+
+def setup(app):
+    app.add_config_value('edit_on_github_project', 'REQUIRED', True)
+    app.add_config_value('edit_on_github_branch', 'master', True)
+    app.add_config_value('edit_on_github_source_root', 'lib', True)
+    app.add_config_value('edit_on_github_doc_root', 'doc', True)
+    app.add_config_value('edit_on_github_docstring_message',
+                         '[edit on github]', True)
+    app.add_config_value('edit_on_github_page_message',
+                         '[edit this page on github]', True)
+    app.add_config_value('edit_on_github_help_message',
+                         'Push the Edit button on the next page', True)
+    app.add_config_value('edit_on_github_skip_regex',
+                         '_.*', True)
+
+    app.connect('doctree-read', doctree_read)
diff --git a/docs/_templates/autosummary/base.rst b/astropy/sphinx/ext/templates/autosummary_core/base.rst
similarity index 100%
copy from docs/_templates/autosummary/base.rst
copy to astropy/sphinx/ext/templates/autosummary_core/base.rst
diff --git a/astropy/sphinx/ext/templates/autosummary_core/class.rst b/astropy/sphinx/ext/templates/autosummary_core/class.rst
new file mode 100644
index 0000000..85105fa
--- /dev/null
+++ b/astropy/sphinx/ext/templates/autosummary_core/class.rst
@@ -0,0 +1,65 @@
+{% if referencefile %}
+.. include:: {{ referencefile }}
+{% endif %}
+
+{{ objname }}
+{{ underline }}
+
+.. currentmodule:: {{ module }}
+
+.. autoclass:: {{ objname }}
+   :show-inheritance:
+
+   {% if '__init__' in methods %}
+     {% set caught_result = methods.remove('__init__') %}
+   {% endif %}
+
+   {% block attributes_summary %}
+   {% if attributes %}
+
+   .. rubric:: Attributes Summary
+
+   .. autosummary::
+   {% for item in attributes %}
+      ~{{ name }}.{{ item }}
+   {%- endfor %}
+
+   {% endif %}
+   {% endblock %}
+
+   {% block methods_summary %}
+   {% if methods %}
+
+   .. rubric:: Methods Summary
+
+   .. autosummary::
+   {% for item in methods %}
+      ~{{ name }}.{{ item }}
+   {%- endfor %}
+
+   {% endif %}
+   {% endblock %}
+
+   {% block attributes_documentation %}
+   {% if attributes %}
+
+   .. rubric:: Attributes Documentation
+
+   {% for item in attributes %}
+   .. autoattribute:: {{ item }}
+   {%- endfor %}
+
+   {% endif %}
+   {% endblock %}
+
+   {% block methods_documentation %}
+   {% if methods %}
+
+   .. rubric:: Methods Documentation
+
+   {% for item in methods %}
+   .. automethod:: {{ item }}
+   {%- endfor %}
+
+   {% endif %}
+   {% endblock %}
diff --git a/docs/_templates/autosummary/module.rst b/astropy/sphinx/ext/templates/autosummary_core/module.rst
similarity index 100%
copy from docs/_templates/autosummary/module.rst
copy to astropy/sphinx/ext/templates/autosummary_core/module.rst
diff --git a/astropy/sphinx/ext/tests/test_automodapi.py b/astropy/sphinx/ext/tests/test_automodapi.py
index 6c62c49..546d6e4 100644
--- a/astropy/sphinx/ext/tests/test_automodapi.py
+++ b/astropy/sphinx/ext/tests/test_automodapi.py
@@ -1,6 +1,7 @@
 # Licensed under a 3-clause BSD style license - see LICENSE.rst
-from pytest import importorskip
-importorskip('sphinx')  # skips these tests if sphinx not present
+from ....tests.helper import pytest
+pytest.importorskip('sphinx')  # skips these tests if sphinx not present
+
 
 class FakeConfig(object):
     """
@@ -50,6 +51,7 @@ Functions
 .. automodsumm:: astropy.sphinx.ext.tests.test_automodapi
     :functions-only:
     :toctree: _generated/
+    {empty}
 
 Classes
 ^^^^^^^
@@ -57,6 +59,7 @@ Classes
 .. automodsumm:: astropy.sphinx.ext.tests.test_automodapi
     :classes-only:
     :toctree: _generated/
+    {empty}
 
 Class Inheritance Diagram
 ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -65,7 +68,7 @@ Class Inheritance Diagram
     :private-bases:
 
 This comes after
-"""
+""".format(empty='')  # necessary for editors that remove empty-line whitespace
 
 
 def test_am_replacer_basic():
@@ -94,6 +97,7 @@ Functions
 .. automodsumm:: astropy.sphinx.ext.tests.test_automodapi
     :functions-only:
     :toctree: _generated/
+    {empty}
 
 Classes
 ^^^^^^^
@@ -101,10 +105,11 @@ Classes
 .. automodsumm:: astropy.sphinx.ext.tests.test_automodapi
     :classes-only:
     :toctree: _generated/
+    {empty}
 
 
 This comes after
-"""
+""".format(empty='')  # necessary for editors that remove empty-line whitespace
 
 
 def test_am_replacer_noinh():
@@ -135,6 +140,7 @@ Functions
 .. automodsumm:: astropy.sphinx.ext.tests.test_automodapi
     :functions-only:
     :toctree: _generated/
+    {empty}
 
 Classes
 *******
@@ -142,6 +148,7 @@ Classes
 .. automodsumm:: astropy.sphinx.ext.tests.test_automodapi
     :classes-only:
     :toctree: _generated/
+    {empty}
 
 Class Inheritance Diagram
 *************************
@@ -151,7 +158,7 @@ Class Inheritance Diagram
 
 
 This comes after
-"""
+""".format(empty='')  # necessary for editors that remove empty-line whitespace
 
 
 def test_am_replacer_titleandhdrs():
@@ -169,43 +176,60 @@ def test_am_replacer_titleandhdrs():
     assert result == am_replacer_titleandhdrs_expected
 
 
-am_replacer_ss_str = """
+am_replacer_nomain_str = """
 This comes before
 
-.. automodapi:: astropy.sphinx.ext
-    :subsections: automodsumm,automodapi,tests,falsemod
-    :no-main-section:
+.. automodapi:: astropy.sphinx.ext.automodapi
+    :no-main-docstr:
 
 This comes after
 """
 
-am_replacer_subsections_expected = """
+am_replacer_nomain_expected = """
 This comes before
 
-astropy.sphinx.ext.automodsumm Module
--------------------------------------
+astropy.sphinx.ext.automodapi Module
+------------------------------------
+
 
-.. automodule:: astropy.sphinx.ext.automodsumm
 
 Functions
 ^^^^^^^^^
 
-.. automodsumm:: astropy.sphinx.ext.automodsumm
+.. automodsumm:: astropy.sphinx.ext.automodapi
     :functions-only:
     :toctree: _generated/
+    {empty}
 
-Classes
-^^^^^^^
 
-.. automodsumm:: astropy.sphinx.ext.automodsumm
-    :classes-only:
-    :toctree: _generated/
+This comes after
+""".format(empty='')  # necessary for editors that remove empty-line whitespace
 
-Class Inheritance Diagram
-^^^^^^^^^^^^^^^^^^^^^^^^^
 
-.. automod-diagram:: astropy.sphinx.ext.automodsumm
-    :private-bases:
+def test_am_replacer_nomain():
+    """
+    Tests replacing an ".. automodapi::" with "no-main-docstring" .
+    """
+    from ..automodapi import automodapi_replace
+
+    fakeapp = FakeApp(automodapi_toctreedirnm='_generated/')
+    result = automodapi_replace(am_replacer_nomain_str, fakeapp)
+
+    assert result == am_replacer_nomain_expected
+
+
+am_replacer_skip_str = """
+This comes before
+
+.. automodapi:: astropy.sphinx.ext.automodapi
+    :skip: something1
+    :skip: something2
+
+This comes after
+"""
+
+am_replacer_skip_expected = """
+This comes before
 
 astropy.sphinx.ext.automodapi Module
 ------------------------------------
@@ -218,29 +242,45 @@ Functions
 .. automodsumm:: astropy.sphinx.ext.automodapi
     :functions-only:
     :toctree: _generated/
+    :skip: something1,something2
 
-astropy.sphinx.ext.tests Module
--------------------------------
 
-.. automodule:: astropy.sphinx.ext.tests
+This comes after
+""".format(empty='')  # necessary for editors that remove empty-line whitespace
+
+
+def test_am_replacer_skip():
+    """
+    Tests using the ":skip: option in an ".. automodapi::" .
+    """
+    from ..automodapi import automodapi_replace
+
+    fakeapp = FakeApp(automodapi_toctreedirnm='_generated/')
+    result = automodapi_replace(am_replacer_skip_str, fakeapp)
+
+    assert result == am_replacer_skip_expected
+
+
+am_replacer_invalidop_str = """
+This comes before
 
+.. automodapi:: astropy.sphinx.ext.automodapi
+    :invalid-option:
 
 This comes after
 """
 
 
-def test_am_replacer_subsections():
+def test_am_replacer_invalidop():
     """
-    Tests replacing an ".. automodapi::" with "subsections" and
-    "no-main-section" options.
+    Tests that a sphinx warning is produced with an invalid option.
     """
     from ..automodapi import automodapi_replace
 
     fakeapp = FakeApp(automodapi_toctreedirnm='_generated/')
-    result = automodapi_replace(am_replacer_ss_str, fakeapp)
+    automodapi_replace(am_replacer_invalidop_str, fakeapp)
 
-    expected_warnings = [('Attempted to add documentation section for '
-      'astropy.sphinx.ext.falsemod, which is not importable. Skipping.', None)]
+    expected_warnings = [('Found additional options invalid-option in '
+                          'automodapi.', None)]
 
     assert fakeapp.warnings == expected_warnings
-    assert result == am_replacer_subsections_expected
diff --git a/astropy/sphinx/ext/tests/test_automodsumm.py b/astropy/sphinx/ext/tests/test_automodsumm.py
index 85831b9..1c3893b 100644
--- a/astropy/sphinx/ext/tests/test_automodsumm.py
+++ b/astropy/sphinx/ext/tests/test_automodsumm.py
@@ -1,6 +1,7 @@
 # Licensed under a 3-clause BSD style license - see LICENSE.rst
-from pytest import importorskip
-importorskip('sphinx')  # skips these tests if sphinx not present
+from ....tests.helper import pytest
+pytest.importorskip('sphinx')  # skips these tests if sphinx not present
+
 
 class FakeEnv(object):
     """
diff --git a/astropy/sphinx/setup_package.py b/astropy/sphinx/setup_package.py
new file mode 100644
index 0000000..579dd09
--- /dev/null
+++ b/astropy/sphinx/setup_package.py
@@ -0,0 +1,9 @@
+# Licensed under a 3-clause BSD style license - see LICENSE.rst
+
+def get_package_data():
+    # Install the theme files
+    return {
+        'astropy.sphinx': [
+            'ext/templates/*/*',
+            'themes/bootstrap-astropy/*.*',
+            'themes/bootstrap-astropy/static/*.*']}
diff --git a/docs/_themes/bootstrap-astropy/globaltoc.html b/astropy/sphinx/themes/bootstrap-astropy/globaltoc.html
similarity index 100%
rename from docs/_themes/bootstrap-astropy/globaltoc.html
rename to astropy/sphinx/themes/bootstrap-astropy/globaltoc.html
diff --git a/docs/_themes/bootstrap-astropy/layout.html b/astropy/sphinx/themes/bootstrap-astropy/layout.html
similarity index 100%
rename from docs/_themes/bootstrap-astropy/layout.html
rename to astropy/sphinx/themes/bootstrap-astropy/layout.html
diff --git a/docs/_themes/bootstrap-astropy/localtoc.html b/astropy/sphinx/themes/bootstrap-astropy/localtoc.html
similarity index 100%
rename from docs/_themes/bootstrap-astropy/localtoc.html
rename to astropy/sphinx/themes/bootstrap-astropy/localtoc.html
diff --git a/docs/_themes/bootstrap-astropy/searchbox.html b/astropy/sphinx/themes/bootstrap-astropy/searchbox.html
similarity index 100%
rename from docs/_themes/bootstrap-astropy/searchbox.html
rename to astropy/sphinx/themes/bootstrap-astropy/searchbox.html
diff --git a/docs/_themes/bootstrap-astropy/sourcelink.html b/astropy/sphinx/themes/bootstrap-astropy/sourcelink.html
similarity index 100%
rename from docs/_themes/bootstrap-astropy/sourcelink.html
rename to astropy/sphinx/themes/bootstrap-astropy/sourcelink.html
diff --git a/astropy/sphinx/themes/bootstrap-astropy/static/astropy_docs_32.png b/astropy/sphinx/themes/bootstrap-astropy/static/astropy_docs_32.png
new file mode 100644
index 0000000..a7f5057
Binary files /dev/null and b/astropy/sphinx/themes/bootstrap-astropy/static/astropy_docs_32.png differ
diff --git a/astropy/sphinx/themes/bootstrap-astropy/static/astropy_linkout_20.png b/astropy/sphinx/themes/bootstrap-astropy/static/astropy_linkout_20.png
new file mode 100644
index 0000000..4322679
Binary files /dev/null and b/astropy/sphinx/themes/bootstrap-astropy/static/astropy_linkout_20.png differ
diff --git a/astropy/sphinx/themes/bootstrap-astropy/static/astropy_logo.ico b/astropy/sphinx/themes/bootstrap-astropy/static/astropy_logo.ico
new file mode 100644
index 0000000..c2bca3a
Binary files /dev/null and b/astropy/sphinx/themes/bootstrap-astropy/static/astropy_logo.ico differ
diff --git a/astropy/sphinx/themes/bootstrap-astropy/static/bootstrap-astropy.css b/astropy/sphinx/themes/bootstrap-astropy/static/bootstrap-astropy.css
new file mode 100644
index 0000000..a288fcb
--- /dev/null
+++ b/astropy/sphinx/themes/bootstrap-astropy/static/bootstrap-astropy.css
@@ -0,0 +1,530 @@
+/*!
+ * Bootstrap v1.4.0
+ *
+ * Copyright 2011 Twitter, Inc
+ * Licensed under the Apache License v2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Heavily modified by Kyle Barbary for the AstroPy Project for use with Sphinx.
+ */
+
+ at import url("basic.css");
+
+body {
+  background-color: #ffffff;
+  margin: 0;
+  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+  font-size: 13px;
+  font-weight: normal;
+  line-height: 18px;
+  color: #404040;
+}
+
+/* Hyperlinks ----------------------------------------------------------------*/
+
+a {
+  color: #0069d6;
+  text-decoration: none;
+  line-height: inherit;
+  font-weight: inherit;
+}
+
+a:hover {
+  color: #00438a;
+  text-decoration: underline;
+}
+
+/* Typography ----------------------------------------------------------------*/
+
+h1,h2,h3,h4,h5,h6 {
+  color: #404040;
+  margin: 0.7em 0 0 0;
+  line-height: 1.5em;
+}
+h1 {
+  font-size: 24px;
+  margin: 0;
+}
+h2 {
+  font-size: 21px;
+  line-height: 1.2em;
+  margin: 1em 0 0.5em 0;
+  border-bottom: 1px solid #404040;
+}
+h3 {
+  font-size: 18px;
+}
+h4 {
+  font-size: 16px;
+}
+h5 {
+  font-size: 14px;
+}
+h6 {
+  font-size: 13px;
+  text-transform: uppercase;
+}
+
+p {
+  font-size: 13px;
+  font-weight: normal;
+  line-height: 18px;
+  margin-top: 0px;
+  margin-bottom: 9px;
+}
+
+ul, ol {
+  margin-left: 0;
+  padding: 0 0 0 25px;
+}
+ul ul, ul ol, ol ol, ol ul {
+  margin-bottom: 0;
+}
+ul {
+  list-style: disc;
+}
+ol {
+  list-style: decimal;
+}
+li {
+  line-height: 18px;
+  color: #404040;
+}
+ul.unstyled {
+  list-style: none;
+  margin-left: 0;
+}
+dl {
+  margin-bottom: 18px;
+}
+dl dt, dl dd {
+  line-height: 18px;
+}
+dl dd {
+  margin-left: 9px;
+}
+hr {
+  margin: 20px 0 19px;
+  border: 0;
+  border-bottom: 1px solid #eee;
+}
+strong {
+  font-style: inherit;
+  font-weight: bold;
+}
+em {
+  font-style: italic;
+  font-weight: inherit;
+  line-height: inherit;
+}
+.muted {
+  color: #bfbfbf;
+}
+
+address {
+  display: block;
+  line-height: 18px;
+  margin-bottom: 18px;
+}
+code, pre {
+  padding: 0 3px 2px;
+  font-family: Monaco, Andale Mono, Courier New, monospace;
+  font-size: 12px;
+  -webkit-border-radius: 3px;
+  -moz-border-radius: 3px;
+  border-radius: 3px;
+}
+code {
+  background-color: #fee9cc;
+  color: rgba(0, 0, 0, 0.75);
+  padding: 1px 3px;
+}
+pre {
+  background-color: #eee;
+  display: block;
+  padding: 8.5px;
+  margin: 0 0 18px;
+  line-height: 18px;
+  font-size: 12px;
+  border: 1px solid #ccc;
+  border: 1px solid rgba(0, 0, 0, 0.15);
+  -webkit-border-radius: 3px;
+  -moz-border-radius: 3px;
+  border-radius: 3px;
+  white-space: pre;
+  white-space: pre-wrap;
+  word-wrap: break-word;
+}
+
+img {
+  margin: 9px 0;
+}
+
+tt {
+    padding: 0 1px 0 1px;
+    font-size: 0.95em;
+}
+th {
+    background-color: #dddddd;
+}
+
+.viewcode-back {
+    font-family: sans-serif;
+}
+
+div.viewcode-block:target {
+    background-color: #f4debf;
+    border-top: 1px solid #ac9;
+    border-bottom: 1px solid #ac9;
+}
+
+table.docutils {
+    border-spacing: 5px;
+    border-collapse: separate;
+}
+
+/* Topbar --------------------------------------------------------------------*/
+
+div.topbar {
+  height: 40px;
+  position: absolute;
+  top: 0;
+  left: 0;
+  right: 0;
+  z-index: 10000;
+  padding: 0px 10px;
+  background-color: #222;
+  background-color: #222222;
+  background-repeat: repeat-x;
+  background-image: -khtml-gradient(linear, left top, left bottom, from(#333333), to(#222222));
+  background-image: -moz-linear-gradient(top, #333333, #222222);
+  background-image: -ms-linear-gradient(top, #333333, #222222);
+  background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #333333), color-stop(100%, #222222));
+  background-image: -webkit-linear-gradient(top, #333333, #222222);
+  background-image: -o-linear-gradient(top, #333333, #222222);
+  background-image: linear-gradient(top, #333333, #222222);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#333333', endColorstr='#222222', GradientType=0);
+}
+
+div.topbar .brand {
+  float: left;
+  display: block;
+  width: 130px;
+  height: 32px;
+  padding: 8px 0px 0px 62px;
+  margin-left: -10px;
+  background: transparent url("astropy_docs_32.png") no-repeat 10px 4px;
+}
+div.topbar .brand:hover, div.topbar ul li a.homelink:hover {
+  background-color: #333;
+  background-color: rgba(255, 255, 255, 0.05);
+}
+
+div.topbar ul {
+    font-size: 110%;
+    list-style: none;
+    margin: 0;
+    padding: 0 0 0 10px;
+    float: right;
+    color: #bfbfbf;
+    text-align: center;
+    text-decoration: none;
+    height: 100%;
+}
+div.topbar ul li {
+    float: left;
+    display: inline;
+    height: 30px;
+    margin: 5px;
+    padding: 0px;
+}
+
+div.topbar ul li a {
+  color: #bfbfbf;
+  text-decoration: none;
+  padding: 5px;
+  display: block;
+  height: auto;
+  text-align: center;
+  vertical-align: middle;
+  border-radius: 4px;
+}
+
+div.topbar ul li a:hover {
+  color: #ffffff;
+  text-decoration: none;
+}
+
+div.topbar ul li a.homelink {
+  width: 112px;
+  display: block;
+  height: 20px;
+  padding: 5px 0px;
+  background: transparent url("astropy_linkout_20.png") no-repeat 10px 5px;
+}
+
+div.topbar form {
+  text-align: left;
+  margin: 0 0 0 5px;
+  position: relative;
+  filter: alpha(opacity=100);
+  -khtml-opacity: 1;
+  -moz-opacity: 1;
+  opacity: 1;
+}
+
+div.topbar input {
+  background-color: #444;
+  background-color: rgba(255, 255, 255, 0.3);
+  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+  font-size: normal;
+  font-weight: 13px;
+  line-height: 1;
+  padding: 4px 9px;
+  color: #ffffff;
+  color: rgba(255, 255, 255, 0.75);
+  border: 1px solid #111;
+  -webkit-border-radius: 4px;
+  -moz-border-radius: 4px;
+  border-radius: 4px;
+  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0px rgba(255, 255, 255, 0.25);
+  -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0px rgba(255, 255, 255, 0.25);
+  box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0px rgba(255, 255, 255, 0.25);
+  -webkit-transition: none;
+  -moz-transition: none;
+  -ms-transition: none;
+  -o-transition: none;
+  transition: none;
+}
+div.topbar input:-moz-placeholder {
+  color: #e6e6e6;
+}
+div.topbar input::-webkit-input-placeholder {
+  color: #e6e6e6;
+}
+div.topbar input:hover {
+  background-color: #bfbfbf;
+  background-color: rgba(255, 255, 255, 0.5);
+  color: #ffffff;
+}
+div.topbar input:focus, div.topbar input.focused {
+  outline: 0;
+  background-color: #ffffff;
+  color: #404040;
+  text-shadow: 0 1px 0 #ffffff;
+  border: 0;
+  padding: 5px 10px;
+  -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);
+  -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);
+  box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);
+}
+
+
+/* Relation bar (breadcrumbs, prev, next) ------------------------------------*/
+
+div.related {
+    height: 21px;
+    width: auto;
+    margin: 0 10px;
+    position: absolute;
+    top: 42px;
+    clear: both;
+    left: 0;
+    right: 0;
+    z-index: 10000;
+    font-size: 100%;
+    vertical-align: middle;
+    background-color: #fff;
+    border-bottom: 1px solid #bbb;
+}
+div.related ul {
+    padding: 0;
+    margin: 0;
+}
+
+
+/* Footer --------------------------------------------------------------------*/
+
+footer {
+  display: block;
+  margin: 10px 10px 0px;
+  padding: 10px 0 0 0;
+  border-top: 1px solid #bbb;
+}
+.pull-right {
+  float: right;
+  width: 280px;
+  text-align: right;
+}
+
+
+/* Sphinx sidebar ------------------------------------------------------------*/
+
+div.sphinxsidebar {
+    font-size: inherit;
+    border-radius: 3px;
+    background-color: #eee;
+    border: 1px solid #bbb;
+}
+
+div.sphinxsidebarwrapper {
+    padding: 0px 0px 0px 5px;
+}
+
+div.sphinxsidebar h3 {
+    font-family: 'Trebuchet MS', sans-serif;
+    font-size: 1.4em;
+    font-weight: normal;
+    margin: 5px 0px 0px 5px;
+    padding: 0;
+    line-height: 1.6em;
+}
+div.sphinxsidebar h4 {
+    font-family: 'Trebuchet MS', sans-serif;
+    font-size: 1.3em;
+    font-weight: normal;
+    margin: 5px 0 0 0;
+    padding: 0;
+}
+div.sphinxsidebar p {
+}
+div.sphinxsidebar p.topless {
+    margin: 5px 10px 10px 10px;
+}
+div.sphinxsidebar ul {
+    margin: 0px 0px 0px 5px;
+    padding: 0;
+}
+
+div.sphinxsidebar ul ul {
+    margin-left: 15px;
+    list-style-type: disc;
+}
+
+/* If showing the global TOC (toctree),
+   color the current page differently */
+div.sphinxsidebar a.current {
+    color: #404040;
+}
+div.sphinxsidebar a.current:hover {
+    color: #404040;
+}
+
+
+/* document, documentwrapper, body, bodywrapper ----------------------------- */
+
+div.document {
+    margin-top: 72px;
+    margin-left: 10px;
+    margin-right: 10px;
+}
+
+div.documentwrapper {
+    float: left;
+    width: 100%;
+}
+
+div.body {
+    background-color: #ffffff;
+    padding: 0 0 0px 20px;
+}
+
+div.bodywrapper {
+    margin: 0 0 0 230px;
+}
+
+
+/* Header links ------------------------------------------------------------- */
+
+a.headerlink {
+    font-size: 0.8em;
+    padding: 0 4px 0 4px;
+    text-decoration: none;
+}
+
+a.headerlink:hover {
+    background-color: #0069d6;
+    color: white;
+    text-docoration: none;
+}
+
+
+/* Admonitions and warnings ------------------------------------------------- */
+
+/* Shared by admonitions and warnings */
+div.admonition,
+div.warning {
+    padding: 0px;
+    border-radius: 3px;
+    -moz-border-radius: 3px;
+    -webkit-border-radius: 3px;
+}
+div.admonition p,
+div.warning p {
+    margin: 0.5em 1em 0.5em 1em;
+    padding: 0;
+}
+div.admonition pre,
+div.warning pre {
+    margin: 0.4em 1em 0.4em 1em;
+}
+div.admonition p.admonition-title,
+div.warning p.admonition-title {
+    margin: 0;
+    padding: 0.1em 0 0.1em 0.5em;
+    color: white;
+    font-weight: bold;
+    font-size: 1.1em;
+}
+div.admonition ul, div.admonition ol,
+div.warning ul, div.warning ol {
+    margin: 0.1em 0.5em 0.5em 3em;
+    padding: 0;
+}
+
+/* Admonitions only */
+div.admonition {
+    border: 1px solid #609060;
+    background-color: #e9ffe9;
+}
+div.admonition p.admonition-title {
+    background-color: #70A070;
+}
+
+/* Warnings only */
+div.warning {
+    border: 1px solid #900000;
+    background-color: #ffe9e9;
+}
+div.warning p.admonition-title {
+    background-color: #b04040;
+}
+
+
+/* Figures ------------------------------------------------------------------ */
+
+.figure.align-center {
+    clear: none;
+}
+
+/* This is a div for containing multiple figures side-by-side, for use with
+ * .. container:: figures */
+div.figures {
+    border: 1px solid #CCCCCC;
+    background-color: #F8F8F8;
+    margin: 1em;
+    text-align: center;
+}
+
+div.figures .figure {
+    clear: none;
+    float: none;
+    display: inline-block;
+    border: none;
+    margin-left: 0.5em;
+    margin-right: 0.5em;
+}
+
+.field-list th {
+    white-space: nowrap;
+}
diff --git a/docs/_themes/bootstrap-astropy/static/sidebar.js b/astropy/sphinx/themes/bootstrap-astropy/static/sidebar.js
similarity index 100%
rename from docs/_themes/bootstrap-astropy/static/sidebar.js
rename to astropy/sphinx/themes/bootstrap-astropy/static/sidebar.js
diff --git a/astropy/sphinx/themes/bootstrap-astropy/theme.conf b/astropy/sphinx/themes/bootstrap-astropy/theme.conf
new file mode 100644
index 0000000..9e2a44b
--- /dev/null
+++ b/astropy/sphinx/themes/bootstrap-astropy/theme.conf
@@ -0,0 +1,5 @@
+# AstroPy theme based on Twitter Bootstrap CSS
+[theme]
+inherit = basic
+stylesheet = bootstrap-astropy.css
+pygments_style = sphinx
diff --git a/astropy/stats/__init__.py b/astropy/stats/__init__.py
new file mode 100644
index 0000000..cc9626f
--- /dev/null
+++ b/astropy/stats/__init__.py
@@ -0,0 +1,14 @@
+# Licensed under a 3-clause BSD style license - see LICENSE.rst
+"""
+This subpackage contains statistical tools provided for or used by Astropy.
+
+While the `scipy.stats` package contains a wide range of statistical
+tools, it is a general-purpose package, and is missing some that are
+particularly useful to astronomy or are used in an atypical way in
+astronomy. This package is intended to provide such functionality, but
+*not* to replace `scipy.stats` if its implementation satisfies
+astronomers' needs.
+
+"""
+
+from .funcs import *
diff --git a/astropy/stats/funcs.py b/astropy/stats/funcs.py
new file mode 100644
index 0000000..aa5d8d0
--- /dev/null
+++ b/astropy/stats/funcs.py
@@ -0,0 +1,111 @@
+# Licensed under a 3-clause BSD style license - see LICENSE.rst
+"""
+This module contains simple statistical algorithms that are straightforwardly
+implemented as a single python function (or family of functions).
+
+This package should generally not be used directly.  Everything in `__all__` is
+imported into `astropy.stats`, and hence that package should be used for
+access.
+"""
+
+import numpy as np  # needed for some defaults
+
+__all__ = ['sigma_clip']
+
+
+def sigma_clip(data, sig=3, iters=1, cenfunc=np.median, varfunc=np.var,
+               maout=False):
+    """ Perform sigma-clipping on the provided data.
+
+    This performs the sigma clipping algorithm - i.e. the data will be iterated
+    over, each time rejecting points that are more than a specified number of
+    standard deviations discrepant.
+
+    .. note::
+        `scipy.stats.sigmaclip` provides a subset of the functionality in this
+        function.
+
+    Parameters
+    ----------
+    data : array-like
+        The data to be sigma-clipped (any shape).
+    sig : float
+        The number of standard deviations (*not* variances) to use as the
+        clipping limit.
+    iters : int or None
+        The number of iterations to perform clipping for, or None to clip until
+        convergence is achieved (i.e. continue until the last iteration clips
+        nothing).
+    cenfunc : callable
+        The technique to compute the center for the clipping. Must be a
+        callable that takes in a 1D data array and outputs the central value.
+        Defaults to the median.
+    varfunc : callable
+        The technique to compute the variance about the center. Must be a
+        callable that takes in a 1D data array and outputs the width estimator
+        that will be interpreted as a variance. Defaults to the variance.
+    maout : bool or 'copy'
+        If True, a masked array will be returned. If the special string
+        'inplace', the masked array will contain the same array as `data`,
+        otherwise the array data will be copied.
+
+    Returns
+    -------
+    filtereddata : `numpy.ndarray` or `numpy.masked.MaskedArray`
+        If `maout` is True, this is a masked array with a shape matching the
+        input that is masked where the algorithm has rejected those values.
+        Otherwise, a 1D array of values including only those that are not
+        clipped.
+    mask : boolean array
+        Only present if `maout` is False. A boolean array with a shape matching
+        the input `data` that is False for rejected values and True for all
+        others.
+
+    Examples
+    --------
+
+    This will generate random variates from a Gaussian distribution and return
+    only the points that are within 2 *sample* standard deviation from the
+    median::
+
+        >>> from astropy.tools.alg import sigma_clip
+        >>> from numpy.random import randn
+        >>> randvar = randn(10000)
+        >>> data,mask = sigma_clip(randvar, 2, 1)
+
+    This will clipping on a similar distribution, but for 3 sigma relative to
+    the sample *mean*, will clip until converged, and produces a
+    `numpy.masked.MaskedArray`::
+
+        >>> from astropy.tools.alg import sigma_clip
+        >>> from numpy.random import randn
+        >>> from numpy import mean
+        >>> randvar = randn(10000)
+        >>> maskedarr = sigma_clip(randvar, 3, None, mean, maout=True)
+
+    """
+
+    data = np.array(data, copy=False)
+    oldshape = data.shape
+    data = data.ravel()
+
+    mask = np.ones(data.size, bool)
+    if iters is None:
+        i = -1
+        lastrej = sum(mask) + 1
+        while(sum(mask) != lastrej):
+            i += 1
+            lastrej = sum(mask)
+            do = data - cenfunc(data[mask])
+            mask = do * do <= varfunc(data[mask]) * sig ** 2
+        iters = i + 1
+        #TODO: ?print iters to the log if iters was None?
+    else:
+        for i in range(iters):
+            do = data - cenfunc(data[mask])
+            mask = do * do <= varfunc(data[mask]) * sig ** 2
+
+    if maout:
+        return np.ma.MaskedArray(data, ~mask, copy=maout != 'inplace')
+    else:
+        return data[mask], mask.reshape(oldshape)
diff --git a/astropy/config/tests/__init__.py b/astropy/stats/tests/__init__.py
similarity index 100%
copy from astropy/config/tests/__init__.py
copy to astropy/stats/tests/__init__.py
diff --git a/astropy/stats/tests/test_funcs.py b/astropy/stats/tests/test_funcs.py
new file mode 100644
index 0000000..f5e28c5
--- /dev/null
+++ b/astropy/stats/tests/test_funcs.py
@@ -0,0 +1,65 @@
+from __future__ import division
+
+import numpy as np
+from ...tests.helper import pytest
+
+from .. import funcs
+from ...utils.misc import NumpyRNGContext
+
+try:
+    from scipy import stats
+except ImportError:
+    HAS_SCIPY = False
+else:
+    HAS_SCIPY = True
+
+
+def test_sigma_clip():
+    from numpy.random import randn
+
+    #need to seed the numpy RNG to make sure we don't get some amazingly flukey
+    #random number that breaks one of the tests
+
+    with NumpyRNGContext(12345):  # Amazing, I've got the same combination on my luggage!
+
+        randvar = randn(10000)
+
+        data, mask = funcs.sigma_clip(randvar, 1, 2)
+        maskedarr = funcs.sigma_clip(randvar, 1, 2, maout=True)
+
+        assert sum(mask) > 0
+        assert data.size < randvar.size
+        assert np.all(mask == ~maskedarr.mask)
+
+        #this is actually a silly thing to do, because it uses the standard
+        #deviation as the variance, but it tests to make sure these arguments
+        #are actually doing something
+        data2, mask2 = funcs.sigma_clip(randvar, 1, 2, varfunc=np.std)
+        assert not np.all(data == data2)
+        assert not np.all(mask == mask2)
+
+        data3, mask3 = funcs.sigma_clip(randvar, 1, 2, cenfunc=np.mean)
+        assert not np.all(data == data3)
+        assert not np.all(mask == mask3)
+
+        #now just make sure the iters=None method works at all.
+        maskedarr = funcs.sigma_clip(randvar, 3, None, maout=True)
+
+
+ at pytest.mark.skipif('not HAS_SCIPY')
+def test_compare_to_scipy_sigmaclip():
+    from numpy.random import randn
+    from numpy.testing import assert_equal
+
+    #need to seed the numpy RNG to make sure we don't get some amazingly flukey
+    #random number that breaks one of the tests
+
+    with NumpyRNGContext(12345):  # Amazing, I've got the same combination on my luggage!
+
+        randvar = randn(10000)
+
+        astropyres = funcs.sigma_clip(randvar, 3, None, np.mean)[0]
+        scipyres = stats.sigmaclip(randvar, 3, 3)[0]
+
+        assert_equal(astropyres, scipyres)
+
diff --git a/astropy/table/__init__.py b/astropy/table/__init__.py
index 2f8449e..e6ff747 100644
--- a/astropy/table/__init__.py
+++ b/astropy/table/__init__.py
@@ -1 +1,6 @@
-from .table import Column, Table, TableColumns, Row
+from .table import Column, Table, TableColumns, Row, MaskedColumn
+
+# Import routines that connect readers/writers to astropy.table
+from ..io.ascii import connect
+from ..io.misc import connect
+from ..io.votable import connect
\ No newline at end of file
diff --git a/astropy/table/io_registry.py b/astropy/table/io_registry.py
new file mode 100644
index 0000000..5604299
--- /dev/null
+++ b/astropy/table/io_registry.py
@@ -0,0 +1,109 @@
+# Licensed under a 3-clause BSD style license - see LICENSE.rst
+
+__all__ = ['register_reader', 'register_writer', 'register_identifier',
+           'identify_format', 'get_reader', 'get_writer']
+
+_readers = {}
+_writers = {}
+_identifiers = {}
+
+
+def register_reader(table_format, function, force=False):
+    '''
+    Register a table reader function.
+
+    Parameters
+    ----------
+    table_format : string
+        The table type identifier. This is the string that will be used to
+        specify the table type when reading.
+    function : function
+        The function to read in a table.
+    force : bool
+        Whether to override any existing function if already present.
+    '''
+
+    if not table_format in _readers or force:
+        _readers[table_format] = function
+    else:
+        raise Exception("Reader for format {0:s} is already defined".format(table_format))
+
+
+def register_writer(table_format, function, force=False):
+    '''
+    Register a table writer function.
+
+    Parameters
+    ----------
+    table_format : string
+        The table type identifier. This is the string that will be used to
+        specify the table type when writing.
+    function : function
+        The function to write in a table.
+    force : bool
+        Whether to override any existing function if already present.
+    '''
+
+    if not table_format in _writers or force:
+        _writers[table_format] = function
+    else:
+        raise Exception("Writer for format {0:s} is already defined".format(table_format))
+
+
+def register_identifier(table_format, identifier, force=False):
+    '''
+    Associate an identifier function with a specific table type.
+
+    Parameters
+    ----------
+    table_format : str
+        The table type identifier. This is the string that is used to
+        specify the table type when reading/writing.
+    identifier : function
+        A function that checks the argument specified to `Table.read` or
+        `Table.write` to determine whether the input can be interpreted as a
+        table of type `table_format`. This function should take two arguments,
+        which will be set to the list of arguments and a dictionary of keyword
+        arguments passed to `Table.read` or `Table.write`. The function should
+        return True if the input can be identified as being of format
+        `table_format`, and False otherwise.
+    force : bool
+        Whether to override any existing function if already present.
+
+    Examples
+    --------
+
+    To set the identifier based on extensions, for formats that take a
+    filename as a first argument, you can do for example::
+
+    >>> register_identifier('ipac', lambda args, kwargs: isinstance(args[0], basestring) and args[0].endswith('.tbl'))
+    '''
+
+    if not table_format in _identifiers or force:
+        _identifiers[table_format] = identifier
+    else:
+        raise Exception("Identifier for format %s is already defined" % table_format)
+
+
+def identify_format(origin, args, kwargs):
+    # Loop through identifiers to see which formats match
+    valid_formats = []
+    for table_format in _identifiers:
+        if _identifiers[table_format](origin, args, kwargs):
+            valid_formats.append(table_format)
+
+    return valid_formats
+
+
+def get_reader(table_format):
+    if table_format in _readers:
+        return _readers[table_format]
+    else:
+        raise Exception("No reader defined for format '{0}'".format(table_format))
+
+
+def get_writer(table_format):
+    if table_format in _writers:
+        return _writers[table_format]
+    else:
+        raise Exception("No writer defined for format '{0}'".format(table_format))
diff --git a/astropy/table/pprint.py b/astropy/table/pprint.py
index 6f7e108..da7326d 100644
--- a/astropy/table/pprint.py
+++ b/astropy/table/pprint.py
@@ -4,24 +4,29 @@ from itertools import izip
 
 from .. import log
 from ..utils.console import Getch, color_print
+from ..config import ConfigurationItem
 
 _format_funcs = {None: lambda format_, val: str(val)}
-MAX_LINES = 25
-MAX_WIDTH = 80
 
+MAX_LINES = ConfigurationItem('max_lines', 25, 'Maximum number of lines for '
+    'the pretty-printer to use if it cannot determine the terminal size. '
+    'Negative numbers mean no limit.')
+MAX_WIDTH = ConfigurationItem('max_width', 80, 'Maximum number of characters '
+    'for the pretty-printer to use per line if it cannot determine the '
+    'terminal size.  Negative numbers mean no limit.')
 
 def _get_pprint_size(max_lines=None, max_width=None):
     """Get the output size (number of lines and character width) for Column and
     Table pformat/pprint methods.
 
-    If no value of ``max_lines`` is supplied then the height of the screen
-    terminal is used to set ``max_lines``.  If the terminal height cannot be
-    determined then a default of ``astropy.table.pprint.MAX_LINES`` is used.
-    If a negative value of ``max_lines`` is supplied then there is no line
-    limit applied.
+    If no value of `max_lines` is supplied then the height of the screen
+    terminal is used to set `max_lines`.  If the terminal height cannot be
+    determined then the default will be determined using the
+    `astropy.table.pprint.MAX_LINES` configuration item. If a negative value
+    of `max_lines` is supplied then there is no line limit applied.
 
-    The Same applies for max_width except the default is
-    ``astropy.table.pprint.MAX_WIDTH``.
+    The same applies for max_width except the configuration item is
+    `astropy.table.pprint.MAX_WIDTH`.
 
     Parameters
     ----------
@@ -50,7 +55,7 @@ def _get_pprint_size(max_lines=None, max_width=None):
             if width > 10:
                 width -= 1
         except:
-            lines, width = MAX_LINES, MAX_WIDTH
+            lines, width = MAX_LINES(), MAX_WIDTH()
 
     if max_lines is None:
         max_lines = lines
@@ -121,6 +126,41 @@ def _pformat_col(col, max_lines=None, show_name=True, show_units=False):
         Number of lines in the header
 
     """
+    outs = {}  # Some values from _pformat_col_iter iterator that are needed here
+    col_strs = list(_pformat_col_iter(col, max_lines, show_name, show_units, outs))
+    col_width = max(len(x) for x in col_strs)
+
+    # Center line content and generate dashed headerline
+    for i in outs['i_centers']:
+        col_strs[i] = col_strs[i].center(col_width)
+    if outs['i_dashes'] is not None:
+        col_strs[outs['i_dashes']] = '-' * col_width
+
+    # Now bring all the column string values to the same fixed width
+    for i, col_str in enumerate(col_strs):
+        col_strs[i] = col_str.rjust(col_width)
+
+    return col_strs, outs['n_header']
+
+
+def _pformat_col_iter(col, max_lines, show_name, show_units, outs):
+    """Iterator which yields formatted string representation of column values.
+
+    Parameters
+    ----------
+    max_lines : int
+        Maximum lines of output (header + data rows)
+
+    show_name : bool
+        Include column name (default=True)
+
+    show_units : bool
+        Include a header row for units (default=False)
+
+    out : dict
+        Must be a dict which is used to pass back additional values
+        defined within the iterator.
+    """
     max_lines, _ = _get_pprint_size(max_lines, -1)
 
     multidims = col.shape[1:]
@@ -131,25 +171,26 @@ def _pformat_col(col, max_lines=None, show_name=True, show_units=False):
     col_strs = []  # List of formatted column values
     i_dashes = None
     i_centers = []  # Line indexes where content should be centered
+    n_header = 0
     if show_name:
-        i_centers.append(len(col_strs))
+        i_centers.append(n_header)
         if multidims:
             col_name = col.name + ' [{0}]'.format(
                 ','.join(str(n) for n in multidims))
         else:
             col_name = col.name
-        col_strs.append(col_name)
-        max_lines -= 1
+        n_header += 1
+        yield col_name
     if show_units:
-        i_centers.append(len(col_strs))
-        col_strs.append(col.units or '')
-        max_lines -= 1
+        i_centers.append(n_header)
+        n_header += 1
+        yield str(col.units or '')
     if show_units or show_name:
-        i_dashes = len(col_strs)
-        col_strs.append('---')
-        max_lines -= 1
+        i_dashes = n_header
+        n_header += 1
+        yield '---'
 
-    n_header = len(col_strs)
+    max_lines -= n_header
     n_print2 = max_lines // 2
     n_rows = len(col)
 
@@ -170,27 +211,16 @@ def _pformat_col(col, max_lines=None, show_name=True, show_units=False):
                            format_func(col.format, col[(i,) + multidim1]))
             else:
                 col_str = format_func(col.format, col[i])
-            col_strs.append(col_str)
+            yield col_str
         elif i == i0:
-            col_strs.append('...')
-
-    col_width = max(len(x) for x in col_strs)
-
-    # Center line content and generate dashed headerline
-    for i in i_centers:
-        col_strs[i] = col_strs[i].center(col_width)
-    if i_dashes is not None:
-        col_strs[i_dashes] = '-' * col_width
-
-    # Now bring all the column string values to the same fixed width
-    for i, col_str in enumerate(col_strs):
-        col_strs[i] = col_str.rjust(col_width)
-
-    return col_strs, n_header
+            yield '...'
 
+    outs['n_header'] = n_header
+    outs['i_centers'] = i_centers
+    outs['i_dashes'] = i_dashes
 
 def _pformat_table(table, max_lines=None, max_width=None, show_name=True,
-                   show_units=False):
+                   show_units=False, html=False):
     """Return a list of lines for the formatted string representation of
     the table.
 
@@ -208,6 +238,9 @@ def _pformat_table(table, max_lines=None, max_width=None, show_name=True,
     show_units : bool
         Include a header row for units (default=False)
 
+    html : bool
+        Format the output as an HTML table (default=False)
+
     Returns
     -------
     out : str
@@ -246,9 +279,21 @@ def _pformat_table(table, max_lines=None, max_width=None, show_name=True,
     # Now "print" the (already-stringified) column values into a
     # row-oriented list.
     rows = []
-    for i in range(n_rows):
-        row = ' '.join(col[i] for col in cols)
-        rows.append(row)
+    if html:
+        rows.append('<table>')
+        for i in range(n_rows):
+            # _pformat_col output has a header line '----' which is not needed here
+            if i == n_header - 1:
+                continue
+            td = 'th' if i < n_header else 'td'
+            vals = ('<{0}>{1}</{2}>'.format(td, col[i].strip(), td) for col in cols)
+            row = ('<tr>' + ''.join(vals) + '</tr>')
+            rows.append(row)
+        rows.append('</table>')
+    else:
+        for i in range(n_rows):
+            row = ' '.join(col[i] for col in cols)
+            rows.append(row)
 
     return rows, n_header
 
diff --git a/astropy/table/table.py b/astropy/table/table.py
index 4374941..56aa37f 100644
--- a/astropy/table/table.py
+++ b/astropy/table/table.py
@@ -1,25 +1,33 @@
+import abc
 import sys
 from copy import deepcopy
-import collections
 
 import numpy as np
+from numpy import ma
 
+from ..units import Unit
+from .. import log
 from ..utils import OrderedDict, isiterable
 from .structhelper import _drop_fields
-from .pprint import _pformat_table, _pformat_col, _more_tabcol
+from .pprint import _pformat_table, _pformat_col, _pformat_col_iter, _more_tabcol
 from ..utils.console import color_print
-
+from ..config import ConfigurationItem
+from  .io_registry import get_reader, get_writer, identify_format
 # Python 2 and 3 source compatibility
 try:
     unicode
 except NameError:
     unicode = basestring = str
 
-AUTO_COLNAME = 'col{0}'
+NUMPY_LT_1P5 = [int(x) for x in np.__version__.split('.')[:2]] < [1, 5]
+
+AUTO_COLNAME = ConfigurationItem('auto_colname', 'col{0}',
+    'The template that determines the name of a column if it cannot be '
+    'determined. Uses new-style (format method) string formatting')
 
 
 def _auto_names(n_cols):
-    return [AUTO_COLNAME.format(i) for i in range(n_cols)]
+    return [AUTO_COLNAME().format(i) for i in range(n_cols)]
 
 
 class TableColumns(OrderedDict):
@@ -88,104 +96,9 @@ class TableColumns(OrderedDict):
         return list(OrderedDict.values(self))
 
 
-class Column(np.ndarray):
-    """Define a data column for use in a Table object.
-
-    Parameters
-    ----------
-    name : str
-        Column name and key for reference within Table
-    data : list, ndarray or None
-        Column data values
-    dtype : numpy.dtype compatible value
-        Data type for column
-    shape : tuple or ()
-        Dimensions of a single row element in the column data
-    length : int or 0
-        Number of row elements in column data
-    description : str or None
-        Full description of column
-    units : str or None
-        Physical units
-    format : str or None
-        Format string for outputting column values.  This can be an
-        "old-style" (``format % value``) or "new-style" (`str.format`)
-        format specification string.
-    meta : dict-like or None
-        Meta-data associated with the column
-
-    Examples
-    --------
-    A Column can be created in two different ways:
-
-    - Provide a ``data`` value and optionally a ``dtype`` value
-
-      Examples::
-
-        col = Column('name', data=[1, 2, 3])         # shape=(3,)
-        col = Column('name', data=[[1, 2], [3, 4]])  # shape=(2, 2)
-        col = Column('name', data=[1, 2, 3], dtype=float)
-        col = Column('name', np.array([1, 2, 3]))
-        col = Column('name', ['hello', 'world'])
-
-      The ``dtype`` argument can be any value which is an acceptable
-      fixed-size data-type initializer for the numpy.dtype() method.  See
-      `<http://docs.scipy.org/doc/numpy/reference/arrays.dtypes.html>`_.
-      Examples include:
-
-      - Python non-string type (float, int, bool)
-      - Numpy non-string type (e.g. np.float32, np.int64, np.bool)
-      - Numpy.dtype array-protocol type strings (e.g. 'i4', 'f8', 'S15')
-
-      If no ``dtype`` value is provide then the type is inferred using
-      ``np.array(data)``.  When ``data`` is provided then the ``shape``
-      and ``length`` arguments are ignored.
-
-    - Provide zero or more of ``dtype``, ``shape``, ``length``
-
-      Examples::
-
-        col = Column('name')
-        col = Column('name', dtype=int, length=10, shape=(3,4))
-
-      The default ``dtype`` is ``np.float64`` and the default ``length`` is
-      zero.  The ``shape`` argument is the array shape of a single cell in the
-      column.  The default ``shape`` is () which means a single value in each
-      element.
-    """
+class BaseColumn(object):
 
-    def __new__(cls, name, data=None,
-                 dtype=None, shape=(), length=0,
-                 description=None, units=None, format=None, meta=None):
-
-        if data is None:
-            dtype = (np.dtype(dtype).str, shape)
-            self_data = np.zeros(length, dtype=dtype)
-        elif isinstance(data, Column):
-            self_data = np.asarray(data.data, dtype=dtype)
-            if description is None:
-                description = data.description
-            if units is None:
-                units = units or data.units
-            if format is None:
-                format = data.format
-            if meta is None:
-                meta = deepcopy(data.meta)
-        else:
-            self_data = np.asarray(data, dtype=dtype)
-
-        self = self_data.view(cls)
-        self._name = name
-        self.units = units
-        self.format = format
-        self.description = description
-        self.parent_table = None
-
-        self.meta = OrderedDict()
-        if meta is not None:
-            self.meta.update(meta)
-
-        return self
+    __metaclass__ = abc.ABCMeta
 
     def __array_finalize__(self, obj):
         # Obj will be none for direct call to Column() creator
@@ -201,6 +114,25 @@ class Column(np.ndarray):
             setattr(self, attr, val)
         self.meta = deepcopy(getattr(obj, 'meta', {}))
 
+    def __array_wrap__(self, out_arr, context=None):
+        """
+        __array_wrap__ is called at the end of every ufunc.
+
+        If the output is the same shape as the column then call the standard
+        ndarray __array_wrap__ which will return a Column object.
+
+        If instead the output shape is different (e.g. for reduction ufuncs
+        like sum() or mean()) then return the output viewed as a standard
+        np.ndarray.  The "[()]" selects everything, but also converts a zero
+        rank array to a scalar.  For some reason np.sum() returns a zero rank
+        scalar array while np.mean() returns a scalar.  So the [()] is needed
+        for this case.
+        """
+        if self.shape == out_arr.shape:
+            return np.ndarray.__array_wrap__(self, out_arr, context)
+        else:
+            return out_arr.view(np.ndarray)[()]
+
     def _get_name(self):
         return self._name
 
@@ -215,21 +147,6 @@ class Column(np.ndarray):
     name = property(_get_name, _set_name)
 
     @property
-    def data(self):
-        return self.view(np.ndarray)
-
-    def copy(self, data=None, copy_data=True):
-        """Return a copy of the current Column instance.
-        """
-        if data is None:
-            data = self.view(np.ndarray)
-            if copy_data:
-                data = data.copy()
-
-        return Column(self.name, data, units=self.units, format=self.format,
-                      description=self.description, meta=deepcopy(self.meta))
-
-    @property
     def descr(self):
         """Array-interface compliant full description of the column.
 
@@ -240,14 +157,32 @@ class Column(np.ndarray):
 
     def __repr__(self):
         if self.name:
-            out = "<Column name={0} units={1} format={2} " \
-                "description={3}>\n{4}".format(
-                repr(self.name), repr(self.units),
+            units = None if self.units is None else str(self.units)
+            out = "<{0} name={1} units={2} format={3} " \
+                "description={4}>\n{5}".format(
+                self.__class__.__name__,
+                repr(self.name), repr(units),
                 repr(self.format), repr(self.description), repr(self.data))
         else:
             out = repr(self.data)
         return out
 
+    def iter_str_vals(self):
+        """
+        Return an iterator that yields the string-formatted values of this
+        column.
+
+        Returns
+        -------
+        str_vals : iterator
+            Column values formatted as strings
+        """
+        # pprint._pformat_col_iter(col, max_lines, show_name, show_units, outs)
+        # Iterate over formatted values with no max number of lines, no column
+        # name, no units, and ignoring the returned header info in outs.
+        for str_val in _pformat_col_iter(self, -1, False, False, {}):
+            yield str_val
+
     def attrs_equal(self, col):
         """Compare the column attributes of ``col`` to this object.
 
@@ -264,8 +199,8 @@ class Column(np.ndarray):
         equal: boolean
             True if all attributes are equal
         """
-        if not isinstance(col, Column):
-            raise ValueError('Comparison `col` must be a Column object')
+        if not isinstance(col, BaseColumn):
+            raise ValueError('Comparison `col` must be a Column or MaskedColumn object')
 
         attrs = ('name', 'units', 'dtype', 'format', 'description', 'meta')
         equal = all(getattr(self, x) == getattr(col, x) for x in attrs)
@@ -275,11 +210,11 @@ class Column(np.ndarray):
     def pformat(self, max_lines=None, show_name=True, show_units=False):
         """Return a list of formatted string representation of column values.
 
-        If no value of ``max_lines`` is supplied then the height of the screen
-        terminal is used to set ``max_lines``.  If the terminal height cannot
-        be determined then a default of ``astropy.table.MAX_LINES`` is used.
-        If a negative value of ``max_lines`` is supplied then there is no line
-        limit applied.
+        If no value of `max_lines` is supplied then the height of the screen
+        terminal is used to set `max_lines`.  If the terminal height cannot be
+        determined then the default will be determined using the
+        `astropy.table.pprint.MAX_LINES` configuration item. If a negative
+        value of `max_lines` is supplied then there is no line limit applied.
 
         Parameters
         ----------
@@ -304,11 +239,11 @@ class Column(np.ndarray):
     def pprint(self, max_lines=None, show_name=True, show_units=False):
         """Print a formatted string representation of column values.
 
-        If no value of ``max_lines`` is supplied then the height of the screen
-        terminal is used to set ``max_lines``.  If the terminal height cannot
-        be determined then a default of ``astropy.table.MAX_LINES`` is used.
-        If a negative value of ``max_lines`` is supplied then there is no line
-        limit applied.
+        If no value of `max_lines` is supplied then the height of the screen
+        terminal is used to set `max_lines`.  If the terminal height cannot be
+        determined then the default will be determined using the
+        `astropy.table.pprint.MAX_LINES` configuration item. If a negative
+        value of `max_lines` is supplied then there is no line limit applied.
 
         Parameters
         ----------
@@ -358,11 +293,326 @@ class Column(np.ndarray):
         _more_tabcol(self, max_lines=max_lines, show_name=show_name,
                      show_units=show_units)
 
+    @property
+    def units(self):
+        """
+        The units associated with this column.  May be a string or a
+        `astropy.units.UnitBase` instance.
+
+        Setting the `units` property does not change the values of the
+        data.  To perform a unit conversion, use `convert_units_to`.
+        """
+        return self._units
+
+    @units.setter
+    def units(self, units):
+        if units is None:
+            self._units = None
+        else:
+            self._units = Unit(units, parse_strict='silent')
+
+    @units.deleter
+    def units(self):
+        self._units = None
+
+    def convert_units_to(self, new_units):
+        """
+        Converts the values of the column in-place from the current
+        unit to the given unit.
+
+        To change the units associated with this column without
+        actually changing the data values, simply set the `units`
+        property.
+
+        Parameters
+        ----------
+        new_units : str or `astropy.units.UnitBase` instance
+            The unit to convert to.
+
+        Raises
+        ------
+        astropy.units.UnitException
+            If units are inconsistent
+        """
+        if self.units is None:
+            raise ValueError("No units set on column")
+        self.data[:] = self.units.to(new_units, self.data)
+        self.units = new_units
+
     def __str__(self):
         lines, n_header = _pformat_col(self)
         return '\n'.join(lines)
 
 
+class Column(BaseColumn, np.ndarray):
+    """Define a data column for use in a Table object.
+
+    Parameters
+    ----------
+    name : str
+        Column name and key for reference within Table
+    data : list, ndarray or None
+        Column data values
+    dtype : numpy.dtype compatible value
+        Data type for column
+    shape : tuple or ()
+        Dimensions of a single row element in the column data
+    length : int or 0
+        Number of row elements in column data
+    description : str or None
+        Full description of column
+    units : str or None
+        Physical units
+    format : str or None
+        Format string for outputting column values.  This can be an
+        "old-style" (``format % value``) or "new-style" (`str.format`)
+        format specification string.
+    meta : dict-like or None
+        Meta-data associated with the column
+
+    Examples
+    --------
+    A Column can be created in two different ways:
+
+    - Provide a ``data`` value and optionally a ``dtype`` value
+
+      Examples::
+
+        col = Column('name', data=[1, 2, 3])         # shape=(3,)
+        col = Column('name', data=[[1, 2], [3, 4]])  # shape=(2, 2)
+        col = Column('name', data=[1, 2, 3], dtype=float)
+        col = Column('name', np.array([1, 2, 3]))
+        col = Column('name', ['hello', 'world'])
+
+      The ``dtype`` argument can be any value which is an acceptable
+      fixed-size data-type initializer for the numpy.dtype() method.  See
+      `<http://docs.scipy.org/doc/numpy/reference/arrays.dtypes.html>`_.
+      Examples include:
+
+      - Python non-string type (float, int, bool)
+      - Numpy non-string type (e.g. np.float32, np.int64, np.bool)
+      - Numpy.dtype array-protocol type strings (e.g. 'i4', 'f8', 'S15')
+
+      If no ``dtype`` value is provide then the type is inferred using
+      ``np.array(data)``.  When ``data`` is provided then the ``shape``
+      and ``length`` arguments are ignored.
+
+    - Provide zero or more of ``dtype``, ``shape``, ``length``
+
+      Examples::
+
+        col = Column('name')
+        col = Column('name', dtype=int, length=10, shape=(3,4))
+
+      The default ``dtype`` is ``np.float64`` and the default ``length`` is
+      zero.  The ``shape`` argument is the array shape of a single cell in the
+      column.  The default ``shape`` is () which means a single value in each
+      element.
+    """
+
+    def __new__(cls, name, data=None,
+                 dtype=None, shape=(), length=0,
+                 description=None, units=None, format=None, meta=None):
+
+        if data is None:
+            dtype = (np.dtype(dtype).str, shape)
+            self_data = np.zeros(length, dtype=dtype)
+        elif isinstance(data, Column):
+            self_data = np.asarray(data.data, dtype=dtype)
+            if description is None:
+                description = data.description
+            if units is None:
+                units = units or data.units
+            if format is None:
+                format = data.format
+            if meta is None:
+                meta = deepcopy(data.meta)
+        elif isinstance(data, MaskedColumn):
+            raise TypeError("Cannot convert a MaskedColumn to a Column")
+        else:
+            self_data = np.asarray(data, dtype=dtype)
+
+        self = self_data.view(cls)
+        self._name = name
+        self.units = units
+        self.format = format
+        self.description = description
+        self.parent_table = None
+
+        self.meta = OrderedDict()
+        if meta is not None:
+            self.meta.update(meta)
+
+        return self
+
+    @property
+    def data(self):
+        return self.view(np.ndarray)
+
+    def copy(self, data=None, copy_data=True):
+        """Return a copy of the current Column instance.
+        """
+        if data is None:
+            data = self.view(np.ndarray)
+            if copy_data:
+                data = data.copy()
+
+        return Column(self.name, data, units=self.units, format=self.format,
+                      description=self.description, meta=deepcopy(self.meta))
+
+
+class MaskedColumn(BaseColumn, ma.MaskedArray):
+
+    def __new__(cls, name, data=None, mask=None, fill_value=None,
+                 dtype=None, shape=(), length=0,
+                 description=None, units=None, format=None, meta=None):
+
+        if NUMPY_LT_1P5:
+            raise ValueError('MaskedColumn requires NumPy version 1.5 or later')
+
+        if data is None:
+            dtype = (np.dtype(dtype).str, shape)
+            self_data = ma.zeros(length, dtype=dtype)
+        elif isinstance(data, (Column, MaskedColumn)):
+            self_data = ma.asarray(data.data, dtype=dtype)
+            if description is None:
+                description = data.description
+            if units is None:
+                units = units or data.units
+            if format is None:
+                format = data.format
+            if meta is None:
+                meta = deepcopy(data.meta)
+        else:
+            self_data = ma.asarray(data, dtype=dtype)
+
+        self = self_data.view(MaskedColumn)
+        if mask is None and hasattr(data, 'mask'):
+            mask = data.mask
+        if fill_value is None and hasattr(data, 'fill_value'):
+            fill_value = data.fill_value
+        self.mask = mask
+        self.fill_value = fill_value
+        self._name = name
+        self.units = units
+        self.format = format
+        self.description = description
+        self.parent_table = None
+
+        self.meta = OrderedDict()
+        if meta is not None:
+            self.meta.update(meta)
+
+        return self
+
+    def __array_finalize__(self, obj):
+        BaseColumn.__array_finalize__(self, obj)
+        ma.MaskedArray.__array_finalize__(self, obj)
+
+    def _fix_fill_value(self, val):
+        """Fix a fill value (if needed) to work around a bug with setting the fill
+        value of a string array in MaskedArray with Python 3.x.  See
+        https://github.com/numpy/numpy/pull/2733.  This mimics the check in
+        numpy.ma.core._check_fill_value() (version < 1.7) which incorrectly sets
+        fill_value to a default if self.dtype.char is 'U' (which is the case for Python
+        3).  Here we change the string to a byte string so that in Python 3 the
+        isinstance(val, basestring) part fails.
+        """
+        if isinstance(val, basestring) and (self.dtype.char not in 'SV'):
+            val = val.encode()
+        return val
+
+    @property
+    def fill_value(self):
+        return self.get_fill_value()  # defer to native ma.MaskedArray method
+
+    @fill_value.setter
+    def fill_value(self, val):
+        """Set fill value both in the masked column view and in the parent table
+        if it exists.  Setting one or the other alone doesn't work."""
+        val = self._fix_fill_value(val)
+
+        if self.parent_table:
+            self.parent_table._data[self._name].fill_value = val
+
+        # Yet another ma bug workaround: If the value of fill_value for a string array is
+        # requested but not yet set then it gets created as 'N/A'.  From this point onward
+        # any new fill_values are truncated to 3 characters.  Note that this does not
+        # occur if the masked array is a structured array (as in the previous block that
+        # deals with the parent table).
+        #
+        # >>> x = ma.array(['xxxx'])
+        # >>> x.fill_value  # fill_value now gets represented as an 'S3' array
+        # 'N/A'
+        # >>> x.fill_value='yyyy'
+        # >>> x.fill_value
+        # 'yyy'
+        #
+        # To handle this we are forced to reset a private variable first:
+        self._fill_value = None
+
+        self.set_fill_value(val)  # defer to native ma.MaskedArray method
+
+    @property
+    def data(self):
+        out = self.view(ma.MaskedArray)
+        # The following is necessary because of a bug in Numpy, which was
+        # fixed in numpy/numpy#2703. The fix should be included in Numpy 1.8.0.
+        out.fill_value = self.fill_value
+        return out
+
+    def filled(self, fill_value=None):
+        """Return a copy of self, with masked values filled with a given value.
+
+        Parameters
+        ----------
+        fill_value : scalar; optional
+            The value to use for invalid entries (None by default).
+            If None, the `fill_value` attribute of the array is used instead.
+
+        Returns
+        -------
+        filled_column : Column
+            A copy of ``self`` with masked entries replaced by `fill_value`
+            (be it the function argument or the attribute of ``self``).
+        """
+        if fill_value is None:
+            fill_value = self.fill_value
+        fill_value = self._fix_fill_value(fill_value)
+
+        data = super(MaskedColumn, self).filled(fill_value)
+        out = Column(self.name, data, units=self.units, format=self.format,
+                     description=self.description, meta=deepcopy(self.meta))
+        return out
+
+    def copy(self, data=None, copy_data=True):
+        """
+        Return a copy of the current MaskedColumn instance.
+
+        Parameters
+        ----------
+        data : array; optional
+            Data to use when creating MaskedColumn copy.  If not supplied the
+            column data array is used.
+        copy_data : boolean; optional
+            Make a copy of input data instead of using a reference (default=True)
+
+        Returns
+        -------
+        column : MaskedColumn
+            A copy of ``self``
+        """
+        if data is None:
+            data = self.view(ma.MaskedArray)
+            if copy_data:
+                data = data.copy()
+
+        return MaskedColumn(self.name, data, units=self.units, format=self.format,
+                            # Do not include mask=self.mask since `data` has the mask
+                            fill_value=self.fill_value,
+                            description=self.description, meta=deepcopy(self.meta))
+
+
 class Row(object):
     """A class to represent one row of a Table object.
 
@@ -386,6 +636,16 @@ class Row(object):
         self._index = index
         self._data = table._data[index]
 
+        # MaskedArray __getitem__ has a strange behavior where if a
+        # row mask is all False then it returns a np.void which
+        # has no mask attribute. This makes it impossible to then set
+        # the mask. Here we recast back to mvoid. This was fixed in
+        # Numpy following issue numpy/numpy#483, and the fix should be
+        # included in Numpy 1.8.0.
+        if self._table.masked and isinstance(self._data, np.void):
+            self._data = ma.core.mvoid(self._data,
+                                       mask=self._table._mask[index])
+
     def __getitem__(self, item):
         return self.data[item]
 
@@ -393,11 +653,22 @@ class Row(object):
         self.data[item] = val
 
     def __eq__(self, other):
+        if self._table.masked:
+            # Sent bug report to numpy-discussion group on 2012-Oct-21, subject:
+            # "Comparing rows in a structured masked array raises exception"
+            # No response, so this is still unresolved.
+            raise ValueError('Unable to compare rows for masked table due to numpy.ma bug')
         return self.data == other
 
     def __ne__(self, other):
+        if self._table.masked:
+            raise ValueError('Unable to compare rows for masked table due to numpy.ma bug')
         return self.data != other
 
+    @property
+    def _mask(self):
+        return self._data.mask
+
     def __array__(self, dtype=None):
         """Support converting Row to np.array via np.array(table).
 
@@ -441,7 +712,7 @@ class Row(object):
         return self.data.dtype
 
     def __repr__(self):
-        return "<Row {0} of table\n values={1}\n dtype={2}>".format(
+        return "<Row {0} of table\n values={1!r}\n dtype={2}>".format(
             self.index, self.data, self.dtype)
 
 
@@ -463,6 +734,8 @@ class Table(object):
     ----------
     data : numpy ndarray, dict, list, or Table, optional
         Data to initialize table.
+    mask : numpy ndarray, dict, list, optional
+        The mask to initialize the table
     names : list, optional
         Specify column names
     dtypes : list, optional
@@ -474,11 +747,12 @@ class Table(object):
 
     """
 
-    def __init__(self, data=None, names=None, dtypes=None, meta=None,
-                 copy=True):
+    def __init__(self, data=None, masked=None, names=None, dtypes=None,
+                 meta=None, copy=True):
 
         # Set up a placeholder empty table
         self._data = None
+        self._set_masked(masked)
         self.columns = TableColumns()
         self.meta = OrderedDict() if meta is None else deepcopy(meta)
 
@@ -539,6 +813,40 @@ class Table(object):
         # Finally do the real initialization
         init_func(data, names, dtypes, n_cols, copy)
 
+        # Whatever happens above, the masked property should be set to a boolean
+        if type(self.masked) != bool:
+            raise TypeError("masked property has not been set to True or False")
+
+        if NUMPY_LT_1P5 and self.masked:
+            raise ValueError('Masked table requires NumPy version 1.5 or later')
+
+    @property
+    def mask(self):
+        return self._data.mask if self.masked else None
+
+    @property
+    def _mask(self):
+        """This is needed due to intricacies in numpy.ma, don't remove it."""
+        return self._data.mask
+
+    def filled(self, fill_value=None):
+        """Return a copy of self, with masked values filled.
+
+        If input ``fill_value`` supplied then that value is used for all masked entries
+        in the table.  Otherwise the individual ``fill_value`` defined for each
+        table column is used.
+
+        Returns
+        -------
+        filled_table : Table
+            New table with masked values filled
+        """
+        if self.masked:
+            data = [col.filled(fill_value) for col in self.columns.values()]
+        else:
+            data = self
+        return Table(data, meta=deepcopy(self.meta))
+
     def __array__(self, dtype=None):
         """Support converting Table to np.array via np.array(table).
 
@@ -556,7 +864,8 @@ class Table(object):
         # array([(0, 0), (0, 0)],
         #       dtype=[('a', '<i8'), ('b', '<i8')])
 
-        return self._data
+        return self._data.data if self.masked else self._data
+
 
     def _check_names_dtypes(self, names, dtypes, n_cols):
         """Make sure that names and dtypes are boths iterable and have
@@ -571,6 +880,16 @@ class Table(object):
                 'Arguments "names" and "dtypes" must match number of columns'
                 .format(inp_str))
 
+    def _set_masked_from_cols(self, cols):
+        if self.masked is None:
+            if any(isinstance(col, (MaskedColumn, ma.MaskedArray)) for col in cols):
+                self._set_masked(True)
+            else:
+                self._set_masked(False)
+        elif not self.masked:
+            if any(isinstance(col, (MaskedColumn, ma.MaskedArray)) for col in cols):
+                self._set_masked(True)
+
     def _init_from_list(self, data, names, dtypes, n_cols, copy):
         """Initialize table from a list of columns.  A column can be a
         Column object, np.ndarray, or any other iterable object.
@@ -578,13 +897,16 @@ class Table(object):
         if not copy:
             raise ValueError('Cannot use copy=False with a list data input')
 
+        # Set self.masked appropriately, then get class to create column instances.
+        self._set_masked_from_cols(data)
+
         cols = []
         def_names = _auto_names(n_cols)
         for col, name, def_name, dtype in zip(data, names, def_names, dtypes):
-            if isinstance(col, Column):
-                col = Column((name or col.name), col, dtype=dtype)
+            if isinstance(col, (Column, MaskedColumn)):
+                col = self.ColumnClass((name or col.name), col, dtype=dtype)
             elif isinstance(col, np.ndarray) or isiterable(col):
-                col = Column((name or def_name), col, dtype=dtype)
+                col = self.ColumnClass((name or def_name), col, dtype=dtype)
             else:
                 raise ValueError('Elements in list initialization must be '
                                  'either Column or list-like')
@@ -602,14 +924,18 @@ class Table(object):
         cols = ([data[name] for name in data_names] if struct else
                 [data[:, i] for i in range(n_cols)])
 
+        # Set self.masked appropriately, then get class to create column instances.
+        self._set_masked_from_cols(cols)
+
         if copy:
             self._init_from_list(cols, names, dtypes, n_cols, copy)
         else:
             dtypes = [(name, col.dtype) for name, col in zip(names, cols)]
             self._data = data.view(dtypes).ravel()
             columns = TableColumns()
+
             for name in names:
-                columns[name] = Column(name, self._data[name])
+                columns[name] = self.ColumnClass(name, self._data[name])
                 columns[name].parent_table = self
             self.columns = columns
 
@@ -630,6 +956,9 @@ class Table(object):
         self.meta = deepcopy(table.meta)
         cols = table.columns.values()
 
+        # Set self.masked appropriately from cols
+        self._set_masked_from_cols(cols)
+
         if copy:
             self._init_from_list(cols, names, dtypes, n_cols, copy)
         else:
@@ -647,9 +976,13 @@ class Table(object):
             raise ValueError('Inconsistent data column lengths: {0}'
                              .format(lengths))
 
+        self._set_masked_from_cols(cols)
+        cols = [self.ColumnClass(col.name, col) for col in cols]
+
         names = [col.name for col in cols]
         dtypes = [col.descr for col in cols]
-        data = np.empty(lengths.pop(), dtype=dtypes)
+        empty_init = ma.empty if self.masked else np.empty
+        data = empty_init(lengths.pop(), dtype=dtypes)
         for col in cols:
             data[col.name] = col.data
 
@@ -697,14 +1030,14 @@ class Table(object):
                show_units=False):
         """Print a formatted string representation of the table.
 
-        If no value of ``max_lines`` is supplied then the height of the screen
-        terminal is used to set ``max_lines``.  If the terminal height cannot
-        be determined then a default of ``astropy.table.pprint.MAX_LINES`` is
-        used.  If a negative value of ``max_lines`` is supplied then there is
-        no line limit applied.
+        If no value of `max_lines` is supplied then the height of the screen
+        terminal is used to set `max_lines`.  If the terminal height cannot
+        be determined then the default is taken from the configuration item
+        `astropy.table.pprint.MAX_LINES`.  If a negative value of `max_lines`
+        is supplied then there is no line limit applied.
 
-        The Same applies for max_width except the default is
-        ``astropy.table.pprint.MAX_WIDTH``.
+        The same applies for max_width except the configuration item is
+        `astropy.table.pprint.MAX_WIDTH`.
 
         Parameters
         ----------
@@ -730,18 +1063,18 @@ class Table(object):
                 print line
 
     def pformat(self, max_lines=None, max_width=None, show_name=True,
-                show_units=False):
+                show_units=False, html=False):
         """Return a list of lines for the formatted string representation of
         the table.
 
-        If no value of ``max_lines`` is supplied then the height of the screen
-        terminal is used to set ``max_lines``.  If the terminal height cannot
-        be determined then a default of ``astropy.table.pprint.MAX_LINES`` is
-        used.  If a negative value of ``max_lines`` is supplied then there is
-        no line limit applied.
+        If no value of `max_lines` is supplied then the height of the screen
+        terminal is used to set `max_lines`.  If the terminal height cannot
+        be determined then the default is taken from the configuration item
+        `astropy.table.pprint.MAX_LINES`.  If a negative value of `max_lines`
+        is supplied then there is no line limit applied.
 
-        The Same applies for max_width except the default is
-        ``astropy.table.pprint.MAX_WIDTH``.
+        The same applies for max_width except the configuration item  is
+        `astropy.table.pprint.MAX_WIDTH`.
 
         Parameters
         ----------
@@ -757,13 +1090,16 @@ class Table(object):
         show_units : bool
             Include a header row for units (default=False)
 
+        html : bool
+            Format the output as an HTML table (default=False)
+
         Returns
         -------
         lines : list
             Formatted table as a list of strings
         """
         lines, n_header = _pformat_table(self, max_lines, max_width,
-                                         show_name, show_units)
+                                         show_name, show_units, html)
         return lines
 
     def more(self, max_lines=None, max_width=None, show_name=True,
@@ -799,6 +1135,10 @@ class Table(object):
         _more_tabcol(self, max_lines, max_width, show_name,
                      show_units)
 
+    def _repr_html_(self):
+        lines = self.pformat(html=True)
+        return ''.join(lines)
+
     def __getitem__(self, item):
         if isinstance(item, basestring):
             return self.columns[item]
@@ -851,6 +1191,53 @@ class Table(object):
         return self.columns[item]
 
     @property
+    def masked(self):
+        return self._masked
+
+    @masked.setter
+    def masked(self, masked):
+        raise Exception('Masked attribute is read-only (use t = Table(t, masked=True)'
+                        ' to convert to a masked table)')
+
+    def _set_masked(self, masked):
+        """
+        Set the table masked property.
+
+        Parameters
+        ----------
+        masked : bool
+            State of table masking (True or False)
+        """
+        if hasattr(self, '_masked'):
+            # The only allowed change is from None to False or True, or False to True
+            if self._masked is None and masked in [False, True]:
+                self._masked = masked
+            elif self._masked is False and masked is True:
+                log.info("Upgrading Table to masked Table")
+                self._masked = masked
+            elif self._masked is masked:
+                raise Exception("Masked attribute is already set to {0}".format(masked))
+            else:
+                raise Exception("Cannot change masked attribute to {0} once it is set to {1}"
+                                .format(masked, self._masked))
+        else:
+            if masked in [True, False, None]:
+                self._masked = masked
+            else:
+                raise ValueError("masked should be one of True, False, None")
+        if self._masked:
+            self._column_class = MaskedColumn
+        else:
+            self._column_class = Column
+
+    @property
+    def ColumnClass(self):
+        if self._column_class is None:
+            return Column
+        else:
+            return self._column_class
+
+    @property
     def dtype(self):
         return self._data.dtype
 
@@ -867,6 +1254,13 @@ class Table(object):
         else:
             return len(self._data)
 
+    def create_mask(self):
+        if isinstance(self._data, ma.MaskedArray):
+            raise Exception("data array is already masked")
+        else:
+            self._data = ma.array(self._data)
+
+
     def index_column(self, name):
         """
         Return the positional index of column ``name``.
@@ -973,7 +1367,7 @@ class Table(object):
 
     def keep_columns(self, names):
         '''
-        Keep only the columns specified (remove the others)
+        Keep only the columns specified (remove the others).
 
         Parameters
         ----------
@@ -1015,7 +1409,7 @@ class Table(object):
 
         self.columns[name].name = new_name
 
-    def add_row(self, vals=None):
+    def add_row(self, vals=None, mask=None):
         """Add a new row to the end of the table.
 
         The ``vals`` argument can be:
@@ -1032,36 +1426,88 @@ class Table(object):
         data.  In particular one cannot add a row to a Table that was
         initialized with copy=False from an existing array.
 
+        The ``mask`` attribute should give (if desired) the mask for the
+        values. The type of the mask should match that of the values, i.e. if
+        ``vals`` is an iterable, then ``mask`` should also be an iterable
+        with the same length, and if ``vals`` is a mapping, then ``mask``
+        should be a dictionary.
+
         Parameters
         ----------
         vals : tuple, list, dict or None
             Use the specified values in the new row
         """
+
+        def _is_mapping(obj):
+            """Minimal checker for mapping (dict-like) interface for obj"""
+            attrs = ('__getitem__', '__len__', '__iter__', 'keys', 'values', 'items')
+            return all(hasattr(obj, attr) for attr in attrs)
+
         newlen = len(self._data) + 1
-        self._data.resize((newlen,), refcheck=False)
 
-        if isinstance(vals, collections.Mapping):
-            row = self._data[-1]
+        if mask is not None and not self.masked:
+            self._set_masked(True)
+
+        if self.masked:
+            self._data = ma.resize(self._data, (newlen,))
+        else:
+            self._data.resize((newlen,), refcheck=False)
+
+        if _is_mapping(vals):
+
+            if mask is not None and not _is_mapping(mask):
+                raise TypeError("Mismatch between type of vals and mask")
+
+            # Now check that the mask is specified for the same keys as the
+            # values, otherwise things get really confusing.
+            if mask is not None and set(vals.keys()) != set(mask.keys()):
+                raise ValueError('keys in mask should match keys in vals')
+
+            if self.masked:
+                # We set the mask to True regardless of whether a mask value
+                # is specified or not - that is, any cell where a new row
+                # value is not specified should be treated as missing.
+                self._data.mask[-1] = (True,) * len(self._data.dtype)
+
+            # First we copy the values
             for name, val in vals.items():
                 try:
-                    row[name] = val
+                    self._data[name][-1] = val
                 except IndexError:
                     raise ValueError("No column {0} in table".format(name))
+                if mask:
+                    self._data[name].mask[-1] = mask[name]
 
         elif isiterable(vals):
+
+            if mask is not None and (not isiterable(mask) or _is_mapping(mask)):
+                raise TypeError("Mismatch between type of vals and mask")
+
             if len(self.columns) != len(vals):
                 raise ValueError('Mismatch between number of vals and columns')
+
             if not isinstance(vals, tuple):
                 vals = tuple(vals)
+
             self._data[-1] = vals
 
+            if mask is not None:
+
+                if len(self.columns) != len(mask):
+                    raise ValueError('Mismatch between number of masks and columns')
+
+                if not isinstance(mask, tuple):
+                    mask = tuple(mask)
+
+                self._data.mask[-1] = mask
+
         elif vals is not None:
             raise TypeError('Vals must be an iterable or mapping or None')
 
         # Add_row() probably corrupted the Column views of self._data.  Rebuild
         # self.columns.  Col.copy() takes an optional data reference that it
         # uses in the copy.
-        cols = [c.copy(self._data[c.name]) for c in self.columns.values()]
+        cols = [self.ColumnClass(c.name, c).copy(self._data[c.name]) for c in self.columns.values()]
         self.columns = TableColumns(cols)
 
     def sort(self, keys):
@@ -1084,3 +1530,59 @@ class Table(object):
         in place and there are no function arguments.
         '''
         self._data[:] = self._data[::-1].copy()
+
+    @classmethod
+    def read(cls, *args, **kwargs):
+        '''
+        Read a table
+
+        The arguments passed to this method depend on the format
+        '''
+
+        if 'format' in kwargs:
+            format = kwargs.pop('format')
+        else:
+            format = None
+
+        if format is None:
+
+            valid_formats = identify_format('read', args, kwargs)
+
+            if len(valid_formats) == 0:
+                raise Exception("Format could not be identified")
+            elif len(valid_formats) > 1:
+                raise Exception("Format is ambiguous - options are: {0:s}".format(', '.join(valid_formats)))
+            else:
+                format = valid_formats[0]
+
+        reader = get_reader(format)
+        table = reader(*args, **kwargs)
+        if not isinstance(table, cls):
+            raise TypeError("reader should return a {0:s} instance".format(cls.__name__))
+        return table
+
+    def write(self, *args, **kwargs):
+        '''
+        Write a table
+
+        The arguments passed to this method depend on the format
+        '''
+
+        if 'format' in kwargs:
+            format = kwargs.pop('format')
+        else:
+            format = None
+
+        if format is None:
+
+            valid_formats = identify_format('write', args, kwargs)
+
+            if len(valid_formats) == 0:
+                raise Exception("Format could not be identified")
+            elif len(valid_formats) > 1:
+                raise Exception("Format is ambiguous - options are: {0:s}".format(', '.join(valid_formats)))
+            else:
+                format = valid_formats[0]
+
+        writer = get_writer(format)
+        writer(self, *args, **kwargs)
diff --git a/astropy/table/tests/test_column.py b/astropy/table/tests/test_column.py
index a2ad273..9cc9b21 100644
--- a/astropy/table/tests/test_column.py
+++ b/astropy/table/tests/test_column.py
@@ -1,21 +1,31 @@
+from distutils import version
 import numpy as np
-from .. import Column
-from .. import pprint
+
+from ...tests.helper import pytest
+from ... import table
+
+numpy_lt_1p5 = version.LooseVersion(np.__version__) < version.LooseVersion('1.5')
+
+# Fixture to run all the Column tests for both an unmasked (ndarray)
+# and masked (MaskedArray) column.
+ at pytest.fixture(params=[table.Column] if numpy_lt_1p5 else [table.Column, table.MaskedColumn])
+def Column(request):
+    return request.param
 
 
 class TestColumn():
 
-    def test_1(self):
+    def test_1(self, Column):
         Column('a')
 
-    def test_subclass(self):
+    def test_subclass(self, Column):
         c = Column('a')
         assert isinstance(c, np.ndarray)
         c2 = c * 2
         assert isinstance(c2, Column)
         assert isinstance(c2, np.ndarray)
 
-    def test_numpy_ops(self):
+    def test_numpy_ops(self, Column):
         """Show that basic numpy operations with Column behave sensibly"""
 
         arr = np.array([1, 2, 3])
@@ -31,21 +41,26 @@ class TestColumn():
         lt = c - 1 < arr
         assert np.all(lt)
 
-    def test_view(self):
+    def test_view(self, Column):
         c = np.array([1, 2, 3]).view(Column)
-        assert repr(c) == 'array([1, 2, 3])'
-
-    def test_format(self):
+        if Column == table.MaskedColumn:
+            assert repr(c) == ('masked_array(data = [1 2 3],\n'
+                               '             mask = False,\n'
+                               '       fill_value = 999999)\n')
+        else:
+            assert repr(c) == 'array([1, 2, 3])'
+
+    def test_format(self, Column):
         """Show that the formatted output from str() works"""
-        MAX_LINES = pprint.MAX_LINES
-        pprint.MAX_LINES = 7
+        MAX_LINES_val = table.pprint.MAX_LINES()
+        table.pprint.MAX_LINES.set(7)
         c1 = Column(name='a', data=np.arange(2000), dtype=float,
                     format='%6.2f')
         assert str(c1) == ('   a   \n-------\n   0.00\n'
                            '   1.00\n    ...\n1998.00\n1999.00')
-        pprint.MAX_LINES = MAX_LINES
+        table.pprint.MAX_LINES.set(MAX_LINES_val)
 
-    def test_convert_numpy_array(self):
+    def test_convert_numpy_array(self, Column):
         d = Column('a', [1, 2, 3], dtype='i8')
 
         np_data = np.array(d)
@@ -55,67 +70,117 @@ class TestColumn():
         np_data = np.array(d, dtype='i4')
         assert np.all(np_data == d)
 
+    def test_convert_units(self, Column):
+        d = Column('a', [1, 2, 3], dtype="f8", units="m")
+        d.convert_units_to("km")
+        assert np.all(d.data == [0.001, 0.002, 0.003])
+
+    def test_array_wrap(self):
+        """Test that the __array_wrap__ method converts a reduction ufunc
+        output that has a different shape into an ndarray view.  Without this a
+        method call like c.mean() returns a Column array object with length=1."""
+        # Mean and sum for a 1-d float column
+        c = table.Column('a', [1., 2., 3.])
+        assert np.allclose(c.mean(), 2.0)
+        assert isinstance(c.mean(), (np.floating, float))
+        assert np.allclose(c.sum(), 6.)
+        assert isinstance(c.sum(), (np.floating, float))
+
+        # Non-reduction ufunc preserves Column class
+        assert isinstance(np.cos(c), table.Column)
+
+        # Sum for a 1-d int column
+        c = table.Column('a', [1, 2, 3])
+        assert np.allclose(c.sum(), 6)
+        assert isinstance(c.sum(), (np.integer, int))
+
+        # Sum for a 2-d int column
+        c = table.Column('a', [[1, 2, 3],
+                               [4, 5, 6]])
+        assert c.sum() == 21
+        assert isinstance(c.sum(), (np.integer, int))
+        assert np.all(c.sum(axis=0) == [5, 7, 9])
+        assert c.sum(axis=0).shape == (3,)
+        assert isinstance(c.sum(axis=0), np.ndarray)
+
+        if not numpy_lt_1p5:
+            # Sum and mean for a 1-d masked column
+            c = table.MaskedColumn('a', [1., 2., 3.], mask=[0, 0, 1])
+            assert np.allclose(c.mean(), 1.5)
+            assert isinstance(c.mean(), (np.floating, float))
+            assert np.allclose(c.sum(), 3.)
+            assert isinstance(c.sum(), (np.floating, float))
+
 
 class TestAttrEqual():
     """Bunch of tests originally from ATpy that test the attrs_equal method."""
 
-    def test_5(self):
+    def test_5(self, Column):
         c1 = Column(name='a', dtype=int, units='mJy')
         c2 = Column(name='a', dtype=int, units='mJy')
         assert c1.attrs_equal(c2)
 
-    def test_6(self):
+    def test_6(self, Column):
         c1 = Column(name='a', dtype=int, units='mJy', format='%i',
                     description='test column', meta={'c': 8, 'd': 12})
         c2 = Column(name='a', dtype=int, units='mJy', format='%i',
                     description='test column', meta={'c': 8, 'd': 12})
         assert c1.attrs_equal(c2)
 
-    def test_7(self):
+    def test_7(self, Column):
         c1 = Column(name='a', dtype=int, units='mJy', format='%i',
                     description='test column', meta={'c': 8, 'd': 12})
         c2 = Column(name='b', dtype=int, units='mJy', format='%i',
                     description='test column', meta={'c': 8, 'd': 12})
         assert not c1.attrs_equal(c2)
 
-    def test_8(self):
+    def test_8(self, Column):
         c1 = Column(name='a', dtype=int, units='mJy', format='%i',
                     description='test column', meta={'c': 8, 'd': 12})
         c2 = Column(name='a', dtype=float, units='mJy', format='%i',
                     description='test column', meta={'c': 8, 'd': 12})
         assert not c1.attrs_equal(c2)
 
-    def test_9(self):
+    def test_9(self, Column):
         c1 = Column(name='a', dtype=int, units='mJy', format='%i',
                     description='test column', meta={'c': 8, 'd': 12})
-        c2 = Column(name='a', dtype=int, units='ergs/cm^2/s/Hz', format='%i',
+        c2 = Column(name='a', dtype=int, units='erg.cm-2.s-1.Hz-1', format='%i',
                     description='test column', meta={'c': 8, 'd': 12})
         assert not c1.attrs_equal(c2)
 
-    def test_10(self):
+    def test_10(self, Column):
         c1 = Column(name='a', dtype=int, units='mJy', format='%i',
                     description='test column', meta={'c': 8, 'd': 12})
         c2 = Column(name='a', dtype=int, units='mJy', format='%g',
                     description='test column', meta={'c': 8, 'd': 12})
         assert not c1.attrs_equal(c2)
 
-    def test_11(self):
+    def test_11(self, Column):
         c1 = Column(name='a', dtype=int, units='mJy', format='%i',
                     description='test column', meta={'c': 8, 'd': 12})
         c2 = Column(name='a', dtype=int, units='mJy', format='%i',
                     description='another test column', meta={'c': 8, 'd': 12})
         assert not c1.attrs_equal(c2)
 
-    def test_12(self):
+    def test_12(self, Column):
         c1 = Column(name='a', dtype=int, units='mJy', format='%i',
                     description='test column', meta={'c': 8, 'd': 12})
         c2 = Column(name='a', dtype=int, units='mJy', format='%i',
                     description='test column', meta={'e': 8, 'd': 12})
         assert not c1.attrs_equal(c2)
 
-    def test_13(self):
+    def test_13(self, Column):
         c1 = Column(name='a', dtype=int, units='mJy', format='%i',
                     description='test column', meta={'c': 8, 'd': 12})
         c2 = Column(name='a', dtype=int, units='mJy', format='%i',
                     description='test column', meta={'c': 9, 'd': 12})
         assert not c1.attrs_equal(c2)
+
+    @pytest.mark.xfail('numpy_lt_1p5')
+    def test_col_and_masked_col(self):
+        c1 = table.Column(name='a', dtype=int, units='mJy', format='%i',
+                          description='test column', meta={'c': 8, 'd': 12})
+        c2 = table.MaskedColumn(name='a', dtype=int, units='mJy', format='%i',
+                                description='test column', meta={'c': 8, 'd': 12})
+        assert c1.attrs_equal(c2)
+        assert c2.attrs_equal(c1)
diff --git a/astropy/table/tests/test_init_table.py b/astropy/table/tests/test_init_table.py
index 0509eb7..6f32c75 100644
--- a/astropy/table/tests/test_init_table.py
+++ b/astropy/table/tests/test_init_table.py
@@ -1,12 +1,35 @@
 from __future__ import print_function  # For print debugging with python 2 or 3
 
-import pytest
+from distutils import version
+
 import numpy as np
 
-from .. import Table, Column
-from astropy.utils import OrderedDict
+from ...tests.helper import pytest
+from ... import table
+from ...table import Column
+from ...utils import OrderedDict
+
+numpy_lt_1p5 = version.LooseVersion(np.__version__) < version.LooseVersion('1.5')
+
+# Dummy init of Table for pyflakes and to be sure test fixture is working
+Table = None
+
+
+class MaskedTable(table.Table):
+    def __init__(self, *args, **kwargs):
+        kwargs['masked'] = True
+        table.Table.__init__(self, *args, **kwargs)
+
+
+# Fixture to run all the Column tests for both an unmasked (ndarray)
+# and masked (MaskedArray) column.
+ at pytest.fixture(params=[False] if numpy_lt_1p5 else [False, True])
+def set_global_Table(request):
+    global Table
+    Table = MaskedTable if request.param else table.Table
 
 
+ at pytest.mark.usefixtures('set_global_Table')
 class BaseInitFrom():
 
     def test_basic_init(self):
@@ -37,6 +60,7 @@ class BaseInitFrom():
             Table(self.data, names=('a',), dtypes=('i4'))
 
 
+ at pytest.mark.usefixtures('set_global_Table')
 class BaseInitFromListLike(BaseInitFrom):
 
     def test_names_cols_mismatch(self):
@@ -48,10 +72,12 @@ class BaseInitFromListLike(BaseInitFrom):
             Table(self.data, names=['a'], dtypes=[int], copy=False)
 
 
+ at pytest.mark.usefixtures('set_global_Table')
 class BaseInitFromDictLike(BaseInitFrom):
     pass
 
 
+ at pytest.mark.usefixtures('set_global_Table')
 class TestInitFromNdarrayHomo(BaseInitFromListLike):
 
     def setup_method(self, method):
@@ -91,6 +117,7 @@ class TestInitFromNdarrayHomo(BaseInitFromListLike):
         assert all(t[name].name == name for name in t.colnames)
 
 
+ at pytest.mark.usefixtures('set_global_Table')
 class TestInitFromListOfLists(BaseInitFromListLike):
 
     def setup_method(self, method):
@@ -118,6 +145,7 @@ class TestInitFromListOfLists(BaseInitFromListLike):
                    [3, 4, 5]])
 
 
+ at pytest.mark.usefixtures('set_global_Table')
 class TestInitFromColsList(BaseInitFromListLike):
 
     def setup_method(self, method):
@@ -143,6 +171,7 @@ class TestInitFromColsList(BaseInitFromListLike):
             Table(self.data, copy=False)
 
 
+ at pytest.mark.usefixtures('set_global_Table')
 class TestInitFromNdarrayStruct(BaseInitFromDictLike):
 
     def setup_method(self, method):
@@ -178,6 +207,7 @@ class TestInitFromNdarrayStruct(BaseInitFromDictLike):
         assert all(t[name].name == name for name in t.colnames)
 
 
+ at pytest.mark.usefixtures('set_global_Table')
 class TestInitFromDict(BaseInitFromDictLike):
 
     def setup_method(self, method):
@@ -186,6 +216,7 @@ class TestInitFromDict(BaseInitFromDictLike):
                           ('c', np.array([3, 5], dtype='i8'))])
 
 
+ at pytest.mark.usefixtures('set_global_Table')
 class TestInitFromOrderedDict(BaseInitFromDictLike):
 
     def setup_method(self, method):
@@ -198,6 +229,7 @@ class TestInitFromOrderedDict(BaseInitFromDictLike):
         assert t.colnames == ['a', 'b', 'c']
 
 
+ at pytest.mark.usefixtures('set_global_Table')
 class TestInitFromTable(BaseInitFromDictLike):
 
     def setup_method(self, method):
@@ -261,6 +293,7 @@ class TestInitFromTable(BaseInitFromDictLike):
         assert t2._data.dtype.names == ('x', 'z')
 
 
+ at pytest.mark.usefixtures('set_global_Table')
 class TestInitFromNone():
     # Note table_table.TestEmptyData tests initializing a completely empty
     # table and adding data.
diff --git a/astropy/table/tests/test_item_access.py b/astropy/table/tests/test_item_access.py
index a017a34..cd293d7 100644
--- a/astropy/table/tests/test_item_access.py
+++ b/astropy/table/tests/test_item_access.py
@@ -1,31 +1,60 @@
 """ Verify item access API in:
 https://github.com/astropy/astropy/wiki/Table-item-access-definition
 """
-from .. import Table, Column
+from distutils import version
 import numpy as np
-import pytest
 
-COLS = [Column('a', [1, 2, 3], description='da',
-               format='fa', meta={'ma': 1}, units='ua'),
-        Column('b', [4, 5, 6], description='db',
-               format='fb', meta={'mb': 1}, units='ub'),
-        Column('c', [7, 8, 9], description='dc',
-               format='fc', meta={'mc': 1}, units='ub')]
-DATA = Table(COLS)
+from ...tests.helper import pytest
+from ... import table
 
+numpy_lt_1p5 = version.LooseVersion(np.__version__) < version.LooseVersion('1.5')
 
+# Dummy init of Table, DATA for pyflakes and to be sure test fixture is working
+Table = None
+Column = None
+DATA = None
+COLS = None
+
+
+class MaskedTable(table.Table):
+    def __init__(self, *args, **kwargs):
+        kwargs['masked'] = True
+        table.Table.__init__(self, *args, **kwargs)
+
+
+# Fixture to run all the Column tests for both an unmasked (ndarray)
+# and masked (MaskedArray) column.
+ at pytest.fixture(params=[False] if numpy_lt_1p5 else [False, True])
+def set_global_Table_DATA(request):
+    global Table, Column, DATA, COLS
+
+    Table = MaskedTable if request.param else table.Table
+    Column = table.MaskedColumn if request.param else table.Column
+    COLS = [Column('a', [1, 2, 3], description='da',
+                   format='fa', meta={'ma': 1}, units='ua'),
+            Column('b', [4, 5, 6], description='db',
+                   format='fb', meta={'mb': 1}, units='ub'),
+            Column('c', [7, 8, 9], description='dc',
+                   format='fc', meta={'mc': 1}, units='ub')]
+    DATA = Table(COLS)
+
+
+ at pytest.mark.usefixtures('set_global_Table_DATA')
 class BaseTestItems():
 
     def setup_method(self, method):
-        self.t = Table(COLS)
-        self.tc = self.t.columns
+        pass
 
 
+ at pytest.mark.usefixtures('set_global_Table_DATA')
 class TestTableColumnsItems(BaseTestItems):
 
     def test_by_name(self):
         """Access TableColumns by name and show that item access returns
         a Column that refers to underlying table data"""
+        self.t = Table(COLS)
+        self.tc = self.t.columns
+
         assert self.tc['a'].name == 'a'
         assert self.tc['a'][1] == 2
         assert self.tc['a'].description == 'da'
@@ -41,6 +70,9 @@ class TestTableColumnsItems(BaseTestItems):
     def test_by_position(self):
         """Access TableColumns by position and show that item access returns
         a Column that refers to underlying table data"""
+        self.t = Table(COLS)
+        self.tc = self.t.columns
+
         assert self.tc[1].name == 'b'
         assert np.all(self.tc[1].data == COLS[1].data)
         assert self.tc[1].description == 'db'
@@ -50,12 +82,17 @@ class TestTableColumnsItems(BaseTestItems):
         assert self.tc[1].attrs_equal(COLS[1])
         assert isinstance(self.tc[1], Column)
 
+        assert self.tc[2].units == 'ub'
+
         self.tc[1][1] = 0
         assert self.t['b'][1] == 0
 
     def test_mult_columns(self):
         """Access TableColumns with "fancy indexing" and showed that returned
         TableColumns object still references original data"""
+        self.t = Table(COLS)
+        self.tc = self.t.columns
+
         tc2 = self.tc['b', 'c']
         assert tc2[1].name == 'c'
         assert tc2[1][1] == 8
@@ -69,6 +106,9 @@ class TestTableColumnsItems(BaseTestItems):
     def test_column_slice(self):
         """Access TableColumns with slice and showed that returned
         TableColumns object still references original data"""
+        self.t = Table(COLS)
+        self.tc = self.t.columns
+
         tc2 = self.tc[1:3]
         assert tc2[1].name == 'c'
         assert tc2[1][1] == 8
@@ -80,10 +120,14 @@ class TestTableColumnsItems(BaseTestItems):
         assert self.t['c'][1] == 0
 
 
+ at pytest.mark.usefixtures('set_global_Table_DATA')
 class TestTableItems(BaseTestItems):
 
     def test_column(self):
         """Column access returns REFERENCE to data"""
+        self.t = Table(COLS)
+        self.tc = self.t.columns
+
         a = self.t['a']
         assert a[1] == 2
         a[1] = 0
@@ -91,6 +135,9 @@ class TestTableItems(BaseTestItems):
 
     def test_row(self):
         """Row  access returns REFERENCE to data"""
+        self.t = Table(COLS)
+        self.tc = self.t.columns
+
         row = self.t[1]
         assert row['a'] == 2
         assert row[1] == 5
@@ -99,10 +146,15 @@ class TestTableItems(BaseTestItems):
         assert row.columns['c'].attrs_equal(COLS[2])
         row[1] = 0
         assert row[1] == 0
-        assert self.t['b'][1] == 0
+        if Table is not MaskedTable:
+            # numpy.core.ma.mvoid makes a copy so this test is skipped for masked table
+            assert self.t['b'][1] == 0
 
     def test_table_slice(self):
         """Table slice returns REFERENCE to data"""
+        self.t = Table(COLS)
+        self.tc = self.t.columns
+
         t2 = self.t[1:3]
         assert np.all(t2['a'] == DATA['a'][1:3])
         assert t2['a'].attrs_equal(COLS[0])
@@ -113,6 +165,9 @@ class TestTableItems(BaseTestItems):
 
     def test_fancy_index_slice(self):
         """Table fancy slice returns COPY of data"""
+        self.t = Table(COLS)
+        self.tc = self.t.columns
+
         slice = np.array([0, 2])
         t2 = self.t[slice]
         assert np.all(t2['a'] == DATA['a'][slice])
@@ -121,10 +176,13 @@ class TestTableItems(BaseTestItems):
         assert t2['c'].attrs_equal(COLS[2])
         t2['a'][0] = 0
         assert np.all(self.t._data == DATA)
-        assert np.any(t2['a'] != DATA['a'])
+        assert np.any(t2['a'] != DATA['a'][slice])
 
     def test_list_index_slice(self):
         """Table list index slice returns COPY of data"""
+        self.t = Table(COLS)
+        self.tc = self.t.columns
+
         slice = [0, 2]
         t2 = self.t[slice]
         assert np.all(t2['a'] == DATA['a'][slice])
@@ -133,11 +191,14 @@ class TestTableItems(BaseTestItems):
         assert t2['c'].attrs_equal(COLS[2])
         t2['a'][0] = 0
         assert np.all(self.t._data == DATA)
-        assert np.any(t2['a'] != DATA['a'])
+        assert np.any(t2['a'] != DATA['a'][slice])
 
     def test_select_columns(self):
         """Select columns returns COPY of data and all column
         attributes"""
+        self.t = Table(COLS)
+        self.tc = self.t.columns
+
         t2 = self.t['a', 'c']
         assert np.all(t2['a'] == DATA['a'])
         assert np.all(t2['c'] == DATA['c'])
@@ -149,5 +210,8 @@ class TestTableItems(BaseTestItems):
 
     def test_select_bad_column(self):
         """Select column name that does not exist"""
+        self.t = Table(COLS)
+        self.tc = self.t.columns
+
         with pytest.raises(ValueError):
             self.t['a', 1]
diff --git a/astropy/table/tests/test_masked.py b/astropy/table/tests/test_masked.py
new file mode 100644
index 0000000..e8dc78f
--- /dev/null
+++ b/astropy/table/tests/test_masked.py
@@ -0,0 +1,329 @@
+"""Test behavior related to masked tables"""
+
+from distutils import version
+import numpy as np
+import numpy.ma as ma
+
+from ...tests.helper import pytest
+from ...table import Column, MaskedColumn, Table
+
+numpy_lt_1p5 = version.LooseVersion(np.__version__) < version.LooseVersion('1.5')
+
+
+class SetupData(object):
+    def setup_method(self, method):
+        self.a = MaskedColumn('a', [1, 2, 3], fill_value=1)
+        self.b = MaskedColumn('b', [4, 5, 6], mask=True)
+        self.c = MaskedColumn('c', [7, 8, 9], mask=False)
+        self.d_mask = np.array([False, True, False])
+        self.d = MaskedColumn('d', [7, 8, 7], mask=self.d_mask)
+        self.t = Table([self.a, self.b], masked=True)
+        self.ca = Column('ca', [1, 2, 3])
+
+
+ at pytest.mark.xfail('numpy_lt_1p5')
+class TestPprint(SetupData):
+    def test_pformat(self):
+        assert self.t.pformat() == [' a   b ', '--- ---', '  1  --', '  2  --', '  3  --']
+
+
+ at pytest.mark.xfail('numpy_lt_1p5')
+class TestFilled(object):
+    """Test the filled method in MaskedColumn and Table"""
+    def setup_method(self, method):
+        mask = [True, False, False]
+        self.meta = {'a': 1, 'b': [2, 3]}
+        a = self.a = MaskedColumn('a', [1, 2, 3], fill_value=10, mask=mask, meta={'a': 1})
+        b = self.b = MaskedColumn('b', [4.0, 5.0, 6.0], fill_value=10.0, mask=mask)
+        c = self.c = MaskedColumn('c', ['7', '8', '9'], fill_value='1', mask=mask)
+
+    def test_filled_column(self):
+        f = self.a.filled()
+        assert np.all(f == [10, 2, 3])
+        assert isinstance(f, Column)
+        assert not isinstance(f, MaskedColumn)
+
+        # Confirm copy, not ref
+        assert f.meta['a'] == 1
+        f.meta['a'] = 2
+        f[1] = 100
+        assert self.a[1] == 2
+        assert self.a.meta['a'] == 1
+
+        # Fill with arg fill_value not column fill_value
+        f = self.a.filled(20)
+        assert np.all(f == [20, 2, 3])
+
+        f = self.b.filled()
+        assert np.all(f == [10.0, 5.0, 6.0])
+        assert isinstance(f, Column)
+
+        f = self.c.filled()
+        assert np.all(f == ['1', '8', '9'])
+        assert isinstance(f, Column)
+
+    def test_filled_masked_table(self):
+        t = Table([self.a, self.b, self.c], meta=self.meta)
+
+        f = t.filled()
+        assert isinstance(f, Table)
+        assert f.masked is False
+        assert np.all(f['a'] == [10, 2, 3])
+        assert np.allclose(f['b'], [10.0, 5.0, 6.0])
+        assert np.all(f['c'] == ['1', '8', '9'])
+
+        # Confirm copy, not ref
+        assert f.meta['b'] == [2, 3]
+        f.meta['b'][0] = 20
+        assert t.meta['b'] == [2, 3]
+        f['a'][2] = 100
+        assert t['a'][2] == 3
+
+    def test_filled_unmasked_table(self):
+        t = Table([(1, 2), ('3', '4')], names=('a', 'b'), meta=self.meta)
+        f = t.filled()
+        assert isinstance(f, Table)
+        assert f.masked is False
+        assert np.all(f['a'] == t['a'])
+        assert np.all(f['b'] == t['b'])
+
+        # Confirm copy, not ref
+        assert f.meta['b'] == [2, 3]
+        f.meta['b'][0] = 20
+        assert t.meta['b'] == [2, 3]
+        f['a'][1] = 100
+        assert t['a'][1] == 2
+
+
+ at pytest.mark.xfail('numpy_lt_1p5')
+class TestFillValue(SetupData):
+    """Test setting and getting fill value in MaskedColumn and Table"""
+
+    def test_init_set_fill_value(self):
+        """Check that setting fill_value in the MaskedColumn init works"""
+        assert self.a.fill_value == 1
+        c = MaskedColumn('c', ['xxxx', 'yyyy'], fill_value='none')
+        assert c.fill_value == 'none'
+
+    def test_set_get_fill_value_for_bare_column(self):
+        """Check set and get of fill value works for bare Column"""
+        self.d.fill_value = -999
+        assert self.d.fill_value == -999
+        assert np.all(self.d.filled() == [7, -999, 7])
+
+    def test_set_get_fill_value_for_str_column(self):
+        c = MaskedColumn('c', ['xxxx', 'yyyy'], mask=[True, False])
+        # assert np.all(c.filled() == ['N/A', 'yyyy'])
+        c.fill_value = 'ABCDEF'
+        assert c.fill_value == 'ABCD'  # string truncated to dtype length
+        assert np.all(c.filled() == ['ABCD', 'yyyy'])
+        assert np.all(c.filled('XY') == ['XY', 'yyyy'])
+
+    def test_table_column_mask_not_ref(self):
+        """Table column mask is not ref of original column mask"""
+        self.b.fill_value = -999
+        assert self.t['b'].fill_value != -999
+
+    def test_set_get_fill_value_for_table_column(self):
+        """Check set and get of fill value works for Column in a Table"""
+        self.t['b'].fill_value = 1
+        assert self.t['b'].fill_value == 1
+        assert np.all(self.t['b'].filled() == [1, 1, 1])
+        assert self.t._data['b'].fill_value == 1
+
+    def test_data_attribute_fill_and_mask(self):
+        """Check that .data attribute preserves fill_value and mask"""
+        self.t['b'].fill_value = 1
+        self.t['b'].mask = [True, False, True]
+        assert self.t['b'].data.fill_value == 1
+        assert np.all(self.t['b'].data.mask == [True, False, True])
+
+
+ at pytest.mark.xfail('numpy_lt_1p5')
+class TestMaskedColumnInit(SetupData):
+    """Initialization of a masked column"""
+
+    def test_set_mask_and_not_ref(self):
+        """Check that mask gets set properly and that it is a copy, not ref"""
+        assert np.all(self.a.mask == False)
+        assert np.all(self.b.mask == True)
+        assert np.all(self.c.mask == False)
+        assert np.all(self.d.mask == self.d_mask)
+        self.d.mask[0] = True
+        assert not np.all(self.d.mask == self.d_mask)
+
+    def test_set_mask_from_list(self):
+        """Set mask from a list"""
+        mask_list = [False, True, False]
+        a = MaskedColumn('a', [1, 2, 3], mask=mask_list)
+        assert np.all(a.mask == mask_list)
+
+    def test_override_existing_mask(self):
+        """Override existing mask values"""
+        mask_list = [False, True, False]
+        b = MaskedColumn('b', self.b, mask=mask_list)
+        assert np.all(b.mask == mask_list)
+
+    def test_incomplete_mask_spec(self):
+        """Incomplete mask specification (mask values cycle through available)"""
+        mask_list = [False, True]
+        b = MaskedColumn('b', length=4, mask=mask_list)
+        assert np.all(b.mask == mask_list + mask_list)
+
+
+ at pytest.mark.xfail('numpy_lt_1p5')
+class TestTableInit(SetupData):
+    """Initializing a table"""
+
+    def test_mask_true_if_any_input_masked(self):
+        """Masking is True if any input is masked"""
+        t = Table([self.ca, self.a])
+        assert t.masked is True
+        t = Table([self.ca])
+        assert t.masked is False
+        t = Table([self.ca, ma.array([1, 2, 3])])
+        assert t.masked is True
+
+    def test_mask_property(self):
+        t = self.t
+        # Access table mask (boolean structured array) by column name
+        assert np.all(t.mask['a'] == np.array([False, False, False]))
+        assert np.all(t.mask['b'] == np.array([True, True, True]))
+        # Check that setting mask from table mask has the desired effect on column
+        t.mask['b'] = np.array([False, True, False])
+        assert np.all(t['b'].mask == np.array([False, True, False]))
+        # Non-masked table returns None for mask attribute
+        t2 = Table([self.ca], masked=False)
+        assert t2.mask is None
+
+
+ at pytest.mark.xfail('numpy_lt_1p5')
+class TestAddColumn(object):
+
+    def test_add_masked_column_to_masked_table(self):
+        t = Table(masked=True)
+        assert t.masked
+        t.add_column(MaskedColumn('a', [1,2,3], mask=[0,1,0]))
+        assert t.masked
+        t.add_column(MaskedColumn('b', [4,5,6], mask=[1,0,1]))
+        assert t.masked
+        assert np.all(t['a'] == np.array([1,2,3]))
+        assert np.all(t['a'].mask == np.array([0,1,0], bool))
+        assert np.all(t['b'] == np.array([4,5,6]))
+        assert np.all(t['b'].mask == np.array([1,0,1], bool))
+
+    def test_add_masked_column_to_non_masked_table(self):
+        t = Table(masked=False)
+        assert not t.masked
+        t.add_column(Column('a', [1,2,3]))
+        assert not t.masked
+        t.add_column(MaskedColumn('b', [4,5,6], mask=[1,0,1]))
+        assert t.masked
+        assert np.all(t['a'] == np.array([1,2,3]))
+        assert np.all(t['a'].mask == np.array([0,0,0], bool))
+        assert np.all(t['b'] == np.array([4,5,6]))
+        assert np.all(t['b'].mask == np.array([1,0,1], bool))
+
+    def test_add_non_masked_column_to_masked_table(self):
+        t = Table(masked=True)
+        assert t.masked
+        t.add_column(Column('a', [1,2,3]))
+        assert t.masked
+        t.add_column(MaskedColumn('b', [4,5,6], mask=[1,0,1]))
+        assert t.masked
+        assert np.all(t['a'] == np.array([1,2,3]))
+        assert np.all(t['a'].mask == np.array([0,0,0], bool))
+        assert np.all(t['b'] == np.array([4,5,6]))
+        assert np.all(t['b'].mask == np.array([1,0,1], bool))
+
+
+ at pytest.mark.xfail('numpy_lt_1p5')
+class TestAddRow(object):
+
+    def test_add_masked_row_to_masked_table_iterable(self):
+        t = Table(masked=True)
+        t.add_column(MaskedColumn('a', [1], mask=[0]))
+        t.add_column(MaskedColumn('b', [4], mask=[1]))
+        t.add_row([2,5], mask=[1,0])
+        t.add_row([3,6], mask=[0,1])
+        assert t.masked
+        assert np.all(np.array(t['a']) == np.array([1,2,3]))
+        assert np.all(t['a'].mask == np.array([0,1,0], bool))
+        assert np.all(np.array(t['b']) == np.array([4,5,6]))
+        assert np.all(t['b'].mask == np.array([1,0,1], bool))
+
+    def test_add_masked_row_to_masked_table_mapping1(self):
+        t = Table(masked=True)
+        t.add_column(MaskedColumn('a', [1], mask=[0]))
+        t.add_column(MaskedColumn('b', [4], mask=[1]))
+        t.add_row({'b':5, 'a':2}, mask={'a':1, 'b':0})
+        t.add_row({'a':3, 'b':6}, mask={'b':1, 'a':0})
+        assert t.masked
+        assert np.all(np.array(t['a']) == np.array([1,2,3]))
+        assert np.all(t['a'].mask == np.array([0,1,0], bool))
+        assert np.all(np.array(t['b']) == np.array([4,5,6]))
+        assert np.all(t['b'].mask == np.array([1,0,1], bool))
+
+    def test_add_masked_row_to_masked_table_mapping2(self):
+        # When adding values to a masked table, if the mask is specified as a
+        # dict, then values not specified will have mask values set to True
+        t = Table(masked=True)
+        t.add_column(MaskedColumn('a', [1], mask=[0]))
+        t.add_column(MaskedColumn('b', [4], mask=[1]))
+        t.add_row({'b':5}, mask={'b':0})
+        t.add_row({'a':3}, mask={'a':0})
+        assert t.masked
+        assert t['a'][0] == 1 and t['a'][2] == 3
+        assert np.all(t['a'].mask == np.array([0,1,0], bool))
+        assert t['b'][1] == 5
+        assert np.all(t['b'].mask == np.array([1,0,1], bool))
+
+    def test_add_masked_row_to_masked_table_mapping3(self):
+        # When adding values to a masked table, if mask is not passed to
+        # add_row, then the mask should be set to False if values are present
+        # and True if not.
+        t = Table(masked=True)
+        t.add_column(MaskedColumn('a', [1], mask=[0]))
+        t.add_column(MaskedColumn('b', [4], mask=[1]))
+        t.add_row({'b':5})
+        t.add_row({'a':3})
+        assert t.masked
+        assert t['a'][0] == 1 and t['a'][2] == 3
+        assert np.all(t['a'].mask == np.array([0,1,0], bool))
+        assert t['b'][1] == 5
+        assert np.all(t['b'].mask == np.array([1,0,1], bool))
+
+    def test_add_masked_row_to_masked_table_mapping4(self):
+        # When adding values to a masked table, if the mask is specified as a
+        # dict, then keys in values should match keys in mask
+        t = Table(masked=True)
+        t.add_column(MaskedColumn('a', [1], mask=[0]))
+        t.add_column(MaskedColumn('b', [4], mask=[1]))
+        with pytest.raises(ValueError) as exc:
+            t.add_row({'b':5}, mask={'a':True})
+        assert exc.value.args[0] == 'keys in mask should match keys in vals'
+
+    def test_add_masked_row_to_masked_table_mismatch(self):
+        t = Table(masked=True)
+        t.add_column(MaskedColumn('a', [1], mask=[0]))
+        t.add_column(MaskedColumn('b', [4], mask=[1]))
+        with pytest.raises(TypeError) as exc:
+            t.add_row([2,5], mask={'a':1, 'b':0})
+        assert exc.value.args[0] == "Mismatch between type of vals and mask"
+        with pytest.raises(TypeError) as exc:
+            t.add_row({'b':5, 'a':2}, mask=[1,0])
+        assert exc.value.args[0] == "Mismatch between type of vals and mask"
+
+    def test_add_masked_row_to_non_masked_table_iterable(self):
+        t = Table(masked=False)
+        t.add_column(Column('a', [1]))
+        t.add_column(Column('b', [4]))
+        assert not t.masked
+        t.add_row([2,5])
+        assert not t.masked
+        t.add_row([3,6], mask=[0,1])
+        assert t.masked
+        assert np.all(np.array(t['a']) == np.array([1,2,3]))
+        assert np.all(t['a'].mask == np.array([0,0,0], bool))
+        assert np.all(np.array(t['b']) == np.array([4,5,6]))
+        assert np.all(t['b'].mask == np.array([0,0,1], bool))
diff --git a/astropy/table/tests/test_pprint.py b/astropy/table/tests/test_pprint.py
index 5ccec41..b7e7479 100644
--- a/astropy/table/tests/test_pprint.py
+++ b/astropy/table/tests/test_pprint.py
@@ -1,13 +1,33 @@
-import pytest
+from distutils import version
 import numpy as np
 
-from .. import Table
-from .. import pprint
+from ...tests.helper import pytest
+from ... import table
+from ...table import pprint
 
 BIG_WIDE_ARR = np.arange(2000, dtype=np.float).reshape(100, 20)
 SMALL_ARR = np.arange(12, dtype=np.int).reshape(4, 3)
 
+numpy_lt_1p5 = version.LooseVersion(np.__version__) < version.LooseVersion('1.5')
 
+# Dummy init of Table for pyflakes and to be sure test fixture is working
+Table = None
+
+
+class MaskedTable(table.Table):
+    def __init__(self, *args, **kwargs):
+        kwargs['masked'] = True
+        table.Table.__init__(self, *args, **kwargs)
+
+
+# Fixture to run all tests for both an unmasked (ndarray) and masked (MaskedArray) column.
+ at pytest.fixture(params=[False] if numpy_lt_1p5 else [False, True])
+def set_global_Table(request):
+    global Table
+    Table = MaskedTable if request.param else table.Table
+
+
+ at pytest.mark.usefixtures('set_global_Table')
 class TestMultiD():
 
     def test_multidim(self):
@@ -25,6 +45,18 @@ class TestMultiD():
                          '-------- -------- --------',
                          '  1 .. 2   3 .. 4   5 .. 6',
                          '10 .. 20 30 .. 40 50 .. 60']
+
+        lines = t.pformat(html=True)
+        assert lines == ['<table>',
+                         '<tr><th>col0 [2]</th><th>col1 [2]</th><th>col2 [2]</th></tr>',
+                         '<tr><td>1 .. 2</td><td>3 .. 4</td><td>5 .. 6</td></tr>',
+                         '<tr><td>10 .. 20</td><td>30 .. 40</td><td>50 .. 60</td></tr>',
+                         '</table>']
+        assert t._repr_html_() == ('<table><tr><th>col0 [2]</th><th>col1 [2]</th><th>col2 [2]'
+                                   '</th></tr><tr><td>1 .. 2</td><td>3 .. 4</td><td>5 .. 6</td>'
+                                   '</tr><tr><td>10 .. 20</td><td>30 .. 40</td><td>50 .. 60</td>'
+                                   '</tr></table>')
+
         t = Table([arr])
         lines = t.pformat()
         print lines
@@ -35,6 +67,7 @@ class TestMultiD():
                          '   5 .. 60']
 
 
+ at pytest.mark.usefixtures('set_global_Table')
 class TestPprint():
 
     def setup_method(self, method):
@@ -42,7 +75,7 @@ class TestPprint():
         self.tb['col0'].format = '%e'
         self.tb['col1'].format = '%.6f'
         self.tb['col0'].units = 'km**2'
-        self.tb['col19'].units = 'kg sec m**-2'
+        self.tb['col19'].units = 'kg s m**-2'
         self.ts = Table(SMALL_ARR)
 
     def test_format0(self):
@@ -51,10 +84,10 @@ class TestPprint():
         """
         arr = np.arange(4000, dtype=np.float).reshape(100, 40)
         lines = Table(arr).pformat()
-        assert len(lines) == pprint.MAX_LINES
+        assert len(lines) == pprint.MAX_LINES()
         for line in lines:
-            assert (len(line) > pprint.MAX_WIDTH - 10 and
-                    len(line) <= pprint.MAX_WIDTH)
+            assert (len(line) > pprint.MAX_WIDTH() - 10 and
+                    len(line) <= pprint.MAX_WIDTH())
 
     def test_format1(self):
         """Basic test of formatting"""
@@ -71,14 +104,15 @@ class TestPprint():
     def test_format2(self):
         """Include the units header row"""
         lines = self.tb.pformat(max_lines=8, max_width=40, show_units=True)
-        assert lines == ['    col0     ...    col19    ',
-                         '   km**2     ... kg sec m**-2',
-                         '------------ ... ------------',
-                         '0.000000e+00 ...         19.0',
-                         '2.000000e+01 ...         39.0',
-                         '         ... ...          ...',
-                         '1.960000e+03 ...       1979.0',
-                         '1.980000e+03 ...       1999.0']
+        print(lines)
+        assert lines == ['    col0         col1    ...    col19   ',
+                         '    km2                  ... kg s / (m2)',
+                         '------------ ----------- ... -----------',
+                         '0.000000e+00    1.000000 ...        19.0',
+                         '2.000000e+01   21.000000 ...        39.0',
+                         '         ...         ... ...         ...',
+                         '1.960000e+03 1961.000000 ...      1979.0',
+                         '1.980000e+03 1981.000000 ...      1999.0']
 
     def test_format3(self):
         """Do not include the name header row"""
@@ -143,6 +177,7 @@ class TestPprint():
             assert len(lines) == max(6, min(102, max_lines))
 
 
+ at pytest.mark.usefixtures('set_global_Table')
 class TestFormat():
 
     def test_column_format(self):
@@ -172,13 +207,12 @@ class TestFormat():
             str(t['a'])
 
     def test_column_format_with_threshold(self):
-        import astropy.table.pprint
-        MAX_LINES = pprint.MAX_LINES
-        pprint.MAX_LINES = 6
+        MAX_LINES_val = pprint.MAX_LINES()
+        pprint.MAX_LINES.set(6)
         t = Table([np.arange(20)], names=['a'])
         t['a'].format = '%{0:}'
         assert str(t['a']) == ' a \n---\n %0\n %1\n...\n%19'
         t['a'].format = '{ %4.2f }'
         assert str(t['a']) == '    a    \n---------\n { 0.00 }\n' \
                               ' { 1.00 }\n      ...\n{ 19.00 }'
-        pprint.MAX_LINES = MAX_LINES
+        pprint.MAX_LINES.set(MAX_LINES_val)
diff --git a/astropy/table/tests/test_row.py b/astropy/table/tests/test_row.py
index 0e0d47f..cb4937c 100644
--- a/astropy/table/tests/test_row.py
+++ b/astropy/table/tests/test_row.py
@@ -1,14 +1,47 @@
-import pytest
+from distutils import version
 import numpy as np
-from .. import Column, Row, Table
 
+from ...tests.helper import pytest
+from ... import table
+from ...table import Row
 
+numpy_lt_1p5 = version.LooseVersion(np.__version__) < version.LooseVersion('1.5')
+
+# Dummy init of Table, DATA for pyflakes and to be sure test fixture is working
+Table = None
+Column = None
+
+
+class MaskedTable(table.Table):
+    def __init__(self, *args, **kwargs):
+        kwargs['masked'] = True
+        table.Table.__init__(self, *args, **kwargs)
+
+
+# Fixture to run all tests for both an unmasked (ndarray) and masked (MaskedArray) column.
+ at pytest.fixture(params=[False] if numpy_lt_1p5 else [False, True])
+def set_global_Table(request):
+    global Table
+    global Column
+    Table = MaskedTable if request.param else table.Table
+    Column = table.MaskedColumn if request.param else table.Column
+
+
+ at pytest.mark.usefixtures('set_global_Table')
 class TestRow():
 
-    def setup_method(self, method):
-        self.a = Column('a', [1, 2, 3], dtype='i8')
-        self.b = Column('b', [4, 5, 6], dtype='i8')
-        self.t = Table([self.a, self.b])
+    @property
+    def t(self):
+        # py.test wants to run this method once before set_global_Table is run
+        # to set Table and Column.  In this case just return None, which would
+        # cause any downstream test to fail if this happened in any other context.
+        if Column is None:
+            return None
+        if not hasattr(self, '_t'):
+            a = Column('a', [1, 2, 3], dtype='i8')
+            b = Column('b', [4, 5, 6], dtype='i8')
+            self._t = Table([a, b])
+        return self._t
 
     def test_subclass(self):
         """Row is subclass of ndarray and Row"""
@@ -35,54 +68,60 @@ class TestRow():
         table = self.t
         row = table[1]
         row['a'] = 10
-        assert table['a'][1] == 10
+        if Table is not MaskedTable:
+            assert table['a'][1] == 10
 
     def test_left_equal(self):
         """Compare a table row to the corresponding structured array row"""
         np_t = self.t._data.copy()
-        for row, np_row in zip(self.t, np_t):
-            assert np.all(row == np_row)
+        if Table is MaskedTable:
+            with pytest.raises(ValueError):
+                self.t[0] == np_t[0]
+        else:
+            for row, np_row in zip(self.t, np_t):
+                assert np.all(row == np_row)
 
     def test_left_not_equal(self):
         """Compare a table row to the corresponding structured array row"""
         np_t = self.t._data.copy()
         np_t['a'] = [0, 0, 0]
-        for row, np_row in zip(self.t, np_t):
-            assert np.all(row != np_row)
+        if Table is MaskedTable:
+            with pytest.raises(ValueError):
+                self.t[0] == np_t[0]
+        else:
+            for row, np_row in zip(self.t, np_t):
+                assert np.all(row != np_row)
 
     def test_right_equal(self):
         """Test right equal"""
         np_t = self.t._data.copy()
-        for row, np_row in zip(self.t, np_t):
-            assert np.all(np_row == row)
-
-    @pytest.mark.xfail
-    def test_set_slice(self):
-        """Set row elements with a slice
-
-        This currently fails because the underlying np.void object
-        row.data = table._data[index] does not support slice assignment.
-        """
-        table = self.t
-        row = table[0]
-        row[:] = [-1, -1]
-        row[:1] = np.array([-2])
-        assert np.all(table._data == np.array([[-1, -1],
-                                               [-2, 5],
-                                               [3, 6]]))
+        if Table is MaskedTable:
+            with pytest.raises(ValueError):
+                self.t[0] == np_t[0]
+        else:
+            for row, np_row in zip(self.t, np_t):
+                assert np.all(np_row == row)
 
     def test_convert_numpy_array(self):
         d = self.t[1]
 
         np_data = np.array(d)
-        assert np.all(np_data == d._data)
+        if Table is not MaskedTable:
+            assert np.all(np_data == d._data)
         assert not np_data is d._data
         assert d.colnames == list(np_data.dtype.names)
 
         np_data = np.array(d, copy=False)
-        assert np.all(np_data == d._data)
+        if Table is not MaskedTable:
+            assert np.all(np_data == d._data)
         assert not np_data is d._data
         assert d.colnames == list(np_data.dtype.names)
 
         with pytest.raises(ValueError):
             np_data = np.array(d, dtype=[('c', 'i8'), ('d', 'i8')])
+
+    def test_format_row(self):
+        """Test formatting row"""
+        table = self.t
+        row = table[0]
+        assert format(row, "").startswith("<Row 0 of table")
diff --git a/astropy/table/tests/test_table.py b/astropy/table/tests/test_table.py
index f934dfc..c84a385 100644
--- a/astropy/table/tests/test_table.py
+++ b/astropy/table/tests/test_table.py
@@ -1,9 +1,70 @@
-import pytest
+from distutils import version
 import numpy as np
 
-from .. import Table, Column
+from ...tests.helper import pytest
+from ... import table
 
+numpy_lt_1p5 = version.LooseVersion(np.__version__) < version.LooseVersion('1.5')
 
+# Dummy init of Table, DATA for pyflakes and to be sure test fixture is working
+Table = None
+Column = None
+
+
+class MaskedTable(table.Table):
+    def __init__(self, *args, **kwargs):
+        kwargs['masked'] = True
+        table.Table.__init__(self, *args, **kwargs)
+
+
+# Fixture to run all the Column tests for both an unmasked (ndarray)
+# and masked (MaskedArray) column.
+ at pytest.fixture(params=[False] if numpy_lt_1p5 else [False, True])
+def set_global_Table(request):
+    global Table, Column
+
+    Table = MaskedTable if request.param else table.Table
+    Column = table.MaskedColumn if request.param else table.Column
+
+
+class SetupData(object):
+    @property
+    def a(self):
+        if Column is not None:
+            if not hasattr(self, '_a'):
+                self._a = Column('a', [1, 2, 3], meta={'aa': np.arange(5)})
+            return self._a
+
+    @property
+    def b(self):
+        if Column is not None:
+            if not hasattr(self, '_b'):
+                self._b = Column('b', [4, 5, 6])
+            return self._b
+
+    @property
+    def c(self):
+        if Column is not None:
+            if not hasattr(self, '_c'):
+                self._c = Column('c', [7, 8, 9])
+            return self._c
+
+    @property
+    def d(self):
+        if Column is not None:
+            if not hasattr(self, '_d'):
+                self._d = Column('d', [7, 8, 7])
+            return self._d
+
+    @property
+    def t(self):
+        if Table is not None:
+            if not hasattr(self, '_t'):
+                self._t = Table([self.a, self.b])
+            return self._t
+
+
+ at pytest.mark.usefixtures('set_global_Table')
 class TestEmptyData():
 
     def test_1(self):
@@ -32,6 +93,7 @@ class TestEmptyData():
         assert len(t['a']) == 0
 
 
+ at pytest.mark.usefixtures('set_global_Table')
 class TestNewFromColumns():
 
     def test_simple(self):
@@ -59,6 +121,7 @@ class TestNewFromColumns():
             Table(cols)
 
 
+ at pytest.mark.usefixtures('set_global_Table')
 class TestReverse():
 
     def test_reverse(self):
@@ -81,6 +144,7 @@ class TestReverse():
         assert np.all(t2['col1'] == np.array(['a', 'b', 'cc']))
 
 
+ at pytest.mark.usefixtures('set_global_Table')
 class TestColumnAccess():
 
     def test_1(self):
@@ -96,10 +160,8 @@ class TestColumnAccess():
             t['b']  # column does not exist
 
 
-class TestAddLength():
-    def setup_method(self, method):
-        self.a = Column('a', [1, 2, 3])
-        self.b = Column('b', [4, 5, 6])
+ at pytest.mark.usefixtures('set_global_Table')
+class TestAddLength(SetupData):
 
     def test_right_length(self):
         t = Table([self.a])
@@ -116,11 +178,8 @@ class TestAddLength():
             t.add_column(Column('b', [4, 5]))  # data too short
 
 
-class TestAddPosition():
-    def setup_method(self, method):
-        self.a = Column('a', [1, 2, 3])
-        self.b = Column('b', [4, 5, 6])
-        self.c = Column('c', [7, 8, 9])
+ at pytest.mark.usefixtures('set_global_Table')
+class TestAddPosition(SetupData):
 
     def test_1(self):
         t = Table()
@@ -171,13 +230,8 @@ class TestAddPosition():
         assert t.columns.keys() == ['c', 'a', 'b']
 
 
-class TestInitFromTable():
-
-    def setup_method(self, method):
-        self.a = Column('a', [1, 2, 3], meta={'aa': np.arange(5)})
-        self.b = Column('b', [4, 5, 6])
-        self.c = Column('c', [7, 8, 9])
-        self.t = Table([self.a, self.b])
+ at pytest.mark.usefixtures('set_global_Table')
+class TestInitFromTable(SetupData):
 
     def test_from_table_cols(self):
         """Ensure that using cols from an existing table gives
@@ -211,13 +265,8 @@ class TestInitFromTable():
             assert t.columns['a'].meta['aa'][3] == 3
 
 
-class TestAddColumns():
-
-    def setup_method(self, method):
-        self.a = Column('a', [1, 2, 3])
-        self.b = Column('b', [4, 5, 6])
-        self.c = Column('c', [7, 8, 9])
-        self.d = Column('d', [7, 8, 7])
+ at pytest.mark.usefixtures('set_global_Table')
+class TestAddColumns(SetupData):
 
     def test_add_columns1(self):
         t = Table()
@@ -262,13 +311,29 @@ class TestAddColumns():
         assert t.colnames == ['a', 'b', 'c', 'd']
 
 
-class TestAddRow():
+ at pytest.mark.usefixtures('set_global_Table')
+class TestAddRow(SetupData):
 
-    def setup_method(self, method):
-        self.a = Column('a', [1, 2, 3])
-        self.b = Column('b', [4.0, 5.1, 6.2])
-        self.c = Column('c', ['7', '8', '9'])
-        self.t = Table([self.a, self.b, self.c])
+    @property
+    def b(self):
+        if Column is not None:
+            if not hasattr(self, '_b'):
+                self._b = Column('b', [4.0, 5.1, 6.2])
+            return self._b
+
+    @property
+    def c(self):
+        if Column is not None:
+            if not hasattr(self, '_c'):
+                self._c = Column('c', ['7', '8', '9'])
+            return self._c
+
+    @property
+    def t(self):
+        if Table is not None:
+            if not hasattr(self, '_t'):
+                self._t = Table([self.a, self.b, self.c])
+            return self._t
 
     def test_add_with_tuple(self):
         t = self.t
@@ -292,15 +357,23 @@ class TestAddRow():
         assert len(t) == 4
         assert np.all(t['a'] == np.array([1, 2, 3, 4]))
         assert np.allclose(t['b'], np.array([4.0, 5.1, 6.2, 7.2]))
-        assert np.all(t['c'] == np.array(['7', '8', '9', '']))
+        if t.masked:
+            assert np.all(t['c'] == np.array(['7', '8', '9', '7']))
+        else:
+            assert np.all(t['c'] == np.array(['7', '8', '9', '']))
 
     def test_add_with_none(self):
         t = self.t
         t.add_row()
         assert len(t) == 4
-        assert np.all(t['a'].data == np.array([1, 2, 3, 0]))
-        assert np.allclose(t['b'], np.array([4.0, 5.1, 6.2, 0.0]))
-        assert np.all(t['c'].data == np.array(['7', '8', '9', '']))
+        if t.masked:
+            assert np.all(t['a'].data == np.array([1, 2, 3, 1]))
+            assert np.allclose(t['b'], np.array([4.0, 5.1, 6.2, 4.0]))
+            assert np.all(t['c'].data == np.array(['7', '8', '9', '7']))
+        else:
+            assert np.all(t['a'].data == np.array([1, 2, 3, 0]))
+            assert np.allclose(t['b'], np.array([4.0, 5.1, 6.2, 0.0]))
+            assert np.all(t['c'].data == np.array(['7', '8', '9', '']))
 
     def test_add_missing_column(self):
         t = self.t
@@ -323,17 +396,13 @@ class TestAddRow():
                          (3, 4, 5)],
                         dtype='i4')
         t = Table(data, copy=False)
-        with pytest.raises(ValueError):
-            t.add_row([6, 7, 8])
+        if not t.masked:
+            with pytest.raises(ValueError):
+                t.add_row([6, 7, 8])
 
 
-class TestTableColumn():
-
-    def setup_method(self, method):
-        self.a = Column('a', [1, 2, 3], meta={'aa': np.arange(5)})
-        self.b = Column('b', [4, 5, 6])
-        self.c = Column('c', [7, 8, 9])
-        self.t = Table([self.a, self.b])
+ at pytest.mark.usefixtures('set_global_Table')
+class TestTableColumn(SetupData):
 
     def test_column_view(self):
         t = self.t
@@ -342,10 +411,8 @@ class TestTableColumn():
         assert t._data['a'][2] == 10
 
 
-class TestArrayColumns():
-
-    def setup_method(self, method):
-        self.a = Column('a', [1, 2, 3])
+ at pytest.mark.usefixtures('set_global_Table')
+class TestArrayColumns(SetupData):
 
     def test_1d(self):
         b = Column('b', dtype=int, shape=(2, ), length=3)
@@ -369,14 +436,22 @@ class TestArrayColumns():
         assert t['b'][0].shape == (2, 4, 6)
 
 
-class TestRemove():
+ at pytest.mark.usefixtures('set_global_Table')
+class TestRemove(SetupData):
+
+    @property
+    def t(self):
+        if Table is not None:
+            if not hasattr(self, '_t'):
+                self._t = Table([self.a])
+            return self._t
 
-    def setup_method(self, method):
-        self.a = Column('a', [1, 2, 3])
-        self.b = Column('b', [4, 5, 6])
-        self.c = Column('c', [7, 8, 9])
-        self.t = Table([self.a])
-        self.t2 = Table([self.a, self.b, self.c])
+    @property
+    def t2(self):
+        if Table is not None:
+            if not hasattr(self, '_t2'):
+                self._t2 = Table([self.a, self.b, self.c])
+            return self._t2
 
     def test_1(self):
         self.t.remove_columns('a')
@@ -408,11 +483,8 @@ class TestRemove():
             del self.t['d']
 
 
-class TestKeep():
-
-    def setup_method(self, method):
-        self.a = Column('a', [1, 2, 3])
-        self.b = Column('b', [4, 5, 6])
+ at pytest.mark.usefixtures('set_global_Table')
+class TestKeep(SetupData):
 
     def test_1(self):
         t = Table([self.a, self.b])
@@ -428,11 +500,8 @@ class TestKeep():
         assert np.all(t['b'] == np.array([4, 5, 6]))
 
 
-class TestRename():
-
-    def setup_method(self, method):
-        self.a = Column('a', [1, 2, 3])
-        self.b = Column('b', [4, 5, 6])
+ at pytest.mark.usefixtures('set_global_Table')
+class TestRename(SetupData):
 
     def test_1(self):
         t = Table([self.a])
@@ -460,6 +529,7 @@ class TestRename():
         assert np.all(t['a'] == np.array([4, 5, 6]))
 
 
+ at pytest.mark.usefixtures('set_global_Table')
 class TestSort():
 
     def test_single(self):
@@ -489,6 +559,7 @@ class TestSort():
         assert np.all(t['b'] == np.array([3, 4, 4, 5, 5, 6]))
 
 
+ at pytest.mark.usefixtures('set_global_Table')
 class TestIterator():
 
     def test_iterator(self):
@@ -496,10 +567,15 @@ class TestIterator():
                       (3, 6),
                       (4, 5)], dtype=[('a', 'i4'), ('b', 'i4')])
         t = Table(d)
-        for row, np_row in zip(t, d):
-            assert np.all(row == np_row)
+        if t.masked:
+            with pytest.raises(ValueError):
+                t[0] == d[0]
+        else:
+            for row, np_row in zip(t, d):
+                assert np.all(row == np_row)
 
 
+ at pytest.mark.usefixtures('set_global_Table')
 class TestSetMeta():
 
     def test_set_meta(self):
@@ -511,19 +587,22 @@ class TestSetMeta():
         assert list(d.meta.keys()) == ['a', 'b', 'c', 'd']
 
 
+ at pytest.mark.usefixtures('set_global_Table')
 class TestConvertNumpyArray():
 
     def test_convert_numpy_array(self):
         d = Table([[1, 2], [3, 4]], names=('a', 'b'))
 
         np_data = np.array(d)
-        assert np.all(np_data == d._data)
+        if Table is not MaskedTable:
+            assert np.all(np_data == d._data)
         assert not np_data is d._data
         assert d.colnames == list(np_data.dtype.names)
 
         np_data = np.array(d, copy=False)
-        assert np.all(np_data == d._data)
-        assert np_data is d._data
+        if Table is not MaskedTable:
+            assert np.all(np_data == d._data)
+            assert np_data is d._data
         assert d.colnames == list(np_data.dtype.names)
 
         with pytest.raises(ValueError):
diff --git a/astropy/table/tests/test_table_io.py b/astropy/table/tests/test_table_io.py
new file mode 100644
index 0000000..2b92a1c
--- /dev/null
+++ b/astropy/table/tests/test_table_io.py
@@ -0,0 +1,238 @@
+from copy import copy
+
+import numpy as np
+
+from ...tests.helper import pytest
+from ...table.io_registry import _readers, _writers, _identifiers
+from ...table import Table
+from ...table import io_registry
+
+_READERS_ORIGINAL = copy(_readers)
+_WRITERS_ORIGINAL = copy(_writers)
+_IDENTIFIERS_ORIGINAL = copy(_identifiers)
+
+
+def setup_function(function):
+    _readers.clear()
+    _writers.clear()
+    _identifiers.clear()
+
+
+def empty_reader(*args, **kwargs):
+    return Table()
+
+
+def empty_writer(table, *args, **kwargs):
+    pass
+
+
+def empty_identifier(args, kwargs):
+    return True
+
+
+def test_get_reader_invalid():
+    with pytest.raises(Exception) as exc:
+        io_registry.get_reader('test')
+    assert exc.value.args[0] == "No reader defined for format 'test'"
+
+
+def test_get_writer_invalid():
+    with pytest.raises(Exception) as exc:
+        io_registry.get_writer('test')
+    assert exc.value.args[0] == "No writer defined for format 'test'"
+
+
+def test_register_reader():
+    io_registry.register_reader('test1', empty_reader)
+    io_registry.register_reader('test2', empty_reader)
+    assert io_registry.get_reader('test1') == empty_reader
+    assert io_registry.get_reader('test2') == empty_reader
+
+
+def test_register_writer():
+    io_registry.register_writer('test1', empty_writer)
+    io_registry.register_writer('test2', empty_writer)
+    assert io_registry.get_writer('test1') == empty_writer
+    assert io_registry.get_writer('test2') == empty_writer
+
+
+def test_register_identifier():
+    io_registry.register_identifier('test1', empty_identifier)
+    io_registry.register_identifier('test2', empty_identifier)
+
+
+def test_register_reader_invalid():
+    io_registry.register_reader('test', empty_reader)
+    with pytest.raises(Exception) as exc:
+        io_registry.register_reader('test', empty_reader)
+    assert exc.value.args[0] == "Reader for format test is already defined"
+
+
+def test_register_writer_invalid():
+    io_registry.register_writer('test', empty_writer)
+    with pytest.raises(Exception) as exc:
+        io_registry.register_writer('test', empty_writer)
+    assert exc.value.args[0] == "Writer for format test is already defined"
+
+
+def test_register_identifier_invalid():
+    io_registry.register_identifier('test', empty_identifier)
+    with pytest.raises(Exception) as exc:
+        io_registry.register_identifier('test', empty_identifier)
+    assert exc.value.args[0] == "Identifier for format test is already defined"
+
+
+def test_register_reader_force():
+    io_registry.register_reader('test', empty_reader)
+    io_registry.register_reader('test', empty_reader, force=True)
+
+
+def test_register_writer_force():
+    io_registry.register_writer('test', empty_writer)
+    io_registry.register_writer('test', empty_writer, force=True)
+
+
+def test_register_identifier_force():
+    io_registry.register_identifier('test', empty_identifier)
+    io_registry.register_identifier('test', empty_identifier, force=True)
+
+
+def test_read_noformat():
+    with pytest.raises(Exception) as exc:
+        Table.read()
+    assert exc.value.args[0] == "Format could not be identified"
+
+
+def test_write_noformat():
+    with pytest.raises(Exception) as exc:
+        Table().write()
+    assert exc.value.args[0] == "Format could not be identified"
+
+
+def test_read_noformat_arbitrary():
+    """Test that all identifier functions can accept arbitary input"""
+    _identifiers.update(_IDENTIFIERS_ORIGINAL)
+    with pytest.raises(Exception) as exc:
+        Table.read(object())
+    assert exc.value.args[0] == "Format could not be identified"
+
+
+def test_write_noformat_arbitrary():
+    """Test that all identifier functions can accept arbitary input"""
+    _identifiers.update(_IDENTIFIERS_ORIGINAL)
+    with pytest.raises(Exception) as exc:
+        Table().write(object())
+    assert exc.value.args[0] == "Format could not be identified"
+
+
+def test_read_toomanyformats():
+    io_registry.register_identifier('test1', lambda o, x, y: True)
+    io_registry.register_identifier('test2', lambda o, x, y: True)
+    with pytest.raises(Exception) as exc:
+        Table.read()
+    assert exc.value.args[0] == "Format is ambiguous - options are: test1, test2"
+
+
+def test_write_toomanyformats():
+    io_registry.register_identifier('test1', lambda o, x, y: True)
+    io_registry.register_identifier('test2', lambda o, x, y: True)
+    with pytest.raises(Exception) as exc:
+        Table().write()
+    assert exc.value.args[0] == "Format is ambiguous - options are: test1, test2"
+
+
+def test_read_format_noreader():
+    with pytest.raises(Exception) as exc:
+        Table.read(format='test')
+    assert exc.value.args[0] == "No reader defined for format 'test'"
+
+
+def test_write_format_nowriter():
+    with pytest.raises(Exception) as exc:
+        Table().write(format='test')
+    assert exc.value.args[0] == "No writer defined for format 'test'"
+
+
+def test_read_identifier():
+
+    io_registry.register_identifier('test1', lambda o, x, y: x[0].startswith('a'))
+    io_registry.register_identifier('test2', lambda o, x, y: x[0].startswith('b'))
+
+    # Now check that we got past the identifier and are trying to get
+    # the reader. The io_registry.get_reader will fail but the error message will
+    # tell us if the identifier worked.
+
+    with pytest.raises(Exception) as exc:
+        Table.read('abc')
+    assert exc.value.args[0] == "No reader defined for format 'test1'"
+
+    with pytest.raises(Exception) as exc:
+        Table.read('bac')
+    assert exc.value.args[0] == "No reader defined for format 'test2'"
+
+
+def test_write_identifier():
+
+    io_registry.register_identifier('test1', lambda o, x, y: x[0].startswith('a'))
+    io_registry.register_identifier('test2', lambda o, x, y: x[0].startswith('b'))
+
+    # Now check that we got past the identifier and are trying to get
+    # the reader. The io_registry.get_writer will fail but the error message will
+    # tell us if the identifier worked.
+
+    with pytest.raises(Exception) as exc:
+        Table().write('abc')
+    assert exc.value.args[0] == "No writer defined for format 'test1'"
+
+    with pytest.raises(Exception) as exc:
+        Table().write('bac')
+    assert exc.value.args[0] == "No writer defined for format 'test2'"
+
+
+def test_identifier_origin():
+
+    io_registry.register_identifier('test1', lambda o, x, y: o == 'read')
+    io_registry.register_identifier('test2', lambda o, x, y: o == 'write')
+    io_registry.register_reader('test1', empty_reader)
+    io_registry.register_writer('test2', empty_writer)
+
+    # There should not be too many formats defined
+    Table.read()
+    Table().write()
+
+    with pytest.raises(Exception) as exc:
+        Table.read(format='test2')
+    assert exc.value.args[0] == "No reader defined for format 'test2'"
+
+    with pytest.raises(Exception) as exc:
+        Table().write(format='test1')
+    assert exc.value.args[0] == "No writer defined for format 'test1'"
+
+
+def test_read_valid_return():
+    io_registry.register_reader('test', lambda: Table())
+    t = Table.read(format='test')
+    assert isinstance(t, Table)
+
+
+def test_read_invalid_return():
+    io_registry.register_reader('test', lambda: 'spam')
+    with pytest.raises(TypeError) as exc:
+        Table.read(format='test')
+    assert exc.value.args[0] == "reader should return a Table instance"
+
+
+def test_read_basic():
+    data = np.array(zip([1, 2, 3], ['a', 'b', 'c']), dtype=[('A', int), ('B', '|S1')])
+    io_registry.register_reader('test', lambda x: Table(x))
+    t = Table.read(data, format='test')
+    assert t.keys() == ['A', 'B']
+    for i in range(3):
+        assert t['A'][i] == data['A'][i]
+        assert t['B'][i] == data['B'][i]
+
+
+def teardown_function(function):
+    _readers.update(_READERS_ORIGINAL)
+    _writers.update(_WRITERS_ORIGINAL)
+    _identifiers.update(_IDENTIFIERS_ORIGINAL)
diff --git a/astropy/tests/compat.py b/astropy/tests/compat.py
new file mode 100644
index 0000000..2256292
--- /dev/null
+++ b/astropy/tests/compat.py
@@ -0,0 +1,15 @@
+import numpy as np
+
+# assert_allclose doesn't exist in Numpy 1.4, so recreate it here
+if tuple([int(x) for x in np.__version__.split(".", 2)[:2]]) < (1, 5):
+    def assert_allclose(actual, desired, rtol=1e-7, atol=0,
+                        err_msg='', verbose=True):
+        from numpy.testing.utils import assert_array_compare
+        def compare(x, y):
+            return np.allclose(x, y, rtol=rtol, atol=atol)
+        actual, desired = np.asanyarray(actual), np.asanyarray(desired)
+        header = 'Not equal to tolerance rtol=%g, atol=%g' % (rtol, atol)
+        assert_array_compare(compare, actual, desired, err_msg=str(err_msg),
+                             verbose=verbose, header=header)
+else:
+    from numpy.testing.utils import assert_allclose
diff --git a/astropy/tests/helper.py b/astropy/tests/helper.py
index 5efb936..88b0527 100644
--- a/astropy/tests/helper.py
+++ b/astropy/tests/helper.py
@@ -14,11 +14,19 @@ import subprocess
 import shutil
 import tempfile
 
+try:
+    # Import pkg_resources to prevent it from issuing warnings upon being
+    # imported from within py.test.  See
+    # https://github.com/astropy/astropy/pull/537 for a detailed explanation.
+    import pkg_resources
+except ImportError:
+    pass
+
 from distutils.core import Command
 
 from .. import test
 
-if os.environ.get('ASTROPY_USE_SYSTEM_PYTEST'):
+if os.environ.get('ASTROPY_USE_SYSTEM_PYTEST') or '_pytest' in sys.modules:
     import pytest
 
 else:
@@ -115,7 +123,7 @@ class TestRunner(object):
                     'Coverage reporting requires pytest-cov plugin: '
                     'http://pypi.python.org/pypi/pytest-cov')
             else:
-                # Don't use get_data_filename here, because it
+                # Don't use get_pkg_data_filename here, because it
                 # requires importing astropy.config and thus screwing
                 # up coverage results for those packages.
                 coveragerc = os.path.join(
@@ -138,25 +146,6 @@ class TestRunner(object):
                 all_args += (
                     ' --cov-report html --cov astropy'
                     ' --cov-config {0}'.format(tmp.name))
-
-        # check if we're inside the distutils test command, which sets the
-        # _ASTROPY_TEST_ builtin
-        try:
-            _ASTROPY_TEST_
-            insidetestcmd = True
-        except NameError:
-            insidetestcmd = False
-
-        #set up environment variables to fake the config and cache systems,
-        #unless this has already been done by the distutils test command
-        if not insidetestcmd:
-            oldconfigdir = os.environ.get('XDG_CONFIG_HOME')
-            oldcachedir = os.environ.get('XDG_CACHE_HOME')
-            os.environ['XDG_CONFIG_HOME'] = tempfile.mkdtemp('astropy_config')
-            os.environ['XDG_CACHE_HOME'] = tempfile.mkdtemp('astropy_cache')
-            os.mkdir(os.path.join(os.environ['XDG_CONFIG_HOME'], 'astropy'))
-            os.mkdir(os.path.join(os.environ['XDG_CACHE_HOME'], 'astropy'))
-
         try:
             all_args = shlex.split(
                 all_args, posix=not sys.platform.startswith('win'))
@@ -168,20 +157,8 @@ class TestRunner(object):
                     tmp.close()
                 os.remove(tmp.name)
 
-            if not insidetestcmd:
-                #wipe the config/cache tmpdirs and restore the envars
-                shutil.rmtree(os.environ['XDG_CONFIG_HOME'])
-                shutil.rmtree(os.environ['XDG_CACHE_HOME'])
-                if oldconfigdir is None:
-                    del os.environ['XDG_CONFIG_HOME']
-                else:
-                    os.environ['XDG_CONFIG_HOME'] = oldconfigdir
-                if oldcachedir is None:
-                    del os.environ['XDG_CACHE_HOME']
-                else:
-                    os.environ['XDG_CACHE_HOME'] = oldcachedir
-
         return result
+
     run_tests.__doc__ = test.__doc__
 
 
@@ -237,46 +214,60 @@ class astropy_test(Command, object):
         build_cmd = self.get_finalized_command('build')
         new_path = os.path.abspath(build_cmd.build_lib)
 
-        # Run the tests in a subprocess--this is necessary since new extension
-        # modules may have appeared, and this is the easiest way to set up a
-        # new environment
-
-        # We need to set a flag in the child's environment so that
-        # unnecessary code is not imported before py.test can start
-        # up, otherwise the coverage results will be artifically low.
-        if sys.version_info[0] >= 3:
-            set_flag = "import builtins; builtins._ASTROPY_TEST_ = True"
-        else:
-            set_flag = "import __builtin__; __builtin__._ASTROPY_TEST_ = True"
-
-        cmd = ('{0}; import {1.package_name}, sys; sys.exit('
-               '{1.package_name}.test({1.package!r}, {1.test_path!r}, '
-               '{1.args!r}, {1.plugins!r}, {1.verbose_results!r}, '
-               '{1.pastebin!r}, {1.remote_data!r}, {1.pep8!r}, {1.pdb!r}, '
-               '{1.coverage!r}))')
-        cmd = cmd.format(set_flag, self)
-
-        #override the config locations to not make a new directory nor use
-        #existing cache or config
-        os.environ['XDG_CONFIG_HOME'] = tempfile.mkdtemp('astropy_config')
-        os.environ['XDG_CACHE_HOME'] = tempfile.mkdtemp('astropy_cache')
-        os.mkdir(os.path.join(os.environ['XDG_CONFIG_HOME'], 'astropy'))
-        os.mkdir(os.path.join(os.environ['XDG_CACHE_HOME'], 'astropy'))
+        # Copy the build to a temporary directory for the purposes of testing
+        # - this avoids creating pyc and __pycache__ directories inside the
+        # build directory
+        tmp_dir = tempfile.mkdtemp(prefix='astropy-test-')
+        testing_path = os.path.join(tmp_dir, os.path.basename(new_path))
+        shutil.copytree(new_path, testing_path)
 
         try:
-            retcode = subprocess.call([sys.executable, '-c', cmd],
-                                      cwd=new_path, close_fds=False)
+
+            # Run the tests in a subprocess--this is necessary since new extension
+            # modules may have appeared, and this is the easiest way to set up a
+            # new environment
+
+            # We need to set a flag in the child's environment so that
+            # unnecessary code is not imported before py.test can start
+            # up, otherwise the coverage results will be artifically low.
+            if sys.version_info[0] >= 3:
+                set_flag = "import builtins; builtins._ASTROPY_TEST_ = True"
+            else:
+                set_flag = "import __builtin__; __builtin__._ASTROPY_TEST_ = True"
+
+            cmd = ('{0}; import {1.package_name}, sys; sys.exit('
+                   '{1.package_name}.test({1.package!r}, {1.test_path!r}, '
+                   '{1.args!r}, {1.plugins!r}, {1.verbose_results!r}, '
+                   '{1.pastebin!r}, {1.remote_data!r}, {1.pep8!r}, {1.pdb!r}, '
+                   '{1.coverage!r}))')
+            cmd = cmd.format(set_flag, self)
+
+            #override the config locations to not make a new directory nor use
+            #existing cache or config
+            os.environ['XDG_CONFIG_HOME'] = tempfile.mkdtemp('astropy_config')
+            os.environ['XDG_CACHE_HOME'] = tempfile.mkdtemp('astropy_cache')
+            os.mkdir(os.path.join(os.environ['XDG_CONFIG_HOME'], 'astropy'))
+            os.mkdir(os.path.join(os.environ['XDG_CACHE_HOME'], 'astropy'))
+
+            try:
+                retcode = subprocess.call([sys.executable, '-c', cmd],
+                                          cwd=testing_path, close_fds=False)
+            finally:
+                # kill the temporary dirs
+                shutil.rmtree(os.environ['XDG_CONFIG_HOME'])
+                shutil.rmtree(os.environ['XDG_CACHE_HOME'])
+
+            if self.coverage and retcode == 0:
+                # Copy the htmlcov from build/lib.../htmlcov to a more
+                # obvious place
+                if os.path.exists('htmlcov'):
+                    shutil.rmtree('htmlcov')
+                shutil.copytree(os.path.join(testing_path, 'htmlcov'), 'htmlcov')
+
         finally:
-            # kill the temporary dirs
-            shutil.rmtree(os.environ['XDG_CONFIG_HOME'])
-            shutil.rmtree(os.environ['XDG_CACHE_HOME'])
-
-        if self.coverage and retcode == 0:
-            # Copy the htmlcov from build/lib.../htmlcov to a more
-            # obvious place
-            if os.path.exists('htmlcov'):
-                shutil.rmtree('htmlcov')
-            shutil.copytree(os.path.join(new_path, 'htmlcov'), 'htmlcov')
+
+            # Remove temporary directory
+            shutil.rmtree(tmp_dir)
 
         raise SystemExit(retcode)
 
diff --git a/astropy/tests/pytest_plugins.py b/astropy/tests/pytest_plugins.py
index 886a27e..2ff5a60 100644
--- a/astropy/tests/pytest_plugins.py
+++ b/astropy/tests/pytest_plugins.py
@@ -33,3 +33,47 @@ def pytest_report_header(config):
         s += "Using Astropy options: {0}.\n".format(" ".join(opts))
 
     return s
+
+
+ at pytest.fixture(autouse=True)
+def modarg(request):
+    """Sets up environment variables to fake the config and cache
+    directories, then removes the temporary directories.
+
+    Does nothing if we are inside the sphinx testing command, as it
+    should have already done this for us.
+    """
+    import os
+    import shutil
+    import tempfile
+
+    # check if we're inside the distutils test command, which sets the
+    # _ASTROPY_TEST_ builtin
+    try:
+        _ASTROPY_TEST_
+        insidetestcmd = True
+    except NameError:
+        insidetestcmd = False
+
+    if not insidetestcmd:
+        oldconfigdir = os.environ.get('XDG_CONFIG_HOME')
+        oldcachedir = os.environ.get('XDG_CACHE_HOME')
+        os.environ['XDG_CONFIG_HOME'] = tempfile.mkdtemp('astropy_config')
+        os.environ['XDG_CACHE_HOME'] = tempfile.mkdtemp('astropy_cache')
+        os.mkdir(os.path.join(os.environ['XDG_CONFIG_HOME'], 'astropy'))
+        os.mkdir(os.path.join(os.environ['XDG_CACHE_HOME'], 'astropy'))
+
+        def teardown():
+            #wipe the config/cache tmpdirs and restore the envars
+            shutil.rmtree(os.environ['XDG_CONFIG_HOME'])
+            shutil.rmtree(os.environ['XDG_CACHE_HOME'])
+            if oldconfigdir is None:
+                del os.environ['XDG_CONFIG_HOME']
+            else:
+                os.environ['XDG_CONFIG_HOME'] = oldconfigdir
+            if oldcachedir is None:
+                del os.environ['XDG_CACHE_HOME']
+            else:
+                os.environ['XDG_CACHE_HOME'] = oldcachedir
+
+        request.addfinalizer(teardown)
diff --git a/astropy/tests/test_logger.py b/astropy/tests/test_logger.py
index 08a3c5d..263262d 100644
--- a/astropy/tests/test_logger.py
+++ b/astropy/tests/test_logger.py
@@ -1,7 +1,7 @@
 import sys
 import warnings
 
-import pytest
+from .helper import pytest
 from .. import log
 from ..logger import LoggingError
 
@@ -13,6 +13,12 @@ _excepthook = sys.__excepthook__
 _showwarning = warnings.showwarning
 
 
+try:
+    ip = get_ipython()
+except NameError:
+    ip = None
+
+
 def setup_function(function):
 
     # Reset hooks to original values
@@ -109,8 +115,8 @@ def test_warnings_logging_with_custom_class():
     assert log_list[0].origin == 'astropy.tests.test_logger'
 
 
-def test_warning_logging_with_io_vo_warning():
-    from ..io.vo.exceptions import W02, vo_warn
+def test_warning_logging_with_io_votable_warning():
+    from ..io.votable.exceptions import W02, vo_warn
 
     with warnings.catch_warnings(record=True) as warn_list:
         log.enable_warnings_logging()
@@ -138,6 +144,9 @@ def test_exception_logging_enable_twice():
     assert e.value.args[0] == 'Exception logging has already been enabled'
 
 
+# You can't really override the exception handler in IPython this way, so
+# this test doesn't really make sense in the IPython context.
+ at pytest.mark.skipif("ip is not None")
 def test_exception_logging_overridden():
     log.enable_exception_logging()
     sys.excepthook = lambda: None
diff --git a/astropy/time/__init__.py b/astropy/time/__init__.py
new file mode 100644
index 0000000..bb67a43
--- /dev/null
+++ b/astropy/time/__init__.py
@@ -0,0 +1 @@
+from .core import *
diff --git a/astropy/time/core.py b/astropy/time/core.py
new file mode 100644
index 0000000..acf3074
--- /dev/null
+++ b/astropy/time/core.py
@@ -0,0 +1,1166 @@
+"""
+The astropy.time package provides functionality for manipulating times and
+dates. Specific emphasis is placed on supporting time scales (e.g. UTC, TAI,
+UT1) and time representations (e.g. JD, MJD, ISO 8601) that are used in
+astronomy.
+"""
+import sys
+import warnings
+import time
+import itertools
+import numpy as np
+
+__all__ = ['Time', 'TimeDelta', 'TimeFormat', 'TimeJD', 'TimeMJD',
+           'TimeFromEpoch', 'TimeUnix', 'TimeCxcSec', 'TimeString',
+           'TimeISO', 'TimeISOT', 'TimeYearDayTime', 'TimeEpochDate',
+           'TimeBesselianEpoch', 'TimeJulianEpoch', 'TimeDeltaFormat',
+           'TimeDeltaSec', 'TimeDeltaJD', 'ScaleValueError',
+           'OperandTypeError', 'TimeEpochDateString',
+           'TimeBesselianEpochString', 'TimeJulianEpochString',
+           'TIME_FORMATS', 'TIME_DELTA_FORMATS', 'TIME_SCALES',
+           'TIME_DELTA_SCALES']
+
+if not _ASTROPY_SETUP_:
+    from . import sofa_time
+
+MJD_ZERO = 2400000.5
+SECS_PER_DAY = 86400
+
+# These both get filled in at end after TimeFormat subclasses defined
+TIME_FORMATS = {}
+TIME_DELTA_FORMATS = {}
+
+TIME_SCALES = ('tai', 'tcb', 'tcg', 'tdb', 'tt', 'ut1', 'utc')
+TIME_DELTA_SCALES = ('tai',)
+
+MULTI_HOPS = {('tai', 'tcb'): ('tt', 'tdb'),
+              ('tai', 'tcg'): ('tt',),
+              ('tai', 'ut1'): ('utc',),
+              ('tai', 'tdb'): ('tt',),
+              ('tcb', 'tcg'): ('tdb', 'tt'),
+              ('tcb', 'tt'): ('tdb',),
+              ('tcb', 'ut1'): ('tdb', 'tt', 'tai', 'utc'),
+              ('tcb', 'utc'): ('tdb', 'tt', 'tai'),
+              ('tcg', 'tdb'): ('tt', 'tdb'),
+              ('tcg', 'ut1'): ('tt', 'tai', 'utc'),
+              ('tcg', 'utc'): ('tt', 'tai'),
+              ('tdb', 'ut1'): ('tt', 'tai', 'utc'),
+              ('tdb', 'utc'): ('tt', 'tai'),
+              ('tt', 'ut1'): ('tai', 'utc'),
+              ('tt', 'utc'): ('tai',),
+              }
+
+
+class Time(object):
+    """
+    Represent and manipulate times and dates for astronomy.
+
+    A Time object is initialized with one or more times in the ``val``
+    argument.  The input times in ``val`` must conform to the specified
+    ``format`` and must correspond to the specified time ``scale``.  The
+    optional ``val2`` time input should be supplied only for numeric input
+    formats (e.g. JD) where very high precision (better than 64-bit precision)
+    is required.
+
+    Parameters
+    ----------
+    val : sequence, str, number, or `~astropy.time.Time` object
+        Value(s) to initialize the time or times.
+    val2 : sequence, str, or number; optional
+        Value(s) to initialize the time or times
+    format : str, optional
+        Format of input value(s)
+    scale : str, optional
+        Time scale of input value(s)
+    opt : dict, optional
+        options
+    lat : float, optional
+        Earth latitude of observer (decimal degrees)
+    lon : float, optional
+        Earth longitude of observer (decimal degrees)
+    copy : bool, optional
+        Make a copy of the input values
+    """
+
+    _precision = 3  # Precision when for seconds as floating point
+    _in_subfmt = '*'  # Select subformat for inputting string times
+    _out_subfmt = '*'  # Select subformat for outputting string times
+
+    SCALES = TIME_SCALES
+    """List of time scales"""
+
+    FORMATS = TIME_FORMATS
+    """Dict of time formats"""
+
+    def __new__(cls, val, val2=None, format=None, scale=None,
+                precision=None, in_subfmt=None, out_subfmt=None,
+                lat=0.0, lon=0.0, copy=False):
+
+        if isinstance(val, cls):
+            self = val.replicate(format=format, copy=copy)
+        else:
+            self = super(Time, cls).__new__(cls)
+        return self
+
+    def __init__(self, val, val2=None, format=None, scale=None,
+                 precision=None, in_subfmt=None, out_subfmt=None,
+                 lat=0.0, lon=0.0, copy=False):
+
+        self.lat = lat
+        self.lon = lon
+        if precision is not None:
+            self.precision = precision
+        if in_subfmt is not None:
+            self.in_subfmt = in_subfmt
+        if out_subfmt is not None:
+            self.out_subfmt = out_subfmt
+
+        if isinstance(val, self.__class__):
+            if scale is not None:
+                self._set_scale(scale)
+        else:
+            self._init_from_vals(val, val2, format, scale, copy)
+
+    def _init_from_vals(self, val, val2, format, scale, copy):
+        """
+        Set the internal _format, _scale, and _time attrs from user
+        inputs.  This handles coercion into the correct shapes and
+        some basic input validation.
+        """
+
+        # Coerce val into a 1-d array
+        val, val_ndim = _make_1d_array(val, copy)
+
+        # If val2 is None then replace with zeros of the same length
+        if val2 is None:
+            val2 = np.zeros(len(val), dtype=np.double)
+            val2_ndim = val_ndim
+        else:
+            val2, val2_ndim = _make_1d_array(val2, copy)
+
+        # Consistency checks
+        if len(val) != len(val2):
+            raise ValueError('Input val and val2 must match in length')
+
+        self.is_scalar = (val_ndim == 0)
+        if val_ndim != val2_ndim:
+            raise ValueError('Input val and val2 must have same dimensions')
+
+        if scale is not None and scale not in self.SCALES:
+            raise ScaleValueError("Scale {0} is not in the allowed scales {1}"
+                                  .format(repr(scale), sorted(self.SCALES)))
+
+        # Parse / convert input values into internal jd1, jd2 based on format
+        self._format, self._time = self._get_time_fmt(val, val2, format, scale)
+        self._scale = scale
+
+    def _get_time_fmt(self, val, val2, format, scale):
+        """
+        Given the supplied val, val2, format and scale try to instantiate
+        the corresponding TimeFormat class to convert the input values into
+        the internal jd1 and jd2.
+
+        If format is None and the input is a string-type array then guess
+        available string formats and stop when one matches.
+        """
+
+        if format is None and val.dtype.kind in ('S', 'U'):
+            formats = [(name, cls) for name, cls in self.FORMATS.items()
+                       if issubclass(cls, TimeString)]
+            err_msg = 'any formats that can interpret strings {0}'.format(
+                      [name for name, cls in formats])
+        elif format not in self.FORMATS:
+            if format is None:
+                raise ValueError("No time format was given, and the input is "
+                                 "not string-like")
+            else:
+                raise ValueError("Format {0} is not one of the allowed "
+                    "formats {1}".format(repr(format), sorted(self.FORMATS)))
+        else:
+            formats = [(format, self.FORMATS[format])]
+            err_msg = 'the format class {0}'.format(format)
+
+        for format, FormatClass in formats:
+            try:
+                return format, FormatClass(val, val2, scale, self.precision,
+                                           self.in_subfmt, self.out_subfmt)
+            except (ValueError, TypeError):
+                pass
+        else:
+            raise ValueError('Input values did not match {0}'.format(err_msg))
+
+    @property
+    def format(self):
+        """Time format"""
+        return self._format
+
+    def __repr__(self):
+        return ("<{0} object: scale='{1}' format='{2}' vals={3}>"
+                .format(self.__class__.__name__, self.scale, self.format,
+                        getattr(self, self.format)))
+
+    def __str__(self):
+        return str(getattr(self, self.format))
+
+    @property
+    def scale(self):
+        """Time scale"""
+        return self._scale
+
+    def _set_scale(self, scale):
+        """
+        This is the key routine that actually does time scale conversions.
+        This is not public and not connected to the read-only scale property.
+        """
+
+        if scale == self._scale:
+            return
+        if scale not in self.SCALES:
+            raise ValueError("Scale {0} is not in the allowed scales {1}"
+                             .format(repr(scale), sorted(self.SCALES)))
+
+        # Determine the chain of scale transformations to get from the current
+        # scale to the new scale.  MULTI_HOPS contains a dict of all
+        # transformations (xforms) that require intermediate xforms.
+        # The MULTI_HOPS dict is keyed by (sys1, sys2) in alphabetical order.
+        xform = (self._scale, scale)
+        xform_sort = tuple(sorted(xform))
+        multi = MULTI_HOPS.get(xform_sort, ())
+        xforms = xform_sort[:1] + multi + xform_sort[-1:]
+        # If we made the reverse xform then reverse it now.
+        if xform_sort != xform:
+            xforms = tuple(reversed(xforms))
+
+        # Transform the jd1,2 pairs through the chain of scale xforms.
+        jd1, jd2 = self._time.jd1, self._time.jd2
+        for sys1, sys2 in itertools.izip(xforms[:-1], xforms[1:]):
+            # Some xforms require an additional delta_ argument that is
+            # provided through Time methods.  These values may be supplied by
+            # the user or computed based on available approximations.  The
+            # get_delta_ methods are available for only one combination of
+            # sys1, sys2 though the property applies for both xform directions.
+            args = [jd1, jd2]
+            for sys12 in ((sys1, sys2), (sys2, sys1)):
+                dt_method = '_get_delta_{0}_{1}'.format(*sys12)
+                try:
+                    get_dt = getattr(self, dt_method)
+                except AttributeError:
+                    pass
+                else:
+                    args.append(get_dt(jd1, jd2))
+                    break
+
+            conv_func = getattr(sofa_time, sys1 + '_' + sys2)
+            jd1, jd2 = conv_func(*args)
+        self._time = self.FORMATS[self.format](jd1, jd2, scale, self.precision,
+                                               self.in_subfmt, self.out_subfmt,
+                                               from_jd=True)
+        self._scale = scale
+
+    @property
+    def precision(self):
+        """
+        Decimal precision when outputting seconds as floating point (int
+        value between 0 and 9 inclusive).
+        """
+        return self._precision
+
+    @precision.setter
+    def precision(self, val):
+        if not isinstance(val, int) or val < 0 or val > 9:
+            raise ValueError('precision attribute must be an int between '
+                             '0 and 9')
+        self._precision = val
+
+    @property
+    def in_subfmt(self):
+        """
+        Unix wildcard pattern to select subformats for parsing string input
+        times
+        """
+        return self._in_subfmt
+
+    @in_subfmt.setter
+    def in_subfmt(self, val):
+        if not isinstance(val, basestring):
+            raise ValueError('in_subfmt attribute must be a string')
+        self._in_subfmt = val
+
+    @property
+    def out_subfmt(self):
+        """
+        Unix wildcard pattern to select subformats for outputting times
+        """
+        return self._out_subfmt
+
+    @out_subfmt.setter
+    def out_subfmt(self, val):
+        if not isinstance(val, basestring):
+            raise ValueError('out_subfmt attribute must be a string')
+        self._out_subfmt = val
+
+    def _shaped_like_input(self, vals):
+        return (vals[0].tolist() if self.is_scalar else vals)
+
+    @property
+    def jd1(self):
+        """
+        First of the two doubles that internally store time value(s) in JD
+        """
+        return self._shaped_like_input(self._time.jd1)
+
+    @property
+    def jd2(self):
+        """
+        Second of the two doubles that internally store time value(s) in JD
+        """
+        return self._shaped_like_input(self._time.jd2)
+
+    @property
+    def val(self):
+        """Time value(s) in current format"""
+        return self._shaped_like_input(self._time.vals)
+
+    @property
+    def vals(self):
+        """Time values in current format as a numpy array"""
+        return self._time.vals
+
+    def copy(self, format=None):
+        """
+        Return a fully independent copy the Time object, optionally changing
+        the format.
+
+        If ``format`` is supplied then the time format of the returned Time
+        object will be set accordingly, otherwise it will be unchanged from the
+        original.
+
+        In this method a full copy of the internal time arrays will be made.
+        The internal time arrays are normally not changeable by the user so in
+        most cases the ``replicate()`` method should be used.
+
+        Parameters
+        ----------
+        format : str, optional
+            Time format of the copy.
+
+        Returns
+        -------
+        tm: Time object
+            Copy of this object
+        """
+        return self.replicate(format, copy=True)
+
+    def replicate(self, format=None, copy=False):
+        """
+        Return a replica of the Time object, optionally changing the format.
+
+        If ``format`` is supplied then the time format of the returned Time
+        object will be set accordingly, otherwise it will be unchanged from the
+        original.
+
+        If ``copy`` is set to True then a full copy of the internal time arrays
+        will be made.  By default the replica will use a reference to the
+        original arrays when possible to save memory.  The internal time arrays
+        are normally not changeable by the user so in most cases it should not
+        be necessary to set ``copy`` to True.
+
+        The convenience method copy() is available in which ``copy`` is True
+        by default.
+
+        Parameters
+        ----------
+        format : str, optional
+            Time format of the replica.
+        copy : bool, optional
+            Return a true copy instead of using references where possible.
+
+        Returns
+        -------
+        tm: Time object
+            Replica of this object
+        """
+        tm = self.__class__(self._time.jd1, self._time.jd2,
+                            format='jd', scale=self.scale, copy=copy)
+
+        # Optional or non-arg attributes
+        attrs = ('is_scalar', '_delta_ut1_utc', '_delta_tdb_tt',
+                 'lat', 'lon', 'precision', 'in_subfmt', 'out_subfmt')
+        for attr in attrs:
+            try:
+                setattr(tm, attr, getattr(self, attr))
+            except AttributeError:
+                pass
+
+        if format is None:
+            format = self.format
+
+        # Make the new internal _time object corresponding to the format
+        # in the copy.  If the format is unchanged this process is lightweight
+        # and does not create any new arrays.
+
+        NewFormat = tm.FORMATS[format]
+        # If the new format class has a "scale" class attr then that scale is
+        # required and the input jd1,2 has to be converted first.
+        if hasattr(NewFormat, 'required_scale'):
+            scale = NewFormat.required_scale
+            new = getattr(tm, scale)  # self JDs converted to scale
+            tm._time = NewFormat(new._time.jd1, new._time.jd2, scale,
+                                   tm.precision,
+                                   tm.in_subfmt, tm.out_subfmt,
+                                   from_jd=True)
+        else:
+            tm._time = NewFormat(tm._time.jd1, tm._time.jd2,
+                                   tm.scale, tm.precision,
+                                   tm.in_subfmt, tm.out_subfmt,
+                                   from_jd=True)
+        tm._format = format
+
+        return tm
+
+    def _getAttributeNames(self):
+        """
+        Add dynamic attribute names for IPython completer.
+        """
+        return list(self.SCALES) + self.FORMATS.keys()
+
+    def __getattr__(self, attr):
+        """
+        Get dynamic attributes to output format or do timescale conversion.
+        """
+        # The following is needed for the IPython completer
+        if attr == 'trait_names':
+            return []
+
+        if attr in self.SCALES:
+            tm = self.replicate()
+            tm._set_scale(attr)
+            return tm
+
+        elif attr in self.FORMATS:
+            tm = self.replicate(format=attr)
+            return (tm.vals[0].tolist() if self.is_scalar else tm.vals)
+
+        else:
+            # Should raise AttributeError
+            return self.__getattribute__(attr)
+
+    def _match_len(self, val):
+        """
+        Ensure that `val` is matched to length of self.  If val has length 1
+        then broadcast, otherwise cast to double and make sure length matches.
+        """
+        val, ndim = _make_1d_array(val, copy=True)  # be conservative and copy
+        if len(val) == 1:
+            oval = val
+            val = np.empty(len(self), dtype=np.double)
+            val[:] = oval
+        elif len(val) != len(self):
+            raise ValueError('Attribute length must match Time object length')
+        return val
+
+    # Property for SOFA DUT arg = UT1 - UTC
+    def _get_delta_ut1_utc(self, jd1=None, jd2=None):
+        """
+        Get SOFA DUT arg = UT1 - UTC.  This getter takes optional jd1 and
+        jd2 args because it gets called that way when converting time scales.
+        The current code ignores these, but when the IERS table is interpolated
+        by this module they will be used.
+        """
+
+        # Sec. 4.3.1: the arg DUT is the quantity delta_UT1 = UT1 - UTC in
+        # seconds. It can be obtained from tables published by the IERS.
+        # TODO - get that table when needed and interpolate or whatever.
+        if not hasattr(self, '_delta_ut1_utc'):
+            # Exception until the IERS table is available to the package
+            raise ValueError('Must set the delta_ut1_utc attribute in '
+                             'order to do the scale transform.')
+
+        return self._delta_ut1_utc
+
+    def _set_delta_ut1_utc(self, val):
+        self._delta_ut1_utc = self._match_len(val)
+
+    # Note can't use @property because _get_delta_tdb_tt is explicitly
+    # called with the optional jd1 and jd2 args.
+    delta_ut1_utc = property(_get_delta_ut1_utc, _set_delta_ut1_utc)
+    """UT1 - UTC time scale offset"""
+
+    # Property for SOFA DTR arg = TDB - TT
+    def _get_delta_tdb_tt(self, jd1=None, jd2=None):
+        if not hasattr(self, '_delta_tdb_tt'):
+            # If jd1 and jd2 are not provided (which is the case for property
+            # attribute access) then require that the time scale is TT or TDB.
+            # Otherwise the computations here are not correct.
+            if jd1 is None or jd2 is None:
+                if self.scale not in ('tt', 'tdb'):
+                    raise ValueError('Accessing the delta_tdb_tt attribute '
+                                     'is only possible for TT or TDB time '
+                                     'scales')
+                else:
+                    jd1 = self._time.jd1
+                    jd2 = self._time.jd2
+
+            # First go from the current input time (which is either
+            # TDB or TT) to an approximate UTC.  Since TT and TDB are
+            # pretty close (few msec?), assume TT.
+            njd1, njd2 = sofa_time.tt_tai(jd1, jd2)
+            njd1, njd2 = sofa_time.tai_utc(njd1, njd2)
+            # TODO: actually need to go to UT1 which needs DUT.
+            ut = njd1 + njd2
+
+            # Compute geodetic params needed for d_tdb_tt()
+            phi = np.radians(self.lat)
+            elon = np.radians(self.lon)
+            xyz = sofa_time.iau_gd2gc(1, elon, phi, 0.0)
+            u = np.sqrt(xyz[0] ** 2 + xyz[1] ** 2)
+            v = xyz[2]
+
+            self._delta_tdb_tt = sofa_time.d_tdb_tt(jd1, jd2, ut, elon, u, v)
+
+        return self._delta_tdb_tt
+
+    def _set_delta_tdb_tt(self, val):
+        self._delta_tdb_tt = self._match_len(val)
+
+    # Note can't use @property because _get_delta_tdb_tt is explicitly
+    # called with the optional jd1 and jd2 args.
+    delta_tdb_tt = property(_get_delta_tdb_tt, _set_delta_tdb_tt)
+    """TDB - TT time scale offset"""
+
+    def __len__(self):
+        return len(self._time)
+
+    def __sub__(self, other):
+        self_tai = self.tai
+        if not isinstance(other, Time):
+            raise OperandTypeError(self, other)
+
+        other_tai = other.tai
+        jd1 = self_tai.jd1 - other_tai.jd1
+        jd2 = self_tai.jd2 - other_tai.jd2
+
+        # T      - Tdelta = T
+        # Tdelta - Tdelta = Tdelta
+        # T      - T      = Tdelta
+        # Tdelta - T      = error
+        self_delta = isinstance(self, TimeDelta)
+        other_delta = isinstance(other, TimeDelta)
+        self_time = not self_delta  # only 2 possibilities
+        other_time = not other_delta
+        if (self_delta and other_delta) or (self_time and other_time):
+            return TimeDelta(jd1, jd2, format='jd')
+        elif (self_time and other_delta):
+            self_tai._time.jd1 = jd1
+            self_tai._time.jd2 = jd2
+            return getattr(self_tai, self.scale)
+        else:
+            raise OperandTypeError(self, other)
+
+    def __add__(self, other):
+        self_tai = self.tai
+        if not isinstance(other, Time):
+            raise OperandTypeError(self, other)
+
+        other_tai = other.tai
+        jd1 = self_tai.jd1 + other_tai.jd1
+        jd2 = self_tai.jd2 + other_tai.jd2
+
+        # T      + Tdelta = T
+        # Tdelta + Tdelta = Tdelta
+        # T      + T      = error
+        # Tdelta + T      = T
+        self_delta = isinstance(self, TimeDelta)
+        other_delta = isinstance(other, TimeDelta)
+        self_time = not self_delta  # only 2 possibilities
+        other_time = not other_delta
+        if (self_delta and other_delta):
+            return TimeDelta(jd1, jd2, format='jd')
+        elif (self_time and other_delta) or (self_delta and other_time):
+            tai = self_tai if self_time else other_tai
+            scale = self.scale if self_time else other.scale
+            tai._time.jd1 = jd1
+            tai._time.jd2 = jd2
+            return getattr(tai, scale)
+        else:
+            raise OperandTypeError(self, other)
+
+
+class TimeDelta(Time):
+    """
+    Represent the time difference between two times.
+
+    A TimeDelta object is initialized with one or more times in the ``val``
+    argument.  The input times in ``val`` must conform to the specified
+    ``format``.  The optional ``val2`` time input should be supplied only for
+    numeric input formats (e.g. JD) where very high precision (better than
+    64-bit precision) is required.
+
+    Parameters
+    ----------
+    val : numpy ndarray, list, str, number, or `~astropy.time.TimeDelta` object
+        Data to initialize table.
+    val2 : numpy ndarray, list, str, or number; optional
+        Data to initialize table.
+    format : str, optional
+        Format of input value(s)
+    copy : bool, optional
+        Make a copy of the input values
+    """
+    SCALES = TIME_DELTA_SCALES
+    """List of time delta scales"""
+
+    FORMATS = TIME_DELTA_FORMATS
+    """Dict of time delta formats"""
+
+    def __init__(self, val, val2=None, format=None, scale=None, copy=False):
+        # Note: scale is not used but is needed because of the inheritance
+        # from Time.
+        if not isinstance(val, self.__class__):
+            self._init_from_vals(val, val2, format, 'tai', copy)
+
+
+class TimeFormat(object):
+    """
+    Base class for time representations.
+
+    Parameters
+    ----------
+    val1 : numpy ndarray, list, str, or number
+        Data to initialize table.
+    val2 : numpy ndarray, list, str, or number; optional
+        Data to initialize table.
+    scale : str
+        Time scale of input value(s)
+    precision : int
+        Precision for seconds as floating point
+    in_subfmt : str
+        Select subformat for inputting string times
+    out_subfmt : str
+        Select subformat for outputting string times
+    from_jd : bool
+        If true then val1, val2 are jd1, jd2
+    """
+    def __init__(self, val1, val2, scale, precision,
+                 in_subfmt, out_subfmt, from_jd=False):
+        self.scale = scale  # validation of scale done later with _check_scale
+        self.precision = precision
+        self.in_subfmt = in_subfmt
+        self.out_subfmt = out_subfmt
+        if len(val1) != len(val2):
+            raise ValueError('Input val1 and val2 must match in length')
+
+        if from_jd:
+            self.jd1 = val1
+            self.jd2 = val2
+        else:
+            self._check_val_type(val1, val2)
+            self.set_jds(val1, val2)
+
+    def __len__(self):
+        return len(self.jd1)
+
+    @property
+    def scale(self):
+        """Time scale"""
+        self._scale = self._check_scale(self._scale)
+        return self._scale
+
+    @scale.setter
+    def scale(self, val):
+        self._scale = val
+
+    def _check_val_type(self, val1, val2):
+        """Input value validation, typically overridden by derived classes"""
+        if val1.dtype.type != np.double or val2.dtype.type != np.double:
+            raise TypeError('Input values for {0} class must be doubles'
+                             .format(self.name))
+
+    def _check_scale(self, scale):
+        """
+        Return a validated scale value.
+
+        If there is a class attribute 'scale' then that defines the default /
+        required time scale for this format.  In this case if a scale value was
+        provided that needs to match the class default, otherwise return
+        the class default.
+
+        Otherwise just make sure that scale is in the allowed list of
+        scales.  Provide a different error message if None (no value) was
+        supplied.
+        """
+        if hasattr(self.__class__, 'required_scale'):
+            # This format class has a required time scale
+            cls_scale = getattr(self.__class__, 'required_scale')
+            if (scale is not None and scale != cls_scale):
+                raise ScaleValueError('Class {0} requires scale={1} or None'
+                                 .format(self.__class__.__name__, cls_scale))
+            scale = cls_scale
+        else:
+            if scale not in TIME_SCALES:
+                if scale is None:
+                    raise ScaleValueError("No scale value supplied but it is "
+                                        "required for class {0}"
+                                        .format(self.__class__.__name__))
+                raise ScaleValueError("Scale value '{0}' not in "
+                                      "allowed values {1}"
+                                    .format(scale, TIME_SCALES))
+        return scale
+
+    def set_jds(self, val1, val2):
+        """
+        Set internal jd1 and jd2 from val1 and val2.  Must be provided
+        by derived classes.
+        """
+        raise NotImplementedError
+
+    @property
+    def vals(self):
+        """
+        Return time representation from internal jd1 and jd2.  Must be
+        provided by by derived classes.
+        """
+        raise NotImplementedError
+
+
+class TimeJD(TimeFormat):
+    """Julian Date time format"""
+    name = 'jd'
+
+    def set_jds(self, val1, val2):
+        self._check_scale(self._scale)  # Validate scale.
+        self.jd1 = val1
+        self.jd2 = val2
+
+    @property
+    def vals(self):
+        return self.jd1 + self.jd2
+
+
+class TimeMJD(TimeFormat):
+    """Modified Julian Date time format"""
+    name = 'mjd'
+
+    def set_jds(self, val1, val2):
+        # TODO - this routine and vals should be Cythonized to follow the SOFA
+        # convention of preserving precision by adding to the larger of the two
+        # values in a vectorized operation.  But in most practical cases the
+        # first one is probably biggest.
+        self._check_scale(self._scale)  # Validate scale.
+        self.jd1 = val1 + MJD_ZERO
+        self.jd2 = val2
+
+    @property
+    def vals(self):
+        return (self.jd1 - MJD_ZERO) + self.jd2
+
+
+class TimeFromEpoch(TimeFormat):
+    """
+    Base class for times that represent the interval from a particular
+    epoch as a floating point multiple of a unit time interval (e.g. seconds
+    or days).
+    """
+    def __init__(self, val1, val2, scale, precision,
+                 in_subfmt, out_subfmt, from_jd=False):
+        self.scale = scale
+        epoch = Time(self.epoch_val, self.epoch_val2, scale=self.epoch_scale,
+                     format=self.epoch_format)
+        self.epoch = getattr(epoch, self.scale)
+        super(TimeFromEpoch, self).__init__(val1, val2, scale, precision,
+                                            in_subfmt, out_subfmt, from_jd)
+
+    def set_jds(self, val1, val2):
+        self.jd1 = self.epoch.jd1 + val2 * self.unit
+        self.jd2 = self.epoch.jd2 + val1 * self.unit
+
+    @property
+    def vals(self):
+        return ((self.jd1 - self.epoch.jd1) +
+                (self.jd2 - self.epoch.jd2)) / self.unit
+
+
+class TimeUnix(TimeFromEpoch):
+    """
+    Unix time: seconds from 1970-01-01 00:00:00 UTC.
+
+    NOTE: this quantity is not exactly unix time and differs from the strict
+    POSIX definition by up to 1 second on days with a leap second.  POSIX
+    unix time actually jumps backward by 1 second at midnight on leap second
+    days while this class value is monotonically increasing at 86400 seconds
+    per UTC day.
+    """
+    name = 'unix'
+    unit = 1.0 / SECS_PER_DAY  # in days (1 day == 86400 seconds)
+    epoch_val = '1970-01-01 00:00:00'
+    epoch_val2 = None
+    epoch_scale = 'utc'
+    epoch_format = 'iso'
+    required_scale = 'utc'
+
+
+class TimeCxcSec(TimeFromEpoch):
+    """Chandra X-ray Center seconds from 1998-01-01 00:00:00 TT"""
+    name = 'cxcsec'
+    unit = 1.0 / SECS_PER_DAY  # in days (1 day == 86400 seconds)
+    epoch_val = '1998-01-01 00:00:00'
+    epoch_val2 = None
+    epoch_scale = 'tt'
+    epoch_format = 'iso'
+    required_scale = 'tai'
+
+
+class TimeString(TimeFormat):
+    """
+    Base class for string-like time represetations.
+
+    This class assumes that anything following the last decimal point to the
+    right is a fraction of a second.
+
+    This is a reference implementation can be made much faster with effort.
+    """
+    def _check_val_type(self, val1, val2):
+        if val1.dtype.kind not in ('S', 'U'):
+            raise TypeError('Input values for {0} class must be strings'
+                             .format(self.name))
+            # Note: don't care about val2 for these classes
+
+    def set_jds(self, val1, val2):
+        """Parse the time strings contained in val1 and set jd1, jd2"""
+        n_times = len(val1)  # val1,2 already checked to have same len
+        iy = np.empty(n_times, dtype=np.intc)
+        im = np.empty(n_times, dtype=np.intc)
+        id = np.empty(n_times, dtype=np.intc)
+        ihr = np.empty(n_times, dtype=np.intc)
+        imin = np.empty(n_times, dtype=np.intc)
+        dsec = np.empty(n_times, dtype=np.double)
+
+        # Select subformats based on current self.in_subfmt
+        subfmts = self._select_subfmts(self.in_subfmt)
+
+        for i, timestr in enumerate(val1):
+            # Assume that anything following "." on the right side is a
+            # floating fraction of a second.
+            try:
+                idot = timestr.rindex('.')
+            except:
+                fracsec = 0.0
+            else:
+                timestr, fracsec = timestr[:idot], timestr[idot:]
+                fracsec = float(fracsec)
+
+            for _, strptime_fmt, _ in subfmts:
+                try:
+                    tm = time.strptime(timestr, strptime_fmt)
+                except ValueError:
+                    pass
+                else:
+                    iy[i] = tm.tm_year
+                    im[i] = tm.tm_mon
+                    id[i] = tm.tm_mday
+                    ihr[i] = tm.tm_hour
+                    imin[i] = tm.tm_min
+                    dsec[i] = tm.tm_sec + fracsec
+                    break
+            else:
+                raise ValueError('Time {0} does not match {1} format'
+                                 .format(timestr, self.name))
+
+        self.jd1, self.jd2 = sofa_time.dtf_jd(self.scale.upper().encode('utf8'),
+                                              iy, im, id, ihr, imin, dsec)
+
+    def str_kwargs(self):
+        """
+        Generator that yields a dict of values corresponding to the
+        calendar date and time for the internal JD values.
+        """
+        iys, ims, ids, ihmsfs = sofa_time.jd_dtf(self.scale.upper()
+                                                 .encode('utf8'),
+                                                 self.precision,
+                                                 self.jd1, self.jd2)
+
+        # Get the str_fmt element of the first allowed output subformat
+        _, _, str_fmt = self._select_subfmts(self.out_subfmt)[0]
+
+        if '{yday:' in str_fmt:
+            from datetime import datetime
+            has_yday = True
+        else:
+            has_yday = False
+            yday = None
+
+        for iy, im, id, ihmsf in itertools.izip(iys, ims, ids, ihmsfs):
+            ihr, imin, isec, ifracsec = ihmsf
+            if has_yday:
+                yday = datetime(iy, im, id).timetuple().tm_yday
+
+            yield {'year': int(iy), 'mon': int(im), 'day': int(id),
+                   'hour': int(ihr), 'min': int(imin), 'sec': int(isec),
+                   'fracsec': int(ifracsec), 'yday': yday}
+
+    @property
+    def vals(self):
+        # Select the first available subformat based on current
+        # self.out_subfmt
+        subfmts = self._select_subfmts(self.out_subfmt)
+        _, _, str_fmt = subfmts[0]
+
+        # TODO: fix this ugly hack
+        if self.precision > 0 and str_fmt.endswith('{sec:02d}'):
+            str_fmt += '.{fracsec:0' + str(self.precision) + 'd}'
+
+        # Try to optimize this later.  Can't pre-allocate because length of
+        # output could change, e.g. year rolls from 999 to 1000.
+        outs = []
+        for kwargs in self.str_kwargs():
+            outs.append(str_fmt.format(**kwargs))
+
+        return np.array(outs)
+
+    def _select_subfmts(self, pattern):
+        """
+        Return a list of subformats where name matches ``pattern`` using
+        fnmatch.
+        """
+        from fnmatch import fnmatchcase
+        subfmts = [x for x in self.subfmts if fnmatchcase(x[0], pattern)]
+        if len(subfmts) == 0:
+            raise ValueError('No subformats match {0}'.format(pattern))
+        return subfmts
+
+
+class TimeISO(TimeString):
+    """
+    ISO 8601 compliant date-time format "YYYY-MM-DD HH:MM:SS.sss...".
+
+    The allowed subformats are:
+
+    - 'date_hms': date + hours, mins, secs (and optional fractional secs)
+    - 'date_hm': date + hours, mins
+    - 'date': date
+    """
+
+    name = 'iso'
+    subfmts = (('date_hms',
+                '%Y-%m-%d %H:%M:%S',
+                # XXX To Do - use strftime for output ??
+                '{year:d}-{mon:02d}-{day:02d} {hour:02d}:{min:02d}:{sec:02d}'),
+               ('date_hm',
+                '%Y-%m-%d %H:%M',
+                '{year:d}-{mon:02d}-{day:02d} {hour:02d}:{min:02d}'),
+               ('date',
+                '%Y-%m-%d',
+                '{year:d}-{mon:02d}-{day:02d}'))
+
+
+class TimeISOT(TimeString):
+    """
+    ISO 8601 compliant date-time format "YYYY-MM-DDTHH:MM:SS.sss...".
+    This is the same as TimeISO except for a "T" instead of space between
+    the date and time.
+
+    The allowed subformats are:
+
+    - 'date_hms': date + hours, mins, secs (and optional fractional secs)
+    - 'date_hm': date + hours, mins
+    - 'date': date
+    """
+
+    name = 'isot'
+    subfmts = (('date_hms',
+                '%Y-%m-%dT%H:%M:%S',
+                '{year:d}-{mon:02d}-{day:02d}T{hour:02d}:{min:02d}:{sec:02d}'),
+               ('date_hm',
+                '%Y-%m-%dT%H:%M',
+                '{year:d}-{mon:02d}-{day:02d}T{hour:02d}:{min:02d}'),
+               ('date',
+                '%Y-%m-%d',
+                '{year:d}-{mon:02d}-{day:02d}'))
+
+
+class TimeYearDayTime(TimeString):
+    """
+    Year, day-of-year and time as "YYYY:DOY:HH:MM:SS.sss...".  The
+    day-of-year (DOY) goes from 001 to 365 (366 in leap years).
+
+    The allowed subformats are:
+
+    - 'date_hms': date + hours, mins, secs (and optional fractional secs)
+    - 'date_hm': date + hours, mins
+    - 'date': date
+    """
+
+    name = 'yday'
+    subfmts = (('date_hms',
+                '%Y:%j:%H:%M:%S',
+                '{year:d}:{yday:03d}:{hour:02d}:{min:02d}:{sec:02d}'),
+               ('date_hm',
+                '%Y:%j:%H:%M',
+                '{year:d}:{yday:03d}:{hour:02d}:{min:02d}'),
+               ('date',
+                '%Y:%j',
+                '{year:d}:{yday:03d}'))
+
+
+class TimeEpochDate(TimeFormat):
+    """
+    Base class for support floating point Besselian and Julian epoch dates
+    """
+    def set_jds(self, val1, val2):
+        self._check_scale(self._scale)  # validate scale.
+        epoch_to_jd = getattr(sofa_time, self.epoch_to_jd)
+        self.jd1, self.jd2 = epoch_to_jd(val1 + val2)
+
+    @property
+    def vals(self):
+        jd_to_epoch = getattr(sofa_time, self.jd_to_epoch)
+        return jd_to_epoch(self.jd1, self.jd2)
+
+
+class TimeBesselianEpoch(TimeEpochDate):
+    """Besselian Epoch year as floating point value(s) like 1950.0"""
+    name = 'byear'
+    epoch_to_jd = 'besselian_epoch_jd'
+    jd_to_epoch = 'jd_besselian_epoch'
+
+
+class TimeJulianEpoch(TimeEpochDate):
+    """Julian Epoch year as floating point value(s) like 2000.0"""
+    name = 'jyear'
+    epoch_to_jd = 'julian_epoch_jd'
+    jd_to_epoch = 'jd_julian_epoch'
+
+
+class TimeEpochDateString(TimeString):
+    """
+    Base class to support string Besselian and Julian epoch dates
+    such as 'B1950.0' or 'J2000.0' respectively.
+    """
+    def set_jds(self, val1, val2):
+        years = np.empty(len(val1), dtype=np.double)
+        epoch_prefix = self.epoch_prefix
+
+        for i, time_str in enumerate(val1):
+            try:
+                epoch_type, year_str = time_str[0], time_str[1:]
+                year = float(year_str)
+                if epoch_type.upper() != epoch_prefix:
+                    raise ValueError
+            except (IndexError, ValueError) as err:
+                raise ValueError('Time {0} does not match {1} format'
+                                 .format(time_str, self.name))
+            else:
+                years[i] = year
+
+        self._check_scale(self._scale)  # validate scale.
+        epoch_to_jd = getattr(sofa_time, self.epoch_to_jd)
+        self.jd1, self.jd2 = epoch_to_jd(years)
+
+    @property
+    def vals(self):
+        jd_to_epoch = getattr(sofa_time, self.jd_to_epoch)
+        years = jd_to_epoch(self.jd1, self.jd2)
+        # Use old-style format since it is a factor of 2 faster
+        str_fmt = self.epoch_prefix + '%.' + str(self.precision) + 'f'
+        outs = [str_fmt % year for year in years]
+        return np.array(outs)
+
+
+class TimeBesselianEpochString(TimeEpochDateString):
+    """Besselian Epoch year as string value(s) like 'B1950.0'"""
+    name = 'byear_str'
+    epoch_to_jd = 'besselian_epoch_jd'
+    jd_to_epoch = 'jd_besselian_epoch'
+    epoch_prefix = 'B'
+
+
+class TimeJulianEpochString(TimeEpochDateString):
+    """Julian Epoch year as string value(s) like 'J2000.0'"""
+    name = 'jyear_str'
+    epoch_to_jd = 'julian_epoch_jd'
+    jd_to_epoch = 'jd_julian_epoch'
+    epoch_prefix = 'J'
+
+
+class TimeDeltaFormat(TimeFormat):
+    """Base class for time delta representations"""
+    pass
+
+
+class TimeDeltaSec(TimeDeltaFormat):
+    """Time delta in SI seconds"""
+    name = 'sec'
+
+    def set_jds(self, val1, val2):
+        self._check_scale(self._scale)  # Validate scale.
+        self.jd1 = val1 / SECS_PER_DAY
+        self.jd2 = val2 / SECS_PER_DAY
+
+    @property
+    def vals(self):
+        return (self.jd1 + self.jd2) * SECS_PER_DAY
+
+
+class TimeDeltaJD(TimeDeltaFormat):
+    """Time delta in Julian days (86400 SI seconds)"""
+    name = 'jd'
+
+    def set_jds(self, val1, val2):
+        self._check_scale(self._scale)  # Validate scale.
+        self.jd1 = val1
+        self.jd2 = val2
+
+    @property
+    def vals(self):
+        return self.jd1 + self.jd2
+
+
+class ScaleValueError(Exception):
+    pass
+
+
+# Set module constant with names of all available time formats
+for name, val in locals().items():
+    try:
+        is_timeformat = issubclass(val, TimeFormat)
+        is_timedeltaformat = issubclass(val, TimeDeltaFormat)
+    except:
+        pass
+    else:
+        if hasattr(val, 'name'):
+            if is_timedeltaformat:
+                TIME_DELTA_FORMATS[val.name] = val
+            elif is_timeformat:
+                TIME_FORMATS[val.name] = val
+
+
+def _make_1d_array(val, copy=False):
+    """
+    Take ``val`` and convert/reshape to a 1-d array.  If ``copy`` is True
+    then copy input values.
+
+    Returns
+    -------
+    val, val_ndim: ndarray, int
+        Array version of ``val`` and the number of dims in original.
+    """
+    val = np.array(val, copy=copy)
+    val_ndim = val.ndim  # remember original ndim
+    if val.ndim == 0:
+        val = np.asarray([val])
+    elif val_ndim > 1:
+        # Maybe lift this restriction later to allow multi-dim in/out?
+        raise TypeError('Input val must be zero or one dimensional')
+
+    # Allow only string or float arrays as input (XXX datetime later...)
+    if val.dtype.kind == 'i':
+        val = np.asarray(val, dtype=np.float64)
+
+    return val, val_ndim
+
+
+class OperandTypeError(TypeError):
+    def __init__(self, left, right):
+        self.value = ("unsupported operand type(s) for -: "
+                      "'{0}' and '{1}'".format(left.__class__.__name__,
+                                               right.__class__.__name__))
diff --git a/astropy/time/setup_package.py b/astropy/time/setup_package.py
new file mode 100644
index 0000000..b0bc577
--- /dev/null
+++ b/astropy/time/setup_package.py
@@ -0,0 +1,13 @@
+import os
+from distutils.extension import Extension
+
+TIMEROOT = os.path.relpath(os.path.dirname(__file__))
+
+
+def get_extensions():
+    time_ext = Extension(
+    name="astropy.time.sofa_time",
+    sources=[os.path.join(TIMEROOT, "sofa_time.pyx"), "cextern/sofa/sofa.c"],
+    include_dirs=['numpy', 'cextern/sofa'],
+    language="c",)
+    return [time_ext]
diff --git a/astropy/time/sofa_time.c b/astropy/time/sofa_time.c
new file mode 100644
index 0000000..afcd8a6
--- /dev/null
+++ b/astropy/time/sofa_time.c
@@ -0,0 +1,15186 @@
+/* Generated by Cython 0.15.1 on Mon Dec 24 15:34:15 2012 */
+
+#define PY_SSIZE_T_CLEAN
+#include "Python.h"
+#ifndef Py_PYTHON_H
+    #error Python headers needed to compile C extensions, please install development version of Python.
+#else
+
+#include <stddef.h> /* For offsetof */
+#ifndef offsetof
+#define offsetof(type, member) ( (size_t) & ((type*)0) -> member )
+#endif
+
+#if !defined(WIN32) && !defined(MS_WINDOWS)
+  #ifndef __stdcall
+    #define __stdcall
+  #endif
+  #ifndef __cdecl
+    #define __cdecl
+  #endif
+  #ifndef __fastcall
+    #define __fastcall
+  #endif
+#endif
+
+#ifndef DL_IMPORT
+  #define DL_IMPORT(t) t
+#endif
+#ifndef DL_EXPORT
+  #define DL_EXPORT(t) t
+#endif
+
+#ifndef PY_LONG_LONG
+  #define PY_LONG_LONG LONG_LONG
+#endif
+
+#if PY_VERSION_HEX < 0x02040000
+  #define METH_COEXIST 0
+  #define PyDict_CheckExact(op) (Py_TYPE(op) == &PyDict_Type)
+  #define PyDict_Contains(d,o)   PySequence_Contains(d,o)
+#endif
+
+#if PY_VERSION_HEX < 0x02050000
+  typedef int Py_ssize_t;
+  #define PY_SSIZE_T_MAX INT_MAX
+  #define PY_SSIZE_T_MIN INT_MIN
+  #define PY_FORMAT_SIZE_T ""
+  #define PyInt_FromSsize_t(z) PyInt_FromLong(z)
+  #define PyInt_AsSsize_t(o)   __Pyx_PyInt_AsInt(o)
+  #define PyNumber_Index(o)    PyNumber_Int(o)
+  #define PyIndex_Check(o)     PyNumber_Check(o)
+  #define PyErr_WarnEx(category, message, stacklevel) PyErr_Warn(category, message)
+#endif
+
+#if PY_VERSION_HEX < 0x02060000
+  #define Py_REFCNT(ob) (((PyObject*)(ob))->ob_refcnt)
+  #define Py_TYPE(ob)   (((PyObject*)(ob))->ob_type)
+  #define Py_SIZE(ob)   (((PyVarObject*)(ob))->ob_size)
+  #define PyVarObject_HEAD_INIT(type, size) \
+          PyObject_HEAD_INIT(type) size,
+  #define PyType_Modified(t)
+
+  typedef struct {
+     void *buf;
+     PyObject *obj;
+     Py_ssize_t len;
+     Py_ssize_t itemsize;
+     int readonly;
+     int ndim;
+     char *format;
+     Py_ssize_t *shape;
+     Py_ssize_t *strides;
+     Py_ssize_t *suboffsets;
+     void *internal;
+  } Py_buffer;
+
+  #define PyBUF_SIMPLE 0
+  #define PyBUF_WRITABLE 0x0001
+  #define PyBUF_FORMAT 0x0004
+  #define PyBUF_ND 0x0008
+  #define PyBUF_STRIDES (0x0010 | PyBUF_ND)
+  #define PyBUF_C_CONTIGUOUS (0x0020 | PyBUF_STRIDES)
+  #define PyBUF_F_CONTIGUOUS (0x0040 | PyBUF_STRIDES)
+  #define PyBUF_ANY_CONTIGUOUS (0x0080 | PyBUF_STRIDES)
+  #define PyBUF_INDIRECT (0x0100 | PyBUF_STRIDES)
+
+#endif
+
+#if PY_MAJOR_VERSION < 3
+  #define __Pyx_BUILTIN_MODULE_NAME "__builtin__"
+#else
+  #define __Pyx_BUILTIN_MODULE_NAME "builtins"
+#endif
+
+#if PY_MAJOR_VERSION >= 3
+  #define Py_TPFLAGS_CHECKTYPES 0
+  #define Py_TPFLAGS_HAVE_INDEX 0
+#endif
+
+#if (PY_VERSION_HEX < 0x02060000) || (PY_MAJOR_VERSION >= 3)
+  #define Py_TPFLAGS_HAVE_NEWBUFFER 0
+#endif
+
+#if PY_MAJOR_VERSION >= 3
+  #define PyBaseString_Type            PyUnicode_Type
+  #define PyStringObject               PyUnicodeObject
+  #define PyString_Type                PyUnicode_Type
+  #define PyString_Check               PyUnicode_Check
+  #define PyString_CheckExact          PyUnicode_CheckExact
+#endif
+
+#if PY_VERSION_HEX < 0x02060000
+  #define PyBytesObject                PyStringObject
+  #define PyBytes_Type                 PyString_Type
+  #define PyBytes_Check                PyString_Check
+  #define PyBytes_CheckExact           PyString_CheckExact
+  #define PyBytes_FromString           PyString_FromString
+  #define PyBytes_FromStringAndSize    PyString_FromStringAndSize
+  #define PyBytes_FromFormat           PyString_FromFormat
+  #define PyBytes_DecodeEscape         PyString_DecodeEscape
+  #define PyBytes_AsString             PyString_AsString
+  #define PyBytes_AsStringAndSize      PyString_AsStringAndSize
+  #define PyBytes_Size                 PyString_Size
+  #define PyBytes_AS_STRING            PyString_AS_STRING
+  #define PyBytes_GET_SIZE             PyString_GET_SIZE
+  #define PyBytes_Repr                 PyString_Repr
+  #define PyBytes_Concat               PyString_Concat
+  #define PyBytes_ConcatAndDel         PyString_ConcatAndDel
+#endif
+
+#if PY_VERSION_HEX < 0x02060000
+  #define PySet_Check(obj)             PyObject_TypeCheck(obj, &PySet_Type)
+  #define PyFrozenSet_Check(obj)       PyObject_TypeCheck(obj, &PyFrozenSet_Type)
+#endif
+#ifndef PySet_CheckExact
+  #define PySet_CheckExact(obj)        (Py_TYPE(obj) == &PySet_Type)
+#endif
+
+#define __Pyx_TypeCheck(obj, type) PyObject_TypeCheck(obj, (PyTypeObject *)type)
+
+#if PY_MAJOR_VERSION >= 3
+  #define PyIntObject                  PyLongObject
+  #define PyInt_Type                   PyLong_Type
+  #define PyInt_Check(op)              PyLong_Check(op)
+  #define PyInt_CheckExact(op)         PyLong_CheckExact(op)
+  #define PyInt_FromString             PyLong_FromString
+  #define PyInt_FromUnicode            PyLong_FromUnicode
+  #define PyInt_FromLong               PyLong_FromLong
+  #define PyInt_FromSize_t             PyLong_FromSize_t
+  #define PyInt_FromSsize_t            PyLong_FromSsize_t
+  #define PyInt_AsLong                 PyLong_AsLong
+  #define PyInt_AS_LONG                PyLong_AS_LONG
+  #define PyInt_AsSsize_t              PyLong_AsSsize_t
+  #define PyInt_AsUnsignedLongMask     PyLong_AsUnsignedLongMask
+  #define PyInt_AsUnsignedLongLongMask PyLong_AsUnsignedLongLongMask
+#endif
+
+#if PY_MAJOR_VERSION >= 3
+  #define PyBoolObject                 PyLongObject
+#endif
+
+#if PY_VERSION_HEX < 0x03020000
+  typedef long Py_hash_t;
+  #define __Pyx_PyInt_FromHash_t PyInt_FromLong
+  #define __Pyx_PyInt_AsHash_t   PyInt_AsLong
+#else
+  #define __Pyx_PyInt_FromHash_t PyInt_FromSsize_t
+  #define __Pyx_PyInt_AsHash_t   PyInt_AsSsize_t
+#endif
+
+
+#if PY_MAJOR_VERSION >= 3
+  #define __Pyx_PyNumber_Divide(x,y)         PyNumber_TrueDivide(x,y)
+  #define __Pyx_PyNumber_InPlaceDivide(x,y)  PyNumber_InPlaceTrueDivide(x,y)
+#else
+  #define __Pyx_PyNumber_Divide(x,y)         PyNumber_Divide(x,y)
+  #define __Pyx_PyNumber_InPlaceDivide(x,y)  PyNumber_InPlaceDivide(x,y)
+#endif
+
+#if (PY_MAJOR_VERSION < 3) || (PY_VERSION_HEX >= 0x03010300)
+  #define __Pyx_PySequence_GetSlice(obj, a, b) PySequence_GetSlice(obj, a, b)
+  #define __Pyx_PySequence_SetSlice(obj, a, b, value) PySequence_SetSlice(obj, a, b, value)
+  #define __Pyx_PySequence_DelSlice(obj, a, b) PySequence_DelSlice(obj, a, b)
+#else
+  #define __Pyx_PySequence_GetSlice(obj, a, b) (unlikely(!(obj)) ? \
+        (PyErr_SetString(PyExc_SystemError, "null argument to internal routine"), (PyObject*)0) : \
+        (likely((obj)->ob_type->tp_as_mapping) ? (PySequence_GetSlice(obj, a, b)) : \
+            (PyErr_Format(PyExc_TypeError, "'%.200s' object is unsliceable", (obj)->ob_type->tp_name), (PyObject*)0)))
+  #define __Pyx_PySequence_SetSlice(obj, a, b, value) (unlikely(!(obj)) ? \
+        (PyErr_SetString(PyExc_SystemError, "null argument to internal routine"), -1) : \
+        (likely((obj)->ob_type->tp_as_mapping) ? (PySequence_SetSlice(obj, a, b, value)) : \
+            (PyErr_Format(PyExc_TypeError, "'%.200s' object doesn't support slice assignment", (obj)->ob_type->tp_name), -1)))
+  #define __Pyx_PySequence_DelSlice(obj, a, b) (unlikely(!(obj)) ? \
+        (PyErr_SetString(PyExc_SystemError, "null argument to internal routine"), -1) : \
+        (likely((obj)->ob_type->tp_as_mapping) ? (PySequence_DelSlice(obj, a, b)) : \
+            (PyErr_Format(PyExc_TypeError, "'%.200s' object doesn't support slice deletion", (obj)->ob_type->tp_name), -1)))
+#endif
+
+#if PY_MAJOR_VERSION >= 3
+  #define PyMethod_New(func, self, klass) ((self) ? PyMethod_New(func, self) : PyInstanceMethod_New(func))
+#endif
+
+#if PY_VERSION_HEX < 0x02050000
+  #define __Pyx_GetAttrString(o,n)   PyObject_GetAttrString((o),((char *)(n)))
+  #define __Pyx_SetAttrString(o,n,a) PyObject_SetAttrString((o),((char *)(n)),(a))
+  #define __Pyx_DelAttrString(o,n)   PyObject_DelAttrString((o),((char *)(n)))
+#else
+  #define __Pyx_GetAttrString(o,n)   PyObject_GetAttrString((o),(n))
+  #define __Pyx_SetAttrString(o,n,a) PyObject_SetAttrString((o),(n),(a))
+  #define __Pyx_DelAttrString(o,n)   PyObject_DelAttrString((o),(n))
+#endif
+
+#if PY_VERSION_HEX < 0x02050000
+  #define __Pyx_NAMESTR(n) ((char *)(n))
+  #define __Pyx_DOCSTR(n)  ((char *)(n))
+#else
+  #define __Pyx_NAMESTR(n) (n)
+  #define __Pyx_DOCSTR(n)  (n)
+#endif
+
+#ifndef __PYX_EXTERN_C
+  #ifdef __cplusplus
+    #define __PYX_EXTERN_C extern "C"
+  #else
+    #define __PYX_EXTERN_C extern
+  #endif
+#endif
+
+#if defined(WIN32) || defined(MS_WINDOWS)
+#define _USE_MATH_DEFINES
+#endif
+#include <math.h>
+#define __PYX_HAVE__astropy__time__sofa_time
+#define __PYX_HAVE_API__astropy__time__sofa_time
+#include "stdio.h"
+#include "stdlib.h"
+#include "numpy/arrayobject.h"
+#include "numpy/ufuncobject.h"
+#include "sofa.h"
+#ifdef _OPENMP
+#include <omp.h>
+#endif /* _OPENMP */
+
+#ifdef PYREX_WITHOUT_ASSERTIONS
+#define CYTHON_WITHOUT_ASSERTIONS
+#endif
+
+
+/* inline attribute */
+#ifndef CYTHON_INLINE
+  #if defined(__GNUC__)
+    #define CYTHON_INLINE __inline__
+  #elif defined(_MSC_VER)
+    #define CYTHON_INLINE __inline
+  #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+    #define CYTHON_INLINE inline
+  #else
+    #define CYTHON_INLINE
+  #endif
+#endif
+
+/* unused attribute */
+#ifndef CYTHON_UNUSED
+# if defined(__GNUC__)
+#   if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))
+#     define CYTHON_UNUSED __attribute__ ((__unused__))
+#   else
+#     define CYTHON_UNUSED
+#   endif
+# elif defined(__ICC) || defined(__INTEL_COMPILER)
+#   define CYTHON_UNUSED __attribute__ ((__unused__))
+# else
+#   define CYTHON_UNUSED
+# endif
+#endif
+
+typedef struct {PyObject **p; char *s; const long n; const char* encoding; const char is_unicode; const char is_str; const char intern; } __Pyx_StringTabEntry; /*proto*/
+
+
+/* Type Conversion Predeclarations */
+
+#define __Pyx_PyBytes_FromUString(s) PyBytes_FromString((char*)s)
+#define __Pyx_PyBytes_AsUString(s)   ((unsigned char*) PyBytes_AsString(s))
+
+#define __Pyx_Owned_Py_None(b) (Py_INCREF(Py_None), Py_None)
+#define __Pyx_PyBool_FromLong(b) ((b) ? (Py_INCREF(Py_True), Py_True) : (Py_INCREF(Py_False), Py_False))
+static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject*);
+static CYTHON_INLINE PyObject* __Pyx_PyNumber_Int(PyObject* x);
+
+static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject*);
+static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t);
+static CYTHON_INLINE size_t __Pyx_PyInt_AsSize_t(PyObject*);
+
+#define __pyx_PyFloat_AsDouble(x) (PyFloat_CheckExact(x) ? PyFloat_AS_DOUBLE(x) : PyFloat_AsDouble(x))
+
+
+#ifdef __GNUC__
+  /* Test for GCC > 2.95 */
+  #if __GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95))
+    #define likely(x)   __builtin_expect(!!(x), 1)
+    #define unlikely(x) __builtin_expect(!!(x), 0)
+  #else /* __GNUC__ > 2 ... */
+    #define likely(x)   (x)
+    #define unlikely(x) (x)
+  #endif /* __GNUC__ > 2 ... */
+#else /* __GNUC__ */
+  #define likely(x)   (x)
+  #define unlikely(x) (x)
+#endif /* __GNUC__ */
+    
+static PyObject *__pyx_m;
+static PyObject *__pyx_b;
+static PyObject *__pyx_empty_tuple;
+static PyObject *__pyx_empty_bytes;
+static int __pyx_lineno;
+static int __pyx_clineno = 0;
+static const char * __pyx_cfilenm= __FILE__;
+static const char *__pyx_filename;
+
+
+#if !defined(CYTHON_CCOMPLEX)
+  #if defined(__cplusplus)
+    #define CYTHON_CCOMPLEX 1
+  #elif defined(_Complex_I)
+    #define CYTHON_CCOMPLEX 1
+  #else
+    #define CYTHON_CCOMPLEX 0
+  #endif
+#endif
+
+#if CYTHON_CCOMPLEX
+  #ifdef __cplusplus
+    #include <complex>
+  #else
+    #include <complex.h>
+  #endif
+#endif
+
+#if CYTHON_CCOMPLEX && !defined(__cplusplus) && defined(__sun__) && defined(__GNUC__)
+  #undef _Complex_I
+  #define _Complex_I 1.0fj
+#endif
+
+static const char *__pyx_f[] = {
+  "sofa_time.pyx",
+  "numpy.pxd",
+};
+
+/* "numpy.pxd":719
+ * # in Cython to enable them only on the right systems.
+ * 
+ * ctypedef npy_int8       int8_t             # <<<<<<<<<<<<<<
+ * ctypedef npy_int16      int16_t
+ * ctypedef npy_int32      int32_t
+ */
+typedef npy_int8 __pyx_t_5numpy_int8_t;
+
+/* "numpy.pxd":720
+ * 
+ * ctypedef npy_int8       int8_t
+ * ctypedef npy_int16      int16_t             # <<<<<<<<<<<<<<
+ * ctypedef npy_int32      int32_t
+ * ctypedef npy_int64      int64_t
+ */
+typedef npy_int16 __pyx_t_5numpy_int16_t;
+
+/* "numpy.pxd":721
+ * ctypedef npy_int8       int8_t
+ * ctypedef npy_int16      int16_t
+ * ctypedef npy_int32      int32_t             # <<<<<<<<<<<<<<
+ * ctypedef npy_int64      int64_t
+ * #ctypedef npy_int96      int96_t
+ */
+typedef npy_int32 __pyx_t_5numpy_int32_t;
+
+/* "numpy.pxd":722
+ * ctypedef npy_int16      int16_t
+ * ctypedef npy_int32      int32_t
+ * ctypedef npy_int64      int64_t             # <<<<<<<<<<<<<<
+ * #ctypedef npy_int96      int96_t
+ * #ctypedef npy_int128     int128_t
+ */
+typedef npy_int64 __pyx_t_5numpy_int64_t;
+
+/* "numpy.pxd":726
+ * #ctypedef npy_int128     int128_t
+ * 
+ * ctypedef npy_uint8      uint8_t             # <<<<<<<<<<<<<<
+ * ctypedef npy_uint16     uint16_t
+ * ctypedef npy_uint32     uint32_t
+ */
+typedef npy_uint8 __pyx_t_5numpy_uint8_t;
+
+/* "numpy.pxd":727
+ * 
+ * ctypedef npy_uint8      uint8_t
+ * ctypedef npy_uint16     uint16_t             # <<<<<<<<<<<<<<
+ * ctypedef npy_uint32     uint32_t
+ * ctypedef npy_uint64     uint64_t
+ */
+typedef npy_uint16 __pyx_t_5numpy_uint16_t;
+
+/* "numpy.pxd":728
+ * ctypedef npy_uint8      uint8_t
+ * ctypedef npy_uint16     uint16_t
+ * ctypedef npy_uint32     uint32_t             # <<<<<<<<<<<<<<
+ * ctypedef npy_uint64     uint64_t
+ * #ctypedef npy_uint96     uint96_t
+ */
+typedef npy_uint32 __pyx_t_5numpy_uint32_t;
+
+/* "numpy.pxd":729
+ * ctypedef npy_uint16     uint16_t
+ * ctypedef npy_uint32     uint32_t
+ * ctypedef npy_uint64     uint64_t             # <<<<<<<<<<<<<<
+ * #ctypedef npy_uint96     uint96_t
+ * #ctypedef npy_uint128    uint128_t
+ */
+typedef npy_uint64 __pyx_t_5numpy_uint64_t;
+
+/* "numpy.pxd":733
+ * #ctypedef npy_uint128    uint128_t
+ * 
+ * ctypedef npy_float32    float32_t             # <<<<<<<<<<<<<<
+ * ctypedef npy_float64    float64_t
+ * #ctypedef npy_float80    float80_t
+ */
+typedef npy_float32 __pyx_t_5numpy_float32_t;
+
+/* "numpy.pxd":734
+ * 
+ * ctypedef npy_float32    float32_t
+ * ctypedef npy_float64    float64_t             # <<<<<<<<<<<<<<
+ * #ctypedef npy_float80    float80_t
+ * #ctypedef npy_float128   float128_t
+ */
+typedef npy_float64 __pyx_t_5numpy_float64_t;
+
+/* "numpy.pxd":743
+ * # The int types are mapped a bit surprising --
+ * # numpy.int corresponds to 'l' and numpy.long to 'q'
+ * ctypedef npy_long       int_t             # <<<<<<<<<<<<<<
+ * ctypedef npy_longlong   long_t
+ * ctypedef npy_longlong   longlong_t
+ */
+typedef npy_long __pyx_t_5numpy_int_t;
+
+/* "numpy.pxd":744
+ * # numpy.int corresponds to 'l' and numpy.long to 'q'
+ * ctypedef npy_long       int_t
+ * ctypedef npy_longlong   long_t             # <<<<<<<<<<<<<<
+ * ctypedef npy_longlong   longlong_t
+ * 
+ */
+typedef npy_longlong __pyx_t_5numpy_long_t;
+
+/* "numpy.pxd":745
+ * ctypedef npy_long       int_t
+ * ctypedef npy_longlong   long_t
+ * ctypedef npy_longlong   longlong_t             # <<<<<<<<<<<<<<
+ * 
+ * ctypedef npy_ulong      uint_t
+ */
+typedef npy_longlong __pyx_t_5numpy_longlong_t;
+
+/* "numpy.pxd":747
+ * ctypedef npy_longlong   longlong_t
+ * 
+ * ctypedef npy_ulong      uint_t             # <<<<<<<<<<<<<<
+ * ctypedef npy_ulonglong  ulong_t
+ * ctypedef npy_ulonglong  ulonglong_t
+ */
+typedef npy_ulong __pyx_t_5numpy_uint_t;
+
+/* "numpy.pxd":748
+ * 
+ * ctypedef npy_ulong      uint_t
+ * ctypedef npy_ulonglong  ulong_t             # <<<<<<<<<<<<<<
+ * ctypedef npy_ulonglong  ulonglong_t
+ * 
+ */
+typedef npy_ulonglong __pyx_t_5numpy_ulong_t;
+
+/* "numpy.pxd":749
+ * ctypedef npy_ulong      uint_t
+ * ctypedef npy_ulonglong  ulong_t
+ * ctypedef npy_ulonglong  ulonglong_t             # <<<<<<<<<<<<<<
+ * 
+ * ctypedef npy_intp       intp_t
+ */
+typedef npy_ulonglong __pyx_t_5numpy_ulonglong_t;
+
+/* "numpy.pxd":751
+ * ctypedef npy_ulonglong  ulonglong_t
+ * 
+ * ctypedef npy_intp       intp_t             # <<<<<<<<<<<<<<
+ * ctypedef npy_uintp      uintp_t
+ * 
+ */
+typedef npy_intp __pyx_t_5numpy_intp_t;
+
+/* "numpy.pxd":752
+ * 
+ * ctypedef npy_intp       intp_t
+ * ctypedef npy_uintp      uintp_t             # <<<<<<<<<<<<<<
+ * 
+ * ctypedef npy_double     float_t
+ */
+typedef npy_uintp __pyx_t_5numpy_uintp_t;
+
+/* "numpy.pxd":754
+ * ctypedef npy_uintp      uintp_t
+ * 
+ * ctypedef npy_double     float_t             # <<<<<<<<<<<<<<
+ * ctypedef npy_double     double_t
+ * ctypedef npy_longdouble longdouble_t
+ */
+typedef npy_double __pyx_t_5numpy_float_t;
+
+/* "numpy.pxd":755
+ * 
+ * ctypedef npy_double     float_t
+ * ctypedef npy_double     double_t             # <<<<<<<<<<<<<<
+ * ctypedef npy_longdouble longdouble_t
+ * 
+ */
+typedef npy_double __pyx_t_5numpy_double_t;
+
+/* "numpy.pxd":756
+ * ctypedef npy_double     float_t
+ * ctypedef npy_double     double_t
+ * ctypedef npy_longdouble longdouble_t             # <<<<<<<<<<<<<<
+ * 
+ * ctypedef npy_cfloat      cfloat_t
+ */
+typedef npy_longdouble __pyx_t_5numpy_longdouble_t;
+
+/* "astropy/time/sofa_time.pyx":7
+ * import cython
+ * 
+ * ctypedef np.double_t DOUBLE_T             # <<<<<<<<<<<<<<
+ * 
+ * cdef extern from "sofa.h":
+ */
+typedef __pyx_t_5numpy_double_t __pyx_t_7astropy_4time_9sofa_time_DOUBLE_T;
+
+#if CYTHON_CCOMPLEX
+  #ifdef __cplusplus
+    typedef ::std::complex< float > __pyx_t_float_complex;
+  #else
+    typedef float _Complex __pyx_t_float_complex;
+  #endif
+#else
+    typedef struct { float real, imag; } __pyx_t_float_complex;
+#endif
+
+#if CYTHON_CCOMPLEX
+  #ifdef __cplusplus
+    typedef ::std::complex< double > __pyx_t_double_complex;
+  #else
+    typedef double _Complex __pyx_t_double_complex;
+  #endif
+#else
+    typedef struct { double real, imag; } __pyx_t_double_complex;
+#endif
+
+/*--- Type declarations ---*/
+
+/* "numpy.pxd":758
+ * ctypedef npy_longdouble longdouble_t
+ * 
+ * ctypedef npy_cfloat      cfloat_t             # <<<<<<<<<<<<<<
+ * ctypedef npy_cdouble     cdouble_t
+ * ctypedef npy_clongdouble clongdouble_t
+ */
+typedef npy_cfloat __pyx_t_5numpy_cfloat_t;
+
+/* "numpy.pxd":759
+ * 
+ * ctypedef npy_cfloat      cfloat_t
+ * ctypedef npy_cdouble     cdouble_t             # <<<<<<<<<<<<<<
+ * ctypedef npy_clongdouble clongdouble_t
+ * 
+ */
+typedef npy_cdouble __pyx_t_5numpy_cdouble_t;
+
+/* "numpy.pxd":760
+ * ctypedef npy_cfloat      cfloat_t
+ * ctypedef npy_cdouble     cdouble_t
+ * ctypedef npy_clongdouble clongdouble_t             # <<<<<<<<<<<<<<
+ * 
+ * ctypedef npy_cdouble     complex_t
+ */
+typedef npy_clongdouble __pyx_t_5numpy_clongdouble_t;
+
+/* "numpy.pxd":762
+ * ctypedef npy_clongdouble clongdouble_t
+ * 
+ * ctypedef npy_cdouble     complex_t             # <<<<<<<<<<<<<<
+ * 
+ * cdef inline object PyArray_MultiIterNew1(a):
+ */
+typedef npy_cdouble __pyx_t_5numpy_complex_t;
+
+
+#ifndef CYTHON_REFNANNY
+  #define CYTHON_REFNANNY 0
+#endif
+
+#if CYTHON_REFNANNY
+  typedef struct {
+    void (*INCREF)(void*, PyObject*, int);
+    void (*DECREF)(void*, PyObject*, int);
+    void (*GOTREF)(void*, PyObject*, int);
+    void (*GIVEREF)(void*, PyObject*, int);
+    void* (*SetupContext)(const char*, int, const char*);
+    void (*FinishContext)(void**);
+  } __Pyx_RefNannyAPIStruct;
+  static __Pyx_RefNannyAPIStruct *__Pyx_RefNanny = NULL;
+  static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname); /*proto*/
+  #define __Pyx_RefNannyDeclarations void *__pyx_refnanny = NULL;
+  #define __Pyx_RefNannySetupContext(name)           __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__)
+  #define __Pyx_RefNannyFinishContext()           __Pyx_RefNanny->FinishContext(&__pyx_refnanny)
+  #define __Pyx_INCREF(r)  __Pyx_RefNanny->INCREF(__pyx_refnanny, (PyObject *)(r), __LINE__)
+  #define __Pyx_DECREF(r)  __Pyx_RefNanny->DECREF(__pyx_refnanny, (PyObject *)(r), __LINE__)
+  #define __Pyx_GOTREF(r)  __Pyx_RefNanny->GOTREF(__pyx_refnanny, (PyObject *)(r), __LINE__)
+  #define __Pyx_GIVEREF(r) __Pyx_RefNanny->GIVEREF(__pyx_refnanny, (PyObject *)(r), __LINE__)
+  #define __Pyx_XINCREF(r)  do { if((r) != NULL) {__Pyx_INCREF(r); }} while(0)
+  #define __Pyx_XDECREF(r)  do { if((r) != NULL) {__Pyx_DECREF(r); }} while(0)
+  #define __Pyx_XGOTREF(r)  do { if((r) != NULL) {__Pyx_GOTREF(r); }} while(0)
+  #define __Pyx_XGIVEREF(r) do { if((r) != NULL) {__Pyx_GIVEREF(r);}} while(0)
+#else
+  #define __Pyx_RefNannyDeclarations
+  #define __Pyx_RefNannySetupContext(name)
+  #define __Pyx_RefNannyFinishContext()
+  #define __Pyx_INCREF(r) Py_INCREF(r)
+  #define __Pyx_DECREF(r) Py_DECREF(r)
+  #define __Pyx_GOTREF(r)
+  #define __Pyx_GIVEREF(r)
+  #define __Pyx_XINCREF(r) Py_XINCREF(r)
+  #define __Pyx_XDECREF(r) Py_XDECREF(r)
+  #define __Pyx_XGOTREF(r)
+  #define __Pyx_XGIVEREF(r)
+#endif /* CYTHON_REFNANNY */
+
+static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/
+
+static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact,
+    Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found); /*proto*/
+
+static void __Pyx_RaiseDoubleKeywordsError(
+    const char* func_name, PyObject* kw_name); /*proto*/
+
+static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[],     PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args,     const char* function_name); /*proto*/
+
+static CYTHON_INLINE int __Pyx_NegateNonNeg(int b) { 
+    return unlikely(b < 0) ? b : !b; 
+}
+static CYTHON_INLINE PyObject* __Pyx_PyBoolOrNull_FromLong(long b) {
+    return unlikely(b < 0) ? NULL : __Pyx_PyBool_FromLong(b);
+}
+
+static CYTHON_INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
+static CYTHON_INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
+
+static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause); /*proto*/
+
+static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
+    const char *name, int exact); /*proto*/
+
+/* Run-time type information about structs used with buffers */
+struct __Pyx_StructField_;
+
+typedef struct {
+  const char* name; /* for error messages only */
+  struct __Pyx_StructField_* fields;
+  size_t size;     /* sizeof(type) */
+  char typegroup; /* _R_eal, _C_omplex, Signed _I_nt, _U_nsigned int, _S_truct, _P_ointer, _O_bject */
+} __Pyx_TypeInfo;
+
+typedef struct __Pyx_StructField_ {
+  __Pyx_TypeInfo* type;
+  const char* name;
+  size_t offset;
+} __Pyx_StructField;
+
+typedef struct {
+  __Pyx_StructField* field;
+  size_t parent_offset;
+} __Pyx_BufFmt_StackElem;
+
+
+static CYTHON_INLINE int  __Pyx_GetBufferAndValidate(Py_buffer* buf, PyObject* obj, __Pyx_TypeInfo* dtype, int flags, int nd, int cast, __Pyx_BufFmt_StackElem* stack);
+static CYTHON_INLINE void __Pyx_SafeReleaseBuffer(Py_buffer* info);
+#define __Pyx_BufPtrStrided1d(type, buf, i0, s0) (type)((char*)buf + i0 * s0)
+
+static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); /*proto*/
+#define __Pyx_BufPtrStrided2d(type, buf, i0, s0, i1, s1) (type)((char*)buf + i0 * s0 + i1 * s1)
+static void __Pyx_RaiseBufferIndexError(int axis); /*proto*/
+
+static CYTHON_INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index);
+
+static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(Py_ssize_t expected);
+
+static CYTHON_INLINE void __Pyx_RaiseNoneNotIterableError(void);
+
+static void __Pyx_UnpackTupleError(PyObject *, Py_ssize_t index); /*proto*/
+#if PY_MAJOR_VERSION < 3
+static int __Pyx_GetBuffer(PyObject *obj, Py_buffer *view, int flags);
+static void __Pyx_ReleaseBuffer(Py_buffer *view);
+#else
+#define __Pyx_GetBuffer PyObject_GetBuffer
+#define __Pyx_ReleaseBuffer PyBuffer_Release
+#endif
+
+Py_ssize_t __Pyx_zeros[] = {0, 0};
+Py_ssize_t __Pyx_minusones[] = {-1, -1};
+
+static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, long level); /*proto*/
+
+#if CYTHON_CCOMPLEX
+  #ifdef __cplusplus
+    #define __Pyx_CREAL(z) ((z).real())
+    #define __Pyx_CIMAG(z) ((z).imag())
+  #else
+    #define __Pyx_CREAL(z) (__real__(z))
+    #define __Pyx_CIMAG(z) (__imag__(z))
+  #endif
+#else
+    #define __Pyx_CREAL(z) ((z).real)
+    #define __Pyx_CIMAG(z) ((z).imag)
+#endif
+
+#if defined(_WIN32) && defined(__cplusplus) && CYTHON_CCOMPLEX
+    #define __Pyx_SET_CREAL(z,x) ((z).real(x))
+    #define __Pyx_SET_CIMAG(z,y) ((z).imag(y))
+#else
+    #define __Pyx_SET_CREAL(z,x) __Pyx_CREAL(z) = (x)
+    #define __Pyx_SET_CIMAG(z,y) __Pyx_CIMAG(z) = (y)
+#endif
+
+static CYTHON_INLINE __pyx_t_float_complex __pyx_t_float_complex_from_parts(float, float);
+
+#if CYTHON_CCOMPLEX
+    #define __Pyx_c_eqf(a, b)   ((a)==(b))
+    #define __Pyx_c_sumf(a, b)  ((a)+(b))
+    #define __Pyx_c_difff(a, b) ((a)-(b))
+    #define __Pyx_c_prodf(a, b) ((a)*(b))
+    #define __Pyx_c_quotf(a, b) ((a)/(b))
+    #define __Pyx_c_negf(a)     (-(a))
+  #ifdef __cplusplus
+    #define __Pyx_c_is_zerof(z) ((z)==(float)0)
+    #define __Pyx_c_conjf(z)    (::std::conj(z))
+    #if 1
+        #define __Pyx_c_absf(z)     (::std::abs(z))
+        #define __Pyx_c_powf(a, b)  (::std::pow(a, b))
+    #endif
+  #else
+    #define __Pyx_c_is_zerof(z) ((z)==0)
+    #define __Pyx_c_conjf(z)    (conjf(z))
+    #if 1
+        #define __Pyx_c_absf(z)     (cabsf(z))
+        #define __Pyx_c_powf(a, b)  (cpowf(a, b))
+    #endif
+ #endif
+#else
+    static CYTHON_INLINE int __Pyx_c_eqf(__pyx_t_float_complex, __pyx_t_float_complex);
+    static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_sumf(__pyx_t_float_complex, __pyx_t_float_complex);
+    static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_difff(__pyx_t_float_complex, __pyx_t_float_complex);
+    static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_prodf(__pyx_t_float_complex, __pyx_t_float_complex);
+    static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_quotf(__pyx_t_float_complex, __pyx_t_float_complex);
+    static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_negf(__pyx_t_float_complex);
+    static CYTHON_INLINE int __Pyx_c_is_zerof(__pyx_t_float_complex);
+    static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_conjf(__pyx_t_float_complex);
+    #if 1
+        static CYTHON_INLINE float __Pyx_c_absf(__pyx_t_float_complex);
+        static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_powf(__pyx_t_float_complex, __pyx_t_float_complex);
+    #endif
+#endif
+
+static CYTHON_INLINE __pyx_t_double_complex __pyx_t_double_complex_from_parts(double, double);
+
+#if CYTHON_CCOMPLEX
+    #define __Pyx_c_eq(a, b)   ((a)==(b))
+    #define __Pyx_c_sum(a, b)  ((a)+(b))
+    #define __Pyx_c_diff(a, b) ((a)-(b))
+    #define __Pyx_c_prod(a, b) ((a)*(b))
+    #define __Pyx_c_quot(a, b) ((a)/(b))
+    #define __Pyx_c_neg(a)     (-(a))
+  #ifdef __cplusplus
+    #define __Pyx_c_is_zero(z) ((z)==(double)0)
+    #define __Pyx_c_conj(z)    (::std::conj(z))
+    #if 1
+        #define __Pyx_c_abs(z)     (::std::abs(z))
+        #define __Pyx_c_pow(a, b)  (::std::pow(a, b))
+    #endif
+  #else
+    #define __Pyx_c_is_zero(z) ((z)==0)
+    #define __Pyx_c_conj(z)    (conj(z))
+    #if 1
+        #define __Pyx_c_abs(z)     (cabs(z))
+        #define __Pyx_c_pow(a, b)  (cpow(a, b))
+    #endif
+ #endif
+#else
+    static CYTHON_INLINE int __Pyx_c_eq(__pyx_t_double_complex, __pyx_t_double_complex);
+    static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_sum(__pyx_t_double_complex, __pyx_t_double_complex);
+    static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_diff(__pyx_t_double_complex, __pyx_t_double_complex);
+    static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_prod(__pyx_t_double_complex, __pyx_t_double_complex);
+    static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_quot(__pyx_t_double_complex, __pyx_t_double_complex);
+    static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_neg(__pyx_t_double_complex);
+    static CYTHON_INLINE int __Pyx_c_is_zero(__pyx_t_double_complex);
+    static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_conj(__pyx_t_double_complex);
+    #if 1
+        static CYTHON_INLINE double __Pyx_c_abs(__pyx_t_double_complex);
+        static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_pow(__pyx_t_double_complex, __pyx_t_double_complex);
+    #endif
+#endif
+
+static CYTHON_INLINE unsigned char __Pyx_PyInt_AsUnsignedChar(PyObject *);
+
+static CYTHON_INLINE unsigned short __Pyx_PyInt_AsUnsignedShort(PyObject *);
+
+static CYTHON_INLINE unsigned int __Pyx_PyInt_AsUnsignedInt(PyObject *);
+
+static CYTHON_INLINE char __Pyx_PyInt_AsChar(PyObject *);
+
+static CYTHON_INLINE short __Pyx_PyInt_AsShort(PyObject *);
+
+static CYTHON_INLINE int __Pyx_PyInt_AsInt(PyObject *);
+
+static CYTHON_INLINE signed char __Pyx_PyInt_AsSignedChar(PyObject *);
+
+static CYTHON_INLINE signed short __Pyx_PyInt_AsSignedShort(PyObject *);
+
+static CYTHON_INLINE signed int __Pyx_PyInt_AsSignedInt(PyObject *);
+
+static CYTHON_INLINE int __Pyx_PyInt_AsLongDouble(PyObject *);
+
+static CYTHON_INLINE unsigned long __Pyx_PyInt_AsUnsignedLong(PyObject *);
+
+static CYTHON_INLINE unsigned PY_LONG_LONG __Pyx_PyInt_AsUnsignedLongLong(PyObject *);
+
+static CYTHON_INLINE long __Pyx_PyInt_AsLong(PyObject *);
+
+static CYTHON_INLINE PY_LONG_LONG __Pyx_PyInt_AsLongLong(PyObject *);
+
+static CYTHON_INLINE signed long __Pyx_PyInt_AsSignedLong(PyObject *);
+
+static CYTHON_INLINE signed PY_LONG_LONG __Pyx_PyInt_AsSignedLongLong(PyObject *);
+
+static int __Pyx_check_binary_version(void);
+
+static PyTypeObject *__Pyx_ImportType(const char *module_name, const char *class_name, size_t size, int strict);  /*proto*/
+
+static PyObject *__Pyx_ImportModule(const char *name); /*proto*/
+
+static void __Pyx_AddTraceback(const char *funcname, int __pyx_clineno,
+                               int __pyx_lineno, const char *__pyx_filename); /*proto*/
+
+static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); /*proto*/
+
+/* Module declarations from 'cpython.buffer' */
+
+/* Module declarations from 'cpython.ref' */
+
+/* Module declarations from 'libc.stdio' */
+
+/* Module declarations from 'cpython.object' */
+
+/* Module declarations from 'libc.stdlib' */
+
+/* Module declarations from 'numpy' */
+
+/* Module declarations from 'numpy' */
+static PyTypeObject *__pyx_ptype_5numpy_dtype = 0;
+static PyTypeObject *__pyx_ptype_5numpy_flatiter = 0;
+static PyTypeObject *__pyx_ptype_5numpy_broadcast = 0;
+static PyTypeObject *__pyx_ptype_5numpy_ndarray = 0;
+static PyTypeObject *__pyx_ptype_5numpy_ufunc = 0;
+static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew1(PyObject *); /*proto*/
+static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew2(PyObject *, PyObject *); /*proto*/
+static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew3(PyObject *, PyObject *, PyObject *); /*proto*/
+static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew4(PyObject *, PyObject *, PyObject *, PyObject *); /*proto*/
+static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew5(PyObject *, PyObject *, PyObject *, PyObject *, PyObject *); /*proto*/
+static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *, char *, char *, int *); /*proto*/
+static CYTHON_INLINE void __pyx_f_5numpy_set_array_base(PyArrayObject *, PyObject *); /*proto*/
+static CYTHON_INLINE PyObject *__pyx_f_5numpy_get_array_base(PyArrayObject *); /*proto*/
+
+/* Module declarations from 'cython.cython.view' */
+
+/* Module declarations from 'cython' */
+
+/* Module declarations from 'astropy.time.sofa_time' */
+static __Pyx_TypeInfo __Pyx_TypeInfo_int = { "int", NULL, sizeof(int), 'I' };
+static __Pyx_TypeInfo __Pyx_TypeInfo_double = { "double", NULL, sizeof(double), 'R' };
+#define __Pyx_MODULE_NAME "astropy.time.sofa_time"
+int __pyx_module_is_main_astropy__time__sofa_time = 0;
+
+/* Implementation of 'astropy.time.sofa_time' */
+static PyObject *__pyx_builtin_ValueError;
+static PyObject *__pyx_builtin_range;
+static PyObject *__pyx_builtin_ord;
+static PyObject *__pyx_builtin_RuntimeError;
+static char __pyx_k_3[] = "{0}: {1}";
+static char __pyx_k_4[] = "Unexpected return code {0} from {1}";
+static char __pyx_k_5[] = "Bad input day (JD still computed)";
+static char __pyx_k_6[] = "Bad input year";
+static char __pyx_k_7[] = "Bad input month";
+static char __pyx_k_8[] = "bad year";
+static char __pyx_k_9[] = "bad month (must be 1 to 12)";
+static char __pyx_k_10[] = "bad day (must be within normal calendar date for a month)";
+static char __pyx_k_11[] = "bad fraction of day";
+static char __pyx_k_12[] = "unacceptable date";
+static char __pyx_k_13[] = "time is after end of day and ";
+static char __pyx_k_14[] = "time is after end of day";
+static char __pyx_k_15[] = "bad month";
+static char __pyx_k_16[] = "bad day";
+static char __pyx_k_17[] = "bad hour";
+static char __pyx_k_18[] = "bad minute";
+static char __pyx_k_19[] = "bad second (< 0)";
+static char __pyx_k_20[] = "ideg outside range 0-359";
+static char __pyx_k_21[] = "iamin outside range 0-59";
+static char __pyx_k_22[] = "asec outside range 0-59.999...";
+static char __pyx_k_24[] = "illegal identifier";
+static char __pyx_k_25[] = "illegal case";
+static char __pyx_k_26[] = "ndarray is not C contiguous";
+static char __pyx_k_28[] = "ndarray is not Fortran contiguous";
+static char __pyx_k_30[] = "Non-native byte order not supported";
+static char __pyx_k_32[] = "unknown dtype code in numpy.pxd (%d)";
+static char __pyx_k_33[] = "Format string allocated too short, see comment in numpy.pxd";
+static char __pyx_k_36[] = "Format string allocated too short.";
+static char __pyx_k_38[] = "dubious year for UTC (before 1960.0 or 5 years beyond last known leap second)";
+static char __pyx_k_39[] = "astropy.time.sofa_time";
+static char __pyx_k__B[] = "B";
+static char __pyx_k__H[] = "H";
+static char __pyx_k__I[] = "I";
+static char __pyx_k__L[] = "L";
+static char __pyx_k__O[] = "O";
+static char __pyx_k__Q[] = "Q";
+static char __pyx_k__b[] = "b";
+static char __pyx_k__d[] = "d";
+static char __pyx_k__f[] = "f";
+static char __pyx_k__g[] = "g";
+static char __pyx_k__h[] = "h";
+static char __pyx_k__i[] = "i";
+static char __pyx_k__l[] = "l";
+static char __pyx_k__n[] = "n";
+static char __pyx_k__q[] = "q";
+static char __pyx_k__u[] = "u";
+static char __pyx_k__v[] = "v";
+static char __pyx_k__Zd[] = "Zd";
+static char __pyx_k__Zf[] = "Zf";
+static char __pyx_k__Zg[] = "Zg";
+static char __pyx_k__d1[] = "d1";
+static char __pyx_k__d2[] = "d2";
+static char __pyx_k__dt[] = "dt";
+static char __pyx_k__fd[] = "fd";
+static char __pyx_k__id[] = "id";
+static char __pyx_k__im[] = "im";
+static char __pyx_k__iy[] = "iy";
+static char __pyx_k__np[] = "np";
+static char __pyx_k__ut[] = "ut";
+static char __pyx_k__djm[] = "djm";
+static char __pyx_k__ihr[] = "ihr";
+static char __pyx_k__imn[] = "imn";
+static char __pyx_k__in1[] = "in1";
+static char __pyx_k__in2[] = "in2";
+static char __pyx_k__jd1[] = "jd1";
+static char __pyx_k__jd2[] = "jd2";
+static char __pyx_k__ndp[] = "ndp";
+static char __pyx_k__ord[] = "ord";
+static char __pyx_k__phi[] = "phi";
+static char __pyx_k__ret[] = "ret";
+static char __pyx_k__sec[] = "sec";
+static char __pyx_k__asec[] = "asec";
+static char __pyx_k__djm0[] = "djm0";
+static char __pyx_k__ideg[] = "ideg";
+static char __pyx_k__intc[] = "intc";
+static char __pyx_k__sign[] = "sign";
+static char __pyx_k__warn[] = "warn";
+static char __pyx_k__dtype[] = "dtype";
+static char __pyx_k__elong[] = "elong";
+static char __pyx_k__empty[] = "empty";
+static char __pyx_k__iamin[] = "iamin";
+static char __pyx_k__numpy[] = "numpy";
+static char __pyx_k__range[] = "range";
+static char __pyx_k__scale[] = "scale";
+static char __pyx_k__warns[] = "warns";
+static char __pyx_k__cal2jd[] = "cal2jd";
+static char __pyx_k__double[] = "double";
+static char __pyx_k__dtf_jd[] = "dtf_jd";
+static char __pyx_k__errors[] = "errors";
+static char __pyx_k__format[] = "format";
+static char __pyx_k__height[] = "height";
+static char __pyx_k__iauDat[] = "iauDat";
+static char __pyx_k__jd_dtf[] = "jd_dtf";
+static char __pyx_k__tai_tt[] = "tai_tt";
+static char __pyx_k__tcg_tt[] = "tcg_tt";
+static char __pyx_k__tdb_tt[] = "tdb_tt";
+static char __pyx_k__tt_tai[] = "tt_tai";
+static char __pyx_k__tt_tcg[] = "tt_tcg";
+static char __pyx_k__tt_tdb[] = "tt_tdb";
+static char __pyx_k__tt_ut1[] = "tt_ut1";
+static char __pyx_k__ut1_tt[] = "ut1_tt";
+static char __pyx_k__DUBIOUS[] = "DUBIOUS";
+static char __pyx_k__iauAf2a[] = "iauAf2a";
+static char __pyx_k__tai_ut1[] = "tai_ut1";
+static char __pyx_k__tai_utc[] = "tai_utc";
+static char __pyx_k__tcb_tdb[] = "tcb_tdb";
+static char __pyx_k__tdb_tcb[] = "tdb_tcb";
+static char __pyx_k__ut1_tai[] = "ut1_tai";
+static char __pyx_k__ut1_utc[] = "ut1_utc";
+static char __pyx_k__utc_tai[] = "utc_tai";
+static char __pyx_k__utc_ut1[] = "utc_ut1";
+static char __pyx_k____main__[] = "__main__";
+static char __pyx_k____test__[] = "__test__";
+static char __pyx_k__d_tdb_tt[] = "d_tdb_tt";
+static char __pyx_k__iauD2dtf[] = "iauD2dtf";
+static char __pyx_k__iauDtf2d[] = "iauDtf2d";
+static char __pyx_k__iauGd2gc[] = "iauGd2gc";
+static char __pyx_k__iauTaitt[] = "iauTaitt";
+static char __pyx_k__iauTcgtt[] = "iauTcgtt";
+static char __pyx_k__iauTdbtt[] = "iauTdbtt";
+static char __pyx_k__iauTttai[] = "iauTttai";
+static char __pyx_k__iauTttcg[] = "iauTttcg";
+static char __pyx_k__iauTttdb[] = "iauTttdb";
+static char __pyx_k__iauTtut1[] = "iauTtut1";
+static char __pyx_k__iauUt1tt[] = "iauUt1tt";
+static char __pyx_k__iau_af2a[] = "iau_af2a";
+static char __pyx_k__warnings[] = "warnings";
+static char __pyx_k__d_tai_utc[] = "d_tai_utc";
+static char __pyx_k__func_name[] = "func_name";
+static char __pyx_k__iauCal2jd[] = "iauCal2jd";
+static char __pyx_k__iauTaiut1[] = "iauTaiut1";
+static char __pyx_k__iauTaiutc[] = "iauTaiutc";
+static char __pyx_k__iauTcbtdb[] = "iauTcbtdb";
+static char __pyx_k__iauTdbtcb[] = "iauTdbtcb";
+static char __pyx_k__iauUt1tai[] = "iauUt1tai";
+static char __pyx_k__iauUt1utc[] = "iauUt1utc";
+static char __pyx_k__iauUtctai[] = "iauUtctai";
+static char __pyx_k__iauUtcut1[] = "iauUtcut1";
+static char __pyx_k__iau_gd2gc[] = "iau_gd2gc";
+static char __pyx_k__ValueError[] = "ValueError";
+static char __pyx_k__RuntimeError[] = "RuntimeError";
+static char __pyx_k__check_return[] = "check_return";
+static char __pyx_k__jd_julian_epoch[] = "jd_julian_epoch";
+static char __pyx_k__julian_epoch_jd[] = "julian_epoch_jd";
+static char __pyx_k__besselian_epoch_jd[] = "besselian_epoch_jd";
+static char __pyx_k__jd_besselian_epoch[] = "jd_besselian_epoch";
+static PyObject *__pyx_kp_s_10;
+static PyObject *__pyx_kp_s_11;
+static PyObject *__pyx_kp_s_12;
+static PyObject *__pyx_kp_s_13;
+static PyObject *__pyx_kp_s_14;
+static PyObject *__pyx_kp_s_15;
+static PyObject *__pyx_kp_s_16;
+static PyObject *__pyx_kp_s_17;
+static PyObject *__pyx_kp_s_18;
+static PyObject *__pyx_kp_s_19;
+static PyObject *__pyx_kp_s_20;
+static PyObject *__pyx_kp_s_21;
+static PyObject *__pyx_kp_s_22;
+static PyObject *__pyx_kp_s_24;
+static PyObject *__pyx_kp_s_25;
+static PyObject *__pyx_kp_u_26;
+static PyObject *__pyx_kp_u_28;
+static PyObject *__pyx_kp_s_3;
+static PyObject *__pyx_kp_u_30;
+static PyObject *__pyx_kp_u_32;
+static PyObject *__pyx_kp_u_33;
+static PyObject *__pyx_kp_u_36;
+static PyObject *__pyx_kp_s_38;
+static PyObject *__pyx_n_s_39;
+static PyObject *__pyx_kp_s_4;
+static PyObject *__pyx_kp_s_5;
+static PyObject *__pyx_kp_s_6;
+static PyObject *__pyx_kp_s_7;
+static PyObject *__pyx_kp_s_8;
+static PyObject *__pyx_kp_s_9;
+static PyObject *__pyx_n_s__DUBIOUS;
+static PyObject *__pyx_n_s__RuntimeError;
+static PyObject *__pyx_n_s__ValueError;
+static PyObject *__pyx_n_s____main__;
+static PyObject *__pyx_n_s____test__;
+static PyObject *__pyx_n_s__asec;
+static PyObject *__pyx_n_s__besselian_epoch_jd;
+static PyObject *__pyx_n_s__cal2jd;
+static PyObject *__pyx_n_s__check_return;
+static PyObject *__pyx_n_s__d1;
+static PyObject *__pyx_n_s__d2;
+static PyObject *__pyx_n_s__d_tai_utc;
+static PyObject *__pyx_n_s__d_tdb_tt;
+static PyObject *__pyx_n_s__djm;
+static PyObject *__pyx_n_s__djm0;
+static PyObject *__pyx_n_s__double;
+static PyObject *__pyx_n_s__dt;
+static PyObject *__pyx_n_s__dtf_jd;
+static PyObject *__pyx_n_s__dtype;
+static PyObject *__pyx_n_s__elong;
+static PyObject *__pyx_n_s__empty;
+static PyObject *__pyx_n_s__errors;
+static PyObject *__pyx_n_s__fd;
+static PyObject *__pyx_n_s__format;
+static PyObject *__pyx_n_s__func_name;
+static PyObject *__pyx_n_s__height;
+static PyObject *__pyx_n_s__iamin;
+static PyObject *__pyx_n_s__iauAf2a;
+static PyObject *__pyx_n_s__iauCal2jd;
+static PyObject *__pyx_n_s__iauD2dtf;
+static PyObject *__pyx_n_s__iauDat;
+static PyObject *__pyx_n_s__iauDtf2d;
+static PyObject *__pyx_n_s__iauGd2gc;
+static PyObject *__pyx_n_s__iauTaitt;
+static PyObject *__pyx_n_s__iauTaiut1;
+static PyObject *__pyx_n_s__iauTaiutc;
+static PyObject *__pyx_n_s__iauTcbtdb;
+static PyObject *__pyx_n_s__iauTcgtt;
+static PyObject *__pyx_n_s__iauTdbtcb;
+static PyObject *__pyx_n_s__iauTdbtt;
+static PyObject *__pyx_n_s__iauTttai;
+static PyObject *__pyx_n_s__iauTttcg;
+static PyObject *__pyx_n_s__iauTttdb;
+static PyObject *__pyx_n_s__iauTtut1;
+static PyObject *__pyx_n_s__iauUt1tai;
+static PyObject *__pyx_n_s__iauUt1tt;
+static PyObject *__pyx_n_s__iauUt1utc;
+static PyObject *__pyx_n_s__iauUtctai;
+static PyObject *__pyx_n_s__iauUtcut1;
+static PyObject *__pyx_n_s__iau_af2a;
+static PyObject *__pyx_n_s__iau_gd2gc;
+static PyObject *__pyx_n_s__id;
+static PyObject *__pyx_n_s__ideg;
+static PyObject *__pyx_n_s__ihr;
+static PyObject *__pyx_n_s__im;
+static PyObject *__pyx_n_s__imn;
+static PyObject *__pyx_n_s__in1;
+static PyObject *__pyx_n_s__in2;
+static PyObject *__pyx_n_s__intc;
+static PyObject *__pyx_n_s__iy;
+static PyObject *__pyx_n_s__jd1;
+static PyObject *__pyx_n_s__jd2;
+static PyObject *__pyx_n_s__jd_besselian_epoch;
+static PyObject *__pyx_n_s__jd_dtf;
+static PyObject *__pyx_n_s__jd_julian_epoch;
+static PyObject *__pyx_n_s__julian_epoch_jd;
+static PyObject *__pyx_n_s__n;
+static PyObject *__pyx_n_s__ndp;
+static PyObject *__pyx_n_s__np;
+static PyObject *__pyx_n_s__numpy;
+static PyObject *__pyx_n_s__ord;
+static PyObject *__pyx_n_s__phi;
+static PyObject *__pyx_n_s__range;
+static PyObject *__pyx_n_s__ret;
+static PyObject *__pyx_n_s__scale;
+static PyObject *__pyx_n_s__sec;
+static PyObject *__pyx_n_s__sign;
+static PyObject *__pyx_n_s__tai_tt;
+static PyObject *__pyx_n_s__tai_ut1;
+static PyObject *__pyx_n_s__tai_utc;
+static PyObject *__pyx_n_s__tcb_tdb;
+static PyObject *__pyx_n_s__tcg_tt;
+static PyObject *__pyx_n_s__tdb_tcb;
+static PyObject *__pyx_n_s__tdb_tt;
+static PyObject *__pyx_n_s__tt_tai;
+static PyObject *__pyx_n_s__tt_tcg;
+static PyObject *__pyx_n_s__tt_tdb;
+static PyObject *__pyx_n_s__tt_ut1;
+static PyObject *__pyx_n_s__u;
+static PyObject *__pyx_n_s__ut;
+static PyObject *__pyx_n_s__ut1_tai;
+static PyObject *__pyx_n_s__ut1_tt;
+static PyObject *__pyx_n_s__ut1_utc;
+static PyObject *__pyx_n_s__utc_tai;
+static PyObject *__pyx_n_s__utc_ut1;
+static PyObject *__pyx_n_s__v;
+static PyObject *__pyx_n_s__warn;
+static PyObject *__pyx_n_s__warnings;
+static PyObject *__pyx_n_s__warns;
+static PyObject *__pyx_int_0;
+static PyObject *__pyx_int_1;
+static PyObject *__pyx_int_2;
+static PyObject *__pyx_int_3;
+static PyObject *__pyx_int_4;
+static PyObject *__pyx_int_neg_1;
+static PyObject *__pyx_int_neg_2;
+static PyObject *__pyx_int_neg_3;
+static PyObject *__pyx_int_neg_4;
+static PyObject *__pyx_int_neg_5;
+static PyObject *__pyx_int_neg_6;
+static PyObject *__pyx_int_15;
+static PyObject *__pyx_k_1;
+static PyObject *__pyx_k_2;
+static PyObject *__pyx_k_tuple_23;
+static PyObject *__pyx_k_tuple_27;
+static PyObject *__pyx_k_tuple_29;
+static PyObject *__pyx_k_tuple_31;
+static PyObject *__pyx_k_tuple_34;
+static PyObject *__pyx_k_tuple_35;
+static PyObject *__pyx_k_tuple_37;
+
+/* "astropy/time/sofa_time.pyx":52
+ *           'beyond last known leap second)'
+ * 
+ * def check_return(ret, func_name, warns={}, errors={}):             # <<<<<<<<<<<<<<
+ *     """Check the return value from an iau routine"""
+ *     if ret in warns:
+ */
+
+static PyObject *__pyx_pf_7astropy_4time_9sofa_time_check_return(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_7astropy_4time_9sofa_time_check_return[] = "Check the return value from an iau routine";
+static PyMethodDef __pyx_mdef_7astropy_4time_9sofa_time_check_return = {__Pyx_NAMESTR("check_return"), (PyCFunction)__pyx_pf_7astropy_4time_9sofa_time_check_return, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(__pyx_doc_7astropy_4time_9sofa_time_check_return)};
+static PyObject *__pyx_pf_7astropy_4time_9sofa_time_check_return(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyObject *__pyx_v_ret = 0;
+  PyObject *__pyx_v_func_name = 0;
+  PyObject *__pyx_v_warns = 0;
+  PyObject *__pyx_v_errors = 0;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  int __pyx_t_1;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
+  PyObject *__pyx_t_5 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__ret,&__pyx_n_s__func_name,&__pyx_n_s__warns,&__pyx_n_s__errors,0};
+  __Pyx_RefNannySetupContext("check_return");
+  __pyx_self = __pyx_self;
+  {
+    PyObject* values[4] = {0,0,0,0};
+    values[2] = __pyx_k_1;
+    values[3] = __pyx_k_2;
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
+        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  0:
+        values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__ret);
+        if (likely(values[0])) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+        case  1:
+        values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__func_name);
+        if (likely(values[1])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("check_return", 0, 2, 4, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 52; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+        case  2:
+        if (kw_args > 0) {
+          PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s__warns);
+          if (value) { values[2] = value; kw_args--; }
+        }
+        case  3:
+        if (kw_args > 0) {
+          PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s__errors);
+          if (value) { values[3] = value; kw_args--; }
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "check_return") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 52; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+    } else {
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
+        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+    }
+    __pyx_v_ret = values[0];
+    __pyx_v_func_name = values[1];
+    __pyx_v_warns = values[2];
+    __pyx_v_errors = values[3];
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("check_return", 0, 2, 4, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 52; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("astropy.time.sofa_time.check_return", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+
+  /* "astropy/time/sofa_time.pyx":54
+ * def check_return(ret, func_name, warns={}, errors={}):
+ *     """Check the return value from an iau routine"""
+ *     if ret in warns:             # <<<<<<<<<<<<<<
+ *         warnings.warn('{0}: {1}'.format(func_name, warns[ret]))
+ *     elif ret in errors:
+ */
+  __pyx_t_1 = ((PySequence_Contains(__pyx_v_warns, __pyx_v_ret))); if (unlikely(__pyx_t_1 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 54; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (__pyx_t_1) {
+
+    /* "astropy/time/sofa_time.pyx":55
+ *     """Check the return value from an iau routine"""
+ *     if ret in warns:
+ *         warnings.warn('{0}: {1}'.format(func_name, warns[ret]))             # <<<<<<<<<<<<<<
+ *     elif ret in errors:
+ *         raise ValueError('{0}: {1}'.format(func_name, errors[ret]))
+ */
+    __pyx_t_2 = __Pyx_GetName(__pyx_m, __pyx_n_s__warnings); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 55; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_2);
+    __pyx_t_3 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s__warn); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 55; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_3);
+    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+    __pyx_t_2 = PyObject_GetAttr(((PyObject *)__pyx_kp_s_3), __pyx_n_s__format); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 55; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_2);
+    __pyx_t_4 = PyObject_GetItem(__pyx_v_warns, __pyx_v_ret); if (!__pyx_t_4) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 55; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_4);
+    __pyx_t_5 = PyTuple_New(2); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 55; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(((PyObject *)__pyx_t_5));
+    __Pyx_INCREF(__pyx_v_func_name);
+    PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_v_func_name);
+    __Pyx_GIVEREF(__pyx_v_func_name);
+    PyTuple_SET_ITEM(__pyx_t_5, 1, __pyx_t_4);
+    __Pyx_GIVEREF(__pyx_t_4);
+    __pyx_t_4 = 0;
+    __pyx_t_4 = PyObject_Call(__pyx_t_2, ((PyObject *)__pyx_t_5), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 55; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_4);
+    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+    __Pyx_DECREF(((PyObject *)__pyx_t_5)); __pyx_t_5 = 0;
+    __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 55; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(((PyObject *)__pyx_t_5));
+    PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_4);
+    __Pyx_GIVEREF(__pyx_t_4);
+    __pyx_t_4 = 0;
+    __pyx_t_4 = PyObject_Call(__pyx_t_3, ((PyObject *)__pyx_t_5), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 55; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_4);
+    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+    __Pyx_DECREF(((PyObject *)__pyx_t_5)); __pyx_t_5 = 0;
+    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+    goto __pyx_L6;
+  }
+
+  /* "astropy/time/sofa_time.pyx":56
+ *     if ret in warns:
+ *         warnings.warn('{0}: {1}'.format(func_name, warns[ret]))
+ *     elif ret in errors:             # <<<<<<<<<<<<<<
+ *         raise ValueError('{0}: {1}'.format(func_name, errors[ret]))
+ *     elif ret != 0:
+ */
+  __pyx_t_1 = ((PySequence_Contains(__pyx_v_errors, __pyx_v_ret))); if (unlikely(__pyx_t_1 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 56; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (__pyx_t_1) {
+
+    /* "astropy/time/sofa_time.pyx":57
+ *         warnings.warn('{0}: {1}'.format(func_name, warns[ret]))
+ *     elif ret in errors:
+ *         raise ValueError('{0}: {1}'.format(func_name, errors[ret]))             # <<<<<<<<<<<<<<
+ *     elif ret != 0:
+ *         raise ValueError('Unexpected return code {0} from {1}'
+ */
+    __pyx_t_4 = PyObject_GetAttr(((PyObject *)__pyx_kp_s_3), __pyx_n_s__format); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 57; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_4);
+    __pyx_t_5 = PyObject_GetItem(__pyx_v_errors, __pyx_v_ret); if (!__pyx_t_5) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 57; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_5);
+    __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 57; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(((PyObject *)__pyx_t_3));
+    __Pyx_INCREF(__pyx_v_func_name);
+    PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_func_name);
+    __Pyx_GIVEREF(__pyx_v_func_name);
+    PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_t_5);
+    __Pyx_GIVEREF(__pyx_t_5);
+    __pyx_t_5 = 0;
+    __pyx_t_5 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 57; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_5);
+    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+    __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
+    __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 57; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(((PyObject *)__pyx_t_3));
+    PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_5);
+    __Pyx_GIVEREF(__pyx_t_5);
+    __pyx_t_5 = 0;
+    __pyx_t_5 = PyObject_Call(__pyx_builtin_ValueError, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 57; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_5);
+    __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
+    __Pyx_Raise(__pyx_t_5, 0, 0, 0);
+    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 57; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    goto __pyx_L6;
+  }
+
+  /* "astropy/time/sofa_time.pyx":58
+ *     elif ret in errors:
+ *         raise ValueError('{0}: {1}'.format(func_name, errors[ret]))
+ *     elif ret != 0:             # <<<<<<<<<<<<<<
+ *         raise ValueError('Unexpected return code {0} from {1}'
+ *                          .format(repr(ret), func_name))
+ */
+  __pyx_t_5 = PyObject_RichCompare(__pyx_v_ret, __pyx_int_0, Py_NE); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_1 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  if (__pyx_t_1) {
+
+    /* "astropy/time/sofa_time.pyx":60
+ *     elif ret != 0:
+ *         raise ValueError('Unexpected return code {0} from {1}'
+ *                          .format(repr(ret), func_name))             # <<<<<<<<<<<<<<
+ * 
+ * 
+ */
+    __pyx_t_5 = PyObject_GetAttr(((PyObject *)__pyx_kp_s_4), __pyx_n_s__format); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 60; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_5);
+    __pyx_t_3 = PyObject_Repr(__pyx_v_ret); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 60; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_3);
+    __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 60; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(((PyObject *)__pyx_t_4));
+    PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_3);
+    __Pyx_GIVEREF(__pyx_t_3);
+    __Pyx_INCREF(__pyx_v_func_name);
+    PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_v_func_name);
+    __Pyx_GIVEREF(__pyx_v_func_name);
+    __pyx_t_3 = 0;
+    __pyx_t_3 = PyObject_Call(__pyx_t_5, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 60; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_3);
+    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+    __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
+    __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 59; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(((PyObject *)__pyx_t_4));
+    PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_3);
+    __Pyx_GIVEREF(__pyx_t_3);
+    __pyx_t_3 = 0;
+    __pyx_t_3 = PyObject_Call(__pyx_builtin_ValueError, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 59; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_3);
+    __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
+    __Pyx_Raise(__pyx_t_3, 0, 0, 0);
+    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 59; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    goto __pyx_L6;
+  }
+  __pyx_L6:;
+
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_XDECREF(__pyx_t_5);
+  __Pyx_AddTraceback("astropy.time.sofa_time.check_return", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "astropy/time/sofa_time.pyx":65
+ * @cython.wraparound(False)
+ * @cython.boundscheck(False)
+ * def cal2jd(             # <<<<<<<<<<<<<<
+ *     np.ndarray[int, ndim=1] iy,
+ *     np.ndarray[int, ndim=1] im,
+ */
+
+static PyObject *__pyx_pf_7astropy_4time_9sofa_time_1cal2jd(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_7astropy_4time_9sofa_time_1cal2jd[] = "\n    int iauCal2jd(int iy, int im, int id, double *djm0, double *djm)\n    Calendar date to high-precision JD.\n\n    **  Given:\n    **     iy,im,id  int     year, month, day in Gregorian calendar (Note 1)\n    **\n    **  Returned:\n    **     djm0      double  MJD zero-point: always 2400000.5\n    **     djm       double  Modified Julian Date for 0 hrs\n    **\n    **  Returned (function value):\n    **               int     status:\n    **                           0 = OK\n    **                          -1 = bad year   (Note 3: JD not computed)\n    **                          -2 = bad month  (JD not computed)\n    **                          -3 = bad day    (JD computed)\n    **\n    **  Notes:\n    **\n    **  1) The algorithm used is valid from -4800 March 1, but this\n    **     implementation rejects dates before -4799 January 1.\n    **\n    **  2) The Julian Date is returned in two pieces, in the usual SOFA\n    **     manner, which is designed to preserve time resolution.  The\n    **     Julian Date is available as a single number by adding djm0 and\n    **     djm.\n    **\n    **  3) In early eras the conversion is from the \"Proleptic Gregorian\n    **     Calendar\";  no account is taken of the date(s) of adoption of\n    **     the Gregorian Calendar, nor is the AD/BC numbering convention\n    **     observed.\n    ";
+static PyMethodDef __pyx_mdef_7astropy_4time_9sofa_time_1cal2jd = {__Pyx_NAMESTR("cal2jd"), (PyCFunction)__pyx_pf_7astropy_4time_9sofa_time_1cal2jd, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(__pyx_doc_7astropy_4time_9sofa_time_1cal2jd)};
+static PyObject *__pyx_pf_7astropy_4time_9sofa_time_1cal2jd(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyArrayObject *__pyx_v_iy = 0;
+  PyArrayObject *__pyx_v_im = 0;
+  PyArrayObject *__pyx_v_id = 0;
+  PyArrayObject *__pyx_v_djm0 = 0;
+  PyArrayObject *__pyx_v_djm = 0;
+  unsigned int __pyx_v_i;
+  unsigned int __pyx_v_n;
+  PyObject *__pyx_v_warns = NULL;
+  PyObject *__pyx_v_errs = NULL;
+  int __pyx_v_ret;
+  Py_buffer __pyx_bstruct_iy;
+  Py_ssize_t __pyx_bstride_0_iy = 0;
+  Py_ssize_t __pyx_bshape_0_iy = 0;
+  Py_buffer __pyx_bstruct_djm0;
+  Py_ssize_t __pyx_bstride_0_djm0 = 0;
+  Py_ssize_t __pyx_bshape_0_djm0 = 0;
+  Py_buffer __pyx_bstruct_im;
+  Py_ssize_t __pyx_bstride_0_im = 0;
+  Py_ssize_t __pyx_bshape_0_im = 0;
+  Py_buffer __pyx_bstruct_djm;
+  Py_ssize_t __pyx_bstride_0_djm = 0;
+  Py_ssize_t __pyx_bshape_0_djm = 0;
+  Py_buffer __pyx_bstruct_id;
+  Py_ssize_t __pyx_bstride_0_id = 0;
+  Py_ssize_t __pyx_bshape_0_id = 0;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  unsigned int __pyx_t_2;
+  unsigned int __pyx_t_3;
+  unsigned int __pyx_t_4;
+  unsigned int __pyx_t_5;
+  unsigned int __pyx_t_6;
+  unsigned int __pyx_t_7;
+  unsigned int __pyx_t_8;
+  PyObject *__pyx_t_9 = NULL;
+  PyObject *__pyx_t_10 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__iy,&__pyx_n_s__im,&__pyx_n_s__id,&__pyx_n_s__djm0,&__pyx_n_s__djm,0};
+  __Pyx_RefNannySetupContext("cal2jd");
+  __pyx_self = __pyx_self;
+  {
+    PyObject* values[5] = {0,0,0,0,0};
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  5: values[4] = PyTuple_GET_ITEM(__pyx_args, 4);
+        case  4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
+        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  0:
+        values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__iy);
+        if (likely(values[0])) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+        case  1:
+        values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__im);
+        if (likely(values[1])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("cal2jd", 1, 5, 5, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 65; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+        case  2:
+        values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__id);
+        if (likely(values[2])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("cal2jd", 1, 5, 5, 2); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 65; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+        case  3:
+        values[3] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__djm0);
+        if (likely(values[3])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("cal2jd", 1, 5, 5, 3); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 65; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+        case  4:
+        values[4] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__djm);
+        if (likely(values[4])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("cal2jd", 1, 5, 5, 4); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 65; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "cal2jd") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 65; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+    } else if (PyTuple_GET_SIZE(__pyx_args) != 5) {
+      goto __pyx_L5_argtuple_error;
+    } else {
+      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+      values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+      values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
+      values[4] = PyTuple_GET_ITEM(__pyx_args, 4);
+    }
+    __pyx_v_iy = ((PyArrayObject *)values[0]);
+    __pyx_v_im = ((PyArrayObject *)values[1]);
+    __pyx_v_id = ((PyArrayObject *)values[2]);
+    __pyx_v_djm0 = ((PyArrayObject *)values[3]);
+    __pyx_v_djm = ((PyArrayObject *)values[4]);
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("cal2jd", 1, 5, 5, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 65; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("astropy.time.sofa_time.cal2jd", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_bstruct_iy.buf = NULL;
+  __pyx_bstruct_im.buf = NULL;
+  __pyx_bstruct_id.buf = NULL;
+  __pyx_bstruct_djm0.buf = NULL;
+  __pyx_bstruct_djm.buf = NULL;
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_iy), __pyx_ptype_5numpy_ndarray, 1, "iy", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 66; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_im), __pyx_ptype_5numpy_ndarray, 1, "im", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 67; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_id), __pyx_ptype_5numpy_ndarray, 1, "id", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 68; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_djm0), __pyx_ptype_5numpy_ndarray, 1, "djm0", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 69; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_djm), __pyx_ptype_5numpy_ndarray, 1, "djm", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 70; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_iy, (PyObject*)__pyx_v_iy, &__Pyx_TypeInfo_int, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 65; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_iy = __pyx_bstruct_iy.strides[0];
+  __pyx_bshape_0_iy = __pyx_bstruct_iy.shape[0];
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_im, (PyObject*)__pyx_v_im, &__Pyx_TypeInfo_int, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 65; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_im = __pyx_bstruct_im.strides[0];
+  __pyx_bshape_0_im = __pyx_bstruct_im.shape[0];
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_id, (PyObject*)__pyx_v_id, &__Pyx_TypeInfo_int, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 65; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_id = __pyx_bstruct_id.strides[0];
+  __pyx_bshape_0_id = __pyx_bstruct_id.shape[0];
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_djm0, (PyObject*)__pyx_v_djm0, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 65; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_djm0 = __pyx_bstruct_djm0.strides[0];
+  __pyx_bshape_0_djm0 = __pyx_bstruct_djm0.shape[0];
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_djm, (PyObject*)__pyx_v_djm, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 65; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_djm = __pyx_bstruct_djm.strides[0];
+  __pyx_bshape_0_djm = __pyx_bstruct_djm.shape[0];
+
+  /* "astropy/time/sofa_time.pyx":105
+ *     """
+ *     cdef unsigned int i
+ *     cdef unsigned n = iy.shape[0]             # <<<<<<<<<<<<<<
+ *     warns = {-3: 'Bad input day (JD still computed)'}
+ *     errs = {-1: 'Bad input year',
+ */
+  __pyx_v_n = (__pyx_v_iy->dimensions[0]);
+
+  /* "astropy/time/sofa_time.pyx":106
+ *     cdef unsigned int i
+ *     cdef unsigned n = iy.shape[0]
+ *     warns = {-3: 'Bad input day (JD still computed)'}             # <<<<<<<<<<<<<<
+ *     errs = {-1: 'Bad input year',
+ *              -2: 'Bad input month'}
+ */
+  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 106; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_1));
+  if (PyDict_SetItem(__pyx_t_1, __pyx_int_neg_3, ((PyObject *)__pyx_kp_s_5)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 106; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_v_warns = __pyx_t_1;
+  __pyx_t_1 = 0;
+
+  /* "astropy/time/sofa_time.pyx":107
+ *     cdef unsigned n = iy.shape[0]
+ *     warns = {-3: 'Bad input day (JD still computed)'}
+ *     errs = {-1: 'Bad input year',             # <<<<<<<<<<<<<<
+ *              -2: 'Bad input month'}
+ *     for i in range(n):
+ */
+  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 107; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_1));
+  if (PyDict_SetItem(__pyx_t_1, __pyx_int_neg_1, ((PyObject *)__pyx_kp_s_6)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 107; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyDict_SetItem(__pyx_t_1, __pyx_int_neg_2, ((PyObject *)__pyx_kp_s_7)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 107; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_v_errs = __pyx_t_1;
+  __pyx_t_1 = 0;
+
+  /* "astropy/time/sofa_time.pyx":109
+ *     errs = {-1: 'Bad input year',
+ *              -2: 'Bad input month'}
+ *     for i in range(n):             # <<<<<<<<<<<<<<
+ *         ret = iauCal2jd( iy[i], im[i], id[i], &djm0[i], &djm[i])
+ *         check_return(ret, 'iauCal2jd', warns, errs)
+ */
+  __pyx_t_2 = __pyx_v_n;
+  for (__pyx_t_3 = 0; __pyx_t_3 < __pyx_t_2; __pyx_t_3+=1) {
+    __pyx_v_i = __pyx_t_3;
+
+    /* "astropy/time/sofa_time.pyx":110
+ *              -2: 'Bad input month'}
+ *     for i in range(n):
+ *         ret = iauCal2jd( iy[i], im[i], id[i], &djm0[i], &djm[i])             # <<<<<<<<<<<<<<
+ *         check_return(ret, 'iauCal2jd', warns, errs)
+ *     return
+ */
+    __pyx_t_4 = __pyx_v_i;
+    __pyx_t_5 = __pyx_v_i;
+    __pyx_t_6 = __pyx_v_i;
+    __pyx_t_7 = __pyx_v_i;
+    __pyx_t_8 = __pyx_v_i;
+    __pyx_v_ret = iauCal2jd((*__Pyx_BufPtrStrided1d(int *, __pyx_bstruct_iy.buf, __pyx_t_4, __pyx_bstride_0_iy)), (*__Pyx_BufPtrStrided1d(int *, __pyx_bstruct_im.buf, __pyx_t_5, __pyx_bstride_0_im)), (*__Pyx_BufPtrStrided1d(int *, __pyx_bstruct_id.buf, __pyx_t_6, __pyx_bstride_0_id)), (&(*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_djm0.buf, __pyx_t_7, __pyx_bstride_0_djm0))), (&(*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_djm.buf, __pyx_t_8, __pyx_bstride_0_djm))));
+
+    /* "astropy/time/sofa_time.pyx":111
+ *     for i in range(n):
+ *         ret = iauCal2jd( iy[i], im[i], id[i], &djm0[i], &djm[i])
+ *         check_return(ret, 'iauCal2jd', warns, errs)             # <<<<<<<<<<<<<<
+ *     return
+ * 
+ */
+    __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__check_return); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 111; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_1);
+    __pyx_t_9 = PyInt_FromLong(__pyx_v_ret); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 111; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_9);
+    __pyx_t_10 = PyTuple_New(4); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 111; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(((PyObject *)__pyx_t_10));
+    PyTuple_SET_ITEM(__pyx_t_10, 0, __pyx_t_9);
+    __Pyx_GIVEREF(__pyx_t_9);
+    __Pyx_INCREF(((PyObject *)__pyx_n_s__iauCal2jd));
+    PyTuple_SET_ITEM(__pyx_t_10, 1, ((PyObject *)__pyx_n_s__iauCal2jd));
+    __Pyx_GIVEREF(((PyObject *)__pyx_n_s__iauCal2jd));
+    __Pyx_INCREF(((PyObject *)__pyx_v_warns));
+    PyTuple_SET_ITEM(__pyx_t_10, 2, ((PyObject *)__pyx_v_warns));
+    __Pyx_GIVEREF(((PyObject *)__pyx_v_warns));
+    __Pyx_INCREF(((PyObject *)__pyx_v_errs));
+    PyTuple_SET_ITEM(__pyx_t_10, 3, ((PyObject *)__pyx_v_errs));
+    __Pyx_GIVEREF(((PyObject *)__pyx_v_errs));
+    __pyx_t_9 = 0;
+    __pyx_t_9 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_10), NULL); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 111; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_9);
+    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    __Pyx_DECREF(((PyObject *)__pyx_t_10)); __pyx_t_10 = 0;
+    __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
+  }
+
+  /* "astropy/time/sofa_time.pyx":112
+ *         ret = iauCal2jd( iy[i], im[i], id[i], &djm0[i], &djm[i])
+ *         check_return(ret, 'iauCal2jd', warns, errs)
+ *     return             # <<<<<<<<<<<<<<
+ * 
+ * @cython.wraparound(False)
+ */
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_9);
+  __Pyx_XDECREF(__pyx_t_10);
+  { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;
+    __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_iy);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_djm0);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_im);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_djm);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_id);
+  __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
+  __Pyx_AddTraceback("astropy.time.sofa_time.cal2jd", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  goto __pyx_L2;
+  __pyx_L0:;
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_iy);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_djm0);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_im);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_djm);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_id);
+  __pyx_L2:;
+  __Pyx_XDECREF(__pyx_v_warns);
+  __Pyx_XDECREF(__pyx_v_errs);
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "astropy/time/sofa_time.pyx":116
+ * @cython.wraparound(False)
+ * @cython.boundscheck(False)
+ * def d_tai_utc(np.ndarray[int, ndim=1] iy,             # <<<<<<<<<<<<<<
+ *               np.ndarray[int, ndim=1] im,
+ *               np.ndarray[int, ndim=1] id,
+ */
+
+static PyObject *__pyx_pf_7astropy_4time_9sofa_time_2d_tai_utc(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_7astropy_4time_9sofa_time_2d_tai_utc[] = "\n    int iauDat(int iy, int im, int id, double fd, double *deltat)\n    For a given UTC date, calculate delta(AT) = TAI-UTC.\n\n    **  Given:\n    **     iy     int      UTC:  year (Notes 1 and 2)\n    **     im     int            month (Note 2)\n    **     id     int            day (Notes 2 and 3)\n    **     fd     double         fraction of day (Note 4)\n    **\n    **  Returned:\n    **     deltat double   TAI minus UTC, seconds\n    **\n    **  Returned (function value):\n    **            int      status (Note 5):\n    **                       1 = dubious year (Note 1)\n    **                       0 = OK\n    **                      -1 = bad year\n    **                      -2 = bad month\n    **                      -3 = bad day (Note 3)\n    **                      -4 = bad fraction (Note 4)\n    **\n    **  Notes:\n    **\n    **  1) UTC began at 1960 January 1.0 (JD 2436934.5) and it is improper\n    **     to call the function with an earlier date.  If this is attempted,\n    **     zero is returned together with a warning status.\n    **\n    **     Because leap seconds cannot, in principle, be predicted in\n    **     advance, a reliable check for dates beyond the valid range is\n    **     impossible.  To guard against gross errors, a year five or more\n    **     after the release year of the present function (see parameter\n    **     IYV) is considered dubious.  In this case a warning status is\n    **     returned but the result is computed in the normal way.\n    **\n    **     For both too-early and too-late years, the warning status is\n    **     j=+1.  This is distinct from the error status j=-1, which\n    **     signifies a year so early that JD could not be computed.\n    **\n    **  2) If the specified date is for a day which ends with a leap second,\n    **     the UTC-TAI value returned is for the period leading up to the\n    **     leap second.  If the date is for a day which begins as a leap\n    **     second ends, the UTC-TAI re""turned is for the period following the\n    **     leap second.\n    **\n    **  3) The day number must be in the normal calendar range, for example\n    **     1 through 30 for April.  The \"almanac\" convention of allowing\n    **     such dates as January 0 and December 32 is not supported in this\n    **     function, in order to avoid confusion near leap seconds.\n    **\n    **  4) The fraction of day is used only for dates before the\n    **     introduction of leap seconds, the first of which occurred at the\n    **     end of 1971.  It is tested for validity (zero to less than 1 is\n    **     the valid range) even if not used;  if invalid, zero is used and\n    **     status j=-4 is returned.  For many applications, setting fd to\n    **     zero is acceptable;  the resulting error is always less than 3 ms\n    **     (and occurs only pre-1972).\n    **\n    **  5) The status value returned in the case where there are multiple\n    **     errors refers to the first error detected.  For example, if the\n    **     month and day are 13 and 32 respectively, j=-2 (bad month)\n    **     will be returned.\n    **\n    **  6) In cases where a valid result is not available, zero is returned.\n\n    **                       1 = dubious year (Note 1)\n    **                       0 = OK\n    **                      -1 = bad year\n    **                      -2 = bad month\n    **                      -3 = bad day (Note 3)\n    **                      -4 = bad fraction (Note 4)\n\n    ";
+static PyMethodDef __pyx_mdef_7astropy_4time_9sofa_time_2d_tai_utc = {__Pyx_NAMESTR("d_tai_utc"), (PyCFunction)__pyx_pf_7astropy_4time_9sofa_time_2d_tai_utc, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(__pyx_doc_7astropy_4time_9sofa_time_2d_tai_utc)};
+static PyObject *__pyx_pf_7astropy_4time_9sofa_time_2d_tai_utc(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyArrayObject *__pyx_v_iy = 0;
+  PyArrayObject *__pyx_v_im = 0;
+  PyArrayObject *__pyx_v_id = 0;
+  PyArrayObject *__pyx_v_fd = 0;
+  int __pyx_v_i;
+  int __pyx_v_n;
+  PyArrayObject *__pyx_v_out = 0;
+  PyObject *__pyx_v_warns = NULL;
+  PyObject *__pyx_v_errs = NULL;
+  int __pyx_v_ret;
+  Py_buffer __pyx_bstruct_iy;
+  Py_ssize_t __pyx_bstride_0_iy = 0;
+  Py_ssize_t __pyx_bshape_0_iy = 0;
+  Py_buffer __pyx_bstruct_fd;
+  Py_ssize_t __pyx_bstride_0_fd = 0;
+  Py_ssize_t __pyx_bshape_0_fd = 0;
+  Py_buffer __pyx_bstruct_im;
+  Py_ssize_t __pyx_bstride_0_im = 0;
+  Py_ssize_t __pyx_bshape_0_im = 0;
+  Py_buffer __pyx_bstruct_id;
+  Py_ssize_t __pyx_bstride_0_id = 0;
+  Py_ssize_t __pyx_bshape_0_id = 0;
+  Py_buffer __pyx_bstruct_out;
+  Py_ssize_t __pyx_bstride_0_out = 0;
+  Py_ssize_t __pyx_bshape_0_out = 0;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  int __pyx_t_1;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
+  PyObject *__pyx_t_5 = NULL;
+  PyObject *__pyx_t_6 = NULL;
+  PyArrayObject *__pyx_t_7 = NULL;
+  int __pyx_t_8;
+  int __pyx_t_9;
+  int __pyx_t_10;
+  int __pyx_t_11;
+  int __pyx_t_12;
+  int __pyx_t_13;
+  int __pyx_t_14;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__iy,&__pyx_n_s__im,&__pyx_n_s__id,&__pyx_n_s__fd,0};
+  __Pyx_RefNannySetupContext("d_tai_utc");
+  __pyx_self = __pyx_self;
+  {
+    PyObject* values[4] = {0,0,0,0};
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
+        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  0:
+        values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__iy);
+        if (likely(values[0])) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+        case  1:
+        values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__im);
+        if (likely(values[1])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("d_tai_utc", 1, 4, 4, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+        case  2:
+        values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__id);
+        if (likely(values[2])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("d_tai_utc", 1, 4, 4, 2); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+        case  3:
+        values[3] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__fd);
+        if (likely(values[3])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("d_tai_utc", 1, 4, 4, 3); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "d_tai_utc") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+    } else if (PyTuple_GET_SIZE(__pyx_args) != 4) {
+      goto __pyx_L5_argtuple_error;
+    } else {
+      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+      values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+      values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
+    }
+    __pyx_v_iy = ((PyArrayObject *)values[0]);
+    __pyx_v_im = ((PyArrayObject *)values[1]);
+    __pyx_v_id = ((PyArrayObject *)values[2]);
+    __pyx_v_fd = ((PyArrayObject *)values[3]);
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("d_tai_utc", 1, 4, 4, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("astropy.time.sofa_time.d_tai_utc", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_bstruct_out.buf = NULL;
+  __pyx_bstruct_iy.buf = NULL;
+  __pyx_bstruct_im.buf = NULL;
+  __pyx_bstruct_id.buf = NULL;
+  __pyx_bstruct_fd.buf = NULL;
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_iy), __pyx_ptype_5numpy_ndarray, 1, "iy", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_im), __pyx_ptype_5numpy_ndarray, 1, "im", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 117; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_id), __pyx_ptype_5numpy_ndarray, 1, "id", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 118; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_fd), __pyx_ptype_5numpy_ndarray, 1, "fd", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 119; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_iy, (PyObject*)__pyx_v_iy, &__Pyx_TypeInfo_int, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_iy = __pyx_bstruct_iy.strides[0];
+  __pyx_bshape_0_iy = __pyx_bstruct_iy.shape[0];
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_im, (PyObject*)__pyx_v_im, &__Pyx_TypeInfo_int, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_im = __pyx_bstruct_im.strides[0];
+  __pyx_bshape_0_im = __pyx_bstruct_im.shape[0];
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_id, (PyObject*)__pyx_v_id, &__Pyx_TypeInfo_int, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_id = __pyx_bstruct_id.strides[0];
+  __pyx_bshape_0_id = __pyx_bstruct_id.shape[0];
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_fd, (PyObject*)__pyx_v_fd, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_fd = __pyx_bstruct_fd.strides[0];
+  __pyx_bshape_0_fd = __pyx_bstruct_fd.shape[0];
+
+  /* "astropy/time/sofa_time.pyx":194
+ *     """
+ *     cdef int i
+ *     cdef int n = iy.shape[0]             # <<<<<<<<<<<<<<
+ *     assert (iy.shape[0] == im.shape[0] == id.shape[0] == fd.shape[0])
+ * 
+ */
+  __pyx_v_n = (__pyx_v_iy->dimensions[0]);
+
+  /* "astropy/time/sofa_time.pyx":195
+ *     cdef int i
+ *     cdef int n = iy.shape[0]
+ *     assert (iy.shape[0] == im.shape[0] == id.shape[0] == fd.shape[0])             # <<<<<<<<<<<<<<
+ * 
+ *     cdef np.ndarray[double, ndim=1] out = np.empty(n, dtype=np.double)
+ */
+  #ifndef CYTHON_WITHOUT_ASSERTIONS
+  __pyx_t_1 = ((__pyx_v_iy->dimensions[0]) == (__pyx_v_im->dimensions[0]));
+  if (__pyx_t_1) {
+    __pyx_t_1 = ((__pyx_v_im->dimensions[0]) == (__pyx_v_id->dimensions[0]));
+    if (__pyx_t_1) {
+      __pyx_t_1 = ((__pyx_v_id->dimensions[0]) == (__pyx_v_fd->dimensions[0]));
+    }
+  }
+  if (unlikely(!__pyx_t_1)) {
+    PyErr_SetNone(PyExc_AssertionError);
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 195; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  #endif
+
+  /* "astropy/time/sofa_time.pyx":197
+ *     assert (iy.shape[0] == im.shape[0] == id.shape[0] == fd.shape[0])
+ * 
+ *     cdef np.ndarray[double, ndim=1] out = np.empty(n, dtype=np.double)             # <<<<<<<<<<<<<<
+ * 
+ *     warns = {1: DUBIOUS}
+ */
+  __pyx_t_2 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 197; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_3 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s__empty); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 197; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __pyx_t_2 = PyInt_FromLong(__pyx_v_n); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 197; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 197; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_4));
+  PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_2);
+  __Pyx_GIVEREF(__pyx_t_2);
+  __pyx_t_2 = 0;
+  __pyx_t_2 = PyDict_New(); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 197; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_2));
+  __pyx_t_5 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 197; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __pyx_t_6 = PyObject_GetAttr(__pyx_t_5, __pyx_n_s__double); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 197; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_6);
+  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  if (PyDict_SetItem(__pyx_t_2, ((PyObject *)__pyx_n_s__dtype), __pyx_t_6) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 197; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+  __pyx_t_6 = PyEval_CallObjectWithKeywords(__pyx_t_3, ((PyObject *)__pyx_t_4), ((PyObject *)__pyx_t_2)); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 197; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_6);
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
+  if (!(likely(((__pyx_t_6) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_6, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 197; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_7 = ((PyArrayObject *)__pyx_t_6);
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_out, (PyObject*)__pyx_t_7, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {
+      __pyx_v_out = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_out.buf = NULL;
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 197; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    } else {__pyx_bstride_0_out = __pyx_bstruct_out.strides[0];
+      __pyx_bshape_0_out = __pyx_bstruct_out.shape[0];
+    }
+  }
+  __pyx_t_7 = 0;
+  __pyx_v_out = ((PyArrayObject *)__pyx_t_6);
+  __pyx_t_6 = 0;
+
+  /* "astropy/time/sofa_time.pyx":199
+ *     cdef np.ndarray[double, ndim=1] out = np.empty(n, dtype=np.double)
+ * 
+ *     warns = {1: DUBIOUS}             # <<<<<<<<<<<<<<
+ *     errs = {-1: 'bad year',
+ *              -2: 'bad month (must be 1 to 12)',
+ */
+  __pyx_t_6 = PyDict_New(); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 199; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_6));
+  __pyx_t_2 = __Pyx_GetName(__pyx_m, __pyx_n_s__DUBIOUS); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 199; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  if (PyDict_SetItem(__pyx_t_6, __pyx_int_1, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 199; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __pyx_v_warns = __pyx_t_6;
+  __pyx_t_6 = 0;
+
+  /* "astropy/time/sofa_time.pyx":200
+ * 
+ *     warns = {1: DUBIOUS}
+ *     errs = {-1: 'bad year',             # <<<<<<<<<<<<<<
+ *              -2: 'bad month (must be 1 to 12)',
+ *              -3: 'bad day (must be within normal calendar date for a month)',
+ */
+  __pyx_t_6 = PyDict_New(); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 200; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_6));
+  if (PyDict_SetItem(__pyx_t_6, __pyx_int_neg_1, ((PyObject *)__pyx_kp_s_8)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 200; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyDict_SetItem(__pyx_t_6, __pyx_int_neg_2, ((PyObject *)__pyx_kp_s_9)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 200; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyDict_SetItem(__pyx_t_6, __pyx_int_neg_3, ((PyObject *)__pyx_kp_s_10)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 200; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyDict_SetItem(__pyx_t_6, __pyx_int_neg_4, ((PyObject *)__pyx_kp_s_11)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 200; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_v_errs = __pyx_t_6;
+  __pyx_t_6 = 0;
+
+  /* "astropy/time/sofa_time.pyx":204
+ *              -3: 'bad day (must be within normal calendar date for a month)',
+ *              -4: 'bad fraction of day'}
+ *     for i in range(n):             # <<<<<<<<<<<<<<
+ *         ret = iauDat(iy[i], im[i], id[i], fd[i],
+ *                      &out[i])
+ */
+  __pyx_t_8 = __pyx_v_n;
+  for (__pyx_t_9 = 0; __pyx_t_9 < __pyx_t_8; __pyx_t_9+=1) {
+    __pyx_v_i = __pyx_t_9;
+
+    /* "astropy/time/sofa_time.pyx":205
+ *              -4: 'bad fraction of day'}
+ *     for i in range(n):
+ *         ret = iauDat(iy[i], im[i], id[i], fd[i],             # <<<<<<<<<<<<<<
+ *                      &out[i])
+ *         check_return(ret, 'iauDat', warns, errs)
+ */
+    __pyx_t_10 = __pyx_v_i;
+    __pyx_t_11 = __pyx_v_i;
+    __pyx_t_12 = __pyx_v_i;
+    __pyx_t_13 = __pyx_v_i;
+
+    /* "astropy/time/sofa_time.pyx":206
+ *     for i in range(n):
+ *         ret = iauDat(iy[i], im[i], id[i], fd[i],
+ *                      &out[i])             # <<<<<<<<<<<<<<
+ *         check_return(ret, 'iauDat', warns, errs)
+ * 
+ */
+    __pyx_t_14 = __pyx_v_i;
+    __pyx_v_ret = iauDat((*__Pyx_BufPtrStrided1d(int *, __pyx_bstruct_iy.buf, __pyx_t_10, __pyx_bstride_0_iy)), (*__Pyx_BufPtrStrided1d(int *, __pyx_bstruct_im.buf, __pyx_t_11, __pyx_bstride_0_im)), (*__Pyx_BufPtrStrided1d(int *, __pyx_bstruct_id.buf, __pyx_t_12, __pyx_bstride_0_id)), (*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_fd.buf, __pyx_t_13, __pyx_bstride_0_fd)), (&(*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_out.buf, __pyx_t_14, __pyx_bstride_0_out))));
+
+    /* "astropy/time/sofa_time.pyx":207
+ *         ret = iauDat(iy[i], im[i], id[i], fd[i],
+ *                      &out[i])
+ *         check_return(ret, 'iauDat', warns, errs)             # <<<<<<<<<<<<<<
+ * 
+ *     return out
+ */
+    __pyx_t_6 = __Pyx_GetName(__pyx_m, __pyx_n_s__check_return); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 207; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_6);
+    __pyx_t_2 = PyInt_FromLong(__pyx_v_ret); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 207; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_2);
+    __pyx_t_4 = PyTuple_New(4); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 207; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(((PyObject *)__pyx_t_4));
+    PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_2);
+    __Pyx_GIVEREF(__pyx_t_2);
+    __Pyx_INCREF(((PyObject *)__pyx_n_s__iauDat));
+    PyTuple_SET_ITEM(__pyx_t_4, 1, ((PyObject *)__pyx_n_s__iauDat));
+    __Pyx_GIVEREF(((PyObject *)__pyx_n_s__iauDat));
+    __Pyx_INCREF(((PyObject *)__pyx_v_warns));
+    PyTuple_SET_ITEM(__pyx_t_4, 2, ((PyObject *)__pyx_v_warns));
+    __Pyx_GIVEREF(((PyObject *)__pyx_v_warns));
+    __Pyx_INCREF(((PyObject *)__pyx_v_errs));
+    PyTuple_SET_ITEM(__pyx_t_4, 3, ((PyObject *)__pyx_v_errs));
+    __Pyx_GIVEREF(((PyObject *)__pyx_v_errs));
+    __pyx_t_2 = 0;
+    __pyx_t_2 = PyObject_Call(__pyx_t_6, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 207; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_2);
+    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+    __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
+    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  }
+
+  /* "astropy/time/sofa_time.pyx":209
+ *         check_return(ret, 'iauDat', warns, errs)
+ * 
+ *     return out             # <<<<<<<<<<<<<<
+ * 
+ * 
+ */
+  __Pyx_XDECREF(__pyx_r);
+  __Pyx_INCREF(((PyObject *)__pyx_v_out));
+  __pyx_r = ((PyObject *)__pyx_v_out);
+  goto __pyx_L0;
+
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_XDECREF(__pyx_t_5);
+  __Pyx_XDECREF(__pyx_t_6);
+  { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;
+    __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_iy);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_fd);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_im);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_id);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out);
+  __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
+  __Pyx_AddTraceback("astropy.time.sofa_time.d_tai_utc", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  goto __pyx_L2;
+  __pyx_L0:;
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_iy);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_fd);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_im);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_id);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out);
+  __pyx_L2:;
+  __Pyx_XDECREF((PyObject *)__pyx_v_out);
+  __Pyx_XDECREF(__pyx_v_warns);
+  __Pyx_XDECREF(__pyx_v_errs);
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "astropy/time/sofa_time.pyx":214
+ * @cython.wraparound(False)
+ * @cython.boundscheck(False)
+ * def jd_dtf(scale, ndp,             # <<<<<<<<<<<<<<
+ *               np.ndarray[double, ndim=1] d1,
+ *               np.ndarray[double, ndim=1] d2):
+ */
+
+static PyObject *__pyx_pf_7astropy_4time_9sofa_time_3jd_dtf(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_7astropy_4time_9sofa_time_3jd_dtf[] = "\n    int iauD2dtf(const char *scale, int ndp, double d1, double d2,\n             int *iy, int *im, int *id, int ihmsf[4])\n\n    **  Given:\n    **     scale     char[]  time scale ID (Note 1)\n    **     ndp       int     resolution (Note 2)\n    **     d1,d2     double  time as a 2-part Julian Date (Notes 3,4)\n    **\n    **  Returned:\n    **     iy,im,id  int     year, month, day in Gregorian calendar (Note 5)\n    **     ihmsf     int[4]  hours, minutes, seconds, fraction (Note 1)\n    **\n    **  Returned (function value):\n    **               int     status: +1 = dubious year (Note 5)\n    **                                0 = OK\n    **                               -1 = unacceptable date (Note 6)\n    **\n    **  Notes:\n    **\n    **  1) scale identifies the time scale.  Only the value \"UTC\" (in upper\n    **     case) is significant, and enables handling of leap seconds (see\n    **     Note 4).\n    **\n    **  2) ndp is the number of decimal places in the seconds field, and can\n    **     have negative as well as positive values, such as:\n    **\n    **     ndp         resolution\n    **     -4            1 00 00\n    **     -3            0 10 00\n    **     -2            0 01 00\n    **     -1            0 00 10\n    **      0            0 00 01\n    **      1            0 00 00.1\n    **      2            0 00 00.01\n    **      3            0 00 00.001\n    **\n    **     The limits are platform dependent, but a safe range is -5 to +9.\n    **\n    **  3) d1+d2 is Julian Date, apportioned in any convenient way between\n    **     the two arguments, for example where d1 is the Julian Day Number\n    **     and d2 is the fraction of a day.  In the case of UTC, where the\n    **     use of JD is problematical, special conventions apply:  see the\n    **     next note.\n    **\n    **  4) JD cannot unambiguously represent UTC during a leap second unless\n    **     special measures are taken.  The SOFA internal convention is that\n    **     the"" quasi-JD day represents UTC days whether the length is 86399,\n    **     86400 or 86401 SI seconds.\n    **\n    **  5) The warning status \"dubious year\" flags UTCs that predate the\n    **     introduction of the time scale and that are too far in the future\n    **     to be trusted.  See iauDat for further details.\n    **\n    **  6) For calendar conventions and limitations, see iauCal2jd.\n    ";
+static PyMethodDef __pyx_mdef_7astropy_4time_9sofa_time_3jd_dtf = {__Pyx_NAMESTR("jd_dtf"), (PyCFunction)__pyx_pf_7astropy_4time_9sofa_time_3jd_dtf, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(__pyx_doc_7astropy_4time_9sofa_time_3jd_dtf)};
+static PyObject *__pyx_pf_7astropy_4time_9sofa_time_3jd_dtf(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyObject *__pyx_v_scale = 0;
+  PyObject *__pyx_v_ndp = 0;
+  PyArrayObject *__pyx_v_d1 = 0;
+  PyArrayObject *__pyx_v_d2 = 0;
+  int __pyx_v_i;
+  int __pyx_v_n;
+  PyArrayObject *__pyx_v_iy = 0;
+  PyArrayObject *__pyx_v_im = 0;
+  PyArrayObject *__pyx_v_id = 0;
+  PyArrayObject *__pyx_v_ihmsf = 0;
+  PyObject *__pyx_v_warns = NULL;
+  PyObject *__pyx_v_errs = NULL;
+  int __pyx_v_ret;
+  Py_buffer __pyx_bstruct_iy;
+  Py_ssize_t __pyx_bstride_0_iy = 0;
+  Py_ssize_t __pyx_bshape_0_iy = 0;
+  Py_buffer __pyx_bstruct_ihmsf;
+  Py_ssize_t __pyx_bstride_0_ihmsf = 0;
+  Py_ssize_t __pyx_bstride_1_ihmsf = 0;
+  Py_ssize_t __pyx_bshape_0_ihmsf = 0;
+  Py_ssize_t __pyx_bshape_1_ihmsf = 0;
+  Py_buffer __pyx_bstruct_im;
+  Py_ssize_t __pyx_bstride_0_im = 0;
+  Py_ssize_t __pyx_bshape_0_im = 0;
+  Py_buffer __pyx_bstruct_d2;
+  Py_ssize_t __pyx_bstride_0_d2 = 0;
+  Py_ssize_t __pyx_bshape_0_d2 = 0;
+  Py_buffer __pyx_bstruct_id;
+  Py_ssize_t __pyx_bstride_0_id = 0;
+  Py_ssize_t __pyx_bshape_0_id = 0;
+  Py_buffer __pyx_bstruct_d1;
+  Py_ssize_t __pyx_bstride_0_d1 = 0;
+  Py_ssize_t __pyx_bshape_0_d1 = 0;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
+  PyObject *__pyx_t_5 = NULL;
+  PyArrayObject *__pyx_t_6 = NULL;
+  PyArrayObject *__pyx_t_7 = NULL;
+  PyArrayObject *__pyx_t_8 = NULL;
+  PyArrayObject *__pyx_t_9 = NULL;
+  int __pyx_t_10;
+  int __pyx_t_11;
+  char *__pyx_t_12;
+  int __pyx_t_13;
+  int __pyx_t_14;
+  int __pyx_t_15;
+  int __pyx_t_16;
+  int __pyx_t_17;
+  int __pyx_t_18;
+  int __pyx_t_19;
+  long __pyx_t_20;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__scale,&__pyx_n_s__ndp,&__pyx_n_s__d1,&__pyx_n_s__d2,0};
+  __Pyx_RefNannySetupContext("jd_dtf");
+  __pyx_self = __pyx_self;
+  {
+    PyObject* values[4] = {0,0,0,0};
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
+        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  0:
+        values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__scale);
+        if (likely(values[0])) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+        case  1:
+        values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__ndp);
+        if (likely(values[1])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("jd_dtf", 1, 4, 4, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 214; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+        case  2:
+        values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__d1);
+        if (likely(values[2])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("jd_dtf", 1, 4, 4, 2); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 214; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+        case  3:
+        values[3] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__d2);
+        if (likely(values[3])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("jd_dtf", 1, 4, 4, 3); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 214; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "jd_dtf") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 214; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+    } else if (PyTuple_GET_SIZE(__pyx_args) != 4) {
+      goto __pyx_L5_argtuple_error;
+    } else {
+      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+      values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+      values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
+    }
+    __pyx_v_scale = values[0];
+    __pyx_v_ndp = values[1];
+    __pyx_v_d1 = ((PyArrayObject *)values[2]);
+    __pyx_v_d2 = ((PyArrayObject *)values[3]);
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("jd_dtf", 1, 4, 4, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 214; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("astropy.time.sofa_time.jd_dtf", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_bstruct_iy.buf = NULL;
+  __pyx_bstruct_im.buf = NULL;
+  __pyx_bstruct_id.buf = NULL;
+  __pyx_bstruct_ihmsf.buf = NULL;
+  __pyx_bstruct_d1.buf = NULL;
+  __pyx_bstruct_d2.buf = NULL;
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_d1), __pyx_ptype_5numpy_ndarray, 1, "d1", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 215; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_d2), __pyx_ptype_5numpy_ndarray, 1, "d2", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 216; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_d1, (PyObject*)__pyx_v_d1, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 214; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_d1 = __pyx_bstruct_d1.strides[0];
+  __pyx_bshape_0_d1 = __pyx_bstruct_d1.shape[0];
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_d2, (PyObject*)__pyx_v_d2, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 214; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_d2 = __pyx_bstruct_d2.strides[0];
+  __pyx_bshape_0_d2 = __pyx_bstruct_d2.shape[0];
+
+  /* "astropy/time/sofa_time.pyx":274
+ *     """
+ *     cdef int i
+ *     cdef int n = d1.shape[0]             # <<<<<<<<<<<<<<
+ * 
+ *     cdef np.ndarray[int, ndim=1] iy = np.empty(n, dtype=np.intc)
+ */
+  __pyx_v_n = (__pyx_v_d1->dimensions[0]);
+
+  /* "astropy/time/sofa_time.pyx":276
+ *     cdef int n = d1.shape[0]
+ * 
+ *     cdef np.ndarray[int, ndim=1] iy = np.empty(n, dtype=np.intc)             # <<<<<<<<<<<<<<
+ *     cdef np.ndarray[int, ndim=1] im = np.empty(n, dtype=np.intc)
+ *     cdef np.ndarray[int, ndim=1] id = np.empty(n, dtype=np.intc)
+ */
+  __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 276; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_2 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s__empty); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 276; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __pyx_t_1 = PyInt_FromLong(__pyx_v_n); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 276; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 276; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_3));
+  PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_1);
+  __Pyx_GIVEREF(__pyx_t_1);
+  __pyx_t_1 = 0;
+  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 276; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_1));
+  __pyx_t_4 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 276; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_4);
+  __pyx_t_5 = PyObject_GetAttr(__pyx_t_4, __pyx_n_s__intc); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 276; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_n_s__dtype), __pyx_t_5) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 276; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  __pyx_t_5 = PyEval_CallObjectWithKeywords(__pyx_t_2, ((PyObject *)__pyx_t_3), ((PyObject *)__pyx_t_1)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 276; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
+  if (!(likely(((__pyx_t_5) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_5, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 276; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_6 = ((PyArrayObject *)__pyx_t_5);
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_iy, (PyObject*)__pyx_t_6, &__Pyx_TypeInfo_int, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {
+      __pyx_v_iy = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_iy.buf = NULL;
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 276; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    } else {__pyx_bstride_0_iy = __pyx_bstruct_iy.strides[0];
+      __pyx_bshape_0_iy = __pyx_bstruct_iy.shape[0];
+    }
+  }
+  __pyx_t_6 = 0;
+  __pyx_v_iy = ((PyArrayObject *)__pyx_t_5);
+  __pyx_t_5 = 0;
+
+  /* "astropy/time/sofa_time.pyx":277
+ * 
+ *     cdef np.ndarray[int, ndim=1] iy = np.empty(n, dtype=np.intc)
+ *     cdef np.ndarray[int, ndim=1] im = np.empty(n, dtype=np.intc)             # <<<<<<<<<<<<<<
+ *     cdef np.ndarray[int, ndim=1] id = np.empty(n, dtype=np.intc)
+ *     cdef np.ndarray[int, ndim=2] ihmsf = np.empty((n, 4), dtype=np.intc)
+ */
+  __pyx_t_5 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 277; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __pyx_t_1 = PyObject_GetAttr(__pyx_t_5, __pyx_n_s__empty); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 277; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  __pyx_t_5 = PyInt_FromLong(__pyx_v_n); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 277; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 277; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_3));
+  PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_5);
+  __Pyx_GIVEREF(__pyx_t_5);
+  __pyx_t_5 = 0;
+  __pyx_t_5 = PyDict_New(); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 277; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_5));
+  __pyx_t_2 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 277; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_4 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s__intc); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 277; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_4);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  if (PyDict_SetItem(__pyx_t_5, ((PyObject *)__pyx_n_s__dtype), __pyx_t_4) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 277; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  __pyx_t_4 = PyEval_CallObjectWithKeywords(__pyx_t_1, ((PyObject *)__pyx_t_3), ((PyObject *)__pyx_t_5)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 277; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_4);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_5)); __pyx_t_5 = 0;
+  if (!(likely(((__pyx_t_4) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_4, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 277; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_7 = ((PyArrayObject *)__pyx_t_4);
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_im, (PyObject*)__pyx_t_7, &__Pyx_TypeInfo_int, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {
+      __pyx_v_im = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_im.buf = NULL;
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 277; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    } else {__pyx_bstride_0_im = __pyx_bstruct_im.strides[0];
+      __pyx_bshape_0_im = __pyx_bstruct_im.shape[0];
+    }
+  }
+  __pyx_t_7 = 0;
+  __pyx_v_im = ((PyArrayObject *)__pyx_t_4);
+  __pyx_t_4 = 0;
+
+  /* "astropy/time/sofa_time.pyx":278
+ *     cdef np.ndarray[int, ndim=1] iy = np.empty(n, dtype=np.intc)
+ *     cdef np.ndarray[int, ndim=1] im = np.empty(n, dtype=np.intc)
+ *     cdef np.ndarray[int, ndim=1] id = np.empty(n, dtype=np.intc)             # <<<<<<<<<<<<<<
+ *     cdef np.ndarray[int, ndim=2] ihmsf = np.empty((n, 4), dtype=np.intc)
+ * 
+ */
+  __pyx_t_4 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 278; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_4);
+  __pyx_t_5 = PyObject_GetAttr(__pyx_t_4, __pyx_n_s__empty); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 278; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  __pyx_t_4 = PyInt_FromLong(__pyx_v_n); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 278; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_4);
+  __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 278; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_3));
+  PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_4);
+  __Pyx_GIVEREF(__pyx_t_4);
+  __pyx_t_4 = 0;
+  __pyx_t_4 = PyDict_New(); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 278; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_4));
+  __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 278; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_2 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s__intc); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 278; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  if (PyDict_SetItem(__pyx_t_4, ((PyObject *)__pyx_n_s__dtype), __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 278; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __pyx_t_2 = PyEval_CallObjectWithKeywords(__pyx_t_5, ((PyObject *)__pyx_t_3), ((PyObject *)__pyx_t_4)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 278; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
+  if (!(likely(((__pyx_t_2) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_2, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 278; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_8 = ((PyArrayObject *)__pyx_t_2);
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_id, (PyObject*)__pyx_t_8, &__Pyx_TypeInfo_int, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {
+      __pyx_v_id = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_id.buf = NULL;
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 278; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    } else {__pyx_bstride_0_id = __pyx_bstruct_id.strides[0];
+      __pyx_bshape_0_id = __pyx_bstruct_id.shape[0];
+    }
+  }
+  __pyx_t_8 = 0;
+  __pyx_v_id = ((PyArrayObject *)__pyx_t_2);
+  __pyx_t_2 = 0;
+
+  /* "astropy/time/sofa_time.pyx":279
+ *     cdef np.ndarray[int, ndim=1] im = np.empty(n, dtype=np.intc)
+ *     cdef np.ndarray[int, ndim=1] id = np.empty(n, dtype=np.intc)
+ *     cdef np.ndarray[int, ndim=2] ihmsf = np.empty((n, 4), dtype=np.intc)             # <<<<<<<<<<<<<<
+ * 
+ *     warns = {1: DUBIOUS}
+ */
+  __pyx_t_2 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 279; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_4 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s__empty); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 279; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_4);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __pyx_t_2 = PyInt_FromLong(__pyx_v_n); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 279; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 279; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_3));
+  PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_2);
+  __Pyx_GIVEREF(__pyx_t_2);
+  __Pyx_INCREF(__pyx_int_4);
+  PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_int_4);
+  __Pyx_GIVEREF(__pyx_int_4);
+  __pyx_t_2 = 0;
+  __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 279; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_2));
+  PyTuple_SET_ITEM(__pyx_t_2, 0, ((PyObject *)__pyx_t_3));
+  __Pyx_GIVEREF(((PyObject *)__pyx_t_3));
+  __pyx_t_3 = 0;
+  __pyx_t_3 = PyDict_New(); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 279; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_3));
+  __pyx_t_5 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 279; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __pyx_t_1 = PyObject_GetAttr(__pyx_t_5, __pyx_n_s__intc); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 279; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  if (PyDict_SetItem(__pyx_t_3, ((PyObject *)__pyx_n_s__dtype), __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 279; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __pyx_t_1 = PyEval_CallObjectWithKeywords(__pyx_t_4, ((PyObject *)__pyx_t_2), ((PyObject *)__pyx_t_3)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 279; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
+  if (!(likely(((__pyx_t_1) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_1, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 279; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_9 = ((PyArrayObject *)__pyx_t_1);
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_ihmsf, (PyObject*)__pyx_t_9, &__Pyx_TypeInfo_int, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) {
+      __pyx_v_ihmsf = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_ihmsf.buf = NULL;
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 279; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    } else {__pyx_bstride_0_ihmsf = __pyx_bstruct_ihmsf.strides[0]; __pyx_bstride_1_ihmsf = __pyx_bstruct_ihmsf.strides[1];
+      __pyx_bshape_0_ihmsf = __pyx_bstruct_ihmsf.shape[0]; __pyx_bshape_1_ihmsf = __pyx_bstruct_ihmsf.shape[1];
+    }
+  }
+  __pyx_t_9 = 0;
+  __pyx_v_ihmsf = ((PyArrayObject *)__pyx_t_1);
+  __pyx_t_1 = 0;
+
+  /* "astropy/time/sofa_time.pyx":281
+ *     cdef np.ndarray[int, ndim=2] ihmsf = np.empty((n, 4), dtype=np.intc)
+ * 
+ *     warns = {1: DUBIOUS}             # <<<<<<<<<<<<<<
+ *     errs = {-1: 'unacceptable date'}
+ * 
+ */
+  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 281; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_1));
+  __pyx_t_3 = __Pyx_GetName(__pyx_m, __pyx_n_s__DUBIOUS); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 281; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  if (PyDict_SetItem(__pyx_t_1, __pyx_int_1, __pyx_t_3) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 281; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  __pyx_v_warns = __pyx_t_1;
+  __pyx_t_1 = 0;
+
+  /* "astropy/time/sofa_time.pyx":282
+ * 
+ *     warns = {1: DUBIOUS}
+ *     errs = {-1: 'unacceptable date'}             # <<<<<<<<<<<<<<
+ * 
+ *     for i in range(n):
+ */
+  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 282; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_1));
+  if (PyDict_SetItem(__pyx_t_1, __pyx_int_neg_1, ((PyObject *)__pyx_kp_s_12)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 282; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_v_errs = __pyx_t_1;
+  __pyx_t_1 = 0;
+
+  /* "astropy/time/sofa_time.pyx":284
+ *     errs = {-1: 'unacceptable date'}
+ * 
+ *     for i in range(n):             # <<<<<<<<<<<<<<
+ *         ret = iauD2dtf(scale, ndp, d1[i], d2[i],
+ *                      &iy[i], &im[i], &id[i], &ihmsf[i, 0])
+ */
+  __pyx_t_10 = __pyx_v_n;
+  for (__pyx_t_11 = 0; __pyx_t_11 < __pyx_t_10; __pyx_t_11+=1) {
+    __pyx_v_i = __pyx_t_11;
+
+    /* "astropy/time/sofa_time.pyx":285
+ * 
+ *     for i in range(n):
+ *         ret = iauD2dtf(scale, ndp, d1[i], d2[i],             # <<<<<<<<<<<<<<
+ *                      &iy[i], &im[i], &id[i], &ihmsf[i, 0])
+ *         check_return(ret, 'iauD2dtf', warns, errs)
+ */
+    __pyx_t_12 = PyBytes_AsString(__pyx_v_scale); if (unlikely((!__pyx_t_12) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 285; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_13 = __Pyx_PyInt_AsInt(__pyx_v_ndp); if (unlikely((__pyx_t_13 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 285; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_14 = __pyx_v_i;
+    __pyx_t_15 = __pyx_v_i;
+
+    /* "astropy/time/sofa_time.pyx":286
+ *     for i in range(n):
+ *         ret = iauD2dtf(scale, ndp, d1[i], d2[i],
+ *                      &iy[i], &im[i], &id[i], &ihmsf[i, 0])             # <<<<<<<<<<<<<<
+ *         check_return(ret, 'iauD2dtf', warns, errs)
+ * 
+ */
+    __pyx_t_16 = __pyx_v_i;
+    __pyx_t_17 = __pyx_v_i;
+    __pyx_t_18 = __pyx_v_i;
+    __pyx_t_19 = __pyx_v_i;
+    __pyx_t_20 = 0;
+    __pyx_v_ret = iauD2dtf(__pyx_t_12, __pyx_t_13, (*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_d1.buf, __pyx_t_14, __pyx_bstride_0_d1)), (*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_d2.buf, __pyx_t_15, __pyx_bstride_0_d2)), (&(*__Pyx_BufPtrStrided1d(int *, __pyx_bstruct_iy.buf, __pyx_t_16, __pyx_bstride_0_iy))), (&(*__Pyx_BufPtrStrided1d(int *, __pyx_bstruct_im.buf, __pyx_t_17, __pyx_bstride_0_im))), (&(*__Pyx_BufPtrStrided1d(int *, __pyx_bstruct_id.buf, __pyx_t_18, __pyx_bstride_0_id))), (&(*__Pyx_BufPtrStrided2d(int *, __pyx_bstruct_ihmsf.buf, __pyx_t_19, __pyx_bstride_0_ihmsf, __pyx_t_20, __pyx_bstride_1_ihmsf))));
+
+    /* "astropy/time/sofa_time.pyx":287
+ *         ret = iauD2dtf(scale, ndp, d1[i], d2[i],
+ *                      &iy[i], &im[i], &id[i], &ihmsf[i, 0])
+ *         check_return(ret, 'iauD2dtf', warns, errs)             # <<<<<<<<<<<<<<
+ * 
+ *     return iy, im, id, ihmsf
+ */
+    __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__check_return); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 287; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_1);
+    __pyx_t_3 = PyInt_FromLong(__pyx_v_ret); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 287; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_3);
+    __pyx_t_2 = PyTuple_New(4); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 287; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(((PyObject *)__pyx_t_2));
+    PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_3);
+    __Pyx_GIVEREF(__pyx_t_3);
+    __Pyx_INCREF(((PyObject *)__pyx_n_s__iauD2dtf));
+    PyTuple_SET_ITEM(__pyx_t_2, 1, ((PyObject *)__pyx_n_s__iauD2dtf));
+    __Pyx_GIVEREF(((PyObject *)__pyx_n_s__iauD2dtf));
+    __Pyx_INCREF(((PyObject *)__pyx_v_warns));
+    PyTuple_SET_ITEM(__pyx_t_2, 2, ((PyObject *)__pyx_v_warns));
+    __Pyx_GIVEREF(((PyObject *)__pyx_v_warns));
+    __Pyx_INCREF(((PyObject *)__pyx_v_errs));
+    PyTuple_SET_ITEM(__pyx_t_2, 3, ((PyObject *)__pyx_v_errs));
+    __Pyx_GIVEREF(((PyObject *)__pyx_v_errs));
+    __pyx_t_3 = 0;
+    __pyx_t_3 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_2), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 287; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_3);
+    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
+    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  }
+
+  /* "astropy/time/sofa_time.pyx":289
+ *         check_return(ret, 'iauD2dtf', warns, errs)
+ * 
+ *     return iy, im, id, ihmsf             # <<<<<<<<<<<<<<
+ * 
+ * @cython.wraparound(False)
+ */
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_t_3 = PyTuple_New(4); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 289; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_3));
+  __Pyx_INCREF(((PyObject *)__pyx_v_iy));
+  PyTuple_SET_ITEM(__pyx_t_3, 0, ((PyObject *)__pyx_v_iy));
+  __Pyx_GIVEREF(((PyObject *)__pyx_v_iy));
+  __Pyx_INCREF(((PyObject *)__pyx_v_im));
+  PyTuple_SET_ITEM(__pyx_t_3, 1, ((PyObject *)__pyx_v_im));
+  __Pyx_GIVEREF(((PyObject *)__pyx_v_im));
+  __Pyx_INCREF(((PyObject *)__pyx_v_id));
+  PyTuple_SET_ITEM(__pyx_t_3, 2, ((PyObject *)__pyx_v_id));
+  __Pyx_GIVEREF(((PyObject *)__pyx_v_id));
+  __Pyx_INCREF(((PyObject *)__pyx_v_ihmsf));
+  PyTuple_SET_ITEM(__pyx_t_3, 3, ((PyObject *)__pyx_v_ihmsf));
+  __Pyx_GIVEREF(((PyObject *)__pyx_v_ihmsf));
+  __pyx_r = ((PyObject *)__pyx_t_3);
+  __pyx_t_3 = 0;
+  goto __pyx_L0;
+
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_XDECREF(__pyx_t_5);
+  { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;
+    __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_iy);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_ihmsf);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_im);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_d2);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_id);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_d1);
+  __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
+  __Pyx_AddTraceback("astropy.time.sofa_time.jd_dtf", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  goto __pyx_L2;
+  __pyx_L0:;
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_iy);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_ihmsf);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_im);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_d2);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_id);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_d1);
+  __pyx_L2:;
+  __Pyx_XDECREF((PyObject *)__pyx_v_iy);
+  __Pyx_XDECREF((PyObject *)__pyx_v_im);
+  __Pyx_XDECREF((PyObject *)__pyx_v_id);
+  __Pyx_XDECREF((PyObject *)__pyx_v_ihmsf);
+  __Pyx_XDECREF(__pyx_v_warns);
+  __Pyx_XDECREF(__pyx_v_errs);
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "astropy/time/sofa_time.pyx":293
+ * @cython.wraparound(False)
+ * @cython.boundscheck(False)
+ * def dtf_jd(scale,             # <<<<<<<<<<<<<<
+ *               np.ndarray[int, ndim=1] iy,
+ *               np.ndarray[int, ndim=1] im,
+ */
+
+static PyObject *__pyx_pf_7astropy_4time_9sofa_time_4dtf_jd(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_7astropy_4time_9sofa_time_4dtf_jd[] = "\n    int iauDtf2d(char *scale, int iy, int im, int id, int ihr, int imn, double sec, double *d1, double *d2)\n\n    **  Given:\n    **     scale     char[]  time scale ID (Note 1)\n    **     iy,im,id  int     year, month, day in Gregorian calendar (Note 2)\n    **     ihr,imn   int     hour, minute\n    **     sec       double  seconds\n    **\n    **  Returned:\n    **     d1,d2     double  2-part Julian Date (Notes 3,4)\n    **\n    **  Returned (function value):\n    **               int     status: +3 = both of next two\n    **                               +2 = time is after end of day (Note 5)\n    **                               +1 = dubious year (Note 6)\n    **                                0 = OK\n    **                               -1 = bad year\n    **                               -2 = bad month\n    **                               -3 = bad day\n    **                               -4 = bad hour\n    **                               -5 = bad minute\n    **                               -6 = bad second (<0)\n    **\n    **  Notes:\n    **\n    **  1) scale identifies the time scale.  Only the value \"UTC\" (in upper\n    **     case) is significant, and enables handling of leap seconds (see\n    **     Note 4).\n    **\n    **  2) For calendar conventions and limitations, see iauCal2jd.\n    **\n    **  3) The sum of the results, d1+d2, is Julian Date, where normally d1\n    **     is the Julian Day Number and d2 is the fraction of a day.  In the\n    **     case of UTC, where the use of JD is problematical, special\n    **     conventions apply:  see the next note.\n    **\n    **  4) JD cannot unambiguously represent UTC during a leap second unless\n    **     special measures are taken.  The SOFA internal convention is that\n    **     the quasi-JD day represents UTC days whether the length is 86399,\n    **     86400 or 86401 SI seconds.\n    **\n    **  5) The warning status \"time is after end of day\" usually means that\n    **     the sec a""rgument is greater than 60.0.  However, in a day ending\n    **     in a leap second the limit changes to 61.0 (or 59.0 in the case\n    **     of a negative leap second).\n    **\n    **  6) The warning status \"dubious year\" flags UTCs that predate the\n    **     introduction of the time scale and that are too far in the future\n    **     to be trusted.  See iauDat for further details.\n    **\n    **  7) Only in the case of continuous and regular time scales (TAI, TT,\n    **     TCG, TCB and TDB) is the result d1+d2 a Julian Date, strictly\n    **     speaking.  In the other cases (UT1 and UTC) the result must be\n    **     used with circumspection;  in particular the difference between\n    **     two such results cannot be interpreted as a precise time\n    **     interval.\n\n    ";
+static PyMethodDef __pyx_mdef_7astropy_4time_9sofa_time_4dtf_jd = {__Pyx_NAMESTR("dtf_jd"), (PyCFunction)__pyx_pf_7astropy_4time_9sofa_time_4dtf_jd, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(__pyx_doc_7astropy_4time_9sofa_time_4dtf_jd)};
+static PyObject *__pyx_pf_7astropy_4time_9sofa_time_4dtf_jd(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyObject *__pyx_v_scale = 0;
+  PyArrayObject *__pyx_v_iy = 0;
+  PyArrayObject *__pyx_v_im = 0;
+  PyArrayObject *__pyx_v_id = 0;
+  PyArrayObject *__pyx_v_ihr = 0;
+  PyArrayObject *__pyx_v_imn = 0;
+  PyArrayObject *__pyx_v_sec = 0;
+  int __pyx_v_i;
+  int __pyx_v_n;
+  PyArrayObject *__pyx_v_out1 = 0;
+  PyArrayObject *__pyx_v_out2 = 0;
+  PyObject *__pyx_v_warns = NULL;
+  PyObject *__pyx_v_errs = NULL;
+  int __pyx_v_ret;
+  Py_buffer __pyx_bstruct_iy;
+  Py_ssize_t __pyx_bstride_0_iy = 0;
+  Py_ssize_t __pyx_bshape_0_iy = 0;
+  Py_buffer __pyx_bstruct_out1;
+  Py_ssize_t __pyx_bstride_0_out1 = 0;
+  Py_ssize_t __pyx_bshape_0_out1 = 0;
+  Py_buffer __pyx_bstruct_out2;
+  Py_ssize_t __pyx_bstride_0_out2 = 0;
+  Py_ssize_t __pyx_bshape_0_out2 = 0;
+  Py_buffer __pyx_bstruct_ihr;
+  Py_ssize_t __pyx_bstride_0_ihr = 0;
+  Py_ssize_t __pyx_bshape_0_ihr = 0;
+  Py_buffer __pyx_bstruct_imn;
+  Py_ssize_t __pyx_bstride_0_imn = 0;
+  Py_ssize_t __pyx_bshape_0_imn = 0;
+  Py_buffer __pyx_bstruct_im;
+  Py_ssize_t __pyx_bstride_0_im = 0;
+  Py_ssize_t __pyx_bshape_0_im = 0;
+  Py_buffer __pyx_bstruct_sec;
+  Py_ssize_t __pyx_bstride_0_sec = 0;
+  Py_ssize_t __pyx_bshape_0_sec = 0;
+  Py_buffer __pyx_bstruct_id;
+  Py_ssize_t __pyx_bstride_0_id = 0;
+  Py_ssize_t __pyx_bshape_0_id = 0;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  int __pyx_t_1;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
+  PyObject *__pyx_t_5 = NULL;
+  PyObject *__pyx_t_6 = NULL;
+  PyArrayObject *__pyx_t_7 = NULL;
+  PyArrayObject *__pyx_t_8 = NULL;
+  int __pyx_t_9;
+  int __pyx_t_10;
+  char *__pyx_t_11;
+  int __pyx_t_12;
+  int __pyx_t_13;
+  int __pyx_t_14;
+  int __pyx_t_15;
+  int __pyx_t_16;
+  int __pyx_t_17;
+  int __pyx_t_18;
+  int __pyx_t_19;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__scale,&__pyx_n_s__iy,&__pyx_n_s__im,&__pyx_n_s__id,&__pyx_n_s__ihr,&__pyx_n_s__imn,&__pyx_n_s__sec,0};
+  __Pyx_RefNannySetupContext("dtf_jd");
+  __pyx_self = __pyx_self;
+  {
+    PyObject* values[7] = {0,0,0,0,0,0,0};
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  7: values[6] = PyTuple_GET_ITEM(__pyx_args, 6);
+        case  6: values[5] = PyTuple_GET_ITEM(__pyx_args, 5);
+        case  5: values[4] = PyTuple_GET_ITEM(__pyx_args, 4);
+        case  4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
+        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  0:
+        values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__scale);
+        if (likely(values[0])) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+        case  1:
+        values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__iy);
+        if (likely(values[1])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("dtf_jd", 1, 7, 7, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 293; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+        case  2:
+        values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__im);
+        if (likely(values[2])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("dtf_jd", 1, 7, 7, 2); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 293; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+        case  3:
+        values[3] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__id);
+        if (likely(values[3])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("dtf_jd", 1, 7, 7, 3); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 293; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+        case  4:
+        values[4] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__ihr);
+        if (likely(values[4])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("dtf_jd", 1, 7, 7, 4); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 293; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+        case  5:
+        values[5] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__imn);
+        if (likely(values[5])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("dtf_jd", 1, 7, 7, 5); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 293; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+        case  6:
+        values[6] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__sec);
+        if (likely(values[6])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("dtf_jd", 1, 7, 7, 6); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 293; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "dtf_jd") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 293; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+    } else if (PyTuple_GET_SIZE(__pyx_args) != 7) {
+      goto __pyx_L5_argtuple_error;
+    } else {
+      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+      values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+      values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
+      values[4] = PyTuple_GET_ITEM(__pyx_args, 4);
+      values[5] = PyTuple_GET_ITEM(__pyx_args, 5);
+      values[6] = PyTuple_GET_ITEM(__pyx_args, 6);
+    }
+    __pyx_v_scale = values[0];
+    __pyx_v_iy = ((PyArrayObject *)values[1]);
+    __pyx_v_im = ((PyArrayObject *)values[2]);
+    __pyx_v_id = ((PyArrayObject *)values[3]);
+    __pyx_v_ihr = ((PyArrayObject *)values[4]);
+    __pyx_v_imn = ((PyArrayObject *)values[5]);
+    __pyx_v_sec = ((PyArrayObject *)values[6]);
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("dtf_jd", 1, 7, 7, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 293; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("astropy.time.sofa_time.dtf_jd", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_bstruct_out1.buf = NULL;
+  __pyx_bstruct_out2.buf = NULL;
+  __pyx_bstruct_iy.buf = NULL;
+  __pyx_bstruct_im.buf = NULL;
+  __pyx_bstruct_id.buf = NULL;
+  __pyx_bstruct_ihr.buf = NULL;
+  __pyx_bstruct_imn.buf = NULL;
+  __pyx_bstruct_sec.buf = NULL;
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_iy), __pyx_ptype_5numpy_ndarray, 1, "iy", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 294; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_im), __pyx_ptype_5numpy_ndarray, 1, "im", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 295; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_id), __pyx_ptype_5numpy_ndarray, 1, "id", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 296; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ihr), __pyx_ptype_5numpy_ndarray, 1, "ihr", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 297; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_imn), __pyx_ptype_5numpy_ndarray, 1, "imn", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 298; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_sec), __pyx_ptype_5numpy_ndarray, 1, "sec", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 299; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_iy, (PyObject*)__pyx_v_iy, &__Pyx_TypeInfo_int, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 293; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_iy = __pyx_bstruct_iy.strides[0];
+  __pyx_bshape_0_iy = __pyx_bstruct_iy.shape[0];
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_im, (PyObject*)__pyx_v_im, &__Pyx_TypeInfo_int, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 293; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_im = __pyx_bstruct_im.strides[0];
+  __pyx_bshape_0_im = __pyx_bstruct_im.shape[0];
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_id, (PyObject*)__pyx_v_id, &__Pyx_TypeInfo_int, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 293; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_id = __pyx_bstruct_id.strides[0];
+  __pyx_bshape_0_id = __pyx_bstruct_id.shape[0];
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_ihr, (PyObject*)__pyx_v_ihr, &__Pyx_TypeInfo_int, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 293; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_ihr = __pyx_bstruct_ihr.strides[0];
+  __pyx_bshape_0_ihr = __pyx_bstruct_ihr.shape[0];
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_imn, (PyObject*)__pyx_v_imn, &__Pyx_TypeInfo_int, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 293; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_imn = __pyx_bstruct_imn.strides[0];
+  __pyx_bshape_0_imn = __pyx_bstruct_imn.shape[0];
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_sec, (PyObject*)__pyx_v_sec, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 293; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_sec = __pyx_bstruct_sec.strides[0];
+  __pyx_bshape_0_sec = __pyx_bstruct_sec.shape[0];
+
+  /* "astropy/time/sofa_time.pyx":360
+ *     """
+ *     cdef int i
+ *     cdef int n = iy.shape[0]             # <<<<<<<<<<<<<<
+ *     assert (iy.shape[0] == im.shape[0] == id.shape[0] ==
+ *             ihr.shape[0] == imn.shape[0] == sec.shape[0])
+ */
+  __pyx_v_n = (__pyx_v_iy->dimensions[0]);
+
+  /* "astropy/time/sofa_time.pyx":361
+ *     cdef int i
+ *     cdef int n = iy.shape[0]
+ *     assert (iy.shape[0] == im.shape[0] == id.shape[0] ==             # <<<<<<<<<<<<<<
+ *             ihr.shape[0] == imn.shape[0] == sec.shape[0])
+ * 
+ */
+  #ifndef CYTHON_WITHOUT_ASSERTIONS
+  __pyx_t_1 = ((__pyx_v_iy->dimensions[0]) == (__pyx_v_im->dimensions[0]));
+  if (__pyx_t_1) {
+    __pyx_t_1 = ((__pyx_v_im->dimensions[0]) == (__pyx_v_id->dimensions[0]));
+    if (__pyx_t_1) {
+
+      /* "astropy/time/sofa_time.pyx":362
+ *     cdef int n = iy.shape[0]
+ *     assert (iy.shape[0] == im.shape[0] == id.shape[0] ==
+ *             ihr.shape[0] == imn.shape[0] == sec.shape[0])             # <<<<<<<<<<<<<<
+ * 
+ *     cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)
+ */
+      __pyx_t_1 = ((__pyx_v_id->dimensions[0]) == (__pyx_v_ihr->dimensions[0]));
+      if (__pyx_t_1) {
+        __pyx_t_1 = ((__pyx_v_ihr->dimensions[0]) == (__pyx_v_imn->dimensions[0]));
+        if (__pyx_t_1) {
+          __pyx_t_1 = ((__pyx_v_imn->dimensions[0]) == (__pyx_v_sec->dimensions[0]));
+        }
+      }
+    }
+  }
+  if (unlikely(!__pyx_t_1)) {
+    PyErr_SetNone(PyExc_AssertionError);
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 361; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  #endif
+
+  /* "astropy/time/sofa_time.pyx":364
+ *             ihr.shape[0] == imn.shape[0] == sec.shape[0])
+ * 
+ *     cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)             # <<<<<<<<<<<<<<
+ *     cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)
+ * 
+ */
+  __pyx_t_2 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 364; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_3 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s__empty); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 364; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __pyx_t_2 = PyInt_FromLong(__pyx_v_n); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 364; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 364; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_4));
+  PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_2);
+  __Pyx_GIVEREF(__pyx_t_2);
+  __pyx_t_2 = 0;
+  __pyx_t_2 = PyDict_New(); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 364; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_2));
+  __pyx_t_5 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 364; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __pyx_t_6 = PyObject_GetAttr(__pyx_t_5, __pyx_n_s__double); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 364; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_6);
+  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  if (PyDict_SetItem(__pyx_t_2, ((PyObject *)__pyx_n_s__dtype), __pyx_t_6) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 364; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+  __pyx_t_6 = PyEval_CallObjectWithKeywords(__pyx_t_3, ((PyObject *)__pyx_t_4), ((PyObject *)__pyx_t_2)); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 364; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_6);
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
+  if (!(likely(((__pyx_t_6) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_6, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 364; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_7 = ((PyArrayObject *)__pyx_t_6);
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_out1, (PyObject*)__pyx_t_7, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {
+      __pyx_v_out1 = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_out1.buf = NULL;
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 364; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    } else {__pyx_bstride_0_out1 = __pyx_bstruct_out1.strides[0];
+      __pyx_bshape_0_out1 = __pyx_bstruct_out1.shape[0];
+    }
+  }
+  __pyx_t_7 = 0;
+  __pyx_v_out1 = ((PyArrayObject *)__pyx_t_6);
+  __pyx_t_6 = 0;
+
+  /* "astropy/time/sofa_time.pyx":365
+ * 
+ *     cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)
+ *     cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)             # <<<<<<<<<<<<<<
+ * 
+ *     warns = {3: 'time is after end of day and ' + DUBIOUS,
+ */
+  __pyx_t_6 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 365; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_6);
+  __pyx_t_2 = PyObject_GetAttr(__pyx_t_6, __pyx_n_s__empty); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 365; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+  __pyx_t_6 = PyInt_FromLong(__pyx_v_n); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 365; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_6);
+  __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 365; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_4));
+  PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_6);
+  __Pyx_GIVEREF(__pyx_t_6);
+  __pyx_t_6 = 0;
+  __pyx_t_6 = PyDict_New(); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 365; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_6));
+  __pyx_t_3 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 365; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __pyx_t_5 = PyObject_GetAttr(__pyx_t_3, __pyx_n_s__double); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 365; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  if (PyDict_SetItem(__pyx_t_6, ((PyObject *)__pyx_n_s__dtype), __pyx_t_5) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 365; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  __pyx_t_5 = PyEval_CallObjectWithKeywords(__pyx_t_2, ((PyObject *)__pyx_t_4), ((PyObject *)__pyx_t_6)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 365; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_6)); __pyx_t_6 = 0;
+  if (!(likely(((__pyx_t_5) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_5, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 365; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_8 = ((PyArrayObject *)__pyx_t_5);
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_out2, (PyObject*)__pyx_t_8, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {
+      __pyx_v_out2 = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_out2.buf = NULL;
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 365; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    } else {__pyx_bstride_0_out2 = __pyx_bstruct_out2.strides[0];
+      __pyx_bshape_0_out2 = __pyx_bstruct_out2.shape[0];
+    }
+  }
+  __pyx_t_8 = 0;
+  __pyx_v_out2 = ((PyArrayObject *)__pyx_t_5);
+  __pyx_t_5 = 0;
+
+  /* "astropy/time/sofa_time.pyx":367
+ *     cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)
+ * 
+ *     warns = {3: 'time is after end of day and ' + DUBIOUS,             # <<<<<<<<<<<<<<
+ *              2: 'time is after end of day',
+ *              1: DUBIOUS}
+ */
+  __pyx_t_5 = PyDict_New(); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 367; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_5));
+  __pyx_t_6 = __Pyx_GetName(__pyx_m, __pyx_n_s__DUBIOUS); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 367; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_6);
+  __pyx_t_4 = PyNumber_Add(((PyObject *)__pyx_kp_s_13), __pyx_t_6); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 367; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_4);
+  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+  if (PyDict_SetItem(__pyx_t_5, __pyx_int_3, __pyx_t_4) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 367; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  if (PyDict_SetItem(__pyx_t_5, __pyx_int_2, ((PyObject *)__pyx_kp_s_14)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 367; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+
+  /* "astropy/time/sofa_time.pyx":369
+ *     warns = {3: 'time is after end of day and ' + DUBIOUS,
+ *              2: 'time is after end of day',
+ *              1: DUBIOUS}             # <<<<<<<<<<<<<<
+ *     errs = {-1: 'bad year',
+ *             -2: 'bad month',
+ */
+  __pyx_t_4 = __Pyx_GetName(__pyx_m, __pyx_n_s__DUBIOUS); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 369; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_4);
+  if (PyDict_SetItem(__pyx_t_5, __pyx_int_1, __pyx_t_4) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 367; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  __pyx_v_warns = __pyx_t_5;
+  __pyx_t_5 = 0;
+
+  /* "astropy/time/sofa_time.pyx":370
+ *              2: 'time is after end of day',
+ *              1: DUBIOUS}
+ *     errs = {-1: 'bad year',             # <<<<<<<<<<<<<<
+ *             -2: 'bad month',
+ *             -3: 'bad day',
+ */
+  __pyx_t_5 = PyDict_New(); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 370; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_5));
+  if (PyDict_SetItem(__pyx_t_5, __pyx_int_neg_1, ((PyObject *)__pyx_kp_s_8)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 370; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyDict_SetItem(__pyx_t_5, __pyx_int_neg_2, ((PyObject *)__pyx_kp_s_15)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 370; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyDict_SetItem(__pyx_t_5, __pyx_int_neg_3, ((PyObject *)__pyx_kp_s_16)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 370; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyDict_SetItem(__pyx_t_5, __pyx_int_neg_4, ((PyObject *)__pyx_kp_s_17)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 370; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyDict_SetItem(__pyx_t_5, __pyx_int_neg_5, ((PyObject *)__pyx_kp_s_18)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 370; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyDict_SetItem(__pyx_t_5, __pyx_int_neg_6, ((PyObject *)__pyx_kp_s_19)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 370; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_v_errs = __pyx_t_5;
+  __pyx_t_5 = 0;
+
+  /* "astropy/time/sofa_time.pyx":377
+ *             -6: 'bad second (< 0)'}
+ * 
+ *     for i in range(n):             # <<<<<<<<<<<<<<
+ *         ret = iauDtf2d(scale, iy[i], im[i], id[i], ihr[i], imn[i], sec[i],
+ *                        &out1[i], &out2[i])
+ */
+  __pyx_t_9 = __pyx_v_n;
+  for (__pyx_t_10 = 0; __pyx_t_10 < __pyx_t_9; __pyx_t_10+=1) {
+    __pyx_v_i = __pyx_t_10;
+
+    /* "astropy/time/sofa_time.pyx":378
+ * 
+ *     for i in range(n):
+ *         ret = iauDtf2d(scale, iy[i], im[i], id[i], ihr[i], imn[i], sec[i],             # <<<<<<<<<<<<<<
+ *                        &out1[i], &out2[i])
+ *         check_return(ret, 'iauDtf2d', warns, errs)
+ */
+    __pyx_t_11 = PyBytes_AsString(__pyx_v_scale); if (unlikely((!__pyx_t_11) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 378; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_12 = __pyx_v_i;
+    __pyx_t_13 = __pyx_v_i;
+    __pyx_t_14 = __pyx_v_i;
+    __pyx_t_15 = __pyx_v_i;
+    __pyx_t_16 = __pyx_v_i;
+    __pyx_t_17 = __pyx_v_i;
+
+    /* "astropy/time/sofa_time.pyx":379
+ *     for i in range(n):
+ *         ret = iauDtf2d(scale, iy[i], im[i], id[i], ihr[i], imn[i], sec[i],
+ *                        &out1[i], &out2[i])             # <<<<<<<<<<<<<<
+ *         check_return(ret, 'iauDtf2d', warns, errs)
+ * 
+ */
+    __pyx_t_18 = __pyx_v_i;
+    __pyx_t_19 = __pyx_v_i;
+    __pyx_v_ret = iauDtf2d(__pyx_t_11, (*__Pyx_BufPtrStrided1d(int *, __pyx_bstruct_iy.buf, __pyx_t_12, __pyx_bstride_0_iy)), (*__Pyx_BufPtrStrided1d(int *, __pyx_bstruct_im.buf, __pyx_t_13, __pyx_bstride_0_im)), (*__Pyx_BufPtrStrided1d(int *, __pyx_bstruct_id.buf, __pyx_t_14, __pyx_bstride_0_id)), (*__Pyx_BufPtrStrided1d(int *, __pyx_bstruct_ihr.buf, __pyx_t_15, __pyx_bstride_0_ihr)), (*__Pyx_BufPtrStrided1d(int *, __pyx_bstruct_imn.buf, __pyx_t_16, __pyx_bstride_0_imn)), (*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_sec.buf, __pyx_t_17, __pyx_bstride_0_sec)), (&(*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_out1.buf, __pyx_t_18, __pyx_bstride_0_out1))), (&(*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_out2.buf, __pyx_t_19, __pyx_bstride_0_out2))));
+
+    /* "astropy/time/sofa_time.pyx":380
+ *         ret = iauDtf2d(scale, iy[i], im[i], id[i], ihr[i], imn[i], sec[i],
+ *                        &out1[i], &out2[i])
+ *         check_return(ret, 'iauDtf2d', warns, errs)             # <<<<<<<<<<<<<<
+ * 
+ *     return out1, out2
+ */
+    __pyx_t_5 = __Pyx_GetName(__pyx_m, __pyx_n_s__check_return); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 380; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_5);
+    __pyx_t_4 = PyInt_FromLong(__pyx_v_ret); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 380; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_4);
+    __pyx_t_6 = PyTuple_New(4); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 380; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(((PyObject *)__pyx_t_6));
+    PyTuple_SET_ITEM(__pyx_t_6, 0, __pyx_t_4);
+    __Pyx_GIVEREF(__pyx_t_4);
+    __Pyx_INCREF(((PyObject *)__pyx_n_s__iauDtf2d));
+    PyTuple_SET_ITEM(__pyx_t_6, 1, ((PyObject *)__pyx_n_s__iauDtf2d));
+    __Pyx_GIVEREF(((PyObject *)__pyx_n_s__iauDtf2d));
+    __Pyx_INCREF(((PyObject *)__pyx_v_warns));
+    PyTuple_SET_ITEM(__pyx_t_6, 2, ((PyObject *)__pyx_v_warns));
+    __Pyx_GIVEREF(((PyObject *)__pyx_v_warns));
+    __Pyx_INCREF(((PyObject *)__pyx_v_errs));
+    PyTuple_SET_ITEM(__pyx_t_6, 3, ((PyObject *)__pyx_v_errs));
+    __Pyx_GIVEREF(((PyObject *)__pyx_v_errs));
+    __pyx_t_4 = 0;
+    __pyx_t_4 = PyObject_Call(__pyx_t_5, ((PyObject *)__pyx_t_6), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 380; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_4);
+    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+    __Pyx_DECREF(((PyObject *)__pyx_t_6)); __pyx_t_6 = 0;
+    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  }
+
+  /* "astropy/time/sofa_time.pyx":382
+ *         check_return(ret, 'iauDtf2d', warns, errs)
+ * 
+ *     return out1, out2             # <<<<<<<<<<<<<<
+ * 
+ * 
+ */
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 382; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_4));
+  __Pyx_INCREF(((PyObject *)__pyx_v_out1));
+  PyTuple_SET_ITEM(__pyx_t_4, 0, ((PyObject *)__pyx_v_out1));
+  __Pyx_GIVEREF(((PyObject *)__pyx_v_out1));
+  __Pyx_INCREF(((PyObject *)__pyx_v_out2));
+  PyTuple_SET_ITEM(__pyx_t_4, 1, ((PyObject *)__pyx_v_out2));
+  __Pyx_GIVEREF(((PyObject *)__pyx_v_out2));
+  __pyx_r = ((PyObject *)__pyx_t_4);
+  __pyx_t_4 = 0;
+  goto __pyx_L0;
+
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_XDECREF(__pyx_t_5);
+  __Pyx_XDECREF(__pyx_t_6);
+  { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;
+    __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_iy);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out1);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out2);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_ihr);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_imn);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_im);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_sec);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_id);
+  __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
+  __Pyx_AddTraceback("astropy.time.sofa_time.dtf_jd", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  goto __pyx_L2;
+  __pyx_L0:;
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_iy);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out1);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out2);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_ihr);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_imn);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_im);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_sec);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_id);
+  __pyx_L2:;
+  __Pyx_XDECREF((PyObject *)__pyx_v_out1);
+  __Pyx_XDECREF((PyObject *)__pyx_v_out2);
+  __Pyx_XDECREF(__pyx_v_warns);
+  __Pyx_XDECREF(__pyx_v_errs);
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "astropy/time/sofa_time.pyx":387
+ * @cython.wraparound(False)
+ * @cython.boundscheck(False)
+ * def tai_tt(             # <<<<<<<<<<<<<<
+ *     np.ndarray[double, ndim=1] in1,
+ *     np.ndarray[double, ndim=1] in2):
+ */
+
+static PyObject *__pyx_pf_7astropy_4time_9sofa_time_5tai_tt(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_7astropy_4time_9sofa_time_5tai_tt[] = "\n    int iauTaitt(double tai1, double tai2, double *tt1, double *tt2)\n\n    **  Given:\n    **     tai1,tai2  double    TAI as a 2-part Julian Date\n    **\n    **  Returned:\n    **     tt1,tt2    double    TT as a 2-part Julian Date\n    **\n    **  Returned (function value):\n    **                int       status:  0 = OK\n    **\n    **  Note:\n    **\n    **     tai1+tai2 is Julian Date, apportioned in any convenient way\n    **     between the two arguments, for example where tai1 is the Julian\n    **     Day Number and tai2 is the fraction of a day.  The returned\n    **     tt1,tt2 follow suit.\n    ";
+static PyMethodDef __pyx_mdef_7astropy_4time_9sofa_time_5tai_tt = {__Pyx_NAMESTR("tai_tt"), (PyCFunction)__pyx_pf_7astropy_4time_9sofa_time_5tai_tt, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(__pyx_doc_7astropy_4time_9sofa_time_5tai_tt)};
+static PyObject *__pyx_pf_7astropy_4time_9sofa_time_5tai_tt(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyArrayObject *__pyx_v_in1 = 0;
+  PyArrayObject *__pyx_v_in2 = 0;
+  unsigned int __pyx_v_n;
+  unsigned int __pyx_v_i;
+  PyArrayObject *__pyx_v_out1 = 0;
+  PyArrayObject *__pyx_v_out2 = 0;
+  int __pyx_v_ret;
+  Py_buffer __pyx_bstruct_out1;
+  Py_ssize_t __pyx_bstride_0_out1 = 0;
+  Py_ssize_t __pyx_bshape_0_out1 = 0;
+  Py_buffer __pyx_bstruct_out2;
+  Py_ssize_t __pyx_bstride_0_out2 = 0;
+  Py_ssize_t __pyx_bshape_0_out2 = 0;
+  Py_buffer __pyx_bstruct_in1;
+  Py_ssize_t __pyx_bstride_0_in1 = 0;
+  Py_ssize_t __pyx_bshape_0_in1 = 0;
+  Py_buffer __pyx_bstruct_in2;
+  Py_ssize_t __pyx_bstride_0_in2 = 0;
+  Py_ssize_t __pyx_bshape_0_in2 = 0;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
+  PyObject *__pyx_t_5 = NULL;
+  PyArrayObject *__pyx_t_6 = NULL;
+  PyArrayObject *__pyx_t_7 = NULL;
+  unsigned int __pyx_t_8;
+  unsigned int __pyx_t_9;
+  unsigned int __pyx_t_10;
+  unsigned int __pyx_t_11;
+  unsigned int __pyx_t_12;
+  unsigned int __pyx_t_13;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__in1,&__pyx_n_s__in2,0};
+  __Pyx_RefNannySetupContext("tai_tt");
+  __pyx_self = __pyx_self;
+  {
+    PyObject* values[2] = {0,0};
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  0:
+        values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__in1);
+        if (likely(values[0])) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+        case  1:
+        values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__in2);
+        if (likely(values[1])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("tai_tt", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 387; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "tai_tt") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 387; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+    } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
+      goto __pyx_L5_argtuple_error;
+    } else {
+      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+    }
+    __pyx_v_in1 = ((PyArrayObject *)values[0]);
+    __pyx_v_in2 = ((PyArrayObject *)values[1]);
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("tai_tt", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 387; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("astropy.time.sofa_time.tai_tt", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_bstruct_out1.buf = NULL;
+  __pyx_bstruct_out2.buf = NULL;
+  __pyx_bstruct_in1.buf = NULL;
+  __pyx_bstruct_in2.buf = NULL;
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_in1), __pyx_ptype_5numpy_ndarray, 1, "in1", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 388; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_in2), __pyx_ptype_5numpy_ndarray, 1, "in2", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 389; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_in1, (PyObject*)__pyx_v_in1, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 387; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_in1 = __pyx_bstruct_in1.strides[0];
+  __pyx_bshape_0_in1 = __pyx_bstruct_in1.shape[0];
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_in2, (PyObject*)__pyx_v_in2, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 387; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_in2 = __pyx_bstruct_in2.strides[0];
+  __pyx_bshape_0_in2 = __pyx_bstruct_in2.shape[0];
+
+  /* "astropy/time/sofa_time.pyx":409
+ *     **     tt1,tt2 follow suit.
+ *     """
+ *     assert in1.shape[0] == in2.shape[0]             # <<<<<<<<<<<<<<
+ *     cdef unsigned n = in1.shape[0]
+ *     cdef unsigned int i
+ */
+  #ifndef CYTHON_WITHOUT_ASSERTIONS
+  if (unlikely(!((__pyx_v_in1->dimensions[0]) == (__pyx_v_in2->dimensions[0])))) {
+    PyErr_SetNone(PyExc_AssertionError);
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 409; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  #endif
+
+  /* "astropy/time/sofa_time.pyx":410
+ *     """
+ *     assert in1.shape[0] == in2.shape[0]
+ *     cdef unsigned n = in1.shape[0]             # <<<<<<<<<<<<<<
+ *     cdef unsigned int i
+ *     cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)
+ */
+  __pyx_v_n = (__pyx_v_in1->dimensions[0]);
+
+  /* "astropy/time/sofa_time.pyx":412
+ *     cdef unsigned n = in1.shape[0]
+ *     cdef unsigned int i
+ *     cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)             # <<<<<<<<<<<<<<
+ *     cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)
+ * 
+ */
+  __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 412; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_2 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s__empty); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 412; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __pyx_t_1 = PyLong_FromUnsignedLong(__pyx_v_n); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 412; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 412; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_3));
+  PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_1);
+  __Pyx_GIVEREF(__pyx_t_1);
+  __pyx_t_1 = 0;
+  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 412; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_1));
+  __pyx_t_4 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 412; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_4);
+  __pyx_t_5 = PyObject_GetAttr(__pyx_t_4, __pyx_n_s__double); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 412; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_n_s__dtype), __pyx_t_5) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 412; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  __pyx_t_5 = PyEval_CallObjectWithKeywords(__pyx_t_2, ((PyObject *)__pyx_t_3), ((PyObject *)__pyx_t_1)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 412; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
+  if (!(likely(((__pyx_t_5) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_5, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 412; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_6 = ((PyArrayObject *)__pyx_t_5);
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_out1, (PyObject*)__pyx_t_6, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {
+      __pyx_v_out1 = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_out1.buf = NULL;
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 412; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    } else {__pyx_bstride_0_out1 = __pyx_bstruct_out1.strides[0];
+      __pyx_bshape_0_out1 = __pyx_bstruct_out1.shape[0];
+    }
+  }
+  __pyx_t_6 = 0;
+  __pyx_v_out1 = ((PyArrayObject *)__pyx_t_5);
+  __pyx_t_5 = 0;
+
+  /* "astropy/time/sofa_time.pyx":413
+ *     cdef unsigned int i
+ *     cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)
+ *     cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)             # <<<<<<<<<<<<<<
+ * 
+ *     for i in range(n):
+ */
+  __pyx_t_5 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 413; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __pyx_t_1 = PyObject_GetAttr(__pyx_t_5, __pyx_n_s__empty); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 413; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  __pyx_t_5 = PyLong_FromUnsignedLong(__pyx_v_n); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 413; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 413; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_3));
+  PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_5);
+  __Pyx_GIVEREF(__pyx_t_5);
+  __pyx_t_5 = 0;
+  __pyx_t_5 = PyDict_New(); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 413; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_5));
+  __pyx_t_2 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 413; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_4 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s__double); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 413; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_4);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  if (PyDict_SetItem(__pyx_t_5, ((PyObject *)__pyx_n_s__dtype), __pyx_t_4) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 413; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  __pyx_t_4 = PyEval_CallObjectWithKeywords(__pyx_t_1, ((PyObject *)__pyx_t_3), ((PyObject *)__pyx_t_5)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 413; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_4);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_5)); __pyx_t_5 = 0;
+  if (!(likely(((__pyx_t_4) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_4, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 413; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_7 = ((PyArrayObject *)__pyx_t_4);
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_out2, (PyObject*)__pyx_t_7, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {
+      __pyx_v_out2 = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_out2.buf = NULL;
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 413; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    } else {__pyx_bstride_0_out2 = __pyx_bstruct_out2.strides[0];
+      __pyx_bshape_0_out2 = __pyx_bstruct_out2.shape[0];
+    }
+  }
+  __pyx_t_7 = 0;
+  __pyx_v_out2 = ((PyArrayObject *)__pyx_t_4);
+  __pyx_t_4 = 0;
+
+  /* "astropy/time/sofa_time.pyx":415
+ *     cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)
+ * 
+ *     for i in range(n):             # <<<<<<<<<<<<<<
+ *         ret = iauTaitt(in1[i], in2[i], &out1[i], &out2[i])
+ *         check_return(ret, 'iauTaitt')
+ */
+  __pyx_t_8 = __pyx_v_n;
+  for (__pyx_t_9 = 0; __pyx_t_9 < __pyx_t_8; __pyx_t_9+=1) {
+    __pyx_v_i = __pyx_t_9;
+
+    /* "astropy/time/sofa_time.pyx":416
+ * 
+ *     for i in range(n):
+ *         ret = iauTaitt(in1[i], in2[i], &out1[i], &out2[i])             # <<<<<<<<<<<<<<
+ *         check_return(ret, 'iauTaitt')
+ * 
+ */
+    __pyx_t_10 = __pyx_v_i;
+    __pyx_t_11 = __pyx_v_i;
+    __pyx_t_12 = __pyx_v_i;
+    __pyx_t_13 = __pyx_v_i;
+    __pyx_v_ret = iauTaitt((*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_in1.buf, __pyx_t_10, __pyx_bstride_0_in1)), (*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_in2.buf, __pyx_t_11, __pyx_bstride_0_in2)), (&(*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_out1.buf, __pyx_t_12, __pyx_bstride_0_out1))), (&(*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_out2.buf, __pyx_t_13, __pyx_bstride_0_out2))));
+
+    /* "astropy/time/sofa_time.pyx":417
+ *     for i in range(n):
+ *         ret = iauTaitt(in1[i], in2[i], &out1[i], &out2[i])
+ *         check_return(ret, 'iauTaitt')             # <<<<<<<<<<<<<<
+ * 
+ *     return out1, out2
+ */
+    __pyx_t_4 = __Pyx_GetName(__pyx_m, __pyx_n_s__check_return); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 417; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_4);
+    __pyx_t_5 = PyInt_FromLong(__pyx_v_ret); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 417; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_5);
+    __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 417; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(((PyObject *)__pyx_t_3));
+    PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_5);
+    __Pyx_GIVEREF(__pyx_t_5);
+    __Pyx_INCREF(((PyObject *)__pyx_n_s__iauTaitt));
+    PyTuple_SET_ITEM(__pyx_t_3, 1, ((PyObject *)__pyx_n_s__iauTaitt));
+    __Pyx_GIVEREF(((PyObject *)__pyx_n_s__iauTaitt));
+    __pyx_t_5 = 0;
+    __pyx_t_5 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 417; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_5);
+    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+    __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
+    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  }
+
+  /* "astropy/time/sofa_time.pyx":419
+ *         check_return(ret, 'iauTaitt')
+ * 
+ *     return out1, out2             # <<<<<<<<<<<<<<
+ * 
+ * 
+ */
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_t_5 = PyTuple_New(2); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 419; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_5));
+  __Pyx_INCREF(((PyObject *)__pyx_v_out1));
+  PyTuple_SET_ITEM(__pyx_t_5, 0, ((PyObject *)__pyx_v_out1));
+  __Pyx_GIVEREF(((PyObject *)__pyx_v_out1));
+  __Pyx_INCREF(((PyObject *)__pyx_v_out2));
+  PyTuple_SET_ITEM(__pyx_t_5, 1, ((PyObject *)__pyx_v_out2));
+  __Pyx_GIVEREF(((PyObject *)__pyx_v_out2));
+  __pyx_r = ((PyObject *)__pyx_t_5);
+  __pyx_t_5 = 0;
+  goto __pyx_L0;
+
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_XDECREF(__pyx_t_5);
+  { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;
+    __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out1);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out2);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in1);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in2);
+  __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
+  __Pyx_AddTraceback("astropy.time.sofa_time.tai_tt", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  goto __pyx_L2;
+  __pyx_L0:;
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out1);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out2);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in1);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in2);
+  __pyx_L2:;
+  __Pyx_XDECREF((PyObject *)__pyx_v_out1);
+  __Pyx_XDECREF((PyObject *)__pyx_v_out2);
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "astropy/time/sofa_time.pyx":424
+ * @cython.wraparound(False)
+ * @cython.boundscheck(False)
+ * def tcb_tdb(             # <<<<<<<<<<<<<<
+ *     np.ndarray[double, ndim=1] in1,
+ *     np.ndarray[double, ndim=1] in2):
+ */
+
+static PyObject *__pyx_pf_7astropy_4time_9sofa_time_6tcb_tdb(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_7astropy_4time_9sofa_time_6tcb_tdb[] = "\n    int iauTcbtdb(double tcb1, double tcb2, double *tdb1, double *tdb2)\n\n    **  Given:\n    **     tcb1,tcb2  double    TCB as a 2-part Julian Date\n    **\n    **  Returned:\n    **     tdb1,tdb2  double    TDB as a 2-part Julian Date\n    **\n    **  Returned (function value):\n    **                int       status:  0 = OK\n    **\n    **  Notes:\n    **\n    **  1) tcb1+tcb2 is Julian Date, apportioned in any convenient way\n    **     between the two arguments, for example where tcb1 is the Julian\n    **     Day Number and tcb2 is the fraction of a day.  The returned\n    **     tdb1,tdb2 follow suit.\n    **\n    **  2) The 2006 IAU General Assembly introduced a conventional linear\n    **     transformation between TDB and TCB.  This transformation\n    **     compensates for the drift between TCB and terrestrial time TT,\n    **     and keeps TDB approximately centered on TT.  Because the\n    **     relationship between TT and TCB depends on the adopted solar\n    **     system ephemeris, the degree of alignment between TDB and TT over\n    **     long intervals will vary according to which ephemeris is used.\n    **     Former definitions of TDB attempted to avoid this problem by\n    **     stipulating that TDB and TT should differ only by periodic\n    **     effects.  This is a good description of the nature of the\n    **     relationship but eluded precise mathematical formulation.  The\n    **     conventional linear relationship adopted in 2006 sidestepped\n    **     these difficulties whilst delivering a TDB that in practice was\n    **     consistent with values before that date.\n    **\n    **  3) TDB is essentially the same as Teph, the time argument for the\n    **     JPL solar system ephemerides.\n    ";
+static PyMethodDef __pyx_mdef_7astropy_4time_9sofa_time_6tcb_tdb = {__Pyx_NAMESTR("tcb_tdb"), (PyCFunction)__pyx_pf_7astropy_4time_9sofa_time_6tcb_tdb, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(__pyx_doc_7astropy_4time_9sofa_time_6tcb_tdb)};
+static PyObject *__pyx_pf_7astropy_4time_9sofa_time_6tcb_tdb(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyArrayObject *__pyx_v_in1 = 0;
+  PyArrayObject *__pyx_v_in2 = 0;
+  unsigned int __pyx_v_n;
+  unsigned int __pyx_v_i;
+  PyArrayObject *__pyx_v_out1 = 0;
+  PyArrayObject *__pyx_v_out2 = 0;
+  int __pyx_v_ret;
+  Py_buffer __pyx_bstruct_out1;
+  Py_ssize_t __pyx_bstride_0_out1 = 0;
+  Py_ssize_t __pyx_bshape_0_out1 = 0;
+  Py_buffer __pyx_bstruct_out2;
+  Py_ssize_t __pyx_bstride_0_out2 = 0;
+  Py_ssize_t __pyx_bshape_0_out2 = 0;
+  Py_buffer __pyx_bstruct_in1;
+  Py_ssize_t __pyx_bstride_0_in1 = 0;
+  Py_ssize_t __pyx_bshape_0_in1 = 0;
+  Py_buffer __pyx_bstruct_in2;
+  Py_ssize_t __pyx_bstride_0_in2 = 0;
+  Py_ssize_t __pyx_bshape_0_in2 = 0;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
+  PyObject *__pyx_t_5 = NULL;
+  PyArrayObject *__pyx_t_6 = NULL;
+  PyArrayObject *__pyx_t_7 = NULL;
+  unsigned int __pyx_t_8;
+  unsigned int __pyx_t_9;
+  unsigned int __pyx_t_10;
+  unsigned int __pyx_t_11;
+  unsigned int __pyx_t_12;
+  unsigned int __pyx_t_13;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__in1,&__pyx_n_s__in2,0};
+  __Pyx_RefNannySetupContext("tcb_tdb");
+  __pyx_self = __pyx_self;
+  {
+    PyObject* values[2] = {0,0};
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  0:
+        values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__in1);
+        if (likely(values[0])) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+        case  1:
+        values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__in2);
+        if (likely(values[1])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("tcb_tdb", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 424; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "tcb_tdb") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 424; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+    } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
+      goto __pyx_L5_argtuple_error;
+    } else {
+      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+    }
+    __pyx_v_in1 = ((PyArrayObject *)values[0]);
+    __pyx_v_in2 = ((PyArrayObject *)values[1]);
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("tcb_tdb", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 424; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("astropy.time.sofa_time.tcb_tdb", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_bstruct_out1.buf = NULL;
+  __pyx_bstruct_out2.buf = NULL;
+  __pyx_bstruct_in1.buf = NULL;
+  __pyx_bstruct_in2.buf = NULL;
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_in1), __pyx_ptype_5numpy_ndarray, 1, "in1", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 425; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_in2), __pyx_ptype_5numpy_ndarray, 1, "in2", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 426; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_in1, (PyObject*)__pyx_v_in1, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 424; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_in1 = __pyx_bstruct_in1.strides[0];
+  __pyx_bshape_0_in1 = __pyx_bstruct_in1.shape[0];
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_in2, (PyObject*)__pyx_v_in2, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 424; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_in2 = __pyx_bstruct_in2.strides[0];
+  __pyx_bshape_0_in2 = __pyx_bstruct_in2.shape[0];
+
+  /* "astropy/time/sofa_time.pyx":465
+ *     """
+ * 
+ *     assert in1.shape[0] == in2.shape[0]             # <<<<<<<<<<<<<<
+ *     cdef unsigned n = in1.shape[0]
+ *     cdef unsigned int i
+ */
+  #ifndef CYTHON_WITHOUT_ASSERTIONS
+  if (unlikely(!((__pyx_v_in1->dimensions[0]) == (__pyx_v_in2->dimensions[0])))) {
+    PyErr_SetNone(PyExc_AssertionError);
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 465; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  #endif
+
+  /* "astropy/time/sofa_time.pyx":466
+ * 
+ *     assert in1.shape[0] == in2.shape[0]
+ *     cdef unsigned n = in1.shape[0]             # <<<<<<<<<<<<<<
+ *     cdef unsigned int i
+ *     cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)
+ */
+  __pyx_v_n = (__pyx_v_in1->dimensions[0]);
+
+  /* "astropy/time/sofa_time.pyx":468
+ *     cdef unsigned n = in1.shape[0]
+ *     cdef unsigned int i
+ *     cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)             # <<<<<<<<<<<<<<
+ *     cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)
+ * 
+ */
+  __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 468; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_2 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s__empty); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 468; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __pyx_t_1 = PyLong_FromUnsignedLong(__pyx_v_n); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 468; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 468; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_3));
+  PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_1);
+  __Pyx_GIVEREF(__pyx_t_1);
+  __pyx_t_1 = 0;
+  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 468; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_1));
+  __pyx_t_4 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 468; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_4);
+  __pyx_t_5 = PyObject_GetAttr(__pyx_t_4, __pyx_n_s__double); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 468; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_n_s__dtype), __pyx_t_5) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 468; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  __pyx_t_5 = PyEval_CallObjectWithKeywords(__pyx_t_2, ((PyObject *)__pyx_t_3), ((PyObject *)__pyx_t_1)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 468; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
+  if (!(likely(((__pyx_t_5) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_5, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 468; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_6 = ((PyArrayObject *)__pyx_t_5);
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_out1, (PyObject*)__pyx_t_6, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {
+      __pyx_v_out1 = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_out1.buf = NULL;
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 468; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    } else {__pyx_bstride_0_out1 = __pyx_bstruct_out1.strides[0];
+      __pyx_bshape_0_out1 = __pyx_bstruct_out1.shape[0];
+    }
+  }
+  __pyx_t_6 = 0;
+  __pyx_v_out1 = ((PyArrayObject *)__pyx_t_5);
+  __pyx_t_5 = 0;
+
+  /* "astropy/time/sofa_time.pyx":469
+ *     cdef unsigned int i
+ *     cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)
+ *     cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)             # <<<<<<<<<<<<<<
+ * 
+ *     for i in range(n):
+ */
+  __pyx_t_5 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 469; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __pyx_t_1 = PyObject_GetAttr(__pyx_t_5, __pyx_n_s__empty); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 469; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  __pyx_t_5 = PyLong_FromUnsignedLong(__pyx_v_n); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 469; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 469; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_3));
+  PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_5);
+  __Pyx_GIVEREF(__pyx_t_5);
+  __pyx_t_5 = 0;
+  __pyx_t_5 = PyDict_New(); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 469; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_5));
+  __pyx_t_2 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 469; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_4 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s__double); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 469; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_4);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  if (PyDict_SetItem(__pyx_t_5, ((PyObject *)__pyx_n_s__dtype), __pyx_t_4) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 469; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  __pyx_t_4 = PyEval_CallObjectWithKeywords(__pyx_t_1, ((PyObject *)__pyx_t_3), ((PyObject *)__pyx_t_5)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 469; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_4);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_5)); __pyx_t_5 = 0;
+  if (!(likely(((__pyx_t_4) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_4, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 469; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_7 = ((PyArrayObject *)__pyx_t_4);
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_out2, (PyObject*)__pyx_t_7, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {
+      __pyx_v_out2 = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_out2.buf = NULL;
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 469; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    } else {__pyx_bstride_0_out2 = __pyx_bstruct_out2.strides[0];
+      __pyx_bshape_0_out2 = __pyx_bstruct_out2.shape[0];
+    }
+  }
+  __pyx_t_7 = 0;
+  __pyx_v_out2 = ((PyArrayObject *)__pyx_t_4);
+  __pyx_t_4 = 0;
+
+  /* "astropy/time/sofa_time.pyx":471
+ *     cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)
+ * 
+ *     for i in range(n):             # <<<<<<<<<<<<<<
+ *         ret = iauTcbtdb(in1[i], in2[i], &out1[i], &out2[i])
+ *         check_return(ret, 'iauTcbtdb')
+ */
+  __pyx_t_8 = __pyx_v_n;
+  for (__pyx_t_9 = 0; __pyx_t_9 < __pyx_t_8; __pyx_t_9+=1) {
+    __pyx_v_i = __pyx_t_9;
+
+    /* "astropy/time/sofa_time.pyx":472
+ * 
+ *     for i in range(n):
+ *         ret = iauTcbtdb(in1[i], in2[i], &out1[i], &out2[i])             # <<<<<<<<<<<<<<
+ *         check_return(ret, 'iauTcbtdb')
+ * 
+ */
+    __pyx_t_10 = __pyx_v_i;
+    __pyx_t_11 = __pyx_v_i;
+    __pyx_t_12 = __pyx_v_i;
+    __pyx_t_13 = __pyx_v_i;
+    __pyx_v_ret = iauTcbtdb((*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_in1.buf, __pyx_t_10, __pyx_bstride_0_in1)), (*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_in2.buf, __pyx_t_11, __pyx_bstride_0_in2)), (&(*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_out1.buf, __pyx_t_12, __pyx_bstride_0_out1))), (&(*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_out2.buf, __pyx_t_13, __pyx_bstride_0_out2))));
+
+    /* "astropy/time/sofa_time.pyx":473
+ *     for i in range(n):
+ *         ret = iauTcbtdb(in1[i], in2[i], &out1[i], &out2[i])
+ *         check_return(ret, 'iauTcbtdb')             # <<<<<<<<<<<<<<
+ * 
+ *     return out1, out2
+ */
+    __pyx_t_4 = __Pyx_GetName(__pyx_m, __pyx_n_s__check_return); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 473; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_4);
+    __pyx_t_5 = PyInt_FromLong(__pyx_v_ret); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 473; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_5);
+    __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 473; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(((PyObject *)__pyx_t_3));
+    PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_5);
+    __Pyx_GIVEREF(__pyx_t_5);
+    __Pyx_INCREF(((PyObject *)__pyx_n_s__iauTcbtdb));
+    PyTuple_SET_ITEM(__pyx_t_3, 1, ((PyObject *)__pyx_n_s__iauTcbtdb));
+    __Pyx_GIVEREF(((PyObject *)__pyx_n_s__iauTcbtdb));
+    __pyx_t_5 = 0;
+    __pyx_t_5 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 473; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_5);
+    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+    __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
+    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  }
+
+  /* "astropy/time/sofa_time.pyx":475
+ *         check_return(ret, 'iauTcbtdb')
+ * 
+ *     return out1, out2             # <<<<<<<<<<<<<<
+ * 
+ * 
+ */
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_t_5 = PyTuple_New(2); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 475; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_5));
+  __Pyx_INCREF(((PyObject *)__pyx_v_out1));
+  PyTuple_SET_ITEM(__pyx_t_5, 0, ((PyObject *)__pyx_v_out1));
+  __Pyx_GIVEREF(((PyObject *)__pyx_v_out1));
+  __Pyx_INCREF(((PyObject *)__pyx_v_out2));
+  PyTuple_SET_ITEM(__pyx_t_5, 1, ((PyObject *)__pyx_v_out2));
+  __Pyx_GIVEREF(((PyObject *)__pyx_v_out2));
+  __pyx_r = ((PyObject *)__pyx_t_5);
+  __pyx_t_5 = 0;
+  goto __pyx_L0;
+
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_XDECREF(__pyx_t_5);
+  { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;
+    __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out1);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out2);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in1);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in2);
+  __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
+  __Pyx_AddTraceback("astropy.time.sofa_time.tcb_tdb", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  goto __pyx_L2;
+  __pyx_L0:;
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out1);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out2);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in1);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in2);
+  __pyx_L2:;
+  __Pyx_XDECREF((PyObject *)__pyx_v_out1);
+  __Pyx_XDECREF((PyObject *)__pyx_v_out2);
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "astropy/time/sofa_time.pyx":480
+ * @cython.wraparound(False)
+ * @cython.boundscheck(False)
+ * def tcg_tt(             # <<<<<<<<<<<<<<
+ *     np.ndarray[double, ndim=1] in1,
+ *     np.ndarray[double, ndim=1] in2):
+ */
+
+static PyObject *__pyx_pf_7astropy_4time_9sofa_time_7tcg_tt(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_7astropy_4time_9sofa_time_7tcg_tt[] = "\n   int iauTcgtt(double tcg1, double tcg2, double *tt1, double *tt2)\n\n   **  Given:\n   **     tcg1,tcg2  double    TCG as a 2-part Julian Date\n   **\n   **  Returned:\n   **     tt1,tt2    double    TT as a 2-part Julian Date\n   **\n   **  Returned (function value):\n   **                int       status:  0 = OK\n    ";
+static PyMethodDef __pyx_mdef_7astropy_4time_9sofa_time_7tcg_tt = {__Pyx_NAMESTR("tcg_tt"), (PyCFunction)__pyx_pf_7astropy_4time_9sofa_time_7tcg_tt, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(__pyx_doc_7astropy_4time_9sofa_time_7tcg_tt)};
+static PyObject *__pyx_pf_7astropy_4time_9sofa_time_7tcg_tt(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyArrayObject *__pyx_v_in1 = 0;
+  PyArrayObject *__pyx_v_in2 = 0;
+  unsigned int __pyx_v_n;
+  unsigned int __pyx_v_i;
+  PyArrayObject *__pyx_v_out1 = 0;
+  PyArrayObject *__pyx_v_out2 = 0;
+  int __pyx_v_ret;
+  Py_buffer __pyx_bstruct_out1;
+  Py_ssize_t __pyx_bstride_0_out1 = 0;
+  Py_ssize_t __pyx_bshape_0_out1 = 0;
+  Py_buffer __pyx_bstruct_out2;
+  Py_ssize_t __pyx_bstride_0_out2 = 0;
+  Py_ssize_t __pyx_bshape_0_out2 = 0;
+  Py_buffer __pyx_bstruct_in1;
+  Py_ssize_t __pyx_bstride_0_in1 = 0;
+  Py_ssize_t __pyx_bshape_0_in1 = 0;
+  Py_buffer __pyx_bstruct_in2;
+  Py_ssize_t __pyx_bstride_0_in2 = 0;
+  Py_ssize_t __pyx_bshape_0_in2 = 0;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
+  PyObject *__pyx_t_5 = NULL;
+  PyArrayObject *__pyx_t_6 = NULL;
+  PyArrayObject *__pyx_t_7 = NULL;
+  unsigned int __pyx_t_8;
+  unsigned int __pyx_t_9;
+  unsigned int __pyx_t_10;
+  unsigned int __pyx_t_11;
+  unsigned int __pyx_t_12;
+  unsigned int __pyx_t_13;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__in1,&__pyx_n_s__in2,0};
+  __Pyx_RefNannySetupContext("tcg_tt");
+  __pyx_self = __pyx_self;
+  {
+    PyObject* values[2] = {0,0};
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  0:
+        values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__in1);
+        if (likely(values[0])) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+        case  1:
+        values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__in2);
+        if (likely(values[1])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("tcg_tt", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 480; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "tcg_tt") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 480; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+    } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
+      goto __pyx_L5_argtuple_error;
+    } else {
+      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+    }
+    __pyx_v_in1 = ((PyArrayObject *)values[0]);
+    __pyx_v_in2 = ((PyArrayObject *)values[1]);
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("tcg_tt", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 480; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("astropy.time.sofa_time.tcg_tt", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_bstruct_out1.buf = NULL;
+  __pyx_bstruct_out2.buf = NULL;
+  __pyx_bstruct_in1.buf = NULL;
+  __pyx_bstruct_in2.buf = NULL;
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_in1), __pyx_ptype_5numpy_ndarray, 1, "in1", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 481; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_in2), __pyx_ptype_5numpy_ndarray, 1, "in2", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 482; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_in1, (PyObject*)__pyx_v_in1, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 480; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_in1 = __pyx_bstruct_in1.strides[0];
+  __pyx_bshape_0_in1 = __pyx_bstruct_in1.shape[0];
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_in2, (PyObject*)__pyx_v_in2, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 480; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_in2 = __pyx_bstruct_in2.strides[0];
+  __pyx_bshape_0_in2 = __pyx_bstruct_in2.shape[0];
+
+  /* "astropy/time/sofa_time.pyx":496
+ *     """
+ * 
+ *     assert in1.shape[0] == in2.shape[0]             # <<<<<<<<<<<<<<
+ *     cdef unsigned n = in1.shape[0]
+ *     cdef unsigned int i
+ */
+  #ifndef CYTHON_WITHOUT_ASSERTIONS
+  if (unlikely(!((__pyx_v_in1->dimensions[0]) == (__pyx_v_in2->dimensions[0])))) {
+    PyErr_SetNone(PyExc_AssertionError);
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 496; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  #endif
+
+  /* "astropy/time/sofa_time.pyx":497
+ * 
+ *     assert in1.shape[0] == in2.shape[0]
+ *     cdef unsigned n = in1.shape[0]             # <<<<<<<<<<<<<<
+ *     cdef unsigned int i
+ *     cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)
+ */
+  __pyx_v_n = (__pyx_v_in1->dimensions[0]);
+
+  /* "astropy/time/sofa_time.pyx":499
+ *     cdef unsigned n = in1.shape[0]
+ *     cdef unsigned int i
+ *     cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)             # <<<<<<<<<<<<<<
+ *     cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)
+ * 
+ */
+  __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 499; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_2 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s__empty); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 499; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __pyx_t_1 = PyLong_FromUnsignedLong(__pyx_v_n); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 499; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 499; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_3));
+  PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_1);
+  __Pyx_GIVEREF(__pyx_t_1);
+  __pyx_t_1 = 0;
+  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 499; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_1));
+  __pyx_t_4 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 499; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_4);
+  __pyx_t_5 = PyObject_GetAttr(__pyx_t_4, __pyx_n_s__double); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 499; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_n_s__dtype), __pyx_t_5) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 499; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  __pyx_t_5 = PyEval_CallObjectWithKeywords(__pyx_t_2, ((PyObject *)__pyx_t_3), ((PyObject *)__pyx_t_1)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 499; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
+  if (!(likely(((__pyx_t_5) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_5, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 499; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_6 = ((PyArrayObject *)__pyx_t_5);
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_out1, (PyObject*)__pyx_t_6, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {
+      __pyx_v_out1 = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_out1.buf = NULL;
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 499; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    } else {__pyx_bstride_0_out1 = __pyx_bstruct_out1.strides[0];
+      __pyx_bshape_0_out1 = __pyx_bstruct_out1.shape[0];
+    }
+  }
+  __pyx_t_6 = 0;
+  __pyx_v_out1 = ((PyArrayObject *)__pyx_t_5);
+  __pyx_t_5 = 0;
+
+  /* "astropy/time/sofa_time.pyx":500
+ *     cdef unsigned int i
+ *     cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)
+ *     cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)             # <<<<<<<<<<<<<<
+ * 
+ *     for i in range(n):
+ */
+  __pyx_t_5 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 500; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __pyx_t_1 = PyObject_GetAttr(__pyx_t_5, __pyx_n_s__empty); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 500; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  __pyx_t_5 = PyLong_FromUnsignedLong(__pyx_v_n); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 500; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 500; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_3));
+  PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_5);
+  __Pyx_GIVEREF(__pyx_t_5);
+  __pyx_t_5 = 0;
+  __pyx_t_5 = PyDict_New(); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 500; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_5));
+  __pyx_t_2 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 500; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_4 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s__double); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 500; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_4);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  if (PyDict_SetItem(__pyx_t_5, ((PyObject *)__pyx_n_s__dtype), __pyx_t_4) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 500; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  __pyx_t_4 = PyEval_CallObjectWithKeywords(__pyx_t_1, ((PyObject *)__pyx_t_3), ((PyObject *)__pyx_t_5)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 500; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_4);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_5)); __pyx_t_5 = 0;
+  if (!(likely(((__pyx_t_4) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_4, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 500; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_7 = ((PyArrayObject *)__pyx_t_4);
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_out2, (PyObject*)__pyx_t_7, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {
+      __pyx_v_out2 = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_out2.buf = NULL;
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 500; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    } else {__pyx_bstride_0_out2 = __pyx_bstruct_out2.strides[0];
+      __pyx_bshape_0_out2 = __pyx_bstruct_out2.shape[0];
+    }
+  }
+  __pyx_t_7 = 0;
+  __pyx_v_out2 = ((PyArrayObject *)__pyx_t_4);
+  __pyx_t_4 = 0;
+
+  /* "astropy/time/sofa_time.pyx":502
+ *     cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)
+ * 
+ *     for i in range(n):             # <<<<<<<<<<<<<<
+ *         ret = iauTcgtt(in1[i], in2[i], &out1[i], &out2[i])
+ *         check_return(ret, 'iauTcgtt')
+ */
+  __pyx_t_8 = __pyx_v_n;
+  for (__pyx_t_9 = 0; __pyx_t_9 < __pyx_t_8; __pyx_t_9+=1) {
+    __pyx_v_i = __pyx_t_9;
+
+    /* "astropy/time/sofa_time.pyx":503
+ * 
+ *     for i in range(n):
+ *         ret = iauTcgtt(in1[i], in2[i], &out1[i], &out2[i])             # <<<<<<<<<<<<<<
+ *         check_return(ret, 'iauTcgtt')
+ * 
+ */
+    __pyx_t_10 = __pyx_v_i;
+    __pyx_t_11 = __pyx_v_i;
+    __pyx_t_12 = __pyx_v_i;
+    __pyx_t_13 = __pyx_v_i;
+    __pyx_v_ret = iauTcgtt((*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_in1.buf, __pyx_t_10, __pyx_bstride_0_in1)), (*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_in2.buf, __pyx_t_11, __pyx_bstride_0_in2)), (&(*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_out1.buf, __pyx_t_12, __pyx_bstride_0_out1))), (&(*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_out2.buf, __pyx_t_13, __pyx_bstride_0_out2))));
+
+    /* "astropy/time/sofa_time.pyx":504
+ *     for i in range(n):
+ *         ret = iauTcgtt(in1[i], in2[i], &out1[i], &out2[i])
+ *         check_return(ret, 'iauTcgtt')             # <<<<<<<<<<<<<<
+ * 
+ *     return out1, out2
+ */
+    __pyx_t_4 = __Pyx_GetName(__pyx_m, __pyx_n_s__check_return); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 504; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_4);
+    __pyx_t_5 = PyInt_FromLong(__pyx_v_ret); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 504; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_5);
+    __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 504; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(((PyObject *)__pyx_t_3));
+    PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_5);
+    __Pyx_GIVEREF(__pyx_t_5);
+    __Pyx_INCREF(((PyObject *)__pyx_n_s__iauTcgtt));
+    PyTuple_SET_ITEM(__pyx_t_3, 1, ((PyObject *)__pyx_n_s__iauTcgtt));
+    __Pyx_GIVEREF(((PyObject *)__pyx_n_s__iauTcgtt));
+    __pyx_t_5 = 0;
+    __pyx_t_5 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 504; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_5);
+    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+    __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
+    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  }
+
+  /* "astropy/time/sofa_time.pyx":506
+ *         check_return(ret, 'iauTcgtt')
+ * 
+ *     return out1, out2             # <<<<<<<<<<<<<<
+ * 
+ * 
+ */
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_t_5 = PyTuple_New(2); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 506; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_5));
+  __Pyx_INCREF(((PyObject *)__pyx_v_out1));
+  PyTuple_SET_ITEM(__pyx_t_5, 0, ((PyObject *)__pyx_v_out1));
+  __Pyx_GIVEREF(((PyObject *)__pyx_v_out1));
+  __Pyx_INCREF(((PyObject *)__pyx_v_out2));
+  PyTuple_SET_ITEM(__pyx_t_5, 1, ((PyObject *)__pyx_v_out2));
+  __Pyx_GIVEREF(((PyObject *)__pyx_v_out2));
+  __pyx_r = ((PyObject *)__pyx_t_5);
+  __pyx_t_5 = 0;
+  goto __pyx_L0;
+
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_XDECREF(__pyx_t_5);
+  { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;
+    __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out1);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out2);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in1);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in2);
+  __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
+  __Pyx_AddTraceback("astropy.time.sofa_time.tcg_tt", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  goto __pyx_L2;
+  __pyx_L0:;
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out1);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out2);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in1);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in2);
+  __pyx_L2:;
+  __Pyx_XDECREF((PyObject *)__pyx_v_out1);
+  __Pyx_XDECREF((PyObject *)__pyx_v_out2);
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "astropy/time/sofa_time.pyx":511
+ * @cython.wraparound(False)
+ * @cython.boundscheck(False)
+ * def tdb_tcb(             # <<<<<<<<<<<<<<
+ *     np.ndarray[double, ndim=1] in1,
+ *     np.ndarray[double, ndim=1] in2):
+ */
+
+static PyObject *__pyx_pf_7astropy_4time_9sofa_time_8tdb_tcb(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_7astropy_4time_9sofa_time_8tdb_tcb[] = "\n    int iauTdbtcb(double tdb1, double tdb2, double *tcb1, double *tcb2)\n\n    **  Given:\n    **     tdb1,tdb2  double    TDB as a 2-part Julian Date\n    **\n    **  Returned:\n    **     tcb1,tcb2  double    TCB as a 2-part Julian Date\n    **\n    **  Returned (function value):\n    **                int       status:  0 = OK\n    ";
+static PyMethodDef __pyx_mdef_7astropy_4time_9sofa_time_8tdb_tcb = {__Pyx_NAMESTR("tdb_tcb"), (PyCFunction)__pyx_pf_7astropy_4time_9sofa_time_8tdb_tcb, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(__pyx_doc_7astropy_4time_9sofa_time_8tdb_tcb)};
+static PyObject *__pyx_pf_7astropy_4time_9sofa_time_8tdb_tcb(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyArrayObject *__pyx_v_in1 = 0;
+  PyArrayObject *__pyx_v_in2 = 0;
+  unsigned int __pyx_v_n;
+  unsigned int __pyx_v_i;
+  PyArrayObject *__pyx_v_out1 = 0;
+  PyArrayObject *__pyx_v_out2 = 0;
+  int __pyx_v_ret;
+  Py_buffer __pyx_bstruct_out1;
+  Py_ssize_t __pyx_bstride_0_out1 = 0;
+  Py_ssize_t __pyx_bshape_0_out1 = 0;
+  Py_buffer __pyx_bstruct_out2;
+  Py_ssize_t __pyx_bstride_0_out2 = 0;
+  Py_ssize_t __pyx_bshape_0_out2 = 0;
+  Py_buffer __pyx_bstruct_in1;
+  Py_ssize_t __pyx_bstride_0_in1 = 0;
+  Py_ssize_t __pyx_bshape_0_in1 = 0;
+  Py_buffer __pyx_bstruct_in2;
+  Py_ssize_t __pyx_bstride_0_in2 = 0;
+  Py_ssize_t __pyx_bshape_0_in2 = 0;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
+  PyObject *__pyx_t_5 = NULL;
+  PyArrayObject *__pyx_t_6 = NULL;
+  PyArrayObject *__pyx_t_7 = NULL;
+  unsigned int __pyx_t_8;
+  unsigned int __pyx_t_9;
+  unsigned int __pyx_t_10;
+  unsigned int __pyx_t_11;
+  unsigned int __pyx_t_12;
+  unsigned int __pyx_t_13;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__in1,&__pyx_n_s__in2,0};
+  __Pyx_RefNannySetupContext("tdb_tcb");
+  __pyx_self = __pyx_self;
+  {
+    PyObject* values[2] = {0,0};
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  0:
+        values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__in1);
+        if (likely(values[0])) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+        case  1:
+        values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__in2);
+        if (likely(values[1])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("tdb_tcb", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 511; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "tdb_tcb") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 511; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+    } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
+      goto __pyx_L5_argtuple_error;
+    } else {
+      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+    }
+    __pyx_v_in1 = ((PyArrayObject *)values[0]);
+    __pyx_v_in2 = ((PyArrayObject *)values[1]);
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("tdb_tcb", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 511; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("astropy.time.sofa_time.tdb_tcb", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_bstruct_out1.buf = NULL;
+  __pyx_bstruct_out2.buf = NULL;
+  __pyx_bstruct_in1.buf = NULL;
+  __pyx_bstruct_in2.buf = NULL;
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_in1), __pyx_ptype_5numpy_ndarray, 1, "in1", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 512; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_in2), __pyx_ptype_5numpy_ndarray, 1, "in2", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 513; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_in1, (PyObject*)__pyx_v_in1, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 511; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_in1 = __pyx_bstruct_in1.strides[0];
+  __pyx_bshape_0_in1 = __pyx_bstruct_in1.shape[0];
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_in2, (PyObject*)__pyx_v_in2, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 511; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_in2 = __pyx_bstruct_in2.strides[0];
+  __pyx_bshape_0_in2 = __pyx_bstruct_in2.shape[0];
+
+  /* "astropy/time/sofa_time.pyx":526
+ *     **                int       status:  0 = OK
+ *     """
+ *     assert in1.shape[0] == in2.shape[0]             # <<<<<<<<<<<<<<
+ *     cdef unsigned n = in1.shape[0]
+ *     cdef unsigned int i
+ */
+  #ifndef CYTHON_WITHOUT_ASSERTIONS
+  if (unlikely(!((__pyx_v_in1->dimensions[0]) == (__pyx_v_in2->dimensions[0])))) {
+    PyErr_SetNone(PyExc_AssertionError);
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 526; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  #endif
+
+  /* "astropy/time/sofa_time.pyx":527
+ *     """
+ *     assert in1.shape[0] == in2.shape[0]
+ *     cdef unsigned n = in1.shape[0]             # <<<<<<<<<<<<<<
+ *     cdef unsigned int i
+ *     cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)
+ */
+  __pyx_v_n = (__pyx_v_in1->dimensions[0]);
+
+  /* "astropy/time/sofa_time.pyx":529
+ *     cdef unsigned n = in1.shape[0]
+ *     cdef unsigned int i
+ *     cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)             # <<<<<<<<<<<<<<
+ *     cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)
+ * 
+ */
+  __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 529; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_2 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s__empty); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 529; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __pyx_t_1 = PyLong_FromUnsignedLong(__pyx_v_n); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 529; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 529; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_3));
+  PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_1);
+  __Pyx_GIVEREF(__pyx_t_1);
+  __pyx_t_1 = 0;
+  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 529; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_1));
+  __pyx_t_4 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 529; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_4);
+  __pyx_t_5 = PyObject_GetAttr(__pyx_t_4, __pyx_n_s__double); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 529; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_n_s__dtype), __pyx_t_5) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 529; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  __pyx_t_5 = PyEval_CallObjectWithKeywords(__pyx_t_2, ((PyObject *)__pyx_t_3), ((PyObject *)__pyx_t_1)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 529; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
+  if (!(likely(((__pyx_t_5) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_5, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 529; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_6 = ((PyArrayObject *)__pyx_t_5);
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_out1, (PyObject*)__pyx_t_6, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {
+      __pyx_v_out1 = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_out1.buf = NULL;
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 529; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    } else {__pyx_bstride_0_out1 = __pyx_bstruct_out1.strides[0];
+      __pyx_bshape_0_out1 = __pyx_bstruct_out1.shape[0];
+    }
+  }
+  __pyx_t_6 = 0;
+  __pyx_v_out1 = ((PyArrayObject *)__pyx_t_5);
+  __pyx_t_5 = 0;
+
+  /* "astropy/time/sofa_time.pyx":530
+ *     cdef unsigned int i
+ *     cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)
+ *     cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)             # <<<<<<<<<<<<<<
+ * 
+ *     for i in range(n):
+ */
+  __pyx_t_5 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 530; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __pyx_t_1 = PyObject_GetAttr(__pyx_t_5, __pyx_n_s__empty); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 530; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  __pyx_t_5 = PyLong_FromUnsignedLong(__pyx_v_n); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 530; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 530; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_3));
+  PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_5);
+  __Pyx_GIVEREF(__pyx_t_5);
+  __pyx_t_5 = 0;
+  __pyx_t_5 = PyDict_New(); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 530; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_5));
+  __pyx_t_2 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 530; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_4 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s__double); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 530; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_4);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  if (PyDict_SetItem(__pyx_t_5, ((PyObject *)__pyx_n_s__dtype), __pyx_t_4) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 530; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  __pyx_t_4 = PyEval_CallObjectWithKeywords(__pyx_t_1, ((PyObject *)__pyx_t_3), ((PyObject *)__pyx_t_5)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 530; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_4);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_5)); __pyx_t_5 = 0;
+  if (!(likely(((__pyx_t_4) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_4, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 530; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_7 = ((PyArrayObject *)__pyx_t_4);
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_out2, (PyObject*)__pyx_t_7, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {
+      __pyx_v_out2 = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_out2.buf = NULL;
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 530; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    } else {__pyx_bstride_0_out2 = __pyx_bstruct_out2.strides[0];
+      __pyx_bshape_0_out2 = __pyx_bstruct_out2.shape[0];
+    }
+  }
+  __pyx_t_7 = 0;
+  __pyx_v_out2 = ((PyArrayObject *)__pyx_t_4);
+  __pyx_t_4 = 0;
+
+  /* "astropy/time/sofa_time.pyx":532
+ *     cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)
+ * 
+ *     for i in range(n):             # <<<<<<<<<<<<<<
+ *         ret = iauTdbtcb(in1[i], in2[i], &out1[i], &out2[i])
+ *         check_return(ret, 'iauTdbtcb')
+ */
+  __pyx_t_8 = __pyx_v_n;
+  for (__pyx_t_9 = 0; __pyx_t_9 < __pyx_t_8; __pyx_t_9+=1) {
+    __pyx_v_i = __pyx_t_9;
+
+    /* "astropy/time/sofa_time.pyx":533
+ * 
+ *     for i in range(n):
+ *         ret = iauTdbtcb(in1[i], in2[i], &out1[i], &out2[i])             # <<<<<<<<<<<<<<
+ *         check_return(ret, 'iauTdbtcb')
+ * 
+ */
+    __pyx_t_10 = __pyx_v_i;
+    __pyx_t_11 = __pyx_v_i;
+    __pyx_t_12 = __pyx_v_i;
+    __pyx_t_13 = __pyx_v_i;
+    __pyx_v_ret = iauTdbtcb((*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_in1.buf, __pyx_t_10, __pyx_bstride_0_in1)), (*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_in2.buf, __pyx_t_11, __pyx_bstride_0_in2)), (&(*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_out1.buf, __pyx_t_12, __pyx_bstride_0_out1))), (&(*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_out2.buf, __pyx_t_13, __pyx_bstride_0_out2))));
+
+    /* "astropy/time/sofa_time.pyx":534
+ *     for i in range(n):
+ *         ret = iauTdbtcb(in1[i], in2[i], &out1[i], &out2[i])
+ *         check_return(ret, 'iauTdbtcb')             # <<<<<<<<<<<<<<
+ * 
+ *     return out1, out2
+ */
+    __pyx_t_4 = __Pyx_GetName(__pyx_m, __pyx_n_s__check_return); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 534; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_4);
+    __pyx_t_5 = PyInt_FromLong(__pyx_v_ret); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 534; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_5);
+    __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 534; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(((PyObject *)__pyx_t_3));
+    PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_5);
+    __Pyx_GIVEREF(__pyx_t_5);
+    __Pyx_INCREF(((PyObject *)__pyx_n_s__iauTdbtcb));
+    PyTuple_SET_ITEM(__pyx_t_3, 1, ((PyObject *)__pyx_n_s__iauTdbtcb));
+    __Pyx_GIVEREF(((PyObject *)__pyx_n_s__iauTdbtcb));
+    __pyx_t_5 = 0;
+    __pyx_t_5 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 534; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_5);
+    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+    __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
+    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  }
+
+  /* "astropy/time/sofa_time.pyx":536
+ *         check_return(ret, 'iauTdbtcb')
+ * 
+ *     return out1, out2             # <<<<<<<<<<<<<<
+ * 
+ * 
+ */
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_t_5 = PyTuple_New(2); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 536; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_5));
+  __Pyx_INCREF(((PyObject *)__pyx_v_out1));
+  PyTuple_SET_ITEM(__pyx_t_5, 0, ((PyObject *)__pyx_v_out1));
+  __Pyx_GIVEREF(((PyObject *)__pyx_v_out1));
+  __Pyx_INCREF(((PyObject *)__pyx_v_out2));
+  PyTuple_SET_ITEM(__pyx_t_5, 1, ((PyObject *)__pyx_v_out2));
+  __Pyx_GIVEREF(((PyObject *)__pyx_v_out2));
+  __pyx_r = ((PyObject *)__pyx_t_5);
+  __pyx_t_5 = 0;
+  goto __pyx_L0;
+
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_XDECREF(__pyx_t_5);
+  { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;
+    __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out1);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out2);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in1);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in2);
+  __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
+  __Pyx_AddTraceback("astropy.time.sofa_time.tdb_tcb", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  goto __pyx_L2;
+  __pyx_L0:;
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out1);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out2);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in1);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in2);
+  __pyx_L2:;
+  __Pyx_XDECREF((PyObject *)__pyx_v_out1);
+  __Pyx_XDECREF((PyObject *)__pyx_v_out2);
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "astropy/time/sofa_time.pyx":541
+ * @cython.wraparound(False)
+ * @cython.boundscheck(False)
+ * def tt_tai(             # <<<<<<<<<<<<<<
+ *     np.ndarray[double, ndim=1] in1,
+ *     np.ndarray[double, ndim=1] in2):
+ */
+
+static PyObject *__pyx_pf_7astropy_4time_9sofa_time_9tt_tai(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_7astropy_4time_9sofa_time_9tt_tai[] = "\n    int iauTttai(double tt1, double tt2, double *tai1, double *tai2)\n\n    **  Given:\n    **     tt1,tt2    double    TT as a 2-part Julian Date\n    **\n    **  Returned:\n    **     tai1,tai2  double    TAI as a 2-part Julian Date\n    **\n    **  Returned (function value):\n    **                int       status:  0 = OK\n    ";
+static PyMethodDef __pyx_mdef_7astropy_4time_9sofa_time_9tt_tai = {__Pyx_NAMESTR("tt_tai"), (PyCFunction)__pyx_pf_7astropy_4time_9sofa_time_9tt_tai, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(__pyx_doc_7astropy_4time_9sofa_time_9tt_tai)};
+static PyObject *__pyx_pf_7astropy_4time_9sofa_time_9tt_tai(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyArrayObject *__pyx_v_in1 = 0;
+  PyArrayObject *__pyx_v_in2 = 0;
+  unsigned int __pyx_v_n;
+  unsigned int __pyx_v_i;
+  PyArrayObject *__pyx_v_out1 = 0;
+  PyArrayObject *__pyx_v_out2 = 0;
+  int __pyx_v_ret;
+  Py_buffer __pyx_bstruct_out1;
+  Py_ssize_t __pyx_bstride_0_out1 = 0;
+  Py_ssize_t __pyx_bshape_0_out1 = 0;
+  Py_buffer __pyx_bstruct_out2;
+  Py_ssize_t __pyx_bstride_0_out2 = 0;
+  Py_ssize_t __pyx_bshape_0_out2 = 0;
+  Py_buffer __pyx_bstruct_in1;
+  Py_ssize_t __pyx_bstride_0_in1 = 0;
+  Py_ssize_t __pyx_bshape_0_in1 = 0;
+  Py_buffer __pyx_bstruct_in2;
+  Py_ssize_t __pyx_bstride_0_in2 = 0;
+  Py_ssize_t __pyx_bshape_0_in2 = 0;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
+  PyObject *__pyx_t_5 = NULL;
+  PyArrayObject *__pyx_t_6 = NULL;
+  PyArrayObject *__pyx_t_7 = NULL;
+  unsigned int __pyx_t_8;
+  unsigned int __pyx_t_9;
+  unsigned int __pyx_t_10;
+  unsigned int __pyx_t_11;
+  unsigned int __pyx_t_12;
+  unsigned int __pyx_t_13;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__in1,&__pyx_n_s__in2,0};
+  __Pyx_RefNannySetupContext("tt_tai");
+  __pyx_self = __pyx_self;
+  {
+    PyObject* values[2] = {0,0};
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  0:
+        values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__in1);
+        if (likely(values[0])) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+        case  1:
+        values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__in2);
+        if (likely(values[1])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("tt_tai", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 541; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "tt_tai") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 541; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+    } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
+      goto __pyx_L5_argtuple_error;
+    } else {
+      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+    }
+    __pyx_v_in1 = ((PyArrayObject *)values[0]);
+    __pyx_v_in2 = ((PyArrayObject *)values[1]);
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("tt_tai", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 541; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("astropy.time.sofa_time.tt_tai", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_bstruct_out1.buf = NULL;
+  __pyx_bstruct_out2.buf = NULL;
+  __pyx_bstruct_in1.buf = NULL;
+  __pyx_bstruct_in2.buf = NULL;
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_in1), __pyx_ptype_5numpy_ndarray, 1, "in1", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 542; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_in2), __pyx_ptype_5numpy_ndarray, 1, "in2", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 543; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_in1, (PyObject*)__pyx_v_in1, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 541; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_in1 = __pyx_bstruct_in1.strides[0];
+  __pyx_bshape_0_in1 = __pyx_bstruct_in1.shape[0];
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_in2, (PyObject*)__pyx_v_in2, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 541; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_in2 = __pyx_bstruct_in2.strides[0];
+  __pyx_bshape_0_in2 = __pyx_bstruct_in2.shape[0];
+
+  /* "astropy/time/sofa_time.pyx":556
+ *     **                int       status:  0 = OK
+ *     """
+ *     assert in1.shape[0] == in2.shape[0]             # <<<<<<<<<<<<<<
+ *     cdef unsigned n = in1.shape[0]
+ *     cdef unsigned int i
+ */
+  #ifndef CYTHON_WITHOUT_ASSERTIONS
+  if (unlikely(!((__pyx_v_in1->dimensions[0]) == (__pyx_v_in2->dimensions[0])))) {
+    PyErr_SetNone(PyExc_AssertionError);
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 556; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  #endif
+
+  /* "astropy/time/sofa_time.pyx":557
+ *     """
+ *     assert in1.shape[0] == in2.shape[0]
+ *     cdef unsigned n = in1.shape[0]             # <<<<<<<<<<<<<<
+ *     cdef unsigned int i
+ *     cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)
+ */
+  __pyx_v_n = (__pyx_v_in1->dimensions[0]);
+
+  /* "astropy/time/sofa_time.pyx":559
+ *     cdef unsigned n = in1.shape[0]
+ *     cdef unsigned int i
+ *     cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)             # <<<<<<<<<<<<<<
+ *     cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)
+ * 
+ */
+  __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 559; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_2 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s__empty); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 559; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __pyx_t_1 = PyLong_FromUnsignedLong(__pyx_v_n); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 559; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 559; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_3));
+  PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_1);
+  __Pyx_GIVEREF(__pyx_t_1);
+  __pyx_t_1 = 0;
+  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 559; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_1));
+  __pyx_t_4 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 559; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_4);
+  __pyx_t_5 = PyObject_GetAttr(__pyx_t_4, __pyx_n_s__double); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 559; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_n_s__dtype), __pyx_t_5) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 559; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  __pyx_t_5 = PyEval_CallObjectWithKeywords(__pyx_t_2, ((PyObject *)__pyx_t_3), ((PyObject *)__pyx_t_1)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 559; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
+  if (!(likely(((__pyx_t_5) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_5, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 559; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_6 = ((PyArrayObject *)__pyx_t_5);
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_out1, (PyObject*)__pyx_t_6, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {
+      __pyx_v_out1 = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_out1.buf = NULL;
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 559; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    } else {__pyx_bstride_0_out1 = __pyx_bstruct_out1.strides[0];
+      __pyx_bshape_0_out1 = __pyx_bstruct_out1.shape[0];
+    }
+  }
+  __pyx_t_6 = 0;
+  __pyx_v_out1 = ((PyArrayObject *)__pyx_t_5);
+  __pyx_t_5 = 0;
+
+  /* "astropy/time/sofa_time.pyx":560
+ *     cdef unsigned int i
+ *     cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)
+ *     cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)             # <<<<<<<<<<<<<<
+ * 
+ *     for i in range(n):
+ */
+  __pyx_t_5 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 560; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __pyx_t_1 = PyObject_GetAttr(__pyx_t_5, __pyx_n_s__empty); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 560; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  __pyx_t_5 = PyLong_FromUnsignedLong(__pyx_v_n); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 560; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 560; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_3));
+  PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_5);
+  __Pyx_GIVEREF(__pyx_t_5);
+  __pyx_t_5 = 0;
+  __pyx_t_5 = PyDict_New(); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 560; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_5));
+  __pyx_t_2 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 560; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_4 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s__double); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 560; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_4);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  if (PyDict_SetItem(__pyx_t_5, ((PyObject *)__pyx_n_s__dtype), __pyx_t_4) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 560; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  __pyx_t_4 = PyEval_CallObjectWithKeywords(__pyx_t_1, ((PyObject *)__pyx_t_3), ((PyObject *)__pyx_t_5)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 560; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_4);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_5)); __pyx_t_5 = 0;
+  if (!(likely(((__pyx_t_4) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_4, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 560; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_7 = ((PyArrayObject *)__pyx_t_4);
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_out2, (PyObject*)__pyx_t_7, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {
+      __pyx_v_out2 = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_out2.buf = NULL;
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 560; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    } else {__pyx_bstride_0_out2 = __pyx_bstruct_out2.strides[0];
+      __pyx_bshape_0_out2 = __pyx_bstruct_out2.shape[0];
+    }
+  }
+  __pyx_t_7 = 0;
+  __pyx_v_out2 = ((PyArrayObject *)__pyx_t_4);
+  __pyx_t_4 = 0;
+
+  /* "astropy/time/sofa_time.pyx":562
+ *     cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)
+ * 
+ *     for i in range(n):             # <<<<<<<<<<<<<<
+ *         ret = iauTttai(in1[i], in2[i], &out1[i], &out2[i])
+ *         check_return(ret, 'iauTttai')
+ */
+  __pyx_t_8 = __pyx_v_n;
+  for (__pyx_t_9 = 0; __pyx_t_9 < __pyx_t_8; __pyx_t_9+=1) {
+    __pyx_v_i = __pyx_t_9;
+
+    /* "astropy/time/sofa_time.pyx":563
+ * 
+ *     for i in range(n):
+ *         ret = iauTttai(in1[i], in2[i], &out1[i], &out2[i])             # <<<<<<<<<<<<<<
+ *         check_return(ret, 'iauTttai')
+ * 
+ */
+    __pyx_t_10 = __pyx_v_i;
+    __pyx_t_11 = __pyx_v_i;
+    __pyx_t_12 = __pyx_v_i;
+    __pyx_t_13 = __pyx_v_i;
+    __pyx_v_ret = iauTttai((*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_in1.buf, __pyx_t_10, __pyx_bstride_0_in1)), (*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_in2.buf, __pyx_t_11, __pyx_bstride_0_in2)), (&(*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_out1.buf, __pyx_t_12, __pyx_bstride_0_out1))), (&(*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_out2.buf, __pyx_t_13, __pyx_bstride_0_out2))));
+
+    /* "astropy/time/sofa_time.pyx":564
+ *     for i in range(n):
+ *         ret = iauTttai(in1[i], in2[i], &out1[i], &out2[i])
+ *         check_return(ret, 'iauTttai')             # <<<<<<<<<<<<<<
+ * 
+ *     return out1, out2
+ */
+    __pyx_t_4 = __Pyx_GetName(__pyx_m, __pyx_n_s__check_return); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 564; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_4);
+    __pyx_t_5 = PyInt_FromLong(__pyx_v_ret); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 564; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_5);
+    __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 564; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(((PyObject *)__pyx_t_3));
+    PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_5);
+    __Pyx_GIVEREF(__pyx_t_5);
+    __Pyx_INCREF(((PyObject *)__pyx_n_s__iauTttai));
+    PyTuple_SET_ITEM(__pyx_t_3, 1, ((PyObject *)__pyx_n_s__iauTttai));
+    __Pyx_GIVEREF(((PyObject *)__pyx_n_s__iauTttai));
+    __pyx_t_5 = 0;
+    __pyx_t_5 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 564; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_5);
+    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+    __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
+    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  }
+
+  /* "astropy/time/sofa_time.pyx":566
+ *         check_return(ret, 'iauTttai')
+ * 
+ *     return out1, out2             # <<<<<<<<<<<<<<
+ * 
+ * 
+ */
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_t_5 = PyTuple_New(2); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 566; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_5));
+  __Pyx_INCREF(((PyObject *)__pyx_v_out1));
+  PyTuple_SET_ITEM(__pyx_t_5, 0, ((PyObject *)__pyx_v_out1));
+  __Pyx_GIVEREF(((PyObject *)__pyx_v_out1));
+  __Pyx_INCREF(((PyObject *)__pyx_v_out2));
+  PyTuple_SET_ITEM(__pyx_t_5, 1, ((PyObject *)__pyx_v_out2));
+  __Pyx_GIVEREF(((PyObject *)__pyx_v_out2));
+  __pyx_r = ((PyObject *)__pyx_t_5);
+  __pyx_t_5 = 0;
+  goto __pyx_L0;
+
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_XDECREF(__pyx_t_5);
+  { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;
+    __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out1);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out2);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in1);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in2);
+  __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
+  __Pyx_AddTraceback("astropy.time.sofa_time.tt_tai", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  goto __pyx_L2;
+  __pyx_L0:;
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out1);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out2);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in1);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in2);
+  __pyx_L2:;
+  __Pyx_XDECREF((PyObject *)__pyx_v_out1);
+  __Pyx_XDECREF((PyObject *)__pyx_v_out2);
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "astropy/time/sofa_time.pyx":571
+ * @cython.wraparound(False)
+ * @cython.boundscheck(False)
+ * def tt_tcg(             # <<<<<<<<<<<<<<
+ *     np.ndarray[double, ndim=1] in1,
+ *     np.ndarray[double, ndim=1] in2):
+ */
+
+static PyObject *__pyx_pf_7astropy_4time_9sofa_time_10tt_tcg(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_7astropy_4time_9sofa_time_10tt_tcg[] = "\n    int iauTttcg(double tt1, double tt2, double *tcg1, double *tcg2)\n    **  Given:\n    **     tt1,tt2    double    TT as a 2-part Julian Date\n    **\n    **  Returned:\n    **     tcg1,tcg2  double    TCG as a 2-part Julian Date\n    **\n    **  Returned (function value):\n    **                int       status:  0 = OK\n    ";
+static PyMethodDef __pyx_mdef_7astropy_4time_9sofa_time_10tt_tcg = {__Pyx_NAMESTR("tt_tcg"), (PyCFunction)__pyx_pf_7astropy_4time_9sofa_time_10tt_tcg, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(__pyx_doc_7astropy_4time_9sofa_time_10tt_tcg)};
+static PyObject *__pyx_pf_7astropy_4time_9sofa_time_10tt_tcg(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyArrayObject *__pyx_v_in1 = 0;
+  PyArrayObject *__pyx_v_in2 = 0;
+  unsigned int __pyx_v_n;
+  unsigned int __pyx_v_i;
+  PyArrayObject *__pyx_v_out1 = 0;
+  PyArrayObject *__pyx_v_out2 = 0;
+  int __pyx_v_ret;
+  Py_buffer __pyx_bstruct_out1;
+  Py_ssize_t __pyx_bstride_0_out1 = 0;
+  Py_ssize_t __pyx_bshape_0_out1 = 0;
+  Py_buffer __pyx_bstruct_out2;
+  Py_ssize_t __pyx_bstride_0_out2 = 0;
+  Py_ssize_t __pyx_bshape_0_out2 = 0;
+  Py_buffer __pyx_bstruct_in1;
+  Py_ssize_t __pyx_bstride_0_in1 = 0;
+  Py_ssize_t __pyx_bshape_0_in1 = 0;
+  Py_buffer __pyx_bstruct_in2;
+  Py_ssize_t __pyx_bstride_0_in2 = 0;
+  Py_ssize_t __pyx_bshape_0_in2 = 0;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
+  PyObject *__pyx_t_5 = NULL;
+  PyArrayObject *__pyx_t_6 = NULL;
+  PyArrayObject *__pyx_t_7 = NULL;
+  unsigned int __pyx_t_8;
+  unsigned int __pyx_t_9;
+  unsigned int __pyx_t_10;
+  unsigned int __pyx_t_11;
+  unsigned int __pyx_t_12;
+  unsigned int __pyx_t_13;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__in1,&__pyx_n_s__in2,0};
+  __Pyx_RefNannySetupContext("tt_tcg");
+  __pyx_self = __pyx_self;
+  {
+    PyObject* values[2] = {0,0};
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  0:
+        values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__in1);
+        if (likely(values[0])) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+        case  1:
+        values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__in2);
+        if (likely(values[1])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("tt_tcg", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 571; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "tt_tcg") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 571; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+    } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
+      goto __pyx_L5_argtuple_error;
+    } else {
+      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+    }
+    __pyx_v_in1 = ((PyArrayObject *)values[0]);
+    __pyx_v_in2 = ((PyArrayObject *)values[1]);
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("tt_tcg", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 571; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("astropy.time.sofa_time.tt_tcg", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_bstruct_out1.buf = NULL;
+  __pyx_bstruct_out2.buf = NULL;
+  __pyx_bstruct_in1.buf = NULL;
+  __pyx_bstruct_in2.buf = NULL;
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_in1), __pyx_ptype_5numpy_ndarray, 1, "in1", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 572; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_in2), __pyx_ptype_5numpy_ndarray, 1, "in2", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 573; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_in1, (PyObject*)__pyx_v_in1, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 571; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_in1 = __pyx_bstruct_in1.strides[0];
+  __pyx_bshape_0_in1 = __pyx_bstruct_in1.shape[0];
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_in2, (PyObject*)__pyx_v_in2, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 571; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_in2 = __pyx_bstruct_in2.strides[0];
+  __pyx_bshape_0_in2 = __pyx_bstruct_in2.shape[0];
+
+  /* "astropy/time/sofa_time.pyx":585
+ *     **                int       status:  0 = OK
+ *     """
+ *     assert in1.shape[0] == in2.shape[0]             # <<<<<<<<<<<<<<
+ *     cdef unsigned n = in1.shape[0]
+ *     cdef unsigned int i
+ */
+  #ifndef CYTHON_WITHOUT_ASSERTIONS
+  if (unlikely(!((__pyx_v_in1->dimensions[0]) == (__pyx_v_in2->dimensions[0])))) {
+    PyErr_SetNone(PyExc_AssertionError);
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 585; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  #endif
+
+  /* "astropy/time/sofa_time.pyx":586
+ *     """
+ *     assert in1.shape[0] == in2.shape[0]
+ *     cdef unsigned n = in1.shape[0]             # <<<<<<<<<<<<<<
+ *     cdef unsigned int i
+ *     cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)
+ */
+  __pyx_v_n = (__pyx_v_in1->dimensions[0]);
+
+  /* "astropy/time/sofa_time.pyx":588
+ *     cdef unsigned n = in1.shape[0]
+ *     cdef unsigned int i
+ *     cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)             # <<<<<<<<<<<<<<
+ *     cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)
+ * 
+ */
+  __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 588; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_2 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s__empty); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 588; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __pyx_t_1 = PyLong_FromUnsignedLong(__pyx_v_n); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 588; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 588; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_3));
+  PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_1);
+  __Pyx_GIVEREF(__pyx_t_1);
+  __pyx_t_1 = 0;
+  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 588; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_1));
+  __pyx_t_4 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 588; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_4);
+  __pyx_t_5 = PyObject_GetAttr(__pyx_t_4, __pyx_n_s__double); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 588; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_n_s__dtype), __pyx_t_5) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 588; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  __pyx_t_5 = PyEval_CallObjectWithKeywords(__pyx_t_2, ((PyObject *)__pyx_t_3), ((PyObject *)__pyx_t_1)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 588; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
+  if (!(likely(((__pyx_t_5) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_5, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 588; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_6 = ((PyArrayObject *)__pyx_t_5);
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_out1, (PyObject*)__pyx_t_6, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {
+      __pyx_v_out1 = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_out1.buf = NULL;
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 588; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    } else {__pyx_bstride_0_out1 = __pyx_bstruct_out1.strides[0];
+      __pyx_bshape_0_out1 = __pyx_bstruct_out1.shape[0];
+    }
+  }
+  __pyx_t_6 = 0;
+  __pyx_v_out1 = ((PyArrayObject *)__pyx_t_5);
+  __pyx_t_5 = 0;
+
+  /* "astropy/time/sofa_time.pyx":589
+ *     cdef unsigned int i
+ *     cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)
+ *     cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)             # <<<<<<<<<<<<<<
+ * 
+ *     for i in range(n):
+ */
+  __pyx_t_5 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 589; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __pyx_t_1 = PyObject_GetAttr(__pyx_t_5, __pyx_n_s__empty); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 589; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  __pyx_t_5 = PyLong_FromUnsignedLong(__pyx_v_n); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 589; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 589; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_3));
+  PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_5);
+  __Pyx_GIVEREF(__pyx_t_5);
+  __pyx_t_5 = 0;
+  __pyx_t_5 = PyDict_New(); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 589; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_5));
+  __pyx_t_2 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 589; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_4 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s__double); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 589; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_4);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  if (PyDict_SetItem(__pyx_t_5, ((PyObject *)__pyx_n_s__dtype), __pyx_t_4) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 589; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  __pyx_t_4 = PyEval_CallObjectWithKeywords(__pyx_t_1, ((PyObject *)__pyx_t_3), ((PyObject *)__pyx_t_5)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 589; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_4);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_5)); __pyx_t_5 = 0;
+  if (!(likely(((__pyx_t_4) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_4, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 589; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_7 = ((PyArrayObject *)__pyx_t_4);
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_out2, (PyObject*)__pyx_t_7, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {
+      __pyx_v_out2 = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_out2.buf = NULL;
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 589; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    } else {__pyx_bstride_0_out2 = __pyx_bstruct_out2.strides[0];
+      __pyx_bshape_0_out2 = __pyx_bstruct_out2.shape[0];
+    }
+  }
+  __pyx_t_7 = 0;
+  __pyx_v_out2 = ((PyArrayObject *)__pyx_t_4);
+  __pyx_t_4 = 0;
+
+  /* "astropy/time/sofa_time.pyx":591
+ *     cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)
+ * 
+ *     for i in range(n):             # <<<<<<<<<<<<<<
+ *         ret = iauTttcg(in1[i], in2[i], &out1[i], &out2[i])
+ *         check_return(ret, 'iauTttcg')
+ */
+  __pyx_t_8 = __pyx_v_n;
+  for (__pyx_t_9 = 0; __pyx_t_9 < __pyx_t_8; __pyx_t_9+=1) {
+    __pyx_v_i = __pyx_t_9;
+
+    /* "astropy/time/sofa_time.pyx":592
+ * 
+ *     for i in range(n):
+ *         ret = iauTttcg(in1[i], in2[i], &out1[i], &out2[i])             # <<<<<<<<<<<<<<
+ *         check_return(ret, 'iauTttcg')
+ * 
+ */
+    __pyx_t_10 = __pyx_v_i;
+    __pyx_t_11 = __pyx_v_i;
+    __pyx_t_12 = __pyx_v_i;
+    __pyx_t_13 = __pyx_v_i;
+    __pyx_v_ret = iauTttcg((*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_in1.buf, __pyx_t_10, __pyx_bstride_0_in1)), (*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_in2.buf, __pyx_t_11, __pyx_bstride_0_in2)), (&(*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_out1.buf, __pyx_t_12, __pyx_bstride_0_out1))), (&(*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_out2.buf, __pyx_t_13, __pyx_bstride_0_out2))));
+
+    /* "astropy/time/sofa_time.pyx":593
+ *     for i in range(n):
+ *         ret = iauTttcg(in1[i], in2[i], &out1[i], &out2[i])
+ *         check_return(ret, 'iauTttcg')             # <<<<<<<<<<<<<<
+ * 
+ *     return out1, out2
+ */
+    __pyx_t_4 = __Pyx_GetName(__pyx_m, __pyx_n_s__check_return); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 593; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_4);
+    __pyx_t_5 = PyInt_FromLong(__pyx_v_ret); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 593; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_5);
+    __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 593; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(((PyObject *)__pyx_t_3));
+    PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_5);
+    __Pyx_GIVEREF(__pyx_t_5);
+    __Pyx_INCREF(((PyObject *)__pyx_n_s__iauTttcg));
+    PyTuple_SET_ITEM(__pyx_t_3, 1, ((PyObject *)__pyx_n_s__iauTttcg));
+    __Pyx_GIVEREF(((PyObject *)__pyx_n_s__iauTttcg));
+    __pyx_t_5 = 0;
+    __pyx_t_5 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 593; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_5);
+    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+    __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
+    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  }
+
+  /* "astropy/time/sofa_time.pyx":595
+ *         check_return(ret, 'iauTttcg')
+ * 
+ *     return out1, out2             # <<<<<<<<<<<<<<
+ * 
+ * 
+ */
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_t_5 = PyTuple_New(2); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 595; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_5));
+  __Pyx_INCREF(((PyObject *)__pyx_v_out1));
+  PyTuple_SET_ITEM(__pyx_t_5, 0, ((PyObject *)__pyx_v_out1));
+  __Pyx_GIVEREF(((PyObject *)__pyx_v_out1));
+  __Pyx_INCREF(((PyObject *)__pyx_v_out2));
+  PyTuple_SET_ITEM(__pyx_t_5, 1, ((PyObject *)__pyx_v_out2));
+  __Pyx_GIVEREF(((PyObject *)__pyx_v_out2));
+  __pyx_r = ((PyObject *)__pyx_t_5);
+  __pyx_t_5 = 0;
+  goto __pyx_L0;
+
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_XDECREF(__pyx_t_5);
+  { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;
+    __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out1);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out2);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in1);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in2);
+  __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
+  __Pyx_AddTraceback("astropy.time.sofa_time.tt_tcg", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  goto __pyx_L2;
+  __pyx_L0:;
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out1);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out2);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in1);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in2);
+  __pyx_L2:;
+  __Pyx_XDECREF((PyObject *)__pyx_v_out1);
+  __Pyx_XDECREF((PyObject *)__pyx_v_out2);
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "astropy/time/sofa_time.pyx":600
+ * @cython.wraparound(False)
+ * @cython.boundscheck(False)
+ * def utc_tai(             # <<<<<<<<<<<<<<
+ *     np.ndarray[double, ndim=1] in1,
+ *     np.ndarray[double, ndim=1] in2):
+ */
+
+static PyObject *__pyx_pf_7astropy_4time_9sofa_time_11utc_tai(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_7astropy_4time_9sofa_time_11utc_tai[] = "\n    int iauUtctai(double utc1, double utc2, double *tai1, double *tai2)\n\n    **  Given:\n    **     utc1,utc2  double   UTC as a 2-part quasi Julian Date (Notes 1-4)\n    **\n    **  Returned:\n    **     tai1,tai2  double   TAI as a 2-part Julian Date (Note 5)\n    **\n    **  Returned (function value):\n    **                int      status: +1 = dubious year (Note 3)\n    **                                  0 = OK\n    **                                 -1 = unacceptable date\n    **\n    **  Notes:\n    **\n    **  1) utc1+utc2 is quasi Julian Date (see Note 2), apportioned in any\n    **     convenient way between the two arguments, for example where utc1\n    **     is the Julian Day Number and utc2 is the fraction of a day.\n    **\n    **  2) JD cannot unambiguously represent UTC during a leap second unless\n    **     special measures are taken.  The convention in the present\n    **     function is that the JD day represents UTC days whether the\n    **     length is 86399, 86400 or 86401 SI seconds.\n    **\n    **  3) The warning status \"dubious year\" flags UTCs that predate the\n    **     introduction of the time scale and that are too far in the future\n    **     to be trusted.  See iauDat  for further details.\n    **\n    **  4) The function iauDtf2d converts from calendar date and time of day\n    **     into 2-part Julian Date, and in the case of UTC implements the\n    **     leap-second-ambiguity convention described above.\n    **\n    **  5) The returned TAI1,TAI2 are such that their sum is the TAI Julian\n    **     Date.\n    **\n    ";
+static PyMethodDef __pyx_mdef_7astropy_4time_9sofa_time_11utc_tai = {__Pyx_NAMESTR("utc_tai"), (PyCFunction)__pyx_pf_7astropy_4time_9sofa_time_11utc_tai, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(__pyx_doc_7astropy_4time_9sofa_time_11utc_tai)};
+static PyObject *__pyx_pf_7astropy_4time_9sofa_time_11utc_tai(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyArrayObject *__pyx_v_in1 = 0;
+  PyArrayObject *__pyx_v_in2 = 0;
+  unsigned int __pyx_v_n;
+  unsigned int __pyx_v_i;
+  PyArrayObject *__pyx_v_out1 = 0;
+  PyArrayObject *__pyx_v_out2 = 0;
+  PyObject *__pyx_v_warns = NULL;
+  PyObject *__pyx_v_errs = NULL;
+  int __pyx_v_ret;
+  Py_buffer __pyx_bstruct_out1;
+  Py_ssize_t __pyx_bstride_0_out1 = 0;
+  Py_ssize_t __pyx_bshape_0_out1 = 0;
+  Py_buffer __pyx_bstruct_out2;
+  Py_ssize_t __pyx_bstride_0_out2 = 0;
+  Py_ssize_t __pyx_bshape_0_out2 = 0;
+  Py_buffer __pyx_bstruct_in1;
+  Py_ssize_t __pyx_bstride_0_in1 = 0;
+  Py_ssize_t __pyx_bshape_0_in1 = 0;
+  Py_buffer __pyx_bstruct_in2;
+  Py_ssize_t __pyx_bstride_0_in2 = 0;
+  Py_ssize_t __pyx_bshape_0_in2 = 0;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
+  PyObject *__pyx_t_5 = NULL;
+  PyArrayObject *__pyx_t_6 = NULL;
+  PyArrayObject *__pyx_t_7 = NULL;
+  unsigned int __pyx_t_8;
+  unsigned int __pyx_t_9;
+  unsigned int __pyx_t_10;
+  unsigned int __pyx_t_11;
+  unsigned int __pyx_t_12;
+  unsigned int __pyx_t_13;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__in1,&__pyx_n_s__in2,0};
+  __Pyx_RefNannySetupContext("utc_tai");
+  __pyx_self = __pyx_self;
+  {
+    PyObject* values[2] = {0,0};
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  0:
+        values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__in1);
+        if (likely(values[0])) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+        case  1:
+        values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__in2);
+        if (likely(values[1])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("utc_tai", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 600; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "utc_tai") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 600; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+    } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
+      goto __pyx_L5_argtuple_error;
+    } else {
+      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+    }
+    __pyx_v_in1 = ((PyArrayObject *)values[0]);
+    __pyx_v_in2 = ((PyArrayObject *)values[1]);
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("utc_tai", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 600; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("astropy.time.sofa_time.utc_tai", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_bstruct_out1.buf = NULL;
+  __pyx_bstruct_out2.buf = NULL;
+  __pyx_bstruct_in1.buf = NULL;
+  __pyx_bstruct_in2.buf = NULL;
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_in1), __pyx_ptype_5numpy_ndarray, 1, "in1", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 601; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_in2), __pyx_ptype_5numpy_ndarray, 1, "in2", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 602; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_in1, (PyObject*)__pyx_v_in1, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 600; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_in1 = __pyx_bstruct_in1.strides[0];
+  __pyx_bshape_0_in1 = __pyx_bstruct_in1.shape[0];
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_in2, (PyObject*)__pyx_v_in2, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 600; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_in2 = __pyx_bstruct_in2.strides[0];
+  __pyx_bshape_0_in2 = __pyx_bstruct_in2.shape[0];
+
+  /* "astropy/time/sofa_time.pyx":640
+ *     **
+ *     """
+ *     assert in1.shape[0] == in2.shape[0]             # <<<<<<<<<<<<<<
+ *     cdef unsigned n = in1.shape[0]
+ *     cdef unsigned int i
+ */
+  #ifndef CYTHON_WITHOUT_ASSERTIONS
+  if (unlikely(!((__pyx_v_in1->dimensions[0]) == (__pyx_v_in2->dimensions[0])))) {
+    PyErr_SetNone(PyExc_AssertionError);
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 640; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  #endif
+
+  /* "astropy/time/sofa_time.pyx":641
+ *     """
+ *     assert in1.shape[0] == in2.shape[0]
+ *     cdef unsigned n = in1.shape[0]             # <<<<<<<<<<<<<<
+ *     cdef unsigned int i
+ *     cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)
+ */
+  __pyx_v_n = (__pyx_v_in1->dimensions[0]);
+
+  /* "astropy/time/sofa_time.pyx":643
+ *     cdef unsigned n = in1.shape[0]
+ *     cdef unsigned int i
+ *     cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)             # <<<<<<<<<<<<<<
+ *     cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)
+ * 
+ */
+  __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 643; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_2 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s__empty); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 643; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __pyx_t_1 = PyLong_FromUnsignedLong(__pyx_v_n); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 643; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 643; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_3));
+  PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_1);
+  __Pyx_GIVEREF(__pyx_t_1);
+  __pyx_t_1 = 0;
+  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 643; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_1));
+  __pyx_t_4 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 643; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_4);
+  __pyx_t_5 = PyObject_GetAttr(__pyx_t_4, __pyx_n_s__double); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 643; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_n_s__dtype), __pyx_t_5) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 643; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  __pyx_t_5 = PyEval_CallObjectWithKeywords(__pyx_t_2, ((PyObject *)__pyx_t_3), ((PyObject *)__pyx_t_1)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 643; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
+  if (!(likely(((__pyx_t_5) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_5, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 643; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_6 = ((PyArrayObject *)__pyx_t_5);
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_out1, (PyObject*)__pyx_t_6, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {
+      __pyx_v_out1 = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_out1.buf = NULL;
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 643; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    } else {__pyx_bstride_0_out1 = __pyx_bstruct_out1.strides[0];
+      __pyx_bshape_0_out1 = __pyx_bstruct_out1.shape[0];
+    }
+  }
+  __pyx_t_6 = 0;
+  __pyx_v_out1 = ((PyArrayObject *)__pyx_t_5);
+  __pyx_t_5 = 0;
+
+  /* "astropy/time/sofa_time.pyx":644
+ *     cdef unsigned int i
+ *     cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)
+ *     cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)             # <<<<<<<<<<<<<<
+ * 
+ *     warns = {1: DUBIOUS}
+ */
+  __pyx_t_5 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 644; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __pyx_t_1 = PyObject_GetAttr(__pyx_t_5, __pyx_n_s__empty); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 644; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  __pyx_t_5 = PyLong_FromUnsignedLong(__pyx_v_n); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 644; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 644; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_3));
+  PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_5);
+  __Pyx_GIVEREF(__pyx_t_5);
+  __pyx_t_5 = 0;
+  __pyx_t_5 = PyDict_New(); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 644; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_5));
+  __pyx_t_2 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 644; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_4 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s__double); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 644; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_4);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  if (PyDict_SetItem(__pyx_t_5, ((PyObject *)__pyx_n_s__dtype), __pyx_t_4) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 644; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  __pyx_t_4 = PyEval_CallObjectWithKeywords(__pyx_t_1, ((PyObject *)__pyx_t_3), ((PyObject *)__pyx_t_5)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 644; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_4);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_5)); __pyx_t_5 = 0;
+  if (!(likely(((__pyx_t_4) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_4, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 644; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_7 = ((PyArrayObject *)__pyx_t_4);
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_out2, (PyObject*)__pyx_t_7, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {
+      __pyx_v_out2 = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_out2.buf = NULL;
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 644; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    } else {__pyx_bstride_0_out2 = __pyx_bstruct_out2.strides[0];
+      __pyx_bshape_0_out2 = __pyx_bstruct_out2.shape[0];
+    }
+  }
+  __pyx_t_7 = 0;
+  __pyx_v_out2 = ((PyArrayObject *)__pyx_t_4);
+  __pyx_t_4 = 0;
+
+  /* "astropy/time/sofa_time.pyx":646
+ *     cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)
+ * 
+ *     warns = {1: DUBIOUS}             # <<<<<<<<<<<<<<
+ *     errs = {-1: 'unacceptable date'}
+ * 
+ */
+  __pyx_t_4 = PyDict_New(); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 646; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_4));
+  __pyx_t_5 = __Pyx_GetName(__pyx_m, __pyx_n_s__DUBIOUS); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 646; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  if (PyDict_SetItem(__pyx_t_4, __pyx_int_1, __pyx_t_5) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 646; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  __pyx_v_warns = __pyx_t_4;
+  __pyx_t_4 = 0;
+
+  /* "astropy/time/sofa_time.pyx":647
+ * 
+ *     warns = {1: DUBIOUS}
+ *     errs = {-1: 'unacceptable date'}             # <<<<<<<<<<<<<<
+ * 
+ *     for i in range(n):
+ */
+  __pyx_t_4 = PyDict_New(); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 647; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_4));
+  if (PyDict_SetItem(__pyx_t_4, __pyx_int_neg_1, ((PyObject *)__pyx_kp_s_12)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 647; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_v_errs = __pyx_t_4;
+  __pyx_t_4 = 0;
+
+  /* "astropy/time/sofa_time.pyx":649
+ *     errs = {-1: 'unacceptable date'}
+ * 
+ *     for i in range(n):             # <<<<<<<<<<<<<<
+ *         ret = iauUtctai(in1[i], in2[i], &out1[i], &out2[i])
+ *         check_return(ret, 'iauUtctai', warns, errs)
+ */
+  __pyx_t_8 = __pyx_v_n;
+  for (__pyx_t_9 = 0; __pyx_t_9 < __pyx_t_8; __pyx_t_9+=1) {
+    __pyx_v_i = __pyx_t_9;
+
+    /* "astropy/time/sofa_time.pyx":650
+ * 
+ *     for i in range(n):
+ *         ret = iauUtctai(in1[i], in2[i], &out1[i], &out2[i])             # <<<<<<<<<<<<<<
+ *         check_return(ret, 'iauUtctai', warns, errs)
+ * 
+ */
+    __pyx_t_10 = __pyx_v_i;
+    __pyx_t_11 = __pyx_v_i;
+    __pyx_t_12 = __pyx_v_i;
+    __pyx_t_13 = __pyx_v_i;
+    __pyx_v_ret = iauUtctai((*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_in1.buf, __pyx_t_10, __pyx_bstride_0_in1)), (*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_in2.buf, __pyx_t_11, __pyx_bstride_0_in2)), (&(*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_out1.buf, __pyx_t_12, __pyx_bstride_0_out1))), (&(*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_out2.buf, __pyx_t_13, __pyx_bstride_0_out2))));
+
+    /* "astropy/time/sofa_time.pyx":651
+ *     for i in range(n):
+ *         ret = iauUtctai(in1[i], in2[i], &out1[i], &out2[i])
+ *         check_return(ret, 'iauUtctai', warns, errs)             # <<<<<<<<<<<<<<
+ * 
+ *     return out1, out2
+ */
+    __pyx_t_4 = __Pyx_GetName(__pyx_m, __pyx_n_s__check_return); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 651; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_4);
+    __pyx_t_5 = PyInt_FromLong(__pyx_v_ret); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 651; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_5);
+    __pyx_t_3 = PyTuple_New(4); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 651; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(((PyObject *)__pyx_t_3));
+    PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_5);
+    __Pyx_GIVEREF(__pyx_t_5);
+    __Pyx_INCREF(((PyObject *)__pyx_n_s__iauUtctai));
+    PyTuple_SET_ITEM(__pyx_t_3, 1, ((PyObject *)__pyx_n_s__iauUtctai));
+    __Pyx_GIVEREF(((PyObject *)__pyx_n_s__iauUtctai));
+    __Pyx_INCREF(((PyObject *)__pyx_v_warns));
+    PyTuple_SET_ITEM(__pyx_t_3, 2, ((PyObject *)__pyx_v_warns));
+    __Pyx_GIVEREF(((PyObject *)__pyx_v_warns));
+    __Pyx_INCREF(((PyObject *)__pyx_v_errs));
+    PyTuple_SET_ITEM(__pyx_t_3, 3, ((PyObject *)__pyx_v_errs));
+    __Pyx_GIVEREF(((PyObject *)__pyx_v_errs));
+    __pyx_t_5 = 0;
+    __pyx_t_5 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 651; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_5);
+    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+    __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
+    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  }
+
+  /* "astropy/time/sofa_time.pyx":653
+ *         check_return(ret, 'iauUtctai', warns, errs)
+ * 
+ *     return out1, out2             # <<<<<<<<<<<<<<
+ * 
+ * 
+ */
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_t_5 = PyTuple_New(2); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 653; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_5));
+  __Pyx_INCREF(((PyObject *)__pyx_v_out1));
+  PyTuple_SET_ITEM(__pyx_t_5, 0, ((PyObject *)__pyx_v_out1));
+  __Pyx_GIVEREF(((PyObject *)__pyx_v_out1));
+  __Pyx_INCREF(((PyObject *)__pyx_v_out2));
+  PyTuple_SET_ITEM(__pyx_t_5, 1, ((PyObject *)__pyx_v_out2));
+  __Pyx_GIVEREF(((PyObject *)__pyx_v_out2));
+  __pyx_r = ((PyObject *)__pyx_t_5);
+  __pyx_t_5 = 0;
+  goto __pyx_L0;
+
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_XDECREF(__pyx_t_5);
+  { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;
+    __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out1);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out2);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in1);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in2);
+  __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
+  __Pyx_AddTraceback("astropy.time.sofa_time.utc_tai", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  goto __pyx_L2;
+  __pyx_L0:;
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out1);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out2);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in1);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in2);
+  __pyx_L2:;
+  __Pyx_XDECREF((PyObject *)__pyx_v_out1);
+  __Pyx_XDECREF((PyObject *)__pyx_v_out2);
+  __Pyx_XDECREF(__pyx_v_warns);
+  __Pyx_XDECREF(__pyx_v_errs);
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "astropy/time/sofa_time.pyx":658
+ * @cython.wraparound(False)
+ * @cython.boundscheck(False)
+ * def tai_utc(             # <<<<<<<<<<<<<<
+ *     np.ndarray[double, ndim=1] in1,
+ *     np.ndarray[double, ndim=1] in2):
+ */
+
+static PyObject *__pyx_pf_7astropy_4time_9sofa_time_12tai_utc(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_7astropy_4time_9sofa_time_12tai_utc[] = "\n    int iauTaiutc(double tai1, double tai2, double *utc1, double *utc2)\n\n    **  Given:\n    **     tai1,tai2  double   TAI as a 2-part Julian Date (Note 1)\n    **\n    **  Returned:\n    **     utc1,utc2  double   UTC as a 2-part quasi Julian Date (Notes 1-3)\n    **\n    **  Returned (function value):\n    **                int      status: +1 = dubious year (Note 4)\n    **                                  0 = OK\n    **                                 -1 = unacceptable date\n    **\n    **  Notes:\n    **\n    **  1) tai1+tai2 is Julian Date, apportioned in any convenient way\n    **     between the two arguments, for example where tai1 is the Julian\n    **     Day Number and tai2 is the fraction of a day.  The returned utc1\n    **     and utc2 form an analogous pair, except that a special convention\n    **     is used, to deal with the problem of leap seconds - see the next\n    **     note.\n    **\n    **  2) JD cannot unambiguously represent UTC during a leap second unless\n    **     special measures are taken.  The convention in the present\n    **     function is that the JD day represents UTC days whether the\n    **     length is 86399, 86400 or 86401 SI seconds.\n    **\n    **  3) The function iauD2dtf can be used to transform the UTC quasi-JD\n    **     into calendar date and clock time, including UTC leap second\n    **     handling.\n    **\n    **  4) The warning status \"dubious year\" flags UTCs that predate the\n    **     introduction of the time scale and that are too far in the future\n    **     to be trusted.  See iauDat for further details.\n        ";
+static PyMethodDef __pyx_mdef_7astropy_4time_9sofa_time_12tai_utc = {__Pyx_NAMESTR("tai_utc"), (PyCFunction)__pyx_pf_7astropy_4time_9sofa_time_12tai_utc, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(__pyx_doc_7astropy_4time_9sofa_time_12tai_utc)};
+static PyObject *__pyx_pf_7astropy_4time_9sofa_time_12tai_utc(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyArrayObject *__pyx_v_in1 = 0;
+  PyArrayObject *__pyx_v_in2 = 0;
+  unsigned int __pyx_v_n;
+  unsigned int __pyx_v_i;
+  PyArrayObject *__pyx_v_out1 = 0;
+  PyArrayObject *__pyx_v_out2 = 0;
+  PyObject *__pyx_v_warns = NULL;
+  PyObject *__pyx_v_errs = NULL;
+  int __pyx_v_ret;
+  Py_buffer __pyx_bstruct_out1;
+  Py_ssize_t __pyx_bstride_0_out1 = 0;
+  Py_ssize_t __pyx_bshape_0_out1 = 0;
+  Py_buffer __pyx_bstruct_out2;
+  Py_ssize_t __pyx_bstride_0_out2 = 0;
+  Py_ssize_t __pyx_bshape_0_out2 = 0;
+  Py_buffer __pyx_bstruct_in1;
+  Py_ssize_t __pyx_bstride_0_in1 = 0;
+  Py_ssize_t __pyx_bshape_0_in1 = 0;
+  Py_buffer __pyx_bstruct_in2;
+  Py_ssize_t __pyx_bstride_0_in2 = 0;
+  Py_ssize_t __pyx_bshape_0_in2 = 0;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
+  PyObject *__pyx_t_5 = NULL;
+  PyArrayObject *__pyx_t_6 = NULL;
+  PyArrayObject *__pyx_t_7 = NULL;
+  unsigned int __pyx_t_8;
+  unsigned int __pyx_t_9;
+  unsigned int __pyx_t_10;
+  unsigned int __pyx_t_11;
+  unsigned int __pyx_t_12;
+  unsigned int __pyx_t_13;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__in1,&__pyx_n_s__in2,0};
+  __Pyx_RefNannySetupContext("tai_utc");
+  __pyx_self = __pyx_self;
+  {
+    PyObject* values[2] = {0,0};
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  0:
+        values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__in1);
+        if (likely(values[0])) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+        case  1:
+        values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__in2);
+        if (likely(values[1])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("tai_utc", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 658; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "tai_utc") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 658; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+    } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
+      goto __pyx_L5_argtuple_error;
+    } else {
+      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+    }
+    __pyx_v_in1 = ((PyArrayObject *)values[0]);
+    __pyx_v_in2 = ((PyArrayObject *)values[1]);
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("tai_utc", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 658; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("astropy.time.sofa_time.tai_utc", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_bstruct_out1.buf = NULL;
+  __pyx_bstruct_out2.buf = NULL;
+  __pyx_bstruct_in1.buf = NULL;
+  __pyx_bstruct_in2.buf = NULL;
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_in1), __pyx_ptype_5numpy_ndarray, 1, "in1", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 659; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_in2), __pyx_ptype_5numpy_ndarray, 1, "in2", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 660; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_in1, (PyObject*)__pyx_v_in1, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 658; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_in1 = __pyx_bstruct_in1.strides[0];
+  __pyx_bshape_0_in1 = __pyx_bstruct_in1.shape[0];
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_in2, (PyObject*)__pyx_v_in2, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 658; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_in2 = __pyx_bstruct_in2.strides[0];
+  __pyx_bshape_0_in2 = __pyx_bstruct_in2.shape[0];
+
+  /* "astropy/time/sofa_time.pyx":697
+ *     **     to be trusted.  See iauDat for further details.
+ *         """
+ *     assert in1.shape[0] == in2.shape[0]             # <<<<<<<<<<<<<<
+ *     cdef unsigned n = in1.shape[0]
+ *     cdef unsigned int i
+ */
+  #ifndef CYTHON_WITHOUT_ASSERTIONS
+  if (unlikely(!((__pyx_v_in1->dimensions[0]) == (__pyx_v_in2->dimensions[0])))) {
+    PyErr_SetNone(PyExc_AssertionError);
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 697; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  #endif
+
+  /* "astropy/time/sofa_time.pyx":698
+ *         """
+ *     assert in1.shape[0] == in2.shape[0]
+ *     cdef unsigned n = in1.shape[0]             # <<<<<<<<<<<<<<
+ *     cdef unsigned int i
+ *     cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)
+ */
+  __pyx_v_n = (__pyx_v_in1->dimensions[0]);
+
+  /* "astropy/time/sofa_time.pyx":700
+ *     cdef unsigned n = in1.shape[0]
+ *     cdef unsigned int i
+ *     cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)             # <<<<<<<<<<<<<<
+ *     cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)
+ * 
+ */
+  __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 700; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_2 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s__empty); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 700; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __pyx_t_1 = PyLong_FromUnsignedLong(__pyx_v_n); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 700; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 700; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_3));
+  PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_1);
+  __Pyx_GIVEREF(__pyx_t_1);
+  __pyx_t_1 = 0;
+  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 700; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_1));
+  __pyx_t_4 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 700; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_4);
+  __pyx_t_5 = PyObject_GetAttr(__pyx_t_4, __pyx_n_s__double); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 700; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_n_s__dtype), __pyx_t_5) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 700; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  __pyx_t_5 = PyEval_CallObjectWithKeywords(__pyx_t_2, ((PyObject *)__pyx_t_3), ((PyObject *)__pyx_t_1)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 700; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
+  if (!(likely(((__pyx_t_5) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_5, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 700; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_6 = ((PyArrayObject *)__pyx_t_5);
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_out1, (PyObject*)__pyx_t_6, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {
+      __pyx_v_out1 = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_out1.buf = NULL;
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 700; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    } else {__pyx_bstride_0_out1 = __pyx_bstruct_out1.strides[0];
+      __pyx_bshape_0_out1 = __pyx_bstruct_out1.shape[0];
+    }
+  }
+  __pyx_t_6 = 0;
+  __pyx_v_out1 = ((PyArrayObject *)__pyx_t_5);
+  __pyx_t_5 = 0;
+
+  /* "astropy/time/sofa_time.pyx":701
+ *     cdef unsigned int i
+ *     cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)
+ *     cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)             # <<<<<<<<<<<<<<
+ * 
+ *     warns = {1: DUBIOUS}
+ */
+  __pyx_t_5 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 701; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __pyx_t_1 = PyObject_GetAttr(__pyx_t_5, __pyx_n_s__empty); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 701; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  __pyx_t_5 = PyLong_FromUnsignedLong(__pyx_v_n); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 701; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 701; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_3));
+  PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_5);
+  __Pyx_GIVEREF(__pyx_t_5);
+  __pyx_t_5 = 0;
+  __pyx_t_5 = PyDict_New(); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 701; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_5));
+  __pyx_t_2 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 701; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_4 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s__double); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 701; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_4);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  if (PyDict_SetItem(__pyx_t_5, ((PyObject *)__pyx_n_s__dtype), __pyx_t_4) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 701; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  __pyx_t_4 = PyEval_CallObjectWithKeywords(__pyx_t_1, ((PyObject *)__pyx_t_3), ((PyObject *)__pyx_t_5)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 701; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_4);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_5)); __pyx_t_5 = 0;
+  if (!(likely(((__pyx_t_4) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_4, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 701; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_7 = ((PyArrayObject *)__pyx_t_4);
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_out2, (PyObject*)__pyx_t_7, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {
+      __pyx_v_out2 = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_out2.buf = NULL;
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 701; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    } else {__pyx_bstride_0_out2 = __pyx_bstruct_out2.strides[0];
+      __pyx_bshape_0_out2 = __pyx_bstruct_out2.shape[0];
+    }
+  }
+  __pyx_t_7 = 0;
+  __pyx_v_out2 = ((PyArrayObject *)__pyx_t_4);
+  __pyx_t_4 = 0;
+
+  /* "astropy/time/sofa_time.pyx":703
+ *     cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)
+ * 
+ *     warns = {1: DUBIOUS}             # <<<<<<<<<<<<<<
+ *     errs = {-1: 'unacceptable date'}
+ * 
+ */
+  __pyx_t_4 = PyDict_New(); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 703; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_4));
+  __pyx_t_5 = __Pyx_GetName(__pyx_m, __pyx_n_s__DUBIOUS); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 703; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  if (PyDict_SetItem(__pyx_t_4, __pyx_int_1, __pyx_t_5) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 703; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  __pyx_v_warns = __pyx_t_4;
+  __pyx_t_4 = 0;
+
+  /* "astropy/time/sofa_time.pyx":704
+ * 
+ *     warns = {1: DUBIOUS}
+ *     errs = {-1: 'unacceptable date'}             # <<<<<<<<<<<<<<
+ * 
+ *     for i in range(n):
+ */
+  __pyx_t_4 = PyDict_New(); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 704; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_4));
+  if (PyDict_SetItem(__pyx_t_4, __pyx_int_neg_1, ((PyObject *)__pyx_kp_s_12)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 704; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_v_errs = __pyx_t_4;
+  __pyx_t_4 = 0;
+
+  /* "astropy/time/sofa_time.pyx":706
+ *     errs = {-1: 'unacceptable date'}
+ * 
+ *     for i in range(n):             # <<<<<<<<<<<<<<
+ *         ret = iauTaiutc(in1[i], in2[i], &out1[i], &out2[i])
+ *         check_return(ret, 'iauTaiutc', warns, errs)
+ */
+  __pyx_t_8 = __pyx_v_n;
+  for (__pyx_t_9 = 0; __pyx_t_9 < __pyx_t_8; __pyx_t_9+=1) {
+    __pyx_v_i = __pyx_t_9;
+
+    /* "astropy/time/sofa_time.pyx":707
+ * 
+ *     for i in range(n):
+ *         ret = iauTaiutc(in1[i], in2[i], &out1[i], &out2[i])             # <<<<<<<<<<<<<<
+ *         check_return(ret, 'iauTaiutc', warns, errs)
+ * 
+ */
+    __pyx_t_10 = __pyx_v_i;
+    __pyx_t_11 = __pyx_v_i;
+    __pyx_t_12 = __pyx_v_i;
+    __pyx_t_13 = __pyx_v_i;
+    __pyx_v_ret = iauTaiutc((*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_in1.buf, __pyx_t_10, __pyx_bstride_0_in1)), (*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_in2.buf, __pyx_t_11, __pyx_bstride_0_in2)), (&(*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_out1.buf, __pyx_t_12, __pyx_bstride_0_out1))), (&(*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_out2.buf, __pyx_t_13, __pyx_bstride_0_out2))));
+
+    /* "astropy/time/sofa_time.pyx":708
+ *     for i in range(n):
+ *         ret = iauTaiutc(in1[i], in2[i], &out1[i], &out2[i])
+ *         check_return(ret, 'iauTaiutc', warns, errs)             # <<<<<<<<<<<<<<
+ * 
+ *     return out1, out2
+ */
+    __pyx_t_4 = __Pyx_GetName(__pyx_m, __pyx_n_s__check_return); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 708; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_4);
+    __pyx_t_5 = PyInt_FromLong(__pyx_v_ret); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 708; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_5);
+    __pyx_t_3 = PyTuple_New(4); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 708; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(((PyObject *)__pyx_t_3));
+    PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_5);
+    __Pyx_GIVEREF(__pyx_t_5);
+    __Pyx_INCREF(((PyObject *)__pyx_n_s__iauTaiutc));
+    PyTuple_SET_ITEM(__pyx_t_3, 1, ((PyObject *)__pyx_n_s__iauTaiutc));
+    __Pyx_GIVEREF(((PyObject *)__pyx_n_s__iauTaiutc));
+    __Pyx_INCREF(((PyObject *)__pyx_v_warns));
+    PyTuple_SET_ITEM(__pyx_t_3, 2, ((PyObject *)__pyx_v_warns));
+    __Pyx_GIVEREF(((PyObject *)__pyx_v_warns));
+    __Pyx_INCREF(((PyObject *)__pyx_v_errs));
+    PyTuple_SET_ITEM(__pyx_t_3, 3, ((PyObject *)__pyx_v_errs));
+    __Pyx_GIVEREF(((PyObject *)__pyx_v_errs));
+    __pyx_t_5 = 0;
+    __pyx_t_5 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 708; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_5);
+    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+    __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
+    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  }
+
+  /* "astropy/time/sofa_time.pyx":710
+ *         check_return(ret, 'iauTaiutc', warns, errs)
+ * 
+ *     return out1, out2             # <<<<<<<<<<<<<<
+ * 
+ * 
+ */
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_t_5 = PyTuple_New(2); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 710; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_5));
+  __Pyx_INCREF(((PyObject *)__pyx_v_out1));
+  PyTuple_SET_ITEM(__pyx_t_5, 0, ((PyObject *)__pyx_v_out1));
+  __Pyx_GIVEREF(((PyObject *)__pyx_v_out1));
+  __Pyx_INCREF(((PyObject *)__pyx_v_out2));
+  PyTuple_SET_ITEM(__pyx_t_5, 1, ((PyObject *)__pyx_v_out2));
+  __Pyx_GIVEREF(((PyObject *)__pyx_v_out2));
+  __pyx_r = ((PyObject *)__pyx_t_5);
+  __pyx_t_5 = 0;
+  goto __pyx_L0;
+
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_XDECREF(__pyx_t_5);
+  { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;
+    __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out1);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out2);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in1);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in2);
+  __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
+  __Pyx_AddTraceback("astropy.time.sofa_time.tai_utc", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  goto __pyx_L2;
+  __pyx_L0:;
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out1);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out2);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in1);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in2);
+  __pyx_L2:;
+  __Pyx_XDECREF((PyObject *)__pyx_v_out1);
+  __Pyx_XDECREF((PyObject *)__pyx_v_out2);
+  __Pyx_XDECREF(__pyx_v_warns);
+  __Pyx_XDECREF(__pyx_v_errs);
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "astropy/time/sofa_time.pyx":715
+ * @cython.wraparound(False)
+ * @cython.boundscheck(False)
+ * def tai_ut1(             # <<<<<<<<<<<<<<
+ *     np.ndarray[double, ndim=1] in1,
+ *     np.ndarray[double, ndim=1] in2,
+ */
+
+static PyObject *__pyx_pf_7astropy_4time_9sofa_time_13tai_ut1(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_7astropy_4time_9sofa_time_13tai_ut1[] = "\n    int iauTaiut1(double tai1, double tai2, double dta, double *ut11, double *ut12)\n\n    **  Given:\n    **     tai1,tai2  double    TAI as a 2-part Julian Date\n    **     dta        double    UT1-TAI in seconds\n    **\n    **  Returned:\n    **     ut11,ut12  double    UT1 as a 2-part Julian Date\n    **\n    **  Returned (function value):\n    **                int       status:  0 = OK\n    **\n    **  Notes:\n    **\n    **  1) tai1+tai2 is Julian Date, apportioned in any convenient way\n    **     between the two arguments, for example where tai1 is the Julian\n    **     Day Number and tai2 is the fraction of a day.  The returned\n    **     UT11,UT12 follow suit.\n    **\n    **  2) The argument dta, i.e. UT1-TAI, is an observed quantity, and is\n    **     available from IERS tabulations.\n    ";
+static PyMethodDef __pyx_mdef_7astropy_4time_9sofa_time_13tai_ut1 = {__Pyx_NAMESTR("tai_ut1"), (PyCFunction)__pyx_pf_7astropy_4time_9sofa_time_13tai_ut1, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(__pyx_doc_7astropy_4time_9sofa_time_13tai_ut1)};
+static PyObject *__pyx_pf_7astropy_4time_9sofa_time_13tai_ut1(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyArrayObject *__pyx_v_in1 = 0;
+  PyArrayObject *__pyx_v_in2 = 0;
+  PyArrayObject *__pyx_v_dt = 0;
+  unsigned int __pyx_v_n;
+  unsigned int __pyx_v_i;
+  PyArrayObject *__pyx_v_out1 = 0;
+  PyArrayObject *__pyx_v_out2 = 0;
+  int __pyx_v_ret;
+  Py_buffer __pyx_bstruct_out1;
+  Py_ssize_t __pyx_bstride_0_out1 = 0;
+  Py_ssize_t __pyx_bshape_0_out1 = 0;
+  Py_buffer __pyx_bstruct_out2;
+  Py_ssize_t __pyx_bstride_0_out2 = 0;
+  Py_ssize_t __pyx_bshape_0_out2 = 0;
+  Py_buffer __pyx_bstruct_in1;
+  Py_ssize_t __pyx_bstride_0_in1 = 0;
+  Py_ssize_t __pyx_bshape_0_in1 = 0;
+  Py_buffer __pyx_bstruct_in2;
+  Py_ssize_t __pyx_bstride_0_in2 = 0;
+  Py_ssize_t __pyx_bshape_0_in2 = 0;
+  Py_buffer __pyx_bstruct_dt;
+  Py_ssize_t __pyx_bstride_0_dt = 0;
+  Py_ssize_t __pyx_bshape_0_dt = 0;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  int __pyx_t_1;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
+  PyObject *__pyx_t_5 = NULL;
+  PyObject *__pyx_t_6 = NULL;
+  PyArrayObject *__pyx_t_7 = NULL;
+  PyArrayObject *__pyx_t_8 = NULL;
+  unsigned int __pyx_t_9;
+  unsigned int __pyx_t_10;
+  unsigned int __pyx_t_11;
+  unsigned int __pyx_t_12;
+  unsigned int __pyx_t_13;
+  unsigned int __pyx_t_14;
+  unsigned int __pyx_t_15;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__in1,&__pyx_n_s__in2,&__pyx_n_s__dt,0};
+  __Pyx_RefNannySetupContext("tai_ut1");
+  __pyx_self = __pyx_self;
+  {
+    PyObject* values[3] = {0,0,0};
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  0:
+        values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__in1);
+        if (likely(values[0])) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+        case  1:
+        values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__in2);
+        if (likely(values[1])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("tai_ut1", 1, 3, 3, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 715; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+        case  2:
+        values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__dt);
+        if (likely(values[2])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("tai_ut1", 1, 3, 3, 2); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 715; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "tai_ut1") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 715; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+    } else if (PyTuple_GET_SIZE(__pyx_args) != 3) {
+      goto __pyx_L5_argtuple_error;
+    } else {
+      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+      values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+    }
+    __pyx_v_in1 = ((PyArrayObject *)values[0]);
+    __pyx_v_in2 = ((PyArrayObject *)values[1]);
+    __pyx_v_dt = ((PyArrayObject *)values[2]);
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("tai_ut1", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 715; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("astropy.time.sofa_time.tai_ut1", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_bstruct_out1.buf = NULL;
+  __pyx_bstruct_out2.buf = NULL;
+  __pyx_bstruct_in1.buf = NULL;
+  __pyx_bstruct_in2.buf = NULL;
+  __pyx_bstruct_dt.buf = NULL;
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_in1), __pyx_ptype_5numpy_ndarray, 1, "in1", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 716; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_in2), __pyx_ptype_5numpy_ndarray, 1, "in2", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 717; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_dt), __pyx_ptype_5numpy_ndarray, 1, "dt", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 718; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_in1, (PyObject*)__pyx_v_in1, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 715; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_in1 = __pyx_bstruct_in1.strides[0];
+  __pyx_bshape_0_in1 = __pyx_bstruct_in1.shape[0];
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_in2, (PyObject*)__pyx_v_in2, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 715; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_in2 = __pyx_bstruct_in2.strides[0];
+  __pyx_bshape_0_in2 = __pyx_bstruct_in2.shape[0];
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_dt, (PyObject*)__pyx_v_dt, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 715; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_dt = __pyx_bstruct_dt.strides[0];
+  __pyx_bshape_0_dt = __pyx_bstruct_dt.shape[0];
+
+  /* "astropy/time/sofa_time.pyx":742
+ *     **     available from IERS tabulations.
+ *     """
+ *     assert in1.shape[0] == in2.shape[0] == dt.shape[0]             # <<<<<<<<<<<<<<
+ *     cdef unsigned n = in1.shape[0]
+ *     cdef unsigned int i
+ */
+  #ifndef CYTHON_WITHOUT_ASSERTIONS
+  __pyx_t_1 = ((__pyx_v_in1->dimensions[0]) == (__pyx_v_in2->dimensions[0]));
+  if (__pyx_t_1) {
+    __pyx_t_1 = ((__pyx_v_in2->dimensions[0]) == (__pyx_v_dt->dimensions[0]));
+  }
+  if (unlikely(!__pyx_t_1)) {
+    PyErr_SetNone(PyExc_AssertionError);
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 742; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  #endif
+
+  /* "astropy/time/sofa_time.pyx":743
+ *     """
+ *     assert in1.shape[0] == in2.shape[0] == dt.shape[0]
+ *     cdef unsigned n = in1.shape[0]             # <<<<<<<<<<<<<<
+ *     cdef unsigned int i
+ *     cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)
+ */
+  __pyx_v_n = (__pyx_v_in1->dimensions[0]);
+
+  /* "astropy/time/sofa_time.pyx":745
+ *     cdef unsigned n = in1.shape[0]
+ *     cdef unsigned int i
+ *     cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)             # <<<<<<<<<<<<<<
+ *     cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)
+ * 
+ */
+  __pyx_t_2 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 745; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_3 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s__empty); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 745; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __pyx_t_2 = PyLong_FromUnsignedLong(__pyx_v_n); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 745; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 745; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_4));
+  PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_2);
+  __Pyx_GIVEREF(__pyx_t_2);
+  __pyx_t_2 = 0;
+  __pyx_t_2 = PyDict_New(); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 745; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_2));
+  __pyx_t_5 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 745; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __pyx_t_6 = PyObject_GetAttr(__pyx_t_5, __pyx_n_s__double); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 745; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_6);
+  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  if (PyDict_SetItem(__pyx_t_2, ((PyObject *)__pyx_n_s__dtype), __pyx_t_6) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 745; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+  __pyx_t_6 = PyEval_CallObjectWithKeywords(__pyx_t_3, ((PyObject *)__pyx_t_4), ((PyObject *)__pyx_t_2)); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 745; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_6);
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
+  if (!(likely(((__pyx_t_6) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_6, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 745; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_7 = ((PyArrayObject *)__pyx_t_6);
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_out1, (PyObject*)__pyx_t_7, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {
+      __pyx_v_out1 = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_out1.buf = NULL;
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 745; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    } else {__pyx_bstride_0_out1 = __pyx_bstruct_out1.strides[0];
+      __pyx_bshape_0_out1 = __pyx_bstruct_out1.shape[0];
+    }
+  }
+  __pyx_t_7 = 0;
+  __pyx_v_out1 = ((PyArrayObject *)__pyx_t_6);
+  __pyx_t_6 = 0;
+
+  /* "astropy/time/sofa_time.pyx":746
+ *     cdef unsigned int i
+ *     cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)
+ *     cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)             # <<<<<<<<<<<<<<
+ * 
+ *     for i in range(n):
+ */
+  __pyx_t_6 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 746; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_6);
+  __pyx_t_2 = PyObject_GetAttr(__pyx_t_6, __pyx_n_s__empty); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 746; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+  __pyx_t_6 = PyLong_FromUnsignedLong(__pyx_v_n); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 746; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_6);
+  __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 746; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_4));
+  PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_6);
+  __Pyx_GIVEREF(__pyx_t_6);
+  __pyx_t_6 = 0;
+  __pyx_t_6 = PyDict_New(); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 746; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_6));
+  __pyx_t_3 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 746; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __pyx_t_5 = PyObject_GetAttr(__pyx_t_3, __pyx_n_s__double); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 746; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  if (PyDict_SetItem(__pyx_t_6, ((PyObject *)__pyx_n_s__dtype), __pyx_t_5) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 746; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  __pyx_t_5 = PyEval_CallObjectWithKeywords(__pyx_t_2, ((PyObject *)__pyx_t_4), ((PyObject *)__pyx_t_6)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 746; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_6)); __pyx_t_6 = 0;
+  if (!(likely(((__pyx_t_5) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_5, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 746; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_8 = ((PyArrayObject *)__pyx_t_5);
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_out2, (PyObject*)__pyx_t_8, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {
+      __pyx_v_out2 = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_out2.buf = NULL;
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 746; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    } else {__pyx_bstride_0_out2 = __pyx_bstruct_out2.strides[0];
+      __pyx_bshape_0_out2 = __pyx_bstruct_out2.shape[0];
+    }
+  }
+  __pyx_t_8 = 0;
+  __pyx_v_out2 = ((PyArrayObject *)__pyx_t_5);
+  __pyx_t_5 = 0;
+
+  /* "astropy/time/sofa_time.pyx":748
+ *     cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)
+ * 
+ *     for i in range(n):             # <<<<<<<<<<<<<<
+ *         ret = iauTaiut1(in1[i], in2[i], dt[i], &out1[i], &out2[i])
+ *         check_return(ret, 'iauTaiut1')
+ */
+  __pyx_t_9 = __pyx_v_n;
+  for (__pyx_t_10 = 0; __pyx_t_10 < __pyx_t_9; __pyx_t_10+=1) {
+    __pyx_v_i = __pyx_t_10;
+
+    /* "astropy/time/sofa_time.pyx":749
+ * 
+ *     for i in range(n):
+ *         ret = iauTaiut1(in1[i], in2[i], dt[i], &out1[i], &out2[i])             # <<<<<<<<<<<<<<
+ *         check_return(ret, 'iauTaiut1')
+ * 
+ */
+    __pyx_t_11 = __pyx_v_i;
+    __pyx_t_12 = __pyx_v_i;
+    __pyx_t_13 = __pyx_v_i;
+    __pyx_t_14 = __pyx_v_i;
+    __pyx_t_15 = __pyx_v_i;
+    __pyx_v_ret = iauTaiut1((*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_in1.buf, __pyx_t_11, __pyx_bstride_0_in1)), (*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_in2.buf, __pyx_t_12, __pyx_bstride_0_in2)), (*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_dt.buf, __pyx_t_13, __pyx_bstride_0_dt)), (&(*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_out1.buf, __pyx_t_14, __pyx_bstride_0_out1))), (&(*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_out2.buf, __pyx_t_15, __pyx_bstride_0_out2))));
+
+    /* "astropy/time/sofa_time.pyx":750
+ *     for i in range(n):
+ *         ret = iauTaiut1(in1[i], in2[i], dt[i], &out1[i], &out2[i])
+ *         check_return(ret, 'iauTaiut1')             # <<<<<<<<<<<<<<
+ * 
+ *     return out1, out2
+ */
+    __pyx_t_5 = __Pyx_GetName(__pyx_m, __pyx_n_s__check_return); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 750; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_5);
+    __pyx_t_6 = PyInt_FromLong(__pyx_v_ret); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 750; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_6);
+    __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 750; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(((PyObject *)__pyx_t_4));
+    PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_6);
+    __Pyx_GIVEREF(__pyx_t_6);
+    __Pyx_INCREF(((PyObject *)__pyx_n_s__iauTaiut1));
+    PyTuple_SET_ITEM(__pyx_t_4, 1, ((PyObject *)__pyx_n_s__iauTaiut1));
+    __Pyx_GIVEREF(((PyObject *)__pyx_n_s__iauTaiut1));
+    __pyx_t_6 = 0;
+    __pyx_t_6 = PyObject_Call(__pyx_t_5, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 750; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_6);
+    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+    __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
+    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+  }
+
+  /* "astropy/time/sofa_time.pyx":752
+ *         check_return(ret, 'iauTaiut1')
+ * 
+ *     return out1, out2             # <<<<<<<<<<<<<<
+ * 
+ * 
+ */
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_t_6 = PyTuple_New(2); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 752; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_6));
+  __Pyx_INCREF(((PyObject *)__pyx_v_out1));
+  PyTuple_SET_ITEM(__pyx_t_6, 0, ((PyObject *)__pyx_v_out1));
+  __Pyx_GIVEREF(((PyObject *)__pyx_v_out1));
+  __Pyx_INCREF(((PyObject *)__pyx_v_out2));
+  PyTuple_SET_ITEM(__pyx_t_6, 1, ((PyObject *)__pyx_v_out2));
+  __Pyx_GIVEREF(((PyObject *)__pyx_v_out2));
+  __pyx_r = ((PyObject *)__pyx_t_6);
+  __pyx_t_6 = 0;
+  goto __pyx_L0;
+
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_XDECREF(__pyx_t_5);
+  __Pyx_XDECREF(__pyx_t_6);
+  { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;
+    __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out1);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out2);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in1);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in2);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_dt);
+  __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
+  __Pyx_AddTraceback("astropy.time.sofa_time.tai_ut1", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  goto __pyx_L2;
+  __pyx_L0:;
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out1);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out2);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in1);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in2);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_dt);
+  __pyx_L2:;
+  __Pyx_XDECREF((PyObject *)__pyx_v_out1);
+  __Pyx_XDECREF((PyObject *)__pyx_v_out2);
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "astropy/time/sofa_time.pyx":757
+ * @cython.wraparound(False)
+ * @cython.boundscheck(False)
+ * def ut1_tai(             # <<<<<<<<<<<<<<
+ *     np.ndarray[double, ndim=1] in1,
+ *     np.ndarray[double, ndim=1] in2,
+ */
+
+static PyObject *__pyx_pf_7astropy_4time_9sofa_time_14ut1_tai(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_7astropy_4time_9sofa_time_14ut1_tai[] = "\n    int iauUt1tai(double ut11, double ut12, double dta, double *tai1, double *tai2)\n\n    **  Given:\n    **     ut11,ut12  double    UT1 as a 2-part Julian Date\n    **     dta        double    UT1-TAI in seconds\n    **\n    **  Returned:\n    **     tai1,tai2  double    TAI as a 2-part Julian Date\n    **\n    **  Returned (function value):\n    **                int       status:  0 = OK\n    **\n    **  Notes:\n    **\n    **  1) ut11+ut12 is Julian Date, apportioned in any convenient way\n    **     between the two arguments, for example where ut11 is the Julian\n    **     Day Number and ut12 is the fraction of a day.  The returned\n    **     tai1,tai2 follow suit.\n    **\n    **  2) The argument dta, i.e. UT1-TAI, is an observed quantity, and is\n    **     available from IERS tabulations.\n    ";
+static PyMethodDef __pyx_mdef_7astropy_4time_9sofa_time_14ut1_tai = {__Pyx_NAMESTR("ut1_tai"), (PyCFunction)__pyx_pf_7astropy_4time_9sofa_time_14ut1_tai, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(__pyx_doc_7astropy_4time_9sofa_time_14ut1_tai)};
+static PyObject *__pyx_pf_7astropy_4time_9sofa_time_14ut1_tai(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyArrayObject *__pyx_v_in1 = 0;
+  PyArrayObject *__pyx_v_in2 = 0;
+  PyArrayObject *__pyx_v_dt = 0;
+  unsigned int __pyx_v_n;
+  unsigned int __pyx_v_i;
+  PyArrayObject *__pyx_v_out1 = 0;
+  PyArrayObject *__pyx_v_out2 = 0;
+  int __pyx_v_ret;
+  Py_buffer __pyx_bstruct_out1;
+  Py_ssize_t __pyx_bstride_0_out1 = 0;
+  Py_ssize_t __pyx_bshape_0_out1 = 0;
+  Py_buffer __pyx_bstruct_out2;
+  Py_ssize_t __pyx_bstride_0_out2 = 0;
+  Py_ssize_t __pyx_bshape_0_out2 = 0;
+  Py_buffer __pyx_bstruct_in1;
+  Py_ssize_t __pyx_bstride_0_in1 = 0;
+  Py_ssize_t __pyx_bshape_0_in1 = 0;
+  Py_buffer __pyx_bstruct_in2;
+  Py_ssize_t __pyx_bstride_0_in2 = 0;
+  Py_ssize_t __pyx_bshape_0_in2 = 0;
+  Py_buffer __pyx_bstruct_dt;
+  Py_ssize_t __pyx_bstride_0_dt = 0;
+  Py_ssize_t __pyx_bshape_0_dt = 0;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  int __pyx_t_1;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
+  PyObject *__pyx_t_5 = NULL;
+  PyObject *__pyx_t_6 = NULL;
+  PyArrayObject *__pyx_t_7 = NULL;
+  PyArrayObject *__pyx_t_8 = NULL;
+  unsigned int __pyx_t_9;
+  unsigned int __pyx_t_10;
+  unsigned int __pyx_t_11;
+  unsigned int __pyx_t_12;
+  unsigned int __pyx_t_13;
+  unsigned int __pyx_t_14;
+  unsigned int __pyx_t_15;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__in1,&__pyx_n_s__in2,&__pyx_n_s__dt,0};
+  __Pyx_RefNannySetupContext("ut1_tai");
+  __pyx_self = __pyx_self;
+  {
+    PyObject* values[3] = {0,0,0};
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  0:
+        values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__in1);
+        if (likely(values[0])) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+        case  1:
+        values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__in2);
+        if (likely(values[1])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("ut1_tai", 1, 3, 3, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 757; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+        case  2:
+        values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__dt);
+        if (likely(values[2])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("ut1_tai", 1, 3, 3, 2); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 757; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "ut1_tai") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 757; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+    } else if (PyTuple_GET_SIZE(__pyx_args) != 3) {
+      goto __pyx_L5_argtuple_error;
+    } else {
+      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+      values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+    }
+    __pyx_v_in1 = ((PyArrayObject *)values[0]);
+    __pyx_v_in2 = ((PyArrayObject *)values[1]);
+    __pyx_v_dt = ((PyArrayObject *)values[2]);
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("ut1_tai", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 757; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("astropy.time.sofa_time.ut1_tai", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_bstruct_out1.buf = NULL;
+  __pyx_bstruct_out2.buf = NULL;
+  __pyx_bstruct_in1.buf = NULL;
+  __pyx_bstruct_in2.buf = NULL;
+  __pyx_bstruct_dt.buf = NULL;
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_in1), __pyx_ptype_5numpy_ndarray, 1, "in1", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 758; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_in2), __pyx_ptype_5numpy_ndarray, 1, "in2", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 759; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_dt), __pyx_ptype_5numpy_ndarray, 1, "dt", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 760; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_in1, (PyObject*)__pyx_v_in1, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 757; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_in1 = __pyx_bstruct_in1.strides[0];
+  __pyx_bshape_0_in1 = __pyx_bstruct_in1.shape[0];
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_in2, (PyObject*)__pyx_v_in2, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 757; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_in2 = __pyx_bstruct_in2.strides[0];
+  __pyx_bshape_0_in2 = __pyx_bstruct_in2.shape[0];
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_dt, (PyObject*)__pyx_v_dt, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 757; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_dt = __pyx_bstruct_dt.strides[0];
+  __pyx_bshape_0_dt = __pyx_bstruct_dt.shape[0];
+
+  /* "astropy/time/sofa_time.pyx":784
+ *     **     available from IERS tabulations.
+ *     """
+ *     assert in1.shape[0] == in2.shape[0] == dt.shape[0]             # <<<<<<<<<<<<<<
+ *     cdef unsigned n = in1.shape[0]
+ *     cdef unsigned int i
+ */
+  #ifndef CYTHON_WITHOUT_ASSERTIONS
+  __pyx_t_1 = ((__pyx_v_in1->dimensions[0]) == (__pyx_v_in2->dimensions[0]));
+  if (__pyx_t_1) {
+    __pyx_t_1 = ((__pyx_v_in2->dimensions[0]) == (__pyx_v_dt->dimensions[0]));
+  }
+  if (unlikely(!__pyx_t_1)) {
+    PyErr_SetNone(PyExc_AssertionError);
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 784; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  #endif
+
+  /* "astropy/time/sofa_time.pyx":785
+ *     """
+ *     assert in1.shape[0] == in2.shape[0] == dt.shape[0]
+ *     cdef unsigned n = in1.shape[0]             # <<<<<<<<<<<<<<
+ *     cdef unsigned int i
+ *     cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)
+ */
+  __pyx_v_n = (__pyx_v_in1->dimensions[0]);
+
+  /* "astropy/time/sofa_time.pyx":787
+ *     cdef unsigned n = in1.shape[0]
+ *     cdef unsigned int i
+ *     cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)             # <<<<<<<<<<<<<<
+ *     cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)
+ * 
+ */
+  __pyx_t_2 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 787; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_3 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s__empty); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 787; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __pyx_t_2 = PyLong_FromUnsignedLong(__pyx_v_n); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 787; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 787; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_4));
+  PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_2);
+  __Pyx_GIVEREF(__pyx_t_2);
+  __pyx_t_2 = 0;
+  __pyx_t_2 = PyDict_New(); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 787; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_2));
+  __pyx_t_5 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 787; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __pyx_t_6 = PyObject_GetAttr(__pyx_t_5, __pyx_n_s__double); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 787; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_6);
+  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  if (PyDict_SetItem(__pyx_t_2, ((PyObject *)__pyx_n_s__dtype), __pyx_t_6) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 787; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+  __pyx_t_6 = PyEval_CallObjectWithKeywords(__pyx_t_3, ((PyObject *)__pyx_t_4), ((PyObject *)__pyx_t_2)); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 787; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_6);
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
+  if (!(likely(((__pyx_t_6) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_6, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 787; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_7 = ((PyArrayObject *)__pyx_t_6);
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_out1, (PyObject*)__pyx_t_7, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {
+      __pyx_v_out1 = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_out1.buf = NULL;
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 787; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    } else {__pyx_bstride_0_out1 = __pyx_bstruct_out1.strides[0];
+      __pyx_bshape_0_out1 = __pyx_bstruct_out1.shape[0];
+    }
+  }
+  __pyx_t_7 = 0;
+  __pyx_v_out1 = ((PyArrayObject *)__pyx_t_6);
+  __pyx_t_6 = 0;
+
+  /* "astropy/time/sofa_time.pyx":788
+ *     cdef unsigned int i
+ *     cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)
+ *     cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)             # <<<<<<<<<<<<<<
+ * 
+ *     for i in range(n):
+ */
+  __pyx_t_6 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 788; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_6);
+  __pyx_t_2 = PyObject_GetAttr(__pyx_t_6, __pyx_n_s__empty); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 788; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+  __pyx_t_6 = PyLong_FromUnsignedLong(__pyx_v_n); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 788; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_6);
+  __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 788; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_4));
+  PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_6);
+  __Pyx_GIVEREF(__pyx_t_6);
+  __pyx_t_6 = 0;
+  __pyx_t_6 = PyDict_New(); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 788; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_6));
+  __pyx_t_3 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 788; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __pyx_t_5 = PyObject_GetAttr(__pyx_t_3, __pyx_n_s__double); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 788; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  if (PyDict_SetItem(__pyx_t_6, ((PyObject *)__pyx_n_s__dtype), __pyx_t_5) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 788; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  __pyx_t_5 = PyEval_CallObjectWithKeywords(__pyx_t_2, ((PyObject *)__pyx_t_4), ((PyObject *)__pyx_t_6)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 788; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_6)); __pyx_t_6 = 0;
+  if (!(likely(((__pyx_t_5) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_5, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 788; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_8 = ((PyArrayObject *)__pyx_t_5);
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_out2, (PyObject*)__pyx_t_8, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {
+      __pyx_v_out2 = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_out2.buf = NULL;
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 788; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    } else {__pyx_bstride_0_out2 = __pyx_bstruct_out2.strides[0];
+      __pyx_bshape_0_out2 = __pyx_bstruct_out2.shape[0];
+    }
+  }
+  __pyx_t_8 = 0;
+  __pyx_v_out2 = ((PyArrayObject *)__pyx_t_5);
+  __pyx_t_5 = 0;
+
+  /* "astropy/time/sofa_time.pyx":790
+ *     cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)
+ * 
+ *     for i in range(n):             # <<<<<<<<<<<<<<
+ *         ret = iauUt1tai(in1[i], in2[i], dt[i], &out1[i], &out2[i])
+ *         check_return(ret, 'iauUt1tai')
+ */
+  __pyx_t_9 = __pyx_v_n;
+  for (__pyx_t_10 = 0; __pyx_t_10 < __pyx_t_9; __pyx_t_10+=1) {
+    __pyx_v_i = __pyx_t_10;
+
+    /* "astropy/time/sofa_time.pyx":791
+ * 
+ *     for i in range(n):
+ *         ret = iauUt1tai(in1[i], in2[i], dt[i], &out1[i], &out2[i])             # <<<<<<<<<<<<<<
+ *         check_return(ret, 'iauUt1tai')
+ * 
+ */
+    __pyx_t_11 = __pyx_v_i;
+    __pyx_t_12 = __pyx_v_i;
+    __pyx_t_13 = __pyx_v_i;
+    __pyx_t_14 = __pyx_v_i;
+    __pyx_t_15 = __pyx_v_i;
+    __pyx_v_ret = iauUt1tai((*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_in1.buf, __pyx_t_11, __pyx_bstride_0_in1)), (*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_in2.buf, __pyx_t_12, __pyx_bstride_0_in2)), (*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_dt.buf, __pyx_t_13, __pyx_bstride_0_dt)), (&(*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_out1.buf, __pyx_t_14, __pyx_bstride_0_out1))), (&(*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_out2.buf, __pyx_t_15, __pyx_bstride_0_out2))));
+
+    /* "astropy/time/sofa_time.pyx":792
+ *     for i in range(n):
+ *         ret = iauUt1tai(in1[i], in2[i], dt[i], &out1[i], &out2[i])
+ *         check_return(ret, 'iauUt1tai')             # <<<<<<<<<<<<<<
+ * 
+ *     return out1, out2
+ */
+    __pyx_t_5 = __Pyx_GetName(__pyx_m, __pyx_n_s__check_return); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 792; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_5);
+    __pyx_t_6 = PyInt_FromLong(__pyx_v_ret); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 792; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_6);
+    __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 792; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(((PyObject *)__pyx_t_4));
+    PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_6);
+    __Pyx_GIVEREF(__pyx_t_6);
+    __Pyx_INCREF(((PyObject *)__pyx_n_s__iauUt1tai));
+    PyTuple_SET_ITEM(__pyx_t_4, 1, ((PyObject *)__pyx_n_s__iauUt1tai));
+    __Pyx_GIVEREF(((PyObject *)__pyx_n_s__iauUt1tai));
+    __pyx_t_6 = 0;
+    __pyx_t_6 = PyObject_Call(__pyx_t_5, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 792; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_6);
+    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+    __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
+    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+  }
+
+  /* "astropy/time/sofa_time.pyx":794
+ *         check_return(ret, 'iauUt1tai')
+ * 
+ *     return out1, out2             # <<<<<<<<<<<<<<
+ * 
+ * 
+ */
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_t_6 = PyTuple_New(2); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 794; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_6));
+  __Pyx_INCREF(((PyObject *)__pyx_v_out1));
+  PyTuple_SET_ITEM(__pyx_t_6, 0, ((PyObject *)__pyx_v_out1));
+  __Pyx_GIVEREF(((PyObject *)__pyx_v_out1));
+  __Pyx_INCREF(((PyObject *)__pyx_v_out2));
+  PyTuple_SET_ITEM(__pyx_t_6, 1, ((PyObject *)__pyx_v_out2));
+  __Pyx_GIVEREF(((PyObject *)__pyx_v_out2));
+  __pyx_r = ((PyObject *)__pyx_t_6);
+  __pyx_t_6 = 0;
+  goto __pyx_L0;
+
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_XDECREF(__pyx_t_5);
+  __Pyx_XDECREF(__pyx_t_6);
+  { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;
+    __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out1);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out2);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in1);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in2);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_dt);
+  __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
+  __Pyx_AddTraceback("astropy.time.sofa_time.ut1_tai", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  goto __pyx_L2;
+  __pyx_L0:;
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out1);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out2);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in1);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in2);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_dt);
+  __pyx_L2:;
+  __Pyx_XDECREF((PyObject *)__pyx_v_out1);
+  __Pyx_XDECREF((PyObject *)__pyx_v_out2);
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "astropy/time/sofa_time.pyx":799
+ * @cython.wraparound(False)
+ * @cython.boundscheck(False)
+ * def tt_ut1(             # <<<<<<<<<<<<<<
+ *     np.ndarray[double, ndim=1] in1,
+ *     np.ndarray[double, ndim=1] in2,
+ */
+
+static PyObject *__pyx_pf_7astropy_4time_9sofa_time_15tt_ut1(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_7astropy_4time_9sofa_time_15tt_ut1[] = "\n    int iauTtut1(double tt1, double tt2, double dt, double *ut11, double *ut12)\n\n    **  Given:\n    **     tt1,tt2    double    TT as a 2-part Julian Date\n    **     dt         double    TT-UT1 in seconds\n    **\n    **  Returned:\n    **     ut11,ut12  double    UT1 as a 2-part Julian Date\n    **\n    **  Returned (function value):\n    **                int       status:  0 = OK\n    **\n    **  Notes:\n    **\n    **  1) tt1+tt2 is Julian Date, apportioned in any convenient way between\n    **     the two arguments, for example where tt1 is the Julian Day Number\n    **     and tt2 is the fraction of a day.  The returned ut11,ut12 follow\n    **     suit.\n    **\n    **  2) The argument dt is classical Delta T.\n    ";
+static PyMethodDef __pyx_mdef_7astropy_4time_9sofa_time_15tt_ut1 = {__Pyx_NAMESTR("tt_ut1"), (PyCFunction)__pyx_pf_7astropy_4time_9sofa_time_15tt_ut1, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(__pyx_doc_7astropy_4time_9sofa_time_15tt_ut1)};
+static PyObject *__pyx_pf_7astropy_4time_9sofa_time_15tt_ut1(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyArrayObject *__pyx_v_in1 = 0;
+  PyArrayObject *__pyx_v_in2 = 0;
+  PyArrayObject *__pyx_v_dt = 0;
+  unsigned int __pyx_v_n;
+  unsigned int __pyx_v_i;
+  PyArrayObject *__pyx_v_out1 = 0;
+  PyArrayObject *__pyx_v_out2 = 0;
+  int __pyx_v_ret;
+  Py_buffer __pyx_bstruct_out1;
+  Py_ssize_t __pyx_bstride_0_out1 = 0;
+  Py_ssize_t __pyx_bshape_0_out1 = 0;
+  Py_buffer __pyx_bstruct_out2;
+  Py_ssize_t __pyx_bstride_0_out2 = 0;
+  Py_ssize_t __pyx_bshape_0_out2 = 0;
+  Py_buffer __pyx_bstruct_in1;
+  Py_ssize_t __pyx_bstride_0_in1 = 0;
+  Py_ssize_t __pyx_bshape_0_in1 = 0;
+  Py_buffer __pyx_bstruct_in2;
+  Py_ssize_t __pyx_bstride_0_in2 = 0;
+  Py_ssize_t __pyx_bshape_0_in2 = 0;
+  Py_buffer __pyx_bstruct_dt;
+  Py_ssize_t __pyx_bstride_0_dt = 0;
+  Py_ssize_t __pyx_bshape_0_dt = 0;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  int __pyx_t_1;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
+  PyObject *__pyx_t_5 = NULL;
+  PyObject *__pyx_t_6 = NULL;
+  PyArrayObject *__pyx_t_7 = NULL;
+  PyArrayObject *__pyx_t_8 = NULL;
+  unsigned int __pyx_t_9;
+  unsigned int __pyx_t_10;
+  unsigned int __pyx_t_11;
+  unsigned int __pyx_t_12;
+  unsigned int __pyx_t_13;
+  unsigned int __pyx_t_14;
+  unsigned int __pyx_t_15;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__in1,&__pyx_n_s__in2,&__pyx_n_s__dt,0};
+  __Pyx_RefNannySetupContext("tt_ut1");
+  __pyx_self = __pyx_self;
+  {
+    PyObject* values[3] = {0,0,0};
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  0:
+        values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__in1);
+        if (likely(values[0])) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+        case  1:
+        values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__in2);
+        if (likely(values[1])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("tt_ut1", 1, 3, 3, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 799; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+        case  2:
+        values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__dt);
+        if (likely(values[2])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("tt_ut1", 1, 3, 3, 2); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 799; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "tt_ut1") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 799; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+    } else if (PyTuple_GET_SIZE(__pyx_args) != 3) {
+      goto __pyx_L5_argtuple_error;
+    } else {
+      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+      values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+    }
+    __pyx_v_in1 = ((PyArrayObject *)values[0]);
+    __pyx_v_in2 = ((PyArrayObject *)values[1]);
+    __pyx_v_dt = ((PyArrayObject *)values[2]);
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("tt_ut1", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 799; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("astropy.time.sofa_time.tt_ut1", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_bstruct_out1.buf = NULL;
+  __pyx_bstruct_out2.buf = NULL;
+  __pyx_bstruct_in1.buf = NULL;
+  __pyx_bstruct_in2.buf = NULL;
+  __pyx_bstruct_dt.buf = NULL;
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_in1), __pyx_ptype_5numpy_ndarray, 1, "in1", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 800; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_in2), __pyx_ptype_5numpy_ndarray, 1, "in2", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 801; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_dt), __pyx_ptype_5numpy_ndarray, 1, "dt", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 802; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_in1, (PyObject*)__pyx_v_in1, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 799; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_in1 = __pyx_bstruct_in1.strides[0];
+  __pyx_bshape_0_in1 = __pyx_bstruct_in1.shape[0];
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_in2, (PyObject*)__pyx_v_in2, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 799; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_in2 = __pyx_bstruct_in2.strides[0];
+  __pyx_bshape_0_in2 = __pyx_bstruct_in2.shape[0];
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_dt, (PyObject*)__pyx_v_dt, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 799; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_dt = __pyx_bstruct_dt.strides[0];
+  __pyx_bshape_0_dt = __pyx_bstruct_dt.shape[0];
+
+  /* "astropy/time/sofa_time.pyx":825
+ *     **  2) The argument dt is classical Delta T.
+ *     """
+ *     assert in1.shape[0] == in2.shape[0] == dt.shape[0]             # <<<<<<<<<<<<<<
+ *     cdef unsigned n = in1.shape[0]
+ *     cdef unsigned int i
+ */
+  #ifndef CYTHON_WITHOUT_ASSERTIONS
+  __pyx_t_1 = ((__pyx_v_in1->dimensions[0]) == (__pyx_v_in2->dimensions[0]));
+  if (__pyx_t_1) {
+    __pyx_t_1 = ((__pyx_v_in2->dimensions[0]) == (__pyx_v_dt->dimensions[0]));
+  }
+  if (unlikely(!__pyx_t_1)) {
+    PyErr_SetNone(PyExc_AssertionError);
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 825; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  #endif
+
+  /* "astropy/time/sofa_time.pyx":826
+ *     """
+ *     assert in1.shape[0] == in2.shape[0] == dt.shape[0]
+ *     cdef unsigned n = in1.shape[0]             # <<<<<<<<<<<<<<
+ *     cdef unsigned int i
+ *     cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)
+ */
+  __pyx_v_n = (__pyx_v_in1->dimensions[0]);
+
+  /* "astropy/time/sofa_time.pyx":828
+ *     cdef unsigned n = in1.shape[0]
+ *     cdef unsigned int i
+ *     cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)             # <<<<<<<<<<<<<<
+ *     cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)
+ * 
+ */
+  __pyx_t_2 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 828; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_3 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s__empty); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 828; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __pyx_t_2 = PyLong_FromUnsignedLong(__pyx_v_n); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 828; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 828; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_4));
+  PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_2);
+  __Pyx_GIVEREF(__pyx_t_2);
+  __pyx_t_2 = 0;
+  __pyx_t_2 = PyDict_New(); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 828; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_2));
+  __pyx_t_5 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 828; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __pyx_t_6 = PyObject_GetAttr(__pyx_t_5, __pyx_n_s__double); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 828; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_6);
+  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  if (PyDict_SetItem(__pyx_t_2, ((PyObject *)__pyx_n_s__dtype), __pyx_t_6) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 828; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+  __pyx_t_6 = PyEval_CallObjectWithKeywords(__pyx_t_3, ((PyObject *)__pyx_t_4), ((PyObject *)__pyx_t_2)); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 828; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_6);
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
+  if (!(likely(((__pyx_t_6) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_6, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 828; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_7 = ((PyArrayObject *)__pyx_t_6);
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_out1, (PyObject*)__pyx_t_7, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {
+      __pyx_v_out1 = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_out1.buf = NULL;
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 828; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    } else {__pyx_bstride_0_out1 = __pyx_bstruct_out1.strides[0];
+      __pyx_bshape_0_out1 = __pyx_bstruct_out1.shape[0];
+    }
+  }
+  __pyx_t_7 = 0;
+  __pyx_v_out1 = ((PyArrayObject *)__pyx_t_6);
+  __pyx_t_6 = 0;
+
+  /* "astropy/time/sofa_time.pyx":829
+ *     cdef unsigned int i
+ *     cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)
+ *     cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)             # <<<<<<<<<<<<<<
+ * 
+ *     for i in range(n):
+ */
+  __pyx_t_6 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 829; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_6);
+  __pyx_t_2 = PyObject_GetAttr(__pyx_t_6, __pyx_n_s__empty); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 829; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+  __pyx_t_6 = PyLong_FromUnsignedLong(__pyx_v_n); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 829; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_6);
+  __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 829; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_4));
+  PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_6);
+  __Pyx_GIVEREF(__pyx_t_6);
+  __pyx_t_6 = 0;
+  __pyx_t_6 = PyDict_New(); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 829; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_6));
+  __pyx_t_3 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 829; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __pyx_t_5 = PyObject_GetAttr(__pyx_t_3, __pyx_n_s__double); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 829; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  if (PyDict_SetItem(__pyx_t_6, ((PyObject *)__pyx_n_s__dtype), __pyx_t_5) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 829; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  __pyx_t_5 = PyEval_CallObjectWithKeywords(__pyx_t_2, ((PyObject *)__pyx_t_4), ((PyObject *)__pyx_t_6)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 829; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_6)); __pyx_t_6 = 0;
+  if (!(likely(((__pyx_t_5) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_5, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 829; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_8 = ((PyArrayObject *)__pyx_t_5);
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_out2, (PyObject*)__pyx_t_8, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {
+      __pyx_v_out2 = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_out2.buf = NULL;
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 829; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    } else {__pyx_bstride_0_out2 = __pyx_bstruct_out2.strides[0];
+      __pyx_bshape_0_out2 = __pyx_bstruct_out2.shape[0];
+    }
+  }
+  __pyx_t_8 = 0;
+  __pyx_v_out2 = ((PyArrayObject *)__pyx_t_5);
+  __pyx_t_5 = 0;
+
+  /* "astropy/time/sofa_time.pyx":831
+ *     cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)
+ * 
+ *     for i in range(n):             # <<<<<<<<<<<<<<
+ *         ret = iauTtut1(in1[i], in2[i], dt[i], &out1[i], &out2[i])
+ *         check_return(ret, 'iauTtut1')
+ */
+  __pyx_t_9 = __pyx_v_n;
+  for (__pyx_t_10 = 0; __pyx_t_10 < __pyx_t_9; __pyx_t_10+=1) {
+    __pyx_v_i = __pyx_t_10;
+
+    /* "astropy/time/sofa_time.pyx":832
+ * 
+ *     for i in range(n):
+ *         ret = iauTtut1(in1[i], in2[i], dt[i], &out1[i], &out2[i])             # <<<<<<<<<<<<<<
+ *         check_return(ret, 'iauTtut1')
+ * 
+ */
+    __pyx_t_11 = __pyx_v_i;
+    __pyx_t_12 = __pyx_v_i;
+    __pyx_t_13 = __pyx_v_i;
+    __pyx_t_14 = __pyx_v_i;
+    __pyx_t_15 = __pyx_v_i;
+    __pyx_v_ret = iauTtut1((*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_in1.buf, __pyx_t_11, __pyx_bstride_0_in1)), (*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_in2.buf, __pyx_t_12, __pyx_bstride_0_in2)), (*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_dt.buf, __pyx_t_13, __pyx_bstride_0_dt)), (&(*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_out1.buf, __pyx_t_14, __pyx_bstride_0_out1))), (&(*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_out2.buf, __pyx_t_15, __pyx_bstride_0_out2))));
+
+    /* "astropy/time/sofa_time.pyx":833
+ *     for i in range(n):
+ *         ret = iauTtut1(in1[i], in2[i], dt[i], &out1[i], &out2[i])
+ *         check_return(ret, 'iauTtut1')             # <<<<<<<<<<<<<<
+ * 
+ *     return out1, out2
+ */
+    __pyx_t_5 = __Pyx_GetName(__pyx_m, __pyx_n_s__check_return); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 833; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_5);
+    __pyx_t_6 = PyInt_FromLong(__pyx_v_ret); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 833; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_6);
+    __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 833; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(((PyObject *)__pyx_t_4));
+    PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_6);
+    __Pyx_GIVEREF(__pyx_t_6);
+    __Pyx_INCREF(((PyObject *)__pyx_n_s__iauTtut1));
+    PyTuple_SET_ITEM(__pyx_t_4, 1, ((PyObject *)__pyx_n_s__iauTtut1));
+    __Pyx_GIVEREF(((PyObject *)__pyx_n_s__iauTtut1));
+    __pyx_t_6 = 0;
+    __pyx_t_6 = PyObject_Call(__pyx_t_5, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 833; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_6);
+    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+    __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
+    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+  }
+
+  /* "astropy/time/sofa_time.pyx":835
+ *         check_return(ret, 'iauTtut1')
+ * 
+ *     return out1, out2             # <<<<<<<<<<<<<<
+ * 
+ * 
+ */
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_t_6 = PyTuple_New(2); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 835; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_6));
+  __Pyx_INCREF(((PyObject *)__pyx_v_out1));
+  PyTuple_SET_ITEM(__pyx_t_6, 0, ((PyObject *)__pyx_v_out1));
+  __Pyx_GIVEREF(((PyObject *)__pyx_v_out1));
+  __Pyx_INCREF(((PyObject *)__pyx_v_out2));
+  PyTuple_SET_ITEM(__pyx_t_6, 1, ((PyObject *)__pyx_v_out2));
+  __Pyx_GIVEREF(((PyObject *)__pyx_v_out2));
+  __pyx_r = ((PyObject *)__pyx_t_6);
+  __pyx_t_6 = 0;
+  goto __pyx_L0;
+
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_XDECREF(__pyx_t_5);
+  __Pyx_XDECREF(__pyx_t_6);
+  { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;
+    __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out1);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out2);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in1);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in2);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_dt);
+  __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
+  __Pyx_AddTraceback("astropy.time.sofa_time.tt_ut1", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  goto __pyx_L2;
+  __pyx_L0:;
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out1);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out2);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in1);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in2);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_dt);
+  __pyx_L2:;
+  __Pyx_XDECREF((PyObject *)__pyx_v_out1);
+  __Pyx_XDECREF((PyObject *)__pyx_v_out2);
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "astropy/time/sofa_time.pyx":840
+ * @cython.wraparound(False)
+ * @cython.boundscheck(False)
+ * def ut1_tt(             # <<<<<<<<<<<<<<
+ *     np.ndarray[double, ndim=1] in1,
+ *     np.ndarray[double, ndim=1] in2,
+ */
+
+static PyObject *__pyx_pf_7astropy_4time_9sofa_time_16ut1_tt(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_7astropy_4time_9sofa_time_16ut1_tt[] = "\n    int iauUt1tt(double ut11, double ut12, double dt, double *tt1, double *tt2)\n\n    **  Given:\n    **     ut11,ut12  double    UT1 as a 2-part Julian Date\n    **     dt         double    TT-UT1 in seconds\n    **\n    **  Returned:\n    **     tt1,tt2    double    TT as a 2-part Julian Date\n    **\n    **  Returned (function value):\n    **                int       status:  0 = OK\n    **\n    **  Notes:\n    **\n    **  1) ut11+ut12 is Julian Date, apportioned in any convenient way\n    **     between the two arguments, for example where ut11 is the Julian\n    **     Day Number and ut12 is the fraction of a day.  The returned\n    **     tt1,tt2 follow suit.\n    **\n    **  2) The argument dt is classical Delta T.\n    ";
+static PyMethodDef __pyx_mdef_7astropy_4time_9sofa_time_16ut1_tt = {__Pyx_NAMESTR("ut1_tt"), (PyCFunction)__pyx_pf_7astropy_4time_9sofa_time_16ut1_tt, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(__pyx_doc_7astropy_4time_9sofa_time_16ut1_tt)};
+static PyObject *__pyx_pf_7astropy_4time_9sofa_time_16ut1_tt(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyArrayObject *__pyx_v_in1 = 0;
+  PyArrayObject *__pyx_v_in2 = 0;
+  PyArrayObject *__pyx_v_dt = 0;
+  unsigned int __pyx_v_n;
+  unsigned int __pyx_v_i;
+  PyArrayObject *__pyx_v_out1 = 0;
+  PyArrayObject *__pyx_v_out2 = 0;
+  int __pyx_v_ret;
+  Py_buffer __pyx_bstruct_out1;
+  Py_ssize_t __pyx_bstride_0_out1 = 0;
+  Py_ssize_t __pyx_bshape_0_out1 = 0;
+  Py_buffer __pyx_bstruct_out2;
+  Py_ssize_t __pyx_bstride_0_out2 = 0;
+  Py_ssize_t __pyx_bshape_0_out2 = 0;
+  Py_buffer __pyx_bstruct_in1;
+  Py_ssize_t __pyx_bstride_0_in1 = 0;
+  Py_ssize_t __pyx_bshape_0_in1 = 0;
+  Py_buffer __pyx_bstruct_in2;
+  Py_ssize_t __pyx_bstride_0_in2 = 0;
+  Py_ssize_t __pyx_bshape_0_in2 = 0;
+  Py_buffer __pyx_bstruct_dt;
+  Py_ssize_t __pyx_bstride_0_dt = 0;
+  Py_ssize_t __pyx_bshape_0_dt = 0;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  int __pyx_t_1;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
+  PyObject *__pyx_t_5 = NULL;
+  PyObject *__pyx_t_6 = NULL;
+  PyArrayObject *__pyx_t_7 = NULL;
+  PyArrayObject *__pyx_t_8 = NULL;
+  unsigned int __pyx_t_9;
+  unsigned int __pyx_t_10;
+  unsigned int __pyx_t_11;
+  unsigned int __pyx_t_12;
+  unsigned int __pyx_t_13;
+  unsigned int __pyx_t_14;
+  unsigned int __pyx_t_15;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__in1,&__pyx_n_s__in2,&__pyx_n_s__dt,0};
+  __Pyx_RefNannySetupContext("ut1_tt");
+  __pyx_self = __pyx_self;
+  {
+    PyObject* values[3] = {0,0,0};
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  0:
+        values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__in1);
+        if (likely(values[0])) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+        case  1:
+        values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__in2);
+        if (likely(values[1])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("ut1_tt", 1, 3, 3, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 840; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+        case  2:
+        values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__dt);
+        if (likely(values[2])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("ut1_tt", 1, 3, 3, 2); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 840; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "ut1_tt") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 840; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+    } else if (PyTuple_GET_SIZE(__pyx_args) != 3) {
+      goto __pyx_L5_argtuple_error;
+    } else {
+      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+      values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+    }
+    __pyx_v_in1 = ((PyArrayObject *)values[0]);
+    __pyx_v_in2 = ((PyArrayObject *)values[1]);
+    __pyx_v_dt = ((PyArrayObject *)values[2]);
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("ut1_tt", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 840; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("astropy.time.sofa_time.ut1_tt", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_bstruct_out1.buf = NULL;
+  __pyx_bstruct_out2.buf = NULL;
+  __pyx_bstruct_in1.buf = NULL;
+  __pyx_bstruct_in2.buf = NULL;
+  __pyx_bstruct_dt.buf = NULL;
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_in1), __pyx_ptype_5numpy_ndarray, 1, "in1", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 841; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_in2), __pyx_ptype_5numpy_ndarray, 1, "in2", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 842; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_dt), __pyx_ptype_5numpy_ndarray, 1, "dt", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 843; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_in1, (PyObject*)__pyx_v_in1, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 840; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_in1 = __pyx_bstruct_in1.strides[0];
+  __pyx_bshape_0_in1 = __pyx_bstruct_in1.shape[0];
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_in2, (PyObject*)__pyx_v_in2, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 840; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_in2 = __pyx_bstruct_in2.strides[0];
+  __pyx_bshape_0_in2 = __pyx_bstruct_in2.shape[0];
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_dt, (PyObject*)__pyx_v_dt, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 840; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_dt = __pyx_bstruct_dt.strides[0];
+  __pyx_bshape_0_dt = __pyx_bstruct_dt.shape[0];
+
+  /* "astropy/time/sofa_time.pyx":866
+ *     **  2) The argument dt is classical Delta T.
+ *     """
+ *     assert in1.shape[0] == in2.shape[0] == dt.shape[0]             # <<<<<<<<<<<<<<
+ *     cdef unsigned n = in1.shape[0]
+ *     cdef unsigned int i
+ */
+  #ifndef CYTHON_WITHOUT_ASSERTIONS
+  __pyx_t_1 = ((__pyx_v_in1->dimensions[0]) == (__pyx_v_in2->dimensions[0]));
+  if (__pyx_t_1) {
+    __pyx_t_1 = ((__pyx_v_in2->dimensions[0]) == (__pyx_v_dt->dimensions[0]));
+  }
+  if (unlikely(!__pyx_t_1)) {
+    PyErr_SetNone(PyExc_AssertionError);
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 866; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  #endif
+
+  /* "astropy/time/sofa_time.pyx":867
+ *     """
+ *     assert in1.shape[0] == in2.shape[0] == dt.shape[0]
+ *     cdef unsigned n = in1.shape[0]             # <<<<<<<<<<<<<<
+ *     cdef unsigned int i
+ *     cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)
+ */
+  __pyx_v_n = (__pyx_v_in1->dimensions[0]);
+
+  /* "astropy/time/sofa_time.pyx":869
+ *     cdef unsigned n = in1.shape[0]
+ *     cdef unsigned int i
+ *     cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)             # <<<<<<<<<<<<<<
+ *     cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)
+ * 
+ */
+  __pyx_t_2 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 869; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_3 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s__empty); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 869; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __pyx_t_2 = PyLong_FromUnsignedLong(__pyx_v_n); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 869; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 869; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_4));
+  PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_2);
+  __Pyx_GIVEREF(__pyx_t_2);
+  __pyx_t_2 = 0;
+  __pyx_t_2 = PyDict_New(); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 869; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_2));
+  __pyx_t_5 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 869; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __pyx_t_6 = PyObject_GetAttr(__pyx_t_5, __pyx_n_s__double); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 869; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_6);
+  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  if (PyDict_SetItem(__pyx_t_2, ((PyObject *)__pyx_n_s__dtype), __pyx_t_6) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 869; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+  __pyx_t_6 = PyEval_CallObjectWithKeywords(__pyx_t_3, ((PyObject *)__pyx_t_4), ((PyObject *)__pyx_t_2)); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 869; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_6);
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
+  if (!(likely(((__pyx_t_6) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_6, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 869; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_7 = ((PyArrayObject *)__pyx_t_6);
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_out1, (PyObject*)__pyx_t_7, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {
+      __pyx_v_out1 = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_out1.buf = NULL;
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 869; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    } else {__pyx_bstride_0_out1 = __pyx_bstruct_out1.strides[0];
+      __pyx_bshape_0_out1 = __pyx_bstruct_out1.shape[0];
+    }
+  }
+  __pyx_t_7 = 0;
+  __pyx_v_out1 = ((PyArrayObject *)__pyx_t_6);
+  __pyx_t_6 = 0;
+
+  /* "astropy/time/sofa_time.pyx":870
+ *     cdef unsigned int i
+ *     cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)
+ *     cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)             # <<<<<<<<<<<<<<
+ * 
+ *     for i in range(n):
+ */
+  __pyx_t_6 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 870; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_6);
+  __pyx_t_2 = PyObject_GetAttr(__pyx_t_6, __pyx_n_s__empty); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 870; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+  __pyx_t_6 = PyLong_FromUnsignedLong(__pyx_v_n); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 870; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_6);
+  __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 870; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_4));
+  PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_6);
+  __Pyx_GIVEREF(__pyx_t_6);
+  __pyx_t_6 = 0;
+  __pyx_t_6 = PyDict_New(); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 870; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_6));
+  __pyx_t_3 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 870; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __pyx_t_5 = PyObject_GetAttr(__pyx_t_3, __pyx_n_s__double); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 870; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  if (PyDict_SetItem(__pyx_t_6, ((PyObject *)__pyx_n_s__dtype), __pyx_t_5) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 870; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  __pyx_t_5 = PyEval_CallObjectWithKeywords(__pyx_t_2, ((PyObject *)__pyx_t_4), ((PyObject *)__pyx_t_6)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 870; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_6)); __pyx_t_6 = 0;
+  if (!(likely(((__pyx_t_5) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_5, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 870; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_8 = ((PyArrayObject *)__pyx_t_5);
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_out2, (PyObject*)__pyx_t_8, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {
+      __pyx_v_out2 = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_out2.buf = NULL;
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 870; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    } else {__pyx_bstride_0_out2 = __pyx_bstruct_out2.strides[0];
+      __pyx_bshape_0_out2 = __pyx_bstruct_out2.shape[0];
+    }
+  }
+  __pyx_t_8 = 0;
+  __pyx_v_out2 = ((PyArrayObject *)__pyx_t_5);
+  __pyx_t_5 = 0;
+
+  /* "astropy/time/sofa_time.pyx":872
+ *     cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)
+ * 
+ *     for i in range(n):             # <<<<<<<<<<<<<<
+ *         ret = iauUt1tt(in1[i], in2[i], dt[i], &out1[i], &out2[i])
+ *         check_return(ret, 'iauUt1tt')
+ */
+  __pyx_t_9 = __pyx_v_n;
+  for (__pyx_t_10 = 0; __pyx_t_10 < __pyx_t_9; __pyx_t_10+=1) {
+    __pyx_v_i = __pyx_t_10;
+
+    /* "astropy/time/sofa_time.pyx":873
+ * 
+ *     for i in range(n):
+ *         ret = iauUt1tt(in1[i], in2[i], dt[i], &out1[i], &out2[i])             # <<<<<<<<<<<<<<
+ *         check_return(ret, 'iauUt1tt')
+ * 
+ */
+    __pyx_t_11 = __pyx_v_i;
+    __pyx_t_12 = __pyx_v_i;
+    __pyx_t_13 = __pyx_v_i;
+    __pyx_t_14 = __pyx_v_i;
+    __pyx_t_15 = __pyx_v_i;
+    __pyx_v_ret = iauUt1tt((*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_in1.buf, __pyx_t_11, __pyx_bstride_0_in1)), (*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_in2.buf, __pyx_t_12, __pyx_bstride_0_in2)), (*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_dt.buf, __pyx_t_13, __pyx_bstride_0_dt)), (&(*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_out1.buf, __pyx_t_14, __pyx_bstride_0_out1))), (&(*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_out2.buf, __pyx_t_15, __pyx_bstride_0_out2))));
+
+    /* "astropy/time/sofa_time.pyx":874
+ *     for i in range(n):
+ *         ret = iauUt1tt(in1[i], in2[i], dt[i], &out1[i], &out2[i])
+ *         check_return(ret, 'iauUt1tt')             # <<<<<<<<<<<<<<
+ * 
+ *     return out1, out2
+ */
+    __pyx_t_5 = __Pyx_GetName(__pyx_m, __pyx_n_s__check_return); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 874; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_5);
+    __pyx_t_6 = PyInt_FromLong(__pyx_v_ret); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 874; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_6);
+    __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 874; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(((PyObject *)__pyx_t_4));
+    PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_6);
+    __Pyx_GIVEREF(__pyx_t_6);
+    __Pyx_INCREF(((PyObject *)__pyx_n_s__iauUt1tt));
+    PyTuple_SET_ITEM(__pyx_t_4, 1, ((PyObject *)__pyx_n_s__iauUt1tt));
+    __Pyx_GIVEREF(((PyObject *)__pyx_n_s__iauUt1tt));
+    __pyx_t_6 = 0;
+    __pyx_t_6 = PyObject_Call(__pyx_t_5, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 874; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_6);
+    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+    __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
+    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+  }
+
+  /* "astropy/time/sofa_time.pyx":876
+ *         check_return(ret, 'iauUt1tt')
+ * 
+ *     return out1, out2             # <<<<<<<<<<<<<<
+ * 
+ * 
+ */
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_t_6 = PyTuple_New(2); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 876; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_6));
+  __Pyx_INCREF(((PyObject *)__pyx_v_out1));
+  PyTuple_SET_ITEM(__pyx_t_6, 0, ((PyObject *)__pyx_v_out1));
+  __Pyx_GIVEREF(((PyObject *)__pyx_v_out1));
+  __Pyx_INCREF(((PyObject *)__pyx_v_out2));
+  PyTuple_SET_ITEM(__pyx_t_6, 1, ((PyObject *)__pyx_v_out2));
+  __Pyx_GIVEREF(((PyObject *)__pyx_v_out2));
+  __pyx_r = ((PyObject *)__pyx_t_6);
+  __pyx_t_6 = 0;
+  goto __pyx_L0;
+
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_XDECREF(__pyx_t_5);
+  __Pyx_XDECREF(__pyx_t_6);
+  { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;
+    __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out1);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out2);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in1);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in2);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_dt);
+  __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
+  __Pyx_AddTraceback("astropy.time.sofa_time.ut1_tt", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  goto __pyx_L2;
+  __pyx_L0:;
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out1);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out2);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in1);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in2);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_dt);
+  __pyx_L2:;
+  __Pyx_XDECREF((PyObject *)__pyx_v_out1);
+  __Pyx_XDECREF((PyObject *)__pyx_v_out2);
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "astropy/time/sofa_time.pyx":881
+ * @cython.wraparound(False)
+ * @cython.boundscheck(False)
+ * def tdb_tt(             # <<<<<<<<<<<<<<
+ *     np.ndarray[double, ndim=1] in1,
+ *     np.ndarray[double, ndim=1] in2,
+ */
+
+static PyObject *__pyx_pf_7astropy_4time_9sofa_time_17tdb_tt(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_7astropy_4time_9sofa_time_17tdb_tt[] = "\n    int iauTdbtt(double tdb1, double tdb2, double dtr, double *tt1, double *tt2)\n\n    **  Given:\n    **     tdb1,tdb2  double    TDB as a 2-part Julian Date\n    **     dtr        double    TDB-TT in seconds\n    **\n    **  Returned:\n    **     tt1,tt2    double    TT as a 2-part Julian Date\n    **\n    **  Returned (function value):\n    **                int       status:  0 = OK\n    **\n    **  Notes:\n    **\n    **  1) tdb1+tdb2 is Julian Date, apportioned in any convenient way\n    **     between the two arguments, for example where tdb1 is the Julian\n    **     Day Number and tdb2 is the fraction of a day.  The returned\n    **     tt1,tt2 follow suit.\n    **\n    **  2) The argument dtr represents the quasi-periodic component of the\n    **     GR transformation between TT and TCB.  It is dependent upon the\n    **     adopted solar-system ephemeris, and can be obtained by numerical\n    **     integration, by interrogating a precomputed time ephemeris or by\n    **     evaluating a model such as that implemented in the SOFA function\n    **     iauDtdb.   The quantity is dominated by an annual term of 1.7 ms\n    **     amplitude.\n    **\n    **  3) TDB is essentially the same as Teph, the time argument for the\n    **     JPL solar system ephemerides.\n    ";
+static PyMethodDef __pyx_mdef_7astropy_4time_9sofa_time_17tdb_tt = {__Pyx_NAMESTR("tdb_tt"), (PyCFunction)__pyx_pf_7astropy_4time_9sofa_time_17tdb_tt, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(__pyx_doc_7astropy_4time_9sofa_time_17tdb_tt)};
+static PyObject *__pyx_pf_7astropy_4time_9sofa_time_17tdb_tt(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyArrayObject *__pyx_v_in1 = 0;
+  PyArrayObject *__pyx_v_in2 = 0;
+  PyArrayObject *__pyx_v_dt = 0;
+  unsigned int __pyx_v_n;
+  unsigned int __pyx_v_i;
+  PyArrayObject *__pyx_v_out1 = 0;
+  PyArrayObject *__pyx_v_out2 = 0;
+  int __pyx_v_ret;
+  Py_buffer __pyx_bstruct_out1;
+  Py_ssize_t __pyx_bstride_0_out1 = 0;
+  Py_ssize_t __pyx_bshape_0_out1 = 0;
+  Py_buffer __pyx_bstruct_out2;
+  Py_ssize_t __pyx_bstride_0_out2 = 0;
+  Py_ssize_t __pyx_bshape_0_out2 = 0;
+  Py_buffer __pyx_bstruct_in1;
+  Py_ssize_t __pyx_bstride_0_in1 = 0;
+  Py_ssize_t __pyx_bshape_0_in1 = 0;
+  Py_buffer __pyx_bstruct_in2;
+  Py_ssize_t __pyx_bstride_0_in2 = 0;
+  Py_ssize_t __pyx_bshape_0_in2 = 0;
+  Py_buffer __pyx_bstruct_dt;
+  Py_ssize_t __pyx_bstride_0_dt = 0;
+  Py_ssize_t __pyx_bshape_0_dt = 0;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  int __pyx_t_1;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
+  PyObject *__pyx_t_5 = NULL;
+  PyObject *__pyx_t_6 = NULL;
+  PyArrayObject *__pyx_t_7 = NULL;
+  PyArrayObject *__pyx_t_8 = NULL;
+  unsigned int __pyx_t_9;
+  unsigned int __pyx_t_10;
+  unsigned int __pyx_t_11;
+  unsigned int __pyx_t_12;
+  unsigned int __pyx_t_13;
+  unsigned int __pyx_t_14;
+  unsigned int __pyx_t_15;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__in1,&__pyx_n_s__in2,&__pyx_n_s__dt,0};
+  __Pyx_RefNannySetupContext("tdb_tt");
+  __pyx_self = __pyx_self;
+  {
+    PyObject* values[3] = {0,0,0};
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  0:
+        values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__in1);
+        if (likely(values[0])) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+        case  1:
+        values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__in2);
+        if (likely(values[1])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("tdb_tt", 1, 3, 3, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 881; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+        case  2:
+        values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__dt);
+        if (likely(values[2])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("tdb_tt", 1, 3, 3, 2); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 881; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "tdb_tt") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 881; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+    } else if (PyTuple_GET_SIZE(__pyx_args) != 3) {
+      goto __pyx_L5_argtuple_error;
+    } else {
+      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+      values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+    }
+    __pyx_v_in1 = ((PyArrayObject *)values[0]);
+    __pyx_v_in2 = ((PyArrayObject *)values[1]);
+    __pyx_v_dt = ((PyArrayObject *)values[2]);
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("tdb_tt", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 881; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("astropy.time.sofa_time.tdb_tt", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_bstruct_out1.buf = NULL;
+  __pyx_bstruct_out2.buf = NULL;
+  __pyx_bstruct_in1.buf = NULL;
+  __pyx_bstruct_in2.buf = NULL;
+  __pyx_bstruct_dt.buf = NULL;
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_in1), __pyx_ptype_5numpy_ndarray, 1, "in1", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 882; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_in2), __pyx_ptype_5numpy_ndarray, 1, "in2", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 883; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_dt), __pyx_ptype_5numpy_ndarray, 1, "dt", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 884; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_in1, (PyObject*)__pyx_v_in1, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 881; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_in1 = __pyx_bstruct_in1.strides[0];
+  __pyx_bshape_0_in1 = __pyx_bstruct_in1.shape[0];
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_in2, (PyObject*)__pyx_v_in2, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 881; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_in2 = __pyx_bstruct_in2.strides[0];
+  __pyx_bshape_0_in2 = __pyx_bstruct_in2.shape[0];
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_dt, (PyObject*)__pyx_v_dt, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 881; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_dt = __pyx_bstruct_dt.strides[0];
+  __pyx_bshape_0_dt = __pyx_bstruct_dt.shape[0];
+
+  /* "astropy/time/sofa_time.pyx":916
+ *     **     JPL solar system ephemerides.
+ *     """
+ *     assert in1.shape[0] == in2.shape[0] == dt.shape[0]             # <<<<<<<<<<<<<<
+ *     cdef unsigned n = in1.shape[0]
+ *     cdef unsigned int i
+ */
+  #ifndef CYTHON_WITHOUT_ASSERTIONS
+  __pyx_t_1 = ((__pyx_v_in1->dimensions[0]) == (__pyx_v_in2->dimensions[0]));
+  if (__pyx_t_1) {
+    __pyx_t_1 = ((__pyx_v_in2->dimensions[0]) == (__pyx_v_dt->dimensions[0]));
+  }
+  if (unlikely(!__pyx_t_1)) {
+    PyErr_SetNone(PyExc_AssertionError);
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 916; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  #endif
+
+  /* "astropy/time/sofa_time.pyx":917
+ *     """
+ *     assert in1.shape[0] == in2.shape[0] == dt.shape[0]
+ *     cdef unsigned n = in1.shape[0]             # <<<<<<<<<<<<<<
+ *     cdef unsigned int i
+ *     cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)
+ */
+  __pyx_v_n = (__pyx_v_in1->dimensions[0]);
+
+  /* "astropy/time/sofa_time.pyx":919
+ *     cdef unsigned n = in1.shape[0]
+ *     cdef unsigned int i
+ *     cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)             # <<<<<<<<<<<<<<
+ *     cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)
+ * 
+ */
+  __pyx_t_2 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 919; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_3 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s__empty); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 919; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __pyx_t_2 = PyLong_FromUnsignedLong(__pyx_v_n); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 919; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 919; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_4));
+  PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_2);
+  __Pyx_GIVEREF(__pyx_t_2);
+  __pyx_t_2 = 0;
+  __pyx_t_2 = PyDict_New(); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 919; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_2));
+  __pyx_t_5 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 919; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __pyx_t_6 = PyObject_GetAttr(__pyx_t_5, __pyx_n_s__double); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 919; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_6);
+  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  if (PyDict_SetItem(__pyx_t_2, ((PyObject *)__pyx_n_s__dtype), __pyx_t_6) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 919; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+  __pyx_t_6 = PyEval_CallObjectWithKeywords(__pyx_t_3, ((PyObject *)__pyx_t_4), ((PyObject *)__pyx_t_2)); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 919; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_6);
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
+  if (!(likely(((__pyx_t_6) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_6, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 919; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_7 = ((PyArrayObject *)__pyx_t_6);
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_out1, (PyObject*)__pyx_t_7, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {
+      __pyx_v_out1 = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_out1.buf = NULL;
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 919; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    } else {__pyx_bstride_0_out1 = __pyx_bstruct_out1.strides[0];
+      __pyx_bshape_0_out1 = __pyx_bstruct_out1.shape[0];
+    }
+  }
+  __pyx_t_7 = 0;
+  __pyx_v_out1 = ((PyArrayObject *)__pyx_t_6);
+  __pyx_t_6 = 0;
+
+  /* "astropy/time/sofa_time.pyx":920
+ *     cdef unsigned int i
+ *     cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)
+ *     cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)             # <<<<<<<<<<<<<<
+ * 
+ *     for i in range(n):
+ */
+  __pyx_t_6 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 920; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_6);
+  __pyx_t_2 = PyObject_GetAttr(__pyx_t_6, __pyx_n_s__empty); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 920; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+  __pyx_t_6 = PyLong_FromUnsignedLong(__pyx_v_n); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 920; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_6);
+  __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 920; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_4));
+  PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_6);
+  __Pyx_GIVEREF(__pyx_t_6);
+  __pyx_t_6 = 0;
+  __pyx_t_6 = PyDict_New(); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 920; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_6));
+  __pyx_t_3 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 920; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __pyx_t_5 = PyObject_GetAttr(__pyx_t_3, __pyx_n_s__double); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 920; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  if (PyDict_SetItem(__pyx_t_6, ((PyObject *)__pyx_n_s__dtype), __pyx_t_5) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 920; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  __pyx_t_5 = PyEval_CallObjectWithKeywords(__pyx_t_2, ((PyObject *)__pyx_t_4), ((PyObject *)__pyx_t_6)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 920; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_6)); __pyx_t_6 = 0;
+  if (!(likely(((__pyx_t_5) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_5, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 920; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_8 = ((PyArrayObject *)__pyx_t_5);
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_out2, (PyObject*)__pyx_t_8, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {
+      __pyx_v_out2 = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_out2.buf = NULL;
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 920; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    } else {__pyx_bstride_0_out2 = __pyx_bstruct_out2.strides[0];
+      __pyx_bshape_0_out2 = __pyx_bstruct_out2.shape[0];
+    }
+  }
+  __pyx_t_8 = 0;
+  __pyx_v_out2 = ((PyArrayObject *)__pyx_t_5);
+  __pyx_t_5 = 0;
+
+  /* "astropy/time/sofa_time.pyx":922
+ *     cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)
+ * 
+ *     for i in range(n):             # <<<<<<<<<<<<<<
+ *         ret = iauTdbtt(in1[i], in2[i], dt[i], &out1[i], &out2[i])
+ *         check_return(ret, 'iauTdbtt')
+ */
+  __pyx_t_9 = __pyx_v_n;
+  for (__pyx_t_10 = 0; __pyx_t_10 < __pyx_t_9; __pyx_t_10+=1) {
+    __pyx_v_i = __pyx_t_10;
+
+    /* "astropy/time/sofa_time.pyx":923
+ * 
+ *     for i in range(n):
+ *         ret = iauTdbtt(in1[i], in2[i], dt[i], &out1[i], &out2[i])             # <<<<<<<<<<<<<<
+ *         check_return(ret, 'iauTdbtt')
+ * 
+ */
+    __pyx_t_11 = __pyx_v_i;
+    __pyx_t_12 = __pyx_v_i;
+    __pyx_t_13 = __pyx_v_i;
+    __pyx_t_14 = __pyx_v_i;
+    __pyx_t_15 = __pyx_v_i;
+    __pyx_v_ret = iauTdbtt((*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_in1.buf, __pyx_t_11, __pyx_bstride_0_in1)), (*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_in2.buf, __pyx_t_12, __pyx_bstride_0_in2)), (*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_dt.buf, __pyx_t_13, __pyx_bstride_0_dt)), (&(*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_out1.buf, __pyx_t_14, __pyx_bstride_0_out1))), (&(*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_out2.buf, __pyx_t_15, __pyx_bstride_0_out2))));
+
+    /* "astropy/time/sofa_time.pyx":924
+ *     for i in range(n):
+ *         ret = iauTdbtt(in1[i], in2[i], dt[i], &out1[i], &out2[i])
+ *         check_return(ret, 'iauTdbtt')             # <<<<<<<<<<<<<<
+ * 
+ *     return out1, out2
+ */
+    __pyx_t_5 = __Pyx_GetName(__pyx_m, __pyx_n_s__check_return); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 924; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_5);
+    __pyx_t_6 = PyInt_FromLong(__pyx_v_ret); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 924; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_6);
+    __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 924; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(((PyObject *)__pyx_t_4));
+    PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_6);
+    __Pyx_GIVEREF(__pyx_t_6);
+    __Pyx_INCREF(((PyObject *)__pyx_n_s__iauTdbtt));
+    PyTuple_SET_ITEM(__pyx_t_4, 1, ((PyObject *)__pyx_n_s__iauTdbtt));
+    __Pyx_GIVEREF(((PyObject *)__pyx_n_s__iauTdbtt));
+    __pyx_t_6 = 0;
+    __pyx_t_6 = PyObject_Call(__pyx_t_5, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 924; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_6);
+    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+    __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
+    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+  }
+
+  /* "astropy/time/sofa_time.pyx":926
+ *         check_return(ret, 'iauTdbtt')
+ * 
+ *     return out1, out2             # <<<<<<<<<<<<<<
+ * 
+ * 
+ */
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_t_6 = PyTuple_New(2); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 926; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_6));
+  __Pyx_INCREF(((PyObject *)__pyx_v_out1));
+  PyTuple_SET_ITEM(__pyx_t_6, 0, ((PyObject *)__pyx_v_out1));
+  __Pyx_GIVEREF(((PyObject *)__pyx_v_out1));
+  __Pyx_INCREF(((PyObject *)__pyx_v_out2));
+  PyTuple_SET_ITEM(__pyx_t_6, 1, ((PyObject *)__pyx_v_out2));
+  __Pyx_GIVEREF(((PyObject *)__pyx_v_out2));
+  __pyx_r = ((PyObject *)__pyx_t_6);
+  __pyx_t_6 = 0;
+  goto __pyx_L0;
+
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_XDECREF(__pyx_t_5);
+  __Pyx_XDECREF(__pyx_t_6);
+  { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;
+    __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out1);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out2);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in1);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in2);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_dt);
+  __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
+  __Pyx_AddTraceback("astropy.time.sofa_time.tdb_tt", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  goto __pyx_L2;
+  __pyx_L0:;
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out1);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out2);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in1);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in2);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_dt);
+  __pyx_L2:;
+  __Pyx_XDECREF((PyObject *)__pyx_v_out1);
+  __Pyx_XDECREF((PyObject *)__pyx_v_out2);
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "astropy/time/sofa_time.pyx":931
+ * @cython.wraparound(False)
+ * @cython.boundscheck(False)
+ * def tt_tdb(             # <<<<<<<<<<<<<<
+ *     np.ndarray[double, ndim=1] in1,
+ *     np.ndarray[double, ndim=1] in2,
+ */
+
+static PyObject *__pyx_pf_7astropy_4time_9sofa_time_18tt_tdb(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_7astropy_4time_9sofa_time_18tt_tdb[] = "\n    int iauTttdb(double tt1, double tt2, double dtr, double *tdb1, double *tdb2)\n\n    **  Given:\n    **     tt1,tt2    double    TT as a 2-part Julian Date\n    **     dtr        double    TDB-TT in seconds\n    **\n    **  Returned:\n    **     tdb1,tdb2  double    TDB as a 2-part Julian Date\n    **\n    **  Returned (function value):\n    **                int       status:  0 = OK\n    **\n    **  Notes:\n    **\n    **  1) tt1+tt2 is Julian Date, apportioned in any convenient way between\n    **     the two arguments, for example where tt1 is the Julian Day Number\n    **     and tt2 is the fraction of a day.  The returned tdb1,tdb2 follow\n    **     suit.\n    **\n    **  2) The argument dtr represents the quasi-periodic component of the\n    **     GR transformation between TT and TCB.  It is dependent upon the\n    **     adopted solar-system ephemeris, and can be obtained by numerical\n    **     integration, by interrogating a precomputed time ephemeris or by\n    **     evaluating a model such as that implemented in the SOFA function\n    **     iauDtdb.   The quantity is dominated by an annual term of 1.7 ms\n    **     amplitude.\n    **\n    **  3) TDB is essentially the same as Teph, the time argument for the JPL\n    **     solar system ephemerides.\n    ";
+static PyMethodDef __pyx_mdef_7astropy_4time_9sofa_time_18tt_tdb = {__Pyx_NAMESTR("tt_tdb"), (PyCFunction)__pyx_pf_7astropy_4time_9sofa_time_18tt_tdb, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(__pyx_doc_7astropy_4time_9sofa_time_18tt_tdb)};
+static PyObject *__pyx_pf_7astropy_4time_9sofa_time_18tt_tdb(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyArrayObject *__pyx_v_in1 = 0;
+  PyArrayObject *__pyx_v_in2 = 0;
+  PyArrayObject *__pyx_v_dt = 0;
+  unsigned int __pyx_v_n;
+  unsigned int __pyx_v_i;
+  PyArrayObject *__pyx_v_out1 = 0;
+  PyArrayObject *__pyx_v_out2 = 0;
+  int __pyx_v_ret;
+  Py_buffer __pyx_bstruct_out1;
+  Py_ssize_t __pyx_bstride_0_out1 = 0;
+  Py_ssize_t __pyx_bshape_0_out1 = 0;
+  Py_buffer __pyx_bstruct_out2;
+  Py_ssize_t __pyx_bstride_0_out2 = 0;
+  Py_ssize_t __pyx_bshape_0_out2 = 0;
+  Py_buffer __pyx_bstruct_in1;
+  Py_ssize_t __pyx_bstride_0_in1 = 0;
+  Py_ssize_t __pyx_bshape_0_in1 = 0;
+  Py_buffer __pyx_bstruct_in2;
+  Py_ssize_t __pyx_bstride_0_in2 = 0;
+  Py_ssize_t __pyx_bshape_0_in2 = 0;
+  Py_buffer __pyx_bstruct_dt;
+  Py_ssize_t __pyx_bstride_0_dt = 0;
+  Py_ssize_t __pyx_bshape_0_dt = 0;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  int __pyx_t_1;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
+  PyObject *__pyx_t_5 = NULL;
+  PyObject *__pyx_t_6 = NULL;
+  PyArrayObject *__pyx_t_7 = NULL;
+  PyArrayObject *__pyx_t_8 = NULL;
+  unsigned int __pyx_t_9;
+  unsigned int __pyx_t_10;
+  unsigned int __pyx_t_11;
+  unsigned int __pyx_t_12;
+  unsigned int __pyx_t_13;
+  unsigned int __pyx_t_14;
+  unsigned int __pyx_t_15;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__in1,&__pyx_n_s__in2,&__pyx_n_s__dt,0};
+  __Pyx_RefNannySetupContext("tt_tdb");
+  __pyx_self = __pyx_self;
+  {
+    PyObject* values[3] = {0,0,0};
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  0:
+        values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__in1);
+        if (likely(values[0])) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+        case  1:
+        values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__in2);
+        if (likely(values[1])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("tt_tdb", 1, 3, 3, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 931; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+        case  2:
+        values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__dt);
+        if (likely(values[2])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("tt_tdb", 1, 3, 3, 2); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 931; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "tt_tdb") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 931; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+    } else if (PyTuple_GET_SIZE(__pyx_args) != 3) {
+      goto __pyx_L5_argtuple_error;
+    } else {
+      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+      values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+    }
+    __pyx_v_in1 = ((PyArrayObject *)values[0]);
+    __pyx_v_in2 = ((PyArrayObject *)values[1]);
+    __pyx_v_dt = ((PyArrayObject *)values[2]);
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("tt_tdb", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 931; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("astropy.time.sofa_time.tt_tdb", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_bstruct_out1.buf = NULL;
+  __pyx_bstruct_out2.buf = NULL;
+  __pyx_bstruct_in1.buf = NULL;
+  __pyx_bstruct_in2.buf = NULL;
+  __pyx_bstruct_dt.buf = NULL;
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_in1), __pyx_ptype_5numpy_ndarray, 1, "in1", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 932; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_in2), __pyx_ptype_5numpy_ndarray, 1, "in2", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 933; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_dt), __pyx_ptype_5numpy_ndarray, 1, "dt", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 934; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_in1, (PyObject*)__pyx_v_in1, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 931; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_in1 = __pyx_bstruct_in1.strides[0];
+  __pyx_bshape_0_in1 = __pyx_bstruct_in1.shape[0];
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_in2, (PyObject*)__pyx_v_in2, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 931; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_in2 = __pyx_bstruct_in2.strides[0];
+  __pyx_bshape_0_in2 = __pyx_bstruct_in2.shape[0];
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_dt, (PyObject*)__pyx_v_dt, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 931; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_dt = __pyx_bstruct_dt.strides[0];
+  __pyx_bshape_0_dt = __pyx_bstruct_dt.shape[0];
+
+  /* "astropy/time/sofa_time.pyx":966
+ *     **     solar system ephemerides.
+ *     """
+ *     assert in1.shape[0] == in2.shape[0] == dt.shape[0]             # <<<<<<<<<<<<<<
+ *     cdef unsigned n = in1.shape[0]
+ *     cdef unsigned int i
+ */
+  #ifndef CYTHON_WITHOUT_ASSERTIONS
+  __pyx_t_1 = ((__pyx_v_in1->dimensions[0]) == (__pyx_v_in2->dimensions[0]));
+  if (__pyx_t_1) {
+    __pyx_t_1 = ((__pyx_v_in2->dimensions[0]) == (__pyx_v_dt->dimensions[0]));
+  }
+  if (unlikely(!__pyx_t_1)) {
+    PyErr_SetNone(PyExc_AssertionError);
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 966; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  #endif
+
+  /* "astropy/time/sofa_time.pyx":967
+ *     """
+ *     assert in1.shape[0] == in2.shape[0] == dt.shape[0]
+ *     cdef unsigned n = in1.shape[0]             # <<<<<<<<<<<<<<
+ *     cdef unsigned int i
+ *     cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)
+ */
+  __pyx_v_n = (__pyx_v_in1->dimensions[0]);
+
+  /* "astropy/time/sofa_time.pyx":969
+ *     cdef unsigned n = in1.shape[0]
+ *     cdef unsigned int i
+ *     cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)             # <<<<<<<<<<<<<<
+ *     cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)
+ * 
+ */
+  __pyx_t_2 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 969; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_3 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s__empty); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 969; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __pyx_t_2 = PyLong_FromUnsignedLong(__pyx_v_n); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 969; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 969; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_4));
+  PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_2);
+  __Pyx_GIVEREF(__pyx_t_2);
+  __pyx_t_2 = 0;
+  __pyx_t_2 = PyDict_New(); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 969; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_2));
+  __pyx_t_5 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 969; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __pyx_t_6 = PyObject_GetAttr(__pyx_t_5, __pyx_n_s__double); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 969; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_6);
+  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  if (PyDict_SetItem(__pyx_t_2, ((PyObject *)__pyx_n_s__dtype), __pyx_t_6) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 969; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+  __pyx_t_6 = PyEval_CallObjectWithKeywords(__pyx_t_3, ((PyObject *)__pyx_t_4), ((PyObject *)__pyx_t_2)); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 969; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_6);
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
+  if (!(likely(((__pyx_t_6) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_6, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 969; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_7 = ((PyArrayObject *)__pyx_t_6);
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_out1, (PyObject*)__pyx_t_7, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {
+      __pyx_v_out1 = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_out1.buf = NULL;
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 969; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    } else {__pyx_bstride_0_out1 = __pyx_bstruct_out1.strides[0];
+      __pyx_bshape_0_out1 = __pyx_bstruct_out1.shape[0];
+    }
+  }
+  __pyx_t_7 = 0;
+  __pyx_v_out1 = ((PyArrayObject *)__pyx_t_6);
+  __pyx_t_6 = 0;
+
+  /* "astropy/time/sofa_time.pyx":970
+ *     cdef unsigned int i
+ *     cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)
+ *     cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)             # <<<<<<<<<<<<<<
+ * 
+ *     for i in range(n):
+ */
+  __pyx_t_6 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 970; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_6);
+  __pyx_t_2 = PyObject_GetAttr(__pyx_t_6, __pyx_n_s__empty); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 970; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+  __pyx_t_6 = PyLong_FromUnsignedLong(__pyx_v_n); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 970; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_6);
+  __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 970; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_4));
+  PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_6);
+  __Pyx_GIVEREF(__pyx_t_6);
+  __pyx_t_6 = 0;
+  __pyx_t_6 = PyDict_New(); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 970; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_6));
+  __pyx_t_3 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 970; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __pyx_t_5 = PyObject_GetAttr(__pyx_t_3, __pyx_n_s__double); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 970; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  if (PyDict_SetItem(__pyx_t_6, ((PyObject *)__pyx_n_s__dtype), __pyx_t_5) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 970; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  __pyx_t_5 = PyEval_CallObjectWithKeywords(__pyx_t_2, ((PyObject *)__pyx_t_4), ((PyObject *)__pyx_t_6)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 970; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_6)); __pyx_t_6 = 0;
+  if (!(likely(((__pyx_t_5) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_5, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 970; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_8 = ((PyArrayObject *)__pyx_t_5);
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_out2, (PyObject*)__pyx_t_8, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {
+      __pyx_v_out2 = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_out2.buf = NULL;
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 970; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    } else {__pyx_bstride_0_out2 = __pyx_bstruct_out2.strides[0];
+      __pyx_bshape_0_out2 = __pyx_bstruct_out2.shape[0];
+    }
+  }
+  __pyx_t_8 = 0;
+  __pyx_v_out2 = ((PyArrayObject *)__pyx_t_5);
+  __pyx_t_5 = 0;
+
+  /* "astropy/time/sofa_time.pyx":972
+ *     cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)
+ * 
+ *     for i in range(n):             # <<<<<<<<<<<<<<
+ *         ret = iauTttdb(in1[i], in2[i], dt[i], &out1[i], &out2[i])
+ *         check_return(ret, 'iauTttdb')
+ */
+  __pyx_t_9 = __pyx_v_n;
+  for (__pyx_t_10 = 0; __pyx_t_10 < __pyx_t_9; __pyx_t_10+=1) {
+    __pyx_v_i = __pyx_t_10;
+
+    /* "astropy/time/sofa_time.pyx":973
+ * 
+ *     for i in range(n):
+ *         ret = iauTttdb(in1[i], in2[i], dt[i], &out1[i], &out2[i])             # <<<<<<<<<<<<<<
+ *         check_return(ret, 'iauTttdb')
+ * 
+ */
+    __pyx_t_11 = __pyx_v_i;
+    __pyx_t_12 = __pyx_v_i;
+    __pyx_t_13 = __pyx_v_i;
+    __pyx_t_14 = __pyx_v_i;
+    __pyx_t_15 = __pyx_v_i;
+    __pyx_v_ret = iauTttdb((*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_in1.buf, __pyx_t_11, __pyx_bstride_0_in1)), (*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_in2.buf, __pyx_t_12, __pyx_bstride_0_in2)), (*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_dt.buf, __pyx_t_13, __pyx_bstride_0_dt)), (&(*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_out1.buf, __pyx_t_14, __pyx_bstride_0_out1))), (&(*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_out2.buf, __pyx_t_15, __pyx_bstride_0_out2))));
+
+    /* "astropy/time/sofa_time.pyx":974
+ *     for i in range(n):
+ *         ret = iauTttdb(in1[i], in2[i], dt[i], &out1[i], &out2[i])
+ *         check_return(ret, 'iauTttdb')             # <<<<<<<<<<<<<<
+ * 
+ *     return out1, out2
+ */
+    __pyx_t_5 = __Pyx_GetName(__pyx_m, __pyx_n_s__check_return); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 974; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_5);
+    __pyx_t_6 = PyInt_FromLong(__pyx_v_ret); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 974; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_6);
+    __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 974; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(((PyObject *)__pyx_t_4));
+    PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_6);
+    __Pyx_GIVEREF(__pyx_t_6);
+    __Pyx_INCREF(((PyObject *)__pyx_n_s__iauTttdb));
+    PyTuple_SET_ITEM(__pyx_t_4, 1, ((PyObject *)__pyx_n_s__iauTttdb));
+    __Pyx_GIVEREF(((PyObject *)__pyx_n_s__iauTttdb));
+    __pyx_t_6 = 0;
+    __pyx_t_6 = PyObject_Call(__pyx_t_5, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 974; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_6);
+    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+    __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
+    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+  }
+
+  /* "astropy/time/sofa_time.pyx":976
+ *         check_return(ret, 'iauTttdb')
+ * 
+ *     return out1, out2             # <<<<<<<<<<<<<<
+ * 
+ * 
+ */
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_t_6 = PyTuple_New(2); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 976; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_6));
+  __Pyx_INCREF(((PyObject *)__pyx_v_out1));
+  PyTuple_SET_ITEM(__pyx_t_6, 0, ((PyObject *)__pyx_v_out1));
+  __Pyx_GIVEREF(((PyObject *)__pyx_v_out1));
+  __Pyx_INCREF(((PyObject *)__pyx_v_out2));
+  PyTuple_SET_ITEM(__pyx_t_6, 1, ((PyObject *)__pyx_v_out2));
+  __Pyx_GIVEREF(((PyObject *)__pyx_v_out2));
+  __pyx_r = ((PyObject *)__pyx_t_6);
+  __pyx_t_6 = 0;
+  goto __pyx_L0;
+
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_XDECREF(__pyx_t_5);
+  __Pyx_XDECREF(__pyx_t_6);
+  { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;
+    __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out1);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out2);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in1);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in2);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_dt);
+  __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
+  __Pyx_AddTraceback("astropy.time.sofa_time.tt_tdb", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  goto __pyx_L2;
+  __pyx_L0:;
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out1);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out2);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in1);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in2);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_dt);
+  __pyx_L2:;
+  __Pyx_XDECREF((PyObject *)__pyx_v_out1);
+  __Pyx_XDECREF((PyObject *)__pyx_v_out2);
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "astropy/time/sofa_time.pyx":981
+ * @cython.wraparound(False)
+ * @cython.boundscheck(False)
+ * def ut1_utc(             # <<<<<<<<<<<<<<
+ *     np.ndarray[double, ndim=1] in1,
+ *     np.ndarray[double, ndim=1] in2,
+ */
+
+static PyObject *__pyx_pf_7astropy_4time_9sofa_time_19ut1_utc(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_7astropy_4time_9sofa_time_19ut1_utc[] = "\n    int iauUt1utc(double ut11, double ut12, double dut1, double *utc1, double *utc2)\n\n    **  Given:\n    **     ut11,ut12  double   UT1 as a 2-part Julian Date (Note 1)\n    **     dut1       double   Delta UT1: UT1-UTC in seconds (Note 2)\n    **\n    **  Returned:\n    **     utc1,utc2  double   UTC as a 2-part quasi Julian Date (Notes 3,4)\n    **\n    **  Returned (function value):\n    **                int      status: +1 = dubious year (Note 5)\n    **                                  0 = OK\n    **                                 -1 = unacceptable date\n    **\n    **  Notes:\n    **\n    **  1) ut11+ut12 is Julian Date, apportioned in any convenient way\n    **     between the two arguments, for example where ut11 is the Julian\n    **     Day Number and ut12 is the fraction of a day.  The returned utc1\n    **     and utc2 form an analogous pair, except that a special convention\n    **     is used, to deal with the problem of leap seconds - see Note 3.\n    **\n    **  2) Delta UT1 can be obtained from tabulations provided by the\n    **     International Earth Rotation and Reference Systems Service.  The\n    **     value changes abruptly by 1s at a leap second;  however, close to\n    **     a leap second the algorithm used here is tolerant of the \"wrong\"\n    **     choice of value being made.\n    **\n    **  3) JD cannot unambiguously represent UTC during a leap second unless\n    **     special measures are taken.  The convention in the present\n    **     function is that the returned quasi JD day UTC1+UTC2 represents\n    **     UTC days whether the length is 86399, 86400 or 86401 SI seconds.\n    **\n    **  4) The function iauD2dtf can be used to transform the UTC quasi-JD\n    **     into calendar date and clock time, including UTC leap second\n    **     handling.\n    **\n    **  5) The warning status \"dubious year\" flags UTCs that predate the\n    **     introduction of the time scale and that are too far in the future\n    **     t""o be trusted.  See iauDat for further details.\n    ";
+static PyMethodDef __pyx_mdef_7astropy_4time_9sofa_time_19ut1_utc = {__Pyx_NAMESTR("ut1_utc"), (PyCFunction)__pyx_pf_7astropy_4time_9sofa_time_19ut1_utc, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(__pyx_doc_7astropy_4time_9sofa_time_19ut1_utc)};
+static PyObject *__pyx_pf_7astropy_4time_9sofa_time_19ut1_utc(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyArrayObject *__pyx_v_in1 = 0;
+  PyArrayObject *__pyx_v_in2 = 0;
+  PyArrayObject *__pyx_v_dt = 0;
+  unsigned int __pyx_v_n;
+  unsigned int __pyx_v_i;
+  PyArrayObject *__pyx_v_out1 = 0;
+  PyArrayObject *__pyx_v_out2 = 0;
+  PyObject *__pyx_v_warns = NULL;
+  PyObject *__pyx_v_errs = NULL;
+  int __pyx_v_ret;
+  Py_buffer __pyx_bstruct_out1;
+  Py_ssize_t __pyx_bstride_0_out1 = 0;
+  Py_ssize_t __pyx_bshape_0_out1 = 0;
+  Py_buffer __pyx_bstruct_out2;
+  Py_ssize_t __pyx_bstride_0_out2 = 0;
+  Py_ssize_t __pyx_bshape_0_out2 = 0;
+  Py_buffer __pyx_bstruct_in1;
+  Py_ssize_t __pyx_bstride_0_in1 = 0;
+  Py_ssize_t __pyx_bshape_0_in1 = 0;
+  Py_buffer __pyx_bstruct_in2;
+  Py_ssize_t __pyx_bstride_0_in2 = 0;
+  Py_ssize_t __pyx_bshape_0_in2 = 0;
+  Py_buffer __pyx_bstruct_dt;
+  Py_ssize_t __pyx_bstride_0_dt = 0;
+  Py_ssize_t __pyx_bshape_0_dt = 0;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  int __pyx_t_1;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
+  PyObject *__pyx_t_5 = NULL;
+  PyObject *__pyx_t_6 = NULL;
+  PyArrayObject *__pyx_t_7 = NULL;
+  PyArrayObject *__pyx_t_8 = NULL;
+  unsigned int __pyx_t_9;
+  unsigned int __pyx_t_10;
+  unsigned int __pyx_t_11;
+  unsigned int __pyx_t_12;
+  unsigned int __pyx_t_13;
+  unsigned int __pyx_t_14;
+  unsigned int __pyx_t_15;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__in1,&__pyx_n_s__in2,&__pyx_n_s__dt,0};
+  __Pyx_RefNannySetupContext("ut1_utc");
+  __pyx_self = __pyx_self;
+  {
+    PyObject* values[3] = {0,0,0};
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  0:
+        values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__in1);
+        if (likely(values[0])) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+        case  1:
+        values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__in2);
+        if (likely(values[1])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("ut1_utc", 1, 3, 3, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 981; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+        case  2:
+        values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__dt);
+        if (likely(values[2])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("ut1_utc", 1, 3, 3, 2); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 981; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "ut1_utc") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 981; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+    } else if (PyTuple_GET_SIZE(__pyx_args) != 3) {
+      goto __pyx_L5_argtuple_error;
+    } else {
+      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+      values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+    }
+    __pyx_v_in1 = ((PyArrayObject *)values[0]);
+    __pyx_v_in2 = ((PyArrayObject *)values[1]);
+    __pyx_v_dt = ((PyArrayObject *)values[2]);
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("ut1_utc", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 981; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("astropy.time.sofa_time.ut1_utc", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_bstruct_out1.buf = NULL;
+  __pyx_bstruct_out2.buf = NULL;
+  __pyx_bstruct_in1.buf = NULL;
+  __pyx_bstruct_in2.buf = NULL;
+  __pyx_bstruct_dt.buf = NULL;
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_in1), __pyx_ptype_5numpy_ndarray, 1, "in1", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 982; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_in2), __pyx_ptype_5numpy_ndarray, 1, "in2", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 983; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_dt), __pyx_ptype_5numpy_ndarray, 1, "dt", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 984; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_in1, (PyObject*)__pyx_v_in1, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 981; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_in1 = __pyx_bstruct_in1.strides[0];
+  __pyx_bshape_0_in1 = __pyx_bstruct_in1.shape[0];
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_in2, (PyObject*)__pyx_v_in2, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 981; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_in2 = __pyx_bstruct_in2.strides[0];
+  __pyx_bshape_0_in2 = __pyx_bstruct_in2.shape[0];
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_dt, (PyObject*)__pyx_v_dt, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 981; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_dt = __pyx_bstruct_dt.strides[0];
+  __pyx_bshape_0_dt = __pyx_bstruct_dt.shape[0];
+
+  /* "astropy/time/sofa_time.pyx":1027
+ *     **     to be trusted.  See iauDat for further details.
+ *     """
+ *     assert in1.shape[0] == in2.shape[0] == dt.shape[0]             # <<<<<<<<<<<<<<
+ *     cdef unsigned n = in1.shape[0]
+ *     cdef unsigned int i
+ */
+  #ifndef CYTHON_WITHOUT_ASSERTIONS
+  __pyx_t_1 = ((__pyx_v_in1->dimensions[0]) == (__pyx_v_in2->dimensions[0]));
+  if (__pyx_t_1) {
+    __pyx_t_1 = ((__pyx_v_in2->dimensions[0]) == (__pyx_v_dt->dimensions[0]));
+  }
+  if (unlikely(!__pyx_t_1)) {
+    PyErr_SetNone(PyExc_AssertionError);
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1027; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  #endif
+
+  /* "astropy/time/sofa_time.pyx":1028
+ *     """
+ *     assert in1.shape[0] == in2.shape[0] == dt.shape[0]
+ *     cdef unsigned n = in1.shape[0]             # <<<<<<<<<<<<<<
+ *     cdef unsigned int i
+ *     cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)
+ */
+  __pyx_v_n = (__pyx_v_in1->dimensions[0]);
+
+  /* "astropy/time/sofa_time.pyx":1030
+ *     cdef unsigned n = in1.shape[0]
+ *     cdef unsigned int i
+ *     cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)             # <<<<<<<<<<<<<<
+ *     cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)
+ * 
+ */
+  __pyx_t_2 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1030; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_3 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s__empty); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1030; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __pyx_t_2 = PyLong_FromUnsignedLong(__pyx_v_n); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1030; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1030; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_4));
+  PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_2);
+  __Pyx_GIVEREF(__pyx_t_2);
+  __pyx_t_2 = 0;
+  __pyx_t_2 = PyDict_New(); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1030; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_2));
+  __pyx_t_5 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1030; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __pyx_t_6 = PyObject_GetAttr(__pyx_t_5, __pyx_n_s__double); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1030; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_6);
+  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  if (PyDict_SetItem(__pyx_t_2, ((PyObject *)__pyx_n_s__dtype), __pyx_t_6) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1030; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+  __pyx_t_6 = PyEval_CallObjectWithKeywords(__pyx_t_3, ((PyObject *)__pyx_t_4), ((PyObject *)__pyx_t_2)); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1030; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_6);
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
+  if (!(likely(((__pyx_t_6) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_6, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1030; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_7 = ((PyArrayObject *)__pyx_t_6);
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_out1, (PyObject*)__pyx_t_7, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {
+      __pyx_v_out1 = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_out1.buf = NULL;
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1030; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    } else {__pyx_bstride_0_out1 = __pyx_bstruct_out1.strides[0];
+      __pyx_bshape_0_out1 = __pyx_bstruct_out1.shape[0];
+    }
+  }
+  __pyx_t_7 = 0;
+  __pyx_v_out1 = ((PyArrayObject *)__pyx_t_6);
+  __pyx_t_6 = 0;
+
+  /* "astropy/time/sofa_time.pyx":1031
+ *     cdef unsigned int i
+ *     cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)
+ *     cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)             # <<<<<<<<<<<<<<
+ * 
+ *     warns = {1: DUBIOUS}
+ */
+  __pyx_t_6 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1031; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_6);
+  __pyx_t_2 = PyObject_GetAttr(__pyx_t_6, __pyx_n_s__empty); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1031; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+  __pyx_t_6 = PyLong_FromUnsignedLong(__pyx_v_n); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1031; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_6);
+  __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1031; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_4));
+  PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_6);
+  __Pyx_GIVEREF(__pyx_t_6);
+  __pyx_t_6 = 0;
+  __pyx_t_6 = PyDict_New(); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1031; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_6));
+  __pyx_t_3 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1031; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __pyx_t_5 = PyObject_GetAttr(__pyx_t_3, __pyx_n_s__double); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1031; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  if (PyDict_SetItem(__pyx_t_6, ((PyObject *)__pyx_n_s__dtype), __pyx_t_5) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1031; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  __pyx_t_5 = PyEval_CallObjectWithKeywords(__pyx_t_2, ((PyObject *)__pyx_t_4), ((PyObject *)__pyx_t_6)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1031; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_6)); __pyx_t_6 = 0;
+  if (!(likely(((__pyx_t_5) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_5, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1031; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_8 = ((PyArrayObject *)__pyx_t_5);
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_out2, (PyObject*)__pyx_t_8, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {
+      __pyx_v_out2 = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_out2.buf = NULL;
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1031; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    } else {__pyx_bstride_0_out2 = __pyx_bstruct_out2.strides[0];
+      __pyx_bshape_0_out2 = __pyx_bstruct_out2.shape[0];
+    }
+  }
+  __pyx_t_8 = 0;
+  __pyx_v_out2 = ((PyArrayObject *)__pyx_t_5);
+  __pyx_t_5 = 0;
+
+  /* "astropy/time/sofa_time.pyx":1033
+ *     cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)
+ * 
+ *     warns = {1: DUBIOUS}             # <<<<<<<<<<<<<<
+ *     errs = {-1: 'unacceptable date'}
+ * 
+ */
+  __pyx_t_5 = PyDict_New(); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1033; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_5));
+  __pyx_t_6 = __Pyx_GetName(__pyx_m, __pyx_n_s__DUBIOUS); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1033; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_6);
+  if (PyDict_SetItem(__pyx_t_5, __pyx_int_1, __pyx_t_6) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1033; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+  __pyx_v_warns = __pyx_t_5;
+  __pyx_t_5 = 0;
+
+  /* "astropy/time/sofa_time.pyx":1034
+ * 
+ *     warns = {1: DUBIOUS}
+ *     errs = {-1: 'unacceptable date'}             # <<<<<<<<<<<<<<
+ * 
+ *     for i in range(n):
+ */
+  __pyx_t_5 = PyDict_New(); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1034; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_5));
+  if (PyDict_SetItem(__pyx_t_5, __pyx_int_neg_1, ((PyObject *)__pyx_kp_s_12)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1034; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_v_errs = __pyx_t_5;
+  __pyx_t_5 = 0;
+
+  /* "astropy/time/sofa_time.pyx":1036
+ *     errs = {-1: 'unacceptable date'}
+ * 
+ *     for i in range(n):             # <<<<<<<<<<<<<<
+ *         ret = iauUt1utc(in1[i], in2[i], dt[i], &out1[i], &out2[i])
+ *         check_return(ret, 'iauUt1utc', warns, errs)
+ */
+  __pyx_t_9 = __pyx_v_n;
+  for (__pyx_t_10 = 0; __pyx_t_10 < __pyx_t_9; __pyx_t_10+=1) {
+    __pyx_v_i = __pyx_t_10;
+
+    /* "astropy/time/sofa_time.pyx":1037
+ * 
+ *     for i in range(n):
+ *         ret = iauUt1utc(in1[i], in2[i], dt[i], &out1[i], &out2[i])             # <<<<<<<<<<<<<<
+ *         check_return(ret, 'iauUt1utc', warns, errs)
+ * 
+ */
+    __pyx_t_11 = __pyx_v_i;
+    __pyx_t_12 = __pyx_v_i;
+    __pyx_t_13 = __pyx_v_i;
+    __pyx_t_14 = __pyx_v_i;
+    __pyx_t_15 = __pyx_v_i;
+    __pyx_v_ret = iauUt1utc((*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_in1.buf, __pyx_t_11, __pyx_bstride_0_in1)), (*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_in2.buf, __pyx_t_12, __pyx_bstride_0_in2)), (*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_dt.buf, __pyx_t_13, __pyx_bstride_0_dt)), (&(*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_out1.buf, __pyx_t_14, __pyx_bstride_0_out1))), (&(*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_out2.buf, __pyx_t_15, __pyx_bstride_0_out2))));
+
+    /* "astropy/time/sofa_time.pyx":1038
+ *     for i in range(n):
+ *         ret = iauUt1utc(in1[i], in2[i], dt[i], &out1[i], &out2[i])
+ *         check_return(ret, 'iauUt1utc', warns, errs)             # <<<<<<<<<<<<<<
+ * 
+ *     return out1, out2
+ */
+    __pyx_t_5 = __Pyx_GetName(__pyx_m, __pyx_n_s__check_return); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1038; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_5);
+    __pyx_t_6 = PyInt_FromLong(__pyx_v_ret); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1038; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_6);
+    __pyx_t_4 = PyTuple_New(4); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1038; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(((PyObject *)__pyx_t_4));
+    PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_6);
+    __Pyx_GIVEREF(__pyx_t_6);
+    __Pyx_INCREF(((PyObject *)__pyx_n_s__iauUt1utc));
+    PyTuple_SET_ITEM(__pyx_t_4, 1, ((PyObject *)__pyx_n_s__iauUt1utc));
+    __Pyx_GIVEREF(((PyObject *)__pyx_n_s__iauUt1utc));
+    __Pyx_INCREF(((PyObject *)__pyx_v_warns));
+    PyTuple_SET_ITEM(__pyx_t_4, 2, ((PyObject *)__pyx_v_warns));
+    __Pyx_GIVEREF(((PyObject *)__pyx_v_warns));
+    __Pyx_INCREF(((PyObject *)__pyx_v_errs));
+    PyTuple_SET_ITEM(__pyx_t_4, 3, ((PyObject *)__pyx_v_errs));
+    __Pyx_GIVEREF(((PyObject *)__pyx_v_errs));
+    __pyx_t_6 = 0;
+    __pyx_t_6 = PyObject_Call(__pyx_t_5, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1038; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_6);
+    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+    __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
+    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+  }
+
+  /* "astropy/time/sofa_time.pyx":1040
+ *         check_return(ret, 'iauUt1utc', warns, errs)
+ * 
+ *     return out1, out2             # <<<<<<<<<<<<<<
+ * 
+ * 
+ */
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_t_6 = PyTuple_New(2); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1040; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_6));
+  __Pyx_INCREF(((PyObject *)__pyx_v_out1));
+  PyTuple_SET_ITEM(__pyx_t_6, 0, ((PyObject *)__pyx_v_out1));
+  __Pyx_GIVEREF(((PyObject *)__pyx_v_out1));
+  __Pyx_INCREF(((PyObject *)__pyx_v_out2));
+  PyTuple_SET_ITEM(__pyx_t_6, 1, ((PyObject *)__pyx_v_out2));
+  __Pyx_GIVEREF(((PyObject *)__pyx_v_out2));
+  __pyx_r = ((PyObject *)__pyx_t_6);
+  __pyx_t_6 = 0;
+  goto __pyx_L0;
+
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_XDECREF(__pyx_t_5);
+  __Pyx_XDECREF(__pyx_t_6);
+  { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;
+    __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out1);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out2);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in1);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in2);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_dt);
+  __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
+  __Pyx_AddTraceback("astropy.time.sofa_time.ut1_utc", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  goto __pyx_L2;
+  __pyx_L0:;
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out1);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out2);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in1);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in2);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_dt);
+  __pyx_L2:;
+  __Pyx_XDECREF((PyObject *)__pyx_v_out1);
+  __Pyx_XDECREF((PyObject *)__pyx_v_out2);
+  __Pyx_XDECREF(__pyx_v_warns);
+  __Pyx_XDECREF(__pyx_v_errs);
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "astropy/time/sofa_time.pyx":1045
+ * @cython.wraparound(False)
+ * @cython.boundscheck(False)
+ * def utc_ut1(             # <<<<<<<<<<<<<<
+ *     np.ndarray[double, ndim=1] in1,
+ *     np.ndarray[double, ndim=1] in2,
+ */
+
+static PyObject *__pyx_pf_7astropy_4time_9sofa_time_20utc_ut1(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_7astropy_4time_9sofa_time_20utc_ut1[] = "\n    int iauUtcut1(double utc1, double utc2, double dut1, double *ut11, double *ut12)\n\n    **  Given:\n    **     utc1,utc2  double   UTC as a 2-part quasi Julian Date (Notes 1-4)\n    **     dut1       double   Delta UT1 = UT1-UTC in seconds (Note 5)\n    **\n    **  Returned:\n    **     ut11,ut12  double   UT1 as a 2-part Julian Date (Note 6)\n    **\n    **  Returned (function value):\n    **                int      status: +1 = dubious year (Note 7)\n    **                                  0 = OK\n    **                                 -1 = unacceptable date\n    **\n    **  Notes:\n    **\n    **  1) utc1+utc2 is quasi Julian Date (see Note 2), apportioned in any\n    **     convenient way between the two arguments, for example where utc1\n    **     is the Julian Day Number and utc2 is the fraction of a day.\n    **\n    **  2) JD cannot unambiguously represent UTC during a leap second unless\n    **     special measures are taken.  The convention in the present\n    **     function is that the JD day represents UTC days whether the\n    **     length is 86399, 86400 or 86401 SI seconds.\n    **\n    **  3) The warning status \"dubious year\" flags UTCs that predate the\n    **     introduction of the time scale and that are too far in the future\n    **     to be trusted.  See iauDat  for further details.\n    **\n    **  4) The function iauDtf2d  converts from calendar date and time of\n    **     day into 2-part Julian Date, and in the case of UTC implements\n    **     the leap-second-ambiguity convention described above.\n    **\n    **  5) Delta UT1 can be obtained from tabulations provided by the\n    **     International Earth Rotation and Reference Systems Service.  It\n    **     It is the caller's responsibility to supply a DUT argument\n    **     containing the UT1-UTC value that matches the given UTC.\n    **\n    **  6) The returned ut11,ut12 are such that their sum is the UT1 Julian\n    **     Date.\n    **\n    **  7) The warning status ""\"dubious year\" flags UTCs that predate the\n    **     introduction of the time scale and that are too far in the future\n    **     to be trusted.  See iauDat for further details.\n    ";
+static PyMethodDef __pyx_mdef_7astropy_4time_9sofa_time_20utc_ut1 = {__Pyx_NAMESTR("utc_ut1"), (PyCFunction)__pyx_pf_7astropy_4time_9sofa_time_20utc_ut1, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(__pyx_doc_7astropy_4time_9sofa_time_20utc_ut1)};
+static PyObject *__pyx_pf_7astropy_4time_9sofa_time_20utc_ut1(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyArrayObject *__pyx_v_in1 = 0;
+  PyArrayObject *__pyx_v_in2 = 0;
+  PyArrayObject *__pyx_v_dt = 0;
+  unsigned int __pyx_v_n;
+  unsigned int __pyx_v_i;
+  PyArrayObject *__pyx_v_out1 = 0;
+  PyArrayObject *__pyx_v_out2 = 0;
+  PyObject *__pyx_v_warns = NULL;
+  PyObject *__pyx_v_errs = NULL;
+  int __pyx_v_ret;
+  Py_buffer __pyx_bstruct_out1;
+  Py_ssize_t __pyx_bstride_0_out1 = 0;
+  Py_ssize_t __pyx_bshape_0_out1 = 0;
+  Py_buffer __pyx_bstruct_out2;
+  Py_ssize_t __pyx_bstride_0_out2 = 0;
+  Py_ssize_t __pyx_bshape_0_out2 = 0;
+  Py_buffer __pyx_bstruct_in1;
+  Py_ssize_t __pyx_bstride_0_in1 = 0;
+  Py_ssize_t __pyx_bshape_0_in1 = 0;
+  Py_buffer __pyx_bstruct_in2;
+  Py_ssize_t __pyx_bstride_0_in2 = 0;
+  Py_ssize_t __pyx_bshape_0_in2 = 0;
+  Py_buffer __pyx_bstruct_dt;
+  Py_ssize_t __pyx_bstride_0_dt = 0;
+  Py_ssize_t __pyx_bshape_0_dt = 0;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  int __pyx_t_1;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
+  PyObject *__pyx_t_5 = NULL;
+  PyObject *__pyx_t_6 = NULL;
+  PyArrayObject *__pyx_t_7 = NULL;
+  PyArrayObject *__pyx_t_8 = NULL;
+  unsigned int __pyx_t_9;
+  unsigned int __pyx_t_10;
+  unsigned int __pyx_t_11;
+  unsigned int __pyx_t_12;
+  unsigned int __pyx_t_13;
+  unsigned int __pyx_t_14;
+  unsigned int __pyx_t_15;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__in1,&__pyx_n_s__in2,&__pyx_n_s__dt,0};
+  __Pyx_RefNannySetupContext("utc_ut1");
+  __pyx_self = __pyx_self;
+  {
+    PyObject* values[3] = {0,0,0};
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  0:
+        values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__in1);
+        if (likely(values[0])) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+        case  1:
+        values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__in2);
+        if (likely(values[1])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("utc_ut1", 1, 3, 3, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1045; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+        case  2:
+        values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__dt);
+        if (likely(values[2])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("utc_ut1", 1, 3, 3, 2); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1045; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "utc_ut1") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1045; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+    } else if (PyTuple_GET_SIZE(__pyx_args) != 3) {
+      goto __pyx_L5_argtuple_error;
+    } else {
+      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+      values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+    }
+    __pyx_v_in1 = ((PyArrayObject *)values[0]);
+    __pyx_v_in2 = ((PyArrayObject *)values[1]);
+    __pyx_v_dt = ((PyArrayObject *)values[2]);
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("utc_ut1", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1045; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("astropy.time.sofa_time.utc_ut1", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_bstruct_out1.buf = NULL;
+  __pyx_bstruct_out2.buf = NULL;
+  __pyx_bstruct_in1.buf = NULL;
+  __pyx_bstruct_in2.buf = NULL;
+  __pyx_bstruct_dt.buf = NULL;
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_in1), __pyx_ptype_5numpy_ndarray, 1, "in1", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1046; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_in2), __pyx_ptype_5numpy_ndarray, 1, "in2", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1047; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_dt), __pyx_ptype_5numpy_ndarray, 1, "dt", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1048; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_in1, (PyObject*)__pyx_v_in1, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1045; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_in1 = __pyx_bstruct_in1.strides[0];
+  __pyx_bshape_0_in1 = __pyx_bstruct_in1.shape[0];
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_in2, (PyObject*)__pyx_v_in2, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1045; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_in2 = __pyx_bstruct_in2.strides[0];
+  __pyx_bshape_0_in2 = __pyx_bstruct_in2.shape[0];
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_dt, (PyObject*)__pyx_v_dt, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1045; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_dt = __pyx_bstruct_dt.strides[0];
+  __pyx_bshape_0_dt = __pyx_bstruct_dt.shape[0];
+
+  /* "astropy/time/sofa_time.pyx":1095
+ *     **     to be trusted.  See iauDat for further details.
+ *     """
+ *     assert in1.shape[0] == in2.shape[0] == dt.shape[0]             # <<<<<<<<<<<<<<
+ *     cdef unsigned n = in1.shape[0]
+ *     cdef unsigned int i
+ */
+  #ifndef CYTHON_WITHOUT_ASSERTIONS
+  __pyx_t_1 = ((__pyx_v_in1->dimensions[0]) == (__pyx_v_in2->dimensions[0]));
+  if (__pyx_t_1) {
+    __pyx_t_1 = ((__pyx_v_in2->dimensions[0]) == (__pyx_v_dt->dimensions[0]));
+  }
+  if (unlikely(!__pyx_t_1)) {
+    PyErr_SetNone(PyExc_AssertionError);
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1095; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  #endif
+
+  /* "astropy/time/sofa_time.pyx":1096
+ *     """
+ *     assert in1.shape[0] == in2.shape[0] == dt.shape[0]
+ *     cdef unsigned n = in1.shape[0]             # <<<<<<<<<<<<<<
+ *     cdef unsigned int i
+ *     cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)
+ */
+  __pyx_v_n = (__pyx_v_in1->dimensions[0]);
+
+  /* "astropy/time/sofa_time.pyx":1098
+ *     cdef unsigned n = in1.shape[0]
+ *     cdef unsigned int i
+ *     cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)             # <<<<<<<<<<<<<<
+ *     cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)
+ * 
+ */
+  __pyx_t_2 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1098; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_3 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s__empty); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1098; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __pyx_t_2 = PyLong_FromUnsignedLong(__pyx_v_n); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1098; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1098; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_4));
+  PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_2);
+  __Pyx_GIVEREF(__pyx_t_2);
+  __pyx_t_2 = 0;
+  __pyx_t_2 = PyDict_New(); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1098; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_2));
+  __pyx_t_5 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1098; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __pyx_t_6 = PyObject_GetAttr(__pyx_t_5, __pyx_n_s__double); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1098; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_6);
+  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  if (PyDict_SetItem(__pyx_t_2, ((PyObject *)__pyx_n_s__dtype), __pyx_t_6) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1098; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+  __pyx_t_6 = PyEval_CallObjectWithKeywords(__pyx_t_3, ((PyObject *)__pyx_t_4), ((PyObject *)__pyx_t_2)); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1098; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_6);
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
+  if (!(likely(((__pyx_t_6) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_6, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1098; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_7 = ((PyArrayObject *)__pyx_t_6);
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_out1, (PyObject*)__pyx_t_7, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {
+      __pyx_v_out1 = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_out1.buf = NULL;
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1098; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    } else {__pyx_bstride_0_out1 = __pyx_bstruct_out1.strides[0];
+      __pyx_bshape_0_out1 = __pyx_bstruct_out1.shape[0];
+    }
+  }
+  __pyx_t_7 = 0;
+  __pyx_v_out1 = ((PyArrayObject *)__pyx_t_6);
+  __pyx_t_6 = 0;
+
+  /* "astropy/time/sofa_time.pyx":1099
+ *     cdef unsigned int i
+ *     cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)
+ *     cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)             # <<<<<<<<<<<<<<
+ * 
+ *     warns = {1: DUBIOUS}
+ */
+  __pyx_t_6 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1099; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_6);
+  __pyx_t_2 = PyObject_GetAttr(__pyx_t_6, __pyx_n_s__empty); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1099; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+  __pyx_t_6 = PyLong_FromUnsignedLong(__pyx_v_n); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1099; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_6);
+  __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1099; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_4));
+  PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_6);
+  __Pyx_GIVEREF(__pyx_t_6);
+  __pyx_t_6 = 0;
+  __pyx_t_6 = PyDict_New(); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1099; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_6));
+  __pyx_t_3 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1099; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __pyx_t_5 = PyObject_GetAttr(__pyx_t_3, __pyx_n_s__double); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1099; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  if (PyDict_SetItem(__pyx_t_6, ((PyObject *)__pyx_n_s__dtype), __pyx_t_5) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1099; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  __pyx_t_5 = PyEval_CallObjectWithKeywords(__pyx_t_2, ((PyObject *)__pyx_t_4), ((PyObject *)__pyx_t_6)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1099; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_6)); __pyx_t_6 = 0;
+  if (!(likely(((__pyx_t_5) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_5, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1099; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_8 = ((PyArrayObject *)__pyx_t_5);
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_out2, (PyObject*)__pyx_t_8, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {
+      __pyx_v_out2 = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_out2.buf = NULL;
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1099; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    } else {__pyx_bstride_0_out2 = __pyx_bstruct_out2.strides[0];
+      __pyx_bshape_0_out2 = __pyx_bstruct_out2.shape[0];
+    }
+  }
+  __pyx_t_8 = 0;
+  __pyx_v_out2 = ((PyArrayObject *)__pyx_t_5);
+  __pyx_t_5 = 0;
+
+  /* "astropy/time/sofa_time.pyx":1101
+ *     cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)
+ * 
+ *     warns = {1: DUBIOUS}             # <<<<<<<<<<<<<<
+ *     errs = {-1: 'unacceptable date'}
+ * 
+ */
+  __pyx_t_5 = PyDict_New(); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1101; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_5));
+  __pyx_t_6 = __Pyx_GetName(__pyx_m, __pyx_n_s__DUBIOUS); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1101; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_6);
+  if (PyDict_SetItem(__pyx_t_5, __pyx_int_1, __pyx_t_6) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1101; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+  __pyx_v_warns = __pyx_t_5;
+  __pyx_t_5 = 0;
+
+  /* "astropy/time/sofa_time.pyx":1102
+ * 
+ *     warns = {1: DUBIOUS}
+ *     errs = {-1: 'unacceptable date'}             # <<<<<<<<<<<<<<
+ * 
+ *     for i in range(n):
+ */
+  __pyx_t_5 = PyDict_New(); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1102; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_5));
+  if (PyDict_SetItem(__pyx_t_5, __pyx_int_neg_1, ((PyObject *)__pyx_kp_s_12)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1102; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_v_errs = __pyx_t_5;
+  __pyx_t_5 = 0;
+
+  /* "astropy/time/sofa_time.pyx":1104
+ *     errs = {-1: 'unacceptable date'}
+ * 
+ *     for i in range(n):             # <<<<<<<<<<<<<<
+ *         ret = iauUtcut1(in1[i], in2[i], dt[i], &out1[i], &out2[i])
+ *         check_return(ret, 'iauUtcut1', warns, errs)
+ */
+  __pyx_t_9 = __pyx_v_n;
+  for (__pyx_t_10 = 0; __pyx_t_10 < __pyx_t_9; __pyx_t_10+=1) {
+    __pyx_v_i = __pyx_t_10;
+
+    /* "astropy/time/sofa_time.pyx":1105
+ * 
+ *     for i in range(n):
+ *         ret = iauUtcut1(in1[i], in2[i], dt[i], &out1[i], &out2[i])             # <<<<<<<<<<<<<<
+ *         check_return(ret, 'iauUtcut1', warns, errs)
+ * 
+ */
+    __pyx_t_11 = __pyx_v_i;
+    __pyx_t_12 = __pyx_v_i;
+    __pyx_t_13 = __pyx_v_i;
+    __pyx_t_14 = __pyx_v_i;
+    __pyx_t_15 = __pyx_v_i;
+    __pyx_v_ret = iauUtcut1((*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_in1.buf, __pyx_t_11, __pyx_bstride_0_in1)), (*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_in2.buf, __pyx_t_12, __pyx_bstride_0_in2)), (*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_dt.buf, __pyx_t_13, __pyx_bstride_0_dt)), (&(*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_out1.buf, __pyx_t_14, __pyx_bstride_0_out1))), (&(*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_out2.buf, __pyx_t_15, __pyx_bstride_0_out2))));
+
+    /* "astropy/time/sofa_time.pyx":1106
+ *     for i in range(n):
+ *         ret = iauUtcut1(in1[i], in2[i], dt[i], &out1[i], &out2[i])
+ *         check_return(ret, 'iauUtcut1', warns, errs)             # <<<<<<<<<<<<<<
+ * 
+ *     return out1, out2
+ */
+    __pyx_t_5 = __Pyx_GetName(__pyx_m, __pyx_n_s__check_return); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1106; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_5);
+    __pyx_t_6 = PyInt_FromLong(__pyx_v_ret); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1106; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_6);
+    __pyx_t_4 = PyTuple_New(4); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1106; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(((PyObject *)__pyx_t_4));
+    PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_6);
+    __Pyx_GIVEREF(__pyx_t_6);
+    __Pyx_INCREF(((PyObject *)__pyx_n_s__iauUtcut1));
+    PyTuple_SET_ITEM(__pyx_t_4, 1, ((PyObject *)__pyx_n_s__iauUtcut1));
+    __Pyx_GIVEREF(((PyObject *)__pyx_n_s__iauUtcut1));
+    __Pyx_INCREF(((PyObject *)__pyx_v_warns));
+    PyTuple_SET_ITEM(__pyx_t_4, 2, ((PyObject *)__pyx_v_warns));
+    __Pyx_GIVEREF(((PyObject *)__pyx_v_warns));
+    __Pyx_INCREF(((PyObject *)__pyx_v_errs));
+    PyTuple_SET_ITEM(__pyx_t_4, 3, ((PyObject *)__pyx_v_errs));
+    __Pyx_GIVEREF(((PyObject *)__pyx_v_errs));
+    __pyx_t_6 = 0;
+    __pyx_t_6 = PyObject_Call(__pyx_t_5, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1106; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_6);
+    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+    __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
+    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+  }
+
+  /* "astropy/time/sofa_time.pyx":1108
+ *         check_return(ret, 'iauUtcut1', warns, errs)
+ * 
+ *     return out1, out2             # <<<<<<<<<<<<<<
+ * 
+ * 
+ */
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_t_6 = PyTuple_New(2); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1108; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_6));
+  __Pyx_INCREF(((PyObject *)__pyx_v_out1));
+  PyTuple_SET_ITEM(__pyx_t_6, 0, ((PyObject *)__pyx_v_out1));
+  __Pyx_GIVEREF(((PyObject *)__pyx_v_out1));
+  __Pyx_INCREF(((PyObject *)__pyx_v_out2));
+  PyTuple_SET_ITEM(__pyx_t_6, 1, ((PyObject *)__pyx_v_out2));
+  __Pyx_GIVEREF(((PyObject *)__pyx_v_out2));
+  __pyx_r = ((PyObject *)__pyx_t_6);
+  __pyx_t_6 = 0;
+  goto __pyx_L0;
+
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_XDECREF(__pyx_t_5);
+  __Pyx_XDECREF(__pyx_t_6);
+  { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;
+    __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out1);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out2);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in1);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in2);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_dt);
+  __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
+  __Pyx_AddTraceback("astropy.time.sofa_time.utc_ut1", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  goto __pyx_L2;
+  __pyx_L0:;
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out1);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out2);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in1);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in2);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_dt);
+  __pyx_L2:;
+  __Pyx_XDECREF((PyObject *)__pyx_v_out1);
+  __Pyx_XDECREF((PyObject *)__pyx_v_out2);
+  __Pyx_XDECREF(__pyx_v_warns);
+  __Pyx_XDECREF(__pyx_v_errs);
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "astropy/time/sofa_time.pyx":1113
+ * @cython.wraparound(False)
+ * @cython.boundscheck(False)
+ * def d_tdb_tt(np.ndarray[double, ndim=1] in1,             # <<<<<<<<<<<<<<
+ *              np.ndarray[double, ndim=1] in2,
+ *              np.ndarray[double, ndim=1] ut,
+ */
+
+static PyObject *__pyx_pf_7astropy_4time_9sofa_time_21d_tdb_tt(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_7astropy_4time_9sofa_time_21d_tdb_tt[] = "\n    compute DTR = TDB-TT\n    double iauDtdb(double date1, double date2, double ut,\n                   double elong, double u, double v)\n\n    **  Given:\n    **     date1,date2   double  date, TDB (Notes 1-3)\n    **     ut            double  universal time (UT1, fraction of one day)\n    **     elong         double  longitude (east positive, radians)\n    **     u             double  distance from Earth spin axis (km)\n    **     v             double  distance north of equatorial plane (km)\n    **\n    **  Returned (function value):\n    **                   double  TDB-TT (seconds)\n    **\n    **  Notes:\n    **\n    **  1) The date date1+date2 is a Julian Date, apportioned in any\n    **     convenient way between the two arguments.  For example,\n    **     JD(TT)=2450123.7 could be expressed in any of these ways,\n    **     among others:\n    **\n    **            date1          date2\n    **\n    **         2450123.7           0.0       (JD method)\n    **         2451545.0       -1421.3       (J2000 method)\n    **         2400000.5       50123.2       (MJD method)\n    **         2450123.5           0.2       (date & time method)\n    **\n    **     The JD method is the most natural and convenient to use in\n    **     cases where the loss of several decimal digits of resolution\n    **     is acceptable.  The J2000 method is best matched to the way\n    **     the argument is handled internally and will deliver the\n    **     optimum resolution.  The MJD method and the date & time methods\n    **     are both good compromises between resolution and convenience.\n    **\n    **     Although the date is, formally, barycentric dynamical time (TDB),\n    **     the terrestrial dynamical time (TT) can be used with no practical\n    **     effect on the accuracy of the prediction.\n    **\n    **  2) TT can be regarded as a coordinate time that is realized as an\n    **     offset of 32.184s from International Atomic Time, TAI.  TT is a\n    **     speci""fic linear transformation of geocentric coordinate time TCG,\n    **     which is the time scale for the Geocentric Celestial Reference\n    **     System, GCRS.\n    **\n    **  3) TDB is a coordinate time, and is a specific linear transformation\n    **     of barycentric coordinate time TCB, which is the time scale for\n    **     the Barycentric Celestial Reference System, BCRS.\n    **\n    **  4) The difference TCG-TCB depends on the masses and positions of the\n    **     bodies of the solar system and the velocity of the Earth.  It is\n    **     dominated by a rate difference, the residual being of a periodic\n    **     character.  The latter, which is modeled by the present function,\n    **     comprises a main (annual) sinusoidal term of amplitude\n    **     approximately 0.00166 seconds, plus planetary terms up to about\n    **     20 microseconds, and lunar and diurnal terms up to 2 microseconds.\n    **     These effects come from the changing transverse Doppler effect\n    **     and gravitational red-shift as the observer (on the Earth's\n    **     surface) experiences variations in speed (with respect to the\n    **     BCRS) and gravitational potential.\n    **\n    **  5) TDB can be regarded as the same as TCB but with a rate adjustment\n    **     to keep it close to TT, which is convenient for many applications.\n    **     The history of successive attempts to define TDB is set out in\n    **     Resolution 3 adopted by the IAU General Assembly in 2006, which\n    **     defines a fixed TDB(TCB) transformation that is consistent with\n    **     contemporary solar-system ephemerides.  Future ephemerides will\n    **     imply slightly changed transformations between TCG and TCB, which\n    **     could introduce a linear drift between TDB and TT;  however, any\n    **     such drift is unlikely to exceed 1 nanosecond per century.\n    **\n    **  6) The geocentric TDB-TT model used in the present function is that of\n    **     Fairhead & B""retagnon (1990), in its full form.  It was originally\n    **     supplied by Fairhead (private communications with P.T.Wallace,\n    **     1990) as a Fortran subroutine.  The present C function contains an\n    **     adaptation of the Fairhead code.  The numerical results are\n    **     essentially unaffected by the changes, the differences with\n    **     respect to the Fairhead & Bretagnon original being at the 1e-20 s\n    **     level.\n    **\n    **     The topocentric part of the model is from Moyer (1981) and\n    **     Murray (1983), with fundamental arguments adapted from\n    **     Simon et al. 1994.  It is an approximation to the expression\n    **     ( v / c ) . ( r / c ), where v is the barycentric velocity of\n    **     the Earth, r is the geocentric position of the observer and\n    **     c is the speed of light.\n    **\n    **     By supplying zeroes for u and v, the topocentric part of the\n    **     model can be nullified, and the function will return the Fairhead\n    **     & Bretagnon result alone.\n    **\n    **  7) During the interval 1950-2050, the absolute accuracy is better\n    **     than +/- 3 nanoseconds relative to time ephemerides obtained by\n    **     direct numerical integrations based on the JPL DE405 solar system\n    **     ephemeris.\n    **\n    **  8) It must be stressed that the present function is merely a model,\n    **     and that numerical integration of solar-system ephemerides is the\n    **     definitive method for predicting the relationship between TCG and\n    **     TCB and hence between TT and TDB.\n    ";
+static PyMethodDef __pyx_mdef_7astropy_4time_9sofa_time_21d_tdb_tt = {__Pyx_NAMESTR("d_tdb_tt"), (PyCFunction)__pyx_pf_7astropy_4time_9sofa_time_21d_tdb_tt, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(__pyx_doc_7astropy_4time_9sofa_time_21d_tdb_tt)};
+static PyObject *__pyx_pf_7astropy_4time_9sofa_time_21d_tdb_tt(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyArrayObject *__pyx_v_in1 = 0;
+  PyArrayObject *__pyx_v_in2 = 0;
+  PyArrayObject *__pyx_v_ut = 0;
+  PyObject *__pyx_v_elong = 0;
+  PyObject *__pyx_v_u = 0;
+  PyObject *__pyx_v_v = 0;
+  unsigned int __pyx_v_n;
+  unsigned int __pyx_v_i;
+  PyArrayObject *__pyx_v_out = 0;
+  double __pyx_v_c_elong;
+  double __pyx_v_c_u;
+  double __pyx_v_c_v;
+  Py_buffer __pyx_bstruct_ut;
+  Py_ssize_t __pyx_bstride_0_ut = 0;
+  Py_ssize_t __pyx_bshape_0_ut = 0;
+  Py_buffer __pyx_bstruct_in1;
+  Py_ssize_t __pyx_bstride_0_in1 = 0;
+  Py_ssize_t __pyx_bshape_0_in1 = 0;
+  Py_buffer __pyx_bstruct_in2;
+  Py_ssize_t __pyx_bstride_0_in2 = 0;
+  Py_ssize_t __pyx_bshape_0_in2 = 0;
+  Py_buffer __pyx_bstruct_out;
+  Py_ssize_t __pyx_bstride_0_out = 0;
+  Py_ssize_t __pyx_bshape_0_out = 0;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  int __pyx_t_1;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
+  PyObject *__pyx_t_5 = NULL;
+  PyObject *__pyx_t_6 = NULL;
+  PyArrayObject *__pyx_t_7 = NULL;
+  double __pyx_t_8;
+  unsigned int __pyx_t_9;
+  unsigned int __pyx_t_10;
+  unsigned int __pyx_t_11;
+  unsigned int __pyx_t_12;
+  unsigned int __pyx_t_13;
+  unsigned int __pyx_t_14;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__in1,&__pyx_n_s__in2,&__pyx_n_s__ut,&__pyx_n_s__elong,&__pyx_n_s__u,&__pyx_n_s__v,0};
+  __Pyx_RefNannySetupContext("d_tdb_tt");
+  __pyx_self = __pyx_self;
+  {
+    PyObject* values[6] = {0,0,0,0,0,0};
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  6: values[5] = PyTuple_GET_ITEM(__pyx_args, 5);
+        case  5: values[4] = PyTuple_GET_ITEM(__pyx_args, 4);
+        case  4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
+        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  0:
+        values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__in1);
+        if (likely(values[0])) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+        case  1:
+        values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__in2);
+        if (likely(values[1])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("d_tdb_tt", 1, 6, 6, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1113; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+        case  2:
+        values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__ut);
+        if (likely(values[2])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("d_tdb_tt", 1, 6, 6, 2); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1113; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+        case  3:
+        values[3] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__elong);
+        if (likely(values[3])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("d_tdb_tt", 1, 6, 6, 3); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1113; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+        case  4:
+        values[4] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__u);
+        if (likely(values[4])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("d_tdb_tt", 1, 6, 6, 4); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1113; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+        case  5:
+        values[5] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__v);
+        if (likely(values[5])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("d_tdb_tt", 1, 6, 6, 5); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1113; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "d_tdb_tt") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1113; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+    } else if (PyTuple_GET_SIZE(__pyx_args) != 6) {
+      goto __pyx_L5_argtuple_error;
+    } else {
+      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+      values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+      values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
+      values[4] = PyTuple_GET_ITEM(__pyx_args, 4);
+      values[5] = PyTuple_GET_ITEM(__pyx_args, 5);
+    }
+    __pyx_v_in1 = ((PyArrayObject *)values[0]);
+    __pyx_v_in2 = ((PyArrayObject *)values[1]);
+    __pyx_v_ut = ((PyArrayObject *)values[2]);
+    __pyx_v_elong = values[3];
+    __pyx_v_u = values[4];
+    __pyx_v_v = values[5];
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("d_tdb_tt", 1, 6, 6, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1113; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("astropy.time.sofa_time.d_tdb_tt", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_bstruct_out.buf = NULL;
+  __pyx_bstruct_in1.buf = NULL;
+  __pyx_bstruct_in2.buf = NULL;
+  __pyx_bstruct_ut.buf = NULL;
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_in1), __pyx_ptype_5numpy_ndarray, 1, "in1", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1113; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_in2), __pyx_ptype_5numpy_ndarray, 1, "in2", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1114; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ut), __pyx_ptype_5numpy_ndarray, 1, "ut", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1115; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_in1, (PyObject*)__pyx_v_in1, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1113; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_in1 = __pyx_bstruct_in1.strides[0];
+  __pyx_bshape_0_in1 = __pyx_bstruct_in1.shape[0];
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_in2, (PyObject*)__pyx_v_in2, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1113; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_in2 = __pyx_bstruct_in2.strides[0];
+  __pyx_bshape_0_in2 = __pyx_bstruct_in2.shape[0];
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_ut, (PyObject*)__pyx_v_ut, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1113; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_ut = __pyx_bstruct_ut.strides[0];
+  __pyx_bshape_0_ut = __pyx_bstruct_ut.shape[0];
+
+  /* "astropy/time/sofa_time.pyx":1219
+ *     **     TCB and hence between TT and TDB.
+ *     """
+ *     assert in1.shape[0] == in2.shape[0] == ut.shape[0]             # <<<<<<<<<<<<<<
+ *     cdef unsigned n = in1.shape[0]
+ *     cdef unsigned int i
+ */
+  #ifndef CYTHON_WITHOUT_ASSERTIONS
+  __pyx_t_1 = ((__pyx_v_in1->dimensions[0]) == (__pyx_v_in2->dimensions[0]));
+  if (__pyx_t_1) {
+    __pyx_t_1 = ((__pyx_v_in2->dimensions[0]) == (__pyx_v_ut->dimensions[0]));
+  }
+  if (unlikely(!__pyx_t_1)) {
+    PyErr_SetNone(PyExc_AssertionError);
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1219; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  #endif
+
+  /* "astropy/time/sofa_time.pyx":1220
+ *     """
+ *     assert in1.shape[0] == in2.shape[0] == ut.shape[0]
+ *     cdef unsigned n = in1.shape[0]             # <<<<<<<<<<<<<<
+ *     cdef unsigned int i
+ *     cdef np.ndarray[double, ndim=1] out = np.empty(n, dtype=np.double)
+ */
+  __pyx_v_n = (__pyx_v_in1->dimensions[0]);
+
+  /* "astropy/time/sofa_time.pyx":1222
+ *     cdef unsigned n = in1.shape[0]
+ *     cdef unsigned int i
+ *     cdef np.ndarray[double, ndim=1] out = np.empty(n, dtype=np.double)             # <<<<<<<<<<<<<<
+ *     cdef double c_elong = elong
+ *     cdef double c_u = u
+ */
+  __pyx_t_2 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1222; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_3 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s__empty); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1222; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __pyx_t_2 = PyLong_FromUnsignedLong(__pyx_v_n); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1222; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1222; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_4));
+  PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_2);
+  __Pyx_GIVEREF(__pyx_t_2);
+  __pyx_t_2 = 0;
+  __pyx_t_2 = PyDict_New(); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1222; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_2));
+  __pyx_t_5 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1222; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __pyx_t_6 = PyObject_GetAttr(__pyx_t_5, __pyx_n_s__double); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1222; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_6);
+  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  if (PyDict_SetItem(__pyx_t_2, ((PyObject *)__pyx_n_s__dtype), __pyx_t_6) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1222; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+  __pyx_t_6 = PyEval_CallObjectWithKeywords(__pyx_t_3, ((PyObject *)__pyx_t_4), ((PyObject *)__pyx_t_2)); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1222; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_6);
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
+  if (!(likely(((__pyx_t_6) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_6, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1222; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_7 = ((PyArrayObject *)__pyx_t_6);
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_out, (PyObject*)__pyx_t_7, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 1, 0, __pyx_stack) == -1)) {
+      __pyx_v_out = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_out.buf = NULL;
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1222; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    } else {__pyx_bstride_0_out = __pyx_bstruct_out.strides[0];
+      __pyx_bshape_0_out = __pyx_bstruct_out.shape[0];
+    }
+  }
+  __pyx_t_7 = 0;
+  __pyx_v_out = ((PyArrayObject *)__pyx_t_6);
+  __pyx_t_6 = 0;
+
+  /* "astropy/time/sofa_time.pyx":1223
+ *     cdef unsigned int i
+ *     cdef np.ndarray[double, ndim=1] out = np.empty(n, dtype=np.double)
+ *     cdef double c_elong = elong             # <<<<<<<<<<<<<<
+ *     cdef double c_u = u
+ *     cdef double c_v = v
+ */
+  __pyx_t_8 = __pyx_PyFloat_AsDouble(__pyx_v_elong); if (unlikely((__pyx_t_8 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1223; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_v_c_elong = __pyx_t_8;
+
+  /* "astropy/time/sofa_time.pyx":1224
+ *     cdef np.ndarray[double, ndim=1] out = np.empty(n, dtype=np.double)
+ *     cdef double c_elong = elong
+ *     cdef double c_u = u             # <<<<<<<<<<<<<<
+ *     cdef double c_v = v
+ * 
+ */
+  __pyx_t_8 = __pyx_PyFloat_AsDouble(__pyx_v_u); if (unlikely((__pyx_t_8 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1224; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_v_c_u = __pyx_t_8;
+
+  /* "astropy/time/sofa_time.pyx":1225
+ *     cdef double c_elong = elong
+ *     cdef double c_u = u
+ *     cdef double c_v = v             # <<<<<<<<<<<<<<
+ * 
+ *     for i in range(n):
+ */
+  __pyx_t_8 = __pyx_PyFloat_AsDouble(__pyx_v_v); if (unlikely((__pyx_t_8 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1225; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_v_c_v = __pyx_t_8;
+
+  /* "astropy/time/sofa_time.pyx":1227
+ *     cdef double c_v = v
+ * 
+ *     for i in range(n):             # <<<<<<<<<<<<<<
+ *         out[i] = iauDtdb(in1[i], in2[i], ut[i], c_elong, c_u, c_v)
+ *     return out
+ */
+  __pyx_t_9 = __pyx_v_n;
+  for (__pyx_t_10 = 0; __pyx_t_10 < __pyx_t_9; __pyx_t_10+=1) {
+    __pyx_v_i = __pyx_t_10;
+
+    /* "astropy/time/sofa_time.pyx":1228
+ * 
+ *     for i in range(n):
+ *         out[i] = iauDtdb(in1[i], in2[i], ut[i], c_elong, c_u, c_v)             # <<<<<<<<<<<<<<
+ *     return out
+ * 
+ */
+    __pyx_t_11 = __pyx_v_i;
+    __pyx_t_12 = __pyx_v_i;
+    __pyx_t_13 = __pyx_v_i;
+    __pyx_t_14 = __pyx_v_i;
+    *__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_out.buf, __pyx_t_14, __pyx_bstride_0_out) = iauDtdb((*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_in1.buf, __pyx_t_11, __pyx_bstride_0_in1)), (*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_in2.buf, __pyx_t_12, __pyx_bstride_0_in2)), (*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_ut.buf, __pyx_t_13, __pyx_bstride_0_ut)), __pyx_v_c_elong, __pyx_v_c_u, __pyx_v_c_v);
+  }
+
+  /* "astropy/time/sofa_time.pyx":1229
+ *     for i in range(n):
+ *         out[i] = iauDtdb(in1[i], in2[i], ut[i], c_elong, c_u, c_v)
+ *     return out             # <<<<<<<<<<<<<<
+ * 
+ * 
+ */
+  __Pyx_XDECREF(__pyx_r);
+  __Pyx_INCREF(((PyObject *)__pyx_v_out));
+  __pyx_r = ((PyObject *)__pyx_v_out);
+  goto __pyx_L0;
+
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_XDECREF(__pyx_t_5);
+  __Pyx_XDECREF(__pyx_t_6);
+  { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;
+    __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_ut);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in1);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in2);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out);
+  __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
+  __Pyx_AddTraceback("astropy.time.sofa_time.d_tdb_tt", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  goto __pyx_L2;
+  __pyx_L0:;
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_ut);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in1);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_in2);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out);
+  __pyx_L2:;
+  __Pyx_XDECREF((PyObject *)__pyx_v_out);
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "astropy/time/sofa_time.pyx":1232
+ * 
+ * 
+ * def iau_af2a(sign, ideg, iamin, asec):             # <<<<<<<<<<<<<<
+ *     """
+ *     int iauAf2a(char s, int ideg, int iamin, double asec, double *rad)
+ */
+
+static PyObject *__pyx_pf_7astropy_4time_9sofa_time_22iau_af2a(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_7astropy_4time_9sofa_time_22iau_af2a[] = "\n    int iauAf2a(char s, int ideg, int iamin, double asec, double *rad)\n\n    **  Given:\n    **     s         char    sign:  '-' = negative, otherwise positive\n    **     ideg      int     degrees\n    **     iamin     int     arcminutes\n    **     asec      double  arcseconds\n    **\n    **  Returned:\n    **     rad       double  angle in radians\n    **\n    **  Returned (function value):\n    **               int     status:  0 = OK\n    **                                1 = ideg outside range 0-359\n    **                                2 = iamin outside range 0-59\n    **                                3 = asec outside range 0-59.999...\n    **\n    **  Notes:\n    **\n    **  1)  The result is computed even if any of the range checks fail.\n    **\n    **  2)  Negative ideg, iamin and/or asec produce a warning status, but\n    **      the absolute value is used in the conversion.\n    **\n    **  3)  If there are multiple errors, the status value reflects only the\n    **      first, the smallest taking precedence.\n    ";
+static PyMethodDef __pyx_mdef_7astropy_4time_9sofa_time_22iau_af2a = {__Pyx_NAMESTR("iau_af2a"), (PyCFunction)__pyx_pf_7astropy_4time_9sofa_time_22iau_af2a, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(__pyx_doc_7astropy_4time_9sofa_time_22iau_af2a)};
+static PyObject *__pyx_pf_7astropy_4time_9sofa_time_22iau_af2a(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyObject *__pyx_v_sign = 0;
+  PyObject *__pyx_v_ideg = 0;
+  PyObject *__pyx_v_iamin = 0;
+  PyObject *__pyx_v_asec = 0;
+  double __pyx_v_rad;
+  PyObject *__pyx_v_s = NULL;
+  PyObject *__pyx_v_warns = NULL;
+  int __pyx_v_ret;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  PyObject *__pyx_t_2 = NULL;
+  char __pyx_t_3;
+  int __pyx_t_4;
+  int __pyx_t_5;
+  double __pyx_t_6;
+  PyObject *__pyx_t_7 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__sign,&__pyx_n_s__ideg,&__pyx_n_s__iamin,&__pyx_n_s__asec,0};
+  __Pyx_RefNannySetupContext("iau_af2a");
+  __pyx_self = __pyx_self;
+  {
+    PyObject* values[4] = {0,0,0,0};
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
+        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  0:
+        values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__sign);
+        if (likely(values[0])) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+        case  1:
+        values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__ideg);
+        if (likely(values[1])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("iau_af2a", 1, 4, 4, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1232; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+        case  2:
+        values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__iamin);
+        if (likely(values[2])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("iau_af2a", 1, 4, 4, 2); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1232; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+        case  3:
+        values[3] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__asec);
+        if (likely(values[3])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("iau_af2a", 1, 4, 4, 3); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1232; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "iau_af2a") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1232; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+    } else if (PyTuple_GET_SIZE(__pyx_args) != 4) {
+      goto __pyx_L5_argtuple_error;
+    } else {
+      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+      values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+      values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
+    }
+    __pyx_v_sign = values[0];
+    __pyx_v_ideg = values[1];
+    __pyx_v_iamin = values[2];
+    __pyx_v_asec = values[3];
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("iau_af2a", 1, 4, 4, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1232; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("astropy.time.sofa_time.iau_af2a", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+
+  /* "astropy/time/sofa_time.pyx":1262
+ *     """
+ *     cdef double rad
+ *     s = ord(sign)             # <<<<<<<<<<<<<<
+ * 
+ *     warns = {1: 'ideg outside range 0-359',
+ */
+  __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1262; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_1));
+  __Pyx_INCREF(__pyx_v_sign);
+  PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v_sign);
+  __Pyx_GIVEREF(__pyx_v_sign);
+  __pyx_t_2 = PyObject_Call(__pyx_builtin_ord, ((PyObject *)__pyx_t_1), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1262; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
+  __pyx_v_s = __pyx_t_2;
+  __pyx_t_2 = 0;
+
+  /* "astropy/time/sofa_time.pyx":1264
+ *     s = ord(sign)
+ * 
+ *     warns = {1: 'ideg outside range 0-359',             # <<<<<<<<<<<<<<
+ *              2: 'iamin outside range 0-59',
+ *              3: 'asec outside range 0-59.999...'}
+ */
+  __pyx_t_2 = PyDict_New(); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1264; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_2));
+  if (PyDict_SetItem(__pyx_t_2, __pyx_int_1, ((PyObject *)__pyx_kp_s_20)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1264; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyDict_SetItem(__pyx_t_2, __pyx_int_2, ((PyObject *)__pyx_kp_s_21)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1264; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyDict_SetItem(__pyx_t_2, __pyx_int_3, ((PyObject *)__pyx_kp_s_22)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1264; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_v_warns = __pyx_t_2;
+  __pyx_t_2 = 0;
+
+  /* "astropy/time/sofa_time.pyx":1268
+ *              3: 'asec outside range 0-59.999...'}
+ * 
+ *     ret = iauAf2a(s, ideg, iamin, asec, &rad)             # <<<<<<<<<<<<<<
+ *     check_return(ret, 'iauAf2a', warns)
+ * 
+ */
+  __pyx_t_3 = __Pyx_PyInt_AsChar(__pyx_v_s); if (unlikely((__pyx_t_3 == (char)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1268; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_4 = __Pyx_PyInt_AsInt(__pyx_v_ideg); if (unlikely((__pyx_t_4 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1268; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_5 = __Pyx_PyInt_AsInt(__pyx_v_iamin); if (unlikely((__pyx_t_5 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1268; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_6 = __pyx_PyFloat_AsDouble(__pyx_v_asec); if (unlikely((__pyx_t_6 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1268; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_v_ret = iauAf2a(__pyx_t_3, __pyx_t_4, __pyx_t_5, __pyx_t_6, (&__pyx_v_rad));
+
+  /* "astropy/time/sofa_time.pyx":1269
+ * 
+ *     ret = iauAf2a(s, ideg, iamin, asec, &rad)
+ *     check_return(ret, 'iauAf2a', warns)             # <<<<<<<<<<<<<<
+ * 
+ *     return rad
+ */
+  __pyx_t_2 = __Pyx_GetName(__pyx_m, __pyx_n_s__check_return); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1269; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_1 = PyInt_FromLong(__pyx_v_ret); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1269; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_7 = PyTuple_New(3); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1269; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_7));
+  PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_1);
+  __Pyx_GIVEREF(__pyx_t_1);
+  __Pyx_INCREF(((PyObject *)__pyx_n_s__iauAf2a));
+  PyTuple_SET_ITEM(__pyx_t_7, 1, ((PyObject *)__pyx_n_s__iauAf2a));
+  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__iauAf2a));
+  __Pyx_INCREF(((PyObject *)__pyx_v_warns));
+  PyTuple_SET_ITEM(__pyx_t_7, 2, ((PyObject *)__pyx_v_warns));
+  __Pyx_GIVEREF(((PyObject *)__pyx_v_warns));
+  __pyx_t_1 = 0;
+  __pyx_t_1 = PyObject_Call(__pyx_t_2, ((PyObject *)__pyx_t_7), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1269; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_7)); __pyx_t_7 = 0;
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+
+  /* "astropy/time/sofa_time.pyx":1271
+ *     check_return(ret, 'iauAf2a', warns)
+ * 
+ *     return rad             # <<<<<<<<<<<<<<
+ * 
+ * def iau_gd2gc(n, elong, phi, height):
+ */
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_t_1 = PyFloat_FromDouble(__pyx_v_rad); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1271; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_r = __pyx_t_1;
+  __pyx_t_1 = 0;
+  goto __pyx_L0;
+
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_7);
+  __Pyx_AddTraceback("astropy.time.sofa_time.iau_af2a", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
+  __Pyx_XDECREF(__pyx_v_s);
+  __Pyx_XDECREF(__pyx_v_warns);
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "astropy/time/sofa_time.pyx":1273
+ *     return rad
+ * 
+ * def iau_gd2gc(n, elong, phi, height):             # <<<<<<<<<<<<<<
+ *     """
+ *     Wrap
+ */
+
+static PyObject *__pyx_pf_7astropy_4time_9sofa_time_23iau_gd2gc(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_7astropy_4time_9sofa_time_23iau_gd2gc[] = "\n    Wrap\n    int iauGd2gc(int n, double elong, double phi, double height, double xyz[3])\n\n    **  Given:\n    **     n       int        ellipsoid identifier (Note 1)\n    **     elong   double     longitude (radians, east +ve)\n    **     phi     double     latitude (geodetic, radians, Note 3)\n    **     height  double     height above ellipsoid (geodetic, Notes 2,3)\n    **\n    **  Returned:\n    **     xyz     double[3]  geocentric vector (Note 2)\n    **\n    **  Returned (function value):\n    **             int        status:  0 = OK\n    **                                -1 = illegal identifier (Note 3)\n    **                                -2 = illegal case (Note 3)\n    **\n    **  Notes:\n    **\n    **  1) The identifier n is a number that specifies the choice of\n    **     reference ellipsoid.  The following are supported:\n    **\n    **        n    ellipsoid\n    **\n    **        1     WGS84\n    **        2     GRS80\n    **        3     WGS72\n    **\n    **     The n value has no significance outside the SOFA software.  For\n    **     convenience, symbols WGS84 etc. are defined in sofam.h.\n    **\n    **  2) The height (height, given) and the geocentric vector (xyz,\n    **     returned) are in meters.\n    **\n    **  3) No validation is performed on the arguments elong, phi and\n    **     height.  An error status -1 means that the identifier n is\n    **     illegal.  An error status -2 protects against cases that would\n    **     lead to arithmetic exceptions.  In all error cases, xyz is set\n    **     to zeros.\n    **\n    **  4) The inverse transformation is performed in the function iauGc2gd.\n    ";
+static PyMethodDef __pyx_mdef_7astropy_4time_9sofa_time_23iau_gd2gc = {__Pyx_NAMESTR("iau_gd2gc"), (PyCFunction)__pyx_pf_7astropy_4time_9sofa_time_23iau_gd2gc, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(__pyx_doc_7astropy_4time_9sofa_time_23iau_gd2gc)};
+static PyObject *__pyx_pf_7astropy_4time_9sofa_time_23iau_gd2gc(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyObject *__pyx_v_n = 0;
+  PyObject *__pyx_v_elong = 0;
+  PyObject *__pyx_v_phi = 0;
+  PyObject *__pyx_v_height = 0;
+  PyArrayObject *__pyx_v_xyz = 0;
+  PyObject *__pyx_v_errs = NULL;
+  int __pyx_v_ret;
+  Py_buffer __pyx_bstruct_xyz;
+  Py_ssize_t __pyx_bstride_0_xyz = 0;
+  Py_ssize_t __pyx_bshape_0_xyz = 0;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
+  PyArrayObject *__pyx_t_5 = NULL;
+  int __pyx_t_6;
+  double __pyx_t_7;
+  double __pyx_t_8;
+  double __pyx_t_9;
+  long __pyx_t_10;
+  int __pyx_t_11;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__n,&__pyx_n_s__elong,&__pyx_n_s__phi,&__pyx_n_s__height,0};
+  __Pyx_RefNannySetupContext("iau_gd2gc");
+  __pyx_self = __pyx_self;
+  {
+    PyObject* values[4] = {0,0,0,0};
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
+        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  0:
+        values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__n);
+        if (likely(values[0])) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+        case  1:
+        values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__elong);
+        if (likely(values[1])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("iau_gd2gc", 1, 4, 4, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1273; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+        case  2:
+        values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__phi);
+        if (likely(values[2])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("iau_gd2gc", 1, 4, 4, 2); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1273; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+        case  3:
+        values[3] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__height);
+        if (likely(values[3])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("iau_gd2gc", 1, 4, 4, 3); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1273; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "iau_gd2gc") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1273; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+    } else if (PyTuple_GET_SIZE(__pyx_args) != 4) {
+      goto __pyx_L5_argtuple_error;
+    } else {
+      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+      values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+      values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
+    }
+    __pyx_v_n = values[0];
+    __pyx_v_elong = values[1];
+    __pyx_v_phi = values[2];
+    __pyx_v_height = values[3];
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("iau_gd2gc", 1, 4, 4, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1273; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("astropy.time.sofa_time.iau_gd2gc", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_bstruct_xyz.buf = NULL;
+
+  /* "astropy/time/sofa_time.pyx":1317
+ *     **  4) The inverse transformation is performed in the function iauGc2gd.
+ *     """
+ *     cdef np.ndarray[double, ndim=1] xyz = np.empty(3, dtype=np.double)             # <<<<<<<<<<<<<<
+ * 
+ *     errs = {-1: 'illegal identifier',
+ */
+  __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1317; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_2 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s__empty); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1317; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1317; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_1));
+  __pyx_t_3 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1317; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __pyx_t_4 = PyObject_GetAttr(__pyx_t_3, __pyx_n_s__double); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1317; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_4);
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_n_s__dtype), __pyx_t_4) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1317; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  __pyx_t_4 = PyEval_CallObjectWithKeywords(__pyx_t_2, ((PyObject *)__pyx_k_tuple_23), ((PyObject *)__pyx_t_1)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1317; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_4);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
+  if (!(likely(((__pyx_t_4) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_4, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1317; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_5 = ((PyArrayObject *)__pyx_t_4);
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_xyz, (PyObject*)__pyx_t_5, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {
+      __pyx_v_xyz = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_xyz.buf = NULL;
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1317; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    } else {__pyx_bstride_0_xyz = __pyx_bstruct_xyz.strides[0];
+      __pyx_bshape_0_xyz = __pyx_bstruct_xyz.shape[0];
+    }
+  }
+  __pyx_t_5 = 0;
+  __pyx_v_xyz = ((PyArrayObject *)__pyx_t_4);
+  __pyx_t_4 = 0;
+
+  /* "astropy/time/sofa_time.pyx":1319
+ *     cdef np.ndarray[double, ndim=1] xyz = np.empty(3, dtype=np.double)
+ * 
+ *     errs = {-1: 'illegal identifier',             # <<<<<<<<<<<<<<
+ *              -2: 'illegal case'}
+ * 
+ */
+  __pyx_t_4 = PyDict_New(); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1319; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_4));
+  if (PyDict_SetItem(__pyx_t_4, __pyx_int_neg_1, ((PyObject *)__pyx_kp_s_24)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1319; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyDict_SetItem(__pyx_t_4, __pyx_int_neg_2, ((PyObject *)__pyx_kp_s_25)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1319; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_v_errs = __pyx_t_4;
+  __pyx_t_4 = 0;
+
+  /* "astropy/time/sofa_time.pyx":1322
+ *              -2: 'illegal case'}
+ * 
+ *     ret = iauGd2gc(n, elong, phi, height, &xyz[0])             # <<<<<<<<<<<<<<
+ *     check_return(ret, 'iauGd2gc', errors=errs)
+ * 
+ */
+  __pyx_t_6 = __Pyx_PyInt_AsInt(__pyx_v_n); if (unlikely((__pyx_t_6 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1322; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_7 = __pyx_PyFloat_AsDouble(__pyx_v_elong); if (unlikely((__pyx_t_7 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1322; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_8 = __pyx_PyFloat_AsDouble(__pyx_v_phi); if (unlikely((__pyx_t_8 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1322; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_9 = __pyx_PyFloat_AsDouble(__pyx_v_height); if (unlikely((__pyx_t_9 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1322; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_10 = 0;
+  __pyx_t_11 = -1;
+  if (__pyx_t_10 < 0) {
+    __pyx_t_10 += __pyx_bshape_0_xyz;
+    if (unlikely(__pyx_t_10 < 0)) __pyx_t_11 = 0;
+  } else if (unlikely(__pyx_t_10 >= __pyx_bshape_0_xyz)) __pyx_t_11 = 0;
+  if (unlikely(__pyx_t_11 != -1)) {
+    __Pyx_RaiseBufferIndexError(__pyx_t_11);
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1322; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_v_ret = iauGd2gc(__pyx_t_6, __pyx_t_7, __pyx_t_8, __pyx_t_9, (&(*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_xyz.buf, __pyx_t_10, __pyx_bstride_0_xyz))));
+
+  /* "astropy/time/sofa_time.pyx":1323
+ * 
+ *     ret = iauGd2gc(n, elong, phi, height, &xyz[0])
+ *     check_return(ret, 'iauGd2gc', errors=errs)             # <<<<<<<<<<<<<<
+ * 
+ *     return xyz
+ */
+  __pyx_t_4 = __Pyx_GetName(__pyx_m, __pyx_n_s__check_return); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1323; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_4);
+  __pyx_t_1 = PyInt_FromLong(__pyx_v_ret); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1323; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1323; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_2));
+  PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_1);
+  __Pyx_GIVEREF(__pyx_t_1);
+  __Pyx_INCREF(((PyObject *)__pyx_n_s__iauGd2gc));
+  PyTuple_SET_ITEM(__pyx_t_2, 1, ((PyObject *)__pyx_n_s__iauGd2gc));
+  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__iauGd2gc));
+  __pyx_t_1 = 0;
+  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1323; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_1));
+  if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_n_s__errors), ((PyObject *)__pyx_v_errs)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1323; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_3 = PyEval_CallObjectWithKeywords(__pyx_t_4, ((PyObject *)__pyx_t_2), ((PyObject *)__pyx_t_1)); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1323; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+
+  /* "astropy/time/sofa_time.pyx":1325
+ *     check_return(ret, 'iauGd2gc', errors=errs)
+ * 
+ *     return xyz             # <<<<<<<<<<<<<<
+ * 
+ * 
+ */
+  __Pyx_XDECREF(__pyx_r);
+  __Pyx_INCREF(((PyObject *)__pyx_v_xyz));
+  __pyx_r = ((PyObject *)__pyx_v_xyz);
+  goto __pyx_L0;
+
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
+  { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;
+    __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_xyz);
+  __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
+  __Pyx_AddTraceback("astropy.time.sofa_time.iau_gd2gc", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  goto __pyx_L2;
+  __pyx_L0:;
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_xyz);
+  __pyx_L2:;
+  __Pyx_XDECREF((PyObject *)__pyx_v_xyz);
+  __Pyx_XDECREF(__pyx_v_errs);
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "astropy/time/sofa_time.pyx":1330
+ * @cython.wraparound(False)
+ * @cython.boundscheck(False)
+ * def jd_julian_epoch(np.ndarray[double, ndim=1] jd1,             # <<<<<<<<<<<<<<
+ *                     np.ndarray[double, ndim=1] jd2):
+ *     """ Wrap double iauEpj(double dj1, double dj2)
+ */
+
+static PyObject *__pyx_pf_7astropy_4time_9sofa_time_24jd_julian_epoch(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_7astropy_4time_9sofa_time_24jd_julian_epoch[] = " Wrap double iauEpj(double dj1, double dj2)\n    **  Julian Date to Julian Epoch.\n\n    **  Given:\n    **     dj1,dj2    double     Julian Date (see note)\n    **\n    **  Returned (function value):\n    **                double     Julian Epoch\n    **\n    **  Note:\n    **\n    **     The Julian Date is supplied in two pieces, in the usual SOFA\n    **     manner, which is designed to preserve time resolution.  The\n    **     Julian Date is available as a single number by adding dj1 and\n    **     dj2.  The maximum resolution is achieved if dj1 is 2451545D0\n    **     (J2000.0).\n    ";
+static PyMethodDef __pyx_mdef_7astropy_4time_9sofa_time_24jd_julian_epoch = {__Pyx_NAMESTR("jd_julian_epoch"), (PyCFunction)__pyx_pf_7astropy_4time_9sofa_time_24jd_julian_epoch, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(__pyx_doc_7astropy_4time_9sofa_time_24jd_julian_epoch)};
+static PyObject *__pyx_pf_7astropy_4time_9sofa_time_24jd_julian_epoch(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyArrayObject *__pyx_v_jd1 = 0;
+  PyArrayObject *__pyx_v_jd2 = 0;
+  unsigned int __pyx_v_n;
+  unsigned int __pyx_v_i;
+  PyArrayObject *__pyx_v_epd = 0;
+  Py_buffer __pyx_bstruct_epd;
+  Py_ssize_t __pyx_bstride_0_epd = 0;
+  Py_ssize_t __pyx_bshape_0_epd = 0;
+  Py_buffer __pyx_bstruct_jd1;
+  Py_ssize_t __pyx_bstride_0_jd1 = 0;
+  Py_ssize_t __pyx_bshape_0_jd1 = 0;
+  Py_buffer __pyx_bstruct_jd2;
+  Py_ssize_t __pyx_bstride_0_jd2 = 0;
+  Py_ssize_t __pyx_bshape_0_jd2 = 0;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
+  PyObject *__pyx_t_5 = NULL;
+  PyArrayObject *__pyx_t_6 = NULL;
+  unsigned int __pyx_t_7;
+  unsigned int __pyx_t_8;
+  unsigned int __pyx_t_9;
+  unsigned int __pyx_t_10;
+  unsigned int __pyx_t_11;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__jd1,&__pyx_n_s__jd2,0};
+  __Pyx_RefNannySetupContext("jd_julian_epoch");
+  __pyx_self = __pyx_self;
+  {
+    PyObject* values[2] = {0,0};
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  0:
+        values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__jd1);
+        if (likely(values[0])) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+        case  1:
+        values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__jd2);
+        if (likely(values[1])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("jd_julian_epoch", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1330; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "jd_julian_epoch") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1330; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+    } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
+      goto __pyx_L5_argtuple_error;
+    } else {
+      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+    }
+    __pyx_v_jd1 = ((PyArrayObject *)values[0]);
+    __pyx_v_jd2 = ((PyArrayObject *)values[1]);
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("jd_julian_epoch", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1330; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("astropy.time.sofa_time.jd_julian_epoch", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_bstruct_epd.buf = NULL;
+  __pyx_bstruct_jd1.buf = NULL;
+  __pyx_bstruct_jd2.buf = NULL;
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_jd1), __pyx_ptype_5numpy_ndarray, 1, "jd1", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1330; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_jd2), __pyx_ptype_5numpy_ndarray, 1, "jd2", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1331; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_jd1, (PyObject*)__pyx_v_jd1, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1330; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_jd1 = __pyx_bstruct_jd1.strides[0];
+  __pyx_bshape_0_jd1 = __pyx_bstruct_jd1.shape[0];
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_jd2, (PyObject*)__pyx_v_jd2, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1330; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_jd2 = __pyx_bstruct_jd2.strides[0];
+  __pyx_bshape_0_jd2 = __pyx_bstruct_jd2.shape[0];
+
+  /* "astropy/time/sofa_time.pyx":1349
+ *     **     (J2000.0).
+ *     """
+ *     assert jd1.shape[0] == jd2.shape[0]             # <<<<<<<<<<<<<<
+ *     cdef unsigned n = jd1.shape[0]
+ *     cdef unsigned int i
+ */
+  #ifndef CYTHON_WITHOUT_ASSERTIONS
+  if (unlikely(!((__pyx_v_jd1->dimensions[0]) == (__pyx_v_jd2->dimensions[0])))) {
+    PyErr_SetNone(PyExc_AssertionError);
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1349; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  #endif
+
+  /* "astropy/time/sofa_time.pyx":1350
+ *     """
+ *     assert jd1.shape[0] == jd2.shape[0]
+ *     cdef unsigned n = jd1.shape[0]             # <<<<<<<<<<<<<<
+ *     cdef unsigned int i
+ *     cdef np.ndarray[double, ndim=1] epd = np.empty(n, dtype=np.double)
+ */
+  __pyx_v_n = (__pyx_v_jd1->dimensions[0]);
+
+  /* "astropy/time/sofa_time.pyx":1352
+ *     cdef unsigned n = jd1.shape[0]
+ *     cdef unsigned int i
+ *     cdef np.ndarray[double, ndim=1] epd = np.empty(n, dtype=np.double)             # <<<<<<<<<<<<<<
+ * 
+ *     for i in range(n):
+ */
+  __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1352; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_2 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s__empty); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1352; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __pyx_t_1 = PyLong_FromUnsignedLong(__pyx_v_n); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1352; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1352; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_3));
+  PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_1);
+  __Pyx_GIVEREF(__pyx_t_1);
+  __pyx_t_1 = 0;
+  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1352; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_1));
+  __pyx_t_4 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1352; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_4);
+  __pyx_t_5 = PyObject_GetAttr(__pyx_t_4, __pyx_n_s__double); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1352; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_n_s__dtype), __pyx_t_5) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1352; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  __pyx_t_5 = PyEval_CallObjectWithKeywords(__pyx_t_2, ((PyObject *)__pyx_t_3), ((PyObject *)__pyx_t_1)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1352; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
+  if (!(likely(((__pyx_t_5) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_5, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1352; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_6 = ((PyArrayObject *)__pyx_t_5);
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_epd, (PyObject*)__pyx_t_6, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 1, 0, __pyx_stack) == -1)) {
+      __pyx_v_epd = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_epd.buf = NULL;
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1352; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    } else {__pyx_bstride_0_epd = __pyx_bstruct_epd.strides[0];
+      __pyx_bshape_0_epd = __pyx_bstruct_epd.shape[0];
+    }
+  }
+  __pyx_t_6 = 0;
+  __pyx_v_epd = ((PyArrayObject *)__pyx_t_5);
+  __pyx_t_5 = 0;
+
+  /* "astropy/time/sofa_time.pyx":1354
+ *     cdef np.ndarray[double, ndim=1] epd = np.empty(n, dtype=np.double)
+ * 
+ *     for i in range(n):             # <<<<<<<<<<<<<<
+ *         epd[i] = iauEpj(jd1[i], jd2[i])
+ *     return epd
+ */
+  __pyx_t_7 = __pyx_v_n;
+  for (__pyx_t_8 = 0; __pyx_t_8 < __pyx_t_7; __pyx_t_8+=1) {
+    __pyx_v_i = __pyx_t_8;
+
+    /* "astropy/time/sofa_time.pyx":1355
+ * 
+ *     for i in range(n):
+ *         epd[i] = iauEpj(jd1[i], jd2[i])             # <<<<<<<<<<<<<<
+ *     return epd
+ * 
+ */
+    __pyx_t_9 = __pyx_v_i;
+    __pyx_t_10 = __pyx_v_i;
+    __pyx_t_11 = __pyx_v_i;
+    *__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_epd.buf, __pyx_t_11, __pyx_bstride_0_epd) = iauEpj((*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_jd1.buf, __pyx_t_9, __pyx_bstride_0_jd1)), (*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_jd2.buf, __pyx_t_10, __pyx_bstride_0_jd2)));
+  }
+
+  /* "astropy/time/sofa_time.pyx":1356
+ *     for i in range(n):
+ *         epd[i] = iauEpj(jd1[i], jd2[i])
+ *     return epd             # <<<<<<<<<<<<<<
+ * 
+ * 
+ */
+  __Pyx_XDECREF(__pyx_r);
+  __Pyx_INCREF(((PyObject *)__pyx_v_epd));
+  __pyx_r = ((PyObject *)__pyx_v_epd);
+  goto __pyx_L0;
+
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_XDECREF(__pyx_t_5);
+  { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;
+    __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_epd);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_jd1);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_jd2);
+  __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
+  __Pyx_AddTraceback("astropy.time.sofa_time.jd_julian_epoch", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  goto __pyx_L2;
+  __pyx_L0:;
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_epd);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_jd1);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_jd2);
+  __pyx_L2:;
+  __Pyx_XDECREF((PyObject *)__pyx_v_epd);
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "astropy/time/sofa_time.pyx":1361
+ * @cython.wraparound(False)
+ * @cython.boundscheck(False)
+ * def julian_epoch_jd(np.ndarray[double, ndim=1] epd):             # <<<<<<<<<<<<<<
+ *     """ Wrap void iauEpj2jd(double epj, double *djm0, double *djm)
+ *     **  Julian Epoch to Julian Date.
+ */
+
+static PyObject *__pyx_pf_7astropy_4time_9sofa_time_25julian_epoch_jd(PyObject *__pyx_self, PyObject *__pyx_v_epd); /*proto*/
+static char __pyx_doc_7astropy_4time_9sofa_time_25julian_epoch_jd[] = " Wrap void iauEpj2jd(double epj, double *djm0, double *djm)\n    **  Julian Epoch to Julian Date.\n    **  Given:\n    **     epj      double    Julian Epoch (e.g. 1996.8D0)\n    **\n    **  Returned:\n    **     djm0     double    MJD zero-point: always 2400000.5\n    **     djm      double    Modified Julian Date\n    ";
+static PyMethodDef __pyx_mdef_7astropy_4time_9sofa_time_25julian_epoch_jd = {__Pyx_NAMESTR("julian_epoch_jd"), (PyCFunction)__pyx_pf_7astropy_4time_9sofa_time_25julian_epoch_jd, METH_O, __Pyx_DOCSTR(__pyx_doc_7astropy_4time_9sofa_time_25julian_epoch_jd)};
+static PyObject *__pyx_pf_7astropy_4time_9sofa_time_25julian_epoch_jd(PyObject *__pyx_self, PyObject *__pyx_v_epd) {
+  unsigned int __pyx_v_n;
+  unsigned int __pyx_v_i;
+  PyArrayObject *__pyx_v_jd1 = 0;
+  PyArrayObject *__pyx_v_jd2 = 0;
+  Py_buffer __pyx_bstruct_epd;
+  Py_ssize_t __pyx_bstride_0_epd = 0;
+  Py_ssize_t __pyx_bshape_0_epd = 0;
+  Py_buffer __pyx_bstruct_jd2;
+  Py_ssize_t __pyx_bstride_0_jd2 = 0;
+  Py_ssize_t __pyx_bshape_0_jd2 = 0;
+  Py_buffer __pyx_bstruct_jd1;
+  Py_ssize_t __pyx_bstride_0_jd1 = 0;
+  Py_ssize_t __pyx_bshape_0_jd1 = 0;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
+  PyObject *__pyx_t_5 = NULL;
+  PyArrayObject *__pyx_t_6 = NULL;
+  PyArrayObject *__pyx_t_7 = NULL;
+  unsigned int __pyx_t_8;
+  unsigned int __pyx_t_9;
+  unsigned int __pyx_t_10;
+  unsigned int __pyx_t_11;
+  unsigned int __pyx_t_12;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("julian_epoch_jd");
+  __pyx_self = __pyx_self;
+  __pyx_bstruct_jd1.buf = NULL;
+  __pyx_bstruct_jd2.buf = NULL;
+  __pyx_bstruct_epd.buf = NULL;
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_epd), __pyx_ptype_5numpy_ndarray, 1, "epd", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1361; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_epd, (PyObject*)__pyx_v_epd, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1361; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_epd = __pyx_bstruct_epd.strides[0];
+  __pyx_bshape_0_epd = __pyx_bstruct_epd.shape[0];
+
+  /* "astropy/time/sofa_time.pyx":1371
+ *     **     djm      double    Modified Julian Date
+ *     """
+ *     cdef unsigned n = epd.shape[0]             # <<<<<<<<<<<<<<
+ *     cdef unsigned int i
+ *     cdef np.ndarray[double, ndim=1] jd1 = np.empty(n, dtype=np.double)
+ */
+  __pyx_v_n = (((PyArrayObject *)__pyx_v_epd)->dimensions[0]);
+
+  /* "astropy/time/sofa_time.pyx":1373
+ *     cdef unsigned n = epd.shape[0]
+ *     cdef unsigned int i
+ *     cdef np.ndarray[double, ndim=1] jd1 = np.empty(n, dtype=np.double)             # <<<<<<<<<<<<<<
+ *     cdef np.ndarray[double, ndim=1] jd2 = np.empty(n, dtype=np.double)
+ * 
+ */
+  __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1373; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_2 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s__empty); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1373; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __pyx_t_1 = PyLong_FromUnsignedLong(__pyx_v_n); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1373; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1373; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_3));
+  PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_1);
+  __Pyx_GIVEREF(__pyx_t_1);
+  __pyx_t_1 = 0;
+  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1373; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_1));
+  __pyx_t_4 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1373; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_4);
+  __pyx_t_5 = PyObject_GetAttr(__pyx_t_4, __pyx_n_s__double); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1373; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_n_s__dtype), __pyx_t_5) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1373; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  __pyx_t_5 = PyEval_CallObjectWithKeywords(__pyx_t_2, ((PyObject *)__pyx_t_3), ((PyObject *)__pyx_t_1)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1373; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
+  if (!(likely(((__pyx_t_5) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_5, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1373; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_6 = ((PyArrayObject *)__pyx_t_5);
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_jd1, (PyObject*)__pyx_t_6, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {
+      __pyx_v_jd1 = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_jd1.buf = NULL;
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1373; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    } else {__pyx_bstride_0_jd1 = __pyx_bstruct_jd1.strides[0];
+      __pyx_bshape_0_jd1 = __pyx_bstruct_jd1.shape[0];
+    }
+  }
+  __pyx_t_6 = 0;
+  __pyx_v_jd1 = ((PyArrayObject *)__pyx_t_5);
+  __pyx_t_5 = 0;
+
+  /* "astropy/time/sofa_time.pyx":1374
+ *     cdef unsigned int i
+ *     cdef np.ndarray[double, ndim=1] jd1 = np.empty(n, dtype=np.double)
+ *     cdef np.ndarray[double, ndim=1] jd2 = np.empty(n, dtype=np.double)             # <<<<<<<<<<<<<<
+ * 
+ *     for i in range(n):
+ */
+  __pyx_t_5 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1374; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __pyx_t_1 = PyObject_GetAttr(__pyx_t_5, __pyx_n_s__empty); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1374; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  __pyx_t_5 = PyLong_FromUnsignedLong(__pyx_v_n); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1374; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1374; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_3));
+  PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_5);
+  __Pyx_GIVEREF(__pyx_t_5);
+  __pyx_t_5 = 0;
+  __pyx_t_5 = PyDict_New(); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1374; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_5));
+  __pyx_t_2 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1374; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_4 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s__double); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1374; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_4);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  if (PyDict_SetItem(__pyx_t_5, ((PyObject *)__pyx_n_s__dtype), __pyx_t_4) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1374; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  __pyx_t_4 = PyEval_CallObjectWithKeywords(__pyx_t_1, ((PyObject *)__pyx_t_3), ((PyObject *)__pyx_t_5)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1374; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_4);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_5)); __pyx_t_5 = 0;
+  if (!(likely(((__pyx_t_4) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_4, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1374; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_7 = ((PyArrayObject *)__pyx_t_4);
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_jd2, (PyObject*)__pyx_t_7, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {
+      __pyx_v_jd2 = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_jd2.buf = NULL;
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1374; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    } else {__pyx_bstride_0_jd2 = __pyx_bstruct_jd2.strides[0];
+      __pyx_bshape_0_jd2 = __pyx_bstruct_jd2.shape[0];
+    }
+  }
+  __pyx_t_7 = 0;
+  __pyx_v_jd2 = ((PyArrayObject *)__pyx_t_4);
+  __pyx_t_4 = 0;
+
+  /* "astropy/time/sofa_time.pyx":1376
+ *     cdef np.ndarray[double, ndim=1] jd2 = np.empty(n, dtype=np.double)
+ * 
+ *     for i in range(n):             # <<<<<<<<<<<<<<
+ *         iauEpj2jd(epd[i], &jd1[i], &jd2[i])
+ *     return jd1, jd2
+ */
+  __pyx_t_8 = __pyx_v_n;
+  for (__pyx_t_9 = 0; __pyx_t_9 < __pyx_t_8; __pyx_t_9+=1) {
+    __pyx_v_i = __pyx_t_9;
+
+    /* "astropy/time/sofa_time.pyx":1377
+ * 
+ *     for i in range(n):
+ *         iauEpj2jd(epd[i], &jd1[i], &jd2[i])             # <<<<<<<<<<<<<<
+ *     return jd1, jd2
+ * 
+ */
+    __pyx_t_10 = __pyx_v_i;
+    __pyx_t_11 = __pyx_v_i;
+    __pyx_t_12 = __pyx_v_i;
+    iauEpj2jd((*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_epd.buf, __pyx_t_10, __pyx_bstride_0_epd)), (&(*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_jd1.buf, __pyx_t_11, __pyx_bstride_0_jd1))), (&(*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_jd2.buf, __pyx_t_12, __pyx_bstride_0_jd2))));
+  }
+
+  /* "astropy/time/sofa_time.pyx":1378
+ *     for i in range(n):
+ *         iauEpj2jd(epd[i], &jd1[i], &jd2[i])
+ *     return jd1, jd2             # <<<<<<<<<<<<<<
+ * 
+ * 
+ */
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1378; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_4));
+  __Pyx_INCREF(((PyObject *)__pyx_v_jd1));
+  PyTuple_SET_ITEM(__pyx_t_4, 0, ((PyObject *)__pyx_v_jd1));
+  __Pyx_GIVEREF(((PyObject *)__pyx_v_jd1));
+  __Pyx_INCREF(((PyObject *)__pyx_v_jd2));
+  PyTuple_SET_ITEM(__pyx_t_4, 1, ((PyObject *)__pyx_v_jd2));
+  __Pyx_GIVEREF(((PyObject *)__pyx_v_jd2));
+  __pyx_r = ((PyObject *)__pyx_t_4);
+  __pyx_t_4 = 0;
+  goto __pyx_L0;
+
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_XDECREF(__pyx_t_5);
+  { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;
+    __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_epd);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_jd2);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_jd1);
+  __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
+  __Pyx_AddTraceback("astropy.time.sofa_time.julian_epoch_jd", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  goto __pyx_L2;
+  __pyx_L0:;
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_epd);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_jd2);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_jd1);
+  __pyx_L2:;
+  __Pyx_XDECREF((PyObject *)__pyx_v_jd1);
+  __Pyx_XDECREF((PyObject *)__pyx_v_jd2);
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "astropy/time/sofa_time.pyx":1383
+ * @cython.wraparound(False)
+ * @cython.boundscheck(False)
+ * def jd_besselian_epoch(np.ndarray[double, ndim=1] jd1,             # <<<<<<<<<<<<<<
+ *                        np.ndarray[double, ndim=1] jd2):
+ *     """ Wrap double iauEpb(double dj1, double dj2)
+ */
+
+static PyObject *__pyx_pf_7astropy_4time_9sofa_time_26jd_besselian_epoch(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_7astropy_4time_9sofa_time_26jd_besselian_epoch[] = " Wrap double iauEpb(double dj1, double dj2)\n    **  Julian Date to Besselian Epoch.\n\n    **  Given:\n    **     dj1,dj2    double     Julian Date (see note)\n    **\n    **  Returned (function value):\n    **                double     Besselian Epoch.\n    **\n    **  Note:\n    **\n    **     The Julian Date is supplied in two pieces, in the usual SOFA\n    **     manner, which is designed to preserve time resolution.  The\n    **     Julian Date is available as a single number by adding dj1 and\n    **     dj2.  The maximum resolution is achieved if dj1 is 2451545D0\n    **     (J2000.0).\n    ";
+static PyMethodDef __pyx_mdef_7astropy_4time_9sofa_time_26jd_besselian_epoch = {__Pyx_NAMESTR("jd_besselian_epoch"), (PyCFunction)__pyx_pf_7astropy_4time_9sofa_time_26jd_besselian_epoch, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(__pyx_doc_7astropy_4time_9sofa_time_26jd_besselian_epoch)};
+static PyObject *__pyx_pf_7astropy_4time_9sofa_time_26jd_besselian_epoch(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyArrayObject *__pyx_v_jd1 = 0;
+  PyArrayObject *__pyx_v_jd2 = 0;
+  unsigned int __pyx_v_n;
+  unsigned int __pyx_v_i;
+  PyArrayObject *__pyx_v_epd = 0;
+  Py_buffer __pyx_bstruct_epd;
+  Py_ssize_t __pyx_bstride_0_epd = 0;
+  Py_ssize_t __pyx_bshape_0_epd = 0;
+  Py_buffer __pyx_bstruct_jd1;
+  Py_ssize_t __pyx_bstride_0_jd1 = 0;
+  Py_ssize_t __pyx_bshape_0_jd1 = 0;
+  Py_buffer __pyx_bstruct_jd2;
+  Py_ssize_t __pyx_bstride_0_jd2 = 0;
+  Py_ssize_t __pyx_bshape_0_jd2 = 0;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
+  PyObject *__pyx_t_5 = NULL;
+  PyArrayObject *__pyx_t_6 = NULL;
+  unsigned int __pyx_t_7;
+  unsigned int __pyx_t_8;
+  unsigned int __pyx_t_9;
+  unsigned int __pyx_t_10;
+  unsigned int __pyx_t_11;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__jd1,&__pyx_n_s__jd2,0};
+  __Pyx_RefNannySetupContext("jd_besselian_epoch");
+  __pyx_self = __pyx_self;
+  {
+    PyObject* values[2] = {0,0};
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  0:
+        values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__jd1);
+        if (likely(values[0])) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+        case  1:
+        values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__jd2);
+        if (likely(values[1])) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("jd_besselian_epoch", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1383; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "jd_besselian_epoch") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1383; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+    } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
+      goto __pyx_L5_argtuple_error;
+    } else {
+      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+    }
+    __pyx_v_jd1 = ((PyArrayObject *)values[0]);
+    __pyx_v_jd2 = ((PyArrayObject *)values[1]);
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("jd_besselian_epoch", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1383; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("astropy.time.sofa_time.jd_besselian_epoch", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_bstruct_epd.buf = NULL;
+  __pyx_bstruct_jd1.buf = NULL;
+  __pyx_bstruct_jd2.buf = NULL;
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_jd1), __pyx_ptype_5numpy_ndarray, 1, "jd1", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1383; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_jd2), __pyx_ptype_5numpy_ndarray, 1, "jd2", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1384; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_jd1, (PyObject*)__pyx_v_jd1, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1383; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_jd1 = __pyx_bstruct_jd1.strides[0];
+  __pyx_bshape_0_jd1 = __pyx_bstruct_jd1.shape[0];
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_jd2, (PyObject*)__pyx_v_jd2, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1383; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_jd2 = __pyx_bstruct_jd2.strides[0];
+  __pyx_bshape_0_jd2 = __pyx_bstruct_jd2.shape[0];
+
+  /* "astropy/time/sofa_time.pyx":1402
+ *     **     (J2000.0).
+ *     """
+ *     assert jd1.shape[0] == jd2.shape[0]             # <<<<<<<<<<<<<<
+ *     cdef unsigned n = jd1.shape[0]
+ *     cdef unsigned int i
+ */
+  #ifndef CYTHON_WITHOUT_ASSERTIONS
+  if (unlikely(!((__pyx_v_jd1->dimensions[0]) == (__pyx_v_jd2->dimensions[0])))) {
+    PyErr_SetNone(PyExc_AssertionError);
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1402; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  #endif
+
+  /* "astropy/time/sofa_time.pyx":1403
+ *     """
+ *     assert jd1.shape[0] == jd2.shape[0]
+ *     cdef unsigned n = jd1.shape[0]             # <<<<<<<<<<<<<<
+ *     cdef unsigned int i
+ *     cdef np.ndarray[double, ndim=1] epd = np.empty(n, dtype=np.double)
+ */
+  __pyx_v_n = (__pyx_v_jd1->dimensions[0]);
+
+  /* "astropy/time/sofa_time.pyx":1405
+ *     cdef unsigned n = jd1.shape[0]
+ *     cdef unsigned int i
+ *     cdef np.ndarray[double, ndim=1] epd = np.empty(n, dtype=np.double)             # <<<<<<<<<<<<<<
+ * 
+ *     for i in range(n):
+ */
+  __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1405; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_2 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s__empty); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1405; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __pyx_t_1 = PyLong_FromUnsignedLong(__pyx_v_n); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1405; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1405; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_3));
+  PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_1);
+  __Pyx_GIVEREF(__pyx_t_1);
+  __pyx_t_1 = 0;
+  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1405; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_1));
+  __pyx_t_4 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1405; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_4);
+  __pyx_t_5 = PyObject_GetAttr(__pyx_t_4, __pyx_n_s__double); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1405; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_n_s__dtype), __pyx_t_5) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1405; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  __pyx_t_5 = PyEval_CallObjectWithKeywords(__pyx_t_2, ((PyObject *)__pyx_t_3), ((PyObject *)__pyx_t_1)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1405; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
+  if (!(likely(((__pyx_t_5) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_5, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1405; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_6 = ((PyArrayObject *)__pyx_t_5);
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_epd, (PyObject*)__pyx_t_6, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 1, 0, __pyx_stack) == -1)) {
+      __pyx_v_epd = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_epd.buf = NULL;
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1405; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    } else {__pyx_bstride_0_epd = __pyx_bstruct_epd.strides[0];
+      __pyx_bshape_0_epd = __pyx_bstruct_epd.shape[0];
+    }
+  }
+  __pyx_t_6 = 0;
+  __pyx_v_epd = ((PyArrayObject *)__pyx_t_5);
+  __pyx_t_5 = 0;
+
+  /* "astropy/time/sofa_time.pyx":1407
+ *     cdef np.ndarray[double, ndim=1] epd = np.empty(n, dtype=np.double)
+ * 
+ *     for i in range(n):             # <<<<<<<<<<<<<<
+ *         epd[i] = iauEpb(jd1[i], jd2[i])
+ *     return epd
+ */
+  __pyx_t_7 = __pyx_v_n;
+  for (__pyx_t_8 = 0; __pyx_t_8 < __pyx_t_7; __pyx_t_8+=1) {
+    __pyx_v_i = __pyx_t_8;
+
+    /* "astropy/time/sofa_time.pyx":1408
+ * 
+ *     for i in range(n):
+ *         epd[i] = iauEpb(jd1[i], jd2[i])             # <<<<<<<<<<<<<<
+ *     return epd
+ * 
+ */
+    __pyx_t_9 = __pyx_v_i;
+    __pyx_t_10 = __pyx_v_i;
+    __pyx_t_11 = __pyx_v_i;
+    *__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_epd.buf, __pyx_t_11, __pyx_bstride_0_epd) = iauEpb((*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_jd1.buf, __pyx_t_9, __pyx_bstride_0_jd1)), (*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_jd2.buf, __pyx_t_10, __pyx_bstride_0_jd2)));
+  }
+
+  /* "astropy/time/sofa_time.pyx":1409
+ *     for i in range(n):
+ *         epd[i] = iauEpb(jd1[i], jd2[i])
+ *     return epd             # <<<<<<<<<<<<<<
+ * 
+ * 
+ */
+  __Pyx_XDECREF(__pyx_r);
+  __Pyx_INCREF(((PyObject *)__pyx_v_epd));
+  __pyx_r = ((PyObject *)__pyx_v_epd);
+  goto __pyx_L0;
+
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_XDECREF(__pyx_t_5);
+  { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;
+    __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_epd);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_jd1);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_jd2);
+  __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
+  __Pyx_AddTraceback("astropy.time.sofa_time.jd_besselian_epoch", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  goto __pyx_L2;
+  __pyx_L0:;
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_epd);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_jd1);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_jd2);
+  __pyx_L2:;
+  __Pyx_XDECREF((PyObject *)__pyx_v_epd);
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "astropy/time/sofa_time.pyx":1414
+ * @cython.wraparound(False)
+ * @cython.boundscheck(False)
+ * def besselian_epoch_jd(np.ndarray[double, ndim=1] epd):             # <<<<<<<<<<<<<<
+ *     """ Wrap void iauEpb2jd(double epj, double *djm0, double *djm)
+ *     **  Besselian Epoch to Julian Date.
+ */
+
+static PyObject *__pyx_pf_7astropy_4time_9sofa_time_27besselian_epoch_jd(PyObject *__pyx_self, PyObject *__pyx_v_epd); /*proto*/
+static char __pyx_doc_7astropy_4time_9sofa_time_27besselian_epoch_jd[] = " Wrap void iauEpb2jd(double epj, double *djm0, double *djm)\n    **  Besselian Epoch to Julian Date.\n\n    **  Given:\n    **     epb      double    Besselian Epoch (e.g. 1957.3D0)\n    **\n    **  Returned:\n    **     djm0     double    MJD zero-point: always 2400000.5\n    **     djm      double    Modified Julian Date\n    **\n    **  Note:\n    **\n    **     The Julian Date is returned in two pieces, in the usual SOFA\n    **     manner, which is designed to preserve time resolution.  The\n    **     Julian Date is available as a single number by adding djm0 and\n    **     djm.\n    ";
+static PyMethodDef __pyx_mdef_7astropy_4time_9sofa_time_27besselian_epoch_jd = {__Pyx_NAMESTR("besselian_epoch_jd"), (PyCFunction)__pyx_pf_7astropy_4time_9sofa_time_27besselian_epoch_jd, METH_O, __Pyx_DOCSTR(__pyx_doc_7astropy_4time_9sofa_time_27besselian_epoch_jd)};
+static PyObject *__pyx_pf_7astropy_4time_9sofa_time_27besselian_epoch_jd(PyObject *__pyx_self, PyObject *__pyx_v_epd) {
+  unsigned int __pyx_v_n;
+  unsigned int __pyx_v_i;
+  PyArrayObject *__pyx_v_jd1 = 0;
+  PyArrayObject *__pyx_v_jd2 = 0;
+  Py_buffer __pyx_bstruct_epd;
+  Py_ssize_t __pyx_bstride_0_epd = 0;
+  Py_ssize_t __pyx_bshape_0_epd = 0;
+  Py_buffer __pyx_bstruct_jd2;
+  Py_ssize_t __pyx_bstride_0_jd2 = 0;
+  Py_ssize_t __pyx_bshape_0_jd2 = 0;
+  Py_buffer __pyx_bstruct_jd1;
+  Py_ssize_t __pyx_bstride_0_jd1 = 0;
+  Py_ssize_t __pyx_bshape_0_jd1 = 0;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
+  PyObject *__pyx_t_5 = NULL;
+  PyArrayObject *__pyx_t_6 = NULL;
+  PyArrayObject *__pyx_t_7 = NULL;
+  unsigned int __pyx_t_8;
+  unsigned int __pyx_t_9;
+  unsigned int __pyx_t_10;
+  unsigned int __pyx_t_11;
+  unsigned int __pyx_t_12;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("besselian_epoch_jd");
+  __pyx_self = __pyx_self;
+  __pyx_bstruct_jd1.buf = NULL;
+  __pyx_bstruct_jd2.buf = NULL;
+  __pyx_bstruct_epd.buf = NULL;
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_epd), __pyx_ptype_5numpy_ndarray, 1, "epd", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1414; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_epd, (PyObject*)__pyx_v_epd, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1414; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_bstride_0_epd = __pyx_bstruct_epd.strides[0];
+  __pyx_bshape_0_epd = __pyx_bstruct_epd.shape[0];
+
+  /* "astropy/time/sofa_time.pyx":1432
+ *     **     djm.
+ *     """
+ *     cdef unsigned n = epd.shape[0]             # <<<<<<<<<<<<<<
+ *     cdef unsigned int i
+ *     cdef np.ndarray[double, ndim=1] jd1 = np.empty(n, dtype=np.double)
+ */
+  __pyx_v_n = (((PyArrayObject *)__pyx_v_epd)->dimensions[0]);
+
+  /* "astropy/time/sofa_time.pyx":1434
+ *     cdef unsigned n = epd.shape[0]
+ *     cdef unsigned int i
+ *     cdef np.ndarray[double, ndim=1] jd1 = np.empty(n, dtype=np.double)             # <<<<<<<<<<<<<<
+ *     cdef np.ndarray[double, ndim=1] jd2 = np.empty(n, dtype=np.double)
+ * 
+ */
+  __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1434; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_2 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s__empty); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1434; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __pyx_t_1 = PyLong_FromUnsignedLong(__pyx_v_n); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1434; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1434; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_3));
+  PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_1);
+  __Pyx_GIVEREF(__pyx_t_1);
+  __pyx_t_1 = 0;
+  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1434; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_1));
+  __pyx_t_4 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1434; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_4);
+  __pyx_t_5 = PyObject_GetAttr(__pyx_t_4, __pyx_n_s__double); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1434; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_n_s__dtype), __pyx_t_5) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1434; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  __pyx_t_5 = PyEval_CallObjectWithKeywords(__pyx_t_2, ((PyObject *)__pyx_t_3), ((PyObject *)__pyx_t_1)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1434; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
+  if (!(likely(((__pyx_t_5) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_5, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1434; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_6 = ((PyArrayObject *)__pyx_t_5);
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_jd1, (PyObject*)__pyx_t_6, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {
+      __pyx_v_jd1 = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_jd1.buf = NULL;
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1434; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    } else {__pyx_bstride_0_jd1 = __pyx_bstruct_jd1.strides[0];
+      __pyx_bshape_0_jd1 = __pyx_bstruct_jd1.shape[0];
+    }
+  }
+  __pyx_t_6 = 0;
+  __pyx_v_jd1 = ((PyArrayObject *)__pyx_t_5);
+  __pyx_t_5 = 0;
+
+  /* "astropy/time/sofa_time.pyx":1435
+ *     cdef unsigned int i
+ *     cdef np.ndarray[double, ndim=1] jd1 = np.empty(n, dtype=np.double)
+ *     cdef np.ndarray[double, ndim=1] jd2 = np.empty(n, dtype=np.double)             # <<<<<<<<<<<<<<
+ * 
+ *     for i in range(n):
+ */
+  __pyx_t_5 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1435; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __pyx_t_1 = PyObject_GetAttr(__pyx_t_5, __pyx_n_s__empty); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1435; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  __pyx_t_5 = PyLong_FromUnsignedLong(__pyx_v_n); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1435; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1435; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_3));
+  PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_5);
+  __Pyx_GIVEREF(__pyx_t_5);
+  __pyx_t_5 = 0;
+  __pyx_t_5 = PyDict_New(); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1435; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_5));
+  __pyx_t_2 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1435; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_4 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s__double); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1435; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_4);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  if (PyDict_SetItem(__pyx_t_5, ((PyObject *)__pyx_n_s__dtype), __pyx_t_4) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1435; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  __pyx_t_4 = PyEval_CallObjectWithKeywords(__pyx_t_1, ((PyObject *)__pyx_t_3), ((PyObject *)__pyx_t_5)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1435; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_4);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_5)); __pyx_t_5 = 0;
+  if (!(likely(((__pyx_t_4) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_4, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1435; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_7 = ((PyArrayObject *)__pyx_t_4);
+  {
+    __Pyx_BufFmt_StackElem __pyx_stack[1];
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_jd2, (PyObject*)__pyx_t_7, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {
+      __pyx_v_jd2 = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_jd2.buf = NULL;
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1435; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    } else {__pyx_bstride_0_jd2 = __pyx_bstruct_jd2.strides[0];
+      __pyx_bshape_0_jd2 = __pyx_bstruct_jd2.shape[0];
+    }
+  }
+  __pyx_t_7 = 0;
+  __pyx_v_jd2 = ((PyArrayObject *)__pyx_t_4);
+  __pyx_t_4 = 0;
+
+  /* "astropy/time/sofa_time.pyx":1437
+ *     cdef np.ndarray[double, ndim=1] jd2 = np.empty(n, dtype=np.double)
+ * 
+ *     for i in range(n):             # <<<<<<<<<<<<<<
+ *         iauEpb2jd(epd[i], &jd1[i], &jd2[i])
+ *     return jd1, jd2
+ */
+  __pyx_t_8 = __pyx_v_n;
+  for (__pyx_t_9 = 0; __pyx_t_9 < __pyx_t_8; __pyx_t_9+=1) {
+    __pyx_v_i = __pyx_t_9;
+
+    /* "astropy/time/sofa_time.pyx":1438
+ * 
+ *     for i in range(n):
+ *         iauEpb2jd(epd[i], &jd1[i], &jd2[i])             # <<<<<<<<<<<<<<
+ *     return jd1, jd2
+ */
+    __pyx_t_10 = __pyx_v_i;
+    __pyx_t_11 = __pyx_v_i;
+    __pyx_t_12 = __pyx_v_i;
+    iauEpb2jd((*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_epd.buf, __pyx_t_10, __pyx_bstride_0_epd)), (&(*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_jd1.buf, __pyx_t_11, __pyx_bstride_0_jd1))), (&(*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_jd2.buf, __pyx_t_12, __pyx_bstride_0_jd2))));
+  }
+
+  /* "astropy/time/sofa_time.pyx":1439
+ *     for i in range(n):
+ *         iauEpb2jd(epd[i], &jd1[i], &jd2[i])
+ *     return jd1, jd2             # <<<<<<<<<<<<<<
+ */
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1439; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_4));
+  __Pyx_INCREF(((PyObject *)__pyx_v_jd1));
+  PyTuple_SET_ITEM(__pyx_t_4, 0, ((PyObject *)__pyx_v_jd1));
+  __Pyx_GIVEREF(((PyObject *)__pyx_v_jd1));
+  __Pyx_INCREF(((PyObject *)__pyx_v_jd2));
+  PyTuple_SET_ITEM(__pyx_t_4, 1, ((PyObject *)__pyx_v_jd2));
+  __Pyx_GIVEREF(((PyObject *)__pyx_v_jd2));
+  __pyx_r = ((PyObject *)__pyx_t_4);
+  __pyx_t_4 = 0;
+  goto __pyx_L0;
+
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_XDECREF(__pyx_t_5);
+  { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;
+    __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_epd);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_jd2);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_jd1);
+  __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
+  __Pyx_AddTraceback("astropy.time.sofa_time.besselian_epoch_jd", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  goto __pyx_L2;
+  __pyx_L0:;
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_epd);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_jd2);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_jd1);
+  __pyx_L2:;
+  __Pyx_XDECREF((PyObject *)__pyx_v_jd1);
+  __Pyx_XDECREF((PyObject *)__pyx_v_jd2);
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "numpy.pxd":190
+ *         # experimental exception made for __getbuffer__ and __releasebuffer__
+ *         # -- the details of this may change.
+ *         def __getbuffer__(ndarray self, Py_buffer* info, int flags):             # <<<<<<<<<<<<<<
+ *             # This implementation of getbuffer is geared towards Cython
+ *             # requirements, and does not yet fullfill the PEP.
+ */
+
+static CYTHON_UNUSED int __pyx_pf_5numpy_7ndarray___getbuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags); /*proto*/
+static CYTHON_UNUSED int __pyx_pf_5numpy_7ndarray___getbuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags) {
+  int __pyx_v_copy_shape;
+  int __pyx_v_i;
+  int __pyx_v_ndim;
+  int __pyx_v_endian_detector;
+  int __pyx_v_little_endian;
+  int __pyx_v_t;
+  char *__pyx_v_f;
+  PyArray_Descr *__pyx_v_descr = 0;
+  int __pyx_v_offset;
+  int __pyx_v_hasfields;
+  int __pyx_r;
+  __Pyx_RefNannyDeclarations
+  int __pyx_t_1;
+  int __pyx_t_2;
+  int __pyx_t_3;
+  PyObject *__pyx_t_4 = NULL;
+  int __pyx_t_5;
+  int __pyx_t_6;
+  int __pyx_t_7;
+  PyObject *__pyx_t_8 = NULL;
+  char *__pyx_t_9;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("__getbuffer__");
+  if (__pyx_v_info != NULL) {
+    __pyx_v_info->obj = Py_None; __Pyx_INCREF(Py_None);
+    __Pyx_GIVEREF(__pyx_v_info->obj);
+  }
+
+  /* "numpy.pxd":196
+ *             # of flags
+ * 
+ *             if info == NULL: return             # <<<<<<<<<<<<<<
+ * 
+ *             cdef int copy_shape, i, ndim
+ */
+  __pyx_t_1 = (__pyx_v_info == NULL);
+  if (__pyx_t_1) {
+    __pyx_r = 0;
+    goto __pyx_L0;
+    goto __pyx_L5;
+  }
+  __pyx_L5:;
+
+  /* "numpy.pxd":199
+ * 
+ *             cdef int copy_shape, i, ndim
+ *             cdef int endian_detector = 1             # <<<<<<<<<<<<<<
+ *             cdef bint little_endian = ((<char*>&endian_detector)[0] != 0)
+ * 
+ */
+  __pyx_v_endian_detector = 1;
+
+  /* "numpy.pxd":200
+ *             cdef int copy_shape, i, ndim
+ *             cdef int endian_detector = 1
+ *             cdef bint little_endian = ((<char*>&endian_detector)[0] != 0)             # <<<<<<<<<<<<<<
+ * 
+ *             ndim = PyArray_NDIM(self)
+ */
+  __pyx_v_little_endian = ((((char *)(&__pyx_v_endian_detector))[0]) != 0);
+
+  /* "numpy.pxd":202
+ *             cdef bint little_endian = ((<char*>&endian_detector)[0] != 0)
+ * 
+ *             ndim = PyArray_NDIM(self)             # <<<<<<<<<<<<<<
+ * 
+ *             if sizeof(npy_intp) != sizeof(Py_ssize_t):
+ */
+  __pyx_v_ndim = PyArray_NDIM(((PyArrayObject *)__pyx_v_self));
+
+  /* "numpy.pxd":204
+ *             ndim = PyArray_NDIM(self)
+ * 
+ *             if sizeof(npy_intp) != sizeof(Py_ssize_t):             # <<<<<<<<<<<<<<
+ *                 copy_shape = 1
+ *             else:
+ */
+  __pyx_t_1 = ((sizeof(npy_intp)) != (sizeof(Py_ssize_t)));
+  if (__pyx_t_1) {
+
+    /* "numpy.pxd":205
+ * 
+ *             if sizeof(npy_intp) != sizeof(Py_ssize_t):
+ *                 copy_shape = 1             # <<<<<<<<<<<<<<
+ *             else:
+ *                 copy_shape = 0
+ */
+    __pyx_v_copy_shape = 1;
+    goto __pyx_L6;
+  }
+  /*else*/ {
+
+    /* "numpy.pxd":207
+ *                 copy_shape = 1
+ *             else:
+ *                 copy_shape = 0             # <<<<<<<<<<<<<<
+ * 
+ *             if ((flags & pybuf.PyBUF_C_CONTIGUOUS == pybuf.PyBUF_C_CONTIGUOUS)
+ */
+    __pyx_v_copy_shape = 0;
+  }
+  __pyx_L6:;
+
+  /* "numpy.pxd":209
+ *                 copy_shape = 0
+ * 
+ *             if ((flags & pybuf.PyBUF_C_CONTIGUOUS == pybuf.PyBUF_C_CONTIGUOUS)             # <<<<<<<<<<<<<<
+ *                 and not PyArray_CHKFLAGS(self, NPY_C_CONTIGUOUS)):
+ *                 raise ValueError(u"ndarray is not C contiguous")
+ */
+  __pyx_t_1 = ((__pyx_v_flags & PyBUF_C_CONTIGUOUS) == PyBUF_C_CONTIGUOUS);
+  if (__pyx_t_1) {
+
+    /* "numpy.pxd":210
+ * 
+ *             if ((flags & pybuf.PyBUF_C_CONTIGUOUS == pybuf.PyBUF_C_CONTIGUOUS)
+ *                 and not PyArray_CHKFLAGS(self, NPY_C_CONTIGUOUS)):             # <<<<<<<<<<<<<<
+ *                 raise ValueError(u"ndarray is not C contiguous")
+ * 
+ */
+    __pyx_t_2 = (!PyArray_CHKFLAGS(((PyArrayObject *)__pyx_v_self), NPY_C_CONTIGUOUS));
+    __pyx_t_3 = __pyx_t_2;
+  } else {
+    __pyx_t_3 = __pyx_t_1;
+  }
+  if (__pyx_t_3) {
+
+    /* "numpy.pxd":211
+ *             if ((flags & pybuf.PyBUF_C_CONTIGUOUS == pybuf.PyBUF_C_CONTIGUOUS)
+ *                 and not PyArray_CHKFLAGS(self, NPY_C_CONTIGUOUS)):
+ *                 raise ValueError(u"ndarray is not C contiguous")             # <<<<<<<<<<<<<<
+ * 
+ *             if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS)
+ */
+    __pyx_t_4 = PyObject_Call(__pyx_builtin_ValueError, ((PyObject *)__pyx_k_tuple_27), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 211; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_4);
+    __Pyx_Raise(__pyx_t_4, 0, 0, 0);
+    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+    {__pyx_filename = __pyx_f[1]; __pyx_lineno = 211; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    goto __pyx_L7;
+  }
+  __pyx_L7:;
+
+  /* "numpy.pxd":213
+ *                 raise ValueError(u"ndarray is not C contiguous")
+ * 
+ *             if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS)             # <<<<<<<<<<<<<<
+ *                 and not PyArray_CHKFLAGS(self, NPY_F_CONTIGUOUS)):
+ *                 raise ValueError(u"ndarray is not Fortran contiguous")
+ */
+  __pyx_t_3 = ((__pyx_v_flags & PyBUF_F_CONTIGUOUS) == PyBUF_F_CONTIGUOUS);
+  if (__pyx_t_3) {
+
+    /* "numpy.pxd":214
+ * 
+ *             if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS)
+ *                 and not PyArray_CHKFLAGS(self, NPY_F_CONTIGUOUS)):             # <<<<<<<<<<<<<<
+ *                 raise ValueError(u"ndarray is not Fortran contiguous")
+ * 
+ */
+    __pyx_t_1 = (!PyArray_CHKFLAGS(((PyArrayObject *)__pyx_v_self), NPY_F_CONTIGUOUS));
+    __pyx_t_2 = __pyx_t_1;
+  } else {
+    __pyx_t_2 = __pyx_t_3;
+  }
+  if (__pyx_t_2) {
+
+    /* "numpy.pxd":215
+ *             if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS)
+ *                 and not PyArray_CHKFLAGS(self, NPY_F_CONTIGUOUS)):
+ *                 raise ValueError(u"ndarray is not Fortran contiguous")             # <<<<<<<<<<<<<<
+ * 
+ *             info.buf = PyArray_DATA(self)
+ */
+    __pyx_t_4 = PyObject_Call(__pyx_builtin_ValueError, ((PyObject *)__pyx_k_tuple_29), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 215; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_4);
+    __Pyx_Raise(__pyx_t_4, 0, 0, 0);
+    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+    {__pyx_filename = __pyx_f[1]; __pyx_lineno = 215; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    goto __pyx_L8;
+  }
+  __pyx_L8:;
+
+  /* "numpy.pxd":217
+ *                 raise ValueError(u"ndarray is not Fortran contiguous")
+ * 
+ *             info.buf = PyArray_DATA(self)             # <<<<<<<<<<<<<<
+ *             info.ndim = ndim
+ *             if copy_shape:
+ */
+  __pyx_v_info->buf = PyArray_DATA(((PyArrayObject *)__pyx_v_self));
+
+  /* "numpy.pxd":218
+ * 
+ *             info.buf = PyArray_DATA(self)
+ *             info.ndim = ndim             # <<<<<<<<<<<<<<
+ *             if copy_shape:
+ *                 # Allocate new buffer for strides and shape info.
+ */
+  __pyx_v_info->ndim = __pyx_v_ndim;
+
+  /* "numpy.pxd":219
+ *             info.buf = PyArray_DATA(self)
+ *             info.ndim = ndim
+ *             if copy_shape:             # <<<<<<<<<<<<<<
+ *                 # Allocate new buffer for strides and shape info.
+ *                 # This is allocated as one block, strides first.
+ */
+  if (__pyx_v_copy_shape) {
+
+    /* "numpy.pxd":222
+ *                 # Allocate new buffer for strides and shape info.
+ *                 # This is allocated as one block, strides first.
+ *                 info.strides = <Py_ssize_t*>stdlib.malloc(sizeof(Py_ssize_t) * <size_t>ndim * 2)             # <<<<<<<<<<<<<<
+ *                 info.shape = info.strides + ndim
+ *                 for i in range(ndim):
+ */
+    __pyx_v_info->strides = ((Py_ssize_t *)malloc((((sizeof(Py_ssize_t)) * ((size_t)__pyx_v_ndim)) * 2)));
+
+    /* "numpy.pxd":223
+ *                 # This is allocated as one block, strides first.
+ *                 info.strides = <Py_ssize_t*>stdlib.malloc(sizeof(Py_ssize_t) * <size_t>ndim * 2)
+ *                 info.shape = info.strides + ndim             # <<<<<<<<<<<<<<
+ *                 for i in range(ndim):
+ *                     info.strides[i] = PyArray_STRIDES(self)[i]
+ */
+    __pyx_v_info->shape = (__pyx_v_info->strides + __pyx_v_ndim);
+
+    /* "numpy.pxd":224
+ *                 info.strides = <Py_ssize_t*>stdlib.malloc(sizeof(Py_ssize_t) * <size_t>ndim * 2)
+ *                 info.shape = info.strides + ndim
+ *                 for i in range(ndim):             # <<<<<<<<<<<<<<
+ *                     info.strides[i] = PyArray_STRIDES(self)[i]
+ *                     info.shape[i] = PyArray_DIMS(self)[i]
+ */
+    __pyx_t_5 = __pyx_v_ndim;
+    for (__pyx_t_6 = 0; __pyx_t_6 < __pyx_t_5; __pyx_t_6+=1) {
+      __pyx_v_i = __pyx_t_6;
+
+      /* "numpy.pxd":225
+ *                 info.shape = info.strides + ndim
+ *                 for i in range(ndim):
+ *                     info.strides[i] = PyArray_STRIDES(self)[i]             # <<<<<<<<<<<<<<
+ *                     info.shape[i] = PyArray_DIMS(self)[i]
+ *             else:
+ */
+      (__pyx_v_info->strides[__pyx_v_i]) = (PyArray_STRIDES(((PyArrayObject *)__pyx_v_self))[__pyx_v_i]);
+
+      /* "numpy.pxd":226
+ *                 for i in range(ndim):
+ *                     info.strides[i] = PyArray_STRIDES(self)[i]
+ *                     info.shape[i] = PyArray_DIMS(self)[i]             # <<<<<<<<<<<<<<
+ *             else:
+ *                 info.strides = <Py_ssize_t*>PyArray_STRIDES(self)
+ */
+      (__pyx_v_info->shape[__pyx_v_i]) = (PyArray_DIMS(((PyArrayObject *)__pyx_v_self))[__pyx_v_i]);
+    }
+    goto __pyx_L9;
+  }
+  /*else*/ {
+
+    /* "numpy.pxd":228
+ *                     info.shape[i] = PyArray_DIMS(self)[i]
+ *             else:
+ *                 info.strides = <Py_ssize_t*>PyArray_STRIDES(self)             # <<<<<<<<<<<<<<
+ *                 info.shape = <Py_ssize_t*>PyArray_DIMS(self)
+ *             info.suboffsets = NULL
+ */
+    __pyx_v_info->strides = ((Py_ssize_t *)PyArray_STRIDES(((PyArrayObject *)__pyx_v_self)));
+
+    /* "numpy.pxd":229
+ *             else:
+ *                 info.strides = <Py_ssize_t*>PyArray_STRIDES(self)
+ *                 info.shape = <Py_ssize_t*>PyArray_DIMS(self)             # <<<<<<<<<<<<<<
+ *             info.suboffsets = NULL
+ *             info.itemsize = PyArray_ITEMSIZE(self)
+ */
+    __pyx_v_info->shape = ((Py_ssize_t *)PyArray_DIMS(((PyArrayObject *)__pyx_v_self)));
+  }
+  __pyx_L9:;
+
+  /* "numpy.pxd":230
+ *                 info.strides = <Py_ssize_t*>PyArray_STRIDES(self)
+ *                 info.shape = <Py_ssize_t*>PyArray_DIMS(self)
+ *             info.suboffsets = NULL             # <<<<<<<<<<<<<<
+ *             info.itemsize = PyArray_ITEMSIZE(self)
+ *             info.readonly = not PyArray_ISWRITEABLE(self)
+ */
+  __pyx_v_info->suboffsets = NULL;
+
+  /* "numpy.pxd":231
+ *                 info.shape = <Py_ssize_t*>PyArray_DIMS(self)
+ *             info.suboffsets = NULL
+ *             info.itemsize = PyArray_ITEMSIZE(self)             # <<<<<<<<<<<<<<
+ *             info.readonly = not PyArray_ISWRITEABLE(self)
+ * 
+ */
+  __pyx_v_info->itemsize = PyArray_ITEMSIZE(((PyArrayObject *)__pyx_v_self));
+
+  /* "numpy.pxd":232
+ *             info.suboffsets = NULL
+ *             info.itemsize = PyArray_ITEMSIZE(self)
+ *             info.readonly = not PyArray_ISWRITEABLE(self)             # <<<<<<<<<<<<<<
+ * 
+ *             cdef int t
+ */
+  __pyx_v_info->readonly = (!PyArray_ISWRITEABLE(((PyArrayObject *)__pyx_v_self)));
+
+  /* "numpy.pxd":235
+ * 
+ *             cdef int t
+ *             cdef char* f = NULL             # <<<<<<<<<<<<<<
+ *             cdef dtype descr = self.descr
+ *             cdef list stack
+ */
+  __pyx_v_f = NULL;
+
+  /* "numpy.pxd":236
+ *             cdef int t
+ *             cdef char* f = NULL
+ *             cdef dtype descr = self.descr             # <<<<<<<<<<<<<<
+ *             cdef list stack
+ *             cdef int offset
+ */
+  __Pyx_INCREF(((PyObject *)((PyArrayObject *)__pyx_v_self)->descr));
+  __pyx_v_descr = ((PyArrayObject *)__pyx_v_self)->descr;
+
+  /* "numpy.pxd":240
+ *             cdef int offset
+ * 
+ *             cdef bint hasfields = PyDataType_HASFIELDS(descr)             # <<<<<<<<<<<<<<
+ * 
+ *             if not hasfields and not copy_shape:
+ */
+  __pyx_v_hasfields = PyDataType_HASFIELDS(__pyx_v_descr);
+
+  /* "numpy.pxd":242
+ *             cdef bint hasfields = PyDataType_HASFIELDS(descr)
+ * 
+ *             if not hasfields and not copy_shape:             # <<<<<<<<<<<<<<
+ *                 # do not call releasebuffer
+ *                 info.obj = None
+ */
+  __pyx_t_2 = (!__pyx_v_hasfields);
+  if (__pyx_t_2) {
+    __pyx_t_3 = (!__pyx_v_copy_shape);
+    __pyx_t_1 = __pyx_t_3;
+  } else {
+    __pyx_t_1 = __pyx_t_2;
+  }
+  if (__pyx_t_1) {
+
+    /* "numpy.pxd":244
+ *             if not hasfields and not copy_shape:
+ *                 # do not call releasebuffer
+ *                 info.obj = None             # <<<<<<<<<<<<<<
+ *             else:
+ *                 # need to call releasebuffer
+ */
+    __Pyx_INCREF(Py_None);
+    __Pyx_GIVEREF(Py_None);
+    __Pyx_GOTREF(__pyx_v_info->obj);
+    __Pyx_DECREF(__pyx_v_info->obj);
+    __pyx_v_info->obj = Py_None;
+    goto __pyx_L12;
+  }
+  /*else*/ {
+
+    /* "numpy.pxd":247
+ *             else:
+ *                 # need to call releasebuffer
+ *                 info.obj = self             # <<<<<<<<<<<<<<
+ * 
+ *             if not hasfields:
+ */
+    __Pyx_INCREF(__pyx_v_self);
+    __Pyx_GIVEREF(__pyx_v_self);
+    __Pyx_GOTREF(__pyx_v_info->obj);
+    __Pyx_DECREF(__pyx_v_info->obj);
+    __pyx_v_info->obj = __pyx_v_self;
+  }
+  __pyx_L12:;
+
+  /* "numpy.pxd":249
+ *                 info.obj = self
+ * 
+ *             if not hasfields:             # <<<<<<<<<<<<<<
+ *                 t = descr.type_num
+ *                 if ((descr.byteorder == '>' and little_endian) or
+ */
+  __pyx_t_1 = (!__pyx_v_hasfields);
+  if (__pyx_t_1) {
+
+    /* "numpy.pxd":250
+ * 
+ *             if not hasfields:
+ *                 t = descr.type_num             # <<<<<<<<<<<<<<
+ *                 if ((descr.byteorder == '>' and little_endian) or
+ *                     (descr.byteorder == '<' and not little_endian)):
+ */
+    __pyx_v_t = __pyx_v_descr->type_num;
+
+    /* "numpy.pxd":251
+ *             if not hasfields:
+ *                 t = descr.type_num
+ *                 if ((descr.byteorder == '>' and little_endian) or             # <<<<<<<<<<<<<<
+ *                     (descr.byteorder == '<' and not little_endian)):
+ *                     raise ValueError(u"Non-native byte order not supported")
+ */
+    __pyx_t_1 = (__pyx_v_descr->byteorder == '>');
+    if (__pyx_t_1) {
+      __pyx_t_2 = __pyx_v_little_endian;
+    } else {
+      __pyx_t_2 = __pyx_t_1;
+    }
+    if (!__pyx_t_2) {
+
+      /* "numpy.pxd":252
+ *                 t = descr.type_num
+ *                 if ((descr.byteorder == '>' and little_endian) or
+ *                     (descr.byteorder == '<' and not little_endian)):             # <<<<<<<<<<<<<<
+ *                     raise ValueError(u"Non-native byte order not supported")
+ *                 if   t == NPY_BYTE:        f = "b"
+ */
+      __pyx_t_1 = (__pyx_v_descr->byteorder == '<');
+      if (__pyx_t_1) {
+        __pyx_t_3 = (!__pyx_v_little_endian);
+        __pyx_t_7 = __pyx_t_3;
+      } else {
+        __pyx_t_7 = __pyx_t_1;
+      }
+      __pyx_t_1 = __pyx_t_7;
+    } else {
+      __pyx_t_1 = __pyx_t_2;
+    }
+    if (__pyx_t_1) {
+
+      /* "numpy.pxd":253
+ *                 if ((descr.byteorder == '>' and little_endian) or
+ *                     (descr.byteorder == '<' and not little_endian)):
+ *                     raise ValueError(u"Non-native byte order not supported")             # <<<<<<<<<<<<<<
+ *                 if   t == NPY_BYTE:        f = "b"
+ *                 elif t == NPY_UBYTE:       f = "B"
+ */
+      __pyx_t_4 = PyObject_Call(__pyx_builtin_ValueError, ((PyObject *)__pyx_k_tuple_31), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 253; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_4);
+      __Pyx_Raise(__pyx_t_4, 0, 0, 0);
+      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+      {__pyx_filename = __pyx_f[1]; __pyx_lineno = 253; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      goto __pyx_L14;
+    }
+    __pyx_L14:;
+
+    /* "numpy.pxd":254
+ *                     (descr.byteorder == '<' and not little_endian)):
+ *                     raise ValueError(u"Non-native byte order not supported")
+ *                 if   t == NPY_BYTE:        f = "b"             # <<<<<<<<<<<<<<
+ *                 elif t == NPY_UBYTE:       f = "B"
+ *                 elif t == NPY_SHORT:       f = "h"
+ */
+    __pyx_t_1 = (__pyx_v_t == NPY_BYTE);
+    if (__pyx_t_1) {
+      __pyx_v_f = __pyx_k__b;
+      goto __pyx_L15;
+    }
+
+    /* "numpy.pxd":255
+ *                     raise ValueError(u"Non-native byte order not supported")
+ *                 if   t == NPY_BYTE:        f = "b"
+ *                 elif t == NPY_UBYTE:       f = "B"             # <<<<<<<<<<<<<<
+ *                 elif t == NPY_SHORT:       f = "h"
+ *                 elif t == NPY_USHORT:      f = "H"
+ */
+    __pyx_t_1 = (__pyx_v_t == NPY_UBYTE);
+    if (__pyx_t_1) {
+      __pyx_v_f = __pyx_k__B;
+      goto __pyx_L15;
+    }
+
+    /* "numpy.pxd":256
+ *                 if   t == NPY_BYTE:        f = "b"
+ *                 elif t == NPY_UBYTE:       f = "B"
+ *                 elif t == NPY_SHORT:       f = "h"             # <<<<<<<<<<<<<<
+ *                 elif t == NPY_USHORT:      f = "H"
+ *                 elif t == NPY_INT:         f = "i"
+ */
+    __pyx_t_1 = (__pyx_v_t == NPY_SHORT);
+    if (__pyx_t_1) {
+      __pyx_v_f = __pyx_k__h;
+      goto __pyx_L15;
+    }
+
+    /* "numpy.pxd":257
+ *                 elif t == NPY_UBYTE:       f = "B"
+ *                 elif t == NPY_SHORT:       f = "h"
+ *                 elif t == NPY_USHORT:      f = "H"             # <<<<<<<<<<<<<<
+ *                 elif t == NPY_INT:         f = "i"
+ *                 elif t == NPY_UINT:        f = "I"
+ */
+    __pyx_t_1 = (__pyx_v_t == NPY_USHORT);
+    if (__pyx_t_1) {
+      __pyx_v_f = __pyx_k__H;
+      goto __pyx_L15;
+    }
+
+    /* "numpy.pxd":258
+ *                 elif t == NPY_SHORT:       f = "h"
+ *                 elif t == NPY_USHORT:      f = "H"
+ *                 elif t == NPY_INT:         f = "i"             # <<<<<<<<<<<<<<
+ *                 elif t == NPY_UINT:        f = "I"
+ *                 elif t == NPY_LONG:        f = "l"
+ */
+    __pyx_t_1 = (__pyx_v_t == NPY_INT);
+    if (__pyx_t_1) {
+      __pyx_v_f = __pyx_k__i;
+      goto __pyx_L15;
+    }
+
+    /* "numpy.pxd":259
+ *                 elif t == NPY_USHORT:      f = "H"
+ *                 elif t == NPY_INT:         f = "i"
+ *                 elif t == NPY_UINT:        f = "I"             # <<<<<<<<<<<<<<
+ *                 elif t == NPY_LONG:        f = "l"
+ *                 elif t == NPY_ULONG:       f = "L"
+ */
+    __pyx_t_1 = (__pyx_v_t == NPY_UINT);
+    if (__pyx_t_1) {
+      __pyx_v_f = __pyx_k__I;
+      goto __pyx_L15;
+    }
+
+    /* "numpy.pxd":260
+ *                 elif t == NPY_INT:         f = "i"
+ *                 elif t == NPY_UINT:        f = "I"
+ *                 elif t == NPY_LONG:        f = "l"             # <<<<<<<<<<<<<<
+ *                 elif t == NPY_ULONG:       f = "L"
+ *                 elif t == NPY_LONGLONG:    f = "q"
+ */
+    __pyx_t_1 = (__pyx_v_t == NPY_LONG);
+    if (__pyx_t_1) {
+      __pyx_v_f = __pyx_k__l;
+      goto __pyx_L15;
+    }
+
+    /* "numpy.pxd":261
+ *                 elif t == NPY_UINT:        f = "I"
+ *                 elif t == NPY_LONG:        f = "l"
+ *                 elif t == NPY_ULONG:       f = "L"             # <<<<<<<<<<<<<<
+ *                 elif t == NPY_LONGLONG:    f = "q"
+ *                 elif t == NPY_ULONGLONG:   f = "Q"
+ */
+    __pyx_t_1 = (__pyx_v_t == NPY_ULONG);
+    if (__pyx_t_1) {
+      __pyx_v_f = __pyx_k__L;
+      goto __pyx_L15;
+    }
+
+    /* "numpy.pxd":262
+ *                 elif t == NPY_LONG:        f = "l"
+ *                 elif t == NPY_ULONG:       f = "L"
+ *                 elif t == NPY_LONGLONG:    f = "q"             # <<<<<<<<<<<<<<
+ *                 elif t == NPY_ULONGLONG:   f = "Q"
+ *                 elif t == NPY_FLOAT:       f = "f"
+ */
+    __pyx_t_1 = (__pyx_v_t == NPY_LONGLONG);
+    if (__pyx_t_1) {
+      __pyx_v_f = __pyx_k__q;
+      goto __pyx_L15;
+    }
+
+    /* "numpy.pxd":263
+ *                 elif t == NPY_ULONG:       f = "L"
+ *                 elif t == NPY_LONGLONG:    f = "q"
+ *                 elif t == NPY_ULONGLONG:   f = "Q"             # <<<<<<<<<<<<<<
+ *                 elif t == NPY_FLOAT:       f = "f"
+ *                 elif t == NPY_DOUBLE:      f = "d"
+ */
+    __pyx_t_1 = (__pyx_v_t == NPY_ULONGLONG);
+    if (__pyx_t_1) {
+      __pyx_v_f = __pyx_k__Q;
+      goto __pyx_L15;
+    }
+
+    /* "numpy.pxd":264
+ *                 elif t == NPY_LONGLONG:    f = "q"
+ *                 elif t == NPY_ULONGLONG:   f = "Q"
+ *                 elif t == NPY_FLOAT:       f = "f"             # <<<<<<<<<<<<<<
+ *                 elif t == NPY_DOUBLE:      f = "d"
+ *                 elif t == NPY_LONGDOUBLE:  f = "g"
+ */
+    __pyx_t_1 = (__pyx_v_t == NPY_FLOAT);
+    if (__pyx_t_1) {
+      __pyx_v_f = __pyx_k__f;
+      goto __pyx_L15;
+    }
+
+    /* "numpy.pxd":265
+ *                 elif t == NPY_ULONGLONG:   f = "Q"
+ *                 elif t == NPY_FLOAT:       f = "f"
+ *                 elif t == NPY_DOUBLE:      f = "d"             # <<<<<<<<<<<<<<
+ *                 elif t == NPY_LONGDOUBLE:  f = "g"
+ *                 elif t == NPY_CFLOAT:      f = "Zf"
+ */
+    __pyx_t_1 = (__pyx_v_t == NPY_DOUBLE);
+    if (__pyx_t_1) {
+      __pyx_v_f = __pyx_k__d;
+      goto __pyx_L15;
+    }
+
+    /* "numpy.pxd":266
+ *                 elif t == NPY_FLOAT:       f = "f"
+ *                 elif t == NPY_DOUBLE:      f = "d"
+ *                 elif t == NPY_LONGDOUBLE:  f = "g"             # <<<<<<<<<<<<<<
+ *                 elif t == NPY_CFLOAT:      f = "Zf"
+ *                 elif t == NPY_CDOUBLE:     f = "Zd"
+ */
+    __pyx_t_1 = (__pyx_v_t == NPY_LONGDOUBLE);
+    if (__pyx_t_1) {
+      __pyx_v_f = __pyx_k__g;
+      goto __pyx_L15;
+    }
+
+    /* "numpy.pxd":267
+ *                 elif t == NPY_DOUBLE:      f = "d"
+ *                 elif t == NPY_LONGDOUBLE:  f = "g"
+ *                 elif t == NPY_CFLOAT:      f = "Zf"             # <<<<<<<<<<<<<<
+ *                 elif t == NPY_CDOUBLE:     f = "Zd"
+ *                 elif t == NPY_CLONGDOUBLE: f = "Zg"
+ */
+    __pyx_t_1 = (__pyx_v_t == NPY_CFLOAT);
+    if (__pyx_t_1) {
+      __pyx_v_f = __pyx_k__Zf;
+      goto __pyx_L15;
+    }
+
+    /* "numpy.pxd":268
+ *                 elif t == NPY_LONGDOUBLE:  f = "g"
+ *                 elif t == NPY_CFLOAT:      f = "Zf"
+ *                 elif t == NPY_CDOUBLE:     f = "Zd"             # <<<<<<<<<<<<<<
+ *                 elif t == NPY_CLONGDOUBLE: f = "Zg"
+ *                 elif t == NPY_OBJECT:      f = "O"
+ */
+    __pyx_t_1 = (__pyx_v_t == NPY_CDOUBLE);
+    if (__pyx_t_1) {
+      __pyx_v_f = __pyx_k__Zd;
+      goto __pyx_L15;
+    }
+
+    /* "numpy.pxd":269
+ *                 elif t == NPY_CFLOAT:      f = "Zf"
+ *                 elif t == NPY_CDOUBLE:     f = "Zd"
+ *                 elif t == NPY_CLONGDOUBLE: f = "Zg"             # <<<<<<<<<<<<<<
+ *                 elif t == NPY_OBJECT:      f = "O"
+ *                 else:
+ */
+    __pyx_t_1 = (__pyx_v_t == NPY_CLONGDOUBLE);
+    if (__pyx_t_1) {
+      __pyx_v_f = __pyx_k__Zg;
+      goto __pyx_L15;
+    }
+
+    /* "numpy.pxd":270
+ *                 elif t == NPY_CDOUBLE:     f = "Zd"
+ *                 elif t == NPY_CLONGDOUBLE: f = "Zg"
+ *                 elif t == NPY_OBJECT:      f = "O"             # <<<<<<<<<<<<<<
+ *                 else:
+ *                     raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t)
+ */
+    __pyx_t_1 = (__pyx_v_t == NPY_OBJECT);
+    if (__pyx_t_1) {
+      __pyx_v_f = __pyx_k__O;
+      goto __pyx_L15;
+    }
+    /*else*/ {
+
+      /* "numpy.pxd":272
+ *                 elif t == NPY_OBJECT:      f = "O"
+ *                 else:
+ *                     raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t)             # <<<<<<<<<<<<<<
+ *                 info.format = f
+ *                 return
+ */
+      __pyx_t_4 = PyInt_FromLong(__pyx_v_t); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 272; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_4);
+      __pyx_t_8 = PyNumber_Remainder(((PyObject *)__pyx_kp_u_32), __pyx_t_4); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 272; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(((PyObject *)__pyx_t_8));
+      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+      __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 272; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(((PyObject *)__pyx_t_4));
+      PyTuple_SET_ITEM(__pyx_t_4, 0, ((PyObject *)__pyx_t_8));
+      __Pyx_GIVEREF(((PyObject *)__pyx_t_8));
+      __pyx_t_8 = 0;
+      __pyx_t_8 = PyObject_Call(__pyx_builtin_ValueError, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 272; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_8);
+      __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
+      __Pyx_Raise(__pyx_t_8, 0, 0, 0);
+      __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
+      {__pyx_filename = __pyx_f[1]; __pyx_lineno = 272; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    }
+    __pyx_L15:;
+
+    /* "numpy.pxd":273
+ *                 else:
+ *                     raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t)
+ *                 info.format = f             # <<<<<<<<<<<<<<
+ *                 return
+ *             else:
+ */
+    __pyx_v_info->format = __pyx_v_f;
+
+    /* "numpy.pxd":274
+ *                     raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t)
+ *                 info.format = f
+ *                 return             # <<<<<<<<<<<<<<
+ *             else:
+ *                 info.format = <char*>stdlib.malloc(_buffer_format_string_len)
+ */
+    __pyx_r = 0;
+    goto __pyx_L0;
+    goto __pyx_L13;
+  }
+  /*else*/ {
+
+    /* "numpy.pxd":276
+ *                 return
+ *             else:
+ *                 info.format = <char*>stdlib.malloc(_buffer_format_string_len)             # <<<<<<<<<<<<<<
+ *                 info.format[0] = '^' # Native data types, manual alignment
+ *                 offset = 0
+ */
+    __pyx_v_info->format = ((char *)malloc(255));
+
+    /* "numpy.pxd":277
+ *             else:
+ *                 info.format = <char*>stdlib.malloc(_buffer_format_string_len)
+ *                 info.format[0] = '^' # Native data types, manual alignment             # <<<<<<<<<<<<<<
+ *                 offset = 0
+ *                 f = _util_dtypestring(descr, info.format + 1,
+ */
+    (__pyx_v_info->format[0]) = '^';
+
+    /* "numpy.pxd":278
+ *                 info.format = <char*>stdlib.malloc(_buffer_format_string_len)
+ *                 info.format[0] = '^' # Native data types, manual alignment
+ *                 offset = 0             # <<<<<<<<<<<<<<
+ *                 f = _util_dtypestring(descr, info.format + 1,
+ *                                       info.format + _buffer_format_string_len,
+ */
+    __pyx_v_offset = 0;
+
+    /* "numpy.pxd":281
+ *                 f = _util_dtypestring(descr, info.format + 1,
+ *                                       info.format + _buffer_format_string_len,
+ *                                       &offset)             # <<<<<<<<<<<<<<
+ *                 f[0] = 0 # Terminate format string
+ * 
+ */
+    __pyx_t_9 = __pyx_f_5numpy__util_dtypestring(__pyx_v_descr, (__pyx_v_info->format + 1), (__pyx_v_info->format + 255), (&__pyx_v_offset)); if (unlikely(__pyx_t_9 == NULL)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 279; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_v_f = __pyx_t_9;
+
+    /* "numpy.pxd":282
+ *                                       info.format + _buffer_format_string_len,
+ *                                       &offset)
+ *                 f[0] = 0 # Terminate format string             # <<<<<<<<<<<<<<
+ * 
+ *         def __releasebuffer__(ndarray self, Py_buffer* info):
+ */
+    (__pyx_v_f[0]) = 0;
+  }
+  __pyx_L13:;
+
+  __pyx_r = 0;
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_XDECREF(__pyx_t_8);
+  __Pyx_AddTraceback("numpy.ndarray.__getbuffer__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = -1;
+  if (__pyx_v_info != NULL && __pyx_v_info->obj != NULL) {
+    __Pyx_GOTREF(__pyx_v_info->obj);
+    __Pyx_DECREF(__pyx_v_info->obj); __pyx_v_info->obj = NULL;
+  }
+  goto __pyx_L2;
+  __pyx_L0:;
+  if (__pyx_v_info != NULL && __pyx_v_info->obj == Py_None) {
+    __Pyx_GOTREF(Py_None);
+    __Pyx_DECREF(Py_None); __pyx_v_info->obj = NULL;
+  }
+  __pyx_L2:;
+  __Pyx_XDECREF((PyObject *)__pyx_v_descr);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "numpy.pxd":284
+ *                 f[0] = 0 # Terminate format string
+ * 
+ *         def __releasebuffer__(ndarray self, Py_buffer* info):             # <<<<<<<<<<<<<<
+ *             if PyArray_HASFIELDS(self):
+ *                 stdlib.free(info.format)
+ */
+
+static CYTHON_UNUSED void __pyx_pf_5numpy_7ndarray_1__releasebuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info); /*proto*/
+static CYTHON_UNUSED void __pyx_pf_5numpy_7ndarray_1__releasebuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info) {
+  __Pyx_RefNannyDeclarations
+  int __pyx_t_1;
+  __Pyx_RefNannySetupContext("__releasebuffer__");
+
+  /* "numpy.pxd":285
+ * 
+ *         def __releasebuffer__(ndarray self, Py_buffer* info):
+ *             if PyArray_HASFIELDS(self):             # <<<<<<<<<<<<<<
+ *                 stdlib.free(info.format)
+ *             if sizeof(npy_intp) != sizeof(Py_ssize_t):
+ */
+  __pyx_t_1 = PyArray_HASFIELDS(((PyArrayObject *)__pyx_v_self));
+  if (__pyx_t_1) {
+
+    /* "numpy.pxd":286
+ *         def __releasebuffer__(ndarray self, Py_buffer* info):
+ *             if PyArray_HASFIELDS(self):
+ *                 stdlib.free(info.format)             # <<<<<<<<<<<<<<
+ *             if sizeof(npy_intp) != sizeof(Py_ssize_t):
+ *                 stdlib.free(info.strides)
+ */
+    free(__pyx_v_info->format);
+    goto __pyx_L5;
+  }
+  __pyx_L5:;
+
+  /* "numpy.pxd":287
+ *             if PyArray_HASFIELDS(self):
+ *                 stdlib.free(info.format)
+ *             if sizeof(npy_intp) != sizeof(Py_ssize_t):             # <<<<<<<<<<<<<<
+ *                 stdlib.free(info.strides)
+ *                 # info.shape was stored after info.strides in the same block
+ */
+  __pyx_t_1 = ((sizeof(npy_intp)) != (sizeof(Py_ssize_t)));
+  if (__pyx_t_1) {
+
+    /* "numpy.pxd":288
+ *                 stdlib.free(info.format)
+ *             if sizeof(npy_intp) != sizeof(Py_ssize_t):
+ *                 stdlib.free(info.strides)             # <<<<<<<<<<<<<<
+ *                 # info.shape was stored after info.strides in the same block
+ * 
+ */
+    free(__pyx_v_info->strides);
+    goto __pyx_L6;
+  }
+  __pyx_L6:;
+
+  __Pyx_RefNannyFinishContext();
+}
+
+/* "numpy.pxd":764
+ * ctypedef npy_cdouble     complex_t
+ * 
+ * cdef inline object PyArray_MultiIterNew1(a):             # <<<<<<<<<<<<<<
+ *     return PyArray_MultiIterNew(1, <void*>a)
+ * 
+ */
+
+static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew1(PyObject *__pyx_v_a) {
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("PyArray_MultiIterNew1");
+
+  /* "numpy.pxd":765
+ * 
+ * cdef inline object PyArray_MultiIterNew1(a):
+ *     return PyArray_MultiIterNew(1, <void*>a)             # <<<<<<<<<<<<<<
+ * 
+ * cdef inline object PyArray_MultiIterNew2(a, b):
+ */
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_t_1 = PyArray_MultiIterNew(1, ((void *)__pyx_v_a)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 765; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_r = __pyx_t_1;
+  __pyx_t_1 = 0;
+  goto __pyx_L0;
+
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_AddTraceback("numpy.PyArray_MultiIterNew1", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = 0;
+  __pyx_L0:;
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "numpy.pxd":767
+ *     return PyArray_MultiIterNew(1, <void*>a)
+ * 
+ * cdef inline object PyArray_MultiIterNew2(a, b):             # <<<<<<<<<<<<<<
+ *     return PyArray_MultiIterNew(2, <void*>a, <void*>b)
+ * 
+ */
+
+static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew2(PyObject *__pyx_v_a, PyObject *__pyx_v_b) {
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("PyArray_MultiIterNew2");
+
+  /* "numpy.pxd":768
+ * 
+ * cdef inline object PyArray_MultiIterNew2(a, b):
+ *     return PyArray_MultiIterNew(2, <void*>a, <void*>b)             # <<<<<<<<<<<<<<
+ * 
+ * cdef inline object PyArray_MultiIterNew3(a, b, c):
+ */
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_t_1 = PyArray_MultiIterNew(2, ((void *)__pyx_v_a), ((void *)__pyx_v_b)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 768; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_r = __pyx_t_1;
+  __pyx_t_1 = 0;
+  goto __pyx_L0;
+
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_AddTraceback("numpy.PyArray_MultiIterNew2", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = 0;
+  __pyx_L0:;
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "numpy.pxd":770
+ *     return PyArray_MultiIterNew(2, <void*>a, <void*>b)
+ * 
+ * cdef inline object PyArray_MultiIterNew3(a, b, c):             # <<<<<<<<<<<<<<
+ *     return PyArray_MultiIterNew(3, <void*>a, <void*>b, <void*> c)
+ * 
+ */
+
+static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew3(PyObject *__pyx_v_a, PyObject *__pyx_v_b, PyObject *__pyx_v_c) {
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("PyArray_MultiIterNew3");
+
+  /* "numpy.pxd":771
+ * 
+ * cdef inline object PyArray_MultiIterNew3(a, b, c):
+ *     return PyArray_MultiIterNew(3, <void*>a, <void*>b, <void*> c)             # <<<<<<<<<<<<<<
+ * 
+ * cdef inline object PyArray_MultiIterNew4(a, b, c, d):
+ */
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_t_1 = PyArray_MultiIterNew(3, ((void *)__pyx_v_a), ((void *)__pyx_v_b), ((void *)__pyx_v_c)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 771; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_r = __pyx_t_1;
+  __pyx_t_1 = 0;
+  goto __pyx_L0;
+
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_AddTraceback("numpy.PyArray_MultiIterNew3", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = 0;
+  __pyx_L0:;
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "numpy.pxd":773
+ *     return PyArray_MultiIterNew(3, <void*>a, <void*>b, <void*> c)
+ * 
+ * cdef inline object PyArray_MultiIterNew4(a, b, c, d):             # <<<<<<<<<<<<<<
+ *     return PyArray_MultiIterNew(4, <void*>a, <void*>b, <void*>c, <void*> d)
+ * 
+ */
+
+static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew4(PyObject *__pyx_v_a, PyObject *__pyx_v_b, PyObject *__pyx_v_c, PyObject *__pyx_v_d) {
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("PyArray_MultiIterNew4");
+
+  /* "numpy.pxd":774
+ * 
+ * cdef inline object PyArray_MultiIterNew4(a, b, c, d):
+ *     return PyArray_MultiIterNew(4, <void*>a, <void*>b, <void*>c, <void*> d)             # <<<<<<<<<<<<<<
+ * 
+ * cdef inline object PyArray_MultiIterNew5(a, b, c, d, e):
+ */
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_t_1 = PyArray_MultiIterNew(4, ((void *)__pyx_v_a), ((void *)__pyx_v_b), ((void *)__pyx_v_c), ((void *)__pyx_v_d)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 774; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_r = __pyx_t_1;
+  __pyx_t_1 = 0;
+  goto __pyx_L0;
+
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_AddTraceback("numpy.PyArray_MultiIterNew4", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = 0;
+  __pyx_L0:;
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "numpy.pxd":776
+ *     return PyArray_MultiIterNew(4, <void*>a, <void*>b, <void*>c, <void*> d)
+ * 
+ * cdef inline object PyArray_MultiIterNew5(a, b, c, d, e):             # <<<<<<<<<<<<<<
+ *     return PyArray_MultiIterNew(5, <void*>a, <void*>b, <void*>c, <void*> d, <void*> e)
+ * 
+ */
+
+static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew5(PyObject *__pyx_v_a, PyObject *__pyx_v_b, PyObject *__pyx_v_c, PyObject *__pyx_v_d, PyObject *__pyx_v_e) {
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("PyArray_MultiIterNew5");
+
+  /* "numpy.pxd":777
+ * 
+ * cdef inline object PyArray_MultiIterNew5(a, b, c, d, e):
+ *     return PyArray_MultiIterNew(5, <void*>a, <void*>b, <void*>c, <void*> d, <void*> e)             # <<<<<<<<<<<<<<
+ * 
+ * cdef inline char* _util_dtypestring(dtype descr, char* f, char* end, int* offset) except NULL:
+ */
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_t_1 = PyArray_MultiIterNew(5, ((void *)__pyx_v_a), ((void *)__pyx_v_b), ((void *)__pyx_v_c), ((void *)__pyx_v_d), ((void *)__pyx_v_e)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 777; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_r = __pyx_t_1;
+  __pyx_t_1 = 0;
+  goto __pyx_L0;
+
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_AddTraceback("numpy.PyArray_MultiIterNew5", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = 0;
+  __pyx_L0:;
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "numpy.pxd":779
+ *     return PyArray_MultiIterNew(5, <void*>a, <void*>b, <void*>c, <void*> d, <void*> e)
+ * 
+ * cdef inline char* _util_dtypestring(dtype descr, char* f, char* end, int* offset) except NULL:             # <<<<<<<<<<<<<<
+ *     # Recursive utility function used in __getbuffer__ to get format
+ *     # string. The new location in the format string is returned.
+ */
+
+static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx_v_descr, char *__pyx_v_f, char *__pyx_v_end, int *__pyx_v_offset) {
+  PyArray_Descr *__pyx_v_child = 0;
+  int __pyx_v_endian_detector;
+  int __pyx_v_little_endian;
+  PyObject *__pyx_v_fields = 0;
+  PyObject *__pyx_v_childname = NULL;
+  PyObject *__pyx_v_new_offset = NULL;
+  PyObject *__pyx_v_t = NULL;
+  char *__pyx_r;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  Py_ssize_t __pyx_t_2;
+  PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
+  PyObject *__pyx_t_5 = NULL;
+  int __pyx_t_6;
+  int __pyx_t_7;
+  int __pyx_t_8;
+  int __pyx_t_9;
+  long __pyx_t_10;
+  char *__pyx_t_11;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("_util_dtypestring");
+
+  /* "numpy.pxd":786
+ *     cdef int delta_offset
+ *     cdef tuple i
+ *     cdef int endian_detector = 1             # <<<<<<<<<<<<<<
+ *     cdef bint little_endian = ((<char*>&endian_detector)[0] != 0)
+ *     cdef tuple fields
+ */
+  __pyx_v_endian_detector = 1;
+
+  /* "numpy.pxd":787
+ *     cdef tuple i
+ *     cdef int endian_detector = 1
+ *     cdef bint little_endian = ((<char*>&endian_detector)[0] != 0)             # <<<<<<<<<<<<<<
+ *     cdef tuple fields
+ * 
+ */
+  __pyx_v_little_endian = ((((char *)(&__pyx_v_endian_detector))[0]) != 0);
+
+  /* "numpy.pxd":790
+ *     cdef tuple fields
+ * 
+ *     for childname in descr.names:             # <<<<<<<<<<<<<<
+ *         fields = descr.fields[childname]
+ *         child, new_offset = fields
+ */
+  if (unlikely(((PyObject *)__pyx_v_descr->names) == Py_None)) {
+    PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable"); {__pyx_filename = __pyx_f[1]; __pyx_lineno = 790; __pyx_clineno = __LINE__; goto __pyx_L1_error;} 
+  }
+  __pyx_t_1 = ((PyObject *)__pyx_v_descr->names); __Pyx_INCREF(__pyx_t_1); __pyx_t_2 = 0;
+  for (;;) {
+    if (__pyx_t_2 >= PyTuple_GET_SIZE(__pyx_t_1)) break;
+    __pyx_t_3 = PyTuple_GET_ITEM(__pyx_t_1, __pyx_t_2); __Pyx_INCREF(__pyx_t_3); __pyx_t_2++;
+    __Pyx_XDECREF(__pyx_v_childname);
+    __pyx_v_childname = __pyx_t_3;
+    __pyx_t_3 = 0;
+
+    /* "numpy.pxd":791
+ * 
+ *     for childname in descr.names:
+ *         fields = descr.fields[childname]             # <<<<<<<<<<<<<<
+ *         child, new_offset = fields
+ * 
+ */
+    __pyx_t_3 = PyObject_GetItem(__pyx_v_descr->fields, __pyx_v_childname); if (!__pyx_t_3) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 791; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_3);
+    if (!(likely(PyTuple_CheckExact(__pyx_t_3))||((__pyx_t_3) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected tuple, got %.200s", Py_TYPE(__pyx_t_3)->tp_name), 0))) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 791; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_XDECREF(((PyObject *)__pyx_v_fields));
+    __pyx_v_fields = ((PyObject*)__pyx_t_3);
+    __pyx_t_3 = 0;
+
+    /* "numpy.pxd":792
+ *     for childname in descr.names:
+ *         fields = descr.fields[childname]
+ *         child, new_offset = fields             # <<<<<<<<<<<<<<
+ * 
+ *         if (end - f) - (new_offset - offset[0]) < 15:
+ */
+    if (likely(PyTuple_CheckExact(((PyObject *)__pyx_v_fields)))) {
+      PyObject* sequence = ((PyObject *)__pyx_v_fields);
+      if (unlikely(PyTuple_GET_SIZE(sequence) != 2)) {
+        if (PyTuple_GET_SIZE(sequence) > 2) __Pyx_RaiseTooManyValuesError(2);
+        else __Pyx_RaiseNeedMoreValuesError(PyTuple_GET_SIZE(sequence));
+        {__pyx_filename = __pyx_f[1]; __pyx_lineno = 792; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      }
+      __pyx_t_3 = PyTuple_GET_ITEM(sequence, 0); 
+      __pyx_t_4 = PyTuple_GET_ITEM(sequence, 1); 
+      __Pyx_INCREF(__pyx_t_3);
+      __Pyx_INCREF(__pyx_t_4);
+    } else {
+      __Pyx_UnpackTupleError(((PyObject *)__pyx_v_fields), 2);
+      {__pyx_filename = __pyx_f[1]; __pyx_lineno = 792; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    }
+    if (!(likely(((__pyx_t_3) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_3, __pyx_ptype_5numpy_dtype))))) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 792; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_XDECREF(((PyObject *)__pyx_v_child));
+    __pyx_v_child = ((PyArray_Descr *)__pyx_t_3);
+    __pyx_t_3 = 0;
+    __Pyx_XDECREF(__pyx_v_new_offset);
+    __pyx_v_new_offset = __pyx_t_4;
+    __pyx_t_4 = 0;
+
+    /* "numpy.pxd":794
+ *         child, new_offset = fields
+ * 
+ *         if (end - f) - (new_offset - offset[0]) < 15:             # <<<<<<<<<<<<<<
+ *             raise RuntimeError(u"Format string allocated too short, see comment in numpy.pxd")
+ * 
+ */
+    __pyx_t_4 = PyInt_FromLong((__pyx_v_end - __pyx_v_f)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 794; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_4);
+    __pyx_t_3 = PyInt_FromLong((__pyx_v_offset[0])); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 794; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_3);
+    __pyx_t_5 = PyNumber_Subtract(__pyx_v_new_offset, __pyx_t_3); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 794; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_5);
+    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+    __pyx_t_3 = PyNumber_Subtract(__pyx_t_4, __pyx_t_5); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 794; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_3);
+    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+    __pyx_t_5 = PyObject_RichCompare(__pyx_t_3, __pyx_int_15, Py_LT); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 794; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_5);
+    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+    __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 794; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+    if (__pyx_t_6) {
+
+      /* "numpy.pxd":795
+ * 
+ *         if (end - f) - (new_offset - offset[0]) < 15:
+ *             raise RuntimeError(u"Format string allocated too short, see comment in numpy.pxd")             # <<<<<<<<<<<<<<
+ * 
+ *         if ((child.byteorder == '>' and little_endian) or
+ */
+      __pyx_t_5 = PyObject_Call(__pyx_builtin_RuntimeError, ((PyObject *)__pyx_k_tuple_34), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 795; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_5);
+      __Pyx_Raise(__pyx_t_5, 0, 0, 0);
+      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+      {__pyx_filename = __pyx_f[1]; __pyx_lineno = 795; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      goto __pyx_L5;
+    }
+    __pyx_L5:;
+
+    /* "numpy.pxd":797
+ *             raise RuntimeError(u"Format string allocated too short, see comment in numpy.pxd")
+ * 
+ *         if ((child.byteorder == '>' and little_endian) or             # <<<<<<<<<<<<<<
+ *             (child.byteorder == '<' and not little_endian)):
+ *             raise ValueError(u"Non-native byte order not supported")
+ */
+    __pyx_t_6 = (__pyx_v_child->byteorder == '>');
+    if (__pyx_t_6) {
+      __pyx_t_7 = __pyx_v_little_endian;
+    } else {
+      __pyx_t_7 = __pyx_t_6;
+    }
+    if (!__pyx_t_7) {
+
+      /* "numpy.pxd":798
+ * 
+ *         if ((child.byteorder == '>' and little_endian) or
+ *             (child.byteorder == '<' and not little_endian)):             # <<<<<<<<<<<<<<
+ *             raise ValueError(u"Non-native byte order not supported")
+ *             # One could encode it in the format string and have Cython
+ */
+      __pyx_t_6 = (__pyx_v_child->byteorder == '<');
+      if (__pyx_t_6) {
+        __pyx_t_8 = (!__pyx_v_little_endian);
+        __pyx_t_9 = __pyx_t_8;
+      } else {
+        __pyx_t_9 = __pyx_t_6;
+      }
+      __pyx_t_6 = __pyx_t_9;
+    } else {
+      __pyx_t_6 = __pyx_t_7;
+    }
+    if (__pyx_t_6) {
+
+      /* "numpy.pxd":799
+ *         if ((child.byteorder == '>' and little_endian) or
+ *             (child.byteorder == '<' and not little_endian)):
+ *             raise ValueError(u"Non-native byte order not supported")             # <<<<<<<<<<<<<<
+ *             # One could encode it in the format string and have Cython
+ *             # complain instead, BUT: < and > in format strings also imply
+ */
+      __pyx_t_5 = PyObject_Call(__pyx_builtin_ValueError, ((PyObject *)__pyx_k_tuple_35), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 799; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_5);
+      __Pyx_Raise(__pyx_t_5, 0, 0, 0);
+      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+      {__pyx_filename = __pyx_f[1]; __pyx_lineno = 799; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      goto __pyx_L6;
+    }
+    __pyx_L6:;
+
+    /* "numpy.pxd":809
+ * 
+ *         # Output padding bytes
+ *         while offset[0] < new_offset:             # <<<<<<<<<<<<<<
+ *             f[0] = 120 # "x"; pad byte
+ *             f += 1
+ */
+    while (1) {
+      __pyx_t_5 = PyInt_FromLong((__pyx_v_offset[0])); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 809; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_5);
+      __pyx_t_3 = PyObject_RichCompare(__pyx_t_5, __pyx_v_new_offset, Py_LT); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 809; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_3);
+      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 809; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+      if (!__pyx_t_6) break;
+
+      /* "numpy.pxd":810
+ *         # Output padding bytes
+ *         while offset[0] < new_offset:
+ *             f[0] = 120 # "x"; pad byte             # <<<<<<<<<<<<<<
+ *             f += 1
+ *             offset[0] += 1
+ */
+      (__pyx_v_f[0]) = 120;
+
+      /* "numpy.pxd":811
+ *         while offset[0] < new_offset:
+ *             f[0] = 120 # "x"; pad byte
+ *             f += 1             # <<<<<<<<<<<<<<
+ *             offset[0] += 1
+ * 
+ */
+      __pyx_v_f = (__pyx_v_f + 1);
+
+      /* "numpy.pxd":812
+ *             f[0] = 120 # "x"; pad byte
+ *             f += 1
+ *             offset[0] += 1             # <<<<<<<<<<<<<<
+ * 
+ *         offset[0] += child.itemsize
+ */
+      __pyx_t_10 = 0;
+      (__pyx_v_offset[__pyx_t_10]) = ((__pyx_v_offset[__pyx_t_10]) + 1);
+    }
+
+    /* "numpy.pxd":814
+ *             offset[0] += 1
+ * 
+ *         offset[0] += child.itemsize             # <<<<<<<<<<<<<<
+ * 
+ *         if not PyDataType_HASFIELDS(child):
+ */
+    __pyx_t_10 = 0;
+    (__pyx_v_offset[__pyx_t_10]) = ((__pyx_v_offset[__pyx_t_10]) + __pyx_v_child->elsize);
+
+    /* "numpy.pxd":816
+ *         offset[0] += child.itemsize
+ * 
+ *         if not PyDataType_HASFIELDS(child):             # <<<<<<<<<<<<<<
+ *             t = child.type_num
+ *             if end - f < 5:
+ */
+    __pyx_t_6 = (!PyDataType_HASFIELDS(__pyx_v_child));
+    if (__pyx_t_6) {
+
+      /* "numpy.pxd":817
+ * 
+ *         if not PyDataType_HASFIELDS(child):
+ *             t = child.type_num             # <<<<<<<<<<<<<<
+ *             if end - f < 5:
+ *                 raise RuntimeError(u"Format string allocated too short.")
+ */
+      __pyx_t_3 = PyInt_FromLong(__pyx_v_child->type_num); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 817; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_3);
+      __Pyx_XDECREF(__pyx_v_t);
+      __pyx_v_t = __pyx_t_3;
+      __pyx_t_3 = 0;
+
+      /* "numpy.pxd":818
+ *         if not PyDataType_HASFIELDS(child):
+ *             t = child.type_num
+ *             if end - f < 5:             # <<<<<<<<<<<<<<
+ *                 raise RuntimeError(u"Format string allocated too short.")
+ * 
+ */
+      __pyx_t_6 = ((__pyx_v_end - __pyx_v_f) < 5);
+      if (__pyx_t_6) {
+
+        /* "numpy.pxd":819
+ *             t = child.type_num
+ *             if end - f < 5:
+ *                 raise RuntimeError(u"Format string allocated too short.")             # <<<<<<<<<<<<<<
+ * 
+ *             # Until ticket #99 is fixed, use integers to avoid warnings
+ */
+        __pyx_t_3 = PyObject_Call(__pyx_builtin_RuntimeError, ((PyObject *)__pyx_k_tuple_37), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 819; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __Pyx_GOTREF(__pyx_t_3);
+        __Pyx_Raise(__pyx_t_3, 0, 0, 0);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        {__pyx_filename = __pyx_f[1]; __pyx_lineno = 819; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        goto __pyx_L10;
+      }
+      __pyx_L10:;
+
+      /* "numpy.pxd":822
+ * 
+ *             # Until ticket #99 is fixed, use integers to avoid warnings
+ *             if   t == NPY_BYTE:        f[0] =  98 #"b"             # <<<<<<<<<<<<<<
+ *             elif t == NPY_UBYTE:       f[0] =  66 #"B"
+ *             elif t == NPY_SHORT:       f[0] = 104 #"h"
+ */
+      __pyx_t_3 = PyInt_FromLong(NPY_BYTE); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 822; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_3);
+      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 822; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_5);
+      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 822; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+      if (__pyx_t_6) {
+        (__pyx_v_f[0]) = 98;
+        goto __pyx_L11;
+      }
+
+      /* "numpy.pxd":823
+ *             # Until ticket #99 is fixed, use integers to avoid warnings
+ *             if   t == NPY_BYTE:        f[0] =  98 #"b"
+ *             elif t == NPY_UBYTE:       f[0] =  66 #"B"             # <<<<<<<<<<<<<<
+ *             elif t == NPY_SHORT:       f[0] = 104 #"h"
+ *             elif t == NPY_USHORT:      f[0] =  72 #"H"
+ */
+      __pyx_t_5 = PyInt_FromLong(NPY_UBYTE); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 823; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_5);
+      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 823; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_3);
+      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 823; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+      if (__pyx_t_6) {
+        (__pyx_v_f[0]) = 66;
+        goto __pyx_L11;
+      }
+
+      /* "numpy.pxd":824
+ *             if   t == NPY_BYTE:        f[0] =  98 #"b"
+ *             elif t == NPY_UBYTE:       f[0] =  66 #"B"
+ *             elif t == NPY_SHORT:       f[0] = 104 #"h"             # <<<<<<<<<<<<<<
+ *             elif t == NPY_USHORT:      f[0] =  72 #"H"
+ *             elif t == NPY_INT:         f[0] = 105 #"i"
+ */
+      __pyx_t_3 = PyInt_FromLong(NPY_SHORT); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 824; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_3);
+      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 824; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_5);
+      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 824; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+      if (__pyx_t_6) {
+        (__pyx_v_f[0]) = 104;
+        goto __pyx_L11;
+      }
+
+      /* "numpy.pxd":825
+ *             elif t == NPY_UBYTE:       f[0] =  66 #"B"
+ *             elif t == NPY_SHORT:       f[0] = 104 #"h"
+ *             elif t == NPY_USHORT:      f[0] =  72 #"H"             # <<<<<<<<<<<<<<
+ *             elif t == NPY_INT:         f[0] = 105 #"i"
+ *             elif t == NPY_UINT:        f[0] =  73 #"I"
+ */
+      __pyx_t_5 = PyInt_FromLong(NPY_USHORT); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 825; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_5);
+      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 825; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_3);
+      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 825; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+      if (__pyx_t_6) {
+        (__pyx_v_f[0]) = 72;
+        goto __pyx_L11;
+      }
+
+      /* "numpy.pxd":826
+ *             elif t == NPY_SHORT:       f[0] = 104 #"h"
+ *             elif t == NPY_USHORT:      f[0] =  72 #"H"
+ *             elif t == NPY_INT:         f[0] = 105 #"i"             # <<<<<<<<<<<<<<
+ *             elif t == NPY_UINT:        f[0] =  73 #"I"
+ *             elif t == NPY_LONG:        f[0] = 108 #"l"
+ */
+      __pyx_t_3 = PyInt_FromLong(NPY_INT); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 826; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_3);
+      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 826; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_5);
+      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 826; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+      if (__pyx_t_6) {
+        (__pyx_v_f[0]) = 105;
+        goto __pyx_L11;
+      }
+
+      /* "numpy.pxd":827
+ *             elif t == NPY_USHORT:      f[0] =  72 #"H"
+ *             elif t == NPY_INT:         f[0] = 105 #"i"
+ *             elif t == NPY_UINT:        f[0] =  73 #"I"             # <<<<<<<<<<<<<<
+ *             elif t == NPY_LONG:        f[0] = 108 #"l"
+ *             elif t == NPY_ULONG:       f[0] = 76  #"L"
+ */
+      __pyx_t_5 = PyInt_FromLong(NPY_UINT); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 827; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_5);
+      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 827; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_3);
+      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 827; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+      if (__pyx_t_6) {
+        (__pyx_v_f[0]) = 73;
+        goto __pyx_L11;
+      }
+
+      /* "numpy.pxd":828
+ *             elif t == NPY_INT:         f[0] = 105 #"i"
+ *             elif t == NPY_UINT:        f[0] =  73 #"I"
+ *             elif t == NPY_LONG:        f[0] = 108 #"l"             # <<<<<<<<<<<<<<
+ *             elif t == NPY_ULONG:       f[0] = 76  #"L"
+ *             elif t == NPY_LONGLONG:    f[0] = 113 #"q"
+ */
+      __pyx_t_3 = PyInt_FromLong(NPY_LONG); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 828; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_3);
+      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 828; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_5);
+      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 828; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+      if (__pyx_t_6) {
+        (__pyx_v_f[0]) = 108;
+        goto __pyx_L11;
+      }
+
+      /* "numpy.pxd":829
+ *             elif t == NPY_UINT:        f[0] =  73 #"I"
+ *             elif t == NPY_LONG:        f[0] = 108 #"l"
+ *             elif t == NPY_ULONG:       f[0] = 76  #"L"             # <<<<<<<<<<<<<<
+ *             elif t == NPY_LONGLONG:    f[0] = 113 #"q"
+ *             elif t == NPY_ULONGLONG:   f[0] = 81  #"Q"
+ */
+      __pyx_t_5 = PyInt_FromLong(NPY_ULONG); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 829; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_5);
+      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 829; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_3);
+      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 829; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+      if (__pyx_t_6) {
+        (__pyx_v_f[0]) = 76;
+        goto __pyx_L11;
+      }
+
+      /* "numpy.pxd":830
+ *             elif t == NPY_LONG:        f[0] = 108 #"l"
+ *             elif t == NPY_ULONG:       f[0] = 76  #"L"
+ *             elif t == NPY_LONGLONG:    f[0] = 113 #"q"             # <<<<<<<<<<<<<<
+ *             elif t == NPY_ULONGLONG:   f[0] = 81  #"Q"
+ *             elif t == NPY_FLOAT:       f[0] = 102 #"f"
+ */
+      __pyx_t_3 = PyInt_FromLong(NPY_LONGLONG); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 830; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_3);
+      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 830; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_5);
+      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 830; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+      if (__pyx_t_6) {
+        (__pyx_v_f[0]) = 113;
+        goto __pyx_L11;
+      }
+
+      /* "numpy.pxd":831
+ *             elif t == NPY_ULONG:       f[0] = 76  #"L"
+ *             elif t == NPY_LONGLONG:    f[0] = 113 #"q"
+ *             elif t == NPY_ULONGLONG:   f[0] = 81  #"Q"             # <<<<<<<<<<<<<<
+ *             elif t == NPY_FLOAT:       f[0] = 102 #"f"
+ *             elif t == NPY_DOUBLE:      f[0] = 100 #"d"
+ */
+      __pyx_t_5 = PyInt_FromLong(NPY_ULONGLONG); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 831; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_5);
+      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 831; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_3);
+      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 831; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+      if (__pyx_t_6) {
+        (__pyx_v_f[0]) = 81;
+        goto __pyx_L11;
+      }
+
+      /* "numpy.pxd":832
+ *             elif t == NPY_LONGLONG:    f[0] = 113 #"q"
+ *             elif t == NPY_ULONGLONG:   f[0] = 81  #"Q"
+ *             elif t == NPY_FLOAT:       f[0] = 102 #"f"             # <<<<<<<<<<<<<<
+ *             elif t == NPY_DOUBLE:      f[0] = 100 #"d"
+ *             elif t == NPY_LONGDOUBLE:  f[0] = 103 #"g"
+ */
+      __pyx_t_3 = PyInt_FromLong(NPY_FLOAT); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 832; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_3);
+      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 832; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_5);
+      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 832; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+      if (__pyx_t_6) {
+        (__pyx_v_f[0]) = 102;
+        goto __pyx_L11;
+      }
+
+      /* "numpy.pxd":833
+ *             elif t == NPY_ULONGLONG:   f[0] = 81  #"Q"
+ *             elif t == NPY_FLOAT:       f[0] = 102 #"f"
+ *             elif t == NPY_DOUBLE:      f[0] = 100 #"d"             # <<<<<<<<<<<<<<
+ *             elif t == NPY_LONGDOUBLE:  f[0] = 103 #"g"
+ *             elif t == NPY_CFLOAT:      f[0] = 90; f[1] = 102; f += 1 # Zf
+ */
+      __pyx_t_5 = PyInt_FromLong(NPY_DOUBLE); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 833; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_5);
+      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 833; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_3);
+      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 833; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+      if (__pyx_t_6) {
+        (__pyx_v_f[0]) = 100;
+        goto __pyx_L11;
+      }
+
+      /* "numpy.pxd":834
+ *             elif t == NPY_FLOAT:       f[0] = 102 #"f"
+ *             elif t == NPY_DOUBLE:      f[0] = 100 #"d"
+ *             elif t == NPY_LONGDOUBLE:  f[0] = 103 #"g"             # <<<<<<<<<<<<<<
+ *             elif t == NPY_CFLOAT:      f[0] = 90; f[1] = 102; f += 1 # Zf
+ *             elif t == NPY_CDOUBLE:     f[0] = 90; f[1] = 100; f += 1 # Zd
+ */
+      __pyx_t_3 = PyInt_FromLong(NPY_LONGDOUBLE); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 834; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_3);
+      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 834; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_5);
+      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 834; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+      if (__pyx_t_6) {
+        (__pyx_v_f[0]) = 103;
+        goto __pyx_L11;
+      }
+
+      /* "numpy.pxd":835
+ *             elif t == NPY_DOUBLE:      f[0] = 100 #"d"
+ *             elif t == NPY_LONGDOUBLE:  f[0] = 103 #"g"
+ *             elif t == NPY_CFLOAT:      f[0] = 90; f[1] = 102; f += 1 # Zf             # <<<<<<<<<<<<<<
+ *             elif t == NPY_CDOUBLE:     f[0] = 90; f[1] = 100; f += 1 # Zd
+ *             elif t == NPY_CLONGDOUBLE: f[0] = 90; f[1] = 103; f += 1 # Zg
+ */
+      __pyx_t_5 = PyInt_FromLong(NPY_CFLOAT); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 835; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_5);
+      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 835; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_3);
+      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 835; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+      if (__pyx_t_6) {
+        (__pyx_v_f[0]) = 90;
+        (__pyx_v_f[1]) = 102;
+        __pyx_v_f = (__pyx_v_f + 1);
+        goto __pyx_L11;
+      }
+
+      /* "numpy.pxd":836
+ *             elif t == NPY_LONGDOUBLE:  f[0] = 103 #"g"
+ *             elif t == NPY_CFLOAT:      f[0] = 90; f[1] = 102; f += 1 # Zf
+ *             elif t == NPY_CDOUBLE:     f[0] = 90; f[1] = 100; f += 1 # Zd             # <<<<<<<<<<<<<<
+ *             elif t == NPY_CLONGDOUBLE: f[0] = 90; f[1] = 103; f += 1 # Zg
+ *             elif t == NPY_OBJECT:      f[0] = 79 #"O"
+ */
+      __pyx_t_3 = PyInt_FromLong(NPY_CDOUBLE); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 836; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_3);
+      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 836; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_5);
+      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 836; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+      if (__pyx_t_6) {
+        (__pyx_v_f[0]) = 90;
+        (__pyx_v_f[1]) = 100;
+        __pyx_v_f = (__pyx_v_f + 1);
+        goto __pyx_L11;
+      }
+
+      /* "numpy.pxd":837
+ *             elif t == NPY_CFLOAT:      f[0] = 90; f[1] = 102; f += 1 # Zf
+ *             elif t == NPY_CDOUBLE:     f[0] = 90; f[1] = 100; f += 1 # Zd
+ *             elif t == NPY_CLONGDOUBLE: f[0] = 90; f[1] = 103; f += 1 # Zg             # <<<<<<<<<<<<<<
+ *             elif t == NPY_OBJECT:      f[0] = 79 #"O"
+ *             else:
+ */
+      __pyx_t_5 = PyInt_FromLong(NPY_CLONGDOUBLE); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 837; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_5);
+      __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 837; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_3);
+      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 837; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+      if (__pyx_t_6) {
+        (__pyx_v_f[0]) = 90;
+        (__pyx_v_f[1]) = 103;
+        __pyx_v_f = (__pyx_v_f + 1);
+        goto __pyx_L11;
+      }
+
+      /* "numpy.pxd":838
+ *             elif t == NPY_CDOUBLE:     f[0] = 90; f[1] = 100; f += 1 # Zd
+ *             elif t == NPY_CLONGDOUBLE: f[0] = 90; f[1] = 103; f += 1 # Zg
+ *             elif t == NPY_OBJECT:      f[0] = 79 #"O"             # <<<<<<<<<<<<<<
+ *             else:
+ *                 raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t)
+ */
+      __pyx_t_3 = PyInt_FromLong(NPY_OBJECT); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 838; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_3);
+      __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 838; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_5);
+      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 838; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+      if (__pyx_t_6) {
+        (__pyx_v_f[0]) = 79;
+        goto __pyx_L11;
+      }
+      /*else*/ {
+
+        /* "numpy.pxd":840
+ *             elif t == NPY_OBJECT:      f[0] = 79 #"O"
+ *             else:
+ *                 raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t)             # <<<<<<<<<<<<<<
+ *             f += 1
+ *         else:
+ */
+        __pyx_t_5 = PyNumber_Remainder(((PyObject *)__pyx_kp_u_32), __pyx_v_t); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 840; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __Pyx_GOTREF(((PyObject *)__pyx_t_5));
+        __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 840; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __Pyx_GOTREF(((PyObject *)__pyx_t_3));
+        PyTuple_SET_ITEM(__pyx_t_3, 0, ((PyObject *)__pyx_t_5));
+        __Pyx_GIVEREF(((PyObject *)__pyx_t_5));
+        __pyx_t_5 = 0;
+        __pyx_t_5 = PyObject_Call(__pyx_builtin_ValueError, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 840; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __Pyx_GOTREF(__pyx_t_5);
+        __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
+        __Pyx_Raise(__pyx_t_5, 0, 0, 0);
+        __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+        {__pyx_filename = __pyx_f[1]; __pyx_lineno = 840; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      }
+      __pyx_L11:;
+
+      /* "numpy.pxd":841
+ *             else:
+ *                 raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t)
+ *             f += 1             # <<<<<<<<<<<<<<
+ *         else:
+ *             # Cython ignores struct boundary information ("T{...}"),
+ */
+      __pyx_v_f = (__pyx_v_f + 1);
+      goto __pyx_L9;
+    }
+    /*else*/ {
+
+      /* "numpy.pxd":845
+ *             # Cython ignores struct boundary information ("T{...}"),
+ *             # so don't output it
+ *             f = _util_dtypestring(child, f, end, offset)             # <<<<<<<<<<<<<<
+ *     return f
+ * 
+ */
+      __pyx_t_11 = __pyx_f_5numpy__util_dtypestring(__pyx_v_child, __pyx_v_f, __pyx_v_end, __pyx_v_offset); if (unlikely(__pyx_t_11 == NULL)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 845; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_v_f = __pyx_t_11;
+    }
+    __pyx_L9:;
+  }
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+
+  /* "numpy.pxd":846
+ *             # so don't output it
+ *             f = _util_dtypestring(child, f, end, offset)
+ *     return f             # <<<<<<<<<<<<<<
+ * 
+ * 
+ */
+  __pyx_r = __pyx_v_f;
+  goto __pyx_L0;
+
+  __pyx_r = 0;
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_XDECREF(__pyx_t_5);
+  __Pyx_AddTraceback("numpy._util_dtypestring", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
+  __Pyx_XDECREF((PyObject *)__pyx_v_child);
+  __Pyx_XDECREF(__pyx_v_fields);
+  __Pyx_XDECREF(__pyx_v_childname);
+  __Pyx_XDECREF(__pyx_v_new_offset);
+  __Pyx_XDECREF(__pyx_v_t);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "numpy.pxd":961
+ * 
+ * 
+ * cdef inline void set_array_base(ndarray arr, object base):             # <<<<<<<<<<<<<<
+ *      cdef PyObject* baseptr
+ *      if base is None:
+ */
+
+static CYTHON_INLINE void __pyx_f_5numpy_set_array_base(PyArrayObject *__pyx_v_arr, PyObject *__pyx_v_base) {
+  PyObject *__pyx_v_baseptr;
+  __Pyx_RefNannyDeclarations
+  int __pyx_t_1;
+  __Pyx_RefNannySetupContext("set_array_base");
+
+  /* "numpy.pxd":963
+ * cdef inline void set_array_base(ndarray arr, object base):
+ *      cdef PyObject* baseptr
+ *      if base is None:             # <<<<<<<<<<<<<<
+ *          baseptr = NULL
+ *      else:
+ */
+  __pyx_t_1 = (__pyx_v_base == Py_None);
+  if (__pyx_t_1) {
+
+    /* "numpy.pxd":964
+ *      cdef PyObject* baseptr
+ *      if base is None:
+ *          baseptr = NULL             # <<<<<<<<<<<<<<
+ *      else:
+ *          Py_INCREF(base) # important to do this before decref below!
+ */
+    __pyx_v_baseptr = NULL;
+    goto __pyx_L3;
+  }
+  /*else*/ {
+
+    /* "numpy.pxd":966
+ *          baseptr = NULL
+ *      else:
+ *          Py_INCREF(base) # important to do this before decref below!             # <<<<<<<<<<<<<<
+ *          baseptr = <PyObject*>base
+ *      Py_XDECREF(arr.base)
+ */
+    Py_INCREF(__pyx_v_base);
+
+    /* "numpy.pxd":967
+ *      else:
+ *          Py_INCREF(base) # important to do this before decref below!
+ *          baseptr = <PyObject*>base             # <<<<<<<<<<<<<<
+ *      Py_XDECREF(arr.base)
+ *      arr.base = baseptr
+ */
+    __pyx_v_baseptr = ((PyObject *)__pyx_v_base);
+  }
+  __pyx_L3:;
+
+  /* "numpy.pxd":968
+ *          Py_INCREF(base) # important to do this before decref below!
+ *          baseptr = <PyObject*>base
+ *      Py_XDECREF(arr.base)             # <<<<<<<<<<<<<<
+ *      arr.base = baseptr
+ * 
+ */
+  Py_XDECREF(__pyx_v_arr->base);
+
+  /* "numpy.pxd":969
+ *          baseptr = <PyObject*>base
+ *      Py_XDECREF(arr.base)
+ *      arr.base = baseptr             # <<<<<<<<<<<<<<
+ * 
+ * cdef inline object get_array_base(ndarray arr):
+ */
+  __pyx_v_arr->base = __pyx_v_baseptr;
+
+  __Pyx_RefNannyFinishContext();
+}
+
+/* "numpy.pxd":971
+ *      arr.base = baseptr
+ * 
+ * cdef inline object get_array_base(ndarray arr):             # <<<<<<<<<<<<<<
+ *     if arr.base is NULL:
+ *         return None
+ */
+
+static CYTHON_INLINE PyObject *__pyx_f_5numpy_get_array_base(PyArrayObject *__pyx_v_arr) {
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  int __pyx_t_1;
+  __Pyx_RefNannySetupContext("get_array_base");
+
+  /* "numpy.pxd":972
+ * 
+ * cdef inline object get_array_base(ndarray arr):
+ *     if arr.base is NULL:             # <<<<<<<<<<<<<<
+ *         return None
+ *     else:
+ */
+  __pyx_t_1 = (__pyx_v_arr->base == NULL);
+  if (__pyx_t_1) {
+
+    /* "numpy.pxd":973
+ * cdef inline object get_array_base(ndarray arr):
+ *     if arr.base is NULL:
+ *         return None             # <<<<<<<<<<<<<<
+ *     else:
+ *         return <object>arr.base
+ */
+    __Pyx_XDECREF(__pyx_r);
+    __Pyx_INCREF(Py_None);
+    __pyx_r = Py_None;
+    goto __pyx_L0;
+    goto __pyx_L3;
+  }
+  /*else*/ {
+
+    /* "numpy.pxd":975
+ *         return None
+ *     else:
+ *         return <object>arr.base             # <<<<<<<<<<<<<<
+ */
+    __Pyx_XDECREF(__pyx_r);
+    __Pyx_INCREF(((PyObject *)__pyx_v_arr->base));
+    __pyx_r = ((PyObject *)__pyx_v_arr->base);
+    goto __pyx_L0;
+  }
+  __pyx_L3:;
+
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  __pyx_L0:;
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static PyMethodDef __pyx_methods[] = {
+  {0, 0, 0, 0}
+};
+
+#if PY_MAJOR_VERSION >= 3
+static struct PyModuleDef __pyx_moduledef = {
+    PyModuleDef_HEAD_INIT,
+    __Pyx_NAMESTR("sofa_time"),
+    0, /* m_doc */
+    -1, /* m_size */
+    __pyx_methods /* m_methods */,
+    NULL, /* m_reload */
+    NULL, /* m_traverse */
+    NULL, /* m_clear */
+    NULL /* m_free */
+};
+#endif
+
+static __Pyx_StringTabEntry __pyx_string_tab[] = {
+  {&__pyx_kp_s_10, __pyx_k_10, sizeof(__pyx_k_10), 0, 0, 1, 0},
+  {&__pyx_kp_s_11, __pyx_k_11, sizeof(__pyx_k_11), 0, 0, 1, 0},
+  {&__pyx_kp_s_12, __pyx_k_12, sizeof(__pyx_k_12), 0, 0, 1, 0},
+  {&__pyx_kp_s_13, __pyx_k_13, sizeof(__pyx_k_13), 0, 0, 1, 0},
+  {&__pyx_kp_s_14, __pyx_k_14, sizeof(__pyx_k_14), 0, 0, 1, 0},
+  {&__pyx_kp_s_15, __pyx_k_15, sizeof(__pyx_k_15), 0, 0, 1, 0},
+  {&__pyx_kp_s_16, __pyx_k_16, sizeof(__pyx_k_16), 0, 0, 1, 0},
+  {&__pyx_kp_s_17, __pyx_k_17, sizeof(__pyx_k_17), 0, 0, 1, 0},
+  {&__pyx_kp_s_18, __pyx_k_18, sizeof(__pyx_k_18), 0, 0, 1, 0},
+  {&__pyx_kp_s_19, __pyx_k_19, sizeof(__pyx_k_19), 0, 0, 1, 0},
+  {&__pyx_kp_s_20, __pyx_k_20, sizeof(__pyx_k_20), 0, 0, 1, 0},
+  {&__pyx_kp_s_21, __pyx_k_21, sizeof(__pyx_k_21), 0, 0, 1, 0},
+  {&__pyx_kp_s_22, __pyx_k_22, sizeof(__pyx_k_22), 0, 0, 1, 0},
+  {&__pyx_kp_s_24, __pyx_k_24, sizeof(__pyx_k_24), 0, 0, 1, 0},
+  {&__pyx_kp_s_25, __pyx_k_25, sizeof(__pyx_k_25), 0, 0, 1, 0},
+  {&__pyx_kp_u_26, __pyx_k_26, sizeof(__pyx_k_26), 0, 1, 0, 0},
+  {&__pyx_kp_u_28, __pyx_k_28, sizeof(__pyx_k_28), 0, 1, 0, 0},
+  {&__pyx_kp_s_3, __pyx_k_3, sizeof(__pyx_k_3), 0, 0, 1, 0},
+  {&__pyx_kp_u_30, __pyx_k_30, sizeof(__pyx_k_30), 0, 1, 0, 0},
+  {&__pyx_kp_u_32, __pyx_k_32, sizeof(__pyx_k_32), 0, 1, 0, 0},
+  {&__pyx_kp_u_33, __pyx_k_33, sizeof(__pyx_k_33), 0, 1, 0, 0},
+  {&__pyx_kp_u_36, __pyx_k_36, sizeof(__pyx_k_36), 0, 1, 0, 0},
+  {&__pyx_kp_s_38, __pyx_k_38, sizeof(__pyx_k_38), 0, 0, 1, 0},
+  {&__pyx_n_s_39, __pyx_k_39, sizeof(__pyx_k_39), 0, 0, 1, 1},
+  {&__pyx_kp_s_4, __pyx_k_4, sizeof(__pyx_k_4), 0, 0, 1, 0},
+  {&__pyx_kp_s_5, __pyx_k_5, sizeof(__pyx_k_5), 0, 0, 1, 0},
+  {&__pyx_kp_s_6, __pyx_k_6, sizeof(__pyx_k_6), 0, 0, 1, 0},
+  {&__pyx_kp_s_7, __pyx_k_7, sizeof(__pyx_k_7), 0, 0, 1, 0},
+  {&__pyx_kp_s_8, __pyx_k_8, sizeof(__pyx_k_8), 0, 0, 1, 0},
+  {&__pyx_kp_s_9, __pyx_k_9, sizeof(__pyx_k_9), 0, 0, 1, 0},
+  {&__pyx_n_s__DUBIOUS, __pyx_k__DUBIOUS, sizeof(__pyx_k__DUBIOUS), 0, 0, 1, 1},
+  {&__pyx_n_s__RuntimeError, __pyx_k__RuntimeError, sizeof(__pyx_k__RuntimeError), 0, 0, 1, 1},
+  {&__pyx_n_s__ValueError, __pyx_k__ValueError, sizeof(__pyx_k__ValueError), 0, 0, 1, 1},
+  {&__pyx_n_s____main__, __pyx_k____main__, sizeof(__pyx_k____main__), 0, 0, 1, 1},
+  {&__pyx_n_s____test__, __pyx_k____test__, sizeof(__pyx_k____test__), 0, 0, 1, 1},
+  {&__pyx_n_s__asec, __pyx_k__asec, sizeof(__pyx_k__asec), 0, 0, 1, 1},
+  {&__pyx_n_s__besselian_epoch_jd, __pyx_k__besselian_epoch_jd, sizeof(__pyx_k__besselian_epoch_jd), 0, 0, 1, 1},
+  {&__pyx_n_s__cal2jd, __pyx_k__cal2jd, sizeof(__pyx_k__cal2jd), 0, 0, 1, 1},
+  {&__pyx_n_s__check_return, __pyx_k__check_return, sizeof(__pyx_k__check_return), 0, 0, 1, 1},
+  {&__pyx_n_s__d1, __pyx_k__d1, sizeof(__pyx_k__d1), 0, 0, 1, 1},
+  {&__pyx_n_s__d2, __pyx_k__d2, sizeof(__pyx_k__d2), 0, 0, 1, 1},
+  {&__pyx_n_s__d_tai_utc, __pyx_k__d_tai_utc, sizeof(__pyx_k__d_tai_utc), 0, 0, 1, 1},
+  {&__pyx_n_s__d_tdb_tt, __pyx_k__d_tdb_tt, sizeof(__pyx_k__d_tdb_tt), 0, 0, 1, 1},
+  {&__pyx_n_s__djm, __pyx_k__djm, sizeof(__pyx_k__djm), 0, 0, 1, 1},
+  {&__pyx_n_s__djm0, __pyx_k__djm0, sizeof(__pyx_k__djm0), 0, 0, 1, 1},
+  {&__pyx_n_s__double, __pyx_k__double, sizeof(__pyx_k__double), 0, 0, 1, 1},
+  {&__pyx_n_s__dt, __pyx_k__dt, sizeof(__pyx_k__dt), 0, 0, 1, 1},
+  {&__pyx_n_s__dtf_jd, __pyx_k__dtf_jd, sizeof(__pyx_k__dtf_jd), 0, 0, 1, 1},
+  {&__pyx_n_s__dtype, __pyx_k__dtype, sizeof(__pyx_k__dtype), 0, 0, 1, 1},
+  {&__pyx_n_s__elong, __pyx_k__elong, sizeof(__pyx_k__elong), 0, 0, 1, 1},
+  {&__pyx_n_s__empty, __pyx_k__empty, sizeof(__pyx_k__empty), 0, 0, 1, 1},
+  {&__pyx_n_s__errors, __pyx_k__errors, sizeof(__pyx_k__errors), 0, 0, 1, 1},
+  {&__pyx_n_s__fd, __pyx_k__fd, sizeof(__pyx_k__fd), 0, 0, 1, 1},
+  {&__pyx_n_s__format, __pyx_k__format, sizeof(__pyx_k__format), 0, 0, 1, 1},
+  {&__pyx_n_s__func_name, __pyx_k__func_name, sizeof(__pyx_k__func_name), 0, 0, 1, 1},
+  {&__pyx_n_s__height, __pyx_k__height, sizeof(__pyx_k__height), 0, 0, 1, 1},
+  {&__pyx_n_s__iamin, __pyx_k__iamin, sizeof(__pyx_k__iamin), 0, 0, 1, 1},
+  {&__pyx_n_s__iauAf2a, __pyx_k__iauAf2a, sizeof(__pyx_k__iauAf2a), 0, 0, 1, 1},
+  {&__pyx_n_s__iauCal2jd, __pyx_k__iauCal2jd, sizeof(__pyx_k__iauCal2jd), 0, 0, 1, 1},
+  {&__pyx_n_s__iauD2dtf, __pyx_k__iauD2dtf, sizeof(__pyx_k__iauD2dtf), 0, 0, 1, 1},
+  {&__pyx_n_s__iauDat, __pyx_k__iauDat, sizeof(__pyx_k__iauDat), 0, 0, 1, 1},
+  {&__pyx_n_s__iauDtf2d, __pyx_k__iauDtf2d, sizeof(__pyx_k__iauDtf2d), 0, 0, 1, 1},
+  {&__pyx_n_s__iauGd2gc, __pyx_k__iauGd2gc, sizeof(__pyx_k__iauGd2gc), 0, 0, 1, 1},
+  {&__pyx_n_s__iauTaitt, __pyx_k__iauTaitt, sizeof(__pyx_k__iauTaitt), 0, 0, 1, 1},
+  {&__pyx_n_s__iauTaiut1, __pyx_k__iauTaiut1, sizeof(__pyx_k__iauTaiut1), 0, 0, 1, 1},
+  {&__pyx_n_s__iauTaiutc, __pyx_k__iauTaiutc, sizeof(__pyx_k__iauTaiutc), 0, 0, 1, 1},
+  {&__pyx_n_s__iauTcbtdb, __pyx_k__iauTcbtdb, sizeof(__pyx_k__iauTcbtdb), 0, 0, 1, 1},
+  {&__pyx_n_s__iauTcgtt, __pyx_k__iauTcgtt, sizeof(__pyx_k__iauTcgtt), 0, 0, 1, 1},
+  {&__pyx_n_s__iauTdbtcb, __pyx_k__iauTdbtcb, sizeof(__pyx_k__iauTdbtcb), 0, 0, 1, 1},
+  {&__pyx_n_s__iauTdbtt, __pyx_k__iauTdbtt, sizeof(__pyx_k__iauTdbtt), 0, 0, 1, 1},
+  {&__pyx_n_s__iauTttai, __pyx_k__iauTttai, sizeof(__pyx_k__iauTttai), 0, 0, 1, 1},
+  {&__pyx_n_s__iauTttcg, __pyx_k__iauTttcg, sizeof(__pyx_k__iauTttcg), 0, 0, 1, 1},
+  {&__pyx_n_s__iauTttdb, __pyx_k__iauTttdb, sizeof(__pyx_k__iauTttdb), 0, 0, 1, 1},
+  {&__pyx_n_s__iauTtut1, __pyx_k__iauTtut1, sizeof(__pyx_k__iauTtut1), 0, 0, 1, 1},
+  {&__pyx_n_s__iauUt1tai, __pyx_k__iauUt1tai, sizeof(__pyx_k__iauUt1tai), 0, 0, 1, 1},
+  {&__pyx_n_s__iauUt1tt, __pyx_k__iauUt1tt, sizeof(__pyx_k__iauUt1tt), 0, 0, 1, 1},
+  {&__pyx_n_s__iauUt1utc, __pyx_k__iauUt1utc, sizeof(__pyx_k__iauUt1utc), 0, 0, 1, 1},
+  {&__pyx_n_s__iauUtctai, __pyx_k__iauUtctai, sizeof(__pyx_k__iauUtctai), 0, 0, 1, 1},
+  {&__pyx_n_s__iauUtcut1, __pyx_k__iauUtcut1, sizeof(__pyx_k__iauUtcut1), 0, 0, 1, 1},
+  {&__pyx_n_s__iau_af2a, __pyx_k__iau_af2a, sizeof(__pyx_k__iau_af2a), 0, 0, 1, 1},
+  {&__pyx_n_s__iau_gd2gc, __pyx_k__iau_gd2gc, sizeof(__pyx_k__iau_gd2gc), 0, 0, 1, 1},
+  {&__pyx_n_s__id, __pyx_k__id, sizeof(__pyx_k__id), 0, 0, 1, 1},
+  {&__pyx_n_s__ideg, __pyx_k__ideg, sizeof(__pyx_k__ideg), 0, 0, 1, 1},
+  {&__pyx_n_s__ihr, __pyx_k__ihr, sizeof(__pyx_k__ihr), 0, 0, 1, 1},
+  {&__pyx_n_s__im, __pyx_k__im, sizeof(__pyx_k__im), 0, 0, 1, 1},
+  {&__pyx_n_s__imn, __pyx_k__imn, sizeof(__pyx_k__imn), 0, 0, 1, 1},
+  {&__pyx_n_s__in1, __pyx_k__in1, sizeof(__pyx_k__in1), 0, 0, 1, 1},
+  {&__pyx_n_s__in2, __pyx_k__in2, sizeof(__pyx_k__in2), 0, 0, 1, 1},
+  {&__pyx_n_s__intc, __pyx_k__intc, sizeof(__pyx_k__intc), 0, 0, 1, 1},
+  {&__pyx_n_s__iy, __pyx_k__iy, sizeof(__pyx_k__iy), 0, 0, 1, 1},
+  {&__pyx_n_s__jd1, __pyx_k__jd1, sizeof(__pyx_k__jd1), 0, 0, 1, 1},
+  {&__pyx_n_s__jd2, __pyx_k__jd2, sizeof(__pyx_k__jd2), 0, 0, 1, 1},
+  {&__pyx_n_s__jd_besselian_epoch, __pyx_k__jd_besselian_epoch, sizeof(__pyx_k__jd_besselian_epoch), 0, 0, 1, 1},
+  {&__pyx_n_s__jd_dtf, __pyx_k__jd_dtf, sizeof(__pyx_k__jd_dtf), 0, 0, 1, 1},
+  {&__pyx_n_s__jd_julian_epoch, __pyx_k__jd_julian_epoch, sizeof(__pyx_k__jd_julian_epoch), 0, 0, 1, 1},
+  {&__pyx_n_s__julian_epoch_jd, __pyx_k__julian_epoch_jd, sizeof(__pyx_k__julian_epoch_jd), 0, 0, 1, 1},
+  {&__pyx_n_s__n, __pyx_k__n, sizeof(__pyx_k__n), 0, 0, 1, 1},
+  {&__pyx_n_s__ndp, __pyx_k__ndp, sizeof(__pyx_k__ndp), 0, 0, 1, 1},
+  {&__pyx_n_s__np, __pyx_k__np, sizeof(__pyx_k__np), 0, 0, 1, 1},
+  {&__pyx_n_s__numpy, __pyx_k__numpy, sizeof(__pyx_k__numpy), 0, 0, 1, 1},
+  {&__pyx_n_s__ord, __pyx_k__ord, sizeof(__pyx_k__ord), 0, 0, 1, 1},
+  {&__pyx_n_s__phi, __pyx_k__phi, sizeof(__pyx_k__phi), 0, 0, 1, 1},
+  {&__pyx_n_s__range, __pyx_k__range, sizeof(__pyx_k__range), 0, 0, 1, 1},
+  {&__pyx_n_s__ret, __pyx_k__ret, sizeof(__pyx_k__ret), 0, 0, 1, 1},
+  {&__pyx_n_s__scale, __pyx_k__scale, sizeof(__pyx_k__scale), 0, 0, 1, 1},
+  {&__pyx_n_s__sec, __pyx_k__sec, sizeof(__pyx_k__sec), 0, 0, 1, 1},
+  {&__pyx_n_s__sign, __pyx_k__sign, sizeof(__pyx_k__sign), 0, 0, 1, 1},
+  {&__pyx_n_s__tai_tt, __pyx_k__tai_tt, sizeof(__pyx_k__tai_tt), 0, 0, 1, 1},
+  {&__pyx_n_s__tai_ut1, __pyx_k__tai_ut1, sizeof(__pyx_k__tai_ut1), 0, 0, 1, 1},
+  {&__pyx_n_s__tai_utc, __pyx_k__tai_utc, sizeof(__pyx_k__tai_utc), 0, 0, 1, 1},
+  {&__pyx_n_s__tcb_tdb, __pyx_k__tcb_tdb, sizeof(__pyx_k__tcb_tdb), 0, 0, 1, 1},
+  {&__pyx_n_s__tcg_tt, __pyx_k__tcg_tt, sizeof(__pyx_k__tcg_tt), 0, 0, 1, 1},
+  {&__pyx_n_s__tdb_tcb, __pyx_k__tdb_tcb, sizeof(__pyx_k__tdb_tcb), 0, 0, 1, 1},
+  {&__pyx_n_s__tdb_tt, __pyx_k__tdb_tt, sizeof(__pyx_k__tdb_tt), 0, 0, 1, 1},
+  {&__pyx_n_s__tt_tai, __pyx_k__tt_tai, sizeof(__pyx_k__tt_tai), 0, 0, 1, 1},
+  {&__pyx_n_s__tt_tcg, __pyx_k__tt_tcg, sizeof(__pyx_k__tt_tcg), 0, 0, 1, 1},
+  {&__pyx_n_s__tt_tdb, __pyx_k__tt_tdb, sizeof(__pyx_k__tt_tdb), 0, 0, 1, 1},
+  {&__pyx_n_s__tt_ut1, __pyx_k__tt_ut1, sizeof(__pyx_k__tt_ut1), 0, 0, 1, 1},
+  {&__pyx_n_s__u, __pyx_k__u, sizeof(__pyx_k__u), 0, 0, 1, 1},
+  {&__pyx_n_s__ut, __pyx_k__ut, sizeof(__pyx_k__ut), 0, 0, 1, 1},
+  {&__pyx_n_s__ut1_tai, __pyx_k__ut1_tai, sizeof(__pyx_k__ut1_tai), 0, 0, 1, 1},
+  {&__pyx_n_s__ut1_tt, __pyx_k__ut1_tt, sizeof(__pyx_k__ut1_tt), 0, 0, 1, 1},
+  {&__pyx_n_s__ut1_utc, __pyx_k__ut1_utc, sizeof(__pyx_k__ut1_utc), 0, 0, 1, 1},
+  {&__pyx_n_s__utc_tai, __pyx_k__utc_tai, sizeof(__pyx_k__utc_tai), 0, 0, 1, 1},
+  {&__pyx_n_s__utc_ut1, __pyx_k__utc_ut1, sizeof(__pyx_k__utc_ut1), 0, 0, 1, 1},
+  {&__pyx_n_s__v, __pyx_k__v, sizeof(__pyx_k__v), 0, 0, 1, 1},
+  {&__pyx_n_s__warn, __pyx_k__warn, sizeof(__pyx_k__warn), 0, 0, 1, 1},
+  {&__pyx_n_s__warnings, __pyx_k__warnings, sizeof(__pyx_k__warnings), 0, 0, 1, 1},
+  {&__pyx_n_s__warns, __pyx_k__warns, sizeof(__pyx_k__warns), 0, 0, 1, 1},
+  {0, 0, 0, 0, 0, 0, 0}
+};
+static int __Pyx_InitCachedBuiltins(void) {
+  __pyx_builtin_ValueError = __Pyx_GetName(__pyx_b, __pyx_n_s__ValueError); if (!__pyx_builtin_ValueError) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 57; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_builtin_range = __Pyx_GetName(__pyx_b, __pyx_n_s__range); if (!__pyx_builtin_range) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 109; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_builtin_ord = __Pyx_GetName(__pyx_b, __pyx_n_s__ord); if (!__pyx_builtin_ord) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1262; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_builtin_RuntimeError = __Pyx_GetName(__pyx_b, __pyx_n_s__RuntimeError); if (!__pyx_builtin_RuntimeError) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 795; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  return 0;
+  __pyx_L1_error:;
+  return -1;
+}
+
+static int __Pyx_InitCachedConstants(void) {
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__Pyx_InitCachedConstants");
+
+  /* "astropy/time/sofa_time.pyx":1317
+ *     **  4) The inverse transformation is performed in the function iauGc2gd.
+ *     """
+ *     cdef np.ndarray[double, ndim=1] xyz = np.empty(3, dtype=np.double)             # <<<<<<<<<<<<<<
+ * 
+ *     errs = {-1: 'illegal identifier',
+ */
+  __pyx_k_tuple_23 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_23)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1317; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_k_tuple_23));
+  __Pyx_INCREF(__pyx_int_3);
+  PyTuple_SET_ITEM(__pyx_k_tuple_23, 0, __pyx_int_3);
+  __Pyx_GIVEREF(__pyx_int_3);
+  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_23));
+
+  /* "numpy.pxd":211
+ *             if ((flags & pybuf.PyBUF_C_CONTIGUOUS == pybuf.PyBUF_C_CONTIGUOUS)
+ *                 and not PyArray_CHKFLAGS(self, NPY_C_CONTIGUOUS)):
+ *                 raise ValueError(u"ndarray is not C contiguous")             # <<<<<<<<<<<<<<
+ * 
+ *             if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS)
+ */
+  __pyx_k_tuple_27 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_27)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 211; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_k_tuple_27));
+  __Pyx_INCREF(((PyObject *)__pyx_kp_u_26));
+  PyTuple_SET_ITEM(__pyx_k_tuple_27, 0, ((PyObject *)__pyx_kp_u_26));
+  __Pyx_GIVEREF(((PyObject *)__pyx_kp_u_26));
+  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_27));
+
+  /* "numpy.pxd":215
+ *             if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS)
+ *                 and not PyArray_CHKFLAGS(self, NPY_F_CONTIGUOUS)):
+ *                 raise ValueError(u"ndarray is not Fortran contiguous")             # <<<<<<<<<<<<<<
+ * 
+ *             info.buf = PyArray_DATA(self)
+ */
+  __pyx_k_tuple_29 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_29)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 215; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_k_tuple_29));
+  __Pyx_INCREF(((PyObject *)__pyx_kp_u_28));
+  PyTuple_SET_ITEM(__pyx_k_tuple_29, 0, ((PyObject *)__pyx_kp_u_28));
+  __Pyx_GIVEREF(((PyObject *)__pyx_kp_u_28));
+  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_29));
+
+  /* "numpy.pxd":253
+ *                 if ((descr.byteorder == '>' and little_endian) or
+ *                     (descr.byteorder == '<' and not little_endian)):
+ *                     raise ValueError(u"Non-native byte order not supported")             # <<<<<<<<<<<<<<
+ *                 if   t == NPY_BYTE:        f = "b"
+ *                 elif t == NPY_UBYTE:       f = "B"
+ */
+  __pyx_k_tuple_31 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_31)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 253; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_k_tuple_31));
+  __Pyx_INCREF(((PyObject *)__pyx_kp_u_30));
+  PyTuple_SET_ITEM(__pyx_k_tuple_31, 0, ((PyObject *)__pyx_kp_u_30));
+  __Pyx_GIVEREF(((PyObject *)__pyx_kp_u_30));
+  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_31));
+
+  /* "numpy.pxd":795
+ * 
+ *         if (end - f) - (new_offset - offset[0]) < 15:
+ *             raise RuntimeError(u"Format string allocated too short, see comment in numpy.pxd")             # <<<<<<<<<<<<<<
+ * 
+ *         if ((child.byteorder == '>' and little_endian) or
+ */
+  __pyx_k_tuple_34 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_34)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 795; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_k_tuple_34));
+  __Pyx_INCREF(((PyObject *)__pyx_kp_u_33));
+  PyTuple_SET_ITEM(__pyx_k_tuple_34, 0, ((PyObject *)__pyx_kp_u_33));
+  __Pyx_GIVEREF(((PyObject *)__pyx_kp_u_33));
+  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_34));
+
+  /* "numpy.pxd":799
+ *         if ((child.byteorder == '>' and little_endian) or
+ *             (child.byteorder == '<' and not little_endian)):
+ *             raise ValueError(u"Non-native byte order not supported")             # <<<<<<<<<<<<<<
+ *             # One could encode it in the format string and have Cython
+ *             # complain instead, BUT: < and > in format strings also imply
+ */
+  __pyx_k_tuple_35 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_35)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 799; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_k_tuple_35));
+  __Pyx_INCREF(((PyObject *)__pyx_kp_u_30));
+  PyTuple_SET_ITEM(__pyx_k_tuple_35, 0, ((PyObject *)__pyx_kp_u_30));
+  __Pyx_GIVEREF(((PyObject *)__pyx_kp_u_30));
+  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_35));
+
+  /* "numpy.pxd":819
+ *             t = child.type_num
+ *             if end - f < 5:
+ *                 raise RuntimeError(u"Format string allocated too short.")             # <<<<<<<<<<<<<<
+ * 
+ *             # Until ticket #99 is fixed, use integers to avoid warnings
+ */
+  __pyx_k_tuple_37 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_37)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 819; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_k_tuple_37));
+  __Pyx_INCREF(((PyObject *)__pyx_kp_u_36));
+  PyTuple_SET_ITEM(__pyx_k_tuple_37, 0, ((PyObject *)__pyx_kp_u_36));
+  __Pyx_GIVEREF(((PyObject *)__pyx_kp_u_36));
+  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_37));
+  __Pyx_RefNannyFinishContext();
+  return 0;
+  __pyx_L1_error:;
+  __Pyx_RefNannyFinishContext();
+  return -1;
+}
+
+static int __Pyx_InitGlobals(void) {
+  if (__Pyx_InitStrings(__pyx_string_tab) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
+  __pyx_int_0 = PyInt_FromLong(0); if (unlikely(!__pyx_int_0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
+  __pyx_int_1 = PyInt_FromLong(1); if (unlikely(!__pyx_int_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
+  __pyx_int_2 = PyInt_FromLong(2); if (unlikely(!__pyx_int_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
+  __pyx_int_3 = PyInt_FromLong(3); if (unlikely(!__pyx_int_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
+  __pyx_int_4 = PyInt_FromLong(4); if (unlikely(!__pyx_int_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
+  __pyx_int_neg_1 = PyInt_FromLong(-1); if (unlikely(!__pyx_int_neg_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
+  __pyx_int_neg_2 = PyInt_FromLong(-2); if (unlikely(!__pyx_int_neg_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
+  __pyx_int_neg_3 = PyInt_FromLong(-3); if (unlikely(!__pyx_int_neg_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
+  __pyx_int_neg_4 = PyInt_FromLong(-4); if (unlikely(!__pyx_int_neg_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
+  __pyx_int_neg_5 = PyInt_FromLong(-5); if (unlikely(!__pyx_int_neg_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
+  __pyx_int_neg_6 = PyInt_FromLong(-6); if (unlikely(!__pyx_int_neg_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
+  __pyx_int_15 = PyInt_FromLong(15); if (unlikely(!__pyx_int_15)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
+  return 0;
+  __pyx_L1_error:;
+  return -1;
+}
+
+#if PY_MAJOR_VERSION < 3
+PyMODINIT_FUNC initsofa_time(void); /*proto*/
+PyMODINIT_FUNC initsofa_time(void)
+#else
+PyMODINIT_FUNC PyInit_sofa_time(void); /*proto*/
+PyMODINIT_FUNC PyInit_sofa_time(void)
+#endif
+{
+  PyObject *__pyx_t_1 = NULL;
+  __Pyx_RefNannyDeclarations
+  #if CYTHON_REFNANNY
+  __Pyx_RefNanny = __Pyx_RefNannyImportAPI("refnanny");
+  if (!__Pyx_RefNanny) {
+      PyErr_Clear();
+      __Pyx_RefNanny = __Pyx_RefNannyImportAPI("Cython.Runtime.refnanny");
+      if (!__Pyx_RefNanny)
+          Py_FatalError("failed to import 'refnanny' module");
+  }
+  #endif
+  __Pyx_RefNannySetupContext("PyMODINIT_FUNC PyInit_sofa_time(void)");
+  if ( __Pyx_check_binary_version() < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_empty_tuple = PyTuple_New(0); if (unlikely(!__pyx_empty_tuple)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_empty_bytes = PyBytes_FromStringAndSize("", 0); if (unlikely(!__pyx_empty_bytes)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  #ifdef __pyx_binding_PyCFunctionType_USED
+  if (__pyx_binding_PyCFunctionType_init() < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  #endif
+  /*--- Library function declarations ---*/
+  /*--- Threads initialization code ---*/
+  #if defined(__PYX_FORCE_INIT_THREADS) && __PYX_FORCE_INIT_THREADS
+  #ifdef WITH_THREAD /* Python build with threading support? */
+  PyEval_InitThreads();
+  #endif
+  #endif
+  /*--- Module creation code ---*/
+  #if PY_MAJOR_VERSION < 3
+  __pyx_m = Py_InitModule4(__Pyx_NAMESTR("sofa_time"), __pyx_methods, 0, 0, PYTHON_API_VERSION);
+  #else
+  __pyx_m = PyModule_Create(&__pyx_moduledef);
+  #endif
+  if (!__pyx_m) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
+  #if PY_MAJOR_VERSION < 3
+  Py_INCREF(__pyx_m);
+  #endif
+  __pyx_b = PyImport_AddModule(__Pyx_NAMESTR(__Pyx_BUILTIN_MODULE_NAME));
+  if (!__pyx_b) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
+  if (__Pyx_SetAttrString(__pyx_m, "__builtins__", __pyx_b) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
+  /*--- Initialize various global constants etc. ---*/
+  if (unlikely(__Pyx_InitGlobals() < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (__pyx_module_is_main_astropy__time__sofa_time) {
+    if (__Pyx_SetAttrString(__pyx_m, "__name__", __pyx_n_s____main__) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
+  }
+  /*--- Builtin init code ---*/
+  if (unlikely(__Pyx_InitCachedBuiltins() < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  /*--- Constants init code ---*/
+  if (unlikely(__Pyx_InitCachedConstants() < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  /*--- Global init code ---*/
+  /*--- Variable export code ---*/
+  /*--- Function export code ---*/
+  /*--- Type init code ---*/
+  /*--- Type import code ---*/
+  __pyx_ptype_5numpy_dtype = __Pyx_ImportType("numpy", "dtype", sizeof(PyArray_Descr), 0); if (unlikely(!__pyx_ptype_5numpy_dtype)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 151; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_5numpy_flatiter = __Pyx_ImportType("numpy", "flatiter", sizeof(PyArrayIterObject), 0); if (unlikely(!__pyx_ptype_5numpy_flatiter)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 161; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_5numpy_broadcast = __Pyx_ImportType("numpy", "broadcast", sizeof(PyArrayMultiIterObject), 0); if (unlikely(!__pyx_ptype_5numpy_broadcast)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 165; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_5numpy_ndarray = __Pyx_ImportType("numpy", "ndarray", sizeof(PyArrayObject), 0); if (unlikely(!__pyx_ptype_5numpy_ndarray)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 174; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_5numpy_ufunc = __Pyx_ImportType("numpy", "ufunc", sizeof(PyUFuncObject), 0); if (unlikely(!__pyx_ptype_5numpy_ufunc)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 857; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  /*--- Variable import code ---*/
+  /*--- Function import code ---*/
+  /*--- Execution code ---*/
+
+  /* "astropy/time/sofa_time.pyx":1
+ * import warnings             # <<<<<<<<<<<<<<
+ * 
+ * import numpy as np
+ */
+  __pyx_t_1 = __Pyx_Import(((PyObject *)__pyx_n_s__warnings), 0, -1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s__warnings, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+
+  /* "astropy/time/sofa_time.pyx":3
+ * import warnings
+ * 
+ * import numpy as np             # <<<<<<<<<<<<<<
+ * cimport numpy as np
+ * import cython
+ */
+  __pyx_t_1 = __Pyx_Import(((PyObject *)__pyx_n_s__numpy), 0, -1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 3; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s__np, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 3; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+
+  /* "astropy/time/sofa_time.pyx":49
+ *     int iauGd2gc(int n, double elong, double phi, double height, double xyz[3])
+ * 
+ * DUBIOUS = 'dubious year for UTC (before 1960.0 or 5 years ' \             # <<<<<<<<<<<<<<
+ *           'beyond last known leap second)'
+ * 
+ */
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s__DUBIOUS, ((PyObject *)__pyx_kp_s_38)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 49; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+
+  /* "astropy/time/sofa_time.pyx":52
+ *           'beyond last known leap second)'
+ * 
+ * def check_return(ret, func_name, warns={}, errors={}):             # <<<<<<<<<<<<<<
+ *     """Check the return value from an iau routine"""
+ *     if ret in warns:
+ */
+  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 52; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_1));
+  __pyx_k_1 = ((PyObject *)__pyx_t_1);
+  __Pyx_GIVEREF(__pyx_t_1);
+  __pyx_t_1 = 0;
+  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 52; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_1));
+  __pyx_k_2 = ((PyObject *)__pyx_t_1);
+  __Pyx_GIVEREF(__pyx_t_1);
+  __pyx_t_1 = 0;
+  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_7astropy_4time_9sofa_time_check_return, NULL, __pyx_n_s_39); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 52; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s__check_return, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 52; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+
+  /* "astropy/time/sofa_time.pyx":65
+ * @cython.wraparound(False)
+ * @cython.boundscheck(False)
+ * def cal2jd(             # <<<<<<<<<<<<<<
+ *     np.ndarray[int, ndim=1] iy,
+ *     np.ndarray[int, ndim=1] im,
+ */
+  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_7astropy_4time_9sofa_time_1cal2jd, NULL, __pyx_n_s_39); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 65; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s__cal2jd, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 65; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+
+  /* "astropy/time/sofa_time.pyx":116
+ * @cython.wraparound(False)
+ * @cython.boundscheck(False)
+ * def d_tai_utc(np.ndarray[int, ndim=1] iy,             # <<<<<<<<<<<<<<
+ *               np.ndarray[int, ndim=1] im,
+ *               np.ndarray[int, ndim=1] id,
+ */
+  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_7astropy_4time_9sofa_time_2d_tai_utc, NULL, __pyx_n_s_39); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s__d_tai_utc, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+
+  /* "astropy/time/sofa_time.pyx":214
+ * @cython.wraparound(False)
+ * @cython.boundscheck(False)
+ * def jd_dtf(scale, ndp,             # <<<<<<<<<<<<<<
+ *               np.ndarray[double, ndim=1] d1,
+ *               np.ndarray[double, ndim=1] d2):
+ */
+  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_7astropy_4time_9sofa_time_3jd_dtf, NULL, __pyx_n_s_39); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 214; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s__jd_dtf, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 214; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+
+  /* "astropy/time/sofa_time.pyx":293
+ * @cython.wraparound(False)
+ * @cython.boundscheck(False)
+ * def dtf_jd(scale,             # <<<<<<<<<<<<<<
+ *               np.ndarray[int, ndim=1] iy,
+ *               np.ndarray[int, ndim=1] im,
+ */
+  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_7astropy_4time_9sofa_time_4dtf_jd, NULL, __pyx_n_s_39); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 293; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s__dtf_jd, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 293; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+
+  /* "astropy/time/sofa_time.pyx":387
+ * @cython.wraparound(False)
+ * @cython.boundscheck(False)
+ * def tai_tt(             # <<<<<<<<<<<<<<
+ *     np.ndarray[double, ndim=1] in1,
+ *     np.ndarray[double, ndim=1] in2):
+ */
+  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_7astropy_4time_9sofa_time_5tai_tt, NULL, __pyx_n_s_39); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 387; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s__tai_tt, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 387; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+
+  /* "astropy/time/sofa_time.pyx":424
+ * @cython.wraparound(False)
+ * @cython.boundscheck(False)
+ * def tcb_tdb(             # <<<<<<<<<<<<<<
+ *     np.ndarray[double, ndim=1] in1,
+ *     np.ndarray[double, ndim=1] in2):
+ */
+  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_7astropy_4time_9sofa_time_6tcb_tdb, NULL, __pyx_n_s_39); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 424; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s__tcb_tdb, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 424; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+
+  /* "astropy/time/sofa_time.pyx":480
+ * @cython.wraparound(False)
+ * @cython.boundscheck(False)
+ * def tcg_tt(             # <<<<<<<<<<<<<<
+ *     np.ndarray[double, ndim=1] in1,
+ *     np.ndarray[double, ndim=1] in2):
+ */
+  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_7astropy_4time_9sofa_time_7tcg_tt, NULL, __pyx_n_s_39); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 480; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s__tcg_tt, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 480; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+
+  /* "astropy/time/sofa_time.pyx":511
+ * @cython.wraparound(False)
+ * @cython.boundscheck(False)
+ * def tdb_tcb(             # <<<<<<<<<<<<<<
+ *     np.ndarray[double, ndim=1] in1,
+ *     np.ndarray[double, ndim=1] in2):
+ */
+  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_7astropy_4time_9sofa_time_8tdb_tcb, NULL, __pyx_n_s_39); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 511; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s__tdb_tcb, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 511; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+
+  /* "astropy/time/sofa_time.pyx":541
+ * @cython.wraparound(False)
+ * @cython.boundscheck(False)
+ * def tt_tai(             # <<<<<<<<<<<<<<
+ *     np.ndarray[double, ndim=1] in1,
+ *     np.ndarray[double, ndim=1] in2):
+ */
+  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_7astropy_4time_9sofa_time_9tt_tai, NULL, __pyx_n_s_39); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 541; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s__tt_tai, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 541; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+
+  /* "astropy/time/sofa_time.pyx":571
+ * @cython.wraparound(False)
+ * @cython.boundscheck(False)
+ * def tt_tcg(             # <<<<<<<<<<<<<<
+ *     np.ndarray[double, ndim=1] in1,
+ *     np.ndarray[double, ndim=1] in2):
+ */
+  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_7astropy_4time_9sofa_time_10tt_tcg, NULL, __pyx_n_s_39); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 571; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s__tt_tcg, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 571; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+
+  /* "astropy/time/sofa_time.pyx":600
+ * @cython.wraparound(False)
+ * @cython.boundscheck(False)
+ * def utc_tai(             # <<<<<<<<<<<<<<
+ *     np.ndarray[double, ndim=1] in1,
+ *     np.ndarray[double, ndim=1] in2):
+ */
+  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_7astropy_4time_9sofa_time_11utc_tai, NULL, __pyx_n_s_39); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 600; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s__utc_tai, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 600; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+
+  /* "astropy/time/sofa_time.pyx":658
+ * @cython.wraparound(False)
+ * @cython.boundscheck(False)
+ * def tai_utc(             # <<<<<<<<<<<<<<
+ *     np.ndarray[double, ndim=1] in1,
+ *     np.ndarray[double, ndim=1] in2):
+ */
+  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_7astropy_4time_9sofa_time_12tai_utc, NULL, __pyx_n_s_39); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 658; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s__tai_utc, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 658; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+
+  /* "astropy/time/sofa_time.pyx":715
+ * @cython.wraparound(False)
+ * @cython.boundscheck(False)
+ * def tai_ut1(             # <<<<<<<<<<<<<<
+ *     np.ndarray[double, ndim=1] in1,
+ *     np.ndarray[double, ndim=1] in2,
+ */
+  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_7astropy_4time_9sofa_time_13tai_ut1, NULL, __pyx_n_s_39); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 715; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s__tai_ut1, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 715; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+
+  /* "astropy/time/sofa_time.pyx":757
+ * @cython.wraparound(False)
+ * @cython.boundscheck(False)
+ * def ut1_tai(             # <<<<<<<<<<<<<<
+ *     np.ndarray[double, ndim=1] in1,
+ *     np.ndarray[double, ndim=1] in2,
+ */
+  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_7astropy_4time_9sofa_time_14ut1_tai, NULL, __pyx_n_s_39); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 757; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s__ut1_tai, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 757; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+
+  /* "astropy/time/sofa_time.pyx":799
+ * @cython.wraparound(False)
+ * @cython.boundscheck(False)
+ * def tt_ut1(             # <<<<<<<<<<<<<<
+ *     np.ndarray[double, ndim=1] in1,
+ *     np.ndarray[double, ndim=1] in2,
+ */
+  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_7astropy_4time_9sofa_time_15tt_ut1, NULL, __pyx_n_s_39); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 799; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s__tt_ut1, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 799; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+
+  /* "astropy/time/sofa_time.pyx":840
+ * @cython.wraparound(False)
+ * @cython.boundscheck(False)
+ * def ut1_tt(             # <<<<<<<<<<<<<<
+ *     np.ndarray[double, ndim=1] in1,
+ *     np.ndarray[double, ndim=1] in2,
+ */
+  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_7astropy_4time_9sofa_time_16ut1_tt, NULL, __pyx_n_s_39); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 840; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s__ut1_tt, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 840; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+
+  /* "astropy/time/sofa_time.pyx":881
+ * @cython.wraparound(False)
+ * @cython.boundscheck(False)
+ * def tdb_tt(             # <<<<<<<<<<<<<<
+ *     np.ndarray[double, ndim=1] in1,
+ *     np.ndarray[double, ndim=1] in2,
+ */
+  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_7astropy_4time_9sofa_time_17tdb_tt, NULL, __pyx_n_s_39); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 881; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s__tdb_tt, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 881; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+
+  /* "astropy/time/sofa_time.pyx":931
+ * @cython.wraparound(False)
+ * @cython.boundscheck(False)
+ * def tt_tdb(             # <<<<<<<<<<<<<<
+ *     np.ndarray[double, ndim=1] in1,
+ *     np.ndarray[double, ndim=1] in2,
+ */
+  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_7astropy_4time_9sofa_time_18tt_tdb, NULL, __pyx_n_s_39); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 931; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s__tt_tdb, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 931; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+
+  /* "astropy/time/sofa_time.pyx":981
+ * @cython.wraparound(False)
+ * @cython.boundscheck(False)
+ * def ut1_utc(             # <<<<<<<<<<<<<<
+ *     np.ndarray[double, ndim=1] in1,
+ *     np.ndarray[double, ndim=1] in2,
+ */
+  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_7astropy_4time_9sofa_time_19ut1_utc, NULL, __pyx_n_s_39); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 981; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s__ut1_utc, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 981; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+
+  /* "astropy/time/sofa_time.pyx":1045
+ * @cython.wraparound(False)
+ * @cython.boundscheck(False)
+ * def utc_ut1(             # <<<<<<<<<<<<<<
+ *     np.ndarray[double, ndim=1] in1,
+ *     np.ndarray[double, ndim=1] in2,
+ */
+  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_7astropy_4time_9sofa_time_20utc_ut1, NULL, __pyx_n_s_39); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1045; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s__utc_ut1, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1045; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+
+  /* "astropy/time/sofa_time.pyx":1113
+ * @cython.wraparound(False)
+ * @cython.boundscheck(False)
+ * def d_tdb_tt(np.ndarray[double, ndim=1] in1,             # <<<<<<<<<<<<<<
+ *              np.ndarray[double, ndim=1] in2,
+ *              np.ndarray[double, ndim=1] ut,
+ */
+  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_7astropy_4time_9sofa_time_21d_tdb_tt, NULL, __pyx_n_s_39); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1113; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s__d_tdb_tt, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1113; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+
+  /* "astropy/time/sofa_time.pyx":1232
+ * 
+ * 
+ * def iau_af2a(sign, ideg, iamin, asec):             # <<<<<<<<<<<<<<
+ *     """
+ *     int iauAf2a(char s, int ideg, int iamin, double asec, double *rad)
+ */
+  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_7astropy_4time_9sofa_time_22iau_af2a, NULL, __pyx_n_s_39); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1232; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s__iau_af2a, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1232; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+
+  /* "astropy/time/sofa_time.pyx":1273
+ *     return rad
+ * 
+ * def iau_gd2gc(n, elong, phi, height):             # <<<<<<<<<<<<<<
+ *     """
+ *     Wrap
+ */
+  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_7astropy_4time_9sofa_time_23iau_gd2gc, NULL, __pyx_n_s_39); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1273; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s__iau_gd2gc, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1273; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+
+  /* "astropy/time/sofa_time.pyx":1330
+ * @cython.wraparound(False)
+ * @cython.boundscheck(False)
+ * def jd_julian_epoch(np.ndarray[double, ndim=1] jd1,             # <<<<<<<<<<<<<<
+ *                     np.ndarray[double, ndim=1] jd2):
+ *     """ Wrap double iauEpj(double dj1, double dj2)
+ */
+  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_7astropy_4time_9sofa_time_24jd_julian_epoch, NULL, __pyx_n_s_39); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1330; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s__jd_julian_epoch, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1330; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+
+  /* "astropy/time/sofa_time.pyx":1361
+ * @cython.wraparound(False)
+ * @cython.boundscheck(False)
+ * def julian_epoch_jd(np.ndarray[double, ndim=1] epd):             # <<<<<<<<<<<<<<
+ *     """ Wrap void iauEpj2jd(double epj, double *djm0, double *djm)
+ *     **  Julian Epoch to Julian Date.
+ */
+  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_7astropy_4time_9sofa_time_25julian_epoch_jd, NULL, __pyx_n_s_39); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1361; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s__julian_epoch_jd, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1361; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+
+  /* "astropy/time/sofa_time.pyx":1383
+ * @cython.wraparound(False)
+ * @cython.boundscheck(False)
+ * def jd_besselian_epoch(np.ndarray[double, ndim=1] jd1,             # <<<<<<<<<<<<<<
+ *                        np.ndarray[double, ndim=1] jd2):
+ *     """ Wrap double iauEpb(double dj1, double dj2)
+ */
+  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_7astropy_4time_9sofa_time_26jd_besselian_epoch, NULL, __pyx_n_s_39); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1383; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s__jd_besselian_epoch, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1383; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+
+  /* "astropy/time/sofa_time.pyx":1414
+ * @cython.wraparound(False)
+ * @cython.boundscheck(False)
+ * def besselian_epoch_jd(np.ndarray[double, ndim=1] epd):             # <<<<<<<<<<<<<<
+ *     """ Wrap void iauEpb2jd(double epj, double *djm0, double *djm)
+ *     **  Besselian Epoch to Julian Date.
+ */
+  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_7astropy_4time_9sofa_time_27besselian_epoch_jd, NULL, __pyx_n_s_39); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1414; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s__besselian_epoch_jd, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1414; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+
+  /* "astropy/time/sofa_time.pyx":1
+ * import warnings             # <<<<<<<<<<<<<<
+ * 
+ * import numpy as np
+ */
+  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_1));
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s____test__, ((PyObject *)__pyx_t_1)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
+
+  /* "numpy.pxd":971
+ *      arr.base = baseptr
+ * 
+ * cdef inline object get_array_base(ndarray arr):             # <<<<<<<<<<<<<<
+ *     if arr.base is NULL:
+ *         return None
+ */
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  if (__pyx_m) {
+    __Pyx_AddTraceback("init astropy.time.sofa_time", __pyx_clineno, __pyx_lineno, __pyx_filename);
+    Py_DECREF(__pyx_m); __pyx_m = 0;
+  } else if (!PyErr_Occurred()) {
+    PyErr_SetString(PyExc_ImportError, "init astropy.time.sofa_time");
+  }
+  __pyx_L0:;
+  __Pyx_RefNannyFinishContext();
+  #if PY_MAJOR_VERSION < 3
+  return;
+  #else
+  return __pyx_m;
+  #endif
+}
+
+/* Runtime support code */
+
+#if CYTHON_REFNANNY
+static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname) {
+    PyObject *m = NULL, *p = NULL;
+    void *r = NULL;
+    m = PyImport_ImportModule((char *)modname);
+    if (!m) goto end;
+    p = PyObject_GetAttrString(m, (char *)"RefNannyAPI");
+    if (!p) goto end;
+    r = PyLong_AsVoidPtr(p);
+end:
+    Py_XDECREF(p);
+    Py_XDECREF(m);
+    return (__Pyx_RefNannyAPIStruct *)r;
+}
+#endif /* CYTHON_REFNANNY */
+
+static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name) {
+    PyObject *result;
+    result = PyObject_GetAttr(dict, name);
+    if (!result) {
+        if (dict != __pyx_b) {
+            PyErr_Clear();
+            result = PyObject_GetAttr(__pyx_b, name);
+        }
+        if (!result) {
+            PyErr_SetObject(PyExc_NameError, name);
+        }
+    }
+    return result;
+}
+
+static void __Pyx_RaiseArgtupleInvalid(
+    const char* func_name,
+    int exact,
+    Py_ssize_t num_min,
+    Py_ssize_t num_max,
+    Py_ssize_t num_found)
+{
+    Py_ssize_t num_expected;
+    const char *more_or_less;
+
+    if (num_found < num_min) {
+        num_expected = num_min;
+        more_or_less = "at least";
+    } else {
+        num_expected = num_max;
+        more_or_less = "at most";
+    }
+    if (exact) {
+        more_or_less = "exactly";
+    }
+    PyErr_Format(PyExc_TypeError,
+                 "%s() takes %s %"PY_FORMAT_SIZE_T"d positional argument%s (%"PY_FORMAT_SIZE_T"d given)",
+                 func_name, more_or_less, num_expected,
+                 (num_expected == 1) ? "" : "s", num_found);
+}
+
+static void __Pyx_RaiseDoubleKeywordsError(
+    const char* func_name,
+    PyObject* kw_name)
+{
+    PyErr_Format(PyExc_TypeError,
+        #if PY_MAJOR_VERSION >= 3
+        "%s() got multiple values for keyword argument '%U'", func_name, kw_name);
+        #else
+        "%s() got multiple values for keyword argument '%s'", func_name,
+        PyString_AS_STRING(kw_name));
+        #endif
+}
+
+static int __Pyx_ParseOptionalKeywords(
+    PyObject *kwds,
+    PyObject **argnames[],
+    PyObject *kwds2,
+    PyObject *values[],
+    Py_ssize_t num_pos_args,
+    const char* function_name)
+{
+    PyObject *key = 0, *value = 0;
+    Py_ssize_t pos = 0;
+    PyObject*** name;
+    PyObject*** first_kw_arg = argnames + num_pos_args;
+
+    while (PyDict_Next(kwds, &pos, &key, &value)) {
+        name = first_kw_arg;
+        while (*name && (**name != key)) name++;
+        if (*name) {
+            values[name-argnames] = value;
+        } else {
+            #if PY_MAJOR_VERSION < 3
+            if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key))) {
+            #else
+            if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key))) {
+            #endif
+                goto invalid_keyword_type;
+            } else {
+                for (name = first_kw_arg; *name; name++) {
+                    #if PY_MAJOR_VERSION >= 3
+                    if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) &&
+                        PyUnicode_Compare(**name, key) == 0) break;
+                    #else
+                    if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) &&
+                        _PyString_Eq(**name, key)) break;
+                    #endif
+                }
+                if (*name) {
+                    values[name-argnames] = value;
+                } else {
+                    /* unexpected keyword found */
+                    for (name=argnames; name != first_kw_arg; name++) {
+                        if (**name == key) goto arg_passed_twice;
+                        #if PY_MAJOR_VERSION >= 3
+                        if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) &&
+                            PyUnicode_Compare(**name, key) == 0) goto arg_passed_twice;
+                        #else
+                        if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) &&
+                            _PyString_Eq(**name, key)) goto arg_passed_twice;
+                        #endif
+                    }
+                    if (kwds2) {
+                        if (unlikely(PyDict_SetItem(kwds2, key, value))) goto bad;
+                    } else {
+                        goto invalid_keyword;
+                    }
+                }
+            }
+        }
+    }
+    return 0;
+arg_passed_twice:
+    __Pyx_RaiseDoubleKeywordsError(function_name, **name);
+    goto bad;
+invalid_keyword_type:
+    PyErr_Format(PyExc_TypeError,
+        "%s() keywords must be strings", function_name);
+    goto bad;
+invalid_keyword:
+    PyErr_Format(PyExc_TypeError,
+    #if PY_MAJOR_VERSION < 3
+        "%s() got an unexpected keyword argument '%s'",
+        function_name, PyString_AsString(key));
+    #else
+        "%s() got an unexpected keyword argument '%U'",
+        function_name, key);
+    #endif
+bad:
+    return -1;
+}
+
+static CYTHON_INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb) {
+    PyObject *tmp_type, *tmp_value, *tmp_tb;
+    PyThreadState *tstate = PyThreadState_GET();
+
+    tmp_type = tstate->curexc_type;
+    tmp_value = tstate->curexc_value;
+    tmp_tb = tstate->curexc_traceback;
+    tstate->curexc_type = type;
+    tstate->curexc_value = value;
+    tstate->curexc_traceback = tb;
+    Py_XDECREF(tmp_type);
+    Py_XDECREF(tmp_value);
+    Py_XDECREF(tmp_tb);
+}
+
+static CYTHON_INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb) {
+    PyThreadState *tstate = PyThreadState_GET();
+    *type = tstate->curexc_type;
+    *value = tstate->curexc_value;
+    *tb = tstate->curexc_traceback;
+
+    tstate->curexc_type = 0;
+    tstate->curexc_value = 0;
+    tstate->curexc_traceback = 0;
+}
+
+
+#if PY_MAJOR_VERSION < 3
+static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause) {
+    /* cause is unused */
+    Py_XINCREF(type);
+    Py_XINCREF(value);
+    Py_XINCREF(tb);
+    /* First, check the traceback argument, replacing None with NULL. */
+    if (tb == Py_None) {
+        Py_DECREF(tb);
+        tb = 0;
+    }
+    else if (tb != NULL && !PyTraceBack_Check(tb)) {
+        PyErr_SetString(PyExc_TypeError,
+            "raise: arg 3 must be a traceback or None");
+        goto raise_error;
+    }
+    /* Next, replace a missing value with None */
+    if (value == NULL) {
+        value = Py_None;
+        Py_INCREF(value);
+    }
+    #if PY_VERSION_HEX < 0x02050000
+    if (!PyClass_Check(type))
+    #else
+    if (!PyType_Check(type))
+    #endif
+    {
+        /* Raising an instance.  The value should be a dummy. */
+        if (value != Py_None) {
+            PyErr_SetString(PyExc_TypeError,
+                "instance exception may not have a separate value");
+            goto raise_error;
+        }
+        /* Normalize to raise <class>, <instance> */
+        Py_DECREF(value);
+        value = type;
+        #if PY_VERSION_HEX < 0x02050000
+            if (PyInstance_Check(type)) {
+                type = (PyObject*) ((PyInstanceObject*)type)->in_class;
+                Py_INCREF(type);
+            }
+            else {
+                type = 0;
+                PyErr_SetString(PyExc_TypeError,
+                    "raise: exception must be an old-style class or instance");
+                goto raise_error;
+            }
+        #else
+            type = (PyObject*) Py_TYPE(type);
+            Py_INCREF(type);
+            if (!PyType_IsSubtype((PyTypeObject *)type, (PyTypeObject *)PyExc_BaseException)) {
+                PyErr_SetString(PyExc_TypeError,
+                    "raise: exception class must be a subclass of BaseException");
+                goto raise_error;
+            }
+        #endif
+    }
+
+    __Pyx_ErrRestore(type, value, tb);
+    return;
+raise_error:
+    Py_XDECREF(value);
+    Py_XDECREF(type);
+    Py_XDECREF(tb);
+    return;
+}
+
+#else /* Python 3+ */
+
+static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause) {
+    if (tb == Py_None) {
+        tb = 0;
+    } else if (tb && !PyTraceBack_Check(tb)) {
+        PyErr_SetString(PyExc_TypeError,
+            "raise: arg 3 must be a traceback or None");
+        goto bad;
+    }
+    if (value == Py_None)
+        value = 0;
+
+    if (PyExceptionInstance_Check(type)) {
+        if (value) {
+            PyErr_SetString(PyExc_TypeError,
+                "instance exception may not have a separate value");
+            goto bad;
+        }
+        value = type;
+        type = (PyObject*) Py_TYPE(value);
+    } else if (!PyExceptionClass_Check(type)) {
+        PyErr_SetString(PyExc_TypeError,
+            "raise: exception class must be a subclass of BaseException");
+        goto bad;
+    }
+
+    if (cause) {
+        PyObject *fixed_cause;
+        if (PyExceptionClass_Check(cause)) {
+            fixed_cause = PyObject_CallObject(cause, NULL);
+            if (fixed_cause == NULL)
+                goto bad;
+        }
+        else if (PyExceptionInstance_Check(cause)) {
+            fixed_cause = cause;
+            Py_INCREF(fixed_cause);
+        }
+        else {
+            PyErr_SetString(PyExc_TypeError,
+                            "exception causes must derive from "
+                            "BaseException");
+            goto bad;
+        }
+        if (!value) {
+            value = PyObject_CallObject(type, NULL);
+        }
+        PyException_SetCause(value, fixed_cause);
+    }
+
+    PyErr_SetObject(type, value);
+
+    if (tb) {
+        PyThreadState *tstate = PyThreadState_GET();
+        PyObject* tmp_tb = tstate->curexc_traceback;
+        if (tb != tmp_tb) {
+            Py_INCREF(tb);
+            tstate->curexc_traceback = tb;
+            Py_XDECREF(tmp_tb);
+        }
+    }
+
+bad:
+    return;
+}
+#endif
+
+static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
+    const char *name, int exact)
+{
+    if (!type) {
+        PyErr_Format(PyExc_SystemError, "Missing type object");
+        return 0;
+    }
+    if (none_allowed && obj == Py_None) return 1;
+    else if (exact) {
+        if (Py_TYPE(obj) == type) return 1;
+    }
+    else {
+        if (PyObject_TypeCheck(obj, type)) return 1;
+    }
+    PyErr_Format(PyExc_TypeError,
+        "Argument '%s' has incorrect type (expected %s, got %s)",
+        name, type->tp_name, Py_TYPE(obj)->tp_name);
+    return 0;
+}
+
+static CYTHON_INLINE int __Pyx_IsLittleEndian(void) {
+  unsigned int n = 1;
+  return *(unsigned char*)(&n) != 0;
+}
+
+typedef struct {
+  __Pyx_StructField root;
+  __Pyx_BufFmt_StackElem* head;
+  size_t fmt_offset;
+  size_t new_count, enc_count;
+  int is_complex;
+  char enc_type;
+  char new_packmode;
+  char enc_packmode;
+} __Pyx_BufFmt_Context;
+
+static void __Pyx_BufFmt_Init(__Pyx_BufFmt_Context* ctx,
+                              __Pyx_BufFmt_StackElem* stack,
+                              __Pyx_TypeInfo* type) {
+  stack[0].field = &ctx->root;
+  stack[0].parent_offset = 0;
+  ctx->root.type = type;
+  ctx->root.name = "buffer dtype";
+  ctx->root.offset = 0;
+  ctx->head = stack;
+  ctx->head->field = &ctx->root;
+  ctx->fmt_offset = 0;
+  ctx->head->parent_offset = 0;
+  ctx->new_packmode = '@';
+  ctx->enc_packmode = '@';
+  ctx->new_count = 1;
+  ctx->enc_count = 0;
+  ctx->enc_type = 0;
+  ctx->is_complex = 0;
+  while (type->typegroup == 'S') {
+    ++ctx->head;
+    ctx->head->field = type->fields;
+    ctx->head->parent_offset = 0;
+    type = type->fields->type;
+  }
+}
+
+static int __Pyx_BufFmt_ParseNumber(const char** ts) {
+    int count;
+    const char* t = *ts;
+    if (*t < '0' || *t > '9') {
+      return -1;
+    } else {
+        count = *t++ - '0';
+        while (*t >= '0' && *t < '9') {
+            count *= 10;
+            count += *t++ - '0';
+        }
+    }
+    *ts = t;
+    return count;
+}
+
+static void __Pyx_BufFmt_RaiseUnexpectedChar(char ch) {
+  PyErr_Format(PyExc_ValueError,
+               "Unexpected format string character: '%c'", ch);
+}
+
+static const char* __Pyx_BufFmt_DescribeTypeChar(char ch, int is_complex) {
+  switch (ch) {
+    case 'b': return "'char'";
+    case 'B': return "'unsigned char'";
+    case 'h': return "'short'";
+    case 'H': return "'unsigned short'";
+    case 'i': return "'int'";
+    case 'I': return "'unsigned int'";
+    case 'l': return "'long'";
+    case 'L': return "'unsigned long'";
+    case 'q': return "'long long'";
+    case 'Q': return "'unsigned long long'";
+    case 'f': return (is_complex ? "'complex float'" : "'float'");
+    case 'd': return (is_complex ? "'complex double'" : "'double'");
+    case 'g': return (is_complex ? "'complex long double'" : "'long double'");
+    case 'T': return "a struct";
+    case 'O': return "Python object";
+    case 'P': return "a pointer";
+    case 0: return "end";
+    default: return "unparseable format string";
+  }
+}
+
+static size_t __Pyx_BufFmt_TypeCharToStandardSize(char ch, int is_complex) {
+  switch (ch) {
+    case '?': case 'c': case 'b': case 'B': return 1;
+    case 'h': case 'H': return 2;
+    case 'i': case 'I': case 'l': case 'L': return 4;
+    case 'q': case 'Q': return 8;
+    case 'f': return (is_complex ? 8 : 4);
+    case 'd': return (is_complex ? 16 : 8);
+    case 'g': {
+      PyErr_SetString(PyExc_ValueError, "Python does not define a standard format string size for long double ('g')..");
+      return 0;
+    }
+    case 'O': case 'P': return sizeof(void*);
+    default:
+      __Pyx_BufFmt_RaiseUnexpectedChar(ch);
+      return 0;
+    }
+}
+
+static size_t __Pyx_BufFmt_TypeCharToNativeSize(char ch, int is_complex) {
+  switch (ch) {
+    case 'c': case 'b': case 'B': return 1;
+    case 'h': case 'H': return sizeof(short);
+    case 'i': case 'I': return sizeof(int);
+    case 'l': case 'L': return sizeof(long);
+    #ifdef HAVE_LONG_LONG
+    case 'q': case 'Q': return sizeof(PY_LONG_LONG);
+    #endif
+    case 'f': return sizeof(float) * (is_complex ? 2 : 1);
+    case 'd': return sizeof(double) * (is_complex ? 2 : 1);
+    case 'g': return sizeof(long double) * (is_complex ? 2 : 1);
+    case 'O': case 'P': return sizeof(void*);
+    default: {
+      __Pyx_BufFmt_RaiseUnexpectedChar(ch);
+      return 0;
+    }
+  }
+}
+
+typedef struct { char c; short x; } __Pyx_st_short;
+typedef struct { char c; int x; } __Pyx_st_int;
+typedef struct { char c; long x; } __Pyx_st_long;
+typedef struct { char c; float x; } __Pyx_st_float;
+typedef struct { char c; double x; } __Pyx_st_double;
+typedef struct { char c; long double x; } __Pyx_st_longdouble;
+typedef struct { char c; void *x; } __Pyx_st_void_p;
+#ifdef HAVE_LONG_LONG
+typedef struct { char c; PY_LONG_LONG x; } __Pyx_st_longlong;
+#endif
+
+static size_t __Pyx_BufFmt_TypeCharToAlignment(char ch, int is_complex) {
+  switch (ch) {
+    case '?': case 'c': case 'b': case 'B': return 1;
+    case 'h': case 'H': return sizeof(__Pyx_st_short) - sizeof(short);
+    case 'i': case 'I': return sizeof(__Pyx_st_int) - sizeof(int);
+    case 'l': case 'L': return sizeof(__Pyx_st_long) - sizeof(long);
+#ifdef HAVE_LONG_LONG
+    case 'q': case 'Q': return sizeof(__Pyx_st_longlong) - sizeof(PY_LONG_LONG);
+#endif
+    case 'f': return sizeof(__Pyx_st_float) - sizeof(float);
+    case 'd': return sizeof(__Pyx_st_double) - sizeof(double);
+    case 'g': return sizeof(__Pyx_st_longdouble) - sizeof(long double);
+    case 'P': case 'O': return sizeof(__Pyx_st_void_p) - sizeof(void*);
+    default:
+      __Pyx_BufFmt_RaiseUnexpectedChar(ch);
+      return 0;
+    }
+}
+
+static char __Pyx_BufFmt_TypeCharToGroup(char ch, int is_complex) {
+  switch (ch) {
+    case 'c': case 'b': case 'h': case 'i': case 'l': case 'q': return 'I';
+    case 'B': case 'H': case 'I': case 'L': case 'Q': return 'U';
+    case 'f': case 'd': case 'g': return (is_complex ? 'C' : 'R');
+    case 'O': return 'O';
+    case 'P': return 'P';
+    default: {
+      __Pyx_BufFmt_RaiseUnexpectedChar(ch);
+      return 0;
+    }
+  }
+}
+
+static void __Pyx_BufFmt_RaiseExpected(__Pyx_BufFmt_Context* ctx) {
+  if (ctx->head == NULL || ctx->head->field == &ctx->root) {
+    const char* expected;
+    const char* quote;
+    if (ctx->head == NULL) {
+      expected = "end";
+      quote = "";
+    } else {
+      expected = ctx->head->field->type->name;
+      quote = "'";
+    }
+    PyErr_Format(PyExc_ValueError,
+                 "Buffer dtype mismatch, expected %s%s%s but got %s",
+                 quote, expected, quote,
+                 __Pyx_BufFmt_DescribeTypeChar(ctx->enc_type, ctx->is_complex));
+  } else {
+    __Pyx_StructField* field = ctx->head->field;
+    __Pyx_StructField* parent = (ctx->head - 1)->field;
+    PyErr_Format(PyExc_ValueError,
+                 "Buffer dtype mismatch, expected '%s' but got %s in '%s.%s'",
+                 field->type->name, __Pyx_BufFmt_DescribeTypeChar(ctx->enc_type, ctx->is_complex),
+                 parent->type->name, field->name);
+  }
+}
+
+static int __Pyx_BufFmt_ProcessTypeChunk(__Pyx_BufFmt_Context* ctx) {
+  char group;
+  size_t size, offset;
+  if (ctx->enc_type == 0) return 0;
+  group = __Pyx_BufFmt_TypeCharToGroup(ctx->enc_type, ctx->is_complex);
+  do {
+    __Pyx_StructField* field = ctx->head->field;
+    __Pyx_TypeInfo* type = field->type;
+
+    if (ctx->enc_packmode == '@' || ctx->enc_packmode == '^') {
+      size = __Pyx_BufFmt_TypeCharToNativeSize(ctx->enc_type, ctx->is_complex);
+    } else {
+      size = __Pyx_BufFmt_TypeCharToStandardSize(ctx->enc_type, ctx->is_complex);
+    }
+    if (ctx->enc_packmode == '@') {
+      size_t align_at = __Pyx_BufFmt_TypeCharToAlignment(ctx->enc_type, ctx->is_complex);
+      size_t align_mod_offset;
+      if (align_at == 0) return -1;
+      align_mod_offset = ctx->fmt_offset % align_at;
+      if (align_mod_offset > 0) ctx->fmt_offset += align_at - align_mod_offset;
+    }
+
+    if (type->size != size || type->typegroup != group) {
+      if (type->typegroup == 'C' && type->fields != NULL) {
+        /* special case -- treat as struct rather than complex number */
+        size_t parent_offset = ctx->head->parent_offset + field->offset;
+        ++ctx->head;
+        ctx->head->field = type->fields;
+        ctx->head->parent_offset = parent_offset;
+        continue;
+      }
+
+      __Pyx_BufFmt_RaiseExpected(ctx);
+      return -1;
+    }
+
+    offset = ctx->head->parent_offset + field->offset;
+    if (ctx->fmt_offset != offset) {
+      PyErr_Format(PyExc_ValueError,
+                   "Buffer dtype mismatch; next field is at offset %"PY_FORMAT_SIZE_T"d but %"PY_FORMAT_SIZE_T"d expected",
+                   (Py_ssize_t)ctx->fmt_offset, (Py_ssize_t)offset);
+      return -1;
+    }
+
+    ctx->fmt_offset += size;
+
+    --ctx->enc_count; /* Consume from buffer string */
+
+    /* Done checking, move to next field, pushing or popping struct stack if needed */
+    while (1) {
+      if (field == &ctx->root) {
+        ctx->head = NULL;
+        if (ctx->enc_count != 0) {
+          __Pyx_BufFmt_RaiseExpected(ctx);
+          return -1;
+        }
+        break; /* breaks both loops as ctx->enc_count == 0 */
+      }
+      ctx->head->field = ++field;
+      if (field->type == NULL) {
+        --ctx->head;
+        field = ctx->head->field;
+        continue;
+      } else if (field->type->typegroup == 'S') {
+        size_t parent_offset = ctx->head->parent_offset + field->offset;
+        if (field->type->fields->type == NULL) continue; /* empty struct */
+        field = field->type->fields;
+        ++ctx->head;
+        ctx->head->field = field;
+        ctx->head->parent_offset = parent_offset;
+        break;
+      } else {
+        break;
+      }
+    }
+  } while (ctx->enc_count);
+  ctx->enc_type = 0;
+  ctx->is_complex = 0;
+  return 0;
+}
+
+static const char* __Pyx_BufFmt_CheckString(__Pyx_BufFmt_Context* ctx, const char* ts) {
+  int got_Z = 0;
+  while (1) {
+    switch(*ts) {
+      case 0:
+        if (ctx->enc_type != 0 && ctx->head == NULL) {
+          __Pyx_BufFmt_RaiseExpected(ctx);
+          return NULL;
+        }
+        if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL;
+        if (ctx->head != NULL) {
+          __Pyx_BufFmt_RaiseExpected(ctx);
+          return NULL;
+        }
+        return ts;
+      case ' ':
+      case 10:
+      case 13:
+        ++ts;
+        break;
+      case '<':
+        if (!__Pyx_IsLittleEndian()) {
+          PyErr_SetString(PyExc_ValueError, "Little-endian buffer not supported on big-endian compiler");
+          return NULL;
+        }
+        ctx->new_packmode = '=';
+        ++ts;
+        break;
+      case '>':
+      case '!':
+        if (__Pyx_IsLittleEndian()) {
+          PyErr_SetString(PyExc_ValueError, "Big-endian buffer not supported on little-endian compiler");
+          return NULL;
+        }
+        ctx->new_packmode = '=';
+        ++ts;
+        break;
+      case '=':
+      case '@':
+      case '^':
+        ctx->new_packmode = *ts++;
+        break;
+      case 'T': /* substruct */
+        {
+          const char* ts_after_sub;
+          size_t i, struct_count = ctx->new_count;
+          ctx->new_count = 1;
+          ++ts;
+          if (*ts != '{') {
+            PyErr_SetString(PyExc_ValueError, "Buffer acquisition: Expected '{' after 'T'");
+            return NULL;
+          }
+          ++ts;
+          ts_after_sub = ts;
+          for (i = 0; i != struct_count; ++i) {
+            ts_after_sub = __Pyx_BufFmt_CheckString(ctx, ts);
+            if (!ts_after_sub) return NULL;
+          }
+          ts = ts_after_sub;
+        }
+        break;
+      case '}': /* end of substruct; either repeat or move on */
+        ++ts;
+        return ts;
+      case 'x':
+        if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL;
+        ctx->fmt_offset += ctx->new_count;
+        ctx->new_count = 1;
+        ctx->enc_count = 0;
+        ctx->enc_type = 0;
+        ctx->enc_packmode = ctx->new_packmode;
+        ++ts;
+        break;
+      case 'Z':
+        got_Z = 1;
+        ++ts;
+        if (*ts != 'f' && *ts != 'd' && *ts != 'g') {
+          __Pyx_BufFmt_RaiseUnexpectedChar('Z');
+          return NULL;
+        }        /* fall through */
+      case 'c': case 'b': case 'B': case 'h': case 'H': case 'i': case 'I':
+      case 'l': case 'L': case 'q': case 'Q':
+      case 'f': case 'd': case 'g':
+      case 'O':
+        if (ctx->enc_type == *ts && got_Z == ctx->is_complex &&
+            ctx->enc_packmode == ctx->new_packmode) {
+          /* Continue pooling same type */
+          ctx->enc_count += ctx->new_count;
+        } else {
+          /* New type */
+          if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL;
+          ctx->enc_count = ctx->new_count;
+          ctx->enc_packmode = ctx->new_packmode;
+          ctx->enc_type = *ts;
+          ctx->is_complex = got_Z;
+        }
+        ++ts;
+        ctx->new_count = 1;
+        got_Z = 0;
+        break;
+      case ':':
+        ++ts;
+        while(*ts != ':') ++ts;
+        ++ts;
+        break;
+      default:
+        {
+          int number = __Pyx_BufFmt_ParseNumber(&ts);
+          if (number == -1) { /* First char was not a digit */
+            PyErr_Format(PyExc_ValueError,
+                         "Does not understand character buffer dtype format string ('%c')", *ts);
+            return NULL;
+          }
+          ctx->new_count = (size_t)number; 
+        }
+    }
+  }
+}
+
+static CYTHON_INLINE void __Pyx_ZeroBuffer(Py_buffer* buf) {
+  buf->buf = NULL;
+  buf->obj = NULL;
+  buf->strides = __Pyx_zeros;
+  buf->shape = __Pyx_zeros;
+  buf->suboffsets = __Pyx_minusones;
+}
+
+static CYTHON_INLINE int __Pyx_GetBufferAndValidate(Py_buffer* buf, PyObject* obj, __Pyx_TypeInfo* dtype, int flags, int nd, int cast, __Pyx_BufFmt_StackElem* stack) {
+  if (obj == Py_None || obj == NULL) {
+    __Pyx_ZeroBuffer(buf);
+    return 0;
+  }
+  buf->buf = NULL;
+  if (__Pyx_GetBuffer(obj, buf, flags) == -1) goto fail;
+  if (buf->ndim != nd) {
+    PyErr_Format(PyExc_ValueError,
+                 "Buffer has wrong number of dimensions (expected %d, got %d)",
+                 nd, buf->ndim);
+    goto fail;
+  }
+  if (!cast) {
+    __Pyx_BufFmt_Context ctx;
+    __Pyx_BufFmt_Init(&ctx, stack, dtype);
+    if (!__Pyx_BufFmt_CheckString(&ctx, buf->format)) goto fail;
+  }
+  if ((unsigned)buf->itemsize != dtype->size) {
+    PyErr_Format(PyExc_ValueError,
+      "Item size of buffer (%"PY_FORMAT_SIZE_T"d byte%s) does not match size of '%s' (%"PY_FORMAT_SIZE_T"d byte%s)",
+      buf->itemsize, (buf->itemsize > 1) ? "s" : "",
+      dtype->name, (Py_ssize_t)dtype->size, (dtype->size > 1) ? "s" : "");
+    goto fail;
+  }
+  if (buf->suboffsets == NULL) buf->suboffsets = __Pyx_minusones;
+  return 0;
+fail:;
+  __Pyx_ZeroBuffer(buf);
+  return -1;
+}
+
+static CYTHON_INLINE void __Pyx_SafeReleaseBuffer(Py_buffer* info) {
+  if (info->buf == NULL) return;
+  if (info->suboffsets == __Pyx_minusones) info->suboffsets = NULL;
+  __Pyx_ReleaseBuffer(info);
+}
+
+static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) {
+    if (unlikely(!type)) {
+        PyErr_Format(PyExc_SystemError, "Missing type object");
+        return 0;
+    }
+    if (likely(PyObject_TypeCheck(obj, type)))
+        return 1;
+    PyErr_Format(PyExc_TypeError, "Cannot convert %.200s to %.200s",
+                 Py_TYPE(obj)->tp_name, type->tp_name);
+    return 0;
+}
+static void __Pyx_RaiseBufferIndexError(int axis) {
+  PyErr_Format(PyExc_IndexError,
+     "Out of bounds on buffer access (axis %d)", axis);
+}
+
+
+static CYTHON_INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index) {
+    PyErr_Format(PyExc_ValueError,
+                 "need more than %"PY_FORMAT_SIZE_T"d value%s to unpack",
+                 index, (index == 1) ? "" : "s");
+}
+
+static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(Py_ssize_t expected) {
+    PyErr_Format(PyExc_ValueError,
+                 "too many values to unpack (expected %"PY_FORMAT_SIZE_T"d)", expected);
+}
+
+static CYTHON_INLINE void __Pyx_RaiseNoneNotIterableError(void) {
+    PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable");
+}
+
+static void __Pyx_UnpackTupleError(PyObject *t, Py_ssize_t index) {
+    if (t == Py_None) {
+      __Pyx_RaiseNoneNotIterableError();
+    } else if (PyTuple_GET_SIZE(t) < index) {
+      __Pyx_RaiseNeedMoreValuesError(PyTuple_GET_SIZE(t));
+    } else {
+      __Pyx_RaiseTooManyValuesError(index);
+    }
+}
+
+#if PY_MAJOR_VERSION < 3
+static int __Pyx_GetBuffer(PyObject *obj, Py_buffer *view, int flags) {
+  #if PY_VERSION_HEX >= 0x02060000
+  if (PyObject_CheckBuffer(obj)) return PyObject_GetBuffer(obj, view, flags);
+  #endif
+  if (PyObject_TypeCheck(obj, __pyx_ptype_5numpy_ndarray)) return __pyx_pf_5numpy_7ndarray___getbuffer__(obj, view, flags);
+  else {
+  PyErr_Format(PyExc_TypeError, "'%100s' does not have the buffer interface", Py_TYPE(obj)->tp_name);
+  return -1;
+    }
+}
+
+static void __Pyx_ReleaseBuffer(Py_buffer *view) {
+  PyObject* obj = view->obj;
+  if (obj) {
+    #if PY_VERSION_HEX >= 0x02060000
+    if (PyObject_CheckBuffer(obj)) {PyBuffer_Release(view); return;}
+    #endif
+    if (PyObject_TypeCheck(obj, __pyx_ptype_5numpy_ndarray)) __pyx_pf_5numpy_7ndarray_1__releasebuffer__(obj, view);
+    Py_DECREF(obj);
+    view->obj = NULL;
+  }
+}
+
+#endif
+
+static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, long level) {
+    PyObject *py_import = 0;
+    PyObject *empty_list = 0;
+    PyObject *module = 0;
+    PyObject *global_dict = 0;
+    PyObject *empty_dict = 0;
+    PyObject *list;
+    py_import = __Pyx_GetAttrString(__pyx_b, "__import__");
+    if (!py_import)
+        goto bad;
+    if (from_list)
+        list = from_list;
+    else {
+        empty_list = PyList_New(0);
+        if (!empty_list)
+            goto bad;
+        list = empty_list;
+    }
+    global_dict = PyModule_GetDict(__pyx_m);
+    if (!global_dict)
+        goto bad;
+    empty_dict = PyDict_New();
+    if (!empty_dict)
+        goto bad;
+    #if PY_VERSION_HEX >= 0x02050000
+    {
+        PyObject *py_level = PyInt_FromLong(level);
+        if (!py_level)
+            goto bad;
+        module = PyObject_CallFunctionObjArgs(py_import,
+            name, global_dict, empty_dict, list, py_level, NULL);
+        Py_DECREF(py_level);
+    }
+    #else
+    if (level>0) {
+        PyErr_SetString(PyExc_RuntimeError, "Relative import is not supported for Python <=2.4.");
+        goto bad;
+    }
+    module = PyObject_CallFunctionObjArgs(py_import,
+        name, global_dict, empty_dict, list, NULL);
+    #endif
+bad:
+    Py_XDECREF(empty_list);
+    Py_XDECREF(py_import);
+    Py_XDECREF(empty_dict);
+    return module;
+}
+
+#if CYTHON_CCOMPLEX
+  #ifdef __cplusplus
+    static CYTHON_INLINE __pyx_t_float_complex __pyx_t_float_complex_from_parts(float x, float y) {
+      return ::std::complex< float >(x, y);
+    }
+  #else
+    static CYTHON_INLINE __pyx_t_float_complex __pyx_t_float_complex_from_parts(float x, float y) {
+      return x + y*(__pyx_t_float_complex)_Complex_I;
+    }
+  #endif
+#else
+    static CYTHON_INLINE __pyx_t_float_complex __pyx_t_float_complex_from_parts(float x, float y) {
+      __pyx_t_float_complex z;
+      z.real = x;
+      z.imag = y;
+      return z;
+    }
+#endif
+
+#if CYTHON_CCOMPLEX
+#else
+    static CYTHON_INLINE int __Pyx_c_eqf(__pyx_t_float_complex a, __pyx_t_float_complex b) {
+       return (a.real == b.real) && (a.imag == b.imag);
+    }
+    static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_sumf(__pyx_t_float_complex a, __pyx_t_float_complex b) {
+        __pyx_t_float_complex z;
+        z.real = a.real + b.real;
+        z.imag = a.imag + b.imag;
+        return z;
+    }
+    static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_difff(__pyx_t_float_complex a, __pyx_t_float_complex b) {
+        __pyx_t_float_complex z;
+        z.real = a.real - b.real;
+        z.imag = a.imag - b.imag;
+        return z;
+    }
+    static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_prodf(__pyx_t_float_complex a, __pyx_t_float_complex b) {
+        __pyx_t_float_complex z;
+        z.real = a.real * b.real - a.imag * b.imag;
+        z.imag = a.real * b.imag + a.imag * b.real;
+        return z;
+    }
+    static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_quotf(__pyx_t_float_complex a, __pyx_t_float_complex b) {
+        __pyx_t_float_complex z;
+        float denom = b.real * b.real + b.imag * b.imag;
+        z.real = (a.real * b.real + a.imag * b.imag) / denom;
+        z.imag = (a.imag * b.real - a.real * b.imag) / denom;
+        return z;
+    }
+    static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_negf(__pyx_t_float_complex a) {
+        __pyx_t_float_complex z;
+        z.real = -a.real;
+        z.imag = -a.imag;
+        return z;
+    }
+    static CYTHON_INLINE int __Pyx_c_is_zerof(__pyx_t_float_complex a) {
+       return (a.real == 0) && (a.imag == 0);
+    }
+    static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_conjf(__pyx_t_float_complex a) {
+        __pyx_t_float_complex z;
+        z.real =  a.real;
+        z.imag = -a.imag;
+        return z;
+    }
+    #if 1
+        static CYTHON_INLINE float __Pyx_c_absf(__pyx_t_float_complex z) {
+          #if !defined(HAVE_HYPOT) || defined(_MSC_VER)
+            return sqrtf(z.real*z.real + z.imag*z.imag);
+          #else
+            return hypotf(z.real, z.imag);
+          #endif
+        }
+        static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_powf(__pyx_t_float_complex a, __pyx_t_float_complex b) {
+            __pyx_t_float_complex z;
+            float r, lnr, theta, z_r, z_theta;
+            if (b.imag == 0 && b.real == (int)b.real) {
+                if (b.real < 0) {
+                    float denom = a.real * a.real + a.imag * a.imag;
+                    a.real = a.real / denom;
+                    a.imag = -a.imag / denom;
+                    b.real = -b.real;
+                }
+                switch ((int)b.real) {
+                    case 0:
+                        z.real = 1;
+                        z.imag = 0;
+                        return z;
+                    case 1:
+                        return a;
+                    case 2:
+                        z = __Pyx_c_prodf(a, a);
+                        return __Pyx_c_prodf(a, a);
+                    case 3:
+                        z = __Pyx_c_prodf(a, a);
+                        return __Pyx_c_prodf(z, a);
+                    case 4:
+                        z = __Pyx_c_prodf(a, a);
+                        return __Pyx_c_prodf(z, z);
+                }
+            }
+            if (a.imag == 0) {
+                if (a.real == 0) {
+                    return a;
+                }
+                r = a.real;
+                theta = 0;
+            } else {
+                r = __Pyx_c_absf(a);
+                theta = atan2f(a.imag, a.real);
+            }
+            lnr = logf(r);
+            z_r = expf(lnr * b.real - theta * b.imag);
+            z_theta = theta * b.real + lnr * b.imag;
+            z.real = z_r * cosf(z_theta);
+            z.imag = z_r * sinf(z_theta);
+            return z;
+        }
+    #endif
+#endif
+
+#if CYTHON_CCOMPLEX
+  #ifdef __cplusplus
+    static CYTHON_INLINE __pyx_t_double_complex __pyx_t_double_complex_from_parts(double x, double y) {
+      return ::std::complex< double >(x, y);
+    }
+  #else
+    static CYTHON_INLINE __pyx_t_double_complex __pyx_t_double_complex_from_parts(double x, double y) {
+      return x + y*(__pyx_t_double_complex)_Complex_I;
+    }
+  #endif
+#else
+    static CYTHON_INLINE __pyx_t_double_complex __pyx_t_double_complex_from_parts(double x, double y) {
+      __pyx_t_double_complex z;
+      z.real = x;
+      z.imag = y;
+      return z;
+    }
+#endif
+
+#if CYTHON_CCOMPLEX
+#else
+    static CYTHON_INLINE int __Pyx_c_eq(__pyx_t_double_complex a, __pyx_t_double_complex b) {
+       return (a.real == b.real) && (a.imag == b.imag);
+    }
+    static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_sum(__pyx_t_double_complex a, __pyx_t_double_complex b) {
+        __pyx_t_double_complex z;
+        z.real = a.real + b.real;
+        z.imag = a.imag + b.imag;
+        return z;
+    }
+    static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_diff(__pyx_t_double_complex a, __pyx_t_double_complex b) {
+        __pyx_t_double_complex z;
+        z.real = a.real - b.real;
+        z.imag = a.imag - b.imag;
+        return z;
+    }
+    static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_prod(__pyx_t_double_complex a, __pyx_t_double_complex b) {
+        __pyx_t_double_complex z;
+        z.real = a.real * b.real - a.imag * b.imag;
+        z.imag = a.real * b.imag + a.imag * b.real;
+        return z;
+    }
+    static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_quot(__pyx_t_double_complex a, __pyx_t_double_complex b) {
+        __pyx_t_double_complex z;
+        double denom = b.real * b.real + b.imag * b.imag;
+        z.real = (a.real * b.real + a.imag * b.imag) / denom;
+        z.imag = (a.imag * b.real - a.real * b.imag) / denom;
+        return z;
+    }
+    static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_neg(__pyx_t_double_complex a) {
+        __pyx_t_double_complex z;
+        z.real = -a.real;
+        z.imag = -a.imag;
+        return z;
+    }
+    static CYTHON_INLINE int __Pyx_c_is_zero(__pyx_t_double_complex a) {
+       return (a.real == 0) && (a.imag == 0);
+    }
+    static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_conj(__pyx_t_double_complex a) {
+        __pyx_t_double_complex z;
+        z.real =  a.real;
+        z.imag = -a.imag;
+        return z;
+    }
+    #if 1
+        static CYTHON_INLINE double __Pyx_c_abs(__pyx_t_double_complex z) {
+          #if !defined(HAVE_HYPOT) || defined(_MSC_VER)
+            return sqrt(z.real*z.real + z.imag*z.imag);
+          #else
+            return hypot(z.real, z.imag);
+          #endif
+        }
+        static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_pow(__pyx_t_double_complex a, __pyx_t_double_complex b) {
+            __pyx_t_double_complex z;
+            double r, lnr, theta, z_r, z_theta;
+            if (b.imag == 0 && b.real == (int)b.real) {
+                if (b.real < 0) {
+                    double denom = a.real * a.real + a.imag * a.imag;
+                    a.real = a.real / denom;
+                    a.imag = -a.imag / denom;
+                    b.real = -b.real;
+                }
+                switch ((int)b.real) {
+                    case 0:
+                        z.real = 1;
+                        z.imag = 0;
+                        return z;
+                    case 1:
+                        return a;
+                    case 2:
+                        z = __Pyx_c_prod(a, a);
+                        return __Pyx_c_prod(a, a);
+                    case 3:
+                        z = __Pyx_c_prod(a, a);
+                        return __Pyx_c_prod(z, a);
+                    case 4:
+                        z = __Pyx_c_prod(a, a);
+                        return __Pyx_c_prod(z, z);
+                }
+            }
+            if (a.imag == 0) {
+                if (a.real == 0) {
+                    return a;
+                }
+                r = a.real;
+                theta = 0;
+            } else {
+                r = __Pyx_c_abs(a);
+                theta = atan2(a.imag, a.real);
+            }
+            lnr = log(r);
+            z_r = exp(lnr * b.real - theta * b.imag);
+            z_theta = theta * b.real + lnr * b.imag;
+            z.real = z_r * cos(z_theta);
+            z.imag = z_r * sin(z_theta);
+            return z;
+        }
+    #endif
+#endif
+
+static CYTHON_INLINE unsigned char __Pyx_PyInt_AsUnsignedChar(PyObject* x) {
+    const unsigned char neg_one = (unsigned char)-1, const_zero = 0;
+    const int is_unsigned = neg_one > const_zero;
+    if (sizeof(unsigned char) < sizeof(long)) {
+        long val = __Pyx_PyInt_AsLong(x);
+        if (unlikely(val != (long)(unsigned char)val)) {
+            if (!unlikely(val == -1 && PyErr_Occurred())) {
+                PyErr_SetString(PyExc_OverflowError,
+                    (is_unsigned && unlikely(val < 0)) ?
+                    "can't convert negative value to unsigned char" :
+                    "value too large to convert to unsigned char");
+            }
+            return (unsigned char)-1;
+        }
+        return (unsigned char)val;
+    }
+    return (unsigned char)__Pyx_PyInt_AsUnsignedLong(x);
+}
+
+static CYTHON_INLINE unsigned short __Pyx_PyInt_AsUnsignedShort(PyObject* x) {
+    const unsigned short neg_one = (unsigned short)-1, const_zero = 0;
+    const int is_unsigned = neg_one > const_zero;
+    if (sizeof(unsigned short) < sizeof(long)) {
+        long val = __Pyx_PyInt_AsLong(x);
+        if (unlikely(val != (long)(unsigned short)val)) {
+            if (!unlikely(val == -1 && PyErr_Occurred())) {
+                PyErr_SetString(PyExc_OverflowError,
+                    (is_unsigned && unlikely(val < 0)) ?
+                    "can't convert negative value to unsigned short" :
+                    "value too large to convert to unsigned short");
+            }
+            return (unsigned short)-1;
+        }
+        return (unsigned short)val;
+    }
+    return (unsigned short)__Pyx_PyInt_AsUnsignedLong(x);
+}
+
+static CYTHON_INLINE unsigned int __Pyx_PyInt_AsUnsignedInt(PyObject* x) {
+    const unsigned int neg_one = (unsigned int)-1, const_zero = 0;
+    const int is_unsigned = neg_one > const_zero;
+    if (sizeof(unsigned int) < sizeof(long)) {
+        long val = __Pyx_PyInt_AsLong(x);
+        if (unlikely(val != (long)(unsigned int)val)) {
+            if (!unlikely(val == -1 && PyErr_Occurred())) {
+                PyErr_SetString(PyExc_OverflowError,
+                    (is_unsigned && unlikely(val < 0)) ?
+                    "can't convert negative value to unsigned int" :
+                    "value too large to convert to unsigned int");
+            }
+            return (unsigned int)-1;
+        }
+        return (unsigned int)val;
+    }
+    return (unsigned int)__Pyx_PyInt_AsUnsignedLong(x);
+}
+
+static CYTHON_INLINE char __Pyx_PyInt_AsChar(PyObject* x) {
+    const char neg_one = (char)-1, const_zero = 0;
+    const int is_unsigned = neg_one > const_zero;
+    if (sizeof(char) < sizeof(long)) {
+        long val = __Pyx_PyInt_AsLong(x);
+        if (unlikely(val != (long)(char)val)) {
+            if (!unlikely(val == -1 && PyErr_Occurred())) {
+                PyErr_SetString(PyExc_OverflowError,
+                    (is_unsigned && unlikely(val < 0)) ?
+                    "can't convert negative value to char" :
+                    "value too large to convert to char");
+            }
+            return (char)-1;
+        }
+        return (char)val;
+    }
+    return (char)__Pyx_PyInt_AsLong(x);
+}
+
+static CYTHON_INLINE short __Pyx_PyInt_AsShort(PyObject* x) {
+    const short neg_one = (short)-1, const_zero = 0;
+    const int is_unsigned = neg_one > const_zero;
+    if (sizeof(short) < sizeof(long)) {
+        long val = __Pyx_PyInt_AsLong(x);
+        if (unlikely(val != (long)(short)val)) {
+            if (!unlikely(val == -1 && PyErr_Occurred())) {
+                PyErr_SetString(PyExc_OverflowError,
+                    (is_unsigned && unlikely(val < 0)) ?
+                    "can't convert negative value to short" :
+                    "value too large to convert to short");
+            }
+            return (short)-1;
+        }
+        return (short)val;
+    }
+    return (short)__Pyx_PyInt_AsLong(x);
+}
+
+static CYTHON_INLINE int __Pyx_PyInt_AsInt(PyObject* x) {
+    const int neg_one = (int)-1, const_zero = 0;
+    const int is_unsigned = neg_one > const_zero;
+    if (sizeof(int) < sizeof(long)) {
+        long val = __Pyx_PyInt_AsLong(x);
+        if (unlikely(val != (long)(int)val)) {
+            if (!unlikely(val == -1 && PyErr_Occurred())) {
+                PyErr_SetString(PyExc_OverflowError,
+                    (is_unsigned && unlikely(val < 0)) ?
+                    "can't convert negative value to int" :
+                    "value too large to convert to int");
+            }
+            return (int)-1;
+        }
+        return (int)val;
+    }
+    return (int)__Pyx_PyInt_AsLong(x);
+}
+
+static CYTHON_INLINE signed char __Pyx_PyInt_AsSignedChar(PyObject* x) {
+    const signed char neg_one = (signed char)-1, const_zero = 0;
+    const int is_unsigned = neg_one > const_zero;
+    if (sizeof(signed char) < sizeof(long)) {
+        long val = __Pyx_PyInt_AsLong(x);
+        if (unlikely(val != (long)(signed char)val)) {
+            if (!unlikely(val == -1 && PyErr_Occurred())) {
+                PyErr_SetString(PyExc_OverflowError,
+                    (is_unsigned && unlikely(val < 0)) ?
+                    "can't convert negative value to signed char" :
+                    "value too large to convert to signed char");
+            }
+            return (signed char)-1;
+        }
+        return (signed char)val;
+    }
+    return (signed char)__Pyx_PyInt_AsSignedLong(x);
+}
+
+static CYTHON_INLINE signed short __Pyx_PyInt_AsSignedShort(PyObject* x) {
+    const signed short neg_one = (signed short)-1, const_zero = 0;
+    const int is_unsigned = neg_one > const_zero;
+    if (sizeof(signed short) < sizeof(long)) {
+        long val = __Pyx_PyInt_AsLong(x);
+        if (unlikely(val != (long)(signed short)val)) {
+            if (!unlikely(val == -1 && PyErr_Occurred())) {
+                PyErr_SetString(PyExc_OverflowError,
+                    (is_unsigned && unlikely(val < 0)) ?
+                    "can't convert negative value to signed short" :
+                    "value too large to convert to signed short");
+            }
+            return (signed short)-1;
+        }
+        return (signed short)val;
+    }
+    return (signed short)__Pyx_PyInt_AsSignedLong(x);
+}
+
+static CYTHON_INLINE signed int __Pyx_PyInt_AsSignedInt(PyObject* x) {
+    const signed int neg_one = (signed int)-1, const_zero = 0;
+    const int is_unsigned = neg_one > const_zero;
+    if (sizeof(signed int) < sizeof(long)) {
+        long val = __Pyx_PyInt_AsLong(x);
+        if (unlikely(val != (long)(signed int)val)) {
+            if (!unlikely(val == -1 && PyErr_Occurred())) {
+                PyErr_SetString(PyExc_OverflowError,
+                    (is_unsigned && unlikely(val < 0)) ?
+                    "can't convert negative value to signed int" :
+                    "value too large to convert to signed int");
+            }
+            return (signed int)-1;
+        }
+        return (signed int)val;
+    }
+    return (signed int)__Pyx_PyInt_AsSignedLong(x);
+}
+
+static CYTHON_INLINE int __Pyx_PyInt_AsLongDouble(PyObject* x) {
+    const int neg_one = (int)-1, const_zero = 0;
+    const int is_unsigned = neg_one > const_zero;
+    if (sizeof(int) < sizeof(long)) {
+        long val = __Pyx_PyInt_AsLong(x);
+        if (unlikely(val != (long)(int)val)) {
+            if (!unlikely(val == -1 && PyErr_Occurred())) {
+                PyErr_SetString(PyExc_OverflowError,
+                    (is_unsigned && unlikely(val < 0)) ?
+                    "can't convert negative value to int" :
+                    "value too large to convert to int");
+            }
+            return (int)-1;
+        }
+        return (int)val;
+    }
+    return (int)__Pyx_PyInt_AsLong(x);
+}
+
+static CYTHON_INLINE unsigned long __Pyx_PyInt_AsUnsignedLong(PyObject* x) {
+    const unsigned long neg_one = (unsigned long)-1, const_zero = 0;
+    const int is_unsigned = neg_one > const_zero;
+#if PY_VERSION_HEX < 0x03000000
+    if (likely(PyInt_Check(x))) {
+        long val = PyInt_AS_LONG(x);
+        if (is_unsigned && unlikely(val < 0)) {
+            PyErr_SetString(PyExc_OverflowError,
+                            "can't convert negative value to unsigned long");
+            return (unsigned long)-1;
+        }
+        return (unsigned long)val;
+    } else
+#endif
+    if (likely(PyLong_Check(x))) {
+        if (is_unsigned) {
+            if (unlikely(Py_SIZE(x) < 0)) {
+                PyErr_SetString(PyExc_OverflowError,
+                                "can't convert negative value to unsigned long");
+                return (unsigned long)-1;
+            }
+            return (unsigned long)PyLong_AsUnsignedLong(x);
+        } else {
+            return (unsigned long)PyLong_AsLong(x);
+        }
+    } else {
+        unsigned long val;
+        PyObject *tmp = __Pyx_PyNumber_Int(x);
+        if (!tmp) return (unsigned long)-1;
+        val = __Pyx_PyInt_AsUnsignedLong(tmp);
+        Py_DECREF(tmp);
+        return val;
+    }
+}
+
+static CYTHON_INLINE unsigned PY_LONG_LONG __Pyx_PyInt_AsUnsignedLongLong(PyObject* x) {
+    const unsigned PY_LONG_LONG neg_one = (unsigned PY_LONG_LONG)-1, const_zero = 0;
+    const int is_unsigned = neg_one > const_zero;
+#if PY_VERSION_HEX < 0x03000000
+    if (likely(PyInt_Check(x))) {
+        long val = PyInt_AS_LONG(x);
+        if (is_unsigned && unlikely(val < 0)) {
+            PyErr_SetString(PyExc_OverflowError,
+                            "can't convert negative value to unsigned PY_LONG_LONG");
+            return (unsigned PY_LONG_LONG)-1;
+        }
+        return (unsigned PY_LONG_LONG)val;
+    } else
+#endif
+    if (likely(PyLong_Check(x))) {
+        if (is_unsigned) {
+            if (unlikely(Py_SIZE(x) < 0)) {
+                PyErr_SetString(PyExc_OverflowError,
+                                "can't convert negative value to unsigned PY_LONG_LONG");
+                return (unsigned PY_LONG_LONG)-1;
+            }
+            return (unsigned PY_LONG_LONG)PyLong_AsUnsignedLongLong(x);
+        } else {
+            return (unsigned PY_LONG_LONG)PyLong_AsLongLong(x);
+        }
+    } else {
+        unsigned PY_LONG_LONG val;
+        PyObject *tmp = __Pyx_PyNumber_Int(x);
+        if (!tmp) return (unsigned PY_LONG_LONG)-1;
+        val = __Pyx_PyInt_AsUnsignedLongLong(tmp);
+        Py_DECREF(tmp);
+        return val;
+    }
+}
+
+static CYTHON_INLINE long __Pyx_PyInt_AsLong(PyObject* x) {
+    const long neg_one = (long)-1, const_zero = 0;
+    const int is_unsigned = neg_one > const_zero;
+#if PY_VERSION_HEX < 0x03000000
+    if (likely(PyInt_Check(x))) {
+        long val = PyInt_AS_LONG(x);
+        if (is_unsigned && unlikely(val < 0)) {
+            PyErr_SetString(PyExc_OverflowError,
+                            "can't convert negative value to long");
+            return (long)-1;
+        }
+        return (long)val;
+    } else
+#endif
+    if (likely(PyLong_Check(x))) {
+        if (is_unsigned) {
+            if (unlikely(Py_SIZE(x) < 0)) {
+                PyErr_SetString(PyExc_OverflowError,
+                                "can't convert negative value to long");
+                return (long)-1;
+            }
+            return (long)PyLong_AsUnsignedLong(x);
+        } else {
+            return (long)PyLong_AsLong(x);
+        }
+    } else {
+        long val;
+        PyObject *tmp = __Pyx_PyNumber_Int(x);
+        if (!tmp) return (long)-1;
+        val = __Pyx_PyInt_AsLong(tmp);
+        Py_DECREF(tmp);
+        return val;
+    }
+}
+
+static CYTHON_INLINE PY_LONG_LONG __Pyx_PyInt_AsLongLong(PyObject* x) {
+    const PY_LONG_LONG neg_one = (PY_LONG_LONG)-1, const_zero = 0;
+    const int is_unsigned = neg_one > const_zero;
+#if PY_VERSION_HEX < 0x03000000
+    if (likely(PyInt_Check(x))) {
+        long val = PyInt_AS_LONG(x);
+        if (is_unsigned && unlikely(val < 0)) {
+            PyErr_SetString(PyExc_OverflowError,
+                            "can't convert negative value to PY_LONG_LONG");
+            return (PY_LONG_LONG)-1;
+        }
+        return (PY_LONG_LONG)val;
+    } else
+#endif
+    if (likely(PyLong_Check(x))) {
+        if (is_unsigned) {
+            if (unlikely(Py_SIZE(x) < 0)) {
+                PyErr_SetString(PyExc_OverflowError,
+                                "can't convert negative value to PY_LONG_LONG");
+                return (PY_LONG_LONG)-1;
+            }
+            return (PY_LONG_LONG)PyLong_AsUnsignedLongLong(x);
+        } else {
+            return (PY_LONG_LONG)PyLong_AsLongLong(x);
+        }
+    } else {
+        PY_LONG_LONG val;
+        PyObject *tmp = __Pyx_PyNumber_Int(x);
+        if (!tmp) return (PY_LONG_LONG)-1;
+        val = __Pyx_PyInt_AsLongLong(tmp);
+        Py_DECREF(tmp);
+        return val;
+    }
+}
+
+static CYTHON_INLINE signed long __Pyx_PyInt_AsSignedLong(PyObject* x) {
+    const signed long neg_one = (signed long)-1, const_zero = 0;
+    const int is_unsigned = neg_one > const_zero;
+#if PY_VERSION_HEX < 0x03000000
+    if (likely(PyInt_Check(x))) {
+        long val = PyInt_AS_LONG(x);
+        if (is_unsigned && unlikely(val < 0)) {
+            PyErr_SetString(PyExc_OverflowError,
+                            "can't convert negative value to signed long");
+            return (signed long)-1;
+        }
+        return (signed long)val;
+    } else
+#endif
+    if (likely(PyLong_Check(x))) {
+        if (is_unsigned) {
+            if (unlikely(Py_SIZE(x) < 0)) {
+                PyErr_SetString(PyExc_OverflowError,
+                                "can't convert negative value to signed long");
+                return (signed long)-1;
+            }
+            return (signed long)PyLong_AsUnsignedLong(x);
+        } else {
+            return (signed long)PyLong_AsLong(x);
+        }
+    } else {
+        signed long val;
+        PyObject *tmp = __Pyx_PyNumber_Int(x);
+        if (!tmp) return (signed long)-1;
+        val = __Pyx_PyInt_AsSignedLong(tmp);
+        Py_DECREF(tmp);
+        return val;
+    }
+}
+
+static CYTHON_INLINE signed PY_LONG_LONG __Pyx_PyInt_AsSignedLongLong(PyObject* x) {
+    const signed PY_LONG_LONG neg_one = (signed PY_LONG_LONG)-1, const_zero = 0;
+    const int is_unsigned = neg_one > const_zero;
+#if PY_VERSION_HEX < 0x03000000
+    if (likely(PyInt_Check(x))) {
+        long val = PyInt_AS_LONG(x);
+        if (is_unsigned && unlikely(val < 0)) {
+            PyErr_SetString(PyExc_OverflowError,
+                            "can't convert negative value to signed PY_LONG_LONG");
+            return (signed PY_LONG_LONG)-1;
+        }
+        return (signed PY_LONG_LONG)val;
+    } else
+#endif
+    if (likely(PyLong_Check(x))) {
+        if (is_unsigned) {
+            if (unlikely(Py_SIZE(x) < 0)) {
+                PyErr_SetString(PyExc_OverflowError,
+                                "can't convert negative value to signed PY_LONG_LONG");
+                return (signed PY_LONG_LONG)-1;
+            }
+            return (signed PY_LONG_LONG)PyLong_AsUnsignedLongLong(x);
+        } else {
+            return (signed PY_LONG_LONG)PyLong_AsLongLong(x);
+        }
+    } else {
+        signed PY_LONG_LONG val;
+        PyObject *tmp = __Pyx_PyNumber_Int(x);
+        if (!tmp) return (signed PY_LONG_LONG)-1;
+        val = __Pyx_PyInt_AsSignedLongLong(tmp);
+        Py_DECREF(tmp);
+        return val;
+    }
+}
+
+static int __Pyx_check_binary_version(void) {
+    char ctversion[4], rtversion[4];
+    PyOS_snprintf(ctversion, 4, "%d.%d", PY_MAJOR_VERSION, PY_MINOR_VERSION);
+    PyOS_snprintf(rtversion, 4, "%s", Py_GetVersion());
+    if (ctversion[0] != rtversion[0] || ctversion[2] != rtversion[2]) {
+        char message[200];
+        PyOS_snprintf(message, sizeof(message),
+                      "compiletime version %s of module '%.100s' "
+                      "does not match runtime version %s",
+                      ctversion, __Pyx_MODULE_NAME, rtversion);
+        #if PY_VERSION_HEX < 0x02050000
+        return PyErr_Warn(NULL, message);
+        #else
+        return PyErr_WarnEx(NULL, message, 1);
+        #endif
+    }
+    return 0;
+}
+
+#ifndef __PYX_HAVE_RT_ImportType
+#define __PYX_HAVE_RT_ImportType
+static PyTypeObject *__Pyx_ImportType(const char *module_name, const char *class_name,
+    size_t size, int strict)
+{
+    PyObject *py_module = 0;
+    PyObject *result = 0;
+    PyObject *py_name = 0;
+    char warning[200];
+
+    py_module = __Pyx_ImportModule(module_name);
+    if (!py_module)
+        goto bad;
+    #if PY_MAJOR_VERSION < 3
+    py_name = PyString_FromString(class_name);
+    #else
+    py_name = PyUnicode_FromString(class_name);
+    #endif
+    if (!py_name)
+        goto bad;
+    result = PyObject_GetAttr(py_module, py_name);
+    Py_DECREF(py_name);
+    py_name = 0;
+    Py_DECREF(py_module);
+    py_module = 0;
+    if (!result)
+        goto bad;
+    if (!PyType_Check(result)) {
+        PyErr_Format(PyExc_TypeError,
+            "%s.%s is not a type object",
+            module_name, class_name);
+        goto bad;
+    }
+    if (!strict && ((PyTypeObject *)result)->tp_basicsize > (Py_ssize_t)size) {
+        PyOS_snprintf(warning, sizeof(warning),
+            "%s.%s size changed, may indicate binary incompatibility",
+            module_name, class_name);
+        #if PY_VERSION_HEX < 0x02050000
+        if (PyErr_Warn(NULL, warning) < 0) goto bad;
+        #else
+        if (PyErr_WarnEx(NULL, warning, 0) < 0) goto bad;
+        #endif
+    }
+    else if (((PyTypeObject *)result)->tp_basicsize != (Py_ssize_t)size) {
+        PyErr_Format(PyExc_ValueError,
+            "%s.%s has the wrong size, try recompiling",
+            module_name, class_name);
+        goto bad;
+    }
+    return (PyTypeObject *)result;
+bad:
+    Py_XDECREF(py_module);
+    Py_XDECREF(result);
+    return NULL;
+}
+#endif
+
+#ifndef __PYX_HAVE_RT_ImportModule
+#define __PYX_HAVE_RT_ImportModule
+static PyObject *__Pyx_ImportModule(const char *name) {
+    PyObject *py_name = 0;
+    PyObject *py_module = 0;
+
+    #if PY_MAJOR_VERSION < 3
+    py_name = PyString_FromString(name);
+    #else
+    py_name = PyUnicode_FromString(name);
+    #endif
+    if (!py_name)
+        goto bad;
+    py_module = PyImport_Import(py_name);
+    Py_DECREF(py_name);
+    return py_module;
+bad:
+    Py_XDECREF(py_name);
+    return 0;
+}
+#endif
+
+#include "compile.h"
+#include "frameobject.h"
+#include "traceback.h"
+
+static void __Pyx_AddTraceback(const char *funcname, int __pyx_clineno,
+                               int __pyx_lineno, const char *__pyx_filename) {
+    PyObject *py_srcfile = 0;
+    PyObject *py_funcname = 0;
+    PyObject *py_globals = 0;
+    PyCodeObject *py_code = 0;
+    PyFrameObject *py_frame = 0;
+
+    #if PY_MAJOR_VERSION < 3
+    py_srcfile = PyString_FromString(__pyx_filename);
+    #else
+    py_srcfile = PyUnicode_FromString(__pyx_filename);
+    #endif
+    if (!py_srcfile) goto bad;
+    if (__pyx_clineno) {
+        #if PY_MAJOR_VERSION < 3
+        py_funcname = PyString_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, __pyx_clineno);
+        #else
+        py_funcname = PyUnicode_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, __pyx_clineno);
+        #endif
+    }
+    else {
+        #if PY_MAJOR_VERSION < 3
+        py_funcname = PyString_FromString(funcname);
+        #else
+        py_funcname = PyUnicode_FromString(funcname);
+        #endif
+    }
+    if (!py_funcname) goto bad;
+    py_globals = PyModule_GetDict(__pyx_m);
+    if (!py_globals) goto bad;
+    py_code = PyCode_New(
+        0,            /*int argcount,*/
+        #if PY_MAJOR_VERSION >= 3
+        0,            /*int kwonlyargcount,*/
+        #endif
+        0,            /*int nlocals,*/
+        0,            /*int stacksize,*/
+        0,            /*int flags,*/
+        __pyx_empty_bytes, /*PyObject *code,*/
+        __pyx_empty_tuple,  /*PyObject *consts,*/
+        __pyx_empty_tuple,  /*PyObject *names,*/
+        __pyx_empty_tuple,  /*PyObject *varnames,*/
+        __pyx_empty_tuple,  /*PyObject *freevars,*/
+        __pyx_empty_tuple,  /*PyObject *cellvars,*/
+        py_srcfile,   /*PyObject *filename,*/
+        py_funcname,  /*PyObject *name,*/
+        __pyx_lineno,   /*int firstlineno,*/
+        __pyx_empty_bytes  /*PyObject *lnotab*/
+    );
+    if (!py_code) goto bad;
+    py_frame = PyFrame_New(
+        PyThreadState_GET(), /*PyThreadState *tstate,*/
+        py_code,             /*PyCodeObject *code,*/
+        py_globals,          /*PyObject *globals,*/
+        0                    /*PyObject *locals*/
+    );
+    if (!py_frame) goto bad;
+    py_frame->f_lineno = __pyx_lineno;
+    PyTraceBack_Here(py_frame);
+bad:
+    Py_XDECREF(py_srcfile);
+    Py_XDECREF(py_funcname);
+    Py_XDECREF(py_code);
+    Py_XDECREF(py_frame);
+}
+
+static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) {
+    while (t->p) {
+        #if PY_MAJOR_VERSION < 3
+        if (t->is_unicode) {
+            *t->p = PyUnicode_DecodeUTF8(t->s, t->n - 1, NULL);
+        } else if (t->intern) {
+            *t->p = PyString_InternFromString(t->s);
+        } else {
+            *t->p = PyString_FromStringAndSize(t->s, t->n - 1);
+        }
+        #else  /* Python 3+ has unicode identifiers */
+        if (t->is_unicode | t->is_str) {
+            if (t->intern) {
+                *t->p = PyUnicode_InternFromString(t->s);
+            } else if (t->encoding) {
+                *t->p = PyUnicode_Decode(t->s, t->n - 1, t->encoding, NULL);
+            } else {
+                *t->p = PyUnicode_FromStringAndSize(t->s, t->n - 1);
+            }
+        } else {
+            *t->p = PyBytes_FromStringAndSize(t->s, t->n - 1);
+        }
+        #endif
+        if (!*t->p)
+            return -1;
+        ++t;
+    }
+    return 0;
+}
+
+/* Type Conversion Functions */
+
+static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject* x) {
+   int is_true = x == Py_True;
+   if (is_true | (x == Py_False) | (x == Py_None)) return is_true;
+   else return PyObject_IsTrue(x);
+}
+
+static CYTHON_INLINE PyObject* __Pyx_PyNumber_Int(PyObject* x) {
+  PyNumberMethods *m;
+  const char *name = NULL;
+  PyObject *res = NULL;
+#if PY_VERSION_HEX < 0x03000000
+  if (PyInt_Check(x) || PyLong_Check(x))
+#else
+  if (PyLong_Check(x))
+#endif
+    return Py_INCREF(x), x;
+  m = Py_TYPE(x)->tp_as_number;
+#if PY_VERSION_HEX < 0x03000000
+  if (m && m->nb_int) {
+    name = "int";
+    res = PyNumber_Int(x);
+  }
+  else if (m && m->nb_long) {
+    name = "long";
+    res = PyNumber_Long(x);
+  }
+#else
+  if (m && m->nb_int) {
+    name = "int";
+    res = PyNumber_Long(x);
+  }
+#endif
+  if (res) {
+#if PY_VERSION_HEX < 0x03000000
+    if (!PyInt_Check(res) && !PyLong_Check(res)) {
+#else
+    if (!PyLong_Check(res)) {
+#endif
+      PyErr_Format(PyExc_TypeError,
+                   "__%s__ returned non-%s (type %.200s)",
+                   name, name, Py_TYPE(res)->tp_name);
+      Py_DECREF(res);
+      return NULL;
+    }
+  }
+  else if (!PyErr_Occurred()) {
+    PyErr_SetString(PyExc_TypeError,
+                    "an integer is required");
+  }
+  return res;
+}
+
+static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject* b) {
+  Py_ssize_t ival;
+  PyObject* x = PyNumber_Index(b);
+  if (!x) return -1;
+  ival = PyInt_AsSsize_t(x);
+  Py_DECREF(x);
+  return ival;
+}
+
+static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t ival) {
+#if PY_VERSION_HEX < 0x02050000
+   if (ival <= LONG_MAX)
+       return PyInt_FromLong((long)ival);
+   else {
+       unsigned char *bytes = (unsigned char *) &ival;
+       int one = 1; int little = (int)*(unsigned char*)&one;
+       return _PyLong_FromByteArray(bytes, sizeof(size_t), little, 0);
+   }
+#else
+   return PyInt_FromSize_t(ival);
+#endif
+}
+
+static CYTHON_INLINE size_t __Pyx_PyInt_AsSize_t(PyObject* x) {
+   unsigned PY_LONG_LONG val = __Pyx_PyInt_AsUnsignedLongLong(x);
+   if (unlikely(val == (unsigned PY_LONG_LONG)-1 && PyErr_Occurred())) {
+       return (size_t)-1;
+   } else if (unlikely(val != (unsigned PY_LONG_LONG)(size_t)val)) {
+       PyErr_SetString(PyExc_OverflowError,
+                       "value too large to convert to size_t");
+       return (size_t)-1;
+   }
+   return (size_t)val;
+}
+
+
+#endif /* Py_PYTHON_H */
diff --git a/astropy/time/sofa_time.pyx b/astropy/time/sofa_time.pyx
new file mode 100644
index 0000000..d56fddf
--- /dev/null
+++ b/astropy/time/sofa_time.pyx
@@ -0,0 +1,1439 @@
+import warnings
+
+import numpy as np
+cimport numpy as np
+import cython
+
+ctypedef np.double_t DOUBLE_T
+
+cdef extern from "sofa.h":
+    double iauEpb(double dj1, double dj2)
+    double iauEpj(double dj1, double dj2)
+    void iauEpj2jd(double epj, double *djm0, double *djm)
+    void iauEpb2jd(double epb, double *djm0, double *djm)
+    int iauCal2jd(int iy, int im, int id, double *djm0, double *djm)
+    int iauJd2cal(double dj1, double dj2,int *iy, int *im, int *id, double *fd)
+    int iauJdcalf(int ndp, double dj1, double dj2, int iymdf[4])
+
+    # Internal JD to/from datetime format converters
+    int iauD2dtf(char *scale, int ndp, double d1, double d2, int *iy, int *im, int *id, int ihmsf[4])
+    int iauDtf2d(char *scale, int iy, int im, int id, int ihr, int imn, double sec, double *d1, double *d2)
+
+    # Time scale helper routines
+    double iauDtdb(double date1, double date2, double ut, double elong, double u, double v)
+    int iauDat(int iy, int im, int id, double fd, double *deltat)
+
+    # Time scale conversion routines
+    int iauTaitt(double tai1, double tai2, double *tt1, double *tt2)
+    int iauTttai(double tt1, double tt2, double *tai1, double *tai2)
+    int iauTaiutc(double tai1, double tai2, double *utc1, double *utc2)
+    int iauUtctai(double utc1, double utc2, double *tai1, double *tai2)
+    int iauTcbtdb(double tcb1, double tcb2, double *tdb1, double *tdb2)
+    int iauTdbtcb(double tdb1, double tdb2, double *tcb1, double *tcb2)
+    int iauTcgtt(double tcg1, double tcg2, double *tt1, double *tt2)
+    int iauTttcg(double tt1, double tt2, double *tcg1, double *tcg2)
+
+    int iauTaiut1(double tai1, double tai2, double dta, double *ut11, double *ut12)
+    int iauUt1tai(double ut11, double ut12, double dta, double *tai1, double *tai2)
+    int iauTtut1(double tt1, double tt2, double dt, double *ut11, double *ut12)
+    int iauUt1tt(double ut11, double ut12, double dt, double *tt1, double *tt2)
+    int iauTdbtt(double tdb1, double tdb2, double dtr, double *tt1, double *tt2)
+    int iauTttdb(double tt1, double tt2, double dtr, double *tdb1, double *tdb2)
+    int iauUt1utc(double ut11, double ut12, double dut1, double *utc1, double *utc2)
+    int iauUtcut1(double utc1, double utc2, double dut1, double *ut11, double *ut12)
+
+    # Geodetic
+    int iauAf2a(char s, int ideg, int iamin, double asec, double *rad)
+    int iauGd2gc(int n, double elong, double phi, double height, double xyz[3])
+
+DUBIOUS = 'dubious year for UTC (before 1960.0 or 5 years ' \
+          'beyond last known leap second)'
+
+def check_return(ret, func_name, warns={}, errors={}):
+    """Check the return value from an iau routine"""
+    if ret in warns:
+        warnings.warn('{0}: {1}'.format(func_name, warns[ret]))
+    elif ret in errors:
+        raise ValueError('{0}: {1}'.format(func_name, errors[ret]))
+    elif ret != 0:
+        raise ValueError('Unexpected return code {0} from {1}'
+                         .format(repr(ret), func_name))
+
+
+ at cython.wraparound(False)
+ at cython.boundscheck(False)
+def cal2jd( 
+    np.ndarray[int, ndim=1] iy,
+    np.ndarray[int, ndim=1] im,
+    np.ndarray[int, ndim=1] id,
+    np.ndarray[double, ndim=1] djm0,
+    np.ndarray[double, ndim=1] djm):
+    """
+    int iauCal2jd(int iy, int im, int id, double *djm0, double *djm)
+    Calendar date to high-precision JD.
+
+    **  Given:
+    **     iy,im,id  int     year, month, day in Gregorian calendar (Note 1)
+    **
+    **  Returned:
+    **     djm0      double  MJD zero-point: always 2400000.5
+    **     djm       double  Modified Julian Date for 0 hrs
+    **
+    **  Returned (function value):
+    **               int     status:
+    **                           0 = OK
+    **                          -1 = bad year   (Note 3: JD not computed)
+    **                          -2 = bad month  (JD not computed)
+    **                          -3 = bad day    (JD computed)
+    **
+    **  Notes:
+    **
+    **  1) The algorithm used is valid from -4800 March 1, but this
+    **     implementation rejects dates before -4799 January 1.
+    **
+    **  2) The Julian Date is returned in two pieces, in the usual SOFA
+    **     manner, which is designed to preserve time resolution.  The
+    **     Julian Date is available as a single number by adding djm0 and
+    **     djm.
+    **
+    **  3) In early eras the conversion is from the "Proleptic Gregorian
+    **     Calendar";  no account is taken of the date(s) of adoption of
+    **     the Gregorian Calendar, nor is the AD/BC numbering convention
+    **     observed.
+    """
+    cdef unsigned int i
+    cdef unsigned n = iy.shape[0]
+    warns = {-3: 'Bad input day (JD still computed)'}
+    errs = {-1: 'Bad input year',
+             -2: 'Bad input month'}
+    for i in range(n):
+        ret = iauCal2jd( iy[i], im[i], id[i], &djm0[i], &djm[i])
+        check_return(ret, 'iauCal2jd', warns, errs)
+    return
+
+ at cython.wraparound(False)
+ at cython.boundscheck(False)
+def d_tai_utc(np.ndarray[int, ndim=1] iy,
+              np.ndarray[int, ndim=1] im,
+              np.ndarray[int, ndim=1] id,
+              np.ndarray[double, ndim=1] fd):
+    """
+    int iauDat(int iy, int im, int id, double fd, double *deltat)
+    For a given UTC date, calculate delta(AT) = TAI-UTC.
+
+    **  Given:
+    **     iy     int      UTC:  year (Notes 1 and 2)
+    **     im     int            month (Note 2)
+    **     id     int            day (Notes 2 and 3)
+    **     fd     double         fraction of day (Note 4)
+    **
+    **  Returned:
+    **     deltat double   TAI minus UTC, seconds
+    **
+    **  Returned (function value):
+    **            int      status (Note 5):
+    **                       1 = dubious year (Note 1)
+    **                       0 = OK
+    **                      -1 = bad year
+    **                      -2 = bad month
+    **                      -3 = bad day (Note 3)
+    **                      -4 = bad fraction (Note 4)
+    **
+    **  Notes:
+    **
+    **  1) UTC began at 1960 January 1.0 (JD 2436934.5) and it is improper
+    **     to call the function with an earlier date.  If this is attempted,
+    **     zero is returned together with a warning status.
+    **
+    **     Because leap seconds cannot, in principle, be predicted in
+    **     advance, a reliable check for dates beyond the valid range is
+    **     impossible.  To guard against gross errors, a year five or more
+    **     after the release year of the present function (see parameter
+    **     IYV) is considered dubious.  In this case a warning status is
+    **     returned but the result is computed in the normal way.
+    **
+    **     For both too-early and too-late years, the warning status is
+    **     j=+1.  This is distinct from the error status j=-1, which
+    **     signifies a year so early that JD could not be computed.
+    **
+    **  2) If the specified date is for a day which ends with a leap second,
+    **     the UTC-TAI value returned is for the period leading up to the
+    **     leap second.  If the date is for a day which begins as a leap
+    **     second ends, the UTC-TAI returned is for the period following the
+    **     leap second.
+    **
+    **  3) The day number must be in the normal calendar range, for example
+    **     1 through 30 for April.  The "almanac" convention of allowing
+    **     such dates as January 0 and December 32 is not supported in this
+    **     function, in order to avoid confusion near leap seconds.
+    **
+    **  4) The fraction of day is used only for dates before the
+    **     introduction of leap seconds, the first of which occurred at the
+    **     end of 1971.  It is tested for validity (zero to less than 1 is
+    **     the valid range) even if not used;  if invalid, zero is used and
+    **     status j=-4 is returned.  For many applications, setting fd to
+    **     zero is acceptable;  the resulting error is always less than 3 ms
+    **     (and occurs only pre-1972).
+    **
+    **  5) The status value returned in the case where there are multiple
+    **     errors refers to the first error detected.  For example, if the
+    **     month and day are 13 and 32 respectively, j=-2 (bad month)
+    **     will be returned.
+    **
+    **  6) In cases where a valid result is not available, zero is returned.
+
+    **                       1 = dubious year (Note 1)
+    **                       0 = OK
+    **                      -1 = bad year
+    **                      -2 = bad month
+    **                      -3 = bad day (Note 3)
+    **                      -4 = bad fraction (Note 4)
+
+    """
+    cdef int i
+    cdef int n = iy.shape[0]
+    assert (iy.shape[0] == im.shape[0] == id.shape[0] == fd.shape[0])
+
+    cdef np.ndarray[double, ndim=1] out = np.empty(n, dtype=np.double)
+
+    warns = {1: DUBIOUS}
+    errs = {-1: 'bad year',
+             -2: 'bad month (must be 1 to 12)',
+             -3: 'bad day (must be within normal calendar date for a month)',
+             -4: 'bad fraction of day'}
+    for i in range(n):
+        ret = iauDat(iy[i], im[i], id[i], fd[i],
+                     &out[i])
+        check_return(ret, 'iauDat', warns, errs)
+
+    return out
+
+
+ at cython.wraparound(False)
+ at cython.boundscheck(False)
+def jd_dtf(scale, ndp,
+              np.ndarray[double, ndim=1] d1,
+              np.ndarray[double, ndim=1] d2):
+    """
+    int iauD2dtf(const char *scale, int ndp, double d1, double d2,
+             int *iy, int *im, int *id, int ihmsf[4])
+
+    **  Given:
+    **     scale     char[]  time scale ID (Note 1)
+    **     ndp       int     resolution (Note 2)
+    **     d1,d2     double  time as a 2-part Julian Date (Notes 3,4)
+    **
+    **  Returned:
+    **     iy,im,id  int     year, month, day in Gregorian calendar (Note 5)
+    **     ihmsf     int[4]  hours, minutes, seconds, fraction (Note 1)
+    **
+    **  Returned (function value):
+    **               int     status: +1 = dubious year (Note 5)
+    **                                0 = OK
+    **                               -1 = unacceptable date (Note 6)
+    **
+    **  Notes:
+    **
+    **  1) scale identifies the time scale.  Only the value "UTC" (in upper
+    **     case) is significant, and enables handling of leap seconds (see
+    **     Note 4).
+    **
+    **  2) ndp is the number of decimal places in the seconds field, and can
+    **     have negative as well as positive values, such as:
+    **
+    **     ndp         resolution
+    **     -4            1 00 00
+    **     -3            0 10 00
+    **     -2            0 01 00
+    **     -1            0 00 10
+    **      0            0 00 01
+    **      1            0 00 00.1
+    **      2            0 00 00.01
+    **      3            0 00 00.001
+    **
+    **     The limits are platform dependent, but a safe range is -5 to +9.
+    **
+    **  3) d1+d2 is Julian Date, apportioned in any convenient way between
+    **     the two arguments, for example where d1 is the Julian Day Number
+    **     and d2 is the fraction of a day.  In the case of UTC, where the
+    **     use of JD is problematical, special conventions apply:  see the
+    **     next note.
+    **
+    **  4) JD cannot unambiguously represent UTC during a leap second unless
+    **     special measures are taken.  The SOFA internal convention is that
+    **     the quasi-JD day represents UTC days whether the length is 86399,
+    **     86400 or 86401 SI seconds.
+    **
+    **  5) The warning status "dubious year" flags UTCs that predate the
+    **     introduction of the time scale and that are too far in the future
+    **     to be trusted.  See iauDat for further details.
+    **
+    **  6) For calendar conventions and limitations, see iauCal2jd.
+    """
+    cdef int i
+    cdef int n = d1.shape[0]
+
+    cdef np.ndarray[int, ndim=1] iy = np.empty(n, dtype=np.intc)
+    cdef np.ndarray[int, ndim=1] im = np.empty(n, dtype=np.intc)
+    cdef np.ndarray[int, ndim=1] id = np.empty(n, dtype=np.intc)
+    cdef np.ndarray[int, ndim=2] ihmsf = np.empty((n, 4), dtype=np.intc)
+
+    warns = {1: DUBIOUS}
+    errs = {-1: 'unacceptable date'}
+
+    for i in range(n):
+        ret = iauD2dtf(scale, ndp, d1[i], d2[i],
+                     &iy[i], &im[i], &id[i], &ihmsf[i, 0])
+        check_return(ret, 'iauD2dtf', warns, errs)
+
+    return iy, im, id, ihmsf
+
+ at cython.wraparound(False)
+ at cython.boundscheck(False)
+def dtf_jd(scale,
+              np.ndarray[int, ndim=1] iy,
+              np.ndarray[int, ndim=1] im,
+              np.ndarray[int, ndim=1] id,
+              np.ndarray[int, ndim=1] ihr,
+              np.ndarray[int, ndim=1] imn,
+              np.ndarray[double, ndim=1] sec):
+    """
+    int iauDtf2d(char *scale, int iy, int im, int id, int ihr, int imn, double sec, double *d1, double *d2)
+
+    **  Given:
+    **     scale     char[]  time scale ID (Note 1)
+    **     iy,im,id  int     year, month, day in Gregorian calendar (Note 2)
+    **     ihr,imn   int     hour, minute
+    **     sec       double  seconds
+    **
+    **  Returned:
+    **     d1,d2     double  2-part Julian Date (Notes 3,4)
+    **
+    **  Returned (function value):
+    **               int     status: +3 = both of next two
+    **                               +2 = time is after end of day (Note 5)
+    **                               +1 = dubious year (Note 6)
+    **                                0 = OK
+    **                               -1 = bad year
+    **                               -2 = bad month
+    **                               -3 = bad day
+    **                               -4 = bad hour
+    **                               -5 = bad minute
+    **                               -6 = bad second (<0)
+    **
+    **  Notes:
+    **
+    **  1) scale identifies the time scale.  Only the value "UTC" (in upper
+    **     case) is significant, and enables handling of leap seconds (see
+    **     Note 4).
+    **
+    **  2) For calendar conventions and limitations, see iauCal2jd.
+    **
+    **  3) The sum of the results, d1+d2, is Julian Date, where normally d1
+    **     is the Julian Day Number and d2 is the fraction of a day.  In the
+    **     case of UTC, where the use of JD is problematical, special
+    **     conventions apply:  see the next note.
+    **
+    **  4) JD cannot unambiguously represent UTC during a leap second unless
+    **     special measures are taken.  The SOFA internal convention is that
+    **     the quasi-JD day represents UTC days whether the length is 86399,
+    **     86400 or 86401 SI seconds.
+    **
+    **  5) The warning status "time is after end of day" usually means that
+    **     the sec argument is greater than 60.0.  However, in a day ending
+    **     in a leap second the limit changes to 61.0 (or 59.0 in the case
+    **     of a negative leap second).
+    **
+    **  6) The warning status "dubious year" flags UTCs that predate the
+    **     introduction of the time scale and that are too far in the future
+    **     to be trusted.  See iauDat for further details.
+    **
+    **  7) Only in the case of continuous and regular time scales (TAI, TT,
+    **     TCG, TCB and TDB) is the result d1+d2 a Julian Date, strictly
+    **     speaking.  In the other cases (UT1 and UTC) the result must be
+    **     used with circumspection;  in particular the difference between
+    **     two such results cannot be interpreted as a precise time
+    **     interval.
+
+    """
+    cdef int i
+    cdef int n = iy.shape[0]
+    assert (iy.shape[0] == im.shape[0] == id.shape[0] ==
+            ihr.shape[0] == imn.shape[0] == sec.shape[0])
+
+    cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)
+    cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)
+
+    warns = {3: 'time is after end of day and ' + DUBIOUS,
+             2: 'time is after end of day',
+             1: DUBIOUS}
+    errs = {-1: 'bad year',
+            -2: 'bad month',
+            -3: 'bad day',
+            -4: 'bad hour',
+            -5: 'bad minute',
+            -6: 'bad second (< 0)'}
+
+    for i in range(n):
+        ret = iauDtf2d(scale, iy[i], im[i], id[i], ihr[i], imn[i], sec[i],
+                       &out1[i], &out2[i])
+        check_return(ret, 'iauDtf2d', warns, errs)
+
+    return out1, out2
+
+
+ at cython.wraparound(False)
+ at cython.boundscheck(False)
+def tai_tt( 
+    np.ndarray[double, ndim=1] in1,
+    np.ndarray[double, ndim=1] in2):
+    """
+    int iauTaitt(double tai1, double tai2, double *tt1, double *tt2)
+
+    **  Given:
+    **     tai1,tai2  double    TAI as a 2-part Julian Date
+    **
+    **  Returned:
+    **     tt1,tt2    double    TT as a 2-part Julian Date
+    **
+    **  Returned (function value):
+    **                int       status:  0 = OK
+    **
+    **  Note:
+    **
+    **     tai1+tai2 is Julian Date, apportioned in any convenient way
+    **     between the two arguments, for example where tai1 is the Julian
+    **     Day Number and tai2 is the fraction of a day.  The returned
+    **     tt1,tt2 follow suit.
+    """
+    assert in1.shape[0] == in2.shape[0]
+    cdef unsigned n = in1.shape[0]
+    cdef unsigned int i
+    cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)
+    cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)
+
+    for i in range(n):
+        ret = iauTaitt(in1[i], in2[i], &out1[i], &out2[i])
+        check_return(ret, 'iauTaitt')
+
+    return out1, out2
+
+
+ at cython.wraparound(False)
+ at cython.boundscheck(False)
+def tcb_tdb( 
+    np.ndarray[double, ndim=1] in1,
+    np.ndarray[double, ndim=1] in2):
+    """
+    int iauTcbtdb(double tcb1, double tcb2, double *tdb1, double *tdb2)
+
+    **  Given:
+    **     tcb1,tcb2  double    TCB as a 2-part Julian Date
+    **
+    **  Returned:
+    **     tdb1,tdb2  double    TDB as a 2-part Julian Date
+    **
+    **  Returned (function value):
+    **                int       status:  0 = OK
+    **
+    **  Notes:
+    **
+    **  1) tcb1+tcb2 is Julian Date, apportioned in any convenient way
+    **     between the two arguments, for example where tcb1 is the Julian
+    **     Day Number and tcb2 is the fraction of a day.  The returned
+    **     tdb1,tdb2 follow suit.
+    **
+    **  2) The 2006 IAU General Assembly introduced a conventional linear
+    **     transformation between TDB and TCB.  This transformation
+    **     compensates for the drift between TCB and terrestrial time TT,
+    **     and keeps TDB approximately centered on TT.  Because the
+    **     relationship between TT and TCB depends on the adopted solar
+    **     system ephemeris, the degree of alignment between TDB and TT over
+    **     long intervals will vary according to which ephemeris is used.
+    **     Former definitions of TDB attempted to avoid this problem by
+    **     stipulating that TDB and TT should differ only by periodic
+    **     effects.  This is a good description of the nature of the
+    **     relationship but eluded precise mathematical formulation.  The
+    **     conventional linear relationship adopted in 2006 sidestepped
+    **     these difficulties whilst delivering a TDB that in practice was
+    **     consistent with values before that date.
+    **
+    **  3) TDB is essentially the same as Teph, the time argument for the
+    **     JPL solar system ephemerides.
+    """
+
+    assert in1.shape[0] == in2.shape[0]
+    cdef unsigned n = in1.shape[0]
+    cdef unsigned int i
+    cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)
+    cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)
+
+    for i in range(n):
+        ret = iauTcbtdb(in1[i], in2[i], &out1[i], &out2[i])
+        check_return(ret, 'iauTcbtdb')
+
+    return out1, out2
+
+
+ at cython.wraparound(False)
+ at cython.boundscheck(False)
+def tcg_tt( 
+    np.ndarray[double, ndim=1] in1,
+    np.ndarray[double, ndim=1] in2):
+    """
+   int iauTcgtt(double tcg1, double tcg2, double *tt1, double *tt2)
+
+   **  Given:
+   **     tcg1,tcg2  double    TCG as a 2-part Julian Date
+   **
+   **  Returned:
+   **     tt1,tt2    double    TT as a 2-part Julian Date
+   **
+   **  Returned (function value):
+   **                int       status:  0 = OK
+    """
+
+    assert in1.shape[0] == in2.shape[0]
+    cdef unsigned n = in1.shape[0]
+    cdef unsigned int i
+    cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)
+    cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)
+
+    for i in range(n):
+        ret = iauTcgtt(in1[i], in2[i], &out1[i], &out2[i])
+        check_return(ret, 'iauTcgtt')
+
+    return out1, out2
+
+
+ at cython.wraparound(False)
+ at cython.boundscheck(False)
+def tdb_tcb( 
+    np.ndarray[double, ndim=1] in1,
+    np.ndarray[double, ndim=1] in2):
+    """
+    int iauTdbtcb(double tdb1, double tdb2, double *tcb1, double *tcb2)
+
+    **  Given:
+    **     tdb1,tdb2  double    TDB as a 2-part Julian Date
+    **
+    **  Returned:
+    **     tcb1,tcb2  double    TCB as a 2-part Julian Date
+    **
+    **  Returned (function value):
+    **                int       status:  0 = OK
+    """
+    assert in1.shape[0] == in2.shape[0]
+    cdef unsigned n = in1.shape[0]
+    cdef unsigned int i
+    cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)
+    cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)
+
+    for i in range(n):
+        ret = iauTdbtcb(in1[i], in2[i], &out1[i], &out2[i])
+        check_return(ret, 'iauTdbtcb')
+
+    return out1, out2
+
+
+ at cython.wraparound(False)
+ at cython.boundscheck(False)
+def tt_tai( 
+    np.ndarray[double, ndim=1] in1,
+    np.ndarray[double, ndim=1] in2):
+    """
+    int iauTttai(double tt1, double tt2, double *tai1, double *tai2)
+
+    **  Given:
+    **     tt1,tt2    double    TT as a 2-part Julian Date
+    **
+    **  Returned:
+    **     tai1,tai2  double    TAI as a 2-part Julian Date
+    **
+    **  Returned (function value):
+    **                int       status:  0 = OK
+    """
+    assert in1.shape[0] == in2.shape[0]
+    cdef unsigned n = in1.shape[0]
+    cdef unsigned int i
+    cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)
+    cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)
+
+    for i in range(n):
+        ret = iauTttai(in1[i], in2[i], &out1[i], &out2[i])
+        check_return(ret, 'iauTttai')
+
+    return out1, out2
+
+
+ at cython.wraparound(False)
+ at cython.boundscheck(False)
+def tt_tcg( 
+    np.ndarray[double, ndim=1] in1,
+    np.ndarray[double, ndim=1] in2):
+    """
+    int iauTttcg(double tt1, double tt2, double *tcg1, double *tcg2)
+    **  Given:
+    **     tt1,tt2    double    TT as a 2-part Julian Date
+    **
+    **  Returned:
+    **     tcg1,tcg2  double    TCG as a 2-part Julian Date
+    **
+    **  Returned (function value):
+    **                int       status:  0 = OK
+    """
+    assert in1.shape[0] == in2.shape[0]
+    cdef unsigned n = in1.shape[0]
+    cdef unsigned int i
+    cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)
+    cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)
+
+    for i in range(n):
+        ret = iauTttcg(in1[i], in2[i], &out1[i], &out2[i])
+        check_return(ret, 'iauTttcg')
+
+    return out1, out2
+
+
+ at cython.wraparound(False)
+ at cython.boundscheck(False)
+def utc_tai( 
+    np.ndarray[double, ndim=1] in1,
+    np.ndarray[double, ndim=1] in2):
+    """
+    int iauUtctai(double utc1, double utc2, double *tai1, double *tai2)
+
+    **  Given:
+    **     utc1,utc2  double   UTC as a 2-part quasi Julian Date (Notes 1-4)
+    **
+    **  Returned:
+    **     tai1,tai2  double   TAI as a 2-part Julian Date (Note 5)
+    **
+    **  Returned (function value):
+    **                int      status: +1 = dubious year (Note 3)
+    **                                  0 = OK
+    **                                 -1 = unacceptable date
+    **
+    **  Notes:
+    **
+    **  1) utc1+utc2 is quasi Julian Date (see Note 2), apportioned in any
+    **     convenient way between the two arguments, for example where utc1
+    **     is the Julian Day Number and utc2 is the fraction of a day.
+    **
+    **  2) JD cannot unambiguously represent UTC during a leap second unless
+    **     special measures are taken.  The convention in the present
+    **     function is that the JD day represents UTC days whether the
+    **     length is 86399, 86400 or 86401 SI seconds.
+    **
+    **  3) The warning status "dubious year" flags UTCs that predate the
+    **     introduction of the time scale and that are too far in the future
+    **     to be trusted.  See iauDat  for further details.
+    **
+    **  4) The function iauDtf2d converts from calendar date and time of day
+    **     into 2-part Julian Date, and in the case of UTC implements the
+    **     leap-second-ambiguity convention described above.
+    **
+    **  5) The returned TAI1,TAI2 are such that their sum is the TAI Julian
+    **     Date.
+    **
+    """
+    assert in1.shape[0] == in2.shape[0]
+    cdef unsigned n = in1.shape[0]
+    cdef unsigned int i
+    cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)
+    cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)
+
+    warns = {1: DUBIOUS}
+    errs = {-1: 'unacceptable date'}
+
+    for i in range(n):
+        ret = iauUtctai(in1[i], in2[i], &out1[i], &out2[i])
+        check_return(ret, 'iauUtctai', warns, errs)
+
+    return out1, out2
+
+
+ at cython.wraparound(False)
+ at cython.boundscheck(False)
+def tai_utc( 
+    np.ndarray[double, ndim=1] in1,
+    np.ndarray[double, ndim=1] in2):
+    """
+    int iauTaiutc(double tai1, double tai2, double *utc1, double *utc2)
+
+    **  Given:
+    **     tai1,tai2  double   TAI as a 2-part Julian Date (Note 1)
+    **
+    **  Returned:
+    **     utc1,utc2  double   UTC as a 2-part quasi Julian Date (Notes 1-3)
+    **
+    **  Returned (function value):
+    **                int      status: +1 = dubious year (Note 4)
+    **                                  0 = OK
+    **                                 -1 = unacceptable date
+    **
+    **  Notes:
+    **
+    **  1) tai1+tai2 is Julian Date, apportioned in any convenient way
+    **     between the two arguments, for example where tai1 is the Julian
+    **     Day Number and tai2 is the fraction of a day.  The returned utc1
+    **     and utc2 form an analogous pair, except that a special convention
+    **     is used, to deal with the problem of leap seconds - see the next
+    **     note.
+    **
+    **  2) JD cannot unambiguously represent UTC during a leap second unless
+    **     special measures are taken.  The convention in the present
+    **     function is that the JD day represents UTC days whether the
+    **     length is 86399, 86400 or 86401 SI seconds.
+    **
+    **  3) The function iauD2dtf can be used to transform the UTC quasi-JD
+    **     into calendar date and clock time, including UTC leap second
+    **     handling.
+    **
+    **  4) The warning status "dubious year" flags UTCs that predate the
+    **     introduction of the time scale and that are too far in the future
+    **     to be trusted.  See iauDat for further details.
+        """
+    assert in1.shape[0] == in2.shape[0]
+    cdef unsigned n = in1.shape[0]
+    cdef unsigned int i
+    cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)
+    cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)
+
+    warns = {1: DUBIOUS}
+    errs = {-1: 'unacceptable date'}
+
+    for i in range(n):
+        ret = iauTaiutc(in1[i], in2[i], &out1[i], &out2[i])
+        check_return(ret, 'iauTaiutc', warns, errs)
+
+    return out1, out2
+
+
+ at cython.wraparound(False)
+ at cython.boundscheck(False)
+def tai_ut1( 
+    np.ndarray[double, ndim=1] in1,
+    np.ndarray[double, ndim=1] in2,
+    np.ndarray[double, ndim=1] dt):
+    """
+    int iauTaiut1(double tai1, double tai2, double dta, double *ut11, double *ut12)
+
+    **  Given:
+    **     tai1,tai2  double    TAI as a 2-part Julian Date
+    **     dta        double    UT1-TAI in seconds
+    **
+    **  Returned:
+    **     ut11,ut12  double    UT1 as a 2-part Julian Date
+    **
+    **  Returned (function value):
+    **                int       status:  0 = OK
+    **
+    **  Notes:
+    **
+    **  1) tai1+tai2 is Julian Date, apportioned in any convenient way
+    **     between the two arguments, for example where tai1 is the Julian
+    **     Day Number and tai2 is the fraction of a day.  The returned
+    **     UT11,UT12 follow suit.
+    **
+    **  2) The argument dta, i.e. UT1-TAI, is an observed quantity, and is
+    **     available from IERS tabulations.
+    """
+    assert in1.shape[0] == in2.shape[0] == dt.shape[0]
+    cdef unsigned n = in1.shape[0]
+    cdef unsigned int i
+    cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)
+    cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)
+
+    for i in range(n):
+        ret = iauTaiut1(in1[i], in2[i], dt[i], &out1[i], &out2[i])
+        check_return(ret, 'iauTaiut1')
+
+    return out1, out2
+
+
+ at cython.wraparound(False)
+ at cython.boundscheck(False)
+def ut1_tai( 
+    np.ndarray[double, ndim=1] in1,
+    np.ndarray[double, ndim=1] in2,
+    np.ndarray[double, ndim=1] dt):
+    """
+    int iauUt1tai(double ut11, double ut12, double dta, double *tai1, double *tai2)
+
+    **  Given:
+    **     ut11,ut12  double    UT1 as a 2-part Julian Date
+    **     dta        double    UT1-TAI in seconds
+    **
+    **  Returned:
+    **     tai1,tai2  double    TAI as a 2-part Julian Date
+    **
+    **  Returned (function value):
+    **                int       status:  0 = OK
+    **
+    **  Notes:
+    **
+    **  1) ut11+ut12 is Julian Date, apportioned in any convenient way
+    **     between the two arguments, for example where ut11 is the Julian
+    **     Day Number and ut12 is the fraction of a day.  The returned
+    **     tai1,tai2 follow suit.
+    **
+    **  2) The argument dta, i.e. UT1-TAI, is an observed quantity, and is
+    **     available from IERS tabulations.
+    """
+    assert in1.shape[0] == in2.shape[0] == dt.shape[0]
+    cdef unsigned n = in1.shape[0]
+    cdef unsigned int i
+    cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)
+    cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)
+
+    for i in range(n):
+        ret = iauUt1tai(in1[i], in2[i], dt[i], &out1[i], &out2[i])
+        check_return(ret, 'iauUt1tai')
+
+    return out1, out2
+
+
+ at cython.wraparound(False)
+ at cython.boundscheck(False)
+def tt_ut1( 
+    np.ndarray[double, ndim=1] in1,
+    np.ndarray[double, ndim=1] in2,
+    np.ndarray[double, ndim=1] dt):
+    """
+    int iauTtut1(double tt1, double tt2, double dt, double *ut11, double *ut12)
+
+    **  Given:
+    **     tt1,tt2    double    TT as a 2-part Julian Date
+    **     dt         double    TT-UT1 in seconds
+    **
+    **  Returned:
+    **     ut11,ut12  double    UT1 as a 2-part Julian Date
+    **
+    **  Returned (function value):
+    **                int       status:  0 = OK
+    **
+    **  Notes:
+    **
+    **  1) tt1+tt2 is Julian Date, apportioned in any convenient way between
+    **     the two arguments, for example where tt1 is the Julian Day Number
+    **     and tt2 is the fraction of a day.  The returned ut11,ut12 follow
+    **     suit.
+    **
+    **  2) The argument dt is classical Delta T.
+    """
+    assert in1.shape[0] == in2.shape[0] == dt.shape[0]
+    cdef unsigned n = in1.shape[0]
+    cdef unsigned int i
+    cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)
+    cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)
+
+    for i in range(n):
+        ret = iauTtut1(in1[i], in2[i], dt[i], &out1[i], &out2[i])
+        check_return(ret, 'iauTtut1')
+
+    return out1, out2
+
+
+ at cython.wraparound(False)
+ at cython.boundscheck(False)
+def ut1_tt( 
+    np.ndarray[double, ndim=1] in1,
+    np.ndarray[double, ndim=1] in2,
+    np.ndarray[double, ndim=1] dt):
+    """
+    int iauUt1tt(double ut11, double ut12, double dt, double *tt1, double *tt2)
+
+    **  Given:
+    **     ut11,ut12  double    UT1 as a 2-part Julian Date
+    **     dt         double    TT-UT1 in seconds
+    **
+    **  Returned:
+    **     tt1,tt2    double    TT as a 2-part Julian Date
+    **
+    **  Returned (function value):
+    **                int       status:  0 = OK
+    **
+    **  Notes:
+    **
+    **  1) ut11+ut12 is Julian Date, apportioned in any convenient way
+    **     between the two arguments, for example where ut11 is the Julian
+    **     Day Number and ut12 is the fraction of a day.  The returned
+    **     tt1,tt2 follow suit.
+    **
+    **  2) The argument dt is classical Delta T.
+    """
+    assert in1.shape[0] == in2.shape[0] == dt.shape[0]
+    cdef unsigned n = in1.shape[0]
+    cdef unsigned int i
+    cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)
+    cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)
+
+    for i in range(n):
+        ret = iauUt1tt(in1[i], in2[i], dt[i], &out1[i], &out2[i])
+        check_return(ret, 'iauUt1tt')
+
+    return out1, out2
+
+
+ at cython.wraparound(False)
+ at cython.boundscheck(False)
+def tdb_tt( 
+    np.ndarray[double, ndim=1] in1,
+    np.ndarray[double, ndim=1] in2,
+    np.ndarray[double, ndim=1] dt):
+    """
+    int iauTdbtt(double tdb1, double tdb2, double dtr, double *tt1, double *tt2)
+
+    **  Given:
+    **     tdb1,tdb2  double    TDB as a 2-part Julian Date
+    **     dtr        double    TDB-TT in seconds
+    **
+    **  Returned:
+    **     tt1,tt2    double    TT as a 2-part Julian Date
+    **
+    **  Returned (function value):
+    **                int       status:  0 = OK
+    **
+    **  Notes:
+    **
+    **  1) tdb1+tdb2 is Julian Date, apportioned in any convenient way
+    **     between the two arguments, for example where tdb1 is the Julian
+    **     Day Number and tdb2 is the fraction of a day.  The returned
+    **     tt1,tt2 follow suit.
+    **
+    **  2) The argument dtr represents the quasi-periodic component of the
+    **     GR transformation between TT and TCB.  It is dependent upon the
+    **     adopted solar-system ephemeris, and can be obtained by numerical
+    **     integration, by interrogating a precomputed time ephemeris or by
+    **     evaluating a model such as that implemented in the SOFA function
+    **     iauDtdb.   The quantity is dominated by an annual term of 1.7 ms
+    **     amplitude.
+    **
+    **  3) TDB is essentially the same as Teph, the time argument for the
+    **     JPL solar system ephemerides.
+    """
+    assert in1.shape[0] == in2.shape[0] == dt.shape[0]
+    cdef unsigned n = in1.shape[0]
+    cdef unsigned int i
+    cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)
+    cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)
+
+    for i in range(n):
+        ret = iauTdbtt(in1[i], in2[i], dt[i], &out1[i], &out2[i])
+        check_return(ret, 'iauTdbtt')
+
+    return out1, out2
+
+
+ at cython.wraparound(False)
+ at cython.boundscheck(False)
+def tt_tdb( 
+    np.ndarray[double, ndim=1] in1,
+    np.ndarray[double, ndim=1] in2,
+    np.ndarray[double, ndim=1] dt):
+    """
+    int iauTttdb(double tt1, double tt2, double dtr, double *tdb1, double *tdb2)
+
+    **  Given:
+    **     tt1,tt2    double    TT as a 2-part Julian Date
+    **     dtr        double    TDB-TT in seconds
+    **
+    **  Returned:
+    **     tdb1,tdb2  double    TDB as a 2-part Julian Date
+    **
+    **  Returned (function value):
+    **                int       status:  0 = OK
+    **
+    **  Notes:
+    **
+    **  1) tt1+tt2 is Julian Date, apportioned in any convenient way between
+    **     the two arguments, for example where tt1 is the Julian Day Number
+    **     and tt2 is the fraction of a day.  The returned tdb1,tdb2 follow
+    **     suit.
+    **
+    **  2) The argument dtr represents the quasi-periodic component of the
+    **     GR transformation between TT and TCB.  It is dependent upon the
+    **     adopted solar-system ephemeris, and can be obtained by numerical
+    **     integration, by interrogating a precomputed time ephemeris or by
+    **     evaluating a model such as that implemented in the SOFA function
+    **     iauDtdb.   The quantity is dominated by an annual term of 1.7 ms
+    **     amplitude.
+    **
+    **  3) TDB is essentially the same as Teph, the time argument for the JPL
+    **     solar system ephemerides.
+    """
+    assert in1.shape[0] == in2.shape[0] == dt.shape[0]
+    cdef unsigned n = in1.shape[0]
+    cdef unsigned int i
+    cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)
+    cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)
+
+    for i in range(n):
+        ret = iauTttdb(in1[i], in2[i], dt[i], &out1[i], &out2[i])
+        check_return(ret, 'iauTttdb')
+
+    return out1, out2
+
+
+ at cython.wraparound(False)
+ at cython.boundscheck(False)
+def ut1_utc( 
+    np.ndarray[double, ndim=1] in1,
+    np.ndarray[double, ndim=1] in2,
+    np.ndarray[double, ndim=1] dt):
+    """
+    int iauUt1utc(double ut11, double ut12, double dut1, double *utc1, double *utc2)
+
+    **  Given:
+    **     ut11,ut12  double   UT1 as a 2-part Julian Date (Note 1)
+    **     dut1       double   Delta UT1: UT1-UTC in seconds (Note 2)
+    **
+    **  Returned:
+    **     utc1,utc2  double   UTC as a 2-part quasi Julian Date (Notes 3,4)
+    **
+    **  Returned (function value):
+    **                int      status: +1 = dubious year (Note 5)
+    **                                  0 = OK
+    **                                 -1 = unacceptable date
+    **
+    **  Notes:
+    **
+    **  1) ut11+ut12 is Julian Date, apportioned in any convenient way
+    **     between the two arguments, for example where ut11 is the Julian
+    **     Day Number and ut12 is the fraction of a day.  The returned utc1
+    **     and utc2 form an analogous pair, except that a special convention
+    **     is used, to deal with the problem of leap seconds - see Note 3.
+    **
+    **  2) Delta UT1 can be obtained from tabulations provided by the
+    **     International Earth Rotation and Reference Systems Service.  The
+    **     value changes abruptly by 1s at a leap second;  however, close to
+    **     a leap second the algorithm used here is tolerant of the "wrong"
+    **     choice of value being made.
+    **
+    **  3) JD cannot unambiguously represent UTC during a leap second unless
+    **     special measures are taken.  The convention in the present
+    **     function is that the returned quasi JD day UTC1+UTC2 represents
+    **     UTC days whether the length is 86399, 86400 or 86401 SI seconds.
+    **
+    **  4) The function iauD2dtf can be used to transform the UTC quasi-JD
+    **     into calendar date and clock time, including UTC leap second
+    **     handling.
+    **
+    **  5) The warning status "dubious year" flags UTCs that predate the
+    **     introduction of the time scale and that are too far in the future
+    **     to be trusted.  See iauDat for further details.
+    """
+    assert in1.shape[0] == in2.shape[0] == dt.shape[0]
+    cdef unsigned n = in1.shape[0]
+    cdef unsigned int i
+    cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)
+    cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)
+
+    warns = {1: DUBIOUS}
+    errs = {-1: 'unacceptable date'}
+
+    for i in range(n):
+        ret = iauUt1utc(in1[i], in2[i], dt[i], &out1[i], &out2[i])
+        check_return(ret, 'iauUt1utc', warns, errs)
+
+    return out1, out2
+
+
+ at cython.wraparound(False)
+ at cython.boundscheck(False)
+def utc_ut1( 
+    np.ndarray[double, ndim=1] in1,
+    np.ndarray[double, ndim=1] in2,
+    np.ndarray[double, ndim=1] dt):
+    """
+    int iauUtcut1(double utc1, double utc2, double dut1, double *ut11, double *ut12)
+
+    **  Given:
+    **     utc1,utc2  double   UTC as a 2-part quasi Julian Date (Notes 1-4)
+    **     dut1       double   Delta UT1 = UT1-UTC in seconds (Note 5)
+    **
+    **  Returned:
+    **     ut11,ut12  double   UT1 as a 2-part Julian Date (Note 6)
+    **
+    **  Returned (function value):
+    **                int      status: +1 = dubious year (Note 7)
+    **                                  0 = OK
+    **                                 -1 = unacceptable date
+    **
+    **  Notes:
+    **
+    **  1) utc1+utc2 is quasi Julian Date (see Note 2), apportioned in any
+    **     convenient way between the two arguments, for example where utc1
+    **     is the Julian Day Number and utc2 is the fraction of a day.
+    **
+    **  2) JD cannot unambiguously represent UTC during a leap second unless
+    **     special measures are taken.  The convention in the present
+    **     function is that the JD day represents UTC days whether the
+    **     length is 86399, 86400 or 86401 SI seconds.
+    **
+    **  3) The warning status "dubious year" flags UTCs that predate the
+    **     introduction of the time scale and that are too far in the future
+    **     to be trusted.  See iauDat  for further details.
+    **
+    **  4) The function iauDtf2d  converts from calendar date and time of
+    **     day into 2-part Julian Date, and in the case of UTC implements
+    **     the leap-second-ambiguity convention described above.
+    **
+    **  5) Delta UT1 can be obtained from tabulations provided by the
+    **     International Earth Rotation and Reference Systems Service.  It
+    **     It is the caller's responsibility to supply a DUT argument
+    **     containing the UT1-UTC value that matches the given UTC.
+    **
+    **  6) The returned ut11,ut12 are such that their sum is the UT1 Julian
+    **     Date.
+    **
+    **  7) The warning status "dubious year" flags UTCs that predate the
+    **     introduction of the time scale and that are too far in the future
+    **     to be trusted.  See iauDat for further details.
+    """
+    assert in1.shape[0] == in2.shape[0] == dt.shape[0]
+    cdef unsigned n = in1.shape[0]
+    cdef unsigned int i
+    cdef np.ndarray[double, ndim=1] out1 = np.empty(n, dtype=np.double)
+    cdef np.ndarray[double, ndim=1] out2 = np.empty(n, dtype=np.double)
+
+    warns = {1: DUBIOUS}
+    errs = {-1: 'unacceptable date'}
+
+    for i in range(n):
+        ret = iauUtcut1(in1[i], in2[i], dt[i], &out1[i], &out2[i])
+        check_return(ret, 'iauUtcut1', warns, errs)
+
+    return out1, out2
+
+
+ at cython.wraparound(False)
+ at cython.boundscheck(False)
+def d_tdb_tt(np.ndarray[double, ndim=1] in1,
+             np.ndarray[double, ndim=1] in2,
+             np.ndarray[double, ndim=1] ut,
+             elong, u, v):
+    """
+    compute DTR = TDB-TT
+    double iauDtdb(double date1, double date2, double ut,
+                   double elong, double u, double v)
+
+    **  Given:
+    **     date1,date2   double  date, TDB (Notes 1-3)
+    **     ut            double  universal time (UT1, fraction of one day)
+    **     elong         double  longitude (east positive, radians)
+    **     u             double  distance from Earth spin axis (km)
+    **     v             double  distance north of equatorial plane (km)
+    **
+    **  Returned (function value):
+    **                   double  TDB-TT (seconds)
+    **
+    **  Notes:
+    **
+    **  1) The date date1+date2 is a Julian Date, apportioned in any
+    **     convenient way between the two arguments.  For example,
+    **     JD(TT)=2450123.7 could be expressed in any of these ways,
+    **     among others:
+    **
+    **            date1          date2
+    **
+    **         2450123.7           0.0       (JD method)
+    **         2451545.0       -1421.3       (J2000 method)
+    **         2400000.5       50123.2       (MJD method)
+    **         2450123.5           0.2       (date & time method)
+    **
+    **     The JD method is the most natural and convenient to use in
+    **     cases where the loss of several decimal digits of resolution
+    **     is acceptable.  The J2000 method is best matched to the way
+    **     the argument is handled internally and will deliver the
+    **     optimum resolution.  The MJD method and the date & time methods
+    **     are both good compromises between resolution and convenience.
+    **
+    **     Although the date is, formally, barycentric dynamical time (TDB),
+    **     the terrestrial dynamical time (TT) can be used with no practical
+    **     effect on the accuracy of the prediction.
+    **
+    **  2) TT can be regarded as a coordinate time that is realized as an
+    **     offset of 32.184s from International Atomic Time, TAI.  TT is a
+    **     specific linear transformation of geocentric coordinate time TCG,
+    **     which is the time scale for the Geocentric Celestial Reference
+    **     System, GCRS.
+    **
+    **  3) TDB is a coordinate time, and is a specific linear transformation
+    **     of barycentric coordinate time TCB, which is the time scale for
+    **     the Barycentric Celestial Reference System, BCRS.
+    **
+    **  4) The difference TCG-TCB depends on the masses and positions of the
+    **     bodies of the solar system and the velocity of the Earth.  It is
+    **     dominated by a rate difference, the residual being of a periodic
+    **     character.  The latter, which is modeled by the present function,
+    **     comprises a main (annual) sinusoidal term of amplitude
+    **     approximately 0.00166 seconds, plus planetary terms up to about
+    **     20 microseconds, and lunar and diurnal terms up to 2 microseconds.
+    **     These effects come from the changing transverse Doppler effect
+    **     and gravitational red-shift as the observer (on the Earth's
+    **     surface) experiences variations in speed (with respect to the
+    **     BCRS) and gravitational potential.
+    **
+    **  5) TDB can be regarded as the same as TCB but with a rate adjustment
+    **     to keep it close to TT, which is convenient for many applications.
+    **     The history of successive attempts to define TDB is set out in
+    **     Resolution 3 adopted by the IAU General Assembly in 2006, which
+    **     defines a fixed TDB(TCB) transformation that is consistent with
+    **     contemporary solar-system ephemerides.  Future ephemerides will
+    **     imply slightly changed transformations between TCG and TCB, which
+    **     could introduce a linear drift between TDB and TT;  however, any
+    **     such drift is unlikely to exceed 1 nanosecond per century.
+    **
+    **  6) The geocentric TDB-TT model used in the present function is that of
+    **     Fairhead & Bretagnon (1990), in its full form.  It was originally
+    **     supplied by Fairhead (private communications with P.T.Wallace,
+    **     1990) as a Fortran subroutine.  The present C function contains an
+    **     adaptation of the Fairhead code.  The numerical results are
+    **     essentially unaffected by the changes, the differences with
+    **     respect to the Fairhead & Bretagnon original being at the 1e-20 s
+    **     level.
+    **
+    **     The topocentric part of the model is from Moyer (1981) and
+    **     Murray (1983), with fundamental arguments adapted from
+    **     Simon et al. 1994.  It is an approximation to the expression
+    **     ( v / c ) . ( r / c ), where v is the barycentric velocity of
+    **     the Earth, r is the geocentric position of the observer and
+    **     c is the speed of light.
+    **
+    **     By supplying zeroes for u and v, the topocentric part of the
+    **     model can be nullified, and the function will return the Fairhead
+    **     & Bretagnon result alone.
+    **
+    **  7) During the interval 1950-2050, the absolute accuracy is better
+    **     than +/- 3 nanoseconds relative to time ephemerides obtained by
+    **     direct numerical integrations based on the JPL DE405 solar system
+    **     ephemeris.
+    **
+    **  8) It must be stressed that the present function is merely a model,
+    **     and that numerical integration of solar-system ephemerides is the
+    **     definitive method for predicting the relationship between TCG and
+    **     TCB and hence between TT and TDB.
+    """
+    assert in1.shape[0] == in2.shape[0] == ut.shape[0]
+    cdef unsigned n = in1.shape[0]
+    cdef unsigned int i
+    cdef np.ndarray[double, ndim=1] out = np.empty(n, dtype=np.double)
+    cdef double c_elong = elong
+    cdef double c_u = u
+    cdef double c_v = v
+
+    for i in range(n):
+        out[i] = iauDtdb(in1[i], in2[i], ut[i], c_elong, c_u, c_v)
+    return out
+
+
+def iau_af2a(sign, ideg, iamin, asec):
+    """
+    int iauAf2a(char s, int ideg, int iamin, double asec, double *rad)
+
+    **  Given:
+    **     s         char    sign:  '-' = negative, otherwise positive
+    **     ideg      int     degrees
+    **     iamin     int     arcminutes
+    **     asec      double  arcseconds
+    **
+    **  Returned:
+    **     rad       double  angle in radians
+    **
+    **  Returned (function value):
+    **               int     status:  0 = OK
+    **                                1 = ideg outside range 0-359
+    **                                2 = iamin outside range 0-59
+    **                                3 = asec outside range 0-59.999...
+    **
+    **  Notes:
+    **
+    **  1)  The result is computed even if any of the range checks fail.
+    **
+    **  2)  Negative ideg, iamin and/or asec produce a warning status, but
+    **      the absolute value is used in the conversion.
+    **
+    **  3)  If there are multiple errors, the status value reflects only the
+    **      first, the smallest taking precedence.
+    """
+    cdef double rad
+    s = ord(sign)
+
+    warns = {1: 'ideg outside range 0-359',
+             2: 'iamin outside range 0-59',
+             3: 'asec outside range 0-59.999...'}
+
+    ret = iauAf2a(s, ideg, iamin, asec, &rad)
+    check_return(ret, 'iauAf2a', warns)
+
+    return rad
+
+def iau_gd2gc(n, elong, phi, height):
+    """
+    Wrap
+    int iauGd2gc(int n, double elong, double phi, double height, double xyz[3])
+
+    **  Given:
+    **     n       int        ellipsoid identifier (Note 1)
+    **     elong   double     longitude (radians, east +ve)
+    **     phi     double     latitude (geodetic, radians, Note 3)
+    **     height  double     height above ellipsoid (geodetic, Notes 2,3)
+    **
+    **  Returned:
+    **     xyz     double[3]  geocentric vector (Note 2)
+    **
+    **  Returned (function value):
+    **             int        status:  0 = OK
+    **                                -1 = illegal identifier (Note 3)
+    **                                -2 = illegal case (Note 3)
+    **
+    **  Notes:
+    **
+    **  1) The identifier n is a number that specifies the choice of
+    **     reference ellipsoid.  The following are supported:
+    **
+    **        n    ellipsoid
+    **
+    **        1     WGS84
+    **        2     GRS80
+    **        3     WGS72
+    **
+    **     The n value has no significance outside the SOFA software.  For
+    **     convenience, symbols WGS84 etc. are defined in sofam.h.
+    **
+    **  2) The height (height, given) and the geocentric vector (xyz,
+    **     returned) are in meters.
+    **
+    **  3) No validation is performed on the arguments elong, phi and
+    **     height.  An error status -1 means that the identifier n is
+    **     illegal.  An error status -2 protects against cases that would
+    **     lead to arithmetic exceptions.  In all error cases, xyz is set
+    **     to zeros.
+    **
+    **  4) The inverse transformation is performed in the function iauGc2gd.
+    """
+    cdef np.ndarray[double, ndim=1] xyz = np.empty(3, dtype=np.double)
+
+    errs = {-1: 'illegal identifier',
+             -2: 'illegal case'}
+
+    ret = iauGd2gc(n, elong, phi, height, &xyz[0])
+    check_return(ret, 'iauGd2gc', errors=errs)
+
+    return xyz
+
+
+ at cython.wraparound(False)
+ at cython.boundscheck(False)
+def jd_julian_epoch(np.ndarray[double, ndim=1] jd1,
+                    np.ndarray[double, ndim=1] jd2):
+    """ Wrap double iauEpj(double dj1, double dj2)
+    **  Julian Date to Julian Epoch.
+
+    **  Given:
+    **     dj1,dj2    double     Julian Date (see note)
+    **
+    **  Returned (function value):
+    **                double     Julian Epoch
+    **
+    **  Note:
+    **
+    **     The Julian Date is supplied in two pieces, in the usual SOFA
+    **     manner, which is designed to preserve time resolution.  The
+    **     Julian Date is available as a single number by adding dj1 and
+    **     dj2.  The maximum resolution is achieved if dj1 is 2451545D0
+    **     (J2000.0).
+    """
+    assert jd1.shape[0] == jd2.shape[0]
+    cdef unsigned n = jd1.shape[0]
+    cdef unsigned int i
+    cdef np.ndarray[double, ndim=1] epd = np.empty(n, dtype=np.double)
+
+    for i in range(n):
+        epd[i] = iauEpj(jd1[i], jd2[i])
+    return epd
+
+
+ at cython.wraparound(False)
+ at cython.boundscheck(False)
+def julian_epoch_jd(np.ndarray[double, ndim=1] epd):
+    """ Wrap void iauEpj2jd(double epj, double *djm0, double *djm)
+    **  Julian Epoch to Julian Date.
+    **  Given:
+    **     epj      double    Julian Epoch (e.g. 1996.8D0)
+    **
+    **  Returned:
+    **     djm0     double    MJD zero-point: always 2400000.5
+    **     djm      double    Modified Julian Date
+    """
+    cdef unsigned n = epd.shape[0]
+    cdef unsigned int i
+    cdef np.ndarray[double, ndim=1] jd1 = np.empty(n, dtype=np.double)
+    cdef np.ndarray[double, ndim=1] jd2 = np.empty(n, dtype=np.double)
+
+    for i in range(n):
+        iauEpj2jd(epd[i], &jd1[i], &jd2[i])
+    return jd1, jd2
+
+
+ at cython.wraparound(False)
+ at cython.boundscheck(False)
+def jd_besselian_epoch(np.ndarray[double, ndim=1] jd1,
+                       np.ndarray[double, ndim=1] jd2):
+    """ Wrap double iauEpb(double dj1, double dj2)
+    **  Julian Date to Besselian Epoch.
+
+    **  Given:
+    **     dj1,dj2    double     Julian Date (see note)
+    **
+    **  Returned (function value):
+    **                double     Besselian Epoch.
+    **
+    **  Note:
+    **
+    **     The Julian Date is supplied in two pieces, in the usual SOFA
+    **     manner, which is designed to preserve time resolution.  The
+    **     Julian Date is available as a single number by adding dj1 and
+    **     dj2.  The maximum resolution is achieved if dj1 is 2451545D0
+    **     (J2000.0).
+    """
+    assert jd1.shape[0] == jd2.shape[0]
+    cdef unsigned n = jd1.shape[0]
+    cdef unsigned int i
+    cdef np.ndarray[double, ndim=1] epd = np.empty(n, dtype=np.double)
+
+    for i in range(n):
+        epd[i] = iauEpb(jd1[i], jd2[i])
+    return epd
+
+
+ at cython.wraparound(False)
+ at cython.boundscheck(False)
+def besselian_epoch_jd(np.ndarray[double, ndim=1] epd):
+    """ Wrap void iauEpb2jd(double epj, double *djm0, double *djm)
+    **  Besselian Epoch to Julian Date.
+
+    **  Given:
+    **     epb      double    Besselian Epoch (e.g. 1957.3D0)
+    **
+    **  Returned:
+    **     djm0     double    MJD zero-point: always 2400000.5
+    **     djm      double    Modified Julian Date
+    **
+    **  Note:
+    **
+    **     The Julian Date is returned in two pieces, in the usual SOFA
+    **     manner, which is designed to preserve time resolution.  The
+    **     Julian Date is available as a single number by adding djm0 and
+    **     djm.
+    """
+    cdef unsigned n = epd.shape[0]
+    cdef unsigned int i
+    cdef np.ndarray[double, ndim=1] jd1 = np.empty(n, dtype=np.double)
+    cdef np.ndarray[double, ndim=1] jd2 = np.empty(n, dtype=np.double)
+
+    for i in range(n):
+        iauEpb2jd(epd[i], &jd1[i], &jd2[i])
+    return jd1, jd2
diff --git a/astropy/config/tests/__init__.py b/astropy/time/tests/__init__.py
similarity index 100%
copy from astropy/config/tests/__init__.py
copy to astropy/time/tests/__init__.py
diff --git a/astropy/time/tests/test_basic.py b/astropy/time/tests/test_basic.py
new file mode 100644
index 0000000..c6e4a7b
--- /dev/null
+++ b/astropy/time/tests/test_basic.py
@@ -0,0 +1,365 @@
+import numpy as np
+
+from ...tests.helper import pytest
+from .. import Time, ScaleValueError, sofa_time
+
+
+class TestBasic():
+    """Basic tests stemming from initial example and API reference"""
+
+    def test_simple(self):
+        times = ['1999-01-01 00:00:00.123456789', '2010-01-01 00:00:00']
+        t = Time(times, format='iso', scale='utc')
+        assert (repr(t) == "<Time object: scale='utc' format='iso' "
+                "vals=['1999-01-01 00:00:00.123' '2010-01-01 00:00:00.000']>")
+        assert np.allclose(t.jd1, np.array([2451179.5, 2455197.5]))
+        assert np.allclose(t.jd2, np.array([1.42889802e-06, 0.00000000e+00]))
+
+        # Set scale to TAI
+        t = t.tai
+        assert (repr(t) == "<Time object: scale='tai' format='iso' "
+                "vals=['1999-01-01 00:00:32.123' '2010-01-01 00:00:34.000']>")
+        assert np.allclose(t.jd1, np.array([2451179.5, 2455197.5]))
+        assert np.allclose(t.jd2, np.array([0.0003718, 0.00039352]))
+
+        # Get a new ``Time`` object which is referenced to the TT scale
+        # (internal JD1 and JD1 are now with respect to TT scale)"""
+
+        assert (repr(t.tt) == "<Time object: scale='tt' format='iso' "
+                "vals=['1999-01-01 00:01:04.307' '2010-01-01 00:01:06.184']>")
+
+        # Get the representation of the ``Time`` object in a particular format
+        # (in this case seconds since 1998.0).  This returns either a scalar or
+        # array, depending on whether the input was a scalar or array"""
+
+        print t.cxcsec
+        assert np.allclose(t.cxcsec, np.array([3.15360643e+07,
+                                               3.78691266e+08]))
+
+    def test_copy_time(self):
+        """Test copying the values of a Time object by passing it into the
+        Time initializer.
+        """
+        t = Time(2455197.5, format='jd', scale='utc')
+
+        t2 = Time(t, copy=False)
+        assert t.jd - t2.jd == 0
+        assert (t - t2).jd == 0
+        assert t._time.jd1 is t2._time.jd1
+        assert t._time.jd2 is t2._time.jd2
+
+        t2 = Time(t, copy=True)
+        assert t.jd - t2.jd == 0
+        assert (t - t2).jd == 0
+        assert t._time.jd1 is not t2._time.jd1
+        assert t._time.jd2 is not t2._time.jd2
+
+        # Include initializers
+        t2 = Time(t, format='iso', scale='tai', precision=1)
+        assert t2.val == '2010-01-01 00:00:34.0'
+        t2 = Time(t, format='iso', scale='tai', out_subfmt='date')
+        assert t2.val == '2010-01-01'
+
+    def test_properties(self):
+        """Use properties to convert scales and formats.  Note that the UT1 to
+        UTC transformation requires a supplementary value (``delta_ut1_utc``)
+        that can be obtained by interpolating from a table supplied by IERS.
+        This will be included in the package later."""
+
+        t = Time('2010-01-01 00:00:00', format='iso', scale='utc')
+        t.delta_ut1_utc = 0.3341  # Explicitly set one part of the xform
+        assert np.allclose(t.jd, 2455197.5)
+        assert t.iso == '2010-01-01 00:00:00.000'
+        assert t.tt.iso == '2010-01-01 00:01:06.184'
+        assert t.tai.iso == '2010-01-01 00:00:34.000'
+        assert np.allclose(t.utc.jd, 2455197.5)
+        assert np.allclose(t.ut1.jd, 2455197.500003867)
+        assert t.tcg.isot == '2010-01-01T00:01:06.910'
+        assert np.allclose(t.unix, 1262304000.0)
+        assert np.allclose(t.cxcsec, 378691266.184)
+
+    def test_precision(self):
+        """Set the output precision which is used for some formats.  This is
+        also a test of the code that provides a dict for global and instance
+        options."""
+
+        t = Time('2010-01-01 00:00:00', format='iso', scale='utc')
+        # Uses initial class-defined precision=3
+        assert t.iso == '2010-01-01 00:00:00.000'
+
+        # Set global precision = 5  XXX this uses private var, FIX THIS
+        Time._precision = 5
+        assert t.iso == '2010-01-01 00:00:00.00000'
+
+        # Set instance precision to 9
+        t.precision = 9
+        assert t.iso == '2010-01-01 00:00:00.000000000'
+        assert t.tai.utc.iso == '2010-01-01 00:00:00.000000000'
+
+        # Restore global to original default of 3, instance is still at 9
+        Time._precision = 3
+        assert t.iso == '2010-01-01 00:00:00.000000000'
+
+        # Make a new time instance and confirm precision = 3
+        t = Time('2010-01-01 00:00:00', format='iso', scale='utc')
+        assert t.iso == '2010-01-01 00:00:00.000'
+
+    def test_transforms(self):
+        """Transform from UTC to all supported time scales (TAI, TCB, TCG,
+        TDB, TT, UT1, UTC).  This requires auxilliary information (latitude and
+        longitude)."""
+
+        lat = 19.48125
+        lon = -155.933222
+        t = Time('2006-01-15 21:24:37.5', format='iso', scale='utc',
+                     precision=6, lat=lat, lon=lon)
+        t.delta_ut1_utc = 0.3341  # Explicitly set one part of the xform
+        assert t.utc.iso == '2006-01-15 21:24:37.500000'
+        assert t.ut1.iso == '2006-01-15 21:24:37.834100'
+        assert t.tai.iso == '2006-01-15 21:25:10.500000'
+        assert t.tt.iso == '2006-01-15 21:25:42.684000'
+        assert t.tcg.iso == '2006-01-15 21:25:43.322690'
+        assert t.tdb.iso == '2006-01-15 21:25:42.683799'
+        assert t.tcb.iso == '2006-01-15 21:25:56.893378'
+
+    def test_creating_all_formats(self):
+        """Create a time object using each defined format"""
+        Time(100.0, format='cxcsec')
+        Time(100.0, format='unix')
+        Time(1950.0, format='byear', scale='tai')
+        Time(2000.0, format='jyear', scale='tai')
+        Time('B1950.0', format='byear_str', scale='tai')
+        Time('J2000.0', format='jyear_str', scale='tai')
+        Time('2000-01-01 12:23:34.0', format='iso', scale='tai')
+        Time('2000-01-01T12:23:34.0', format='isot', scale='tai')
+        Time(2400000.5, 51544.0333981, format='jd', scale='tai')
+        Time(0.0, 51544.0333981, format='mjd', scale='tai')
+        Time('2000:001:12:23:34.0', format='yday', scale='tai')
+
+    def test_epoch_transform(self):
+        """Besselian and julian epoch transforms"""
+        jd = 2457073.05631
+        t = Time(jd, format='jd', scale='tai', precision=6)
+        assert np.allclose(t.byear, 2015.1365941021)
+        assert np.allclose(t.jyear, 2015.1349933196)
+        assert t.byear_str == 'B2015.136594'
+        assert t.jyear_str == 'J2015.134993'
+        t2 = Time(t.byear, format='byear', scale='tai')
+        assert np.allclose(t2.jd, jd)
+        t2 = Time(t.jyear, format='jyear', scale='tai')
+        assert np.allclose(t2.jd, jd)
+
+        t = Time('J2015.134993', scale='tai', precision=6)
+        assert np.allclose(t.jd, jd)
+        assert t.byear_str == 'B2015.136594'
+
+    def test_input_validation(self):
+        """Wrong input type raises error"""
+        times = [10, 20]
+        with pytest.raises(ValueError):
+            Time(times, format='iso', scale='utc')
+        with pytest.raises(ValueError):
+            Time('2000:001', format='jd', scale='utc')
+        with pytest.raises(ValueError):
+            Time([50000.0], ['bad'], format='mjd', scale='tai')
+        with pytest.raises(ValueError):
+            Time(50000.0, 'bad', format='mjd', scale='tai')
+
+    def test_utc_leap_sec(self):
+        """Time behaves properly near or in UTC leap second.  This
+        uses the 2012-06-30 leap second for testing."""
+
+        # Start with a day without a leap second and note rollover
+        t1 = Time('2012-06-01 23:59:60.0', scale='utc')
+        assert t1.iso == '2012-06-02 00:00:00.000'
+
+        # Leap second is different
+        t1 = Time('2012-06-30 23:59:59.900', scale='utc')
+        assert t1.iso == '2012-06-30 23:59:59.900'
+
+        t1 = Time('2012-06-30 23:59:60.000', scale='utc')
+        assert t1.iso == '2012-06-30 23:59:60.000'
+
+        t1 = Time('2012-06-30 23:59:60.999', scale='utc')
+        assert t1.iso == '2012-06-30 23:59:60.999'
+
+        t1 = Time('2012-06-30 23:59:61.0', scale='utc')
+        assert t1.iso == '2012-07-01 00:00:00.000'
+
+        # Delta time gives 2 seconds here as expected
+        t0 = Time('2012-06-30 23:59:59', scale='utc')
+        t1 = Time('2012-07-01 00:00:00', scale='utc')
+        assert np.allclose((t1 - t0).sec, 2.0)
+
+
+class TestVal2():
+    """Tests related to val2"""
+
+    def test_val2_ignored(self):
+        """Test that val2 is ignored for string input"""
+        t = Time('2001:001', 'ignored', scale='utc')
+        assert t.yday == '2001:001:00:00:00.000'
+
+    def test_val2(self):
+        """Various tests of the val2 input"""
+        t = Time([0.0, 50000.0], [50000.0, 0.0], format='mjd', scale='tai')
+        assert t.mjd[0] == t.mjd[1]
+        assert t.jd[0] == t.jd[1]
+
+    def test_val_matches_val2(self):
+        with pytest.raises(ValueError):
+            Time([0.0, 50000.0], [0.0], format='mjd', scale='tai')
+        with pytest.raises(ValueError):
+            Time([0.0], 0.0, format='mjd', scale='tai')
+
+class TestSubFormat():
+    """Test input and output subformat functionality"""
+
+    def test_input_subformat(self):
+        """Input subformat selection"""
+        # Heterogeneous input formats with in_subfmt='*' (default)
+        times = ['2000-01-01', '2000-01-01 01:01',
+                 '2000-01-01 01:01:01', '2000-01-01 01:01:01.123']
+        t = Time(times, format='iso', scale='tai')
+        assert np.all(t.iso == np.array(['2000-01-01 00:00:00.000',
+                                         '2000-01-01 01:01:00.000',
+                                         '2000-01-01 01:01:01.000',
+                                         '2000-01-01 01:01:01.123']))
+
+        # Heterogeneous input formats with in_subfmt='date_*'
+        times = ['2000-01-01 01:01',
+                 '2000-01-01 01:01:01', '2000-01-01 01:01:01.123']
+        t = Time(times, format='iso', scale='tai',
+                     in_subfmt='date_*')
+        assert np.all(t.iso == np.array(['2000-01-01 01:01:00.000',
+                                         '2000-01-01 01:01:01.000',
+                                         '2000-01-01 01:01:01.123']))
+
+    def test_input_subformat_fail(self):
+        """Failed format matching"""
+        with pytest.raises(ValueError):
+            Time('2000-01-01 01:01', format='iso', scale='tai',
+                     in_subfmt='date')
+
+    def test_bad_input_subformat(self):
+        """Non-existent input subformat"""
+        with pytest.raises(ValueError):
+            Time('2000-01-01 01:01', format='iso', scale='tai',
+                     in_subfmt='doesnt exist')
+
+    def test_output_subformat(self):
+        """Input subformat selection"""
+        # Heterogeneous input formats with in_subfmt='*' (default)
+        times = ['2000-01-01', '2000-01-01 01:01',
+                 '2000-01-01 01:01:01', '2000-01-01 01:01:01.123']
+        t = Time(times, format='iso', scale='tai',
+                     out_subfmt='date_hm')
+        assert np.all(t.iso == np.array(['2000-01-01 00:00',
+                                         '2000-01-01 01:01',
+                                         '2000-01-01 01:01',
+                                         '2000-01-01 01:01']))
+
+    def test_yday_format(self):
+        """Year:Day_of_year format"""
+        # Heterogeneous input formats with in_subfmt='*' (default)
+        times = ['2000-12-01', '2001-12-01 01:01:01.123']
+        t = Time(times, format='iso', scale='tai')
+        t.out_subfmt = 'date_hm'
+        assert np.all(t.yday == np.array(['2000:336:00:00',
+                                          '2001:335:01:01']))
+        t.out_subfmt = '*'
+        assert np.all(t.yday == np.array(['2000:336:00:00:00.000',
+                                          '2001:335:01:01:01.123']))
+
+    def test_scale_input(self):
+        """Test for issues related to scale input"""
+        # Check case where required scale is defined by the TimeFormat.
+        # The first two should succeed, the third should fail
+        Time(100.0, format='cxcsec')
+        Time(100.0, format='cxcsec', scale='tai')
+        with pytest.raises(ScaleValueError):
+            Time(100.0, format='cxcsec', scale='utc')
+
+        # Check that bad scale is caught when format is specified
+        with pytest.raises(ScaleValueError):
+            Time(1950.0, format='byear')
+        with pytest.raises(ScaleValueError):
+            Time(1950.0, format='byear', scale='bad scale')
+
+        # Check that bad scale is caught when format is auto-determined
+        with pytest.raises(ScaleValueError):
+            Time('2000:001:00:00:00')
+        with pytest.raises(ScaleValueError):
+            Time('2000:001:00:00:00', scale='bad scale')
+
+class TestSofaErrors():
+    """Test that sofa_time.pyx handles sofa status return values correctly"""
+
+    def test_bad_time(self):
+        iy = np.array([2000], dtype=np.intc)
+        im = np.array([2000], dtype=np.intc) # bad month
+        id = np.array([2000], dtype=np.intc) # bad day
+        djm0 = np.array([0], dtype=np.double)
+        djm = np.array([0], dtype=np.double)
+        with pytest.raises(ValueError):  # bad month, fatal error
+            sofa_time.cal2jd(iy, im, id, djm0, djm)
+
+        # Set month to a good value so now the bad day just gives a warning
+        im[0] = 2
+        sofa_time.cal2jd(iy, im, id, djm0, djm)
+        assert np.allclose(djm0, [2400000.5])
+        assert np.allclose(djm, [ 53574.])
+
+        # How do you test for warnings in pytest?  Test that dubious year for
+        # UTC works.
+
+
+class TestCopyReplicate():
+    """Test issues related to copying and replicating data"""
+
+    def test_mutable_input(self):
+        """By default if JDs are provided with copy=False then internals are
+        mutable."""
+        jds = np.array([2450000.5], dtype=np.double)
+        t = Time(jds, format='jd', scale='tai')
+        assert np.allclose(t.jd, jds)
+        jds[0] = 2459009.5
+        assert np.allclose(t.jd, jds)
+
+        t = Time(jds, format='jd', scale='tai', copy=True)
+        assert np.allclose(t.jd, jds)
+        jds[0] = 2458654
+        assert not np.allclose(t.jd, jds)
+
+        # MJD does not suffer from this mutability
+        mjds = np.array([50000.0], dtype=np.double)
+        t = Time(mjds, format='mjd', scale='tai')
+        assert np.allclose(t.jd, [2450000.5])
+        mjds[0] = 0.0
+        assert np.allclose(t.jd, [2450000.5])
+
+    def test_replicate(self):
+        """Test replicate method"""
+        t = Time('2000:001', format='yday', scale='tai')
+        t_yday = t.yday
+        t2 = t.replicate()
+        assert t.yday == t2.yday
+        assert t.format == t2.format
+        assert t.scale == t2.scale
+        # This is not allowed publicly, but here we hack the internal time values
+        # to show that t and t2 are sharing references.
+        t2._time.jd1 += 100.0
+        assert t.yday == t2.yday
+        assert t.yday != t_yday  # prove that it changed
+
+    def test_copy(self):
+        """Test copy method"""
+        t = Time('2000:001', format='yday', scale='tai')
+        t_yday = t.yday
+        t2 = t.copy()
+        assert t.yday == t2.yday
+        # This is not allowed publicly, but here we hack the internal time values
+        # to show that t and t2 are not sharing references.
+        t2._time.jd1 += 100.0
+        assert t.yday != t2.yday
+        assert t.yday == t_yday  # prove that it did not change
diff --git a/astropy/time/tests/test_delta.py b/astropy/time/tests/test_delta.py
new file mode 100644
index 0000000..133b45a
--- /dev/null
+++ b/astropy/time/tests/test_delta.py
@@ -0,0 +1,74 @@
+import numpy as np
+
+from ...tests.helper import pytest
+from .. import Time, TimeDelta, OperandTypeError
+
+
+class TestTimeDelta():
+    """Test TimeDelta class"""
+
+    def setup(self):
+        self.t = Time('2010-01-01', scale='utc')
+        self.t2 = Time('2010-01-02 00:00:01', scale='utc')
+        self.dt = TimeDelta(100.0, format='sec')
+
+    def test_sub(self):
+        # time - time
+        dt = self.t2 - self.t
+        assert (repr(dt).startswith("<TimeDelta object: scale='tai' "
+                                    "format='jd' vals=1.00001157407"))
+        assert np.allclose(dt.jd, 1.00001157407)
+        assert np.allclose(dt.sec, 86401.0)
+
+        # time - delta_time
+        t = self.t2 - dt
+        assert t.iso == self.t.iso
+
+        # delta_time - delta_time
+        dt2 = dt - self.dt
+        assert np.allclose(dt2.sec, 86301.0)
+
+        # delta_time - time
+        with pytest.raises(OperandTypeError):
+            dt - self.t
+
+    def test_add(self):
+        # time + time
+        with pytest.raises(OperandTypeError):
+            self.t2 + self.t
+
+        # time + delta_time
+        dt = self.t2 - self.t
+        t2 = self.t + dt
+        assert t2.iso == self.t2.iso
+
+        # delta_time + delta_time
+        dt2 = dt + self.dt
+        assert np.allclose(dt2.sec, 86501.0)
+
+        # delta_time + time
+        dt = self.t2 - self.t
+        t2 = dt + self.t
+        assert t2.iso == self.t2.iso
+
+    def test_copy_timedelta(self):
+        """Test copying the values of a TimeDelta object by passing it into the
+        Time initializer.
+        """
+        t = Time(2455197.5, format='jd', scale='utc')
+        t2 = Time(2455198.5, format='jd', scale='utc')
+        dt = t2 - t
+
+        dt2 = TimeDelta(dt, copy=False)
+        assert dt.jd == dt2.jd
+        assert dt._time.jd1 is dt2._time.jd1
+        assert dt._time.jd2 is dt2._time.jd2
+
+        dt2 = TimeDelta(dt, copy=True)
+        assert dt.jd == dt2.jd
+        assert dt._time.jd1 is not dt2._time.jd1
+        assert dt._time.jd2 is not dt2._time.jd2
+
+        # Include initializers
+        dt2 = TimeDelta(dt, format='sec')
+        assert np.allclose(dt2.val, 86400.0)
diff --git a/astropy/time/tests/test_guess.py b/astropy/time/tests/test_guess.py
new file mode 100644
index 0000000..d4a493d
--- /dev/null
+++ b/astropy/time/tests/test_guess.py
@@ -0,0 +1,28 @@
+from ...tests.helper import pytest
+from .. import Time
+
+
+class TestGuess():
+    """Test guessing the input value format"""
+
+    def test_guess1(self):
+        times = ['1999-01-01 00:00:00.123456789', '2010-01-01 00:00:00']
+        t = Time(times, scale='utc')
+        assert (repr(t) == "<Time object: scale='utc' format='iso' "
+                "vals=['1999-01-01 00:00:00.123' '2010-01-01 00:00:00.000']>")
+
+    def test_guess2(self):
+        times = ['1999-01-01 00:00:00.123456789', '2010-01 00:00:00']
+        with pytest.raises(ValueError):
+            Time(times, scale='utc')
+
+    def test_guess3(self):
+        times = ['1999:001:00:00:00.123456789', '2010:001']
+        t = Time(times, scale='utc')
+        assert (repr(t) == "<Time object: scale='utc' format='yday' "
+                "vals=['1999:001:00:00:00.123' '2010:001:00:00:00.000']>")
+
+    def test_guess4(self):
+        times = [10, 20]
+        with pytest.raises(ValueError):
+            Time(times, scale='utc')
diff --git a/astropy/tools/__init__.py b/astropy/tools/__init__.py
deleted file mode 100644
index 8d221a1..0000000
--- a/astropy/tools/__init__.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# Licensed under a 3-clause BSD style license - see LICENSE.rst
-"""
-This subpackage contains astronomy-related tools provided by Astropy. Classes
-and functions here are of general use across multiple areas of Astropy, or are
-otherwise not specific to a particular Astropy subpackage.
-
-This package is intended to contain functionality that is of use to users, in
-contrast to the `astropy.utils` module, which is focused more on developer
-tools or python-specific utilities.
-"""
-
-from .misc import *
diff --git a/astropy/tools/misc.py b/astropy/tools/misc.py
deleted file mode 100644
index 8efd2bc..0000000
--- a/astropy/tools/misc.py
+++ /dev/null
@@ -1,107 +0,0 @@
-# Licensed under a 3-clause BSD style license - see LICENSE.rst
-"""
-This module contains simple algorithmic functionality common in astronomy or
-used in multiple places throughout Astropy, but are not complex enough to
-necessarily warrant their own module.
-
-This package should generally not be used directly.  Everything in `__all__` is
-imported into `astropy.tools`, and hence that package should be used for
-access.
-"""
-
-import numpy as np  # needed for some defaults
-
-__all__ = ['sigma_clip']
-
-
-def sigma_clip(data, sig=3, iters=1, cenfunc=np.median, varfunc=np.var,
-               maout=False):
-    """ Perform sigma-clipping on the provided data.
-
-    This performs the sigma clipping algorithm - i.e. the data will be iterated
-    over, each time rejecting points that are more than a specified number of
-    standard deviations discrepant.
-
-    Parameters
-    ----------
-    data : array-like
-        The data to be sigma-clipped (any shape).
-    sig : float
-        The number of standard deviations (*not* variances) to use as the
-        clipping limit.
-    iters : int or None
-        The number of iterations to perform clipping for, or None to clip until
-        convergence is achieved (i.e. continue until the last iteration clips
-        nothing).
-    cenfunc : callable
-        The technique to compute the center for the clipping. Must be a
-        callable that takes in a 1D data array and outputs the central value.
-        Defaults to the median.
-    varfunc : callable
-        The technique to compute the variance about the center. Must be a
-        callable that takes in a 1D data array and outputs the width estimator
-        that will be interpreted as a variance. Defaults to the variance.
-    maout : bool or 'copy'
-        If True, a masked array will be returned. If the special string
-        'inplace', the masked array will contain the same array as `data`,
-        otherwise the array data will be copied.
-
-    Returns
-    -------
-    filtereddata : `numpy.ndarray` or `numpy.masked.MaskedArray`
-        If `maout` is True, this is a masked array with a shape matching the
-        input that is masked where the algorithm has rejected those values.
-        Otherwise, a 1D array of values including only those that are not
-        clipped.
-    mask : boolean array
-        Only present if `maout` is False. A boolean array with a shape matching
-        the input `data` that is False for rejected values and True for all
-        others.
-
-    Examples
-    --------
-
-    This will generate random variates from a Gaussian distribution and return
-    only the points that are within 2 *sample* standard deviation from the
-    median::
-
-        >>> from astropy.tools.alg import sigma_clip
-        >>> from numpy.random import randn
-        >>> randvar = randn(10000)
-        >>> data,mask = sigma_clip(randvar,2,1)
-
-    This will clipping on a similar distribution, but for 3 sigma relative to
-    the sample *mean*, will clip until converged, and produces a
-    `numpy.masked.MaskedArray`::
-
-        >>> from astropy.tools.alg import sigma_clip
-        >>> from numpy.random import randn
-        >>> from numpy import mean
-        >>> randvar = randn(10000)
-        >>> maskedarr = sigma_clip(randvar,3,None,mean,maout=True)
-
-    """
-    data = np.array(data, copy=False)
-    oldshape = data.shape
-    data = data.ravel()
-
-    mask = np.ones(data.size, bool)
-    if iters is None:
-        i = -1
-        lastrej = sum(mask) + 1
-        while(sum(mask) != lastrej):
-            i += 1
-            lastrej = sum(mask)
-            do = data - cenfunc(data[mask])
-            mask = do * do <= varfunc(data[mask]) * sig ** 2
-        iters = i + 1
-        #TODO: ?print iters to the log if iters was None?
-    else:
-        for i in range(iters):
-            do = data - cenfunc(data[mask])
-            mask = do * do <= varfunc(data[mask]) * sig ** 2
-
-    if maout:
-        return np.ma.MaskedArray(data, ~mask, copy=maout != 'inplace')
-    else:
-        return data[mask], mask.reshape(oldshape)
diff --git a/astropy/tools/tests/test_misc.py b/astropy/tools/tests/test_misc.py
deleted file mode 100644
index d0e97b4..0000000
--- a/astropy/tools/tests/test_misc.py
+++ /dev/null
@@ -1,40 +0,0 @@
-from __future__ import division
-
-import numpy as np
-from .. import misc
-
-
-def test_sigma_clip():
-    from numpy.random import randn,seed,get_state,set_state
-    
-    #need to seed the numpy RNG to make sure we don't get some amazingly flukey
-    #random number that breaks one of the tests
-    
-    randstate = get_state()
-    try:
-        seed(12345)  # Amazing, I've got the same combination on my luggage!
-        
-        randvar = randn(10000)
-
-        data, mask = misc.sigma_clip(randvar, 1, 2)
-        maskedarr = misc.sigma_clip(randvar, 1, 2, maout=True)
-
-        assert sum(mask) > 0
-        assert data.size < randvar.size
-        assert np.all(mask == ~maskedarr.mask)
-
-        #this is actually a silly thing to do, because it uses the standard
-        #deviation as the variance, but it tests to make sure these arguments
-        #are actually doing something
-        data2, mask2 = misc.sigma_clip(randvar, 1, 2, varfunc=np.std)
-        assert not np.all(data == data2)
-        assert not np.all(mask == mask2)
-
-        data3, mask3 = misc.sigma_clip(randvar, 1, 2, cenfunc=np.mean)
-        assert not np.all(data == data3)
-        assert not np.all(mask == mask3)
-
-        #now just make sure the iters=None method works at all.
-        maskedarr = misc.sigma_clip(randvar, 3, None, maout=True)
-    finally:
-        set_state(randstate)
\ No newline at end of file
diff --git a/astropy/units/__init__.py b/astropy/units/__init__.py
new file mode 100644
index 0000000..2e4b883
--- /dev/null
+++ b/astropy/units/__init__.py
@@ -0,0 +1,26 @@
+# Licensed under a 3-clause BSD style license - see LICENSE.rst
+"""
+This subpackage contains classes and functions for defining and converting
+between different physical units.
+
+This code is adapted from the `pynbody
+<http://code.google.com/p/pynbody/>`_ units module written by Andrew
+Pontzen, who has granted the Astropy project permission to use the
+code under a BSD license.
+"""
+
+from .core import *
+from .si import *
+from .astrophys import *
+from .cgs import *
+from .imperial import *
+from .equivalencies import *
+from .physical import *
+from .quantity import *
+
+# Create a special singleton for the dimensionless unit
+dimensionless = Unit(1)
+
+# After importing the unit definitions above, set the unit namespace
+# to this top-level module so that new units are added here.
+UnitBase._set_namespace(globals())
diff --git a/astropy/units/astrophys.py b/astropy/units/astrophys.py
new file mode 100644
index 0000000..86ba5cb
--- /dev/null
+++ b/astropy/units/astrophys.py
@@ -0,0 +1,119 @@
+# -*- coding: utf-8 -*-
+# Licensed under a 3-clause BSD style license - see LICENSE.rst
+"""
+This package defines the astrophysics-specific units.  They are also
+available in the `astropy.units` namespace.
+
+The `mag` unit is provided for compatibility with the FITS unit string
+standard.  However, it is not very useful as-is since it is "orphaned"
+and can not be converted to any other unit.  A future astropy
+magnitudes library is planned to address this shortcoming.
+
+"""
+from __future__ import absolute_import, division, print_function, unicode_literals
+
+from . import si
+from .._constants import si as _si
+from .core import UnitBase, def_unit
+
+import numpy as _numpy
+
+UnitBase._set_namespace(globals())
+
+###########################################################################
+# LENGTH
+
+def_unit(['AU', 'au'], _si.au * si.m, register=True, prefixes=True,
+         doc="astronomical unit: approximately the mean Earth--Sun "
+         "distance.")
+
+def_unit(['pc', 'parsec'], _si.pc * si.m, register=True, prefixes=True,
+         doc="parsec: approximately 3.26 light-years.")
+
+def_unit(['solRad', 'R_sun'], _si.R_sun * si.m, register=True,
+         doc="Solar radius")
+def_unit(['lyr', 'lightyear'], 9.460730e15 * si.m, register=True,
+         doc="Light year")
+
+
+###########################################################################
+# AREAS
+
+def_unit(['barn'], 10 ** -28 * si.m ** 2, register=True, prefixes=True,
+         doc="barn: unit of area used in HEP")
+
+
+###########################################################################
+# MASS
+
+def_unit(['solMass', 'M_sun'], _si.M_sun * si.kg, register=True, prefixes=True,
+         doc="Solar mass",
+         format={'latex': r'M_{\odot}', 'unicode': 'M⊙'})
+def_unit(['M_p'], _si.m_p * si.kg, register=True,
+         doc="Proton mass",
+         format={'latex': r'M_{p}', 'unicode': 'Mâ‚š'})
+def_unit(['M_e'], _si.m_e * si.kg, register=True,
+         doc="Electron mass",
+         format={'latex': r'M_{e}', 'unicode': 'Mâ‚‘'})
+# Unified atomic mass unit
+def_unit(['u', 'Da', 'Dalton'], 1.6605387e-27 * si.kg, register=True,
+         doc="Unified atomic mass unit")
+
+
+##########################################################################
+# ENERGY
+
+def_unit(['Ry', 'rydberg'], 13.605692 * si.eV, register=True,
+         doc="Rydberg: Energy of a photon whose wavenumber is the Rydberg "
+         "constant",
+         format={'latex': r'R_{\infty}', 'unicode': 'R∞'})
+
+
+###########################################################################
+# ILLUMINATION
+
+def_unit(['solLum', 'L_sun'], _si.L_sun * si.W, register=True, prefixes=True,
+         doc="Solar luminance")
+
+
+###########################################################################
+# SPECTRAL DENSITY
+
+def_unit(['Jy', 'Jansky', 'jansky'], 1e-26 * si.W / si.m ** 2 / si.Hz,
+         register=True, prefixes=True,
+         doc="Jansky: spectral flux density")
+def_unit(['R', 'Rayleigh', 'rayleigh'],
+         (1e10 / (4 * _numpy.pi)) *
+         si.ph * si.m ** -2 * si.s ** -1 * si.sr ** -1,
+         register=True, prefixes=True,
+         doc="Rayleigh: photon flux")
+
+def_unit(['mag'], register=True, prefixes=True,
+         doc="Stellar magnitude.")
+
+
+###########################################################################
+# MISCELLANEOUS
+
+# Some of these are very FITS-specific and perhaps considered a mistake.
+# Maybe they should be moved into the FITS format class?
+# TODO: This is defined by the FITS standard as "relative to the sun".
+# Is that mass, volume, what?
+def_unit(['Sun'], register=True)
+
+
+###########################################################################
+# CLEANUP
+
+del UnitBase
+del def_unit
+del si
+
+
+###########################################################################
+# DOCSTRING
+
+# This generates a docstring for this module that describes all of the
+# standard units defined here.
+from .utils import generate_unit_summary as _generate_unit_summary
+__doc__ += _generate_unit_summary(globals())
diff --git a/astropy/units/cgs.py b/astropy/units/cgs.py
new file mode 100644
index 0000000..661d88e
--- /dev/null
+++ b/astropy/units/cgs.py
@@ -0,0 +1,115 @@
+# -*- coding: utf-8 -*-
+# Licensed under a 3-clause BSD style license - see LICENSE.rst
+"""
+This package defines the CGS units.  They are also available in the
+top-level `astropy.units` namespace.
+
+"""
+from __future__ import absolute_import, division, print_function, unicode_literals
+
+from fractions import Fraction
+
+from . import si
+from .core import UnitBase, def_unit
+
+
+UnitBase._set_namespace(globals())
+
+##########################################################################
+# ACCELERATION
+
+def_unit(['Gal', 'gal'], si.cm / si.s ** 2, register=True, prefixes=True,
+         doc="Gal: CGS unit of acceleration")
+
+
+##########################################################################
+# ENERGY
+
+# Use CGS definition of erg
+def_unit(['erg'], si.g * si.cm ** 2 / si.s ** 2, register=True, prefixes=True,
+         doc="erg: CGS unit of energy")
+
+
+##########################################################################
+# FORCE
+
+def_unit(['dyn', 'dyne'], si.g * si.cm / si.s ** 2, register=True,
+         prefixes=True,
+         doc="dyne: CGS unit of force")
+
+
+##########################################################################
+# PRESSURE
+
+def_unit(['Ba', 'Barye', 'barye'], si.g / (si.cm * si.s ** 2), register=True,
+         prefixes=True,
+         doc="Barye: CGS unit of pressure")
+
+
+##########################################################################
+# DYNAMIC VISCOSITY
+
+def_unit(['P', 'poise'], si.g / (si.cm * si.s), register=True,
+         prefixes=True,
+         doc="poise: CGS unit of dynamic viscosity")
+
+
+##########################################################################
+# KINEMATIC VISCOSITY
+
+def_unit(['St', 'stokes'], si.cm ** 2 / si.s, register=True,
+         prefixes=True,
+         doc="stokes: CGS unit of kinematic viscosity")
+
+
+##########################################################################
+# WAVENUMBER
+
+def_unit(['k', 'Kayser', 'kayser'], si.cm ** -1, register=True,
+         prefixes=True,
+         doc="kayser: CGS unit of wavenumber")
+
+
+###########################################################################
+# ELECTRICAL
+
+def_unit(['D', 'Debye', 'debye'], Fraction(1, 3) * 1e-29 * si.C * si.m,
+         register=True,
+         doc="Debye: CGS unit of electric dipole moment")
+
+def_unit(['Fr', 'Franklin', 'statcoulomb', 'statC', 'esu'],
+         si.g ** Fraction(1, 2) * si.cm ** Fraction(3, 2) * si.s ** -1,
+         register=True)
+
+###########################################################################
+# MAGNETIC
+
+def_unit(['G', 'Gauss', 'gauss'], 1e-4 * si.T, register=True, prefixes=True,
+         doc="Gauss: CGS unit for magnetic field")
+
+
+# Mapping from SI units to CGS units
+_cgs_bases = {si.meter : si.cm,
+              si.joule : erg,
+              si.newton : dyne,
+              si.pascal : barye,
+              si.tesla : gauss,
+              si.coulomb : statcoulomb,
+              si.kilogram : si.g}
+
+###########################################################################
+# CLEANUP
+
+del UnitBase
+del def_unit
+del si
+del Fraction
+
+
+###########################################################################
+# DOCSTRING
+
+# This generates a docstring for this module that describes all of the
+# standard units defined here.
+from .utils import generate_unit_summary as _generate_unit_summary
+__doc__ += _generate_unit_summary(globals())
diff --git a/astropy/units/core.py b/astropy/units/core.py
new file mode 100644
index 0000000..82f723a
--- /dev/null
+++ b/astropy/units/core.py
@@ -0,0 +1,1161 @@
+# -*- coding: utf-8 -*-
+# Licensed under a 3-clause BSD style license - see LICENSE.rst
+"""
+Core units classes and functions
+"""
+from __future__ import absolute_import, division, print_function, unicode_literals
+
+from fractions import Fraction
+import re
+import sys
+import textwrap
+import warnings
+import numbers
+
+import numpy as np
+from numpy import ma
+
+from . import format as unit_format
+
+# TODO: Support functional units, e.g. log(x), ln(x)
+
+__all__ = [
+    'UnitsException', 'UnitsWarning', 'UnitBase', 'NamedUnit',
+    'IrreducibleUnit', 'Unit', 'def_unit', 'CompositeUnit',
+    'PrefixUnit', 'UnrecognizedUnit']
+
+
+class UnitsException(Exception):
+    """
+    The base class for unit-specific exceptions.
+    """
+    pass
+
+
+class UnitsWarning(Warning):
+    """
+    The base class for unit-specific exceptions.
+    """
+    pass
+
+
+class UnitBase(object):
+    """
+    Abstract base class for units.
+
+    Most of the arithmetic operations on units are defined in this
+    base class.
+
+    Should not be instantiated by users directly.
+    """
+    _registry = []
+    _namespace = {}
+
+    # Make sure that __rmul__ of units gets called over the __mul__ of Numpy
+    # arrays to avoid element-wise multiplication.
+    __array_priority__ = 1000
+
+    def __deepcopy__(self, memo):
+        # This may look odd, but the units conversion will be very
+        # broken after deep-copying if we don't guarantee that a given
+        # physical unit corresponds to only one instance
+        return self
+
+    def _repr_latex_(self):
+        """
+        Generate latex representation of unit name.  This is used by
+        the IPython notebook to print a unit with a nice layout.
+
+        Returns
+        -------
+        Latex string
+        """
+        return unit_format.Latex().to_string(self)
+
+    def __str__(self):
+        """Return string representation for unit"""
+        return unit_format.Generic().to_string(self)
+
+    def __repr__(self):
+        return 'Unit("' + str(self) + '")'
+
+    def to_string(self, format='generic'):
+        """
+        Output the unit in the given format as a string.
+
+        Parameters
+        ----------
+        format : `astropy.format.Base` instance or str
+            The name of a format or a formatter object.  If not
+            provided, defaults to the generic format.
+        """
+        f = unit_format.get_format(format)
+        return f.to_string(self)
+
+    @staticmethod
+    def _get_namespace():
+        """
+        Get the namespace that units will be registered to.
+        """
+        return UnitBase._namespace
+
+    @staticmethod
+    def _set_namespace(d):
+        """
+        Set the namespace that units will be registered to.
+        """
+        UnitBase._namespace = d
+
+    def __pow__(self, p):
+        if isinstance(p, tuple) and len(p) == 2:
+            p = Fraction(p[0], p[1])
+        else:
+            # allow two possible floating point fractions, all others illegal
+            if not int(2 * p) == 2 * p:
+                raise ValueError(
+                    "floating values for unit powers must be integers or "
+                    "integers + 0.5")
+        return CompositeUnit(1, [self], [p]).simplify()
+
+    def __div__(self, m):
+        # Strictly speaking, we should be using old-style division here.
+        # However, I think it's less surprising for this to behave the
+        # same way whether __future__ division is being used or not
+        if isinstance(m, UnitBase):
+            return CompositeUnit(1, [self, m], [1, -1]).simplify()
+        else:
+            from .quantity import Quantity
+            return Quantity(1. / m, self)
+
+    def __rdiv__(self, m):
+        from .quantity import Quantity
+        return Quantity(m, CompositeUnit(1.0, [self], [-1]).simplify())
+
+    def __truediv__(self, m):
+        return self.__div__(m)
+
+    def __rtruediv__(self, m):
+        return self.__rdiv__(m)
+
+    def __mul__(self, m):
+        if isinstance(m, UnitBase):
+            return CompositeUnit(1, [self, m], [1, 1]).simplify()
+        else:
+            from .quantity import Quantity
+            return Quantity(m, self)
+
+    def __rmul__(self, m):
+        from .quantity import Quantity
+        return Quantity(m, self)
+
+    if sys.version_info[0] >= 3:
+        def __hash__(self):
+            # Since this class defines __eq__, it will become unhashable
+            # on Python 3.x, so we need to define our own hash.
+            return id(self)
+
+    def __eq__(self, other):
+        other = Unit(other, parse_strict='silent')
+        try:
+            return np.allclose(self.to(other, 1), 1.0)
+        except UnitsException:
+            return False
+
+    def __ne__(self, other):
+        return not (self == other)
+
+    def __lt__(self, other):
+        other = Unit(other)
+        return self.to(other, 1) < 1.
+
+    def __gt__(self, other):
+        other = Unit(other)
+        return self.to(other, 1) > 1.
+
+    def __le__(self, other):
+        other = Unit(other)
+        return self.to(other, 1) <= 1.
+
+    def __ge__(self, other):
+        other = Unit(other)
+        return self.to(other, 1) >= 1.
+
+    def __neg__(self):
+        return self * -1.
+
+    def simplify(self):
+        """
+        Compresses a possibly composite unit down to a single
+        instance.
+        """
+        return self
+
+    def is_dimensionless(self):
+        """
+        Returns `True` if this unit translates into a scalar quantity
+        without a unit.
+
+        Examples
+        --------
+        >>> ((2 * u.m) / (3 * u.m)).is_dimensionless()
+        True
+        >>> (2 * u.m).is_dimensionless()
+        False
+        """
+        return False
+
+    def is_equivalent(self, other, equivs=[]):
+        """
+        Returns `True` if this unit is equivalent to `other`.
+
+        Parameters
+        ----------
+        other : unit object or string
+           The unit to convert to.
+
+        equivs : list of equivalence pairs, optional
+           A list of equivalence pairs to try if the units are not
+           directly convertible.  See :ref:`unit_equivalencies`.
+
+        Returns
+        -------
+        bool
+        """
+        other = Unit(other, parse_strict='silent')
+
+        if isinstance(other, UnrecognizedUnit):
+            return False
+
+        try:
+            (self / other).dimensionless_constant()
+        except UnitsException:
+            unit = self.decompose()
+            other = other.decompose()
+            for equiv in equivs:
+                a = equiv[0]
+                b = equiv[1]
+                if (unit.is_equivalent(a) and
+                    other.is_equivalent(b)):
+                    return True
+                elif (unit.is_equivalent(b) and
+                      other.is_equivalent(a)):
+                    return True
+            return False
+        else:
+            return True
+
+    def _apply_equivalences(self, unit, other, equivs):
+        """
+        Internal function (used from `get_converter`) to apply
+        equivalence pairs.
+        """
+        def make_converter(scale1, func, scale2):
+            def convert(v):
+                return func(_condition_arg(v) * scale1) * scale2
+            return convert
+
+        orig_unit = unit
+        orig_other = other
+
+        unit = self.decompose()
+        other = other.decompose()
+
+        for equiv in equivs:
+            if len(equiv) == 2:
+                funit, tunit = equiv
+                a, b = lambda x: x
+            if len(equiv) == 3:
+                funit, tunit, a = equiv
+                b = a
+            elif len(equiv) == 4:
+                funit, tunit, a, b = equiv
+            else:
+                raise ValueError("Invalid equivalence entry")
+            if (unit.is_equivalent(funit) and
+                other.is_equivalent(tunit)):
+                scale1 = (unit / funit).dimensionless_constant()
+                scale2 = (tunit / other).dimensionless_constant()
+                return make_converter(scale1, a, scale2)
+            elif (other.is_equivalent(funit) and
+                  unit.is_equivalent(tunit)):
+                scale1 = (unit / tunit).dimensionless_constant()
+                scale2 = (funit / other).dimensionless_constant()
+                return make_converter(scale1, b, scale2)
+
+        def get_err_str(unit):
+            unit_str = unit.to_string('unscaled')
+            physical_type = unit.physical_type
+            if physical_type != 'unknown':
+                unit_str = "'{0}' ({1})".format(
+                    unit_str, physical_type)
+            else:
+                unit_str = "'{0}'".format(unit_str)
+            return unit_str
+
+        unit_str = get_err_str(orig_unit)
+        other_str = get_err_str(orig_other)
+
+        raise UnitsException(
+            "{0} and {1} are not convertible".format(
+                unit_str, other_str))
+
+    def get_converter(self, other, equivs=[]):
+        """
+        Return the conversion function to convert values from `self`
+        to the specified unit.
+
+        Parameters
+        ----------
+        other : unit object or string
+           The unit to convert to.
+
+        equivs : list of equivalence pairs, optional
+           A list of equivalence pairs to try if the units are not
+           directly convertible.  See :ref:`unit_equivalencies`.
+
+        Returns
+        -------
+        func : callable
+            A callable that normally expects a single argument that is
+            a scalar value or an array of values (or anything that may
+            be converted to an array).
+
+        Raises
+        ------
+        UnitsException
+            If units are inconsistent
+        """
+        other = Unit(other)
+
+        try:
+            scale = (self / other).dimensionless_constant()
+        except UnitsException:
+            return self._apply_equivalences(
+                self, other, equivs)
+        return lambda val: scale * _condition_arg(val)
+
+    def to(self, other, value=1.0, equivs=[]):
+        """
+        Return the converted values in the specified unit.
+
+        Parameters
+        ----------
+        other : unit object or string
+            The unit to convert to.
+
+        value : scalar int or float, or sequence that can be converted to array, optional
+            Value(s) in the current unit to be converted to the
+            specified unit.  If not provided, defaults to 1.0
+
+        equivs : list of equivalence pairs, optional
+           A list of equivalence pairs to try if the units are not
+           directly convertible.  See :ref:`unit_equivalencies`.
+
+        Returns
+        -------
+        values : scalar or array
+            Converted value(s). Input value sequences are returned as
+            numpy arrays.
+
+        Raises
+        ------
+        UnitException
+            If units are inconsistent
+        """
+        other = Unit(other)
+        return self.get_converter(other, equivs=equivs)(value)
+
+    def in_units(self, other, value=1.0, equivs=[]):
+        """
+        Alias for `to` for backward compatibility with pynbody.
+        """
+        return self.to(other, value=value, equivs=equivs)
+
+    def decompose(self):
+        """
+        Return a unit object composed of only irreducible units.
+
+        Parameters
+        ----------
+        None
+
+        Returns
+        -------
+        unit : CompositeUnit object
+            New object containing only irreducible unit objects.
+        """
+        return self
+
+    @property
+    def physical_type(self):
+        """
+        Return the physical type on the unit.
+
+        Examples
+        --------
+        >>> u.m.physical_type
+        'length'
+        """
+        from . import physical
+        return physical.get_physical_type(self)
+
+    class EquivalentUnitsList(list):
+        """
+        A class to handle pretty-printing the result of
+        `find_equivalent_units`.
+        """
+        def __repr__(self):
+            if len(self) == 0:
+                return "[]"
+            else:
+                lines = []
+                for u in self:
+                    irred = u.decompose().to_string()
+                    if irred == u.name:
+                        irred = "irreducible"
+                    lines.append((u.name, irred, ', '.join(u.aliases)))
+
+                lines.sort()
+                lines.insert(0, ('Primary name', 'Unit definition', 'Aliases'))
+                widths = [0, 0, 0]
+                for line in lines:
+                    for i, col in enumerate(line):
+                        widths[i] = max(widths[i], len(col))
+
+                f = "  {{0:<{0}s}} | {{1:<{1}s}} | {{2:<{2}s}}".format(*widths)
+                lines = [f.format(*line) for line in lines]
+                lines = (lines[0:1] +
+                         ['['] +
+                         ['{0} ,'.format(x) for x in lines[1:]] +
+                         [']'])
+                return '\n'.join(lines)
+
+    def find_equivalent_units(self, equivs=[]):
+        """
+        Return a list of all the units that are the same type as the
+        specified unit.
+
+        Parameters
+        ----------
+        u : Unit instance or string
+            The `Unit` to find similar units to.
+
+        equivs : list of equivalence pairs, optional
+            A list of equivalence pairs to also list.  See
+            :ref:`unit_equivalencies`.
+
+        Returns
+        -------
+        units : list of `UnitBase`
+            A list of unit objects that match `u`.  A subclass of
+            `list` (`EquivalentUnitsList`) is returned that
+            pretty-prints the list of units when output.
+        """
+        units = [self]
+        for equiv in equivs:
+            funit, tunit = equiv[:2]
+            if self.is_equivalent(funit):
+                units.append(tunit)
+            elif self.is_equivalent(tunit):
+                units.append(funit)
+
+        equivs = set()
+        for tunit in UnitBase._registry:
+            if not isinstance(tunit, PrefixUnit):
+                for u in units:
+                    try:
+                        tunit.get_converter(u)
+                    except UnitsException:
+                        pass
+                    else:
+                        equivs.add(tunit)
+
+        return self.EquivalentUnitsList(equivs)
+
+
+class NamedUnit(UnitBase):
+    """
+    The base class of units that have a name.
+
+    Parameters
+    ----------
+    st : str or list of str
+        The name of the unit.  If a list, the first element is the
+        canonical (short) name, and the rest of the elements are
+        aliases.
+
+    register : boolean, optional
+        When `True`, also register the unit in the standard unit
+        namespace.  Default is `False`.
+
+    doc : str, optional
+        A docstring describing the unit.
+
+    format : dict, optional
+        A mapping to format-specific representations of this unit.
+        For example, for the ``Ohm`` unit, it might be nice to have it
+        displayed as ``\\Omega`` by the ``latex`` formatter.  In that
+        case, `format` argument should be set to::
+
+            {'latex': r'\\Omega'}
+
+    Raises
+    ------
+    ValueError
+        If any of the given unit names are already in the registry.
+
+    ValueError
+        If any of the given unit names are not valid Python tokens.
+    """
+    def __init__(self, st, register=False, doc=None, format=None):
+        UnitBase.__init__(self)
+
+        if isinstance(st, (bytes, unicode)):
+            self._names = [st]
+        else:
+            if len(st) == 0:
+                raise ValueError(
+                    "st list must have at least one entry")
+            self._names = st[:]
+
+        if format is None:
+            format = {}
+        self._format = format
+
+        if doc is None:
+            doc = self._generate_doc()
+
+        doc = textwrap.dedent(doc)
+        doc = textwrap.fill(doc)
+
+        self.__doc__ = doc
+
+        self._register_unit(register)
+
+    def _generate_doc(self):
+        """
+        Generate a docstring for the unit if the user didn't supply
+        one.  This is only used from the constructor and may be
+        overridden in subclasses.
+        """
+        names = self.names
+        if len(self.names) > 1:
+            return "{1} ({0})".format(*names[:2])
+        else:
+            return names[0]
+
+    def get_format_name(self, format):
+        """
+        Get a name for this unit that is specific to a particular
+        format.
+
+        Uses the dictionary passed into the `format` kwarg in the
+        constructor.
+
+        Parameters
+        ----------
+        format : str
+            The name of the format
+
+        Returns
+        -------
+        name : str
+            The name of the unit for the given format.
+        """
+        return self._format.get(format, self.name)
+
+    @property
+    def names(self):
+        """
+        Returns all of the names associated with this unit.
+        """
+        return self._names
+
+    @property
+    def name(self):
+        """
+        Returns the canonical (short) name associated with this unit.
+        """
+        return self._names[0]
+
+    @property
+    def aliases(self):
+        """
+        Returns the alias (long) names for this unit.
+        """
+        return self._names[1:]
+
+    def _register_unit(self, register):
+        """
+        Registers the unit in the registry, and optionally in another
+        namespace.  It is registered under all of the names and
+        aliases given to the constructor.
+
+        The namespace used is set with `UnitBase._set_namespace`.
+
+        Parameters
+        ----------
+        register : bool
+            When `True`, register the unit in the external namespace
+            as well as the central registry.
+        """
+        if not self._names:
+            raise UnitsException("unit has no string representation")
+
+        for st in self._names:
+            if not re.match("^[A-Za-z_]+$", st):
+                # will cause problems for simple string parser in
+                # unit() factory
+                raise ValueError(
+                    "Invalid unit name {0!r}".format(st))
+
+            if register:
+                if st in self._namespace:
+                    raise ValueError(
+                        "Object with name {0!r} already exists "
+                        "in namespace".format(st))
+                self._namespace[st] = self
+
+        self._registry.append(self)
+
+
+class IrreducibleUnit(NamedUnit):
+    """
+    Irreducible units are the units that all other units are defined
+    in terms of.
+
+    Examples are meters, seconds, kilograms, amperes, etc.  There is
+    only once instance of such a unit per type.
+    """
+    def decompose(self):
+        return CompositeUnit(1, [self], [1])
+    decompose.__doc__ = UnitBase.decompose.__doc__
+
+
+class UnrecognizedUnit(IrreducibleUnit):
+    """
+    A unit that did not parse correctly.  This allows for
+    roundtripping it as a string, but no unit operations actually work
+    on it.
+
+    Parameters
+    ----------
+    st : str
+        The name of the unit.
+    """
+    def __init__(self, st):
+        IrreducibleUnit.__init__(self, st)
+
+    def __repr__(self):
+        return "UnrecognizedUnit({0})".format(str(self))
+
+    def __str__(self):
+        return self.name
+
+    def to_string(self, format='generic'):
+        return self.name
+
+    def _register_unit(self, register):
+        pass
+
+    def _unrecognized_operator(self, *args, **kwargs):
+        raise ValueError(
+            "The unit {0!r} is unrecognized, so all arithmetic operations "
+            "with it are invalid.".format(self.name))
+
+    __pow__ = __div__ = __rdiv__ = __truediv__ = __rtruediv__ = __mul__ = \
+      __rmul__ = __lt__ = __gt__ = __le__ = __ge__ = __neg__ = \
+      _unrecognized_operator
+
+    def __eq__(self, other):
+        other = Unit(other, parse_strict='silent')
+        return isinstance(other, UnrecognizedUnit) and self.name == other.name
+
+    def __ne__(self, other):
+        return not (self == other)
+
+    def is_equivalent(self, other, equivs=[]):
+        return self == other
+
+    def get_converter(self, other, equivs=[]):
+        raise ValueError(
+            "The unit {0!r} is unrecognized.  It can not be converted "
+            "to other units.".format(self.name))
+
+    def get_format_name(self, format):
+        return self.name
+
+
+class _UnitMetaClass(type):
+    """
+    This metaclass exists because the Unit constructor should
+    sometimes return instances that already exist.  This "overrides"
+    the constructor before the new instance is actually created, so we
+    can return an existing one.
+    """
+    def __call__(self, s, represents=None, format=None, register=False,
+                 doc=None, parse_strict='raise'):
+
+
+        from .quantity import Quantity
+        if isinstance(represents, Quantity):
+            if represents.value == 1:
+                represents = represents.unit
+            elif isinstance(represents.unit, CompositeUnit):
+                represents = CompositeUnit(represents.value, bases=represents.unit.bases, powers=represents.unit.powers)
+            else:
+                represents = CompositeUnit(represents.value, bases=[represents.unit], powers=[1])
+
+        if isinstance(s, Quantity):
+            if s.value == 1:
+                s = s.unit
+            elif isinstance(s.unit, CompositeUnit):
+                s = CompositeUnit(s.value*s.unit.scale, bases=s.unit.bases, powers=s.unit.powers)
+            else:
+                s = CompositeUnit(s.value, bases=[s.unit], powers=[1])
+
+        if isinstance(represents, UnitBase):
+            # This has the effect of calling the real __new__ and
+            # __init__ on the Unit class.
+            return super(_UnitMetaClass, self).__call__(
+                s, represents, format=format, register=register, doc=doc)
+            raise TypeError("Can not convert {0!r} to a unit".format(s))
+
+        elif isinstance(s, UnitBase):
+            return s
+
+        elif isinstance(s, (bytes, unicode)):
+            if len(s.strip()) == 0:
+                # Return the NULL unit
+                return CompositeUnit(1.0, [], [])
+
+            if format is None:
+                format = 'generic'
+
+            f = unit_format.get_format(format)
+            try:
+                return f.parse(s)
+            except ValueError as e:
+                if parse_strict == 'raise':
+                    raise
+                elif parse_strict == 'warn':
+                    warnings.warn(
+                        "'{0}' did not parse using format '{1}'. {2}".format(
+                            s, format, str(e)),
+                            UnitsWarning)
+                elif parse_strict != 'silent':
+                    raise ValueError(
+                        "'parse_strict' must be 'warn', 'raise' or 'silent'")
+                return UnrecognizedUnit(s)
+
+        elif isinstance(s, (int, float, np.floating, np.integer)):
+            return CompositeUnit(s, [], [])
+
+        elif s is None:
+            raise ValueError("None is not a valid Unit")
+
+        else:
+            raise TypeError("{0} can not be converted to a Unit".format(s))
+
+
+class Unit(NamedUnit):
+    """
+    The main unit class.
+
+    There are a number of different ways to construct a Unit, but
+    always returns a `UnitBase` instance.  If the arguments refer to
+    an already-existing unit, that existing unit instance is returned,
+    rather than a new one.
+
+    - From a string::
+
+        Unit(s, format=None, parse_strict='silent')
+
+      Construct from a string representing a (possibly compound) unit.
+
+      The optional `format` keyword argument specifies the format the
+      string is in, by default ``"generic"``.  For a description of
+      the available formats, see `astropy.units.format`.
+
+      The optional `parse_strict` keyword controls what happens when an
+      unrecognized unit string is passed in.  It may be one of the following:
+
+         - ``'raise'``: (default) raise a ValueError exception.
+
+         - ``'warn'``: emit a Warning, and return an
+           `UnrecognizedUnit` instance.
+
+         - ``'silent'``: return an `UnrecognizedUnit` instance.
+
+    - From a number::
+
+        Unit(number)
+
+      Creates a dimensionless unit.
+
+    - From a `UnitBase` instance::
+
+        Unit(unit)
+
+      Returns the given unit unchanged.
+
+    - From `None`::
+
+        Unit()
+
+      Returns the null unit.
+
+    - The last form, which creates a new `Unit` is described in detail
+      below.
+
+    Parameters
+    ----------
+    st : str or list of str
+        The name of the unit.  If a list, the first element is the
+        canonical (short) name, and the rest of the elements are
+        aliases.
+
+    represents : UnitBase instance
+        The unit that this named unit represents.
+
+    register : boolean, optional
+        When `True`, also register the unit in the standard unit
+        namespace.  Default is `False`.
+
+    doc : str, optional
+        A docstring describing the unit.
+
+    format : dict, optional
+        A mapping to format-specific representations of this unit.
+        For example, for the ``Ohm`` unit, it might be nice to have it
+        displayed as ``\\Omega`` by the ``latex`` formatter.  In that
+        case, `format` argument should be set to::
+
+            {'latex': r'\\Omega'}
+
+    Raises
+    ------
+    ValueError
+        If any of the given unit names are already in the registry.
+
+    ValueError
+        If any of the given unit names are not valid Python tokens.
+    """
+    __metaclass__ = _UnitMetaClass
+
+    def __init__(self, st, represents=None, register=False, doc=None,
+                 format=None):
+
+        represents = Unit(represents)
+        self._represents = represents
+
+        NamedUnit.__init__(self, st, register=register, doc=doc,
+                           format=format)
+
+    def decompose(self):
+        return self._represents.decompose()
+    decompose.__doc__ = UnitBase.decompose.__doc__
+
+
+class PrefixUnit(Unit):
+    """
+    A unit that is simply a SI-prefixed version of another unit.
+
+    For example, `mm` is a `PrefixUnit` of ``.001 * m``.
+
+    The constructor is the same as for `Unit`.
+    """
+    pass
+
+
+class CompositeUnit(UnitBase):
+    """
+    Create a composite unit using expressions of previously defined
+    units.
+
+    Direct use of this class is not recommended. Instead use the
+    factory function `Unit(...)` and arithmetic operators to compose
+    units.
+
+    Parameters
+    ----------
+    scale : number
+        A scaling factor for the unit.
+
+    bases : sequence of `UnitBase`
+        A sequence of units this unit is composed of.
+
+    powers : sequence of numbers
+        A sequence of powers (in parallel with `bases`) for each
+        of the base units.
+    """
+    def __init__(self, scale, bases, powers):
+        if scale == 1.:
+            scale = 1
+        self._scale = scale
+        for base in bases:
+            if not isinstance(base, UnitBase):
+                raise TypeError("bases must be sequence of UnitBase instances")
+        self._bases = bases
+        self._powers = powers
+
+    def __repr__(self):
+        if len(self._bases):
+            return super(CompositeUnit, self).__repr__()
+        else:
+            return 'Unit(dimensionless)'
+
+    @property
+    def scale(self):
+        """
+        Return the scale of the composite unit.
+        """
+        return self._scale
+
+    @property
+    def bases(self):
+        """
+        Return the bases of the composite unit.
+        """
+        return self._bases
+
+    @property
+    def powers(self):
+        """
+        Return the powers of the composite unit.
+        """
+        return self._powers
+
+    def _expand_and_gather(self, decompose=False):
+        bases = {}
+        scale = self.scale
+
+        for i, (b, p) in enumerate(zip(self.bases, self.powers)):
+            if decompose:
+                b = b.decompose()
+
+            if isinstance(b, CompositeUnit):
+                scale *= b.scale ** p
+                for b_sub, p_sub in zip(b.bases, b.powers):
+                    bases[b_sub] = p_sub * p + bases.get(b_sub, 0)
+
+            else:
+                bases[b] = p + bases.get(b, 0)
+
+        bases = [(b, p) for (b, p) in bases.items() if p != 0]
+        bases.sort(key=lambda x: x[1], reverse=True)
+
+        self._bases = [x[0] for x in bases]
+        self._powers = [x[1] for x in bases]
+        self._scale = scale
+
+    def __copy__(self):
+        """
+        For compatibility with python copy module.
+        """
+        return CompositeUnit(self._scale, self._bases[:], self._powers[:])
+
+    def simplify(self):
+        self._expand_and_gather()
+        return self
+    simplify.__doc__ = UnitBase.simplify.__doc__
+
+    def decompose(self):
+        x = CompositeUnit(self.scale, self.bases, self.powers)
+        x._expand_and_gather(True)
+        return x
+    decompose.__doc__ = UnitBase.decompose.__doc__
+
+    def is_dimensionless(self):
+        x = self.decompose()
+        return (len(x.powers) == 0)
+    is_dimensionless.__doc__ = UnitBase.is_dimensionless.__doc__
+
+    def dimensionless_constant(self):
+        """
+        If this unit is dimensionless, return its scalar quantity.
+
+        Direct use of this method is not recommended. It is generally
+        better to use the `to` or `get_converter` methods
+        instead.
+        """
+        x = self.decompose()
+        c = x.scale
+        if len(x.bases):
+            raise UnitsException(
+                "'{0}' is not dimensionless".format(self.to_string()))
+        return c
+
+
+si_prefixes = [
+    (['Y'], ['yotta'], 1e24),
+    (['Z'], ['zetta'], 1e21),
+    (['E'], ['exa'], 1e18),
+    (['P'], ['peta'], 1e15),
+    (['T'], ['tera'], 1e12),
+    (['G'], ['giga'], 1e9),
+    (['M'], ['mega'], 1e6),
+    (['k'], ['kilo'], 1e3),
+    (['h'], ['hecto'], 1e2),
+    (['da'], ['deka', 'deca'], 1e1),
+    (['d'], ['deci'], 1e-1),
+    (['c'], ['centi'], 1e-2),
+    (['m'], ['milli'], 1e-3),
+    (['u'], ['micro'], 1e-6),
+    (['n'], ['nano'], 1e-9),
+    (['p'], ['pico'], 1e-12),
+    (['f'], ['femto'], 1e-15),
+    (['a'], ['atto'], 1e-18),
+    (['z'], ['zepto'], 1e-21),
+    (['y'], ['yocto'], 1e-24)
+    ]
+
+
+def _add_prefixes(u, excludes=[], register=False):
+    """
+    Set up all of the standard metric prefixes for a unit.  This
+    function should not be used directly, but instead use the
+    `prefixes` kwarg on `def_unit`.
+
+    Parameters
+    ----------
+    excludes : list of str, optional
+        Any prefixes to exclude from creation to avoid namespace
+        collisions.
+
+    register : bool, optional
+        When `True`, also register the unit in the standard unit
+        namespace.  Default is `False`.
+    """
+    for short, long, factor in si_prefixes:
+        exclude = False
+        for prefix in short:
+            if prefix in excludes:
+                exclude = True
+        if exclude:
+            continue
+
+        names = []
+        format = {}
+        for prefix in short:
+            for alias in [u.name] + [x for x in u.aliases if len(x) <= 2]:
+                names.append(prefix + alias)
+
+                # This is a hack to use Greek mu as a prefix
+                # for some formatters.
+                if prefix == 'u':
+                    format['latex'] = r'\mu ' + u.get_format_name('latex')
+                    format['unicode'] = 'μ' + u.get_format_name('unicode')
+
+                for key, val in u._format.items():
+                    format.setdefault(key, prefix + val)
+
+        for prefix in long:
+            for alias in u.aliases:
+                if len(alias) > 2:
+                    names.append(prefix + alias)
+
+        PrefixUnit(names, CompositeUnit(factor, [u], [1]), register=register, format=format)
+
+def def_unit(s, represents=None, register=None, doc=None,
+             format=None, prefixes=False, exclude_prefixes=[]):
+    """
+    Factory function for defining new units.
+
+    Parameters
+    ----------
+    names : str or list of str
+        The name of the unit.  If a list, the first element is the
+        canonical (short) name, and the rest of the elements are
+        aliases.
+
+    represents : UnitBase instance, optional
+        The unit that this named unit represents.  If not provided,
+        a new `IrreducibleUnit` is created.
+
+    register : boolean, optional
+        When `True`, also register the unit in the standard unit
+        namespace.  Default is `False`.
+
+    doc : str, optional
+        A docstring describing the unit.
+
+    format : dict, optional
+        A mapping to format-specific representations of this unit.
+        For example, for the ``Ohm`` unit, it might be nice to
+        have it displayed as ``\\Omega`` by the ``latex``
+        formatter.  In that case, `format` argument should be set
+        to::
+
+            {'latex': r'\\Omega'}
+
+    prefixes : bool, optional
+        When `True`, generate all of the SI prefixed versions of the
+        unit as well.  For example, for a given unit `m`, will generate
+        `mm`, `cm`, `km`, etc.  Default is `False`.  This function
+        always returns the base unit object, even if multiple scaled
+        versions of the unit were created.
+
+    exclude_prefixes : list of str, optional
+        If any of the SI prefixes need to be excluded, they may be
+        listed here.  For example, `Pa` can be interpreted either as
+        "petaannum" or "Pascal".  Therefore, when defining the
+        prefixes for `a`, `exclude_prefixes` should be set to
+        ``["P"]``.
+
+    Returns
+    -------
+    unit : `UnitBase` object
+        The newly-defined unit, or a matching unit that was already
+        defined.
+    """
+
+    if register is None:
+        register = False
+    if represents is not None:
+        result = Unit(s, represents, register=register, doc=doc,
+                      format=format)
+    else:
+        result = IrreducibleUnit(s, register=register, doc=doc, format=format)
+
+    if prefixes:
+        _add_prefixes(result, excludes=exclude_prefixes, register=register)
+    return result
+
+
+def _condition_arg(value):
+    """
+    Validate value is acceptable for conversion purposes.
+
+    Will convert into an array if not a scalar, and can be converted
+    into an array
+
+    Parameters
+    ----------
+    value: int or float value, or sequence of such values
+        that can be converted into an array if not scalar
+
+    Returns
+    -------
+    Scalar value or numpy array
+
+    Raises
+    ------
+    ValueError
+        If value is not as expected
+    """
+    if isinstance(value, float) or isinstance(value, int):
+        return value
+    else:
+        try:
+            avalue = np.array(value)
+            dt = str(avalue.dtype)
+            if not (dt.startswith('int') or dt.startswith('float')):
+                raise ValueError("Must be convertable to int or float array")
+            if ma.isMaskedArray(value):
+                return value
+            return avalue
+        except ValueError:
+            raise ValueError(
+                "Value not scalar compatible or convertable into a float or "
+                "integer array")
diff --git a/astropy/units/equivalencies.py b/astropy/units/equivalencies.py
new file mode 100644
index 0000000..db948cd
--- /dev/null
+++ b/astropy/units/equivalencies.py
@@ -0,0 +1,51 @@
+# Licensed under a 3-clause BSD style license - see LICENSE.rst
+"""
+A set of standard astronomical equivalencies.
+"""
+from __future__ import absolute_import, division, print_function, unicode_literals
+
+from .._constants import si as _si
+from . import si
+from . import cgs
+
+__all__ = ['spectral', 'spectral_density']
+
+
+def spectral():
+    """
+    Returns a list of equivalence pairs that handle spectral
+    wavelength, frequency, and energy equivalences.
+
+    Allows conversions between wavelength units, frequency units and
+    energy units as they relate to light.
+    """
+
+    return [
+        (si.m, si.Hz, lambda x: _si.c / x),
+        (si.m, si.J, lambda x: (_si.c * _si.h) / x),
+        (si.Hz, si.J, lambda x: _si.h * x)
+    ]
+
+
+def spectral_density(sunit, sfactor):
+    """
+    Returns a list of equivalence pairs that handle spectral density
+    with regard to wavelength and frequency.
+    """
+    c_Aps = _si.c * 10 ** 10
+
+    flambda = cgs.erg / si.angstrom / si.cm ** 2 / si.s
+    fnu = cgs.erg / si.Hz / si.cm ** 2 / si.s
+
+    def converter(x):
+        return x * (sunit.to(si.AA, sfactor, spectral()) ** 2 / c_Aps)
+
+    def iconverter(x):
+        return x / (sunit.to(si.AA, sfactor, spectral()) ** 2 / c_Aps)
+
+    return [
+        (si.AA, fnu, converter, iconverter),
+        (flambda, fnu, converter, iconverter),
+        (si.AA, si.Hz, converter, iconverter),
+        (flambda, si.Hz, converter, iconverter)
+        ]
diff --git a/astropy/units/format/__init__.py b/astropy/units/format/__init__.py
new file mode 100644
index 0000000..ad85315
--- /dev/null
+++ b/astropy/units/format/__init__.py
@@ -0,0 +1,49 @@
+# Licensed under a 3-clause BSD style license - see LICENSE.rst
+"""
+A collection of different unit formats.
+"""
+from __future__ import absolute_import, division, print_function, unicode_literals
+
+from .base import Base
+from .generic import Generic, Unscaled
+from .cds import CDS
+from .console import Console
+from .fits import Fits
+from .latex import Latex
+from .unicode_format import Unicode
+from .vounit import VOUnit
+
+__all__ = [
+    'Generic', 'CDS', 'Console', 'Fits', 'Latex', 'Unicode', 'Unscaled',
+    'VOUnit', 'get_format']
+
+
+def get_format(format=None):
+    """
+    Get a formatter by name.
+
+    Parameters
+    ----------
+    format : str or `astropy.units.format.Base` instance or subclass
+        The name of the format, or the format instance or subclass
+        itself.
+
+    Returns
+    -------
+    format : `astropy.units.format.Base` instance
+        The requested formatter.
+    """
+    if isinstance(format, type) and issubclass(format, Base):
+        return format()
+    elif isinstance(format, Base):
+        return format
+
+    if format is None:
+        format = 'generic'
+    format = format.lower()
+    for key in __all__:
+        val = globals()[key]
+        if (issubclass(val, Base) and
+            key.lower() == format.lower()):
+            return val()
+    raise ValueError("Unknown format {0!r}".format(format))
diff --git a/astropy/units/format/base.py b/astropy/units/format/base.py
new file mode 100644
index 0000000..5dff928
--- /dev/null
+++ b/astropy/units/format/base.py
@@ -0,0 +1,23 @@
+# Licensed under a 3-clause BSD style license - see LICENSE.rst
+from __future__ import absolute_import, division, print_function, unicode_literals
+
+
+class Base(object):
+    """
+    The abstract base class of all unit formats.
+    """
+    def parse(self, s):
+        """
+        Convert a string to a unit object.  Must be overridden by the
+        subclass.
+        """
+        raise NotImplementedError(
+            "Can not parse {0}".format(self.__class__.__name__))
+
+    def to_string(self, u):
+        """
+        Convert a unit object to a string.  Must be overridden by the
+        subclass.
+        """
+        raise NotImplementedError(
+            "Can not output in {0} format".format(self.__class__.__name__))
diff --git a/astropy/units/format/cds.py b/astropy/units/format/cds.py
new file mode 100644
index 0000000..07a688d
--- /dev/null
+++ b/astropy/units/format/cds.py
@@ -0,0 +1,271 @@
+# -*- coding: utf-8 -*-
+# Licensed under a 3-clause BSD style license - see LICNSE.rst
+"""
+Handles a "generic" string format for units
+"""
+from __future__ import absolute_import, division, print_function, unicode_literals
+
+from fractions import Fraction
+import functools
+
+from .base import Base
+from . import utils
+
+
+# TODO: Support logarithmic units using bracketed syntax
+
+class CDS(Base):
+    """
+    Support the `Centre de Données astronomiques de Strasbourg
+    <http://cds.u-strasbg.fr/>`_ `Standards for Astronomical
+    Catalogues 2.0 <http://cds.u-strasbg.fr/doc/catstd-3.2.htx>`_
+    format.  This format is used by VOTable up to version 1.2.
+    """
+    def __init__(self):
+        # Build this on the class, so it only gets generated once.
+        if not '_units' in CDS.__dict__:
+            CDS._units = self._generate_unit_names()
+
+        if '_parser' not in CDS.__dict__:
+            CDS._parser = self._make_parser()
+
+    @staticmethod
+    def _generate_unit_names():
+        from ... import units as u
+        names = {}
+
+        names['%'] = u.Unit(0.01)
+
+        bases = [
+            'A', 'C', 'cd', 'eV', 'F', 'g', 'H', 'Hz', 'J', 'K',
+            'lm', 'lx', 'm', 'mol', 'N', 'Ohm', 'Pa', 'rad', 's', 'S',
+            'sr', 'T', 'V', 'W', 'Wb']
+
+        prefixes = [
+            'y', 'z', 'a', 'f', 'p', 'n', 'u', 'm', 'c', 'd',
+            '', 'da', 'h', 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y']
+
+        for base in bases:
+            for prefix in prefixes:
+                key = prefix + base
+                names[key] = getattr(u, key)
+
+        simple_bases = [
+            'a', 'AU', 'arcmin', 'arcsec', 'barn', 'bit',
+            'byte', 'ct', 'D', 'd', 'deg', 'h', 'Jy', 'mag', 'mas',
+            'min', 'pc', 'pix', 'Ry', 'solLum', 'solMass', 'solRad',
+            'Sun', 'yr']
+
+        for base in simple_bases:
+            names[base] = getattr(u, base)
+
+        return names
+
+    @classmethod
+    def _make_parser(cls):
+        """
+        The grammar here is based on the description in the `Standards
+        for Astronomical Catalogues 2.0
+        <http://cds.u-strasbg.fr/doc/catstd-3.2.htx>`_, which is not
+        terribly precise.  The exact grammar is here is based on the
+        YACC grammar in the `unity library
+        <https://bitbucket.org/nxg/unity/>`_.
+        """
+        from astropy.extern import pyparsing as p
+
+        product = p.Literal(".")
+        division = p.Literal("/")
+        open_p = p.Literal("(")
+        close_p = p.Literal(")")
+        literal10 = p.Literal("10")
+        literalx = p.Literal("x")
+
+        unsigned_integer = p.Regex(r'\d+')
+        signed_integer = p.Regex(r'[+-]\d+')
+        integer = p.Regex(r'[+-]?\d+')
+        floating_point = p.Regex(r'[+-]?((\d+\.?\d*)|(\.\d+))([eE][+-]?\d+)?')
+
+        factor = p.Forward()
+        main = p.Forward()
+        numeric_power = p.Forward()
+        product_of_units = p.Forward()
+        unit_expression = p.Forward()
+        unit = p.Forward()
+        unit_with_power = p.Forward()
+
+        main << (
+            (p.Optional(factor, default=1.0) +
+             product_of_units +
+             p.StringEnd()))
+
+        product_of_units << (
+            (unit_expression + p.StringEnd()) ^
+            (division + unit_expression) ^
+            (unit_expression + product + product_of_units) ^
+            (unit_expression + division + product_of_units))
+
+        unit_expression << (
+            (unit_with_power) ^
+            (p.Suppress(open_p) + product_of_units + p.Suppress(close_p)))
+
+        factor << (
+            (floating_point + literalx + literal10 + signed_integer) ^
+            (literal10 + signed_integer) ^
+            (unsigned_integer) ^
+            (literal10) ^
+            (floating_point))
+
+        unit_with_power << (
+            (unit + p.Optional(numeric_power)))
+
+        numeric_power << (
+            integer)
+
+        unit << (
+            p.Literal('%') |
+            p.Word(p.alphas, p.alphas + '_'))
+
+        # Set actions
+        for key, val in locals().items():
+            if isinstance(val, p.ParserElement):
+                val.setName(key)
+                val.leaveWhitespace()
+            method_name = "_parse_{0}".format(key)
+            if hasattr(cls, method_name):
+                val.setParseAction(getattr(cls, method_name))
+
+        return main
+
+    @classmethod
+    @utils._trace
+    def _parse_unsigned_integer(cls, s, loc, toks):
+        return int(toks[0])
+
+    @classmethod
+    @utils._trace
+    def _parse_signed_integer(cls, s, loc, toks):
+        return int(toks[0])
+
+    @classmethod
+    @utils._trace
+    def _parse_integer(cls, s, loc, toks):
+        return int(toks[0])
+
+    @classmethod
+    @utils._trace
+    def _parse_floating_point(cls, s, loc, toks):
+        return float(toks[0])
+
+    @classmethod
+    @utils._trace
+    def _parse_factor(cls, s, loc, toks):
+        if len(toks) == 1:
+            return toks[0]
+        elif len(toks) == 2:
+            return 10.0 ** float(toks[1])
+        elif len(toks) == 4:
+            return toks[0] * 10.0 ** toks[3]
+
+    @classmethod
+    @utils._trace
+    def _parse_unit_with_power(cls, s, loc, toks):
+        if len(toks) == 1:
+            return toks[0]
+        elif len(toks) == 2:
+            return toks[0] ** toks[1]
+
+    @classmethod
+    @utils._trace
+    def _parse_unit(cls, s, loc, toks):
+        from astropy.extern import pyparsing as p
+
+        unit = toks[0]
+        if unit not in cls._units:
+            raise p.ParseException(
+                "Unit {0!r} not supported by the CDS SAC "
+                "standard.".format(unit))
+
+        return cls._units[unit]
+
+    @classmethod
+    @utils._trace
+    def _parse_product_of_units(cls, s, loc, toks):
+        if len(toks) == 1:
+            return toks[0]
+        elif len(toks) == 2:
+            from ..core import Unit
+            return Unit(1.0 / toks[1])
+        elif len(toks) == 3:
+            if toks[1] == '/':
+                return toks[0] / toks[2]
+            else:
+                return toks[0] * toks[2]
+
+    @classmethod
+    @utils._trace
+    def _parse_main(cls, s, loc, toks):
+        from ..core import Unit
+        return Unit(toks[0] * toks[1])
+
+    def parse(self, s):
+        from astropy.extern import pyparsing as p
+
+        if utils.DEBUG:
+            print("parse", s)
+
+        if ' ' in s:
+            raise ValueError('CDS unit must not contain whitespace')
+
+        # This is a short circuit for the case where the string
+        # is just a single unit name
+        try:
+            return self._parse_unit(s, 0, [s])
+        except p.ParseException as e:
+            try:
+                return self._parser.parseString(s, parseAll=True)[0]
+            except p.ParseException as e:
+                raise ValueError("{0} in {1!r}".format(
+                    utils.cleanup_pyparsing_error(e), s))
+
+    def _get_unit_name(self, unit):
+        return unit.get_format_name('cds')
+
+    def _format_unit_list(self, units):
+        out = []
+        for base, power in units:
+            if power == 1:
+                out.append(self._get_unit_name(base))
+            else:
+                out.append('{0}{1}'.format(
+                    self._get_unit_name(base), power))
+        return '.'.join(out)
+
+    def to_string(self, unit):
+        from .. import core
+
+        # Remove units that aren't known to the format
+        unit = utils.decompose_to_known_units(unit, self._get_unit_name)
+
+        if isinstance(unit, core.CompositeUnit):
+            s = ''
+            if unit.scale != 1:
+                m, e = utils.split_mantissa_exponent(unit.scale)
+                parts = []
+                if m:
+                    parts.append(m)
+                if e:
+                    if not e.startswith('-'):
+                        e = "+" + e
+                    parts.append('10{0}'.format(e))
+                s = 'x'.join(parts)
+            else:
+                s = ''
+
+            pairs = zip(unit.bases, unit.powers)
+            pairs.sort(key=lambda x: x[1], reverse=True)
+
+            s += self._format_unit_list(pairs)
+        elif isinstance(unit, core.NamedUnit):
+            s = self._get_unit_name(unit)
+
+        return s
diff --git a/astropy/units/format/console.py b/astropy/units/format/console.py
new file mode 100644
index 0000000..85ad366
--- /dev/null
+++ b/astropy/units/format/console.py
@@ -0,0 +1,94 @@
+# -*- coding: utf-8 -*-
+# Licensed under a 3-clause BSD style license - see LICENSE.rst
+"""
+Handles the "Console" unit format.
+"""
+from __future__ import absolute_import, division, print_function, unicode_literals
+
+from . import base
+from . import utils
+
+
+class Console(base.Base):
+    """
+    Output-only format for to display pretty formatting at the
+    console.
+
+    For example::
+
+      >>> print fluxunit.to_string('console')
+       erg
+      ------
+      s cm^2
+    """
+    def __init__(self):
+        pass
+
+    _times = "*"
+    _line = "-"
+
+    def _get_unit_name(self, unit):
+        return unit.get_format_name('console')
+
+    def _format_superscript(self, number):
+        return '^{0}'.format(number)
+
+    def _format_unit_list(self, units):
+        out = []
+        for base, power in units:
+            if power == 1:
+                out.append(self._get_unit_name(base))
+            else:
+                out.append('{0}{1}'.format(
+                    self._get_unit_name(base),
+                    self._format_superscript(str(power))))
+        return ' '.join(out)
+
+    def _format_exponential_notation(self, val):
+        m, ex = utils.split_mantissa_exponent(val)
+
+        parts = []
+        if m:
+            parts.append(m)
+
+        if ex:
+            parts.append("10{0}".format(
+                self._format_superscript(ex)))
+
+        return self._times.join(parts)
+
+    def to_string(self, unit):
+        from .. import core
+
+        if isinstance(unit, core.CompositeUnit):
+            if unit.scale != 1:
+                s = self._format_exponential_notation(unit.scale)
+            else:
+                s = ''
+
+            if len(unit.bases):
+                positives, negatives = utils.get_grouped_by_powers(
+                    unit.bases, unit.powers)
+                if len(negatives):
+                    if len(positives):
+                        positives = self._format_unit_list(positives)
+                    else:
+                        positives = '1'
+                    negatives = self._format_unit_list(negatives)
+                    l = len(s)
+                    r = max(len(positives), len(negatives))
+                    f = "{{0:^{0}s}} {{1:^{1}s}}".format(l, r)
+
+                    lines = [
+                        f.format('', positives),
+                        f.format(s, self._line * r),
+                        f.format('', negatives)
+                        ]
+                    s = '\n'.join(lines)
+                else:
+                    positives = self._format_unit_list(positives)
+                    s += positives
+        elif isinstance(unit, core.NamedUnit):
+            s = self._get_unit_name(unit)
+
+        return s
diff --git a/astropy/units/format/fits.py b/astropy/units/format/fits.py
new file mode 100644
index 0000000..c2e17b6
--- /dev/null
+++ b/astropy/units/format/fits.py
@@ -0,0 +1,124 @@
+# Licensed under a 3-clause BSD style license - see LICENSE.rst
+"""
+Handles the "FITS" unit format.
+"""
+from __future__ import absolute_import, division, print_function, unicode_literals
+
+import warnings
+
+from . import generic
+from . import utils
+
+
+class Fits(generic.Generic):
+    """
+    The FITS standard unit format.
+
+    This supports the format defined in the Units section of the `FITS
+    Standard <http://fits.gsfc.nasa.gov/fits_standard.html>`_.
+    """
+    name = 'fits'
+
+    def __init__(self):
+        if not '_units' in Fits.__dict__:
+            Fits._units, Fits._deprecated_units = self._generate_unit_names()
+
+        if not '_parser' in Fits.__dict__:
+            Fits._parser = self._make_parser()
+
+    @staticmethod
+    def _generate_unit_names():
+        from ... import units as u
+        names = {}
+        deprecated_names = set()
+
+        bases = [
+            'm', 'g', 's', 'rad', 'sr', 'K', 'A', 'mol', 'cd',
+            'Hz', 'J', 'W', 'V', 'N', 'Pa', 'C', 'Ohm', 'S',
+            'F', 'Wb', 'T', 'H', 'lm', 'lx', 'a', 'yr', 'eV',
+            'pc', 'Jy', 'mag', 'R', 'bit', 'byte'
+            ]
+        deprecated_bases = [
+            'G', 'barn'
+            ]
+        prefixes = [
+            'y', 'z', 'a', 'f', 'p', 'n', 'u', 'm', 'c', 'd',
+            '', 'da', 'h', 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y']
+
+        for base in bases + deprecated_bases:
+            for prefix in prefixes:
+                key = prefix + base
+                names[key] = getattr(u, key)
+        for base in deprecated_bases:
+            for prefix in prefixes:
+                deprecated_names.add(prefix + base)
+
+        simple_units = [
+            'deg', 'arcmin', 'arcsec', 'mas', 'min', 'h', 'd', 'Ry',
+            'solMass', 'u', 'solLum', 'solRad', 'AU', 'lyr', 'count',
+            'photon', 'ph', 'pixel', 'pix', 'D', 'Sun', 'chan', 'bin',
+            'voxel', 'adu', 'beam'
+            ]
+        deprecated_units = [
+            'erg', 'Angstrom'
+        ]
+
+        for unit in simple_units + deprecated_units:
+            names[unit] = getattr(u, unit)
+        for unit in deprecated_units:
+            deprecated_names.add(unit)
+
+        return names, deprecated_names
+
+    @classmethod
+    def _parse_unit(cls, s, loc, toks):
+        from astropy.extern import pyparsing as p
+
+        unit = toks[0]
+        if unit not in cls._units:
+            raise p.ParseException(
+                "Unit {0!r} not supported by the FITS standard.".format(unit))
+
+        if unit in cls._deprecated_units:
+            warnings.warn(
+                "The unit {0!r} has been deprecated in the FITS "
+                "standard.".format(unit),
+                DeprecationWarning)
+
+        return cls._units[unit]
+
+    def _get_unit_name(self, unit):
+        name = unit.get_format_name('fits')
+
+        if name not in self._units:
+            raise ValueError(
+                "Unit {0!r} is not part of the FITS standard".format(name))
+
+        if name in self._deprecated_units:
+            warnings.warn(
+                "The unit {0!r} has been deprecated in the FITS "
+                "standard.".format(name),
+                DeprecationWarning)
+
+        return name
+
+    def to_string(self, unit):
+        from .. import core
+
+        # Remove units that aren't known to the format
+        unit = utils.decompose_to_known_units(unit, self._get_unit_name)
+
+        if isinstance(unit, core.CompositeUnit):
+            if unit.scale != 1.0:
+                raise ValueError(
+                    "The FITS unit format is not able to represent scale. "
+                    "Multiply your data by {0:e}.".format(unit.scale))
+
+            pairs = zip(unit.bases, unit.powers)
+            pairs.sort(key=lambda x: x[1], reverse=True)
+
+            s = self._format_unit_list(pairs)
+        elif isinstance(unit, core.NamedUnit):
+            s = self._get_unit_name(unit)
+
+        return s
diff --git a/astropy/units/format/generic.py b/astropy/units/format/generic.py
new file mode 100644
index 0000000..76c79c5
--- /dev/null
+++ b/astropy/units/format/generic.py
@@ -0,0 +1,301 @@
+# Licensed under a 3-clause BSD style license - see LICENSE.rst
+"""
+Handles a "generic" string format for units
+"""
+from __future__ import absolute_import, division, print_function, unicode_literals
+
+from fractions import Fraction
+
+from .base import Base
+from . import utils
+
+
+class Generic(Base):
+    """
+    A "generic" format.
+
+    The syntax of the format is based directly on the FITS standard,
+    but instead of only supporting the units that FITS knows about, it
+    supports any unit available in the `astropy.units` namespace.
+    """
+    _show_scale = True
+
+    def __init__(self):
+        # Build this on the class, so it only gets generated once.
+        if '_parser' not in Generic.__dict__:
+            Generic._parser = self._make_parser()
+
+    @classmethod
+    def _make_parser(cls):
+        """
+        The grammar here is based on the description in the `FITS
+        standard
+        <http://fits.gsfc.nasa.gov/standard30/fits_standard30aa.pdf>`_,
+        Section 4.3, which is not terribly precise.  The exact grammar
+        is here is based on the YACC grammar in the `unity library
+        <https://bitbucket.org/nxg/unity/>`_.
+
+        This same grammar is used by the `"fits"` and `"vounit"`
+        formats, the only difference being the set of available unit
+        strings.
+        """
+        from astropy.extern import pyparsing as p
+
+        product = p.Literal("*") | p.Literal(".") | p.White()
+        division = p.Literal("/")
+        power = p.Literal("**") | p.Literal("^") | p.Empty()
+        open_p = p.Literal("(")
+        close_p = p.Literal(")")
+        # TODO: We only support the sqrt function for now because it's
+        # obvious how to handle it.
+        function_name = p.Literal("sqrt")
+
+        unsigned_integer = p.Regex(r'\d+')
+        signed_integer = p.Regex(r'[+-]\d+')
+        integer = p.Regex(r'[+-]?\d+')
+        floating_point = p.Regex(r'[+-]?((\d+\.?\d*)|(\.\d+))([eE][+-]?\d+)?')
+
+        division_product_of_units = p.Forward()
+        factor = p.Forward()
+        factor_product_of_units = p.Forward()
+        frac = p.Forward()
+        function = p.Forward()
+        main = p.Forward()
+        numeric_power = p.Forward()
+        product_of_units = p.Forward()
+        unit_expression = p.Forward()
+        unit = p.Forward()
+        unit_with_power = p.Forward()
+
+        main << (
+            (factor_product_of_units) ^
+            (division_product_of_units))
+
+        factor_product_of_units << (
+            (p.Optional(factor +
+                        p.Suppress(p.Optional(p.White())), default=1.0) +
+             product_of_units +
+             p.StringEnd()))
+
+        division_product_of_units << (
+            (p.Optional(factor, default=1.0) +
+             p.Optional(product_of_units, default=1.0) +
+             p.Suppress(division) +
+             unit_expression +
+             p.StringEnd()))
+
+        product_of_units << (
+            (unit_expression + p.Suppress(product) + product_of_units) ^
+            (unit_expression))
+
+        function << (
+            function_name +
+            p.Suppress(open_p) + unit_expression + p.Suppress(close_p))
+
+        unit_expression << (
+            (function) ^
+            (unit_with_power) ^
+            (p.Suppress(open_p) + product_of_units + p.Suppress(close_p))
+            )
+
+        factor << (
+            (unsigned_integer + signed_integer) ^
+            (unsigned_integer + p.Suppress(power) + numeric_power) ^
+            (floating_point + p.Suppress(p.White()) +
+             unsigned_integer + signed_integer) ^
+            (floating_point + p.Suppress(p.White()) +
+             unsigned_integer + p.Suppress(power) + numeric_power) ^
+            (floating_point)
+            )
+
+        unit << p.Word(p.alphas, p.alphas + '_')
+
+        unit_with_power << (
+            (unit + p.Suppress(power) + numeric_power) ^
+            (unit))
+
+        numeric_power << (
+            integer |
+            (p.Suppress(open_p) + integer + p.Suppress(close_p)) ^
+            (p.Suppress(open_p) + floating_point + p.Suppress(close_p)) ^
+            (p.Suppress(open_p) + frac + p.Suppress(close_p)))
+
+        frac << (
+            integer + p.Suppress(division) + integer)
+
+        # Set actions
+        for key, val in locals().items():
+            if isinstance(val, p.ParserElement):
+                val.setName(key)
+                val.leaveWhitespace()
+            method_name = "_parse_{0}".format(key)
+            if hasattr(cls, method_name):
+                val.setParseAction(getattr(cls, method_name))
+
+        return main
+
+    @classmethod
+    @utils._trace
+    def _parse_unsigned_integer(cls, s, loc, toks):
+        return int(toks[0])
+
+    @classmethod
+    @utils._trace
+    def _parse_signed_integer(cls, s, loc, toks):
+        return int(toks[0])
+
+    @classmethod
+    @utils._trace
+    def _parse_integer(cls, s, loc, toks):
+        return int(toks[0])
+
+    @classmethod
+    @utils._trace
+    def _parse_floating_point(cls, s, loc, toks):
+        return float(toks[0])
+
+    @classmethod
+    @utils._trace
+    def _parse_factor(cls, s, loc, toks):
+        if len(toks) == 1:
+            return toks[0]
+        elif len(toks) == 2:
+            return toks[0] ** float(toks[1])
+        elif len(toks) == 3:
+            return float(toks[0]) * toks[1] ** float(toks[2])
+
+    @classmethod
+    @utils._trace
+    def _parse_frac(cls, s, loc, toks):
+        return Fraction(toks[0], toks[1])
+
+    @classmethod
+    @utils._trace
+    def _parse_unit(cls, s, loc, toks):
+        from astropy.extern import pyparsing as p
+
+        if toks[0] in cls._unit_namespace:
+            return cls._unit_namespace[toks[0]]
+        raise p.ParseException(
+            s, loc, "{0!r} is not a recognized unit".format(toks[0]))
+
+    @classmethod
+    @utils._trace
+    def _parse_product_of_units(cls, s, loc, toks):
+        if len(toks) == 1:
+            return toks[0]
+        else:
+            return toks[0] * toks[1]
+
+    @classmethod
+    @utils._trace
+    def _parse_division_product_of_units(cls, s, loc, toks):
+        from ..core import Unit
+        return Unit((toks[0] * toks[1]) / toks[2])
+
+    @classmethod
+    @utils._trace
+    def _parse_factor_product_of_units(cls, s, loc, toks):
+        if toks[0] != 1.0:
+            from ..core import Unit
+            return Unit(toks[0] * toks[1])
+        else:
+            return toks[1]
+
+    @classmethod
+    @utils._trace
+    def _parse_unit_with_power(cls, s, loc, toks):
+        if len(toks) == 1:
+            return toks[0]
+        else:
+            return toks[0] ** toks[1]
+
+    @classmethod
+    @utils._trace
+    def _parse_function(cls, s, loc, toks):
+        from astropy.extern import pyparsing as p
+
+        # TODO: Add support for more functions here
+        if toks[0] == 'sqrt':
+            return toks[1] ** -2.0
+        else:
+            raise p.ParseException(
+                s, loc, "{0!r} is not a recognized function".format(
+                    toks[0]))
+
+    def parse(self, s):
+        from astropy.extern import pyparsing as p
+
+        if utils.DEBUG:
+            print("parse", s)
+
+        if '_unit_namespace' not in Generic.__dict__:
+            from ... import units as u
+            ns = {}
+            for key, val in u.__dict__.items():
+                if isinstance(val, u.UnitBase):
+                    ns[key] = val
+            Generic._unit_namespace = ns
+
+        # This is a short circuit for the case where the string
+        # is just a single unit name
+        try:
+            return self._parse_unit(s, 0, [s])
+        except p.ParseException as e:
+            try:
+                return self._parser.parseString(s, parseAll=True)[0]
+            except p.ParseException as e:
+                raise ValueError("{0} in {1!r}".format(
+                    utils.cleanup_pyparsing_error(e), s))
+
+    def _get_unit_name(self, unit):
+        return unit.get_format_name('generic')
+
+    def _format_unit_list(self, units):
+        out = []
+        units.sort(key=lambda x: self._get_unit_name(x[0]).lower())
+
+        for base, power in units:
+            if power == 1:
+                out.append(self._get_unit_name(base))
+            elif isinstance(power, Fraction):
+                out.append('{0}({1})'.format(
+                    self._get_unit_name(base), power))
+            else:
+                out.append('{0}{1}'.format(
+                    self._get_unit_name(base), power))
+        return ' '.join(out)
+
+    def to_string(self, unit):
+        from .. import core
+
+        if isinstance(unit, core.CompositeUnit):
+            if unit.scale != 1 and self._show_scale:
+                s = '{0:e} '.format(unit.scale)
+            else:
+                s = ''
+
+            if len(unit.bases):
+                positives, negatives = utils.get_grouped_by_powers(
+                    unit.bases, unit.powers)
+                if len(positives):
+                    s += self._format_unit_list(positives)
+                elif s == '':
+                    s = '1'
+
+                if len(negatives):
+                    s += ' / ({0})'.format(self._format_unit_list(negatives))
+        elif isinstance(unit, core.NamedUnit):
+            s = self._get_unit_name(unit)
+
+        return s
+
+
+class Unscaled(Generic):
+    """
+    A format that doesn't display the scale part of the unit, other
+    than that, it is identical to the `Generic` format.
+
+    This is used in some error messages where the scale is irrelevant.
+    """
+    _show_scale = False
diff --git a/astropy/units/format/latex.py b/astropy/units/format/latex.py
new file mode 100644
index 0000000..706efd5
--- /dev/null
+++ b/astropy/units/format/latex.py
@@ -0,0 +1,79 @@
+# Licensed under a 3-clause BSD style license - see LICENSE.rst
+"""
+Handles the "LaTeX" unit format.
+"""
+from __future__ import absolute_import, division, print_function, unicode_literals
+
+from . import base
+from . import utils
+
+
+class Latex(base.Base):
+    """
+    Output LaTeX to display the unit based on IAU style guidelines.
+
+    Attempts to follow the `IAU Style Manual
+    <http://www.iau.org/static/publications/stylemanual1989.pdf>`_.
+    """
+    def __init__(self):
+        pass
+
+    def _latex_escape(self, name):
+        # This doesn't escape arbitrary LaTeX strings, but it should
+        # be good enough for unit names which are required to be alpha
+        # + "_" anyway.
+        return name.replace('_', r'\_')
+
+    def _get_unit_name(self, unit):
+        name = unit.get_format_name('latex')
+        if name == unit.name:
+            return self._latex_escape(name)
+        return name
+
+    def _format_unit_list(self, units):
+        out = []
+        for base, power in units:
+            if power == 1:
+                out.append(self._get_unit_name(base))
+            else:
+                out.append('{0}^{{{1}}}'.format(
+                    self._get_unit_name(base), power))
+        return r'\ '.join(out)
+
+    def _format_exponential_notation(self, val):
+        m, ex = utils.split_mantissa_exponent(val)
+
+        parts = []
+        if m:
+            parts.append(m)
+        if ex:
+            parts.append("10^{{{0}}}".format(ex))
+
+        return r" \times ".join(parts)
+
+    def to_string(self, unit):
+        from .. import core
+
+        if isinstance(unit, core.CompositeUnit):
+            if unit.scale != 1:
+                s = self._format_exponential_notation(unit.scale) + r'\ '
+            else:
+                s = ''
+
+            if len(unit.bases):
+                positives, negatives = utils.get_grouped_by_powers(
+                    unit.bases, unit.powers)
+                if len(negatives):
+                    if len(positives):
+                        positives = self._format_unit_list(positives)
+                    else:
+                        positives = '1'
+                    negatives = self._format_unit_list(negatives)
+                    s += r'\frac{{{0}}}{{{1}}}'.format(positives, negatives)
+                else:
+                    positives = self._format_unit_list(positives)
+                    s += positives
+        elif isinstance(unit, core.NamedUnit):
+            s = self._get_unit_name(unit)
+
+        return r'$\mathrm{{{0}}}$'.format(s)
diff --git a/astropy/units/format/unicode_format.py b/astropy/units/format/unicode_format.py
new file mode 100644
index 0000000..0007c00
--- /dev/null
+++ b/astropy/units/format/unicode_format.py
@@ -0,0 +1,50 @@
+# -*- coding: utf-8 -*-
+# Licensed under a 3-clause BSD style license - see LICENSE.rst
+"""
+Handles the "Unicode" unit format.
+"""
+from __future__ import absolute_import, division, print_function, unicode_literals
+
+from . import console
+
+
+class Unicode(console.Console):
+    """
+    Output-only format for to display pretty formatting at the console
+    using Unicode characters.
+
+    For example::
+
+      >>> print u.Ry.decompose().to_string('unicode')
+                 m² kg
+      2.18×10-¹⁸ ─────
+                  s²
+    """
+
+    def __init__(self):
+        pass
+
+    _times = "×"
+    _line = "─"
+
+    def _get_unit_name(self, unit):
+        return unit.get_format_name('unicode')
+
+    @staticmethod
+    def _format_superscript(number):
+        mapping = {
+            '0': '⁰',
+            '1': '¹',
+            '2': '²',
+            '3': '³',
+            '4': '⁴',
+            '5': '⁵',
+            '6': '⁶',
+            '7': '⁷',
+            '8': '⁸',
+            '9': '⁹',
+            '-': '⁻'}
+        output = []
+        for c in number:
+            output.append(mapping[c])
+        return ''.join(output)
diff --git a/astropy/units/format/utils.py b/astropy/units/format/utils.py
new file mode 100644
index 0000000..969a953
--- /dev/null
+++ b/astropy/units/format/utils.py
@@ -0,0 +1,126 @@
+# Licensed under a 3-clause BSD style license - see LICENSE.rst
+"""
+Utilities shared by the different formats.
+"""
+from __future__ import absolute_import, division, print_function, unicode_literals
+
+import functools
+import re
+
+
+def get_grouped_by_powers(bases, powers):
+    """
+    Groups the powers and bases in the given
+    `~astropy.units.core.CompositeUnit` into positive powers and
+    negative powers for easy display on either side of a solidus.
+
+    Parameters
+    ----------
+    bases : list of `astropy.units.UnitBase` instances
+
+    powers : list of ints
+
+    Returns
+    -------
+    positives, negatives : tuple of lists
+       Each element in each list is tuple of the form (*base*,
+       *power*).  The negatives have the sign of their power reversed
+       (i.e. the powers are all positive).
+    """
+    positive = []
+    negative = []
+    for base, power in zip(bases, powers):
+        if power < 0:
+            negative.append((base, -power))
+        elif power > 0:
+            positive.append((base, power))
+        else:
+            raise ValueError("Unit with 0 power")
+    return positive, negative
+
+
+def split_mantissa_exponent(v):
+    """
+    Given a number, split it into its mantissa and base 10 exponent
+    parts, each as strings.
+    """
+    x = "{0:.4e}".format(v).split('e')
+    if x[0] != '1.' + '0' * (len(x[0]) - 2):
+        m = x[0]
+        if '.' in m:
+            m = m.rstrip('0')
+    else:
+        m = ''
+
+    m = m.rstrip('.')
+
+    ex = x[1].lstrip("0+")
+    if len(ex) > 0 and ex[0] == '-':
+        ex = '-' + ex[1:].lstrip('0')
+
+    return m, ex
+
+
+def decompose_to_known_units(unit, func):
+    """
+    Partially decomposes a unit so it is only composed of units that
+    are "known" to a given format.
+
+    Parameters
+    ----------
+    unit : `astropy.units.UnitBase` instance
+
+    func : callable
+        This function will be called to determine if a given unit is "known".
+        If the unit is not known, this function should raise a `ValueError`.
+
+    Returns
+    -------
+    unit : `astropy.units.UnitBase` instance
+        A flattened unit.
+    """
+    from .. import core
+    if isinstance(unit, core.CompositeUnit):
+        new_unit = core.Unit(unit.scale)
+        for base, power in zip(unit.bases, unit.powers):
+            new_unit = new_unit * decompose_to_known_units(base, func) ** power
+        return new_unit
+    elif isinstance(unit, core.NamedUnit):
+        try:
+            func(unit)
+        except ValueError:
+            if isinstance(unit, core.Unit):
+                return decompose_to_known_units(unit._represents, func)
+            raise
+        return unit
+
+
+DEBUG = False
+
+
+def _trace(func):
+    """
+    A utility decorator to help debug the parser.
+    """
+    def run(self, s, loc, toks):
+        print(func.__name__, toks, end=' ')
+        try:
+            result = func(self, s, loc, toks)
+        except Exception as e:
+            print("Exception: ", e.message)
+            raise
+        print(result)
+        return result
+
+    if DEBUG:
+        return functools.update_wrapper(run, func)
+    else:
+        return func
+
+
+def cleanup_pyparsing_error(e):
+    """
+    Given a pyparsing.ParseException, returns a string that has the
+    line and column numbers removed.
+    """
+    return re.sub(", \(line:[0-9]+, col:[0-9]+\)", "", str(e))
diff --git a/astropy/units/format/vounit.py b/astropy/units/format/vounit.py
new file mode 100644
index 0000000..9b5bce6
--- /dev/null
+++ b/astropy/units/format/vounit.py
@@ -0,0 +1,123 @@
+# Licensed under a 3-clause BSD style license - see LICENSE.rst
+"""
+Handles the "VOUnit" unit format.
+"""
+from __future__ import absolute_import, division, print_function, unicode_literals
+
+import warnings
+
+from . import generic
+from . import utils
+
+
+class VOUnit(generic.Generic):
+    """
+    The proposed IVOA standard for units used by the VO.
+
+    This is an implementation of `proposed IVOA standard for units
+    <http://www.ivoa.net/Documents/VOUnits/>`_.
+    """
+    def __init__(self):
+        if not '_units' in VOUnit.__dict__:
+            VOUnit._units, VOUnit._deprecated_units = \
+              VOUnit._generate_unit_names()
+
+        if not '_parser' in VOUnit.__dict__:
+            VOUnit._parser = self._make_parser()
+
+    @staticmethod
+    def _generate_unit_names():
+        from ... import units as u
+        names = {}
+        deprecated_names = set()
+
+        bases = ['m', 's', 'A', 'K', 'mol', 'cd', 'g', 'rad', 'sr',
+                'Hz', 'N', 'Pa', 'J', 'W', 'C', 'V', 'S', 'F',
+                'Wb', 'T', 'H', 'lm', 'lx', 'Ohm']
+        prefixes = [
+            'y', 'z', 'a', 'f', 'p', 'n', 'u', 'm', 'c', 'd',
+            '', 'da', 'h', 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y']
+
+        for base in bases:
+            for prefix in prefixes:
+                key = prefix + base
+                names[key] = getattr(u, key)
+
+        simple_units = ['min', 'h', 'd',
+            'a', 'yr', 'deg', 'arcsec', 'arcmin', 'deg', 'mas', 'AU',
+            'pc', 'u', 'eV', 'Jy']
+        deprecated_units = ['angstrom', 'Angstrom',
+            'barn', 'erg', 'G', 'mag', 'solMass', 'solLum', 'solRad',
+            'lyr', 'ct', 'count', 'photon', 'ph', 'R', 'pix',
+            'pixel', 'D', 'Sun', 'chan', 'bin', 'voxel', 'bit',
+            'byte', 'adu', 'beam']
+
+        for unit in simple_units + deprecated_units:
+            names[unit] = getattr(u, unit)
+        for unit in deprecated_units:
+            deprecated_names.add(unit)
+
+        return names, deprecated_names
+
+    @classmethod
+    def _parse_unit(cls, s, loc, toks):
+        from astropy.extern import pyparsing as p
+
+        unit = toks[0]
+
+        if unit not in cls._units:
+            raise p.ParseException(
+                "Unit {0!r} not supported by the VOUnit "
+                "standard.".format(unit))
+
+        if unit in cls._deprecated_units:
+            warnings.warn(
+                "The use of unit {0!r} is discouraged by the "
+                "VOUnit standard.".format(unit),
+                DeprecationWarning)
+
+        return cls._units[unit]
+
+    def _get_unit_name(self, unit):
+        name = unit.get_format_name('vounit')
+
+        if name not in self._units:
+            raise ValueError(
+                "Unit {0!r} is not part of the VOUnit standard".format(name))
+
+        if name in self._deprecated_units:
+            warnings.warn(
+                "The use of unit {0!r} is discouraged by the "
+                "VOUnit standard.".format(name),
+                DeprecationWarning)
+
+        return name
+
+    def to_string(self, unit):
+        from .. import core
+
+        # Remove units that aren't known to the format
+        unit = utils.decompose_to_known_units(unit, self._get_unit_name)
+
+        if isinstance(unit, core.CompositeUnit):
+            s = ''
+            if unit.scale != 1:
+                m, ex = utils.split_mantissa_exponent(unit.scale)
+                if m:
+                    s += m + ' '
+                if ex:
+                    s += ' 10'
+                    if not ex.startswith('-'):
+                        s += '+'
+                    s += ex
+            else:
+                s = ''
+
+            pairs = zip(unit.bases, unit.powers)
+            pairs.sort(key=lambda x: x[1], reverse=True)
+
+            s += self._format_unit_list(pairs)
+        elif isinstance(unit, core.NamedUnit):
+            s = self._get_unit_name(unit)
+
+        return s
diff --git a/astropy/units/imperial.py b/astropy/units/imperial.py
new file mode 100644
index 0000000..ba9c666
--- /dev/null
+++ b/astropy/units/imperial.py
@@ -0,0 +1,100 @@
+# -*- coding: utf-8 -*-
+# Licensed under a 3-clause BSD style license - see LICENSE.rst
+"""
+This package defines colloquially used Imperial units.  They are also
+available in the `astropy.units` namespace.
+
+"""
+from __future__ import absolute_import, division, print_function, unicode_literals
+
+from .core import UnitBase, def_unit
+from . import si
+
+UnitBase._set_namespace(globals())
+
+###########################################################################
+# LENGTH
+
+def_unit(['inch'], 2.54 * si.cm, register=True,
+         doc="International inch")
+def_unit(['ft', 'foot'], 12 * inch, register=True,
+         doc="International foot")
+def_unit(['yd', 'yard'], 3 * ft, register=True,
+         doc="International yard")
+def_unit(['mi', 'mile'], 5280 * ft, register=True,
+         doc="International mile")
+
+
+###########################################################################
+# AREAS
+
+def_unit(['ac', 'acre'], 43560 * ft ** 2, register=True,
+         doc="International acre")
+
+
+###########################################################################
+# VOLUMES
+
+def_unit(['gallon'], si.liter / 0.264172052, register=True,
+         doc="U.S. liquid gallon")
+def_unit(['quart'], gallon / 4, register=True,
+         doc="U.S. liquid quart")
+def_unit(['pint'], quart / 2, register=True,
+         doc="U.S. liquid pint")
+def_unit(['cup'], pint / 2, register=True,
+         doc="U.S. customary cup")
+def_unit(['foz', 'fluid_oz', 'fluid_ounce'], cup / 8, register=True,
+         doc="U.S. fluid ounce")
+def_unit(['tbsp', 'tablespoon'], foz / 2, register=True,
+         doc="U.S. customary tablespoon")
+def_unit(['tsp', 'teaspoon'], tbsp / 3, register=True,
+         doc="U.S. customary teaspoon")
+
+
+###########################################################################
+# MASS
+
+# Imperial measurements
+# well, force actually, but who uses it that way?
+def_unit(['oz', 'ounce'], 28.349523125 * si.g, register=True,
+         doc="International avoirdupois ounce")
+def_unit(['lb', 'pound'], 16 * oz, register=True,
+         doc="International avoirdupois pound")
+def_unit(['ton'], 2000 * lb, register=True,
+         doc="International avoirdupois ton")
+
+
+##########################################################################
+# ENERGY
+
+def_unit(['BTU', 'btu'], 1.05505585 * si.kJ, register=True,
+         doc="British thermal unit")
+def_unit(['cal', 'calorie'], 4.184 * si.J, register=True,
+         doc="Thermochemical calorie: pre-SI metric unit of energy")
+def_unit(['kcal', 'Cal', 'Calorie', 'kilocal', 'kilocalorie'],
+         1000 * cal, register=True,
+         doc="Calorie: colloquial definition of Calorie")
+
+
+###########################################################################
+# POWER
+
+# Imperial units
+def_unit(['hp', 'horsepower'], si.W / 0.00134102209, register=True,
+         doc="Electrical horsepower")
+
+
+###########################################################################
+# CLEANUP
+
+del UnitBase
+del def_unit
+
+
+###########################################################################
+# DOCSTRING
+
+# This generates a docstring for this module that describes all of the
+# standard units defined here.
+from .utils import generate_unit_summary as _generate_unit_summary
+__doc__ += _generate_unit_summary(globals())
diff --git a/astropy/units/physical.py b/astropy/units/physical.py
new file mode 100644
index 0000000..aa7500d
--- /dev/null
+++ b/astropy/units/physical.py
@@ -0,0 +1,120 @@
+# -*- coding: utf-8 -*-
+# Licensed under a 3-clause BSD style license - see LICENSE.rst
+"""
+Defines physical unit names.
+
+This module is not intended for use by user code directly.  Instead,
+the physical unit name of a `Unit` can be obtained using its `ptype`
+property.
+"""
+from __future__ import absolute_import, division, print_function, unicode_literals
+
+from . import si
+from . import astrophys
+
+
+__all__ = ['def_physical_type', 'get_physical_type']
+
+
+_physical_unit_mapping = {}
+
+
+def _tuple_repr(unit):
+    """
+    Creates a canonical representation of a (possibly compound)
+    unit that can be used as a dictionary key.  This makes looking
+    up other units with the same signature easy.
+
+    Parameters
+    ----------
+    unit : `~astropy.units.UnitBase` instance
+        The unit to create a tuple for.
+
+    Returns
+    -------
+    canonical : tuple
+        A canonical, hashable representation of the unit.
+    """
+    unit = unit.decompose()
+    r = zip([unicode(x) for x in unit.bases], unit.powers)
+    r.sort()
+    r = tuple(r)
+    return r
+
+
+def def_physical_type(unit, name):
+    """
+    Adds a new physical unit mapping.
+
+    Parameters
+    ----------
+    unit : `~astropy.units.UnitBase` instance
+        The unit to map from.
+
+    name : str
+        The physical name of the unit.
+    """
+    r = _tuple_repr(unit)
+    if r in _physical_unit_mapping:
+        raise ValueError(
+            "{0!r} already defined as {1!r}".format(
+                r, _physical_unit_mapping[r]))
+    _physical_unit_mapping[r] = name
+
+
+def get_physical_type(unit):
+    """
+    Given a unit, returns the name of the physical quantity it
+    represents.  If it represents an unknown physical quantity,
+    ``"unknown"`` is returned.
+
+    Parameters
+    ----------
+    unit : `~astropy.units.UnitBase` instance
+        The unit to lookup
+
+    Returns
+    -------
+    physical : str
+        The name of the physical quantity, or unknown if not
+        known.
+    """
+    r = _tuple_repr(unit)
+    return _physical_unit_mapping.get(r, 'unknown')
+
+
+for unit, name in [
+    (si.m, 'length'),
+    (si.m ** 2, 'area'),
+    (si.m ** 3, 'volume'),
+    (si.rad, 'angle'),
+    (si.sr, 'solid angle'),
+    (si.m / si.s, 'speed'),
+    (si.m / si.s ** 2, 'acceleration'),
+    (si.Hz, 'frequency'),
+    (si.g, 'mass'),
+    (si.mol, 'amount of substance'),
+    (si.K, 'temperature'),
+    (si.N, 'force'),
+    (si.J, 'energy'),
+    (si.Pa, 'pressure'),
+    (si.W, 'power'),
+    (si.g / (si.m * si.s), 'dynamic viscosity'),
+    (si.m ** 2 / si.s, 'kinematic viscosity'),
+    (si.m ** -1, 'wavenumber'),
+    (si.C, 'electrical charge'),
+    (si.V, 'electrical potential'),
+    (si.Ohm, 'electrical resistance'),
+    (si.S, 'electrical conductance'),
+    (si.F, 'electrical capacitance'),
+    (si.C * si.m, 'electrical dipole moment'),
+    (si.Wb, 'magnetic flux'),
+    (si.T, 'magnetic flux density'),
+    (si.H, 'inductance'),
+    (si.cd, 'luminous intensity'),
+    (si.lm, 'luminous flux'),
+    (si.lx, 'luminous emittence'),
+    (astrophys.Jy, 'spectral flux density'),
+    (astrophys.R, 'photon flux'),
+    ]:
+    def_physical_type(unit, name)
diff --git a/astropy/units/quantity.py b/astropy/units/quantity.py
new file mode 100644
index 0000000..e8f38a0
--- /dev/null
+++ b/astropy/units/quantity.py
@@ -0,0 +1,420 @@
+# coding: utf-8
+# Licensed under a 3-clause BSD style license - see LICENSE.rst
+"""
+This module defines the `Quantity` object, which represents a number with some associated
+units. `Quantity` objects support operations like ordinary numbers, but will deal with
+unit conversions internally.
+"""
+
+from __future__ import absolute_import, unicode_literals, division, print_function
+
+# Standard library
+import copy
+import numbers
+
+import numpy as np
+
+# AstroPy
+from .core import Unit, UnitBase, IrreducibleUnit, CompositeUnit
+
+__all__ = ["Quantity"]
+
+
+def _validate_value(value):
+    """ Make sure that the input is a Python numeric type.
+
+    Parameters
+    ----------
+    value : number
+        An object that will be checked whether it is a numeric type or not.
+
+    Returns
+    -------
+    newval
+        The new value either as an array or a scalar
+    """
+    from ..utils.misc import isiterable
+
+    if isinstance(value, numbers.Number):
+        value_obj = value
+    elif isiterable(value):
+        value_obj = np.array(value, copy=True)
+    elif isinstance(value, np.ndarray):
+        # A length-0 numpy array (i.e. numpy scalar) which we accept as-is
+        value_obj = np.array(value, copy=True)
+    else:
+        raise TypeError("The value must be a valid Python numeric type.")
+
+    return value_obj
+
+
+class Quantity(object):
+    """ A `Quantity` represents a number with some associated unit.
+
+    Parameters
+    ----------
+    value : number
+        The numerical value of this quantity in the units given by unit.
+    unit : `~astropy.units.UnitBase` instance, str
+        An object that represents the unit associated with the input value. Must be an `~astropy.units.UnitBase`
+        object or a string parseable by the `units` package.
+
+    Raises
+    ------
+    TypeError
+        If the value provided is not a Python numeric type.
+    TypeError
+        If the unit provided is not either a `Unit` object or a parseable string unit.
+    """
+
+    def __init__(self, value, unit):
+        self._value = _validate_value(value)
+        self._unit = Unit(unit)
+
+    def to(self, unit):
+        """ Returns a new `Quantity` object with the specified units.
+
+        Parameters
+        ----------
+        unit : `~astropy.units.UnitBase` instance, str
+            An object that represents the unit to convert to. Must be an `~astropy.units.UnitBase`
+            object or a string parseable by the `units` package.
+        """
+        new_val = self.unit.to(unit, self.value)
+        new_unit = Unit(unit)
+        return Quantity(new_val, new_unit)
+
+    @property
+    def value(self):
+        """ The numerical value of this quantity. """
+        return self._value
+
+    @value.setter
+    def value(self, obj):
+        """ Setter for the value attribute. We allow the user to change the value by setting this attribute,
+        so this will validate the new object.
+
+        Parameters
+        ----------
+        obj : number
+            The numerical value of this quantity in the same units as stored internally.
+
+        Raises
+        ------
+        TypeError
+            If the value provided is not a Python numeric type.
+        """
+        self._value = _validate_value(obj)
+
+    @property
+    def unit(self):
+        """ A `~astropy.units.UnitBase` object representing the unit of this quantity. """
+        return self._unit
+
+    @property
+    def si(self):
+        """ Returns a copy of the current `Quantity` instance with SI units. The value of the
+            resulting object will be scaled.
+        """
+
+        from . import si as _si
+        si_unit_set = set([ss for ss in _si.__dict__.values() if isinstance(ss, IrreducibleUnit)])
+        si_quantity_value = self.value
+
+        if isinstance(self.unit, CompositeUnit):
+            si_quantity_bases = []
+            si_quantity_powers = []
+
+            for base_unit, power in zip(self.unit.bases, self.unit.powers):
+                is_si = True
+                for si_unit in si_unit_set:
+                    if base_unit.is_equivalent(si_unit) and base_unit != si_unit:
+                        scale = (base_unit / si_unit).dimensionless_constant() ** power
+                        si_quantity_value *= scale
+                        is_si = False
+                        si_quantity_bases.append(si_unit)
+                        si_quantity_powers.append(power)
+                        break
+
+                if is_si:
+                    si_quantity_bases.append(base_unit)
+                    si_quantity_powers.append(power)
+
+            return Quantity(si_quantity_value, CompositeUnit(1., si_quantity_bases, si_quantity_powers).simplify())
+        else:
+            for si_unit in si_unit_set:
+                if self.unit.is_equivalent(si_unit) and self.unit != si_unit:
+                    # Don't have to worry about power here because if it has a power, it's a CompositeUnit
+                    scale = (self.unit / si_unit).dimensionless_constant()
+                    si_quantity_value *= scale
+
+                    return Quantity(si_quantity_value, si_unit)
+
+            return self.copy()
+
+    @property
+    def cgs(self):
+        """ Returns a copy of the current `Quantity` instance with CGS units. The value of the
+            resulting object will be scaled.
+        """
+
+
+        from . import cgs as _cgs
+        si_quantity = self.si
+        cgs_quantity_value = si_quantity.value
+
+        if isinstance(si_quantity.unit, CompositeUnit):
+            cgs_quantity_bases = []
+            cgs_quantity_powers = []
+
+            for base_unit, power in zip(si_quantity.unit.bases, si_quantity.unit.powers):
+                if base_unit in _cgs._cgs_bases.keys():
+                    scale = (base_unit / _cgs._cgs_bases[base_unit]).dimensionless_constant() ** power
+                    cgs_quantity_value *= scale
+                    cgs_quantity_bases.append(_cgs._cgs_bases[base_unit])
+                    cgs_quantity_powers.append(power)
+                else:
+                    cgs_quantity_bases.append(base_unit)
+                    cgs_quantity_powers.append(power)
+
+            return Quantity(cgs_quantity_value, CompositeUnit(1., cgs_quantity_bases, cgs_quantity_powers).simplify())
+        else:
+            if si_quantity.unit in _cgs._cgs_bases.keys():
+                # Don't have to worry about power here because if it has a power, it's a CompositeUnit
+                scale = (si_quantity.unit / _cgs._cgs_bases[si_quantity.unit]).dimensionless_constant()
+                cgs_quantity_value *= scale
+
+                return Quantity(cgs_quantity_value, _cgs._cgs_bases[si_quantity.unit])
+            else:
+                return Quantity(si_quantity.value, si_quantity.unit)
+
+    @property
+    def isscalar(self):
+        """
+        True if the `value` of this quantity is a scalar, or False if it
+        is an array-like object.
+
+        .. note::
+            This is subtly different from `numpy.isscalar` in that
+            `numpy.isscalar` returns False for a zero-dimensional array
+            (e.g. ``np.array(1)``), while this is True in that case.
+        """
+        from ..utils.misc import isiterable
+
+        return not isiterable(self.value)
+
+    def copy(self):
+        """ Return a copy of this `Quantity` instance """
+        return Quantity(self.value, unit=self.unit)
+
+    # Arithmetic operations
+    def __add__(self, other):
+        """ Addition between `Quantity` objects and other objects.  If
+        they are both `Quantity` objects, results in the units of the
+        **left** object if they are compatible, otherwise this fails.
+        """
+        if isinstance(other, Quantity):
+            return Quantity(self.value + other.to(self.unit).value, unit=self.unit)
+        else:
+            raise TypeError("Object of type '{0}' cannot be added with a "
+                "Quantity object. Addition is only supported between Quantity "
+                "objects with compatible units.".format(other.__class__))
+
+    def __sub__(self, other):
+        """ Subtraction between `Quantity` objects and other objects.
+        If they are both `Quantity` objects, results in the units of the
+        **left** object if they are compatible, otherwise this fails.
+        """
+        if isinstance(other, Quantity):
+            return Quantity(self.value - other.to(self.unit).value, unit=self.unit)
+        else:
+            raise TypeError("Object of type '{0}' cannot be added with a "
+                "Quantity object. Addition is only supported between Quantity "
+                "objects with compatible units.".format(other.__class__))
+
+    def __mul__(self, other):
+        """ Multiplication between `Quantity` objects and other objects.
+        """
+        if isinstance(other, Quantity):
+            return Quantity(self.value * other.value, unit=self.unit * other.unit)
+        elif isinstance(other, UnitBase):
+            return Quantity(self.value, unit=other * self.unit)
+        else:
+            try:
+                return Quantity(other * self.value, unit=self.unit)
+            except TypeError:
+                raise TypeError("Object of type '{0}' cannot be multiplied with a Quantity object.".format(other.__class__))
+
+    def __rmul__(self, other):
+        """ Right Multiplication between `Quantity` objects and other
+        objects.
+        """
+        return self.__mul__(other)
+
+    def __div__(self, other):
+        """ Division between `Quantity` objects and other objects.
+        """
+        if isinstance(other, Quantity):
+            return Quantity(self.value / other.value, unit=self.unit / other.unit)
+        elif isinstance(other, UnitBase):
+            return Quantity(self.value, unit=self.unit / other)
+        elif isinstance(other, numbers.Number) and hasattr(self.unit, "bases"):
+            new_unit_bases = copy.copy(self.unit.bases)
+            new_unit_powers = [-p for p in self.unit.powers]
+            return Quantity(other / self.value, unit=CompositeUnit(1., new_unit_bases, new_unit_powers))
+        else:
+            try:
+                return Quantity(self.value / other, unit=self.unit)
+            except TypeError:
+                raise TypeError("Object of type '{0}' cannot be diveded with a Quantity object.".format(other.__class__))
+
+    def __rdiv__(self, other):
+        """ Right Division between `Quantity` objects and other objects.
+        """
+        if isinstance(other, Quantity):
+            return Quantity(other.value / self.value, unit=other.unit / self.unit)
+        elif isinstance(other, UnitBase):
+            return Quantity(1. / self.value, unit=other / self.unit)
+        else:
+            try:
+                return Quantity(other / self.value, unit=1. / self.unit)
+            except TypeError:
+                raise TypeError("Object of type '{0}' cannot be diveded with a Quantity object.".format(other.__class__))
+
+    def __truediv__(self, other):
+        """ Division between `Quantity` objects. """
+        return self.__div__(other)
+
+    def __rtruediv__(self, other):
+        """ Division between `Quantity` objects. """
+        return self.__rdiv__(other)
+
+    def __pow__(self, p):
+        """ Raise `Quantity` object to a power. """
+        if hasattr(p, 'unit'):
+            raise TypeError('Cannot raise a Quantity object to a power of something with a unit')
+        return Quantity(self.value ** p, unit=self.unit ** p)
+
+    # Comparison operations
+    def __eq__(self, other):
+        if hasattr(other, 'value') and hasattr(other, 'to'):
+            return self.value == other.to(self.unit).value
+        else:
+            return False
+
+    def __ne__(self, other):
+        if hasattr(other, 'value') and hasattr(other, 'to'):
+            return self.value != other.to(self.unit).value
+        else:
+            return True
+
+    def __lt__(self, other):
+        if isinstance(other, Quantity):
+            return self.value < other.to(self.unit).value
+        else:
+            raise TypeError("Quantity object cannot be compared to an object of type {0}".format(other.__class__))
+
+    def __le__(self, other):
+        if isinstance(other, Quantity):
+            return self.value <= other.to(self.unit).value
+        else:
+            raise TypeError("Quantity object cannot be compared to an object of type {0}".format(other.__class__))
+
+    def __gt__(self, other):
+        if isinstance(other, Quantity):
+            return self.value > other.to(self.unit).value
+        else:
+            raise TypeError("Quantity object cannot be compared to an object of type {0}".format(other.__class__))
+
+    def __ge__(self, other):
+        if isinstance(other, Quantity):
+            return self.value >= other.to(self.unit).value
+        else:
+            raise TypeError("Quantity object cannot be compared to an object of type {0}".format(other.__class__))
+
+    #other overrides of special functions
+    def __hash__(self):
+        return hash(self.value) ^ hash(self.unit)
+
+    def __getitem__(self, key):
+        if self.isscalar:
+            raise TypeError("'{cls}' object with a scalar value does not support indexing".format(cls=self.__class__.__name__))
+        else:
+            return Quantity(self.value[key], unit=self.unit)
+
+    def __len__(self):
+        if self.isscalar:
+            raise TypeError("'{cls}' object with a scalar value has no len()".format(cls=self.__class__.__name__))
+        else:
+            return len(self.value)
+
+    # Display
+    # TODO: we may want to add a hook for dimensionless quantities?
+    def __str__(self):
+        return "{0} {1:s}".format(self.value, self.unit.to_string())
+
+    def __repr__(self):
+        return "<Quantity {0} {1:s}>".format(self.value, self.unit.to_string())
+
+    def _repr_latex_(self):
+        """
+        Generate latex representation of unit name.  This is used by
+        the IPython notebook to show it all latexified.
+
+        Returns
+        -------
+        lstr
+            LaTeX string
+        """
+
+        # Format value
+        latex_value = "{0:g}".format(self.value)
+        if "e" in latex_value:
+            latex_value = latex_value.replace('e', '\\times 10^{') + '}'
+
+        # Format unit
+        # [1:-1] strips the '$' on either side needed for math mode
+        latex_unit = self.unit._repr_latex_()[1:-1]  # note this is unicode
+
+        return u'${0} \; {1}$'.format(latex_value, latex_unit)
+
+    @property
+    def decomposed_unit(self):
+        """
+        Generates a new `Quantity` with the units decomposed. Decomposed
+        units have only irreducible units in them (see
+        `astropy.units.UnitBase.decompose`).
+
+        Returns
+        -------
+        newq : `~astropy.units.quantity.Quantity`
+            A new object equal to this quantity with units decomposed.
+        """
+        return self._decomposed_unit(False)
+
+    def _decomposed_unit(self, allowscaledunits=False):
+        """
+        Generates a new `Quantity` with the units decomposed. Decomposed
+        units have only irreducible units in them (see
+        `astropy.units.UnitBase.decompose`).
+
+        Parameters
+        ----------
+        allowscaledunits : bool
+            If True, the resulting `Quantity` may have a scale factor
+            associated with it.  If False, any scaling in the unit will
+            be subsumed into the value of the resulting `Quantity`
+
+        Returns
+        -------
+        newq : `~astropy.units.quantity.Quantity`
+            A new object equal to this quantity with units decomposed.
+
+        """
+        newu = self.unit.decompose()
+        newval = self.value
+        if not allowscaledunits and hasattr(newu, 'scale'):
+            newval *= newu.scale
+            newu = newu / Unit(newu.scale)
+
+        return Quantity(newval, newu)
diff --git a/astropy/units/si.py b/astropy/units/si.py
new file mode 100644
index 0000000..e1bf0ea
--- /dev/null
+++ b/astropy/units/si.py
@@ -0,0 +1,219 @@
+# -*- coding: utf-8 -*-
+# Licensed under a 3-clause BSD style license - see LICENSE.rst
+"""
+This package defines the SI units.  They are also available in the
+`astropy.units` namespace.
+
+"""
+from __future__ import absolute_import, division, print_function, unicode_literals
+
+from .._constants import si as _si
+from .core import UnitBase, def_unit
+
+import numpy as _numpy
+
+UnitBase._set_namespace(globals())
+
+###########################################################################
+# LENGTH
+
+def_unit(['m', 'meter'], register=True, prefixes=True,
+         doc="meter: base unit of length in SI")
+
+def_unit(['micron'], um, register=True,
+         doc="micron: alias for micrometer (um)",
+         format={'latex': r'\mu', 'unicode': 'μ'})
+
+def_unit(['Angstrom', 'AA', 'angstrom'], 0.1 * nm, register=True,
+         doc="ångström: 10 ** -10 m",
+         format={'latex': r'\AA', 'unicode': 'Ã…', 'vounit': 'angstrom'})
+
+
+###########################################################################
+# VOLUMES
+
+def_unit(['l', 'L', 'liter'], 1000 * cm ** 3, register=True, prefixes=True,
+         doc="liter: metric unit of volume")
+
+
+###########################################################################
+# ANGULAR MEASUREMENTS
+
+def_unit(['rad', 'radian'], register=True, prefixes=True,
+         doc="radian: angular measurement of the ratio between the length "
+         "on an arc and its radius")
+def_unit(['deg', 'degree'], _numpy.pi / 180.0 * rad, register=True,
+         doc="degree: angular measurement 1/360 of full rotation",
+         format={'latex': r'{}^{\circ}', 'unicode': '°'})
+def_unit(['arcmin', 'arcminute'], 1.0 / 60.0 * deg, register=True,
+         doc="arc minute: angular measurement",
+         format={'latex': r'\prime', 'unicode': '′'})
+def_unit(['arcsec', 'arcsecond'], 1.0 / 3600.0 * deg, register=True,
+         doc="arc second: angular measurement",
+         format={'latex': r'\second', 'unicode': '″'})
+def_unit(['mas'], 1.0 / 3600000 * deg, register=True,
+         doc="milliarc second: angular measurement",
+         format={'latex': r'\third', 'unicode': '‴'})
+
+def_unit(['sr', 'steradian'], register=True, prefixes=True,
+         doc="steradian: base unit of solid angle in SI")
+
+
+###########################################################################
+# TIME
+
+def_unit(['s', 'second'], register=True, prefixes=True,
+     doc="second: base unit of time in SI.")
+
+def_unit(['min', 'minute'], 60 * s, register=True)
+def_unit(['h', 'hour'], 3600 * s, register=True)
+def_unit(['d', 'day'], 24 * h, register=True)
+def_unit(['sday'], 86164.09053 * s, register=True,
+         doc="Sidereal day (sday) is the time of one rotation of the Earth.")
+def_unit(['wk', 'week'], 7 * day, register=True)
+def_unit(['fortnight'], 2 * wk, register=True)
+
+def_unit(['a', 'annum'], 3.1556926e7 * s, register=True,
+     prefixes=True, exclude_prefixes=['P'])
+def_unit(['yr', 'year'], 3.1556926e7 * s, register=True,
+     prefixes=True)
+
+
+
+###########################################################################
+# FREQUENCY
+
+def_unit(['Hz', 'Hertz', 'hertz'], 1 / s, register=True, prefixes=True,
+         doc="Frequency")
+
+
+###########################################################################
+# MASS
+
+def_unit(['kg', 'kilogram'], register=True,
+         doc="kilogram: base unit of mass in SI.")
+def_unit(['g', 'gram'], 1.0e-3 * kg, register=True, prefixes=True,
+         exclude_prefixes=['k'])
+
+def_unit(['t', 'tonne'], 1000 * kg, register=True,
+         doc="Metric tonne")
+
+
+###########################################################################
+# AMOUNT OF SUBSTANCE
+
+def_unit(['mol', 'mole'], register=True, prefixes=True,
+     doc="mole: amount of a chemical substance in SI.")
+
+
+###########################################################################
+# TEMPERATURE
+
+def_unit(
+    ['K', 'Kelvin'], register=True, prefixes=True,
+    doc="Kelvin: temperature with a null point at absolute zero.")
+
+
+###########################################################################
+# FORCE
+
+def_unit(['N', 'Newton', 'newton'], kg * m * s ** -2, register=True, prefixes=True,
+         doc="Newton: force")
+
+
+##########################################################################
+# ENERGY
+
+def_unit(['J', 'Joule', 'joule'], N * m, register=True, prefixes=True,
+         doc="Joule: energy")
+def_unit(['eV', 'electronvolt'], _si.e * J, register=True, prefixes=True,
+         doc="Electron Volt")
+def_unit(['Pa', 'Pascal', 'pascal'], J * m ** -3, register=True, prefixes=True,
+         doc="Pascal: pressure")
+
+
+###########################################################################
+# POWER
+
+def_unit(['W', 'Watt', 'watt'], J / s, register=True, prefixes=True,
+         doc="Watt: power")
+
+
+###########################################################################
+# ELECTRICAL
+
+def_unit(['A', 'ampere', 'amp'], register=True, prefixes=True,
+         doc="ampere: base unit of electric current in SI")
+def_unit(['C', 'coulomb'], A * s, register=True, prefixes=True,
+         doc="coulomb: electric charge")
+def_unit(['V', 'Volt', 'volt'], J * C ** -1, register=True, prefixes=True,
+         doc="Volt: electric potential or electromotive force")
+def_unit(['Ohm', 'ohm'], V * A ** -1, register=True, prefixes=True,
+         doc="Ohm: electrical resistance",
+         format={'latex': r'\Omega', 'unicode': 'Ω'})
+def_unit(['S', 'Siemens', 'siemens'], A * V ** -1, register=True, prefixes=True,
+         doc="Siemens: electrical conductance")
+def_unit(['F', 'Farad', 'farad'], C * V ** -1, register=True, prefixes=True,
+         doc="Farad: electrical capacitance")
+
+
+###########################################################################
+# MAGNETIC
+
+def_unit(['Wb', 'Weber', 'weber'], V * s, register=True, prefixes=True,
+         doc="Weber: magnetic flux")
+def_unit(['T', 'Tesla', 'tesla'], Wb * m ** -2, register=True, prefixes=True,
+         doc="Tesla: magnetic flux density")
+def_unit(['H', 'Henry', 'henry'], Wb * A ** -1, register=True, prefixes=True,
+         doc="Henry: inductance")
+
+
+###########################################################################
+# ILLUMINATION
+
+def_unit(['cd', 'candela'], register=True, prefixes=True,
+         doc="candela: base unit of luminous intensity in SI")
+def_unit(['lm', 'lumen'], cd * sr, register=True, prefixes=True,
+         doc="lumen: luminous flux")
+def_unit(['lx', 'lux'], lm * m ** -2, register=True, prefixes=True,
+         doc="lux: luminous emittence")
+
+
+###########################################################################
+# EVENTS
+
+def_unit(['ct', 'count'], register=True)
+def_unit(['ph', 'photon'], register=True)
+def_unit(['pix', 'pixel'], register=True)
+
+
+###########################################################################
+# MISCELLANEOUS
+
+# Some of these are very FITS-specific and perhaps considered a mistake.
+# Maybe they should be moved into the FITS format class?
+# TODO: This is defined by the FITS standard as "relative to the sun".
+# Is that mass, volume, what?
+def_unit(['chan'], register=True)
+def_unit(['bin'], register=True)
+def_unit(['vox', 'voxel'], register=True)
+def_unit(['bit'], register=True, prefixes=True)
+def_unit(['byte'], register=True, prefixes=True)
+def_unit(['adu'], register=True)
+def_unit(['beam'], register=True)
+
+
+###########################################################################
+# CLEANUP
+
+del UnitBase
+del def_unit
+
+
+###########################################################################
+# DOCSTRING
+
+# This generates a docstring for this module that describes all of the
+# standard units defined here.
+from .utils import generate_unit_summary as _generate_unit_summary
+__doc__ += _generate_unit_summary(globals())
diff --git a/astropy/io/vo/tests/__init__.py b/astropy/units/tests/__init__.py
similarity index 100%
rename from astropy/io/vo/tests/__init__.py
rename to astropy/units/tests/__init__.py
diff --git a/astropy/units/tests/test_format.py b/astropy/units/tests/test_format.py
new file mode 100644
index 0000000..82fa66d
--- /dev/null
+++ b/astropy/units/tests/test_format.py
@@ -0,0 +1,178 @@
+# Licensed under a 3-clause BSD style license - see LICENSE.rst
+"""
+Regression tests for the units.format package
+"""
+
+from __future__ import absolute_import, unicode_literals, division, print_function
+
+from ...tests.helper import raises
+from ...tests.compat import assert_allclose
+
+from ... import units as u
+from .. import core
+from .. import format
+from ... import wcs
+
+
+def test_unit_grammar():
+    def _test_unit_grammar(s, unit):
+        print(s)
+        unit2 = format.Generic().parse(s)
+        assert unit2 == unit
+
+    data = [
+        (["m s", "m*s", "m.s"], u.m * u.s),
+        (["m/s", "m*s**-1"], u.m / u.s),
+        (["m**2", "m2", "m**(2)", "m**+2", "m+2", "m^(+2)"], u.m ** 2),
+        (["m**-3", "m-3", "m^(-3)", "/m3"], u.m ** -3),
+        (["m**(1.5)", "m(3/2)", "m**(3/2)", "m^(3/2)"], u.m ** 1.5),
+        (["2.54cm"], u.Unit(u.cm * 2.54)),
+        (["10+8m"], u.Unit(u.m * 1e8)),
+        # # This is the VOUnits documentation, but doesn't seem to follow the unity grammar
+        # (["3.45 10**(-4)Jy"], 3.45 * 1e-4 * u.Jy) #
+        (["sqrt(m)"], u.m ** -2)
+        ]
+
+    for strings, unit in data:
+        for s in strings:
+            yield _test_unit_grammar, s, unit
+
+
+def test_cds_grammar():
+    def _test_cds_grammar(s, unit):
+        print(s)
+        unit2 = format.CDS().parse(s)
+        assert unit2 == unit
+
+    data = [
+        (["0.1nm"], u.AA),
+        (["mW/m2"], u.Unit(u.erg / u.cm ** 2 / u.s)),
+        (["km/s", "km.s-1"], u.km / u.s),
+        (["10pix/nm"], u.Unit(10 * u.pix / u.nm)),
+        (["1.5x10+11m"], u.Unit(1.5e11 * u.m)),
+        (["m2"], u.m ** 2),
+        (["10+21m"], u.Unit(u.m * 1e21)),
+        (["2.54cm"], u.Unit(u.cm * 2.54)),
+        (["20%"], 0.20)]
+
+    for strings, unit in data:
+        for s in strings:
+            yield _test_cds_grammar, s, unit
+
+
+def test_cds_grammar_fail():
+    @raises(ValueError)
+    def _test_cds_grammar_fail(s):
+        print(s)
+        format.CDS().parse(s)
+
+    data = ['0.1 nm', 'solMass(3/2)', 'km / s', 'km s-1',
+            'pix0.1nm', 'pix/(0.1nm)', 'km*s', 'km**2']
+
+    for s in data:
+        yield _test_cds_grammar_fail, s
+
+
+
+def test_roundtrip():
+    def _test_roundtrip(unit):
+        a = core.Unit(unit.to_string('generic'), format='generic')
+        b = core.Unit(unit.decompose().to_string('generic'), format='generic')
+        assert_allclose(a.decompose().scale, unit.decompose().scale, rtol=1e-2)
+        assert_allclose(b.decompose().scale, unit.decompose().scale, rtol=1e-2)
+
+    for key, val in u.__dict__.items():
+        if isinstance(val, core.Unit) and not isinstance(val, core.PrefixUnit):
+            yield _test_roundtrip, val
+
+
+def test_roundtrip_vo_unit():
+    def _test_roundtrip_vo_unit(unit):
+        a = core.Unit(unit.to_string('vounit'), format='vounit')
+        b = core.Unit(unit.decompose().to_string('vounit'), format='vounit')
+        assert_allclose(a.decompose().scale, unit.decompose().scale, rtol=1e-2)
+        assert_allclose(b.decompose().scale, unit.decompose().scale, rtol=1e-2)
+
+    x = format.VOUnit()
+    for key, val in x._units.items():
+        if isinstance(val, core.Unit) and not isinstance(val, core.PrefixUnit):
+            yield _test_roundtrip_vo_unit, val
+
+
+def test_roundtrip_fits():
+    def _test_roundtrip_fits(unit):
+        s = unit.to_string('fits')
+        a = core.Unit(s, format='fits')
+        assert_allclose(a.decompose().scale, unit.decompose().scale, rtol=1e-2)
+
+    for key, val in format.Fits()._units.items():
+        if isinstance(val, core.Unit) and not isinstance(val, core.PrefixUnit):
+            yield _test_roundtrip_fits, val
+
+
+def test_roundtrip_cds():
+    def _test_roundtrip_cds(unit):
+        a = core.Unit(unit.to_string('cds'), format='cds')
+        b = core.Unit(unit.decompose().to_string('cds'), format='cds')
+        assert_allclose(a.decompose().scale, unit.decompose().scale, rtol=1e-2)
+        assert_allclose(b.decompose().scale, unit.decompose().scale, rtol=1e-2)
+
+    x = format.CDS()
+    for key, val in x._units.items():
+        if isinstance(val, core.Unit) and not isinstance(val, core.PrefixUnit):
+            yield _test_roundtrip_cds, val
+
+
+def test_fits_units_available():
+    format.Fits()
+
+
+def test_vo_units_available():
+    format.VOUnit()
+
+
+def test_cds_units_available():
+    format.CDS()
+
+
+def test_latex():
+    fluxunit = u.erg / (u.cm ** 2 * u.s)
+    assert fluxunit.to_string('latex') == r'$\mathrm{\frac{erg}{s\ cm^{2}}}$'
+
+
+def test_wcs_parse():
+    """
+    Tests that the output of to_string('fits') is also parsed by
+    wcslib.  Even if we deprecated access to wcslib's unit parser, we
+    may want to keep it around and hidden for this test.
+    """
+    def _test_wcs_parse(unit):
+        try:
+            fits_string = unit.decompose().to_string('fits')
+        except ValueError:
+            return
+        wcs.UnitConverter(fits_string, fits_string)
+
+    for key, val in u.__dict__.items():
+        if isinstance(val, core.Unit) and not isinstance(val, core.PrefixUnit):
+            yield _test_wcs_parse, val
+
+
+def test_flatten_to_known():
+    myunit = u.def_unit("FOOBAR", u.erg / u.Hz)
+    assert myunit.to_string('fits') == 'erg Hz-1'
+    myunit2 = myunit * u.bit ** 3
+    assert myunit2.to_string('fits') == 'bit3 erg Hz-1'
+
+
+ at raises(ValueError)
+def test_flatten_impossible():
+    myunit = u.def_unit("FOOBAR")
+    myunit.to_string('fits')
+
+
+def test_console_out():
+    """
+    Issue #436.
+    """
+    u.Jy.decompose().to_string('console')
diff --git a/astropy/units/tests/test_physical.py b/astropy/units/tests/test_physical.py
new file mode 100644
index 0000000..8a9e161
--- /dev/null
+++ b/astropy/units/tests/test_physical.py
@@ -0,0 +1,24 @@
+# Licensed under a 3-clause BSD style license - see LICENSE.rst
+"""
+Regression tests for the physical_type support in the units package
+"""
+from __future__ import absolute_import, unicode_literals, division, print_function
+
+
+from ... import units as u
+
+
+def test_simple():
+    assert u.mile.physical_type == 'length'
+
+
+def test_power():
+    assert (u.foot ** 3).physical_type == 'volume'
+
+
+def test_speed():
+    assert (u.mile / u.h).physical_type == 'speed'
+
+
+def test_unknown():
+    assert (u.m * u.s).physical_type == 'unknown'
diff --git a/astropy/units/tests/test_quantity.py b/astropy/units/tests/test_quantity.py
new file mode 100644
index 0000000..52cc9bd
--- /dev/null
+++ b/astropy/units/tests/test_quantity.py
@@ -0,0 +1,348 @@
+# coding: utf-8
+# Licensed under a 3-clause BSD style license - see LICENSE.rst
+"""
+    Test the Quantity class and related.
+"""
+
+from __future__ import absolute_import, unicode_literals, division, print_function
+
+import pytest
+import numpy as np
+
+from ...tests.helper import raises
+from ...tests.compat import assert_allclose
+from ... import units as u
+
+""" The Quantity class will represent a number + unit + uncertainty """
+
+class TestQuantityCreation():
+
+    def test_1(self):
+        # create objects through operations with Unit objects:
+
+        quantity = 11.42 * u.meter # returns a Quantity object
+        assert isinstance(quantity,u.Quantity)
+        quantity = u.meter * 11.42 # returns a Quantity object
+        assert isinstance(quantity,u.Quantity)
+
+        quantity = 11.42 / u.meter
+        assert isinstance(quantity,u.Quantity)
+        quantity = u.meter / 11.42
+        assert isinstance(quantity,u.Quantity)
+
+        quantity = 11.42 * u.meter / u.second
+        assert isinstance(quantity,u.Quantity)
+
+        with pytest.raises(TypeError):
+            quantity = 182.234 + u.meter
+
+        with pytest.raises(TypeError):
+            quantity = 182.234 - u.meter
+
+        with pytest.raises(TypeError):
+            quantity = 182.234 % u.meter
+
+    def test_2(self):
+        # create objects using the Quantity constructor:
+        q1 = u.Quantity(11.412, unit=u.meter)
+        q2 = u.Quantity(21.52, "cm")
+
+        with pytest.raises(TypeError):
+            q3 = u.Quantity(11.412)
+
+    def test_3(self):
+        #with pytest.raises(u.UnitsException):
+        with pytest.raises(ValueError): # Until @mdboom fixes the errors in units
+            q1 = u.Quantity(11.412, unit="testingggg")
+
+    def test_unit_property(self):
+        # test getting and setting 'unit' attribute
+        q1 = u.Quantity(11.4, unit=u.meter)
+
+        with pytest.raises(AttributeError):
+            q1.unit = u.centimeter
+
+class TestQuantityOperations():
+    q1 = u.Quantity(11.42, u.meter)
+    q2 = u.Quantity(8.0, u.centimeter)
+
+    def test_addition(self):
+        # Take units from left object, q1
+        new_quantity = self.q1 + self.q2
+        assert new_quantity.value == 11.5
+        assert new_quantity.unit == u.meter
+
+        # Take units from left object, q2
+        new_quantity = self.q2 + self.q1
+        assert new_quantity.value == 1150.0
+        assert new_quantity.unit == u.centimeter
+
+        new_q = u.Quantity(1500.1,u.m) + u.Quantity(13.5,u.km)
+        assert new_q.unit == u.m
+        assert new_q.value == 15000.1
+
+    def test_subtraction(self):
+        # Take units from left object, q1
+        new_quantity = self.q1 - self.q2
+        assert new_quantity.value == 11.34
+        assert new_quantity.unit == u.meter
+
+        # Take units from left object, q2
+        new_quantity = self.q2 - self.q1
+        assert new_quantity.value == -1134.0
+        assert new_quantity.unit == u.centimeter
+
+    def test_multiplication(self):
+        # Take units from left object, q1
+        new_quantity = self.q1 * self.q2
+        assert new_quantity.value == 91.36
+        assert new_quantity.unit == (u.meter*u.centimeter)
+
+        # Take units from left object, q2
+        new_quantity = self.q2 * self.q1
+        assert new_quantity.value == 91.36
+        assert new_quantity.unit == (u.centimeter*u.meter)
+
+        # Multiply with a number
+        new_quantity = 15. * self.q1
+        assert new_quantity.value == 171.3
+        assert new_quantity.unit == u.meter
+
+        # Multiply with a number
+        new_quantity = self.q1 * 15.
+        assert new_quantity.value == 171.3
+        assert new_quantity.unit == u.meter
+
+    def test_division(self):
+        # Take units from left object, q1
+        new_quantity = self.q1 / self.q2
+        np.testing.assert_array_almost_equal(new_quantity.value, 1.4275, decimal=5)
+        assert new_quantity.unit == (u.meter / u.centimeter)
+
+        # Take units from left object, q2
+        new_quantity = self.q2 / self.q1
+        np.testing.assert_array_almost_equal(new_quantity.value, 0.70052539404553416, decimal=16)
+        assert new_quantity.unit == (u.centimeter / u.meter)
+
+        q1 = u.Quantity(11.4, unit=u.meter)
+        q2 = u.Quantity(10.0, unit=u.second)
+        new_quantity = q1 / q2
+        np.testing.assert_array_almost_equal(new_quantity.value, 1.14, decimal=10)
+        assert new_quantity.unit == (u.meter / u.second)
+
+        # divide with a number
+        new_quantity = self.q1 / 10.
+        assert new_quantity.value == 1.142
+        assert new_quantity.unit == u.meter
+
+        # divide with a number
+        new_quantity = 11.42 / self.q1
+        assert new_quantity.value == 1.
+        assert new_quantity.unit == u.Unit("1/m")
+
+    def test_power(self):
+        # raise quantity to a power
+        new_quantity = self.q1**2
+        np.testing.assert_array_almost_equal(new_quantity.value, 130.4164, decimal=5)
+        assert new_quantity.unit == u.Unit("m^2")
+
+        new_quantity = self.q1**3
+        np.testing.assert_array_almost_equal(new_quantity.value, 1489.355288, decimal=7)
+        assert new_quantity.unit == u.Unit("m^3")
+
+    def test_incompatible_units(self):
+        """ When trying to add or subtract units that aren't compatible, throw an error """
+
+        q1 = u.Quantity(11.412, unit=u.meter)
+        q2 = u.Quantity(21.52, unit=u.second)
+
+        with pytest.raises(u.UnitsException):
+            new_q = q1 + q2
+
+    def test_dimensionless_operations(self):
+        # this test will check that operations with dimensionless Quantities don't work
+
+        with pytest.raises(u.UnitsException):
+            self.q1 + u.Quantity(0.1, unit=u.Unit(""))
+
+        with pytest.raises(u.UnitsException):
+            self.q1 - u.Quantity(0.1, unit=u.Unit(""))
+
+    def test_complicated_operation(self):
+        """ Perform a more complicated test """
+
+        # Multiple units
+        distance = u.Quantity(15., u.meter)
+        time = u.Quantity(11., u.second)
+
+        velocity = (distance / time).to(u.mile/u.hour)
+        np.testing.assert_array_almost_equal(velocity.value, 3.05037, decimal=5)
+
+        G = u.Quantity(6.673E-11, u.m**3/u.kg/u.s**2)
+        new_q = ((1. / (4.*np.pi*G)).to(u.pc**-3/u.s**-2*u.kg))
+
+        # Area
+        side1 = u.Quantity(11., u.centimeter)
+        side2 = u.Quantity(7., u.centimeter)
+        area = side1 * side2
+        np.testing.assert_array_almost_equal(area.value, 77., decimal=15)
+        assert area.unit == u.cm*u.cm
+
+    def test_comparison(self):
+        # equality/ non-equality is straightforward for quantity objects
+        assert (1 / (u.cm * u.cm)) == 1 * u.cm ** -2
+        assert 1 * u.m == 100 * u.cm
+        assert 1 * u.m != 1 * u.cm
+
+        #here one is a unit, which is an invalid comparison
+        assert 1. * u.cm * u.cm * u.cm != u.cm ** 3
+
+        #mismatched types should never work
+        assert not 1. * u.cm == 1.
+        assert 1. * u.cm != 1.
+
+
+
+def test_quantity_conversion():
+    q1 = u.Quantity(0.1, unit=u.meter)
+
+    new_quantity = q1.to(u.kilometer)
+    assert new_quantity.value == 0.0001
+
+    with pytest.raises(u.UnitsException):
+        q1.to(u.zettastokes)
+
+def test_si():
+    q1 = 10. * u.m * u.s**2 / (200. * u.ms)**2 # 250 meters
+    assert q1.si.value == 250
+    assert q1.si.unit == u.m
+
+    q = 10.*u.m # 10 meters
+    assert q.si.value == 10
+    assert q.si.unit == u.m
+
+    q = 10./u.m # 10 1 / meters
+    assert q.si.value == 10
+    assert q.si.unit == (1/u.m)
+
+def test_cgs():
+    q1 = 10. * u.cm * u.s**2 / (200. * u.ms)**2 # 250 centimeters
+    assert q1.cgs.value == 250
+    assert q1.cgs.unit == u.cm
+
+    q = 10.*u.m # 10 centimeters
+    assert q.cgs.value == 1000
+    assert q.cgs.unit == u.cm
+
+    q = 10./u.cm # 10 1 / centimeters
+    assert q.cgs.value == 10
+    assert q.cgs.unit == (1/u.cm)
+
+    q = 10.*u.Pa # 10 pascals
+    assert q.cgs.value == 100
+    assert q.cgs.unit == u.barye
+
+class TestQuantityComparison():
+    def test_quantity_equality(self):
+        assert u.Quantity(1000, unit='m') == u.Quantity(1, unit='km')
+        assert not (u.Quantity(1, unit='m') == u.Quantity(1, unit='km'))
+        with pytest.raises(u.UnitsException):
+            u.Quantity(1, unit='m') == u.Quantity(1, unit='s')
+
+    def test_quantity_comparison(self):
+        assert u.Quantity(1100, unit=u.meter) > u.Quantity(1, unit=u.kilometer)
+        assert u.Quantity(900, unit=u.meter) < u.Quantity(1, unit=u.kilometer)
+
+        with pytest.raises(u.UnitsException):
+            assert u.Quantity(1100, unit=u.meter) > u.Quantity(1, unit=u.second)
+
+        with pytest.raises(u.UnitsException):
+            assert u.Quantity(1100, unit=u.meter) < u.Quantity(1, unit=u.second)
+
+        assert u.Quantity(1100, unit=u.meter) >= u.Quantity(1, unit=u.kilometer)
+        assert u.Quantity(1000, unit=u.meter) >= u.Quantity(1, unit=u.kilometer)
+
+        assert u.Quantity(900, unit=u.meter) <= u.Quantity(1, unit=u.kilometer)
+        assert u.Quantity(1000, unit=u.meter) <= u.Quantity(1, unit=u.kilometer)
+
+        with pytest.raises(u.UnitsException):
+            assert u.Quantity(1100, unit=u.meter) >= u.Quantity(1, unit=u.second)
+
+        with pytest.raises(u.UnitsException):
+            assert u.Quantity(1100, unit=u.meter) <= u.Quantity(1, unit=u.second)
+
+        assert u.Quantity(1200, unit=u.meter) != u.Quantity(1, unit=u.kilometer)
+
+        with pytest.raises(u.UnitsException):
+            assert u.Quantity(1100, unit=u.meter) != u.Quantity(1, unit=u.second)
+
+class TestQuantityDisplay():
+
+    def test_quantity_str(self):
+        q1 = u.Quantity(1, unit='m')
+        assert str(q1) == "1 m"
+
+    def test_quantity_repr(self):
+        q1 = u.Quantity(1, unit='m')
+        assert repr(q1) == "<Quantity 1 m>"
+
+
+def test_decompose():
+    q1 = 5 * u.N
+    assert q1.decomposed_unit == (5 * u.kg * u.m * u.s ** -2)
+
+def test_arrays():
+    """
+    Test using quantites with array values
+    """
+    from numpy.testing import assert_array_equal
+
+    qsec = u.Quantity(np.arange(10), u.second)
+    assert isinstance(qsec.value, np.ndarray)
+    assert not qsec.isscalar
+
+    #len and indexing should work for arrays
+    assert len(qsec) == len(qsec.value)
+    qsecsub25 = qsec[2:5]
+    assert qsecsub25.unit == qsec.unit
+    assert isinstance(qsecsub25, u.Quantity)
+    assert len(qsecsub25) == 3
+
+    #make sure isscalar, len, and indexing behave correcly for non-arrays.
+    qsecnotarray = u.Quantity(10., u.second)
+    assert qsecnotarray.isscalar
+    with pytest.raises(TypeError):
+        len(qsecnotarray)
+    with pytest.raises(TypeError):
+        qsecnotarray[0]
+
+    qseclen0array = u.Quantity(np.array(10), u.second)
+    # 0d numpy array should act basically like a scalar, but still keep its identity as a numpy array
+    assert qseclen0array.isscalar
+    with pytest.raises(TypeError):
+        len(qseclen0array)
+    with pytest.raises(TypeError):
+        qseclen0array[0]
+    assert isinstance(qseclen0array.value, np.ndarray)
+
+
+    #can also create from lists, will auto-convert to arrays
+    qsec = u.Quantity(range(10), u.second)
+    assert isinstance(qsec.value, np.ndarray)
+
+    #quantity math should work with arrays
+    assert_array_equal((qsec * 2).value, (np.arange(10) * 2))
+    assert_array_equal((qsec / 2).value, (np.arange(10) / 2))
+    #quantity addition/subtraction should *not* work with arrays b/c unit ambiguous
+    with pytest.raises(TypeError):
+        assert_array_equal((qsec + 2).value, (np.arange(10) + 2))
+    with pytest.raises(TypeError):
+        assert_array_equal((qsec - 2).value, (np.arange(10) + 2))
+
+    #should create by unit multiplication, too
+    qsec2 = np.arange(10) * u.second
+    qsec3 = u.second * np.arange(10)
+
+    assert np.all(qsec == qsec2)
+    assert np.all(qsec2 == qsec3)
+
diff --git a/astropy/units/tests/test_units.py b/astropy/units/tests/test_units.py
new file mode 100644
index 0000000..4692587
--- /dev/null
+++ b/astropy/units/tests/test_units.py
@@ -0,0 +1,219 @@
+# Licensed under a 3-clause BSD style license - see LICENSE.rst
+"""
+Regression tests for the units package
+"""
+
+from __future__ import absolute_import, unicode_literals, division, print_function
+
+import warnings
+
+from ...tests.helper import pytest, raises
+from ...tests.compat import assert_allclose
+
+from ... import units as u
+
+
+def test_getting_started():
+    """
+    Corresponds to "Getting Started" section in the docs.
+    """
+    speed_unit = u.cm / u.s
+    x = speed_unit.to(u.mile / u.hour, 1)
+    assert_allclose(x, 0.02236936292054402)
+    speed_converter = speed_unit.get_converter("mile hour^-1")
+    x = speed_converter([1., 1000., 5000.])
+    assert_allclose(x, [2.23693629e-02, 2.23693629e+01, 1.11846815e+02])
+
+
+ at raises(ValueError)
+def test_invalid_power():
+    u.m ** 0.3
+
+
+def test_invalid_compare():
+    assert not (u.m == u.s)
+
+
+def test_convert():
+    assert u.h.get_converter(u.s)(1) == 3600
+
+
+def test_convert_fail():
+    with pytest.raises(u.UnitsException):
+        u.cm.to(u.s, 1)
+    with pytest.raises(u.UnitsException):
+        (u.cm / u.s).to(u.m, 1)
+
+
+def test_is_equivalent():
+    assert u.m.is_equivalent(u.inch)
+    assert not (u.Hz.is_equivalent(u.J))
+    assert u.Hz.is_equivalent(u.J, u.spectral())
+    assert u.J.is_equivalent(u.Hz, u.spectral())
+
+
+def test_composite():
+    assert (u.cm / u.s * u.h).get_converter(u.m)(1) == 36
+    assert u.cm * u.cm == u.cm ** 2
+
+    assert u.cm * u.cm * u.cm == u.cm ** 3
+
+    assert u.Hz.to(1000 * u.Hz, 1) == 0.001
+
+
+def test_str():
+    assert str(u.cm) == "cm"
+
+
+def test_repr():
+    assert repr(u.cm) == 'Unit("cm")'
+
+
+def test_spectral():
+    a = u.AA.to(u.Hz, 1, u.spectral())
+    assert_allclose(a, 2.9979245799999995e+18)
+    b = u.Hz.to(u.AA, a, u.spectral())
+    assert_allclose(b, 1)
+
+    a = u.AA.to(u.MHz, 1, u.spectral())
+    assert_allclose(a, 2.9979245799999995e+12)
+    b = u.MHz.to(u.AA, a, u.spectral())
+    assert_allclose(b, 1)
+
+    a = u.m.to(u.Hz, 1, u.spectral())
+    assert_allclose(a, 2.9979245799999995e+8)
+    b = u.Hz.to(u.m, a, u.spectral())
+    assert_allclose(b, 1)
+
+
+def test_spectral2():
+    a = u.nm.to(u.J, 500, u.spectral())
+    assert_allclose(a, 3.972891366538605e-19)
+    b = u.J.to(u.nm, a, u.spectral())
+    assert_allclose(b, 500)
+
+    a = u.AA.to(u.Hz, 1, u.spectral())
+    b = u.Hz.to(u.J, a, u.spectral())
+    c = u.AA.to(u.J, 1, u.spectral())
+    assert_allclose(b, c)
+
+
+def test_spectral3():
+    a = u.nm.to(u.Hz, [1000, 2000], u.spectral())
+    assert_allclose(a, [2.99792458e+14, 1.49896229e+14])
+
+
+def test_spectraldensity():
+    a = u.AA.to(u.Jy, 1, u.spectral_density(u.eV, 2.2))
+    assert_allclose(a, 1059416252057.8357, rtol=1e-4)
+    b = u.Jy.to(u.AA, a, u.spectral_density(u.eV, 2.2))
+    assert_allclose(b, 1)
+
+
+def test_spectraldensity2():
+    flambda = u.erg / u.angstrom / u.cm ** 2 / u.s
+    fnu = u.erg / u.Hz / u.cm ** 2 / u.s
+
+    a = flambda.to(fnu, 1, u.spectral_density(u.AA, 3500))
+    assert_allclose(a, 4.086160166177361e-12)
+
+
+def test_units_conversion():
+    assert_allclose(u.kpc.to(u.Mpc), 0.001)
+    assert_allclose(u.Mpc.to(u.kpc), 1000)
+    assert_allclose(u.yr.to(u.Myr), 1.e-6)
+    assert_allclose(u.AU.to(u.pc), 4.84813681e-6)
+
+
+def test_units_manipulation():
+    # Just do some manipulation and check it's happy
+    (u.kpc * u.yr) ** (1, 3) / u.Myr
+    (u.AA * u.erg) ** 9
+
+
+def test_decompose():
+    assert u.Ry == u.Ry.decompose()
+
+
+def test_equivalent_units():
+    assert u.pound in u.g.find_equivalent_units()
+    assert u.J in u.Hz.find_equivalent_units(u.spectral())
+
+
+def test_unknown_unit():
+    with warnings.catch_warnings(record=True) as warning_lines:
+        warnings.resetwarnings()
+        warnings.simplefilter("always", u.UnitsWarning, append=True)
+        u.Unit("FOO", parse_strict='warn')
+
+    print(dir(warning_lines[0]))
+    assert warning_lines[0].category == u.UnitsWarning
+    assert 'FOO' in str(warning_lines[0].message)
+
+
+def test_unknown_unit2():
+    with warnings.catch_warnings(record=True) as warning_lines:
+        warnings.resetwarnings()
+        warnings.simplefilter("always", u.UnitsWarning, append=True)
+        assert u.Unit("m/s/kg", parse_strict='warn').to_string() == 'm/s/kg'
+
+    print(dir(warning_lines[0]))
+    assert warning_lines[0].category == u.UnitsWarning
+    assert 'm/s/kg' in str(warning_lines[0].message)
+
+
+def test_unknown_unit3():
+    unit = u.Unit("FOO", parse_strict='silent')
+    assert isinstance(unit, u.UnrecognizedUnit)
+    assert unit.name == "FOO"
+
+
+def test_register():
+    try:
+        u.def_unit("foo", u.m ** 3, register=True)
+        assert hasattr(u, 'foo')
+    finally:
+        if hasattr(u, 'foo'):
+            del u.UnitBase._registry[u.UnitBase._registry.index(u.foo)]
+            del u.foo
+
+
+def test_in_units():
+    speed_unit = u.cm / u.s
+    x = speed_unit.in_units(u.mile / u.hour, 1)
+
+
+def test_null_unit():
+    assert (u.m / u.m) == u.Unit(1)
+
+
+def test_unrecognized_equivalency():
+    assert u.m.is_equivalent('foo') == False
+    assert u.m.is_equivalent('foot') == True
+
+
+ at raises(TypeError)
+def test_unit_noarg():
+    u.Unit()
+
+
+def test_convertible_exception():
+    try:
+        u.AA.to(u.h * u.s ** 2)
+    except u.UnitsException as e:
+        assert "length" in str(e)
+
+
+def test_convertible_exception2():
+    try:
+        u.m.to(u.s)
+    except u.UnitsException as e:
+        assert 'time' not in str(e)
+
+
+ at raises(TypeError)
+def test_invalid_type():
+    class A(object):
+        pass
+
+    u.Unit(A())
diff --git a/astropy/units/utils.py b/astropy/units/utils.py
new file mode 100644
index 0000000..ba3e4d6
--- /dev/null
+++ b/astropy/units/utils.py
@@ -0,0 +1,98 @@
+# Licensed under a 3-clause BSD style license - see LICENSE.rst
+"""
+Miscellaneous utilities for `astropy.units`.
+
+None of the functions in the module are meant for use outside of the
+package.
+"""
+from __future__ import absolute_import, division, print_function, unicode_literals
+
+from . import core
+
+
+def _get_first_sentence(s):
+    """
+    Get the first sentence from a string and remove any carriage
+    returns.
+    """
+    import re
+    x = re.match(".*?\S\.\s", s)
+    if x is not None:
+        s = x.group(0)
+    return s.replace('\n', ' ')
+
+
+def generate_unit_summary(namespace):
+    """
+    Generates a summary of units from a given namespace.  This is used
+    to generate the docstring for the modules that define the actual
+    units.
+
+    Parameters
+    ----------
+    namespace : dict
+        A namespace containing units.
+
+    Returns
+    -------
+    docstring : str
+        A docstring containing a summary table of the units.
+    """
+    from . import core
+    import io
+
+    # Get all of the units, and keep track of which ones have SI
+    # prefixes
+    units = []
+    has_prefixes = set()
+    for key, val in namespace.items():
+        # Skip non-unit items
+        if not isinstance(val, core.UnitBase):
+            continue
+
+        # Skip aliases
+        if key != val.name:
+            continue
+
+        if isinstance(val, core.PrefixUnit):
+            has_prefixes.add(val.decompose().bases[0].name)
+        else:
+            units.append(val)
+
+    # Sort alphabetically, case insensitive
+    units.sort(key=lambda x: x.name.lower())
+
+    docstring = io.StringIO()
+
+    docstring.write("""
+.. list-table:: Available Units
+   :header-rows: 1
+   :widths: 10 20 20 20 1
+
+   * - Unit
+     - Description
+     - Represents
+     - Aliases
+     - SI Prefixes
+""")
+
+    for unit in units:
+        if unit.name in has_prefixes:
+            unit_has_prefixes = 'Y'
+        else:
+            unit_has_prefixes = 'N'
+        doc = _get_first_sentence(unit.__doc__).strip()
+        represents = ''
+        if isinstance(unit, core.Unit):
+            represents = ":math:`{0}`".format(
+                unit._represents.to_string('latex')[1:-1])
+        aliases = ', '.join('``{0}``'.format(x) for x in unit.aliases)
+        docstring.write("""
+   * - ``{0}``
+     - {1}
+     - {2}
+     - {3}
+     - {4}
+""".format(unit, doc, represents, aliases, unit_has_prefixes))
+
+    return docstring.getvalue()
diff --git a/astropy/utils/__init__.py b/astropy/utils/__init__.py
index 560ccdc..78262e6 100644
--- a/astropy/utils/__init__.py
+++ b/astropy/utils/__init__.py
@@ -7,9 +7,6 @@ packages, but this subpackage is for utilities that are primarily of use for
 developers or to implement python hacks. This subpackage also includes the
 `astropy.utils.compat` package, which houses utilities that provide
 compatibility and bugfixes across all versions of Python that Astropy supports.
-
-For astronomy-specific utilities of general use (e.g. not specific to some
-other subpackage), see the `astropy.tools` package.
 """
 
 from .compat.odict import OrderedDict
diff --git a/astropy/utils/console.py b/astropy/utils/console.py
index 278b552..60cb37d 100644
--- a/astropy/utils/console.py
+++ b/astropy/utils/console.py
@@ -11,9 +11,14 @@ import sys
 import time
 
 try:
-    from IPython.zmq.iostream import OutStream
-except ImportError:
+    get_ipython()
+except NameError:
     OutStream = None
+else:
+    try:
+        from IPython.zmq.iostream import OutStream
+    except ImportError:
+        OutStream = None
 
 from ..config import ConfigurationItem
 
@@ -47,11 +52,54 @@ def isatty(file):
         return file.isatty()
     return False
 
+def _color_text(text, color):
+    """
+    Returns a string wrapped in ANSI color codes for coloring the
+    text in a terminal::
+
+        colored_text = color_text('Here is a message', 'blue')
+
+    This won't actually effect the text until it is printed to the
+    terminal.
+
+    Parameters
+    ----------
+    text : str
+        The string to return, bounded by the color codes.
+    color : str
+        An ANSI terminal color name. Must be one of:
+        black, red, green, brown, blue, magenta, cyan, lightgrey,
+        default, darkgrey, lightred, lightgreen, yellow, lightblue,
+        lightmagenta, lightcyan, white, or '' (the empty string).
+    """
+    color_mapping = {
+        'black': '0;30',
+        'red': '0;31',
+        'green': '0;32',
+        'brown': '0;33',
+        'blue': '0;34',
+        'magenta': '0;35',
+        'cyan': '0;36',
+        'lightgrey': '0;37',
+        'default': '0;39',
+        'darkgrey': '1;30',
+        'lightred': '1;31',
+        'lightgreen': '1;32',
+        'yellow': '1;33',
+        'lightblue': '1;34',
+        'lightmagenta': '1;35',
+        'lightcyan': '1;36',
+        'white': '1;37'}
+
+    color_code = color_mapping.get(color, '0;39')
+    return u'\033[{0}m{1}\033[0m'.format(color_code, text)
 
 def color_print(*args, **kwargs):
     """
     Prints colors and styles to the terminal uses ANSI escape
-    sequences::
+    sequences.
+
+    ::
 
        color_print('This is the color ', 'default', 'GREEN', 'green')
 
@@ -76,24 +124,6 @@ def color_print(*args, **kwargs):
         The ending of the message.  Defaults to ``\\n``.  The end will
         be printed after resetting any color or font state.
     """
-    color_mapping = {
-        'black': '0;30',
-        'red': '0;31',
-        'green': '0;32',
-        'brown': '0;33',
-        'blue': '0;34',
-        'magenta': '0;35',
-        'cyan': '0;36',
-        'lightgrey': '0;37',
-        'default': '0;39',
-        'darkgrey': '1;30',
-        'lightred': '1;31',
-        'lightgreen': '1;32',
-        'yellow': '1;33',
-        'lightblue': '1;34',
-        'lightmagenta': '1;35',
-        'lightcyan': '1;36',
-        'white': '1;37'}
 
     file = kwargs.get('file', sys.stdout)
     end = kwargs.get('end', u'\n')
@@ -113,9 +143,7 @@ def color_print(*args, **kwargs):
             if color == u'' or color is None:
                 write(msg)
             else:
-                color_code = color_mapping.get(color, '0;39')
-                write(u'\033[{0}m{1}\033[0m'.format(
-                    color_code, msg))
+                write(_color_text(msg, color))
 
         write(end)
     else:
@@ -126,7 +154,6 @@ def color_print(*args, **kwargs):
             write(msg)
         write(end)
 
-
 def strip_ansi_codes(s):
     """
     Remove ANSI color codes from the string.
@@ -298,7 +325,9 @@ class ProgressBar:
     def map(cls, function, items, multiprocess=False, file=sys.stdout):
         """
         Does a `map` operation while displaying a progress bar with
-        percentage complete::
+        percentage complete.
+
+        ::
 
             def work(i):
                 print(i)
@@ -343,7 +372,9 @@ class ProgressBar:
     def iterate(cls, items, file=sys.stdout):
         """
         Iterate over a sequence while indicating progress with a progress
-        bar in the terminal::
+        bar in the terminal.
+
+        ::
 
             for item in ProgressBar.iterate(items):
                 pass
diff --git a/astropy/utils/data.py b/astropy/utils/data.py
new file mode 100644
index 0000000..5e44f9a
--- /dev/null
+++ b/astropy/utils/data.py
@@ -0,0 +1,987 @@
+# Licensed under a 3-clause BSD style license - see LICENSE.rst
+""" This module contains helper functions for accessing, downloading, and
+caching data files.
+"""
+
+from __future__ import division
+
+import os
+import io
+import sys
+import atexit
+import contextlib
+import urllib2
+
+from ..config.configuration import ConfigurationItem
+
+__all__ = ['get_readable_fileobj', 'get_file_contents', 'get_pkg_data_fileobj',
+           'get_pkg_data_filename', 'get_pkg_data_contents',
+           'get_pkg_data_fileobjs', 'get_pkg_data_filenames', 'compute_hash',
+           'clear_download_cache', 'CacheMissingWarning', 'download_file']
+
+DATAURL = ConfigurationItem(
+    'dataurl', 'http://data.astropy.org/', 'URL for astropy remote data site.')
+REMOTE_TIMEOUT = ConfigurationItem(
+    'remote_timeout', 3., 'Time to wait for remote data query (in seconds).')
+COMPUTE_HASH_BLOCK_SIZE = ConfigurationItem(
+    'hash_block_size', 2 ** 16,  # 64K
+    'Block size for computing MD5 file hashes.')
+DOWNLOAD_CACHE_BLOCK_SIZE = ConfigurationItem(
+    'download_block_size', 2 ** 16,  # 64K
+    'Number of bytes of remote data to download per step.')
+DOWNLOAD_CACHE_LOCK_ATTEMPTS = ConfigurationItem(
+    'download_cache_lock_attempts', 3, 'Number of times to try to get the lock ' +
+    'while accessing the data cache before giving up.')
+DELETE_TEMPORARY_DOWNLOADS_AT_EXIT = ConfigurationItem(
+    'delete_temporary_downloads_at_exit', True, 'If True, temporary download' +
+    ' files created when the cache is inacessible will be deleted at the end' +
+    ' of the python session.')
+
+
+PY3K = sys.version_info[0] >= 3
+
+
+class CacheMissingWarning(Warning):
+    """
+    This warning indicates the standard cache directory is not accessible, with
+    the first argument providing the warning message. If args[1] is present, it
+    is a filename indicating the path to a temporary file that was created to
+    store a remote data download in the absence of the cache.
+    """
+
+
+def _is_url(string):
+    """
+    Test whether a string is a valid URL
+
+    Parameters
+    ----------
+    string : str
+        The string to test
+    """
+    from urlparse import urlparse
+    url = urlparse(string)
+    # url[0]==url.scheme, but url[0] is py 2.6-compat
+    # we can't just check that url[0] is not an empty string, because
+    # file paths in windows would return a non-empty scheme (e.g. e:\\
+    # returns 'e').
+    return url[0].lower() in ['http', 'https', 'ftp']
+
+
+ at contextlib.contextmanager
+def get_readable_fileobj(name_or_obj, encoding=None, cache=False):
+    """
+    Given a filename or a readable file-like object, return a context
+    manager that yields a readable file-like object.
+
+    This supports passing filenames, URLs, and readable file-like
+    objects, any of which can be compressed in gzip or bzip2.
+
+
+    Notes
+    -----
+
+    This function is a context manager, and should be used for example
+    as::
+
+        with get_readable_fileobj('file.dat') as f:
+            contents = f.read()
+
+    Parameters
+    ----------
+    name_or_obj : str or file-like object
+        The filename of the file to access (if given as a string), or
+        the file-like object to access.
+
+        If a file-like object, it must be opened in binary mode.
+
+    encoding : str, optional
+        When `None` (default), returns a file-like object with a
+        `read` method that on Python 2.x returns `bytes` objects and
+        on Python 3.x returns `str` (`unicode`) objects, using
+        `locale.getpreferredencoding()` as an encoding.  This matches
+        the default behavior of the built-in `open` when no `mode`
+        argument is provided.
+
+        When `'binary'`, returns a file-like object where its `read`
+        method returns `bytes` objects.
+
+        When another string, it is the name of an encoding, and the
+        file-like object's `read` method will return `str` (`unicode`)
+        objects, decoded from binary using the given encoding.
+
+    cache : bool, optional
+        Whether to cache the contents of remote URLs
+    """
+    import tempfile
+
+    # close_fds is a list of file handles created by this function
+    # that need to be closed.  We don't want to always just close the
+    # returned file handle, because it may simply be the file handle
+    # passed in.  In that case it is not the responsibility of this
+    # function to close it: doing so could result in a "double close"
+    # and an "invalid file descriptor" exception.
+    close_fds = []
+    delete_fds = []
+
+    # Get a file object to the content
+    if isinstance(name_or_obj, basestring):
+        if _is_url(name_or_obj):
+            name_or_obj = download_file(name_or_obj, cache=cache)
+        if PY3K:
+            fileobj = io.FileIO(name_or_obj, 'r')
+        else:
+            fileobj = open(name_or_obj, 'rb')
+        close_fds.append(fileobj)
+    else:
+        fileobj = name_or_obj
+
+    # Check if the file object supports random access, and if not,
+    # then wrap it in a BytesIO buffer.  It would be nicer to use a
+    # BufferedReader to avoid reading loading the whole file first,
+    # but that is not compatible with streams or urllib2.urlopen
+    # objects on Python 2.x.
+    if not hasattr(fileobj, 'seek'):
+        fileobj = io.BytesIO(fileobj.read())
+
+    # Now read enough bytes to look at signature
+    signature = fileobj.read(4)
+    fileobj.seek(0)
+
+    if signature[:3] == b'\x1f\x8b\x08':  # gzip
+        import struct
+        try:
+            from .compat import gzip
+            fileobj_new = gzip.GzipFile(fileobj=fileobj, mode='rb')
+            fileobj_new.read(1)  # need to check that the file is really gzip
+        except IOError:  # invalid gzip file
+            fileobj.seek(0)
+            fileobj_new.close()
+        except struct.error:  # invalid gzip file on Python 3
+            fileobj.seek(0)
+            fileobj_new.close()
+        else:
+            fileobj_new.seek(0)
+            fileobj = fileobj_new
+    elif signature[:3] == b'BZh':  # bzip2
+        try:
+            # bz2.BZ2File does not support file objects, only filenames, so we
+            # need to write the data to a temporary file
+            tmp = tempfile.NamedTemporaryFile("wb", delete=False)
+            tmp.write(fileobj.read())
+            tmp.close()
+            delete_fds.append(tmp)
+            import bz2
+            fileobj_new = bz2.BZ2File(tmp.name, mode='rb')
+            fileobj_new.read(1)  # need to check that the file is really bzip2
+        except IOError:  # invalid bzip2 file
+            fileobj.seek(0)
+            fileobj_new.close()
+        else:
+            fileobj_new.seek(0)
+            close_fds.append(fileobj_new)
+            fileobj = fileobj_new
+
+    # By this point, we have a file, io.FileIO, gzip.GzipFile, or
+    # bz2.BZ2File instance opened in binary mode (that is, read
+    # returns bytes).  Now we need to, if requested, wrap it in a
+    # io.TextIOWrapper so read will return unicode based on the
+    # encoding parameter.
+
+    if PY3K:
+        needs_textio_wrapper = encoding != 'binary'
+    else:
+        needs_textio_wrapper = encoding != 'binary' and encoding is not None
+
+    if needs_textio_wrapper:
+        # A bz2.BZ2File can not be wrapped by a TextIOWrapper,
+        # so we decompress it to a temporary file and then
+        # return a handle to that.
+        import bz2
+        if isinstance(fileobj, bz2.BZ2File):
+            tmp = tempfile.NamedTemporaryFile("wb", delete=False)
+            data = fileobj.read()
+            tmp.write(data)
+            tmp.close()
+            delete_fds.append(tmp)
+            if PY3K:
+                fileobj = io.FileIO(tmp.name, 'r')
+            else:
+                fileobj = open(tmp.name, 'rb')
+            close_fds.append(fileobj)
+
+        # On Python 2.x, we need to first wrap the regular `file`
+        # instance in a `io.FileIO` object before it can be
+        # wrapped in a `TextIOWrapper`.  We don't just create an
+        # `io.FileIO` object in the first place, because we can't
+        # get a raw file descriptor out of it on Python 2.x, which
+        # is required for the XML iterparser.
+        if not PY3K and isinstance(fileobj, file):
+            fileobj = io.FileIO(fileobj.fileno())
+
+        fileobj = io.BufferedReader(fileobj)
+        fileobj = io.TextIOWrapper(fileobj, encoding=encoding)
+
+        # Ensure that file is at the start - io.FileIO will for
+        # example not always be at the start:
+        # >>> import io
+        # >>> f = open('test.fits', 'rb')
+        # >>> f.read(4)
+        # 'SIMP'
+        # >>> f.seek(0)
+        # >>> fileobj = io.FileIO(f.fileno())
+        # >>> fileobj.tell()
+        # 4096L
+
+        fileobj.seek(0)
+
+    try:
+        yield fileobj
+    finally:
+        for fd in close_fds:
+            fd.close()
+        for fd in delete_fds:
+            os.remove(fd.name)
+
+def get_file_contents(name_or_obj, encoding=None, cache=False):
+    """
+    Retrieves the contents of a filename or file-like object.
+
+    See  the `get_readable_fileobj` docstring for details on parameters.
+
+    Returns
+    -------
+    content
+        The content of the file (as requested by `encoding`).
+
+    """
+    with get_readable_fileobj(name_or_obj, encoding, cache) as f:
+        return f.read()
+
+
+def get_pkg_data_fileobj(data_name, encoding=None, cache=True):
+    """
+    Retrieves a data file from the standard locations for the package and
+    provides the file as a file-like object that reads bytes.
+
+    Parameters
+    ----------
+    data_name : str
+        Name/location of the desired data file.  One of the following:
+
+            * The name of a data file included in the source
+              distribution.  The path is relative to the module
+              calling this function.  For example, if calling from
+              `astropy.pkname`, use ``'data/file.dat'`` to get the
+              file in ``astropy/pkgname/data/file.dat``.  Double-dots
+              can be used to go up a level.  In the same example, use
+              ``'../data/file.dat'`` to get ``astropy/data/file.dat``.
+            * If a matching local file does not exist, the Astropy
+              data server will be queried for the file.
+            * A hash like that produced by `compute_hash` can be
+              requested, prefixed by 'hash/'
+              e.g. 'hash/395dd6493cc584df1e78b474fb150840'.  The hash
+              will first be searched for locally, and if not found,
+              the Astropy data server will be queried.
+
+    encoding : str, optional
+        When `None` (default), returns a file-like object with a
+        `read` method that on Python 2.x returns `bytes` objects and
+        on Python 3.x returns `str` (`unicode`) objects, using
+        `locale.getpreferredencoding()` as an encoding.  This matches
+        the default behavior of the built-in `open` when no `mode`
+        argument is provided.
+
+        When `'binary'`, returns a file-like object where its `read`
+        method returns `bytes` objects.
+
+        When another string, it is the name of an encoding, and the
+        file-like object's `read` method will return `str` (`unicode`)
+        objects, decoded from binary using the given encoding.
+
+    cache : bool
+        If True, the file will be downloaded and saved locally or the
+        already-cached local copy will be accessed. If False, the file-like
+        object will directly access the resource (e.g. if a remote URL is
+        accessed, an object like that from `urllib2.urlopen` is returned).
+
+    Returns
+    -------
+    fileobj : file-like
+        An object with the contents of the data file available via
+        :func:`read`.  Can be used as part of a ``with`` statement,
+        automatically closing itself after the ``with`` block.
+
+    Raises
+    ------
+    urllib2.URLError
+        If a remote file cannot be found.
+    IOError
+        If problems occur writing or reading a local file.
+
+    Examples
+    --------
+
+    This will retrieve a data file and its contents for the `astropy.wcs`
+    tests::
+
+        from astropy.config import get_pkg_data_fileobj
+
+        with get_pkg_data_fileobj('data/3d_cd.hdr') as fobj:
+            fcontents = fobj.read()
+
+    This would download a data file from the astropy data server
+    because the ``standards/vega.fits`` file is not present in the
+    source distribution.  It will also save the file locally so the
+    next time it is accessed it won't need to be downloaded.::
+
+        from astropy.config import get_pkg_data_fileobj
+
+        with get_pkg_data_fileobj('standards/vega.fits') as fobj:
+            fcontents = fobj.read()
+
+    This does the same thing but does *not* cache it locally::
+
+        with get_pkg_data_fileobj('standards/vega.fits', cache=False) as fobj:
+            fcontents = fobj.read()
+
+    See Also
+    --------
+    get_pkg_data_contents : returns the contents of a file or url as a bytes object
+    get_pkg_data_filename : returns a local name for a file containing the data
+    """
+    datafn = _find_pkg_data_path(data_name)
+    if os.path.isdir(datafn):
+        raise IOError("Tried to access a data file that's actually "
+                      "a package data directory")
+    elif os.path.isfile(datafn):  # local file
+        return get_readable_fileobj(datafn, encoding=encoding)
+    else:  # remote file
+        return get_readable_fileobj(DATAURL() + datafn, encoding=encoding,
+                                    cache=cache)
+
+
+def get_pkg_data_filename(data_name):
+    """
+    Retrieves a data file from the standard locations for the package and
+    provides a local filename for the data.
+
+    This function is similar to `get_pkg_data_fileobj` but returns the file *name*
+    instead of a readable file-like object.  This means that this function must
+    always cache remote files locally, unlike `get_pkg_data_fileobj`.
+
+    Parameters
+    ----------
+    data_name : str
+        Name/location of the desired data file.  One of the following:
+
+            * The name of a data file included in the source
+              distribution.  The path is relative to the module
+              calling this function.  For example, if calling from
+              `astropy.pkname`, use ``'data/file.dat'`` to get the
+              file in ``astropy/pkgname/data/file.dat``.  Double-dots
+              can be used to go up a level.  In the same example, use
+              ``'../data/file.dat'`` to get ``astropy/data/file.dat``.
+            * If a matching local file does not exist, the Astropy
+              data server will be queried for the file.
+            * A hash like that produced by `compute_hash` can be
+              requested, prefixed by 'hash/'
+              e.g. 'hash/395dd6493cc584df1e78b474fb150840'.  The hash
+              will first be searched for locally, and if not found,
+              the Astropy data server will be queried.
+
+    Raises
+    ------
+    urllib2.URLError
+        If a remote file cannot be found.
+    IOError
+        If problems occur writing or reading a local file.
+
+    Returns
+    -------
+    filename : str
+        A file path on the local file system corresponding to the data
+        requested in `data_name`.
+
+    Examples
+    --------
+
+    This will retrieve the contents of the data file for the `astropy.wcs`
+    tests::
+
+        from astropy.config import get_pkg_data_filename
+
+        fn = get_pkg_data_filename('data/3d_cd.hdr')
+        with open(fn) as f:
+            fcontents = f.read()
+
+
+    This retrieves a data file by hash either locally or from the astropy data
+    server::
+
+        from astropy.config import get_pkg_data_filename
+
+        fn = get_pkg_data_filename('hash/da34a7b07ef153eede67387bf950bb32')
+        with open(fn) as f:
+            fcontents = f.read()
+
+    See Also
+    --------
+    get_pkg_data_contents : returns the contents of a file or url as a bytes object
+    get_pkg_data_fileobj : returns a file-like object with the data
+    """
+
+    if data_name.startswith('hash/'):
+        # first try looking for a local version if a hash is specified
+        hashfn = _find_hash_fn(data_name[5:])
+        if hashfn is None:
+            return download_file(DATAURL() + data_name, cache=True)
+        else:
+            return hashfn
+    else:
+        datafn = _find_pkg_data_path(data_name)
+        if os.path.isdir(datafn):
+            raise IOError("Tried to access a data file that's actually "
+                          "a package data directory")
+        elif os.path.isfile(datafn):  # local file
+            return datafn
+        else:  # remote file
+            return download_file(DATAURL() + data_name, cache=True)
+
+
+def get_pkg_data_contents(data_name, encoding=None, cache=True):
+    """
+    Retrieves a data file from the standard locations and returns its
+    contents as a bytes object.
+
+    Parameters
+    ----------
+    data_name : str
+        Name/location of the desired data file.  One of the following:
+
+            * The name of a data file included in the source
+              distribution.  The path is relative to the module
+              calling this function.  For example, if calling from
+              `astropy.pkname`, use ``'data/file.dat'`` to get the
+              file in ``astropy/pkgname/data/file.dat``.  Double-dots
+              can be used to go up a level.  In the same example, use
+              ``'../data/file.dat'`` to get ``astropy/data/file.dat``.
+            * If a matching local file does not exist, the Astropy
+              data server will be queried for the file.
+            * A hash like that produced by `compute_hash` can be
+              requested, prefixed by 'hash/'
+              e.g. 'hash/395dd6493cc584df1e78b474fb150840'.  The hash
+              will first be searched for locally, and if not found,
+              the Astropy data server will be queried.
+            * A URL to some other file.
+
+    encoding : str, optional
+        When `None` (default), returns a file-like object with a
+        `read` method that on Python 2.x returns `bytes` objects and
+        on Python 3.x returns `str` (`unicode`) objects, using
+        `locale.getpreferredencoding()` as an encoding.  This matches
+        the default behavior of the built-in `open` when no `mode`
+        argument is provided.
+
+        When `'binary'`, returns a file-like object where its `read`
+        method returns `bytes` objects.
+
+        When another string, it is the name of an encoding, and the
+        file-like object's `read` method will return `str` (`unicode`)
+        objects, decoded from binary using the given encoding.
+
+    cache : bool
+        If True, the file will be downloaded and saved locally or the
+        already-cached local copy will be accessed. If False, the file-like
+        object will directly access the resource (e.g. if a remote URL is
+        accessed, an object like that from `urllib2.urlopen` is returned).
+
+    Returns
+    -------
+    contents : bytes
+        The complete contents of the file as a bytes object.
+
+    Raises
+    ------
+    urllib2.URLError
+        If a remote file cannot be found.
+    IOError
+        If problems occur writing or reading a local file.
+
+    See Also
+    --------
+    get_pkg_data_fileobj : returns a file-like object with the data
+    get_pkg_data_filename : returns a local name for a file containing the data
+    """
+    with get_pkg_data_fileobj(data_name, encoding=encoding, cache=cache) as fd:
+        contents = fd.read()
+    return contents
+
+
+def get_pkg_data_filenames(datadir, pattern='*'):
+    """
+    Returns the path of all of the data files in a given directory
+    that match a given glob pattern.
+
+    Parameters
+    ----------
+    datadir : str
+        Name/location of the desired data files.  One of the following:
+
+            * The name of a directory included in the source
+              distribution.  The path is relative to the module
+              calling this function.  For example, if calling from
+              `astropy.pkname`, use ``'data'`` to get the
+              files in ``astropy/pkgname/data``.
+            * Remote URLs are not currently supported.
+
+    pattern : str, optional
+        A UNIX-style filename glob pattern to match files.  See the
+        `glob` module in the standard library for more information.
+        By default, matches all files.
+
+    Returns
+    -------
+    filenames : iterator of str
+        Paths on the local filesystem in *datadir* matching *pattern*.
+
+    Examples
+    --------
+    This will retrieve the contents of the data file for the `astropy.wcs`
+    tests::
+
+        from astropy.config import get_pkg_data_filenames
+
+        for fn in get_pkg_data_filename('maps', '*.hdr'):
+            with open(fn) as f:
+                fcontents = f.read()
+    """
+    import fnmatch
+    from os.path import isdir, isfile, join
+    from os import listdir
+
+    path = _find_pkg_data_path(datadir)
+    if isfile(path):
+        raise IOError(
+            "Tried to access a data directory that's actually "
+            "a package data file")
+    elif isdir(path):
+        for filename in listdir(path):
+            if fnmatch.fnmatch(filename, pattern):
+                yield join(path, filename)
+    else:
+        raise IOError("Path not found")
+
+
+def get_pkg_data_fileobjs(datadir, pattern='*', encoding=None):
+    """
+    Returns readable file objects for all of the data files in a given
+    directory that match a given glob pattern.
+
+    Parameters
+    ----------
+    datadir : str
+        Name/location of the desired data files.  One of the following:
+
+            * The name of a directory included in the source
+              distribution.  The path is relative to the module
+              calling this function.  For example, if calling from
+              `astropy.pkname`, use ``'data'`` to get the
+              files in ``astropy/pkgname/data``
+            * Remote URLs are not currently supported
+
+    pattern : str, optional
+        A UNIX-style filename glob pattern to match files.  See the
+        `glob` module in the standard library for more information.
+        By default, matches all files.
+
+    encoding : str, optional
+        When `None` (default), returns a file-like object with a
+        `read` method that on Python 2.x returns `bytes` objects and
+        on Python 3.x returns `str` (`unicode`) objects, using
+        `locale.getpreferredencoding()` as an encoding.  This matches
+        the default behavior of the built-in `open` when no `mode`
+        argument is provided.
+
+        When `'binary'`, returns a file-like object where its `read`
+        method returns `bytes` objects.
+
+        When another string, it is the name of an encoding, and the
+        file-like object's `read` method will return `str` (`unicode`)
+        objects, decoded from binary using the given encoding.
+
+    Returns
+    -------
+    fileobjs : iterator of file objects
+        File objects for each of the files on the local filesystem in
+        *datadir* matching *pattern*.
+
+    Examples
+    --------
+    This will retrieve the contents of the data file for the `astropy.wcs`
+    tests::
+
+        from astropy.config import get_pkg_data_filenames
+
+        for fd in get_pkg_data_filename('maps', '*.hdr'):
+            fcontents = fd.read()
+    """
+    for fn in get_pkg_data_filenames(datadir, pattern):
+        with get_pkg_data_fileobj(fn, encoding=encoding) as fd:
+            yield fd
+
+
+def compute_hash(localfn):
+    """ Computes the MD5 hash for a file.
+
+    The hash for a data file is used for looking up data files in a unique
+    fashion. This is of particular use for tests; a test may require a
+    particular version of a particular file, in which case it can be accessed
+    via hash to get the appropriate version.
+
+    Typically, if you wish to write a test that requires a particular data
+    file, you will want to submit that file to the astropy data servers, and
+    use e.g. ``get_pkg_data_filename('hash/a725fa6ba642587436612c2df0451956')``,
+    but with the hash for your file in place of the hash in the example.
+
+    Parameters
+    ----------
+    localfn : str
+        The path to the file for which the hash should be generated.
+
+    Returns
+    -------
+    md5hash : str
+        The hex digest of the MD5 hash for the contents of the `localfn` file.
+
+    """
+    import hashlib
+
+    with open(localfn, 'rb') as f:
+        h = hashlib.md5()
+        block = f.read(COMPUTE_HASH_BLOCK_SIZE())
+        while block:
+            h.update(block)
+            block = f.read(COMPUTE_HASH_BLOCK_SIZE())
+
+    return h.hexdigest()
+
+
+def _find_pkg_data_path(data_name):
+    """
+    Look for data in the source-included data directories and return the
+    path.
+    """
+    from os.path import abspath, dirname, join
+    from ..utils.misc import find_current_module
+
+    module = find_current_module(1, True)
+    if module is None:
+        # not called from inside an astropy package.  So just pass name through
+        return data_name
+    rootpkgname = module.__package__.split('.')[0]
+
+    rootpkg = __import__(rootpkgname)
+
+    module_path = dirname(module.__file__)
+    path = join(module_path, data_name)
+
+    root_dir = dirname(rootpkg.__file__)
+    assert abspath(path).startswith(abspath(root_dir)), \
+           ("attempted to get a local data file outside "
+            "of the " + rootpkgname + " tree")
+
+    return path
+
+
+def _find_hash_fn(hash):
+    """
+    Looks for a local file by hash - returns file name if found and a valid
+    file, otherwise returns None.
+    """
+    from os.path import isfile, join
+    from warnings import warn
+
+    try:
+        dldir, urlmapfn = _get_download_cache_locs()
+    except (IOError, OSError) as e:
+        msg = 'Could not access cache directory to search for data file: '
+        warn(CacheMissingWarning(msg + str(e)))
+        return None
+    hashfn = join(dldir, hash)
+    if isfile(hashfn):
+        return hashfn
+    else:
+        return None
+
+
+def download_file(remote_url, cache=False):
+    """
+    Accepts a URL, downloads and optionally caches the result
+    returning the filename, with a name determined by the file's MD5
+    hash. If ``cache=True`` and the file is present in the cache, just
+    returns the filename.
+
+    Parameters
+    ----------
+    remote_url : str
+        The URL of the file to download
+    cache : bool, optional
+        Whether to use the cache
+    """
+
+    import hashlib
+    from contextlib import closing
+    from tempfile import NamedTemporaryFile
+    from shutil import move
+    from warnings import warn
+
+    from ..utils.console import ProgressBarOrSpinner
+
+    missing_cache = False
+
+    if cache:
+
+        try:
+            dldir, urlmapfn = _get_download_cache_locs()
+        except (IOError, OSError) as e:
+            msg = 'Remote data cache could not be accessed due to '
+            estr = '' if len(e.args) < 1 else (': ' + str(e))
+            warn(CacheMissingWarning(msg + e.__class__.__name__ + estr))
+            cache = False
+            missing_cache = True  # indicates that the cache is missing to raise a warning later
+
+        if not missing_cache:
+            _acquire_download_cache_lock()
+    try:
+        if cache:
+            with _open_shelve(urlmapfn, True) as url2hash:
+                if str(remote_url) in url2hash:
+                    return url2hash[str(remote_url)]
+
+        with closing(urllib2.urlopen(remote_url, timeout=REMOTE_TIMEOUT())) as remote:
+
+            #keep a hash to rename the local file to the hashed name
+            hash = hashlib.md5()
+
+            info = remote.info()
+            if 'Content-Length' in info:
+                try:
+                    size = int(info['Content-Length'])
+                except ValueError:
+                    size = None
+            else:
+                size = None
+
+            dlmsg = "Downloading {0}".format(remote_url)
+            with ProgressBarOrSpinner(size, dlmsg) as p:
+                with NamedTemporaryFile(delete=False) as f:
+                    bytes_read = 0
+                    block = remote.read(DOWNLOAD_CACHE_BLOCK_SIZE())
+                    while block:
+                        f.write(block)
+                        hash.update(block)
+                        bytes_read += len(block)
+                        p.update(bytes_read)
+                        block = remote.read(DOWNLOAD_CACHE_BLOCK_SIZE())
+
+        if cache:
+            with _open_shelve(urlmapfn, True) as url2hash:
+                local_path = os.path.join(dldir, hash.hexdigest())
+                move(f.name, local_path)
+                url2hash[str(remote_url)] = local_path
+        else:
+            local_path = f.name
+            if missing_cache:
+                msg = ('File downloaded to temporary location due to problem '
+                       'with cache directory and will not be cached.')
+                warn(CacheMissingWarning(msg, local_path))
+            if DELETE_TEMPORARY_DOWNLOADS_AT_EXIT():
+                global _tempfilestodel
+                _tempfilestodel.append(local_path)
+    except urllib2.URLError, e:
+        if e.reason.errno == 8:
+            e.reason.strerror = e.reason.strerror + '. requested URL: ' + remote_url
+            e.reason.args = (e.reason.errno, e.reason.strerror)
+        raise e
+    finally:
+        if cache and not missing_cache:
+            _release_download_cache_lock()
+
+    return local_path
+
+
+# This is used by download_file and _deltemps to determine the files to delete
+# when the interpreter exits
+_tempfilestodel = []
+
+
+ at atexit.register
+def _deltemps():
+
+    global _tempfilestodel
+
+    while len(_tempfilestodel) > 0:
+        fn = _tempfilestodel.pop()
+        if os.path.isfile(fn):
+            os.remove(fn)
+
+
+def clear_download_cache(hashorurl=None):
+    """ Clears the data file cache by deleting the local file(s).
+
+    Parameters
+    ----------
+    hashorurl : str or None
+        If None, the whole cache is cleared.  Otherwise, either specifies a
+        hash for the cached file that is supposed to be deleted, or a URL that
+        has previously been downloaded to the cache.
+
+    Raises
+    ------
+    OSEerror
+        If the requested filename is not present in the data directory.
+
+    """
+    from os import unlink
+    from os.path import join, exists, abspath
+    from shutil import rmtree
+    from warnings import warn
+
+    try:
+        dldir, urlmapfn = _get_download_cache_locs()
+    except (IOError, OSError) as e:
+        msg = 'Not clearing data cache - cache inacessable due to '
+        estr = '' if len(e.args) < 1 else (': ' + str(e))
+        warn(CacheMissingWarning(msg + e.__class__.__name__ + estr))
+        return
+
+    _acquire_download_cache_lock()
+    try:
+
+        if hashorurl is None:
+            if exists(dldir):
+                rmtree(dldir)
+            if exists(urlmapfn):
+                unlink(urlmapfn)
+        else:
+            with _open_shelve(urlmapfn, True) as url2hash:
+                filepath = join(dldir, hashorurl)
+                assert abspath(filepath).startswith(abspath(dldir)), \
+                       ("attempted to use clear_download_cache on a location" +
+                        " that's not inside the data cache directory")
+
+                if exists(filepath):
+                    for k, v in url2hash.items():
+                        if v == filepath:
+                            del url2hash[k]
+                    unlink(filepath)
+
+                elif hashorurl in url2hash:
+                    filepath = url2hash[hashorurl]
+                    del url2hash[hashorurl]
+                    unlink(filepath)
+
+                else:
+                    msg = 'Could not find file or url {0}'
+                    raise OSError(msg.format(hashorurl))
+    finally:
+        # the lock will be gone if rmtree was used above, but release otherwise
+        if exists(join(_get_download_cache_locs()[0], 'lock')):
+            _release_download_cache_lock()
+
+
+def _get_download_cache_locs():
+    """ Finds the path to the data cache directory.
+
+    Returns
+    -------
+    datadir : str
+        The path to the data cache directory.
+    shelveloc : str
+        The path to the shelve object that stores the cache info.
+    """
+    from ..config.paths import get_cache_dir
+    from os.path import exists, isdir, join
+    from os import mkdir
+
+    datadir = join(get_cache_dir(), 'download')
+    shelveloc = join(get_cache_dir(), 'download_urlmap')
+    if not exists(datadir):
+        mkdir(datadir)
+    elif not isdir(datadir):
+        msg = 'Data cache directory {0} is not a directory'
+        raise IOError(msg.format(datadir))
+
+    if isdir(shelveloc):
+        msg = 'Data cache shelve object location {0} is a directory'
+        raise IOError(msg.format(shelveloc))
+
+    return datadir, shelveloc
+
+
+def _open_shelve(shelffn, withclosing=False):
+    """
+    opens a shelf in a way that is py3.x and py2.x compatible.  If
+    `withclosing` is  True, it will be opened with closing, allowing use like:
+
+        with _open_shelve('somefile',True) as s:
+            ...
+    """
+    import shelve
+    from contextlib import closing
+
+    if not PY3K:  # pragma: py3
+        shelf = shelve.open(shelffn, protocol=2)
+    else:  # pragma: py2
+        shelf = shelve.open(shelffn + '.db', protocol=2)
+
+    if withclosing:
+        return closing(shelf)
+    else:
+        return shelf
+
+
+#the cache directory must be locked before any writes are performed.  Same for
+#the hash shelve, so this should be used for both.
+def _acquire_download_cache_lock():
+    """
+    Uses the lock directory method.  This is good because `mkdir` is
+    atomic at the system call level, so it's thread-safe.
+    """
+    from os.path import join
+    from os import mkdir
+    from time import sleep
+
+    lockdir = os.path.join(_get_download_cache_locs()[0], 'lock')
+    for i in range(DOWNLOAD_CACHE_LOCK_ATTEMPTS()):
+        try:
+            mkdir(lockdir)
+            #write the pid of this process for informational purposes
+            with open(join(lockdir, 'pid'), 'w') as f:
+                f.write(str(os.getpid()))
+
+        except OSError:
+            sleep(1)
+        else:
+            return
+    msg = 'Unable to acquire lock for cache directory ({0} exists)'
+    raise RuntimeError(msg.format(lockdir))
+
+
+def _release_download_cache_lock():
+    from os.path import join, exists, isdir
+    from os import rmdir
+
+    lockdir = join(_get_download_cache_locs()[0], 'lock')
+
+    if isdir(lockdir):
+        #if the pid file is present, be sure to remove it
+        pidfn = join(lockdir, 'pid')
+        if exists(pidfn):
+            os.remove(pidfn)
+        rmdir(lockdir)
+    else:
+        msg = 'Error releasing lock. "{0}" either does not exist or is not ' +\
+              'a directory.'
+        raise RuntimeError(msg.format(lockdir))
diff --git a/astropy/utils/misc.py b/astropy/utils/misc.py
index 8e8eee8..e34b7c4 100644
--- a/astropy/utils/misc.py
+++ b/astropy/utils/misc.py
@@ -1,7 +1,7 @@
 # Licensed under a 3-clause BSD style license - see LICENSE.rst
 """
-A "grab bag" of smallish general-purpose utilities that don't have a
-clear other module/pakcage to live in.
+A "grab bag" of relatively small general-purpose utilities that don't have
+a clear module/package to live in.
 """
 
 from __future__ import absolute_import
@@ -10,10 +10,11 @@ import collections
 import functools
 import sys
 import textwrap
+import traceback
 import warnings
 
-__all__ = ['find_current_module', 'fnpickle', 'fnunpickle', 'isiterable',
-           'deprecated', 'lazyproperty']
+__all__ = ['find_current_module', 'isiterable', 'deprecated', 'lazyproperty',
+           'deprecated_attribute', 'format_exception', 'NumpyRNGContext']
 
 
 def find_current_module(depth=1, finddiff=False):
@@ -193,117 +194,6 @@ def find_mod_objs(modname, onlylocals=False):
     return localnames, fqnames, objs
 
 
-def fnunpickle(fileorname, number=0, usecPickle=True):
-    """ Unpickle pickled objects from a specified file and return the contents.
-
-    Parameters
-    ----------
-    fileorname : str or `file`-like
-        The file name or file from which to unpickle objects. If a file object,
-        it should have been opened in binary mode.
-    number : int
-        If 0, a single object will be returned (the first in the file). If >0,
-        this specifies the number of objects to be unpickled, and a list will
-        be returned with exactly that many objects. If <0, all objects in the
-        file will be unpickled and returned as a list.
-    usecPickle : bool
-        If True, the :mod:`cPickle` module is to be used in place of
-        :mod:`pickle` (cPickle is faster). This only applies for python 2.x.
-
-    Raises
-    ------
-    EOFError
-        If `number` is >0 and there are fewer than `number` objects in the
-        pickled file.
-
-    Returns
-    -------
-    contents : obj or list
-        If `number` is 0, this is a individual object - the first one unpickled
-        from the file. Otherwise, it is a list of objects unpickled from the
-        file.
-
-    """
-
-    if usecPickle and sys.version_info[0] < 3:  # pragma: py2
-        import cPickle as pickle
-    else:
-        import pickle
-
-    if isinstance(fileorname, basestring):
-        f = open(fileorname, 'rb')
-        close = True
-    else:
-        f = fileorname
-        close = False
-
-    try:
-        if number > 0:  # get that number
-            res = []
-            for i in range(number):
-                res.append(pickle.load(f))
-        elif number < 0:  # get all objects
-            res = []
-            eof = False
-            while not eof:
-                try:
-                    res.append(pickle.load(f))
-                except EOFError:
-                    eof = True
-        else:  # number==0
-            res = pickle.load(f)
-    finally:
-        if close:
-            f.close()
-
-    return res
-
-
-def fnpickle(object, fileorname, usecPickle=True, protocol=None, append=False):
-    """Pickle an object to a specified file.
-
-    Parameters
-    ----------
-    object
-        The python object to pickle.
-    fileorname : str or `file`-like
-        The filename or file into which the `object` should be pickled. If a
-        file object, it should have been opened in binary mode.
-    usecPickle : bool
-        If True (default), the :mod:`cPickle` module is to be used in place of
-        :mod:`pickle` (cPickle is faster). This only applies for python 2.x.
-    protocol : int or None
-        Pickle protocol to use - see the :mod:`pickle` module for details on
-        these options. If None, the most recent protocol will be used.
-    append : bool
-        If True, the object is appended to the end of the file, otherwise the
-        file will be overwritten (if a file object is given instead of a
-        file name, this has no effect).
-
-    """
-
-    if usecPickle and sys.version_info[0] < 3:  # pragma: py2
-        import cPickle as pickle
-    else:
-        import pickle
-
-    if protocol is None:
-        protocol = pickle.HIGHEST_PROTOCOL
-
-    if isinstance(fileorname, basestring):
-        f = open(fileorname, 'ab' if append else 'wb')
-        close = True
-    else:
-        f = fileorname
-        close = False
-
-    try:
-        pickle.dump(object, f, protocol=protocol)
-    finally:
-        if close:
-            f.close()
-
-
 def isiterable(obj):
     """Returns `True` if the given object is iterable."""
     from numpy import ndarray
@@ -335,7 +225,7 @@ class lazyproperty(object):
         >>> class LazyTest(object):
         ...     @lazyproperty
         ...     def complicated_property(self):
-        ...         print 'Computing the value for complicated_property..."
+        ...         print 'Computing the value for complicated_property...'
         ...         return 42
         ...
         >>> lt = LazyTest()
@@ -408,29 +298,33 @@ class lazyproperty(object):
 
 
 # TODO: Provide a class deprecation marker as well.
-def deprecated(since, message='', name='', alternative='', pending=False):
+def deprecated(since, message='', name='', alternative='', pending=False,
+               obj_type='function'):
     """
     Used to mark a function as deprecated.
 
-    To mark an attribute as deprecated, replace that attribute with a
-    depcrecated property.
+    To mark an attribute as deprecated, use `deprecated_attribute`.
 
     Parameters
     ------------
     since : str
-        The release at which this API became deprecated.  This is required.
+        The release at which this API became deprecated.  This is
+        required.
 
     message : str, optional
-        Override the default deprecation message.  The format specifier
-        %(func)s may be used for the name of the function, and %(alternative)s
-        may be used in the deprecation message to insert the name of an
-        alternative to the deprecated function.
+        Override the default deprecation message.  The format
+        specifier `%(func)s` may be used for the name of the function,
+        and `%(alternative)s` may be used in the deprecation message
+        to insert the name of an alternative to the deprecated
+        function.  `%(obj_type)` may be used to insert a friendly name
+        for the type of object being deprecated.
 
     name : str, optional
-        The name of the deprecated function; if not provided the name is
-        automatically determined from the passed in function, though this is
-        useful in the case of renamed functions, where the new function is just
-        assigned to the name of the deprecated function.  For example::
+        The name of the deprecated function; if not provided the name
+        is automatically determined from the passed in function,
+        though this is useful in the case of renamed functions, where
+        the new function is just assigned to the name of the
+        deprecated function.  For example::
 
             def new_function():
                 ...
@@ -473,16 +367,20 @@ def deprecated(since, message='', name='', alternative='', pending=False):
         altmessage = ''
         if not message or type(message) == type(deprecate):
             if pending:
-                message = ('The %(func)s function will be deprecated in a '
+                message = ('The %(func)s %(obj_type)s will be deprecated in a '
                            'future version.')
             else:
-                message = ('The %(func)s function is deprecated and may '
+                message = ('The %(func)s %(obj_type)s is deprecated and may '
                            'be removed in a future version.')
             if alternative:
                 altmessage = '\n        Use %s instead.' % alternative
 
-        message = ((message % {'func': name, 'alternative': alternative}) +
-                   altmessage)
+        message = ((message % {
+            'func': name,
+            'name': name,
+            'alternative': alternative,
+            'obj_type': obj_type}) +
+            altmessage)
 
         @functools.wraps(func)
         def deprecated_func(*args, **kwargs):
@@ -520,3 +418,147 @@ def deprecated(since, message='', name='', alternative='', pending=False):
         return deprecate(message)
 
     return deprecate
+
+
+def deprecated_attribute(name, since, message=None, alternative=None,
+                         pending=False):
+    """
+    Used to mark a public attribute as deprecated.  This creates a
+    property that will warn when the given attribute name is accessed.
+    To prevent the warning (i.e. for internal code), use the private
+    name for the attribute by prepending an underscore
+    (i.e. `self._name`).
+
+    Parameters
+    ----------
+    name : str
+        The name of the deprecated attribute.
+
+    since : str
+        The release at which this API became deprecated.  This is
+        required.
+
+    message : str, optional
+        Override the default deprecation message.  The format
+        specifier `%(name)s` may be used for the name of the attribute,
+        and `%(alternative)s` may be used in the deprecation message
+        to insert the name of an alternative to the deprecated
+        function.
+
+    alternative : str, optional
+        An alternative attribute that the user may use in place of the
+        deprecated attribute.  The deprecation warning will tell the
+        user about this alternative if provided.
+
+    pending : bool, optional
+        If True, uses a PendingDeprecationWarning instead of a
+        DeprecationWarning.
+
+    Examples
+    --------
+
+    ::
+
+        class MyClass:
+            # Mark the old_name as deprecated
+            old_name = misc.deprecated_attribute('old_name', '0.1')
+
+            def method(self):
+                self._old_name = 42
+    """
+    private_name = '_' + name
+
+    @deprecated(since, name=name, obj_type='attribute')
+    def get(self):
+        return getattr(self, private_name)
+
+    @deprecated(since, name=name, obj_type='attribute')
+    def set(self, val):
+        setattr(self, private_name, val)
+
+    @deprecated(since, name=name, obj_type='attribute')
+    def delete(self):
+        delattr(self, private_name)
+
+    return property(get, set, delete)
+
+
+def format_exception(msg, *args, **kwargs):
+    """
+    Given an exception message string, uses new-style formatting arguments
+    ``{filename}``, ``{lineno}``, ``{func}`` and/or ``{text}`` to fill in
+    information about the exception that occurred.  For example:
+
+        try:
+            1/0
+        except:
+            raise ZeroDivisionError(
+                format_except('A divide by zero occurred in {filename} at '
+                              'line {lineno} of function {func}.'))
+
+    Any additional positional or keyword arguments passed to this function are
+    also used to format the message.
+
+    .. note::
+        This uses `sys.exc_info` to gather up the information needed to
+        fill in the formatting arguments. Python 2.x and 3.x have slightly
+        different behavior regarding `sys.exc_info` (the latter will not carry
+        it outside a handled exception), so it's not wise to use this outside of
+        an `except` clause - if it is, this will substitute '<unkown>' for the 4
+        formatting arguments.
+    """
+
+    tb = traceback.extract_tb(sys.exc_info()[2], limit=1)
+    if len(tb) > 0:
+        filename, lineno, func, text = tb[0]
+    else:
+        filename = lineno = func = text = '<unknown>'
+
+    return msg.format(*args, filename=filename, lineno=lineno, func=func,
+                      text=text, **kwargs)
+
+
+class NumpyRNGContext(object):
+    """
+    A context manager (for use with the ``with`` statement) that will seed the
+    numpy random number generator (RNG) to a specific value, and then restore
+    the RNG state back to whatever it was before.
+
+    This is primarily intended for use in the astropy testing suit, but it
+    may be useful in ensuring reproducibility of Monte Carlo simulations in a
+    science context.
+
+    Parameters
+    ----------
+    seed : int
+        The value to use to seed the numpy RNG
+
+    Examples
+    --------
+    A typical use case might be::
+
+        with NumpyRNGContext(<some seed value you pick>):
+            from numpy import random
+
+            randarr = random.randn(100)
+            ... run your test using `randarr` ...
+
+        #Any code using numpy.random at this indent level will act just as it
+        #would have if it had been before the with statement - e.g. whatever
+        #the default seed is.
+
+
+    """
+    def __init__(self, seed):
+        self.seed = seed
+
+    def __enter__(self):
+        from numpy import random
+
+        self.startstate = random.get_state()
+        random.seed(self.seed)
+
+    def __exit__(self, exc_type, exc_value, traceback):
+        from numpy import random
+
+        random.set_state(self.startstate)
diff --git a/astropy/utils/setup_package.py b/astropy/utils/setup_package.py
index e92a972..4417cd5 100644
--- a/astropy/utils/setup_package.py
+++ b/astropy/utils/setup_package.py
@@ -9,3 +9,14 @@ def get_extensions():
         Extension('astropy.utils._compiler',
                   [relpath(join(ROOT, 'src', 'compiler.c'))])
         ]
+
+
+def get_package_data():
+    # Installs the testing data files
+    return {
+        'astropy.utils.tests': [
+            'data/*.dat',
+            'data/*.dat.gz',
+            'data/*.dat.bz2',
+            'data/*.txt']
+        }
diff --git a/astropy/utils/tests/data/invalid.dat.bz2 b/astropy/utils/tests/data/invalid.dat.bz2
new file mode 100644
index 0000000..244d27c
--- /dev/null
+++ b/astropy/utils/tests/data/invalid.dat.bz2
@@ -0,0 +1 @@
+BZhinvalid
\ No newline at end of file
diff --git a/astropy/utils/tests/data/invalid.dat.gz b/astropy/utils/tests/data/invalid.dat.gz
new file mode 100644
index 0000000..c7a63ae
--- /dev/null
+++ b/astropy/utils/tests/data/invalid.dat.gz
@@ -0,0 +1 @@
+‹invalid
\ No newline at end of file
diff --git a/astropy/config/tests/data/local.dat b/astropy/utils/tests/data/local.dat
similarity index 100%
rename from astropy/config/tests/data/local.dat
rename to astropy/utils/tests/data/local.dat
diff --git a/astropy/utils/tests/data/local.dat.bz2 b/astropy/utils/tests/data/local.dat.bz2
new file mode 100644
index 0000000..7518fba
Binary files /dev/null and b/astropy/utils/tests/data/local.dat.bz2 differ
diff --git a/astropy/utils/tests/data/local.dat.gz b/astropy/utils/tests/data/local.dat.gz
new file mode 100644
index 0000000..8ac4dd2
Binary files /dev/null and b/astropy/utils/tests/data/local.dat.gz differ
diff --git a/astropy/utils/tests/data/unicode.txt b/astropy/utils/tests/data/unicode.txt
new file mode 100644
index 0000000..723f2a6
--- /dev/null
+++ b/astropy/utils/tests/data/unicode.txt
@@ -0,0 +1,2 @@
+# -*- coding: utf-8 -*-
+האסטרונומי פייתון
diff --git a/astropy/utils/tests/test_console.py b/astropy/utils/tests/test_console.py
index f0d53d2..49bfbef 100644
--- a/astropy/utils/tests/test_console.py
+++ b/astropy/utils/tests/test_console.py
@@ -7,6 +7,8 @@ from astropy.tests.helper import raises
 
 from .. import console
 
+def test_color_text():
+    assert console._color_text("foo", "green") == u'\033[0;32mfoo\033[0m'
 
 def test_color_print():
     # This stuff is hard to test, at least smoke test it
diff --git a/astropy/utils/tests/test_data.py b/astropy/utils/tests/test_data.py
new file mode 100644
index 0000000..2e3e492
--- /dev/null
+++ b/astropy/utils/tests/test_data.py
@@ -0,0 +1,252 @@
+# Licensed under a 3-clause BSD style license - see LICENSE.rst
+from ...tests.helper import remote_data, raises
+
+import os
+import io
+
+import pytest
+from ..data import _get_download_cache_locs
+
+TESTURL = 'http://www.google.com/index.html'
+
+# General file object function
+
+
+ at remote_data
+def test_download_nocache():
+
+    from ..data import download_file
+
+    fnout = download_file(TESTURL)
+    assert os.path.isfile(fnout)
+
+
+ at remote_data
+def test_download_cache():
+
+    from ..data import download_file, clear_download_cache
+
+    fnout = download_file(TESTURL, cache=True)
+    assert os.path.isfile(fnout)
+    clear_download_cache(TESTURL)
+    assert not os.path.isfile(fnout)
+
+    lockdir = os.path.join(_get_download_cache_locs()[0], 'lock')
+    assert not os.path.isdir(lockdir), 'Cache dir lock was not released!'
+
+
+ at remote_data
+def test_url_nocache():
+
+    from ..data import get_readable_fileobj
+
+    with get_readable_fileobj(TESTURL, cache=False) as googlepage:
+        assert googlepage.read().find('oogle</title>') > -1
+
+ at remote_data
+def test_find_by_hash():
+
+    from ..data import get_readable_fileobj, get_pkg_data_filename, clear_download_cache
+
+    import hashlib
+
+    with get_readable_fileobj(TESTURL, encoding="binary", cache=True) as googlepage:
+        hash = hashlib.md5(googlepage.read())
+
+    hashstr = 'hash/' + hash.hexdigest()
+
+    fnout = get_pkg_data_filename(hashstr)
+    assert os.path.isfile(fnout)
+    clear_download_cache(hashstr[5:])
+    assert not os.path.isfile(fnout)
+
+    lockdir = os.path.join(_get_download_cache_locs()[0], 'lock')
+    assert not os.path.isdir(lockdir), 'Cache dir lock was not released!'
+
+
+# Package data functions
+ at pytest.mark.parametrize(('filename'), ['local.dat', 'local.dat.gz', 'local.dat.bz2'])
+def test_local_data_obj(filename):
+    from ..data import get_pkg_data_fileobj
+
+    with get_pkg_data_fileobj(os.path.join('data', filename), encoding='binary') as f:
+        f.readline()
+        assert f.read().rstrip() == b'CONTENT'
+
+
+ at pytest.mark.parametrize(('filename'), ['invalid.dat.gz', 'invalid.dat.bz2'])
+def test_local_data_obj_invalid(filename):
+    from ..data import get_pkg_data_fileobj
+
+    with get_pkg_data_fileobj(os.path.join('data', filename), encoding='binary') as f:
+        assert f.read().rstrip().endswith(b'invalid')
+
+
+def test_local_data_name():
+    from ..data import get_pkg_data_filename
+
+    fnout = get_pkg_data_filename('data/local.dat')
+    assert os.path.isfile(fnout) and fnout.endswith('local.dat')
+
+    #TODO: if in the future, the root data/ directory is added in, the below
+    #test should be uncommented and the README.rst should be replaced with
+    #whatever file is there
+
+    #get something in the astropy root
+    #fnout2 = get_pkg_data_filename('../../data/README.rst')
+    #assert os.path.isfile(fnout2) and fnout2.endswith('README.rst')
+
+
+ at raises(AssertionError)
+def test_local_data_nonlocalfail():
+    from ..data import get_pkg_data_filename
+
+    #this would go *outside* the atropy tree
+    get_pkg_data_filename('../../../data/README.rst')
+
+
+def test_compute_hash(tmpdir):
+    import hashlib
+    from ..data import compute_hash
+
+    rands = b'1234567890abcdefghijklmnopqrstuvwxyz'
+
+    filename = tmpdir.join('tmp.dat').strpath
+
+    with io.open(filename, 'wb') as ntf:
+        ntf.write(rands)
+        ntf.flush()
+
+    chhash = compute_hash(filename)
+    shash = hashlib.md5(rands).hexdigest()
+
+    assert chhash == shash
+
+
+def test_get_pkg_data_contents():
+    from ..data import get_pkg_data_fileobj, get_pkg_data_contents
+
+    with get_pkg_data_fileobj('data/local.dat') as f:
+        contents1 = f.read()
+
+    contents2 = get_pkg_data_contents('data/local.dat')
+
+    assert contents1 == contents2
+
+
+ at remote_data
+def test_data_noastropy_fallback(monkeypatch, recwarn):
+    """
+    Tests to make sure the default behavior when the cache directory can't
+    be located is correct
+    """
+    from pytest import raises
+    from .. import data
+    from ...config import paths
+
+    # needed for testing the *real* lock at the end
+    lockdir = os.path.join(_get_download_cache_locs()[0], 'lock')
+
+    #better yet, set the configuration to make sure the temp files are deleted
+    data.DELETE_TEMPORARY_DOWNLOADS_AT_EXIT.set(True)
+
+    #make sure the config and cache directories are not searched
+    monkeypatch.setenv('XDG_CONFIG_HOME', 'foo')
+    monkeypatch.delenv('XDG_CONFIG_HOME')
+    monkeypatch.setenv('XDG_CACHE_HOME', 'bar')
+    monkeypatch.delenv('XDG_CACHE_HOME')
+
+    # make sure the _find_or_create_astropy_dir function fails as though the
+    # astropy dir could not be accessed
+    def osraiser(dirnm, linkto):
+        raise OSError
+    monkeypatch.setattr(paths, '_find_or_create_astropy_dir', osraiser)
+
+    with raises(OSError):
+        #make sure the config dir search fails
+        paths.get_cache_dir()
+
+    #first try with cache
+    fnout = data.download_file(TESTURL, cache=True)
+    assert os.path.isfile(fnout)
+
+    assert len(recwarn.list) > 1
+    w1 = recwarn.pop()
+    w2 = recwarn.pop()
+
+    assert w1.category == data.CacheMissingWarning
+    assert 'Remote data cache could not be accessed' in w1.message.args[0]
+    assert w2.category == data.CacheMissingWarning
+    assert 'File downloaded to temporary location' in w2.message.args[0]
+    assert fnout == w2.message.args[1]
+
+    #clearing the cache should be a no-up that doesn't affect fnout
+    data.clear_download_cache(TESTURL)
+    assert os.path.isfile(fnout)
+
+    #now remove it so tests don't clutter up the temp dir
+    #this should get called at exit, anyway, but we do it here just to make
+    #sure it's working correctly
+    data._deltemps()
+    assert not os.path.isfile(fnout)
+
+    assert len(recwarn.list) > 0
+    w3 = recwarn.pop()
+
+    assert w3.category == data.CacheMissingWarning
+    assert 'Not clearing data cache - cache inacessable' in str(w3.message)
+
+    #now try with no cache
+    fnnocache = data.download_file(TESTURL, cache=False)
+    with open(fnnocache, 'rb') as googlepage:
+        assert googlepage.read().decode().find('oogle</title>') > -1
+
+    #no warnings should be raise in fileobj because cache is unnecessary
+    assert len(recwarn.list) == 0
+
+    # lockdir determined above as the *real* lockdir, not the temp one
+    assert not os.path.isdir(lockdir), 'Cache dir lock was not released!'
+
+
+def test_read_unicode():
+    from ..data import get_pkg_data_contents
+
+    contents = get_pkg_data_contents('data/unicode.txt', encoding='utf-8')
+    assert isinstance(contents, unicode)
+    contents = contents.splitlines()[1]
+    assert contents == u"\u05d4\u05d0\u05e1\u05d8\u05e8\u05d5\u05e0\u05d5\u05de\u05d9 \u05e4\u05d9\u05d9\u05ea\u05d5\u05df"
+
+    contents = get_pkg_data_contents('data/unicode.txt', encoding='binary')
+    assert isinstance(contents, bytes)
+    contents = contents.splitlines()[1]
+    assert contents == b"\xd7\x94\xd7\x90\xd7\xa1\xd7\x98\xd7\xa8\xd7\x95\xd7\xa0\xd7\x95\xd7\x9e\xd7\x99 \xd7\xa4\xd7\x99\xd7\x99\xd7\xaa\xd7\x95\xd7\x9f"
+
+
+def test_compressed_stream():
+    import base64
+    from ..data import get_readable_fileobj
+
+    gzipped_data = b"H4sICIxwG1AAA2xvY2FsLmRhdAALycgsVkjLzElVANKlxakpCpl5CiUZqQolqcUl8Tn5yYk58SmJJYnxWmCRzLx0hbTSvOSSzPy8Yi5nf78QV78QLgAlLytnRQAAAA=="
+    gzipped_data = base64.b64decode(gzipped_data)
+    assert isinstance(gzipped_data, bytes)
+
+    class FakeStream:
+        """
+        A fake stream that has `read`, but no `seek`.
+        """
+        def __init__(self, data):
+            self.data = data
+
+        def read(self, nbytes=None):
+            if nbytes is None:
+                result = self.data
+                self.data = b''
+            else:
+                result = self.data[:nbytes]
+                self.data = self.data[nbytes:]
+            return result
+
+    stream = FakeStream(gzipped_data)
+    with get_readable_fileobj(stream, encoding='binary') as f:
+        f.readline()
+        assert f.read().rstrip() == b'CONTENT'
diff --git a/astropy/utils/tests/test_misc.py b/astropy/utils/tests/test_misc.py
index c759941..8df3a97 100644
--- a/astropy/utils/tests/test_misc.py
+++ b/astropy/utils/tests/test_misc.py
@@ -3,6 +3,7 @@ from .. import misc
 
 #namedtuple is needed for find_mod_objs so it can have a non-local module
 from collections import namedtuple
+import warnings
 
 
 def test_pkg_finder():
@@ -18,109 +19,6 @@ def test_pkg_finder():
     assert misc.find_current_module(0, True).__name__ == mod3
 
 
-def test_fnpickling_simple(tmpdir):
-    """
-    Tests the `utils.misc.fnpickle` and `utils.misc.fnupickle` functions' basic
-    operation by pickling and unpickling a string, using both a filename and a
-    file.
-    """
-    fn = str(tmpdir.join('test1.pickle'))
-
-    obj1 = 'astring'
-    misc.fnpickle(obj1, fn)
-    res = misc.fnunpickle(fn)
-    assert obj1 == res
-
-    #try without cPickle
-    misc.fnpickle(obj1, fn, usecPickle=False)
-    res = misc.fnunpickle(fn, usecPickle=False)
-    assert obj1 == res
-
-    #now try with a file-like object instead of a string
-    with open(fn, 'wb') as f:
-        misc.fnpickle(obj1, f)
-    with open(fn, 'rb') as f:
-        res = misc.fnunpickle(f)
-        assert obj1 == res
-
-    #same without cPickle
-    with open(fn, 'wb') as f:
-        misc.fnpickle(obj1, f, usecPickle=False)
-    with open(fn, 'rb') as f:
-        res = misc.fnunpickle(f, usecPickle=False)
-        assert obj1 == res
-
-
-class ToBePickled(object):
-    def __init__(self, item):
-        self.item = item
-
-    def __eq__(self, other):
-        if isinstance(other, ToBePickled):
-            return self.item == other.item
-        else:
-            return False
-
-
-def test_fnpickling_class(tmpdir):
-    """
-    Tests the `utils.misc.fnpickle` and `utils.misc.fnupickle` functions'
-    ability to pickle and unpickle custom classes.
-    """
-    fn = str(tmpdir.join('test2.pickle'))
-
-    obj1 = 'astring'
-    obj2 = ToBePickled(obj1)
-    misc.fnpickle(obj2, fn)
-    res = misc.fnunpickle(fn)
-    assert res == obj2
-
-
-def test_fnpickling_protocol(tmpdir):
-    """
-    Tests the `utils.misc.fnpickle` and `utils.misc.fnupickle` functions'
-    ability to pickle and unpickle pickle files from all protcols.
-    """
-    import pickle
-
-    obj1 = 'astring'
-    obj2 = ToBePickled(obj1)
-
-    for p in range(pickle.HIGHEST_PROTOCOL + 1):
-        fn = str(tmpdir.join('testp%i.pickle' % p))
-        misc.fnpickle(obj2, fn, protocol=p)
-        res = misc.fnunpickle(fn)
-        assert res == obj2
-
-
-def test_fnpickling_many(tmpdir):
-    """
-    Tests the `utils.misc.fnpickle` and `utils.misc.fnupickle` functions'
-    ability to pickle and unpickle multiple objects from a single file.
-    """
-    from pytest import raises
-
-    fn = str(tmpdir.join('test3.pickle'))
-
-    #now try multiples
-    obj3 = 328.3432
-    obj4 = 'blahblahfoo'
-    misc.fnpickle(obj3, fn)
-    misc.fnpickle(obj4, fn, append=True)
-
-    res = misc.fnunpickle(fn, number=-1)
-    assert len(res) == 2
-    assert res[0] == obj3
-    assert res[1] == obj4
-
-    misc.fnpickle(obj4, fn, append=True)
-    res = misc.fnunpickle(fn, number=2)
-    assert len(res) == 2
-
-    with raises(EOFError):
-        misc.fnunpickle(fn, number=5)
-
-
 def test_find_mod_objs():
     lnms, fqns, objs = misc.find_mod_objs('astropy')
 
@@ -148,7 +46,7 @@ def test_find_mod_objs():
 
 def test_find_current_mod():
     from sys import getrecursionlimit
-    from pytest import raises
+    from ...tests.helper import pytest
 
     thismodnm = __name__
 
@@ -160,7 +58,7 @@ def test_find_current_mod():
     assert misc.find_current_module(0, [misc]).__name__ == thismodnm
     assert misc.find_current_module(0, ['astropy.utils.misc']).__name__ == thismodnm
 
-    with raises(ImportError):
+    with pytest.raises(ImportError):
         misc.find_current_module(0, ['faddfdsasewrweriopunjlfiurrhujnkflgwhu'])
 
 
@@ -172,3 +70,32 @@ def test_isiterable():
     assert misc.isiterable([1, 2, 3]) is True
     assert misc.isiterable(array(2)) is False
     assert misc.isiterable(array([1, 2, 3])) is True
+
+
+def test_deprecated_attribute():
+    class DummyClass:
+        def __init__(self):
+            self._foo = 42
+
+        def set_private(self):
+            self._foo = 100
+
+        foo = misc.deprecated_attribute('foo', '0.2')
+
+    dummy = DummyClass()
+
+    with warnings.catch_warnings(record=True) as w:
+        warnings.resetwarnings()
+        warnings.simplefilter('always')
+        x = dummy.foo
+
+    assert len(w) == 1
+    assert str(w[0].message) == ("The foo attribute is deprecated and may be "
+                                 "removed in a future version.")
+
+    with warnings.catch_warnings(record=True) as w:
+        warnings.resetwarnings()
+        warnings.simplefilter('always')
+        dummy.set_private()
+
+    assert len(w) == 0
diff --git a/astropy/utils/xml/iterparser.py b/astropy/utils/xml/iterparser.py
index b67ad74..e418c03 100644
--- a/astropy/utils/xml/iterparser.py
+++ b/astropy/utils/xml/iterparser.py
@@ -9,6 +9,9 @@ import contextlib
 import io
 import sys
 
+# ASTROPY
+from .. import data
+
 
 __all__ = ['get_xml_iterator', 'get_xml_encoding', 'xml_readlines']
 
@@ -47,20 +50,25 @@ def _convert_to_fd_or_read_function(fd):
        - If it's not a real file object, it's much handier to just
          have a Python function to call.
 
+    This is somewhat quirky behavior, of course, which is why it is
+    private.  For a more useful version of similar behavior, see
+    `astropy.utils.misc.get_readable_fileobj`.
+
     Parameters
     ----------
     fd : object
         May be:
 
-            - a file object, in which case it is returned verbatim.
+            - a file object.  If the file is uncompressed, this raw
+              file object is returned verbatim.  Otherwise, the read
+              method is returned.
 
             - a function that reads from a stream, in which case it is
               returned verbatim.
 
-            - a file path, in which case it is opened.  If it ends in
-              `.gz`, it is assumed to be a gzipped file, and the
-              :meth:`read` method on the file object is returned.
-              Otherwise, the raw file object is returned.
+            - a file path, in which case it is opened.  Again, like a
+              file object, if it's uncompressed, a raw file object is
+              returned, otherwise its read method.
 
             - an object with a :meth:`read` method, in which case that
               method is returned.
@@ -73,50 +81,23 @@ def _convert_to_fd_or_read_function(fd):
     if is_callable(fd):
         yield fd
         return
-    elif isinstance(fd, basestring):
-        if fd.endswith('.gz'):
-            from ...utils.compat import gzip
-            with gzip.GzipFile(fd, 'rb') as real_fd:
-                yield real_fd.read
-                return
+
+    from astropy.utils.data import get_readable_fileobj
+
+    with get_readable_fileobj(fd, encoding='binary') as new_fd:
+        if sys.platform.startswith('win'):
+            yield new_fd.read
         else:
-            with open(fd, 'rb') as real_fd:
-                if sys.platform.startswith('win'):
-                    # On Windows, we can't pass a real file descriptor
-                    # to the C level, so we pass the read method
-                    yield real_fd.read
-                    return
-                yield real_fd
-                return
-    elif hasattr(fd, 'read'):
-        assert is_callable(fd.read)
-        magic = fd.read(2)
-        fd.seek(0)
-        if magic == b'\x1f\x8b':
-            from ...utils.compat import gzip
-            fd = gzip.GzipFile(fileobj=fd)
-
-        if type(fd.read(0)) == type(u''):
-            def make_encoder(reader):
-                def read(n):
-                    return reader(n).encode('utf-8')
-            yield make_encoder(fd.read)
-            return
-
-        if not sys.platform.startswith('win'):
             if IS_PY3K:
-                if isinstance(fd, io.FileIO):
-                    yield fd
-                    return
+                if isinstance(new_fd, io.FileIO):
+                    yield new_fd
+                else:
+                    yield new_fd.read
             else:
-                if isinstance(fd, file):
-                    yield fd
-                    return
-
-        yield fd.read
-        return
-    else:
-        raise TypeError("Can not be coerced to read function")
+                if isinstance(new_fd, file):
+                    yield new_fd
+                else:
+                    yield new_fd.read
 
 
 def _fast_iterparse(fd, buffersize=2 ** 10):
@@ -230,7 +211,8 @@ def get_xml_encoding(source):
         if not start or tag != u'xml':
             raise IOError('Invalid XML file')
 
-    return data['encoding']
+    # The XML spec says that no encoding === utf-8
+    return data.get('encoding') or 'utf-8'
 
 
 def xml_readlines(source):
@@ -248,7 +230,8 @@ def xml_readlines(source):
     """
     encoding = get_xml_encoding(source)
 
-    with io.open(source, 'rt', encoding=encoding) as input:
+    with data.get_readable_fileobj(source, encoding=encoding) as input:
+        input.seek(0)
         xml_lines = input.readlines()
 
     return xml_lines
diff --git a/astropy/utils/xml/setup_package.py b/astropy/utils/xml/setup_package.py
index 0bdf042..efb9de8 100644
--- a/astropy/utils/xml/setup_package.py
+++ b/astropy/utils/xml/setup_package.py
@@ -2,37 +2,53 @@ from distutils.core import Extension
 from os.path import join
 import sys
 
+from astropy import setup_helpers
+
+
+def get_external_libraries():
+    return ['expat']
+
 
 def get_extensions(build_type='release'):
-    EXPAT_DIR = 'cextern/expat/lib'
     XML_DIR = 'astropy/utils/xml/src'
 
-    defines = [("HAVE_EXPAT_CONFIG_H", 1)]
-    if sys.byteorder == 'big':
-        defines.append(('BYTEORDER', '4321'))
-    else:
-        defines.append(('BYTEORDER', '1234'))
-    if sys.platform != 'win32':
-        defines.append(('HAVE_UNISTD_H', None))
-
-    if sys.platform.startswith('linux'):
-        # This is to ensure we only export the Python entry point
-        # symbols and the linker won't try to use the system expat in
-        # place of ours.
-        extra_link_args = [
-            '-Wl,--version-script={0}'.format(
-                join(XML_DIR, 'iterparse.map'))
-            ]
+    source_files = [join(XML_DIR, "iterparse.c")]
+    include_dirs = []
+    extra_link_args = []
+    defines = []
+    libraries = []
+    library_dirs = []
+
+    if setup_helpers.use_system_library('expat'):
+        setup_helpers.pkg_config(
+            ['expat'], ['expat'], include_dirs, library_dirs, libraries)
     else:
-        extra_link_args = []
+        EXPAT_DIR = 'cextern/expat/lib'
+        source_files.extend([
+            join(EXPAT_DIR, fn) for fn in
+            ["xmlparse.c", "xmlrole.c", "xmltok.c", "xmltok_impl.c"]])
+        include_dirs.extend([XML_DIR, EXPAT_DIR])
+        if sys.platform.startswith('linux'):
+            # This is to ensure we only export the Python entry point
+            # symbols and the linker won't try to use the system expat in
+            # place of ours.
+            extra_link_args.append(
+                '-Wl,--version-script={0}'.format(
+                    join(XML_DIR, 'iterparse.map'))
+                )
+        defines = [("HAVE_EXPAT_CONFIG_H", 1)]
+        if sys.byteorder == 'big':
+            defines.append(('BYTEORDER', '4321'))
+        else:
+            defines.append(('BYTEORDER', '1234'))
+        if sys.platform != 'win32':
+            defines.append(('HAVE_UNISTD_H', None))
 
     return [Extension(
         "astropy.utils.xml._iterparser",
-        [join(XML_DIR, "iterparse.c"),
-         join(EXPAT_DIR, "xmlparse.c"),
-         join(EXPAT_DIR, "xmlrole.c"),
-         join(EXPAT_DIR, "xmltok.c"),
-         join(EXPAT_DIR, "xmltok_impl.c")],
+        source_files,
         define_macros=defines,
-        include_dirs=[XML_DIR, EXPAT_DIR],
+        include_dirs=include_dirs,
+        library_dirs=library_dirs,
+        libraries=libraries,
         extra_link_args=extra_link_args)]
diff --git a/astropy/utils/xml/src/iterparse.c b/astropy/utils/xml/src/iterparse.c
index 4a6f212..a524c06 100644
--- a/astropy/utils/xml/src/iterparse.c
+++ b/astropy/utils/xml/src/iterparse.c
@@ -11,8 +11,8 @@
  *     faster and more memory efficient than the alternatives in the
  *     Python standard library because it does not build a tree of
  *     objects, and also throws away most text nodes, since for
- *     astropy.io.vo (the primary user of this library) we only care
- *     about simple text nodes contained between a single pair of
+ *     astropy.io.votable (the primary user of this library) we only
+ *     care about simple text nodes contained between a single pair of
  *     open/close element nodes.  It also has an optimization for
  *     recognizing the most commonly occuring element in a VO file,
  *     "TD".
diff --git a/astropy/version.py b/astropy/version.py
index c2a4336..43b6f94 100644
--- a/astropy/version.py
+++ b/astropy/version.py
@@ -1,12 +1,14 @@
-# Autogenerated by Astropy's setup.py on 2012-06-19 02:09:53.770030
+# Autogenerated by Astropy's setup.py on 2012-12-24 15:42:13.215854
 
-from astropy.version_helper import _update_git_devstr, get_git_devstr
+from astropy.version_helper import update_git_devstr, get_git_devstr
 
-version = _update_git_devstr('0.1')
+_last_generated_version = '0.2b1'
+
+version = update_git_devstr(_last_generated_version)
 githash = get_git_devstr(sha=True, show_warning=False)
 
 major = 0
-minor = 1
+minor = 2
 bugfix = 0
 
 release = True
diff --git a/astropy/version_helper.py b/astropy/version_helper.py
index d6d54c4..c04cc16 100644
--- a/astropy/version_helper.py
+++ b/astropy/version_helper.py
@@ -26,14 +26,18 @@ def _version_split(version):
     optional, defaulting to 0).
     """
 
-    versplit = version.split('.dev')[0].split('.')
+    for prerel in ('.dev', 'a', 'b', 'rc'):
+        if prerel in version:
+            version = version.split(prerel)[0]
+
+    versplit = version.split('.')
     major = int(versplit[0])
     minor = int(versplit[1])
     bugfix = 0 if len(versplit) < 3 else int(versplit[2])
     return major, minor, bugfix
 
 
-def _update_git_devstr(version, path=None):
+def update_git_devstr(version, path=None):
     """
     Updates the git revision string if and only if the path is being imported
     directly from a git working copy.  This ensures that the revision number in
@@ -135,13 +139,17 @@ def get_git_devstr(sha=False, show_warning=True, path=None):
 
 
 # This is used by setup.py to create a new version.py - see that file for
-# details
-_frozen_version_py_template = """
+# details. Note that the imports have to be absolute, since this is also used
+# by affiliated packages.
+
+_FROZEN_VERSION_PY_TEMPLATE = """
 # Autogenerated by {packagename}'s setup.py on {timestamp}
 
-from astropy.version_helper import _update_git_devstr, get_git_devstr
+from astropy.version_helper import update_git_devstr, get_git_devstr
 
-version = _update_git_devstr({verstr!r})
+_last_generated_version = {verstr!r}
+
+version = update_git_devstr(_last_generated_version)
 githash = get_git_devstr(sha=True, show_warning=False)
 
 major = {major}
@@ -168,7 +176,7 @@ def _get_version_py_str(packagename, version, release, debug):
         packagename = 'Astropy'
     else:
         packagename = 'Astropy-affiliated package ' + packagename
-    return _frozen_version_py_template.format(packagename=packagename,
+    return _FROZEN_VERSION_PY_TEMPLATE.format(packagename=packagename,
                                               timestamp=timestamp,
                                               verstr=version,
                                               major=major,
@@ -177,7 +185,7 @@ def _get_version_py_str(packagename, version, release, debug):
                                               rel=release, debug=debug)
 
 
-def generate_version_py(packagename, version, release, debug=None):
+def generate_version_py(packagename, version, release=None, debug=None):
     """Regenerate the version.py module if necessary."""
 
     from .setup_helpers import is_distutils_display_option
@@ -188,23 +196,33 @@ def generate_version_py(packagename, version, release, debug=None):
 
     try:
         version_module = __import__(packagename + '.version',
-                                    fromlist=['version', 'release', 'debug'])
-        current_version = version_module.version
+                                    fromlist=['_last_generated_version',
+                                              'version', 'release', 'debug'])
+        try:
+            last_generated_version = version_module._last_generated_version
+        except AttributeError:
+            # Older version.py with no _last_generated_version; this will
+            # ensure a new version.py is written
+            last_generated_version = None
         current_release = version_module.release
         current_debug = version_module.debug
     except ImportError:
         version_module = None
-        current_version = None
+        last_generated_version = None
         current_release = None
         current_debug = None
 
-    if debug is None:
+    if release is None:
         # Keep whatever the current value is, if it exists
+        release = bool(current_release)
+
+    if debug is None:
+        # Likewise, keep whatever the current value is, if it exists
         debug = bool(current_debug)
 
     version_py = os.path.join(packagename, 'version.py')
 
-    if (current_version != version or current_release != release or
+    if (last_generated_version != version or current_release != release or
         current_debug != debug):
         if '-q' not in sys.argv and '--quiet' not in sys.argv:
             log.set_threshold(log.INFO)
diff --git a/astropy/wcs/__init__.py b/astropy/wcs/__init__.py
index c605ec0..b1f6a33 100644
--- a/astropy/wcs/__init__.py
+++ b/astropy/wcs/__init__.py
@@ -24,7 +24,4 @@ from __future__ import division  # confidence high
 if not _ASTROPY_SETUP_:
     from .wcs import *
 
-    class Wcsprm(Wcsprm):
-        pass
-
     pass
diff --git a/astropy/wcs/_docutil.py b/astropy/wcs/_docutil.py
index 0f32ed8..68411c3 100644
--- a/astropy/wcs/_docutil.py
+++ b/astropy/wcs/_docutil.py
@@ -14,16 +14,17 @@ def _fix(content, indent=0):
     return indent.join(lines)
 
 
-def TWO_OR_THREE_ARGS(naxis, indent=0):
+def TWO_OR_MORE_ARGS(naxis, indent=0):
     return _fix(
 """args : flexible
-    Either two or three arguments may be provided.
+    There are two accepted forms for the positional arguments:
 
-        - 2 arguments: An *N* x *{0}* array of *x*- and
-          *y*-coordinates, and an *origin*.
+        - 2 arguments: An *N* x *{0}* array of coordinates, and an
+          *origin*.
 
-        - 3 arguments: 2 one-dimensional arrays of *x* and *y*
-          coordinates, and an *origin*.
+        - more than 2 arguments: An array for each axis, followed by
+          an *origin*.  These arrays must be broadcastable to one
+          another.
 
     Here, *origin* is the coordinate in the upper left corner of the
     image.  In FITS and Fortran standards, this is 1.  In Numpy and C
@@ -54,5 +55,6 @@ def RA_DEC_ORDER(indent=0):
 ra_dec_order : bool, optional
     When `True` will ensure that world coordinates are always given
     and returned in as (*ra*, *dec*) pairs, regardless of the order of
-    the axes specified by the in the ``CTYPE`` keywords.
+    the axes specified by the in the ``CTYPE`` keywords.  Default is
+    `False`.
 """, indent)
diff --git a/astropy/wcs/docstrings.py b/astropy/wcs/docstrings.py
index 3a12cd7..6a878c4 100644
--- a/astropy/wcs/docstrings.py
+++ b/astropy/wcs/docstrings.py
@@ -400,7 +400,8 @@ understood by the lower-level projection routines.
 """
 
 cunit = """
-``list of strings[naxis]`` List of ``CUNITia`` keyvalues.
+``list of astropy.UnitBase[naxis]`` List of ``CUNITia`` keyvalues as
+`astropy.units.UnitBase` instances.
 
 These define the units of measurement of the ``CRVALia``, ``CDELTia``
 and ``CDi_ja`` keywords.
@@ -620,7 +621,7 @@ keysel : sequence of flags
 
 Returns
 -------
-wcs_list : list of `~astropy.wcs._astropy.wcs._Wcsprm` objects
+wcs_list : list of `~astropy.wcs._astropy.wcs.Wcsprm` objects
 """
 
 fix = """
@@ -2003,16 +2004,21 @@ a units specification where it does not create ambiguity (e.g. not
 between a metric prefix and a basic unit string), including in strings
 like ``"log (m ** 2)"`` which is formally disallowed.
 
+.. note:: Deprecated in Astropy 0.2
+
+   `UnitConverter` will be removed in a future version of astropy.
+   The `astropy.units` package should be used instead.
+
 Parameters
 ----------
 
 have : string
-    :ref:`fits-unit` to convert from, with or without surrounding
+    FITS unit string to convert from, with or without surrounding
     square brackets (for inline specifications); text following the
     closing bracket is ignored.
 
 want : string
-    :ref:`fits-unit` to convert to, with or without surrounding square
+    FITS unit string to convert to, with or without surrounding square
     brackets (for inline specifications); text following the closing
     bracket is ignored.
 
@@ -2037,8 +2043,6 @@ ctrl : string, optional
     Thus ``''`` doesn't do any unsafe translations, whereas ``'shd'``
     does all of them.
 
-    See :ref:`fits-unit` for more information.
-
 Raises
 ------
 ValueError
@@ -2109,8 +2113,6 @@ translate_units : string, optional
     Thus ``''`` doesn't do any unsafe translations, whereas ``'shd'``
     does all of them.
 
-    See :ref:`fits-unit` for more information.
-
 Returns
 -------
 success : int
@@ -2177,7 +2179,7 @@ det2im : A pair of `~astropy.wcs.DistortionLookupTable` objects, or
 Wcsprm = """
 Wcsprm(header=None, key=' ', relax=False, naxis=2, keysel=0, colsel=None)
 
-`~astropy.wcs.Wcsprm` is a direct wrapper around `wcslib`_, and
+`~astropy.wcs.Wcsprm` is a direct wrapper around `wcslib`_.  It
 provides access to the core WCS transformations that it supports.
 
 The FITS header parsing enforces correct FITS "keyword = value" syntax
@@ -2188,7 +2190,7 @@ Sect. 5.2.1), integer (Sect. 5.2.3), and floating-point values
 
 Parameters
 ----------
-header : An astropy.io.fits header, string, or `None`.
+header : An `astropy.io.fits.Header`, string, or `None`.
   If ``None``, the object will be initialized to default values.
 
 key : string, optional
diff --git a/astropy/wcs/include/docstrings.h b/astropy/wcs/include/docstrings.h
index 9f9eaba..f7489e1 100644
--- a/astropy/wcs/include/docstrings.h
+++ b/astropy/wcs/include/docstrings.h
@@ -17,9 +17,9 @@ extern char doc_K[202];
 extern char doc_M[56];
 extern char doc_Sip[1040];
 extern char doc_Tabprm[234];
-extern char doc_UnitConverter[2246];
+extern char doc_UnitConverter[2358];
 extern char doc_Wcs[513];
-extern char doc_Wcsprm[2089];
+extern char doc_Wcsprm[2091];
 extern char doc_Wtbarr[202];
 extern char doc_a[264];
 extern char doc_a_order[60];
@@ -53,7 +53,7 @@ extern char doc_crval_tabprm[94];
 extern char doc_csyer[132];
 extern char doc_ctype[228];
 extern char doc_cubeface[1236];
-extern char doc_cunit[1272];
+extern char doc_cunit[1319];
 extern char doc_cylfix[162];
 extern char doc_data[78];
 extern char doc_data_wtbarr[52];
@@ -70,7 +70,7 @@ extern char doc_extlev[73];
 extern char doc_extnam[74];
 extern char doc_extrema[452];
 extern char doc_extver[73];
-extern char doc_find_all_wcs[880];
+extern char doc_find_all_wcs[879];
 extern char doc_fix[1613];
 extern char doc_get_cdelt[452];
 extern char doc_get_offset[206];
@@ -140,7 +140,7 @@ extern char doc_tab[112];
 extern char doc_theta0[289];
 extern char doc_to_header[2229];
 extern char doc_ttype[108];
-extern char doc_unitfix[1098];
+extern char doc_unitfix[1050];
 extern char doc_velangl[186];
 extern char doc_velosys[316];
 extern char doc_want[173];
diff --git a/astropy/wcs/include/pyutil.h b/astropy/wcs/include/pyutil.h
index 24e2a6a..a0ecec0 100644
--- a/astropy/wcs/include/pyutil.h
+++ b/astropy/wcs/include/pyutil.h
@@ -40,15 +40,12 @@ PyArrayReadOnlyProxy_New(
     int typenum,
     const void* data);
 
-typedef int (*str_verify_fn)(char *);
-
 /*@null@*/ PyObject *
 PyStrListProxy_New(
     PyObject* owner,
     Py_ssize_t size,
     Py_ssize_t maxsize,
-    char (*array)[72],
-    str_verify_fn verify
+    char (*array)[72]
     );
 
 int
@@ -302,18 +299,6 @@ set_int_array(
     int* dest);
 
 static INLINE PyObject*
-get_str_list_verified(
-    /*@unused@*/ const char* propname,
-    char (*array)[72],
-    Py_ssize_t len,
-    Py_ssize_t maxlen,
-    PyObject* owner,
-    str_verify_fn verify) {
-
-  return PyStrListProxy_New(owner, len, maxlen, array, verify);
-}
-
-static INLINE PyObject*
 get_str_list(
     /*@unused@*/ const char* propname,
     char (*array)[72],
@@ -321,28 +306,16 @@ get_str_list(
     Py_ssize_t maxlen,
     PyObject* owner) {
 
-  return get_str_list_verified(propname, array, len, maxlen, owner, NULL);
+  return PyStrListProxy_New(owner, len, maxlen, array);
 }
 
 int
-set_str_list_verified(
-    const char* propname,
-    PyObject* value,
-    Py_ssize_t len,
-    Py_ssize_t maxlen,
-    char (*dest)[72],
-    str_verify_fn verify);
-
-static INLINE int
 set_str_list(
     const char* propname,
     PyObject* value,
     Py_ssize_t len,
     Py_ssize_t maxlen,
-    char (*dest)[72]) {
-
-  return set_str_list_verified(propname, value, len, maxlen, dest, NULL);
-}
+    char (*dest)[72]);
 
 PyObject*
 get_pscards(
diff --git a/astropy/wcs/include/str_list_proxy.h b/astropy/wcs/include/str_list_proxy.h
index 6e1def1..b646265 100644
--- a/astropy/wcs/include/str_list_proxy.h
+++ b/astropy/wcs/include/str_list_proxy.h
@@ -22,10 +22,15 @@ PyStrListProxy_New(
     PyObject* owner,
     Py_ssize_t size,
     Py_ssize_t maxsize,
-    char (*array)[72],
-    str_verify_fn verify
+    char (*array)[72]
     );
 
+/*@null@*/ PyObject*
+str_list_proxy_repr(
+    char (*array)[72],
+    Py_ssize_t size,
+    Py_ssize_t maxsize);
+
 int
 _setup_str_list_proxy_type(
     PyObject* m);
diff --git a/astropy/wcs/include/unit_list_proxy.h b/astropy/wcs/include/unit_list_proxy.h
new file mode 100644
index 0000000..875346f
--- /dev/null
+++ b/astropy/wcs/include/unit_list_proxy.h
@@ -0,0 +1,47 @@
+/*
+ Author: Michael Droettboom
+         mdroe at stsci.edu
+*/
+
+#ifndef __UNIT_LIST_PROXY_H__
+#define __UNIT_LIST_PROXY_H__
+
+#include "pyutil.h"
+
+/***************************************************************************
+ * List-of-units proxy object
+ *
+ * A Python object that looks like a list of units, but is back by a C
+ *   char * list[];
+ ***************************************************************************/
+
+/*@null@*/ PyObject *
+PyUnitListProxy_New(
+    PyObject* owner,
+    Py_ssize_t size,
+    char (*array)[72]
+    );
+
+int
+_setup_unit_list_proxy_type(
+    PyObject* m);
+
+static INLINE PyObject*
+get_unit_list(
+    /*@unused@*/ const char* propname,
+    char (*array)[72],
+    Py_ssize_t len,
+    PyObject* owner) {
+
+  return PyUnitListProxy_New(owner, len, array);
+}
+
+int
+set_unit_list(
+    PyObject *owner,
+    const char* propname,
+    PyObject* value,
+    Py_ssize_t len,
+    char (*dest)[72]);
+
+#endif /* __UNIT_LIST_PROXY_H__ */
diff --git a/astropy/wcs/setup_package.py b/astropy/wcs/setup_package.py
index 26749ce..4b5775c 100644
--- a/astropy/wcs/setup_package.py
+++ b/astropy/wcs/setup_package.py
@@ -198,37 +198,59 @@ MSVC, do not support string literals greater than 256 characters.
 def get_extensions():
     from astropy.version import debug
 
-    write_wcsconfig_h()
     generate_c_docstrings()
 
     ######################################################################
-    # WCSLIB
-    wcslib_path = join(WCSROOT, "src", "wcslib")  # Path to wcslib
-    wcslib_cpath = join(wcslib_path, "C")  # Path to wcslib source files
-    wcslib_files = [  # List of wcslib files to compile
-        'flexed/wcsbth.c',
-        'flexed/wcspih.c',
-        'flexed/wcsulex.c',
-        'flexed/wcsutrn.c',
-        'cel.c',
-        'lin.c',
-        'log.c',
-        'prj.c',
-        'spc.c',
-        'sph.c',
-        'spx.c',
-        'tab.c',
-        'wcs.c',
-        'wcserr.c',
-        'wcsfix.c',
-        'wcshdr.c',
-        'wcsprintf.c',
-        'wcsunits.c',
-        'wcsutil.c']
-    wcslib_files = [join(wcslib_cpath, x) for x in wcslib_files]
+    # DISTUTILS SETUP
+    source_files = []
+    libraries = []
+    include_dirs = [
+        'numpy',
+        join(WCSROOT, "include")]
+
+    library_dirs = []
+    define_macros = [
+        ('ECHO', None),
+        ('WCSTRIG_MACRO', None),
+        ('ASTROPY_WCS_BUILD', None),
+        ('_GNU_SOURCE', None),
+        ('WCSVERSION', WCSVERSION)]
+    undef_macros = []
+    extra_compile_args = []
+    extra_link_args = []
+
+    if (not setup_helpers.use_system_library('wcslib') or
+        sys.platform == 'win32'):
+        write_wcsconfig_h()
+
+        wcslib_path = join("cextern", "wcslib")  # Path to wcslib
+        wcslib_cpath = join(wcslib_path, "C")  # Path to wcslib source files
+        wcslib_files = [  # List of wcslib files to compile
+            'flexed/wcsbth.c',
+            'flexed/wcspih.c',
+            'flexed/wcsulex.c',
+            'flexed/wcsutrn.c',
+            'cel.c',
+            'lin.c',
+            'log.c',
+            'prj.c',
+            'spc.c',
+            'sph.c',
+            'spx.c',
+            'tab.c',
+            'wcs.c',
+            'wcserr.c',
+            'wcsfix.c',
+            'wcshdr.c',
+            'wcsprintf.c',
+            'wcsunits.c',
+            'wcsutil.c']
+        source_files.extend(join(wcslib_cpath, x) for x in wcslib_files)
+        include_dirs.append(wcslib_cpath)
+    else:
+        setup_helpers.pkg_config(
+            ['wcslib'], ['wcs'], include_dirs, library_dirs, libraries)
 
-    ######################################################################
-    # ASTROPY.WCS-SPECIFIC AND WRAPPER SOURCE FILES
     astropy_wcs_files = [  # List of astropy.wcs files to compile
         'distortion.c',
         'distortion_wrap.c',
@@ -240,31 +262,19 @@ def get_extensions():
         'sip.c',
         'sip_wrap.c',
         'str_list_proxy.c',
+        'unit_list_proxy.c',
         'util.c',
         'wcslib_wrap.c',
         'wcslib_tabprm_wrap.c',
         'wcslib_units_wrap.c',
         'wcslib_wtbarr_wrap.c']
-    astropy_wcs_files = [join(WCSROOT, 'src', x) for x in astropy_wcs_files]
-
-    ######################################################################
-    # DISTUTILS SETUP
-    libraries = []
-    define_macros = [
-        ('ECHO', None),
-        ('WCSTRIG_MACRO', None),
-        ('ASTROPY_WCS_BUILD', None),
-        ('_GNU_SOURCE', None),
-        ('WCSVERSION', WCSVERSION)]
-    undef_macros = []
-    extra_compile_args = []
-    extra_link_args = []
+    source_files.extend(join(WCSROOT, 'src', x) for x in astropy_wcs_files)
 
     if debug:
         define_macros.append(('DEBUG', None))
         undef_macros.append('NDEBUG')
-        if not sys.platform.startswith('sun') and \
-           not sys.platform == 'win32':
+        if (not sys.platform.startswith('sun') and
+            not sys.platform == 'win32'):
             extra_compile_args.extend(["-fno-inline", "-O0", "-g"])
     else:
         # Define ECHO as nothing to prevent spurious newlines from
@@ -281,23 +291,21 @@ def get_extensions():
             ('_NO_OLDNAMES', None),  # for mingw32
             ('NO_OLDNAMES', None),  # for mingw64
             ('__STDC__', None)  # for MSVC
-            ])
+        ])
 
     if sys.platform.startswith('linux'):
         define_macros.append(('HAVE_SINCOS', None))
 
     return [
         Extension('astropy.wcs._wcs',
-                  wcslib_files + astropy_wcs_files,
-                  include_dirs=[
-                      setup_helpers.get_numpy_include_path(),
-                      wcslib_cpath,
-                      join(WCSROOT, "include")],
+                  source_files,
+                  include_dirs=include_dirs,
                   define_macros=define_macros,
                   undef_macros=undef_macros,
                   extra_compile_args=extra_compile_args,
                   extra_link_args=extra_link_args,
-                  libraries=libraries)]
+                  libraries=libraries,
+                  library_dirs=library_dirs)]
 
 
 def get_package_data():
@@ -310,3 +318,7 @@ def get_package_data():
 
 def get_legacy_alias():
     return setup_helpers.add_legacy_alias('pywcs', 'astropy.wcs', '1.11')
+
+
+def get_external_libraries():
+    return ['wcslib']
diff --git a/astropy/wcs/src/astropy_wcs.c b/astropy/wcs/src/astropy_wcs.c
index b503441..e8035d3 100644
--- a/astropy/wcs/src/astropy_wcs.c
+++ b/astropy/wcs/src/astropy_wcs.c
@@ -12,6 +12,7 @@
 #include "sip_wrap.h"
 #include "docstrings.h"
 #include "astropy_wcs_api.h"
+#include "unit_list_proxy.h"
 
 #include <structmember.h> /* from Python */
 
@@ -969,6 +970,7 @@ struct module_state {
 
   if (_setup_api(m)                 ||
       _setup_str_list_proxy_type(m) ||
+      _setup_unit_list_proxy_type(m)||
       _setup_wcsprm_type(m)         ||
       _setup_tabprm_type(m)         ||
       _setup_units_type(m)          ||
diff --git a/astropy/wcs/src/docstrings.c b/astropy/wcs/src/docstrings.c
index 47daf70..31f0eae 100644
--- a/astropy/wcs/src/docstrings.c
+++ b/astropy/wcs/src/docstrings.c
@@ -17,9 +17,9 @@ char doc_K[202];
 char doc_M[56];
 char doc_Sip[1040];
 char doc_Tabprm[234];
-char doc_UnitConverter[2246];
+char doc_UnitConverter[2358];
 char doc_Wcs[513];
-char doc_Wcsprm[2089];
+char doc_Wcsprm[2091];
 char doc_Wtbarr[202];
 char doc_a[264];
 char doc_a_order[60];
@@ -53,7 +53,7 @@ char doc_crval_tabprm[94];
 char doc_csyer[132];
 char doc_ctype[228];
 char doc_cubeface[1236];
-char doc_cunit[1272];
+char doc_cunit[1319];
 char doc_cylfix[162];
 char doc_data[78];
 char doc_data_wtbarr[52];
@@ -70,7 +70,7 @@ char doc_extlev[73];
 char doc_extnam[74];
 char doc_extrema[452];
 char doc_extver[73];
-char doc_find_all_wcs[880];
+char doc_find_all_wcs[879];
 char doc_fix[1613];
 char doc_get_cdelt[452];
 char doc_get_offset[206];
@@ -140,7 +140,7 @@ char doc_tab[112];
 char doc_theta0[289];
 char doc_to_header[2229];
 char doc_ttype[108];
-char doc_unitfix[1098];
+char doc_unitfix[1050];
 char doc_velangl[186];
 char doc_velosys[316];
 char doc_want[173];
@@ -165,28 +165,29 @@ void fill_docstrings(void)
    strncpy(doc_Tabprm + 0, "A class to store the information related to tabular coordinates,\ni.e., coordinates that are defined via a lookup table.\n\nThis class can not be constructed directly from Python, but instead is\nreturned from `~astropy.wcs.Wcsprm.tab`.\n\x00", 234);
 
    strncpy(doc_UnitConverter + 0, "UnitConverter(have, want, translate_units=\'\')\n\nAn object for converting from one system of units to another.\n\nUse the returned object\'s `~astropy.wcs.UnitConverter.convert` method\nto convert values from *have* to *want*.\n\nThis function is permissive in acc", 256);
-   strncpy(doc_UnitConverter + 256, "epting whitespace in all contexts in\na units specification where it does not create ambiguity (e.g. not\nbetween a metric prefix and a basic unit string), including in strings\nlike ``\"log (m ** 2)\"`` which is formally disallowed.\n\nParameters\n----------\n\nhav", 256);
-   strncpy(doc_UnitConverter + 512, "e : string\n    :ref:`fits-unit` to convert from, with or without surrounding\n    square brackets (for inline specifications); text following the\n    closing bracket is ignored.\n\nwant : string\n    :ref:`fits-unit` to convert to, with or without surrounding ", 256);
-   strncpy(doc_UnitConverter + 768, "square\n    brackets (for inline specifications); text following the closing\n    bracket is ignored.\n\nctrl : string, optional\n    Do potentially unsafe translations of non-standard unit strings.\n\n    Although ``\"S\"`` is commonly used to represent seconds, i", 256);
-   strncpy(doc_UnitConverter + 1024, "ts\n    recognizes ``\"S\"`` formally as Siemens, however rarely that may\n    be translation to ``\"s\"`` is potentially unsafe since the\n    standard used.  The same applies to ``\"H\"`` for hours (Henry),\n    and ``\"D\"`` for days (Debye).\n\n    This string contr", 256);
-   strncpy(doc_UnitConverter + 1280, "ols what to do in such cases, and is\n    case-insensitive.\n\n    - If the string contains ``\"s\"``, translate ``\"S\"`` to ``\"s\"``.\n\n    - If the string contains ``\"h\"``, translate ``\"H\"`` to ``\"h\"``.\n\n    - If the string contains ``\"d\"``, translate ``\"D\"`` to", 256);
-   strncpy(doc_UnitConverter + 1536, " ``\"d\"``.\n\n    Thus ``\'\'`` doesn\'t do any unsafe translations, whereas ``\'shd\'``\n    does all of them.\n\n    See :ref:`fits-unit` for more information.\n\nRaises\n------\nValueError\n    Invalid numeric multiplier.\n\nSyntaxError\n    Dangling binary operator.\n\nSyn", 256);
-   strncpy(doc_UnitConverter + 1792, "taxError\n    Invalid symbol in INITIAL context.\n\nSyntaxError\n    Function in invalid context.\n\nSyntaxError\n    Invalid symbol in EXPON context.\n\nSyntaxError\n    Unbalanced bracket.\n\nSyntaxError\n    Unbalanced parenthesis.\n\nSyntaxError\n    Consecutive binar", 256);
-   strncpy(doc_UnitConverter + 2048, "y operators.\n\nSyntaxError\n    Internal parser error.\n\nSyntaxError\n    Non-conformant unit specifications.\n\nSyntaxError\n    Non-conformant functions.\n\nValueError\n    Potentially unsafe translation.\n\x00", 198);
+   strncpy(doc_UnitConverter + 256, "epting whitespace in all contexts in\na units specification where it does not create ambiguity (e.g. not\nbetween a metric prefix and a basic unit string), including in strings\nlike ``\"log (m ** 2)\"`` which is formally disallowed.\n\n.. note:: Deprecated in As", 256);
+   strncpy(doc_UnitConverter + 512, "tropy 0.2\n\n   `UnitConverter` will be removed in a future version of astropy.\n   The `astropy.units` package should be used instead.\n\nParameters\n----------\n\nhave : string\n    FITS unit string to convert from, with or without surrounding\n    square brackets", 256);
+   strncpy(doc_UnitConverter + 768, " (for inline specifications); text following the\n    closing bracket is ignored.\n\nwant : string\n    FITS unit string to convert to, with or without surrounding square\n    brackets (for inline specifications); text following the closing\n    bracket is ignor", 256);
+   strncpy(doc_UnitConverter + 1024, "ed.\n\nctrl : string, optional\n    Do potentially unsafe translations of non-standard unit strings.\n\n    Although ``\"S\"`` is commonly used to represent seconds, its\n    recognizes ``\"S\"`` formally as Siemens, however rarely that may\n    be translation to ``\"", 256);
+   strncpy(doc_UnitConverter + 1280, "s\"`` is potentially unsafe since the\n    standard used.  The same applies to ``\"H\"`` for hours (Henry),\n    and ``\"D\"`` for days (Debye).\n\n    This string controls what to do in such cases, and is\n    case-insensitive.\n\n    - If the string contains ``\"s\"``", 256);
+   strncpy(doc_UnitConverter + 1536, ", translate ``\"S\"`` to ``\"s\"``.\n\n    - If the string contains ``\"h\"``, translate ``\"H\"`` to ``\"h\"``.\n\n    - If the string contains ``\"d\"``, translate ``\"D\"`` to ``\"d\"``.\n\n    Thus ``\'\'`` doesn\'t do any unsafe translations, whereas ``\'shd\'``\n    does all of", 256);
+   strncpy(doc_UnitConverter + 1792, " them.\n\nRaises\n------\nValueError\n    Invalid numeric multiplier.\n\nSyntaxError\n    Dangling binary operator.\n\nSyntaxError\n    Invalid symbol in INITIAL context.\n\nSyntaxError\n    Function in invalid context.\n\nSyntaxError\n    Invalid symbol in EXPON context.\n", 256);
+   strncpy(doc_UnitConverter + 2048, "\nSyntaxError\n    Unbalanced bracket.\n\nSyntaxError\n    Unbalanced parenthesis.\n\nSyntaxError\n    Consecutive binary operators.\n\nSyntaxError\n    Internal parser error.\n\nSyntaxError\n    Non-conformant unit specifications.\n\nSyntaxError\n    Non-conformant functi", 256);
+   strncpy(doc_UnitConverter + 2304, "ons.\n\nValueError\n    Potentially unsafe translation.\n\x00", 54);
 
    strncpy(doc_Wcs + 0, "Wcs(*sip, cpdis, wcsprm, det2im*)\n\nWcs objects amalgamate basic WCS (as provided by `wcslib`_), with\n`SIP`_ and `Paper IV`_ distortion operations.\n\nTo perform all distortion corrections and WCS tranformation, use\n`all_pix2world`.\n\nParameters\n----------\nsip", 256);
    strncpy(doc_Wcs + 256, " : `~astropy.wcs.Sip` object or `None`\n\ncpdis : A pair of `~astropy.wcs.DistortionLookupTable` objects, or\n  ``(None, None)``.\n\nwcsprm : `~astropy.wcs.Wcsprm` object\n\ndet2im : A pair of `~astropy.wcs.DistortionLookupTable` objects, or\n   ``(None, None)``.\n", 256);
    strncpy(doc_Wcs + 512, "\x00", 1);
 
-   strncpy(doc_Wcsprm + 0, "Wcsprm(header=None, key=\' \', relax=False, naxis=2, keysel=0, colsel=None)\n\n`~astropy.wcs.Wcsprm` is a direct wrapper around `wcslib`_, and\nprovides access to the core WCS transformations that it supports.\n\nThe FITS header parsing enforces correct FITS \"key", 256);
+   strncpy(doc_Wcsprm + 0, "Wcsprm(header=None, key=\' \', relax=False, naxis=2, keysel=0, colsel=None)\n\n`~astropy.wcs.Wcsprm` is a direct wrapper around `wcslib`_.  It\nprovides access to the core WCS transformations that it supports.\n\nThe FITS header parsing enforces correct FITS \"key", 256);
    strncpy(doc_Wcsprm + 256, "word = value\" syntax\nwith regard to the equals sign occurring in columns 9 and 10.\nHowever, it does recognize free-format character (NOST 100-2.0,\nSect. 5.2.1), integer (Sect. 5.2.3), and floating-point values\n(Sect. 5.2.4) for all keywords.\n\nParameters\n--", 256);
-   strncpy(doc_Wcsprm + 512, "--------\nheader : An astropy.io.fits header, string, or `None`.\n  If ``None``, the object will be initialized to default values.\n\nkey : string, optional\n    The key referring to a particular WCS transform in the header.\n    This may be either ``\' \'`` or ``", 256);
-   strncpy(doc_Wcsprm + 768, "\'A\'``-``\'Z\'`` and corresponds to\n    the ``\"a\"`` part of ``\"CTYPEia\"``.  (*key* may only be\n    provided if *header* is also provided.)\n\nrelax : bool or int, optional\n\n    Degree of permissiveness:\n\n    - `False`: Recognize only FITS keywords defined by th", 256);
-   strncpy(doc_Wcsprm + 1024, "e published\n      WCS standard.\n\n    - `True`: Admit all recognized informal extensions of the WCS\n      standard.\n\n    - `int`: a bit field selecting specific extensions to accept.  See\n      :ref:`relaxread` for details.\n\nnaxis : int, optional\n    The nu", 256);
-   strncpy(doc_Wcsprm + 1280, "mber of world coordinates axes for the object.  (*naxis* may\n    only be provided if *header* is `None`.)\n\nkeysel : sequence of flag bits, optional\n    Vector of flag bits that may be used to restrict the keyword types\n    considered:\n\n        - ``WCSHDR_I", 256);
-   strncpy(doc_Wcsprm + 1536, "MGHEAD``: Image header keywords.\n\n        - ``WCSHDR_BIMGARR``: Binary table image array.\n\n        - ``WCSHDR_PIXLIST``: Pixel list keywords.\n\n    If zero, there is no restriction.  If -1, the underlying wcslib\n    function ``wcspih()`` is called, rather t", 256);
-   strncpy(doc_Wcsprm + 1792, "han ``wcstbh()``.\n\ncolsel : sequence of int\n    A sequence of table column numbers used to restrict the keywords\n    considered.  `None` indicates no restriction.\n\nRaises\n------\nMemoryError\n     Memory allocation failed.\n\nValueError\n     Invalid key.\n\nKeyE", 256);
-   strncpy(doc_Wcsprm + 2048, "rror\n     Key not found in FITS header.\n\x00", 41);
+   strncpy(doc_Wcsprm + 512, "--------\nheader : An `astropy.io.fits.Header`, string, or `None`.\n  If ``None``, the object will be initialized to default values.\n\nkey : string, optional\n    The key referring to a particular WCS transform in the header.\n    This may be either ``\' \'`` or ", 256);
+   strncpy(doc_Wcsprm + 768, "``\'A\'``-``\'Z\'`` and corresponds to\n    the ``\"a\"`` part of ``\"CTYPEia\"``.  (*key* may only be\n    provided if *header* is also provided.)\n\nrelax : bool or int, optional\n\n    Degree of permissiveness:\n\n    - `False`: Recognize only FITS keywords defined by ", 256);
+   strncpy(doc_Wcsprm + 1024, "the published\n      WCS standard.\n\n    - `True`: Admit all recognized informal extensions of the WCS\n      standard.\n\n    - `int`: a bit field selecting specific extensions to accept.  See\n      :ref:`relaxread` for details.\n\nnaxis : int, optional\n    The ", 256);
+   strncpy(doc_Wcsprm + 1280, "number of world coordinates axes for the object.  (*naxis* may\n    only be provided if *header* is `None`.)\n\nkeysel : sequence of flag bits, optional\n    Vector of flag bits that may be used to restrict the keyword types\n    considered:\n\n        - ``WCSHDR", 256);
+   strncpy(doc_Wcsprm + 1536, "_IMGHEAD``: Image header keywords.\n\n        - ``WCSHDR_BIMGARR``: Binary table image array.\n\n        - ``WCSHDR_PIXLIST``: Pixel list keywords.\n\n    If zero, there is no restriction.  If -1, the underlying wcslib\n    function ``wcspih()`` is called, rather", 256);
+   strncpy(doc_Wcsprm + 1792, " than ``wcstbh()``.\n\ncolsel : sequence of int\n    A sequence of table column numbers used to restrict the keywords\n    considered.  `None` indicates no restriction.\n\nRaises\n------\nMemoryError\n     Memory allocation failed.\n\nValueError\n     Invalid key.\n\nKe", 256);
+   strncpy(doc_Wcsprm + 2048, "yError\n     Key not found in FITS header.\n\x00", 43);
 
    strncpy(doc_Wtbarr + 0, "Classes to construct coordinate lookup tables from a binary table\nextension (BINTABLE).\n\nThis class can not be constructed directly from Python, but instead is\nreturned from `~astropy.wcs.Wcsprm.wtb`.\n\x00", 202);
 
@@ -281,11 +282,12 @@ void fill_docstrings(void)
    strncpy(doc_cubeface + 768, "in a\n      three-dimensional structure using a ``CUBEFACE`` axis indexed\n      from 0 to 5 as above.\n\nThese routines support both methods; `~astropy.wcs.Wcsprm.set`\ndetermines which is being used by the presence or absence of a\n``CUBEFACE`` axis in `~astro", 256);
    strncpy(doc_cubeface + 1024, "py.wcs.Wcsprm.ctype`.\n`~astropy.wcs.Wcsprm.p2s` and `~astropy.wcs.Wcsprm.s2p` translate the\n``CUBEFACE`` axis representation to the single plane representation\nunderstood by the lower-level projection routines.\n\x00", 212);
 
-   strncpy(doc_cunit + 0, "``list of strings[naxis]`` List of ``CUNITia`` keyvalues.\n\nThese define the units of measurement of the ``CRVALia``, ``CDELTia``\nand ``CDi_ja`` keywords.\n\nAs ``CUNITia`` is an optional header keyword,\n`~astropy.wcs.Wcsprm.cunit` may be left blank but other", 256);
-   strncpy(doc_cunit + 256, "wise is\nexpected to contain a standard units specification as defined by WCS\nPaper I.  `~astropy.wcs.Wcsprm.unitfix` is available to translate\ncommonly used non-standard units specifications but this must be done\nas a separate step before invoking `~astrop", 256);
-   strncpy(doc_cunit + 512, "y.wcs.Wcsprm.set`.\n\nFor celestial axes, if `~astropy.wcs.Wcsprm.cunit` is not blank,\n`~astropy.wcs.Wcsprm.set` uses `wcsunits` to parse it and scale\n`~astropy.wcs.Wcsprm.cdelt`, `~astropy.wcs.Wcsprm.crval`, and\n`~astropy.wcs.Wcsprm.cd` to decimal degrees. ", 256);
-   strncpy(doc_cunit + 768, " It then resets\n`~astropy.wcs.Wcsprm.cunit` to ``\"deg\"``.\n\nFor spectral axes, if `~astropy.wcs.Wcsprm.cunit` is not blank,\n`~astropy.wcs.Wcsprm.set` uses `wcsunits` to parse it and scale\n`~astropy.wcs.Wcsprm.cdelt`, `~astropy.wcs.Wcsprm.crval`, and\n`~astro", 256);
-   strncpy(doc_cunit + 1024, "py.wcs.Wcsprm.cd` to SI units.  It then resets\n`~astropy.wcs.Wcsprm.cunit` accordingly.\n\n`~astropy.wcs.Wcsprm.set` ignores `~astropy.wcs.Wcsprm.cunit` for\nother coordinate types; `~astropy.wcs.Wcsprm.cunit` may be used to\nlabel coordinate values.\n\x00", 248);
+   strncpy(doc_cunit + 0, "``list of astropy.UnitBase[naxis]`` List of ``CUNITia`` keyvalues as\n`astropy.units.UnitBase` instances.\n\nThese define the units of measurement of the ``CRVALia``, ``CDELTia``\nand ``CDi_ja`` keywords.\n\nAs ``CUNITia`` is an optional header keyword,\n`~astrop", 256);
+   strncpy(doc_cunit + 256, "y.wcs.Wcsprm.cunit` may be left blank but otherwise is\nexpected to contain a standard units specification as defined by WCS\nPaper I.  `~astropy.wcs.Wcsprm.unitfix` is available to translate\ncommonly used non-standard units specifications but this must be d", 256);
+   strncpy(doc_cunit + 512, "one\nas a separate step before invoking `~astropy.wcs.Wcsprm.set`.\n\nFor celestial axes, if `~astropy.wcs.Wcsprm.cunit` is not blank,\n`~astropy.wcs.Wcsprm.set` uses `wcsunits` to parse it and scale\n`~astropy.wcs.Wcsprm.cdelt`, `~astropy.wcs.Wcsprm.crval`, an", 256);
+   strncpy(doc_cunit + 768, "d\n`~astropy.wcs.Wcsprm.cd` to decimal degrees.  It then resets\n`~astropy.wcs.Wcsprm.cunit` to ``\"deg\"``.\n\nFor spectral axes, if `~astropy.wcs.Wcsprm.cunit` is not blank,\n`~astropy.wcs.Wcsprm.set` uses `wcsunits` to parse it and scale\n`~astropy.wcs.Wcsprm.c", 256);
+   strncpy(doc_cunit + 1024, "delt`, `~astropy.wcs.Wcsprm.crval`, and\n`~astropy.wcs.Wcsprm.cd` to SI units.  It then resets\n`~astropy.wcs.Wcsprm.cunit` accordingly.\n\n`~astropy.wcs.Wcsprm.set` ignores `~astropy.wcs.Wcsprm.cunit` for\nother coordinate types; `~astropy.wcs.Wcsprm.cunit` ma", 256);
+   strncpy(doc_cunit + 1280, "y be used to\nlabel coordinate values.\n\x00", 39);
 
    strncpy(doc_cylfix + 0, "cylfix()\n\nFixes WCS keyvalues for malformed cylindrical projections.\n\nReturns\n-------\nsuccess : int\n    Returns ``0`` for success; ``-1`` if no change required.\n\x00", 162);
 
@@ -324,7 +326,7 @@ void fill_docstrings(void)
    strncpy(doc_find_all_wcs + 0, "find_all_wcs(relax=0, keysel=0)\n\nFind all WCS transformations in the header.\n\nParameters\n----------\n\nheader : str\n    The raw FITS header data.\n\nrelax : bool or int\n    Degree of permissiveness:\n\n    - `False`: Recognize only FITS keywords defined by the p", 256);
    strncpy(doc_find_all_wcs + 256, "ublished\n      WCS standard.\n\n    - `True`: Admit all recognized informal extensions of the WCS\n      standard.\n\n    - `int`: a bit field selecting specific extensions to accept.  See\n      :ref:`relaxread` for details.\n\nkeysel : sequence of flags\n    Used", 256);
    strncpy(doc_find_all_wcs + 512, " to restrict the keyword types considered:\n\n    - ``WCSHDR_IMGHEAD``: Image header keywords.\n\n    - ``WCSHDR_BIMGARR``: Binary table image array.\n\n    - ``WCSHDR_PIXLIST``: Pixel list keywords.\n\n    If zero, there is no restriction.  If -1, `wcspih` is cal", 256);
-   strncpy(doc_find_all_wcs + 768, "led,\n    rather than `wcstbh`.\n\nReturns\n-------\nwcs_list : list of `~astropy.wcs._astropy.wcs._Wcsprm` objects\n\x00", 112);
+   strncpy(doc_find_all_wcs + 768, "led,\n    rather than `wcstbh`.\n\nReturns\n-------\nwcs_list : list of `~astropy.wcs._astropy.wcs.Wcsprm` objects\n\x00", 111);
 
    strncpy(doc_fix + 0, "fix(translate_units=\'\', naxis=0)\n\nApplies all of the corrections handled separately by\n`~astropy.wcs.Wcsprm.datfix`, `~astropy.wcs.Wcsprm.unitfix`,\n`~astropy.wcs.Wcsprm.celfix`, `~astropy.wcs.Wcsprm.spcfix`,\n`~astropy.wcs.Wcsprm.cylfix` and `~astropy.wcs.W", 256);
    strncpy(doc_fix + 256, "csprm.cdfix`.\n\nParameters\n----------\n\ntranslate_units : str\n    Do potentially unsafe translations of non-standard unit strings.\n\n    Although ``\"S\"`` is commonly used to represent seconds, its\n    translation to ``\"s\"`` is potentially unsafe since the sta", 256);
@@ -569,8 +571,8 @@ void fill_docstrings(void)
    strncpy(doc_unitfix + 0, "unitfix(translate_units=\'\')\n\nTranslates non-standard ``CUNITia`` keyvalues.\n\nFor example, ``DEG`` -> ``deg``, also stripping off unnecessary\nwhitespace.\n\nParameters\n----------\ntranslate_units : string, optional\n    Do potentially unsafe translations of non", 256);
    strncpy(doc_unitfix + 256, "-standard unit strings.\n\n    Although ``\"S\"`` is commonly used to represent seconds, its\n    recognizes ``\"S\"`` formally as Siemens, however rarely that may\n    be translation to ``\"s\"`` is potentially unsafe since the\n    standard used.  The same applies ", 256);
    strncpy(doc_unitfix + 512, "to ``\"H\"`` for hours (Henry),\n    and ``\"D\"`` for days (Debye).\n\n    This string controls what to do in such cases, and is\n    case-insensitive.\n\n    - If the string contains ``\"s\"``, translate ``\"S\"`` to ``\"s\"``.\n\n    - If the string contains ``\"h\"``, tra", 256);
-   strncpy(doc_unitfix + 768, "nslate ``\"H\"`` to ``\"h\"``.\n\n    - If the string contains ``\"d\"``, translate ``\"D\"`` to ``\"d\"``.\n\n    Thus ``\'\'`` doesn\'t do any unsafe translations, whereas ``\'shd\'``\n    does all of them.\n\n    See :ref:`fits-unit` for more information.\n\nReturns\n-------\nsu", 256);
-   strncpy(doc_unitfix + 1024, "ccess : int\n    Returns ``0`` for success; ``-1`` if no change required.\n\x00", 74);
+   strncpy(doc_unitfix + 768, "nslate ``\"H\"`` to ``\"h\"``.\n\n    - If the string contains ``\"d\"``, translate ``\"D\"`` to ``\"d\"``.\n\n    Thus ``\'\'`` doesn\'t do any unsafe translations, whereas ``\'shd\'``\n    does all of them.\n\nReturns\n-------\nsuccess : int\n    Returns ``0`` for success; ``-1`", 256);
+   strncpy(doc_unitfix + 1024, "` if no change required.\n\x00", 26);
 
    strncpy(doc_velangl + 0, "``double`` Velocity angle.\n\nThe angle in degrees that should be used to decompose an observed\nvelocity into radial and transverse components.\n\nAn undefined value is represented by NaN.\n\x00", 186);
 
@@ -597,11 +599,11 @@ char doc_Sip[1040] = "Sip(*a, b, ap, bp, crpix*)\n\nThe `~astropy.wcs.Sip` class
 
 char doc_Tabprm[234] = "A class to store the information related to tabular coordinates,\ni.e., coordinates that are defined via a lookup table.\n\nThis class can not be constructed directly from Python, but instead is\nreturned from `~astropy.wcs.Wcsprm.tab`.\n\x00";
 
-char doc_UnitConverter[2246] = "UnitConverter(have, want, translate_units=\'\')\n\nAn object for converting from one system of units to another.\n\nUse the returned object\'s `~astropy.wcs.UnitConverter.convert` method\nto convert values from *have* to *want*.\n\nThis function is permissive in accepting whitespace in all contexts in\na units specification where it does not create ambiguity (e.g. not\nbetween a metric prefix and a basic unit string), including in strings\nlike ``\"log (m ** 2)\"`` which is formally disallowed.\n\nParameters\n----------\n\nhave : string\n    :ref:`fits-unit` to convert from, with or without surrounding\n    square brackets (for inline specifications); text following the\n    closing bracket is ignored.\n\nwant : string\n    :ref:`fits-unit` to convert to, with or without surrounding square\n    brackets (for inline specifications); text following the closing\n    bracket is ignored.\n\nctrl : string, optional\n    Do potentially unsafe translations of non-standard unit strings.\n\n    Although ``\"S\"`` is commonly used to represent seconds, its\n    recognizes ``\"S\"`` formally as Siemens, however rarely that may\n    be translation to ``\"s\"`` is potentially unsafe since the\n    standard used.  The same applies to ``\"H\"`` for hours (Henry),\n    and ``\"D\"`` for days (Debye).\n\n    This string controls what to do in such cases, and is\n    case-insensitive.\n\n    - If the string contains ``\"s\"``, translate ``\"S\"`` to ``\"s\"``.\n\n    - If the string contains ``\"h\"``, translate ``\"H\"`` to ``\"h\"``.\n\n    - If the string contains ``\"d\"``, translate ``\"D\"`` to ``\"d\"``.\n\n    Thus ``\'\'`` doesn\'t do any unsafe translations, whereas ``\'shd\'``\n    does all of them.\n\n    See :ref:`fits-unit` for more information.\n\nRaises\n------\nValueError\n    Invalid numeric multiplier.\n\nSyntaxError\n    Dangling binary operator.\n\nSyntaxError\n    Invalid symbol in INITIAL context.\n\nSyntaxError\n    Function in invalid context.\n\nSyntaxError\n    Invalid symbol in EXPON context.\n\nSyntaxError\n    Unbalanced bracket.\n\nSyntaxError\n    Unbalanced parenthesis.\n\nSyntaxError\n    Consecutive binary operators.\n\nSyntaxError\n    Internal parser error.\n\nSyntaxError\n    Non-conformant unit specifications.\n\nSyntaxError\n    Non-conformant functions.\n\nValueError\n    Potentially unsafe translation.\n\x00";
+char doc_UnitConverter[2358] = "UnitConverter(have, want, translate_units=\'\')\n\nAn object for converting from one system of units to another.\n\nUse the returned object\'s `~astropy.wcs.UnitConverter.convert` method\nto convert values from *have* to *want*.\n\nThis function is permissive in accepting whitespace in all contexts in\na units specification where it does not create ambiguity (e.g. not\nbetween a metric prefix and a basic unit string), including in strings\nlike ``\"log (m ** 2)\"`` which is formally disallowed.\n\n.. note:: Deprecated in Astropy 0.2\n\n   `UnitConverter` will be removed in a future version of astropy.\n   The `astropy.units` package should be used instead.\n\nParameters\n----------\n\nhave : string\n    FITS unit string to convert from, with or without surrounding\n    square brackets (for inline specifications); text following the\n    closing bracket is ignored.\n\nwant : string\n    FITS unit string to convert to, with or without surrounding square\n    brackets (for inline specifications); text following the closing\n    bracket is ignored.\n\nctrl : string, optional\n    Do potentially unsafe translations of non-standard unit strings.\n\n    Although ``\"S\"`` is commonly used to represent seconds, its\n    recognizes ``\"S\"`` formally as Siemens, however rarely that may\n    be translation to ``\"s\"`` is potentially unsafe since the\n    standard used.  The same applies to ``\"H\"`` for hours (Henry),\n    and ``\"D\"`` for days (Debye).\n\n    This string controls what to do in such cases, and is\n    case-insensitive.\n\n    - If the string contains ``\"s\"``, translate ``\"S\"`` to ``\"s\"``.\n\n    - If the string contains ``\"h\"``, translate ``\"H\"`` to ``\"h\"``.\n\n    - If the string contains ``\"d\"``, translate ``\"D\"`` to ``\"d\"``.\n\n    Thus ``\'\'`` doesn\'t do any unsafe translations, whereas ``\'shd\'``\n    does all of them.\n\nRaises\n------\nValueError\n    Invalid numeric multiplier.\n\nSyntaxError\n    Dangling binary operator.\n\nSyntaxError\n    Invalid symbol in INITIAL context.\n\nSyntaxError\n    Function in invalid context.\n\nSyntaxError\n    Invalid symbol in EXPON context.\n\nSyntaxError\n    Unbalanced bracket.\n\nSyntaxError\n    Unbalanced parenthesis.\n\nSyntaxError\n    Consecutive binary operators.\n\nSyntaxError\n    Internal parser error.\n\nSyntaxError\n    Non-conformant unit specifications.\n\nSyntaxError\n    Non-conformant functions.\n\nValueError\n    Potentially unsafe translation.\n\x00";
 
 char doc_Wcs[513] = "Wcs(*sip, cpdis, wcsprm, det2im*)\n\nWcs objects amalgamate basic WCS (as provided by `wcslib`_), with\n`SIP`_ and `Paper IV`_ distortion operations.\n\nTo perform all distortion corrections and WCS tranformation, use\n`all_pix2world`.\n\nParameters\n----------\nsip : `~astropy.wcs.Sip` object or `None`\n\ncpdis : A pair of `~astropy.wcs.DistortionLookupTable` objects, or\n  ``(None, None)``.\n\nwcsprm : `~astropy.wcs.Wcsprm` object\n\ndet2im : A pair of `~astropy.wcs.DistortionLookupTable` objects, or\n   ``(None, None)``.\n\x00";
 
-char doc_Wcsprm[2089] = "Wcsprm(header=None, key=\' \', relax=False, naxis=2, keysel=0, colsel=None)\n\n`~astropy.wcs.Wcsprm` is a direct wrapper around `wcslib`_, and\nprovides access to the core WCS transformations that it supports.\n\nThe FITS header parsing enforces correct FITS \"keyword = value\" syntax\nwith regard to the equals sign occurring in columns 9 and 10.\nHowever, it does recognize free-format character (NOST 100-2.0,\nSect. 5.2.1), integer (Sect. 5.2.3), and floating-point values\n(Sect. 5.2.4) for all keywords.\n\nParameters\n----------\nheader : An astropy.io.fits header, string, or `None`.\n  If ``None``, the object will be initialized to default values.\n\nkey : string, optional\n    The key referring to a particular WCS transform in the header.\n    This may be either ``\' \'`` or ``\'A\'``-``\'Z\'`` and corresponds to\n    the ``\"a\"`` part of ``\"CTYPEia\"``.  (*key* may only be\n    provided if *header* is also provided.)\n\nrelax : bool or int, optional\n\n    Degree of permissiveness:\n\n    - `False`: Recognize only FITS keywords defined by the published\n      WCS standard.\n\n    - `True`: Admit all recognized informal extensions of the WCS\n      standard.\n\n    - `int`: a bit field selecting specific extensions to accept.  See\n      :ref:`relaxread` for details.\n\nnaxis : int, optional\n    The number of world coordinates axes for the object.  (*naxis* may\n    only be provided if *header* is `None`.)\n\nkeysel : sequence of flag bits, optional\n    Vector of flag bits that may be used to restrict the keyword types\n    considered:\n\n        - ``WCSHDR_IMGHEAD``: Image header keywords.\n\n        - ``WCSHDR_BIMGARR``: Binary table image array.\n\n        - ``WCSHDR_PIXLIST``: Pixel list keywords.\n\n    If zero, there is no restriction.  If -1, the underlying wcslib\n    function ``wcspih()`` is called, rather than ``wcstbh()``.\n\ncolsel : sequence of int\n    A sequence of table column numbers used to restrict the keywords\n    considered.  `None` indicates no restriction.\n\nRaises\n------\nMemoryError\n     Memory allocation failed.\n\nValueError\n     Invalid key.\n\nKeyError\n     Key not found in FITS header.\n\x00";
+char doc_Wcsprm[2091] = "Wcsprm(header=None, key=\' \', relax=False, naxis=2, keysel=0, colsel=None)\n\n`~astropy.wcs.Wcsprm` is a direct wrapper around `wcslib`_.  It\nprovides access to the core WCS transformations that it supports.\n\nThe FITS header parsing enforces correct FITS \"keyword = value\" syntax\nwith regard to the equals sign occurring in columns 9 and 10.\nHowever, it does recognize free-format character (NOST 100-2.0,\nSect. 5.2.1), integer (Sect. 5.2.3), and floating-point values\n(Sect. 5.2.4) for all keywords.\n\nParameters\n----------\nheader : An `astropy.io.fits.Header`, string, or `None`.\n  If ``None``, the object will be initialized to default values.\n\nkey : string, optional\n    The key referring to a particular WCS transform in the header.\n    This may be either ``\' \'`` or ``\'A\'``-``\'Z\'`` and corresponds to\n    the ``\"a\"`` part of ``\"CTYPEia\"``.  (*key* may only be\n    provided if *header* is also provided.)\n\nrelax : bool or int, optional\n\n    Degree of permissiveness:\n\n    - `False`: Recognize only FITS keywords defined by the published\n      WCS standard.\n\n    - `True`: Admit all recognized informal extensions of the WCS\n      standard.\n\n    - `int`: a bit field selecting specific extensions to accept.  See\n      :ref:`relaxread` for details.\n\nnaxis : int, optional\n    The number of world coordinates axes for the object.  (*naxis* may\n    only be provided if *header* is `None`.)\n\nkeysel : sequence of flag bits, optional\n    Vector of flag bits that may be used to restrict the keyword types\n    considered:\n\n        - ``WCSHDR_IMGHEAD``: Image header keywords.\n\n        - ``WCSHDR_BIMGARR``: Binary table image array.\n\n        - ``WCSHDR_PIXLIST``: Pixel list keywords.\n\n    If zero, there is no restriction.  If -1, the underlying wcslib\n    function ``wcspih()`` is called, rather than ``wcstbh()``.\n\ncolsel : sequence of int\n    A sequence of table column numbers used to restrict the keywords\n    considered.  `None` indicates no restriction.\n\nRaises\n------\nMemoryError\n     Memory allocation failed.\n\nValueError\n     Invalid key.\n\nKeyError\n     Key not found in FITS header.\n\x00";
 
 char doc_Wtbarr[202] = "Classes to construct coordinate lookup tables from a binary table\nextension (BINTABLE).\n\nThis class can not be constructed directly from Python, but instead is\nreturned from `~astropy.wcs.Wcsprm.wtb`.\n\x00";
 
@@ -669,7 +671,7 @@ char doc_ctype[228] = "``list of strings[naxis]`` List of ``CTYPEia`` keyvalues.
 
 char doc_cubeface[1236] = "``int`` Index into the ``pixcrd`` (pixel coordinate) array for the\n``CUBEFACE`` axis.\n\nThis is used for quadcube projections where the cube faces are stored\non a separate axis.\n\nThe quadcube projections (``TSC``, ``CSC``, ``QSC``) may be\nrepresented in FITS in either of two ways:\n\n    - The six faces may be laid out in one plane and numbered as\n      follows::\n\n\n                                       0\n\n                              4  3  2  1  4  3  2\n\n                                       5\n\n      Faces 2, 3 and 4 may appear on one side or the other (or both).\n      The world-to-pixel routines map faces 2, 3 and 4 to the left but\n      the pixel-to-world routines accept them on either side.\n\n    - The ``COBE`` convention in which the six faces are stored in a\n      three-dimensional structure using a ``CUBEFACE`` axis indexed\n      from 0 to 5 as above.\n\nThese routines support both methods; `~astropy.wcs.Wcsprm.set`\ndetermines which is being used by the presence or absence of a\n``CUBEFACE`` axis in `~astropy.wcs.Wcsprm.ctype`.\n`~astropy.wcs.Wcsprm.p2s` and `~astropy.wcs.Wcsprm.s2p` translate the\n``CUBEFACE`` axis representation to the single plane representation\nunderstood by the lower-level projection routines.\n\x00";
 
-char doc_cunit[1272] = "``list of strings[naxis]`` List of ``CUNITia`` keyvalues.\n\nThese define the units of measurement of the ``CRVALia``, ``CDELTia``\nand ``CDi_ja`` keywords.\n\nAs ``CUNITia`` is an optional header keyword,\n`~astropy.wcs.Wcsprm.cunit` may be left blank but otherwise is\nexpected to contain a standard units specification as defined by WCS\nPaper I.  `~astropy.wcs.Wcsprm.unitfix` is available to translate\ncommonly used non-standard units specifications but this must be done\nas a separate step before invoking `~astropy.wcs.Wcsprm.set`.\n\nFor celestial axes, if `~astropy.wcs.Wcsprm.cunit` is not blank,\n`~astropy.wcs.Wcsprm.set` uses `wcsunits` to parse it and scale\n`~astropy.wcs.Wcsprm.cdelt`, `~astropy.wcs.Wcsprm.crval`, and\n`~astropy.wcs.Wcsprm.cd` to decimal degrees.  It then resets\n`~astropy.wcs.Wcsprm.cunit` to ``\"deg\"``.\n\nFor spectral axes, if `~astropy.wcs.Wcsprm.cunit` is not blank,\n`~astropy.wcs.Wcsprm.set` uses `wcsunits` to parse it and scale\n`~astropy.wcs.Wcsprm.cdelt`, `~astropy.wcs.Wcsprm.crval`, and\n`~astropy.wcs.Wcsprm.cd` to SI units.  It then resets\n`~astropy.wcs.Wcsprm.cunit` accordingly.\n\n`~astropy.wcs.Wcsprm.set` ignores `~astropy.wcs.Wcsprm.cunit` for\nother coordinate types; `~astropy.wcs.Wcsprm.cunit` may be used to\nlabel coordinate values.\n\x00";
+char doc_cunit[1319] = "``list of astropy.UnitBase[naxis]`` List of ``CUNITia`` keyvalues as\n`astropy.units.UnitBase` instances.\n\nThese define the units of measurement of the ``CRVALia``, ``CDELTia``\nand ``CDi_ja`` keywords.\n\nAs ``CUNITia`` is an optional header keyword,\n`~astropy.wcs.Wcsprm.cunit` may be left blank but otherwise is\nexpected to contain a standard units specification as defined by WCS\nPaper I.  `~astropy.wcs.Wcsprm.unitfix` is available to translate\ncommonly used non-standard units specifications but this must be done\nas a separate step before invoking `~astropy.wcs.Wcsprm.set`.\n\nFor celestial axes, if `~astropy.wcs.Wcsprm.cunit` is not blank,\n`~astropy.wcs.Wcsprm.set` uses `wcsunits` to parse it and scale\n`~astropy.wcs.Wcsprm.cdelt`, `~astropy.wcs.Wcsprm.crval`, and\n`~astropy.wcs.Wcsprm.cd` to decimal degrees.  It then resets\n`~astropy.wcs.Wcsprm.cunit` to ``\"deg\"``.\n\nFor spectral axes, if `~astropy.wcs.Wcsprm.cunit` is not blank,\n`~astropy.wcs.Wcsprm.set` uses `wcsunits` to parse it and scale\n`~astropy.wcs.Wcsprm.cdelt`, `~astropy.wcs.Wcsprm.crval`, and\n`~astropy.wcs.Wcsprm.cd` to SI units.  It then resets\n`~astropy.wcs.Wcsprm.cunit` accordingly.\n\n`~astropy.wcs.Wcsprm.set` ignores `~astropy.wcs.Wcsprm.cunit` for\nother coordinate types; `~astropy.wcs.Wcsprm.cunit` may be used to\nlabel coordinate values.\n\x00";
 
 char doc_cylfix[162] = "cylfix()\n\nFixes WCS keyvalues for malformed cylindrical projections.\n\nReturns\n-------\nsuccess : int\n    Returns ``0`` for success; ``-1`` if no change required.\n\x00";
 
@@ -703,7 +705,7 @@ char doc_extrema[452] = "``double array[K_M]...[K_2][2][M]`` (read-only)\n\nAn a
 
 char doc_extver[73] = "``int`` (read-only)\n\n``EXTVER`` identifying the binary table extension.\n\x00";
 
-char doc_find_all_wcs[880] = "find_all_wcs(relax=0, keysel=0)\n\nFind all WCS transformations in the header.\n\nParameters\n----------\n\nheader : str\n    The raw FITS header data.\n\nrelax : bool or int\n    Degree of permissiveness:\n\n    - `False`: Recognize only FITS keywords defined by the published\n      WCS standard.\n\n    - `True`: Admit all recognized informal extensions of the WCS\n      standard.\n\n    - `int`: a bit field selecting specific extensions to accept.  See\n      :ref:`relaxread` for details.\n\nkeysel : sequence of flags\n    Used to restrict the keyword types considered:\n\n    - ``WCSHDR_IMGHEAD``: Image header keywords.\n\n    - ``WCSHDR_BIMGARR``: Binary table image array.\n\n    - ``WCSHDR_PIXLIST``: Pixel list keywords.\n\n    If zero, there is no restriction.  If -1, `wcspih` is called,\n    rather than `wcstbh`.\n\nReturns\n-------\nwcs_list : list of `~astropy.wcs._astropy.wcs._Wcsprm` objects\n\x00";
+char doc_find_all_wcs[879] = "find_all_wcs(relax=0, keysel=0)\n\nFind all WCS transformations in the header.\n\nParameters\n----------\n\nheader : str\n    The raw FITS header data.\n\nrelax : bool or int\n    Degree of permissiveness:\n\n    - `False`: Recognize only FITS keywords defined by the published\n      WCS standard.\n\n    - `True`: Admit all recognized informal extensions of the WCS\n      standard.\n\n    - `int`: a bit field selecting specific extensions to accept.  See\n      :ref:`relaxread` for details.\n\nkeysel : sequence of flags\n    Used to restrict the keyword types considered:\n\n    - ``WCSHDR_IMGHEAD``: Image header keywords.\n\n    - ``WCSHDR_BIMGARR``: Binary table image array.\n\n    - ``WCSHDR_PIXLIST``: Pixel list keywords.\n\n    If zero, there is no restriction.  If -1, `wcspih` is called,\n    rather than `wcstbh`.\n\nReturns\n-------\nwcs_list : list of `~astropy.wcs._astropy.wcs.Wcsprm` objects\n\x00";
 
 char doc_fix[1613] = "fix(translate_units=\'\', naxis=0)\n\nApplies all of the corrections handled separately by\n`~astropy.wcs.Wcsprm.datfix`, `~astropy.wcs.Wcsprm.unitfix`,\n`~astropy.wcs.Wcsprm.celfix`, `~astropy.wcs.Wcsprm.spcfix`,\n`~astropy.wcs.Wcsprm.cylfix` and `~astropy.wcs.Wcsprm.cdfix`.\n\nParameters\n----------\n\ntranslate_units : str\n    Do potentially unsafe translations of non-standard unit strings.\n\n    Although ``\"S\"`` is commonly used to represent seconds, its\n    translation to ``\"s\"`` is potentially unsafe since the standard\n    recognizes ``\"S\"`` formally as Siemens, however rarely that may be\n    used.  The same applies to ``\"H\"`` for hours (Henry), and ``\"D\"``\n    for days (Debye).\n\n    This string controls what to do in such cases, and is\n    case-insensitive.\n\n    - If the string contains ``\"s\"``, translate ``\"S\"`` to ``\"s\"``.\n\n    - If the string contains ``\"h\"``, translate ``\"H\"`` to ``\"h\"``.\n\n    - If the string contains ``\"d\"``, translate ``\"D\"`` to ``\"d\"``.\n\n    Thus ``\'\'`` doesn\'t do any unsafe translations, whereas ``\'shd\'``\n    does all of them.\n\nnaxis : int array[naxis]\n    Image axis lengths.  If this array is set to zero or ``None``,\n    then `~astropy.wcs.Wcsprm.cylfix` will not be invoked.\n\nReturns\n-------\nstatus : dict\n\n    Returns a dictionary containing the following keys, each referring\n    to a status string for each of the sub-fix functions that were\n    called:\n\n    - `~astropy.wcs.Wcsprm.cdfix`\n\n    - `~astropy.wcs.Wcsprm.datfix`\n\n    - `~astropy.wcs.Wcsprm.unitfix`\n\n    - `~astropy.wcs.Wcsprm.celfix`\n\n    - `~astropy.wcs.Wcsprm.spcfix`\n\n    - `~astropy.wcs.Wcsprm.cylfix`\n\x00";
 
@@ -843,7 +845,7 @@ char doc_to_header[2229] = "to_header(relax=False)\n\n`to_header` translates a W
 
 char doc_ttype[108] = "``str`` (read-only)\n\n``TTYPEn`` identifying the column of the binary table that contains\nthe wcstab array.\n\x00";
 
-char doc_unitfix[1098] = "unitfix(translate_units=\'\')\n\nTranslates non-standard ``CUNITia`` keyvalues.\n\nFor example, ``DEG`` -> ``deg``, also stripping off unnecessary\nwhitespace.\n\nParameters\n----------\ntranslate_units : string, optional\n    Do potentially unsafe translations of non-standard unit strings.\n\n    Although ``\"S\"`` is commonly used to represent seconds, its\n    recognizes ``\"S\"`` formally as Siemens, however rarely that may\n    be translation to ``\"s\"`` is potentially unsafe since the\n    standard used.  The same applies to ``\"H\"`` for hours (Henry),\n    and ``\"D\"`` for days (Debye).\n\n    This string controls what to do in such cases, and is\n    case-insensitive.\n\n    - If the string contains ``\"s\"``, translate ``\"S\"`` to ``\"s\"``.\n\n    - If the string contains ``\"h\"``, translate ``\"H\"`` to ``\"h\"``.\n\n    - If the string contains ``\"d\"``, translate ``\"D\"`` to ``\"d\"``.\n\n    Thus ``\'\'`` doesn\'t do any unsafe translations, whereas ``\'shd\'``\n    does all of them.\n\n    See :ref:`fits-unit` for more information.\n\nReturns\n-------\nsuccess : int\n    Returns ``0`` for success; ``-1`` if no change required.\n\x00";
+char doc_unitfix[1050] = "unitfix(translate_units=\'\')\n\nTranslates non-standard ``CUNITia`` keyvalues.\n\nFor example, ``DEG`` -> ``deg``, also stripping off unnecessary\nwhitespace.\n\nParameters\n----------\ntranslate_units : string, optional\n    Do potentially unsafe translations of non-standard unit strings.\n\n    Although ``\"S\"`` is commonly used to represent seconds, its\n    recognizes ``\"S\"`` formally as Siemens, however rarely that may\n    be translation to ``\"s\"`` is potentially unsafe since the\n    standard used.  The same applies to ``\"H\"`` for hours (Henry),\n    and ``\"D\"`` for days (Debye).\n\n    This string controls what to do in such cases, and is\n    case-insensitive.\n\n    - If the string contains ``\"s\"``, translate ``\"S\"`` to ``\"s\"``.\n\n    - If the string contains ``\"h\"``, translate ``\"H\"`` to ``\"h\"``.\n\n    - If the string contains ``\"d\"``, translate ``\"D\"`` to ``\"d\"``.\n\n    Thus ``\'\'`` doesn\'t do any unsafe translations, whereas ``\'shd\'``\n    does all of them.\n\nReturns\n-------\nsuccess : int\n    Returns ``0`` for success; ``-1`` if no change required.\n\x00";
 
 char doc_velangl[186] = "``double`` Velocity angle.\n\nThe angle in degrees that should be used to decompose an observed\nvelocity into radial and transverse components.\n\nAn undefined value is represented by NaN.\n\x00";
 
diff --git a/astropy/wcs/src/pyutil.c b/astropy/wcs/src/pyutil.c
index 2f96b8c..f2ce0b2 100644
--- a/astropy/wcs/src/pyutil.c
+++ b/astropy/wcs/src/pyutil.c
@@ -553,13 +553,12 @@ set_int_array(
 /* set_str_list is inlined */
 
 int
-set_str_list_verified(
+set_str_list(
     const char* propname,
     PyObject* value,
     Py_ssize_t len,
     Py_ssize_t maxlen,
-    char (*dest)[72],
-    str_verify_fn verify) {
+    char (*dest)[72]) {
 
   PyObject*  str      = NULL;
   char*      str_char = NULL;
@@ -635,18 +634,6 @@ set_str_list_verified(
       return -1;
     }
 
-    if (verify) {
-      #if PY3K
-      str_char = PyBytes_AsString(str);
-      #else
-      str_char = PyString_AsString(str);
-      #endif
-      if (!verify(str_char)) {
-        Py_DECREF(str);
-        return -1;
-      }
-    }
-
     Py_DECREF(str);
   }
 
@@ -684,6 +671,7 @@ set_str_list_verified(
   return 0;
 }
 
+
 /*@null@*/ PyObject*
 get_pscards(
     /*@unused@*/ const char* propname,
@@ -940,5 +928,3 @@ parse_unsafe_unit_conversion_spec(
 
   return 0;
 }
-
-
diff --git a/astropy/wcs/src/str_list_proxy.c b/astropy/wcs/src/str_list_proxy.c
index 59a0552..eddf8a7 100644
--- a/astropy/wcs/src/str_list_proxy.c
+++ b/astropy/wcs/src/str_list_proxy.c
@@ -19,7 +19,6 @@ typedef struct {
   Py_ssize_t size;
   Py_ssize_t maxsize;
   char (*array)[72];
-  str_verify_fn verify;
 } PyStrListProxy;
 
 static void
@@ -81,8 +80,7 @@ PyStrListProxy_New(
     /*@shared@*/ PyObject* owner,
     Py_ssize_t size,
     Py_ssize_t maxsize,
-    char (*array)[72],
-    str_verify_fn verify) {
+    char (*array)[72]) {
 
   PyStrListProxy* self = NULL;
 
@@ -100,7 +98,6 @@ PyStrListProxy_New(
   self->size = size;
   self->maxsize = maxsize;
   self->array = array;
-  self->verify = verify;
   return (PyObject*)self;
 }
 
@@ -156,18 +153,16 @@ PyStrListProxy_setitem(
     return -1;
   }
 
-  if (self->verify && !self->verify(value)) {
-    return -1;
-  }
-
   strncpy(self->array[index], value, self->maxsize);
 
   return 0;
 }
 
-/*@null@*/ static PyObject*
-PyStrListProxy_repr(
-    PyStrListProxy* self) {
+/*@null@*/ PyObject*
+str_list_proxy_repr(
+    char (*array)[72],
+    Py_ssize_t size,
+    Py_ssize_t maxsize) {
 
   char*       buffer  = NULL;
   char*       wp      = NULL;
@@ -182,7 +177,7 @@ PyStrListProxy_repr(
   char        next_char = '\0';
 
   /* Overallocating to allow for escaped characters */
-  buffer = malloc((size_t)self->size*self->maxsize*2 + 2);
+  buffer = malloc((size_t)size*maxsize*2 + 2);
   if (buffer == NULL) {
     PyErr_SetString(PyExc_MemoryError, "Could not allocate memory.");
     return NULL;
@@ -191,10 +186,10 @@ PyStrListProxy_repr(
   wp = buffer;
   *wp++ = '[';
 
-  for (i = 0; i < self->size; ++i) {
+  for (i = 0; i < size; ++i) {
     *wp++ = '\'';
-    rp = self->array[i];
-    for (j = 0; j < self->maxsize && *rp != '\0'; ++j) {
+    rp = array[i];
+    for (j = 0; j < maxsize && *rp != '\0'; ++j) {
       /* Check if this character should be escaped */
       e = escapes;
       next_char = *rp++;
@@ -215,7 +210,7 @@ PyStrListProxy_repr(
     *wp++ = '\'';
 
     /* Add a comma for all but the last one */
-    if (i != self->size - 1) {
+    if (i != size - 1) {
       *wp++ = ',';
       *wp++ = ' ';
     }
@@ -233,6 +228,13 @@ PyStrListProxy_repr(
   return result;
 }
 
+/*@null@*/ static PyObject*
+PyStrListProxy_repr(
+    PyStrListProxy* self) {
+
+  return str_list_proxy_repr(self->array, self->size, self->maxsize);
+}
+
 static PySequenceMethods PyStrListProxy_sequence_methods = {
   (lenfunc)PyStrListProxy_len,
   NULL,
diff --git a/astropy/wcs/src/unit_list_proxy.c b/astropy/wcs/src/unit_list_proxy.c
new file mode 100644
index 0000000..fdd0ad6
--- /dev/null
+++ b/astropy/wcs/src/unit_list_proxy.c
@@ -0,0 +1,366 @@
+/*
+ Author: Michael Droettboom
+         mdroe at stsci.edu
+*/
+
+#define NO_IMPORT_ARRAY
+
+#include "pyutil.h"
+#include "str_list_proxy.h"
+
+/***************************************************************************
+ * List-of-units proxy object
+ ***************************************************************************/
+
+#define MAXSIZE 68
+
+static PyTypeObject PyUnitListProxyType;
+
+typedef struct {
+  PyObject_HEAD
+  /*@null@*/ /*@shared@*/ PyObject* pyobject;
+  Py_ssize_t size;
+  char (*array)[72];
+  PyObject* unit_class;
+} PyUnitListProxy;
+
+static void
+PyUnitListProxy_dealloc(
+    PyUnitListProxy* self) {
+
+  Py_XDECREF(self->pyobject);
+  Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+/*@null@*/ static PyObject *
+PyUnitListProxy_new(
+    PyTypeObject* type,
+    /*@unused@*/ PyObject* args,
+    /*@unused@*/ PyObject* kwds) {
+
+  PyUnitListProxy* self = NULL;
+
+  self = (PyUnitListProxy*)type->tp_alloc(type, 0);
+  if (self != NULL) {
+    self->pyobject = NULL;
+    self->unit_class = NULL;
+  }
+  return (PyObject*)self;
+}
+
+static int
+PyUnitListProxy_traverse(
+    PyUnitListProxy* self,
+    visitproc visit,
+    void *arg) {
+
+  int vret;
+
+  if (self->pyobject) {
+    vret = visit(self->pyobject, arg);
+    if (vret != 0) {
+      return vret;
+    }
+  }
+
+  if (self->unit_class) {
+    vret = visit(self->unit_class, arg);
+    if (vret != 0) {
+      return vret;
+    }
+  }
+
+  return 0;
+}
+
+static int
+PyUnitListProxy_clear(
+    PyUnitListProxy *self) {
+
+  PyObject *tmp;
+
+  tmp = self->pyobject;
+  self->pyobject = NULL;
+  Py_XDECREF(tmp);
+
+  tmp = self->unit_class;
+  self->unit_class = NULL;
+  Py_XDECREF(tmp);
+
+  return 0;
+}
+
+/*@null@*/ PyObject *
+PyUnitListProxy_New(
+    /*@shared@*/ PyObject* owner,
+    Py_ssize_t size,
+    char (*array)[72]) {
+
+  PyUnitListProxy* self = NULL;
+  PyObject *units_module;
+  PyObject *units_dict;
+  PyObject *unit_class;
+
+  units_module = PyImport_ImportModule("astropy.units");
+  if (units_module == NULL) {
+    return NULL;
+  }
+
+  units_dict = PyModule_GetDict(units_module);
+  if (units_dict == NULL) {
+    return NULL;
+  }
+
+  unit_class = PyDict_GetItemString(units_dict, "Unit");
+  if (unit_class == NULL) {
+    PyErr_SetString(PyExc_RuntimeError, "Could not import Unit class");
+    return NULL;
+  }
+
+  Py_INCREF(unit_class);
+
+  self = (PyUnitListProxy*)PyUnitListProxyType.tp_alloc(
+      &PyUnitListProxyType, 0);
+  if (self == NULL) {
+    return NULL;
+  }
+
+  Py_XINCREF(owner);
+  self->pyobject = owner;
+  self->size = size;
+  self->array = array;
+  self->unit_class = unit_class;
+  return (PyObject*)self;
+}
+
+static Py_ssize_t
+PyUnitListProxy_len(
+    PyUnitListProxy* self) {
+
+  return self->size;
+}
+
+static PyObject*
+_get_unit(
+    PyObject *unit_class,
+    PyObject *unit) {
+
+  PyObject *args;
+  PyObject *kw;
+  PyObject *fits;
+  PyObject *result;
+
+  args = PyTuple_New(1);
+  PyTuple_SetItem(args, 0, unit);
+  Py_INCREF(unit);
+  fits = PyUnicode_FromStringAndSize("fits", 4);
+  kw = PyDict_New();
+  PyDict_SetItemString(kw, "format", fits);
+
+  result = PyObject_Call(unit_class, args, kw);
+
+  Py_DECREF(args);
+  Py_DECREF(fits);
+  Py_DECREF(kw);
+  return result;
+}
+
+/*@null@*/ static PyObject*
+PyUnitListProxy_getitem(
+    PyUnitListProxy* self,
+    Py_ssize_t index) {
+
+  PyObject *value;
+  PyObject *result;
+
+  if (index >= self->size) {
+    PyErr_SetString(PyExc_IndexError, "index out of range");
+    return NULL;
+  }
+
+  value = PyUnicode_FromString(self->array[index]);
+
+  result = _get_unit(self->unit_class, value);
+
+  Py_DECREF(value);
+  return result;
+}
+
+static int
+PyUnitListProxy_setitem(
+    PyUnitListProxy* self,
+    Py_ssize_t index,
+    PyObject* arg) {
+
+  PyObject* value;
+  PyObject* unicode_value;
+  PyObject* bytes_value;
+
+  if (index > self->size) {
+    PyErr_SetString(PyExc_IndexError, "index out of range");
+    return -1;
+  }
+
+  value = _get_unit(self->unit_class, arg);
+  if (value == NULL) {
+    return -1;
+  }
+
+  unicode_value = PyObject_CallMethod(value, "to_string", "s", "fits");
+  if (unicode_value == NULL) {
+    Py_DECREF(value);
+    return -1;
+  }
+  Py_DECREF(value);
+
+  if (PyUnicode_Check(unicode_value)) {
+    bytes_value = PyUnicode_AsASCIIString(unicode_value);
+    if (bytes_value == NULL) {
+      Py_DECREF(unicode_value);
+      return -1;
+    }
+    Py_DECREF(unicode_value);
+  } else {
+    bytes_value = unicode_value;
+  }
+
+  strncpy(self->array[index], PyBytes_AsString(bytes_value), MAXSIZE);
+  Py_DECREF(bytes_value);
+
+  return 0;
+}
+
+/*@null@*/ static PyObject*
+PyUnitListProxy_repr(
+    PyUnitListProxy* self) {
+
+  return str_list_proxy_repr(self->array, self->size, MAXSIZE);
+}
+
+static PySequenceMethods PyUnitListProxy_sequence_methods = {
+  (lenfunc)PyUnitListProxy_len,
+  NULL,
+  NULL,
+  (ssizeargfunc)PyUnitListProxy_getitem,
+  NULL,
+  (ssizeobjargproc)PyUnitListProxy_setitem,
+  NULL,
+  NULL,
+  NULL,
+  NULL
+};
+
+static PyTypeObject PyUnitListProxyType = {
+  #if PY3K
+  PyVarObject_HEAD_INIT(NULL, 0)
+  #else
+  PyObject_HEAD_INIT(NULL)
+  0,                          /*ob_size*/
+  #endif
+  "astropy.wcs.UnitListProxy", /*tp_name*/
+  sizeof(PyUnitListProxy),  /*tp_basicsize*/
+  0,                          /*tp_itemsize*/
+  (destructor)PyUnitListProxy_dealloc, /*tp_dealloc*/
+  0,                          /*tp_print*/
+  0,                          /*tp_getattr*/
+  0,                          /*tp_setattr*/
+  0,                          /*tp_compare*/
+  (reprfunc)PyUnitListProxy_repr, /*tp_repr*/
+  0,                          /*tp_as_number*/
+  &PyUnitListProxy_sequence_methods, /*tp_as_sequence*/
+  0,                          /*tp_as_mapping*/
+  0,                          /*tp_hash */
+  0,                          /*tp_call*/
+  (reprfunc)PyUnitListProxy_repr, /*tp_str*/
+  0,                          /*tp_getattro*/
+  0,                          /*tp_setattro*/
+  0,                          /*tp_as_buffer*/
+  Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
+  0,                          /* tp_doc */
+  (traverseproc)PyUnitListProxy_traverse, /* tp_traverse */
+  (inquiry)PyUnitListProxy_clear, /* tp_clear */
+  0,                          /* tp_richcompare */
+  0,                          /* tp_weaklistoffset */
+  0,                          /* tp_iter */
+  0,                          /* tp_iternext */
+  0,                          /* tp_methods */
+  0,                          /* tp_members */
+  0,                          /* tp_getset */
+  0,                          /* tp_base */
+  0,                          /* tp_dict */
+  0,                          /* tp_descr_get */
+  0,                          /* tp_descr_set */
+  0,                          /* tp_dictoffset */
+  0,                          /* tp_init */
+  0,                          /* tp_alloc */
+  PyUnitListProxy_new,      /* tp_new */
+};
+
+
+int
+set_unit_list(
+    PyObject* owner,
+    const char* propname,
+    PyObject* value,
+    Py_ssize_t len,
+    char (*dest)[72]) {
+
+  PyObject*  unit  = NULL;
+  PyObject*  proxy = NULL;
+  Py_ssize_t i        = 0;
+
+  if (check_delete(propname, value)) {
+    return -1;
+  }
+
+  if (!PySequence_Check(value)) {
+    PyErr_Format(
+        PyExc_TypeError,
+        "'%s' must be a sequence of strings",
+        propname);
+    return -1;
+  }
+
+  if (PySequence_Size(value) != len) {
+    PyErr_Format(
+        PyExc_ValueError,
+        "len(%s) must be %u",
+        propname,
+        (unsigned int)len);
+    return -1;
+  }
+
+  proxy = PyUnitListProxy_New(owner, len, dest);
+
+  for (i = 0; i < len; ++i) {
+    unit = PySequence_GetItem(value, i);
+    if (unit == NULL) {
+      Py_DECREF(proxy);
+      return -1;
+    }
+
+    if (PySequence_SetItem(proxy, i, unit) == -1) {
+      Py_DECREF(proxy);
+      Py_DECREF(unit);
+      return -1;
+    }
+
+    Py_DECREF(unit);
+  }
+
+  Py_DECREF(proxy);
+
+  return 0;
+}
+
+
+int
+_setup_unit_list_proxy_type(
+    /*@unused@*/ PyObject* m) {
+
+  if (PyType_Ready(&PyUnitListProxyType) < 0) {
+    return 1;
+  }
+
+  return 0;
+}
diff --git a/astropy/wcs/src/wcslib/C/GNUmakefile b/astropy/wcs/src/wcslib/C/GNUmakefile
deleted file mode 100644
index b90a5d3..0000000
--- a/astropy/wcs/src/wcslib/C/GNUmakefile
+++ /dev/null
@@ -1,438 +0,0 @@
-#-----------------------------------------------------------------------------
-# GNU makefile for building WCSLIB 4.10 and its test suite.
-#
-# Summary of the main targets
-# ---------------------------
-#   build:     Build the library.
-#
-#   clean:     Delete intermediate object files.
-#
-#   cleaner:   clean, and also delete the test executables.
-#
-#   cleanest (distclean or realclean): cleaner, and also delete the object
-#              library the C source files generated by 'flex'.
-#
-#   check (or test): Compile and run the test programs.  By default they are
-#              executed in batch mode, and non-graphical tests only report
-#              "PASS" on success.  Use
-#
-#                make MODE=interactive check
-#
-#              to run them interactively with full diagnostic output.  To skip
-#              graphical tests even if PGPLOT is available, use
-#
-#                make CHECK=nopgplot check
-#
-#   tests:     Compile the test programs (but don't run them).
-#
-# Notes:
-#   1) If you need to make changes then preferably modify ../makedefs.in
-#      instead and re-run configure.
-#
-# Author: Mark Calabretta, Australia Telescope National Facility
-# http://www.atnf.csiro.au/~mcalabre/index.html
-# $Id: GNUmakefile,v 4.10 2012/02/05 23:41:44 cal103 Exp $
-#-----------------------------------------------------------------------------
-# Get configure settings.
-include ../makedefs
-
-FLEXMODS := $(patsubst %.l,%.c,$(wildcard *.l))
-MODULES  := $(sort \
-              $(patsubst %.c,%.o, \
-                $(filter-out getwcstab.c,$(wildcard *.c)) $(FLEXMODS)))
-
-ifeq "$(WCSTRIG)" "MACRO"
-  CPPFLAGS += -DWCSTRIG_MACRO
-  MODULES  := $(filter-out wcstrig.o, $(MODULES))
-else
-  ifeq "$(WCSTRIG)" "NATIVE"
-    MODULES := $(filter-out wcstrig.o, $(MODULES))
-  endif
-endif
-
-# For building the sharable library.
-PICLIB := libwcs-PIC.a
-
-CPPFLAGS += -I. -I..
-
-vpath %.c  test
-vpath %.h  ..
-vpath %.in ..
-
-
-# For building and exercising the test suite
-# ------------------------------------------
-# Signals tfitshdr to use wcshdr().
-ifneq "$(DO_WCSHDR)" ""
-  CPPFLAGS += -DDO_WCSHDR
-endif
-
-# Test programs that don't require CFITSIO or PGPLOT.
-TEST_N := tlin tlog tprj1 tsph tsphdpa tspx ttab1 twcs twcssub tpih1 tbth1 \
-          tfitshdr tunits twcsfix
-
-# Test programs that require CFITSIO (they don't need PGPLOT).
-TEST_C := twcstab twcshdr
-
-# Test programs that require PGPLOT but not PGSBOX.
-TEST_P := tspc tprj2 tcel1 tcel2 ttab2 ttab3 twcsmix
-
-# Test programs that require PGPLOT and PGSBOX.
-TEST_B := tpih2
-
-# Test programs that aren't automatically exercised.
-TEST_X := tsphdpa twcshdr
-
-TESTS  := $(TEST_N)
-
-# Add test programs that require CFITSIO if we have it.
-ifneq "$(CFITSIOINC)" ""
-ifneq "$(CFITSIOLIB)" ""
-  TESTS += $(TEST_C)
-endif
-endif
-
-# Add test programs that require PGPLOT if we have it.
-ifneq "$(CHECK)" "nopgplot"
-ifneq "$(PGPLOTINC)" ""
-ifneq "$(PGPLOTLIB)" ""
-  TESTS += $(TEST_P) $(TEST_B)
-endif
-endif
-endif
-
-# Remove tests that aren't automatically exercised.
-TESTS := $(filter-out $(TEST_X), $(TESTS))
-
-PGSBOXLIB := ../pgsbox/libpgsbox-$(LIBVER).a
-
-# Pattern rules
-#--------------
-
-ifeq "$(FLEX)" "flex"
-  %.c : %.l
-	-@ echo ''
-	-@ $(RM) $@
-	   $(FLEX) $(FLFLAGS) -t $< | sed -e 's/^[	 ]*#/#/' > $@
-else
-  %.c : %.l
-	-@ echo ''
-	-@ $(RM) $@
-	   cp flexed/$@ .
-endif
-
-$(WCSLIB)(%.o) : %.c
-	-@ echo ''
-	   $(CC) $(CPPFLAGS) $(CFLAGS) -c $<
-	   $(AR) r $(WCSLIB) $%
-	-@ $(RM) $%
-
-$(PICLIB)(%.o) : %.c
-	-@ echo ''
-	   $(CC) $(CPPFLAGS) $(CFLAGS) $(SHRFLAGS) -c $<
-	   $(AR) r $(PICLIB) $%
-	-@ $(RM) $%
-
-%.i : %.c
-	-@ echo ''
-	-@ $(RM) $@
-	   $(CPP) $(CPPFLAGS) $(CFLAGS) $< > $@
-
-# Print out include file dependencies.
-%.d : %.c
-	-@ echo ''
-	-@ $(CPP) $(CPPFLAGS) $(CFLAGS) $< | \
-	   sed -n -e 's|^# 1 "\([^/].*\.h\)".*|\1|p' | \
-	   sort -u
-
-# Use 'make FLAVOUR=Linux run_%' to have VALGRIND defined (from flavours).
-run_% : %
-	-@ echo ''
-	-@ $(TIMER)
-	 @ if [ '$(MODE)' = interactive -o '$(VALGRIND)' ] ; then \
-	     printf 'Press <CR> to run $<: ' ; \
-	     read DUMMY ; \
-	   fi ; \
-	   if [ '$(VALGRIND)' ] ; then \
-	     if [ '$<' = tunits ] ; then \
-	       $(VALGRIND) ./$< < test/units_test ; \
-	     else \
-	       $(VALGRIND) ./$< ; \
-	     fi ; \
-	   else \
-	     if [ '$(filter $<, $(TEST_N) $(TEST_C))' ] ; then \
-	       if [ '$<' = tunits ] ; then \
-	         if [ '$(MODE)' = interactive ] ; then \
-	           ./$< < test/units_test 2>&1 | tee $<.out ; \
-	         else \
-	           ./$< < test/units_test > $<.out 2>&1 ; \
-	         fi ; \
-	       else \
-	         if [ '$(MODE)' = interactive ] ; then \
-	           ./$< < /dev/null 2>&1 | tee $<.out ; \
-	         else \
-	           ./$< < /dev/null > $<.out 2>&1 ; \
-	         fi ; \
-	       fi ; \
-	       if grep 'PASS:' $<.out > /dev/null ; then \
-	         if [ '$(MODE)' != interactive ] ; then \
-	           head -2 $<.out ; \
-	           grep 'PASS:' $<.out ; \
-	         fi ; \
-	         echo 'PASS: C/$<' >> test_results ; \
-	       elif [ -f 'test/$<.out' ] ; then \
-	         trap 'rm -f run_test.tmp' 0 1 2 3 15 ; \
-	         sed -e 's/0x[0-9a-f][0-9a-f][0-9a-f]*/0x<address>/g' $<.out > \
-	           run_test.tmp ; \
-	         mv -f run_test.tmp $<.out ; \
-	         if cmp -s $<.out test/$<.out ; then \
-	           if [ '$(MODE)' != interactive ] ; then \
-	             head -1 $<.out ; \
-	           fi ; \
-	           echo '' ; \
-	           echo 'PASS: Output agrees with C/test/$<.out' ; \
-	           echo 'PASS: C/$<' >> test_results ; \
-	         else \
-	           if [ '$(MODE)' != interactive ] ; then \
-	             cat $<.out ; \
-	           fi ; \
-	           echo '' ; \
-	           echo 'FAIL: Output disagrees with C/test/$<.out' ; \
-	           echo 'FAIL: C/$<' >> test_results ; \
-	         fi ; \
-	       elif [ '$(MODE)' != interactive ] ; then \
-	         cat $<.out ; \
-	         echo 'FAIL: C/$<' >> test_results ; \
-	       fi ; \
-	     elif [ '$(MODE)' = interactive ] ; then \
-	       ./$< ; \
-	     else \
-	       if [ '$<' = tcel2 ] ; then \
-	         echo N | ./$< ; \
-	       else \
-	         ./$< < /dev/null 2>&1 ; \
-	       fi ; \
-	     fi ; \
-	   fi
-	-@ echo ''
-
-# Static and static pattern rules
-#--------------------------------
-
-.PHONY : build check clean cleaner cleanest distclean install lib realclean \
-         run_% test tests
-
-build : lib
-
-lib : $(FLEXMODS) $(WCSLIB) $(SHRLIB)
-
-$(WCSLIB) : $(MODULES:%=$(WCSLIB)(%))
-	-@ echo ''
-	   $(RANLIB) $@
-
-$(SHRLIB) : $(PICLIB)
-	-@ echo ''
-	-@ $(RM) -r tmp
-	   mkdir tmp && \
-	     cd tmp && \
-	     trap 'cd .. ; $(RM) -r tmp' 0 1 2 3 15 ; \
-	     $(AR) x ../$(PICLIB) && \
-	     $(SHRLD) $(LDFLAGS) -o $@ *.o && \
-	     mv $@ ..
-
-$(PICLIB) : $(MODULES:%.o=$(PICLIB)(%.o)) ;
-
-install : build
-	-  if [ ! -d "$(LIBDIR)" ] ; then \
-	     $(INSTALL) -d -m 2775 $(LIBDIR) ; \
-	   fi
-	   $(INSTALL) -m 644 $(WCSLIB) $(LIBDIR)
-	   $(RANLIB) $(LIBDIR)/$(WCSLIB)
-	-  if [ -h "$(LIBDIR)/libwcs.a" ] ; then \
-	     $(RM) $(LIBDIR)/libwcs.a ; \
-	   fi
-	-  $(LN_S) $(WCSLIB) $(LIBDIR)/libwcs.a
-	-  if [ "$(SHRLIB)" != "" ] ; then \
-	     $(INSTALL) -m 644 $(SHRLIB) $(LIBDIR) ; \
-	     if [ -h "$(LIBDIR)/$(SONAME)" ] ; then \
-	       $(RM) $(LIBDIR)/$(SONAME) ; \
-	     fi ; \
-	     $(LN_S) $(SHRLIB) $(LIBDIR)/$(SONAME) ; \
-	     if [ "$(SHRLN)" != "" ] ; then \
-	       if [ -h "$(LIBDIR)/$(SHRLN)" ] ; then \
-	         $(RM) $(LIBDIR)/$(SHRLN) ; \
-	       fi ; \
-	       $(LN_S) $(SONAME) $(LIBDIR)/$(SHRLN) ; \
-	     fi ; \
-	   fi
-	-  if [ ! -d "$(INCDIR)" ] ; then \
-	     $(INSTALL) -d -m 2775 $(INCDIR) ; \
-	   fi
-	   $(INSTALL) -m 444 *.h $(INCDIR)
-	   $(RM) $(INCLINK)
-	   $(LN_S) $(notdir $(INCDIR)) $(INCLINK)
-
-clean :
-	- $(RM) -r *.o *.i a.out t*.out core *.dSYM $(EXTRA_CLEAN)
-
-cleaner : clean
-	-  $(RM) .gdb_history
-	-  $(RM) $(TEST_N) $(TEST_X)
-	-  $(RM) $(TEST_P) tpih2 twcstab twcshdr
-	-  $(RM) tofits bth.fits pih.fits wcstab.fits
-	-  $(RM) t*_cfitsio test_results
-
-cleanest distclean realclean : cleaner
-	-  $(RM) ../wcsconfig.h ../wcsconfig_tests.h
-	-  $(RM) fitshdr.c wcsbth.c wcspih.c wcsulex.c wcsutrn.c
-	-  $(RM) $(PICLIB) libwcs-*.a libwcs.so.* libwcs.*.dylib
-
-check test : tests $(TESTS:%=run_%)
-
-tests : $(TESTS) $(TEST_X)
-
-$(TEST_N) : % : test/%.c $(WCSLIB)
-	-@ echo ''
-	   $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ $< $(WCSLIB) $(LIBS)
-	-@ $(RM) $@.o
-
-$(TEST_P) : % : test/%.c $(WCSLIB)
-	-@ echo ''
-	   $(CC) $(CPPFLAGS) $(PGPLOTINC) $(CFLAGS) -c -o $@.o $<
-	   $(LD) $(LDFLAGS) -o $@ $@.o $(PGPLOTLIB) $(WCSLIB) $(FLIBS) $(LIBS)
-	-@ $(RM) $@.o
-
-tpih2 : test/tpih2.c $(PGSBOXLIB) $(WCSLIB)
-	-@ echo ''
-	   $(CC) $(CPPFLAGS) -I../pgsbox $(PGPLOTINC) $(CFLAGS) -c -o $@.o $<
-	   $(LD) $(LDFLAGS) -o $@ $@.o $(PGSBOXLIB) $(PGPLOTLIB) $(WCSLIB) \
-	     $(FLIBS) $(LIBS)
-	-@ $(RM) $@.o
-
-tfitshdr_cfitsio tpih1_cfitsio tbth1_cfitsio : %_cfitsio : test/%.c $(WCSLIB)
-	-@ echo ''
-	   $(CC) -DDO_CFITSIO $(CPPFLAGS) $(CFITSIOINC) $(CFLAGS) \
-	     $(LDFLAGS) -o $@ $< $(CFITSIOLIB) $(WCSLIB) $(LIBS)
-	-@ $(RM) $@.o
-
-tpih2_cfitsio : test/tpih2.c $(PGSBOXLIB) $(WCSLIB)
-	-@ echo ''
-	   $(CC) -DDO_CFITSIO $(CPPFLAGS) -I../pgsbox $(PGPLOTINC) \
-	     $(CFITSIOINC) $(CFLAGS) -c -o $@.o $<
-	   $(LD) $(LDFLAGS) -o $@ $@.o $(PGSBOXLIB) $(PGPLOTLIB) \
-	     $(CFITSIOLIB) $(WCSLIB) $(FLIBS) $(LIBS)
-	-@ $(RM) $@.o
-
-twcstab : test/twcstab.c $(GETWCSTAB) $(WCSLIB)
-	-@ echo ''
-	   $(CC) $(CPPFLAGS) $(CFITSIOINC) $(CFLAGS) $(LDFLAGS) -o $@ $< \
-	     $(GETWCSTAB) $(CFITSIOLIB) $(WCSLIB) $(LIBS)
-	-@ $(RM) $@.o
-
-twcshdr : test/twcshdr.c $(GETWCSTAB) $(WCSLIB)
-	-@ echo ''
-	   $(CC) $(CPPFLAGS) $(CFITSIOINC) $(CFLAGS) $(LDFLAGS) -o $@ $< \
-	     $(GETWCSTAB) $(CFITSIOLIB) $(WCSLIB) $(LIBS)
-	-@ $(RM) $@.o
-
-getwcstab.o : getwcstab.c getwcstab.h
-	-@ echo ''
-	   $(CC) $(CPPFLAGS) $(CFLAGS) $(CFITSIOINC) -c $<
-
-$(PGSBOXLIB) :
-	-@ echo ''
-	   $(MAKE) -C ../pgsbox lib
-
-tofits : test/tofits.c
-	   $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $<
-
-pih.fits : test/pih.keyrec tofits
-	   ./tofits < $< > $@
-
-bth.fits : test/bth.keyrec tofits
-	   ./tofits < $< > $@
-
-GNUmakefile : ../makedefs ;
-
-../makedefs ../wcsconfig.h ../wcsconfig_tests.h : makedefs.in wcsconfig.h.in \
-    wcsconfig_tests.h.in ../config.status
-	-@ $(RM) ../wcsconfig.h ../wcsconfig_tests.h
-	   cd .. && ./config.status
-
-show ::
-	-@ -@ echo '  FLEXMODS    := $(FLEXMODS)'
-	-@ -@ echo '  MODULES     := $(MODULES)'
-
-# Dependencies (use the %.d pattern rule to list them)
-#-----------------------------------------------------
-
-$(WCSLIB)(cel.o)      : cel.h prj.h sph.h wcsconfig.h wcserr.h wcsmath.h \
-                        wcsprintf.h wcstrig.h
-$(WCSLIB)(fitshdr.o)  : wcsconfig.h fitshdr.h
-$(WCSLIB)(lin.o)      : lin.h wcserr.h wcsprintf.h
-$(WCSLIB)(log.o)      : log.h
-$(WCSLIB)(prj.o)      : prj.h wcsconfig.h wcserr.h wcsmath.h wcsprintf.h \
-                        wcstrig.h wcsutil.h
-$(WCSLIB)(spc.o)      : spc.h spx.h wcserr.h wcsmath.h wcsprintf.h wcstrig.h \
-                        wcsutil.h
-$(WCSLIB)(sph.o)      : sph.h wcsconfig.h wcstrig.h
-$(WCSLIB)(spx.o)      : spx.h wcserr.h wcsmath.h
-$(WCSLIB)(tab.o)      : tab.h wcserr.h wcsmath.h wcsprintf.h
-$(WCSLIB)(wcs.o)      : cel.h lin.h log.h prj.h spc.h sph.h spx.h tab.h \
-                        wcs.h wcsconfig.h wcserr.h wcsmath.h wcsprintf.h \
-                        wcstrig.h wcsunits.h wcsutil.h
-$(WCSLIB)(wcsbth.o)   : cel.h lin.h prj.h spc.h spx.h tab.h wcs.h wcserr.h \
-                        wcshdr.h wcsmath.h
-$(WCSLIB)(wcserr.o)   : wcserr.h wcsprintf.h
-$(WCSLIB)(wcsfix.o)   : cel.h lin.h prj.h spc.h sph.h spx.h tab.h wcs.h \
-                        wcserr.h wcsfix.h wcsmath.h wcsunits.h wcsutil.h
-$(WCSLIB)(wcshdr.o)   : cel.h lin.h prj.h spc.h spx.h tab.h wcs.h wcserr.h \
-                        wcshdr.h wcsmath.h wcsutil.h
-$(WCSLIB)(wcspih.o)   : cel.h lin.h prj.h spc.h spx.h tab.h wcs.h wcserr.h \
-                        wcshdr.h wcsmath.h
-$(WCSLIB)(wcsprintf.o): wcsprintf.h
-$(WCSLIB)(wcstrig.o)  : wcsconfig.h wcsmath.h wcstrig.h
-$(WCSLIB)(wcsulex.o)  : wcserr.h wcsmath.h wcsunits.h
-$(WCSLIB)(wcsunits.o) : wcserr.h wcsunits.h
-$(WCSLIB)(wcsutil.o)  : wcsutil.h
-$(WCSLIB)(wcsutrn.o)  : wcserr.h wcsunits.h
-
-tbth1 tbth1_cfitsio : cel.h lin.h prj.h spc.h spx.h tab.h wcs.h wcsconfig.h \
-                      wcsconfig_tests.h wcserr.h wcsfix.h wcshdr.h
-tcel1   : cel.h prj.h wcserr.h
-tcel2   : cel.h prj.h wcserr.h
-tfitshdr tfitshdr_cfitsio : fitshdr.h wcsconfig.h wcsconfig_tests.h
-tlin    : lin.h wcserr.h
-tlog    : log.h
-tpih1 tpih1_cfitsio : cel.h lin.h prj.h spc.h spx.h tab.h wcs.h wcsconfig.h \
-                      wcsconfig_tests.h wcserr.h wcsfix.h wcshdr.h wcsprintf.h
-tpih2 tpih2_cfitsio : cel.h lin.h prj.h spc.h spx.h tab.h wcs.h wcsconfig.h \
-                      wcsconfig_tests.h wcserr.h wcshdr.h
-tprj1   : prj.h wcsconfig.h wcserr.h wcstrig.h
-tprj2   : prj.h wcserr.h
-tspc    : spc.h spx.h wcsconfig.h wcserr.h wcstrig.h
-tsph    : sph.h wcsconfig.h wcstrig.h
-tsphdpa : sph.h
-tspx    : spx.h wcserr.h
-ttab1   : tab.h wcserr.h
-ttab2   : tab.h wcserr.h
-ttab3   : prj.h tab.h wcserr.h
-tunits  : wcserr.h wcsunits.h
-twcs    : cel.h lin.h log.h prj.h spc.h sph.h spx.h tab.h wcs.h wcsconfig.h \
-          wcsconfig_tests.h wcserr.h wcsfix.h wcshdr.h wcslib.h wcsmath.h \
-          wcsprintf.h wcstrig.h wcsunits.h wcsutil.h
-twcsfix : cel.h lin.h prj.h spc.h spx.h tab.h wcs.h wcserr.h wcsfix.h \
-          wcsunits.h
-twcshdr : cel.h fitshdr.h getwcstab.h lin.h log.h prj.h spc.h sph.h spx.h \
-          tab.h wcs.h wcsconfig.h wcserr.h wcsfix.h wcshdr.h wcslib.h \
-          wcsmath.h wcsprintf.h wcstrig.h wcsunits.h wcsutil.h
-twcsmix : cel.h lin.h prj.h spc.h sph.h spx.h tab.h wcs.h wcserr.h
-twcssub : cel.h lin.h prj.h spc.h spx.h tab.h wcs.h wcserr.h
-twcstab : cel.h fitshdr.h getwcstab.h lin.h log.h prj.h spc.h sph.h spx.h \
-          tab.h wcs.h wcsconfig.h wcserr.h wcsfix.h wcshdr.h wcslib.h \
-          wcsmath.h wcsprintf.h wcstrig.h wcsunits.h wcsutil.h
-
-run_tbth1 run_tbth1_cfitsio : bth.fits
-run_tfitshdr run_tfitshdr_cfitsio : pih.fits
-run_tpih1 run_tpih1_cfitsio : pih.fits
-run_tpih2 run_tpih2_cfitsio : pih.fits
diff --git a/astropy/wcs/src/wcslib/C/cel.c b/astropy/wcs/src/wcslib/C/cel.c
deleted file mode 100644
index 32b072f..0000000
--- a/astropy/wcs/src/wcslib/C/cel.c
+++ /dev/null
@@ -1,508 +0,0 @@
-/*============================================================================
-
-  WCSLIB 4.10 - an implementation of the FITS WCS standard.
-  Copyright (C) 1995-2012, Mark Calabretta
-
-  This file is part of WCSLIB.
-
-  WCSLIB is free software: you can redistribute it and/or modify it under the
-  terms of the GNU Lesser General Public License as published by the Free
-  Software Foundation, either version 3 of the License, or (at your option)
-  any later version.
-
-  WCSLIB 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 Lesser General Public License for
-  more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with WCSLIB.  If not, see <http://www.gnu.org/licenses/>.
-
-  Correspondence concerning WCSLIB may be directed to:
-    Internet email: mcalabre at atnf.csiro.au
-    Postal address: Dr. Mark Calabretta
-                    Australia Telescope National Facility, CSIRO
-                    PO Box 76
-                    Epping NSW 1710
-                    AUSTRALIA
-
-  Author: Mark Calabretta, Australia Telescope National Facility
-  http://www.atnf.csiro.au/~mcalabre/index.html
-  $Id: cel.c,v 4.10 2012/02/05 23:41:44 cal103 Exp $
-*===========================================================================*/
-
-#include <math.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "wcserr.h"
-#include "wcsmath.h"
-#include "wcsprintf.h"
-#include "wcstrig.h"
-#include "sph.h"
-#include "cel.h"
-
-const int CELSET = 137;
-
-/* Map status return value to message. */
-const char *cel_errmsg[] = {
-  "Success",
-  "Null celprm pointer passed",
-  "Invalid projection parameters",
-  "Invalid coordinate transformation parameters",
-  "Ill-conditioned coordinate transformation parameters",
-  "One or more of the (x,y) coordinates were invalid",
-  "One or more of the (lng,lat) coordinates were invalid"};
-
-/* Convenience macro for invoking wcserr_set(). */
-#define CEL_ERRMSG(status) WCSERR_SET(status), cel_errmsg[status]
-
-/*--------------------------------------------------------------------------*/
-
-int celini(cel)
-
-struct celprm *cel;
-
-{
-  register int k;
-
-  if (cel == 0x0) return CELERR_NULL_POINTER;
-
-  cel->flag = 0;
-
-  cel->offset = 0;
-  cel->phi0   = UNDEFINED;
-  cel->theta0 = UNDEFINED;
-  cel->ref[0] =   0.0;
-  cel->ref[1] =   0.0;
-  cel->ref[2] = UNDEFINED;
-  cel->ref[3] = +90.0;
-
-  for (k = 0; k < 5; cel->euler[k++] = 0.0);
-  cel->latpreq = -1;
-
-  cel->err = 0x0;
-
-  return prjini(&(cel->prj));
-}
-
-/*--------------------------------------------------------------------------*/
-
-int celfree(cel)
-
-struct celprm *cel;
-
-{
-  if (cel == 0x0) return CELERR_NULL_POINTER;
-
-  if (cel->err) free(cel->err);
-  cel->err = 0x0;
-
-  prjfree(&(cel->prj));
-
-  return 0;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int celprt(cel)
-
-const struct celprm *cel;
-
-{
-  int i;
-
-  if (cel == 0x0) return CELERR_NULL_POINTER;
-
-  wcsprintf("      flag: %d\n",  cel->flag);
-  wcsprintf("     offset: %d\n",  cel->offset);
-  if (undefined(cel->phi0)) {
-    wcsprintf("       phi0: UNDEFINED\n");
-  } else {
-    wcsprintf("       phi0: %9f\n", cel->phi0);
-  }
-  if (undefined(cel->theta0)) {
-    wcsprintf("     theta0: UNDEFINED\n");
-  } else {
-    wcsprintf("     theta0: %9f\n", cel->theta0);
-  }
-  wcsprintf("       ref:");
-  for (i = 0; i < 4; i++) {
-    wcsprintf("  %- 11.5g", cel->ref[i]);
-  }
-  wcsprintf("\n");
-  wcsprintf("       prj: (see below)\n");
-
-  wcsprintf("     euler:");
-  for (i = 0; i < 5; i++) {
-    wcsprintf("  %- 11.5g", cel->euler[i]);
-  }
-  wcsprintf("\n");
-  wcsprintf("    latpreq: %d", cel->latpreq);
-  if (cel->latpreq == 0) {
-    wcsprintf(" (not required)\n");
-  } else if (cel->latpreq == 1) {
-    wcsprintf(" (disambiguation)\n");
-  } else if (cel->latpreq == 2) {
-    wcsprintf(" (specification)\n");
-  } else {
-    wcsprintf(" (UNDEFINED)\n");
-  }
-  wcsprintf("     isolat: %d\n", cel->isolat);
-
-  WCSPRINTF_PTR("        err: ", cel->err, "\n");
-  if (cel->err) {
-    wcserr_prt(cel->err, "             ");
-  }
-
-  wcsprintf("\n");
-  wcsprintf("   prj.*\n");
-  prjprt(&(cel->prj));
-
-  return 0;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int celset(cel)
-
-struct celprm *cel;
-
-{
-  static const char *function = "celset";
-
-  const double tol = 1.0e-10;
-  double clat0, cphip, cthe0, lat0, lng0, phip, slat0, slz, sphip, sthe0;
-  double latp, latp1, latp2, lngp;
-  double u, v, x, y, z;
-  struct prjprm *celprj;
-  struct wcserr **err;
-
-  if (cel == 0x0) return CELERR_NULL_POINTER;
-  err = &(cel->err);
-
-  /* Initialize the projection driver routines. */
-  celprj = &(cel->prj);
-  if (cel->offset) {
-    celprj->phi0   = cel->phi0;
-    celprj->theta0 = cel->theta0;
-  } else {
-    /* Ensure that these are undefined - no fiducial offset. */
-    celprj->phi0   = UNDEFINED;
-    celprj->theta0 = UNDEFINED;
-  }
-
-  if (prjset(celprj)) {
-    return wcserr_set(CEL_ERRMSG(CELERR_BAD_PARAM));
-  }
-
-  /* Defaults set by the projection routines. */
-  if (undefined(cel->phi0)) {
-    cel->phi0 = celprj->phi0;
-  }
-
-  if (undefined(cel->theta0)) {
-    cel->theta0 = celprj->theta0;
-
-  } else if (fabs(cel->theta0) > 90.0) {
-    if (fabs(cel->theta0) > 90.0 + tol) {
-      return wcserr_set(WCSERR_SET(CELERR_BAD_COORD_TRANS),
-        "Invalid coordinate transformation parameters: theta0 > 90");
-    }
-
-    if (cel->theta0 > 90.0) {
-      cel->theta0 =  90.0;
-    } else {
-      cel->theta0 = -90.0;
-    }
-  }
-
-
-  lng0 = cel->ref[0];
-  lat0 = cel->ref[1];
-  phip = cel->ref[2];
-  latp = cel->ref[3];
-
-  /* Set default for native longitude of the celestial pole? */
-  if (undefined(phip) || phip == 999.0) {
-    phip = (lat0 < cel->theta0) ? 180.0 : 0.0;
-    phip += cel->phi0;
-
-    if (phip < -180.0) {
-      phip += 360.0;
-    } else if (phip > 180.0) {
-      phip -= 360.0;
-    }
-
-    cel->ref[2] = phip;
-  }
-
-
-  /* Compute celestial coordinates of the native pole. */
-  cel->latpreq = 0;
-  if (cel->theta0 == 90.0) {
-    /* Fiducial point at the native pole. */
-    lngp = lng0;
-    latp = lat0;
-
-  } else {
-    /* Fiducial point away from the native pole. */
-    sincosd(lat0, &slat0, &clat0);
-    sincosd(cel->theta0, &sthe0, &cthe0);
-
-    if (phip == cel->phi0) {
-      sphip = 0.0;
-      cphip = 1.0;
-
-      u = cel->theta0;
-      v = 90.0 - lat0;
-
-    } else {
-      sincosd(phip - cel->phi0, &sphip, &cphip);
-
-      x = cthe0*cphip;
-      y = sthe0;
-      z = sqrt(x*x + y*y);
-      if (z == 0.0) {
-        if (slat0 != 0.0) {
-          return wcserr_set(WCSERR_SET(CELERR_BAD_COORD_TRANS),
-            "Invalid coordinate description:\n"
-            "lat0 == 0 is required for |phip - phi0| = 90 and theta0 == 0");
-        }
-
-        /* latp determined solely by LATPOLEa in this case. */
-        cel->latpreq = 2;
-        if (latp > 90.0) {
-          latp = 90.0;
-        } else if (latp < -90.0) {
-          latp = -90.0;
-        }
-
-      } else {
-        slz = slat0/z;
-        if (fabs(slz) > 1.0) {
-          if ((fabs(slz) - 1.0) < tol) {
-            if (slz > 0.0) {
-              slz = 1.0;
-            } else {
-              slz = -1.0;
-            }
-          } else {
-            return wcserr_set(WCSERR_SET(CELERR_BAD_COORD_TRANS),
-              "Invalid coordinate description:\n|lat0| <= %.3f is required "
-              "for these values of phip, phi0, and theta0", asind(z));
-          }
-        }
-
-        u = atan2d(y,x);
-        v = acosd(slz);
-      }
-    }
-
-    if (cel->latpreq == 0) {
-      latp1 = u + v;
-      if (latp1 > 180.0) {
-        latp1 -= 360.0;
-      } else if (latp1 < -180.0) {
-        latp1 += 360.0;
-      }
-
-      latp2 = u - v;
-      if (latp2 > 180.0) {
-        latp2 -= 360.0;
-      } else if (latp2 < -180.0) {
-        latp2 += 360.0;
-      }
-
-      if (fabs(latp1) < 90.0+tol &&
-          fabs(latp2) < 90.0+tol) {
-        /* There are two valid solutions for latp. */
-        cel->latpreq = 1;
-      }
-
-      if (fabs(latp-latp1) < fabs(latp-latp2)) {
-        if (fabs(latp1) < 90.0+tol) {
-          latp = latp1;
-        } else {
-          latp = latp2;
-        }
-      } else {
-        if (fabs(latp2) < 90.0+tol) {
-          latp = latp2;
-        } else {
-          latp = latp1;
-        }
-      }
-
-      /* Account for rounding error. */
-      if (fabs(latp) < 90.0+tol) {
-        if (latp > 90.0) {
-          latp =  90.0;
-        } else if (latp < -90.0) {
-          latp = -90.0;
-        }
-      }
-    }
-
-    z = cosd(latp)*clat0;
-    if (fabs(z) < tol) {
-      if (fabs(clat0) < tol) {
-        /* Celestial pole at the fiducial point. */
-        lngp = lng0;
-
-      } else if (latp > 0.0) {
-        /* Celestial north pole at the native pole.*/
-        lngp = lng0 + phip - cel->phi0 - 180.0;
-
-      } else {
-        /* Celestial south pole at the native pole. */
-        lngp = lng0 - phip + cel->phi0;
-      }
-
-    } else {
-      x = (sthe0 - sind(latp)*slat0)/z;
-      y =  sphip*cthe0/clat0;
-      if (x == 0.0 && y == 0.0) {
-        /* Sanity check (shouldn't be possible). */
-        return wcserr_set(WCSERR_SET(CELERR_BAD_COORD_TRANS),
-          "Invalid coordinate transformation parameters, internal error");
-      }
-      lngp = lng0 - atan2d(y,x);
-    }
-
-    /* Make celestial longitude of the native pole the same sign as at the
-       fiducial point. */
-    if (lng0 >= 0.0) {
-      if (lngp < 0.0) {
-        lngp += 360.0;
-      } else if (lngp > 360.0) {
-        lngp -= 360.0;
-      }
-    } else {
-      if (lngp > 0.0) {
-        lngp -= 360.0;
-      } else if (lngp < -360.0) {
-        lngp += 360.0;
-      }
-    }
-  }
-
-  /* Reset LATPOLEa. */
-  cel->ref[3] = latp;
-
-  /* Set the Euler angles. */
-  cel->euler[0] = lngp;
-  cel->euler[1] = 90.0 - latp;
-  cel->euler[2] = phip;
-  sincosd(cel->euler[1], &cel->euler[4], &cel->euler[3]);
-  cel->isolat = (cel->euler[4] == 0.0);
-  cel->flag = CELSET;
-
-  /* Check for ill-conditioned parameters. */
-  if (fabs(latp) > 90.0+tol) {
-    return wcserr_set(WCSERR_SET(CELERR_ILL_COORD_TRANS),
-      "Ill-conditioned coordinate transformation parameters\nNo valid "
-      "solution for latp for these values of phip, phi0, and theta0");
-  }
-
-  return 0;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int celx2s(cel, nx, ny, sxy, sll, x, y, phi, theta, lng, lat, stat)
-
-struct celprm *cel;
-int nx, ny, sxy, sll;
-const double x[], y[];
-double phi[], theta[];
-double lng[], lat[];
-int stat[];
-
-{
-  static const char *function = "celx2s";
-
-  int    nphi, status;
-  struct prjprm *celprj;
-  struct wcserr **err;
-
-  /* Initialize. */
-  if (cel == 0x0) return CELERR_NULL_POINTER;
-  err = &(cel->err);
-
-  if (cel->flag != CELSET) {
-    if ((status = celset(cel))) return status;
-  }
-
-  /* Apply spherical deprojection. */
-  celprj = &(cel->prj);
-  if ((status = celprj->prjx2s(celprj, nx, ny, sxy, 1, x, y, phi, theta,
-                               stat))) {
-    if (status == PRJERR_BAD_PIX) {
-      status = CELERR_BAD_PIX;
-    }
-
-    wcserr_set(CEL_ERRMSG(status));
-
-    if (status != CELERR_BAD_PIX) return status;
-  }
-
-  nphi = (ny > 0) ? (nx*ny) : nx;
-
-  /* Compute celestial coordinates. */
-  sphx2s(cel->euler, nphi, 0, 1, sll, phi, theta, lng, lat);
-
-  return status;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int cels2x(cel, nlng, nlat, sll, sxy, lng, lat, phi, theta, x, y, stat)
-
-struct celprm *cel;
-int nlng, nlat, sll, sxy;
-const double lng[], lat[];
-double phi[], theta[];
-double x[], y[];
-int stat[];
-
-{
-  static const char *function = "cels2x";
-
-  int    nphi, ntheta, status;
-  struct prjprm *celprj;
-  struct wcserr **err;
-
-  /* Initialize. */
-  if (cel == 0x0) return CELERR_NULL_POINTER;
-  err = &(cel->err);
-
-  if (cel->flag != CELSET) {
-    if ((status = celset(cel))) return status;
-  }
-
-  /* Compute native coordinates. */
-  sphs2x(cel->euler, nlng, nlat, sll, 1, lng, lat, phi, theta);
-
-  if (cel->isolat) {
-    /* Constant celestial latitude -> constant native latitude. */
-    nphi   = nlng;
-    ntheta = nlat;
-  } else {
-    nphi   = (nlat > 0) ? (nlng*nlat) : nlng;
-    ntheta = 0;
-  }
-
-  /* Apply the spherical projection. */
-  celprj = &(cel->prj);
-  if ((status = celprj->prjs2x(celprj, nphi, ntheta, 1, sxy, phi, theta, x, y,
-                               stat))) {
-    if (status != PRJERR_BAD_PARAM) {
-      status = CELERR_BAD_WORLD;
-    }
-
-    return wcserr_set(CEL_ERRMSG(status));
-  }
-
-  return 0;
-}
diff --git a/astropy/wcs/src/wcslib/C/cel.h b/astropy/wcs/src/wcslib/C/cel.h
deleted file mode 100644
index 4d9dbe8..0000000
--- a/astropy/wcs/src/wcslib/C/cel.h
+++ /dev/null
@@ -1,441 +0,0 @@
-/*============================================================================
-
-  WCSLIB 4.10 - an implementation of the FITS WCS standard.
-  Copyright (C) 1995-2012, Mark Calabretta
-
-  This file is part of WCSLIB.
-
-  WCSLIB is free software: you can redistribute it and/or modify it under the
-  terms of the GNU Lesser General Public License as published by the Free
-  Software Foundation, either version 3 of the License, or (at your option)
-  any later version.
-
-  WCSLIB 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 Lesser General Public License for
-  more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with WCSLIB.  If not, see <http://www.gnu.org/licenses/>.
-
-  Correspondence concerning WCSLIB may be directed to:
-    Internet email: mcalabre at atnf.csiro.au
-    Postal address: Dr. Mark Calabretta
-                    Australia Telescope National Facility, CSIRO
-                    PO Box 76
-                    Epping NSW 1710
-                    AUSTRALIA
-
-  Author: Mark Calabretta, Australia Telescope National Facility
-  http://www.atnf.csiro.au/~mcalabre/index.html
-  $Id: cel.h,v 4.10 2012/02/05 23:41:44 cal103 Exp $
-*=============================================================================
-*
-* WCSLIB 4.10 - C routines that implement the FITS World Coordinate System
-* (WCS) standard.  Refer to
-*
-*   "Representations of world coordinates in FITS",
-*   Greisen, E.W., & Calabretta, M.R. 2002, A&A, 395, 1061 (Paper I)
-*
-*   "Representations of celestial coordinates in FITS",
-*   Calabretta, M.R., & Greisen, E.W. 2002, A&A, 395, 1077 (Paper II)
-*
-* Refer to the README file provided with WCSLIB for an overview of the
-* library.
-*
-*
-* Summary of the cel routines
-* ---------------------------
-* These routines implement the part of the FITS World Coordinate System (WCS)
-* standard that deals with celestial coordinates.  They define methods to be
-* used for computing celestial world coordinates from intermediate world
-* coordinates (a linear transformation of image pixel coordinates), and vice
-* versa.  They are based on the celprm struct which contains all information
-* needed for the computations.  This struct contains some elements that must
-* be set by the user, and others that are maintained by these routines,
-* somewhat like a C++ class but with no encapsulation.
-*
-* Routine celini() is provided to initialize the celprm struct with default
-* values, celfree() reclaims any memory that may have been allocated to store
-* an error message, and celprt() prints its contents.
-*
-* A setup routine, celset(), computes intermediate values in the celprm struct
-* from parameters in it that were supplied by the user.  The struct always
-* needs to be set up by celset() but it need not be called explicitly - refer
-* to the explanation of celprm::flag.
-*
-* celx2s() and cels2x() implement the WCS celestial coordinate
-* transformations.  In fact, they are high level driver routines for the lower
-* level spherical coordinate rotation and projection routines described in
-* sph.h and prj.h.
-*
-*
-* celini() - Default constructor for the celprm struct
-* ----------------------------------------------------
-* celini() sets all members of a celprm struct to default values.  It should
-* be used to initialize every celprm struct.
-*
-* Returned:
-*   cel       struct celprm*
-*                       Celestial transformation parameters.
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         1: Null celprm pointer passed.
-*
-*
-* celfree() - Destructor for the celprm struct
-* --------------------------------------------
-* celfree() frees any memory that may have been allocated to store an error
-* message in the celprm struct.
-*
-* Given:
-*   cel       struct celprm*
-*                       Celestial transformation parameters.
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         1: Null celprm pointer passed.
-*
-*
-* celprt() - Print routine for the celprm struct
-* ----------------------------------------------
-* celprt() prints the contents of a celprm struct using wcsprintf().  Mainly
-* intended for diagnostic purposes.
-*
-* Given:
-*   cel       const struct celprm*
-*                       Celestial transformation parameters.
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         1: Null celprm pointer passed.
-*
-*
-* celset() - Setup routine for the celprm struct
-* ----------------------------------------------
-* celset() sets up a celprm struct according to information supplied within
-* it.
-*
-* Note that this routine need not be called directly; it will be invoked by
-* celx2s() and cels2x() if celprm::flag is anything other than a predefined
-* magic value.
-*
-* Given and returned:
-*   cel       struct celprm*
-*                       Celestial transformation parameters.
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         1: Null celprm pointer passed.
-*                         2: Invalid projection parameters.
-*                         3: Invalid coordinate transformation parameters.
-*                         4: Ill-conditioned coordinate transformation
-*                            parameters.
-*
-*                       For returns > 1, a detailed error message is set in
-*                       celprm::err if enabled, see wcserr_enable().
-*
-*
-* celx2s() - Pixel-to-world celestial transformation
-* --------------------------------------------------
-* celx2s() transforms (x,y) coordinates in the plane of projection to
-* celestial coordinates (lng,lat).
-*
-* Given and returned:
-*   cel       struct celprm*
-*                       Celestial transformation parameters.
-*
-* Given:
-*   nx,ny     int       Vector lengths.
-*
-*   sxy,sll   int       Vector strides.
-*
-*   x,y       const double[]
-*                       Projected coordinates in pseudo "degrees".
-*
-* Returned:
-*   phi,theta double[]  Longitude and latitude (phi,theta) in the native
-*                       coordinate system of the projection [deg].
-*
-*   lng,lat   double[]  Celestial longitude and latitude (lng,lat) of the
-*                       projected point [deg].
-*
-*   stat      int[]     Status return value for each vector element:
-*                         0: Success.
-*                         1: Invalid value of (x,y).
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         1: Null celprm pointer passed.
-*                         2: Invalid projection parameters.
-*                         3: Invalid coordinate transformation parameters.
-*                         4: Ill-conditioned coordinate transformation
-*                            parameters.
-*                         5: One or more of the (x,y) coordinates were
-*                            invalid, as indicated by the stat vector.
-*
-*                       For returns > 1, a detailed error message is set in
-*                       celprm::err if enabled, see wcserr_enable().
-*
-*
-* cels2x() - World-to-pixel celestial transformation
-* --------------------------------------------------
-* cels2x() transforms celestial coordinates (lng,lat) to (x,y) coordinates in
-* the plane of projection.
-*
-* Given and returned:
-*   cel       struct celprm*
-*                       Celestial transformation parameters.
-*
-* Given:
-*   nlng,nlat int       Vector lengths.
-*
-*   sll,sxy   int       Vector strides.
-*
-*   lng,lat   const double[]
-*                       Celestial longitude and latitude (lng,lat) of the
-*                       projected point [deg].
-*
-* Returned:
-*   phi,theta double[]  Longitude and latitude (phi,theta) in the native
-*                       coordinate system of the projection [deg].
-*
-*   x,y       double[]  Projected coordinates in pseudo "degrees".
-*
-*   stat      int[]     Status return value for each vector element:
-*                         0: Success.
-*                         1: Invalid value of (lng,lat).
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         1: Null celprm pointer passed.
-*                         2: Invalid projection parameters.
-*                         3: Invalid coordinate transformation parameters.
-*                         4: Ill-conditioned coordinate transformation
-*                            parameters.
-*                         6: One or more of the (lng,lat) coordinates were
-*                            invalid, as indicated by the stat vector.
-*
-*                       For returns > 1, a detailed error message is set in
-*                       celprm::err if enabled, see wcserr_enable().
-*
-*
-* celprm struct - Celestial transformation parameters
-* ---------------------------------------------------
-* The celprm struct contains information required to transform celestial
-* coordinates.  It consists of certain members that must be set by the user
-* ("given") and others that are set by the WCSLIB routines ("returned").  Some
-* of the latter are supplied for informational purposes and others are for
-* internal use only.
-*
-* Returned celprm struct members must not be modified by the user.
-*
-*   int flag
-*     (Given and returned) This flag must be set to zero whenever any of the
-*     following celprm struct members are set or changed:
-*
-*       - celprm::offset,
-*       - celprm::phi0,
-*       - celprm::theta0,
-*       - celprm::ref[4],
-*       - celprm::prj:
-*         - prjprm::code,
-*         - prjprm::r0,
-*         - prjprm::pv[],
-*         - prjprm::phi0,
-*         - prjprm::theta0.
-*
-*     This signals the initialization routine, celset(), to recompute the
-*     returned members of the celprm struct.  celset() will reset flag to
-*     indicate that this has been done.
-*
-*   int offset
-*     (Given) If true (non-zero), an offset will be applied to (x,y) to
-*     force (x,y) = (0,0) at the fiducial point, (phi_0,theta_0).
-*     Default is 0 (false).
-*
-*   double phi0
-*     (Given) The native longitude, phi_0 [deg], and ...
-*
-*   double theta0
-*     (Given) ... the native latitude, theta_0 [deg], of the fiducial point,
-*     i.e. the point whose celestial coordinates are given in
-*     celprm::ref[1:2].  If undefined (set to a magic value by prjini()) the
-*     initialization routine, celset(), will set this to a projection-specific
-*     default.
-*
-*   double ref[4]
-*     (Given) The first pair of values should be set to the celestial
-*     longitude and latitude of the fiducial point [deg] - typically right
-*     ascension and declination.  These are given by the CRVALia keywords in
-*     FITS.
-*
-*     (Given and returned) The second pair of values are the native longitude,
-*     phi_p [deg], and latitude, theta_p [deg], of the celestial pole (the
-*     latter is the same as the celestial latitude of the native pole,
-*     delta_p) and these are given by the FITS keywords LONPOLEa and LATPOLEa
-*     (or by PVi_2a and PVi_3a attached to the longitude axis which take
-*     precedence if defined).
-*
-*     LONPOLEa defaults to phi_0 (see above) if the celestial latitude of the
-*     fiducial point of the projection is greater than or equal to the native
-*     latitude, otherwise phi_0 + 180 [deg].  (This is the condition for the
-*     celestial latitude to increase in the same direction as the native
-*     latitude at the fiducial point.)  ref[2] may be set to UNDEFINED (from
-*     wcsmath.h) or 999.0 to indicate that the correct default should be
-*     substituted.
-*
-*     theta_p, the native latitude of the celestial pole (or equally the
-*     celestial latitude of the native pole, delta_p) is often determined
-*     uniquely by CRVALia and LONPOLEa in which case LATPOLEa is ignored.
-*     However, in some circumstances there are two valid solutions for theta_p
-*     and LATPOLEa is used to choose between them.  LATPOLEa is set in ref[3]
-*     and the solution closest to this value is used to reset ref[3].  It is
-*     therefore legitimate, for example, to set ref[3] to +90.0 to choose the
-*     more northerly solution - the default if the LATPOLEa keyword is omitted
-*     from the FITS header.  For the special case where the fiducial point of
-*     the projection is at native latitude zero, its celestial latitude is
-*     zero, and LONPOLEa = +/- 90.0 then the celestial latitude of the native
-*     pole is not determined by the first three reference values and LATPOLEa
-*     specifies it completely.
-*
-*     The returned value, celprm::latpreq, specifies how LATPOLEa was actually
-*     used.
-*
-*   struct prjprm prj
-*     (Given and returned) Projection parameters described in the prologue to
-*     prj.h.
-*
-*   double euler[5]
-*     (Returned) Euler angles and associated intermediaries derived from the
-*     coordinate reference values.  The first three values are the Z-, X-, and
-*     Z'-Euler angles [deg], and the remaining two are the cosine and sine of
-*     the X-Euler angle.
-*
-*   int latpreq
-*     (Returned) For informational purposes, this indicates how the LATPOLEa
-*     keyword was used
-*       - 0: Not required, theta_p (== delta_p) was determined uniquely by the
-*            CRVALia and LONPOLEa keywords.
-*       - 1: Required to select between two valid solutions of theta_p.
-*       - 2: theta_p was specified solely by LATPOLEa.
-*
-*   int isolat
-*     (Returned) True if the spherical rotation preserves the magnitude of the
-*     latitude, which occurs iff the axes of the native and celestial
-*     coordinates are coincident.  It signals an opportunity to cache
-*     intermediate calculations common to all elements in a vector
-*     computation.
-*
-*   struct wcserr *err
-*     (Returned) If enabled, when an error status is returned this struct
-*     contains detailed information about the error, see wcserr_enable().
-*
-*   void *padding
-*     (An unused variable inserted for alignment purposes only.)
-*
-* Global variable: const char *cel_errmsg[] - Status return messages
-* ------------------------------------------------------------------
-* Status messages to match the status value returned from each function.
-*
-*===========================================================================*/
-
-#ifndef WCSLIB_CEL
-#define WCSLIB_CEL
-
-#include "prj.h"
-#include "wcserr.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-extern const char *cel_errmsg[];
-
-enum cel_errmsg_enum {
-  CELERR_SUCCESS         = 0,	/* Success. */
-  CELERR_NULL_POINTER    = 1,	/* Null celprm pointer passed. */
-  CELERR_BAD_PARAM       = 2,	/* Invalid projection parameters. */
-  CELERR_BAD_COORD_TRANS = 3,	/* Invalid coordinate transformation
-				   parameters. */
-  CELERR_ILL_COORD_TRANS = 4,	/* Ill-conditioned coordinated transformation
-				   parameters. */
-  CELERR_BAD_PIX         = 5,	/* One or more of the (x,y) coordinates were
-				   invalid. */
-  CELERR_BAD_WORLD       = 6 	/* One or more of the (lng,lat) coordinates
-				   were invalid. */
-};
-
-struct celprm {
-  /* Initialization flag (see the prologue above).                          */
-  /*------------------------------------------------------------------------*/
-  int    flag;			/* Set to zero to force initialization.     */
-
-  /* Parameters to be provided (see the prologue above).                    */
-  /*------------------------------------------------------------------------*/
-  int    offset;		/* Force (x,y) = (0,0) at (phi_0,theta_0).  */
-  double phi0, theta0;		/* Native coordinates of fiducial point.    */
-  double ref[4];		/* Celestial coordinates of fiducial        */
-                                /* point and native coordinates of          */
-                                /* celestial pole.                          */
-
-  struct prjprm prj;		/* Projection parameters (see prj.h).       */
-
-  /* Information derived from the parameters supplied.                      */
-  /*------------------------------------------------------------------------*/
-  double euler[5];		/* Euler angles and functions thereof.      */
-  int    latpreq;		/* LATPOLEa requirement.                    */
-  int    isolat;		/* True if |latitude| is preserved.         */
-
-  /* Error handling                                                         */
-  /*------------------------------------------------------------------------*/
-  struct wcserr *err;
-
-  /* Private                                                                */
-  /*------------------------------------------------------------------------*/
-  void   *padding;		/* (Dummy inserted for alignment purposes.) */
-};
-
-/* Size of the celprm struct in int units, used by the Fortran wrappers. */
-#define CELLEN (sizeof(struct celprm)/sizeof(int))
-
-
-int celini(struct celprm *cel);
-
-int celfree(struct celprm *cel);
-
-int celprt(const struct celprm *cel);
-
-int celset(struct celprm *cel);
-
-int celx2s(struct celprm *cel, int nx, int ny, int sxy, int sll,
-           const double x[], const double y[],
-           double phi[], double theta[], double lng[], double lat[],
-           int stat[]);
-
-int cels2x(struct celprm *cel, int nlng, int nlat, int sll, int sxy,
-           const double lng[], const double lat[],
-           double phi[], double theta[], double x[], double y[],
-           int stat[]);
-
-
-/* Deprecated. */
-#define celini_errmsg cel_errmsg
-#define celprt_errmsg cel_errmsg
-#define celset_errmsg cel_errmsg
-#define celx2s_errmsg cel_errmsg
-#define cels2x_errmsg cel_errmsg
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* WCSLIB_CEL */
diff --git a/astropy/wcs/src/wcslib/C/fitshdr.h b/astropy/wcs/src/wcslib/C/fitshdr.h
deleted file mode 100644
index ddca0b8..0000000
--- a/astropy/wcs/src/wcslib/C/fitshdr.h
+++ /dev/null
@@ -1,449 +0,0 @@
-/*============================================================================
-
-  WCSLIB 4.10 - an implementation of the FITS WCS standard.
-  Copyright (C) 1995-2012, Mark Calabretta
-
-  This file is part of WCSLIB.
-
-  WCSLIB is free software: you can redistribute it and/or modify it under the
-  terms of the GNU Lesser General Public License as published by the Free
-  Software Foundation, either version 3 of the License, or (at your option)
-  any later version.
-
-  WCSLIB 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 Lesser General Public License for
-  more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with WCSLIB.  If not, see <http://www.gnu.org/licenses/>.
-
-  Correspondence concerning WCSLIB may be directed to:
-    Internet email: mcalabre at atnf.csiro.au
-    Postal address: Dr. Mark Calabretta
-                    Australia Telescope National Facility, CSIRO
-                    PO Box 76
-                    Epping NSW 1710
-                    AUSTRALIA
-
-  Author: Mark Calabretta, Australia Telescope National Facility
-  http://www.atnf.csiro.au/~mcalabre/index.html
-  $Id: fitshdr.h,v 4.10 2012/02/05 23:41:44 cal103 Exp $
-*=============================================================================
-*
-* The Flexible Image Transport System (FITS), a data format widely used in
-* astronomy for data interchange and archive, is described in
-*
-*   "Definition of The Flexible Image Transport System (FITS)",
-*   Hanisch, R.J., Farris, A., Greisen, E.W., et al. 2001, A&A, 376, 359
-*
-* which formalizes NOST 100-2.0, a document produced by the NASA/Science
-* Office of Standards and Technology, see http://fits.gsfc.nasa.gov.
-*
-* Refer to the README file provided with WCSLIB for an overview of the
-* library.
-*
-*
-* Summary of the fitshdr routines
-* -------------------------------
-* fitshdr() is a generic FITS header parser provided to handle keyrecords that
-* are ignored by the WCS header parsers, wcspih() and wcsbth().  Typically the
-* latter may be set to remove WCS keyrecords from a header leaving fitshdr()
-* to handle the remainder.
-*
-*
-* fitshdr() - FITS header parser routine
-* --------------------------------------
-* fitshdr() parses a character array containing a FITS header, extracting
-* all keywords and their values into an array of fitskey structs.
-*
-* Given:
-*   header    const char []
-*                       Character array containing the (entire) FITS header,
-*                       for example, as might be obtained conveniently via the
-*                       CFITSIO routine fits_hdr2str().
-*
-*                       Each header "keyrecord" (formerly "card image")
-*                       consists of exactly 80 7-bit ASCII printing characters
-*                       in the range 0x20 to 0x7e (which excludes NUL, BS,
-*                       TAB, LF, FF and CR) especially noting that the
-*                       keyrecords are NOT null-terminated.
-*
-*   nkeyrec   int       Number of keyrecords in header[].
-*
-*   nkeyids   int       Number of entries in keyids[].
-*
-* Given and returned:
-*   keyids    struct fitskeyid []
-*                       While all keywords are extracted from the header,
-*                       keyids[] provides a convienient way of indexing them.
-*                       The fitskeyid struct contains three members;
-*                       fitskeyid::name must be set by the user while
-*                       fitskeyid::count and fitskeyid::name are returned by
-*                       fitshdr().  All matched keywords will have their
-*                       fitskey::keyno member negated.
-*
-* Returned:
-*   nreject   int*      Number of header keyrecords rejected for syntax
-*                       errors.
-*
-*   keys      struct fitskey**
-*                       Pointer to an array of nkeyrec fitskey structs
-*                       containing all keywords and keyvalues extracted from
-*                       the header.
-*
-*                       Memory for the array is allocated by fitshdr() and
-*                       this must be freed by the user by invoking free() on
-*                       the array.
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         1: Null fitskey pointer passed.
-*                         2: Memory allocation failed.
-*                         3: Fatal error returned by Flex parser.
-*
-* Notes:
-*   1: Keyword parsing is done in accordance with the syntax defined by
-*      NOST 100-2.0, noting the following points in particular:
-*
-*      a: Sect. 5.1.2.1 specifies that keywords be left-justified in columns
-*         1-8, blank-filled with no embedded spaces, composed only of the
-*         ASCII characters ABCDEFGHJKLMNOPQRSTUVWXYZ0123456789-_
-*
-*         fitshdr() accepts any characters in columns 1-8 but flags keywords
-*         that do not conform to standard syntax.
-*
-*      b: Sect. 5.1.2.2 defines the "value indicator" as the characters "= "
-*         occurring in columns 9 and 10.  If these are absent then the
-*         keyword has no value and columns 9-80 may contain any ASCII text
-*         (but see note 2 for CONTINUE keyrecords).  This is copied to the
-*         comment member of the fitskey struct.
-*
-*      c: Sect. 5.1.2.3 states that a keyword may have a null (undefined)
-*         value if the value/comment field, columns 11-80, consists entirely
-*         of spaces, possibly followed by a comment.
-*
-*      d: Sect. 5.1.1 states that trailing blanks in a string keyvalue are
-*         not significant and the parser always removes them.  A string
-*         containing nothing but blanks will be replaced with a single
-*         blank.
-*
-*         Sect. 5.2.1 also states that a quote character (') in a string
-*         value is to be represented by two successive quote characters and
-*         the parser removes the repeated quote.
-*
-*      e: The parser recognizes free-format character (NOST 100-2.0,
-*         Sect. 5.2.1), integer (Sect. 5.2.3), and floating-point values
-*         (Sect. 5.2.4) for all keywords.
-*
-*      f: Sect. 5.2.3 offers no comment on the size of an integer keyvalue
-*         except indirectly in limiting it to 70 digits.  The parser will
-*         translates an integer keyvalue to a 32-bit signed integer if it
-*         lies in the range -2147483648 to +2147483647, otherwise it
-*         interprets it as a 64-bit signed integer if possible, or else a
-*         "very long" integer (see fitskey::type).
-*
-*      g: END not followed by 77 blanks is not considered to be a legitimate
-*         end keyrecord.
-*
-*   2: The parser supports a generalization of the OGIP Long String Keyvalue
-*      Convention (v1.0) whereby strings may be continued onto successive
-*      header keyrecords.  A keyrecord contains a segment of a continued
-*      string if and only if
-*
-*      a: it contains the pseudo-keyword CONTINUE,
-*
-*      b: columns 9 and 10 are both blank,
-*
-*      c: columns 11 to 80 contain what would be considered a valid string
-*         keyvalue, including optional keycomment, if column 9 had contained
-*         '=',
-*
-*      d: the previous keyrecord contained either a valid string keyvalue or
-*         a valid CONTINUE keyrecord.
-*
-*      If any of these conditions is violated, the keyrecord is considered in
-*      isolation.
-*
-*      Syntax errors in keycomments in a continued string are treated more
-*      permissively than usual; the '/' delimiter may be omitted provided that
-*      parsing of the string keyvalue is not compromised.  However, the
-*      FITSHDR_COMMENT status bit will be set for the keyrecord (see
-*      fitskey::status).
-*
-*      As for normal strings, trailing blanks in a continued string are not
-*      significant.
-*
-*      In the OGIP convention "the '&' character is used as the last non-blank
-*      character of the string to indicate that the string is (probably)
-*      continued on the following keyword".  This additional syntax is not
-*      required by fitshdr(), but if '&' does occur as the last non-blank
-*      character of a continued string keyvalue then it will be removed, along
-*      with any trailing blanks.  However, blanks that occur before the '&'
-*      will be preserved.
-*
-*
-* fitskeyid struct - Keyword indexing
-* -----------------------------------
-* fitshdr() uses the fitskeyid struct to return indexing information for
-* specified keywords.  The struct contains three members, the first of which,
-* fitskeyid::name, must be set by the user with the remainder returned by
-* fitshdr().
-*
-*   char name[12]:
-*     (Given) Name of the required keyword.  This is to be set by the user;
-*     the '.' character may be used for wildcarding.  Trailing blanks will be
-*     replaced with nulls.
-*
-*   int count:
-*     (Returned) The number of matches found for the keyword.
-*
-*   int idx[2]:
-*     (Returned) Indices into keys[], the array of fitskey structs returned by
-*     fitshdr().  Note that these are 0-relative array indices, not keyrecord
-*     numbers.
-*
-*     If the keyword is found in the header the first index will be set to the
-*     array index of its first occurrence, otherwise it will be set to -1.
-*
-*     If multiples of the keyword are found, the second index will be set to
-*     the array index of its last occurrence, otherwise it will be set to -1.
-*
-*
-* fitskey struct - Keyword/value information
-* ------------------------------------------
-* fitshdr() returns an array of fitskey structs, each of which contains the
-* result of parsing one FITS header keyrecord.  All members of the fitskey
-* struct are returned by fitshdr(), none are given by the user.
-*
-*   int keyno
-*     (Returned) Keyrecord number (1-relative) in the array passed as input to
-*     fitshdr().  This will be negated if the keyword matched any specified in
-*     the keyids[] index.
-*
-*   int keyid
-*     (Returned) Index into the first entry in keyids[] with which the
-*     keyrecord matches, else -1.
-*
-*   int status
-*     (Returned) Status flag bit-vector for the header keyrecord employing the
-*     following bit masks defined as preprocessor macros:
-*
-*       - FITSHDR_KEYWORD:    Illegal keyword syntax.
-*       - FITSHDR_KEYVALUE:   Illegal keyvalue syntax.
-*       - FITSHDR_COMMENT:    Illegal keycomment syntax.
-*       - FITSHDR_KEYREC:     Illegal keyrecord, e.g. an END keyrecord with
-*                             trailing text.
-*       - FITSHDR_TRAILER:    Keyrecord following a valid END keyrecord.
-*
-*     The header keyrecord is syntactically correct if no bits are set.
-*
-*   char keyword[12]
-*     (Returned) Keyword name, null-filled for keywords of less than eight
-*     characters (trailing blanks replaced by nulls).
-*
-*     Use
-*
-=       sprintf(dst, "%.8s", keyword)
-*
-*     to copy it to a character array with null-termination, or
-*
-=       sprintf(dst, "%8.8s", keyword)
-*
-*     to blank-fill to eight characters followed by null-termination.
-*
-*   int type
-*     (Returned) Keyvalue data type:
-*       - 0: No keyvalue.
-*       - 1: Logical, represented as int.
-*       - 2: 32-bit signed integer.
-*       - 3: 64-bit signed integer (see below).
-*       - 4: Very long integer (see below).
-*       - 5: Floating point (stored as double).
-*       - 6: Integer complex (stored as double[2]).
-*       - 7: Floating point complex (stored as double[2]).
-*       - 8: String.
-*       - 8+10*n: Continued string (described below and in fitshdr() note 2).
-*
-*     A negative type indicates that a syntax error was encountered when
-*     attempting to parse a keyvalue of the particular type.
-*
-*     Comments on particular data types:
-*       - 64-bit signed integers lie in the range
-*
-=           (-9223372036854775808 <= int64 <  -2147483648) ||
-=                    (+2147483647 <  int64 <= +9223372036854775807)
-*
-*         A native 64-bit data type may be defined via preprocessor macro
-*         WCSLIB_INT64 defined in wcsconfig.h, e.g. as 'long long int'; this
-*         will be typedef'd to 'int64' here.  If WCSLIB_INT64 is not set, then
-*         int64 is typedef'd to int[3] instead and fitskey::keyvalue is to be
-*         computed as
-*
-=           ((keyvalue.k[2]) * 1000000000 +
-=             keyvalue.k[1]) * 1000000000 +
-=             keyvalue.k[0]
-*
-*         and may reported via
-*
-=            if (keyvalue.k[2]) {
-=              printf("%d%09d%09d", keyvalue.k[2], abs(keyvalue.k[1]),
-=                                   abs(keyvalue.k[0]));
-=            } else {
-=              printf("%d%09d", keyvalue.k[1], abs(keyvalue.k[0]));
-=            }
-*
-*         where keyvalue.k[0] and keyvalue.k[1] range from -999999999 to
-*         +999999999.
-*
-*       - Very long integers, up to 70 decimal digits in length, are encoded
-*         in keyvalue.l as an array of int[8], each of which stores 9 decimal
-*         digits.  fitskey::keyvalue is to be computed as
-*
-=           (((((((keyvalue.l[7]) * 1000000000 +
-=                  keyvalue.l[6]) * 1000000000 +
-=                  keyvalue.l[5]) * 1000000000 +
-=                  keyvalue.l[4]) * 1000000000 +
-=                  keyvalue.l[3]) * 1000000000 +
-=                  keyvalue.l[2]) * 1000000000 +
-=                  keyvalue.l[1]) * 1000000000 +
-=                  keyvalue.l[0]
-*
-*       - Continued strings are not reconstructed, they remain split over
-*         successive fitskey structs in the keys[] array returned by
-*         fitshdr().  fitskey::keyvalue data type, 8 + 10n, indicates the
-*         segment number, n, in the continuation.
-*
-*   int padding
-*     (An unused variable inserted for alignment purposes only.)
-*
-*   union keyvalue
-*     (Returned) A union comprised of
-*
-*       - fitskey::i,
-*       - fitskey::k,
-*       - fitskey::l,
-*       - fitskey::f,
-*       - fitskey::c,
-*       - fitskey::s,
-*
-*     used by the fitskey struct to contain the value associated with a
-*     keyword.
-*
-*   int i
-*     (Returned) Logical (fitskey::type == 1) and 32-bit signed integer
-*     (fitskey::type == 2) data types in the fitskey::keyvalue union.
-*
-*   int64 k
-*     (Returned) 64-bit signed integer (fitskey::type == 3) data type in the
-*     fitskey::keyvalue union.
-*
-*   int l[8]
-*     (Returned) Very long integer (fitskey::type == 4) data type in the
-*     fitskey::keyvalue union.
-*
-*   double f
-*     (Returned) Floating point (fitskey::type == 5) data type in the
-*     fitskey::keyvalue union.
-*
-*   double c[2]
-*     (Returned) Integer and floating point complex (fitskey::type == 6 || 7)
-*     data types in the fitskey::keyvalue union.
-*
-*   char s[72]
-*     (Returned) Null-terminated string (fitskey::type == 8) data type in the
-*     fitskey::keyvalue union.
-*
-*   int ulen
-*     (Returned) Where a keycomment contains a units string in the standard
-*     form, e.g. [m/s], the ulen member indicates its length, inclusive of
-*     square brackets.  Otherwise ulen is zero.
-*
-*   char comment[84]
-*     (Returned) Keycomment, i.e. comment associated with the keyword or, for
-*     keyrecords rejected because of syntax errors, the compete keyrecord
-*     itself with null-termination.
-*
-*     Comments are null-terminated with trailing spaces removed.  Leading
-*     spaces are also removed from keycomments (i.e. those immediately
-*     following the '/' character), but not from COMMENT or HISTORY keyrecords
-*     or keyrecords without a value indicator ("= " in columns 9-80).
-*
-*
-* Global variable: const char *fitshdr_errmsg[] - Status return messages
-* ----------------------------------------------------------------------
-* Error messages to match the status value returned from each function.
-*
-*===========================================================================*/
-
-#ifndef WCSLIB_FITSHDR
-#define WCSLIB_FITSHDR
-
-#include "wcsconfig.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define FITSHDR_KEYWORD  0x01
-#define FITSHDR_KEYVALUE 0x02
-#define FITSHDR_COMMENT  0x04
-#define FITSHDR_KEYREC   0x08
-#define FITSHDR_CARD     0x08	/* Alias for backwards compatibility. */
-#define FITSHDR_TRAILER  0x10
-
-
-extern const char *fitshdr_errmsg[];
-
-#ifdef WCSLIB_INT64
-  typedef WCSLIB_INT64 int64;
-#else
-  typedef int int64[3];
-#endif
-
-
-/* Struct used for indexing the keywords. */
-struct fitskeyid {
-  char name[12];		/* Keyword name, null-terminated.           */
-  int  count;			/* Number of occurrences of keyword.        */
-  int  idx[2];			/* Indices into fitskey array.              */
-};
-
-/* Size of the fitskeyid struct in int units, used by the Fortran wrappers. */
-#define KEYIDLEN (sizeof(struct fitskeyid)/sizeof(int))
-
-
-/* Struct used for storing FITS keywords. */
-struct fitskey {
-  int  keyno;			/* Header keyrecord sequence number (1-rel).*/
-  int  keyid;			/* Index into fitskeyid[].                  */
-  int  status;			/* Header keyrecord status bit flags.       */
-  char keyword[12];		/* Keyword name, null-filled.               */
-  int  type;			/* Keyvalue type (see above).               */
-  int  padding;			/* (Dummy inserted for alignment purposes.) */
-  union {
-    int    i;			/* 32-bit integer and logical values.       */
-    int64  k;			/* 64-bit integer values.                   */
-    int    l[8];		/* Very long signed integer values.         */
-    double f;			/* Floating point values.                   */
-    double c[2];		/* Complex values.                          */
-    char   s[72];		/* String values, null-terminated.          */
-  } keyvalue;			/* Keyvalue.                                */
-  int  ulen;			/* Length of units string.                  */
-  char comment[84];		/* Comment (or keyrecord), null-terminated. */
-};
-
-/* Size of the fitskey struct in int units, used by the Fortran wrappers. */
-#define KEYLEN (sizeof(struct fitskey)/sizeof(int))
-
-
-int fitshdr(const char header[], int nkeyrec, int nkeyids,
-            struct fitskeyid keyids[], int *nreject, struct fitskey **keys);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* WCSLIB_FITSHDR */
diff --git a/astropy/wcs/src/wcslib/C/fitshdr.l b/astropy/wcs/src/wcslib/C/fitshdr.l
deleted file mode 100644
index 8464871..0000000
--- a/astropy/wcs/src/wcslib/C/fitshdr.l
+++ /dev/null
@@ -1,560 +0,0 @@
-/*============================================================================
-
-  WCSLIB 4.10 - an implementation of the FITS WCS standard.
-  Copyright (C) 1995-2012, Mark Calabretta
-
-  This file is part of WCSLIB.
-
-  WCSLIB is free software: you can redistribute it and/or modify it under the
-  terms of the GNU Lesser General Public License as published by the Free
-  Software Foundation, either version 3 of the License, or (at your option)
-  any later version.
-
-  WCSLIB 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 Lesser General Public License for
-  more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with WCSLIB.  If not, see <http://www.gnu.org/licenses/>.
-
-  Correspondence concerning WCSLIB may be directed to:
-    Internet email: mcalabre at atnf.csiro.au
-    Postal address: Dr. Mark Calabretta
-                    Australia Telescope National Facility, CSIRO
-                    PO Box 76
-                    Epping NSW 1710
-                    AUSTRALIA
-
-  Author: Mark Calabretta, Australia Telescope National Facility
-  http://www.atnf.csiro.au/~mcalabre/index.html
-  $Id: fitshdr.l,v 4.10 2012/02/05 23:41:44 cal103 Exp $
-*=============================================================================
-*
-* fitshdr.l is a Flex description file containing a lexical scanner
-* definition for extracting keywords and keyvalues from a FITS header.
-*
-* It requires Flex v2.5.4 or later.
-*
-* Refer to fitshdr.h for a description of the user interface and operating
-* notes.
-*
-*===========================================================================*/
-
-/* Options. */
-%option full
-%option never-interactive
-%option nounput
-%option noyywrap
-%option outfile="fitshdr.c"
-%option prefix="fitshdr"
-
-/* Keywords. */
-KEYCHR	[-_A-Z0-9]
-KW1	{KEYCHR}{1}" "{7}
-KW2	{KEYCHR}{2}" "{6}
-KW3	{KEYCHR}{3}" "{5}
-KW4	{KEYCHR}{4}" "{4}
-KW5	{KEYCHR}{5}" "{3}
-KW6	{KEYCHR}{6}" "{2}
-KW7	{KEYCHR}{7}" "{1}
-KW8	{KEYCHR}{8}
-KEYWORD	({KW1}|{KW2}|{KW3}|{KW4}|{KW5}|{KW6}|{KW7}|{KW8})
-
-/* Keyvalue data types. */
-LOGICAL	[TF]
-INT32	[+-]?0*[0-9]{1,9}
-INT64	[+-]?0*[0-9]{10,18}
-INTVL	[+-]?0*[0-9]{19,}
-INTEGER	[+-]?[0-9]+
-FLOAT	[+-]?([0-9]+\.?[0-9]*|\.[0-9]+)([eE][+-]?[0-9]+)?
-ICOMPLX	\(" "*{INTEGER}" "*," "*{INTEGER}" "*\)
-FCOMPLX	\(" "*{FLOAT}" "*," "*{FLOAT}" "*\)
-STRING	'([^']|'')*'
-
-/* Characters forming standard unit strings (jwBIQX are not used). */
-UNITSTR \[[-+*/^(). 0-9a-zA-Z]+\]
-
-/* Exclusive start states. */
-%x VALUE INLINE UNITS COMMENT ERROR FLUSH
-
-%{
-#include <math.h>
-#include <limits.h>
-#include <setjmp.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "fitshdr.h"
-
-#define YY_DECL int fitshdr(const char header[], int nkeyrec, int nkeyids, \
-                            struct fitskeyid keyids[], int *nreject, \
-                            struct fitskey **keys)
-
-#define YY_INPUT(inbuff, count, bufsize) \
-	{ \
-	  if (fitshdr_nkeyrec) { \
-	    strncpy(inbuff, fitshdr_hdr, 80); \
-	    inbuff[80] = '\n'; \
-	    fitshdr_hdr += 80; \
-	    fitshdr_nkeyrec--; \
-	    count = 81; \
-	  } else { \
-	    count = YY_NULL; \
-	  } \
-	}
-
-/* These global variables are required by YY_INPUT. */
-const char *fitshdr_hdr;
-int  fitshdr_nkeyrec;
-
-/* Used in preempting the call to exit() by yy_fatal_error(). */
-jmp_buf fitshdr_abort_jmp_env;
-#define exit(status) longjmp(fitshdr_abort_jmp_env, status)
-
-/* Map status return value to message. */
-const char *fitshdr_errmsg[] = {
-   "Success",
-   "Null fitskey pointer-pointer passed",
-   "Memory allocation failed",
-   "Fatal error returned by Flex parser"};
-
-%}
-
-%%
-	char *cptr, ctmp[72];
-	int  blank, continuation, end, j, k, keyno;
-	double dtmp;
-	struct fitskey *kptr;
-	struct fitskeyid *iptr;
-	void nullfill(char cptr[], int len);
-	int  yylex_destroy(void);
-	
-	fitshdr_hdr = header;
-	fitshdr_nkeyrec = nkeyrec;
-	
-	*nreject = 0;
-	keyno = 0;
-	
-	if (keys == 0x0) {
-	  return 1;
-	}
-	
-	/* Allocate memory for the required number of fitskey structs. */
-	/* Recall that calloc() initializes allocated memory to zero.  */
-	if (!(kptr = *keys = calloc(nkeyrec, sizeof(struct fitskey)))) {
-	  return 2;
-	}
-	
-	/* Initialize keyids[]. */
-	iptr = keyids;
-	for (j = 0; j < nkeyids; j++, iptr++) {
-	  iptr->count  = 0;
-	  iptr->idx[0] = -1;
-	  iptr->idx[1] = -1;
-	}
-	
-	blank = 0;
-	continuation = 0;
-	end = 0;
-	
-	/* Return here via longjmp() invoked by yy_fatal_error(). */
-	if (setjmp(fitshdr_abort_jmp_env)) {
-	  return 3;
-	}
-	
-	BEGIN(INITIAL);
-
-^" "{80} {
-	  /* A completely blank keyrecord. */
-	  strncpy(kptr->keyword, yytext, 8);
-	  yyless(0);
-	  blank = 1;
-	  BEGIN(COMMENT);
-	}
-
-^(COMMENT|HISTORY|" "{8}) {
-	  strncpy(kptr->keyword, yytext, 8);
-	  BEGIN(COMMENT);
-	}
-
-^END" "{77} {
-	  strncpy(kptr->keyword, yytext, 8);
-	  end = 1;
-	  BEGIN(FLUSH);
-	}
-
-^END" "{5}=" "+ {
-	  /* Illegal END keyrecord. */
-	  strncpy(kptr->keyword, yytext, 8);
-	  kptr->status |= FITSHDR_KEYREC;
-	  BEGIN(VALUE);
-	}
-
-^END" "{5} {
-	  /* Illegal END keyrecord. */
-	  strncpy(kptr->keyword, yytext, 8);
-	  kptr->status |= FITSHDR_KEYREC;
-	  BEGIN(COMMENT);
-	}
-
-^{KEYWORD}=" "+ {
-	  strncpy(kptr->keyword, yytext, 8);
-	  BEGIN(VALUE);
-	}
-
-^CONTINUE"  "+{STRING} {
-	  /* Continued string keyvalue. */
-	  strncpy(kptr->keyword, yytext, 8);
-	
-	  if (keyno > 0 && (kptr-1)->type%10 == 8) {
-	    /* Put back the string keyvalue. */
-	    for (k = 10; yytext[k] != '\''; k++);
-	    yyless(k);
-	    continuation = 1;
-	    BEGIN(VALUE);
-	
-	  } else {
-	    /* Not a valid continuation. */
-	    yyless(8);
-	    BEGIN(COMMENT);
-	  }
-	}
-
-^{KEYWORD} {
-	  /* Keyword without value. */
-	  strncpy(kptr->keyword, yytext, 8);
-	  BEGIN(COMMENT);
-	}
-
-^.{8}=" "+ {
-	  /* Illegal keyword, carry on regardless. */
-	  strncpy(kptr->keyword, yytext, 8);
-	  kptr->status |= FITSHDR_KEYWORD;
-	  BEGIN(VALUE);
-	}
-
-^.{8}	{
-	  /* Illegal keyword, carry on regardless. */
-	  strncpy(kptr->keyword, yytext, 8);
-	  kptr->status |= FITSHDR_KEYWORD;
-	  BEGIN(COMMENT);
-	}
-
-<VALUE>" "*/\/ {
-	  /* Null keyvalue. */
-	  BEGIN(INLINE);
-	}
-
-<VALUE>{LOGICAL} {
-	  /* Logical keyvalue. */
-	  kptr->type = 1;
-	  kptr->keyvalue.i = (*yytext == 'T');
-	  BEGIN(INLINE);
-	}
-
-<VALUE>{INT32} {
-	  /* 32-bit signed integer keyvalue. */
-	  kptr->type = 2;
-	  if (sscanf(yytext, "%d", &(kptr->keyvalue.i)) < 1) {
-	    kptr->status |= FITSHDR_KEYVALUE;
-	    BEGIN(ERROR);
-	  }
-	
-	  BEGIN(INLINE);
-	}
-
-<VALUE>{INT64} {
-	  /* 64-bit signed integer keyvalue (up to 18 digits). */
-	  if (sscanf(yytext, "%lf", &dtmp) < 1) {
-	    kptr->status |= FITSHDR_KEYVALUE;
-	    BEGIN(ERROR);
-	
-	  } else if (INT_MIN <= dtmp && dtmp <= INT_MAX) {
-	    /* Can be accomodated as a 32-bit signed integer. */
-	    kptr->type = 2;
-	    if (sscanf(yytext, "%d", &(kptr->keyvalue.i)) < 1) {
-	      kptr->status |= FITSHDR_KEYVALUE;
-	      BEGIN(ERROR);
-	    }
-	
-	  } else {
-	    /* 64-bit signed integer. */
-	    kptr->type = 3;
-	    #ifdef WCSLIB_INT64
-	      /* Native 64-bit integer is available. */
-	      if (sscanf(yytext, "%lld", &(kptr->keyvalue.k)) < 1) {
-	        kptr->status |= FITSHDR_KEYVALUE;
-	        BEGIN(ERROR);
-	      }
-	    #else
-	      /* 64-bit integer (up to 18 digits) implemented as int[3]. */
-	      kptr->keyvalue.k[2] = 0;
-	
-	      sprintf(ctmp, "%%%dd%%9d", yyleng-9);
-	      if (sscanf(yytext, ctmp, kptr->keyvalue.k+1,
-	                 kptr->keyvalue.k) < 1) {
-	        kptr->status |= FITSHDR_KEYVALUE;
-	        BEGIN(ERROR);
-	      } else if (*yytext == '-') {
-	        kptr->keyvalue.k[0] *= -1;
-	      }
-	    #endif
-	  }
-	
-	  BEGIN(INLINE);
-	}
-
-<VALUE>{INTVL} {
-	  /* Very long integer keyvalue (and 19-digit int64). */
-	  kptr->type = 4;
-	  strcpy(ctmp, yytext);
-	  k = yyleng;
-	  for (j = 0; j < 8; j++) {
-	    /* Read it backwards. */
-	    k -= 9;
-	    if (k < 0) k = 0;
-	    if (sscanf(ctmp+k, "%d", kptr->keyvalue.l+j) < 1) {
-	      kptr->status |= FITSHDR_KEYVALUE;
-	      BEGIN(ERROR);
-	    }
-	    if (*yytext == '-') {
-	      kptr->keyvalue.l[j] = -abs(kptr->keyvalue.l[j]);
-	    }
-	
-	    if (k == 0) break;
-	    ctmp[k] = '\0';
-	  }
-	
-	  /* Can it be accomodated as a 64-bit signed integer? */
-	  if (j == 2 && abs(kptr->keyvalue.l[2]) <=  9 &&
-	                abs(kptr->keyvalue.l[1]) <=  223372036 &&
-	                    kptr->keyvalue.l[0]  <=  854775807 &&
-	                    kptr->keyvalue.l[0]  >= -854775808) {
-	    kptr->type = 3;
-	
-	    #ifdef WCSLIB_INT64
-	      /* Native 64-bit integer is available. */
-	      kptr->keyvalue.l[2] = 0;
-	      if (sscanf(yytext, "%lld", &(kptr->keyvalue.k)) < 1) {
-	        kptr->status |= FITSHDR_KEYVALUE;
-	        BEGIN(ERROR);
-	      }
-	    #endif
-	  }
-	
-	  BEGIN(INLINE);
-	}
-
-<VALUE>{FLOAT} {
-	  /* Float keyvalue. */
-	  kptr->type = 5;
-	  if (sscanf(yytext, "%lf", &(kptr->keyvalue.f)) < 1) {
-	    kptr->status |= FITSHDR_KEYVALUE;
-	    BEGIN(ERROR);
-	  }
-	
-	  BEGIN(INLINE);
-	}
-
-<VALUE>{ICOMPLX} {
-	  /* Integer complex keyvalue. */
-	  kptr->type = 6;
-	  if (sscanf(yytext, "(%lf,%lf)", kptr->keyvalue.c,
-	      kptr->keyvalue.c+1) < 2) {
-	    kptr->status |= FITSHDR_KEYVALUE;
-	    BEGIN(ERROR);
-	  }
-	
-	  BEGIN(INLINE);
-	}
-
-<VALUE>{FCOMPLX} {
-	  /* Floating point complex keyvalue. */
-	  kptr->type = 7;
-	  if (sscanf(yytext, "(%lf,%lf)", kptr->keyvalue.c,
-	      kptr->keyvalue.c+1) < 2) {
-	    kptr->status |= FITSHDR_KEYVALUE;
-	    BEGIN(ERROR);
-	  }
-	
-	  BEGIN(INLINE);
-	}
-
-<VALUE>{STRING} {
-	  /* String keyvalue. */
-	  kptr->type = 8;
-	  cptr = kptr->keyvalue.s;
-	  strcpy(cptr, yytext+1);
-	
-	  /* Squeeze out repeated quotes. */
-	  k = 0;
-	  for (j = 0; j < 72; j++) {
-	    if (k < j) {
-	      cptr[k] = cptr[j];
-	    }
-	
-	    if (cptr[j] == '\0') {
-	      if (k) cptr[k-1] = '\0';
-	      break;
-	    } else if (cptr[j] == '\'' && cptr[j+1] == '\'') {
-	      j++;
-	    }
-	
-	    k++;
-	  }
-	
-	  if (*cptr) {
-	    /* Retain the initial blank in all-blank strings. */
-	    nullfill(cptr+1, 71);
-	  } else {
-	    nullfill(cptr, 72);
-	  }
-	
-	  BEGIN(INLINE);
-	}
-
-<VALUE>. {
-	  kptr->status |= FITSHDR_KEYVALUE;
-	  BEGIN(ERROR);
-	}
-
-<INLINE>" "*$ {
-	  BEGIN(FLUSH);
-	}
-
-<INLINE>" "*\/" "*$ {
-	  BEGIN(FLUSH);
-	}
-
-<INLINE>" "*\/" "* {
-	  BEGIN(UNITS);
-	}
-
-<INLINE>" " {
-	  kptr->status |= FITSHDR_COMMENT;
-	  BEGIN(ERROR);
-	}
-
-<INLINE>. {
-	  /* Keyvalue parsing must now also be suspect. */
-	  kptr->status |= FITSHDR_COMMENT;
-	  kptr->type = 0;
-	  BEGIN(ERROR);
-	}
-
-<UNITS>{UNITSTR} {
-	  kptr->ulen = yyleng;
-	  yymore();
-	  BEGIN(COMMENT);
-	}
-
-<UNITS>. {
-	  yymore();
-	  BEGIN(COMMENT);
-	}
-
-<COMMENT>.* {
-	  strcpy(kptr->comment, yytext);
-	  nullfill(kptr->comment, 84);
-	  BEGIN(FLUSH);
-	}
-
-<ERROR>.* {
-	  if (!continuation) kptr->type = -abs(kptr->type);
-	
-	  sprintf(kptr->comment, "%.80s", fitshdr_hdr-80);
-	  kptr->comment[80] = '\0';
-	  nullfill(kptr->comment+80, 4);
-	
-	  BEGIN(FLUSH);
-	}
-
-<FLUSH>.*\n {
-	  /* Discard the rest of the input line. */
-	  kptr->keyno = ++keyno;
-	
-	  /* Null-fill the keyword. */
-	  kptr->keyword[8] = '\0';
-	  nullfill(kptr->keyword, 12);
-	
-	  /* Do indexing. */
-	  iptr = keyids;
-	  kptr->keyid = -1;
-	  for (j = 0; j < nkeyids; j++, iptr++) {
-	    cptr = iptr->name;
-	    cptr[8] = '\0';
-	    nullfill(cptr, 12);
-	    for (k = 0; k < 8; k++, cptr++) {
-	      if (*cptr != '.' && *cptr != kptr->keyword[k]) break;
-	    }
-	
-	    if (k == 8) {
-	      /* Found a match. */
-	      iptr->count++;
-	      if (iptr->idx[0] == -1) {
-	        iptr->idx[0] = keyno-1;
-	      } else {
-	        iptr->idx[1] = keyno-1;
-	      }
-	
-	      kptr->keyno = -abs(kptr->keyno);
-	      if (kptr->keyid < 0) kptr->keyid = j;
-	    }
-	  }
-	
-	  /* Deal with continued strings. */
-	  if (continuation) {
-	    /* Tidy up the previous string keyvalue. */
-	    if ((kptr-1)->type == 8) (kptr-1)->type += 10;
-	    cptr = (kptr-1)->keyvalue.s;
-	    if (cptr[strlen(cptr)-1] == '&') cptr[strlen(cptr)-1] = '\0';
-	
-	    kptr->type = (kptr-1)->type + 10;
-	  }
-	
-	  /* Check for keyrecords following the END keyrecord. */
-	  if (end && (end++ > 1) && !blank) {
-	    kptr->status |= FITSHDR_TRAILER;
-	  }
-	  if (kptr->status) (*nreject)++;
-	
-	  kptr++;
-	  blank = 0;
-	  continuation = 0;
-	
-	  BEGIN(INITIAL);
-	}
-
-<<EOF>>	{
-	  /* End-of-input. */
-	  yylex_destroy();
-	  return 0;
-	}
-
-%%
-
-/*--------------------------------------------------------------------------*/
-
-void nullfill(char cptr[], int len)
-
-{
-  int j, k;
-
-  /* Null-fill the string. */
-  for (j = 0; j < len; j++) {
-    if (cptr[j] == '\0') {
-      for (k = j+1; k < len; k++) {
-        cptr[k] = '\0';
-      }
-      break;
-    }
-  }
-
-  for (k = j-1; k >= 0; k--) {
-    if (cptr[k] != ' ') break;
-    cptr[k] = '\0';
-  }
-
-  return;
-}
diff --git a/astropy/wcs/src/wcslib/C/flexed/fitshdr.c b/astropy/wcs/src/wcslib/C/flexed/fitshdr.c
deleted file mode 100644
index 4f9fdca..0000000
--- a/astropy/wcs/src/wcslib/C/flexed/fitshdr.c
+++ /dev/null
@@ -1,11937 +0,0 @@
-#line 2 "fitshdr.c"
-
-#line 4 "fitshdr.c"
-
-#define  YY_INT_ALIGNED short int
-
-/* A lexical scanner generated by flex */
-
-#define yy_create_buffer fitshdr_create_buffer
-#define yy_delete_buffer fitshdr_delete_buffer
-#define yy_flex_debug fitshdr_flex_debug
-#define yy_init_buffer fitshdr_init_buffer
-#define yy_flush_buffer fitshdr_flush_buffer
-#define yy_load_buffer_state fitshdr_load_buffer_state
-#define yy_switch_to_buffer fitshdr_switch_to_buffer
-#define yyin fitshdrin
-#define yyleng fitshdrleng
-#define yylex fitshdrlex
-#define yylineno fitshdrlineno
-#define yyout fitshdrout
-#define yyrestart fitshdrrestart
-#define yytext fitshdrtext
-#define yywrap fitshdrwrap
-#define yyalloc fitshdralloc
-#define yyrealloc fitshdrrealloc
-#define yyfree fitshdrfree
-
-#define FLEX_SCANNER
-#define YY_FLEX_MAJOR_VERSION 2
-#define YY_FLEX_MINOR_VERSION 5
-#define YY_FLEX_SUBMINOR_VERSION 35
-#if YY_FLEX_SUBMINOR_VERSION > 0
-#define FLEX_BETA
-#endif
-
-/* First, we deal with  platform-specific or compiler-specific issues. */
-
-/* begin standard C headers. */
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <stdlib.h>
-
-/* end standard C headers. */
-
-/* flex integer type definitions */
-
-#ifndef FLEXINT_H
-#define FLEXINT_H
-
-/* C99 systems have <inttypes.h>. 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 <inttypes.h>
-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;
-
-/* 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 /* ! C99 */
-
-#endif /* ! FLEXINT_H */
-
-#ifdef __cplusplus
-
-/* The "const" storage-class-modifier is valid. */
-#define YY_USE_CONST
-
-#else	/* ! __cplusplus */
-
-/* C99 requires __STDC__ to be defined as 1. */
-#if defined (__STDC__)
-
-#define YY_USE_CONST
-
-#endif	/* defined (__STDC__) */
-#endif	/* ! __cplusplus */
-
-#ifdef YY_USE_CONST
-#define yyconst const
-#else
-#define yyconst
-#endif
-
-/* Returned upon end-of-file. */
-#define YY_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 YY_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 (yy_start) = 1 + 2 *
-
-/* Translate the current start state into a value that can be later handed
- * to BEGIN to return to the state.  The YYSTATE alias is for lex
- * compatibility.
- */
-#define YY_START (((yy_start) - 1) / 2)
-#define YYSTATE YY_START
-
-/* Action number for EOF rule of a given start state. */
-#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
-
-/* Special action meaning "start processing a new file". */
-#define YY_NEW_FILE fitshdrrestart(fitshdrin  )
-
-#define YY_END_OF_BUFFER_CHAR 0
-
-/* Size of default input buffer. */
-#ifndef YY_BUF_SIZE
-#ifdef __ia64__
-/* On IA-64, the buffer size is 16k, not 8k.
- * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
- * Ditto for the __ia64__ case accordingly.
- */
-#define YY_BUF_SIZE 32768
-#else
-#define YY_BUF_SIZE 16384
-#endif /* __ia64__ */
-#endif
-
-/* The state buf must be large enough to hold one state per character in the main buffer.
- */
-#define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
-
-#ifndef YY_TYPEDEF_YY_BUFFER_STATE
-#define YY_TYPEDEF_YY_BUFFER_STATE
-typedef struct yy_buffer_state *YY_BUFFER_STATE;
-#endif
-
-extern int fitshdrleng;
-
-extern FILE *fitshdrin, *fitshdrout;
-
-#define EOB_ACT_CONTINUE_SCAN 0
-#define EOB_ACT_END_OF_FILE 1
-#define EOB_ACT_LAST_MATCH 2
-
-#define YY_LESS_LINENO(n)
-    
-/* Return all but the first "n" matched characters back to the input stream. */
-#define yyless(n) \
-	do \
-		{ \
-		/* Undo effects of setting up fitshdrtext. */ \
-        int yyless_macro_arg = (n); \
-        YY_LESS_LINENO(yyless_macro_arg);\
-		*yy_cp = (yy_hold_char); \
-		YY_RESTORE_YY_MORE_OFFSET \
-		(yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
-		YY_DO_BEFORE_ACTION; /* set up fitshdrtext again */ \
-		} \
-	while ( 0 )
-
-#define unput(c) yyunput( c, (yytext_ptr)  )
-
-#ifndef YY_TYPEDEF_YY_SIZE_T
-#define YY_TYPEDEF_YY_SIZE_T
-typedef size_t yy_size_t;
-#endif
-
-#ifndef YY_STRUCT_YY_BUFFER_STATE
-#define YY_STRUCT_YY_BUFFER_STATE
-struct yy_buffer_state
-	{
-	FILE *yy_input_file;
-
-	char *yy_ch_buf;		/* input buffer */
-	char *yy_buf_pos;		/* current position in input buffer */
-
-	/* Size of input buffer in bytes, not including room for EOB
-	 * characters.
-	 */
-	yy_size_t yy_buf_size;
-
-	/* Number of characters read into yy_ch_buf, not including EOB
-	 * characters.
-	 */
-	int yy_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 yy_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 yy_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 yy_at_bol;
-
-    int yy_bs_lineno; /**< The line count. */
-    int yy_bs_column; /**< The column count. */
-    
-	/* Whether to try to fill the input buffer when we reach the
-	 * end of it.
-	 */
-	int yy_fill_buffer;
-
-	int yy_buffer_status;
-
-#define YY_BUFFER_NEW 0
-#define YY_BUFFER_NORMAL 1
-	/* When an EOF's been seen but there's still some text to process
-	 * then we mark the buffer as YY_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 fitshdrrestart()), so that the user can continue scanning by
-	 * just pointing fitshdrin at a new input file.
-	 */
-#define YY_BUFFER_EOF_PENDING 2
-
-	};
-#endif /* !YY_STRUCT_YY_BUFFER_STATE */
-
-/* Stack of input buffers. */
-static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
-static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
-static YY_BUFFER_STATE * yy_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 YY_CURRENT_BUFFER ( (yy_buffer_stack) \
-                          ? (yy_buffer_stack)[(yy_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 YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
-
-/* yy_hold_char holds the character lost when fitshdrtext is formed. */
-static char yy_hold_char;
-static int yy_n_chars;		/* number of characters read into yy_ch_buf */
-int fitshdrleng;
-
-/* Points to current character in buffer. */
-static char *yy_c_buf_p = (char *) 0;
-static int yy_init = 0;		/* whether we need to initialize */
-static int yy_start = 0;	/* start state number */
-
-/* Flag which is used to allow fitshdrwrap()'s to do buffer switches
- * instead of setting up a fresh fitshdrin.  A bit of a hack ...
- */
-static int yy_did_buffer_switch_on_eof;
-
-void fitshdrrestart (FILE *input_file  );
-void fitshdr_switch_to_buffer (YY_BUFFER_STATE new_buffer  );
-YY_BUFFER_STATE fitshdr_create_buffer (FILE *file,int size  );
-void fitshdr_delete_buffer (YY_BUFFER_STATE b  );
-void fitshdr_flush_buffer (YY_BUFFER_STATE b  );
-void fitshdrpush_buffer_state (YY_BUFFER_STATE new_buffer  );
-void fitshdrpop_buffer_state (void );
-
-static void fitshdrensure_buffer_stack (void );
-static void fitshdr_load_buffer_state (void );
-static void fitshdr_init_buffer (YY_BUFFER_STATE b,FILE *file  );
-
-#define YY_FLUSH_BUFFER fitshdr_flush_buffer(YY_CURRENT_BUFFER )
-
-YY_BUFFER_STATE fitshdr_scan_buffer (char *base,yy_size_t size  );
-YY_BUFFER_STATE fitshdr_scan_string (yyconst char *yy_str  );
-YY_BUFFER_STATE fitshdr_scan_bytes (yyconst char *bytes,int len  );
-
-void *fitshdralloc (yy_size_t  );
-void *fitshdrrealloc (void *,yy_size_t  );
-void fitshdrfree (void *  );
-
-#define yy_new_buffer fitshdr_create_buffer
-
-#define yy_set_interactive(is_interactive) \
-	{ \
-	if ( ! YY_CURRENT_BUFFER ){ \
-        fitshdrensure_buffer_stack (); \
-		YY_CURRENT_BUFFER_LVALUE =    \
-            fitshdr_create_buffer(fitshdrin,YY_BUF_SIZE ); \
-	} \
-	YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
-	}
-
-#define yy_set_bol(at_bol) \
-	{ \
-	if ( ! YY_CURRENT_BUFFER ){\
-        fitshdrensure_buffer_stack (); \
-		YY_CURRENT_BUFFER_LVALUE =    \
-            fitshdr_create_buffer(fitshdrin,YY_BUF_SIZE ); \
-	} \
-	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
-	}
-
-#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
-
-/* Begin user sect3 */
-
-#define fitshdrwrap(n) 1
-#define YY_SKIP_YYWRAP
-
-typedef char YY_CHAR;
-
-FILE *fitshdrin = (FILE *) 0, *fitshdrout = (FILE *) 0;
-
-typedef int yy_state_type;
-
-extern int fitshdrlineno;
-
-int fitshdrlineno = 1;
-
-extern char *fitshdrtext;
-#define yytext_ptr fitshdrtext
-static yyconst flex_int16_t yy_nxt[][128] =
-    {
-    {
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0
-    },
-
-    {
-       15,   16,   16,   16,   16,   16,   16,   16,   16,   16,
-       16,   16,   16,   16,   16,   16,   16,   16,   16,   16,
-       16,   16,   16,   16,   16,   16,   16,   16,   16,   16,
-       16,   16,   16,   16,   16,   16,   16,   16,   16,   16,
-       16,   16,   16,   16,   16,   16,   16,   16,   16,   16,
-       16,   16,   16,   16,   16,   16,   16,   16,   16,   16,
-       16,   16,   16,   16,   16,   16,   16,   16,   16,   16,
-
-       16,   16,   16,   16,   16,   16,   16,   16,   16,   16,
-       16,   16,   16,   16,   16,   16,   16,   16,   16,   16,
-       16,   16,   16,   16,   16,   16,   16,   16,   16,   16,
-       16,   16,   16,   16,   16,   16,   16,   16,   16,   16,
-       16,   16,   16,   16,   16,   16,   16,   16,   16,   16,
-       16,   16,   16,   16,   16,   16,   16,   16
-    },
-
-    {
-       15,   17,   17,   17,   17,   17,   17,   17,   17,   17,
-       16,   17,   17,   17,   17,   17,   17,   17,   17,   17,
-       17,   17,   17,   17,   17,   17,   17,   17,   17,   17,
-       17,   17,   18,   17,   17,   17,   17,   17,   17,   17,
-
-       17,   17,   17,   17,   17,   19,   17,   17,   19,   19,
-       19,   19,   19,   19,   19,   19,   19,   19,   17,   17,
-       17,   17,   17,   17,   17,   19,   19,   20,   19,   21,
-       19,   19,   22,   19,   19,   19,   19,   19,   19,   19,
-       19,   19,   19,   19,   19,   19,   19,   19,   19,   19,
-       19,   17,   17,   17,   17,   19,   17,   17,   17,   17,
-       17,   17,   17,   17,   17,   17,   17,   17,   17,   17,
-       17,   17,   17,   17,   17,   17,   17,   17,   17,   17,
-       17,   17,   17,   17,   17,   17,   17,   17
-    },
-
-    {
-       15,   23,   23,   23,   23,   23,   23,   23,   23,   23,
-
-       16,   23,   23,   23,   23,   23,   23,   23,   23,   23,
-       23,   23,   23,   23,   23,   23,   23,   23,   23,   23,
-       23,   23,   24,   23,   23,   23,   23,   23,   23,   25,
-       26,   23,   23,   27,   23,   27,   28,   29,   30,   31,
-       31,   31,   31,   31,   31,   31,   31,   31,   23,   23,
-       23,   23,   23,   23,   23,   23,   23,   23,   23,   23,
-       32,   23,   23,   23,   23,   23,   23,   23,   23,   23,
-       23,   23,   23,   23,   32,   23,   23,   23,   23,   23,
-       23,   23,   23,   23,   23,   23,   23,   23,   23,   23,
-       23,   23,   23,   23,   23,   23,   23,   23,   23,   23,
-
-       23,   23,   23,   23,   23,   23,   23,   23,   23,   23,
-       23,   23,   23,   23,   23,   23,   23,   23
-    },
-
-    {
-       15,   23,   23,   23,   23,   23,   23,   23,   23,   23,
-       16,   23,   23,   23,   23,   23,   23,   23,   23,   23,
-       23,   23,   23,   23,   23,   23,   23,   23,   23,   23,
-       23,   23,   24,   23,   23,   23,   23,   23,   23,   25,
-       26,   23,   23,   27,   23,   27,   28,   29,   30,   31,
-       31,   31,   31,   31,   31,   31,   31,   31,   23,   23,
-       23,   23,   23,   23,   23,   23,   23,   23,   23,   23,
-       32,   23,   23,   23,   23,   23,   23,   23,   23,   23,
-
-       23,   23,   23,   23,   32,   23,   23,   23,   23,   23,
-       23,   23,   23,   23,   23,   23,   23,   23,   23,   23,
-       23,   23,   23,   23,   23,   23,   23,   23,   23,   23,
-       23,   23,   23,   23,   23,   23,   23,   23,   23,   23,
-       23,   23,   23,   23,   23,   23,   23,   23
-    },
-
-    {
-       15,   33,   33,   33,   33,   33,   33,   33,   33,   33,
-       34,   33,   33,   33,   33,   33,   33,   33,   33,   33,
-       33,   33,   33,   33,   33,   33,   33,   33,   33,   33,
-       33,   33,   35,   33,   33,   33,   33,   33,   33,   33,
-       33,   33,   33,   33,   33,   33,   33,   36,   33,   33,
-
-       33,   33,   33,   33,   33,   33,   33,   33,   33,   33,
-       33,   33,   33,   33,   33,   33,   33,   33,   33,   33,
-       33,   33,   33,   33,   33,   33,   33,   33,   33,   33,
-       33,   33,   33,   33,   33,   33,   33,   33,   33,   33,
-       33,   33,   33,   33,   33,   33,   33,   33,   33,   33,
-       33,   33,   33,   33,   33,   33,   33,   33,   33,   33,
-       33,   33,   33,   33,   33,   33,   33,   33,   33,   33,
-       33,   33,   33,   33,   33,   33,   33,   33
-    },
-
-    {
-       15,   33,   33,   33,   33,   33,   33,   33,   33,   33,
-       34,   33,   33,   33,   33,   33,   33,   33,   33,   33,
-
-       33,   33,   33,   33,   33,   33,   33,   33,   33,   33,
-       33,   33,   35,   33,   33,   33,   33,   33,   33,   33,
-       33,   33,   33,   33,   33,   33,   33,   36,   33,   33,
-       33,   33,   33,   33,   33,   33,   33,   33,   33,   33,
-       33,   33,   33,   33,   33,   33,   33,   33,   33,   33,
-       33,   33,   33,   33,   33,   33,   33,   33,   33,   33,
-       33,   33,   33,   33,   33,   33,   33,   33,   33,   33,
-       33,   33,   33,   33,   33,   33,   33,   33,   33,   33,
-       33,   33,   33,   33,   33,   33,   33,   33,   33,   33,
-       33,   33,   33,   33,   33,   33,   33,   33,   33,   33,
-
-       33,   33,   33,   33,   33,   33,   33,   33
-    },
-
-    {
-       15,   37,   37,   37,   37,   37,   37,   37,   37,   37,
-       16,   37,   37,   37,   37,   37,   37,   37,   37,   37,
-       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
-       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
-       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
-       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
-       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
-       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
-       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
-
-       37,   38,   37,   37,   37,   37,   37,   37,   37,   37,
-       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
-       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
-       37,   37,   37,   37,   37,   37,   37,   37
-    },
-
-    {
-       15,   37,   37,   37,   37,   37,   37,   37,   37,   37,
-       16,   37,   37,   37,   37,   37,   37,   37,   37,   37,
-       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
-       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
-       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
-       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
-
-       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
-       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
-       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
-       37,   38,   37,   37,   37,   37,   37,   37,   37,   37,
-       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
-       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
-       37,   37,   37,   37,   37,   37,   37,   37
-    },
-
-    {
-       15,   39,   39,   39,   39,   39,   39,   39,   39,   39,
-       16,   39,   39,   39,   39,   39,   39,   39,   39,   39,
-       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
-
-       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
-       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
-       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
-       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
-       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
-       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
-       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
-       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
-       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
-       39,   39,   39,   39,   39,   39,   39,   39
-
-    },
-
-    {
-       15,   39,   39,   39,   39,   39,   39,   39,   39,   39,
-       16,   39,   39,   39,   39,   39,   39,   39,   39,   39,
-       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
-       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
-       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
-       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
-       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
-       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
-       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
-       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
-
-       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
-       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
-       39,   39,   39,   39,   39,   39,   39,   39
-    },
-
-    {
-       15,   40,   40,   40,   40,   40,   40,   40,   40,   40,
-       16,   40,   40,   40,   40,   40,   40,   40,   40,   40,
-       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
-       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
-       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
-       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
-       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
-
-       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
-       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
-       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
-       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
-       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
-       40,   40,   40,   40,   40,   40,   40,   40
-    },
-
-    {
-       15,   40,   40,   40,   40,   40,   40,   40,   40,   40,
-       16,   40,   40,   40,   40,   40,   40,   40,   40,   40,
-       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
-       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
-
-       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
-       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
-       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
-       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
-       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
-       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
-       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
-       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
-       40,   40,   40,   40,   40,   40,   40,   40
-    },
-
-    {
-       15,   41,   41,   41,   41,   41,   41,   41,   41,   41,
-
-       42,   41,   41,   41,   41,   41,   41,   41,   41,   41,
-       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
-       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
-       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
-       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
-       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
-       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
-       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
-       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
-       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
-
-       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
-       41,   41,   41,   41,   41,   41,   41,   41
-    },
-
-    {
-       15,   41,   41,   41,   41,   41,   41,   41,   41,   41,
-       42,   41,   41,   41,   41,   41,   41,   41,   41,   41,
-       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
-       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
-       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
-       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
-       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
-       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
-
-       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
-       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
-       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
-       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
-       41,   41,   41,   41,   41,   41,   41,   41
-    },
-
-    {
-      -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,  -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
-    },
-
-    {
-       15,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
-      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
-
-      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
-      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
-      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
-      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
-      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
-      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
-      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
-      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
-      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
-      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
-
-      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16
-    },
-
-    {
-       15,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-      -17,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43
-    },
-
-    {
-       15,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-      -18,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   44,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43
-    },
-
-    {
-       15,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-      -19,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43,   43,   45,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   46,   43,   43,   46,   46,
-       46,   46,   46,   46,   46,   46,   46,   46,   43,   43,
-       43,   43,   43,   43,   43,   46,   46,   46,   46,   46,
-       46,   46,   46,   46,   46,   46,   46,   46,   46,   46,
-       46,   46,   46,   46,   46,   46,   46,   46,   46,   46,
-       46,   43,   43,   43,   43,   46,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43
-
-    },
-
-    {
-       15,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-      -20,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   45,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   46,   43,   43,   46,   46,
-       46,   46,   46,   46,   46,   46,   46,   46,   43,   43,
-       43,   43,   43,   43,   43,   46,   46,   46,   46,   46,
-       46,   46,   46,   46,   46,   46,   46,   46,   46,   47,
-       46,   46,   46,   46,   46,   46,   46,   46,   46,   46,
-       46,   43,   43,   43,   43,   46,   43,   43,   43,   43,
-
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43
-    },
-
-    {
-       15,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-      -21,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   45,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   46,   43,   43,   46,   46,
-       46,   46,   46,   46,   46,   46,   46,   46,   43,   43,
-       43,   43,   43,   43,   43,   46,   46,   46,   46,   46,
-
-       46,   46,   46,   46,   46,   46,   46,   46,   48,   46,
-       46,   46,   46,   46,   46,   46,   46,   46,   46,   46,
-       46,   43,   43,   43,   43,   46,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43
-    },
-
-    {
-       15,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-      -22,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   45,   43,   43,   43,   43,   43,   43,   43,
-
-       43,   43,   43,   43,   43,   46,   43,   43,   46,   46,
-       46,   46,   46,   46,   46,   46,   46,   46,   43,   43,
-       43,   43,   43,   43,   43,   46,   46,   46,   46,   46,
-       46,   46,   46,   49,   46,   46,   46,   46,   46,   46,
-       46,   46,   46,   46,   46,   46,   46,   46,   46,   46,
-       46,   43,   43,   43,   43,   46,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43
-    },
-
-    {
-       15,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
-
-      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
-      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
-      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
-      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
-      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
-      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
-      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
-      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
-      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
-      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
-
-      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
-      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23
-    },
-
-    {
-       15,  -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,   50,  -24,  -24,  -24,  -24,  -24,  -24,  -24,
-      -24,  -24,  -24,  -24,  -24,  -24,  -24,   51,  -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,
-
-      -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,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,
-      -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24
-    },
-
-    {
-       15,   52,   52,   52,   52,   52,   52,   52,   52,   52,
-       52,   52,   52,   52,   52,   52,   52,   52,   52,   52,
-       52,   52,   52,   52,   52,   52,   52,   52,   52,   52,
-       52,   52,   52,   52,   52,   52,   52,   52,   52,   53,
-       52,   52,   52,   52,   52,   52,   52,   52,   52,   52,
-
-       52,   52,   52,   52,   52,   52,   52,   52,   52,   52,
-       52,   52,   52,   52,   52,   52,   52,   52,   52,   52,
-       52,   52,   52,   52,   52,   52,   52,   52,   52,   52,
-       52,   52,   52,   52,   52,   52,   52,   52,   52,   52,
-       52,   52,   52,   52,   52,   52,   52,   52,   52,   52,
-       52,   52,   52,   52,   52,   52,   52,   52,   52,   52,
-       52,   52,   52,   52,   52,   52,   52,   52,   52,   52,
-       52,   52,   52,   52,   52,   52,   52,   52
-    },
-
-    {
-       15,  -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,   54,  -26,  -26,  -26,  -26,  -26,  -26,  -26,
-      -26,  -26,  -26,   55,  -26,   55,   56,  -26,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,  -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,
-      -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,  -26,  -26,  -26,  -26,  -26,  -26
-    },
-
-    {
-       15,  -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,  -27,  -27,  -27,  -27,  -27,  -27,  -27,
-      -27,  -27,  -27,  -27,  -27,  -27,   58,  -27,   59,   60,
-       60,   60,   60,   60,   60,   60,   60,   60,  -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,
-
-      -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,  -27,  -27,  -27,  -27,  -27,  -27
-    },
-
-    {
-       15,  -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,   61,   61,
-       61,   61,   61,   61,   61,   61,   61,   61,  -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,  -28,  -28,  -28,  -28,  -28,  -28
-    },
-
-    {
-       15,  -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,  -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
-
-    },
-
-    {
-       15,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
-      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
-      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
-      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
-      -30,  -30,  -30,  -30,  -30,  -30,   62,  -30,   63,   64,
-       64,   64,   64,   64,   64,   64,   64,   64,  -30,  -30,
-      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,   65,
-      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
-      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
-      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
-
-      -30,   65,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
-      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
-      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30
-    },
-
-    {
-       15,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
-      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
-      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
-      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
-      -31,  -31,  -31,  -31,  -31,  -31,   62,  -31,   66,   66,
-       66,   66,   66,   66,   66,   66,   66,   66,  -31,  -31,
-      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,   65,
-
-      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
-      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
-      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
-      -31,   65,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
-      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
-      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31
-    },
-
-    {
-       15,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
-      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
-      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
-      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
-
-      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
-      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
-      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
-      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
-      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
-      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
-      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
-      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
-      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32
-    },
-
-    {
-       15,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
-
-      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
-      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
-      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
-      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
-      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
-      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
-      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
-      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
-      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
-      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
-
-      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
-      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33
-    },
-
-    {
-       15,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34
-    },
-
-    {
-       15,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
-       67,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
-      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
-      -35,  -35,   68,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
-      -35,  -35,  -35,  -35,  -35,  -35,  -35,   69,  -35,  -35,
-
-      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
-      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
-      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
-      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
-      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
-      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
-      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
-      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35
-    },
-
-    {
-       15,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
-       70,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
-
-      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
-      -36,  -36,   71,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
-      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
-      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
-      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
-      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
-      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
-      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
-      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
-      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
-
-      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36
-    },
-
-    {
-       15,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
-      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
-      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
-      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
-      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
-      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
-      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
-      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
-      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
-
-      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
-      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
-      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
-      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37
-    },
-
-    {
-       15,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
-      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
-      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
-      -38,  -38,   72,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
-       72,   72,   72,   72,  -38,   72,   72,   72,   72,   72,
-       72,   72,   72,   72,   72,   72,   72,   72,  -38,  -38,
-
-      -38,  -38,  -38,  -38,  -38,   72,   72,   72,   72,   72,
-       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
-       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
-       72,  -38,  -38,  -38,   72,  -38,  -38,   72,   72,   72,
-       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
-       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
-       72,   72,   72,  -38,  -38,  -38,  -38,  -38
-    },
-
-    {
-       15,   73,   73,   73,   73,   73,   73,   73,   73,   73,
-      -39,   73,   73,   73,   73,   73,   73,   73,   73,   73,
-       73,   73,   73,   73,   73,   73,   73,   73,   73,   73,
-
-       73,   73,   73,   73,   73,   73,   73,   73,   73,   73,
-       73,   73,   73,   73,   73,   73,   73,   73,   73,   73,
-       73,   73,   73,   73,   73,   73,   73,   73,   73,   73,
-       73,   73,   73,   73,   73,   73,   73,   73,   73,   73,
-       73,   73,   73,   73,   73,   73,   73,   73,   73,   73,
-       73,   73,   73,   73,   73,   73,   73,   73,   73,   73,
-       73,   73,   73,   73,   73,   73,   73,   73,   73,   73,
-       73,   73,   73,   73,   73,   73,   73,   73,   73,   73,
-       73,   73,   73,   73,   73,   73,   73,   73,   73,   73,
-       73,   73,   73,   73,   73,   73,   73,   73
-
-    },
-
-    {
-       15,   74,   74,   74,   74,   74,   74,   74,   74,   74,
-      -40,   74,   74,   74,   74,   74,   74,   74,   74,   74,
-       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
-       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
-       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
-       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
-       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
-       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
-       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
-       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
-
-       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
-       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
-       74,   74,   74,   74,   74,   74,   74,   74
-    },
-
-    {
-       15,   75,   75,   75,   75,   75,   75,   75,   75,   75,
-       76,   75,   75,   75,   75,   75,   75,   75,   75,   75,
-       75,   75,   75,   75,   75,   75,   75,   75,   75,   75,
-       75,   75,   75,   75,   75,   75,   75,   75,   75,   75,
-       75,   75,   75,   75,   75,   75,   75,   75,   75,   75,
-       75,   75,   75,   75,   75,   75,   75,   75,   75,   75,
-       75,   75,   75,   75,   75,   75,   75,   75,   75,   75,
-
-       75,   75,   75,   75,   75,   75,   75,   75,   75,   75,
-       75,   75,   75,   75,   75,   75,   75,   75,   75,   75,
-       75,   75,   75,   75,   75,   75,   75,   75,   75,   75,
-       75,   75,   75,   75,   75,   75,   75,   75,   75,   75,
-       75,   75,   75,   75,   75,   75,   75,   75,   75,   75,
-       75,   75,   75,   75,   75,   75,   75,   75
-    },
-
-    {
-       15,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
-      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
-      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
-      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
-
-      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
-      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
-      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
-      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
-      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
-      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
-      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
-      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
-      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42
-    },
-
-    {
-       15,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-
-      -43,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77
-    },
-
-    {
-       15,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-      -44,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   78,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77
-    },
-
-    {
-       15,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-      -45,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   79,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77
-    },
-
-    {
-       15,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-      -46,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   80,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   81,   77,   77,   81,   81,
-       81,   81,   81,   81,   81,   81,   81,   81,   77,   77,
-       77,   77,   77,   77,   77,   81,   81,   81,   81,   81,
-       81,   81,   81,   81,   81,   81,   81,   81,   81,   81,
-       81,   81,   81,   81,   81,   81,   81,   81,   81,   81,
-       81,   77,   77,   77,   77,   81,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-
-       77,   77,   77,   77,   77,   77,   77,   77
-    },
-
-    {
-       15,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-      -47,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   80,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   81,   77,   77,   81,   81,
-       81,   81,   81,   81,   81,   81,   81,   81,   77,   77,
-       77,   77,   77,   77,   77,   81,   81,   81,   81,   81,
-       81,   81,   81,   81,   81,   81,   81,   82,   83,   81,
-       81,   81,   81,   81,   81,   81,   81,   81,   81,   81,
-
-       81,   77,   77,   77,   77,   81,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77
-    },
-
-    {
-       15,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-      -48,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   80,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   81,   77,   77,   81,   81,
-       81,   81,   81,   81,   81,   81,   81,   81,   77,   77,
-
-       77,   77,   77,   77,   77,   81,   81,   81,   84,   81,
-       81,   81,   81,   81,   81,   81,   81,   81,   81,   81,
-       81,   81,   81,   81,   81,   81,   81,   81,   81,   81,
-       81,   77,   77,   77,   77,   81,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77
-    },
-
-    {
-       15,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-      -49,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-
-       77,   77,   80,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   81,   77,   77,   81,   81,
-       81,   81,   81,   81,   81,   81,   81,   81,   77,   77,
-       77,   77,   77,   77,   77,   81,   81,   81,   81,   81,
-       81,   81,   81,   81,   81,   81,   81,   81,   81,   81,
-       81,   81,   81,   85,   81,   81,   81,   81,   81,   81,
-       81,   77,   77,   77,   77,   81,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77
-
-    },
-
-    {
-       15,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
-      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
-      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
-      -50,  -50,   50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
-      -50,  -50,  -50,  -50,  -50,  -50,  -50,   51,  -50,  -50,
-      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
-      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
-      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
-      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
-      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
-
-      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
-      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
-      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50
-    },
-
-    {
-       15,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51
-    },
-
-    {
-       15,   52,   52,   52,   52,   52,   52,   52,   52,   52,
-       52,   52,   52,   52,   52,   52,   52,   52,   52,   52,
-       52,   52,   52,   52,   52,   52,   52,   52,   52,   52,
-       52,   52,   52,   52,   52,   52,   52,   52,   52,   53,
-
-       52,   52,   52,   52,   52,   52,   52,   52,   52,   52,
-       52,   52,   52,   52,   52,   52,   52,   52,   52,   52,
-       52,   52,   52,   52,   52,   52,   52,   52,   52,   52,
-       52,   52,   52,   52,   52,   52,   52,   52,   52,   52,
-       52,   52,   52,   52,   52,   52,   52,   52,   52,   52,
-       52,   52,   52,   52,   52,   52,   52,   52,   52,   52,
-       52,   52,   52,   52,   52,   52,   52,   52,   52,   52,
-       52,   52,   52,   52,   52,   52,   52,   52,   52,   52,
-       52,   52,   52,   52,   52,   52,   52,   52
-    },
-
-    {
-       15,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
-
-      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
-      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
-      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,   52,
-      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
-      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
-      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
-      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
-      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
-      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
-      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
-
-      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
-      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53
-    },
-
-    {
-       15,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
-      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
-      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
-      -54,  -54,   54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
-      -54,  -54,  -54,   55,  -54,   55,   56,  -54,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,  -54,  -54,
-      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
-      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
-
-      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
-      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
-      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
-      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
-      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54
-    },
-
-    {
-       15,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
-      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
-      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
-      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
-      -55,  -55,  -55,  -55,  -55,  -55,   56,  -55,   57,   57,
-
-       57,   57,   57,   57,   57,   57,   57,   57,  -55,  -55,
-      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
-      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
-      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
-      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
-      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
-      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
-      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55
-    },
-
-    {
-       15,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
-      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
-
-      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
-      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
-      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,   86,   86,
-       86,   86,   86,   86,   86,   86,   86,   86,  -56,  -56,
-      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
-      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
-      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
-      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
-      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
-      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
-
-      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56
-    },
-
-    {
-       15,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
-      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
-      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
-      -57,  -57,   87,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
-      -57,  -57,  -57,  -57,   88,  -57,   89,  -57,   90,   90,
-       90,   90,   90,   90,   90,   90,   90,   90,  -57,  -57,
-      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,   91,
-      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
-      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
-
-      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
-      -57,   91,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
-      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
-      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57
-    },
-
-    {
-       15,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
-      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
-      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
-      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
-      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,   61,   61,
-       61,   61,   61,   61,   61,   61,   61,   61,  -58,  -58,
-
-      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
-      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
-      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
-      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
-      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
-      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
-      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58
-    },
-
-    {
-       15,  -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,  -59,  -59,
-      -59,  -59,  -59,  -59,  -59,  -59,   62,  -59,   63,   64,
-       64,   64,   64,   64,   64,   64,   64,   64,  -59,  -59,
-      -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,   65,
-      -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,   65,  -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
-
-    },
-
-    {
-       15,  -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,  -60,   66,   66,
-       66,   66,   66,   66,   66,   66,   66,   66,  -60,  -60,
-      -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,   65,
-      -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,   65,  -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
-    },
-
-    {
-       15,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
-      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
-      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
-      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
-      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,   61,   61,
-       61,   61,   61,   61,   61,   61,   61,   61,  -61,  -61,
-      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,   65,
-
-      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
-      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
-      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
-      -61,   65,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
-      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
-      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61
-    },
-
-    {
-       15,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
-      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
-      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
-      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
-
-      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,   92,   92,
-       92,   92,   92,   92,   92,   92,   92,   92,  -62,  -62,
-      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,   65,
-      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
-      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
-      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
-      -62,   65,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
-      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
-      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62
-    },
-
-    {
-       15,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
-
-      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
-      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
-      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
-      -63,  -63,  -63,  -63,  -63,  -63,   62,  -63,   93,   94,
-       94,   94,   94,   94,   94,   94,   94,   94,  -63,  -63,
-      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,   65,
-      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
-      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
-      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
-      -63,   65,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
-
-      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
-      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63
-    },
-
-    {
-       15,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
-      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
-      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
-      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
-      -64,  -64,  -64,  -64,  -64,  -64,   62,  -64,   95,   95,
-       95,   95,   95,   95,   95,   95,   95,   95,  -64,  -64,
-      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,   65,
-      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
-
-      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
-      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
-      -64,   65,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
-      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
-      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64
-    },
-
-    {
-       15,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
-      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
-      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
-      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
-      -65,  -65,  -65,   96,  -65,   96,  -65,  -65,   97,   97,
-
-       97,   97,   97,   97,   97,   97,   97,   97,  -65,  -65,
-      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
-      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
-      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
-      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
-      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
-      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
-      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65
-    },
-
-    {
-       15,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
-      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
-
-      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
-      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
-      -66,  -66,  -66,  -66,  -66,  -66,   62,  -66,   98,   98,
-       98,   98,   98,   98,   98,   98,   98,   98,  -66,  -66,
-      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,   65,
-      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
-      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
-      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
-      -66,   65,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
-      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
-
-      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66
-    },
-
-    {
-       15,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67
-    },
-
-    {
-       15,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-       67,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-      -68,  -68,   68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-      -68,  -68,  -68,  -68,  -68,  -68,  -68,   69,  -68,  -68,
-      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-
-      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68
-    },
-
-    {
-       15,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-       70,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-
-      -69,  -69,   71,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69
-
-    },
-
-    {
-       15,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
-      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
-      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
-      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
-      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
-      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
-      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
-      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
-      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
-      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
-
-      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
-      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
-      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70
-    },
-
-    {
-       15,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
-       70,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
-      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
-      -71,  -71,   71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
-      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
-      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
-      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
-
-      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
-      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
-      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
-      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
-      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
-      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71
-    },
-
-    {
-       15,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
-      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
-      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
-      -72,  -72,   72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
-
-       72,   72,   72,   72,  -72,   72,   72,   72,   72,   72,
-       72,   72,   72,   72,   72,   72,   72,   72,  -72,  -72,
-      -72,  -72,  -72,  -72,  -72,   72,   72,   72,   72,   72,
-       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
-       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
-       72,  -72,  -72,   99,   72,  -72,  -72,   72,   72,   72,
-       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
-       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
-       72,   72,   72,  -72,  -72,  -72,  -72,  -72
-    },
-
-    {
-       15,   73,   73,   73,   73,   73,   73,   73,   73,   73,
-
-      -73,   73,   73,   73,   73,   73,   73,   73,   73,   73,
-       73,   73,   73,   73,   73,   73,   73,   73,   73,   73,
-       73,   73,   73,   73,   73,   73,   73,   73,   73,   73,
-       73,   73,   73,   73,   73,   73,   73,   73,   73,   73,
-       73,   73,   73,   73,   73,   73,   73,   73,   73,   73,
-       73,   73,   73,   73,   73,   73,   73,   73,   73,   73,
-       73,   73,   73,   73,   73,   73,   73,   73,   73,   73,
-       73,   73,   73,   73,   73,   73,   73,   73,   73,   73,
-       73,   73,   73,   73,   73,   73,   73,   73,   73,   73,
-       73,   73,   73,   73,   73,   73,   73,   73,   73,   73,
-
-       73,   73,   73,   73,   73,   73,   73,   73,   73,   73,
-       73,   73,   73,   73,   73,   73,   73,   73
-    },
-
-    {
-       15,   74,   74,   74,   74,   74,   74,   74,   74,   74,
-      -74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
-       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
-       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
-       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
-       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
-       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
-       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
-
-       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
-       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
-       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
-       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
-       74,   74,   74,   74,   74,   74,   74,   74
-    },
-
-    {
-       15,   75,   75,   75,   75,   75,   75,   75,   75,   75,
-       76,   75,   75,   75,   75,   75,   75,   75,   75,   75,
-       75,   75,   75,   75,   75,   75,   75,   75,   75,   75,
-       75,   75,   75,   75,   75,   75,   75,   75,   75,   75,
-       75,   75,   75,   75,   75,   75,   75,   75,   75,   75,
-
-       75,   75,   75,   75,   75,   75,   75,   75,   75,   75,
-       75,   75,   75,   75,   75,   75,   75,   75,   75,   75,
-       75,   75,   75,   75,   75,   75,   75,   75,   75,   75,
-       75,   75,   75,   75,   75,   75,   75,   75,   75,   75,
-       75,   75,   75,   75,   75,   75,   75,   75,   75,   75,
-       75,   75,   75,   75,   75,   75,   75,   75,   75,   75,
-       75,   75,   75,   75,   75,   75,   75,   75,   75,   75,
-       75,   75,   75,   75,   75,   75,   75,   75
-    },
-
-    {
-       15,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
-      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
-
-      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
-      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
-      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
-      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
-      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
-      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
-      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
-      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
-      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
-      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
-
-      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76
-    },
-
-    {
-       15,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      -77,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-
-      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      100,  100,  100,  100,  100,  100,  100,  100
-    },
-
-    {
-       15,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      -78,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      100,  100,  101,  100,  100,  100,  100,  100,  100,  100,
-      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-
-      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      100,  100,  100,  100,  100,  100,  100,  100
-    },
-
-    {
-       15,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      -79,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-
-      100,  100,  102,  100,  100,  100,  100,  100,  100,  100,
-      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      100,  100,  100,  100,  100,  100,  100,  100
-
-    },
-
-    {
-       15,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      -80,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      100,  100,  103,  100,  100,  100,  100,  100,  100,  100,
-      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-
-      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      100,  100,  100,  100,  100,  100,  100,  100
-    },
-
-    {
-       15,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      -81,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      100,  100,  104,  100,  100,  100,  100,  100,  100,  100,
-      100,  100,  100,  100,  100,  105,  100,  100,  105,  105,
-      105,  105,  105,  105,  105,  105,  105,  105,  100,  100,
-      100,  100,  100,  100,  100,  105,  105,  105,  105,  105,
-
-      105,  105,  105,  105,  105,  105,  105,  105,  105,  105,
-      105,  105,  105,  105,  105,  105,  105,  105,  105,  105,
-      105,  100,  100,  100,  100,  105,  100,  100,  100,  100,
-      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      100,  100,  100,  100,  100,  100,  100,  100
-    },
-
-    {
-       15,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      -82,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      100,  100,  104,  100,  100,  100,  100,  100,  100,  100,
-
-      100,  100,  100,  100,  100,  105,  100,  100,  105,  105,
-      105,  105,  105,  105,  105,  105,  105,  105,  100,  100,
-      100,  100,  100,  100,  100,  105,  105,  105,  105,  105,
-      105,  105,  105,  105,  105,  105,  105,  106,  105,  105,
-      105,  105,  105,  105,  105,  105,  105,  105,  105,  105,
-      105,  100,  100,  100,  100,  105,  100,  100,  100,  100,
-      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      100,  100,  100,  100,  100,  100,  100,  100
-    },
-
-    {
-       15,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-
-      -83,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      100,  100,  104,  100,  100,  100,  100,  100,  100,  100,
-      100,  100,  100,  100,  100,  105,  100,  100,  105,  105,
-      105,  105,  105,  105,  105,  105,  105,  105,  100,  100,
-      100,  100,  100,  100,  100,  105,  105,  105,  105,  105,
-      105,  105,  105,  105,  105,  105,  105,  105,  105,  105,
-      105,  105,  105,  105,  107,  105,  105,  105,  105,  105,
-      105,  100,  100,  100,  100,  105,  100,  100,  100,  100,
-      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-
-      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      100,  100,  100,  100,  100,  100,  100,  100
-    },
-
-    {
-       15,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      -84,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      100,  100,  108,  100,  100,  100,  100,  100,  100,  100,
-      100,  100,  100,  100,  100,  105,  100,  100,  105,  105,
-      105,  105,  105,  105,  105,  105,  105,  105,  100,  100,
-      100,  100,  100,  100,  100,  105,  105,  105,  105,  105,
-      105,  105,  105,  105,  105,  105,  105,  105,  105,  105,
-
-      105,  105,  105,  105,  105,  105,  105,  105,  105,  105,
-      105,  100,  100,  100,  100,  105,  100,  100,  100,  100,
-      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      100,  100,  100,  100,  100,  100,  100,  100
-    },
-
-    {
-       15,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      -85,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      100,  100,  104,  100,  100,  100,  100,  100,  100,  100,
-      100,  100,  100,  100,  100,  105,  100,  100,  105,  105,
-
-      105,  105,  105,  105,  105,  105,  105,  105,  100,  100,
-      100,  100,  100,  100,  100,  105,  105,  105,  105,  105,
-      105,  105,  105,  105,  105,  105,  105,  105,  105,  105,
-      105,  105,  105,  105,  109,  105,  105,  105,  105,  105,
-      105,  100,  100,  100,  100,  105,  100,  100,  100,  100,
-      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
-      100,  100,  100,  100,  100,  100,  100,  100
-    },
-
-    {
-       15,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
-      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
-
-      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
-      -86,  -86,  110,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
-      -86,  -86,  -86,  -86,  111,  -86,  -86,  -86,   86,   86,
-       86,   86,   86,   86,   86,   86,   86,   86,  -86,  -86,
-      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,   91,
-      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
-      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
-      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
-      -86,   91,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
-      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
-
-      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86
-    },
-
-    {
-       15,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-      -87,  -87,   87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-      -87,  -87,  -87,  -87,   88,  -87,  -87,  -87,  -87,  -87,
-      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-
-      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87
-    },
-
-    {
-       15,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
-      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
-      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
-      -88,  -88,  112,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
-      -88,  -88,  -88,  113,  -88,  113,  114,  -88,  115,  115,
-      115,  115,  115,  115,  115,  115,  115,  115,  -88,  -88,
-
-      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
-      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
-      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
-      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
-      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
-      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
-      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88
-    },
-
-    {
-       15,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-
-      -89,  -89,  110,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-      -89,  -89,  -89,  -89,  111,  -89,  -89,  -89,  116,  116,
-      116,  116,  116,  116,  116,  116,  116,  116,  -89,  -89,
-      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,   91,
-      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-      -89,   91,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89
-
-    },
-
-    {
-       15,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
-      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
-      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
-      -90,  -90,   87,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
-      -90,  -90,  -90,  -90,   88,  -90,   89,  -90,   90,   90,
-       90,   90,   90,   90,   90,   90,   90,   90,  -90,  -90,
-      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,   91,
-      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
-      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
-      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
-
-      -90,   91,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
-      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
-      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90
-    },
-
-    {
-       15,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
-      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
-      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
-      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
-      -91,  -91,  -91,  117,  -91,  117,  -91,  -91,  118,  118,
-      118,  118,  118,  118,  118,  118,  118,  118,  -91,  -91,
-      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
-
-      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
-      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
-      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
-      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
-      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
-      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91
-    },
-
-    {
-       15,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
-      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
-      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
-      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
-
-      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,   92,   92,
-       92,   92,   92,   92,   92,   92,   92,   92,  -92,  -92,
-      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,   65,
-      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
-      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
-      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
-      -92,   65,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
-      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
-      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92
-    },
-
-    {
-       15,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-
-      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-      -93,  -93,  -93,  -93,  -93,  -93,   62,  -93,  119,  120,
-      120,  120,  120,  120,  120,  120,  120,  120,  -93,  -93,
-      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,   65,
-      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-      -93,   65,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-
-      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93
-    },
-
-    {
-       15,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
-      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
-      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
-      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
-      -94,  -94,  -94,  -94,  -94,  -94,   62,  -94,  121,  121,
-      121,  121,  121,  121,  121,  121,  121,  121,  -94,  -94,
-      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,   65,
-      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
-
-      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
-      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
-      -94,   65,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
-      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
-      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94
-    },
-
-    {
-       15,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
-      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
-      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
-      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
-      -95,  -95,  -95,  -95,  -95,  -95,   62,  -95,  122,  122,
-
-      122,  122,  122,  122,  122,  122,  122,  122,  -95,  -95,
-      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,   65,
-      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
-      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
-      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
-      -95,   65,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
-      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
-      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95
-    },
-
-    {
-       15,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
-      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
-
-      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
-      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
-      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,   97,   97,
-       97,   97,   97,   97,   97,   97,   97,   97,  -96,  -96,
-      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
-      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
-      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
-      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
-      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
-      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
-
-      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96
-    },
-
-    {
-       15,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
-      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
-      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
-      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
-      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,   97,   97,
-       97,   97,   97,   97,   97,   97,   97,   97,  -97,  -97,
-      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
-      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
-      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
-
-      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
-      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
-      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
-      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97
-    },
-
-    {
-       15,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
-      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
-      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
-      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
-      -98,  -98,  -98,  -98,  -98,  -98,   62,  -98,  123,  123,
-      123,  123,  123,  123,  123,  123,  123,  123,  -98,  -98,
-
-      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,   65,
-      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
-      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
-      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
-      -98,   65,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
-      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
-      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98
-    },
-
-    {
-       15,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-
-      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99
-
-    },
-
-    {
-       15,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-     -100,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124
-    },
-
-    {
-       15,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-     -101,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  125,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124
-    },
-
-    {
-       15,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-     -102,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  126,  124,  124,  124,  124,  124,  124,  124,
-
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124
-    },
-
-    {
-       15,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-
-     -103,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  127,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124
-    },
-
-    {
-       15,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-     -104,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  128,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124
-    },
-
-    {
-       15,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-     -105,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  129,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  130,  124,  124,  130,  130,
-
-      130,  130,  130,  130,  130,  130,  130,  130,  124,  124,
-      124,  124,  124,  124,  124,  130,  130,  130,  130,  130,
-      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-      130,  124,  124,  124,  124,  130,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124
-    },
-
-    {
-       15,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-     -106,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  129,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  130,  124,  124,  130,  130,
-      130,  130,  130,  130,  130,  130,  130,  130,  124,  124,
-      124,  124,  124,  124,  124,  130,  130,  130,  130,  131,
-      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-      130,  124,  124,  124,  124,  130,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-
-      124,  124,  124,  124,  124,  124,  124,  124
-    },
-
-    {
-       15,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-     -107,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  129,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  130,  124,  124,  130,  130,
-      130,  130,  130,  130,  130,  130,  130,  130,  124,  124,
-      124,  124,  124,  124,  124,  130,  130,  130,  130,  130,
-      130,  130,  130,  132,  130,  130,  130,  130,  130,  130,
-      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-
-      130,  124,  124,  124,  124,  130,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124
-    },
-
-    {
-       15,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-     -108,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  133,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124
-    },
-
-    {
-       15,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-     -109,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-
-      124,  124,  129,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  130,  124,  124,  130,  130,
-      130,  130,  130,  130,  130,  130,  130,  130,  124,  124,
-      124,  124,  124,  124,  124,  130,  130,  130,  130,  130,
-      130,  130,  130,  130,  130,  130,  130,  130,  130,  134,
-      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-      130,  124,  124,  124,  124,  130,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124
-
-    },
-
-    {
-       15, -110, -110, -110, -110, -110, -110, -110, -110, -110,
-     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
-     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
-     -110, -110,  110, -110, -110, -110, -110, -110, -110, -110,
-     -110, -110, -110, -110,  111, -110, -110, -110, -110, -110,
-     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
-     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
-     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
-     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
-     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
-
-     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
-     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
-     -110, -110, -110, -110, -110, -110, -110, -110
-    },
-
-    {
-       15, -111, -111, -111, -111, -111, -111, -111, -111, -111,
-     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
-     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
-     -111, -111,  135, -111, -111, -111, -111, -111, -111, -111,
-     -111, -111, -111,  136, -111,  136,  114, -111,  137,  137,
-      137,  137,  137,  137,  137,  137,  137,  137, -111, -111,
-     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
-
-     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
-     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
-     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
-     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
-     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
-     -111, -111, -111, -111, -111, -111, -111, -111
-    },
-
-    {
-       15, -112, -112, -112, -112, -112, -112, -112, -112, -112,
-     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
-     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
-     -112, -112,  112, -112, -112, -112, -112, -112, -112, -112,
-
-     -112, -112, -112,  113, -112,  113,  114, -112,  115,  115,
-      115,  115,  115,  115,  115,  115,  115,  115, -112, -112,
-     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
-     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
-     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
-     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
-     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
-     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
-     -112, -112, -112, -112, -112, -112, -112, -112
-    },
-
-    {
-       15, -113, -113, -113, -113, -113, -113, -113, -113, -113,
-
-     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
-     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
-     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
-     -113, -113, -113, -113, -113, -113,  114, -113,  115,  115,
-      115,  115,  115,  115,  115,  115,  115,  115, -113, -113,
-     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
-     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
-     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
-     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
-     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
-
-     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
-     -113, -113, -113, -113, -113, -113, -113, -113
-    },
-
-    {
-       15, -114, -114, -114, -114, -114, -114, -114, -114, -114,
-     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
-     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
-     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
-     -114, -114, -114, -114, -114, -114, -114, -114,  138,  138,
-      138,  138,  138,  138,  138,  138,  138,  138, -114, -114,
-     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
-     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
-
-     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
-     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
-     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
-     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
-     -114, -114, -114, -114, -114, -114, -114, -114
-    },
-
-    {
-       15, -115, -115, -115, -115, -115, -115, -115, -115, -115,
-     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
-     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
-     -115, -115,  139, -115, -115, -115, -115, -115, -115, -115,
-     -115,  140, -115, -115, -115, -115,  141, -115,  142,  142,
-
-      142,  142,  142,  142,  142,  142,  142,  142, -115, -115,
-     -115, -115, -115, -115, -115, -115, -115, -115, -115,  143,
-     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
-     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
-     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
-     -115,  143, -115, -115, -115, -115, -115, -115, -115, -115,
-     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
-     -115, -115, -115, -115, -115, -115, -115, -115
-    },
-
-    {
-       15, -116, -116, -116, -116, -116, -116, -116, -116, -116,
-     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
-
-     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
-     -116, -116,  110, -116, -116, -116, -116, -116, -116, -116,
-     -116, -116, -116, -116,  111, -116, -116, -116,  116,  116,
-      116,  116,  116,  116,  116,  116,  116,  116, -116, -116,
-     -116, -116, -116, -116, -116, -116, -116, -116, -116,   91,
-     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
-     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
-     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
-     -116,   91, -116, -116, -116, -116, -116, -116, -116, -116,
-     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
-
-     -116, -116, -116, -116, -116, -116, -116, -116
-    },
-
-    {
-       15, -117, -117, -117, -117, -117, -117, -117, -117, -117,
-     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
-     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
-     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
-     -117, -117, -117, -117, -117, -117, -117, -117,  118,  118,
-      118,  118,  118,  118,  118,  118,  118,  118, -117, -117,
-     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
-     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
-     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
-
-     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
-     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
-     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
-     -117, -117, -117, -117, -117, -117, -117, -117
-    },
-
-    {
-       15, -118, -118, -118, -118, -118, -118, -118, -118, -118,
-     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
-     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
-     -118, -118,  110, -118, -118, -118, -118, -118, -118, -118,
-     -118, -118, -118, -118,  111, -118, -118, -118,  118,  118,
-      118,  118,  118,  118,  118,  118,  118,  118, -118, -118,
-
-     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
-     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
-     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
-     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
-     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
-     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
-     -118, -118, -118, -118, -118, -118, -118, -118
-    },
-
-    {
-       15, -119, -119, -119, -119, -119, -119, -119, -119, -119,
-     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
-     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
-
-     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
-     -119, -119, -119, -119, -119, -119,   62, -119,  144,  145,
-      145,  145,  145,  145,  145,  145,  145,  145, -119, -119,
-     -119, -119, -119, -119, -119, -119, -119, -119, -119,   65,
-     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
-     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
-     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
-     -119,   65, -119, -119, -119, -119, -119, -119, -119, -119,
-     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
-     -119, -119, -119, -119, -119, -119, -119, -119
-
-    },
-
-    {
-       15, -120, -120, -120, -120, -120, -120, -120, -120, -120,
-     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
-     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
-     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
-     -120, -120, -120, -120, -120, -120,   62, -120,  146,  146,
-      146,  146,  146,  146,  146,  146,  146,  146, -120, -120,
-     -120, -120, -120, -120, -120, -120, -120, -120, -120,   65,
-     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
-     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
-     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
-
-     -120,   65, -120, -120, -120, -120, -120, -120, -120, -120,
-     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
-     -120, -120, -120, -120, -120, -120, -120, -120
-    },
-
-    {
-       15, -121, -121, -121, -121, -121, -121, -121, -121, -121,
-     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
-     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
-     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
-     -121, -121, -121, -121, -121, -121,   62, -121,  147,  147,
-      147,  147,  147,  147,  147,  147,  147,  147, -121, -121,
-     -121, -121, -121, -121, -121, -121, -121, -121, -121,   65,
-
-     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
-     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
-     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
-     -121,   65, -121, -121, -121, -121, -121, -121, -121, -121,
-     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
-     -121, -121, -121, -121, -121, -121, -121, -121
-    },
-
-    {
-       15, -122, -122, -122, -122, -122, -122, -122, -122, -122,
-     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
-     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
-     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
-
-     -122, -122, -122, -122, -122, -122,   62, -122,  148,  148,
-      148,  148,  148,  148,  148,  148,  148,  148, -122, -122,
-     -122, -122, -122, -122, -122, -122, -122, -122, -122,   65,
-     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
-     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
-     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
-     -122,   65, -122, -122, -122, -122, -122, -122, -122, -122,
-     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
-     -122, -122, -122, -122, -122, -122, -122, -122
-    },
-
-    {
-       15, -123, -123, -123, -123, -123, -123, -123, -123, -123,
-
-     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
-     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
-     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
-     -123, -123, -123, -123, -123, -123,   62, -123,  149,  149,
-      149,  149,  149,  149,  149,  149,  149,  149, -123, -123,
-     -123, -123, -123, -123, -123, -123, -123, -123, -123,   65,
-     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
-     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
-     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
-     -123,   65, -123, -123, -123, -123, -123, -123, -123, -123,
-
-     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
-     -123, -123, -123, -123, -123, -123, -123, -123
-    },
-
-    {
-       15,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-     -124,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150
-    },
-
-    {
-       15,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-     -125,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  151,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150
-    },
-
-    {
-       15,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-     -126,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  152,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-
-      150,  150,  150,  150,  150,  150,  150,  150
-    },
-
-    {
-       15,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-     -127,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  153,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150
-    },
-
-    {
-       15,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-     -128,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  154,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150
-    },
-
-    {
-       15,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-     -129,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-
-      150,  150,  155,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150
-
-    },
-
-    {
-       15,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-     -130,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  156,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  157,  150,  150,  157,  157,
-      157,  157,  157,  157,  157,  157,  157,  157,  150,  150,
-      150,  150,  150,  150,  150,  157,  157,  157,  157,  157,
-      157,  157,  157,  157,  157,  157,  157,  157,  157,  157,
-      157,  157,  157,  157,  157,  157,  157,  157,  157,  157,
-      157,  150,  150,  150,  150,  157,  150,  150,  150,  150,
-
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150
-    },
-
-    {
-       15,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-     -131,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  156,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  157,  150,  150,  157,  157,
-      157,  157,  157,  157,  157,  157,  157,  157,  150,  150,
-      150,  150,  150,  150,  150,  157,  157,  157,  157,  157,
-
-      157,  157,  157,  157,  157,  157,  157,  157,  158,  157,
-      157,  157,  157,  157,  157,  157,  157,  157,  157,  157,
-      157,  150,  150,  150,  150,  157,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150
-    },
-
-    {
-       15,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-     -132,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  156,  150,  150,  150,  150,  150,  150,  150,
-
-      150,  150,  150,  150,  150,  157,  150,  150,  157,  157,
-      157,  157,  157,  157,  157,  157,  157,  157,  150,  150,
-      150,  150,  150,  150,  150,  157,  157,  157,  157,  157,
-      157,  157,  157,  157,  157,  157,  157,  157,  159,  157,
-      157,  157,  157,  157,  157,  157,  157,  157,  157,  157,
-      157,  150,  150,  150,  150,  157,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150
-    },
-
-    {
-       15,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-
-     -133,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  160,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150
-    },
-
-    {
-       15,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-     -134,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  156,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  157,  150,  150,  157,  157,
-      157,  157,  157,  157,  157,  157,  157,  157,  150,  150,
-      150,  150,  150,  150,  150,  157,  157,  157,  157,  157,
-      157,  157,  157,  157,  157,  157,  157,  157,  157,  157,
-
-      157,  157,  161,  157,  157,  157,  157,  157,  157,  157,
-      157,  150,  150,  150,  150,  157,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,  150,  150,  150,  150
-    },
-
-    {
-       15, -135, -135, -135, -135, -135, -135, -135, -135, -135,
-     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
-     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
-     -135, -135,  135, -135, -135, -135, -135, -135, -135, -135,
-     -135, -135, -135,  136, -135,  136,  114, -135,  137,  137,
-
-      137,  137,  137,  137,  137,  137,  137,  137, -135, -135,
-     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
-     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
-     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
-     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
-     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
-     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
-     -135, -135, -135, -135, -135, -135, -135, -135
-    },
-
-    {
-       15, -136, -136, -136, -136, -136, -136, -136, -136, -136,
-     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
-
-     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
-     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
-     -136, -136, -136, -136, -136, -136,  114, -136,  137,  137,
-      137,  137,  137,  137,  137,  137,  137,  137, -136, -136,
-     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
-     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
-     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
-     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
-     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
-     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
-
-     -136, -136, -136, -136, -136, -136, -136, -136
-    },
-
-    {
-       15, -137, -137, -137, -137, -137, -137, -137, -137, -137,
-     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
-     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
-     -137, -137,  162, -137, -137, -137, -137, -137, -137, -137,
-     -137,  163, -137, -137, -137, -137,  141, -137,  164,  164,
-      164,  164,  164,  164,  164,  164,  164,  164, -137, -137,
-     -137, -137, -137, -137, -137, -137, -137, -137, -137,  143,
-     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
-     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
-
-     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
-     -137,  143, -137, -137, -137, -137, -137, -137, -137, -137,
-     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
-     -137, -137, -137, -137, -137, -137, -137, -137
-    },
-
-    {
-       15, -138, -138, -138, -138, -138, -138, -138, -138, -138,
-     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
-     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
-     -138, -138,  162, -138, -138, -138, -138, -138, -138, -138,
-     -138,  163, -138, -138, -138, -138, -138, -138,  138,  138,
-      138,  138,  138,  138,  138,  138,  138,  138, -138, -138,
-
-     -138, -138, -138, -138, -138, -138, -138, -138, -138,  143,
-     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
-     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
-     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
-     -138,  143, -138, -138, -138, -138, -138, -138, -138, -138,
-     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
-     -138, -138, -138, -138, -138, -138, -138, -138
-    },
-
-    {
-       15, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-
-     -139, -139,  139, -139, -139, -139, -139, -139, -139, -139,
-     -139,  140, -139, -139, -139, -139, -139, -139, -139, -139,
-     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-     -139, -139, -139, -139, -139, -139, -139, -139
-
-    },
-
-    {
-       15, -140, -140, -140, -140, -140, -140, -140, -140, -140,
-     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
-     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
-     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
-     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
-     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
-     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
-     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
-     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
-     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
-
-     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
-     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
-     -140, -140, -140, -140, -140, -140, -140, -140
-    },
-
-    {
-       15, -141, -141, -141, -141, -141, -141, -141, -141, -141,
-     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
-     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
-     -141, -141,  162, -141, -141, -141, -141, -141, -141, -141,
-     -141,  163, -141, -141, -141, -141, -141, -141,  165,  165,
-      165,  165,  165,  165,  165,  165,  165,  165, -141, -141,
-     -141, -141, -141, -141, -141, -141, -141, -141, -141,  143,
-
-     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
-     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
-     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
-     -141,  143, -141, -141, -141, -141, -141, -141, -141, -141,
-     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
-     -141, -141, -141, -141, -141, -141, -141, -141
-    },
-
-    {
-       15, -142, -142, -142, -142, -142, -142, -142, -142, -142,
-     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
-     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
-     -142, -142,  139, -142, -142, -142, -142, -142, -142, -142,
-
-     -142,  140, -142, -142, -142, -142,  141, -142,  142,  142,
-      142,  142,  142,  142,  142,  142,  142,  142, -142, -142,
-     -142, -142, -142, -142, -142, -142, -142, -142, -142,  143,
-     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
-     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
-     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
-     -142,  143, -142, -142, -142, -142, -142, -142, -142, -142,
-     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
-     -142, -142, -142, -142, -142, -142, -142, -142
-    },
-
-    {
-       15, -143, -143, -143, -143, -143, -143, -143, -143, -143,
-
-     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
-     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
-     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
-     -143, -143, -143,  166, -143,  166, -143, -143,  167,  167,
-      167,  167,  167,  167,  167,  167,  167,  167, -143, -143,
-     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
-     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
-     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
-     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
-     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
-
-     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
-     -143, -143, -143, -143, -143, -143, -143, -143
-    },
-
-    {
-       15, -144, -144, -144, -144, -144, -144, -144, -144, -144,
-     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
-     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
-     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
-     -144, -144, -144, -144, -144, -144,   62, -144,  168,  169,
-      169,  169,  169,  169,  169,  169,  169,  169, -144, -144,
-     -144, -144, -144, -144, -144, -144, -144, -144, -144,   65,
-     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
-
-     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
-     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
-     -144,   65, -144, -144, -144, -144, -144, -144, -144, -144,
-     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
-     -144, -144, -144, -144, -144, -144, -144, -144
-    },
-
-    {
-       15, -145, -145, -145, -145, -145, -145, -145, -145, -145,
-     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
-     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
-     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
-     -145, -145, -145, -145, -145, -145,   62, -145,  170,  170,
-
-      170,  170,  170,  170,  170,  170,  170,  170, -145, -145,
-     -145, -145, -145, -145, -145, -145, -145, -145, -145,   65,
-     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
-     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
-     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
-     -145,   65, -145, -145, -145, -145, -145, -145, -145, -145,
-     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
-     -145, -145, -145, -145, -145, -145, -145, -145
-    },
-
-    {
-       15, -146, -146, -146, -146, -146, -146, -146, -146, -146,
-     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
-
-     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
-     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
-     -146, -146, -146, -146, -146, -146,   62, -146,  171,  171,
-      171,  171,  171,  171,  171,  171,  171,  171, -146, -146,
-     -146, -146, -146, -146, -146, -146, -146, -146, -146,   65,
-     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
-     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
-     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
-     -146,   65, -146, -146, -146, -146, -146, -146, -146, -146,
-     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
-
-     -146, -146, -146, -146, -146, -146, -146, -146
-    },
-
-    {
-       15, -147, -147, -147, -147, -147, -147, -147, -147, -147,
-     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
-     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
-     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
-     -147, -147, -147, -147, -147, -147,   62, -147,  172,  172,
-      172,  172,  172,  172,  172,  172,  172,  172, -147, -147,
-     -147, -147, -147, -147, -147, -147, -147, -147, -147,   65,
-     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
-     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
-
-     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
-     -147,   65, -147, -147, -147, -147, -147, -147, -147, -147,
-     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
-     -147, -147, -147, -147, -147, -147, -147, -147
-    },
-
-    {
-       15, -148, -148, -148, -148, -148, -148, -148, -148, -148,
-     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
-     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
-     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
-     -148, -148, -148, -148, -148, -148,   62, -148,  173,  173,
-      173,  173,  173,  173,  173,  173,  173,  173, -148, -148,
-
-     -148, -148, -148, -148, -148, -148, -148, -148, -148,   65,
-     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
-     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
-     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
-     -148,   65, -148, -148, -148, -148, -148, -148, -148, -148,
-     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
-     -148, -148, -148, -148, -148, -148, -148, -148
-    },
-
-    {
-       15, -149, -149, -149, -149, -149, -149, -149, -149, -149,
-     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
-     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
-
-     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
-     -149, -149, -149, -149, -149, -149,   62, -149,  174,  174,
-      174,  174,  174,  174,  174,  174,  174,  174, -149, -149,
-     -149, -149, -149, -149, -149, -149, -149, -149, -149,   65,
-     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
-     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
-     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
-     -149,   65, -149, -149, -149, -149, -149, -149, -149, -149,
-     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
-     -149, -149, -149, -149, -149, -149, -149, -149
-
-    },
-
-    {
-       15,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-     -150,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175
-    },
-
-    {
-       15,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-     -151,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  176,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175
-    },
-
-    {
-       15,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-     -152,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  177,  175,  175,  175,  175,  175,  175,  175,
-
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175
-    },
-
-    {
-       15,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-
-     -153,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  178,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175
-    },
-
-    {
-       15,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-     -154,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  179,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175
-    },
-
-    {
-       15,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-     -155,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  180,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175
-    },
-
-    {
-       15,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-     -156,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  181,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-
-      175,  175,  175,  175,  175,  175,  175,  175
-    },
-
-    {
-       15,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-     -157,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  182,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  183,  175,  175,  183,  183,
-      183,  183,  183,  183,  183,  183,  183,  183,  175,  175,
-      175,  175,  175,  175,  175,  183,  183,  183,  183,  183,
-      183,  183,  183,  183,  183,  183,  183,  183,  183,  183,
-      183,  183,  183,  183,  183,  183,  183,  183,  183,  183,
-
-      183,  175,  175,  175,  175,  183,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175
-    },
-
-    {
-       15,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-     -158,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  182,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  183,  175,  175,  183,  183,
-      183,  183,  183,  183,  183,  183,  183,  183,  175,  175,
-
-      175,  175,  175,  175,  175,  183,  183,  183,  183,  183,
-      183,  183,  183,  183,  183,  183,  183,  183,  183,  183,
-      183,  183,  183,  183,  184,  183,  183,  183,  183,  183,
-      183,  175,  175,  175,  175,  183,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175
-    },
-
-    {
-       15,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-     -159,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-
-      175,  175,  182,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  183,  175,  175,  183,  183,
-      183,  183,  183,  183,  183,  183,  183,  183,  175,  175,
-      175,  175,  175,  175,  175,  183,  183,  183,  183,  183,
-      183,  183,  183,  183,  183,  183,  183,  183,  183,  183,
-      183,  183,  183,  183,  183,  185,  183,  183,  183,  183,
-      183,  175,  175,  175,  175,  183,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175
-
-    },
-
-    {
-       15,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-     -160,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  186,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175
-    },
-
-    {
-       15,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-     -161,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  182,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  183,  175,  175,  183,  183,
-      183,  183,  183,  183,  183,  183,  183,  183,  175,  175,
-      175,  175,  175,  175,  175,  183,  183,  183,  183,  183,
-
-      183,  183,  183,  183,  183,  183,  183,  183,  183,  183,
-      183,  183,  183,  183,  183,  183,  183,  183,  183,  184,
-      183,  175,  175,  175,  175,  183,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,  175,  175,  175,  175,  175,  175,  175
-    },
-
-    {
-       15, -162, -162, -162, -162, -162, -162, -162, -162, -162,
-     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
-     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
-     -162, -162,  162, -162, -162, -162, -162, -162, -162, -162,
-
-     -162,  163, -162, -162, -162, -162, -162, -162, -162, -162,
-     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
-     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
-     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
-     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
-     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
-     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
-     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
-     -162, -162, -162, -162, -162, -162, -162, -162
-    },
-
-    {
-       15, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-
-     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-
-     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-     -163, -163, -163, -163, -163, -163, -163, -163
-    },
-
-    {
-       15, -164, -164, -164, -164, -164, -164, -164, -164, -164,
-     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
-     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
-     -164, -164,  162, -164, -164, -164, -164, -164, -164, -164,
-     -164,  163, -164, -164, -164, -164,  141, -164,  164,  164,
-      164,  164,  164,  164,  164,  164,  164,  164, -164, -164,
-     -164, -164, -164, -164, -164, -164, -164, -164, -164,  143,
-     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
-
-     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
-     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
-     -164,  143, -164, -164, -164, -164, -164, -164, -164, -164,
-     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
-     -164, -164, -164, -164, -164, -164, -164, -164
-    },
-
-    {
-       15, -165, -165, -165, -165, -165, -165, -165, -165, -165,
-     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
-     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
-     -165, -165,  162, -165, -165, -165, -165, -165, -165, -165,
-     -165,  163, -165, -165, -165, -165, -165, -165,  165,  165,
-
-      165,  165,  165,  165,  165,  165,  165,  165, -165, -165,
-     -165, -165, -165, -165, -165, -165, -165, -165, -165,  143,
-     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
-     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
-     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
-     -165,  143, -165, -165, -165, -165, -165, -165, -165, -165,
-     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
-     -165, -165, -165, -165, -165, -165, -165, -165
-    },
-
-    {
-       15, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-
-     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-     -166, -166, -166, -166, -166, -166, -166, -166,  167,  167,
-      167,  167,  167,  167,  167,  167,  167,  167, -166, -166,
-     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-
-     -166, -166, -166, -166, -166, -166, -166, -166
-    },
-
-    {
-       15, -167, -167, -167, -167, -167, -167, -167, -167, -167,
-     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
-     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
-     -167, -167,  162, -167, -167, -167, -167, -167, -167, -167,
-     -167,  163, -167, -167, -167, -167, -167, -167,  167,  167,
-      167,  167,  167,  167,  167,  167,  167,  167, -167, -167,
-     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
-     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
-     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
-
-     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
-     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
-     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
-     -167, -167, -167, -167, -167, -167, -167, -167
-    },
-
-    {
-       15, -168, -168, -168, -168, -168, -168, -168, -168, -168,
-     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
-     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
-     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
-     -168, -168, -168, -168, -168, -168,   62, -168,  187,  188,
-      188,  188,  188,  188,  188,  188,  188,  188, -168, -168,
-
-     -168, -168, -168, -168, -168, -168, -168, -168, -168,   65,
-     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
-     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
-     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
-     -168,   65, -168, -168, -168, -168, -168, -168, -168, -168,
-     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
-     -168, -168, -168, -168, -168, -168, -168, -168
-    },
-
-    {
-       15, -169, -169, -169, -169, -169, -169, -169, -169, -169,
-     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
-     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
-
-     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
-     -169, -169, -169, -169, -169, -169,   62, -169,  189,  189,
-      189,  189,  189,  189,  189,  189,  189,  189, -169, -169,
-     -169, -169, -169, -169, -169, -169, -169, -169, -169,   65,
-     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
-     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
-     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
-     -169,   65, -169, -169, -169, -169, -169, -169, -169, -169,
-     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
-     -169, -169, -169, -169, -169, -169, -169, -169
-
-    },
-
-    {
-       15, -170, -170, -170, -170, -170, -170, -170, -170, -170,
-     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
-     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
-     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
-     -170, -170, -170, -170, -170, -170,   62, -170,  190,  190,
-      190,  190,  190,  190,  190,  190,  190,  190, -170, -170,
-     -170, -170, -170, -170, -170, -170, -170, -170, -170,   65,
-     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
-     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
-     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
-
-     -170,   65, -170, -170, -170, -170, -170, -170, -170, -170,
-     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
-     -170, -170, -170, -170, -170, -170, -170, -170
-    },
-
-    {
-       15, -171, -171, -171, -171, -171, -171, -171, -171, -171,
-     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
-     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
-     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
-     -171, -171, -171, -171, -171, -171,   62, -171,  191,  191,
-      191,  191,  191,  191,  191,  191,  191,  191, -171, -171,
-     -171, -171, -171, -171, -171, -171, -171, -171, -171,   65,
-
-     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
-     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
-     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
-     -171,   65, -171, -171, -171, -171, -171, -171, -171, -171,
-     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
-     -171, -171, -171, -171, -171, -171, -171, -171
-    },
-
-    {
-       15, -172, -172, -172, -172, -172, -172, -172, -172, -172,
-     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
-     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
-     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
-
-     -172, -172, -172, -172, -172, -172,   62, -172,  192,  192,
-      192,  192,  192,  192,  192,  192,  192,  192, -172, -172,
-     -172, -172, -172, -172, -172, -172, -172, -172, -172,   65,
-     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
-     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
-     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
-     -172,   65, -172, -172, -172, -172, -172, -172, -172, -172,
-     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
-     -172, -172, -172, -172, -172, -172, -172, -172
-    },
-
-    {
-       15, -173, -173, -173, -173, -173, -173, -173, -173, -173,
-
-     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
-     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
-     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
-     -173, -173, -173, -173, -173, -173,   62, -173,  193,  193,
-      193,  193,  193,  193,  193,  193,  193,  193, -173, -173,
-     -173, -173, -173, -173, -173, -173, -173, -173, -173,   65,
-     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
-     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
-     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
-     -173,   65, -173, -173, -173, -173, -173, -173, -173, -173,
-
-     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
-     -173, -173, -173, -173, -173, -173, -173, -173
-    },
-
-    {
-       15, -174, -174, -174, -174, -174, -174, -174, -174, -174,
-     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
-     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
-     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
-     -174, -174, -174, -174, -174, -174,   62, -174,  194,  194,
-      194,  194,  194,  194,  194,  194,  194,  194, -174, -174,
-     -174, -174, -174, -174, -174, -174, -174, -174, -174,   65,
-     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
-
-     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
-     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
-     -174,   65, -174, -174, -174, -174, -174, -174, -174, -174,
-     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
-     -174, -174, -174, -174, -174, -174, -174, -174
-    },
-
-    {
-       15,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-     -175,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195
-    },
-
-    {
-       15,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-     -176,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  196,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-
-      195,  195,  195,  195,  195,  195,  195,  195
-    },
-
-    {
-       15,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-     -177,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  197,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195
-    },
-
-    {
-       15,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-     -178,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  197,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195
-    },
-
-    {
-       15,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-     -179,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-
-      195,  195,  197,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195
-
-    },
-
-    {
-       15,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-     -180,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  197,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195
-    },
-
-    {
-       15,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-     -181,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  197,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195
-    },
-
-    {
-       15,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-     -182,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  197,  195,  195,  195,  195,  195,  195,  195,
-
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195
-    },
-
-    {
-       15,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-
-     -183,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  198,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  197,  195,  195,  197,  197,
-      197,  197,  197,  197,  197,  197,  197,  197,  195,  195,
-      195,  195,  195,  195,  195,  197,  197,  197,  197,  197,
-      197,  197,  197,  197,  197,  197,  197,  197,  197,  197,
-      197,  197,  197,  197,  197,  197,  197,  197,  197,  197,
-      197,  195,  195,  195,  195,  197,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195
-    },
-
-    {
-       15,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-     -184,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  198,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  197,  195,  195,  197,  197,
-      197,  197,  197,  197,  197,  197,  197,  197,  195,  195,
-      195,  195,  195,  195,  195,  197,  197,  197,  197,  197,
-      197,  197,  197,  197,  197,  197,  197,  197,  197,  197,
-
-      197,  197,  197,  197,  197,  197,  197,  197,  197,  197,
-      197,  195,  195,  195,  195,  197,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195
-    },
-
-    {
-       15,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-     -185,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  198,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  197,  195,  195,  197,  197,
-
-      197,  197,  197,  197,  197,  197,  197,  197,  195,  195,
-      195,  195,  195,  195,  195,  197,  197,  197,  197,  199,
-      197,  197,  197,  197,  197,  197,  197,  197,  197,  197,
-      197,  197,  197,  197,  197,  197,  197,  197,  197,  197,
-      197,  195,  195,  195,  195,  197,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195
-    },
-
-    {
-       15,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-     -186,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  200,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
-
-      195,  195,  195,  195,  195,  195,  195,  195
-    },
-
-    {
-       15, -187, -187, -187, -187, -187, -187, -187, -187, -187,
-     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
-     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
-     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
-     -187, -187, -187, -187, -187, -187,   62, -187,  201,  202,
-      202,  202,  202,  202,  202,  202,  202,  202, -187, -187,
-     -187, -187, -187, -187, -187, -187, -187, -187, -187,   65,
-     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
-     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
-
-     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
-     -187,   65, -187, -187, -187, -187, -187, -187, -187, -187,
-     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
-     -187, -187, -187, -187, -187, -187, -187, -187
-    },
-
-    {
-       15, -188, -188, -188, -188, -188, -188, -188, -188, -188,
-     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
-     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
-     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
-     -188, -188, -188, -188, -188, -188,   62, -188,  203,  203,
-      203,  203,  203,  203,  203,  203,  203,  203, -188, -188,
-
-     -188, -188, -188, -188, -188, -188, -188, -188, -188,   65,
-     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
-     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
-     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
-     -188,   65, -188, -188, -188, -188, -188, -188, -188, -188,
-     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
-     -188, -188, -188, -188, -188, -188, -188, -188
-    },
-
-    {
-       15, -189, -189, -189, -189, -189, -189, -189, -189, -189,
-     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
-     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
-
-     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
-     -189, -189, -189, -189, -189, -189,   62, -189,  204,  204,
-      204,  204,  204,  204,  204,  204,  204,  204, -189, -189,
-     -189, -189, -189, -189, -189, -189, -189, -189, -189,   65,
-     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
-     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
-     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
-     -189,   65, -189, -189, -189, -189, -189, -189, -189, -189,
-     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
-     -189, -189, -189, -189, -189, -189, -189, -189
-
-    },
-
-    {
-       15, -190, -190, -190, -190, -190, -190, -190, -190, -190,
-     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
-     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
-     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
-     -190, -190, -190, -190, -190, -190,   62, -190,  205,  205,
-      205,  205,  205,  205,  205,  205,  205,  205, -190, -190,
-     -190, -190, -190, -190, -190, -190, -190, -190, -190,   65,
-     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
-     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
-     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
-
-     -190,   65, -190, -190, -190, -190, -190, -190, -190, -190,
-     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
-     -190, -190, -190, -190, -190, -190, -190, -190
-    },
-
-    {
-       15, -191, -191, -191, -191, -191, -191, -191, -191, -191,
-     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
-     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
-     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
-     -191, -191, -191, -191, -191, -191,   62, -191,  206,  206,
-      206,  206,  206,  206,  206,  206,  206,  206, -191, -191,
-     -191, -191, -191, -191, -191, -191, -191, -191, -191,   65,
-
-     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
-     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
-     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
-     -191,   65, -191, -191, -191, -191, -191, -191, -191, -191,
-     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
-     -191, -191, -191, -191, -191, -191, -191, -191
-    },
-
-    {
-       15, -192, -192, -192, -192, -192, -192, -192, -192, -192,
-     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
-     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
-     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
-
-     -192, -192, -192, -192, -192, -192,   62, -192,  207,  207,
-      207,  207,  207,  207,  207,  207,  207,  207, -192, -192,
-     -192, -192, -192, -192, -192, -192, -192, -192, -192,   65,
-     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
-     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
-     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
-     -192,   65, -192, -192, -192, -192, -192, -192, -192, -192,
-     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
-     -192, -192, -192, -192, -192, -192, -192, -192
-    },
-
-    {
-       15, -193, -193, -193, -193, -193, -193, -193, -193, -193,
-
-     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
-     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
-     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
-     -193, -193, -193, -193, -193, -193,   62, -193,  208,  208,
-      208,  208,  208,  208,  208,  208,  208,  208, -193, -193,
-     -193, -193, -193, -193, -193, -193, -193, -193, -193,   65,
-     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
-     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
-     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
-     -193,   65, -193, -193, -193, -193, -193, -193, -193, -193,
-
-     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
-     -193, -193, -193, -193, -193, -193, -193, -193
-    },
-
-    {
-       15, -194, -194, -194, -194, -194, -194, -194, -194, -194,
-     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
-     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
-     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
-     -194, -194, -194, -194, -194, -194,   62, -194,  209,  209,
-      209,  209,  209,  209,  209,  209,  209,  209, -194, -194,
-     -194, -194, -194, -194, -194, -194, -194, -194, -194,   65,
-     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
-
-     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
-     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
-     -194,   65, -194, -194, -194, -194, -194, -194, -194, -194,
-     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
-     -194, -194, -194, -194, -194, -194, -194, -194
-    },
-
-    {
-       15, -195, -195, -195, -195, -195, -195, -195, -195, -195,
-     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
-     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
-     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
-     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
-
-     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
-     -195,  210, -195, -195, -195, -195, -195, -195, -195, -195,
-     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
-     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
-     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
-     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
-     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
-     -195, -195, -195, -195, -195, -195, -195, -195
-    },
-
-    {
-       15, -196, -196, -196, -196, -196, -196, -196, -196, -196,
-     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
-
-     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
-     -196, -196,  211, -196, -196, -196, -196, -196, -196, -196,
-     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
-     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
-     -196,  210, -196, -196, -196, -196, -196, -196, -196, -196,
-     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
-     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
-     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
-     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
-     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
-
-     -196, -196, -196, -196, -196, -196, -196, -196
-    },
-
-    {
-       15, -197, -197, -197, -197, -197, -197, -197, -197, -197,
-     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
-     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
-     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
-     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
-     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
-     -197,  212, -197, -197, -197, -197, -197, -197, -197, -197,
-     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
-     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
-
-     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
-     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
-     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
-     -197, -197, -197, -197, -197, -197, -197, -197
-    },
-
-    {
-       15, -198, -198, -198, -198, -198, -198, -198, -198, -198,
-     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
-     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
-     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
-     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
-     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
-
-     -198,  212, -198, -198, -198, -198, -198, -198, -198, -198,
-     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
-     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
-     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
-     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
-     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
-     -198, -198, -198, -198, -198, -198, -198, -198
-    },
-
-    {
-       15, -199, -199, -199, -199, -199, -199, -199, -199, -199,
-     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
-     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
-
-     -199, -199,  213, -199, -199, -199, -199, -199, -199, -199,
-     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
-     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
-     -199,  212, -199, -199, -199, -199, -199, -199, -199, -199,
-     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
-     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
-     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
-     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
-     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
-     -199, -199, -199, -199, -199, -199, -199, -199
-
-    },
-
-    {
-       15, -200, -200, -200, -200, -200, -200, -200, -200, -200,
-     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
-     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
-     -200, -200,  214, -200, -200, -200, -200, -200, -200, -200,
-     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
-     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
-     -200,  215, -200, -200, -200, -200, -200, -200, -200, -200,
-     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
-     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
-     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
-
-     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
-     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
-     -200, -200, -200, -200, -200, -200, -200, -200
-    },
-
-    {
-       15, -201, -201, -201, -201, -201, -201, -201, -201, -201,
-     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
-     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
-     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
-     -201, -201, -201, -201, -201, -201,   62, -201,  216,  217,
-      217,  217,  217,  217,  217,  217,  217,  217, -201, -201,
-     -201, -201, -201, -201, -201, -201, -201, -201, -201,   65,
-
-     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
-     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
-     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
-     -201,   65, -201, -201, -201, -201, -201, -201, -201, -201,
-     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
-     -201, -201, -201, -201, -201, -201, -201, -201
-    },
-
-    {
-       15, -202, -202, -202, -202, -202, -202, -202, -202, -202,
-     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
-     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
-     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
-
-     -202, -202, -202, -202, -202, -202,   62, -202,  218,  218,
-      218,  218,  218,  218,  218,  218,  218,  218, -202, -202,
-     -202, -202, -202, -202, -202, -202, -202, -202, -202,   65,
-     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
-     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
-     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
-     -202,   65, -202, -202, -202, -202, -202, -202, -202, -202,
-     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
-     -202, -202, -202, -202, -202, -202, -202, -202
-    },
-
-    {
-       15, -203, -203, -203, -203, -203, -203, -203, -203, -203,
-
-     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
-     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
-     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
-     -203, -203, -203, -203, -203, -203,   62, -203,  219,  219,
-      219,  219,  219,  219,  219,  219,  219,  219, -203, -203,
-     -203, -203, -203, -203, -203, -203, -203, -203, -203,   65,
-     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
-     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
-     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
-     -203,   65, -203, -203, -203, -203, -203, -203, -203, -203,
-
-     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
-     -203, -203, -203, -203, -203, -203, -203, -203
-    },
-
-    {
-       15, -204, -204, -204, -204, -204, -204, -204, -204, -204,
-     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
-     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
-     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
-     -204, -204, -204, -204, -204, -204,   62, -204,  220,  220,
-      220,  220,  220,  220,  220,  220,  220,  220, -204, -204,
-     -204, -204, -204, -204, -204, -204, -204, -204, -204,   65,
-     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
-
-     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
-     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
-     -204,   65, -204, -204, -204, -204, -204, -204, -204, -204,
-     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
-     -204, -204, -204, -204, -204, -204, -204, -204
-    },
-
-    {
-       15, -205, -205, -205, -205, -205, -205, -205, -205, -205,
-     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
-     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
-     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
-     -205, -205, -205, -205, -205, -205,   62, -205,  221,  221,
-
-      221,  221,  221,  221,  221,  221,  221,  221, -205, -205,
-     -205, -205, -205, -205, -205, -205, -205, -205, -205,   65,
-     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
-     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
-     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
-     -205,   65, -205, -205, -205, -205, -205, -205, -205, -205,
-     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
-     -205, -205, -205, -205, -205, -205, -205, -205
-    },
-
-    {
-       15, -206, -206, -206, -206, -206, -206, -206, -206, -206,
-     -206, -206, -206, -206, -206, -206, -206, -206, -206, -206,
-
-     -206, -206, -206, -206, -206, -206, -206, -206, -206, -206,
-     -206, -206, -206, -206, -206, -206, -206, -206, -206, -206,
-     -206, -206, -206, -206, -206, -206,   62, -206,  222,  222,
-      222,  222,  222,  222,  222,  222,  222,  222, -206, -206,
-     -206, -206, -206, -206, -206, -206, -206, -206, -206,   65,
-     -206, -206, -206, -206, -206, -206, -206, -206, -206, -206,
-     -206, -206, -206, -206, -206, -206, -206, -206, -206, -206,
-     -206, -206, -206, -206, -206, -206, -206, -206, -206, -206,
-     -206,   65, -206, -206, -206, -206, -206, -206, -206, -206,
-     -206, -206, -206, -206, -206, -206, -206, -206, -206, -206,
-
-     -206, -206, -206, -206, -206, -206, -206, -206
-    },
-
-    {
-       15, -207, -207, -207, -207, -207, -207, -207, -207, -207,
-     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
-     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
-     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
-     -207, -207, -207, -207, -207, -207,   62, -207,  223,  223,
-      223,  223,  223,  223,  223,  223,  223,  223, -207, -207,
-     -207, -207, -207, -207, -207, -207, -207, -207, -207,   65,
-     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
-     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
-
-     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
-     -207,   65, -207, -207, -207, -207, -207, -207, -207, -207,
-     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
-     -207, -207, -207, -207, -207, -207, -207, -207
-    },
-
-    {
-       15, -208, -208, -208, -208, -208, -208, -208, -208, -208,
-     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
-     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
-     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
-     -208, -208, -208, -208, -208, -208,   62, -208,  224,  224,
-      224,  224,  224,  224,  224,  224,  224,  224, -208, -208,
-
-     -208, -208, -208, -208, -208, -208, -208, -208, -208,   65,
-     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
-     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
-     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
-     -208,   65, -208, -208, -208, -208, -208, -208, -208, -208,
-     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
-     -208, -208, -208, -208, -208, -208, -208, -208
-    },
-
-    {
-       15, -209, -209, -209, -209, -209, -209, -209, -209, -209,
-     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
-     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
-
-     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
-     -209, -209, -209, -209, -209, -209,   62, -209,  225,  225,
-      225,  225,  225,  225,  225,  225,  225,  225, -209, -209,
-     -209, -209, -209, -209, -209, -209, -209, -209, -209,   65,
-     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
-     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
-     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
-     -209,   65, -209, -209, -209, -209, -209, -209, -209, -209,
-     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
-     -209, -209, -209, -209, -209, -209, -209, -209
-
-    },
-
-    {
-       15, -210, -210, -210, -210, -210, -210, -210, -210, -210,
-     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
-     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
-     -210, -210,  226, -210, -210, -210, -210, -210, -210, -210,
-     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
-     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
-     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
-     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
-     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
-     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
-
-     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
-     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
-     -210, -210, -210, -210, -210, -210, -210, -210
-    },
-
-    {
-       15, -211, -211, -211, -211, -211, -211, -211, -211, -211,
-     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
-     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
-     -211, -211,  227, -211, -211, -211, -211, -211, -211, -211,
-     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
-     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
-     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
-
-     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
-     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
-     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
-     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
-     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
-     -211, -211, -211, -211, -211, -211, -211, -211
-    },
-
-    {
-       15, -212, -212, -212, -212, -212, -212, -212, -212, -212,
-     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
-     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
-     -212, -212,  228, -212, -212, -212, -212, -212, -212, -212,
-
-     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
-     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
-     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
-     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
-     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
-     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
-     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
-     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
-     -212, -212, -212, -212, -212, -212, -212, -212
-    },
-
-    {
-       15, -213, -213, -213, -213, -213, -213, -213, -213, -213,
-
-     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
-     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
-     -213, -213,  229, -213, -213, -213, -213, -213, -213, -213,
-     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
-     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
-     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
-     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
-     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
-     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
-     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
-
-     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
-     -213, -213, -213, -213, -213, -213, -213, -213
-    },
-
-    {
-       15, -214, -214, -214, -214, -214, -214, -214, -214, -214,
-     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
-     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
-     -214, -214,  230, -214, -214, -214, -214, -214, -214, -214,
-     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
-     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
-     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
-     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
-
-     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
-     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
-     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
-     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
-     -214, -214, -214, -214, -214, -214, -214, -214
-    },
-
-    {
-       15, -215, -215, -215, -215, -215, -215, -215, -215, -215,
-     -215, -215, -215, -215, -215, -215, -215, -215, -215, -215,
-     -215, -215, -215, -215, -215, -215, -215, -215, -215, -215,
-     -215, -215,  231, -215, -215, -215, -215, -215, -215, -215,
-     -215, -215, -215, -215, -215, -215, -215, -215, -215, -215,
-
-     -215, -215, -215, -215, -215, -215, -215, -215, -215, -215,
-     -215, -215, -215, -215, -215, -215, -215, -215, -215, -215,
-     -215, -215, -215, -215, -215, -215, -215, -215, -215, -215,
-     -215, -215, -215, -215, -215, -215, -215, -215, -215, -215,
-     -215, -215, -215, -215, -215, -215, -215, -215, -215, -215,
-     -215, -215, -215, -215, -215, -215, -215, -215, -215, -215,
-     -215, -215, -215, -215, -215, -215, -215, -215, -215, -215,
-     -215, -215, -215, -215, -215, -215, -215, -215
-    },
-
-    {
-       15, -216, -216, -216, -216, -216, -216, -216, -216, -216,
-     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
-
-     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
-     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
-     -216, -216, -216, -216, -216, -216,   62, -216,  232,  233,
-      233,  233,  233,  233,  233,  233,  233,  233, -216, -216,
-     -216, -216, -216, -216, -216, -216, -216, -216, -216,   65,
-     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
-     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
-     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
-     -216,   65, -216, -216, -216, -216, -216, -216, -216, -216,
-     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
-
-     -216, -216, -216, -216, -216, -216, -216, -216
-    },
-
-    {
-       15, -217, -217, -217, -217, -217, -217, -217, -217, -217,
-     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
-     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
-     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
-     -217, -217, -217, -217, -217, -217,   62, -217,  234,  234,
-      234,  234,  234,  234,  234,  234,  234,  234, -217, -217,
-     -217, -217, -217, -217, -217, -217, -217, -217, -217,   65,
-     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
-     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
-
-     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
-     -217,   65, -217, -217, -217, -217, -217, -217, -217, -217,
-     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
-     -217, -217, -217, -217, -217, -217, -217, -217
-    },
-
-    {
-       15, -218, -218, -218, -218, -218, -218, -218, -218, -218,
-     -218, -218, -218, -218, -218, -218, -218, -218, -218, -218,
-     -218, -218, -218, -218, -218, -218, -218, -218, -218, -218,
-     -218, -218, -218, -218, -218, -218, -218, -218, -218, -218,
-     -218, -218, -218, -218, -218, -218,   62, -218,  235,  235,
-      235,  235,  235,  235,  235,  235,  235,  235, -218, -218,
-
-     -218, -218, -218, -218, -218, -218, -218, -218, -218,   65,
-     -218, -218, -218, -218, -218, -218, -218, -218, -218, -218,
-     -218, -218, -218, -218, -218, -218, -218, -218, -218, -218,
-     -218, -218, -218, -218, -218, -218, -218, -218, -218, -218,
-     -218,   65, -218, -218, -218, -218, -218, -218, -218, -218,
-     -218, -218, -218, -218, -218, -218, -218, -218, -218, -218,
-     -218, -218, -218, -218, -218, -218, -218, -218
-    },
-
-    {
-       15, -219, -219, -219, -219, -219, -219, -219, -219, -219,
-     -219, -219, -219, -219, -219, -219, -219, -219, -219, -219,
-     -219, -219, -219, -219, -219, -219, -219, -219, -219, -219,
-
-     -219, -219, -219, -219, -219, -219, -219, -219, -219, -219,
-     -219, -219, -219, -219, -219, -219,   62, -219,  236,  236,
-      236,  236,  236,  236,  236,  236,  236,  236, -219, -219,
-     -219, -219, -219, -219, -219, -219, -219, -219, -219,   65,
-     -219, -219, -219, -219, -219, -219, -219, -219, -219, -219,
-     -219, -219, -219, -219, -219, -219, -219, -219, -219, -219,
-     -219, -219, -219, -219, -219, -219, -219, -219, -219, -219,
-     -219,   65, -219, -219, -219, -219, -219, -219, -219, -219,
-     -219, -219, -219, -219, -219, -219, -219, -219, -219, -219,
-     -219, -219, -219, -219, -219, -219, -219, -219
-
-    },
-
-    {
-       15, -220, -220, -220, -220, -220, -220, -220, -220, -220,
-     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
-     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
-     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
-     -220, -220, -220, -220, -220, -220,   62, -220,  237,  237,
-      237,  237,  237,  237,  237,  237,  237,  237, -220, -220,
-     -220, -220, -220, -220, -220, -220, -220, -220, -220,   65,
-     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
-     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
-     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
-
-     -220,   65, -220, -220, -220, -220, -220, -220, -220, -220,
-     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
-     -220, -220, -220, -220, -220, -220, -220, -220
-    },
-
-    {
-       15, -221, -221, -221, -221, -221, -221, -221, -221, -221,
-     -221, -221, -221, -221, -221, -221, -221, -221, -221, -221,
-     -221, -221, -221, -221, -221, -221, -221, -221, -221, -221,
-     -221, -221, -221, -221, -221, -221, -221, -221, -221, -221,
-     -221, -221, -221, -221, -221, -221,   62, -221,  238,  238,
-      238,  238,  238,  238,  238,  238,  238,  238, -221, -221,
-     -221, -221, -221, -221, -221, -221, -221, -221, -221,   65,
-
-     -221, -221, -221, -221, -221, -221, -221, -221, -221, -221,
-     -221, -221, -221, -221, -221, -221, -221, -221, -221, -221,
-     -221, -221, -221, -221, -221, -221, -221, -221, -221, -221,
-     -221,   65, -221, -221, -221, -221, -221, -221, -221, -221,
-     -221, -221, -221, -221, -221, -221, -221, -221, -221, -221,
-     -221, -221, -221, -221, -221, -221, -221, -221
-    },
-
-    {
-       15, -222, -222, -222, -222, -222, -222, -222, -222, -222,
-     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
-     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
-     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
-
-     -222, -222, -222, -222, -222, -222,   62, -222,  239,  239,
-      239,  239,  239,  239,  239,  239,  239,  239, -222, -222,
-     -222, -222, -222, -222, -222, -222, -222, -222, -222,   65,
-     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
-     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
-     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
-     -222,   65, -222, -222, -222, -222, -222, -222, -222, -222,
-     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
-     -222, -222, -222, -222, -222, -222, -222, -222
-    },
-
-    {
-       15, -223, -223, -223, -223, -223, -223, -223, -223, -223,
-
-     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
-     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
-     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
-     -223, -223, -223, -223, -223, -223,   62, -223,  240,  240,
-      240,  240,  240,  240,  240,  240,  240,  240, -223, -223,
-     -223, -223, -223, -223, -223, -223, -223, -223, -223,   65,
-     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
-     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
-     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
-     -223,   65, -223, -223, -223, -223, -223, -223, -223, -223,
-
-     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
-     -223, -223, -223, -223, -223, -223, -223, -223
-    },
-
-    {
-       15, -224, -224, -224, -224, -224, -224, -224, -224, -224,
-     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
-     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
-     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
-     -224, -224, -224, -224, -224, -224,   62, -224,  241,  241,
-      241,  241,  241,  241,  241,  241,  241,  241, -224, -224,
-     -224, -224, -224, -224, -224, -224, -224, -224, -224,   65,
-     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
-
-     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
-     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
-     -224,   65, -224, -224, -224, -224, -224, -224, -224, -224,
-     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
-     -224, -224, -224, -224, -224, -224, -224, -224
-    },
-
-    {
-       15, -225, -225, -225, -225, -225, -225, -225, -225, -225,
-     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
-     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
-     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
-     -225, -225, -225, -225, -225, -225,   62, -225,  242,  242,
-
-      242,  242,  242,  242,  242,  242,  242,  242, -225, -225,
-     -225, -225, -225, -225, -225, -225, -225, -225, -225,   65,
-     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
-     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
-     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
-     -225,   65, -225, -225, -225, -225, -225, -225, -225, -225,
-     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
-     -225, -225, -225, -225, -225, -225, -225, -225
-    },
-
-    {
-       15, -226, -226, -226, -226, -226, -226, -226, -226, -226,
-     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
-
-     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
-     -226, -226,  226, -226, -226, -226, -226, -226, -226, -226,
-     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
-     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
-     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
-     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
-     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
-     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
-     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
-     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
-
-     -226, -226, -226, -226, -226, -226, -226, -226
-    },
-
-    {
-       15, -227, -227, -227, -227, -227, -227, -227, -227, -227,
-     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
-     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
-     -227, -227,  243, -227, -227, -227, -227, -227, -227, -227,
-     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
-     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
-     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
-     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
-     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
-
-     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
-     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
-     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
-     -227, -227, -227, -227, -227, -227, -227, -227
-    },
-
-    {
-       15, -228, -228, -228, -228, -228, -228, -228, -228, -228,
-     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
-     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
-     -228, -228,  228, -228, -228, -228, -228, -228, -228, -228,
-     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
-     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
-
-     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
-     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
-     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
-     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
-     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
-     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
-     -228, -228, -228, -228, -228, -228, -228, -228
-    },
-
-    {
-       15, -229, -229, -229, -229, -229, -229, -229, -229, -229,
-     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
-     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
-
-     -229, -229,  213, -229, -229, -229, -229, -229, -229,  244,
-     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
-     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
-     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
-     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
-     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
-     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
-     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
-     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
-     -229, -229, -229, -229, -229, -229, -229, -229
-
-    },
-
-    {
-       15, -230, -230, -230, -230, -230, -230, -230, -230, -230,
-     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
-     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
-     -230, -230,  245, -230, -230, -230, -230, -230, -230, -230,
-     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
-     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
-     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
-     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
-     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
-     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
-
-     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
-     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
-     -230, -230, -230, -230, -230, -230, -230, -230
-    },
-
-    {
-       15, -231, -231, -231, -231, -231, -231, -231, -231, -231,
-     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
-     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
-     -231, -231,  231, -231, -231, -231, -231, -231, -231, -231,
-     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
-     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
-     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
-
-     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
-     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
-     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
-     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
-     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
-     -231, -231, -231, -231, -231, -231, -231, -231
-    },
-
-    {
-       15, -232, -232, -232, -232, -232, -232, -232, -232, -232,
-     -232, -232, -232, -232, -232, -232, -232, -232, -232, -232,
-     -232, -232, -232, -232, -232, -232, -232, -232, -232, -232,
-     -232, -232, -232, -232, -232, -232, -232, -232, -232, -232,
-
-     -232, -232, -232, -232, -232, -232,   62, -232,  246,  247,
-      247,  247,  247,  247,  247,  247,  247,  247, -232, -232,
-     -232, -232, -232, -232, -232, -232, -232, -232, -232,   65,
-     -232, -232, -232, -232, -232, -232, -232, -232, -232, -232,
-     -232, -232, -232, -232, -232, -232, -232, -232, -232, -232,
-     -232, -232, -232, -232, -232, -232, -232, -232, -232, -232,
-     -232,   65, -232, -232, -232, -232, -232, -232, -232, -232,
-     -232, -232, -232, -232, -232, -232, -232, -232, -232, -232,
-     -232, -232, -232, -232, -232, -232, -232, -232
-    },
-
-    {
-       15, -233, -233, -233, -233, -233, -233, -233, -233, -233,
-
-     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
-     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
-     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
-     -233, -233, -233, -233, -233, -233,   62, -233,  248,  248,
-      248,  248,  248,  248,  248,  248,  248,  248, -233, -233,
-     -233, -233, -233, -233, -233, -233, -233, -233, -233,   65,
-     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
-     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
-     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
-     -233,   65, -233, -233, -233, -233, -233, -233, -233, -233,
-
-     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
-     -233, -233, -233, -233, -233, -233, -233, -233
-    },
-
-    {
-       15, -234, -234, -234, -234, -234, -234, -234, -234, -234,
-     -234, -234, -234, -234, -234, -234, -234, -234, -234, -234,
-     -234, -234, -234, -234, -234, -234, -234, -234, -234, -234,
-     -234, -234, -234, -234, -234, -234, -234, -234, -234, -234,
-     -234, -234, -234, -234, -234, -234,   62, -234,  249,  249,
-      249,  249,  249,  249,  249,  249,  249,  249, -234, -234,
-     -234, -234, -234, -234, -234, -234, -234, -234, -234,   65,
-     -234, -234, -234, -234, -234, -234, -234, -234, -234, -234,
-
-     -234, -234, -234, -234, -234, -234, -234, -234, -234, -234,
-     -234, -234, -234, -234, -234, -234, -234, -234, -234, -234,
-     -234,   65, -234, -234, -234, -234, -234, -234, -234, -234,
-     -234, -234, -234, -234, -234, -234, -234, -234, -234, -234,
-     -234, -234, -234, -234, -234, -234, -234, -234
-    },
-
-    {
-       15, -235, -235, -235, -235, -235, -235, -235, -235, -235,
-     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
-     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
-     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
-     -235, -235, -235, -235, -235, -235,   62, -235,  250,  250,
-
-      250,  250,  250,  250,  250,  250,  250,  250, -235, -235,
-     -235, -235, -235, -235, -235, -235, -235, -235, -235,   65,
-     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
-     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
-     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
-     -235,   65, -235, -235, -235, -235, -235, -235, -235, -235,
-     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
-     -235, -235, -235, -235, -235, -235, -235, -235
-    },
-
-    {
-       15, -236, -236, -236, -236, -236, -236, -236, -236, -236,
-     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
-
-     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
-     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
-     -236, -236, -236, -236, -236, -236,   62, -236,  251,  251,
-      251,  251,  251,  251,  251,  251,  251,  251, -236, -236,
-     -236, -236, -236, -236, -236, -236, -236, -236, -236,   65,
-     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
-     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
-     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
-     -236,   65, -236, -236, -236, -236, -236, -236, -236, -236,
-     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
-
-     -236, -236, -236, -236, -236, -236, -236, -236
-    },
-
-    {
-       15, -237, -237, -237, -237, -237, -237, -237, -237, -237,
-     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
-     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
-     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
-     -237, -237, -237, -237, -237, -237,   62, -237,  252,  252,
-      252,  252,  252,  252,  252,  252,  252,  252, -237, -237,
-     -237, -237, -237, -237, -237, -237, -237, -237, -237,   65,
-     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
-     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
-
-     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
-     -237,   65, -237, -237, -237, -237, -237, -237, -237, -237,
-     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
-     -237, -237, -237, -237, -237, -237, -237, -237
-    },
-
-    {
-       15, -238, -238, -238, -238, -238, -238, -238, -238, -238,
-     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
-     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
-     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
-     -238, -238, -238, -238, -238, -238,   62, -238,  253,  253,
-      253,  253,  253,  253,  253,  253,  253,  253, -238, -238,
-
-     -238, -238, -238, -238, -238, -238, -238, -238, -238,   65,
-     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
-     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
-     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
-     -238,   65, -238, -238, -238, -238, -238, -238, -238, -238,
-     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
-     -238, -238, -238, -238, -238, -238, -238, -238
-    },
-
-    {
-       15, -239, -239, -239, -239, -239, -239, -239, -239, -239,
-     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
-     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
-
-     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
-     -239, -239, -239, -239, -239, -239,   62, -239,  254,  254,
-      254,  254,  254,  254,  254,  254,  254,  254, -239, -239,
-     -239, -239, -239, -239, -239, -239, -239, -239, -239,   65,
-     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
-     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
-     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
-     -239,   65, -239, -239, -239, -239, -239, -239, -239, -239,
-     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
-     -239, -239, -239, -239, -239, -239, -239, -239
-
-    },
-
-    {
-       15, -240, -240, -240, -240, -240, -240, -240, -240, -240,
-     -240, -240, -240, -240, -240, -240, -240, -240, -240, -240,
-     -240, -240, -240, -240, -240, -240, -240, -240, -240, -240,
-     -240, -240, -240, -240, -240, -240, -240, -240, -240, -240,
-     -240, -240, -240, -240, -240, -240,   62, -240,  255,  255,
-      255,  255,  255,  255,  255,  255,  255,  255, -240, -240,
-     -240, -240, -240, -240, -240, -240, -240, -240, -240,   65,
-     -240, -240, -240, -240, -240, -240, -240, -240, -240, -240,
-     -240, -240, -240, -240, -240, -240, -240, -240, -240, -240,
-     -240, -240, -240, -240, -240, -240, -240, -240, -240, -240,
-
-     -240,   65, -240, -240, -240, -240, -240, -240, -240, -240,
-     -240, -240, -240, -240, -240, -240, -240, -240, -240, -240,
-     -240, -240, -240, -240, -240, -240, -240, -240
-    },
-
-    {
-       15, -241, -241, -241, -241, -241, -241, -241, -241, -241,
-     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
-     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
-     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
-     -241, -241, -241, -241, -241, -241,   62, -241,  256,  256,
-      256,  256,  256,  256,  256,  256,  256,  256, -241, -241,
-     -241, -241, -241, -241, -241, -241, -241, -241, -241,   65,
-
-     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
-     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
-     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
-     -241,   65, -241, -241, -241, -241, -241, -241, -241, -241,
-     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
-     -241, -241, -241, -241, -241, -241, -241, -241
-    },
-
-    {
-       15, -242, -242, -242, -242, -242, -242, -242, -242, -242,
-     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
-     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
-     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
-
-     -242, -242, -242, -242, -242, -242,   62, -242,  257,  257,
-      257,  257,  257,  257,  257,  257,  257,  257, -242, -242,
-     -242, -242, -242, -242, -242, -242, -242, -242, -242,   65,
-     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
-     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
-     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
-     -242,   65, -242, -242, -242, -242, -242, -242, -242, -242,
-     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
-     -242, -242, -242, -242, -242, -242, -242, -242
-    },
-
-    {
-       15, -243, -243, -243, -243, -243, -243, -243, -243, -243,
-
-     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
-     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
-     -243, -243,  258, -243, -243, -243, -243, -243, -243, -243,
-     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
-     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
-     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
-     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
-     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
-     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
-     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
-
-     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
-     -243, -243, -243, -243, -243, -243, -243, -243
-    },
-
-    {
-       15,  259,  259,  259,  259,  259,  259,  259,  259,  259,
-      259,  259,  259,  259,  259,  259,  259,  259,  259,  259,
-      259,  259,  259,  259,  259,  259,  259,  259,  259,  259,
-      259,  259,  259,  259,  259,  259,  259,  259,  259,  260,
-      259,  259,  259,  259,  259,  259,  259,  259,  259,  259,
-      259,  259,  259,  259,  259,  259,  259,  259,  259,  259,
-      259,  259,  259,  259,  259,  259,  259,  259,  259,  259,
-      259,  259,  259,  259,  259,  259,  259,  259,  259,  259,
-
-      259,  259,  259,  259,  259,  259,  259,  259,  259,  259,
-      259,  259,  259,  259,  259,  259,  259,  259,  259,  259,
-      259,  259,  259,  259,  259,  259,  259,  259,  259,  259,
-      259,  259,  259,  259,  259,  259,  259,  259,  259,  259,
-      259,  259,  259,  259,  259,  259,  259,  259
-    },
-
-    {
-       15, -245, -245, -245, -245, -245, -245, -245, -245, -245,
-     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
-     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
-     -245, -245,  261, -245, -245, -245, -245, -245, -245, -245,
-     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
-
-     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
-     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
-     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
-     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
-     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
-     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
-     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
-     -245, -245, -245, -245, -245, -245, -245, -245
-    },
-
-    {
-       15, -246, -246, -246, -246, -246, -246, -246, -246, -246,
-     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
-
-     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
-     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
-     -246, -246, -246, -246, -246, -246,   62, -246,  262,  263,
-      263,  263,  263,  263,  263,  263,  263,  263, -246, -246,
-     -246, -246, -246, -246, -246, -246, -246, -246, -246,   65,
-     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
-     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
-     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
-     -246,   65, -246, -246, -246, -246, -246, -246, -246, -246,
-     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
-
-     -246, -246, -246, -246, -246, -246, -246, -246
-    },
-
-    {
-       15, -247, -247, -247, -247, -247, -247, -247, -247, -247,
-     -247, -247, -247, -247, -247, -247, -247, -247, -247, -247,
-     -247, -247, -247, -247, -247, -247, -247, -247, -247, -247,
-     -247, -247, -247, -247, -247, -247, -247, -247, -247, -247,
-     -247, -247, -247, -247, -247, -247,   62, -247,  264,  264,
-      264,  264,  264,  264,  264,  264,  264,  264, -247, -247,
-     -247, -247, -247, -247, -247, -247, -247, -247, -247,   65,
-     -247, -247, -247, -247, -247, -247, -247, -247, -247, -247,
-     -247, -247, -247, -247, -247, -247, -247, -247, -247, -247,
-
-     -247, -247, -247, -247, -247, -247, -247, -247, -247, -247,
-     -247,   65, -247, -247, -247, -247, -247, -247, -247, -247,
-     -247, -247, -247, -247, -247, -247, -247, -247, -247, -247,
-     -247, -247, -247, -247, -247, -247, -247, -247
-    },
-
-    {
-       15, -248, -248, -248, -248, -248, -248, -248, -248, -248,
-     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
-     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
-     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
-     -248, -248, -248, -248, -248, -248,   62, -248,  265,  265,
-      265,  265,  265,  265,  265,  265,  265,  265, -248, -248,
-
-     -248, -248, -248, -248, -248, -248, -248, -248, -248,   65,
-     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
-     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
-     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
-     -248,   65, -248, -248, -248, -248, -248, -248, -248, -248,
-     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
-     -248, -248, -248, -248, -248, -248, -248, -248
-    },
-
-    {
-       15, -249, -249, -249, -249, -249, -249, -249, -249, -249,
-     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
-     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
-
-     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
-     -249, -249, -249, -249, -249, -249,   62, -249,  266,  266,
-      266,  266,  266,  266,  266,  266,  266,  266, -249, -249,
-     -249, -249, -249, -249, -249, -249, -249, -249, -249,   65,
-     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
-     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
-     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
-     -249,   65, -249, -249, -249, -249, -249, -249, -249, -249,
-     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
-     -249, -249, -249, -249, -249, -249, -249, -249
-
-    },
-
-    {
-       15, -250, -250, -250, -250, -250, -250, -250, -250, -250,
-     -250, -250, -250, -250, -250, -250, -250, -250, -250, -250,
-     -250, -250, -250, -250, -250, -250, -250, -250, -250, -250,
-     -250, -250, -250, -250, -250, -250, -250, -250, -250, -250,
-     -250, -250, -250, -250, -250, -250,   62, -250,  267,  267,
-      267,  267,  267,  267,  267,  267,  267,  267, -250, -250,
-     -250, -250, -250, -250, -250, -250, -250, -250, -250,   65,
-     -250, -250, -250, -250, -250, -250, -250, -250, -250, -250,
-     -250, -250, -250, -250, -250, -250, -250, -250, -250, -250,
-     -250, -250, -250, -250, -250, -250, -250, -250, -250, -250,
-
-     -250,   65, -250, -250, -250, -250, -250, -250, -250, -250,
-     -250, -250, -250, -250, -250, -250, -250, -250, -250, -250,
-     -250, -250, -250, -250, -250, -250, -250, -250
-    },
-
-    {
-       15, -251, -251, -251, -251, -251, -251, -251, -251, -251,
-     -251, -251, -251, -251, -251, -251, -251, -251, -251, -251,
-     -251, -251, -251, -251, -251, -251, -251, -251, -251, -251,
-     -251, -251, -251, -251, -251, -251, -251, -251, -251, -251,
-     -251, -251, -251, -251, -251, -251,   62, -251,  268,  268,
-      268,  268,  268,  268,  268,  268,  268,  268, -251, -251,
-     -251, -251, -251, -251, -251, -251, -251, -251, -251,   65,
-
-     -251, -251, -251, -251, -251, -251, -251, -251, -251, -251,
-     -251, -251, -251, -251, -251, -251, -251, -251, -251, -251,
-     -251, -251, -251, -251, -251, -251, -251, -251, -251, -251,
-     -251,   65, -251, -251, -251, -251, -251, -251, -251, -251,
-     -251, -251, -251, -251, -251, -251, -251, -251, -251, -251,
-     -251, -251, -251, -251, -251, -251, -251, -251
-    },
-
-    {
-       15, -252, -252, -252, -252, -252, -252, -252, -252, -252,
-     -252, -252, -252, -252, -252, -252, -252, -252, -252, -252,
-     -252, -252, -252, -252, -252, -252, -252, -252, -252, -252,
-     -252, -252, -252, -252, -252, -252, -252, -252, -252, -252,
-
-     -252, -252, -252, -252, -252, -252,   62, -252,  269,  269,
-      269,  269,  269,  269,  269,  269,  269,  269, -252, -252,
-     -252, -252, -252, -252, -252, -252, -252, -252, -252,   65,
-     -252, -252, -252, -252, -252, -252, -252, -252, -252, -252,
-     -252, -252, -252, -252, -252, -252, -252, -252, -252, -252,
-     -252, -252, -252, -252, -252, -252, -252, -252, -252, -252,
-     -252,   65, -252, -252, -252, -252, -252, -252, -252, -252,
-     -252, -252, -252, -252, -252, -252, -252, -252, -252, -252,
-     -252, -252, -252, -252, -252, -252, -252, -252
-    },
-
-    {
-       15, -253, -253, -253, -253, -253, -253, -253, -253, -253,
-
-     -253, -253, -253, -253, -253, -253, -253, -253, -253, -253,
-     -253, -253, -253, -253, -253, -253, -253, -253, -253, -253,
-     -253, -253, -253, -253, -253, -253, -253, -253, -253, -253,
-     -253, -253, -253, -253, -253, -253,   62, -253,  270,  270,
-      270,  270,  270,  270,  270,  270,  270,  270, -253, -253,
-     -253, -253, -253, -253, -253, -253, -253, -253, -253,   65,
-     -253, -253, -253, -253, -253, -253, -253, -253, -253, -253,
-     -253, -253, -253, -253, -253, -253, -253, -253, -253, -253,
-     -253, -253, -253, -253, -253, -253, -253, -253, -253, -253,
-     -253,   65, -253, -253, -253, -253, -253, -253, -253, -253,
-
-     -253, -253, -253, -253, -253, -253, -253, -253, -253, -253,
-     -253, -253, -253, -253, -253, -253, -253, -253
-    },
-
-    {
-       15, -254, -254, -254, -254, -254, -254, -254, -254, -254,
-     -254, -254, -254, -254, -254, -254, -254, -254, -254, -254,
-     -254, -254, -254, -254, -254, -254, -254, -254, -254, -254,
-     -254, -254, -254, -254, -254, -254, -254, -254, -254, -254,
-     -254, -254, -254, -254, -254, -254,   62, -254,  271,  271,
-      271,  271,  271,  271,  271,  271,  271,  271, -254, -254,
-     -254, -254, -254, -254, -254, -254, -254, -254, -254,   65,
-     -254, -254, -254, -254, -254, -254, -254, -254, -254, -254,
-
-     -254, -254, -254, -254, -254, -254, -254, -254, -254, -254,
-     -254, -254, -254, -254, -254, -254, -254, -254, -254, -254,
-     -254,   65, -254, -254, -254, -254, -254, -254, -254, -254,
-     -254, -254, -254, -254, -254, -254, -254, -254, -254, -254,
-     -254, -254, -254, -254, -254, -254, -254, -254
-    },
-
-    {
-       15, -255, -255, -255, -255, -255, -255, -255, -255, -255,
-     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
-     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
-     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
-     -255, -255, -255, -255, -255, -255,   62, -255,  272,  272,
-
-      272,  272,  272,  272,  272,  272,  272,  272, -255, -255,
-     -255, -255, -255, -255, -255, -255, -255, -255, -255,   65,
-     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
-     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
-     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
-     -255,   65, -255, -255, -255, -255, -255, -255, -255, -255,
-     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
-     -255, -255, -255, -255, -255, -255, -255, -255
-    },
-
-    {
-       15, -256, -256, -256, -256, -256, -256, -256, -256, -256,
-     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
-
-     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
-     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
-     -256, -256, -256, -256, -256, -256,   62, -256,  273,  273,
-      273,  273,  273,  273,  273,  273,  273,  273, -256, -256,
-     -256, -256, -256, -256, -256, -256, -256, -256, -256,   65,
-     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
-     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
-     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
-     -256,   65, -256, -256, -256, -256, -256, -256, -256, -256,
-     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
-
-     -256, -256, -256, -256, -256, -256, -256, -256
-    },
-
-    {
-       15, -257, -257, -257, -257, -257, -257, -257, -257, -257,
-     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
-     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
-     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
-     -257, -257, -257, -257, -257, -257,   62, -257,  274,  274,
-      274,  274,  274,  274,  274,  274,  274,  274, -257, -257,
-     -257, -257, -257, -257, -257, -257, -257, -257, -257,   65,
-     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
-     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
-
-     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
-     -257,   65, -257, -257, -257, -257, -257, -257, -257, -257,
-     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
-     -257, -257, -257, -257, -257, -257, -257, -257
-    },
-
-    {
-       15, -258, -258, -258, -258, -258, -258, -258, -258, -258,
-     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
-     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
-     -258, -258,  275, -258, -258, -258, -258, -258, -258, -258,
-     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
-     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
-
-     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
-     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
-     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
-     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
-     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
-     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
-     -258, -258, -258, -258, -258, -258, -258, -258
-    },
-
-    {
-       15,  259,  259,  259,  259,  259,  259,  259,  259,  259,
-      259,  259,  259,  259,  259,  259,  259,  259,  259,  259,
-      259,  259,  259,  259,  259,  259,  259,  259,  259,  259,
-
-      259,  259,  259,  259,  259,  259,  259,  259,  259,  260,
-      259,  259,  259,  259,  259,  259,  259,  259,  259,  259,
-      259,  259,  259,  259,  259,  259,  259,  259,  259,  259,
-      259,  259,  259,  259,  259,  259,  259,  259,  259,  259,
-      259,  259,  259,  259,  259,  259,  259,  259,  259,  259,
-      259,  259,  259,  259,  259,  259,  259,  259,  259,  259,
-      259,  259,  259,  259,  259,  259,  259,  259,  259,  259,
-      259,  259,  259,  259,  259,  259,  259,  259,  259,  259,
-      259,  259,  259,  259,  259,  259,  259,  259,  259,  259,
-      259,  259,  259,  259,  259,  259,  259,  259
-
-    },
-
-    {
-       15, -260, -260, -260, -260, -260, -260, -260, -260, -260,
-     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
-     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
-     -260, -260, -260, -260, -260, -260, -260, -260, -260,  259,
-     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
-     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
-     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
-     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
-     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
-     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
-
-     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
-     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
-     -260, -260, -260, -260, -260, -260, -260, -260
-    },
-
-    {
-       15, -261, -261, -261, -261, -261, -261, -261, -261, -261,
-     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
-     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
-     -261, -261,  276, -261, -261, -261, -261, -261, -261, -261,
-     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
-     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
-     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
-
-     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
-     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
-     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
-     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
-     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
-     -261, -261, -261, -261, -261, -261, -261, -261
-    },
-
-    {
-       15, -262, -262, -262, -262, -262, -262, -262, -262, -262,
-     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
-     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
-     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
-
-     -262, -262, -262, -262, -262, -262,   62, -262,  277,  278,
-      278,  278,  278,  278,  278,  278,  278,  278, -262, -262,
-     -262, -262, -262, -262, -262, -262, -262, -262, -262,   65,
-     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
-     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
-     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
-     -262,   65, -262, -262, -262, -262, -262, -262, -262, -262,
-     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
-     -262, -262, -262, -262, -262, -262, -262, -262
-    },
-
-    {
-       15, -263, -263, -263, -263, -263, -263, -263, -263, -263,
-
-     -263, -263, -263, -263, -263, -263, -263, -263, -263, -263,
-     -263, -263, -263, -263, -263, -263, -263, -263, -263, -263,
-     -263, -263, -263, -263, -263, -263, -263, -263, -263, -263,
-     -263, -263, -263, -263, -263, -263,   62, -263,  279,  279,
-      279,  279,  279,  279,  279,  279,  279,  279, -263, -263,
-     -263, -263, -263, -263, -263, -263, -263, -263, -263,   65,
-     -263, -263, -263, -263, -263, -263, -263, -263, -263, -263,
-     -263, -263, -263, -263, -263, -263, -263, -263, -263, -263,
-     -263, -263, -263, -263, -263, -263, -263, -263, -263, -263,
-     -263,   65, -263, -263, -263, -263, -263, -263, -263, -263,
-
-     -263, -263, -263, -263, -263, -263, -263, -263, -263, -263,
-     -263, -263, -263, -263, -263, -263, -263, -263
-    },
-
-    {
-       15, -264, -264, -264, -264, -264, -264, -264, -264, -264,
-     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
-     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
-     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
-     -264, -264, -264, -264, -264, -264,   62, -264,  280,  280,
-      280,  280,  280,  280,  280,  280,  280,  280, -264, -264,
-     -264, -264, -264, -264, -264, -264, -264, -264, -264,   65,
-     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
-
-     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
-     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
-     -264,   65, -264, -264, -264, -264, -264, -264, -264, -264,
-     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
-     -264, -264, -264, -264, -264, -264, -264, -264
-    },
-
-    {
-       15, -265, -265, -265, -265, -265, -265, -265, -265, -265,
-     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
-     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
-     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
-     -265, -265, -265, -265, -265, -265,   62, -265,  281,  281,
-
-      281,  281,  281,  281,  281,  281,  281,  281, -265, -265,
-     -265, -265, -265, -265, -265, -265, -265, -265, -265,   65,
-     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
-     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
-     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
-     -265,   65, -265, -265, -265, -265, -265, -265, -265, -265,
-     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
-     -265, -265, -265, -265, -265, -265, -265, -265
-    },
-
-    {
-       15, -266, -266, -266, -266, -266, -266, -266, -266, -266,
-     -266, -266, -266, -266, -266, -266, -266, -266, -266, -266,
-
-     -266, -266, -266, -266, -266, -266, -266, -266, -266, -266,
-     -266, -266, -266, -266, -266, -266, -266, -266, -266, -266,
-     -266, -266, -266, -266, -266, -266,   62, -266,  282,  282,
-      282,  282,  282,  282,  282,  282,  282,  282, -266, -266,
-     -266, -266, -266, -266, -266, -266, -266, -266, -266,   65,
-     -266, -266, -266, -266, -266, -266, -266, -266, -266, -266,
-     -266, -266, -266, -266, -266, -266, -266, -266, -266, -266,
-     -266, -266, -266, -266, -266, -266, -266, -266, -266, -266,
-     -266,   65, -266, -266, -266, -266, -266, -266, -266, -266,
-     -266, -266, -266, -266, -266, -266, -266, -266, -266, -266,
-
-     -266, -266, -266, -266, -266, -266, -266, -266
-    },
-
-    {
-       15, -267, -267, -267, -267, -267, -267, -267, -267, -267,
-     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
-     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
-     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
-     -267, -267, -267, -267, -267, -267,   62, -267,  283,  283,
-      283,  283,  283,  283,  283,  283,  283,  283, -267, -267,
-     -267, -267, -267, -267, -267, -267, -267, -267, -267,   65,
-     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
-     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
-
-     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
-     -267,   65, -267, -267, -267, -267, -267, -267, -267, -267,
-     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
-     -267, -267, -267, -267, -267, -267, -267, -267
-    },
-
-    {
-       15, -268, -268, -268, -268, -268, -268, -268, -268, -268,
-     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
-     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
-     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
-     -268, -268, -268, -268, -268, -268,   62, -268,  284,  284,
-      284,  284,  284,  284,  284,  284,  284,  284, -268, -268,
-
-     -268, -268, -268, -268, -268, -268, -268, -268, -268,   65,
-     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
-     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
-     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
-     -268,   65, -268, -268, -268, -268, -268, -268, -268, -268,
-     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
-     -268, -268, -268, -268, -268, -268, -268, -268
-    },
-
-    {
-       15, -269, -269, -269, -269, -269, -269, -269, -269, -269,
-     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
-     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
-
-     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
-     -269, -269, -269, -269, -269, -269,   62, -269,  285,  285,
-      285,  285,  285,  285,  285,  285,  285,  285, -269, -269,
-     -269, -269, -269, -269, -269, -269, -269, -269, -269,   65,
-     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
-     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
-     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
-     -269,   65, -269, -269, -269, -269, -269, -269, -269, -269,
-     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
-     -269, -269, -269, -269, -269, -269, -269, -269
-
-    },
-
-    {
-       15, -270, -270, -270, -270, -270, -270, -270, -270, -270,
-     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
-     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
-     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
-     -270, -270, -270, -270, -270, -270,   62, -270,  286,  286,
-      286,  286,  286,  286,  286,  286,  286,  286, -270, -270,
-     -270, -270, -270, -270, -270, -270, -270, -270, -270,   65,
-     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
-     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
-     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
-
-     -270,   65, -270, -270, -270, -270, -270, -270, -270, -270,
-     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
-     -270, -270, -270, -270, -270, -270, -270, -270
-    },
-
-    {
-       15, -271, -271, -271, -271, -271, -271, -271, -271, -271,
-     -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
-     -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
-     -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
-     -271, -271, -271, -271, -271, -271,   62, -271,  287,  287,
-      287,  287,  287,  287,  287,  287,  287,  287, -271, -271,
-     -271, -271, -271, -271, -271, -271, -271, -271, -271,   65,
-
-     -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
-     -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
-     -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
-     -271,   65, -271, -271, -271, -271, -271, -271, -271, -271,
-     -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
-     -271, -271, -271, -271, -271, -271, -271, -271
-    },
-
-    {
-       15, -272, -272, -272, -272, -272, -272, -272, -272, -272,
-     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
-     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
-     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
-
-     -272, -272, -272, -272, -272, -272,   62, -272,  288,  288,
-      288,  288,  288,  288,  288,  288,  288,  288, -272, -272,
-     -272, -272, -272, -272, -272, -272, -272, -272, -272,   65,
-     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
-     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
-     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
-     -272,   65, -272, -272, -272, -272, -272, -272, -272, -272,
-     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
-     -272, -272, -272, -272, -272, -272, -272, -272
-    },
-
-    {
-       15, -273, -273, -273, -273, -273, -273, -273, -273, -273,
-
-     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
-     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
-     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
-     -273, -273, -273, -273, -273, -273,   62, -273,  289,  289,
-      289,  289,  289,  289,  289,  289,  289,  289, -273, -273,
-     -273, -273, -273, -273, -273, -273, -273, -273, -273,   65,
-     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
-     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
-     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
-     -273,   65, -273, -273, -273, -273, -273, -273, -273, -273,
-
-     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
-     -273, -273, -273, -273, -273, -273, -273, -273
-    },
-
-    {
-       15, -274, -274, -274, -274, -274, -274, -274, -274, -274,
-     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
-     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
-     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
-     -274, -274, -274, -274, -274, -274,   62, -274,  290,  290,
-      290,  290,  290,  290,  290,  290,  290,  290, -274, -274,
-     -274, -274, -274, -274, -274, -274, -274, -274, -274,   65,
-     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
-
-     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
-     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
-     -274,   65, -274, -274, -274, -274, -274, -274, -274, -274,
-     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
-     -274, -274, -274, -274, -274, -274, -274, -274
-    },
-
-    {
-       15, -275, -275, -275, -275, -275, -275, -275, -275, -275,
-     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
-     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
-     -275, -275,  291, -275, -275, -275, -275, -275, -275, -275,
-     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
-
-     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
-     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
-     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
-     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
-     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
-     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
-     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
-     -275, -275, -275, -275, -275, -275, -275, -275
-    },
-
-    {
-       15, -276, -276, -276, -276, -276, -276, -276, -276, -276,
-     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
-
-     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
-     -276, -276,  292, -276, -276, -276, -276, -276, -276, -276,
-     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
-     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
-     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
-     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
-     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
-     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
-     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
-     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
-
-     -276, -276, -276, -276, -276, -276, -276, -276
-    },
-
-    {
-       15, -277, -277, -277, -277, -277, -277, -277, -277, -277,
-     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
-     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
-     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
-     -277, -277, -277, -277, -277, -277,   62, -277,  293,  294,
-      294,  294,  294,  294,  294,  294,  294,  294, -277, -277,
-     -277, -277, -277, -277, -277, -277, -277, -277, -277,   65,
-     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
-     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
-
-     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
-     -277,   65, -277, -277, -277, -277, -277, -277, -277, -277,
-     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
-     -277, -277, -277, -277, -277, -277, -277, -277
-    },
-
-    {
-       15, -278, -278, -278, -278, -278, -278, -278, -278, -278,
-     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
-     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
-     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
-     -278, -278, -278, -278, -278, -278,   62, -278,  295,  295,
-      295,  295,  295,  295,  295,  295,  295,  295, -278, -278,
-
-     -278, -278, -278, -278, -278, -278, -278, -278, -278,   65,
-     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
-     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
-     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
-     -278,   65, -278, -278, -278, -278, -278, -278, -278, -278,
-     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
-     -278, -278, -278, -278, -278, -278, -278, -278
-    },
-
-    {
-       15, -279, -279, -279, -279, -279, -279, -279, -279, -279,
-     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
-     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
-
-     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
-     -279, -279, -279, -279, -279, -279,   62, -279,  296,  296,
-      296,  296,  296,  296,  296,  296,  296,  296, -279, -279,
-     -279, -279, -279, -279, -279, -279, -279, -279, -279,   65,
-     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
-     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
-     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
-     -279,   65, -279, -279, -279, -279, -279, -279, -279, -279,
-     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
-     -279, -279, -279, -279, -279, -279, -279, -279
-
-    },
-
-    {
-       15, -280, -280, -280, -280, -280, -280, -280, -280, -280,
-     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
-     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
-     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
-     -280, -280, -280, -280, -280, -280,   62, -280,  297,  297,
-      297,  297,  297,  297,  297,  297,  297,  297, -280, -280,
-     -280, -280, -280, -280, -280, -280, -280, -280, -280,   65,
-     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
-     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
-     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
-
-     -280,   65, -280, -280, -280, -280, -280, -280, -280, -280,
-     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
-     -280, -280, -280, -280, -280, -280, -280, -280
-    },
-
-    {
-       15, -281, -281, -281, -281, -281, -281, -281, -281, -281,
-     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
-     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
-     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
-     -281, -281, -281, -281, -281, -281,   62, -281,  298,  298,
-      298,  298,  298,  298,  298,  298,  298,  298, -281, -281,
-     -281, -281, -281, -281, -281, -281, -281, -281, -281,   65,
-
-     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
-     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
-     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
-     -281,   65, -281, -281, -281, -281, -281, -281, -281, -281,
-     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
-     -281, -281, -281, -281, -281, -281, -281, -281
-    },
-
-    {
-       15, -282, -282, -282, -282, -282, -282, -282, -282, -282,
-     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
-     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
-     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
-
-     -282, -282, -282, -282, -282, -282,   62, -282,  299,  299,
-      299,  299,  299,  299,  299,  299,  299,  299, -282, -282,
-     -282, -282, -282, -282, -282, -282, -282, -282, -282,   65,
-     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
-     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
-     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
-     -282,   65, -282, -282, -282, -282, -282, -282, -282, -282,
-     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
-     -282, -282, -282, -282, -282, -282, -282, -282
-    },
-
-    {
-       15, -283, -283, -283, -283, -283, -283, -283, -283, -283,
-
-     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
-     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
-     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
-     -283, -283, -283, -283, -283, -283,   62, -283,  300,  300,
-      300,  300,  300,  300,  300,  300,  300,  300, -283, -283,
-     -283, -283, -283, -283, -283, -283, -283, -283, -283,   65,
-     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
-     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
-     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
-     -283,   65, -283, -283, -283, -283, -283, -283, -283, -283,
-
-     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
-     -283, -283, -283, -283, -283, -283, -283, -283
-    },
-
-    {
-       15, -284, -284, -284, -284, -284, -284, -284, -284, -284,
-     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
-     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
-     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
-     -284, -284, -284, -284, -284, -284,   62, -284,  301,  301,
-      301,  301,  301,  301,  301,  301,  301,  301, -284, -284,
-     -284, -284, -284, -284, -284, -284, -284, -284, -284,   65,
-     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
-
-     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
-     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
-     -284,   65, -284, -284, -284, -284, -284, -284, -284, -284,
-     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
-     -284, -284, -284, -284, -284, -284, -284, -284
-    },
-
-    {
-       15, -285, -285, -285, -285, -285, -285, -285, -285, -285,
-     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
-     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
-     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
-     -285, -285, -285, -285, -285, -285,   62, -285,  302,  302,
-
-      302,  302,  302,  302,  302,  302,  302,  302, -285, -285,
-     -285, -285, -285, -285, -285, -285, -285, -285, -285,   65,
-     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
-     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
-     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
-     -285,   65, -285, -285, -285, -285, -285, -285, -285, -285,
-     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
-     -285, -285, -285, -285, -285, -285, -285, -285
-    },
-
-    {
-       15, -286, -286, -286, -286, -286, -286, -286, -286, -286,
-     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
-
-     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
-     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
-     -286, -286, -286, -286, -286, -286,   62, -286,  303,  303,
-      303,  303,  303,  303,  303,  303,  303,  303, -286, -286,
-     -286, -286, -286, -286, -286, -286, -286, -286, -286,   65,
-     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
-     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
-     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
-     -286,   65, -286, -286, -286, -286, -286, -286, -286, -286,
-     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
-
-     -286, -286, -286, -286, -286, -286, -286, -286
-    },
-
-    {
-       15, -287, -287, -287, -287, -287, -287, -287, -287, -287,
-     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
-     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
-     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
-     -287, -287, -287, -287, -287, -287,   62, -287,  304,  304,
-      304,  304,  304,  304,  304,  304,  304,  304, -287, -287,
-     -287, -287, -287, -287, -287, -287, -287, -287, -287,   65,
-     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
-     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
-
-     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
-     -287,   65, -287, -287, -287, -287, -287, -287, -287, -287,
-     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
-     -287, -287, -287, -287, -287, -287, -287, -287
-    },
-
-    {
-       15, -288, -288, -288, -288, -288, -288, -288, -288, -288,
-     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
-     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
-     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
-     -288, -288, -288, -288, -288, -288,   62, -288,  305,  305,
-      305,  305,  305,  305,  305,  305,  305,  305, -288, -288,
-
-     -288, -288, -288, -288, -288, -288, -288, -288, -288,   65,
-     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
-     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
-     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
-     -288,   65, -288, -288, -288, -288, -288, -288, -288, -288,
-     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
-     -288, -288, -288, -288, -288, -288, -288, -288
-    },
-
-    {
-       15, -289, -289, -289, -289, -289, -289, -289, -289, -289,
-     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
-     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
-
-     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
-     -289, -289, -289, -289, -289, -289,   62, -289,  306,  306,
-      306,  306,  306,  306,  306,  306,  306,  306, -289, -289,
-     -289, -289, -289, -289, -289, -289, -289, -289, -289,   65,
-     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
-     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
-     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
-     -289,   65, -289, -289, -289, -289, -289, -289, -289, -289,
-     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
-     -289, -289, -289, -289, -289, -289, -289, -289
-
-    },
-
-    {
-       15, -290, -290, -290, -290, -290, -290, -290, -290, -290,
-     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
-     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
-     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
-     -290, -290, -290, -290, -290, -290,   62, -290,  307,  307,
-      307,  307,  307,  307,  307,  307,  307,  307, -290, -290,
-     -290, -290, -290, -290, -290, -290, -290, -290, -290,   65,
-     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
-     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
-     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
-
-     -290,   65, -290, -290, -290, -290, -290, -290, -290, -290,
-     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
-     -290, -290, -290, -290, -290, -290, -290, -290
-    },
-
-    {
-       15, -291, -291, -291, -291, -291, -291, -291, -291, -291,
-     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
-     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
-     -291, -291,  308, -291, -291, -291, -291, -291, -291, -291,
-     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
-     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
-     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
-
-     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
-     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
-     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
-     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
-     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
-     -291, -291, -291, -291, -291, -291, -291, -291
-    },
-
-    {
-       15, -292, -292, -292, -292, -292, -292, -292, -292, -292,
-     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
-     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
-     -292, -292,  309, -292, -292, -292, -292, -292, -292, -292,
-
-     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
-     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
-     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
-     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
-     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
-     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
-     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
-     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
-     -292, -292, -292, -292, -292, -292, -292, -292
-    },
-
-    {
-       15, -293, -293, -293, -293, -293, -293, -293, -293, -293,
-
-     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
-     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
-     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
-     -293, -293, -293, -293, -293, -293,   62, -293,  310,  311,
-      311,  311,  311,  311,  311,  311,  311,  311, -293, -293,
-     -293, -293, -293, -293, -293, -293, -293, -293, -293,   65,
-     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
-     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
-     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
-     -293,   65, -293, -293, -293, -293, -293, -293, -293, -293,
-
-     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
-     -293, -293, -293, -293, -293, -293, -293, -293
-    },
-
-    {
-       15, -294, -294, -294, -294, -294, -294, -294, -294, -294,
-     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
-     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
-     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
-     -294, -294, -294, -294, -294, -294,   62, -294,  312,  312,
-      312,  312,  312,  312,  312,  312,  312,  312, -294, -294,
-     -294, -294, -294, -294, -294, -294, -294, -294, -294,   65,
-     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
-
-     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
-     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
-     -294,   65, -294, -294, -294, -294, -294, -294, -294, -294,
-     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
-     -294, -294, -294, -294, -294, -294, -294, -294
-    },
-
-    {
-       15, -295, -295, -295, -295, -295, -295, -295, -295, -295,
-     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
-     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
-     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
-     -295, -295, -295, -295, -295, -295,   62, -295,  313,  313,
-
-      313,  313,  313,  313,  313,  313,  313,  313, -295, -295,
-     -295, -295, -295, -295, -295, -295, -295, -295, -295,   65,
-     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
-     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
-     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
-     -295,   65, -295, -295, -295, -295, -295, -295, -295, -295,
-     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
-     -295, -295, -295, -295, -295, -295, -295, -295
-    },
-
-    {
-       15, -296, -296, -296, -296, -296, -296, -296, -296, -296,
-     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
-
-     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
-     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
-     -296, -296, -296, -296, -296, -296,   62, -296,  314,  314,
-      314,  314,  314,  314,  314,  314,  314,  314, -296, -296,
-     -296, -296, -296, -296, -296, -296, -296, -296, -296,   65,
-     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
-     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
-     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
-     -296,   65, -296, -296, -296, -296, -296, -296, -296, -296,
-     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
-
-     -296, -296, -296, -296, -296, -296, -296, -296
-    },
-
-    {
-       15, -297, -297, -297, -297, -297, -297, -297, -297, -297,
-     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
-     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
-     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
-     -297, -297, -297, -297, -297, -297,   62, -297,  315,  315,
-      315,  315,  315,  315,  315,  315,  315,  315, -297, -297,
-     -297, -297, -297, -297, -297, -297, -297, -297, -297,   65,
-     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
-     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
-
-     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
-     -297,   65, -297, -297, -297, -297, -297, -297, -297, -297,
-     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
-     -297, -297, -297, -297, -297, -297, -297, -297
-    },
-
-    {
-       15, -298, -298, -298, -298, -298, -298, -298, -298, -298,
-     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
-     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
-     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
-     -298, -298, -298, -298, -298, -298,   62, -298,  316,  316,
-      316,  316,  316,  316,  316,  316,  316,  316, -298, -298,
-
-     -298, -298, -298, -298, -298, -298, -298, -298, -298,   65,
-     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
-     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
-     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
-     -298,   65, -298, -298, -298, -298, -298, -298, -298, -298,
-     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
-     -298, -298, -298, -298, -298, -298, -298, -298
-    },
-
-    {
-       15, -299, -299, -299, -299, -299, -299, -299, -299, -299,
-     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
-     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
-
-     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
-     -299, -299, -299, -299, -299, -299,   62, -299,  317,  317,
-      317,  317,  317,  317,  317,  317,  317,  317, -299, -299,
-     -299, -299, -299, -299, -299, -299, -299, -299, -299,   65,
-     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
-     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
-     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
-     -299,   65, -299, -299, -299, -299, -299, -299, -299, -299,
-     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
-     -299, -299, -299, -299, -299, -299, -299, -299
-
-    },
-
-    {
-       15, -300, -300, -300, -300, -300, -300, -300, -300, -300,
-     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
-     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
-     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
-     -300, -300, -300, -300, -300, -300,   62, -300,  318,  318,
-      318,  318,  318,  318,  318,  318,  318,  318, -300, -300,
-     -300, -300, -300, -300, -300, -300, -300, -300, -300,   65,
-     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
-     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
-     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
-
-     -300,   65, -300, -300, -300, -300, -300, -300, -300, -300,
-     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
-     -300, -300, -300, -300, -300, -300, -300, -300
-    },
-
-    {
-       15, -301, -301, -301, -301, -301, -301, -301, -301, -301,
-     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
-     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
-     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
-     -301, -301, -301, -301, -301, -301,   62, -301,  319,  319,
-      319,  319,  319,  319,  319,  319,  319,  319, -301, -301,
-     -301, -301, -301, -301, -301, -301, -301, -301, -301,   65,
-
-     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
-     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
-     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
-     -301,   65, -301, -301, -301, -301, -301, -301, -301, -301,
-     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
-     -301, -301, -301, -301, -301, -301, -301, -301
-    },
-
-    {
-       15, -302, -302, -302, -302, -302, -302, -302, -302, -302,
-     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
-     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
-     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
-
-     -302, -302, -302, -302, -302, -302,   62, -302,  320,  320,
-      320,  320,  320,  320,  320,  320,  320,  320, -302, -302,
-     -302, -302, -302, -302, -302, -302, -302, -302, -302,   65,
-     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
-     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
-     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
-     -302,   65, -302, -302, -302, -302, -302, -302, -302, -302,
-     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
-     -302, -302, -302, -302, -302, -302, -302, -302
-    },
-
-    {
-       15, -303, -303, -303, -303, -303, -303, -303, -303, -303,
-
-     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
-     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
-     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
-     -303, -303, -303, -303, -303, -303,   62, -303,  321,  321,
-      321,  321,  321,  321,  321,  321,  321,  321, -303, -303,
-     -303, -303, -303, -303, -303, -303, -303, -303, -303,   65,
-     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
-     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
-     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
-     -303,   65, -303, -303, -303, -303, -303, -303, -303, -303,
-
-     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
-     -303, -303, -303, -303, -303, -303, -303, -303
-    },
-
-    {
-       15, -304, -304, -304, -304, -304, -304, -304, -304, -304,
-     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
-     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
-     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
-     -304, -304, -304, -304, -304, -304,   62, -304,  322,  322,
-      322,  322,  322,  322,  322,  322,  322,  322, -304, -304,
-     -304, -304, -304, -304, -304, -304, -304, -304, -304,   65,
-     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
-
-     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
-     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
-     -304,   65, -304, -304, -304, -304, -304, -304, -304, -304,
-     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
-     -304, -304, -304, -304, -304, -304, -304, -304
-    },
-
-    {
-       15, -305, -305, -305, -305, -305, -305, -305, -305, -305,
-     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
-     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
-     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
-     -305, -305, -305, -305, -305, -305,   62, -305,  323,  323,
-
-      323,  323,  323,  323,  323,  323,  323,  323, -305, -305,
-     -305, -305, -305, -305, -305, -305, -305, -305, -305,   65,
-     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
-     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
-     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
-     -305,   65, -305, -305, -305, -305, -305, -305, -305, -305,
-     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
-     -305, -305, -305, -305, -305, -305, -305, -305
-    },
-
-    {
-       15, -306, -306, -306, -306, -306, -306, -306, -306, -306,
-     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
-
-     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
-     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
-     -306, -306, -306, -306, -306, -306,   62, -306,  324,  324,
-      324,  324,  324,  324,  324,  324,  324,  324, -306, -306,
-     -306, -306, -306, -306, -306, -306, -306, -306, -306,   65,
-     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
-     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
-     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
-     -306,   65, -306, -306, -306, -306, -306, -306, -306, -306,
-     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
-
-     -306, -306, -306, -306, -306, -306, -306, -306
-    },
-
-    {
-       15, -307, -307, -307, -307, -307, -307, -307, -307, -307,
-     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
-     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
-     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
-     -307, -307, -307, -307, -307, -307,   62, -307,  325,  325,
-      325,  325,  325,  325,  325,  325,  325,  325, -307, -307,
-     -307, -307, -307, -307, -307, -307, -307, -307, -307,   65,
-     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
-     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
-
-     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
-     -307,   65, -307, -307, -307, -307, -307, -307, -307, -307,
-     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
-     -307, -307, -307, -307, -307, -307, -307, -307
-    },
-
-    {
-       15, -308, -308, -308, -308, -308, -308, -308, -308, -308,
-     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
-     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
-     -308, -308,  326, -308, -308, -308, -308, -308, -308, -308,
-     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
-     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
-
-     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
-     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
-     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
-     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
-     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
-     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
-     -308, -308, -308, -308, -308, -308, -308, -308
-    },
-
-    {
-       15, -309, -309, -309, -309, -309, -309, -309, -309, -309,
-     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
-     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
-
-     -309, -309,  327, -309, -309, -309, -309, -309, -309, -309,
-     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
-     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
-     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
-     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
-     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
-     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
-     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
-     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
-     -309, -309, -309, -309, -309, -309, -309, -309
-
-    },
-
-    {
-       15, -310, -310, -310, -310, -310, -310, -310, -310, -310,
-     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
-     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
-     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
-     -310, -310, -310, -310, -310, -310,   62, -310,  328,  329,
-      329,  329,  329,  329,  329,  329,  329,  329, -310, -310,
-     -310, -310, -310, -310, -310, -310, -310, -310, -310,   65,
-     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
-     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
-     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
-
-     -310,   65, -310, -310, -310, -310, -310, -310, -310, -310,
-     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
-     -310, -310, -310, -310, -310, -310, -310, -310
-    },
-
-    {
-       15, -311, -311, -311, -311, -311, -311, -311, -311, -311,
-     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
-     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
-     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
-     -311, -311, -311, -311, -311, -311,   62, -311,  330,  330,
-      330,  330,  330,  330,  330,  330,  330,  330, -311, -311,
-     -311, -311, -311, -311, -311, -311, -311, -311, -311,   65,
-
-     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
-     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
-     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
-     -311,   65, -311, -311, -311, -311, -311, -311, -311, -311,
-     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
-     -311, -311, -311, -311, -311, -311, -311, -311
-    },
-
-    {
-       15, -312, -312, -312, -312, -312, -312, -312, -312, -312,
-     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
-     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
-     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
-
-     -312, -312, -312, -312, -312, -312,   62, -312,  331,  331,
-      331,  331,  331,  331,  331,  331,  331,  331, -312, -312,
-     -312, -312, -312, -312, -312, -312, -312, -312, -312,   65,
-     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
-     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
-     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
-     -312,   65, -312, -312, -312, -312, -312, -312, -312, -312,
-     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
-     -312, -312, -312, -312, -312, -312, -312, -312
-    },
-
-    {
-       15, -313, -313, -313, -313, -313, -313, -313, -313, -313,
-
-     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
-     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
-     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
-     -313, -313, -313, -313, -313, -313,   62, -313,  332,  332,
-      332,  332,  332,  332,  332,  332,  332,  332, -313, -313,
-     -313, -313, -313, -313, -313, -313, -313, -313, -313,   65,
-     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
-     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
-     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
-     -313,   65, -313, -313, -313, -313, -313, -313, -313, -313,
-
-     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
-     -313, -313, -313, -313, -313, -313, -313, -313
-    },
-
-    {
-       15, -314, -314, -314, -314, -314, -314, -314, -314, -314,
-     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
-     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
-     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
-     -314, -314, -314, -314, -314, -314,   62, -314,  333,  333,
-      333,  333,  333,  333,  333,  333,  333,  333, -314, -314,
-     -314, -314, -314, -314, -314, -314, -314, -314, -314,   65,
-     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
-
-     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
-     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
-     -314,   65, -314, -314, -314, -314, -314, -314, -314, -314,
-     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
-     -314, -314, -314, -314, -314, -314, -314, -314
-    },
-
-    {
-       15, -315, -315, -315, -315, -315, -315, -315, -315, -315,
-     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
-     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
-     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
-     -315, -315, -315, -315, -315, -315,   62, -315,  334,  334,
-
-      334,  334,  334,  334,  334,  334,  334,  334, -315, -315,
-     -315, -315, -315, -315, -315, -315, -315, -315, -315,   65,
-     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
-     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
-     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
-     -315,   65, -315, -315, -315, -315, -315, -315, -315, -315,
-     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
-     -315, -315, -315, -315, -315, -315, -315, -315
-    },
-
-    {
-       15, -316, -316, -316, -316, -316, -316, -316, -316, -316,
-     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
-
-     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
-     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
-     -316, -316, -316, -316, -316, -316,   62, -316,  335,  335,
-      335,  335,  335,  335,  335,  335,  335,  335, -316, -316,
-     -316, -316, -316, -316, -316, -316, -316, -316, -316,   65,
-     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
-     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
-     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
-     -316,   65, -316, -316, -316, -316, -316, -316, -316, -316,
-     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
-
-     -316, -316, -316, -316, -316, -316, -316, -316
-    },
-
-    {
-       15, -317, -317, -317, -317, -317, -317, -317, -317, -317,
-     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
-     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
-     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
-     -317, -317, -317, -317, -317, -317,   62, -317,  336,  336,
-      336,  336,  336,  336,  336,  336,  336,  336, -317, -317,
-     -317, -317, -317, -317, -317, -317, -317, -317, -317,   65,
-     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
-     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
-
-     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
-     -317,   65, -317, -317, -317, -317, -317, -317, -317, -317,
-     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
-     -317, -317, -317, -317, -317, -317, -317, -317
-    },
-
-    {
-       15, -318, -318, -318, -318, -318, -318, -318, -318, -318,
-     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
-     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
-     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
-     -318, -318, -318, -318, -318, -318,   62, -318,  337,  337,
-      337,  337,  337,  337,  337,  337,  337,  337, -318, -318,
-
-     -318, -318, -318, -318, -318, -318, -318, -318, -318,   65,
-     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
-     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
-     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
-     -318,   65, -318, -318, -318, -318, -318, -318, -318, -318,
-     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
-     -318, -318, -318, -318, -318, -318, -318, -318
-    },
-
-    {
-       15, -319, -319, -319, -319, -319, -319, -319, -319, -319,
-     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
-     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
-
-     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
-     -319, -319, -319, -319, -319, -319,   62, -319,  338,  338,
-      338,  338,  338,  338,  338,  338,  338,  338, -319, -319,
-     -319, -319, -319, -319, -319, -319, -319, -319, -319,   65,
-     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
-     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
-     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
-     -319,   65, -319, -319, -319, -319, -319, -319, -319, -319,
-     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
-     -319, -319, -319, -319, -319, -319, -319, -319
-
-    },
-
-    {
-       15, -320, -320, -320, -320, -320, -320, -320, -320, -320,
-     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
-     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
-     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
-     -320, -320, -320, -320, -320, -320,   62, -320,  339,  339,
-      339,  339,  339,  339,  339,  339,  339,  339, -320, -320,
-     -320, -320, -320, -320, -320, -320, -320, -320, -320,   65,
-     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
-     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
-     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
-
-     -320,   65, -320, -320, -320, -320, -320, -320, -320, -320,
-     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
-     -320, -320, -320, -320, -320, -320, -320, -320
-    },
-
-    {
-       15, -321, -321, -321, -321, -321, -321, -321, -321, -321,
-     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
-     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
-     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
-     -321, -321, -321, -321, -321, -321,   62, -321,  340,  340,
-      340,  340,  340,  340,  340,  340,  340,  340, -321, -321,
-     -321, -321, -321, -321, -321, -321, -321, -321, -321,   65,
-
-     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
-     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
-     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
-     -321,   65, -321, -321, -321, -321, -321, -321, -321, -321,
-     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
-     -321, -321, -321, -321, -321, -321, -321, -321
-    },
-
-    {
-       15, -322, -322, -322, -322, -322, -322, -322, -322, -322,
-     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
-     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
-     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
-
-     -322, -322, -322, -322, -322, -322,   62, -322,  341,  341,
-      341,  341,  341,  341,  341,  341,  341,  341, -322, -322,
-     -322, -322, -322, -322, -322, -322, -322, -322, -322,   65,
-     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
-     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
-     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
-     -322,   65, -322, -322, -322, -322, -322, -322, -322, -322,
-     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
-     -322, -322, -322, -322, -322, -322, -322, -322
-    },
-
-    {
-       15, -323, -323, -323, -323, -323, -323, -323, -323, -323,
-
-     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
-     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
-     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
-     -323, -323, -323, -323, -323, -323,   62, -323,  342,  342,
-      342,  342,  342,  342,  342,  342,  342,  342, -323, -323,
-     -323, -323, -323, -323, -323, -323, -323, -323, -323,   65,
-     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
-     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
-     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
-     -323,   65, -323, -323, -323, -323, -323, -323, -323, -323,
-
-     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
-     -323, -323, -323, -323, -323, -323, -323, -323
-    },
-
-    {
-       15, -324, -324, -324, -324, -324, -324, -324, -324, -324,
-     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
-     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
-     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
-     -324, -324, -324, -324, -324, -324,   62, -324,  343,  343,
-      343,  343,  343,  343,  343,  343,  343,  343, -324, -324,
-     -324, -324, -324, -324, -324, -324, -324, -324, -324,   65,
-     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
-
-     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
-     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
-     -324,   65, -324, -324, -324, -324, -324, -324, -324, -324,
-     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
-     -324, -324, -324, -324, -324, -324, -324, -324
-    },
-
-    {
-       15, -325, -325, -325, -325, -325, -325, -325, -325, -325,
-     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
-     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
-     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
-     -325, -325, -325, -325, -325, -325,   62, -325,  344,  344,
-
-      344,  344,  344,  344,  344,  344,  344,  344, -325, -325,
-     -325, -325, -325, -325, -325, -325, -325, -325, -325,   65,
-     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
-     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
-     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
-     -325,   65, -325, -325, -325, -325, -325, -325, -325, -325,
-     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
-     -325, -325, -325, -325, -325, -325, -325, -325
-    },
-
-    {
-       15, -326, -326, -326, -326, -326, -326, -326, -326, -326,
-     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
-
-     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
-     -326, -326,  345, -326, -326, -326, -326, -326, -326, -326,
-     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
-     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
-     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
-     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
-     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
-     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
-     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
-     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
-
-     -326, -326, -326, -326, -326, -326, -326, -326
-    },
-
-    {
-       15, -327, -327, -327, -327, -327, -327, -327, -327, -327,
-     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
-     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
-     -327, -327,  346, -327, -327, -327, -327, -327, -327, -327,
-     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
-     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
-     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
-     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
-     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
-
-     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
-     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
-     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
-     -327, -327, -327, -327, -327, -327, -327, -327
-    },
-
-    {
-       15, -328, -328, -328, -328, -328, -328, -328, -328, -328,
-     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
-     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
-     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
-     -328, -328, -328, -328, -328, -328,   62, -328,  347,  348,
-      348,  348,  348,  348,  348,  348,  348,  348, -328, -328,
-
-     -328, -328, -328, -328, -328, -328, -328, -328, -328,   65,
-     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
-     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
-     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
-     -328,   65, -328, -328, -328, -328, -328, -328, -328, -328,
-     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
-     -328, -328, -328, -328, -328, -328, -328, -328
-    },
-
-    {
-       15, -329, -329, -329, -329, -329, -329, -329, -329, -329,
-     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
-     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
-
-     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
-     -329, -329, -329, -329, -329, -329,   62, -329,  349,  349,
-      349,  349,  349,  349,  349,  349,  349,  349, -329, -329,
-     -329, -329, -329, -329, -329, -329, -329, -329, -329,   65,
-     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
-     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
-     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
-     -329,   65, -329, -329, -329, -329, -329, -329, -329, -329,
-     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
-     -329, -329, -329, -329, -329, -329, -329, -329
-
-    },
-
-    {
-       15, -330, -330, -330, -330, -330, -330, -330, -330, -330,
-     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
-     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
-     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
-     -330, -330, -330, -330, -330, -330,   62, -330,  350,  350,
-      350,  350,  350,  350,  350,  350,  350,  350, -330, -330,
-     -330, -330, -330, -330, -330, -330, -330, -330, -330,   65,
-     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
-     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
-     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
-
-     -330,   65, -330, -330, -330, -330, -330, -330, -330, -330,
-     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
-     -330, -330, -330, -330, -330, -330, -330, -330
-    },
-
-    {
-       15, -331, -331, -331, -331, -331, -331, -331, -331, -331,
-     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
-     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
-     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
-     -331, -331, -331, -331, -331, -331,   62, -331,  351,  351,
-      351,  351,  351,  351,  351,  351,  351,  351, -331, -331,
-     -331, -331, -331, -331, -331, -331, -331, -331, -331,   65,
-
-     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
-     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
-     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
-     -331,   65, -331, -331, -331, -331, -331, -331, -331, -331,
-     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
-     -331, -331, -331, -331, -331, -331, -331, -331
-    },
-
-    {
-       15, -332, -332, -332, -332, -332, -332, -332, -332, -332,
-     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
-     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
-     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
-
-     -332, -332, -332, -332, -332, -332,   62, -332,  352,  352,
-      352,  352,  352,  352,  352,  352,  352,  352, -332, -332,
-     -332, -332, -332, -332, -332, -332, -332, -332, -332,   65,
-     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
-     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
-     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
-     -332,   65, -332, -332, -332, -332, -332, -332, -332, -332,
-     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
-     -332, -332, -332, -332, -332, -332, -332, -332
-    },
-
-    {
-       15, -333, -333, -333, -333, -333, -333, -333, -333, -333,
-
-     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
-     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
-     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
-     -333, -333, -333, -333, -333, -333,   62, -333,  353,  353,
-      353,  353,  353,  353,  353,  353,  353,  353, -333, -333,
-     -333, -333, -333, -333, -333, -333, -333, -333, -333,   65,
-     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
-     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
-     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
-     -333,   65, -333, -333, -333, -333, -333, -333, -333, -333,
-
-     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
-     -333, -333, -333, -333, -333, -333, -333, -333
-    },
-
-    {
-       15, -334, -334, -334, -334, -334, -334, -334, -334, -334,
-     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
-     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
-     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
-     -334, -334, -334, -334, -334, -334,   62, -334,  354,  354,
-      354,  354,  354,  354,  354,  354,  354,  354, -334, -334,
-     -334, -334, -334, -334, -334, -334, -334, -334, -334,   65,
-     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
-
-     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
-     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
-     -334,   65, -334, -334, -334, -334, -334, -334, -334, -334,
-     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
-     -334, -334, -334, -334, -334, -334, -334, -334
-    },
-
-    {
-       15, -335, -335, -335, -335, -335, -335, -335, -335, -335,
-     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
-     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
-     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
-     -335, -335, -335, -335, -335, -335,   62, -335,  355,  355,
-
-      355,  355,  355,  355,  355,  355,  355,  355, -335, -335,
-     -335, -335, -335, -335, -335, -335, -335, -335, -335,   65,
-     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
-     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
-     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
-     -335,   65, -335, -335, -335, -335, -335, -335, -335, -335,
-     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
-     -335, -335, -335, -335, -335, -335, -335, -335
-    },
-
-    {
-       15, -336, -336, -336, -336, -336, -336, -336, -336, -336,
-     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
-
-     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
-     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
-     -336, -336, -336, -336, -336, -336,   62, -336,  356,  356,
-      356,  356,  356,  356,  356,  356,  356,  356, -336, -336,
-     -336, -336, -336, -336, -336, -336, -336, -336, -336,   65,
-     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
-     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
-     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
-     -336,   65, -336, -336, -336, -336, -336, -336, -336, -336,
-     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
-
-     -336, -336, -336, -336, -336, -336, -336, -336
-    },
-
-    {
-       15, -337, -337, -337, -337, -337, -337, -337, -337, -337,
-     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
-     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
-     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
-     -337, -337, -337, -337, -337, -337,   62, -337,  357,  357,
-      357,  357,  357,  357,  357,  357,  357,  357, -337, -337,
-     -337, -337, -337, -337, -337, -337, -337, -337, -337,   65,
-     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
-     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
-
-     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
-     -337,   65, -337, -337, -337, -337, -337, -337, -337, -337,
-     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
-     -337, -337, -337, -337, -337, -337, -337, -337
-    },
-
-    {
-       15, -338, -338, -338, -338, -338, -338, -338, -338, -338,
-     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
-     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
-     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
-     -338, -338, -338, -338, -338, -338,   62, -338,  358,  358,
-      358,  358,  358,  358,  358,  358,  358,  358, -338, -338,
-
-     -338, -338, -338, -338, -338, -338, -338, -338, -338,   65,
-     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
-     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
-     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
-     -338,   65, -338, -338, -338, -338, -338, -338, -338, -338,
-     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
-     -338, -338, -338, -338, -338, -338, -338, -338
-    },
-
-    {
-       15, -339, -339, -339, -339, -339, -339, -339, -339, -339,
-     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
-     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
-
-     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
-     -339, -339, -339, -339, -339, -339,   62, -339,  359,  359,
-      359,  359,  359,  359,  359,  359,  359,  359, -339, -339,
-     -339, -339, -339, -339, -339, -339, -339, -339, -339,   65,
-     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
-     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
-     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
-     -339,   65, -339, -339, -339, -339, -339, -339, -339, -339,
-     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
-     -339, -339, -339, -339, -339, -339, -339, -339
-
-    },
-
-    {
-       15, -340, -340, -340, -340, -340, -340, -340, -340, -340,
-     -340, -340, -340, -340, -340, -340, -340, -340, -340, -340,
-     -340, -340, -340, -340, -340, -340, -340, -340, -340, -340,
-     -340, -340, -340, -340, -340, -340, -340, -340, -340, -340,
-     -340, -340, -340, -340, -340, -340,   62, -340,  360,  360,
-      360,  360,  360,  360,  360,  360,  360,  360, -340, -340,
-     -340, -340, -340, -340, -340, -340, -340, -340, -340,   65,
-     -340, -340, -340, -340, -340, -340, -340, -340, -340, -340,
-     -340, -340, -340, -340, -340, -340, -340, -340, -340, -340,
-     -340, -340, -340, -340, -340, -340, -340, -340, -340, -340,
-
-     -340,   65, -340, -340, -340, -340, -340, -340, -340, -340,
-     -340, -340, -340, -340, -340, -340, -340, -340, -340, -340,
-     -340, -340, -340, -340, -340, -340, -340, -340
-    },
-
-    {
-       15, -341, -341, -341, -341, -341, -341, -341, -341, -341,
-     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
-     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
-     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
-     -341, -341, -341, -341, -341, -341,   62, -341,  361,  361,
-      361,  361,  361,  361,  361,  361,  361,  361, -341, -341,
-     -341, -341, -341, -341, -341, -341, -341, -341, -341,   65,
-
-     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
-     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
-     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
-     -341,   65, -341, -341, -341, -341, -341, -341, -341, -341,
-     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
-     -341, -341, -341, -341, -341, -341, -341, -341
-    },
-
-    {
-       15, -342, -342, -342, -342, -342, -342, -342, -342, -342,
-     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
-     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
-     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
-
-     -342, -342, -342, -342, -342, -342,   62, -342,  362,  362,
-      362,  362,  362,  362,  362,  362,  362,  362, -342, -342,
-     -342, -342, -342, -342, -342, -342, -342, -342, -342,   65,
-     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
-     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
-     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
-     -342,   65, -342, -342, -342, -342, -342, -342, -342, -342,
-     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
-     -342, -342, -342, -342, -342, -342, -342, -342
-    },
-
-    {
-       15, -343, -343, -343, -343, -343, -343, -343, -343, -343,
-
-     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
-     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
-     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
-     -343, -343, -343, -343, -343, -343,   62, -343,  363,  363,
-      363,  363,  363,  363,  363,  363,  363,  363, -343, -343,
-     -343, -343, -343, -343, -343, -343, -343, -343, -343,   65,
-     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
-     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
-     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
-     -343,   65, -343, -343, -343, -343, -343, -343, -343, -343,
-
-     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
-     -343, -343, -343, -343, -343, -343, -343, -343
-    },
-
-    {
-       15, -344, -344, -344, -344, -344, -344, -344, -344, -344,
-     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
-     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
-     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
-     -344, -344, -344, -344, -344, -344,   62, -344,  364,  364,
-      364,  364,  364,  364,  364,  364,  364,  364, -344, -344,
-     -344, -344, -344, -344, -344, -344, -344, -344, -344,   65,
-     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
-
-     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
-     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
-     -344,   65, -344, -344, -344, -344, -344, -344, -344, -344,
-     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
-     -344, -344, -344, -344, -344, -344, -344, -344
-    },
-
-    {
-       15, -345, -345, -345, -345, -345, -345, -345, -345, -345,
-     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
-     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
-     -345, -345,  365, -345, -345, -345, -345, -345, -345, -345,
-     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
-
-     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
-     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
-     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
-     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
-     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
-     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
-     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
-     -345, -345, -345, -345, -345, -345, -345, -345
-    },
-
-    {
-       15, -346, -346, -346, -346, -346, -346, -346, -346, -346,
-     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
-
-     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
-     -346, -346,  366, -346, -346, -346, -346, -346, -346, -346,
-     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
-     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
-     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
-     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
-     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
-     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
-     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
-     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
-
-     -346, -346, -346, -346, -346, -346, -346, -346
-    },
-
-    {
-       15, -347, -347, -347, -347, -347, -347, -347, -347, -347,
-     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
-     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
-     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
-     -347, -347, -347, -347, -347, -347,   62, -347,  367,  368,
-      368,  368,  368,  368,  368,  368,  368,  368, -347, -347,
-     -347, -347, -347, -347, -347, -347, -347, -347, -347,   65,
-     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
-     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
-
-     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
-     -347,   65, -347, -347, -347, -347, -347, -347, -347, -347,
-     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
-     -347, -347, -347, -347, -347, -347, -347, -347
-    },
-
-    {
-       15, -348, -348, -348, -348, -348, -348, -348, -348, -348,
-     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
-     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
-     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
-     -348, -348, -348, -348, -348, -348,   62, -348,  369,  369,
-      369,  369,  369,  369,  369,  369,  369,  369, -348, -348,
-
-     -348, -348, -348, -348, -348, -348, -348, -348, -348,   65,
-     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
-     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
-     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
-     -348,   65, -348, -348, -348, -348, -348, -348, -348, -348,
-     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
-     -348, -348, -348, -348, -348, -348, -348, -348
-    },
-
-    {
-       15, -349, -349, -349, -349, -349, -349, -349, -349, -349,
-     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
-     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
-
-     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
-     -349, -349, -349, -349, -349, -349,   62, -349,  370,  370,
-      370,  370,  370,  370,  370,  370,  370,  370, -349, -349,
-     -349, -349, -349, -349, -349, -349, -349, -349, -349,   65,
-     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
-     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
-     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
-     -349,   65, -349, -349, -349, -349, -349, -349, -349, -349,
-     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
-     -349, -349, -349, -349, -349, -349, -349, -349
-
-    },
-
-    {
-       15, -350, -350, -350, -350, -350, -350, -350, -350, -350,
-     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
-     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
-     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
-     -350, -350, -350, -350, -350, -350,   62, -350,  371,  371,
-      371,  371,  371,  371,  371,  371,  371,  371, -350, -350,
-     -350, -350, -350, -350, -350, -350, -350, -350, -350,   65,
-     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
-     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
-     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
-
-     -350,   65, -350, -350, -350, -350, -350, -350, -350, -350,
-     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
-     -350, -350, -350, -350, -350, -350, -350, -350
-    },
-
-    {
-       15, -351, -351, -351, -351, -351, -351, -351, -351, -351,
-     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
-     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
-     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
-     -351, -351, -351, -351, -351, -351,   62, -351,  372,  372,
-      372,  372,  372,  372,  372,  372,  372,  372, -351, -351,
-     -351, -351, -351, -351, -351, -351, -351, -351, -351,   65,
-
-     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
-     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
-     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
-     -351,   65, -351, -351, -351, -351, -351, -351, -351, -351,
-     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
-     -351, -351, -351, -351, -351, -351, -351, -351
-    },
-
-    {
-       15, -352, -352, -352, -352, -352, -352, -352, -352, -352,
-     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
-     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
-     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
-
-     -352, -352, -352, -352, -352, -352,   62, -352,  373,  373,
-      373,  373,  373,  373,  373,  373,  373,  373, -352, -352,
-     -352, -352, -352, -352, -352, -352, -352, -352, -352,   65,
-     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
-     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
-     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
-     -352,   65, -352, -352, -352, -352, -352, -352, -352, -352,
-     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
-     -352, -352, -352, -352, -352, -352, -352, -352
-    },
-
-    {
-       15, -353, -353, -353, -353, -353, -353, -353, -353, -353,
-
-     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
-     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
-     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
-     -353, -353, -353, -353, -353, -353,   62, -353,  374,  374,
-      374,  374,  374,  374,  374,  374,  374,  374, -353, -353,
-     -353, -353, -353, -353, -353, -353, -353, -353, -353,   65,
-     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
-     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
-     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
-     -353,   65, -353, -353, -353, -353, -353, -353, -353, -353,
-
-     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
-     -353, -353, -353, -353, -353, -353, -353, -353
-    },
-
-    {
-       15, -354, -354, -354, -354, -354, -354, -354, -354, -354,
-     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
-     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
-     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
-     -354, -354, -354, -354, -354, -354,   62, -354,  375,  375,
-      375,  375,  375,  375,  375,  375,  375,  375, -354, -354,
-     -354, -354, -354, -354, -354, -354, -354, -354, -354,   65,
-     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
-
-     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
-     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
-     -354,   65, -354, -354, -354, -354, -354, -354, -354, -354,
-     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
-     -354, -354, -354, -354, -354, -354, -354, -354
-    },
-
-    {
-       15, -355, -355, -355, -355, -355, -355, -355, -355, -355,
-     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
-     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
-     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
-     -355, -355, -355, -355, -355, -355,   62, -355,  376,  376,
-
-      376,  376,  376,  376,  376,  376,  376,  376, -355, -355,
-     -355, -355, -355, -355, -355, -355, -355, -355, -355,   65,
-     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
-     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
-     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
-     -355,   65, -355, -355, -355, -355, -355, -355, -355, -355,
-     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
-     -355, -355, -355, -355, -355, -355, -355, -355
-    },
-
-    {
-       15, -356, -356, -356, -356, -356, -356, -356, -356, -356,
-     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
-
-     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
-     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
-     -356, -356, -356, -356, -356, -356,   62, -356,  377,  377,
-      377,  377,  377,  377,  377,  377,  377,  377, -356, -356,
-     -356, -356, -356, -356, -356, -356, -356, -356, -356,   65,
-     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
-     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
-     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
-     -356,   65, -356, -356, -356, -356, -356, -356, -356, -356,
-     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
-
-     -356, -356, -356, -356, -356, -356, -356, -356
-    },
-
-    {
-       15, -357, -357, -357, -357, -357, -357, -357, -357, -357,
-     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
-     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
-     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
-     -357, -357, -357, -357, -357, -357,   62, -357,  378,  378,
-      378,  378,  378,  378,  378,  378,  378,  378, -357, -357,
-     -357, -357, -357, -357, -357, -357, -357, -357, -357,   65,
-     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
-     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
-
-     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
-     -357,   65, -357, -357, -357, -357, -357, -357, -357, -357,
-     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
-     -357, -357, -357, -357, -357, -357, -357, -357
-    },
-
-    {
-       15, -358, -358, -358, -358, -358, -358, -358, -358, -358,
-     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
-     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
-     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
-     -358, -358, -358, -358, -358, -358,   62, -358,  379,  379,
-      379,  379,  379,  379,  379,  379,  379,  379, -358, -358,
-
-     -358, -358, -358, -358, -358, -358, -358, -358, -358,   65,
-     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
-     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
-     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
-     -358,   65, -358, -358, -358, -358, -358, -358, -358, -358,
-     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
-     -358, -358, -358, -358, -358, -358, -358, -358
-    },
-
-    {
-       15, -359, -359, -359, -359, -359, -359, -359, -359, -359,
-     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
-     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
-
-     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
-     -359, -359, -359, -359, -359, -359,   62, -359,  380,  380,
-      380,  380,  380,  380,  380,  380,  380,  380, -359, -359,
-     -359, -359, -359, -359, -359, -359, -359, -359, -359,   65,
-     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
-     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
-     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
-     -359,   65, -359, -359, -359, -359, -359, -359, -359, -359,
-     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
-     -359, -359, -359, -359, -359, -359, -359, -359
-
-    },
-
-    {
-       15, -360, -360, -360, -360, -360, -360, -360, -360, -360,
-     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
-     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
-     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
-     -360, -360, -360, -360, -360, -360,   62, -360,  381,  381,
-      381,  381,  381,  381,  381,  381,  381,  381, -360, -360,
-     -360, -360, -360, -360, -360, -360, -360, -360, -360,   65,
-     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
-     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
-     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
-
-     -360,   65, -360, -360, -360, -360, -360, -360, -360, -360,
-     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
-     -360, -360, -360, -360, -360, -360, -360, -360
-    },
-
-    {
-       15, -361, -361, -361, -361, -361, -361, -361, -361, -361,
-     -361, -361, -361, -361, -361, -361, -361, -361, -361, -361,
-     -361, -361, -361, -361, -361, -361, -361, -361, -361, -361,
-     -361, -361, -361, -361, -361, -361, -361, -361, -361, -361,
-     -361, -361, -361, -361, -361, -361,   62, -361,  382,  382,
-      382,  382,  382,  382,  382,  382,  382,  382, -361, -361,
-     -361, -361, -361, -361, -361, -361, -361, -361, -361,   65,
-
-     -361, -361, -361, -361, -361, -361, -361, -361, -361, -361,
-     -361, -361, -361, -361, -361, -361, -361, -361, -361, -361,
-     -361, -361, -361, -361, -361, -361, -361, -361, -361, -361,
-     -361,   65, -361, -361, -361, -361, -361, -361, -361, -361,
-     -361, -361, -361, -361, -361, -361, -361, -361, -361, -361,
-     -361, -361, -361, -361, -361, -361, -361, -361
-    },
-
-    {
-       15, -362, -362, -362, -362, -362, -362, -362, -362, -362,
-     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
-     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
-     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
-
-     -362, -362, -362, -362, -362, -362,   62, -362,  383,  383,
-      383,  383,  383,  383,  383,  383,  383,  383, -362, -362,
-     -362, -362, -362, -362, -362, -362, -362, -362, -362,   65,
-     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
-     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
-     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
-     -362,   65, -362, -362, -362, -362, -362, -362, -362, -362,
-     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
-     -362, -362, -362, -362, -362, -362, -362, -362
-    },
-
-    {
-       15, -363, -363, -363, -363, -363, -363, -363, -363, -363,
-
-     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
-     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
-     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
-     -363, -363, -363, -363, -363, -363,   62, -363,  384,  384,
-      384,  384,  384,  384,  384,  384,  384,  384, -363, -363,
-     -363, -363, -363, -363, -363, -363, -363, -363, -363,   65,
-     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
-     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
-     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
-     -363,   65, -363, -363, -363, -363, -363, -363, -363, -363,
-
-     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
-     -363, -363, -363, -363, -363, -363, -363, -363
-    },
-
-    {
-       15, -364, -364, -364, -364, -364, -364, -364, -364, -364,
-     -364, -364, -364, -364, -364, -364, -364, -364, -364, -364,
-     -364, -364, -364, -364, -364, -364, -364, -364, -364, -364,
-     -364, -364, -364, -364, -364, -364, -364, -364, -364, -364,
-     -364, -364, -364, -364, -364, -364,   62, -364,  385,  385,
-      385,  385,  385,  385,  385,  385,  385,  385, -364, -364,
-     -364, -364, -364, -364, -364, -364, -364, -364, -364,   65,
-     -364, -364, -364, -364, -364, -364, -364, -364, -364, -364,
-
-     -364, -364, -364, -364, -364, -364, -364, -364, -364, -364,
-     -364, -364, -364, -364, -364, -364, -364, -364, -364, -364,
-     -364,   65, -364, -364, -364, -364, -364, -364, -364, -364,
-     -364, -364, -364, -364, -364, -364, -364, -364, -364, -364,
-     -364, -364, -364, -364, -364, -364, -364, -364
-    },
-
-    {
-       15, -365, -365, -365, -365, -365, -365, -365, -365, -365,
-     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
-     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
-     -365, -365,  386, -365, -365, -365, -365, -365, -365, -365,
-     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
-
-     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
-     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
-     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
-     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
-     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
-     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
-     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
-     -365, -365, -365, -365, -365, -365, -365, -365
-    },
-
-    {
-       15, -366, -366, -366, -366, -366, -366, -366, -366, -366,
-     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
-
-     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
-     -366, -366,  387, -366, -366, -366, -366, -366, -366, -366,
-     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
-     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
-     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
-     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
-     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
-     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
-     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
-     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
-
-     -366, -366, -366, -366, -366, -366, -366, -366
-    },
-
-    {
-       15, -367, -367, -367, -367, -367, -367, -367, -367, -367,
-     -367, -367, -367, -367, -367, -367, -367, -367, -367, -367,
-     -367, -367, -367, -367, -367, -367, -367, -367, -367, -367,
-     -367, -367, -367, -367, -367, -367, -367, -367, -367, -367,
-     -367, -367, -367, -367, -367, -367,   62, -367,  388,  389,
-      389,  389,  389,  389,  389,  389,  389,  389, -367, -367,
-     -367, -367, -367, -367, -367, -367, -367, -367, -367,   65,
-     -367, -367, -367, -367, -367, -367, -367, -367, -367, -367,
-     -367, -367, -367, -367, -367, -367, -367, -367, -367, -367,
-
-     -367, -367, -367, -367, -367, -367, -367, -367, -367, -367,
-     -367,   65, -367, -367, -367, -367, -367, -367, -367, -367,
-     -367, -367, -367, -367, -367, -367, -367, -367, -367, -367,
-     -367, -367, -367, -367, -367, -367, -367, -367
-    },
-
-    {
-       15, -368, -368, -368, -368, -368, -368, -368, -368, -368,
-     -368, -368, -368, -368, -368, -368, -368, -368, -368, -368,
-     -368, -368, -368, -368, -368, -368, -368, -368, -368, -368,
-     -368, -368, -368, -368, -368, -368, -368, -368, -368, -368,
-     -368, -368, -368, -368, -368, -368,   62, -368,  390,  390,
-      390,  390,  390,  390,  390,  390,  390,  390, -368, -368,
-
-     -368, -368, -368, -368, -368, -368, -368, -368, -368,   65,
-     -368, -368, -368, -368, -368, -368, -368, -368, -368, -368,
-     -368, -368, -368, -368, -368, -368, -368, -368, -368, -368,
-     -368, -368, -368, -368, -368, -368, -368, -368, -368, -368,
-     -368,   65, -368, -368, -368, -368, -368, -368, -368, -368,
-     -368, -368, -368, -368, -368, -368, -368, -368, -368, -368,
-     -368, -368, -368, -368, -368, -368, -368, -368
-    },
-
-    {
-       15, -369, -369, -369, -369, -369, -369, -369, -369, -369,
-     -369, -369, -369, -369, -369, -369, -369, -369, -369, -369,
-     -369, -369, -369, -369, -369, -369, -369, -369, -369, -369,
-
-     -369, -369, -369, -369, -369, -369, -369, -369, -369, -369,
-     -369, -369, -369, -369, -369, -369,   62, -369,  391,  391,
-      391,  391,  391,  391,  391,  391,  391,  391, -369, -369,
-     -369, -369, -369, -369, -369, -369, -369, -369, -369,   65,
-     -369, -369, -369, -369, -369, -369, -369, -369, -369, -369,
-     -369, -369, -369, -369, -369, -369, -369, -369, -369, -369,
-     -369, -369, -369, -369, -369, -369, -369, -369, -369, -369,
-     -369,   65, -369, -369, -369, -369, -369, -369, -369, -369,
-     -369, -369, -369, -369, -369, -369, -369, -369, -369, -369,
-     -369, -369, -369, -369, -369, -369, -369, -369
-
-    },
-
-    {
-       15, -370, -370, -370, -370, -370, -370, -370, -370, -370,
-     -370, -370, -370, -370, -370, -370, -370, -370, -370, -370,
-     -370, -370, -370, -370, -370, -370, -370, -370, -370, -370,
-     -370, -370, -370, -370, -370, -370, -370, -370, -370, -370,
-     -370, -370, -370, -370, -370, -370,   62, -370,  392,  392,
-      392,  392,  392,  392,  392,  392,  392,  392, -370, -370,
-     -370, -370, -370, -370, -370, -370, -370, -370, -370,   65,
-     -370, -370, -370, -370, -370, -370, -370, -370, -370, -370,
-     -370, -370, -370, -370, -370, -370, -370, -370, -370, -370,
-     -370, -370, -370, -370, -370, -370, -370, -370, -370, -370,
-
-     -370,   65, -370, -370, -370, -370, -370, -370, -370, -370,
-     -370, -370, -370, -370, -370, -370, -370, -370, -370, -370,
-     -370, -370, -370, -370, -370, -370, -370, -370
-    },
-
-    {
-       15, -371, -371, -371, -371, -371, -371, -371, -371, -371,
-     -371, -371, -371, -371, -371, -371, -371, -371, -371, -371,
-     -371, -371, -371, -371, -371, -371, -371, -371, -371, -371,
-     -371, -371, -371, -371, -371, -371, -371, -371, -371, -371,
-     -371, -371, -371, -371, -371, -371,   62, -371,  393,  393,
-      393,  393,  393,  393,  393,  393,  393,  393, -371, -371,
-     -371, -371, -371, -371, -371, -371, -371, -371, -371,   65,
-
-     -371, -371, -371, -371, -371, -371, -371, -371, -371, -371,
-     -371, -371, -371, -371, -371, -371, -371, -371, -371, -371,
-     -371, -371, -371, -371, -371, -371, -371, -371, -371, -371,
-     -371,   65, -371, -371, -371, -371, -371, -371, -371, -371,
-     -371, -371, -371, -371, -371, -371, -371, -371, -371, -371,
-     -371, -371, -371, -371, -371, -371, -371, -371
-    },
-
-    {
-       15, -372, -372, -372, -372, -372, -372, -372, -372, -372,
-     -372, -372, -372, -372, -372, -372, -372, -372, -372, -372,
-     -372, -372, -372, -372, -372, -372, -372, -372, -372, -372,
-     -372, -372, -372, -372, -372, -372, -372, -372, -372, -372,
-
-     -372, -372, -372, -372, -372, -372,   62, -372,  394,  394,
-      394,  394,  394,  394,  394,  394,  394,  394, -372, -372,
-     -372, -372, -372, -372, -372, -372, -372, -372, -372,   65,
-     -372, -372, -372, -372, -372, -372, -372, -372, -372, -372,
-     -372, -372, -372, -372, -372, -372, -372, -372, -372, -372,
-     -372, -372, -372, -372, -372, -372, -372, -372, -372, -372,
-     -372,   65, -372, -372, -372, -372, -372, -372, -372, -372,
-     -372, -372, -372, -372, -372, -372, -372, -372, -372, -372,
-     -372, -372, -372, -372, -372, -372, -372, -372
-    },
-
-    {
-       15, -373, -373, -373, -373, -373, -373, -373, -373, -373,
-
-     -373, -373, -373, -373, -373, -373, -373, -373, -373, -373,
-     -373, -373, -373, -373, -373, -373, -373, -373, -373, -373,
-     -373, -373, -373, -373, -373, -373, -373, -373, -373, -373,
-     -373, -373, -373, -373, -373, -373,   62, -373,  395,  395,
-      395,  395,  395,  395,  395,  395,  395,  395, -373, -373,
-     -373, -373, -373, -373, -373, -373, -373, -373, -373,   65,
-     -373, -373, -373, -373, -373, -373, -373, -373, -373, -373,
-     -373, -373, -373, -373, -373, -373, -373, -373, -373, -373,
-     -373, -373, -373, -373, -373, -373, -373, -373, -373, -373,
-     -373,   65, -373, -373, -373, -373, -373, -373, -373, -373,
-
-     -373, -373, -373, -373, -373, -373, -373, -373, -373, -373,
-     -373, -373, -373, -373, -373, -373, -373, -373
-    },
-
-    {
-       15, -374, -374, -374, -374, -374, -374, -374, -374, -374,
-     -374, -374, -374, -374, -374, -374, -374, -374, -374, -374,
-     -374, -374, -374, -374, -374, -374, -374, -374, -374, -374,
-     -374, -374, -374, -374, -374, -374, -374, -374, -374, -374,
-     -374, -374, -374, -374, -374, -374,   62, -374,  396,  396,
-      396,  396,  396,  396,  396,  396,  396,  396, -374, -374,
-     -374, -374, -374, -374, -374, -374, -374, -374, -374,   65,
-     -374, -374, -374, -374, -374, -374, -374, -374, -374, -374,
-
-     -374, -374, -374, -374, -374, -374, -374, -374, -374, -374,
-     -374, -374, -374, -374, -374, -374, -374, -374, -374, -374,
-     -374,   65, -374, -374, -374, -374, -374, -374, -374, -374,
-     -374, -374, -374, -374, -374, -374, -374, -374, -374, -374,
-     -374, -374, -374, -374, -374, -374, -374, -374
-    },
-
-    {
-       15, -375, -375, -375, -375, -375, -375, -375, -375, -375,
-     -375, -375, -375, -375, -375, -375, -375, -375, -375, -375,
-     -375, -375, -375, -375, -375, -375, -375, -375, -375, -375,
-     -375, -375, -375, -375, -375, -375, -375, -375, -375, -375,
-     -375, -375, -375, -375, -375, -375,   62, -375,  397,  397,
-
-      397,  397,  397,  397,  397,  397,  397,  397, -375, -375,
-     -375, -375, -375, -375, -375, -375, -375, -375, -375,   65,
-     -375, -375, -375, -375, -375, -375, -375, -375, -375, -375,
-     -375, -375, -375, -375, -375, -375, -375, -375, -375, -375,
-     -375, -375, -375, -375, -375, -375, -375, -375, -375, -375,
-     -375,   65, -375, -375, -375, -375, -375, -375, -375, -375,
-     -375, -375, -375, -375, -375, -375, -375, -375, -375, -375,
-     -375, -375, -375, -375, -375, -375, -375, -375
-    },
-
-    {
-       15, -376, -376, -376, -376, -376, -376, -376, -376, -376,
-     -376, -376, -376, -376, -376, -376, -376, -376, -376, -376,
-
-     -376, -376, -376, -376, -376, -376, -376, -376, -376, -376,
-     -376, -376, -376, -376, -376, -376, -376, -376, -376, -376,
-     -376, -376, -376, -376, -376, -376,   62, -376,  398,  398,
-      398,  398,  398,  398,  398,  398,  398,  398, -376, -376,
-     -376, -376, -376, -376, -376, -376, -376, -376, -376,   65,
-     -376, -376, -376, -376, -376, -376, -376, -376, -376, -376,
-     -376, -376, -376, -376, -376, -376, -376, -376, -376, -376,
-     -376, -376, -376, -376, -376, -376, -376, -376, -376, -376,
-     -376,   65, -376, -376, -376, -376, -376, -376, -376, -376,
-     -376, -376, -376, -376, -376, -376, -376, -376, -376, -376,
-
-     -376, -376, -376, -376, -376, -376, -376, -376
-    },
-
-    {
-       15, -377, -377, -377, -377, -377, -377, -377, -377, -377,
-     -377, -377, -377, -377, -377, -377, -377, -377, -377, -377,
-     -377, -377, -377, -377, -377, -377, -377, -377, -377, -377,
-     -377, -377, -377, -377, -377, -377, -377, -377, -377, -377,
-     -377, -377, -377, -377, -377, -377,   62, -377,  399,  399,
-      399,  399,  399,  399,  399,  399,  399,  399, -377, -377,
-     -377, -377, -377, -377, -377, -377, -377, -377, -377,   65,
-     -377, -377, -377, -377, -377, -377, -377, -377, -377, -377,
-     -377, -377, -377, -377, -377, -377, -377, -377, -377, -377,
-
-     -377, -377, -377, -377, -377, -377, -377, -377, -377, -377,
-     -377,   65, -377, -377, -377, -377, -377, -377, -377, -377,
-     -377, -377, -377, -377, -377, -377, -377, -377, -377, -377,
-     -377, -377, -377, -377, -377, -377, -377, -377
-    },
-
-    {
-       15, -378, -378, -378, -378, -378, -378, -378, -378, -378,
-     -378, -378, -378, -378, -378, -378, -378, -378, -378, -378,
-     -378, -378, -378, -378, -378, -378, -378, -378, -378, -378,
-     -378, -378, -378, -378, -378, -378, -378, -378, -378, -378,
-     -378, -378, -378, -378, -378, -378,   62, -378,  400,  400,
-      400,  400,  400,  400,  400,  400,  400,  400, -378, -378,
-
-     -378, -378, -378, -378, -378, -378, -378, -378, -378,   65,
-     -378, -378, -378, -378, -378, -378, -378, -378, -378, -378,
-     -378, -378, -378, -378, -378, -378, -378, -378, -378, -378,
-     -378, -378, -378, -378, -378, -378, -378, -378, -378, -378,
-     -378,   65, -378, -378, -378, -378, -378, -378, -378, -378,
-     -378, -378, -378, -378, -378, -378, -378, -378, -378, -378,
-     -378, -378, -378, -378, -378, -378, -378, -378
-    },
-
-    {
-       15, -379, -379, -379, -379, -379, -379, -379, -379, -379,
-     -379, -379, -379, -379, -379, -379, -379, -379, -379, -379,
-     -379, -379, -379, -379, -379, -379, -379, -379, -379, -379,
-
-     -379, -379, -379, -379, -379, -379, -379, -379, -379, -379,
-     -379, -379, -379, -379, -379, -379,   62, -379,  401,  401,
-      401,  401,  401,  401,  401,  401,  401,  401, -379, -379,
-     -379, -379, -379, -379, -379, -379, -379, -379, -379,   65,
-     -379, -379, -379, -379, -379, -379, -379, -379, -379, -379,
-     -379, -379, -379, -379, -379, -379, -379, -379, -379, -379,
-     -379, -379, -379, -379, -379, -379, -379, -379, -379, -379,
-     -379,   65, -379, -379, -379, -379, -379, -379, -379, -379,
-     -379, -379, -379, -379, -379, -379, -379, -379, -379, -379,
-     -379, -379, -379, -379, -379, -379, -379, -379
-
-    },
-
-    {
-       15, -380, -380, -380, -380, -380, -380, -380, -380, -380,
-     -380, -380, -380, -380, -380, -380, -380, -380, -380, -380,
-     -380, -380, -380, -380, -380, -380, -380, -380, -380, -380,
-     -380, -380, -380, -380, -380, -380, -380, -380, -380, -380,
-     -380, -380, -380, -380, -380, -380,   62, -380,  402,  402,
-      402,  402,  402,  402,  402,  402,  402,  402, -380, -380,
-     -380, -380, -380, -380, -380, -380, -380, -380, -380,   65,
-     -380, -380, -380, -380, -380, -380, -380, -380, -380, -380,
-     -380, -380, -380, -380, -380, -380, -380, -380, -380, -380,
-     -380, -380, -380, -380, -380, -380, -380, -380, -380, -380,
-
-     -380,   65, -380, -380, -380, -380, -380, -380, -380, -380,
-     -380, -380, -380, -380, -380, -380, -380, -380, -380, -380,
-     -380, -380, -380, -380, -380, -380, -380, -380
-    },
-
-    {
-       15, -381, -381, -381, -381, -381, -381, -381, -381, -381,
-     -381, -381, -381, -381, -381, -381, -381, -381, -381, -381,
-     -381, -381, -381, -381, -381, -381, -381, -381, -381, -381,
-     -381, -381, -381, -381, -381, -381, -381, -381, -381, -381,
-     -381, -381, -381, -381, -381, -381,   62, -381,  403,  403,
-      403,  403,  403,  403,  403,  403,  403,  403, -381, -381,
-     -381, -381, -381, -381, -381, -381, -381, -381, -381,   65,
-
-     -381, -381, -381, -381, -381, -381, -381, -381, -381, -381,
-     -381, -381, -381, -381, -381, -381, -381, -381, -381, -381,
-     -381, -381, -381, -381, -381, -381, -381, -381, -381, -381,
-     -381,   65, -381, -381, -381, -381, -381, -381, -381, -381,
-     -381, -381, -381, -381, -381, -381, -381, -381, -381, -381,
-     -381, -381, -381, -381, -381, -381, -381, -381
-    },
-
-    {
-       15, -382, -382, -382, -382, -382, -382, -382, -382, -382,
-     -382, -382, -382, -382, -382, -382, -382, -382, -382, -382,
-     -382, -382, -382, -382, -382, -382, -382, -382, -382, -382,
-     -382, -382, -382, -382, -382, -382, -382, -382, -382, -382,
-
-     -382, -382, -382, -382, -382, -382,   62, -382,  404,  404,
-      404,  404,  404,  404,  404,  404,  404,  404, -382, -382,
-     -382, -382, -382, -382, -382, -382, -382, -382, -382,   65,
-     -382, -382, -382, -382, -382, -382, -382, -382, -382, -382,
-     -382, -382, -382, -382, -382, -382, -382, -382, -382, -382,
-     -382, -382, -382, -382, -382, -382, -382, -382, -382, -382,
-     -382,   65, -382, -382, -382, -382, -382, -382, -382, -382,
-     -382, -382, -382, -382, -382, -382, -382, -382, -382, -382,
-     -382, -382, -382, -382, -382, -382, -382, -382
-    },
-
-    {
-       15, -383, -383, -383, -383, -383, -383, -383, -383, -383,
-
-     -383, -383, -383, -383, -383, -383, -383, -383, -383, -383,
-     -383, -383, -383, -383, -383, -383, -383, -383, -383, -383,
-     -383, -383, -383, -383, -383, -383, -383, -383, -383, -383,
-     -383, -383, -383, -383, -383, -383,   62, -383,  405,  405,
-      405,  405,  405,  405,  405,  405,  405,  405, -383, -383,
-     -383, -383, -383, -383, -383, -383, -383, -383, -383,   65,
-     -383, -383, -383, -383, -383, -383, -383, -383, -383, -383,
-     -383, -383, -383, -383, -383, -383, -383, -383, -383, -383,
-     -383, -383, -383, -383, -383, -383, -383, -383, -383, -383,
-     -383,   65, -383, -383, -383, -383, -383, -383, -383, -383,
-
-     -383, -383, -383, -383, -383, -383, -383, -383, -383, -383,
-     -383, -383, -383, -383, -383, -383, -383, -383
-    },
-
-    {
-       15, -384, -384, -384, -384, -384, -384, -384, -384, -384,
-     -384, -384, -384, -384, -384, -384, -384, -384, -384, -384,
-     -384, -384, -384, -384, -384, -384, -384, -384, -384, -384,
-     -384, -384, -384, -384, -384, -384, -384, -384, -384, -384,
-     -384, -384, -384, -384, -384, -384,   62, -384,  406,  406,
-      406,  406,  406,  406,  406,  406,  406,  406, -384, -384,
-     -384, -384, -384, -384, -384, -384, -384, -384, -384,   65,
-     -384, -384, -384, -384, -384, -384, -384, -384, -384, -384,
-
-     -384, -384, -384, -384, -384, -384, -384, -384, -384, -384,
-     -384, -384, -384, -384, -384, -384, -384, -384, -384, -384,
-     -384,   65, -384, -384, -384, -384, -384, -384, -384, -384,
-     -384, -384, -384, -384, -384, -384, -384, -384, -384, -384,
-     -384, -384, -384, -384, -384, -384, -384, -384
-    },
-
-    {
-       15, -385, -385, -385, -385, -385, -385, -385, -385, -385,
-     -385, -385, -385, -385, -385, -385, -385, -385, -385, -385,
-     -385, -385, -385, -385, -385, -385, -385, -385, -385, -385,
-     -385, -385, -385, -385, -385, -385, -385, -385, -385, -385,
-     -385, -385, -385, -385, -385, -385,   62, -385,  407,  407,
-
-      407,  407,  407,  407,  407,  407,  407,  407, -385, -385,
-     -385, -385, -385, -385, -385, -385, -385, -385, -385,   65,
-     -385, -385, -385, -385, -385, -385, -385, -385, -385, -385,
-     -385, -385, -385, -385, -385, -385, -385, -385, -385, -385,
-     -385, -385, -385, -385, -385, -385, -385, -385, -385, -385,
-     -385,   65, -385, -385, -385, -385, -385, -385, -385, -385,
-     -385, -385, -385, -385, -385, -385, -385, -385, -385, -385,
-     -385, -385, -385, -385, -385, -385, -385, -385
-    },
-
-    {
-       15, -386, -386, -386, -386, -386, -386, -386, -386, -386,
-     -386, -386, -386, -386, -386, -386, -386, -386, -386, -386,
-
-     -386, -386, -386, -386, -386, -386, -386, -386, -386, -386,
-     -386, -386,  408, -386, -386, -386, -386, -386, -386, -386,
-     -386, -386, -386, -386, -386, -386, -386, -386, -386, -386,
-     -386, -386, -386, -386, -386, -386, -386, -386, -386, -386,
-     -386, -386, -386, -386, -386, -386, -386, -386, -386, -386,
-     -386, -386, -386, -386, -386, -386, -386, -386, -386, -386,
-     -386, -386, -386, -386, -386, -386, -386, -386, -386, -386,
-     -386, -386, -386, -386, -386, -386, -386, -386, -386, -386,
-     -386, -386, -386, -386, -386, -386, -386, -386, -386, -386,
-     -386, -386, -386, -386, -386, -386, -386, -386, -386, -386,
-
-     -386, -386, -386, -386, -386, -386, -386, -386
-    },
-
-    {
-       15, -387, -387, -387, -387, -387, -387, -387, -387, -387,
-     -387, -387, -387, -387, -387, -387, -387, -387, -387, -387,
-     -387, -387, -387, -387, -387, -387, -387, -387, -387, -387,
-     -387, -387,  409, -387, -387, -387, -387, -387, -387, -387,
-     -387, -387, -387, -387, -387, -387, -387, -387, -387, -387,
-     -387, -387, -387, -387, -387, -387, -387, -387, -387, -387,
-     -387, -387, -387, -387, -387, -387, -387, -387, -387, -387,
-     -387, -387, -387, -387, -387, -387, -387, -387, -387, -387,
-     -387, -387, -387, -387, -387, -387, -387, -387, -387, -387,
-
-     -387, -387, -387, -387, -387, -387, -387, -387, -387, -387,
-     -387, -387, -387, -387, -387, -387, -387, -387, -387, -387,
-     -387, -387, -387, -387, -387, -387, -387, -387, -387, -387,
-     -387, -387, -387, -387, -387, -387, -387, -387
-    },
-
-    {
-       15, -388, -388, -388, -388, -388, -388, -388, -388, -388,
-     -388, -388, -388, -388, -388, -388, -388, -388, -388, -388,
-     -388, -388, -388, -388, -388, -388, -388, -388, -388, -388,
-     -388, -388, -388, -388, -388, -388, -388, -388, -388, -388,
-     -388, -388, -388, -388, -388, -388,   62, -388,  410,  411,
-      411,  411,  411,  411,  411,  411,  411,  411, -388, -388,
-
-     -388, -388, -388, -388, -388, -388, -388, -388, -388,   65,
-     -388, -388, -388, -388, -388, -388, -388, -388, -388, -388,
-     -388, -388, -388, -388, -388, -388, -388, -388, -388, -388,
-     -388, -388, -388, -388, -388, -388, -388, -388, -388, -388,
-     -388,   65, -388, -388, -388, -388, -388, -388, -388, -388,
-     -388, -388, -388, -388, -388, -388, -388, -388, -388, -388,
-     -388, -388, -388, -388, -388, -388, -388, -388
-    },
-
-    {
-       15, -389, -389, -389, -389, -389, -389, -389, -389, -389,
-     -389, -389, -389, -389, -389, -389, -389, -389, -389, -389,
-     -389, -389, -389, -389, -389, -389, -389, -389, -389, -389,
-
-     -389, -389, -389, -389, -389, -389, -389, -389, -389, -389,
-     -389, -389, -389, -389, -389, -389,   62, -389,  412,  412,
-      412,  412,  412,  412,  412,  412,  412,  412, -389, -389,
-     -389, -389, -389, -389, -389, -389, -389, -389, -389,   65,
-     -389, -389, -389, -389, -389, -389, -389, -389, -389, -389,
-     -389, -389, -389, -389, -389, -389, -389, -389, -389, -389,
-     -389, -389, -389, -389, -389, -389, -389, -389, -389, -389,
-     -389,   65, -389, -389, -389, -389, -389, -389, -389, -389,
-     -389, -389, -389, -389, -389, -389, -389, -389, -389, -389,
-     -389, -389, -389, -389, -389, -389, -389, -389
-
-    },
-
-    {
-       15, -390, -390, -390, -390, -390, -390, -390, -390, -390,
-     -390, -390, -390, -390, -390, -390, -390, -390, -390, -390,
-     -390, -390, -390, -390, -390, -390, -390, -390, -390, -390,
-     -390, -390, -390, -390, -390, -390, -390, -390, -390, -390,
-     -390, -390, -390, -390, -390, -390,   62, -390,  413,  413,
-      413,  413,  413,  413,  413,  413,  413,  413, -390, -390,
-     -390, -390, -390, -390, -390, -390, -390, -390, -390,   65,
-     -390, -390, -390, -390, -390, -390, -390, -390, -390, -390,
-     -390, -390, -390, -390, -390, -390, -390, -390, -390, -390,
-     -390, -390, -390, -390, -390, -390, -390, -390, -390, -390,
-
-     -390,   65, -390, -390, -390, -390, -390, -390, -390, -390,
-     -390, -390, -390, -390, -390, -390, -390, -390, -390, -390,
-     -390, -390, -390, -390, -390, -390, -390, -390
-    },
-
-    {
-       15, -391, -391, -391, -391, -391, -391, -391, -391, -391,
-     -391, -391, -391, -391, -391, -391, -391, -391, -391, -391,
-     -391, -391, -391, -391, -391, -391, -391, -391, -391, -391,
-     -391, -391, -391, -391, -391, -391, -391, -391, -391, -391,
-     -391, -391, -391, -391, -391, -391,   62, -391,  414,  414,
-      414,  414,  414,  414,  414,  414,  414,  414, -391, -391,
-     -391, -391, -391, -391, -391, -391, -391, -391, -391,   65,
-
-     -391, -391, -391, -391, -391, -391, -391, -391, -391, -391,
-     -391, -391, -391, -391, -391, -391, -391, -391, -391, -391,
-     -391, -391, -391, -391, -391, -391, -391, -391, -391, -391,
-     -391,   65, -391, -391, -391, -391, -391, -391, -391, -391,
-     -391, -391, -391, -391, -391, -391, -391, -391, -391, -391,
-     -391, -391, -391, -391, -391, -391, -391, -391
-    },
-
-    {
-       15, -392, -392, -392, -392, -392, -392, -392, -392, -392,
-     -392, -392, -392, -392, -392, -392, -392, -392, -392, -392,
-     -392, -392, -392, -392, -392, -392, -392, -392, -392, -392,
-     -392, -392, -392, -392, -392, -392, -392, -392, -392, -392,
-
-     -392, -392, -392, -392, -392, -392,   62, -392,  415,  415,
-      415,  415,  415,  415,  415,  415,  415,  415, -392, -392,
-     -392, -392, -392, -392, -392, -392, -392, -392, -392,   65,
-     -392, -392, -392, -392, -392, -392, -392, -392, -392, -392,
-     -392, -392, -392, -392, -392, -392, -392, -392, -392, -392,
-     -392, -392, -392, -392, -392, -392, -392, -392, -392, -392,
-     -392,   65, -392, -392, -392, -392, -392, -392, -392, -392,
-     -392, -392, -392, -392, -392, -392, -392, -392, -392, -392,
-     -392, -392, -392, -392, -392, -392, -392, -392
-    },
-
-    {
-       15, -393, -393, -393, -393, -393, -393, -393, -393, -393,
-
-     -393, -393, -393, -393, -393, -393, -393, -393, -393, -393,
-     -393, -393, -393, -393, -393, -393, -393, -393, -393, -393,
-     -393, -393, -393, -393, -393, -393, -393, -393, -393, -393,
-     -393, -393, -393, -393, -393, -393,   62, -393,  416,  416,
-      416,  416,  416,  416,  416,  416,  416,  416, -393, -393,
-     -393, -393, -393, -393, -393, -393, -393, -393, -393,   65,
-     -393, -393, -393, -393, -393, -393, -393, -393, -393, -393,
-     -393, -393, -393, -393, -393, -393, -393, -393, -393, -393,
-     -393, -393, -393, -393, -393, -393, -393, -393, -393, -393,
-     -393,   65, -393, -393, -393, -393, -393, -393, -393, -393,
-
-     -393, -393, -393, -393, -393, -393, -393, -393, -393, -393,
-     -393, -393, -393, -393, -393, -393, -393, -393
-    },
-
-    {
-       15, -394, -394, -394, -394, -394, -394, -394, -394, -394,
-     -394, -394, -394, -394, -394, -394, -394, -394, -394, -394,
-     -394, -394, -394, -394, -394, -394, -394, -394, -394, -394,
-     -394, -394, -394, -394, -394, -394, -394, -394, -394, -394,
-     -394, -394, -394, -394, -394, -394,   62, -394,  417,  417,
-      417,  417,  417,  417,  417,  417,  417,  417, -394, -394,
-     -394, -394, -394, -394, -394, -394, -394, -394, -394,   65,
-     -394, -394, -394, -394, -394, -394, -394, -394, -394, -394,
-
-     -394, -394, -394, -394, -394, -394, -394, -394, -394, -394,
-     -394, -394, -394, -394, -394, -394, -394, -394, -394, -394,
-     -394,   65, -394, -394, -394, -394, -394, -394, -394, -394,
-     -394, -394, -394, -394, -394, -394, -394, -394, -394, -394,
-     -394, -394, -394, -394, -394, -394, -394, -394
-    },
-
-    {
-       15, -395, -395, -395, -395, -395, -395, -395, -395, -395,
-     -395, -395, -395, -395, -395, -395, -395, -395, -395, -395,
-     -395, -395, -395, -395, -395, -395, -395, -395, -395, -395,
-     -395, -395, -395, -395, -395, -395, -395, -395, -395, -395,
-     -395, -395, -395, -395, -395, -395,   62, -395,  418,  418,
-
-      418,  418,  418,  418,  418,  418,  418,  418, -395, -395,
-     -395, -395, -395, -395, -395, -395, -395, -395, -395,   65,
-     -395, -395, -395, -395, -395, -395, -395, -395, -395, -395,
-     -395, -395, -395, -395, -395, -395, -395, -395, -395, -395,
-     -395, -395, -395, -395, -395, -395, -395, -395, -395, -395,
-     -395,   65, -395, -395, -395, -395, -395, -395, -395, -395,
-     -395, -395, -395, -395, -395, -395, -395, -395, -395, -395,
-     -395, -395, -395, -395, -395, -395, -395, -395
-    },
-
-    {
-       15, -396, -396, -396, -396, -396, -396, -396, -396, -396,
-     -396, -396, -396, -396, -396, -396, -396, -396, -396, -396,
-
-     -396, -396, -396, -396, -396, -396, -396, -396, -396, -396,
-     -396, -396, -396, -396, -396, -396, -396, -396, -396, -396,
-     -396, -396, -396, -396, -396, -396,   62, -396,  419,  419,
-      419,  419,  419,  419,  419,  419,  419,  419, -396, -396,
-     -396, -396, -396, -396, -396, -396, -396, -396, -396,   65,
-     -396, -396, -396, -396, -396, -396, -396, -396, -396, -396,
-     -396, -396, -396, -396, -396, -396, -396, -396, -396, -396,
-     -396, -396, -396, -396, -396, -396, -396, -396, -396, -396,
-     -396,   65, -396, -396, -396, -396, -396, -396, -396, -396,
-     -396, -396, -396, -396, -396, -396, -396, -396, -396, -396,
-
-     -396, -396, -396, -396, -396, -396, -396, -396
-    },
-
-    {
-       15, -397, -397, -397, -397, -397, -397, -397, -397, -397,
-     -397, -397, -397, -397, -397, -397, -397, -397, -397, -397,
-     -397, -397, -397, -397, -397, -397, -397, -397, -397, -397,
-     -397, -397, -397, -397, -397, -397, -397, -397, -397, -397,
-     -397, -397, -397, -397, -397, -397,   62, -397,  420,  420,
-      420,  420,  420,  420,  420,  420,  420,  420, -397, -397,
-     -397, -397, -397, -397, -397, -397, -397, -397, -397,   65,
-     -397, -397, -397, -397, -397, -397, -397, -397, -397, -397,
-     -397, -397, -397, -397, -397, -397, -397, -397, -397, -397,
-
-     -397, -397, -397, -397, -397, -397, -397, -397, -397, -397,
-     -397,   65, -397, -397, -397, -397, -397, -397, -397, -397,
-     -397, -397, -397, -397, -397, -397, -397, -397, -397, -397,
-     -397, -397, -397, -397, -397, -397, -397, -397
-    },
-
-    {
-       15, -398, -398, -398, -398, -398, -398, -398, -398, -398,
-     -398, -398, -398, -398, -398, -398, -398, -398, -398, -398,
-     -398, -398, -398, -398, -398, -398, -398, -398, -398, -398,
-     -398, -398, -398, -398, -398, -398, -398, -398, -398, -398,
-     -398, -398, -398, -398, -398, -398,   62, -398,  421,  421,
-      421,  421,  421,  421,  421,  421,  421,  421, -398, -398,
-
-     -398, -398, -398, -398, -398, -398, -398, -398, -398,   65,
-     -398, -398, -398, -398, -398, -398, -398, -398, -398, -398,
-     -398, -398, -398, -398, -398, -398, -398, -398, -398, -398,
-     -398, -398, -398, -398, -398, -398, -398, -398, -398, -398,
-     -398,   65, -398, -398, -398, -398, -398, -398, -398, -398,
-     -398, -398, -398, -398, -398, -398, -398, -398, -398, -398,
-     -398, -398, -398, -398, -398, -398, -398, -398
-    },
-
-    {
-       15, -399, -399, -399, -399, -399, -399, -399, -399, -399,
-     -399, -399, -399, -399, -399, -399, -399, -399, -399, -399,
-     -399, -399, -399, -399, -399, -399, -399, -399, -399, -399,
-
-     -399, -399, -399, -399, -399, -399, -399, -399, -399, -399,
-     -399, -399, -399, -399, -399, -399,   62, -399,  422,  422,
-      422,  422,  422,  422,  422,  422,  422,  422, -399, -399,
-     -399, -399, -399, -399, -399, -399, -399, -399, -399,   65,
-     -399, -399, -399, -399, -399, -399, -399, -399, -399, -399,
-     -399, -399, -399, -399, -399, -399, -399, -399, -399, -399,
-     -399, -399, -399, -399, -399, -399, -399, -399, -399, -399,
-     -399,   65, -399, -399, -399, -399, -399, -399, -399, -399,
-     -399, -399, -399, -399, -399, -399, -399, -399, -399, -399,
-     -399, -399, -399, -399, -399, -399, -399, -399
-
-    },
-
-    {
-       15, -400, -400, -400, -400, -400, -400, -400, -400, -400,
-     -400, -400, -400, -400, -400, -400, -400, -400, -400, -400,
-     -400, -400, -400, -400, -400, -400, -400, -400, -400, -400,
-     -400, -400, -400, -400, -400, -400, -400, -400, -400, -400,
-     -400, -400, -400, -400, -400, -400,   62, -400,  423,  423,
-      423,  423,  423,  423,  423,  423,  423,  423, -400, -400,
-     -400, -400, -400, -400, -400, -400, -400, -400, -400,   65,
-     -400, -400, -400, -400, -400, -400, -400, -400, -400, -400,
-     -400, -400, -400, -400, -400, -400, -400, -400, -400, -400,
-     -400, -400, -400, -400, -400, -400, -400, -400, -400, -400,
-
-     -400,   65, -400, -400, -400, -400, -400, -400, -400, -400,
-     -400, -400, -400, -400, -400, -400, -400, -400, -400, -400,
-     -400, -400, -400, -400, -400, -400, -400, -400
-    },
-
-    {
-       15, -401, -401, -401, -401, -401, -401, -401, -401, -401,
-     -401, -401, -401, -401, -401, -401, -401, -401, -401, -401,
-     -401, -401, -401, -401, -401, -401, -401, -401, -401, -401,
-     -401, -401, -401, -401, -401, -401, -401, -401, -401, -401,
-     -401, -401, -401, -401, -401, -401,   62, -401,  424,  424,
-      424,  424,  424,  424,  424,  424,  424,  424, -401, -401,
-     -401, -401, -401, -401, -401, -401, -401, -401, -401,   65,
-
-     -401, -401, -401, -401, -401, -401, -401, -401, -401, -401,
-     -401, -401, -401, -401, -401, -401, -401, -401, -401, -401,
-     -401, -401, -401, -401, -401, -401, -401, -401, -401, -401,
-     -401,   65, -401, -401, -401, -401, -401, -401, -401, -401,
-     -401, -401, -401, -401, -401, -401, -401, -401, -401, -401,
-     -401, -401, -401, -401, -401, -401, -401, -401
-    },
-
-    {
-       15, -402, -402, -402, -402, -402, -402, -402, -402, -402,
-     -402, -402, -402, -402, -402, -402, -402, -402, -402, -402,
-     -402, -402, -402, -402, -402, -402, -402, -402, -402, -402,
-     -402, -402, -402, -402, -402, -402, -402, -402, -402, -402,
-
-     -402, -402, -402, -402, -402, -402,   62, -402,  425,  425,
-      425,  425,  425,  425,  425,  425,  425,  425, -402, -402,
-     -402, -402, -402, -402, -402, -402, -402, -402, -402,   65,
-     -402, -402, -402, -402, -402, -402, -402, -402, -402, -402,
-     -402, -402, -402, -402, -402, -402, -402, -402, -402, -402,
-     -402, -402, -402, -402, -402, -402, -402, -402, -402, -402,
-     -402,   65, -402, -402, -402, -402, -402, -402, -402, -402,
-     -402, -402, -402, -402, -402, -402, -402, -402, -402, -402,
-     -402, -402, -402, -402, -402, -402, -402, -402
-    },
-
-    {
-       15, -403, -403, -403, -403, -403, -403, -403, -403, -403,
-
-     -403, -403, -403, -403, -403, -403, -403, -403, -403, -403,
-     -403, -403, -403, -403, -403, -403, -403, -403, -403, -403,
-     -403, -403, -403, -403, -403, -403, -403, -403, -403, -403,
-     -403, -403, -403, -403, -403, -403,   62, -403,  426,  426,
-      426,  426,  426,  426,  426,  426,  426,  426, -403, -403,
-     -403, -403, -403, -403, -403, -403, -403, -403, -403,   65,
-     -403, -403, -403, -403, -403, -403, -403, -403, -403, -403,
-     -403, -403, -403, -403, -403, -403, -403, -403, -403, -403,
-     -403, -403, -403, -403, -403, -403, -403, -403, -403, -403,
-     -403,   65, -403, -403, -403, -403, -403, -403, -403, -403,
-
-     -403, -403, -403, -403, -403, -403, -403, -403, -403, -403,
-     -403, -403, -403, -403, -403, -403, -403, -403
-    },
-
-    {
-       15, -404, -404, -404, -404, -404, -404, -404, -404, -404,
-     -404, -404, -404, -404, -404, -404, -404, -404, -404, -404,
-     -404, -404, -404, -404, -404, -404, -404, -404, -404, -404,
-     -404, -404, -404, -404, -404, -404, -404, -404, -404, -404,
-     -404, -404, -404, -404, -404, -404,   62, -404,  427,  427,
-      427,  427,  427,  427,  427,  427,  427,  427, -404, -404,
-     -404, -404, -404, -404, -404, -404, -404, -404, -404,   65,
-     -404, -404, -404, -404, -404, -404, -404, -404, -404, -404,
-
-     -404, -404, -404, -404, -404, -404, -404, -404, -404, -404,
-     -404, -404, -404, -404, -404, -404, -404, -404, -404, -404,
-     -404,   65, -404, -404, -404, -404, -404, -404, -404, -404,
-     -404, -404, -404, -404, -404, -404, -404, -404, -404, -404,
-     -404, -404, -404, -404, -404, -404, -404, -404
-    },
-
-    {
-       15, -405, -405, -405, -405, -405, -405, -405, -405, -405,
-     -405, -405, -405, -405, -405, -405, -405, -405, -405, -405,
-     -405, -405, -405, -405, -405, -405, -405, -405, -405, -405,
-     -405, -405, -405, -405, -405, -405, -405, -405, -405, -405,
-     -405, -405, -405, -405, -405, -405,   62, -405,  428,  428,
-
-      428,  428,  428,  428,  428,  428,  428,  428, -405, -405,
-     -405, -405, -405, -405, -405, -405, -405, -405, -405,   65,
-     -405, -405, -405, -405, -405, -405, -405, -405, -405, -405,
-     -405, -405, -405, -405, -405, -405, -405, -405, -405, -405,
-     -405, -405, -405, -405, -405, -405, -405, -405, -405, -405,
-     -405,   65, -405, -405, -405, -405, -405, -405, -405, -405,
-     -405, -405, -405, -405, -405, -405, -405, -405, -405, -405,
-     -405, -405, -405, -405, -405, -405, -405, -405
-    },
-
-    {
-       15, -406, -406, -406, -406, -406, -406, -406, -406, -406,
-     -406, -406, -406, -406, -406, -406, -406, -406, -406, -406,
-
-     -406, -406, -406, -406, -406, -406, -406, -406, -406, -406,
-     -406, -406, -406, -406, -406, -406, -406, -406, -406, -406,
-     -406, -406, -406, -406, -406, -406,   62, -406,  429,  429,
-      429,  429,  429,  429,  429,  429,  429,  429, -406, -406,
-     -406, -406, -406, -406, -406, -406, -406, -406, -406,   65,
-     -406, -406, -406, -406, -406, -406, -406, -406, -406, -406,
-     -406, -406, -406, -406, -406, -406, -406, -406, -406, -406,
-     -406, -406, -406, -406, -406, -406, -406, -406, -406, -406,
-     -406,   65, -406, -406, -406, -406, -406, -406, -406, -406,
-     -406, -406, -406, -406, -406, -406, -406, -406, -406, -406,
-
-     -406, -406, -406, -406, -406, -406, -406, -406
-    },
-
-    {
-       15, -407, -407, -407, -407, -407, -407, -407, -407, -407,
-     -407, -407, -407, -407, -407, -407, -407, -407, -407, -407,
-     -407, -407, -407, -407, -407, -407, -407, -407, -407, -407,
-     -407, -407, -407, -407, -407, -407, -407, -407, -407, -407,
-     -407, -407, -407, -407, -407, -407,   62, -407,  430,  430,
-      430,  430,  430,  430,  430,  430,  430,  430, -407, -407,
-     -407, -407, -407, -407, -407, -407, -407, -407, -407,   65,
-     -407, -407, -407, -407, -407, -407, -407, -407, -407, -407,
-     -407, -407, -407, -407, -407, -407, -407, -407, -407, -407,
-
-     -407, -407, -407, -407, -407, -407, -407, -407, -407, -407,
-     -407,   65, -407, -407, -407, -407, -407, -407, -407, -407,
-     -407, -407, -407, -407, -407, -407, -407, -407, -407, -407,
-     -407, -407, -407, -407, -407, -407, -407, -407
-    },
-
-    {
-       15, -408, -408, -408, -408, -408, -408, -408, -408, -408,
-     -408, -408, -408, -408, -408, -408, -408, -408, -408, -408,
-     -408, -408, -408, -408, -408, -408, -408, -408, -408, -408,
-     -408, -408,  431, -408, -408, -408, -408, -408, -408, -408,
-     -408, -408, -408, -408, -408, -408, -408, -408, -408, -408,
-     -408, -408, -408, -408, -408, -408, -408, -408, -408, -408,
-
-     -408, -408, -408, -408, -408, -408, -408, -408, -408, -408,
-     -408, -408, -408, -408, -408, -408, -408, -408, -408, -408,
-     -408, -408, -408, -408, -408, -408, -408, -408, -408, -408,
-     -408, -408, -408, -408, -408, -408, -408, -408, -408, -408,
-     -408, -408, -408, -408, -408, -408, -408, -408, -408, -408,
-     -408, -408, -408, -408, -408, -408, -408, -408, -408, -408,
-     -408, -408, -408, -408, -408, -408, -408, -408
-    },
-
-    {
-       15, -409, -409, -409, -409, -409, -409, -409, -409, -409,
-     -409, -409, -409, -409, -409, -409, -409, -409, -409, -409,
-     -409, -409, -409, -409, -409, -409, -409, -409, -409, -409,
-
-     -409, -409,  432, -409, -409, -409, -409, -409, -409, -409,
-     -409, -409, -409, -409, -409, -409, -409, -409, -409, -409,
-     -409, -409, -409, -409, -409, -409, -409, -409, -409, -409,
-     -409, -409, -409, -409, -409, -409, -409, -409, -409, -409,
-     -409, -409, -409, -409, -409, -409, -409, -409, -409, -409,
-     -409, -409, -409, -409, -409, -409, -409, -409, -409, -409,
-     -409, -409, -409, -409, -409, -409, -409, -409, -409, -409,
-     -409, -409, -409, -409, -409, -409, -409, -409, -409, -409,
-     -409, -409, -409, -409, -409, -409, -409, -409, -409, -409,
-     -409, -409, -409, -409, -409, -409, -409, -409
-
-    },
-
-    {
-       15, -410, -410, -410, -410, -410, -410, -410, -410, -410,
-     -410, -410, -410, -410, -410, -410, -410, -410, -410, -410,
-     -410, -410, -410, -410, -410, -410, -410, -410, -410, -410,
-     -410, -410, -410, -410, -410, -410, -410, -410, -410, -410,
-     -410, -410, -410, -410, -410, -410,   62, -410,  410,  411,
-      411,  411,  411,  411,  411,  411,  411,  411, -410, -410,
-     -410, -410, -410, -410, -410, -410, -410, -410, -410,   65,
-     -410, -410, -410, -410, -410, -410, -410, -410, -410, -410,
-     -410, -410, -410, -410, -410, -410, -410, -410, -410, -410,
-     -410, -410, -410, -410, -410, -410, -410, -410, -410, -410,
-
-     -410,   65, -410, -410, -410, -410, -410, -410, -410, -410,
-     -410, -410, -410, -410, -410, -410, -410, -410, -410, -410,
-     -410, -410, -410, -410, -410, -410, -410, -410
-    },
-
-    {
-       15, -411, -411, -411, -411, -411, -411, -411, -411, -411,
-     -411, -411, -411, -411, -411, -411, -411, -411, -411, -411,
-     -411, -411, -411, -411, -411, -411, -411, -411, -411, -411,
-     -411, -411, -411, -411, -411, -411, -411, -411, -411, -411,
-     -411, -411, -411, -411, -411, -411,   62, -411,  412,  412,
-      412,  412,  412,  412,  412,  412,  412,  412, -411, -411,
-     -411, -411, -411, -411, -411, -411, -411, -411, -411,   65,
-
-     -411, -411, -411, -411, -411, -411, -411, -411, -411, -411,
-     -411, -411, -411, -411, -411, -411, -411, -411, -411, -411,
-     -411, -411, -411, -411, -411, -411, -411, -411, -411, -411,
-     -411,   65, -411, -411, -411, -411, -411, -411, -411, -411,
-     -411, -411, -411, -411, -411, -411, -411, -411, -411, -411,
-     -411, -411, -411, -411, -411, -411, -411, -411
-    },
-
-    {
-       15, -412, -412, -412, -412, -412, -412, -412, -412, -412,
-     -412, -412, -412, -412, -412, -412, -412, -412, -412, -412,
-     -412, -412, -412, -412, -412, -412, -412, -412, -412, -412,
-     -412, -412, -412, -412, -412, -412, -412, -412, -412, -412,
-
-     -412, -412, -412, -412, -412, -412,   62, -412,  413,  413,
-      413,  413,  413,  413,  413,  413,  413,  413, -412, -412,
-     -412, -412, -412, -412, -412, -412, -412, -412, -412,   65,
-     -412, -412, -412, -412, -412, -412, -412, -412, -412, -412,
-     -412, -412, -412, -412, -412, -412, -412, -412, -412, -412,
-     -412, -412, -412, -412, -412, -412, -412, -412, -412, -412,
-     -412,   65, -412, -412, -412, -412, -412, -412, -412, -412,
-     -412, -412, -412, -412, -412, -412, -412, -412, -412, -412,
-     -412, -412, -412, -412, -412, -412, -412, -412
-    },
-
-    {
-       15, -413, -413, -413, -413, -413, -413, -413, -413, -413,
-
-     -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
-     -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
-     -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
-     -413, -413, -413, -413, -413, -413,   62, -413,  414,  414,
-      414,  414,  414,  414,  414,  414,  414,  414, -413, -413,
-     -413, -413, -413, -413, -413, -413, -413, -413, -413,   65,
-     -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
-     -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
-     -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
-     -413,   65, -413, -413, -413, -413, -413, -413, -413, -413,
-
-     -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
-     -413, -413, -413, -413, -413, -413, -413, -413
-    },
-
-    {
-       15, -414, -414, -414, -414, -414, -414, -414, -414, -414,
-     -414, -414, -414, -414, -414, -414, -414, -414, -414, -414,
-     -414, -414, -414, -414, -414, -414, -414, -414, -414, -414,
-     -414, -414, -414, -414, -414, -414, -414, -414, -414, -414,
-     -414, -414, -414, -414, -414, -414,   62, -414,  415,  415,
-      415,  415,  415,  415,  415,  415,  415,  415, -414, -414,
-     -414, -414, -414, -414, -414, -414, -414, -414, -414,   65,
-     -414, -414, -414, -414, -414, -414, -414, -414, -414, -414,
-
-     -414, -414, -414, -414, -414, -414, -414, -414, -414, -414,
-     -414, -414, -414, -414, -414, -414, -414, -414, -414, -414,
-     -414,   65, -414, -414, -414, -414, -414, -414, -414, -414,
-     -414, -414, -414, -414, -414, -414, -414, -414, -414, -414,
-     -414, -414, -414, -414, -414, -414, -414, -414
-    },
-
-    {
-       15, -415, -415, -415, -415, -415, -415, -415, -415, -415,
-     -415, -415, -415, -415, -415, -415, -415, -415, -415, -415,
-     -415, -415, -415, -415, -415, -415, -415, -415, -415, -415,
-     -415, -415, -415, -415, -415, -415, -415, -415, -415, -415,
-     -415, -415, -415, -415, -415, -415,   62, -415,  416,  416,
-
-      416,  416,  416,  416,  416,  416,  416,  416, -415, -415,
-     -415, -415, -415, -415, -415, -415, -415, -415, -415,   65,
-     -415, -415, -415, -415, -415, -415, -415, -415, -415, -415,
-     -415, -415, -415, -415, -415, -415, -415, -415, -415, -415,
-     -415, -415, -415, -415, -415, -415, -415, -415, -415, -415,
-     -415,   65, -415, -415, -415, -415, -415, -415, -415, -415,
-     -415, -415, -415, -415, -415, -415, -415, -415, -415, -415,
-     -415, -415, -415, -415, -415, -415, -415, -415
-    },
-
-    {
-       15, -416, -416, -416, -416, -416, -416, -416, -416, -416,
-     -416, -416, -416, -416, -416, -416, -416, -416, -416, -416,
-
-     -416, -416, -416, -416, -416, -416, -416, -416, -416, -416,
-     -416, -416, -416, -416, -416, -416, -416, -416, -416, -416,
-     -416, -416, -416, -416, -416, -416,   62, -416,  417,  417,
-      417,  417,  417,  417,  417,  417,  417,  417, -416, -416,
-     -416, -416, -416, -416, -416, -416, -416, -416, -416,   65,
-     -416, -416, -416, -416, -416, -416, -416, -416, -416, -416,
-     -416, -416, -416, -416, -416, -416, -416, -416, -416, -416,
-     -416, -416, -416, -416, -416, -416, -416, -416, -416, -416,
-     -416,   65, -416, -416, -416, -416, -416, -416, -416, -416,
-     -416, -416, -416, -416, -416, -416, -416, -416, -416, -416,
-
-     -416, -416, -416, -416, -416, -416, -416, -416
-    },
-
-    {
-       15, -417, -417, -417, -417, -417, -417, -417, -417, -417,
-     -417, -417, -417, -417, -417, -417, -417, -417, -417, -417,
-     -417, -417, -417, -417, -417, -417, -417, -417, -417, -417,
-     -417, -417, -417, -417, -417, -417, -417, -417, -417, -417,
-     -417, -417, -417, -417, -417, -417,   62, -417,  418,  418,
-      418,  418,  418,  418,  418,  418,  418,  418, -417, -417,
-     -417, -417, -417, -417, -417, -417, -417, -417, -417,   65,
-     -417, -417, -417, -417, -417, -417, -417, -417, -417, -417,
-     -417, -417, -417, -417, -417, -417, -417, -417, -417, -417,
-
-     -417, -417, -417, -417, -417, -417, -417, -417, -417, -417,
-     -417,   65, -417, -417, -417, -417, -417, -417, -417, -417,
-     -417, -417, -417, -417, -417, -417, -417, -417, -417, -417,
-     -417, -417, -417, -417, -417, -417, -417, -417
-    },
-
-    {
-       15, -418, -418, -418, -418, -418, -418, -418, -418, -418,
-     -418, -418, -418, -418, -418, -418, -418, -418, -418, -418,
-     -418, -418, -418, -418, -418, -418, -418, -418, -418, -418,
-     -418, -418, -418, -418, -418, -418, -418, -418, -418, -418,
-     -418, -418, -418, -418, -418, -418,   62, -418,  419,  419,
-      419,  419,  419,  419,  419,  419,  419,  419, -418, -418,
-
-     -418, -418, -418, -418, -418, -418, -418, -418, -418,   65,
-     -418, -418, -418, -418, -418, -418, -418, -418, -418, -418,
-     -418, -418, -418, -418, -418, -418, -418, -418, -418, -418,
-     -418, -418, -418, -418, -418, -418, -418, -418, -418, -418,
-     -418,   65, -418, -418, -418, -418, -418, -418, -418, -418,
-     -418, -418, -418, -418, -418, -418, -418, -418, -418, -418,
-     -418, -418, -418, -418, -418, -418, -418, -418
-    },
-
-    {
-       15, -419, -419, -419, -419, -419, -419, -419, -419, -419,
-     -419, -419, -419, -419, -419, -419, -419, -419, -419, -419,
-     -419, -419, -419, -419, -419, -419, -419, -419, -419, -419,
-
-     -419, -419, -419, -419, -419, -419, -419, -419, -419, -419,
-     -419, -419, -419, -419, -419, -419,   62, -419,  420,  420,
-      420,  420,  420,  420,  420,  420,  420,  420, -419, -419,
-     -419, -419, -419, -419, -419, -419, -419, -419, -419,   65,
-     -419, -419, -419, -419, -419, -419, -419, -419, -419, -419,
-     -419, -419, -419, -419, -419, -419, -419, -419, -419, -419,
-     -419, -419, -419, -419, -419, -419, -419, -419, -419, -419,
-     -419,   65, -419, -419, -419, -419, -419, -419, -419, -419,
-     -419, -419, -419, -419, -419, -419, -419, -419, -419, -419,
-     -419, -419, -419, -419, -419, -419, -419, -419
-
-    },
-
-    {
-       15, -420, -420, -420, -420, -420, -420, -420, -420, -420,
-     -420, -420, -420, -420, -420, -420, -420, -420, -420, -420,
-     -420, -420, -420, -420, -420, -420, -420, -420, -420, -420,
-     -420, -420, -420, -420, -420, -420, -420, -420, -420, -420,
-     -420, -420, -420, -420, -420, -420,   62, -420,  421,  421,
-      421,  421,  421,  421,  421,  421,  421,  421, -420, -420,
-     -420, -420, -420, -420, -420, -420, -420, -420, -420,   65,
-     -420, -420, -420, -420, -420, -420, -420, -420, -420, -420,
-     -420, -420, -420, -420, -420, -420, -420, -420, -420, -420,
-     -420, -420, -420, -420, -420, -420, -420, -420, -420, -420,
-
-     -420,   65, -420, -420, -420, -420, -420, -420, -420, -420,
-     -420, -420, -420, -420, -420, -420, -420, -420, -420, -420,
-     -420, -420, -420, -420, -420, -420, -420, -420
-    },
-
-    {
-       15, -421, -421, -421, -421, -421, -421, -421, -421, -421,
-     -421, -421, -421, -421, -421, -421, -421, -421, -421, -421,
-     -421, -421, -421, -421, -421, -421, -421, -421, -421, -421,
-     -421, -421, -421, -421, -421, -421, -421, -421, -421, -421,
-     -421, -421, -421, -421, -421, -421,   62, -421,  422,  422,
-      422,  422,  422,  422,  422,  422,  422,  422, -421, -421,
-     -421, -421, -421, -421, -421, -421, -421, -421, -421,   65,
-
-     -421, -421, -421, -421, -421, -421, -421, -421, -421, -421,
-     -421, -421, -421, -421, -421, -421, -421, -421, -421, -421,
-     -421, -421, -421, -421, -421, -421, -421, -421, -421, -421,
-     -421,   65, -421, -421, -421, -421, -421, -421, -421, -421,
-     -421, -421, -421, -421, -421, -421, -421, -421, -421, -421,
-     -421, -421, -421, -421, -421, -421, -421, -421
-    },
-
-    {
-       15, -422, -422, -422, -422, -422, -422, -422, -422, -422,
-     -422, -422, -422, -422, -422, -422, -422, -422, -422, -422,
-     -422, -422, -422, -422, -422, -422, -422, -422, -422, -422,
-     -422, -422, -422, -422, -422, -422, -422, -422, -422, -422,
-
-     -422, -422, -422, -422, -422, -422,   62, -422,  423,  423,
-      423,  423,  423,  423,  423,  423,  423,  423, -422, -422,
-     -422, -422, -422, -422, -422, -422, -422, -422, -422,   65,
-     -422, -422, -422, -422, -422, -422, -422, -422, -422, -422,
-     -422, -422, -422, -422, -422, -422, -422, -422, -422, -422,
-     -422, -422, -422, -422, -422, -422, -422, -422, -422, -422,
-     -422,   65, -422, -422, -422, -422, -422, -422, -422, -422,
-     -422, -422, -422, -422, -422, -422, -422, -422, -422, -422,
-     -422, -422, -422, -422, -422, -422, -422, -422
-    },
-
-    {
-       15, -423, -423, -423, -423, -423, -423, -423, -423, -423,
-
-     -423, -423, -423, -423, -423, -423, -423, -423, -423, -423,
-     -423, -423, -423, -423, -423, -423, -423, -423, -423, -423,
-     -423, -423, -423, -423, -423, -423, -423, -423, -423, -423,
-     -423, -423, -423, -423, -423, -423,   62, -423,  424,  424,
-      424,  424,  424,  424,  424,  424,  424,  424, -423, -423,
-     -423, -423, -423, -423, -423, -423, -423, -423, -423,   65,
-     -423, -423, -423, -423, -423, -423, -423, -423, -423, -423,
-     -423, -423, -423, -423, -423, -423, -423, -423, -423, -423,
-     -423, -423, -423, -423, -423, -423, -423, -423, -423, -423,
-     -423,   65, -423, -423, -423, -423, -423, -423, -423, -423,
-
-     -423, -423, -423, -423, -423, -423, -423, -423, -423, -423,
-     -423, -423, -423, -423, -423, -423, -423, -423
-    },
-
-    {
-       15, -424, -424, -424, -424, -424, -424, -424, -424, -424,
-     -424, -424, -424, -424, -424, -424, -424, -424, -424, -424,
-     -424, -424, -424, -424, -424, -424, -424, -424, -424, -424,
-     -424, -424, -424, -424, -424, -424, -424, -424, -424, -424,
-     -424, -424, -424, -424, -424, -424,   62, -424,  425,  425,
-      425,  425,  425,  425,  425,  425,  425,  425, -424, -424,
-     -424, -424, -424, -424, -424, -424, -424, -424, -424,   65,
-     -424, -424, -424, -424, -424, -424, -424, -424, -424, -424,
-
-     -424, -424, -424, -424, -424, -424, -424, -424, -424, -424,
-     -424, -424, -424, -424, -424, -424, -424, -424, -424, -424,
-     -424,   65, -424, -424, -424, -424, -424, -424, -424, -424,
-     -424, -424, -424, -424, -424, -424, -424, -424, -424, -424,
-     -424, -424, -424, -424, -424, -424, -424, -424
-    },
-
-    {
-       15, -425, -425, -425, -425, -425, -425, -425, -425, -425,
-     -425, -425, -425, -425, -425, -425, -425, -425, -425, -425,
-     -425, -425, -425, -425, -425, -425, -425, -425, -425, -425,
-     -425, -425, -425, -425, -425, -425, -425, -425, -425, -425,
-     -425, -425, -425, -425, -425, -425,   62, -425,  426,  426,
-
-      426,  426,  426,  426,  426,  426,  426,  426, -425, -425,
-     -425, -425, -425, -425, -425, -425, -425, -425, -425,   65,
-     -425, -425, -425, -425, -425, -425, -425, -425, -425, -425,
-     -425, -425, -425, -425, -425, -425, -425, -425, -425, -425,
-     -425, -425, -425, -425, -425, -425, -425, -425, -425, -425,
-     -425,   65, -425, -425, -425, -425, -425, -425, -425, -425,
-     -425, -425, -425, -425, -425, -425, -425, -425, -425, -425,
-     -425, -425, -425, -425, -425, -425, -425, -425
-    },
-
-    {
-       15, -426, -426, -426, -426, -426, -426, -426, -426, -426,
-     -426, -426, -426, -426, -426, -426, -426, -426, -426, -426,
-
-     -426, -426, -426, -426, -426, -426, -426, -426, -426, -426,
-     -426, -426, -426, -426, -426, -426, -426, -426, -426, -426,
-     -426, -426, -426, -426, -426, -426,   62, -426,  427,  427,
-      427,  427,  427,  427,  427,  427,  427,  427, -426, -426,
-     -426, -426, -426, -426, -426, -426, -426, -426, -426,   65,
-     -426, -426, -426, -426, -426, -426, -426, -426, -426, -426,
-     -426, -426, -426, -426, -426, -426, -426, -426, -426, -426,
-     -426, -426, -426, -426, -426, -426, -426, -426, -426, -426,
-     -426,   65, -426, -426, -426, -426, -426, -426, -426, -426,
-     -426, -426, -426, -426, -426, -426, -426, -426, -426, -426,
-
-     -426, -426, -426, -426, -426, -426, -426, -426
-    },
-
-    {
-       15, -427, -427, -427, -427, -427, -427, -427, -427, -427,
-     -427, -427, -427, -427, -427, -427, -427, -427, -427, -427,
-     -427, -427, -427, -427, -427, -427, -427, -427, -427, -427,
-     -427, -427, -427, -427, -427, -427, -427, -427, -427, -427,
-     -427, -427, -427, -427, -427, -427,   62, -427,  428,  428,
-      428,  428,  428,  428,  428,  428,  428,  428, -427, -427,
-     -427, -427, -427, -427, -427, -427, -427, -427, -427,   65,
-     -427, -427, -427, -427, -427, -427, -427, -427, -427, -427,
-     -427, -427, -427, -427, -427, -427, -427, -427, -427, -427,
-
-     -427, -427, -427, -427, -427, -427, -427, -427, -427, -427,
-     -427,   65, -427, -427, -427, -427, -427, -427, -427, -427,
-     -427, -427, -427, -427, -427, -427, -427, -427, -427, -427,
-     -427, -427, -427, -427, -427, -427, -427, -427
-    },
-
-    {
-       15, -428, -428, -428, -428, -428, -428, -428, -428, -428,
-     -428, -428, -428, -428, -428, -428, -428, -428, -428, -428,
-     -428, -428, -428, -428, -428, -428, -428, -428, -428, -428,
-     -428, -428, -428, -428, -428, -428, -428, -428, -428, -428,
-     -428, -428, -428, -428, -428, -428,   62, -428,  429,  429,
-      429,  429,  429,  429,  429,  429,  429,  429, -428, -428,
-
-     -428, -428, -428, -428, -428, -428, -428, -428, -428,   65,
-     -428, -428, -428, -428, -428, -428, -428, -428, -428, -428,
-     -428, -428, -428, -428, -428, -428, -428, -428, -428, -428,
-     -428, -428, -428, -428, -428, -428, -428, -428, -428, -428,
-     -428,   65, -428, -428, -428, -428, -428, -428, -428, -428,
-     -428, -428, -428, -428, -428, -428, -428, -428, -428, -428,
-     -428, -428, -428, -428, -428, -428, -428, -428
-    },
-
-    {
-       15, -429, -429, -429, -429, -429, -429, -429, -429, -429,
-     -429, -429, -429, -429, -429, -429, -429, -429, -429, -429,
-     -429, -429, -429, -429, -429, -429, -429, -429, -429, -429,
-
-     -429, -429, -429, -429, -429, -429, -429, -429, -429, -429,
-     -429, -429, -429, -429, -429, -429,   62, -429,  430,  430,
-      430,  430,  430,  430,  430,  430,  430,  430, -429, -429,
-     -429, -429, -429, -429, -429, -429, -429, -429, -429,   65,
-     -429, -429, -429, -429, -429, -429, -429, -429, -429, -429,
-     -429, -429, -429, -429, -429, -429, -429, -429, -429, -429,
-     -429, -429, -429, -429, -429, -429, -429, -429, -429, -429,
-     -429,   65, -429, -429, -429, -429, -429, -429, -429, -429,
-     -429, -429, -429, -429, -429, -429, -429, -429, -429, -429,
-     -429, -429, -429, -429, -429, -429, -429, -429
-
-    },
-
-    {
-       15, -430, -430, -430, -430, -430, -430, -430, -430, -430,
-     -430, -430, -430, -430, -430, -430, -430, -430, -430, -430,
-     -430, -430, -430, -430, -430, -430, -430, -430, -430, -430,
-     -430, -430, -430, -430, -430, -430, -430, -430, -430, -430,
-     -430, -430, -430, -430, -430, -430,   62, -430,  430,  430,
-      430,  430,  430,  430,  430,  430,  430,  430, -430, -430,
-     -430, -430, -430, -430, -430, -430, -430, -430, -430,   65,
-     -430, -430, -430, -430, -430, -430, -430, -430, -430, -430,
-     -430, -430, -430, -430, -430, -430, -430, -430, -430, -430,
-     -430, -430, -430, -430, -430, -430, -430, -430, -430, -430,
-
-     -430,   65, -430, -430, -430, -430, -430, -430, -430, -430,
-     -430, -430, -430, -430, -430, -430, -430, -430, -430, -430,
-     -430, -430, -430, -430, -430, -430, -430, -430
-    },
-
-    {
-       15, -431, -431, -431, -431, -431, -431, -431, -431, -431,
-     -431, -431, -431, -431, -431, -431, -431, -431, -431, -431,
-     -431, -431, -431, -431, -431, -431, -431, -431, -431, -431,
-     -431, -431,  433, -431, -431, -431, -431, -431, -431, -431,
-     -431, -431, -431, -431, -431, -431, -431, -431, -431, -431,
-     -431, -431, -431, -431, -431, -431, -431, -431, -431, -431,
-     -431, -431, -431, -431, -431, -431, -431, -431, -431, -431,
-
-     -431, -431, -431, -431, -431, -431, -431, -431, -431, -431,
-     -431, -431, -431, -431, -431, -431, -431, -431, -431, -431,
-     -431, -431, -431, -431, -431, -431, -431, -431, -431, -431,
-     -431, -431, -431, -431, -431, -431, -431, -431, -431, -431,
-     -431, -431, -431, -431, -431, -431, -431, -431, -431, -431,
-     -431, -431, -431, -431, -431, -431, -431, -431
-    },
-
-    {
-       15, -432, -432, -432, -432, -432, -432, -432, -432, -432,
-     -432, -432, -432, -432, -432, -432, -432, -432, -432, -432,
-     -432, -432, -432, -432, -432, -432, -432, -432, -432, -432,
-     -432, -432,  434, -432, -432, -432, -432, -432, -432, -432,
-
-     -432, -432, -432, -432, -432, -432, -432, -432, -432, -432,
-     -432, -432, -432, -432, -432, -432, -432, -432, -432, -432,
-     -432, -432, -432, -432, -432, -432, -432, -432, -432, -432,
-     -432, -432, -432, -432, -432, -432, -432, -432, -432, -432,
-     -432, -432, -432, -432, -432, -432, -432, -432, -432, -432,
-     -432, -432, -432, -432, -432, -432, -432, -432, -432, -432,
-     -432, -432, -432, -432, -432, -432, -432, -432, -432, -432,
-     -432, -432, -432, -432, -432, -432, -432, -432, -432, -432,
-     -432, -432, -432, -432, -432, -432, -432, -432
-    },
-
-    {
-       15, -433, -433, -433, -433, -433, -433, -433, -433, -433,
-
-     -433, -433, -433, -433, -433, -433, -433, -433, -433, -433,
-     -433, -433, -433, -433, -433, -433, -433, -433, -433, -433,
-     -433, -433,  435, -433, -433, -433, -433, -433, -433, -433,
-     -433, -433, -433, -433, -433, -433, -433, -433, -433, -433,
-     -433, -433, -433, -433, -433, -433, -433, -433, -433, -433,
-     -433, -433, -433, -433, -433, -433, -433, -433, -433, -433,
-     -433, -433, -433, -433, -433, -433, -433, -433, -433, -433,
-     -433, -433, -433, -433, -433, -433, -433, -433, -433, -433,
-     -433, -433, -433, -433, -433, -433, -433, -433, -433, -433,
-     -433, -433, -433, -433, -433, -433, -433, -433, -433, -433,
-
-     -433, -433, -433, -433, -433, -433, -433, -433, -433, -433,
-     -433, -433, -433, -433, -433, -433, -433, -433
-    },
-
-    {
-       15, -434, -434, -434, -434, -434, -434, -434, -434, -434,
-     -434, -434, -434, -434, -434, -434, -434, -434, -434, -434,
-     -434, -434, -434, -434, -434, -434, -434, -434, -434, -434,
-     -434, -434,  436, -434, -434, -434, -434, -434, -434, -434,
-     -434, -434, -434, -434, -434, -434, -434, -434, -434, -434,
-     -434, -434, -434, -434, -434, -434, -434, -434, -434, -434,
-     -434, -434, -434, -434, -434, -434, -434, -434, -434, -434,
-     -434, -434, -434, -434, -434, -434, -434, -434, -434, -434,
-
-     -434, -434, -434, -434, -434, -434, -434, -434, -434, -434,
-     -434, -434, -434, -434, -434, -434, -434, -434, -434, -434,
-     -434, -434, -434, -434, -434, -434, -434, -434, -434, -434,
-     -434, -434, -434, -434, -434, -434, -434, -434, -434, -434,
-     -434, -434, -434, -434, -434, -434, -434, -434
-    },
-
-    {
-       15, -435, -435, -435, -435, -435, -435, -435, -435, -435,
-     -435, -435, -435, -435, -435, -435, -435, -435, -435, -435,
-     -435, -435, -435, -435, -435, -435, -435, -435, -435, -435,
-     -435, -435,  437, -435, -435, -435, -435, -435, -435, -435,
-     -435, -435, -435, -435, -435, -435, -435, -435, -435, -435,
-
-     -435, -435, -435, -435, -435, -435, -435, -435, -435, -435,
-     -435, -435, -435, -435, -435, -435, -435, -435, -435, -435,
-     -435, -435, -435, -435, -435, -435, -435, -435, -435, -435,
-     -435, -435, -435, -435, -435, -435, -435, -435, -435, -435,
-     -435, -435, -435, -435, -435, -435, -435, -435, -435, -435,
-     -435, -435, -435, -435, -435, -435, -435, -435, -435, -435,
-     -435, -435, -435, -435, -435, -435, -435, -435, -435, -435,
-     -435, -435, -435, -435, -435, -435, -435, -435
-    },
-
-    {
-       15, -436, -436, -436, -436, -436, -436, -436, -436, -436,
-     -436, -436, -436, -436, -436, -436, -436, -436, -436, -436,
-
-     -436, -436, -436, -436, -436, -436, -436, -436, -436, -436,
-     -436, -436,  438, -436, -436, -436, -436, -436, -436, -436,
-     -436, -436, -436, -436, -436, -436, -436, -436, -436, -436,
-     -436, -436, -436, -436, -436, -436, -436, -436, -436, -436,
-     -436, -436, -436, -436, -436, -436, -436, -436, -436, -436,
-     -436, -436, -436, -436, -436, -436, -436, -436, -436, -436,
-     -436, -436, -436, -436, -436, -436, -436, -436, -436, -436,
-     -436, -436, -436, -436, -436, -436, -436, -436, -436, -436,
-     -436, -436, -436, -436, -436, -436, -436, -436, -436, -436,
-     -436, -436, -436, -436, -436, -436, -436, -436, -436, -436,
-
-     -436, -436, -436, -436, -436, -436, -436, -436
-    },
-
-    {
-       15, -437, -437, -437, -437, -437, -437, -437, -437, -437,
-     -437, -437, -437, -437, -437, -437, -437, -437, -437, -437,
-     -437, -437, -437, -437, -437, -437, -437, -437, -437, -437,
-     -437, -437,  439, -437, -437, -437, -437, -437, -437, -437,
-     -437, -437, -437, -437, -437, -437, -437, -437, -437, -437,
-     -437, -437, -437, -437, -437, -437, -437, -437, -437, -437,
-     -437, -437, -437, -437, -437, -437, -437, -437, -437, -437,
-     -437, -437, -437, -437, -437, -437, -437, -437, -437, -437,
-     -437, -437, -437, -437, -437, -437, -437, -437, -437, -437,
-
-     -437, -437, -437, -437, -437, -437, -437, -437, -437, -437,
-     -437, -437, -437, -437, -437, -437, -437, -437, -437, -437,
-     -437, -437, -437, -437, -437, -437, -437, -437, -437, -437,
-     -437, -437, -437, -437, -437, -437, -437, -437
-    },
-
-    {
-       15, -438, -438, -438, -438, -438, -438, -438, -438, -438,
-     -438, -438, -438, -438, -438, -438, -438, -438, -438, -438,
-     -438, -438, -438, -438, -438, -438, -438, -438, -438, -438,
-     -438, -438,  440, -438, -438, -438, -438, -438, -438, -438,
-     -438, -438, -438, -438, -438, -438, -438, -438, -438, -438,
-     -438, -438, -438, -438, -438, -438, -438, -438, -438, -438,
-
-     -438, -438, -438, -438, -438, -438, -438, -438, -438, -438,
-     -438, -438, -438, -438, -438, -438, -438, -438, -438, -438,
-     -438, -438, -438, -438, -438, -438, -438, -438, -438, -438,
-     -438, -438, -438, -438, -438, -438, -438, -438, -438, -438,
-     -438, -438, -438, -438, -438, -438, -438, -438, -438, -438,
-     -438, -438, -438, -438, -438, -438, -438, -438, -438, -438,
-     -438, -438, -438, -438, -438, -438, -438, -438
-    },
-
-    {
-       15, -439, -439, -439, -439, -439, -439, -439, -439, -439,
-     -439, -439, -439, -439, -439, -439, -439, -439, -439, -439,
-     -439, -439, -439, -439, -439, -439, -439, -439, -439, -439,
-
-     -439, -439,  441, -439, -439, -439, -439, -439, -439, -439,
-     -439, -439, -439, -439, -439, -439, -439, -439, -439, -439,
-     -439, -439, -439, -439, -439, -439, -439, -439, -439, -439,
-     -439, -439, -439, -439, -439, -439, -439, -439, -439, -439,
-     -439, -439, -439, -439, -439, -439, -439, -439, -439, -439,
-     -439, -439, -439, -439, -439, -439, -439, -439, -439, -439,
-     -439, -439, -439, -439, -439, -439, -439, -439, -439, -439,
-     -439, -439, -439, -439, -439, -439, -439, -439, -439, -439,
-     -439, -439, -439, -439, -439, -439, -439, -439, -439, -439,
-     -439, -439, -439, -439, -439, -439, -439, -439
-
-    },
-
-    {
-       15, -440, -440, -440, -440, -440, -440, -440, -440, -440,
-     -440, -440, -440, -440, -440, -440, -440, -440, -440, -440,
-     -440, -440, -440, -440, -440, -440, -440, -440, -440, -440,
-     -440, -440,  442, -440, -440, -440, -440, -440, -440, -440,
-     -440, -440, -440, -440, -440, -440, -440, -440, -440, -440,
-     -440, -440, -440, -440, -440, -440, -440, -440, -440, -440,
-     -440, -440, -440, -440, -440, -440, -440, -440, -440, -440,
-     -440, -440, -440, -440, -440, -440, -440, -440, -440, -440,
-     -440, -440, -440, -440, -440, -440, -440, -440, -440, -440,
-     -440, -440, -440, -440, -440, -440, -440, -440, -440, -440,
-
-     -440, -440, -440, -440, -440, -440, -440, -440, -440, -440,
-     -440, -440, -440, -440, -440, -440, -440, -440, -440, -440,
-     -440, -440, -440, -440, -440, -440, -440, -440
-    },
-
-    {
-       15, -441, -441, -441, -441, -441, -441, -441, -441, -441,
-     -441, -441, -441, -441, -441, -441, -441, -441, -441, -441,
-     -441, -441, -441, -441, -441, -441, -441, -441, -441, -441,
-     -441, -441,  443, -441, -441, -441, -441, -441, -441, -441,
-     -441, -441, -441, -441, -441, -441, -441, -441, -441, -441,
-     -441, -441, -441, -441, -441, -441, -441, -441, -441, -441,
-     -441, -441, -441, -441, -441, -441, -441, -441, -441, -441,
-
-     -441, -441, -441, -441, -441, -441, -441, -441, -441, -441,
-     -441, -441, -441, -441, -441, -441, -441, -441, -441, -441,
-     -441, -441, -441, -441, -441, -441, -441, -441, -441, -441,
-     -441, -441, -441, -441, -441, -441, -441, -441, -441, -441,
-     -441, -441, -441, -441, -441, -441, -441, -441, -441, -441,
-     -441, -441, -441, -441, -441, -441, -441, -441
-    },
-
-    {
-       15, -442, -442, -442, -442, -442, -442, -442, -442, -442,
-     -442, -442, -442, -442, -442, -442, -442, -442, -442, -442,
-     -442, -442, -442, -442, -442, -442, -442, -442, -442, -442,
-     -442, -442,  444, -442, -442, -442, -442, -442, -442, -442,
-
-     -442, -442, -442, -442, -442, -442, -442, -442, -442, -442,
-     -442, -442, -442, -442, -442, -442, -442, -442, -442, -442,
-     -442, -442, -442, -442, -442, -442, -442, -442, -442, -442,
-     -442, -442, -442, -442, -442, -442, -442, -442, -442, -442,
-     -442, -442, -442, -442, -442, -442, -442, -442, -442, -442,
-     -442, -442, -442, -442, -442, -442, -442, -442, -442, -442,
-     -442, -442, -442, -442, -442, -442, -442, -442, -442, -442,
-     -442, -442, -442, -442, -442, -442, -442, -442, -442, -442,
-     -442, -442, -442, -442, -442, -442, -442, -442
-    },
-
-    {
-       15, -443, -443, -443, -443, -443, -443, -443, -443, -443,
-
-     -443, -443, -443, -443, -443, -443, -443, -443, -443, -443,
-     -443, -443, -443, -443, -443, -443, -443, -443, -443, -443,
-     -443, -443,  445, -443, -443, -443, -443, -443, -443, -443,
-     -443, -443, -443, -443, -443, -443, -443, -443, -443, -443,
-     -443, -443, -443, -443, -443, -443, -443, -443, -443, -443,
-     -443, -443, -443, -443, -443, -443, -443, -443, -443, -443,
-     -443, -443, -443, -443, -443, -443, -443, -443, -443, -443,
-     -443, -443, -443, -443, -443, -443, -443, -443, -443, -443,
-     -443, -443, -443, -443, -443, -443, -443, -443, -443, -443,
-     -443, -443, -443, -443, -443, -443, -443, -443, -443, -443,
-
-     -443, -443, -443, -443, -443, -443, -443, -443, -443, -443,
-     -443, -443, -443, -443, -443, -443, -443, -443
-    },
-
-    {
-       15, -444, -444, -444, -444, -444, -444, -444, -444, -444,
-     -444, -444, -444, -444, -444, -444, -444, -444, -444, -444,
-     -444, -444, -444, -444, -444, -444, -444, -444, -444, -444,
-     -444, -444,  446, -444, -444, -444, -444, -444, -444, -444,
-     -444, -444, -444, -444, -444, -444, -444, -444, -444, -444,
-     -444, -444, -444, -444, -444, -444, -444, -444, -444, -444,
-     -444, -444, -444, -444, -444, -444, -444, -444, -444, -444,
-     -444, -444, -444, -444, -444, -444, -444, -444, -444, -444,
-
-     -444, -444, -444, -444, -444, -444, -444, -444, -444, -444,
-     -444, -444, -444, -444, -444, -444, -444, -444, -444, -444,
-     -444, -444, -444, -444, -444, -444, -444, -444, -444, -444,
-     -444, -444, -444, -444, -444, -444, -444, -444, -444, -444,
-     -444, -444, -444, -444, -444, -444, -444, -444
-    },
-
-    {
-       15, -445, -445, -445, -445, -445, -445, -445, -445, -445,
-     -445, -445, -445, -445, -445, -445, -445, -445, -445, -445,
-     -445, -445, -445, -445, -445, -445, -445, -445, -445, -445,
-     -445, -445,  447, -445, -445, -445, -445, -445, -445, -445,
-     -445, -445, -445, -445, -445, -445, -445, -445, -445, -445,
-
-     -445, -445, -445, -445, -445, -445, -445, -445, -445, -445,
-     -445, -445, -445, -445, -445, -445, -445, -445, -445, -445,
-     -445, -445, -445, -445, -445, -445, -445, -445, -445, -445,
-     -445, -445, -445, -445, -445, -445, -445, -445, -445, -445,
-     -445, -445, -445, -445, -445, -445, -445, -445, -445, -445,
-     -445, -445, -445, -445, -445, -445, -445, -445, -445, -445,
-     -445, -445, -445, -445, -445, -445, -445, -445, -445, -445,
-     -445, -445, -445, -445, -445, -445, -445, -445
-    },
-
-    {
-       15, -446, -446, -446, -446, -446, -446, -446, -446, -446,
-     -446, -446, -446, -446, -446, -446, -446, -446, -446, -446,
-
-     -446, -446, -446, -446, -446, -446, -446, -446, -446, -446,
-     -446, -446,  448, -446, -446, -446, -446, -446, -446, -446,
-     -446, -446, -446, -446, -446, -446, -446, -446, -446, -446,
-     -446, -446, -446, -446, -446, -446, -446, -446, -446, -446,
-     -446, -446, -446, -446, -446, -446, -446, -446, -446, -446,
-     -446, -446, -446, -446, -446, -446, -446, -446, -446, -446,
-     -446, -446, -446, -446, -446, -446, -446, -446, -446, -446,
-     -446, -446, -446, -446, -446, -446, -446, -446, -446, -446,
-     -446, -446, -446, -446, -446, -446, -446, -446, -446, -446,
-     -446, -446, -446, -446, -446, -446, -446, -446, -446, -446,
-
-     -446, -446, -446, -446, -446, -446, -446, -446
-    },
-
-    {
-       15, -447, -447, -447, -447, -447, -447, -447, -447, -447,
-     -447, -447, -447, -447, -447, -447, -447, -447, -447, -447,
-     -447, -447, -447, -447, -447, -447, -447, -447, -447, -447,
-     -447, -447,  449, -447, -447, -447, -447, -447, -447, -447,
-     -447, -447, -447, -447, -447, -447, -447, -447, -447, -447,
-     -447, -447, -447, -447, -447, -447, -447, -447, -447, -447,
-     -447, -447, -447, -447, -447, -447, -447, -447, -447, -447,
-     -447, -447, -447, -447, -447, -447, -447, -447, -447, -447,
-     -447, -447, -447, -447, -447, -447, -447, -447, -447, -447,
-
-     -447, -447, -447, -447, -447, -447, -447, -447, -447, -447,
-     -447, -447, -447, -447, -447, -447, -447, -447, -447, -447,
-     -447, -447, -447, -447, -447, -447, -447, -447, -447, -447,
-     -447, -447, -447, -447, -447, -447, -447, -447
-    },
-
-    {
-       15, -448, -448, -448, -448, -448, -448, -448, -448, -448,
-     -448, -448, -448, -448, -448, -448, -448, -448, -448, -448,
-     -448, -448, -448, -448, -448, -448, -448, -448, -448, -448,
-     -448, -448,  450, -448, -448, -448, -448, -448, -448, -448,
-     -448, -448, -448, -448, -448, -448, -448, -448, -448, -448,
-     -448, -448, -448, -448, -448, -448, -448, -448, -448, -448,
-
-     -448, -448, -448, -448, -448, -448, -448, -448, -448, -448,
-     -448, -448, -448, -448, -448, -448, -448, -448, -448, -448,
-     -448, -448, -448, -448, -448, -448, -448, -448, -448, -448,
-     -448, -448, -448, -448, -448, -448, -448, -448, -448, -448,
-     -448, -448, -448, -448, -448, -448, -448, -448, -448, -448,
-     -448, -448, -448, -448, -448, -448, -448, -448, -448, -448,
-     -448, -448, -448, -448, -448, -448, -448, -448
-    },
-
-    {
-       15, -449, -449, -449, -449, -449, -449, -449, -449, -449,
-     -449, -449, -449, -449, -449, -449, -449, -449, -449, -449,
-     -449, -449, -449, -449, -449, -449, -449, -449, -449, -449,
-
-     -449, -449,  451, -449, -449, -449, -449, -449, -449, -449,
-     -449, -449, -449, -449, -449, -449, -449, -449, -449, -449,
-     -449, -449, -449, -449, -449, -449, -449, -449, -449, -449,
-     -449, -449, -449, -449, -449, -449, -449, -449, -449, -449,
-     -449, -449, -449, -449, -449, -449, -449, -449, -449, -449,
-     -449, -449, -449, -449, -449, -449, -449, -449, -449, -449,
-     -449, -449, -449, -449, -449, -449, -449, -449, -449, -449,
-     -449, -449, -449, -449, -449, -449, -449, -449, -449, -449,
-     -449, -449, -449, -449, -449, -449, -449, -449, -449, -449,
-     -449, -449, -449, -449, -449, -449, -449, -449
-
-    },
-
-    {
-       15, -450, -450, -450, -450, -450, -450, -450, -450, -450,
-     -450, -450, -450, -450, -450, -450, -450, -450, -450, -450,
-     -450, -450, -450, -450, -450, -450, -450, -450, -450, -450,
-     -450, -450,  452, -450, -450, -450, -450, -450, -450, -450,
-     -450, -450, -450, -450, -450, -450, -450, -450, -450, -450,
-     -450, -450, -450, -450, -450, -450, -450, -450, -450, -450,
-     -450, -450, -450, -450, -450, -450, -450, -450, -450, -450,
-     -450, -450, -450, -450, -450, -450, -450, -450, -450, -450,
-     -450, -450, -450, -450, -450, -450, -450, -450, -450, -450,
-     -450, -450, -450, -450, -450, -450, -450, -450, -450, -450,
-
-     -450, -450, -450, -450, -450, -450, -450, -450, -450, -450,
-     -450, -450, -450, -450, -450, -450, -450, -450, -450, -450,
-     -450, -450, -450, -450, -450, -450, -450, -450
-    },
-
-    {
-       15, -451, -451, -451, -451, -451, -451, -451, -451, -451,
-     -451, -451, -451, -451, -451, -451, -451, -451, -451, -451,
-     -451, -451, -451, -451, -451, -451, -451, -451, -451, -451,
-     -451, -451,  453, -451, -451, -451, -451, -451, -451, -451,
-     -451, -451, -451, -451, -451, -451, -451, -451, -451, -451,
-     -451, -451, -451, -451, -451, -451, -451, -451, -451, -451,
-     -451, -451, -451, -451, -451, -451, -451, -451, -451, -451,
-
-     -451, -451, -451, -451, -451, -451, -451, -451, -451, -451,
-     -451, -451, -451, -451, -451, -451, -451, -451, -451, -451,
-     -451, -451, -451, -451, -451, -451, -451, -451, -451, -451,
-     -451, -451, -451, -451, -451, -451, -451, -451, -451, -451,
-     -451, -451, -451, -451, -451, -451, -451, -451, -451, -451,
-     -451, -451, -451, -451, -451, -451, -451, -451
-    },
-
-    {
-       15, -452, -452, -452, -452, -452, -452, -452, -452, -452,
-     -452, -452, -452, -452, -452, -452, -452, -452, -452, -452,
-     -452, -452, -452, -452, -452, -452, -452, -452, -452, -452,
-     -452, -452,  454, -452, -452, -452, -452, -452, -452, -452,
-
-     -452, -452, -452, -452, -452, -452, -452, -452, -452, -452,
-     -452, -452, -452, -452, -452, -452, -452, -452, -452, -452,
-     -452, -452, -452, -452, -452, -452, -452, -452, -452, -452,
-     -452, -452, -452, -452, -452, -452, -452, -452, -452, -452,
-     -452, -452, -452, -452, -452, -452, -452, -452, -452, -452,
-     -452, -452, -452, -452, -452, -452, -452, -452, -452, -452,
-     -452, -452, -452, -452, -452, -452, -452, -452, -452, -452,
-     -452, -452, -452, -452, -452, -452, -452, -452, -452, -452,
-     -452, -452, -452, -452, -452, -452, -452, -452
-    },
-
-    {
-       15, -453, -453, -453, -453, -453, -453, -453, -453, -453,
-
-     -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
-     -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
-     -453, -453,  455, -453, -453, -453, -453, -453, -453, -453,
-     -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
-     -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
-     -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
-     -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
-     -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
-     -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
-     -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
-
-     -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
-     -453, -453, -453, -453, -453, -453, -453, -453
-    },
-
-    {
-       15, -454, -454, -454, -454, -454, -454, -454, -454, -454,
-     -454, -454, -454, -454, -454, -454, -454, -454, -454, -454,
-     -454, -454, -454, -454, -454, -454, -454, -454, -454, -454,
-     -454, -454,  456, -454, -454, -454, -454, -454, -454, -454,
-     -454, -454, -454, -454, -454, -454, -454, -454, -454, -454,
-     -454, -454, -454, -454, -454, -454, -454, -454, -454, -454,
-     -454, -454, -454, -454, -454, -454, -454, -454, -454, -454,
-     -454, -454, -454, -454, -454, -454, -454, -454, -454, -454,
-
-     -454, -454, -454, -454, -454, -454, -454, -454, -454, -454,
-     -454, -454, -454, -454, -454, -454, -454, -454, -454, -454,
-     -454, -454, -454, -454, -454, -454, -454, -454, -454, -454,
-     -454, -454, -454, -454, -454, -454, -454, -454, -454, -454,
-     -454, -454, -454, -454, -454, -454, -454, -454
-    },
-
-    {
-       15, -455, -455, -455, -455, -455, -455, -455, -455, -455,
-     -455, -455, -455, -455, -455, -455, -455, -455, -455, -455,
-     -455, -455, -455, -455, -455, -455, -455, -455, -455, -455,
-     -455, -455,  457, -455, -455, -455, -455, -455, -455, -455,
-     -455, -455, -455, -455, -455, -455, -455, -455, -455, -455,
-
-     -455, -455, -455, -455, -455, -455, -455, -455, -455, -455,
-     -455, -455, -455, -455, -455, -455, -455, -455, -455, -455,
-     -455, -455, -455, -455, -455, -455, -455, -455, -455, -455,
-     -455, -455, -455, -455, -455, -455, -455, -455, -455, -455,
-     -455, -455, -455, -455, -455, -455, -455, -455, -455, -455,
-     -455, -455, -455, -455, -455, -455, -455, -455, -455, -455,
-     -455, -455, -455, -455, -455, -455, -455, -455, -455, -455,
-     -455, -455, -455, -455, -455, -455, -455, -455
-    },
-
-    {
-       15, -456, -456, -456, -456, -456, -456, -456, -456, -456,
-     -456, -456, -456, -456, -456, -456, -456, -456, -456, -456,
-
-     -456, -456, -456, -456, -456, -456, -456, -456, -456, -456,
-     -456, -456,  458, -456, -456, -456, -456, -456, -456, -456,
-     -456, -456, -456, -456, -456, -456, -456, -456, -456, -456,
-     -456, -456, -456, -456, -456, -456, -456, -456, -456, -456,
-     -456, -456, -456, -456, -456, -456, -456, -456, -456, -456,
-     -456, -456, -456, -456, -456, -456, -456, -456, -456, -456,
-     -456, -456, -456, -456, -456, -456, -456, -456, -456, -456,
-     -456, -456, -456, -456, -456, -456, -456, -456, -456, -456,
-     -456, -456, -456, -456, -456, -456, -456, -456, -456, -456,
-     -456, -456, -456, -456, -456, -456, -456, -456, -456, -456,
-
-     -456, -456, -456, -456, -456, -456, -456, -456
-    },
-
-    {
-       15, -457, -457, -457, -457, -457, -457, -457, -457, -457,
-     -457, -457, -457, -457, -457, -457, -457, -457, -457, -457,
-     -457, -457, -457, -457, -457, -457, -457, -457, -457, -457,
-     -457, -457,  459, -457, -457, -457, -457, -457, -457, -457,
-     -457, -457, -457, -457, -457, -457, -457, -457, -457, -457,
-     -457, -457, -457, -457, -457, -457, -457, -457, -457, -457,
-     -457, -457, -457, -457, -457, -457, -457, -457, -457, -457,
-     -457, -457, -457, -457, -457, -457, -457, -457, -457, -457,
-     -457, -457, -457, -457, -457, -457, -457, -457, -457, -457,
-
-     -457, -457, -457, -457, -457, -457, -457, -457, -457, -457,
-     -457, -457, -457, -457, -457, -457, -457, -457, -457, -457,
-     -457, -457, -457, -457, -457, -457, -457, -457, -457, -457,
-     -457, -457, -457, -457, -457, -457, -457, -457
-    },
-
-    {
-       15, -458, -458, -458, -458, -458, -458, -458, -458, -458,
-     -458, -458, -458, -458, -458, -458, -458, -458, -458, -458,
-     -458, -458, -458, -458, -458, -458, -458, -458, -458, -458,
-     -458, -458,  460, -458, -458, -458, -458, -458, -458, -458,
-     -458, -458, -458, -458, -458, -458, -458, -458, -458, -458,
-     -458, -458, -458, -458, -458, -458, -458, -458, -458, -458,
-
-     -458, -458, -458, -458, -458, -458, -458, -458, -458, -458,
-     -458, -458, -458, -458, -458, -458, -458, -458, -458, -458,
-     -458, -458, -458, -458, -458, -458, -458, -458, -458, -458,
-     -458, -458, -458, -458, -458, -458, -458, -458, -458, -458,
-     -458, -458, -458, -458, -458, -458, -458, -458, -458, -458,
-     -458, -458, -458, -458, -458, -458, -458, -458, -458, -458,
-     -458, -458, -458, -458, -458, -458, -458, -458
-    },
-
-    {
-       15, -459, -459, -459, -459, -459, -459, -459, -459, -459,
-     -459, -459, -459, -459, -459, -459, -459, -459, -459, -459,
-     -459, -459, -459, -459, -459, -459, -459, -459, -459, -459,
-
-     -459, -459,  461, -459, -459, -459, -459, -459, -459, -459,
-     -459, -459, -459, -459, -459, -459, -459, -459, -459, -459,
-     -459, -459, -459, -459, -459, -459, -459, -459, -459, -459,
-     -459, -459, -459, -459, -459, -459, -459, -459, -459, -459,
-     -459, -459, -459, -459, -459, -459, -459, -459, -459, -459,
-     -459, -459, -459, -459, -459, -459, -459, -459, -459, -459,
-     -459, -459, -459, -459, -459, -459, -459, -459, -459, -459,
-     -459, -459, -459, -459, -459, -459, -459, -459, -459, -459,
-     -459, -459, -459, -459, -459, -459, -459, -459, -459, -459,
-     -459, -459, -459, -459, -459, -459, -459, -459
-
-    },
-
-    {
-       15, -460, -460, -460, -460, -460, -460, -460, -460, -460,
-     -460, -460, -460, -460, -460, -460, -460, -460, -460, -460,
-     -460, -460, -460, -460, -460, -460, -460, -460, -460, -460,
-     -460, -460,  462, -460, -460, -460, -460, -460, -460, -460,
-     -460, -460, -460, -460, -460, -460, -460, -460, -460, -460,
-     -460, -460, -460, -460, -460, -460, -460, -460, -460, -460,
-     -460, -460, -460, -460, -460, -460, -460, -460, -460, -460,
-     -460, -460, -460, -460, -460, -460, -460, -460, -460, -460,
-     -460, -460, -460, -460, -460, -460, -460, -460, -460, -460,
-     -460, -460, -460, -460, -460, -460, -460, -460, -460, -460,
-
-     -460, -460, -460, -460, -460, -460, -460, -460, -460, -460,
-     -460, -460, -460, -460, -460, -460, -460, -460, -460, -460,
-     -460, -460, -460, -460, -460, -460, -460, -460
-    },
-
-    {
-       15, -461, -461, -461, -461, -461, -461, -461, -461, -461,
-     -461, -461, -461, -461, -461, -461, -461, -461, -461, -461,
-     -461, -461, -461, -461, -461, -461, -461, -461, -461, -461,
-     -461, -461,  463, -461, -461, -461, -461, -461, -461, -461,
-     -461, -461, -461, -461, -461, -461, -461, -461, -461, -461,
-     -461, -461, -461, -461, -461, -461, -461, -461, -461, -461,
-     -461, -461, -461, -461, -461, -461, -461, -461, -461, -461,
-
-     -461, -461, -461, -461, -461, -461, -461, -461, -461, -461,
-     -461, -461, -461, -461, -461, -461, -461, -461, -461, -461,
-     -461, -461, -461, -461, -461, -461, -461, -461, -461, -461,
-     -461, -461, -461, -461, -461, -461, -461, -461, -461, -461,
-     -461, -461, -461, -461, -461, -461, -461, -461, -461, -461,
-     -461, -461, -461, -461, -461, -461, -461, -461
-    },
-
-    {
-       15, -462, -462, -462, -462, -462, -462, -462, -462, -462,
-     -462, -462, -462, -462, -462, -462, -462, -462, -462, -462,
-     -462, -462, -462, -462, -462, -462, -462, -462, -462, -462,
-     -462, -462,  464, -462, -462, -462, -462, -462, -462, -462,
-
-     -462, -462, -462, -462, -462, -462, -462, -462, -462, -462,
-     -462, -462, -462, -462, -462, -462, -462, -462, -462, -462,
-     -462, -462, -462, -462, -462, -462, -462, -462, -462, -462,
-     -462, -462, -462, -462, -462, -462, -462, -462, -462, -462,
-     -462, -462, -462, -462, -462, -462, -462, -462, -462, -462,
-     -462, -462, -462, -462, -462, -462, -462, -462, -462, -462,
-     -462, -462, -462, -462, -462, -462, -462, -462, -462, -462,
-     -462, -462, -462, -462, -462, -462, -462, -462, -462, -462,
-     -462, -462, -462, -462, -462, -462, -462, -462
-    },
-
-    {
-       15, -463, -463, -463, -463, -463, -463, -463, -463, -463,
-
-     -463, -463, -463, -463, -463, -463, -463, -463, -463, -463,
-     -463, -463, -463, -463, -463, -463, -463, -463, -463, -463,
-     -463, -463,  465, -463, -463, -463, -463, -463, -463, -463,
-     -463, -463, -463, -463, -463, -463, -463, -463, -463, -463,
-     -463, -463, -463, -463, -463, -463, -463, -463, -463, -463,
-     -463, -463, -463, -463, -463, -463, -463, -463, -463, -463,
-     -463, -463, -463, -463, -463, -463, -463, -463, -463, -463,
-     -463, -463, -463, -463, -463, -463, -463, -463, -463, -463,
-     -463, -463, -463, -463, -463, -463, -463, -463, -463, -463,
-     -463, -463, -463, -463, -463, -463, -463, -463, -463, -463,
-
-     -463, -463, -463, -463, -463, -463, -463, -463, -463, -463,
-     -463, -463, -463, -463, -463, -463, -463, -463
-    },
-
-    {
-       15, -464, -464, -464, -464, -464, -464, -464, -464, -464,
-     -464, -464, -464, -464, -464, -464, -464, -464, -464, -464,
-     -464, -464, -464, -464, -464, -464, -464, -464, -464, -464,
-     -464, -464,  466, -464, -464, -464, -464, -464, -464, -464,
-     -464, -464, -464, -464, -464, -464, -464, -464, -464, -464,
-     -464, -464, -464, -464, -464, -464, -464, -464, -464, -464,
-     -464, -464, -464, -464, -464, -464, -464, -464, -464, -464,
-     -464, -464, -464, -464, -464, -464, -464, -464, -464, -464,
-
-     -464, -464, -464, -464, -464, -464, -464, -464, -464, -464,
-     -464, -464, -464, -464, -464, -464, -464, -464, -464, -464,
-     -464, -464, -464, -464, -464, -464, -464, -464, -464, -464,
-     -464, -464, -464, -464, -464, -464, -464, -464, -464, -464,
-     -464, -464, -464, -464, -464, -464, -464, -464
-    },
-
-    {
-       15, -465, -465, -465, -465, -465, -465, -465, -465, -465,
-     -465, -465, -465, -465, -465, -465, -465, -465, -465, -465,
-     -465, -465, -465, -465, -465, -465, -465, -465, -465, -465,
-     -465, -465,  467, -465, -465, -465, -465, -465, -465, -465,
-     -465, -465, -465, -465, -465, -465, -465, -465, -465, -465,
-
-     -465, -465, -465, -465, -465, -465, -465, -465, -465, -465,
-     -465, -465, -465, -465, -465, -465, -465, -465, -465, -465,
-     -465, -465, -465, -465, -465, -465, -465, -465, -465, -465,
-     -465, -465, -465, -465, -465, -465, -465, -465, -465, -465,
-     -465, -465, -465, -465, -465, -465, -465, -465, -465, -465,
-     -465, -465, -465, -465, -465, -465, -465, -465, -465, -465,
-     -465, -465, -465, -465, -465, -465, -465, -465, -465, -465,
-     -465, -465, -465, -465, -465, -465, -465, -465
-    },
-
-    {
-       15, -466, -466, -466, -466, -466, -466, -466, -466, -466,
-     -466, -466, -466, -466, -466, -466, -466, -466, -466, -466,
-
-     -466, -466, -466, -466, -466, -466, -466, -466, -466, -466,
-     -466, -466,  468, -466, -466, -466, -466, -466, -466, -466,
-     -466, -466, -466, -466, -466, -466, -466, -466, -466, -466,
-     -466, -466, -466, -466, -466, -466, -466, -466, -466, -466,
-     -466, -466, -466, -466, -466, -466, -466, -466, -466, -466,
-     -466, -466, -466, -466, -466, -466, -466, -466, -466, -466,
-     -466, -466, -466, -466, -466, -466, -466, -466, -466, -466,
-     -466, -466, -466, -466, -466, -466, -466, -466, -466, -466,
-     -466, -466, -466, -466, -466, -466, -466, -466, -466, -466,
-     -466, -466, -466, -466, -466, -466, -466, -466, -466, -466,
-
-     -466, -466, -466, -466, -466, -466, -466, -466
-    },
-
-    {
-       15, -467, -467, -467, -467, -467, -467, -467, -467, -467,
-     -467, -467, -467, -467, -467, -467, -467, -467, -467, -467,
-     -467, -467, -467, -467, -467, -467, -467, -467, -467, -467,
-     -467, -467,  469, -467, -467, -467, -467, -467, -467, -467,
-     -467, -467, -467, -467, -467, -467, -467, -467, -467, -467,
-     -467, -467, -467, -467, -467, -467, -467, -467, -467, -467,
-     -467, -467, -467, -467, -467, -467, -467, -467, -467, -467,
-     -467, -467, -467, -467, -467, -467, -467, -467, -467, -467,
-     -467, -467, -467, -467, -467, -467, -467, -467, -467, -467,
-
-     -467, -467, -467, -467, -467, -467, -467, -467, -467, -467,
-     -467, -467, -467, -467, -467, -467, -467, -467, -467, -467,
-     -467, -467, -467, -467, -467, -467, -467, -467, -467, -467,
-     -467, -467, -467, -467, -467, -467, -467, -467
-    },
-
-    {
-       15, -468, -468, -468, -468, -468, -468, -468, -468, -468,
-     -468, -468, -468, -468, -468, -468, -468, -468, -468, -468,
-     -468, -468, -468, -468, -468, -468, -468, -468, -468, -468,
-     -468, -468,  470, -468, -468, -468, -468, -468, -468, -468,
-     -468, -468, -468, -468, -468, -468, -468, -468, -468, -468,
-     -468, -468, -468, -468, -468, -468, -468, -468, -468, -468,
-
-     -468, -468, -468, -468, -468, -468, -468, -468, -468, -468,
-     -468, -468, -468, -468, -468, -468, -468, -468, -468, -468,
-     -468, -468, -468, -468, -468, -468, -468, -468, -468, -468,
-     -468, -468, -468, -468, -468, -468, -468, -468, -468, -468,
-     -468, -468, -468, -468, -468, -468, -468, -468, -468, -468,
-     -468, -468, -468, -468, -468, -468, -468, -468, -468, -468,
-     -468, -468, -468, -468, -468, -468, -468, -468
-    },
-
-    {
-       15, -469, -469, -469, -469, -469, -469, -469, -469, -469,
-     -469, -469, -469, -469, -469, -469, -469, -469, -469, -469,
-     -469, -469, -469, -469, -469, -469, -469, -469, -469, -469,
-
-     -469, -469,  471, -469, -469, -469, -469, -469, -469, -469,
-     -469, -469, -469, -469, -469, -469, -469, -469, -469, -469,
-     -469, -469, -469, -469, -469, -469, -469, -469, -469, -469,
-     -469, -469, -469, -469, -469, -469, -469, -469, -469, -469,
-     -469, -469, -469, -469, -469, -469, -469, -469, -469, -469,
-     -469, -469, -469, -469, -469, -469, -469, -469, -469, -469,
-     -469, -469, -469, -469, -469, -469, -469, -469, -469, -469,
-     -469, -469, -469, -469, -469, -469, -469, -469, -469, -469,
-     -469, -469, -469, -469, -469, -469, -469, -469, -469, -469,
-     -469, -469, -469, -469, -469, -469, -469, -469
-
-    },
-
-    {
-       15, -470, -470, -470, -470, -470, -470, -470, -470, -470,
-     -470, -470, -470, -470, -470, -470, -470, -470, -470, -470,
-     -470, -470, -470, -470, -470, -470, -470, -470, -470, -470,
-     -470, -470,  472, -470, -470, -470, -470, -470, -470, -470,
-     -470, -470, -470, -470, -470, -470, -470, -470, -470, -470,
-     -470, -470, -470, -470, -470, -470, -470, -470, -470, -470,
-     -470, -470, -470, -470, -470, -470, -470, -470, -470, -470,
-     -470, -470, -470, -470, -470, -470, -470, -470, -470, -470,
-     -470, -470, -470, -470, -470, -470, -470, -470, -470, -470,
-     -470, -470, -470, -470, -470, -470, -470, -470, -470, -470,
-
-     -470, -470, -470, -470, -470, -470, -470, -470, -470, -470,
-     -470, -470, -470, -470, -470, -470, -470, -470, -470, -470,
-     -470, -470, -470, -470, -470, -470, -470, -470
-    },
-
-    {
-       15, -471, -471, -471, -471, -471, -471, -471, -471, -471,
-     -471, -471, -471, -471, -471, -471, -471, -471, -471, -471,
-     -471, -471, -471, -471, -471, -471, -471, -471, -471, -471,
-     -471, -471,  473, -471, -471, -471, -471, -471, -471, -471,
-     -471, -471, -471, -471, -471, -471, -471, -471, -471, -471,
-     -471, -471, -471, -471, -471, -471, -471, -471, -471, -471,
-     -471, -471, -471, -471, -471, -471, -471, -471, -471, -471,
-
-     -471, -471, -471, -471, -471, -471, -471, -471, -471, -471,
-     -471, -471, -471, -471, -471, -471, -471, -471, -471, -471,
-     -471, -471, -471, -471, -471, -471, -471, -471, -471, -471,
-     -471, -471, -471, -471, -471, -471, -471, -471, -471, -471,
-     -471, -471, -471, -471, -471, -471, -471, -471, -471, -471,
-     -471, -471, -471, -471, -471, -471, -471, -471
-    },
-
-    {
-       15, -472, -472, -472, -472, -472, -472, -472, -472, -472,
-     -472, -472, -472, -472, -472, -472, -472, -472, -472, -472,
-     -472, -472, -472, -472, -472, -472, -472, -472, -472, -472,
-     -472, -472,  474, -472, -472, -472, -472, -472, -472, -472,
-
-     -472, -472, -472, -472, -472, -472, -472, -472, -472, -472,
-     -472, -472, -472, -472, -472, -472, -472, -472, -472, -472,
-     -472, -472, -472, -472, -472, -472, -472, -472, -472, -472,
-     -472, -472, -472, -472, -472, -472, -472, -472, -472, -472,
-     -472, -472, -472, -472, -472, -472, -472, -472, -472, -472,
-     -472, -472, -472, -472, -472, -472, -472, -472, -472, -472,
-     -472, -472, -472, -472, -472, -472, -472, -472, -472, -472,
-     -472, -472, -472, -472, -472, -472, -472, -472, -472, -472,
-     -472, -472, -472, -472, -472, -472, -472, -472
-    },
-
-    {
-       15, -473, -473, -473, -473, -473, -473, -473, -473, -473,
-
-     -473, -473, -473, -473, -473, -473, -473, -473, -473, -473,
-     -473, -473, -473, -473, -473, -473, -473, -473, -473, -473,
-     -473, -473,  475, -473, -473, -473, -473, -473, -473, -473,
-     -473, -473, -473, -473, -473, -473, -473, -473, -473, -473,
-     -473, -473, -473, -473, -473, -473, -473, -473, -473, -473,
-     -473, -473, -473, -473, -473, -473, -473, -473, -473, -473,
-     -473, -473, -473, -473, -473, -473, -473, -473, -473, -473,
-     -473, -473, -473, -473, -473, -473, -473, -473, -473, -473,
-     -473, -473, -473, -473, -473, -473, -473, -473, -473, -473,
-     -473, -473, -473, -473, -473, -473, -473, -473, -473, -473,
-
-     -473, -473, -473, -473, -473, -473, -473, -473, -473, -473,
-     -473, -473, -473, -473, -473, -473, -473, -473
-    },
-
-    {
-       15, -474, -474, -474, -474, -474, -474, -474, -474, -474,
-     -474, -474, -474, -474, -474, -474, -474, -474, -474, -474,
-     -474, -474, -474, -474, -474, -474, -474, -474, -474, -474,
-     -474, -474,  476, -474, -474, -474, -474, -474, -474, -474,
-     -474, -474, -474, -474, -474, -474, -474, -474, -474, -474,
-     -474, -474, -474, -474, -474, -474, -474, -474, -474, -474,
-     -474, -474, -474, -474, -474, -474, -474, -474, -474, -474,
-     -474, -474, -474, -474, -474, -474, -474, -474, -474, -474,
-
-     -474, -474, -474, -474, -474, -474, -474, -474, -474, -474,
-     -474, -474, -474, -474, -474, -474, -474, -474, -474, -474,
-     -474, -474, -474, -474, -474, -474, -474, -474, -474, -474,
-     -474, -474, -474, -474, -474, -474, -474, -474, -474, -474,
-     -474, -474, -474, -474, -474, -474, -474, -474
-    },
-
-    {
-       15, -475, -475, -475, -475, -475, -475, -475, -475, -475,
-     -475, -475, -475, -475, -475, -475, -475, -475, -475, -475,
-     -475, -475, -475, -475, -475, -475, -475, -475, -475, -475,
-     -475, -475,  477, -475, -475, -475, -475, -475, -475, -475,
-     -475, -475, -475, -475, -475, -475, -475, -475, -475, -475,
-
-     -475, -475, -475, -475, -475, -475, -475, -475, -475, -475,
-     -475, -475, -475, -475, -475, -475, -475, -475, -475, -475,
-     -475, -475, -475, -475, -475, -475, -475, -475, -475, -475,
-     -475, -475, -475, -475, -475, -475, -475, -475, -475, -475,
-     -475, -475, -475, -475, -475, -475, -475, -475, -475, -475,
-     -475, -475, -475, -475, -475, -475, -475, -475, -475, -475,
-     -475, -475, -475, -475, -475, -475, -475, -475, -475, -475,
-     -475, -475, -475, -475, -475, -475, -475, -475
-    },
-
-    {
-       15, -476, -476, -476, -476, -476, -476, -476, -476, -476,
-     -476, -476, -476, -476, -476, -476, -476, -476, -476, -476,
-
-     -476, -476, -476, -476, -476, -476, -476, -476, -476, -476,
-     -476, -476,  478, -476, -476, -476, -476, -476, -476, -476,
-     -476, -476, -476, -476, -476, -476, -476, -476, -476, -476,
-     -476, -476, -476, -476, -476, -476, -476, -476, -476, -476,
-     -476, -476, -476, -476, -476, -476, -476, -476, -476, -476,
-     -476, -476, -476, -476, -476, -476, -476, -476, -476, -476,
-     -476, -476, -476, -476, -476, -476, -476, -476, -476, -476,
-     -476, -476, -476, -476, -476, -476, -476, -476, -476, -476,
-     -476, -476, -476, -476, -476, -476, -476, -476, -476, -476,
-     -476, -476, -476, -476, -476, -476, -476, -476, -476, -476,
-
-     -476, -476, -476, -476, -476, -476, -476, -476
-    },
-
-    {
-       15, -477, -477, -477, -477, -477, -477, -477, -477, -477,
-     -477, -477, -477, -477, -477, -477, -477, -477, -477, -477,
-     -477, -477, -477, -477, -477, -477, -477, -477, -477, -477,
-     -477, -477,  479, -477, -477, -477, -477, -477, -477, -477,
-     -477, -477, -477, -477, -477, -477, -477, -477, -477, -477,
-     -477, -477, -477, -477, -477, -477, -477, -477, -477, -477,
-     -477, -477, -477, -477, -477, -477, -477, -477, -477, -477,
-     -477, -477, -477, -477, -477, -477, -477, -477, -477, -477,
-     -477, -477, -477, -477, -477, -477, -477, -477, -477, -477,
-
-     -477, -477, -477, -477, -477, -477, -477, -477, -477, -477,
-     -477, -477, -477, -477, -477, -477, -477, -477, -477, -477,
-     -477, -477, -477, -477, -477, -477, -477, -477, -477, -477,
-     -477, -477, -477, -477, -477, -477, -477, -477
-    },
-
-    {
-       15, -478, -478, -478, -478, -478, -478, -478, -478, -478,
-     -478, -478, -478, -478, -478, -478, -478, -478, -478, -478,
-     -478, -478, -478, -478, -478, -478, -478, -478, -478, -478,
-     -478, -478,  480, -478, -478, -478, -478, -478, -478, -478,
-     -478, -478, -478, -478, -478, -478, -478, -478, -478, -478,
-     -478, -478, -478, -478, -478, -478, -478, -478, -478, -478,
-
-     -478, -478, -478, -478, -478, -478, -478, -478, -478, -478,
-     -478, -478, -478, -478, -478, -478, -478, -478, -478, -478,
-     -478, -478, -478, -478, -478, -478, -478, -478, -478, -478,
-     -478, -478, -478, -478, -478, -478, -478, -478, -478, -478,
-     -478, -478, -478, -478, -478, -478, -478, -478, -478, -478,
-     -478, -478, -478, -478, -478, -478, -478, -478, -478, -478,
-     -478, -478, -478, -478, -478, -478, -478, -478
-    },
-
-    {
-       15, -479, -479, -479, -479, -479, -479, -479, -479, -479,
-     -479, -479, -479, -479, -479, -479, -479, -479, -479, -479,
-     -479, -479, -479, -479, -479, -479, -479, -479, -479, -479,
-
-     -479, -479,  481, -479, -479, -479, -479, -479, -479, -479,
-     -479, -479, -479, -479, -479, -479, -479, -479, -479, -479,
-     -479, -479, -479, -479, -479, -479, -479, -479, -479, -479,
-     -479, -479, -479, -479, -479, -479, -479, -479, -479, -479,
-     -479, -479, -479, -479, -479, -479, -479, -479, -479, -479,
-     -479, -479, -479, -479, -479, -479, -479, -479, -479, -479,
-     -479, -479, -479, -479, -479, -479, -479, -479, -479, -479,
-     -479, -479, -479, -479, -479, -479, -479, -479, -479, -479,
-     -479, -479, -479, -479, -479, -479, -479, -479, -479, -479,
-     -479, -479, -479, -479, -479, -479, -479, -479
-
-    },
-
-    {
-       15, -480, -480, -480, -480, -480, -480, -480, -480, -480,
-     -480, -480, -480, -480, -480, -480, -480, -480, -480, -480,
-     -480, -480, -480, -480, -480, -480, -480, -480, -480, -480,
-     -480, -480,  482, -480, -480, -480, -480, -480, -480, -480,
-     -480, -480, -480, -480, -480, -480, -480, -480, -480, -480,
-     -480, -480, -480, -480, -480, -480, -480, -480, -480, -480,
-     -480, -480, -480, -480, -480, -480, -480, -480, -480, -480,
-     -480, -480, -480, -480, -480, -480, -480, -480, -480, -480,
-     -480, -480, -480, -480, -480, -480, -480, -480, -480, -480,
-     -480, -480, -480, -480, -480, -480, -480, -480, -480, -480,
-
-     -480, -480, -480, -480, -480, -480, -480, -480, -480, -480,
-     -480, -480, -480, -480, -480, -480, -480, -480, -480, -480,
-     -480, -480, -480, -480, -480, -480, -480, -480
-    },
-
-    {
-       15, -481, -481, -481, -481, -481, -481, -481, -481, -481,
-     -481, -481, -481, -481, -481, -481, -481, -481, -481, -481,
-     -481, -481, -481, -481, -481, -481, -481, -481, -481, -481,
-     -481, -481,  483, -481, -481, -481, -481, -481, -481, -481,
-     -481, -481, -481, -481, -481, -481, -481, -481, -481, -481,
-     -481, -481, -481, -481, -481, -481, -481, -481, -481, -481,
-     -481, -481, -481, -481, -481, -481, -481, -481, -481, -481,
-
-     -481, -481, -481, -481, -481, -481, -481, -481, -481, -481,
-     -481, -481, -481, -481, -481, -481, -481, -481, -481, -481,
-     -481, -481, -481, -481, -481, -481, -481, -481, -481, -481,
-     -481, -481, -481, -481, -481, -481, -481, -481, -481, -481,
-     -481, -481, -481, -481, -481, -481, -481, -481, -481, -481,
-     -481, -481, -481, -481, -481, -481, -481, -481
-    },
-
-    {
-       15, -482, -482, -482, -482, -482, -482, -482, -482, -482,
-     -482, -482, -482, -482, -482, -482, -482, -482, -482, -482,
-     -482, -482, -482, -482, -482, -482, -482, -482, -482, -482,
-     -482, -482,  484, -482, -482, -482, -482, -482, -482, -482,
-
-     -482, -482, -482, -482, -482, -482, -482, -482, -482, -482,
-     -482, -482, -482, -482, -482, -482, -482, -482, -482, -482,
-     -482, -482, -482, -482, -482, -482, -482, -482, -482, -482,
-     -482, -482, -482, -482, -482, -482, -482, -482, -482, -482,
-     -482, -482, -482, -482, -482, -482, -482, -482, -482, -482,
-     -482, -482, -482, -482, -482, -482, -482, -482, -482, -482,
-     -482, -482, -482, -482, -482, -482, -482, -482, -482, -482,
-     -482, -482, -482, -482, -482, -482, -482, -482, -482, -482,
-     -482, -482, -482, -482, -482, -482, -482, -482
-    },
-
-    {
-       15, -483, -483, -483, -483, -483, -483, -483, -483, -483,
-
-     -483, -483, -483, -483, -483, -483, -483, -483, -483, -483,
-     -483, -483, -483, -483, -483, -483, -483, -483, -483, -483,
-     -483, -483,  485, -483, -483, -483, -483, -483, -483, -483,
-     -483, -483, -483, -483, -483, -483, -483, -483, -483, -483,
-     -483, -483, -483, -483, -483, -483, -483, -483, -483, -483,
-     -483, -483, -483, -483, -483, -483, -483, -483, -483, -483,
-     -483, -483, -483, -483, -483, -483, -483, -483, -483, -483,
-     -483, -483, -483, -483, -483, -483, -483, -483, -483, -483,
-     -483, -483, -483, -483, -483, -483, -483, -483, -483, -483,
-     -483, -483, -483, -483, -483, -483, -483, -483, -483, -483,
-
-     -483, -483, -483, -483, -483, -483, -483, -483, -483, -483,
-     -483, -483, -483, -483, -483, -483, -483, -483
-    },
-
-    {
-       15, -484, -484, -484, -484, -484, -484, -484, -484, -484,
-     -484, -484, -484, -484, -484, -484, -484, -484, -484, -484,
-     -484, -484, -484, -484, -484, -484, -484, -484, -484, -484,
-     -484, -484,  486, -484, -484, -484, -484, -484, -484, -484,
-     -484, -484, -484, -484, -484, -484, -484, -484, -484, -484,
-     -484, -484, -484, -484, -484, -484, -484, -484, -484, -484,
-     -484, -484, -484, -484, -484, -484, -484, -484, -484, -484,
-     -484, -484, -484, -484, -484, -484, -484, -484, -484, -484,
-
-     -484, -484, -484, -484, -484, -484, -484, -484, -484, -484,
-     -484, -484, -484, -484, -484, -484, -484, -484, -484, -484,
-     -484, -484, -484, -484, -484, -484, -484, -484, -484, -484,
-     -484, -484, -484, -484, -484, -484, -484, -484, -484, -484,
-     -484, -484, -484, -484, -484, -484, -484, -484
-    },
-
-    {
-       15, -485, -485, -485, -485, -485, -485, -485, -485, -485,
-     -485, -485, -485, -485, -485, -485, -485, -485, -485, -485,
-     -485, -485, -485, -485, -485, -485, -485, -485, -485, -485,
-     -485, -485,  487, -485, -485, -485, -485, -485, -485, -485,
-     -485, -485, -485, -485, -485, -485, -485, -485, -485, -485,
-
-     -485, -485, -485, -485, -485, -485, -485, -485, -485, -485,
-     -485, -485, -485, -485, -485, -485, -485, -485, -485, -485,
-     -485, -485, -485, -485, -485, -485, -485, -485, -485, -485,
-     -485, -485, -485, -485, -485, -485, -485, -485, -485, -485,
-     -485, -485, -485, -485, -485, -485, -485, -485, -485, -485,
-     -485, -485, -485, -485, -485, -485, -485, -485, -485, -485,
-     -485, -485, -485, -485, -485, -485, -485, -485, -485, -485,
-     -485, -485, -485, -485, -485, -485, -485, -485
-    },
-
-    {
-       15, -486, -486, -486, -486, -486, -486, -486, -486, -486,
-     -486, -486, -486, -486, -486, -486, -486, -486, -486, -486,
-
-     -486, -486, -486, -486, -486, -486, -486, -486, -486, -486,
-     -486, -486,  488, -486, -486, -486, -486, -486, -486, -486,
-     -486, -486, -486, -486, -486, -486, -486, -486, -486, -486,
-     -486, -486, -486, -486, -486, -486, -486, -486, -486, -486,
-     -486, -486, -486, -486, -486, -486, -486, -486, -486, -486,
-     -486, -486, -486, -486, -486, -486, -486, -486, -486, -486,
-     -486, -486, -486, -486, -486, -486, -486, -486, -486, -486,
-     -486, -486, -486, -486, -486, -486, -486, -486, -486, -486,
-     -486, -486, -486, -486, -486, -486, -486, -486, -486, -486,
-     -486, -486, -486, -486, -486, -486, -486, -486, -486, -486,
-
-     -486, -486, -486, -486, -486, -486, -486, -486
-    },
-
-    {
-       15, -487, -487, -487, -487, -487, -487, -487, -487, -487,
-     -487, -487, -487, -487, -487, -487, -487, -487, -487, -487,
-     -487, -487, -487, -487, -487, -487, -487, -487, -487, -487,
-     -487, -487,  489, -487, -487, -487, -487, -487, -487, -487,
-     -487, -487, -487, -487, -487, -487, -487, -487, -487, -487,
-     -487, -487, -487, -487, -487, -487, -487, -487, -487, -487,
-     -487, -487, -487, -487, -487, -487, -487, -487, -487, -487,
-     -487, -487, -487, -487, -487, -487, -487, -487, -487, -487,
-     -487, -487, -487, -487, -487, -487, -487, -487, -487, -487,
-
-     -487, -487, -487, -487, -487, -487, -487, -487, -487, -487,
-     -487, -487, -487, -487, -487, -487, -487, -487, -487, -487,
-     -487, -487, -487, -487, -487, -487, -487, -487, -487, -487,
-     -487, -487, -487, -487, -487, -487, -487, -487
-    },
-
-    {
-       15, -488, -488, -488, -488, -488, -488, -488, -488, -488,
-     -488, -488, -488, -488, -488, -488, -488, -488, -488, -488,
-     -488, -488, -488, -488, -488, -488, -488, -488, -488, -488,
-     -488, -488,  490, -488, -488, -488, -488, -488, -488, -488,
-     -488, -488, -488, -488, -488, -488, -488, -488, -488, -488,
-     -488, -488, -488, -488, -488, -488, -488, -488, -488, -488,
-
-     -488, -488, -488, -488, -488, -488, -488, -488, -488, -488,
-     -488, -488, -488, -488, -488, -488, -488, -488, -488, -488,
-     -488, -488, -488, -488, -488, -488, -488, -488, -488, -488,
-     -488, -488, -488, -488, -488, -488, -488, -488, -488, -488,
-     -488, -488, -488, -488, -488, -488, -488, -488, -488, -488,
-     -488, -488, -488, -488, -488, -488, -488, -488, -488, -488,
-     -488, -488, -488, -488, -488, -488, -488, -488
-    },
-
-    {
-       15, -489, -489, -489, -489, -489, -489, -489, -489, -489,
-     -489, -489, -489, -489, -489, -489, -489, -489, -489, -489,
-     -489, -489, -489, -489, -489, -489, -489, -489, -489, -489,
-
-     -489, -489,  491, -489, -489, -489, -489, -489, -489, -489,
-     -489, -489, -489, -489, -489, -489, -489, -489, -489, -489,
-     -489, -489, -489, -489, -489, -489, -489, -489, -489, -489,
-     -489, -489, -489, -489, -489, -489, -489, -489, -489, -489,
-     -489, -489, -489, -489, -489, -489, -489, -489, -489, -489,
-     -489, -489, -489, -489, -489, -489, -489, -489, -489, -489,
-     -489, -489, -489, -489, -489, -489, -489, -489, -489, -489,
-     -489, -489, -489, -489, -489, -489, -489, -489, -489, -489,
-     -489, -489, -489, -489, -489, -489, -489, -489, -489, -489,
-     -489, -489, -489, -489, -489, -489, -489, -489
-
-    },
-
-    {
-       15, -490, -490, -490, -490, -490, -490, -490, -490, -490,
-     -490, -490, -490, -490, -490, -490, -490, -490, -490, -490,
-     -490, -490, -490, -490, -490, -490, -490, -490, -490, -490,
-     -490, -490,  492, -490, -490, -490, -490, -490, -490, -490,
-     -490, -490, -490, -490, -490, -490, -490, -490, -490, -490,
-     -490, -490, -490, -490, -490, -490, -490, -490, -490, -490,
-     -490, -490, -490, -490, -490, -490, -490, -490, -490, -490,
-     -490, -490, -490, -490, -490, -490, -490, -490, -490, -490,
-     -490, -490, -490, -490, -490, -490, -490, -490, -490, -490,
-     -490, -490, -490, -490, -490, -490, -490, -490, -490, -490,
-
-     -490, -490, -490, -490, -490, -490, -490, -490, -490, -490,
-     -490, -490, -490, -490, -490, -490, -490, -490, -490, -490,
-     -490, -490, -490, -490, -490, -490, -490, -490
-    },
-
-    {
-       15, -491, -491, -491, -491, -491, -491, -491, -491, -491,
-     -491, -491, -491, -491, -491, -491, -491, -491, -491, -491,
-     -491, -491, -491, -491, -491, -491, -491, -491, -491, -491,
-     -491, -491,  493, -491, -491, -491, -491, -491, -491, -491,
-     -491, -491, -491, -491, -491, -491, -491, -491, -491, -491,
-     -491, -491, -491, -491, -491, -491, -491, -491, -491, -491,
-     -491, -491, -491, -491, -491, -491, -491, -491, -491, -491,
-
-     -491, -491, -491, -491, -491, -491, -491, -491, -491, -491,
-     -491, -491, -491, -491, -491, -491, -491, -491, -491, -491,
-     -491, -491, -491, -491, -491, -491, -491, -491, -491, -491,
-     -491, -491, -491, -491, -491, -491, -491, -491, -491, -491,
-     -491, -491, -491, -491, -491, -491, -491, -491, -491, -491,
-     -491, -491, -491, -491, -491, -491, -491, -491
-    },
-
-    {
-       15, -492, -492, -492, -492, -492, -492, -492, -492, -492,
-     -492, -492, -492, -492, -492, -492, -492, -492, -492, -492,
-     -492, -492, -492, -492, -492, -492, -492, -492, -492, -492,
-     -492, -492,  494, -492, -492, -492, -492, -492, -492, -492,
-
-     -492, -492, -492, -492, -492, -492, -492, -492, -492, -492,
-     -492, -492, -492, -492, -492, -492, -492, -492, -492, -492,
-     -492, -492, -492, -492, -492, -492, -492, -492, -492, -492,
-     -492, -492, -492, -492, -492, -492, -492, -492, -492, -492,
-     -492, -492, -492, -492, -492, -492, -492, -492, -492, -492,
-     -492, -492, -492, -492, -492, -492, -492, -492, -492, -492,
-     -492, -492, -492, -492, -492, -492, -492, -492, -492, -492,
-     -492, -492, -492, -492, -492, -492, -492, -492, -492, -492,
-     -492, -492, -492, -492, -492, -492, -492, -492
-    },
-
-    {
-       15, -493, -493, -493, -493, -493, -493, -493, -493, -493,
-
-     -493, -493, -493, -493, -493, -493, -493, -493, -493, -493,
-     -493, -493, -493, -493, -493, -493, -493, -493, -493, -493,
-     -493, -493,  495, -493, -493, -493, -493, -493, -493, -493,
-     -493, -493, -493, -493, -493, -493, -493, -493, -493, -493,
-     -493, -493, -493, -493, -493, -493, -493, -493, -493, -493,
-     -493, -493, -493, -493, -493, -493, -493, -493, -493, -493,
-     -493, -493, -493, -493, -493, -493, -493, -493, -493, -493,
-     -493, -493, -493, -493, -493, -493, -493, -493, -493, -493,
-     -493, -493, -493, -493, -493, -493, -493, -493, -493, -493,
-     -493, -493, -493, -493, -493, -493, -493, -493, -493, -493,
-
-     -493, -493, -493, -493, -493, -493, -493, -493, -493, -493,
-     -493, -493, -493, -493, -493, -493, -493, -493
-    },
-
-    {
-       15, -494, -494, -494, -494, -494, -494, -494, -494, -494,
-     -494, -494, -494, -494, -494, -494, -494, -494, -494, -494,
-     -494, -494, -494, -494, -494, -494, -494, -494, -494, -494,
-     -494, -494,  496, -494, -494, -494, -494, -494, -494, -494,
-     -494, -494, -494, -494, -494, -494, -494, -494, -494, -494,
-     -494, -494, -494, -494, -494, -494, -494, -494, -494, -494,
-     -494, -494, -494, -494, -494, -494, -494, -494, -494, -494,
-     -494, -494, -494, -494, -494, -494, -494, -494, -494, -494,
-
-     -494, -494, -494, -494, -494, -494, -494, -494, -494, -494,
-     -494, -494, -494, -494, -494, -494, -494, -494, -494, -494,
-     -494, -494, -494, -494, -494, -494, -494, -494, -494, -494,
-     -494, -494, -494, -494, -494, -494, -494, -494, -494, -494,
-     -494, -494, -494, -494, -494, -494, -494, -494
-    },
-
-    {
-       15, -495, -495, -495, -495, -495, -495, -495, -495, -495,
-     -495, -495, -495, -495, -495, -495, -495, -495, -495, -495,
-     -495, -495, -495, -495, -495, -495, -495, -495, -495, -495,
-     -495, -495,  497, -495, -495, -495, -495, -495, -495, -495,
-     -495, -495, -495, -495, -495, -495, -495, -495, -495, -495,
-
-     -495, -495, -495, -495, -495, -495, -495, -495, -495, -495,
-     -495, -495, -495, -495, -495, -495, -495, -495, -495, -495,
-     -495, -495, -495, -495, -495, -495, -495, -495, -495, -495,
-     -495, -495, -495, -495, -495, -495, -495, -495, -495, -495,
-     -495, -495, -495, -495, -495, -495, -495, -495, -495, -495,
-     -495, -495, -495, -495, -495, -495, -495, -495, -495, -495,
-     -495, -495, -495, -495, -495, -495, -495, -495, -495, -495,
-     -495, -495, -495, -495, -495, -495, -495, -495
-    },
-
-    {
-       15, -496, -496, -496, -496, -496, -496, -496, -496, -496,
-     -496, -496, -496, -496, -496, -496, -496, -496, -496, -496,
-
-     -496, -496, -496, -496, -496, -496, -496, -496, -496, -496,
-     -496, -496,  498, -496, -496, -496, -496, -496, -496, -496,
-     -496, -496, -496, -496, -496, -496, -496, -496, -496, -496,
-     -496, -496, -496, -496, -496, -496, -496, -496, -496, -496,
-     -496, -496, -496, -496, -496, -496, -496, -496, -496, -496,
-     -496, -496, -496, -496, -496, -496, -496, -496, -496, -496,
-     -496, -496, -496, -496, -496, -496, -496, -496, -496, -496,
-     -496, -496, -496, -496, -496, -496, -496, -496, -496, -496,
-     -496, -496, -496, -496, -496, -496, -496, -496, -496, -496,
-     -496, -496, -496, -496, -496, -496, -496, -496, -496, -496,
-
-     -496, -496, -496, -496, -496, -496, -496, -496
-    },
-
-    {
-       15, -497, -497, -497, -497, -497, -497, -497, -497, -497,
-     -497, -497, -497, -497, -497, -497, -497, -497, -497, -497,
-     -497, -497, -497, -497, -497, -497, -497, -497, -497, -497,
-     -497, -497,  499, -497, -497, -497, -497, -497, -497, -497,
-     -497, -497, -497, -497, -497, -497, -497, -497, -497, -497,
-     -497, -497, -497, -497, -497, -497, -497, -497, -497, -497,
-     -497, -497, -497, -497, -497, -497, -497, -497, -497, -497,
-     -497, -497, -497, -497, -497, -497, -497, -497, -497, -497,
-     -497, -497, -497, -497, -497, -497, -497, -497, -497, -497,
-
-     -497, -497, -497, -497, -497, -497, -497, -497, -497, -497,
-     -497, -497, -497, -497, -497, -497, -497, -497, -497, -497,
-     -497, -497, -497, -497, -497, -497, -497, -497, -497, -497,
-     -497, -497, -497, -497, -497, -497, -497, -497
-    },
-
-    {
-       15, -498, -498, -498, -498, -498, -498, -498, -498, -498,
-     -498, -498, -498, -498, -498, -498, -498, -498, -498, -498,
-     -498, -498, -498, -498, -498, -498, -498, -498, -498, -498,
-     -498, -498,  500, -498, -498, -498, -498, -498, -498, -498,
-     -498, -498, -498, -498, -498, -498, -498, -498, -498, -498,
-     -498, -498, -498, -498, -498, -498, -498, -498, -498, -498,
-
-     -498, -498, -498, -498, -498, -498, -498, -498, -498, -498,
-     -498, -498, -498, -498, -498, -498, -498, -498, -498, -498,
-     -498, -498, -498, -498, -498, -498, -498, -498, -498, -498,
-     -498, -498, -498, -498, -498, -498, -498, -498, -498, -498,
-     -498, -498, -498, -498, -498, -498, -498, -498, -498, -498,
-     -498, -498, -498, -498, -498, -498, -498, -498, -498, -498,
-     -498, -498, -498, -498, -498, -498, -498, -498
-    },
-
-    {
-       15, -499, -499, -499, -499, -499, -499, -499, -499, -499,
-     -499, -499, -499, -499, -499, -499, -499, -499, -499, -499,
-     -499, -499, -499, -499, -499, -499, -499, -499, -499, -499,
-
-     -499, -499,  501, -499, -499, -499, -499, -499, -499, -499,
-     -499, -499, -499, -499, -499, -499, -499, -499, -499, -499,
-     -499, -499, -499, -499, -499, -499, -499, -499, -499, -499,
-     -499, -499, -499, -499, -499, -499, -499, -499, -499, -499,
-     -499, -499, -499, -499, -499, -499, -499, -499, -499, -499,
-     -499, -499, -499, -499, -499, -499, -499, -499, -499, -499,
-     -499, -499, -499, -499, -499, -499, -499, -499, -499, -499,
-     -499, -499, -499, -499, -499, -499, -499, -499, -499, -499,
-     -499, -499, -499, -499, -499, -499, -499, -499, -499, -499,
-     -499, -499, -499, -499, -499, -499, -499, -499
-
-    },
-
-    {
-       15, -500, -500, -500, -500, -500, -500, -500, -500, -500,
-     -500, -500, -500, -500, -500, -500, -500, -500, -500, -500,
-     -500, -500, -500, -500, -500, -500, -500, -500, -500, -500,
-     -500, -500,  502, -500, -500, -500, -500, -500, -500, -500,
-     -500, -500, -500, -500, -500, -500, -500, -500, -500, -500,
-     -500, -500, -500, -500, -500, -500, -500, -500, -500, -500,
-     -500, -500, -500, -500, -500, -500, -500, -500, -500, -500,
-     -500, -500, -500, -500, -500, -500, -500, -500, -500, -500,
-     -500, -500, -500, -500, -500, -500, -500, -500, -500, -500,
-     -500, -500, -500, -500, -500, -500, -500, -500, -500, -500,
-
-     -500, -500, -500, -500, -500, -500, -500, -500, -500, -500,
-     -500, -500, -500, -500, -500, -500, -500, -500, -500, -500,
-     -500, -500, -500, -500, -500, -500, -500, -500
-    },
-
-    {
-       15, -501, -501, -501, -501, -501, -501, -501, -501, -501,
-     -501, -501, -501, -501, -501, -501, -501, -501, -501, -501,
-     -501, -501, -501, -501, -501, -501, -501, -501, -501, -501,
-     -501, -501,  503, -501, -501, -501, -501, -501, -501, -501,
-     -501, -501, -501, -501, -501, -501, -501, -501, -501, -501,
-     -501, -501, -501, -501, -501, -501, -501, -501, -501, -501,
-     -501, -501, -501, -501, -501, -501, -501, -501, -501, -501,
-
-     -501, -501, -501, -501, -501, -501, -501, -501, -501, -501,
-     -501, -501, -501, -501, -501, -501, -501, -501, -501, -501,
-     -501, -501, -501, -501, -501, -501, -501, -501, -501, -501,
-     -501, -501, -501, -501, -501, -501, -501, -501, -501, -501,
-     -501, -501, -501, -501, -501, -501, -501, -501, -501, -501,
-     -501, -501, -501, -501, -501, -501, -501, -501
-    },
-
-    {
-       15, -502, -502, -502, -502, -502, -502, -502, -502, -502,
-     -502, -502, -502, -502, -502, -502, -502, -502, -502, -502,
-     -502, -502, -502, -502, -502, -502, -502, -502, -502, -502,
-     -502, -502,  504, -502, -502, -502, -502, -502, -502, -502,
-
-     -502, -502, -502, -502, -502, -502, -502, -502, -502, -502,
-     -502, -502, -502, -502, -502, -502, -502, -502, -502, -502,
-     -502, -502, -502, -502, -502, -502, -502, -502, -502, -502,
-     -502, -502, -502, -502, -502, -502, -502, -502, -502, -502,
-     -502, -502, -502, -502, -502, -502, -502, -502, -502, -502,
-     -502, -502, -502, -502, -502, -502, -502, -502, -502, -502,
-     -502, -502, -502, -502, -502, -502, -502, -502, -502, -502,
-     -502, -502, -502, -502, -502, -502, -502, -502, -502, -502,
-     -502, -502, -502, -502, -502, -502, -502, -502
-    },
-
-    {
-       15, -503, -503, -503, -503, -503, -503, -503, -503, -503,
-
-     -503, -503, -503, -503, -503, -503, -503, -503, -503, -503,
-     -503, -503, -503, -503, -503, -503, -503, -503, -503, -503,
-     -503, -503,  505, -503, -503, -503, -503, -503, -503, -503,
-     -503, -503, -503, -503, -503, -503, -503, -503, -503, -503,
-     -503, -503, -503, -503, -503, -503, -503, -503, -503, -503,
-     -503, -503, -503, -503, -503, -503, -503, -503, -503, -503,
-     -503, -503, -503, -503, -503, -503, -503, -503, -503, -503,
-     -503, -503, -503, -503, -503, -503, -503, -503, -503, -503,
-     -503, -503, -503, -503, -503, -503, -503, -503, -503, -503,
-     -503, -503, -503, -503, -503, -503, -503, -503, -503, -503,
-
-     -503, -503, -503, -503, -503, -503, -503, -503, -503, -503,
-     -503, -503, -503, -503, -503, -503, -503, -503
-    },
-
-    {
-       15, -504, -504, -504, -504, -504, -504, -504, -504, -504,
-     -504, -504, -504, -504, -504, -504, -504, -504, -504, -504,
-     -504, -504, -504, -504, -504, -504, -504, -504, -504, -504,
-     -504, -504,  506, -504, -504, -504, -504, -504, -504, -504,
-     -504, -504, -504, -504, -504, -504, -504, -504, -504, -504,
-     -504, -504, -504, -504, -504, -504, -504, -504, -504, -504,
-     -504, -504, -504, -504, -504, -504, -504, -504, -504, -504,
-     -504, -504, -504, -504, -504, -504, -504, -504, -504, -504,
-
-     -504, -504, -504, -504, -504, -504, -504, -504, -504, -504,
-     -504, -504, -504, -504, -504, -504, -504, -504, -504, -504,
-     -504, -504, -504, -504, -504, -504, -504, -504, -504, -504,
-     -504, -504, -504, -504, -504, -504, -504, -504, -504, -504,
-     -504, -504, -504, -504, -504, -504, -504, -504
-    },
-
-    {
-       15, -505, -505, -505, -505, -505, -505, -505, -505, -505,
-     -505, -505, -505, -505, -505, -505, -505, -505, -505, -505,
-     -505, -505, -505, -505, -505, -505, -505, -505, -505, -505,
-     -505, -505,  507, -505, -505, -505, -505, -505, -505, -505,
-     -505, -505, -505, -505, -505, -505, -505, -505, -505, -505,
-
-     -505, -505, -505, -505, -505, -505, -505, -505, -505, -505,
-     -505, -505, -505, -505, -505, -505, -505, -505, -505, -505,
-     -505, -505, -505, -505, -505, -505, -505, -505, -505, -505,
-     -505, -505, -505, -505, -505, -505, -505, -505, -505, -505,
-     -505, -505, -505, -505, -505, -505, -505, -505, -505, -505,
-     -505, -505, -505, -505, -505, -505, -505, -505, -505, -505,
-     -505, -505, -505, -505, -505, -505, -505, -505, -505, -505,
-     -505, -505, -505, -505, -505, -505, -505, -505
-    },
-
-    {
-       15, -506, -506, -506, -506, -506, -506, -506, -506, -506,
-     -506, -506, -506, -506, -506, -506, -506, -506, -506, -506,
-
-     -506, -506, -506, -506, -506, -506, -506, -506, -506, -506,
-     -506, -506,  508, -506, -506, -506, -506, -506, -506, -506,
-     -506, -506, -506, -506, -506, -506, -506, -506, -506, -506,
-     -506, -506, -506, -506, -506, -506, -506, -506, -506, -506,
-     -506, -506, -506, -506, -506, -506, -506, -506, -506, -506,
-     -506, -506, -506, -506, -506, -506, -506, -506, -506, -506,
-     -506, -506, -506, -506, -506, -506, -506, -506, -506, -506,
-     -506, -506, -506, -506, -506, -506, -506, -506, -506, -506,
-     -506, -506, -506, -506, -506, -506, -506, -506, -506, -506,
-     -506, -506, -506, -506, -506, -506, -506, -506, -506, -506,
-
-     -506, -506, -506, -506, -506, -506, -506, -506
-    },
-
-    {
-       15, -507, -507, -507, -507, -507, -507, -507, -507, -507,
-     -507, -507, -507, -507, -507, -507, -507, -507, -507, -507,
-     -507, -507, -507, -507, -507, -507, -507, -507, -507, -507,
-     -507, -507,  509, -507, -507, -507, -507, -507, -507, -507,
-     -507, -507, -507, -507, -507, -507, -507, -507, -507, -507,
-     -507, -507, -507, -507, -507, -507, -507, -507, -507, -507,
-     -507, -507, -507, -507, -507, -507, -507, -507, -507, -507,
-     -507, -507, -507, -507, -507, -507, -507, -507, -507, -507,
-     -507, -507, -507, -507, -507, -507, -507, -507, -507, -507,
-
-     -507, -507, -507, -507, -507, -507, -507, -507, -507, -507,
-     -507, -507, -507, -507, -507, -507, -507, -507, -507, -507,
-     -507, -507, -507, -507, -507, -507, -507, -507, -507, -507,
-     -507, -507, -507, -507, -507, -507, -507, -507
-    },
-
-    {
-       15, -508, -508, -508, -508, -508, -508, -508, -508, -508,
-     -508, -508, -508, -508, -508, -508, -508, -508, -508, -508,
-     -508, -508, -508, -508, -508, -508, -508, -508, -508, -508,
-     -508, -508,  510, -508, -508, -508, -508, -508, -508, -508,
-     -508, -508, -508, -508, -508, -508, -508, -508, -508, -508,
-     -508, -508, -508, -508, -508, -508, -508, -508, -508, -508,
-
-     -508, -508, -508, -508, -508, -508, -508, -508, -508, -508,
-     -508, -508, -508, -508, -508, -508, -508, -508, -508, -508,
-     -508, -508, -508, -508, -508, -508, -508, -508, -508, -508,
-     -508, -508, -508, -508, -508, -508, -508, -508, -508, -508,
-     -508, -508, -508, -508, -508, -508, -508, -508, -508, -508,
-     -508, -508, -508, -508, -508, -508, -508, -508, -508, -508,
-     -508, -508, -508, -508, -508, -508, -508, -508
-    },
-
-    {
-       15, -509, -509, -509, -509, -509, -509, -509, -509, -509,
-     -509, -509, -509, -509, -509, -509, -509, -509, -509, -509,
-     -509, -509, -509, -509, -509, -509, -509, -509, -509, -509,
-
-     -509, -509,  511, -509, -509, -509, -509, -509, -509, -509,
-     -509, -509, -509, -509, -509, -509, -509, -509, -509, -509,
-     -509, -509, -509, -509, -509, -509, -509, -509, -509, -509,
-     -509, -509, -509, -509, -509, -509, -509, -509, -509, -509,
-     -509, -509, -509, -509, -509, -509, -509, -509, -509, -509,
-     -509, -509, -509, -509, -509, -509, -509, -509, -509, -509,
-     -509, -509, -509, -509, -509, -509, -509, -509, -509, -509,
-     -509, -509, -509, -509, -509, -509, -509, -509, -509, -509,
-     -509, -509, -509, -509, -509, -509, -509, -509, -509, -509,
-     -509, -509, -509, -509, -509, -509, -509, -509
-
-    },
-
-    {
-       15, -510, -510, -510, -510, -510, -510, -510, -510, -510,
-     -510, -510, -510, -510, -510, -510, -510, -510, -510, -510,
-     -510, -510, -510, -510, -510, -510, -510, -510, -510, -510,
-     -510, -510,  512, -510, -510, -510, -510, -510, -510, -510,
-     -510, -510, -510, -510, -510, -510, -510, -510, -510, -510,
-     -510, -510, -510, -510, -510, -510, -510, -510, -510, -510,
-     -510, -510, -510, -510, -510, -510, -510, -510, -510, -510,
-     -510, -510, -510, -510, -510, -510, -510, -510, -510, -510,
-     -510, -510, -510, -510, -510, -510, -510, -510, -510, -510,
-     -510, -510, -510, -510, -510, -510, -510, -510, -510, -510,
-
-     -510, -510, -510, -510, -510, -510, -510, -510, -510, -510,
-     -510, -510, -510, -510, -510, -510, -510, -510, -510, -510,
-     -510, -510, -510, -510, -510, -510, -510, -510
-    },
-
-    {
-       15, -511, -511, -511, -511, -511, -511, -511, -511, -511,
-     -511, -511, -511, -511, -511, -511, -511, -511, -511, -511,
-     -511, -511, -511, -511, -511, -511, -511, -511, -511, -511,
-     -511, -511,  513, -511, -511, -511, -511, -511, -511, -511,
-     -511, -511, -511, -511, -511, -511, -511, -511, -511, -511,
-     -511, -511, -511, -511, -511, -511, -511, -511, -511, -511,
-     -511, -511, -511, -511, -511, -511, -511, -511, -511, -511,
-
-     -511, -511, -511, -511, -511, -511, -511, -511, -511, -511,
-     -511, -511, -511, -511, -511, -511, -511, -511, -511, -511,
-     -511, -511, -511, -511, -511, -511, -511, -511, -511, -511,
-     -511, -511, -511, -511, -511, -511, -511, -511, -511, -511,
-     -511, -511, -511, -511, -511, -511, -511, -511, -511, -511,
-     -511, -511, -511, -511, -511, -511, -511, -511
-    },
-
-    {
-       15, -512, -512, -512, -512, -512, -512, -512, -512, -512,
-     -512, -512, -512, -512, -512, -512, -512, -512, -512, -512,
-     -512, -512, -512, -512, -512, -512, -512, -512, -512, -512,
-     -512, -512,  514, -512, -512, -512, -512, -512, -512, -512,
-
-     -512, -512, -512, -512, -512, -512, -512, -512, -512, -512,
-     -512, -512, -512, -512, -512, -512, -512, -512, -512, -512,
-     -512, -512, -512, -512, -512, -512, -512, -512, -512, -512,
-     -512, -512, -512, -512, -512, -512, -512, -512, -512, -512,
-     -512, -512, -512, -512, -512, -512, -512, -512, -512, -512,
-     -512, -512, -512, -512, -512, -512, -512, -512, -512, -512,
-     -512, -512, -512, -512, -512, -512, -512, -512, -512, -512,
-     -512, -512, -512, -512, -512, -512, -512, -512, -512, -512,
-     -512, -512, -512, -512, -512, -512, -512, -512
-    },
-
-    {
-       15, -513, -513, -513, -513, -513, -513, -513, -513, -513,
-
-     -513, -513, -513, -513, -513, -513, -513, -513, -513, -513,
-     -513, -513, -513, -513, -513, -513, -513, -513, -513, -513,
-     -513, -513,  515, -513, -513, -513, -513, -513, -513, -513,
-     -513, -513, -513, -513, -513, -513, -513, -513, -513, -513,
-     -513, -513, -513, -513, -513, -513, -513, -513, -513, -513,
-     -513, -513, -513, -513, -513, -513, -513, -513, -513, -513,
-     -513, -513, -513, -513, -513, -513, -513, -513, -513, -513,
-     -513, -513, -513, -513, -513, -513, -513, -513, -513, -513,
-     -513, -513, -513, -513, -513, -513, -513, -513, -513, -513,
-     -513, -513, -513, -513, -513, -513, -513, -513, -513, -513,
-
-     -513, -513, -513, -513, -513, -513, -513, -513, -513, -513,
-     -513, -513, -513, -513, -513, -513, -513, -513
-    },
-
-    {
-       15, -514, -514, -514, -514, -514, -514, -514, -514, -514,
-     -514, -514, -514, -514, -514, -514, -514, -514, -514, -514,
-     -514, -514, -514, -514, -514, -514, -514, -514, -514, -514,
-     -514, -514,  516, -514, -514, -514, -514, -514, -514, -514,
-     -514, -514, -514, -514, -514, -514, -514, -514, -514, -514,
-     -514, -514, -514, -514, -514, -514, -514, -514, -514, -514,
-     -514, -514, -514, -514, -514, -514, -514, -514, -514, -514,
-     -514, -514, -514, -514, -514, -514, -514, -514, -514, -514,
-
-     -514, -514, -514, -514, -514, -514, -514, -514, -514, -514,
-     -514, -514, -514, -514, -514, -514, -514, -514, -514, -514,
-     -514, -514, -514, -514, -514, -514, -514, -514, -514, -514,
-     -514, -514, -514, -514, -514, -514, -514, -514, -514, -514,
-     -514, -514, -514, -514, -514, -514, -514, -514
-    },
-
-    {
-       15, -515, -515, -515, -515, -515, -515, -515, -515, -515,
-     -515, -515, -515, -515, -515, -515, -515, -515, -515, -515,
-     -515, -515, -515, -515, -515, -515, -515, -515, -515, -515,
-     -515, -515,  517, -515, -515, -515, -515, -515, -515, -515,
-     -515, -515, -515, -515, -515, -515, -515, -515, -515, -515,
-
-     -515, -515, -515, -515, -515, -515, -515, -515, -515, -515,
-     -515, -515, -515, -515, -515, -515, -515, -515, -515, -515,
-     -515, -515, -515, -515, -515, -515, -515, -515, -515, -515,
-     -515, -515, -515, -515, -515, -515, -515, -515, -515, -515,
-     -515, -515, -515, -515, -515, -515, -515, -515, -515, -515,
-     -515, -515, -515, -515, -515, -515, -515, -515, -515, -515,
-     -515, -515, -515, -515, -515, -515, -515, -515, -515, -515,
-     -515, -515, -515, -515, -515, -515, -515, -515
-    },
-
-    {
-       15, -516, -516, -516, -516, -516, -516, -516, -516, -516,
-     -516, -516, -516, -516, -516, -516, -516, -516, -516, -516,
-
-     -516, -516, -516, -516, -516, -516, -516, -516, -516, -516,
-     -516, -516,  518, -516, -516, -516, -516, -516, -516, -516,
-     -516, -516, -516, -516, -516, -516, -516, -516, -516, -516,
-     -516, -516, -516, -516, -516, -516, -516, -516, -516, -516,
-     -516, -516, -516, -516, -516, -516, -516, -516, -516, -516,
-     -516, -516, -516, -516, -516, -516, -516, -516, -516, -516,
-     -516, -516, -516, -516, -516, -516, -516, -516, -516, -516,
-     -516, -516, -516, -516, -516, -516, -516, -516, -516, -516,
-     -516, -516, -516, -516, -516, -516, -516, -516, -516, -516,
-     -516, -516, -516, -516, -516, -516, -516, -516, -516, -516,
-
-     -516, -516, -516, -516, -516, -516, -516, -516
-    },
-
-    {
-       15, -517, -517, -517, -517, -517, -517, -517, -517, -517,
-     -517, -517, -517, -517, -517, -517, -517, -517, -517, -517,
-     -517, -517, -517, -517, -517, -517, -517, -517, -517, -517,
-     -517, -517,  519, -517, -517, -517, -517, -517, -517, -517,
-     -517, -517, -517, -517, -517, -517, -517, -517, -517, -517,
-     -517, -517, -517, -517, -517, -517, -517, -517, -517, -517,
-     -517, -517, -517, -517, -517, -517, -517, -517, -517, -517,
-     -517, -517, -517, -517, -517, -517, -517, -517, -517, -517,
-     -517, -517, -517, -517, -517, -517, -517, -517, -517, -517,
-
-     -517, -517, -517, -517, -517, -517, -517, -517, -517, -517,
-     -517, -517, -517, -517, -517, -517, -517, -517, -517, -517,
-     -517, -517, -517, -517, -517, -517, -517, -517, -517, -517,
-     -517, -517, -517, -517, -517, -517, -517, -517
-    },
-
-    {
-       15, -518, -518, -518, -518, -518, -518, -518, -518, -518,
-     -518, -518, -518, -518, -518, -518, -518, -518, -518, -518,
-     -518, -518, -518, -518, -518, -518, -518, -518, -518, -518,
-     -518, -518,  520, -518, -518, -518, -518, -518, -518, -518,
-     -518, -518, -518, -518, -518, -518, -518, -518, -518, -518,
-     -518, -518, -518, -518, -518, -518, -518, -518, -518, -518,
-
-     -518, -518, -518, -518, -518, -518, -518, -518, -518, -518,
-     -518, -518, -518, -518, -518, -518, -518, -518, -518, -518,
-     -518, -518, -518, -518, -518, -518, -518, -518, -518, -518,
-     -518, -518, -518, -518, -518, -518, -518, -518, -518, -518,
-     -518, -518, -518, -518, -518, -518, -518, -518, -518, -518,
-     -518, -518, -518, -518, -518, -518, -518, -518, -518, -518,
-     -518, -518, -518, -518, -518, -518, -518, -518
-    },
-
-    {
-       15, -519, -519, -519, -519, -519, -519, -519, -519, -519,
-     -519, -519, -519, -519, -519, -519, -519, -519, -519, -519,
-     -519, -519, -519, -519, -519, -519, -519, -519, -519, -519,
-
-     -519, -519,  521, -519, -519, -519, -519, -519, -519, -519,
-     -519, -519, -519, -519, -519, -519, -519, -519, -519, -519,
-     -519, -519, -519, -519, -519, -519, -519, -519, -519, -519,
-     -519, -519, -519, -519, -519, -519, -519, -519, -519, -519,
-     -519, -519, -519, -519, -519, -519, -519, -519, -519, -519,
-     -519, -519, -519, -519, -519, -519, -519, -519, -519, -519,
-     -519, -519, -519, -519, -519, -519, -519, -519, -519, -519,
-     -519, -519, -519, -519, -519, -519, -519, -519, -519, -519,
-     -519, -519, -519, -519, -519, -519, -519, -519, -519, -519,
-     -519, -519, -519, -519, -519, -519, -519, -519
-
-    },
-
-    {
-       15, -520, -520, -520, -520, -520, -520, -520, -520, -520,
-     -520, -520, -520, -520, -520, -520, -520, -520, -520, -520,
-     -520, -520, -520, -520, -520, -520, -520, -520, -520, -520,
-     -520, -520,  522, -520, -520, -520, -520, -520, -520, -520,
-     -520, -520, -520, -520, -520, -520, -520, -520, -520, -520,
-     -520, -520, -520, -520, -520, -520, -520, -520, -520, -520,
-     -520, -520, -520, -520, -520, -520, -520, -520, -520, -520,
-     -520, -520, -520, -520, -520, -520, -520, -520, -520, -520,
-     -520, -520, -520, -520, -520, -520, -520, -520, -520, -520,
-     -520, -520, -520, -520, -520, -520, -520, -520, -520, -520,
-
-     -520, -520, -520, -520, -520, -520, -520, -520, -520, -520,
-     -520, -520, -520, -520, -520, -520, -520, -520, -520, -520,
-     -520, -520, -520, -520, -520, -520, -520, -520
-    },
-
-    {
-       15, -521, -521, -521, -521, -521, -521, -521, -521, -521,
-     -521, -521, -521, -521, -521, -521, -521, -521, -521, -521,
-     -521, -521, -521, -521, -521, -521, -521, -521, -521, -521,
-     -521, -521,  523, -521, -521, -521, -521, -521, -521, -521,
-     -521, -521, -521, -521, -521, -521, -521, -521, -521, -521,
-     -521, -521, -521, -521, -521, -521, -521, -521, -521, -521,
-     -521, -521, -521, -521, -521, -521, -521, -521, -521, -521,
-
-     -521, -521, -521, -521, -521, -521, -521, -521, -521, -521,
-     -521, -521, -521, -521, -521, -521, -521, -521, -521, -521,
-     -521, -521, -521, -521, -521, -521, -521, -521, -521, -521,
-     -521, -521, -521, -521, -521, -521, -521, -521, -521, -521,
-     -521, -521, -521, -521, -521, -521, -521, -521, -521, -521,
-     -521, -521, -521, -521, -521, -521, -521, -521
-    },
-
-    {
-       15, -522, -522, -522, -522, -522, -522, -522, -522, -522,
-     -522, -522, -522, -522, -522, -522, -522, -522, -522, -522,
-     -522, -522, -522, -522, -522, -522, -522, -522, -522, -522,
-     -522, -522,  524, -522, -522, -522, -522, -522, -522, -522,
-
-     -522, -522, -522, -522, -522, -522, -522, -522, -522, -522,
-     -522, -522, -522, -522, -522, -522, -522, -522, -522, -522,
-     -522, -522, -522, -522, -522, -522, -522, -522, -522, -522,
-     -522, -522, -522, -522, -522, -522, -522, -522, -522, -522,
-     -522, -522, -522, -522, -522, -522, -522, -522, -522, -522,
-     -522, -522, -522, -522, -522, -522, -522, -522, -522, -522,
-     -522, -522, -522, -522, -522, -522, -522, -522, -522, -522,
-     -522, -522, -522, -522, -522, -522, -522, -522, -522, -522,
-     -522, -522, -522, -522, -522, -522, -522, -522
-    },
-
-    {
-       15, -523, -523, -523, -523, -523, -523, -523, -523, -523,
-
-     -523, -523, -523, -523, -523, -523, -523, -523, -523, -523,
-     -523, -523, -523, -523, -523, -523, -523, -523, -523, -523,
-     -523, -523,  525, -523, -523, -523, -523, -523, -523, -523,
-     -523, -523, -523, -523, -523, -523, -523, -523, -523, -523,
-     -523, -523, -523, -523, -523, -523, -523, -523, -523, -523,
-     -523, -523, -523, -523, -523, -523, -523, -523, -523, -523,
-     -523, -523, -523, -523, -523, -523, -523, -523, -523, -523,
-     -523, -523, -523, -523, -523, -523, -523, -523, -523, -523,
-     -523, -523, -523, -523, -523, -523, -523, -523, -523, -523,
-     -523, -523, -523, -523, -523, -523, -523, -523, -523, -523,
-
-     -523, -523, -523, -523, -523, -523, -523, -523, -523, -523,
-     -523, -523, -523, -523, -523, -523, -523, -523
-    },
-
-    {
-       15, -524, -524, -524, -524, -524, -524, -524, -524, -524,
-     -524, -524, -524, -524, -524, -524, -524, -524, -524, -524,
-     -524, -524, -524, -524, -524, -524, -524, -524, -524, -524,
-     -524, -524,  526, -524, -524, -524, -524, -524, -524, -524,
-     -524, -524, -524, -524, -524, -524, -524, -524, -524, -524,
-     -524, -524, -524, -524, -524, -524, -524, -524, -524, -524,
-     -524, -524, -524, -524, -524, -524, -524, -524, -524, -524,
-     -524, -524, -524, -524, -524, -524, -524, -524, -524, -524,
-
-     -524, -524, -524, -524, -524, -524, -524, -524, -524, -524,
-     -524, -524, -524, -524, -524, -524, -524, -524, -524, -524,
-     -524, -524, -524, -524, -524, -524, -524, -524, -524, -524,
-     -524, -524, -524, -524, -524, -524, -524, -524, -524, -524,
-     -524, -524, -524, -524, -524, -524, -524, -524
-    },
-
-    {
-       15, -525, -525, -525, -525, -525, -525, -525, -525, -525,
-     -525, -525, -525, -525, -525, -525, -525, -525, -525, -525,
-     -525, -525, -525, -525, -525, -525, -525, -525, -525, -525,
-     -525, -525,  527, -525, -525, -525, -525, -525, -525, -525,
-     -525, -525, -525, -525, -525, -525, -525, -525, -525, -525,
-
-     -525, -525, -525, -525, -525, -525, -525, -525, -525, -525,
-     -525, -525, -525, -525, -525, -525, -525, -525, -525, -525,
-     -525, -525, -525, -525, -525, -525, -525, -525, -525, -525,
-     -525, -525, -525, -525, -525, -525, -525, -525, -525, -525,
-     -525, -525, -525, -525, -525, -525, -525, -525, -525, -525,
-     -525, -525, -525, -525, -525, -525, -525, -525, -525, -525,
-     -525, -525, -525, -525, -525, -525, -525, -525, -525, -525,
-     -525, -525, -525, -525, -525, -525, -525, -525
-    },
-
-    {
-       15, -526, -526, -526, -526, -526, -526, -526, -526, -526,
-     -526, -526, -526, -526, -526, -526, -526, -526, -526, -526,
-
-     -526, -526, -526, -526, -526, -526, -526, -526, -526, -526,
-     -526, -526,  528, -526, -526, -526, -526, -526, -526, -526,
-     -526, -526, -526, -526, -526, -526, -526, -526, -526, -526,
-     -526, -526, -526, -526, -526, -526, -526, -526, -526, -526,
-     -526, -526, -526, -526, -526, -526, -526, -526, -526, -526,
-     -526, -526, -526, -526, -526, -526, -526, -526, -526, -526,
-     -526, -526, -526, -526, -526, -526, -526, -526, -526, -526,
-     -526, -526, -526, -526, -526, -526, -526, -526, -526, -526,
-     -526, -526, -526, -526, -526, -526, -526, -526, -526, -526,
-     -526, -526, -526, -526, -526, -526, -526, -526, -526, -526,
-
-     -526, -526, -526, -526, -526, -526, -526, -526
-    },
-
-    {
-       15, -527, -527, -527, -527, -527, -527, -527, -527, -527,
-     -527, -527, -527, -527, -527, -527, -527, -527, -527, -527,
-     -527, -527, -527, -527, -527, -527, -527, -527, -527, -527,
-     -527, -527,  529, -527, -527, -527, -527, -527, -527, -527,
-     -527, -527, -527, -527, -527, -527, -527, -527, -527, -527,
-     -527, -527, -527, -527, -527, -527, -527, -527, -527, -527,
-     -527, -527, -527, -527, -527, -527, -527, -527, -527, -527,
-     -527, -527, -527, -527, -527, -527, -527, -527, -527, -527,
-     -527, -527, -527, -527, -527, -527, -527, -527, -527, -527,
-
-     -527, -527, -527, -527, -527, -527, -527, -527, -527, -527,
-     -527, -527, -527, -527, -527, -527, -527, -527, -527, -527,
-     -527, -527, -527, -527, -527, -527, -527, -527, -527, -527,
-     -527, -527, -527, -527, -527, -527, -527, -527
-    },
-
-    {
-       15, -528, -528, -528, -528, -528, -528, -528, -528, -528,
-     -528, -528, -528, -528, -528, -528, -528, -528, -528, -528,
-     -528, -528, -528, -528, -528, -528, -528, -528, -528, -528,
-     -528, -528,  530, -528, -528, -528, -528, -528, -528, -528,
-     -528, -528, -528, -528, -528, -528, -528, -528, -528, -528,
-     -528, -528, -528, -528, -528, -528, -528, -528, -528, -528,
-
-     -528, -528, -528, -528, -528, -528, -528, -528, -528, -528,
-     -528, -528, -528, -528, -528, -528, -528, -528, -528, -528,
-     -528, -528, -528, -528, -528, -528, -528, -528, -528, -528,
-     -528, -528, -528, -528, -528, -528, -528, -528, -528, -528,
-     -528, -528, -528, -528, -528, -528, -528, -528, -528, -528,
-     -528, -528, -528, -528, -528, -528, -528, -528, -528, -528,
-     -528, -528, -528, -528, -528, -528, -528, -528
-    },
-
-    {
-       15, -529, -529, -529, -529, -529, -529, -529, -529, -529,
-     -529, -529, -529, -529, -529, -529, -529, -529, -529, -529,
-     -529, -529, -529, -529, -529, -529, -529, -529, -529, -529,
-
-     -529, -529,  531, -529, -529, -529, -529, -529, -529, -529,
-     -529, -529, -529, -529, -529, -529, -529, -529, -529, -529,
-     -529, -529, -529, -529, -529, -529, -529, -529, -529, -529,
-     -529, -529, -529, -529, -529, -529, -529, -529, -529, -529,
-     -529, -529, -529, -529, -529, -529, -529, -529, -529, -529,
-     -529, -529, -529, -529, -529, -529, -529, -529, -529, -529,
-     -529, -529, -529, -529, -529, -529, -529, -529, -529, -529,
-     -529, -529, -529, -529, -529, -529, -529, -529, -529, -529,
-     -529, -529, -529, -529, -529, -529, -529, -529, -529, -529,
-     -529, -529, -529, -529, -529, -529, -529, -529
-
-    },
-
-    {
-       15, -530, -530, -530, -530, -530, -530, -530, -530, -530,
-     -530, -530, -530, -530, -530, -530, -530, -530, -530, -530,
-     -530, -530, -530, -530, -530, -530, -530, -530, -530, -530,
-     -530, -530,  532, -530, -530, -530, -530, -530, -530, -530,
-     -530, -530, -530, -530, -530, -530, -530, -530, -530, -530,
-     -530, -530, -530, -530, -530, -530, -530, -530, -530, -530,
-     -530, -530, -530, -530, -530, -530, -530, -530, -530, -530,
-     -530, -530, -530, -530, -530, -530, -530, -530, -530, -530,
-     -530, -530, -530, -530, -530, -530, -530, -530, -530, -530,
-     -530, -530, -530, -530, -530, -530, -530, -530, -530, -530,
-
-     -530, -530, -530, -530, -530, -530, -530, -530, -530, -530,
-     -530, -530, -530, -530, -530, -530, -530, -530, -530, -530,
-     -530, -530, -530, -530, -530, -530, -530, -530
-    },
-
-    {
-       15, -531, -531, -531, -531, -531, -531, -531, -531, -531,
-     -531, -531, -531, -531, -531, -531, -531, -531, -531, -531,
-     -531, -531, -531, -531, -531, -531, -531, -531, -531, -531,
-     -531, -531,  533, -531, -531, -531, -531, -531, -531, -531,
-     -531, -531, -531, -531, -531, -531, -531, -531, -531, -531,
-     -531, -531, -531, -531, -531, -531, -531, -531, -531, -531,
-     -531, -531, -531, -531, -531, -531, -531, -531, -531, -531,
-
-     -531, -531, -531, -531, -531, -531, -531, -531, -531, -531,
-     -531, -531, -531, -531, -531, -531, -531, -531, -531, -531,
-     -531, -531, -531, -531, -531, -531, -531, -531, -531, -531,
-     -531, -531, -531, -531, -531, -531, -531, -531, -531, -531,
-     -531, -531, -531, -531, -531, -531, -531, -531, -531, -531,
-     -531, -531, -531, -531, -531, -531, -531, -531
-    },
-
-    {
-       15, -532, -532, -532, -532, -532, -532, -532, -532, -532,
-     -532, -532, -532, -532, -532, -532, -532, -532, -532, -532,
-     -532, -532, -532, -532, -532, -532, -532, -532, -532, -532,
-     -532, -532,  534, -532, -532, -532, -532, -532, -532, -532,
-
-     -532, -532, -532, -532, -532, -532, -532, -532, -532, -532,
-     -532, -532, -532, -532, -532, -532, -532, -532, -532, -532,
-     -532, -532, -532, -532, -532, -532, -532, -532, -532, -532,
-     -532, -532, -532, -532, -532, -532, -532, -532, -532, -532,
-     -532, -532, -532, -532, -532, -532, -532, -532, -532, -532,
-     -532, -532, -532, -532, -532, -532, -532, -532, -532, -532,
-     -532, -532, -532, -532, -532, -532, -532, -532, -532, -532,
-     -532, -532, -532, -532, -532, -532, -532, -532, -532, -532,
-     -532, -532, -532, -532, -532, -532, -532, -532
-    },
-
-    {
-       15, -533, -533, -533, -533, -533, -533, -533, -533, -533,
-
-     -533, -533, -533, -533, -533, -533, -533, -533, -533, -533,
-     -533, -533, -533, -533, -533, -533, -533, -533, -533, -533,
-     -533, -533,  535, -533, -533, -533, -533, -533, -533, -533,
-     -533, -533, -533, -533, -533, -533, -533, -533, -533, -533,
-     -533, -533, -533, -533, -533, -533, -533, -533, -533, -533,
-     -533, -533, -533, -533, -533, -533, -533, -533, -533, -533,
-     -533, -533, -533, -533, -533, -533, -533, -533, -533, -533,
-     -533, -533, -533, -533, -533, -533, -533, -533, -533, -533,
-     -533, -533, -533, -533, -533, -533, -533, -533, -533, -533,
-     -533, -533, -533, -533, -533, -533, -533, -533, -533, -533,
-
-     -533, -533, -533, -533, -533, -533, -533, -533, -533, -533,
-     -533, -533, -533, -533, -533, -533, -533, -533
-    },
-
-    {
-       15, -534, -534, -534, -534, -534, -534, -534, -534, -534,
-     -534, -534, -534, -534, -534, -534, -534, -534, -534, -534,
-     -534, -534, -534, -534, -534, -534, -534, -534, -534, -534,
-     -534, -534,  536, -534, -534, -534, -534, -534, -534, -534,
-     -534, -534, -534, -534, -534, -534, -534, -534, -534, -534,
-     -534, -534, -534, -534, -534, -534, -534, -534, -534, -534,
-     -534, -534, -534, -534, -534, -534, -534, -534, -534, -534,
-     -534, -534, -534, -534, -534, -534, -534, -534, -534, -534,
-
-     -534, -534, -534, -534, -534, -534, -534, -534, -534, -534,
-     -534, -534, -534, -534, -534, -534, -534, -534, -534, -534,
-     -534, -534, -534, -534, -534, -534, -534, -534, -534, -534,
-     -534, -534, -534, -534, -534, -534, -534, -534, -534, -534,
-     -534, -534, -534, -534, -534, -534, -534, -534
-    },
-
-    {
-       15, -535, -535, -535, -535, -535, -535, -535, -535, -535,
-     -535, -535, -535, -535, -535, -535, -535, -535, -535, -535,
-     -535, -535, -535, -535, -535, -535, -535, -535, -535, -535,
-     -535, -535,  537, -535, -535, -535, -535, -535, -535, -535,
-     -535, -535, -535, -535, -535, -535, -535, -535, -535, -535,
-
-     -535, -535, -535, -535, -535, -535, -535, -535, -535, -535,
-     -535, -535, -535, -535, -535, -535, -535, -535, -535, -535,
-     -535, -535, -535, -535, -535, -535, -535, -535, -535, -535,
-     -535, -535, -535, -535, -535, -535, -535, -535, -535, -535,
-     -535, -535, -535, -535, -535, -535, -535, -535, -535, -535,
-     -535, -535, -535, -535, -535, -535, -535, -535, -535, -535,
-     -535, -535, -535, -535, -535, -535, -535, -535, -535, -535,
-     -535, -535, -535, -535, -535, -535, -535, -535
-    },
-
-    {
-       15, -536, -536, -536, -536, -536, -536, -536, -536, -536,
-     -536, -536, -536, -536, -536, -536, -536, -536, -536, -536,
-
-     -536, -536, -536, -536, -536, -536, -536, -536, -536, -536,
-     -536, -536,  538, -536, -536, -536, -536, -536, -536, -536,
-     -536, -536, -536, -536, -536, -536, -536, -536, -536, -536,
-     -536, -536, -536, -536, -536, -536, -536, -536, -536, -536,
-     -536, -536, -536, -536, -536, -536, -536, -536, -536, -536,
-     -536, -536, -536, -536, -536, -536, -536, -536, -536, -536,
-     -536, -536, -536, -536, -536, -536, -536, -536, -536, -536,
-     -536, -536, -536, -536, -536, -536, -536, -536, -536, -536,
-     -536, -536, -536, -536, -536, -536, -536, -536, -536, -536,
-     -536, -536, -536, -536, -536, -536, -536, -536, -536, -536,
-
-     -536, -536, -536, -536, -536, -536, -536, -536
-    },
-
-    {
-       15, -537, -537, -537, -537, -537, -537, -537, -537, -537,
-     -537, -537, -537, -537, -537, -537, -537, -537, -537, -537,
-     -537, -537, -537, -537, -537, -537, -537, -537, -537, -537,
-     -537, -537,  539, -537, -537, -537, -537, -537, -537, -537,
-     -537, -537, -537, -537, -537, -537, -537, -537, -537, -537,
-     -537, -537, -537, -537, -537, -537, -537, -537, -537, -537,
-     -537, -537, -537, -537, -537, -537, -537, -537, -537, -537,
-     -537, -537, -537, -537, -537, -537, -537, -537, -537, -537,
-     -537, -537, -537, -537, -537, -537, -537, -537, -537, -537,
-
-     -537, -537, -537, -537, -537, -537, -537, -537, -537, -537,
-     -537, -537, -537, -537, -537, -537, -537, -537, -537, -537,
-     -537, -537, -537, -537, -537, -537, -537, -537, -537, -537,
-     -537, -537, -537, -537, -537, -537, -537, -537
-    },
-
-    {
-       15, -538, -538, -538, -538, -538, -538, -538, -538, -538,
-     -538, -538, -538, -538, -538, -538, -538, -538, -538, -538,
-     -538, -538, -538, -538, -538, -538, -538, -538, -538, -538,
-     -538, -538,  540, -538, -538, -538, -538, -538, -538, -538,
-     -538, -538, -538, -538, -538, -538, -538, -538, -538, -538,
-     -538, -538, -538, -538, -538, -538, -538, -538, -538, -538,
-
-     -538, -538, -538, -538, -538, -538, -538, -538, -538, -538,
-     -538, -538, -538, -538, -538, -538, -538, -538, -538, -538,
-     -538, -538, -538, -538, -538, -538, -538, -538, -538, -538,
-     -538, -538, -538, -538, -538, -538, -538, -538, -538, -538,
-     -538, -538, -538, -538, -538, -538, -538, -538, -538, -538,
-     -538, -538, -538, -538, -538, -538, -538, -538, -538, -538,
-     -538, -538, -538, -538, -538, -538, -538, -538
-    },
-
-    {
-       15, -539, -539, -539, -539, -539, -539, -539, -539, -539,
-     -539, -539, -539, -539, -539, -539, -539, -539, -539, -539,
-     -539, -539, -539, -539, -539, -539, -539, -539, -539, -539,
-
-     -539, -539,  541, -539, -539, -539, -539, -539, -539, -539,
-     -539, -539, -539, -539, -539, -539, -539, -539, -539, -539,
-     -539, -539, -539, -539, -539, -539, -539, -539, -539, -539,
-     -539, -539, -539, -539, -539, -539, -539, -539, -539, -539,
-     -539, -539, -539, -539, -539, -539, -539, -539, -539, -539,
-     -539, -539, -539, -539, -539, -539, -539, -539, -539, -539,
-     -539, -539, -539, -539, -539, -539, -539, -539, -539, -539,
-     -539, -539, -539, -539, -539, -539, -539, -539, -539, -539,
-     -539, -539, -539, -539, -539, -539, -539, -539, -539, -539,
-     -539, -539, -539, -539, -539, -539, -539, -539
-
-    },
-
-    {
-       15, -540, -540, -540, -540, -540, -540, -540, -540, -540,
-     -540, -540, -540, -540, -540, -540, -540, -540, -540, -540,
-     -540, -540, -540, -540, -540, -540, -540, -540, -540, -540,
-     -540, -540,  542, -540, -540, -540, -540, -540, -540, -540,
-     -540, -540, -540, -540, -540, -540, -540, -540, -540, -540,
-     -540, -540, -540, -540, -540, -540, -540, -540, -540, -540,
-     -540, -540, -540, -540, -540, -540, -540, -540, -540, -540,
-     -540, -540, -540, -540, -540, -540, -540, -540, -540, -540,
-     -540, -540, -540, -540, -540, -540, -540, -540, -540, -540,
-     -540, -540, -540, -540, -540, -540, -540, -540, -540, -540,
-
-     -540, -540, -540, -540, -540, -540, -540, -540, -540, -540,
-     -540, -540, -540, -540, -540, -540, -540, -540, -540, -540,
-     -540, -540, -540, -540, -540, -540, -540, -540
-    },
-
-    {
-       15, -541, -541, -541, -541, -541, -541, -541, -541, -541,
-     -541, -541, -541, -541, -541, -541, -541, -541, -541, -541,
-     -541, -541, -541, -541, -541, -541, -541, -541, -541, -541,
-     -541, -541,  543, -541, -541, -541, -541, -541, -541, -541,
-     -541, -541, -541, -541, -541, -541, -541, -541, -541, -541,
-     -541, -541, -541, -541, -541, -541, -541, -541, -541, -541,
-     -541, -541, -541, -541, -541, -541, -541, -541, -541, -541,
-
-     -541, -541, -541, -541, -541, -541, -541, -541, -541, -541,
-     -541, -541, -541, -541, -541, -541, -541, -541, -541, -541,
-     -541, -541, -541, -541, -541, -541, -541, -541, -541, -541,
-     -541, -541, -541, -541, -541, -541, -541, -541, -541, -541,
-     -541, -541, -541, -541, -541, -541, -541, -541, -541, -541,
-     -541, -541, -541, -541, -541, -541, -541, -541
-    },
-
-    {
-       15, -542, -542, -542, -542, -542, -542, -542, -542, -542,
-     -542, -542, -542, -542, -542, -542, -542, -542, -542, -542,
-     -542, -542, -542, -542, -542, -542, -542, -542, -542, -542,
-     -542, -542,  544, -542, -542, -542, -542, -542, -542, -542,
-
-     -542, -542, -542, -542, -542, -542, -542, -542, -542, -542,
-     -542, -542, -542, -542, -542, -542, -542, -542, -542, -542,
-     -542, -542, -542, -542, -542, -542, -542, -542, -542, -542,
-     -542, -542, -542, -542, -542, -542, -542, -542, -542, -542,
-     -542, -542, -542, -542, -542, -542, -542, -542, -542, -542,
-     -542, -542, -542, -542, -542, -542, -542, -542, -542, -542,
-     -542, -542, -542, -542, -542, -542, -542, -542, -542, -542,
-     -542, -542, -542, -542, -542, -542, -542, -542, -542, -542,
-     -542, -542, -542, -542, -542, -542, -542, -542
-    },
-
-    {
-       15, -543, -543, -543, -543, -543, -543, -543, -543, -543,
-
-     -543, -543, -543, -543, -543, -543, -543, -543, -543, -543,
-     -543, -543, -543, -543, -543, -543, -543, -543, -543, -543,
-     -543, -543,  545, -543, -543, -543, -543, -543, -543, -543,
-     -543, -543, -543, -543, -543, -543, -543, -543, -543, -543,
-     -543, -543, -543, -543, -543, -543, -543, -543, -543, -543,
-     -543, -543, -543, -543, -543, -543, -543, -543, -543, -543,
-     -543, -543, -543, -543, -543, -543, -543, -543, -543, -543,
-     -543, -543, -543, -543, -543, -543, -543, -543, -543, -543,
-     -543, -543, -543, -543, -543, -543, -543, -543, -543, -543,
-     -543, -543, -543, -543, -543, -543, -543, -543, -543, -543,
-
-     -543, -543, -543, -543, -543, -543, -543, -543, -543, -543,
-     -543, -543, -543, -543, -543, -543, -543, -543
-    },
-
-    {
-       15, -544, -544, -544, -544, -544, -544, -544, -544, -544,
-     -544, -544, -544, -544, -544, -544, -544, -544, -544, -544,
-     -544, -544, -544, -544, -544, -544, -544, -544, -544, -544,
-     -544, -544,  546, -544, -544, -544, -544, -544, -544, -544,
-     -544, -544, -544, -544, -544, -544, -544, -544, -544, -544,
-     -544, -544, -544, -544, -544, -544, -544, -544, -544, -544,
-     -544, -544, -544, -544, -544, -544, -544, -544, -544, -544,
-     -544, -544, -544, -544, -544, -544, -544, -544, -544, -544,
-
-     -544, -544, -544, -544, -544, -544, -544, -544, -544, -544,
-     -544, -544, -544, -544, -544, -544, -544, -544, -544, -544,
-     -544, -544, -544, -544, -544, -544, -544, -544, -544, -544,
-     -544, -544, -544, -544, -544, -544, -544, -544, -544, -544,
-     -544, -544, -544, -544, -544, -544, -544, -544
-    },
-
-    {
-       15, -545, -545, -545, -545, -545, -545, -545, -545, -545,
-     -545, -545, -545, -545, -545, -545, -545, -545, -545, -545,
-     -545, -545, -545, -545, -545, -545, -545, -545, -545, -545,
-     -545, -545,  547, -545, -545, -545, -545, -545, -545, -545,
-     -545, -545, -545, -545, -545, -545, -545, -545, -545, -545,
-
-     -545, -545, -545, -545, -545, -545, -545, -545, -545, -545,
-     -545, -545, -545, -545, -545, -545, -545, -545, -545, -545,
-     -545, -545, -545, -545, -545, -545, -545, -545, -545, -545,
-     -545, -545, -545, -545, -545, -545, -545, -545, -545, -545,
-     -545, -545, -545, -545, -545, -545, -545, -545, -545, -545,
-     -545, -545, -545, -545, -545, -545, -545, -545, -545, -545,
-     -545, -545, -545, -545, -545, -545, -545, -545, -545, -545,
-     -545, -545, -545, -545, -545, -545, -545, -545
-    },
-
-    {
-       15, -546, -546, -546, -546, -546, -546, -546, -546, -546,
-     -546, -546, -546, -546, -546, -546, -546, -546, -546, -546,
-
-     -546, -546, -546, -546, -546, -546, -546, -546, -546, -546,
-     -546, -546,  548, -546, -546, -546, -546, -546, -546, -546,
-     -546, -546, -546, -546, -546, -546, -546, -546, -546, -546,
-     -546, -546, -546, -546, -546, -546, -546, -546, -546, -546,
-     -546, -546, -546, -546, -546, -546, -546, -546, -546, -546,
-     -546, -546, -546, -546, -546, -546, -546, -546, -546, -546,
-     -546, -546, -546, -546, -546, -546, -546, -546, -546, -546,
-     -546, -546, -546, -546, -546, -546, -546, -546, -546, -546,
-     -546, -546, -546, -546, -546, -546, -546, -546, -546, -546,
-     -546, -546, -546, -546, -546, -546, -546, -546, -546, -546,
-
-     -546, -546, -546, -546, -546, -546, -546, -546
-    },
-
-    {
-       15, -547, -547, -547, -547, -547, -547, -547, -547, -547,
-     -547, -547, -547, -547, -547, -547, -547, -547, -547, -547,
-     -547, -547, -547, -547, -547, -547, -547, -547, -547, -547,
-     -547, -547,  549, -547, -547, -547, -547, -547, -547, -547,
-     -547, -547, -547, -547, -547, -547, -547, -547, -547, -547,
-     -547, -547, -547, -547, -547, -547, -547, -547, -547, -547,
-     -547, -547, -547, -547, -547, -547, -547, -547, -547, -547,
-     -547, -547, -547, -547, -547, -547, -547, -547, -547, -547,
-     -547, -547, -547, -547, -547, -547, -547, -547, -547, -547,
-
-     -547, -547, -547, -547, -547, -547, -547, -547, -547, -547,
-     -547, -547, -547, -547, -547, -547, -547, -547, -547, -547,
-     -547, -547, -547, -547, -547, -547, -547, -547, -547, -547,
-     -547, -547, -547, -547, -547, -547, -547, -547
-    },
-
-    {
-       15, -548, -548, -548, -548, -548, -548, -548, -548, -548,
-     -548, -548, -548, -548, -548, -548, -548, -548, -548, -548,
-     -548, -548, -548, -548, -548, -548, -548, -548, -548, -548,
-     -548, -548,  550, -548, -548, -548, -548, -548, -548, -548,
-     -548, -548, -548, -548, -548, -548, -548, -548, -548, -548,
-     -548, -548, -548, -548, -548, -548, -548, -548, -548, -548,
-
-     -548, -548, -548, -548, -548, -548, -548, -548, -548, -548,
-     -548, -548, -548, -548, -548, -548, -548, -548, -548, -548,
-     -548, -548, -548, -548, -548, -548, -548, -548, -548, -548,
-     -548, -548, -548, -548, -548, -548, -548, -548, -548, -548,
-     -548, -548, -548, -548, -548, -548, -548, -548, -548, -548,
-     -548, -548, -548, -548, -548, -548, -548, -548, -548, -548,
-     -548, -548, -548, -548, -548, -548, -548, -548
-    },
-
-    {
-       15, -549, -549, -549, -549, -549, -549, -549, -549, -549,
-     -549, -549, -549, -549, -549, -549, -549, -549, -549, -549,
-     -549, -549, -549, -549, -549, -549, -549, -549, -549, -549,
-
-     -549, -549, -549, -549, -549, -549, -549, -549, -549, -549,
-     -549, -549, -549, -549, -549, -549, -549, -549, -549, -549,
-     -549, -549, -549, -549, -549, -549, -549, -549, -549, -549,
-     -549, -549, -549, -549, -549, -549, -549, -549, -549, -549,
-     -549, -549, -549, -549, -549, -549, -549, -549, -549, -549,
-     -549, -549, -549, -549, -549, -549, -549, -549, -549, -549,
-     -549, -549, -549, -549, -549, -549, -549, -549, -549, -549,
-     -549, -549, -549, -549, -549, -549, -549, -549, -549, -549,
-     -549, -549, -549, -549, -549, -549, -549, -549, -549, -549,
-     -549, -549, -549, -549, -549, -549, -549, -549
-
-    },
-
-    {
-       15, -550, -550, -550, -550, -550, -550, -550, -550, -550,
-     -550, -550, -550, -550, -550, -550, -550, -550, -550, -550,
-     -550, -550, -550, -550, -550, -550, -550, -550, -550, -550,
-     -550, -550, -550, -550, -550, -550, -550, -550, -550, -550,
-     -550, -550, -550, -550, -550, -550, -550, -550, -550, -550,
-     -550, -550, -550, -550, -550, -550, -550, -550, -550, -550,
-     -550, -550, -550, -550, -550, -550, -550, -550, -550, -550,
-     -550, -550, -550, -550, -550, -550, -550, -550, -550, -550,
-     -550, -550, -550, -550, -550, -550, -550, -550, -550, -550,
-     -550, -550, -550, -550, -550, -550, -550, -550, -550, -550,
-
-     -550, -550, -550, -550, -550, -550, -550, -550, -550, -550,
-     -550, -550, -550, -550, -550, -550, -550, -550, -550, -550,
-     -550, -550, -550, -550, -550, -550, -550, -550
-    },
-
-    } ;
-
-static yy_state_type yy_get_previous_state (void );
-static yy_state_type yy_try_NUL_trans (yy_state_type current_state  );
-static int yy_get_next_buffer (void );
-static void yy_fatal_error (yyconst char msg[]  );
-
-/* Done after the current pattern has been matched and before the
- * corresponding action - sets up fitshdrtext.
- */
-#define YY_DO_BEFORE_ACTION \
-	(yytext_ptr) = yy_bp; \
-	(yytext_ptr) -= (yy_more_len); \
-	fitshdrleng = (size_t) (yy_cp - (yytext_ptr)); \
-	(yy_hold_char) = *yy_cp; \
-	*yy_cp = '\0'; \
-	(yy_c_buf_p) = yy_cp;
-
-#define YY_NUM_RULES 31
-#define YY_END_OF_BUFFER 32
-/* This struct is not used in this scanner,
-   but its presence is necessary. */
-struct yy_trans_info
-	{
-	flex_int32_t yy_verify;
-	flex_int32_t yy_nxt;
-	};
-static yyconst flex_int16_t yy_accept[551] =
-    {   0,
-        0,    0,    0,    0,    0,    0,    0,    0,   28,   28,
-       29,   29,    0,    0,   32,   31,   31,   31,   31,   31,
-       31,   31,   20,   20,   20,   20,   20,   20,   11,   13,
-       13,   12,   25,   21,   24,   23,   27,   27,   28,   29,
-       31,   30,    0,    0,    0,    0,    0,    0,    0,    0,
-       11,    0,   19,    0,    0,    0,    0,    0,   13,   13,
-       16,   16,   13,   13,    0,   13,   21,    0,   23,   22,
-       23,    0,   28,   29,    0,   30,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,   16,   13,   13,   13,    0,   16,   13,   26,    0,
-
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,   13,   13,
-       13,   13,   13,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,   17,
-        0,    0,    0,   13,   13,   13,   13,   13,   13,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,   18,    0,    0,    0,    0,   13,   13,   13,
-       13,   13,   13,   13,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    2,    0,    0,   13,   13,   13,   13,
-       13,   13,   13,   13,   10,    2,    8,    8,    8,    5,
-
-       13,   13,   13,   13,   13,   13,   13,   13,   13,    0,
-        0,    0,    0,    0,    0,   13,   13,   13,   13,   13,
-       13,   13,   13,   13,   13,    9,    0,    6,    0,    0,
-        4,   13,   13,   13,   13,   13,   13,   13,   13,   13,
-       13,   14,    0,    0,    0,   13,   13,   13,   13,   13,
-       13,   13,   13,   13,   13,   14,   14,    0,    0,    7,
-        0,   13,   13,   13,   13,   13,   13,   13,   13,   13,
-       13,   14,   14,   14,    0,    0,   13,   13,   13,   13,
-       13,   13,   13,   13,   13,   13,   14,   14,   14,   14,
-        0,    0,   13,   13,   13,   13,   13,   13,   13,   13,
-
-       13,   13,   14,   14,   14,   14,   14,    0,    0,   13,
-       13,   13,   13,   13,   13,   13,   13,   13,   13,   14,
-       14,   14,   14,   14,   14,    0,    0,   13,   13,   13,
-       13,   13,   13,   13,   13,   13,   13,   14,   14,   14,
-       14,   14,   14,   14,    0,    0,   13,   13,   13,   13,
-       13,   13,   13,   13,   13,   13,   14,   14,   14,   14,
-       14,   14,   14,   14,    0,    0,   13,   13,   13,   13,
-       13,   13,   13,   13,   13,   13,   14,   14,   14,   14,
-       14,   14,   14,   14,   14,    0,    0,   13,   13,   13,
-       13,   13,   13,   13,   13,   13,   13,   14,   14,   14,
-
-       14,   14,   14,   14,   14,   14,   15,    0,    0,   13,
-       13,   13,   13,   13,   13,   13,   13,   13,   13,   14,
-       14,   14,   14,   14,   14,   14,   14,   14,   15,   15,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    1,    3
-    } ;
-
-static yy_state_type yy_last_accepting_state;
-static char *yy_last_accepting_cpos;
-
-static yyconst yy_state_type yy_NUL_trans[551] =
-    {   0,
-       16,   17,   23,   23,   33,   33,   37,   37,   39,   39,
-       40,   40,   41,   41,    0,    0,   43,   43,   43,   43,
-       43,   43,    0,    0,   52,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,   73,   74,
-       75,    0,   77,   77,   77,   77,   77,   77,   77,    0,
-        0,   52,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,   73,   74,   75,    0,  100,  100,  100,  100,
-      100,  100,  100,  100,  100,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,  124,
-
-      124,  124,  124,  124,  124,  124,  124,  124,  124,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,  150,  150,  150,  150,  150,  150,  150,
-      150,  150,  150,  150,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,  175,
-      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
-      175,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,  195,  195,  195,  195,  195,  195,
-      195,  195,  195,  195,  195,  195,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,  259,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,  259,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0
-    } ;
-
-extern int fitshdr_flex_debug;
-int fitshdr_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
-static int yy_more_flag = 0;
-static int yy_more_len = 0;
-#define yymore() ((yy_more_flag) = 1)
-#define YY_MORE_ADJ (yy_more_len)
-#define YY_RESTORE_YY_MORE_OFFSET
-char *fitshdrtext;
-#line 1 "fitshdr.l"
-/*============================================================================
-
-  WCSLIB 4.10 - an implementation of the FITS WCS standard.
-  Copyright (C) 1995-2012, Mark Calabretta
-
-  This file is part of WCSLIB.
-
-  WCSLIB is free software: you can redistribute it and/or modify it under the
-  terms of the GNU Lesser General Public License as published by the Free
-  Software Foundation, either version 3 of the License, or (at your option)
-  any later version.
-
-  WCSLIB 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 Lesser General Public License for
-  more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with WCSLIB.  If not, see <http://www.gnu.org/licenses/>.
-
-  Correspondence concerning WCSLIB may be directed to:
-    Internet email: mcalabre at atnf.csiro.au
-    Postal address: Dr. Mark Calabretta
-                    Australia Telescope National Facility, CSIRO
-                    PO Box 76
-                    Epping NSW 1710
-                    AUSTRALIA
-
-  Author: Mark Calabretta, Australia Telescope National Facility
-  http://www.atnf.csiro.au/~mcalabre/index.html
-  $Id: fitshdr.c,v 4.10 2012/02/05 23:41:44 cal103 Exp $
-*=============================================================================
-*
-* fitshdr.l is a Flex description file containing a lexical scanner
-* definition for extracting keywords and keyvalues from a FITS header.
-*
-* It requires Flex v2.5.4 or later.
-*
-* Refer to fitshdr.h for a description of the user interface and operating
-* notes.
-*
-*===========================================================================*/
-/* Options. */
-/* Keywords. */
-/* Keyvalue data types. */
-/* Characters forming standard unit strings (jwBIQX are not used). */
-/* Exclusive start states. */
-
-#line 82 "fitshdr.l"
-#include <math.h>
-#include <limits.h>
-#include <setjmp.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "fitshdr.h"
-
-#define YY_DECL int fitshdr(const char header[], int nkeyrec, int nkeyids, \
-                            struct fitskeyid keyids[], int *nreject, \
-                            struct fitskey **keys)
-
-#define YY_INPUT(inbuff, count, bufsize) \
-	{ \
-	  if (fitshdr_nkeyrec) { \
-	    strncpy(inbuff, fitshdr_hdr, 80); \
-	    inbuff[80] = '\n'; \
-	    fitshdr_hdr += 80; \
-	    fitshdr_nkeyrec--; \
-	    count = 81; \
-	  } else { \
-	    count = YY_NULL; \
-	  } \
-	}
-
-/* These global variables are required by YY_INPUT. */
-const char *fitshdr_hdr;
-int  fitshdr_nkeyrec;
-
-/* Used in preempting the call to exit() by yy_fatal_error(). */
-jmp_buf fitshdr_abort_jmp_env;
-#define exit(status) longjmp(fitshdr_abort_jmp_env, status)
-
-/* Map status return value to message. */
-const char *fitshdr_errmsg[] = {
-   "Success",
-   "Null fitskey pointer-pointer passed",
-   "Memory allocation failed",
-   "Fatal error returned by Flex parser"};
-
-#line 10174 "fitshdr.c"
-
-#define INITIAL 0
-#define VALUE 1
-#define INLINE 2
-#define UNITS 3
-#define COMMENT 4
-#define ERROR 5
-#define FLUSH 6
-
-#ifndef YY_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 <unistd.h>
-#endif
-
-#ifndef YY_EXTRA_TYPE
-#define YY_EXTRA_TYPE void *
-#endif
-
-static int yy_init_globals (void );
-
-/* Accessor methods to globals.
-   These are made visible to non-reentrant scanners for convenience. */
-
-int fitshdrlex_destroy (void );
-
-int fitshdrget_debug (void );
-
-void fitshdrset_debug (int debug_flag  );
-
-YY_EXTRA_TYPE fitshdrget_extra (void );
-
-void fitshdrset_extra (YY_EXTRA_TYPE user_defined  );
-
-FILE *fitshdrget_in (void );
-
-void fitshdrset_in  (FILE * in_str  );
-
-FILE *fitshdrget_out (void );
-
-void fitshdrset_out  (FILE * out_str  );
-
-int fitshdrget_leng (void );
-
-char *fitshdrget_text (void );
-
-int fitshdrget_lineno (void );
-
-void fitshdrset_lineno (int line_number  );
-
-/* Macros after this point can all be overridden by user definitions in
- * section 1.
- */
-
-#ifndef YY_SKIP_YYWRAP
-#ifdef __cplusplus
-extern "C" int fitshdrwrap (void );
-#else
-extern int fitshdrwrap (void );
-#endif
-#endif
-
-#ifndef yytext_ptr
-static void yy_flex_strncpy (char *,yyconst char *,int );
-#endif
-
-#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * );
-#endif
-
-#ifndef YY_NO_INPUT
-
-#ifdef __cplusplus
-static int yyinput (void );
-#else
-static int input (void );
-#endif
-
-#endif
-
-/* Amount of stuff to slurp up with each read. */
-#ifndef YY_READ_BUF_SIZE
-#ifdef __ia64__
-/* On IA-64, the buffer size is 16k, not 8k */
-#define YY_READ_BUF_SIZE 16384
-#else
-#define YY_READ_BUF_SIZE 8192
-#endif /* __ia64__ */
-#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( fitshdrtext, fitshdrleng, 1, fitshdrout )) {} } while (0)
-#endif
-
-/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
- * is returned in "result".
- */
-#ifndef YY_INPUT
-#define YY_INPUT(buf,result,max_size) \
-	errno=0; \
-	while ( (result = read( fileno(fitshdrin), (char *) buf, max_size )) < 0 ) \
-	{ \
-		if( errno != EINTR) \
-		{ \
-			YY_FATAL_ERROR( "input in flex scanner failed" ); \
-			break; \
-		} \
-		errno=0; \
-		clearerr(fitshdrin); \
-	}\
-\
-
-#endif
-
-/* No semi-colon after return; correct usage is to write "yyterminate();" -
- * we don't want an extra ';' after the "return" because that will cause
- * some compilers to complain about unreachable statements.
- */
-#ifndef yyterminate
-#define yyterminate() return YY_NULL
-#endif
-
-/* Number of entries by which start-condition stack grows. */
-#ifndef YY_START_STACK_INCR
-#define YY_START_STACK_INCR 25
-#endif
-
-/* Report a fatal error. */
-#ifndef YY_FATAL_ERROR
-#define YY_FATAL_ERROR(msg) yy_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 YY_DECL
-#define YY_DECL_IS_OURS 1
-
-extern int fitshdrlex (void);
-
-#define YY_DECL int fitshdrlex (void)
-#endif /* !YY_DECL */
-
-/* Code executed at the beginning of each rule, after fitshdrtext and fitshdrleng
- * have been set up.
- */
-#ifndef YY_USER_ACTION
-#define YY_USER_ACTION
-#endif
-
-/* Code executed at the end of each rule. */
-#ifndef YY_BREAK
-#define YY_BREAK break;
-#endif
-
-#define YY_RULE_SETUP \
-	if ( fitshdrleng > 0 ) \
-		YY_CURRENT_BUFFER_LVALUE->yy_at_bol = \
-				(fitshdrtext[fitshdrleng - 1] == '\n'); \
-	YY_USER_ACTION
-
-/** The main scanner function which does all the work.
- */
-YY_DECL
-{
-	register yy_state_type yy_current_state;
-	register char *yy_cp, *yy_bp;
-	register int yy_act;
-    
-#line 124 "fitshdr.l"
-
-	char *cptr, ctmp[72];
-	int  blank, continuation, end, j, k, keyno;
-	double dtmp;
-	struct fitskey *kptr;
-	struct fitskeyid *iptr;
-	void nullfill(char cptr[], int len);
-	int  fitshdrlex_destroy(void);
-	
-	fitshdr_hdr = header;
-	fitshdr_nkeyrec = nkeyrec;
-	
-	*nreject = 0;
-	keyno = 0;
-	
-	if (keys == 0x0) {
-	  return 1;
-	}
-	
-	/* Allocate memory for the required number of fitskey structs. */
-	/* Recall that calloc() initializes allocated memory to zero.  */
-	if (!(kptr = *keys = calloc(nkeyrec, sizeof(struct fitskey)))) {
-	  return 2;
-	}
-	
-	/* Initialize keyids[]. */
-	iptr = keyids;
-	for (j = 0; j < nkeyids; j++, iptr++) {
-	  iptr->count  = 0;
-	  iptr->idx[0] = -1;
-	  iptr->idx[1] = -1;
-	}
-	
-	blank = 0;
-	continuation = 0;
-	end = 0;
-	
-	/* Return here via longjmp() invoked by yy_fatal_error(). */
-	if (setjmp(fitshdr_abort_jmp_env)) {
-	  return 3;
-	}
-	
-	BEGIN(INITIAL);
-
-#line 10397 "fitshdr.c"
-
-	if ( !(yy_init) )
-		{
-		(yy_init) = 1;
-
-#ifdef YY_USER_INIT
-		YY_USER_INIT;
-#endif
-
-		if ( ! (yy_start) )
-			(yy_start) = 1;	/* first start state */
-
-		if ( ! fitshdrin )
-			fitshdrin = stdin;
-
-		if ( ! fitshdrout )
-			fitshdrout = stdout;
-
-		if ( ! YY_CURRENT_BUFFER ) {
-			fitshdrensure_buffer_stack ();
-			YY_CURRENT_BUFFER_LVALUE =
-				fitshdr_create_buffer(fitshdrin,YY_BUF_SIZE );
-		}
-
-		fitshdr_load_buffer_state( );
-		}
-
-	while ( 1 )		/* loops until end-of-file is reached */
-		{
-		(yy_more_len) = 0;
-		if ( (yy_more_flag) )
-			{
-			(yy_more_len) = (yy_c_buf_p) - (yytext_ptr);
-			(yy_more_flag) = 0;
-			}
-		yy_cp = (yy_c_buf_p);
-
-		/* Support of fitshdrtext. */
-		*yy_cp = (yy_hold_char);
-
-		/* yy_bp points to the position in yy_ch_buf of the start of
-		 * the current run.
-		 */
-		yy_bp = yy_cp;
-
-		yy_current_state = (yy_start);
-		yy_current_state += YY_AT_BOL();
-yy_match:
-		while ( (yy_current_state = yy_nxt[yy_current_state][ YY_SC_TO_UI(*yy_cp) ]) > 0 )
-			{
-			if ( yy_accept[yy_current_state] )
-				{
-				(yy_last_accepting_state) = yy_current_state;
-				(yy_last_accepting_cpos) = yy_cp;
-				}
-
-			++yy_cp;
-			}
-
-		yy_current_state = -yy_current_state;
-
-yy_find_action:
-		yy_act = yy_accept[yy_current_state];
-
-		YY_DO_BEFORE_ACTION;
-
-do_action:	/* This label is used only to access EOF actions. */
-
-		switch ( yy_act )
-	{ /* beginning of action switch */
-			case 0: /* must back up */
-			/* undo the effects of YY_DO_BEFORE_ACTION */
-			*yy_cp = (yy_hold_char);
-			yy_cp = (yy_last_accepting_cpos) + 1;
-			yy_current_state = (yy_last_accepting_state);
-			goto yy_find_action;
-
-case 1:
-YY_RULE_SETUP
-#line 168 "fitshdr.l"
-{
-	  /* A completely blank keyrecord. */
-	  strncpy(kptr->keyword, fitshdrtext, 8);
-	  yyless(0);
-	  blank = 1;
-	  BEGIN(COMMENT);
-	}
-	YY_BREAK
-case 2:
-YY_RULE_SETUP
-#line 176 "fitshdr.l"
-{
-	  strncpy(kptr->keyword, fitshdrtext, 8);
-	  BEGIN(COMMENT);
-	}
-	YY_BREAK
-case 3:
-YY_RULE_SETUP
-#line 181 "fitshdr.l"
-{
-	  strncpy(kptr->keyword, fitshdrtext, 8);
-	  end = 1;
-	  BEGIN(FLUSH);
-	}
-	YY_BREAK
-case 4:
-YY_RULE_SETUP
-#line 187 "fitshdr.l"
-{
-	  /* Illegal END keyrecord. */
-	  strncpy(kptr->keyword, fitshdrtext, 8);
-	  kptr->status |= FITSHDR_KEYREC;
-	  BEGIN(VALUE);
-	}
-	YY_BREAK
-case 5:
-YY_RULE_SETUP
-#line 194 "fitshdr.l"
-{
-	  /* Illegal END keyrecord. */
-	  strncpy(kptr->keyword, fitshdrtext, 8);
-	  kptr->status |= FITSHDR_KEYREC;
-	  BEGIN(COMMENT);
-	}
-	YY_BREAK
-case 6:
-YY_RULE_SETUP
-#line 201 "fitshdr.l"
-{
-	  strncpy(kptr->keyword, fitshdrtext, 8);
-	  BEGIN(VALUE);
-	}
-	YY_BREAK
-case 7:
-/* rule 7 can match eol */
-YY_RULE_SETUP
-#line 206 "fitshdr.l"
-{
-	  /* Continued string keyvalue. */
-	  strncpy(kptr->keyword, fitshdrtext, 8);
-	
-	  if (keyno > 0 && (kptr-1)->type%10 == 8) {
-	    /* Put back the string keyvalue. */
-	    for (k = 10; fitshdrtext[k] != '\''; k++);
-	    yyless(k);
-	    continuation = 1;
-	    BEGIN(VALUE);
-	
-	  } else {
-	    /* Not a valid continuation. */
-	    yyless(8);
-	    BEGIN(COMMENT);
-	  }
-	}
-	YY_BREAK
-case 8:
-YY_RULE_SETUP
-#line 224 "fitshdr.l"
-{
-	  /* Keyword without value. */
-	  strncpy(kptr->keyword, fitshdrtext, 8);
-	  BEGIN(COMMENT);
-	}
-	YY_BREAK
-case 9:
-YY_RULE_SETUP
-#line 230 "fitshdr.l"
-{
-	  /* Illegal keyword, carry on regardless. */
-	  strncpy(kptr->keyword, fitshdrtext, 8);
-	  kptr->status |= FITSHDR_KEYWORD;
-	  BEGIN(VALUE);
-	}
-	YY_BREAK
-case 10:
-YY_RULE_SETUP
-#line 237 "fitshdr.l"
-{
-	  /* Illegal keyword, carry on regardless. */
-	  strncpy(kptr->keyword, fitshdrtext, 8);
-	  kptr->status |= FITSHDR_KEYWORD;
-	  BEGIN(COMMENT);
-	}
-	YY_BREAK
-case 11:
-*yy_cp = (yy_hold_char); /* undo effects of setting up fitshdrtext */
-(yy_c_buf_p) = yy_cp -= 1;
-YY_DO_BEFORE_ACTION; /* set up fitshdrtext again */
-YY_RULE_SETUP
-#line 244 "fitshdr.l"
-{
-	  /* Null keyvalue. */
-	  BEGIN(INLINE);
-	}
-	YY_BREAK
-case 12:
-YY_RULE_SETUP
-#line 249 "fitshdr.l"
-{
-	  /* Logical keyvalue. */
-	  kptr->type = 1;
-	  kptr->keyvalue.i = (*fitshdrtext == 'T');
-	  BEGIN(INLINE);
-	}
-	YY_BREAK
-case 13:
-YY_RULE_SETUP
-#line 256 "fitshdr.l"
-{
-	  /* 32-bit signed integer keyvalue. */
-	  kptr->type = 2;
-	  if (sscanf(fitshdrtext, "%d", &(kptr->keyvalue.i)) < 1) {
-	    kptr->status |= FITSHDR_KEYVALUE;
-	    BEGIN(ERROR);
-	  }
-	
-	  BEGIN(INLINE);
-	}
-	YY_BREAK
-case 14:
-YY_RULE_SETUP
-#line 267 "fitshdr.l"
-{
-	  /* 64-bit signed integer keyvalue (up to 18 digits). */
-	  if (sscanf(fitshdrtext, "%lf", &dtmp) < 1) {
-	    kptr->status |= FITSHDR_KEYVALUE;
-	    BEGIN(ERROR);
-	
-	  } else if (INT_MIN <= dtmp && dtmp <= INT_MAX) {
-	    /* Can be accomodated as a 32-bit signed integer. */
-	    kptr->type = 2;
-	    if (sscanf(fitshdrtext, "%d", &(kptr->keyvalue.i)) < 1) {
-	      kptr->status |= FITSHDR_KEYVALUE;
-	      BEGIN(ERROR);
-	    }
-	
-	  } else {
-	    /* 64-bit signed integer. */
-	    kptr->type = 3;
-#ifdef WCSLIB_INT64
-	      /* Native 64-bit integer is available. */
-	      if (sscanf(fitshdrtext, "%lld", &(kptr->keyvalue.k)) < 1) {
-	        kptr->status |= FITSHDR_KEYVALUE;
-	        BEGIN(ERROR);
-	      }
-#else
-	      /* 64-bit integer (up to 18 digits) implemented as int[3]. */
-	      kptr->keyvalue.k[2] = 0;
-	
-	      sprintf(ctmp, "%%%dd%%9d", fitshdrleng-9);
-	      if (sscanf(fitshdrtext, ctmp, kptr->keyvalue.k+1,
-	                 kptr->keyvalue.k) < 1) {
-	        kptr->status |= FITSHDR_KEYVALUE;
-	        BEGIN(ERROR);
-	      } else if (*fitshdrtext == '-') {
-	        kptr->keyvalue.k[0] *= -1;
-	      }
-#endif
-	  }
-	
-	  BEGIN(INLINE);
-	}
-	YY_BREAK
-case 15:
-YY_RULE_SETUP
-#line 308 "fitshdr.l"
-{
-	  /* Very long integer keyvalue (and 19-digit int64). */
-	  kptr->type = 4;
-	  strcpy(ctmp, fitshdrtext);
-	  k = fitshdrleng;
-	  for (j = 0; j < 8; j++) {
-	    /* Read it backwards. */
-	    k -= 9;
-	    if (k < 0) k = 0;
-	    if (sscanf(ctmp+k, "%d", kptr->keyvalue.l+j) < 1) {
-	      kptr->status |= FITSHDR_KEYVALUE;
-	      BEGIN(ERROR);
-	    }
-	    if (*fitshdrtext == '-') {
-	      kptr->keyvalue.l[j] = -abs(kptr->keyvalue.l[j]);
-	    }
-	
-	    if (k == 0) break;
-	    ctmp[k] = '\0';
-	  }
-	
-	  /* Can it be accomodated as a 64-bit signed integer? */
-	  if (j == 2 && abs(kptr->keyvalue.l[2]) <=  9 &&
-	                abs(kptr->keyvalue.l[1]) <=  223372036 &&
-	                    kptr->keyvalue.l[0]  <=  854775807 &&
-	                    kptr->keyvalue.l[0]  >= -854775808) {
-	    kptr->type = 3;
-	
-#ifdef WCSLIB_INT64
-	      /* Native 64-bit integer is available. */
-	      kptr->keyvalue.l[2] = 0;
-	      if (sscanf(fitshdrtext, "%lld", &(kptr->keyvalue.k)) < 1) {
-	        kptr->status |= FITSHDR_KEYVALUE;
-	        BEGIN(ERROR);
-	      }
-#endif
-	  }
-	
-	  BEGIN(INLINE);
-	}
-	YY_BREAK
-case 16:
-YY_RULE_SETUP
-#line 349 "fitshdr.l"
-{
-	  /* Float keyvalue. */
-	  kptr->type = 5;
-	  if (sscanf(fitshdrtext, "%lf", &(kptr->keyvalue.f)) < 1) {
-	    kptr->status |= FITSHDR_KEYVALUE;
-	    BEGIN(ERROR);
-	  }
-	
-	  BEGIN(INLINE);
-	}
-	YY_BREAK
-case 17:
-YY_RULE_SETUP
-#line 360 "fitshdr.l"
-{
-	  /* Integer complex keyvalue. */
-	  kptr->type = 6;
-	  if (sscanf(fitshdrtext, "(%lf,%lf)", kptr->keyvalue.c,
-	      kptr->keyvalue.c+1) < 2) {
-	    kptr->status |= FITSHDR_KEYVALUE;
-	    BEGIN(ERROR);
-	  }
-	
-	  BEGIN(INLINE);
-	}
-	YY_BREAK
-case 18:
-YY_RULE_SETUP
-#line 372 "fitshdr.l"
-{
-	  /* Floating point complex keyvalue. */
-	  kptr->type = 7;
-	  if (sscanf(fitshdrtext, "(%lf,%lf)", kptr->keyvalue.c,
-	      kptr->keyvalue.c+1) < 2) {
-	    kptr->status |= FITSHDR_KEYVALUE;
-	    BEGIN(ERROR);
-	  }
-	
-	  BEGIN(INLINE);
-	}
-	YY_BREAK
-case 19:
-/* rule 19 can match eol */
-YY_RULE_SETUP
-#line 384 "fitshdr.l"
-{
-	  /* String keyvalue. */
-	  kptr->type = 8;
-	  cptr = kptr->keyvalue.s;
-	  strcpy(cptr, fitshdrtext+1);
-	
-	  /* Squeeze out repeated quotes. */
-	  k = 0;
-	  for (j = 0; j < 72; j++) {
-	    if (k < j) {
-	      cptr[k] = cptr[j];
-	    }
-	
-	    if (cptr[j] == '\0') {
-	      if (k) cptr[k-1] = '\0';
-	      break;
-	    } else if (cptr[j] == '\'' && cptr[j+1] == '\'') {
-	      j++;
-	    }
-	
-	    k++;
-	  }
-	
-	  if (*cptr) {
-	    /* Retain the initial blank in all-blank strings. */
-	    nullfill(cptr+1, 71);
-	  } else {
-	    nullfill(cptr, 72);
-	  }
-	
-	  BEGIN(INLINE);
-	}
-	YY_BREAK
-case 20:
-YY_RULE_SETUP
-#line 417 "fitshdr.l"
-{
-	  kptr->status |= FITSHDR_KEYVALUE;
-	  BEGIN(ERROR);
-	}
-	YY_BREAK
-case 21:
-*yy_cp = (yy_hold_char); /* undo effects of setting up fitshdrtext */
-(yy_c_buf_p) = yy_cp -= 1;
-YY_DO_BEFORE_ACTION; /* set up fitshdrtext again */
-YY_RULE_SETUP
-#line 422 "fitshdr.l"
-{
-	  BEGIN(FLUSH);
-	}
-	YY_BREAK
-case 22:
-*yy_cp = (yy_hold_char); /* undo effects of setting up fitshdrtext */
-(yy_c_buf_p) = yy_cp -= 1;
-YY_DO_BEFORE_ACTION; /* set up fitshdrtext again */
-YY_RULE_SETUP
-#line 426 "fitshdr.l"
-{
-	  BEGIN(FLUSH);
-	}
-	YY_BREAK
-case 23:
-YY_RULE_SETUP
-#line 430 "fitshdr.l"
-{
-	  BEGIN(UNITS);
-	}
-	YY_BREAK
-case 24:
-YY_RULE_SETUP
-#line 434 "fitshdr.l"
-{
-	  kptr->status |= FITSHDR_COMMENT;
-	  BEGIN(ERROR);
-	}
-	YY_BREAK
-case 25:
-YY_RULE_SETUP
-#line 439 "fitshdr.l"
-{
-	  /* Keyvalue parsing must now also be suspect. */
-	  kptr->status |= FITSHDR_COMMENT;
-	  kptr->type = 0;
-	  BEGIN(ERROR);
-	}
-	YY_BREAK
-case 26:
-YY_RULE_SETUP
-#line 446 "fitshdr.l"
-{
-	  kptr->ulen = fitshdrleng;
-	  yymore();
-	  BEGIN(COMMENT);
-	}
-	YY_BREAK
-case 27:
-YY_RULE_SETUP
-#line 452 "fitshdr.l"
-{
-	  yymore();
-	  BEGIN(COMMENT);
-	}
-	YY_BREAK
-case 28:
-YY_RULE_SETUP
-#line 457 "fitshdr.l"
-{
-	  strcpy(kptr->comment, fitshdrtext);
-	  nullfill(kptr->comment, 84);
-	  BEGIN(FLUSH);
-	}
-	YY_BREAK
-case 29:
-YY_RULE_SETUP
-#line 463 "fitshdr.l"
-{
-	  if (!continuation) kptr->type = -abs(kptr->type);
-	
-	  sprintf(kptr->comment, "%.80s", fitshdr_hdr-80);
-	  kptr->comment[80] = '\0';
-	  nullfill(kptr->comment+80, 4);
-	
-	  BEGIN(FLUSH);
-	}
-	YY_BREAK
-case 30:
-/* rule 30 can match eol */
-YY_RULE_SETUP
-#line 473 "fitshdr.l"
-{
-	  /* Discard the rest of the input line. */
-	  kptr->keyno = ++keyno;
-	
-	  /* Null-fill the keyword. */
-	  kptr->keyword[8] = '\0';
-	  nullfill(kptr->keyword, 12);
-	
-	  /* Do indexing. */
-	  iptr = keyids;
-	  kptr->keyid = -1;
-	  for (j = 0; j < nkeyids; j++, iptr++) {
-	    cptr = iptr->name;
-	    cptr[8] = '\0';
-	    nullfill(cptr, 12);
-	    for (k = 0; k < 8; k++, cptr++) {
-	      if (*cptr != '.' && *cptr != kptr->keyword[k]) break;
-	    }
-	
-	    if (k == 8) {
-	      /* Found a match. */
-	      iptr->count++;
-	      if (iptr->idx[0] == -1) {
-	        iptr->idx[0] = keyno-1;
-	      } else {
-	        iptr->idx[1] = keyno-1;
-	      }
-	
-	      kptr->keyno = -abs(kptr->keyno);
-	      if (kptr->keyid < 0) kptr->keyid = j;
-	    }
-	  }
-	
-	  /* Deal with continued strings. */
-	  if (continuation) {
-	    /* Tidy up the previous string keyvalue. */
-	    if ((kptr-1)->type == 8) (kptr-1)->type += 10;
-	    cptr = (kptr-1)->keyvalue.s;
-	    if (cptr[strlen(cptr)-1] == '&') cptr[strlen(cptr)-1] = '\0';
-	
-	    kptr->type = (kptr-1)->type + 10;
-	  }
-	
-	  /* Check for keyrecords following the END keyrecord. */
-	  if (end && (end++ > 1) && !blank) {
-	    kptr->status |= FITSHDR_TRAILER;
-	  }
-	  if (kptr->status) (*nreject)++;
-	
-	  kptr++;
-	  blank = 0;
-	  continuation = 0;
-	
-	  BEGIN(INITIAL);
-	}
-	YY_BREAK
-case YY_STATE_EOF(INITIAL):
-case YY_STATE_EOF(VALUE):
-case YY_STATE_EOF(INLINE):
-case YY_STATE_EOF(UNITS):
-case YY_STATE_EOF(COMMENT):
-case YY_STATE_EOF(ERROR):
-case YY_STATE_EOF(FLUSH):
-#line 529 "fitshdr.l"
-{
-	  /* End-of-input. */
-	  fitshdrlex_destroy();
-	  return 0;
-	}
-	YY_BREAK
-case 31:
-YY_RULE_SETUP
-#line 535 "fitshdr.l"
-ECHO;
-	YY_BREAK
-#line 10957 "fitshdr.c"
-
-	case YY_END_OF_BUFFER:
-		{
-		/* Amount of text matched not including the EOB char. */
-		int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;
-
-		/* Undo the effects of YY_DO_BEFORE_ACTION. */
-		*yy_cp = (yy_hold_char);
-		YY_RESTORE_YY_MORE_OFFSET
-
-		if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
-			{
-			/* We're scanning a new file or input source.  It's
-			 * possible that this happened because the user
-			 * just pointed fitshdrin at a new source and called
-			 * fitshdrlex().  If so, then we have to assure
-			 * consistency between YY_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.
-			 */
-			(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
-			YY_CURRENT_BUFFER_LVALUE->yy_input_file = fitshdrin;
-			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
-			}
-
-		/* Note that here we test for yy_c_buf_p "<=" to the position
-		 * of the first EOB in the buffer, since yy_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 ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
-			{ /* This was really a NUL. */
-			yy_state_type yy_next_state;
-
-			(yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;
-
-			yy_current_state = yy_get_previous_state(  );
-
-			/* Okay, we're now positioned to make the NUL
-			 * transition.  We couldn't have
-			 * yy_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).
-			 */
-
-			yy_next_state = yy_try_NUL_trans( yy_current_state );
-
-			yy_bp = (yytext_ptr) + YY_MORE_ADJ;
-
-			if ( yy_next_state )
-				{
-				/* Consume the NUL. */
-				yy_cp = ++(yy_c_buf_p);
-				yy_current_state = yy_next_state;
-				goto yy_match;
-				}
-
-			else
-				{
-				yy_cp = (yy_c_buf_p);
-				goto yy_find_action;
-				}
-			}
-
-		else switch ( yy_get_next_buffer(  ) )
-			{
-			case EOB_ACT_END_OF_FILE:
-				{
-				(yy_did_buffer_switch_on_eof) = 0;
-
-				if ( fitshdrwrap( ) )
-					{
-					/* Note: because we've taken care in
-					 * yy_get_next_buffer() to have set up
-					 * fitshdrtext, we can now set up
-					 * yy_c_buf_p so that if some total
-					 * hoser (like flex itself) wants to
-					 * call the scanner after we return the
-					 * YY_NULL, it'll still work - another
-					 * YY_NULL will get returned.
-					 */
-					(yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;
-
-					yy_act = YY_STATE_EOF(YY_START);
-					goto do_action;
-					}
-
-				else
-					{
-					if ( ! (yy_did_buffer_switch_on_eof) )
-						YY_NEW_FILE;
-					}
-				break;
-				}
-
-			case EOB_ACT_CONTINUE_SCAN:
-				(yy_c_buf_p) =
-					(yytext_ptr) + yy_amount_of_matched_text;
-
-				yy_current_state = yy_get_previous_state(  );
-
-				yy_cp = (yy_c_buf_p);
-				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
-				goto yy_match;
-
-			case EOB_ACT_LAST_MATCH:
-				(yy_c_buf_p) =
-				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];
-
-				yy_current_state = yy_get_previous_state(  );
-
-				yy_cp = (yy_c_buf_p);
-				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
-				goto yy_find_action;
-			}
-		break;
-		}
-
-	default:
-		YY_FATAL_ERROR(
-			"fatal flex scanner internal error--no action found" );
-	} /* end of action switch */
-		} /* end of scanning one token */
-} /* end of fitshdrlex */
-
-/* yy_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 yy_get_next_buffer (void)
-{
-    	register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
-	register char *source = (yytext_ptr);
-	register int number_to_move, i;
-	int ret_val;
-
-	if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
-		YY_FATAL_ERROR(
-		"fatal flex scanner internal error--end of buffer missed" );
-
-	if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
-		{ /* Don't try to fill the buffer, so this is an EOF. */
-		if ( (yy_c_buf_p) - (yytext_ptr) - YY_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) ((yy_c_buf_p) - (yytext_ptr)) - 1;
-
-	for ( i = 0; i < number_to_move; ++i )
-		*(dest++) = *(source++);
-
-	if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
-		/* don't do the read, it's not guaranteed to return an EOF,
-		 * just force an EOF
-		 */
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
-
-	else
-		{
-			int num_to_read =
-			YY_CURRENT_BUFFER_LVALUE->yy_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 */
-			YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
-
-			int yy_c_buf_p_offset =
-				(int) ((yy_c_buf_p) - b->yy_ch_buf);
-
-			if ( b->yy_is_our_buffer )
-				{
-				int new_size = b->yy_buf_size * 2;
-
-				if ( new_size <= 0 )
-					b->yy_buf_size += b->yy_buf_size / 8;
-				else
-					b->yy_buf_size *= 2;
-
-				b->yy_ch_buf = (char *)
-					/* Include room in for 2 EOB chars. */
-					fitshdrrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2  );
-				}
-			else
-				/* Can't grow it, we don't own it. */
-				b->yy_ch_buf = 0;
-
-			if ( ! b->yy_ch_buf )
-				YY_FATAL_ERROR(
-				"fatal error - scanner input buffer overflow" );
-
-			(yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset];
-
-			num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
-						number_to_move - 1;
-
-			}
-
-		if ( num_to_read > YY_READ_BUF_SIZE )
-			num_to_read = YY_READ_BUF_SIZE;
-
-		/* Read in more data. */
-		YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
-			(yy_n_chars), (size_t) num_to_read );
-
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
-		}
-
-	if ( (yy_n_chars) == 0 )
-		{
-		if ( number_to_move == YY_MORE_ADJ )
-			{
-			ret_val = EOB_ACT_END_OF_FILE;
-			fitshdrrestart(fitshdrin  );
-			}
-
-		else
-			{
-			ret_val = EOB_ACT_LAST_MATCH;
-			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
-				YY_BUFFER_EOF_PENDING;
-			}
-		}
-
-	else
-		ret_val = EOB_ACT_CONTINUE_SCAN;
-
-	if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
-		/* Extend the array by 50%, plus the number we really need. */
-		yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1);
-		YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) fitshdrrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size  );
-		if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
-			YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
-	}
-
-	(yy_n_chars) += number_to_move;
-	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
-	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
-
-	(yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
-
-	return ret_val;
-}
-
-/* yy_get_previous_state - get the state just before the EOB char was reached */
-
-    static yy_state_type yy_get_previous_state (void)
-{
-	register yy_state_type yy_current_state;
-	register char *yy_cp;
-    
-	yy_current_state = (yy_start);
-	yy_current_state += YY_AT_BOL();
-
-	for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
-		{
-		if ( *yy_cp )
-			{
-			yy_current_state = yy_nxt[yy_current_state][YY_SC_TO_UI(*yy_cp)];
-			}
-		else
-			yy_current_state = yy_NUL_trans[yy_current_state];
-		if ( yy_accept[yy_current_state] )
-			{
-			(yy_last_accepting_state) = yy_current_state;
-			(yy_last_accepting_cpos) = yy_cp;
-			}
-		}
-
-	return yy_current_state;
-}
-
-/* yy_try_NUL_trans - try to make a transition on the NUL character
- *
- * synopsis
- *	next_state = yy_try_NUL_trans( current_state );
- */
-    static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state )
-{
-	register int yy_is_jam;
-    	register char *yy_cp = (yy_c_buf_p);
-
-	yy_current_state = yy_NUL_trans[yy_current_state];
-	yy_is_jam = (yy_current_state == 0);
-
-	if ( ! yy_is_jam )
-		{
-		if ( yy_accept[yy_current_state] )
-			{
-			(yy_last_accepting_state) = yy_current_state;
-			(yy_last_accepting_cpos) = yy_cp;
-			}
-		}
-
-	return yy_is_jam ? 0 : yy_current_state;
-}
-
-#ifndef YY_NO_INPUT
-#ifdef __cplusplus
-    static int yyinput (void)
-#else
-    static int input  (void)
-#endif
-
-{
-	int c;
-    
-	*(yy_c_buf_p) = (yy_hold_char);
-
-	if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
-		{
-		/* yy_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 ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
-			/* This was really a NUL. */
-			*(yy_c_buf_p) = '\0';
-
-		else
-			{ /* need more input */
-			int offset = (yy_c_buf_p) - (yytext_ptr);
-			++(yy_c_buf_p);
-
-			switch ( yy_get_next_buffer(  ) )
-				{
-				case EOB_ACT_LAST_MATCH:
-					/* This happens because yy_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. */
-					fitshdrrestart(fitshdrin );
-
-					/*FALLTHROUGH*/
-
-				case EOB_ACT_END_OF_FILE:
-					{
-					if ( fitshdrwrap( ) )
-						return EOF;
-
-					if ( ! (yy_did_buffer_switch_on_eof) )
-						YY_NEW_FILE;
-#ifdef __cplusplus
-					return yyinput();
-#else
-					return input();
-#endif
-					}
-
-				case EOB_ACT_CONTINUE_SCAN:
-					(yy_c_buf_p) = (yytext_ptr) + offset;
-					break;
-				}
-			}
-		}
-
-	c = *(unsigned char *) (yy_c_buf_p);	/* cast for 8-bit char's */
-	*(yy_c_buf_p) = '\0';	/* preserve fitshdrtext */
-	(yy_hold_char) = *++(yy_c_buf_p);
-
-	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = (c == '\n');
-
-	return c;
-}
-#endif	/* ifndef YY_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 fitshdrrestart  (FILE * input_file )
-{
-    
-	if ( ! YY_CURRENT_BUFFER ){
-        fitshdrensure_buffer_stack ();
-		YY_CURRENT_BUFFER_LVALUE =
-            fitshdr_create_buffer(fitshdrin,YY_BUF_SIZE );
-	}
-
-	fitshdr_init_buffer(YY_CURRENT_BUFFER,input_file );
-	fitshdr_load_buffer_state( );
-}
-
-/** Switch to a different input buffer.
- * @param new_buffer The new input buffer.
- * 
- */
-    void fitshdr_switch_to_buffer  (YY_BUFFER_STATE  new_buffer )
-{
-    
-	/* TODO. We should be able to replace this entire function body
-	 * with
-	 *		fitshdrpop_buffer_state();
-	 *		fitshdrpush_buffer_state(new_buffer);
-     */
-	fitshdrensure_buffer_stack ();
-	if ( YY_CURRENT_BUFFER == new_buffer )
-		return;
-
-	if ( YY_CURRENT_BUFFER )
-		{
-		/* Flush out information for old buffer. */
-		*(yy_c_buf_p) = (yy_hold_char);
-		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
-		}
-
-	YY_CURRENT_BUFFER_LVALUE = new_buffer;
-	fitshdr_load_buffer_state( );
-
-	/* We don't actually know whether we did this switch during
-	 * EOF (fitshdrwrap()) processing, but the only time this flag
-	 * is looked at is after fitshdrwrap() is called, so it's safe
-	 * to go ahead and always set it.
-	 */
-	(yy_did_buffer_switch_on_eof) = 1;
-}
-
-static void fitshdr_load_buffer_state  (void)
-{
-    	(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
-	(yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
-	fitshdrin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
-	(yy_hold_char) = *(yy_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 YY_BUF_SIZE.
- * 
- * @return the allocated buffer state.
- */
-    YY_BUFFER_STATE fitshdr_create_buffer  (FILE * file, int  size )
-{
-	YY_BUFFER_STATE b;
-    
-	b = (YY_BUFFER_STATE) fitshdralloc(sizeof( struct yy_buffer_state )  );
-	if ( ! b )
-		YY_FATAL_ERROR( "out of dynamic memory in fitshdr_create_buffer()" );
-
-	b->yy_buf_size = size;
-
-	/* yy_ch_buf has to be 2 characters longer than the size given because
-	 * we need to put in 2 end-of-buffer characters.
-	 */
-	b->yy_ch_buf = (char *) fitshdralloc(b->yy_buf_size + 2  );
-	if ( ! b->yy_ch_buf )
-		YY_FATAL_ERROR( "out of dynamic memory in fitshdr_create_buffer()" );
-
-	b->yy_is_our_buffer = 1;
-
-	fitshdr_init_buffer(b,file );
-
-	return b;
-}
-
-/** Destroy the buffer.
- * @param b a buffer created with fitshdr_create_buffer()
- * 
- */
-    void fitshdr_delete_buffer (YY_BUFFER_STATE  b )
-{
-    
-	if ( ! b )
-		return;
-
-	if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
-		YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
-
-	if ( b->yy_is_our_buffer )
-		fitshdrfree((void *) b->yy_ch_buf  );
-
-	fitshdrfree((void *) b  );
-}
-
-/* Initializes or reinitializes a buffer.
- * This function is sometimes called more than once on the same buffer,
- * such as during a fitshdrrestart() or at EOF.
- */
-    static void fitshdr_init_buffer  (YY_BUFFER_STATE  b, FILE * file )
-
-{
-	int oerrno = errno;
-    
-	fitshdr_flush_buffer(b );
-
-	b->yy_input_file = file;
-	b->yy_fill_buffer = 1;
-
-    /* If b is the current buffer, then fitshdr_init_buffer was _probably_
-     * called from fitshdrrestart() or through yy_get_next_buffer.
-     * In that case, we don't want to reset the lineno or column.
-     */
-    if (b != YY_CURRENT_BUFFER){
-        b->yy_bs_lineno = 1;
-        b->yy_bs_column = 0;
-    }
-
-        b->yy_is_interactive = 0;
-    
-	errno = oerrno;
-}
-
-/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
- * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
- * 
- */
-    void fitshdr_flush_buffer (YY_BUFFER_STATE  b )
-{
-    	if ( ! b )
-		return;
-
-	b->yy_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->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
-	b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
-
-	b->yy_buf_pos = &b->yy_ch_buf[0];
-
-	b->yy_at_bol = 1;
-	b->yy_buffer_status = YY_BUFFER_NEW;
-
-	if ( b == YY_CURRENT_BUFFER )
-		fitshdr_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 fitshdrpush_buffer_state (YY_BUFFER_STATE new_buffer )
-{
-    	if (new_buffer == NULL)
-		return;
-
-	fitshdrensure_buffer_stack();
-
-	/* This block is copied from fitshdr_switch_to_buffer. */
-	if ( YY_CURRENT_BUFFER )
-		{
-		/* Flush out information for old buffer. */
-		*(yy_c_buf_p) = (yy_hold_char);
-		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
-		}
-
-	/* Only push if top exists. Otherwise, replace top. */
-	if (YY_CURRENT_BUFFER)
-		(yy_buffer_stack_top)++;
-	YY_CURRENT_BUFFER_LVALUE = new_buffer;
-
-	/* copied from fitshdr_switch_to_buffer. */
-	fitshdr_load_buffer_state( );
-	(yy_did_buffer_switch_on_eof) = 1;
-}
-
-/** Removes and deletes the top of the stack, if present.
- *  The next element becomes the new top.
- *  
- */
-void fitshdrpop_buffer_state (void)
-{
-    	if (!YY_CURRENT_BUFFER)
-		return;
-
-	fitshdr_delete_buffer(YY_CURRENT_BUFFER );
-	YY_CURRENT_BUFFER_LVALUE = NULL;
-	if ((yy_buffer_stack_top) > 0)
-		--(yy_buffer_stack_top);
-
-	if (YY_CURRENT_BUFFER) {
-		fitshdr_load_buffer_state( );
-		(yy_did_buffer_switch_on_eof) = 1;
-	}
-}
-
-/* Allocates the stack if it does not exist.
- *  Guarantees space for at least one push.
- */
-static void fitshdrensure_buffer_stack (void)
-{
-	int num_to_alloc;
-    
-	if (!(yy_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;
-		(yy_buffer_stack) = (struct yy_buffer_state**)fitshdralloc
-								(num_to_alloc * sizeof(struct yy_buffer_state*)
-								);
-		if ( ! (yy_buffer_stack) )
-			YY_FATAL_ERROR( "out of dynamic memory in fitshdrensure_buffer_stack()" );
-								  
-		memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
-				
-		(yy_buffer_stack_max) = num_to_alloc;
-		(yy_buffer_stack_top) = 0;
-		return;
-	}
-
-	if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
-
-		/* Increase the buffer to prepare for a possible push. */
-		int grow_size = 8 /* arbitrary grow size */;
-
-		num_to_alloc = (yy_buffer_stack_max) + grow_size;
-		(yy_buffer_stack) = (struct yy_buffer_state**)fitshdrrealloc
-								((yy_buffer_stack),
-								num_to_alloc * sizeof(struct yy_buffer_state*)
-								);
-		if ( ! (yy_buffer_stack) )
-			YY_FATAL_ERROR( "out of dynamic memory in fitshdrensure_buffer_stack()" );
-
-		/* zero only the new slots.*/
-		memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
-		(yy_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. 
- */
-YY_BUFFER_STATE fitshdr_scan_buffer  (char * base, yy_size_t  size )
-{
-	YY_BUFFER_STATE b;
-    
-	if ( size < 2 ||
-	     base[size-2] != YY_END_OF_BUFFER_CHAR ||
-	     base[size-1] != YY_END_OF_BUFFER_CHAR )
-		/* They forgot to leave room for the EOB's. */
-		return 0;
-
-	b = (YY_BUFFER_STATE) fitshdralloc(sizeof( struct yy_buffer_state )  );
-	if ( ! b )
-		YY_FATAL_ERROR( "out of dynamic memory in fitshdr_scan_buffer()" );
-
-	b->yy_buf_size = size - 2;	/* "- 2" to take care of EOB's */
-	b->yy_buf_pos = b->yy_ch_buf = base;
-	b->yy_is_our_buffer = 0;
-	b->yy_input_file = 0;
-	b->yy_n_chars = b->yy_buf_size;
-	b->yy_is_interactive = 0;
-	b->yy_at_bol = 1;
-	b->yy_fill_buffer = 0;
-	b->yy_buffer_status = YY_BUFFER_NEW;
-
-	fitshdr_switch_to_buffer(b  );
-
-	return b;
-}
-
-/** Setup the input buffer state to scan a string. The next call to fitshdrlex() will
- * scan from a @e copy of @a str.
- * @param yystr 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
- *       fitshdr_scan_bytes() instead.
- */
-YY_BUFFER_STATE fitshdr_scan_string (yyconst char * yystr )
-{
-    
-	return fitshdr_scan_bytes(yystr,strlen(yystr) );
-}
-
-/** Setup the input buffer state to scan the given bytes. The next call to fitshdrlex() will
- * scan from a @e copy of @a bytes.
- * @param yybytes the byte buffer to scan
- * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
- * 
- * @return the newly allocated buffer state object.
- */
-YY_BUFFER_STATE fitshdr_scan_bytes  (yyconst char * yybytes, int  _yybytes_len )
-{
-	YY_BUFFER_STATE b;
-	char *buf;
-	yy_size_t n;
-	int i;
-    
-	/* Get memory for full buffer, including space for trailing EOB's. */
-	n = _yybytes_len + 2;
-	buf = (char *) fitshdralloc(n  );
-	if ( ! buf )
-		YY_FATAL_ERROR( "out of dynamic memory in fitshdr_scan_bytes()" );
-
-	for ( i = 0; i < _yybytes_len; ++i )
-		buf[i] = yybytes[i];
-
-	buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
-
-	b = fitshdr_scan_buffer(buf,n );
-	if ( ! b )
-		YY_FATAL_ERROR( "bad buffer in fitshdr_scan_bytes()" );
-
-	/* It's okay to grow etc. this buffer, and we should throw it
-	 * away when we're done.
-	 */
-	b->yy_is_our_buffer = 1;
-
-	return b;
-}
-
-#ifndef YY_EXIT_FAILURE
-#define YY_EXIT_FAILURE 2
-#endif
-
-static void yy_fatal_error (yyconst char* msg )
-{
-    	(void) fprintf( stderr, "%s\n", msg );
-	exit( YY_EXIT_FAILURE );
-}
-
-/* Redefine yyless() so it works in section 3 code. */
-
-#undef yyless
-#define yyless(n) \
-	do \
-		{ \
-		/* Undo effects of setting up fitshdrtext. */ \
-        int yyless_macro_arg = (n); \
-        YY_LESS_LINENO(yyless_macro_arg);\
-		fitshdrtext[fitshdrleng] = (yy_hold_char); \
-		(yy_c_buf_p) = fitshdrtext + yyless_macro_arg; \
-		(yy_hold_char) = *(yy_c_buf_p); \
-		*(yy_c_buf_p) = '\0'; \
-		fitshdrleng = yyless_macro_arg; \
-		} \
-	while ( 0 )
-
-/* Accessor  methods (get/set functions) to struct members. */
-
-/** Get the current line number.
- * 
- */
-int fitshdrget_lineno  (void)
-{
-        
-    return fitshdrlineno;
-}
-
-/** Get the input stream.
- * 
- */
-FILE *fitshdrget_in  (void)
-{
-        return fitshdrin;
-}
-
-/** Get the output stream.
- * 
- */
-FILE *fitshdrget_out  (void)
-{
-        return fitshdrout;
-}
-
-/** Get the length of the current token.
- * 
- */
-int fitshdrget_leng  (void)
-{
-        return fitshdrleng;
-}
-
-/** Get the current token.
- * 
- */
-
-char *fitshdrget_text  (void)
-{
-        return fitshdrtext;
-}
-
-/** Set the current line number.
- * @param line_number
- * 
- */
-void fitshdrset_lineno (int  line_number )
-{
-    
-    fitshdrlineno = line_number;
-}
-
-/** Set the input stream. This does not discard the current
- * input buffer.
- * @param in_str A readable stream.
- * 
- * @see fitshdr_switch_to_buffer
- */
-void fitshdrset_in (FILE *  in_str )
-{
-        fitshdrin = in_str ;
-}
-
-void fitshdrset_out (FILE *  out_str )
-{
-        fitshdrout = out_str ;
-}
-
-int fitshdrget_debug  (void)
-{
-        return fitshdr_flex_debug;
-}
-
-void fitshdrset_debug (int  bdebug )
-{
-        fitshdr_flex_debug = bdebug ;
-}
-
-static int yy_init_globals (void)
-{
-        /* Initialization is the same as for the non-reentrant scanner.
-     * This function is called from fitshdrlex_destroy(), so don't allocate here.
-     */
-
-    (yy_buffer_stack) = 0;
-    (yy_buffer_stack_top) = 0;
-    (yy_buffer_stack_max) = 0;
-    (yy_c_buf_p) = (char *) 0;
-    (yy_init) = 0;
-    (yy_start) = 0;
-
-/* Defined in main.c */
-#ifdef YY_STDINIT
-    fitshdrin = stdin;
-    fitshdrout = stdout;
-#else
-    fitshdrin = (FILE *) 0;
-    fitshdrout = (FILE *) 0;
-#endif
-
-    /* For future reference: Set errno on error, since we are called by
-     * fitshdrlex_init()
-     */
-    return 0;
-}
-
-/* fitshdrlex_destroy is for both reentrant and non-reentrant scanners. */
-int fitshdrlex_destroy  (void)
-{
-    
-    /* Pop the buffer stack, destroying each element. */
-	while(YY_CURRENT_BUFFER){
-		fitshdr_delete_buffer(YY_CURRENT_BUFFER  );
-		YY_CURRENT_BUFFER_LVALUE = NULL;
-		fitshdrpop_buffer_state();
-	}
-
-	/* Destroy the stack itself. */
-	fitshdrfree((yy_buffer_stack) );
-	(yy_buffer_stack) = NULL;
-
-    /* Reset the globals. This is important in a non-reentrant scanner so the next time
-     * fitshdrlex() is called, initialization will occur. */
-    yy_init_globals( );
-
-    return 0;
-}
-
-/*
- * Internal utility routines.
- */
-
-#ifndef yytext_ptr
-static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
-{
-	register int i;
-	for ( i = 0; i < n; ++i )
-		s1[i] = s2[i];
-}
-#endif
-
-#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * s )
-{
-	register int n;
-	for ( n = 0; s[n]; ++n )
-		;
-
-	return n;
-}
-#endif
-
-void *fitshdralloc (yy_size_t  size )
-{
-	return (void *) malloc( size );
-}
-
-void *fitshdrrealloc  (void * ptr, yy_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 fitshdrfree (void * ptr )
-{
-	free( (char *) ptr );	/* see fitshdrrealloc() for (char *) cast */
-}
-
-#define YYTABLES_NAME "yytables"
-
-#line 535 "fitshdr.l"
-
-
-
-/*--------------------------------------------------------------------------*/
-
-void nullfill(char cptr[], int len)
-
-{
-  int j, k;
-
-  /* Null-fill the string. */
-  for (j = 0; j < len; j++) {
-    if (cptr[j] == '\0') {
-      for (k = j+1; k < len; k++) {
-        cptr[k] = '\0';
-      }
-      break;
-    }
-  }
-
-  for (k = j-1; k >= 0; k--) {
-    if (cptr[k] != ' ') break;
-    cptr[k] = '\0';
-  }
-
-  return;
-}
-
diff --git a/astropy/wcs/src/wcslib/C/flexed/wcsbth.c b/astropy/wcs/src/wcslib/C/flexed/wcsbth.c
deleted file mode 100644
index fbb0892..0000000
--- a/astropy/wcs/src/wcslib/C/flexed/wcsbth.c
+++ /dev/null
@@ -1,21068 +0,0 @@
-#line 2 "wcsbth.c"
-
-#line 4 "wcsbth.c"
-
-#define  YY_INT_ALIGNED short int
-
-/* A lexical scanner generated by flex */
-
-#define yy_create_buffer wcsbth_create_buffer
-#define yy_delete_buffer wcsbth_delete_buffer
-#define yy_flex_debug wcsbth_flex_debug
-#define yy_init_buffer wcsbth_init_buffer
-#define yy_flush_buffer wcsbth_flush_buffer
-#define yy_load_buffer_state wcsbth_load_buffer_state
-#define yy_switch_to_buffer wcsbth_switch_to_buffer
-#define yyin wcsbthin
-#define yyleng wcsbthleng
-#define yylex wcsbthlex
-#define yylineno wcsbthlineno
-#define yyout wcsbthout
-#define yyrestart wcsbthrestart
-#define yytext wcsbthtext
-#define yywrap wcsbthwrap
-#define yyalloc wcsbthalloc
-#define yyrealloc wcsbthrealloc
-#define yyfree wcsbthfree
-
-#define FLEX_SCANNER
-#define YY_FLEX_MAJOR_VERSION 2
-#define YY_FLEX_MINOR_VERSION 5
-#define YY_FLEX_SUBMINOR_VERSION 35
-#if YY_FLEX_SUBMINOR_VERSION > 0
-#define FLEX_BETA
-#endif
-
-/* First, we deal with  platform-specific or compiler-specific issues. */
-
-/* begin standard C headers. */
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <stdlib.h>
-
-/* end standard C headers. */
-
-/* flex integer type definitions */
-
-#ifndef FLEXINT_H
-#define FLEXINT_H
-
-/* C99 systems have <inttypes.h>. 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 <inttypes.h>
-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;
-
-/* 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 /* ! C99 */
-
-#endif /* ! FLEXINT_H */
-
-#ifdef __cplusplus
-
-/* The "const" storage-class-modifier is valid. */
-#define YY_USE_CONST
-
-#else	/* ! __cplusplus */
-
-/* C99 requires __STDC__ to be defined as 1. */
-#if defined (__STDC__)
-
-#define YY_USE_CONST
-
-#endif	/* defined (__STDC__) */
-#endif	/* ! __cplusplus */
-
-#ifdef YY_USE_CONST
-#define yyconst const
-#else
-#define yyconst
-#endif
-
-/* Returned upon end-of-file. */
-#define YY_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 YY_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 (yy_start) = 1 + 2 *
-
-/* Translate the current start state into a value that can be later handed
- * to BEGIN to return to the state.  The YYSTATE alias is for lex
- * compatibility.
- */
-#define YY_START (((yy_start) - 1) / 2)
-#define YYSTATE YY_START
-
-/* Action number for EOF rule of a given start state. */
-#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
-
-/* Special action meaning "start processing a new file". */
-#define YY_NEW_FILE wcsbthrestart(wcsbthin  )
-
-#define YY_END_OF_BUFFER_CHAR 0
-
-/* Size of default input buffer. */
-#ifndef YY_BUF_SIZE
-#ifdef __ia64__
-/* On IA-64, the buffer size is 16k, not 8k.
- * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
- * Ditto for the __ia64__ case accordingly.
- */
-#define YY_BUF_SIZE 32768
-#else
-#define YY_BUF_SIZE 16384
-#endif /* __ia64__ */
-#endif
-
-/* The state buf must be large enough to hold one state per character in the main buffer.
- */
-#define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
-
-#ifndef YY_TYPEDEF_YY_BUFFER_STATE
-#define YY_TYPEDEF_YY_BUFFER_STATE
-typedef struct yy_buffer_state *YY_BUFFER_STATE;
-#endif
-
-extern int wcsbthleng;
-
-extern FILE *wcsbthin, *wcsbthout;
-
-#define EOB_ACT_CONTINUE_SCAN 0
-#define EOB_ACT_END_OF_FILE 1
-#define EOB_ACT_LAST_MATCH 2
-
-#define YY_LESS_LINENO(n)
-    
-/* Return all but the first "n" matched characters back to the input stream. */
-#define yyless(n) \
-	do \
-		{ \
-		/* Undo effects of setting up wcsbthtext. */ \
-        int yyless_macro_arg = (n); \
-        YY_LESS_LINENO(yyless_macro_arg);\
-		*yy_cp = (yy_hold_char); \
-		YY_RESTORE_YY_MORE_OFFSET \
-		(yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
-		YY_DO_BEFORE_ACTION; /* set up wcsbthtext again */ \
-		} \
-	while ( 0 )
-
-#define unput(c) yyunput( c, (yytext_ptr)  )
-
-#ifndef YY_TYPEDEF_YY_SIZE_T
-#define YY_TYPEDEF_YY_SIZE_T
-typedef size_t yy_size_t;
-#endif
-
-#ifndef YY_STRUCT_YY_BUFFER_STATE
-#define YY_STRUCT_YY_BUFFER_STATE
-struct yy_buffer_state
-	{
-	FILE *yy_input_file;
-
-	char *yy_ch_buf;		/* input buffer */
-	char *yy_buf_pos;		/* current position in input buffer */
-
-	/* Size of input buffer in bytes, not including room for EOB
-	 * characters.
-	 */
-	yy_size_t yy_buf_size;
-
-	/* Number of characters read into yy_ch_buf, not including EOB
-	 * characters.
-	 */
-	int yy_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 yy_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 yy_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 yy_at_bol;
-
-    int yy_bs_lineno; /**< The line count. */
-    int yy_bs_column; /**< The column count. */
-    
-	/* Whether to try to fill the input buffer when we reach the
-	 * end of it.
-	 */
-	int yy_fill_buffer;
-
-	int yy_buffer_status;
-
-#define YY_BUFFER_NEW 0
-#define YY_BUFFER_NORMAL 1
-	/* When an EOF's been seen but there's still some text to process
-	 * then we mark the buffer as YY_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 wcsbthrestart()), so that the user can continue scanning by
-	 * just pointing wcsbthin at a new input file.
-	 */
-#define YY_BUFFER_EOF_PENDING 2
-
-	};
-#endif /* !YY_STRUCT_YY_BUFFER_STATE */
-
-/* Stack of input buffers. */
-static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
-static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
-static YY_BUFFER_STATE * yy_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 YY_CURRENT_BUFFER ( (yy_buffer_stack) \
-                          ? (yy_buffer_stack)[(yy_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 YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
-
-/* yy_hold_char holds the character lost when wcsbthtext is formed. */
-static char yy_hold_char;
-static int yy_n_chars;		/* number of characters read into yy_ch_buf */
-int wcsbthleng;
-
-/* Points to current character in buffer. */
-static char *yy_c_buf_p = (char *) 0;
-static int yy_init = 0;		/* whether we need to initialize */
-static int yy_start = 0;	/* start state number */
-
-/* Flag which is used to allow wcsbthwrap()'s to do buffer switches
- * instead of setting up a fresh wcsbthin.  A bit of a hack ...
- */
-static int yy_did_buffer_switch_on_eof;
-
-void wcsbthrestart (FILE *input_file  );
-void wcsbth_switch_to_buffer (YY_BUFFER_STATE new_buffer  );
-YY_BUFFER_STATE wcsbth_create_buffer (FILE *file,int size  );
-void wcsbth_delete_buffer (YY_BUFFER_STATE b  );
-void wcsbth_flush_buffer (YY_BUFFER_STATE b  );
-void wcsbthpush_buffer_state (YY_BUFFER_STATE new_buffer  );
-void wcsbthpop_buffer_state (void );
-
-static void wcsbthensure_buffer_stack (void );
-static void wcsbth_load_buffer_state (void );
-static void wcsbth_init_buffer (YY_BUFFER_STATE b,FILE *file  );
-
-#define YY_FLUSH_BUFFER wcsbth_flush_buffer(YY_CURRENT_BUFFER )
-
-YY_BUFFER_STATE wcsbth_scan_buffer (char *base,yy_size_t size  );
-YY_BUFFER_STATE wcsbth_scan_string (yyconst char *yy_str  );
-YY_BUFFER_STATE wcsbth_scan_bytes (yyconst char *bytes,int len  );
-
-void *wcsbthalloc (yy_size_t  );
-void *wcsbthrealloc (void *,yy_size_t  );
-void wcsbthfree (void *  );
-
-#define yy_new_buffer wcsbth_create_buffer
-
-#define yy_set_interactive(is_interactive) \
-	{ \
-	if ( ! YY_CURRENT_BUFFER ){ \
-        wcsbthensure_buffer_stack (); \
-		YY_CURRENT_BUFFER_LVALUE =    \
-            wcsbth_create_buffer(wcsbthin,YY_BUF_SIZE ); \
-	} \
-	YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
-	}
-
-#define yy_set_bol(at_bol) \
-	{ \
-	if ( ! YY_CURRENT_BUFFER ){\
-        wcsbthensure_buffer_stack (); \
-		YY_CURRENT_BUFFER_LVALUE =    \
-            wcsbth_create_buffer(wcsbthin,YY_BUF_SIZE ); \
-	} \
-	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
-	}
-
-#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
-
-/* Begin user sect3 */
-
-#define wcsbthwrap(n) 1
-#define YY_SKIP_YYWRAP
-
-typedef char YY_CHAR;
-
-FILE *wcsbthin = (FILE *) 0, *wcsbthout = (FILE *) 0;
-
-typedef int yy_state_type;
-
-extern int wcsbthlineno;
-
-int wcsbthlineno = 1;
-
-extern char *wcsbthtext;
-#define yytext_ptr wcsbthtext
-static yyconst flex_int16_t yy_nxt[][128] =
-    {
-    {
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0
-    },
-
-    {
-       67,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68
-    },
-
-    {
-       67,   69,   69,   69,   69,   69,   69,   69,   69,   69,
-       68,   69,   69,   69,   69,   69,   69,   69,   69,   69,
-       69,   69,   69,   69,   69,   69,   69,   69,   69,   69,
-       69,   69,   69,   69,   69,   69,   69,   69,   69,   69,
-
-       69,   69,   69,   69,   69,   69,   69,   69,   69,   70,
-       70,   70,   70,   70,   70,   70,   70,   70,   69,   69,
-       69,   69,   69,   69,   69,   69,   69,   71,   72,   73,
-       69,   69,   69,   69,   69,   69,   74,   75,   69,   76,
-       77,   69,   78,   79,   80,   69,   81,   82,   69,   69,
-       83,   69,   69,   69,   69,   69,   69,   69,   69,   69,
-       69,   69,   69,   69,   69,   69,   69,   69,   69,   69,
-       69,   69,   69,   69,   69,   69,   69,   69,   69,   69,
-       69,   69,   69,   69,   69,   69,   69,   69
-    },
-
-    {
-       67,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   84,
-       84,   84,   84,   84,   84,   84,   84,   84,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68
-    },
-
-    {
-       67,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   84,
-       84,   84,   84,   84,   84,   84,   84,   84,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68
-    },
-
-    {
-       67,   85,   85,   85,   85,   85,   85,   85,   85,   85,
-       68,   85,   85,   85,   85,   85,   85,   85,   85,   85,
-       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
-       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
-       85,   85,   85,   85,   85,   85,   85,   85,   85,   86,
-
-       86,   86,   86,   86,   86,   86,   86,   86,   85,   85,
-       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
-       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
-       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
-       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
-       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
-       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
-       85,   85,   85,   85,   85,   85,   85,   85
-    },
-
-    {
-       67,   85,   85,   85,   85,   85,   85,   85,   85,   85,
-       68,   85,   85,   85,   85,   85,   85,   85,   85,   85,
-
-       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
-       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
-       85,   85,   85,   85,   85,   85,   85,   85,   85,   86,
-       86,   86,   86,   86,   86,   86,   86,   86,   85,   85,
-       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
-       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
-       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
-       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
-       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
-       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
-
-       85,   85,   85,   85,   85,   85,   85,   85
-    },
-
-    {
-       67,   87,   87,   87,   87,   87,   87,   87,   87,   87,
-       68,   87,   87,   87,   87,   87,   87,   87,   87,   87,
-       87,   87,   87,   87,   87,   87,   87,   87,   87,   87,
-       87,   87,   87,   87,   87,   87,   87,   87,   87,   87,
-       87,   87,   87,   87,   87,   87,   87,   87,   87,   88,
-       88,   88,   88,   88,   88,   88,   88,   88,   87,   87,
-       87,   87,   87,   87,   87,   87,   87,   87,   87,   87,
-       87,   87,   87,   87,   87,   87,   87,   87,   87,   87,
-       87,   87,   87,   87,   87,   87,   87,   87,   87,   87,
-
-       87,   87,   87,   87,   87,   87,   87,   87,   87,   87,
-       87,   87,   87,   87,   87,   87,   87,   87,   87,   87,
-       87,   87,   87,   87,   87,   87,   87,   87,   87,   87,
-       87,   87,   87,   87,   87,   87,   87,   87
-    },
-
-    {
-       67,   87,   87,   87,   87,   87,   87,   87,   87,   87,
-       68,   87,   87,   87,   87,   87,   87,   87,   87,   87,
-       87,   87,   87,   87,   87,   87,   87,   87,   87,   87,
-       87,   87,   87,   87,   87,   87,   87,   87,   87,   87,
-       87,   87,   87,   87,   87,   87,   87,   87,   87,   88,
-       88,   88,   88,   88,   88,   88,   88,   88,   87,   87,
-
-       87,   87,   87,   87,   87,   87,   87,   87,   87,   87,
-       87,   87,   87,   87,   87,   87,   87,   87,   87,   87,
-       87,   87,   87,   87,   87,   87,   87,   87,   87,   87,
-       87,   87,   87,   87,   87,   87,   87,   87,   87,   87,
-       87,   87,   87,   87,   87,   87,   87,   87,   87,   87,
-       87,   87,   87,   87,   87,   87,   87,   87,   87,   87,
-       87,   87,   87,   87,   87,   87,   87,   87
-    },
-
-    {
-       67,   89,   89,   89,   89,   89,   89,   89,   89,   89,
-       68,   89,   89,   89,   89,   89,   89,   89,   89,   89,
-       89,   89,   89,   89,   89,   89,   89,   89,   89,   89,
-
-       89,   89,   89,   89,   89,   89,   89,   89,   89,   89,
-       89,   89,   89,   89,   89,   89,   89,   89,   89,   90,
-       90,   90,   90,   90,   90,   90,   90,   90,   89,   89,
-       89,   89,   89,   89,   89,   89,   89,   89,   89,   89,
-       89,   89,   89,   89,   89,   89,   89,   89,   89,   89,
-       89,   89,   89,   89,   89,   89,   89,   89,   89,   89,
-       89,   89,   89,   89,   89,   89,   89,   89,   89,   89,
-       89,   89,   89,   89,   89,   89,   89,   89,   89,   89,
-       89,   89,   89,   89,   89,   89,   89,   89,   89,   89,
-       89,   89,   89,   89,   89,   89,   89,   89
-
-    },
-
-    {
-       67,   89,   89,   89,   89,   89,   89,   89,   89,   89,
-       68,   89,   89,   89,   89,   89,   89,   89,   89,   89,
-       89,   89,   89,   89,   89,   89,   89,   89,   89,   89,
-       89,   89,   89,   89,   89,   89,   89,   89,   89,   89,
-       89,   89,   89,   89,   89,   89,   89,   89,   89,   90,
-       90,   90,   90,   90,   90,   90,   90,   90,   89,   89,
-       89,   89,   89,   89,   89,   89,   89,   89,   89,   89,
-       89,   89,   89,   89,   89,   89,   89,   89,   89,   89,
-       89,   89,   89,   89,   89,   89,   89,   89,   89,   89,
-       89,   89,   89,   89,   89,   89,   89,   89,   89,   89,
-
-       89,   89,   89,   89,   89,   89,   89,   89,   89,   89,
-       89,   89,   89,   89,   89,   89,   89,   89,   89,   89,
-       89,   89,   89,   89,   89,   89,   89,   89
-    },
-
-    {
-       67,   91,   91,   91,   91,   91,   91,   91,   91,   91,
-       68,   91,   91,   91,   91,   91,   91,   91,   91,   91,
-       91,   91,   91,   91,   91,   91,   91,   91,   91,   91,
-       91,   91,   91,   91,   91,   91,   91,   91,   91,   91,
-       91,   91,   91,   91,   91,   91,   91,   91,   91,   92,
-       92,   92,   92,   92,   92,   92,   92,   92,   91,   91,
-       91,   91,   91,   91,   91,   91,   91,   91,   91,   91,
-
-       91,   91,   91,   91,   91,   91,   91,   91,   91,   91,
-       91,   91,   91,   91,   91,   91,   91,   91,   91,   91,
-       91,   91,   91,   91,   91,   91,   91,   91,   91,   91,
-       91,   91,   91,   91,   91,   91,   91,   91,   91,   91,
-       91,   91,   91,   91,   91,   91,   91,   91,   91,   91,
-       91,   91,   91,   91,   91,   91,   91,   91
-    },
-
-    {
-       67,   91,   91,   91,   91,   91,   91,   91,   91,   91,
-       68,   91,   91,   91,   91,   91,   91,   91,   91,   91,
-       91,   91,   91,   91,   91,   91,   91,   91,   91,   91,
-       91,   91,   91,   91,   91,   91,   91,   91,   91,   91,
-
-       91,   91,   91,   91,   91,   91,   91,   91,   91,   92,
-       92,   92,   92,   92,   92,   92,   92,   92,   91,   91,
-       91,   91,   91,   91,   91,   91,   91,   91,   91,   91,
-       91,   91,   91,   91,   91,   91,   91,   91,   91,   91,
-       91,   91,   91,   91,   91,   91,   91,   91,   91,   91,
-       91,   91,   91,   91,   91,   91,   91,   91,   91,   91,
-       91,   91,   91,   91,   91,   91,   91,   91,   91,   91,
-       91,   91,   91,   91,   91,   91,   91,   91,   91,   91,
-       91,   91,   91,   91,   91,   91,   91,   91
-    },
-
-    {
-       67,   93,   93,   93,   93,   93,   93,   93,   93,   93,
-
-       68,   93,   93,   93,   93,   93,   93,   93,   93,   93,
-       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
-       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
-       93,   93,   93,   93,   93,   93,   93,   93,   94,   95,
-       95,   95,   95,   95,   95,   95,   95,   95,   93,   93,
-       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
-       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
-       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
-       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
-       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
-
-       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
-       93,   93,   93,   93,   93,   93,   93,   93
-    },
-
-    {
-       67,   93,   93,   93,   93,   93,   93,   93,   93,   93,
-       68,   93,   93,   93,   93,   93,   93,   93,   93,   93,
-       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
-       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
-       93,   93,   93,   93,   93,   93,   93,   93,   94,   95,
-       95,   95,   95,   95,   95,   95,   95,   95,   93,   93,
-       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
-       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
-
-       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
-       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
-       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
-       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
-       93,   93,   93,   93,   93,   93,   93,   93
-    },
-
-    {
-       67,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   96,
-
-       96,   96,   96,   96,   96,   96,   96,   96,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68
-    },
-
-    {
-       67,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   96,
-       96,   96,   96,   96,   96,   96,   96,   96,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-
-       68,   68,   68,   68,   68,   68,   68,   68
-    },
-
-    {
-       67,   97,   97,   97,   97,   97,   97,   97,   97,   97,
-       68,   97,   97,   97,   97,   97,   97,   97,   97,   97,
-       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
-       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
-       97,   97,   97,   97,   97,   97,   97,   97,   97,   98,
-       98,   98,   98,   98,   98,   98,   98,   98,   97,   97,
-       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
-       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
-       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
-
-       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
-       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
-       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
-       97,   97,   97,   97,   97,   97,   97,   97
-    },
-
-    {
-       67,   97,   97,   97,   97,   97,   97,   97,   97,   97,
-       68,   97,   97,   97,   97,   97,   97,   97,   97,   97,
-       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
-       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
-       97,   97,   97,   97,   97,   97,   97,   97,   97,   98,
-       98,   98,   98,   98,   98,   98,   98,   98,   97,   97,
-
-       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
-       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
-       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
-       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
-       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
-       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
-       97,   97,   97,   97,   97,   97,   97,   97
-    },
-
-    {
-       67,   99,   99,   99,   99,   99,   99,   99,   99,   99,
-       68,   99,   99,   99,   99,   99,   99,   99,   99,   99,
-       99,   99,   99,   99,   99,   99,   99,   99,   99,   99,
-
-       99,   99,   99,   99,   99,   99,   99,   99,   99,   99,
-       99,   99,   99,   99,   99,   99,   99,   99,   99,  100,
-      100,  100,  100,  100,  100,  100,  100,  100,   99,   99,
-       99,   99,   99,   99,   99,   99,   99,   99,   99,   99,
-       99,   99,   99,   99,   99,   99,   99,   99,   99,   99,
-       99,   99,   99,   99,   99,   99,   99,   99,   99,   99,
-       99,   99,   99,   99,   99,   99,   99,   99,   99,   99,
-       99,   99,   99,   99,   99,   99,   99,   99,   99,   99,
-       99,   99,   99,   99,   99,   99,   99,   99,   99,   99,
-       99,   99,   99,   99,   99,   99,   99,   99
-
-    },
-
-    {
-       67,   99,   99,   99,   99,   99,   99,   99,   99,   99,
-       68,   99,   99,   99,   99,   99,   99,   99,   99,   99,
-       99,   99,   99,   99,   99,   99,   99,   99,   99,   99,
-       99,   99,   99,   99,   99,   99,   99,   99,   99,   99,
-       99,   99,   99,   99,   99,   99,   99,   99,   99,  100,
-      100,  100,  100,  100,  100,  100,  100,  100,   99,   99,
-       99,   99,   99,   99,   99,   99,   99,   99,   99,   99,
-       99,   99,   99,   99,   99,   99,   99,   99,   99,   99,
-       99,   99,   99,   99,   99,   99,   99,   99,   99,   99,
-       99,   99,   99,   99,   99,   99,   99,   99,   99,   99,
-
-       99,   99,   99,   99,   99,   99,   99,   99,   99,   99,
-       99,   99,   99,   99,   99,   99,   99,   99,   99,   99,
-       99,   99,   99,   99,   99,   99,   99,   99
-    },
-
-    {
-       67,  101,  101,  101,  101,  101,  101,  101,  101,  101,
-       68,  101,  101,  101,  101,  101,  101,  101,  101,  101,
-      101,  101,  101,  101,  101,  101,  101,  101,  101,  101,
-      101,  101,  101,  101,  101,  101,  101,  101,  101,  101,
-      101,  101,  101,  101,  101,  101,  101,  101,  101,  102,
-      102,  102,  102,  102,  102,  102,  102,  102,  101,  101,
-      101,  101,  101,  101,  101,  101,  101,  101,  101,  101,
-
-      101,  101,  101,  101,  101,  101,  101,  101,  101,  101,
-      101,  101,  101,  101,  101,  101,  101,  101,  101,  101,
-      101,  101,  101,  101,  101,  101,  101,  101,  101,  101,
-      101,  101,  101,  101,  101,  101,  101,  101,  101,  101,
-      101,  101,  101,  101,  101,  101,  101,  101,  101,  101,
-      101,  101,  101,  101,  101,  101,  101,  101
-    },
-
-    {
-       67,  101,  101,  101,  101,  101,  101,  101,  101,  101,
-       68,  101,  101,  101,  101,  101,  101,  101,  101,  101,
-      101,  101,  101,  101,  101,  101,  101,  101,  101,  101,
-      101,  101,  101,  101,  101,  101,  101,  101,  101,  101,
-
-      101,  101,  101,  101,  101,  101,  101,  101,  101,  102,
-      102,  102,  102,  102,  102,  102,  102,  102,  101,  101,
-      101,  101,  101,  101,  101,  101,  101,  101,  101,  101,
-      101,  101,  101,  101,  101,  101,  101,  101,  101,  101,
-      101,  101,  101,  101,  101,  101,  101,  101,  101,  101,
-      101,  101,  101,  101,  101,  101,  101,  101,  101,  101,
-      101,  101,  101,  101,  101,  101,  101,  101,  101,  101,
-      101,  101,  101,  101,  101,  101,  101,  101,  101,  101,
-      101,  101,  101,  101,  101,  101,  101,  101
-    },
-
-    {
-       67,  103,  103,  103,  103,  103,  103,  103,  103,  103,
-
-       68,  103,  103,  103,  103,  103,  103,  103,  103,  103,
-      103,  103,  103,  103,  103,  103,  103,  103,  103,  103,
-      103,  103,  103,  103,  103,  103,  103,  103,  103,  103,
-      103,  103,  103,  103,  103,  103,  103,  103,  103,  104,
-      104,  104,  104,  104,  104,  104,  104,  104,  103,  103,
-      103,  103,  103,  103,  103,  103,  103,  103,  103,  103,
-      103,  103,  103,  103,  103,  103,  103,  103,  103,  103,
-      103,  103,  103,  103,  103,  103,  103,  103,  103,  103,
-      103,  103,  103,  103,  103,  103,  103,  103,  103,  103,
-      103,  103,  103,  103,  103,  103,  103,  103,  103,  103,
-
-      103,  103,  103,  103,  103,  103,  103,  103,  103,  103,
-      103,  103,  103,  103,  103,  103,  103,  103
-    },
-
-    {
-       67,  103,  103,  103,  103,  103,  103,  103,  103,  103,
-       68,  103,  103,  103,  103,  103,  103,  103,  103,  103,
-      103,  103,  103,  103,  103,  103,  103,  103,  103,  103,
-      103,  103,  103,  103,  103,  103,  103,  103,  103,  103,
-      103,  103,  103,  103,  103,  103,  103,  103,  103,  104,
-      104,  104,  104,  104,  104,  104,  104,  104,  103,  103,
-      103,  103,  103,  103,  103,  103,  103,  103,  103,  103,
-      103,  103,  103,  103,  103,  103,  103,  103,  103,  103,
-
-      103,  103,  103,  103,  103,  103,  103,  103,  103,  103,
-      103,  103,  103,  103,  103,  103,  103,  103,  103,  103,
-      103,  103,  103,  103,  103,  103,  103,  103,  103,  103,
-      103,  103,  103,  103,  103,  103,  103,  103,  103,  103,
-      103,  103,  103,  103,  103,  103,  103,  103
-    },
-
-    {
-       67,  105,  105,  105,  105,  105,  105,  105,  105,  105,
-       68,  105,  105,  105,  105,  105,  105,  105,  105,  105,
-      105,  105,  105,  105,  105,  105,  105,  105,  105,  105,
-      105,  105,  105,  105,  105,  105,  105,  105,  105,  105,
-      105,  105,  105,  105,  105,  105,  105,  105,  105,  106,
-
-      106,  106,  106,  106,  106,  106,  106,  106,  105,  105,
-      105,  105,  105,  105,  105,  105,  105,  105,  105,  105,
-      105,  105,  105,  105,  105,  105,  105,  105,  105,  105,
-      105,  105,  105,  105,  105,  105,  105,  105,  105,  105,
-      105,  105,  105,  105,  105,  105,  105,  105,  105,  105,
-      105,  105,  105,  105,  105,  105,  105,  105,  105,  105,
-      105,  105,  105,  105,  105,  105,  105,  105,  105,  105,
-      105,  105,  105,  105,  105,  105,  105,  105
-    },
-
-    {
-       67,  105,  105,  105,  105,  105,  105,  105,  105,  105,
-       68,  105,  105,  105,  105,  105,  105,  105,  105,  105,
-
-      105,  105,  105,  105,  105,  105,  105,  105,  105,  105,
-      105,  105,  105,  105,  105,  105,  105,  105,  105,  105,
-      105,  105,  105,  105,  105,  105,  105,  105,  105,  106,
-      106,  106,  106,  106,  106,  106,  106,  106,  105,  105,
-      105,  105,  105,  105,  105,  105,  105,  105,  105,  105,
-      105,  105,  105,  105,  105,  105,  105,  105,  105,  105,
-      105,  105,  105,  105,  105,  105,  105,  105,  105,  105,
-      105,  105,  105,  105,  105,  105,  105,  105,  105,  105,
-      105,  105,  105,  105,  105,  105,  105,  105,  105,  105,
-      105,  105,  105,  105,  105,  105,  105,  105,  105,  105,
-
-      105,  105,  105,  105,  105,  105,  105,  105
-    },
-
-    {
-       67,  107,  107,  107,  107,  107,  107,  107,  107,  107,
-       68,  107,  107,  107,  107,  107,  107,  107,  107,  107,
-      107,  107,  107,  107,  107,  107,  107,  107,  107,  107,
-      107,  107,  107,  107,  107,  107,  107,  107,  107,  107,
-      107,  107,  107,  107,  107,  107,  107,  107,  107,  108,
-      108,  108,  108,  108,  108,  108,  108,  108,  107,  107,
-      107,  107,  107,  107,  107,  107,  107,  107,  107,  107,
-      107,  107,  107,  107,  107,  107,  107,  107,  107,  107,
-      107,  107,  107,  107,  107,  107,  107,  107,  107,  107,
-
-      107,  107,  107,  107,  107,  107,  107,  107,  107,  107,
-      107,  107,  107,  107,  107,  107,  107,  107,  107,  107,
-      107,  107,  107,  107,  107,  107,  107,  107,  107,  107,
-      107,  107,  107,  107,  107,  107,  107,  107
-    },
-
-    {
-       67,  107,  107,  107,  107,  107,  107,  107,  107,  107,
-       68,  107,  107,  107,  107,  107,  107,  107,  107,  107,
-      107,  107,  107,  107,  107,  107,  107,  107,  107,  107,
-      107,  107,  107,  107,  107,  107,  107,  107,  107,  107,
-      107,  107,  107,  107,  107,  107,  107,  107,  107,  108,
-      108,  108,  108,  108,  108,  108,  108,  108,  107,  107,
-
-      107,  107,  107,  107,  107,  107,  107,  107,  107,  107,
-      107,  107,  107,  107,  107,  107,  107,  107,  107,  107,
-      107,  107,  107,  107,  107,  107,  107,  107,  107,  107,
-      107,  107,  107,  107,  107,  107,  107,  107,  107,  107,
-      107,  107,  107,  107,  107,  107,  107,  107,  107,  107,
-      107,  107,  107,  107,  107,  107,  107,  107,  107,  107,
-      107,  107,  107,  107,  107,  107,  107,  107
-    },
-
-    {
-       67,  109,  109,  109,  109,  109,  109,  109,  109,  109,
-       68,  109,  109,  109,  109,  109,  109,  109,  109,  109,
-      109,  109,  109,  109,  109,  109,  109,  109,  109,  109,
-
-      109,  109,  109,  109,  109,  109,  109,  109,  109,  109,
-      109,  109,  109,  109,  109,  109,  109,  109,  109,  110,
-      110,  110,  110,  110,  110,  110,  110,  110,  109,  109,
-      109,  109,  109,  109,  109,  109,  109,  109,  109,  109,
-      109,  109,  109,  109,  109,  109,  109,  109,  109,  109,
-      109,  109,  109,  109,  109,  109,  109,  109,  109,  109,
-      109,  109,  109,  109,  109,  109,  109,  109,  109,  109,
-      109,  109,  109,  109,  109,  109,  109,  109,  109,  109,
-      109,  109,  109,  109,  109,  109,  109,  109,  109,  109,
-      109,  109,  109,  109,  109,  109,  109,  109
-
-    },
-
-    {
-       67,  109,  109,  109,  109,  109,  109,  109,  109,  109,
-       68,  109,  109,  109,  109,  109,  109,  109,  109,  109,
-      109,  109,  109,  109,  109,  109,  109,  109,  109,  109,
-      109,  109,  109,  109,  109,  109,  109,  109,  109,  109,
-      109,  109,  109,  109,  109,  109,  109,  109,  109,  110,
-      110,  110,  110,  110,  110,  110,  110,  110,  109,  109,
-      109,  109,  109,  109,  109,  109,  109,  109,  109,  109,
-      109,  109,  109,  109,  109,  109,  109,  109,  109,  109,
-      109,  109,  109,  109,  109,  109,  109,  109,  109,  109,
-      109,  109,  109,  109,  109,  109,  109,  109,  109,  109,
-
-      109,  109,  109,  109,  109,  109,  109,  109,  109,  109,
-      109,  109,  109,  109,  109,  109,  109,  109,  109,  109,
-      109,  109,  109,  109,  109,  109,  109,  109
-    },
-
-    {
-       67,  111,  111,  111,  111,  111,  111,  111,  111,  111,
-       68,  111,  111,  111,  111,  111,  111,  111,  111,  111,
-      111,  111,  111,  111,  111,  111,  111,  111,  111,  111,
-      111,  111,  111,  111,  111,  111,  111,  111,  111,  111,
-      111,  111,  111,  111,  111,  111,  111,  111,  111,  112,
-      112,  112,  112,  112,  112,  112,  112,  112,  111,  111,
-      111,  111,  111,  111,  111,  111,  111,  111,  111,  111,
-
-      111,  111,  111,  111,  111,  111,  111,  111,  111,  111,
-      111,  111,  111,  111,  111,  111,  111,  111,  111,  111,
-      111,  111,  111,  111,  111,  111,  111,  111,  111,  111,
-      111,  111,  111,  111,  111,  111,  111,  111,  111,  111,
-      111,  111,  111,  111,  111,  111,  111,  111,  111,  111,
-      111,  111,  111,  111,  111,  111,  111,  111
-    },
-
-    {
-       67,  111,  111,  111,  111,  111,  111,  111,  111,  111,
-       68,  111,  111,  111,  111,  111,  111,  111,  111,  111,
-      111,  111,  111,  111,  111,  111,  111,  111,  111,  111,
-      111,  111,  111,  111,  111,  111,  111,  111,  111,  111,
-
-      111,  111,  111,  111,  111,  111,  111,  111,  111,  112,
-      112,  112,  112,  112,  112,  112,  112,  112,  111,  111,
-      111,  111,  111,  111,  111,  111,  111,  111,  111,  111,
-      111,  111,  111,  111,  111,  111,  111,  111,  111,  111,
-      111,  111,  111,  111,  111,  111,  111,  111,  111,  111,
-      111,  111,  111,  111,  111,  111,  111,  111,  111,  111,
-      111,  111,  111,  111,  111,  111,  111,  111,  111,  111,
-      111,  111,  111,  111,  111,  111,  111,  111,  111,  111,
-      111,  111,  111,  111,  111,  111,  111,  111
-    },
-
-    {
-       67,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-
-       68,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  114,
-      114,  114,  114,  114,  114,  114,  114,  114,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113
-    },
-
-    {
-       67,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-       68,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  114,
-      114,  114,  114,  114,  114,  114,  114,  114,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113
-    },
-
-    {
-       67,  115,  115,  115,  115,  115,  115,  115,  115,  115,
-       68,  115,  115,  115,  115,  115,  115,  115,  115,  115,
-      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
-      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
-      115,  115,  115,  115,  115,  115,  115,  115,  115,  116,
-
-      116,  116,  116,  116,  116,  116,  116,  116,  115,  115,
-      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
-      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
-      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
-      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
-      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
-      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
-      115,  115,  115,  115,  115,  115,  115,  115
-    },
-
-    {
-       67,  115,  115,  115,  115,  115,  115,  115,  115,  115,
-       68,  115,  115,  115,  115,  115,  115,  115,  115,  115,
-
-      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
-      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
-      115,  115,  115,  115,  115,  115,  115,  115,  115,  116,
-      116,  116,  116,  116,  116,  116,  116,  116,  115,  115,
-      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
-      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
-      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
-      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
-      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
-      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
-
-      115,  115,  115,  115,  115,  115,  115,  115
-    },
-
-    {
-       67,  117,  117,  117,  117,  117,  117,  117,  117,  117,
-       68,  117,  117,  117,  117,  117,  117,  117,  117,  117,
-      117,  117,  117,  117,  117,  117,  117,  117,  117,  117,
-      117,  117,  117,  117,  117,  117,  117,  117,  117,  117,
-      117,  117,  117,  117,  117,  117,  117,  117,  118,  118,
-      118,  118,  118,  118,  118,  118,  118,  118,  117,  117,
-      117,  117,  117,  117,  117,  117,  117,  117,  117,  117,
-      117,  117,  117,  117,  117,  117,  117,  117,  117,  117,
-      117,  117,  117,  117,  117,  117,  117,  117,  117,  117,
-
-      117,  117,  117,  117,  117,  117,  117,  117,  117,  117,
-      117,  117,  117,  117,  117,  117,  117,  117,  117,  117,
-      117,  117,  117,  117,  117,  117,  117,  117,  117,  117,
-      117,  117,  117,  117,  117,  117,  117,  117
-    },
-
-    {
-       67,  117,  117,  117,  117,  117,  117,  117,  117,  117,
-       68,  117,  117,  117,  117,  117,  117,  117,  117,  117,
-      117,  117,  117,  117,  117,  117,  117,  117,  117,  117,
-      117,  117,  117,  117,  117,  117,  117,  117,  117,  117,
-      117,  117,  117,  117,  117,  117,  117,  117,  118,  118,
-      118,  118,  118,  118,  118,  118,  118,  118,  117,  117,
-
-      117,  117,  117,  117,  117,  117,  117,  117,  117,  117,
-      117,  117,  117,  117,  117,  117,  117,  117,  117,  117,
-      117,  117,  117,  117,  117,  117,  117,  117,  117,  117,
-      117,  117,  117,  117,  117,  117,  117,  117,  117,  117,
-      117,  117,  117,  117,  117,  117,  117,  117,  117,  117,
-      117,  117,  117,  117,  117,  117,  117,  117,  117,  117,
-      117,  117,  117,  117,  117,  117,  117,  117
-    },
-
-    {
-       67,  119,  119,  119,  119,  119,  119,  119,  119,  119,
-       68,  119,  119,  119,  119,  119,  119,  119,  119,  119,
-      119,  119,  119,  119,  119,  119,  119,  119,  119,  119,
-
-      119,  119,  119,  119,  119,  119,  119,  119,  119,  119,
-      119,  119,  119,  119,  119,  119,  119,  119,  119,  119,
-      119,  119,  119,  119,  119,  119,  119,  119,  119,  119,
-      119,  119,  119,  119,  119,  119,  119,  119,  119,  119,
-      119,  119,  119,  119,  119,  119,  119,  119,  119,  119,
-      119,  119,  119,  119,  119,  119,  119,  119,  119,  119,
-      119,  119,  119,  119,  119,  119,  119,  119,  119,  119,
-      119,  119,  119,  119,  119,  119,  119,  119,  119,  119,
-      119,  119,  119,  119,  119,  119,  119,  119,  119,  119,
-      119,  119,  119,  119,  119,  119,  119,  119
-
-    },
-
-    {
-       67,  119,  119,  119,  119,  119,  119,  119,  119,  119,
-       68,  119,  119,  119,  119,  119,  119,  119,  119,  119,
-      119,  119,  119,  119,  119,  119,  119,  119,  119,  119,
-      119,  119,  119,  119,  119,  119,  119,  119,  119,  119,
-      119,  119,  119,  119,  119,  119,  119,  119,  119,  119,
-      119,  119,  119,  119,  119,  119,  119,  119,  119,  119,
-      119,  119,  119,  119,  119,  119,  119,  119,  119,  119,
-      119,  119,  119,  119,  119,  119,  119,  119,  119,  119,
-      119,  119,  119,  119,  119,  119,  119,  119,  119,  119,
-      119,  119,  119,  119,  119,  119,  119,  119,  119,  119,
-
-      119,  119,  119,  119,  119,  119,  119,  119,  119,  119,
-      119,  119,  119,  119,  119,  119,  119,  119,  119,  119,
-      119,  119,  119,  119,  119,  119,  119,  119
-    },
-
-    {
-       67,  120,  120,  120,  120,  120,  120,  120,  120,  120,
-       68,  120,  120,  120,  120,  120,  120,  120,  120,  120,
-      120,  120,  120,  120,  120,  120,  120,  120,  120,  120,
-      120,  120,  121,  120,  120,  120,  120,  120,  120,  120,
-      120,  120,  120,  120,  120,  120,  120,  120,  120,  120,
-      120,  120,  120,  120,  120,  120,  120,  120,  120,  120,
-      120,  120,  120,  120,  120,  121,  121,  121,  121,  121,
-
-      121,  121,  121,  121,  121,  121,  121,  121,  121,  121,
-      121,  121,  121,  121,  121,  121,  121,  121,  121,  121,
-      121,  120,  120,  120,  120,  120,  120,  120,  120,  120,
-      120,  120,  120,  120,  120,  120,  120,  120,  120,  120,
-      120,  120,  120,  120,  120,  120,  120,  120,  120,  120,
-      120,  120,  120,  120,  120,  120,  120,  120
-    },
-
-    {
-       67,  120,  120,  120,  120,  120,  120,  120,  120,  120,
-       68,  120,  120,  120,  120,  120,  120,  120,  120,  120,
-      120,  120,  120,  120,  120,  120,  120,  120,  120,  120,
-      120,  120,  121,  120,  120,  120,  120,  120,  120,  120,
-
-      120,  120,  120,  120,  120,  120,  120,  120,  120,  120,
-      120,  120,  120,  120,  120,  120,  120,  120,  120,  120,
-      120,  120,  120,  120,  120,  121,  121,  121,  121,  121,
-      121,  121,  121,  121,  121,  121,  121,  121,  121,  121,
-      121,  121,  121,  121,  121,  121,  121,  121,  121,  121,
-      121,  120,  120,  120,  120,  120,  120,  120,  120,  120,
-      120,  120,  120,  120,  120,  120,  120,  120,  120,  120,
-      120,  120,  120,  120,  120,  120,  120,  120,  120,  120,
-      120,  120,  120,  120,  120,  120,  120,  120
-    },
-
-    {
-       67,  122,  122,  122,  122,  122,  122,  122,  122,  122,
-
-       68,  122,  122,  122,  122,  122,  122,  122,  122,  122,
-      122,  122,  122,  122,  122,  122,  122,  122,  122,  122,
-      122,  122,  122,  122,  122,  122,  122,  122,  122,  122,
-      122,  122,  122,  122,  122,  122,  122,  122,  122,  123,
-      123,  123,  123,  123,  123,  123,  123,  123,  122,  122,
-      122,  122,  122,  122,  122,  122,  122,  122,  122,  122,
-      122,  122,  122,  122,  122,  122,  122,  122,  122,  122,
-      122,  122,  122,  122,  122,  122,  122,  122,  122,  122,
-      122,  122,  122,  122,  122,  122,  122,  122,  122,  122,
-      122,  122,  122,  122,  122,  122,  122,  122,  122,  122,
-
-      122,  122,  122,  122,  122,  122,  122,  122,  122,  122,
-      122,  122,  122,  122,  122,  122,  122,  122
-    },
-
-    {
-       67,  122,  122,  122,  122,  122,  122,  122,  122,  122,
-       68,  122,  122,  122,  122,  122,  122,  122,  122,  122,
-      122,  122,  122,  122,  122,  122,  122,  122,  122,  122,
-      122,  122,  122,  122,  122,  122,  122,  122,  122,  122,
-      122,  122,  122,  122,  122,  122,  122,  122,  122,  123,
-      123,  123,  123,  123,  123,  123,  123,  123,  122,  122,
-      122,  122,  122,  122,  122,  122,  122,  122,  122,  122,
-      122,  122,  122,  122,  122,  122,  122,  122,  122,  122,
-
-      122,  122,  122,  122,  122,  122,  122,  122,  122,  122,
-      122,  122,  122,  122,  122,  122,  122,  122,  122,  122,
-      122,  122,  122,  122,  122,  122,  122,  122,  122,  122,
-      122,  122,  122,  122,  122,  122,  122,  122,  122,  122,
-      122,  122,  122,  122,  122,  122,  122,  122
-    },
-
-    {
-       67,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-       68,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  125,
-
-      125,  125,  125,  125,  125,  125,  125,  125,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124
-    },
-
-    {
-       67,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-       68,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  125,
-      125,  125,  125,  125,  125,  125,  125,  125,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
-
-      124,  124,  124,  124,  124,  124,  124,  124
-    },
-
-    {
-       67,  126,  126,  126,  126,  126,  126,  126,  126,  126,
-       68,  126,  126,  126,  126,  126,  126,  126,  126,  126,
-      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
-      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
-      126,  126,  126,  126,  126,  126,  126,  126,  126,  127,
-      127,  127,  127,  127,  127,  127,  127,  127,  126,  126,
-      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
-      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
-      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
-
-      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
-      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
-      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
-      126,  126,  126,  126,  126,  126,  126,  126
-    },
-
-    {
-       67,  126,  126,  126,  126,  126,  126,  126,  126,  126,
-       68,  126,  126,  126,  126,  126,  126,  126,  126,  126,
-      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
-      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
-      126,  126,  126,  126,  126,  126,  126,  126,  126,  127,
-      127,  127,  127,  127,  127,  127,  127,  127,  126,  126,
-
-      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
-      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
-      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
-      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
-      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
-      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
-      126,  126,  126,  126,  126,  126,  126,  126
-    },
-
-    {
-       67,  128,  128,  128,  128,  128,  128,  128,  128,  128,
-       68,  128,  128,  128,  128,  128,  128,  128,  128,  128,
-      128,  128,  128,  128,  128,  128,  128,  128,  128,  128,
-
-      128,  128,  128,  128,  128,  128,  128,  128,  128,  128,
-      128,  128,  128,  128,  128,  128,  128,  128,  128,  129,
-      129,  129,  129,  129,  129,  129,  129,  129,  128,  128,
-      128,  128,  128,  128,  128,  128,  128,  128,  128,  128,
-      128,  128,  128,  128,  128,  128,  128,  128,  128,  128,
-      128,  128,  128,  128,  128,  128,  128,  128,  128,  128,
-      128,  128,  128,  128,  128,  128,  128,  128,  128,  128,
-      128,  128,  128,  128,  128,  128,  128,  128,  128,  128,
-      128,  128,  128,  128,  128,  128,  128,  128,  128,  128,
-      128,  128,  128,  128,  128,  128,  128,  128
-
-    },
-
-    {
-       67,  128,  128,  128,  128,  128,  128,  128,  128,  128,
-       68,  128,  128,  128,  128,  128,  128,  128,  128,  128,
-      128,  128,  128,  128,  128,  128,  128,  128,  128,  128,
-      128,  128,  128,  128,  128,  128,  128,  128,  128,  128,
-      128,  128,  128,  128,  128,  128,  128,  128,  128,  129,
-      129,  129,  129,  129,  129,  129,  129,  129,  128,  128,
-      128,  128,  128,  128,  128,  128,  128,  128,  128,  128,
-      128,  128,  128,  128,  128,  128,  128,  128,  128,  128,
-      128,  128,  128,  128,  128,  128,  128,  128,  128,  128,
-      128,  128,  128,  128,  128,  128,  128,  128,  128,  128,
-
-      128,  128,  128,  128,  128,  128,  128,  128,  128,  128,
-      128,  128,  128,  128,  128,  128,  128,  128,  128,  128,
-      128,  128,  128,  128,  128,  128,  128,  128
-    },
-
-    {
-       67,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-       68,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-      130,  131,  130,  130,  130,  130,  130,  130,  130,  130,
-
-      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-      130,  130,  130,  130,  130,  130,  130,  130
-    },
-
-    {
-       67,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-       68,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-
-      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-      130,  131,  130,  130,  130,  130,  130,  130,  130,  130,
-      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-      130,  130,  130,  130,  130,  130,  130,  130
-    },
-
-    {
-       67,  132,  132,  132,  132,  132,  132,  132,  132,  132,
-
-       68,  132,  132,  132,  132,  132,  132,  132,  132,  132,
-      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
-      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
-      132,  132,  132,  133,  132,  133,  132,  132,  134,  134,
-      134,  134,  134,  134,  134,  134,  134,  134,  132,  132,
-      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
-      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
-      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
-      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
-      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
-
-      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
-      132,  132,  132,  132,  132,  132,  132,  132
-    },
-
-    {
-       67,  132,  132,  132,  132,  132,  132,  132,  132,  132,
-       68,  132,  132,  132,  132,  132,  132,  132,  132,  132,
-      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
-      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
-      132,  132,  132,  133,  132,  133,  132,  132,  134,  134,
-      134,  134,  134,  134,  134,  134,  134,  134,  132,  132,
-      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
-      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
-
-      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
-      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
-      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
-      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
-      132,  132,  132,  132,  132,  132,  132,  132
-    },
-
-    {
-       67,  135,  135,  135,  135,  135,  135,  135,  135,  135,
-       68,  135,  135,  135,  135,  135,  135,  135,  135,  135,
-      135,  135,  135,  135,  135,  135,  135,  135,  135,  135,
-      135,  135,  135,  135,  135,  135,  135,  135,  135,  135,
-      135,  135,  135,  136,  135,  136,  137,  135,  138,  138,
-
-      138,  138,  138,  138,  138,  138,  138,  138,  135,  135,
-      135,  135,  135,  135,  135,  135,  135,  135,  135,  135,
-      135,  135,  135,  135,  135,  135,  135,  135,  135,  135,
-      135,  135,  135,  135,  135,  135,  135,  135,  135,  135,
-      135,  135,  135,  135,  135,  135,  135,  135,  135,  135,
-      135,  135,  135,  135,  135,  135,  135,  135,  135,  135,
-      135,  135,  135,  135,  135,  135,  135,  135,  135,  135,
-      135,  135,  135,  135,  135,  135,  135,  135
-    },
-
-    {
-       67,  135,  135,  135,  135,  135,  135,  135,  135,  135,
-       68,  135,  135,  135,  135,  135,  135,  135,  135,  135,
-
-      135,  135,  135,  135,  135,  135,  135,  135,  135,  135,
-      135,  135,  135,  135,  135,  135,  135,  135,  135,  135,
-      135,  135,  135,  136,  135,  136,  137,  135,  138,  138,
-      138,  138,  138,  138,  138,  138,  138,  138,  135,  135,
-      135,  135,  135,  135,  135,  135,  135,  135,  135,  135,
-      135,  135,  135,  135,  135,  135,  135,  135,  135,  135,
-      135,  135,  135,  135,  135,  135,  135,  135,  135,  135,
-      135,  135,  135,  135,  135,  135,  135,  135,  135,  135,
-      135,  135,  135,  135,  135,  135,  135,  135,  135,  135,
-      135,  135,  135,  135,  135,  135,  135,  135,  135,  135,
-
-      135,  135,  135,  135,  135,  135,  135,  135
-    },
-
-    {
-       67,  139,  139,  139,  139,  139,  139,  139,  139,  139,
-       68,  139,  139,  139,  139,  139,  139,  139,  139,  139,
-      139,  139,  139,  139,  139,  139,  139,  139,  139,  139,
-      139,  139,  139,  139,  139,  139,  139,  139,  139,  140,
-      139,  139,  139,  139,  139,  139,  139,  139,  139,  139,
-      139,  139,  139,  139,  139,  139,  139,  139,  139,  139,
-      139,  139,  139,  139,  139,  139,  139,  139,  139,  139,
-      139,  139,  139,  139,  139,  139,  139,  139,  139,  139,
-      139,  139,  139,  139,  139,  139,  139,  139,  139,  139,
-
-      139,  139,  139,  139,  139,  139,  139,  139,  139,  139,
-      139,  139,  139,  139,  139,  139,  139,  139,  139,  139,
-      139,  139,  139,  139,  139,  139,  139,  139,  139,  139,
-      139,  139,  139,  139,  139,  139,  139,  139
-    },
-
-    {
-       67,  139,  139,  139,  139,  139,  139,  139,  139,  139,
-       68,  139,  139,  139,  139,  139,  139,  139,  139,  139,
-      139,  139,  139,  139,  139,  139,  139,  139,  139,  139,
-      139,  139,  139,  139,  139,  139,  139,  139,  139,  140,
-      139,  139,  139,  139,  139,  139,  139,  139,  139,  139,
-      139,  139,  139,  139,  139,  139,  139,  139,  139,  139,
-
-      139,  139,  139,  139,  139,  139,  139,  139,  139,  139,
-      139,  139,  139,  139,  139,  139,  139,  139,  139,  139,
-      139,  139,  139,  139,  139,  139,  139,  139,  139,  139,
-      139,  139,  139,  139,  139,  139,  139,  139,  139,  139,
-      139,  139,  139,  139,  139,  139,  139,  139,  139,  139,
-      139,  139,  139,  139,  139,  139,  139,  139,  139,  139,
-      139,  139,  139,  139,  139,  139,  139,  139
-    },
-
-    {
-       67,  141,  141,  141,  141,  141,  141,  141,  141,  141,
-       68,  141,  141,  141,  141,  141,  141,  141,  141,  141,
-      141,  141,  141,  141,  141,  141,  141,  141,  141,  141,
-
-      141,  141,  142,  141,  141,  141,  141,  141,  141,  141,
-      141,  141,  141,  141,  141,  141,  141,  143,  141,  141,
-      141,  141,  141,  141,  141,  141,  141,  141,  141,  141,
-      141,  141,  141,  141,  141,  141,  141,  141,  141,  141,
-      141,  141,  141,  141,  141,  141,  141,  141,  141,  141,
-      141,  141,  141,  141,  141,  141,  141,  141,  141,  141,
-      141,  141,  141,  141,  141,  141,  141,  141,  141,  141,
-      141,  141,  141,  141,  141,  141,  141,  141,  141,  141,
-      141,  141,  141,  141,  141,  141,  141,  141,  141,  141,
-      141,  141,  141,  141,  141,  141,  141,  141
-
-    },
-
-    {
-       67,  141,  141,  141,  141,  141,  141,  141,  141,  141,
-       68,  141,  141,  141,  141,  141,  141,  141,  141,  141,
-      141,  141,  141,  141,  141,  141,  141,  141,  141,  141,
-      141,  141,  142,  141,  141,  141,  141,  141,  141,  141,
-      141,  141,  141,  141,  141,  141,  141,  143,  141,  141,
-      141,  141,  141,  141,  141,  141,  141,  141,  141,  141,
-      141,  141,  141,  141,  141,  141,  141,  141,  141,  141,
-      141,  141,  141,  141,  141,  141,  141,  141,  141,  141,
-      141,  141,  141,  141,  141,  141,  141,  141,  141,  141,
-      141,  141,  141,  141,  141,  141,  141,  141,  141,  141,
-
-      141,  141,  141,  141,  141,  141,  141,  141,  141,  141,
-      141,  141,  141,  141,  141,  141,  141,  141,  141,  141,
-      141,  141,  141,  141,  141,  141,  141,  141
-    },
-
-    {
-       67,  144,  144,  144,  144,  144,  144,  144,  144,  144,
-       68,  144,  144,  144,  144,  144,  144,  144,  144,  144,
-      144,  144,  144,  144,  144,  144,  144,  144,  144,  144,
-      144,  144,  144,  144,  144,  144,  144,  144,  144,  144,
-      144,  144,  144,  144,  144,  144,  144,  144,  144,  144,
-      144,  144,  144,  144,  144,  144,  144,  144,  144,  144,
-      144,  144,  144,  144,  144,  144,  144,  144,  144,  144,
-
-      144,  144,  144,  144,  144,  144,  144,  144,  144,  144,
-      144,  144,  144,  144,  144,  144,  144,  144,  144,  144,
-      144,  144,  144,  144,  144,  144,  144,  144,  144,  144,
-      144,  144,  144,  144,  144,  144,  144,  144,  144,  144,
-      144,  144,  144,  144,  144,  144,  144,  144,  144,  144,
-      144,  144,  144,  144,  144,  144,  144,  144
-    },
-
-    {
-       67,  144,  144,  144,  144,  144,  144,  144,  144,  144,
-       68,  144,  144,  144,  144,  144,  144,  144,  144,  144,
-      144,  144,  144,  144,  144,  144,  144,  144,  144,  144,
-      144,  144,  144,  144,  144,  144,  144,  144,  144,  144,
-
-      144,  144,  144,  144,  144,  144,  144,  144,  144,  144,
-      144,  144,  144,  144,  144,  144,  144,  144,  144,  144,
-      144,  144,  144,  144,  144,  144,  144,  144,  144,  144,
-      144,  144,  144,  144,  144,  144,  144,  144,  144,  144,
-      144,  144,  144,  144,  144,  144,  144,  144,  144,  144,
-      144,  144,  144,  144,  144,  144,  144,  144,  144,  144,
-      144,  144,  144,  144,  144,  144,  144,  144,  144,  144,
-      144,  144,  144,  144,  144,  144,  144,  144,  144,  144,
-      144,  144,  144,  144,  144,  144,  144,  144
-    },
-
-    {
-       67,  145,  145,  145,  145,  145,  145,  145,  145,  145,
-
-       68,  145,  145,  145,  145,  145,  145,  145,  145,  145,
-      145,  145,  145,  145,  145,  145,  145,  145,  145,  145,
-      145,  145,  145,  145,  145,  145,  145,  145,  145,  145,
-      145,  145,  145,  145,  145,  145,  145,  145,  145,  145,
-      145,  145,  145,  145,  145,  145,  145,  145,  145,  145,
-      145,  145,  145,  145,  145,  145,  145,  145,  145,  145,
-      145,  145,  145,  145,  145,  145,  145,  145,  145,  145,
-      145,  145,  145,  145,  145,  145,  145,  145,  145,  145,
-      145,  145,  145,  145,  145,  145,  145,  145,  145,  145,
-      145,  145,  145,  145,  145,  145,  145,  145,  145,  145,
-
-      145,  145,  145,  145,  145,  145,  145,  145,  145,  145,
-      145,  145,  145,  145,  145,  145,  145,  145
-    },
-
-    {
-       67,  145,  145,  145,  145,  145,  145,  145,  145,  145,
-       68,  145,  145,  145,  145,  145,  145,  145,  145,  145,
-      145,  145,  145,  145,  145,  145,  145,  145,  145,  145,
-      145,  145,  145,  145,  145,  145,  145,  145,  145,  145,
-      145,  145,  145,  145,  145,  145,  145,  145,  145,  145,
-      145,  145,  145,  145,  145,  145,  145,  145,  145,  145,
-      145,  145,  145,  145,  145,  145,  145,  145,  145,  145,
-      145,  145,  145,  145,  145,  145,  145,  145,  145,  145,
-
-      145,  145,  145,  145,  145,  145,  145,  145,  145,  145,
-      145,  145,  145,  145,  145,  145,  145,  145,  145,  145,
-      145,  145,  145,  145,  145,  145,  145,  145,  145,  145,
-      145,  145,  145,  145,  145,  145,  145,  145,  145,  145,
-      145,  145,  145,  145,  145,  145,  145,  145
-    },
-
-    {
-       67,  146,  146,  146,  146,  146,  146,  146,  146,  146,
-      147,  146,  146,  146,  146,  146,  146,  146,  146,  146,
-      146,  146,  146,  146,  146,  146,  146,  146,  146,  146,
-      146,  146,  146,  146,  146,  146,  146,  146,  146,  146,
-      146,  146,  146,  146,  146,  146,  146,  146,  146,  146,
-
-      146,  146,  146,  146,  146,  146,  146,  146,  146,  146,
-      146,  146,  146,  146,  146,  146,  146,  146,  146,  146,
-      146,  146,  146,  146,  146,  146,  146,  146,  146,  146,
-      146,  146,  146,  146,  146,  146,  146,  146,  146,  146,
-      146,  146,  146,  146,  146,  146,  146,  146,  146,  146,
-      146,  146,  146,  146,  146,  146,  146,  146,  146,  146,
-      146,  146,  146,  146,  146,  146,  146,  146,  146,  146,
-      146,  146,  146,  146,  146,  146,  146,  146
-    },
-
-    {
-       67,  146,  146,  146,  146,  146,  146,  146,  146,  146,
-      147,  146,  146,  146,  146,  146,  146,  146,  146,  146,
-
-      146,  146,  146,  146,  146,  146,  146,  146,  146,  146,
-      146,  146,  146,  146,  146,  146,  146,  146,  146,  146,
-      146,  146,  146,  146,  146,  146,  146,  146,  146,  146,
-      146,  146,  146,  146,  146,  146,  146,  146,  146,  146,
-      146,  146,  146,  146,  146,  146,  146,  146,  146,  146,
-      146,  146,  146,  146,  146,  146,  146,  146,  146,  146,
-      146,  146,  146,  146,  146,  146,  146,  146,  146,  146,
-      146,  146,  146,  146,  146,  146,  146,  146,  146,  146,
-      146,  146,  146,  146,  146,  146,  146,  146,  146,  146,
-      146,  146,  146,  146,  146,  146,  146,  146,  146,  146,
-
-      146,  146,  146,  146,  146,  146,  146,  146
-    },
-
-    {
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67
-    },
-
-    {
-       67,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-
-      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68
-    },
-
-    {
-       67,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-
-      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69
-
-    },
-
-    {
-       67,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
-      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
-      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
-      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
-      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  148,  148,
-      148,  148,  148,  148,  148,  148,  148,  148,  -70,  -70,
-      -70,  -70,  -70,  -70,  -70,  -70,  -70,  149,  -70,  -70,
-      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
-      150,  -70,  -70,  151,  -70,  -70,  152,  -70,  -70,  -70,
-      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
-
-      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
-      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
-      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70
-    },
-
-    {
-       67,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
-      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
-      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
-      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
-      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
-      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
-      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  153,  -71,
-
-      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  154,  -71,
-      -71,  -71,  155,  156,  157,  158,  -71,  -71,  -71,  -71,
-      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
-      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
-      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
-      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71
-    },
-
-    {
-       67,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
-      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
-      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
-      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
-
-      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
-      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
-      -72,  -72,  -72,  -72,  -72,  159,  -72,  -72,  -72,  -72,
-      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  160,
-      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
-      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
-      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
-      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
-      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72
-    },
-
-    {
-       67,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
-
-      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
-      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
-      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
-      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
-      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
-      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
-      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  161,  -73,
-      162,  163,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
-      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
-      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
-
-      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
-      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73
-    },
-
-    {
-       67,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
-      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
-      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
-      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
-      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
-      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
-      -74,  -74,  -74,  -74,  -74,  164,  -74,  -74,  -74,  -74,
-      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  165,
-
-      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
-      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
-      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
-      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
-      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74
-    },
-
-    {
-       67,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
-      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
-      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
-      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
-      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
-
-      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
-      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
-      -75,  -75,  -75,  -75,  166,  -75,  -75,  -75,  -75,  -75,
-      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
-      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
-      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
-      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
-      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75
-    },
-
-    {
-       67,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
-      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
-
-      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
-      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
-      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
-      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
-      -76,  -76,  -76,  -76,  -76,  -76,  167,  -76,  -76,  -76,
-      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
-      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
-      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
-      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
-      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
-
-      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76
-    },
-
-    {
-       67,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
-      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
-      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
-      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
-      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
-      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
-      -77,  -77,  -77,  -77,  -77,  -77,  -77,  168,  -77,  -77,
-      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
-      -77,  -77,  169,  170,  -77,  -77,  171,  -77,  -77,  -77,
-
-      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
-      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
-      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
-      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77
-    },
-
-    {
-       67,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
-      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
-      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
-      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
-      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
-      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
-
-      -78,  -78,  -78,  -78,  -78,  172,  -78,  -78,  -78,  173,
-      174,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
-      -78,  -78,  -78,  -78,  -78,  -78,  -78,  175,  -78,  -78,
-      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
-      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
-      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
-      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78
-    },
-
-    {
-       67,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
-      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
-      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
-
-      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
-      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
-      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
-      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
-      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  176,
-      177,  -79,  -79,  178,  -79,  -79,  -79,  -79,  -79,  -79,
-      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
-      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
-      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
-      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79
-
-    },
-
-    {
-       67,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
-      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
-      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
-      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
-      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
-      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
-      -80,  -80,  -80,  -80,  -80,  -80,  -80,  179,  -80,  -80,
-      180,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
-      181,  -80,  -80,  182,  -80,  -80,  183,  184,  -80,  -80,
-      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
-
-      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
-      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
-      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80
-    },
-
-    {
-       67,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
-      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
-      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
-      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
-      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
-      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
-      -81,  -81,  -81,  -81,  -81,  185,  -81,  -81,  -81,  186,
-
-      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
-      -81,  -81,  -81,  187,  -81,  -81,  -81,  -81,  -81,  -81,
-      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
-      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
-      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
-      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81
-    },
-
-    {
-       67,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
-      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
-      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
-      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
-
-      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
-      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
-      -82,  -82,  -82,  -82,  -82,  -82,  -82,  188,  -82,  -82,
-      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
-      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
-      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
-      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
-      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
-      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82
-    },
-
-    {
-       67,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
-
-      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
-      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
-      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
-      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
-      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
-      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
-      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
-      -83,  -83,  -83,  189,  -83,  -83,  -83,  -83,  -83,  -83,
-      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
-      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
-
-      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
-      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83
-    },
-
-    {
-       67,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
-      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
-      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
-      -84,  -84,  190,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
-      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  191,  191,
-      191,  191,  191,  191,  191,  191,  191,  191,  -84,  -84,
-      -84,  -84,  -84,  -84,  -84,  190,  190,  190,  190,  190,
-      190,  190,  190,  190,  190,  190,  190,  190,  190,  190,
-
-      190,  190,  190,  190,  190,  190,  190,  190,  190,  190,
-      190,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
-      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
-      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
-      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84
-    },
-
-    {
-       67,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
-      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
-      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
-      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
-      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
-
-      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
-      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
-      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
-      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
-      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
-      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
-      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
-      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85
-    },
-
-    {
-       67,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
-      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
-
-      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
-      -86,  -86,  192,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
-      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  193,  193,
-      193,  193,  193,  193,  193,  193,  193,  193,  -86,  -86,
-      -86,  -86,  -86,  -86,  -86,  192,  192,  192,  192,  192,
-      192,  192,  192,  192,  192,  192,  192,  192,  192,  192,
-      192,  192,  192,  192,  192,  192,  192,  192,  192,  192,
-      192,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
-      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
-      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
-
-      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86
-    },
-
-    {
-       67,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-
-      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87
-    },
-
-    {
-       67,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
-      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
-      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
-      -88,  -88,  194,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
-      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  195,  195,
-      195,  195,  195,  195,  195,  195,  195,  195,  -88,  -88,
-
-      -88,  -88,  -88,  -88,  -88,  196,  196,  196,  196,  196,
-      196,  196,  196,  196,  196,  196,  196,  196,  196,  196,
-      196,  196,  196,  196,  196,  196,  196,  196,  196,  196,
-      196,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
-      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
-      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
-      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88
-    },
-
-    {
-       67,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-
-      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89
-
-    },
-
-    {
-       67,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
-      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
-      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
-      -90,  -90,  197,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
-      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  198,  198,
-      198,  198,  198,  198,  198,  198,  198,  198,  -90,  -90,
-      -90,  -90,  -90,  -90,  -90,  197,  197,  197,  197,  197,
-      197,  197,  197,  197,  197,  197,  197,  197,  197,  197,
-      197,  197,  197,  197,  197,  197,  197,  197,  197,  197,
-      197,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
-
-      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
-      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
-      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90
-    },
-
-    {
-       67,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
-      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
-      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
-      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
-      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
-      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
-      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
-
-      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
-      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
-      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
-      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
-      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
-      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91
-    },
-
-    {
-       67,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
-      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
-      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
-      -92,  -92,  199,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
-
-      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  200,  200,
-      200,  200,  200,  200,  200,  200,  200,  200,  -92,  -92,
-      -92,  -92,  -92,  -92,  -92,  201,  201,  201,  201,  201,
-      201,  201,  201,  201,  201,  201,  201,  201,  201,  201,
-      201,  201,  201,  201,  201,  201,  201,  201,  201,  201,
-      201,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
-      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
-      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
-      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92
-    },
-
-    {
-       67,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-
-      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-
-      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93
-    },
-
-    {
-       67,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
-      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
-      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
-      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
-      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  202,  202,
-      202,  202,  202,  202,  202,  202,  202,  202,  -94,  -94,
-      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
-      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
-
-      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
-      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
-      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
-      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
-      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94
-    },
-
-    {
-       67,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
-      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
-      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
-      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
-      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  203,  203,
-
-      203,  203,  203,  203,  203,  203,  203,  203,  -95,  -95,
-      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
-      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
-      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
-      -95,  -95,  -95,  -95,  -95,  204,  -95,  -95,  -95,  -95,
-      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
-      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
-      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95
-    },
-
-    {
-       67,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
-      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
-
-      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
-      -96,  -96,  205,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
-      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  206,  206,
-      206,  206,  206,  206,  206,  206,  206,  206,  -96,  -96,
-      -96,  -96,  -96,  -96,  -96,  205,  205,  205,  205,  205,
-      205,  205,  205,  205,  205,  205,  205,  205,  205,  205,
-      205,  205,  205,  205,  205,  205,  205,  205,  205,  205,
-      205,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
-      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
-      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
-
-      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96
-    },
-
-    {
-       67,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
-      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
-      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
-      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
-      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
-      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
-      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
-      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
-      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
-
-      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
-      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
-      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
-      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97
-    },
-
-    {
-       67,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
-      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
-      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
-      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
-      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  207,  207,
-      207,  207,  207,  207,  207,  207,  207,  207,  -98,  -98,
-
-      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
-      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
-      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
-      -98,  -98,  -98,  -98,  -98,  208,  -98,  -98,  -98,  -98,
-      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
-      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
-      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98
-    },
-
-    {
-       67,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-
-      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99
-
-    },
-
-    {
-       67, -100, -100, -100, -100, -100, -100, -100, -100, -100,
-     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
-     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
-     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
-     -100, -100, -100, -100, -100, -100, -100, -100,  209,  209,
-      209,  209,  209,  209,  209,  209,  209,  209, -100, -100,
-     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
-     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
-     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
-     -100, -100, -100, -100, -100,  210, -100, -100, -100, -100,
-
-     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
-     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
-     -100, -100, -100, -100, -100, -100, -100, -100
-    },
-
-    {
-       67, -101, -101, -101, -101, -101, -101, -101, -101, -101,
-     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
-     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
-     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
-     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
-     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
-     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
-
-     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
-     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
-     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
-     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
-     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
-     -101, -101, -101, -101, -101, -101, -101, -101
-    },
-
-    {
-       67, -102, -102, -102, -102, -102, -102, -102, -102, -102,
-     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
-     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
-     -102, -102,  211, -102, -102, -102, -102, -102, -102, -102,
-
-     -102, -102, -102, -102, -102, -102, -102, -102,  212,  212,
-      212,  212,  212,  212,  212,  212,  212,  212, -102, -102,
-     -102, -102, -102, -102, -102,  213,  213,  213,  213,  213,
-      213,  213,  213,  213,  213,  213,  213,  213,  213,  213,
-      213,  213,  213,  213,  213,  213,  213,  213,  213,  213,
-      213, -102, -102, -102, -102, -102, -102, -102, -102, -102,
-     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
-     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
-     -102, -102, -102, -102, -102, -102, -102, -102
-    },
-
-    {
-       67, -103, -103, -103, -103, -103, -103, -103, -103, -103,
-
-     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
-     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
-     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
-     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
-     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
-     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
-     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
-     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
-     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
-     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
-
-     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
-     -103, -103, -103, -103, -103, -103, -103, -103
-    },
-
-    {
-       67, -104, -104, -104, -104, -104, -104, -104, -104, -104,
-     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
-     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
-     -104, -104,  214, -104, -104, -104, -104, -104, -104, -104,
-     -104, -104, -104, -104, -104, -104, -104, -104,  215,  215,
-      215,  215,  215,  215,  215,  215,  215,  215, -104, -104,
-     -104, -104, -104, -104, -104,  216,  216,  216,  216,  216,
-      216,  216,  216,  216,  216,  216,  216,  216,  216,  216,
-
-      216,  216,  216,  216,  216,  216,  216,  216,  216,  216,
-      216, -104, -104, -104, -104, -104, -104, -104, -104, -104,
-     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
-     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
-     -104, -104, -104, -104, -104, -104, -104, -104
-    },
-
-    {
-       67, -105, -105, -105, -105, -105, -105, -105, -105, -105,
-     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
-     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
-     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
-     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
-
-     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
-     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
-     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
-     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
-     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
-     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
-     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
-     -105, -105, -105, -105, -105, -105, -105, -105
-    },
-
-    {
-       67, -106, -106, -106, -106, -106, -106, -106, -106, -106,
-     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
-
-     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
-     -106, -106,  217, -106, -106, -106, -106, -106, -106, -106,
-     -106, -106, -106, -106, -106, -106, -106, -106,  218,  218,
-      218,  218,  218,  218,  218,  218,  218,  218, -106, -106,
-     -106, -106, -106, -106, -106,  219,  219,  219,  219,  219,
-      219,  219,  219,  219,  219,  219,  219,  219,  219,  219,
-      219,  219,  219,  219,  219,  219,  219,  219,  219,  219,
-      219, -106, -106, -106, -106, -106, -106, -106, -106, -106,
-     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
-     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
-
-     -106, -106, -106, -106, -106, -106, -106, -106
-    },
-
-    {
-       67, -107, -107, -107, -107, -107, -107, -107, -107, -107,
-     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
-     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
-     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
-     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
-     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
-     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
-     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
-     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
-
-     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
-     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
-     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
-     -107, -107, -107, -107, -107, -107, -107, -107
-    },
-
-    {
-       67, -108, -108, -108, -108, -108, -108, -108, -108, -108,
-     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
-     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
-     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
-     -108, -108, -108, -108, -108, -108, -108, -108,  220,  220,
-      220,  220,  220,  220,  220,  220,  220,  220, -108, -108,
-
-     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
-     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
-     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
-     -108, -108, -108, -108, -108,  221, -108, -108, -108, -108,
-     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
-     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
-     -108, -108, -108, -108, -108, -108, -108, -108
-    },
-
-    {
-       67, -109, -109, -109, -109, -109, -109, -109, -109, -109,
-     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
-     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
-
-     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
-     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
-     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
-     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
-     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
-     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
-     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
-     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
-     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
-     -109, -109, -109, -109, -109, -109, -109, -109
-
-    },
-
-    {
-       67, -110, -110, -110, -110, -110, -110, -110, -110, -110,
-     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
-     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
-     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
-     -110, -110, -110, -110, -110, -110, -110, -110,  222,  222,
-      222,  222,  222,  222,  222,  222,  222,  222, -110, -110,
-     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
-     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
-     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
-     -110, -110, -110, -110, -110,  223, -110, -110, -110, -110,
-
-     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
-     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
-     -110, -110, -110, -110, -110, -110, -110, -110
-    },
-
-    {
-       67, -111, -111, -111, -111, -111, -111, -111, -111, -111,
-     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
-     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
-     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
-     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
-     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
-     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
-
-     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
-     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
-     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
-     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
-     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
-     -111, -111, -111, -111, -111, -111, -111, -111
-    },
-
-    {
-       67, -112, -112, -112, -112, -112, -112, -112, -112, -112,
-     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
-     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
-     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
-
-     -112, -112, -112, -112, -112, -112, -112, -112,  224,  224,
-      224,  224,  224,  224,  224,  224,  224,  224, -112, -112,
-     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
-     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
-     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
-     -112, -112, -112, -112, -112,  225, -112, -112, -112, -112,
-     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
-     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
-     -112, -112, -112, -112, -112, -112, -112, -112
-    },
-
-    {
-       67, -113, -113, -113, -113, -113, -113, -113, -113, -113,
-
-     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
-     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
-     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
-     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
-     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
-     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
-     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
-     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
-     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
-     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
-
-     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
-     -113, -113, -113, -113, -113, -113, -113, -113
-    },
-
-    {
-       67, -114, -114, -114, -114, -114, -114, -114, -114, -114,
-     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
-     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
-     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
-     -114, -114, -114, -114, -114, -114, -114, -114,  226,  226,
-      226,  226,  226,  226,  226,  226,  226,  226, -114, -114,
-     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
-     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
-
-     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
-     -114, -114, -114, -114, -114,  227, -114, -114, -114, -114,
-     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
-     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
-     -114, -114, -114, -114, -114, -114, -114, -114
-    },
-
-    {
-       67, -115, -115, -115, -115, -115, -115, -115, -115, -115,
-     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
-     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
-     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
-     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
-
-     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
-     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
-     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
-     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
-     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
-     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
-     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
-     -115, -115, -115, -115, -115, -115, -115, -115
-    },
-
-    {
-       67, -116, -116, -116, -116, -116, -116, -116, -116, -116,
-     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
-
-     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
-     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
-     -116, -116, -116, -116, -116, -116, -116, -116,  228,  228,
-      228,  228,  228,  228,  228,  228,  228,  228, -116, -116,
-     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
-     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
-     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
-     -116, -116, -116, -116, -116,  229, -116, -116, -116, -116,
-     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
-     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
-
-     -116, -116, -116, -116, -116, -116, -116, -116
-    },
-
-    {
-       67, -117, -117, -117, -117, -117, -117, -117, -117, -117,
-     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
-     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
-     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
-     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
-     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
-     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
-     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
-     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
-
-     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
-     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
-     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
-     -117, -117, -117, -117, -117, -117, -117, -117
-    },
-
-    {
-       67, -118, -118, -118, -118, -118, -118, -118, -118, -118,
-     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
-     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
-     -118, -118,  230, -118, -118, -118, -118, -118, -118, -118,
-     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
-     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
-
-     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
-     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
-     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
-     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
-     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
-     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
-     -118, -118, -118, -118, -118, -118, -118, -118
-    },
-
-    {
-       67, -119, -119, -119, -119, -119, -119, -119, -119, -119,
-     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
-     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
-
-     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
-     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
-     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
-     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
-     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
-     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
-     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
-     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
-     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
-     -119, -119, -119, -119, -119, -119, -119, -119
-
-    },
-
-    {
-       67, -120, -120, -120, -120, -120, -120, -120, -120, -120,
-     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
-     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
-     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
-     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
-     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
-     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
-     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
-     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
-     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
-
-     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
-     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
-     -120, -120, -120, -120, -120, -120, -120, -120
-    },
-
-    {
-       67, -121, -121, -121, -121, -121, -121, -121, -121, -121,
-     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
-     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
-     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
-     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
-     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
-     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
-
-     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
-     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
-     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
-     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
-     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
-     -121, -121, -121, -121, -121, -121, -121, -121
-    },
-
-    {
-       67, -122, -122, -122, -122, -122, -122, -122, -122, -122,
-     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
-     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
-     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
-
-     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
-     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
-     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
-     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
-     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
-     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
-     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
-     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
-     -122, -122, -122, -122, -122, -122, -122, -122
-    },
-
-    {
-       67, -123, -123, -123, -123, -123, -123, -123, -123, -123,
-
-     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
-     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
-     -123, -123,  231, -123, -123, -123, -123, -123, -123, -123,
-     -123, -123, -123, -123, -123, -123, -123, -123,  232,  232,
-      232,  232,  232,  232,  232,  232,  232,  232, -123, -123,
-     -123, -123, -123, -123, -123,  231,  231,  231,  231,  231,
-      231,  231,  231,  231,  231,  231,  231,  231,  231,  231,
-      231,  231,  231,  231,  231,  231,  231,  231,  231,  231,
-      231, -123, -123, -123, -123, -123, -123, -123, -123, -123,
-     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
-
-     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
-     -123, -123, -123, -123, -123, -123, -123, -123
-    },
-
-    {
-       67, -124, -124, -124, -124, -124, -124, -124, -124, -124,
-     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
-     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
-     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
-     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
-     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
-     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
-     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
-
-     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
-     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
-     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
-     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
-     -124, -124, -124, -124, -124, -124, -124, -124
-    },
-
-    {
-       67, -125, -125, -125, -125, -125, -125, -125, -125, -125,
-     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
-     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
-     -125, -125,  233, -125, -125, -125, -125, -125, -125, -125,
-     -125, -125, -125, -125, -125, -125, -125, -125,  234,  234,
-
-      234,  234,  234,  234,  234,  234,  234,  234, -125, -125,
-     -125, -125, -125, -125, -125,  233,  233,  233,  233,  233,
-      233,  233,  233,  233,  233,  233,  233,  233,  233,  233,
-      233,  233,  233,  233,  233,  233,  233,  233,  233,  233,
-      233, -125, -125, -125, -125, -125, -125, -125, -125, -125,
-     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
-     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
-     -125, -125, -125, -125, -125, -125, -125, -125
-    },
-
-    {
-       67, -126, -126, -126, -126, -126, -126, -126, -126, -126,
-     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
-
-     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
-     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
-     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
-     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
-     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
-     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
-     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
-     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
-     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
-     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
-
-     -126, -126, -126, -126, -126, -126, -126, -126
-    },
-
-    {
-       67, -127, -127, -127, -127, -127, -127, -127, -127, -127,
-     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
-     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
-     -127, -127,  235, -127, -127, -127, -127, -127, -127, -127,
-     -127, -127, -127, -127, -127, -127, -127, -127,  236,  236,
-      236,  236,  236,  236,  236,  236,  236,  236, -127, -127,
-     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
-     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
-     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
-
-     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
-     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
-     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
-     -127, -127, -127, -127, -127, -127, -127, -127
-    },
-
-    {
-       67, -128, -128, -128, -128, -128, -128, -128, -128, -128,
-     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
-     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
-     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
-     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
-     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
-
-     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
-     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
-     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
-     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
-     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
-     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
-     -128, -128, -128, -128, -128, -128, -128, -128
-    },
-
-    {
-       67, -129, -129, -129, -129, -129, -129, -129, -129, -129,
-     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
-     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
-
-     -129, -129,  237, -129, -129, -129, -129, -129, -129, -129,
-     -129, -129, -129, -129, -129, -129, -129, -129,  238,  238,
-      238,  238,  238,  238,  238,  238,  238,  238, -129, -129,
-     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
-     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
-     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
-     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
-     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
-     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
-     -129, -129, -129, -129, -129, -129, -129, -129
-
-    },
-
-    {
-       67, -130, -130, -130, -130, -130, -130, -130, -130, -130,
-     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
-     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
-     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
-     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
-     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
-     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
-     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
-     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
-     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
-
-     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
-     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
-     -130, -130, -130, -130, -130, -130, -130, -130
-    },
-
-    {
-       67, -131, -131, -131, -131, -131, -131, -131, -131, -131,
-     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
-     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
-     -131, -131,  239, -131, -131, -131, -131, -131, -131, -131,
-     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
-     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
-     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
-
-     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
-     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
-     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
-     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
-     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
-     -131, -131, -131, -131, -131, -131, -131, -131
-    },
-
-    {
-       67, -132, -132, -132, -132, -132, -132, -132, -132, -132,
-     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
-     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
-     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
-
-     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
-     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
-     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
-     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
-     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
-     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
-     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
-     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
-     -132, -132, -132, -132, -132, -132, -132, -132
-    },
-
-    {
-       67, -133, -133, -133, -133, -133, -133, -133, -133, -133,
-
-     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
-     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
-     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
-     -133, -133, -133, -133, -133, -133, -133, -133,  240,  240,
-      240,  240,  240,  240,  240,  240,  240,  240, -133, -133,
-     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
-     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
-     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
-     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
-     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
-
-     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
-     -133, -133, -133, -133, -133, -133, -133, -133
-    },
-
-    {
-       67, -134, -134, -134, -134, -134, -134, -134, -134, -134,
-     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
-     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
-     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
-     -134, -134, -134, -134, -134, -134, -134, -134,  240,  240,
-      240,  240,  240,  240,  240,  240,  240,  240, -134, -134,
-     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
-     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
-
-     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
-     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
-     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
-     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
-     -134, -134, -134, -134, -134, -134, -134, -134
-    },
-
-    {
-       67, -135, -135, -135, -135, -135, -135, -135, -135, -135,
-     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
-     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
-     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
-     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
-
-     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
-     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
-     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
-     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
-     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
-     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
-     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
-     -135, -135, -135, -135, -135, -135, -135, -135
-    },
-
-    {
-       67, -136, -136, -136, -136, -136, -136, -136, -136, -136,
-     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
-
-     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
-     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
-     -136, -136, -136, -136, -136, -136,  241, -136,  242,  242,
-      242,  242,  242,  242,  242,  242,  242,  242, -136, -136,
-     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
-     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
-     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
-     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
-     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
-     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
-
-     -136, -136, -136, -136, -136, -136, -136, -136
-    },
-
-    {
-       67, -137, -137, -137, -137, -137, -137, -137, -137, -137,
-     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
-     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
-     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
-     -137, -137, -137, -137, -137, -137, -137, -137,  243,  243,
-      243,  243,  243,  243,  243,  243,  243,  243, -137, -137,
-     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
-     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
-     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
-
-     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
-     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
-     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
-     -137, -137, -137, -137, -137, -137, -137, -137
-    },
-
-    {
-       67, -138, -138, -138, -138, -138, -138, -138, -138, -138,
-     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
-     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
-     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
-     -138, -138, -138, -138, -138, -138,  244, -138,  245,  245,
-      245,  245,  245,  245,  245,  245,  245,  245, -138, -138,
-
-     -138, -138, -138, -138, -138, -138, -138, -138, -138,  246,
-     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
-     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
-     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
-     -138,  246, -138, -138, -138, -138, -138, -138, -138, -138,
-     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
-     -138, -138, -138, -138, -138, -138, -138, -138
-    },
-
-    {
-       67, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-
-     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-     -139, -139, -139, -139, -139, -139, -139, -139
-
-    },
-
-    {
-       67,  247,  247,  247,  247,  247,  247,  247,  247,  247,
-      247,  247,  247,  247,  247,  247,  247,  247,  247,  247,
-      247,  247,  247,  247,  247,  247,  247,  247,  247,  247,
-      247,  247,  247,  247,  247,  247,  247,  247,  247,  248,
-      247,  247,  247,  247,  247,  247,  247,  247,  247,  247,
-      247,  247,  247,  247,  247,  247,  247,  247,  247,  247,
-      247,  247,  247,  247,  247,  247,  247,  247,  247,  247,
-      247,  247,  247,  247,  247,  247,  247,  247,  247,  247,
-      247,  247,  247,  247,  247,  247,  247,  247,  247,  247,
-      247,  247,  247,  247,  247,  247,  247,  247,  247,  247,
-
-      247,  247,  247,  247,  247,  247,  247,  247,  247,  247,
-      247,  247,  247,  247,  247,  247,  247,  247,  247,  247,
-      247,  247,  247,  247,  247,  247,  247,  247
-    },
-
-    {
-       67, -141, -141, -141, -141, -141, -141, -141, -141, -141,
-     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
-     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
-     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
-     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
-     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
-     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
-
-     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
-     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
-     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
-     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
-     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
-     -141, -141, -141, -141, -141, -141, -141, -141
-    },
-
-    {
-       67, -142, -142, -142, -142, -142, -142, -142, -142, -142,
-     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
-     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
-     -142, -142,  249, -142, -142, -142, -142, -142, -142, -142,
-
-     -142, -142, -142, -142, -142, -142, -142,  250, -142, -142,
-     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
-     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
-     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
-     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
-     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
-     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
-     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
-     -142, -142, -142, -142, -142, -142, -142, -142
-    },
-
-    {
-       67,  251,  251,  251,  251,  251,  251,  251,  251,  251,
-
-     -143,  251,  251,  251,  251,  251,  251,  251,  251,  251,
-      251,  251,  251,  251,  251,  251,  251,  251,  251,  251,
-      251,  251,  251,  251,  251,  251,  251,  251,  251,  251,
-      251,  251,  251,  251,  251,  251,  251,  251,  251,  251,
-      251,  251,  251,  251,  251,  251,  251,  251,  251,  251,
-      251,  251,  251,  251,  251,  251,  251,  251,  251,  251,
-      251,  251,  251,  251,  251,  251,  251,  251,  251,  251,
-      251,  251,  251,  251,  251,  251,  251,  251,  251,  251,
-      251,  251,  251,  251,  251,  251,  251,  251,  251,  251,
-      251,  251,  251,  251,  251,  251,  251,  251,  251,  251,
-
-      251,  251,  251,  251,  251,  251,  251,  251,  251,  251,
-      251,  251,  251,  251,  251,  251,  251,  251
-    },
-
-    {
-       67,  252,  252,  252,  252,  252,  252,  252,  252,  252,
-     -144,  252,  252,  252,  252,  252,  252,  252,  252,  252,
-      252,  252,  252,  252,  252,  252,  252,  252,  252,  252,
-      252,  252,  252,  252,  252,  252,  252,  252,  252,  252,
-      252,  252,  252,  252,  252,  252,  252,  252,  252,  252,
-      252,  252,  252,  252,  252,  252,  252,  252,  252,  252,
-      252,  252,  252,  252,  252,  252,  252,  252,  252,  252,
-      252,  252,  252,  252,  252,  252,  252,  252,  252,  252,
-
-      252,  252,  252,  252,  252,  252,  252,  252,  252,  252,
-      252,  252,  252,  252,  252,  252,  252,  252,  252,  252,
-      252,  252,  252,  252,  252,  252,  252,  252,  252,  252,
-      252,  252,  252,  252,  252,  252,  252,  252,  252,  252,
-      252,  252,  252,  252,  252,  252,  252,  252
-    },
-
-    {
-       67,  253,  253,  253,  253,  253,  253,  253,  253,  253,
-     -145,  253,  253,  253,  253,  253,  253,  253,  253,  253,
-      253,  253,  253,  253,  253,  253,  253,  253,  253,  253,
-      253,  253,  253,  253,  253,  253,  253,  253,  253,  253,
-      253,  253,  253,  253,  253,  253,  253,  253,  253,  253,
-
-      253,  253,  253,  253,  253,  253,  253,  253,  253,  253,
-      253,  253,  253,  253,  253,  253,  253,  253,  253,  253,
-      253,  253,  253,  253,  253,  253,  253,  253,  253,  253,
-      253,  253,  253,  253,  253,  253,  253,  253,  253,  253,
-      253,  253,  253,  253,  253,  253,  253,  253,  253,  253,
-      253,  253,  253,  253,  253,  253,  253,  253,  253,  253,
-      253,  253,  253,  253,  253,  253,  253,  253,  253,  253,
-      253,  253,  253,  253,  253,  253,  253,  253
-    },
-
-    {
-       67,  254,  254,  254,  254,  254,  254,  254,  254,  254,
-      255,  254,  254,  254,  254,  254,  254,  254,  254,  254,
-
-      254,  254,  254,  254,  254,  254,  254,  254,  254,  254,
-      254,  254,  254,  254,  254,  254,  254,  254,  254,  254,
-      254,  254,  254,  254,  254,  254,  254,  254,  254,  254,
-      254,  254,  254,  254,  254,  254,  254,  254,  254,  254,
-      254,  254,  254,  254,  254,  254,  254,  254,  254,  254,
-      254,  254,  254,  254,  254,  254,  254,  254,  254,  254,
-      254,  254,  254,  254,  254,  254,  254,  254,  254,  254,
-      254,  254,  254,  254,  254,  254,  254,  254,  254,  254,
-      254,  254,  254,  254,  254,  254,  254,  254,  254,  254,
-      254,  254,  254,  254,  254,  254,  254,  254,  254,  254,
-
-      254,  254,  254,  254,  254,  254,  254,  254
-    },
-
-    {
-       67, -147, -147, -147, -147, -147, -147, -147, -147, -147,
-     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
-     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
-     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
-     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
-     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
-     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
-     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
-     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
-
-     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
-     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
-     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
-     -147, -147, -147, -147, -147, -147, -147, -147
-    },
-
-    {
-       67, -148, -148, -148, -148, -148, -148, -148, -148, -148,
-     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
-     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
-     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
-     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
-     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
-
-     -148, -148, -148, -148, -148, -148, -148,  256, -148, -148,
-     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
-      257, -148, -148, -148, -148, -148, -148, -148, -148, -148,
-     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
-     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
-     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
-     -148, -148, -148, -148, -148, -148, -148, -148
-    },
-
-    {
-       67, -149, -149, -149, -149, -149, -149, -149, -149, -149,
-     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
-     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
-
-     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
-     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
-     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
-     -149, -149, -149, -149, -149, -149, -149, -149,  258, -149,
-     -149, -149, -149, -149, -149, -149, -149, -149,  259, -149,
-     -149, -149,  260,  261,  262,  263, -149, -149, -149, -149,
-     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
-     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
-     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
-     -149, -149, -149, -149, -149, -149, -149, -149
-
-    },
-
-    {
-       67, -150, -150, -150, -150, -150, -150, -150, -150, -150,
-     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
-     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
-     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
-     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
-     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
-     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
-     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
-     -150, -150, -150,  264, -150, -150,  265, -150, -150, -150,
-     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
-
-     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
-     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
-     -150, -150, -150, -150, -150, -150, -150, -150
-    },
-
-    {
-       67, -151, -151, -151, -151, -151, -151, -151, -151, -151,
-     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
-     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
-     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
-     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
-     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
-     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
-
-     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
-     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
-     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
-     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
-     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
-     -151, -151, -151, -151, -151, -151, -151, -151
-    },
-
-    {
-       67, -152, -152, -152, -152, -152, -152, -152, -152, -152,
-     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
-     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
-     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
-
-     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
-     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
-     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
-     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
-     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
-     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
-     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
-     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
-     -152, -152, -152, -152, -152, -152, -152, -152
-    },
-
-    {
-       67, -153, -153, -153, -153, -153, -153, -153, -153, -153,
-
-     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
-     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
-     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
-     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
-     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
-     -153, -153, -153, -153, -153, -153, -153, -153, -153,  266,
-     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
-     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
-     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
-     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
-
-     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
-     -153, -153, -153, -153, -153, -153, -153, -153
-    },
-
-    {
-       67, -154, -154, -154, -154, -154, -154, -154, -154, -154,
-     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
-     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
-     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
-     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
-     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
-     -154, -154, -154, -154, -154,  267, -154, -154, -154, -154,
-     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
-
-     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
-     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
-     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
-     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
-     -154, -154, -154, -154, -154, -154, -154, -154
-    },
-
-    {
-       67, -155, -155, -155, -155, -155, -155, -155, -155, -155,
-     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
-     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
-     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
-     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
-
-     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
-     -155, -155, -155, -155, -155, -155, -155, -155,  268, -155,
-     -155, -155, -155, -155, -155, -155, -155, -155, -155,  269,
-      270, -155, -155, -155, -155, -155,  271, -155, -155, -155,
-     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
-     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
-     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
-     -155, -155, -155, -155, -155, -155, -155, -155
-    },
-
-    {
-       67, -156, -156, -156, -156, -156, -156, -156, -156, -156,
-     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
-
-     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
-     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
-     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
-     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
-     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
-     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
-     -156, -156, -156, -156, -156, -156, -156, -156, -156,  272,
-     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
-     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
-     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
-
-     -156, -156, -156, -156, -156, -156, -156, -156
-    },
-
-    {
-       67, -157, -157, -157, -157, -157, -157, -157, -157, -157,
-     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
-     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
-     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
-     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
-     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
-     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
-     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
-     -157, -157, -157, -157, -157, -157, -157, -157, -157,  273,
-
-     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
-     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
-     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
-     -157, -157, -157, -157, -157, -157, -157, -157
-    },
-
-    {
-       67, -158, -158, -158, -158, -158, -158, -158, -158, -158,
-     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
-     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
-     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
-     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
-     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
-
-     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
-     -158, -158, -158, -158, -158, -158, -158, -158,  274, -158,
-     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
-     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
-     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
-     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
-     -158, -158, -158, -158, -158, -158, -158, -158
-    },
-
-    {
-       67, -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, -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,  275, -159,  276, -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
-
-    },
-
-    {
-       67, -160, -160, -160, -160, -160, -160, -160, -160, -160,
-     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
-     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
-     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
-     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
-     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
-     -160, -160, -160, -160, -160, -160,  277, -160, -160, -160,
-     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
-     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
-     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
-
-     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
-     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
-     -160, -160, -160, -160, -160, -160, -160, -160
-    },
-
-    {
-       67, -161, -161, -161, -161, -161, -161, -161, -161, -161,
-     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
-     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
-     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
-     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
-     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
-     -161, -161, -161, -161, -161, -161, -161, -161,  278, -161,
-
-     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
-     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
-     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
-     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
-     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
-     -161, -161, -161, -161, -161, -161, -161, -161
-    },
-
-    {
-       67, -162, -162, -162, -162, -162, -162, -162, -162, -162,
-     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
-     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
-     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
-
-     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
-     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
-     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
-     -162, -162, -162, -162, -162, -162, -162, -162, -162,  279,
-     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
-     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
-     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
-     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
-     -162, -162, -162, -162, -162, -162, -162, -162
-    },
-
-    {
-       67, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-
-     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-     -163, -163, -163, -163, -163,  280, -163, -163, -163, -163,
-     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-
-     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-     -163, -163, -163, -163, -163, -163, -163, -163
-    },
-
-    {
-       67, -164, -164, -164, -164, -164, -164, -164, -164, -164,
-     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
-     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
-     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
-     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
-     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
-     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
-     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
-
-     -164, -164, -164, -164,  281, -164, -164, -164, -164, -164,
-     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
-     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
-     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
-     -164, -164, -164, -164, -164, -164, -164, -164
-    },
-
-    {
-       67, -165, -165, -165, -165, -165, -165, -165, -165, -165,
-     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
-     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
-     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
-     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
-
-     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
-     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
-     -165, -165, -165, -165, -165, -165, -165, -165,  282, -165,
-     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
-     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
-     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
-     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
-     -165, -165, -165, -165, -165, -165, -165, -165
-    },
-
-    {
-       67, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-
-     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-     -166, -166, -166, -166, -166, -166, -166, -166,  283, -166,
-     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-
-     -166, -166, -166, -166, -166, -166, -166, -166
-    },
-
-    {
-       67, -167, -167, -167, -167, -167, -167, -167, -167, -167,
-     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
-     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
-     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
-     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
-     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
-     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
-     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
-     -167, -167, -167,  284, -167, -167, -167, -167, -167, -167,
-
-     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
-     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
-     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
-     -167, -167, -167, -167, -167, -167, -167, -167
-    },
-
-    {
-       67, -168, -168, -168, -168, -168, -168, -168, -168, -168,
-     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
-     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
-     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
-     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
-     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
-
-     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
-     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
-     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
-     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
-     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
-     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
-     -168, -168, -168, -168, -168, -168, -168, -168
-    },
-
-    {
-       67, -169, -169, -169, -169, -169, -169, -169, -169, -169,
-     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
-     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
-
-     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
-     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
-     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
-     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
-     -169, -169, -169, -169, -169, -169, -169, -169, -169,  285,
-     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
-     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
-     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
-     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
-     -169, -169, -169, -169, -169, -169, -169, -169
-
-    },
-
-    {
-       67, -170, -170, -170, -170, -170, -170, -170, -170, -170,
-     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
-     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
-     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
-     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
-     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
-     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
-     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
-     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
-     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
-
-     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
-     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
-     -170, -170, -170, -170, -170, -170, -170, -170
-    },
-
-    {
-       67, -171, -171, -171, -171, -171, -171, -171, -171, -171,
-     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
-     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
-     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
-     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
-     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
-     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
-
-     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
-     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
-     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
-     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
-     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
-     -171, -171, -171, -171, -171, -171, -171, -171
-    },
-
-    {
-       67, -172, -172, -172, -172, -172, -172, -172, -172, -172,
-     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
-     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
-     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
-
-     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
-     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
-     -172, -172, -172, -172, -172, -172, -172, -172,  286, -172,
-     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
-     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
-     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
-     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
-     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
-     -172, -172, -172, -172, -172, -172, -172, -172
-    },
-
-    {
-       67, -173, -173, -173, -173, -173, -173, -173, -173, -173,
-
-     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
-     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
-     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
-     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
-     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
-     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
-     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
-     -173, -173, -173,  287, -173, -173, -173, -173, -173, -173,
-     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
-     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
-
-     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
-     -173, -173, -173, -173, -173, -173, -173, -173
-    },
-
-    {
-       67, -174, -174, -174, -174, -174, -174, -174, -174, -174,
-     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
-     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
-     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
-     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
-     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
-     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
-     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
-
-     -174, -174,  288, -174, -174, -174, -174, -174, -174, -174,
-     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
-     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
-     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
-     -174, -174, -174, -174, -174, -174, -174, -174
-    },
-
-    {
-       67, -175, -175, -175, -175, -175, -175, -175, -175, -175,
-     -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
-     -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
-     -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
-     -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
-
-     -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
-     -175, -175, -175, -175, -175,  289, -175, -175, -175, -175,
-     -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
-     -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
-     -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
-     -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
-     -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
-     -175, -175, -175, -175, -175, -175, -175, -175
-    },
-
-    {
-       67, -176, -176, -176, -176, -176, -176, -176, -176, -176,
-     -176, -176, -176, -176, -176, -176, -176, -176, -176, -176,
-
-     -176, -176, -176, -176, -176, -176, -176, -176, -176, -176,
-     -176, -176, -176, -176, -176, -176, -176, -176, -176, -176,
-     -176, -176, -176, -176, -176, -176, -176, -176, -176, -176,
-     -176, -176, -176, -176, -176, -176, -176, -176, -176, -176,
-     -176, -176, -176, -176, -176, -176,  290, -176, -176, -176,
-     -176, -176, -176, -176, -176, -176, -176, -176, -176, -176,
-     -176, -176, -176, -176, -176, -176, -176, -176, -176, -176,
-     -176, -176, -176, -176, -176, -176, -176, -176, -176, -176,
-     -176, -176, -176, -176, -176, -176, -176, -176, -176, -176,
-     -176, -176, -176, -176, -176, -176, -176, -176, -176, -176,
-
-     -176, -176, -176, -176, -176, -176, -176, -176
-    },
-
-    {
-       67, -177, -177, -177, -177, -177, -177, -177, -177, -177,
-     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
-     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
-     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
-     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
-     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
-     -177, -177, -177, -177, -177, -177, -177, -177, -177,  291,
-     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
-     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
-
-     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
-     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
-     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
-     -177, -177, -177, -177, -177, -177, -177, -177
-    },
-
-    {
-       67, -178, -178, -178, -178, -178, -178, -178, -178, -178,
-     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
-     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
-     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
-     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
-     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
-
-     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
-     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
-     -178, -178,  292, -178, -178, -178, -178, -178, -178,  293,
-     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
-     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
-     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
-     -178, -178, -178, -178, -178, -178, -178, -178
-    },
-
-    {
-       67, -179, -179, -179, -179, -179, -179, -179, -179, -179,
-     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
-     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
-
-     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
-     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
-     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
-     -179, -179, -179, -179, -179, -179, -179, -179,  294, -179,
-     -179, -179, -179, -179, -179, -179, -179, -179,  295, -179,
-     -179, -179,  296,  297,  298,  299, -179, -179, -179, -179,
-     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
-     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
-     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
-     -179, -179, -179, -179, -179, -179, -179, -179
-
-    },
-
-    {
-       67, -180, -180, -180, -180, -180, -180, -180, -180, -180,
-     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
-     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
-     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
-     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
-     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
-     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
-     -180, -180, -180,  300, -180, -180, -180, -180, -180, -180,
-     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
-     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
-
-     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
-     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
-     -180, -180, -180, -180, -180, -180, -180, -180
-    },
-
-    {
-       67, -181, -181, -181, -181, -181, -181, -181, -181, -181,
-     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
-     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
-     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
-     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
-     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
-     -181, -181, -181, -181, -181, -181, -181,  301, -181, -181,
-
-     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
-     -181, -181, -181,  302, -181, -181,  303, -181, -181, -181,
-     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
-     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
-     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
-     -181, -181, -181, -181, -181, -181, -181, -181
-    },
-
-    {
-       67, -182, -182, -182, -182, -182, -182, -182, -182, -182,
-     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
-     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
-     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
-
-     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
-     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
-     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
-     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
-     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
-     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
-     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
-     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
-     -182, -182, -182, -182, -182, -182, -182, -182
-    },
-
-    {
-       67, -183, -183, -183, -183, -183, -183, -183, -183, -183,
-
-     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
-     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
-     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
-     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
-     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
-     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
-     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
-     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
-     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
-     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
-
-     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
-     -183, -183, -183, -183, -183, -183, -183, -183
-    },
-
-    {
-       67, -184, -184, -184, -184, -184, -184, -184, -184, -184,
-     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
-     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
-     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
-     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
-     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
-     -184, -184, -184, -184, -184, -184, -184,  304, -184, -184,
-     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
-
-     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
-     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
-     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
-     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
-     -184, -184, -184, -184, -184, -184, -184, -184
-    },
-
-    {
-       67, -185, -185, -185, -185, -185, -185, -185, -185, -185,
-     -185, -185, -185, -185, -185, -185, -185, -185, -185, -185,
-     -185, -185, -185, -185, -185, -185, -185, -185, -185, -185,
-     -185, -185, -185, -185, -185, -185, -185, -185, -185, -185,
-     -185, -185, -185, -185, -185, -185, -185, -185, -185, -185,
-
-     -185, -185, -185, -185, -185, -185, -185, -185, -185, -185,
-     -185, -185, -185, -185, -185, -185, -185, -185, -185, -185,
-     -185, -185, -185, -185, -185, -185, -185, -185,  305, -185,
-     -185, -185, -185, -185, -185, -185, -185, -185, -185, -185,
-     -185, -185, -185, -185, -185, -185, -185, -185, -185, -185,
-     -185, -185, -185, -185, -185, -185, -185, -185, -185, -185,
-     -185, -185, -185, -185, -185, -185, -185, -185, -185, -185,
-     -185, -185, -185, -185, -185, -185, -185, -185
-    },
-
-    {
-       67, -186, -186, -186, -186, -186, -186, -186, -186, -186,
-     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
-
-     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
-     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
-     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
-     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
-     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
-     -186, -186, -186, -186, -186, -186,  306, -186, -186, -186,
-     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
-     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
-     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
-     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
-
-     -186, -186, -186, -186, -186, -186, -186, -186
-    },
-
-    {
-       67, -187, -187, -187, -187, -187, -187, -187, -187, -187,
-     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
-     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
-     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
-     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
-     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
-     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
-     -187, -187, -187, -187, -187, -187, -187, -187, -187,  307,
-     -187, -187, -187, -187, -187, -187, -187, -187, -187,  308,
-
-     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
-     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
-     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
-     -187, -187, -187, -187, -187, -187, -187, -187
-    },
-
-    {
-       67, -188, -188, -188, -188, -188, -188, -188, -188, -188,
-     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
-     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
-     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
-     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
-     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
-
-     -188, -188, -188, -188, -188,  309, -188, -188, -188, -188,
-     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
-     -188, -188, -188,  310, -188, -188, -188, -188, -188, -188,
-     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
-     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
-     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
-     -188, -188, -188, -188, -188, -188, -188, -188
-    },
-
-    {
-       67, -189, -189, -189, -189, -189, -189, -189, -189, -189,
-     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
-     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
-
-     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
-     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
-     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
-     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
-     -189, -189, -189, -189, -189, -189, -189, -189, -189,  311,
-     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
-     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
-     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
-     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
-     -189, -189, -189, -189, -189, -189, -189, -189
-
-    },
-
-    {
-       67, -190, -190, -190, -190, -190, -190, -190, -190, -190,
-     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
-     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
-     -190, -190,  312, -190, -190, -190, -190, -190, -190, -190,
-     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
-     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
-     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
-     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
-     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
-     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
-
-     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
-     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
-     -190, -190, -190, -190, -190, -190, -190, -190
-    },
-
-    {
-       67, -191, -191, -191, -191, -191, -191, -191, -191, -191,
-     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
-     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
-     -191, -191,  313, -191, -191, -191, -191, -191, -191, -191,
-     -191, -191, -191, -191, -191, -191, -191, -191,  314,  314,
-      314,  314,  314,  314,  314,  314,  314,  314, -191, -191,
-     -191, -191, -191, -191, -191,  313,  313,  313,  313,  313,
-
-      313,  313,  313,  313,  313,  313,  313,  313,  313,  313,
-      313,  313,  313,  313,  313,  313,  313,  313,  313,  313,
-      313, -191, -191, -191, -191, -191, -191, -191, -191, -191,
-     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
-     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
-     -191, -191, -191, -191, -191, -191, -191, -191
-    },
-
-    {
-       67, -192, -192, -192, -192, -192, -192, -192, -192, -192,
-     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
-     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
-     -192, -192,  315, -192, -192, -192, -192, -192, -192, -192,
-
-     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
-     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
-     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
-     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
-     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
-     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
-     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
-     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
-     -192, -192, -192, -192, -192, -192, -192, -192
-    },
-
-    {
-       67, -193, -193, -193, -193, -193, -193, -193, -193, -193,
-
-     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
-     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
-     -193, -193,  316, -193, -193, -193, -193, -193, -193, -193,
-     -193, -193, -193, -193, -193, -193, -193, -193,  317,  317,
-      317,  317,  317,  317,  317,  317,  317,  317, -193, -193,
-     -193, -193, -193, -193, -193,  316,  316,  316,  316,  316,
-      316,  316,  316,  316,  316,  316,  316,  316,  316,  316,
-      316,  316,  316,  316,  316,  316,  316,  316,  316,  316,
-      316, -193, -193, -193, -193, -193, -193, -193, -193, -193,
-     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
-
-     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
-     -193, -193, -193, -193, -193, -193, -193, -193
-    },
-
-    {
-       67, -194, -194, -194, -194, -194, -194, -194, -194, -194,
-     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
-     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
-     -194, -194,  318, -194, -194, -194, -194, -194, -194, -194,
-     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
-     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
-     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
-     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
-
-     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
-     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
-     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
-     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
-     -194, -194, -194, -194, -194, -194, -194, -194
-    },
-
-    {
-       67, -195, -195, -195, -195, -195, -195, -195, -195, -195,
-     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
-     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
-     -195, -195,  319, -195, -195, -195, -195, -195, -195, -195,
-     -195, -195, -195, -195, -195, -195, -195, -195,  320,  320,
-
-      320,  320,  320,  320,  320,  320,  320,  320, -195, -195,
-     -195, -195, -195, -195, -195,  321,  321,  321,  321,  321,
-      321,  321,  321,  321,  321,  321,  321,  321,  321,  321,
-      321,  321,  321,  321,  321,  321,  321,  321,  321,  321,
-      321, -195, -195, -195, -195, -195, -195, -195, -195, -195,
-     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
-     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
-     -195, -195, -195, -195, -195, -195, -195, -195
-    },
-
-    {
-       67, -196, -196, -196, -196, -196, -196, -196, -196, -196,
-     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
-
-     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
-     -196, -196,  322, -196, -196, -196, -196, -196, -196, -196,
-     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
-     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
-     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
-     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
-     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
-     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
-     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
-     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
-
-     -196, -196, -196, -196, -196, -196, -196, -196
-    },
-
-    {
-       67, -197, -197, -197, -197, -197, -197, -197, -197, -197,
-     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
-     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
-     -197, -197,  323, -197, -197, -197, -197, -197, -197, -197,
-     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
-     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
-     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
-     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
-     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
-
-     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
-     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
-     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
-     -197, -197, -197, -197, -197, -197, -197, -197
-    },
-
-    {
-       67, -198, -198, -198, -198, -198, -198, -198, -198, -198,
-     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
-     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
-     -198, -198,  324, -198, -198, -198, -198, -198, -198, -198,
-     -198, -198, -198, -198, -198, -198, -198, -198,  325,  325,
-      325,  325,  325,  325,  325,  325,  325,  325, -198, -198,
-
-     -198, -198, -198, -198, -198,  324,  324,  324,  324,  324,
-      324,  324,  324,  324,  324,  324,  324,  324,  324,  324,
-      324,  324,  324,  324,  324,  324,  324,  324,  324,  324,
-      324, -198, -198, -198, -198, -198, -198, -198, -198, -198,
-     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
-     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
-     -198, -198, -198, -198, -198, -198, -198, -198
-    },
-
-    {
-       67, -199, -199, -199, -199, -199, -199, -199, -199, -199,
-     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
-     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
-
-     -199, -199,  326, -199, -199, -199, -199, -199, -199, -199,
-     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
-     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
-     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
-     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
-     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
-     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
-     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
-     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
-     -199, -199, -199, -199, -199, -199, -199, -199
-
-    },
-
-    {
-       67, -200, -200, -200, -200, -200, -200, -200, -200, -200,
-     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
-     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
-     -200, -200,  327, -200, -200, -200, -200, -200, -200, -200,
-     -200, -200, -200, -200, -200, -200, -200, -200,  328,  328,
-      328,  328,  328,  328,  328,  328,  328,  328, -200, -200,
-     -200, -200, -200, -200, -200,  329,  329,  329,  329,  329,
-      329,  329,  329,  329,  329,  329,  329,  329,  329,  329,
-      329,  329,  329,  329,  329,  329,  329,  329,  329,  329,
-      329, -200, -200, -200, -200, -200, -200, -200, -200, -200,
-
-     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
-     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
-     -200, -200, -200, -200, -200, -200, -200, -200
-    },
-
-    {
-       67, -201, -201, -201, -201, -201, -201, -201, -201, -201,
-     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
-     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
-     -201, -201,  330, -201, -201, -201, -201, -201, -201, -201,
-     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
-     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
-     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
-
-     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
-     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
-     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
-     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
-     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
-     -201, -201, -201, -201, -201, -201, -201, -201
-    },
-
-    {
-       67, -202, -202, -202, -202, -202, -202, -202, -202, -202,
-     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
-     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
-     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
-
-     -202, -202, -202, -202, -202, -202, -202, -202,  331,  331,
-      331,  331,  331,  331,  331,  331,  331,  331, -202, -202,
-     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
-     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
-     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
-     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
-     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
-     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
-     -202, -202, -202, -202, -202, -202, -202, -202
-    },
-
-    {
-       67, -203, -203, -203, -203, -203, -203, -203, -203, -203,
-
-     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
-     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
-     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
-     -203, -203, -203, -203, -203, -203, -203, -203,  332,  332,
-      332,  332,  332,  332,  332,  332,  332,  332, -203, -203,
-     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
-     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
-     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
-     -203, -203, -203, -203, -203,  333, -203, -203, -203, -203,
-     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
-
-     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
-     -203, -203, -203, -203, -203, -203, -203, -203
-    },
-
-    {
-       67, -204, -204, -204, -204, -204, -204, -204, -204, -204,
-     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
-     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
-     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
-     -204, -204, -204, -204, -204, -204, -204, -204, -204,  334,
-      334,  334,  334,  334,  334,  334,  334,  334, -204, -204,
-     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
-     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
-
-     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
-     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
-     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
-     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
-     -204, -204, -204, -204, -204, -204, -204, -204
-    },
-
-    {
-       67, -205, -205, -205, -205, -205, -205, -205, -205, -205,
-     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
-     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
-     -205, -205,  335, -205, -205, -205, -205, -205, -205, -205,
-     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
-
-     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
-     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
-     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
-     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
-     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
-     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
-     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
-     -205, -205, -205, -205, -205, -205, -205, -205
-    },
-
-    {
-       67, -206, -206, -206, -206, -206, -206, -206, -206, -206,
-     -206, -206, -206, -206, -206, -206, -206, -206, -206, -206,
-
-     -206, -206, -206, -206, -206, -206, -206, -206, -206, -206,
-     -206, -206,  336, -206, -206, -206, -206, -206, -206, -206,
-     -206, -206, -206, -206, -206, -206, -206, -206,  337,  337,
-      337,  337,  337,  337,  337,  337,  337,  337, -206, -206,
-     -206, -206, -206, -206, -206,  336,  336,  336,  336,  336,
-      336,  336,  336,  336,  336,  336,  336,  336,  336,  336,
-      336,  336,  336,  336,  336,  336,  336,  336,  336,  336,
-      336, -206, -206, -206, -206, -206, -206, -206, -206, -206,
-     -206, -206, -206, -206, -206, -206, -206, -206, -206, -206,
-     -206, -206, -206, -206, -206, -206, -206, -206, -206, -206,
-
-     -206, -206, -206, -206, -206, -206, -206, -206
-    },
-
-    {
-       67, -207, -207, -207, -207, -207, -207, -207, -207, -207,
-     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
-     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
-     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
-     -207, -207, -207, -207, -207, -207, -207, -207,  338,  338,
-      338,  338,  338,  338,  338,  338,  338,  338, -207, -207,
-     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
-     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
-     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
-
-     -207, -207, -207, -207, -207,  339, -207, -207, -207, -207,
-     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
-     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
-     -207, -207, -207, -207, -207, -207, -207, -207
-    },
-
-    {
-       67, -208, -208, -208, -208, -208, -208, -208, -208, -208,
-     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
-     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
-     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
-     -208, -208, -208, -208, -208, -208, -208, -208, -208,  340,
-      340,  340,  340,  340,  340,  340,  340,  340, -208, -208,
-
-     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
-     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
-     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
-     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
-     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
-     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
-     -208, -208, -208, -208, -208, -208, -208, -208
-    },
-
-    {
-       67, -209, -209, -209, -209, -209, -209, -209, -209, -209,
-     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
-     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
-
-     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
-     -209, -209, -209, -209, -209, -209, -209, -209,  341,  341,
-      341,  341,  341,  341,  341,  341,  341,  341, -209, -209,
-     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
-     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
-     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
-     -209, -209, -209, -209, -209,  342, -209, -209, -209, -209,
-     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
-     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
-     -209, -209, -209, -209, -209, -209, -209, -209
-
-    },
-
-    {
-       67, -210, -210, -210, -210, -210, -210, -210, -210, -210,
-     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
-     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
-     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
-     -210, -210, -210, -210, -210, -210, -210, -210, -210,  343,
-      343,  343,  343,  343,  343,  343,  343,  343, -210, -210,
-     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
-     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
-     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
-     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
-
-     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
-     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
-     -210, -210, -210, -210, -210, -210, -210, -210
-    },
-
-    {
-       67, -211, -211, -211, -211, -211, -211, -211, -211, -211,
-     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
-     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
-     -211, -211,  344, -211, -211, -211, -211, -211, -211, -211,
-     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
-     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
-     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
-
-     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
-     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
-     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
-     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
-     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
-     -211, -211, -211, -211, -211, -211, -211, -211
-    },
-
-    {
-       67, -212, -212, -212, -212, -212, -212, -212, -212, -212,
-     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
-     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
-     -212, -212,  345, -212, -212, -212, -212, -212, -212, -212,
-
-     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
-     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
-     -212, -212, -212, -212, -212,  346,  346,  346,  346,  346,
-      346,  346,  346,  346,  346,  346,  346,  346,  346,  346,
-      346,  346,  346,  346,  346,  346,  346,  346,  346,  346,
-      346, -212, -212, -212, -212, -212, -212, -212, -212, -212,
-     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
-     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
-     -212, -212, -212, -212, -212, -212, -212, -212
-    },
-
-    {
-       67, -213, -213, -213, -213, -213, -213, -213, -213, -213,
-
-     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
-     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
-     -213, -213,  347, -213, -213, -213, -213, -213, -213, -213,
-     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
-     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
-     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
-     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
-     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
-     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
-     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
-
-     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
-     -213, -213, -213, -213, -213, -213, -213, -213
-    },
-
-    {
-       67, -214, -214, -214, -214, -214, -214, -214, -214, -214,
-     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
-     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
-     -214, -214,  348, -214, -214, -214, -214, -214, -214, -214,
-     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
-     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
-     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
-     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
-
-     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
-     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
-     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
-     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
-     -214, -214, -214, -214, -214, -214, -214, -214
-    },
-
-    {
-       67, -215, -215, -215, -215, -215, -215, -215, -215, -215,
-     -215, -215, -215, -215, -215, -215, -215, -215, -215, -215,
-     -215, -215, -215, -215, -215, -215, -215, -215, -215, -215,
-     -215, -215,  349, -215, -215, -215, -215, -215, -215, -215,
-     -215, -215, -215, -215, -215, -215, -215, -215,  350,  350,
-
-      350,  350,  350,  350,  350,  350,  350,  350, -215, -215,
-     -215, -215, -215, -215, -215,  351,  351,  351,  351,  351,
-      351,  351,  351,  351,  351,  351,  351,  351,  351,  351,
-      351,  351,  351,  351,  351,  351,  351,  351,  351,  351,
-      351, -215, -215, -215, -215, -215, -215, -215, -215, -215,
-     -215, -215, -215, -215, -215, -215, -215, -215, -215, -215,
-     -215, -215, -215, -215, -215, -215, -215, -215, -215, -215,
-     -215, -215, -215, -215, -215, -215, -215, -215
-    },
-
-    {
-       67, -216, -216, -216, -216, -216, -216, -216, -216, -216,
-     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
-
-     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
-     -216, -216,  352, -216, -216, -216, -216, -216, -216, -216,
-     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
-     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
-     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
-     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
-     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
-     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
-     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
-     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
-
-     -216, -216, -216, -216, -216, -216, -216, -216
-    },
-
-    {
-       67, -217, -217, -217, -217, -217, -217, -217, -217, -217,
-     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
-     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
-     -217, -217,  353, -217, -217, -217, -217, -217, -217, -217,
-     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
-     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
-     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
-     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
-     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
-
-     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
-     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
-     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
-     -217, -217, -217, -217, -217, -217, -217, -217
-    },
-
-    {
-       67, -218, -218, -218, -218, -218, -218, -218, -218, -218,
-     -218, -218, -218, -218, -218, -218, -218, -218, -218, -218,
-     -218, -218, -218, -218, -218, -218, -218, -218, -218, -218,
-     -218, -218,  354, -218, -218, -218, -218, -218, -218, -218,
-     -218, -218, -218, -218, -218, -218, -218, -218,  355,  355,
-      355,  355,  355,  355,  355,  355,  355,  355, -218, -218,
-
-     -218, -218, -218, -218, -218,  356,  356,  356,  356,  356,
-      356,  356,  356,  356,  356,  356,  356,  356,  356,  356,
-      356,  356,  356,  356,  356,  356,  356,  356,  356,  356,
-      356, -218, -218, -218, -218, -218, -218, -218, -218, -218,
-     -218, -218, -218, -218, -218, -218, -218, -218, -218, -218,
-     -218, -218, -218, -218, -218, -218, -218, -218, -218, -218,
-     -218, -218, -218, -218, -218, -218, -218, -218
-    },
-
-    {
-       67, -219, -219, -219, -219, -219, -219, -219, -219, -219,
-     -219, -219, -219, -219, -219, -219, -219, -219, -219, -219,
-     -219, -219, -219, -219, -219, -219, -219, -219, -219, -219,
-
-     -219, -219,  357, -219, -219, -219, -219, -219, -219, -219,
-     -219, -219, -219, -219, -219, -219, -219, -219, -219, -219,
-     -219, -219, -219, -219, -219, -219, -219, -219, -219, -219,
-     -219, -219, -219, -219, -219, -219, -219, -219, -219, -219,
-     -219, -219, -219, -219, -219, -219, -219, -219, -219, -219,
-     -219, -219, -219, -219, -219, -219, -219, -219, -219, -219,
-     -219, -219, -219, -219, -219, -219, -219, -219, -219, -219,
-     -219, -219, -219, -219, -219, -219, -219, -219, -219, -219,
-     -219, -219, -219, -219, -219, -219, -219, -219, -219, -219,
-     -219, -219, -219, -219, -219, -219, -219, -219
-
-    },
-
-    {
-       67, -220, -220, -220, -220, -220, -220, -220, -220, -220,
-     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
-     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
-     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
-     -220, -220, -220, -220, -220, -220, -220, -220,  358,  358,
-      358,  358,  358,  358,  358,  358,  358,  358, -220, -220,
-     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
-     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
-     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
-     -220, -220, -220, -220, -220,  359, -220, -220, -220, -220,
-
-     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
-     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
-     -220, -220, -220, -220, -220, -220, -220, -220
-    },
-
-    {
-       67, -221, -221, -221, -221, -221, -221, -221, -221, -221,
-     -221, -221, -221, -221, -221, -221, -221, -221, -221, -221,
-     -221, -221, -221, -221, -221, -221, -221, -221, -221, -221,
-     -221, -221, -221, -221, -221, -221, -221, -221, -221, -221,
-     -221, -221, -221, -221, -221, -221, -221, -221,  360,  361,
-      361,  361,  361,  361,  361,  361,  361,  361, -221, -221,
-     -221, -221, -221, -221, -221, -221, -221, -221, -221, -221,
-
-     -221, -221, -221, -221, -221, -221, -221, -221, -221, -221,
-     -221, -221, -221, -221, -221, -221, -221, -221, -221, -221,
-     -221, -221, -221, -221, -221, -221, -221, -221, -221, -221,
-     -221, -221, -221, -221, -221, -221, -221, -221, -221, -221,
-     -221, -221, -221, -221, -221, -221, -221, -221, -221, -221,
-     -221, -221, -221, -221, -221, -221, -221, -221
-    },
-
-    {
-       67, -222, -222, -222, -222, -222, -222, -222, -222, -222,
-     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
-     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
-     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
-
-     -222, -222, -222, -222, -222, -222, -222, -222,  362,  362,
-      362,  362,  362,  362,  362,  362,  362,  362, -222, -222,
-     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
-     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
-     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
-     -222, -222, -222, -222, -222,  363, -222, -222, -222, -222,
-     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
-     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
-     -222, -222, -222, -222, -222, -222, -222, -222
-    },
-
-    {
-       67, -223, -223, -223, -223, -223, -223, -223, -223, -223,
-
-     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
-     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
-     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
-     -223, -223, -223, -223, -223, -223, -223, -223,  364,  365,
-      365,  365,  365,  365,  365,  365,  365,  365, -223, -223,
-     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
-     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
-     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
-     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
-     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
-
-     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
-     -223, -223, -223, -223, -223, -223, -223, -223
-    },
-
-    {
-       67, -224, -224, -224, -224, -224, -224, -224, -224, -224,
-     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
-     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
-     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
-     -224, -224, -224, -224, -224, -224, -224, -224,  366,  366,
-      366,  366,  366,  366,  366,  366,  366,  366, -224, -224,
-     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
-     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
-
-     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
-     -224, -224, -224, -224, -224,  367, -224, -224, -224, -224,
-     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
-     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
-     -224, -224, -224, -224, -224, -224, -224, -224
-    },
-
-    {
-       67, -225, -225, -225, -225, -225, -225, -225, -225, -225,
-     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
-     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
-     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
-     -225, -225, -225, -225, -225, -225, -225, -225,  368,  369,
-
-      369,  369,  369,  369,  369,  369,  369,  369, -225, -225,
-     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
-     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
-     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
-     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
-     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
-     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
-     -225, -225, -225, -225, -225, -225, -225, -225
-    },
-
-    {
-       67, -226, -226, -226, -226, -226, -226, -226, -226, -226,
-     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
-
-     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
-     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
-     -226, -226, -226, -226, -226, -226, -226, -226,  370,  370,
-      370,  370,  370,  370,  370,  370,  370,  370, -226, -226,
-     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
-     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
-     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
-     -226, -226, -226, -226, -226,  371, -226, -226, -226, -226,
-     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
-     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
-
-     -226, -226, -226, -226, -226, -226, -226, -226
-    },
-
-    {
-       67, -227, -227, -227, -227, -227, -227, -227, -227, -227,
-     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
-     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
-     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
-     -227, -227, -227, -227, -227, -227, -227, -227,  372,  373,
-      373,  373,  373,  373,  373,  373,  373,  373, -227, -227,
-     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
-     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
-     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
-
-     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
-     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
-     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
-     -227, -227, -227, -227, -227, -227, -227, -227
-    },
-
-    {
-       67, -228, -228, -228, -228, -228, -228, -228, -228, -228,
-     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
-     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
-     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
-     -228, -228, -228, -228, -228, -228, -228, -228,  374,  374,
-      374,  374,  374,  374,  374,  374,  374,  374, -228, -228,
-
-     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
-     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
-     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
-     -228, -228, -228, -228, -228,  375, -228, -228, -228, -228,
-     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
-     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
-     -228, -228, -228, -228, -228, -228, -228, -228
-    },
-
-    {
-       67, -229, -229, -229, -229, -229, -229, -229, -229, -229,
-     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
-     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
-
-     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
-     -229, -229, -229, -229, -229, -229, -229, -229,  376,  377,
-      377,  377,  377,  377,  377,  377,  377,  377, -229, -229,
-     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
-     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
-     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
-     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
-     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
-     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
-     -229, -229, -229, -229, -229, -229, -229, -229
-
-    },
-
-    {
-       67, -230, -230, -230, -230, -230, -230, -230, -230, -230,
-     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
-     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
-     -230, -230,  378, -230, -230, -230, -230, -230, -230, -230,
-     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
-     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
-     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
-     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
-     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
-     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
-
-     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
-     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
-     -230, -230, -230, -230, -230, -230, -230, -230
-    },
-
-    {
-       67, -231, -231, -231, -231, -231, -231, -231, -231, -231,
-     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
-     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
-     -231, -231,  379, -231, -231, -231, -231, -231, -231, -231,
-     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
-     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
-     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
-
-     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
-     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
-     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
-     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
-     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
-     -231, -231, -231, -231, -231, -231, -231, -231
-    },
-
-    {
-       67, -232, -232, -232, -232, -232, -232, -232, -232, -232,
-     -232, -232, -232, -232, -232, -232, -232, -232, -232, -232,
-     -232, -232, -232, -232, -232, -232, -232, -232, -232, -232,
-     -232, -232,  380, -232, -232, -232, -232, -232, -232, -232,
-
-     -232, -232, -232, -232, -232, -232, -232, -232,  381,  381,
-      381,  381,  381,  381,  381,  381,  381,  381, -232, -232,
-     -232, -232, -232, -232, -232,  380,  380,  380,  380,  380,
-      380,  380,  380,  380,  380,  380,  380,  380,  380,  380,
-      380,  380,  380,  380,  380,  380,  380,  380,  380,  380,
-      380, -232, -232, -232, -232, -232, -232, -232, -232, -232,
-     -232, -232, -232, -232, -232, -232, -232, -232, -232, -232,
-     -232, -232, -232, -232, -232, -232, -232, -232, -232, -232,
-     -232, -232, -232, -232, -232, -232, -232, -232
-    },
-
-    {
-       67, -233, -233, -233, -233, -233, -233, -233, -233, -233,
-
-     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
-     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
-     -233, -233,  382, -233, -233, -233, -233, -233, -233, -233,
-     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
-     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
-     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
-     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
-     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
-     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
-     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
-
-     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
-     -233, -233, -233, -233, -233, -233, -233, -233
-    },
-
-    {
-       67, -234, -234, -234, -234, -234, -234, -234, -234, -234,
-     -234, -234, -234, -234, -234, -234, -234, -234, -234, -234,
-     -234, -234, -234, -234, -234, -234, -234, -234, -234, -234,
-     -234, -234,  383, -234, -234, -234, -234, -234, -234, -234,
-     -234, -234, -234, -234, -234, -234, -234, -234,  384,  384,
-      384,  384,  384,  384,  384,  384,  384,  384, -234, -234,
-     -234, -234, -234, -234, -234,  383,  383,  383,  383,  383,
-      383,  383,  383,  383,  383,  383,  383,  383,  383,  383,
-
-      383,  383,  383,  383,  383,  383,  383,  383,  383,  383,
-      383, -234, -234, -234, -234, -234, -234, -234, -234, -234,
-     -234, -234, -234, -234, -234, -234, -234, -234, -234, -234,
-     -234, -234, -234, -234, -234, -234, -234, -234, -234, -234,
-     -234, -234, -234, -234, -234, -234, -234, -234
-    },
-
-    {
-       67, -235, -235, -235, -235, -235, -235, -235, -235, -235,
-     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
-     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
-     -235, -235,  385, -235, -235, -235, -235, -235, -235, -235,
-     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
-
-     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
-     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
-     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
-     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
-     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
-     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
-     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
-     -235, -235, -235, -235, -235, -235, -235, -235
-    },
-
-    {
-       67, -236, -236, -236, -236, -236, -236, -236, -236, -236,
-     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
-
-     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
-     -236, -236,  386, -236, -236, -236, -236, -236, -236, -236,
-     -236, -236, -236, -236, -236, -236, -236, -236,  387,  387,
-      387,  387,  387,  387,  387,  387,  387,  387, -236, -236,
-     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
-     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
-     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
-     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
-     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
-     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
-
-     -236, -236, -236, -236, -236, -236, -236, -236
-    },
-
-    {
-       67, -237, -237, -237, -237, -237, -237, -237, -237, -237,
-     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
-     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
-     -237, -237,  388, -237, -237, -237, -237, -237, -237, -237,
-     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
-     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
-     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
-     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
-     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
-
-     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
-     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
-     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
-     -237, -237, -237, -237, -237, -237, -237, -237
-    },
-
-    {
-       67, -238, -238, -238, -238, -238, -238, -238, -238, -238,
-     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
-     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
-     -238, -238,  389, -238, -238, -238, -238, -238, -238, -238,
-     -238, -238, -238, -238, -238, -238, -238, -238,  390,  390,
-      390,  390,  390,  390,  390,  390,  390,  390, -238, -238,
-
-     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
-     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
-     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
-     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
-     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
-     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
-     -238, -238, -238, -238, -238, -238, -238, -238
-    },
-
-    {
-       67, -239, -239, -239, -239, -239, -239, -239, -239, -239,
-     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
-     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
-
-     -239, -239,  239, -239, -239, -239, -239, -239, -239, -239,
-     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
-     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
-     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
-     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
-     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
-     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
-     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
-     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
-     -239, -239, -239, -239, -239, -239, -239, -239
-
-    },
-
-    {
-       67, -240, -240, -240, -240, -240, -240, -240, -240, -240,
-     -240, -240, -240, -240, -240, -240, -240, -240, -240, -240,
-     -240, -240, -240, -240, -240, -240, -240, -240, -240, -240,
-     -240, -240, -240, -240, -240, -240, -240, -240, -240, -240,
-     -240, -240, -240, -240, -240, -240, -240, -240,  240,  240,
-      240,  240,  240,  240,  240,  240,  240,  240, -240, -240,
-     -240, -240, -240, -240, -240, -240, -240, -240, -240, -240,
-     -240, -240, -240, -240, -240, -240, -240, -240, -240, -240,
-     -240, -240, -240, -240, -240, -240, -240, -240, -240, -240,
-     -240, -240, -240, -240, -240, -240, -240, -240, -240, -240,
-
-     -240, -240, -240, -240, -240, -240, -240, -240, -240, -240,
-     -240, -240, -240, -240, -240, -240, -240, -240, -240, -240,
-     -240, -240, -240, -240, -240, -240, -240, -240
-    },
-
-    {
-       67, -241, -241, -241, -241, -241, -241, -241, -241, -241,
-     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
-     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
-     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
-     -241, -241, -241, -241, -241, -241, -241, -241,  243,  243,
-      243,  243,  243,  243,  243,  243,  243,  243, -241, -241,
-     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
-
-     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
-     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
-     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
-     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
-     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
-     -241, -241, -241, -241, -241, -241, -241, -241
-    },
-
-    {
-       67, -242, -242, -242, -242, -242, -242, -242, -242, -242,
-     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
-     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
-     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
-
-     -242, -242, -242, -242, -242, -242,  244, -242,  245,  245,
-      245,  245,  245,  245,  245,  245,  245,  245, -242, -242,
-     -242, -242, -242, -242, -242, -242, -242, -242, -242,  246,
-     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
-     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
-     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
-     -242,  246, -242, -242, -242, -242, -242, -242, -242, -242,
-     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
-     -242, -242, -242, -242, -242, -242, -242, -242
-    },
-
-    {
-       67, -243, -243, -243, -243, -243, -243, -243, -243, -243,
-
-     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
-     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
-     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
-     -243, -243, -243, -243, -243, -243, -243, -243,  243,  243,
-      243,  243,  243,  243,  243,  243,  243,  243, -243, -243,
-     -243, -243, -243, -243, -243, -243, -243, -243, -243,  246,
-     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
-     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
-     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
-     -243,  246, -243, -243, -243, -243, -243, -243, -243, -243,
-
-     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
-     -243, -243, -243, -243, -243, -243, -243, -243
-    },
-
-    {
-       67, -244, -244, -244, -244, -244, -244, -244, -244, -244,
-     -244, -244, -244, -244, -244, -244, -244, -244, -244, -244,
-     -244, -244, -244, -244, -244, -244, -244, -244, -244, -244,
-     -244, -244, -244, -244, -244, -244, -244, -244, -244, -244,
-     -244, -244, -244, -244, -244, -244, -244, -244,  391,  391,
-      391,  391,  391,  391,  391,  391,  391,  391, -244, -244,
-     -244, -244, -244, -244, -244, -244, -244, -244, -244,  246,
-     -244, -244, -244, -244, -244, -244, -244, -244, -244, -244,
-
-     -244, -244, -244, -244, -244, -244, -244, -244, -244, -244,
-     -244, -244, -244, -244, -244, -244, -244, -244, -244, -244,
-     -244,  246, -244, -244, -244, -244, -244, -244, -244, -244,
-     -244, -244, -244, -244, -244, -244, -244, -244, -244, -244,
-     -244, -244, -244, -244, -244, -244, -244, -244
-    },
-
-    {
-       67, -245, -245, -245, -245, -245, -245, -245, -245, -245,
-     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
-     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
-     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
-     -245, -245, -245, -245, -245, -245,  244, -245,  245,  245,
-
-      245,  245,  245,  245,  245,  245,  245,  245, -245, -245,
-     -245, -245, -245, -245, -245, -245, -245, -245, -245,  246,
-     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
-     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
-     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
-     -245,  246, -245, -245, -245, -245, -245, -245, -245, -245,
-     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
-     -245, -245, -245, -245, -245, -245, -245, -245
-    },
-
-    {
-       67, -246, -246, -246, -246, -246, -246, -246, -246, -246,
-     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
-
-     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
-     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
-     -246, -246, -246,  392, -246,  392, -246, -246,  393,  393,
-      393,  393,  393,  393,  393,  393,  393,  393, -246, -246,
-     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
-     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
-     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
-     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
-     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
-     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
-
-     -246, -246, -246, -246, -246, -246, -246, -246
-    },
-
-    {
-       67,  247,  247,  247,  247,  247,  247,  247,  247,  247,
-      247,  247,  247,  247,  247,  247,  247,  247,  247,  247,
-      247,  247,  247,  247,  247,  247,  247,  247,  247,  247,
-      247,  247,  247,  247,  247,  247,  247,  247,  247,  248,
-      247,  247,  247,  247,  247,  247,  247,  247,  247,  247,
-      247,  247,  247,  247,  247,  247,  247,  247,  247,  247,
-      247,  247,  247,  247,  247,  247,  247,  247,  247,  247,
-      247,  247,  247,  247,  247,  247,  247,  247,  247,  247,
-      247,  247,  247,  247,  247,  247,  247,  247,  247,  247,
-
-      247,  247,  247,  247,  247,  247,  247,  247,  247,  247,
-      247,  247,  247,  247,  247,  247,  247,  247,  247,  247,
-      247,  247,  247,  247,  247,  247,  247,  247,  247,  247,
-      247,  247,  247,  247,  247,  247,  247,  247
-    },
-
-    {
-       67, -248, -248, -248, -248, -248, -248, -248, -248, -248,
-     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
-     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
-     -248, -248, -248, -248, -248, -248, -248, -248, -248,  247,
-     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
-     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
-
-     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
-     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
-     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
-     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
-     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
-     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
-     -248, -248, -248, -248, -248, -248, -248, -248
-    },
-
-    {
-       67, -249, -249, -249, -249, -249, -249, -249, -249, -249,
-     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
-     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
-
-     -249, -249,  249, -249, -249, -249, -249, -249, -249, -249,
-     -249, -249, -249, -249, -249, -249, -249,  250, -249, -249,
-     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
-     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
-     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
-     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
-     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
-     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
-     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
-     -249, -249, -249, -249, -249, -249, -249, -249
-
-    },
-
-    {
-       67,  251,  251,  251,  251,  251,  251,  251,  251,  251,
-     -250,  251,  251,  251,  251,  251,  251,  251,  251,  251,
-      251,  251,  251,  251,  251,  251,  251,  251,  251,  251,
-      251,  251,  251,  251,  251,  251,  251,  251,  251,  251,
-      251,  251,  251,  251,  251,  251,  251,  251,  251,  251,
-      251,  251,  251,  251,  251,  251,  251,  251,  251,  251,
-      251,  251,  251,  251,  251,  251,  251,  251,  251,  251,
-      251,  251,  251,  251,  251,  251,  251,  251,  251,  251,
-      251,  251,  251,  251,  251,  251,  251,  251,  251,  251,
-      251,  251,  251,  251,  251,  251,  251,  251,  251,  251,
-
-      251,  251,  251,  251,  251,  251,  251,  251,  251,  251,
-      251,  251,  251,  251,  251,  251,  251,  251,  251,  251,
-      251,  251,  251,  251,  251,  251,  251,  251
-    },
-
-    {
-       67,  251,  251,  251,  251,  251,  251,  251,  251,  251,
-     -251,  251,  251,  251,  251,  251,  251,  251,  251,  251,
-      251,  251,  251,  251,  251,  251,  251,  251,  251,  251,
-      251,  251,  251,  251,  251,  251,  251,  251,  251,  251,
-      251,  251,  251,  251,  251,  251,  251,  251,  251,  251,
-      251,  251,  251,  251,  251,  251,  251,  251,  251,  251,
-      251,  251,  251,  251,  251,  251,  251,  251,  251,  251,
-
-      251,  251,  251,  251,  251,  251,  251,  251,  251,  251,
-      251,  251,  251,  251,  251,  251,  251,  251,  251,  251,
-      251,  251,  251,  251,  251,  251,  251,  251,  251,  251,
-      251,  251,  251,  251,  251,  251,  251,  251,  251,  251,
-      251,  251,  251,  251,  251,  251,  251,  251,  251,  251,
-      251,  251,  251,  251,  251,  251,  251,  251
-    },
-
-    {
-       67,  252,  252,  252,  252,  252,  252,  252,  252,  252,
-     -252,  252,  252,  252,  252,  252,  252,  252,  252,  252,
-      252,  252,  252,  252,  252,  252,  252,  252,  252,  252,
-      252,  252,  252,  252,  252,  252,  252,  252,  252,  252,
-
-      252,  252,  252,  252,  252,  252,  252,  252,  252,  252,
-      252,  252,  252,  252,  252,  252,  252,  252,  252,  252,
-      252,  252,  252,  252,  252,  252,  252,  252,  252,  252,
-      252,  252,  252,  252,  252,  252,  252,  252,  252,  252,
-      252,  252,  252,  252,  252,  252,  252,  252,  252,  252,
-      252,  252,  252,  252,  252,  252,  252,  252,  252,  252,
-      252,  252,  252,  252,  252,  252,  252,  252,  252,  252,
-      252,  252,  252,  252,  252,  252,  252,  252,  252,  252,
-      252,  252,  252,  252,  252,  252,  252,  252
-    },
-
-    {
-       67,  253,  253,  253,  253,  253,  253,  253,  253,  253,
-
-     -253,  253,  253,  253,  253,  253,  253,  253,  253,  253,
-      253,  253,  253,  253,  253,  253,  253,  253,  253,  253,
-      253,  253,  253,  253,  253,  253,  253,  253,  253,  253,
-      253,  253,  253,  253,  253,  253,  253,  253,  253,  253,
-      253,  253,  253,  253,  253,  253,  253,  253,  253,  253,
-      253,  253,  253,  253,  253,  253,  253,  253,  253,  253,
-      253,  253,  253,  253,  253,  253,  253,  253,  253,  253,
-      253,  253,  253,  253,  253,  253,  253,  253,  253,  253,
-      253,  253,  253,  253,  253,  253,  253,  253,  253,  253,
-      253,  253,  253,  253,  253,  253,  253,  253,  253,  253,
-
-      253,  253,  253,  253,  253,  253,  253,  253,  253,  253,
-      253,  253,  253,  253,  253,  253,  253,  253
-    },
-
-    {
-       67,  254,  254,  254,  254,  254,  254,  254,  254,  254,
-      255,  254,  254,  254,  254,  254,  254,  254,  254,  254,
-      254,  254,  254,  254,  254,  254,  254,  254,  254,  254,
-      254,  254,  254,  254,  254,  254,  254,  254,  254,  254,
-      254,  254,  254,  254,  254,  254,  254,  254,  254,  254,
-      254,  254,  254,  254,  254,  254,  254,  254,  254,  254,
-      254,  254,  254,  254,  254,  254,  254,  254,  254,  254,
-      254,  254,  254,  254,  254,  254,  254,  254,  254,  254,
-
-      254,  254,  254,  254,  254,  254,  254,  254,  254,  254,
-      254,  254,  254,  254,  254,  254,  254,  254,  254,  254,
-      254,  254,  254,  254,  254,  254,  254,  254,  254,  254,
-      254,  254,  254,  254,  254,  254,  254,  254,  254,  254,
-      254,  254,  254,  254,  254,  254,  254,  254
-    },
-
-    {
-       67, -255, -255, -255, -255, -255, -255, -255, -255, -255,
-     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
-     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
-     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
-     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
-
-     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
-     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
-     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
-     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
-     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
-     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
-     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
-     -255, -255, -255, -255, -255, -255, -255, -255
-    },
-
-    {
-       67, -256, -256, -256, -256, -256, -256, -256, -256, -256,
-     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
-
-     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
-     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
-     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
-     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
-     -256, -256, -256, -256, -256, -256, -256, -256,  394, -256,
-     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
-     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
-     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
-     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
-     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
-
-     -256, -256, -256, -256, -256, -256, -256, -256
-    },
-
-    {
-       67, -257, -257, -257, -257, -257, -257, -257, -257, -257,
-     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
-     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
-     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
-     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
-     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
-     -257, -257, -257, -257, -257, -257, -257,  395, -257, -257,
-     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
-     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
-
-     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
-     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
-     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
-     -257, -257, -257, -257, -257, -257, -257, -257
-    },
-
-    {
-       67, -258, -258, -258, -258, -258, -258, -258, -258, -258,
-     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
-     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
-     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
-     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
-     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
-
-     -258, -258, -258, -258, -258, -258, -258, -258, -258,  396,
-     -258, -258, -258, -258, -258, -258,  397, -258, -258, -258,
-     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
-     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
-     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
-     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
-     -258, -258, -258, -258, -258, -258, -258, -258
-    },
-
-    {
-       67, -259, -259, -259, -259, -259, -259, -259, -259, -259,
-     -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
-     -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
-
-     -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
-     -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
-     -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
-     -259, -259, -259, -259, -259,  398, -259, -259, -259, -259,
-     -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
-     -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
-     -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
-     -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
-     -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
-     -259, -259, -259, -259, -259, -259, -259, -259
-
-    },
-
-    {
-       67, -260, -260, -260, -260, -260, -260, -260, -260, -260,
-     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
-     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
-     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
-     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
-     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
-     -260, -260, -260, -260, -260, -260, -260, -260,  399, -260,
-     -260, -260, -260, -260, -260, -260, -260, -260, -260,  400,
-      401, -260, -260, -260, -260, -260,  402, -260, -260, -260,
-     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
-
-     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
-     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
-     -260, -260, -260, -260, -260, -260, -260, -260
-    },
-
-    {
-       67, -261, -261, -261, -261, -261, -261, -261, -261, -261,
-     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
-     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
-     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
-     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
-     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
-     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
-
-     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
-     -261, -261, -261, -261, -261, -261, -261, -261, -261,  403,
-     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
-     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
-     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
-     -261, -261, -261, -261, -261, -261, -261, -261
-    },
-
-    {
-       67, -262, -262, -262, -262, -262, -262, -262, -262, -262,
-     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
-     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
-     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
-
-     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
-     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
-     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
-     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
-     -262, -262, -262, -262, -262, -262, -262, -262, -262,  404,
-     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
-     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
-     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
-     -262, -262, -262, -262, -262, -262, -262, -262
-    },
-
-    {
-       67, -263, -263, -263, -263, -263, -263, -263, -263, -263,
-
-     -263, -263, -263, -263, -263, -263, -263, -263, -263, -263,
-     -263, -263, -263, -263, -263, -263, -263, -263, -263, -263,
-     -263, -263, -263, -263, -263, -263, -263, -263, -263, -263,
-     -263, -263, -263, -263, -263, -263, -263, -263, -263, -263,
-     -263, -263, -263, -263, -263, -263, -263, -263, -263, -263,
-     -263, -263, -263, -263, -263, -263, -263, -263, -263, -263,
-     -263, -263, -263, -263, -263, -263, -263, -263,  405, -263,
-     -263, -263, -263, -263, -263, -263, -263, -263, -263, -263,
-     -263, -263, -263, -263, -263, -263, -263, -263, -263, -263,
-     -263, -263, -263, -263, -263, -263, -263, -263, -263, -263,
-
-     -263, -263, -263, -263, -263, -263, -263, -263, -263, -263,
-     -263, -263, -263, -263, -263, -263, -263, -263
-    },
-
-    {
-       67, -264, -264, -264, -264, -264, -264, -264, -264, -264,
-     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
-     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
-     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
-     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
-     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
-     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
-     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
-
-     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
-     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
-     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
-     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
-     -264, -264, -264, -264, -264, -264, -264, -264
-    },
-
-    {
-       67, -265, -265, -265, -265, -265, -265, -265, -265, -265,
-     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
-     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
-     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
-     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
-
-     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
-     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
-     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
-     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
-     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
-     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
-     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
-     -265, -265, -265, -265, -265, -265, -265, -265
-    },
-
-    {
-       67, -266, -266, -266, -266, -266, -266, -266, -266, -266,
-     -266, -266, -266, -266, -266, -266, -266, -266, -266, -266,
-
-     -266, -266, -266, -266, -266, -266, -266, -266, -266, -266,
-     -266, -266, -266, -266, -266, -266, -266, -266, -266, -266,
-     -266, -266, -266, -266, -266, -266, -266, -266, -266, -266,
-     -266, -266, -266, -266, -266, -266, -266, -266, -266, -266,
-     -266, -266, -266, -266, -266, -266, -266, -266, -266, -266,
-     -266, -266, -266, -266, -266, -266,  406, -266, -266, -266,
-     -266, -266, -266, -266, -266, -266, -266, -266, -266, -266,
-     -266, -266, -266, -266, -266, -266, -266, -266, -266, -266,
-     -266, -266, -266, -266, -266, -266, -266, -266, -266, -266,
-     -266, -266, -266, -266, -266, -266, -266, -266, -266, -266,
-
-     -266, -266, -266, -266, -266, -266, -266, -266
-    },
-
-    {
-       67, -267, -267, -267, -267, -267, -267, -267, -267, -267,
-     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
-     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
-     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
-     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
-     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
-     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
-     -267, -267, -267, -267, -267, -267, -267,  407, -267, -267,
-     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
-
-     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
-     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
-     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
-     -267, -267, -267, -267, -267, -267, -267, -267
-    },
-
-    {
-       67, -268, -268, -268, -268, -268, -268, -268, -268, -268,
-     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
-     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
-     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
-     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
-     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
-
-     -268, -268, -268, -268, -268, -268, -268, -268, -268,  408,
-     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
-     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
-     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
-     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
-     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
-     -268, -268, -268, -268, -268, -268, -268, -268
-    },
-
-    {
-       67, -269, -269, -269, -269, -269, -269, -269, -269, -269,
-     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
-     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
-
-     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
-     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
-     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
-     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
-     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
-     -269, -269, -269, -269,  409, -269, -269, -269, -269, -269,
-     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
-     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
-     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
-     -269, -269, -269, -269, -269, -269, -269, -269
-
-    },
-
-    {
-       67, -270, -270, -270, -270, -270, -270, -270, -270, -270,
-     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
-     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
-     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
-     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
-     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
-     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
-     -270, -270, -270,  410, -270, -270, -270, -270, -270, -270,
-     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
-     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
-
-     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
-     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
-     -270, -270, -270, -270, -270, -270, -270, -270
-    },
-
-    {
-       67, -271, -271, -271, -271, -271, -271, -271, -271, -271,
-     -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
-     -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
-     -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
-     -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
-     -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
-     -271, -271, -271, -271, -271,  411, -271, -271, -271, -271,
-
-     -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
-     -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
-     -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
-     -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
-     -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
-     -271, -271, -271, -271, -271, -271, -271, -271
-    },
-
-    {
-       67, -272, -272, -272, -272, -272, -272, -272, -272, -272,
-     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
-     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
-     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
-
-     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
-     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
-     -272, -272, -272, -272, -272, -272, -272, -272, -272,  412,
-     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
-     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
-     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
-     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
-     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
-     -272, -272, -272, -272, -272, -272, -272, -272
-    },
-
-    {
-       67, -273, -273, -273, -273, -273, -273, -273, -273, -273,
-
-     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
-     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
-     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
-     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
-     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
-     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
-     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
-      413, -273, -273, -273, -273, -273, -273, -273, -273, -273,
-     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
-     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
-
-     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
-     -273, -273, -273, -273, -273, -273, -273, -273
-    },
-
-    {
-       67, -274, -274, -274, -274, -274, -274, -274, -274, -274,
-     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
-     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
-     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
-     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
-     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
-     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
-     -274, -274, -274,  414, -274, -274, -274, -274, -274, -274,
-
-     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
-     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
-     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
-     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
-     -274, -274, -274, -274, -274, -274, -274, -274
-    },
-
-    {
-       67, -275, -275, -275, -275, -275, -275, -275, -275, -275,
-     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
-     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
-     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
-     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
-
-     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
-     -275, -275, -275, -275, -275, -275, -275, -275, -275,  415,
-     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
-     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
-     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
-     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
-     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
-     -275, -275, -275, -275, -275, -275, -275, -275
-    },
-
-    {
-       67, -276, -276, -276, -276, -276, -276, -276, -276, -276,
-     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
-
-     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
-     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
-     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
-     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
-     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
-     -276,  416, -276, -276, -276, -276, -276, -276, -276, -276,
-     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
-     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
-     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
-     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
-
-     -276, -276, -276, -276, -276, -276, -276, -276
-    },
-
-    {
-       67, -277, -277, -277, -277, -277, -277, -277, -277, -277,
-     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
-     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
-     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
-     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
-     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
-     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
-     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
-     -277, -277, -277,  417, -277, -277, -277, -277, -277, -277,
-
-     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
-     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
-     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
-     -277, -277, -277, -277, -277, -277, -277, -277
-    },
-
-    {
-       67, -278, -278, -278, -278, -278, -278, -278, -278, -278,
-     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
-     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
-     -278, -278,  418, -278, -278, -278, -278, -278, -278, -278,
-     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
-     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
-
-     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
-     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
-     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
-     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
-     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
-     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
-     -278, -278, -278, -278, -278, -278, -278, -278
-    },
-
-    {
-       67, -279, -279, -279, -279, -279, -279, -279, -279, -279,
-     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
-     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
-
-     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
-     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
-     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
-     -279, -279, -279, -279, -279, -279, -279,  419, -279, -279,
-     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
-     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
-     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
-     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
-     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
-     -279, -279, -279, -279, -279, -279, -279, -279
-
-    },
-
-    {
-       67, -280, -280, -280, -280, -280, -280, -280, -280, -280,
-     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
-     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
-     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
-     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
-     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
-     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
-     -280, -280, -280,  420, -280, -280, -280, -280, -280, -280,
-     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
-     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
-
-     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
-     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
-     -280, -280, -280, -280, -280, -280, -280, -280
-    },
-
-    {
-       67, -281, -281, -281, -281, -281, -281, -281, -281, -281,
-     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
-     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
-     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
-     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
-     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
-     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
-
-     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
-      421, -281, -281, -281, -281, -281, -281, -281, -281, -281,
-     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
-     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
-     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
-     -281, -281, -281, -281, -281, -281, -281, -281
-    },
-
-    {
-       67, -282, -282, -282, -282, -282, -282, -282, -282, -282,
-     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
-     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
-     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
-
-     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
-     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
-     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
-     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
-      422, -282, -282, -282, -282, -282, -282, -282, -282, -282,
-     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
-     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
-     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
-     -282, -282, -282, -282, -282, -282, -282, -282
-    },
-
-    {
-       67, -283, -283, -283, -283, -283, -283, -283, -283, -283,
-
-     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
-     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
-     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
-     -283, -283, -283, -283, -283,  423, -283, -283, -283, -283,
-     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
-     -283, -283, -283, -283, -283,  424, -283, -283, -283, -283,
-     -283, -283, -283, -283, -283, -283, -283, -283, -283,  425,
-     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
-     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
-     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
-
-     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
-     -283, -283, -283, -283, -283, -283, -283, -283
-    },
-
-    {
-       67, -284, -284, -284, -284, -284, -284, -284, -284, -284,
-     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
-     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
-     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
-     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
-     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
-     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
-     -284,  426, -284, -284, -284, -284, -284, -284, -284, -284,
-
-     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
-     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
-     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
-     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
-     -284, -284, -284, -284, -284, -284, -284, -284
-    },
-
-    {
-       67, -285, -285, -285, -285, -285, -285, -285, -285, -285,
-     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
-     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
-     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
-     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
-
-     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
-     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
-     -285, -285, -285, -285,  427, -285, -285, -285, -285, -285,
-     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
-     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
-     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
-     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
-     -285, -285, -285, -285, -285, -285, -285, -285
-    },
-
-    {
-       67, -286, -286, -286, -286, -286, -286, -286, -286, -286,
-     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
-
-     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
-     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
-     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
-     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
-     -286, -286, -286, -286, -286, -286, -286, -286, -286,  428,
-     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
-     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
-     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
-     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
-     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
-
-     -286, -286, -286, -286, -286, -286, -286, -286
-    },
-
-    {
-       67, -287, -287, -287, -287, -287, -287, -287, -287, -287,
-     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
-     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
-     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
-     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
-     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
-     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
-     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
-     -287, -287, -287, -287,  429, -287, -287, -287, -287, -287,
-
-     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
-     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
-     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
-     -287, -287, -287, -287, -287, -287, -287, -287
-    },
-
-    {
-       67, -288, -288, -288, -288, -288, -288, -288, -288, -288,
-     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
-     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
-     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
-     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
-     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
-
-     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
-     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
-     -288,  430, -288, -288, -288, -288, -288, -288, -288, -288,
-     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
-     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
-     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
-     -288, -288, -288, -288, -288, -288, -288, -288
-    },
-
-    {
-       67, -289, -289, -289, -289, -289, -289, -289, -289, -289,
-     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
-     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
-
-     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
-     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
-     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
-     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
-     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
-     -289, -289, -289, -289, -289, -289,  431, -289, -289, -289,
-     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
-     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
-     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
-     -289, -289, -289, -289, -289, -289, -289, -289
-
-    },
-
-    {
-       67, -290, -290, -290, -290, -290, -290, -290, -290, -290,
-     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
-     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
-     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
-     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
-     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
-     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
-     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
-     -290, -290, -290,  432, -290, -290, -290, -290, -290, -290,
-     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
-
-     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
-     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
-     -290, -290, -290, -290, -290, -290, -290, -290
-    },
-
-    {
-       67, -291, -291, -291, -291, -291, -291, -291, -291, -291,
-     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
-     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
-     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
-     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
-     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
-     -291, -291, -291, -291, -291, -291, -291,  433, -291, -291,
-
-     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
-     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
-     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
-     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
-     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
-     -291, -291, -291, -291, -291, -291, -291, -291
-    },
-
-    {
-       67, -292, -292, -292, -292, -292, -292, -292, -292, -292,
-     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
-     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
-     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
-
-     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
-     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
-     -292, -292, -292, -292, -292, -292, -292,  434, -292, -292,
-     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
-     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
-     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
-     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
-     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
-     -292, -292, -292, -292, -292, -292, -292, -292
-    },
-
-    {
-       67, -293, -293, -293, -293, -293, -293, -293, -293, -293,
-
-     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
-     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
-     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
-     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
-     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
-     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
-     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
-     -293, -293, -293,  435, -293, -293, -293, -293, -293, -293,
-     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
-     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
-
-     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
-     -293, -293, -293, -293, -293, -293, -293, -293
-    },
-
-    {
-       67, -294, -294, -294, -294, -294, -294, -294, -294, -294,
-     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
-     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
-     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
-     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
-     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
-     -294, -294, -294, -294, -294, -294, -294, -294, -294,  436,
-     -294, -294, -294, -294, -294, -294,  437, -294, -294, -294,
-
-     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
-     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
-     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
-     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
-     -294, -294, -294, -294, -294, -294, -294, -294
-    },
-
-    {
-       67, -295, -295, -295, -295, -295, -295, -295, -295, -295,
-     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
-     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
-     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
-     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
-
-     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
-     -295, -295, -295, -295, -295,  438, -295, -295, -295, -295,
-     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
-     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
-     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
-     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
-     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
-     -295, -295, -295, -295, -295, -295, -295, -295
-    },
-
-    {
-       67, -296, -296, -296, -296, -296, -296, -296, -296, -296,
-     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
-
-     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
-     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
-     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
-     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
-     -296, -296, -296, -296, -296, -296, -296, -296,  439, -296,
-     -296, -296, -296, -296, -296, -296, -296, -296, -296,  440,
-      441, -296, -296, -296, -296, -296,  442, -296, -296, -296,
-     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
-     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
-     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
-
-     -296, -296, -296, -296, -296, -296, -296, -296
-    },
-
-    {
-       67, -297, -297, -297, -297, -297, -297, -297, -297, -297,
-     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
-     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
-     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
-     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
-     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
-     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
-     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
-     -297, -297, -297, -297, -297, -297, -297, -297, -297,  443,
-
-     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
-     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
-     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
-     -297, -297, -297, -297, -297, -297, -297, -297
-    },
-
-    {
-       67, -298, -298, -298, -298, -298, -298, -298, -298, -298,
-     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
-     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
-     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
-     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
-     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
-
-     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
-     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
-     -298, -298, -298, -298, -298, -298, -298, -298, -298,  444,
-     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
-     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
-     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
-     -298, -298, -298, -298, -298, -298, -298, -298
-    },
-
-    {
-       67, -299, -299, -299, -299, -299, -299, -299, -299, -299,
-     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
-     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
-
-     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
-     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
-     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
-     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
-     -299, -299, -299, -299, -299, -299, -299, -299,  445, -299,
-     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
-     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
-     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
-     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
-     -299, -299, -299, -299, -299, -299, -299, -299
-
-    },
-
-    {
-       67, -300, -300, -300, -300, -300, -300, -300, -300, -300,
-     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
-     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
-     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
-     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
-     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
-     -300, -300, -300, -300, -300, -300, -300, -300, -300,  446,
-     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
-     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
-     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
-
-     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
-     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
-     -300, -300, -300, -300, -300, -300, -300, -300
-    },
-
-    {
-       67, -301, -301, -301, -301, -301, -301, -301, -301, -301,
-     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
-     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
-     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
-     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
-     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
-     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
-
-     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
-     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
-     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
-     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
-     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
-     -301, -301, -301, -301, -301, -301, -301, -301
-    },
-
-    {
-       67, -302, -302, -302, -302, -302, -302, -302, -302, -302,
-     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
-     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
-     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
-
-     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
-     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
-     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
-     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
-     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
-     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
-     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
-     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
-     -302, -302, -302, -302, -302, -302, -302, -302
-    },
-
-    {
-       67, -303, -303, -303, -303, -303, -303, -303, -303, -303,
-
-     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
-     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
-     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
-     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
-     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
-     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
-     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
-     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
-     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
-     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
-
-     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
-     -303, -303, -303, -303, -303, -303, -303, -303
-    },
-
-    {
-       67, -304, -304, -304, -304, -304, -304, -304, -304, -304,
-     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
-     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
-     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
-     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
-     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
-     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
-     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
-
-     -304, -304, -304,  447, -304, -304, -304, -304, -304, -304,
-     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
-     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
-     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
-     -304, -304, -304, -304, -304, -304, -304, -304
-    },
-
-    {
-       67, -305, -305, -305, -305, -305, -305, -305, -305, -305,
-     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
-     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
-     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
-     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
-
-     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
-     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
-     -305,  448, -305, -305, -305, -305, -305, -305, -305, -305,
-     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
-     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
-     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
-     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
-     -305, -305, -305, -305, -305, -305, -305, -305
-    },
-
-    {
-       67, -306, -306, -306, -306, -306, -306, -306, -306, -306,
-     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
-
-     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
-     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
-     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
-     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
-     -306, -306, -306, -306, -306,  449, -306, -306, -306, -306,
-     -306, -306, -306, -306, -306, -306, -306, -306, -306,  450,
-     -306, -306,  451, -306, -306, -306, -306, -306, -306, -306,
-     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
-     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
-     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
-
-     -306, -306, -306, -306, -306, -306, -306, -306
-    },
-
-    {
-       67, -307, -307, -307, -307, -307, -307, -307, -307, -307,
-     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
-     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
-     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
-     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
-     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
-     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
-     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
-     -307, -307, -307, -307, -307,  452, -307, -307, -307, -307,
-
-     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
-     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
-     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
-     -307, -307, -307, -307, -307, -307, -307, -307
-    },
-
-    {
-       67, -308, -308, -308, -308, -308, -308, -308, -308, -308,
-     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
-     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
-     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
-     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
-     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
-
-     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
-     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
-     -308, -308, -308,  453, -308, -308, -308, -308, -308, -308,
-     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
-     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
-     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
-     -308, -308, -308, -308, -308, -308, -308, -308
-    },
-
-    {
-       67, -309, -309, -309, -309, -309, -309, -309, -309, -309,
-     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
-     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
-
-     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
-     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
-     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
-     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
-     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
-     -309, -309, -309, -309, -309, -309, -309, -309,  454, -309,
-     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
-     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
-     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
-     -309, -309, -309, -309, -309, -309, -309, -309
-
-    },
-
-    {
-       67, -310, -310, -310, -310, -310, -310, -310, -310, -310,
-     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
-     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
-     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
-     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
-     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
-     -310, -310, -310, -310, -310,  455, -310, -310, -310, -310,
-     -310, -310, -310, -310, -310, -310, -310, -310,  456, -310,
-     -310, -310, -310, -310,  457, -310, -310, -310,  458, -310,
-     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
-
-     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
-     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
-     -310, -310, -310, -310, -310, -310, -310, -310
-    },
-
-    {
-       67, -311, -311, -311, -311, -311, -311, -311, -311, -311,
-     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
-     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
-     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
-     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
-     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
-     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
-
-     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
-     -311, -311, -311, -311, -311,  459, -311, -311, -311, -311,
-     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
-     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
-     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
-     -311, -311, -311, -311, -311, -311, -311, -311
-    },
-
-    {
-       67, -312, -312, -312, -312, -312, -312, -312, -312, -312,
-     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
-     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
-     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
-
-     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
-     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
-     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
-     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
-     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
-     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
-     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
-     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
-     -312, -312, -312, -312, -312, -312, -312, -312
-    },
-
-    {
-       67, -313, -313, -313, -313, -313, -313, -313, -313, -313,
-
-     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
-     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
-     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
-     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
-     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
-     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
-     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
-     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
-     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
-     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
-
-     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
-     -313, -313, -313, -313, -313, -313, -313, -313
-    },
-
-    {
-       67, -314, -314, -314, -314, -314, -314, -314, -314, -314,
-     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
-     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
-     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
-     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
-     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
-     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
-     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
-
-     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
-     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
-     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
-     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
-     -314, -314, -314, -314, -314, -314, -314, -314
-    },
-
-    {
-       67, -315, -315, -315, -315, -315, -315, -315, -315, -315,
-     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
-     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
-     -315, -315,  460, -315, -315, -315, -315, -315, -315, -315,
-     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
-
-     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
-     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
-     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
-     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
-     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
-     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
-     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
-     -315, -315, -315, -315, -315, -315, -315, -315
-    },
-
-    {
-       67, -316, -316, -316, -316, -316, -316, -316, -316, -316,
-     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
-
-     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
-     -316, -316,  461, -316, -316, -316, -316, -316, -316, -316,
-     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
-     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
-     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
-     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
-     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
-     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
-     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
-     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
-
-     -316, -316, -316, -316, -316, -316, -316, -316
-    },
-
-    {
-       67, -317, -317, -317, -317, -317, -317, -317, -317, -317,
-     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
-     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
-     -317, -317,  462, -317, -317, -317, -317, -317, -317, -317,
-     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
-     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
-     -317, -317, -317, -317, -317,  462,  462,  462,  462,  462,
-      462,  462,  462,  462,  462,  462,  462,  462,  462,  462,
-      462,  462,  462,  462,  462,  462,  462,  462,  462,  462,
-
-      462, -317, -317, -317, -317, -317, -317, -317, -317, -317,
-     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
-     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
-     -317, -317, -317, -317, -317, -317, -317, -317
-    },
-
-    {
-       67, -318, -318, -318, -318, -318, -318, -318, -318, -318,
-     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
-     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
-     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
-     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
-     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
-
-     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
-     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
-     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
-     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
-     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
-     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
-     -318, -318, -318, -318, -318, -318, -318, -318
-    },
-
-    {
-       67, -319, -319, -319, -319, -319, -319, -319, -319, -319,
-     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
-     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
-
-     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
-     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
-     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
-     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
-     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
-     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
-     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
-     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
-     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
-     -319, -319, -319, -319, -319, -319, -319, -319
-
-    },
-
-    {
-       67, -320, -320, -320, -320, -320, -320, -320, -320, -320,
-     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
-     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
-     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
-     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
-     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
-     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
-     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
-     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
-     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
-
-     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
-     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
-     -320, -320, -320, -320, -320, -320, -320, -320
-    },
-
-    {
-       67, -321, -321, -321, -321, -321, -321, -321, -321, -321,
-     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
-     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
-     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
-     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
-     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
-     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
-
-     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
-     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
-     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
-     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
-     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
-     -321, -321, -321, -321, -321, -321, -321, -321
-    },
-
-    {
-       67, -322, -322, -322, -322, -322, -322, -322, -322, -322,
-     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
-     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
-     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
-
-     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
-     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
-     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
-     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
-     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
-     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
-     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
-     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
-     -322, -322, -322, -322, -322, -322, -322, -322
-    },
-
-    {
-       67, -323, -323, -323, -323, -323, -323, -323, -323, -323,
-
-     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
-     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
-     -323, -323,  463, -323, -323, -323, -323, -323, -323, -323,
-     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
-     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
-     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
-     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
-     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
-     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
-     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
-
-     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
-     -323, -323, -323, -323, -323, -323, -323, -323
-    },
-
-    {
-       67, -324, -324, -324, -324, -324, -324, -324, -324, -324,
-     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
-     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
-     -324, -324,  464, -324, -324, -324, -324, -324, -324, -324,
-     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
-     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
-     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
-     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
-
-     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
-     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
-     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
-     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
-     -324, -324, -324, -324, -324, -324, -324, -324
-    },
-
-    {
-       67, -325, -325, -325, -325, -325, -325, -325, -325, -325,
-     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
-     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
-     -325, -325,  465, -325, -325, -325, -325, -325, -325, -325,
-     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
-
-     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
-     -325, -325, -325, -325, -325,  465,  465,  465,  465,  465,
-      465,  465,  465,  465,  465,  465,  465,  465,  465,  465,
-      465,  465,  465,  465,  465,  465,  465,  465,  465,  465,
-      465, -325, -325, -325, -325, -325, -325, -325, -325, -325,
-     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
-     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
-     -325, -325, -325, -325, -325, -325, -325, -325
-    },
-
-    {
-       67, -326, -326, -326, -326, -326, -326, -326, -326, -326,
-     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
-
-     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
-     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
-     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
-     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
-     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
-     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
-     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
-     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
-     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
-     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
-
-     -326, -326, -326, -326, -326, -326, -326, -326
-    },
-
-    {
-       67, -327, -327, -327, -327, -327, -327, -327, -327, -327,
-     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
-     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
-     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
-     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
-     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
-     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
-     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
-     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
-
-     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
-     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
-     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
-     -327, -327, -327, -327, -327, -327, -327, -327
-    },
-
-    {
-       67, -328, -328, -328, -328, -328, -328, -328, -328, -328,
-     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
-     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
-     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
-     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
-     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
-
-     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
-     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
-     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
-     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
-     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
-     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
-     -328, -328, -328, -328, -328, -328, -328, -328
-    },
-
-    {
-       67, -329, -329, -329, -329, -329, -329, -329, -329, -329,
-     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
-     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
-
-     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
-     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
-     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
-     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
-     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
-     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
-     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
-     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
-     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
-     -329, -329, -329, -329, -329, -329, -329, -329
-
-    },
-
-    {
-       67, -330, -330, -330, -330, -330, -330, -330, -330, -330,
-     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
-     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
-     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
-     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
-     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
-     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
-     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
-     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
-     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
-
-     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
-     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
-     -330, -330, -330, -330, -330, -330, -330, -330
-    },
-
-    {
-       67, -331, -331, -331, -331, -331, -331, -331, -331, -331,
-     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
-     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
-     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
-     -331, -331, -331, -331, -331, -331, -331, -331,  466,  466,
-      466,  466,  466,  466,  466,  466,  466,  466, -331, -331,
-     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
-
-     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
-     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
-     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
-     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
-     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
-     -331, -331, -331, -331, -331, -331, -331, -331
-    },
-
-    {
-       67, -332, -332, -332, -332, -332, -332, -332, -332, -332,
-     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
-     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
-     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
-
-     -332, -332, -332, -332, -332, -332, -332, -332,  467,  467,
-      467,  467,  467,  467,  467,  467,  467,  467, -332, -332,
-     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
-     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
-     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
-     -332, -332, -332, -332, -332,  468, -332, -332, -332, -332,
-     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
-     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
-     -332, -332, -332, -332, -332, -332, -332, -332
-    },
-
-    {
-       67, -333, -333, -333, -333, -333, -333, -333, -333, -333,
-
-     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
-     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
-     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
-     -333, -333, -333, -333, -333, -333, -333, -333, -333,  469,
-      469,  469,  469,  469,  469,  469,  469,  469, -333, -333,
-     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
-     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
-     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
-     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
-     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
-
-     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
-     -333, -333, -333, -333, -333, -333, -333, -333
-    },
-
-    {
-       67, -334, -334, -334, -334, -334, -334, -334, -334, -334,
-     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
-     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
-     -334, -334,  470, -334, -334, -334, -334, -334, -334, -334,
-     -334, -334, -334, -334, -334, -334, -334, -334,  471,  471,
-      471,  471,  471,  471,  471,  471,  471,  471, -334, -334,
-     -334, -334, -334, -334, -334,  470,  470,  470,  470,  470,
-      470,  470,  470,  470,  470,  470,  470,  470,  470,  470,
-
-      470,  470,  470,  470,  470,  470,  470,  470,  470,  470,
-      470, -334, -334, -334, -334, -334, -334, -334, -334, -334,
-     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
-     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
-     -334, -334, -334, -334, -334, -334, -334, -334
-    },
-
-    {
-       67, -335, -335, -335, -335, -335, -335, -335, -335, -335,
-     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
-     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
-     -335, -335,  472, -335, -335, -335, -335, -335, -335, -335,
-     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
-
-     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
-     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
-     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
-     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
-     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
-     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
-     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
-     -335, -335, -335, -335, -335, -335, -335, -335
-    },
-
-    {
-       67, -336, -336, -336, -336, -336, -336, -336, -336, -336,
-     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
-
-     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
-     -336, -336,  473, -336, -336, -336, -336, -336, -336, -336,
-     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
-     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
-     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
-     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
-     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
-     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
-     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
-     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
-
-     -336, -336, -336, -336, -336, -336, -336, -336
-    },
-
-    {
-       67, -337, -337, -337, -337, -337, -337, -337, -337, -337,
-     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
-     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
-     -337, -337,  474, -337, -337, -337, -337, -337, -337, -337,
-     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
-     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
-     -337, -337, -337, -337, -337,  474,  474,  474,  474,  474,
-      474,  474,  474,  474,  474,  474,  474,  474,  474,  474,
-      474,  474,  474,  474,  474,  474,  474,  474,  474,  474,
-
-      474, -337, -337, -337, -337, -337, -337, -337, -337, -337,
-     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
-     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
-     -337, -337, -337, -337, -337, -337, -337, -337
-    },
-
-    {
-       67, -338, -338, -338, -338, -338, -338, -338, -338, -338,
-     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
-     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
-     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
-     -338, -338, -338, -338, -338, -338, -338, -338,  475,  475,
-      475,  475,  475,  475,  475,  475,  475,  475, -338, -338,
-
-     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
-     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
-     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
-     -338, -338, -338, -338, -338,  476, -338, -338, -338, -338,
-     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
-     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
-     -338, -338, -338, -338, -338, -338, -338, -338
-    },
-
-    {
-       67, -339, -339, -339, -339, -339, -339, -339, -339, -339,
-     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
-     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
-
-     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
-     -339, -339, -339, -339, -339, -339, -339, -339, -339,  477,
-      477,  477,  477,  477,  477,  477,  477,  477, -339, -339,
-     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
-     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
-     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
-     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
-     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
-     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
-     -339, -339, -339, -339, -339, -339, -339, -339
-
-    },
-
-    {
-       67, -340, -340, -340, -340, -340, -340, -340, -340, -340,
-     -340, -340, -340, -340, -340, -340, -340, -340, -340, -340,
-     -340, -340, -340, -340, -340, -340, -340, -340, -340, -340,
-     -340, -340,  478, -340, -340, -340, -340, -340, -340, -340,
-     -340, -340, -340, -340, -340, -340, -340, -340,  479,  479,
-      479,  479,  479,  479,  479,  479,  479,  479, -340, -340,
-     -340, -340, -340, -340, -340,  478,  478,  478,  478,  478,
-      478,  478,  478,  478,  478,  478,  478,  478,  478,  478,
-      478,  478,  478,  478,  478,  478,  478,  478,  478,  478,
-      478, -340, -340, -340, -340, -340, -340, -340, -340, -340,
-
-     -340, -340, -340, -340, -340, -340, -340, -340, -340, -340,
-     -340, -340, -340, -340, -340, -340, -340, -340, -340, -340,
-     -340, -340, -340, -340, -340, -340, -340, -340
-    },
-
-    {
-       67, -341, -341, -341, -341, -341, -341, -341, -341, -341,
-     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
-     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
-     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
-     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
-     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
-     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
-
-     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
-     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
-     -341, -341, -341, -341, -341,  480, -341, -341, -341, -341,
-     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
-     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
-     -341, -341, -341, -341, -341, -341, -341, -341
-    },
-
-    {
-       67, -342, -342, -342, -342, -342, -342, -342, -342, -342,
-     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
-     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
-     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
-
-     -342, -342, -342, -342, -342, -342, -342, -342, -342,  481,
-      481,  481,  481,  481,  481,  481,  481,  481, -342, -342,
-     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
-     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
-     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
-     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
-     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
-     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
-     -342, -342, -342, -342, -342, -342, -342, -342
-    },
-
-    {
-       67, -343, -343, -343, -343, -343, -343, -343, -343, -343,
-
-     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
-     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
-     -343, -343,  482, -343, -343, -343, -343, -343, -343, -343,
-     -343, -343, -343, -343, -343, -343, -343, -343,  483,  483,
-      483,  483,  483,  483,  483,  483,  483,  483, -343, -343,
-     -343, -343, -343, -343, -343,  482,  482,  482,  482,  482,
-      482,  482,  482,  482,  482,  482,  482,  482,  482,  482,
-      482,  482,  482,  482,  482,  482,  482,  482,  482,  482,
-      482, -343, -343, -343, -343, -343, -343, -343, -343, -343,
-     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
-
-     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
-     -343, -343, -343, -343, -343, -343, -343, -343
-    },
-
-    {
-       67, -344, -344, -344, -344, -344, -344, -344, -344, -344,
-     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
-     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
-     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
-     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
-     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
-     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
-     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
-
-     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
-     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
-     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
-     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
-     -344, -344, -344, -344, -344, -344, -344, -344
-    },
-
-    {
-       67, -345, -345, -345, -345, -345, -345, -345, -345, -345,
-     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
-     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
-     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
-     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
-
-     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
-     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
-     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
-     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
-     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
-     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
-     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
-     -345, -345, -345, -345, -345, -345, -345, -345
-    },
-
-    {
-       67, -346, -346, -346, -346, -346, -346, -346, -346, -346,
-     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
-
-     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
-     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
-     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
-     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
-     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
-     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
-     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
-     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
-     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
-     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
-
-     -346, -346, -346, -346, -346, -346, -346, -346
-    },
-
-    {
-       67, -347, -347, -347, -347, -347, -347, -347, -347, -347,
-     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
-     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
-     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
-     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
-     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
-     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
-     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
-     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
-
-     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
-     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
-     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
-     -347, -347, -347, -347, -347, -347, -347, -347
-    },
-
-    {
-       67, -348, -348, -348, -348, -348, -348, -348, -348, -348,
-     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
-     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
-     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
-     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
-     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
-
-     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
-     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
-     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
-     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
-     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
-     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
-     -348, -348, -348, -348, -348, -348, -348, -348
-    },
-
-    {
-       67, -349, -349, -349, -349, -349, -349, -349, -349, -349,
-     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
-     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
-
-     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
-     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
-     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
-     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
-     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
-     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
-     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
-     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
-     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
-     -349, -349, -349, -349, -349, -349, -349, -349
-
-    },
-
-    {
-       67, -350, -350, -350, -350, -350, -350, -350, -350, -350,
-     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
-     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
-     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
-     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
-     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
-     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
-     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
-     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
-     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
-
-     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
-     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
-     -350, -350, -350, -350, -350, -350, -350, -350
-    },
-
-    {
-       67, -351, -351, -351, -351, -351, -351, -351, -351, -351,
-     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
-     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
-     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
-     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
-     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
-     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
-
-     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
-     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
-     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
-     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
-     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
-     -351, -351, -351, -351, -351, -351, -351, -351
-    },
-
-    {
-       67, -352, -352, -352, -352, -352, -352, -352, -352, -352,
-     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
-     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
-     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
-
-     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
-     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
-     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
-     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
-     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
-     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
-     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
-     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
-     -352, -352, -352, -352, -352, -352, -352, -352
-    },
-
-    {
-       67, -353, -353, -353, -353, -353, -353, -353, -353, -353,
-
-     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
-     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
-     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
-     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
-     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
-     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
-     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
-     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
-     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
-     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
-
-     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
-     -353, -353, -353, -353, -353, -353, -353, -353
-    },
-
-    {
-       67, -354, -354, -354, -354, -354, -354, -354, -354, -354,
-     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
-     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
-     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
-     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
-     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
-     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
-     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
-
-     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
-     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
-     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
-     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
-     -354, -354, -354, -354, -354, -354, -354, -354
-    },
-
-    {
-       67, -355, -355, -355, -355, -355, -355, -355, -355, -355,
-     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
-     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
-     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
-     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
-
-     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
-     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
-     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
-     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
-     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
-     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
-     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
-     -355, -355, -355, -355, -355, -355, -355, -355
-    },
-
-    {
-       67, -356, -356, -356, -356, -356, -356, -356, -356, -356,
-     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
-
-     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
-     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
-     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
-     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
-     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
-     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
-     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
-     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
-     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
-     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
-
-     -356, -356, -356, -356, -356, -356, -356, -356
-    },
-
-    {
-       67, -357, -357, -357, -357, -357, -357, -357, -357, -357,
-     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
-     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
-     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
-     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
-     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
-     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
-     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
-     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
-
-     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
-     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
-     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
-     -357, -357, -357, -357, -357, -357, -357, -357
-    },
-
-    {
-       67, -358, -358, -358, -358, -358, -358, -358, -358, -358,
-     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
-     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
-     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
-     -358, -358, -358, -358, -358, -358, -358, -358,  484,  484,
-      484,  484,  484,  484,  484,  484,  484,  484, -358, -358,
-
-     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
-     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
-     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
-     -358, -358, -358, -358, -358,  485, -358, -358, -358, -358,
-     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
-     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
-     -358, -358, -358, -358, -358, -358, -358, -358
-    },
-
-    {
-       67, -359, -359, -359, -359, -359, -359, -359, -359, -359,
-     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
-     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
-
-     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
-     -359, -359, -359, -359, -359, -359, -359, -359,  486,  487,
-      487,  487,  487,  487,  487,  487,  487,  487, -359, -359,
-     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
-     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
-     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
-     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
-     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
-     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
-     -359, -359, -359, -359, -359, -359, -359, -359
-
-    },
-
-    {
-       67, -360, -360, -360, -360, -360, -360, -360, -360, -360,
-     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
-     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
-     -360, -360,  488, -360, -360, -360, -360, -360, -360, -360,
-     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
-     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
-     -360, -360, -360, -360, -360,  488,  488,  488,  488,  488,
-      488,  488,  488,  488,  488,  488,  488,  488,  488,  488,
-      488,  488,  488,  488,  488,  488,  488,  488,  488,  488,
-      488, -360, -360, -360, -360, -360, -360, -360, -360, -360,
-
-     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
-     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
-     -360, -360, -360, -360, -360, -360, -360, -360
-    },
-
-    {
-       67, -361, -361, -361, -361, -361, -361, -361, -361, -361,
-     -361, -361, -361, -361, -361, -361, -361, -361, -361, -361,
-     -361, -361, -361, -361, -361, -361, -361, -361, -361, -361,
-     -361, -361,  488, -361, -361, -361, -361, -361, -361, -361,
-     -361, -361, -361, -361, -361, -361, -361, -361,  489,  489,
-      489,  489,  489,  489,  489,  489,  489,  489, -361, -361,
-     -361, -361, -361, -361, -361,  488,  488,  488,  488,  488,
-
-      488,  488,  488,  488,  488,  488,  488,  488,  488,  488,
-      488,  488,  488,  488,  488,  488,  488,  488,  488,  488,
-      488, -361, -361, -361, -361, -361, -361, -361, -361, -361,
-     -361, -361, -361, -361, -361, -361, -361, -361, -361, -361,
-     -361, -361, -361, -361, -361, -361, -361, -361, -361, -361,
-     -361, -361, -361, -361, -361, -361, -361, -361
-    },
-
-    {
-       67, -362, -362, -362, -362, -362, -362, -362, -362, -362,
-     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
-     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
-     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
-
-     -362, -362, -362, -362, -362, -362, -362, -362,  490,  490,
-      490,  490,  490,  490,  490,  490,  490,  490, -362, -362,
-     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
-     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
-     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
-     -362, -362, -362, -362, -362,  491, -362, -362, -362, -362,
-     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
-     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
-     -362, -362, -362, -362, -362, -362, -362, -362
-    },
-
-    {
-       67, -363, -363, -363, -363, -363, -363, -363, -363, -363,
-
-     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
-     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
-     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
-     -363, -363, -363, -363, -363, -363, -363, -363,  492,  493,
-      493,  493,  493,  493,  493,  493,  493,  493, -363, -363,
-     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
-     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
-     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
-     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
-     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
-
-     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
-     -363, -363, -363, -363, -363, -363, -363, -363
-    },
-
-    {
-       67, -364, -364, -364, -364, -364, -364, -364, -364, -364,
-     -364, -364, -364, -364, -364, -364, -364, -364, -364, -364,
-     -364, -364, -364, -364, -364, -364, -364, -364, -364, -364,
-     -364, -364,  494, -364, -364, -364, -364, -364, -364, -364,
-     -364, -364, -364, -364, -364, -364, -364, -364, -364, -364,
-     -364, -364, -364, -364, -364, -364, -364, -364, -364, -364,
-     -364, -364, -364, -364, -364,  494,  494,  494,  494,  494,
-      494,  494,  494,  494,  494,  494,  494,  494,  494,  494,
-
-      494,  494,  494,  494,  494,  494,  494,  494,  494,  494,
-      494, -364, -364, -364, -364, -364, -364, -364, -364, -364,
-     -364, -364, -364, -364, -364, -364, -364, -364, -364, -364,
-     -364, -364, -364, -364, -364, -364, -364, -364, -364, -364,
-     -364, -364, -364, -364, -364, -364, -364, -364
-    },
-
-    {
-       67, -365, -365, -365, -365, -365, -365, -365, -365, -365,
-     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
-     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
-     -365, -365,  494, -365, -365, -365, -365, -365, -365, -365,
-     -365, -365, -365, -365, -365, -365, -365, -365,  495,  495,
-
-      495,  495,  495,  495,  495,  495,  495,  495, -365, -365,
-     -365, -365, -365, -365, -365,  494,  494,  494,  494,  494,
-      494,  494,  494,  494,  494,  494,  494,  494,  494,  494,
-      494,  494,  494,  494,  494,  494,  494,  494,  494,  494,
-      494, -365, -365, -365, -365, -365, -365, -365, -365, -365,
-     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
-     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
-     -365, -365, -365, -365, -365, -365, -365, -365
-    },
-
-    {
-       67, -366, -366, -366, -366, -366, -366, -366, -366, -366,
-     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
-
-     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
-     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
-     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
-     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
-     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
-     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
-     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
-     -366, -366, -366, -366, -366,  496, -366, -366, -366, -366,
-     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
-     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
-
-     -366, -366, -366, -366, -366, -366, -366, -366
-    },
-
-    {
-       67, -367, -367, -367, -367, -367, -367, -367, -367, -367,
-     -367, -367, -367, -367, -367, -367, -367, -367, -367, -367,
-     -367, -367, -367, -367, -367, -367, -367, -367, -367, -367,
-     -367, -367, -367, -367, -367, -367, -367, -367, -367, -367,
-     -367, -367, -367, -367, -367, -367, -367, -367,  497,  498,
-      498,  498,  498,  498,  498,  498,  498,  498, -367, -367,
-     -367, -367, -367, -367, -367, -367, -367, -367, -367, -367,
-     -367, -367, -367, -367, -367, -367, -367, -367, -367, -367,
-     -367, -367, -367, -367, -367, -367, -367, -367, -367, -367,
-
-     -367, -367, -367, -367, -367, -367, -367, -367, -367, -367,
-     -367, -367, -367, -367, -367, -367, -367, -367, -367, -367,
-     -367, -367, -367, -367, -367, -367, -367, -367, -367, -367,
-     -367, -367, -367, -367, -367, -367, -367, -367
-    },
-
-    {
-       67, -368, -368, -368, -368, -368, -368, -368, -368, -368,
-     -368, -368, -368, -368, -368, -368, -368, -368, -368, -368,
-     -368, -368, -368, -368, -368, -368, -368, -368, -368, -368,
-     -368, -368,  499, -368, -368, -368, -368, -368, -368, -368,
-     -368, -368, -368, -368, -368, -368, -368, -368, -368, -368,
-     -368, -368, -368, -368, -368, -368, -368, -368, -368, -368,
-
-     -368, -368, -368, -368, -368,  499,  499,  499,  499,  499,
-      499,  499,  499,  499,  499,  499,  499,  499,  499,  499,
-      499,  499,  499,  499,  499,  499,  499,  499,  499,  499,
-      499, -368, -368, -368, -368, -368, -368, -368, -368, -368,
-     -368, -368, -368, -368, -368, -368, -368, -368, -368, -368,
-     -368, -368, -368, -368, -368, -368, -368, -368, -368, -368,
-     -368, -368, -368, -368, -368, -368, -368, -368
-    },
-
-    {
-       67, -369, -369, -369, -369, -369, -369, -369, -369, -369,
-     -369, -369, -369, -369, -369, -369, -369, -369, -369, -369,
-     -369, -369, -369, -369, -369, -369, -369, -369, -369, -369,
-
-     -369, -369,  499, -369, -369, -369, -369, -369, -369, -369,
-     -369, -369, -369, -369, -369, -369, -369, -369,  500,  500,
-      500,  500,  500,  500,  500,  500,  500,  500, -369, -369,
-     -369, -369, -369, -369, -369,  499,  499,  499,  499,  499,
-      499,  499,  499,  499,  499,  499,  499,  499,  499,  499,
-      499,  499,  499,  499,  499,  499,  499,  499,  499,  499,
-      499, -369, -369, -369, -369, -369, -369, -369, -369, -369,
-     -369, -369, -369, -369, -369, -369, -369, -369, -369, -369,
-     -369, -369, -369, -369, -369, -369, -369, -369, -369, -369,
-     -369, -369, -369, -369, -369, -369, -369, -369
-
-    },
-
-    {
-       67, -370, -370, -370, -370, -370, -370, -370, -370, -370,
-     -370, -370, -370, -370, -370, -370, -370, -370, -370, -370,
-     -370, -370, -370, -370, -370, -370, -370, -370, -370, -370,
-     -370, -370, -370, -370, -370, -370, -370, -370, -370, -370,
-     -370, -370, -370, -370, -370, -370, -370, -370,  501,  501,
-      501,  501,  501,  501,  501,  501,  501,  501, -370, -370,
-     -370, -370, -370, -370, -370, -370, -370, -370, -370, -370,
-     -370, -370, -370, -370, -370, -370, -370, -370, -370, -370,
-     -370, -370, -370, -370, -370, -370, -370, -370, -370, -370,
-     -370, -370, -370, -370, -370,  502, -370, -370, -370, -370,
-
-     -370, -370, -370, -370, -370, -370, -370, -370, -370, -370,
-     -370, -370, -370, -370, -370, -370, -370, -370, -370, -370,
-     -370, -370, -370, -370, -370, -370, -370, -370
-    },
-
-    {
-       67, -371, -371, -371, -371, -371, -371, -371, -371, -371,
-     -371, -371, -371, -371, -371, -371, -371, -371, -371, -371,
-     -371, -371, -371, -371, -371, -371, -371, -371, -371, -371,
-     -371, -371, -371, -371, -371, -371, -371, -371, -371, -371,
-     -371, -371, -371, -371, -371, -371, -371, -371,  503,  504,
-      504,  504,  504,  504,  504,  504,  504,  504, -371, -371,
-     -371, -371, -371, -371, -371, -371, -371, -371, -371, -371,
-
-     -371, -371, -371, -371, -371, -371, -371, -371, -371, -371,
-     -371, -371, -371, -371, -371, -371, -371, -371, -371, -371,
-     -371, -371, -371, -371, -371, -371, -371, -371, -371, -371,
-     -371, -371, -371, -371, -371, -371, -371, -371, -371, -371,
-     -371, -371, -371, -371, -371, -371, -371, -371, -371, -371,
-     -371, -371, -371, -371, -371, -371, -371, -371
-    },
-
-    {
-       67, -372, -372, -372, -372, -372, -372, -372, -372, -372,
-     -372, -372, -372, -372, -372, -372, -372, -372, -372, -372,
-     -372, -372, -372, -372, -372, -372, -372, -372, -372, -372,
-     -372, -372,  505, -372, -372, -372, -372, -372, -372, -372,
-
-     -372, -372, -372, -372, -372, -372, -372, -372, -372, -372,
-     -372, -372, -372, -372, -372, -372, -372, -372, -372, -372,
-     -372, -372, -372, -372, -372,  505,  505,  505,  505,  505,
-      505,  505,  505,  505,  505,  505,  505,  505,  505,  505,
-      505,  505,  505,  505,  505,  505,  505,  505,  505,  505,
-      505, -372, -372, -372, -372, -372, -372, -372, -372, -372,
-     -372, -372, -372, -372, -372, -372, -372, -372, -372, -372,
-     -372, -372, -372, -372, -372, -372, -372, -372, -372, -372,
-     -372, -372, -372, -372, -372, -372, -372, -372
-    },
-
-    {
-       67, -373, -373, -373, -373, -373, -373, -373, -373, -373,
-
-     -373, -373, -373, -373, -373, -373, -373, -373, -373, -373,
-     -373, -373, -373, -373, -373, -373, -373, -373, -373, -373,
-     -373, -373,  505, -373, -373, -373, -373, -373, -373, -373,
-     -373, -373, -373, -373, -373, -373, -373, -373,  506,  506,
-      506,  506,  506,  506,  506,  506,  506,  506, -373, -373,
-     -373, -373, -373, -373, -373,  505,  505,  505,  505,  505,
-      505,  505,  505,  505,  505,  505,  505,  505,  505,  505,
-      505,  505,  505,  505,  505,  505,  505,  505,  505,  505,
-      505, -373, -373, -373, -373, -373, -373, -373, -373, -373,
-     -373, -373, -373, -373, -373, -373, -373, -373, -373, -373,
-
-     -373, -373, -373, -373, -373, -373, -373, -373, -373, -373,
-     -373, -373, -373, -373, -373, -373, -373, -373
-    },
-
-    {
-       67, -374, -374, -374, -374, -374, -374, -374, -374, -374,
-     -374, -374, -374, -374, -374, -374, -374, -374, -374, -374,
-     -374, -374, -374, -374, -374, -374, -374, -374, -374, -374,
-     -374, -374, -374, -374, -374, -374, -374, -374, -374, -374,
-     -374, -374, -374, -374, -374, -374, -374, -374, -374, -374,
-     -374, -374, -374, -374, -374, -374, -374, -374, -374, -374,
-     -374, -374, -374, -374, -374, -374, -374, -374, -374, -374,
-     -374, -374, -374, -374, -374, -374, -374, -374, -374, -374,
-
-     -374, -374, -374, -374, -374, -374, -374, -374, -374, -374,
-     -374, -374, -374, -374, -374,  507, -374, -374, -374, -374,
-     -374, -374, -374, -374, -374, -374, -374, -374, -374, -374,
-     -374, -374, -374, -374, -374, -374, -374, -374, -374, -374,
-     -374, -374, -374, -374, -374, -374, -374, -374
-    },
-
-    {
-       67, -375, -375, -375, -375, -375, -375, -375, -375, -375,
-     -375, -375, -375, -375, -375, -375, -375, -375, -375, -375,
-     -375, -375, -375, -375, -375, -375, -375, -375, -375, -375,
-     -375, -375, -375, -375, -375, -375, -375, -375, -375, -375,
-     -375, -375, -375, -375, -375, -375, -375, -375,  508,  509,
-
-      509,  509,  509,  509,  509,  509,  509,  509, -375, -375,
-     -375, -375, -375, -375, -375, -375, -375, -375, -375, -375,
-     -375, -375, -375, -375, -375, -375, -375, -375, -375, -375,
-     -375, -375, -375, -375, -375, -375, -375, -375, -375, -375,
-     -375, -375, -375, -375, -375, -375, -375, -375, -375, -375,
-     -375, -375, -375, -375, -375, -375, -375, -375, -375, -375,
-     -375, -375, -375, -375, -375, -375, -375, -375, -375, -375,
-     -375, -375, -375, -375, -375, -375, -375, -375
-    },
-
-    {
-       67, -376, -376, -376, -376, -376, -376, -376, -376, -376,
-     -376, -376, -376, -376, -376, -376, -376, -376, -376, -376,
-
-     -376, -376, -376, -376, -376, -376, -376, -376, -376, -376,
-     -376, -376,  510, -376, -376, -376, -376, -376, -376, -376,
-     -376, -376, -376, -376, -376, -376, -376, -376, -376, -376,
-     -376, -376, -376, -376, -376, -376, -376, -376, -376, -376,
-     -376, -376, -376, -376, -376,  510,  510,  510,  510,  510,
-      510,  510,  510,  510,  510,  510,  510,  510,  510,  510,
-      510,  510,  510,  510,  510,  510,  510,  510,  510,  510,
-      510, -376, -376, -376, -376, -376, -376, -376, -376, -376,
-     -376, -376, -376, -376, -376, -376, -376, -376, -376, -376,
-     -376, -376, -376, -376, -376, -376, -376, -376, -376, -376,
-
-     -376, -376, -376, -376, -376, -376, -376, -376
-    },
-
-    {
-       67, -377, -377, -377, -377, -377, -377, -377, -377, -377,
-     -377, -377, -377, -377, -377, -377, -377, -377, -377, -377,
-     -377, -377, -377, -377, -377, -377, -377, -377, -377, -377,
-     -377, -377,  510, -377, -377, -377, -377, -377, -377, -377,
-     -377, -377, -377, -377, -377, -377, -377, -377,  511,  511,
-      511,  511,  511,  511,  511,  511,  511,  511, -377, -377,
-     -377, -377, -377, -377, -377,  510,  510,  510,  510,  510,
-      510,  510,  510,  510,  510,  510,  510,  510,  510,  510,
-      510,  510,  510,  510,  510,  510,  510,  510,  510,  510,
-
-      510, -377, -377, -377, -377, -377, -377, -377, -377, -377,
-     -377, -377, -377, -377, -377, -377, -377, -377, -377, -377,
-     -377, -377, -377, -377, -377, -377, -377, -377, -377, -377,
-     -377, -377, -377, -377, -377, -377, -377, -377
-    },
-
-    {
-       67, -378, -378, -378, -378, -378, -378, -378, -378, -378,
-     -378, -378, -378, -378, -378, -378, -378, -378, -378, -378,
-     -378, -378, -378, -378, -378, -378, -378, -378, -378, -378,
-     -378, -378, -378, -378, -378, -378, -378, -378, -378, -378,
-     -378, -378, -378, -378, -378, -378, -378, -378, -378, -378,
-     -378, -378, -378, -378, -378, -378, -378, -378, -378, -378,
-
-     -378, -378, -378, -378, -378, -378, -378, -378, -378, -378,
-     -378, -378, -378, -378, -378, -378, -378, -378, -378, -378,
-     -378, -378, -378, -378, -378, -378, -378, -378, -378, -378,
-     -378, -378, -378, -378, -378, -378, -378, -378, -378, -378,
-     -378, -378, -378, -378, -378, -378, -378, -378, -378, -378,
-     -378, -378, -378, -378, -378, -378, -378, -378, -378, -378,
-     -378, -378, -378, -378, -378, -378, -378, -378
-    },
-
-    {
-       67, -379, -379, -379, -379, -379, -379, -379, -379, -379,
-     -379, -379, -379, -379, -379, -379, -379, -379, -379, -379,
-     -379, -379, -379, -379, -379, -379, -379, -379, -379, -379,
-
-     -379, -379,  512, -379, -379, -379, -379, -379, -379, -379,
-     -379, -379, -379, -379, -379, -379, -379, -379, -379, -379,
-     -379, -379, -379, -379, -379, -379, -379, -379, -379, -379,
-     -379, -379, -379, -379, -379, -379, -379, -379, -379, -379,
-     -379, -379, -379, -379, -379, -379, -379, -379, -379, -379,
-     -379, -379, -379, -379, -379, -379, -379, -379, -379, -379,
-     -379, -379, -379, -379, -379, -379, -379, -379, -379, -379,
-     -379, -379, -379, -379, -379, -379, -379, -379, -379, -379,
-     -379, -379, -379, -379, -379, -379, -379, -379, -379, -379,
-     -379, -379, -379, -379, -379, -379, -379, -379
-
-    },
-
-    {
-       67, -380, -380, -380, -380, -380, -380, -380, -380, -380,
-     -380, -380, -380, -380, -380, -380, -380, -380, -380, -380,
-     -380, -380, -380, -380, -380, -380, -380, -380, -380, -380,
-     -380, -380,  513, -380, -380, -380, -380, -380, -380, -380,
-     -380, -380, -380, -380, -380, -380, -380, -380, -380, -380,
-     -380, -380, -380, -380, -380, -380, -380, -380, -380, -380,
-     -380, -380, -380, -380, -380, -380, -380, -380, -380, -380,
-     -380, -380, -380, -380, -380, -380, -380, -380, -380, -380,
-     -380, -380, -380, -380, -380, -380, -380, -380, -380, -380,
-     -380, -380, -380, -380, -380, -380, -380, -380, -380, -380,
-
-     -380, -380, -380, -380, -380, -380, -380, -380, -380, -380,
-     -380, -380, -380, -380, -380, -380, -380, -380, -380, -380,
-     -380, -380, -380, -380, -380, -380, -380, -380
-    },
-
-    {
-       67, -381, -381, -381, -381, -381, -381, -381, -381, -381,
-     -381, -381, -381, -381, -381, -381, -381, -381, -381, -381,
-     -381, -381, -381, -381, -381, -381, -381, -381, -381, -381,
-     -381, -381,  514, -381, -381, -381, -381, -381, -381, -381,
-     -381, -381, -381, -381, -381, -381, -381, -381, -381, -381,
-     -381, -381, -381, -381, -381, -381, -381, -381, -381, -381,
-     -381, -381, -381, -381, -381,  514,  514,  514,  514,  514,
-
-      514,  514,  514,  514,  514,  514,  514,  514,  514,  514,
-      514,  514,  514,  514,  514,  514,  514,  514,  514,  514,
-      514, -381, -381, -381, -381, -381, -381, -381, -381, -381,
-     -381, -381, -381, -381, -381, -381, -381, -381, -381, -381,
-     -381, -381, -381, -381, -381, -381, -381, -381, -381, -381,
-     -381, -381, -381, -381, -381, -381, -381, -381
-    },
-
-    {
-       67, -382, -382, -382, -382, -382, -382, -382, -382, -382,
-     -382, -382, -382, -382, -382, -382, -382, -382, -382, -382,
-     -382, -382, -382, -382, -382, -382, -382, -382, -382, -382,
-     -382, -382, -382, -382, -382, -382, -382, -382, -382, -382,
-
-     -382, -382, -382, -382, -382, -382, -382, -382, -382, -382,
-     -382, -382, -382, -382, -382, -382, -382, -382, -382, -382,
-     -382, -382, -382, -382, -382, -382, -382, -382, -382, -382,
-     -382, -382, -382, -382, -382, -382, -382, -382, -382, -382,
-     -382, -382, -382, -382, -382, -382, -382, -382, -382, -382,
-     -382, -382, -382, -382, -382, -382, -382, -382, -382, -382,
-     -382, -382, -382, -382, -382, -382, -382, -382, -382, -382,
-     -382, -382, -382, -382, -382, -382, -382, -382, -382, -382,
-     -382, -382, -382, -382, -382, -382, -382, -382
-    },
-
-    {
-       67, -383, -383, -383, -383, -383, -383, -383, -383, -383,
-
-     -383, -383, -383, -383, -383, -383, -383, -383, -383, -383,
-     -383, -383, -383, -383, -383, -383, -383, -383, -383, -383,
-     -383, -383, -383, -383, -383, -383, -383, -383, -383, -383,
-     -383, -383, -383, -383, -383, -383, -383, -383, -383, -383,
-     -383, -383, -383, -383, -383, -383, -383, -383, -383, -383,
-     -383, -383, -383, -383, -383, -383, -383, -383, -383, -383,
-     -383, -383, -383, -383, -383, -383, -383, -383, -383, -383,
-     -383, -383, -383, -383, -383, -383, -383, -383, -383, -383,
-     -383, -383, -383, -383, -383, -383, -383, -383, -383, -383,
-     -383, -383, -383, -383, -383, -383, -383, -383, -383, -383,
-
-     -383, -383, -383, -383, -383, -383, -383, -383, -383, -383,
-     -383, -383, -383, -383, -383, -383, -383, -383
-    },
-
-    {
-       67, -384, -384, -384, -384, -384, -384, -384, -384, -384,
-     -384, -384, -384, -384, -384, -384, -384, -384, -384, -384,
-     -384, -384, -384, -384, -384, -384, -384, -384, -384, -384,
-     -384, -384, -384, -384, -384, -384, -384, -384, -384, -384,
-     -384, -384, -384, -384, -384, -384, -384, -384, -384, -384,
-     -384, -384, -384, -384, -384, -384, -384, -384, -384, -384,
-     -384, -384, -384, -384, -384, -384, -384, -384, -384, -384,
-     -384, -384, -384, -384, -384, -384, -384, -384, -384, -384,
-
-     -384, -384, -384, -384, -384, -384, -384, -384, -384, -384,
-     -384, -384, -384, -384, -384, -384, -384, -384, -384, -384,
-     -384, -384, -384, -384, -384, -384, -384, -384, -384, -384,
-     -384, -384, -384, -384, -384, -384, -384, -384, -384, -384,
-     -384, -384, -384, -384, -384, -384, -384, -384
-    },
-
-    {
-       67, -385, -385, -385, -385, -385, -385, -385, -385, -385,
-     -385, -385, -385, -385, -385, -385, -385, -385, -385, -385,
-     -385, -385, -385, -385, -385, -385, -385, -385, -385, -385,
-     -385, -385,  515, -385, -385, -385, -385, -385, -385, -385,
-     -385, -385, -385, -385, -385, -385, -385, -385, -385, -385,
-
-     -385, -385, -385, -385, -385, -385, -385, -385, -385, -385,
-     -385, -385, -385, -385, -385, -385, -385, -385, -385, -385,
-     -385, -385, -385, -385, -385, -385, -385, -385, -385, -385,
-     -385, -385, -385, -385, -385, -385, -385, -385, -385, -385,
-     -385, -385, -385, -385, -385, -385, -385, -385, -385, -385,
-     -385, -385, -385, -385, -385, -385, -385, -385, -385, -385,
-     -385, -385, -385, -385, -385, -385, -385, -385, -385, -385,
-     -385, -385, -385, -385, -385, -385, -385, -385
-    },
-
-    {
-       67, -386, -386, -386, -386, -386, -386, -386, -386, -386,
-     -386, -386, -386, -386, -386, -386, -386, -386, -386, -386,
-
-     -386, -386, -386, -386, -386, -386, -386, -386, -386, -386,
-     -386, -386,  516, -386, -386, -386, -386, -386, -386, -386,
-     -386, -386, -386, -386, -386, -386, -386, -386, -386, -386,
-     -386, -386, -386, -386, -386, -386, -386, -386, -386, -386,
-     -386, -386, -386, -386, -386, -386, -386, -386, -386, -386,
-     -386, -386, -386, -386, -386, -386, -386, -386, -386, -386,
-     -386, -386, -386, -386, -386, -386, -386, -386, -386, -386,
-     -386, -386, -386, -386, -386, -386, -386, -386, -386, -386,
-     -386, -386, -386, -386, -386, -386, -386, -386, -386, -386,
-     -386, -386, -386, -386, -386, -386, -386, -386, -386, -386,
-
-     -386, -386, -386, -386, -386, -386, -386, -386
-    },
-
-    {
-       67, -387, -387, -387, -387, -387, -387, -387, -387, -387,
-     -387, -387, -387, -387, -387, -387, -387, -387, -387, -387,
-     -387, -387, -387, -387, -387, -387, -387, -387, -387, -387,
-     -387, -387,  517, -387, -387, -387, -387, -387, -387, -387,
-     -387, -387, -387, -387, -387, -387, -387, -387,  518,  518,
-      518,  518,  518,  518,  518,  518,  518,  518, -387, -387,
-     -387, -387, -387, -387, -387, -387, -387, -387, -387, -387,
-     -387, -387, -387, -387, -387, -387, -387, -387, -387, -387,
-     -387, -387, -387, -387, -387, -387, -387, -387, -387, -387,
-
-     -387, -387, -387, -387, -387, -387, -387, -387, -387, -387,
-     -387, -387, -387, -387, -387, -387, -387, -387, -387, -387,
-     -387, -387, -387, -387, -387, -387, -387, -387, -387, -387,
-     -387, -387, -387, -387, -387, -387, -387, -387
-    },
-
-    {
-       67, -388, -388, -388, -388, -388, -388, -388, -388, -388,
-     -388, -388, -388, -388, -388, -388, -388, -388, -388, -388,
-     -388, -388, -388, -388, -388, -388, -388, -388, -388, -388,
-     -388, -388, -388, -388, -388, -388, -388, -388, -388, -388,
-     -388, -388, -388, -388, -388, -388, -388, -388, -388, -388,
-     -388, -388, -388, -388, -388, -388, -388, -388, -388, -388,
-
-     -388, -388, -388, -388, -388, -388, -388, -388, -388, -388,
-     -388, -388, -388, -388, -388, -388, -388, -388, -388, -388,
-     -388, -388, -388, -388, -388, -388, -388, -388, -388, -388,
-     -388, -388, -388, -388, -388, -388, -388, -388, -388, -388,
-     -388, -388, -388, -388, -388, -388, -388, -388, -388, -388,
-     -388, -388, -388, -388, -388, -388, -388, -388, -388, -388,
-     -388, -388, -388, -388, -388, -388, -388, -388
-    },
-
-    {
-       67, -389, -389, -389, -389, -389, -389, -389, -389, -389,
-     -389, -389, -389, -389, -389, -389, -389, -389, -389, -389,
-     -389, -389, -389, -389, -389, -389, -389, -389, -389, -389,
-
-     -389, -389, -389, -389, -389, -389, -389, -389, -389, -389,
-     -389, -389, -389, -389, -389, -389, -389, -389, -389, -389,
-     -389, -389, -389, -389, -389, -389, -389, -389, -389, -389,
-     -389, -389, -389, -389, -389, -389, -389, -389, -389, -389,
-     -389, -389, -389, -389, -389, -389, -389, -389, -389, -389,
-     -389, -389, -389, -389, -389, -389, -389, -389, -389, -389,
-     -389, -389, -389, -389, -389, -389, -389, -389, -389, -389,
-     -389, -389, -389, -389, -389, -389, -389, -389, -389, -389,
-     -389, -389, -389, -389, -389, -389, -389, -389, -389, -389,
-     -389, -389, -389, -389, -389, -389, -389, -389
-
-    },
-
-    {
-       67, -390, -390, -390, -390, -390, -390, -390, -390, -390,
-     -390, -390, -390, -390, -390, -390, -390, -390, -390, -390,
-     -390, -390, -390, -390, -390, -390, -390, -390, -390, -390,
-     -390, -390, -390, -390, -390, -390, -390, -390, -390, -390,
-     -390, -390, -390, -390, -390, -390, -390, -390, -390, -390,
-     -390, -390, -390, -390, -390, -390, -390, -390, -390, -390,
-     -390, -390, -390, -390, -390, -390, -390, -390, -390, -390,
-     -390, -390, -390, -390, -390, -390, -390, -390, -390, -390,
-     -390, -390, -390, -390, -390, -390, -390, -390, -390, -390,
-     -390, -390, -390, -390, -390, -390, -390, -390, -390, -390,
-
-     -390, -390, -390, -390, -390, -390, -390, -390, -390, -390,
-     -390, -390, -390, -390, -390, -390, -390, -390, -390, -390,
-     -390, -390, -390, -390, -390, -390, -390, -390
-    },
-
-    {
-       67, -391, -391, -391, -391, -391, -391, -391, -391, -391,
-     -391, -391, -391, -391, -391, -391, -391, -391, -391, -391,
-     -391, -391, -391, -391, -391, -391, -391, -391, -391, -391,
-     -391, -391, -391, -391, -391, -391, -391, -391, -391, -391,
-     -391, -391, -391, -391, -391, -391, -391, -391,  391,  391,
-      391,  391,  391,  391,  391,  391,  391,  391, -391, -391,
-     -391, -391, -391, -391, -391, -391, -391, -391, -391,  246,
-
-     -391, -391, -391, -391, -391, -391, -391, -391, -391, -391,
-     -391, -391, -391, -391, -391, -391, -391, -391, -391, -391,
-     -391, -391, -391, -391, -391, -391, -391, -391, -391, -391,
-     -391,  246, -391, -391, -391, -391, -391, -391, -391, -391,
-     -391, -391, -391, -391, -391, -391, -391, -391, -391, -391,
-     -391, -391, -391, -391, -391, -391, -391, -391
-    },
-
-    {
-       67, -392, -392, -392, -392, -392, -392, -392, -392, -392,
-     -392, -392, -392, -392, -392, -392, -392, -392, -392, -392,
-     -392, -392, -392, -392, -392, -392, -392, -392, -392, -392,
-     -392, -392, -392, -392, -392, -392, -392, -392, -392, -392,
-
-     -392, -392, -392, -392, -392, -392, -392, -392,  393,  393,
-      393,  393,  393,  393,  393,  393,  393,  393, -392, -392,
-     -392, -392, -392, -392, -392, -392, -392, -392, -392, -392,
-     -392, -392, -392, -392, -392, -392, -392, -392, -392, -392,
-     -392, -392, -392, -392, -392, -392, -392, -392, -392, -392,
-     -392, -392, -392, -392, -392, -392, -392, -392, -392, -392,
-     -392, -392, -392, -392, -392, -392, -392, -392, -392, -392,
-     -392, -392, -392, -392, -392, -392, -392, -392, -392, -392,
-     -392, -392, -392, -392, -392, -392, -392, -392
-    },
-
-    {
-       67, -393, -393, -393, -393, -393, -393, -393, -393, -393,
-
-     -393, -393, -393, -393, -393, -393, -393, -393, -393, -393,
-     -393, -393, -393, -393, -393, -393, -393, -393, -393, -393,
-     -393, -393, -393, -393, -393, -393, -393, -393, -393, -393,
-     -393, -393, -393, -393, -393, -393, -393, -393,  393,  393,
-      393,  393,  393,  393,  393,  393,  393,  393, -393, -393,
-     -393, -393, -393, -393, -393, -393, -393, -393, -393, -393,
-     -393, -393, -393, -393, -393, -393, -393, -393, -393, -393,
-     -393, -393, -393, -393, -393, -393, -393, -393, -393, -393,
-     -393, -393, -393, -393, -393, -393, -393, -393, -393, -393,
-     -393, -393, -393, -393, -393, -393, -393, -393, -393, -393,
-
-     -393, -393, -393, -393, -393, -393, -393, -393, -393, -393,
-     -393, -393, -393, -393, -393, -393, -393, -393
-    },
-
-    {
-       67, -394, -394, -394, -394, -394, -394, -394, -394, -394,
-     -394, -394, -394, -394, -394, -394, -394, -394, -394, -394,
-     -394, -394, -394, -394, -394, -394, -394, -394, -394, -394,
-     -394, -394, -394, -394, -394, -394, -394, -394, -394, -394,
-     -394, -394, -394, -394, -394, -394, -394, -394, -394, -394,
-     -394, -394, -394, -394, -394, -394, -394, -394, -394, -394,
-     -394, -394, -394, -394, -394, -394, -394, -394, -394, -394,
-     -394, -394, -394, -394, -394, -394, -394, -394, -394, -394,
-
-     -394, -394, -394, -394, -394, -394, -394, -394, -394, -394,
-     -394, -394, -394, -394, -394, -394, -394, -394, -394, -394,
-     -394, -394, -394, -394, -394, -394, -394, -394, -394, -394,
-     -394, -394, -394, -394, -394, -394, -394, -394, -394, -394,
-     -394, -394, -394, -394, -394, -394, -394, -394
-    },
-
-    {
-       67, -395, -395, -395, -395, -395, -395, -395, -395, -395,
-     -395, -395, -395, -395, -395, -395, -395, -395, -395, -395,
-     -395, -395, -395, -395, -395, -395, -395, -395, -395, -395,
-     -395, -395, -395, -395, -395, -395, -395, -395, -395, -395,
-     -395, -395, -395, -395, -395, -395, -395, -395, -395, -395,
-
-     -395, -395, -395, -395, -395, -395, -395, -395, -395, -395,
-     -395, -395, -395, -395, -395, -395, -395, -395, -395, -395,
-     -395, -395, -395, -395, -395, -395, -395, -395, -395, -395,
-     -395, -395, -395, -395, -395, -395, -395, -395, -395, -395,
-     -395, -395, -395, -395, -395, -395, -395, -395, -395, -395,
-     -395, -395, -395, -395, -395, -395, -395, -395, -395, -395,
-     -395, -395, -395, -395, -395, -395, -395, -395, -395, -395,
-     -395, -395, -395, -395, -395, -395, -395, -395
-    },
-
-    {
-       67, -396, -396, -396, -396, -396, -396, -396, -396, -396,
-     -396, -396, -396, -396, -396, -396, -396, -396, -396, -396,
-
-     -396, -396, -396, -396, -396, -396, -396, -396, -396, -396,
-     -396, -396, -396, -396, -396, -396, -396, -396, -396, -396,
-     -396, -396, -396, -396, -396, -396, -396, -396, -396, -396,
-     -396, -396, -396, -396, -396, -396, -396, -396, -396, -396,
-     -396, -396, -396, -396, -396, -396, -396, -396, -396, -396,
-     -396, -396, -396, -396, -396, -396, -396, -396, -396, -396,
-     -396, -396, -396, -396, -396, -396, -396, -396, -396, -396,
-     -396, -396, -396, -396, -396, -396, -396, -396, -396, -396,
-     -396, -396, -396, -396, -396, -396, -396, -396, -396, -396,
-     -396, -396, -396, -396, -396, -396, -396, -396, -396, -396,
-
-     -396, -396, -396, -396, -396, -396, -396, -396
-    },
-
-    {
-       67, -397, -397, -397, -397, -397, -397, -397, -397, -397,
-     -397, -397, -397, -397, -397, -397, -397, -397, -397, -397,
-     -397, -397, -397, -397, -397, -397, -397, -397, -397, -397,
-     -397, -397, -397, -397, -397, -397, -397, -397, -397, -397,
-     -397, -397, -397, -397, -397, -397, -397, -397, -397, -397,
-     -397, -397, -397, -397, -397, -397, -397, -397, -397, -397,
-     -397, -397, -397, -397, -397, -397, -397, -397, -397, -397,
-     -397, -397, -397, -397, -397, -397, -397, -397, -397, -397,
-     -397, -397, -397, -397,  519, -397, -397, -397, -397, -397,
-
-     -397, -397, -397, -397, -397, -397, -397, -397, -397, -397,
-     -397, -397, -397, -397, -397, -397, -397, -397, -397, -397,
-     -397, -397, -397, -397, -397, -397, -397, -397, -397, -397,
-     -397, -397, -397, -397, -397, -397, -397, -397
-    },
-
-    {
-       67, -398, -398, -398, -398, -398, -398, -398, -398, -398,
-     -398, -398, -398, -398, -398, -398, -398, -398, -398, -398,
-     -398, -398, -398, -398, -398, -398, -398, -398, -398, -398,
-     -398, -398, -398, -398, -398, -398, -398, -398, -398, -398,
-     -398, -398, -398, -398, -398, -398, -398, -398, -398, -398,
-     -398, -398, -398, -398, -398, -398, -398, -398, -398, -398,
-
-     -398, -398, -398, -398, -398, -398, -398, -398, -398, -398,
-     -398, -398, -398, -398, -398, -398, -398,  520, -398, -398,
-     -398, -398, -398, -398, -398, -398, -398, -398, -398, -398,
-     -398, -398, -398, -398, -398, -398, -398, -398, -398, -398,
-     -398, -398, -398, -398, -398, -398, -398, -398, -398, -398,
-     -398, -398, -398, -398, -398, -398, -398, -398, -398, -398,
-     -398, -398, -398, -398, -398, -398, -398, -398
-    },
-
-    {
-       67, -399, -399, -399, -399, -399, -399, -399, -399, -399,
-     -399, -399, -399, -399, -399, -399, -399, -399, -399, -399,
-     -399, -399, -399, -399, -399, -399, -399, -399, -399, -399,
-
-     -399, -399, -399, -399, -399, -399, -399, -399, -399, -399,
-     -399, -399, -399, -399, -399, -399, -399, -399, -399, -399,
-     -399, -399, -399, -399, -399, -399, -399, -399, -399, -399,
-     -399, -399, -399, -399, -399, -399, -399, -399, -399,  521,
-     -399, -399, -399, -399, -399, -399, -399, -399, -399, -399,
-     -399, -399, -399, -399, -399, -399, -399, -399, -399, -399,
-     -399, -399, -399, -399, -399, -399, -399, -399, -399, -399,
-     -399, -399, -399, -399, -399, -399, -399, -399, -399, -399,
-     -399, -399, -399, -399, -399, -399, -399, -399, -399, -399,
-     -399, -399, -399, -399, -399, -399, -399, -399
-
-    },
-
-    {
-       67, -400, -400, -400, -400, -400, -400, -400, -400, -400,
-     -400, -400, -400, -400, -400, -400, -400, -400, -400, -400,
-     -400, -400, -400, -400, -400, -400, -400, -400, -400, -400,
-     -400, -400, -400, -400, -400, -400, -400, -400, -400, -400,
-     -400, -400, -400, -400, -400, -400, -400, -400, -400, -400,
-     -400, -400, -400, -400, -400, -400, -400, -400, -400, -400,
-     -400, -400, -400, -400, -400, -400, -400, -400, -400, -400,
-     -400, -400, -400, -400, -400, -400, -400, -400, -400, -400,
-     -400, -400, -400, -400,  522, -400, -400, -400, -400, -400,
-     -400, -400, -400, -400, -400, -400, -400, -400, -400, -400,
-
-     -400, -400, -400, -400, -400, -400, -400, -400, -400, -400,
-     -400, -400, -400, -400, -400, -400, -400, -400, -400, -400,
-     -400, -400, -400, -400, -400, -400, -400, -400
-    },
-
-    {
-       67, -401, -401, -401, -401, -401, -401, -401, -401, -401,
-     -401, -401, -401, -401, -401, -401, -401, -401, -401, -401,
-     -401, -401, -401, -401, -401, -401, -401, -401, -401, -401,
-     -401, -401, -401, -401, -401, -401, -401, -401, -401, -401,
-     -401, -401, -401, -401, -401, -401, -401, -401, -401, -401,
-     -401, -401, -401, -401, -401, -401, -401, -401, -401, -401,
-     -401, -401, -401, -401, -401, -401, -401, -401, -401, -401,
-
-     -401, -401, -401, -401, -401, -401, -401, -401, -401, -401,
-     -401, -401, -401, -401, -401, -401, -401, -401,  523, -401,
-     -401, -401, -401, -401, -401, -401, -401, -401, -401, -401,
-     -401, -401, -401, -401, -401, -401, -401, -401, -401, -401,
-     -401, -401, -401, -401, -401, -401, -401, -401, -401, -401,
-     -401, -401, -401, -401, -401, -401, -401, -401
-    },
-
-    {
-       67, -402, -402, -402, -402, -402, -402, -402, -402, -402,
-     -402, -402, -402, -402, -402, -402, -402, -402, -402, -402,
-     -402, -402, -402, -402, -402, -402, -402, -402, -402, -402,
-     -402, -402, -402, -402, -402, -402, -402, -402, -402, -402,
-
-     -402, -402, -402, -402, -402, -402, -402, -402, -402, -402,
-     -402, -402, -402, -402, -402, -402, -402, -402, -402, -402,
-     -402, -402, -402, -402, -402, -402, -402, -402, -402, -402,
-     -402, -402, -402, -402, -402, -402,  524, -402, -402, -402,
-     -402, -402, -402, -402, -402, -402, -402, -402, -402, -402,
-     -402, -402, -402, -402, -402, -402, -402, -402, -402, -402,
-     -402, -402, -402, -402, -402, -402, -402, -402, -402, -402,
-     -402, -402, -402, -402, -402, -402, -402, -402, -402, -402,
-     -402, -402, -402, -402, -402, -402, -402, -402
-    },
-
-    {
-       67, -403, -403, -403, -403, -403, -403, -403, -403, -403,
-
-     -403, -403, -403, -403, -403, -403, -403, -403, -403, -403,
-     -403, -403, -403, -403, -403, -403, -403, -403, -403, -403,
-     -403, -403, -403, -403, -403, -403, -403, -403, -403, -403,
-     -403, -403, -403, -403, -403, -403, -403, -403, -403, -403,
-     -403, -403, -403, -403, -403, -403, -403, -403, -403, -403,
-     -403, -403, -403, -403, -403, -403, -403, -403, -403,  525,
-     -403, -403, -403, -403, -403, -403, -403, -403, -403, -403,
-     -403, -403, -403, -403, -403, -403, -403, -403, -403, -403,
-     -403, -403, -403, -403, -403, -403, -403, -403, -403, -403,
-     -403, -403, -403, -403, -403, -403, -403, -403, -403, -403,
-
-     -403, -403, -403, -403, -403, -403, -403, -403, -403, -403,
-     -403, -403, -403, -403, -403, -403, -403, -403
-    },
-
-    {
-       67, -404, -404, -404, -404, -404, -404, -404, -404, -404,
-     -404, -404, -404, -404, -404, -404, -404, -404, -404, -404,
-     -404, -404, -404, -404, -404, -404, -404, -404, -404, -404,
-     -404, -404, -404, -404, -404, -404, -404, -404, -404, -404,
-     -404, -404, -404, -404, -404, -404, -404, -404, -404, -404,
-     -404, -404, -404, -404, -404, -404, -404, -404, -404, -404,
-     -404, -404, -404, -404, -404, -404, -404, -404, -404, -404,
-     -404, -404, -404, -404, -404, -404, -404, -404, -404, -404,
-
-      526, -404, -404, -404, -404, -404, -404, -404, -404, -404,
-     -404, -404, -404, -404, -404, -404, -404, -404, -404, -404,
-     -404, -404, -404, -404, -404, -404, -404, -404, -404, -404,
-     -404, -404, -404, -404, -404, -404, -404, -404, -404, -404,
-     -404, -404, -404, -404, -404, -404, -404, -404
-    },
-
-    {
-       67, -405, -405, -405, -405, -405, -405, -405, -405, -405,
-     -405, -405, -405, -405, -405, -405, -405, -405, -405, -405,
-     -405, -405, -405, -405, -405, -405, -405, -405, -405, -405,
-     -405, -405, -405, -405, -405, -405, -405, -405, -405, -405,
-     -405, -405, -405, -405, -405, -405, -405, -405, -405, -405,
-
-     -405, -405, -405, -405, -405, -405, -405, -405, -405, -405,
-     -405, -405, -405, -405, -405, -405, -405, -405, -405, -405,
-     -405, -405, -405,  527, -405, -405, -405, -405, -405, -405,
-     -405, -405, -405, -405, -405, -405, -405, -405, -405, -405,
-     -405, -405, -405, -405, -405, -405, -405, -405, -405, -405,
-     -405, -405, -405, -405, -405, -405, -405, -405, -405, -405,
-     -405, -405, -405, -405, -405, -405, -405, -405, -405, -405,
-     -405, -405, -405, -405, -405, -405, -405, -405
-    },
-
-    {
-       67, -406, -406, -406, -406, -406, -406, -406, -406, -406,
-     -406, -406, -406, -406, -406, -406, -406, -406, -406, -406,
-
-     -406, -406, -406, -406, -406, -406, -406, -406, -406, -406,
-     -406, -406, -406, -406, -406, -406, -406, -406, -406, -406,
-     -406, -406, -406, -406, -406, -406, -406, -406, -406, -406,
-     -406, -406, -406, -406, -406, -406, -406, -406, -406, -406,
-     -406, -406, -406, -406, -406, -406, -406, -406, -406, -406,
-     -406, -406, -406, -406, -406, -406, -406, -406, -406, -406,
-     -406, -406, -406, -406,  528, -406, -406, -406, -406, -406,
-     -406, -406, -406, -406, -406, -406, -406, -406, -406, -406,
-     -406, -406, -406, -406, -406, -406, -406, -406, -406, -406,
-     -406, -406, -406, -406, -406, -406, -406, -406, -406, -406,
-
-     -406, -406, -406, -406, -406, -406, -406, -406
-    },
-
-    {
-       67, -407, -407, -407, -407, -407, -407, -407, -407, -407,
-     -407, -407, -407, -407, -407, -407, -407, -407, -407, -407,
-     -407, -407, -407, -407, -407, -407, -407, -407, -407, -407,
-     -407, -407, -407, -407, -407, -407, -407, -407, -407, -407,
-     -407, -407, -407, -407, -407, -407, -407, -407, -407, -407,
-     -407, -407, -407, -407, -407, -407, -407, -407, -407, -407,
-     -407, -407, -407, -407, -407, -407, -407, -407, -407,  529,
-     -407, -407, -407, -407, -407, -407, -407, -407, -407, -407,
-     -407, -407, -407, -407, -407, -407, -407, -407, -407, -407,
-
-     -407, -407, -407, -407, -407, -407, -407, -407, -407, -407,
-     -407, -407, -407, -407, -407, -407, -407, -407, -407, -407,
-     -407, -407, -407, -407, -407, -407, -407, -407, -407, -407,
-     -407, -407, -407, -407, -407, -407, -407, -407
-    },
-
-    {
-       67, -408, -408, -408, -408, -408, -408, -408, -408, -408,
-     -408, -408, -408, -408, -408, -408, -408, -408, -408, -408,
-     -408, -408, -408, -408, -408, -408, -408, -408, -408, -408,
-     -408, -408, -408, -408, -408, -408, -408, -408, -408, -408,
-     -408, -408, -408, -408, -408, -408, -408, -408, -408, -408,
-     -408, -408, -408, -408, -408, -408, -408, -408, -408, -408,
-
-     -408, -408, -408, -408, -408, -408, -408, -408, -408, -408,
-     -408, -408, -408, -408, -408, -408, -408, -408, -408, -408,
-     -408, -408,  530, -408, -408, -408, -408, -408, -408, -408,
-     -408, -408, -408, -408, -408, -408, -408, -408, -408, -408,
-     -408, -408, -408, -408, -408, -408, -408, -408, -408, -408,
-     -408, -408, -408, -408, -408, -408, -408, -408, -408, -408,
-     -408, -408, -408, -408, -408, -408, -408, -408
-    },
-
-    {
-       67, -409, -409, -409, -409, -409, -409, -409, -409, -409,
-     -409, -409, -409, -409, -409, -409, -409, -409, -409, -409,
-     -409, -409, -409, -409, -409, -409, -409, -409, -409, -409,
-
-     -409, -409, -409, -409, -409, -409, -409, -409, -409, -409,
-     -409, -409, -409, -409, -409, -409, -409, -409, -409, -409,
-     -409, -409, -409, -409, -409, -409, -409, -409, -409, -409,
-     -409, -409, -409, -409, -409,  531, -409, -409, -409, -409,
-     -409, -409, -409, -409, -409, -409, -409, -409, -409, -409,
-     -409, -409, -409, -409, -409, -409, -409, -409, -409, -409,
-     -409, -409, -409, -409, -409, -409, -409, -409, -409, -409,
-     -409, -409, -409, -409, -409, -409, -409, -409, -409, -409,
-     -409, -409, -409, -409, -409, -409, -409, -409, -409, -409,
-     -409, -409, -409, -409, -409, -409, -409, -409
-
-    },
-
-    {
-       67, -410, -410, -410, -410, -410, -410, -410, -410, -410,
-     -410, -410, -410, -410, -410, -410, -410, -410, -410, -410,
-     -410, -410, -410, -410, -410, -410, -410, -410, -410, -410,
-     -410, -410, -410, -410, -410, -410, -410, -410, -410, -410,
-     -410, -410, -410, -410, -410, -410, -410, -410, -410, -410,
-     -410, -410, -410, -410, -410, -410, -410, -410, -410, -410,
-     -410, -410, -410, -410, -410, -410, -410, -410, -410, -410,
-     -410, -410, -410, -410, -410, -410, -410, -410, -410, -410,
-     -410, -410, -410, -410, -410, -410, -410, -410,  532, -410,
-     -410, -410, -410, -410, -410, -410, -410, -410, -410, -410,
-
-     -410, -410, -410, -410, -410, -410, -410, -410, -410, -410,
-     -410, -410, -410, -410, -410, -410, -410, -410, -410, -410,
-     -410, -410, -410, -410, -410, -410, -410, -410
-    },
-
-    {
-       67, -411, -411, -411, -411, -411, -411, -411, -411, -411,
-     -411, -411, -411, -411, -411, -411, -411, -411, -411, -411,
-     -411, -411, -411, -411, -411, -411, -411, -411, -411, -411,
-     -411, -411, -411, -411, -411, -411, -411, -411, -411, -411,
-     -411, -411, -411, -411, -411, -411, -411, -411, -411, -411,
-     -411, -411, -411, -411, -411, -411, -411, -411, -411, -411,
-     -411, -411, -411, -411, -411, -411, -411, -411, -411, -411,
-
-     -411, -411, -411, -411, -411, -411,  533, -411, -411, -411,
-     -411, -411, -411, -411, -411, -411, -411, -411, -411, -411,
-     -411, -411, -411, -411, -411, -411, -411, -411, -411, -411,
-     -411, -411, -411, -411, -411, -411, -411, -411, -411, -411,
-     -411, -411, -411, -411, -411, -411, -411, -411, -411, -411,
-     -411, -411, -411, -411, -411, -411, -411, -411
-    },
-
-    {
-       67, -412, -412, -412, -412, -412, -412, -412, -412, -412,
-     -412, -412, -412, -412, -412, -412, -412, -412, -412, -412,
-     -412, -412, -412, -412, -412, -412, -412, -412, -412, -412,
-     -412, -412, -412, -412, -412, -412, -412, -412, -412, -412,
-
-     -412, -412, -412, -412, -412, -412, -412, -412, -412, -412,
-     -412, -412, -412, -412, -412, -412, -412, -412, -412, -412,
-     -412, -412, -412, -412, -412, -412, -412, -412, -412, -412,
-     -412, -412, -412, -412, -412, -412, -412, -412, -412, -412,
-     -412, -412,  534, -412, -412, -412, -412, -412, -412, -412,
-     -412, -412, -412, -412, -412, -412, -412, -412, -412, -412,
-     -412, -412, -412, -412, -412, -412, -412, -412, -412, -412,
-     -412, -412, -412, -412, -412, -412, -412, -412, -412, -412,
-     -412, -412, -412, -412, -412, -412, -412, -412
-    },
-
-    {
-       67, -413, -413, -413, -413, -413, -413, -413, -413, -413,
-
-     -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
-     -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
-     -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
-     -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
-     -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
-     -413, -413, -413, -413, -413, -413, -413, -413, -413,  535,
-     -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
-     -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
-     -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
-     -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
-
-     -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
-     -413, -413, -413, -413, -413, -413, -413, -413
-    },
-
-    {
-       67, -414, -414, -414, -414, -414, -414, -414, -414, -414,
-     -414, -414, -414, -414, -414, -414, -414, -414, -414, -414,
-     -414, -414, -414, -414, -414, -414, -414, -414, -414, -414,
-     -414, -414, -414, -414, -414, -414, -414, -414, -414, -414,
-     -414, -414, -414, -414, -414, -414, -414, -414, -414, -414,
-     -414, -414, -414, -414, -414, -414, -414, -414, -414, -414,
-     -414, -414, -414, -414, -414, -414, -414, -414, -414, -414,
-     -414, -414, -414, -414, -414, -414, -414, -414, -414, -414,
-
-     -414, -414, -414, -414,  536, -414, -414, -414, -414, -414,
-     -414, -414, -414, -414, -414, -414, -414, -414, -414, -414,
-     -414, -414, -414, -414, -414, -414, -414, -414, -414, -414,
-     -414, -414, -414, -414, -414, -414, -414, -414, -414, -414,
-     -414, -414, -414, -414, -414, -414, -414, -414
-    },
-
-    {
-       67, -415, -415, -415, -415, -415, -415, -415, -415, -415,
-     -415, -415, -415, -415, -415, -415, -415, -415, -415, -415,
-     -415, -415, -415, -415, -415, -415, -415, -415, -415, -415,
-     -415, -415, -415, -415, -415, -415, -415, -415, -415, -415,
-     -415, -415, -415, -415, -415,  537, -415, -415, -415, -415,
-
-     -415, -415, -415, -415, -415, -415, -415, -415, -415, -415,
-     -415, -415, -415, -415, -415, -415, -415, -415, -415, -415,
-     -415, -415, -415, -415, -415, -415, -415, -415, -415, -415,
-     -415, -415, -415, -415, -415, -415, -415, -415, -415, -415,
-     -415, -415, -415, -415, -415, -415, -415, -415, -415, -415,
-     -415, -415, -415, -415, -415, -415, -415, -415, -415, -415,
-     -415, -415, -415, -415, -415, -415, -415, -415, -415, -415,
-     -415, -415, -415, -415, -415, -415, -415, -415
-    },
-
-    {
-       67, -416, -416, -416, -416, -416, -416, -416, -416, -416,
-     -416, -416, -416, -416, -416, -416, -416, -416, -416, -416,
-
-     -416, -416, -416, -416, -416, -416, -416, -416, -416, -416,
-     -416, -416, -416, -416, -416, -416, -416, -416, -416, -416,
-     -416, -416, -416, -416, -416, -416, -416, -416, -416, -416,
-     -416, -416, -416, -416, -416, -416, -416, -416, -416, -416,
-     -416, -416, -416, -416, -416, -416, -416, -416, -416, -416,
-     -416, -416, -416, -416, -416, -416, -416, -416, -416, -416,
-     -416, -416, -416, -416, -416, -416, -416, -416, -416, -416,
-     -416, -416, -416, -416, -416, -416, -416, -416, -416, -416,
-     -416, -416, -416, -416, -416, -416, -416, -416, -416, -416,
-     -416, -416, -416, -416, -416, -416, -416, -416, -416, -416,
-
-     -416, -416, -416, -416, -416, -416, -416, -416
-    },
-
-    {
-       67, -417, -417, -417, -417, -417, -417, -417, -417, -417,
-     -417, -417, -417, -417, -417, -417, -417, -417, -417, -417,
-     -417, -417, -417, -417, -417, -417, -417, -417, -417, -417,
-     -417, -417, -417, -417, -417, -417, -417, -417, -417, -417,
-     -417, -417, -417, -417, -417, -417, -417, -417, -417,  538,
-      538,  538,  538,  538,  538,  538,  538,  538, -417, -417,
-     -417, -417, -417, -417, -417, -417, -417, -417, -417, -417,
-     -417, -417, -417, -417, -417, -417, -417, -417, -417, -417,
-     -417, -417, -417, -417, -417, -417, -417, -417, -417, -417,
-
-     -417, -417, -417, -417, -417, -417, -417, -417, -417, -417,
-     -417, -417, -417, -417, -417, -417, -417, -417, -417, -417,
-     -417, -417, -417, -417, -417, -417, -417, -417, -417, -417,
-     -417, -417, -417, -417, -417, -417, -417, -417
-    },
-
-    {
-       67, -418, -418, -418, -418, -418, -418, -418, -418, -418,
-     -418, -418, -418, -418, -418, -418, -418, -418, -418, -418,
-     -418, -418, -418, -418, -418, -418, -418, -418, -418, -418,
-     -418, -418,  539, -418, -418, -418, -418, -418, -418, -418,
-     -418, -418, -418, -418, -418, -418, -418, -418, -418, -418,
-     -418, -418, -418, -418, -418, -418, -418, -418, -418, -418,
-
-     -418, -418, -418, -418, -418, -418, -418, -418, -418, -418,
-     -418, -418, -418, -418, -418, -418, -418, -418, -418, -418,
-     -418, -418, -418, -418, -418, -418, -418, -418, -418, -418,
-     -418, -418, -418, -418, -418, -418, -418, -418, -418, -418,
-     -418, -418, -418, -418, -418, -418, -418, -418, -418, -418,
-     -418, -418, -418, -418, -418, -418, -418, -418, -418, -418,
-     -418, -418, -418, -418, -418, -418, -418, -418
-    },
-
-    {
-       67, -419, -419, -419, -419, -419, -419, -419, -419, -419,
-     -419, -419, -419, -419, -419, -419, -419, -419, -419, -419,
-     -419, -419, -419, -419, -419, -419, -419, -419, -419, -419,
-
-     -419, -419, -419, -419, -419, -419, -419, -419, -419, -419,
-     -419, -419, -419, -419, -419, -419, -419, -419, -419, -419,
-     -419, -419, -419, -419, -419, -419, -419, -419, -419, -419,
-     -419, -419, -419, -419, -419, -419, -419, -419, -419, -419,
-     -419, -419,  540, -419, -419, -419, -419, -419, -419, -419,
-     -419, -419, -419, -419, -419, -419, -419, -419, -419, -419,
-     -419, -419, -419, -419, -419, -419, -419, -419, -419, -419,
-     -419, -419, -419, -419, -419, -419, -419, -419, -419, -419,
-     -419, -419, -419, -419, -419, -419, -419, -419, -419, -419,
-     -419, -419, -419, -419, -419, -419, -419, -419
-
-    },
-
-    {
-       67, -420, -420, -420, -420, -420, -420, -420, -420, -420,
-     -420, -420, -420, -420, -420, -420, -420, -420, -420, -420,
-     -420, -420, -420, -420, -420, -420, -420, -420, -420, -420,
-     -420, -420, -420, -420, -420, -420, -420, -420, -420, -420,
-     -420, -420, -420, -420, -420, -420, -420, -420, -420, -420,
-     -420, -420, -420, -420, -420, -420, -420, -420, -420, -420,
-     -420, -420, -420, -420, -420, -420, -420, -420, -420, -420,
-     -420, -420, -420, -420, -420, -420, -420, -420,  541, -420,
-     -420, -420, -420, -420, -420, -420, -420, -420, -420, -420,
-     -420, -420, -420, -420, -420, -420, -420, -420, -420, -420,
-
-     -420, -420, -420, -420, -420, -420, -420, -420, -420, -420,
-     -420, -420, -420, -420, -420, -420, -420, -420, -420, -420,
-     -420, -420, -420, -420, -420, -420, -420, -420
-    },
-
-    {
-       67, -421, -421, -421, -421, -421, -421, -421, -421, -421,
-     -421, -421, -421, -421, -421, -421, -421, -421, -421, -421,
-     -421, -421, -421, -421, -421, -421, -421, -421, -421, -421,
-     -421, -421, -421, -421, -421, -421, -421, -421, -421, -421,
-     -421, -421, -421, -421, -421, -421, -421, -421, -421, -421,
-     -421, -421, -421, -421, -421, -421, -421, -421, -421, -421,
-     -421, -421, -421, -421, -421, -421, -421, -421, -421, -421,
-
-     -421, -421, -421, -421, -421, -421, -421, -421, -421,  542,
-     -421, -421, -421, -421, -421, -421, -421, -421, -421, -421,
-     -421, -421, -421, -421, -421, -421, -421, -421, -421, -421,
-     -421, -421, -421, -421, -421, -421, -421, -421, -421, -421,
-     -421, -421, -421, -421, -421, -421, -421, -421, -421, -421,
-     -421, -421, -421, -421, -421, -421, -421, -421
-    },
-
-    {
-       67, -422, -422, -422, -422, -422, -422, -422, -422, -422,
-     -422, -422, -422, -422, -422, -422, -422, -422, -422, -422,
-     -422, -422, -422, -422, -422, -422, -422, -422, -422, -422,
-     -422, -422, -422, -422, -422, -422, -422, -422, -422, -422,
-
-     -422, -422, -422, -422, -422, -422, -422, -422, -422, -422,
-     -422, -422, -422, -422, -422, -422, -422, -422, -422, -422,
-     -422, -422, -422, -422, -422, -422, -422, -422, -422, -422,
-     -422, -422, -422, -422, -422, -422, -422, -422, -422,  543,
-     -422, -422, -422, -422, -422, -422, -422, -422, -422, -422,
-     -422, -422, -422, -422, -422, -422, -422, -422, -422, -422,
-     -422, -422, -422, -422, -422, -422, -422, -422, -422, -422,
-     -422, -422, -422, -422, -422, -422, -422, -422, -422, -422,
-     -422, -422, -422, -422, -422, -422, -422, -422
-    },
-
-    {
-       67, -423, -423, -423, -423, -423, -423, -423, -423, -423,
-
-     -423, -423, -423, -423, -423, -423, -423, -423, -423, -423,
-     -423, -423, -423, -423, -423, -423, -423, -423, -423, -423,
-     -423, -423, -423, -423, -423, -423, -423, -423, -423, -423,
-     -423, -423, -423, -423, -423, -423, -423, -423, -423, -423,
-     -423, -423, -423, -423, -423, -423, -423, -423, -423, -423,
-     -423, -423, -423, -423, -423,  544, -423, -423, -423, -423,
-     -423, -423, -423, -423, -423, -423, -423, -423, -423,  545,
-     -423, -423, -423, -423, -423, -423, -423, -423, -423, -423,
-     -423, -423, -423, -423, -423, -423, -423, -423, -423, -423,
-     -423, -423, -423, -423, -423, -423, -423, -423, -423, -423,
-
-     -423, -423, -423, -423, -423, -423, -423, -423, -423, -423,
-     -423, -423, -423, -423, -423, -423, -423, -423
-    },
-
-    {
-       67, -424, -424, -424, -424, -424, -424, -424, -424, -424,
-     -424, -424, -424, -424, -424, -424, -424, -424, -424, -424,
-     -424, -424, -424, -424, -424, -424, -424, -424, -424, -424,
-     -424, -424, -424, -424, -424, -424, -424, -424, -424, -424,
-     -424, -424, -424, -424, -424, -424, -424, -424, -424, -424,
-     -424, -424, -424, -424, -424, -424, -424, -424, -424, -424,
-     -424, -424, -424, -424, -424, -424, -424, -424, -424, -424,
-     -424, -424, -424, -424, -424, -424, -424, -424, -424, -424,
-
-     -424, -424, -424, -424, -424, -424, -424, -424, -424, -424,
-     -424, -424, -424, -424, -424, -424, -424, -424, -424, -424,
-     -424, -424, -424, -424, -424, -424, -424, -424, -424, -424,
-     -424, -424, -424, -424, -424, -424, -424, -424, -424, -424,
-     -424, -424, -424, -424, -424, -424, -424, -424
-    },
-
-    {
-       67, -425, -425, -425, -425, -425, -425, -425, -425, -425,
-     -425, -425, -425, -425, -425, -425, -425, -425, -425, -425,
-     -425, -425, -425, -425, -425, -425, -425, -425, -425, -425,
-     -425, -425, -425, -425, -425, -425, -425, -425, -425, -425,
-     -425, -425, -425, -425, -425, -425, -425, -425, -425, -425,
-
-     -425, -425, -425, -425, -425, -425, -425, -425, -425, -425,
-     -425, -425, -425, -425, -425, -425,  546, -425, -425, -425,
-     -425, -425, -425, -425, -425, -425, -425, -425, -425, -425,
-     -425, -425, -425, -425, -425, -425, -425, -425, -425, -425,
-     -425, -425, -425, -425, -425, -425, -425, -425, -425, -425,
-     -425, -425, -425, -425, -425, -425, -425, -425, -425, -425,
-     -425, -425, -425, -425, -425, -425, -425, -425, -425, -425,
-     -425, -425, -425, -425, -425, -425, -425, -425
-    },
-
-    {
-       67, -426, -426, -426, -426, -426, -426, -426, -426, -426,
-     -426, -426, -426, -426, -426, -426, -426, -426, -426, -426,
-
-     -426, -426, -426, -426, -426, -426, -426, -426, -426, -426,
-     -426, -426, -426, -426, -426, -426, -426, -426, -426, -426,
-     -426, -426, -426, -426, -426, -426, -426, -426, -426, -426,
-     -426, -426, -426, -426, -426, -426, -426, -426, -426, -426,
-     -426, -426, -426, -426, -426, -426, -426, -426, -426,  547,
-     -426, -426, -426, -426, -426, -426, -426, -426, -426, -426,
-     -426, -426, -426, -426, -426, -426, -426, -426,  548,  549,
-      550, -426, -426, -426, -426, -426, -426, -426, -426, -426,
-     -426, -426, -426, -426, -426, -426, -426, -426, -426, -426,
-     -426, -426, -426, -426, -426, -426, -426, -426, -426, -426,
-
-     -426, -426, -426, -426, -426, -426, -426, -426
-    },
-
-    {
-       67, -427, -427, -427, -427, -427, -427, -427, -427, -427,
-     -427, -427, -427, -427, -427, -427, -427, -427, -427, -427,
-     -427, -427, -427, -427, -427, -427, -427, -427, -427, -427,
-     -427, -427, -427, -427, -427, -427, -427, -427, -427, -427,
-     -427, -427, -427, -427, -427, -427, -427, -427, -427, -427,
-     -427, -427, -427, -427, -427, -427, -427, -427, -427, -427,
-     -427, -427, -427, -427, -427, -427, -427, -427, -427, -427,
-     -427, -427, -427, -427, -427, -427, -427, -427, -427, -427,
-      551, -427, -427, -427, -427, -427, -427, -427, -427, -427,
-
-     -427, -427, -427, -427, -427, -427, -427, -427, -427, -427,
-     -427, -427, -427, -427, -427, -427, -427, -427, -427, -427,
-     -427, -427, -427, -427, -427, -427, -427, -427, -427, -427,
-     -427, -427, -427, -427, -427, -427, -427, -427
-    },
-
-    {
-       67, -428, -428, -428, -428, -428, -428, -428, -428, -428,
-     -428, -428, -428, -428, -428, -428, -428, -428, -428, -428,
-     -428, -428, -428, -428, -428, -428, -428, -428, -428, -428,
-     -428, -428, -428, -428, -428, -428, -428, -428, -428, -428,
-     -428, -428, -428, -428, -428, -428, -428, -428, -428, -428,
-     -428, -428, -428, -428, -428, -428, -428, -428, -428, -428,
-
-     -428, -428, -428, -428, -428, -428, -428,  552, -428, -428,
-     -428, -428, -428, -428, -428, -428, -428, -428, -428, -428,
-     -428, -428, -428,  553, -428, -428, -428, -428, -428, -428,
-     -428, -428, -428, -428, -428, -428, -428, -428, -428, -428,
-     -428, -428, -428, -428, -428, -428, -428, -428, -428, -428,
-     -428, -428, -428, -428, -428, -428, -428, -428, -428, -428,
-     -428, -428, -428, -428, -428, -428, -428, -428
-    },
-
-    {
-       67, -429, -429, -429, -429, -429, -429, -429, -429, -429,
-     -429, -429, -429, -429, -429, -429, -429, -429, -429, -429,
-     -429, -429, -429, -429, -429, -429, -429, -429, -429, -429,
-
-     -429, -429, -429, -429, -429, -429, -429, -429, -429, -429,
-     -429, -429, -429, -429, -429, -429, -429, -429, -429, -429,
-     -429, -429, -429, -429, -429, -429, -429, -429, -429, -429,
-     -429, -429, -429, -429, -429, -429, -429, -429, -429, -429,
-      554, -429, -429, -429, -429, -429, -429, -429, -429, -429,
-     -429, -429, -429, -429, -429, -429, -429,  555, -429, -429,
-     -429, -429, -429, -429, -429, -429, -429, -429, -429, -429,
-     -429, -429, -429, -429, -429, -429, -429, -429, -429, -429,
-     -429, -429, -429, -429, -429, -429, -429, -429, -429, -429,
-     -429, -429, -429, -429, -429, -429, -429, -429
-
-    },
-
-    {
-       67, -430, -430, -430, -430, -430, -430, -430, -430, -430,
-     -430, -430, -430, -430, -430, -430, -430, -430, -430, -430,
-     -430, -430, -430, -430, -430, -430, -430, -430, -430, -430,
-     -430, -430, -430, -430, -430, -430, -430, -430, -430, -430,
-     -430, -430, -430, -430, -430, -430, -430, -430, -430, -430,
-     -430, -430, -430, -430, -430, -430, -430, -430, -430, -430,
-     -430, -430, -430, -430, -430, -430, -430, -430, -430, -430,
-     -430, -430, -430, -430, -430, -430, -430, -430, -430, -430,
-     -430, -430, -430, -430, -430, -430, -430, -430, -430, -430,
-     -430, -430, -430, -430, -430, -430, -430, -430, -430, -430,
-
-     -430, -430, -430, -430, -430, -430, -430, -430, -430, -430,
-     -430, -430, -430, -430, -430, -430, -430, -430, -430, -430,
-     -430, -430, -430, -430, -430, -430, -430, -430
-    },
-
-    {
-       67, -431, -431, -431, -431, -431, -431, -431, -431, -431,
-     -431, -431, -431, -431, -431, -431, -431, -431, -431, -431,
-     -431, -431, -431, -431, -431, -431, -431, -431, -431, -431,
-     -431, -431, -431, -431, -431, -431, -431, -431, -431, -431,
-     -431, -431, -431, -431, -431, -431, -431, -431, -431, -431,
-     -431, -431, -431, -431, -431, -431, -431, -431, -431, -431,
-     -431, -431, -431, -431, -431, -431, -431, -431, -431, -431,
-
-     -431, -431, -431, -431, -431, -431, -431, -431, -431, -431,
-     -431, -431, -431, -431, -431, -431, -431, -431, -431, -431,
-     -431, -431, -431, -431, -431, -431, -431, -431, -431, -431,
-     -431, -431, -431, -431, -431, -431, -431, -431, -431, -431,
-     -431, -431, -431, -431, -431, -431, -431, -431, -431, -431,
-     -431, -431, -431, -431, -431, -431, -431, -431
-    },
-
-    {
-       67, -432, -432, -432, -432, -432, -432, -432, -432, -432,
-     -432, -432, -432, -432, -432, -432, -432, -432, -432, -432,
-     -432, -432, -432, -432, -432, -432, -432, -432, -432, -432,
-     -432, -432, -432, -432, -432, -432, -432, -432, -432, -432,
-
-     -432, -432, -432, -432, -432, -432, -432, -432, -432, -432,
-     -432, -432, -432, -432, -432, -432, -432, -432, -432, -432,
-     -432, -432, -432, -432, -432, -432, -432, -432, -432, -432,
-     -432, -432, -432, -432, -432, -432, -432, -432, -432, -432,
-     -432, -432, -432, -432, -432, -432, -432, -432, -432, -432,
-     -432, -432, -432, -432, -432, -432, -432, -432, -432, -432,
-     -432, -432, -432, -432, -432, -432, -432, -432, -432, -432,
-     -432, -432, -432, -432, -432, -432, -432, -432, -432, -432,
-     -432, -432, -432, -432, -432, -432, -432, -432
-    },
-
-    {
-       67, -433, -433, -433, -433, -433, -433, -433, -433, -433,
-
-     -433, -433, -433, -433, -433, -433, -433, -433, -433, -433,
-     -433, -433, -433, -433, -433, -433, -433, -433, -433, -433,
-     -433, -433, -433, -433, -433, -433, -433, -433, -433, -433,
-     -433, -433, -433, -433, -433, -433, -433, -433, -433, -433,
-     -433, -433, -433, -433, -433, -433, -433, -433, -433, -433,
-     -433, -433, -433, -433, -433, -433, -433, -433, -433, -433,
-     -433, -433, -433, -433, -433, -433, -433, -433, -433, -433,
-     -433, -433, -433,  556, -433, -433, -433, -433, -433, -433,
-     -433, -433, -433, -433, -433, -433, -433, -433, -433, -433,
-     -433, -433, -433, -433, -433, -433, -433, -433, -433, -433,
-
-     -433, -433, -433, -433, -433, -433, -433, -433, -433, -433,
-     -433, -433, -433, -433, -433, -433, -433, -433
-    },
-
-    {
-       67, -434, -434, -434, -434, -434, -434, -434, -434, -434,
-     -434, -434, -434, -434, -434, -434, -434, -434, -434, -434,
-     -434, -434, -434, -434, -434, -434, -434, -434, -434, -434,
-     -434, -434, -434, -434, -434, -434, -434, -434, -434, -434,
-     -434, -434, -434, -434, -434, -434, -434, -434, -434, -434,
-     -434, -434, -434, -434, -434, -434, -434, -434, -434, -434,
-     -434, -434, -434, -434, -434, -434, -434, -434, -434, -434,
-     -434, -434, -434, -434, -434, -434, -434, -434, -434, -434,
-
-     -434, -434, -434, -434, -434, -434, -434, -434, -434, -434,
-     -434, -434, -434, -434, -434, -434, -434, -434, -434, -434,
-     -434, -434, -434, -434, -434, -434, -434, -434, -434, -434,
-     -434, -434, -434, -434, -434, -434, -434, -434, -434, -434,
-     -434, -434, -434, -434, -434, -434, -434, -434
-    },
-
-    {
-       67, -435, -435, -435, -435, -435, -435, -435, -435, -435,
-     -435, -435, -435, -435, -435, -435, -435, -435, -435, -435,
-     -435, -435, -435, -435, -435, -435, -435, -435, -435, -435,
-     -435, -435, -435, -435, -435, -435, -435, -435, -435, -435,
-     -435, -435, -435, -435, -435, -435, -435, -435, -435, -435,
-
-     -435, -435, -435, -435, -435, -435, -435, -435, -435, -435,
-     -435, -435, -435, -435, -435, -435, -435, -435, -435, -435,
-     -435, -435, -435, -435, -435, -435, -435, -435, -435,  557,
-     -435, -435, -435,  558, -435, -435, -435, -435, -435, -435,
-     -435, -435, -435, -435, -435, -435, -435, -435, -435, -435,
-     -435, -435, -435, -435, -435, -435, -435, -435, -435, -435,
-     -435, -435, -435, -435, -435, -435, -435, -435, -435, -435,
-     -435, -435, -435, -435, -435, -435, -435, -435
-    },
-
-    {
-       67, -436, -436, -436, -436, -436, -436, -436, -436, -436,
-     -436, -436, -436, -436, -436, -436, -436, -436, -436, -436,
-
-     -436, -436, -436, -436, -436, -436, -436, -436, -436, -436,
-     -436, -436, -436, -436, -436, -436, -436, -436, -436, -436,
-     -436, -436, -436, -436, -436, -436, -436, -436, -436, -436,
-     -436, -436, -436, -436, -436, -436, -436, -436, -436, -436,
-     -436, -436, -436, -436, -436, -436, -436, -436, -436, -436,
-     -436, -436, -436, -436, -436, -436, -436, -436, -436, -436,
-     -436, -436, -436, -436, -436, -436, -436, -436, -436, -436,
-     -436, -436, -436, -436, -436, -436, -436, -436, -436, -436,
-     -436, -436, -436, -436, -436, -436, -436, -436, -436, -436,
-     -436, -436, -436, -436, -436, -436, -436, -436, -436, -436,
-
-     -436, -436, -436, -436, -436, -436, -436, -436
-    },
-
-    {
-       67, -437, -437, -437, -437, -437, -437, -437, -437, -437,
-     -437, -437, -437, -437, -437, -437, -437, -437, -437, -437,
-     -437, -437, -437, -437, -437, -437, -437, -437, -437, -437,
-     -437, -437, -437, -437, -437, -437, -437, -437, -437, -437,
-     -437, -437, -437, -437, -437, -437, -437, -437, -437, -437,
-     -437, -437, -437, -437, -437, -437, -437, -437, -437, -437,
-     -437, -437, -437, -437, -437, -437, -437, -437, -437, -437,
-     -437, -437, -437, -437, -437, -437, -437, -437, -437, -437,
-     -437, -437, -437, -437,  559, -437, -437, -437, -437, -437,
-
-     -437, -437, -437, -437, -437, -437, -437, -437, -437, -437,
-     -437, -437, -437, -437, -437, -437, -437, -437, -437, -437,
-     -437, -437, -437, -437, -437, -437, -437, -437, -437, -437,
-     -437, -437, -437, -437, -437, -437, -437, -437
-    },
-
-    {
-       67, -438, -438, -438, -438, -438, -438, -438, -438, -438,
-     -438, -438, -438, -438, -438, -438, -438, -438, -438, -438,
-     -438, -438, -438, -438, -438, -438, -438, -438, -438, -438,
-     -438, -438, -438, -438, -438, -438, -438, -438, -438, -438,
-     -438, -438, -438, -438, -438, -438, -438, -438, -438, -438,
-     -438, -438, -438, -438, -438, -438, -438, -438, -438, -438,
-
-     -438, -438, -438, -438, -438, -438, -438, -438, -438, -438,
-     -438, -438, -438, -438, -438, -438, -438,  560, -438, -438,
-     -438, -438, -438, -438, -438, -438, -438, -438, -438, -438,
-     -438, -438, -438, -438, -438, -438, -438, -438, -438, -438,
-     -438, -438, -438, -438, -438, -438, -438, -438, -438, -438,
-     -438, -438, -438, -438, -438, -438, -438, -438, -438, -438,
-     -438, -438, -438, -438, -438, -438, -438, -438
-    },
-
-    {
-       67, -439, -439, -439, -439, -439, -439, -439, -439, -439,
-     -439, -439, -439, -439, -439, -439, -439, -439, -439, -439,
-     -439, -439, -439, -439, -439, -439, -439, -439, -439, -439,
-
-     -439, -439, -439, -439, -439, -439, -439, -439, -439, -439,
-     -439, -439, -439, -439, -439, -439, -439, -439, -439, -439,
-     -439, -439, -439, -439, -439, -439, -439, -439, -439, -439,
-     -439, -439, -439, -439, -439, -439, -439, -439, -439,  561,
-     -439, -439, -439, -439, -439, -439, -439, -439, -439, -439,
-     -439, -439, -439, -439, -439, -439, -439, -439, -439, -439,
-     -439, -439, -439, -439, -439, -439, -439, -439, -439, -439,
-     -439, -439, -439, -439, -439, -439, -439, -439, -439, -439,
-     -439, -439, -439, -439, -439, -439, -439, -439, -439, -439,
-     -439, -439, -439, -439, -439, -439, -439, -439
-
-    },
-
-    {
-       67, -440, -440, -440, -440, -440, -440, -440, -440, -440,
-     -440, -440, -440, -440, -440, -440, -440, -440, -440, -440,
-     -440, -440, -440, -440, -440, -440, -440, -440, -440, -440,
-     -440, -440, -440, -440, -440, -440, -440, -440, -440, -440,
-     -440, -440, -440, -440, -440, -440, -440, -440, -440, -440,
-     -440, -440, -440, -440, -440, -440, -440, -440, -440, -440,
-     -440, -440, -440, -440, -440, -440, -440, -440, -440, -440,
-     -440, -440, -440, -440, -440, -440, -440, -440, -440, -440,
-     -440, -440, -440, -440,  562, -440, -440, -440, -440, -440,
-     -440, -440, -440, -440, -440, -440, -440, -440, -440, -440,
-
-     -440, -440, -440, -440, -440, -440, -440, -440, -440, -440,
-     -440, -440, -440, -440, -440, -440, -440, -440, -440, -440,
-     -440, -440, -440, -440, -440, -440, -440, -440
-    },
-
-    {
-       67, -441, -441, -441, -441, -441, -441, -441, -441, -441,
-     -441, -441, -441, -441, -441, -441, -441, -441, -441, -441,
-     -441, -441, -441, -441, -441, -441, -441, -441, -441, -441,
-     -441, -441, -441, -441, -441, -441, -441, -441, -441, -441,
-     -441, -441, -441, -441, -441, -441, -441, -441, -441, -441,
-     -441, -441, -441, -441, -441, -441, -441, -441, -441, -441,
-     -441, -441, -441, -441, -441, -441, -441, -441, -441, -441,
-
-     -441, -441, -441, -441, -441, -441, -441, -441, -441, -441,
-     -441, -441, -441, -441, -441, -441, -441, -441,  563, -441,
-     -441, -441, -441, -441, -441, -441, -441, -441, -441, -441,
-     -441, -441, -441, -441, -441, -441, -441, -441, -441, -441,
-     -441, -441, -441, -441, -441, -441, -441, -441, -441, -441,
-     -441, -441, -441, -441, -441, -441, -441, -441
-    },
-
-    {
-       67, -442, -442, -442, -442, -442, -442, -442, -442, -442,
-     -442, -442, -442, -442, -442, -442, -442, -442, -442, -442,
-     -442, -442, -442, -442, -442, -442, -442, -442, -442, -442,
-     -442, -442, -442, -442, -442, -442, -442, -442, -442, -442,
-
-     -442, -442, -442, -442, -442, -442, -442, -442, -442, -442,
-     -442, -442, -442, -442, -442, -442, -442, -442, -442, -442,
-     -442, -442, -442, -442, -442, -442, -442, -442, -442, -442,
-     -442, -442, -442, -442, -442, -442,  564, -442, -442, -442,
-     -442, -442, -442, -442, -442, -442, -442, -442, -442, -442,
-     -442, -442, -442, -442, -442, -442, -442, -442, -442, -442,
-     -442, -442, -442, -442, -442, -442, -442, -442, -442, -442,
-     -442, -442, -442, -442, -442, -442, -442, -442, -442, -442,
-     -442, -442, -442, -442, -442, -442, -442, -442
-    },
-
-    {
-       67, -443, -443, -443, -443, -443, -443, -443, -443, -443,
-
-     -443, -443, -443, -443, -443, -443, -443, -443, -443, -443,
-     -443, -443, -443, -443, -443, -443, -443, -443, -443, -443,
-     -443, -443, -443, -443, -443, -443, -443, -443, -443, -443,
-     -443, -443, -443, -443, -443, -443, -443, -443, -443, -443,
-     -443, -443, -443, -443, -443, -443, -443, -443, -443, -443,
-     -443, -443, -443, -443, -443, -443, -443, -443, -443,  565,
-     -443, -443, -443, -443, -443, -443, -443, -443, -443, -443,
-     -443, -443, -443, -443, -443, -443, -443, -443, -443, -443,
-     -443, -443, -443, -443, -443, -443, -443, -443, -443, -443,
-     -443, -443, -443, -443, -443, -443, -443, -443, -443, -443,
-
-     -443, -443, -443, -443, -443, -443, -443, -443, -443, -443,
-     -443, -443, -443, -443, -443, -443, -443, -443
-    },
-
-    {
-       67, -444, -444, -444, -444, -444, -444, -444, -444, -444,
-     -444, -444, -444, -444, -444, -444, -444, -444, -444, -444,
-     -444, -444, -444, -444, -444, -444, -444, -444, -444, -444,
-     -444, -444, -444, -444, -444, -444, -444, -444, -444, -444,
-     -444, -444, -444, -444, -444, -444, -444, -444, -444, -444,
-     -444, -444, -444, -444, -444, -444, -444, -444, -444, -444,
-     -444, -444, -444, -444, -444, -444, -444, -444, -444, -444,
-     -444, -444, -444, -444, -444, -444, -444, -444, -444, -444,
-
-      566, -444, -444, -444, -444, -444, -444, -444, -444, -444,
-     -444, -444, -444, -444, -444, -444, -444, -444, -444, -444,
-     -444, -444, -444, -444, -444, -444, -444, -444, -444, -444,
-     -444, -444, -444, -444, -444, -444, -444, -444, -444, -444,
-     -444, -444, -444, -444, -444, -444, -444, -444
-    },
-
-    {
-       67, -445, -445, -445, -445, -445, -445, -445, -445, -445,
-     -445, -445, -445, -445, -445, -445, -445, -445, -445, -445,
-     -445, -445, -445, -445, -445, -445, -445, -445, -445, -445,
-     -445, -445, -445, -445, -445, -445, -445, -445, -445, -445,
-     -445, -445, -445, -445, -445, -445, -445, -445, -445, -445,
-
-     -445, -445, -445, -445, -445, -445, -445, -445, -445, -445,
-     -445, -445, -445, -445, -445, -445, -445, -445, -445, -445,
-     -445, -445, -445,  567, -445, -445, -445, -445, -445, -445,
-     -445, -445, -445, -445, -445, -445, -445, -445, -445, -445,
-     -445, -445, -445, -445, -445, -445, -445, -445, -445, -445,
-     -445, -445, -445, -445, -445, -445, -445, -445, -445, -445,
-     -445, -445, -445, -445, -445, -445, -445, -445, -445, -445,
-     -445, -445, -445, -445, -445, -445, -445, -445
-    },
-
-    {
-       67, -446, -446, -446, -446, -446, -446, -446, -446, -446,
-     -446, -446, -446, -446, -446, -446, -446, -446, -446, -446,
-
-     -446, -446, -446, -446, -446, -446, -446, -446, -446, -446,
-     -446, -446, -446, -446, -446, -446, -446, -446, -446, -446,
-     -446, -446, -446, -446, -446, -446, -446, -446, -446, -446,
-     -446, -446, -446, -446, -446, -446, -446, -446, -446, -446,
-     -446, -446, -446, -446, -446, -446, -446, -446, -446, -446,
-     -446, -446, -446, -446, -446, -446,  568, -446, -446, -446,
-     -446, -446, -446, -446, -446, -446, -446, -446, -446, -446,
-     -446, -446, -446, -446, -446, -446, -446, -446, -446, -446,
-     -446, -446, -446, -446, -446, -446, -446, -446, -446, -446,
-     -446, -446, -446, -446, -446, -446, -446, -446, -446, -446,
-
-     -446, -446, -446, -446, -446, -446, -446, -446
-    },
-
-    {
-       67, -447, -447, -447, -447, -447, -447, -447, -447, -447,
-     -447, -447, -447, -447, -447, -447, -447, -447, -447, -447,
-     -447, -447, -447, -447, -447, -447, -447, -447, -447, -447,
-     -447, -447, -447, -447, -447, -447, -447, -447, -447, -447,
-     -447, -447, -447, -447, -447, -447, -447, -447, -447, -447,
-     -447, -447, -447, -447, -447, -447, -447, -447, -447, -447,
-     -447, -447, -447, -447, -447, -447, -447, -447, -447, -447,
-     -447, -447, -447, -447, -447, -447, -447, -447, -447, -447,
-     -447, -447, -447, -447, -447, -447, -447, -447, -447, -447,
-
-     -447, -447, -447, -447, -447, -447, -447, -447, -447, -447,
-     -447, -447, -447, -447, -447, -447, -447, -447, -447, -447,
-     -447, -447, -447, -447, -447, -447, -447, -447, -447, -447,
-     -447, -447, -447, -447, -447, -447, -447, -447
-    },
-
-    {
-       67, -448, -448, -448, -448, -448, -448, -448, -448, -448,
-     -448, -448, -448, -448, -448, -448, -448, -448, -448, -448,
-     -448, -448, -448, -448, -448, -448, -448, -448, -448, -448,
-     -448, -448, -448, -448, -448, -448, -448, -448, -448, -448,
-     -448, -448, -448, -448, -448, -448, -448, -448, -448, -448,
-     -448, -448, -448, -448, -448, -448, -448, -448, -448, -448,
-
-     -448, -448, -448, -448, -448, -448, -448, -448, -448, -448,
-     -448, -448, -448, -448, -448, -448, -448, -448, -448, -448,
-     -448, -448, -448, -448, -448, -448, -448, -448, -448, -448,
-     -448, -448, -448, -448, -448, -448, -448, -448, -448, -448,
-     -448, -448, -448, -448, -448, -448, -448, -448, -448, -448,
-     -448, -448, -448, -448, -448, -448, -448, -448, -448, -448,
-     -448, -448, -448, -448, -448, -448, -448, -448
-    },
-
-    {
-       67, -449, -449, -449, -449, -449, -449, -449, -449, -449,
-     -449, -449, -449, -449, -449, -449, -449, -449, -449, -449,
-     -449, -449, -449, -449, -449, -449, -449, -449, -449, -449,
-
-     -449, -449, -449, -449, -449, -449, -449, -449, -449, -449,
-     -449, -449, -449, -449, -449, -449, -449, -449, -449, -449,
-     -449, -449, -449, -449, -449, -449, -449, -449, -449, -449,
-     -449, -449, -449, -449, -449, -449, -449, -449, -449, -449,
-     -449, -449, -449, -449, -449, -449, -449, -449,  569, -449,
-     -449, -449, -449, -449, -449, -449, -449, -449, -449, -449,
-     -449, -449, -449, -449, -449, -449, -449, -449, -449, -449,
-     -449, -449, -449, -449, -449, -449, -449, -449, -449, -449,
-     -449, -449, -449, -449, -449, -449, -449, -449, -449, -449,
-     -449, -449, -449, -449, -449, -449, -449, -449
-
-    },
-
-    {
-       67, -450, -450, -450, -450, -450, -450, -450, -450, -450,
-     -450, -450, -450, -450, -450, -450, -450, -450, -450, -450,
-     -450, -450, -450, -450, -450, -450, -450, -450, -450, -450,
-     -450, -450, -450, -450, -450, -450, -450, -450, -450, -450,
-     -450, -450, -450, -450, -450, -450, -450, -450, -450, -450,
-     -450, -450, -450, -450, -450, -450, -450, -450, -450, -450,
-     -450, -450, -450, -450, -450, -450, -450, -450, -450, -450,
-     -450, -450, -450, -450, -450, -450, -450, -450, -450, -450,
-     -450, -450, -450,  570, -450, -450, -450, -450, -450, -450,
-     -450, -450, -450, -450, -450, -450, -450, -450, -450, -450,
-
-     -450, -450, -450, -450, -450, -450, -450, -450, -450, -450,
-     -450, -450, -450, -450, -450, -450, -450, -450, -450, -450,
-     -450, -450, -450, -450, -450, -450, -450, -450
-    },
-
-    {
-       67, -451, -451, -451, -451, -451, -451, -451, -451, -451,
-     -451, -451, -451, -451, -451, -451, -451, -451, -451, -451,
-     -451, -451, -451, -451, -451, -451, -451, -451, -451, -451,
-     -451, -451, -451, -451, -451, -451, -451, -451, -451, -451,
-     -451, -451, -451, -451, -451, -451, -451, -451, -451, -451,
-     -451, -451, -451, -451, -451, -451, -451, -451, -451, -451,
-     -451, -451, -451, -451, -451, -451, -451, -451, -451,  571,
-
-     -451, -451, -451, -451, -451, -451, -451, -451, -451, -451,
-     -451, -451, -451, -451, -451, -451, -451, -451, -451, -451,
-     -451, -451, -451, -451, -451, -451, -451, -451, -451, -451,
-     -451, -451, -451, -451, -451, -451, -451, -451, -451, -451,
-     -451, -451, -451, -451, -451, -451, -451, -451, -451, -451,
-     -451, -451, -451, -451, -451, -451, -451, -451
-    },
-
-    {
-       67, -452, -452, -452, -452, -452, -452, -452, -452, -452,
-     -452, -452, -452, -452, -452, -452, -452, -452, -452, -452,
-     -452, -452, -452, -452, -452, -452, -452, -452, -452, -452,
-     -452, -452, -452, -452, -452, -452, -452, -452, -452, -452,
-
-     -452, -452, -452, -452, -452, -452, -452, -452, -452,  572,
-      572,  572,  572,  572,  572,  572,  572,  572, -452, -452,
-     -452, -452, -452, -452, -452, -452, -452, -452, -452, -452,
-     -452, -452, -452, -452, -452, -452, -452, -452, -452, -452,
-     -452, -452,  573, -452, -452, -452, -452, -452, -452, -452,
-     -452, -452, -452, -452, -452, -452, -452, -452, -452, -452,
-     -452, -452, -452, -452, -452, -452, -452, -452, -452, -452,
-     -452, -452, -452, -452, -452, -452, -452, -452, -452, -452,
-     -452, -452, -452, -452, -452, -452, -452, -452
-    },
-
-    {
-       67, -453, -453, -453, -453, -453, -453, -453, -453, -453,
-
-     -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
-     -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
-     -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
-     -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
-     -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
-     -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
-     -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
-     -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
-     -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
-     -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
-
-     -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
-     -453, -453, -453, -453, -453, -453, -453, -453
-    },
-
-    {
-       67, -454, -454, -454, -454, -454, -454, -454, -454, -454,
-     -454, -454, -454, -454, -454, -454, -454, -454, -454, -454,
-     -454, -454, -454, -454, -454, -454, -454, -454, -454, -454,
-     -454, -454, -454, -454, -454, -454, -454, -454, -454, -454,
-     -454, -454, -454, -454, -454, -454, -454, -454, -454,  574,
-      574,  574,  574,  574,  574,  574,  574,  574, -454, -454,
-     -454, -454, -454, -454, -454, -454, -454, -454, -454, -454,
-     -454, -454, -454, -454, -454, -454, -454, -454, -454, -454,
-
-     -454, -454, -454, -454, -454, -454, -454, -454, -454, -454,
-     -454, -454, -454, -454, -454, -454, -454, -454, -454, -454,
-     -454, -454, -454, -454, -454, -454, -454, -454, -454, -454,
-     -454, -454, -454, -454, -454, -454, -454, -454, -454, -454,
-     -454, -454, -454, -454, -454, -454, -454, -454
-    },
-
-    {
-       67, -455, -455, -455, -455, -455, -455, -455, -455, -455,
-     -455, -455, -455, -455, -455, -455, -455, -455, -455, -455,
-     -455, -455, -455, -455, -455, -455, -455, -455, -455, -455,
-     -455, -455, -455, -455, -455, -455, -455, -455, -455, -455,
-     -455, -455, -455, -455, -455, -455, -455, -455, -455, -455,
-
-     -455, -455, -455, -455, -455, -455, -455, -455, -455, -455,
-     -455, -455, -455, -455, -455, -455, -455, -455, -455, -455,
-     -455, -455, -455, -455, -455, -455, -455, -455, -455, -455,
-     -455, -455, -455, -455, -455, -455, -455, -455,  575, -455,
-     -455, -455, -455, -455, -455, -455, -455, -455, -455, -455,
-     -455, -455, -455, -455, -455, -455, -455, -455, -455, -455,
-     -455, -455, -455, -455, -455, -455, -455, -455, -455, -455,
-     -455, -455, -455, -455, -455, -455, -455, -455
-    },
-
-    {
-       67, -456, -456, -456, -456, -456, -456, -456, -456, -456,
-     -456, -456, -456, -456, -456, -456, -456, -456, -456, -456,
-
-     -456, -456, -456, -456, -456, -456, -456, -456, -456, -456,
-     -456, -456, -456, -456, -456, -456, -456, -456, -456, -456,
-     -456, -456, -456, -456, -456, -456, -456, -456, -456, -456,
-     -456, -456, -456, -456, -456, -456, -456, -456, -456, -456,
-     -456, -456, -456, -456, -456,  576, -456, -456, -456, -456,
-     -456, -456, -456, -456, -456, -456, -456, -456, -456, -456,
-     -456, -456, -456, -456, -456, -456, -456, -456, -456, -456,
-     -456, -456, -456, -456, -456, -456, -456, -456, -456, -456,
-     -456, -456, -456, -456, -456, -456, -456, -456, -456, -456,
-     -456, -456, -456, -456, -456, -456, -456, -456, -456, -456,
-
-     -456, -456, -456, -456, -456, -456, -456, -456
-    },
-
-    {
-       67, -457, -457, -457, -457, -457, -457, -457, -457, -457,
-     -457, -457, -457, -457, -457, -457, -457, -457, -457, -457,
-     -457, -457, -457, -457, -457, -457, -457, -457, -457, -457,
-     -457, -457, -457, -457, -457, -457, -457, -457, -457, -457,
-     -457, -457, -457, -457, -457, -457, -457, -457, -457,  577,
-      577,  577,  577,  577,  577,  577,  577,  577, -457, -457,
-     -457, -457, -457, -457, -457, -457, -457, -457, -457, -457,
-     -457, -457, -457, -457, -457, -457, -457, -457, -457, -457,
-     -457, -457, -457, -457, -457, -457, -457, -457, -457, -457,
-
-     -457, -457, -457, -457, -457, -457, -457, -457, -457, -457,
-     -457, -457, -457, -457, -457, -457, -457, -457, -457, -457,
-     -457, -457, -457, -457, -457, -457, -457, -457, -457, -457,
-     -457, -457, -457, -457, -457, -457, -457, -457
-    },
-
-    {
-       67, -458, -458, -458, -458, -458, -458, -458, -458, -458,
-     -458, -458, -458, -458, -458, -458, -458, -458, -458, -458,
-     -458, -458, -458, -458, -458, -458, -458, -458, -458, -458,
-     -458, -458, -458, -458, -458, -458, -458, -458, -458, -458,
-     -458, -458, -458, -458, -458, -458, -458, -458, -458,  578,
-      578,  578,  578,  578,  578,  578,  578,  578, -458, -458,
-
-     -458, -458, -458, -458, -458, -458, -458, -458, -458, -458,
-     -458, -458, -458, -458, -458, -458, -458, -458, -458, -458,
-     -458, -458, -458, -458, -458, -458, -458, -458, -458, -458,
-     -458, -458, -458, -458, -458, -458, -458, -458, -458, -458,
-     -458, -458, -458, -458, -458, -458, -458, -458, -458, -458,
-     -458, -458, -458, -458, -458, -458, -458, -458, -458, -458,
-     -458, -458, -458, -458, -458, -458, -458, -458
-    },
-
-    {
-       67, -459, -459, -459, -459, -459, -459, -459, -459, -459,
-     -459, -459, -459, -459, -459, -459, -459, -459, -459, -459,
-     -459, -459, -459, -459, -459, -459, -459, -459, -459, -459,
-
-     -459, -459, -459, -459, -459, -459, -459, -459, -459, -459,
-     -459, -459, -459, -459, -459, -459, -459, -459, -459, -459,
-     -459, -459, -459, -459, -459, -459, -459, -459, -459, -459,
-     -459, -459, -459, -459, -459, -459, -459, -459, -459, -459,
-     -459, -459, -459, -459, -459, -459, -459, -459, -459, -459,
-     -459, -459,  579, -459, -459, -459, -459, -459, -459, -459,
-     -459, -459, -459, -459, -459, -459, -459, -459, -459, -459,
-     -459, -459, -459, -459, -459, -459, -459, -459, -459, -459,
-     -459, -459, -459, -459, -459, -459, -459, -459, -459, -459,
-     -459, -459, -459, -459, -459, -459, -459, -459
-
-    },
-
-    {
-       67, -460, -460, -460, -460, -460, -460, -460, -460, -460,
-     -460, -460, -460, -460, -460, -460, -460, -460, -460, -460,
-     -460, -460, -460, -460, -460, -460, -460, -460, -460, -460,
-     -460, -460, -460, -460, -460, -460, -460, -460, -460, -460,
-     -460, -460, -460, -460, -460, -460, -460, -460, -460, -460,
-     -460, -460, -460, -460, -460, -460, -460, -460, -460, -460,
-     -460, -460, -460, -460, -460, -460, -460, -460, -460, -460,
-     -460, -460, -460, -460, -460, -460, -460, -460, -460, -460,
-     -460, -460, -460, -460, -460, -460, -460, -460, -460, -460,
-     -460, -460, -460, -460, -460, -460, -460, -460, -460, -460,
-
-     -460, -460, -460, -460, -460, -460, -460, -460, -460, -460,
-     -460, -460, -460, -460, -460, -460, -460, -460, -460, -460,
-     -460, -460, -460, -460, -460, -460, -460, -460
-    },
-
-    {
-       67, -461, -461, -461, -461, -461, -461, -461, -461, -461,
-     -461, -461, -461, -461, -461, -461, -461, -461, -461, -461,
-     -461, -461, -461, -461, -461, -461, -461, -461, -461, -461,
-     -461, -461, -461, -461, -461, -461, -461, -461, -461, -461,
-     -461, -461, -461, -461, -461, -461, -461, -461, -461, -461,
-     -461, -461, -461, -461, -461, -461, -461, -461, -461, -461,
-     -461, -461, -461, -461, -461, -461, -461, -461, -461, -461,
-
-     -461, -461, -461, -461, -461, -461, -461, -461, -461, -461,
-     -461, -461, -461, -461, -461, -461, -461, -461, -461, -461,
-     -461, -461, -461, -461, -461, -461, -461, -461, -461, -461,
-     -461, -461, -461, -461, -461, -461, -461, -461, -461, -461,
-     -461, -461, -461, -461, -461, -461, -461, -461, -461, -461,
-     -461, -461, -461, -461, -461, -461, -461, -461
-    },
-
-    {
-       67, -462, -462, -462, -462, -462, -462, -462, -462, -462,
-     -462, -462, -462, -462, -462, -462, -462, -462, -462, -462,
-     -462, -462, -462, -462, -462, -462, -462, -462, -462, -462,
-     -462, -462, -462, -462, -462, -462, -462, -462, -462, -462,
-
-     -462, -462, -462, -462, -462, -462, -462, -462, -462, -462,
-     -462, -462, -462, -462, -462, -462, -462, -462, -462, -462,
-     -462, -462, -462, -462, -462, -462, -462, -462, -462, -462,
-     -462, -462, -462, -462, -462, -462, -462, -462, -462, -462,
-     -462, -462, -462, -462, -462, -462, -462, -462, -462, -462,
-     -462, -462, -462, -462, -462, -462, -462, -462, -462, -462,
-     -462, -462, -462, -462, -462, -462, -462, -462, -462, -462,
-     -462, -462, -462, -462, -462, -462, -462, -462, -462, -462,
-     -462, -462, -462, -462, -462, -462, -462, -462
-    },
-
-    {
-       67, -463, -463, -463, -463, -463, -463, -463, -463, -463,
-
-     -463, -463, -463, -463, -463, -463, -463, -463, -463, -463,
-     -463, -463, -463, -463, -463, -463, -463, -463, -463, -463,
-     -463, -463, -463, -463, -463, -463, -463, -463, -463, -463,
-     -463, -463, -463, -463, -463, -463, -463, -463, -463, -463,
-     -463, -463, -463, -463, -463, -463, -463, -463, -463, -463,
-     -463, -463, -463, -463, -463, -463, -463, -463, -463, -463,
-     -463, -463, -463, -463, -463, -463, -463, -463, -463, -463,
-     -463, -463, -463, -463, -463, -463, -463, -463, -463, -463,
-     -463, -463, -463, -463, -463, -463, -463, -463, -463, -463,
-     -463, -463, -463, -463, -463, -463, -463, -463, -463, -463,
-
-     -463, -463, -463, -463, -463, -463, -463, -463, -463, -463,
-     -463, -463, -463, -463, -463, -463, -463, -463
-    },
-
-    {
-       67, -464, -464, -464, -464, -464, -464, -464, -464, -464,
-     -464, -464, -464, -464, -464, -464, -464, -464, -464, -464,
-     -464, -464, -464, -464, -464, -464, -464, -464, -464, -464,
-     -464, -464, -464, -464, -464, -464, -464, -464, -464, -464,
-     -464, -464, -464, -464, -464, -464, -464, -464, -464, -464,
-     -464, -464, -464, -464, -464, -464, -464, -464, -464, -464,
-     -464, -464, -464, -464, -464, -464, -464, -464, -464, -464,
-     -464, -464, -464, -464, -464, -464, -464, -464, -464, -464,
-
-     -464, -464, -464, -464, -464, -464, -464, -464, -464, -464,
-     -464, -464, -464, -464, -464, -464, -464, -464, -464, -464,
-     -464, -464, -464, -464, -464, -464, -464, -464, -464, -464,
-     -464, -464, -464, -464, -464, -464, -464, -464, -464, -464,
-     -464, -464, -464, -464, -464, -464, -464, -464
-    },
-
-    {
-       67, -465, -465, -465, -465, -465, -465, -465, -465, -465,
-     -465, -465, -465, -465, -465, -465, -465, -465, -465, -465,
-     -465, -465, -465, -465, -465, -465, -465, -465, -465, -465,
-     -465, -465, -465, -465, -465, -465, -465, -465, -465, -465,
-     -465, -465, -465, -465, -465, -465, -465, -465, -465, -465,
-
-     -465, -465, -465, -465, -465, -465, -465, -465, -465, -465,
-     -465, -465, -465, -465, -465, -465, -465, -465, -465, -465,
-     -465, -465, -465, -465, -465, -465, -465, -465, -465, -465,
-     -465, -465, -465, -465, -465, -465, -465, -465, -465, -465,
-     -465, -465, -465, -465, -465, -465, -465, -465, -465, -465,
-     -465, -465, -465, -465, -465, -465, -465, -465, -465, -465,
-     -465, -465, -465, -465, -465, -465, -465, -465, -465, -465,
-     -465, -465, -465, -465, -465, -465, -465, -465
-    },
-
-    {
-       67, -466, -466, -466, -466, -466, -466, -466, -466, -466,
-     -466, -466, -466, -466, -466, -466, -466, -466, -466, -466,
-
-     -466, -466, -466, -466, -466, -466, -466, -466, -466, -466,
-     -466, -466, -466, -466, -466, -466, -466, -466, -466, -466,
-     -466, -466, -466, -466, -466, -466, -466, -466,  580,  580,
-      580,  580,  580,  580,  580,  580,  580,  580, -466, -466,
-     -466, -466, -466, -466, -466, -466, -466, -466, -466, -466,
-     -466, -466, -466, -466, -466, -466, -466, -466, -466, -466,
-     -466, -466, -466, -466, -466, -466, -466, -466, -466, -466,
-     -466, -466, -466, -466, -466, -466, -466, -466, -466, -466,
-     -466, -466, -466, -466, -466, -466, -466, -466, -466, -466,
-     -466, -466, -466, -466, -466, -466, -466, -466, -466, -466,
-
-     -466, -466, -466, -466, -466, -466, -466, -466
-    },
-
-    {
-       67, -467, -467, -467, -467, -467, -467, -467, -467, -467,
-     -467, -467, -467, -467, -467, -467, -467, -467, -467, -467,
-     -467, -467, -467, -467, -467, -467, -467, -467, -467, -467,
-     -467, -467, -467, -467, -467, -467, -467, -467, -467, -467,
-     -467, -467, -467, -467, -467, -467, -467, -467,  580,  580,
-      580,  580,  580,  580,  580,  580,  580,  580, -467, -467,
-     -467, -467, -467, -467, -467, -467, -467, -467, -467, -467,
-     -467, -467, -467, -467, -467, -467, -467, -467, -467, -467,
-     -467, -467, -467, -467, -467, -467, -467, -467, -467, -467,
-
-     -467, -467, -467, -467, -467,  581, -467, -467, -467, -467,
-     -467, -467, -467, -467, -467, -467, -467, -467, -467, -467,
-     -467, -467, -467, -467, -467, -467, -467, -467, -467, -467,
-     -467, -467, -467, -467, -467, -467, -467, -467
-    },
-
-    {
-       67, -468, -468, -468, -468, -468, -468, -468, -468, -468,
-     -468, -468, -468, -468, -468, -468, -468, -468, -468, -468,
-     -468, -468, -468, -468, -468, -468, -468, -468, -468, -468,
-     -468, -468, -468, -468, -468, -468, -468, -468, -468, -468,
-     -468, -468, -468, -468, -468, -468, -468, -468, -468,  582,
-      582,  582,  582,  582,  582,  582,  582,  582, -468, -468,
-
-     -468, -468, -468, -468, -468, -468, -468, -468, -468, -468,
-     -468, -468, -468, -468, -468, -468, -468, -468, -468, -468,
-     -468, -468, -468, -468, -468, -468, -468, -468, -468, -468,
-     -468, -468, -468, -468, -468, -468, -468, -468, -468, -468,
-     -468, -468, -468, -468, -468, -468, -468, -468, -468, -468,
-     -468, -468, -468, -468, -468, -468, -468, -468, -468, -468,
-     -468, -468, -468, -468, -468, -468, -468, -468
-    },
-
-    {
-       67, -469, -469, -469, -469, -469, -469, -469, -469, -469,
-     -469, -469, -469, -469, -469, -469, -469, -469, -469, -469,
-     -469, -469, -469, -469, -469, -469, -469, -469, -469, -469,
-
-     -469, -469,  583, -469, -469, -469, -469, -469, -469, -469,
-     -469, -469, -469, -469, -469, -469, -469, -469,  584,  584,
-      584,  584,  584,  584,  584,  584,  584,  584, -469, -469,
-     -469, -469, -469, -469, -469,  583,  583,  583,  583,  583,
-      583,  583,  583,  583,  583,  583,  583,  583,  583,  583,
-      583,  583,  583,  583,  583,  583,  583,  583,  583,  583,
-      583, -469, -469, -469, -469, -469, -469, -469, -469, -469,
-     -469, -469, -469, -469, -469, -469, -469, -469, -469, -469,
-     -469, -469, -469, -469, -469, -469, -469, -469, -469, -469,
-     -469, -469, -469, -469, -469, -469, -469, -469
-
-    },
-
-    {
-       67, -470, -470, -470, -470, -470, -470, -470, -470, -470,
-     -470, -470, -470, -470, -470, -470, -470, -470, -470, -470,
-     -470, -470, -470, -470, -470, -470, -470, -470, -470, -470,
-     -470, -470,  585, -470, -470, -470, -470, -470, -470, -470,
-     -470, -470, -470, -470, -470, -470, -470, -470, -470, -470,
-     -470, -470, -470, -470, -470, -470, -470, -470, -470, -470,
-     -470, -470, -470, -470, -470, -470, -470, -470, -470, -470,
-     -470, -470, -470, -470, -470, -470, -470, -470, -470, -470,
-     -470, -470, -470, -470, -470, -470, -470, -470, -470, -470,
-     -470, -470, -470, -470, -470, -470, -470, -470, -470, -470,
-
-     -470, -470, -470, -470, -470, -470, -470, -470, -470, -470,
-     -470, -470, -470, -470, -470, -470, -470, -470, -470, -470,
-     -470, -470, -470, -470, -470, -470, -470, -470
-    },
-
-    {
-       67, -471, -471, -471, -471, -471, -471, -471, -471, -471,
-     -471, -471, -471, -471, -471, -471, -471, -471, -471, -471,
-     -471, -471, -471, -471, -471, -471, -471, -471, -471, -471,
-     -471, -471,  586, -471, -471, -471, -471, -471, -471, -471,
-     -471, -471, -471, -471, -471, -471, -471, -471,  587,  587,
-      587,  587,  587,  587,  587,  587,  587,  587, -471, -471,
-     -471, -471, -471, -471, -471,  586,  586,  586,  586,  586,
-
-      586,  586,  586,  586,  586,  586,  586,  586,  586,  586,
-      586,  586,  586,  586,  586,  586,  586,  586,  586,  586,
-      586, -471, -471, -471, -471, -471, -471, -471, -471, -471,
-     -471, -471, -471, -471, -471, -471, -471, -471, -471, -471,
-     -471, -471, -471, -471, -471, -471, -471, -471, -471, -471,
-     -471, -471, -471, -471, -471, -471, -471, -471
-    },
-
-    {
-       67, -472, -472, -472, -472, -472, -472, -472, -472, -472,
-     -472, -472, -472, -472, -472, -472, -472, -472, -472, -472,
-     -472, -472, -472, -472, -472, -472, -472, -472, -472, -472,
-     -472, -472, -472, -472, -472, -472, -472, -472, -472, -472,
-
-     -472, -472, -472, -472, -472, -472, -472, -472, -472, -472,
-     -472, -472, -472, -472, -472, -472, -472, -472, -472, -472,
-     -472, -472, -472, -472, -472, -472, -472, -472, -472, -472,
-     -472, -472, -472, -472, -472, -472, -472, -472, -472, -472,
-     -472, -472, -472, -472, -472, -472, -472, -472, -472, -472,
-     -472, -472, -472, -472, -472, -472, -472, -472, -472, -472,
-     -472, -472, -472, -472, -472, -472, -472, -472, -472, -472,
-     -472, -472, -472, -472, -472, -472, -472, -472, -472, -472,
-     -472, -472, -472, -472, -472, -472, -472, -472
-    },
-
-    {
-       67, -473, -473, -473, -473, -473, -473, -473, -473, -473,
-
-     -473, -473, -473, -473, -473, -473, -473, -473, -473, -473,
-     -473, -473, -473, -473, -473, -473, -473, -473, -473, -473,
-     -473, -473, -473, -473, -473, -473, -473, -473, -473, -473,
-     -473, -473, -473, -473, -473, -473, -473, -473, -473, -473,
-     -473, -473, -473, -473, -473, -473, -473, -473, -473, -473,
-     -473, -473, -473, -473, -473, -473, -473, -473, -473, -473,
-     -473, -473, -473, -473, -473, -473, -473, -473, -473, -473,
-     -473, -473, -473, -473, -473, -473, -473, -473, -473, -473,
-     -473, -473, -473, -473, -473, -473, -473, -473, -473, -473,
-     -473, -473, -473, -473, -473, -473, -473, -473, -473, -473,
-
-     -473, -473, -473, -473, -473, -473, -473, -473, -473, -473,
-     -473, -473, -473, -473, -473, -473, -473, -473
-    },
-
-    {
-       67, -474, -474, -474, -474, -474, -474, -474, -474, -474,
-     -474, -474, -474, -474, -474, -474, -474, -474, -474, -474,
-     -474, -474, -474, -474, -474, -474, -474, -474, -474, -474,
-     -474, -474, -474, -474, -474, -474, -474, -474, -474, -474,
-     -474, -474, -474, -474, -474, -474, -474, -474, -474, -474,
-     -474, -474, -474, -474, -474, -474, -474, -474, -474, -474,
-     -474, -474, -474, -474, -474, -474, -474, -474, -474, -474,
-     -474, -474, -474, -474, -474, -474, -474, -474, -474, -474,
-
-     -474, -474, -474, -474, -474, -474, -474, -474, -474, -474,
-     -474, -474, -474, -474, -474, -474, -474, -474, -474, -474,
-     -474, -474, -474, -474, -474, -474, -474, -474, -474, -474,
-     -474, -474, -474, -474, -474, -474, -474, -474, -474, -474,
-     -474, -474, -474, -474, -474, -474, -474, -474
-    },
-
-    {
-       67, -475, -475, -475, -475, -475, -475, -475, -475, -475,
-     -475, -475, -475, -475, -475, -475, -475, -475, -475, -475,
-     -475, -475, -475, -475, -475, -475, -475, -475, -475, -475,
-     -475, -475, -475, -475, -475, -475, -475, -475, -475, -475,
-     -475, -475, -475, -475, -475, -475, -475, -475, -475, -475,
-
-     -475, -475, -475, -475, -475, -475, -475, -475, -475, -475,
-     -475, -475, -475, -475, -475, -475, -475, -475, -475, -475,
-     -475, -475, -475, -475, -475, -475, -475, -475, -475, -475,
-     -475, -475, -475, -475, -475, -475, -475, -475, -475, -475,
-     -475, -475, -475, -475, -475,  588, -475, -475, -475, -475,
-     -475, -475, -475, -475, -475, -475, -475, -475, -475, -475,
-     -475, -475, -475, -475, -475, -475, -475, -475, -475, -475,
-     -475, -475, -475, -475, -475, -475, -475, -475
-    },
-
-    {
-       67, -476, -476, -476, -476, -476, -476, -476, -476, -476,
-     -476, -476, -476, -476, -476, -476, -476, -476, -476, -476,
-
-     -476, -476, -476, -476, -476, -476, -476, -476, -476, -476,
-     -476, -476, -476, -476, -476, -476, -476, -476, -476, -476,
-     -476, -476, -476, -476, -476, -476, -476, -476, -476,  589,
-      589,  589,  589,  589,  589,  589,  589,  589, -476, -476,
-     -476, -476, -476, -476, -476, -476, -476, -476, -476, -476,
-     -476, -476, -476, -476, -476, -476, -476, -476, -476, -476,
-     -476, -476, -476, -476, -476, -476, -476, -476, -476, -476,
-     -476, -476, -476, -476, -476, -476, -476, -476, -476, -476,
-     -476, -476, -476, -476, -476, -476, -476, -476, -476, -476,
-     -476, -476, -476, -476, -476, -476, -476, -476, -476, -476,
-
-     -476, -476, -476, -476, -476, -476, -476, -476
-    },
-
-    {
-       67, -477, -477, -477, -477, -477, -477, -477, -477, -477,
-     -477, -477, -477, -477, -477, -477, -477, -477, -477, -477,
-     -477, -477, -477, -477, -477, -477, -477, -477, -477, -477,
-     -477, -477,  590, -477, -477, -477, -477, -477, -477, -477,
-     -477, -477, -477, -477, -477, -477, -477, -477,  591,  591,
-      591,  591,  591,  591,  591,  591,  591,  591, -477, -477,
-     -477, -477, -477, -477, -477,  590,  590,  590,  590,  590,
-      590,  590,  590,  590,  590,  590,  590,  590,  590,  590,
-      590,  590,  590,  590,  590,  590,  590,  590,  590,  590,
-
-      590, -477, -477, -477, -477, -477, -477, -477, -477, -477,
-     -477, -477, -477, -477, -477, -477, -477, -477, -477, -477,
-     -477, -477, -477, -477, -477, -477, -477, -477, -477, -477,
-     -477, -477, -477, -477, -477, -477, -477, -477
-    },
-
-    {
-       67, -478, -478, -478, -478, -478, -478, -478, -478, -478,
-     -478, -478, -478, -478, -478, -478, -478, -478, -478, -478,
-     -478, -478, -478, -478, -478, -478, -478, -478, -478, -478,
-     -478, -478,  592, -478, -478, -478, -478, -478, -478, -478,
-     -478, -478, -478, -478, -478, -478, -478, -478, -478, -478,
-     -478, -478, -478, -478, -478, -478, -478, -478, -478, -478,
-
-     -478, -478, -478, -478, -478, -478, -478, -478, -478, -478,
-     -478, -478, -478, -478, -478, -478, -478, -478, -478, -478,
-     -478, -478, -478, -478, -478, -478, -478, -478, -478, -478,
-     -478, -478, -478, -478, -478, -478, -478, -478, -478, -478,
-     -478, -478, -478, -478, -478, -478, -478, -478, -478, -478,
-     -478, -478, -478, -478, -478, -478, -478, -478, -478, -478,
-     -478, -478, -478, -478, -478, -478, -478, -478
-    },
-
-    {
-       67, -479, -479, -479, -479, -479, -479, -479, -479, -479,
-     -479, -479, -479, -479, -479, -479, -479, -479, -479, -479,
-     -479, -479, -479, -479, -479, -479, -479, -479, -479, -479,
-
-     -479, -479,  593, -479, -479, -479, -479, -479, -479, -479,
-     -479, -479, -479, -479, -479, -479, -479, -479,  594,  594,
-      594,  594,  594,  594,  594,  594,  594,  594, -479, -479,
-     -479, -479, -479, -479, -479,  593,  593,  593,  593,  593,
-      593,  593,  593,  593,  593,  593,  593,  593,  593,  593,
-      593,  593,  593,  593,  593,  593,  593,  593,  593,  593,
-      593, -479, -479, -479, -479, -479, -479, -479, -479, -479,
-     -479, -479, -479, -479, -479, -479, -479, -479, -479, -479,
-     -479, -479, -479, -479, -479, -479, -479, -479, -479, -479,
-     -479, -479, -479, -479, -479, -479, -479, -479
-
-    },
-
-    {
-       67, -480, -480, -480, -480, -480, -480, -480, -480, -480,
-     -480, -480, -480, -480, -480, -480, -480, -480, -480, -480,
-     -480, -480, -480, -480, -480, -480, -480, -480, -480, -480,
-     -480, -480, -480, -480, -480, -480, -480, -480, -480, -480,
-     -480, -480, -480, -480, -480, -480, -480, -480, -480,  595,
-      595,  595,  595,  595,  595,  595,  595,  595, -480, -480,
-     -480, -480, -480, -480, -480, -480, -480, -480, -480, -480,
-     -480, -480, -480, -480, -480, -480, -480, -480, -480, -480,
-     -480, -480, -480, -480, -480, -480, -480, -480, -480, -480,
-     -480, -480, -480, -480, -480, -480, -480, -480, -480, -480,
-
-     -480, -480, -480, -480, -480, -480, -480, -480, -480, -480,
-     -480, -480, -480, -480, -480, -480, -480, -480, -480, -480,
-     -480, -480, -480, -480, -480, -480, -480, -480
-    },
-
-    {
-       67, -481, -481, -481, -481, -481, -481, -481, -481, -481,
-     -481, -481, -481, -481, -481, -481, -481, -481, -481, -481,
-     -481, -481, -481, -481, -481, -481, -481, -481, -481, -481,
-     -481, -481,  596, -481, -481, -481, -481, -481, -481, -481,
-     -481, -481, -481, -481, -481, -481, -481, -481,  597,  597,
-      597,  597,  597,  597,  597,  597,  597,  597, -481, -481,
-     -481, -481, -481, -481, -481,  596,  596,  596,  596,  596,
-
-      596,  596,  596,  596,  596,  596,  596,  596,  596,  596,
-      596,  596,  596,  596,  596,  596,  596,  596,  596,  596,
-      596, -481, -481, -481, -481, -481, -481, -481, -481, -481,
-     -481, -481, -481, -481, -481, -481, -481, -481, -481, -481,
-     -481, -481, -481, -481, -481, -481, -481, -481, -481, -481,
-     -481, -481, -481, -481, -481, -481, -481, -481
-    },
-
-    {
-       67, -482, -482, -482, -482, -482, -482, -482, -482, -482,
-     -482, -482, -482, -482, -482, -482, -482, -482, -482, -482,
-     -482, -482, -482, -482, -482, -482, -482, -482, -482, -482,
-     -482, -482,  598, -482, -482, -482, -482, -482, -482, -482,
-
-     -482, -482, -482, -482, -482, -482, -482, -482, -482, -482,
-     -482, -482, -482, -482, -482, -482, -482, -482, -482, -482,
-     -482, -482, -482, -482, -482, -482, -482, -482, -482, -482,
-     -482, -482, -482, -482, -482, -482, -482, -482, -482, -482,
-     -482, -482, -482, -482, -482, -482, -482, -482, -482, -482,
-     -482, -482, -482, -482, -482, -482, -482, -482, -482, -482,
-     -482, -482, -482, -482, -482, -482, -482, -482, -482, -482,
-     -482, -482, -482, -482, -482, -482, -482, -482, -482, -482,
-     -482, -482, -482, -482, -482, -482, -482, -482
-    },
-
-    {
-       67, -483, -483, -483, -483, -483, -483, -483, -483, -483,
-
-     -483, -483, -483, -483, -483, -483, -483, -483, -483, -483,
-     -483, -483, -483, -483, -483, -483, -483, -483, -483, -483,
-     -483, -483,  599, -483, -483, -483, -483, -483, -483, -483,
-     -483, -483, -483, -483, -483, -483, -483, -483,  600,  600,
-      600,  600,  600,  600,  600,  600,  600,  600, -483, -483,
-     -483, -483, -483, -483, -483,  599,  599,  599,  599,  599,
-      599,  599,  599,  599,  599,  599,  599,  599,  599,  599,
-      599,  599,  599,  599,  599,  599,  599,  599,  599,  599,
-      599, -483, -483, -483, -483, -483, -483, -483, -483, -483,
-     -483, -483, -483, -483, -483, -483, -483, -483, -483, -483,
-
-     -483, -483, -483, -483, -483, -483, -483, -483, -483, -483,
-     -483, -483, -483, -483, -483, -483, -483, -483
-    },
-
-    {
-       67, -484, -484, -484, -484, -484, -484, -484, -484, -484,
-     -484, -484, -484, -484, -484, -484, -484, -484, -484, -484,
-     -484, -484, -484, -484, -484, -484, -484, -484, -484, -484,
-     -484, -484, -484, -484, -484, -484, -484, -484, -484, -484,
-     -484, -484, -484, -484, -484, -484, -484, -484, -484, -484,
-     -484, -484, -484, -484, -484, -484, -484, -484, -484, -484,
-     -484, -484, -484, -484, -484, -484, -484, -484, -484, -484,
-     -484, -484, -484, -484, -484, -484, -484, -484, -484, -484,
-
-     -484, -484, -484, -484, -484, -484, -484, -484, -484, -484,
-     -484, -484, -484, -484, -484,  601, -484, -484, -484, -484,
-     -484, -484, -484, -484, -484, -484, -484, -484, -484, -484,
-     -484, -484, -484, -484, -484, -484, -484, -484, -484, -484,
-     -484, -484, -484, -484, -484, -484, -484, -484
-    },
-
-    {
-       67, -485, -485, -485, -485, -485, -485, -485, -485, -485,
-     -485, -485, -485, -485, -485, -485, -485, -485, -485, -485,
-     -485, -485, -485, -485, -485, -485, -485, -485, -485, -485,
-     -485, -485, -485, -485, -485, -485, -485, -485, -485, -485,
-     -485, -485, -485, -485, -485, -485, -485, -485,  602,  603,
-
-      603,  603,  603,  603,  603,  603,  603,  603, -485, -485,
-     -485, -485, -485, -485, -485, -485, -485, -485, -485, -485,
-     -485, -485, -485, -485, -485, -485, -485, -485, -485, -485,
-     -485, -485, -485, -485, -485, -485, -485, -485, -485, -485,
-     -485, -485, -485, -485, -485, -485, -485, -485, -485, -485,
-     -485, -485, -485, -485, -485, -485, -485, -485, -485, -485,
-     -485, -485, -485, -485, -485, -485, -485, -485, -485, -485,
-     -485, -485, -485, -485, -485, -485, -485, -485
-    },
-
-    {
-       67, -486, -486, -486, -486, -486, -486, -486, -486, -486,
-     -486, -486, -486, -486, -486, -486, -486, -486, -486, -486,
-
-     -486, -486, -486, -486, -486, -486, -486, -486, -486, -486,
-     -486, -486,  604, -486, -486, -486, -486, -486, -486, -486,
-     -486, -486, -486, -486, -486, -486, -486, -486, -486, -486,
-     -486, -486, -486, -486, -486, -486, -486, -486, -486, -486,
-     -486, -486, -486, -486, -486,  604,  604,  604,  604,  604,
-      604,  604,  604,  604,  604,  604,  604,  604,  604,  604,
-      604,  604,  604,  604,  604,  604,  604,  604,  604,  604,
-      604, -486, -486, -486, -486, -486, -486, -486, -486, -486,
-     -486, -486, -486, -486, -486, -486, -486, -486, -486, -486,
-     -486, -486, -486, -486, -486, -486, -486, -486, -486, -486,
-
-     -486, -486, -486, -486, -486, -486, -486, -486
-    },
-
-    {
-       67, -487, -487, -487, -487, -487, -487, -487, -487, -487,
-     -487, -487, -487, -487, -487, -487, -487, -487, -487, -487,
-     -487, -487, -487, -487, -487, -487, -487, -487, -487, -487,
-     -487, -487,  604, -487, -487, -487, -487, -487, -487, -487,
-     -487, -487, -487, -487, -487, -487, -487, -487,  605,  605,
-      605,  605,  605,  605,  605,  605,  605,  605, -487, -487,
-     -487, -487, -487, -487, -487,  604,  604,  604,  604,  604,
-      604,  604,  604,  604,  604,  604,  604,  604,  604,  604,
-      604,  604,  604,  604,  604,  604,  604,  604,  604,  604,
-
-      604, -487, -487, -487, -487, -487, -487, -487, -487, -487,
-     -487, -487, -487, -487, -487, -487, -487, -487, -487, -487,
-     -487, -487, -487, -487, -487, -487, -487, -487, -487, -487,
-     -487, -487, -487, -487, -487, -487, -487, -487
-    },
-
-    {
-       67, -488, -488, -488, -488, -488, -488, -488, -488, -488,
-     -488, -488, -488, -488, -488, -488, -488, -488, -488, -488,
-     -488, -488, -488, -488, -488, -488, -488, -488, -488, -488,
-     -488, -488,  606, -488, -488, -488, -488, -488, -488, -488,
-     -488, -488, -488, -488, -488, -488, -488, -488, -488, -488,
-     -488, -488, -488, -488, -488, -488, -488, -488, -488, -488,
-
-     -488, -488, -488, -488, -488, -488, -488, -488, -488, -488,
-     -488, -488, -488, -488, -488, -488, -488, -488, -488, -488,
-     -488, -488, -488, -488, -488, -488, -488, -488, -488, -488,
-     -488, -488, -488, -488, -488, -488, -488, -488, -488, -488,
-     -488, -488, -488, -488, -488, -488, -488, -488, -488, -488,
-     -488, -488, -488, -488, -488, -488, -488, -488, -488, -488,
-     -488, -488, -488, -488, -488, -488, -488, -488
-    },
-
-    {
-       67, -489, -489, -489, -489, -489, -489, -489, -489, -489,
-     -489, -489, -489, -489, -489, -489, -489, -489, -489, -489,
-     -489, -489, -489, -489, -489, -489, -489, -489, -489, -489,
-
-     -489, -489,  607, -489, -489, -489, -489, -489, -489, -489,
-     -489, -489, -489, -489, -489, -489, -489, -489,  608,  608,
-      608,  608,  608,  608,  608,  608,  608,  608, -489, -489,
-     -489, -489, -489, -489, -489,  607,  607,  607,  607,  607,
-      607,  607,  607,  607,  607,  607,  607,  607,  607,  607,
-      607,  607,  607,  607,  607,  607,  607,  607,  607,  607,
-      607, -489, -489, -489, -489, -489, -489, -489, -489, -489,
-     -489, -489, -489, -489, -489, -489, -489, -489, -489, -489,
-     -489, -489, -489, -489, -489, -489, -489, -489, -489, -489,
-     -489, -489, -489, -489, -489, -489, -489, -489
-
-    },
-
-    {
-       67, -490, -490, -490, -490, -490, -490, -490, -490, -490,
-     -490, -490, -490, -490, -490, -490, -490, -490, -490, -490,
-     -490, -490, -490, -490, -490, -490, -490, -490, -490, -490,
-     -490, -490, -490, -490, -490, -490, -490, -490, -490, -490,
-     -490, -490, -490, -490, -490, -490, -490, -490, -490, -490,
-     -490, -490, -490, -490, -490, -490, -490, -490, -490, -490,
-     -490, -490, -490, -490, -490, -490, -490, -490, -490, -490,
-     -490, -490, -490, -490, -490, -490, -490, -490, -490, -490,
-     -490, -490, -490, -490, -490, -490, -490, -490, -490, -490,
-     -490, -490, -490, -490, -490,  609, -490, -490, -490, -490,
-
-     -490, -490, -490, -490, -490, -490, -490, -490, -490, -490,
-     -490, -490, -490, -490, -490, -490, -490, -490, -490, -490,
-     -490, -490, -490, -490, -490, -490, -490, -490
-    },
-
-    {
-       67, -491, -491, -491, -491, -491, -491, -491, -491, -491,
-     -491, -491, -491, -491, -491, -491, -491, -491, -491, -491,
-     -491, -491, -491, -491, -491, -491, -491, -491, -491, -491,
-     -491, -491, -491, -491, -491, -491, -491, -491, -491, -491,
-     -491, -491, -491, -491, -491, -491, -491, -491,  610,  611,
-      611,  611,  611,  611,  611,  611,  611,  611, -491, -491,
-     -491, -491, -491, -491, -491, -491, -491, -491, -491, -491,
-
-     -491, -491, -491, -491, -491, -491, -491, -491, -491, -491,
-     -491, -491, -491, -491, -491, -491, -491, -491, -491, -491,
-     -491, -491, -491, -491, -491, -491, -491, -491, -491, -491,
-     -491, -491, -491, -491, -491, -491, -491, -491, -491, -491,
-     -491, -491, -491, -491, -491, -491, -491, -491, -491, -491,
-     -491, -491, -491, -491, -491, -491, -491, -491
-    },
-
-    {
-       67, -492, -492, -492, -492, -492, -492, -492, -492, -492,
-     -492, -492, -492, -492, -492, -492, -492, -492, -492, -492,
-     -492, -492, -492, -492, -492, -492, -492, -492, -492, -492,
-     -492, -492,  612, -492, -492, -492, -492, -492, -492, -492,
-
-     -492, -492, -492, -492, -492, -492, -492, -492, -492, -492,
-     -492, -492, -492, -492, -492, -492, -492, -492, -492, -492,
-     -492, -492, -492, -492, -492,  612,  612,  612,  612,  612,
-      612,  612,  612,  612,  612,  612,  612,  612,  612,  612,
-      612,  612,  612,  612,  612,  612,  612,  612,  612,  612,
-      612, -492, -492, -492, -492, -492, -492, -492, -492, -492,
-     -492, -492, -492, -492, -492, -492, -492, -492, -492, -492,
-     -492, -492, -492, -492, -492, -492, -492, -492, -492, -492,
-     -492, -492, -492, -492, -492, -492, -492, -492
-    },
-
-    {
-       67, -493, -493, -493, -493, -493, -493, -493, -493, -493,
-
-     -493, -493, -493, -493, -493, -493, -493, -493, -493, -493,
-     -493, -493, -493, -493, -493, -493, -493, -493, -493, -493,
-     -493, -493,  612, -493, -493, -493, -493, -493, -493, -493,
-     -493, -493, -493, -493, -493, -493, -493, -493,  613,  613,
-      613,  613,  613,  613,  613,  613,  613,  613, -493, -493,
-     -493, -493, -493, -493, -493,  612,  612,  612,  612,  612,
-      612,  612,  612,  612,  612,  612,  612,  612,  612,  612,
-      612,  612,  612,  612,  612,  612,  612,  612,  612,  612,
-      612, -493, -493, -493, -493, -493, -493, -493, -493, -493,
-     -493, -493, -493, -493, -493, -493, -493, -493, -493, -493,
-
-     -493, -493, -493, -493, -493, -493, -493, -493, -493, -493,
-     -493, -493, -493, -493, -493, -493, -493, -493
-    },
-
-    {
-       67, -494, -494, -494, -494, -494, -494, -494, -494, -494,
-     -494, -494, -494, -494, -494, -494, -494, -494, -494, -494,
-     -494, -494, -494, -494, -494, -494, -494, -494, -494, -494,
-     -494, -494,  614, -494, -494, -494, -494, -494, -494, -494,
-     -494, -494, -494, -494, -494, -494, -494, -494, -494, -494,
-     -494, -494, -494, -494, -494, -494, -494, -494, -494, -494,
-     -494, -494, -494, -494, -494, -494, -494, -494, -494, -494,
-     -494, -494, -494, -494, -494, -494, -494, -494, -494, -494,
-
-     -494, -494, -494, -494, -494, -494, -494, -494, -494, -494,
-     -494, -494, -494, -494, -494, -494, -494, -494, -494, -494,
-     -494, -494, -494, -494, -494, -494, -494, -494, -494, -494,
-     -494, -494, -494, -494, -494, -494, -494, -494, -494, -494,
-     -494, -494, -494, -494, -494, -494, -494, -494
-    },
-
-    {
-       67, -495, -495, -495, -495, -495, -495, -495, -495, -495,
-     -495, -495, -495, -495, -495, -495, -495, -495, -495, -495,
-     -495, -495, -495, -495, -495, -495, -495, -495, -495, -495,
-     -495, -495,  615, -495, -495, -495, -495, -495, -495, -495,
-     -495, -495, -495, -495, -495, -495, -495, -495,  616,  616,
-
-      616,  616,  616,  616,  616,  616,  616,  616, -495, -495,
-     -495, -495, -495, -495, -495,  615,  615,  615,  615,  615,
-      615,  615,  615,  615,  615,  615,  615,  615,  615,  615,
-      615,  615,  615,  615,  615,  615,  615,  615,  615,  615,
-      615, -495, -495, -495, -495, -495, -495, -495, -495, -495,
-     -495, -495, -495, -495, -495, -495, -495, -495, -495, -495,
-     -495, -495, -495, -495, -495, -495, -495, -495, -495, -495,
-     -495, -495, -495, -495, -495, -495, -495, -495
-    },
-
-    {
-       67, -496, -496, -496, -496, -496, -496, -496, -496, -496,
-     -496, -496, -496, -496, -496, -496, -496, -496, -496, -496,
-
-     -496, -496, -496, -496, -496, -496, -496, -496, -496, -496,
-     -496, -496, -496, -496, -496, -496, -496, -496, -496, -496,
-     -496, -496, -496, -496, -496, -496, -496, -496,  617,  617,
-      617,  617,  617,  617,  617,  617,  617,  617, -496, -496,
-     -496, -496, -496, -496, -496, -496, -496, -496, -496, -496,
-     -496, -496, -496, -496, -496, -496, -496, -496, -496, -496,
-     -496, -496, -496, -496, -496, -496, -496, -496, -496, -496,
-     -496, -496, -496, -496, -496, -496, -496, -496, -496, -496,
-     -496, -496, -496, -496, -496, -496, -496, -496, -496, -496,
-     -496, -496, -496, -496, -496, -496, -496, -496, -496, -496,
-
-     -496, -496, -496, -496, -496, -496, -496, -496
-    },
-
-    {
-       67, -497, -497, -497, -497, -497, -497, -497, -497, -497,
-     -497, -497, -497, -497, -497, -497, -497, -497, -497, -497,
-     -497, -497, -497, -497, -497, -497, -497, -497, -497, -497,
-     -497, -497,  618, -497, -497, -497, -497, -497, -497, -497,
-     -497, -497, -497, -497, -497, -497, -497, -497, -497, -497,
-     -497, -497, -497, -497, -497, -497, -497, -497, -497, -497,
-     -497, -497, -497, -497, -497,  618,  618,  618,  618,  618,
-      618,  618,  618,  618,  618,  618,  618,  618,  618,  618,
-      618,  618,  618,  618,  618,  618,  618,  618,  618,  618,
-
-      618, -497, -497, -497, -497, -497, -497, -497, -497, -497,
-     -497, -497, -497, -497, -497, -497, -497, -497, -497, -497,
-     -497, -497, -497, -497, -497, -497, -497, -497, -497, -497,
-     -497, -497, -497, -497, -497, -497, -497, -497
-    },
-
-    {
-       67, -498, -498, -498, -498, -498, -498, -498, -498, -498,
-     -498, -498, -498, -498, -498, -498, -498, -498, -498, -498,
-     -498, -498, -498, -498, -498, -498, -498, -498, -498, -498,
-     -498, -498,  618, -498, -498, -498, -498, -498, -498, -498,
-     -498, -498, -498, -498, -498, -498, -498, -498,  619,  619,
-      619,  619,  619,  619,  619,  619,  619,  619, -498, -498,
-
-     -498, -498, -498, -498, -498,  618,  618,  618,  618,  618,
-      618,  618,  618,  618,  618,  618,  618,  618,  618,  618,
-      618,  618,  618,  618,  618,  618,  618,  618,  618,  618,
-      618, -498, -498, -498, -498, -498, -498, -498, -498, -498,
-     -498, -498, -498, -498, -498, -498, -498, -498, -498, -498,
-     -498, -498, -498, -498, -498, -498, -498, -498, -498, -498,
-     -498, -498, -498, -498, -498, -498, -498, -498
-    },
-
-    {
-       67, -499, -499, -499, -499, -499, -499, -499, -499, -499,
-     -499, -499, -499, -499, -499, -499, -499, -499, -499, -499,
-     -499, -499, -499, -499, -499, -499, -499, -499, -499, -499,
-
-     -499, -499,  620, -499, -499, -499, -499, -499, -499, -499,
-     -499, -499, -499, -499, -499, -499, -499, -499, -499, -499,
-     -499, -499, -499, -499, -499, -499, -499, -499, -499, -499,
-     -499, -499, -499, -499, -499, -499, -499, -499, -499, -499,
-     -499, -499, -499, -499, -499, -499, -499, -499, -499, -499,
-     -499, -499, -499, -499, -499, -499, -499, -499, -499, -499,
-     -499, -499, -499, -499, -499, -499, -499, -499, -499, -499,
-     -499, -499, -499, -499, -499, -499, -499, -499, -499, -499,
-     -499, -499, -499, -499, -499, -499, -499, -499, -499, -499,
-     -499, -499, -499, -499, -499, -499, -499, -499
-
-    },
-
-    {
-       67, -500, -500, -500, -500, -500, -500, -500, -500, -500,
-     -500, -500, -500, -500, -500, -500, -500, -500, -500, -500,
-     -500, -500, -500, -500, -500, -500, -500, -500, -500, -500,
-     -500, -500,  621, -500, -500, -500, -500, -500, -500, -500,
-     -500, -500, -500, -500, -500, -500, -500, -500,  622,  622,
-      622,  622,  622,  622,  622,  622,  622,  622, -500, -500,
-     -500, -500, -500, -500, -500,  621,  621,  621,  621,  621,
-      621,  621,  621,  621,  621,  621,  621,  621,  621,  621,
-      621,  621,  621,  621,  621,  621,  621,  621,  621,  621,
-      621, -500, -500, -500, -500, -500, -500, -500, -500, -500,
-
-     -500, -500, -500, -500, -500, -500, -500, -500, -500, -500,
-     -500, -500, -500, -500, -500, -500, -500, -500, -500, -500,
-     -500, -500, -500, -500, -500, -500, -500, -500
-    },
-
-    {
-       67, -501, -501, -501, -501, -501, -501, -501, -501, -501,
-     -501, -501, -501, -501, -501, -501, -501, -501, -501, -501,
-     -501, -501, -501, -501, -501, -501, -501, -501, -501, -501,
-     -501, -501, -501, -501, -501, -501, -501, -501, -501, -501,
-     -501, -501, -501, -501, -501, -501, -501, -501, -501, -501,
-     -501, -501, -501, -501, -501, -501, -501, -501, -501, -501,
-     -501, -501, -501, -501, -501, -501, -501, -501, -501, -501,
-
-     -501, -501, -501, -501, -501, -501, -501, -501, -501, -501,
-     -501, -501, -501, -501, -501, -501, -501, -501, -501, -501,
-     -501, -501, -501, -501, -501,  623, -501, -501, -501, -501,
-     -501, -501, -501, -501, -501, -501, -501, -501, -501, -501,
-     -501, -501, -501, -501, -501, -501, -501, -501, -501, -501,
-     -501, -501, -501, -501, -501, -501, -501, -501
-    },
-
-    {
-       67, -502, -502, -502, -502, -502, -502, -502, -502, -502,
-     -502, -502, -502, -502, -502, -502, -502, -502, -502, -502,
-     -502, -502, -502, -502, -502, -502, -502, -502, -502, -502,
-     -502, -502, -502, -502, -502, -502, -502, -502, -502, -502,
-
-     -502, -502, -502, -502, -502, -502, -502, -502,  624,  625,
-      625,  625,  625,  625,  625,  625,  625,  625, -502, -502,
-     -502, -502, -502, -502, -502, -502, -502, -502, -502, -502,
-     -502, -502, -502, -502, -502, -502, -502, -502, -502, -502,
-     -502, -502, -502, -502, -502, -502, -502, -502, -502, -502,
-     -502, -502, -502, -502, -502, -502, -502, -502, -502, -502,
-     -502, -502, -502, -502, -502, -502, -502, -502, -502, -502,
-     -502, -502, -502, -502, -502, -502, -502, -502, -502, -502,
-     -502, -502, -502, -502, -502, -502, -502, -502
-    },
-
-    {
-       67, -503, -503, -503, -503, -503, -503, -503, -503, -503,
-
-     -503, -503, -503, -503, -503, -503, -503, -503, -503, -503,
-     -503, -503, -503, -503, -503, -503, -503, -503, -503, -503,
-     -503, -503,  626, -503, -503, -503, -503, -503, -503, -503,
-     -503, -503, -503, -503, -503, -503, -503, -503, -503, -503,
-     -503, -503, -503, -503, -503, -503, -503, -503, -503, -503,
-     -503, -503, -503, -503, -503,  626,  626,  626,  626,  626,
-      626,  626,  626,  626,  626,  626,  626,  626,  626,  626,
-      626,  626,  626,  626,  626,  626,  626,  626,  626,  626,
-      626, -503, -503, -503, -503, -503, -503, -503, -503, -503,
-     -503, -503, -503, -503, -503, -503, -503, -503, -503, -503,
-
-     -503, -503, -503, -503, -503, -503, -503, -503, -503, -503,
-     -503, -503, -503, -503, -503, -503, -503, -503
-    },
-
-    {
-       67, -504, -504, -504, -504, -504, -504, -504, -504, -504,
-     -504, -504, -504, -504, -504, -504, -504, -504, -504, -504,
-     -504, -504, -504, -504, -504, -504, -504, -504, -504, -504,
-     -504, -504,  626, -504, -504, -504, -504, -504, -504, -504,
-     -504, -504, -504, -504, -504, -504, -504, -504,  627,  627,
-      627,  627,  627,  627,  627,  627,  627,  627, -504, -504,
-     -504, -504, -504, -504, -504,  626,  626,  626,  626,  626,
-      626,  626,  626,  626,  626,  626,  626,  626,  626,  626,
-
-      626,  626,  626,  626,  626,  626,  626,  626,  626,  626,
-      626, -504, -504, -504, -504, -504, -504, -504, -504, -504,
-     -504, -504, -504, -504, -504, -504, -504, -504, -504, -504,
-     -504, -504, -504, -504, -504, -504, -504, -504, -504, -504,
-     -504, -504, -504, -504, -504, -504, -504, -504
-    },
-
-    {
-       67, -505, -505, -505, -505, -505, -505, -505, -505, -505,
-     -505, -505, -505, -505, -505, -505, -505, -505, -505, -505,
-     -505, -505, -505, -505, -505, -505, -505, -505, -505, -505,
-     -505, -505,  628, -505, -505, -505, -505, -505, -505, -505,
-     -505, -505, -505, -505, -505, -505, -505, -505, -505, -505,
-
-     -505, -505, -505, -505, -505, -505, -505, -505, -505, -505,
-     -505, -505, -505, -505, -505, -505, -505, -505, -505, -505,
-     -505, -505, -505, -505, -505, -505, -505, -505, -505, -505,
-     -505, -505, -505, -505, -505, -505, -505, -505, -505, -505,
-     -505, -505, -505, -505, -505, -505, -505, -505, -505, -505,
-     -505, -505, -505, -505, -505, -505, -505, -505, -505, -505,
-     -505, -505, -505, -505, -505, -505, -505, -505, -505, -505,
-     -505, -505, -505, -505, -505, -505, -505, -505
-    },
-
-    {
-       67, -506, -506, -506, -506, -506, -506, -506, -506, -506,
-     -506, -506, -506, -506, -506, -506, -506, -506, -506, -506,
-
-     -506, -506, -506, -506, -506, -506, -506, -506, -506, -506,
-     -506, -506,  629, -506, -506, -506, -506, -506, -506, -506,
-     -506, -506, -506, -506, -506, -506, -506, -506,  630,  630,
-      630,  630,  630,  630,  630,  630,  630,  630, -506, -506,
-     -506, -506, -506, -506, -506,  629,  629,  629,  629,  629,
-      629,  629,  629,  629,  629,  629,  629,  629,  629,  629,
-      629,  629,  629,  629,  629,  629,  629,  629,  629,  629,
-      629, -506, -506, -506, -506, -506, -506, -506, -506, -506,
-     -506, -506, -506, -506, -506, -506, -506, -506, -506, -506,
-     -506, -506, -506, -506, -506, -506, -506, -506, -506, -506,
-
-     -506, -506, -506, -506, -506, -506, -506, -506
-    },
-
-    {
-       67, -507, -507, -507, -507, -507, -507, -507, -507, -507,
-     -507, -507, -507, -507, -507, -507, -507, -507, -507, -507,
-     -507, -507, -507, -507, -507, -507, -507, -507, -507, -507,
-     -507, -507, -507, -507, -507, -507, -507, -507, -507, -507,
-     -507, -507, -507, -507, -507, -507, -507, -507,  631,  631,
-      631,  631,  631,  631,  631,  631,  631,  631, -507, -507,
-     -507, -507, -507, -507, -507, -507, -507, -507, -507, -507,
-     -507, -507, -507, -507, -507, -507, -507, -507, -507, -507,
-     -507, -507, -507, -507, -507, -507, -507, -507, -507, -507,
-
-     -507, -507, -507, -507, -507, -507, -507, -507, -507, -507,
-     -507, -507, -507, -507, -507, -507, -507, -507, -507, -507,
-     -507, -507, -507, -507, -507, -507, -507, -507, -507, -507,
-     -507, -507, -507, -507, -507, -507, -507, -507
-    },
-
-    {
-       67, -508, -508, -508, -508, -508, -508, -508, -508, -508,
-     -508, -508, -508, -508, -508, -508, -508, -508, -508, -508,
-     -508, -508, -508, -508, -508, -508, -508, -508, -508, -508,
-     -508, -508,  632, -508, -508, -508, -508, -508, -508, -508,
-     -508, -508, -508, -508, -508, -508, -508, -508, -508, -508,
-     -508, -508, -508, -508, -508, -508, -508, -508, -508, -508,
-
-     -508, -508, -508, -508, -508,  632,  632,  632,  632,  632,
-      632,  632,  632,  632,  632,  632,  632,  632,  632,  632,
-      632,  632,  632,  632,  632,  632,  632,  632,  632,  632,
-      632, -508, -508, -508, -508, -508, -508, -508, -508, -508,
-     -508, -508, -508, -508, -508, -508, -508, -508, -508, -508,
-     -508, -508, -508, -508, -508, -508, -508, -508, -508, -508,
-     -508, -508, -508, -508, -508, -508, -508, -508
-    },
-
-    {
-       67, -509, -509, -509, -509, -509, -509, -509, -509, -509,
-     -509, -509, -509, -509, -509, -509, -509, -509, -509, -509,
-     -509, -509, -509, -509, -509, -509, -509, -509, -509, -509,
-
-     -509, -509,  632, -509, -509, -509, -509, -509, -509, -509,
-     -509, -509, -509, -509, -509, -509, -509, -509,  633,  633,
-      633,  633,  633,  633,  633,  633,  633,  633, -509, -509,
-     -509, -509, -509, -509, -509,  632,  632,  632,  632,  632,
-      632,  632,  632,  632,  632,  632,  632,  632,  632,  632,
-      632,  632,  632,  632,  632,  632,  632,  632,  632,  632,
-      632, -509, -509, -509, -509, -509, -509, -509, -509, -509,
-     -509, -509, -509, -509, -509, -509, -509, -509, -509, -509,
-     -509, -509, -509, -509, -509, -509, -509, -509, -509, -509,
-     -509, -509, -509, -509, -509, -509, -509, -509
-
-    },
-
-    {
-       67, -510, -510, -510, -510, -510, -510, -510, -510, -510,
-     -510, -510, -510, -510, -510, -510, -510, -510, -510, -510,
-     -510, -510, -510, -510, -510, -510, -510, -510, -510, -510,
-     -510, -510,  634, -510, -510, -510, -510, -510, -510, -510,
-     -510, -510, -510, -510, -510, -510, -510, -510, -510, -510,
-     -510, -510, -510, -510, -510, -510, -510, -510, -510, -510,
-     -510, -510, -510, -510, -510, -510, -510, -510, -510, -510,
-     -510, -510, -510, -510, -510, -510, -510, -510, -510, -510,
-     -510, -510, -510, -510, -510, -510, -510, -510, -510, -510,
-     -510, -510, -510, -510, -510, -510, -510, -510, -510, -510,
-
-     -510, -510, -510, -510, -510, -510, -510, -510, -510, -510,
-     -510, -510, -510, -510, -510, -510, -510, -510, -510, -510,
-     -510, -510, -510, -510, -510, -510, -510, -510
-    },
-
-    {
-       67, -511, -511, -511, -511, -511, -511, -511, -511, -511,
-     -511, -511, -511, -511, -511, -511, -511, -511, -511, -511,
-     -511, -511, -511, -511, -511, -511, -511, -511, -511, -511,
-     -511, -511,  635, -511, -511, -511, -511, -511, -511, -511,
-     -511, -511, -511, -511, -511, -511, -511, -511,  636,  636,
-      636,  636,  636,  636,  636,  636,  636,  636, -511, -511,
-     -511, -511, -511, -511, -511,  635,  635,  635,  635,  635,
-
-      635,  635,  635,  635,  635,  635,  635,  635,  635,  635,
-      635,  635,  635,  635,  635,  635,  635,  635,  635,  635,
-      635, -511, -511, -511, -511, -511, -511, -511, -511, -511,
-     -511, -511, -511, -511, -511, -511, -511, -511, -511, -511,
-     -511, -511, -511, -511, -511, -511, -511, -511, -511, -511,
-     -511, -511, -511, -511, -511, -511, -511, -511
-    },
-
-    {
-       67, -512, -512, -512, -512, -512, -512, -512, -512, -512,
-     -512, -512, -512, -512, -512, -512, -512, -512, -512, -512,
-     -512, -512, -512, -512, -512, -512, -512, -512, -512, -512,
-     -512, -512, -512, -512, -512, -512, -512, -512, -512, -512,
-
-     -512, -512, -512, -512, -512, -512, -512, -512, -512, -512,
-     -512, -512, -512, -512, -512, -512, -512, -512, -512, -512,
-     -512, -512, -512, -512, -512, -512, -512, -512, -512, -512,
-     -512, -512, -512, -512, -512, -512, -512, -512, -512, -512,
-     -512, -512, -512, -512, -512, -512, -512, -512, -512, -512,
-     -512, -512, -512, -512, -512, -512, -512, -512, -512, -512,
-     -512, -512, -512, -512, -512, -512, -512, -512, -512, -512,
-     -512, -512, -512, -512, -512, -512, -512, -512, -512, -512,
-     -512, -512, -512, -512, -512, -512, -512, -512
-    },
-
-    {
-       67, -513, -513, -513, -513, -513, -513, -513, -513, -513,
-
-     -513, -513, -513, -513, -513, -513, -513, -513, -513, -513,
-     -513, -513, -513, -513, -513, -513, -513, -513, -513, -513,
-     -513, -513, -513, -513, -513, -513, -513, -513, -513, -513,
-     -513, -513, -513, -513, -513, -513, -513, -513, -513, -513,
-     -513, -513, -513, -513, -513, -513, -513, -513, -513, -513,
-     -513, -513, -513, -513, -513, -513, -513, -513, -513, -513,
-     -513, -513, -513, -513, -513, -513, -513, -513, -513, -513,
-     -513, -513, -513, -513, -513, -513, -513, -513, -513, -513,
-     -513, -513, -513, -513, -513, -513, -513, -513, -513, -513,
-     -513, -513, -513, -513, -513, -513, -513, -513, -513, -513,
-
-     -513, -513, -513, -513, -513, -513, -513, -513, -513, -513,
-     -513, -513, -513, -513, -513, -513, -513, -513
-    },
-
-    {
-       67, -514, -514, -514, -514, -514, -514, -514, -514, -514,
-     -514, -514, -514, -514, -514, -514, -514, -514, -514, -514,
-     -514, -514, -514, -514, -514, -514, -514, -514, -514, -514,
-     -514, -514, -514, -514, -514, -514, -514, -514, -514, -514,
-     -514, -514, -514, -514, -514, -514, -514, -514, -514, -514,
-     -514, -514, -514, -514, -514, -514, -514, -514, -514, -514,
-     -514, -514, -514, -514, -514, -514, -514, -514, -514, -514,
-     -514, -514, -514, -514, -514, -514, -514, -514, -514, -514,
-
-     -514, -514, -514, -514, -514, -514, -514, -514, -514, -514,
-     -514, -514, -514, -514, -514, -514, -514, -514, -514, -514,
-     -514, -514, -514, -514, -514, -514, -514, -514, -514, -514,
-     -514, -514, -514, -514, -514, -514, -514, -514, -514, -514,
-     -514, -514, -514, -514, -514, -514, -514, -514
-    },
-
-    {
-       67, -515, -515, -515, -515, -515, -515, -515, -515, -515,
-     -515, -515, -515, -515, -515, -515, -515, -515, -515, -515,
-     -515, -515, -515, -515, -515, -515, -515, -515, -515, -515,
-     -515, -515, -515, -515, -515, -515, -515, -515, -515, -515,
-     -515, -515, -515, -515, -515, -515, -515, -515, -515, -515,
-
-     -515, -515, -515, -515, -515, -515, -515, -515, -515, -515,
-     -515, -515, -515, -515, -515, -515, -515, -515, -515, -515,
-     -515, -515, -515, -515, -515, -515, -515, -515, -515, -515,
-     -515, -515, -515, -515, -515, -515, -515, -515, -515, -515,
-     -515, -515, -515, -515, -515, -515, -515, -515, -515, -515,
-     -515, -515, -515, -515, -515, -515, -515, -515, -515, -515,
-     -515, -515, -515, -515, -515, -515, -515, -515, -515, -515,
-     -515, -515, -515, -515, -515, -515, -515, -515
-    },
-
-    {
-       67, -516, -516, -516, -516, -516, -516, -516, -516, -516,
-     -516, -516, -516, -516, -516, -516, -516, -516, -516, -516,
-
-     -516, -516, -516, -516, -516, -516, -516, -516, -516, -516,
-     -516, -516, -516, -516, -516, -516, -516, -516, -516, -516,
-     -516, -516, -516, -516, -516, -516, -516, -516, -516, -516,
-     -516, -516, -516, -516, -516, -516, -516, -516, -516, -516,
-     -516, -516, -516, -516, -516, -516, -516, -516, -516, -516,
-     -516, -516, -516, -516, -516, -516, -516, -516, -516, -516,
-     -516, -516, -516, -516, -516, -516, -516, -516, -516, -516,
-     -516, -516, -516, -516, -516, -516, -516, -516, -516, -516,
-     -516, -516, -516, -516, -516, -516, -516, -516, -516, -516,
-     -516, -516, -516, -516, -516, -516, -516, -516, -516, -516,
-
-     -516, -516, -516, -516, -516, -516, -516, -516
-    },
-
-    {
-       67, -517, -517, -517, -517, -517, -517, -517, -517, -517,
-     -517, -517, -517, -517, -517, -517, -517, -517, -517, -517,
-     -517, -517, -517, -517, -517, -517, -517, -517, -517, -517,
-     -517, -517, -517, -517, -517, -517, -517, -517, -517, -517,
-     -517, -517, -517, -517, -517, -517, -517, -517, -517, -517,
-     -517, -517, -517, -517, -517, -517, -517, -517, -517, -517,
-     -517, -517, -517, -517, -517, -517, -517, -517, -517, -517,
-     -517, -517, -517, -517, -517, -517, -517, -517, -517, -517,
-     -517, -517, -517, -517, -517, -517, -517, -517, -517, -517,
-
-     -517, -517, -517, -517, -517, -517, -517, -517, -517, -517,
-     -517, -517, -517, -517, -517, -517, -517, -517, -517, -517,
-     -517, -517, -517, -517, -517, -517, -517, -517, -517, -517,
-     -517, -517, -517, -517, -517, -517, -517, -517
-    },
-
-    {
-       67, -518, -518, -518, -518, -518, -518, -518, -518, -518,
-     -518, -518, -518, -518, -518, -518, -518, -518, -518, -518,
-     -518, -518, -518, -518, -518, -518, -518, -518, -518, -518,
-     -518, -518, -518, -518, -518, -518, -518, -518, -518, -518,
-     -518, -518, -518, -518, -518, -518, -518, -518, -518, -518,
-     -518, -518, -518, -518, -518, -518, -518, -518, -518, -518,
-
-     -518, -518, -518, -518, -518, -518, -518, -518, -518, -518,
-     -518, -518, -518, -518, -518, -518, -518, -518, -518, -518,
-     -518, -518, -518, -518, -518, -518, -518, -518, -518, -518,
-     -518, -518, -518, -518, -518, -518, -518, -518, -518, -518,
-     -518, -518, -518, -518, -518, -518, -518, -518, -518, -518,
-     -518, -518, -518, -518, -518, -518, -518, -518, -518, -518,
-     -518, -518, -518, -518, -518, -518, -518, -518
-    },
-
-    {
-       67, -519, -519, -519, -519, -519, -519, -519, -519, -519,
-     -519, -519, -519, -519, -519, -519, -519, -519, -519, -519,
-     -519, -519, -519, -519, -519, -519, -519, -519, -519, -519,
-
-     -519, -519, -519, -519, -519, -519, -519, -519, -519, -519,
-     -519, -519, -519, -519, -519, -519, -519, -519, -519, -519,
-     -519, -519, -519, -519, -519, -519, -519, -519, -519, -519,
-     -519, -519, -519, -519, -519, -519, -519, -519, -519, -519,
-     -519, -519, -519, -519, -519, -519, -519, -519, -519, -519,
-     -519, -519, -519, -519, -519, -519, -519, -519, -519, -519,
-     -519, -519, -519, -519, -519, -519, -519, -519, -519, -519,
-     -519, -519, -519, -519, -519, -519, -519, -519, -519, -519,
-     -519, -519, -519, -519, -519, -519, -519, -519, -519, -519,
-     -519, -519, -519, -519, -519, -519, -519, -519
-
-    },
-
-    {
-       67, -520, -520, -520, -520, -520, -520, -520, -520, -520,
-     -520, -520, -520, -520, -520, -520, -520, -520, -520, -520,
-     -520, -520, -520, -520, -520, -520, -520, -520, -520, -520,
-     -520, -520, -520, -520, -520, -520, -520, -520, -520, -520,
-     -520, -520, -520, -520, -520, -520, -520, -520, -520, -520,
-     -520, -520, -520, -520, -520, -520, -520, -520, -520, -520,
-     -520, -520, -520, -520, -520, -520, -520, -520, -520, -520,
-     -520, -520, -520, -520, -520, -520, -520, -520, -520, -520,
-     -520, -520, -520, -520, -520, -520, -520, -520, -520, -520,
-     -520, -520, -520, -520, -520, -520, -520, -520, -520, -520,
-
-     -520, -520, -520, -520, -520, -520, -520, -520, -520, -520,
-     -520, -520, -520, -520, -520, -520, -520, -520, -520, -520,
-     -520, -520, -520, -520, -520, -520, -520, -520
-    },
-
-    {
-       67, -521, -521, -521, -521, -521, -521, -521, -521, -521,
-     -521, -521, -521, -521, -521, -521, -521, -521, -521, -521,
-     -521, -521, -521, -521, -521, -521, -521, -521, -521, -521,
-     -521, -521, -521, -521, -521, -521, -521, -521, -521, -521,
-     -521, -521, -521, -521, -521, -521, -521, -521, -521, -521,
-     -521, -521, -521, -521, -521, -521, -521, -521, -521, -521,
-     -521, -521, -521, -521, -521, -521, -521, -521, -521, -521,
-
-     -521, -521, -521, -521, -521, -521, -521, -521, -521, -521,
-     -521, -521, -521, -521, -521, -521, -521, -521, -521, -521,
-     -521, -521, -521, -521, -521, -521, -521, -521, -521, -521,
-     -521, -521, -521, -521, -521, -521, -521, -521, -521, -521,
-     -521, -521, -521, -521, -521, -521, -521, -521, -521, -521,
-     -521, -521, -521, -521, -521, -521, -521, -521
-    },
-
-    {
-       67, -522, -522, -522, -522, -522, -522, -522, -522, -522,
-     -522, -522, -522, -522, -522, -522, -522, -522, -522, -522,
-     -522, -522, -522, -522, -522, -522, -522, -522, -522, -522,
-     -522, -522, -522, -522, -522, -522, -522, -522, -522, -522,
-
-     -522, -522, -522, -522, -522, -522, -522, -522, -522, -522,
-     -522, -522, -522, -522, -522, -522, -522, -522, -522, -522,
-     -522, -522, -522, -522, -522, -522, -522, -522, -522, -522,
-     -522, -522, -522, -522, -522, -522, -522, -522, -522, -522,
-     -522, -522, -522, -522, -522, -522, -522, -522, -522, -522,
-     -522, -522, -522, -522, -522, -522, -522, -522, -522, -522,
-     -522, -522, -522, -522, -522, -522, -522, -522, -522, -522,
-     -522, -522, -522, -522, -522, -522, -522, -522, -522, -522,
-     -522, -522, -522, -522, -522, -522, -522, -522
-    },
-
-    {
-       67, -523, -523, -523, -523, -523, -523, -523, -523, -523,
-
-     -523, -523, -523, -523, -523, -523, -523, -523, -523, -523,
-     -523, -523, -523, -523, -523, -523, -523, -523, -523, -523,
-     -523, -523, -523, -523, -523, -523, -523, -523, -523, -523,
-     -523, -523, -523, -523, -523, -523, -523, -523, -523, -523,
-     -523, -523, -523, -523, -523, -523, -523, -523, -523, -523,
-     -523, -523, -523, -523, -523, -523, -523, -523, -523, -523,
-     -523, -523, -523, -523, -523, -523, -523, -523, -523, -523,
-     -523, -523, -523, -523, -523, -523, -523, -523, -523, -523,
-     -523, -523, -523, -523, -523, -523, -523, -523, -523, -523,
-     -523, -523, -523, -523, -523, -523, -523, -523, -523, -523,
-
-     -523, -523, -523, -523, -523, -523, -523, -523, -523, -523,
-     -523, -523, -523, -523, -523, -523, -523, -523
-    },
-
-    {
-       67, -524, -524, -524, -524, -524, -524, -524, -524, -524,
-     -524, -524, -524, -524, -524, -524, -524, -524, -524, -524,
-     -524, -524, -524, -524, -524, -524, -524, -524, -524, -524,
-     -524, -524, -524, -524, -524, -524, -524, -524, -524, -524,
-     -524, -524, -524, -524, -524, -524, -524, -524, -524, -524,
-     -524, -524, -524, -524, -524, -524, -524, -524, -524, -524,
-     -524, -524, -524, -524, -524, -524, -524, -524, -524, -524,
-     -524, -524, -524, -524, -524, -524, -524, -524, -524, -524,
-
-     -524, -524, -524, -524, -524, -524, -524, -524, -524, -524,
-     -524, -524, -524, -524, -524, -524, -524, -524, -524, -524,
-     -524, -524, -524, -524, -524, -524, -524, -524, -524, -524,
-     -524, -524, -524, -524, -524, -524, -524, -524, -524, -524,
-     -524, -524, -524, -524, -524, -524, -524, -524
-    },
-
-    {
-       67, -525, -525, -525, -525, -525, -525, -525, -525, -525,
-     -525, -525, -525, -525, -525, -525, -525, -525, -525, -525,
-     -525, -525, -525, -525, -525, -525, -525, -525, -525, -525,
-     -525, -525, -525, -525, -525, -525, -525, -525, -525, -525,
-     -525, -525, -525, -525, -525, -525, -525, -525, -525, -525,
-
-     -525, -525, -525, -525, -525, -525, -525, -525, -525, -525,
-     -525, -525, -525, -525, -525, -525, -525, -525, -525, -525,
-     -525, -525, -525, -525, -525, -525, -525, -525, -525, -525,
-     -525, -525, -525, -525, -525, -525, -525, -525, -525, -525,
-     -525, -525, -525, -525, -525, -525, -525, -525, -525, -525,
-     -525, -525, -525, -525, -525, -525, -525, -525, -525, -525,
-     -525, -525, -525, -525, -525, -525, -525, -525, -525, -525,
-     -525, -525, -525, -525, -525, -525, -525, -525
-    },
-
-    {
-       67, -526, -526, -526, -526, -526, -526, -526, -526, -526,
-     -526, -526, -526, -526, -526, -526, -526, -526, -526, -526,
-
-     -526, -526, -526, -526, -526, -526, -526, -526, -526, -526,
-     -526, -526, -526, -526, -526, -526, -526, -526, -526, -526,
-     -526, -526, -526, -526, -526, -526, -526, -526, -526, -526,
-     -526, -526, -526, -526, -526, -526, -526, -526, -526, -526,
-     -526, -526, -526, -526, -526, -526, -526, -526, -526, -526,
-     -526, -526, -526, -526, -526, -526, -526, -526, -526, -526,
-     -526, -526, -526, -526, -526, -526, -526, -526, -526, -526,
-     -526, -526, -526, -526, -526, -526, -526, -526, -526, -526,
-     -526, -526, -526, -526, -526, -526, -526, -526, -526, -526,
-     -526, -526, -526, -526, -526, -526, -526, -526, -526, -526,
-
-     -526, -526, -526, -526, -526, -526, -526, -526
-    },
-
-    {
-       67, -527, -527, -527, -527, -527, -527, -527, -527, -527,
-     -527, -527, -527, -527, -527, -527, -527, -527, -527, -527,
-     -527, -527, -527, -527, -527, -527, -527, -527, -527, -527,
-     -527, -527, -527, -527, -527, -527, -527, -527, -527, -527,
-     -527, -527, -527, -527, -527, -527, -527, -527, -527, -527,
-     -527, -527, -527, -527, -527, -527, -527, -527, -527, -527,
-     -527, -527, -527, -527, -527, -527, -527, -527, -527, -527,
-     -527, -527, -527, -527, -527, -527, -527, -527, -527, -527,
-     -527, -527, -527, -527, -527, -527, -527, -527, -527, -527,
-
-     -527, -527, -527, -527, -527, -527, -527, -527, -527, -527,
-     -527, -527, -527, -527, -527, -527, -527, -527, -527, -527,
-     -527, -527, -527, -527, -527, -527, -527, -527, -527, -527,
-     -527, -527, -527, -527, -527, -527, -527, -527
-    },
-
-    {
-       67, -528, -528, -528, -528, -528, -528, -528, -528, -528,
-     -528, -528, -528, -528, -528, -528, -528, -528, -528, -528,
-     -528, -528, -528, -528, -528, -528, -528, -528, -528, -528,
-     -528, -528, -528, -528, -528, -528, -528, -528, -528, -528,
-     -528, -528, -528, -528, -528, -528, -528, -528, -528, -528,
-     -528, -528, -528, -528, -528, -528, -528, -528, -528, -528,
-
-     -528, -528, -528, -528, -528, -528, -528, -528, -528, -528,
-     -528, -528, -528, -528, -528, -528, -528, -528, -528, -528,
-     -528, -528, -528, -528, -528, -528, -528, -528, -528, -528,
-     -528, -528, -528, -528, -528, -528, -528, -528, -528, -528,
-     -528, -528, -528, -528, -528, -528, -528, -528, -528, -528,
-     -528, -528, -528, -528, -528, -528, -528, -528, -528, -528,
-     -528, -528, -528, -528, -528, -528, -528, -528
-    },
-
-    {
-       67, -529, -529, -529, -529, -529, -529, -529, -529, -529,
-     -529, -529, -529, -529, -529, -529, -529, -529, -529, -529,
-     -529, -529, -529, -529, -529, -529, -529, -529, -529, -529,
-
-     -529, -529, -529, -529, -529, -529, -529, -529, -529, -529,
-     -529, -529, -529, -529, -529, -529, -529, -529, -529, -529,
-     -529, -529, -529, -529, -529, -529, -529, -529, -529, -529,
-     -529, -529, -529, -529, -529, -529, -529, -529, -529, -529,
-     -529, -529, -529, -529, -529, -529, -529, -529, -529, -529,
-     -529, -529, -529, -529, -529, -529, -529, -529, -529, -529,
-     -529, -529, -529, -529, -529, -529, -529, -529, -529, -529,
-     -529, -529, -529, -529, -529, -529, -529, -529, -529, -529,
-     -529, -529, -529, -529, -529, -529, -529, -529, -529, -529,
-     -529, -529, -529, -529, -529, -529, -529, -529
-
-    },
-
-    {
-       67, -530, -530, -530, -530, -530, -530, -530, -530, -530,
-     -530, -530, -530, -530, -530, -530, -530, -530, -530, -530,
-     -530, -530, -530, -530, -530, -530, -530, -530, -530, -530,
-     -530, -530, -530, -530, -530, -530, -530, -530, -530, -530,
-     -530, -530, -530, -530, -530, -530, -530, -530, -530, -530,
-     -530, -530, -530, -530, -530, -530, -530, -530, -530, -530,
-     -530, -530, -530, -530, -530, -530, -530, -530, -530, -530,
-     -530, -530, -530, -530, -530, -530, -530, -530, -530, -530,
-     -530, -530, -530, -530, -530, -530, -530, -530, -530, -530,
-     -530, -530, -530, -530, -530, -530, -530, -530, -530, -530,
-
-     -530, -530, -530, -530, -530, -530, -530, -530, -530, -530,
-     -530, -530, -530, -530, -530, -530, -530, -530, -530, -530,
-     -530, -530, -530, -530, -530, -530, -530, -530
-    },
-
-    {
-       67, -531, -531, -531, -531, -531, -531, -531, -531, -531,
-     -531, -531, -531, -531, -531, -531, -531, -531, -531, -531,
-     -531, -531, -531, -531, -531, -531, -531, -531, -531, -531,
-     -531, -531, -531, -531, -531, -531, -531, -531, -531, -531,
-     -531, -531, -531, -531, -531, -531, -531, -531, -531, -531,
-     -531, -531, -531, -531, -531, -531, -531, -531, -531, -531,
-     -531, -531, -531, -531, -531, -531, -531, -531, -531, -531,
-
-     -531, -531, -531, -531, -531, -531, -531, -531, -531, -531,
-     -531, -531, -531, -531, -531, -531, -531, -531, -531, -531,
-     -531, -531, -531, -531, -531, -531, -531, -531, -531, -531,
-     -531, -531, -531, -531, -531, -531, -531, -531, -531, -531,
-     -531, -531, -531, -531, -531, -531, -531, -531, -531, -531,
-     -531, -531, -531, -531, -531, -531, -531, -531
-    },
-
-    {
-       67, -532, -532, -532, -532, -532, -532, -532, -532, -532,
-     -532, -532, -532, -532, -532, -532, -532, -532, -532, -532,
-     -532, -532, -532, -532, -532, -532, -532, -532, -532, -532,
-     -532, -532, -532, -532, -532, -532, -532, -532, -532, -532,
-
-     -532, -532, -532, -532, -532, -532, -532, -532, -532, -532,
-     -532, -532, -532, -532, -532, -532, -532, -532, -532, -532,
-     -532, -532, -532, -532, -532, -532, -532, -532, -532, -532,
-     -532, -532, -532, -532, -532, -532, -532, -532, -532, -532,
-     -532, -532, -532, -532, -532, -532, -532, -532, -532, -532,
-     -532, -532, -532, -532, -532, -532, -532, -532, -532, -532,
-     -532, -532, -532, -532, -532, -532, -532, -532, -532, -532,
-     -532, -532, -532, -532, -532, -532, -532, -532, -532, -532,
-     -532, -532, -532, -532, -532, -532, -532, -532
-    },
-
-    {
-       67, -533, -533, -533, -533, -533, -533, -533, -533, -533,
-
-     -533, -533, -533, -533, -533, -533, -533, -533, -533, -533,
-     -533, -533, -533, -533, -533, -533, -533, -533, -533, -533,
-     -533, -533, -533, -533, -533, -533, -533, -533, -533, -533,
-     -533, -533, -533, -533, -533, -533, -533, -533, -533, -533,
-     -533, -533, -533, -533, -533, -533, -533, -533, -533, -533,
-     -533, -533, -533, -533, -533, -533, -533, -533, -533, -533,
-     -533, -533, -533, -533, -533, -533, -533, -533, -533, -533,
-     -533, -533, -533, -533, -533, -533, -533, -533, -533, -533,
-     -533, -533, -533, -533, -533, -533, -533, -533, -533, -533,
-     -533, -533, -533, -533, -533, -533, -533, -533, -533, -533,
-
-     -533, -533, -533, -533, -533, -533, -533, -533, -533, -533,
-     -533, -533, -533, -533, -533, -533, -533, -533
-    },
-
-    {
-       67, -534, -534, -534, -534, -534, -534, -534, -534, -534,
-     -534, -534, -534, -534, -534, -534, -534, -534, -534, -534,
-     -534, -534, -534, -534, -534, -534, -534, -534, -534, -534,
-     -534, -534, -534, -534, -534, -534, -534, -534, -534, -534,
-     -534, -534, -534, -534, -534, -534, -534, -534, -534, -534,
-     -534, -534, -534, -534, -534, -534, -534, -534, -534, -534,
-     -534, -534, -534, -534, -534, -534, -534, -534, -534, -534,
-     -534, -534, -534, -534, -534, -534, -534, -534, -534, -534,
-
-     -534, -534, -534, -534, -534, -534, -534, -534, -534, -534,
-     -534, -534, -534, -534, -534, -534, -534, -534, -534, -534,
-     -534, -534, -534, -534, -534, -534, -534, -534, -534, -534,
-     -534, -534, -534, -534, -534, -534, -534, -534, -534, -534,
-     -534, -534, -534, -534, -534, -534, -534, -534
-    },
-
-    {
-       67, -535, -535, -535, -535, -535, -535, -535, -535, -535,
-     -535, -535, -535, -535, -535, -535, -535, -535, -535, -535,
-     -535, -535, -535, -535, -535, -535, -535, -535, -535, -535,
-     -535, -535, -535, -535, -535, -535, -535, -535, -535, -535,
-     -535, -535, -535, -535, -535, -535, -535, -535, -535, -535,
-
-     -535, -535, -535, -535, -535, -535, -535, -535, -535, -535,
-     -535, -535, -535, -535, -535, -535, -535, -535, -535, -535,
-     -535, -535, -535, -535, -535, -535, -535, -535, -535, -535,
-     -535, -535, -535, -535, -535, -535, -535, -535, -535, -535,
-     -535, -535, -535, -535, -535, -535, -535, -535, -535, -535,
-     -535, -535, -535, -535, -535, -535, -535, -535, -535, -535,
-     -535, -535, -535, -535, -535, -535, -535, -535, -535, -535,
-     -535, -535, -535, -535, -535, -535, -535, -535
-    },
-
-    {
-       67, -536, -536, -536, -536, -536, -536, -536, -536, -536,
-     -536, -536, -536, -536, -536, -536, -536, -536, -536, -536,
-
-     -536, -536, -536, -536, -536, -536, -536, -536, -536, -536,
-     -536, -536, -536, -536, -536, -536, -536, -536, -536, -536,
-     -536, -536, -536, -536, -536, -536, -536, -536, -536, -536,
-     -536, -536, -536, -536, -536, -536, -536, -536, -536, -536,
-     -536, -536, -536, -536, -536, -536, -536, -536, -536, -536,
-     -536, -536, -536, -536, -536, -536, -536, -536, -536, -536,
-     -536, -536, -536, -536, -536, -536, -536, -536, -536, -536,
-     -536, -536, -536, -536, -536, -536, -536, -536, -536, -536,
-     -536, -536, -536, -536, -536, -536, -536, -536, -536, -536,
-     -536, -536, -536, -536, -536, -536, -536, -536, -536, -536,
-
-     -536, -536, -536, -536, -536, -536, -536, -536
-    },
-
-    {
-       67, -537, -537, -537, -537, -537, -537, -537, -537, -537,
-     -537, -537, -537, -537, -537, -537, -537, -537, -537, -537,
-     -537, -537, -537, -537, -537, -537, -537, -537, -537, -537,
-     -537, -537, -537, -537, -537, -537, -537, -537, -537, -537,
-     -537, -537, -537, -537, -537, -537, -537, -537, -537, -537,
-     -537, -537, -537, -537, -537, -537, -537, -537, -537, -537,
-     -537, -537, -537, -537, -537,  637, -537, -537, -537, -537,
-     -537, -537, -537, -537, -537, -537, -537, -537, -537,  638,
-     -537, -537, -537, -537, -537, -537, -537, -537, -537, -537,
-
-     -537, -537, -537, -537, -537, -537, -537, -537, -537, -537,
-     -537, -537, -537, -537, -537, -537, -537, -537, -537, -537,
-     -537, -537, -537, -537, -537, -537, -537, -537, -537, -537,
-     -537, -537, -537, -537, -537, -537, -537, -537
-    },
-
-    {
-       67, -538, -538, -538, -538, -538, -538, -538, -538, -538,
-     -538, -538, -538, -538, -538, -538, -538, -538, -538, -538,
-     -538, -538, -538, -538, -538, -538, -538, -538, -538, -538,
-     -538, -538,  639, -538, -538, -538, -538, -538, -538, -538,
-     -538, -538, -538, -538, -538, -538, -538, -538,  640,  640,
-      640,  640,  640,  640,  640,  640,  640,  640, -538, -538,
-
-     -538, -538, -538, -538, -538, -538, -538, -538, -538, -538,
-     -538, -538, -538, -538, -538, -538, -538, -538, -538, -538,
-     -538, -538, -538, -538, -538, -538, -538, -538, -538, -538,
-     -538, -538, -538, -538, -538, -538, -538, -538, -538, -538,
-     -538, -538, -538, -538, -538, -538, -538, -538, -538, -538,
-     -538, -538, -538, -538, -538, -538, -538, -538, -538, -538,
-     -538, -538, -538, -538, -538, -538, -538, -538
-    },
-
-    {
-       67, -539, -539, -539, -539, -539, -539, -539, -539, -539,
-     -539, -539, -539, -539, -539, -539, -539, -539, -539, -539,
-     -539, -539, -539, -539, -539, -539, -539, -539, -539, -539,
-
-     -539, -539,  641, -539, -539, -539, -539, -539, -539, -539,
-     -539, -539, -539, -539, -539, -539, -539, -539, -539, -539,
-     -539, -539, -539, -539, -539, -539, -539, -539, -539, -539,
-     -539, -539, -539, -539, -539, -539, -539, -539, -539, -539,
-     -539, -539, -539, -539, -539, -539, -539, -539, -539, -539,
-     -539, -539, -539, -539, -539, -539, -539, -539, -539, -539,
-     -539, -539, -539, -539, -539, -539, -539, -539, -539, -539,
-     -539, -539, -539, -539, -539, -539, -539, -539, -539, -539,
-     -539, -539, -539, -539, -539, -539, -539, -539, -539, -539,
-     -539, -539, -539, -539, -539, -539, -539, -539
-
-    },
-
-    {
-       67, -540, -540, -540, -540, -540, -540, -540, -540, -540,
-     -540, -540, -540, -540, -540, -540, -540, -540, -540, -540,
-     -540, -540, -540, -540, -540, -540, -540, -540, -540, -540,
-     -540, -540,  642, -540, -540, -540, -540, -540, -540, -540,
-     -540, -540, -540, -540, -540, -540, -540, -540, -540, -540,
-     -540, -540, -540, -540, -540, -540, -540, -540, -540, -540,
-     -540, -540, -540, -540, -540,  642,  642,  642,  642,  642,
-      642,  642,  642,  642,  642,  642,  642,  642,  642,  642,
-      642,  642,  642,  642,  642,  642,  642,  642,  642,  642,
-      642, -540, -540, -540, -540, -540, -540, -540, -540, -540,
-
-     -540, -540, -540, -540, -540, -540, -540, -540, -540, -540,
-     -540, -540, -540, -540, -540, -540, -540, -540, -540, -540,
-     -540, -540, -540, -540, -540, -540, -540, -540
-    },
-
-    {
-       67, -541, -541, -541, -541, -541, -541, -541, -541, -541,
-     -541, -541, -541, -541, -541, -541, -541, -541, -541, -541,
-     -541, -541, -541, -541, -541, -541, -541, -541, -541, -541,
-     -541, -541, -541, -541, -541, -541, -541, -541, -541, -541,
-     -541, -541, -541, -541, -541, -541, -541, -541, -541, -541,
-     -541, -541, -541, -541, -541, -541, -541, -541, -541, -541,
-     -541, -541, -541, -541, -541, -541, -541, -541, -541, -541,
-
-     -541, -541, -541, -541, -541, -541, -541, -541, -541,  643,
-     -541, -541, -541, -541, -541, -541, -541, -541, -541, -541,
-     -541, -541, -541, -541, -541, -541, -541, -541, -541, -541,
-     -541, -541, -541, -541, -541, -541, -541, -541, -541, -541,
-     -541, -541, -541, -541, -541, -541, -541, -541, -541, -541,
-     -541, -541, -541, -541, -541, -541, -541, -541
-    },
-
-    {
-       67, -542, -542, -542, -542, -542, -542, -542, -542, -542,
-     -542, -542, -542, -542, -542, -542, -542, -542, -542, -542,
-     -542, -542, -542, -542, -542, -542, -542, -542, -542, -542,
-     -542, -542, -542, -542, -542, -542, -542, -542, -542, -542,
-
-     -542, -542, -542, -542, -542, -542, -542, -542, -542, -542,
-     -542, -542, -542, -542, -542, -542, -542, -542, -542, -542,
-     -542, -542, -542, -542, -542, -542, -542, -542, -542, -542,
-     -542, -542, -542, -542, -542, -542,  644, -542, -542, -542,
-     -542, -542, -542, -542, -542, -542, -542, -542, -542, -542,
-     -542, -542, -542, -542, -542, -542, -542, -542, -542, -542,
-     -542, -542, -542, -542, -542, -542, -542, -542, -542, -542,
-     -542, -542, -542, -542, -542, -542, -542, -542, -542, -542,
-     -542, -542, -542, -542, -542, -542, -542, -542
-    },
-
-    {
-       67, -543, -543, -543, -543, -543, -543, -543, -543, -543,
-
-     -543, -543, -543, -543, -543, -543, -543, -543, -543, -543,
-     -543, -543, -543, -543, -543, -543, -543, -543, -543, -543,
-     -543, -543, -543, -543, -543, -543, -543, -543, -543, -543,
-     -543, -543, -543, -543, -543, -543, -543, -543, -543, -543,
-     -543, -543, -543, -543, -543, -543, -543, -543, -543, -543,
-     -543, -543, -543, -543, -543, -543, -543, -543, -543, -543,
-     -543, -543, -543, -543, -543, -543,  645, -543, -543, -543,
-     -543, -543, -543, -543, -543, -543, -543, -543, -543, -543,
-     -543, -543, -543, -543, -543, -543, -543, -543, -543, -543,
-     -543, -543, -543, -543, -543, -543, -543, -543, -543, -543,
-
-     -543, -543, -543, -543, -543, -543, -543, -543, -543, -543,
-     -543, -543, -543, -543, -543, -543, -543, -543
-    },
-
-    {
-       67, -544, -544, -544, -544, -544, -544, -544, -544, -544,
-     -544, -544, -544, -544, -544, -544, -544, -544, -544, -544,
-     -544, -544, -544, -544, -544, -544, -544, -544, -544, -544,
-     -544, -544, -544, -544, -544, -544, -544, -544, -544, -544,
-     -544, -544, -544, -544, -544, -544, -544, -544, -544, -544,
-     -544, -544, -544, -544, -544, -544, -544, -544, -544, -544,
-     -544, -544, -544, -544, -544, -544, -544, -544, -544, -544,
-     -544, -544, -544, -544, -544, -544, -544, -544, -544, -544,
-
-     -544, -544, -544, -544, -544, -544,  646, -544, -544, -544,
-     -544, -544, -544, -544, -544, -544, -544, -544, -544, -544,
-     -544, -544, -544, -544, -544, -544, -544, -544, -544, -544,
-     -544, -544, -544, -544, -544, -544, -544, -544, -544, -544,
-     -544, -544, -544, -544, -544, -544, -544, -544
-    },
-
-    {
-       67, -545, -545, -545, -545, -545, -545, -545, -545, -545,
-     -545, -545, -545, -545, -545, -545, -545, -545, -545, -545,
-     -545, -545, -545, -545, -545, -545, -545, -545, -545, -545,
-     -545, -545, -545, -545, -545, -545, -545, -545, -545, -545,
-     -545, -545, -545, -545, -545, -545, -545, -545, -545, -545,
-
-     -545, -545, -545, -545, -545, -545, -545, -545, -545, -545,
-     -545, -545, -545, -545, -545, -545,  647, -545, -545, -545,
-     -545, -545, -545, -545, -545, -545, -545, -545, -545, -545,
-     -545, -545, -545, -545, -545, -545, -545, -545, -545, -545,
-     -545, -545, -545, -545, -545, -545, -545, -545, -545, -545,
-     -545, -545, -545, -545, -545, -545, -545, -545, -545, -545,
-     -545, -545, -545, -545, -545, -545, -545, -545, -545, -545,
-     -545, -545, -545, -545, -545, -545, -545, -545
-    },
-
-    {
-       67, -546, -546, -546, -546, -546, -546, -546, -546, -546,
-     -546, -546, -546, -546, -546, -546, -546, -546, -546, -546,
-
-     -546, -546, -546, -546, -546, -546, -546, -546, -546, -546,
-     -546, -546, -546, -546, -546, -546, -546, -546, -546, -546,
-     -546, -546, -546, -546, -546, -546, -546, -546, -546, -546,
-     -546, -546, -546, -546, -546, -546, -546, -546, -546, -546,
-     -546, -546, -546, -546, -546, -546, -546, -546, -546, -546,
-     -546, -546, -546, -546, -546, -546, -546, -546, -546, -546,
-     -546, -546, -546, -546, -546, -546, -546, -546, -546, -546,
-     -546, -546, -546, -546, -546, -546, -546, -546, -546, -546,
-     -546, -546, -546, -546, -546, -546, -546, -546, -546, -546,
-     -546, -546, -546, -546, -546, -546, -546, -546, -546, -546,
-
-     -546, -546, -546, -546, -546, -546, -546, -546
-    },
-
-    {
-       67, -547, -547, -547, -547, -547, -547, -547, -547, -547,
-     -547, -547, -547, -547, -547, -547, -547, -547, -547, -547,
-     -547, -547, -547, -547, -547, -547, -547, -547, -547, -547,
-     -547, -547, -547, -547, -547, -547, -547, -547, -547, -547,
-     -547, -547, -547, -547, -547, -547, -547, -547, -547, -547,
-     -547, -547, -547, -547, -547, -547, -547, -547, -547, -547,
-     -547, -547, -547, -547, -547, -547, -547, -547, -547, -547,
-     -547, -547, -547, -547, -547, -547, -547, -547, -547,  648,
-     -547, -547, -547, -547, -547, -547, -547, -547, -547, -547,
-
-     -547, -547, -547, -547, -547, -547, -547, -547, -547, -547,
-     -547, -547, -547, -547, -547, -547, -547, -547, -547, -547,
-     -547, -547, -547, -547, -547, -547, -547, -547, -547, -547,
-     -547, -547, -547, -547, -547, -547, -547, -547
-    },
-
-    {
-       67, -548, -548, -548, -548, -548, -548, -548, -548, -548,
-     -548, -548, -548, -548, -548, -548, -548, -548, -548, -548,
-     -548, -548, -548, -548, -548, -548, -548, -548, -548, -548,
-     -548, -548, -548, -548, -548, -548, -548, -548, -548, -548,
-     -548, -548, -548, -548, -548, -548, -548, -548, -548, -548,
-     -548, -548, -548, -548, -548, -548, -548, -548, -548, -548,
-
-     -548, -548, -548, -548, -548, -548, -548, -548, -548, -548,
-     -548, -548, -548, -548, -548, -548, -548, -548, -548, -548,
-     -548, -548, -548, -548, -548, -548, -548, -548, -548, -548,
-     -548, -548, -548, -548, -548, -548, -548, -548, -548, -548,
-     -548, -548, -548, -548, -548, -548, -548, -548, -548, -548,
-     -548, -548, -548, -548, -548, -548, -548, -548, -548, -548,
-     -548, -548, -548, -548, -548, -548, -548, -548
-    },
-
-    {
-       67, -549, -549, -549, -549, -549, -549, -549, -549, -549,
-     -549, -549, -549, -549, -549, -549, -549, -549, -549, -549,
-     -549, -549, -549, -549, -549, -549, -549, -549, -549, -549,
-
-     -549, -549, -549, -549, -549, -549, -549, -549, -549, -549,
-     -549, -549, -549, -549, -549, -549, -549, -549, -549, -549,
-     -549, -549, -549, -549, -549, -549, -549, -549, -549, -549,
-     -549, -549, -549, -549, -549, -549, -549, -549, -549, -549,
-     -549, -549, -549, -549, -549, -549, -549, -549, -549, -549,
-     -549, -549, -549, -549, -549, -549, -549, -549, -549, -549,
-     -549, -549, -549, -549, -549, -549, -549, -549, -549, -549,
-     -549, -549, -549, -549, -549, -549, -549, -549, -549, -549,
-     -549, -549, -549, -549, -549, -549, -549, -549, -549, -549,
-     -549, -549, -549, -549, -549, -549, -549, -549
-
-    },
-
-    {
-       67, -550, -550, -550, -550, -550, -550, -550, -550, -550,
-     -550, -550, -550, -550, -550, -550, -550, -550, -550, -550,
-     -550, -550, -550, -550, -550, -550, -550, -550, -550, -550,
-     -550, -550, -550, -550, -550, -550, -550, -550, -550, -550,
-     -550, -550, -550, -550, -550, -550, -550, -550, -550, -550,
-     -550, -550, -550, -550, -550, -550, -550, -550, -550, -550,
-     -550, -550, -550, -550, -550, -550, -550, -550, -550, -550,
-     -550, -550, -550, -550, -550, -550, -550, -550, -550, -550,
-     -550, -550, -550, -550, -550, -550, -550, -550, -550, -550,
-     -550, -550, -550, -550, -550, -550, -550, -550, -550, -550,
-
-     -550, -550, -550, -550, -550, -550, -550, -550, -550, -550,
-     -550, -550, -550, -550, -550, -550, -550, -550, -550, -550,
-     -550, -550, -550, -550, -550, -550, -550, -550
-    },
-
-    {
-       67, -551, -551, -551, -551, -551, -551, -551, -551, -551,
-     -551, -551, -551, -551, -551, -551, -551, -551, -551, -551,
-     -551, -551, -551, -551, -551, -551, -551, -551, -551, -551,
-     -551, -551, -551, -551, -551, -551, -551, -551, -551, -551,
-     -551, -551, -551, -551, -551, -551, -551, -551, -551, -551,
-     -551, -551, -551, -551, -551, -551, -551, -551, -551, -551,
-     -551, -551, -551, -551, -551, -551, -551, -551, -551, -551,
-
-     -551, -551, -551, -551, -551, -551, -551, -551, -551, -551,
-     -551, -551, -551, -551, -551, -551, -551, -551, -551, -551,
-     -551, -551, -551, -551, -551, -551, -551, -551, -551, -551,
-     -551, -551, -551, -551, -551, -551, -551, -551, -551, -551,
-     -551, -551, -551, -551, -551, -551, -551, -551, -551, -551,
-     -551, -551, -551, -551, -551, -551, -551, -551
-    },
-
-    {
-       67, -552, -552, -552, -552, -552, -552, -552, -552, -552,
-     -552, -552, -552, -552, -552, -552, -552, -552, -552, -552,
-     -552, -552, -552, -552, -552, -552, -552, -552, -552, -552,
-     -552, -552, -552, -552, -552, -552, -552, -552, -552, -552,
-
-     -552, -552, -552, -552, -552, -552, -552, -552, -552, -552,
-     -552, -552, -552, -552, -552, -552, -552, -552, -552, -552,
-     -552, -552, -552, -552, -552, -552, -552, -552, -552, -552,
-     -552, -552, -552, -552, -552, -552, -552, -552, -552, -552,
-     -552, -552, -552,  649, -552, -552, -552, -552, -552, -552,
-     -552, -552, -552, -552, -552, -552, -552, -552, -552, -552,
-     -552, -552, -552, -552, -552, -552, -552, -552, -552, -552,
-     -552, -552, -552, -552, -552, -552, -552, -552, -552, -552,
-     -552, -552, -552, -552, -552, -552, -552, -552
-    },
-
-    {
-       67, -553, -553, -553, -553, -553, -553, -553, -553, -553,
-
-     -553, -553, -553, -553, -553, -553, -553, -553, -553, -553,
-     -553, -553, -553, -553, -553, -553, -553, -553, -553, -553,
-     -553, -553, -553, -553, -553, -553, -553, -553, -553, -553,
-     -553, -553, -553, -553, -553, -553, -553, -553, -553, -553,
-     -553, -553, -553, -553, -553, -553, -553, -553, -553, -553,
-     -553, -553, -553, -553, -553, -553, -553, -553, -553, -553,
-     -553, -553, -553, -553, -553, -553, -553, -553, -553, -553,
-     -553, -553, -553, -553, -553, -553, -553, -553, -553,  650,
-     -553, -553, -553, -553, -553, -553, -553, -553, -553, -553,
-     -553, -553, -553, -553, -553, -553, -553, -553, -553, -553,
-
-     -553, -553, -553, -553, -553, -553, -553, -553, -553, -553,
-     -553, -553, -553, -553, -553, -553, -553, -553
-    },
-
-    {
-       67, -554, -554, -554, -554, -554, -554, -554, -554, -554,
-     -554, -554, -554, -554, -554, -554, -554, -554, -554, -554,
-     -554, -554, -554, -554, -554, -554, -554, -554, -554, -554,
-     -554, -554, -554, -554, -554, -554, -554, -554, -554, -554,
-     -554, -554, -554, -554, -554, -554, -554, -554, -554, -554,
-     -554, -554, -554, -554, -554, -554, -554, -554, -554, -554,
-     -554, -554, -554, -554, -554, -554, -554, -554, -554, -554,
-     -554, -554, -554, -554, -554, -554, -554, -554, -554, -554,
-
-     -554, -554,  651, -554, -554, -554, -554, -554, -554, -554,
-     -554, -554, -554, -554, -554, -554, -554, -554, -554, -554,
-     -554, -554, -554, -554, -554, -554, -554, -554, -554, -554,
-     -554, -554, -554, -554, -554, -554, -554, -554, -554, -554,
-     -554, -554, -554, -554, -554, -554, -554, -554
-    },
-
-    {
-       67, -555, -555, -555, -555, -555, -555, -555, -555, -555,
-     -555, -555, -555, -555, -555, -555, -555, -555, -555, -555,
-     -555, -555, -555, -555, -555, -555, -555, -555, -555, -555,
-     -555, -555, -555, -555, -555, -555, -555, -555, -555, -555,
-     -555, -555, -555, -555, -555, -555, -555, -555, -555, -555,
-
-     -555, -555, -555, -555, -555, -555, -555, -555, -555, -555,
-     -555, -555, -555, -555, -555,  652, -555, -555, -555, -555,
-     -555, -555, -555, -555, -555, -555, -555, -555, -555, -555,
-     -555, -555, -555, -555, -555, -555, -555, -555, -555, -555,
-     -555, -555, -555, -555, -555, -555, -555, -555, -555, -555,
-     -555, -555, -555, -555, -555, -555, -555, -555, -555, -555,
-     -555, -555, -555, -555, -555, -555, -555, -555, -555, -555,
-     -555, -555, -555, -555, -555, -555, -555, -555
-    },
-
-    {
-       67, -556, -556, -556, -556, -556, -556, -556, -556, -556,
-     -556, -556, -556, -556, -556, -556, -556, -556, -556, -556,
-
-     -556, -556, -556, -556, -556, -556, -556, -556, -556, -556,
-     -556, -556, -556, -556, -556, -556, -556, -556, -556, -556,
-     -556, -556, -556, -556, -556, -556, -556, -556, -556, -556,
-     -556, -556, -556, -556, -556, -556, -556, -556, -556, -556,
-     -556, -556, -556, -556, -556, -556, -556, -556, -556, -556,
-     -556, -556, -556, -556, -556, -556, -556, -556, -556, -556,
-     -556, -556, -556, -556, -556, -556, -556, -556, -556,  653,
-     -556, -556, -556, -556, -556, -556, -556, -556, -556, -556,
-     -556, -556, -556, -556, -556, -556, -556, -556, -556, -556,
-     -556, -556, -556, -556, -556, -556, -556, -556, -556, -556,
-
-     -556, -556, -556, -556, -556, -556, -556, -556
-    },
-
-    {
-       67, -557, -557, -557, -557, -557, -557, -557, -557, -557,
-     -557, -557, -557, -557, -557, -557, -557, -557, -557, -557,
-     -557, -557, -557, -557, -557, -557, -557, -557, -557, -557,
-     -557, -557, -557, -557, -557, -557, -557, -557, -557, -557,
-     -557, -557, -557, -557, -557, -557, -557, -557, -557, -557,
-     -557, -557, -557, -557, -557, -557, -557, -557, -557, -557,
-     -557, -557, -557, -557, -557, -557,  654, -557, -557, -557,
-     -557, -557, -557, -557, -557, -557, -557, -557, -557, -557,
-     -557, -557, -557, -557, -557, -557, -557, -557, -557, -557,
-
-     -557, -557, -557, -557, -557, -557, -557, -557, -557, -557,
-     -557, -557, -557, -557, -557, -557, -557, -557, -557, -557,
-     -557, -557, -557, -557, -557, -557, -557, -557, -557, -557,
-     -557, -557, -557, -557, -557, -557, -557, -557
-    },
-
-    {
-       67, -558, -558, -558, -558, -558, -558, -558, -558, -558,
-     -558, -558, -558, -558, -558, -558, -558, -558, -558, -558,
-     -558, -558, -558, -558, -558, -558, -558, -558, -558, -558,
-     -558, -558, -558, -558, -558, -558, -558, -558, -558, -558,
-     -558, -558, -558, -558, -558, -558, -558, -558, -558, -558,
-     -558, -558, -558, -558, -558, -558, -558, -558, -558, -558,
-
-     -558, -558, -558, -558, -558, -558, -558, -558, -558, -558,
-     -558, -558, -558, -558, -558, -558, -558, -558, -558, -558,
-     -558, -558,  655, -558, -558, -558, -558, -558, -558, -558,
-     -558, -558, -558, -558, -558, -558, -558, -558, -558, -558,
-     -558, -558, -558, -558, -558, -558, -558, -558, -558, -558,
-     -558, -558, -558, -558, -558, -558, -558, -558, -558, -558,
-     -558, -558, -558, -558, -558, -558, -558, -558
-    },
-
-    {
-       67, -559, -559, -559, -559, -559, -559, -559, -559, -559,
-     -559, -559, -559, -559, -559, -559, -559, -559, -559, -559,
-     -559, -559, -559, -559, -559, -559, -559, -559, -559, -559,
-
-     -559, -559, -559, -559, -559, -559, -559, -559, -559, -559,
-     -559, -559, -559, -559, -559, -559, -559, -559, -559, -559,
-     -559, -559, -559, -559, -559, -559, -559, -559, -559, -559,
-     -559, -559, -559, -559, -559, -559, -559, -559, -559, -559,
-     -559, -559, -559, -559, -559, -559, -559, -559, -559, -559,
-     -559, -559, -559, -559, -559, -559, -559, -559, -559, -559,
-     -559, -559, -559, -559, -559, -559, -559, -559, -559, -559,
-     -559, -559, -559, -559, -559, -559, -559, -559, -559, -559,
-     -559, -559, -559, -559, -559, -559, -559, -559, -559, -559,
-     -559, -559, -559, -559, -559, -559, -559, -559
-
-    },
-
-    {
-       67, -560, -560, -560, -560, -560, -560, -560, -560, -560,
-     -560, -560, -560, -560, -560, -560, -560, -560, -560, -560,
-     -560, -560, -560, -560, -560, -560, -560, -560, -560, -560,
-     -560, -560, -560, -560, -560, -560, -560, -560, -560, -560,
-     -560, -560, -560, -560, -560, -560, -560, -560, -560, -560,
-     -560, -560, -560, -560, -560, -560, -560, -560, -560, -560,
-     -560, -560, -560, -560, -560, -560, -560, -560, -560, -560,
-     -560, -560, -560, -560, -560, -560, -560, -560, -560, -560,
-     -560, -560, -560, -560, -560, -560, -560, -560, -560, -560,
-     -560, -560, -560, -560, -560, -560, -560, -560, -560, -560,
-
-     -560, -560, -560, -560, -560, -560, -560, -560, -560, -560,
-     -560, -560, -560, -560, -560, -560, -560, -560, -560, -560,
-     -560, -560, -560, -560, -560, -560, -560, -560
-    },
-
-    {
-       67, -561, -561, -561, -561, -561, -561, -561, -561, -561,
-     -561, -561, -561, -561, -561, -561, -561, -561, -561, -561,
-     -561, -561, -561, -561, -561, -561, -561, -561, -561, -561,
-     -561, -561, -561, -561, -561, -561, -561, -561, -561, -561,
-     -561, -561, -561, -561, -561, -561, -561, -561, -561, -561,
-     -561, -561, -561, -561, -561, -561, -561, -561, -561, -561,
-     -561, -561, -561, -561, -561, -561, -561, -561, -561, -561,
-
-     -561, -561, -561, -561, -561, -561, -561, -561, -561, -561,
-     -561, -561, -561, -561, -561, -561, -561, -561, -561, -561,
-     -561, -561, -561, -561, -561, -561, -561, -561, -561, -561,
-     -561, -561, -561, -561, -561, -561, -561, -561, -561, -561,
-     -561, -561, -561, -561, -561, -561, -561, -561, -561, -561,
-     -561, -561, -561, -561, -561, -561, -561, -561
-    },
-
-    {
-       67, -562, -562, -562, -562, -562, -562, -562, -562, -562,
-     -562, -562, -562, -562, -562, -562, -562, -562, -562, -562,
-     -562, -562, -562, -562, -562, -562, -562, -562, -562, -562,
-     -562, -562, -562, -562, -562, -562, -562, -562, -562, -562,
-
-     -562, -562, -562, -562, -562, -562, -562, -562, -562, -562,
-     -562, -562, -562, -562, -562, -562, -562, -562, -562, -562,
-     -562, -562, -562, -562, -562, -562, -562, -562, -562, -562,
-     -562, -562, -562, -562, -562, -562, -562, -562, -562, -562,
-     -562, -562, -562, -562, -562, -562, -562, -562, -562, -562,
-     -562, -562, -562, -562, -562, -562, -562, -562, -562, -562,
-     -562, -562, -562, -562, -562, -562, -562, -562, -562, -562,
-     -562, -562, -562, -562, -562, -562, -562, -562, -562, -562,
-     -562, -562, -562, -562, -562, -562, -562, -562
-    },
-
-    {
-       67, -563, -563, -563, -563, -563, -563, -563, -563, -563,
-
-     -563, -563, -563, -563, -563, -563, -563, -563, -563, -563,
-     -563, -563, -563, -563, -563, -563, -563, -563, -563, -563,
-     -563, -563, -563, -563, -563, -563, -563, -563, -563, -563,
-     -563, -563, -563, -563, -563, -563, -563, -563, -563, -563,
-     -563, -563, -563, -563, -563, -563, -563, -563, -563, -563,
-     -563, -563, -563, -563, -563, -563, -563, -563, -563, -563,
-     -563, -563, -563, -563, -563, -563, -563, -563, -563, -563,
-     -563, -563, -563, -563, -563, -563, -563, -563, -563, -563,
-     -563, -563, -563, -563, -563, -563, -563, -563, -563, -563,
-     -563, -563, -563, -563, -563, -563, -563, -563, -563, -563,
-
-     -563, -563, -563, -563, -563, -563, -563, -563, -563, -563,
-     -563, -563, -563, -563, -563, -563, -563, -563
-    },
-
-    {
-       67, -564, -564, -564, -564, -564, -564, -564, -564, -564,
-     -564, -564, -564, -564, -564, -564, -564, -564, -564, -564,
-     -564, -564, -564, -564, -564, -564, -564, -564, -564, -564,
-     -564, -564, -564, -564, -564, -564, -564, -564, -564, -564,
-     -564, -564, -564, -564, -564, -564, -564, -564, -564, -564,
-     -564, -564, -564, -564, -564, -564, -564, -564, -564, -564,
-     -564, -564, -564, -564, -564, -564, -564, -564, -564, -564,
-     -564, -564, -564, -564, -564, -564, -564, -564, -564, -564,
-
-     -564, -564, -564, -564, -564, -564, -564, -564, -564, -564,
-     -564, -564, -564, -564, -564, -564, -564, -564, -564, -564,
-     -564, -564, -564, -564, -564, -564, -564, -564, -564, -564,
-     -564, -564, -564, -564, -564, -564, -564, -564, -564, -564,
-     -564, -564, -564, -564, -564, -564, -564, -564
-    },
-
-    {
-       67, -565, -565, -565, -565, -565, -565, -565, -565, -565,
-     -565, -565, -565, -565, -565, -565, -565, -565, -565, -565,
-     -565, -565, -565, -565, -565, -565, -565, -565, -565, -565,
-     -565, -565, -565, -565, -565, -565, -565, -565, -565, -565,
-     -565, -565, -565, -565, -565, -565, -565, -565, -565, -565,
-
-     -565, -565, -565, -565, -565, -565, -565, -565, -565, -565,
-     -565, -565, -565, -565, -565, -565, -565, -565, -565, -565,
-     -565, -565, -565, -565, -565, -565, -565, -565, -565, -565,
-     -565, -565, -565, -565, -565, -565, -565, -565, -565, -565,
-     -565, -565, -565, -565, -565, -565, -565, -565, -565, -565,
-     -565, -565, -565, -565, -565, -565, -565, -565, -565, -565,
-     -565, -565, -565, -565, -565, -565, -565, -565, -565, -565,
-     -565, -565, -565, -565, -565, -565, -565, -565
-    },
-
-    {
-       67, -566, -566, -566, -566, -566, -566, -566, -566, -566,
-     -566, -566, -566, -566, -566, -566, -566, -566, -566, -566,
-
-     -566, -566, -566, -566, -566, -566, -566, -566, -566, -566,
-     -566, -566, -566, -566, -566, -566, -566, -566, -566, -566,
-     -566, -566, -566, -566, -566, -566, -566, -566, -566, -566,
-     -566, -566, -566, -566, -566, -566, -566, -566, -566, -566,
-     -566, -566, -566, -566, -566, -566, -566, -566, -566, -566,
-     -566, -566, -566, -566, -566, -566, -566, -566, -566, -566,
-     -566, -566, -566, -566, -566, -566, -566, -566, -566, -566,
-     -566, -566, -566, -566, -566, -566, -566, -566, -566, -566,
-     -566, -566, -566, -566, -566, -566, -566, -566, -566, -566,
-     -566, -566, -566, -566, -566, -566, -566, -566, -566, -566,
-
-     -566, -566, -566, -566, -566, -566, -566, -566
-    },
-
-    {
-       67, -567, -567, -567, -567, -567, -567, -567, -567, -567,
-     -567, -567, -567, -567, -567, -567, -567, -567, -567, -567,
-     -567, -567, -567, -567, -567, -567, -567, -567, -567, -567,
-     -567, -567, -567, -567, -567, -567, -567, -567, -567, -567,
-     -567, -567, -567, -567, -567, -567, -567, -567, -567, -567,
-     -567, -567, -567, -567, -567, -567, -567, -567, -567, -567,
-     -567, -567, -567, -567, -567, -567, -567, -567, -567, -567,
-     -567, -567, -567, -567, -567, -567, -567, -567, -567, -567,
-     -567, -567, -567, -567, -567, -567, -567, -567, -567, -567,
-
-     -567, -567, -567, -567, -567, -567, -567, -567, -567, -567,
-     -567, -567, -567, -567, -567, -567, -567, -567, -567, -567,
-     -567, -567, -567, -567, -567, -567, -567, -567, -567, -567,
-     -567, -567, -567, -567, -567, -567, -567, -567
-    },
-
-    {
-       67, -568, -568, -568, -568, -568, -568, -568, -568, -568,
-     -568, -568, -568, -568, -568, -568, -568, -568, -568, -568,
-     -568, -568, -568, -568, -568, -568, -568, -568, -568, -568,
-     -568, -568, -568, -568, -568, -568, -568, -568, -568, -568,
-     -568, -568, -568, -568, -568, -568, -568, -568, -568, -568,
-     -568, -568, -568, -568, -568, -568, -568, -568, -568, -568,
-
-     -568, -568, -568, -568, -568, -568, -568, -568,  656, -568,
-     -568, -568, -568, -568, -568, -568, -568, -568, -568, -568,
-     -568, -568, -568, -568, -568, -568, -568, -568, -568, -568,
-     -568, -568, -568, -568, -568, -568, -568, -568, -568, -568,
-     -568, -568, -568, -568, -568, -568, -568, -568, -568, -568,
-     -568, -568, -568, -568, -568, -568, -568, -568, -568, -568,
-     -568, -568, -568, -568, -568, -568, -568, -568
-    },
-
-    {
-       67, -569, -569, -569, -569, -569, -569, -569, -569, -569,
-     -569, -569, -569, -569, -569, -569, -569, -569, -569, -569,
-     -569, -569, -569, -569, -569, -569, -569, -569, -569, -569,
-
-     -569, -569, -569, -569, -569, -569, -569, -569, -569, -569,
-     -569, -569, -569, -569, -569, -569, -569, -569, -569, -569,
-     -569, -569, -569, -569, -569, -569, -569, -569, -569, -569,
-     -569, -569, -569, -569, -569, -569, -569, -569, -569, -569,
-     -569,  657, -569, -569, -569, -569, -569, -569, -569, -569,
-     -569, -569, -569, -569, -569, -569, -569, -569, -569, -569,
-     -569, -569, -569, -569, -569, -569, -569, -569, -569, -569,
-     -569, -569, -569, -569, -569, -569, -569, -569, -569, -569,
-     -569, -569, -569, -569, -569, -569, -569, -569, -569, -569,
-     -569, -569, -569, -569, -569, -569, -569, -569
-
-    },
-
-    {
-       67, -570, -570, -570, -570, -570, -570, -570, -570, -570,
-     -570, -570, -570, -570, -570, -570, -570, -570, -570, -570,
-     -570, -570, -570, -570, -570, -570, -570, -570, -570, -570,
-     -570, -570, -570, -570, -570, -570, -570, -570, -570, -570,
-     -570, -570, -570, -570, -570, -570, -570, -570, -570, -570,
-     -570, -570, -570, -570, -570, -570, -570, -570, -570, -570,
-     -570, -570, -570, -570, -570, -570, -570, -570, -570, -570,
-     -570, -570, -570, -570, -570, -570, -570, -570, -570, -570,
-     -570, -570, -570, -570, -570, -570, -570, -570, -570,  658,
-     -570, -570, -570, -570, -570, -570, -570, -570, -570, -570,
-
-     -570, -570, -570, -570, -570, -570, -570, -570, -570, -570,
-     -570, -570, -570, -570, -570, -570, -570, -570, -570, -570,
-     -570, -570, -570, -570, -570, -570, -570, -570
-    },
-
-    {
-       67, -571, -571, -571, -571, -571, -571, -571, -571, -571,
-     -571, -571, -571, -571, -571, -571, -571, -571, -571, -571,
-     -571, -571, -571, -571, -571, -571, -571, -571, -571, -571,
-     -571, -571, -571, -571, -571, -571, -571, -571, -571, -571,
-     -571, -571, -571, -571, -571, -571, -571, -571, -571, -571,
-     -571, -571, -571, -571, -571, -571, -571, -571, -571, -571,
-     -571, -571, -571, -571, -571, -571, -571, -571, -571, -571,
-
-      659, -571, -571, -571, -571, -571, -571, -571, -571, -571,
-     -571, -571, -571, -571, -571, -571, -571, -571, -571, -571,
-     -571, -571, -571, -571, -571, -571, -571, -571, -571, -571,
-     -571, -571, -571, -571, -571, -571, -571, -571, -571, -571,
-     -571, -571, -571, -571, -571, -571, -571, -571, -571, -571,
-     -571, -571, -571, -571, -571, -571, -571, -571
-    },
-
-    {
-       67, -572, -572, -572, -572, -572, -572, -572, -572, -572,
-     -572, -572, -572, -572, -572, -572, -572, -572, -572, -572,
-     -572, -572, -572, -572, -572, -572, -572, -572, -572, -572,
-     -572, -572,  660, -572, -572, -572, -572, -572, -572, -572,
-
-     -572, -572, -572, -572, -572, -572, -572, -572,  661,  661,
-      661,  661,  661,  661,  661,  661,  661,  661, -572, -572,
-     -572, -572, -572, -572, -572,  660,  660,  660,  660,  660,
-      660,  660,  660,  660,  660,  660,  660,  660,  660,  660,
-      660,  660,  660,  660,  660,  660,  660,  660,  660,  660,
-      660, -572, -572, -572, -572, -572, -572, -572, -572, -572,
-     -572, -572, -572, -572, -572, -572, -572, -572, -572, -572,
-     -572, -572, -572, -572, -572, -572, -572, -572, -572, -572,
-     -572, -572, -572, -572, -572, -572, -572, -572
-    },
-
-    {
-       67, -573, -573, -573, -573, -573, -573, -573, -573, -573,
-
-     -573, -573, -573, -573, -573, -573, -573, -573, -573, -573,
-     -573, -573, -573, -573, -573, -573, -573, -573, -573, -573,
-     -573, -573, -573, -573, -573, -573, -573, -573, -573, -573,
-     -573, -573, -573, -573, -573, -573, -573, -573, -573, -573,
-     -573, -573, -573, -573, -573, -573, -573, -573, -573, -573,
-     -573, -573, -573, -573, -573, -573, -573,  662, -573, -573,
-     -573, -573, -573, -573, -573, -573, -573, -573, -573, -573,
-     -573, -573, -573, -573, -573, -573, -573, -573, -573, -573,
-     -573, -573, -573, -573, -573, -573, -573, -573, -573, -573,
-     -573, -573, -573, -573, -573, -573, -573, -573, -573, -573,
-
-     -573, -573, -573, -573, -573, -573, -573, -573, -573, -573,
-     -573, -573, -573, -573, -573, -573, -573, -573
-    },
-
-    {
-       67, -574, -574, -574, -574, -574, -574, -574, -574, -574,
-     -574, -574, -574, -574, -574, -574, -574, -574, -574, -574,
-     -574, -574, -574, -574, -574, -574, -574, -574, -574, -574,
-     -574, -574,  663, -574, -574, -574, -574, -574, -574, -574,
-     -574, -574, -574, -574, -574, -574, -574, -574,  664,  664,
-      664,  664,  664,  664,  664,  664,  664,  664, -574, -574,
-     -574, -574, -574, -574, -574,  663,  663,  663,  663,  663,
-      663,  663,  663,  663,  663,  663,  663,  663,  663,  663,
-
-      663,  663,  663,  663,  663,  663,  663,  663,  663,  663,
-      663, -574, -574, -574, -574, -574, -574, -574, -574, -574,
-     -574, -574, -574, -574, -574, -574, -574, -574, -574, -574,
-     -574, -574, -574, -574, -574, -574, -574, -574, -574, -574,
-     -574, -574, -574, -574, -574, -574, -574, -574
-    },
-
-    {
-       67, -575, -575, -575, -575, -575, -575, -575, -575, -575,
-     -575, -575, -575, -575, -575, -575, -575, -575, -575, -575,
-     -575, -575, -575, -575, -575, -575, -575, -575, -575, -575,
-     -575, -575, -575, -575, -575, -575, -575, -575, -575, -575,
-     -575, -575, -575, -575, -575, -575, -575, -575, -575, -575,
-
-     -575, -575, -575, -575, -575, -575, -575, -575, -575, -575,
-     -575, -575, -575, -575, -575, -575, -575, -575, -575,  665,
-     -575, -575, -575, -575, -575, -575, -575, -575, -575, -575,
-     -575, -575, -575, -575, -575, -575, -575, -575, -575, -575,
-     -575, -575, -575, -575, -575, -575, -575, -575, -575, -575,
-     -575, -575, -575, -575, -575, -575, -575, -575, -575, -575,
-     -575, -575, -575, -575, -575, -575, -575, -575, -575, -575,
-     -575, -575, -575, -575, -575, -575, -575, -575
-    },
-
-    {
-       67, -576, -576, -576, -576, -576, -576, -576, -576, -576,
-     -576, -576, -576, -576, -576, -576, -576, -576, -576, -576,
-
-     -576, -576, -576, -576, -576, -576, -576, -576, -576, -576,
-     -576, -576, -576, -576, -576, -576, -576, -576, -576, -576,
-     -576, -576, -576, -576, -576, -576, -576, -576, -576, -576,
-     -576, -576, -576, -576, -576, -576, -576, -576, -576, -576,
-     -576, -576, -576, -576, -576, -576, -576, -576, -576, -576,
-     -576, -576, -576, -576, -576, -576, -576,  666, -576, -576,
-     -576, -576, -576, -576, -576, -576, -576, -576, -576, -576,
-     -576, -576, -576, -576, -576, -576, -576, -576, -576, -576,
-     -576, -576, -576, -576, -576, -576, -576, -576, -576, -576,
-     -576, -576, -576, -576, -576, -576, -576, -576, -576, -576,
-
-     -576, -576, -576, -576, -576, -576, -576, -576
-    },
-
-    {
-       67, -577, -577, -577, -577, -577, -577, -577, -577, -577,
-     -577, -577, -577, -577, -577, -577, -577, -577, -577, -577,
-     -577, -577, -577, -577, -577, -577, -577, -577, -577, -577,
-     -577, -577,  667, -577, -577, -577, -577, -577, -577, -577,
-     -577, -577, -577, -577, -577, -577, -577, -577,  668,  668,
-      668,  668,  668,  668,  668,  668,  668,  668, -577, -577,
-     -577, -577, -577, -577, -577,  667,  667,  667,  667,  667,
-      667,  667,  667,  667,  667,  667,  667,  667,  667,  667,
-      667,  667,  667,  667,  667,  667,  667,  667,  667,  667,
-
-      667, -577, -577, -577, -577, -577, -577, -577, -577, -577,
-     -577, -577, -577, -577, -577, -577, -577, -577, -577, -577,
-     -577, -577, -577, -577, -577, -577, -577, -577, -577, -577,
-     -577, -577, -577, -577, -577, -577, -577, -577
-    },
-
-    {
-       67, -578, -578, -578, -578, -578, -578, -578, -578, -578,
-     -578, -578, -578, -578, -578, -578, -578, -578, -578, -578,
-     -578, -578, -578, -578, -578, -578, -578, -578, -578, -578,
-     -578, -578,  669, -578, -578, -578, -578, -578, -578, -578,
-     -578, -578, -578, -578, -578, -578, -578, -578,  670,  670,
-      670,  670,  670,  670,  670,  670,  670,  670, -578, -578,
-
-     -578, -578, -578, -578, -578,  669,  669,  669,  669,  669,
-      669,  669,  669,  669,  669,  669,  669,  669,  669,  669,
-      669,  669,  669,  669,  669,  669,  669,  669,  669,  669,
-      669, -578, -578, -578, -578, -578, -578, -578, -578, -578,
-     -578, -578, -578, -578, -578, -578, -578, -578, -578, -578,
-     -578, -578, -578, -578, -578, -578, -578, -578, -578, -578,
-     -578, -578, -578, -578, -578, -578, -578, -578
-    },
-
-    {
-       67, -579, -579, -579, -579, -579, -579, -579, -579, -579,
-     -579, -579, -579, -579, -579, -579, -579, -579, -579, -579,
-     -579, -579, -579, -579, -579, -579, -579, -579, -579, -579,
-
-     -579, -579, -579, -579, -579, -579, -579, -579, -579, -579,
-     -579, -579, -579, -579, -579, -579, -579, -579, -579, -579,
-     -579, -579, -579, -579, -579, -579, -579, -579, -579, -579,
-     -579, -579, -579, -579, -579, -579, -579,  671, -579, -579,
-     -579, -579, -579, -579, -579, -579, -579, -579, -579, -579,
-     -579, -579, -579, -579, -579, -579, -579, -579, -579, -579,
-     -579, -579, -579, -579, -579, -579, -579, -579, -579, -579,
-     -579, -579, -579, -579, -579, -579, -579, -579, -579, -579,
-     -579, -579, -579, -579, -579, -579, -579, -579, -579, -579,
-     -579, -579, -579, -579, -579, -579, -579, -579
-
-    },
-
-    {
-       67, -580, -580, -580, -580, -580, -580, -580, -580, -580,
-     -580, -580, -580, -580, -580, -580, -580, -580, -580, -580,
-     -580, -580, -580, -580, -580, -580, -580, -580, -580, -580,
-     -580, -580, -580, -580, -580, -580, -580, -580, -580, -580,
-     -580, -580, -580, -580, -580, -580, -580, -580,  672,  672,
-      672,  672,  672,  672,  672,  672,  672,  672, -580, -580,
-     -580, -580, -580, -580, -580, -580, -580, -580, -580, -580,
-     -580, -580, -580, -580, -580, -580, -580, -580, -580, -580,
-     -580, -580, -580, -580, -580, -580, -580, -580, -580, -580,
-     -580, -580, -580, -580, -580, -580, -580, -580, -580, -580,
-
-     -580, -580, -580, -580, -580, -580, -580, -580, -580, -580,
-     -580, -580, -580, -580, -580, -580, -580, -580, -580, -580,
-     -580, -580, -580, -580, -580, -580, -580, -580
-    },
-
-    {
-       67, -581, -581, -581, -581, -581, -581, -581, -581, -581,
-     -581, -581, -581, -581, -581, -581, -581, -581, -581, -581,
-     -581, -581, -581, -581, -581, -581, -581, -581, -581, -581,
-     -581, -581, -581, -581, -581, -581, -581, -581, -581, -581,
-     -581, -581, -581, -581, -581, -581, -581, -581, -581,  673,
-      673,  673,  673,  673,  673,  673,  673,  673, -581, -581,
-     -581, -581, -581, -581, -581, -581, -581, -581, -581, -581,
-
-     -581, -581, -581, -581, -581, -581, -581, -581, -581, -581,
-     -581, -581, -581, -581, -581, -581, -581, -581, -581, -581,
-     -581, -581, -581, -581, -581, -581, -581, -581, -581, -581,
-     -581, -581, -581, -581, -581, -581, -581, -581, -581, -581,
-     -581, -581, -581, -581, -581, -581, -581, -581, -581, -581,
-     -581, -581, -581, -581, -581, -581, -581, -581
-    },
-
-    {
-       67, -582, -582, -582, -582, -582, -582, -582, -582, -582,
-     -582, -582, -582, -582, -582, -582, -582, -582, -582, -582,
-     -582, -582, -582, -582, -582, -582, -582, -582, -582, -582,
-     -582, -582,  674, -582, -582, -582, -582, -582, -582, -582,
-
-     -582, -582, -582, -582, -582, -582, -582, -582,  675,  675,
-      675,  675,  675,  675,  675,  675,  675,  675, -582, -582,
-     -582, -582, -582, -582, -582,  674,  674,  674,  674,  674,
-      674,  674,  674,  674,  674,  674,  674,  674,  674,  674,
-      674,  674,  674,  674,  674,  674,  674,  674,  674,  674,
-      674, -582, -582, -582, -582, -582, -582, -582, -582, -582,
-     -582, -582, -582, -582, -582, -582, -582, -582, -582, -582,
-     -582, -582, -582, -582, -582, -582, -582, -582, -582, -582,
-     -582, -582, -582, -582, -582, -582, -582, -582
-    },
-
-    {
-       67, -583, -583, -583, -583, -583, -583, -583, -583, -583,
-
-     -583, -583, -583, -583, -583, -583, -583, -583, -583, -583,
-     -583, -583, -583, -583, -583, -583, -583, -583, -583, -583,
-     -583, -583,  676, -583, -583, -583, -583, -583, -583, -583,
-     -583, -583, -583, -583, -583, -583, -583, -583, -583, -583,
-     -583, -583, -583, -583, -583, -583, -583, -583, -583, -583,
-     -583, -583, -583, -583, -583, -583, -583, -583, -583, -583,
-     -583, -583, -583, -583, -583, -583, -583, -583, -583, -583,
-     -583, -583, -583, -583, -583, -583, -583, -583, -583, -583,
-     -583, -583, -583, -583, -583, -583, -583, -583, -583, -583,
-     -583, -583, -583, -583, -583, -583, -583, -583, -583, -583,
-
-     -583, -583, -583, -583, -583, -583, -583, -583, -583, -583,
-     -583, -583, -583, -583, -583, -583, -583, -583
-    },
-
-    {
-       67, -584, -584, -584, -584, -584, -584, -584, -584, -584,
-     -584, -584, -584, -584, -584, -584, -584, -584, -584, -584,
-     -584, -584, -584, -584, -584, -584, -584, -584, -584, -584,
-     -584, -584,  677, -584, -584, -584, -584, -584, -584, -584,
-     -584, -584, -584, -584, -584, -584, -584, -584,  678,  678,
-      678,  678,  678,  678,  678,  678,  678,  678, -584, -584,
-     -584, -584, -584, -584, -584,  677,  677,  677,  677,  677,
-      677,  677,  677,  677,  677,  677,  677,  677,  677,  677,
-
-      677,  677,  677,  677,  677,  677,  677,  677,  677,  677,
-      677, -584, -584, -584, -584, -584, -584, -584, -584, -584,
-     -584, -584, -584, -584, -584, -584, -584, -584, -584, -584,
-     -584, -584, -584, -584, -584, -584, -584, -584, -584, -584,
-     -584, -584, -584, -584, -584, -584, -584, -584
-    },
-
-    {
-       67, -585, -585, -585, -585, -585, -585, -585, -585, -585,
-     -585, -585, -585, -585, -585, -585, -585, -585, -585, -585,
-     -585, -585, -585, -585, -585, -585, -585, -585, -585, -585,
-     -585, -585,  679, -585, -585, -585, -585, -585, -585, -585,
-     -585, -585, -585, -585, -585, -585, -585, -585, -585, -585,
-
-     -585, -585, -585, -585, -585, -585, -585, -585, -585, -585,
-     -585, -585, -585, -585, -585, -585, -585, -585, -585, -585,
-     -585, -585, -585, -585, -585, -585, -585, -585, -585, -585,
-     -585, -585, -585, -585, -585, -585, -585, -585, -585, -585,
-     -585, -585, -585, -585, -585, -585, -585, -585, -585, -585,
-     -585, -585, -585, -585, -585, -585, -585, -585, -585, -585,
-     -585, -585, -585, -585, -585, -585, -585, -585, -585, -585,
-     -585, -585, -585, -585, -585, -585, -585, -585
-    },
-
-    {
-       67, -586, -586, -586, -586, -586, -586, -586, -586, -586,
-     -586, -586, -586, -586, -586, -586, -586, -586, -586, -586,
-
-     -586, -586, -586, -586, -586, -586, -586, -586, -586, -586,
-     -586, -586,  680, -586, -586, -586, -586, -586, -586, -586,
-     -586, -586, -586, -586, -586, -586, -586, -586, -586, -586,
-     -586, -586, -586, -586, -586, -586, -586, -586, -586, -586,
-     -586, -586, -586, -586, -586, -586, -586, -586, -586, -586,
-     -586, -586, -586, -586, -586, -586, -586, -586, -586, -586,
-     -586, -586, -586, -586, -586, -586, -586, -586, -586, -586,
-     -586, -586, -586, -586, -586, -586, -586, -586, -586, -586,
-     -586, -586, -586, -586, -586, -586, -586, -586, -586, -586,
-     -586, -586, -586, -586, -586, -586, -586, -586, -586, -586,
-
-     -586, -586, -586, -586, -586, -586, -586, -586
-    },
-
-    {
-       67, -587, -587, -587, -587, -587, -587, -587, -587, -587,
-     -587, -587, -587, -587, -587, -587, -587, -587, -587, -587,
-     -587, -587, -587, -587, -587, -587, -587, -587, -587, -587,
-     -587, -587,  681, -587, -587, -587, -587, -587, -587, -587,
-     -587, -587, -587, -587, -587, -587, -587, -587,  682,  682,
-      682,  682,  682,  682,  682,  682,  682,  682, -587, -587,
-     -587, -587, -587, -587, -587,  681,  681,  681,  681,  681,
-      681,  681,  681,  681,  681,  681,  681,  681,  681,  681,
-      681,  681,  681,  681,  681,  681,  681,  681,  681,  681,
-
-      681, -587, -587, -587, -587, -587, -587, -587, -587, -587,
-     -587, -587, -587, -587, -587, -587, -587, -587, -587, -587,
-     -587, -587, -587, -587, -587, -587, -587, -587, -587, -587,
-     -587, -587, -587, -587, -587, -587, -587, -587
-    },
-
-    {
-       67, -588, -588, -588, -588, -588, -588, -588, -588, -588,
-     -588, -588, -588, -588, -588, -588, -588, -588, -588, -588,
-     -588, -588, -588, -588, -588, -588, -588, -588, -588, -588,
-     -588, -588, -588, -588, -588, -588, -588, -588, -588, -588,
-     -588, -588, -588, -588, -588, -588, -588, -588, -588,  683,
-      683,  683,  683,  683,  683,  683,  683,  683, -588, -588,
-
-     -588, -588, -588, -588, -588, -588, -588, -588, -588, -588,
-     -588, -588, -588, -588, -588, -588, -588, -588, -588, -588,
-     -588, -588, -588, -588, -588, -588, -588, -588, -588, -588,
-     -588, -588, -588, -588, -588, -588, -588, -588, -588, -588,
-     -588, -588, -588, -588, -588, -588, -588, -588, -588, -588,
-     -588, -588, -588, -588, -588, -588, -588, -588, -588, -588,
-     -588, -588, -588, -588, -588, -588, -588, -588
-    },
-
-    {
-       67, -589, -589, -589, -589, -589, -589, -589, -589, -589,
-     -589, -589, -589, -589, -589, -589, -589, -589, -589, -589,
-     -589, -589, -589, -589, -589, -589, -589, -589, -589, -589,
-
-     -589, -589,  684, -589, -589, -589, -589, -589, -589, -589,
-     -589, -589, -589, -589, -589, -589, -589, -589,  685,  685,
-      685,  685,  685,  685,  685,  685,  685,  685, -589, -589,
-     -589, -589, -589, -589, -589,  684,  684,  684,  684,  684,
-      684,  684,  684,  684,  684,  684,  684,  684,  684,  684,
-      684,  684,  684,  684,  684,  684,  684,  684,  684,  684,
-      684, -589, -589, -589, -589, -589, -589, -589, -589, -589,
-     -589, -589, -589, -589, -589, -589, -589, -589, -589, -589,
-     -589, -589, -589, -589, -589, -589, -589, -589, -589, -589,
-     -589, -589, -589, -589, -589, -589, -589, -589
-
-    },
-
-    {
-       67, -590, -590, -590, -590, -590, -590, -590, -590, -590,
-     -590, -590, -590, -590, -590, -590, -590, -590, -590, -590,
-     -590, -590, -590, -590, -590, -590, -590, -590, -590, -590,
-     -590, -590,  686, -590, -590, -590, -590, -590, -590, -590,
-     -590, -590, -590, -590, -590, -590, -590, -590, -590, -590,
-     -590, -590, -590, -590, -590, -590, -590, -590, -590, -590,
-     -590, -590, -590, -590, -590, -590, -590, -590, -590, -590,
-     -590, -590, -590, -590, -590, -590, -590, -590, -590, -590,
-     -590, -590, -590, -590, -590, -590, -590, -590, -590, -590,
-     -590, -590, -590, -590, -590, -590, -590, -590, -590, -590,
-
-     -590, -590, -590, -590, -590, -590, -590, -590, -590, -590,
-     -590, -590, -590, -590, -590, -590, -590, -590, -590, -590,
-     -590, -590, -590, -590, -590, -590, -590, -590
-    },
-
-    {
-       67, -591, -591, -591, -591, -591, -591, -591, -591, -591,
-     -591, -591, -591, -591, -591, -591, -591, -591, -591, -591,
-     -591, -591, -591, -591, -591, -591, -591, -591, -591, -591,
-     -591, -591,  687, -591, -591, -591, -591, -591, -591, -591,
-     -591, -591, -591, -591, -591, -591, -591, -591,  688,  688,
-      688,  688,  688,  688,  688,  688,  688,  688, -591, -591,
-     -591, -591, -591, -591, -591,  687,  687,  687,  687,  687,
-
-      687,  687,  687,  687,  687,  687,  687,  687,  687,  687,
-      687,  687,  687,  687,  687,  687,  687,  687,  687,  687,
-      687, -591, -591, -591, -591, -591, -591, -591, -591, -591,
-     -591, -591, -591, -591, -591, -591, -591, -591, -591, -591,
-     -591, -591, -591, -591, -591, -591, -591, -591, -591, -591,
-     -591, -591, -591, -591, -591, -591, -591, -591
-    },
-
-    {
-       67, -592, -592, -592, -592, -592, -592, -592, -592, -592,
-     -592, -592, -592, -592, -592, -592, -592, -592, -592, -592,
-     -592, -592, -592, -592, -592, -592, -592, -592, -592, -592,
-     -592, -592,  689, -592, -592, -592, -592, -592, -592, -592,
-
-     -592, -592, -592, -592, -592, -592, -592, -592, -592, -592,
-     -592, -592, -592, -592, -592, -592, -592, -592, -592, -592,
-     -592, -592, -592, -592, -592, -592, -592, -592, -592, -592,
-     -592, -592, -592, -592, -592, -592, -592, -592, -592, -592,
-     -592, -592, -592, -592, -592, -592, -592, -592, -592, -592,
-     -592, -592, -592, -592, -592, -592, -592, -592, -592, -592,
-     -592, -592, -592, -592, -592, -592, -592, -592, -592, -592,
-     -592, -592, -592, -592, -592, -592, -592, -592, -592, -592,
-     -592, -592, -592, -592, -592, -592, -592, -592
-    },
-
-    {
-       67, -593, -593, -593, -593, -593, -593, -593, -593, -593,
-
-     -593, -593, -593, -593, -593, -593, -593, -593, -593, -593,
-     -593, -593, -593, -593, -593, -593, -593, -593, -593, -593,
-     -593, -593,  690, -593, -593, -593, -593, -593, -593, -593,
-     -593, -593, -593, -593, -593, -593, -593, -593, -593, -593,
-     -593, -593, -593, -593, -593, -593, -593, -593, -593, -593,
-     -593, -593, -593, -593, -593, -593, -593, -593, -593, -593,
-     -593, -593, -593, -593, -593, -593, -593, -593, -593, -593,
-     -593, -593, -593, -593, -593, -593, -593, -593, -593, -593,
-     -593, -593, -593, -593, -593, -593, -593, -593, -593, -593,
-     -593, -593, -593, -593, -593, -593, -593, -593, -593, -593,
-
-     -593, -593, -593, -593, -593, -593, -593, -593, -593, -593,
-     -593, -593, -593, -593, -593, -593, -593, -593
-    },
-
-    {
-       67, -594, -594, -594, -594, -594, -594, -594, -594, -594,
-     -594, -594, -594, -594, -594, -594, -594, -594, -594, -594,
-     -594, -594, -594, -594, -594, -594, -594, -594, -594, -594,
-     -594, -594,  691, -594, -594, -594, -594, -594, -594, -594,
-     -594, -594, -594, -594, -594, -594, -594, -594,  692,  692,
-      692,  692,  692,  692,  692,  692,  692,  692, -594, -594,
-     -594, -594, -594, -594, -594,  691,  691,  691,  691,  691,
-      691,  691,  691,  691,  691,  691,  691,  691,  691,  691,
-
-      691,  691,  691,  691,  691,  691,  691,  691,  691,  691,
-      691, -594, -594, -594, -594, -594, -594, -594, -594, -594,
-     -594, -594, -594, -594, -594, -594, -594, -594, -594, -594,
-     -594, -594, -594, -594, -594, -594, -594, -594, -594, -594,
-     -594, -594, -594, -594, -594, -594, -594, -594
-    },
-
-    {
-       67, -595, -595, -595, -595, -595, -595, -595, -595, -595,
-     -595, -595, -595, -595, -595, -595, -595, -595, -595, -595,
-     -595, -595, -595, -595, -595, -595, -595, -595, -595, -595,
-     -595, -595, -595, -595, -595, -595, -595, -595, -595, -595,
-     -595, -595, -595, -595, -595, -595, -595, -595, -595, -595,
-
-     -595, -595, -595, -595, -595, -595, -595, -595, -595, -595,
-     -595, -595, -595, -595, -595, -595, -595, -595, -595, -595,
-     -595, -595, -595, -595, -595, -595, -595, -595, -595, -595,
-     -595, -595, -595, -595, -595, -595, -595, -595, -595, -595,
-     -595, -595, -595, -595, -595, -595, -595, -595, -595, -595,
-     -595, -595, -595, -595, -595, -595, -595, -595, -595, -595,
-     -595, -595, -595, -595, -595, -595, -595, -595, -595, -595,
-     -595, -595, -595, -595, -595, -595, -595, -595
-    },
-
-    {
-       67, -596, -596, -596, -596, -596, -596, -596, -596, -596,
-     -596, -596, -596, -596, -596, -596, -596, -596, -596, -596,
-
-     -596, -596, -596, -596, -596, -596, -596, -596, -596, -596,
-     -596, -596, -596, -596, -596, -596, -596, -596, -596, -596,
-     -596, -596, -596, -596, -596, -596, -596, -596, -596, -596,
-     -596, -596, -596, -596, -596, -596, -596, -596, -596, -596,
-     -596, -596, -596, -596, -596, -596, -596, -596, -596, -596,
-     -596, -596, -596, -596, -596, -596, -596, -596, -596, -596,
-     -596, -596, -596, -596, -596, -596, -596, -596, -596, -596,
-     -596, -596, -596, -596, -596, -596, -596, -596, -596, -596,
-     -596, -596, -596, -596, -596, -596, -596, -596, -596, -596,
-     -596, -596, -596, -596, -596, -596, -596, -596, -596, -596,
-
-     -596, -596, -596, -596, -596, -596, -596, -596
-    },
-
-    {
-       67, -597, -597, -597, -597, -597, -597, -597, -597, -597,
-     -597, -597, -597, -597, -597, -597, -597, -597, -597, -597,
-     -597, -597, -597, -597, -597, -597, -597, -597, -597, -597,
-     -597, -597, -597, -597, -597, -597, -597, -597, -597, -597,
-     -597, -597, -597, -597, -597, -597, -597, -597, -597, -597,
-     -597, -597, -597, -597, -597, -597, -597, -597, -597, -597,
-     -597, -597, -597, -597, -597, -597, -597, -597, -597, -597,
-     -597, -597, -597, -597, -597, -597, -597, -597, -597, -597,
-     -597, -597, -597, -597, -597, -597, -597, -597, -597, -597,
-
-     -597, -597, -597, -597, -597, -597, -597, -597, -597, -597,
-     -597, -597, -597, -597, -597, -597, -597, -597, -597, -597,
-     -597, -597, -597, -597, -597, -597, -597, -597, -597, -597,
-     -597, -597, -597, -597, -597, -597, -597, -597
-    },
-
-    {
-       67, -598, -598, -598, -598, -598, -598, -598, -598, -598,
-     -598, -598, -598, -598, -598, -598, -598, -598, -598, -598,
-     -598, -598, -598, -598, -598, -598, -598, -598, -598, -598,
-     -598, -598, -598, -598, -598, -598, -598, -598, -598, -598,
-     -598, -598, -598, -598, -598, -598, -598, -598, -598, -598,
-     -598, -598, -598, -598, -598, -598, -598, -598, -598, -598,
-
-     -598, -598, -598, -598, -598, -598, -598, -598, -598, -598,
-     -598, -598, -598, -598, -598, -598, -598, -598, -598, -598,
-     -598, -598, -598, -598, -598, -598, -598, -598, -598, -598,
-     -598, -598, -598, -598, -598, -598, -598, -598, -598, -598,
-     -598, -598, -598, -598, -598, -598, -598, -598, -598, -598,
-     -598, -598, -598, -598, -598, -598, -598, -598, -598, -598,
-     -598, -598, -598, -598, -598, -598, -598, -598
-    },
-
-    {
-       67, -599, -599, -599, -599, -599, -599, -599, -599, -599,
-     -599, -599, -599, -599, -599, -599, -599, -599, -599, -599,
-     -599, -599, -599, -599, -599, -599, -599, -599, -599, -599,
-
-     -599, -599, -599, -599, -599, -599, -599, -599, -599, -599,
-     -599, -599, -599, -599, -599, -599, -599, -599, -599, -599,
-     -599, -599, -599, -599, -599, -599, -599, -599, -599, -599,
-     -599, -599, -599, -599, -599, -599, -599, -599, -599, -599,
-     -599, -599, -599, -599, -599, -599, -599, -599, -599, -599,
-     -599, -599, -599, -599, -599, -599, -599, -599, -599, -599,
-     -599, -599, -599, -599, -599, -599, -599, -599, -599, -599,
-     -599, -599, -599, -599, -599, -599, -599, -599, -599, -599,
-     -599, -599, -599, -599, -599, -599, -599, -599, -599, -599,
-     -599, -599, -599, -599, -599, -599, -599, -599
-
-    },
-
-    {
-       67, -600, -600, -600, -600, -600, -600, -600, -600, -600,
-     -600, -600, -600, -600, -600, -600, -600, -600, -600, -600,
-     -600, -600, -600, -600, -600, -600, -600, -600, -600, -600,
-     -600, -600, -600, -600, -600, -600, -600, -600, -600, -600,
-     -600, -600, -600, -600, -600, -600, -600, -600, -600, -600,
-     -600, -600, -600, -600, -600, -600, -600, -600, -600, -600,
-     -600, -600, -600, -600, -600, -600, -600, -600, -600, -600,
-     -600, -600, -600, -600, -600, -600, -600, -600, -600, -600,
-     -600, -600, -600, -600, -600, -600, -600, -600, -600, -600,
-     -600, -600, -600, -600, -600, -600, -600, -600, -600, -600,
-
-     -600, -600, -600, -600, -600, -600, -600, -600, -600, -600,
-     -600, -600, -600, -600, -600, -600, -600, -600, -600, -600,
-     -600, -600, -600, -600, -600, -600, -600, -600
-    },
-
-    {
-       67, -601, -601, -601, -601, -601, -601, -601, -601, -601,
-     -601, -601, -601, -601, -601, -601, -601, -601, -601, -601,
-     -601, -601, -601, -601, -601, -601, -601, -601, -601, -601,
-     -601, -601, -601, -601, -601, -601, -601, -601, -601, -601,
-     -601, -601, -601, -601, -601, -601, -601, -601,  693,  693,
-      693,  693,  693,  693,  693,  693,  693,  693, -601, -601,
-     -601, -601, -601, -601, -601, -601, -601, -601, -601, -601,
-
-     -601, -601, -601, -601, -601, -601, -601, -601, -601, -601,
-     -601, -601, -601, -601, -601, -601, -601, -601, -601, -601,
-     -601, -601, -601, -601, -601, -601, -601, -601, -601, -601,
-     -601, -601, -601, -601, -601, -601, -601, -601, -601, -601,
-     -601, -601, -601, -601, -601, -601, -601, -601, -601, -601,
-     -601, -601, -601, -601, -601, -601, -601, -601
-    },
-
-    {
-       67, -602, -602, -602, -602, -602, -602, -602, -602, -602,
-     -602, -602, -602, -602, -602, -602, -602, -602, -602, -602,
-     -602, -602, -602, -602, -602, -602, -602, -602, -602, -602,
-     -602, -602,  694, -602, -602, -602, -602, -602, -602, -602,
-
-     -602, -602, -602, -602, -602, -602, -602, -602, -602, -602,
-     -602, -602, -602, -602, -602, -602, -602, -602, -602, -602,
-     -602, -602, -602, -602, -602,  694,  694,  694,  694,  694,
-      694,  694,  694,  694,  694,  694,  694,  694,  694,  694,
-      694,  694,  694,  694,  694,  694,  694,  694,  694,  694,
-      694, -602, -602, -602, -602, -602, -602, -602, -602, -602,
-     -602, -602, -602, -602, -602, -602, -602, -602, -602, -602,
-     -602, -602, -602, -602, -602, -602, -602, -602, -602, -602,
-     -602, -602, -602, -602, -602, -602, -602, -602
-    },
-
-    {
-       67, -603, -603, -603, -603, -603, -603, -603, -603, -603,
-
-     -603, -603, -603, -603, -603, -603, -603, -603, -603, -603,
-     -603, -603, -603, -603, -603, -603, -603, -603, -603, -603,
-     -603, -603,  694, -603, -603, -603, -603, -603, -603, -603,
-     -603, -603, -603, -603, -603, -603, -603, -603,  695,  695,
-      695,  695,  695,  695,  695,  695,  695,  695, -603, -603,
-     -603, -603, -603, -603, -603,  694,  694,  694,  694,  694,
-      694,  694,  694,  694,  694,  694,  694,  694,  694,  694,
-      694,  694,  694,  694,  694,  694,  694,  694,  694,  694,
-      694, -603, -603, -603, -603, -603, -603, -603, -603, -603,
-     -603, -603, -603, -603, -603, -603, -603, -603, -603, -603,
-
-     -603, -603, -603, -603, -603, -603, -603, -603, -603, -603,
-     -603, -603, -603, -603, -603, -603, -603, -603
-    },
-
-    {
-       67, -604, -604, -604, -604, -604, -604, -604, -604, -604,
-     -604, -604, -604, -604, -604, -604, -604, -604, -604, -604,
-     -604, -604, -604, -604, -604, -604, -604, -604, -604, -604,
-     -604, -604,  696, -604, -604, -604, -604, -604, -604, -604,
-     -604, -604, -604, -604, -604, -604, -604, -604, -604, -604,
-     -604, -604, -604, -604, -604, -604, -604, -604, -604, -604,
-     -604, -604, -604, -604, -604, -604, -604, -604, -604, -604,
-     -604, -604, -604, -604, -604, -604, -604, -604, -604, -604,
-
-     -604, -604, -604, -604, -604, -604, -604, -604, -604, -604,
-     -604, -604, -604, -604, -604, -604, -604, -604, -604, -604,
-     -604, -604, -604, -604, -604, -604, -604, -604, -604, -604,
-     -604, -604, -604, -604, -604, -604, -604, -604, -604, -604,
-     -604, -604, -604, -604, -604, -604, -604, -604
-    },
-
-    {
-       67, -605, -605, -605, -605, -605, -605, -605, -605, -605,
-     -605, -605, -605, -605, -605, -605, -605, -605, -605, -605,
-     -605, -605, -605, -605, -605, -605, -605, -605, -605, -605,
-     -605, -605,  697, -605, -605, -605, -605, -605, -605, -605,
-     -605, -605, -605, -605, -605, -605, -605, -605,  698,  698,
-
-      698,  698,  698,  698,  698,  698,  698,  698, -605, -605,
-     -605, -605, -605, -605, -605,  697,  697,  697,  697,  697,
-      697,  697,  697,  697,  697,  697,  697,  697,  697,  697,
-      697,  697,  697,  697,  697,  697,  697,  697,  697,  697,
-      697, -605, -605, -605, -605, -605, -605, -605, -605, -605,
-     -605, -605, -605, -605, -605, -605, -605, -605, -605, -605,
-     -605, -605, -605, -605, -605, -605, -605, -605, -605, -605,
-     -605, -605, -605, -605, -605, -605, -605, -605
-    },
-
-    {
-       67, -606, -606, -606, -606, -606, -606, -606, -606, -606,
-     -606, -606, -606, -606, -606, -606, -606, -606, -606, -606,
-
-     -606, -606, -606, -606, -606, -606, -606, -606, -606, -606,
-     -606, -606,  699, -606, -606, -606, -606, -606, -606, -606,
-     -606, -606, -606, -606, -606, -606, -606, -606, -606, -606,
-     -606, -606, -606, -606, -606, -606, -606, -606, -606, -606,
-     -606, -606, -606, -606, -606, -606, -606, -606, -606, -606,
-     -606, -606, -606, -606, -606, -606, -606, -606, -606, -606,
-     -606, -606, -606, -606, -606, -606, -606, -606, -606, -606,
-     -606, -606, -606, -606, -606, -606, -606, -606, -606, -606,
-     -606, -606, -606, -606, -606, -606, -606, -606, -606, -606,
-     -606, -606, -606, -606, -606, -606, -606, -606, -606, -606,
-
-     -606, -606, -606, -606, -606, -606, -606, -606
-    },
-
-    {
-       67, -607, -607, -607, -607, -607, -607, -607, -607, -607,
-     -607, -607, -607, -607, -607, -607, -607, -607, -607, -607,
-     -607, -607, -607, -607, -607, -607, -607, -607, -607, -607,
-     -607, -607,  700, -607, -607, -607, -607, -607, -607, -607,
-     -607, -607, -607, -607, -607, -607, -607, -607, -607, -607,
-     -607, -607, -607, -607, -607, -607, -607, -607, -607, -607,
-     -607, -607, -607, -607, -607, -607, -607, -607, -607, -607,
-     -607, -607, -607, -607, -607, -607, -607, -607, -607, -607,
-     -607, -607, -607, -607, -607, -607, -607, -607, -607, -607,
-
-     -607, -607, -607, -607, -607, -607, -607, -607, -607, -607,
-     -607, -607, -607, -607, -607, -607, -607, -607, -607, -607,
-     -607, -607, -607, -607, -607, -607, -607, -607, -607, -607,
-     -607, -607, -607, -607, -607, -607, -607, -607
-    },
-
-    {
-       67, -608, -608, -608, -608, -608, -608, -608, -608, -608,
-     -608, -608, -608, -608, -608, -608, -608, -608, -608, -608,
-     -608, -608, -608, -608, -608, -608, -608, -608, -608, -608,
-     -608, -608,  701, -608, -608, -608, -608, -608, -608, -608,
-     -608, -608, -608, -608, -608, -608, -608, -608,  702,  702,
-      702,  702,  702,  702,  702,  702,  702,  702, -608, -608,
-
-     -608, -608, -608, -608, -608,  701,  701,  701,  701,  701,
-      701,  701,  701,  701,  701,  701,  701,  701,  701,  701,
-      701,  701,  701,  701,  701,  701,  701,  701,  701,  701,
-      701, -608, -608, -608, -608, -608, -608, -608, -608, -608,
-     -608, -608, -608, -608, -608, -608, -608, -608, -608, -608,
-     -608, -608, -608, -608, -608, -608, -608, -608, -608, -608,
-     -608, -608, -608, -608, -608, -608, -608, -608
-    },
-
-    {
-       67, -609, -609, -609, -609, -609, -609, -609, -609, -609,
-     -609, -609, -609, -609, -609, -609, -609, -609, -609, -609,
-     -609, -609, -609, -609, -609, -609, -609, -609, -609, -609,
-
-     -609, -609, -609, -609, -609, -609, -609, -609, -609, -609,
-     -609, -609, -609, -609, -609, -609, -609, -609,  703,  703,
-      703,  703,  703,  703,  703,  703,  703,  703, -609, -609,
-     -609, -609, -609, -609, -609, -609, -609, -609, -609, -609,
-     -609, -609, -609, -609, -609, -609, -609, -609, -609, -609,
-     -609, -609, -609, -609, -609, -609, -609, -609, -609, -609,
-     -609, -609, -609, -609, -609, -609, -609, -609, -609, -609,
-     -609, -609, -609, -609, -609, -609, -609, -609, -609, -609,
-     -609, -609, -609, -609, -609, -609, -609, -609, -609, -609,
-     -609, -609, -609, -609, -609, -609, -609, -609
-
-    },
-
-    {
-       67, -610, -610, -610, -610, -610, -610, -610, -610, -610,
-     -610, -610, -610, -610, -610, -610, -610, -610, -610, -610,
-     -610, -610, -610, -610, -610, -610, -610, -610, -610, -610,
-     -610, -610,  704, -610, -610, -610, -610, -610, -610, -610,
-     -610, -610, -610, -610, -610, -610, -610, -610, -610, -610,
-     -610, -610, -610, -610, -610, -610, -610, -610, -610, -610,
-     -610, -610, -610, -610, -610,  704,  704,  704,  704,  704,
-      704,  704,  704,  704,  704,  704,  704,  704,  704,  704,
-      704,  704,  704,  704,  704,  704,  704,  704,  704,  704,
-      704, -610, -610, -610, -610, -610, -610, -610, -610, -610,
-
-     -610, -610, -610, -610, -610, -610, -610, -610, -610, -610,
-     -610, -610, -610, -610, -610, -610, -610, -610, -610, -610,
-     -610, -610, -610, -610, -610, -610, -610, -610
-    },
-
-    {
-       67, -611, -611, -611, -611, -611, -611, -611, -611, -611,
-     -611, -611, -611, -611, -611, -611, -611, -611, -611, -611,
-     -611, -611, -611, -611, -611, -611, -611, -611, -611, -611,
-     -611, -611,  704, -611, -611, -611, -611, -611, -611, -611,
-     -611, -611, -611, -611, -611, -611, -611, -611,  705,  705,
-      705,  705,  705,  705,  705,  705,  705,  705, -611, -611,
-     -611, -611, -611, -611, -611,  704,  704,  704,  704,  704,
-
-      704,  704,  704,  704,  704,  704,  704,  704,  704,  704,
-      704,  704,  704,  704,  704,  704,  704,  704,  704,  704,
-      704, -611, -611, -611, -611, -611, -611, -611, -611, -611,
-     -611, -611, -611, -611, -611, -611, -611, -611, -611, -611,
-     -611, -611, -611, -611, -611, -611, -611, -611, -611, -611,
-     -611, -611, -611, -611, -611, -611, -611, -611
-    },
-
-    {
-       67, -612, -612, -612, -612, -612, -612, -612, -612, -612,
-     -612, -612, -612, -612, -612, -612, -612, -612, -612, -612,
-     -612, -612, -612, -612, -612, -612, -612, -612, -612, -612,
-     -612, -612,  706, -612, -612, -612, -612, -612, -612, -612,
-
-     -612, -612, -612, -612, -612, -612, -612, -612, -612, -612,
-     -612, -612, -612, -612, -612, -612, -612, -612, -612, -612,
-     -612, -612, -612, -612, -612, -612, -612, -612, -612, -612,
-     -612, -612, -612, -612, -612, -612, -612, -612, -612, -612,
-     -612, -612, -612, -612, -612, -612, -612, -612, -612, -612,
-     -612, -612, -612, -612, -612, -612, -612, -612, -612, -612,
-     -612, -612, -612, -612, -612, -612, -612, -612, -612, -612,
-     -612, -612, -612, -612, -612, -612, -612, -612, -612, -612,
-     -612, -612, -612, -612, -612, -612, -612, -612
-    },
-
-    {
-       67, -613, -613, -613, -613, -613, -613, -613, -613, -613,
-
-     -613, -613, -613, -613, -613, -613, -613, -613, -613, -613,
-     -613, -613, -613, -613, -613, -613, -613, -613, -613, -613,
-     -613, -613,  707, -613, -613, -613, -613, -613, -613, -613,
-     -613, -613, -613, -613, -613, -613, -613, -613,  708,  708,
-      708,  708,  708,  708,  708,  708,  708,  708, -613, -613,
-     -613, -613, -613, -613, -613,  707,  707,  707,  707,  707,
-      707,  707,  707,  707,  707,  707,  707,  707,  707,  707,
-      707,  707,  707,  707,  707,  707,  707,  707,  707,  707,
-      707, -613, -613, -613, -613, -613, -613, -613, -613, -613,
-     -613, -613, -613, -613, -613, -613, -613, -613, -613, -613,
-
-     -613, -613, -613, -613, -613, -613, -613, -613, -613, -613,
-     -613, -613, -613, -613, -613, -613, -613, -613
-    },
-
-    {
-       67, -614, -614, -614, -614, -614, -614, -614, -614, -614,
-     -614, -614, -614, -614, -614, -614, -614, -614, -614, -614,
-     -614, -614, -614, -614, -614, -614, -614, -614, -614, -614,
-     -614, -614,  709, -614, -614, -614, -614, -614, -614, -614,
-     -614, -614, -614, -614, -614, -614, -614, -614, -614, -614,
-     -614, -614, -614, -614, -614, -614, -614, -614, -614, -614,
-     -614, -614, -614, -614, -614, -614, -614, -614, -614, -614,
-     -614, -614, -614, -614, -614, -614, -614, -614, -614, -614,
-
-     -614, -614, -614, -614, -614, -614, -614, -614, -614, -614,
-     -614, -614, -614, -614, -614, -614, -614, -614, -614, -614,
-     -614, -614, -614, -614, -614, -614, -614, -614, -614, -614,
-     -614, -614, -614, -614, -614, -614, -614, -614, -614, -614,
-     -614, -614, -614, -614, -614, -614, -614, -614
-    },
-
-    {
-       67, -615, -615, -615, -615, -615, -615, -615, -615, -615,
-     -615, -615, -615, -615, -615, -615, -615, -615, -615, -615,
-     -615, -615, -615, -615, -615, -615, -615, -615, -615, -615,
-     -615, -615,  710, -615, -615, -615, -615, -615, -615, -615,
-     -615, -615, -615, -615, -615, -615, -615, -615, -615, -615,
-
-     -615, -615, -615, -615, -615, -615, -615, -615, -615, -615,
-     -615, -615, -615, -615, -615, -615, -615, -615, -615, -615,
-     -615, -615, -615, -615, -615, -615, -615, -615, -615, -615,
-     -615, -615, -615, -615, -615, -615, -615, -615, -615, -615,
-     -615, -615, -615, -615, -615, -615, -615, -615, -615, -615,
-     -615, -615, -615, -615, -615, -615, -615, -615, -615, -615,
-     -615, -615, -615, -615, -615, -615, -615, -615, -615, -615,
-     -615, -615, -615, -615, -615, -615, -615, -615
-    },
-
-    {
-       67, -616, -616, -616, -616, -616, -616, -616, -616, -616,
-     -616, -616, -616, -616, -616, -616, -616, -616, -616, -616,
-
-     -616, -616, -616, -616, -616, -616, -616, -616, -616, -616,
-     -616, -616,  711, -616, -616, -616, -616, -616, -616, -616,
-     -616, -616, -616, -616, -616, -616, -616, -616,  712,  712,
-      712,  712,  712,  712,  712,  712,  712,  712, -616, -616,
-     -616, -616, -616, -616, -616,  711,  711,  711,  711,  711,
-      711,  711,  711,  711,  711,  711,  711,  711,  711,  711,
-      711,  711,  711,  711,  711,  711,  711,  711,  711,  711,
-      711, -616, -616, -616, -616, -616, -616, -616, -616, -616,
-     -616, -616, -616, -616, -616, -616, -616, -616, -616, -616,
-     -616, -616, -616, -616, -616, -616, -616, -616, -616, -616,
-
-     -616, -616, -616, -616, -616, -616, -616, -616
-    },
-
-    {
-       67, -617, -617, -617, -617, -617, -617, -617, -617, -617,
-     -617, -617, -617, -617, -617, -617, -617, -617, -617, -617,
-     -617, -617, -617, -617, -617, -617, -617, -617, -617, -617,
-     -617, -617, -617, -617, -617, -617, -617, -617, -617, -617,
-     -617, -617, -617, -617, -617, -617, -617, -617, -617, -617,
-     -617, -617, -617, -617, -617, -617, -617, -617, -617, -617,
-     -617, -617, -617, -617, -617, -617, -617, -617, -617, -617,
-     -617, -617, -617, -617, -617, -617, -617, -617, -617, -617,
-     -617, -617, -617, -617, -617, -617, -617, -617, -617, -617,
-
-     -617, -617, -617, -617, -617, -617, -617, -617, -617, -617,
-     -617, -617, -617, -617, -617, -617, -617, -617, -617, -617,
-     -617, -617, -617, -617, -617, -617, -617, -617, -617, -617,
-     -617, -617, -617, -617, -617, -617, -617, -617
-    },
-
-    {
-       67, -618, -618, -618, -618, -618, -618, -618, -618, -618,
-     -618, -618, -618, -618, -618, -618, -618, -618, -618, -618,
-     -618, -618, -618, -618, -618, -618, -618, -618, -618, -618,
-     -618, -618, -618, -618, -618, -618, -618, -618, -618, -618,
-     -618, -618, -618, -618, -618, -618, -618, -618, -618, -618,
-     -618, -618, -618, -618, -618, -618, -618, -618, -618, -618,
-
-     -618, -618, -618, -618, -618, -618, -618, -618, -618, -618,
-     -618, -618, -618, -618, -618, -618, -618, -618, -618, -618,
-     -618, -618, -618, -618, -618, -618, -618, -618, -618, -618,
-     -618, -618, -618, -618, -618, -618, -618, -618, -618, -618,
-     -618, -618, -618, -618, -618, -618, -618, -618, -618, -618,
-     -618, -618, -618, -618, -618, -618, -618, -618, -618, -618,
-     -618, -618, -618, -618, -618, -618, -618, -618
-    },
-
-    {
-       67, -619, -619, -619, -619, -619, -619, -619, -619, -619,
-     -619, -619, -619, -619, -619, -619, -619, -619, -619, -619,
-     -619, -619, -619, -619, -619, -619, -619, -619, -619, -619,
-
-     -619, -619, -619, -619, -619, -619, -619, -619, -619, -619,
-     -619, -619, -619, -619, -619, -619, -619, -619, -619, -619,
-     -619, -619, -619, -619, -619, -619, -619, -619, -619, -619,
-     -619, -619, -619, -619, -619, -619, -619, -619, -619, -619,
-     -619, -619, -619, -619, -619, -619, -619, -619, -619, -619,
-     -619, -619, -619, -619, -619, -619, -619, -619, -619, -619,
-     -619, -619, -619, -619, -619, -619, -619, -619, -619, -619,
-     -619, -619, -619, -619, -619, -619, -619, -619, -619, -619,
-     -619, -619, -619, -619, -619, -619, -619, -619, -619, -619,
-     -619, -619, -619, -619, -619, -619, -619, -619
-
-    },
-
-    {
-       67, -620, -620, -620, -620, -620, -620, -620, -620, -620,
-     -620, -620, -620, -620, -620, -620, -620, -620, -620, -620,
-     -620, -620, -620, -620, -620, -620, -620, -620, -620, -620,
-     -620, -620, -620, -620, -620, -620, -620, -620, -620, -620,
-     -620, -620, -620, -620, -620, -620, -620, -620, -620, -620,
-     -620, -620, -620, -620, -620, -620, -620, -620, -620, -620,
-     -620, -620, -620, -620, -620, -620, -620, -620, -620, -620,
-     -620, -620, -620, -620, -620, -620, -620, -620, -620, -620,
-     -620, -620, -620, -620, -620, -620, -620, -620, -620, -620,
-     -620, -620, -620, -620, -620, -620, -620, -620, -620, -620,
-
-     -620, -620, -620, -620, -620, -620, -620, -620, -620, -620,
-     -620, -620, -620, -620, -620, -620, -620, -620, -620, -620,
-     -620, -620, -620, -620, -620, -620, -620, -620
-    },
-
-    {
-       67, -621, -621, -621, -621, -621, -621, -621, -621, -621,
-     -621, -621, -621, -621, -621, -621, -621, -621, -621, -621,
-     -621, -621, -621, -621, -621, -621, -621, -621, -621, -621,
-     -621, -621, -621, -621, -621, -621, -621, -621, -621, -621,
-     -621, -621, -621, -621, -621, -621, -621, -621, -621, -621,
-     -621, -621, -621, -621, -621, -621, -621, -621, -621, -621,
-     -621, -621, -621, -621, -621, -621, -621, -621, -621, -621,
-
-     -621, -621, -621, -621, -621, -621, -621, -621, -621, -621,
-     -621, -621, -621, -621, -621, -621, -621, -621, -621, -621,
-     -621, -621, -621, -621, -621, -621, -621, -621, -621, -621,
-     -621, -621, -621, -621, -621, -621, -621, -621, -621, -621,
-     -621, -621, -621, -621, -621, -621, -621, -621, -621, -621,
-     -621, -621, -621, -621, -621, -621, -621, -621
-    },
-
-    {
-       67, -622, -622, -622, -622, -622, -622, -622, -622, -622,
-     -622, -622, -622, -622, -622, -622, -622, -622, -622, -622,
-     -622, -622, -622, -622, -622, -622, -622, -622, -622, -622,
-     -622, -622, -622, -622, -622, -622, -622, -622, -622, -622,
-
-     -622, -622, -622, -622, -622, -622, -622, -622, -622, -622,
-     -622, -622, -622, -622, -622, -622, -622, -622, -622, -622,
-     -622, -622, -622, -622, -622, -622, -622, -622, -622, -622,
-     -622, -622, -622, -622, -622, -622, -622, -622, -622, -622,
-     -622, -622, -622, -622, -622, -622, -622, -622, -622, -622,
-     -622, -622, -622, -622, -622, -622, -622, -622, -622, -622,
-     -622, -622, -622, -622, -622, -622, -622, -622, -622, -622,
-     -622, -622, -622, -622, -622, -622, -622, -622, -622, -622,
-     -622, -622, -622, -622, -622, -622, -622, -622
-    },
-
-    {
-       67, -623, -623, -623, -623, -623, -623, -623, -623, -623,
-
-     -623, -623, -623, -623, -623, -623, -623, -623, -623, -623,
-     -623, -623, -623, -623, -623, -623, -623, -623, -623, -623,
-     -623, -623, -623, -623, -623, -623, -623, -623, -623, -623,
-     -623, -623, -623, -623, -623, -623, -623, -623,  713,  713,
-      713,  713,  713,  713,  713,  713,  713,  713, -623, -623,
-     -623, -623, -623, -623, -623, -623, -623, -623, -623, -623,
-     -623, -623, -623, -623, -623, -623, -623, -623, -623, -623,
-     -623, -623, -623, -623, -623, -623, -623, -623, -623, -623,
-     -623, -623, -623, -623, -623, -623, -623, -623, -623, -623,
-     -623, -623, -623, -623, -623, -623, -623, -623, -623, -623,
-
-     -623, -623, -623, -623, -623, -623, -623, -623, -623, -623,
-     -623, -623, -623, -623, -623, -623, -623, -623
-    },
-
-    {
-       67, -624, -624, -624, -624, -624, -624, -624, -624, -624,
-     -624, -624, -624, -624, -624, -624, -624, -624, -624, -624,
-     -624, -624, -624, -624, -624, -624, -624, -624, -624, -624,
-     -624, -624,  714, -624, -624, -624, -624, -624, -624, -624,
-     -624, -624, -624, -624, -624, -624, -624, -624, -624, -624,
-     -624, -624, -624, -624, -624, -624, -624, -624, -624, -624,
-     -624, -624, -624, -624, -624,  714,  714,  714,  714,  714,
-      714,  714,  714,  714,  714,  714,  714,  714,  714,  714,
-
-      714,  714,  714,  714,  714,  714,  714,  714,  714,  714,
-      714, -624, -624, -624, -624, -624, -624, -624, -624, -624,
-     -624, -624, -624, -624, -624, -624, -624, -624, -624, -624,
-     -624, -624, -624, -624, -624, -624, -624, -624, -624, -624,
-     -624, -624, -624, -624, -624, -624, -624, -624
-    },
-
-    {
-       67, -625, -625, -625, -625, -625, -625, -625, -625, -625,
-     -625, -625, -625, -625, -625, -625, -625, -625, -625, -625,
-     -625, -625, -625, -625, -625, -625, -625, -625, -625, -625,
-     -625, -625,  714, -625, -625, -625, -625, -625, -625, -625,
-     -625, -625, -625, -625, -625, -625, -625, -625,  715,  715,
-
-      715,  715,  715,  715,  715,  715,  715,  715, -625, -625,
-     -625, -625, -625, -625, -625,  714,  714,  714,  714,  714,
-      714,  714,  714,  714,  714,  714,  714,  714,  714,  714,
-      714,  714,  714,  714,  714,  714,  714,  714,  714,  714,
-      714, -625, -625, -625, -625, -625, -625, -625, -625, -625,
-     -625, -625, -625, -625, -625, -625, -625, -625, -625, -625,
-     -625, -625, -625, -625, -625, -625, -625, -625, -625, -625,
-     -625, -625, -625, -625, -625, -625, -625, -625
-    },
-
-    {
-       67, -626, -626, -626, -626, -626, -626, -626, -626, -626,
-     -626, -626, -626, -626, -626, -626, -626, -626, -626, -626,
-
-     -626, -626, -626, -626, -626, -626, -626, -626, -626, -626,
-     -626, -626,  716, -626, -626, -626, -626, -626, -626, -626,
-     -626, -626, -626, -626, -626, -626, -626, -626, -626, -626,
-     -626, -626, -626, -626, -626, -626, -626, -626, -626, -626,
-     -626, -626, -626, -626, -626, -626, -626, -626, -626, -626,
-     -626, -626, -626, -626, -626, -626, -626, -626, -626, -626,
-     -626, -626, -626, -626, -626, -626, -626, -626, -626, -626,
-     -626, -626, -626, -626, -626, -626, -626, -626, -626, -626,
-     -626, -626, -626, -626, -626, -626, -626, -626, -626, -626,
-     -626, -626, -626, -626, -626, -626, -626, -626, -626, -626,
-
-     -626, -626, -626, -626, -626, -626, -626, -626
-    },
-
-    {
-       67, -627, -627, -627, -627, -627, -627, -627, -627, -627,
-     -627, -627, -627, -627, -627, -627, -627, -627, -627, -627,
-     -627, -627, -627, -627, -627, -627, -627, -627, -627, -627,
-     -627, -627,  717, -627, -627, -627, -627, -627, -627, -627,
-     -627, -627, -627, -627, -627, -627, -627, -627,  718,  718,
-      718,  718,  718,  718,  718,  718,  718,  718, -627, -627,
-     -627, -627, -627, -627, -627,  717,  717,  717,  717,  717,
-      717,  717,  717,  717,  717,  717,  717,  717,  717,  717,
-      717,  717,  717,  717,  717,  717,  717,  717,  717,  717,
-
-      717, -627, -627, -627, -627, -627, -627, -627, -627, -627,
-     -627, -627, -627, -627, -627, -627, -627, -627, -627, -627,
-     -627, -627, -627, -627, -627, -627, -627, -627, -627, -627,
-     -627, -627, -627, -627, -627, -627, -627, -627
-    },
-
-    {
-       67, -628, -628, -628, -628, -628, -628, -628, -628, -628,
-     -628, -628, -628, -628, -628, -628, -628, -628, -628, -628,
-     -628, -628, -628, -628, -628, -628, -628, -628, -628, -628,
-     -628, -628,  719, -628, -628, -628, -628, -628, -628, -628,
-     -628, -628, -628, -628, -628, -628, -628, -628, -628, -628,
-     -628, -628, -628, -628, -628, -628, -628, -628, -628, -628,
-
-     -628, -628, -628, -628, -628, -628, -628, -628, -628, -628,
-     -628, -628, -628, -628, -628, -628, -628, -628, -628, -628,
-     -628, -628, -628, -628, -628, -628, -628, -628, -628, -628,
-     -628, -628, -628, -628, -628, -628, -628, -628, -628, -628,
-     -628, -628, -628, -628, -628, -628, -628, -628, -628, -628,
-     -628, -628, -628, -628, -628, -628, -628, -628, -628, -628,
-     -628, -628, -628, -628, -628, -628, -628, -628
-    },
-
-    {
-       67, -629, -629, -629, -629, -629, -629, -629, -629, -629,
-     -629, -629, -629, -629, -629, -629, -629, -629, -629, -629,
-     -629, -629, -629, -629, -629, -629, -629, -629, -629, -629,
-
-     -629, -629,  720, -629, -629, -629, -629, -629, -629, -629,
-     -629, -629, -629, -629, -629, -629, -629, -629, -629, -629,
-     -629, -629, -629, -629, -629, -629, -629, -629, -629, -629,
-     -629, -629, -629, -629, -629, -629, -629, -629, -629, -629,
-     -629, -629, -629, -629, -629, -629, -629, -629, -629, -629,
-     -629, -629, -629, -629, -629, -629, -629, -629, -629, -629,
-     -629, -629, -629, -629, -629, -629, -629, -629, -629, -629,
-     -629, -629, -629, -629, -629, -629, -629, -629, -629, -629,
-     -629, -629, -629, -629, -629, -629, -629, -629, -629, -629,
-     -629, -629, -629, -629, -629, -629, -629, -629
-
-    },
-
-    {
-       67, -630, -630, -630, -630, -630, -630, -630, -630, -630,
-     -630, -630, -630, -630, -630, -630, -630, -630, -630, -630,
-     -630, -630, -630, -630, -630, -630, -630, -630, -630, -630,
-     -630, -630,  721, -630, -630, -630, -630, -630, -630, -630,
-     -630, -630, -630, -630, -630, -630, -630, -630,  722,  722,
-      722,  722,  722,  722,  722,  722,  722,  722, -630, -630,
-     -630, -630, -630, -630, -630,  721,  721,  721,  721,  721,
-      721,  721,  721,  721,  721,  721,  721,  721,  721,  721,
-      721,  721,  721,  721,  721,  721,  721,  721,  721,  721,
-      721, -630, -630, -630, -630, -630, -630, -630, -630, -630,
-
-     -630, -630, -630, -630, -630, -630, -630, -630, -630, -630,
-     -630, -630, -630, -630, -630, -630, -630, -630, -630, -630,
-     -630, -630, -630, -630, -630, -630, -630, -630
-    },
-
-    {
-       67, -631, -631, -631, -631, -631, -631, -631, -631, -631,
-     -631, -631, -631, -631, -631, -631, -631, -631, -631, -631,
-     -631, -631, -631, -631, -631, -631, -631, -631, -631, -631,
-     -631, -631, -631, -631, -631, -631, -631, -631, -631, -631,
-     -631, -631, -631, -631, -631, -631, -631, -631, -631, -631,
-     -631, -631, -631, -631, -631, -631, -631, -631, -631, -631,
-     -631, -631, -631, -631, -631, -631, -631, -631, -631, -631,
-
-     -631, -631, -631, -631, -631, -631, -631, -631, -631, -631,
-     -631, -631, -631, -631, -631, -631, -631, -631, -631, -631,
-     -631, -631, -631, -631, -631, -631, -631, -631, -631, -631,
-     -631, -631, -631, -631, -631, -631, -631, -631, -631, -631,
-     -631, -631, -631, -631, -631, -631, -631, -631, -631, -631,
-     -631, -631, -631, -631, -631, -631, -631, -631
-    },
-
-    {
-       67, -632, -632, -632, -632, -632, -632, -632, -632, -632,
-     -632, -632, -632, -632, -632, -632, -632, -632, -632, -632,
-     -632, -632, -632, -632, -632, -632, -632, -632, -632, -632,
-     -632, -632, -632, -632, -632, -632, -632, -632, -632, -632,
-
-     -632, -632, -632, -632, -632, -632, -632, -632, -632, -632,
-     -632, -632, -632, -632, -632, -632, -632, -632, -632, -632,
-     -632, -632, -632, -632, -632, -632, -632, -632, -632, -632,
-     -632, -632, -632, -632, -632, -632, -632, -632, -632, -632,
-     -632, -632, -632, -632, -632, -632, -632, -632, -632, -632,
-     -632, -632, -632, -632, -632, -632, -632, -632, -632, -632,
-     -632, -632, -632, -632, -632, -632, -632, -632, -632, -632,
-     -632, -632, -632, -632, -632, -632, -632, -632, -632, -632,
-     -632, -632, -632, -632, -632, -632, -632, -632
-    },
-
-    {
-       67, -633, -633, -633, -633, -633, -633, -633, -633, -633,
-
-     -633, -633, -633, -633, -633, -633, -633, -633, -633, -633,
-     -633, -633, -633, -633, -633, -633, -633, -633, -633, -633,
-     -633, -633, -633, -633, -633, -633, -633, -633, -633, -633,
-     -633, -633, -633, -633, -633, -633, -633, -633, -633, -633,
-     -633, -633, -633, -633, -633, -633, -633, -633, -633, -633,
-     -633, -633, -633, -633, -633, -633, -633, -633, -633, -633,
-     -633, -633, -633, -633, -633, -633, -633, -633, -633, -633,
-     -633, -633, -633, -633, -633, -633, -633, -633, -633, -633,
-     -633, -633, -633, -633, -633, -633, -633, -633, -633, -633,
-     -633, -633, -633, -633, -633, -633, -633, -633, -633, -633,
-
-     -633, -633, -633, -633, -633, -633, -633, -633, -633, -633,
-     -633, -633, -633, -633, -633, -633, -633, -633
-    },
-
-    {
-       67, -634, -634, -634, -634, -634, -634, -634, -634, -634,
-     -634, -634, -634, -634, -634, -634, -634, -634, -634, -634,
-     -634, -634, -634, -634, -634, -634, -634, -634, -634, -634,
-     -634, -634, -634, -634, -634, -634, -634, -634, -634, -634,
-     -634, -634, -634, -634, -634, -634, -634, -634, -634, -634,
-     -634, -634, -634, -634, -634, -634, -634, -634, -634, -634,
-     -634, -634, -634, -634, -634, -634, -634, -634, -634, -634,
-     -634, -634, -634, -634, -634, -634, -634, -634, -634, -634,
-
-     -634, -634, -634, -634, -634, -634, -634, -634, -634, -634,
-     -634, -634, -634, -634, -634, -634, -634, -634, -634, -634,
-     -634, -634, -634, -634, -634, -634, -634, -634, -634, -634,
-     -634, -634, -634, -634, -634, -634, -634, -634, -634, -634,
-     -634, -634, -634, -634, -634, -634, -634, -634
-    },
-
-    {
-       67, -635, -635, -635, -635, -635, -635, -635, -635, -635,
-     -635, -635, -635, -635, -635, -635, -635, -635, -635, -635,
-     -635, -635, -635, -635, -635, -635, -635, -635, -635, -635,
-     -635, -635, -635, -635, -635, -635, -635, -635, -635, -635,
-     -635, -635, -635, -635, -635, -635, -635, -635, -635, -635,
-
-     -635, -635, -635, -635, -635, -635, -635, -635, -635, -635,
-     -635, -635, -635, -635, -635, -635, -635, -635, -635, -635,
-     -635, -635, -635, -635, -635, -635, -635, -635, -635, -635,
-     -635, -635, -635, -635, -635, -635, -635, -635, -635, -635,
-     -635, -635, -635, -635, -635, -635, -635, -635, -635, -635,
-     -635, -635, -635, -635, -635, -635, -635, -635, -635, -635,
-     -635, -635, -635, -635, -635, -635, -635, -635, -635, -635,
-     -635, -635, -635, -635, -635, -635, -635, -635
-    },
-
-    {
-       67, -636, -636, -636, -636, -636, -636, -636, -636, -636,
-     -636, -636, -636, -636, -636, -636, -636, -636, -636, -636,
-
-     -636, -636, -636, -636, -636, -636, -636, -636, -636, -636,
-     -636, -636, -636, -636, -636, -636, -636, -636, -636, -636,
-     -636, -636, -636, -636, -636, -636, -636, -636, -636, -636,
-     -636, -636, -636, -636, -636, -636, -636, -636, -636, -636,
-     -636, -636, -636, -636, -636, -636, -636, -636, -636, -636,
-     -636, -636, -636, -636, -636, -636, -636, -636, -636, -636,
-     -636, -636, -636, -636, -636, -636, -636, -636, -636, -636,
-     -636, -636, -636, -636, -636, -636, -636, -636, -636, -636,
-     -636, -636, -636, -636, -636, -636, -636, -636, -636, -636,
-     -636, -636, -636, -636, -636, -636, -636, -636, -636, -636,
-
-     -636, -636, -636, -636, -636, -636, -636, -636
-    },
-
-    {
-       67, -637, -637, -637, -637, -637, -637, -637, -637, -637,
-     -637, -637, -637, -637, -637, -637, -637, -637, -637, -637,
-     -637, -637, -637, -637, -637, -637, -637, -637, -637, -637,
-     -637, -637, -637, -637, -637, -637, -637, -637, -637, -637,
-     -637, -637, -637, -637, -637, -637, -637, -637, -637, -637,
-     -637, -637, -637, -637, -637, -637, -637, -637, -637, -637,
-     -637, -637, -637, -637, -637, -637, -637, -637, -637, -637,
-     -637, -637, -637, -637, -637, -637, -637, -637, -637, -637,
-     -637, -637, -637, -637, -637, -637,  723, -637, -637, -637,
-
-     -637, -637, -637, -637, -637, -637, -637, -637, -637, -637,
-     -637, -637, -637, -637, -637, -637, -637, -637, -637, -637,
-     -637, -637, -637, -637, -637, -637, -637, -637, -637, -637,
-     -637, -637, -637, -637, -637, -637, -637, -637
-    },
-
-    {
-       67, -638, -638, -638, -638, -638, -638, -638, -638, -638,
-     -638, -638, -638, -638, -638, -638, -638, -638, -638, -638,
-     -638, -638, -638, -638, -638, -638, -638, -638, -638, -638,
-     -638, -638, -638, -638, -638, -638, -638, -638, -638, -638,
-     -638, -638, -638, -638, -638, -638, -638, -638, -638, -638,
-     -638, -638, -638, -638, -638, -638, -638, -638, -638, -638,
-
-     -638, -638, -638, -638, -638, -638,  724, -638, -638, -638,
-     -638, -638, -638, -638, -638, -638, -638, -638, -638, -638,
-     -638, -638, -638, -638, -638, -638, -638, -638, -638, -638,
-     -638, -638, -638, -638, -638, -638, -638, -638, -638, -638,
-     -638, -638, -638, -638, -638, -638, -638, -638, -638, -638,
-     -638, -638, -638, -638, -638, -638, -638, -638, -638, -638,
-     -638, -638, -638, -638, -638, -638, -638, -638
-    },
-
-    {
-       67, -639, -639, -639, -639, -639, -639, -639, -639, -639,
-     -639, -639, -639, -639, -639, -639, -639, -639, -639, -639,
-     -639, -639, -639, -639, -639, -639, -639, -639, -639, -639,
-
-     -639, -639,  725, -639, -639, -639, -639, -639, -639, -639,
-     -639, -639, -639, -639, -639, -639, -639, -639, -639, -639,
-     -639, -639, -639, -639, -639, -639, -639, -639, -639, -639,
-     -639, -639, -639, -639, -639, -639, -639, -639, -639, -639,
-     -639, -639, -639, -639, -639, -639, -639, -639, -639, -639,
-     -639, -639, -639, -639, -639, -639, -639, -639, -639, -639,
-     -639, -639, -639, -639, -639, -639, -639, -639, -639, -639,
-     -639, -639, -639, -639, -639, -639, -639, -639, -639, -639,
-     -639, -639, -639, -639, -639, -639, -639, -639, -639, -639,
-     -639, -639, -639, -639, -639, -639, -639, -639
-
-    },
-
-    {
-       67, -640, -640, -640, -640, -640, -640, -640, -640, -640,
-     -640, -640, -640, -640, -640, -640, -640, -640, -640, -640,
-     -640, -640, -640, -640, -640, -640, -640, -640, -640, -640,
-     -640, -640,  726, -640, -640, -640, -640, -640, -640, -640,
-     -640, -640, -640, -640, -640, -640, -640, -640,  727,  727,
-      727,  727,  727,  727,  727,  727,  727,  727, -640, -640,
-     -640, -640, -640, -640, -640, -640, -640, -640, -640, -640,
-     -640, -640, -640, -640, -640, -640, -640, -640, -640, -640,
-     -640, -640, -640, -640, -640, -640, -640, -640, -640, -640,
-     -640, -640, -640, -640, -640, -640, -640, -640, -640, -640,
-
-     -640, -640, -640, -640, -640, -640, -640, -640, -640, -640,
-     -640, -640, -640, -640, -640, -640, -640, -640, -640, -640,
-     -640, -640, -640, -640, -640, -640, -640, -640
-    },
-
-    {
-       67, -641, -641, -641, -641, -641, -641, -641, -641, -641,
-     -641, -641, -641, -641, -641, -641, -641, -641, -641, -641,
-     -641, -641, -641, -641, -641, -641, -641, -641, -641, -641,
-     -641, -641,  728, -641, -641, -641, -641, -641, -641, -641,
-     -641, -641, -641, -641, -641, -641, -641, -641, -641, -641,
-     -641, -641, -641, -641, -641, -641, -641, -641, -641, -641,
-     -641, -641, -641, -641, -641, -641, -641, -641, -641, -641,
-
-     -641, -641, -641, -641, -641, -641, -641, -641, -641, -641,
-     -641, -641, -641, -641, -641, -641, -641, -641, -641, -641,
-     -641, -641, -641, -641, -641, -641, -641, -641, -641, -641,
-     -641, -641, -641, -641, -641, -641, -641, -641, -641, -641,
-     -641, -641, -641, -641, -641, -641, -641, -641, -641, -641,
-     -641, -641, -641, -641, -641, -641, -641, -641
-    },
-
-    {
-       67, -642, -642, -642, -642, -642, -642, -642, -642, -642,
-     -642, -642, -642, -642, -642, -642, -642, -642, -642, -642,
-     -642, -642, -642, -642, -642, -642, -642, -642, -642, -642,
-     -642, -642,  729, -642, -642, -642, -642, -642, -642, -642,
-
-     -642, -642, -642, -642, -642, -642, -642, -642, -642, -642,
-     -642, -642, -642, -642, -642, -642, -642, -642, -642, -642,
-     -642, -642, -642, -642, -642, -642, -642, -642, -642, -642,
-     -642, -642, -642, -642, -642, -642, -642, -642, -642, -642,
-     -642, -642, -642, -642, -642, -642, -642, -642, -642, -642,
-     -642, -642, -642, -642, -642, -642, -642, -642, -642, -642,
-     -642, -642, -642, -642, -642, -642, -642, -642, -642, -642,
-     -642, -642, -642, -642, -642, -642, -642, -642, -642, -642,
-     -642, -642, -642, -642, -642, -642, -642, -642
-    },
-
-    {
-       67, -643, -643, -643, -643, -643, -643, -643, -643, -643,
-
-     -643, -643, -643, -643, -643, -643, -643, -643, -643, -643,
-     -643, -643, -643, -643, -643, -643, -643, -643, -643, -643,
-     -643, -643, -643, -643, -643, -643, -643, -643, -643, -643,
-     -643, -643, -643, -643, -643, -643, -643, -643, -643, -643,
-     -643, -643, -643, -643, -643, -643, -643, -643, -643, -643,
-     -643, -643, -643, -643, -643, -643, -643, -643, -643, -643,
-     -643, -643, -643, -643, -643, -643, -643, -643, -643, -643,
-     -643, -643, -643, -643, -643, -643, -643, -643,  730, -643,
-     -643, -643, -643, -643, -643, -643, -643, -643, -643, -643,
-     -643, -643, -643, -643, -643, -643, -643, -643, -643, -643,
-
-     -643, -643, -643, -643, -643, -643, -643, -643, -643, -643,
-     -643, -643, -643, -643, -643, -643, -643, -643
-    },
-
-    {
-       67, -644, -644, -644, -644, -644, -644, -644, -644, -644,
-     -644, -644, -644, -644, -644, -644, -644, -644, -644, -644,
-     -644, -644, -644, -644, -644, -644, -644, -644, -644, -644,
-     -644, -644, -644, -644, -644, -644, -644, -644, -644, -644,
-     -644, -644, -644, -644, -644, -644, -644, -644, -644, -644,
-     -644, -644, -644, -644, -644, -644, -644, -644, -644, -644,
-     -644, -644, -644, -644, -644, -644, -644, -644, -644,  731,
-     -644, -644, -644, -644, -644, -644, -644, -644, -644, -644,
-
-     -644, -644, -644, -644, -644, -644, -644, -644, -644, -644,
-     -644, -644, -644, -644, -644, -644, -644, -644, -644, -644,
-     -644, -644, -644, -644, -644, -644, -644, -644, -644, -644,
-     -644, -644, -644, -644, -644, -644, -644, -644, -644, -644,
-     -644, -644, -644, -644, -644, -644, -644, -644
-    },
-
-    {
-       67, -645, -645, -645, -645, -645, -645, -645, -645, -645,
-     -645, -645, -645, -645, -645, -645, -645, -645, -645, -645,
-     -645, -645, -645, -645, -645, -645, -645, -645, -645, -645,
-     -645, -645, -645, -645, -645, -645, -645, -645, -645, -645,
-     -645, -645, -645, -645, -645, -645, -645, -645, -645, -645,
-
-     -645, -645, -645, -645, -645, -645, -645, -645, -645, -645,
-     -645, -645, -645, -645, -645, -645, -645, -645, -645,  732,
-     -645, -645, -645, -645, -645, -645, -645, -645, -645, -645,
-     -645, -645, -645, -645, -645, -645, -645, -645, -645, -645,
-     -645, -645, -645, -645, -645, -645, -645, -645, -645, -645,
-     -645, -645, -645, -645, -645, -645, -645, -645, -645, -645,
-     -645, -645, -645, -645, -645, -645, -645, -645, -645, -645,
-     -645, -645, -645, -645, -645, -645, -645, -645
-    },
-
-    {
-       67, -646, -646, -646, -646, -646, -646, -646, -646, -646,
-     -646, -646, -646, -646, -646, -646, -646, -646, -646, -646,
-
-     -646, -646, -646, -646, -646, -646, -646, -646, -646, -646,
-     -646, -646, -646, -646, -646, -646, -646, -646, -646, -646,
-     -646, -646, -646, -646, -646, -646, -646, -646, -646, -646,
-     -646, -646, -646, -646, -646, -646, -646, -646, -646, -646,
-     -646, -646, -646, -646, -646, -646, -646, -646, -646, -646,
-     -646,  733, -646, -646, -646, -646, -646, -646, -646, -646,
-     -646, -646, -646, -646, -646, -646, -646, -646, -646, -646,
-     -646, -646, -646, -646, -646, -646, -646, -646, -646, -646,
-     -646, -646, -646, -646, -646, -646, -646, -646, -646, -646,
-     -646, -646, -646, -646, -646, -646, -646, -646, -646, -646,
-
-     -646, -646, -646, -646, -646, -646, -646, -646
-    },
-
-    {
-       67, -647, -647, -647, -647, -647, -647, -647, -647, -647,
-     -647, -647, -647, -647, -647, -647, -647, -647, -647, -647,
-     -647, -647, -647, -647, -647, -647, -647, -647, -647, -647,
-     -647, -647, -647, -647, -647, -647, -647, -647, -647, -647,
-     -647, -647, -647, -647, -647, -647, -647, -647, -647, -647,
-     -647, -647, -647, -647, -647, -647, -647, -647, -647, -647,
-     -647, -647, -647, -647, -647, -647, -647, -647, -647, -647,
-     -647, -647, -647, -647, -647, -647, -647, -647, -647, -647,
-     -647, -647, -647,  734, -647, -647, -647, -647, -647, -647,
-
-     -647, -647, -647, -647, -647, -647, -647, -647, -647, -647,
-     -647, -647, -647, -647, -647, -647, -647, -647, -647, -647,
-     -647, -647, -647, -647, -647, -647, -647, -647, -647, -647,
-     -647, -647, -647, -647, -647, -647, -647, -647
-    },
-
-    {
-       67, -648, -648, -648, -648, -648, -648, -648, -648, -648,
-     -648, -648, -648, -648, -648, -648, -648, -648, -648, -648,
-     -648, -648, -648, -648, -648, -648, -648, -648, -648, -648,
-     -648, -648, -648, -648, -648, -648, -648, -648, -648, -648,
-     -648, -648, -648, -648, -648,  735, -648, -648, -648, -648,
-     -648, -648, -648, -648, -648, -648, -648, -648, -648, -648,
-
-     -648, -648, -648, -648, -648, -648, -648, -648, -648, -648,
-     -648, -648, -648, -648, -648, -648, -648, -648, -648, -648,
-     -648, -648, -648, -648, -648, -648, -648, -648, -648, -648,
-     -648, -648, -648, -648, -648, -648, -648, -648, -648, -648,
-     -648, -648, -648, -648, -648, -648, -648, -648, -648, -648,
-     -648, -648, -648, -648, -648, -648, -648, -648, -648, -648,
-     -648, -648, -648, -648, -648, -648, -648, -648
-    },
-
-    {
-       67, -649, -649, -649, -649, -649, -649, -649, -649, -649,
-     -649, -649, -649, -649, -649, -649, -649, -649, -649, -649,
-     -649, -649, -649, -649, -649, -649, -649, -649, -649, -649,
-
-     -649, -649, -649, -649, -649, -649, -649, -649, -649, -649,
-     -649, -649, -649, -649, -649, -649, -649, -649, -649, -649,
-     -649, -649, -649, -649, -649, -649, -649, -649, -649, -649,
-     -649, -649, -649, -649, -649, -649, -649, -649, -649, -649,
-     -649, -649, -649, -649, -649, -649, -649, -649, -649, -649,
-     -649, -649, -649, -649, -649, -649, -649, -649, -649,  736,
-     -649, -649, -649, -649, -649, -649, -649, -649, -649, -649,
-     -649, -649, -649, -649, -649, -649, -649, -649, -649, -649,
-     -649, -649, -649, -649, -649, -649, -649, -649, -649, -649,
-     -649, -649, -649, -649, -649, -649, -649, -649
-
-    },
-
-    {
-       67, -650, -650, -650, -650, -650, -650, -650, -650, -650,
-     -650, -650, -650, -650, -650, -650, -650, -650, -650, -650,
-     -650, -650, -650, -650, -650, -650, -650, -650, -650, -650,
-     -650, -650, -650, -650, -650, -650, -650, -650, -650, -650,
-     -650, -650, -650, -650, -650, -650, -650, -650, -650, -650,
-     -650, -650, -650, -650, -650, -650, -650, -650, -650, -650,
-     -650, -650, -650, -650, -650, -650, -650, -650, -650, -650,
-     -650, -650, -650, -650, -650, -650, -650, -650, -650, -650,
-     -650, -650, -650,  737, -650, -650, -650, -650, -650, -650,
-     -650, -650, -650, -650, -650, -650, -650, -650, -650, -650,
-
-     -650, -650, -650, -650, -650, -650, -650, -650, -650, -650,
-     -650, -650, -650, -650, -650, -650, -650, -650, -650, -650,
-     -650, -650, -650, -650, -650, -650, -650, -650
-    },
-
-    {
-       67, -651, -651, -651, -651, -651, -651, -651, -651, -651,
-     -651, -651, -651, -651, -651, -651, -651, -651, -651, -651,
-     -651, -651, -651, -651, -651, -651, -651, -651, -651, -651,
-     -651, -651, -651, -651, -651, -651, -651, -651, -651, -651,
-     -651, -651, -651, -651, -651, -651, -651, -651, -651, -651,
-     -651, -651, -651, -651, -651, -651, -651, -651, -651, -651,
-     -651, -651, -651, -651, -651, -651, -651, -651, -651,  738,
-
-     -651, -651, -651, -651, -651, -651, -651, -651, -651, -651,
-     -651,  739, -651, -651, -651, -651, -651, -651, -651, -651,
-     -651, -651, -651, -651, -651, -651, -651, -651, -651, -651,
-     -651, -651, -651, -651, -651, -651, -651, -651, -651, -651,
-     -651, -651, -651, -651, -651, -651, -651, -651, -651, -651,
-     -651, -651, -651, -651, -651, -651, -651, -651
-    },
-
-    {
-       67, -652, -652, -652, -652, -652, -652, -652, -652, -652,
-     -652, -652, -652, -652, -652, -652, -652, -652, -652, -652,
-     -652, -652, -652, -652, -652, -652, -652, -652, -652, -652,
-     -652, -652, -652, -652, -652, -652, -652, -652, -652, -652,
-
-     -652, -652, -652, -652, -652, -652, -652, -652, -652, -652,
-     -652, -652, -652, -652, -652, -652, -652, -652, -652, -652,
-     -652, -652, -652, -652, -652, -652, -652, -652, -652, -652,
-     -652, -652, -652, -652, -652, -652, -652, -652, -652, -652,
-     -652, -652, -652, -652, -652, -652,  740, -652, -652, -652,
-     -652, -652, -652, -652, -652, -652, -652, -652, -652, -652,
-     -652, -652, -652, -652, -652, -652, -652, -652, -652, -652,
-     -652, -652, -652, -652, -652, -652, -652, -652, -652, -652,
-     -652, -652, -652, -652, -652, -652, -652, -652
-    },
-
-    {
-       67, -653, -653, -653, -653, -653, -653, -653, -653, -653,
-
-     -653, -653, -653, -653, -653, -653, -653, -653, -653, -653,
-     -653, -653, -653, -653, -653, -653, -653, -653, -653, -653,
-     -653, -653, -653, -653, -653, -653, -653, -653, -653, -653,
-     -653, -653, -653, -653, -653, -653, -653, -653, -653, -653,
-     -653, -653, -653, -653, -653, -653, -653, -653, -653, -653,
-     -653, -653, -653, -653, -653, -653, -653, -653, -653, -653,
-     -653, -653, -653, -653, -653, -653, -653, -653, -653, -653,
-     -653, -653, -653,  741, -653, -653, -653, -653, -653, -653,
-     -653, -653, -653, -653, -653, -653, -653, -653, -653, -653,
-     -653, -653, -653, -653, -653, -653, -653, -653, -653, -653,
-
-     -653, -653, -653, -653, -653, -653, -653, -653, -653, -653,
-     -653, -653, -653, -653, -653, -653, -653, -653
-    },
-
-    {
-       67, -654, -654, -654, -654, -654, -654, -654, -654, -654,
-     -654, -654, -654, -654, -654, -654, -654, -654, -654, -654,
-     -654, -654, -654, -654, -654, -654, -654, -654, -654, -654,
-     -654, -654, -654, -654, -654, -654, -654, -654, -654, -654,
-     -654, -654, -654, -654, -654, -654, -654, -654, -654, -654,
-     -654, -654, -654, -654, -654, -654, -654, -654, -654, -654,
-     -654, -654, -654, -654, -654, -654, -654, -654, -654, -654,
-     -654, -654, -654, -654, -654, -654, -654, -654, -654, -654,
-
-     -654, -654, -654,  742, -654, -654, -654, -654, -654, -654,
-     -654, -654, -654, -654, -654, -654, -654, -654, -654, -654,
-     -654, -654, -654, -654, -654, -654, -654, -654, -654, -654,
-     -654, -654, -654, -654, -654, -654, -654, -654, -654, -654,
-     -654, -654, -654, -654, -654, -654, -654, -654
-    },
-
-    {
-       67, -655, -655, -655, -655, -655, -655, -655, -655, -655,
-     -655, -655, -655, -655, -655, -655, -655, -655, -655, -655,
-     -655, -655, -655, -655, -655, -655, -655, -655, -655, -655,
-     -655, -655, -655, -655, -655, -655, -655, -655, -655, -655,
-     -655, -655, -655, -655, -655, -655, -655, -655, -655, -655,
-
-     -655, -655, -655, -655, -655, -655, -655, -655, -655, -655,
-     -655, -655, -655, -655, -655, -655, -655,  743, -655, -655,
-     -655, -655, -655, -655, -655, -655, -655, -655, -655, -655,
-     -655, -655, -655, -655, -655, -655, -655, -655, -655, -655,
-     -655, -655, -655, -655, -655, -655, -655, -655, -655, -655,
-     -655, -655, -655, -655, -655, -655, -655, -655, -655, -655,
-     -655, -655, -655, -655, -655, -655, -655, -655, -655, -655,
-     -655, -655, -655, -655, -655, -655, -655, -655
-    },
-
-    {
-       67, -656, -656, -656, -656, -656, -656, -656, -656, -656,
-     -656, -656, -656, -656, -656, -656, -656, -656, -656, -656,
-
-     -656, -656, -656, -656, -656, -656, -656, -656, -656, -656,
-     -656, -656, -656, -656, -656, -656, -656, -656, -656, -656,
-     -656, -656, -656, -656, -656, -656, -656, -656, -656, -656,
-     -656, -656, -656, -656, -656, -656, -656, -656, -656, -656,
-     -656, -656, -656, -656, -656, -656, -656, -656, -656, -656,
-     -656, -656, -656, -656, -656, -656, -656, -656, -656, -656,
-     -656, -656, -656,  744, -656, -656, -656, -656, -656, -656,
-     -656, -656, -656, -656, -656, -656, -656, -656, -656, -656,
-     -656, -656, -656, -656, -656, -656, -656, -656, -656, -656,
-     -656, -656, -656, -656, -656, -656, -656, -656, -656, -656,
-
-     -656, -656, -656, -656, -656, -656, -656, -656
-    },
-
-    {
-       67, -657, -657, -657, -657, -657, -657, -657, -657, -657,
-     -657, -657, -657, -657, -657, -657, -657, -657, -657, -657,
-     -657, -657, -657, -657, -657, -657, -657, -657, -657, -657,
-     -657, -657, -657, -657, -657, -657, -657, -657, -657, -657,
-     -657, -657, -657, -657, -657, -657, -657, -657, -657, -657,
-     -657, -657, -657, -657, -657, -657, -657, -657, -657, -657,
-     -657, -657, -657, -657, -657, -657, -657, -657, -657, -657,
-     -657, -657, -657, -657, -657, -657,  745, -657, -657, -657,
-     -657, -657, -657, -657, -657, -657, -657, -657, -657, -657,
-
-     -657, -657, -657, -657, -657, -657, -657, -657, -657, -657,
-     -657, -657, -657, -657, -657, -657, -657, -657, -657, -657,
-     -657, -657, -657, -657, -657, -657, -657, -657, -657, -657,
-     -657, -657, -657, -657, -657, -657, -657, -657
-    },
-
-    {
-       67, -658, -658, -658, -658, -658, -658, -658, -658, -658,
-     -658, -658, -658, -658, -658, -658, -658, -658, -658, -658,
-     -658, -658, -658, -658, -658, -658, -658, -658, -658, -658,
-     -658, -658, -658, -658, -658, -658, -658, -658, -658, -658,
-     -658, -658, -658, -658, -658, -658, -658, -658, -658, -658,
-     -658, -658, -658, -658, -658, -658, -658, -658, -658, -658,
-
-     -658, -658, -658, -658, -658, -658, -658, -658, -658, -658,
-     -658, -658, -658, -658, -658, -658, -658, -658, -658, -658,
-     -658, -658, -658,  746, -658, -658, -658, -658, -658, -658,
-     -658, -658, -658, -658, -658, -658, -658, -658, -658, -658,
-     -658, -658, -658, -658, -658, -658, -658, -658, -658, -658,
-     -658, -658, -658, -658, -658, -658, -658, -658, -658, -658,
-     -658, -658, -658, -658, -658, -658, -658, -658
-    },
-
-    {
-       67, -659, -659, -659, -659, -659, -659, -659, -659, -659,
-     -659, -659, -659, -659, -659, -659, -659, -659, -659, -659,
-     -659, -659, -659, -659, -659, -659, -659, -659, -659, -659,
-
-     -659, -659,  747, -659, -659, -659, -659, -659, -659, -659,
-     -659, -659, -659, -659, -659, -659, -659, -659, -659, -659,
-     -659, -659, -659, -659, -659, -659, -659, -659, -659, -659,
-     -659, -659, -659, -659, -659,  747,  747,  747,  747,  747,
-      747,  747,  747,  747,  747,  747,  747,  747,  747,  747,
-      747,  747,  747,  747,  747,  747,  747,  747,  747,  747,
-      747, -659, -659, -659, -659, -659, -659, -659, -659, -659,
-     -659, -659, -659, -659, -659, -659, -659, -659, -659, -659,
-     -659, -659, -659, -659, -659, -659, -659, -659, -659, -659,
-     -659, -659, -659, -659, -659, -659, -659, -659
-
-    },
-
-    {
-       67, -660, -660, -660, -660, -660, -660, -660, -660, -660,
-     -660, -660, -660, -660, -660, -660, -660, -660, -660, -660,
-     -660, -660, -660, -660, -660, -660, -660, -660, -660, -660,
-     -660, -660,  748, -660, -660, -660, -660, -660, -660, -660,
-     -660, -660, -660, -660, -660, -660, -660, -660, -660, -660,
-     -660, -660, -660, -660, -660, -660, -660, -660, -660, -660,
-     -660, -660, -660, -660, -660, -660, -660, -660, -660, -660,
-     -660, -660, -660, -660, -660, -660, -660, -660, -660, -660,
-     -660, -660, -660, -660, -660, -660, -660, -660, -660, -660,
-     -660, -660, -660, -660, -660, -660, -660, -660, -660, -660,
-
-     -660, -660, -660, -660, -660, -660, -660, -660, -660, -660,
-     -660, -660, -660, -660, -660, -660, -660, -660, -660, -660,
-     -660, -660, -660, -660, -660, -660, -660, -660
-    },
-
-    {
-       67, -661, -661, -661, -661, -661, -661, -661, -661, -661,
-     -661, -661, -661, -661, -661, -661, -661, -661, -661, -661,
-     -661, -661, -661, -661, -661, -661, -661, -661, -661, -661,
-     -661, -661,  749, -661, -661, -661, -661, -661, -661, -661,
-     -661, -661, -661, -661, -661, -661, -661, -661,  750,  750,
-      750,  750,  750,  750,  750,  750,  750,  750, -661, -661,
-     -661, -661, -661, -661, -661,  749,  749,  749,  749,  749,
-
-      749,  749,  749,  749,  749,  749,  749,  749,  749,  749,
-      749,  749,  749,  749,  749,  749,  749,  749,  749,  749,
-      749, -661, -661, -661, -661, -661, -661, -661, -661, -661,
-     -661, -661, -661, -661, -661, -661, -661, -661, -661, -661,
-     -661, -661, -661, -661, -661, -661, -661, -661, -661, -661,
-     -661, -661, -661, -661, -661, -661, -661, -661
-    },
-
-    {
-       67, -662, -662, -662, -662, -662, -662, -662, -662, -662,
-     -662, -662, -662, -662, -662, -662, -662, -662, -662, -662,
-     -662, -662, -662, -662, -662, -662, -662, -662, -662, -662,
-     -662, -662, -662, -662, -662, -662, -662, -662, -662, -662,
-
-     -662, -662, -662, -662, -662, -662, -662, -662, -662, -662,
-     -662, -662, -662, -662, -662, -662, -662, -662, -662, -662,
-     -662, -662, -662, -662, -662, -662, -662, -662, -662,  751,
-     -662, -662, -662, -662, -662, -662, -662, -662, -662, -662,
-     -662, -662, -662, -662, -662, -662, -662, -662, -662, -662,
-     -662, -662, -662, -662, -662, -662, -662, -662, -662, -662,
-     -662, -662, -662, -662, -662, -662, -662, -662, -662, -662,
-     -662, -662, -662, -662, -662, -662, -662, -662, -662, -662,
-     -662, -662, -662, -662, -662, -662, -662, -662
-    },
-
-    {
-       67, -663, -663, -663, -663, -663, -663, -663, -663, -663,
-
-     -663, -663, -663, -663, -663, -663, -663, -663, -663, -663,
-     -663, -663, -663, -663, -663, -663, -663, -663, -663, -663,
-     -663, -663,  752, -663, -663, -663, -663, -663, -663, -663,
-     -663, -663, -663, -663, -663, -663, -663, -663, -663, -663,
-     -663, -663, -663, -663, -663, -663, -663, -663, -663, -663,
-     -663, -663, -663, -663, -663, -663, -663, -663, -663, -663,
-     -663, -663, -663, -663, -663, -663, -663, -663, -663, -663,
-     -663, -663, -663, -663, -663, -663, -663, -663, -663, -663,
-     -663, -663, -663, -663, -663, -663, -663, -663, -663, -663,
-     -663, -663, -663, -663, -663, -663, -663, -663, -663, -663,
-
-     -663, -663, -663, -663, -663, -663, -663, -663, -663, -663,
-     -663, -663, -663, -663, -663, -663, -663, -663
-    },
-
-    {
-       67, -664, -664, -664, -664, -664, -664, -664, -664, -664,
-     -664, -664, -664, -664, -664, -664, -664, -664, -664, -664,
-     -664, -664, -664, -664, -664, -664, -664, -664, -664, -664,
-     -664, -664,  753, -664, -664, -664, -664, -664, -664, -664,
-     -664, -664, -664, -664, -664, -664, -664, -664,  754,  754,
-      754,  754,  754,  754,  754,  754,  754,  754, -664, -664,
-     -664, -664, -664, -664, -664,  753,  753,  753,  753,  753,
-      753,  753,  753,  753,  753,  753,  753,  753,  753,  753,
-
-      753,  753,  753,  753,  753,  753,  753,  753,  753,  753,
-      753, -664, -664, -664, -664, -664, -664, -664, -664, -664,
-     -664, -664, -664, -664, -664, -664, -664, -664, -664, -664,
-     -664, -664, -664, -664, -664, -664, -664, -664, -664, -664,
-     -664, -664, -664, -664, -664, -664, -664, -664
-    },
-
-    {
-       67, -665, -665, -665, -665, -665, -665, -665, -665, -665,
-     -665, -665, -665, -665, -665, -665, -665, -665, -665, -665,
-     -665, -665, -665, -665, -665, -665, -665, -665, -665, -665,
-     -665, -665, -665, -665, -665, -665, -665, -665, -665, -665,
-     -665, -665, -665, -665, -665, -665, -665, -665, -665, -665,
-
-     -665, -665, -665, -665, -665, -665, -665, -665, -665, -665,
-     -665, -665, -665, -665, -665, -665, -665, -665, -665, -665,
-     -665, -665, -665, -665, -665, -665, -665, -665, -665, -665,
-     -665, -665, -665,  755, -665, -665, -665, -665, -665, -665,
-     -665, -665, -665, -665, -665, -665, -665, -665, -665, -665,
-     -665, -665, -665, -665, -665, -665, -665, -665, -665, -665,
-     -665, -665, -665, -665, -665, -665, -665, -665, -665, -665,
-     -665, -665, -665, -665, -665, -665, -665, -665
-    },
-
-    {
-       67, -666, -666, -666, -666, -666, -666, -666, -666, -666,
-     -666, -666, -666, -666, -666, -666, -666, -666, -666, -666,
-
-     -666, -666, -666, -666, -666, -666, -666, -666, -666, -666,
-     -666, -666, -666, -666, -666, -666, -666, -666, -666, -666,
-     -666, -666, -666, -666, -666, -666, -666, -666, -666, -666,
-     -666, -666, -666, -666, -666, -666, -666, -666, -666, -666,
-     -666, -666, -666, -666, -666, -666, -666, -666, -666,  756,
-     -666, -666, -666, -666, -666, -666, -666, -666, -666, -666,
-     -666, -666, -666, -666, -666, -666, -666, -666, -666, -666,
-     -666, -666, -666, -666, -666, -666, -666, -666, -666, -666,
-     -666, -666, -666, -666, -666, -666, -666, -666, -666, -666,
-     -666, -666, -666, -666, -666, -666, -666, -666, -666, -666,
-
-     -666, -666, -666, -666, -666, -666, -666, -666
-    },
-
-    {
-       67, -667, -667, -667, -667, -667, -667, -667, -667, -667,
-     -667, -667, -667, -667, -667, -667, -667, -667, -667, -667,
-     -667, -667, -667, -667, -667, -667, -667, -667, -667, -667,
-     -667, -667,  757, -667, -667, -667, -667, -667, -667, -667,
-     -667, -667, -667, -667, -667, -667, -667, -667, -667, -667,
-     -667, -667, -667, -667, -667, -667, -667, -667, -667, -667,
-     -667, -667, -667, -667, -667, -667, -667, -667, -667, -667,
-     -667, -667, -667, -667, -667, -667, -667, -667, -667, -667,
-     -667, -667, -667, -667, -667, -667, -667, -667, -667, -667,
-
-     -667, -667, -667, -667, -667, -667, -667, -667, -667, -667,
-     -667, -667, -667, -667, -667, -667, -667, -667, -667, -667,
-     -667, -667, -667, -667, -667, -667, -667, -667, -667, -667,
-     -667, -667, -667, -667, -667, -667, -667, -667
-    },
-
-    {
-       67, -668, -668, -668, -668, -668, -668, -668, -668, -668,
-     -668, -668, -668, -668, -668, -668, -668, -668, -668, -668,
-     -668, -668, -668, -668, -668, -668, -668, -668, -668, -668,
-     -668, -668,  758, -668, -668, -668, -668, -668, -668, -668,
-     -668, -668, -668, -668, -668, -668, -668, -668,  759,  759,
-      759,  759,  759,  759,  759,  759,  759,  759, -668, -668,
-
-     -668, -668, -668, -668, -668,  758,  758,  758,  758,  758,
-      758,  758,  758,  758,  758,  758,  758,  758,  758,  758,
-      758,  758,  758,  758,  758,  758,  758,  758,  758,  758,
-      758, -668, -668, -668, -668, -668, -668, -668, -668, -668,
-     -668, -668, -668, -668, -668, -668, -668, -668, -668, -668,
-     -668, -668, -668, -668, -668, -668, -668, -668, -668, -668,
-     -668, -668, -668, -668, -668, -668, -668, -668
-    },
-
-    {
-       67, -669, -669, -669, -669, -669, -669, -669, -669, -669,
-     -669, -669, -669, -669, -669, -669, -669, -669, -669, -669,
-     -669, -669, -669, -669, -669, -669, -669, -669, -669, -669,
-
-     -669, -669,  760, -669, -669, -669, -669, -669, -669, -669,
-     -669, -669, -669, -669, -669, -669, -669, -669, -669, -669,
-     -669, -669, -669, -669, -669, -669, -669, -669, -669, -669,
-     -669, -669, -669, -669, -669, -669, -669, -669, -669, -669,
-     -669, -669, -669, -669, -669, -669, -669, -669, -669, -669,
-     -669, -669, -669, -669, -669, -669, -669, -669, -669, -669,
-     -669, -669, -669, -669, -669, -669, -669, -669, -669, -669,
-     -669, -669, -669, -669, -669, -669, -669, -669, -669, -669,
-     -669, -669, -669, -669, -669, -669, -669, -669, -669, -669,
-     -669, -669, -669, -669, -669, -669, -669, -669
-
-    },
-
-    {
-       67, -670, -670, -670, -670, -670, -670, -670, -670, -670,
-     -670, -670, -670, -670, -670, -670, -670, -670, -670, -670,
-     -670, -670, -670, -670, -670, -670, -670, -670, -670, -670,
-     -670, -670,  761, -670, -670, -670, -670, -670, -670, -670,
-     -670, -670, -670, -670, -670, -670, -670, -670,  762,  762,
-      762,  762,  762,  762,  762,  762,  762,  762, -670, -670,
-     -670, -670, -670, -670, -670,  761,  761,  761,  761,  761,
-      761,  761,  761,  761,  761,  761,  761,  761,  761,  761,
-      761,  761,  761,  761,  761,  761,  761,  761,  761,  761,
-      761, -670, -670, -670, -670, -670, -670, -670, -670, -670,
-
-     -670, -670, -670, -670, -670, -670, -670, -670, -670, -670,
-     -670, -670, -670, -670, -670, -670, -670, -670, -670, -670,
-     -670, -670, -670, -670, -670, -670, -670, -670
-    },
-
-    {
-       67, -671, -671, -671, -671, -671, -671, -671, -671, -671,
-     -671, -671, -671, -671, -671, -671, -671, -671, -671, -671,
-     -671, -671, -671, -671, -671, -671, -671, -671, -671, -671,
-     -671, -671, -671, -671, -671, -671, -671, -671, -671, -671,
-     -671, -671, -671, -671, -671, -671, -671, -671, -671, -671,
-     -671, -671, -671, -671, -671, -671, -671, -671, -671, -671,
-     -671, -671, -671, -671, -671, -671, -671, -671, -671,  763,
-
-     -671, -671, -671, -671, -671, -671, -671, -671, -671, -671,
-     -671, -671, -671, -671, -671, -671, -671, -671, -671, -671,
-     -671, -671, -671, -671, -671, -671, -671, -671, -671, -671,
-     -671, -671, -671, -671, -671, -671, -671, -671, -671, -671,
-     -671, -671, -671, -671, -671, -671, -671, -671, -671, -671,
-     -671, -671, -671, -671, -671, -671, -671, -671
-    },
-
-    {
-       67, -672, -672, -672, -672, -672, -672, -672, -672, -672,
-     -672, -672, -672, -672, -672, -672, -672, -672, -672, -672,
-     -672, -672, -672, -672, -672, -672, -672, -672, -672, -672,
-     -672, -672, -672, -672, -672, -672, -672, -672, -672, -672,
-
-     -672, -672, -672, -672, -672, -672, -672, -672, -672, -672,
-     -672, -672, -672, -672, -672, -672, -672, -672, -672, -672,
-     -672, -672, -672, -672, -672, -672, -672, -672, -672, -672,
-     -672, -672, -672, -672, -672, -672, -672, -672, -672, -672,
-     -672, -672, -672, -672, -672, -672, -672, -672, -672, -672,
-     -672, -672, -672, -672, -672, -672, -672, -672, -672, -672,
-     -672, -672, -672, -672, -672, -672, -672, -672, -672, -672,
-     -672, -672, -672, -672, -672, -672, -672, -672, -672, -672,
-     -672, -672, -672, -672, -672, -672, -672, -672
-    },
-
-    {
-       67, -673, -673, -673, -673, -673, -673, -673, -673, -673,
-
-     -673, -673, -673, -673, -673, -673, -673, -673, -673, -673,
-     -673, -673, -673, -673, -673, -673, -673, -673, -673, -673,
-     -673, -673, -673, -673, -673, -673, -673, -673, -673, -673,
-     -673, -673, -673, -673, -673, -673, -673, -673, -673, -673,
-     -673, -673, -673, -673, -673, -673, -673, -673, -673, -673,
-     -673, -673, -673, -673, -673, -673, -673, -673, -673, -673,
-     -673, -673, -673, -673, -673, -673, -673, -673, -673, -673,
-     -673, -673, -673, -673, -673, -673, -673, -673, -673, -673,
-     -673, -673, -673, -673, -673, -673, -673, -673, -673, -673,
-     -673, -673, -673, -673, -673, -673, -673, -673, -673, -673,
-
-     -673, -673, -673, -673, -673, -673, -673, -673, -673, -673,
-     -673, -673, -673, -673, -673, -673, -673, -673
-    },
-
-    {
-       67, -674, -674, -674, -674, -674, -674, -674, -674, -674,
-     -674, -674, -674, -674, -674, -674, -674, -674, -674, -674,
-     -674, -674, -674, -674, -674, -674, -674, -674, -674, -674,
-     -674, -674, -674, -674, -674, -674, -674, -674, -674, -674,
-     -674, -674, -674, -674, -674, -674, -674, -674, -674, -674,
-     -674, -674, -674, -674, -674, -674, -674, -674, -674, -674,
-     -674, -674, -674, -674, -674, -674, -674, -674, -674, -674,
-     -674, -674, -674, -674, -674, -674, -674, -674, -674, -674,
-
-     -674, -674, -674, -674, -674, -674, -674, -674, -674, -674,
-     -674, -674, -674, -674, -674, -674, -674, -674, -674, -674,
-     -674, -674, -674, -674, -674, -674, -674, -674, -674, -674,
-     -674, -674, -674, -674, -674, -674, -674, -674, -674, -674,
-     -674, -674, -674, -674, -674, -674, -674, -674
-    },
-
-    {
-       67, -675, -675, -675, -675, -675, -675, -675, -675, -675,
-     -675, -675, -675, -675, -675, -675, -675, -675, -675, -675,
-     -675, -675, -675, -675, -675, -675, -675, -675, -675, -675,
-     -675, -675, -675, -675, -675, -675, -675, -675, -675, -675,
-     -675, -675, -675, -675, -675, -675, -675, -675, -675, -675,
-
-     -675, -675, -675, -675, -675, -675, -675, -675, -675, -675,
-     -675, -675, -675, -675, -675, -675, -675, -675, -675, -675,
-     -675, -675, -675, -675, -675, -675, -675, -675, -675, -675,
-     -675, -675, -675, -675, -675, -675, -675, -675, -675, -675,
-     -675, -675, -675, -675, -675, -675, -675, -675, -675, -675,
-     -675, -675, -675, -675, -675, -675, -675, -675, -675, -675,
-     -675, -675, -675, -675, -675, -675, -675, -675, -675, -675,
-     -675, -675, -675, -675, -675, -675, -675, -675
-    },
-
-    {
-       67, -676, -676, -676, -676, -676, -676, -676, -676, -676,
-     -676, -676, -676, -676, -676, -676, -676, -676, -676, -676,
-
-     -676, -676, -676, -676, -676, -676, -676, -676, -676, -676,
-     -676, -676, -676, -676, -676, -676, -676, -676, -676, -676,
-     -676, -676, -676, -676, -676, -676, -676, -676, -676, -676,
-     -676, -676, -676, -676, -676, -676, -676, -676, -676, -676,
-     -676, -676, -676, -676, -676, -676, -676, -676, -676, -676,
-     -676, -676, -676, -676, -676, -676, -676, -676, -676, -676,
-     -676, -676, -676, -676, -676, -676, -676, -676, -676, -676,
-     -676, -676, -676, -676, -676, -676, -676, -676, -676, -676,
-     -676, -676, -676, -676, -676, -676, -676, -676, -676, -676,
-     -676, -676, -676, -676, -676, -676, -676, -676, -676, -676,
-
-     -676, -676, -676, -676, -676, -676, -676, -676
-    },
-
-    {
-       67, -677, -677, -677, -677, -677, -677, -677, -677, -677,
-     -677, -677, -677, -677, -677, -677, -677, -677, -677, -677,
-     -677, -677, -677, -677, -677, -677, -677, -677, -677, -677,
-     -677, -677, -677, -677, -677, -677, -677, -677, -677, -677,
-     -677, -677, -677, -677, -677, -677, -677, -677, -677, -677,
-     -677, -677, -677, -677, -677, -677, -677, -677, -677, -677,
-     -677, -677, -677, -677, -677, -677, -677, -677, -677, -677,
-     -677, -677, -677, -677, -677, -677, -677, -677, -677, -677,
-     -677, -677, -677, -677, -677, -677, -677, -677, -677, -677,
-
-     -677, -677, -677, -677, -677, -677, -677, -677, -677, -677,
-     -677, -677, -677, -677, -677, -677, -677, -677, -677, -677,
-     -677, -677, -677, -677, -677, -677, -677, -677, -677, -677,
-     -677, -677, -677, -677, -677, -677, -677, -677
-    },
-
-    {
-       67, -678, -678, -678, -678, -678, -678, -678, -678, -678,
-     -678, -678, -678, -678, -678, -678, -678, -678, -678, -678,
-     -678, -678, -678, -678, -678, -678, -678, -678, -678, -678,
-     -678, -678, -678, -678, -678, -678, -678, -678, -678, -678,
-     -678, -678, -678, -678, -678, -678, -678, -678, -678, -678,
-     -678, -678, -678, -678, -678, -678, -678, -678, -678, -678,
-
-     -678, -678, -678, -678, -678, -678, -678, -678, -678, -678,
-     -678, -678, -678, -678, -678, -678, -678, -678, -678, -678,
-     -678, -678, -678, -678, -678, -678, -678, -678, -678, -678,
-     -678, -678, -678, -678, -678, -678, -678, -678, -678, -678,
-     -678, -678, -678, -678, -678, -678, -678, -678, -678, -678,
-     -678, -678, -678, -678, -678, -678, -678, -678, -678, -678,
-     -678, -678, -678, -678, -678, -678, -678, -678
-    },
-
-    {
-       67, -679, -679, -679, -679, -679, -679, -679, -679, -679,
-     -679, -679, -679, -679, -679, -679, -679, -679, -679, -679,
-     -679, -679, -679, -679, -679, -679, -679, -679, -679, -679,
-
-     -679, -679, -679, -679, -679, -679, -679, -679, -679, -679,
-     -679, -679, -679, -679, -679, -679, -679, -679, -679, -679,
-     -679, -679, -679, -679, -679, -679, -679, -679, -679, -679,
-     -679, -679, -679, -679, -679, -679, -679, -679, -679, -679,
-     -679, -679, -679, -679, -679, -679, -679, -679, -679, -679,
-     -679, -679, -679, -679, -679, -679, -679, -679, -679, -679,
-     -679, -679, -679, -679, -679, -679, -679, -679, -679, -679,
-     -679, -679, -679, -679, -679, -679, -679, -679, -679, -679,
-     -679, -679, -679, -679, -679, -679, -679, -679, -679, -679,
-     -679, -679, -679, -679, -679, -679, -679, -679
-
-    },
-
-    {
-       67, -680, -680, -680, -680, -680, -680, -680, -680, -680,
-     -680, -680, -680, -680, -680, -680, -680, -680, -680, -680,
-     -680, -680, -680, -680, -680, -680, -680, -680, -680, -680,
-     -680, -680, -680, -680, -680, -680, -680, -680, -680, -680,
-     -680, -680, -680, -680, -680, -680, -680, -680, -680, -680,
-     -680, -680, -680, -680, -680, -680, -680, -680, -680, -680,
-     -680, -680, -680, -680, -680, -680, -680, -680, -680, -680,
-     -680, -680, -680, -680, -680, -680, -680, -680, -680, -680,
-     -680, -680, -680, -680, -680, -680, -680, -680, -680, -680,
-     -680, -680, -680, -680, -680, -680, -680, -680, -680, -680,
-
-     -680, -680, -680, -680, -680, -680, -680, -680, -680, -680,
-     -680, -680, -680, -680, -680, -680, -680, -680, -680, -680,
-     -680, -680, -680, -680, -680, -680, -680, -680
-    },
-
-    {
-       67, -681, -681, -681, -681, -681, -681, -681, -681, -681,
-     -681, -681, -681, -681, -681, -681, -681, -681, -681, -681,
-     -681, -681, -681, -681, -681, -681, -681, -681, -681, -681,
-     -681, -681, -681, -681, -681, -681, -681, -681, -681, -681,
-     -681, -681, -681, -681, -681, -681, -681, -681, -681, -681,
-     -681, -681, -681, -681, -681, -681, -681, -681, -681, -681,
-     -681, -681, -681, -681, -681, -681, -681, -681, -681, -681,
-
-     -681, -681, -681, -681, -681, -681, -681, -681, -681, -681,
-     -681, -681, -681, -681, -681, -681, -681, -681, -681, -681,
-     -681, -681, -681, -681, -681, -681, -681, -681, -681, -681,
-     -681, -681, -681, -681, -681, -681, -681, -681, -681, -681,
-     -681, -681, -681, -681, -681, -681, -681, -681, -681, -681,
-     -681, -681, -681, -681, -681, -681, -681, -681
-    },
-
-    {
-       67, -682, -682, -682, -682, -682, -682, -682, -682, -682,
-     -682, -682, -682, -682, -682, -682, -682, -682, -682, -682,
-     -682, -682, -682, -682, -682, -682, -682, -682, -682, -682,
-     -682, -682, -682, -682, -682, -682, -682, -682, -682, -682,
-
-     -682, -682, -682, -682, -682, -682, -682, -682, -682, -682,
-     -682, -682, -682, -682, -682, -682, -682, -682, -682, -682,
-     -682, -682, -682, -682, -682, -682, -682, -682, -682, -682,
-     -682, -682, -682, -682, -682, -682, -682, -682, -682, -682,
-     -682, -682, -682, -682, -682, -682, -682, -682, -682, -682,
-     -682, -682, -682, -682, -682, -682, -682, -682, -682, -682,
-     -682, -682, -682, -682, -682, -682, -682, -682, -682, -682,
-     -682, -682, -682, -682, -682, -682, -682, -682, -682, -682,
-     -682, -682, -682, -682, -682, -682, -682, -682
-    },
-
-    {
-       67, -683, -683, -683, -683, -683, -683, -683, -683, -683,
-
-     -683, -683, -683, -683, -683, -683, -683, -683, -683, -683,
-     -683, -683, -683, -683, -683, -683, -683, -683, -683, -683,
-     -683, -683, -683, -683, -683, -683, -683, -683, -683, -683,
-     -683, -683, -683, -683, -683, -683, -683, -683, -683, -683,
-     -683, -683, -683, -683, -683, -683, -683, -683, -683, -683,
-     -683, -683, -683, -683, -683, -683, -683, -683, -683, -683,
-     -683, -683, -683, -683, -683, -683, -683, -683, -683, -683,
-     -683, -683, -683, -683, -683, -683, -683, -683, -683, -683,
-     -683, -683, -683, -683, -683, -683, -683, -683, -683, -683,
-     -683, -683, -683, -683, -683, -683, -683, -683, -683, -683,
-
-     -683, -683, -683, -683, -683, -683, -683, -683, -683, -683,
-     -683, -683, -683, -683, -683, -683, -683, -683
-    },
-
-    {
-       67, -684, -684, -684, -684, -684, -684, -684, -684, -684,
-     -684, -684, -684, -684, -684, -684, -684, -684, -684, -684,
-     -684, -684, -684, -684, -684, -684, -684, -684, -684, -684,
-     -684, -684, -684, -684, -684, -684, -684, -684, -684, -684,
-     -684, -684, -684, -684, -684, -684, -684, -684, -684, -684,
-     -684, -684, -684, -684, -684, -684, -684, -684, -684, -684,
-     -684, -684, -684, -684, -684, -684, -684, -684, -684, -684,
-     -684, -684, -684, -684, -684, -684, -684, -684, -684, -684,
-
-     -684, -684, -684, -684, -684, -684, -684, -684, -684, -684,
-     -684, -684, -684, -684, -684, -684, -684, -684, -684, -684,
-     -684, -684, -684, -684, -684, -684, -684, -684, -684, -684,
-     -684, -684, -684, -684, -684, -684, -684, -684, -684, -684,
-     -684, -684, -684, -684, -684, -684, -684, -684
-    },
-
-    {
-       67, -685, -685, -685, -685, -685, -685, -685, -685, -685,
-     -685, -685, -685, -685, -685, -685, -685, -685, -685, -685,
-     -685, -685, -685, -685, -685, -685, -685, -685, -685, -685,
-     -685, -685, -685, -685, -685, -685, -685, -685, -685, -685,
-     -685, -685, -685, -685, -685, -685, -685, -685, -685, -685,
-
-     -685, -685, -685, -685, -685, -685, -685, -685, -685, -685,
-     -685, -685, -685, -685, -685, -685, -685, -685, -685, -685,
-     -685, -685, -685, -685, -685, -685, -685, -685, -685, -685,
-     -685, -685, -685, -685, -685, -685, -685, -685, -685, -685,
-     -685, -685, -685, -685, -685, -685, -685, -685, -685, -685,
-     -685, -685, -685, -685, -685, -685, -685, -685, -685, -685,
-     -685, -685, -685, -685, -685, -685, -685, -685, -685, -685,
-     -685, -685, -685, -685, -685, -685, -685, -685
-    },
-
-    {
-       67, -686, -686, -686, -686, -686, -686, -686, -686, -686,
-     -686, -686, -686, -686, -686, -686, -686, -686, -686, -686,
-
-     -686, -686, -686, -686, -686, -686, -686, -686, -686, -686,
-     -686, -686, -686, -686, -686, -686, -686, -686, -686, -686,
-     -686, -686, -686, -686, -686, -686, -686, -686, -686, -686,
-     -686, -686, -686, -686, -686, -686, -686, -686, -686, -686,
-     -686, -686, -686, -686, -686, -686, -686, -686, -686, -686,
-     -686, -686, -686, -686, -686, -686, -686, -686, -686, -686,
-     -686, -686, -686, -686, -686, -686, -686, -686, -686, -686,
-     -686, -686, -686, -686, -686, -686, -686, -686, -686, -686,
-     -686, -686, -686, -686, -686, -686, -686, -686, -686, -686,
-     -686, -686, -686, -686, -686, -686, -686, -686, -686, -686,
-
-     -686, -686, -686, -686, -686, -686, -686, -686
-    },
-
-    {
-       67, -687, -687, -687, -687, -687, -687, -687, -687, -687,
-     -687, -687, -687, -687, -687, -687, -687, -687, -687, -687,
-     -687, -687, -687, -687, -687, -687, -687, -687, -687, -687,
-     -687, -687, -687, -687, -687, -687, -687, -687, -687, -687,
-     -687, -687, -687, -687, -687, -687, -687, -687, -687, -687,
-     -687, -687, -687, -687, -687, -687, -687, -687, -687, -687,
-     -687, -687, -687, -687, -687, -687, -687, -687, -687, -687,
-     -687, -687, -687, -687, -687, -687, -687, -687, -687, -687,
-     -687, -687, -687, -687, -687, -687, -687, -687, -687, -687,
-
-     -687, -687, -687, -687, -687, -687, -687, -687, -687, -687,
-     -687, -687, -687, -687, -687, -687, -687, -687, -687, -687,
-     -687, -687, -687, -687, -687, -687, -687, -687, -687, -687,
-     -687, -687, -687, -687, -687, -687, -687, -687
-    },
-
-    {
-       67, -688, -688, -688, -688, -688, -688, -688, -688, -688,
-     -688, -688, -688, -688, -688, -688, -688, -688, -688, -688,
-     -688, -688, -688, -688, -688, -688, -688, -688, -688, -688,
-     -688, -688, -688, -688, -688, -688, -688, -688, -688, -688,
-     -688, -688, -688, -688, -688, -688, -688, -688, -688, -688,
-     -688, -688, -688, -688, -688, -688, -688, -688, -688, -688,
-
-     -688, -688, -688, -688, -688, -688, -688, -688, -688, -688,
-     -688, -688, -688, -688, -688, -688, -688, -688, -688, -688,
-     -688, -688, -688, -688, -688, -688, -688, -688, -688, -688,
-     -688, -688, -688, -688, -688, -688, -688, -688, -688, -688,
-     -688, -688, -688, -688, -688, -688, -688, -688, -688, -688,
-     -688, -688, -688, -688, -688, -688, -688, -688, -688, -688,
-     -688, -688, -688, -688, -688, -688, -688, -688
-    },
-
-    {
-       67, -689, -689, -689, -689, -689, -689, -689, -689, -689,
-     -689, -689, -689, -689, -689, -689, -689, -689, -689, -689,
-     -689, -689, -689, -689, -689, -689, -689, -689, -689, -689,
-
-     -689, -689, -689, -689, -689, -689, -689, -689, -689, -689,
-     -689, -689, -689, -689, -689, -689, -689, -689, -689, -689,
-     -689, -689, -689, -689, -689, -689, -689, -689, -689, -689,
-     -689, -689, -689, -689, -689, -689, -689, -689, -689, -689,
-     -689, -689, -689, -689, -689, -689, -689, -689, -689, -689,
-     -689, -689, -689, -689, -689, -689, -689, -689, -689, -689,
-     -689, -689, -689, -689, -689, -689, -689, -689, -689, -689,
-     -689, -689, -689, -689, -689, -689, -689, -689, -689, -689,
-     -689, -689, -689, -689, -689, -689, -689, -689, -689, -689,
-     -689, -689, -689, -689, -689, -689, -689, -689
-
-    },
-
-    {
-       67, -690, -690, -690, -690, -690, -690, -690, -690, -690,
-     -690, -690, -690, -690, -690, -690, -690, -690, -690, -690,
-     -690, -690, -690, -690, -690, -690, -690, -690, -690, -690,
-     -690, -690, -690, -690, -690, -690, -690, -690, -690, -690,
-     -690, -690, -690, -690, -690, -690, -690, -690, -690, -690,
-     -690, -690, -690, -690, -690, -690, -690, -690, -690, -690,
-     -690, -690, -690, -690, -690, -690, -690, -690, -690, -690,
-     -690, -690, -690, -690, -690, -690, -690, -690, -690, -690,
-     -690, -690, -690, -690, -690, -690, -690, -690, -690, -690,
-     -690, -690, -690, -690, -690, -690, -690, -690, -690, -690,
-
-     -690, -690, -690, -690, -690, -690, -690, -690, -690, -690,
-     -690, -690, -690, -690, -690, -690, -690, -690, -690, -690,
-     -690, -690, -690, -690, -690, -690, -690, -690
-    },
-
-    {
-       67, -691, -691, -691, -691, -691, -691, -691, -691, -691,
-     -691, -691, -691, -691, -691, -691, -691, -691, -691, -691,
-     -691, -691, -691, -691, -691, -691, -691, -691, -691, -691,
-     -691, -691, -691, -691, -691, -691, -691, -691, -691, -691,
-     -691, -691, -691, -691, -691, -691, -691, -691, -691, -691,
-     -691, -691, -691, -691, -691, -691, -691, -691, -691, -691,
-     -691, -691, -691, -691, -691, -691, -691, -691, -691, -691,
-
-     -691, -691, -691, -691, -691, -691, -691, -691, -691, -691,
-     -691, -691, -691, -691, -691, -691, -691, -691, -691, -691,
-     -691, -691, -691, -691, -691, -691, -691, -691, -691, -691,
-     -691, -691, -691, -691, -691, -691, -691, -691, -691, -691,
-     -691, -691, -691, -691, -691, -691, -691, -691, -691, -691,
-     -691, -691, -691, -691, -691, -691, -691, -691
-    },
-
-    {
-       67, -692, -692, -692, -692, -692, -692, -692, -692, -692,
-     -692, -692, -692, -692, -692, -692, -692, -692, -692, -692,
-     -692, -692, -692, -692, -692, -692, -692, -692, -692, -692,
-     -692, -692, -692, -692, -692, -692, -692, -692, -692, -692,
-
-     -692, -692, -692, -692, -692, -692, -692, -692, -692, -692,
-     -692, -692, -692, -692, -692, -692, -692, -692, -692, -692,
-     -692, -692, -692, -692, -692, -692, -692, -692, -692, -692,
-     -692, -692, -692, -692, -692, -692, -692, -692, -692, -692,
-     -692, -692, -692, -692, -692, -692, -692, -692, -692, -692,
-     -692, -692, -692, -692, -692, -692, -692, -692, -692, -692,
-     -692, -692, -692, -692, -692, -692, -692, -692, -692, -692,
-     -692, -692, -692, -692, -692, -692, -692, -692, -692, -692,
-     -692, -692, -692, -692, -692, -692, -692, -692
-    },
-
-    {
-       67, -693, -693, -693, -693, -693, -693, -693, -693, -693,
-
-     -693, -693, -693, -693, -693, -693, -693, -693, -693, -693,
-     -693, -693, -693, -693, -693, -693, -693, -693, -693, -693,
-     -693, -693, -693, -693, -693, -693, -693, -693, -693, -693,
-     -693, -693, -693, -693, -693, -693, -693, -693, -693, -693,
-     -693, -693, -693, -693, -693, -693, -693, -693, -693, -693,
-     -693, -693, -693, -693, -693, -693, -693, -693, -693, -693,
-     -693, -693, -693, -693, -693, -693, -693, -693, -693, -693,
-     -693, -693, -693, -693, -693, -693, -693, -693, -693, -693,
-     -693, -693, -693, -693, -693, -693, -693, -693, -693, -693,
-     -693, -693, -693, -693, -693, -693, -693, -693, -693, -693,
-
-     -693, -693, -693, -693, -693, -693, -693, -693, -693, -693,
-     -693, -693, -693, -693, -693, -693, -693, -693
-    },
-
-    {
-       67, -694, -694, -694, -694, -694, -694, -694, -694, -694,
-     -694, -694, -694, -694, -694, -694, -694, -694, -694, -694,
-     -694, -694, -694, -694, -694, -694, -694, -694, -694, -694,
-     -694, -694, -694, -694, -694, -694, -694, -694, -694, -694,
-     -694, -694, -694, -694, -694, -694, -694, -694, -694, -694,
-     -694, -694, -694, -694, -694, -694, -694, -694, -694, -694,
-     -694, -694, -694, -694, -694, -694, -694, -694, -694, -694,
-     -694, -694, -694, -694, -694, -694, -694, -694, -694, -694,
-
-     -694, -694, -694, -694, -694, -694, -694, -694, -694, -694,
-     -694, -694, -694, -694, -694, -694, -694, -694, -694, -694,
-     -694, -694, -694, -694, -694, -694, -694, -694, -694, -694,
-     -694, -694, -694, -694, -694, -694, -694, -694, -694, -694,
-     -694, -694, -694, -694, -694, -694, -694, -694
-    },
-
-    {
-       67, -695, -695, -695, -695, -695, -695, -695, -695, -695,
-     -695, -695, -695, -695, -695, -695, -695, -695, -695, -695,
-     -695, -695, -695, -695, -695, -695, -695, -695, -695, -695,
-     -695, -695, -695, -695, -695, -695, -695, -695, -695, -695,
-     -695, -695, -695, -695, -695, -695, -695, -695, -695, -695,
-
-     -695, -695, -695, -695, -695, -695, -695, -695, -695, -695,
-     -695, -695, -695, -695, -695, -695, -695, -695, -695, -695,
-     -695, -695, -695, -695, -695, -695, -695, -695, -695, -695,
-     -695, -695, -695, -695, -695, -695, -695, -695, -695, -695,
-     -695, -695, -695, -695, -695, -695, -695, -695, -695, -695,
-     -695, -695, -695, -695, -695, -695, -695, -695, -695, -695,
-     -695, -695, -695, -695, -695, -695, -695, -695, -695, -695,
-     -695, -695, -695, -695, -695, -695, -695, -695
-    },
-
-    {
-       67, -696, -696, -696, -696, -696, -696, -696, -696, -696,
-     -696, -696, -696, -696, -696, -696, -696, -696, -696, -696,
-
-     -696, -696, -696, -696, -696, -696, -696, -696, -696, -696,
-     -696, -696, -696, -696, -696, -696, -696, -696, -696, -696,
-     -696, -696, -696, -696, -696, -696, -696, -696, -696, -696,
-     -696, -696, -696, -696, -696, -696, -696, -696, -696, -696,
-     -696, -696, -696, -696, -696, -696, -696, -696, -696, -696,
-     -696, -696, -696, -696, -696, -696, -696, -696, -696, -696,
-     -696, -696, -696, -696, -696, -696, -696, -696, -696, -696,
-     -696, -696, -696, -696, -696, -696, -696, -696, -696, -696,
-     -696, -696, -696, -696, -696, -696, -696, -696, -696, -696,
-     -696, -696, -696, -696, -696, -696, -696, -696, -696, -696,
-
-     -696, -696, -696, -696, -696, -696, -696, -696
-    },
-
-    {
-       67, -697, -697, -697, -697, -697, -697, -697, -697, -697,
-     -697, -697, -697, -697, -697, -697, -697, -697, -697, -697,
-     -697, -697, -697, -697, -697, -697, -697, -697, -697, -697,
-     -697, -697, -697, -697, -697, -697, -697, -697, -697, -697,
-     -697, -697, -697, -697, -697, -697, -697, -697, -697, -697,
-     -697, -697, -697, -697, -697, -697, -697, -697, -697, -697,
-     -697, -697, -697, -697, -697, -697, -697, -697, -697, -697,
-     -697, -697, -697, -697, -697, -697, -697, -697, -697, -697,
-     -697, -697, -697, -697, -697, -697, -697, -697, -697, -697,
-
-     -697, -697, -697, -697, -697, -697, -697, -697, -697, -697,
-     -697, -697, -697, -697, -697, -697, -697, -697, -697, -697,
-     -697, -697, -697, -697, -697, -697, -697, -697, -697, -697,
-     -697, -697, -697, -697, -697, -697, -697, -697
-    },
-
-    {
-       67, -698, -698, -698, -698, -698, -698, -698, -698, -698,
-     -698, -698, -698, -698, -698, -698, -698, -698, -698, -698,
-     -698, -698, -698, -698, -698, -698, -698, -698, -698, -698,
-     -698, -698, -698, -698, -698, -698, -698, -698, -698, -698,
-     -698, -698, -698, -698, -698, -698, -698, -698, -698, -698,
-     -698, -698, -698, -698, -698, -698, -698, -698, -698, -698,
-
-     -698, -698, -698, -698, -698, -698, -698, -698, -698, -698,
-     -698, -698, -698, -698, -698, -698, -698, -698, -698, -698,
-     -698, -698, -698, -698, -698, -698, -698, -698, -698, -698,
-     -698, -698, -698, -698, -698, -698, -698, -698, -698, -698,
-     -698, -698, -698, -698, -698, -698, -698, -698, -698, -698,
-     -698, -698, -698, -698, -698, -698, -698, -698, -698, -698,
-     -698, -698, -698, -698, -698, -698, -698, -698
-    },
-
-    {
-       67, -699, -699, -699, -699, -699, -699, -699, -699, -699,
-     -699, -699, -699, -699, -699, -699, -699, -699, -699, -699,
-     -699, -699, -699, -699, -699, -699, -699, -699, -699, -699,
-
-     -699, -699, -699, -699, -699, -699, -699, -699, -699, -699,
-     -699, -699, -699, -699, -699, -699, -699, -699, -699, -699,
-     -699, -699, -699, -699, -699, -699, -699, -699, -699, -699,
-     -699, -699, -699, -699, -699, -699, -699, -699, -699, -699,
-     -699, -699, -699, -699, -699, -699, -699, -699, -699, -699,
-     -699, -699, -699, -699, -699, -699, -699, -699, -699, -699,
-     -699, -699, -699, -699, -699, -699, -699, -699, -699, -699,
-     -699, -699, -699, -699, -699, -699, -699, -699, -699, -699,
-     -699, -699, -699, -699, -699, -699, -699, -699, -699, -699,
-     -699, -699, -699, -699, -699, -699, -699, -699
-
-    },
-
-    {
-       67, -700, -700, -700, -700, -700, -700, -700, -700, -700,
-     -700, -700, -700, -700, -700, -700, -700, -700, -700, -700,
-     -700, -700, -700, -700, -700, -700, -700, -700, -700, -700,
-     -700, -700, -700, -700, -700, -700, -700, -700, -700, -700,
-     -700, -700, -700, -700, -700, -700, -700, -700, -700, -700,
-     -700, -700, -700, -700, -700, -700, -700, -700, -700, -700,
-     -700, -700, -700, -700, -700, -700, -700, -700, -700, -700,
-     -700, -700, -700, -700, -700, -700, -700, -700, -700, -700,
-     -700, -700, -700, -700, -700, -700, -700, -700, -700, -700,
-     -700, -700, -700, -700, -700, -700, -700, -700, -700, -700,
-
-     -700, -700, -700, -700, -700, -700, -700, -700, -700, -700,
-     -700, -700, -700, -700, -700, -700, -700, -700, -700, -700,
-     -700, -700, -700, -700, -700, -700, -700, -700
-    },
-
-    {
-       67, -701, -701, -701, -701, -701, -701, -701, -701, -701,
-     -701, -701, -701, -701, -701, -701, -701, -701, -701, -701,
-     -701, -701, -701, -701, -701, -701, -701, -701, -701, -701,
-     -701, -701, -701, -701, -701, -701, -701, -701, -701, -701,
-     -701, -701, -701, -701, -701, -701, -701, -701, -701, -701,
-     -701, -701, -701, -701, -701, -701, -701, -701, -701, -701,
-     -701, -701, -701, -701, -701, -701, -701, -701, -701, -701,
-
-     -701, -701, -701, -701, -701, -701, -701, -701, -701, -701,
-     -701, -701, -701, -701, -701, -701, -701, -701, -701, -701,
-     -701, -701, -701, -701, -701, -701, -701, -701, -701, -701,
-     -701, -701, -701, -701, -701, -701, -701, -701, -701, -701,
-     -701, -701, -701, -701, -701, -701, -701, -701, -701, -701,
-     -701, -701, -701, -701, -701, -701, -701, -701
-    },
-
-    {
-       67, -702, -702, -702, -702, -702, -702, -702, -702, -702,
-     -702, -702, -702, -702, -702, -702, -702, -702, -702, -702,
-     -702, -702, -702, -702, -702, -702, -702, -702, -702, -702,
-     -702, -702, -702, -702, -702, -702, -702, -702, -702, -702,
-
-     -702, -702, -702, -702, -702, -702, -702, -702, -702, -702,
-     -702, -702, -702, -702, -702, -702, -702, -702, -702, -702,
-     -702, -702, -702, -702, -702, -702, -702, -702, -702, -702,
-     -702, -702, -702, -702, -702, -702, -702, -702, -702, -702,
-     -702, -702, -702, -702, -702, -702, -702, -702, -702, -702,
-     -702, -702, -702, -702, -702, -702, -702, -702, -702, -702,
-     -702, -702, -702, -702, -702, -702, -702, -702, -702, -702,
-     -702, -702, -702, -702, -702, -702, -702, -702, -702, -702,
-     -702, -702, -702, -702, -702, -702, -702, -702
-    },
-
-    {
-       67, -703, -703, -703, -703, -703, -703, -703, -703, -703,
-
-     -703, -703, -703, -703, -703, -703, -703, -703, -703, -703,
-     -703, -703, -703, -703, -703, -703, -703, -703, -703, -703,
-     -703, -703, -703, -703, -703, -703, -703, -703, -703, -703,
-     -703, -703, -703, -703, -703, -703, -703, -703, -703, -703,
-     -703, -703, -703, -703, -703, -703, -703, -703, -703, -703,
-     -703, -703, -703, -703, -703, -703, -703, -703, -703, -703,
-     -703, -703, -703, -703, -703, -703, -703, -703, -703, -703,
-     -703, -703, -703, -703, -703, -703, -703, -703, -703, -703,
-     -703, -703, -703, -703, -703, -703, -703, -703, -703, -703,
-     -703, -703, -703, -703, -703, -703, -703, -703, -703, -703,
-
-     -703, -703, -703, -703, -703, -703, -703, -703, -703, -703,
-     -703, -703, -703, -703, -703, -703, -703, -703
-    },
-
-    {
-       67, -704, -704, -704, -704, -704, -704, -704, -704, -704,
-     -704, -704, -704, -704, -704, -704, -704, -704, -704, -704,
-     -704, -704, -704, -704, -704, -704, -704, -704, -704, -704,
-     -704, -704, -704, -704, -704, -704, -704, -704, -704, -704,
-     -704, -704, -704, -704, -704, -704, -704, -704, -704, -704,
-     -704, -704, -704, -704, -704, -704, -704, -704, -704, -704,
-     -704, -704, -704, -704, -704, -704, -704, -704, -704, -704,
-     -704, -704, -704, -704, -704, -704, -704, -704, -704, -704,
-
-     -704, -704, -704, -704, -704, -704, -704, -704, -704, -704,
-     -704, -704, -704, -704, -704, -704, -704, -704, -704, -704,
-     -704, -704, -704, -704, -704, -704, -704, -704, -704, -704,
-     -704, -704, -704, -704, -704, -704, -704, -704, -704, -704,
-     -704, -704, -704, -704, -704, -704, -704, -704
-    },
-
-    {
-       67, -705, -705, -705, -705, -705, -705, -705, -705, -705,
-     -705, -705, -705, -705, -705, -705, -705, -705, -705, -705,
-     -705, -705, -705, -705, -705, -705, -705, -705, -705, -705,
-     -705, -705, -705, -705, -705, -705, -705, -705, -705, -705,
-     -705, -705, -705, -705, -705, -705, -705, -705, -705, -705,
-
-     -705, -705, -705, -705, -705, -705, -705, -705, -705, -705,
-     -705, -705, -705, -705, -705, -705, -705, -705, -705, -705,
-     -705, -705, -705, -705, -705, -705, -705, -705, -705, -705,
-     -705, -705, -705, -705, -705, -705, -705, -705, -705, -705,
-     -705, -705, -705, -705, -705, -705, -705, -705, -705, -705,
-     -705, -705, -705, -705, -705, -705, -705, -705, -705, -705,
-     -705, -705, -705, -705, -705, -705, -705, -705, -705, -705,
-     -705, -705, -705, -705, -705, -705, -705, -705
-    },
-
-    {
-       67, -706, -706, -706, -706, -706, -706, -706, -706, -706,
-     -706, -706, -706, -706, -706, -706, -706, -706, -706, -706,
-
-     -706, -706, -706, -706, -706, -706, -706, -706, -706, -706,
-     -706, -706, -706, -706, -706, -706, -706, -706, -706, -706,
-     -706, -706, -706, -706, -706, -706, -706, -706, -706, -706,
-     -706, -706, -706, -706, -706, -706, -706, -706, -706, -706,
-     -706, -706, -706, -706, -706, -706, -706, -706, -706, -706,
-     -706, -706, -706, -706, -706, -706, -706, -706, -706, -706,
-     -706, -706, -706, -706, -706, -706, -706, -706, -706, -706,
-     -706, -706, -706, -706, -706, -706, -706, -706, -706, -706,
-     -706, -706, -706, -706, -706, -706, -706, -706, -706, -706,
-     -706, -706, -706, -706, -706, -706, -706, -706, -706, -706,
-
-     -706, -706, -706, -706, -706, -706, -706, -706
-    },
-
-    {
-       67, -707, -707, -707, -707, -707, -707, -707, -707, -707,
-     -707, -707, -707, -707, -707, -707, -707, -707, -707, -707,
-     -707, -707, -707, -707, -707, -707, -707, -707, -707, -707,
-     -707, -707, -707, -707, -707, -707, -707, -707, -707, -707,
-     -707, -707, -707, -707, -707, -707, -707, -707, -707, -707,
-     -707, -707, -707, -707, -707, -707, -707, -707, -707, -707,
-     -707, -707, -707, -707, -707, -707, -707, -707, -707, -707,
-     -707, -707, -707, -707, -707, -707, -707, -707, -707, -707,
-     -707, -707, -707, -707, -707, -707, -707, -707, -707, -707,
-
-     -707, -707, -707, -707, -707, -707, -707, -707, -707, -707,
-     -707, -707, -707, -707, -707, -707, -707, -707, -707, -707,
-     -707, -707, -707, -707, -707, -707, -707, -707, -707, -707,
-     -707, -707, -707, -707, -707, -707, -707, -707
-    },
-
-    {
-       67, -708, -708, -708, -708, -708, -708, -708, -708, -708,
-     -708, -708, -708, -708, -708, -708, -708, -708, -708, -708,
-     -708, -708, -708, -708, -708, -708, -708, -708, -708, -708,
-     -708, -708, -708, -708, -708, -708, -708, -708, -708, -708,
-     -708, -708, -708, -708, -708, -708, -708, -708, -708, -708,
-     -708, -708, -708, -708, -708, -708, -708, -708, -708, -708,
-
-     -708, -708, -708, -708, -708, -708, -708, -708, -708, -708,
-     -708, -708, -708, -708, -708, -708, -708, -708, -708, -708,
-     -708, -708, -708, -708, -708, -708, -708, -708, -708, -708,
-     -708, -708, -708, -708, -708, -708, -708, -708, -708, -708,
-     -708, -708, -708, -708, -708, -708, -708, -708, -708, -708,
-     -708, -708, -708, -708, -708, -708, -708, -708, -708, -708,
-     -708, -708, -708, -708, -708, -708, -708, -708
-    },
-
-    {
-       67, -709, -709, -709, -709, -709, -709, -709, -709, -709,
-     -709, -709, -709, -709, -709, -709, -709, -709, -709, -709,
-     -709, -709, -709, -709, -709, -709, -709, -709, -709, -709,
-
-     -709, -709, -709, -709, -709, -709, -709, -709, -709, -709,
-     -709, -709, -709, -709, -709, -709, -709, -709, -709, -709,
-     -709, -709, -709, -709, -709, -709, -709, -709, -709, -709,
-     -709, -709, -709, -709, -709, -709, -709, -709, -709, -709,
-     -709, -709, -709, -709, -709, -709, -709, -709, -709, -709,
-     -709, -709, -709, -709, -709, -709, -709, -709, -709, -709,
-     -709, -709, -709, -709, -709, -709, -709, -709, -709, -709,
-     -709, -709, -709, -709, -709, -709, -709, -709, -709, -709,
-     -709, -709, -709, -709, -709, -709, -709, -709, -709, -709,
-     -709, -709, -709, -709, -709, -709, -709, -709
-
-    },
-
-    {
-       67, -710, -710, -710, -710, -710, -710, -710, -710, -710,
-     -710, -710, -710, -710, -710, -710, -710, -710, -710, -710,
-     -710, -710, -710, -710, -710, -710, -710, -710, -710, -710,
-     -710, -710, -710, -710, -710, -710, -710, -710, -710, -710,
-     -710, -710, -710, -710, -710, -710, -710, -710, -710, -710,
-     -710, -710, -710, -710, -710, -710, -710, -710, -710, -710,
-     -710, -710, -710, -710, -710, -710, -710, -710, -710, -710,
-     -710, -710, -710, -710, -710, -710, -710, -710, -710, -710,
-     -710, -710, -710, -710, -710, -710, -710, -710, -710, -710,
-     -710, -710, -710, -710, -710, -710, -710, -710, -710, -710,
-
-     -710, -710, -710, -710, -710, -710, -710, -710, -710, -710,
-     -710, -710, -710, -710, -710, -710, -710, -710, -710, -710,
-     -710, -710, -710, -710, -710, -710, -710, -710
-    },
-
-    {
-       67, -711, -711, -711, -711, -711, -711, -711, -711, -711,
-     -711, -711, -711, -711, -711, -711, -711, -711, -711, -711,
-     -711, -711, -711, -711, -711, -711, -711, -711, -711, -711,
-     -711, -711, -711, -711, -711, -711, -711, -711, -711, -711,
-     -711, -711, -711, -711, -711, -711, -711, -711, -711, -711,
-     -711, -711, -711, -711, -711, -711, -711, -711, -711, -711,
-     -711, -711, -711, -711, -711, -711, -711, -711, -711, -711,
-
-     -711, -711, -711, -711, -711, -711, -711, -711, -711, -711,
-     -711, -711, -711, -711, -711, -711, -711, -711, -711, -711,
-     -711, -711, -711, -711, -711, -711, -711, -711, -711, -711,
-     -711, -711, -711, -711, -711, -711, -711, -711, -711, -711,
-     -711, -711, -711, -711, -711, -711, -711, -711, -711, -711,
-     -711, -711, -711, -711, -711, -711, -711, -711
-    },
-
-    {
-       67, -712, -712, -712, -712, -712, -712, -712, -712, -712,
-     -712, -712, -712, -712, -712, -712, -712, -712, -712, -712,
-     -712, -712, -712, -712, -712, -712, -712, -712, -712, -712,
-     -712, -712, -712, -712, -712, -712, -712, -712, -712, -712,
-
-     -712, -712, -712, -712, -712, -712, -712, -712, -712, -712,
-     -712, -712, -712, -712, -712, -712, -712, -712, -712, -712,
-     -712, -712, -712, -712, -712, -712, -712, -712, -712, -712,
-     -712, -712, -712, -712, -712, -712, -712, -712, -712, -712,
-     -712, -712, -712, -712, -712, -712, -712, -712, -712, -712,
-     -712, -712, -712, -712, -712, -712, -712, -712, -712, -712,
-     -712, -712, -712, -712, -712, -712, -712, -712, -712, -712,
-     -712, -712, -712, -712, -712, -712, -712, -712, -712, -712,
-     -712, -712, -712, -712, -712, -712, -712, -712
-    },
-
-    {
-       67, -713, -713, -713, -713, -713, -713, -713, -713, -713,
-
-     -713, -713, -713, -713, -713, -713, -713, -713, -713, -713,
-     -713, -713, -713, -713, -713, -713, -713, -713, -713, -713,
-     -713, -713, -713, -713, -713, -713, -713, -713, -713, -713,
-     -713, -713, -713, -713, -713, -713, -713, -713, -713, -713,
-     -713, -713, -713, -713, -713, -713, -713, -713, -713, -713,
-     -713, -713, -713, -713, -713, -713, -713, -713, -713, -713,
-     -713, -713, -713, -713, -713, -713, -713, -713, -713, -713,
-     -713, -713, -713, -713, -713, -713, -713, -713, -713, -713,
-     -713, -713, -713, -713, -713, -713, -713, -713, -713, -713,
-     -713, -713, -713, -713, -713, -713, -713, -713, -713, -713,
-
-     -713, -713, -713, -713, -713, -713, -713, -713, -713, -713,
-     -713, -713, -713, -713, -713, -713, -713, -713
-    },
-
-    {
-       67, -714, -714, -714, -714, -714, -714, -714, -714, -714,
-     -714, -714, -714, -714, -714, -714, -714, -714, -714, -714,
-     -714, -714, -714, -714, -714, -714, -714, -714, -714, -714,
-     -714, -714, -714, -714, -714, -714, -714, -714, -714, -714,
-     -714, -714, -714, -714, -714, -714, -714, -714, -714, -714,
-     -714, -714, -714, -714, -714, -714, -714, -714, -714, -714,
-     -714, -714, -714, -714, -714, -714, -714, -714, -714, -714,
-     -714, -714, -714, -714, -714, -714, -714, -714, -714, -714,
-
-     -714, -714, -714, -714, -714, -714, -714, -714, -714, -714,
-     -714, -714, -714, -714, -714, -714, -714, -714, -714, -714,
-     -714, -714, -714, -714, -714, -714, -714, -714, -714, -714,
-     -714, -714, -714, -714, -714, -714, -714, -714, -714, -714,
-     -714, -714, -714, -714, -714, -714, -714, -714
-    },
-
-    {
-       67, -715, -715, -715, -715, -715, -715, -715, -715, -715,
-     -715, -715, -715, -715, -715, -715, -715, -715, -715, -715,
-     -715, -715, -715, -715, -715, -715, -715, -715, -715, -715,
-     -715, -715, -715, -715, -715, -715, -715, -715, -715, -715,
-     -715, -715, -715, -715, -715, -715, -715, -715, -715, -715,
-
-     -715, -715, -715, -715, -715, -715, -715, -715, -715, -715,
-     -715, -715, -715, -715, -715, -715, -715, -715, -715, -715,
-     -715, -715, -715, -715, -715, -715, -715, -715, -715, -715,
-     -715, -715, -715, -715, -715, -715, -715, -715, -715, -715,
-     -715, -715, -715, -715, -715, -715, -715, -715, -715, -715,
-     -715, -715, -715, -715, -715, -715, -715, -715, -715, -715,
-     -715, -715, -715, -715, -715, -715, -715, -715, -715, -715,
-     -715, -715, -715, -715, -715, -715, -715, -715
-    },
-
-    {
-       67, -716, -716, -716, -716, -716, -716, -716, -716, -716,
-     -716, -716, -716, -716, -716, -716, -716, -716, -716, -716,
-
-     -716, -716, -716, -716, -716, -716, -716, -716, -716, -716,
-     -716, -716, -716, -716, -716, -716, -716, -716, -716, -716,
-     -716, -716, -716, -716, -716, -716, -716, -716, -716, -716,
-     -716, -716, -716, -716, -716, -716, -716, -716, -716, -716,
-     -716, -716, -716, -716, -716, -716, -716, -716, -716, -716,
-     -716, -716, -716, -716, -716, -716, -716, -716, -716, -716,
-     -716, -716, -716, -716, -716, -716, -716, -716, -716, -716,
-     -716, -716, -716, -716, -716, -716, -716, -716, -716, -716,
-     -716, -716, -716, -716, -716, -716, -716, -716, -716, -716,
-     -716, -716, -716, -716, -716, -716, -716, -716, -716, -716,
-
-     -716, -716, -716, -716, -716, -716, -716, -716
-    },
-
-    {
-       67, -717, -717, -717, -717, -717, -717, -717, -717, -717,
-     -717, -717, -717, -717, -717, -717, -717, -717, -717, -717,
-     -717, -717, -717, -717, -717, -717, -717, -717, -717, -717,
-     -717, -717, -717, -717, -717, -717, -717, -717, -717, -717,
-     -717, -717, -717, -717, -717, -717, -717, -717, -717, -717,
-     -717, -717, -717, -717, -717, -717, -717, -717, -717, -717,
-     -717, -717, -717, -717, -717, -717, -717, -717, -717, -717,
-     -717, -717, -717, -717, -717, -717, -717, -717, -717, -717,
-     -717, -717, -717, -717, -717, -717, -717, -717, -717, -717,
-
-     -717, -717, -717, -717, -717, -717, -717, -717, -717, -717,
-     -717, -717, -717, -717, -717, -717, -717, -717, -717, -717,
-     -717, -717, -717, -717, -717, -717, -717, -717, -717, -717,
-     -717, -717, -717, -717, -717, -717, -717, -717
-    },
-
-    {
-       67, -718, -718, -718, -718, -718, -718, -718, -718, -718,
-     -718, -718, -718, -718, -718, -718, -718, -718, -718, -718,
-     -718, -718, -718, -718, -718, -718, -718, -718, -718, -718,
-     -718, -718, -718, -718, -718, -718, -718, -718, -718, -718,
-     -718, -718, -718, -718, -718, -718, -718, -718, -718, -718,
-     -718, -718, -718, -718, -718, -718, -718, -718, -718, -718,
-
-     -718, -718, -718, -718, -718, -718, -718, -718, -718, -718,
-     -718, -718, -718, -718, -718, -718, -718, -718, -718, -718,
-     -718, -718, -718, -718, -718, -718, -718, -718, -718, -718,
-     -718, -718, -718, -718, -718, -718, -718, -718, -718, -718,
-     -718, -718, -718, -718, -718, -718, -718, -718, -718, -718,
-     -718, -718, -718, -718, -718, -718, -718, -718, -718, -718,
-     -718, -718, -718, -718, -718, -718, -718, -718
-    },
-
-    {
-       67, -719, -719, -719, -719, -719, -719, -719, -719, -719,
-     -719, -719, -719, -719, -719, -719, -719, -719, -719, -719,
-     -719, -719, -719, -719, -719, -719, -719, -719, -719, -719,
-
-     -719, -719, -719, -719, -719, -719, -719, -719, -719, -719,
-     -719, -719, -719, -719, -719, -719, -719, -719, -719, -719,
-     -719, -719, -719, -719, -719, -719, -719, -719, -719, -719,
-     -719, -719, -719, -719, -719, -719, -719, -719, -719, -719,
-     -719, -719, -719, -719, -719, -719, -719, -719, -719, -719,
-     -719, -719, -719, -719, -719, -719, -719, -719, -719, -719,
-     -719, -719, -719, -719, -719, -719, -719, -719, -719, -719,
-     -719, -719, -719, -719, -719, -719, -719, -719, -719, -719,
-     -719, -719, -719, -719, -719, -719, -719, -719, -719, -719,
-     -719, -719, -719, -719, -719, -719, -719, -719
-
-    },
-
-    {
-       67, -720, -720, -720, -720, -720, -720, -720, -720, -720,
-     -720, -720, -720, -720, -720, -720, -720, -720, -720, -720,
-     -720, -720, -720, -720, -720, -720, -720, -720, -720, -720,
-     -720, -720, -720, -720, -720, -720, -720, -720, -720, -720,
-     -720, -720, -720, -720, -720, -720, -720, -720, -720, -720,
-     -720, -720, -720, -720, -720, -720, -720, -720, -720, -720,
-     -720, -720, -720, -720, -720, -720, -720, -720, -720, -720,
-     -720, -720, -720, -720, -720, -720, -720, -720, -720, -720,
-     -720, -720, -720, -720, -720, -720, -720, -720, -720, -720,
-     -720, -720, -720, -720, -720, -720, -720, -720, -720, -720,
-
-     -720, -720, -720, -720, -720, -720, -720, -720, -720, -720,
-     -720, -720, -720, -720, -720, -720, -720, -720, -720, -720,
-     -720, -720, -720, -720, -720, -720, -720, -720
-    },
-
-    {
-       67, -721, -721, -721, -721, -721, -721, -721, -721, -721,
-     -721, -721, -721, -721, -721, -721, -721, -721, -721, -721,
-     -721, -721, -721, -721, -721, -721, -721, -721, -721, -721,
-     -721, -721, -721, -721, -721, -721, -721, -721, -721, -721,
-     -721, -721, -721, -721, -721, -721, -721, -721, -721, -721,
-     -721, -721, -721, -721, -721, -721, -721, -721, -721, -721,
-     -721, -721, -721, -721, -721, -721, -721, -721, -721, -721,
-
-     -721, -721, -721, -721, -721, -721, -721, -721, -721, -721,
-     -721, -721, -721, -721, -721, -721, -721, -721, -721, -721,
-     -721, -721, -721, -721, -721, -721, -721, -721, -721, -721,
-     -721, -721, -721, -721, -721, -721, -721, -721, -721, -721,
-     -721, -721, -721, -721, -721, -721, -721, -721, -721, -721,
-     -721, -721, -721, -721, -721, -721, -721, -721
-    },
-
-    {
-       67, -722, -722, -722, -722, -722, -722, -722, -722, -722,
-     -722, -722, -722, -722, -722, -722, -722, -722, -722, -722,
-     -722, -722, -722, -722, -722, -722, -722, -722, -722, -722,
-     -722, -722, -722, -722, -722, -722, -722, -722, -722, -722,
-
-     -722, -722, -722, -722, -722, -722, -722, -722, -722, -722,
-     -722, -722, -722, -722, -722, -722, -722, -722, -722, -722,
-     -722, -722, -722, -722, -722, -722, -722, -722, -722, -722,
-     -722, -722, -722, -722, -722, -722, -722, -722, -722, -722,
-     -722, -722, -722, -722, -722, -722, -722, -722, -722, -722,
-     -722, -722, -722, -722, -722, -722, -722, -722, -722, -722,
-     -722, -722, -722, -722, -722, -722, -722, -722, -722, -722,
-     -722, -722, -722, -722, -722, -722, -722, -722, -722, -722,
-     -722, -722, -722, -722, -722, -722, -722, -722
-    },
-
-    {
-       67, -723, -723, -723, -723, -723, -723, -723, -723, -723,
-
-     -723, -723, -723, -723, -723, -723, -723, -723, -723, -723,
-     -723, -723, -723, -723, -723, -723, -723, -723, -723, -723,
-     -723, -723, -723, -723, -723, -723, -723, -723, -723, -723,
-     -723, -723, -723, -723, -723, -723, -723, -723, -723, -723,
-     -723, -723, -723, -723, -723, -723, -723, -723, -723, -723,
-     -723, -723, -723, -723, -723, -723, -723, -723, -723, -723,
-     -723,  764, -723, -723, -723, -723, -723, -723, -723, -723,
-     -723, -723, -723, -723, -723, -723, -723, -723, -723, -723,
-     -723, -723, -723, -723, -723, -723, -723, -723, -723, -723,
-     -723, -723, -723, -723, -723, -723, -723, -723, -723, -723,
-
-     -723, -723, -723, -723, -723, -723, -723, -723, -723, -723,
-     -723, -723, -723, -723, -723, -723, -723, -723
-    },
-
-    {
-       67, -724, -724, -724, -724, -724, -724, -724, -724, -724,
-     -724, -724, -724, -724, -724, -724, -724, -724, -724, -724,
-     -724, -724, -724, -724, -724, -724, -724, -724, -724, -724,
-     -724, -724, -724, -724, -724, -724, -724, -724, -724, -724,
-     -724, -724, -724, -724, -724, -724, -724, -724, -724, -724,
-     -724, -724, -724, -724, -724, -724, -724, -724, -724, -724,
-     -724, -724, -724, -724, -724, -724, -724, -724, -724, -724,
-     -724, -724, -724, -724, -724, -724, -724, -724, -724, -724,
-
-     -724, -724, -724,  765, -724, -724, -724, -724, -724, -724,
-     -724, -724, -724, -724, -724, -724, -724, -724, -724, -724,
-     -724, -724, -724, -724, -724, -724, -724, -724, -724, -724,
-     -724, -724, -724, -724, -724, -724, -724, -724, -724, -724,
-     -724, -724, -724, -724, -724, -724, -724, -724
-    },
-
-    {
-       67, -725, -725, -725, -725, -725, -725, -725, -725, -725,
-     -725, -725, -725, -725, -725, -725, -725, -725, -725, -725,
-     -725, -725, -725, -725, -725, -725, -725, -725, -725, -725,
-     -725, -725,  766, -725, -725, -725, -725, -725, -725, -725,
-     -725, -725, -725, -725, -725, -725, -725, -725, -725, -725,
-
-     -725, -725, -725, -725, -725, -725, -725, -725, -725, -725,
-     -725, -725, -725, -725, -725, -725, -725, -725, -725, -725,
-     -725, -725, -725, -725, -725, -725, -725, -725, -725, -725,
-     -725, -725, -725, -725, -725, -725, -725, -725, -725, -725,
-     -725, -725, -725, -725, -725, -725, -725, -725, -725, -725,
-     -725, -725, -725, -725, -725, -725, -725, -725, -725, -725,
-     -725, -725, -725, -725, -725, -725, -725, -725, -725, -725,
-     -725, -725, -725, -725, -725, -725, -725, -725
-    },
-
-    {
-       67, -726, -726, -726, -726, -726, -726, -726, -726, -726,
-     -726, -726, -726, -726, -726, -726, -726, -726, -726, -726,
-
-     -726, -726, -726, -726, -726, -726, -726, -726, -726, -726,
-     -726, -726,  767, -726, -726, -726, -726, -726, -726, -726,
-     -726, -726, -726, -726, -726, -726, -726, -726, -726, -726,
-     -726, -726, -726, -726, -726, -726, -726, -726, -726, -726,
-     -726, -726, -726, -726, -726, -726, -726, -726, -726, -726,
-     -726, -726, -726, -726, -726, -726, -726, -726, -726, -726,
-     -726, -726, -726, -726, -726, -726, -726, -726, -726, -726,
-     -726, -726, -726, -726, -726, -726, -726, -726, -726, -726,
-     -726, -726, -726, -726, -726, -726, -726, -726, -726, -726,
-     -726, -726, -726, -726, -726, -726, -726, -726, -726, -726,
-
-     -726, -726, -726, -726, -726, -726, -726, -726
-    },
-
-    {
-       67, -727, -727, -727, -727, -727, -727, -727, -727, -727,
-     -727, -727, -727, -727, -727, -727, -727, -727, -727, -727,
-     -727, -727, -727, -727, -727, -727, -727, -727, -727, -727,
-     -727, -727,  768, -727, -727, -727, -727, -727, -727, -727,
-     -727, -727, -727, -727, -727, -727, -727, -727, -727, -727,
-     -727, -727, -727, -727, -727, -727, -727, -727, -727, -727,
-     -727, -727, -727, -727, -727, -727, -727, -727, -727, -727,
-     -727, -727, -727, -727, -727, -727, -727, -727, -727, -727,
-     -727, -727, -727, -727, -727, -727, -727, -727, -727, -727,
-
-     -727, -727, -727, -727, -727, -727, -727, -727, -727, -727,
-     -727, -727, -727, -727, -727, -727, -727, -727, -727, -727,
-     -727, -727, -727, -727, -727, -727, -727, -727, -727, -727,
-     -727, -727, -727, -727, -727, -727, -727, -727
-    },
-
-    {
-       67, -728, -728, -728, -728, -728, -728, -728, -728, -728,
-     -728, -728, -728, -728, -728, -728, -728, -728, -728, -728,
-     -728, -728, -728, -728, -728, -728, -728, -728, -728, -728,
-     -728, -728,  769, -728, -728, -728, -728, -728, -728, -728,
-     -728, -728, -728, -728, -728, -728, -728, -728, -728, -728,
-     -728, -728, -728, -728, -728, -728, -728, -728, -728, -728,
-
-     -728, -728, -728, -728, -728, -728, -728, -728, -728, -728,
-     -728, -728, -728, -728, -728, -728, -728, -728, -728, -728,
-     -728, -728, -728, -728, -728, -728, -728, -728, -728, -728,
-     -728, -728, -728, -728, -728, -728, -728, -728, -728, -728,
-     -728, -728, -728, -728, -728, -728, -728, -728, -728, -728,
-     -728, -728, -728, -728, -728, -728, -728, -728, -728, -728,
-     -728, -728, -728, -728, -728, -728, -728, -728
-    },
-
-    {
-       67, -729, -729, -729, -729, -729, -729, -729, -729, -729,
-     -729, -729, -729, -729, -729, -729, -729, -729, -729, -729,
-     -729, -729, -729, -729, -729, -729, -729, -729, -729, -729,
-
-     -729, -729,  770, -729, -729, -729, -729, -729, -729, -729,
-     -729, -729, -729, -729, -729, -729, -729, -729, -729, -729,
-     -729, -729, -729, -729, -729, -729, -729, -729, -729, -729,
-     -729, -729, -729, -729, -729, -729, -729, -729, -729, -729,
-     -729, -729, -729, -729, -729, -729, -729, -729, -729, -729,
-     -729, -729, -729, -729, -729, -729, -729, -729, -729, -729,
-     -729, -729, -729, -729, -729, -729, -729, -729, -729, -729,
-     -729, -729, -729, -729, -729, -729, -729, -729, -729, -729,
-     -729, -729, -729, -729, -729, -729, -729, -729, -729, -729,
-     -729, -729, -729, -729, -729, -729, -729, -729
-
-    },
-
-    {
-       67, -730, -730, -730, -730, -730, -730, -730, -730, -730,
-     -730, -730, -730, -730, -730, -730, -730, -730, -730, -730,
-     -730, -730, -730, -730, -730, -730, -730, -730, -730, -730,
-     -730, -730, -730, -730, -730, -730, -730, -730, -730, -730,
-     -730, -730, -730, -730, -730, -730, -730, -730, -730, -730,
-     -730, -730, -730, -730, -730, -730, -730, -730, -730, -730,
-     -730, -730, -730, -730, -730, -730, -730, -730, -730, -730,
-     -730, -730, -730, -730, -730, -730, -730, -730, -730, -730,
-     -730, -730, -730, -730, -730, -730, -730, -730, -730, -730,
-     -730, -730, -730, -730, -730, -730, -730, -730, -730, -730,
-
-     -730, -730, -730, -730, -730, -730, -730, -730, -730, -730,
-     -730, -730, -730, -730, -730, -730, -730, -730, -730, -730,
-     -730, -730, -730, -730, -730, -730, -730, -730
-    },
-
-    {
-       67, -731, -731, -731, -731, -731, -731, -731, -731, -731,
-     -731, -731, -731, -731, -731, -731, -731, -731, -731, -731,
-     -731, -731, -731, -731, -731, -731, -731, -731, -731, -731,
-     -731, -731, -731, -731, -731, -731, -731, -731, -731, -731,
-     -731, -731, -731, -731, -731, -731, -731, -731, -731, -731,
-     -731, -731, -731, -731, -731, -731, -731, -731, -731, -731,
-     -731, -731, -731, -731, -731, -731, -731, -731, -731, -731,
-
-     -731, -731, -731, -731, -731, -731, -731, -731, -731, -731,
-     -731, -731, -731, -731, -731, -731, -731, -731, -731, -731,
-     -731, -731, -731, -731, -731, -731, -731, -731, -731, -731,
-     -731, -731, -731, -731, -731, -731, -731, -731, -731, -731,
-     -731, -731, -731, -731, -731, -731, -731, -731, -731, -731,
-     -731, -731, -731, -731, -731, -731, -731, -731
-    },
-
-    {
-       67, -732, -732, -732, -732, -732, -732, -732, -732, -732,
-     -732, -732, -732, -732, -732, -732, -732, -732, -732, -732,
-     -732, -732, -732, -732, -732, -732, -732, -732, -732, -732,
-     -732, -732, -732, -732, -732, -732, -732, -732, -732, -732,
-
-     -732, -732, -732, -732, -732, -732, -732, -732, -732, -732,
-     -732, -732, -732, -732, -732, -732, -732, -732, -732, -732,
-     -732, -732, -732, -732, -732, -732, -732, -732, -732, -732,
-     -732, -732, -732, -732, -732, -732, -732, -732, -732, -732,
-     -732, -732, -732, -732, -732, -732, -732, -732, -732, -732,
-     -732, -732, -732, -732, -732, -732, -732, -732, -732, -732,
-     -732, -732, -732, -732, -732, -732, -732, -732, -732, -732,
-     -732, -732, -732, -732, -732, -732, -732, -732, -732, -732,
-     -732, -732, -732, -732, -732, -732, -732, -732
-    },
-
-    {
-       67, -733, -733, -733, -733, -733, -733, -733, -733, -733,
-
-     -733, -733, -733, -733, -733, -733, -733, -733, -733, -733,
-     -733, -733, -733, -733, -733, -733, -733, -733, -733, -733,
-     -733, -733,  771, -733, -733, -733, -733, -733, -733, -733,
-     -733, -733, -733, -733, -733, -733, -733, -733, -733, -733,
-     -733, -733, -733, -733, -733, -733, -733, -733, -733, -733,
-     -733, -733, -733, -733, -733, -733, -733, -733, -733, -733,
-     -733, -733, -733, -733, -733, -733, -733, -733, -733, -733,
-     -733, -733, -733, -733, -733, -733, -733, -733, -733, -733,
-     -733, -733, -733, -733, -733, -733, -733, -733, -733, -733,
-     -733, -733, -733, -733, -733, -733, -733, -733, -733, -733,
-
-     -733, -733, -733, -733, -733, -733, -733, -733, -733, -733,
-     -733, -733, -733, -733, -733, -733, -733, -733
-    },
-
-    {
-       67, -734, -734, -734, -734, -734, -734, -734, -734, -734,
-     -734, -734, -734, -734, -734, -734, -734, -734, -734, -734,
-     -734, -734, -734, -734, -734, -734, -734, -734, -734, -734,
-     -734, -734,  772, -734, -734, -734, -734, -734, -734, -734,
-     -734, -734, -734, -734, -734, -734, -734, -734, -734, -734,
-     -734, -734, -734, -734, -734, -734, -734, -734, -734, -734,
-     -734, -734, -734, -734, -734, -734, -734, -734, -734, -734,
-     -734, -734, -734, -734, -734, -734, -734, -734, -734, -734,
-
-     -734, -734, -734, -734, -734, -734, -734, -734, -734, -734,
-     -734, -734, -734, -734, -734, -734, -734, -734, -734, -734,
-     -734, -734, -734, -734, -734, -734, -734, -734, -734, -734,
-     -734, -734, -734, -734, -734, -734, -734, -734, -734, -734,
-     -734, -734, -734, -734, -734, -734, -734, -734
-    },
-
-    {
-       67, -735, -735, -735, -735, -735, -735, -735, -735, -735,
-     -735, -735, -735, -735, -735, -735, -735, -735, -735, -735,
-     -735, -735, -735, -735, -735, -735, -735, -735, -735, -735,
-     -735, -735, -735, -735, -735, -735, -735, -735, -735, -735,
-     -735, -735, -735, -735, -735, -735, -735, -735, -735, -735,
-
-     -735, -735, -735, -735, -735, -735, -735, -735, -735, -735,
-     -735, -735, -735, -735, -735, -735, -735, -735, -735, -735,
-     -735, -735, -735, -735, -735, -735, -735, -735, -735, -735,
-     -735, -735, -735, -735, -735, -735, -735, -735,  773,  774,
-      775, -735, -735, -735, -735, -735, -735, -735, -735, -735,
-     -735, -735, -735, -735, -735, -735, -735, -735, -735, -735,
-     -735, -735, -735, -735, -735, -735, -735, -735, -735, -735,
-     -735, -735, -735, -735, -735, -735, -735, -735
-    },
-
-    {
-       67, -736, -736, -736, -736, -736, -736, -736, -736, -736,
-     -736, -736, -736, -736, -736, -736, -736, -736, -736, -736,
-
-     -736, -736, -736, -736, -736, -736, -736, -736, -736, -736,
-     -736, -736, -736, -736, -736, -736, -736, -736, -736, -736,
-     -736, -736, -736, -736, -736, -736, -736, -736, -736, -736,
-     -736, -736, -736, -736, -736, -736, -736, -736, -736, -736,
-     -736, -736, -736, -736, -736, -736, -736, -736, -736, -736,
-     -736, -736, -736, -736, -736, -736, -736, -736, -736, -736,
-     -736, -736, -736,  776, -736, -736, -736, -736, -736, -736,
-     -736, -736, -736, -736, -736, -736, -736, -736, -736, -736,
-     -736, -736, -736, -736, -736, -736, -736, -736, -736, -736,
-     -736, -736, -736, -736, -736, -736, -736, -736, -736, -736,
-
-     -736, -736, -736, -736, -736, -736, -736, -736
-    },
-
-    {
-       67, -737, -737, -737, -737, -737, -737, -737, -737, -737,
-     -737, -737, -737, -737, -737, -737, -737, -737, -737, -737,
-     -737, -737, -737, -737, -737, -737, -737, -737, -737, -737,
-     -737, -737, -737, -737, -737, -737, -737, -737, -737, -737,
-     -737, -737, -737, -737, -737, -737, -737, -737, -737, -737,
-     -737, -737, -737, -737, -737, -737, -737, -737, -737, -737,
-     -737, -737, -737, -737, -737, -737, -737, -737, -737, -737,
-     -737, -737, -737, -737, -737, -737, -737, -737, -737, -737,
-     -737, -737, -737, -737, -737, -737, -737, -737, -737, -737,
-
-     -737, -737, -737, -737, -737, -737, -737, -737, -737, -737,
-     -737, -737, -737, -737, -737, -737, -737, -737, -737, -737,
-     -737, -737, -737, -737, -737, -737, -737, -737, -737, -737,
-     -737, -737, -737, -737, -737, -737, -737, -737
-    },
-
-    {
-       67, -738, -738, -738, -738, -738, -738, -738, -738, -738,
-     -738, -738, -738, -738, -738, -738, -738, -738, -738, -738,
-     -738, -738, -738, -738, -738, -738, -738, -738, -738, -738,
-     -738, -738, -738, -738, -738, -738, -738, -738, -738, -738,
-     -738, -738, -738, -738, -738, -738, -738, -738, -738, -738,
-     -738, -738, -738, -738, -738, -738, -738, -738, -738, -738,
-
-     -738, -738, -738, -738, -738, -738, -738, -738, -738, -738,
-     -738, -738, -738, -738, -738, -738, -738, -738, -738, -738,
-     -738,  777, -738, -738, -738, -738, -738, -738, -738, -738,
-     -738, -738, -738, -738, -738, -738, -738, -738, -738, -738,
-     -738, -738, -738, -738, -738, -738, -738, -738, -738, -738,
-     -738, -738, -738, -738, -738, -738, -738, -738, -738, -738,
-     -738, -738, -738, -738, -738, -738, -738, -738
-    },
-
-    {
-       67, -739, -739, -739, -739, -739, -739, -739, -739, -739,
-     -739, -739, -739, -739, -739, -739, -739, -739, -739, -739,
-     -739, -739, -739, -739, -739, -739, -739, -739, -739, -739,
-
-     -739, -739, -739, -739, -739, -739, -739, -739, -739, -739,
-     -739, -739, -739, -739, -739, -739, -739, -739, -739, -739,
-     -739, -739, -739, -739, -739, -739, -739, -739, -739, -739,
-     -739, -739, -739, -739, -739, -739, -739, -739, -739, -739,
-     -739, -739, -739, -739, -739, -739, -739, -739, -739, -739,
-     -739, -739, -739, -739, -739, -739, -739, -739, -739, -739,
-     -739, -739, -739, -739, -739, -739, -739, -739, -739, -739,
-     -739, -739, -739, -739, -739, -739, -739, -739, -739, -739,
-     -739, -739, -739, -739, -739, -739, -739, -739, -739, -739,
-     -739, -739, -739, -739, -739, -739, -739, -739
-
-    },
-
-    {
-       67, -740, -740, -740, -740, -740, -740, -740, -740, -740,
-     -740, -740, -740, -740, -740, -740, -740, -740, -740, -740,
-     -740, -740, -740, -740, -740, -740, -740, -740, -740, -740,
-     -740, -740, -740, -740, -740, -740, -740, -740, -740, -740,
-     -740, -740, -740, -740, -740, -740, -740, -740, -740, -740,
-     -740, -740, -740, -740, -740, -740, -740, -740, -740, -740,
-     -740, -740, -740, -740, -740, -740, -740, -740, -740, -740,
-     -740, -740, -740, -740, -740, -740, -740, -740, -740, -740,
-     -740, -740, -740, -740, -740, -740, -740, -740, -740, -740,
-     -740, -740, -740, -740, -740, -740, -740, -740, -740, -740,
-
-     -740, -740, -740, -740, -740, -740, -740, -740, -740, -740,
-     -740, -740, -740, -740, -740, -740, -740, -740, -740, -740,
-     -740, -740, -740, -740, -740, -740, -740, -740
-    },
-
-    {
-       67, -741, -741, -741, -741, -741, -741, -741, -741, -741,
-     -741, -741, -741, -741, -741, -741, -741, -741, -741, -741,
-     -741, -741, -741, -741, -741, -741, -741, -741, -741, -741,
-     -741, -741, -741, -741, -741, -741, -741, -741, -741, -741,
-     -741, -741, -741, -741, -741, -741, -741, -741, -741, -741,
-     -741, -741, -741, -741, -741, -741, -741, -741, -741, -741,
-     -741, -741, -741, -741, -741, -741, -741, -741, -741, -741,
-
-     -741, -741, -741, -741, -741, -741, -741, -741, -741, -741,
-     -741, -741, -741, -741, -741, -741, -741, -741, -741, -741,
-     -741, -741, -741, -741, -741, -741, -741, -741, -741, -741,
-     -741, -741, -741, -741, -741, -741, -741, -741, -741, -741,
-     -741, -741, -741, -741, -741, -741, -741, -741, -741, -741,
-     -741, -741, -741, -741, -741, -741, -741, -741
-    },
-
-    {
-       67, -742, -742, -742, -742, -742, -742, -742, -742, -742,
-     -742, -742, -742, -742, -742, -742, -742, -742, -742, -742,
-     -742, -742, -742, -742, -742, -742, -742, -742, -742, -742,
-     -742, -742, -742, -742, -742, -742, -742, -742, -742, -742,
-
-     -742, -742, -742, -742, -742, -742, -742, -742, -742, -742,
-     -742, -742, -742, -742, -742, -742, -742, -742, -742, -742,
-     -742, -742, -742, -742, -742, -742, -742, -742, -742, -742,
-     -742, -742, -742, -742, -742, -742, -742, -742, -742, -742,
-     -742, -742, -742, -742, -742, -742, -742, -742, -742, -742,
-     -742, -742, -742, -742, -742, -742, -742, -742, -742, -742,
-     -742, -742, -742, -742, -742, -742, -742, -742, -742, -742,
-     -742, -742, -742, -742, -742, -742, -742, -742, -742, -742,
-     -742, -742, -742, -742, -742, -742, -742, -742
-    },
-
-    {
-       67, -743, -743, -743, -743, -743, -743, -743, -743, -743,
-
-     -743, -743, -743, -743, -743, -743, -743, -743, -743, -743,
-     -743, -743, -743, -743, -743, -743, -743, -743, -743, -743,
-     -743, -743, -743, -743, -743, -743, -743, -743, -743, -743,
-     -743, -743, -743, -743, -743, -743, -743, -743, -743, -743,
-     -743, -743, -743, -743, -743, -743, -743, -743, -743, -743,
-     -743, -743, -743, -743, -743, -743, -743, -743, -743, -743,
-     -743, -743, -743, -743, -743, -743, -743, -743, -743, -743,
-     -743, -743, -743, -743, -743, -743, -743, -743, -743, -743,
-     -743, -743, -743, -743, -743, -743, -743, -743, -743, -743,
-     -743, -743, -743, -743, -743, -743, -743, -743, -743, -743,
-
-     -743, -743, -743, -743, -743, -743, -743, -743, -743, -743,
-     -743, -743, -743, -743, -743, -743, -743, -743
-    },
-
-    {
-       67, -744, -744, -744, -744, -744, -744, -744, -744, -744,
-     -744, -744, -744, -744, -744, -744, -744, -744, -744, -744,
-     -744, -744, -744, -744, -744, -744, -744, -744, -744, -744,
-     -744, -744,  778, -744, -744, -744, -744, -744, -744, -744,
-     -744, -744, -744, -744, -744, -744, -744, -744, -744, -744,
-     -744, -744, -744, -744, -744, -744, -744, -744, -744, -744,
-     -744, -744, -744, -744, -744, -744, -744, -744, -744, -744,
-     -744, -744, -744, -744, -744, -744, -744, -744, -744, -744,
-
-     -744, -744, -744, -744, -744, -744, -744, -744, -744, -744,
-     -744, -744, -744, -744, -744, -744, -744, -744, -744, -744,
-     -744, -744, -744, -744, -744, -744, -744, -744, -744, -744,
-     -744, -744, -744, -744, -744, -744, -744, -744, -744, -744,
-     -744, -744, -744, -744, -744, -744, -744, -744
-    },
-
-    {
-       67, -745, -745, -745, -745, -745, -745, -745, -745, -745,
-     -745, -745, -745, -745, -745, -745, -745, -745, -745, -745,
-     -745, -745, -745, -745, -745, -745, -745, -745, -745, -745,
-     -745, -745, -745, -745, -745, -745, -745, -745, -745, -745,
-     -745, -745, -745, -745, -745, -745, -745, -745, -745, -745,
-
-     -745, -745, -745, -745, -745, -745, -745, -745, -745, -745,
-     -745, -745, -745, -745, -745, -745, -745, -745, -745, -745,
-     -745, -745, -745, -745, -745, -745, -745, -745, -745, -745,
-     -745, -745, -745, -745, -745, -745, -745, -745, -745, -745,
-     -745, -745, -745, -745, -745, -745, -745, -745, -745, -745,
-     -745, -745, -745, -745, -745, -745, -745, -745, -745, -745,
-     -745, -745, -745, -745, -745, -745, -745, -745, -745, -745,
-     -745, -745, -745, -745, -745, -745, -745, -745
-    },
-
-    {
-       67, -746, -746, -746, -746, -746, -746, -746, -746, -746,
-     -746, -746, -746, -746, -746, -746, -746, -746, -746, -746,
-
-     -746, -746, -746, -746, -746, -746, -746, -746, -746, -746,
-     -746, -746, -746, -746, -746, -746, -746, -746, -746, -746,
-     -746, -746, -746, -746, -746, -746, -746, -746, -746, -746,
-     -746, -746, -746, -746, -746, -746, -746, -746, -746, -746,
-     -746, -746, -746, -746, -746, -746, -746, -746, -746, -746,
-     -746, -746, -746, -746, -746, -746, -746, -746, -746, -746,
-     -746, -746, -746, -746, -746, -746, -746, -746, -746, -746,
-     -746, -746, -746, -746, -746, -746, -746, -746, -746, -746,
-     -746, -746, -746, -746, -746, -746, -746, -746, -746, -746,
-     -746, -746, -746, -746, -746, -746, -746, -746, -746, -746,
-
-     -746, -746, -746, -746, -746, -746, -746, -746
-    },
-
-    {
-       67, -747, -747, -747, -747, -747, -747, -747, -747, -747,
-     -747, -747, -747, -747, -747, -747, -747, -747, -747, -747,
-     -747, -747, -747, -747, -747, -747, -747, -747, -747, -747,
-     -747, -747,  779, -747, -747, -747, -747, -747, -747, -747,
-     -747, -747, -747, -747, -747, -747, -747, -747, -747, -747,
-     -747, -747, -747, -747, -747, -747, -747, -747, -747, -747,
-     -747, -747, -747, -747, -747, -747, -747, -747, -747, -747,
-     -747, -747, -747, -747, -747, -747, -747, -747, -747, -747,
-     -747, -747, -747, -747, -747, -747, -747, -747, -747, -747,
-
-     -747, -747, -747, -747, -747, -747, -747, -747, -747, -747,
-     -747, -747, -747, -747, -747, -747, -747, -747, -747, -747,
-     -747, -747, -747, -747, -747, -747, -747, -747, -747, -747,
-     -747, -747, -747, -747, -747, -747, -747, -747
-    },
-
-    {
-       67, -748, -748, -748, -748, -748, -748, -748, -748, -748,
-     -748, -748, -748, -748, -748, -748, -748, -748, -748, -748,
-     -748, -748, -748, -748, -748, -748, -748, -748, -748, -748,
-     -748, -748,  780, -748, -748, -748, -748, -748, -748, -748,
-     -748, -748, -748, -748, -748, -748, -748, -748, -748, -748,
-     -748, -748, -748, -748, -748, -748, -748, -748, -748, -748,
-
-     -748, -748, -748, -748, -748, -748, -748, -748, -748, -748,
-     -748, -748, -748, -748, -748, -748, -748, -748, -748, -748,
-     -748, -748, -748, -748, -748, -748, -748, -748, -748, -748,
-     -748, -748, -748, -748, -748, -748, -748, -748, -748, -748,
-     -748, -748, -748, -748, -748, -748, -748, -748, -748, -748,
-     -748, -748, -748, -748, -748, -748, -748, -748, -748, -748,
-     -748, -748, -748, -748, -748, -748, -748, -748
-    },
-
-    {
-       67, -749, -749, -749, -749, -749, -749, -749, -749, -749,
-     -749, -749, -749, -749, -749, -749, -749, -749, -749, -749,
-     -749, -749, -749, -749, -749, -749, -749, -749, -749, -749,
-
-     -749, -749,  781, -749, -749, -749, -749, -749, -749, -749,
-     -749, -749, -749, -749, -749, -749, -749, -749, -749, -749,
-     -749, -749, -749, -749, -749, -749, -749, -749, -749, -749,
-     -749, -749, -749, -749, -749, -749, -749, -749, -749, -749,
-     -749, -749, -749, -749, -749, -749, -749, -749, -749, -749,
-     -749, -749, -749, -749, -749, -749, -749, -749, -749, -749,
-     -749, -749, -749, -749, -749, -749, -749, -749, -749, -749,
-     -749, -749, -749, -749, -749, -749, -749, -749, -749, -749,
-     -749, -749, -749, -749, -749, -749, -749, -749, -749, -749,
-     -749, -749, -749, -749, -749, -749, -749, -749
-
-    },
-
-    {
-       67, -750, -750, -750, -750, -750, -750, -750, -750, -750,
-     -750, -750, -750, -750, -750, -750, -750, -750, -750, -750,
-     -750, -750, -750, -750, -750, -750, -750, -750, -750, -750,
-     -750, -750,  782, -750, -750, -750, -750, -750, -750, -750,
-     -750, -750, -750, -750, -750, -750, -750, -750, -750, -750,
-     -750, -750, -750, -750, -750, -750, -750, -750, -750, -750,
-     -750, -750, -750, -750, -750,  782,  782,  782,  782,  782,
-      782,  782,  782,  782,  782,  782,  782,  782,  782,  782,
-      782,  782,  782,  782,  782,  782,  782,  782,  782,  782,
-      782, -750, -750, -750, -750, -750, -750, -750, -750, -750,
-
-     -750, -750, -750, -750, -750, -750, -750, -750, -750, -750,
-     -750, -750, -750, -750, -750, -750, -750, -750, -750, -750,
-     -750, -750, -750, -750, -750, -750, -750, -750
-    },
-
-    {
-       67, -751, -751, -751, -751, -751, -751, -751, -751, -751,
-     -751, -751, -751, -751, -751, -751, -751, -751, -751, -751,
-     -751, -751, -751, -751, -751, -751, -751, -751, -751, -751,
-     -751, -751,  783, -751, -751, -751, -751, -751, -751, -751,
-     -751, -751, -751, -751, -751, -751, -751, -751, -751, -751,
-     -751, -751, -751, -751, -751, -751, -751, -751, -751, -751,
-     -751, -751, -751, -751, -751,  783,  783,  783,  783,  783,
-
-      783,  783,  783,  783,  783,  783,  783,  783,  783,  783,
-      783,  783,  783,  783,  783,  783,  783,  783,  783,  783,
-      783, -751, -751, -751, -751, -751, -751, -751, -751, -751,
-     -751, -751, -751, -751, -751, -751, -751, -751, -751, -751,
-     -751, -751, -751, -751, -751, -751, -751, -751, -751, -751,
-     -751, -751, -751, -751, -751, -751, -751, -751
-    },
-
-    {
-       67, -752, -752, -752, -752, -752, -752, -752, -752, -752,
-     -752, -752, -752, -752, -752, -752, -752, -752, -752, -752,
-     -752, -752, -752, -752, -752, -752, -752, -752, -752, -752,
-     -752, -752,  784, -752, -752, -752, -752, -752, -752, -752,
-
-     -752, -752, -752, -752, -752, -752, -752, -752, -752, -752,
-     -752, -752, -752, -752, -752, -752, -752, -752, -752, -752,
-     -752, -752, -752, -752, -752, -752, -752, -752, -752, -752,
-     -752, -752, -752, -752, -752, -752, -752, -752, -752, -752,
-     -752, -752, -752, -752, -752, -752, -752, -752, -752, -752,
-     -752, -752, -752, -752, -752, -752, -752, -752, -752, -752,
-     -752, -752, -752, -752, -752, -752, -752, -752, -752, -752,
-     -752, -752, -752, -752, -752, -752, -752, -752, -752, -752,
-     -752, -752, -752, -752, -752, -752, -752, -752
-    },
-
-    {
-       67, -753, -753, -753, -753, -753, -753, -753, -753, -753,
-
-     -753, -753, -753, -753, -753, -753, -753, -753, -753, -753,
-     -753, -753, -753, -753, -753, -753, -753, -753, -753, -753,
-     -753, -753,  785, -753, -753, -753, -753, -753, -753, -753,
-     -753, -753, -753, -753, -753, -753, -753, -753, -753, -753,
-     -753, -753, -753, -753, -753, -753, -753, -753, -753, -753,
-     -753, -753, -753, -753, -753, -753, -753, -753, -753, -753,
-     -753, -753, -753, -753, -753, -753, -753, -753, -753, -753,
-     -753, -753, -753, -753, -753, -753, -753, -753, -753, -753,
-     -753, -753, -753, -753, -753, -753, -753, -753, -753, -753,
-     -753, -753, -753, -753, -753, -753, -753, -753, -753, -753,
-
-     -753, -753, -753, -753, -753, -753, -753, -753, -753, -753,
-     -753, -753, -753, -753, -753, -753, -753, -753
-    },
-
-    {
-       67, -754, -754, -754, -754, -754, -754, -754, -754, -754,
-     -754, -754, -754, -754, -754, -754, -754, -754, -754, -754,
-     -754, -754, -754, -754, -754, -754, -754, -754, -754, -754,
-     -754, -754,  786, -754, -754, -754, -754, -754, -754, -754,
-     -754, -754, -754, -754, -754, -754, -754, -754, -754, -754,
-     -754, -754, -754, -754, -754, -754, -754, -754, -754, -754,
-     -754, -754, -754, -754, -754,  786,  786,  786,  786,  786,
-      786,  786,  786,  786,  786,  786,  786,  786,  786,  786,
-
-      786,  786,  786,  786,  786,  786,  786,  786,  786,  786,
-      786, -754, -754, -754, -754, -754, -754, -754, -754, -754,
-     -754, -754, -754, -754, -754, -754, -754, -754, -754, -754,
-     -754, -754, -754, -754, -754, -754, -754, -754, -754, -754,
-     -754, -754, -754, -754, -754, -754, -754, -754
-    },
-
-    {
-       67, -755, -755, -755, -755, -755, -755, -755, -755, -755,
-     -755, -755, -755, -755, -755, -755, -755, -755, -755, -755,
-     -755, -755, -755, -755, -755, -755, -755, -755, -755, -755,
-     -755, -755,  787, -755, -755, -755, -755, -755, -755, -755,
-     -755, -755, -755, -755, -755, -755, -755, -755, -755, -755,
-
-     -755, -755, -755, -755, -755, -755, -755, -755, -755, -755,
-     -755, -755, -755, -755, -755,  787,  787,  787,  787,  787,
-      787,  787,  787,  787,  787,  787,  787,  787,  787,  787,
-      787,  787,  787,  787,  787,  787,  787,  787,  787,  787,
-      787, -755, -755, -755, -755, -755, -755, -755, -755, -755,
-     -755, -755, -755, -755, -755, -755, -755, -755, -755, -755,
-     -755, -755, -755, -755, -755, -755, -755, -755, -755, -755,
-     -755, -755, -755, -755, -755, -755, -755, -755
-    },
-
-    {
-       67, -756, -756, -756, -756, -756, -756, -756, -756, -756,
-     -756, -756, -756, -756, -756, -756, -756, -756, -756, -756,
-
-     -756, -756, -756, -756, -756, -756, -756, -756, -756, -756,
-     -756, -756, -756, -756, -756, -756, -756, -756, -756, -756,
-     -756, -756, -756, -756, -756, -756, -756, -756, -756, -756,
-     -756, -756, -756, -756, -756, -756, -756, -756, -756, -756,
-     -756, -756, -756, -756, -756, -756, -756, -756, -756, -756,
-     -756, -756, -756, -756, -756, -756, -756, -756, -756, -756,
-     -756, -756, -756, -756, -756, -756, -756, -756, -756, -756,
-     -756, -756, -756, -756, -756, -756, -756, -756, -756, -756,
-     -756, -756, -756, -756, -756, -756, -756, -756, -756, -756,
-     -756, -756, -756, -756, -756, -756, -756, -756, -756, -756,
-
-     -756, -756, -756, -756, -756, -756, -756, -756
-    },
-
-    {
-       67, -757, -757, -757, -757, -757, -757, -757, -757, -757,
-     -757, -757, -757, -757, -757, -757, -757, -757, -757, -757,
-     -757, -757, -757, -757, -757, -757, -757, -757, -757, -757,
-     -757, -757,  788, -757, -757, -757, -757, -757, -757, -757,
-     -757, -757, -757, -757, -757, -757, -757, -757, -757, -757,
-     -757, -757, -757, -757, -757, -757, -757, -757, -757, -757,
-     -757, -757, -757, -757, -757, -757, -757, -757, -757, -757,
-     -757, -757, -757, -757, -757, -757, -757, -757, -757, -757,
-     -757, -757, -757, -757, -757, -757, -757, -757, -757, -757,
-
-     -757, -757, -757, -757, -757, -757, -757, -757, -757, -757,
-     -757, -757, -757, -757, -757, -757, -757, -757, -757, -757,
-     -757, -757, -757, -757, -757, -757, -757, -757, -757, -757,
-     -757, -757, -757, -757, -757, -757, -757, -757
-    },
-
-    {
-       67, -758, -758, -758, -758, -758, -758, -758, -758, -758,
-     -758, -758, -758, -758, -758, -758, -758, -758, -758, -758,
-     -758, -758, -758, -758, -758, -758, -758, -758, -758, -758,
-     -758, -758,  789, -758, -758, -758, -758, -758, -758, -758,
-     -758, -758, -758, -758, -758, -758, -758, -758, -758, -758,
-     -758, -758, -758, -758, -758, -758, -758, -758, -758, -758,
-
-     -758, -758, -758, -758, -758, -758, -758, -758, -758, -758,
-     -758, -758, -758, -758, -758, -758, -758, -758, -758, -758,
-     -758, -758, -758, -758, -758, -758, -758, -758, -758, -758,
-     -758, -758, -758, -758, -758, -758, -758, -758, -758, -758,
-     -758, -758, -758, -758, -758, -758, -758, -758, -758, -758,
-     -758, -758, -758, -758, -758, -758, -758, -758, -758, -758,
-     -758, -758, -758, -758, -758, -758, -758, -758
-    },
-
-    {
-       67, -759, -759, -759, -759, -759, -759, -759, -759, -759,
-     -759, -759, -759, -759, -759, -759, -759, -759, -759, -759,
-     -759, -759, -759, -759, -759, -759, -759, -759, -759, -759,
-
-     -759, -759,  790, -759, -759, -759, -759, -759, -759, -759,
-     -759, -759, -759, -759, -759, -759, -759, -759, -759, -759,
-     -759, -759, -759, -759, -759, -759, -759, -759, -759, -759,
-     -759, -759, -759, -759, -759,  790,  790,  790,  790,  790,
-      790,  790,  790,  790,  790,  790,  790,  790,  790,  790,
-      790,  790,  790,  790,  790,  790,  790,  790,  790,  790,
-      790, -759, -759, -759, -759, -759, -759, -759, -759, -759,
-     -759, -759, -759, -759, -759, -759, -759, -759, -759, -759,
-     -759, -759, -759, -759, -759, -759, -759, -759, -759, -759,
-     -759, -759, -759, -759, -759, -759, -759, -759
-
-    },
-
-    {
-       67, -760, -760, -760, -760, -760, -760, -760, -760, -760,
-     -760, -760, -760, -760, -760, -760, -760, -760, -760, -760,
-     -760, -760, -760, -760, -760, -760, -760, -760, -760, -760,
-     -760, -760,  791, -760, -760, -760, -760, -760, -760, -760,
-     -760, -760, -760, -760, -760, -760, -760, -760, -760, -760,
-     -760, -760, -760, -760, -760, -760, -760, -760, -760, -760,
-     -760, -760, -760, -760, -760, -760, -760, -760, -760, -760,
-     -760, -760, -760, -760, -760, -760, -760, -760, -760, -760,
-     -760, -760, -760, -760, -760, -760, -760, -760, -760, -760,
-     -760, -760, -760, -760, -760, -760, -760, -760, -760, -760,
-
-     -760, -760, -760, -760, -760, -760, -760, -760, -760, -760,
-     -760, -760, -760, -760, -760, -760, -760, -760, -760, -760,
-     -760, -760, -760, -760, -760, -760, -760, -760
-    },
-
-    {
-       67, -761, -761, -761, -761, -761, -761, -761, -761, -761,
-     -761, -761, -761, -761, -761, -761, -761, -761, -761, -761,
-     -761, -761, -761, -761, -761, -761, -761, -761, -761, -761,
-     -761, -761,  792, -761, -761, -761, -761, -761, -761, -761,
-     -761, -761, -761, -761, -761, -761, -761, -761, -761, -761,
-     -761, -761, -761, -761, -761, -761, -761, -761, -761, -761,
-     -761, -761, -761, -761, -761, -761, -761, -761, -761, -761,
-
-     -761, -761, -761, -761, -761, -761, -761, -761, -761, -761,
-     -761, -761, -761, -761, -761, -761, -761, -761, -761, -761,
-     -761, -761, -761, -761, -761, -761, -761, -761, -761, -761,
-     -761, -761, -761, -761, -761, -761, -761, -761, -761, -761,
-     -761, -761, -761, -761, -761, -761, -761, -761, -761, -761,
-     -761, -761, -761, -761, -761, -761, -761, -761
-    },
-
-    {
-       67, -762, -762, -762, -762, -762, -762, -762, -762, -762,
-     -762, -762, -762, -762, -762, -762, -762, -762, -762, -762,
-     -762, -762, -762, -762, -762, -762, -762, -762, -762, -762,
-     -762, -762,  793, -762, -762, -762, -762, -762, -762, -762,
-
-     -762, -762, -762, -762, -762, -762, -762, -762, -762, -762,
-     -762, -762, -762, -762, -762, -762, -762, -762, -762, -762,
-     -762, -762, -762, -762, -762,  793,  793,  793,  793,  793,
-      793,  793,  793,  793,  793,  793,  793,  793,  793,  793,
-      793,  793,  793,  793,  793,  793,  793,  793,  793,  793,
-      793, -762, -762, -762, -762, -762, -762, -762, -762, -762,
-     -762, -762, -762, -762, -762, -762, -762, -762, -762, -762,
-     -762, -762, -762, -762, -762, -762, -762, -762, -762, -762,
-     -762, -762, -762, -762, -762, -762, -762, -762
-    },
-
-    {
-       67, -763, -763, -763, -763, -763, -763, -763, -763, -763,
-
-     -763, -763, -763, -763, -763, -763, -763, -763, -763, -763,
-     -763, -763, -763, -763, -763, -763, -763, -763, -763, -763,
-     -763, -763, -763, -763, -763, -763, -763, -763, -763, -763,
-     -763, -763, -763, -763, -763, -763, -763, -763, -763, -763,
-     -763, -763, -763, -763, -763, -763, -763, -763, -763, -763,
-     -763, -763, -763, -763, -763, -763, -763, -763, -763, -763,
-     -763, -763, -763, -763, -763, -763, -763, -763, -763, -763,
-     -763, -763, -763, -763, -763, -763, -763, -763, -763, -763,
-     -763, -763, -763, -763, -763, -763, -763, -763, -763, -763,
-     -763, -763, -763, -763, -763, -763, -763, -763, -763, -763,
-
-     -763, -763, -763, -763, -763, -763, -763, -763, -763, -763,
-     -763, -763, -763, -763, -763, -763, -763, -763
-    },
-
-    {
-       67, -764, -764, -764, -764, -764, -764, -764, -764, -764,
-     -764, -764, -764, -764, -764, -764, -764, -764, -764, -764,
-     -764, -764, -764, -764, -764, -764, -764, -764, -764, -764,
-     -764, -764, -764, -764, -764, -764, -764, -764, -764, -764,
-     -764, -764, -764, -764, -764, -764, -764, -764, -764, -764,
-     -764, -764, -764, -764, -764, -764, -764, -764, -764, -764,
-     -764, -764, -764, -764, -764, -764, -764, -764, -764, -764,
-     -764, -764, -764, -764, -764, -764, -764, -764, -764, -764,
-
-     -764, -764, -764, -764, -764, -764, -764, -764, -764, -764,
-     -764, -764, -764, -764, -764, -764, -764, -764, -764, -764,
-     -764, -764, -764, -764, -764, -764, -764, -764, -764, -764,
-     -764, -764, -764, -764, -764, -764, -764, -764, -764, -764,
-     -764, -764, -764, -764, -764, -764, -764, -764
-    },
-
-    {
-       67, -765, -765, -765, -765, -765, -765, -765, -765, -765,
-     -765, -765, -765, -765, -765, -765, -765, -765, -765, -765,
-     -765, -765, -765, -765, -765, -765, -765, -765, -765, -765,
-     -765, -765, -765, -765, -765, -765, -765, -765, -765, -765,
-     -765, -765, -765, -765, -765, -765, -765, -765, -765, -765,
-
-     -765, -765, -765, -765, -765, -765, -765, -765, -765, -765,
-     -765, -765, -765, -765, -765, -765, -765, -765, -765, -765,
-     -765, -765, -765, -765, -765, -765, -765, -765, -765, -765,
-     -765, -765, -765, -765, -765, -765, -765, -765, -765, -765,
-     -765, -765, -765, -765, -765, -765, -765, -765, -765, -765,
-     -765, -765, -765, -765, -765, -765, -765, -765, -765, -765,
-     -765, -765, -765, -765, -765, -765, -765, -765, -765, -765,
-     -765, -765, -765, -765, -765, -765, -765, -765
-    },
-
-    {
-       67, -766, -766, -766, -766, -766, -766, -766, -766, -766,
-     -766, -766, -766, -766, -766, -766, -766, -766, -766, -766,
-
-     -766, -766, -766, -766, -766, -766, -766, -766, -766, -766,
-     -766, -766, -766, -766, -766, -766, -766, -766, -766, -766,
-     -766, -766, -766, -766, -766, -766, -766, -766, -766, -766,
-     -766, -766, -766, -766, -766, -766, -766, -766, -766, -766,
-     -766, -766, -766, -766, -766, -766, -766, -766, -766, -766,
-     -766, -766, -766, -766, -766, -766, -766, -766, -766, -766,
-     -766, -766, -766, -766, -766, -766, -766, -766, -766, -766,
-     -766, -766, -766, -766, -766, -766, -766, -766, -766, -766,
-     -766, -766, -766, -766, -766, -766, -766, -766, -766, -766,
-     -766, -766, -766, -766, -766, -766, -766, -766, -766, -766,
-
-     -766, -766, -766, -766, -766, -766, -766, -766
-    },
-
-    {
-       67, -767, -767, -767, -767, -767, -767, -767, -767, -767,
-     -767, -767, -767, -767, -767, -767, -767, -767, -767, -767,
-     -767, -767, -767, -767, -767, -767, -767, -767, -767, -767,
-     -767, -767, -767, -767, -767, -767, -767, -767, -767, -767,
-     -767, -767, -767, -767, -767, -767, -767, -767, -767, -767,
-     -767, -767, -767, -767, -767, -767, -767, -767, -767, -767,
-     -767, -767, -767, -767, -767, -767, -767, -767, -767, -767,
-     -767, -767, -767, -767, -767, -767, -767, -767, -767, -767,
-     -767, -767, -767, -767, -767, -767, -767, -767, -767, -767,
-
-     -767, -767, -767, -767, -767, -767, -767, -767, -767, -767,
-     -767, -767, -767, -767, -767, -767, -767, -767, -767, -767,
-     -767, -767, -767, -767, -767, -767, -767, -767, -767, -767,
-     -767, -767, -767, -767, -767, -767, -767, -767
-    },
-
-    {
-       67, -768, -768, -768, -768, -768, -768, -768, -768, -768,
-     -768, -768, -768, -768, -768, -768, -768, -768, -768, -768,
-     -768, -768, -768, -768, -768, -768, -768, -768, -768, -768,
-     -768, -768, -768, -768, -768, -768, -768, -768, -768, -768,
-     -768, -768, -768, -768, -768, -768, -768, -768, -768, -768,
-     -768, -768, -768, -768, -768, -768, -768, -768, -768, -768,
-
-     -768, -768, -768, -768, -768, -768, -768, -768, -768, -768,
-     -768, -768, -768, -768, -768, -768, -768, -768, -768, -768,
-     -768, -768, -768, -768, -768, -768, -768, -768, -768, -768,
-     -768, -768, -768, -768, -768, -768, -768, -768, -768, -768,
-     -768, -768, -768, -768, -768, -768, -768, -768, -768, -768,
-     -768, -768, -768, -768, -768, -768, -768, -768, -768, -768,
-     -768, -768, -768, -768, -768, -768, -768, -768
-    },
-
-    {
-       67, -769, -769, -769, -769, -769, -769, -769, -769, -769,
-     -769, -769, -769, -769, -769, -769, -769, -769, -769, -769,
-     -769, -769, -769, -769, -769, -769, -769, -769, -769, -769,
-
-     -769, -769,  794, -769, -769, -769, -769, -769, -769, -769,
-     -769, -769, -769, -769, -769, -769, -769, -769, -769, -769,
-     -769, -769, -769, -769, -769, -769, -769, -769, -769, -769,
-     -769, -769, -769, -769, -769, -769, -769, -769, -769, -769,
-     -769, -769, -769, -769, -769, -769, -769, -769, -769, -769,
-     -769, -769, -769, -769, -769, -769, -769, -769, -769, -769,
-     -769, -769, -769, -769, -769, -769, -769, -769, -769, -769,
-     -769, -769, -769, -769, -769, -769, -769, -769, -769, -769,
-     -769, -769, -769, -769, -769, -769, -769, -769, -769, -769,
-     -769, -769, -769, -769, -769, -769, -769, -769
-
-    },
-
-    {
-       67, -770, -770, -770, -770, -770, -770, -770, -770, -770,
-     -770, -770, -770, -770, -770, -770, -770, -770, -770, -770,
-     -770, -770, -770, -770, -770, -770, -770, -770, -770, -770,
-     -770, -770, -770, -770, -770, -770, -770, -770, -770, -770,
-     -770, -770, -770, -770, -770, -770, -770, -770, -770, -770,
-     -770, -770, -770, -770, -770, -770, -770, -770, -770, -770,
-     -770, -770, -770, -770, -770, -770, -770, -770, -770, -770,
-     -770, -770, -770, -770, -770, -770, -770, -770, -770, -770,
-     -770, -770, -770, -770, -770, -770, -770, -770, -770, -770,
-     -770, -770, -770, -770, -770, -770, -770, -770, -770, -770,
-
-     -770, -770, -770, -770, -770, -770, -770, -770, -770, -770,
-     -770, -770, -770, -770, -770, -770, -770, -770, -770, -770,
-     -770, -770, -770, -770, -770, -770, -770, -770
-    },
-
-    {
-       67, -771, -771, -771, -771, -771, -771, -771, -771, -771,
-     -771, -771, -771, -771, -771, -771, -771, -771, -771, -771,
-     -771, -771, -771, -771, -771, -771, -771, -771, -771, -771,
-     -771, -771, -771, -771, -771, -771, -771, -771, -771, -771,
-     -771, -771, -771, -771, -771, -771, -771, -771, -771, -771,
-     -771, -771, -771, -771, -771, -771, -771, -771, -771, -771,
-     -771, -771, -771, -771, -771, -771, -771, -771, -771, -771,
-
-     -771, -771, -771, -771, -771, -771, -771, -771, -771, -771,
-     -771, -771, -771, -771, -771, -771, -771, -771, -771, -771,
-     -771, -771, -771, -771, -771, -771, -771, -771, -771, -771,
-     -771, -771, -771, -771, -771, -771, -771, -771, -771, -771,
-     -771, -771, -771, -771, -771, -771, -771, -771, -771, -771,
-     -771, -771, -771, -771, -771, -771, -771, -771
-    },
-
-    {
-       67, -772, -772, -772, -772, -772, -772, -772, -772, -772,
-     -772, -772, -772, -772, -772, -772, -772, -772, -772, -772,
-     -772, -772, -772, -772, -772, -772, -772, -772, -772, -772,
-     -772, -772, -772, -772, -772, -772, -772, -772, -772, -772,
-
-     -772, -772, -772, -772, -772, -772, -772, -772, -772, -772,
-     -772, -772, -772, -772, -772, -772, -772, -772, -772, -772,
-     -772, -772, -772, -772, -772, -772, -772, -772, -772, -772,
-     -772, -772, -772, -772, -772, -772, -772, -772, -772, -772,
-     -772, -772, -772, -772, -772, -772, -772, -772, -772, -772,
-     -772, -772, -772, -772, -772, -772, -772, -772, -772, -772,
-     -772, -772, -772, -772, -772, -772, -772, -772, -772, -772,
-     -772, -772, -772, -772, -772, -772, -772, -772, -772, -772,
-     -772, -772, -772, -772, -772, -772, -772, -772
-    },
-
-    {
-       67, -773, -773, -773, -773, -773, -773, -773, -773, -773,
-
-     -773, -773, -773, -773, -773, -773, -773, -773, -773, -773,
-     -773, -773, -773, -773, -773, -773, -773, -773, -773, -773,
-     -773, -773, -773, -773, -773, -773, -773, -773, -773, -773,
-     -773, -773, -773, -773, -773, -773, -773, -773, -773, -773,
-     -773, -773, -773, -773, -773, -773, -773, -773, -773, -773,
-     -773, -773, -773, -773, -773, -773, -773, -773, -773, -773,
-     -773, -773, -773, -773, -773, -773, -773, -773, -773, -773,
-     -773, -773, -773, -773, -773, -773, -773, -773, -773, -773,
-     -773, -773, -773, -773, -773, -773, -773, -773, -773, -773,
-     -773, -773, -773, -773, -773, -773, -773, -773, -773, -773,
-
-     -773, -773, -773, -773, -773, -773, -773, -773, -773, -773,
-     -773, -773, -773, -773, -773, -773, -773, -773
-    },
-
-    {
-       67, -774, -774, -774, -774, -774, -774, -774, -774, -774,
-     -774, -774, -774, -774, -774, -774, -774, -774, -774, -774,
-     -774, -774, -774, -774, -774, -774, -774, -774, -774, -774,
-     -774, -774, -774, -774, -774, -774, -774, -774, -774, -774,
-     -774, -774, -774, -774, -774, -774, -774, -774, -774, -774,
-     -774, -774, -774, -774, -774, -774, -774, -774, -774, -774,
-     -774, -774, -774, -774, -774, -774, -774, -774, -774, -774,
-     -774, -774, -774, -774, -774, -774, -774, -774, -774, -774,
-
-     -774, -774, -774, -774, -774, -774, -774, -774, -774, -774,
-     -774, -774, -774, -774, -774, -774, -774, -774, -774, -774,
-     -774, -774, -774, -774, -774, -774, -774, -774, -774, -774,
-     -774, -774, -774, -774, -774, -774, -774, -774, -774, -774,
-     -774, -774, -774, -774, -774, -774, -774, -774
-    },
-
-    {
-       67, -775, -775, -775, -775, -775, -775, -775, -775, -775,
-     -775, -775, -775, -775, -775, -775, -775, -775, -775, -775,
-     -775, -775, -775, -775, -775, -775, -775, -775, -775, -775,
-     -775, -775, -775, -775, -775, -775, -775, -775, -775, -775,
-     -775, -775, -775, -775, -775, -775, -775, -775, -775, -775,
-
-     -775, -775, -775, -775, -775, -775, -775, -775, -775, -775,
-     -775, -775, -775, -775, -775, -775, -775, -775, -775, -775,
-     -775, -775, -775, -775, -775, -775, -775, -775, -775, -775,
-     -775, -775, -775, -775, -775, -775, -775, -775, -775, -775,
-     -775, -775, -775, -775, -775, -775, -775, -775, -775, -775,
-     -775, -775, -775, -775, -775, -775, -775, -775, -775, -775,
-     -775, -775, -775, -775, -775, -775, -775, -775, -775, -775,
-     -775, -775, -775, -775, -775, -775, -775, -775
-    },
-
-    {
-       67, -776, -776, -776, -776, -776, -776, -776, -776, -776,
-     -776, -776, -776, -776, -776, -776, -776, -776, -776, -776,
-
-     -776, -776, -776, -776, -776, -776, -776, -776, -776, -776,
-     -776, -776, -776, -776, -776, -776, -776, -776, -776, -776,
-     -776, -776, -776, -776, -776, -776, -776, -776, -776, -776,
-     -776, -776, -776, -776, -776, -776, -776, -776, -776, -776,
-     -776, -776, -776, -776, -776, -776, -776, -776, -776, -776,
-     -776, -776, -776, -776, -776, -776, -776, -776, -776, -776,
-     -776, -776, -776, -776, -776, -776, -776, -776, -776, -776,
-     -776, -776, -776, -776, -776, -776, -776, -776, -776, -776,
-     -776, -776, -776, -776, -776, -776, -776, -776, -776, -776,
-     -776, -776, -776, -776, -776, -776, -776, -776, -776, -776,
-
-     -776, -776, -776, -776, -776, -776, -776, -776
-    },
-
-    {
-       67, -777, -777, -777, -777, -777, -777, -777, -777, -777,
-     -777, -777, -777, -777, -777, -777, -777, -777, -777, -777,
-     -777, -777, -777, -777, -777, -777, -777, -777, -777, -777,
-     -777, -777, -777, -777, -777, -777, -777, -777, -777, -777,
-     -777, -777, -777, -777, -777, -777, -777, -777, -777, -777,
-     -777, -777, -777, -777, -777, -777, -777, -777, -777, -777,
-     -777, -777, -777, -777, -777, -777, -777, -777, -777, -777,
-     -777, -777, -777, -777, -777, -777, -777, -777, -777, -777,
-     -777, -777, -777, -777, -777, -777, -777, -777, -777, -777,
-
-     -777, -777, -777, -777, -777, -777, -777, -777, -777, -777,
-     -777, -777, -777, -777, -777, -777, -777, -777, -777, -777,
-     -777, -777, -777, -777, -777, -777, -777, -777, -777, -777,
-     -777, -777, -777, -777, -777, -777, -777, -777
-    },
-
-    {
-       67, -778, -778, -778, -778, -778, -778, -778, -778, -778,
-     -778, -778, -778, -778, -778, -778, -778, -778, -778, -778,
-     -778, -778, -778, -778, -778, -778, -778, -778, -778, -778,
-     -778, -778, -778, -778, -778, -778, -778, -778, -778, -778,
-     -778, -778, -778, -778, -778, -778, -778, -778, -778, -778,
-     -778, -778, -778, -778, -778, -778, -778, -778, -778, -778,
-
-     -778,  795, -778, -778, -778, -778, -778, -778, -778, -778,
-     -778, -778, -778, -778, -778, -778, -778, -778, -778, -778,
-     -778, -778, -778, -778, -778, -778, -778, -778, -778, -778,
-     -778, -778, -778, -778, -778, -778, -778, -778, -778, -778,
-     -778, -778, -778, -778, -778, -778, -778, -778, -778, -778,
-     -778, -778, -778, -778, -778, -778, -778, -778, -778, -778,
-     -778, -778, -778, -778, -778, -778, -778, -778
-    },
-
-    {
-       67, -779, -779, -779, -779, -779, -779, -779, -779, -779,
-     -779, -779, -779, -779, -779, -779, -779, -779, -779, -779,
-     -779, -779, -779, -779, -779, -779, -779, -779, -779, -779,
-
-     -779, -779, -779, -779, -779, -779, -779, -779, -779, -779,
-     -779, -779, -779, -779, -779, -779, -779, -779, -779, -779,
-     -779, -779, -779, -779, -779, -779, -779, -779, -779, -779,
-     -779, -779, -779, -779, -779, -779, -779, -779, -779, -779,
-     -779, -779, -779, -779, -779, -779, -779, -779, -779, -779,
-     -779, -779, -779, -779, -779, -779, -779, -779, -779, -779,
-     -779, -779, -779, -779, -779, -779, -779, -779, -779, -779,
-     -779, -779, -779, -779, -779, -779, -779, -779, -779, -779,
-     -779, -779, -779, -779, -779, -779, -779, -779, -779, -779,
-     -779, -779, -779, -779, -779, -779, -779, -779
-
-    },
-
-    {
-       67, -780, -780, -780, -780, -780, -780, -780, -780, -780,
-     -780, -780, -780, -780, -780, -780, -780, -780, -780, -780,
-     -780, -780, -780, -780, -780, -780, -780, -780, -780, -780,
-     -780, -780, -780, -780, -780, -780, -780, -780, -780, -780,
-     -780, -780, -780, -780, -780, -780, -780, -780, -780, -780,
-     -780, -780, -780, -780, -780, -780, -780, -780, -780, -780,
-     -780, -780, -780, -780, -780, -780, -780, -780, -780, -780,
-     -780, -780, -780, -780, -780, -780, -780, -780, -780, -780,
-     -780, -780, -780, -780, -780, -780, -780, -780, -780, -780,
-     -780, -780, -780, -780, -780, -780, -780, -780, -780, -780,
-
-     -780, -780, -780, -780, -780, -780, -780, -780, -780, -780,
-     -780, -780, -780, -780, -780, -780, -780, -780, -780, -780,
-     -780, -780, -780, -780, -780, -780, -780, -780
-    },
-
-    {
-       67, -781, -781, -781, -781, -781, -781, -781, -781, -781,
-     -781, -781, -781, -781, -781, -781, -781, -781, -781, -781,
-     -781, -781, -781, -781, -781, -781, -781, -781, -781, -781,
-     -781, -781, -781, -781, -781, -781, -781, -781, -781, -781,
-     -781, -781, -781, -781, -781, -781, -781, -781, -781, -781,
-     -781, -781, -781, -781, -781, -781, -781, -781, -781, -781,
-     -781, -781, -781, -781, -781, -781, -781, -781, -781, -781,
-
-     -781, -781, -781, -781, -781, -781, -781, -781, -781, -781,
-     -781, -781, -781, -781, -781, -781, -781, -781, -781, -781,
-     -781, -781, -781, -781, -781, -781, -781, -781, -781, -781,
-     -781, -781, -781, -781, -781, -781, -781, -781, -781, -781,
-     -781, -781, -781, -781, -781, -781, -781, -781, -781, -781,
-     -781, -781, -781, -781, -781, -781, -781, -781
-    },
-
-    {
-       67, -782, -782, -782, -782, -782, -782, -782, -782, -782,
-     -782, -782, -782, -782, -782, -782, -782, -782, -782, -782,
-     -782, -782, -782, -782, -782, -782, -782, -782, -782, -782,
-     -782, -782, -782, -782, -782, -782, -782, -782, -782, -782,
-
-     -782, -782, -782, -782, -782, -782, -782, -782, -782, -782,
-     -782, -782, -782, -782, -782, -782, -782, -782, -782, -782,
-     -782, -782, -782, -782, -782, -782, -782, -782, -782, -782,
-     -782, -782, -782, -782, -782, -782, -782, -782, -782, -782,
-     -782, -782, -782, -782, -782, -782, -782, -782, -782, -782,
-     -782, -782, -782, -782, -782, -782, -782, -782, -782, -782,
-     -782, -782, -782, -782, -782, -782, -782, -782, -782, -782,
-     -782, -782, -782, -782, -782, -782, -782, -782, -782, -782,
-     -782, -782, -782, -782, -782, -782, -782, -782
-    },
-
-    {
-       67, -783, -783, -783, -783, -783, -783, -783, -783, -783,
-
-     -783, -783, -783, -783, -783, -783, -783, -783, -783, -783,
-     -783, -783, -783, -783, -783, -783, -783, -783, -783, -783,
-     -783, -783, -783, -783, -783, -783, -783, -783, -783, -783,
-     -783, -783, -783, -783, -783, -783, -783, -783, -783, -783,
-     -783, -783, -783, -783, -783, -783, -783, -783, -783, -783,
-     -783, -783, -783, -783, -783, -783, -783, -783, -783, -783,
-     -783, -783, -783, -783, -783, -783, -783, -783, -783, -783,
-     -783, -783, -783, -783, -783, -783, -783, -783, -783, -783,
-     -783, -783, -783, -783, -783, -783, -783, -783, -783, -783,
-     -783, -783, -783, -783, -783, -783, -783, -783, -783, -783,
-
-     -783, -783, -783, -783, -783, -783, -783, -783, -783, -783,
-     -783, -783, -783, -783, -783, -783, -783, -783
-    },
-
-    {
-       67, -784, -784, -784, -784, -784, -784, -784, -784, -784,
-     -784, -784, -784, -784, -784, -784, -784, -784, -784, -784,
-     -784, -784, -784, -784, -784, -784, -784, -784, -784, -784,
-     -784, -784, -784, -784, -784, -784, -784, -784, -784, -784,
-     -784, -784, -784, -784, -784, -784, -784, -784, -784, -784,
-     -784, -784, -784, -784, -784, -784, -784, -784, -784, -784,
-     -784,  796, -784, -784, -784, -784, -784, -784, -784, -784,
-     -784, -784, -784, -784, -784, -784, -784, -784, -784, -784,
-
-     -784, -784, -784, -784, -784, -784, -784, -784, -784, -784,
-     -784, -784, -784, -784, -784, -784, -784, -784, -784, -784,
-     -784, -784, -784, -784, -784, -784, -784, -784, -784, -784,
-     -784, -784, -784, -784, -784, -784, -784, -784, -784, -784,
-     -784, -784, -784, -784, -784, -784, -784, -784
-    },
-
-    {
-       67, -785, -785, -785, -785, -785, -785, -785, -785, -785,
-     -785, -785, -785, -785, -785, -785, -785, -785, -785, -785,
-     -785, -785, -785, -785, -785, -785, -785, -785, -785, -785,
-     -785, -785, -785, -785, -785, -785, -785, -785, -785, -785,
-     -785, -785, -785, -785, -785, -785, -785, -785, -785, -785,
-
-     -785, -785, -785, -785, -785, -785, -785, -785, -785, -785,
-     -785,  797, -785, -785, -785, -785, -785, -785, -785, -785,
-     -785, -785, -785, -785, -785, -785, -785, -785, -785, -785,
-     -785, -785, -785, -785, -785, -785, -785, -785, -785, -785,
-     -785, -785, -785, -785, -785, -785, -785, -785, -785, -785,
-     -785, -785, -785, -785, -785, -785, -785, -785, -785, -785,
-     -785, -785, -785, -785, -785, -785, -785, -785, -785, -785,
-     -785, -785, -785, -785, -785, -785, -785, -785
-    },
-
-    {
-       67, -786, -786, -786, -786, -786, -786, -786, -786, -786,
-     -786, -786, -786, -786, -786, -786, -786, -786, -786, -786,
-
-     -786, -786, -786, -786, -786, -786, -786, -786, -786, -786,
-     -786, -786, -786, -786, -786, -786, -786, -786, -786, -786,
-     -786, -786, -786, -786, -786, -786, -786, -786, -786, -786,
-     -786, -786, -786, -786, -786, -786, -786, -786, -786, -786,
-     -786,  798, -786, -786, -786, -786, -786, -786, -786, -786,
-     -786, -786, -786, -786, -786, -786, -786, -786, -786, -786,
-     -786, -786, -786, -786, -786, -786, -786, -786, -786, -786,
-     -786, -786, -786, -786, -786, -786, -786, -786, -786, -786,
-     -786, -786, -786, -786, -786, -786, -786, -786, -786, -786,
-     -786, -786, -786, -786, -786, -786, -786, -786, -786, -786,
-
-     -786, -786, -786, -786, -786, -786, -786, -786
-    },
-
-    {
-       67, -787, -787, -787, -787, -787, -787, -787, -787, -787,
-     -787, -787, -787, -787, -787, -787, -787, -787, -787, -787,
-     -787, -787, -787, -787, -787, -787, -787, -787, -787, -787,
-     -787, -787, -787, -787, -787, -787, -787, -787, -787, -787,
-     -787, -787, -787, -787, -787, -787, -787, -787, -787, -787,
-     -787, -787, -787, -787, -787, -787, -787, -787, -787, -787,
-     -787,  799, -787, -787, -787, -787, -787, -787, -787, -787,
-     -787, -787, -787, -787, -787, -787, -787, -787, -787, -787,
-     -787, -787, -787, -787, -787, -787, -787, -787, -787, -787,
-
-     -787, -787, -787, -787, -787, -787, -787, -787, -787, -787,
-     -787, -787, -787, -787, -787, -787, -787, -787, -787, -787,
-     -787, -787, -787, -787, -787, -787, -787, -787, -787, -787,
-     -787, -787, -787, -787, -787, -787, -787, -787
-    },
-
-    {
-       67, -788, -788, -788, -788, -788, -788, -788, -788, -788,
-     -788, -788, -788, -788, -788, -788, -788, -788, -788, -788,
-     -788, -788, -788, -788, -788, -788, -788, -788, -788, -788,
-     -788, -788, -788, -788, -788, -788, -788, -788, -788, -788,
-     -788, -788, -788, -788, -788, -788, -788, -788, -788, -788,
-     -788, -788, -788, -788, -788, -788, -788, -788, -788, -788,
-
-     -788,  800, -788, -788, -788, -788, -788, -788, -788, -788,
-     -788, -788, -788, -788, -788, -788, -788, -788, -788, -788,
-     -788, -788, -788, -788, -788, -788, -788, -788, -788, -788,
-     -788, -788, -788, -788, -788, -788, -788, -788, -788, -788,
-     -788, -788, -788, -788, -788, -788, -788, -788, -788, -788,
-     -788, -788, -788, -788, -788, -788, -788, -788, -788, -788,
-     -788, -788, -788, -788, -788, -788, -788, -788
-    },
-
-    {
-       67, -789, -789, -789, -789, -789, -789, -789, -789, -789,
-     -789, -789, -789, -789, -789, -789, -789, -789, -789, -789,
-     -789, -789, -789, -789, -789, -789, -789, -789, -789, -789,
-
-     -789, -789, -789, -789, -789, -789, -789, -789, -789, -789,
-     -789, -789, -789, -789, -789, -789, -789, -789, -789, -789,
-     -789, -789, -789, -789, -789, -789, -789, -789, -789, -789,
-     -789,  801, -789, -789, -789, -789, -789, -789, -789, -789,
-     -789, -789, -789, -789, -789, -789, -789, -789, -789, -789,
-     -789, -789, -789, -789, -789, -789, -789, -789, -789, -789,
-     -789, -789, -789, -789, -789, -789, -789, -789, -789, -789,
-     -789, -789, -789, -789, -789, -789, -789, -789, -789, -789,
-     -789, -789, -789, -789, -789, -789, -789, -789, -789, -789,
-     -789, -789, -789, -789, -789, -789, -789, -789
-
-    },
-
-    {
-       67, -790, -790, -790, -790, -790, -790, -790, -790, -790,
-     -790, -790, -790, -790, -790, -790, -790, -790, -790, -790,
-     -790, -790, -790, -790, -790, -790, -790, -790, -790, -790,
-     -790, -790, -790, -790, -790, -790, -790, -790, -790, -790,
-     -790, -790, -790, -790, -790, -790, -790, -790, -790, -790,
-     -790, -790, -790, -790, -790, -790, -790, -790, -790, -790,
-     -790,  802, -790, -790, -790, -790, -790, -790, -790, -790,
-     -790, -790, -790, -790, -790, -790, -790, -790, -790, -790,
-     -790, -790, -790, -790, -790, -790, -790, -790, -790, -790,
-     -790, -790, -790, -790, -790, -790, -790, -790, -790, -790,
-
-     -790, -790, -790, -790, -790, -790, -790, -790, -790, -790,
-     -790, -790, -790, -790, -790, -790, -790, -790, -790, -790,
-     -790, -790, -790, -790, -790, -790, -790, -790
-    },
-
-    {
-       67, -791, -791, -791, -791, -791, -791, -791, -791, -791,
-     -791, -791, -791, -791, -791, -791, -791, -791, -791, -791,
-     -791, -791, -791, -791, -791, -791, -791, -791, -791, -791,
-     -791, -791, -791, -791, -791, -791, -791, -791, -791, -791,
-     -791, -791, -791, -791, -791, -791, -791, -791, -791, -791,
-     -791, -791, -791, -791, -791, -791, -791, -791, -791, -791,
-     -791,  803, -791, -791, -791, -791, -791, -791, -791, -791,
-
-     -791, -791, -791, -791, -791, -791, -791, -791, -791, -791,
-     -791, -791, -791, -791, -791, -791, -791, -791, -791, -791,
-     -791, -791, -791, -791, -791, -791, -791, -791, -791, -791,
-     -791, -791, -791, -791, -791, -791, -791, -791, -791, -791,
-     -791, -791, -791, -791, -791, -791, -791, -791, -791, -791,
-     -791, -791, -791, -791, -791, -791, -791, -791
-    },
-
-    {
-       67, -792, -792, -792, -792, -792, -792, -792, -792, -792,
-     -792, -792, -792, -792, -792, -792, -792, -792, -792, -792,
-     -792, -792, -792, -792, -792, -792, -792, -792, -792, -792,
-     -792, -792, -792, -792, -792, -792, -792, -792, -792, -792,
-
-     -792, -792, -792, -792, -792, -792, -792, -792, -792, -792,
-     -792, -792, -792, -792, -792, -792, -792, -792, -792, -792,
-     -792,  804, -792, -792, -792, -792, -792, -792, -792, -792,
-     -792, -792, -792, -792, -792, -792, -792, -792, -792, -792,
-     -792, -792, -792, -792, -792, -792, -792, -792, -792, -792,
-     -792, -792, -792, -792, -792, -792, -792, -792, -792, -792,
-     -792, -792, -792, -792, -792, -792, -792, -792, -792, -792,
-     -792, -792, -792, -792, -792, -792, -792, -792, -792, -792,
-     -792, -792, -792, -792, -792, -792, -792, -792
-    },
-
-    {
-       67, -793, -793, -793, -793, -793, -793, -793, -793, -793,
-
-     -793, -793, -793, -793, -793, -793, -793, -793, -793, -793,
-     -793, -793, -793, -793, -793, -793, -793, -793, -793, -793,
-     -793, -793, -793, -793, -793, -793, -793, -793, -793, -793,
-     -793, -793, -793, -793, -793, -793, -793, -793, -793, -793,
-     -793, -793, -793, -793, -793, -793, -793, -793, -793, -793,
-     -793,  805, -793, -793, -793, -793, -793, -793, -793, -793,
-     -793, -793, -793, -793, -793, -793, -793, -793, -793, -793,
-     -793, -793, -793, -793, -793, -793, -793, -793, -793, -793,
-     -793, -793, -793, -793, -793, -793, -793, -793, -793, -793,
-     -793, -793, -793, -793, -793, -793, -793, -793, -793, -793,
-
-     -793, -793, -793, -793, -793, -793, -793, -793, -793, -793,
-     -793, -793, -793, -793, -793, -793, -793, -793
-    },
-
-    {
-       67, -794, -794, -794, -794, -794, -794, -794, -794, -794,
-     -794, -794, -794, -794, -794, -794, -794, -794, -794, -794,
-     -794, -794, -794, -794, -794, -794, -794, -794, -794, -794,
-     -794, -794,  806, -794, -794, -794, -794, -794, -794, -794,
-     -794, -794, -794, -794, -794, -794, -794, -794, -794, -794,
-     -794, -794, -794, -794, -794, -794, -794, -794, -794, -794,
-     -794, -794, -794, -794, -794, -794, -794, -794, -794, -794,
-     -794, -794, -794, -794, -794, -794, -794, -794, -794, -794,
-
-     -794, -794, -794, -794, -794, -794, -794, -794, -794, -794,
-     -794, -794, -794, -794, -794, -794, -794, -794, -794, -794,
-     -794, -794, -794, -794, -794, -794, -794, -794, -794, -794,
-     -794, -794, -794, -794, -794, -794, -794, -794, -794, -794,
-     -794, -794, -794, -794, -794, -794, -794, -794
-    },
-
-    {
-       67, -795, -795, -795, -795, -795, -795, -795, -795, -795,
-     -795, -795, -795, -795, -795, -795, -795, -795, -795, -795,
-     -795, -795, -795, -795, -795, -795, -795, -795, -795, -795,
-     -795, -795,  807, -795, -795, -795, -795, -795, -795, -795,
-     -795, -795, -795, -795, -795, -795, -795, -795, -795, -795,
-
-     -795, -795, -795, -795, -795, -795, -795, -795, -795, -795,
-     -795, -795, -795, -795, -795, -795, -795, -795, -795, -795,
-     -795, -795, -795, -795, -795, -795, -795, -795, -795, -795,
-     -795, -795, -795, -795, -795, -795, -795, -795, -795, -795,
-     -795, -795, -795, -795, -795, -795, -795, -795, -795, -795,
-     -795, -795, -795, -795, -795, -795, -795, -795, -795, -795,
-     -795, -795, -795, -795, -795, -795, -795, -795, -795, -795,
-     -795, -795, -795, -795, -795, -795, -795, -795
-    },
-
-    {
-       67, -796, -796, -796, -796, -796, -796, -796, -796, -796,
-     -796, -796, -796, -796, -796, -796, -796, -796, -796, -796,
-
-     -796, -796, -796, -796, -796, -796, -796, -796, -796, -796,
-     -796, -796,  808, -796, -796, -796, -796, -796, -796, -796,
-     -796, -796, -796, -796, -796, -796, -796, -796, -796, -796,
-     -796, -796, -796, -796, -796, -796, -796, -796, -796, -796,
-     -796, -796, -796, -796, -796, -796, -796, -796, -796, -796,
-     -796, -796, -796, -796, -796, -796, -796, -796, -796, -796,
-     -796, -796, -796, -796, -796, -796, -796, -796, -796, -796,
-     -796, -796, -796, -796, -796, -796, -796, -796, -796, -796,
-     -796, -796, -796, -796, -796, -796, -796, -796, -796, -796,
-     -796, -796, -796, -796, -796, -796, -796, -796, -796, -796,
-
-     -796, -796, -796, -796, -796, -796, -796, -796
-    },
-
-    {
-       67, -797, -797, -797, -797, -797, -797, -797, -797, -797,
-     -797, -797, -797, -797, -797, -797, -797, -797, -797, -797,
-     -797, -797, -797, -797, -797, -797, -797, -797, -797, -797,
-     -797, -797,  809, -797, -797, -797, -797, -797, -797, -797,
-     -797, -797, -797, -797, -797, -797, -797, -797, -797, -797,
-     -797, -797, -797, -797, -797, -797, -797, -797, -797, -797,
-     -797, -797, -797, -797, -797, -797, -797, -797, -797, -797,
-     -797, -797, -797, -797, -797, -797, -797, -797, -797, -797,
-     -797, -797, -797, -797, -797, -797, -797, -797, -797, -797,
-
-     -797, -797, -797, -797, -797, -797, -797, -797, -797, -797,
-     -797, -797, -797, -797, -797, -797, -797, -797, -797, -797,
-     -797, -797, -797, -797, -797, -797, -797, -797, -797, -797,
-     -797, -797, -797, -797, -797, -797, -797, -797
-    },
-
-    {
-       67, -798, -798, -798, -798, -798, -798, -798, -798, -798,
-     -798, -798, -798, -798, -798, -798, -798, -798, -798, -798,
-     -798, -798, -798, -798, -798, -798, -798, -798, -798, -798,
-     -798, -798,  810, -798, -798, -798, -798, -798, -798, -798,
-     -798, -798, -798, -798, -798, -798, -798, -798, -798, -798,
-     -798, -798, -798, -798, -798, -798, -798, -798, -798, -798,
-
-     -798, -798, -798, -798, -798, -798, -798, -798, -798, -798,
-     -798, -798, -798, -798, -798, -798, -798, -798, -798, -798,
-     -798, -798, -798, -798, -798, -798, -798, -798, -798, -798,
-     -798, -798, -798, -798, -798, -798, -798, -798, -798, -798,
-     -798, -798, -798, -798, -798, -798, -798, -798, -798, -798,
-     -798, -798, -798, -798, -798, -798, -798, -798, -798, -798,
-     -798, -798, -798, -798, -798, -798, -798, -798
-    },
-
-    {
-       67, -799, -799, -799, -799, -799, -799, -799, -799, -799,
-     -799, -799, -799, -799, -799, -799, -799, -799, -799, -799,
-     -799, -799, -799, -799, -799, -799, -799, -799, -799, -799,
-
-     -799, -799,  811, -799, -799, -799, -799, -799, -799, -799,
-     -799, -799, -799, -799, -799, -799, -799, -799, -799, -799,
-     -799, -799, -799, -799, -799, -799, -799, -799, -799, -799,
-     -799, -799, -799, -799, -799, -799, -799, -799, -799, -799,
-     -799, -799, -799, -799, -799, -799, -799, -799, -799, -799,
-     -799, -799, -799, -799, -799, -799, -799, -799, -799, -799,
-     -799, -799, -799, -799, -799, -799, -799, -799, -799, -799,
-     -799, -799, -799, -799, -799, -799, -799, -799, -799, -799,
-     -799, -799, -799, -799, -799, -799, -799, -799, -799, -799,
-     -799, -799, -799, -799, -799, -799, -799, -799
-
-    },
-
-    {
-       67, -800, -800, -800, -800, -800, -800, -800, -800, -800,
-     -800, -800, -800, -800, -800, -800, -800, -800, -800, -800,
-     -800, -800, -800, -800, -800, -800, -800, -800, -800, -800,
-     -800, -800,  812, -800, -800, -800, -800, -800, -800, -800,
-     -800, -800, -800, -800, -800, -800, -800, -800, -800, -800,
-     -800, -800, -800, -800, -800, -800, -800, -800, -800, -800,
-     -800, -800, -800, -800, -800, -800, -800, -800, -800, -800,
-     -800, -800, -800, -800, -800, -800, -800, -800, -800, -800,
-     -800, -800, -800, -800, -800, -800, -800, -800, -800, -800,
-     -800, -800, -800, -800, -800, -800, -800, -800, -800, -800,
-
-     -800, -800, -800, -800, -800, -800, -800, -800, -800, -800,
-     -800, -800, -800, -800, -800, -800, -800, -800, -800, -800,
-     -800, -800, -800, -800, -800, -800, -800, -800
-    },
-
-    {
-       67, -801, -801, -801, -801, -801, -801, -801, -801, -801,
-     -801, -801, -801, -801, -801, -801, -801, -801, -801, -801,
-     -801, -801, -801, -801, -801, -801, -801, -801, -801, -801,
-     -801, -801,  813, -801, -801, -801, -801, -801, -801, -801,
-     -801, -801, -801, -801, -801, -801, -801, -801, -801, -801,
-     -801, -801, -801, -801, -801, -801, -801, -801, -801, -801,
-     -801, -801, -801, -801, -801, -801, -801, -801, -801, -801,
-
-     -801, -801, -801, -801, -801, -801, -801, -801, -801, -801,
-     -801, -801, -801, -801, -801, -801, -801, -801, -801, -801,
-     -801, -801, -801, -801, -801, -801, -801, -801, -801, -801,
-     -801, -801, -801, -801, -801, -801, -801, -801, -801, -801,
-     -801, -801, -801, -801, -801, -801, -801, -801, -801, -801,
-     -801, -801, -801, -801, -801, -801, -801, -801
-    },
-
-    {
-       67, -802, -802, -802, -802, -802, -802, -802, -802, -802,
-     -802, -802, -802, -802, -802, -802, -802, -802, -802, -802,
-     -802, -802, -802, -802, -802, -802, -802, -802, -802, -802,
-     -802, -802,  814, -802, -802, -802, -802, -802, -802, -802,
-
-     -802, -802, -802, -802, -802, -802, -802, -802, -802, -802,
-     -802, -802, -802, -802, -802, -802, -802, -802, -802, -802,
-     -802, -802, -802, -802, -802, -802, -802, -802, -802, -802,
-     -802, -802, -802, -802, -802, -802, -802, -802, -802, -802,
-     -802, -802, -802, -802, -802, -802, -802, -802, -802, -802,
-     -802, -802, -802, -802, -802, -802, -802, -802, -802, -802,
-     -802, -802, -802, -802, -802, -802, -802, -802, -802, -802,
-     -802, -802, -802, -802, -802, -802, -802, -802, -802, -802,
-     -802, -802, -802, -802, -802, -802, -802, -802
-    },
-
-    {
-       67, -803, -803, -803, -803, -803, -803, -803, -803, -803,
-
-     -803, -803, -803, -803, -803, -803, -803, -803, -803, -803,
-     -803, -803, -803, -803, -803, -803, -803, -803, -803, -803,
-     -803, -803,  815, -803, -803, -803, -803, -803, -803, -803,
-     -803, -803, -803, -803, -803, -803, -803, -803, -803, -803,
-     -803, -803, -803, -803, -803, -803, -803, -803, -803, -803,
-     -803, -803, -803, -803, -803, -803, -803, -803, -803, -803,
-     -803, -803, -803, -803, -803, -803, -803, -803, -803, -803,
-     -803, -803, -803, -803, -803, -803, -803, -803, -803, -803,
-     -803, -803, -803, -803, -803, -803, -803, -803, -803, -803,
-     -803, -803, -803, -803, -803, -803, -803, -803, -803, -803,
-
-     -803, -803, -803, -803, -803, -803, -803, -803, -803, -803,
-     -803, -803, -803, -803, -803, -803, -803, -803
-    },
-
-    {
-       67, -804, -804, -804, -804, -804, -804, -804, -804, -804,
-     -804, -804, -804, -804, -804, -804, -804, -804, -804, -804,
-     -804, -804, -804, -804, -804, -804, -804, -804, -804, -804,
-     -804, -804,  816, -804, -804, -804, -804, -804, -804, -804,
-     -804, -804, -804, -804, -804, -804, -804, -804, -804, -804,
-     -804, -804, -804, -804, -804, -804, -804, -804, -804, -804,
-     -804, -804, -804, -804, -804, -804, -804, -804, -804, -804,
-     -804, -804, -804, -804, -804, -804, -804, -804, -804, -804,
-
-     -804, -804, -804, -804, -804, -804, -804, -804, -804, -804,
-     -804, -804, -804, -804, -804, -804, -804, -804, -804, -804,
-     -804, -804, -804, -804, -804, -804, -804, -804, -804, -804,
-     -804, -804, -804, -804, -804, -804, -804, -804, -804, -804,
-     -804, -804, -804, -804, -804, -804, -804, -804
-    },
-
-    {
-       67, -805, -805, -805, -805, -805, -805, -805, -805, -805,
-     -805, -805, -805, -805, -805, -805, -805, -805, -805, -805,
-     -805, -805, -805, -805, -805, -805, -805, -805, -805, -805,
-     -805, -805,  817, -805, -805, -805, -805, -805, -805, -805,
-     -805, -805, -805, -805, -805, -805, -805, -805, -805, -805,
-
-     -805, -805, -805, -805, -805, -805, -805, -805, -805, -805,
-     -805, -805, -805, -805, -805, -805, -805, -805, -805, -805,
-     -805, -805, -805, -805, -805, -805, -805, -805, -805, -805,
-     -805, -805, -805, -805, -805, -805, -805, -805, -805, -805,
-     -805, -805, -805, -805, -805, -805, -805, -805, -805, -805,
-     -805, -805, -805, -805, -805, -805, -805, -805, -805, -805,
-     -805, -805, -805, -805, -805, -805, -805, -805, -805, -805,
-     -805, -805, -805, -805, -805, -805, -805, -805
-    },
-
-    {
-       67, -806, -806, -806, -806, -806, -806, -806, -806, -806,
-     -806, -806, -806, -806, -806, -806, -806, -806, -806, -806,
-
-     -806, -806, -806, -806, -806, -806, -806, -806, -806, -806,
-     -806, -806,  818, -806, -806, -806, -806, -806, -806, -806,
-     -806, -806, -806, -806, -806, -806, -806, -806, -806, -806,
-     -806, -806, -806, -806, -806, -806, -806, -806, -806, -806,
-     -806, -806, -806, -806, -806, -806, -806, -806, -806, -806,
-     -806, -806, -806, -806, -806, -806, -806, -806, -806, -806,
-     -806, -806, -806, -806, -806, -806, -806, -806, -806, -806,
-     -806, -806, -806, -806, -806, -806, -806, -806, -806, -806,
-     -806, -806, -806, -806, -806, -806, -806, -806, -806, -806,
-     -806, -806, -806, -806, -806, -806, -806, -806, -806, -806,
-
-     -806, -806, -806, -806, -806, -806, -806, -806
-    },
-
-    {
-       67, -807, -807, -807, -807, -807, -807, -807, -807, -807,
-     -807, -807, -807, -807, -807, -807, -807, -807, -807, -807,
-     -807, -807, -807, -807, -807, -807, -807, -807, -807, -807,
-     -807, -807,  819, -807, -807, -807, -807, -807, -807, -807,
-     -807, -807, -807,  820, -807,  820, -807, -807,  821,  821,
-      821,  821,  821,  821,  821,  821,  821,  821, -807, -807,
-     -807, -807, -807, -807, -807, -807, -807, -807, -807, -807,
-     -807, -807, -807, -807, -807, -807, -807, -807, -807, -807,
-     -807, -807, -807, -807, -807, -807, -807, -807, -807, -807,
-
-     -807, -807, -807, -807, -807, -807, -807, -807, -807, -807,
-     -807, -807, -807, -807, -807, -807, -807, -807, -807, -807,
-     -807, -807, -807, -807, -807, -807, -807, -807, -807, -807,
-     -807, -807, -807, -807, -807, -807, -807, -807
-    },
-
-    {
-       67, -808, -808, -808, -808, -808, -808, -808, -808, -808,
-     -808, -808, -808, -808, -808, -808, -808, -808, -808, -808,
-     -808, -808, -808, -808, -808, -808, -808, -808, -808, -808,
-     -808, -808,  822, -808, -808, -808, -808, -808, -808, -808,
-     -808, -808, -808,  823, -808,  823, -808, -808,  824,  824,
-      824,  824,  824,  824,  824,  824,  824,  824, -808, -808,
-
-     -808, -808, -808, -808, -808, -808, -808, -808, -808, -808,
-     -808, -808, -808, -808, -808, -808, -808, -808, -808, -808,
-     -808, -808, -808, -808, -808, -808, -808, -808, -808, -808,
-     -808, -808, -808, -808, -808, -808, -808, -808, -808, -808,
-     -808, -808, -808, -808, -808, -808, -808, -808, -808, -808,
-     -808, -808, -808, -808, -808, -808, -808, -808, -808, -808,
-     -808, -808, -808, -808, -808, -808, -808, -808
-    },
-
-    {
-       67, -809, -809, -809, -809, -809, -809, -809, -809, -809,
-     -809, -809, -809, -809, -809, -809, -809, -809, -809, -809,
-     -809, -809, -809, -809, -809, -809, -809, -809, -809, -809,
-
-     -809, -809,  825, -809, -809, -809, -809, -809, -809, -809,
-     -809, -809, -809,  826, -809,  826, -809, -809,  827,  827,
-      827,  827,  827,  827,  827,  827,  827,  827, -809, -809,
-     -809, -809, -809, -809, -809, -809, -809, -809, -809, -809,
-     -809, -809, -809, -809, -809, -809, -809, -809, -809, -809,
-     -809, -809, -809, -809, -809, -809, -809, -809, -809, -809,
-     -809, -809, -809, -809, -809, -809, -809, -809, -809, -809,
-     -809, -809, -809, -809, -809, -809, -809, -809, -809, -809,
-     -809, -809, -809, -809, -809, -809, -809, -809, -809, -809,
-     -809, -809, -809, -809, -809, -809, -809, -809
-
-    },
-
-    {
-       67, -810, -810, -810, -810, -810, -810, -810, -810, -810,
-     -810, -810, -810, -810, -810, -810, -810, -810, -810, -810,
-     -810, -810, -810, -810, -810, -810, -810, -810, -810, -810,
-     -810, -810,  828, -810, -810, -810, -810, -810, -810, -810,
-     -810, -810, -810,  829, -810,  829, -810, -810,  830,  830,
-      830,  830,  830,  830,  830,  830,  830,  830, -810, -810,
-     -810, -810, -810, -810, -810, -810, -810, -810, -810, -810,
-     -810, -810, -810, -810, -810, -810, -810, -810, -810, -810,
-     -810, -810, -810, -810, -810, -810, -810, -810, -810, -810,
-     -810, -810, -810, -810, -810, -810, -810, -810, -810, -810,
-
-     -810, -810, -810, -810, -810, -810, -810, -810, -810, -810,
-     -810, -810, -810, -810, -810, -810, -810, -810, -810, -810,
-     -810, -810, -810, -810, -810, -810, -810, -810
-    },
-
-    {
-       67, -811, -811, -811, -811, -811, -811, -811, -811, -811,
-     -811, -811, -811, -811, -811, -811, -811, -811, -811, -811,
-     -811, -811, -811, -811, -811, -811, -811, -811, -811, -811,
-     -811, -811,  831, -811, -811, -811, -811, -811, -811, -811,
-     -811, -811, -811,  832, -811,  832, -811, -811,  833,  833,
-      833,  833,  833,  833,  833,  833,  833,  833, -811, -811,
-     -811, -811, -811, -811, -811, -811, -811, -811, -811, -811,
-
-     -811, -811, -811, -811, -811, -811, -811, -811, -811, -811,
-     -811, -811, -811, -811, -811, -811, -811, -811, -811, -811,
-     -811, -811, -811, -811, -811, -811, -811, -811, -811, -811,
-     -811, -811, -811, -811, -811, -811, -811, -811, -811, -811,
-     -811, -811, -811, -811, -811, -811, -811, -811, -811, -811,
-     -811, -811, -811, -811, -811, -811, -811, -811
-    },
-
-    {
-       67, -812, -812, -812, -812, -812, -812, -812, -812, -812,
-     -812, -812, -812, -812, -812, -812, -812, -812, -812, -812,
-     -812, -812, -812, -812, -812, -812, -812, -812, -812, -812,
-     -812, -812,  834, -812, -812, -812, -812, -812, -812,  835,
-
-     -812, -812, -812, -812, -812, -812, -812, -812, -812, -812,
-     -812, -812, -812, -812, -812, -812, -812, -812, -812, -812,
-     -812, -812, -812, -812, -812, -812, -812, -812, -812, -812,
-     -812, -812, -812, -812, -812, -812, -812, -812, -812, -812,
-     -812, -812, -812, -812, -812, -812, -812, -812, -812, -812,
-     -812, -812, -812, -812, -812, -812, -812, -812, -812, -812,
-     -812, -812, -812, -812, -812, -812, -812, -812, -812, -812,
-     -812, -812, -812, -812, -812, -812, -812, -812, -812, -812,
-     -812, -812, -812, -812, -812, -812, -812, -812
-    },
-
-    {
-       67, -813, -813, -813, -813, -813, -813, -813, -813, -813,
-
-     -813, -813, -813, -813, -813, -813, -813, -813, -813, -813,
-     -813, -813, -813, -813, -813, -813, -813, -813, -813, -813,
-     -813, -813,  836, -813, -813, -813, -813, -813, -813,  837,
-     -813, -813, -813, -813, -813, -813, -813, -813, -813, -813,
-     -813, -813, -813, -813, -813, -813, -813, -813, -813, -813,
-     -813, -813, -813, -813, -813, -813, -813, -813, -813, -813,
-     -813, -813, -813, -813, -813, -813, -813, -813, -813, -813,
-     -813, -813, -813, -813, -813, -813, -813, -813, -813, -813,
-     -813, -813, -813, -813, -813, -813, -813, -813, -813, -813,
-     -813, -813, -813, -813, -813, -813, -813, -813, -813, -813,
-
-     -813, -813, -813, -813, -813, -813, -813, -813, -813, -813,
-     -813, -813, -813, -813, -813, -813, -813, -813
-    },
-
-    {
-       67, -814, -814, -814, -814, -814, -814, -814, -814, -814,
-     -814, -814, -814, -814, -814, -814, -814, -814, -814, -814,
-     -814, -814, -814, -814, -814, -814, -814, -814, -814, -814,
-     -814, -814,  838, -814, -814, -814, -814, -814, -814,  839,
-     -814, -814, -814, -814, -814, -814, -814, -814, -814, -814,
-     -814, -814, -814, -814, -814, -814, -814, -814, -814, -814,
-     -814, -814, -814, -814, -814, -814, -814, -814, -814, -814,
-     -814, -814, -814, -814, -814, -814, -814, -814, -814, -814,
-
-     -814, -814, -814, -814, -814, -814, -814, -814, -814, -814,
-     -814, -814, -814, -814, -814, -814, -814, -814, -814, -814,
-     -814, -814, -814, -814, -814, -814, -814, -814, -814, -814,
-     -814, -814, -814, -814, -814, -814, -814, -814, -814, -814,
-     -814, -814, -814, -814, -814, -814, -814, -814
-    },
-
-    {
-       67, -815, -815, -815, -815, -815, -815, -815, -815, -815,
-     -815, -815, -815, -815, -815, -815, -815, -815, -815, -815,
-     -815, -815, -815, -815, -815, -815, -815, -815, -815, -815,
-     -815, -815,  840, -815, -815, -815, -815, -815, -815,  841,
-     -815, -815, -815, -815, -815, -815, -815, -815, -815, -815,
-
-     -815, -815, -815, -815, -815, -815, -815, -815, -815, -815,
-     -815, -815, -815, -815, -815, -815, -815, -815, -815, -815,
-     -815, -815, -815, -815, -815, -815, -815, -815, -815, -815,
-     -815, -815, -815, -815, -815, -815, -815, -815, -815, -815,
-     -815, -815, -815, -815, -815, -815, -815, -815, -815, -815,
-     -815, -815, -815, -815, -815, -815, -815, -815, -815, -815,
-     -815, -815, -815, -815, -815, -815, -815, -815, -815, -815,
-     -815, -815, -815, -815, -815, -815, -815, -815
-    },
-
-    {
-       67, -816, -816, -816, -816, -816, -816, -816, -816, -816,
-     -816, -816, -816, -816, -816, -816, -816, -816, -816, -816,
-
-     -816, -816, -816, -816, -816, -816, -816, -816, -816, -816,
-     -816, -816,  842, -816, -816, -816, -816, -816, -816,  843,
-     -816, -816, -816, -816, -816, -816, -816, -816, -816, -816,
-     -816, -816, -816, -816, -816, -816, -816, -816, -816, -816,
-     -816, -816, -816, -816, -816, -816, -816, -816, -816, -816,
-     -816, -816, -816, -816, -816, -816, -816, -816, -816, -816,
-     -816, -816, -816, -816, -816, -816, -816, -816, -816, -816,
-     -816, -816, -816, -816, -816, -816, -816, -816, -816, -816,
-     -816, -816, -816, -816, -816, -816, -816, -816, -816, -816,
-     -816, -816, -816, -816, -816, -816, -816, -816, -816, -816,
-
-     -816, -816, -816, -816, -816, -816, -816, -816
-    },
-
-    {
-       67, -817, -817, -817, -817, -817, -817, -817, -817, -817,
-     -817, -817, -817, -817, -817, -817, -817, -817, -817, -817,
-     -817, -817, -817, -817, -817, -817, -817, -817, -817, -817,
-     -817, -817,  844, -817, -817, -817, -817, -817, -817,  845,
-     -817, -817, -817, -817, -817, -817, -817, -817, -817, -817,
-     -817, -817, -817, -817, -817, -817, -817, -817, -817, -817,
-     -817, -817, -817, -817, -817, -817, -817, -817, -817, -817,
-     -817, -817, -817, -817, -817, -817, -817, -817, -817, -817,
-     -817, -817, -817, -817, -817, -817, -817, -817, -817, -817,
-
-     -817, -817, -817, -817, -817, -817, -817, -817, -817, -817,
-     -817, -817, -817, -817, -817, -817, -817, -817, -817, -817,
-     -817, -817, -817, -817, -817, -817, -817, -817, -817, -817,
-     -817, -817, -817, -817, -817, -817, -817, -817
-    },
-
-    {
-       67, -818, -818, -818, -818, -818, -818, -818, -818, -818,
-     -818, -818, -818, -818, -818, -818, -818, -818, -818, -818,
-     -818, -818, -818, -818, -818, -818, -818, -818, -818, -818,
-     -818, -818,  846, -818, -818, -818, -818, -818, -818, -818,
-     -818, -818, -818, -818, -818, -818, -818, -818, -818, -818,
-     -818, -818, -818, -818, -818, -818, -818, -818, -818, -818,
-
-     -818, -818, -818, -818, -818, -818, -818, -818, -818, -818,
-     -818, -818, -818, -818, -818, -818, -818, -818, -818, -818,
-     -818, -818, -818, -818, -818, -818, -818, -818, -818, -818,
-     -818, -818, -818, -818, -818, -818, -818, -818, -818, -818,
-     -818, -818, -818, -818, -818, -818, -818, -818, -818, -818,
-     -818, -818, -818, -818, -818, -818, -818, -818, -818, -818,
-     -818, -818, -818, -818, -818, -818, -818, -818
-    },
-
-    {
-       67, -819, -819, -819, -819, -819, -819, -819, -819, -819,
-     -819, -819, -819, -819, -819, -819, -819, -819, -819, -819,
-     -819, -819, -819, -819, -819, -819, -819, -819, -819, -819,
-
-     -819, -819,  819, -819, -819, -819, -819, -819, -819, -819,
-     -819, -819, -819,  820, -819,  820, -819, -819,  821,  821,
-      821,  821,  821,  821,  821,  821,  821,  821, -819, -819,
-     -819, -819, -819, -819, -819, -819, -819, -819, -819, -819,
-     -819, -819, -819, -819, -819, -819, -819, -819, -819, -819,
-     -819, -819, -819, -819, -819, -819, -819, -819, -819, -819,
-     -819, -819, -819, -819, -819, -819, -819, -819, -819, -819,
-     -819, -819, -819, -819, -819, -819, -819, -819, -819, -819,
-     -819, -819, -819, -819, -819, -819, -819, -819, -819, -819,
-     -819, -819, -819, -819, -819, -819, -819, -819
-
-    },
-
-    {
-       67, -820, -820, -820, -820, -820, -820, -820, -820, -820,
-     -820, -820, -820, -820, -820, -820, -820, -820, -820, -820,
-     -820, -820, -820, -820, -820, -820, -820, -820, -820, -820,
-     -820, -820, -820, -820, -820, -820, -820, -820, -820, -820,
-     -820, -820, -820, -820, -820, -820, -820, -820,  821,  821,
-      821,  821,  821,  821,  821,  821,  821,  821, -820, -820,
-     -820, -820, -820, -820, -820, -820, -820, -820, -820, -820,
-     -820, -820, -820, -820, -820, -820, -820, -820, -820, -820,
-     -820, -820, -820, -820, -820, -820, -820, -820, -820, -820,
-     -820, -820, -820, -820, -820, -820, -820, -820, -820, -820,
-
-     -820, -820, -820, -820, -820, -820, -820, -820, -820, -820,
-     -820, -820, -820, -820, -820, -820, -820, -820, -820, -820,
-     -820, -820, -820, -820, -820, -820, -820, -820
-    },
-
-    {
-       67, -821, -821, -821, -821, -821, -821, -821, -821, -821,
-     -821, -821, -821, -821, -821, -821, -821, -821, -821, -821,
-     -821, -821, -821, -821, -821, -821, -821, -821, -821, -821,
-     -821, -821, -821, -821, -821, -821, -821, -821, -821, -821,
-     -821, -821, -821, -821, -821, -821, -821, -821,  821,  821,
-      821,  821,  821,  821,  821,  821,  821,  821, -821, -821,
-     -821, -821, -821, -821, -821, -821, -821, -821, -821, -821,
-
-     -821, -821, -821, -821, -821, -821, -821, -821, -821, -821,
-     -821, -821, -821, -821, -821, -821, -821, -821, -821, -821,
-     -821, -821, -821, -821, -821, -821, -821, -821, -821, -821,
-     -821, -821, -821, -821, -821, -821, -821, -821, -821, -821,
-     -821, -821, -821, -821, -821, -821, -821, -821, -821, -821,
-     -821, -821, -821, -821, -821, -821, -821, -821
-    },
-
-    {
-       67, -822, -822, -822, -822, -822, -822, -822, -822, -822,
-     -822, -822, -822, -822, -822, -822, -822, -822, -822, -822,
-     -822, -822, -822, -822, -822, -822, -822, -822, -822, -822,
-     -822, -822,  822, -822, -822, -822, -822, -822, -822, -822,
-
-     -822, -822, -822,  823, -822,  823, -822, -822,  824,  824,
-      824,  824,  824,  824,  824,  824,  824,  824, -822, -822,
-     -822, -822, -822, -822, -822, -822, -822, -822, -822, -822,
-     -822, -822, -822, -822, -822, -822, -822, -822, -822, -822,
-     -822, -822, -822, -822, -822, -822, -822, -822, -822, -822,
-     -822, -822, -822, -822, -822, -822, -822, -822, -822, -822,
-     -822, -822, -822, -822, -822, -822, -822, -822, -822, -822,
-     -822, -822, -822, -822, -822, -822, -822, -822, -822, -822,
-     -822, -822, -822, -822, -822, -822, -822, -822
-    },
-
-    {
-       67, -823, -823, -823, -823, -823, -823, -823, -823, -823,
-
-     -823, -823, -823, -823, -823, -823, -823, -823, -823, -823,
-     -823, -823, -823, -823, -823, -823, -823, -823, -823, -823,
-     -823, -823, -823, -823, -823, -823, -823, -823, -823, -823,
-     -823, -823, -823, -823, -823, -823, -823, -823,  824,  824,
-      824,  824,  824,  824,  824,  824,  824,  824, -823, -823,
-     -823, -823, -823, -823, -823, -823, -823, -823, -823, -823,
-     -823, -823, -823, -823, -823, -823, -823, -823, -823, -823,
-     -823, -823, -823, -823, -823, -823, -823, -823, -823, -823,
-     -823, -823, -823, -823, -823, -823, -823, -823, -823, -823,
-     -823, -823, -823, -823, -823, -823, -823, -823, -823, -823,
-
-     -823, -823, -823, -823, -823, -823, -823, -823, -823, -823,
-     -823, -823, -823, -823, -823, -823, -823, -823
-    },
-
-    {
-       67, -824, -824, -824, -824, -824, -824, -824, -824, -824,
-     -824, -824, -824, -824, -824, -824, -824, -824, -824, -824,
-     -824, -824, -824, -824, -824, -824, -824, -824, -824, -824,
-     -824, -824, -824, -824, -824, -824, -824, -824, -824, -824,
-     -824, -824, -824, -824, -824, -824, -824, -824,  824,  824,
-      824,  824,  824,  824,  824,  824,  824,  824, -824, -824,
-     -824, -824, -824, -824, -824, -824, -824, -824, -824, -824,
-     -824, -824, -824, -824, -824, -824, -824, -824, -824, -824,
-
-     -824, -824, -824, -824, -824, -824, -824, -824, -824, -824,
-     -824, -824, -824, -824, -824, -824, -824, -824, -824, -824,
-     -824, -824, -824, -824, -824, -824, -824, -824, -824, -824,
-     -824, -824, -824, -824, -824, -824, -824, -824, -824, -824,
-     -824, -824, -824, -824, -824, -824, -824, -824
-    },
-
-    {
-       67, -825, -825, -825, -825, -825, -825, -825, -825, -825,
-     -825, -825, -825, -825, -825, -825, -825, -825, -825, -825,
-     -825, -825, -825, -825, -825, -825, -825, -825, -825, -825,
-     -825, -825,  825, -825, -825, -825, -825, -825, -825, -825,
-     -825, -825, -825,  826, -825,  826, -825, -825,  827,  827,
-
-      827,  827,  827,  827,  827,  827,  827,  827, -825, -825,
-     -825, -825, -825, -825, -825, -825, -825, -825, -825, -825,
-     -825, -825, -825, -825, -825, -825, -825, -825, -825, -825,
-     -825, -825, -825, -825, -825, -825, -825, -825, -825, -825,
-     -825, -825, -825, -825, -825, -825, -825, -825, -825, -825,
-     -825, -825, -825, -825, -825, -825, -825, -825, -825, -825,
-     -825, -825, -825, -825, -825, -825, -825, -825, -825, -825,
-     -825, -825, -825, -825, -825, -825, -825, -825
-    },
-
-    {
-       67, -826, -826, -826, -826, -826, -826, -826, -826, -826,
-     -826, -826, -826, -826, -826, -826, -826, -826, -826, -826,
-
-     -826, -826, -826, -826, -826, -826, -826, -826, -826, -826,
-     -826, -826, -826, -826, -826, -826, -826, -826, -826, -826,
-     -826, -826, -826, -826, -826, -826, -826, -826,  827,  827,
-      827,  827,  827,  827,  827,  827,  827,  827, -826, -826,
-     -826, -826, -826, -826, -826, -826, -826, -826, -826, -826,
-     -826, -826, -826, -826, -826, -826, -826, -826, -826, -826,
-     -826, -826, -826, -826, -826, -826, -826, -826, -826, -826,
-     -826, -826, -826, -826, -826, -826, -826, -826, -826, -826,
-     -826, -826, -826, -826, -826, -826, -826, -826, -826, -826,
-     -826, -826, -826, -826, -826, -826, -826, -826, -826, -826,
-
-     -826, -826, -826, -826, -826, -826, -826, -826
-    },
-
-    {
-       67, -827, -827, -827, -827, -827, -827, -827, -827, -827,
-     -827, -827, -827, -827, -827, -827, -827, -827, -827, -827,
-     -827, -827, -827, -827, -827, -827, -827, -827, -827, -827,
-     -827, -827, -827, -827, -827, -827, -827, -827, -827, -827,
-     -827, -827, -827, -827, -827, -827, -827, -827,  827,  827,
-      827,  827,  827,  827,  827,  827,  827,  827, -827, -827,
-     -827, -827, -827, -827, -827, -827, -827, -827, -827, -827,
-     -827, -827, -827, -827, -827, -827, -827, -827, -827, -827,
-     -827, -827, -827, -827, -827, -827, -827, -827, -827, -827,
-
-     -827, -827, -827, -827, -827, -827, -827, -827, -827, -827,
-     -827, -827, -827, -827, -827, -827, -827, -827, -827, -827,
-     -827, -827, -827, -827, -827, -827, -827, -827, -827, -827,
-     -827, -827, -827, -827, -827, -827, -827, -827
-    },
-
-    {
-       67, -828, -828, -828, -828, -828, -828, -828, -828, -828,
-     -828, -828, -828, -828, -828, -828, -828, -828, -828, -828,
-     -828, -828, -828, -828, -828, -828, -828, -828, -828, -828,
-     -828, -828,  828, -828, -828, -828, -828, -828, -828, -828,
-     -828, -828, -828,  829, -828,  829, -828, -828,  830,  830,
-      830,  830,  830,  830,  830,  830,  830,  830, -828, -828,
-
-     -828, -828, -828, -828, -828, -828, -828, -828, -828, -828,
-     -828, -828, -828, -828, -828, -828, -828, -828, -828, -828,
-     -828, -828, -828, -828, -828, -828, -828, -828, -828, -828,
-     -828, -828, -828, -828, -828, -828, -828, -828, -828, -828,
-     -828, -828, -828, -828, -828, -828, -828, -828, -828, -828,
-     -828, -828, -828, -828, -828, -828, -828, -828, -828, -828,
-     -828, -828, -828, -828, -828, -828, -828, -828
-    },
-
-    {
-       67, -829, -829, -829, -829, -829, -829, -829, -829, -829,
-     -829, -829, -829, -829, -829, -829, -829, -829, -829, -829,
-     -829, -829, -829, -829, -829, -829, -829, -829, -829, -829,
-
-     -829, -829, -829, -829, -829, -829, -829, -829, -829, -829,
-     -829, -829, -829, -829, -829, -829, -829, -829,  830,  830,
-      830,  830,  830,  830,  830,  830,  830,  830, -829, -829,
-     -829, -829, -829, -829, -829, -829, -829, -829, -829, -829,
-     -829, -829, -829, -829, -829, -829, -829, -829, -829, -829,
-     -829, -829, -829, -829, -829, -829, -829, -829, -829, -829,
-     -829, -829, -829, -829, -829, -829, -829, -829, -829, -829,
-     -829, -829, -829, -829, -829, -829, -829, -829, -829, -829,
-     -829, -829, -829, -829, -829, -829, -829, -829, -829, -829,
-     -829, -829, -829, -829, -829, -829, -829, -829
-
-    },
-
-    {
-       67, -830, -830, -830, -830, -830, -830, -830, -830, -830,
-     -830, -830, -830, -830, -830, -830, -830, -830, -830, -830,
-     -830, -830, -830, -830, -830, -830, -830, -830, -830, -830,
-     -830, -830, -830, -830, -830, -830, -830, -830, -830, -830,
-     -830, -830, -830, -830, -830, -830, -830, -830,  830,  830,
-      830,  830,  830,  830,  830,  830,  830,  830, -830, -830,
-     -830, -830, -830, -830, -830, -830, -830, -830, -830, -830,
-     -830, -830, -830, -830, -830, -830, -830, -830, -830, -830,
-     -830, -830, -830, -830, -830, -830, -830, -830, -830, -830,
-     -830, -830, -830, -830, -830, -830, -830, -830, -830, -830,
-
-     -830, -830, -830, -830, -830, -830, -830, -830, -830, -830,
-     -830, -830, -830, -830, -830, -830, -830, -830, -830, -830,
-     -830, -830, -830, -830, -830, -830, -830, -830
-    },
-
-    {
-       67, -831, -831, -831, -831, -831, -831, -831, -831, -831,
-     -831, -831, -831, -831, -831, -831, -831, -831, -831, -831,
-     -831, -831, -831, -831, -831, -831, -831, -831, -831, -831,
-     -831, -831,  831, -831, -831, -831, -831, -831, -831, -831,
-     -831, -831, -831,  832, -831,  832, -831, -831,  833,  833,
-      833,  833,  833,  833,  833,  833,  833,  833, -831, -831,
-     -831, -831, -831, -831, -831, -831, -831, -831, -831, -831,
-
-     -831, -831, -831, -831, -831, -831, -831, -831, -831, -831,
-     -831, -831, -831, -831, -831, -831, -831, -831, -831, -831,
-     -831, -831, -831, -831, -831, -831, -831, -831, -831, -831,
-     -831, -831, -831, -831, -831, -831, -831, -831, -831, -831,
-     -831, -831, -831, -831, -831, -831, -831, -831, -831, -831,
-     -831, -831, -831, -831, -831, -831, -831, -831
-    },
-
-    {
-       67, -832, -832, -832, -832, -832, -832, -832, -832, -832,
-     -832, -832, -832, -832, -832, -832, -832, -832, -832, -832,
-     -832, -832, -832, -832, -832, -832, -832, -832, -832, -832,
-     -832, -832, -832, -832, -832, -832, -832, -832, -832, -832,
-
-     -832, -832, -832, -832, -832, -832, -832, -832,  833,  833,
-      833,  833,  833,  833,  833,  833,  833,  833, -832, -832,
-     -832, -832, -832, -832, -832, -832, -832, -832, -832, -832,
-     -832, -832, -832, -832, -832, -832, -832, -832, -832, -832,
-     -832, -832, -832, -832, -832, -832, -832, -832, -832, -832,
-     -832, -832, -832, -832, -832, -832, -832, -832, -832, -832,
-     -832, -832, -832, -832, -832, -832, -832, -832, -832, -832,
-     -832, -832, -832, -832, -832, -832, -832, -832, -832, -832,
-     -832, -832, -832, -832, -832, -832, -832, -832
-    },
-
-    {
-       67, -833, -833, -833, -833, -833, -833, -833, -833, -833,
-
-     -833, -833, -833, -833, -833, -833, -833, -833, -833, -833,
-     -833, -833, -833, -833, -833, -833, -833, -833, -833, -833,
-     -833, -833, -833, -833, -833, -833, -833, -833, -833, -833,
-     -833, -833, -833, -833, -833, -833, -833, -833,  833,  833,
-      833,  833,  833,  833,  833,  833,  833,  833, -833, -833,
-     -833, -833, -833, -833, -833, -833, -833, -833, -833, -833,
-     -833, -833, -833, -833, -833, -833, -833, -833, -833, -833,
-     -833, -833, -833, -833, -833, -833, -833, -833, -833, -833,
-     -833, -833, -833, -833, -833, -833, -833, -833, -833, -833,
-     -833, -833, -833, -833, -833, -833, -833, -833, -833, -833,
-
-     -833, -833, -833, -833, -833, -833, -833, -833, -833, -833,
-     -833, -833, -833, -833, -833, -833, -833, -833
-    },
-
-    {
-       67, -834, -834, -834, -834, -834, -834, -834, -834, -834,
-     -834, -834, -834, -834, -834, -834, -834, -834, -834, -834,
-     -834, -834, -834, -834, -834, -834, -834, -834, -834, -834,
-     -834, -834,  834, -834, -834, -834, -834, -834, -834,  835,
-     -834, -834, -834, -834, -834, -834, -834, -834, -834, -834,
-     -834, -834, -834, -834, -834, -834, -834, -834, -834, -834,
-     -834, -834, -834, -834, -834, -834, -834, -834, -834, -834,
-     -834, -834, -834, -834, -834, -834, -834, -834, -834, -834,
-
-     -834, -834, -834, -834, -834, -834, -834, -834, -834, -834,
-     -834, -834, -834, -834, -834, -834, -834, -834, -834, -834,
-     -834, -834, -834, -834, -834, -834, -834, -834, -834, -834,
-     -834, -834, -834, -834, -834, -834, -834, -834, -834, -834,
-     -834, -834, -834, -834, -834, -834, -834, -834
-    },
-
-    {
-       67,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  848,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847
-    },
-
-    {
-       67, -836, -836, -836, -836, -836, -836, -836, -836, -836,
-     -836, -836, -836, -836, -836, -836, -836, -836, -836, -836,
-
-     -836, -836, -836, -836, -836, -836, -836, -836, -836, -836,
-     -836, -836,  836, -836, -836, -836, -836, -836, -836,  837,
-     -836, -836, -836, -836, -836, -836, -836, -836, -836, -836,
-     -836, -836, -836, -836, -836, -836, -836, -836, -836, -836,
-     -836, -836, -836, -836, -836, -836, -836, -836, -836, -836,
-     -836, -836, -836, -836, -836, -836, -836, -836, -836, -836,
-     -836, -836, -836, -836, -836, -836, -836, -836, -836, -836,
-     -836, -836, -836, -836, -836, -836, -836, -836, -836, -836,
-     -836, -836, -836, -836, -836, -836, -836, -836, -836, -836,
-     -836, -836, -836, -836, -836, -836, -836, -836, -836, -836,
-
-     -836, -836, -836, -836, -836, -836, -836, -836
-    },
-
-    {
-       67,  849,  849,  849,  849,  849,  849,  849,  849,  849,
-      849,  849,  849,  849,  849,  849,  849,  849,  849,  849,
-      849,  849,  849,  849,  849,  849,  849,  849,  849,  849,
-      849,  849,  849,  849,  849,  849,  849,  849,  849,  850,
-      849,  849,  849,  849,  849,  849,  849,  849,  849,  849,
-      849,  849,  849,  849,  849,  849,  849,  849,  849,  849,
-      849,  849,  849,  849,  849,  849,  849,  849,  849,  849,
-      849,  849,  849,  849,  849,  849,  849,  849,  849,  849,
-      849,  849,  849,  849,  849,  849,  849,  849,  849,  849,
-
-      849,  849,  849,  849,  849,  849,  849,  849,  849,  849,
-      849,  849,  849,  849,  849,  849,  849,  849,  849,  849,
-      849,  849,  849,  849,  849,  849,  849,  849,  849,  849,
-      849,  849,  849,  849,  849,  849,  849,  849
-    },
-
-    {
-       67, -838, -838, -838, -838, -838, -838, -838, -838, -838,
-     -838, -838, -838, -838, -838, -838, -838, -838, -838, -838,
-     -838, -838, -838, -838, -838, -838, -838, -838, -838, -838,
-     -838, -838,  838, -838, -838, -838, -838, -838, -838,  839,
-     -838, -838, -838, -838, -838, -838, -838, -838, -838, -838,
-     -838, -838, -838, -838, -838, -838, -838, -838, -838, -838,
-
-     -838, -838, -838, -838, -838, -838, -838, -838, -838, -838,
-     -838, -838, -838, -838, -838, -838, -838, -838, -838, -838,
-     -838, -838, -838, -838, -838, -838, -838, -838, -838, -838,
-     -838, -838, -838, -838, -838, -838, -838, -838, -838, -838,
-     -838, -838, -838, -838, -838, -838, -838, -838, -838, -838,
-     -838, -838, -838, -838, -838, -838, -838, -838, -838, -838,
-     -838, -838, -838, -838, -838, -838, -838, -838
-    },
-
-    {
-       67,  851,  851,  851,  851,  851,  851,  851,  851,  851,
-      851,  851,  851,  851,  851,  851,  851,  851,  851,  851,
-      851,  851,  851,  851,  851,  851,  851,  851,  851,  851,
-
-      851,  851,  851,  851,  851,  851,  851,  851,  851,  852,
-      851,  851,  851,  851,  851,  851,  851,  851,  851,  851,
-      851,  851,  851,  851,  851,  851,  851,  851,  851,  851,
-      851,  851,  851,  851,  851,  851,  851,  851,  851,  851,
-      851,  851,  851,  851,  851,  851,  851,  851,  851,  851,
-      851,  851,  851,  851,  851,  851,  851,  851,  851,  851,
-      851,  851,  851,  851,  851,  851,  851,  851,  851,  851,
-      851,  851,  851,  851,  851,  851,  851,  851,  851,  851,
-      851,  851,  851,  851,  851,  851,  851,  851,  851,  851,
-      851,  851,  851,  851,  851,  851,  851,  851
-
-    },
-
-    {
-       67, -840, -840, -840, -840, -840, -840, -840, -840, -840,
-     -840, -840, -840, -840, -840, -840, -840, -840, -840, -840,
-     -840, -840, -840, -840, -840, -840, -840, -840, -840, -840,
-     -840, -840,  840, -840, -840, -840, -840, -840, -840,  841,
-     -840, -840, -840, -840, -840, -840, -840, -840, -840, -840,
-     -840, -840, -840, -840, -840, -840, -840, -840, -840, -840,
-     -840, -840, -840, -840, -840, -840, -840, -840, -840, -840,
-     -840, -840, -840, -840, -840, -840, -840, -840, -840, -840,
-     -840, -840, -840, -840, -840, -840, -840, -840, -840, -840,
-     -840, -840, -840, -840, -840, -840, -840, -840, -840, -840,
-
-     -840, -840, -840, -840, -840, -840, -840, -840, -840, -840,
-     -840, -840, -840, -840, -840, -840, -840, -840, -840, -840,
-     -840, -840, -840, -840, -840, -840, -840, -840
-    },
-
-    {
-       67,  853,  853,  853,  853,  853,  853,  853,  853,  853,
-      853,  853,  853,  853,  853,  853,  853,  853,  853,  853,
-      853,  853,  853,  853,  853,  853,  853,  853,  853,  853,
-      853,  853,  853,  853,  853,  853,  853,  853,  853,  854,
-      853,  853,  853,  853,  853,  853,  853,  853,  853,  853,
-      853,  853,  853,  853,  853,  853,  853,  853,  853,  853,
-      853,  853,  853,  853,  853,  853,  853,  853,  853,  853,
-
-      853,  853,  853,  853,  853,  853,  853,  853,  853,  853,
-      853,  853,  853,  853,  853,  853,  853,  853,  853,  853,
-      853,  853,  853,  853,  853,  853,  853,  853,  853,  853,
-      853,  853,  853,  853,  853,  853,  853,  853,  853,  853,
-      853,  853,  853,  853,  853,  853,  853,  853,  853,  853,
-      853,  853,  853,  853,  853,  853,  853,  853
-    },
-
-    {
-       67, -842, -842, -842, -842, -842, -842, -842, -842, -842,
-     -842, -842, -842, -842, -842, -842, -842, -842, -842, -842,
-     -842, -842, -842, -842, -842, -842, -842, -842, -842, -842,
-     -842, -842,  842, -842, -842, -842, -842, -842, -842,  843,
-
-     -842, -842, -842, -842, -842, -842, -842, -842, -842, -842,
-     -842, -842, -842, -842, -842, -842, -842, -842, -842, -842,
-     -842, -842, -842, -842, -842, -842, -842, -842, -842, -842,
-     -842, -842, -842, -842, -842, -842, -842, -842, -842, -842,
-     -842, -842, -842, -842, -842, -842, -842, -842, -842, -842,
-     -842, -842, -842, -842, -842, -842, -842, -842, -842, -842,
-     -842, -842, -842, -842, -842, -842, -842, -842, -842, -842,
-     -842, -842, -842, -842, -842, -842, -842, -842, -842, -842,
-     -842, -842, -842, -842, -842, -842, -842, -842
-    },
-
-    {
-       67,  855,  855,  855,  855,  855,  855,  855,  855,  855,
-
-      855,  855,  855,  855,  855,  855,  855,  855,  855,  855,
-      855,  855,  855,  855,  855,  855,  855,  855,  855,  855,
-      855,  855,  855,  855,  855,  855,  855,  855,  855,  856,
-      855,  855,  855,  855,  855,  855,  855,  855,  855,  855,
-      855,  855,  855,  855,  855,  855,  855,  855,  855,  855,
-      855,  855,  855,  855,  855,  855,  855,  855,  855,  855,
-      855,  855,  855,  855,  855,  855,  855,  855,  855,  855,
-      855,  855,  855,  855,  855,  855,  855,  855,  855,  855,
-      855,  855,  855,  855,  855,  855,  855,  855,  855,  855,
-      855,  855,  855,  855,  855,  855,  855,  855,  855,  855,
-
-      855,  855,  855,  855,  855,  855,  855,  855,  855,  855,
-      855,  855,  855,  855,  855,  855,  855,  855
-    },
-
-    {
-       67, -844, -844, -844, -844, -844, -844, -844, -844, -844,
-     -844, -844, -844, -844, -844, -844, -844, -844, -844, -844,
-     -844, -844, -844, -844, -844, -844, -844, -844, -844, -844,
-     -844, -844,  844, -844, -844, -844, -844, -844, -844,  845,
-     -844, -844, -844, -844, -844, -844, -844, -844, -844, -844,
-     -844, -844, -844, -844, -844, -844, -844, -844, -844, -844,
-     -844, -844, -844, -844, -844, -844, -844, -844, -844, -844,
-     -844, -844, -844, -844, -844, -844, -844, -844, -844, -844,
-
-     -844, -844, -844, -844, -844, -844, -844, -844, -844, -844,
-     -844, -844, -844, -844, -844, -844, -844, -844, -844, -844,
-     -844, -844, -844, -844, -844, -844, -844, -844, -844, -844,
-     -844, -844, -844, -844, -844, -844, -844, -844, -844, -844,
-     -844, -844, -844, -844, -844, -844, -844, -844
-    },
-
-    {
-       67,  857,  857,  857,  857,  857,  857,  857,  857,  857,
-      857,  857,  857,  857,  857,  857,  857,  857,  857,  857,
-      857,  857,  857,  857,  857,  857,  857,  857,  857,  857,
-      857,  857,  857,  857,  857,  857,  857,  857,  857,  858,
-      857,  857,  857,  857,  857,  857,  857,  857,  857,  857,
-
-      857,  857,  857,  857,  857,  857,  857,  857,  857,  857,
-      857,  857,  857,  857,  857,  857,  857,  857,  857,  857,
-      857,  857,  857,  857,  857,  857,  857,  857,  857,  857,
-      857,  857,  857,  857,  857,  857,  857,  857,  857,  857,
-      857,  857,  857,  857,  857,  857,  857,  857,  857,  857,
-      857,  857,  857,  857,  857,  857,  857,  857,  857,  857,
-      857,  857,  857,  857,  857,  857,  857,  857,  857,  857,
-      857,  857,  857,  857,  857,  857,  857,  857
-    },
-
-    {
-       67, -846, -846, -846, -846, -846, -846, -846, -846, -846,
-     -846, -846, -846, -846, -846, -846, -846, -846, -846, -846,
-
-     -846, -846, -846, -846, -846, -846, -846, -846, -846, -846,
-     -846, -846,  859, -846, -846, -846, -846, -846, -846, -846,
-     -846, -846, -846, -846, -846, -846, -846, -846, -846, -846,
-     -846, -846, -846, -846, -846, -846, -846, -846, -846, -846,
-     -846, -846, -846, -846, -846, -846, -846, -846, -846, -846,
-     -846, -846, -846, -846, -846, -846, -846, -846, -846, -846,
-     -846, -846, -846, -846, -846, -846, -846, -846, -846, -846,
-     -846, -846, -846, -846, -846, -846, -846, -846, -846, -846,
-     -846, -846, -846, -846, -846, -846, -846, -846, -846, -846,
-     -846, -846, -846, -846, -846, -846, -846, -846, -846, -846,
-
-     -846, -846, -846, -846, -846, -846, -846, -846
-    },
-
-    {
-       67,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  848,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
-      847,  847,  847,  847,  847,  847,  847,  847
-    },
-
-    {
-       67, -848, -848, -848, -848, -848, -848, -848, -848, -848,
-     -848, -848, -848, -848, -848, -848, -848, -848, -848, -848,
-     -848, -848, -848, -848, -848, -848, -848, -848, -848, -848,
-     -848, -848, -848, -848, -848, -848, -848, -848, -848,  847,
-     -848, -848, -848, -848, -848, -848, -848, -848, -848, -848,
-     -848, -848, -848, -848, -848, -848, -848, -848, -848, -848,
-
-     -848, -848, -848, -848, -848, -848, -848, -848, -848, -848,
-     -848, -848, -848, -848, -848, -848, -848, -848, -848, -848,
-     -848, -848, -848, -848, -848, -848, -848, -848, -848, -848,
-     -848, -848, -848, -848, -848, -848, -848, -848, -848, -848,
-     -848, -848, -848, -848, -848, -848, -848, -848, -848, -848,
-     -848, -848, -848, -848, -848, -848, -848, -848, -848, -848,
-     -848, -848, -848, -848, -848, -848, -848, -848
-    },
-
-    {
-       67,  849,  849,  849,  849,  849,  849,  849,  849,  849,
-      849,  849,  849,  849,  849,  849,  849,  849,  849,  849,
-      849,  849,  849,  849,  849,  849,  849,  849,  849,  849,
-
-      849,  849,  849,  849,  849,  849,  849,  849,  849,  850,
-      849,  849,  849,  849,  849,  849,  849,  849,  849,  849,
-      849,  849,  849,  849,  849,  849,  849,  849,  849,  849,
-      849,  849,  849,  849,  849,  849,  849,  849,  849,  849,
-      849,  849,  849,  849,  849,  849,  849,  849,  849,  849,
-      849,  849,  849,  849,  849,  849,  849,  849,  849,  849,
-      849,  849,  849,  849,  849,  849,  849,  849,  849,  849,
-      849,  849,  849,  849,  849,  849,  849,  849,  849,  849,
-      849,  849,  849,  849,  849,  849,  849,  849,  849,  849,
-      849,  849,  849,  849,  849,  849,  849,  849
-
-    },
-
-    {
-       67, -850, -850, -850, -850, -850, -850, -850, -850, -850,
-     -850, -850, -850, -850, -850, -850, -850, -850, -850, -850,
-     -850, -850, -850, -850, -850, -850, -850, -850, -850, -850,
-     -850, -850, -850, -850, -850, -850, -850, -850, -850,  849,
-     -850, -850, -850, -850, -850, -850, -850, -850, -850, -850,
-     -850, -850, -850, -850, -850, -850, -850, -850, -850, -850,
-     -850, -850, -850, -850, -850, -850, -850, -850, -850, -850,
-     -850, -850, -850, -850, -850, -850, -850, -850, -850, -850,
-     -850, -850, -850, -850, -850, -850, -850, -850, -850, -850,
-     -850, -850, -850, -850, -850, -850, -850, -850, -850, -850,
-
-     -850, -850, -850, -850, -850, -850, -850, -850, -850, -850,
-     -850, -850, -850, -850, -850, -850, -850, -850, -850, -850,
-     -850, -850, -850, -850, -850, -850, -850, -850
-    },
-
-    {
-       67,  851,  851,  851,  851,  851,  851,  851,  851,  851,
-      851,  851,  851,  851,  851,  851,  851,  851,  851,  851,
-      851,  851,  851,  851,  851,  851,  851,  851,  851,  851,
-      851,  851,  851,  851,  851,  851,  851,  851,  851,  852,
-      851,  851,  851,  851,  851,  851,  851,  851,  851,  851,
-      851,  851,  851,  851,  851,  851,  851,  851,  851,  851,
-      851,  851,  851,  851,  851,  851,  851,  851,  851,  851,
-
-      851,  851,  851,  851,  851,  851,  851,  851,  851,  851,
-      851,  851,  851,  851,  851,  851,  851,  851,  851,  851,
-      851,  851,  851,  851,  851,  851,  851,  851,  851,  851,
-      851,  851,  851,  851,  851,  851,  851,  851,  851,  851,
-      851,  851,  851,  851,  851,  851,  851,  851,  851,  851,
-      851,  851,  851,  851,  851,  851,  851,  851
-    },
-
-    {
-       67, -852, -852, -852, -852, -852, -852, -852, -852, -852,
-     -852, -852, -852, -852, -852, -852, -852, -852, -852, -852,
-     -852, -852, -852, -852, -852, -852, -852, -852, -852, -852,
-     -852, -852, -852, -852, -852, -852, -852, -852, -852,  851,
-
-     -852, -852, -852, -852, -852, -852, -852, -852, -852, -852,
-     -852, -852, -852, -852, -852, -852, -852, -852, -852, -852,
-     -852, -852, -852, -852, -852, -852, -852, -852, -852, -852,
-     -852, -852, -852, -852, -852, -852, -852, -852, -852, -852,
-     -852, -852, -852, -852, -852, -852, -852, -852, -852, -852,
-     -852, -852, -852, -852, -852, -852, -852, -852, -852, -852,
-     -852, -852, -852, -852, -852, -852, -852, -852, -852, -852,
-     -852, -852, -852, -852, -852, -852, -852, -852, -852, -852,
-     -852, -852, -852, -852, -852, -852, -852, -852
-    },
-
-    {
-       67,  853,  853,  853,  853,  853,  853,  853,  853,  853,
-
-      853,  853,  853,  853,  853,  853,  853,  853,  853,  853,
-      853,  853,  853,  853,  853,  853,  853,  853,  853,  853,
-      853,  853,  853,  853,  853,  853,  853,  853,  853,  854,
-      853,  853,  853,  853,  853,  853,  853,  853,  853,  853,
-      853,  853,  853,  853,  853,  853,  853,  853,  853,  853,
-      853,  853,  853,  853,  853,  853,  853,  853,  853,  853,
-      853,  853,  853,  853,  853,  853,  853,  853,  853,  853,
-      853,  853,  853,  853,  853,  853,  853,  853,  853,  853,
-      853,  853,  853,  853,  853,  853,  853,  853,  853,  853,
-      853,  853,  853,  853,  853,  853,  853,  853,  853,  853,
-
-      853,  853,  853,  853,  853,  853,  853,  853,  853,  853,
-      853,  853,  853,  853,  853,  853,  853,  853
-    },
-
-    {
-       67, -854, -854, -854, -854, -854, -854, -854, -854, -854,
-     -854, -854, -854, -854, -854, -854, -854, -854, -854, -854,
-     -854, -854, -854, -854, -854, -854, -854, -854, -854, -854,
-     -854, -854, -854, -854, -854, -854, -854, -854, -854,  853,
-     -854, -854, -854, -854, -854, -854, -854, -854, -854, -854,
-     -854, -854, -854, -854, -854, -854, -854, -854, -854, -854,
-     -854, -854, -854, -854, -854, -854, -854, -854, -854, -854,
-     -854, -854, -854, -854, -854, -854, -854, -854, -854, -854,
-
-     -854, -854, -854, -854, -854, -854, -854, -854, -854, -854,
-     -854, -854, -854, -854, -854, -854, -854, -854, -854, -854,
-     -854, -854, -854, -854, -854, -854, -854, -854, -854, -854,
-     -854, -854, -854, -854, -854, -854, -854, -854, -854, -854,
-     -854, -854, -854, -854, -854, -854, -854, -854
-    },
-
-    {
-       67,  855,  855,  855,  855,  855,  855,  855,  855,  855,
-      855,  855,  855,  855,  855,  855,  855,  855,  855,  855,
-      855,  855,  855,  855,  855,  855,  855,  855,  855,  855,
-      855,  855,  855,  855,  855,  855,  855,  855,  855,  856,
-      855,  855,  855,  855,  855,  855,  855,  855,  855,  855,
-
-      855,  855,  855,  855,  855,  855,  855,  855,  855,  855,
-      855,  855,  855,  855,  855,  855,  855,  855,  855,  855,
-      855,  855,  855,  855,  855,  855,  855,  855,  855,  855,
-      855,  855,  855,  855,  855,  855,  855,  855,  855,  855,
-      855,  855,  855,  855,  855,  855,  855,  855,  855,  855,
-      855,  855,  855,  855,  855,  855,  855,  855,  855,  855,
-      855,  855,  855,  855,  855,  855,  855,  855,  855,  855,
-      855,  855,  855,  855,  855,  855,  855,  855
-    },
-
-    {
-       67, -856, -856, -856, -856, -856, -856, -856, -856, -856,
-     -856, -856, -856, -856, -856, -856, -856, -856, -856, -856,
-
-     -856, -856, -856, -856, -856, -856, -856, -856, -856, -856,
-     -856, -856, -856, -856, -856, -856, -856, -856, -856,  855,
-     -856, -856, -856, -856, -856, -856, -856, -856, -856, -856,
-     -856, -856, -856, -856, -856, -856, -856, -856, -856, -856,
-     -856, -856, -856, -856, -856, -856, -856, -856, -856, -856,
-     -856, -856, -856, -856, -856, -856, -856, -856, -856, -856,
-     -856, -856, -856, -856, -856, -856, -856, -856, -856, -856,
-     -856, -856, -856, -856, -856, -856, -856, -856, -856, -856,
-     -856, -856, -856, -856, -856, -856, -856, -856, -856, -856,
-     -856, -856, -856, -856, -856, -856, -856, -856, -856, -856,
-
-     -856, -856, -856, -856, -856, -856, -856, -856
-    },
-
-    {
-       67,  857,  857,  857,  857,  857,  857,  857,  857,  857,
-      857,  857,  857,  857,  857,  857,  857,  857,  857,  857,
-      857,  857,  857,  857,  857,  857,  857,  857,  857,  857,
-      857,  857,  857,  857,  857,  857,  857,  857,  857,  858,
-      857,  857,  857,  857,  857,  857,  857,  857,  857,  857,
-      857,  857,  857,  857,  857,  857,  857,  857,  857,  857,
-      857,  857,  857,  857,  857,  857,  857,  857,  857,  857,
-      857,  857,  857,  857,  857,  857,  857,  857,  857,  857,
-      857,  857,  857,  857,  857,  857,  857,  857,  857,  857,
-
-      857,  857,  857,  857,  857,  857,  857,  857,  857,  857,
-      857,  857,  857,  857,  857,  857,  857,  857,  857,  857,
-      857,  857,  857,  857,  857,  857,  857,  857,  857,  857,
-      857,  857,  857,  857,  857,  857,  857,  857
-    },
-
-    {
-       67, -858, -858, -858, -858, -858, -858, -858, -858, -858,
-     -858, -858, -858, -858, -858, -858, -858, -858, -858, -858,
-     -858, -858, -858, -858, -858, -858, -858, -858, -858, -858,
-     -858, -858, -858, -858, -858, -858, -858, -858, -858,  857,
-     -858, -858, -858, -858, -858, -858, -858, -858, -858, -858,
-     -858, -858, -858, -858, -858, -858, -858, -858, -858, -858,
-
-     -858, -858, -858, -858, -858, -858, -858, -858, -858, -858,
-     -858, -858, -858, -858, -858, -858, -858, -858, -858, -858,
-     -858, -858, -858, -858, -858, -858, -858, -858, -858, -858,
-     -858, -858, -858, -858, -858, -858, -858, -858, -858, -858,
-     -858, -858, -858, -858, -858, -858, -858, -858, -858, -858,
-     -858, -858, -858, -858, -858, -858, -858, -858, -858, -858,
-     -858, -858, -858, -858, -858, -858, -858, -858
-    },
-
-    {
-       67, -859, -859, -859, -859, -859, -859, -859, -859, -859,
-     -859, -859, -859, -859, -859, -859, -859, -859, -859, -859,
-     -859, -859, -859, -859, -859, -859, -859, -859, -859, -859,
-
-     -859, -859,  860, -859, -859, -859, -859, -859, -859, -859,
-     -859, -859, -859, -859, -859, -859, -859, -859, -859, -859,
-     -859, -859, -859, -859, -859, -859, -859, -859, -859, -859,
-     -859, -859, -859, -859, -859, -859, -859, -859, -859, -859,
-     -859, -859, -859, -859, -859, -859, -859, -859, -859, -859,
-     -859, -859, -859, -859, -859, -859, -859, -859, -859, -859,
-     -859, -859, -859, -859, -859, -859, -859, -859, -859, -859,
-     -859, -859, -859, -859, -859, -859, -859, -859, -859, -859,
-     -859, -859, -859, -859, -859, -859, -859, -859, -859, -859,
-     -859, -859, -859, -859, -859, -859, -859, -859
-
-    },
-
-    {
-       67, -860, -860, -860, -860, -860, -860, -860, -860, -860,
-     -860, -860, -860, -860, -860, -860, -860, -860, -860, -860,
-     -860, -860, -860, -860, -860, -860, -860, -860, -860, -860,
-     -860, -860,  861, -860, -860, -860, -860, -860, -860, -860,
-     -860, -860, -860, -860, -860, -860, -860, -860, -860, -860,
-     -860, -860, -860, -860, -860, -860, -860, -860, -860, -860,
-     -860, -860, -860, -860, -860, -860, -860, -860, -860, -860,
-     -860, -860, -860, -860, -860, -860, -860, -860, -860, -860,
-     -860, -860, -860, -860, -860, -860, -860, -860, -860, -860,
-     -860, -860, -860, -860, -860, -860, -860, -860, -860, -860,
-
-     -860, -860, -860, -860, -860, -860, -860, -860, -860, -860,
-     -860, -860, -860, -860, -860, -860, -860, -860, -860, -860,
-     -860, -860, -860, -860, -860, -860, -860, -860
-    },
-
-    {
-       67, -861, -861, -861, -861, -861, -861, -861, -861, -861,
-     -861, -861, -861, -861, -861, -861, -861, -861, -861, -861,
-     -861, -861, -861, -861, -861, -861, -861, -861, -861, -861,
-     -861, -861,  862, -861, -861, -861, -861, -861, -861, -861,
-     -861, -861, -861, -861, -861, -861, -861, -861, -861, -861,
-     -861, -861, -861, -861, -861, -861, -861, -861, -861, -861,
-     -861, -861, -861, -861, -861, -861, -861, -861, -861, -861,
-
-     -861, -861, -861, -861, -861, -861, -861, -861, -861, -861,
-     -861, -861, -861, -861, -861, -861, -861, -861, -861, -861,
-     -861, -861, -861, -861, -861, -861, -861, -861, -861, -861,
-     -861, -861, -861, -861, -861, -861, -861, -861, -861, -861,
-     -861, -861, -861, -861, -861, -861, -861, -861, -861, -861,
-     -861, -861, -861, -861, -861, -861, -861, -861
-    },
-
-    {
-       67, -862, -862, -862, -862, -862, -862, -862, -862, -862,
-     -862, -862, -862, -862, -862, -862, -862, -862, -862, -862,
-     -862, -862, -862, -862, -862, -862, -862, -862, -862, -862,
-     -862, -862,  863, -862, -862, -862, -862, -862, -862, -862,
-
-     -862, -862, -862, -862, -862, -862, -862, -862, -862, -862,
-     -862, -862, -862, -862, -862, -862, -862, -862, -862, -862,
-     -862, -862, -862, -862, -862, -862, -862, -862, -862, -862,
-     -862, -862, -862, -862, -862, -862, -862, -862, -862, -862,
-     -862, -862, -862, -862, -862, -862, -862, -862, -862, -862,
-     -862, -862, -862, -862, -862, -862, -862, -862, -862, -862,
-     -862, -862, -862, -862, -862, -862, -862, -862, -862, -862,
-     -862, -862, -862, -862, -862, -862, -862, -862, -862, -862,
-     -862, -862, -862, -862, -862, -862, -862, -862
-    },
-
-    {
-       67, -863, -863, -863, -863, -863, -863, -863, -863, -863,
-
-     -863, -863, -863, -863, -863, -863, -863, -863, -863, -863,
-     -863, -863, -863, -863, -863, -863, -863, -863, -863, -863,
-     -863, -863,  864, -863, -863, -863, -863, -863, -863, -863,
-     -863, -863, -863, -863, -863, -863, -863, -863, -863, -863,
-     -863, -863, -863, -863, -863, -863, -863, -863, -863, -863,
-     -863, -863, -863, -863, -863, -863, -863, -863, -863, -863,
-     -863, -863, -863, -863, -863, -863, -863, -863, -863, -863,
-     -863, -863, -863, -863, -863, -863, -863, -863, -863, -863,
-     -863, -863, -863, -863, -863, -863, -863, -863, -863, -863,
-     -863, -863, -863, -863, -863, -863, -863, -863, -863, -863,
-
-     -863, -863, -863, -863, -863, -863, -863, -863, -863, -863,
-     -863, -863, -863, -863, -863, -863, -863, -863
-    },
-
-    {
-       67, -864, -864, -864, -864, -864, -864, -864, -864, -864,
-     -864, -864, -864, -864, -864, -864, -864, -864, -864, -864,
-     -864, -864, -864, -864, -864, -864, -864, -864, -864, -864,
-     -864, -864,  865, -864, -864, -864, -864, -864, -864, -864,
-     -864, -864, -864, -864, -864, -864, -864, -864, -864, -864,
-     -864, -864, -864, -864, -864, -864, -864, -864, -864, -864,
-     -864, -864, -864, -864, -864, -864, -864, -864, -864, -864,
-     -864, -864, -864, -864, -864, -864, -864, -864, -864, -864,
-
-     -864, -864, -864, -864, -864, -864, -864, -864, -864, -864,
-     -864, -864, -864, -864, -864, -864, -864, -864, -864, -864,
-     -864, -864, -864, -864, -864, -864, -864, -864, -864, -864,
-     -864, -864, -864, -864, -864, -864, -864, -864, -864, -864,
-     -864, -864, -864, -864, -864, -864, -864, -864
-    },
-
-    {
-       67, -865, -865, -865, -865, -865, -865, -865, -865, -865,
-     -865, -865, -865, -865, -865, -865, -865, -865, -865, -865,
-     -865, -865, -865, -865, -865, -865, -865, -865, -865, -865,
-     -865, -865,  866, -865, -865, -865, -865, -865, -865, -865,
-     -865, -865, -865, -865, -865, -865, -865, -865, -865, -865,
-
-     -865, -865, -865, -865, -865, -865, -865, -865, -865, -865,
-     -865, -865, -865, -865, -865, -865, -865, -865, -865, -865,
-     -865, -865, -865, -865, -865, -865, -865, -865, -865, -865,
-     -865, -865, -865, -865, -865, -865, -865, -865, -865, -865,
-     -865, -865, -865, -865, -865, -865, -865, -865, -865, -865,
-     -865, -865, -865, -865, -865, -865, -865, -865, -865, -865,
-     -865, -865, -865, -865, -865, -865, -865, -865, -865, -865,
-     -865, -865, -865, -865, -865, -865, -865, -865
-    },
-
-    {
-       67, -866, -866, -866, -866, -866, -866, -866, -866, -866,
-     -866, -866, -866, -866, -866, -866, -866, -866, -866, -866,
-
-     -866, -866, -866, -866, -866, -866, -866, -866, -866, -866,
-     -866, -866,  867, -866, -866, -866, -866, -866, -866, -866,
-     -866, -866, -866, -866, -866, -866, -866, -866, -866, -866,
-     -866, -866, -866, -866, -866, -866, -866, -866, -866, -866,
-     -866, -866, -866, -866, -866, -866, -866, -866, -866, -866,
-     -866, -866, -866, -866, -866, -866, -866, -866, -866, -866,
-     -866, -866, -866, -866, -866, -866, -866, -866, -866, -866,
-     -866, -866, -866, -866, -866, -866, -866, -866, -866, -866,
-     -866, -866, -866, -866, -866, -866, -866, -866, -866, -866,
-     -866, -866, -866, -866, -866, -866, -866, -866, -866, -866,
-
-     -866, -866, -866, -866, -866, -866, -866, -866
-    },
-
-    {
-       67, -867, -867, -867, -867, -867, -867, -867, -867, -867,
-     -867, -867, -867, -867, -867, -867, -867, -867, -867, -867,
-     -867, -867, -867, -867, -867, -867, -867, -867, -867, -867,
-     -867, -867,  868, -867, -867, -867, -867, -867, -867, -867,
-     -867, -867, -867, -867, -867, -867, -867, -867, -867, -867,
-     -867, -867, -867, -867, -867, -867, -867, -867, -867, -867,
-     -867, -867, -867, -867, -867, -867, -867, -867, -867, -867,
-     -867, -867, -867, -867, -867, -867, -867, -867, -867, -867,
-     -867, -867, -867, -867, -867, -867, -867, -867, -867, -867,
-
-     -867, -867, -867, -867, -867, -867, -867, -867, -867, -867,
-     -867, -867, -867, -867, -867, -867, -867, -867, -867, -867,
-     -867, -867, -867, -867, -867, -867, -867, -867, -867, -867,
-     -867, -867, -867, -867, -867, -867, -867, -867
-    },
-
-    {
-       67, -868, -868, -868, -868, -868, -868, -868, -868, -868,
-     -868, -868, -868, -868, -868, -868, -868, -868, -868, -868,
-     -868, -868, -868, -868, -868, -868, -868, -868, -868, -868,
-     -868, -868,  869, -868, -868, -868, -868, -868, -868, -868,
-     -868, -868, -868, -868, -868, -868, -868, -868, -868, -868,
-     -868, -868, -868, -868, -868, -868, -868, -868, -868, -868,
-
-     -868, -868, -868, -868, -868, -868, -868, -868, -868, -868,
-     -868, -868, -868, -868, -868, -868, -868, -868, -868, -868,
-     -868, -868, -868, -868, -868, -868, -868, -868, -868, -868,
-     -868, -868, -868, -868, -868, -868, -868, -868, -868, -868,
-     -868, -868, -868, -868, -868, -868, -868, -868, -868, -868,
-     -868, -868, -868, -868, -868, -868, -868, -868, -868, -868,
-     -868, -868, -868, -868, -868, -868, -868, -868
-    },
-
-    {
-       67, -869, -869, -869, -869, -869, -869, -869, -869, -869,
-     -869, -869, -869, -869, -869, -869, -869, -869, -869, -869,
-     -869, -869, -869, -869, -869, -869, -869, -869, -869, -869,
-
-     -869, -869,  870, -869, -869, -869, -869, -869, -869, -869,
-     -869, -869, -869, -869, -869, -869, -869, -869, -869, -869,
-     -869, -869, -869, -869, -869, -869, -869, -869, -869, -869,
-     -869, -869, -869, -869, -869, -869, -869, -869, -869, -869,
-     -869, -869, -869, -869, -869, -869, -869, -869, -869, -869,
-     -869, -869, -869, -869, -869, -869, -869, -869, -869, -869,
-     -869, -869, -869, -869, -869, -869, -869, -869, -869, -869,
-     -869, -869, -869, -869, -869, -869, -869, -869, -869, -869,
-     -869, -869, -869, -869, -869, -869, -869, -869, -869, -869,
-     -869, -869, -869, -869, -869, -869, -869, -869
-
-    },
-
-    {
-       67, -870, -870, -870, -870, -870, -870, -870, -870, -870,
-     -870, -870, -870, -870, -870, -870, -870, -870, -870, -870,
-     -870, -870, -870, -870, -870, -870, -870, -870, -870, -870,
-     -870, -870,  871, -870, -870, -870, -870, -870, -870, -870,
-     -870, -870, -870, -870, -870, -870, -870, -870, -870, -870,
-     -870, -870, -870, -870, -870, -870, -870, -870, -870, -870,
-     -870, -870, -870, -870, -870, -870, -870, -870, -870, -870,
-     -870, -870, -870, -870, -870, -870, -870, -870, -870, -870,
-     -870, -870, -870, -870, -870, -870, -870, -870, -870, -870,
-     -870, -870, -870, -870, -870, -870, -870, -870, -870, -870,
-
-     -870, -870, -870, -870, -870, -870, -870, -870, -870, -870,
-     -870, -870, -870, -870, -870, -870, -870, -870, -870, -870,
-     -870, -870, -870, -870, -870, -870, -870, -870
-    },
-
-    {
-       67, -871, -871, -871, -871, -871, -871, -871, -871, -871,
-     -871, -871, -871, -871, -871, -871, -871, -871, -871, -871,
-     -871, -871, -871, -871, -871, -871, -871, -871, -871, -871,
-     -871, -871,  872, -871, -871, -871, -871, -871, -871, -871,
-     -871, -871, -871, -871, -871, -871, -871, -871, -871, -871,
-     -871, -871, -871, -871, -871, -871, -871, -871, -871, -871,
-     -871, -871, -871, -871, -871, -871, -871, -871, -871, -871,
-
-     -871, -871, -871, -871, -871, -871, -871, -871, -871, -871,
-     -871, -871, -871, -871, -871, -871, -871, -871, -871, -871,
-     -871, -871, -871, -871, -871, -871, -871, -871, -871, -871,
-     -871, -871, -871, -871, -871, -871, -871, -871, -871, -871,
-     -871, -871, -871, -871, -871, -871, -871, -871, -871, -871,
-     -871, -871, -871, -871, -871, -871, -871, -871
-    },
-
-    {
-       67, -872, -872, -872, -872, -872, -872, -872, -872, -872,
-     -872, -872, -872, -872, -872, -872, -872, -872, -872, -872,
-     -872, -872, -872, -872, -872, -872, -872, -872, -872, -872,
-     -872, -872,  873, -872, -872, -872, -872, -872, -872, -872,
-
-     -872, -872, -872, -872, -872, -872, -872, -872, -872, -872,
-     -872, -872, -872, -872, -872, -872, -872, -872, -872, -872,
-     -872, -872, -872, -872, -872, -872, -872, -872, -872, -872,
-     -872, -872, -872, -872, -872, -872, -872, -872, -872, -872,
-     -872, -872, -872, -872, -872, -872, -872, -872, -872, -872,
-     -872, -872, -872, -872, -872, -872, -872, -872, -872, -872,
-     -872, -872, -872, -872, -872, -872, -872, -872, -872, -872,
-     -872, -872, -872, -872, -872, -872, -872, -872, -872, -872,
-     -872, -872, -872, -872, -872, -872, -872, -872
-    },
-
-    {
-       67, -873, -873, -873, -873, -873, -873, -873, -873, -873,
-
-     -873, -873, -873, -873, -873, -873, -873, -873, -873, -873,
-     -873, -873, -873, -873, -873, -873, -873, -873, -873, -873,
-     -873, -873,  874, -873, -873, -873, -873, -873, -873, -873,
-     -873, -873, -873, -873, -873, -873, -873, -873, -873, -873,
-     -873, -873, -873, -873, -873, -873, -873, -873, -873, -873,
-     -873, -873, -873, -873, -873, -873, -873, -873, -873, -873,
-     -873, -873, -873, -873, -873, -873, -873, -873, -873, -873,
-     -873, -873, -873, -873, -873, -873, -873, -873, -873, -873,
-     -873, -873, -873, -873, -873, -873, -873, -873, -873, -873,
-     -873, -873, -873, -873, -873, -873, -873, -873, -873, -873,
-
-     -873, -873, -873, -873, -873, -873, -873, -873, -873, -873,
-     -873, -873, -873, -873, -873, -873, -873, -873
-    },
-
-    {
-       67, -874, -874, -874, -874, -874, -874, -874, -874, -874,
-     -874, -874, -874, -874, -874, -874, -874, -874, -874, -874,
-     -874, -874, -874, -874, -874, -874, -874, -874, -874, -874,
-     -874, -874,  875, -874, -874, -874, -874, -874, -874, -874,
-     -874, -874, -874, -874, -874, -874, -874, -874, -874, -874,
-     -874, -874, -874, -874, -874, -874, -874, -874, -874, -874,
-     -874, -874, -874, -874, -874, -874, -874, -874, -874, -874,
-     -874, -874, -874, -874, -874, -874, -874, -874, -874, -874,
-
-     -874, -874, -874, -874, -874, -874, -874, -874, -874, -874,
-     -874, -874, -874, -874, -874, -874, -874, -874, -874, -874,
-     -874, -874, -874, -874, -874, -874, -874, -874, -874, -874,
-     -874, -874, -874, -874, -874, -874, -874, -874, -874, -874,
-     -874, -874, -874, -874, -874, -874, -874, -874
-    },
-
-    {
-       67, -875, -875, -875, -875, -875, -875, -875, -875, -875,
-     -875, -875, -875, -875, -875, -875, -875, -875, -875, -875,
-     -875, -875, -875, -875, -875, -875, -875, -875, -875, -875,
-     -875, -875,  876, -875, -875, -875, -875, -875, -875, -875,
-     -875, -875, -875, -875, -875, -875, -875, -875, -875, -875,
-
-     -875, -875, -875, -875, -875, -875, -875, -875, -875, -875,
-     -875, -875, -875, -875, -875, -875, -875, -875, -875, -875,
-     -875, -875, -875, -875, -875, -875, -875, -875, -875, -875,
-     -875, -875, -875, -875, -875, -875, -875, -875, -875, -875,
-     -875, -875, -875, -875, -875, -875, -875, -875, -875, -875,
-     -875, -875, -875, -875, -875, -875, -875, -875, -875, -875,
-     -875, -875, -875, -875, -875, -875, -875, -875, -875, -875,
-     -875, -875, -875, -875, -875, -875, -875, -875
-    },
-
-    {
-       67, -876, -876, -876, -876, -876, -876, -876, -876, -876,
-     -876, -876, -876, -876, -876, -876, -876, -876, -876, -876,
-
-     -876, -876, -876, -876, -876, -876, -876, -876, -876, -876,
-     -876, -876,  877, -876, -876, -876, -876, -876, -876, -876,
-     -876, -876, -876, -876, -876, -876, -876, -876, -876, -876,
-     -876, -876, -876, -876, -876, -876, -876, -876, -876, -876,
-     -876, -876, -876, -876, -876, -876, -876, -876, -876, -876,
-     -876, -876, -876, -876, -876, -876, -876, -876, -876, -876,
-     -876, -876, -876, -876, -876, -876, -876, -876, -876, -876,
-     -876, -876, -876, -876, -876, -876, -876, -876, -876, -876,
-     -876, -876, -876, -876, -876, -876, -876, -876, -876, -876,
-     -876, -876, -876, -876, -876, -876, -876, -876, -876, -876,
-
-     -876, -876, -876, -876, -876, -876, -876, -876
-    },
-
-    {
-       67, -877, -877, -877, -877, -877, -877, -877, -877, -877,
-     -877, -877, -877, -877, -877, -877, -877, -877, -877, -877,
-     -877, -877, -877, -877, -877, -877, -877, -877, -877, -877,
-     -877, -877,  878, -877, -877, -877, -877, -877, -877, -877,
-     -877, -877, -877, -877, -877, -877, -877, -877, -877, -877,
-     -877, -877, -877, -877, -877, -877, -877, -877, -877, -877,
-     -877, -877, -877, -877, -877, -877, -877, -877, -877, -877,
-     -877, -877, -877, -877, -877, -877, -877, -877, -877, -877,
-     -877, -877, -877, -877, -877, -877, -877, -877, -877, -877,
-
-     -877, -877, -877, -877, -877, -877, -877, -877, -877, -877,
-     -877, -877, -877, -877, -877, -877, -877, -877, -877, -877,
-     -877, -877, -877, -877, -877, -877, -877, -877, -877, -877,
-     -877, -877, -877, -877, -877, -877, -877, -877
-    },
-
-    {
-       67, -878, -878, -878, -878, -878, -878, -878, -878, -878,
-     -878, -878, -878, -878, -878, -878, -878, -878, -878, -878,
-     -878, -878, -878, -878, -878, -878, -878, -878, -878, -878,
-     -878, -878,  879, -878, -878, -878, -878, -878, -878, -878,
-     -878, -878, -878, -878, -878, -878, -878, -878, -878, -878,
-     -878, -878, -878, -878, -878, -878, -878, -878, -878, -878,
-
-     -878, -878, -878, -878, -878, -878, -878, -878, -878, -878,
-     -878, -878, -878, -878, -878, -878, -878, -878, -878, -878,
-     -878, -878, -878, -878, -878, -878, -878, -878, -878, -878,
-     -878, -878, -878, -878, -878, -878, -878, -878, -878, -878,
-     -878, -878, -878, -878, -878, -878, -878, -878, -878, -878,
-     -878, -878, -878, -878, -878, -878, -878, -878, -878, -878,
-     -878, -878, -878, -878, -878, -878, -878, -878
-    },
-
-    {
-       67, -879, -879, -879, -879, -879, -879, -879, -879, -879,
-     -879, -879, -879, -879, -879, -879, -879, -879, -879, -879,
-     -879, -879, -879, -879, -879, -879, -879, -879, -879, -879,
-
-     -879, -879,  880, -879, -879, -879, -879, -879, -879, -879,
-     -879, -879, -879, -879, -879, -879, -879, -879, -879, -879,
-     -879, -879, -879, -879, -879, -879, -879, -879, -879, -879,
-     -879, -879, -879, -879, -879, -879, -879, -879, -879, -879,
-     -879, -879, -879, -879, -879, -879, -879, -879, -879, -879,
-     -879, -879, -879, -879, -879, -879, -879, -879, -879, -879,
-     -879, -879, -879, -879, -879, -879, -879, -879, -879, -879,
-     -879, -879, -879, -879, -879, -879, -879, -879, -879, -879,
-     -879, -879, -879, -879, -879, -879, -879, -879, -879, -879,
-     -879, -879, -879, -879, -879, -879, -879, -879
-
-    },
-
-    {
-       67, -880, -880, -880, -880, -880, -880, -880, -880, -880,
-     -880, -880, -880, -880, -880, -880, -880, -880, -880, -880,
-     -880, -880, -880, -880, -880, -880, -880, -880, -880, -880,
-     -880, -880,  881, -880, -880, -880, -880, -880, -880, -880,
-     -880, -880, -880, -880, -880, -880, -880, -880, -880, -880,
-     -880, -880, -880, -880, -880, -880, -880, -880, -880, -880,
-     -880, -880, -880, -880, -880, -880, -880, -880, -880, -880,
-     -880, -880, -880, -880, -880, -880, -880, -880, -880, -880,
-     -880, -880, -880, -880, -880, -880, -880, -880, -880, -880,
-     -880, -880, -880, -880, -880, -880, -880, -880, -880, -880,
-
-     -880, -880, -880, -880, -880, -880, -880, -880, -880, -880,
-     -880, -880, -880, -880, -880, -880, -880, -880, -880, -880,
-     -880, -880, -880, -880, -880, -880, -880, -880
-    },
-
-    {
-       67, -881, -881, -881, -881, -881, -881, -881, -881, -881,
-     -881, -881, -881, -881, -881, -881, -881, -881, -881, -881,
-     -881, -881, -881, -881, -881, -881, -881, -881, -881, -881,
-     -881, -881,  882, -881, -881, -881, -881, -881, -881, -881,
-     -881, -881, -881, -881, -881, -881, -881, -881, -881, -881,
-     -881, -881, -881, -881, -881, -881, -881, -881, -881, -881,
-     -881, -881, -881, -881, -881, -881, -881, -881, -881, -881,
-
-     -881, -881, -881, -881, -881, -881, -881, -881, -881, -881,
-     -881, -881, -881, -881, -881, -881, -881, -881, -881, -881,
-     -881, -881, -881, -881, -881, -881, -881, -881, -881, -881,
-     -881, -881, -881, -881, -881, -881, -881, -881, -881, -881,
-     -881, -881, -881, -881, -881, -881, -881, -881, -881, -881,
-     -881, -881, -881, -881, -881, -881, -881, -881
-    },
-
-    {
-       67, -882, -882, -882, -882, -882, -882, -882, -882, -882,
-     -882, -882, -882, -882, -882, -882, -882, -882, -882, -882,
-     -882, -882, -882, -882, -882, -882, -882, -882, -882, -882,
-     -882, -882,  883, -882, -882, -882, -882, -882, -882, -882,
-
-     -882, -882, -882, -882, -882, -882, -882, -882, -882, -882,
-     -882, -882, -882, -882, -882, -882, -882, -882, -882, -882,
-     -882, -882, -882, -882, -882, -882, -882, -882, -882, -882,
-     -882, -882, -882, -882, -882, -882, -882, -882, -882, -882,
-     -882, -882, -882, -882, -882, -882, -882, -882, -882, -882,
-     -882, -882, -882, -882, -882, -882, -882, -882, -882, -882,
-     -882, -882, -882, -882, -882, -882, -882, -882, -882, -882,
-     -882, -882, -882, -882, -882, -882, -882, -882, -882, -882,
-     -882, -882, -882, -882, -882, -882, -882, -882
-    },
-
-    {
-       67, -883, -883, -883, -883, -883, -883, -883, -883, -883,
-
-     -883, -883, -883, -883, -883, -883, -883, -883, -883, -883,
-     -883, -883, -883, -883, -883, -883, -883, -883, -883, -883,
-     -883, -883,  884, -883, -883, -883, -883, -883, -883, -883,
-     -883, -883, -883, -883, -883, -883, -883, -883, -883, -883,
-     -883, -883, -883, -883, -883, -883, -883, -883, -883, -883,
-     -883, -883, -883, -883, -883, -883, -883, -883, -883, -883,
-     -883, -883, -883, -883, -883, -883, -883, -883, -883, -883,
-     -883, -883, -883, -883, -883, -883, -883, -883, -883, -883,
-     -883, -883, -883, -883, -883, -883, -883, -883, -883, -883,
-     -883, -883, -883, -883, -883, -883, -883, -883, -883, -883,
-
-     -883, -883, -883, -883, -883, -883, -883, -883, -883, -883,
-     -883, -883, -883, -883, -883, -883, -883, -883
-    },
-
-    {
-       67, -884, -884, -884, -884, -884, -884, -884, -884, -884,
-     -884, -884, -884, -884, -884, -884, -884, -884, -884, -884,
-     -884, -884, -884, -884, -884, -884, -884, -884, -884, -884,
-     -884, -884,  885, -884, -884, -884, -884, -884, -884, -884,
-     -884, -884, -884, -884, -884, -884, -884, -884, -884, -884,
-     -884, -884, -884, -884, -884, -884, -884, -884, -884, -884,
-     -884, -884, -884, -884, -884, -884, -884, -884, -884, -884,
-     -884, -884, -884, -884, -884, -884, -884, -884, -884, -884,
-
-     -884, -884, -884, -884, -884, -884, -884, -884, -884, -884,
-     -884, -884, -884, -884, -884, -884, -884, -884, -884, -884,
-     -884, -884, -884, -884, -884, -884, -884, -884, -884, -884,
-     -884, -884, -884, -884, -884, -884, -884, -884, -884, -884,
-     -884, -884, -884, -884, -884, -884, -884, -884
-    },
-
-    {
-       67, -885, -885, -885, -885, -885, -885, -885, -885, -885,
-     -885, -885, -885, -885, -885, -885, -885, -885, -885, -885,
-     -885, -885, -885, -885, -885, -885, -885, -885, -885, -885,
-     -885, -885,  886, -885, -885, -885, -885, -885, -885, -885,
-     -885, -885, -885, -885, -885, -885, -885, -885, -885, -885,
-
-     -885, -885, -885, -885, -885, -885, -885, -885, -885, -885,
-     -885, -885, -885, -885, -885, -885, -885, -885, -885, -885,
-     -885, -885, -885, -885, -885, -885, -885, -885, -885, -885,
-     -885, -885, -885, -885, -885, -885, -885, -885, -885, -885,
-     -885, -885, -885, -885, -885, -885, -885, -885, -885, -885,
-     -885, -885, -885, -885, -885, -885, -885, -885, -885, -885,
-     -885, -885, -885, -885, -885, -885, -885, -885, -885, -885,
-     -885, -885, -885, -885, -885, -885, -885, -885
-    },
-
-    {
-       67, -886, -886, -886, -886, -886, -886, -886, -886, -886,
-     -886, -886, -886, -886, -886, -886, -886, -886, -886, -886,
-
-     -886, -886, -886, -886, -886, -886, -886, -886, -886, -886,
-     -886, -886,  887, -886, -886, -886, -886, -886, -886, -886,
-     -886, -886, -886, -886, -886, -886, -886, -886, -886, -886,
-     -886, -886, -886, -886, -886, -886, -886, -886, -886, -886,
-     -886, -886, -886, -886, -886, -886, -886, -886, -886, -886,
-     -886, -886, -886, -886, -886, -886, -886, -886, -886, -886,
-     -886, -886, -886, -886, -886, -886, -886, -886, -886, -886,
-     -886, -886, -886, -886, -886, -886, -886, -886, -886, -886,
-     -886, -886, -886, -886, -886, -886, -886, -886, -886, -886,
-     -886, -886, -886, -886, -886, -886, -886, -886, -886, -886,
-
-     -886, -886, -886, -886, -886, -886, -886, -886
-    },
-
-    {
-       67, -887, -887, -887, -887, -887, -887, -887, -887, -887,
-     -887, -887, -887, -887, -887, -887, -887, -887, -887, -887,
-     -887, -887, -887, -887, -887, -887, -887, -887, -887, -887,
-     -887, -887,  888, -887, -887, -887, -887, -887, -887, -887,
-     -887, -887, -887, -887, -887, -887, -887, -887, -887, -887,
-     -887, -887, -887, -887, -887, -887, -887, -887, -887, -887,
-     -887, -887, -887, -887, -887, -887, -887, -887, -887, -887,
-     -887, -887, -887, -887, -887, -887, -887, -887, -887, -887,
-     -887, -887, -887, -887, -887, -887, -887, -887, -887, -887,
-
-     -887, -887, -887, -887, -887, -887, -887, -887, -887, -887,
-     -887, -887, -887, -887, -887, -887, -887, -887, -887, -887,
-     -887, -887, -887, -887, -887, -887, -887, -887, -887, -887,
-     -887, -887, -887, -887, -887, -887, -887, -887
-    },
-
-    {
-       67, -888, -888, -888, -888, -888, -888, -888, -888, -888,
-     -888, -888, -888, -888, -888, -888, -888, -888, -888, -888,
-     -888, -888, -888, -888, -888, -888, -888, -888, -888, -888,
-     -888, -888,  889, -888, -888, -888, -888, -888, -888, -888,
-     -888, -888, -888, -888, -888, -888, -888, -888, -888, -888,
-     -888, -888, -888, -888, -888, -888, -888, -888, -888, -888,
-
-     -888, -888, -888, -888, -888, -888, -888, -888, -888, -888,
-     -888, -888, -888, -888, -888, -888, -888, -888, -888, -888,
-     -888, -888, -888, -888, -888, -888, -888, -888, -888, -888,
-     -888, -888, -888, -888, -888, -888, -888, -888, -888, -888,
-     -888, -888, -888, -888, -888, -888, -888, -888, -888, -888,
-     -888, -888, -888, -888, -888, -888, -888, -888, -888, -888,
-     -888, -888, -888, -888, -888, -888, -888, -888
-    },
-
-    {
-       67, -889, -889, -889, -889, -889, -889, -889, -889, -889,
-     -889, -889, -889, -889, -889, -889, -889, -889, -889, -889,
-     -889, -889, -889, -889, -889, -889, -889, -889, -889, -889,
-
-     -889, -889,  890, -889, -889, -889, -889, -889, -889, -889,
-     -889, -889, -889, -889, -889, -889, -889, -889, -889, -889,
-     -889, -889, -889, -889, -889, -889, -889, -889, -889, -889,
-     -889, -889, -889, -889, -889, -889, -889, -889, -889, -889,
-     -889, -889, -889, -889, -889, -889, -889, -889, -889, -889,
-     -889, -889, -889, -889, -889, -889, -889, -889, -889, -889,
-     -889, -889, -889, -889, -889, -889, -889, -889, -889, -889,
-     -889, -889, -889, -889, -889, -889, -889, -889, -889, -889,
-     -889, -889, -889, -889, -889, -889, -889, -889, -889, -889,
-     -889, -889, -889, -889, -889, -889, -889, -889
-
-    },
-
-    {
-       67, -890, -890, -890, -890, -890, -890, -890, -890, -890,
-     -890, -890, -890, -890, -890, -890, -890, -890, -890, -890,
-     -890, -890, -890, -890, -890, -890, -890, -890, -890, -890,
-     -890, -890,  891, -890, -890, -890, -890, -890, -890, -890,
-     -890, -890, -890, -890, -890, -890, -890, -890, -890, -890,
-     -890, -890, -890, -890, -890, -890, -890, -890, -890, -890,
-     -890, -890, -890, -890, -890, -890, -890, -890, -890, -890,
-     -890, -890, -890, -890, -890, -890, -890, -890, -890, -890,
-     -890, -890, -890, -890, -890, -890, -890, -890, -890, -890,
-     -890, -890, -890, -890, -890, -890, -890, -890, -890, -890,
-
-     -890, -890, -890, -890, -890, -890, -890, -890, -890, -890,
-     -890, -890, -890, -890, -890, -890, -890, -890, -890, -890,
-     -890, -890, -890, -890, -890, -890, -890, -890
-    },
-
-    {
-       67, -891, -891, -891, -891, -891, -891, -891, -891, -891,
-     -891, -891, -891, -891, -891, -891, -891, -891, -891, -891,
-     -891, -891, -891, -891, -891, -891, -891, -891, -891, -891,
-     -891, -891,  892, -891, -891, -891, -891, -891, -891, -891,
-     -891, -891, -891, -891, -891, -891, -891, -891, -891, -891,
-     -891, -891, -891, -891, -891, -891, -891, -891, -891, -891,
-     -891, -891, -891, -891, -891, -891, -891, -891, -891, -891,
-
-     -891, -891, -891, -891, -891, -891, -891, -891, -891, -891,
-     -891, -891, -891, -891, -891, -891, -891, -891, -891, -891,
-     -891, -891, -891, -891, -891, -891, -891, -891, -891, -891,
-     -891, -891, -891, -891, -891, -891, -891, -891, -891, -891,
-     -891, -891, -891, -891, -891, -891, -891, -891, -891, -891,
-     -891, -891, -891, -891, -891, -891, -891, -891
-    },
-
-    {
-       67, -892, -892, -892, -892, -892, -892, -892, -892, -892,
-     -892, -892, -892, -892, -892, -892, -892, -892, -892, -892,
-     -892, -892, -892, -892, -892, -892, -892, -892, -892, -892,
-     -892, -892,  893, -892, -892, -892, -892, -892, -892, -892,
-
-     -892, -892, -892, -892, -892, -892, -892, -892, -892, -892,
-     -892, -892, -892, -892, -892, -892, -892, -892, -892, -892,
-     -892, -892, -892, -892, -892, -892, -892, -892, -892, -892,
-     -892, -892, -892, -892, -892, -892, -892, -892, -892, -892,
-     -892, -892, -892, -892, -892, -892, -892, -892, -892, -892,
-     -892, -892, -892, -892, -892, -892, -892, -892, -892, -892,
-     -892, -892, -892, -892, -892, -892, -892, -892, -892, -892,
-     -892, -892, -892, -892, -892, -892, -892, -892, -892, -892,
-     -892, -892, -892, -892, -892, -892, -892, -892
-    },
-
-    {
-       67, -893, -893, -893, -893, -893, -893, -893, -893, -893,
-
-     -893, -893, -893, -893, -893, -893, -893, -893, -893, -893,
-     -893, -893, -893, -893, -893, -893, -893, -893, -893, -893,
-     -893, -893,  894, -893, -893, -893, -893, -893, -893, -893,
-     -893, -893, -893, -893, -893, -893, -893, -893, -893, -893,
-     -893, -893, -893, -893, -893, -893, -893, -893, -893, -893,
-     -893, -893, -893, -893, -893, -893, -893, -893, -893, -893,
-     -893, -893, -893, -893, -893, -893, -893, -893, -893, -893,
-     -893, -893, -893, -893, -893, -893, -893, -893, -893, -893,
-     -893, -893, -893, -893, -893, -893, -893, -893, -893, -893,
-     -893, -893, -893, -893, -893, -893, -893, -893, -893, -893,
-
-     -893, -893, -893, -893, -893, -893, -893, -893, -893, -893,
-     -893, -893, -893, -893, -893, -893, -893, -893
-    },
-
-    {
-       67, -894, -894, -894, -894, -894, -894, -894, -894, -894,
-     -894, -894, -894, -894, -894, -894, -894, -894, -894, -894,
-     -894, -894, -894, -894, -894, -894, -894, -894, -894, -894,
-     -894, -894,  895, -894, -894, -894, -894, -894, -894, -894,
-     -894, -894, -894, -894, -894, -894, -894, -894, -894, -894,
-     -894, -894, -894, -894, -894, -894, -894, -894, -894, -894,
-     -894, -894, -894, -894, -894, -894, -894, -894, -894, -894,
-     -894, -894, -894, -894, -894, -894, -894, -894, -894, -894,
-
-     -894, -894, -894, -894, -894, -894, -894, -894, -894, -894,
-     -894, -894, -894, -894, -894, -894, -894, -894, -894, -894,
-     -894, -894, -894, -894, -894, -894, -894, -894, -894, -894,
-     -894, -894, -894, -894, -894, -894, -894, -894, -894, -894,
-     -894, -894, -894, -894, -894, -894, -894, -894
-    },
-
-    {
-       67, -895, -895, -895, -895, -895, -895, -895, -895, -895,
-     -895, -895, -895, -895, -895, -895, -895, -895, -895, -895,
-     -895, -895, -895, -895, -895, -895, -895, -895, -895, -895,
-     -895, -895,  896, -895, -895, -895, -895, -895, -895, -895,
-     -895, -895, -895, -895, -895, -895, -895, -895, -895, -895,
-
-     -895, -895, -895, -895, -895, -895, -895, -895, -895, -895,
-     -895, -895, -895, -895, -895, -895, -895, -895, -895, -895,
-     -895, -895, -895, -895, -895, -895, -895, -895, -895, -895,
-     -895, -895, -895, -895, -895, -895, -895, -895, -895, -895,
-     -895, -895, -895, -895, -895, -895, -895, -895, -895, -895,
-     -895, -895, -895, -895, -895, -895, -895, -895, -895, -895,
-     -895, -895, -895, -895, -895, -895, -895, -895, -895, -895,
-     -895, -895, -895, -895, -895, -895, -895, -895
-    },
-
-    {
-       67, -896, -896, -896, -896, -896, -896, -896, -896, -896,
-     -896, -896, -896, -896, -896, -896, -896, -896, -896, -896,
-
-     -896, -896, -896, -896, -896, -896, -896, -896, -896, -896,
-     -896, -896,  897, -896, -896, -896, -896, -896, -896, -896,
-     -896, -896, -896, -896, -896, -896, -896, -896, -896, -896,
-     -896, -896, -896, -896, -896, -896, -896, -896, -896, -896,
-     -896, -896, -896, -896, -896, -896, -896, -896, -896, -896,
-     -896, -896, -896, -896, -896, -896, -896, -896, -896, -896,
-     -896, -896, -896, -896, -896, -896, -896, -896, -896, -896,
-     -896, -896, -896, -896, -896, -896, -896, -896, -896, -896,
-     -896, -896, -896, -896, -896, -896, -896, -896, -896, -896,
-     -896, -896, -896, -896, -896, -896, -896, -896, -896, -896,
-
-     -896, -896, -896, -896, -896, -896, -896, -896
-    },
-
-    {
-       67, -897, -897, -897, -897, -897, -897, -897, -897, -897,
-     -897, -897, -897, -897, -897, -897, -897, -897, -897, -897,
-     -897, -897, -897, -897, -897, -897, -897, -897, -897, -897,
-     -897, -897,  898, -897, -897, -897, -897, -897, -897, -897,
-     -897, -897, -897, -897, -897, -897, -897, -897, -897, -897,
-     -897, -897, -897, -897, -897, -897, -897, -897, -897, -897,
-     -897, -897, -897, -897, -897, -897, -897, -897, -897, -897,
-     -897, -897, -897, -897, -897, -897, -897, -897, -897, -897,
-     -897, -897, -897, -897, -897, -897, -897, -897, -897, -897,
-
-     -897, -897, -897, -897, -897, -897, -897, -897, -897, -897,
-     -897, -897, -897, -897, -897, -897, -897, -897, -897, -897,
-     -897, -897, -897, -897, -897, -897, -897, -897, -897, -897,
-     -897, -897, -897, -897, -897, -897, -897, -897
-    },
-
-    {
-       67, -898, -898, -898, -898, -898, -898, -898, -898, -898,
-     -898, -898, -898, -898, -898, -898, -898, -898, -898, -898,
-     -898, -898, -898, -898, -898, -898, -898, -898, -898, -898,
-     -898, -898,  899, -898, -898, -898, -898, -898, -898, -898,
-     -898, -898, -898, -898, -898, -898, -898, -898, -898, -898,
-     -898, -898, -898, -898, -898, -898, -898, -898, -898, -898,
-
-     -898, -898, -898, -898, -898, -898, -898, -898, -898, -898,
-     -898, -898, -898, -898, -898, -898, -898, -898, -898, -898,
-     -898, -898, -898, -898, -898, -898, -898, -898, -898, -898,
-     -898, -898, -898, -898, -898, -898, -898, -898, -898, -898,
-     -898, -898, -898, -898, -898, -898, -898, -898, -898, -898,
-     -898, -898, -898, -898, -898, -898, -898, -898, -898, -898,
-     -898, -898, -898, -898, -898, -898, -898, -898
-    },
-
-    {
-       67, -899, -899, -899, -899, -899, -899, -899, -899, -899,
-     -899, -899, -899, -899, -899, -899, -899, -899, -899, -899,
-     -899, -899, -899, -899, -899, -899, -899, -899, -899, -899,
-
-     -899, -899,  900, -899, -899, -899, -899, -899, -899, -899,
-     -899, -899, -899, -899, -899, -899, -899, -899, -899, -899,
-     -899, -899, -899, -899, -899, -899, -899, -899, -899, -899,
-     -899, -899, -899, -899, -899, -899, -899, -899, -899, -899,
-     -899, -899, -899, -899, -899, -899, -899, -899, -899, -899,
-     -899, -899, -899, -899, -899, -899, -899, -899, -899, -899,
-     -899, -899, -899, -899, -899, -899, -899, -899, -899, -899,
-     -899, -899, -899, -899, -899, -899, -899, -899, -899, -899,
-     -899, -899, -899, -899, -899, -899, -899, -899, -899, -899,
-     -899, -899, -899, -899, -899, -899, -899, -899
-
-    },
-
-    {
-       67, -900, -900, -900, -900, -900, -900, -900, -900, -900,
-     -900, -900, -900, -900, -900, -900, -900, -900, -900, -900,
-     -900, -900, -900, -900, -900, -900, -900, -900, -900, -900,
-     -900, -900,  901, -900, -900, -900, -900, -900, -900, -900,
-     -900, -900, -900, -900, -900, -900, -900, -900, -900, -900,
-     -900, -900, -900, -900, -900, -900, -900, -900, -900, -900,
-     -900, -900, -900, -900, -900, -900, -900, -900, -900, -900,
-     -900, -900, -900, -900, -900, -900, -900, -900, -900, -900,
-     -900, -900, -900, -900, -900, -900, -900, -900, -900, -900,
-     -900, -900, -900, -900, -900, -900, -900, -900, -900, -900,
-
-     -900, -900, -900, -900, -900, -900, -900, -900, -900, -900,
-     -900, -900, -900, -900, -900, -900, -900, -900, -900, -900,
-     -900, -900, -900, -900, -900, -900, -900, -900
-    },
-
-    {
-       67, -901, -901, -901, -901, -901, -901, -901, -901, -901,
-     -901, -901, -901, -901, -901, -901, -901, -901, -901, -901,
-     -901, -901, -901, -901, -901, -901, -901, -901, -901, -901,
-     -901, -901,  902, -901, -901, -901, -901, -901, -901, -901,
-     -901, -901, -901, -901, -901, -901, -901, -901, -901, -901,
-     -901, -901, -901, -901, -901, -901, -901, -901, -901, -901,
-     -901, -901, -901, -901, -901, -901, -901, -901, -901, -901,
-
-     -901, -901, -901, -901, -901, -901, -901, -901, -901, -901,
-     -901, -901, -901, -901, -901, -901, -901, -901, -901, -901,
-     -901, -901, -901, -901, -901, -901, -901, -901, -901, -901,
-     -901, -901, -901, -901, -901, -901, -901, -901, -901, -901,
-     -901, -901, -901, -901, -901, -901, -901, -901, -901, -901,
-     -901, -901, -901, -901, -901, -901, -901, -901
-    },
-
-    {
-       67, -902, -902, -902, -902, -902, -902, -902, -902, -902,
-     -902, -902, -902, -902, -902, -902, -902, -902, -902, -902,
-     -902, -902, -902, -902, -902, -902, -902, -902, -902, -902,
-     -902, -902,  903, -902, -902, -902, -902, -902, -902, -902,
-
-     -902, -902, -902, -902, -902, -902, -902, -902, -902, -902,
-     -902, -902, -902, -902, -902, -902, -902, -902, -902, -902,
-     -902, -902, -902, -902, -902, -902, -902, -902, -902, -902,
-     -902, -902, -902, -902, -902, -902, -902, -902, -902, -902,
-     -902, -902, -902, -902, -902, -902, -902, -902, -902, -902,
-     -902, -902, -902, -902, -902, -902, -902, -902, -902, -902,
-     -902, -902, -902, -902, -902, -902, -902, -902, -902, -902,
-     -902, -902, -902, -902, -902, -902, -902, -902, -902, -902,
-     -902, -902, -902, -902, -902, -902, -902, -902
-    },
-
-    {
-       67, -903, -903, -903, -903, -903, -903, -903, -903, -903,
-
-     -903, -903, -903, -903, -903, -903, -903, -903, -903, -903,
-     -903, -903, -903, -903, -903, -903, -903, -903, -903, -903,
-     -903, -903,  904, -903, -903, -903, -903, -903, -903, -903,
-     -903, -903, -903, -903, -903, -903, -903, -903, -903, -903,
-     -903, -903, -903, -903, -903, -903, -903, -903, -903, -903,
-     -903, -903, -903, -903, -903, -903, -903, -903, -903, -903,
-     -903, -903, -903, -903, -903, -903, -903, -903, -903, -903,
-     -903, -903, -903, -903, -903, -903, -903, -903, -903, -903,
-     -903, -903, -903, -903, -903, -903, -903, -903, -903, -903,
-     -903, -903, -903, -903, -903, -903, -903, -903, -903, -903,
-
-     -903, -903, -903, -903, -903, -903, -903, -903, -903, -903,
-     -903, -903, -903, -903, -903, -903, -903, -903
-    },
-
-    {
-       67, -904, -904, -904, -904, -904, -904, -904, -904, -904,
-     -904, -904, -904, -904, -904, -904, -904, -904, -904, -904,
-     -904, -904, -904, -904, -904, -904, -904, -904, -904, -904,
-     -904, -904,  905, -904, -904, -904, -904, -904, -904, -904,
-     -904, -904, -904, -904, -904, -904, -904, -904, -904, -904,
-     -904, -904, -904, -904, -904, -904, -904, -904, -904, -904,
-     -904, -904, -904, -904, -904, -904, -904, -904, -904, -904,
-     -904, -904, -904, -904, -904, -904, -904, -904, -904, -904,
-
-     -904, -904, -904, -904, -904, -904, -904, -904, -904, -904,
-     -904, -904, -904, -904, -904, -904, -904, -904, -904, -904,
-     -904, -904, -904, -904, -904, -904, -904, -904, -904, -904,
-     -904, -904, -904, -904, -904, -904, -904, -904, -904, -904,
-     -904, -904, -904, -904, -904, -904, -904, -904
-    },
-
-    {
-       67, -905, -905, -905, -905, -905, -905, -905, -905, -905,
-     -905, -905, -905, -905, -905, -905, -905, -905, -905, -905,
-     -905, -905, -905, -905, -905, -905, -905, -905, -905, -905,
-     -905, -905,  906, -905, -905, -905, -905, -905, -905, -905,
-     -905, -905, -905, -905, -905, -905, -905, -905, -905, -905,
-
-     -905, -905, -905, -905, -905, -905, -905, -905, -905, -905,
-     -905, -905, -905, -905, -905, -905, -905, -905, -905, -905,
-     -905, -905, -905, -905, -905, -905, -905, -905, -905, -905,
-     -905, -905, -905, -905, -905, -905, -905, -905, -905, -905,
-     -905, -905, -905, -905, -905, -905, -905, -905, -905, -905,
-     -905, -905, -905, -905, -905, -905, -905, -905, -905, -905,
-     -905, -905, -905, -905, -905, -905, -905, -905, -905, -905,
-     -905, -905, -905, -905, -905, -905, -905, -905
-    },
-
-    {
-       67, -906, -906, -906, -906, -906, -906, -906, -906, -906,
-     -906, -906, -906, -906, -906, -906, -906, -906, -906, -906,
-
-     -906, -906, -906, -906, -906, -906, -906, -906, -906, -906,
-     -906, -906,  907, -906, -906, -906, -906, -906, -906, -906,
-     -906, -906, -906, -906, -906, -906, -906, -906, -906, -906,
-     -906, -906, -906, -906, -906, -906, -906, -906, -906, -906,
-     -906, -906, -906, -906, -906, -906, -906, -906, -906, -906,
-     -906, -906, -906, -906, -906, -906, -906, -906, -906, -906,
-     -906, -906, -906, -906, -906, -906, -906, -906, -906, -906,
-     -906, -906, -906, -906, -906, -906, -906, -906, -906, -906,
-     -906, -906, -906, -906, -906, -906, -906, -906, -906, -906,
-     -906, -906, -906, -906, -906, -906, -906, -906, -906, -906,
-
-     -906, -906, -906, -906, -906, -906, -906, -906
-    },
-
-    {
-       67, -907, -907, -907, -907, -907, -907, -907, -907, -907,
-     -907, -907, -907, -907, -907, -907, -907, -907, -907, -907,
-     -907, -907, -907, -907, -907, -907, -907, -907, -907, -907,
-     -907, -907,  908, -907, -907, -907, -907, -907, -907, -907,
-     -907, -907, -907, -907, -907, -907, -907, -907, -907, -907,
-     -907, -907, -907, -907, -907, -907, -907, -907, -907, -907,
-     -907, -907, -907, -907, -907, -907, -907, -907, -907, -907,
-     -907, -907, -907, -907, -907, -907, -907, -907, -907, -907,
-     -907, -907, -907, -907, -907, -907, -907, -907, -907, -907,
-
-     -907, -907, -907, -907, -907, -907, -907, -907, -907, -907,
-     -907, -907, -907, -907, -907, -907, -907, -907, -907, -907,
-     -907, -907, -907, -907, -907, -907, -907, -907, -907, -907,
-     -907, -907, -907, -907, -907, -907, -907, -907
-    },
-
-    {
-       67, -908, -908, -908, -908, -908, -908, -908, -908, -908,
-     -908, -908, -908, -908, -908, -908, -908, -908, -908, -908,
-     -908, -908, -908, -908, -908, -908, -908, -908, -908, -908,
-     -908, -908,  909, -908, -908, -908, -908, -908, -908, -908,
-     -908, -908, -908, -908, -908, -908, -908, -908, -908, -908,
-     -908, -908, -908, -908, -908, -908, -908, -908, -908, -908,
-
-     -908, -908, -908, -908, -908, -908, -908, -908, -908, -908,
-     -908, -908, -908, -908, -908, -908, -908, -908, -908, -908,
-     -908, -908, -908, -908, -908, -908, -908, -908, -908, -908,
-     -908, -908, -908, -908, -908, -908, -908, -908, -908, -908,
-     -908, -908, -908, -908, -908, -908, -908, -908, -908, -908,
-     -908, -908, -908, -908, -908, -908, -908, -908, -908, -908,
-     -908, -908, -908, -908, -908, -908, -908, -908
-    },
-
-    {
-       67, -909, -909, -909, -909, -909, -909, -909, -909, -909,
-     -909, -909, -909, -909, -909, -909, -909, -909, -909, -909,
-     -909, -909, -909, -909, -909, -909, -909, -909, -909, -909,
-
-     -909, -909,  910, -909, -909, -909, -909, -909, -909, -909,
-     -909, -909, -909, -909, -909, -909, -909, -909, -909, -909,
-     -909, -909, -909, -909, -909, -909, -909, -909, -909, -909,
-     -909, -909, -909, -909, -909, -909, -909, -909, -909, -909,
-     -909, -909, -909, -909, -909, -909, -909, -909, -909, -909,
-     -909, -909, -909, -909, -909, -909, -909, -909, -909, -909,
-     -909, -909, -909, -909, -909, -909, -909, -909, -909, -909,
-     -909, -909, -909, -909, -909, -909, -909, -909, -909, -909,
-     -909, -909, -909, -909, -909, -909, -909, -909, -909, -909,
-     -909, -909, -909, -909, -909, -909, -909, -909
-
-    },
-
-    {
-       67, -910, -910, -910, -910, -910, -910, -910, -910, -910,
-     -910, -910, -910, -910, -910, -910, -910, -910, -910, -910,
-     -910, -910, -910, -910, -910, -910, -910, -910, -910, -910,
-     -910, -910,  911, -910, -910, -910, -910, -910, -910, -910,
-     -910, -910, -910, -910, -910, -910, -910, -910, -910, -910,
-     -910, -910, -910, -910, -910, -910, -910, -910, -910, -910,
-     -910, -910, -910, -910, -910, -910, -910, -910, -910, -910,
-     -910, -910, -910, -910, -910, -910, -910, -910, -910, -910,
-     -910, -910, -910, -910, -910, -910, -910, -910, -910, -910,
-     -910, -910, -910, -910, -910, -910, -910, -910, -910, -910,
-
-     -910, -910, -910, -910, -910, -910, -910, -910, -910, -910,
-     -910, -910, -910, -910, -910, -910, -910, -910, -910, -910,
-     -910, -910, -910, -910, -910, -910, -910, -910
-    },
-
-    {
-       67, -911, -911, -911, -911, -911, -911, -911, -911, -911,
-     -911, -911, -911, -911, -911, -911, -911, -911, -911, -911,
-     -911, -911, -911, -911, -911, -911, -911, -911, -911, -911,
-     -911, -911,  912, -911, -911, -911, -911, -911, -911, -911,
-     -911, -911, -911, -911, -911, -911, -911, -911, -911, -911,
-     -911, -911, -911, -911, -911, -911, -911, -911, -911, -911,
-     -911, -911, -911, -911, -911, -911, -911, -911, -911, -911,
-
-     -911, -911, -911, -911, -911, -911, -911, -911, -911, -911,
-     -911, -911, -911, -911, -911, -911, -911, -911, -911, -911,
-     -911, -911, -911, -911, -911, -911, -911, -911, -911, -911,
-     -911, -911, -911, -911, -911, -911, -911, -911, -911, -911,
-     -911, -911, -911, -911, -911, -911, -911, -911, -911, -911,
-     -911, -911, -911, -911, -911, -911, -911, -911
-    },
-
-    {
-       67, -912, -912, -912, -912, -912, -912, -912, -912, -912,
-     -912, -912, -912, -912, -912, -912, -912, -912, -912, -912,
-     -912, -912, -912, -912, -912, -912, -912, -912, -912, -912,
-     -912, -912,  913, -912, -912, -912, -912, -912, -912, -912,
-
-     -912, -912, -912, -912, -912, -912, -912, -912, -912, -912,
-     -912, -912, -912, -912, -912, -912, -912, -912, -912, -912,
-     -912, -912, -912, -912, -912, -912, -912, -912, -912, -912,
-     -912, -912, -912, -912, -912, -912, -912, -912, -912, -912,
-     -912, -912, -912, -912, -912, -912, -912, -912, -912, -912,
-     -912, -912, -912, -912, -912, -912, -912, -912, -912, -912,
-     -912, -912, -912, -912, -912, -912, -912, -912, -912, -912,
-     -912, -912, -912, -912, -912, -912, -912, -912, -912, -912,
-     -912, -912, -912, -912, -912, -912, -912, -912
-    },
-
-    {
-       67, -913, -913, -913, -913, -913, -913, -913, -913, -913,
-
-     -913, -913, -913, -913, -913, -913, -913, -913, -913, -913,
-     -913, -913, -913, -913, -913, -913, -913, -913, -913, -913,
-     -913, -913,  914, -913, -913, -913, -913, -913, -913, -913,
-     -913, -913, -913, -913, -913, -913, -913, -913, -913, -913,
-     -913, -913, -913, -913, -913, -913, -913, -913, -913, -913,
-     -913, -913, -913, -913, -913, -913, -913, -913, -913, -913,
-     -913, -913, -913, -913, -913, -913, -913, -913, -913, -913,
-     -913, -913, -913, -913, -913, -913, -913, -913, -913, -913,
-     -913, -913, -913, -913, -913, -913, -913, -913, -913, -913,
-     -913, -913, -913, -913, -913, -913, -913, -913, -913, -913,
-
-     -913, -913, -913, -913, -913, -913, -913, -913, -913, -913,
-     -913, -913, -913, -913, -913, -913, -913, -913
-    },
-
-    {
-       67, -914, -914, -914, -914, -914, -914, -914, -914, -914,
-     -914, -914, -914, -914, -914, -914, -914, -914, -914, -914,
-     -914, -914, -914, -914, -914, -914, -914, -914, -914, -914,
-     -914, -914,  915, -914, -914, -914, -914, -914, -914, -914,
-     -914, -914, -914, -914, -914, -914, -914, -914, -914, -914,
-     -914, -914, -914, -914, -914, -914, -914, -914, -914, -914,
-     -914, -914, -914, -914, -914, -914, -914, -914, -914, -914,
-     -914, -914, -914, -914, -914, -914, -914, -914, -914, -914,
-
-     -914, -914, -914, -914, -914, -914, -914, -914, -914, -914,
-     -914, -914, -914, -914, -914, -914, -914, -914, -914, -914,
-     -914, -914, -914, -914, -914, -914, -914, -914, -914, -914,
-     -914, -914, -914, -914, -914, -914, -914, -914, -914, -914,
-     -914, -914, -914, -914, -914, -914, -914, -914
-    },
-
-    {
-       67, -915, -915, -915, -915, -915, -915, -915, -915, -915,
-     -915, -915, -915, -915, -915, -915, -915, -915, -915, -915,
-     -915, -915, -915, -915, -915, -915, -915, -915, -915, -915,
-     -915, -915,  916, -915, -915, -915, -915, -915, -915, -915,
-     -915, -915, -915, -915, -915, -915, -915, -915, -915, -915,
-
-     -915, -915, -915, -915, -915, -915, -915, -915, -915, -915,
-     -915, -915, -915, -915, -915, -915, -915, -915, -915, -915,
-     -915, -915, -915, -915, -915, -915, -915, -915, -915, -915,
-     -915, -915, -915, -915, -915, -915, -915, -915, -915, -915,
-     -915, -915, -915, -915, -915, -915, -915, -915, -915, -915,
-     -915, -915, -915, -915, -915, -915, -915, -915, -915, -915,
-     -915, -915, -915, -915, -915, -915, -915, -915, -915, -915,
-     -915, -915, -915, -915, -915, -915, -915, -915
-    },
-
-    {
-       67, -916, -916, -916, -916, -916, -916, -916, -916, -916,
-     -916, -916, -916, -916, -916, -916, -916, -916, -916, -916,
-
-     -916, -916, -916, -916, -916, -916, -916, -916, -916, -916,
-     -916, -916,  917, -916, -916, -916, -916, -916, -916, -916,
-     -916, -916, -916, -916, -916, -916, -916, -916, -916, -916,
-     -916, -916, -916, -916, -916, -916, -916, -916, -916, -916,
-     -916, -916, -916, -916, -916, -916, -916, -916, -916, -916,
-     -916, -916, -916, -916, -916, -916, -916, -916, -916, -916,
-     -916, -916, -916, -916, -916, -916, -916, -916, -916, -916,
-     -916, -916, -916, -916, -916, -916, -916, -916, -916, -916,
-     -916, -916, -916, -916, -916, -916, -916, -916, -916, -916,
-     -916, -916, -916, -916, -916, -916, -916, -916, -916, -916,
-
-     -916, -916, -916, -916, -916, -916, -916, -916
-    },
-
-    {
-       67, -917, -917, -917, -917, -917, -917, -917, -917, -917,
-     -917, -917, -917, -917, -917, -917, -917, -917, -917, -917,
-     -917, -917, -917, -917, -917, -917, -917, -917, -917, -917,
-     -917, -917,  918, -917, -917, -917, -917, -917, -917, -917,
-     -917, -917, -917, -917, -917, -917, -917, -917, -917, -917,
-     -917, -917, -917, -917, -917, -917, -917, -917, -917, -917,
-     -917, -917, -917, -917, -917, -917, -917, -917, -917, -917,
-     -917, -917, -917, -917, -917, -917, -917, -917, -917, -917,
-     -917, -917, -917, -917, -917, -917, -917, -917, -917, -917,
-
-     -917, -917, -917, -917, -917, -917, -917, -917, -917, -917,
-     -917, -917, -917, -917, -917, -917, -917, -917, -917, -917,
-     -917, -917, -917, -917, -917, -917, -917, -917, -917, -917,
-     -917, -917, -917, -917, -917, -917, -917, -917
-    },
-
-    {
-       67, -918, -918, -918, -918, -918, -918, -918, -918, -918,
-     -918, -918, -918, -918, -918, -918, -918, -918, -918, -918,
-     -918, -918, -918, -918, -918, -918, -918, -918, -918, -918,
-     -918, -918,  919, -918, -918, -918, -918, -918, -918, -918,
-     -918, -918, -918, -918, -918, -918, -918, -918, -918, -918,
-     -918, -918, -918, -918, -918, -918, -918, -918, -918, -918,
-
-     -918, -918, -918, -918, -918, -918, -918, -918, -918, -918,
-     -918, -918, -918, -918, -918, -918, -918, -918, -918, -918,
-     -918, -918, -918, -918, -918, -918, -918, -918, -918, -918,
-     -918, -918, -918, -918, -918, -918, -918, -918, -918, -918,
-     -918, -918, -918, -918, -918, -918, -918, -918, -918, -918,
-     -918, -918, -918, -918, -918, -918, -918, -918, -918, -918,
-     -918, -918, -918, -918, -918, -918, -918, -918
-    },
-
-    {
-       67, -919, -919, -919, -919, -919, -919, -919, -919, -919,
-     -919, -919, -919, -919, -919, -919, -919, -919, -919, -919,
-     -919, -919, -919, -919, -919, -919, -919, -919, -919, -919,
-
-     -919, -919,  920, -919, -919, -919, -919, -919, -919, -919,
-     -919, -919, -919, -919, -919, -919, -919, -919, -919, -919,
-     -919, -919, -919, -919, -919, -919, -919, -919, -919, -919,
-     -919, -919, -919, -919, -919, -919, -919, -919, -919, -919,
-     -919, -919, -919, -919, -919, -919, -919, -919, -919, -919,
-     -919, -919, -919, -919, -919, -919, -919, -919, -919, -919,
-     -919, -919, -919, -919, -919, -919, -919, -919, -919, -919,
-     -919, -919, -919, -919, -919, -919, -919, -919, -919, -919,
-     -919, -919, -919, -919, -919, -919, -919, -919, -919, -919,
-     -919, -919, -919, -919, -919, -919, -919, -919
-
-    },
-
-    {
-       67, -920, -920, -920, -920, -920, -920, -920, -920, -920,
-     -920, -920, -920, -920, -920, -920, -920, -920, -920, -920,
-     -920, -920, -920, -920, -920, -920, -920, -920, -920, -920,
-     -920, -920,  921, -920, -920, -920, -920, -920, -920, -920,
-     -920, -920, -920, -920, -920, -920, -920, -920, -920, -920,
-     -920, -920, -920, -920, -920, -920, -920, -920, -920, -920,
-     -920, -920, -920, -920, -920, -920, -920, -920, -920, -920,
-     -920, -920, -920, -920, -920, -920, -920, -920, -920, -920,
-     -920, -920, -920, -920, -920, -920, -920, -920, -920, -920,
-     -920, -920, -920, -920, -920, -920, -920, -920, -920, -920,
-
-     -920, -920, -920, -920, -920, -920, -920, -920, -920, -920,
-     -920, -920, -920, -920, -920, -920, -920, -920, -920, -920,
-     -920, -920, -920, -920, -920, -920, -920, -920
-    },
-
-    {
-       67, -921, -921, -921, -921, -921, -921, -921, -921, -921,
-     -921, -921, -921, -921, -921, -921, -921, -921, -921, -921,
-     -921, -921, -921, -921, -921, -921, -921, -921, -921, -921,
-     -921, -921,  922, -921, -921, -921, -921, -921, -921, -921,
-     -921, -921, -921, -921, -921, -921, -921, -921, -921, -921,
-     -921, -921, -921, -921, -921, -921, -921, -921, -921, -921,
-     -921, -921, -921, -921, -921, -921, -921, -921, -921, -921,
-
-     -921, -921, -921, -921, -921, -921, -921, -921, -921, -921,
-     -921, -921, -921, -921, -921, -921, -921, -921, -921, -921,
-     -921, -921, -921, -921, -921, -921, -921, -921, -921, -921,
-     -921, -921, -921, -921, -921, -921, -921, -921, -921, -921,
-     -921, -921, -921, -921, -921, -921, -921, -921, -921, -921,
-     -921, -921, -921, -921, -921, -921, -921, -921
-    },
-
-    {
-       67, -922, -922, -922, -922, -922, -922, -922, -922, -922,
-     -922, -922, -922, -922, -922, -922, -922, -922, -922, -922,
-     -922, -922, -922, -922, -922, -922, -922, -922, -922, -922,
-     -922, -922,  923, -922, -922, -922, -922, -922, -922, -922,
-
-     -922, -922, -922, -922, -922, -922, -922, -922, -922, -922,
-     -922, -922, -922, -922, -922, -922, -922, -922, -922, -922,
-     -922, -922, -922, -922, -922, -922, -922, -922, -922, -922,
-     -922, -922, -922, -922, -922, -922, -922, -922, -922, -922,
-     -922, -922, -922, -922, -922, -922, -922, -922, -922, -922,
-     -922, -922, -922, -922, -922, -922, -922, -922, -922, -922,
-     -922, -922, -922, -922, -922, -922, -922, -922, -922, -922,
-     -922, -922, -922, -922, -922, -922, -922, -922, -922, -922,
-     -922, -922, -922, -922, -922, -922, -922, -922
-    },
-
-    {
-       67, -923, -923, -923, -923, -923, -923, -923, -923, -923,
-
-     -923, -923, -923, -923, -923, -923, -923, -923, -923, -923,
-     -923, -923, -923, -923, -923, -923, -923, -923, -923, -923,
-     -923, -923,  924, -923, -923, -923, -923, -923, -923, -923,
-     -923, -923, -923, -923, -923, -923, -923, -923, -923, -923,
-     -923, -923, -923, -923, -923, -923, -923, -923, -923, -923,
-     -923, -923, -923, -923, -923, -923, -923, -923, -923, -923,
-     -923, -923, -923, -923, -923, -923, -923, -923, -923, -923,
-     -923, -923, -923, -923, -923, -923, -923, -923, -923, -923,
-     -923, -923, -923, -923, -923, -923, -923, -923, -923, -923,
-     -923, -923, -923, -923, -923, -923, -923, -923, -923, -923,
-
-     -923, -923, -923, -923, -923, -923, -923, -923, -923, -923,
-     -923, -923, -923, -923, -923, -923, -923, -923
-    },
-
-    {
-       67, -924, -924, -924, -924, -924, -924, -924, -924, -924,
-     -924, -924, -924, -924, -924, -924, -924, -924, -924, -924,
-     -924, -924, -924, -924, -924, -924, -924, -924, -924, -924,
-     -924, -924,  925, -924, -924, -924, -924, -924, -924, -924,
-     -924, -924, -924, -924, -924, -924, -924, -924, -924, -924,
-     -924, -924, -924, -924, -924, -924, -924, -924, -924, -924,
-     -924, -924, -924, -924, -924, -924, -924, -924, -924, -924,
-     -924, -924, -924, -924, -924, -924, -924, -924, -924, -924,
-
-     -924, -924, -924, -924, -924, -924, -924, -924, -924, -924,
-     -924, -924, -924, -924, -924, -924, -924, -924, -924, -924,
-     -924, -924, -924, -924, -924, -924, -924, -924, -924, -924,
-     -924, -924, -924, -924, -924, -924, -924, -924, -924, -924,
-     -924, -924, -924, -924, -924, -924, -924, -924
-    },
-
-    {
-       67, -925, -925, -925, -925, -925, -925, -925, -925, -925,
-     -925, -925, -925, -925, -925, -925, -925, -925, -925, -925,
-     -925, -925, -925, -925, -925, -925, -925, -925, -925, -925,
-     -925, -925,  926, -925, -925, -925, -925, -925, -925, -925,
-     -925, -925, -925, -925, -925, -925, -925, -925, -925, -925,
-
-     -925, -925, -925, -925, -925, -925, -925, -925, -925, -925,
-     -925, -925, -925, -925, -925, -925, -925, -925, -925, -925,
-     -925, -925, -925, -925, -925, -925, -925, -925, -925, -925,
-     -925, -925, -925, -925, -925, -925, -925, -925, -925, -925,
-     -925, -925, -925, -925, -925, -925, -925, -925, -925, -925,
-     -925, -925, -925, -925, -925, -925, -925, -925, -925, -925,
-     -925, -925, -925, -925, -925, -925, -925, -925, -925, -925,
-     -925, -925, -925, -925, -925, -925, -925, -925
-    },
-
-    {
-       67, -926, -926, -926, -926, -926, -926, -926, -926, -926,
-     -926, -926, -926, -926, -926, -926, -926, -926, -926, -926,
-
-     -926, -926, -926, -926, -926, -926, -926, -926, -926, -926,
-     -926, -926, -926, -926, -926, -926, -926, -926, -926, -926,
-     -926, -926, -926, -926, -926, -926, -926, -926, -926, -926,
-     -926, -926, -926, -926, -926, -926, -926, -926, -926, -926,
-     -926, -926, -926, -926, -926, -926, -926, -926, -926, -926,
-     -926, -926, -926, -926, -926, -926, -926, -926, -926, -926,
-     -926, -926, -926, -926, -926, -926, -926, -926, -926, -926,
-     -926, -926, -926, -926, -926, -926, -926, -926, -926, -926,
-     -926, -926, -926, -926, -926, -926, -926, -926, -926, -926,
-     -926, -926, -926, -926, -926, -926, -926, -926, -926, -926,
-
-     -926, -926, -926, -926, -926, -926, -926, -926
-    },
-
-    } ;
-
-static yy_state_type yy_get_previous_state (void );
-static yy_state_type yy_try_NUL_trans (yy_state_type current_state  );
-static int yy_get_next_buffer (void );
-static void yy_fatal_error (yyconst char msg[]  );
-
-/* Done after the current pattern has been matched and before the
- * corresponding action - sets up wcsbthtext.
- */
-#define YY_DO_BEFORE_ACTION \
-	(yytext_ptr) = yy_bp; \
-	wcsbthleng = (size_t) (yy_cp - yy_bp); \
-	(yy_hold_char) = *yy_cp; \
-	*yy_cp = '\0'; \
-	(yy_c_buf_p) = yy_cp;
-
-#define YY_NUM_RULES 283
-#define YY_END_OF_BUFFER 284
-/* This struct is not used in this scanner,
-   but its presence is necessary. */
-struct yy_trans_info
-	{
-	flex_int32_t yy_verify;
-	flex_int32_t yy_nxt;
-	};
-static yyconst flex_int16_t yy_accept[927] =
-    {   0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,  278,  278,
-      280,  280,  281,  281,    0,    0,  284,  283,  126,  126,
-      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
-      126,  126,  126,  283,  148,  148,  140,  140,  149,  149,
-      141,  141,  161,  161,  161,  283,  182,  182,  171,  171,
-
-      187,  187,  198,  198,  199,  199,  230,  230,  265,  265,
-      243,  243,  266,  266,  244,  244,  268,  268,  201,  202,
-      200,  209,  209,  210,  210,  218,  218,  219,  219,  270,
-      270,  272,  272,  271,  274,  274,  274,  273,  276,  276,
-      279,  278,  277,  280,  281,  283,  282,    0,    0,    0,
-       64,   58,   21,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,   17,    0,   63,
-       57,    0,    0,    0,    0,    0,    0,    0,   23,    0,
-       19,   66,   60,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,  269,  271,
-        0,  273,  273,  273,  273,    0,    0,  275,  278,  277,
-      277,  280,  281,    0,  282,    0,    0,    0,    0,    0,
-        0,    0,    0,   65,   59,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,   24,    0,    0,    0,    0,    0,    0,
-
-       20,   67,   61,    0,    0,    0,    0,    0,    0,    0,
-        0,  127,  128,  129,    0,    0,    0,  130,  131,  132,
-      137,  136,    0,    0,    0,  133,  134,  135,  139,  138,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,  183,  184,  186,  185,  188,  189,  190,
-      195,  194,  191,  192,  193,  197,  196,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,  267,    0,    0,
-        0,  206,  207,  208,    0,    0,    0,  215,  216,  217,
-      273,    0,  273,   22,   18,   26,    0,   69,   74,    0,
-
-       13,   44,   79,   39,   34,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,   84,    0,    0,    0,   91,
-       51,   49,    0,   93,    0,    0,    0,  103,    0,   54,
-       56,  108,  106,  110,    0,   28,    0,   71,   76,    0,
-       15,   46,   81,   41,   36,    0,  122,  114,    0,    0,
-        0,    0,  112,    0,    0,  121,    0,    0,  124,  142,
-      143,  144,  145,  146,  147,    0,    0,    0,    0,    0,
-        0,  162,  163,  164,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,  203,  204,  205,  211,  212,  213,  214,   27,   70,
-       75,   31,   14,   45,   80,   40,   35,   25,   68,   73,
-       30,   12,   43,   78,   38,   33,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,   95,    0,   97,   99,  101,
-       62,    0,    0,    0,    0,    0,    0,    0,   29,   72,
-       77,   32,   16,   47,   82,   42,   37,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,  170,  167,  169,  165,  166,  168,
-
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,  236,  234,  235,  231,
-      232,  233,    0,    0,    0,    0,    0,    0,    0,    0,
-      242,  240,  241,  237,  238,  239,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,  160,  159,  155,  158,  152,  153,  157,  150,  151,
-      154,  156,  181,  177,  180,  174,  176,  179,  172,  173,
-      175,  178,  229,  225,  228,  222,  223,  227,  220,  221,
-
-      224,  226,  260,  250,  259,  248,  249,  258,  245,  246,
-      247,  257,  264,  256,  263,  254,  255,  262,  251,  252,
-      253,  261,    0,    0,    0,    0,    0,    0,    0,   90,
-       50,   48,    0,    0,    0,    0,  102,    0,   52,   55,
-      105,  107,  109,    0,  113,  111,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,  120,    0,    0,    0,    0,
-        0,    0,  123,   83,   85,   86,   87,   88,    0,   89,
-       92,   94,   96,   98,  100,  104,   53,    0,  115,  117,
-      118,  119,  116,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        1,    0,    0,    3,    0,    0,    4,    0,    0,    5,
-        0,    0,    2,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    6,    0,    7,
-        0,    8,    0,    9,    0,   10,    0,   11,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,  125
-    } ;
-
-static yy_state_type yy_last_accepting_state;
-static char *yy_last_accepting_cpos;
-
-static yyconst yy_state_type yy_NUL_trans[927] =
-    {   0,
-       68,   69,   68,   68,   85,   85,   87,   87,   89,   89,
-       91,   91,   93,   93,   68,   68,   97,   97,   99,   99,
-      101,  101,  103,  103,  105,  105,  107,  107,  109,  109,
-      111,  111,  113,  113,  115,  115,  117,  117,  119,  119,
-      120,  120,  122,  122,  124,  124,  126,  126,  128,  128,
-      130,  130,  132,  132,  135,  135,  139,  139,  141,  141,
-      144,  144,  145,  145,  146,  146,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,  247,
-        0,    0,  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,    0,  247,    0,    0,  251,
-      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,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,  847,    0,  849,    0,  851,    0,
-      853,    0,  855,    0,  857,    0,  847,    0,  849,    0,
-      851,    0,  853,    0,  855,    0,  857,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0
-    } ;
-
-extern int wcsbth_flex_debug;
-int wcsbth_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 yymore() yymore_used_but_not_detected
-#define YY_MORE_ADJ 0
-#define YY_RESTORE_YY_MORE_OFFSET
-char *wcsbthtext;
-#line 1 "wcsbth.l"
-/*============================================================================
-
-  WCSLIB 4.10 - an implementation of the FITS WCS standard.
-  Copyright (C) 1995-2012, Mark Calabretta
-
-  This file is part of WCSLIB.
-
-  WCSLIB is free software: you can redistribute it and/or modify it under the
-  terms of the GNU Lesser General Public License as published by the Free
-  Software Foundation, either version 3 of the License, or (at your option)
-  any later version.
-
-  WCSLIB 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 Lesser General Public License for
-  more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with WCSLIB.  If not, see <http://www.gnu.org/licenses/>.
-
-  Correspondence concerning WCSLIB may be directed to:
-    Internet email: mcalabre at atnf.csiro.au
-    Postal address: Dr. Mark Calabretta
-                    Australia Telescope National Facility, CSIRO
-                    PO Box 76
-                    Epping NSW 1710
-                    AUSTRALIA
-
-  Author: Mark Calabretta, Australia Telescope National Facility
-  http://www.atnf.csiro.au/~mcalabre/index.html
-  $Id: wcsbth.c,v 4.10 2012/02/05 23:41:44 cal103 Exp $
-*=============================================================================
-*
-* wcsbth.l is a Flex description file containing the definition of a lexical
-* scanner for parsing the WCS keyrecords for one or more image arrays and/or
-* pixel lists in a FITS binary table header.  It can also handle primary image
-* and image extension headers.
-*
-* wcsbth.l requires Flex v2.5.4 or later.  Refer to wcshdr.h for a description
-* of the user interface and operating notes.
-*
-* Implementation notes
-* --------------------
-* wcsbth() may be invoked with an option that causes it to recognise the
-* image-header form of WCS keywords as defaults for each alternate coordinate
-* representation (up to 27).  By design, with this option enabled wcsbth() can
-* also handle primary image and image extension headers, effectively treating
-* them as a single-column binary table though with WCS keywords of a different
-* form.
-*
-* NAXIS is always 2 for binary tables, it refers to the two-dimensional nature
-* of the table.  Thus NAXIS does not count the number of image axes in either
-* image arrays or pixels lists and for the latter there is not even a formal
-* equivalent of WCSAXESa.  Hence NAXIS is always ignored and a first pass
-* through the header is required to determine the number of images, the number
-* of alternate coordinate representations for each image (up to 27), and the
-* number of coordinate axes in each representation; this pass also counts the
-* number of iPVn_ma and iPSn_ma or TVk_ma and TSk_ma keywords in each
-* representation.
-*
-* On completion of the first pass, the association between column number and
-* axis number is defined for each representation of a pixel list.  Memory is
-* allocated for an array of the required number of wcsprm structs and each of
-* these is initialized appropriately.  These structs are filled in the second
-* pass.
-*
-* It is permissible for a scalar table column to contain degenerate (single-
-* point) image arrays and simultaneously form one axis of a pixel list.
-*
-* The parser does not check for duplicated keywords, for most keywords it
-* accepts the last encountered.
-*
-* wcsbth() does not currently handle the Green Bank convention.
-*
-*===========================================================================*/
-/* Options. */
-/* Indices for parameterized keywords. */
-/* Alternate coordinate system identifier. */
-/* Keyvalue data types. */
-/* Exclusive start states. */
-
-
-
-
-
-
-
-
-
-
-#line 112 "wcsbth.l"
-#include <math.h>
-#include <setjmp.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "wcs.h"
-#include "wcshdr.h"
-#include "wcsmath.h"
-
-			/* Codes used for keyvalue data types. */
-#define INTEGER 0
-#define FLOAT   1
-#define STRING  2
-
-			/* Bit masks used for keyword types:        */
-#define IMGAUX  0x1	/* Auxiliary image header, e.g. LONPOLEa or */
-			/* DATE-OBS.                                */
-#define IMGAXIS 0x2	/* Image header with axis number, e.g.      */
-			/* CTYPEia.                                 */
-#define IMGHEAD 0x3	/* Image header of either type.             */
-#define BIMGARR 0x4	/* Binary table image array with axis       */
-			/* number, e.g. iCTYna.                     */
-#define PIXLIST 0x8	/* Pixel list, e.g. TCTYna.                 */
-#define BINTAB  0xC	/* Shared binary table image array (without */
-			/* axis number) or pixel list, e.g. LONPna  */
-			/* or OBSGXn.                               */
-
-#define YY_DECL int wcsbth(char *header, int nkeyrec, int relax, int ctrl, \
-                           int keysel, int *colsel, int *nreject, int *nwcs, \
-			   struct wcsprm **wcs)
-
-#define YY_INPUT(inbuff, count, bufsize) \
-	{ \
-	  if (wcsbth_nkeyrec) { \
-	    strncpy(inbuff, wcsbth_hdr, 80); \
-	    inbuff[80] = '\n'; \
-	    wcsbth_hdr += 80; \
-	    wcsbth_nkeyrec--; \
-	    count = 81; \
-	  } else { \
-	    count = YY_NULL; \
-	  } \
-	}
-
-/* A convenience macro to get around incompatibilities between unput() and
-   yyless(): put wcsbthtext followed by a blank back onto the input stream. */
-#define WCSBTH_PUTBACK \
-  sprintf(stmp, "%s ", wcsbthtext); \
-  itmp = strlen(stmp); \
-  while (itmp) unput(stmp[--itmp]);
-
-/* These global variables are required by YY_INPUT. */
-char *wcsbth_hdr;
-int  wcsbth_nkeyrec;
-
-/* Used in preempting the call to exit() by yy_fatal_error(). */
-jmp_buf wcsbth_abort_jmp_env;
-#define exit(status) longjmp(wcsbth_abort_jmp_env, status)
-
-/* Struct used internally for header bookkeeping. */
-struct wcsbth_alts {
-  int ncol, ialt, icol, imgherit;
-  short int (*arridx)[27];
-  short int pixidx[27];
-  short int pad1;
-  unsigned int *pixlist;
-
-  unsigned char (*npv)[27];
-  unsigned char (*nps)[27];
-  unsigned char pixnpv[27];
-  unsigned char pixnps[27];
-  unsigned char pad2[2];
-};
-
-int wcsbth_pass1(int keytype, int i, int j, int n, int k, char a, char ptype,
-        struct wcsbth_alts *alts);
-int wcsbth_init1(struct wcsbth_alts *alts, int *nwcs, struct wcsprm **wcs);
-
-struct wcsprm *wcsbth_idx(struct wcsprm *wcs, struct wcsbth_alts *alts,
-        int keytype, int n, char a);
-int wcsbth_colax(struct wcsprm *wcs, struct wcsbth_alts *alts, int k, char a);
-
-int wcsbth_epoch(void *wptr);
-int wcsbth_vsource(void *wptr);
-
-int wcsbth_final(struct wcsbth_alts *alts, int *nwcs, struct wcsprm **wcs);
-
-#line 16850 "wcsbth.c"
-
-#define INITIAL 0
-#define CCCCCia 1
-#define iCCCna 2
-#define iCCCCn 3
-#define TCCCna 4
-#define TCCCCn 5
-#define CCi_ja 6
-#define ijCCna 7
-#define TCn_ka 8
-#define TCCn_ka 9
-#define CROTAi 10
-#define iCROTn 11
-#define TCROTn 12
-#define CCi_ma 13
-#define iCn_ma 14
-#define iCCn_ma 15
-#define TCn_ma 16
-#define TCCn_ma 17
-#define PROJPm 18
-#define CCCCCCCC 19
-#define CCCCCCCa 20
-#define CCCCna 21
-#define CCCCCna 22
-#define CCCCn 23
-#define CCCCCn 24
-#define VALUE 25
-#define INTEGER_VAL 26
-#define FLOAT_VAL 27
-#define STRING_VAL 28
-#define COMMENT 29
-#define DISCARD 30
-#define ERROR 31
-#define FLUSH 32
-
-#ifndef YY_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 <unistd.h>
-#endif
-
-#ifndef YY_EXTRA_TYPE
-#define YY_EXTRA_TYPE void *
-#endif
-
-static int yy_init_globals (void );
-
-/* Accessor methods to globals.
-   These are made visible to non-reentrant scanners for convenience. */
-
-int wcsbthlex_destroy (void );
-
-int wcsbthget_debug (void );
-
-void wcsbthset_debug (int debug_flag  );
-
-YY_EXTRA_TYPE wcsbthget_extra (void );
-
-void wcsbthset_extra (YY_EXTRA_TYPE user_defined  );
-
-FILE *wcsbthget_in (void );
-
-void wcsbthset_in  (FILE * in_str  );
-
-FILE *wcsbthget_out (void );
-
-void wcsbthset_out  (FILE * out_str  );
-
-int wcsbthget_leng (void );
-
-char *wcsbthget_text (void );
-
-int wcsbthget_lineno (void );
-
-void wcsbthset_lineno (int line_number  );
-
-/* Macros after this point can all be overridden by user definitions in
- * section 1.
- */
-
-#ifndef YY_SKIP_YYWRAP
-#ifdef __cplusplus
-extern "C" int wcsbthwrap (void );
-#else
-extern int wcsbthwrap (void );
-#endif
-#endif
-
-    static void yyunput (int c,char *buf_ptr  );
-    
-#ifndef yytext_ptr
-static void yy_flex_strncpy (char *,yyconst char *,int );
-#endif
-
-#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * );
-#endif
-
-#ifndef YY_NO_INPUT
-
-#ifdef __cplusplus
-static int yyinput (void );
-#else
-static int input (void );
-#endif
-
-#endif
-
-/* Amount of stuff to slurp up with each read. */
-#ifndef YY_READ_BUF_SIZE
-#ifdef __ia64__
-/* On IA-64, the buffer size is 16k, not 8k */
-#define YY_READ_BUF_SIZE 16384
-#else
-#define YY_READ_BUF_SIZE 8192
-#endif /* __ia64__ */
-#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( wcsbthtext, wcsbthleng, 1, wcsbthout )) {} } while (0)
-#endif
-
-/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
- * is returned in "result".
- */
-#ifndef YY_INPUT
-#define YY_INPUT(buf,result,max_size) \
-	errno=0; \
-	while ( (result = read( fileno(wcsbthin), (char *) buf, max_size )) < 0 ) \
-	{ \
-		if( errno != EINTR) \
-		{ \
-			YY_FATAL_ERROR( "input in flex scanner failed" ); \
-			break; \
-		} \
-		errno=0; \
-		clearerr(wcsbthin); \
-	}\
-\
-
-#endif
-
-/* No semi-colon after return; correct usage is to write "yyterminate();" -
- * we don't want an extra ';' after the "return" because that will cause
- * some compilers to complain about unreachable statements.
- */
-#ifndef yyterminate
-#define yyterminate() return YY_NULL
-#endif
-
-/* Number of entries by which start-condition stack grows. */
-#ifndef YY_START_STACK_INCR
-#define YY_START_STACK_INCR 25
-#endif
-
-/* Report a fatal error. */
-#ifndef YY_FATAL_ERROR
-#define YY_FATAL_ERROR(msg) yy_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 YY_DECL
-#define YY_DECL_IS_OURS 1
-
-extern int wcsbthlex (void);
-
-#define YY_DECL int wcsbthlex (void)
-#endif /* !YY_DECL */
-
-/* Code executed at the beginning of each rule, after wcsbthtext and wcsbthleng
- * have been set up.
- */
-#ifndef YY_USER_ACTION
-#define YY_USER_ACTION
-#endif
-
-/* Code executed at the end of each rule. */
-#ifndef YY_BREAK
-#define YY_BREAK break;
-#endif
-
-#define YY_RULE_SETUP \
-	if ( wcsbthleng > 0 ) \
-		YY_CURRENT_BUFFER_LVALUE->yy_at_bol = \
-				(wcsbthtext[wcsbthleng - 1] == '\n'); \
-	YY_USER_ACTION
-
-/** The main scanner function which does all the work.
- */
-YY_DECL
-{
-	register yy_state_type yy_current_state;
-	register char *yy_cp, *yy_bp;
-	register int yy_act;
-    
-#line 202 "wcsbth.l"
-
-	/* Keyword indices, as used in the WCS papers, e.g. iVn_ma, TPn_ka. */
-	char a;
-	int  i, j, k, m, n;
-	
-	char *cptr, *errmsg, errtxt[80], exclude[1000], *extkey, *hptr, ptype,
-	     stmp[16];
-	int  altlin, ialt, icol, incl, ipass, ipx, itmp, ix, jx, keytype,
-	     nsel, npass, status, valtype, voff;
-	void   *vptr, *wptr;
-	struct wcsbth_alts alts;
-	struct wcsprm *wcsp, wcstem;
-	int (*special)(void *);
-	int wcsbthlex_destroy(void);
-	
-	/* The data structures produced. */
-	*nwcs = 0;
-	*wcs  = 0x0;
-	
-	/* Parameters used to implement YY_INPUT. */
-	wcsbth_hdr = header;
-	wcsbth_nkeyrec = nkeyrec;
-	
-	/* Our handle on the input stream. */
-	hptr = header;
-	*nreject = 0;
-	
-	/* Keyword parameters. */
-	i = j = 0;
-	n = k = 0;
-	m = 0;
-	a = ' ';
-	
-	/* Header bookkeeping. */
-	alts.ncol = 0;
-	alts.arridx  = 0x0;
-	alts.pixlist = 0x0;
-	alts.npv = 0x0;
-	alts.nps = 0x0;
-	
-	for (ialt = 0; ialt < 27; ialt++) {
-	  alts.pixidx[ialt] = 0;
-	  alts.pixnpv[ialt] = 0;
-	  alts.pixnps[ialt] = 0;
-	}
-	
-	/* For decoding the keyvalue. */
-	keytype =  0;
-	valtype = -1;
-	vptr    = 0x0;
-	
-	/* For keywords that require special handling. */
-	altlin = 0;
-	ptype  = ' ';
-	special = 0x0;
-	
-	/* Selection by column number. */
-	nsel = colsel ? colsel[0] : 0;
-	incl = (nsel > 0);
-	for (icol = 0; icol < 1000; icol++) {
-	  exclude[icol] = incl;
-	}
-	for (icol = 1; icol <= abs(nsel); icol++) {
-	  itmp = colsel[icol];
-	  if (0 < itmp && itmp < 1000) {
-	    exclude[itmp] = !incl;
-	  }
-	}
-	exclude[0] = 0;
-	
-	/* Selection by keyword type. */
-	itmp = keysel;
-	keysel = 0;
-	if (itmp) {
-	  if (itmp & WCSHDR_IMGHEAD) keysel |= IMGHEAD;
-	  if (itmp & WCSHDR_BIMGARR) keysel |= BIMGARR;
-	  if (itmp & WCSHDR_PIXLIST) keysel |= PIXLIST;
-	}
-	if (keysel == 0) {
-	  keysel = IMGHEAD | BINTAB;
-	}
-	
-	/* Control variables. */
-	ipass = 1;
-	npass = 2;
-	
-	/* Return here via longjmp() invoked by yy_fatal_error(). */
-	if (setjmp(wcsbth_abort_jmp_env)) {
-	  return 4;
-	}
-	
-	BEGIN(INITIAL);
-
-
-#line 17151 "wcsbth.c"
-
-	if ( !(yy_init) )
-		{
-		(yy_init) = 1;
-
-#ifdef YY_USER_INIT
-		YY_USER_INIT;
-#endif
-
-		if ( ! (yy_start) )
-			(yy_start) = 1;	/* first start state */
-
-		if ( ! wcsbthin )
-			wcsbthin = stdin;
-
-		if ( ! wcsbthout )
-			wcsbthout = stdout;
-
-		if ( ! YY_CURRENT_BUFFER ) {
-			wcsbthensure_buffer_stack ();
-			YY_CURRENT_BUFFER_LVALUE =
-				wcsbth_create_buffer(wcsbthin,YY_BUF_SIZE );
-		}
-
-		wcsbth_load_buffer_state( );
-		}
-
-	while ( 1 )		/* loops until end-of-file is reached */
-		{
-		yy_cp = (yy_c_buf_p);
-
-		/* Support of wcsbthtext. */
-		*yy_cp = (yy_hold_char);
-
-		/* yy_bp points to the position in yy_ch_buf of the start of
-		 * the current run.
-		 */
-		yy_bp = yy_cp;
-
-		yy_current_state = (yy_start);
-		yy_current_state += YY_AT_BOL();
-yy_match:
-		while ( (yy_current_state = yy_nxt[yy_current_state][ YY_SC_TO_UI(*yy_cp) ]) > 0 )
-			{
-			if ( yy_accept[yy_current_state] )
-				{
-				(yy_last_accepting_state) = yy_current_state;
-				(yy_last_accepting_cpos) = yy_cp;
-				}
-
-			++yy_cp;
-			}
-
-		yy_current_state = -yy_current_state;
-
-yy_find_action:
-		yy_act = yy_accept[yy_current_state];
-
-		YY_DO_BEFORE_ACTION;
-
-do_action:	/* This label is used only to access EOF actions. */
-
-		switch ( yy_act )
-	{ /* beginning of action switch */
-			case 0: /* must back up */
-			/* undo the effects of YY_DO_BEFORE_ACTION */
-			*yy_cp = (yy_hold_char);
-			yy_cp = (yy_last_accepting_cpos) + 1;
-			yy_current_state = (yy_last_accepting_state);
-			goto yy_find_action;
-
-case 1:
-YY_RULE_SETUP
-#line 296 "wcsbth.l"
-{
-	  if (ipass == 1) {
-	    if (alts.ncol == 0) {
-	      sscanf(wcsbthtext, "TFIELDS = %d", &(alts.ncol));
-	      BEGIN(FLUSH);
-	    } else {
-	      errmsg = "Duplicate or out-of-sequence TFIELDS keyword";
-	      BEGIN(ERROR);
-	    }
-	
-	  } else {
-	    BEGIN(FLUSH);
-	  }
-	}
-	YY_BREAK
-case 2:
-YY_RULE_SETUP
-#line 311 "wcsbth.l"
-{
-	  keytype = IMGAXIS;
-	
-	  if (!(keytype & keysel)) {
-	    /* Ignore this key type. */
-	    BEGIN(DISCARD);
-	
-	  } else {
-	    if (relax & WCSHDR_ALLIMG) {
-	      if (ipass == 1) {
-	        sscanf(wcsbthtext, "WCSAXES%c= %d", &a, &i);
-	        wcsbth_pass1(IMGAXIS, i, 0, 0, 0, a, ' ', &alts);
-	      }
-	
-	      BEGIN(FLUSH);
-	
-	    } else if (relax & WCSHDR_reject) {
-	      errmsg = "Image-header keyword WCSAXESa in binary table";
-	      BEGIN(ERROR);
-	
-	    } else {
-	      /* Pretend we don't recognize it. */
-	      BEGIN(DISCARD);
-	    }
-	  }
-	}
-	YY_BREAK
-case 3:
-#line 339 "wcsbth.l"
-case 4:
-#line 340 "wcsbth.l"
-case 5:
-YY_RULE_SETUP
-#line 340 "wcsbth.l"
-{
-	  keytype = BIMGARR;
-	
-	  /* Note that a blank in the sscanf() format string matches zero or
-	     more of them in the input. */
-	  sscanf(wcsbthtext, "WCAX%d%c = %d", &n, &a, &i);
-	
-	  if (!(keytype & keysel) || exclude[n]) {
-	    /* Ignore this key type or column. */
-	    BEGIN(DISCARD);
-	  } else {
-	    if (ipass == 1) {
-	      wcsbth_pass1(BIMGARR, i, 0, n, 0, a, ' ', &alts);
-	    }
-	    BEGIN(FLUSH);
-	  }
-	}
-	YY_BREAK
-case 6:
-/* rule 6 can match eol */
-#line 359 "wcsbth.l"
-case 7:
-/* rule 7 can match eol */
-#line 360 "wcsbth.l"
-case 8:
-/* rule 8 can match eol */
-YY_RULE_SETUP
-#line 360 "wcsbth.l"
-{
-	  /* Cross-reference supplier. */
-	  keytype = BIMGARR;
-	  errmsg = "Cross-references are not currently implemented";
-	  BEGIN(ERROR);
-	}
-	YY_BREAK
-case 9:
-/* rule 9 can match eol */
-#line 368 "wcsbth.l"
-case 10:
-/* rule 10 can match eol */
-#line 369 "wcsbth.l"
-case 11:
-/* rule 11 can match eol */
-YY_RULE_SETUP
-#line 369 "wcsbth.l"
-{
-	  /* Cross-reference consumer. */
-	  keytype = BIMGARR;
-	  errmsg = "Cross-references are not currently implemented";
-	  BEGIN(ERROR);
-	}
-	YY_BREAK
-case 12:
-YY_RULE_SETUP
-#line 376 "wcsbth.l"
-{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.crpix);
-	
-	  extkey = "CRPIXja";
-	  BEGIN(CCCCCia);
-	}
-	YY_BREAK
-case 13:
-#line 385 "wcsbth.l"
-case 14:
-YY_RULE_SETUP
-#line 385 "wcsbth.l"
-{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.crpix);
-	
-	  sscanf(wcsbthtext, "%d", &i);
-	
-	  if (wcsbthleng == 4) {
-	    BEGIN(iCCCna);
-	  } else {
-	    extkey = "jCRPXn";
-	    BEGIN(iCCCCn);
-	  }
-	}
-	YY_BREAK
-case 15:
-#line 400 "wcsbth.l"
-case 16:
-YY_RULE_SETUP
-#line 400 "wcsbth.l"
-{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.crpix);
-	
-	  if (wcsbthleng == 4) {
-	    BEGIN(TCCCna);
-	  } else {
-	    extkey = "TCRPXn";
-	    BEGIN(TCCCCn);
-	  }
-	}
-	YY_BREAK
-case 17:
-YY_RULE_SETUP
-#line 412 "wcsbth.l"
-{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.pc);
-	  altlin = 1;
-	
-	  extkey = "PCi_ja";
-	  BEGIN(CCi_ja);
-	}
-	YY_BREAK
-case 18:
-YY_RULE_SETUP
-#line 421 "wcsbth.l"
-{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.pc);
-	  altlin = 1;
-	
-	  sscanf(wcsbthtext, "%1d%1d", &i, &j);
-	
-	  BEGIN(ijCCna);
-	}
-	YY_BREAK
-case 19:
-#line 432 "wcsbth.l"
-case 20:
-YY_RULE_SETUP
-#line 432 "wcsbth.l"
-{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.pc);
-	  altlin = 1;
-	
-	  if (wcsbthleng == 2) {
-	    BEGIN(TCn_ka);
-	  } else {
-	    extkey = "TPCn_ka";
-	    BEGIN(TCCn_ka);
-	  }
-	}
-	YY_BREAK
-case 21:
-YY_RULE_SETUP
-#line 445 "wcsbth.l"
-{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.cd);
-	  altlin = 2;
-	
-	  extkey = "CDi_ja";
-	  BEGIN(CCi_ja);
-	}
-	YY_BREAK
-case 22:
-YY_RULE_SETUP
-#line 454 "wcsbth.l"
-{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.cd);
-	  altlin = 2;
-	
-	  sscanf(wcsbthtext, "%1d%1d", &i, &j);
-	
-	  BEGIN(ijCCna);
-	}
-	YY_BREAK
-case 23:
-#line 465 "wcsbth.l"
-case 24:
-YY_RULE_SETUP
-#line 465 "wcsbth.l"
-{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.cd);
-	  altlin = 2;
-	
-	  if (wcsbthleng == 2) {
-	    BEGIN(TCn_ka);
-	  } else {
-	    extkey = "TCDn_ka";
-	    BEGIN(TCCn_ka);
-	  }
-	}
-	YY_BREAK
-case 25:
-YY_RULE_SETUP
-#line 478 "wcsbth.l"
-{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.cdelt);
-	
-	  extkey = "CDELTia";
-	  BEGIN(CCCCCia);
-	}
-	YY_BREAK
-case 26:
-#line 487 "wcsbth.l"
-case 27:
-YY_RULE_SETUP
-#line 487 "wcsbth.l"
-{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.cdelt);
-	
-	  sscanf(wcsbthtext, "%d", &i);
-	
-	  if (wcsbthleng == 4) {
-	    BEGIN(iCCCna);
-	  } else {
-	    extkey = "iCDLTn";
-	    BEGIN(iCCCCn);
-	  }
-	}
-	YY_BREAK
-case 28:
-#line 502 "wcsbth.l"
-case 29:
-YY_RULE_SETUP
-#line 502 "wcsbth.l"
-{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.cdelt);
-	
-	  if (wcsbthleng == 4) {
-	    BEGIN(TCCCna);
-	  } else {
-	    extkey = "TCDLTn";
-	    BEGIN(TCCCCn);
-	  }
-	}
-	YY_BREAK
-case 30:
-YY_RULE_SETUP
-#line 514 "wcsbth.l"
-{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.crota);
-	  altlin = 4;
-	
-	  extkey = "CROTAi";
-	  BEGIN(CROTAi);
-	}
-	YY_BREAK
-case 31:
-YY_RULE_SETUP
-#line 523 "wcsbth.l"
-{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.crota);
-	  altlin = 4;
-	
-	  sscanf(wcsbthtext, "%d", &i);
-	
-	  extkey = "iCROTn";
-	  BEGIN(iCROTn);
-	}
-	YY_BREAK
-case 32:
-YY_RULE_SETUP
-#line 534 "wcsbth.l"
-{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.crota);
-	  altlin = 4;
-	
-	  extkey = "TCROTn";
-	  BEGIN(TCROTn);
-	}
-	YY_BREAK
-case 33:
-YY_RULE_SETUP
-#line 543 "wcsbth.l"
-{
-	  valtype = STRING;
-	  vptr = &(wcstem.cunit);
-	
-	  extkey = "CUNITia";
-	  BEGIN(CCCCCia);
-	}
-	YY_BREAK
-case 34:
-#line 552 "wcsbth.l"
-case 35:
-YY_RULE_SETUP
-#line 552 "wcsbth.l"
-{
-	  valtype = STRING;
-	  vptr = &(wcstem.cunit);
-	
-	  sscanf(wcsbthtext, "%d", &i);
-	
-	  if (wcsbthleng == 4) {
-	    BEGIN(iCCCna);
-	  } else {
-	    extkey = "iCUNIn";
-	    BEGIN(iCCCCn);
-	  }
-	}
-	YY_BREAK
-case 36:
-#line 567 "wcsbth.l"
-case 37:
-YY_RULE_SETUP
-#line 567 "wcsbth.l"
-{
-	  valtype = STRING;
-	  vptr = &(wcstem.cunit);
-	
-	  if (wcsbthleng == 4) {
-	    BEGIN(TCCCna);
-	  } else {
-	    extkey = "TCUNIn";
-	    BEGIN(TCCCCn);
-	  }
-	}
-	YY_BREAK
-case 38:
-YY_RULE_SETUP
-#line 579 "wcsbth.l"
-{
-	  valtype = STRING;
-	  vptr = &(wcstem.ctype);
-	
-	  extkey = "CTYPEia";
-	  BEGIN(CCCCCia);
-	}
-	YY_BREAK
-case 39:
-#line 588 "wcsbth.l"
-case 40:
-YY_RULE_SETUP
-#line 588 "wcsbth.l"
-{
-	  valtype = STRING;
-	  vptr = &(wcstem.ctype);
-	
-	  sscanf(wcsbthtext, "%d", &i);
-	
-	  if (wcsbthleng == 4) {
-	    BEGIN(iCCCna);
-	  } else {
-	    extkey = "iCTYPn";
-	    BEGIN(iCCCCn);
-	  }
-	}
-	YY_BREAK
-case 41:
-#line 603 "wcsbth.l"
-case 42:
-YY_RULE_SETUP
-#line 603 "wcsbth.l"
-{
-	  valtype = STRING;
-	  vptr = &(wcstem.ctype);
-	
-	  if (wcsbthleng == 4) {
-	    BEGIN(TCCCna);
-	  } else {
-	    extkey = "TCTYPn";
-	    BEGIN(TCCCCn);
-	  }
-	}
-	YY_BREAK
-case 43:
-YY_RULE_SETUP
-#line 615 "wcsbth.l"
-{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.crval);
-	
-	  extkey = "CRVALia";
-	  BEGIN(CCCCCia);
-	}
-	YY_BREAK
-case 44:
-#line 624 "wcsbth.l"
-case 45:
-YY_RULE_SETUP
-#line 624 "wcsbth.l"
-{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.crval);
-	
-	  sscanf(wcsbthtext, "%d", &i);
-	
-	  if (wcsbthleng == 4) {
-	    BEGIN(iCCCna);
-	  } else {
-	    extkey = "iCRVLn";
-	    BEGIN(iCCCCn);
-	  }
-	}
-	YY_BREAK
-case 46:
-#line 639 "wcsbth.l"
-case 47:
-YY_RULE_SETUP
-#line 639 "wcsbth.l"
-{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.crval);
-	
-	  if (wcsbthleng == 4) {
-	    BEGIN(TCCCna);
-	  } else {
-	    extkey = "TCRVLn";
-	    BEGIN(TCCCCn);
-	  }
-	}
-	YY_BREAK
-case 48:
-#line 652 "wcsbth.l"
-case 49:
-YY_RULE_SETUP
-#line 652 "wcsbth.l"
-{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.lonpole);
-	
-	  if (wcsbthleng == 7) {
-	    extkey = "LONPOLEa";
-	    BEGIN(CCCCCCCa);
-	  } else {
-	    BEGIN(CCCCna);
-	  }
-	}
-	YY_BREAK
-case 50:
-#line 665 "wcsbth.l"
-case 51:
-YY_RULE_SETUP
-#line 665 "wcsbth.l"
-{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.latpole);
-	
-	  if (wcsbthleng == 7) {
-	    extkey = "LATPOLEa";
-	    BEGIN(CCCCCCCa);
-	  } else {
-	    BEGIN(CCCCna);
-	  }
-	}
-	YY_BREAK
-case 52:
-#line 678 "wcsbth.l"
-case 53:
-#line 679 "wcsbth.l"
-case 54:
-YY_RULE_SETUP
-#line 679 "wcsbth.l"
-{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.restfrq);
-	
-	  if (wcsbthleng == 8) {
-	    unput(' ');
-	    extkey = "RESTFREQ";
-	    BEGIN(CCCCCCCa);
-	  } else if (wcsbthleng == 7) {
-	    extkey = "RESTFRQa";
-	    BEGIN(CCCCCCCa);
-	  } else {
-	    BEGIN(CCCCna);
-	  }
-	}
-	YY_BREAK
-case 55:
-#line 696 "wcsbth.l"
-case 56:
-YY_RULE_SETUP
-#line 696 "wcsbth.l"
-{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.restwav);
-	
-	  if (wcsbthleng == 7) {
-	    extkey = "RESTWAVa";
-	    BEGIN(CCCCCCCa);
-	  } else {
-	    BEGIN(CCCCna);
-	  }
-	}
-	YY_BREAK
-case 57:
-YY_RULE_SETUP
-#line 708 "wcsbth.l"
-{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.pv);
-	  ptype = 'v';
-	
-	  extkey = "PVi_ma";
-	  BEGIN(CCi_ma);
-	}
-	YY_BREAK
-case 58:
-#line 718 "wcsbth.l"
-case 59:
-YY_RULE_SETUP
-#line 718 "wcsbth.l"
-{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.pv);
-	  ptype = 'v';
-	
-	  sscanf(wcsbthtext, "%d", &i);
-	
-	  if (wcsbthleng == 2) {
-	    BEGIN(iCn_ma);
-	  } else {
-	    extkey = "iPVn_ma";
-	    BEGIN(iCCn_ma);
-	  }
-	}
-	YY_BREAK
-case 60:
-#line 734 "wcsbth.l"
-case 61:
-YY_RULE_SETUP
-#line 734 "wcsbth.l"
-{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.pv);
-	  ptype = 'v';
-	
-	  if (wcsbthleng == 2) {
-	    BEGIN(TCn_ma);
-	  } else {
-	    extkey = "TPVn_ma";
-	    BEGIN(TCCn_ma);
-	  }
-	}
-	YY_BREAK
-case 62:
-YY_RULE_SETUP
-#line 747 "wcsbth.l"
-{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.pv);
-	  ptype = 'v';
-	
-	  BEGIN(PROJPm);
-	}
-	YY_BREAK
-case 63:
-YY_RULE_SETUP
-#line 755 "wcsbth.l"
-{
-	  valtype = STRING;
-	  vptr = &(wcstem.ps);
-	  ptype = 's';
-	
-	  extkey = "PSi_ma";
-	  BEGIN(CCi_ma);
-	}
-	YY_BREAK
-case 64:
-#line 765 "wcsbth.l"
-case 65:
-YY_RULE_SETUP
-#line 765 "wcsbth.l"
-{
-	  valtype = STRING;
-	  vptr = &(wcstem.ps);
-	  ptype = 's';
-	
-	  sscanf(wcsbthtext, "%d", &i);
-	
-	  if (wcsbthleng == 2) {
-	    BEGIN(iCn_ma);
-	  } else {
-	    extkey = "iPSn_ma";
-	    BEGIN(iCCn_ma);
-	  }
-	}
-	YY_BREAK
-case 66:
-#line 781 "wcsbth.l"
-case 67:
-YY_RULE_SETUP
-#line 781 "wcsbth.l"
-{
-	  valtype = STRING;
-	  vptr = &(wcstem.ps);
-	  ptype = 's';
-	
-	  if (wcsbthleng == 2) {
-	    BEGIN(TCn_ma);
-	  } else {
-	    extkey = "TPSn_ma";
-	    BEGIN(TCCn_ma);
-	  }
-	}
-	YY_BREAK
-case 68:
-YY_RULE_SETUP
-#line 794 "wcsbth.l"
-{
-	  valtype = STRING;
-	  vptr = &(wcstem.cname);
-	
-	  extkey = "CNAMEia";
-	  BEGIN(CCCCCia);
-	}
-	YY_BREAK
-case 69:
-#line 803 "wcsbth.l"
-case 70:
-YY_RULE_SETUP
-#line 803 "wcsbth.l"
-{
-	  valtype = STRING;
-	  vptr = &(wcstem.cname);
-	
-	  sscanf(wcsbthtext, "%d", &i);
-	
-	  if (wcsbthleng == 4) {
-	    BEGIN(iCCCna);
-	  } else {
-	    if (!(relax & WCSHDR_CNAMn)) vptr = 0x0;
-	    extkey = "iCNAMn";
-	    BEGIN(iCCCCn);
-	  }
-	}
-	YY_BREAK
-case 71:
-#line 819 "wcsbth.l"
-case 72:
-YY_RULE_SETUP
-#line 819 "wcsbth.l"
-{
-	  valtype = STRING;
-	  vptr = &(wcstem.cname);
-	
-	  if (wcsbthleng == 4) {
-	    BEGIN(TCCCna);
-	  } else {
-	    if (!(relax & WCSHDR_CNAMn)) vptr = 0x0;
-	    extkey = "TCNAMn";
-	    BEGIN(TCCCCn);
-	  }
-	}
-	YY_BREAK
-case 73:
-YY_RULE_SETUP
-#line 832 "wcsbth.l"
-{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.crder);
-	
-	  extkey = "CRDERia";
-	  BEGIN(CCCCCia);
-	}
-	YY_BREAK
-case 74:
-#line 841 "wcsbth.l"
-case 75:
-YY_RULE_SETUP
-#line 841 "wcsbth.l"
-{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.crder);
-	
-	  sscanf(wcsbthtext, "%d", &i);
-	
-	  if (wcsbthleng == 4) {
-	    BEGIN(iCCCna);
-	  } else {
-	    if (!(relax & WCSHDR_CNAMn)) vptr = 0x0;
-	    extkey = "iCRDEn";
-	    BEGIN(iCCCCn);
-	  }
-	}
-	YY_BREAK
-case 76:
-#line 857 "wcsbth.l"
-case 77:
-YY_RULE_SETUP
-#line 857 "wcsbth.l"
-{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.crder);
-	
-	  if (wcsbthleng == 4) {
-	    BEGIN(TCCCna);
-	  } else {
-	    if (!(relax & WCSHDR_CNAMn)) vptr = 0x0;
-	    extkey = "TCRDEn";
-	    BEGIN(TCCCCn);
-	  }
-	}
-	YY_BREAK
-case 78:
-YY_RULE_SETUP
-#line 870 "wcsbth.l"
-{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.csyer);
-	
-	  extkey = "CSYERia";
-	  BEGIN(CCCCCia);
-	}
-	YY_BREAK
-case 79:
-#line 879 "wcsbth.l"
-case 80:
-YY_RULE_SETUP
-#line 879 "wcsbth.l"
-{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.csyer);
-	
-	  sscanf(wcsbthtext, "%d", &i);
-	
-	  if (wcsbthleng == 4) {
-	    BEGIN(iCCCna);
-	  } else {
-	    if (!(relax & WCSHDR_CNAMn)) vptr = 0x0;
-	    extkey = "iCSYEn";
-	    BEGIN(iCCCCn);
-	  }
-	}
-	YY_BREAK
-case 81:
-#line 895 "wcsbth.l"
-case 82:
-YY_RULE_SETUP
-#line 895 "wcsbth.l"
-{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.csyer);
-	
-	  if (wcsbthleng == 4) {
-	    BEGIN(TCCCna);
-	  } else {
-	    if (!(relax & WCSHDR_CNAMn)) vptr = 0x0;
-	    extkey = "TCSYEn";
-	    BEGIN(TCCCCn);
-	  }
-	}
-	YY_BREAK
-case 83:
-#line 909 "wcsbth.l"
-case 84:
-YY_RULE_SETUP
-#line 909 "wcsbth.l"
-{
-	  valtype = STRING;
-	  vptr = wcstem.dateavg;
-	
-	  if (wcsbthleng == 8) {
-	    extkey = "DATE-AVG";
-	    BEGIN(CCCCCCCC);
-	  } else {
-	    BEGIN(CCCCn);
-	  }
-	}
-	YY_BREAK
-case 85:
-YY_RULE_SETUP
-#line 921 "wcsbth.l"
-{
-	  valtype = STRING;
-	  vptr = wcstem.dateobs;
-	
-	  extkey = "DATE-OBS";
-	  BEGIN(CCCCCCCC);
-	}
-	YY_BREAK
-case 86:
-#line 930 "wcsbth.l"
-case 87:
-#line 931 "wcsbth.l"
-case 88:
-YY_RULE_SETUP
-#line 931 "wcsbth.l"
-{
-	  if (relax & WCSHDR_DOBSn) {
-	    valtype = STRING;
-	    vptr = wcstem.dateobs;
-	
-	    yyless(4);
-	    BEGIN(CCCCn);
-	
-	  } else {
-	    keytype = BINTAB;
-	    if (relax & WCSHDR_reject) {
-	      errmsg = "DOBSna keyword is non-standard";
-	      BEGIN(ERROR);
-	    } else {
-	      BEGIN(DISCARD);
-	    }
-	  }
-	}
-	YY_BREAK
-case 89:
-YY_RULE_SETUP
-#line 950 "wcsbth.l"
-{
-	  sscanf(wcsbthtext, "EPOCH%c", &a);
-	
-	  if (a == ' ' || (relax & WCSHDR_EPOCHa)) {
-	    valtype = FLOAT;
-	    vptr = &(wcstem.equinox);
-	    special = wcsbth_epoch;
-	
-	    unput(a);
-	    extkey = "EPOCH";
-	    BEGIN(CCCCCCCa);
-	
-	  } else {
-	    keytype = IMGAUX;
-	    if (relax & WCSHDR_reject) {
-	      errmsg = "EPOCH keyword may not have an alternate version code";
-	      BEGIN(ERROR);
-	    } else {
-	      BEGIN(DISCARD);
-	    }
-	  }
-	}
-	YY_BREAK
-case 90:
-#line 974 "wcsbth.l"
-case 91:
-YY_RULE_SETUP
-#line 974 "wcsbth.l"
-{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.equinox);
-	
-	  if (wcsbthleng == 7) {
-	    extkey = "EQUINOXa";
-	    BEGIN(CCCCCCCa);
-	  } else {
-	    BEGIN(CCCCna);
-	  }
-	}
-	YY_BREAK
-case 92:
-#line 987 "wcsbth.l"
-case 93:
-YY_RULE_SETUP
-#line 987 "wcsbth.l"
-{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.mjdavg);
-	
-	  if (wcsbthleng == 8) {
-	    extkey = "MJD-AVG";
-	    BEGIN(CCCCCCCC);
-	  } else {
-	    BEGIN(CCCCn);
-	  }
-	}
-	YY_BREAK
-case 94:
-#line 1000 "wcsbth.l"
-case 95:
-YY_RULE_SETUP
-#line 1000 "wcsbth.l"
-{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.mjdobs);
-	
-	  if (wcsbthleng == 8) {
-	    extkey = "MJD-OBS";
-	    BEGIN(CCCCCCCC);
-	  } else {
-	    BEGIN(CCCCCn);
-	  }
-	}
-	YY_BREAK
-case 96:
-#line 1013 "wcsbth.l"
-case 97:
-YY_RULE_SETUP
-#line 1013 "wcsbth.l"
-{
-	  valtype = FLOAT;
-	  vptr = wcstem.obsgeo;
-	
-	  if (wcsbthleng == 8) {
-	    extkey = "OBSGEO-X";
-	    BEGIN(CCCCCCCC);
-	  } else {
-	    BEGIN(CCCCCn);
-	  }
-	}
-	YY_BREAK
-case 98:
-#line 1026 "wcsbth.l"
-case 99:
-YY_RULE_SETUP
-#line 1026 "wcsbth.l"
-{
-	  valtype = FLOAT;
-	  vptr = wcstem.obsgeo + 1;
-	
-	  if (wcsbthleng == 8) {
-	    extkey = "OBSGEO-Y";
-	    BEGIN(CCCCCCCC);
-	  } else {
-	    BEGIN(CCCCCn);
-	  }
-	}
-	YY_BREAK
-case 100:
-#line 1039 "wcsbth.l"
-case 101:
-YY_RULE_SETUP
-#line 1039 "wcsbth.l"
-{
-	  valtype = FLOAT;
-	  vptr = wcstem.obsgeo + 2;
-	
-	  if (wcsbthleng == 8) {
-	    extkey = "OBSGEO-Z";
-	    BEGIN(CCCCCCCC);
-	  } else {
-	    BEGIN(CCCCCn);
-	  }
-	}
-	YY_BREAK
-case 102:
-#line 1052 "wcsbth.l"
-case 103:
-YY_RULE_SETUP
-#line 1052 "wcsbth.l"
-{
-	  valtype = STRING;
-	  vptr = wcstem.radesys;
-	
-	  if (wcsbthleng == 7) {
-	    extkey = "RADESYSa";
-	    BEGIN(CCCCCCCa);
-	  } else {
-	    BEGIN(CCCCna);
-	  }
-	}
-	YY_BREAK
-case 104:
-YY_RULE_SETUP
-#line 1064 "wcsbth.l"
-{
-	  if (relax & WCSHDR_RADECSYS) {
-	    valtype = STRING;
-	    vptr = wcstem.radesys;
-	
-	    unput(' ');
-	    extkey = "RADECSYS";
-	    BEGIN(CCCCCCCa);
-	
-	  } else {
-	    keytype = IMGAUX;
-	    if (relax & WCSHDR_reject) {
-	      errmsg = "RADECSYS keyword is non-standard";
-	      BEGIN(ERROR);
-	    } else {
-	      BEGIN(DISCARD);
-	    }
-	  }
-	}
-	YY_BREAK
-case 105:
-#line 1085 "wcsbth.l"
-case 106:
-YY_RULE_SETUP
-#line 1085 "wcsbth.l"
-{
-	  valtype = STRING;
-	  vptr = wcstem.specsys;
-	
-	  if (wcsbthleng == 7) {
-	    extkey = "SPECSYSa";
-	    BEGIN(CCCCCCCa);
-	  } else {
-	    BEGIN(CCCCna);
-	  }
-	}
-	YY_BREAK
-case 107:
-#line 1098 "wcsbth.l"
-case 108:
-YY_RULE_SETUP
-#line 1098 "wcsbth.l"
-{
-	  valtype = STRING;
-	  vptr = wcstem.ssysobs;
-	
-	  if (wcsbthleng == 7) {
-	    extkey = "SSYSOBSa";
-	    BEGIN(CCCCCCCa);
-	  } else {
-	    BEGIN(CCCCna);
-	  }
-	}
-	YY_BREAK
-case 109:
-#line 1111 "wcsbth.l"
-case 110:
-YY_RULE_SETUP
-#line 1111 "wcsbth.l"
-{
-	  valtype = STRING;
-	  vptr = wcstem.ssyssrc;
-	
-	  if (wcsbthleng == 7) {
-	    extkey = "SSYSSRCa";
-	    BEGIN(CCCCCCCa);
-	  } else {
-	    BEGIN(CCCCna);
-	  }
-	}
-	YY_BREAK
-case 111:
-#line 1124 "wcsbth.l"
-case 112:
-YY_RULE_SETUP
-#line 1124 "wcsbth.l"
-{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.velosys);
-	
-	  if (wcsbthleng == 7) {
-	    extkey = "VELOSYSa";
-	    BEGIN(CCCCCCCa);
-	  } else {
-	    BEGIN(CCCCna);
-	  }
-	}
-	YY_BREAK
-case 113:
-#line 1137 "wcsbth.l"
-case 114:
-YY_RULE_SETUP
-#line 1137 "wcsbth.l"
-{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.velangl);
-	
-	  if (wcsbthleng == 7) {
-	    extkey = "VELANGLa";
-	    BEGIN(CCCCCCCa);
-	  } else {
-	    BEGIN(CCCCna);
-	  }
-	}
-	YY_BREAK
-case 115:
-YY_RULE_SETUP
-#line 1149 "wcsbth.l"
-{
-	  sscanf(wcsbthtext, "VELREF%c", &a);
-	
-	  if (a == ' ' || (relax & WCSHDR_VELREFa)) {
-	    valtype = INTEGER;
-	    vptr = &(wcstem.velref);
-	
-	    unput(a);
-	    extkey = "VELREF";
-	    BEGIN(CCCCCCCa);
-	
-	  } else {
-	    keytype = IMGAUX;
-	    if (relax & WCSHDR_reject) {
-	      errmsg = "VELREF keyword may not have an alternate version code";
-	      BEGIN(ERROR);
-	    } else {
-	      BEGIN(DISCARD);
-	    }
-	  }
-	}
-	YY_BREAK
-case 116:
-YY_RULE_SETUP
-#line 1171 "wcsbth.l"
-{
-	  if (relax & WCSHDR_VSOURCE) {
-	    valtype = FLOAT;
-	    vptr = &(wcstem.zsource);
-	    special = wcsbth_vsource;
-	
-	    yyless(7);
-	    extkey = "VSOURCEa";
-	    BEGIN(CCCCCCCa);
-	
-	  } else {
-	    keytype = IMGAUX;
-	    if (relax & WCSHDR_reject) {
-	      errmsg = "VSOURCEa keyword is deprecated";
-	      BEGIN(ERROR);
-	    } else {
-	      BEGIN(DISCARD);
-	    }
-	  }
-	}
-	YY_BREAK
-case 117:
-#line 1193 "wcsbth.l"
-case 118:
-#line 1194 "wcsbth.l"
-case 119:
-YY_RULE_SETUP
-#line 1194 "wcsbth.l"
-{
-	  if (relax & WCSHDR_VSOURCE) {
-	    valtype = FLOAT;
-	    vptr = &(wcstem.zsource);
-	    special = wcsbth_vsource;
-	
-	    yyless(4);
-	    BEGIN(CCCCna);
-	
-	  } else {
-	    keytype = BINTAB;
-	    if (relax & WCSHDR_reject) {
-	      errmsg = "VSOUna keyword is deprecated";
-	      BEGIN(ERROR);
-	    } else {
-	      /* Pretend we don't recognize it. */
-	      BEGIN(DISCARD);
-	    }
-	  }
-	}
-	YY_BREAK
-case 120:
-#line 1216 "wcsbth.l"
-case 121:
-#line 1217 "wcsbth.l"
-case 122:
-YY_RULE_SETUP
-#line 1217 "wcsbth.l"
-{
-	  valtype = STRING;
-	  vptr = wcstem.wcsname;
-	
-	  if (wcsbthleng == 7) {
-	    extkey = "WCSNAMEa";
-	    BEGIN(CCCCCCCa);
-	  } else {
-	    BEGIN(CCCCna);
-	  }
-	}
-	YY_BREAK
-case 123:
-#line 1230 "wcsbth.l"
-case 124:
-YY_RULE_SETUP
-#line 1230 "wcsbth.l"
-{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.zsource);
-	
-	  if (wcsbthleng == 7) {
-	    extkey = "ZSOURCEa";
-	    BEGIN(CCCCCCCa);
-	  } else {
-	    BEGIN(CCCCna);
-	  }
-	}
-	YY_BREAK
-case 125:
-YY_RULE_SETUP
-#line 1242 "wcsbth.l"
-{
-	  yyless(0);
-	  if (wcsbth_nkeyrec) {
-	    wcsbth_nkeyrec = 0;
-	    errmsg = "Keyrecords following the END keyrecord were ignored";
-	    BEGIN(ERROR);
-	  } else {
-	    BEGIN(DISCARD);
-	  }
-	}
-	YY_BREAK
-case 126:
-YY_RULE_SETUP
-#line 1253 "wcsbth.l"
-{
-	  yyless(0);
-	  BEGIN(DISCARD);
-	}
-	YY_BREAK
-case 127:
-#line 1259 "wcsbth.l"
-case 128:
-YY_RULE_SETUP
-#line 1259 "wcsbth.l"
-{
-	  /* Image-header keyword. */
-	  keytype = IMGAXIS;
-	  if (relax & WCSHDR_ALLIMG) {
-	    sscanf(wcsbthtext, "%d%c", &i, &a);
-	    BEGIN(VALUE);
-	
-	  } else if (relax & WCSHDR_reject) {
-	    errmsg = errtxt;
-	    sprintf(errmsg,
-	      "Image-header keyword %s in binary table", extkey);
-	    BEGIN(ERROR);
-	
-	  } else {
-	    /* Pretend we don't recognize it. */
-	    BEGIN(DISCARD);
-	  }
-	}
-	YY_BREAK
-case 129:
-YY_RULE_SETUP
-#line 1278 "wcsbth.l"
-{
-	  /* Invalid axis number in image-header keyword. */
-	  keytype = IMGAXIS;
-	  if (relax & WCSHDR_ALLIMG) {
-	    /* Will also be flagged by <VALUE> as invalid. */
-	    sscanf(wcsbthtext, "%3d", &i);
-	    BEGIN(VALUE);
-	
-	  } else {
-	    /* Pretend we don't recognize it. */
-	    BEGIN(DISCARD);
-	  }
-	}
-	YY_BREAK
-case 130:
-#line 1293 "wcsbth.l"
-case 131:
-#line 1294 "wcsbth.l"
-case 132:
-#line 1295 "wcsbth.l"
-case 133:
-#line 1296 "wcsbth.l"
-case 134:
-#line 1297 "wcsbth.l"
-case 135:
-YY_RULE_SETUP
-#line 1297 "wcsbth.l"
-{
-	  if (vptr) {
-	    WCSBTH_PUTBACK;
-	    BEGIN((YY_START == iCCCCn) ? iCCCna : TCCCna);
-	  } else {
-	    keytype = (YY_START == iCCCCn) ? BIMGARR : PIXLIST;
-	    if (relax & WCSHDR_reject) {
-	      errmsg = errtxt;
-	      sprintf(errmsg, "%s keyword is non-standard", extkey);
-	      BEGIN(ERROR);
-	    } else {
-	      BEGIN(DISCARD);
-	    }
-	  }
-	}
-	YY_BREAK
-case 136:
-#line 1314 "wcsbth.l"
-case 137:
-#line 1315 "wcsbth.l"
-case 138:
-#line 1316 "wcsbth.l"
-case 139:
-YY_RULE_SETUP
-#line 1316 "wcsbth.l"
-{
-	  if (vptr && (relax & WCSHDR_LONGKEY)) {
-	    WCSBTH_PUTBACK;
-	    BEGIN((YY_START == iCCCCn) ? iCCCna : TCCCna);
-	
-	  } else {
-	    keytype = (YY_START == iCCCna) ? BIMGARR : PIXLIST;
-	    if (relax & WCSHDR_reject) {
-	      errmsg = errtxt;
-	      if (!vptr) {
-	        sprintf(errmsg, "%s keyword is non-standard", extkey);
-	      } else {
-	        sprintf(errmsg,
-	          "%s keyword may not have an alternate version code", extkey);
-	      }
-	      BEGIN(ERROR);
-	
-	    } else {
-	      /* Pretend we don't recognize it. */
-	      BEGIN(DISCARD);
-	    }
-	  }
-	}
-	YY_BREAK
-case 140:
-#line 1341 "wcsbth.l"
-case 141:
-YY_RULE_SETUP
-#line 1341 "wcsbth.l"
-{
-	  BEGIN(DISCARD);
-	}
-	YY_BREAK
-case 142:
-#line 1346 "wcsbth.l"
-case 143:
-#line 1347 "wcsbth.l"
-case 144:
-#line 1348 "wcsbth.l"
-case 145:
-#line 1349 "wcsbth.l"
-case 146:
-#line 1350 "wcsbth.l"
-case 147:
-YY_RULE_SETUP
-#line 1350 "wcsbth.l"
-{
-	  sscanf(wcsbthtext, "%d%c", &n, &a);
-	  if (YY_START == TCCCna) i = wcsbth_colax(*wcs, &alts, n, a);
-	  keytype = (YY_START == iCCCna) ? BIMGARR : PIXLIST;
-	  BEGIN(VALUE);
-	}
-	YY_BREAK
-case 148:
-#line 1358 "wcsbth.l"
-case 149:
-YY_RULE_SETUP
-#line 1358 "wcsbth.l"
-{
-	  BEGIN(DISCARD);
-	}
-	YY_BREAK
-case 150:
-#line 1363 "wcsbth.l"
-case 151:
-#line 1364 "wcsbth.l"
-case 152:
-#line 1365 "wcsbth.l"
-case 153:
-YY_RULE_SETUP
-#line 1365 "wcsbth.l"
-{
-	  /* Image-header keyword. */
-	  if (relax & WCSHDR_ALLIMG) {
-	    sscanf(wcsbthtext, "%d_%d%c", &i, &j, &a);
-	    keytype = IMGAXIS;
-	    BEGIN(VALUE);
-	
-	  } else if (relax & WCSHDR_reject) {
-	    errmsg = errtxt;
-	    sprintf(errmsg,
-	      "Image-header keyword %s in binary table", extkey);
-	    BEGIN(ERROR);
-	
-	  } else {
-	    /* Pretend we don't recognize it. */
-	    BEGIN(DISCARD);
-	  }
-	}
-	YY_BREAK
-case 154:
-#line 1385 "wcsbth.l"
-case 155:
-#line 1386 "wcsbth.l"
-case 156:
-#line 1387 "wcsbth.l"
-case 157:
-#line 1388 "wcsbth.l"
-case 158:
-#line 1389 "wcsbth.l"
-case 159:
-YY_RULE_SETUP
-#line 1389 "wcsbth.l"
-{
-	  /* Invalid axis number in image-header keyword. */
-	  if (relax & WCSHDR_ALLIMG) {
-	    /* Will be flagged by <VALUE> as invalid. */
-	    sscanf(wcsbthtext, "%d_%d", &i, &j);
-	    keytype = IMGAXIS;
-	    BEGIN(VALUE);
-	
-	  } else {
-	    /* Pretend we don't recognize it. */
-	    BEGIN(DISCARD);
-	  }
-	}
-	YY_BREAK
-case 160:
-YY_RULE_SETUP
-#line 1403 "wcsbth.l"
-{
-	  /* This covers the defunct forms CD00i00j and PC00i00j. */
-	  if (((relax & WCSHDR_PC00i00j) && (altlin == 1)) ||
-	      ((relax & WCSHDR_CD00i00j) && (altlin == 2))) {
-	    sscanf(wcsbthtext, "%3d%3d", &i, &j);
-	    a = ' ';
-	    keytype = IMGAXIS;
-	    BEGIN(VALUE);
-	
-	  } else if (relax & WCSHDR_reject) {
-	    errmsg = errtxt;
-	    sprintf(errmsg, "Defunct form of %si_ja keyword",
-	                     (altlin==1) ? "PC" : "CD");
-	    BEGIN(ERROR);
-	
-	  } else {
-	    /* Pretend we don't recognize it. */
-	    BEGIN(DISCARD);
-	  }
-	}
-	YY_BREAK
-case 161:
-YY_RULE_SETUP
-#line 1424 "wcsbth.l"
-{
-	  BEGIN(DISCARD);
-	}
-	YY_BREAK
-case 162:
-#line 1429 "wcsbth.l"
-case 163:
-#line 1430 "wcsbth.l"
-case 164:
-YY_RULE_SETUP
-#line 1430 "wcsbth.l"
-{
-	  sscanf(wcsbthtext, "%d%c", &n, &a);
-	  keytype = BIMGARR;
-	  BEGIN(VALUE);
-	}
-	YY_BREAK
-case 165:
-#line 1437 "wcsbth.l"
-case 166:
-#line 1438 "wcsbth.l"
-case 167:
-#line 1439 "wcsbth.l"
-case 168:
-#line 1440 "wcsbth.l"
-case 169:
-#line 1441 "wcsbth.l"
-case 170:
-YY_RULE_SETUP
-#line 1441 "wcsbth.l"
-{
-	  if (relax & WCSHDR_LONGKEY) {
-	    WCSBTH_PUTBACK;
-	    BEGIN(TCn_ka);
-	
-	  } else if (relax & WCSHDR_reject) {
-	    errmsg = errtxt;
-	    sprintf(errmsg, "%s keyword is non-standard", extkey);
-	    BEGIN(ERROR);
-	
-	  } else {
-	    /* Pretend we don't recognize it. */
-	    BEGIN(DISCARD);
-	  }
-	}
-	YY_BREAK
-case 171:
-YY_RULE_SETUP
-#line 1457 "wcsbth.l"
-{
-	  BEGIN(DISCARD);
-	}
-	YY_BREAK
-case 172:
-#line 1462 "wcsbth.l"
-case 173:
-#line 1463 "wcsbth.l"
-case 174:
-#line 1464 "wcsbth.l"
-case 175:
-#line 1465 "wcsbth.l"
-case 176:
-#line 1466 "wcsbth.l"
-case 177:
-YY_RULE_SETUP
-#line 1466 "wcsbth.l"
-{
-	  sscanf(wcsbthtext, "%d_%d%c", &n, &k, &a);
-	  i = wcsbth_colax(*wcs, &alts, n, a);
-	  j = wcsbth_colax(*wcs, &alts, k, a);
-	  keytype = PIXLIST;
-	  BEGIN(VALUE);
-	}
-	YY_BREAK
-case 178:
-#line 1475 "wcsbth.l"
-case 179:
-#line 1476 "wcsbth.l"
-case 180:
-#line 1477 "wcsbth.l"
-case 181:
-YY_RULE_SETUP
-#line 1477 "wcsbth.l"
-{
-	  sscanf(wcsbthtext, "%d_%d", &n, &k);
-	  a = ' ';
-	  i = wcsbth_colax(*wcs, &alts, n, a);
-	  j = wcsbth_colax(*wcs, &alts, k, a);
-	  keytype = PIXLIST;
-	  BEGIN(VALUE);
-	}
-	YY_BREAK
-case 182:
-YY_RULE_SETUP
-#line 1486 "wcsbth.l"
-{
-	  BEGIN(DISCARD);
-	}
-	YY_BREAK
-case 183:
-#line 1491 "wcsbth.l"
-case 184:
-YY_RULE_SETUP
-#line 1491 "wcsbth.l"
-{
-	  yyless(0);
-	  BEGIN(CCCCCia);
-	}
-	YY_BREAK
-case 185:
-#line 1497 "wcsbth.l"
-case 186:
-YY_RULE_SETUP
-#line 1497 "wcsbth.l"
-{
-	  if (relax & WCSHDR_CROTAia) {
-	    yyless(0);
-	    BEGIN(CCCCCia);
-	
-	  } else if (relax & WCSHDR_reject) {
-	    errmsg = "CROTAn keyword may not have an alternate version code";
-	    BEGIN(ERROR);
-	
-	  } else {
-	    /* Pretend we don't recognize it. */
-	    BEGIN(DISCARD);
-	  }
-	}
-	YY_BREAK
-case 187:
-YY_RULE_SETUP
-#line 1512 "wcsbth.l"
-{
-	  BEGIN(DISCARD);
-	}
-	YY_BREAK
-case 188:
-#line 1517 "wcsbth.l"
-case 189:
-#line 1518 "wcsbth.l"
-case 190:
-#line 1519 "wcsbth.l"
-case 191:
-#line 1520 "wcsbth.l"
-case 192:
-#line 1521 "wcsbth.l"
-case 193:
-YY_RULE_SETUP
-#line 1521 "wcsbth.l"
-{
-	  WCSBTH_PUTBACK;
-	  BEGIN((YY_START == iCROTn) ? iCCCna : TCCCna);
-	}
-	YY_BREAK
-case 194:
-#line 1527 "wcsbth.l"
-case 195:
-#line 1528 "wcsbth.l"
-case 196:
-#line 1529 "wcsbth.l"
-case 197:
-YY_RULE_SETUP
-#line 1529 "wcsbth.l"
-{
-	  if (relax & WCSHDR_CROTAia) {
-	    WCSBTH_PUTBACK;
-	    BEGIN((YY_START == iCROTn) ? iCCCna : TCCCna);
-	
-	  } else if (relax & WCSHDR_reject) {
-	    errmsg = errtxt;
-	    sprintf(errmsg,
-	      "%s keyword may not have an alternate version code", extkey);
-	    BEGIN(ERROR);
-	
-	  } else {
-	    /* Pretend we don't recognize it. */
-	    BEGIN(DISCARD);
-	  }
-	}
-	YY_BREAK
-case 198:
-#line 1547 "wcsbth.l"
-case 199:
-YY_RULE_SETUP
-#line 1547 "wcsbth.l"
-{
-	  BEGIN(DISCARD);
-	}
-	YY_BREAK
-case 200:
-#line 1552 "wcsbth.l"
-case 201:
-YY_RULE_SETUP
-#line 1552 "wcsbth.l"
-{
-	  /* Image-header keyword. */
-	  if (relax & (WCSHDR_AUXIMG | WCSHDR_ALLIMG)) {
-	    if (YY_START == CCCCCCCa) {
-	      sscanf(wcsbthtext, "%c", &a);
-	    } else {
-	      a = 0;
-	      unput(wcsbthtext[0]);
-	    }
-	    keytype = IMGAUX;
-	    BEGIN(VALUE);
-	
-	  } else if (relax & WCSHDR_reject) {
-	    errmsg = errtxt;
-	    sprintf(errmsg,
-	      "Image-header keyword %s in binary table", extkey);
-	    BEGIN(ERROR);
-	
-	  } else {
-	    /* Pretend we don't recognize it. */
-	    BEGIN(DISCARD);
-	  }
-	}
-	YY_BREAK
-case 202:
-YY_RULE_SETUP
-#line 1576 "wcsbth.l"
-{
-	  BEGIN(DISCARD);
-	}
-	YY_BREAK
-case 203:
-#line 1581 "wcsbth.l"
-case 204:
-#line 1582 "wcsbth.l"
-case 205:
-#line 1583 "wcsbth.l"
-case 206:
-#line 1584 "wcsbth.l"
-case 207:
-YY_RULE_SETUP
-#line 1584 "wcsbth.l"
-{
-	  sscanf(wcsbthtext, "%d%c", &n, &a);
-	  keytype = BINTAB;
-	  BEGIN(VALUE);
-	}
-	YY_BREAK
-case 208:
-YY_RULE_SETUP
-#line 1590 "wcsbth.l"
-{
-	  sscanf(wcsbthtext, "%d", &n);
-	  a = ' ';
-	  keytype = BINTAB;
-	  BEGIN(VALUE);
-	}
-	YY_BREAK
-case 209:
-#line 1598 "wcsbth.l"
-case 210:
-YY_RULE_SETUP
-#line 1598 "wcsbth.l"
-{
-	  BEGIN(DISCARD);
-	}
-	YY_BREAK
-case 211:
-#line 1603 "wcsbth.l"
-case 212:
-#line 1604 "wcsbth.l"
-case 213:
-#line 1605 "wcsbth.l"
-case 214:
-#line 1606 "wcsbth.l"
-case 215:
-#line 1607 "wcsbth.l"
-case 216:
-#line 1608 "wcsbth.l"
-case 217:
-YY_RULE_SETUP
-#line 1608 "wcsbth.l"
-{
-	  sscanf(wcsbthtext, "%d", &n);
-	  a = 0;
-	  keytype = BINTAB;
-	  BEGIN(VALUE);
-	}
-	YY_BREAK
-case 218:
-#line 1616 "wcsbth.l"
-case 219:
-YY_RULE_SETUP
-#line 1616 "wcsbth.l"
-{
-	  BEGIN(DISCARD);
-	}
-	YY_BREAK
-case 220:
-#line 1621 "wcsbth.l"
-case 221:
-#line 1622 "wcsbth.l"
-case 222:
-#line 1623 "wcsbth.l"
-case 223:
-YY_RULE_SETUP
-#line 1623 "wcsbth.l"
-{
-	  /* Image-header keyword. */
-	  if (relax & WCSHDR_ALLIMG) {
-	    sscanf(wcsbthtext, "%d_%d%c", &i, &m, &a);
-	    keytype = IMGAXIS;
-	    BEGIN(VALUE);
-	
-	  } else if (relax & WCSHDR_reject) {
-	    errmsg = errtxt;
-	    sprintf(errmsg,
-	      "Image-header keyword %s in binary table", extkey);
-	    BEGIN(ERROR);
-	
-	  } else {
-	    /* Pretend we don't recognize it. */
-	    BEGIN(DISCARD);
-	  }
-	}
-	YY_BREAK
-case 224:
-#line 1643 "wcsbth.l"
-case 225:
-#line 1644 "wcsbth.l"
-case 226:
-#line 1645 "wcsbth.l"
-case 227:
-#line 1646 "wcsbth.l"
-case 228:
-#line 1647 "wcsbth.l"
-case 229:
-YY_RULE_SETUP
-#line 1647 "wcsbth.l"
-{
-	  /* Invalid parameter in image-header keyword. */
-	  if (relax & WCSHDR_ALLIMG) {
-	    /* Will be flagged by <VALUE> as invalid. */
-	    sscanf(wcsbthtext, "%d_%d", &i, &m);
-	    keytype = IMGAXIS;
-	    BEGIN(VALUE);
-	
-	  } else {
-	    /* Pretend we don't recognize it. */
-	    BEGIN(DISCARD);
-	  }
-	}
-	YY_BREAK
-case 230:
-YY_RULE_SETUP
-#line 1661 "wcsbth.l"
-{
-	  BEGIN(DISCARD);
-	}
-	YY_BREAK
-case 231:
-#line 1666 "wcsbth.l"
-case 232:
-#line 1667 "wcsbth.l"
-case 233:
-#line 1668 "wcsbth.l"
-case 234:
-#line 1669 "wcsbth.l"
-case 235:
-#line 1670 "wcsbth.l"
-case 236:
-#line 1671 "wcsbth.l"
-case 237:
-#line 1672 "wcsbth.l"
-case 238:
-#line 1673 "wcsbth.l"
-case 239:
-#line 1674 "wcsbth.l"
-case 240:
-#line 1675 "wcsbth.l"
-case 241:
-#line 1676 "wcsbth.l"
-case 242:
-YY_RULE_SETUP
-#line 1676 "wcsbth.l"
-{
-	  if (relax & WCSHDR_LONGKEY) {
-	    WCSBTH_PUTBACK;
-	    BEGIN((YY_START == iCCn_ma) ? iCn_ma : TCn_ma);
-	
-	  } else if (relax & WCSHDR_reject) {
-	    errmsg = errtxt;
-	    sprintf(errmsg, "%s keyword is non-standard", extkey);
-	    BEGIN(ERROR);
-	
-	  } else {
-	    /* Pretend we don't recognize it. */
-	    BEGIN(DISCARD);
-	  }
-	}
-	YY_BREAK
-case 243:
-#line 1693 "wcsbth.l"
-case 244:
-YY_RULE_SETUP
-#line 1693 "wcsbth.l"
-{
-	  BEGIN(DISCARD);
-	}
-	YY_BREAK
-case 245:
-#line 1698 "wcsbth.l"
-case 246:
-#line 1699 "wcsbth.l"
-case 247:
-#line 1700 "wcsbth.l"
-case 248:
-#line 1701 "wcsbth.l"
-case 249:
-#line 1702 "wcsbth.l"
-case 250:
-#line 1703 "wcsbth.l"
-case 251:
-#line 1704 "wcsbth.l"
-case 252:
-#line 1705 "wcsbth.l"
-case 253:
-#line 1706 "wcsbth.l"
-case 254:
-#line 1707 "wcsbth.l"
-case 255:
-#line 1708 "wcsbth.l"
-case 256:
-YY_RULE_SETUP
-#line 1708 "wcsbth.l"
-{
-	  sscanf(wcsbthtext, "%d_%d%c", &n, &m, &a);
-	  if (YY_START == TCn_ma) i = wcsbth_colax(*wcs, &alts, n, a);
-	  keytype = (YY_START == iCn_ma) ? BIMGARR : PIXLIST;
-	  BEGIN(VALUE);
-	}
-	YY_BREAK
-case 257:
-#line 1716 "wcsbth.l"
-case 258:
-#line 1717 "wcsbth.l"
-case 259:
-#line 1718 "wcsbth.l"
-case 260:
-#line 1719 "wcsbth.l"
-case 261:
-#line 1720 "wcsbth.l"
-case 262:
-#line 1721 "wcsbth.l"
-case 263:
-#line 1722 "wcsbth.l"
-case 264:
-YY_RULE_SETUP
-#line 1722 "wcsbth.l"
-{
-	  /* Invalid combinations will be flagged by <VALUE>. */
-	  sscanf(wcsbthtext, "%d_%d", &n, &m);
-	  a = ' ';
-	  if (YY_START == TCn_ma) i = wcsbth_colax(*wcs, &alts, n, a);
-	  keytype = (YY_START == iCn_ma) ? BIMGARR : PIXLIST;
-	  BEGIN(VALUE);
-	}
-	YY_BREAK
-case 265:
-#line 1732 "wcsbth.l"
-case 266:
-YY_RULE_SETUP
-#line 1732 "wcsbth.l"
-{
-	  BEGIN(DISCARD);
-	}
-	YY_BREAK
-case 267:
-YY_RULE_SETUP
-#line 1736 "wcsbth.l"
-{
-	  if (relax & WCSHDR_PROJPn) {
-	    sscanf(wcsbthtext, "%d", &m);
-	    i = 0;
-	    a = ' ';
-	    keytype = IMGAXIS;
-	    BEGIN(VALUE);
-	
-	  } else if (relax & WCSHDR_reject) {
-	    errmsg = "PROJPn keyword is defunct";
-	    BEGIN(ERROR);
-	
-	  } else {
-	    /* Pretend we don't recognize it. */
-	    BEGIN(DISCARD);
-	  }
-	}
-	YY_BREAK
-case 268:
-YY_RULE_SETUP
-#line 1754 "wcsbth.l"
-{
-	  BEGIN(DISCARD);
-	}
-	YY_BREAK
-case 269:
-YY_RULE_SETUP
-#line 1758 "wcsbth.l"
-{
-	  /* Do checks on i, j, m, n, k. */
-	  if (!(keytype & keysel)) {
-	    /* Selection by keyword type. */
-	    BEGIN(DISCARD);
-	
-	  } else if (exclude[n] || exclude[k]) {
-	    /* One or other column is not selected. */
-	    if (k && (exclude[n] != exclude[k])) {
-	      /* For keywords such as TCn_ka, both columns must be excluded.
-	         User error, so return immediately. */
-	      wcsbthlex_destroy();
-	      return 3;
-	
-	    } else {
-	      BEGIN(DISCARD);
-	    }
-	
-	  } else if (i > 99 || j > 99 || m > 99 || n > 999 || k > 999) {
-	    if (relax & WCSHDR_reject) {
-	      errmsg = errtxt;
-	      if (i > 99 || j > 99) {
-	        sprintf(errmsg, "Axis number exceeds 99");
-	      } else if (m > 99) {
-	        sprintf(errmsg, "Parameter number exceeds 99");
-	      } else if (n > 999 || k > 999) {
-	        sprintf(errmsg, "Column number exceeds 999");
-	      }
-	      BEGIN(ERROR);
-	
-	    } else {
-	      /* Pretend we don't recognize it. */
-	      BEGIN(DISCARD);
-	    }
-	
-	  } else if (ipass == 2 && npass == 3 && (keytype & BINTAB)) {
-	    /* Skip keyvalues that won't be inherited. */
-	    BEGIN(FLUSH);
-	
-	  } else if (ipass == 3 && (keytype & IMGHEAD)) {
-	    /* IMGHEAD keytypes are always dealt with on the second pass. */
-	    BEGIN(FLUSH);
-	
-	  } else if (vptr) {
-	    alts.icol = 0;
-	    alts.ialt = 0;
-	    voff = (char *)vptr - (char *)(&wcstem);
-	
-	    if (valtype == INTEGER) {
-	      BEGIN(INTEGER_VAL);
-	    } else if (valtype == FLOAT) {
-	      BEGIN(FLOAT_VAL);
-	    } else if (valtype == STRING) {
-	      BEGIN(STRING_VAL);
-	    } else {
-	      errmsg = errtxt;
-	      sprintf(errmsg, "Internal parser ERROR, bad data type: %d",
-	        valtype);
-	      BEGIN(ERROR);
-	    }
-	
-	  } else {
-	    errmsg = "Internal parser ERROR, null pointer";
-	    BEGIN(ERROR);
-	  }
-	}
-	YY_BREAK
-case 270:
-YY_RULE_SETUP
-#line 1825 "wcsbth.l"
-{
-	  errmsg = "Invalid KEYWORD = VALUE syntax";
-	  BEGIN(ERROR);
-	}
-	YY_BREAK
-case 271:
-YY_RULE_SETUP
-#line 1830 "wcsbth.l"
-{
-	  if (ipass == 1) {
-	    /* Do first-pass bookkeeping. */
-	    wcsbth_pass1(keytype, i, j, n, k, a, ptype, &alts);
-	    BEGIN(FLUSH);
-	
-	  } else {
-	    /* Update each coordinate representation. */
-	    while ((wcsp = wcsbth_idx(*wcs, &alts, keytype, n, a))) {
-	      wptr = (void *)((char *)wcsp + voff);
-	
-	      /* Read the keyvalue. */
-	      if (special) {
-	        special(wptr);
-	      } else {
-	        sscanf(wcsbthtext, "%d", (int *)wptr);
-	      }
-	    }
-	
-	    BEGIN(COMMENT);
-	  }
-	}
-	YY_BREAK
-case 272:
-YY_RULE_SETUP
-#line 1853 "wcsbth.l"
-{
-	  errmsg = "An integer value was expected";
-	  BEGIN(ERROR);
-	}
-	YY_BREAK
-case 273:
-YY_RULE_SETUP
-#line 1858 "wcsbth.l"
-{
-	  if (ipass == 1) {
-	    /* Do first-pass bookkeeping. */
-	    wcsbth_pass1(keytype, i, j, n, k, a, ptype, &alts);
-	    BEGIN(FLUSH);
-	
-	  } else {
-	    /* Update each coordinate representation. */
-	    while ((wcsp = wcsbth_idx(*wcs, &alts, keytype, n, a))) {
-	      wptr = (void *)((char *)wcsp + voff);
-	
-	      /* Apply keyword parameterization. */
-	      if (ptype == 'v') {
-	        ipx = wcsp->npv++;
-	        wcsp->pv[ipx].i = i;
-	        wcsp->pv[ipx].m = m;
-	        wptr = &(wcsp->pv[ipx].value);
-	
-	      } else if (j) {
-	        /* Is the de-reference necessary? */
-	        wptr = *((double **)wptr) + (i - 1)*(wcsp->naxis) + (j - 1);
-	
-	      } else if (i) {
-	        wptr = *((double **)wptr) + (i - 1);
-	      }
-	
-	      /* Read the keyvalue. */
-	      if (special) {
-	        special(wptr);
-	      } else {
-	        sscanf(wcsbthtext, "%lf", (double *)wptr);
-	      }
-	
-	      /* Flag the presence of PC, or CD and/or CROTA. */
-	      if (altlin) {
-	        wcsp->altlin |= altlin;
-	        altlin = 0;
-	      }
-	    }
-	
-	    BEGIN(COMMENT);
-	  }
-	}
-	YY_BREAK
-case 274:
-YY_RULE_SETUP
-#line 1902 "wcsbth.l"
-{
-	  errmsg = "A floating-point value was expected";
-	  BEGIN(ERROR);
-	}
-	YY_BREAK
-case 275:
-/* rule 275 can match eol */
-YY_RULE_SETUP
-#line 1907 "wcsbth.l"
-{
-	  if (ipass == 1) {
-	    /* Do first-pass bookkeeping. */
-	    wcsbth_pass1(keytype, i, j, n, k, a, ptype, &alts);
-	    BEGIN(FLUSH);
-	
-	  } else {
-	    /* Update each coordinate representation. */
-	    while ((wcsp = wcsbth_idx(*wcs, &alts, keytype, n, a))) {
-	      wptr = (void *)((char *)wcsp + voff);
-	
-	      /* Apply keyword parameterization. */
-	      if (ptype == 's') {
-	        ipx = wcsp->nps++;
-	        wcsp->ps[ipx].i = i;
-	        wcsp->ps[ipx].m = m;
-	        wptr = wcsp->ps[ipx].value;
-	
-	      } else if (j) {
-	        wptr = *((char (**)[72])wptr) +
-	                (i - 1)*(wcsp->naxis) + (j - 1);
-	
-	      } else if (i) {
-	        wptr = *((char (**)[72])wptr) + (i - 1);
-	      }
-	
-	      /* Read the keyvalue. */
-	      cptr = (char *)wptr;
-	      strcpy(cptr, wcsbthtext+1);
-	
-	      /* Squeeze out repeated quotes. */
-	      ix = 0;
-	      for (jx = 0; jx < 72; jx++) {
-	        if (ix < jx) {
-	          cptr[ix] = cptr[jx];
-	        }
-	
-	        if (cptr[jx] == '\0') {
-	          if (ix) cptr[ix-1] = '\0';
-	          break;
-	        } else if (cptr[jx] == '\'' && cptr[jx+1] == '\'') {
-	          jx++;
-	        }
-	
-	        ix++;
-	      }
-	    }
-	
-	    BEGIN(COMMENT);
-	  }
-	}
-	YY_BREAK
-case 276:
-YY_RULE_SETUP
-#line 1959 "wcsbth.l"
-{
-	  errmsg = "A string value was expected";
-	  BEGIN(ERROR);
-	}
-	YY_BREAK
-case 277:
-#line 1965 "wcsbth.l"
-case 278:
-YY_RULE_SETUP
-#line 1965 "wcsbth.l"
-{
-	  BEGIN(FLUSH);
-	}
-	YY_BREAK
-case 279:
-YY_RULE_SETUP
-#line 1969 "wcsbth.l"
-{
-	  errmsg = "Malformed keycomment";
-	  BEGIN(ERROR);
-	}
-	YY_BREAK
-case 280:
-YY_RULE_SETUP
-#line 1974 "wcsbth.l"
-{
-	  if (ipass == npass) {
-	    if (ctrl < 0) {
-	      /* Preserve discards. */
-	      if (hptr < wcsbth_hdr-80) {
-	        strncpy(hptr, wcsbth_hdr-80, 80);
-	      }
-	      hptr += 80;
-	
-	    } else if (ctrl > 2) {
-	      fprintf(stderr, "%.80s\n  Discarded.\n", wcsbth_hdr-80);
-	    }
-	  }
-	
-	  BEGIN(FLUSH);
-	}
-	YY_BREAK
-case 281:
-YY_RULE_SETUP
-#line 1991 "wcsbth.l"
-{
-	  (*nreject)++;
-	  if (ipass == npass) {
-	    if (ctrl == -1) {
-	      if (hptr < wcsbth_hdr-80) {
-	        /* Preserve rejects. */
-	        strncpy(hptr, wcsbth_hdr-80, 80);
-	      }
-	      hptr += 80;
-	    }
-	
-	    if (abs(ctrl) > 1) {
-	      fprintf(stderr, "%.80s\n%4d: %s.\n", wcsbth_hdr-80, *nreject,
-	        errmsg);
-	    }
-	  }
-	
-	  BEGIN(FLUSH);
-	}
-	YY_BREAK
-case 282:
-/* rule 282 can match eol */
-YY_RULE_SETUP
-#line 2011 "wcsbth.l"
-{
-	  /* Throw away the rest of the line and reset for the next one. */
-	  i = j = 0;
-	  n = k = 0;
-	  m = 0;
-	  a = ' ';
-	
-	  keytype =  0;
-	  valtype = -1;
-	  vptr    = 0x0;
-	
-	  altlin = 0;
-	  ptype  = ' ';
-	  special = 0x0;
-	  BEGIN(INITIAL);
-	}
-	YY_BREAK
-case YY_STATE_EOF(INITIAL):
-case YY_STATE_EOF(CCCCCia):
-case YY_STATE_EOF(iCCCna):
-case YY_STATE_EOF(iCCCCn):
-case YY_STATE_EOF(TCCCna):
-case YY_STATE_EOF(TCCCCn):
-case YY_STATE_EOF(CCi_ja):
-case YY_STATE_EOF(ijCCna):
-case YY_STATE_EOF(TCn_ka):
-case YY_STATE_EOF(TCCn_ka):
-case YY_STATE_EOF(CROTAi):
-case YY_STATE_EOF(iCROTn):
-case YY_STATE_EOF(TCROTn):
-case YY_STATE_EOF(CCi_ma):
-case YY_STATE_EOF(iCn_ma):
-case YY_STATE_EOF(iCCn_ma):
-case YY_STATE_EOF(TCn_ma):
-case YY_STATE_EOF(TCCn_ma):
-case YY_STATE_EOF(PROJPm):
-case YY_STATE_EOF(CCCCCCCC):
-case YY_STATE_EOF(CCCCCCCa):
-case YY_STATE_EOF(CCCCna):
-case YY_STATE_EOF(CCCCCna):
-case YY_STATE_EOF(CCCCn):
-case YY_STATE_EOF(CCCCCn):
-case YY_STATE_EOF(VALUE):
-case YY_STATE_EOF(INTEGER_VAL):
-case YY_STATE_EOF(FLOAT_VAL):
-case YY_STATE_EOF(STRING_VAL):
-case YY_STATE_EOF(COMMENT):
-case YY_STATE_EOF(DISCARD):
-case YY_STATE_EOF(ERROR):
-case YY_STATE_EOF(FLUSH):
-#line 2028 "wcsbth.l"
-{
-	  /* End-of-input. */
-	  if (ipass == 1) {
-	    if ((status = wcsbth_init1(&alts, nwcs, wcs)) || *nwcs == 0) {
-	      wcsbthlex_destroy();
-	      return status;
-	    }
-
-	    if (alts.imgherit) npass = 3;
-	
-	    if (abs(ctrl) > 2) {
-	      if (*nwcs == 1) {
-	        fprintf(stderr, "Found one coordinate representation.\n");
-	      } else {
-	        fprintf(stderr, "Found %d coordinate representations.\n",
-	          *nwcs);
-	      }
-	    }
-	  }
-	
-	  if (ipass++ < npass) {
-	    wcsbth_hdr = header;
-	    wcsbth_nkeyrec = nkeyrec;
-	    *nreject = 0;
-	
-	    i = j = 0;
-	    k = n = 0;
-	    m = 0;
-	    a = ' ';
-	
-	    keytype =  0;
-	    valtype = -1;
-	    vptr    = 0x0;
-	
-	    altlin = 0;
-	    ptype  = ' ';
-	    special = 0x0;
-	
-	    wcsbthrestart(wcsbthin);
-	
-	  } else {
-	    wcsbthlex_destroy();
-	
-	    if (ctrl < 0) {
-	      *hptr = '\0';
-	    } else if (ctrl == 1) {
-	      fprintf(stderr, "%d WCS keyrecords were rejected.\n", *nreject);
-	    }
-	
-	    return wcsbth_final(&alts, nwcs, wcs);
-	  }
-	}
-	YY_BREAK
-case 283:
-YY_RULE_SETUP
-#line 2081 "wcsbth.l"
-ECHO;
-	YY_BREAK
-#line 19589 "wcsbth.c"
-
-	case YY_END_OF_BUFFER:
-		{
-		/* Amount of text matched not including the EOB char. */
-		int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;
-
-		/* Undo the effects of YY_DO_BEFORE_ACTION. */
-		*yy_cp = (yy_hold_char);
-		YY_RESTORE_YY_MORE_OFFSET
-
-		if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
-			{
-			/* We're scanning a new file or input source.  It's
-			 * possible that this happened because the user
-			 * just pointed wcsbthin at a new source and called
-			 * wcsbthlex().  If so, then we have to assure
-			 * consistency between YY_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.
-			 */
-			(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
-			YY_CURRENT_BUFFER_LVALUE->yy_input_file = wcsbthin;
-			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
-			}
-
-		/* Note that here we test for yy_c_buf_p "<=" to the position
-		 * of the first EOB in the buffer, since yy_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 ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
-			{ /* This was really a NUL. */
-			yy_state_type yy_next_state;
-
-			(yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;
-
-			yy_current_state = yy_get_previous_state(  );
-
-			/* Okay, we're now positioned to make the NUL
-			 * transition.  We couldn't have
-			 * yy_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).
-			 */
-
-			yy_next_state = yy_try_NUL_trans( yy_current_state );
-
-			yy_bp = (yytext_ptr) + YY_MORE_ADJ;
-
-			if ( yy_next_state )
-				{
-				/* Consume the NUL. */
-				yy_cp = ++(yy_c_buf_p);
-				yy_current_state = yy_next_state;
-				goto yy_match;
-				}
-
-			else
-				{
-				yy_cp = (yy_c_buf_p);
-				goto yy_find_action;
-				}
-			}
-
-		else switch ( yy_get_next_buffer(  ) )
-			{
-			case EOB_ACT_END_OF_FILE:
-				{
-				(yy_did_buffer_switch_on_eof) = 0;
-
-				if ( wcsbthwrap( ) )
-					{
-					/* Note: because we've taken care in
-					 * yy_get_next_buffer() to have set up
-					 * wcsbthtext, we can now set up
-					 * yy_c_buf_p so that if some total
-					 * hoser (like flex itself) wants to
-					 * call the scanner after we return the
-					 * YY_NULL, it'll still work - another
-					 * YY_NULL will get returned.
-					 */
-					(yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;
-
-					yy_act = YY_STATE_EOF(YY_START);
-					goto do_action;
-					}
-
-				else
-					{
-					if ( ! (yy_did_buffer_switch_on_eof) )
-						YY_NEW_FILE;
-					}
-				break;
-				}
-
-			case EOB_ACT_CONTINUE_SCAN:
-				(yy_c_buf_p) =
-					(yytext_ptr) + yy_amount_of_matched_text;
-
-				yy_current_state = yy_get_previous_state(  );
-
-				yy_cp = (yy_c_buf_p);
-				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
-				goto yy_match;
-
-			case EOB_ACT_LAST_MATCH:
-				(yy_c_buf_p) =
-				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];
-
-				yy_current_state = yy_get_previous_state(  );
-
-				yy_cp = (yy_c_buf_p);
-				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
-				goto yy_find_action;
-			}
-		break;
-		}
-
-	default:
-		YY_FATAL_ERROR(
-			"fatal flex scanner internal error--no action found" );
-	} /* end of action switch */
-		} /* end of scanning one token */
-} /* end of wcsbthlex */
-
-/* yy_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 yy_get_next_buffer (void)
-{
-    	register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
-	register char *source = (yytext_ptr);
-	register int number_to_move, i;
-	int ret_val;
-
-	if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
-		YY_FATAL_ERROR(
-		"fatal flex scanner internal error--end of buffer missed" );
-
-	if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
-		{ /* Don't try to fill the buffer, so this is an EOF. */
-		if ( (yy_c_buf_p) - (yytext_ptr) - YY_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) ((yy_c_buf_p) - (yytext_ptr)) - 1;
-
-	for ( i = 0; i < number_to_move; ++i )
-		*(dest++) = *(source++);
-
-	if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
-		/* don't do the read, it's not guaranteed to return an EOF,
-		 * just force an EOF
-		 */
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
-
-	else
-		{
-			int num_to_read =
-			YY_CURRENT_BUFFER_LVALUE->yy_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 */
-			YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
-
-			int yy_c_buf_p_offset =
-				(int) ((yy_c_buf_p) - b->yy_ch_buf);
-
-			if ( b->yy_is_our_buffer )
-				{
-				int new_size = b->yy_buf_size * 2;
-
-				if ( new_size <= 0 )
-					b->yy_buf_size += b->yy_buf_size / 8;
-				else
-					b->yy_buf_size *= 2;
-
-				b->yy_ch_buf = (char *)
-					/* Include room in for 2 EOB chars. */
-					wcsbthrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2  );
-				}
-			else
-				/* Can't grow it, we don't own it. */
-				b->yy_ch_buf = 0;
-
-			if ( ! b->yy_ch_buf )
-				YY_FATAL_ERROR(
-				"fatal error - scanner input buffer overflow" );
-
-			(yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset];
-
-			num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
-						number_to_move - 1;
-
-			}
-
-		if ( num_to_read > YY_READ_BUF_SIZE )
-			num_to_read = YY_READ_BUF_SIZE;
-
-		/* Read in more data. */
-		YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
-			(yy_n_chars), (size_t) num_to_read );
-
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
-		}
-
-	if ( (yy_n_chars) == 0 )
-		{
-		if ( number_to_move == YY_MORE_ADJ )
-			{
-			ret_val = EOB_ACT_END_OF_FILE;
-			wcsbthrestart(wcsbthin  );
-			}
-
-		else
-			{
-			ret_val = EOB_ACT_LAST_MATCH;
-			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
-				YY_BUFFER_EOF_PENDING;
-			}
-		}
-
-	else
-		ret_val = EOB_ACT_CONTINUE_SCAN;
-
-	if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
-		/* Extend the array by 50%, plus the number we really need. */
-		yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1);
-		YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) wcsbthrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size  );
-		if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
-			YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
-	}
-
-	(yy_n_chars) += number_to_move;
-	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
-	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
-
-	(yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
-
-	return ret_val;
-}
-
-/* yy_get_previous_state - get the state just before the EOB char was reached */
-
-    static yy_state_type yy_get_previous_state (void)
-{
-	register yy_state_type yy_current_state;
-	register char *yy_cp;
-    
-	yy_current_state = (yy_start);
-	yy_current_state += YY_AT_BOL();
-
-	for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
-		{
-		if ( *yy_cp )
-			{
-			yy_current_state = yy_nxt[yy_current_state][YY_SC_TO_UI(*yy_cp)];
-			}
-		else
-			yy_current_state = yy_NUL_trans[yy_current_state];
-		if ( yy_accept[yy_current_state] )
-			{
-			(yy_last_accepting_state) = yy_current_state;
-			(yy_last_accepting_cpos) = yy_cp;
-			}
-		}
-
-	return yy_current_state;
-}
-
-/* yy_try_NUL_trans - try to make a transition on the NUL character
- *
- * synopsis
- *	next_state = yy_try_NUL_trans( current_state );
- */
-    static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state )
-{
-	register int yy_is_jam;
-    	register char *yy_cp = (yy_c_buf_p);
-
-	yy_current_state = yy_NUL_trans[yy_current_state];
-	yy_is_jam = (yy_current_state == 0);
-
-	if ( ! yy_is_jam )
-		{
-		if ( yy_accept[yy_current_state] )
-			{
-			(yy_last_accepting_state) = yy_current_state;
-			(yy_last_accepting_cpos) = yy_cp;
-			}
-		}
-
-	return yy_is_jam ? 0 : yy_current_state;
-}
-
-    static void yyunput (int c, register char * yy_bp )
-{
-	register char *yy_cp;
-    
-    yy_cp = (yy_c_buf_p);
-
-	/* undo effects of setting up wcsbthtext */
-	*yy_cp = (yy_hold_char);
-
-	if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
-		{ /* need to shift things up to make room */
-		/* +2 for EOB chars. */
-		register int number_to_move = (yy_n_chars) + 2;
-		register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
-					YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
-		register char *source =
-				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
-
-		while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
-			*--dest = *--source;
-
-		yy_cp += (int) (dest - source);
-		yy_bp += (int) (dest - source);
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars =
-			(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size;
-
-		if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
-			YY_FATAL_ERROR( "flex scanner push-back overflow" );
-		}
-
-	*--yy_cp = (char) c;
-
-	(yytext_ptr) = yy_bp;
-	(yy_hold_char) = *yy_cp;
-	(yy_c_buf_p) = yy_cp;
-}
-
-#ifndef YY_NO_INPUT
-#ifdef __cplusplus
-    static int yyinput (void)
-#else
-    static int input  (void)
-#endif
-
-{
-	int c;
-    
-	*(yy_c_buf_p) = (yy_hold_char);
-
-	if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
-		{
-		/* yy_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 ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
-			/* This was really a NUL. */
-			*(yy_c_buf_p) = '\0';
-
-		else
-			{ /* need more input */
-			int offset = (yy_c_buf_p) - (yytext_ptr);
-			++(yy_c_buf_p);
-
-			switch ( yy_get_next_buffer(  ) )
-				{
-				case EOB_ACT_LAST_MATCH:
-					/* This happens because yy_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. */
-					wcsbthrestart(wcsbthin );
-
-					/*FALLTHROUGH*/
-
-				case EOB_ACT_END_OF_FILE:
-					{
-					if ( wcsbthwrap( ) )
-						return EOF;
-
-					if ( ! (yy_did_buffer_switch_on_eof) )
-						YY_NEW_FILE;
-#ifdef __cplusplus
-					return yyinput();
-#else
-					return input();
-#endif
-					}
-
-				case EOB_ACT_CONTINUE_SCAN:
-					(yy_c_buf_p) = (yytext_ptr) + offset;
-					break;
-				}
-			}
-		}
-
-	c = *(unsigned char *) (yy_c_buf_p);	/* cast for 8-bit char's */
-	*(yy_c_buf_p) = '\0';	/* preserve wcsbthtext */
-	(yy_hold_char) = *++(yy_c_buf_p);
-
-	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = (c == '\n');
-
-	return c;
-}
-#endif	/* ifndef YY_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 wcsbthrestart  (FILE * input_file )
-{
-    
-	if ( ! YY_CURRENT_BUFFER ){
-        wcsbthensure_buffer_stack ();
-		YY_CURRENT_BUFFER_LVALUE =
-            wcsbth_create_buffer(wcsbthin,YY_BUF_SIZE );
-	}
-
-	wcsbth_init_buffer(YY_CURRENT_BUFFER,input_file );
-	wcsbth_load_buffer_state( );
-}
-
-/** Switch to a different input buffer.
- * @param new_buffer The new input buffer.
- * 
- */
-    void wcsbth_switch_to_buffer  (YY_BUFFER_STATE  new_buffer )
-{
-    
-	/* TODO. We should be able to replace this entire function body
-	 * with
-	 *		wcsbthpop_buffer_state();
-	 *		wcsbthpush_buffer_state(new_buffer);
-     */
-	wcsbthensure_buffer_stack ();
-	if ( YY_CURRENT_BUFFER == new_buffer )
-		return;
-
-	if ( YY_CURRENT_BUFFER )
-		{
-		/* Flush out information for old buffer. */
-		*(yy_c_buf_p) = (yy_hold_char);
-		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
-		}
-
-	YY_CURRENT_BUFFER_LVALUE = new_buffer;
-	wcsbth_load_buffer_state( );
-
-	/* We don't actually know whether we did this switch during
-	 * EOF (wcsbthwrap()) processing, but the only time this flag
-	 * is looked at is after wcsbthwrap() is called, so it's safe
-	 * to go ahead and always set it.
-	 */
-	(yy_did_buffer_switch_on_eof) = 1;
-}
-
-static void wcsbth_load_buffer_state  (void)
-{
-    	(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
-	(yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
-	wcsbthin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
-	(yy_hold_char) = *(yy_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 YY_BUF_SIZE.
- * 
- * @return the allocated buffer state.
- */
-    YY_BUFFER_STATE wcsbth_create_buffer  (FILE * file, int  size )
-{
-	YY_BUFFER_STATE b;
-    
-	b = (YY_BUFFER_STATE) wcsbthalloc(sizeof( struct yy_buffer_state )  );
-	if ( ! b )
-		YY_FATAL_ERROR( "out of dynamic memory in wcsbth_create_buffer()" );
-
-	b->yy_buf_size = size;
-
-	/* yy_ch_buf has to be 2 characters longer than the size given because
-	 * we need to put in 2 end-of-buffer characters.
-	 */
-	b->yy_ch_buf = (char *) wcsbthalloc(b->yy_buf_size + 2  );
-	if ( ! b->yy_ch_buf )
-		YY_FATAL_ERROR( "out of dynamic memory in wcsbth_create_buffer()" );
-
-	b->yy_is_our_buffer = 1;
-
-	wcsbth_init_buffer(b,file );
-
-	return b;
-}
-
-/** Destroy the buffer.
- * @param b a buffer created with wcsbth_create_buffer()
- * 
- */
-    void wcsbth_delete_buffer (YY_BUFFER_STATE  b )
-{
-    
-	if ( ! b )
-		return;
-
-	if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
-		YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
-
-	if ( b->yy_is_our_buffer )
-		wcsbthfree((void *) b->yy_ch_buf  );
-
-	wcsbthfree((void *) b  );
-}
-
-/* Initializes or reinitializes a buffer.
- * This function is sometimes called more than once on the same buffer,
- * such as during a wcsbthrestart() or at EOF.
- */
-    static void wcsbth_init_buffer  (YY_BUFFER_STATE  b, FILE * file )
-
-{
-	int oerrno = errno;
-    
-	wcsbth_flush_buffer(b );
-
-	b->yy_input_file = file;
-	b->yy_fill_buffer = 1;
-
-    /* If b is the current buffer, then wcsbth_init_buffer was _probably_
-     * called from wcsbthrestart() or through yy_get_next_buffer.
-     * In that case, we don't want to reset the lineno or column.
-     */
-    if (b != YY_CURRENT_BUFFER){
-        b->yy_bs_lineno = 1;
-        b->yy_bs_column = 0;
-    }
-
-        b->yy_is_interactive = 0;
-    
-	errno = oerrno;
-}
-
-/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
- * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
- * 
- */
-    void wcsbth_flush_buffer (YY_BUFFER_STATE  b )
-{
-    	if ( ! b )
-		return;
-
-	b->yy_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->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
-	b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
-
-	b->yy_buf_pos = &b->yy_ch_buf[0];
-
-	b->yy_at_bol = 1;
-	b->yy_buffer_status = YY_BUFFER_NEW;
-
-	if ( b == YY_CURRENT_BUFFER )
-		wcsbth_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 wcsbthpush_buffer_state (YY_BUFFER_STATE new_buffer )
-{
-    	if (new_buffer == NULL)
-		return;
-
-	wcsbthensure_buffer_stack();
-
-	/* This block is copied from wcsbth_switch_to_buffer. */
-	if ( YY_CURRENT_BUFFER )
-		{
-		/* Flush out information for old buffer. */
-		*(yy_c_buf_p) = (yy_hold_char);
-		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
-		}
-
-	/* Only push if top exists. Otherwise, replace top. */
-	if (YY_CURRENT_BUFFER)
-		(yy_buffer_stack_top)++;
-	YY_CURRENT_BUFFER_LVALUE = new_buffer;
-
-	/* copied from wcsbth_switch_to_buffer. */
-	wcsbth_load_buffer_state( );
-	(yy_did_buffer_switch_on_eof) = 1;
-}
-
-/** Removes and deletes the top of the stack, if present.
- *  The next element becomes the new top.
- *  
- */
-void wcsbthpop_buffer_state (void)
-{
-    	if (!YY_CURRENT_BUFFER)
-		return;
-
-	wcsbth_delete_buffer(YY_CURRENT_BUFFER );
-	YY_CURRENT_BUFFER_LVALUE = NULL;
-	if ((yy_buffer_stack_top) > 0)
-		--(yy_buffer_stack_top);
-
-	if (YY_CURRENT_BUFFER) {
-		wcsbth_load_buffer_state( );
-		(yy_did_buffer_switch_on_eof) = 1;
-	}
-}
-
-/* Allocates the stack if it does not exist.
- *  Guarantees space for at least one push.
- */
-static void wcsbthensure_buffer_stack (void)
-{
-	int num_to_alloc;
-    
-	if (!(yy_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;
-		(yy_buffer_stack) = (struct yy_buffer_state**)wcsbthalloc
-								(num_to_alloc * sizeof(struct yy_buffer_state*)
-								);
-		if ( ! (yy_buffer_stack) )
-			YY_FATAL_ERROR( "out of dynamic memory in wcsbthensure_buffer_stack()" );
-								  
-		memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
-				
-		(yy_buffer_stack_max) = num_to_alloc;
-		(yy_buffer_stack_top) = 0;
-		return;
-	}
-
-	if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
-
-		/* Increase the buffer to prepare for a possible push. */
-		int grow_size = 8 /* arbitrary grow size */;
-
-		num_to_alloc = (yy_buffer_stack_max) + grow_size;
-		(yy_buffer_stack) = (struct yy_buffer_state**)wcsbthrealloc
-								((yy_buffer_stack),
-								num_to_alloc * sizeof(struct yy_buffer_state*)
-								);
-		if ( ! (yy_buffer_stack) )
-			YY_FATAL_ERROR( "out of dynamic memory in wcsbthensure_buffer_stack()" );
-
-		/* zero only the new slots.*/
-		memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
-		(yy_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. 
- */
-YY_BUFFER_STATE wcsbth_scan_buffer  (char * base, yy_size_t  size )
-{
-	YY_BUFFER_STATE b;
-    
-	if ( size < 2 ||
-	     base[size-2] != YY_END_OF_BUFFER_CHAR ||
-	     base[size-1] != YY_END_OF_BUFFER_CHAR )
-		/* They forgot to leave room for the EOB's. */
-		return 0;
-
-	b = (YY_BUFFER_STATE) wcsbthalloc(sizeof( struct yy_buffer_state )  );
-	if ( ! b )
-		YY_FATAL_ERROR( "out of dynamic memory in wcsbth_scan_buffer()" );
-
-	b->yy_buf_size = size - 2;	/* "- 2" to take care of EOB's */
-	b->yy_buf_pos = b->yy_ch_buf = base;
-	b->yy_is_our_buffer = 0;
-	b->yy_input_file = 0;
-	b->yy_n_chars = b->yy_buf_size;
-	b->yy_is_interactive = 0;
-	b->yy_at_bol = 1;
-	b->yy_fill_buffer = 0;
-	b->yy_buffer_status = YY_BUFFER_NEW;
-
-	wcsbth_switch_to_buffer(b  );
-
-	return b;
-}
-
-/** Setup the input buffer state to scan a string. The next call to wcsbthlex() will
- * scan from a @e copy of @a str.
- * @param yystr 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
- *       wcsbth_scan_bytes() instead.
- */
-YY_BUFFER_STATE wcsbth_scan_string (yyconst char * yystr )
-{
-    
-	return wcsbth_scan_bytes(yystr,strlen(yystr) );
-}
-
-/** Setup the input buffer state to scan the given bytes. The next call to wcsbthlex() will
- * scan from a @e copy of @a bytes.
- * @param yybytes the byte buffer to scan
- * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
- * 
- * @return the newly allocated buffer state object.
- */
-YY_BUFFER_STATE wcsbth_scan_bytes  (yyconst char * yybytes, int  _yybytes_len )
-{
-	YY_BUFFER_STATE b;
-	char *buf;
-	yy_size_t n;
-	int i;
-    
-	/* Get memory for full buffer, including space for trailing EOB's. */
-	n = _yybytes_len + 2;
-	buf = (char *) wcsbthalloc(n  );
-	if ( ! buf )
-		YY_FATAL_ERROR( "out of dynamic memory in wcsbth_scan_bytes()" );
-
-	for ( i = 0; i < _yybytes_len; ++i )
-		buf[i] = yybytes[i];
-
-	buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
-
-	b = wcsbth_scan_buffer(buf,n );
-	if ( ! b )
-		YY_FATAL_ERROR( "bad buffer in wcsbth_scan_bytes()" );
-
-	/* It's okay to grow etc. this buffer, and we should throw it
-	 * away when we're done.
-	 */
-	b->yy_is_our_buffer = 1;
-
-	return b;
-}
-
-#ifndef YY_EXIT_FAILURE
-#define YY_EXIT_FAILURE 2
-#endif
-
-static void yy_fatal_error (yyconst char* msg )
-{
-    	(void) fprintf( stderr, "%s\n", msg );
-	exit( YY_EXIT_FAILURE );
-}
-
-/* Redefine yyless() so it works in section 3 code. */
-
-#undef yyless
-#define yyless(n) \
-	do \
-		{ \
-		/* Undo effects of setting up wcsbthtext. */ \
-        int yyless_macro_arg = (n); \
-        YY_LESS_LINENO(yyless_macro_arg);\
-		wcsbthtext[wcsbthleng] = (yy_hold_char); \
-		(yy_c_buf_p) = wcsbthtext + yyless_macro_arg; \
-		(yy_hold_char) = *(yy_c_buf_p); \
-		*(yy_c_buf_p) = '\0'; \
-		wcsbthleng = yyless_macro_arg; \
-		} \
-	while ( 0 )
-
-/* Accessor  methods (get/set functions) to struct members. */
-
-/** Get the current line number.
- * 
- */
-int wcsbthget_lineno  (void)
-{
-        
-    return wcsbthlineno;
-}
-
-/** Get the input stream.
- * 
- */
-FILE *wcsbthget_in  (void)
-{
-        return wcsbthin;
-}
-
-/** Get the output stream.
- * 
- */
-FILE *wcsbthget_out  (void)
-{
-        return wcsbthout;
-}
-
-/** Get the length of the current token.
- * 
- */
-int wcsbthget_leng  (void)
-{
-        return wcsbthleng;
-}
-
-/** Get the current token.
- * 
- */
-
-char *wcsbthget_text  (void)
-{
-        return wcsbthtext;
-}
-
-/** Set the current line number.
- * @param line_number
- * 
- */
-void wcsbthset_lineno (int  line_number )
-{
-    
-    wcsbthlineno = line_number;
-}
-
-/** Set the input stream. This does not discard the current
- * input buffer.
- * @param in_str A readable stream.
- * 
- * @see wcsbth_switch_to_buffer
- */
-void wcsbthset_in (FILE *  in_str )
-{
-        wcsbthin = in_str ;
-}
-
-void wcsbthset_out (FILE *  out_str )
-{
-        wcsbthout = out_str ;
-}
-
-int wcsbthget_debug  (void)
-{
-        return wcsbth_flex_debug;
-}
-
-void wcsbthset_debug (int  bdebug )
-{
-        wcsbth_flex_debug = bdebug ;
-}
-
-static int yy_init_globals (void)
-{
-        /* Initialization is the same as for the non-reentrant scanner.
-     * This function is called from wcsbthlex_destroy(), so don't allocate here.
-     */
-
-    (yy_buffer_stack) = 0;
-    (yy_buffer_stack_top) = 0;
-    (yy_buffer_stack_max) = 0;
-    (yy_c_buf_p) = (char *) 0;
-    (yy_init) = 0;
-    (yy_start) = 0;
-
-/* Defined in main.c */
-#ifdef YY_STDINIT
-    wcsbthin = stdin;
-    wcsbthout = stdout;
-#else
-    wcsbthin = (FILE *) 0;
-    wcsbthout = (FILE *) 0;
-#endif
-
-    /* For future reference: Set errno on error, since we are called by
-     * wcsbthlex_init()
-     */
-    return 0;
-}
-
-/* wcsbthlex_destroy is for both reentrant and non-reentrant scanners. */
-int wcsbthlex_destroy  (void)
-{
-    
-    /* Pop the buffer stack, destroying each element. */
-	while(YY_CURRENT_BUFFER){
-		wcsbth_delete_buffer(YY_CURRENT_BUFFER  );
-		YY_CURRENT_BUFFER_LVALUE = NULL;
-		wcsbthpop_buffer_state();
-	}
-
-	/* Destroy the stack itself. */
-	wcsbthfree((yy_buffer_stack) );
-	(yy_buffer_stack) = NULL;
-
-    /* Reset the globals. This is important in a non-reentrant scanner so the next time
-     * wcsbthlex() is called, initialization will occur. */
-    yy_init_globals( );
-
-    return 0;
-}
-
-/*
- * Internal utility routines.
- */
-
-#ifndef yytext_ptr
-static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
-{
-	register int i;
-	for ( i = 0; i < n; ++i )
-		s1[i] = s2[i];
-}
-#endif
-
-#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * s )
-{
-	register int n;
-	for ( n = 0; s[n]; ++n )
-		;
-
-	return n;
-}
-#endif
-
-void *wcsbthalloc (yy_size_t  size )
-{
-	return (void *) malloc( size );
-}
-
-void *wcsbthrealloc  (void * ptr, yy_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 wcsbthfree (void * ptr )
-{
-	free( (char *) ptr );	/* see wcsbthrealloc() for (char *) cast */
-}
-
-#define YYTABLES_NAME "yytables"
-
-#line 2081 "wcsbth.l"
-
-
-
-/*----------------------------------------------------------------------------
-* Perform first-pass tasks:
-*
-* 1) Count the number of coordinate axes in each of the 27 possible alternate
-*    image-header coordinate representations.  Also count the number of PVi_ma
-*    and PSi_ma keywords in each representation.
-*
-* 2) Determine the number of binary table columns that have an image array
-*    with a coordinate representation (up to 999), and count the number of
-*    coordinate axes in each of the 27 possible alternates.  Also count the
-*    number of iVn_ma and iSn_ma keywords in each representation.
-*
-* 3) Determine the number of alternate pixel list coordinate representations
-*    (up to 27) and the table columns associated with each.  Also count the
-*    number of TVn_ma and TSn_ma keywords in each representation.
-*
-* In the first pass alts->arridx[icol][27] is used to determine the number of
-* axes in each of 27 possible image-header coordinate descriptions (icol == 0)
-* and each of the 27 possible coordinate representations for an image array in
-* each column.
-*
-* The elements of alts->pixlist[icol] are used as bit arrays to flag which of
-* the 27 possible pixel list coordinate representations are associated with
-* each table column.
-*---------------------------------------------------------------------------*/
-
-int wcsbth_pass1(
-  int keytype,
-  int i,
-  int j,
-  int n,
-  int k,
-  char a,
-  char ptype,
-  struct wcsbth_alts *alts)
-
-{
-  int ialt, icol, mask, ncol;
-
-  if (a == 0) {
-    /* Keywords such as DATE-OBS go along for the ride. */
-    return 0;
-  }
-
-  ncol = alts->ncol;
-
-  /* Do we need to allocate memory for alts? */
-  if (alts->arridx == 0x0) {
-    if (ncol == 0) {
-      /* Can only happen if TFIELDS is missing or out-of-sequence.  If n and
-         k are both zero then we may be processing an image header so leave
-         ncol alone - the array will be realloc'd later if required. */
-      if (n || k) {
-        /* The header is mangled, assume the worst. */
-        ncol = 999;
-      }
-    }
-
-    if (!(alts->arridx  =  calloc((1 + ncol)*27, sizeof(short int))) ||
-        !(alts->npv     =  calloc((1 + ncol)*27, sizeof(unsigned char)))  ||
-        !(alts->nps     =  calloc((1 + ncol)*27, sizeof(unsigned char)))  ||
-        !(alts->pixlist =  calloc((1 + ncol),    sizeof(unsigned int)))) {
-      if (alts->arridx)  free(alts->arridx);
-      if (alts->npv)     free(alts->npv);
-      if (alts->nps)     free(alts->nps);
-      if (alts->pixlist) free(alts->pixlist);
-      return 2;
-    }
-
-    alts->ncol = ncol;
-
-  } else if (n > ncol || k > ncol) {
-    /* Can only happen if TFIELDS or the WCS keyword is wrong; carry on. */
-    ncol = 999;
-    if (!(alts->arridx  = realloc(alts->arridx,
-                                    27*(1 + ncol)*sizeof(short int))) ||
-        !(alts->npv     = realloc(alts->npv,
-                                    27*(1 + ncol)*sizeof(unsigned char)))  ||
-        !(alts->nps     = realloc(alts->nps,
-                                    27*(1 + ncol)*sizeof(unsigned char)))  ||
-        !(alts->pixlist = realloc(alts->pixlist,
-                                       (1 + ncol)*sizeof(unsigned int)))) {
-      if (alts->arridx)  free(alts->arridx);
-      if (alts->npv)     free(alts->npv);
-      if (alts->nps)     free(alts->nps);
-      if (alts->pixlist) free(alts->pixlist);
-      return 2;
-    }
-
-    /* Since realloc() doesn't initialize the extra memory. */
-    for (icol = (1 + alts->ncol); icol < (1 + ncol); icol++) {
-      for (ialt = 0; ialt < 27; ialt++) {
-        alts->arridx[icol][ialt] = 0;
-        alts->npv[icol][ialt] = 0;
-        alts->nps[icol][ialt] = 0;
-        alts->pixlist[icol]   = 0;
-      }
-    }
-
-    alts->ncol = ncol;
-  }
-
-  ialt = 0;
-  if (a != ' ') {
-    ialt = a - 'A' + 1;
-  }
-
-  /* A BINTAB keytype such as LONPna, in conjunction with an IMGAXIS keytype
-     causes a table column to be recognized as an image array. */
-  if (keytype & IMGHEAD || keytype & BIMGARR) {
-    /* n == 0 is expected for IMGHEAD keywords. */
-    if (i == 0 && j == 0) {
-      if (alts->arridx[n][ialt] == 0) {
-        /* Flag that an auxiliary keyword was seen. */
-        alts->arridx[n][ialt] = -1;
-      }
-
-    } else {
-      /* Record the maximum axis number found. */
-      if (alts->arridx[n][ialt] < i) {
-        alts->arridx[n][ialt] = i;
-      }
-
-      if (alts->arridx[n][ialt] < j) {
-        alts->arridx[n][ialt] = j;
-      }
-    }
-
-    if (ptype == 'v') {
-      alts->npv[n][ialt]++;
-    } else if (ptype == 's') {
-      alts->nps[n][ialt]++;
-    }
-  }
-
-  /* BINTAB keytypes, which apply both to pixel lists as well as binary table
-     image arrays, never contribute to recognizing a table column as a pixel
-     list axis.  A PIXLIST keytype is required for that. */
-  if (keytype == PIXLIST) {
-    mask = 1 << ialt;
-
-    /* n > 0 for PIXLIST keytypes. */
-    alts->pixlist[n] |= mask;
-    if (k) alts->pixlist[k] |= mask;
-
-    /* Used as a flag over all columns. */
-    alts->pixlist[0] |= mask;
-
-    if (ptype == 'v') {
-      alts->pixnpv[ialt]++;
-    } else if (ptype == 's') {
-      alts->pixnps[ialt]++;
-    }
-  }
-
-  return 0;
-}
-
-
-/*----------------------------------------------------------------------------
-* Perform initializations at the end of the first pass:
-*
-* 1) Determine the required number of wcsprm structs, allocate memory for
-*    an array of them and initialize each one.
-*---------------------------------------------------------------------------*/
-
-int wcsbth_init1(
-  struct wcsbth_alts *alts,
-  int *nwcs,
-  struct wcsprm **wcs)
-
-{
-  int ialt, icol, inherit[27], ix, mask, ncol, npsmax, npvmax, status = 0;
-  struct wcsprm *wcsp;
-
-
-  if (alts->arridx == 0x0) {
-    *nwcs = 0;
-    return 0;
-  }
-
-  /* Determine the number of axes in each pixel list representation. */
-  ncol = alts->ncol;
-  for (ialt = 0, mask = 1; ialt < 27; ialt++, mask <<= 1) {
-    alts->pixidx[ialt] = 0;
-
-    if (alts->pixlist[0] | mask) {
-      for (icol = 1; icol <= ncol; icol++) {
-        if (alts->pixlist[icol] & mask) {
-          alts->pixidx[ialt]++;
-        }
-      }
-    }
-  }
-
-  /* Find the total number of coordinate representations. */
-  *nwcs = 0;
-  alts->imgherit = 0;
-  for (ialt = 0; ialt < 27; ialt++) {
-    inherit[ialt] = 0;
-
-    for (icol = 1; icol <= ncol; icol++) {
-      if (alts->arridx[icol][ialt] < 0) {
-        /* No BIMGARR keytype but there's at least one BINTAB. */
-        if (alts->arridx[0][ialt] > 0) {
-          /* There is an IMGAXIS keytype that we will inherit, so count this
-             representation. */
-          alts->arridx[icol][ialt] = alts->arridx[0][ialt];
-        } else {
-          alts->arridx[icol][ialt] = 0;
-        }
-      }
-
-      if (alts->arridx[icol][ialt]) {
-        if (alts->arridx[0][ialt]) {
-          /* All IMGHEAD keywords are inherited for this ialt. */
-          inherit[ialt] = 1;
-
-          if (alts->arridx[icol][ialt] < alts->arridx[0][ialt]) {
-            /* The extra axes are also inherited. */
-            alts->arridx[icol][ialt] = alts->arridx[0][ialt];
-          }
-        }
-
-        (*nwcs)++;
-      }
-    }
-
-    /* Count every "a" found in any IMGHEAD keyword... */
-    if (alts->arridx[0][ialt]) {
-      if (inherit[ialt]) {
-        /* ...but not if the IMGHEAD keywords will be inherited. */
-        alts->arridx[0][ialt] = 0;
-        alts->imgherit = 1;
-      } else {
-        (*nwcs)++;
-      }
-    }
-
-    /* We need a struct for every "a" found in a PIXLIST keyword. */
-    if (alts->pixidx[ialt]) {
-      (*nwcs)++;
-    }
-  }
-
-
-  if (*nwcs) {
-    /* Allocate memory for the required number of wcsprm structs. */
-    if (!(*wcs = calloc(*nwcs, sizeof(struct wcsprm)))) {
-      return 2;
-    }
-
-    /* Record the current values of NPVMAX and NPSMAX. */
-    npvmax = wcsnpv(-1);
-    npsmax = wcsnps(-1);
-
-    /* Initialize each wcsprm struct. */
-    wcsp = *wcs;
-    *nwcs = 0;
-    for (icol = 0; icol <= ncol; icol++) {
-      for (ialt = 0; ialt < 27; ialt++) {
-        if (alts->arridx[icol][ialt]) {
-          /* Image-header representations that are not for inheritance
-             (icol == 0) or binary table image array representations. */
-          wcsp->flag = -1;
-          wcsnpv(alts->npv[icol][ialt]);
-          wcsnps(alts->nps[icol][ialt]);
-          if ((status = wcsini(1, (int)(alts->arridx[icol][ialt]), wcsp))) {
-            wcsvfree(nwcs, wcs);
-            break;
-          }
-
-          /* Record the alternate version code. */
-          if (ialt) {
-            wcsp->alt[0] = 'A' + ialt - 1;
-          }
-
-          /* Record the table column number. */
-          wcsp->colnum = icol;
-
-          /* On the second pass alts->arridx[icol][27] indexes the array of
-             wcsprm structs. */
-          alts->arridx[icol][ialt] = (*nwcs)++;
-
-          wcsp++;
-
-        } else {
-          /* Signal that this column has no WCS for this "a". */
-          alts->arridx[icol][ialt] = -1;
-        }
-      }
-    }
-
-    for (ialt = 0; ialt < 27; ialt++) {
-      if (alts->pixidx[ialt]) {
-        /* Pixel lists representations. */
-        wcsp->flag = -1;
-        wcsnpv(alts->pixnpv[ialt]);
-        wcsnps(alts->pixnps[ialt]);
-        if ((status = wcsini(1, (int)(alts->pixidx[ialt]), wcsp))) {
-          wcsvfree(nwcs, wcs);
-          break;
-        }
-
-        /* Record the alternate version code. */
-        if (ialt) {
-          wcsp->alt[0] = 'A' + ialt - 1;
-        }
-
-        /* Record the pixel list column numbers. */
-        mask = (1 << ialt);
-        for (icol = 1, ix = 0; icol <= ncol; icol++) {
-          if (alts->pixlist[icol] & mask) {
-            wcsp->colax[ix++] = icol;
-          }
-        }
-
-        /* alts->pixidx[] indexes the array of wcsprm structs. */
-        alts->pixidx[ialt] = (*nwcs)++;
-
-        wcsp++;
-
-      } else {
-        /* Signal that this column is not a pixel list axis for this "a". */
-        alts->pixidx[ialt] = -1;
-      }
-    }
-
-    /* Restore the original values of NPVMAX and NPSMAX. */
-    wcsnpv(npvmax);
-    wcsnps(npsmax);
-  }
-
-  return status;
-}
-
-
-/*----------------------------------------------------------------------------
-* Return a pointer to the next wcsprm struct for a particular column number
-* and alternate.
-*---------------------------------------------------------------------------*/
-
-struct wcsprm *wcsbth_idx(
-  struct wcsprm *wcs,
-  struct wcsbth_alts *alts,
-  int  keytype,
-  int  n,
-  char a)
-
-{
-  const char as[] = " ABCDEFGHIJKLMNOPQRSTUVWXYZ";
-  int iwcs;
-
-  if (!wcs) return 0x0;
-
-  iwcs = -1;
-  for (; iwcs < 0 && alts->ialt < 27; alts->ialt++) {
-    /* Note that a == 0 applies to every alternate, otherwise this
-       loop simply determines the appropriate value of alts->ialt. */
-    if (a && a != as[alts->ialt]) continue;
-
-    if (keytype & (IMGHEAD | BIMGARR)) {
-      for (; iwcs < 0 && alts->icol <= alts->ncol; alts->icol++) {
-        /* Image header keywords, n == 0, apply to all columns, otherwise this
-           loop simply determines the appropriate value of alts->icol. */
-        if (n && n != alts->icol) continue;
-        iwcs = alts->arridx[alts->icol][alts->ialt];
-      }
-
-      /* Break out of the loop to stop alts->ialt from being incremented. */
-      if (iwcs >= 0) break;
-
-      /* Start from scratch for the next alts->ialt. */
-      alts->icol = 0;
-    }
-
-    if (keytype & (IMGAUX | PIXLIST)) {
-      iwcs = alts->pixidx[alts->ialt];
-    }
-  }
-
-  return (iwcs >= 0) ? (wcs + iwcs) : 0x0;
-}
-
-
-/*----------------------------------------------------------------------------
-* Return the axis number associated with the specified column number in a
-* particular pixel list coordinate representation.
-*---------------------------------------------------------------------------*/
-
-int wcsbth_colax(
-  struct wcsprm *wcs,
-  struct wcsbth_alts *alts,
-  int n,
-  char a)
-
-{
-  int ix;
-  struct wcsprm *wcsp;
-
-  if (!wcs) return 0;
-
-  wcsp = wcs;
-  if (a != ' ') {
-    wcsp += alts->pixidx[a-'A'+1];
-  }
-
-  for (ix = 0; ix < wcsp->naxis; ix++) {
-    if (wcsp->colax[ix] == n) {
-      return ++ix;
-    }
-  }
-
-  return 0;
-}
-
-
-/*----------------------------------------------------------------------------
-* Interpret EPOCH keywords.
-*---------------------------------------------------------------------------*/
-
-int wcsbth_epoch(void *wptr)
-
-{
-  double *equinox;
-
-  /* If EQUINOXa is currently undefined then set it from EPOCHa. */
-  equinox = (double *)wptr;
-  if (undefined(*equinox)) {
-    sscanf(wcsbthtext, "%lf", equinox);
-  }
-
-  return 0;
-}
-
-
-/*----------------------------------------------------------------------------
-* Interpret VSOURCE keywords.
-*---------------------------------------------------------------------------*/
-
-int wcsbth_vsource(void *wptr)
-
-{
-  double beta, c = 299792458.0, vsource, *zsource;
-
-  /* If ZSOURCEa is currently undefined then set it from VSOURCEa. */
-  zsource = (double *)wptr;
-  if (undefined(*zsource)) {
-    sscanf(wcsbthtext, "%lf", &vsource);
-
-    /* Convert relativistic Doppler velocity to redshift. */
-    beta = vsource/c;
-    *zsource = (1.0 + beta)/sqrt(1.0 - beta*beta) - 1.0;
-  }
-
-  return 0;
-}
-
-
-/*----------------------------------------------------------------------------
-* Tie up loose ends.
-*---------------------------------------------------------------------------*/
-
-int wcsbth_final(
-  struct wcsbth_alts *alts,
-  int *nwcs,
-  struct wcsprm **wcs)
-
-{
-  int ialt, status;
-
-  if (alts->arridx)  free(alts->arridx);
-  if (alts->npv)     free(alts->npv);
-  if (alts->nps)     free(alts->nps);
-  if (alts->pixlist) free(alts->pixlist);
-
-  for (ialt = 0; ialt < *nwcs; ialt++) {
-    /* Interpret -TAB header keywords. */
-    if ((status = wcstab(*wcs+ialt))) {
-       wcsvfree(nwcs, wcs);
-       return status;
-    }
-  }
-
-  return 0;
-}
-
diff --git a/astropy/wcs/src/wcslib/C/flexed/wcspih.c b/astropy/wcs/src/wcslib/C/flexed/wcspih.c
deleted file mode 100644
index e52843f..0000000
--- a/astropy/wcs/src/wcslib/C/flexed/wcspih.c
+++ /dev/null
@@ -1,10829 +0,0 @@
-#line 2 "wcspih.c"
-
-#line 4 "wcspih.c"
-
-#define  YY_INT_ALIGNED short int
-
-/* A lexical scanner generated by flex */
-
-#define yy_create_buffer wcspih_create_buffer
-#define yy_delete_buffer wcspih_delete_buffer
-#define yy_flex_debug wcspih_flex_debug
-#define yy_init_buffer wcspih_init_buffer
-#define yy_flush_buffer wcspih_flush_buffer
-#define yy_load_buffer_state wcspih_load_buffer_state
-#define yy_switch_to_buffer wcspih_switch_to_buffer
-#define yyin wcspihin
-#define yyleng wcspihleng
-#define yylex wcspihlex
-#define yylineno wcspihlineno
-#define yyout wcspihout
-#define yyrestart wcspihrestart
-#define yytext wcspihtext
-#define yywrap wcspihwrap
-#define yyalloc wcspihalloc
-#define yyrealloc wcspihrealloc
-#define yyfree wcspihfree
-
-#define FLEX_SCANNER
-#define YY_FLEX_MAJOR_VERSION 2
-#define YY_FLEX_MINOR_VERSION 5
-#define YY_FLEX_SUBMINOR_VERSION 35
-#if YY_FLEX_SUBMINOR_VERSION > 0
-#define FLEX_BETA
-#endif
-
-/* First, we deal with  platform-specific or compiler-specific issues. */
-
-/* begin standard C headers. */
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <stdlib.h>
-
-/* end standard C headers. */
-
-/* flex integer type definitions */
-
-#ifndef FLEXINT_H
-#define FLEXINT_H
-
-/* C99 systems have <inttypes.h>. 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 <inttypes.h>
-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;
-
-/* 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 /* ! C99 */
-
-#endif /* ! FLEXINT_H */
-
-#ifdef __cplusplus
-
-/* The "const" storage-class-modifier is valid. */
-#define YY_USE_CONST
-
-#else	/* ! __cplusplus */
-
-/* C99 requires __STDC__ to be defined as 1. */
-#if defined (__STDC__)
-
-#define YY_USE_CONST
-
-#endif	/* defined (__STDC__) */
-#endif	/* ! __cplusplus */
-
-#ifdef YY_USE_CONST
-#define yyconst const
-#else
-#define yyconst
-#endif
-
-/* Returned upon end-of-file. */
-#define YY_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 YY_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 (yy_start) = 1 + 2 *
-
-/* Translate the current start state into a value that can be later handed
- * to BEGIN to return to the state.  The YYSTATE alias is for lex
- * compatibility.
- */
-#define YY_START (((yy_start) - 1) / 2)
-#define YYSTATE YY_START
-
-/* Action number for EOF rule of a given start state. */
-#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
-
-/* Special action meaning "start processing a new file". */
-#define YY_NEW_FILE wcspihrestart(wcspihin  )
-
-#define YY_END_OF_BUFFER_CHAR 0
-
-/* Size of default input buffer. */
-#ifndef YY_BUF_SIZE
-#ifdef __ia64__
-/* On IA-64, the buffer size is 16k, not 8k.
- * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
- * Ditto for the __ia64__ case accordingly.
- */
-#define YY_BUF_SIZE 32768
-#else
-#define YY_BUF_SIZE 16384
-#endif /* __ia64__ */
-#endif
-
-/* The state buf must be large enough to hold one state per character in the main buffer.
- */
-#define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
-
-#ifndef YY_TYPEDEF_YY_BUFFER_STATE
-#define YY_TYPEDEF_YY_BUFFER_STATE
-typedef struct yy_buffer_state *YY_BUFFER_STATE;
-#endif
-
-extern int wcspihleng;
-
-extern FILE *wcspihin, *wcspihout;
-
-#define EOB_ACT_CONTINUE_SCAN 0
-#define EOB_ACT_END_OF_FILE 1
-#define EOB_ACT_LAST_MATCH 2
-
-#define YY_LESS_LINENO(n)
-    
-/* Return all but the first "n" matched characters back to the input stream. */
-#define yyless(n) \
-	do \
-		{ \
-		/* Undo effects of setting up wcspihtext. */ \
-        int yyless_macro_arg = (n); \
-        YY_LESS_LINENO(yyless_macro_arg);\
-		*yy_cp = (yy_hold_char); \
-		YY_RESTORE_YY_MORE_OFFSET \
-		(yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
-		YY_DO_BEFORE_ACTION; /* set up wcspihtext again */ \
-		} \
-	while ( 0 )
-
-#define unput(c) yyunput( c, (yytext_ptr)  )
-
-#ifndef YY_TYPEDEF_YY_SIZE_T
-#define YY_TYPEDEF_YY_SIZE_T
-typedef size_t yy_size_t;
-#endif
-
-#ifndef YY_STRUCT_YY_BUFFER_STATE
-#define YY_STRUCT_YY_BUFFER_STATE
-struct yy_buffer_state
-	{
-	FILE *yy_input_file;
-
-	char *yy_ch_buf;		/* input buffer */
-	char *yy_buf_pos;		/* current position in input buffer */
-
-	/* Size of input buffer in bytes, not including room for EOB
-	 * characters.
-	 */
-	yy_size_t yy_buf_size;
-
-	/* Number of characters read into yy_ch_buf, not including EOB
-	 * characters.
-	 */
-	int yy_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 yy_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 yy_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 yy_at_bol;
-
-    int yy_bs_lineno; /**< The line count. */
-    int yy_bs_column; /**< The column count. */
-    
-	/* Whether to try to fill the input buffer when we reach the
-	 * end of it.
-	 */
-	int yy_fill_buffer;
-
-	int yy_buffer_status;
-
-#define YY_BUFFER_NEW 0
-#define YY_BUFFER_NORMAL 1
-	/* When an EOF's been seen but there's still some text to process
-	 * then we mark the buffer as YY_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 wcspihrestart()), so that the user can continue scanning by
-	 * just pointing wcspihin at a new input file.
-	 */
-#define YY_BUFFER_EOF_PENDING 2
-
-	};
-#endif /* !YY_STRUCT_YY_BUFFER_STATE */
-
-/* Stack of input buffers. */
-static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
-static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
-static YY_BUFFER_STATE * yy_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 YY_CURRENT_BUFFER ( (yy_buffer_stack) \
-                          ? (yy_buffer_stack)[(yy_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 YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
-
-/* yy_hold_char holds the character lost when wcspihtext is formed. */
-static char yy_hold_char;
-static int yy_n_chars;		/* number of characters read into yy_ch_buf */
-int wcspihleng;
-
-/* Points to current character in buffer. */
-static char *yy_c_buf_p = (char *) 0;
-static int yy_init = 0;		/* whether we need to initialize */
-static int yy_start = 0;	/* start state number */
-
-/* Flag which is used to allow wcspihwrap()'s to do buffer switches
- * instead of setting up a fresh wcspihin.  A bit of a hack ...
- */
-static int yy_did_buffer_switch_on_eof;
-
-void wcspihrestart (FILE *input_file  );
-void wcspih_switch_to_buffer (YY_BUFFER_STATE new_buffer  );
-YY_BUFFER_STATE wcspih_create_buffer (FILE *file,int size  );
-void wcspih_delete_buffer (YY_BUFFER_STATE b  );
-void wcspih_flush_buffer (YY_BUFFER_STATE b  );
-void wcspihpush_buffer_state (YY_BUFFER_STATE new_buffer  );
-void wcspihpop_buffer_state (void );
-
-static void wcspihensure_buffer_stack (void );
-static void wcspih_load_buffer_state (void );
-static void wcspih_init_buffer (YY_BUFFER_STATE b,FILE *file  );
-
-#define YY_FLUSH_BUFFER wcspih_flush_buffer(YY_CURRENT_BUFFER )
-
-YY_BUFFER_STATE wcspih_scan_buffer (char *base,yy_size_t size  );
-YY_BUFFER_STATE wcspih_scan_string (yyconst char *yy_str  );
-YY_BUFFER_STATE wcspih_scan_bytes (yyconst char *bytes,int len  );
-
-void *wcspihalloc (yy_size_t  );
-void *wcspihrealloc (void *,yy_size_t  );
-void wcspihfree (void *  );
-
-#define yy_new_buffer wcspih_create_buffer
-
-#define yy_set_interactive(is_interactive) \
-	{ \
-	if ( ! YY_CURRENT_BUFFER ){ \
-        wcspihensure_buffer_stack (); \
-		YY_CURRENT_BUFFER_LVALUE =    \
-            wcspih_create_buffer(wcspihin,YY_BUF_SIZE ); \
-	} \
-	YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
-	}
-
-#define yy_set_bol(at_bol) \
-	{ \
-	if ( ! YY_CURRENT_BUFFER ){\
-        wcspihensure_buffer_stack (); \
-		YY_CURRENT_BUFFER_LVALUE =    \
-            wcspih_create_buffer(wcspihin,YY_BUF_SIZE ); \
-	} \
-	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
-	}
-
-#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
-
-/* Begin user sect3 */
-
-#define wcspihwrap(n) 1
-#define YY_SKIP_YYWRAP
-
-typedef char YY_CHAR;
-
-FILE *wcspihin = (FILE *) 0, *wcspihout = (FILE *) 0;
-
-typedef int yy_state_type;
-
-extern int wcspihlineno;
-
-int wcspihlineno = 1;
-
-extern char *wcspihtext;
-#define yytext_ptr wcspihtext
-static yyconst flex_int16_t yy_nxt[][128] =
-    {
-    {
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0
-    },
-
-    {
-       33,   34,   34,   34,   34,   34,   34,   34,   34,   34,
-       34,   34,   34,   34,   34,   34,   34,   34,   34,   34,
-       34,   34,   34,   34,   34,   34,   34,   34,   34,   34,
-       34,   34,   34,   34,   34,   34,   34,   34,   34,   34,
-       34,   34,   34,   34,   34,   34,   34,   34,   34,   34,
-       34,   34,   34,   34,   34,   34,   34,   34,   34,   34,
-       34,   34,   34,   34,   34,   34,   34,   34,   34,   34,
-
-       34,   34,   34,   34,   34,   34,   34,   34,   34,   34,
-       34,   34,   34,   34,   34,   34,   34,   34,   34,   34,
-       34,   34,   34,   34,   34,   34,   34,   34,   34,   34,
-       34,   34,   34,   34,   34,   34,   34,   34,   34,   34,
-       34,   34,   34,   34,   34,   34,   34,   34,   34,   34,
-       34,   34,   34,   34,   34,   34,   34,   34
-    },
-
-    {
-       33,   35,   35,   35,   35,   35,   35,   35,   35,   35,
-       34,   35,   35,   35,   35,   35,   35,   35,   35,   35,
-       35,   35,   35,   35,   35,   35,   35,   35,   35,   35,
-       35,   35,   35,   35,   35,   35,   35,   35,   35,   35,
-
-       35,   35,   35,   35,   35,   35,   35,   35,   35,   35,
-       35,   35,   35,   35,   35,   35,   35,   35,   35,   35,
-       35,   35,   35,   35,   35,   35,   35,   36,   37,   38,
-       35,   35,   35,   35,   35,   35,   39,   40,   41,   42,
-       43,   35,   44,   45,   35,   35,   46,   47,   35,   35,
-       48,   35,   35,   35,   35,   35,   35,   35,   35,   35,
-       35,   35,   35,   35,   35,   35,   35,   35,   35,   35,
-       35,   35,   35,   35,   35,   35,   35,   35,   35,   35,
-       35,   35,   35,   35,   35,   35,   35,   35
-    },
-
-    {
-       33,   49,   49,   49,   49,   49,   49,   49,   49,   49,
-
-       34,   49,   49,   49,   49,   49,   49,   49,   49,   49,
-       49,   49,   49,   49,   49,   49,   49,   49,   49,   49,
-       49,   49,   49,   49,   49,   49,   49,   49,   49,   49,
-       49,   49,   49,   49,   49,   49,   49,   49,   49,   50,
-       50,   50,   50,   50,   50,   50,   50,   50,   49,   49,
-       49,   49,   49,   49,   49,   49,   49,   49,   49,   49,
-       49,   49,   49,   49,   49,   49,   49,   49,   49,   49,
-       49,   49,   49,   49,   49,   49,   49,   49,   49,   49,
-       49,   49,   49,   49,   49,   49,   49,   49,   49,   49,
-       49,   49,   49,   49,   49,   49,   49,   49,   49,   49,
-
-       49,   49,   49,   49,   49,   49,   49,   49,   49,   49,
-       49,   49,   49,   49,   49,   49,   49,   49
-    },
-
-    {
-       33,   49,   49,   49,   49,   49,   49,   49,   49,   49,
-       34,   49,   49,   49,   49,   49,   49,   49,   49,   49,
-       49,   49,   49,   49,   49,   49,   49,   49,   49,   49,
-       49,   49,   49,   49,   49,   49,   49,   49,   49,   49,
-       49,   49,   49,   49,   49,   49,   49,   49,   49,   50,
-       50,   50,   50,   50,   50,   50,   50,   50,   49,   49,
-       49,   49,   49,   49,   49,   49,   49,   49,   49,   49,
-       49,   49,   49,   49,   49,   49,   49,   49,   49,   49,
-
-       49,   49,   49,   49,   49,   49,   49,   49,   49,   49,
-       49,   49,   49,   49,   49,   49,   49,   49,   49,   49,
-       49,   49,   49,   49,   49,   49,   49,   49,   49,   49,
-       49,   49,   49,   49,   49,   49,   49,   49,   49,   49,
-       49,   49,   49,   49,   49,   49,   49,   49
-    },
-
-    {
-       33,   51,   51,   51,   51,   51,   51,   51,   51,   51,
-       34,   51,   51,   51,   51,   51,   51,   51,   51,   51,
-       51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
-       51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
-       51,   51,   51,   51,   51,   51,   51,   51,   52,   52,
-
-       52,   52,   52,   52,   52,   52,   52,   52,   51,   51,
-       51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
-       51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
-       51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
-       51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
-       51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
-       51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
-       51,   51,   51,   51,   51,   51,   51,   51
-    },
-
-    {
-       33,   51,   51,   51,   51,   51,   51,   51,   51,   51,
-       34,   51,   51,   51,   51,   51,   51,   51,   51,   51,
-
-       51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
-       51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
-       51,   51,   51,   51,   51,   51,   51,   51,   52,   52,
-       52,   52,   52,   52,   52,   52,   52,   52,   51,   51,
-       51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
-       51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
-       51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
-       51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
-       51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
-       51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
-
-       51,   51,   51,   51,   51,   51,   51,   51
-    },
-
-    {
-       33,   53,   53,   53,   53,   53,   53,   53,   53,   53,
-       34,   53,   53,   53,   53,   53,   53,   53,   53,   53,
-       53,   53,   53,   53,   53,   53,   53,   53,   53,   53,
-       53,   53,   53,   53,   53,   53,   53,   53,   53,   53,
-       53,   53,   53,   53,   53,   53,   53,   53,   53,   54,
-       54,   54,   54,   54,   54,   54,   54,   54,   53,   53,
-       53,   53,   53,   53,   53,   53,   53,   53,   53,   53,
-       53,   53,   53,   53,   53,   53,   53,   53,   53,   53,
-       53,   53,   53,   53,   53,   53,   53,   53,   53,   53,
-
-       53,   53,   53,   53,   53,   53,   53,   53,   53,   53,
-       53,   53,   53,   53,   53,   53,   53,   53,   53,   53,
-       53,   53,   53,   53,   53,   53,   53,   53,   53,   53,
-       53,   53,   53,   53,   53,   53,   53,   53
-    },
-
-    {
-       33,   53,   53,   53,   53,   53,   53,   53,   53,   53,
-       34,   53,   53,   53,   53,   53,   53,   53,   53,   53,
-       53,   53,   53,   53,   53,   53,   53,   53,   53,   53,
-       53,   53,   53,   53,   53,   53,   53,   53,   53,   53,
-       53,   53,   53,   53,   53,   53,   53,   53,   53,   54,
-       54,   54,   54,   54,   54,   54,   54,   54,   53,   53,
-
-       53,   53,   53,   53,   53,   53,   53,   53,   53,   53,
-       53,   53,   53,   53,   53,   53,   53,   53,   53,   53,
-       53,   53,   53,   53,   53,   53,   53,   53,   53,   53,
-       53,   53,   53,   53,   53,   53,   53,   53,   53,   53,
-       53,   53,   53,   53,   53,   53,   53,   53,   53,   53,
-       53,   53,   53,   53,   53,   53,   53,   53,   53,   53,
-       53,   53,   53,   53,   53,   53,   53,   53
-    },
-
-    {
-       33,   55,   55,   55,   55,   55,   55,   55,   55,   55,
-       34,   55,   55,   55,   55,   55,   55,   55,   55,   55,
-       55,   55,   55,   55,   55,   55,   55,   55,   55,   55,
-
-       55,   55,   55,   55,   55,   55,   55,   55,   55,   55,
-       55,   55,   55,   55,   55,   55,   55,   55,   56,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   55,   55,
-       55,   55,   55,   55,   55,   55,   55,   55,   55,   55,
-       55,   55,   55,   55,   55,   55,   55,   55,   55,   55,
-       55,   55,   55,   55,   55,   55,   55,   55,   55,   55,
-       55,   55,   55,   55,   55,   55,   55,   55,   55,   55,
-       55,   55,   55,   55,   55,   55,   55,   55,   55,   55,
-       55,   55,   55,   55,   55,   55,   55,   55,   55,   55,
-       55,   55,   55,   55,   55,   55,   55,   55
-
-    },
-
-    {
-       33,   55,   55,   55,   55,   55,   55,   55,   55,   55,
-       34,   55,   55,   55,   55,   55,   55,   55,   55,   55,
-       55,   55,   55,   55,   55,   55,   55,   55,   55,   55,
-       55,   55,   55,   55,   55,   55,   55,   55,   55,   55,
-       55,   55,   55,   55,   55,   55,   55,   55,   56,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   55,   55,
-       55,   55,   55,   55,   55,   55,   55,   55,   55,   55,
-       55,   55,   55,   55,   55,   55,   55,   55,   55,   55,
-       55,   55,   55,   55,   55,   55,   55,   55,   55,   55,
-       55,   55,   55,   55,   55,   55,   55,   55,   55,   55,
-
-       55,   55,   55,   55,   55,   55,   55,   55,   55,   55,
-       55,   55,   55,   55,   55,   55,   55,   55,   55,   55,
-       55,   55,   55,   55,   55,   55,   55,   55
-    },
-
-    {
-       33,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       34,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   59,
-       59,   59,   59,   59,   59,   59,   59,   59,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58
-    },
-
-    {
-       33,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       34,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   59,
-       59,   59,   59,   59,   59,   59,   59,   59,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58
-    },
-
-    {
-       33,   60,   60,   60,   60,   60,   60,   60,   60,   60,
-
-       34,   60,   60,   60,   60,   60,   60,   60,   60,   60,
-       60,   60,   60,   60,   60,   60,   60,   60,   60,   60,
-       60,   60,   61,   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,   61,   61,   61,   61,   61,
-       61,   61,   61,   61,   61,   61,   61,   61,   61,   61,
-       61,   61,   61,   61,   61,   61,   61,   61,   61,   61,
-       61,   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
-    },
-
-    {
-       33,   60,   60,   60,   60,   60,   60,   60,   60,   60,
-       34,   60,   60,   60,   60,   60,   60,   60,   60,   60,
-       60,   60,   60,   60,   60,   60,   60,   60,   60,   60,
-       60,   60,   61,   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,   61,   61,   61,   61,   61,
-       61,   61,   61,   61,   61,   61,   61,   61,   61,   61,
-
-       61,   61,   61,   61,   61,   61,   61,   61,   61,   61,
-       61,   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
-    },
-
-    {
-       33,   62,   62,   62,   62,   62,   62,   62,   62,   62,
-       34,   62,   62,   62,   62,   62,   62,   62,   62,   62,
-       62,   62,   62,   62,   62,   62,   62,   62,   62,   62,
-       62,   62,   62,   62,   62,   62,   62,   62,   62,   62,
-       62,   62,   62,   62,   62,   62,   62,   62,   62,   62,
-
-       62,   62,   62,   62,   62,   62,   62,   62,   62,   62,
-       62,   62,   62,   62,   62,   62,   62,   62,   62,   62,
-       62,   62,   62,   62,   62,   62,   62,   62,   62,   62,
-       62,   62,   62,   62,   62,   62,   62,   62,   62,   62,
-       62,   62,   62,   62,   62,   62,   62,   62,   62,   62,
-       62,   62,   62,   62,   62,   62,   62,   62,   62,   62,
-       62,   62,   62,   62,   62,   62,   62,   62,   62,   62,
-       62,   62,   62,   62,   62,   62,   62,   62
-    },
-
-    {
-       33,   62,   62,   62,   62,   62,   62,   62,   62,   62,
-       34,   62,   62,   62,   62,   62,   62,   62,   62,   62,
-
-       62,   62,   62,   62,   62,   62,   62,   62,   62,   62,
-       62,   62,   62,   62,   62,   62,   62,   62,   62,   62,
-       62,   62,   62,   62,   62,   62,   62,   62,   62,   62,
-       62,   62,   62,   62,   62,   62,   62,   62,   62,   62,
-       62,   62,   62,   62,   62,   62,   62,   62,   62,   62,
-       62,   62,   62,   62,   62,   62,   62,   62,   62,   62,
-       62,   62,   62,   62,   62,   62,   62,   62,   62,   62,
-       62,   62,   62,   62,   62,   62,   62,   62,   62,   62,
-       62,   62,   62,   62,   62,   62,   62,   62,   62,   62,
-       62,   62,   62,   62,   62,   62,   62,   62,   62,   62,
-
-       62,   62,   62,   62,   62,   62,   62,   62
-    },
-
-    {
-       33,   63,   63,   63,   63,   63,   63,   63,   63,   63,
-       34,   63,   63,   63,   63,   63,   63,   63,   63,   63,
-       63,   63,   63,   63,   63,   63,   63,   63,   63,   63,
-       63,   63,   63,   63,   63,   63,   63,   63,   63,   63,
-       63,   63,   63,   63,   63,   63,   63,   63,   63,   63,
-       63,   63,   63,   63,   63,   63,   63,   63,   63,   63,
-       63,   64,   63,   63,   63,   63,   63,   63,   63,   63,
-       63,   63,   63,   63,   63,   63,   63,   63,   63,   63,
-       63,   63,   63,   63,   63,   63,   63,   63,   63,   63,
-
-       63,   63,   63,   63,   63,   63,   63,   63,   63,   63,
-       63,   63,   63,   63,   63,   63,   63,   63,   63,   63,
-       63,   63,   63,   63,   63,   63,   63,   63,   63,   63,
-       63,   63,   63,   63,   63,   63,   63,   63
-    },
-
-    {
-       33,   63,   63,   63,   63,   63,   63,   63,   63,   63,
-       34,   63,   63,   63,   63,   63,   63,   63,   63,   63,
-       63,   63,   63,   63,   63,   63,   63,   63,   63,   63,
-       63,   63,   63,   63,   63,   63,   63,   63,   63,   63,
-       63,   63,   63,   63,   63,   63,   63,   63,   63,   63,
-       63,   63,   63,   63,   63,   63,   63,   63,   63,   63,
-
-       63,   64,   63,   63,   63,   63,   63,   63,   63,   63,
-       63,   63,   63,   63,   63,   63,   63,   63,   63,   63,
-       63,   63,   63,   63,   63,   63,   63,   63,   63,   63,
-       63,   63,   63,   63,   63,   63,   63,   63,   63,   63,
-       63,   63,   63,   63,   63,   63,   63,   63,   63,   63,
-       63,   63,   63,   63,   63,   63,   63,   63,   63,   63,
-       63,   63,   63,   63,   63,   63,   63,   63
-    },
-
-    {
-       33,   65,   65,   65,   65,   65,   65,   65,   65,   65,
-       34,   65,   65,   65,   65,   65,   65,   65,   65,   65,
-       65,   65,   65,   65,   65,   65,   65,   65,   65,   65,
-
-       65,   65,   65,   65,   65,   65,   65,   65,   65,   65,
-       65,   65,   65,   66,   65,   66,   65,   65,   67,   67,
-       67,   67,   67,   67,   67,   67,   67,   67,   65,   65,
-       65,   65,   65,   65,   65,   65,   65,   65,   65,   65,
-       65,   65,   65,   65,   65,   65,   65,   65,   65,   65,
-       65,   65,   65,   65,   65,   65,   65,   65,   65,   65,
-       65,   65,   65,   65,   65,   65,   65,   65,   65,   65,
-       65,   65,   65,   65,   65,   65,   65,   65,   65,   65,
-       65,   65,   65,   65,   65,   65,   65,   65,   65,   65,
-       65,   65,   65,   65,   65,   65,   65,   65
-
-    },
-
-    {
-       33,   65,   65,   65,   65,   65,   65,   65,   65,   65,
-       34,   65,   65,   65,   65,   65,   65,   65,   65,   65,
-       65,   65,   65,   65,   65,   65,   65,   65,   65,   65,
-       65,   65,   65,   65,   65,   65,   65,   65,   65,   65,
-       65,   65,   65,   66,   65,   66,   65,   65,   67,   67,
-       67,   67,   67,   67,   67,   67,   67,   67,   65,   65,
-       65,   65,   65,   65,   65,   65,   65,   65,   65,   65,
-       65,   65,   65,   65,   65,   65,   65,   65,   65,   65,
-       65,   65,   65,   65,   65,   65,   65,   65,   65,   65,
-       65,   65,   65,   65,   65,   65,   65,   65,   65,   65,
-
-       65,   65,   65,   65,   65,   65,   65,   65,   65,   65,
-       65,   65,   65,   65,   65,   65,   65,   65,   65,   65,
-       65,   65,   65,   65,   65,   65,   65,   65
-    },
-
-    {
-       33,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       34,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   69,   68,   69,   70,   68,   71,   71,
-       71,   71,   71,   71,   71,   71,   71,   71,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68
-    },
-
-    {
-       33,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       34,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-
-       68,   68,   68,   69,   68,   69,   70,   68,   71,   71,
-       71,   71,   71,   71,   71,   71,   71,   71,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
-       68,   68,   68,   68,   68,   68,   68,   68
-    },
-
-    {
-       33,   72,   72,   72,   72,   72,   72,   72,   72,   72,
-
-       34,   72,   72,   72,   72,   72,   72,   72,   72,   72,
-       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
-       72,   72,   72,   72,   72,   72,   72,   72,   72,   73,
-       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
-       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
-       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
-       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
-       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
-       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
-       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
-
-       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
-       72,   72,   72,   72,   72,   72,   72,   72
-    },
-
-    {
-       33,   72,   72,   72,   72,   72,   72,   72,   72,   72,
-       34,   72,   72,   72,   72,   72,   72,   72,   72,   72,
-       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
-       72,   72,   72,   72,   72,   72,   72,   72,   72,   73,
-       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
-       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
-       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
-       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
-
-       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
-       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
-       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
-       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
-       72,   72,   72,   72,   72,   72,   72,   72
-    },
-
-    {
-       33,   74,   74,   74,   74,   74,   74,   74,   74,   74,
-       34,   74,   74,   74,   74,   74,   74,   74,   74,   74,
-       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
-       74,   74,   75,   74,   74,   74,   74,   74,   74,   74,
-       74,   74,   74,   74,   74,   74,   74,   76,   74,   74,
-
-       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
-       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
-       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
-       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
-       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
-       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
-       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
-       74,   74,   74,   74,   74,   74,   74,   74
-    },
-
-    {
-       33,   74,   74,   74,   74,   74,   74,   74,   74,   74,
-       34,   74,   74,   74,   74,   74,   74,   74,   74,   74,
-
-       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
-       74,   74,   75,   74,   74,   74,   74,   74,   74,   74,
-       74,   74,   74,   74,   74,   74,   74,   76,   74,   74,
-       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
-       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
-       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
-       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
-       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
-       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
-       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
-
-       74,   74,   74,   74,   74,   74,   74,   74
-    },
-
-    {
-       33,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       34,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77
-    },
-
-    {
-       33,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       34,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77
-    },
-
-    {
-       33,   78,   78,   78,   78,   78,   78,   78,   78,   78,
-       34,   78,   78,   78,   78,   78,   78,   78,   78,   78,
-       78,   78,   78,   78,   78,   78,   78,   78,   78,   78,
-
-       78,   78,   78,   78,   78,   78,   78,   78,   78,   78,
-       78,   78,   78,   78,   78,   78,   78,   78,   78,   78,
-       78,   78,   78,   78,   78,   78,   78,   78,   78,   78,
-       78,   78,   78,   78,   78,   78,   78,   78,   78,   78,
-       78,   78,   78,   78,   78,   78,   78,   78,   78,   78,
-       78,   78,   78,   78,   78,   78,   78,   78,   78,   78,
-       78,   78,   78,   78,   78,   78,   78,   78,   78,   78,
-       78,   78,   78,   78,   78,   78,   78,   78,   78,   78,
-       78,   78,   78,   78,   78,   78,   78,   78,   78,   78,
-       78,   78,   78,   78,   78,   78,   78,   78
-
-    },
-
-    {
-       33,   78,   78,   78,   78,   78,   78,   78,   78,   78,
-       34,   78,   78,   78,   78,   78,   78,   78,   78,   78,
-       78,   78,   78,   78,   78,   78,   78,   78,   78,   78,
-       78,   78,   78,   78,   78,   78,   78,   78,   78,   78,
-       78,   78,   78,   78,   78,   78,   78,   78,   78,   78,
-       78,   78,   78,   78,   78,   78,   78,   78,   78,   78,
-       78,   78,   78,   78,   78,   78,   78,   78,   78,   78,
-       78,   78,   78,   78,   78,   78,   78,   78,   78,   78,
-       78,   78,   78,   78,   78,   78,   78,   78,   78,   78,
-       78,   78,   78,   78,   78,   78,   78,   78,   78,   78,
-
-       78,   78,   78,   78,   78,   78,   78,   78,   78,   78,
-       78,   78,   78,   78,   78,   78,   78,   78,   78,   78,
-       78,   78,   78,   78,   78,   78,   78,   78
-    },
-
-    {
-       33,   79,   79,   79,   79,   79,   79,   79,   79,   79,
-       80,   79,   79,   79,   79,   79,   79,   79,   79,   79,
-       79,   79,   79,   79,   79,   79,   79,   79,   79,   79,
-       79,   79,   79,   79,   79,   79,   79,   79,   79,   79,
-       79,   79,   79,   79,   79,   79,   79,   79,   79,   79,
-       79,   79,   79,   79,   79,   79,   79,   79,   79,   79,
-       79,   79,   79,   79,   79,   79,   79,   79,   79,   79,
-
-       79,   79,   79,   79,   79,   79,   79,   79,   79,   79,
-       79,   79,   79,   79,   79,   79,   79,   79,   79,   79,
-       79,   79,   79,   79,   79,   79,   79,   79,   79,   79,
-       79,   79,   79,   79,   79,   79,   79,   79,   79,   79,
-       79,   79,   79,   79,   79,   79,   79,   79,   79,   79,
-       79,   79,   79,   79,   79,   79,   79,   79
-    },
-
-    {
-       33,   79,   79,   79,   79,   79,   79,   79,   79,   79,
-       80,   79,   79,   79,   79,   79,   79,   79,   79,   79,
-       79,   79,   79,   79,   79,   79,   79,   79,   79,   79,
-       79,   79,   79,   79,   79,   79,   79,   79,   79,   79,
-
-       79,   79,   79,   79,   79,   79,   79,   79,   79,   79,
-       79,   79,   79,   79,   79,   79,   79,   79,   79,   79,
-       79,   79,   79,   79,   79,   79,   79,   79,   79,   79,
-       79,   79,   79,   79,   79,   79,   79,   79,   79,   79,
-       79,   79,   79,   79,   79,   79,   79,   79,   79,   79,
-       79,   79,   79,   79,   79,   79,   79,   79,   79,   79,
-       79,   79,   79,   79,   79,   79,   79,   79,   79,   79,
-       79,   79,   79,   79,   79,   79,   79,   79,   79,   79,
-       79,   79,   79,   79,   79,   79,   79,   79
-    },
-
-    {
-      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
-
-      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
-      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
-      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
-      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
-      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
-      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
-      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
-      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
-      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
-      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
-
-      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
-      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33
-    },
-
-    {
-       33,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34
-    },
-
-    {
-       33,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
-      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
-      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
-      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
-      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
-
-      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
-      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
-      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
-      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
-      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
-      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
-      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
-      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35
-    },
-
-    {
-       33,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
-      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
-
-      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
-      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
-      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
-      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
-      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,   81,  -36,
-      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,   82,  -36,
-      -36,  -36,   83,   84,   85,   86,  -36,  -36,  -36,  -36,
-      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
-      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
-      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
-
-      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36
-    },
-
-    {
-       33,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
-      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
-      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
-      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
-      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
-      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
-      -37,  -37,  -37,  -37,  -37,   87,  -37,  -37,  -37,  -37,
-      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
-      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
-
-      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
-      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
-      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
-      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37
-    },
-
-    {
-       33,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
-      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
-      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
-      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
-      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
-      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
-
-      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
-      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,   88,  -38,
-       89,   90,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
-      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
-      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
-      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
-      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38
-    },
-
-    {
-       33,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
-      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
-      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
-
-      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
-      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
-      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
-      -39,  -39,  -39,  -39,  -39,   91,  -39,  -39,  -39,  -39,
-      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,   92,
-      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
-      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
-      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
-      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
-      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39
-
-    },
-
-    {
-       33,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
-      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
-      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
-      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
-      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
-      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
-      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
-      -40,  -40,  -40,  -40,   93,  -40,  -40,  -40,  -40,  -40,
-      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
-      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
-
-      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
-      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
-      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40
-    },
-
-    {
-       33,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,
-      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,
-      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,
-      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,
-      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,
-      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,
-      -41,  -41,  -41,  -41,  -41,   94,  -41,  -41,  -41,  -41,
-
-      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,
-      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,
-      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,
-      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,
-      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,
-      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41
-    },
-
-    {
-       33,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
-      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
-      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
-      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
-
-      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
-      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
-      -42,  -42,  -42,  -42,  -42,  -42,   95,  -42,  -42,  -42,
-      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
-      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
-      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
-      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
-      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
-      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42
-    },
-
-    {
-       33,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
-
-      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
-      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
-      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
-      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
-      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
-      -43,  -43,  -43,  -43,  -43,  -43,  -43,   96,  -43,  -43,
-      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
-      -43,  -43,   97,   98,  -43,  -43,   99,  -43,  -43,  -43,
-      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
-      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
-
-      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
-      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43
-    },
-
-    {
-       33,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
-      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
-      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
-      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
-      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
-      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
-      -44,  -44,  -44,  -44,  -44,  100,  -44,  -44,  -44,  101,
-      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
-
-      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
-      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
-      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
-      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
-      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44
-    },
-
-    {
-       33,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
-      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
-      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
-      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
-      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
-
-      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
-      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
-      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
-      102,  -45,  -45,  103,  -45,  -45,  -45,  -45,  -45,  -45,
-      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
-      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
-      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
-      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45
-    },
-
-    {
-       33,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
-      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
-
-      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
-      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
-      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
-      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
-      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  104,
-      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
-      -46,  -46,  -46,  105,  -46,  -46,  -46,  -46,  -46,  -46,
-      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
-      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
-      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
-
-      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46
-    },
-
-    {
-       33,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
-      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
-      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
-      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
-      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
-      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
-      -47,  -47,  -47,  -47,  -47,  -47,  -47,  106,  -47,  -47,
-      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
-      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
-
-      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
-      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
-      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
-      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47
-    },
-
-    {
-       33,  -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,  107,  -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,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
-      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
-      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
-
-      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
-      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
-      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
-      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
-      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
-      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
-      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
-      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
-      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
-      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49
-
-    },
-
-    {
-       33,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
-      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
-      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
-      -50,  -50,  108,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
-      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  109,  109,
-      109,  109,  109,  109,  109,  109,  109,  109,  -50,  -50,
-      -50,  -50,  -50,  -50,  -50,  108,  108,  108,  108,  108,
-      108,  108,  108,  108,  108,  108,  108,  108,  108,  108,
-      108,  108,  108,  108,  108,  108,  108,  108,  108,  108,
-      108,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
-
-      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
-      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
-      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50
-    },
-
-    {
-       33,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51
-    },
-
-    {
-       33,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
-      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
-      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
-      -52,  -52,  110,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
-
-      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
-      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
-      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
-      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
-      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
-      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
-      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
-      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
-      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52
-    },
-
-    {
-       33,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
-
-      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
-      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
-      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
-      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
-      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
-      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
-      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
-      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
-      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
-      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
-
-      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
-      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53
-    },
-
-    {
-       33,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
-      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
-      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
-      -54,  -54,  111,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
-      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  112,  112,
-      112,  112,  112,  112,  112,  112,  112,  112,  -54,  -54,
-      -54,  -54,  -54,  -54,  -54,  111,  111,  111,  111,  111,
-      111,  111,  111,  111,  111,  111,  111,  111,  111,  111,
-
-      111,  111,  111,  111,  111,  111,  111,  111,  111,  111,
-      111,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
-      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
-      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
-      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54
-    },
-
-    {
-       33,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
-      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
-      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
-      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
-      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
-
-      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
-      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
-      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
-      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
-      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
-      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
-      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
-      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55
-    },
-
-    {
-       33,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
-      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
-
-      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
-      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
-      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  -56,  -56,
-      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
-      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
-      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
-      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
-      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
-      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
-
-      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56
-    },
-
-    {
-       33,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
-      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
-      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
-      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
-      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  114,  114,
-      114,  114,  114,  114,  114,  114,  114,  114,  -57,  -57,
-      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
-      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
-      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
-
-      -57,  -57,  -57,  -57,  -57,  115,  -57,  -57,  -57,  -57,
-      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
-      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
-      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57
-    },
-
-    {
-       33,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
-      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
-      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
-      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
-      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
-      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
-
-      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
-      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
-      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
-      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
-      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
-      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
-      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58
-    },
-
-    {
-       33,  -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,  -59,  -59,
-      -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  116,  116,
-      116,  116,  116,  116,  116,  116,  116,  116,  -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,  117,  -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
-
-    },
-
-    {
-       33,  -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,
-      -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,  -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
-    },
-
-    {
-       33,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
-      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
-      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
-      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
-      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
-      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
-      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
-
-      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
-      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
-      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
-      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
-      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
-      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61
-    },
-
-    {
-       33,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
-      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
-      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
-      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
-
-      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
-      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
-      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
-      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
-      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
-      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
-      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
-      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
-      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62
-    },
-
-    {
-       33,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
-
-      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
-      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
-      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
-      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
-      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
-      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
-      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
-      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
-      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
-      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
-
-      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
-      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63
-    },
-
-    {
-       33,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
-      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
-      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
-      -64,  -64,  118,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
-      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
-      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
-      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
-      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
-
-      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
-      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
-      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
-      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
-      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64
-    },
-
-    {
-       33,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
-      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
-      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
-      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
-      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
-
-      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
-      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
-      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
-      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
-      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
-      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
-      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
-      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65
-    },
-
-    {
-       33,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
-      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
-
-      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
-      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
-      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  119,  119,
-      119,  119,  119,  119,  119,  119,  119,  119,  -66,  -66,
-      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
-      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
-      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
-      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
-      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
-      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
-
-      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66
-    },
-
-    {
-       33,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  119,  119,
-      119,  119,  119,  119,  119,  119,  119,  119,  -67,  -67,
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67
-    },
-
-    {
-       33,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-
-      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68
-    },
-
-    {
-       33,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-
-      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-      -69,  -69,  -69,  -69,  -69,  -69,  120,  -69,  121,  121,
-      121,  121,  121,  121,  121,  121,  121,  121,  -69,  -69,
-      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69
-
-    },
-
-    {
-       33,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
-      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
-      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
-      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
-      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  122,  122,
-      122,  122,  122,  122,  122,  122,  122,  122,  -70,  -70,
-      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
-      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
-      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
-      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
-
-      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
-      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
-      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70
-    },
-
-    {
-       33,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
-      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
-      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
-      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
-      -71,  -71,  -71,  -71,  -71,  -71,  123,  -71,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124,  -71,  -71,
-      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  125,
-
-      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
-      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
-      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
-      -71,  125,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
-      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
-      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71
-    },
-
-    {
-       33,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
-      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
-      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
-      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
-
-      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
-      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
-      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
-      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
-      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
-      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
-      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
-      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
-      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72
-    },
-
-    {
-       33,  126,  126,  126,  126,  126,  126,  126,  126,  126,
-
-      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
-      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
-      126,  126,  126,  126,  126,  126,  126,  126,  126,  127,
-      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
-      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
-      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
-      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
-      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
-      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
-      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
-
-      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
-      126,  126,  126,  126,  126,  126,  126,  126
-    },
-
-    {
-       33,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
-      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
-      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
-      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
-      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
-      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
-      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
-      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
-
-      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
-      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
-      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
-      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
-      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74
-    },
-
-    {
-       33,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
-      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
-      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
-      -75,  -75,  128,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
-      -75,  -75,  -75,  -75,  -75,  -75,  -75,  129,  -75,  -75,
-
-      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
-      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
-      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
-      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
-      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
-      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
-      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
-      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75
-    },
-
-    {
-       33,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-      -76,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-
-      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-
-      130,  130,  130,  130,  130,  130,  130,  130
-    },
-
-    {
-       33,  131,  131,  131,  131,  131,  131,  131,  131,  131,
-      -77,  131,  131,  131,  131,  131,  131,  131,  131,  131,
-      131,  131,  131,  131,  131,  131,  131,  131,  131,  131,
-      131,  131,  131,  131,  131,  131,  131,  131,  131,  131,
-      131,  131,  131,  131,  131,  131,  131,  131,  131,  131,
-      131,  131,  131,  131,  131,  131,  131,  131,  131,  131,
-      131,  131,  131,  131,  131,  131,  131,  131,  131,  131,
-      131,  131,  131,  131,  131,  131,  131,  131,  131,  131,
-      131,  131,  131,  131,  131,  131,  131,  131,  131,  131,
-
-      131,  131,  131,  131,  131,  131,  131,  131,  131,  131,
-      131,  131,  131,  131,  131,  131,  131,  131,  131,  131,
-      131,  131,  131,  131,  131,  131,  131,  131,  131,  131,
-      131,  131,  131,  131,  131,  131,  131,  131
-    },
-
-    {
-       33,  132,  132,  132,  132,  132,  132,  132,  132,  132,
-      -78,  132,  132,  132,  132,  132,  132,  132,  132,  132,
-      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
-      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
-      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
-      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
-
-      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
-      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
-      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
-      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
-      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
-      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
-      132,  132,  132,  132,  132,  132,  132,  132
-    },
-
-    {
-       33,  133,  133,  133,  133,  133,  133,  133,  133,  133,
-      134,  133,  133,  133,  133,  133,  133,  133,  133,  133,
-      133,  133,  133,  133,  133,  133,  133,  133,  133,  133,
-
-      133,  133,  133,  133,  133,  133,  133,  133,  133,  133,
-      133,  133,  133,  133,  133,  133,  133,  133,  133,  133,
-      133,  133,  133,  133,  133,  133,  133,  133,  133,  133,
-      133,  133,  133,  133,  133,  133,  133,  133,  133,  133,
-      133,  133,  133,  133,  133,  133,  133,  133,  133,  133,
-      133,  133,  133,  133,  133,  133,  133,  133,  133,  133,
-      133,  133,  133,  133,  133,  133,  133,  133,  133,  133,
-      133,  133,  133,  133,  133,  133,  133,  133,  133,  133,
-      133,  133,  133,  133,  133,  133,  133,  133,  133,  133,
-      133,  133,  133,  133,  133,  133,  133,  133
-
-    },
-
-    {
-       33,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
-      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
-      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
-      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
-      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
-      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
-      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
-      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
-      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
-      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
-
-      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
-      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
-      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80
-    },
-
-    {
-       33,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
-      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
-      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
-      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
-      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
-      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
-      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  135,
-
-      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
-      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
-      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
-      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
-      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
-      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81
-    },
-
-    {
-       33,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
-      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
-      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
-      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
-
-      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
-      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
-      -82,  -82,  -82,  -82,  -82,  136,  -82,  -82,  -82,  -82,
-      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
-      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
-      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
-      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
-      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
-      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82
-    },
-
-    {
-       33,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
-
-      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
-      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
-      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
-      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
-      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
-      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  137,  -83,
-      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  138,
-      139,  -83,  -83,  -83,  -83,  -83,  140,  -83,  -83,  -83,
-      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
-      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
-
-      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
-      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83
-    },
-
-    {
-       33,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
-      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
-      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
-      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
-      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
-      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
-      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
-      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
-
-      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  141,
-      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
-      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
-      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
-      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84
-    },
-
-    {
-       33,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
-      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
-      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
-      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
-      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
-
-      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
-      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
-      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
-      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  142,
-      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
-      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
-      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
-      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85
-    },
-
-    {
-       33,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
-      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
-
-      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
-      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
-      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
-      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
-      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
-      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  143,  -86,
-      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
-      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
-      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
-      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
-
-      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86
-    },
-
-    {
-       33,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-      -87,  -87,  -87,  -87,  144,  -87,  -87,  -87,  -87,  -87,
-
-      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87
-    },
-
-    {
-       33,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
-      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
-      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
-      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
-      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
-      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
-
-      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  145,  -88,
-      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
-      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
-      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
-      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
-      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
-      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88
-    },
-
-    {
-       33,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-
-      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  146,
-      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89
-
-    },
-
-    {
-       33,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
-      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
-      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
-      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
-      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
-      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
-      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
-      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
-      -90,  -90,  -90,  -90,  -90,  147,  -90,  -90,  -90,  -90,
-      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
-
-      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
-      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
-      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90
-    },
-
-    {
-       33,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
-      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
-      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
-      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
-      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
-      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
-      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
-
-      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
-      -91,  -91,  -91,  -91,  148,  -91,  -91,  -91,  -91,  -91,
-      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
-      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
-      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
-      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91
-    },
-
-    {
-       33,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
-      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
-      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
-      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
-
-      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
-      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
-      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
-      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  149,  -92,
-      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
-      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
-      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
-      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
-      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92
-    },
-
-    {
-       33,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-
-      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  150,  -93,
-      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-
-      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93
-    },
-
-    {
-       33,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
-      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
-      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
-      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
-      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
-      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
-      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
-      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
-
-      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  151,  -94,
-      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
-      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
-      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
-      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94
-    },
-
-    {
-       33,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
-      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
-      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
-      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
-      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
-
-      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
-      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
-      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
-      -95,  -95,  -95,  152,  -95,  -95,  -95,  -95,  -95,  -95,
-      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
-      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
-      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
-      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95
-    },
-
-    {
-       33,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
-      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
-
-      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
-      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
-      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
-      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
-      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
-      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
-      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
-      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
-      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
-      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
-
-      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96
-    },
-
-    {
-       33,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
-      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
-      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
-      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
-      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
-      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
-      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
-      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  153,
-      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
-
-      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
-      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
-      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
-      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97
-    },
-
-    {
-       33,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
-      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
-      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
-      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
-      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
-      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
-
-      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
-      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
-      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
-      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
-      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
-      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
-      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98
-    },
-
-    {
-       33,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-
-      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99
-
-    },
-
-    {
-       33, -100, -100, -100, -100, -100, -100, -100, -100, -100,
-     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
-     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
-     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
-     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
-     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
-     -100, -100, -100, -100, -100, -100, -100, -100,  154, -100,
-     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
-     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
-     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
-
-     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
-     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
-     -100, -100, -100, -100, -100, -100, -100, -100
-    },
-
-    {
-       33, -101, -101, -101, -101, -101, -101, -101, -101, -101,
-     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
-     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
-     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
-     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
-     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
-     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
-
-     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
-     -101, -101, -101,  155, -101, -101, -101, -101, -101, -101,
-     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
-     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
-     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
-     -101, -101, -101, -101, -101, -101, -101, -101
-    },
-
-    {
-       33, -102, -102, -102, -102, -102, -102, -102, -102, -102,
-     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
-     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
-     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
-
-     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
-     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
-     -102, -102, -102, -102, -102, -102, -102, -102, -102,  156,
-     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
-     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
-     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
-     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
-     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
-     -102, -102, -102, -102, -102, -102, -102, -102
-    },
-
-    {
-       33, -103, -103, -103, -103, -103, -103, -103, -103, -103,
-
-     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
-     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
-     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
-     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
-     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
-     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
-     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
-     -103, -103, -103, -103, -103, -103, -103, -103, -103,  157,
-     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
-     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
-
-     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
-     -103, -103, -103, -103, -103, -103, -103, -103
-    },
-
-    {
-       33, -104, -104, -104, -104, -104, -104, -104, -104, -104,
-     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
-     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
-     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
-     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
-     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
-     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
-     -104, -104, -104, -104, -104, -104,  158, -104, -104, -104,
-
-     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
-     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
-     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
-     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
-     -104, -104, -104, -104, -104, -104, -104, -104
-    },
-
-    {
-       33, -105, -105, -105, -105, -105, -105, -105, -105, -105,
-     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
-     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
-     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
-     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
-
-     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
-     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
-     -105, -105, -105, -105, -105, -105, -105, -105, -105,  159,
-     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
-     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
-     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
-     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
-     -105, -105, -105, -105, -105, -105, -105, -105
-    },
-
-    {
-       33, -106, -106, -106, -106, -106, -106, -106, -106, -106,
-     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
-
-     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
-     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
-     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
-     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
-     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
-     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
-     -106, -106, -106,  160, -106, -106, -106, -106, -106, -106,
-     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
-     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
-     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
-
-     -106, -106, -106, -106, -106, -106, -106, -106
-    },
-
-    {
-       33, -107, -107, -107, -107, -107, -107, -107, -107, -107,
-     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
-     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
-     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
-     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
-     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
-     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
-     -107, -107, -107, -107, -107, -107, -107, -107, -107,  161,
-     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
-
-     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
-     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
-     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
-     -107, -107, -107, -107, -107, -107, -107, -107
-    },
-
-    {
-       33, -108, -108, -108, -108, -108, -108, -108, -108, -108,
-     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
-     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
-     -108, -108,  162, -108, -108, -108, -108, -108, -108, -108,
-     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
-     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
-
-     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
-     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
-     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
-     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
-     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
-     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
-     -108, -108, -108, -108, -108, -108, -108, -108
-    },
-
-    {
-       33, -109, -109, -109, -109, -109, -109, -109, -109, -109,
-     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
-     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
-
-     -109, -109,  163, -109, -109, -109, -109, -109, -109, -109,
-     -109, -109, -109, -109, -109, -109, -109, -109,  164,  164,
-      164,  164,  164,  164,  164,  164,  164,  164, -109, -109,
-     -109, -109, -109, -109, -109,  163,  163,  163,  163,  163,
-      163,  163,  163,  163,  163,  163,  163,  163,  163,  163,
-      163,  163,  163,  163,  163,  163,  163,  163,  163,  163,
-      163, -109, -109, -109, -109, -109, -109, -109, -109, -109,
-     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
-     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
-     -109, -109, -109, -109, -109, -109, -109, -109
-
-    },
-
-    {
-       33, -110, -110, -110, -110, -110, -110, -110, -110, -110,
-     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
-     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
-     -110, -110,  165, -110, -110, -110, -110, -110, -110, -110,
-     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
-     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
-     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
-     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
-     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
-     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
-
-     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
-     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
-     -110, -110, -110, -110, -110, -110, -110, -110
-    },
-
-    {
-       33, -111, -111, -111, -111, -111, -111, -111, -111, -111,
-     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
-     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
-     -111, -111,  166, -111, -111, -111, -111, -111, -111, -111,
-     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
-     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
-     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
-
-     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
-     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
-     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
-     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
-     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
-     -111, -111, -111, -111, -111, -111, -111, -111
-    },
-
-    {
-       33, -112, -112, -112, -112, -112, -112, -112, -112, -112,
-     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
-     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
-     -112, -112,  167, -112, -112, -112, -112, -112, -112, -112,
-
-     -112, -112, -112, -112, -112, -112, -112, -112,  168,  168,
-      168,  168,  168,  168,  168,  168,  168,  168, -112, -112,
-     -112, -112, -112, -112, -112,  167,  167,  167,  167,  167,
-      167,  167,  167,  167,  167,  167,  167,  167,  167,  167,
-      167,  167,  167,  167,  167,  167,  167,  167,  167,  167,
-      167, -112, -112, -112, -112, -112, -112, -112, -112, -112,
-     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
-     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
-     -112, -112, -112, -112, -112, -112, -112, -112
-    },
-
-    {
-       33, -113, -113, -113, -113, -113, -113, -113, -113, -113,
-
-     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
-     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
-     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
-     -113, -113, -113, -113, -113, -113, -113, -113,  169,  169,
-      169,  169,  169,  169,  169,  169,  169,  169, -113, -113,
-     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
-     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
-     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
-     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
-     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
-
-     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
-     -113, -113, -113, -113, -113, -113, -113, -113
-    },
-
-    {
-       33, -114, -114, -114, -114, -114, -114, -114, -114, -114,
-     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
-     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
-     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
-     -114, -114, -114, -114, -114, -114, -114, -114,  170,  170,
-      170,  170,  170,  170,  170,  170,  170,  170, -114, -114,
-     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
-     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
-
-     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
-     -114, -114, -114, -114, -114,  171, -114, -114, -114, -114,
-     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
-     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
-     -114, -114, -114, -114, -114, -114, -114, -114
-    },
-
-    {
-       33, -115, -115, -115, -115, -115, -115, -115, -115, -115,
-     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
-     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
-     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
-     -115, -115, -115, -115, -115, -115, -115, -115, -115,  172,
-
-      172,  172,  172,  172,  172,  172,  172,  172, -115, -115,
-     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
-     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
-     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
-     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
-     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
-     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
-     -115, -115, -115, -115, -115, -115, -115, -115
-    },
-
-    {
-       33, -116, -116, -116, -116, -116, -116, -116, -116, -116,
-     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
-
-     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
-     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
-     -116, -116, -116, -116, -116, -116, -116, -116,  173,  173,
-      173,  173,  173,  173,  173,  173,  173,  173, -116, -116,
-     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
-     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
-     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
-     -116, -116, -116, -116, -116,  174, -116, -116, -116, -116,
-     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
-     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
-
-     -116, -116, -116, -116, -116, -116, -116, -116
-    },
-
-    {
-       33, -117, -117, -117, -117, -117, -117, -117, -117, -117,
-     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
-     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
-     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
-     -117, -117, -117, -117, -117, -117, -117, -117,  175,  176,
-      176,  176,  176,  176,  176,  176,  176,  176, -117, -117,
-     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
-     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
-     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
-
-     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
-     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
-     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
-     -117, -117, -117, -117, -117, -117, -117, -117
-    },
-
-    {
-       33, -118, -118, -118, -118, -118, -118, -118, -118, -118,
-     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
-     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
-     -118, -118,  118, -118, -118, -118, -118, -118, -118, -118,
-     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
-     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
-
-     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
-     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
-     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
-     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
-     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
-     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
-     -118, -118, -118, -118, -118, -118, -118, -118
-    },
-
-    {
-       33, -119, -119, -119, -119, -119, -119, -119, -119, -119,
-     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
-     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
-
-     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
-     -119, -119, -119, -119, -119, -119, -119, -119,  119,  119,
-      119,  119,  119,  119,  119,  119,  119,  119, -119, -119,
-     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
-     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
-     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
-     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
-     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
-     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
-     -119, -119, -119, -119, -119, -119, -119, -119
-
-    },
-
-    {
-       33, -120, -120, -120, -120, -120, -120, -120, -120, -120,
-     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
-     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
-     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
-     -120, -120, -120, -120, -120, -120, -120, -120,  122,  122,
-      122,  122,  122,  122,  122,  122,  122,  122, -120, -120,
-     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
-     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
-     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
-     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
-
-     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
-     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
-     -120, -120, -120, -120, -120, -120, -120, -120
-    },
-
-    {
-       33, -121, -121, -121, -121, -121, -121, -121, -121, -121,
-     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
-     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
-     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
-     -121, -121, -121, -121, -121, -121,  123, -121,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124, -121, -121,
-     -121, -121, -121, -121, -121, -121, -121, -121, -121,  125,
-
-     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
-     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
-     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
-     -121,  125, -121, -121, -121, -121, -121, -121, -121, -121,
-     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
-     -121, -121, -121, -121, -121, -121, -121, -121
-    },
-
-    {
-       33, -122, -122, -122, -122, -122, -122, -122, -122, -122,
-     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
-     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
-     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
-
-     -122, -122, -122, -122, -122, -122, -122, -122,  122,  122,
-      122,  122,  122,  122,  122,  122,  122,  122, -122, -122,
-     -122, -122, -122, -122, -122, -122, -122, -122, -122,  125,
-     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
-     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
-     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
-     -122,  125, -122, -122, -122, -122, -122, -122, -122, -122,
-     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
-     -122, -122, -122, -122, -122, -122, -122, -122
-    },
-
-    {
-       33, -123, -123, -123, -123, -123, -123, -123, -123, -123,
-
-     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
-     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
-     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
-     -123, -123, -123, -123, -123, -123, -123, -123,  177,  177,
-      177,  177,  177,  177,  177,  177,  177,  177, -123, -123,
-     -123, -123, -123, -123, -123, -123, -123, -123, -123,  125,
-     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
-     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
-     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
-     -123,  125, -123, -123, -123, -123, -123, -123, -123, -123,
-
-     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
-     -123, -123, -123, -123, -123, -123, -123, -123
-    },
-
-    {
-       33, -124, -124, -124, -124, -124, -124, -124, -124, -124,
-     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
-     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
-     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
-     -124, -124, -124, -124, -124, -124,  123, -124,  124,  124,
-      124,  124,  124,  124,  124,  124,  124,  124, -124, -124,
-     -124, -124, -124, -124, -124, -124, -124, -124, -124,  125,
-     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
-
-     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
-     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
-     -124,  125, -124, -124, -124, -124, -124, -124, -124, -124,
-     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
-     -124, -124, -124, -124, -124, -124, -124, -124
-    },
-
-    {
-       33, -125, -125, -125, -125, -125, -125, -125, -125, -125,
-     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
-     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
-     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
-     -125, -125, -125,  178, -125,  178, -125, -125,  179,  179,
-
-      179,  179,  179,  179,  179,  179,  179,  179, -125, -125,
-     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
-     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
-     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
-     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
-     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
-     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
-     -125, -125, -125, -125, -125, -125, -125, -125
-    },
-
-    {
-       33,  126,  126,  126,  126,  126,  126,  126,  126,  126,
-      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
-
-      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
-      126,  126,  126,  126,  126,  126,  126,  126,  126,  127,
-      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
-      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
-      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
-      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
-      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
-      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
-      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
-      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
-
-      126,  126,  126,  126,  126,  126,  126,  126
-    },
-
-    {
-       33, -127, -127, -127, -127, -127, -127, -127, -127, -127,
-     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
-     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
-     -127, -127, -127, -127, -127, -127, -127, -127, -127,  126,
-     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
-     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
-     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
-     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
-     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
-
-     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
-     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
-     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
-     -127, -127, -127, -127, -127, -127, -127, -127
-    },
-
-    {
-       33, -128, -128, -128, -128, -128, -128, -128, -128, -128,
-     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
-     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
-     -128, -128,  128, -128, -128, -128, -128, -128, -128, -128,
-     -128, -128, -128, -128, -128, -128, -128,  129, -128, -128,
-     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
-
-     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
-     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
-     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
-     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
-     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
-     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
-     -128, -128, -128, -128, -128, -128, -128, -128
-    },
-
-    {
-       33,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-     -129,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-
-      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-      130,  130,  130,  130,  130,  130,  130,  130
-
-    },
-
-    {
-       33,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-     -130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-
-      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-      130,  130,  130,  130,  130,  130,  130,  130
-    },
-
-    {
-       33,  131,  131,  131,  131,  131,  131,  131,  131,  131,
-     -131,  131,  131,  131,  131,  131,  131,  131,  131,  131,
-      131,  131,  131,  131,  131,  131,  131,  131,  131,  131,
-      131,  131,  131,  131,  131,  131,  131,  131,  131,  131,
-      131,  131,  131,  131,  131,  131,  131,  131,  131,  131,
-      131,  131,  131,  131,  131,  131,  131,  131,  131,  131,
-      131,  131,  131,  131,  131,  131,  131,  131,  131,  131,
-
-      131,  131,  131,  131,  131,  131,  131,  131,  131,  131,
-      131,  131,  131,  131,  131,  131,  131,  131,  131,  131,
-      131,  131,  131,  131,  131,  131,  131,  131,  131,  131,
-      131,  131,  131,  131,  131,  131,  131,  131,  131,  131,
-      131,  131,  131,  131,  131,  131,  131,  131,  131,  131,
-      131,  131,  131,  131,  131,  131,  131,  131
-    },
-
-    {
-       33,  132,  132,  132,  132,  132,  132,  132,  132,  132,
-     -132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
-      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
-      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
-
-      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
-      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
-      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
-      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
-      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
-      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
-      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
-      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
-      132,  132,  132,  132,  132,  132,  132,  132
-    },
-
-    {
-       33,  133,  133,  133,  133,  133,  133,  133,  133,  133,
-
-      134,  133,  133,  133,  133,  133,  133,  133,  133,  133,
-      133,  133,  133,  133,  133,  133,  133,  133,  133,  133,
-      133,  133,  133,  133,  133,  133,  133,  133,  133,  133,
-      133,  133,  133,  133,  133,  133,  133,  133,  133,  133,
-      133,  133,  133,  133,  133,  133,  133,  133,  133,  133,
-      133,  133,  133,  133,  133,  133,  133,  133,  133,  133,
-      133,  133,  133,  133,  133,  133,  133,  133,  133,  133,
-      133,  133,  133,  133,  133,  133,  133,  133,  133,  133,
-      133,  133,  133,  133,  133,  133,  133,  133,  133,  133,
-      133,  133,  133,  133,  133,  133,  133,  133,  133,  133,
-
-      133,  133,  133,  133,  133,  133,  133,  133,  133,  133,
-      133,  133,  133,  133,  133,  133,  133,  133
-    },
-
-    {
-       33, -134, -134, -134, -134, -134, -134, -134, -134, -134,
-     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
-     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
-     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
-     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
-     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
-     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
-     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
-
-     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
-     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
-     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
-     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
-     -134, -134, -134, -134, -134, -134, -134, -134
-    },
-
-    {
-       33, -135, -135, -135, -135, -135, -135, -135, -135, -135,
-     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
-     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
-     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
-     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
-
-     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
-     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
-     -135, -135, -135, -135, -135, -135,  180, -135, -135, -135,
-     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
-     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
-     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
-     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
-     -135, -135, -135, -135, -135, -135, -135, -135
-    },
-
-    {
-       33, -136, -136, -136, -136, -136, -136, -136, -136, -136,
-     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
-
-     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
-     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
-     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
-     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
-     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
-     -136, -136, -136, -136, -136, -136, -136,  181, -136, -136,
-     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
-     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
-     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
-     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
-
-     -136, -136, -136, -136, -136, -136, -136, -136
-    },
-
-    {
-       33, -137, -137, -137, -137, -137, -137, -137, -137, -137,
-     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
-     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
-     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
-     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
-     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
-     -137, -137, -137, -137, -137, -137, -137, -137, -137,  182,
-     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
-     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
-
-     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
-     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
-     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
-     -137, -137, -137, -137, -137, -137, -137, -137
-    },
-
-    {
-       33, -138, -138, -138, -138, -138, -138, -138, -138, -138,
-     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
-     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
-     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
-     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
-     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
-
-     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
-     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
-     -138, -138, -138, -138,  183, -138, -138, -138, -138, -138,
-     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
-     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
-     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
-     -138, -138, -138, -138, -138, -138, -138, -138
-    },
-
-    {
-       33, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-
-     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-     -139, -139, -139,  184, -139, -139, -139, -139, -139, -139,
-     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-     -139, -139, -139, -139, -139, -139, -139, -139
-
-    },
-
-    {
-       33, -140, -140, -140, -140, -140, -140, -140, -140, -140,
-     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
-     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
-     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
-     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
-     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
-     -140, -140, -140, -140, -140,  185, -140, -140, -140, -140,
-     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
-     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
-     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
-
-     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
-     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
-     -140, -140, -140, -140, -140, -140, -140, -140
-    },
-
-    {
-       33, -141, -141, -141, -141, -141, -141, -141, -141, -141,
-     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
-     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
-     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
-     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
-     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
-     -141, -141, -141, -141, -141, -141, -141, -141, -141,  186,
-
-     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
-     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
-     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
-     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
-     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
-     -141, -141, -141, -141, -141, -141, -141, -141
-    },
-
-    {
-       33, -142, -142, -142, -142, -142, -142, -142, -142, -142,
-     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
-     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
-     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
-
-     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
-     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
-     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
-     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
-      187, -142, -142, -142, -142, -142, -142, -142, -142, -142,
-     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
-     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
-     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
-     -142, -142, -142, -142, -142, -142, -142, -142
-    },
-
-    {
-       33, -143, -143, -143, -143, -143, -143, -143, -143, -143,
-
-     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
-     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
-     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
-     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
-     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
-     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
-     -143, -143, -143,  188, -143, -143, -143, -143, -143, -143,
-     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
-     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
-     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
-
-     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
-     -143, -143, -143, -143, -143, -143, -143, -143
-    },
-
-    {
-       33, -144, -144, -144, -144, -144, -144, -144, -144, -144,
-     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
-     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
-     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
-     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
-     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
-     -144, -144, -144, -144, -144, -144, -144, -144, -144,  189,
-     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
-
-     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
-     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
-     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
-     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
-     -144, -144, -144, -144, -144, -144, -144, -144
-    },
-
-    {
-       33, -145, -145, -145, -145, -145, -145, -145, -145, -145,
-     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
-     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
-     -145, -145,  190, -145, -145, -145, -145, -145, -145, -145,
-     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
-
-     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
-     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
-     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
-     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
-     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
-     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
-     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
-     -145, -145, -145, -145, -145, -145, -145, -145
-    },
-
-    {
-       33, -146, -146, -146, -146, -146, -146, -146, -146, -146,
-     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
-
-     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
-     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
-     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
-     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
-     -146, -146, -146, -146, -146, -146, -146,  191, -146, -146,
-     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
-     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
-     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
-     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
-     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
-
-     -146, -146, -146, -146, -146, -146, -146, -146
-    },
-
-    {
-       33, -147, -147, -147, -147, -147, -147, -147, -147, -147,
-     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
-     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
-     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
-     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
-     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
-     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
-     -147, -147, -147,  192, -147, -147, -147, -147, -147, -147,
-     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
-
-     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
-     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
-     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
-     -147, -147, -147, -147, -147, -147, -147, -147
-    },
-
-    {
-       33, -148, -148, -148, -148, -148, -148, -148, -148, -148,
-     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
-     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
-     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
-     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
-     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
-
-     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
-     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
-      193, -148, -148, -148, -148, -148, -148, -148, -148, -148,
-     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
-     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
-     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
-     -148, -148, -148, -148, -148, -148, -148, -148
-    },
-
-    {
-       33, -149, -149, -149, -149, -149, -149, -149, -149, -149,
-     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
-     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
-
-     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
-     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
-     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
-     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
-     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
-      194, -149, -149, -149, -149, -149, -149, -149, -149, -149,
-     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
-     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
-     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
-     -149, -149, -149, -149, -149, -149, -149, -149
-
-    },
-
-    {
-       33, -150, -150, -150, -150, -150, -150, -150, -150, -150,
-     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
-     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
-     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
-     -150, -150, -150, -150, -150,  195, -150, -150, -150, -150,
-     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
-     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
-     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
-     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
-     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
-
-     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
-     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
-     -150, -150, -150, -150, -150, -150, -150, -150
-    },
-
-    {
-       33, -151, -151, -151, -151, -151, -151, -151, -151, -151,
-     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
-     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
-     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
-     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
-     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
-     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
-
-     -151, -151, -151,  196, -151, -151, -151, -151, -151, -151,
-     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
-     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
-     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
-     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
-     -151, -151, -151, -151, -151, -151, -151, -151
-    },
-
-    {
-       33, -152, -152, -152, -152, -152, -152, -152, -152, -152,
-     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
-     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
-     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
-
-     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
-     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
-     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
-     -152,  197, -152, -152, -152, -152, -152, -152, -152, -152,
-     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
-     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
-     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
-     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
-     -152, -152, -152, -152, -152, -152, -152, -152
-    },
-
-    {
-       33, -153, -153, -153, -153, -153, -153, -153, -153, -153,
-
-     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
-     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
-     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
-     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
-     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
-     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
-     -153, -153, -153, -153,  198, -153, -153, -153, -153, -153,
-     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
-     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
-     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
-
-     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
-     -153, -153, -153, -153, -153, -153, -153, -153
-    },
-
-    {
-       33, -154, -154, -154, -154, -154, -154, -154, -154, -154,
-     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
-     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
-     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
-     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
-     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
-     -154, -154, -154, -154, -154, -154, -154, -154, -154,  199,
-     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
-
-     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
-     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
-     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
-     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
-     -154, -154, -154, -154, -154, -154, -154, -154
-    },
-
-    {
-       33, -155, -155, -155, -155, -155, -155, -155, -155, -155,
-     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
-     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
-     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
-     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
-
-     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
-     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
-     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
-     -155, -155, -155, -155,  200, -155, -155, -155, -155, -155,
-     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
-     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
-     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
-     -155, -155, -155, -155, -155, -155, -155, -155
-    },
-
-    {
-       33, -156, -156, -156, -156, -156, -156, -156, -156, -156,
-     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
-
-     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
-     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
-     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
-     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
-     -156, -156, -156, -156, -156, -156, -156,  201, -156, -156,
-     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
-     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
-     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
-     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
-     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
-
-     -156, -156, -156, -156, -156, -156, -156, -156
-    },
-
-    {
-       33, -157, -157, -157, -157, -157, -157, -157, -157, -157,
-     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
-     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
-     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
-     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
-     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
-     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
-     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
-     -157, -157, -157,  202, -157, -157, -157, -157, -157, -157,
-
-     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
-     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
-     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
-     -157, -157, -157, -157, -157, -157, -157, -157
-    },
-
-    {
-       33, -158, -158, -158, -158, -158, -158, -158, -158, -158,
-     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
-     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
-     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
-     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
-     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
-
-     -158, -158, -158, -158, -158,  203, -158, -158, -158, -158,
-     -158, -158, -158, -158, -158, -158, -158, -158, -158,  204,
-     -158, -158,  205, -158, -158, -158, -158, -158, -158, -158,
-     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
-     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
-     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
-     -158, -158, -158, -158, -158, -158, -158, -158
-    },
-
-    {
-       33, -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, -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,  206, -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
-
-    },
-
-    {
-       33, -160, -160, -160, -160, -160, -160, -160, -160, -160,
-     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
-     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
-     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
-     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
-     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
-     -160, -160, -160, -160, -160,  207, -160, -160, -160, -160,
-     -160, -160, -160, -160, -160, -160, -160, -160,  208, -160,
-     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
-     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
-
-     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
-     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
-     -160, -160, -160, -160, -160, -160, -160, -160
-    },
-
-    {
-       33, -161, -161, -161, -161, -161, -161, -161, -161, -161,
-     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
-     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
-     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
-     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
-     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
-     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
-
-     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
-     -161, -161, -161, -161, -161,  209, -161, -161, -161, -161,
-     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
-     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
-     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
-     -161, -161, -161, -161, -161, -161, -161, -161
-    },
-
-    {
-       33, -162, -162, -162, -162, -162, -162, -162, -162, -162,
-     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
-     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
-     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
-
-     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
-     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
-     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
-     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
-     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
-     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
-     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
-     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
-     -162, -162, -162, -162, -162, -162, -162, -162
-    },
-
-    {
-       33, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-
-     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-
-     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-     -163, -163, -163, -163, -163, -163, -163, -163
-    },
-
-    {
-       33, -164, -164, -164, -164, -164, -164, -164, -164, -164,
-     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
-     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
-     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
-     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
-     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
-     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
-     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
-
-     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
-     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
-     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
-     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
-     -164, -164, -164, -164, -164, -164, -164, -164
-    },
-
-    {
-       33, -165, -165, -165, -165, -165, -165, -165, -165, -165,
-     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
-     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
-     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
-     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
-
-     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
-     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
-     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
-     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
-     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
-     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
-     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
-     -165, -165, -165, -165, -165, -165, -165, -165
-    },
-
-    {
-       33, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-
-     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-
-     -166, -166, -166, -166, -166, -166, -166, -166
-    },
-
-    {
-       33, -167, -167, -167, -167, -167, -167, -167, -167, -167,
-     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
-     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
-     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
-     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
-     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
-     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
-     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
-     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
-
-     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
-     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
-     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
-     -167, -167, -167, -167, -167, -167, -167, -167
-    },
-
-    {
-       33, -168, -168, -168, -168, -168, -168, -168, -168, -168,
-     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
-     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
-     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
-     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
-     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
-
-     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
-     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
-     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
-     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
-     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
-     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
-     -168, -168, -168, -168, -168, -168, -168, -168
-    },
-
-    {
-       33, -169, -169, -169, -169, -169, -169, -169, -169, -169,
-     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
-     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
-
-     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
-     -169, -169, -169, -169, -169, -169, -169, -169,  210,  210,
-      210,  210,  210,  210,  210,  210,  210,  210, -169, -169,
-     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
-     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
-     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
-     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
-     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
-     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
-     -169, -169, -169, -169, -169, -169, -169, -169
-
-    },
-
-    {
-       33, -170, -170, -170, -170, -170, -170, -170, -170, -170,
-     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
-     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
-     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
-     -170, -170, -170, -170, -170, -170, -170, -170,  211,  211,
-      211,  211,  211,  211,  211,  211,  211,  211, -170, -170,
-     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
-     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
-     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
-     -170, -170, -170, -170, -170,  212, -170, -170, -170, -170,
-
-     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
-     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
-     -170, -170, -170, -170, -170, -170, -170, -170
-    },
-
-    {
-       33, -171, -171, -171, -171, -171, -171, -171, -171, -171,
-     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
-     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
-     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
-     -171, -171, -171, -171, -171, -171, -171, -171, -171,  213,
-      213,  213,  213,  213,  213,  213,  213,  213, -171, -171,
-     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
-
-     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
-     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
-     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
-     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
-     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
-     -171, -171, -171, -171, -171, -171, -171, -171
-    },
-
-    {
-       33, -172, -172, -172, -172, -172, -172, -172, -172, -172,
-     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
-     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
-     -172, -172,  214, -172, -172, -172, -172, -172, -172, -172,
-
-     -172, -172, -172, -172, -172, -172, -172, -172,  215,  215,
-      215,  215,  215,  215,  215,  215,  215,  215, -172, -172,
-     -172, -172, -172, -172, -172,  214,  214,  214,  214,  214,
-      214,  214,  214,  214,  214,  214,  214,  214,  214,  214,
-      214,  214,  214,  214,  214,  214,  214,  214,  214,  214,
-      214, -172, -172, -172, -172, -172, -172, -172, -172, -172,
-     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
-     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
-     -172, -172, -172, -172, -172, -172, -172, -172
-    },
-
-    {
-       33, -173, -173, -173, -173, -173, -173, -173, -173, -173,
-
-     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
-     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
-     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
-     -173, -173, -173, -173, -173, -173, -173, -173,  216,  216,
-      216,  216,  216,  216,  216,  216,  216,  216, -173, -173,
-     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
-     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
-     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
-     -173, -173, -173, -173, -173,  217, -173, -173, -173, -173,
-     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
-
-     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
-     -173, -173, -173, -173, -173, -173, -173, -173
-    },
-
-    {
-       33, -174, -174, -174, -174, -174, -174, -174, -174, -174,
-     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
-     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
-     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
-     -174, -174, -174, -174, -174, -174, -174, -174,  218,  219,
-      219,  219,  219,  219,  219,  219,  219,  219, -174, -174,
-     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
-     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
-
-     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
-     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
-     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
-     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
-     -174, -174, -174, -174, -174, -174, -174, -174
-    },
-
-    {
-       33, -175, -175, -175, -175, -175, -175, -175, -175, -175,
-     -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
-     -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
-     -175, -175,  220, -175, -175, -175, -175, -175, -175, -175,
-     -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
-
-     -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
-     -175, -175, -175, -175, -175,  220,  220,  220,  220,  220,
-      220,  220,  220,  220,  220,  220,  220,  220,  220,  220,
-      220,  220,  220,  220,  220,  220,  220,  220,  220,  220,
-      220, -175, -175, -175, -175, -175, -175, -175, -175, -175,
-     -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
-     -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
-     -175, -175, -175, -175, -175, -175, -175, -175
-    },
-
-    {
-       33, -176, -176, -176, -176, -176, -176, -176, -176, -176,
-     -176, -176, -176, -176, -176, -176, -176, -176, -176, -176,
-
-     -176, -176, -176, -176, -176, -176, -176, -176, -176, -176,
-     -176, -176,  220, -176, -176, -176, -176, -176, -176, -176,
-     -176, -176, -176, -176, -176, -176, -176, -176,  221,  221,
-      221,  221,  221,  221,  221,  221,  221,  221, -176, -176,
-     -176, -176, -176, -176, -176,  220,  220,  220,  220,  220,
-      220,  220,  220,  220,  220,  220,  220,  220,  220,  220,
-      220,  220,  220,  220,  220,  220,  220,  220,  220,  220,
-      220, -176, -176, -176, -176, -176, -176, -176, -176, -176,
-     -176, -176, -176, -176, -176, -176, -176, -176, -176, -176,
-     -176, -176, -176, -176, -176, -176, -176, -176, -176, -176,
-
-     -176, -176, -176, -176, -176, -176, -176, -176
-    },
-
-    {
-       33, -177, -177, -177, -177, -177, -177, -177, -177, -177,
-     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
-     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
-     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
-     -177, -177, -177, -177, -177, -177, -177, -177,  177,  177,
-      177,  177,  177,  177,  177,  177,  177,  177, -177, -177,
-     -177, -177, -177, -177, -177, -177, -177, -177, -177,  125,
-     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
-     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
-
-     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
-     -177,  125, -177, -177, -177, -177, -177, -177, -177, -177,
-     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
-     -177, -177, -177, -177, -177, -177, -177, -177
-    },
-
-    {
-       33, -178, -178, -178, -178, -178, -178, -178, -178, -178,
-     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
-     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
-     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
-     -178, -178, -178, -178, -178, -178, -178, -178,  179,  179,
-      179,  179,  179,  179,  179,  179,  179,  179, -178, -178,
-
-     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
-     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
-     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
-     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
-     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
-     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
-     -178, -178, -178, -178, -178, -178, -178, -178
-    },
-
-    {
-       33, -179, -179, -179, -179, -179, -179, -179, -179, -179,
-     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
-     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
-
-     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
-     -179, -179, -179, -179, -179, -179, -179, -179,  179,  179,
-      179,  179,  179,  179,  179,  179,  179,  179, -179, -179,
-     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
-     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
-     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
-     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
-     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
-     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
-     -179, -179, -179, -179, -179, -179, -179, -179
-
-    },
-
-    {
-       33, -180, -180, -180, -180, -180, -180, -180, -180, -180,
-     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
-     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
-     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
-     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
-     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
-     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
-     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
-     -180, -180, -180, -180,  222, -180, -180, -180, -180, -180,
-     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
-
-     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
-     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
-     -180, -180, -180, -180, -180, -180, -180, -180
-    },
-
-    {
-       33, -181, -181, -181, -181, -181, -181, -181, -181, -181,
-     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
-     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
-     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
-     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
-     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
-     -181, -181, -181, -181, -181, -181, -181, -181, -181,  223,
-
-     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
-     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
-     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
-     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
-     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
-     -181, -181, -181, -181, -181, -181, -181, -181
-    },
-
-    {
-       33, -182, -182, -182, -182, -182, -182, -182, -182, -182,
-     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
-     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
-     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
-
-     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
-     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
-     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
-     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
-     -182, -182,  224, -182, -182, -182, -182, -182, -182, -182,
-     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
-     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
-     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
-     -182, -182, -182, -182, -182, -182, -182, -182
-    },
-
-    {
-       33, -183, -183, -183, -183, -183, -183, -183, -183, -183,
-
-     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
-     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
-     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
-     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
-     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
-     -183, -183, -183, -183, -183,  225, -183, -183, -183, -183,
-     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
-     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
-     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
-     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
-
-     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
-     -183, -183, -183, -183, -183, -183, -183, -183
-    },
-
-    {
-       33, -184, -184, -184, -184, -184, -184, -184, -184, -184,
-     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
-     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
-     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
-     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
-     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
-     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
-     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
-
-     -184, -184, -184, -184, -184, -184, -184, -184,  226, -184,
-     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
-     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
-     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
-     -184, -184, -184, -184, -184, -184, -184, -184
-    },
-
-    {
-       33, -185, -185, -185, -185, -185, -185, -185, -185, -185,
-     -185, -185, -185, -185, -185, -185, -185, -185, -185, -185,
-     -185, -185, -185, -185, -185, -185, -185, -185, -185, -185,
-     -185, -185, -185, -185, -185, -185, -185, -185, -185, -185,
-     -185, -185, -185, -185, -185, -185, -185, -185, -185, -185,
-
-     -185, -185, -185, -185, -185, -185, -185, -185, -185, -185,
-     -185, -185, -185, -185, -185, -185, -185, -185, -185, -185,
-     -185, -185, -185, -185, -185, -185,  227, -185, -185, -185,
-     -185, -185, -185, -185, -185, -185, -185, -185, -185, -185,
-     -185, -185, -185, -185, -185, -185, -185, -185, -185, -185,
-     -185, -185, -185, -185, -185, -185, -185, -185, -185, -185,
-     -185, -185, -185, -185, -185, -185, -185, -185, -185, -185,
-     -185, -185, -185, -185, -185, -185, -185, -185
-    },
-
-    {
-       33, -186, -186, -186, -186, -186, -186, -186, -186, -186,
-     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
-
-     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
-     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
-     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
-     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
-     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
-     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
-     -186, -186,  228, -186, -186, -186, -186, -186, -186, -186,
-     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
-     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
-     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
-
-     -186, -186, -186, -186, -186, -186, -186, -186
-    },
-
-    {
-       33, -187, -187, -187, -187, -187, -187, -187, -187, -187,
-     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
-     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
-     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
-     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
-     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
-     -187, -187, -187, -187, -187, -187, -187, -187, -187,  229,
-     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
-     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
-
-     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
-     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
-     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
-     -187, -187, -187, -187, -187, -187, -187, -187
-    },
-
-    {
-       33, -188, -188, -188, -188, -188, -188, -188, -188, -188,
-     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
-     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
-     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
-     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
-     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
-
-     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
-     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
-     -188, -188, -188, -188,  230, -188, -188, -188, -188, -188,
-     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
-     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
-     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
-     -188, -188, -188, -188, -188, -188, -188, -188
-    },
-
-    {
-       33, -189, -189, -189, -189, -189, -189, -189, -189, -189,
-     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
-     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
-
-     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
-     -189, -189, -189, -189, -189,  231, -189, -189, -189, -189,
-     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
-     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
-     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
-     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
-     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
-     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
-     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
-     -189, -189, -189, -189, -189, -189, -189, -189
-
-    },
-
-    {
-       33, -190, -190, -190, -190, -190, -190, -190, -190, -190,
-     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
-     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
-     -190, -190,  232, -190, -190, -190, -190, -190, -190, -190,
-     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
-     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
-     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
-     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
-     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
-     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
-
-     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
-     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
-     -190, -190, -190, -190, -190, -190, -190, -190
-    },
-
-    {
-       33, -191, -191, -191, -191, -191, -191, -191, -191, -191,
-     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
-     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
-     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
-     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
-     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
-     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
-
-     -191, -191,  233, -191, -191, -191, -191, -191, -191, -191,
-     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
-     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
-     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
-     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
-     -191, -191, -191, -191, -191, -191, -191, -191
-    },
-
-    {
-       33, -192, -192, -192, -192, -192, -192, -192, -192, -192,
-     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
-     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
-     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
-
-     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
-     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
-     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
-     -192, -192, -192, -192, -192, -192, -192, -192,  234, -192,
-     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
-     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
-     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
-     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
-     -192, -192, -192, -192, -192, -192, -192, -192
-    },
-
-    {
-       33, -193, -193, -193, -193, -193, -193, -193, -193, -193,
-
-     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
-     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
-     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
-     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
-     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
-     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
-     -193, -193, -193, -193, -193, -193, -193, -193, -193,  235,
-     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
-     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
-     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
-
-     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
-     -193, -193, -193, -193, -193, -193, -193, -193
-    },
-
-    {
-       33, -194, -194, -194, -194, -194, -194, -194, -194, -194,
-     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
-     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
-     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
-     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
-     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
-     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
-     -194, -194, -194, -194, -194, -194, -194, -194, -194,  236,
-
-     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
-     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
-     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
-     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
-     -194, -194, -194, -194, -194, -194, -194, -194
-    },
-
-    {
-       33, -195, -195, -195, -195, -195, -195, -195, -195, -195,
-     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
-     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
-     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
-     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
-
-     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
-     -195, -195, -195, -195, -195,  237, -195, -195, -195, -195,
-     -195, -195, -195, -195, -195, -195, -195, -195, -195,  238,
-     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
-     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
-     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
-     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
-     -195, -195, -195, -195, -195, -195, -195, -195
-    },
-
-    {
-       33, -196, -196, -196, -196, -196, -196, -196, -196, -196,
-     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
-
-     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
-     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
-     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
-     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
-     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
-     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
-     -196, -196, -196,  239, -196, -196, -196, -196, -196, -196,
-     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
-     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
-     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
-
-     -196, -196, -196, -196, -196, -196, -196, -196
-    },
-
-    {
-       33, -197, -197, -197, -197, -197, -197, -197, -197, -197,
-     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
-     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
-     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
-     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
-     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
-     -197, -197, -197, -197, -197, -197, -197, -197, -197,  240,
-     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
-     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
-
-     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
-     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
-     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
-     -197, -197, -197, -197, -197, -197, -197, -197
-    },
-
-    {
-       33, -198, -198, -198, -198, -198, -198, -198, -198, -198,
-     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
-     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
-     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
-     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
-     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
-
-     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
-     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
-      241, -198, -198, -198, -198, -198, -198, -198, -198, -198,
-     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
-     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
-     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
-     -198, -198, -198, -198, -198, -198, -198, -198
-    },
-
-    {
-       33, -199, -199, -199, -199, -199, -199, -199, -199, -199,
-     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
-     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
-
-     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
-     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
-     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
-     -199, -199, -199, -199, -199, -199, -199,  242, -199, -199,
-     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
-     -199, -199, -199,  243, -199, -199, -199, -199, -199, -199,
-     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
-     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
-     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
-     -199, -199, -199, -199, -199, -199, -199, -199
-
-    },
-
-    {
-       33, -200, -200, -200, -200, -200, -200, -200, -200, -200,
-     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
-     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
-     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
-     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
-     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
-     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
-      244, -200, -200, -200, -200, -200, -200, -200, -200, -200,
-     -200, -200, -200, -200, -200, -200, -200,  245, -200, -200,
-     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
-
-     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
-     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
-     -200, -200, -200, -200, -200, -200, -200, -200
-    },
-
-    {
-       33, -201, -201, -201, -201, -201, -201, -201, -201, -201,
-     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
-     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
-     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
-     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
-     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
-     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
-
-     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
-     -201, -201, -201,  246, -201, -201, -201, -201, -201, -201,
-     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
-     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
-     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
-     -201, -201, -201, -201, -201, -201, -201, -201
-    },
-
-    {
-       33, -202, -202, -202, -202, -202, -202, -202, -202, -202,
-     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
-     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
-     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
-
-     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
-     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
-     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
-     -202, -202, -202, -202, -202, -202, -202, -202, -202,  247,
-     -202, -202, -202,  248, -202, -202, -202, -202, -202, -202,
-     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
-     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
-     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
-     -202, -202, -202, -202, -202, -202, -202, -202
-    },
-
-    {
-       33, -203, -203, -203, -203, -203, -203, -203, -203, -203,
-
-     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
-     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
-     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
-     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
-     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
-     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
-     -203, -203, -203, -203, -203, -203, -203, -203,  249, -203,
-     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
-     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
-     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
-
-     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
-     -203, -203, -203, -203, -203, -203, -203, -203
-    },
-
-    {
-       33, -204, -204, -204, -204, -204, -204, -204, -204, -204,
-     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
-     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
-     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
-     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
-     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
-     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
-     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
-
-     -204, -204, -204,  250, -204, -204, -204, -204, -204, -204,
-     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
-     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
-     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
-     -204, -204, -204, -204, -204, -204, -204, -204
-    },
-
-    {
-       33, -205, -205, -205, -205, -205, -205, -205, -205, -205,
-     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
-     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
-     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
-     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
-
-     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
-     -205, -205, -205, -205, -205, -205, -205, -205, -205,  251,
-     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
-     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
-     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
-     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
-     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
-     -205, -205, -205, -205, -205, -205, -205, -205
-    },
-
-    {
-       33, -206, -206, -206, -206, -206, -206, -206, -206, -206,
-     -206, -206, -206, -206, -206, -206, -206, -206, -206, -206,
-
-     -206, -206, -206, -206, -206, -206, -206, -206, -206, -206,
-     -206, -206, -206, -206, -206, -206, -206, -206, -206, -206,
-     -206, -206, -206, -206, -206, -206, -206, -206, -206, -206,
-     -206, -206, -206, -206, -206, -206, -206, -206, -206, -206,
-     -206, -206, -206, -206, -206, -206, -206, -206, -206, -206,
-     -206, -206, -206, -206, -206, -206, -206, -206, -206, -206,
-     -206, -206,  252, -206, -206, -206, -206, -206, -206, -206,
-     -206, -206, -206, -206, -206, -206, -206, -206, -206, -206,
-     -206, -206, -206, -206, -206, -206, -206, -206, -206, -206,
-     -206, -206, -206, -206, -206, -206, -206, -206, -206, -206,
-
-     -206, -206, -206, -206, -206, -206, -206, -206
-    },
-
-    {
-       33, -207, -207, -207, -207, -207, -207, -207, -207, -207,
-     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
-     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
-     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
-     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
-     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
-     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
-     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
-     -207, -207, -207, -207, -207, -207, -207, -207,  253, -207,
-
-     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
-     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
-     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
-     -207, -207, -207, -207, -207, -207, -207, -207
-    },
-
-    {
-       33, -208, -208, -208, -208, -208, -208, -208, -208, -208,
-     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
-     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
-     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
-     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
-     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
-
-     -208, -208, -208, -208, -208,  254, -208, -208, -208, -208,
-     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
-     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
-     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
-     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
-     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
-     -208, -208, -208, -208, -208, -208, -208, -208
-    },
-
-    {
-       33, -209, -209, -209, -209, -209, -209, -209, -209, -209,
-     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
-     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
-
-     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
-     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
-     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
-     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
-     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
-     -209, -209,  255, -209, -209, -209, -209, -209, -209, -209,
-     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
-     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
-     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
-     -209, -209, -209, -209, -209, -209, -209, -209
-
-    },
-
-    {
-       33, -210, -210, -210, -210, -210, -210, -210, -210, -210,
-     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
-     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
-     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
-     -210, -210, -210, -210, -210, -210, -210, -210,  256,  256,
-      256,  256,  256,  256,  256,  256,  256,  256, -210, -210,
-     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
-     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
-     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
-     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
-
-     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
-     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
-     -210, -210, -210, -210, -210, -210, -210, -210
-    },
-
-    {
-       33, -211, -211, -211, -211, -211, -211, -211, -211, -211,
-     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
-     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
-     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
-     -211, -211, -211, -211, -211, -211, -211, -211,  256,  256,
-      256,  256,  256,  256,  256,  256,  256,  256, -211, -211,
-     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
-
-     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
-     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
-     -211, -211, -211, -211, -211,  257, -211, -211, -211, -211,
-     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
-     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
-     -211, -211, -211, -211, -211, -211, -211, -211
-    },
-
-    {
-       33, -212, -212, -212, -212, -212, -212, -212, -212, -212,
-     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
-     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
-     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
-
-     -212, -212, -212, -212, -212, -212, -212, -212, -212,  258,
-      258,  258,  258,  258,  258,  258,  258,  258, -212, -212,
-     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
-     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
-     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
-     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
-     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
-     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
-     -212, -212, -212, -212, -212, -212, -212, -212
-    },
-
-    {
-       33, -213, -213, -213, -213, -213, -213, -213, -213, -213,
-
-     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
-     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
-     -213, -213,  259, -213, -213, -213, -213, -213, -213, -213,
-     -213, -213, -213, -213, -213, -213, -213, -213,  260,  260,
-      260,  260,  260,  260,  260,  260,  260,  260, -213, -213,
-     -213, -213, -213, -213, -213,  259,  259,  259,  259,  259,
-      259,  259,  259,  259,  259,  259,  259,  259,  259,  259,
-      259,  259,  259,  259,  259,  259,  259,  259,  259,  259,
-      259, -213, -213, -213, -213, -213, -213, -213, -213, -213,
-     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
-
-     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
-     -213, -213, -213, -213, -213, -213, -213, -213
-    },
-
-    {
-       33, -214, -214, -214, -214, -214, -214, -214, -214, -214,
-     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
-     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
-     -214, -214,  261, -214, -214, -214, -214, -214, -214, -214,
-     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
-     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
-     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
-     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
-
-     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
-     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
-     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
-     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
-     -214, -214, -214, -214, -214, -214, -214, -214
-    },
-
-    {
-       33, -215, -215, -215, -215, -215, -215, -215, -215, -215,
-     -215, -215, -215, -215, -215, -215, -215, -215, -215, -215,
-     -215, -215, -215, -215, -215, -215, -215, -215, -215, -215,
-     -215, -215,  262, -215, -215, -215, -215, -215, -215, -215,
-     -215, -215, -215, -215, -215, -215, -215, -215,  263,  263,
-
-      263,  263,  263,  263,  263,  263,  263,  263, -215, -215,
-     -215, -215, -215, -215, -215,  262,  262,  262,  262,  262,
-      262,  262,  262,  262,  262,  262,  262,  262,  262,  262,
-      262,  262,  262,  262,  262,  262,  262,  262,  262,  262,
-      262, -215, -215, -215, -215, -215, -215, -215, -215, -215,
-     -215, -215, -215, -215, -215, -215, -215, -215, -215, -215,
-     -215, -215, -215, -215, -215, -215, -215, -215, -215, -215,
-     -215, -215, -215, -215, -215, -215, -215, -215
-    },
-
-    {
-       33, -216, -216, -216, -216, -216, -216, -216, -216, -216,
-     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
-
-     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
-     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
-     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
-     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
-     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
-     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
-     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
-     -216, -216, -216, -216, -216,  264, -216, -216, -216, -216,
-     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
-     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
-
-     -216, -216, -216, -216, -216, -216, -216, -216
-    },
-
-    {
-       33, -217, -217, -217, -217, -217, -217, -217, -217, -217,
-     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
-     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
-     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
-     -217, -217, -217, -217, -217, -217, -217, -217,  265,  266,
-      266,  266,  266,  266,  266,  266,  266,  266, -217, -217,
-     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
-     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
-     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
-
-     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
-     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
-     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
-     -217, -217, -217, -217, -217, -217, -217, -217
-    },
-
-    {
-       33, -218, -218, -218, -218, -218, -218, -218, -218, -218,
-     -218, -218, -218, -218, -218, -218, -218, -218, -218, -218,
-     -218, -218, -218, -218, -218, -218, -218, -218, -218, -218,
-     -218, -218,  267, -218, -218, -218, -218, -218, -218, -218,
-     -218, -218, -218, -218, -218, -218, -218, -218, -218, -218,
-     -218, -218, -218, -218, -218, -218, -218, -218, -218, -218,
-
-     -218, -218, -218, -218, -218,  267,  267,  267,  267,  267,
-      267,  267,  267,  267,  267,  267,  267,  267,  267,  267,
-      267,  267,  267,  267,  267,  267,  267,  267,  267,  267,
-      267, -218, -218, -218, -218, -218, -218, -218, -218, -218,
-     -218, -218, -218, -218, -218, -218, -218, -218, -218, -218,
-     -218, -218, -218, -218, -218, -218, -218, -218, -218, -218,
-     -218, -218, -218, -218, -218, -218, -218, -218
-    },
-
-    {
-       33, -219, -219, -219, -219, -219, -219, -219, -219, -219,
-     -219, -219, -219, -219, -219, -219, -219, -219, -219, -219,
-     -219, -219, -219, -219, -219, -219, -219, -219, -219, -219,
-
-     -219, -219,  267, -219, -219, -219, -219, -219, -219, -219,
-     -219, -219, -219, -219, -219, -219, -219, -219,  268,  268,
-      268,  268,  268,  268,  268,  268,  268,  268, -219, -219,
-     -219, -219, -219, -219, -219,  267,  267,  267,  267,  267,
-      267,  267,  267,  267,  267,  267,  267,  267,  267,  267,
-      267,  267,  267,  267,  267,  267,  267,  267,  267,  267,
-      267, -219, -219, -219, -219, -219, -219, -219, -219, -219,
-     -219, -219, -219, -219, -219, -219, -219, -219, -219, -219,
-     -219, -219, -219, -219, -219, -219, -219, -219, -219, -219,
-     -219, -219, -219, -219, -219, -219, -219, -219
-
-    },
-
-    {
-       33, -220, -220, -220, -220, -220, -220, -220, -220, -220,
-     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
-     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
-     -220, -220,  269, -220, -220, -220, -220, -220, -220, -220,
-     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
-     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
-     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
-     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
-     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
-     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
-
-     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
-     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
-     -220, -220, -220, -220, -220, -220, -220, -220
-    },
-
-    {
-       33, -221, -221, -221, -221, -221, -221, -221, -221, -221,
-     -221, -221, -221, -221, -221, -221, -221, -221, -221, -221,
-     -221, -221, -221, -221, -221, -221, -221, -221, -221, -221,
-     -221, -221,  270, -221, -221, -221, -221, -221, -221, -221,
-     -221, -221, -221, -221, -221, -221, -221, -221,  271,  271,
-      271,  271,  271,  271,  271,  271,  271,  271, -221, -221,
-     -221, -221, -221, -221, -221,  270,  270,  270,  270,  270,
-
-      270,  270,  270,  270,  270,  270,  270,  270,  270,  270,
-      270,  270,  270,  270,  270,  270,  270,  270,  270,  270,
-      270, -221, -221, -221, -221, -221, -221, -221, -221, -221,
-     -221, -221, -221, -221, -221, -221, -221, -221, -221, -221,
-     -221, -221, -221, -221, -221, -221, -221, -221, -221, -221,
-     -221, -221, -221, -221, -221, -221, -221, -221
-    },
-
-    {
-       33, -222, -222, -222, -222, -222, -222, -222, -222, -222,
-     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
-     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
-     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
-
-     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
-     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
-     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
-     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
-     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
-     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
-     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
-     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
-     -222, -222, -222, -222, -222, -222, -222, -222
-    },
-
-    {
-       33, -223, -223, -223, -223, -223, -223, -223, -223, -223,
-
-     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
-     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
-     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
-     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
-     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
-     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
-     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
-     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
-     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
-     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
-
-     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
-     -223, -223, -223, -223, -223, -223, -223, -223
-    },
-
-    {
-       33, -224, -224, -224, -224, -224, -224, -224, -224, -224,
-     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
-     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
-     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
-     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
-     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
-     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
-     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
-
-     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
-     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
-     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
-     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
-     -224, -224, -224, -224, -224, -224, -224, -224
-    },
-
-    {
-       33, -225, -225, -225, -225, -225, -225, -225, -225, -225,
-     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
-     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
-     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
-     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
-
-     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
-     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
-     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
-     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
-     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
-     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
-     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
-     -225, -225, -225, -225, -225, -225, -225, -225
-    },
-
-    {
-       33, -226, -226, -226, -226, -226, -226, -226, -226, -226,
-     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
-
-     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
-     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
-     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
-     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
-     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
-     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
-     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
-     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
-     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
-     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
-
-     -226, -226, -226, -226, -226, -226, -226, -226
-    },
-
-    {
-       33, -227, -227, -227, -227, -227, -227, -227, -227, -227,
-     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
-     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
-     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
-     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
-     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
-     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
-     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
-     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
-
-     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
-     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
-     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
-     -227, -227, -227, -227, -227, -227, -227, -227
-    },
-
-    {
-       33, -228, -228, -228, -228, -228, -228, -228, -228, -228,
-     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
-     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
-     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
-     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
-     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
-
-     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
-     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
-     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
-     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
-     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
-     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
-     -228, -228, -228, -228, -228, -228, -228, -228
-    },
-
-    {
-       33, -229, -229, -229, -229, -229, -229, -229, -229, -229,
-     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
-     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
-
-     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
-     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
-     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
-     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
-     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
-     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
-     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
-     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
-     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
-     -229, -229, -229, -229, -229, -229, -229, -229
-
-    },
-
-    {
-       33, -230, -230, -230, -230, -230, -230, -230, -230, -230,
-     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
-     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
-     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
-     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
-     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
-     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
-     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
-     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
-     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
-
-     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
-     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
-     -230, -230, -230, -230, -230, -230, -230, -230
-    },
-
-    {
-       33, -231, -231, -231, -231, -231, -231, -231, -231, -231,
-     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
-     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
-     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
-     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
-     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
-     -231, -231, -231, -231, -231,  272, -231, -231, -231, -231,
-
-     -231, -231, -231, -231, -231, -231, -231, -231, -231,  273,
-     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
-     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
-     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
-     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
-     -231, -231, -231, -231, -231, -231, -231, -231
-    },
-
-    {
-       33, -232, -232, -232, -232, -232, -232, -232, -232, -232,
-     -232, -232, -232, -232, -232, -232, -232, -232, -232, -232,
-     -232, -232, -232, -232, -232, -232, -232, -232, -232, -232,
-     -232, -232,  274, -232, -232, -232, -232, -232, -232, -232,
-
-     -232, -232, -232, -232, -232, -232, -232, -232, -232, -232,
-     -232, -232, -232, -232, -232, -232, -232, -232, -232, -232,
-     -232, -232, -232, -232, -232, -232, -232, -232, -232, -232,
-     -232, -232, -232, -232, -232, -232, -232, -232, -232, -232,
-     -232, -232, -232, -232, -232, -232, -232, -232, -232, -232,
-     -232, -232, -232, -232, -232, -232, -232, -232, -232, -232,
-     -232, -232, -232, -232, -232, -232, -232, -232, -232, -232,
-     -232, -232, -232, -232, -232, -232, -232, -232, -232, -232,
-     -232, -232, -232, -232, -232, -232, -232, -232
-    },
-
-    {
-       33, -233, -233, -233, -233, -233, -233, -233, -233, -233,
-
-     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
-     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
-     -233, -233,  275, -233, -233, -233, -233, -233, -233, -233,
-     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
-     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
-     -233, -233, -233, -233, -233,  275,  275,  275,  275,  275,
-      275,  275,  275,  275,  275,  275,  275,  275,  275,  275,
-      275,  275,  275,  275,  275,  275,  275,  275,  275,  275,
-      275, -233, -233, -233, -233, -233, -233, -233, -233, -233,
-     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
-
-     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
-     -233, -233, -233, -233, -233, -233, -233, -233
-    },
-
-    {
-       33, -234, -234, -234, -234, -234, -234, -234, -234, -234,
-     -234, -234, -234, -234, -234, -234, -234, -234, -234, -234,
-     -234, -234, -234, -234, -234, -234, -234, -234, -234, -234,
-     -234, -234, -234, -234, -234, -234, -234, -234, -234, -234,
-     -234, -234, -234, -234, -234, -234, -234, -234, -234, -234,
-     -234, -234, -234, -234, -234, -234, -234, -234, -234, -234,
-     -234, -234, -234, -234, -234, -234, -234, -234, -234, -234,
-     -234, -234, -234, -234, -234, -234, -234, -234, -234,  276,
-
-     -234, -234, -234, -234, -234, -234, -234, -234, -234, -234,
-     -234, -234, -234, -234, -234, -234, -234, -234, -234, -234,
-     -234, -234, -234, -234, -234, -234, -234, -234, -234, -234,
-     -234, -234, -234, -234, -234, -234, -234, -234, -234, -234,
-     -234, -234, -234, -234, -234, -234, -234, -234
-    },
-
-    {
-       33, -235, -235, -235, -235, -235, -235, -235, -235, -235,
-     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
-     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
-     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
-     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
-
-     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
-     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
-     -235, -235, -235, -235, -235, -235,  277, -235, -235, -235,
-     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
-     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
-     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
-     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
-     -235, -235, -235, -235, -235, -235, -235, -235
-    },
-
-    {
-       33, -236, -236, -236, -236, -236, -236, -236, -236, -236,
-     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
-
-     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
-     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
-     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
-     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
-     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
-     -236, -236, -236, -236, -236, -236,  278, -236, -236, -236,
-     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
-     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
-     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
-     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
-
-     -236, -236, -236, -236, -236, -236, -236, -236
-    },
-
-    {
-       33, -237, -237, -237, -237, -237, -237, -237, -237, -237,
-     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
-     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
-     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
-     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
-     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
-     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
-     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
-     -237, -237, -237, -237, -237, -237,  279, -237, -237, -237,
-
-     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
-     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
-     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
-     -237, -237, -237, -237, -237, -237, -237, -237
-    },
-
-    {
-       33, -238, -238, -238, -238, -238, -238, -238, -238, -238,
-     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
-     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
-     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
-     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
-     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
-
-     -238, -238, -238, -238, -238, -238,  280, -238, -238, -238,
-     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
-     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
-     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
-     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
-     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
-     -238, -238, -238, -238, -238, -238, -238, -238
-    },
-
-    {
-       33, -239, -239, -239, -239, -239, -239, -239, -239, -239,
-     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
-     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
-
-     -239, -239,  281, -239, -239, -239, -239, -239, -239, -239,
-     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
-     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
-     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
-     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
-     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
-     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
-     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
-     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
-     -239, -239, -239, -239, -239, -239, -239, -239
-
-    },
-
-    {
-       33, -240, -240, -240, -240, -240, -240, -240, -240, -240,
-     -240, -240, -240, -240, -240, -240, -240, -240, -240, -240,
-     -240, -240, -240, -240, -240, -240, -240, -240, -240, -240,
-     -240, -240, -240, -240, -240, -240, -240, -240, -240, -240,
-     -240, -240, -240, -240, -240, -240, -240, -240, -240, -240,
-     -240, -240, -240, -240, -240, -240, -240, -240, -240, -240,
-     -240, -240, -240, -240, -240, -240, -240, -240, -240, -240,
-     -240, -240, -240, -240, -240, -240, -240, -240, -240,  282,
-     -240, -240, -240, -240, -240, -240, -240, -240, -240, -240,
-     -240, -240, -240, -240, -240, -240, -240, -240, -240, -240,
-
-     -240, -240, -240, -240, -240, -240, -240, -240, -240, -240,
-     -240, -240, -240, -240, -240, -240, -240, -240, -240, -240,
-     -240, -240, -240, -240, -240, -240, -240, -240
-    },
-
-    {
-       33, -241, -241, -241, -241, -241, -241, -241, -241, -241,
-     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
-     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
-     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
-     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
-     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
-     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
-
-     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
-     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
-     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
-     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
-     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
-     -241, -241, -241, -241, -241, -241, -241, -241
-    },
-
-    {
-       33, -242, -242, -242, -242, -242, -242, -242, -242, -242,
-     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
-     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
-     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
-
-     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
-     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
-     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
-     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
-     -242, -242, -242,  283, -242, -242, -242, -242, -242, -242,
-     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
-     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
-     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
-     -242, -242, -242, -242, -242, -242, -242, -242
-    },
-
-    {
-       33, -243, -243, -243, -243, -243, -243, -243, -243, -243,
-
-     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
-     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
-     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
-     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
-     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
-     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
-     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
-     -243, -243, -243, -243, -243, -243, -243, -243, -243,  284,
-     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
-     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
-
-     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
-     -243, -243, -243, -243, -243, -243, -243, -243
-    },
-
-    {
-       33, -244, -244, -244, -244, -244, -244, -244, -244, -244,
-     -244, -244, -244, -244, -244, -244, -244, -244, -244, -244,
-     -244, -244, -244, -244, -244, -244, -244, -244, -244, -244,
-     -244, -244, -244, -244, -244, -244, -244, -244, -244, -244,
-     -244, -244, -244, -244, -244, -244, -244, -244, -244, -244,
-     -244, -244, -244, -244, -244, -244, -244, -244, -244, -244,
-     -244, -244, -244, -244, -244, -244, -244, -244, -244, -244,
-     -244, -244, -244, -244, -244, -244, -244, -244, -244, -244,
-
-     -244, -244,  285, -244, -244, -244, -244, -244, -244, -244,
-     -244, -244, -244, -244, -244, -244, -244, -244, -244, -244,
-     -244, -244, -244, -244, -244, -244, -244, -244, -244, -244,
-     -244, -244, -244, -244, -244, -244, -244, -244, -244, -244,
-     -244, -244, -244, -244, -244, -244, -244, -244
-    },
-
-    {
-       33, -245, -245, -245, -245, -245, -245, -245, -245, -245,
-     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
-     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
-     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
-     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
-
-     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
-     -245, -245, -245, -245, -245,  286, -245, -245, -245, -245,
-     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
-     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
-     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
-     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
-     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
-     -245, -245, -245, -245, -245, -245, -245, -245
-    },
-
-    {
-       33, -246, -246, -246, -246, -246, -246, -246, -246, -246,
-     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
-
-     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
-     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
-     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
-     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
-     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
-     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
-     -246, -246, -246, -246, -246, -246, -246, -246, -246,  287,
-     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
-     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
-     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
-
-     -246, -246, -246, -246, -246, -246, -246, -246
-    },
-
-    {
-       33, -247, -247, -247, -247, -247, -247, -247, -247, -247,
-     -247, -247, -247, -247, -247, -247, -247, -247, -247, -247,
-     -247, -247, -247, -247, -247, -247, -247, -247, -247, -247,
-     -247, -247, -247, -247, -247, -247, -247, -247, -247, -247,
-     -247, -247, -247, -247, -247, -247, -247, -247, -247, -247,
-     -247, -247, -247, -247, -247, -247, -247, -247, -247, -247,
-     -247, -247, -247, -247, -247, -247,  288, -247, -247, -247,
-     -247, -247, -247, -247, -247, -247, -247, -247, -247, -247,
-     -247, -247, -247, -247, -247, -247, -247, -247, -247, -247,
-
-     -247, -247, -247, -247, -247, -247, -247, -247, -247, -247,
-     -247, -247, -247, -247, -247, -247, -247, -247, -247, -247,
-     -247, -247, -247, -247, -247, -247, -247, -247, -247, -247,
-     -247, -247, -247, -247, -247, -247, -247, -247
-    },
-
-    {
-       33, -248, -248, -248, -248, -248, -248, -248, -248, -248,
-     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
-     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
-     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
-     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
-     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
-
-     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
-     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
-     -248, -248,  289, -248, -248, -248, -248, -248, -248, -248,
-     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
-     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
-     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
-     -248, -248, -248, -248, -248, -248, -248, -248
-    },
-
-    {
-       33, -249, -249, -249, -249, -249, -249, -249, -249, -249,
-     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
-     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
-
-     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
-     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
-     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
-     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
-     -249,  290, -249, -249, -249, -249, -249, -249, -249, -249,
-     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
-     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
-     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
-     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
-     -249, -249, -249, -249, -249, -249, -249, -249
-
-    },
-
-    {
-       33, -250, -250, -250, -250, -250, -250, -250, -250, -250,
-     -250, -250, -250, -250, -250, -250, -250, -250, -250, -250,
-     -250, -250, -250, -250, -250, -250, -250, -250, -250, -250,
-     -250, -250, -250, -250, -250, -250, -250, -250, -250, -250,
-     -250, -250, -250, -250, -250, -250, -250, -250, -250, -250,
-     -250, -250, -250, -250, -250, -250, -250, -250, -250, -250,
-     -250, -250, -250, -250, -250, -250, -250, -250, -250, -250,
-     -250, -250, -250, -250, -250, -250, -250, -250, -250, -250,
-     -250, -250, -250, -250, -250, -250, -250, -250, -250,  291,
-     -250, -250, -250, -250, -250, -250, -250, -250, -250, -250,
-
-     -250, -250, -250, -250, -250, -250, -250, -250, -250, -250,
-     -250, -250, -250, -250, -250, -250, -250, -250, -250, -250,
-     -250, -250, -250, -250, -250, -250, -250, -250
-    },
-
-    {
-       33, -251, -251, -251, -251, -251, -251, -251, -251, -251,
-     -251, -251, -251, -251, -251, -251, -251, -251, -251, -251,
-     -251, -251, -251, -251, -251, -251, -251, -251, -251, -251,
-     -251, -251, -251, -251, -251, -251, -251, -251, -251, -251,
-     -251, -251, -251, -251, -251, -251, -251, -251, -251, -251,
-     -251, -251, -251, -251, -251, -251, -251, -251, -251, -251,
-     -251, -251, -251, -251, -251, -251, -251, -251, -251, -251,
-
-      292, -251, -251, -251, -251, -251, -251, -251, -251, -251,
-     -251, -251, -251, -251, -251, -251, -251, -251, -251, -251,
-     -251, -251, -251, -251, -251, -251, -251, -251, -251, -251,
-     -251, -251, -251, -251, -251, -251, -251, -251, -251, -251,
-     -251, -251, -251, -251, -251, -251, -251, -251, -251, -251,
-     -251, -251, -251, -251, -251, -251, -251, -251
-    },
-
-    {
-       33, -252, -252, -252, -252, -252, -252, -252, -252, -252,
-     -252, -252, -252, -252, -252, -252, -252, -252, -252, -252,
-     -252, -252, -252, -252, -252, -252, -252, -252, -252, -252,
-     -252, -252, -252, -252, -252, -252, -252, -252, -252, -252,
-
-     -252, -252, -252, -252, -252, -252, -252, -252, -252, -252,
-     -252, -252, -252, -252, -252, -252, -252, -252, -252, -252,
-     -252, -252, -252, -252, -252, -252, -252,  293, -252, -252,
-     -252, -252, -252, -252, -252, -252, -252, -252, -252, -252,
-     -252, -252, -252, -252, -252, -252, -252, -252, -252, -252,
-     -252, -252, -252, -252, -252, -252, -252, -252, -252, -252,
-     -252, -252, -252, -252, -252, -252, -252, -252, -252, -252,
-     -252, -252, -252, -252, -252, -252, -252, -252, -252, -252,
-     -252, -252, -252, -252, -252, -252, -252, -252
-    },
-
-    {
-       33, -253, -253, -253, -253, -253, -253, -253, -253, -253,
-
-     -253, -253, -253, -253, -253, -253, -253, -253, -253, -253,
-     -253, -253, -253, -253, -253, -253, -253, -253, -253, -253,
-     -253, -253, -253, -253, -253, -253, -253, -253, -253, -253,
-     -253, -253, -253, -253, -253, -253, -253, -253, -253, -253,
-     -253, -253, -253, -253, -253, -253, -253, -253, -253, -253,
-     -253, -253, -253, -253, -253, -253, -253, -253, -253,  294,
-     -253, -253, -253, -253, -253, -253, -253, -253, -253, -253,
-     -253, -253, -253, -253, -253, -253, -253, -253, -253, -253,
-     -253, -253, -253, -253, -253, -253, -253, -253, -253, -253,
-     -253, -253, -253, -253, -253, -253, -253, -253, -253, -253,
-
-     -253, -253, -253, -253, -253, -253, -253, -253, -253, -253,
-     -253, -253, -253, -253, -253, -253, -253, -253
-    },
-
-    {
-       33, -254, -254, -254, -254, -254, -254, -254, -254, -254,
-     -254, -254, -254, -254, -254, -254, -254, -254, -254, -254,
-     -254, -254, -254, -254, -254, -254, -254, -254, -254, -254,
-     -254, -254, -254, -254, -254, -254, -254, -254, -254, -254,
-     -254, -254, -254, -254, -254, -254, -254, -254, -254, -254,
-     -254, -254, -254, -254, -254, -254, -254, -254, -254, -254,
-     -254, -254, -254, -254, -254, -254, -254, -254, -254, -254,
-     -254, -254, -254, -254, -254, -254, -254,  295, -254, -254,
-
-     -254, -254, -254, -254, -254, -254, -254, -254, -254, -254,
-     -254, -254, -254, -254, -254, -254, -254, -254, -254, -254,
-     -254, -254, -254, -254, -254, -254, -254, -254, -254, -254,
-     -254, -254, -254, -254, -254, -254, -254, -254, -254, -254,
-     -254, -254, -254, -254, -254, -254, -254, -254
-    },
-
-    {
-       33, -255, -255, -255, -255, -255, -255, -255, -255, -255,
-     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
-     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
-     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
-     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
-
-     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
-     -255, -255, -255, -255, -255, -255, -255,  296, -255, -255,
-     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
-     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
-     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
-     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
-     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
-     -255, -255, -255, -255, -255, -255, -255, -255
-    },
-
-    {
-       33, -256, -256, -256, -256, -256, -256, -256, -256, -256,
-     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
-
-     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
-     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
-     -256, -256, -256, -256, -256, -256, -256, -256,  297,  297,
-      297,  297,  297,  297,  297,  297,  297,  297, -256, -256,
-     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
-     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
-     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
-     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
-     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
-     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
-
-     -256, -256, -256, -256, -256, -256, -256, -256
-    },
-
-    {
-       33, -257, -257, -257, -257, -257, -257, -257, -257, -257,
-     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
-     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
-     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
-     -257, -257, -257, -257, -257, -257, -257, -257, -257,  298,
-      298,  298,  298,  298,  298,  298,  298,  298, -257, -257,
-     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
-     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
-     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
-
-     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
-     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
-     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
-     -257, -257, -257, -257, -257, -257, -257, -257
-    },
-
-    {
-       33, -258, -258, -258, -258, -258, -258, -258, -258, -258,
-     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
-     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
-     -258, -258,  299, -258, -258, -258, -258, -258, -258, -258,
-     -258, -258, -258, -258, -258, -258, -258, -258,  300,  300,
-      300,  300,  300,  300,  300,  300,  300,  300, -258, -258,
-
-     -258, -258, -258, -258, -258,  299,  299,  299,  299,  299,
-      299,  299,  299,  299,  299,  299,  299,  299,  299,  299,
-      299,  299,  299,  299,  299,  299,  299,  299,  299,  299,
-      299, -258, -258, -258, -258, -258, -258, -258, -258, -258,
-     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
-     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
-     -258, -258, -258, -258, -258, -258, -258, -258
-    },
-
-    {
-       33, -259, -259, -259, -259, -259, -259, -259, -259, -259,
-     -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
-     -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
-
-     -259, -259,  301, -259, -259, -259, -259, -259, -259, -259,
-     -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
-     -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
-     -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
-     -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
-     -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
-     -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
-     -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
-     -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
-     -259, -259, -259, -259, -259, -259, -259, -259
-
-    },
-
-    {
-       33, -260, -260, -260, -260, -260, -260, -260, -260, -260,
-     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
-     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
-     -260, -260,  302, -260, -260, -260, -260, -260, -260, -260,
-     -260, -260, -260, -260, -260, -260, -260, -260,  303,  303,
-      303,  303,  303,  303,  303,  303,  303,  303, -260, -260,
-     -260, -260, -260, -260, -260,  302,  302,  302,  302,  302,
-      302,  302,  302,  302,  302,  302,  302,  302,  302,  302,
-      302,  302,  302,  302,  302,  302,  302,  302,  302,  302,
-      302, -260, -260, -260, -260, -260, -260, -260, -260, -260,
-
-     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
-     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
-     -260, -260, -260, -260, -260, -260, -260, -260
-    },
-
-    {
-       33, -261, -261, -261, -261, -261, -261, -261, -261, -261,
-     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
-     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
-     -261, -261,  304, -261, -261, -261, -261, -261, -261, -261,
-     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
-     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
-     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
-
-     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
-     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
-     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
-     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
-     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
-     -261, -261, -261, -261, -261, -261, -261, -261
-    },
-
-    {
-       33, -262, -262, -262, -262, -262, -262, -262, -262, -262,
-     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
-     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
-     -262, -262,  305, -262, -262, -262, -262, -262, -262, -262,
-
-     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
-     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
-     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
-     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
-     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
-     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
-     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
-     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
-     -262, -262, -262, -262, -262, -262, -262, -262
-    },
-
-    {
-       33, -263, -263, -263, -263, -263, -263, -263, -263, -263,
-
-     -263, -263, -263, -263, -263, -263, -263, -263, -263, -263,
-     -263, -263, -263, -263, -263, -263, -263, -263, -263, -263,
-     -263, -263,  306, -263, -263, -263, -263, -263, -263, -263,
-     -263, -263, -263, -263, -263, -263, -263, -263,  307,  307,
-      307,  307,  307,  307,  307,  307,  307,  307, -263, -263,
-     -263, -263, -263, -263, -263,  306,  306,  306,  306,  306,
-      306,  306,  306,  306,  306,  306,  306,  306,  306,  306,
-      306,  306,  306,  306,  306,  306,  306,  306,  306,  306,
-      306, -263, -263, -263, -263, -263, -263, -263, -263, -263,
-     -263, -263, -263, -263, -263, -263, -263, -263, -263, -263,
-
-     -263, -263, -263, -263, -263, -263, -263, -263, -263, -263,
-     -263, -263, -263, -263, -263, -263, -263, -263
-    },
-
-    {
-       33, -264, -264, -264, -264, -264, -264, -264, -264, -264,
-     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
-     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
-     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
-     -264, -264, -264, -264, -264, -264, -264, -264,  308,  308,
-      308,  308,  308,  308,  308,  308,  308,  308, -264, -264,
-     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
-     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
-
-     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
-     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
-     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
-     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
-     -264, -264, -264, -264, -264, -264, -264, -264
-    },
-
-    {
-       33, -265, -265, -265, -265, -265, -265, -265, -265, -265,
-     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
-     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
-     -265, -265,  309, -265, -265, -265, -265, -265, -265, -265,
-     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
-
-     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
-     -265, -265, -265, -265, -265,  309,  309,  309,  309,  309,
-      309,  309,  309,  309,  309,  309,  309,  309,  309,  309,
-      309,  309,  309,  309,  309,  309,  309,  309,  309,  309,
-      309, -265, -265, -265, -265, -265, -265, -265, -265, -265,
-     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
-     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
-     -265, -265, -265, -265, -265, -265, -265, -265
-    },
-
-    {
-       33, -266, -266, -266, -266, -266, -266, -266, -266, -266,
-     -266, -266, -266, -266, -266, -266, -266, -266, -266, -266,
-
-     -266, -266, -266, -266, -266, -266, -266, -266, -266, -266,
-     -266, -266,  309, -266, -266, -266, -266, -266, -266, -266,
-     -266, -266, -266, -266, -266, -266, -266, -266,  310,  310,
-      310,  310,  310,  310,  310,  310,  310,  310, -266, -266,
-     -266, -266, -266, -266, -266,  309,  309,  309,  309,  309,
-      309,  309,  309,  309,  309,  309,  309,  309,  309,  309,
-      309,  309,  309,  309,  309,  309,  309,  309,  309,  309,
-      309, -266, -266, -266, -266, -266, -266, -266, -266, -266,
-     -266, -266, -266, -266, -266, -266, -266, -266, -266, -266,
-     -266, -266, -266, -266, -266, -266, -266, -266, -266, -266,
-
-     -266, -266, -266, -266, -266, -266, -266, -266
-    },
-
-    {
-       33, -267, -267, -267, -267, -267, -267, -267, -267, -267,
-     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
-     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
-     -267, -267,  311, -267, -267, -267, -267, -267, -267, -267,
-     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
-     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
-     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
-     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
-     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
-
-     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
-     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
-     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
-     -267, -267, -267, -267, -267, -267, -267, -267
-    },
-
-    {
-       33, -268, -268, -268, -268, -268, -268, -268, -268, -268,
-     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
-     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
-     -268, -268,  312, -268, -268, -268, -268, -268, -268, -268,
-     -268, -268, -268, -268, -268, -268, -268, -268,  313,  313,
-      313,  313,  313,  313,  313,  313,  313,  313, -268, -268,
-
-     -268, -268, -268, -268, -268,  312,  312,  312,  312,  312,
-      312,  312,  312,  312,  312,  312,  312,  312,  312,  312,
-      312,  312,  312,  312,  312,  312,  312,  312,  312,  312,
-      312, -268, -268, -268, -268, -268, -268, -268, -268, -268,
-     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
-     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
-     -268, -268, -268, -268, -268, -268, -268, -268
-    },
-
-    {
-       33, -269, -269, -269, -269, -269, -269, -269, -269, -269,
-     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
-     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
-
-     -269, -269,  314, -269, -269, -269, -269, -269, -269, -269,
-     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
-     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
-     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
-     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
-     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
-     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
-     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
-     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
-     -269, -269, -269, -269, -269, -269, -269, -269
-
-    },
-
-    {
-       33, -270, -270, -270, -270, -270, -270, -270, -270, -270,
-     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
-     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
-     -270, -270,  315, -270, -270, -270, -270, -270, -270, -270,
-     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
-     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
-     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
-     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
-     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
-     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
-
-     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
-     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
-     -270, -270, -270, -270, -270, -270, -270, -270
-    },
-
-    {
-       33, -271, -271, -271, -271, -271, -271, -271, -271, -271,
-     -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
-     -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
-     -271, -271,  316, -271, -271, -271, -271, -271, -271, -271,
-     -271, -271, -271, -271, -271, -271, -271, -271,  317,  317,
-      317,  317,  317,  317,  317,  317,  317,  317, -271, -271,
-     -271, -271, -271, -271, -271,  316,  316,  316,  316,  316,
-
-      316,  316,  316,  316,  316,  316,  316,  316,  316,  316,
-      316,  316,  316,  316,  316,  316,  316,  316,  316,  316,
-      316, -271, -271, -271, -271, -271, -271, -271, -271, -271,
-     -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
-     -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
-     -271, -271, -271, -271, -271, -271, -271, -271
-    },
-
-    {
-       33, -272, -272, -272, -272, -272, -272, -272, -272, -272,
-     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
-     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
-     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
-
-     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
-     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
-     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
-     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
-     -272, -272, -272, -272, -272, -272,  318, -272, -272, -272,
-     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
-     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
-     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
-     -272, -272, -272, -272, -272, -272, -272, -272
-    },
-
-    {
-       33, -273, -273, -273, -273, -273, -273, -273, -273, -273,
-
-     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
-     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
-     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
-     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
-     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
-     -273, -273, -273, -273, -273, -273,  319, -273, -273, -273,
-     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
-     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
-     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
-     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
-
-     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
-     -273, -273, -273, -273, -273, -273, -273, -273
-    },
-
-    {
-       33, -274, -274, -274, -274, -274, -274, -274, -274, -274,
-     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
-     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
-     -274, -274,  320, -274, -274, -274, -274, -274, -274, -274,
-     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
-     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
-     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
-     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
-
-     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
-     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
-     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
-     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
-     -274, -274, -274, -274, -274, -274, -274, -274
-    },
-
-    {
-       33, -275, -275, -275, -275, -275, -275, -275, -275, -275,
-     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
-     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
-     -275, -275,  321, -275, -275, -275, -275, -275, -275, -275,
-     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
-
-     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
-     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
-     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
-     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
-     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
-     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
-     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
-     -275, -275, -275, -275, -275, -275, -275, -275
-    },
-
-    {
-       33, -276, -276, -276, -276, -276, -276, -276, -276, -276,
-     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
-
-     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
-     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
-     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
-     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
-     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
-     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
-     -276, -276, -276, -276, -276, -276, -276, -276,  322, -276,
-     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
-     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
-     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
-
-     -276, -276, -276, -276, -276, -276, -276, -276
-    },
-
-    {
-       33, -277, -277, -277, -277, -277, -277, -277, -277, -277,
-     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
-     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
-     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
-     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
-     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
-     -277, -277, -277, -277, -277, -277, -277, -277, -277,  323,
-     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
-     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
-
-     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
-     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
-     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
-     -277, -277, -277, -277, -277, -277, -277, -277
-    },
-
-    {
-       33, -278, -278, -278, -278, -278, -278, -278, -278, -278,
-     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
-     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
-     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
-     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
-     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
-
-     -278, -278, -278, -278, -278, -278, -278, -278, -278,  324,
-     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
-     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
-     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
-     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
-     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
-     -278, -278, -278, -278, -278, -278, -278, -278
-    },
-
-    {
-       33, -279, -279, -279, -279, -279, -279, -279, -279, -279,
-     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
-     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
-
-     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
-     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
-     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
-     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
-     -279,  325, -279, -279, -279, -279, -279, -279, -279, -279,
-     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
-     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
-     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
-     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
-     -279, -279, -279, -279, -279, -279, -279, -279
-
-    },
-
-    {
-       33, -280, -280, -280, -280, -280, -280, -280, -280, -280,
-     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
-     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
-     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
-     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
-     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
-     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
-     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
-     -280, -280, -280,  326, -280, -280, -280, -280, -280, -280,
-     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
-
-     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
-     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
-     -280, -280, -280, -280, -280, -280, -280, -280
-    },
-
-    {
-       33, -281, -281, -281, -281, -281, -281, -281, -281, -281,
-     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
-     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
-     -281, -281,  327, -281, -281, -281, -281, -281, -281, -281,
-     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
-     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
-     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
-
-     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
-     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
-     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
-     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
-     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
-     -281, -281, -281, -281, -281, -281, -281, -281
-    },
-
-    {
-       33, -282, -282, -282, -282, -282, -282, -282, -282, -282,
-     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
-     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
-     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
-
-     -282, -282, -282, -282, -282,  328, -282, -282, -282, -282,
-     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
-     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
-     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
-     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
-     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
-     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
-     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
-     -282, -282, -282, -282, -282, -282, -282, -282
-    },
-
-    {
-       33, -283, -283, -283, -283, -283, -283, -283, -283, -283,
-
-     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
-     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
-     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
-     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
-     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
-     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
-     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
-     -283, -283, -283, -283, -283, -283, -283, -283, -283,  329,
-     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
-     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
-
-     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
-     -283, -283, -283, -283, -283, -283, -283, -283
-    },
-
-    {
-       33, -284, -284, -284, -284, -284, -284, -284, -284, -284,
-     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
-     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
-     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
-     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
-     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
-     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
-     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
-
-     -284, -284, -284,  330, -284, -284, -284, -284, -284, -284,
-     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
-     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
-     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
-     -284, -284, -284, -284, -284, -284, -284, -284
-    },
-
-    {
-       33, -285, -285, -285, -285, -285, -285, -285, -285, -285,
-     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
-     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
-     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
-     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
-
-     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
-     -285, -285, -285, -285, -285, -285, -285, -285, -285,  331,
-     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
-     -285,  332, -285, -285, -285, -285, -285, -285, -285, -285,
-     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
-     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
-     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
-     -285, -285, -285, -285, -285, -285, -285, -285
-    },
-
-    {
-       33, -286, -286, -286, -286, -286, -286, -286, -286, -286,
-     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
-
-     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
-     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
-     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
-     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
-     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
-     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
-     -286, -286, -286, -286, -286, -286,  333, -286, -286, -286,
-     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
-     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
-     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
-
-     -286, -286, -286, -286, -286, -286, -286, -286
-    },
-
-    {
-       33, -287, -287, -287, -287, -287, -287, -287, -287, -287,
-     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
-     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
-     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
-     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
-     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
-     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
-     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
-     -287, -287, -287,  334, -287, -287, -287, -287, -287, -287,
-
-     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
-     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
-     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
-     -287, -287, -287, -287, -287, -287, -287, -287
-    },
-
-    {
-       33, -288, -288, -288, -288, -288, -288, -288, -288, -288,
-     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
-     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
-     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
-     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
-     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
-
-     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
-     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
-     -288, -288, -288,  335, -288, -288, -288, -288, -288, -288,
-     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
-     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
-     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
-     -288, -288, -288, -288, -288, -288, -288, -288
-    },
-
-    {
-       33, -289, -289, -289, -289, -289, -289, -289, -289, -289,
-     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
-     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
-
-     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
-     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
-     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
-     -289, -289, -289, -289, -289, -289, -289,  336, -289, -289,
-     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
-     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
-     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
-     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
-     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
-     -289, -289, -289, -289, -289, -289, -289, -289
-
-    },
-
-    {
-       33, -290, -290, -290, -290, -290, -290, -290, -290, -290,
-     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
-     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
-     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
-     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
-     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
-     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
-     -290, -290, -290, -290, -290, -290,  337, -290, -290, -290,
-     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
-     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
-
-     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
-     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
-     -290, -290, -290, -290, -290, -290, -290, -290
-    },
-
-    {
-       33, -291, -291, -291, -291, -291, -291, -291, -291, -291,
-     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
-     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
-     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
-     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
-     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
-     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
-
-     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
-     -291, -291, -291,  338, -291, -291, -291, -291, -291, -291,
-     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
-     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
-     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
-     -291, -291, -291, -291, -291, -291, -291, -291
-    },
-
-    {
-       33, -292, -292, -292, -292, -292, -292, -292, -292, -292,
-     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
-     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
-     -292, -292,  339, -292, -292, -292, -292, -292, -292, -292,
-
-     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
-     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
-     -292, -292, -292, -292, -292,  339,  339,  339,  339,  339,
-      339,  339,  339,  339,  339,  339,  339,  339,  339,  339,
-      339,  339,  339,  339,  339,  339,  339,  339,  339,  339,
-      339, -292, -292, -292, -292, -292, -292, -292, -292, -292,
-     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
-     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
-     -292, -292, -292, -292, -292, -292, -292, -292
-    },
-
-    {
-       33, -293, -293, -293, -293, -293, -293, -293, -293, -293,
-
-     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
-     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
-     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
-     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
-     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
-     -293, -293, -293, -293, -293, -293, -293, -293, -293,  340,
-     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
-     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
-     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
-     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
-
-     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
-     -293, -293, -293, -293, -293, -293, -293, -293
-    },
-
-    {
-       33, -294, -294, -294, -294, -294, -294, -294, -294, -294,
-     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
-     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
-     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
-     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
-     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
-     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
-     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
-
-     -294, -294, -294,  341, -294, -294, -294, -294, -294, -294,
-     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
-     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
-     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
-     -294, -294, -294, -294, -294, -294, -294, -294
-    },
-
-    {
-       33, -295, -295, -295, -295, -295, -295, -295, -295, -295,
-     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
-     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
-     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
-     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
-
-     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
-     -295, -295, -295, -295, -295, -295, -295, -295, -295,  342,
-     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
-     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
-     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
-     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
-     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
-     -295, -295, -295, -295, -295, -295, -295, -295
-    },
-
-    {
-       33, -296, -296, -296, -296, -296, -296, -296, -296, -296,
-     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
-
-     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
-     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
-     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
-     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
-     -296, -296, -296, -296, -296, -296, -296, -296, -296,  343,
-     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
-     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
-     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
-     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
-     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
-
-     -296, -296, -296, -296, -296, -296, -296, -296
-    },
-
-    {
-       33, -297, -297, -297, -297, -297, -297, -297, -297, -297,
-     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
-     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
-     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
-     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
-     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
-     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
-     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
-     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
-
-     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
-     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
-     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
-     -297, -297, -297, -297, -297, -297, -297, -297
-    },
-
-    {
-       33, -298, -298, -298, -298, -298, -298, -298, -298, -298,
-     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
-     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
-     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
-     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
-     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
-
-     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
-     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
-     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
-     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
-     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
-     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
-     -298, -298, -298, -298, -298, -298, -298, -298
-    },
-
-    {
-       33, -299, -299, -299, -299, -299, -299, -299, -299, -299,
-     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
-     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
-
-     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
-     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
-     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
-     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
-     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
-     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
-     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
-     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
-     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
-     -299, -299, -299, -299, -299, -299, -299, -299
-
-    },
-
-    {
-       33, -300, -300, -300, -300, -300, -300, -300, -300, -300,
-     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
-     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
-     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
-     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
-     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
-     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
-     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
-     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
-     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
-
-     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
-     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
-     -300, -300, -300, -300, -300, -300, -300, -300
-    },
-
-    {
-       33, -301, -301, -301, -301, -301, -301, -301, -301, -301,
-     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
-     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
-     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
-     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
-     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
-     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
-
-     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
-     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
-     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
-     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
-     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
-     -301, -301, -301, -301, -301, -301, -301, -301
-    },
-
-    {
-       33, -302, -302, -302, -302, -302, -302, -302, -302, -302,
-     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
-     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
-     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
-
-     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
-     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
-     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
-     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
-     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
-     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
-     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
-     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
-     -302, -302, -302, -302, -302, -302, -302, -302
-    },
-
-    {
-       33, -303, -303, -303, -303, -303, -303, -303, -303, -303,
-
-     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
-     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
-     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
-     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
-     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
-     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
-     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
-     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
-     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
-     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
-
-     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
-     -303, -303, -303, -303, -303, -303, -303, -303
-    },
-
-    {
-       33, -304, -304, -304, -304, -304, -304, -304, -304, -304,
-     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
-     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
-     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
-     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
-     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
-     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
-     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
-
-     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
-     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
-     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
-     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
-     -304, -304, -304, -304, -304, -304, -304, -304
-    },
-
-    {
-       33, -305, -305, -305, -305, -305, -305, -305, -305, -305,
-     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
-     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
-     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
-     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
-
-     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
-     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
-     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
-     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
-     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
-     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
-     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
-     -305, -305, -305, -305, -305, -305, -305, -305
-    },
-
-    {
-       33, -306, -306, -306, -306, -306, -306, -306, -306, -306,
-     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
-
-     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
-     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
-     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
-     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
-     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
-     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
-     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
-     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
-     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
-     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
-
-     -306, -306, -306, -306, -306, -306, -306, -306
-    },
-
-    {
-       33, -307, -307, -307, -307, -307, -307, -307, -307, -307,
-     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
-     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
-     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
-     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
-     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
-     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
-     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
-     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
-
-     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
-     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
-     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
-     -307, -307, -307, -307, -307, -307, -307, -307
-    },
-
-    {
-       33, -308, -308, -308, -308, -308, -308, -308, -308, -308,
-     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
-     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
-     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
-     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
-     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
-
-     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
-     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
-     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
-     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
-     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
-     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
-     -308, -308, -308, -308, -308, -308, -308, -308
-    },
-
-    {
-       33, -309, -309, -309, -309, -309, -309, -309, -309, -309,
-     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
-     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
-
-     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
-     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
-     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
-     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
-     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
-     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
-     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
-     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
-     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
-     -309, -309, -309, -309, -309, -309, -309, -309
-
-    },
-
-    {
-       33, -310, -310, -310, -310, -310, -310, -310, -310, -310,
-     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
-     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
-     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
-     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
-     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
-     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
-     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
-     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
-     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
-
-     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
-     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
-     -310, -310, -310, -310, -310, -310, -310, -310
-    },
-
-    {
-       33, -311, -311, -311, -311, -311, -311, -311, -311, -311,
-     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
-     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
-     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
-     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
-     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
-     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
-
-     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
-     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
-     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
-     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
-     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
-     -311, -311, -311, -311, -311, -311, -311, -311
-    },
-
-    {
-       33, -312, -312, -312, -312, -312, -312, -312, -312, -312,
-     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
-     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
-     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
-
-     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
-     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
-     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
-     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
-     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
-     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
-     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
-     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
-     -312, -312, -312, -312, -312, -312, -312, -312
-    },
-
-    {
-       33, -313, -313, -313, -313, -313, -313, -313, -313, -313,
-
-     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
-     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
-     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
-     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
-     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
-     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
-     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
-     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
-     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
-     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
-
-     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
-     -313, -313, -313, -313, -313, -313, -313, -313
-    },
-
-    {
-       33, -314, -314, -314, -314, -314, -314, -314, -314, -314,
-     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
-     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
-     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
-     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
-     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
-     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
-     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
-
-     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
-     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
-     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
-     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
-     -314, -314, -314, -314, -314, -314, -314, -314
-    },
-
-    {
-       33, -315, -315, -315, -315, -315, -315, -315, -315, -315,
-     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
-     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
-     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
-     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
-
-     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
-     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
-     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
-     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
-     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
-     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
-     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
-     -315, -315, -315, -315, -315, -315, -315, -315
-    },
-
-    {
-       33, -316, -316, -316, -316, -316, -316, -316, -316, -316,
-     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
-
-     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
-     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
-     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
-     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
-     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
-     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
-     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
-     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
-     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
-     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
-
-     -316, -316, -316, -316, -316, -316, -316, -316
-    },
-
-    {
-       33, -317, -317, -317, -317, -317, -317, -317, -317, -317,
-     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
-     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
-     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
-     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
-     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
-     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
-     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
-     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
-
-     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
-     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
-     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
-     -317, -317, -317, -317, -317, -317, -317, -317
-    },
-
-    {
-       33, -318, -318, -318, -318, -318, -318, -318, -318, -318,
-     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
-     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
-     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
-     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
-     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
-
-     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
-     -318,  344, -318, -318, -318, -318, -318, -318, -318, -318,
-     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
-     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
-     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
-     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
-     -318, -318, -318, -318, -318, -318, -318, -318
-    },
-
-    {
-       33, -319, -319, -319, -319, -319, -319, -319, -319, -319,
-     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
-     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
-
-     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
-     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
-     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
-     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
-     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
-     -319, -319, -319,  345, -319, -319, -319, -319, -319, -319,
-     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
-     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
-     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
-     -319, -319, -319, -319, -319, -319, -319, -319
-
-    },
-
-    {
-       33, -320, -320, -320, -320, -320, -320, -320, -320, -320,
-     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
-     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
-     -320, -320,  346, -320, -320, -320, -320, -320, -320, -320,
-     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
-     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
-     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
-     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
-     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
-     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
-
-     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
-     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
-     -320, -320, -320, -320, -320, -320, -320, -320
-    },
-
-    {
-       33, -321, -321, -321, -321, -321, -321, -321, -321, -321,
-     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
-     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
-     -321, -321,  347, -321, -321, -321, -321, -321, -321, -321,
-     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
-     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
-     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
-
-     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
-     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
-     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
-     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
-     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
-     -321, -321, -321, -321, -321, -321, -321, -321
-    },
-
-    {
-       33, -322, -322, -322, -322, -322, -322, -322, -322, -322,
-     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
-     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
-     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
-
-     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
-     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
-     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
-     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
-     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
-     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
-     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
-     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
-     -322, -322, -322, -322, -322, -322, -322, -322
-    },
-
-    {
-       33, -323, -323, -323, -323, -323, -323, -323, -323, -323,
-
-     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
-     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
-     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
-     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
-     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
-     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
-     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
-     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
-     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
-     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
-
-     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
-     -323, -323, -323, -323, -323, -323, -323, -323
-    },
-
-    {
-       33, -324, -324, -324, -324, -324, -324, -324, -324, -324,
-     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
-     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
-     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
-     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
-     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
-     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
-     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
-
-     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
-     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
-     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
-     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
-     -324, -324, -324, -324, -324, -324, -324, -324
-    },
-
-    {
-       33, -325, -325, -325, -325, -325, -325, -325, -325, -325,
-     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
-     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
-     -325, -325,  348, -325, -325, -325, -325, -325, -325, -325,
-     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
-
-     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
-     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
-     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
-     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
-     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
-     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
-     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
-     -325, -325, -325, -325, -325, -325, -325, -325
-    },
-
-    {
-       33, -326, -326, -326, -326, -326, -326, -326, -326, -326,
-     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
-
-     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
-     -326, -326,  349, -326, -326, -326, -326, -326, -326, -326,
-     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
-     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
-     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
-     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
-     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
-     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
-     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
-     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
-
-     -326, -326, -326, -326, -326, -326, -326, -326
-    },
-
-    {
-       33, -327, -327, -327, -327, -327, -327, -327, -327, -327,
-     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
-     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
-     -327, -327,  350, -327, -327, -327, -327, -327, -327, -327,
-     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
-     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
-     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
-     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
-     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
-
-     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
-     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
-     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
-     -327, -327, -327, -327, -327, -327, -327, -327
-    },
-
-    {
-       33, -328, -328, -328, -328, -328, -328, -328, -328, -328,
-     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
-     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
-     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
-     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
-     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
-
-     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
-     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
-     -328, -328, -328, -328, -328, -328, -328, -328,  351,  352,
-      353, -328, -328, -328, -328, -328, -328, -328, -328, -328,
-     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
-     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
-     -328, -328, -328, -328, -328, -328, -328, -328
-    },
-
-    {
-       33, -329, -329, -329, -329, -329, -329, -329, -329, -329,
-     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
-     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
-
-     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
-     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
-     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
-     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
-     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
-     -329, -329, -329,  354, -329, -329, -329, -329, -329, -329,
-     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
-     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
-     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
-     -329, -329, -329, -329, -329, -329, -329, -329
-
-    },
-
-    {
-       33, -330, -330, -330, -330, -330, -330, -330, -330, -330,
-     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
-     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
-     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
-     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
-     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
-     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
-     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
-     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
-     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
-
-     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
-     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
-     -330, -330, -330, -330, -330, -330, -330, -330
-    },
-
-    {
-       33, -331, -331, -331, -331, -331, -331, -331, -331, -331,
-     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
-     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
-     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
-     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
-     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
-     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
-
-     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
-     -331,  355, -331, -331, -331, -331, -331, -331, -331, -331,
-     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
-     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
-     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
-     -331, -331, -331, -331, -331, -331, -331, -331
-    },
-
-    {
-       33, -332, -332, -332, -332, -332, -332, -332, -332, -332,
-     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
-     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
-     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
-
-     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
-     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
-     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
-     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
-     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
-     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
-     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
-     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
-     -332, -332, -332, -332, -332, -332, -332, -332
-    },
-
-    {
-       33, -333, -333, -333, -333, -333, -333, -333, -333, -333,
-
-     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
-     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
-     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
-     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
-     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
-     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
-     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
-     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
-     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
-     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
-
-     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
-     -333, -333, -333, -333, -333, -333, -333, -333
-    },
-
-    {
-       33, -334, -334, -334, -334, -334, -334, -334, -334, -334,
-     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
-     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
-     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
-     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
-     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
-     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
-     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
-
-     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
-     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
-     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
-     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
-     -334, -334, -334, -334, -334, -334, -334, -334
-    },
-
-    {
-       33, -335, -335, -335, -335, -335, -335, -335, -335, -335,
-     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
-     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
-     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
-     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
-
-     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
-     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
-     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
-     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
-     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
-     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
-     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
-     -335, -335, -335, -335, -335, -335, -335, -335
-    },
-
-    {
-       33, -336, -336, -336, -336, -336, -336, -336, -336, -336,
-     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
-
-     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
-     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
-     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
-     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
-     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
-     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
-     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
-     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
-     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
-     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
-
-     -336, -336, -336, -336, -336, -336, -336, -336
-    },
-
-    {
-       33, -337, -337, -337, -337, -337, -337, -337, -337, -337,
-     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
-     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
-     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
-     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
-     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
-     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
-     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
-     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
-
-     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
-     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
-     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
-     -337, -337, -337, -337, -337, -337, -337, -337
-    },
-
-    {
-       33, -338, -338, -338, -338, -338, -338, -338, -338, -338,
-     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
-     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
-     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
-     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
-     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
-
-     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
-     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
-     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
-     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
-     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
-     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
-     -338, -338, -338, -338, -338, -338, -338, -338
-    },
-
-    {
-       33, -339, -339, -339, -339, -339, -339, -339, -339, -339,
-     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
-     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
-
-     -339, -339,  356, -339, -339, -339, -339, -339, -339, -339,
-     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
-     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
-     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
-     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
-     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
-     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
-     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
-     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
-     -339, -339, -339, -339, -339, -339, -339, -339
-
-    },
-
-    {
-       33, -340, -340, -340, -340, -340, -340, -340, -340, -340,
-     -340, -340, -340, -340, -340, -340, -340, -340, -340, -340,
-     -340, -340, -340, -340, -340, -340, -340, -340, -340, -340,
-     -340, -340,  357, -340, -340, -340, -340, -340, -340, -340,
-     -340, -340, -340, -340, -340, -340, -340, -340, -340, -340,
-     -340, -340, -340, -340, -340, -340, -340, -340, -340, -340,
-     -340, -340, -340, -340, -340,  357,  357,  357,  357,  357,
-      357,  357,  357,  357,  357,  357,  357,  357,  357,  357,
-      357,  357,  357,  357,  357,  357,  357,  357,  357,  357,
-      357, -340, -340, -340, -340, -340, -340, -340, -340, -340,
-
-     -340, -340, -340, -340, -340, -340, -340, -340, -340, -340,
-     -340, -340, -340, -340, -340, -340, -340, -340, -340, -340,
-     -340, -340, -340, -340, -340, -340, -340, -340
-    },
-
-    {
-       33, -341, -341, -341, -341, -341, -341, -341, -341, -341,
-     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
-     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
-     -341, -341,  358, -341, -341, -341, -341, -341, -341, -341,
-     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
-     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
-     -341, -341, -341, -341, -341,  358,  358,  358,  358,  358,
-
-      358,  358,  358,  358,  358,  358,  358,  358,  358,  358,
-      358,  358,  358,  358,  358,  358,  358,  358,  358,  358,
-      358, -341, -341, -341, -341, -341, -341, -341, -341, -341,
-     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
-     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
-     -341, -341, -341, -341, -341, -341, -341, -341
-    },
-
-    {
-       33, -342, -342, -342, -342, -342, -342, -342, -342, -342,
-     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
-     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
-     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
-
-     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
-     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
-     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
-     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
-     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
-     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
-     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
-     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
-     -342, -342, -342, -342, -342, -342, -342, -342
-    },
-
-    {
-       33, -343, -343, -343, -343, -343, -343, -343, -343, -343,
-
-     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
-     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
-     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
-     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
-     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
-     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
-     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
-     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
-     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
-     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
-
-     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
-     -343, -343, -343, -343, -343, -343, -343, -343
-    },
-
-    {
-       33, -344, -344, -344, -344, -344, -344, -344, -344, -344,
-     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
-     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
-     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
-     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
-     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
-     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
-     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
-
-     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
-     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
-     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
-     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
-     -344, -344, -344, -344, -344, -344, -344, -344
-    },
-
-    {
-       33, -345, -345, -345, -345, -345, -345, -345, -345, -345,
-     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
-     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
-     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
-     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
-
-     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
-     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
-     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
-     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
-     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
-     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
-     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
-     -345, -345, -345, -345, -345, -345, -345, -345
-    },
-
-    {
-       33, -346, -346, -346, -346, -346, -346, -346, -346, -346,
-     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
-
-     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
-     -346, -346,  359, -346, -346, -346, -346, -346, -346, -346,
-     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
-     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
-     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
-     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
-     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
-     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
-     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
-     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
-
-     -346, -346, -346, -346, -346, -346, -346, -346
-    },
-
-    {
-       33, -347, -347, -347, -347, -347, -347, -347, -347, -347,
-     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
-     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
-     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
-     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
-     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
-     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
-     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
-     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
-
-     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
-     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
-     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
-     -347, -347, -347, -347, -347, -347, -347, -347
-    },
-
-    {
-       33, -348, -348, -348, -348, -348, -348, -348, -348, -348,
-     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
-     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
-     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
-     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
-     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
-
-     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
-     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
-     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
-     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
-     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
-     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
-     -348, -348, -348, -348, -348, -348, -348, -348
-    },
-
-    {
-       33, -349, -349, -349, -349, -349, -349, -349, -349, -349,
-     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
-     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
-
-     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
-     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
-     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
-     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
-     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
-     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
-     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
-     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
-     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
-     -349, -349, -349, -349, -349, -349, -349, -349
-
-    },
-
-    {
-       33, -350, -350, -350, -350, -350, -350, -350, -350, -350,
-     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
-     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
-     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
-     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
-     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
-     -350,  360, -350, -350, -350, -350, -350, -350, -350, -350,
-     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
-     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
-     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
-
-     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
-     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
-     -350, -350, -350, -350, -350, -350, -350, -350
-    },
-
-    {
-       33, -351, -351, -351, -351, -351, -351, -351, -351, -351,
-     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
-     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
-     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
-     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
-     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
-     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
-
-     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
-     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
-     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
-     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
-     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
-     -351, -351, -351, -351, -351, -351, -351, -351
-    },
-
-    {
-       33, -352, -352, -352, -352, -352, -352, -352, -352, -352,
-     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
-     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
-     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
-
-     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
-     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
-     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
-     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
-     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
-     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
-     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
-     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
-     -352, -352, -352, -352, -352, -352, -352, -352
-    },
-
-    {
-       33, -353, -353, -353, -353, -353, -353, -353, -353, -353,
-
-     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
-     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
-     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
-     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
-     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
-     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
-     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
-     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
-     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
-     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
-
-     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
-     -353, -353, -353, -353, -353, -353, -353, -353
-    },
-
-    {
-       33, -354, -354, -354, -354, -354, -354, -354, -354, -354,
-     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
-     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
-     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
-     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
-     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
-     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
-     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
-
-     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
-     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
-     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
-     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
-     -354, -354, -354, -354, -354, -354, -354, -354
-    },
-
-    {
-       33, -355, -355, -355, -355, -355, -355, -355, -355, -355,
-     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
-     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
-     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
-     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
-
-     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
-     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
-     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
-     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
-     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
-     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
-     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
-     -355, -355, -355, -355, -355, -355, -355, -355
-    },
-
-    {
-       33, -356, -356, -356, -356, -356, -356, -356, -356, -356,
-     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
-
-     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
-     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
-     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
-     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
-     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
-     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
-     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
-     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
-     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
-     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
-
-     -356, -356, -356, -356, -356, -356, -356, -356
-    },
-
-    {
-       33, -357, -357, -357, -357, -357, -357, -357, -357, -357,
-     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
-     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
-     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
-     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
-     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
-     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
-     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
-     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
-
-     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
-     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
-     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
-     -357, -357, -357, -357, -357, -357, -357, -357
-    },
-
-    {
-       33, -358, -358, -358, -358, -358, -358, -358, -358, -358,
-     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
-     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
-     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
-     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
-     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
-
-     -358,  361, -358, -358, -358, -358, -358, -358, -358, -358,
-     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
-     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
-     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
-     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
-     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
-     -358, -358, -358, -358, -358, -358, -358, -358
-    },
-
-    {
-       33, -359, -359, -359, -359, -359, -359, -359, -359, -359,
-     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
-     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
-
-     -359, -359,  362, -359, -359, -359, -359, -359, -359, -359,
-     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
-     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
-     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
-     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
-     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
-     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
-     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
-     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
-     -359, -359, -359, -359, -359, -359, -359, -359
-
-    },
-
-    {
-       33, -360, -360, -360, -360, -360, -360, -360, -360, -360,
-     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
-     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
-     -360, -360,  363, -360, -360, -360, -360, -360, -360, -360,
-     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
-     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
-     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
-     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
-     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
-     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
-
-     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
-     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
-     -360, -360, -360, -360, -360, -360, -360, -360
-    },
-
-    {
-       33, -361, -361, -361, -361, -361, -361, -361, -361, -361,
-     -361, -361, -361, -361, -361, -361, -361, -361, -361, -361,
-     -361, -361, -361, -361, -361, -361, -361, -361, -361, -361,
-     -361, -361,  364, -361, -361, -361, -361, -361, -361, -361,
-     -361, -361, -361, -361, -361, -361, -361, -361, -361, -361,
-     -361, -361, -361, -361, -361, -361, -361, -361, -361, -361,
-     -361, -361, -361, -361, -361, -361, -361, -361, -361, -361,
-
-     -361, -361, -361, -361, -361, -361, -361, -361, -361, -361,
-     -361, -361, -361, -361, -361, -361, -361, -361, -361, -361,
-     -361, -361, -361, -361, -361, -361, -361, -361, -361, -361,
-     -361, -361, -361, -361, -361, -361, -361, -361, -361, -361,
-     -361, -361, -361, -361, -361, -361, -361, -361, -361, -361,
-     -361, -361, -361, -361, -361, -361, -361, -361
-    },
-
-    {
-       33, -362, -362, -362, -362, -362, -362, -362, -362, -362,
-     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
-     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
-     -362, -362,  365, -362, -362, -362, -362, -362, -362, -362,
-
-     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
-     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
-     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
-     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
-     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
-     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
-     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
-     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
-     -362, -362, -362, -362, -362, -362, -362, -362
-    },
-
-    {
-       33, -363, -363, -363, -363, -363, -363, -363, -363, -363,
-
-     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
-     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
-     -363, -363,  366, -363, -363, -363, -363, -363, -363, -363,
-     -363, -363, -363,  367, -363,  367, -363, -363,  368,  368,
-      368,  368,  368,  368,  368,  368,  368,  368, -363, -363,
-     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
-     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
-     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
-     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
-     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
-
-     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
-     -363, -363, -363, -363, -363, -363, -363, -363
-    },
-
-    {
-       33, -364, -364, -364, -364, -364, -364, -364, -364, -364,
-     -364, -364, -364, -364, -364, -364, -364, -364, -364, -364,
-     -364, -364, -364, -364, -364, -364, -364, -364, -364, -364,
-     -364, -364,  369, -364, -364, -364, -364, -364, -364, -364,
-     -364, -364, -364,  370, -364,  370, -364, -364,  371,  371,
-      371,  371,  371,  371,  371,  371,  371,  371, -364, -364,
-     -364, -364, -364, -364, -364, -364, -364, -364, -364, -364,
-     -364, -364, -364, -364, -364, -364, -364, -364, -364, -364,
-
-     -364, -364, -364, -364, -364, -364, -364, -364, -364, -364,
-     -364, -364, -364, -364, -364, -364, -364, -364, -364, -364,
-     -364, -364, -364, -364, -364, -364, -364, -364, -364, -364,
-     -364, -364, -364, -364, -364, -364, -364, -364, -364, -364,
-     -364, -364, -364, -364, -364, -364, -364, -364
-    },
-
-    {
-       33, -365, -365, -365, -365, -365, -365, -365, -365, -365,
-     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
-     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
-     -365, -365,  372, -365, -365, -365, -365, -365, -365, -365,
-     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
-
-     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
-     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
-     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
-     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
-     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
-     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
-     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
-     -365, -365, -365, -365, -365, -365, -365, -365
-    },
-
-    {
-       33, -366, -366, -366, -366, -366, -366, -366, -366, -366,
-     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
-
-     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
-     -366, -366,  366, -366, -366, -366, -366, -366, -366, -366,
-     -366, -366, -366,  367, -366,  367, -366, -366,  368,  368,
-      368,  368,  368,  368,  368,  368,  368,  368, -366, -366,
-     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
-     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
-     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
-     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
-     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
-     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
-
-     -366, -366, -366, -366, -366, -366, -366, -366
-    },
-
-    {
-       33, -367, -367, -367, -367, -367, -367, -367, -367, -367,
-     -367, -367, -367, -367, -367, -367, -367, -367, -367, -367,
-     -367, -367, -367, -367, -367, -367, -367, -367, -367, -367,
-     -367, -367, -367, -367, -367, -367, -367, -367, -367, -367,
-     -367, -367, -367, -367, -367, -367, -367, -367,  368,  368,
-      368,  368,  368,  368,  368,  368,  368,  368, -367, -367,
-     -367, -367, -367, -367, -367, -367, -367, -367, -367, -367,
-     -367, -367, -367, -367, -367, -367, -367, -367, -367, -367,
-     -367, -367, -367, -367, -367, -367, -367, -367, -367, -367,
-
-     -367, -367, -367, -367, -367, -367, -367, -367, -367, -367,
-     -367, -367, -367, -367, -367, -367, -367, -367, -367, -367,
-     -367, -367, -367, -367, -367, -367, -367, -367, -367, -367,
-     -367, -367, -367, -367, -367, -367, -367, -367
-    },
-
-    {
-       33, -368, -368, -368, -368, -368, -368, -368, -368, -368,
-     -368, -368, -368, -368, -368, -368, -368, -368, -368, -368,
-     -368, -368, -368, -368, -368, -368, -368, -368, -368, -368,
-     -368, -368, -368, -368, -368, -368, -368, -368, -368, -368,
-     -368, -368, -368, -368, -368, -368, -368, -368,  368,  368,
-      368,  368,  368,  368,  368,  368,  368,  368, -368, -368,
-
-     -368, -368, -368, -368, -368, -368, -368, -368, -368, -368,
-     -368, -368, -368, -368, -368, -368, -368, -368, -368, -368,
-     -368, -368, -368, -368, -368, -368, -368, -368, -368, -368,
-     -368, -368, -368, -368, -368, -368, -368, -368, -368, -368,
-     -368, -368, -368, -368, -368, -368, -368, -368, -368, -368,
-     -368, -368, -368, -368, -368, -368, -368, -368, -368, -368,
-     -368, -368, -368, -368, -368, -368, -368, -368
-    },
-
-    {
-       33, -369, -369, -369, -369, -369, -369, -369, -369, -369,
-     -369, -369, -369, -369, -369, -369, -369, -369, -369, -369,
-     -369, -369, -369, -369, -369, -369, -369, -369, -369, -369,
-
-     -369, -369,  369, -369, -369, -369, -369, -369, -369, -369,
-     -369, -369, -369,  370, -369,  370, -369, -369,  371,  371,
-      371,  371,  371,  371,  371,  371,  371,  371, -369, -369,
-     -369, -369, -369, -369, -369, -369, -369, -369, -369, -369,
-     -369, -369, -369, -369, -369, -369, -369, -369, -369, -369,
-     -369, -369, -369, -369, -369, -369, -369, -369, -369, -369,
-     -369, -369, -369, -369, -369, -369, -369, -369, -369, -369,
-     -369, -369, -369, -369, -369, -369, -369, -369, -369, -369,
-     -369, -369, -369, -369, -369, -369, -369, -369, -369, -369,
-     -369, -369, -369, -369, -369, -369, -369, -369
-
-    },
-
-    {
-       33, -370, -370, -370, -370, -370, -370, -370, -370, -370,
-     -370, -370, -370, -370, -370, -370, -370, -370, -370, -370,
-     -370, -370, -370, -370, -370, -370, -370, -370, -370, -370,
-     -370, -370, -370, -370, -370, -370, -370, -370, -370, -370,
-     -370, -370, -370, -370, -370, -370, -370, -370,  371,  371,
-      371,  371,  371,  371,  371,  371,  371,  371, -370, -370,
-     -370, -370, -370, -370, -370, -370, -370, -370, -370, -370,
-     -370, -370, -370, -370, -370, -370, -370, -370, -370, -370,
-     -370, -370, -370, -370, -370, -370, -370, -370, -370, -370,
-     -370, -370, -370, -370, -370, -370, -370, -370, -370, -370,
-
-     -370, -370, -370, -370, -370, -370, -370, -370, -370, -370,
-     -370, -370, -370, -370, -370, -370, -370, -370, -370, -370,
-     -370, -370, -370, -370, -370, -370, -370, -370
-    },
-
-    {
-       33, -371, -371, -371, -371, -371, -371, -371, -371, -371,
-     -371, -371, -371, -371, -371, -371, -371, -371, -371, -371,
-     -371, -371, -371, -371, -371, -371, -371, -371, -371, -371,
-     -371, -371, -371, -371, -371, -371, -371, -371, -371, -371,
-     -371, -371, -371, -371, -371, -371, -371, -371,  371,  371,
-      371,  371,  371,  371,  371,  371,  371,  371, -371, -371,
-     -371, -371, -371, -371, -371, -371, -371, -371, -371, -371,
-
-     -371, -371, -371, -371, -371, -371, -371, -371, -371, -371,
-     -371, -371, -371, -371, -371, -371, -371, -371, -371, -371,
-     -371, -371, -371, -371, -371, -371, -371, -371, -371, -371,
-     -371, -371, -371, -371, -371, -371, -371, -371, -371, -371,
-     -371, -371, -371, -371, -371, -371, -371, -371, -371, -371,
-     -371, -371, -371, -371, -371, -371, -371, -371
-    },
-
-    {
-       33, -372, -372, -372, -372, -372, -372, -372, -372, -372,
-     -372, -372, -372, -372, -372, -372, -372, -372, -372, -372,
-     -372, -372, -372, -372, -372, -372, -372, -372, -372, -372,
-     -372, -372,  373, -372, -372, -372, -372, -372, -372, -372,
-
-     -372, -372, -372, -372, -372, -372, -372, -372, -372, -372,
-     -372, -372, -372, -372, -372, -372, -372, -372, -372, -372,
-     -372, -372, -372, -372, -372, -372, -372, -372, -372, -372,
-     -372, -372, -372, -372, -372, -372, -372, -372, -372, -372,
-     -372, -372, -372, -372, -372, -372, -372, -372, -372, -372,
-     -372, -372, -372, -372, -372, -372, -372, -372, -372, -372,
-     -372, -372, -372, -372, -372, -372, -372, -372, -372, -372,
-     -372, -372, -372, -372, -372, -372, -372, -372, -372, -372,
-     -372, -372, -372, -372, -372, -372, -372, -372
-    },
-
-    {
-       33, -373, -373, -373, -373, -373, -373, -373, -373, -373,
-
-     -373, -373, -373, -373, -373, -373, -373, -373, -373, -373,
-     -373, -373, -373, -373, -373, -373, -373, -373, -373, -373,
-     -373, -373,  374, -373, -373, -373, -373, -373, -373, -373,
-     -373, -373, -373, -373, -373, -373, -373, -373, -373, -373,
-     -373, -373, -373, -373, -373, -373, -373, -373, -373, -373,
-     -373, -373, -373, -373, -373, -373, -373, -373, -373, -373,
-     -373, -373, -373, -373, -373, -373, -373, -373, -373, -373,
-     -373, -373, -373, -373, -373, -373, -373, -373, -373, -373,
-     -373, -373, -373, -373, -373, -373, -373, -373, -373, -373,
-     -373, -373, -373, -373, -373, -373, -373, -373, -373, -373,
-
-     -373, -373, -373, -373, -373, -373, -373, -373, -373, -373,
-     -373, -373, -373, -373, -373, -373, -373, -373
-    },
-
-    {
-       33, -374, -374, -374, -374, -374, -374, -374, -374, -374,
-     -374, -374, -374, -374, -374, -374, -374, -374, -374, -374,
-     -374, -374, -374, -374, -374, -374, -374, -374, -374, -374,
-     -374, -374,  375, -374, -374, -374, -374, -374, -374, -374,
-     -374, -374, -374, -374, -374, -374, -374, -374, -374, -374,
-     -374, -374, -374, -374, -374, -374, -374, -374, -374, -374,
-     -374, -374, -374, -374, -374, -374, -374, -374, -374, -374,
-     -374, -374, -374, -374, -374, -374, -374, -374, -374, -374,
-
-     -374, -374, -374, -374, -374, -374, -374, -374, -374, -374,
-     -374, -374, -374, -374, -374, -374, -374, -374, -374, -374,
-     -374, -374, -374, -374, -374, -374, -374, -374, -374, -374,
-     -374, -374, -374, -374, -374, -374, -374, -374, -374, -374,
-     -374, -374, -374, -374, -374, -374, -374, -374
-    },
-
-    {
-       33, -375, -375, -375, -375, -375, -375, -375, -375, -375,
-     -375, -375, -375, -375, -375, -375, -375, -375, -375, -375,
-     -375, -375, -375, -375, -375, -375, -375, -375, -375, -375,
-     -375, -375,  376, -375, -375, -375, -375, -375, -375, -375,
-     -375, -375, -375, -375, -375, -375, -375, -375, -375, -375,
-
-     -375, -375, -375, -375, -375, -375, -375, -375, -375, -375,
-     -375, -375, -375, -375, -375, -375, -375, -375, -375, -375,
-     -375, -375, -375, -375, -375, -375, -375, -375, -375, -375,
-     -375, -375, -375, -375, -375, -375, -375, -375, -375, -375,
-     -375, -375, -375, -375, -375, -375, -375, -375, -375, -375,
-     -375, -375, -375, -375, -375, -375, -375, -375, -375, -375,
-     -375, -375, -375, -375, -375, -375, -375, -375, -375, -375,
-     -375, -375, -375, -375, -375, -375, -375, -375
-    },
-
-    {
-       33, -376, -376, -376, -376, -376, -376, -376, -376, -376,
-     -376, -376, -376, -376, -376, -376, -376, -376, -376, -376,
-
-     -376, -376, -376, -376, -376, -376, -376, -376, -376, -376,
-     -376, -376,  377, -376, -376, -376, -376, -376, -376, -376,
-     -376, -376, -376, -376, -376, -376, -376, -376, -376, -376,
-     -376, -376, -376, -376, -376, -376, -376, -376, -376, -376,
-     -376, -376, -376, -376, -376, -376, -376, -376, -376, -376,
-     -376, -376, -376, -376, -376, -376, -376, -376, -376, -376,
-     -376, -376, -376, -376, -376, -376, -376, -376, -376, -376,
-     -376, -376, -376, -376, -376, -376, -376, -376, -376, -376,
-     -376, -376, -376, -376, -376, -376, -376, -376, -376, -376,
-     -376, -376, -376, -376, -376, -376, -376, -376, -376, -376,
-
-     -376, -376, -376, -376, -376, -376, -376, -376
-    },
-
-    {
-       33, -377, -377, -377, -377, -377, -377, -377, -377, -377,
-     -377, -377, -377, -377, -377, -377, -377, -377, -377, -377,
-     -377, -377, -377, -377, -377, -377, -377, -377, -377, -377,
-     -377, -377,  378, -377, -377, -377, -377, -377, -377, -377,
-     -377, -377, -377, -377, -377, -377, -377, -377, -377, -377,
-     -377, -377, -377, -377, -377, -377, -377, -377, -377, -377,
-     -377, -377, -377, -377, -377, -377, -377, -377, -377, -377,
-     -377, -377, -377, -377, -377, -377, -377, -377, -377, -377,
-     -377, -377, -377, -377, -377, -377, -377, -377, -377, -377,
-
-     -377, -377, -377, -377, -377, -377, -377, -377, -377, -377,
-     -377, -377, -377, -377, -377, -377, -377, -377, -377, -377,
-     -377, -377, -377, -377, -377, -377, -377, -377, -377, -377,
-     -377, -377, -377, -377, -377, -377, -377, -377
-    },
-
-    {
-       33, -378, -378, -378, -378, -378, -378, -378, -378, -378,
-     -378, -378, -378, -378, -378, -378, -378, -378, -378, -378,
-     -378, -378, -378, -378, -378, -378, -378, -378, -378, -378,
-     -378, -378,  379, -378, -378, -378, -378, -378, -378, -378,
-     -378, -378, -378, -378, -378, -378, -378, -378, -378, -378,
-     -378, -378, -378, -378, -378, -378, -378, -378, -378, -378,
-
-     -378, -378, -378, -378, -378, -378, -378, -378, -378, -378,
-     -378, -378, -378, -378, -378, -378, -378, -378, -378, -378,
-     -378, -378, -378, -378, -378, -378, -378, -378, -378, -378,
-     -378, -378, -378, -378, -378, -378, -378, -378, -378, -378,
-     -378, -378, -378, -378, -378, -378, -378, -378, -378, -378,
-     -378, -378, -378, -378, -378, -378, -378, -378, -378, -378,
-     -378, -378, -378, -378, -378, -378, -378, -378
-    },
-
-    {
-       33, -379, -379, -379, -379, -379, -379, -379, -379, -379,
-     -379, -379, -379, -379, -379, -379, -379, -379, -379, -379,
-     -379, -379, -379, -379, -379, -379, -379, -379, -379, -379,
-
-     -379, -379,  380, -379, -379, -379, -379, -379, -379, -379,
-     -379, -379, -379, -379, -379, -379, -379, -379, -379, -379,
-     -379, -379, -379, -379, -379, -379, -379, -379, -379, -379,
-     -379, -379, -379, -379, -379, -379, -379, -379, -379, -379,
-     -379, -379, -379, -379, -379, -379, -379, -379, -379, -379,
-     -379, -379, -379, -379, -379, -379, -379, -379, -379, -379,
-     -379, -379, -379, -379, -379, -379, -379, -379, -379, -379,
-     -379, -379, -379, -379, -379, -379, -379, -379, -379, -379,
-     -379, -379, -379, -379, -379, -379, -379, -379, -379, -379,
-     -379, -379, -379, -379, -379, -379, -379, -379
-
-    },
-
-    {
-       33, -380, -380, -380, -380, -380, -380, -380, -380, -380,
-     -380, -380, -380, -380, -380, -380, -380, -380, -380, -380,
-     -380, -380, -380, -380, -380, -380, -380, -380, -380, -380,
-     -380, -380,  381, -380, -380, -380, -380, -380, -380, -380,
-     -380, -380, -380, -380, -380, -380, -380, -380, -380, -380,
-     -380, -380, -380, -380, -380, -380, -380, -380, -380, -380,
-     -380, -380, -380, -380, -380, -380, -380, -380, -380, -380,
-     -380, -380, -380, -380, -380, -380, -380, -380, -380, -380,
-     -380, -380, -380, -380, -380, -380, -380, -380, -380, -380,
-     -380, -380, -380, -380, -380, -380, -380, -380, -380, -380,
-
-     -380, -380, -380, -380, -380, -380, -380, -380, -380, -380,
-     -380, -380, -380, -380, -380, -380, -380, -380, -380, -380,
-     -380, -380, -380, -380, -380, -380, -380, -380
-    },
-
-    {
-       33, -381, -381, -381, -381, -381, -381, -381, -381, -381,
-     -381, -381, -381, -381, -381, -381, -381, -381, -381, -381,
-     -381, -381, -381, -381, -381, -381, -381, -381, -381, -381,
-     -381, -381,  382, -381, -381, -381, -381, -381, -381, -381,
-     -381, -381, -381, -381, -381, -381, -381, -381, -381, -381,
-     -381, -381, -381, -381, -381, -381, -381, -381, -381, -381,
-     -381, -381, -381, -381, -381, -381, -381, -381, -381, -381,
-
-     -381, -381, -381, -381, -381, -381, -381, -381, -381, -381,
-     -381, -381, -381, -381, -381, -381, -381, -381, -381, -381,
-     -381, -381, -381, -381, -381, -381, -381, -381, -381, -381,
-     -381, -381, -381, -381, -381, -381, -381, -381, -381, -381,
-     -381, -381, -381, -381, -381, -381, -381, -381, -381, -381,
-     -381, -381, -381, -381, -381, -381, -381, -381
-    },
-
-    {
-       33, -382, -382, -382, -382, -382, -382, -382, -382, -382,
-     -382, -382, -382, -382, -382, -382, -382, -382, -382, -382,
-     -382, -382, -382, -382, -382, -382, -382, -382, -382, -382,
-     -382, -382,  383, -382, -382, -382, -382, -382, -382, -382,
-
-     -382, -382, -382, -382, -382, -382, -382, -382, -382, -382,
-     -382, -382, -382, -382, -382, -382, -382, -382, -382, -382,
-     -382, -382, -382, -382, -382, -382, -382, -382, -382, -382,
-     -382, -382, -382, -382, -382, -382, -382, -382, -382, -382,
-     -382, -382, -382, -382, -382, -382, -382, -382, -382, -382,
-     -382, -382, -382, -382, -382, -382, -382, -382, -382, -382,
-     -382, -382, -382, -382, -382, -382, -382, -382, -382, -382,
-     -382, -382, -382, -382, -382, -382, -382, -382, -382, -382,
-     -382, -382, -382, -382, -382, -382, -382, -382
-    },
-
-    {
-       33, -383, -383, -383, -383, -383, -383, -383, -383, -383,
-
-     -383, -383, -383, -383, -383, -383, -383, -383, -383, -383,
-     -383, -383, -383, -383, -383, -383, -383, -383, -383, -383,
-     -383, -383,  384, -383, -383, -383, -383, -383, -383, -383,
-     -383, -383, -383, -383, -383, -383, -383, -383, -383, -383,
-     -383, -383, -383, -383, -383, -383, -383, -383, -383, -383,
-     -383, -383, -383, -383, -383, -383, -383, -383, -383, -383,
-     -383, -383, -383, -383, -383, -383, -383, -383, -383, -383,
-     -383, -383, -383, -383, -383, -383, -383, -383, -383, -383,
-     -383, -383, -383, -383, -383, -383, -383, -383, -383, -383,
-     -383, -383, -383, -383, -383, -383, -383, -383, -383, -383,
-
-     -383, -383, -383, -383, -383, -383, -383, -383, -383, -383,
-     -383, -383, -383, -383, -383, -383, -383, -383
-    },
-
-    {
-       33, -384, -384, -384, -384, -384, -384, -384, -384, -384,
-     -384, -384, -384, -384, -384, -384, -384, -384, -384, -384,
-     -384, -384, -384, -384, -384, -384, -384, -384, -384, -384,
-     -384, -384,  385, -384, -384, -384, -384, -384, -384, -384,
-     -384, -384, -384, -384, -384, -384, -384, -384, -384, -384,
-     -384, -384, -384, -384, -384, -384, -384, -384, -384, -384,
-     -384, -384, -384, -384, -384, -384, -384, -384, -384, -384,
-     -384, -384, -384, -384, -384, -384, -384, -384, -384, -384,
-
-     -384, -384, -384, -384, -384, -384, -384, -384, -384, -384,
-     -384, -384, -384, -384, -384, -384, -384, -384, -384, -384,
-     -384, -384, -384, -384, -384, -384, -384, -384, -384, -384,
-     -384, -384, -384, -384, -384, -384, -384, -384, -384, -384,
-     -384, -384, -384, -384, -384, -384, -384, -384
-    },
-
-    {
-       33, -385, -385, -385, -385, -385, -385, -385, -385, -385,
-     -385, -385, -385, -385, -385, -385, -385, -385, -385, -385,
-     -385, -385, -385, -385, -385, -385, -385, -385, -385, -385,
-     -385, -385,  386, -385, -385, -385, -385, -385, -385, -385,
-     -385, -385, -385, -385, -385, -385, -385, -385, -385, -385,
-
-     -385, -385, -385, -385, -385, -385, -385, -385, -385, -385,
-     -385, -385, -385, -385, -385, -385, -385, -385, -385, -385,
-     -385, -385, -385, -385, -385, -385, -385, -385, -385, -385,
-     -385, -385, -385, -385, -385, -385, -385, -385, -385, -385,
-     -385, -385, -385, -385, -385, -385, -385, -385, -385, -385,
-     -385, -385, -385, -385, -385, -385, -385, -385, -385, -385,
-     -385, -385, -385, -385, -385, -385, -385, -385, -385, -385,
-     -385, -385, -385, -385, -385, -385, -385, -385
-    },
-
-    {
-       33, -386, -386, -386, -386, -386, -386, -386, -386, -386,
-     -386, -386, -386, -386, -386, -386, -386, -386, -386, -386,
-
-     -386, -386, -386, -386, -386, -386, -386, -386, -386, -386,
-     -386, -386,  387, -386, -386, -386, -386, -386, -386, -386,
-     -386, -386, -386, -386, -386, -386, -386, -386, -386, -386,
-     -386, -386, -386, -386, -386, -386, -386, -386, -386, -386,
-     -386, -386, -386, -386, -386, -386, -386, -386, -386, -386,
-     -386, -386, -386, -386, -386, -386, -386, -386, -386, -386,
-     -386, -386, -386, -386, -386, -386, -386, -386, -386, -386,
-     -386, -386, -386, -386, -386, -386, -386, -386, -386, -386,
-     -386, -386, -386, -386, -386, -386, -386, -386, -386, -386,
-     -386, -386, -386, -386, -386, -386, -386, -386, -386, -386,
-
-     -386, -386, -386, -386, -386, -386, -386, -386
-    },
-
-    {
-       33, -387, -387, -387, -387, -387, -387, -387, -387, -387,
-     -387, -387, -387, -387, -387, -387, -387, -387, -387, -387,
-     -387, -387, -387, -387, -387, -387, -387, -387, -387, -387,
-     -387, -387,  388, -387, -387, -387, -387, -387, -387, -387,
-     -387, -387, -387, -387, -387, -387, -387, -387, -387, -387,
-     -387, -387, -387, -387, -387, -387, -387, -387, -387, -387,
-     -387, -387, -387, -387, -387, -387, -387, -387, -387, -387,
-     -387, -387, -387, -387, -387, -387, -387, -387, -387, -387,
-     -387, -387, -387, -387, -387, -387, -387, -387, -387, -387,
-
-     -387, -387, -387, -387, -387, -387, -387, -387, -387, -387,
-     -387, -387, -387, -387, -387, -387, -387, -387, -387, -387,
-     -387, -387, -387, -387, -387, -387, -387, -387, -387, -387,
-     -387, -387, -387, -387, -387, -387, -387, -387
-    },
-
-    {
-       33, -388, -388, -388, -388, -388, -388, -388, -388, -388,
-     -388, -388, -388, -388, -388, -388, -388, -388, -388, -388,
-     -388, -388, -388, -388, -388, -388, -388, -388, -388, -388,
-     -388, -388,  389, -388, -388, -388, -388, -388, -388, -388,
-     -388, -388, -388, -388, -388, -388, -388, -388, -388, -388,
-     -388, -388, -388, -388, -388, -388, -388, -388, -388, -388,
-
-     -388, -388, -388, -388, -388, -388, -388, -388, -388, -388,
-     -388, -388, -388, -388, -388, -388, -388, -388, -388, -388,
-     -388, -388, -388, -388, -388, -388, -388, -388, -388, -388,
-     -388, -388, -388, -388, -388, -388, -388, -388, -388, -388,
-     -388, -388, -388, -388, -388, -388, -388, -388, -388, -388,
-     -388, -388, -388, -388, -388, -388, -388, -388, -388, -388,
-     -388, -388, -388, -388, -388, -388, -388, -388
-    },
-
-    {
-       33, -389, -389, -389, -389, -389, -389, -389, -389, -389,
-     -389, -389, -389, -389, -389, -389, -389, -389, -389, -389,
-     -389, -389, -389, -389, -389, -389, -389, -389, -389, -389,
-
-     -389, -389,  390, -389, -389, -389, -389, -389, -389, -389,
-     -389, -389, -389, -389, -389, -389, -389, -389, -389, -389,
-     -389, -389, -389, -389, -389, -389, -389, -389, -389, -389,
-     -389, -389, -389, -389, -389, -389, -389, -389, -389, -389,
-     -389, -389, -389, -389, -389, -389, -389, -389, -389, -389,
-     -389, -389, -389, -389, -389, -389, -389, -389, -389, -389,
-     -389, -389, -389, -389, -389, -389, -389, -389, -389, -389,
-     -389, -389, -389, -389, -389, -389, -389, -389, -389, -389,
-     -389, -389, -389, -389, -389, -389, -389, -389, -389, -389,
-     -389, -389, -389, -389, -389, -389, -389, -389
-
-    },
-
-    {
-       33, -390, -390, -390, -390, -390, -390, -390, -390, -390,
-     -390, -390, -390, -390, -390, -390, -390, -390, -390, -390,
-     -390, -390, -390, -390, -390, -390, -390, -390, -390, -390,
-     -390, -390,  391, -390, -390, -390, -390, -390, -390, -390,
-     -390, -390, -390, -390, -390, -390, -390, -390, -390, -390,
-     -390, -390, -390, -390, -390, -390, -390, -390, -390, -390,
-     -390, -390, -390, -390, -390, -390, -390, -390, -390, -390,
-     -390, -390, -390, -390, -390, -390, -390, -390, -390, -390,
-     -390, -390, -390, -390, -390, -390, -390, -390, -390, -390,
-     -390, -390, -390, -390, -390, -390, -390, -390, -390, -390,
-
-     -390, -390, -390, -390, -390, -390, -390, -390, -390, -390,
-     -390, -390, -390, -390, -390, -390, -390, -390, -390, -390,
-     -390, -390, -390, -390, -390, -390, -390, -390
-    },
-
-    {
-       33, -391, -391, -391, -391, -391, -391, -391, -391, -391,
-     -391, -391, -391, -391, -391, -391, -391, -391, -391, -391,
-     -391, -391, -391, -391, -391, -391, -391, -391, -391, -391,
-     -391, -391,  392, -391, -391, -391, -391, -391, -391, -391,
-     -391, -391, -391, -391, -391, -391, -391, -391, -391, -391,
-     -391, -391, -391, -391, -391, -391, -391, -391, -391, -391,
-     -391, -391, -391, -391, -391, -391, -391, -391, -391, -391,
-
-     -391, -391, -391, -391, -391, -391, -391, -391, -391, -391,
-     -391, -391, -391, -391, -391, -391, -391, -391, -391, -391,
-     -391, -391, -391, -391, -391, -391, -391, -391, -391, -391,
-     -391, -391, -391, -391, -391, -391, -391, -391, -391, -391,
-     -391, -391, -391, -391, -391, -391, -391, -391, -391, -391,
-     -391, -391, -391, -391, -391, -391, -391, -391
-    },
-
-    {
-       33, -392, -392, -392, -392, -392, -392, -392, -392, -392,
-     -392, -392, -392, -392, -392, -392, -392, -392, -392, -392,
-     -392, -392, -392, -392, -392, -392, -392, -392, -392, -392,
-     -392, -392,  393, -392, -392, -392, -392, -392, -392, -392,
-
-     -392, -392, -392, -392, -392, -392, -392, -392, -392, -392,
-     -392, -392, -392, -392, -392, -392, -392, -392, -392, -392,
-     -392, -392, -392, -392, -392, -392, -392, -392, -392, -392,
-     -392, -392, -392, -392, -392, -392, -392, -392, -392, -392,
-     -392, -392, -392, -392, -392, -392, -392, -392, -392, -392,
-     -392, -392, -392, -392, -392, -392, -392, -392, -392, -392,
-     -392, -392, -392, -392, -392, -392, -392, -392, -392, -392,
-     -392, -392, -392, -392, -392, -392, -392, -392, -392, -392,
-     -392, -392, -392, -392, -392, -392, -392, -392
-    },
-
-    {
-       33, -393, -393, -393, -393, -393, -393, -393, -393, -393,
-
-     -393, -393, -393, -393, -393, -393, -393, -393, -393, -393,
-     -393, -393, -393, -393, -393, -393, -393, -393, -393, -393,
-     -393, -393,  394, -393, -393, -393, -393, -393, -393, -393,
-     -393, -393, -393, -393, -393, -393, -393, -393, -393, -393,
-     -393, -393, -393, -393, -393, -393, -393, -393, -393, -393,
-     -393, -393, -393, -393, -393, -393, -393, -393, -393, -393,
-     -393, -393, -393, -393, -393, -393, -393, -393, -393, -393,
-     -393, -393, -393, -393, -393, -393, -393, -393, -393, -393,
-     -393, -393, -393, -393, -393, -393, -393, -393, -393, -393,
-     -393, -393, -393, -393, -393, -393, -393, -393, -393, -393,
-
-     -393, -393, -393, -393, -393, -393, -393, -393, -393, -393,
-     -393, -393, -393, -393, -393, -393, -393, -393
-    },
-
-    {
-       33, -394, -394, -394, -394, -394, -394, -394, -394, -394,
-     -394, -394, -394, -394, -394, -394, -394, -394, -394, -394,
-     -394, -394, -394, -394, -394, -394, -394, -394, -394, -394,
-     -394, -394,  395, -394, -394, -394, -394, -394, -394, -394,
-     -394, -394, -394, -394, -394, -394, -394, -394, -394, -394,
-     -394, -394, -394, -394, -394, -394, -394, -394, -394, -394,
-     -394, -394, -394, -394, -394, -394, -394, -394, -394, -394,
-     -394, -394, -394, -394, -394, -394, -394, -394, -394, -394,
-
-     -394, -394, -394, -394, -394, -394, -394, -394, -394, -394,
-     -394, -394, -394, -394, -394, -394, -394, -394, -394, -394,
-     -394, -394, -394, -394, -394, -394, -394, -394, -394, -394,
-     -394, -394, -394, -394, -394, -394, -394, -394, -394, -394,
-     -394, -394, -394, -394, -394, -394, -394, -394
-    },
-
-    {
-       33, -395, -395, -395, -395, -395, -395, -395, -395, -395,
-     -395, -395, -395, -395, -395, -395, -395, -395, -395, -395,
-     -395, -395, -395, -395, -395, -395, -395, -395, -395, -395,
-     -395, -395,  396, -395, -395, -395, -395, -395, -395, -395,
-     -395, -395, -395, -395, -395, -395, -395, -395, -395, -395,
-
-     -395, -395, -395, -395, -395, -395, -395, -395, -395, -395,
-     -395, -395, -395, -395, -395, -395, -395, -395, -395, -395,
-     -395, -395, -395, -395, -395, -395, -395, -395, -395, -395,
-     -395, -395, -395, -395, -395, -395, -395, -395, -395, -395,
-     -395, -395, -395, -395, -395, -395, -395, -395, -395, -395,
-     -395, -395, -395, -395, -395, -395, -395, -395, -395, -395,
-     -395, -395, -395, -395, -395, -395, -395, -395, -395, -395,
-     -395, -395, -395, -395, -395, -395, -395, -395
-    },
-
-    {
-       33, -396, -396, -396, -396, -396, -396, -396, -396, -396,
-     -396, -396, -396, -396, -396, -396, -396, -396, -396, -396,
-
-     -396, -396, -396, -396, -396, -396, -396, -396, -396, -396,
-     -396, -396,  397, -396, -396, -396, -396, -396, -396, -396,
-     -396, -396, -396, -396, -396, -396, -396, -396, -396, -396,
-     -396, -396, -396, -396, -396, -396, -396, -396, -396, -396,
-     -396, -396, -396, -396, -396, -396, -396, -396, -396, -396,
-     -396, -396, -396, -396, -396, -396, -396, -396, -396, -396,
-     -396, -396, -396, -396, -396, -396, -396, -396, -396, -396,
-     -396, -396, -396, -396, -396, -396, -396, -396, -396, -396,
-     -396, -396, -396, -396, -396, -396, -396, -396, -396, -396,
-     -396, -396, -396, -396, -396, -396, -396, -396, -396, -396,
-
-     -396, -396, -396, -396, -396, -396, -396, -396
-    },
-
-    {
-       33, -397, -397, -397, -397, -397, -397, -397, -397, -397,
-     -397, -397, -397, -397, -397, -397, -397, -397, -397, -397,
-     -397, -397, -397, -397, -397, -397, -397, -397, -397, -397,
-     -397, -397,  398, -397, -397, -397, -397, -397, -397, -397,
-     -397, -397, -397, -397, -397, -397, -397, -397, -397, -397,
-     -397, -397, -397, -397, -397, -397, -397, -397, -397, -397,
-     -397, -397, -397, -397, -397, -397, -397, -397, -397, -397,
-     -397, -397, -397, -397, -397, -397, -397, -397, -397, -397,
-     -397, -397, -397, -397, -397, -397, -397, -397, -397, -397,
-
-     -397, -397, -397, -397, -397, -397, -397, -397, -397, -397,
-     -397, -397, -397, -397, -397, -397, -397, -397, -397, -397,
-     -397, -397, -397, -397, -397, -397, -397, -397, -397, -397,
-     -397, -397, -397, -397, -397, -397, -397, -397
-    },
-
-    {
-       33, -398, -398, -398, -398, -398, -398, -398, -398, -398,
-     -398, -398, -398, -398, -398, -398, -398, -398, -398, -398,
-     -398, -398, -398, -398, -398, -398, -398, -398, -398, -398,
-     -398, -398,  399, -398, -398, -398, -398, -398, -398, -398,
-     -398, -398, -398, -398, -398, -398, -398, -398, -398, -398,
-     -398, -398, -398, -398, -398, -398, -398, -398, -398, -398,
-
-     -398, -398, -398, -398, -398, -398, -398, -398, -398, -398,
-     -398, -398, -398, -398, -398, -398, -398, -398, -398, -398,
-     -398, -398, -398, -398, -398, -398, -398, -398, -398, -398,
-     -398, -398, -398, -398, -398, -398, -398, -398, -398, -398,
-     -398, -398, -398, -398, -398, -398, -398, -398, -398, -398,
-     -398, -398, -398, -398, -398, -398, -398, -398, -398, -398,
-     -398, -398, -398, -398, -398, -398, -398, -398
-    },
-
-    {
-       33, -399, -399, -399, -399, -399, -399, -399, -399, -399,
-     -399, -399, -399, -399, -399, -399, -399, -399, -399, -399,
-     -399, -399, -399, -399, -399, -399, -399, -399, -399, -399,
-
-     -399, -399,  400, -399, -399, -399, -399, -399, -399, -399,
-     -399, -399, -399, -399, -399, -399, -399, -399, -399, -399,
-     -399, -399, -399, -399, -399, -399, -399, -399, -399, -399,
-     -399, -399, -399, -399, -399, -399, -399, -399, -399, -399,
-     -399, -399, -399, -399, -399, -399, -399, -399, -399, -399,
-     -399, -399, -399, -399, -399, -399, -399, -399, -399, -399,
-     -399, -399, -399, -399, -399, -399, -399, -399, -399, -399,
-     -399, -399, -399, -399, -399, -399, -399, -399, -399, -399,
-     -399, -399, -399, -399, -399, -399, -399, -399, -399, -399,
-     -399, -399, -399, -399, -399, -399, -399, -399
-
-    },
-
-    {
-       33, -400, -400, -400, -400, -400, -400, -400, -400, -400,
-     -400, -400, -400, -400, -400, -400, -400, -400, -400, -400,
-     -400, -400, -400, -400, -400, -400, -400, -400, -400, -400,
-     -400, -400,  401, -400, -400, -400, -400, -400, -400, -400,
-     -400, -400, -400, -400, -400, -400, -400, -400, -400, -400,
-     -400, -400, -400, -400, -400, -400, -400, -400, -400, -400,
-     -400, -400, -400, -400, -400, -400, -400, -400, -400, -400,
-     -400, -400, -400, -400, -400, -400, -400, -400, -400, -400,
-     -400, -400, -400, -400, -400, -400, -400, -400, -400, -400,
-     -400, -400, -400, -400, -400, -400, -400, -400, -400, -400,
-
-     -400, -400, -400, -400, -400, -400, -400, -400, -400, -400,
-     -400, -400, -400, -400, -400, -400, -400, -400, -400, -400,
-     -400, -400, -400, -400, -400, -400, -400, -400
-    },
-
-    {
-       33, -401, -401, -401, -401, -401, -401, -401, -401, -401,
-     -401, -401, -401, -401, -401, -401, -401, -401, -401, -401,
-     -401, -401, -401, -401, -401, -401, -401, -401, -401, -401,
-     -401, -401,  402, -401, -401, -401, -401, -401, -401, -401,
-     -401, -401, -401, -401, -401, -401, -401, -401, -401, -401,
-     -401, -401, -401, -401, -401, -401, -401, -401, -401, -401,
-     -401, -401, -401, -401, -401, -401, -401, -401, -401, -401,
-
-     -401, -401, -401, -401, -401, -401, -401, -401, -401, -401,
-     -401, -401, -401, -401, -401, -401, -401, -401, -401, -401,
-     -401, -401, -401, -401, -401, -401, -401, -401, -401, -401,
-     -401, -401, -401, -401, -401, -401, -401, -401, -401, -401,
-     -401, -401, -401, -401, -401, -401, -401, -401, -401, -401,
-     -401, -401, -401, -401, -401, -401, -401, -401
-    },
-
-    {
-       33, -402, -402, -402, -402, -402, -402, -402, -402, -402,
-     -402, -402, -402, -402, -402, -402, -402, -402, -402, -402,
-     -402, -402, -402, -402, -402, -402, -402, -402, -402, -402,
-     -402, -402,  403, -402, -402, -402, -402, -402, -402, -402,
-
-     -402, -402, -402, -402, -402, -402, -402, -402, -402, -402,
-     -402, -402, -402, -402, -402, -402, -402, -402, -402, -402,
-     -402, -402, -402, -402, -402, -402, -402, -402, -402, -402,
-     -402, -402, -402, -402, -402, -402, -402, -402, -402, -402,
-     -402, -402, -402, -402, -402, -402, -402, -402, -402, -402,
-     -402, -402, -402, -402, -402, -402, -402, -402, -402, -402,
-     -402, -402, -402, -402, -402, -402, -402, -402, -402, -402,
-     -402, -402, -402, -402, -402, -402, -402, -402, -402, -402,
-     -402, -402, -402, -402, -402, -402, -402, -402
-    },
-
-    {
-       33, -403, -403, -403, -403, -403, -403, -403, -403, -403,
-
-     -403, -403, -403, -403, -403, -403, -403, -403, -403, -403,
-     -403, -403, -403, -403, -403, -403, -403, -403, -403, -403,
-     -403, -403,  404, -403, -403, -403, -403, -403, -403, -403,
-     -403, -403, -403, -403, -403, -403, -403, -403, -403, -403,
-     -403, -403, -403, -403, -403, -403, -403, -403, -403, -403,
-     -403, -403, -403, -403, -403, -403, -403, -403, -403, -403,
-     -403, -403, -403, -403, -403, -403, -403, -403, -403, -403,
-     -403, -403, -403, -403, -403, -403, -403, -403, -403, -403,
-     -403, -403, -403, -403, -403, -403, -403, -403, -403, -403,
-     -403, -403, -403, -403, -403, -403, -403, -403, -403, -403,
-
-     -403, -403, -403, -403, -403, -403, -403, -403, -403, -403,
-     -403, -403, -403, -403, -403, -403, -403, -403
-    },
-
-    {
-       33, -404, -404, -404, -404, -404, -404, -404, -404, -404,
-     -404, -404, -404, -404, -404, -404, -404, -404, -404, -404,
-     -404, -404, -404, -404, -404, -404, -404, -404, -404, -404,
-     -404, -404,  405, -404, -404, -404, -404, -404, -404, -404,
-     -404, -404, -404, -404, -404, -404, -404, -404, -404, -404,
-     -404, -404, -404, -404, -404, -404, -404, -404, -404, -404,
-     -404, -404, -404, -404, -404, -404, -404, -404, -404, -404,
-     -404, -404, -404, -404, -404, -404, -404, -404, -404, -404,
-
-     -404, -404, -404, -404, -404, -404, -404, -404, -404, -404,
-     -404, -404, -404, -404, -404, -404, -404, -404, -404, -404,
-     -404, -404, -404, -404, -404, -404, -404, -404, -404, -404,
-     -404, -404, -404, -404, -404, -404, -404, -404, -404, -404,
-     -404, -404, -404, -404, -404, -404, -404, -404
-    },
-
-    {
-       33, -405, -405, -405, -405, -405, -405, -405, -405, -405,
-     -405, -405, -405, -405, -405, -405, -405, -405, -405, -405,
-     -405, -405, -405, -405, -405, -405, -405, -405, -405, -405,
-     -405, -405,  406, -405, -405, -405, -405, -405, -405, -405,
-     -405, -405, -405, -405, -405, -405, -405, -405, -405, -405,
-
-     -405, -405, -405, -405, -405, -405, -405, -405, -405, -405,
-     -405, -405, -405, -405, -405, -405, -405, -405, -405, -405,
-     -405, -405, -405, -405, -405, -405, -405, -405, -405, -405,
-     -405, -405, -405, -405, -405, -405, -405, -405, -405, -405,
-     -405, -405, -405, -405, -405, -405, -405, -405, -405, -405,
-     -405, -405, -405, -405, -405, -405, -405, -405, -405, -405,
-     -405, -405, -405, -405, -405, -405, -405, -405, -405, -405,
-     -405, -405, -405, -405, -405, -405, -405, -405
-    },
-
-    {
-       33, -406, -406, -406, -406, -406, -406, -406, -406, -406,
-     -406, -406, -406, -406, -406, -406, -406, -406, -406, -406,
-
-     -406, -406, -406, -406, -406, -406, -406, -406, -406, -406,
-     -406, -406,  407, -406, -406, -406, -406, -406, -406, -406,
-     -406, -406, -406, -406, -406, -406, -406, -406, -406, -406,
-     -406, -406, -406, -406, -406, -406, -406, -406, -406, -406,
-     -406, -406, -406, -406, -406, -406, -406, -406, -406, -406,
-     -406, -406, -406, -406, -406, -406, -406, -406, -406, -406,
-     -406, -406, -406, -406, -406, -406, -406, -406, -406, -406,
-     -406, -406, -406, -406, -406, -406, -406, -406, -406, -406,
-     -406, -406, -406, -406, -406, -406, -406, -406, -406, -406,
-     -406, -406, -406, -406, -406, -406, -406, -406, -406, -406,
-
-     -406, -406, -406, -406, -406, -406, -406, -406
-    },
-
-    {
-       33, -407, -407, -407, -407, -407, -407, -407, -407, -407,
-     -407, -407, -407, -407, -407, -407, -407, -407, -407, -407,
-     -407, -407, -407, -407, -407, -407, -407, -407, -407, -407,
-     -407, -407,  408, -407, -407, -407, -407, -407, -407, -407,
-     -407, -407, -407, -407, -407, -407, -407, -407, -407, -407,
-     -407, -407, -407, -407, -407, -407, -407, -407, -407, -407,
-     -407, -407, -407, -407, -407, -407, -407, -407, -407, -407,
-     -407, -407, -407, -407, -407, -407, -407, -407, -407, -407,
-     -407, -407, -407, -407, -407, -407, -407, -407, -407, -407,
-
-     -407, -407, -407, -407, -407, -407, -407, -407, -407, -407,
-     -407, -407, -407, -407, -407, -407, -407, -407, -407, -407,
-     -407, -407, -407, -407, -407, -407, -407, -407, -407, -407,
-     -407, -407, -407, -407, -407, -407, -407, -407
-    },
-
-    {
-       33, -408, -408, -408, -408, -408, -408, -408, -408, -408,
-     -408, -408, -408, -408, -408, -408, -408, -408, -408, -408,
-     -408, -408, -408, -408, -408, -408, -408, -408, -408, -408,
-     -408, -408,  409, -408, -408, -408, -408, -408, -408, -408,
-     -408, -408, -408, -408, -408, -408, -408, -408, -408, -408,
-     -408, -408, -408, -408, -408, -408, -408, -408, -408, -408,
-
-     -408, -408, -408, -408, -408, -408, -408, -408, -408, -408,
-     -408, -408, -408, -408, -408, -408, -408, -408, -408, -408,
-     -408, -408, -408, -408, -408, -408, -408, -408, -408, -408,
-     -408, -408, -408, -408, -408, -408, -408, -408, -408, -408,
-     -408, -408, -408, -408, -408, -408, -408, -408, -408, -408,
-     -408, -408, -408, -408, -408, -408, -408, -408, -408, -408,
-     -408, -408, -408, -408, -408, -408, -408, -408
-    },
-
-    {
-       33, -409, -409, -409, -409, -409, -409, -409, -409, -409,
-     -409, -409, -409, -409, -409, -409, -409, -409, -409, -409,
-     -409, -409, -409, -409, -409, -409, -409, -409, -409, -409,
-
-     -409, -409,  410, -409, -409, -409, -409, -409, -409, -409,
-     -409, -409, -409, -409, -409, -409, -409, -409, -409, -409,
-     -409, -409, -409, -409, -409, -409, -409, -409, -409, -409,
-     -409, -409, -409, -409, -409, -409, -409, -409, -409, -409,
-     -409, -409, -409, -409, -409, -409, -409, -409, -409, -409,
-     -409, -409, -409, -409, -409, -409, -409, -409, -409, -409,
-     -409, -409, -409, -409, -409, -409, -409, -409, -409, -409,
-     -409, -409, -409, -409, -409, -409, -409, -409, -409, -409,
-     -409, -409, -409, -409, -409, -409, -409, -409, -409, -409,
-     -409, -409, -409, -409, -409, -409, -409, -409
-
-    },
-
-    {
-       33, -410, -410, -410, -410, -410, -410, -410, -410, -410,
-     -410, -410, -410, -410, -410, -410, -410, -410, -410, -410,
-     -410, -410, -410, -410, -410, -410, -410, -410, -410, -410,
-     -410, -410,  411, -410, -410, -410, -410, -410, -410, -410,
-     -410, -410, -410, -410, -410, -410, -410, -410, -410, -410,
-     -410, -410, -410, -410, -410, -410, -410, -410, -410, -410,
-     -410, -410, -410, -410, -410, -410, -410, -410, -410, -410,
-     -410, -410, -410, -410, -410, -410, -410, -410, -410, -410,
-     -410, -410, -410, -410, -410, -410, -410, -410, -410, -410,
-     -410, -410, -410, -410, -410, -410, -410, -410, -410, -410,
-
-     -410, -410, -410, -410, -410, -410, -410, -410, -410, -410,
-     -410, -410, -410, -410, -410, -410, -410, -410, -410, -410,
-     -410, -410, -410, -410, -410, -410, -410, -410
-    },
-
-    {
-       33, -411, -411, -411, -411, -411, -411, -411, -411, -411,
-     -411, -411, -411, -411, -411, -411, -411, -411, -411, -411,
-     -411, -411, -411, -411, -411, -411, -411, -411, -411, -411,
-     -411, -411,  412, -411, -411, -411, -411, -411, -411, -411,
-     -411, -411, -411, -411, -411, -411, -411, -411, -411, -411,
-     -411, -411, -411, -411, -411, -411, -411, -411, -411, -411,
-     -411, -411, -411, -411, -411, -411, -411, -411, -411, -411,
-
-     -411, -411, -411, -411, -411, -411, -411, -411, -411, -411,
-     -411, -411, -411, -411, -411, -411, -411, -411, -411, -411,
-     -411, -411, -411, -411, -411, -411, -411, -411, -411, -411,
-     -411, -411, -411, -411, -411, -411, -411, -411, -411, -411,
-     -411, -411, -411, -411, -411, -411, -411, -411, -411, -411,
-     -411, -411, -411, -411, -411, -411, -411, -411
-    },
-
-    {
-       33, -412, -412, -412, -412, -412, -412, -412, -412, -412,
-     -412, -412, -412, -412, -412, -412, -412, -412, -412, -412,
-     -412, -412, -412, -412, -412, -412, -412, -412, -412, -412,
-     -412, -412,  413, -412, -412, -412, -412, -412, -412, -412,
-
-     -412, -412, -412, -412, -412, -412, -412, -412, -412, -412,
-     -412, -412, -412, -412, -412, -412, -412, -412, -412, -412,
-     -412, -412, -412, -412, -412, -412, -412, -412, -412, -412,
-     -412, -412, -412, -412, -412, -412, -412, -412, -412, -412,
-     -412, -412, -412, -412, -412, -412, -412, -412, -412, -412,
-     -412, -412, -412, -412, -412, -412, -412, -412, -412, -412,
-     -412, -412, -412, -412, -412, -412, -412, -412, -412, -412,
-     -412, -412, -412, -412, -412, -412, -412, -412, -412, -412,
-     -412, -412, -412, -412, -412, -412, -412, -412
-    },
-
-    {
-       33, -413, -413, -413, -413, -413, -413, -413, -413, -413,
-
-     -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
-     -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
-     -413, -413,  414, -413, -413, -413, -413, -413, -413, -413,
-     -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
-     -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
-     -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
-     -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
-     -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
-     -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
-     -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
-
-     -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
-     -413, -413, -413, -413, -413, -413, -413, -413
-    },
-
-    {
-       33, -414, -414, -414, -414, -414, -414, -414, -414, -414,
-     -414, -414, -414, -414, -414, -414, -414, -414, -414, -414,
-     -414, -414, -414, -414, -414, -414, -414, -414, -414, -414,
-     -414, -414,  415, -414, -414, -414, -414, -414, -414, -414,
-     -414, -414, -414, -414, -414, -414, -414, -414, -414, -414,
-     -414, -414, -414, -414, -414, -414, -414, -414, -414, -414,
-     -414, -414, -414, -414, -414, -414, -414, -414, -414, -414,
-     -414, -414, -414, -414, -414, -414, -414, -414, -414, -414,
-
-     -414, -414, -414, -414, -414, -414, -414, -414, -414, -414,
-     -414, -414, -414, -414, -414, -414, -414, -414, -414, -414,
-     -414, -414, -414, -414, -414, -414, -414, -414, -414, -414,
-     -414, -414, -414, -414, -414, -414, -414, -414, -414, -414,
-     -414, -414, -414, -414, -414, -414, -414, -414
-    },
-
-    {
-       33, -415, -415, -415, -415, -415, -415, -415, -415, -415,
-     -415, -415, -415, -415, -415, -415, -415, -415, -415, -415,
-     -415, -415, -415, -415, -415, -415, -415, -415, -415, -415,
-     -415, -415,  416, -415, -415, -415, -415, -415, -415, -415,
-     -415, -415, -415, -415, -415, -415, -415, -415, -415, -415,
-
-     -415, -415, -415, -415, -415, -415, -415, -415, -415, -415,
-     -415, -415, -415, -415, -415, -415, -415, -415, -415, -415,
-     -415, -415, -415, -415, -415, -415, -415, -415, -415, -415,
-     -415, -415, -415, -415, -415, -415, -415, -415, -415, -415,
-     -415, -415, -415, -415, -415, -415, -415, -415, -415, -415,
-     -415, -415, -415, -415, -415, -415, -415, -415, -415, -415,
-     -415, -415, -415, -415, -415, -415, -415, -415, -415, -415,
-     -415, -415, -415, -415, -415, -415, -415, -415
-    },
-
-    {
-       33, -416, -416, -416, -416, -416, -416, -416, -416, -416,
-     -416, -416, -416, -416, -416, -416, -416, -416, -416, -416,
-
-     -416, -416, -416, -416, -416, -416, -416, -416, -416, -416,
-     -416, -416,  417, -416, -416, -416, -416, -416, -416, -416,
-     -416, -416, -416, -416, -416, -416, -416, -416, -416, -416,
-     -416, -416, -416, -416, -416, -416, -416, -416, -416, -416,
-     -416, -416, -416, -416, -416, -416, -416, -416, -416, -416,
-     -416, -416, -416, -416, -416, -416, -416, -416, -416, -416,
-     -416, -416, -416, -416, -416, -416, -416, -416, -416, -416,
-     -416, -416, -416, -416, -416, -416, -416, -416, -416, -416,
-     -416, -416, -416, -416, -416, -416, -416, -416, -416, -416,
-     -416, -416, -416, -416, -416, -416, -416, -416, -416, -416,
-
-     -416, -416, -416, -416, -416, -416, -416, -416
-    },
-
-    {
-       33, -417, -417, -417, -417, -417, -417, -417, -417, -417,
-     -417, -417, -417, -417, -417, -417, -417, -417, -417, -417,
-     -417, -417, -417, -417, -417, -417, -417, -417, -417, -417,
-     -417, -417,  418, -417, -417, -417, -417, -417, -417, -417,
-     -417, -417, -417, -417, -417, -417, -417, -417, -417, -417,
-     -417, -417, -417, -417, -417, -417, -417, -417, -417, -417,
-     -417, -417, -417, -417, -417, -417, -417, -417, -417, -417,
-     -417, -417, -417, -417, -417, -417, -417, -417, -417, -417,
-     -417, -417, -417, -417, -417, -417, -417, -417, -417, -417,
-
-     -417, -417, -417, -417, -417, -417, -417, -417, -417, -417,
-     -417, -417, -417, -417, -417, -417, -417, -417, -417, -417,
-     -417, -417, -417, -417, -417, -417, -417, -417, -417, -417,
-     -417, -417, -417, -417, -417, -417, -417, -417
-    },
-
-    {
-       33, -418, -418, -418, -418, -418, -418, -418, -418, -418,
-     -418, -418, -418, -418, -418, -418, -418, -418, -418, -418,
-     -418, -418, -418, -418, -418, -418, -418, -418, -418, -418,
-     -418, -418,  419, -418, -418, -418, -418, -418, -418, -418,
-     -418, -418, -418, -418, -418, -418, -418, -418, -418, -418,
-     -418, -418, -418, -418, -418, -418, -418, -418, -418, -418,
-
-     -418, -418, -418, -418, -418, -418, -418, -418, -418, -418,
-     -418, -418, -418, -418, -418, -418, -418, -418, -418, -418,
-     -418, -418, -418, -418, -418, -418, -418, -418, -418, -418,
-     -418, -418, -418, -418, -418, -418, -418, -418, -418, -418,
-     -418, -418, -418, -418, -418, -418, -418, -418, -418, -418,
-     -418, -418, -418, -418, -418, -418, -418, -418, -418, -418,
-     -418, -418, -418, -418, -418, -418, -418, -418
-    },
-
-    {
-       33, -419, -419, -419, -419, -419, -419, -419, -419, -419,
-     -419, -419, -419, -419, -419, -419, -419, -419, -419, -419,
-     -419, -419, -419, -419, -419, -419, -419, -419, -419, -419,
-
-     -419, -419,  420, -419, -419, -419, -419, -419, -419, -419,
-     -419, -419, -419, -419, -419, -419, -419, -419, -419, -419,
-     -419, -419, -419, -419, -419, -419, -419, -419, -419, -419,
-     -419, -419, -419, -419, -419, -419, -419, -419, -419, -419,
-     -419, -419, -419, -419, -419, -419, -419, -419, -419, -419,
-     -419, -419, -419, -419, -419, -419, -419, -419, -419, -419,
-     -419, -419, -419, -419, -419, -419, -419, -419, -419, -419,
-     -419, -419, -419, -419, -419, -419, -419, -419, -419, -419,
-     -419, -419, -419, -419, -419, -419, -419, -419, -419, -419,
-     -419, -419, -419, -419, -419, -419, -419, -419
-
-    },
-
-    {
-       33, -420, -420, -420, -420, -420, -420, -420, -420, -420,
-     -420, -420, -420, -420, -420, -420, -420, -420, -420, -420,
-     -420, -420, -420, -420, -420, -420, -420, -420, -420, -420,
-     -420, -420,  421, -420, -420, -420, -420, -420, -420, -420,
-     -420, -420, -420, -420, -420, -420, -420, -420, -420, -420,
-     -420, -420, -420, -420, -420, -420, -420, -420, -420, -420,
-     -420, -420, -420, -420, -420, -420, -420, -420, -420, -420,
-     -420, -420, -420, -420, -420, -420, -420, -420, -420, -420,
-     -420, -420, -420, -420, -420, -420, -420, -420, -420, -420,
-     -420, -420, -420, -420, -420, -420, -420, -420, -420, -420,
-
-     -420, -420, -420, -420, -420, -420, -420, -420, -420, -420,
-     -420, -420, -420, -420, -420, -420, -420, -420, -420, -420,
-     -420, -420, -420, -420, -420, -420, -420, -420
-    },
-
-    {
-       33, -421, -421, -421, -421, -421, -421, -421, -421, -421,
-     -421, -421, -421, -421, -421, -421, -421, -421, -421, -421,
-     -421, -421, -421, -421, -421, -421, -421, -421, -421, -421,
-     -421, -421,  422, -421, -421, -421, -421, -421, -421, -421,
-     -421, -421, -421, -421, -421, -421, -421, -421, -421, -421,
-     -421, -421, -421, -421, -421, -421, -421, -421, -421, -421,
-     -421, -421, -421, -421, -421, -421, -421, -421, -421, -421,
-
-     -421, -421, -421, -421, -421, -421, -421, -421, -421, -421,
-     -421, -421, -421, -421, -421, -421, -421, -421, -421, -421,
-     -421, -421, -421, -421, -421, -421, -421, -421, -421, -421,
-     -421, -421, -421, -421, -421, -421, -421, -421, -421, -421,
-     -421, -421, -421, -421, -421, -421, -421, -421, -421, -421,
-     -421, -421, -421, -421, -421, -421, -421, -421
-    },
-
-    {
-       33, -422, -422, -422, -422, -422, -422, -422, -422, -422,
-     -422, -422, -422, -422, -422, -422, -422, -422, -422, -422,
-     -422, -422, -422, -422, -422, -422, -422, -422, -422, -422,
-     -422, -422,  423, -422, -422, -422, -422, -422, -422, -422,
-
-     -422, -422, -422, -422, -422, -422, -422, -422, -422, -422,
-     -422, -422, -422, -422, -422, -422, -422, -422, -422, -422,
-     -422, -422, -422, -422, -422, -422, -422, -422, -422, -422,
-     -422, -422, -422, -422, -422, -422, -422, -422, -422, -422,
-     -422, -422, -422, -422, -422, -422, -422, -422, -422, -422,
-     -422, -422, -422, -422, -422, -422, -422, -422, -422, -422,
-     -422, -422, -422, -422, -422, -422, -422, -422, -422, -422,
-     -422, -422, -422, -422, -422, -422, -422, -422, -422, -422,
-     -422, -422, -422, -422, -422, -422, -422, -422
-    },
-
-    {
-       33, -423, -423, -423, -423, -423, -423, -423, -423, -423,
-
-     -423, -423, -423, -423, -423, -423, -423, -423, -423, -423,
-     -423, -423, -423, -423, -423, -423, -423, -423, -423, -423,
-     -423, -423,  424, -423, -423, -423, -423, -423, -423, -423,
-     -423, -423, -423, -423, -423, -423, -423, -423, -423, -423,
-     -423, -423, -423, -423, -423, -423, -423, -423, -423, -423,
-     -423, -423, -423, -423, -423, -423, -423, -423, -423, -423,
-     -423, -423, -423, -423, -423, -423, -423, -423, -423, -423,
-     -423, -423, -423, -423, -423, -423, -423, -423, -423, -423,
-     -423, -423, -423, -423, -423, -423, -423, -423, -423, -423,
-     -423, -423, -423, -423, -423, -423, -423, -423, -423, -423,
-
-     -423, -423, -423, -423, -423, -423, -423, -423, -423, -423,
-     -423, -423, -423, -423, -423, -423, -423, -423
-    },
-
-    {
-       33, -424, -424, -424, -424, -424, -424, -424, -424, -424,
-     -424, -424, -424, -424, -424, -424, -424, -424, -424, -424,
-     -424, -424, -424, -424, -424, -424, -424, -424, -424, -424,
-     -424, -424,  425, -424, -424, -424, -424, -424, -424, -424,
-     -424, -424, -424, -424, -424, -424, -424, -424, -424, -424,
-     -424, -424, -424, -424, -424, -424, -424, -424, -424, -424,
-     -424, -424, -424, -424, -424, -424, -424, -424, -424, -424,
-     -424, -424, -424, -424, -424, -424, -424, -424, -424, -424,
-
-     -424, -424, -424, -424, -424, -424, -424, -424, -424, -424,
-     -424, -424, -424, -424, -424, -424, -424, -424, -424, -424,
-     -424, -424, -424, -424, -424, -424, -424, -424, -424, -424,
-     -424, -424, -424, -424, -424, -424, -424, -424, -424, -424,
-     -424, -424, -424, -424, -424, -424, -424, -424
-    },
-
-    {
-       33, -425, -425, -425, -425, -425, -425, -425, -425, -425,
-     -425, -425, -425, -425, -425, -425, -425, -425, -425, -425,
-     -425, -425, -425, -425, -425, -425, -425, -425, -425, -425,
-     -425, -425,  426, -425, -425, -425, -425, -425, -425, -425,
-     -425, -425, -425, -425, -425, -425, -425, -425, -425, -425,
-
-     -425, -425, -425, -425, -425, -425, -425, -425, -425, -425,
-     -425, -425, -425, -425, -425, -425, -425, -425, -425, -425,
-     -425, -425, -425, -425, -425, -425, -425, -425, -425, -425,
-     -425, -425, -425, -425, -425, -425, -425, -425, -425, -425,
-     -425, -425, -425, -425, -425, -425, -425, -425, -425, -425,
-     -425, -425, -425, -425, -425, -425, -425, -425, -425, -425,
-     -425, -425, -425, -425, -425, -425, -425, -425, -425, -425,
-     -425, -425, -425, -425, -425, -425, -425, -425
-    },
-
-    {
-       33, -426, -426, -426, -426, -426, -426, -426, -426, -426,
-     -426, -426, -426, -426, -426, -426, -426, -426, -426, -426,
-
-     -426, -426, -426, -426, -426, -426, -426, -426, -426, -426,
-     -426, -426,  427, -426, -426, -426, -426, -426, -426, -426,
-     -426, -426, -426, -426, -426, -426, -426, -426, -426, -426,
-     -426, -426, -426, -426, -426, -426, -426, -426, -426, -426,
-     -426, -426, -426, -426, -426, -426, -426, -426, -426, -426,
-     -426, -426, -426, -426, -426, -426, -426, -426, -426, -426,
-     -426, -426, -426, -426, -426, -426, -426, -426, -426, -426,
-     -426, -426, -426, -426, -426, -426, -426, -426, -426, -426,
-     -426, -426, -426, -426, -426, -426, -426, -426, -426, -426,
-     -426, -426, -426, -426, -426, -426, -426, -426, -426, -426,
-
-     -426, -426, -426, -426, -426, -426, -426, -426
-    },
-
-    {
-       33, -427, -427, -427, -427, -427, -427, -427, -427, -427,
-     -427, -427, -427, -427, -427, -427, -427, -427, -427, -427,
-     -427, -427, -427, -427, -427, -427, -427, -427, -427, -427,
-     -427, -427,  428, -427, -427, -427, -427, -427, -427, -427,
-     -427, -427, -427, -427, -427, -427, -427, -427, -427, -427,
-     -427, -427, -427, -427, -427, -427, -427, -427, -427, -427,
-     -427, -427, -427, -427, -427, -427, -427, -427, -427, -427,
-     -427, -427, -427, -427, -427, -427, -427, -427, -427, -427,
-     -427, -427, -427, -427, -427, -427, -427, -427, -427, -427,
-
-     -427, -427, -427, -427, -427, -427, -427, -427, -427, -427,
-     -427, -427, -427, -427, -427, -427, -427, -427, -427, -427,
-     -427, -427, -427, -427, -427, -427, -427, -427, -427, -427,
-     -427, -427, -427, -427, -427, -427, -427, -427
-    },
-
-    {
-       33, -428, -428, -428, -428, -428, -428, -428, -428, -428,
-     -428, -428, -428, -428, -428, -428, -428, -428, -428, -428,
-     -428, -428, -428, -428, -428, -428, -428, -428, -428, -428,
-     -428, -428,  429, -428, -428, -428, -428, -428, -428, -428,
-     -428, -428, -428, -428, -428, -428, -428, -428, -428, -428,
-     -428, -428, -428, -428, -428, -428, -428, -428, -428, -428,
-
-     -428, -428, -428, -428, -428, -428, -428, -428, -428, -428,
-     -428, -428, -428, -428, -428, -428, -428, -428, -428, -428,
-     -428, -428, -428, -428, -428, -428, -428, -428, -428, -428,
-     -428, -428, -428, -428, -428, -428, -428, -428, -428, -428,
-     -428, -428, -428, -428, -428, -428, -428, -428, -428, -428,
-     -428, -428, -428, -428, -428, -428, -428, -428, -428, -428,
-     -428, -428, -428, -428, -428, -428, -428, -428
-    },
-
-    {
-       33, -429, -429, -429, -429, -429, -429, -429, -429, -429,
-     -429, -429, -429, -429, -429, -429, -429, -429, -429, -429,
-     -429, -429, -429, -429, -429, -429, -429, -429, -429, -429,
-
-     -429, -429,  430, -429, -429, -429, -429, -429, -429, -429,
-     -429, -429, -429, -429, -429, -429, -429, -429, -429, -429,
-     -429, -429, -429, -429, -429, -429, -429, -429, -429, -429,
-     -429, -429, -429, -429, -429, -429, -429, -429, -429, -429,
-     -429, -429, -429, -429, -429, -429, -429, -429, -429, -429,
-     -429, -429, -429, -429, -429, -429, -429, -429, -429, -429,
-     -429, -429, -429, -429, -429, -429, -429, -429, -429, -429,
-     -429, -429, -429, -429, -429, -429, -429, -429, -429, -429,
-     -429, -429, -429, -429, -429, -429, -429, -429, -429, -429,
-     -429, -429, -429, -429, -429, -429, -429, -429
-
-    },
-
-    {
-       33, -430, -430, -430, -430, -430, -430, -430, -430, -430,
-     -430, -430, -430, -430, -430, -430, -430, -430, -430, -430,
-     -430, -430, -430, -430, -430, -430, -430, -430, -430, -430,
-     -430, -430,  431, -430, -430, -430, -430, -430, -430, -430,
-     -430, -430, -430, -430, -430, -430, -430, -430, -430, -430,
-     -430, -430, -430, -430, -430, -430, -430, -430, -430, -430,
-     -430, -430, -430, -430, -430, -430, -430, -430, -430, -430,
-     -430, -430, -430, -430, -430, -430, -430, -430, -430, -430,
-     -430, -430, -430, -430, -430, -430, -430, -430, -430, -430,
-     -430, -430, -430, -430, -430, -430, -430, -430, -430, -430,
-
-     -430, -430, -430, -430, -430, -430, -430, -430, -430, -430,
-     -430, -430, -430, -430, -430, -430, -430, -430, -430, -430,
-     -430, -430, -430, -430, -430, -430, -430, -430
-    },
-
-    {
-       33, -431, -431, -431, -431, -431, -431, -431, -431, -431,
-     -431, -431, -431, -431, -431, -431, -431, -431, -431, -431,
-     -431, -431, -431, -431, -431, -431, -431, -431, -431, -431,
-     -431, -431,  432, -431, -431, -431, -431, -431, -431, -431,
-     -431, -431, -431, -431, -431, -431, -431, -431, -431, -431,
-     -431, -431, -431, -431, -431, -431, -431, -431, -431, -431,
-     -431, -431, -431, -431, -431, -431, -431, -431, -431, -431,
-
-     -431, -431, -431, -431, -431, -431, -431, -431, -431, -431,
-     -431, -431, -431, -431, -431, -431, -431, -431, -431, -431,
-     -431, -431, -431, -431, -431, -431, -431, -431, -431, -431,
-     -431, -431, -431, -431, -431, -431, -431, -431, -431, -431,
-     -431, -431, -431, -431, -431, -431, -431, -431, -431, -431,
-     -431, -431, -431, -431, -431, -431, -431, -431
-    },
-
-    {
-       33, -432, -432, -432, -432, -432, -432, -432, -432, -432,
-     -432, -432, -432, -432, -432, -432, -432, -432, -432, -432,
-     -432, -432, -432, -432, -432, -432, -432, -432, -432, -432,
-     -432, -432,  433, -432, -432, -432, -432, -432, -432, -432,
-
-     -432, -432, -432, -432, -432, -432, -432, -432, -432, -432,
-     -432, -432, -432, -432, -432, -432, -432, -432, -432, -432,
-     -432, -432, -432, -432, -432, -432, -432, -432, -432, -432,
-     -432, -432, -432, -432, -432, -432, -432, -432, -432, -432,
-     -432, -432, -432, -432, -432, -432, -432, -432, -432, -432,
-     -432, -432, -432, -432, -432, -432, -432, -432, -432, -432,
-     -432, -432, -432, -432, -432, -432, -432, -432, -432, -432,
-     -432, -432, -432, -432, -432, -432, -432, -432, -432, -432,
-     -432, -432, -432, -432, -432, -432, -432, -432
-    },
-
-    {
-       33, -433, -433, -433, -433, -433, -433, -433, -433, -433,
-
-     -433, -433, -433, -433, -433, -433, -433, -433, -433, -433,
-     -433, -433, -433, -433, -433, -433, -433, -433, -433, -433,
-     -433, -433,  434, -433, -433, -433, -433, -433, -433, -433,
-     -433, -433, -433, -433, -433, -433, -433, -433, -433, -433,
-     -433, -433, -433, -433, -433, -433, -433, -433, -433, -433,
-     -433, -433, -433, -433, -433, -433, -433, -433, -433, -433,
-     -433, -433, -433, -433, -433, -433, -433, -433, -433, -433,
-     -433, -433, -433, -433, -433, -433, -433, -433, -433, -433,
-     -433, -433, -433, -433, -433, -433, -433, -433, -433, -433,
-     -433, -433, -433, -433, -433, -433, -433, -433, -433, -433,
-
-     -433, -433, -433, -433, -433, -433, -433, -433, -433, -433,
-     -433, -433, -433, -433, -433, -433, -433, -433
-    },
-
-    {
-       33, -434, -434, -434, -434, -434, -434, -434, -434, -434,
-     -434, -434, -434, -434, -434, -434, -434, -434, -434, -434,
-     -434, -434, -434, -434, -434, -434, -434, -434, -434, -434,
-     -434, -434,  435, -434, -434, -434, -434, -434, -434, -434,
-     -434, -434, -434, -434, -434, -434, -434, -434, -434, -434,
-     -434, -434, -434, -434, -434, -434, -434, -434, -434, -434,
-     -434, -434, -434, -434, -434, -434, -434, -434, -434, -434,
-     -434, -434, -434, -434, -434, -434, -434, -434, -434, -434,
-
-     -434, -434, -434, -434, -434, -434, -434, -434, -434, -434,
-     -434, -434, -434, -434, -434, -434, -434, -434, -434, -434,
-     -434, -434, -434, -434, -434, -434, -434, -434, -434, -434,
-     -434, -434, -434, -434, -434, -434, -434, -434, -434, -434,
-     -434, -434, -434, -434, -434, -434, -434, -434
-    },
-
-    {
-       33, -435, -435, -435, -435, -435, -435, -435, -435, -435,
-     -435, -435, -435, -435, -435, -435, -435, -435, -435, -435,
-     -435, -435, -435, -435, -435, -435, -435, -435, -435, -435,
-     -435, -435,  436, -435, -435, -435, -435, -435, -435, -435,
-     -435, -435, -435, -435, -435, -435, -435, -435, -435, -435,
-
-     -435, -435, -435, -435, -435, -435, -435, -435, -435, -435,
-     -435, -435, -435, -435, -435, -435, -435, -435, -435, -435,
-     -435, -435, -435, -435, -435, -435, -435, -435, -435, -435,
-     -435, -435, -435, -435, -435, -435, -435, -435, -435, -435,
-     -435, -435, -435, -435, -435, -435, -435, -435, -435, -435,
-     -435, -435, -435, -435, -435, -435, -435, -435, -435, -435,
-     -435, -435, -435, -435, -435, -435, -435, -435, -435, -435,
-     -435, -435, -435, -435, -435, -435, -435, -435
-    },
-
-    {
-       33, -436, -436, -436, -436, -436, -436, -436, -436, -436,
-     -436, -436, -436, -436, -436, -436, -436, -436, -436, -436,
-
-     -436, -436, -436, -436, -436, -436, -436, -436, -436, -436,
-     -436, -436,  437, -436, -436, -436, -436, -436, -436, -436,
-     -436, -436, -436, -436, -436, -436, -436, -436, -436, -436,
-     -436, -436, -436, -436, -436, -436, -436, -436, -436, -436,
-     -436, -436, -436, -436, -436, -436, -436, -436, -436, -436,
-     -436, -436, -436, -436, -436, -436, -436, -436, -436, -436,
-     -436, -436, -436, -436, -436, -436, -436, -436, -436, -436,
-     -436, -436, -436, -436, -436, -436, -436, -436, -436, -436,
-     -436, -436, -436, -436, -436, -436, -436, -436, -436, -436,
-     -436, -436, -436, -436, -436, -436, -436, -436, -436, -436,
-
-     -436, -436, -436, -436, -436, -436, -436, -436
-    },
-
-    {
-       33, -437, -437, -437, -437, -437, -437, -437, -437, -437,
-     -437, -437, -437, -437, -437, -437, -437, -437, -437, -437,
-     -437, -437, -437, -437, -437, -437, -437, -437, -437, -437,
-     -437, -437,  438, -437, -437, -437, -437, -437, -437, -437,
-     -437, -437, -437, -437, -437, -437, -437, -437, -437, -437,
-     -437, -437, -437, -437, -437, -437, -437, -437, -437, -437,
-     -437, -437, -437, -437, -437, -437, -437, -437, -437, -437,
-     -437, -437, -437, -437, -437, -437, -437, -437, -437, -437,
-     -437, -437, -437, -437, -437, -437, -437, -437, -437, -437,
-
-     -437, -437, -437, -437, -437, -437, -437, -437, -437, -437,
-     -437, -437, -437, -437, -437, -437, -437, -437, -437, -437,
-     -437, -437, -437, -437, -437, -437, -437, -437, -437, -437,
-     -437, -437, -437, -437, -437, -437, -437, -437
-    },
-
-    {
-       33, -438, -438, -438, -438, -438, -438, -438, -438, -438,
-     -438, -438, -438, -438, -438, -438, -438, -438, -438, -438,
-     -438, -438, -438, -438, -438, -438, -438, -438, -438, -438,
-     -438, -438,  439, -438, -438, -438, -438, -438, -438, -438,
-     -438, -438, -438, -438, -438, -438, -438, -438, -438, -438,
-     -438, -438, -438, -438, -438, -438, -438, -438, -438, -438,
-
-     -438, -438, -438, -438, -438, -438, -438, -438, -438, -438,
-     -438, -438, -438, -438, -438, -438, -438, -438, -438, -438,
-     -438, -438, -438, -438, -438, -438, -438, -438, -438, -438,
-     -438, -438, -438, -438, -438, -438, -438, -438, -438, -438,
-     -438, -438, -438, -438, -438, -438, -438, -438, -438, -438,
-     -438, -438, -438, -438, -438, -438, -438, -438, -438, -438,
-     -438, -438, -438, -438, -438, -438, -438, -438
-    },
-
-    {
-       33, -439, -439, -439, -439, -439, -439, -439, -439, -439,
-     -439, -439, -439, -439, -439, -439, -439, -439, -439, -439,
-     -439, -439, -439, -439, -439, -439, -439, -439, -439, -439,
-
-     -439, -439,  440, -439, -439, -439, -439, -439, -439, -439,
-     -439, -439, -439, -439, -439, -439, -439, -439, -439, -439,
-     -439, -439, -439, -439, -439, -439, -439, -439, -439, -439,
-     -439, -439, -439, -439, -439, -439, -439, -439, -439, -439,
-     -439, -439, -439, -439, -439, -439, -439, -439, -439, -439,
-     -439, -439, -439, -439, -439, -439, -439, -439, -439, -439,
-     -439, -439, -439, -439, -439, -439, -439, -439, -439, -439,
-     -439, -439, -439, -439, -439, -439, -439, -439, -439, -439,
-     -439, -439, -439, -439, -439, -439, -439, -439, -439, -439,
-     -439, -439, -439, -439, -439, -439, -439, -439
-
-    },
-
-    {
-       33, -440, -440, -440, -440, -440, -440, -440, -440, -440,
-     -440, -440, -440, -440, -440, -440, -440, -440, -440, -440,
-     -440, -440, -440, -440, -440, -440, -440, -440, -440, -440,
-     -440, -440, -440, -440, -440, -440, -440, -440, -440, -440,
-     -440, -440, -440, -440, -440, -440, -440, -440, -440, -440,
-     -440, -440, -440, -440, -440, -440, -440, -440, -440, -440,
-     -440, -440, -440, -440, -440, -440, -440, -440, -440, -440,
-     -440, -440, -440, -440, -440, -440, -440, -440, -440, -440,
-     -440, -440, -440, -440, -440, -440, -440, -440, -440, -440,
-     -440, -440, -440, -440, -440, -440, -440, -440, -440, -440,
-
-     -440, -440, -440, -440, -440, -440, -440, -440, -440, -440,
-     -440, -440, -440, -440, -440, -440, -440, -440, -440, -440,
-     -440, -440, -440, -440, -440, -440, -440, -440
-    },
-
-    } ;
-
-static yy_state_type yy_get_previous_state (void );
-static yy_state_type yy_try_NUL_trans (yy_state_type current_state  );
-static int yy_get_next_buffer (void );
-static void yy_fatal_error (yyconst char msg[]  );
-
-/* Done after the current pattern has been matched and before the
- * corresponding action - sets up wcspihtext.
- */
-#define YY_DO_BEFORE_ACTION \
-	(yytext_ptr) = yy_bp; \
-	wcspihleng = (size_t) (yy_cp - yy_bp); \
-	(yy_hold_char) = *yy_cp; \
-	*yy_cp = '\0'; \
-	(yy_c_buf_p) = yy_cp;
-
-#define YY_NUM_RULES 94
-#define YY_END_OF_BUFFER 95
-/* This struct is not used in this scanner,
-   but its presence is necessary. */
-struct yy_trans_info
-	{
-	flex_int32_t yy_verify;
-	flex_int32_t yy_nxt;
-	};
-static yyconst flex_int16_t yy_accept[441] =
-    {   0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,   89,   89,   91,   91,   92,   92,
-        0,    0,   95,   94,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   63,   63,
-       79,   79,   47,   47,   59,   59,   59,   77,   77,   66,
-       64,   65,   81,   81,   83,   83,   82,   85,   85,   85,
-       84,   87,   87,   90,   89,   88,   91,   92,   94,   93,
-        5,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    4,    0,   18,   16,    0,
-
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,   80,   82,    0,
-       84,   84,   84,   84,    0,    0,   86,   89,   88,   88,
-       91,   92,    0,   93,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,   60,   61,   62,   78,   44,   45,   46,    0,    0,
-        0,    0,    0,    0,    0,    0,   84,    0,   84,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    6,   19,   20,    7,    3,   10,   21,    9,    8,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-       17,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,   58,   57,   53,   56,
-
-       50,   51,   55,   48,   49,   52,   54,   76,   72,   75,
-       69,   70,   74,   67,   68,   71,   73,    0,    0,    0,
-        0,   25,   12,   11,    0,    0,    0,    0,    0,   31,
-        0,   13,   15,   33,   34,   35,   36,   37,    0,    0,
-        0,   40,   41,   22,   23,    0,   24,   26,   27,    0,
-       28,   29,   30,   32,   14,   38,   39,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    1,    0,    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,    0,    0,    0,    0,    0,    0,
-
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,   42
-    } ;
-
-static yy_state_type yy_last_accepting_state;
-static char *yy_last_accepting_cpos;
-
-static yyconst yy_state_type yy_NUL_trans[441] =
-    {   0,
-       34,   35,   49,   49,   51,   51,   53,   53,   55,   55,
-       58,   58,   60,   60,   62,   62,   63,   63,   65,   65,
-       68,   68,   72,   72,   74,   74,   77,   77,   78,   78,
-       79,   79,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,  126,    0,    0,  130,  131,  132,  133,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,  126,    0,    0,  130,  130,
-      131,  132,  133,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0
-    } ;
-
-extern int wcspih_flex_debug;
-int wcspih_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 yymore() yymore_used_but_not_detected
-#define YY_MORE_ADJ 0
-#define YY_RESTORE_YY_MORE_OFFSET
-char *wcspihtext;
-#line 1 "wcspih.l"
-/*============================================================================
-
-  WCSLIB 4.10 - an implementation of the FITS WCS standard.
-  Copyright (C) 1995-2012, Mark Calabretta
-
-  This file is part of WCSLIB.
-
-  WCSLIB is free software: you can redistribute it and/or modify it under the
-  terms of the GNU Lesser General Public License as published by the Free
-  Software Foundation, either version 3 of the License, or (at your option)
-  any later version.
-
-  WCSLIB 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 Lesser General Public License for
-  more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with WCSLIB.  If not, see <http://www.gnu.org/licenses/>.
-
-  Correspondence concerning WCSLIB may be directed to:
-    Internet email: mcalabre at atnf.csiro.au
-    Postal address: Dr. Mark Calabretta
-                    Australia Telescope National Facility, CSIRO
-                    PO Box 76
-                    Epping NSW 1710
-                    AUSTRALIA
-
-  Author: Mark Calabretta, Australia Telescope National Facility
-  http://www.atnf.csiro.au/~mcalabre/index.html
-  $Id: wcspih.c,v 4.10 2012/02/05 23:41:44 cal103 Exp $
-*=============================================================================
-*
-* wcspih.l is a Flex description file containing the definition of a lexical
-* scanner for parsing the WCS keyrecords from a FITS primary image or image
-* extension header.
-*
-* wcspih.l requires Flex v2.5.4 or later.  Refer to wcshdr.h for a description
-* of the user interface and operating notes.
-*
-* Implementation notes
-* --------------------
-* Use of the WCSAXESa keyword is not mandatory.  Its default value is "the
-* larger of NAXIS and the largest index of these keywords [i.e. CRPIXj, PCi_j
-* or CDi_j, CDELTi, CTYPEi, CRVALi, and CUNITi] found in the FITS header".
-* Consequently the definition of WCSAXESa effectively invalidates the use of
-* NAXIS for determining the number of coordinate axes and forces a preliminary
-* pass through the header to determine the "largest index" in headers where
-* WCSAXESa was omitted.
-*
-* Furthermore, since the use of WCSAXESa is optional, there is no way to
-* determine the number of coordinate representations (the "a" value) other
-* than by parsing all of the WCS keywords in the header; even if WCSAXESa was
-* specified for some representations it cannot be known in advance whether it
-* was specified for all of those present in the header.
-*
-* Hence the definition of WCSAXESa forces the scanner to be implemented in two
-* passes.  The first pass is used to determine the number of coordinate
-* representations (up to 27) and the number of coordinate axes in each.
-* Effectively WCSAXESa is ignored unless it exceeds the "largest index" in
-* which case the keywords for the extra axes assume their default values.  The
-* number of PVi_ma and PSi_ma keywords in each representation is also counted
-* in the first pass.
-*
-* On completion of the first pass, memory is allocated for an array of the
-* required number of wcsprm structs and each of these is initialized
-* appropriately.  These structs are filled in the second pass.
-*
-* The parser does not check for duplicated keywords, it accepts the last
-* encountered.
-*
-*===========================================================================*/
-/* Options. */
-/* Indices for parameterized keywords. */
-/* Alternate coordinate system identifier. */
-/* Keyvalue data types. */
-/* Exclusive start states. */
-
-
-
-
-
-
-#line 105 "wcspih.l"
-#include <math.h>
-#include <setjmp.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "wcs.h"
-#include "wcshdr.h"
-#include "wcsmath.h"
-
-#define INTEGER 0
-#define FLOAT   1
-#define STRING  2
-
-#define YY_DECL int wcspih(char *header, int nkeyrec, int relax, int ctrl, \
-                           int *nreject, int *nwcs, struct wcsprm **wcs)
-
-#define YY_INPUT(inbuff, count, bufsize) \
-	{ \
-	  if (wcspih_nkeyrec) { \
-	    strncpy(inbuff, wcspih_hdr, 80); \
-	    inbuff[80] = '\n'; \
-	    wcspih_hdr += 80; \
-	    wcspih_nkeyrec--; \
-	    count = 81; \
-	  } else { \
-	    count = YY_NULL; \
-	  } \
-	}
-
-/* These global variables are required by YY_INPUT. */
-char *wcspih_hdr;
-int  wcspih_nkeyrec;
-
-int wcspih_final(int alts[], double epoch[], double vsource[], int *nwcs,
-        struct wcsprm **wcs);
-int wcspih_inits(int naxis, int alts[], int npv[], int nps[], int *nwcs,
-        struct wcsprm **wcs);
-void wcspih_naxes(int naxis, int i, int j, char a, int alts[], int *npptr);
-
-/* Used in preempting the call to exit() by yy_fatal_error(). */
-jmp_buf wcspih_abort_jmp_env;
-#define exit(status) longjmp(wcspih_abort_jmp_env, status)
-
-#line 8283 "wcspih.c"
-
-#define INITIAL 0
-#define CROTAi 1
-#define PROJPn 2
-#define CCCCCia 3
-#define CCi_ja 4
-#define CCi_ma 5
-#define CCCCCCCa 6
-#define CCCCCCCC 7
-#define VALUE 8
-#define INTEGER_VAL 9
-#define FLOAT_VAL 10
-#define STRING_VAL 11
-#define COMMENT 12
-#define DISCARD 13
-#define ERROR 14
-#define FLUSH 15
-
-#ifndef YY_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 <unistd.h>
-#endif
-
-#ifndef YY_EXTRA_TYPE
-#define YY_EXTRA_TYPE void *
-#endif
-
-static int yy_init_globals (void );
-
-/* Accessor methods to globals.
-   These are made visible to non-reentrant scanners for convenience. */
-
-int wcspihlex_destroy (void );
-
-int wcspihget_debug (void );
-
-void wcspihset_debug (int debug_flag  );
-
-YY_EXTRA_TYPE wcspihget_extra (void );
-
-void wcspihset_extra (YY_EXTRA_TYPE user_defined  );
-
-FILE *wcspihget_in (void );
-
-void wcspihset_in  (FILE * in_str  );
-
-FILE *wcspihget_out (void );
-
-void wcspihset_out  (FILE * out_str  );
-
-int wcspihget_leng (void );
-
-char *wcspihget_text (void );
-
-int wcspihget_lineno (void );
-
-void wcspihset_lineno (int line_number  );
-
-/* Macros after this point can all be overridden by user definitions in
- * section 1.
- */
-
-#ifndef YY_SKIP_YYWRAP
-#ifdef __cplusplus
-extern "C" int wcspihwrap (void );
-#else
-extern int wcspihwrap (void );
-#endif
-#endif
-
-    static void yyunput (int c,char *buf_ptr  );
-    
-#ifndef yytext_ptr
-static void yy_flex_strncpy (char *,yyconst char *,int );
-#endif
-
-#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * );
-#endif
-
-#ifndef YY_NO_INPUT
-
-#ifdef __cplusplus
-static int yyinput (void );
-#else
-static int input (void );
-#endif
-
-#endif
-
-/* Amount of stuff to slurp up with each read. */
-#ifndef YY_READ_BUF_SIZE
-#ifdef __ia64__
-/* On IA-64, the buffer size is 16k, not 8k */
-#define YY_READ_BUF_SIZE 16384
-#else
-#define YY_READ_BUF_SIZE 8192
-#endif /* __ia64__ */
-#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( wcspihtext, wcspihleng, 1, wcspihout )) {} } while (0)
-#endif
-
-/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
- * is returned in "result".
- */
-#ifndef YY_INPUT
-#define YY_INPUT(buf,result,max_size) \
-	errno=0; \
-	while ( (result = read( fileno(wcspihin), (char *) buf, max_size )) < 0 ) \
-	{ \
-		if( errno != EINTR) \
-		{ \
-			YY_FATAL_ERROR( "input in flex scanner failed" ); \
-			break; \
-		} \
-		errno=0; \
-		clearerr(wcspihin); \
-	}\
-\
-
-#endif
-
-/* No semi-colon after return; correct usage is to write "yyterminate();" -
- * we don't want an extra ';' after the "return" because that will cause
- * some compilers to complain about unreachable statements.
- */
-#ifndef yyterminate
-#define yyterminate() return YY_NULL
-#endif
-
-/* Number of entries by which start-condition stack grows. */
-#ifndef YY_START_STACK_INCR
-#define YY_START_STACK_INCR 25
-#endif
-
-/* Report a fatal error. */
-#ifndef YY_FATAL_ERROR
-#define YY_FATAL_ERROR(msg) yy_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 YY_DECL
-#define YY_DECL_IS_OURS 1
-
-extern int wcspihlex (void);
-
-#define YY_DECL int wcspihlex (void)
-#endif /* !YY_DECL */
-
-/* Code executed at the beginning of each rule, after wcspihtext and wcspihleng
- * have been set up.
- */
-#ifndef YY_USER_ACTION
-#define YY_USER_ACTION
-#endif
-
-/* Code executed at the end of each rule. */
-#ifndef YY_BREAK
-#define YY_BREAK break;
-#endif
-
-#define YY_RULE_SETUP \
-	if ( wcspihleng > 0 ) \
-		YY_CURRENT_BUFFER_LVALUE->yy_at_bol = \
-				(wcspihtext[wcspihleng - 1] == '\n'); \
-	YY_USER_ACTION
-
-/** The main scanner function which does all the work.
- */
-YY_DECL
-{
-	register yy_state_type yy_current_state;
-	register char *yy_cp, *yy_bp;
-	register int yy_act;
-    
-#line 151 "wcspih.l"
-
-	/* Keyword indices, as used in the WCS papers, e.g. PCi_ja, PVi_ma. */
-	char a;
-	int  i, j, m;
-	
-	char *cptr, *errmsg, errtxt[80], *hptr, *keep;
-	int  altlin, alts[27], ialt, idx, ipx, ix, jx, naxis, *npptr,
-	     nps[27], npv[27], pass, status, valtype, voff;
-	double epoch[27], vsource[27];
-	void *vptr, *wptr;
-	struct wcsprm *wcsp;
-	int wcspihlex_destroy(void);
-	
-	naxis = 0;
-	for (ialt = 0; ialt < 27; ialt++) {
-	  alts[ialt] = 0;
-	  npv[ialt] = 0;
-	  nps[ialt] = 0;
-	  epoch[ialt]   = UNDEFINED;
-	  vsource[ialt] = UNDEFINED;
-	}
-	
-	/* Parameters used to implement YY_INPUT. */
-	wcspih_hdr = header;
-	wcspih_nkeyrec = nkeyrec;
-	
-	/* Our handle on the input stream. */
-	hptr = header;
-	keep = 0x0;
-	*nreject = 0;
-	
-	/* Keyword parameters. */
-	i = j = m = 0;
-	a = ' ';
-	
-	/* For decoding the keyvalue. */
-	valtype = -1;
-	idx     = -1;
-	vptr    = 0x0;
-	
-	/* For keywords that require special handling. */
-	altlin = 0;
-	npptr  = 0x0;
-	
-	/* The data structures produced. */
-	*nwcs = 0;
-	*wcs  = 0x0;
-	
-	pass = 1;
-	
-	/* Return here via longjmp() invoked by yy_fatal_error(). */
-	if (setjmp(wcspih_abort_jmp_env)) {
-	  return 3;
-	}
-	
-	BEGIN(INITIAL);
-
-
-#line 8531 "wcspih.c"
-
-	if ( !(yy_init) )
-		{
-		(yy_init) = 1;
-
-#ifdef YY_USER_INIT
-		YY_USER_INIT;
-#endif
-
-		if ( ! (yy_start) )
-			(yy_start) = 1;	/* first start state */
-
-		if ( ! wcspihin )
-			wcspihin = stdin;
-
-		if ( ! wcspihout )
-			wcspihout = stdout;
-
-		if ( ! YY_CURRENT_BUFFER ) {
-			wcspihensure_buffer_stack ();
-			YY_CURRENT_BUFFER_LVALUE =
-				wcspih_create_buffer(wcspihin,YY_BUF_SIZE );
-		}
-
-		wcspih_load_buffer_state( );
-		}
-
-	while ( 1 )		/* loops until end-of-file is reached */
-		{
-		yy_cp = (yy_c_buf_p);
-
-		/* Support of wcspihtext. */
-		*yy_cp = (yy_hold_char);
-
-		/* yy_bp points to the position in yy_ch_buf of the start of
-		 * the current run.
-		 */
-		yy_bp = yy_cp;
-
-		yy_current_state = (yy_start);
-		yy_current_state += YY_AT_BOL();
-yy_match:
-		while ( (yy_current_state = yy_nxt[yy_current_state][ YY_SC_TO_UI(*yy_cp) ]) > 0 )
-			{
-			if ( yy_accept[yy_current_state] )
-				{
-				(yy_last_accepting_state) = yy_current_state;
-				(yy_last_accepting_cpos) = yy_cp;
-				}
-
-			++yy_cp;
-			}
-
-		yy_current_state = -yy_current_state;
-
-yy_find_action:
-		yy_act = yy_accept[yy_current_state];
-
-		YY_DO_BEFORE_ACTION;
-
-do_action:	/* This label is used only to access EOF actions. */
-
-		switch ( yy_act )
-	{ /* beginning of action switch */
-			case 0: /* must back up */
-			/* undo the effects of YY_DO_BEFORE_ACTION */
-			*yy_cp = (yy_hold_char);
-			yy_cp = (yy_last_accepting_cpos) + 1;
-			yy_current_state = (yy_last_accepting_state);
-			goto yy_find_action;
-
-case 1:
-YY_RULE_SETUP
-#line 209 "wcspih.l"
-{
-	  if (pass == 1) {
-	    sscanf(wcspihtext, "NAXIS   = %d", &naxis);
-	  }
-	
-	  if (naxis < 0) {
-	    errmsg = errtxt;
-	    sprintf(errmsg, "Negative value of NAXIS ignored: %d", naxis);
-	    naxis = 0;
-	    BEGIN(ERROR);
-	  } else {
-	    BEGIN(DISCARD);
-	  }
-	}
-	YY_BREAK
-case 2:
-YY_RULE_SETUP
-#line 224 "wcspih.l"
-{
-	  if (pass == 1) {
-	    sscanf(wcspihtext, "WCSAXES%c= %d", &a, &i);
-	    wcspih_naxes(naxis, i, 0, a, alts, 0);
-	  }
-	  BEGIN(FLUSH);
-	}
-	YY_BREAK
-case 3:
-YY_RULE_SETUP
-#line 232 "wcspih.l"
-{
-	  valtype = FLOAT;
-	  if (pass == 2) vptr = &((*wcs)->crpix);
-	  BEGIN(CCCCCia);
-	}
-	YY_BREAK
-case 4:
-YY_RULE_SETUP
-#line 238 "wcspih.l"
-{
-	  valtype = FLOAT;
-	  if (pass == 2) vptr = &((*wcs)->pc);
-	  altlin = 1;
-	  BEGIN(CCi_ja);
-	}
-	YY_BREAK
-case 5:
-YY_RULE_SETUP
-#line 245 "wcspih.l"
-{
-	  valtype = FLOAT;
-	  if (pass == 2) vptr = &((*wcs)->cd);
-	  altlin = 2;
-	  BEGIN(CCi_ja);
-	}
-	YY_BREAK
-case 6:
-YY_RULE_SETUP
-#line 252 "wcspih.l"
-{
-	  valtype = FLOAT;
-	  if (pass == 2) vptr = &((*wcs)->cdelt);
-	  BEGIN(CCCCCia);
-	}
-	YY_BREAK
-case 7:
-YY_RULE_SETUP
-#line 258 "wcspih.l"
-{
-	  valtype = FLOAT;
-	  if (pass == 2) vptr = &((*wcs)->crota);
-	  altlin = 4;
-	  BEGIN(CROTAi);
-	}
-	YY_BREAK
-case 8:
-YY_RULE_SETUP
-#line 265 "wcspih.l"
-{
-	  valtype = STRING;
-	  if (pass == 2) vptr = &((*wcs)->cunit);
-	  BEGIN(CCCCCia);
-	}
-	YY_BREAK
-case 9:
-YY_RULE_SETUP
-#line 271 "wcspih.l"
-{
-	  valtype = STRING;
-	  if (pass == 2) vptr = &((*wcs)->ctype);
-	  BEGIN(CCCCCia);
-	}
-	YY_BREAK
-case 10:
-YY_RULE_SETUP
-#line 277 "wcspih.l"
-{
-	  valtype = FLOAT;
-	  if (pass == 2) vptr = &((*wcs)->crval);
-	  BEGIN(CCCCCia);
-	}
-	YY_BREAK
-case 11:
-YY_RULE_SETUP
-#line 283 "wcspih.l"
-{
-	  valtype = FLOAT;
-	  if (pass == 2) vptr = &((*wcs)->lonpole);
-	  BEGIN(CCCCCCCa);
-	}
-	YY_BREAK
-case 12:
-YY_RULE_SETUP
-#line 289 "wcspih.l"
-{
-	  valtype = FLOAT;
-	  if (pass == 2) vptr = &((*wcs)->latpole);
-	  BEGIN(CCCCCCCa);
-	}
-	YY_BREAK
-case 13:
-YY_RULE_SETUP
-#line 295 "wcspih.l"
-{
-	  valtype = FLOAT;
-	  if (pass == 2) vptr = &((*wcs)->restfrq);
-	  BEGIN(CCCCCCCa);
-	}
-	YY_BREAK
-case 14:
-YY_RULE_SETUP
-#line 301 "wcspih.l"
-{
-	  valtype = FLOAT;
-	  if (pass == 2) vptr = &((*wcs)->restfrq);
-	  unput(' ');
-	  BEGIN(CCCCCCCa);
-	}
-	YY_BREAK
-case 15:
-YY_RULE_SETUP
-#line 308 "wcspih.l"
-{
-	  valtype = FLOAT;
-	  if (pass == 2) vptr = &((*wcs)->restwav);
-	  BEGIN(CCCCCCCa);
-	}
-	YY_BREAK
-case 16:
-YY_RULE_SETUP
-#line 314 "wcspih.l"
-{
-	  valtype = FLOAT;
-	  if (pass == 2) vptr = &((*wcs)->pv);
-	  npptr = npv;
-	  BEGIN(CCi_ma);
-	}
-	YY_BREAK
-case 17:
-YY_RULE_SETUP
-#line 321 "wcspih.l"
-{
-	  valtype = FLOAT;
-	  if (pass == 2) vptr = &((*wcs)->pv);
-	  npptr = npv;
-	  BEGIN(PROJPn);
-	}
-	YY_BREAK
-case 18:
-YY_RULE_SETUP
-#line 328 "wcspih.l"
-{
-	  valtype = STRING;
-	  if (pass == 2) vptr = &((*wcs)->ps);
-	  npptr = nps;
-	  BEGIN(CCi_ma);
-	}
-	YY_BREAK
-case 19:
-YY_RULE_SETUP
-#line 335 "wcspih.l"
-{
-	  valtype = STRING;
-	  if (pass == 2) vptr = &((*wcs)->cname);
-	  BEGIN(CCCCCia);
-	}
-	YY_BREAK
-case 20:
-YY_RULE_SETUP
-#line 341 "wcspih.l"
-{
-	  valtype = FLOAT;
-	  if (pass == 2) vptr = &((*wcs)->crder);
-	  BEGIN(CCCCCia);
-	}
-	YY_BREAK
-case 21:
-YY_RULE_SETUP
-#line 347 "wcspih.l"
-{
-	  valtype = FLOAT;
-	  if (pass == 2) vptr = &((*wcs)->csyer);
-	  BEGIN(CCCCCia);
-	}
-	YY_BREAK
-case 22:
-YY_RULE_SETUP
-#line 353 "wcspih.l"
-{
-	  valtype = STRING;
-	  if (pass == 2) vptr = (*wcs)->dateavg;
-	  if (ctrl < -10) keep = wcspih_hdr - 80;
-	  BEGIN(CCCCCCCC);
-	}
-	YY_BREAK
-case 23:
-YY_RULE_SETUP
-#line 360 "wcspih.l"
-{
-	  valtype = STRING;
-	  if (pass == 2) vptr = (*wcs)->dateobs;
-	  if (ctrl < -10) keep = wcspih_hdr - 80;
-	  BEGIN(CCCCCCCC);
-	}
-	YY_BREAK
-case 24:
-YY_RULE_SETUP
-#line 367 "wcspih.l"
-{
-	  sscanf(wcspihtext, "EPOCH%c", &a);
-	
-	  if (a == ' ' || relax & WCSHDR_EPOCHa) {
-	    valtype = FLOAT;
-	    if (pass == 2) {
-	      vptr = epoch;
-	      if (a >= 'A') {
-	        vptr = (void *)((double *)vptr + alts[a-'A'+1]);
-	      }
-	    }
-	
-	    unput(' ');
-	    BEGIN(CCCCCCCa);
-	
-	  } else if (relax & WCSHDR_reject) {
-	    errmsg = "EPOCH keyword may not have an alternate version code";
-	    BEGIN(ERROR);
-	
-	  } else {
-	    BEGIN(DISCARD);
-	  }
-	}
-	YY_BREAK
-case 25:
-YY_RULE_SETUP
-#line 391 "wcspih.l"
-{
-	  valtype = FLOAT;
-	  if (pass == 2) vptr = &((*wcs)->equinox);
-	  BEGIN(CCCCCCCa);
-	}
-	YY_BREAK
-case 26:
-YY_RULE_SETUP
-#line 397 "wcspih.l"
-{
-	  valtype = FLOAT;
-	  if (pass == 2) vptr = &((*wcs)->mjdavg);
-	  if (ctrl < -10) keep = wcspih_hdr - 80;
-	  BEGIN(CCCCCCCC);
-	}
-	YY_BREAK
-case 27:
-YY_RULE_SETUP
-#line 404 "wcspih.l"
-{
-	  valtype = FLOAT;
-	  if (pass == 2) vptr = &((*wcs)->mjdobs);
-	  if (ctrl < -10) keep = wcspih_hdr - 80;
-	  BEGIN(CCCCCCCC);
-	}
-	YY_BREAK
-case 28:
-YY_RULE_SETUP
-#line 411 "wcspih.l"
-{
-	  valtype = FLOAT;
-	  if (pass == 2) vptr = (*wcs)->obsgeo;
-	  if (ctrl < -10) keep = wcspih_hdr - 80;
-	  BEGIN(CCCCCCCC);
-	}
-	YY_BREAK
-case 29:
-YY_RULE_SETUP
-#line 418 "wcspih.l"
-{
-	  valtype = FLOAT;
-	  if (pass == 2) vptr = (*wcs)->obsgeo + 1;
-	  if (ctrl < -10) keep = wcspih_hdr - 80;
-	  BEGIN(CCCCCCCC);
-	}
-	YY_BREAK
-case 30:
-YY_RULE_SETUP
-#line 425 "wcspih.l"
-{
-	  valtype = FLOAT;
-	  if (pass == 2) vptr = (*wcs)->obsgeo + 2;
-	  if (ctrl < -10) keep = wcspih_hdr - 80;
-	  BEGIN(CCCCCCCC);
-	}
-	YY_BREAK
-case 31:
-YY_RULE_SETUP
-#line 432 "wcspih.l"
-{
-	  valtype = STRING;
-	  if (pass == 2) vptr = (*wcs)->radesys;
-	  BEGIN(CCCCCCCa);
-	}
-	YY_BREAK
-case 32:
-YY_RULE_SETUP
-#line 438 "wcspih.l"
-{
-	  if (relax & WCSHDR_RADECSYS) {
-	    valtype = STRING;
-	    if (pass == 2) vptr = (*wcs)->radesys;
-	    unput(' ');
-	    BEGIN(CCCCCCCa);
-	
-	  } else if (relax & WCSHDR_reject) {
-	    errmsg = "RADECSYS is non-standard, use RADESYSa";
-	    BEGIN(ERROR);
-	
-	  } else {
-	    BEGIN(DISCARD);
-	  }
-	}
-	YY_BREAK
-case 33:
-YY_RULE_SETUP
-#line 454 "wcspih.l"
-{
-	  valtype = STRING;
-	  if (pass == 2) vptr = (*wcs)->specsys;
-	  BEGIN(CCCCCCCa);
-	}
-	YY_BREAK
-case 34:
-YY_RULE_SETUP
-#line 460 "wcspih.l"
-{
-	  valtype = STRING;
-	  if (pass == 2) vptr = (*wcs)->ssysobs;
-	  BEGIN(CCCCCCCa);
-	}
-	YY_BREAK
-case 35:
-YY_RULE_SETUP
-#line 466 "wcspih.l"
-{
-	  valtype = STRING;
-	  if (pass == 2) vptr = (*wcs)->ssyssrc;
-	  BEGIN(CCCCCCCa);
-	}
-	YY_BREAK
-case 36:
-YY_RULE_SETUP
-#line 472 "wcspih.l"
-{
-	  valtype = FLOAT;
-	  if (pass == 2) vptr = &((*wcs)->velangl);
-	  BEGIN(CCCCCCCa);
-	}
-	YY_BREAK
-case 37:
-YY_RULE_SETUP
-#line 478 "wcspih.l"
-{
-	  valtype = FLOAT;
-	  if (pass == 2) vptr = &((*wcs)->velosys);
-	  BEGIN(CCCCCCCa);
-	}
-	YY_BREAK
-case 38:
-YY_RULE_SETUP
-#line 484 "wcspih.l"
-{
-	  sscanf(wcspihtext, "VELREF%c", &a);
-	
-	  if (a == ' ' || relax & WCSHDR_VELREFa) {
-	    valtype = INTEGER;
-	    if (pass == 2) vptr = &((*wcs)->velref);
-	
-	    unput(a);
-	    BEGIN(CCCCCCCa);
-	
-	  } else if (relax & WCSHDR_reject) {
-	    errmsg = "VELREF keyword may not have an alternate version code";
-	    BEGIN(ERROR);
-	
-	  } else {
-	    BEGIN(DISCARD);
-	  }
-	}
-	YY_BREAK
-case 39:
-YY_RULE_SETUP
-#line 503 "wcspih.l"
-{
-	  sscanf(wcspihtext, "VSOURCE%c", &a);
-	
-	  if (relax & WCSHDR_VSOURCE) {
-	    valtype = FLOAT;
-	    if (pass == 2) {
-	      vptr = vsource;
-	      if (a >= 'A') {
-	        vptr = (void *)((double *)vptr + alts[a-'A'+1]);
-	      }
-	    }
-	
-	    unput(' ');
-	    BEGIN(CCCCCCCa);
-	
-	  } else if (relax & WCSHDR_reject) {
-	    errmsg = "Deprecated VSOURCEa keyword rejected";
-	    BEGIN(ERROR);
-	
-	  } else {
-	    BEGIN(DISCARD);
-	  }
-	}
-	YY_BREAK
-case 40:
-YY_RULE_SETUP
-#line 527 "wcspih.l"
-{
-	  valtype = STRING;
-	  if (pass == 2) vptr = (*wcs)->wcsname;
-	  BEGIN(CCCCCCCa);
-	}
-	YY_BREAK
-case 41:
-YY_RULE_SETUP
-#line 533 "wcspih.l"
-{
-	  valtype = FLOAT;
-	  if (pass == 2) vptr = &((*wcs)->zsource);
-	  BEGIN(CCCCCCCa);
-	}
-	YY_BREAK
-case 42:
-YY_RULE_SETUP
-#line 539 "wcspih.l"
-{
-	  yyless(0);
-	  if (wcspih_nkeyrec) {
-	    wcspih_nkeyrec = 0;
-	    errmsg = "Keyrecords following the END keyrecord were ignored";
-	    BEGIN(ERROR);
-	  } else {
-	    BEGIN(DISCARD);
-	  }
-	}
-	YY_BREAK
-case 43:
-YY_RULE_SETUP
-#line 550 "wcspih.l"
-{
-	  BEGIN(DISCARD);
-	}
-	YY_BREAK
-case 44:
-#line 555 "wcspih.l"
-case 45:
-YY_RULE_SETUP
-#line 555 "wcspih.l"
-{
-	  sscanf(wcspihtext, "%d%c", &i, &a);
-	  idx = i - 1;
-	  BEGIN(VALUE);
-	}
-	YY_BREAK
-case 46:
-YY_RULE_SETUP
-#line 561 "wcspih.l"
-{
-	  /* Invalid axis number will be caught by <VALUE>. */
-	  sscanf(wcspihtext, "%3d", &i);
-	  BEGIN(VALUE);
-	}
-	YY_BREAK
-case 47:
-YY_RULE_SETUP
-#line 567 "wcspih.l"
-{
-	  BEGIN(DISCARD);
-	}
-	YY_BREAK
-case 48:
-#line 572 "wcspih.l"
-case 49:
-#line 573 "wcspih.l"
-case 50:
-#line 574 "wcspih.l"
-case 51:
-YY_RULE_SETUP
-#line 574 "wcspih.l"
-{
-	  sscanf(wcspihtext, "%d_%d%c", &i, &j, &a);
-	  if (pass == 2) {
-	    wcsp = *wcs;
-	    if (a != ' ') {
-	      wcsp += alts[a-'A'+1];
-	    }
-	
-	    idx = (i-1)*(wcsp->naxis) + j - 1;
-	  }
-	  BEGIN(VALUE);
-	}
-	YY_BREAK
-case 52:
-#line 588 "wcspih.l"
-case 53:
-#line 589 "wcspih.l"
-case 54:
-#line 590 "wcspih.l"
-case 55:
-#line 591 "wcspih.l"
-case 56:
-#line 592 "wcspih.l"
-case 57:
-YY_RULE_SETUP
-#line 592 "wcspih.l"
-{
-	  /* Invalid axis numbers will be caught by <VALUE>. */
-	  sscanf(wcspihtext, "%d_%d", &i, &j);
-	  BEGIN(VALUE);
-	}
-	YY_BREAK
-case 58:
-YY_RULE_SETUP
-#line 598 "wcspih.l"
-{
-	  /* This covers the defunct forms CD00i00j and PC00i00j. */
-	  if (((relax & WCSHDR_PC00i00j) && (altlin == 1)) ||
-	      ((relax & WCSHDR_CD00i00j) && (altlin == 2))) {
-	    sscanf(wcspihtext, "%3d%3d", &i, &j);
-	    a = ' ';
-	    if (pass == 2) {
-	      idx = (i-1)*((*wcs)->naxis) + j - 1;
-	    }
-	    BEGIN(VALUE);
-	
-	  } else if (relax & WCSHDR_reject) {
-	    errmsg = errtxt;
-	    sprintf(errmsg, "Defunct form of %si_ja keyword",
-	                     (altlin==1) ? "PC" : "CD");
-	    BEGIN(ERROR);
-	
-	  } else {
-	    BEGIN(DISCARD);
-	  }
-	}
-	YY_BREAK
-case 59:
-YY_RULE_SETUP
-#line 620 "wcspih.l"
-{
-	  BEGIN(DISCARD);
-	}
-	YY_BREAK
-case 60:
-#line 625 "wcspih.l"
-case 61:
-YY_RULE_SETUP
-#line 625 "wcspih.l"
-{
-	  sscanf(wcspihtext, "%d%c", &i, &a);
-	  if (a == ' ' || relax & WCSHDR_CROTAia) {
-	    idx = i - 1;
-	    BEGIN(VALUE);
-	
-	  } else if (relax & WCSHDR_reject) {
-	    errmsg = "CROTAn keyword may not have an alternate version code";
-	    BEGIN(ERROR);
-	
-	  } else {
-	    BEGIN(DISCARD);
-	  }
-	}
-	YY_BREAK
-case 62:
-YY_RULE_SETUP
-#line 640 "wcspih.l"
-{
-	  sscanf(wcspihtext, "%d", &i);
-	  a = ' ';
-	  idx = i - 1;
-	  BEGIN(VALUE);
-	}
-	YY_BREAK
-case 63:
-YY_RULE_SETUP
-#line 647 "wcspih.l"
-{
-	  BEGIN(DISCARD);
-	}
-	YY_BREAK
-case 64:
-#line 652 "wcspih.l"
-case 65:
-YY_RULE_SETUP
-#line 652 "wcspih.l"
-{
-	  idx = -1;
-	
-	  if (YY_START == CCCCCCCa) {
-	    sscanf(wcspihtext, "%c", &a);
-	  } else {
-	    unput(wcspihtext[0]);
-	    a = 0;
-	  }
-	  BEGIN(VALUE);
-	}
-	YY_BREAK
-case 66:
-YY_RULE_SETUP
-#line 664 "wcspih.l"
-{
-	  BEGIN(DISCARD);
-	}
-	YY_BREAK
-case 67:
-#line 669 "wcspih.l"
-case 68:
-#line 670 "wcspih.l"
-case 69:
-#line 671 "wcspih.l"
-case 70:
-YY_RULE_SETUP
-#line 671 "wcspih.l"
-{
-	  sscanf(wcspihtext, "%d_%d%c", &i, &m, &a);
-	  idx = -1;
-	  BEGIN(VALUE);
-	}
-	YY_BREAK
-case 71:
-#line 678 "wcspih.l"
-case 72:
-#line 679 "wcspih.l"
-case 73:
-#line 680 "wcspih.l"
-case 74:
-#line 681 "wcspih.l"
-case 75:
-#line 682 "wcspih.l"
-case 76:
-YY_RULE_SETUP
-#line 682 "wcspih.l"
-{
-	  /* Invalid parameters will be caught by <VALUE>. */
-	  sscanf(wcspihtext, "%d_%d", &i, &m);
-	  BEGIN(VALUE);
-	}
-	YY_BREAK
-case 77:
-YY_RULE_SETUP
-#line 688 "wcspih.l"
-{
-	  BEGIN(DISCARD);
-	}
-	YY_BREAK
-case 78:
-YY_RULE_SETUP
-#line 692 "wcspih.l"
-{
-	  if (relax & WCSHDR_PROJPn) {
-	    sscanf(wcspihtext, "%d", &m);
-	    i = 0;
-	    a = ' ';
-	    idx = -1;
-	    BEGIN(VALUE);
-	
-	  } else if (relax & WCSHDR_reject) {
-	    errmsg = "Defunct PROJPn keyword rejected";
-	    BEGIN(ERROR);
-	
-	  } else {
-	    BEGIN(DISCARD);
-	  }
-	}
-	YY_BREAK
-case 79:
-YY_RULE_SETUP
-#line 709 "wcspih.l"
-{
-	  BEGIN(DISCARD);
-	}
-	YY_BREAK
-case 80:
-YY_RULE_SETUP
-#line 713 "wcspih.l"
-{
-	  /* Do checks on i, j & m. */
-	  if (i > 99 || j > 99 || m > 99) {
-	    if (relax & WCSHDR_reject) {
-	      errmsg = errtxt;
-	      if (i > 99 || j > 99) {
-	        sprintf(errmsg, "Axis number exceeds 99");
-	      } else if (m > 99) {
-	        sprintf(errmsg, "Parameter number exceeds 99");
-	      }
-	      BEGIN(ERROR);
-	
-	    } else {
-	      /* Pretend we don't recognize it. */
-	      BEGIN(DISCARD);
-	    }
-	
-	  } else {
-	    if (valtype == INTEGER) {
-	      BEGIN(INTEGER_VAL);
-	    } else if (valtype == FLOAT) {
-	      BEGIN(FLOAT_VAL);
-	    } else if (valtype == STRING) {
-	      BEGIN(STRING_VAL);
-	    } else {
-	      errmsg = errtxt;
-	      sprintf(errmsg, "Internal parser ERROR, bad data type: %d",
-	        valtype);
-	      BEGIN(ERROR);
-	    }
-	  }
-	}
-	YY_BREAK
-case 81:
-YY_RULE_SETUP
-#line 746 "wcspih.l"
-{
-	  errmsg = "Invalid KEYWORD = VALUE syntax";
-	  BEGIN(ERROR);
-	}
-	YY_BREAK
-case 82:
-YY_RULE_SETUP
-#line 751 "wcspih.l"
-{
-	  if (pass == 1) {
-	    wcspih_naxes(naxis, i, j, a, alts, npptr);
-	    BEGIN(FLUSH);
-	
-	  } else {
-	    if (vptr) {
-	      /* Determine the coordinate representation. */
-	      for (ialt = 0; ialt < *nwcs; ialt++) {
-	        /* The loop here is for keywords that apply */
-	        /* to every alternate; these have a == 0. */
-	        if (a >= 'A') {
-	          ialt = alts[a-'A'+1];
-	        }
-	
-	        wptr = vptr;
-	        if (ialt) {
-	          voff = (char *)(*wcs+ialt) - (char *)(*wcs);
-	          wptr = (void *)((char *)vptr + voff);
-	        }
-	
-	        /* Apply keyword parameterization. */
-	        if (idx >= 0) {
-	          wptr = *((int **)wptr) + idx;
-	        }
-	
-	        /* Read the keyvalue. */
-	        sscanf(wcspihtext, "%d", (int *)wptr);
-	
-	        if (a) break;
-	      }
-	
-	      BEGIN(COMMENT);
-	
-	    } else {
-	      errmsg = "Internal parser ERROR, null int pointer";
-	      BEGIN(ERROR);
-	    }
-	  }
-	}
-	YY_BREAK
-case 83:
-YY_RULE_SETUP
-#line 792 "wcspih.l"
-{
-	  errmsg = "An integer value was expected";
-	  BEGIN(ERROR);
-	}
-	YY_BREAK
-case 84:
-YY_RULE_SETUP
-#line 797 "wcspih.l"
-{
-	  if (pass == 1) {
-	    wcspih_naxes(naxis, i, j, a, alts, npptr);
-	    BEGIN(FLUSH);
-	
-	  } else {
-	    if (vptr) {
-	      /* Determine the coordinate representation. */
-	      for (ialt = 0; ialt < *nwcs; ialt++) {
-	        /* The loop here is for keywords like MJD-OBS that */
-	        /* apply to every alternate; these have a == 0.  */
-	        if (a >= 'A') {
-	          ialt = alts[a-'A'+1];
-	        }
-	
-	        wptr = vptr;
-	        if (ialt) {
-	          voff = (char *)(*wcs+ialt) - (char *)(*wcs);
-	          wptr = (void *)((char *)vptr + voff);
-	        }
-	
-	        /* Apply keyword parameterization. */
-	        if (idx >= 0) {
-	          wptr = *((double **)wptr) + idx;
-	
-	        } else if (npptr == npv) {
-	          ipx = (*wcs+ialt)->npv++;
-	          (*wcs+ialt)->pv[ipx].i = i;
-	          (*wcs+ialt)->pv[ipx].m = m;
-	          wptr = &((*wcs+ialt)->pv[ipx].value);
-	        }
-	
-	        /* Read the keyvalue. */
-	        sscanf(wcspihtext, "%lf", (double *)wptr);
-	
-	        /* Flag the presence of PCi_ja, or CDi_ja and/or CROTAia. */
-	        if (altlin) {
-	          (*wcs+ialt)->altlin |= altlin;
-	          altlin = 0;
-	        }
-	
-	        if (a) break;
-	      }
-	
-	      BEGIN(COMMENT);
-	
-	    } else {
-	      errmsg = "Internal parser ERROR, null float pointer";
-	      BEGIN(ERROR);
-	    }
-	  }
-	}
-	YY_BREAK
-case 85:
-YY_RULE_SETUP
-#line 850 "wcspih.l"
-{
-	  errmsg = "A floating-point value was expected";
-	  BEGIN(ERROR);
-	}
-	YY_BREAK
-case 86:
-/* rule 86 can match eol */
-YY_RULE_SETUP
-#line 855 "wcspih.l"
-{
-	  if (pass == 1) {
-	    wcspih_naxes(naxis, i, j, a, alts, npptr);
-	    BEGIN(FLUSH);
-	
-	  } else {
-	    if (vptr) {
-	      /* Determine the coordinate representation. */
-	      for (ialt = 0; ialt < *nwcs; ialt++) {
-	        /* The loop here is for keywords like DATE-OBS that */
-	        /* apply to every alternate; these have a == 0.   */
-	        if (a >= 'A') {
-	          ialt = alts[a-'A'+1];
-	        }
-	
-	        wptr = vptr;
-	        if (ialt) {
-	          voff = (char *)(*wcs+ialt) - (char *)(*wcs);
-	          wptr = (void *)((char *)vptr + voff);
-	        }
-	
-	        /* Apply keyword parameterization. */
-	        if (idx >= 0) {
-	          wptr = *((char (**)[72])wptr) + idx;
-	
-	        } else if (npptr == nps) {
-	          ipx = (*wcs+ialt)->nps++;
-	          (*wcs+ialt)->ps[ipx].i = i;
-	          (*wcs+ialt)->ps[ipx].m = m;
-	          wptr = (*wcs+ialt)->ps[ipx].value;
-	        }
-	
-	        /* Read the keyvalue. */
-	        cptr = (char *)wptr;
-	        strcpy(cptr, wcspihtext+1);
-	
-	        /* Squeeze out repeated quotes. */
-	        ix = 0;
-	        for (jx = 0; jx < 72; jx++) {
-	          if (ix < jx) {
-	            cptr[ix] = cptr[jx];
-	          }
-	
-	          if (cptr[jx] == '\0') {
-	            if (ix) cptr[ix-1] = '\0';
-	            break;
-	          } else if (cptr[jx] == '\'' && cptr[jx+1] == '\'') {
-	            jx++;
-	          }
-	
-	          ix++;
-	        }
-	
-	        if (a) break;
-	      }
-	
-	      BEGIN(COMMENT);
-	
-	    } else {
-	      errmsg = "Internal parser ERROR, null string pointer";
-	      BEGIN(ERROR);
-	    }
-	  }
-	}
-	YY_BREAK
-case 87:
-YY_RULE_SETUP
-#line 920 "wcspih.l"
-{
-	  errmsg = "A string value was expected";
-	  BEGIN(ERROR);
-	}
-	YY_BREAK
-case 88:
-#line 926 "wcspih.l"
-case 89:
-YY_RULE_SETUP
-#line 926 "wcspih.l"
-{
-	  BEGIN(FLUSH);
-	}
-	YY_BREAK
-case 90:
-YY_RULE_SETUP
-#line 930 "wcspih.l"
-{
-	  errmsg = "Malformed keycomment";
-	  BEGIN(ERROR);
-	}
-	YY_BREAK
-case 91:
-YY_RULE_SETUP
-#line 935 "wcspih.l"
-{
-	  if (pass == 2) {
-	    if (ctrl < 0) {
-	      /* Preserve discards. */
-	      keep = wcspih_hdr - 80;
-	
-	    } else if (ctrl > 2) {
-	      fprintf(stderr, "%.80s\n  Discarded.\n", wcspih_hdr-80);
-	    }
-	  }
-	  BEGIN(FLUSH);
-	}
-	YY_BREAK
-case 92:
-YY_RULE_SETUP
-#line 948 "wcspih.l"
-{
-	  (*nreject)++;
-	  if (pass == 2) {
-	    if (ctrl%10 == -1) {
-	      /* Preserve rejects. */
-	      keep = wcspih_hdr - 80;
-	    }
-	
-	    if (abs(ctrl%10) > 1) {
-	      fprintf(stderr, "%.80s\n%4d: %s.\n", wcspih_hdr-80, *nreject,
-	        errmsg);
-	    }
-	  }
-	  BEGIN(FLUSH);
-	}
-	YY_BREAK
-case 93:
-/* rule 93 can match eol */
-YY_RULE_SETUP
-#line 964 "wcspih.l"
-{
-	  if (pass == 2 && keep) {
-	    if (hptr < keep) {
-	      strncpy(hptr, keep, 80);
-	    }
-	    hptr += 80;
-	  }
-	
-	  i = j = m = 0;
-	  a = ' ';
-	  valtype = -1;
-	  keep = 0x0;
-	  altlin = 0;
-	  npptr = 0x0;
-	  BEGIN(INITIAL);
-	}
-	YY_BREAK
-case YY_STATE_EOF(INITIAL):
-case YY_STATE_EOF(CROTAi):
-case YY_STATE_EOF(PROJPn):
-case YY_STATE_EOF(CCCCCia):
-case YY_STATE_EOF(CCi_ja):
-case YY_STATE_EOF(CCi_ma):
-case YY_STATE_EOF(CCCCCCCa):
-case YY_STATE_EOF(CCCCCCCC):
-case YY_STATE_EOF(VALUE):
-case YY_STATE_EOF(INTEGER_VAL):
-case YY_STATE_EOF(FLOAT_VAL):
-case YY_STATE_EOF(STRING_VAL):
-case YY_STATE_EOF(COMMENT):
-case YY_STATE_EOF(DISCARD):
-case YY_STATE_EOF(ERROR):
-case YY_STATE_EOF(FLUSH):
-#line 981 "wcspih.l"
-{
-	  /* End-of-input. */
-	  if (pass == 1) {
-	    if ((status = wcspih_inits(naxis, alts, npv, nps, nwcs, wcs)) ||
-	         *nwcs == 0) {
-	      wcspihlex_destroy();
-	      return status;
-	    }
-	
-	    if (abs(ctrl%10) > 2) {
-	      if (*nwcs == 1) {
-	        fprintf(stderr, "Found one coordinate representation.\n");
-	      } else {
-	        fprintf(stderr, "Found %d coordinate representations.\n",
-	          *nwcs);
-	      }
-	    }
-	
-	    wcspih_hdr = header;
-	    wcspih_nkeyrec = nkeyrec;
-	    *nreject = 0;
-	
-	    pass = 2;
-	    i = j = m = 0;
-	    a = ' ';
-	    valtype = -1;
-	
-	    wcspihrestart(wcspihin);
-	
-	  } else {
-	    wcspihlex_destroy();
-	
-	    if (ctrl < 0) {
-	      *hptr = '\0';
-	    } else if (ctrl == 1) {
-	      fprintf(stderr, "%d WCS keyrecords were rejected.\n",
-	        *nreject);
-	    }
-	
-	    return wcspih_final(alts, epoch, vsource, nwcs, wcs);
-	  }
-	}
-	YY_BREAK
-case 94:
-YY_RULE_SETUP
-#line 1024 "wcspih.l"
-ECHO;
-	YY_BREAK
-#line 9681 "wcspih.c"
-
-	case YY_END_OF_BUFFER:
-		{
-		/* Amount of text matched not including the EOB char. */
-		int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;
-
-		/* Undo the effects of YY_DO_BEFORE_ACTION. */
-		*yy_cp = (yy_hold_char);
-		YY_RESTORE_YY_MORE_OFFSET
-
-		if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
-			{
-			/* We're scanning a new file or input source.  It's
-			 * possible that this happened because the user
-			 * just pointed wcspihin at a new source and called
-			 * wcspihlex().  If so, then we have to assure
-			 * consistency between YY_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.
-			 */
-			(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
-			YY_CURRENT_BUFFER_LVALUE->yy_input_file = wcspihin;
-			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
-			}
-
-		/* Note that here we test for yy_c_buf_p "<=" to the position
-		 * of the first EOB in the buffer, since yy_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 ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
-			{ /* This was really a NUL. */
-			yy_state_type yy_next_state;
-
-			(yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;
-
-			yy_current_state = yy_get_previous_state(  );
-
-			/* Okay, we're now positioned to make the NUL
-			 * transition.  We couldn't have
-			 * yy_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).
-			 */
-
-			yy_next_state = yy_try_NUL_trans( yy_current_state );
-
-			yy_bp = (yytext_ptr) + YY_MORE_ADJ;
-
-			if ( yy_next_state )
-				{
-				/* Consume the NUL. */
-				yy_cp = ++(yy_c_buf_p);
-				yy_current_state = yy_next_state;
-				goto yy_match;
-				}
-
-			else
-				{
-				yy_cp = (yy_c_buf_p);
-				goto yy_find_action;
-				}
-			}
-
-		else switch ( yy_get_next_buffer(  ) )
-			{
-			case EOB_ACT_END_OF_FILE:
-				{
-				(yy_did_buffer_switch_on_eof) = 0;
-
-				if ( wcspihwrap( ) )
-					{
-					/* Note: because we've taken care in
-					 * yy_get_next_buffer() to have set up
-					 * wcspihtext, we can now set up
-					 * yy_c_buf_p so that if some total
-					 * hoser (like flex itself) wants to
-					 * call the scanner after we return the
-					 * YY_NULL, it'll still work - another
-					 * YY_NULL will get returned.
-					 */
-					(yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;
-
-					yy_act = YY_STATE_EOF(YY_START);
-					goto do_action;
-					}
-
-				else
-					{
-					if ( ! (yy_did_buffer_switch_on_eof) )
-						YY_NEW_FILE;
-					}
-				break;
-				}
-
-			case EOB_ACT_CONTINUE_SCAN:
-				(yy_c_buf_p) =
-					(yytext_ptr) + yy_amount_of_matched_text;
-
-				yy_current_state = yy_get_previous_state(  );
-
-				yy_cp = (yy_c_buf_p);
-				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
-				goto yy_match;
-
-			case EOB_ACT_LAST_MATCH:
-				(yy_c_buf_p) =
-				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];
-
-				yy_current_state = yy_get_previous_state(  );
-
-				yy_cp = (yy_c_buf_p);
-				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
-				goto yy_find_action;
-			}
-		break;
-		}
-
-	default:
-		YY_FATAL_ERROR(
-			"fatal flex scanner internal error--no action found" );
-	} /* end of action switch */
-		} /* end of scanning one token */
-} /* end of wcspihlex */
-
-/* yy_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 yy_get_next_buffer (void)
-{
-    	register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
-	register char *source = (yytext_ptr);
-	register int number_to_move, i;
-	int ret_val;
-
-	if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
-		YY_FATAL_ERROR(
-		"fatal flex scanner internal error--end of buffer missed" );
-
-	if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
-		{ /* Don't try to fill the buffer, so this is an EOF. */
-		if ( (yy_c_buf_p) - (yytext_ptr) - YY_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) ((yy_c_buf_p) - (yytext_ptr)) - 1;
-
-	for ( i = 0; i < number_to_move; ++i )
-		*(dest++) = *(source++);
-
-	if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
-		/* don't do the read, it's not guaranteed to return an EOF,
-		 * just force an EOF
-		 */
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
-
-	else
-		{
-			int num_to_read =
-			YY_CURRENT_BUFFER_LVALUE->yy_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 */
-			YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
-
-			int yy_c_buf_p_offset =
-				(int) ((yy_c_buf_p) - b->yy_ch_buf);
-
-			if ( b->yy_is_our_buffer )
-				{
-				int new_size = b->yy_buf_size * 2;
-
-				if ( new_size <= 0 )
-					b->yy_buf_size += b->yy_buf_size / 8;
-				else
-					b->yy_buf_size *= 2;
-
-				b->yy_ch_buf = (char *)
-					/* Include room in for 2 EOB chars. */
-					wcspihrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2  );
-				}
-			else
-				/* Can't grow it, we don't own it. */
-				b->yy_ch_buf = 0;
-
-			if ( ! b->yy_ch_buf )
-				YY_FATAL_ERROR(
-				"fatal error - scanner input buffer overflow" );
-
-			(yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset];
-
-			num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
-						number_to_move - 1;
-
-			}
-
-		if ( num_to_read > YY_READ_BUF_SIZE )
-			num_to_read = YY_READ_BUF_SIZE;
-
-		/* Read in more data. */
-		YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
-			(yy_n_chars), (size_t) num_to_read );
-
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
-		}
-
-	if ( (yy_n_chars) == 0 )
-		{
-		if ( number_to_move == YY_MORE_ADJ )
-			{
-			ret_val = EOB_ACT_END_OF_FILE;
-			wcspihrestart(wcspihin  );
-			}
-
-		else
-			{
-			ret_val = EOB_ACT_LAST_MATCH;
-			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
-				YY_BUFFER_EOF_PENDING;
-			}
-		}
-
-	else
-		ret_val = EOB_ACT_CONTINUE_SCAN;
-
-	if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
-		/* Extend the array by 50%, plus the number we really need. */
-		yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1);
-		YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) wcspihrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size  );
-		if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
-			YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
-	}
-
-	(yy_n_chars) += number_to_move;
-	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
-	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
-
-	(yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
-
-	return ret_val;
-}
-
-/* yy_get_previous_state - get the state just before the EOB char was reached */
-
-    static yy_state_type yy_get_previous_state (void)
-{
-	register yy_state_type yy_current_state;
-	register char *yy_cp;
-    
-	yy_current_state = (yy_start);
-	yy_current_state += YY_AT_BOL();
-
-	for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
-		{
-		if ( *yy_cp )
-			{
-			yy_current_state = yy_nxt[yy_current_state][YY_SC_TO_UI(*yy_cp)];
-			}
-		else
-			yy_current_state = yy_NUL_trans[yy_current_state];
-		if ( yy_accept[yy_current_state] )
-			{
-			(yy_last_accepting_state) = yy_current_state;
-			(yy_last_accepting_cpos) = yy_cp;
-			}
-		}
-
-	return yy_current_state;
-}
-
-/* yy_try_NUL_trans - try to make a transition on the NUL character
- *
- * synopsis
- *	next_state = yy_try_NUL_trans( current_state );
- */
-    static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state )
-{
-	register int yy_is_jam;
-    	register char *yy_cp = (yy_c_buf_p);
-
-	yy_current_state = yy_NUL_trans[yy_current_state];
-	yy_is_jam = (yy_current_state == 0);
-
-	if ( ! yy_is_jam )
-		{
-		if ( yy_accept[yy_current_state] )
-			{
-			(yy_last_accepting_state) = yy_current_state;
-			(yy_last_accepting_cpos) = yy_cp;
-			}
-		}
-
-	return yy_is_jam ? 0 : yy_current_state;
-}
-
-    static void yyunput (int c, register char * yy_bp )
-{
-	register char *yy_cp;
-    
-    yy_cp = (yy_c_buf_p);
-
-	/* undo effects of setting up wcspihtext */
-	*yy_cp = (yy_hold_char);
-
-	if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
-		{ /* need to shift things up to make room */
-		/* +2 for EOB chars. */
-		register int number_to_move = (yy_n_chars) + 2;
-		register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
-					YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
-		register char *source =
-				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
-
-		while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
-			*--dest = *--source;
-
-		yy_cp += (int) (dest - source);
-		yy_bp += (int) (dest - source);
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars =
-			(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size;
-
-		if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
-			YY_FATAL_ERROR( "flex scanner push-back overflow" );
-		}
-
-	*--yy_cp = (char) c;
-
-	(yytext_ptr) = yy_bp;
-	(yy_hold_char) = *yy_cp;
-	(yy_c_buf_p) = yy_cp;
-}
-
-#ifndef YY_NO_INPUT
-#ifdef __cplusplus
-    static int yyinput (void)
-#else
-    static int input  (void)
-#endif
-
-{
-	int c;
-    
-	*(yy_c_buf_p) = (yy_hold_char);
-
-	if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
-		{
-		/* yy_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 ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
-			/* This was really a NUL. */
-			*(yy_c_buf_p) = '\0';
-
-		else
-			{ /* need more input */
-			int offset = (yy_c_buf_p) - (yytext_ptr);
-			++(yy_c_buf_p);
-
-			switch ( yy_get_next_buffer(  ) )
-				{
-				case EOB_ACT_LAST_MATCH:
-					/* This happens because yy_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. */
-					wcspihrestart(wcspihin );
-
-					/*FALLTHROUGH*/
-
-				case EOB_ACT_END_OF_FILE:
-					{
-					if ( wcspihwrap( ) )
-						return EOF;
-
-					if ( ! (yy_did_buffer_switch_on_eof) )
-						YY_NEW_FILE;
-#ifdef __cplusplus
-					return yyinput();
-#else
-					return input();
-#endif
-					}
-
-				case EOB_ACT_CONTINUE_SCAN:
-					(yy_c_buf_p) = (yytext_ptr) + offset;
-					break;
-				}
-			}
-		}
-
-	c = *(unsigned char *) (yy_c_buf_p);	/* cast for 8-bit char's */
-	*(yy_c_buf_p) = '\0';	/* preserve wcspihtext */
-	(yy_hold_char) = *++(yy_c_buf_p);
-
-	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = (c == '\n');
-
-	return c;
-}
-#endif	/* ifndef YY_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 wcspihrestart  (FILE * input_file )
-{
-    
-	if ( ! YY_CURRENT_BUFFER ){
-        wcspihensure_buffer_stack ();
-		YY_CURRENT_BUFFER_LVALUE =
-            wcspih_create_buffer(wcspihin,YY_BUF_SIZE );
-	}
-
-	wcspih_init_buffer(YY_CURRENT_BUFFER,input_file );
-	wcspih_load_buffer_state( );
-}
-
-/** Switch to a different input buffer.
- * @param new_buffer The new input buffer.
- * 
- */
-    void wcspih_switch_to_buffer  (YY_BUFFER_STATE  new_buffer )
-{
-    
-	/* TODO. We should be able to replace this entire function body
-	 * with
-	 *		wcspihpop_buffer_state();
-	 *		wcspihpush_buffer_state(new_buffer);
-     */
-	wcspihensure_buffer_stack ();
-	if ( YY_CURRENT_BUFFER == new_buffer )
-		return;
-
-	if ( YY_CURRENT_BUFFER )
-		{
-		/* Flush out information for old buffer. */
-		*(yy_c_buf_p) = (yy_hold_char);
-		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
-		}
-
-	YY_CURRENT_BUFFER_LVALUE = new_buffer;
-	wcspih_load_buffer_state( );
-
-	/* We don't actually know whether we did this switch during
-	 * EOF (wcspihwrap()) processing, but the only time this flag
-	 * is looked at is after wcspihwrap() is called, so it's safe
-	 * to go ahead and always set it.
-	 */
-	(yy_did_buffer_switch_on_eof) = 1;
-}
-
-static void wcspih_load_buffer_state  (void)
-{
-    	(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
-	(yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
-	wcspihin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
-	(yy_hold_char) = *(yy_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 YY_BUF_SIZE.
- * 
- * @return the allocated buffer state.
- */
-    YY_BUFFER_STATE wcspih_create_buffer  (FILE * file, int  size )
-{
-	YY_BUFFER_STATE b;
-    
-	b = (YY_BUFFER_STATE) wcspihalloc(sizeof( struct yy_buffer_state )  );
-	if ( ! b )
-		YY_FATAL_ERROR( "out of dynamic memory in wcspih_create_buffer()" );
-
-	b->yy_buf_size = size;
-
-	/* yy_ch_buf has to be 2 characters longer than the size given because
-	 * we need to put in 2 end-of-buffer characters.
-	 */
-	b->yy_ch_buf = (char *) wcspihalloc(b->yy_buf_size + 2  );
-	if ( ! b->yy_ch_buf )
-		YY_FATAL_ERROR( "out of dynamic memory in wcspih_create_buffer()" );
-
-	b->yy_is_our_buffer = 1;
-
-	wcspih_init_buffer(b,file );
-
-	return b;
-}
-
-/** Destroy the buffer.
- * @param b a buffer created with wcspih_create_buffer()
- * 
- */
-    void wcspih_delete_buffer (YY_BUFFER_STATE  b )
-{
-    
-	if ( ! b )
-		return;
-
-	if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
-		YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
-
-	if ( b->yy_is_our_buffer )
-		wcspihfree((void *) b->yy_ch_buf  );
-
-	wcspihfree((void *) b  );
-}
-
-/* Initializes or reinitializes a buffer.
- * This function is sometimes called more than once on the same buffer,
- * such as during a wcspihrestart() or at EOF.
- */
-    static void wcspih_init_buffer  (YY_BUFFER_STATE  b, FILE * file )
-
-{
-	int oerrno = errno;
-    
-	wcspih_flush_buffer(b );
-
-	b->yy_input_file = file;
-	b->yy_fill_buffer = 1;
-
-    /* If b is the current buffer, then wcspih_init_buffer was _probably_
-     * called from wcspihrestart() or through yy_get_next_buffer.
-     * In that case, we don't want to reset the lineno or column.
-     */
-    if (b != YY_CURRENT_BUFFER){
-        b->yy_bs_lineno = 1;
-        b->yy_bs_column = 0;
-    }
-
-        b->yy_is_interactive = 0;
-    
-	errno = oerrno;
-}
-
-/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
- * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
- * 
- */
-    void wcspih_flush_buffer (YY_BUFFER_STATE  b )
-{
-    	if ( ! b )
-		return;
-
-	b->yy_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->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
-	b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
-
-	b->yy_buf_pos = &b->yy_ch_buf[0];
-
-	b->yy_at_bol = 1;
-	b->yy_buffer_status = YY_BUFFER_NEW;
-
-	if ( b == YY_CURRENT_BUFFER )
-		wcspih_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 wcspihpush_buffer_state (YY_BUFFER_STATE new_buffer )
-{
-    	if (new_buffer == NULL)
-		return;
-
-	wcspihensure_buffer_stack();
-
-	/* This block is copied from wcspih_switch_to_buffer. */
-	if ( YY_CURRENT_BUFFER )
-		{
-		/* Flush out information for old buffer. */
-		*(yy_c_buf_p) = (yy_hold_char);
-		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
-		}
-
-	/* Only push if top exists. Otherwise, replace top. */
-	if (YY_CURRENT_BUFFER)
-		(yy_buffer_stack_top)++;
-	YY_CURRENT_BUFFER_LVALUE = new_buffer;
-
-	/* copied from wcspih_switch_to_buffer. */
-	wcspih_load_buffer_state( );
-	(yy_did_buffer_switch_on_eof) = 1;
-}
-
-/** Removes and deletes the top of the stack, if present.
- *  The next element becomes the new top.
- *  
- */
-void wcspihpop_buffer_state (void)
-{
-    	if (!YY_CURRENT_BUFFER)
-		return;
-
-	wcspih_delete_buffer(YY_CURRENT_BUFFER );
-	YY_CURRENT_BUFFER_LVALUE = NULL;
-	if ((yy_buffer_stack_top) > 0)
-		--(yy_buffer_stack_top);
-
-	if (YY_CURRENT_BUFFER) {
-		wcspih_load_buffer_state( );
-		(yy_did_buffer_switch_on_eof) = 1;
-	}
-}
-
-/* Allocates the stack if it does not exist.
- *  Guarantees space for at least one push.
- */
-static void wcspihensure_buffer_stack (void)
-{
-	int num_to_alloc;
-    
-	if (!(yy_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;
-		(yy_buffer_stack) = (struct yy_buffer_state**)wcspihalloc
-								(num_to_alloc * sizeof(struct yy_buffer_state*)
-								);
-		if ( ! (yy_buffer_stack) )
-			YY_FATAL_ERROR( "out of dynamic memory in wcspihensure_buffer_stack()" );
-								  
-		memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
-				
-		(yy_buffer_stack_max) = num_to_alloc;
-		(yy_buffer_stack_top) = 0;
-		return;
-	}
-
-	if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
-
-		/* Increase the buffer to prepare for a possible push. */
-		int grow_size = 8 /* arbitrary grow size */;
-
-		num_to_alloc = (yy_buffer_stack_max) + grow_size;
-		(yy_buffer_stack) = (struct yy_buffer_state**)wcspihrealloc
-								((yy_buffer_stack),
-								num_to_alloc * sizeof(struct yy_buffer_state*)
-								);
-		if ( ! (yy_buffer_stack) )
-			YY_FATAL_ERROR( "out of dynamic memory in wcspihensure_buffer_stack()" );
-
-		/* zero only the new slots.*/
-		memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
-		(yy_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. 
- */
-YY_BUFFER_STATE wcspih_scan_buffer  (char * base, yy_size_t  size )
-{
-	YY_BUFFER_STATE b;
-    
-	if ( size < 2 ||
-	     base[size-2] != YY_END_OF_BUFFER_CHAR ||
-	     base[size-1] != YY_END_OF_BUFFER_CHAR )
-		/* They forgot to leave room for the EOB's. */
-		return 0;
-
-	b = (YY_BUFFER_STATE) wcspihalloc(sizeof( struct yy_buffer_state )  );
-	if ( ! b )
-		YY_FATAL_ERROR( "out of dynamic memory in wcspih_scan_buffer()" );
-
-	b->yy_buf_size = size - 2;	/* "- 2" to take care of EOB's */
-	b->yy_buf_pos = b->yy_ch_buf = base;
-	b->yy_is_our_buffer = 0;
-	b->yy_input_file = 0;
-	b->yy_n_chars = b->yy_buf_size;
-	b->yy_is_interactive = 0;
-	b->yy_at_bol = 1;
-	b->yy_fill_buffer = 0;
-	b->yy_buffer_status = YY_BUFFER_NEW;
-
-	wcspih_switch_to_buffer(b  );
-
-	return b;
-}
-
-/** Setup the input buffer state to scan a string. The next call to wcspihlex() will
- * scan from a @e copy of @a str.
- * @param yystr 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
- *       wcspih_scan_bytes() instead.
- */
-YY_BUFFER_STATE wcspih_scan_string (yyconst char * yystr )
-{
-    
-	return wcspih_scan_bytes(yystr,strlen(yystr) );
-}
-
-/** Setup the input buffer state to scan the given bytes. The next call to wcspihlex() will
- * scan from a @e copy of @a bytes.
- * @param yybytes the byte buffer to scan
- * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
- * 
- * @return the newly allocated buffer state object.
- */
-YY_BUFFER_STATE wcspih_scan_bytes  (yyconst char * yybytes, int  _yybytes_len )
-{
-	YY_BUFFER_STATE b;
-	char *buf;
-	yy_size_t n;
-	int i;
-    
-	/* Get memory for full buffer, including space for trailing EOB's. */
-	n = _yybytes_len + 2;
-	buf = (char *) wcspihalloc(n  );
-	if ( ! buf )
-		YY_FATAL_ERROR( "out of dynamic memory in wcspih_scan_bytes()" );
-
-	for ( i = 0; i < _yybytes_len; ++i )
-		buf[i] = yybytes[i];
-
-	buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
-
-	b = wcspih_scan_buffer(buf,n );
-	if ( ! b )
-		YY_FATAL_ERROR( "bad buffer in wcspih_scan_bytes()" );
-
-	/* It's okay to grow etc. this buffer, and we should throw it
-	 * away when we're done.
-	 */
-	b->yy_is_our_buffer = 1;
-
-	return b;
-}
-
-#ifndef YY_EXIT_FAILURE
-#define YY_EXIT_FAILURE 2
-#endif
-
-static void yy_fatal_error (yyconst char* msg )
-{
-    	(void) fprintf( stderr, "%s\n", msg );
-	exit( YY_EXIT_FAILURE );
-}
-
-/* Redefine yyless() so it works in section 3 code. */
-
-#undef yyless
-#define yyless(n) \
-	do \
-		{ \
-		/* Undo effects of setting up wcspihtext. */ \
-        int yyless_macro_arg = (n); \
-        YY_LESS_LINENO(yyless_macro_arg);\
-		wcspihtext[wcspihleng] = (yy_hold_char); \
-		(yy_c_buf_p) = wcspihtext + yyless_macro_arg; \
-		(yy_hold_char) = *(yy_c_buf_p); \
-		*(yy_c_buf_p) = '\0'; \
-		wcspihleng = yyless_macro_arg; \
-		} \
-	while ( 0 )
-
-/* Accessor  methods (get/set functions) to struct members. */
-
-/** Get the current line number.
- * 
- */
-int wcspihget_lineno  (void)
-{
-        
-    return wcspihlineno;
-}
-
-/** Get the input stream.
- * 
- */
-FILE *wcspihget_in  (void)
-{
-        return wcspihin;
-}
-
-/** Get the output stream.
- * 
- */
-FILE *wcspihget_out  (void)
-{
-        return wcspihout;
-}
-
-/** Get the length of the current token.
- * 
- */
-int wcspihget_leng  (void)
-{
-        return wcspihleng;
-}
-
-/** Get the current token.
- * 
- */
-
-char *wcspihget_text  (void)
-{
-        return wcspihtext;
-}
-
-/** Set the current line number.
- * @param line_number
- * 
- */
-void wcspihset_lineno (int  line_number )
-{
-    
-    wcspihlineno = line_number;
-}
-
-/** Set the input stream. This does not discard the current
- * input buffer.
- * @param in_str A readable stream.
- * 
- * @see wcspih_switch_to_buffer
- */
-void wcspihset_in (FILE *  in_str )
-{
-        wcspihin = in_str ;
-}
-
-void wcspihset_out (FILE *  out_str )
-{
-        wcspihout = out_str ;
-}
-
-int wcspihget_debug  (void)
-{
-        return wcspih_flex_debug;
-}
-
-void wcspihset_debug (int  bdebug )
-{
-        wcspih_flex_debug = bdebug ;
-}
-
-static int yy_init_globals (void)
-{
-        /* Initialization is the same as for the non-reentrant scanner.
-     * This function is called from wcspihlex_destroy(), so don't allocate here.
-     */
-
-    (yy_buffer_stack) = 0;
-    (yy_buffer_stack_top) = 0;
-    (yy_buffer_stack_max) = 0;
-    (yy_c_buf_p) = (char *) 0;
-    (yy_init) = 0;
-    (yy_start) = 0;
-
-/* Defined in main.c */
-#ifdef YY_STDINIT
-    wcspihin = stdin;
-    wcspihout = stdout;
-#else
-    wcspihin = (FILE *) 0;
-    wcspihout = (FILE *) 0;
-#endif
-
-    /* For future reference: Set errno on error, since we are called by
-     * wcspihlex_init()
-     */
-    return 0;
-}
-
-/* wcspihlex_destroy is for both reentrant and non-reentrant scanners. */
-int wcspihlex_destroy  (void)
-{
-    
-    /* Pop the buffer stack, destroying each element. */
-	while(YY_CURRENT_BUFFER){
-		wcspih_delete_buffer(YY_CURRENT_BUFFER  );
-		YY_CURRENT_BUFFER_LVALUE = NULL;
-		wcspihpop_buffer_state();
-	}
-
-	/* Destroy the stack itself. */
-	wcspihfree((yy_buffer_stack) );
-	(yy_buffer_stack) = NULL;
-
-    /* Reset the globals. This is important in a non-reentrant scanner so the next time
-     * wcspihlex() is called, initialization will occur. */
-    yy_init_globals( );
-
-    return 0;
-}
-
-/*
- * Internal utility routines.
- */
-
-#ifndef yytext_ptr
-static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
-{
-	register int i;
-	for ( i = 0; i < n; ++i )
-		s1[i] = s2[i];
-}
-#endif
-
-#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * s )
-{
-	register int n;
-	for ( n = 0; s[n]; ++n )
-		;
-
-	return n;
-}
-#endif
-
-void *wcspihalloc (yy_size_t  size )
-{
-	return (void *) malloc( size );
-}
-
-void *wcspihrealloc  (void * ptr, yy_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 wcspihfree (void * ptr )
-{
-	free( (char *) ptr );	/* see wcspihrealloc() for (char *) cast */
-}
-
-#define YYTABLES_NAME "yytables"
-
-#line 1024 "wcspih.l"
-
-
-
-/*----------------------------------------------------------------------------
-* Determine the number of coordinate representations (up to 27) and the
-* number of coordinate axes in each, and count the number of PVi_ma and
-* PSi_ma keywords in each representation.
-*---------------------------------------------------------------------------*/
-
-void wcspih_naxes(int naxis, int i, int j, char a, int alts[], int *npptr)
-
-{
-  /* On the first pass alts[] is used to determine the number of axes */
-  /* for each of the 27 possible alternate coordinate descriptions.   */
-  int ialt, *ip;
-
-  if (a == 0) {
-    return;
-  }
-
-  ialt = 0;
-  if (a != ' ') {
-    ialt = a - 'A' + 1;
-  }
-
-  ip = alts + ialt;
-
-  if (*ip < naxis) {
-    *ip = naxis;
-  }
-
-  /* i or j can be greater than naxis. */
-  if (*ip < i) {
-    *ip = i;
-  }
-
-  if (*ip < j) {
-    *ip = j;
-  }
-
-  if (npptr) {
-    npptr[ialt]++;
-  }
-}
-
-
-/*----------------------------------------------------------------------------
-* Allocate memory for an array of the required number of wcsprm structs and
-* initialize each of them.
-*---------------------------------------------------------------------------*/
-
-int wcspih_inits(
-  int naxis,
-  int alts[],
-  int npv[],
-  int nps[],
-  int *nwcs,
-  struct wcsprm **wcs)
-
-{
-  int ialt, npsmax, npvmax, status = 0;
-  struct wcsprm *wcsp;
-
-  /* Find the number of coordinate descriptions. */
-  *nwcs = 0;
-  for (ialt = 0; ialt < 27; ialt++) {
-    if (alts[ialt]) (*nwcs)++;
-  }
-
-  if (!(*nwcs) && naxis) {
-    /* NAXIS is non-zero but there were no WCS keywords with an alternate
-       version code; create a default WCS with blank alternate version. */
-    wcspih_naxes(naxis, 0, 0, ' ', alts, 0x0);
-    *nwcs = 1;
-  }
-
-  if (*nwcs) {
-    /* Allocate memory for the required number of wcsprm structs. */
-    if (!(*wcs = calloc(*nwcs, sizeof(struct wcsprm)))) {
-      return 2;
-    }
-
-    /* Record the current values of NPVMAX and NPSMAX. */
-    npvmax = wcsnpv(-1);
-    npsmax = wcsnps(-1);
-
-    /* Initialize each wcsprm struct. */
-    wcsp = *wcs;
-    *nwcs = 0;
-    for (ialt = 0; ialt < 27; ialt++) {
-      if (alts[ialt]) {
-        wcsp->flag = -1;
-        wcsnpv(npv[ialt]);
-        wcsnps(nps[ialt]);
-        if ((status = wcsini(1, alts[ialt], wcsp))) {
-          wcsvfree(nwcs, wcs);
-          break;
-        }
-
-        /* Record the alternate version code. */
-        if (ialt) {
-          wcsp->alt[0] = 'A' + ialt - 1;
-        }
-
-        /* On the second pass alts[] indexes the array of wcsprm structs. */
-        alts[ialt] = (*nwcs)++;
-
-        wcsp++;
-      }
-    }
-
-    /* Restore the original values of NPVMAX and NPSMAX. */
-    wcsnpv(npvmax);
-    wcsnps(npsmax);
-  }
-
-  return status;
-}
-
-
-/*----------------------------------------------------------------------------
-* Interpret special keywords encountered for each coordinate representation.
-*---------------------------------------------------------------------------*/
-
-int wcspih_final(
-  int alts[],
-  double epoch[],
-  double vsource[],
-  int *nwcs,
-  struct wcsprm **wcs)
-
-{
-  int ialt, status;
-  double beta, c = 299792458.0;
-
-  for (ialt = 0; ialt < *nwcs; ialt++) {
-    /* Check for EPOCH overriding EQUINOXa. */
-    if (undefined((*wcs+ialt)->equinox) && !undefined(epoch[ialt])) {
-      /* Set EQUINOXa. */
-      (*wcs+ialt)->equinox = epoch[ialt];
-    }
-
-    /* Check for VSOURCEa overriding ZSOURCEa. */
-    if (undefined((*wcs+ialt)->zsource) && !undefined(vsource[ialt])) {
-      /* Convert relativistic Doppler velocity to redshift. */
-      beta = vsource[ialt]/c;
-      (*wcs+ialt)->zsource = (1.0+beta)/sqrt(1.0 - beta*beta) - 1.0;
-    }
-
-    /* Interpret -TAB header keywords. */
-    if ((status = wcstab(*wcs+ialt))) {
-       wcsvfree(nwcs, wcs);
-       return status;
-    }
-  }
-
-  return 0;
-}
-
diff --git a/astropy/wcs/src/wcslib/C/flexed/wcsulex.c b/astropy/wcs/src/wcslib/C/flexed/wcsulex.c
deleted file mode 100644
index b47a867..0000000
--- a/astropy/wcs/src/wcslib/C/flexed/wcsulex.c
+++ /dev/null
@@ -1,9429 +0,0 @@
-#line 2 "wcsulex.c"
-
-#line 4 "wcsulex.c"
-
-#define  YY_INT_ALIGNED short int
-
-/* A lexical scanner generated by flex */
-
-#define yy_create_buffer wcsulex_create_buffer
-#define yy_delete_buffer wcsulex_delete_buffer
-#define yy_flex_debug wcsulex_flex_debug
-#define yy_init_buffer wcsulex_init_buffer
-#define yy_flush_buffer wcsulex_flush_buffer
-#define yy_load_buffer_state wcsulex_load_buffer_state
-#define yy_switch_to_buffer wcsulex_switch_to_buffer
-#define yyin wcsulexin
-#define yyleng wcsulexleng
-#define yylex wcsulexlex
-#define yylineno wcsulexlineno
-#define yyout wcsulexout
-#define yyrestart wcsulexrestart
-#define yytext wcsulextext
-#define yywrap wcsulexwrap
-#define yyalloc wcsulexalloc
-#define yyrealloc wcsulexrealloc
-#define yyfree wcsulexfree
-
-#define FLEX_SCANNER
-#define YY_FLEX_MAJOR_VERSION 2
-#define YY_FLEX_MINOR_VERSION 5
-#define YY_FLEX_SUBMINOR_VERSION 35
-#if YY_FLEX_SUBMINOR_VERSION > 0
-#define FLEX_BETA
-#endif
-
-/* First, we deal with  platform-specific or compiler-specific issues. */
-
-/* begin standard C headers. */
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <stdlib.h>
-
-/* end standard C headers. */
-
-/* flex integer type definitions */
-
-#ifndef FLEXINT_H
-#define FLEXINT_H
-
-/* C99 systems have <inttypes.h>. 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 <inttypes.h>
-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;
-
-/* 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 /* ! C99 */
-
-#endif /* ! FLEXINT_H */
-
-#ifdef __cplusplus
-
-/* The "const" storage-class-modifier is valid. */
-#define YY_USE_CONST
-
-#else	/* ! __cplusplus */
-
-/* C99 requires __STDC__ to be defined as 1. */
-#if defined (__STDC__)
-
-#define YY_USE_CONST
-
-#endif	/* defined (__STDC__) */
-#endif	/* ! __cplusplus */
-
-#ifdef YY_USE_CONST
-#define yyconst const
-#else
-#define yyconst
-#endif
-
-/* Returned upon end-of-file. */
-#define YY_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 YY_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 (yy_start) = 1 + 2 *
-
-/* Translate the current start state into a value that can be later handed
- * to BEGIN to return to the state.  The YYSTATE alias is for lex
- * compatibility.
- */
-#define YY_START (((yy_start) - 1) / 2)
-#define YYSTATE YY_START
-
-/* Action number for EOF rule of a given start state. */
-#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
-
-/* Special action meaning "start processing a new file". */
-#define YY_NEW_FILE wcsulexrestart(wcsulexin  )
-
-#define YY_END_OF_BUFFER_CHAR 0
-
-/* Size of default input buffer. */
-#ifndef YY_BUF_SIZE
-#ifdef __ia64__
-/* On IA-64, the buffer size is 16k, not 8k.
- * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
- * Ditto for the __ia64__ case accordingly.
- */
-#define YY_BUF_SIZE 32768
-#else
-#define YY_BUF_SIZE 16384
-#endif /* __ia64__ */
-#endif
-
-/* The state buf must be large enough to hold one state per character in the main buffer.
- */
-#define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
-
-#ifndef YY_TYPEDEF_YY_BUFFER_STATE
-#define YY_TYPEDEF_YY_BUFFER_STATE
-typedef struct yy_buffer_state *YY_BUFFER_STATE;
-#endif
-
-extern int wcsulexleng;
-
-extern FILE *wcsulexin, *wcsulexout;
-
-#define EOB_ACT_CONTINUE_SCAN 0
-#define EOB_ACT_END_OF_FILE 1
-#define EOB_ACT_LAST_MATCH 2
-
-#define YY_LESS_LINENO(n)
-    
-/* Return all but the first "n" matched characters back to the input stream. */
-#define yyless(n) \
-	do \
-		{ \
-		/* Undo effects of setting up wcsulextext. */ \
-        int yyless_macro_arg = (n); \
-        YY_LESS_LINENO(yyless_macro_arg);\
-		*yy_cp = (yy_hold_char); \
-		YY_RESTORE_YY_MORE_OFFSET \
-		(yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
-		YY_DO_BEFORE_ACTION; /* set up wcsulextext again */ \
-		} \
-	while ( 0 )
-
-#define unput(c) yyunput( c, (yytext_ptr)  )
-
-#ifndef YY_TYPEDEF_YY_SIZE_T
-#define YY_TYPEDEF_YY_SIZE_T
-typedef size_t yy_size_t;
-#endif
-
-#ifndef YY_STRUCT_YY_BUFFER_STATE
-#define YY_STRUCT_YY_BUFFER_STATE
-struct yy_buffer_state
-	{
-	FILE *yy_input_file;
-
-	char *yy_ch_buf;		/* input buffer */
-	char *yy_buf_pos;		/* current position in input buffer */
-
-	/* Size of input buffer in bytes, not including room for EOB
-	 * characters.
-	 */
-	yy_size_t yy_buf_size;
-
-	/* Number of characters read into yy_ch_buf, not including EOB
-	 * characters.
-	 */
-	int yy_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 yy_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 yy_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 yy_at_bol;
-
-    int yy_bs_lineno; /**< The line count. */
-    int yy_bs_column; /**< The column count. */
-    
-	/* Whether to try to fill the input buffer when we reach the
-	 * end of it.
-	 */
-	int yy_fill_buffer;
-
-	int yy_buffer_status;
-
-#define YY_BUFFER_NEW 0
-#define YY_BUFFER_NORMAL 1
-	/* When an EOF's been seen but there's still some text to process
-	 * then we mark the buffer as YY_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 wcsulexrestart()), so that the user can continue scanning by
-	 * just pointing wcsulexin at a new input file.
-	 */
-#define YY_BUFFER_EOF_PENDING 2
-
-	};
-#endif /* !YY_STRUCT_YY_BUFFER_STATE */
-
-/* Stack of input buffers. */
-static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
-static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
-static YY_BUFFER_STATE * yy_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 YY_CURRENT_BUFFER ( (yy_buffer_stack) \
-                          ? (yy_buffer_stack)[(yy_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 YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
-
-/* yy_hold_char holds the character lost when wcsulextext is formed. */
-static char yy_hold_char;
-static int yy_n_chars;		/* number of characters read into yy_ch_buf */
-int wcsulexleng;
-
-/* Points to current character in buffer. */
-static char *yy_c_buf_p = (char *) 0;
-static int yy_init = 0;		/* whether we need to initialize */
-static int yy_start = 0;	/* start state number */
-
-/* Flag which is used to allow wcsulexwrap()'s to do buffer switches
- * instead of setting up a fresh wcsulexin.  A bit of a hack ...
- */
-static int yy_did_buffer_switch_on_eof;
-
-void wcsulexrestart (FILE *input_file  );
-void wcsulex_switch_to_buffer (YY_BUFFER_STATE new_buffer  );
-YY_BUFFER_STATE wcsulex_create_buffer (FILE *file,int size  );
-void wcsulex_delete_buffer (YY_BUFFER_STATE b  );
-void wcsulex_flush_buffer (YY_BUFFER_STATE b  );
-void wcsulexpush_buffer_state (YY_BUFFER_STATE new_buffer  );
-void wcsulexpop_buffer_state (void );
-
-static void wcsulexensure_buffer_stack (void );
-static void wcsulex_load_buffer_state (void );
-static void wcsulex_init_buffer (YY_BUFFER_STATE b,FILE *file  );
-
-#define YY_FLUSH_BUFFER wcsulex_flush_buffer(YY_CURRENT_BUFFER )
-
-YY_BUFFER_STATE wcsulex_scan_buffer (char *base,yy_size_t size  );
-YY_BUFFER_STATE wcsulex_scan_string (yyconst char *yy_str  );
-YY_BUFFER_STATE wcsulex_scan_bytes (yyconst char *bytes,int len  );
-
-void *wcsulexalloc (yy_size_t  );
-void *wcsulexrealloc (void *,yy_size_t  );
-void wcsulexfree (void *  );
-
-#define yy_new_buffer wcsulex_create_buffer
-
-#define yy_set_interactive(is_interactive) \
-	{ \
-	if ( ! YY_CURRENT_BUFFER ){ \
-        wcsulexensure_buffer_stack (); \
-		YY_CURRENT_BUFFER_LVALUE =    \
-            wcsulex_create_buffer(wcsulexin,YY_BUF_SIZE ); \
-	} \
-	YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
-	}
-
-#define yy_set_bol(at_bol) \
-	{ \
-	if ( ! YY_CURRENT_BUFFER ){\
-        wcsulexensure_buffer_stack (); \
-		YY_CURRENT_BUFFER_LVALUE =    \
-            wcsulex_create_buffer(wcsulexin,YY_BUF_SIZE ); \
-	} \
-	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
-	}
-
-#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
-
-/* Begin user sect3 */
-
-#define wcsulexwrap(n) 1
-#define YY_SKIP_YYWRAP
-
-typedef char YY_CHAR;
-
-FILE *wcsulexin = (FILE *) 0, *wcsulexout = (FILE *) 0;
-
-typedef int yy_state_type;
-
-extern int wcsulexlineno;
-
-int wcsulexlineno = 1;
-
-extern char *wcsulextext;
-#define yytext_ptr wcsulextext
-static yyconst flex_int16_t yy_nxt[][128] =
-    {
-    {
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0
-    },
-
-    {
-       13,   14,   14,   14,   14,   14,   14,   14,   14,   14,
-       15,   14,   14,   14,   14,   14,   14,   14,   14,   14,
-       14,   14,   14,   14,   14,   14,   14,   14,   14,   14,
-       14,   14,   16,   14,   14,   14,   14,   14,   14,   14,
-       17,   14,   18,   14,   14,   14,   18,   19,   14,   14,
-       14,   14,   14,   14,   14,   14,   14,   14,   14,   14,
-       14,   14,   14,   14,   14,   20,   21,   22,   23,   24,
-
-       22,   25,   26,   14,   27,   28,   14,   24,   22,   29,
-       30,   14,   31,   32,   33,   14,   22,   34,   14,   24,
-       24,   14,   14,   35,   14,   14,   14,   36,   37,   38,
-       39,   40,   41,   28,   42,   14,   14,   24,   43,   44,
-       41,   29,   45,   14,   46,   47,   14,   48,   49,   14,
-       14,   50,   41,   14,   14,   14,   14,   14
-    },
-
-    {
-       13,   14,   14,   14,   14,   14,   14,   14,   14,   14,
-       15,   14,   14,   14,   14,   14,   14,   14,   14,   14,
-       14,   14,   14,   14,   14,   14,   14,   14,   14,   14,
-       14,   14,   51,   14,   14,   14,   14,   14,   14,   14,
-
-       17,   14,   52,   14,   14,   14,   52,   19,   14,   53,
-       14,   14,   14,   14,   14,   14,   14,   14,   14,   14,
-       14,   14,   14,   14,   14,   20,   21,   22,   23,   24,
-       22,   25,   26,   14,   27,   28,   14,   24,   22,   29,
-       30,   14,   31,   32,   33,   14,   22,   34,   14,   24,
-       24,   54,   14,   35,   14,   14,   14,   36,   37,   38,
-       39,   55,   41,   28,   42,   14,   14,   24,   56,   44,
-       41,   29,   45,   14,   46,   47,   14,   48,   49,   14,
-       14,   50,   41,   14,   14,   14,   14,   14
-    },
-
-    {
-       13,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       58,   59,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57
-    },
-
-    {
-       13,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       58,   59,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,   57,   57,   57,   57
-    },
-
-    {
-       13,   60,   60,   60,   60,   60,   60,   60,   60,   60,
-       15,   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,
-       60,   60,   60,   60,   60,   60,   60,   60,   60,   61,
-       60,   62,   60,   60,   60,   60,   60,   63,   60,   60,
-       64,   60,   60,   60,   65,   60,   60,   60,   60,   66,
-       67,   60,   60,   60,   60,   60,   60,   68,   60,   69,
-       70,   60,   71,   60,   72,   60,   60,   73,   60,   74,
-       75,   60,   76,   60,   60,   60,   60,   77,   60,   60,
-       60,   78,   79,   60,   60,   60,   60,   60
-    },
-
-    {
-       13,   60,   60,   60,   60,   60,   60,   60,   60,   60,
-       15,   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,
-       60,   60,   60,   60,   60,   60,   60,   60,   60,   61,
-       60,   62,   60,   60,   60,   60,   60,   63,   60,   60,
-       64,   60,   60,   60,   65,   60,   60,   60,   60,   66,
-       67,   60,   60,   60,   60,   60,   60,   68,   60,   69,
-       70,   60,   71,   60,   72,   60,   60,   73,   60,   74,
-       75,   60,   76,   60,   60,   60,   60,   77,   60,   60,
-
-       60,   78,   79,   60,   60,   60,   60,   60
-    },
-
-    {
-       13,   80,   80,   80,   80,   80,   80,   80,   80,   80,
-       15,   80,   80,   80,   80,   80,   80,   80,   80,   80,
-       80,   80,   80,   80,   80,   80,   80,   80,   80,   80,
-       80,   80,   80,   80,   80,   80,   80,   80,   80,   80,
-       80,   80,   80,   80,   80,   80,   80,   80,   80,   80,
-       80,   80,   80,   80,   80,   80,   80,   80,   80,   80,
-       80,   80,   80,   80,   80,   81,   82,   83,   84,   80,
-       85,   86,   87,   80,   88,   89,   80,   80,   90,   91,
-       92,   80,   93,   94,   95,   80,   96,   97,   80,   80,
-
-       80,   80,   80,   80,   80,   80,   80,   98,   99,  100,
-      101,  102,   80,  103,  104,   80,   80,   80,  105,  106,
-       80,   91,  107,   80,  108,  109,   80,  110,  111,   80,
-       80,  112,   80,   80,   80,   80,   80,   80
-    },
-
-    {
-       13,   80,   80,   80,   80,   80,   80,   80,   80,   80,
-       15,   80,   80,   80,   80,   80,   80,   80,   80,   80,
-       80,   80,   80,   80,   80,   80,   80,   80,   80,   80,
-       80,   80,   80,   80,   80,   80,   80,   80,   80,   80,
-       80,   80,   80,   80,   80,   80,   80,   80,   80,   80,
-       80,   80,   80,   80,   80,   80,   80,   80,   80,   80,
-
-       80,   80,   80,   80,   80,   81,   82,   83,   84,   80,
-       85,   86,   87,   80,   88,   89,   80,   80,   90,   91,
-       92,   80,   93,   94,   95,   80,   96,   97,   80,   80,
-       80,   80,   80,   80,   80,   80,   80,   98,   99,  100,
-      101,  102,   80,  103,  104,   80,   80,   80,  105,  106,
-       80,   91,  107,   80,  108,  109,   80,  110,  111,   80,
-       80,  112,   80,   80,   80,   80,   80,   80
-    },
-
-    {
-       13,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-       15,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-
-      113,  113,  114,  113,  113,  113,  113,  113,  113,  113,
-      115,  113,  116,  117,  113,  117,  118,  119,  113,  120,
-      120,  120,  120,  120,  120,  120,  120,  120,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  121,  122,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113
-
-    },
-
-    {
-       13,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-       15,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  114,  113,  113,  113,  113,  113,  113,  113,
-      115,  113,  116,  117,  113,  117,  118,  119,  113,  120,
-      120,  120,  120,  120,  120,  120,  120,  120,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  121,  122,  113,  113,  113,  113,  113,
-
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113
-    },
-
-    {
-       13,  123,  123,  123,  123,  123,  123,  123,  123,  123,
-       15,  123,  123,  123,  123,  123,  123,  123,  123,  123,
-      123,  123,  123,  123,  123,  123,  123,  123,  123,  123,
-      123,  123,  123,  123,  123,  123,  123,  123,  123,  123,
-      123,  123,  123,  123,  123,  123,  123,  123,  123,  123,
-      123,  123,  123,  123,  123,  123,  123,  123,  123,  123,
-      123,  123,  123,  123,  123,  123,  123,  123,  123,  123,
-
-      123,  123,  123,  123,  123,  123,  123,  123,  123,  123,
-      123,  123,  123,  123,  123,  123,  123,  123,  123,  123,
-      123,  123,  123,  123,  123,  123,  123,  123,  123,  123,
-      123,  123,  123,  123,  123,  123,  123,  123,  123,  123,
-      123,  123,  123,  123,  123,  123,  123,  123,  123,  123,
-      123,  123,  123,  123,  123,  123,  123,  123
-    },
-
-    {
-       13,  123,  123,  123,  123,  123,  123,  123,  123,  123,
-       15,  123,  123,  123,  123,  123,  123,  123,  123,  123,
-      123,  123,  123,  123,  123,  123,  123,  123,  123,  123,
-      123,  123,  123,  123,  123,  123,  123,  123,  123,  123,
-
-      123,  123,  123,  123,  123,  123,  123,  123,  123,  123,
-      123,  123,  123,  123,  123,  123,  123,  123,  123,  123,
-      123,  123,  123,  123,  123,  123,  123,  123,  123,  123,
-      123,  123,  123,  123,  123,  123,  123,  123,  123,  123,
-      123,  123,  123,  123,  123,  123,  123,  123,  123,  123,
-      123,  123,  123,  123,  123,  123,  123,  123,  123,  123,
-      123,  123,  123,  123,  123,  123,  123,  123,  123,  123,
-      123,  123,  123,  123,  123,  123,  123,  123,  123,  123,
-      123,  123,  123,  123,  123,  123,  123,  123
-    },
-
-    {
-      -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,  -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,  -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,  -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
-    },
-
-    {
-       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,  -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
-    },
-
-    {
-       13,  -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,  -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
-    },
-
-    {
-       13,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
-      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
-
-      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
-      -16,  -16,  124,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
-      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
-      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
-      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
-      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
-      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
-      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
-      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
-      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
-
-      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16
-    },
-
-    {
-       13,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
-      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
-      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
-      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
-      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
-      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
-      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
-      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
-      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
-
-      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
-      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
-      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
-      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17
-    },
-
-    {
-       13,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,
-      -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,
-      -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,
-      -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,
-      -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,
-      -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,
-
-      -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,
-      -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,
-      -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,
-      -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,
-      -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,
-      -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,
-      -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18
-    },
-
-    {
-       13,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,
-      -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,
-      -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,
-
-      -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,
-      -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,
-      -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,
-      -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,
-      -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,
-      -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,
-      -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,
-      -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,
-      -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,
-      -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19
-
-    },
-
-    {
-       13,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,
-      -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,
-      -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,
-      -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,
-      -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,
-      -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,
-      -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,
-      -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,
-      -20,  -20,  -20,  -20,  -20,  125,  -20,  -20,  -20,  -20,
-      -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,
-
-      -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,
-      126,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,
-      -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20
-    },
-
-    {
-       13,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,
-      -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,
-      -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,
-      -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,
-      -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,
-      -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,
-      -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,
-
-      -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,
-      -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,
-      -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,
-      -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,
-      -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,
-      -21,  127,  -21,  -21,  -21,  -21,  -21,  -21
-    },
-
-    {
-       13,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,
-      -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,
-      -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,
-      -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,
-
-      -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,
-      -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,
-      -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,
-      -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,
-      -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,
-      -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,
-      -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,
-      -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,
-      -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22
-    },
-
-    {
-       13,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
-
-      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
-      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
-      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
-      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
-      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
-      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
-      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
-      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
-      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
-      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
-
-      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
-      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23
-    },
-
-    {
-       13,  -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,  -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,  128,  129,  130,  -24,  -24,
-      130,  131,  132,  -24,  133,  128,  -24,  -24,  130,  134,
-
-      135,  -24,  131,  130,  130,  -24,  130,  136,  -24,  -24,
-      -24,  -24,  -24,  -24,  -24,  -24,  -24,  137,  138,  139,
-      -24,  140,  -24,  128,  -24,  -24,  -24,  -24,  141,  142,
-      -24,  134,  143,  -24,  144,  145,  -24,  -24,  -24,  -24,
-      -24,  146,  -24,  -24,  -24,  -24,  -24,  -24
-    },
-
-    {
-       13,  -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,  -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,  128,  129,  130,  -25,  -25,
-      130,  131,  132,  -25,  133,  128,  -25,  -25,  130,  134,
-      135,  -25,  131,  130,  130,  -25,  130,  136,  -25,  -25,
-      -25,  -25,  -25,  -25,  -25,  -25,  -25,  137,  138,  139,
-      -25,  140,  -25,  128,  -25,  -25,  -25,  -25,  141,  142,
-      -25,  134,  143,  -25,  144,  145,  -25,  -25,  -25,  -25,
-      -25,  146,  -25,  -25,  -25,  -25,  -25,  -25
-    },
-
-    {
-       13,  -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,  -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,  -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,  -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,  147,  -26,  -26,  -26,  -26,  -26
-    },
-
-    {
-       13,  -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,  -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,  -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,  -27,  -27,  -27,
-      -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,
-      -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,
-      -27,  148,  -27,  -27,  -27,  -27,  -27,  -27
-    },
-
-    {
-       13,  -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,  -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
-    },
-
-    {
-       13,  -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,  -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,  149,  -29,  -29,  -29,  -29,  -29,
-      -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,
-      -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29
-
-    },
-
-    {
-       13,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
-      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
-      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
-      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
-      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
-      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
-      -30,  -30,  -30,  -30,  -30,  128,  129,  130,  -30,  -30,
-      130,  131,  132,  -30,  133,  128,  -30,  -30,  130,  134,
-      135,  -30,  131,  130,  130,  -30,  130,  136,  -30,  -30,
-      -30,  -30,  -30,  -30,  -30,  -30,  -30,  150,  138,  139,
-
-      -30,  140,  -30,  128,  -30,  -30,  -30,  -30,  141,  142,
-      -30,  134,  143,  -30,  144,  145,  -30,  -30,  -30,  -30,
-      -30,  146,  -30,  -30,  -30,  -30,  -30,  -30
-    },
-
-    {
-       13,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
-      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
-      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
-      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
-      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
-      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
-      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
-
-      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
-      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
-      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
-      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
-      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
-      -31,  151,  -31,  -31,  -31,  -31,  -31,  -31
-    },
-
-    {
-       13,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
-      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
-      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
-      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
-
-      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
-      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
-      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
-      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
-      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
-      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
-      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
-      -32,  -32,  -32,  -32,  -32,  -32,  -32,  152,  -32,  -32,
-      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32
-    },
-
-    {
-       13,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
-
-      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
-      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
-      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
-      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
-      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
-      -33,  -33,  -33,  -33,  -33,  128,  129,  130,  -33,  -33,
-      130,  131,  132,  -33,  133,  128,  -33,  -33,  130,  134,
-      135,  -33,  131,  130,  130,  -33,  130,  136,  -33,  -33,
-      -33,  -33,  -33,  -33,  -33,  -33,  -33,  137,  138,  139,
-      -33,  140,  -33,  128,  -33,  -33,  -33,  -33,  141,  142,
-
-      -33,  134,  143,  -33,  144,  145,  -33,  -33,  -33,  -33,
-      -33,  146,  -33,  -33,  -33,  -33,  -33,  -33
-    },
-
-    {
-       13,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  147,  -34,
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34
-    },
-
-    {
-       13,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
-      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
-      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
-      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
-      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
-
-      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
-      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
-      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
-      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
-      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
-      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
-      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
-      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35
-    },
-
-    {
-       13,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
-      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
-
-      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
-      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
-      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
-      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
-      -36,  -36,  -36,  -36,  -36,  128,  -36,  130,  -36,  -36,
-      130,  131,  132,  -36,  133,  128,  -36,  -36,  130,  134,
-      135,  -36,  131,  130,  130,  -36,  130,  136,  -36,  -36,
-      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  153,  139,
-      154,  140,  -36,  128,  -36,  -36,  -36,  -36,  141,  155,
-      126,  134,  -36,  -36,  156,  145,  -36,  -36,  -36,  -36,
-
-      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36
-    },
-
-    {
-       13,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
-      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
-      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
-      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
-      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
-      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
-      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
-      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
-      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
-
-      -37,  -37,  -37,  -37,  -37,  -37,  -37,  157,  -37,  -37,
-      -37,  158,  -37,  -37,  -37,  159,  -37,  -37,  -37,  -37,
-      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
-      -37,  127,  -37,  -37,  -37,  -37,  -37,  -37
-    },
-
-    {
-       13,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
-      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
-      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
-      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
-      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
-      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
-
-      -38,  -38,  -38,  -38,  -38,  128,  -38,  130,  -38,  -38,
-      130,  131,  132,  -38,  133,  128,  -38,  -38,  130,  134,
-      135,  -38,  131,  130,  130,  -38,  130,  136,  -38,  -38,
-      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  153,  139,
-      160,  140,  -38,  128,  161,  -38,  -38,  -38,  141,  155,
-      -38,  162,  -38,  -38,  144,  145,  163,  -38,  -38,  -38,
-      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38
-    },
-
-    {
-       13,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
-      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
-      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
-
-      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
-      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
-      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
-      -39,  -39,  -39,  -39,  -39,  128,  -39,  130,  -39,  -39,
-      130,  131,  132,  -39,  133,  128,  -39,  -39,  130,  134,
-      135,  -39,  131,  130,  130,  -39,  130,  136,  -39,  -39,
-      -39,  -39,  -39,  -39,  -39,  -39,  -39,  164,  153,  139,
-      -39,  165,  -39,  128,  -39,  -39,  -39,  -39,  141,  155,
-      -39,  134,  -39,  -39,  144,  145,  -39,  -39,  -39,  -39,
-      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39
-
-    },
-
-    {
-       13,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
-      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
-      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
-      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
-      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
-      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
-      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
-      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
-      -40,  -40,  -40,  -40,  -40,  -40,  148,  -40,  -40,  -40,
-      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
-
-      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
-      -40,  -40,  -40,  -40,  166,  -40,  -40,  -40,  -40,  -40,
-      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40
-    },
-
-    {
-       13,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,
-      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,
-      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,
-      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,
-      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,
-      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,
-      -41,  -41,  -41,  -41,  -41,  128,  -41,  130,  -41,  -41,
-
-      130,  131,  132,  -41,  133,  128,  -41,  -41,  130,  134,
-      135,  -41,  131,  130,  130,  -41,  130,  136,  -41,  -41,
-      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  153,  139,
-      -41,  140,  -41,  128,  -41,  -41,  -41,  -41,  141,  155,
-      -41,  134,  -41,  -41,  144,  145,  -41,  -41,  -41,  -41,
-      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41
-    },
-
-    {
-       13,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
-      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
-      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
-      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
-
-      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
-      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
-      -42,  -42,  -42,  -42,  -42,  128,  129,  130,  -42,  -42,
-      130,  131,  132,  -42,  133,  128,  -42,  -42,  130,  134,
-      135,  -42,  131,  130,  130,  -42,  130,  136,  -42,  -42,
-      -42,  -42,  -42,  -42,  -42,  -42,  -42,  137,  138,  139,
-      -42,  140,  -42,  128,  -42,  -42,  -42,  -42,  141,  142,
-      -42,  134,  143,  -42,  144,  145,  -42,  -42,  -42,  -42,
-      -42,  146,  -42,  -42,  -42,  -42,  -42,  -42
-    },
-
-    {
-       13,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
-
-      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
-      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
-      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
-      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
-      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
-      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
-      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
-      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
-      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
-      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  147,
-
-      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
-      147,  167,  -43,  -43,  -43,  -43,  -43,  -43
-    },
-
-    {
-       13,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
-      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
-      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
-      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
-      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
-      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
-      -44,  -44,  -44,  -44,  -44,  128,  -44,  130,  -44,  -44,
-      130,  131,  132,  -44,  133,  128,  -44,  -44,  130,  134,
-
-      135,  -44,  131,  130,  130,  -44,  130,  136,  -44,  -44,
-      -44,  -44,  -44,  -44,  -44,  -44,  -44,  168,  153,  139,
-      -44,  140,  -44,  128,  -44,  169,  -44,  -44,  141,  155,
-      -44,  170,  -44,  -44,  144,  145,  -44,  -44,  -44,  -44,
-      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44
-    },
-
-    {
-       13,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
-      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
-      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
-      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
-      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
-
-      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
-      -45,  -45,  -45,  -45,  -45,  128,  -45,  130,  -45,  -45,
-      130,  131,  132,  -45,  133,  128,  -45,  -45,  130,  134,
-      135,  -45,  131,  130,  130,  -45,  130,  136,  -45,  -45,
-      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  153,  171,
-      -45,  140,  -45,  128,  172,  173,  -45,  -45,  141,  155,
-      -45,  134,  -45,  -45,  144,  145,  -45,  -45,  -45,  -45,
-      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45
-    },
-
-    {
-       13,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
-      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
-
-      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
-      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
-      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
-      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
-      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
-      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
-      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
-      -46,  -46,  -46,  -46,  -46,  -46,  -46,  174,  -46,  -46,
-      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
-      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
-
-      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46
-    },
-
-    {
-       13,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
-      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
-      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
-      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
-      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
-      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
-      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
-      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
-      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
-
-      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
-      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
-      -47,  175,  -47,  176,  160,  -47,  -47,  -47,  -47,  -47,
-      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47
-    },
-
-    {
-       13,  -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,  128,  -48,  130,  -48,  -48,
-      130,  131,  132,  -48,  133,  128,  -48,  -48,  130,  134,
-      135,  -48,  131,  130,  130,  -48,  130,  136,  -48,  -48,
-      -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  153,  139,
-      -48,  140,  -48,  128,  -48,  -48,  -48,  -48,  141,  155,
-      -48,  134,  -48,  -48,  144,  145,  -48,  -48,  -48,  -48,
-      -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48
-    },
-
-    {
-       13,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
-      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
-      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
-
-      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
-      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
-      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
-      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
-      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
-      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
-      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
-      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
-      -49,  177,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
-      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49
-
-    },
-
-    {
-       13,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
-      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
-      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
-      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
-      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
-      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
-      -50,  -50,  -50,  -50,  -50,  128,  -50,  130,  -50,  -50,
-      130,  131,  132,  -50,  133,  128,  -50,  -50,  130,  134,
-      135,  -50,  131,  130,  130,  -50,  130,  136,  -50,  -50,
-      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  153,  139,
-
-      -50,  140,  -50,  128,  -50,  -50,  -50,  -50,  141,  155,
-      -50,  134,  -50,  -50,  178,  145,  -50,  -50,  -50,  -50,
-      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50
-    },
-
-    {
-       13,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,  -51,  179,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51
-    },
-
-    {
-       13,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
-      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
-      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
-      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
-
-      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
-      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
-      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
-      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
-      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
-      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
-      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
-      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
-      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52
-    },
-
-    {
-       13,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
-
-      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
-      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
-      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
-      -53,  -53,  -53,  -53,  -53,  -53,  -53,  180,  181,  -53,
-      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
-      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
-      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
-      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
-      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
-      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
-
-      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
-      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53
-    },
-
-    {
-       13,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
-      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
-      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
-      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
-      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
-      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
-      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
-      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
-
-      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
-      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
-      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
-      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
-      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54
-    },
-
-    {
-       13,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
-      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
-      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
-      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
-      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
-
-      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
-      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
-      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
-      -55,  -55,  -55,  -55,  -55,  -55,  148,  -55,  -55,  -55,
-      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
-      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
-      -55,  -55,  -55,  -55,  166,  -55,  -55,  -55,  -55,  -55,
-      182,  -55,  -55,  -55,  -55,  -55,  -55,  -55
-    },
-
-    {
-       13,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
-      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
-
-      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
-      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
-      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
-      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
-      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
-      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
-      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
-      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
-      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  147,
-      183,  184,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
-
-      147,  167,  -56,  -56,  -56,  -56,  -56,  -56
-    },
-
-    {
-       13,  185,  185,  185,  185,  185,  185,  185,  185,  185,
-      185,  185,  185,  185,  185,  185,  185,  185,  185,  185,
-      185,  185,  185,  185,  185,  185,  185,  185,  185,  185,
-      185,  185,  185,  185,  185,  185,  185,  185,  185,  185,
-      -57,  -57,  185,  185,  185,  185,  185,  185,  185,  185,
-      185,  185,  185,  185,  185,  185,  185,  185,  185,  185,
-      185,  185,  185,  185,  185,  185,  185,  185,  185,  185,
-      185,  185,  185,  185,  185,  185,  185,  185,  185,  185,
-      185,  185,  185,  185,  185,  185,  185,  185,  185,  185,
-
-      185,  185,  185,  185,  185,  185,  185,  185,  185,  185,
-      185,  185,  185,  185,  185,  185,  185,  185,  185,  185,
-      185,  185,  185,  185,  185,  185,  185,  185,  185,  185,
-      185,  185,  185,  185,  185,  185,  185,  185
-    },
-
-    {
-       13,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
-      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
-      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
-      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
-      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
-      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
-
-      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
-      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
-      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
-      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
-      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
-      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
-      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58
-    },
-
-    {
-       13,  -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,  -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,  -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,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,
-      -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59
-
-    },
-
-    {
-       13,  -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,
-      -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,  -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
-    },
-
-    {
-       13,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
-      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
-      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
-      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
-      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
-      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
-      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
-
-      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
-      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
-      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
-      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
-      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
-      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61
-    },
-
-    {
-       13,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
-      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
-      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
-      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
-
-      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
-      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
-      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
-      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
-      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
-      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
-      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
-      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
-      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62
-    },
-
-    {
-       13,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
-
-      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
-      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
-      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
-      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
-      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
-      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
-      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
-      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
-      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
-      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
-
-      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
-      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63
-    },
-
-    {
-       13,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
-      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
-      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
-      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
-      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
-      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
-      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
-      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
-
-      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
-      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
-      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
-      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
-      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64
-    },
-
-    {
-       13,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
-      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
-      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
-      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
-      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
-
-      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
-      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
-      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
-      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
-      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
-      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
-      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
-      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65
-    },
-
-    {
-       13,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
-      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
-
-      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
-      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
-      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
-      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
-      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
-      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
-      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
-      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
-      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
-      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
-
-      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66
-    },
-
-    {
-       13,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67
-    },
-
-    {
-       13,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-
-      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68
-    },
-
-    {
-       13,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-
-      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69
-
-    },
-
-    {
-       13,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
-      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
-      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
-      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
-      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
-      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
-      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
-      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
-      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
-      -70,  -70,  -70,  -70,  -70,  -70,  -70,  186,  -70,  -70,
-
-      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
-      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
-      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70
-    },
-
-    {
-       13,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
-      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
-      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
-      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
-      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
-      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
-      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
-
-      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
-      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
-      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
-      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
-      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
-      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71
-    },
-
-    {
-       13,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
-      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
-      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
-      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
-
-      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
-      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
-      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
-      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
-      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
-      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
-      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
-      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
-      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72
-    },
-
-    {
-       13,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
-
-      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
-      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
-      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
-      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
-      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
-      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
-      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
-      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
-      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
-      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
-
-      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
-      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73
-    },
-
-    {
-       13,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
-      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
-      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
-      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
-      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
-      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
-      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
-      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
-
-      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
-      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
-      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
-      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
-      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74
-    },
-
-    {
-       13,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
-      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
-      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
-      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
-      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
-
-      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
-      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
-      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
-      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
-      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
-      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
-      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
-      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75
-    },
-
-    {
-       13,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
-      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
-
-      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
-      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
-      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
-      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
-      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
-      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
-      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
-      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
-      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
-      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
-
-      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76
-    },
-
-    {
-       13,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
-      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
-      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
-      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
-      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
-      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
-      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
-      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
-      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
-
-      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
-      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
-      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
-      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77
-    },
-
-    {
-       13,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
-      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
-      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
-      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
-      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
-      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
-
-      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
-      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
-      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
-      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
-      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
-      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
-      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78
-    },
-
-    {
-       13,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
-      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
-      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
-
-      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
-      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
-      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
-      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
-      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
-      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
-      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
-      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
-      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
-      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79
-
-    },
-
-    {
-       13,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
-      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
-      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
-      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
-      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
-      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
-      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
-      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
-      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
-      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
-
-      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
-      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
-      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80
-    },
-
-    {
-       13,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
-      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
-      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
-      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
-      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
-      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
-      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
-
-      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
-      -81,  -81,  -81,  -81,  -81,  187,  -81,  -81,  -81,  -81,
-      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
-      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
-      188,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
-      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81
-    },
-
-    {
-       13,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
-      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
-      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
-      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
-
-      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
-      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
-      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
-      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
-      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
-      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
-      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
-      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
-      -82,  189,  -82,  -82,  -82,  -82,  -82,  -82
-    },
-
-    {
-       13,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
-
-      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
-      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
-      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
-      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
-      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
-      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
-      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
-      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
-      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
-      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
-
-      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
-      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83
-    },
-
-    {
-       13,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
-      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
-      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
-      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
-      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
-      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
-      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
-      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
-
-      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
-      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
-      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
-      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
-      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84
-    },
-
-    {
-       13,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
-      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
-      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
-      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
-      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
-
-      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
-      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
-      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
-      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
-      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
-      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
-      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
-      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85
-    },
-
-    {
-       13,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
-      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
-
-      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
-      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
-      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
-      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
-      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
-      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
-      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
-      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
-      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
-      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
-
-      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86
-    },
-
-    {
-       13,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-
-      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-      -87,  -87,  190,  -87,  -87,  -87,  -87,  -87
-    },
-
-    {
-       13,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
-      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
-      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
-      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
-      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
-      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
-
-      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
-      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
-      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
-      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
-      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
-      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
-      -88,  191,  -88,  -88,  -88,  -88,  -88,  -88
-    },
-
-    {
-       13,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-
-      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89
-
-    },
-
-    {
-       13,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
-      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
-      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
-      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
-      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
-      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
-      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
-      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
-      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
-      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
-
-      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
-      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
-      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90
-    },
-
-    {
-       13,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
-      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
-      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
-      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
-      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
-      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
-      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
-
-      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
-      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
-      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
-      -91,  -91,  -91,  -91,  192,  -91,  -91,  -91,  -91,  -91,
-      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
-      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91
-    },
-
-    {
-       13,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
-      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
-      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
-      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
-
-      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
-      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
-      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
-      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
-      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
-      -92,  -92,  -92,  -92,  -92,  -92,  -92,  193,  -92,  -92,
-      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
-      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
-      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92
-    },
-
-    {
-       13,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-
-      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-
-      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-      -93,  194,  -93,  -93,  -93,  -93,  -93,  -93
-    },
-
-    {
-       13,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
-      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
-      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
-      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
-      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
-      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
-      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
-      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
-
-      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
-      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
-      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
-      -94,  -94,  -94,  -94,  -94,  -94,  -94,  195,  -94,  -94,
-      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94
-    },
-
-    {
-       13,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
-      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
-      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
-      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
-      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
-
-      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
-      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
-      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
-      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
-      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
-      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
-      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
-      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95
-    },
-
-    {
-       13,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
-      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
-
-      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
-      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
-      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
-      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
-      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
-      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
-      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
-      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
-      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
-      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
-
-      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96
-    },
-
-    {
-       13,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
-      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
-      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
-      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
-      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
-      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
-      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
-      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
-      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
-
-      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  196,  -97,
-      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
-      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
-      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97
-    },
-
-    {
-       13,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
-      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
-      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
-      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
-      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
-      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
-
-      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
-      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
-      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
-      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
-      197,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
-      188,  -98,  -98,  -98,  198,  -98,  -98,  -98,  -98,  -98,
-      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98
-    },
-
-    {
-       13,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-
-      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-      -99,  -99,  -99,  -99,  -99,  -99,  -99,  199,  -99,  -99,
-      -99,  200,  -99,  -99,  -99,  201,  -99,  -99,  -99,  -99,
-      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-      -99,  189,  -99,  -99,  -99,  -99,  -99,  -99
-
-    },
-
-    {
-       13, -100, -100, -100, -100, -100, -100, -100, -100, -100,
-     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
-     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
-     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
-     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
-     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
-     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
-     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
-     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
-     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
-
-      202, -100, -100, -100,  203, -100, -100, -100, -100, -100,
-     -100,  204, -100, -100, -100, -100,  205, -100, -100, -100,
-     -100, -100, -100, -100, -100, -100, -100, -100
-    },
-
-    {
-       13, -101, -101, -101, -101, -101, -101, -101, -101, -101,
-     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
-     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
-     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
-     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
-     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
-     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
-
-     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
-     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
-     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
-     -101,  206, -101, -101, -101, -101, -101, -101, -101, -101,
-     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
-     -101, -101, -101, -101, -101, -101, -101, -101
-    },
-
-    {
-       13, -102, -102, -102, -102, -102, -102, -102, -102, -102,
-     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
-     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
-     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
-
-     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
-     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
-     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
-     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
-     -102, -102, -102, -102, -102, -102,  207, -102, -102, -102,
-     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
-     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
-     -102, -102, -102, -102,  208, -102, -102, -102, -102, -102,
-     -102, -102, -102, -102, -102, -102, -102, -102
-    },
-
-    {
-       13, -103, -103, -103, -103, -103, -103, -103, -103, -103,
-
-     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
-     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
-     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
-     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
-     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
-     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
-     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
-     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
-     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
-     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
-
-     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
-     -103, -103, -103, -103, -103, -103, -103, -103
-    },
-
-    {
-       13, -104, -104, -104, -104, -104, -104, -104, -104, -104,
-     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
-     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
-     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
-     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
-     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
-     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
-     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
-
-     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
-     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
-     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
-     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
-     -104, -104, -104, -104, -104, -104, -104, -104
-    },
-
-    {
-       13, -105, -105, -105, -105, -105, -105, -105, -105, -105,
-     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
-     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
-     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
-     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
-
-     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
-     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
-     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
-     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
-     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
-     -105, -105, -105, -105, -105, -105, -105, -105, -105,  209,
-     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
-      210,  211, -105, -105, -105, -105, -105, -105
-    },
-
-    {
-       13, -106, -106, -106, -106, -106, -106, -106, -106, -106,
-     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
-
-     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
-     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
-     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
-     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
-     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
-     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
-     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
-     -106, -106, -106, -106, -106, -106, -106,  212, -106, -106,
-     -106, -106, -106, -106, -106,  213, -106, -106, -106, -106,
-     -106,  214, -106, -106, -106, -106, -106, -106, -106, -106,
-
-     -106, -106, -106, -106, -106, -106, -106, -106
-    },
-
-    {
-       13, -107, -107, -107, -107, -107, -107, -107, -107, -107,
-     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
-     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
-     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
-     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
-     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
-     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
-     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
-     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
-
-     -107, -107, -107, -107, -107, -107, -107, -107, -107,  215,
-     -107, -107, -107, -107,  216,  217, -107, -107, -107, -107,
-     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
-     -107, -107, -107, -107, -107, -107, -107, -107
-    },
-
-    {
-       13, -108, -108, -108, -108, -108, -108, -108, -108, -108,
-     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
-     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
-     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
-     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
-     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
-
-     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
-     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
-     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
-     -108, -108, -108, -108, -108, -108, -108,  218, -108, -108,
-     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
-     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
-     -108, -108, -108, -108, -108, -108, -108, -108
-    },
-
-    {
-       13, -109, -109, -109, -109, -109, -109, -109, -109, -109,
-     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
-     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
-
-     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
-     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
-     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
-     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
-     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
-     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
-     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
-     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
-     -109,  219, -109, -109,  220, -109, -109, -109, -109, -109,
-     -109, -109, -109, -109, -109, -109, -109, -109
-
-    },
-
-    {
-       13, -110, -110, -110, -110, -110, -110, -110, -110, -110,
-     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
-     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
-     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
-     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
-     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
-     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
-     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
-     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
-     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
-
-     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
-     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
-     -110, -110, -110, -110, -110, -110, -110, -110
-    },
-
-    {
-       13, -111, -111, -111, -111, -111, -111, -111, -111, -111,
-     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
-     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
-     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
-     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
-     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
-     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
-
-     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
-     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
-     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
-     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
-     -111,  221, -111, -111, -111, -111, -111, -111, -111, -111,
-     -111, -111, -111, -111, -111, -111, -111, -111
-    },
-
-    {
-       13, -112, -112, -112, -112, -112, -112, -112, -112, -112,
-     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
-     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
-     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
-
-     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
-     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
-     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
-     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
-     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
-     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
-     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
-     -112, -112, -112, -112,  222, -112, -112, -112, -112, -112,
-     -112, -112, -112, -112, -112, -112, -112, -112
-    },
-
-    {
-       13, -113, -113, -113, -113, -113, -113, -113, -113, -113,
-
-     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
-     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
-     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
-     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
-     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
-     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
-     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
-     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
-     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
-     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
-
-     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
-     -113, -113, -113, -113, -113, -113, -113, -113
-    },
-
-    {
-       13, -114, -114, -114, -114, -114, -114, -114, -114, -114,
-     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
-     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
-     -114, -114,  223, -114, -114, -114, -114, -114, -114, -114,
-      224, -114,  225,  226, -114,  226,  227,  228, -114,  229,
-      229,  229,  229,  229,  229,  229,  229,  229, -114, -114,
-     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
-     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
-
-     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
-     -114, -114, -114,  230,  231, -114, -114, -114, -114, -114,
-     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
-     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
-     -114, -114, -114, -114, -114, -114, -114, -114
-    },
-
-    {
-       13, -115, -115, -115, -115, -115, -115, -115, -115, -115,
-     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
-     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
-     -115, -115,  232, -115, -115, -115, -115, -115, -115, -115,
-     -115, -115, -115,  233, -115,  233,  234, -115,  235,  236,
-
-      236,  236,  236,  236,  236,  236,  236,  236, -115, -115,
-     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
-     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
-     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
-     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
-     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
-     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
-     -115, -115, -115, -115, -115, -115, -115, -115
-    },
-
-    {
-       13, -116, -116, -116, -116, -116, -116, -116, -116, -116,
-     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
-
-     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
-     -116, -116,  237, -116, -116, -116, -116, -116, -116, -116,
-     -116, -116,  231, -116, -116, -116, -116, -116, -116, -116,
-     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
-     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
-     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
-     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
-     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
-     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
-     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
-
-     -116, -116, -116, -116, -116, -116, -116, -116
-    },
-
-    {
-       13, -117, -117, -117, -117, -117, -117, -117, -117, -117,
-     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
-     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
-     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
-     -117, -117, -117, -117, -117, -117, -117, -117, -117,  229,
-      229,  229,  229,  229,  229,  229,  229,  229, -117, -117,
-     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
-     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
-     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
-
-     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
-     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
-     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
-     -117, -117, -117, -117, -117, -117, -117, -117
-    },
-
-    {
-       13, -118, -118, -118, -118, -118, -118, -118, -118, -118,
-     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
-     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
-     -118, -118,  237, -118, -118, -118, -118, -118, -118, -118,
-     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
-     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
-
-     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
-     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
-     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
-     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
-     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
-     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
-     -118, -118, -118, -118, -118, -118, -118, -118
-    },
-
-    {
-       13, -119, -119, -119, -119, -119, -119, -119, -119, -119,
-     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
-     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
-
-     -119, -119,  238, -119, -119, -119, -119, -119, -119, -119,
-     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
-     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
-     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
-     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
-     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
-     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
-     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
-     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
-     -119, -119, -119, -119, -119, -119, -119, -119
-
-    },
-
-    {
-       13, -120, -120, -120, -120, -120, -120, -120, -120, -120,
-     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
-     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
-     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
-     -120, -120, -120, -120, -120, -120, -120, -120,  239,  239,
-      239,  239,  239,  239,  239,  239,  239,  239, -120, -120,
-     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
-     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
-     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
-     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
-
-     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
-     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
-     -120, -120, -120, -120, -120, -120, -120, -120
-    },
-
-    {
-       13, -121, -121, -121, -121, -121, -121, -121, -121, -121,
-     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
-     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
-     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
-     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
-     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
-     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
-
-     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
-     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
-     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
-     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
-     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
-     -121, -121, -121, -121, -121, -121, -121, -121
-    },
-
-    {
-       13, -122, -122, -122, -122, -122, -122, -122, -122, -122,
-     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
-     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
-     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
-
-     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
-     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
-     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
-     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
-     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
-     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
-     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
-     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
-     -122, -122, -122, -122, -122, -122, -122, -122
-    },
-
-    {
-       13,  240,  240,  240,  240,  240,  240,  240,  240,  240,
-
-     -123,  240,  240,  240,  240,  240,  240,  240,  240,  240,
-      240,  240,  240,  240,  240,  240,  240,  240,  240,  240,
-      240,  240,  240,  240,  240,  240,  240,  240,  240,  240,
-      240,  240,  240,  240,  240,  240,  240,  240,  240,  240,
-      240,  240,  240,  240,  240,  240,  240,  240,  240,  240,
-      240,  240,  240,  240,  240,  240,  240,  240,  240,  240,
-      240,  240,  240,  240,  240,  240,  240,  240,  240,  240,
-      240,  240,  240,  240,  240,  240,  240,  240,  240,  240,
-      240,  240,  240,  240,  240,  240,  240,  240,  240,  240,
-      240,  240,  240,  240,  240,  240,  240,  240,  240,  240,
-
-      240,  240,  240,  240,  240,  240,  240,  240,  240,  240,
-      240,  240,  240,  240,  240,  240,  240,  240
-    },
-
-    {
-       13, -124, -124, -124, -124, -124, -124, -124, -124, -124,
-     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
-     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
-     -124, -124,  124, -124, -124, -124, -124, -124, -124, -124,
-     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
-     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
-     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
-     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
-
-     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
-     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
-     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
-     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
-     -124, -124, -124, -124, -124, -124, -124, -124
-    },
-
-    {
-       13, -125, -125, -125, -125, -125, -125, -125, -125, -125,
-     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
-     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
-     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
-     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
-
-     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
-     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
-     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
-     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
-     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
-     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
-     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
-     -125, -125, -125, -125, -125, -125, -125, -125
-    },
-
-    {
-       13, -126, -126, -126, -126, -126, -126, -126, -126, -126,
-     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
-
-     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
-     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
-     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
-     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
-     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
-     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
-     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
-     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
-     -126, -126, -126,  241, -126, -126, -126, -126, -126, -126,
-     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
-
-     -126, -126, -126, -126, -126, -126, -126, -126
-    },
-
-    {
-       13, -127, -127, -127, -127, -127, -127, -127, -127, -127,
-     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
-     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
-     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
-     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
-     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
-     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
-     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
-     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
-
-     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
-     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
-     -127, -127, -127, -127, -127, -127,  242, -127, -127, -127,
-     -127, -127, -127, -127, -127, -127, -127, -127
-    },
-
-    {
-       13, -128, -128, -128, -128, -128, -128, -128, -128, -128,
-     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
-     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
-     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
-     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
-     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
-
-     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
-     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
-     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
-     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
-     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
-     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
-     -128, -128, -128, -128, -128, -128, -128, -128
-    },
-
-    {
-       13, -129, -129, -129, -129, -129, -129, -129, -129, -129,
-     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
-     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
-
-     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
-     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
-     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
-     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
-     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
-     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
-     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
-     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
-     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
-     -129,  243, -129, -129, -129, -129, -129, -129
-
-    },
-
-    {
-       13, -130, -130, -130, -130, -130, -130, -130, -130, -130,
-     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
-     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
-     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
-     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
-     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
-     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
-     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
-     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
-     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
-
-     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
-     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
-     -130, -130, -130, -130, -130, -130, -130, -130
-    },
-
-    {
-       13, -131, -131, -131, -131, -131, -131, -131, -131, -131,
-     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
-     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
-     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
-     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
-     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
-     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
-
-     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
-     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
-     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
-     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
-     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
-     -131, -131, -131, -131, -131, -131, -131, -131
-    },
-
-    {
-       13, -132, -132, -132, -132, -132, -132, -132, -132, -132,
-     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
-     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
-     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
-
-     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
-     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
-     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
-     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
-     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
-     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
-     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
-     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
-     -132, -132,  130, -132, -132, -132, -132, -132
-    },
-
-    {
-       13, -133, -133, -133, -133, -133, -133, -133, -133, -133,
-
-     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
-     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
-     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
-     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
-     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
-     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
-     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
-     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
-     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
-     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
-
-     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
-     -133,  131, -133, -133, -133, -133, -133, -133
-    },
-
-    {
-       13, -134, -134, -134, -134, -134, -134, -134, -134, -134,
-     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
-     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
-     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
-     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
-     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
-     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
-     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
-
-     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
-     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
-     -134, -134, -134, -134,  244, -134, -134, -134, -134, -134,
-     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
-     -134, -134, -134, -134, -134, -134, -134, -134
-    },
-
-    {
-       13, -135, -135, -135, -135, -135, -135, -135, -135, -135,
-     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
-     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
-     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
-     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
-
-     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
-     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
-     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
-     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
-     -135, -135, -135, -135, -135, -135, -135,  130, -135, -135,
-     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
-     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
-     -135, -135, -135, -135, -135, -135, -135, -135
-    },
-
-    {
-       13, -136, -136, -136, -136, -136, -136, -136, -136, -136,
-     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
-
-     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
-     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
-     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
-     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
-     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
-     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
-     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
-     -136, -136, -136, -136, -136, -136, -136, -136,  130, -136,
-     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
-     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
-
-     -136, -136, -136, -136, -136, -136, -136, -136
-    },
-
-    {
-       13, -137, -137, -137, -137, -137, -137, -137, -137, -137,
-     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
-     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
-     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
-     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
-     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
-     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
-     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
-     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
-
-     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
-     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
-     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
-     -137, -137, -137, -137, -137, -137, -137, -137
-    },
-
-    {
-       13, -138, -138, -138, -138, -138, -138, -138, -138, -138,
-     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
-     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
-     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
-     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
-     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
-
-     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
-     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
-     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
-     -138, -138, -138, -138, -138, -138, -138,  245, -138, -138,
-     -138, -138, -138, -138, -138,  246, -138, -138, -138, -138,
-     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
-     -138,  243, -138, -138, -138, -138, -138, -138
-    },
-
-    {
-       13, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-
-     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-      128, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-     -139, -139, -139, -139, -139, -139, -139, -139
-
-    },
-
-    {
-       13, -140, -140, -140, -140, -140, -140, -140, -140, -140,
-     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
-     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
-     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
-     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
-     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
-     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
-     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
-     -140, -140, -140, -140, -140, -140,  131, -140, -140, -140,
-     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
-
-     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
-     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
-     -140, -140, -140, -140, -140, -140, -140, -140
-    },
-
-    {
-       13, -141, -141, -141, -141, -141, -141, -141, -141, -141,
-     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
-     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
-     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
-     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
-     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
-     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
-
-     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
-     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
-     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
-     -141, -141, -141, -141, -141, -141, -141, -141, -141,  130,
-     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
-      130, -141, -141, -141, -141, -141, -141, -141
-    },
-
-    {
-       13, -142, -142, -142, -142, -142, -142, -142, -142, -142,
-     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
-     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
-     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
-
-     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
-     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
-     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
-     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
-     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
-     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
-     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
-     -142,  247, -142, -142, -142, -142, -142, -142, -142, -142,
-     -142, -142, -142, -142, -142, -142, -142, -142
-    },
-
-    {
-       13, -143, -143, -143, -143, -143, -143, -143, -143, -143,
-
-     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
-     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
-     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
-     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
-     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
-     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
-     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
-     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
-     -143, -143, -143, -143, -143, -143, -143, -143, -143,  137,
-     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
-
-     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
-     -143, -143, -143, -143, -143, -143, -143, -143
-    },
-
-    {
-       13, -144, -144, -144, -144, -144, -144, -144, -144, -144,
-     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
-     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
-     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
-     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
-     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
-     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
-     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
-
-     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
-     -144, -144, -144, -144, -144, -144, -144,  248, -144, -144,
-     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
-     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
-     -144, -144, -144, -144, -144, -144, -144, -144
-    },
-
-    {
-       13, -145, -145, -145, -145, -145, -145, -145, -145, -145,
-     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
-     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
-     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
-     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
-
-     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
-     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
-     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
-     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
-     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
-     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
-     -145, -145, -145, -145,  128, -145, -145, -145, -145, -145,
-     -145, -145, -145, -145, -145, -145, -145, -145
-    },
-
-    {
-       13, -146, -146, -146, -146, -146, -146, -146, -146, -146,
-     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
-
-     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
-     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
-     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
-     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
-     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
-     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
-     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
-     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
-     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
-     -146, -146, -146, -146,  137, -146, -146, -146, -146, -146,
-
-     -146, -146, -146, -146, -146, -146, -146, -146
-    },
-
-    {
-       13, -147, -147, -147, -147, -147, -147, -147, -147, -147,
-     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
-     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
-     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
-     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
-     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
-     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
-     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
-     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
-
-     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
-     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
-     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
-     -147, -147, -147, -147, -147, -147, -147, -147
-    },
-
-    {
-       13, -148, -148, -148, -148, -148, -148, -148, -148, -148,
-     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
-     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
-     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
-     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
-     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
-
-     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
-     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
-     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
-     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
-     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
-     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
-     -148, -148, -148, -148, -148, -148, -148, -148
-    },
-
-    {
-       13, -149, -149, -149, -149, -149, -149, -149, -149, -149,
-     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
-     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
-
-     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
-     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
-     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
-     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
-     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
-     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
-     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
-     -149, -149, -149, -149, -149, -149, -149, -149, -149,  147,
-     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
-     -149, -149, -149, -149, -149, -149, -149, -149
-
-    },
-
-    {
-       13, -150, -150, -150, -150, -150, -150, -150, -150, -150,
-     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
-     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
-     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
-     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
-     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
-     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
-     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
-     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
-     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
-
-     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
-     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
-     -150, -150, -150, -150, -150, -150, -150, -150
-    },
-
-    {
-       13, -151, -151, -151, -151, -151, -151, -151, -151, -151,
-     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
-     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
-     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
-     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
-     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
-     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
-
-     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
-     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
-     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
-     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
-     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
-     -151, -151, -151, -151, -151, -151, -151, -151
-    },
-
-    {
-       13, -152, -152, -152, -152, -152, -152, -152, -152, -152,
-     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
-     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
-     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
-
-     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
-     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
-     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
-     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
-     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
-     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
-     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
-      125, -152, -152, -152, -152, -152, -152, -152, -152, -152,
-     -152, -152, -152, -152, -152, -152, -152, -152
-    },
-
-    {
-       13, -153, -153, -153, -153, -153, -153, -153, -153, -153,
-
-     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
-     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
-     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
-     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
-     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
-     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
-     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
-     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
-     -153, -153, -153, -153, -153, -153, -153,  245, -153, -153,
-     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
-
-     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
-     -153, -153, -153, -153, -153, -153, -153, -153
-    },
-
-    {
-       13, -154, -154, -154, -154, -154, -154, -154, -154, -154,
-     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
-     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
-     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
-     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
-     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
-     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
-     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
-
-     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
-     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
-     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
-     -154, -154, -154, -154, -154, -154, -154,  163, -154, -154,
-     -154, -154, -154, -154, -154, -154, -154, -154
-    },
-
-    {
-       13, -155, -155, -155, -155, -155, -155, -155, -155, -155,
-     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
-     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
-     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
-     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
-
-     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
-     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
-     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
-     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
-     -155, -155, -155, -155, -155, -155, -155,  249, -155, -155,
-     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
-     -155,  247, -155, -155, -155, -155, -155, -155, -155, -155,
-     -155, -155, -155, -155, -155, -155, -155, -155
-    },
-
-    {
-       13, -156, -156, -156, -156, -156, -156, -156, -156, -156,
-     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
-
-     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
-     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
-     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
-     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
-     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
-     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
-     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
-     -156, -156, -156, -156, -156, -156, -156,  248, -156,  250,
-     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
-     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
-
-     -156, -156, -156, -156, -156, -156, -156, -156
-    },
-
-    {
-       13, -157, -157, -157, -157, -157, -157, -157, -157, -157,
-     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
-     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
-     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
-     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
-     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
-     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
-     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
-     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
-
-     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
-     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
-     -157, -157, -157, -157,  251, -157, -157, -157, -157, -157,
-     -157, -157, -157, -157, -157, -157, -157, -157
-    },
-
-    {
-       13, -158, -158, -158, -158, -158, -158, -158, -158, -158,
-     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
-     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
-     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
-     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
-     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
-
-     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
-     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
-     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
-     -158, -158, -158, -158, -158, -158, -158,  252, -158, -158,
-     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
-     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
-     -158, -158, -158, -158, -158, -158, -158, -158
-    },
-
-    {
-       13, -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, -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,
-      163, -159, -159, -159, -159, -159,  253, -159, -159, -159,
-     -159, -159, -159, -159, -159, -159, -159, -159
-
-    },
-
-    {
-       13, -160, -160, -160, -160, -160, -160, -160, -160, -160,
-     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
-     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
-     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
-     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
-     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
-     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
-     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
-     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
-     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
-
-     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
-     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
-     -160, -160, -160, -160, -160, -160, -160, -160
-    },
-
-    {
-       13, -161, -161, -161, -161, -161, -161, -161, -161, -161,
-     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
-     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
-     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
-     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
-     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
-     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
-
-     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
-     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
-     -161, -161, -161, -161, -161, -161, -161,  254, -161, -161,
-     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
-     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
-     -161, -161, -161, -161, -161, -161, -161, -161
-    },
-
-    {
-       13, -162, -162, -162, -162, -162, -162, -162, -162, -162,
-     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
-     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
-     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
-
-     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
-     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
-     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
-     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
-     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
-     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
-     -162, -162, -162, -162,  244, -162, -162, -162, -162, -162,
-     -162, -162, -162, -162, -162, -162, -162,  255, -162, -162,
-     -162, -162, -162, -162, -162, -162, -162, -162
-    },
-
-    {
-       13, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-
-     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-
-     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-     -163, -163, -163, -163, -163, -163, -163, -163
-    },
-
-    {
-       13, -164, -164, -164, -164, -164, -164, -164, -164, -164,
-     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
-     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
-     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
-     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
-     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
-     -164, -164, -164, -164, -164,  128,  129,  130, -164, -164,
-      130,  131,  132, -164,  133,  128, -164, -164,  130,  134,
-
-      135, -164,  131,  130,  130, -164,  130,  136, -164, -164,
-     -164, -164, -164, -164, -164, -164, -164,  137,  138,  139,
-     -164,  140, -164,  128, -164, -164, -164, -164,  141,  142,
-     -164,  134,  143, -164,  144,  145, -164, -164, -164, -164,
-     -164,  146, -164, -164, -164, -164, -164, -164
-    },
-
-    {
-       13, -165, -165, -165, -165, -165, -165, -165, -165, -165,
-     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
-     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
-     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
-     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
-
-     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
-     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
-     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
-     -165, -165, -165, -165, -165, -165,  131, -165, -165, -165,
-     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
-     -165, -165, -165,  151, -165, -165, -165, -165, -165, -165,
-     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
-     -165, -165, -165, -165, -165, -165, -165, -165
-    },
-
-    {
-       13, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-
-     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-     -166, -166, -166,  151, -166, -166, -166, -166, -166, -166,
-     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-
-     -166, -166, -166, -166, -166, -166, -166, -166
-    },
-
-    {
-       13, -167, -167, -167, -167, -167, -167, -167, -167, -167,
-     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
-     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
-     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
-     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
-     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
-     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
-     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
-     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
-
-     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
-     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
-     -167, -167, -167, -167,  125, -167, -167, -167, -167, -167,
-     -167, -167, -167, -167, -167, -167, -167, -167
-    },
-
-    {
-       13, -168, -168, -168, -168, -168, -168, -168, -168, -168,
-     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
-     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
-     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
-     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
-     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
-
-     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
-     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
-     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
-     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
-     -168, -168, -168,  148, -168, -168, -168, -168, -168, -168,
-     -168, -168, -168, -168, -168,  151, -168, -168, -168, -168,
-     -168, -168, -168, -168, -168, -168, -168, -168
-    },
-
-    {
-       13, -169, -169, -169, -169, -169, -169, -169, -169, -169,
-     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
-     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
-
-     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
-     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
-     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
-     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
-     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
-     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
-     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
-     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
-      151, -169, -169, -169, -169, -169, -169, -169, -169, -169,
-     -169, -169, -169, -169, -169, -169, -169, -169
-
-    },
-
-    {
-       13, -170, -170, -170, -170, -170, -170, -170, -170, -170,
-     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
-     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
-     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
-     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
-     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
-     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
-     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
-     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
-     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
-
-     -170, -170, -170, -170,  244, -170, -170, -170,  160, -170,
-     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
-     -170, -170, -170, -170, -170, -170, -170, -170
-    },
-
-    {
-       13, -171, -171, -171, -171, -171, -171, -171, -171, -171,
-     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
-     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
-     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
-     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
-     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
-     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
-
-     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
-     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
-     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
-      128, -171, -171, -171, -171, -171, -171, -171, -171, -171,
-     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
-     -171, -171, -171, -171, -171, -171, -171, -171
-    },
-
-    {
-       13, -172, -172, -172, -172, -172, -172, -172, -172, -172,
-     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
-     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
-     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
-
-     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
-     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
-     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
-     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
-     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
-     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
-     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
-     -172,  256, -172, -172, -172, -172, -172, -172, -172, -172,
-     -172, -172, -172, -172, -172, -172, -172, -172
-    },
-
-    {
-       13, -173, -173, -173, -173, -173, -173, -173, -173, -173,
-
-     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
-     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
-     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
-     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
-     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
-     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
-     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
-     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
-     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
-     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
-
-     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
-      257, -173, -173, -173, -173, -173, -173, -173
-    },
-
-    {
-       13, -174, -174, -174, -174, -174, -174, -174, -174, -174,
-     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
-     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
-     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
-     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
-     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
-     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
-     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
-
-     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
-     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
-      160, -174, -174, -174, -174, -174, -174, -174, -174, -174,
-     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
-     -174, -174, -174, -174, -174, -174, -174, -174
-    },
-
-    {
-       13, -175, -175, -175, -175, -175, -175, -175, -175, -175,
-     -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
-     -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
-     -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
-     -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
-
-     -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
-     -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
-     -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
-     -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
-     -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
-     -175, -175, -175, -175, -175, -175, -175, -175,  258, -175,
-     -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
-     -175, -175, -175, -175, -175, -175, -175, -175
-    },
-
-    {
-       13, -176, -176, -176, -176, -176, -176, -176, -176, -176,
-     -176, -176, -176, -176, -176, -176, -176, -176, -176, -176,
-
-     -176, -176, -176, -176, -176, -176, -176, -176, -176, -176,
-     -176, -176, -176, -176, -176, -176, -176, -176, -176, -176,
-     -176, -176, -176, -176, -176, -176, -176, -176, -176, -176,
-     -176, -176, -176, -176, -176, -176, -176, -176, -176, -176,
-     -176, -176, -176, -176, -176, -176, -176, -176, -176, -176,
-     -176, -176, -176, -176, -176, -176, -176, -176, -176, -176,
-     -176, -176, -176, -176, -176, -176, -176, -176, -176, -176,
-     -176, -176, -176, -176, -176, -176, -176, -176, -176, -176,
-     -176, -176, -176, -176, -176, -176, -176, -176, -176, -176,
-     -176, -176, -176, -176,  259, -176, -176, -176, -176, -176,
-
-     -176, -176, -176, -176, -176, -176, -176, -176
-    },
-
-    {
-       13, -177, -177, -177, -177, -177, -177, -177, -177, -177,
-     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
-     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
-     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
-     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
-     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
-     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
-     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
-     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
-
-     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
-     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
-     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
-      260, -177, -177, -177, -177, -177, -177, -177
-    },
-
-    {
-       13, -178, -178, -178, -178, -178, -178, -178, -178, -178,
-     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
-     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
-     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
-     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
-     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
-
-     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
-     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
-     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
-     -178, -178, -178, -178, -178, -178, -178,  248, -178, -178,
-     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
-     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
-     -178, -178, -178, -178, -178, -178, -178, -178
-    },
-
-    {
-       13, -179, -179, -179, -179, -179, -179, -179, -179, -179,
-     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
-     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
-
-     -179, -179,  179, -179, -179, -179, -179, -179, -179, -179,
-     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
-     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
-     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
-     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
-     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
-     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
-     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
-     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
-     -179, -179, -179, -179, -179, -179, -179, -179
-
-    },
-
-    {
-       13, -180, -180, -180, -180, -180, -180, -180, -180, -180,
-     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
-     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
-     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
-     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
-     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
-     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
-     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
-     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
-     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
-
-     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
-     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
-     -180, -180, -180, -180, -180, -180, -180, -180
-    },
-
-    {
-       13, -181, -181, -181, -181, -181, -181, -181, -181, -181,
-     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
-     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
-     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
-     -181, -181, -181, -181, -181, -181, -181, -181,  261,  261,
-      261,  261,  261,  261,  261,  261,  261,  261, -181, -181,
-     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
-
-     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
-     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
-     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
-     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
-     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
-     -181, -181, -181, -181, -181, -181, -181, -181
-    },
-
-    {
-       13, -182, -182, -182, -182, -182, -182, -182, -182, -182,
-     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
-     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
-     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
-
-     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
-     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
-     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
-     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
-     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
-     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
-     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
-     -182, -182,  262, -182, -182, -182, -182, -182, -182, -182,
-     -182, -182, -182, -182, -182, -182, -182, -182
-    },
-
-    {
-       13, -183, -183, -183, -183, -183, -183, -183, -183, -183,
-
-     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
-     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
-     -183, -183,  263, -183, -183, -183, -183, -183, -183, -183,
-      264, -183, -183, -183, -183, -183, -183, -183, -183, -183,
-     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
-     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
-     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
-     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
-     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
-     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
-
-     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
-     -183, -183, -183, -183, -183, -183, -183, -183
-    },
-
-    {
-       13, -184, -184, -184, -184, -184, -184, -184, -184, -184,
-     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
-     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
-     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
-     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
-     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
-     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
-     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
-
-     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
-     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
-     -184, -184, -184,  265, -184, -184, -184, -184, -184, -184,
-     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
-     -184, -184, -184, -184, -184, -184, -184, -184
-    },
-
-    {
-       13,  185,  185,  185,  185,  185,  185,  185,  185,  185,
-      185,  185,  185,  185,  185,  185,  185,  185,  185,  185,
-      185,  185,  185,  185,  185,  185,  185,  185,  185,  185,
-      185,  185,  185,  185,  185,  185,  185,  185,  185,  185,
-     -185, -185,  185,  185,  185,  185,  185,  185,  185,  185,
-
-      185,  185,  185,  185,  185,  185,  185,  185,  185,  185,
-      185,  185,  185,  185,  185,  185,  185,  185,  185,  185,
-      185,  185,  185,  185,  185,  185,  185,  185,  185,  185,
-      185,  185,  185,  185,  185,  185,  185,  185,  185,  185,
-      185,  185,  185,  185,  185,  185,  185,  185,  185,  185,
-      185,  185,  185,  185,  185,  185,  185,  185,  185,  185,
-      185,  185,  185,  185,  185,  185,  185,  185,  185,  185,
-      185,  185,  185,  185,  185,  185,  185,  185
-    },
-
-    {
-       13, -186, -186, -186, -186, -186, -186, -186, -186, -186,
-     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
-
-     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
-     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
-     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
-     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
-     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
-     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
-     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
-     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
-     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
-     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
-
-     -186, -186, -186, -186, -186, -186, -186, -186
-    },
-
-    {
-       13, -187, -187, -187, -187, -187, -187, -187, -187, -187,
-     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
-     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
-     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
-     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
-     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
-     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
-     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
-     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
-
-     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
-     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
-     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
-     -187, -187, -187, -187, -187, -187, -187, -187
-    },
-
-    {
-       13, -188, -188, -188, -188, -188, -188, -188, -188, -188,
-     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
-     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
-     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
-     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
-     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
-
-     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
-     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
-     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
-     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
-     -188, -188, -188,  266, -188, -188, -188, -188, -188, -188,
-     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
-     -188, -188, -188, -188, -188, -188, -188, -188
-    },
-
-    {
-       13, -189, -189, -189, -189, -189, -189, -189, -189, -189,
-     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
-     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
-
-     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
-     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
-     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
-     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
-     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
-     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
-     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
-     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
-     -189, -189, -189, -189, -189, -189,  267, -189, -189, -189,
-     -189, -189, -189, -189, -189, -189, -189, -189
-
-    },
-
-    {
-       13, -190, -190, -190, -190, -190, -190, -190, -190, -190,
-     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
-     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
-     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
-     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
-     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
-     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
-     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
-     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
-     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
-
-     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
-     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
-     -190, -190, -190, -190, -190, -190, -190, -190
-    },
-
-    {
-       13, -191, -191, -191, -191, -191, -191, -191, -191, -191,
-     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
-     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
-     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
-     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
-     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
-     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
-
-     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
-     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
-     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
-     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
-     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
-     -191, -191, -191, -191, -191, -191, -191, -191
-    },
-
-    {
-       13, -192, -192, -192, -192, -192, -192, -192, -192, -192,
-     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
-     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
-     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
-
-     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
-     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
-     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
-     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
-     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
-     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
-     -192, -192, -192, -192, -192, -192, -192, -192, -192,  268,
-     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
-     -192, -192, -192, -192, -192, -192, -192, -192
-    },
-
-    {
-       13, -193, -193, -193, -193, -193, -193, -193, -193, -193,
-
-     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
-     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
-     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
-     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
-     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
-     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
-     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
-     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
-     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
-     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
-
-     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
-     -193, -193, -193, -193, -193, -193, -193, -193
-    },
-
-    {
-       13, -194, -194, -194, -194, -194, -194, -194, -194, -194,
-     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
-     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
-     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
-     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
-     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
-     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
-     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
-
-     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
-     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
-     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
-     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
-     -194, -194, -194, -194, -194, -194, -194, -194
-    },
-
-    {
-       13, -195, -195, -195, -195, -195, -195, -195, -195, -195,
-     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
-     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
-     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
-     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
-
-     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
-     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
-     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
-     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
-     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
-     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
-      269, -195, -195, -195, -195, -195, -195, -195, -195, -195,
-     -195, -195, -195, -195, -195, -195, -195, -195
-    },
-
-    {
-       13, -196, -196, -196, -196, -196, -196, -196, -196, -196,
-     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
-
-     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
-     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
-     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
-     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
-     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
-     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
-     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
-     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
-     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
-     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
-
-     -196, -196, -196, -196, -196, -196, -196, -196
-    },
-
-    {
-       13, -197, -197, -197, -197, -197, -197, -197, -197, -197,
-     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
-     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
-     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
-     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
-     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
-     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
-     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
-     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
-
-     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
-     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
-     -197, -197, -197, -197, -197, -197, -197,  270, -197, -197,
-     -197, -197, -197, -197, -197, -197, -197, -197
-    },
-
-    {
-       13, -198, -198, -198, -198, -198, -198, -198, -198, -198,
-     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
-     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
-     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
-     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
-     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
-
-     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
-     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
-     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
-     -198, -198, -198, -198, -198, -198, -198, -198, -198,  271,
-     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
-     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
-     -198, -198, -198, -198, -198, -198, -198, -198
-    },
-
-    {
-       13, -199, -199, -199, -199, -199, -199, -199, -199, -199,
-     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
-     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
-
-     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
-     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
-     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
-     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
-     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
-     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
-     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
-     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
-     -199, -199, -199, -199,  272, -199, -199, -199, -199, -199,
-     -199, -199, -199, -199, -199, -199, -199, -199
-
-    },
-
-    {
-       13, -200, -200, -200, -200, -200, -200, -200, -200, -200,
-     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
-     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
-     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
-     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
-     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
-     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
-     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
-     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
-     -200, -200, -200, -200, -200, -200, -200,  273, -200, -200,
-
-     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
-     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
-     -200, -200, -200, -200, -200, -200, -200, -200
-    },
-
-    {
-       13, -201, -201, -201, -201, -201, -201, -201, -201, -201,
-     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
-     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
-     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
-     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
-     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
-     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
-
-     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
-     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
-     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
-     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
-      274, -201, -201, -201, -201, -201,  275, -201, -201, -201,
-     -201, -201, -201, -201, -201, -201, -201, -201
-    },
-
-    {
-       13, -202, -202, -202, -202, -202, -202, -202, -202, -202,
-     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
-     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
-     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
-
-     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
-     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
-     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
-     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
-     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
-     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
-     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
-     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
-     -202, -202, -202, -202, -202, -202, -202, -202
-    },
-
-    {
-       13, -203, -203, -203, -203, -203, -203, -203, -203, -203,
-
-     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
-     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
-     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
-     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
-     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
-     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
-     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
-     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
-     -203, -203, -203, -203, -203, -203, -203,  276, -203, -203,
-     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
-
-     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
-     -203, -203, -203, -203, -203, -203, -203, -203
-    },
-
-    {
-       13, -204, -204, -204, -204, -204, -204, -204, -204, -204,
-     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
-     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
-     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
-     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
-     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
-     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
-     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
-
-     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
-     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
-     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
-     -204, -204, -204, -204, -204, -204, -204,  277, -204, -204,
-     -204, -204, -204, -204, -204, -204, -204, -204
-    },
-
-    {
-       13, -205, -205, -205, -205, -205, -205, -205, -205, -205,
-     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
-     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
-     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
-     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
-
-     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
-     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
-     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
-     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
-     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
-     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
-     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
-     -205, -205, -205, -205, -205, -205, -205, -205
-    },
-
-    {
-       13, -206, -206, -206, -206, -206, -206, -206, -206, -206,
-     -206, -206, -206, -206, -206, -206, -206, -206, -206, -206,
-
-     -206, -206, -206, -206, -206, -206, -206, -206, -206, -206,
-     -206, -206, -206, -206, -206, -206, -206, -206, -206, -206,
-     -206, -206, -206, -206, -206, -206, -206, -206, -206, -206,
-     -206, -206, -206, -206, -206, -206, -206, -206, -206, -206,
-     -206, -206, -206, -206, -206, -206, -206, -206, -206, -206,
-     -206, -206, -206, -206, -206, -206, -206, -206, -206, -206,
-     -206, -206, -206, -206, -206, -206, -206, -206, -206, -206,
-     -206, -206, -206, -206, -206, -206, -206, -206, -206, -206,
-     -206, -206, -206,  278, -206, -206, -206, -206, -206, -206,
-     -206, -206, -206, -206, -206, -206, -206, -206, -206, -206,
-
-     -206, -206, -206, -206, -206, -206, -206, -206
-    },
-
-    {
-       13, -207, -207, -207, -207, -207, -207, -207, -207, -207,
-     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
-     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
-     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
-     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
-     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
-     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
-     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
-     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
-
-     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
-     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
-     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
-     -207, -207, -207, -207, -207, -207, -207, -207
-    },
-
-    {
-       13, -208, -208, -208, -208, -208, -208, -208, -208, -208,
-     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
-     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
-     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
-     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
-     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
-
-     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
-     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
-     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
-     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
-     -208, -208, -208,  279, -208, -208, -208, -208, -208, -208,
-     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
-     -208, -208, -208, -208, -208, -208, -208, -208
-    },
-
-    {
-       13, -209, -209, -209, -209, -209, -209, -209, -209, -209,
-     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
-     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
-
-     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
-     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
-     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
-     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
-     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
-     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
-     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
-     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
-     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
-     -209, -209, -209, -209, -209, -209, -209, -209
-
-    },
-
-    {
-       13, -210, -210, -210, -210, -210, -210, -210, -210, -210,
-     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
-     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
-     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
-     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
-     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
-     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
-     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
-     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
-     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
-
-     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
-     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
-     -210, -210, -210, -210, -210, -210, -210, -210
-    },
-
-    {
-       13, -211, -211, -211, -211, -211, -211, -211, -211, -211,
-     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
-     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
-     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
-     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
-     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
-     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
-
-     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
-     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
-     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
-     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
-     -211, -211, -211, -211,  280, -211, -211, -211, -211, -211,
-     -211, -211, -211, -211, -211, -211, -211, -211
-    },
-
-    {
-       13, -212, -212, -212, -212, -212, -212, -212, -212, -212,
-     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
-     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
-     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
-
-     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
-     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
-     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
-     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
-     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
-     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
-     -212, -212, -212,  281, -212, -212, -212, -212, -212, -212,
-     -212, -212, -212, -212, -212,  282, -212, -212, -212, -212,
-     -212, -212, -212, -212, -212, -212, -212, -212
-    },
-
-    {
-       13, -213, -213, -213, -213, -213, -213, -213, -213, -213,
-
-     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
-     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
-     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
-     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
-     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
-     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
-     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
-     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
-     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
-     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
-
-      283, -213, -213, -213, -213, -213, -213, -213, -213, -213,
-     -213, -213, -213, -213, -213, -213, -213, -213
-    },
-
-    {
-       13, -214, -214, -214, -214, -214, -214, -214, -214, -214,
-     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
-     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
-     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
-     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
-     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
-     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
-     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
-
-     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
-     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
-     -214, -214, -214, -214, -214, -214, -214, -214,  284, -214,
-     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
-     -214, -214, -214, -214, -214, -214, -214, -214
-    },
-
-    {
-       13, -215, -215, -215, -215, -215, -215, -215, -215, -215,
-     -215, -215, -215, -215, -215, -215, -215, -215, -215, -215,
-     -215, -215, -215, -215, -215, -215, -215, -215, -215, -215,
-     -215, -215, -215, -215, -215, -215, -215, -215, -215, -215,
-     -215, -215, -215, -215, -215, -215, -215, -215, -215, -215,
-
-     -215, -215, -215, -215, -215, -215, -215, -215, -215, -215,
-     -215, -215, -215, -215, -215, -215, -215, -215, -215, -215,
-     -215, -215, -215, -215, -215, -215, -215, -215, -215, -215,
-     -215, -215, -215, -215, -215, -215, -215, -215, -215, -215,
-     -215, -215, -215, -215, -215, -215, -215, -215, -215, -215,
-     -215, -215, -215, -215, -215, -215, -215, -215, -215, -215,
-     -215, -215, -215, -215, -215, -215, -215, -215, -215, -215,
-     -215, -215, -215, -215, -215, -215, -215, -215
-    },
-
-    {
-       13, -216, -216, -216, -216, -216, -216, -216, -216, -216,
-     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
-
-     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
-     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
-     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
-     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
-     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
-     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
-     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
-     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
-     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
-     -216,  285, -216, -216, -216, -216, -216, -216, -216, -216,
-
-     -216, -216, -216, -216, -216, -216, -216, -216
-    },
-
-    {
-       13, -217, -217, -217, -217, -217, -217, -217, -217, -217,
-     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
-     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
-     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
-     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
-     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
-     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
-     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
-     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
-
-     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
-     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
-     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
-      286, -217, -217, -217, -217, -217, -217, -217
-    },
-
-    {
-       13, -218, -218, -218, -218, -218, -218, -218, -218, -218,
-     -218, -218, -218, -218, -218, -218, -218, -218, -218, -218,
-     -218, -218, -218, -218, -218, -218, -218, -218, -218, -218,
-     -218, -218, -218, -218, -218, -218, -218, -218, -218, -218,
-     -218, -218, -218, -218, -218, -218, -218, -218, -218, -218,
-     -218, -218, -218, -218, -218, -218, -218, -218, -218, -218,
-
-     -218, -218, -218, -218, -218, -218, -218, -218, -218, -218,
-     -218, -218, -218, -218, -218, -218, -218, -218, -218, -218,
-     -218, -218, -218, -218, -218, -218, -218, -218, -218, -218,
-     -218, -218, -218, -218, -218, -218, -218, -218, -218, -218,
-      287, -218, -218, -218, -218, -218, -218, -218, -218, -218,
-     -218, -218, -218, -218, -218, -218, -218, -218, -218, -218,
-     -218, -218, -218, -218, -218, -218, -218, -218
-    },
-
-    {
-       13, -219, -219, -219, -219, -219, -219, -219, -219, -219,
-     -219, -219, -219, -219, -219, -219, -219, -219, -219, -219,
-     -219, -219, -219, -219, -219, -219, -219, -219, -219, -219,
-
-     -219, -219, -219, -219, -219, -219, -219, -219, -219, -219,
-     -219, -219, -219, -219, -219, -219, -219, -219, -219, -219,
-     -219, -219, -219, -219, -219, -219, -219, -219, -219, -219,
-     -219, -219, -219, -219, -219, -219, -219, -219, -219, -219,
-     -219, -219, -219, -219, -219, -219, -219, -219, -219, -219,
-     -219, -219, -219, -219, -219, -219, -219, -219, -219, -219,
-     -219, -219, -219, -219, -219, -219, -219, -219, -219, -219,
-     -219, -219, -219, -219, -219, -219, -219, -219,  288, -219,
-     -219, -219, -219, -219, -219, -219, -219, -219, -219, -219,
-     -219, -219, -219, -219, -219, -219, -219, -219
-
-    },
-
-    {
-       13, -220, -220, -220, -220, -220, -220, -220, -220, -220,
-     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
-     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
-     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
-     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
-     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
-     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
-     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
-     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
-     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
-
-     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
-     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
-     -220, -220, -220, -220, -220, -220, -220, -220
-    },
-
-    {
-       13, -221, -221, -221, -221, -221, -221, -221, -221, -221,
-     -221, -221, -221, -221, -221, -221, -221, -221, -221, -221,
-     -221, -221, -221, -221, -221, -221, -221, -221, -221, -221,
-     -221, -221, -221, -221, -221, -221, -221, -221, -221, -221,
-     -221, -221, -221, -221, -221, -221, -221, -221, -221, -221,
-     -221, -221, -221, -221, -221, -221, -221, -221, -221, -221,
-     -221, -221, -221, -221, -221, -221, -221, -221, -221, -221,
-
-     -221, -221, -221, -221, -221, -221, -221, -221, -221, -221,
-     -221, -221, -221, -221, -221, -221, -221, -221, -221, -221,
-     -221, -221, -221, -221, -221, -221, -221, -221, -221, -221,
-     -221, -221, -221, -221, -221, -221, -221, -221, -221, -221,
-     -221, -221, -221, -221, -221, -221, -221, -221, -221, -221,
-      289, -221, -221, -221, -221, -221, -221, -221
-    },
-
-    {
-       13, -222, -222, -222, -222, -222, -222, -222, -222, -222,
-     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
-     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
-     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
-
-     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
-     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
-     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
-     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
-     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
-     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
-     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
-     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
-     -222, -222, -222, -222, -222, -222, -222, -222
-    },
-
-    {
-       13, -223, -223, -223, -223, -223, -223, -223, -223, -223,
-
-     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
-     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
-     -223, -223,  223, -223, -223, -223, -223, -223, -223, -223,
-      224, -223,  225,  226, -223,  226,  227,  228, -223,  229,
-      229,  229,  229,  229,  229,  229,  229,  229, -223, -223,
-     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
-     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
-     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
-     -223, -223, -223,  230,  231, -223, -223, -223, -223, -223,
-     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
-
-     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
-     -223, -223, -223, -223, -223, -223, -223, -223
-    },
-
-    {
-       13, -224, -224, -224, -224, -224, -224, -224, -224, -224,
-     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
-     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
-     -224, -224,  232, -224, -224, -224, -224, -224, -224, -224,
-     -224, -224, -224,  233, -224,  233,  234, -224,  235,  236,
-      236,  236,  236,  236,  236,  236,  236,  236, -224, -224,
-     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
-     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
-
-     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
-     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
-     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
-     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
-     -224, -224, -224, -224, -224, -224, -224, -224
-    },
-
-    {
-       13, -225, -225, -225, -225, -225, -225, -225, -225, -225,
-     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
-     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
-     -225, -225,  237, -225, -225, -225, -225, -225, -225, -225,
-     -225, -225,  231, -225, -225, -225, -225, -225, -225, -225,
-
-     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
-     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
-     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
-     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
-     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
-     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
-     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
-     -225, -225, -225, -225, -225, -225, -225, -225
-    },
-
-    {
-       13, -226, -226, -226, -226, -226, -226, -226, -226, -226,
-     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
-
-     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
-     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
-     -226, -226, -226, -226, -226, -226, -226, -226, -226,  229,
-      229,  229,  229,  229,  229,  229,  229,  229, -226, -226,
-     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
-     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
-     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
-     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
-     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
-     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
-
-     -226, -226, -226, -226, -226, -226, -226, -226
-    },
-
-    {
-       13, -227, -227, -227, -227, -227, -227, -227, -227, -227,
-     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
-     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
-     -227, -227,  237, -227, -227, -227, -227, -227, -227, -227,
-     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
-     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
-     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
-     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
-     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
-
-     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
-     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
-     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
-     -227, -227, -227, -227, -227, -227, -227, -227
-    },
-
-    {
-       13, -228, -228, -228, -228, -228, -228, -228, -228, -228,
-     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
-     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
-     -228, -228,  238, -228, -228, -228, -228, -228, -228, -228,
-     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
-     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
-
-     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
-     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
-     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
-     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
-     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
-     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
-     -228, -228, -228, -228, -228, -228, -228, -228
-    },
-
-    {
-       13, -229, -229, -229, -229, -229, -229, -229, -229, -229,
-     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
-     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
-
-     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
-     -229, -229, -229, -229, -229, -229, -229, -229,  239,  239,
-      239,  239,  239,  239,  239,  239,  239,  239, -229, -229,
-     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
-     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
-     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
-     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
-     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
-     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
-     -229, -229, -229, -229, -229, -229, -229, -229
-
-    },
-
-    {
-       13, -230, -230, -230, -230, -230, -230, -230, -230, -230,
-     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
-     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
-     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
-     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
-     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
-     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
-     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
-     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
-     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
-
-     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
-     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
-     -230, -230, -230, -230, -230, -230, -230, -230
-    },
-
-    {
-       13, -231, -231, -231, -231, -231, -231, -231, -231, -231,
-     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
-     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
-     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
-     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
-     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
-     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
-
-     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
-     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
-     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
-     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
-     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
-     -231, -231, -231, -231, -231, -231, -231, -231
-    },
-
-    {
-       13, -232, -232, -232, -232, -232, -232, -232, -232, -232,
-     -232, -232, -232, -232, -232, -232, -232, -232, -232, -232,
-     -232, -232, -232, -232, -232, -232, -232, -232, -232, -232,
-     -232, -232,  232, -232, -232, -232, -232, -232, -232, -232,
-
-     -232, -232, -232,  233, -232,  233,  234, -232,  235,  236,
-      236,  236,  236,  236,  236,  236,  236,  236, -232, -232,
-     -232, -232, -232, -232, -232, -232, -232, -232, -232, -232,
-     -232, -232, -232, -232, -232, -232, -232, -232, -232, -232,
-     -232, -232, -232, -232, -232, -232, -232, -232, -232, -232,
-     -232, -232, -232, -232, -232, -232, -232, -232, -232, -232,
-     -232, -232, -232, -232, -232, -232, -232, -232, -232, -232,
-     -232, -232, -232, -232, -232, -232, -232, -232, -232, -232,
-     -232, -232, -232, -232, -232, -232, -232, -232
-    },
-
-    {
-       13, -233, -233, -233, -233, -233, -233, -233, -233, -233,
-
-     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
-     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
-     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
-     -233, -233, -233, -233, -233, -233,  234, -233,  235,  236,
-      236,  236,  236,  236,  236,  236,  236,  236, -233, -233,
-     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
-     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
-     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
-     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
-     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
-
-     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
-     -233, -233, -233, -233, -233, -233, -233, -233
-    },
-
-    {
-       13, -234, -234, -234, -234, -234, -234, -234, -234, -234,
-     -234, -234, -234, -234, -234, -234, -234, -234, -234, -234,
-     -234, -234, -234, -234, -234, -234, -234, -234, -234, -234,
-     -234, -234, -234, -234, -234, -234, -234, -234, -234, -234,
-     -234, -234, -234, -234, -234, -234, -234, -234,  290,  290,
-      290,  290,  290,  290,  290,  290,  290,  290, -234, -234,
-     -234, -234, -234, -234, -234, -234, -234, -234, -234, -234,
-     -234, -234, -234, -234, -234, -234, -234, -234, -234, -234,
-
-     -234, -234, -234, -234, -234, -234, -234, -234, -234, -234,
-     -234, -234, -234, -234, -234, -234, -234, -234, -234, -234,
-     -234, -234, -234, -234, -234, -234, -234, -234, -234, -234,
-     -234, -234, -234, -234, -234, -234, -234, -234, -234, -234,
-     -234, -234, -234, -234, -234, -234, -234, -234
-    },
-
-    {
-       13, -235, -235, -235, -235, -235, -235, -235, -235, -235,
-     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
-     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
-     -235, -235,  291, -235, -235, -235, -235, -235, -235, -235,
-     -235,  292, -235, -235, -235, -235,  293, -235,  294,  294,
-
-      294,  294,  294,  294,  294,  294,  294,  294, -235, -235,
-     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
-     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
-     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
-     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
-     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
-     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
-     -235, -235, -235, -235, -235, -235, -235, -235
-    },
-
-    {
-       13, -236, -236, -236, -236, -236, -236, -236, -236, -236,
-     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
-
-     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
-     -236, -236,  295, -236, -236, -236, -236, -236, -236, -236,
-     -236,  296, -236, -236, -236, -236,  293,  297,  298,  298,
-      298,  298,  298,  298,  298,  298,  298,  298, -236, -236,
-     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
-     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
-     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
-     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
-     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
-     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
-
-     -236, -236, -236, -236, -236, -236, -236, -236
-    },
-
-    {
-       13, -237, -237, -237, -237, -237, -237, -237, -237, -237,
-     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
-     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
-     -237, -237,  237, -237, -237, -237, -237, -237, -237, -237,
-     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
-     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
-     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
-     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
-     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
-
-     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
-     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
-     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
-     -237, -237, -237, -237, -237, -237, -237, -237
-    },
-
-    {
-       13, -238, -238, -238, -238, -238, -238, -238, -238, -238,
-     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
-     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
-     -238, -238,  238, -238, -238, -238, -238, -238, -238, -238,
-     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
-     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
-
-     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
-     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
-     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
-     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
-     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
-     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
-     -238, -238, -238, -238, -238, -238, -238, -238
-    },
-
-    {
-       13, -239, -239, -239, -239, -239, -239, -239, -239, -239,
-     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
-     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
-
-     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
-     -239, -239, -239, -239, -239, -239, -239, -239,  239,  239,
-      239,  239,  239,  239,  239,  239,  239,  239, -239, -239,
-     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
-     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
-     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
-     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
-     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
-     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
-     -239, -239, -239, -239, -239, -239, -239, -239
-
-    },
-
-    {
-       13,  240,  240,  240,  240,  240,  240,  240,  240,  240,
-     -240,  240,  240,  240,  240,  240,  240,  240,  240,  240,
-      240,  240,  240,  240,  240,  240,  240,  240,  240,  240,
-      240,  240,  240,  240,  240,  240,  240,  240,  240,  240,
-      240,  240,  240,  240,  240,  240,  240,  240,  240,  240,
-      240,  240,  240,  240,  240,  240,  240,  240,  240,  240,
-      240,  240,  240,  240,  240,  240,  240,  240,  240,  240,
-      240,  240,  240,  240,  240,  240,  240,  240,  240,  240,
-      240,  240,  240,  240,  240,  240,  240,  240,  240,  240,
-      240,  240,  240,  240,  240,  240,  240,  240,  240,  240,
-
-      240,  240,  240,  240,  240,  240,  240,  240,  240,  240,
-      240,  240,  240,  240,  240,  240,  240,  240,  240,  240,
-      240,  240,  240,  240,  240,  240,  240,  240
-    },
-
-    {
-       13, -241, -241, -241, -241, -241, -241, -241, -241, -241,
-     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
-     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
-     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
-     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
-     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
-     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
-
-     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
-     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
-     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
-     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
-     -241, -241, -241, -241, -241,  299, -241, -241, -241, -241,
-     -241, -241, -241, -241, -241, -241, -241, -241
-    },
-
-    {
-       13, -242, -242, -242, -242, -242, -242, -242, -242, -242,
-     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
-     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
-     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
-
-     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
-     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
-     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
-     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
-     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
-     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
-     -242,  253, -242, -242, -242, -242, -242, -242, -242, -242,
-     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
-     -242, -242, -242, -242, -242, -242, -242, -242
-    },
-
-    {
-       13, -243, -243, -243, -243, -243, -243, -243, -243, -243,
-
-     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
-     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
-     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
-     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
-     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
-     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
-     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
-     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
-     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
-     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
-
-     -243, -243, -243, -243, -243, -243,  300, -243, -243, -243,
-     -243, -243, -243, -243, -243, -243, -243, -243
-    },
-
-    {
-       13, -244, -244, -244, -244, -244, -244, -244, -244, -244,
-     -244, -244, -244, -244, -244, -244, -244, -244, -244, -244,
-     -244, -244, -244, -244, -244, -244, -244, -244, -244, -244,
-     -244, -244, -244, -244, -244, -244, -244, -244, -244, -244,
-     -244, -244, -244, -244, -244, -244, -244, -244, -244, -244,
-     -244, -244, -244, -244, -244, -244, -244, -244, -244, -244,
-     -244, -244, -244, -244, -244, -244, -244, -244, -244, -244,
-     -244, -244, -244, -244, -244, -244, -244, -244, -244, -244,
-
-     -244, -244, -244, -244, -244, -244, -244, -244, -244, -244,
-     -244, -244, -244, -244, -244, -244, -244, -244, -244, -244,
-     -244, -244, -244, -244, -244, -244, -244, -244, -244,  130,
-     -244, -244, -244, -244, -244, -244, -244, -244, -244, -244,
-     -244, -244, -244, -244, -244, -244, -244, -244
-    },
-
-    {
-       13, -245, -245, -245, -245, -245, -245, -245, -245, -245,
-     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
-     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
-     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
-     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
-
-     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
-     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
-     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
-     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
-     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
-     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
-     -245, -245, -245, -245,  301, -245, -245, -245, -245, -245,
-     -245, -245, -245, -245, -245, -245, -245, -245
-    },
-
-    {
-       13, -246, -246, -246, -246, -246, -246, -246, -246, -246,
-     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
-
-     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
-     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
-     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
-     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
-     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
-     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
-     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
-     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
-     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
-     -246, -246, -246, -246, -246, -246,  137, -246, -246, -246,
-
-     -246, -246, -246, -246, -246, -246, -246, -246
-    },
-
-    {
-       13, -247, -247, -247, -247, -247, -247, -247, -247, -247,
-     -247, -247, -247, -247, -247, -247, -247, -247, -247, -247,
-     -247, -247, -247, -247, -247, -247, -247, -247, -247, -247,
-     -247, -247, -247, -247, -247, -247, -247, -247, -247, -247,
-     -247, -247, -247, -247, -247, -247, -247, -247, -247, -247,
-     -247, -247, -247, -247, -247, -247, -247, -247, -247, -247,
-     -247, -247, -247, -247, -247, -247, -247, -247, -247, -247,
-     -247, -247, -247, -247, -247, -247, -247, -247, -247, -247,
-     -247, -247, -247, -247, -247, -247, -247, -247, -247, -247,
-
-     -247, -247, -247, -247, -247, -247, -247, -247, -247, -247,
-     -247, -247, -247, -247, -247, -247, -247, -247,  128, -247,
-     -247, -247, -247, -247, -247, -247, -247, -247, -247, -247,
-     -247, -247, -247, -247, -247, -247, -247, -247
-    },
-
-    {
-       13, -248, -248, -248, -248, -248, -248, -248, -248, -248,
-     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
-     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
-     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
-     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
-     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
-
-     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
-     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
-     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
-     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
-      128, -248, -248, -248, -248, -248, -248, -248, -248, -248,
-     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
-     -248, -248, -248, -248, -248, -248, -248, -248
-    },
-
-    {
-       13, -249, -249, -249, -249, -249, -249, -249, -249, -249,
-     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
-     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
-
-     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
-     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
-     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
-     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
-     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
-     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
-     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
-     -249, -249, -249,  302, -249, -249, -249, -249, -249, -249,
-     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
-     -249, -249, -249, -249, -249, -249, -249, -249
-
-    },
-
-    {
-       13, -250, -250, -250, -250, -250, -250, -250, -250, -250,
-     -250, -250, -250, -250, -250, -250, -250, -250, -250, -250,
-     -250, -250, -250, -250, -250, -250, -250, -250, -250, -250,
-     -250, -250, -250, -250, -250, -250, -250, -250, -250, -250,
-     -250, -250, -250, -250, -250, -250, -250, -250, -250, -250,
-     -250, -250, -250, -250, -250, -250, -250, -250, -250, -250,
-     -250, -250, -250, -250, -250, -250, -250, -250, -250, -250,
-     -250, -250, -250, -250, -250, -250, -250, -250, -250, -250,
-     -250, -250, -250, -250, -250, -250, -250, -250, -250, -250,
-     -250, -250, -250, -250, -250, -250, -250, -250, -250, -250,
-
-     -250, -250, -250, -250, -250, -250, -250, -250, -250,  303,
-     -250, -250, -250, -250, -250,  304, -250, -250, -250, -250,
-     -250, -250, -250, -250, -250, -250, -250, -250
-    },
-
-    {
-       13, -251, -251, -251, -251, -251, -251, -251, -251, -251,
-     -251, -251, -251, -251, -251, -251, -251, -251, -251, -251,
-     -251, -251, -251, -251, -251, -251, -251, -251, -251, -251,
-     -251, -251, -251, -251, -251, -251, -251, -251, -251, -251,
-     -251, -251, -251, -251, -251, -251, -251, -251, -251, -251,
-     -251, -251, -251, -251, -251, -251, -251, -251, -251, -251,
-     -251, -251, -251, -251, -251, -251, -251, -251, -251, -251,
-
-     -251, -251, -251, -251, -251, -251, -251, -251, -251, -251,
-     -251, -251, -251, -251, -251, -251, -251, -251, -251, -251,
-     -251, -251, -251, -251, -251, -251, -251, -251, -251, -251,
-     -251, -251, -251, -251, -251, -251, -251, -251, -251, -251,
-      148, -251, -251, -251, -251, -251, -251, -251, -251, -251,
-     -251, -251, -251, -251, -251, -251, -251, -251
-    },
-
-    {
-       13, -252, -252, -252, -252, -252, -252, -252, -252, -252,
-     -252, -252, -252, -252, -252, -252, -252, -252, -252, -252,
-     -252, -252, -252, -252, -252, -252, -252, -252, -252, -252,
-     -252, -252, -252, -252, -252, -252, -252, -252, -252, -252,
-
-     -252, -252, -252, -252, -252, -252, -252, -252, -252, -252,
-     -252, -252, -252, -252, -252, -252, -252, -252, -252, -252,
-     -252, -252, -252, -252, -252, -252, -252, -252, -252, -252,
-     -252, -252, -252, -252, -252, -252, -252, -252, -252, -252,
-     -252, -252, -252, -252, -252, -252, -252, -252, -252, -252,
-     -252, -252, -252, -252, -252, -252, -252, -252, -252, -252,
-     -252, -252, -252, -252, -252, -252, -252, -252, -252,  125,
-     -252, -252, -252, -252, -252, -252, -252, -252, -252, -252,
-     -252, -252, -252, -252, -252, -252, -252, -252
-    },
-
-    {
-       13, -253, -253, -253, -253, -253, -253, -253, -253, -253,
-
-     -253, -253, -253, -253, -253, -253, -253, -253, -253, -253,
-     -253, -253, -253, -253, -253, -253, -253, -253, -253, -253,
-     -253, -253, -253, -253, -253, -253, -253, -253, -253, -253,
-     -253, -253, -253, -253, -253, -253, -253, -253, -253, -253,
-     -253, -253, -253, -253, -253, -253, -253, -253, -253, -253,
-     -253, -253, -253, -253, -253, -253, -253, -253, -253, -253,
-     -253, -253, -253, -253, -253, -253, -253, -253, -253, -253,
-     -253, -253, -253, -253, -253, -253, -253, -253, -253, -253,
-     -253, -253, -253, -253, -253, -253, -253, -253, -253, -253,
-     -253, -253, -253, -253, -253, -253, -253, -253, -253, -253,
-
-     -253, -253, -253, -253, -253, -253, -253, -253, -253, -253,
-     -253, -253, -253, -253, -253, -253, -253, -253
-    },
-
-    {
-       13, -254, -254, -254, -254, -254, -254, -254, -254, -254,
-     -254, -254, -254, -254, -254, -254, -254, -254, -254, -254,
-     -254, -254, -254, -254, -254, -254, -254, -254, -254, -254,
-     -254, -254, -254, -254, -254, -254, -254, -254, -254, -254,
-     -254, -254, -254, -254, -254, -254, -254, -254, -254, -254,
-     -254, -254, -254, -254, -254, -254, -254, -254, -254, -254,
-     -254, -254, -254, -254, -254, -254, -254, -254, -254, -254,
-     -254, -254, -254, -254, -254, -254, -254, -254, -254, -254,
-
-     -254, -254, -254, -254, -254, -254, -254, -254, -254, -254,
-     -254, -254, -254, -254, -254, -254, -254, -254, -254, -254,
-     -254, -254, -254, -254, -254, -254, -254, -254, -254, -254,
-      163, -254, -254, -254, -254, -254, -254, -254, -254, -254,
-     -254, -254, -254, -254, -254, -254, -254, -254
-    },
-
-    {
-       13, -255, -255, -255, -255, -255, -255, -255, -255, -255,
-     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
-     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
-     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
-     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
-
-     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
-     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
-     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
-     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
-     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
-     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
-      305, -255, -255, -255, -255, -255, -255, -255, -255, -255,
-     -255, -255, -255, -255, -255, -255, -255, -255
-    },
-
-    {
-       13, -256, -256, -256, -256, -256, -256, -256, -256, -256,
-     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
-
-     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
-     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
-     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
-     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
-     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
-     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
-     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
-     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
-     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
-     -256, -256, -256, -256, -256, -256,  306, -256, -256, -256,
-
-     -256, -256, -256, -256, -256, -256, -256, -256
-    },
-
-    {
-       13, -257, -257, -257, -257, -257, -257, -257, -257, -257,
-     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
-     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
-     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
-     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
-     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
-     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
-     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
-     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
-
-     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
-     -257,  307, -257, -257, -257, -257, -257, -257, -257, -257,
-     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
-     -257, -257, -257, -257, -257, -257, -257, -257
-    },
-
-    {
-       13, -258, -258, -258, -258, -258, -258, -258, -258, -258,
-     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
-     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
-     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
-     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
-     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
-
-     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
-     -258, -258, -258, -258, -258, -258,  308,  309, -258, -258,
-     -258, -258,  310, -258, -258, -258, -258, -258, -258, -258,
-     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
-     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
-     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
-     -258, -258, -258, -258, -258, -258, -258, -258
-    },
-
-    {
-       13, -259, -259, -259, -259, -259, -259, -259, -259, -259,
-     -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
-     -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
-
-     -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
-     -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
-     -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
-     -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
-     -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
-     -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
-     -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
-     -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
-     -259, -259, -259, -259, -259, -259,  311, -259, -259, -259,
-     -259, -259, -259, -259, -259, -259, -259, -259
-
-    },
-
-    {
-       13, -260, -260, -260, -260, -260, -260, -260, -260, -260,
-     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
-     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
-     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
-     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
-     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
-     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
-     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
-     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
-     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
-
-     -260,  312, -260, -260, -260, -260, -260, -260, -260, -260,
-     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
-     -260, -260, -260, -260, -260, -260, -260, -260
-    },
-
-    {
-       13, -261, -261, -261, -261, -261, -261, -261, -261, -261,
-     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
-     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
-     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
-     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
-     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
-     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
-
-     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
-     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
-     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
-     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
-     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
-     -261, -261, -261, -261, -261, -261, -261, -261
-    },
-
-    {
-       13, -262, -262, -262, -262, -262, -262, -262, -262, -262,
-     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
-     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
-     -262, -262,  313, -262, -262, -262, -262, -262, -262, -262,
-
-      314, -262, -262, -262, -262, -262, -262, -262, -262, -262,
-     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
-     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
-     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
-     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
-     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
-     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
-     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
-     -262, -262, -262, -262, -262, -262, -262, -262
-    },
-
-    {
-       13, -263, -263, -263, -263, -263, -263, -263, -263, -263,
-
-     -263, -263, -263, -263, -263, -263, -263, -263, -263, -263,
-     -263, -263, -263, -263, -263, -263, -263, -263, -263, -263,
-     -263, -263,  263, -263, -263, -263, -263, -263, -263, -263,
-      264, -263, -263, -263, -263, -263, -263, -263, -263, -263,
-     -263, -263, -263, -263, -263, -263, -263, -263, -263, -263,
-     -263, -263, -263, -263, -263, -263, -263, -263, -263, -263,
-     -263, -263, -263, -263, -263, -263, -263, -263, -263, -263,
-     -263, -263, -263, -263, -263, -263, -263, -263, -263, -263,
-     -263, -263, -263, -263, -263, -263, -263, -263, -263, -263,
-     -263, -263, -263, -263, -263, -263, -263, -263, -263, -263,
-
-     -263, -263, -263, -263, -263, -263, -263, -263, -263, -263,
-     -263, -263, -263, -263, -263, -263, -263, -263
-    },
-
-    {
-       13, -264, -264, -264, -264, -264, -264, -264, -264, -264,
-     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
-     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
-     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
-     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
-     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
-     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
-     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
-
-     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
-     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
-     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
-     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
-     -264, -264, -264, -264, -264, -264, -264, -264
-    },
-
-    {
-       13, -265, -265, -265, -265, -265, -265, -265, -265, -265,
-     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
-     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
-     -265, -265,  315, -265, -265, -265, -265, -265, -265, -265,
-      316, -265, -265, -265, -265, -265, -265, -265, -265, -265,
-
-     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
-     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
-     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
-     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
-     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
-     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
-     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
-     -265, -265, -265, -265, -265, -265, -265, -265
-    },
-
-    {
-       13, -266, -266, -266, -266, -266, -266, -266, -266, -266,
-     -266, -266, -266, -266, -266, -266, -266, -266, -266, -266,
-
-     -266, -266, -266, -266, -266, -266, -266, -266, -266, -266,
-     -266, -266, -266, -266, -266, -266, -266, -266, -266, -266,
-     -266, -266, -266, -266, -266, -266, -266, -266, -266, -266,
-     -266, -266, -266, -266, -266, -266, -266, -266, -266, -266,
-     -266, -266, -266, -266, -266, -266, -266, -266, -266, -266,
-     -266, -266, -266, -266, -266, -266, -266, -266, -266, -266,
-     -266, -266, -266, -266, -266, -266, -266, -266, -266, -266,
-     -266, -266, -266, -266, -266, -266, -266, -266, -266, -266,
-     -266, -266, -266, -266, -266, -266, -266, -266, -266, -266,
-     -266, -266, -266, -266, -266,  317, -266, -266, -266, -266,
-
-     -266, -266, -266, -266, -266, -266, -266, -266
-    },
-
-    {
-       13, -267, -267, -267, -267, -267, -267, -267, -267, -267,
-     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
-     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
-     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
-     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
-     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
-     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
-     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
-     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
-
-     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
-     -267,  318, -267, -267, -267, -267, -267, -267, -267, -267,
-     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
-     -267, -267, -267, -267, -267, -267, -267, -267
-    },
-
-    {
-       13, -268, -268, -268, -268, -268, -268, -268, -268, -268,
-     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
-     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
-     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
-     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
-     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
-
-     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
-     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
-     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
-     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
-     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
-     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
-     -268, -268, -268, -268, -268, -268, -268, -268
-    },
-
-    {
-       13, -269, -269, -269, -269, -269, -269, -269, -269, -269,
-     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
-     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
-
-     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
-     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
-     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
-     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
-     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
-     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
-     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
-     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
-     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
-     -269, -269, -269, -269, -269, -269, -269, -269
-
-    },
-
-    {
-       13, -270, -270, -270, -270, -270, -270, -270, -270, -270,
-     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
-     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
-     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
-     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
-     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
-     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
-     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
-     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
-     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
-
-     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
-     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
-     -270, -270, -270, -270, -270, -270, -270, -270
-    },
-
-    {
-       13, -271, -271, -271, -271, -271, -271, -271, -271, -271,
-     -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
-     -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
-     -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
-     -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
-     -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
-     -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
-
-     -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
-     -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
-     -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
-     -271, -271, -271, -271, -271, -271, -271, -271, -271,  319,
-     -271, -271, -271, -271, -271,  320, -271, -271, -271, -271,
-     -271, -271, -271, -271, -271, -271, -271, -271
-    },
-
-    {
-       13, -272, -272, -272, -272, -272, -272, -272, -272, -272,
-     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
-     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
-     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
-
-     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
-     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
-     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
-     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
-     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
-     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
-     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
-      321, -272, -272, -272, -272, -272, -272, -272, -272, -272,
-     -272, -272, -272, -272, -272, -272, -272, -272
-    },
-
-    {
-       13, -273, -273, -273, -273, -273, -273, -273, -273, -273,
-
-     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
-     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
-     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
-     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
-     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
-     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
-     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
-     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
-     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
-     -273, -273, -273, -273, -273, -273, -273, -273, -273,  322,
-
-     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
-     -273, -273, -273, -273, -273, -273, -273, -273
-    },
-
-    {
-       13, -274, -274, -274, -274, -274, -274, -274, -274, -274,
-     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
-     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
-     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
-     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
-     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
-     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
-     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
-
-     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
-     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
-     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
-     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
-     -274, -274, -274, -274, -274, -274, -274, -274
-    },
-
-    {
-       13, -275, -275, -275, -275, -275, -275, -275, -275, -275,
-     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
-     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
-     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
-     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
-
-     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
-     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
-     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
-     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
-     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
-     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
-     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
-     -275, -275, -275, -275, -275, -275, -275, -275
-    },
-
-    {
-       13, -276, -276, -276, -276, -276, -276, -276, -276, -276,
-     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
-
-     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
-     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
-     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
-     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
-     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
-     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
-     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
-     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
-     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
-      323, -276, -276, -276, -276, -276, -276, -276, -276, -276,
-
-     -276, -276, -276, -276, -276, -276, -276, -276
-    },
-
-    {
-       13, -277, -277, -277, -277, -277, -277, -277, -277, -277,
-     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
-     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
-     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
-     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
-     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
-     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
-     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
-     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
-
-     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
-     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
-      324, -277, -277, -277, -277, -277, -277, -277, -277, -277,
-     -277, -277, -277, -277, -277, -277, -277, -277
-    },
-
-    {
-       13, -278, -278, -278, -278, -278, -278, -278, -278, -278,
-     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
-     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
-     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
-     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
-     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
-
-     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
-     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
-     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
-     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
-     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
-     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
-     -278, -278, -278, -278, -278, -278, -278, -278
-    },
-
-    {
-       13, -279, -279, -279, -279, -279, -279, -279, -279, -279,
-     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
-     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
-
-     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
-     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
-     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
-     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
-     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
-     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
-     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
-     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
-     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
-     -279, -279, -279, -279, -279, -279, -279, -279
-
-    },
-
-    {
-       13, -280, -280, -280, -280, -280, -280, -280, -280, -280,
-     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
-     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
-     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
-     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
-     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
-     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
-     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
-     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
-     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
-
-     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
-     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
-     -280, -280, -280, -280, -280, -280, -280, -280
-    },
-
-    {
-       13, -281, -281, -281, -281, -281, -281, -281, -281, -281,
-     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
-     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
-     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
-     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
-     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
-     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
-
-     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
-     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
-     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
-     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
-     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
-     -281, -281, -281, -281, -281, -281, -281, -281
-    },
-
-    {
-       13, -282, -282, -282, -282, -282, -282, -282, -282, -282,
-     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
-     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
-     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
-
-     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
-     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
-     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
-     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
-     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
-     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
-     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
-     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
-     -282, -282, -282, -282, -282, -282, -282, -282
-    },
-
-    {
-       13, -283, -283, -283, -283, -283, -283, -283, -283, -283,
-
-     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
-     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
-     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
-     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
-     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
-     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
-     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
-     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
-     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
-     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
-
-     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
-     -283, -283, -283, -283, -283, -283, -283, -283
-    },
-
-    {
-       13, -284, -284, -284, -284, -284, -284, -284, -284, -284,
-     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
-     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
-     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
-     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
-     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
-     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
-     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
-
-     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
-     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
-     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
-     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
-     -284, -284, -284, -284, -284, -284, -284, -284
-    },
-
-    {
-       13, -285, -285, -285, -285, -285, -285, -285, -285, -285,
-     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
-     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
-     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
-     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
-
-     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
-     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
-     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
-     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
-     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
-     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
-     -285, -285, -285, -285, -285, -285,  325, -285, -285, -285,
-     -285, -285, -285, -285, -285, -285, -285, -285
-    },
-
-    {
-       13, -286, -286, -286, -286, -286, -286, -286, -286, -286,
-     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
-
-     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
-     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
-     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
-     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
-     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
-     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
-     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
-     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
-     -286,  326, -286, -286, -286, -286, -286, -286, -286, -286,
-     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
-
-     -286, -286, -286, -286, -286, -286, -286, -286
-    },
-
-    {
-       13, -287, -287, -287, -287, -287, -287, -287, -287, -287,
-     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
-     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
-     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
-     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
-     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
-     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
-     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
-     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
-
-     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
-     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
-     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
-     -287, -287, -287, -287, -287, -287, -287, -287
-    },
-
-    {
-       13, -288, -288, -288, -288, -288, -288, -288, -288, -288,
-     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
-     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
-     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
-     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
-     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
-
-     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
-     -288, -288, -288, -288, -288, -288,  327,  328, -288, -288,
-     -288, -288,  329, -288, -288, -288, -288, -288, -288, -288,
-     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
-     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
-     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
-     -288, -288, -288, -288, -288, -288, -288, -288
-    },
-
-    {
-       13, -289, -289, -289, -289, -289, -289, -289, -289, -289,
-     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
-     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
-
-     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
-     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
-     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
-     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
-     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
-     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
-     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
-     -289,  330, -289, -289, -289, -289, -289, -289, -289, -289,
-     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
-     -289, -289, -289, -289, -289, -289, -289, -289
-
-    },
-
-    {
-       13, -290, -290, -290, -290, -290, -290, -290, -290, -290,
-     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
-     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
-     -290, -290,  291, -290, -290, -290, -290, -290, -290, -290,
-     -290,  292, -290, -290, -290, -290, -290, -290,  290,  290,
-      290,  290,  290,  290,  290,  290,  290,  290, -290, -290,
-     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
-     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
-     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
-     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
-
-     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
-     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
-     -290, -290, -290, -290, -290, -290, -290, -290
-    },
-
-    {
-       13, -291, -291, -291, -291, -291, -291, -291, -291, -291,
-     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
-     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
-     -291, -291,  291, -291, -291, -291, -291, -291, -291, -291,
-     -291,  292, -291, -291, -291, -291, -291, -291, -291, -291,
-     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
-     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
-
-     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
-     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
-     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
-     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
-     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
-     -291, -291, -291, -291, -291, -291, -291, -291
-    },
-
-    {
-       13, -292, -292, -292, -292, -292, -292, -292, -292, -292,
-     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
-     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
-     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
-
-     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
-     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
-     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
-     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
-     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
-     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
-     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
-     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
-     -292, -292, -292, -292, -292, -292, -292, -292
-    },
-
-    {
-       13, -293, -293, -293, -293, -293, -293, -293, -293, -293,
-
-     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
-     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
-     -293, -293,  291, -293, -293, -293, -293, -293, -293, -293,
-     -293,  292, -293, -293, -293, -293, -293, -293,  331,  331,
-      331,  331,  331,  331,  331,  331,  331,  331, -293, -293,
-     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
-     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
-     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
-     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
-     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
-
-     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
-     -293, -293, -293, -293, -293, -293, -293, -293
-    },
-
-    {
-       13, -294, -294, -294, -294, -294, -294, -294, -294, -294,
-     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
-     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
-     -294, -294,  291, -294, -294, -294, -294, -294, -294, -294,
-     -294,  292, -294, -294, -294, -294,  293, -294,  294,  294,
-      294,  294,  294,  294,  294,  294,  294,  294, -294, -294,
-     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
-     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
-
-     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
-     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
-     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
-     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
-     -294, -294, -294, -294, -294, -294, -294, -294
-    },
-
-    {
-       13, -295, -295, -295, -295, -295, -295, -295, -295, -295,
-     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
-     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
-     -295, -295,  295, -295, -295, -295, -295, -295, -295, -295,
-     -295,  296, -295, -295, -295, -295, -295, -295, -295, -295,
-
-     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
-     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
-     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
-     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
-     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
-     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
-     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
-     -295, -295, -295, -295, -295, -295, -295, -295
-    },
-
-    {
-       13, -296, -296, -296, -296, -296, -296, -296, -296, -296,
-     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
-
-     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
-     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
-     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
-     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
-     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
-     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
-     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
-     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
-     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
-     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
-
-     -296, -296, -296, -296, -296, -296, -296, -296
-    },
-
-    {
-       13, -297, -297, -297, -297, -297, -297, -297, -297, -297,
-     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
-     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
-     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
-     -297, -297, -297, -297, -297, -297, -297, -297, -297,  332,
-      332,  332,  332,  332,  332,  332,  332,  332, -297, -297,
-     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
-     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
-     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
-
-     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
-     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
-     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
-     -297, -297, -297, -297, -297, -297, -297, -297
-    },
-
-    {
-       13, -298, -298, -298, -298, -298, -298, -298, -298, -298,
-     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
-     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
-     -298, -298,  295, -298, -298, -298, -298, -298, -298, -298,
-     -298,  296, -298, -298, -298, -298,  293,  297,  298,  298,
-      298,  298,  298,  298,  298,  298,  298,  298, -298, -298,
-
-     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
-     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
-     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
-     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
-     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
-     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
-     -298, -298, -298, -298, -298, -298, -298, -298
-    },
-
-    {
-       13, -299, -299, -299, -299, -299, -299, -299, -299, -299,
-     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
-     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
-
-     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
-     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
-     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
-     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
-     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
-     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
-     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
-     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
-     -299, -299, -299, -299, -299, -299,  333, -299, -299, -299,
-     -299, -299, -299, -299, -299, -299, -299, -299
-
-    },
-
-    {
-       13, -300, -300, -300, -300, -300, -300, -300, -300, -300,
-     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
-     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
-     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
-     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
-     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
-     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
-     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
-     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
-     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
-
-     -300,  137, -300, -300, -300, -300, -300, -300, -300, -300,
-     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
-     -300, -300, -300, -300, -300, -300, -300, -300
-    },
-
-    {
-       13, -301, -301, -301, -301, -301, -301, -301, -301, -301,
-     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
-     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
-     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
-     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
-     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
-     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
-
-     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
-     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
-     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
-     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
-      131, -301, -301, -301, -301, -301, -301, -301, -301, -301,
-     -301, -301, -301, -301, -301, -301, -301, -301
-    },
-
-    {
-       13, -302, -302, -302, -302, -302, -302, -302, -302, -302,
-     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
-     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
-     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
-
-     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
-     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
-     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
-     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
-     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
-     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
-     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
-     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
-     -302, -302, -302, -302, -302, -302, -302, -302
-    },
-
-    {
-       13, -303, -303, -303, -303, -303, -303, -303, -303, -303,
-
-     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
-     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
-     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
-     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
-     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
-     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
-     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
-     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
-     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
-     -303, -303, -303, -303, -303,  334, -303, -303, -303, -303,
-
-     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
-     -303, -303, -303, -303, -303, -303, -303, -303
-    },
-
-    {
-       13, -304, -304, -304, -304, -304, -304, -304, -304, -304,
-     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
-     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
-     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
-     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
-     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
-     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
-     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
-
-     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
-     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
-     -304,  335, -304, -304, -304, -304, -304, -304, -304, -304,
-     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
-     -304, -304, -304, -304, -304, -304, -304, -304
-    },
-
-    {
-       13, -305, -305, -305, -305, -305, -305, -305, -305, -305,
-     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
-     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
-     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
-     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
-
-     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
-     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
-     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
-     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
-     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
-     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
-     -305, -305, -305, -305, -305, -305,  163, -305, -305, -305,
-     -305, -305, -305, -305, -305, -305, -305, -305
-    },
-
-    {
-       13, -306, -306, -306, -306, -306, -306, -306, -306, -306,
-     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
-
-     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
-     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
-     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
-     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
-     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
-     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
-     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
-     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
-     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
-     -306,  336, -306, -306, -306, -306, -306, -306, -306, -306,
-
-     -306, -306, -306, -306, -306, -306, -306, -306
-    },
-
-    {
-       13, -307, -307, -307, -307, -307, -307, -307, -307, -307,
-     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
-     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
-     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
-     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
-     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
-     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
-     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
-     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
-
-     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
-     -307, -307, -307, -307, -307, -307, -307, -307,  163, -307,
-     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
-     -307, -307, -307, -307, -307, -307, -307, -307
-    },
-
-    {
-       13, -308, -308, -308, -308, -308, -308, -308, -308, -308,
-     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
-     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
-     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
-     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
-     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
-
-     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
-     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
-     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
-     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
-     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
-     -308, -308, -308, -308, -308, -308, -308,  337, -308, -308,
-     -308, -308, -308, -308, -308, -308, -308, -308
-    },
-
-    {
-       13, -309, -309, -309, -309, -309, -309, -309, -309, -309,
-     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
-     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
-
-     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
-     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
-     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
-     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
-     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
-     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
-     -309, -309, -309, -309, -309, -309, -309,  338, -309, -309,
-     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
-     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
-     -309, -309, -309, -309, -309, -309, -309, -309
-
-    },
-
-    {
-       13, -310, -310, -310, -310, -310, -310, -310, -310, -310,
-     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
-     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
-     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
-     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
-     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
-     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
-     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
-     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
-     -310, -310, -310, -310, -310, -310, -310,  339, -310, -310,
-
-     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
-     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
-     -310, -310, -310, -310, -310, -310, -310, -310
-    },
-
-    {
-       13, -311, -311, -311, -311, -311, -311, -311, -311, -311,
-     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
-     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
-     -311, -311,  340, -311, -311, -311, -311, -311, -311, -311,
-      341, -311, -311, -311, -311, -311, -311, -311, -311, -311,
-     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
-     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
-
-     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
-     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
-     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
-     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
-     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
-     -311, -311, -311, -311, -311, -311, -311, -311
-    },
-
-    {
-       13, -312, -312, -312, -312, -312, -312, -312, -312, -312,
-     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
-     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
-     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
-
-     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
-     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
-     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
-     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
-     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
-     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
-     -312, -312, -312, -312, -312, -312, -312, -312,  163, -312,
-     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
-     -312, -312, -312, -312, -312, -312, -312, -312
-    },
-
-    {
-       13, -313, -313, -313, -313, -313, -313, -313, -313, -313,
-
-     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
-     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
-     -313, -313,  313, -313, -313, -313, -313, -313, -313, -313,
-      314, -313, -313, -313, -313, -313, -313, -313, -313, -313,
-     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
-     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
-     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
-     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
-     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
-     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
-
-     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
-     -313, -313, -313, -313, -313, -313, -313, -313
-    },
-
-    {
-       13, -314, -314, -314, -314, -314, -314, -314, -314, -314,
-     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
-     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
-     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
-     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
-     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
-     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
-     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
-
-     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
-     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
-     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
-     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
-     -314, -314, -314, -314, -314, -314, -314, -314
-    },
-
-    {
-       13, -315, -315, -315, -315, -315, -315, -315, -315, -315,
-     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
-     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
-     -315, -315,  315, -315, -315, -315, -315, -315, -315, -315,
-      316, -315, -315, -315, -315, -315, -315, -315, -315, -315,
-
-     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
-     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
-     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
-     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
-     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
-     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
-     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
-     -315, -315, -315, -315, -315, -315, -315, -315
-    },
-
-    {
-       13, -316, -316, -316, -316, -316, -316, -316, -316, -316,
-     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
-
-     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
-     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
-     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
-     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
-     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
-     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
-     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
-     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
-     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
-     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
-
-     -316, -316, -316, -316, -316, -316, -316, -316
-    },
-
-    {
-       13, -317, -317, -317, -317, -317, -317, -317, -317, -317,
-     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
-     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
-     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
-     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
-     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
-     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
-     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
-     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
-
-     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
-     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
-     -317, -317, -317, -317, -317, -317,  342, -317, -317, -317,
-     -317, -317, -317, -317, -317, -317, -317, -317
-    },
-
-    {
-       13, -318, -318, -318, -318, -318, -318, -318, -318, -318,
-     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
-     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
-     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
-     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
-     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
-
-     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
-     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
-     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
-     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
-     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
-     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
-     -318, -318, -318, -318, -318, -318, -318, -318
-    },
-
-    {
-       13, -319, -319, -319, -319, -319, -319, -319, -319, -319,
-     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
-     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
-
-     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
-     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
-     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
-     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
-     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
-     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
-     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
-     -319, -319, -319, -319, -319,  343, -319, -319, -319, -319,
-     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
-     -319, -319, -319, -319, -319, -319, -319, -319
-
-    },
-
-    {
-       13, -320, -320, -320, -320, -320, -320, -320, -320, -320,
-     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
-     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
-     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
-     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
-     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
-     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
-     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
-     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
-     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
-
-     -320,  344, -320, -320, -320, -320, -320, -320, -320, -320,
-     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
-     -320, -320, -320, -320, -320, -320, -320, -320
-    },
-
-    {
-       13, -321, -321, -321, -321, -321, -321, -321, -321, -321,
-     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
-     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
-     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
-     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
-     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
-     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
-
-     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
-     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
-     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
-     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
-     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
-     -321, -321, -321, -321, -321, -321, -321, -321
-    },
-
-    {
-       13, -322, -322, -322, -322, -322, -322, -322, -322, -322,
-     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
-     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
-     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
-
-     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
-     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
-     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
-     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
-     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
-     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
-     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
-     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
-     -322, -322, -322, -322, -322, -322, -322, -322
-    },
-
-    {
-       13, -323, -323, -323, -323, -323, -323, -323, -323, -323,
-
-     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
-     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
-     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
-     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
-     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
-     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
-     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
-     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
-     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
-     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
-
-     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
-     -323, -323, -323, -323, -323, -323, -323, -323
-    },
-
-    {
-       13, -324, -324, -324, -324, -324, -324, -324, -324, -324,
-     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
-     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
-     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
-     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
-     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
-     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
-     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
-
-     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
-     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
-     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
-     -324, -324, -324, -324, -324, -324,  205, -324, -324, -324,
-     -324, -324, -324, -324, -324, -324, -324, -324
-    },
-
-    {
-       13, -325, -325, -325, -325, -325, -325, -325, -325, -325,
-     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
-     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
-     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
-     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
-
-     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
-     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
-     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
-     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
-     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
-     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
-     -325,  345, -325, -325, -325, -325, -325, -325, -325, -325,
-     -325, -325, -325, -325, -325, -325, -325, -325
-    },
-
-    {
-       13, -326, -326, -326, -326, -326, -326, -326, -326, -326,
-     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
-
-     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
-     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
-     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
-     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
-     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
-     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
-     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
-     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
-     -326, -326, -326, -326, -326, -326, -326, -326,  346, -326,
-     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
-
-     -326, -326, -326, -326, -326, -326, -326, -326
-    },
-
-    {
-       13, -327, -327, -327, -327, -327, -327, -327, -327, -327,
-     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
-     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
-     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
-     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
-     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
-     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
-     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
-     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
-
-     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
-     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
-     -327, -327, -327, -327, -327, -327, -327,  347, -327, -327,
-     -327, -327, -327, -327, -327, -327, -327, -327
-    },
-
-    {
-       13, -328, -328, -328, -328, -328, -328, -328, -328, -328,
-     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
-     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
-     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
-     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
-     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
-
-     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
-     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
-     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
-     -328, -328, -328, -328, -328, -328, -328,  348, -328, -328,
-     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
-     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
-     -328, -328, -328, -328, -328, -328, -328, -328
-    },
-
-    {
-       13, -329, -329, -329, -329, -329, -329, -329, -329, -329,
-     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
-     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
-
-     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
-     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
-     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
-     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
-     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
-     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
-     -329, -329, -329, -329, -329, -329, -329,  349, -329, -329,
-     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
-     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
-     -329, -329, -329, -329, -329, -329, -329, -329
-
-    },
-
-    {
-       13, -330, -330, -330, -330, -330, -330, -330, -330, -330,
-     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
-     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
-     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
-     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
-     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
-     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
-     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
-     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
-     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
-
-     -330, -330, -330, -330, -330, -330, -330, -330,  350, -330,
-     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
-     -330, -330, -330, -330, -330, -330, -330, -330
-    },
-
-    {
-       13, -331, -331, -331, -331, -331, -331, -331, -331, -331,
-     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
-     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
-     -331, -331,  291, -331, -331, -331, -331, -331, -331, -331,
-     -331,  292, -331, -331, -331, -331, -331, -331,  331,  331,
-      331,  331,  331,  331,  331,  331,  331,  331, -331, -331,
-     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
-
-     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
-     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
-     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
-     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
-     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
-     -331, -331, -331, -331, -331, -331, -331, -331
-    },
-
-    {
-       13, -332, -332, -332, -332, -332, -332, -332, -332, -332,
-     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
-     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
-     -332, -332,  351, -332, -332, -332, -332, -332, -332, -332,
-
-     -332,  352, -332, -332, -332, -332, -332, -332,  353,  353,
-      353,  353,  353,  353,  353,  353,  353,  353, -332, -332,
-     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
-     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
-     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
-     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
-     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
-     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
-     -332, -332, -332, -332, -332, -332, -332, -332
-    },
-
-    {
-       13, -333, -333, -333, -333, -333, -333, -333, -333, -333,
-
-     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
-     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
-     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
-     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
-     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
-     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
-     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
-     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
-     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
-     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
-
-     -333, -333, -333, -333,  354, -333, -333, -333, -333, -333,
-     -333, -333, -333, -333, -333, -333, -333, -333
-    },
-
-    {
-       13, -334, -334, -334, -334, -334, -334, -334, -334, -334,
-     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
-     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
-     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
-     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
-     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
-     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
-     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
-
-     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
-     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
-     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
-      151, -334, -334, -334, -334, -334, -334, -334, -334, -334,
-     -334, -334, -334, -334, -334, -334, -334, -334
-    },
-
-    {
-       13, -335, -335, -335, -335, -335, -335, -335, -335, -335,
-     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
-     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
-     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
-     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
-
-     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
-     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
-     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
-     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
-     -335, -335, -335, -335, -335, -335, -335, -335, -335,  151,
-     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
-     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
-     -335, -335, -335, -335, -335, -335, -335, -335
-    },
-
-    {
-       13, -336, -336, -336, -336, -336, -336, -336, -336, -336,
-     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
-
-     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
-     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
-     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
-     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
-     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
-     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
-     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
-     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
-     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
-      163, -336, -336, -336, -336, -336, -336, -336, -336, -336,
-
-     -336, -336, -336, -336, -336, -336, -336, -336
-    },
-
-    {
-       13, -337, -337, -337, -337, -337, -337, -337, -337, -337,
-     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
-     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
-     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
-     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
-     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
-     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
-     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
-     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
-
-     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
-     -337, -337, -337, -337, -337, -337, -337, -337, -337,  125,
-     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
-     -337, -337, -337, -337, -337, -337, -337, -337
-    },
-
-    {
-       13, -338, -338, -338, -338, -338, -338, -338, -338, -338,
-     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
-     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
-     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
-     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
-     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
-
-     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
-     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
-     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
-     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
-     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
-     -338, -338, -338, -338, -338,  355, -338, -338, -338, -338,
-     -338, -338, -338, -338, -338, -338, -338, -338
-    },
-
-    {
-       13, -339, -339, -339, -339, -339, -339, -339, -339, -339,
-     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
-     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
-
-     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
-     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
-     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
-     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
-     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
-     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
-     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
-      125, -339, -339, -339, -339, -339, -339, -339, -339, -339,
-     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
-     -339, -339, -339, -339, -339, -339, -339, -339
-
-    },
-
-    {
-       13, -340, -340, -340, -340, -340, -340, -340, -340, -340,
-     -340, -340, -340, -340, -340, -340, -340, -340, -340, -340,
-     -340, -340, -340, -340, -340, -340, -340, -340, -340, -340,
-     -340, -340,  340, -340, -340, -340, -340, -340, -340, -340,
-      341, -340, -340, -340, -340, -340, -340, -340, -340, -340,
-     -340, -340, -340, -340, -340, -340, -340, -340, -340, -340,
-     -340, -340, -340, -340, -340, -340, -340, -340, -340, -340,
-     -340, -340, -340, -340, -340, -340, -340, -340, -340, -340,
-     -340, -340, -340, -340, -340, -340, -340, -340, -340, -340,
-     -340, -340, -340, -340, -340, -340, -340, -340, -340, -340,
-
-     -340, -340, -340, -340, -340, -340, -340, -340, -340, -340,
-     -340, -340, -340, -340, -340, -340, -340, -340, -340, -340,
-     -340, -340, -340, -340, -340, -340, -340, -340
-    },
-
-    {
-       13, -341, -341, -341, -341, -341, -341, -341, -341, -341,
-     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
-     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
-     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
-     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
-     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
-     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
-
-     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
-     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
-     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
-     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
-     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
-     -341, -341, -341, -341, -341, -341, -341, -341
-    },
-
-    {
-       13, -342, -342, -342, -342, -342, -342, -342, -342, -342,
-     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
-     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
-     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
-
-     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
-     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
-     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
-     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
-     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
-     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
-     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
-     -342, -342, -342, -342,  356, -342, -342, -342, -342, -342,
-     -342, -342, -342, -342, -342, -342, -342, -342
-    },
-
-    {
-       13, -343, -343, -343, -343, -343, -343, -343, -343, -343,
-
-     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
-     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
-     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
-     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
-     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
-     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
-     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
-     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
-     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
-     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
-
-      357, -343, -343, -343, -343, -343, -343, -343, -343, -343,
-     -343, -343, -343, -343, -343, -343, -343, -343
-    },
-
-    {
-       13, -344, -344, -344, -344, -344, -344, -344, -344, -344,
-     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
-     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
-     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
-     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
-     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
-     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
-     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
-
-     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
-     -344, -344, -344, -344, -344, -344, -344, -344, -344,  358,
-     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
-     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
-     -344, -344, -344, -344, -344, -344, -344, -344
-    },
-
-    {
-       13, -345, -345, -345, -345, -345, -345, -345, -345, -345,
-     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
-     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
-     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
-     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
-
-     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
-     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
-     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
-     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
-     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
-     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
-      359, -345, -345, -345, -345, -345, -345, -345, -345, -345,
-     -345, -345, -345, -345, -345, -345, -345, -345
-    },
-
-    {
-       13, -346, -346, -346, -346, -346, -346, -346, -346, -346,
-     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
-
-     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
-     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
-     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
-     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
-     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
-     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
-     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
-     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
-     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
-     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
-
-     -346, -346, -346, -346, -346, -346, -346, -346
-    },
-
-    {
-       13, -347, -347, -347, -347, -347, -347, -347, -347, -347,
-     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
-     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
-     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
-     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
-     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
-     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
-     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
-     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
-
-     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
-     -347, -347, -347, -347, -347, -347, -347, -347, -347,  360,
-     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
-     -347, -347, -347, -347, -347, -347, -347, -347
-    },
-
-    {
-       13, -348, -348, -348, -348, -348, -348, -348, -348, -348,
-     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
-     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
-     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
-     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
-     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
-
-     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
-     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
-     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
-     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
-     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
-     -348, -348, -348, -348, -348,  361, -348, -348, -348, -348,
-     -348, -348, -348, -348, -348, -348, -348, -348
-    },
-
-    {
-       13, -349, -349, -349, -349, -349, -349, -349, -349, -349,
-     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
-     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
-
-     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
-     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
-     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
-     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
-     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
-     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
-     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
-      362, -349, -349, -349, -349, -349, -349, -349, -349, -349,
-     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
-     -349, -349, -349, -349, -349, -349, -349, -349
-
-    },
-
-    {
-       13, -350, -350, -350, -350, -350, -350, -350, -350, -350,
-     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
-     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
-     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
-     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
-     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
-     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
-     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
-     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
-     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
-
-     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
-     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
-     -350, -350, -350, -350, -350, -350, -350, -350
-    },
-
-    {
-       13, -351, -351, -351, -351, -351, -351, -351, -351, -351,
-     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
-     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
-     -351, -351,  351, -351, -351, -351, -351, -351, -351, -351,
-     -351,  352, -351, -351, -351, -351, -351, -351, -351, -351,
-     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
-     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
-
-     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
-     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
-     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
-     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
-     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
-     -351, -351, -351, -351, -351, -351, -351, -351
-    },
-
-    {
-       13, -352, -352, -352, -352, -352, -352, -352, -352, -352,
-     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
-     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
-     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
-
-     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
-     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
-     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
-     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
-     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
-     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
-     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
-     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
-     -352, -352, -352, -352, -352, -352, -352, -352
-    },
-
-    {
-       13, -353, -353, -353, -353, -353, -353, -353, -353, -353,
-
-     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
-     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
-     -353, -353,  351, -353, -353, -353, -353, -353, -353, -353,
-     -353,  352, -353, -353, -353, -353, -353, -353,  353,  353,
-      353,  353,  353,  353,  353,  353,  353,  353, -353, -353,
-     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
-     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
-     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
-     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
-     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
-
-     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
-     -353, -353, -353, -353, -353, -353, -353, -353
-    },
-
-    {
-       13, -354, -354, -354, -354, -354, -354, -354, -354, -354,
-     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
-     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
-     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
-     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
-     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
-     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
-     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
-
-     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
-     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
-     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
-     -354,  363, -354, -354, -354, -354, -354, -354, -354, -354,
-     -354, -354, -354, -354, -354, -354, -354, -354
-    },
-
-    {
-       13, -355, -355, -355, -355, -355, -355, -355, -355, -355,
-     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
-     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
-     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
-     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
-
-     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
-     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
-     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
-     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
-     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
-     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
-     -355, -355, -355, -355, -355,  125, -355, -355, -355, -355,
-     -355, -355, -355, -355, -355, -355, -355, -355
-    },
-
-    {
-       13, -356, -356, -356, -356, -356, -356, -356, -356, -356,
-     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
-
-     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
-     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
-     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
-     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
-     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
-     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
-     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
-     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
-     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
-     -356,  364, -356, -356, -356, -356, -356, -356, -356, -356,
-
-     -356, -356, -356, -356, -356, -356, -356, -356
-    },
-
-    {
-       13, -357, -357, -357, -357, -357, -357, -357, -357, -357,
-     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
-     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
-     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
-     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
-     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
-     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
-     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
-     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
-
-     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
-     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
-     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
-     -357, -357, -357, -357, -357, -357, -357, -357
-    },
-
-    {
-       13, -358, -358, -358, -358, -358, -358, -358, -358, -358,
-     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
-     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
-     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
-     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
-     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
-
-     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
-     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
-     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
-     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
-     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
-     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
-     -358, -358, -358, -358, -358, -358, -358, -358
-    },
-
-    {
-       13, -359, -359, -359, -359, -359, -359, -359, -359, -359,
-     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
-     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
-
-     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
-     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
-     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
-     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
-     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
-     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
-     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
-     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
-     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
-     -359, -359, -359, -359, -359, -359, -359, -359
-
-    },
-
-    {
-       13, -360, -360, -360, -360, -360, -360, -360, -360, -360,
-     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
-     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
-     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
-     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
-     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
-     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
-     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
-     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
-     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
-
-     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
-     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
-     -360, -360, -360, -360, -360, -360, -360, -360
-    },
-
-    {
-       13, -361, -361, -361, -361, -361, -361, -361, -361, -361,
-     -361, -361, -361, -361, -361, -361, -361, -361, -361, -361,
-     -361, -361, -361, -361, -361, -361, -361, -361, -361, -361,
-     -361, -361, -361, -361, -361, -361, -361, -361, -361, -361,
-     -361, -361, -361, -361, -361, -361, -361, -361, -361, -361,
-     -361, -361, -361, -361, -361, -361, -361, -361, -361, -361,
-     -361, -361, -361, -361, -361, -361, -361, -361, -361, -361,
-
-     -361, -361, -361, -361, -361, -361, -361, -361, -361, -361,
-     -361, -361, -361, -361, -361, -361, -361, -361, -361, -361,
-     -361, -361, -361, -361, -361, -361, -361, -361, -361, -361,
-     -361, -361, -361, -361, -361, -361, -361, -361, -361, -361,
-     -361, -361, -361, -361, -361,  365, -361, -361, -361, -361,
-     -361, -361, -361, -361, -361, -361, -361, -361
-    },
-
-    {
-       13, -362, -362, -362, -362, -362, -362, -362, -362, -362,
-     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
-     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
-     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
-
-     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
-     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
-     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
-     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
-     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
-     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
-     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
-     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
-     -362, -362, -362, -362, -362, -362, -362, -362
-    },
-
-    {
-       13, -363, -363, -363, -363, -363, -363, -363, -363, -363,
-
-     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
-     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
-     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
-     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
-     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
-     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
-     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
-     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
-     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
-     -363, -363, -363, -363, -363, -363, -363, -363, -363,  125,
-
-     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
-     -363, -363, -363, -363, -363, -363, -363, -363
-    },
-
-    {
-       13, -364, -364, -364, -364, -364, -364, -364, -364, -364,
-     -364, -364, -364, -364, -364, -364, -364, -364, -364, -364,
-     -364, -364, -364, -364, -364, -364, -364, -364, -364, -364,
-     -364, -364, -364, -364, -364, -364, -364, -364, -364, -364,
-     -364, -364, -364, -364, -364, -364, -364, -364, -364, -364,
-     -364, -364, -364, -364, -364, -364, -364, -364, -364, -364,
-     -364, -364, -364, -364, -364, -364, -364, -364, -364, -364,
-     -364, -364, -364, -364, -364, -364, -364, -364, -364, -364,
-
-     -364, -364, -364, -364, -364, -364, -364, -364, -364, -364,
-     -364, -364, -364, -364, -364, -364, -364, -364, -364, -364,
-     -364, -364, -364, -364, -364, -364, -364, -364, -364,  366,
-     -364, -364, -364, -364, -364, -364, -364, -364, -364, -364,
-     -364, -364, -364, -364, -364, -364, -364, -364
-    },
-
-    {
-       13, -365, -365, -365, -365, -365, -365, -365, -365, -365,
-     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
-     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
-     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
-     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
-
-     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
-     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
-     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
-     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
-     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
-     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
-     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
-     -365, -365, -365, -365, -365, -365, -365, -365
-    },
-
-    {
-       13, -366, -366, -366, -366, -366, -366, -366, -366, -366,
-     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
-
-     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
-     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
-     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
-     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
-     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
-     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
-     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
-     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
-     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
-     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
-
-     -366, -366, -366, -366, -366, -366, -366, -366
-    },
-
-    } ;
-
-static yy_state_type yy_get_previous_state (void );
-static yy_state_type yy_try_NUL_trans (yy_state_type current_state  );
-static int yy_get_next_buffer (void );
-static void yy_fatal_error (yyconst char msg[]  );
-
-/* Done after the current pattern has been matched and before the
- * corresponding action - sets up wcsulextext.
- */
-#define YY_DO_BEFORE_ACTION \
-	(yytext_ptr) = yy_bp; \
-	(yytext_ptr) -= (yy_more_len); \
-	wcsulexleng = (size_t) (yy_cp - (yytext_ptr)); \
-	(yy_hold_char) = *yy_cp; \
-	*yy_cp = '\0'; \
-	(yy_c_buf_p) = yy_cp;
-
-#define YY_NUM_RULES 118
-#define YY_END_OF_BUFFER 119
-/* This struct is not used in this scanner,
-   but its presence is necessary. */
-struct yy_trans_info
-	{
-	flex_int32_t yy_verify;
-	flex_int32_t yy_nxt;
-	};
-static yyconst flex_int16_t yy_accept[367] =
-    {   0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-      117,  117,  119,   20,  118,    9,   11,   12,   14,   15,
-       20,   15,   15,   20,   15,   15,   15,   15,   20,   20,
-       15,   15,   15,   15,   19,   15,   20,   20,   15,   20,
-       20,   15,   20,   15,   20,   20,   15,   15,   20,   20,
-        1,    8,   20,    2,   20,   20,   23,   21,   22,   44,
-       41,   38,   37,   40,   39,   43,   42,   31,   25,   24,
-       30,   35,   36,   26,   28,   29,   27,   33,   32,  105,
-       45,  105,   57,   61,   66,   67,   69,   72,   74,   83,
-      105,  105,   89,   92,   99,  101,  103,   46,  105,  105,
-
-       62,  105,   68,   70,  105,   78,  105,  105,   93,  100,
-      105,  105,  116,  113,  112,  111,  116,  111,  114,  107,
-      115,  106,  117,    9,   15,    0,    0,   16,    0,   16,
-       16,   16,   16,    0,    0,   16,   17,    0,    0,    0,
-        0,   16,    0,    0,   16,    0,   15,   15,    0,   15,
-       15,    0,    0,    0,   16,    0,    0,    0,    0,   15,
-        0,    0,   15,    0,    0,    0,    0,    0,    0,    0,
-       15,   15,    0,    0,    0,    0,    0,   15,    1,   13,
-        4,    0,    0,    0,   23,   34,   51,    0,    0,   71,
-       73,    0,   85,   91,    0,  104,    0,    0,    0,    0,
-
-        0,   58,    0,    0,   60,    0,   65,    0,   75,   76,
-        0,    0,    0,    0,   86,   87,    0,    0,    0,   97,
-        0,   46,  113,  112,  111,    0,  111,  114,  107,  115,
-      106,    0,    0,    0,    0,    0,  111,  114,  107,  117,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,   15,    0,    0,    0,   15,    0,    0,    0,
-        3,    0,    0,    6,    0,    0,    0,   84,   98,   47,
-        0,    0,    0,   54,   55,    0,    0,   63,   64,   77,
-       79,   80,   81,   82,    0,   88,   90,    0,    0,    0,
-        0,  110,    0,    0,    0,  108,    0,    0,    0,    0,
-
-        0,   18,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    7,    0,    5,    0,   56,    0,    0,
-       52,   53,   59,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-       10,    0,    0,    0,    0,   88,    0,    0,    0,  102,
-        0,  109,    0,    0,    0,    0,   49,   50,   87,   94,
-        0,   96,    0,    0,   95,   48
-    } ;
-
-static yy_state_type yy_last_accepting_state;
-static char *yy_last_accepting_cpos;
-
-static yyconst yy_state_type yy_NUL_trans[367] =
-    {   0,
-       14,   14,   57,   57,   60,   60,   80,   80,  113,  113,
-      123,  123,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,  185,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,  240,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,  185,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,  240,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0
-    } ;
-
-extern int wcsulex_flex_debug;
-int wcsulex_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
-static int yy_more_flag = 0;
-static int yy_more_len = 0;
-#define yymore() ((yy_more_flag) = 1)
-#define YY_MORE_ADJ (yy_more_len)
-#define YY_RESTORE_YY_MORE_OFFSET
-char *wcsulextext;
-#line 1 "wcsulex.l"
-/*============================================================================
-
-  WCSLIB 4.10 - an implementation of the FITS WCS standard.
-  Copyright (C) 1995-2012, Mark Calabretta
-
-  This file is part of WCSLIB.
-
-  WCSLIB is free software: you can redistribute it and/or modify it under the
-  terms of the GNU Lesser General Public License as published by the Free
-  Software Foundation, either version 3 of the License, or (at your option)
-  any later version.
-
-  WCSLIB 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 Lesser General Public License for
-  more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with WCSLIB.  If not, see <http://www.gnu.org/licenses/>.
-
-  Correspondence concerning WCSLIB may be directed to:
-    Internet email: mcalabre at atnf.csiro.au
-    Postal address: Dr. Mark Calabretta
-                    Australia Telescope National Facility, CSIRO
-                    PO Box 76
-                    Epping NSW 1710
-                    AUSTRALIA
-
-  Author: Mark Calabretta, Australia Telescope National Facility
-  http://www.atnf.csiro.au/~mcalabre/index.html
-  $Id: wcsulex.c,v 4.10 2012/02/05 23:41:44 cal103 Exp $
-*=============================================================================
-*
-* wcsulex.l is a Flex description file containing the definition of a
-* recursive, multi-buffered lexical scanner that parses FITS units
-* specifications.
-*
-* It requires Flex v2.5.4 or later.
-*
-* Refer to wcsunits.h for a description of the user interface and operating
-* notes.
-*
-*===========================================================================*/
-/* Options. */
-/* Exponents. */
-/* Metric prefixes. */
-/* Basic and derived SI units. */
-/* Additional recognized units: all metric prefixes allowed. */
-/* Additional recognized units: only super-metric prefixes allowed. */
-/* Additional recognized units: only sub-metric prefixes allowed. */
-/* Additional recognized units for which NO metric prefixes are allowed. */
-/* All additional recognized units. */
-/* Exclusive start states. */
-
-#line 91 "wcsulex.l"
-/* To get the prototype for fileno() from stdio.h when gcc is invoked with
- * -std=c89 (same as -ansi) or -std=c99 since we do not define YY_INPUT. */
-#define _POSIX_SOURCE 1
-
-#include <math.h>
-#include <setjmp.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "wcserr.h"
-#include "wcsmath.h"
-#include "wcsunits.h"
-
-#define YY_DECL int wcsulexe(const char unitstr[], int *func, double *scale, \
-                             double units[], struct wcserr **err)
-
-/* Used in preempting the call to exit() by yy_fatal_error(). */
-jmp_buf wcsulex_abort_jmp_env;
-#define exit(status) longjmp(wcsulex_abort_jmp_env, status)
-
-#line 6937 "wcsulex.c"
-
-#define INITIAL 0
-#define PAREN 1
-#define PREFIX 2
-#define UNITS 3
-#define EXPON 4
-#define FLUSH 5
-
-#ifndef YY_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 <unistd.h>
-#endif
-
-#ifndef YY_EXTRA_TYPE
-#define YY_EXTRA_TYPE void *
-#endif
-
-static int yy_init_globals (void );
-
-/* Accessor methods to globals.
-   These are made visible to non-reentrant scanners for convenience. */
-
-int wcsulexlex_destroy (void );
-
-int wcsulexget_debug (void );
-
-void wcsulexset_debug (int debug_flag  );
-
-YY_EXTRA_TYPE wcsulexget_extra (void );
-
-void wcsulexset_extra (YY_EXTRA_TYPE user_defined  );
-
-FILE *wcsulexget_in (void );
-
-void wcsulexset_in  (FILE * in_str  );
-
-FILE *wcsulexget_out (void );
-
-void wcsulexset_out  (FILE * out_str  );
-
-int wcsulexget_leng (void );
-
-char *wcsulexget_text (void );
-
-int wcsulexget_lineno (void );
-
-void wcsulexset_lineno (int line_number  );
-
-/* Macros after this point can all be overridden by user definitions in
- * section 1.
- */
-
-#ifndef YY_SKIP_YYWRAP
-#ifdef __cplusplus
-extern "C" int wcsulexwrap (void );
-#else
-extern int wcsulexwrap (void );
-#endif
-#endif
-
-    static void yyunput (int c,char *buf_ptr  );
-    
-#ifndef yytext_ptr
-static void yy_flex_strncpy (char *,yyconst char *,int );
-#endif
-
-#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * );
-#endif
-
-#ifndef YY_NO_INPUT
-
-#ifdef __cplusplus
-static int yyinput (void );
-#else
-static int input (void );
-#endif
-
-#endif
-
-/* Amount of stuff to slurp up with each read. */
-#ifndef YY_READ_BUF_SIZE
-#ifdef __ia64__
-/* On IA-64, the buffer size is 16k, not 8k */
-#define YY_READ_BUF_SIZE 16384
-#else
-#define YY_READ_BUF_SIZE 8192
-#endif /* __ia64__ */
-#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( wcsulextext, wcsulexleng, 1, wcsulexout )) {} } while (0)
-#endif
-
-/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
- * is returned in "result".
- */
-#ifndef YY_INPUT
-#define YY_INPUT(buf,result,max_size) \
-	errno=0; \
-	while ( (result = read( fileno(wcsulexin), (char *) buf, max_size )) < 0 ) \
-	{ \
-		if( errno != EINTR) \
-		{ \
-			YY_FATAL_ERROR( "input in flex scanner failed" ); \
-			break; \
-		} \
-		errno=0; \
-		clearerr(wcsulexin); \
-	}\
-\
-
-#endif
-
-/* No semi-colon after return; correct usage is to write "yyterminate();" -
- * we don't want an extra ';' after the "return" because that will cause
- * some compilers to complain about unreachable statements.
- */
-#ifndef yyterminate
-#define yyterminate() return YY_NULL
-#endif
-
-/* Number of entries by which start-condition stack grows. */
-#ifndef YY_START_STACK_INCR
-#define YY_START_STACK_INCR 25
-#endif
-
-/* Report a fatal error. */
-#ifndef YY_FATAL_ERROR
-#define YY_FATAL_ERROR(msg) yy_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 YY_DECL
-#define YY_DECL_IS_OURS 1
-
-extern int wcsulexlex (void);
-
-#define YY_DECL int wcsulexlex (void)
-#endif /* !YY_DECL */
-
-/* Code executed at the beginning of each rule, after wcsulextext and wcsulexleng
- * have been set up.
- */
-#ifndef YY_USER_ACTION
-#define YY_USER_ACTION
-#endif
-
-/* Code executed at the end of each rule. */
-#ifndef YY_BREAK
-#define YY_BREAK break;
-#endif
-
-#define YY_RULE_SETUP \
-	if ( wcsulexleng > 0 ) \
-		YY_CURRENT_BUFFER_LVALUE->yy_at_bol = \
-				(wcsulextext[wcsulexleng - 1] == '\n'); \
-	YY_USER_ACTION
-
-/** The main scanner function which does all the work.
- */
-YY_DECL
-{
-	register yy_state_type yy_current_state;
-	register char *yy_cp, *yy_bp;
-	register int yy_act;
-    
-#line 113 "wcsulex.l"
-
-	static const char *function = "wcsulexe";
-
-	int bracket  = 0;
-	int operator = 0;
-	int paren    = 0;
-	int status   = 0;
-	int func_r, i, j;
-	double dexp, expon, factor, factor_r, types[WCSUNITS_NTYPE];
-	YY_BUFFER_STATE buf;
-	void add(double *factor, double types[], double *expon, double *scale,
-	    double units[]);
-	int wcsulexlex_destroy(void);
-	
-	*func = 0;
-	for (i = 0; i < WCSUNITS_NTYPE; i++) {
-	  units[i] = 0.0;
-	  types[i] = 0.0;
-	}
-	expon  = 1.0;
-	factor = 1.0;
-	*scale = 1.0;
-	
-	wcsulex_scan_string(unitstr);
-	
-	/* Return here via longjmp() invoked by yy_fatal_error(). */
-	if (setjmp(wcsulex_abort_jmp_env)) {
-	  return wcserr_set(WCSERR_SET(UNITSERR_PARSER_ERROR),
-	    "Internal units parser error parsing '%s'", unitstr);
-	}
-	
-	BEGIN(INITIAL);
-	
-#ifdef DEBUG
-	fprintf(stderr, "\n%s ->\n", unitstr);
-#endif
-
-#line 7154 "wcsulex.c"
-
-	if ( !(yy_init) )
-		{
-		(yy_init) = 1;
-
-#ifdef YY_USER_INIT
-		YY_USER_INIT;
-#endif
-
-		if ( ! (yy_start) )
-			(yy_start) = 1;	/* first start state */
-
-		if ( ! wcsulexin )
-			wcsulexin = stdin;
-
-		if ( ! wcsulexout )
-			wcsulexout = stdout;
-
-		if ( ! YY_CURRENT_BUFFER ) {
-			wcsulexensure_buffer_stack ();
-			YY_CURRENT_BUFFER_LVALUE =
-				wcsulex_create_buffer(wcsulexin,YY_BUF_SIZE );
-		}
-
-		wcsulex_load_buffer_state( );
-		}
-
-	while ( 1 )		/* loops until end-of-file is reached */
-		{
-		(yy_more_len) = 0;
-		if ( (yy_more_flag) )
-			{
-			(yy_more_len) = (yy_c_buf_p) - (yytext_ptr);
-			(yy_more_flag) = 0;
-			}
-		yy_cp = (yy_c_buf_p);
-
-		/* Support of wcsulextext. */
-		*yy_cp = (yy_hold_char);
-
-		/* yy_bp points to the position in yy_ch_buf of the start of
-		 * the current run.
-		 */
-		yy_bp = yy_cp;
-
-		yy_current_state = (yy_start);
-		yy_current_state += YY_AT_BOL();
-yy_match:
-		while ( (yy_current_state = yy_nxt[yy_current_state][ YY_SC_TO_UI(*yy_cp) ]) > 0 )
-			{
-			if ( yy_accept[yy_current_state] )
-				{
-				(yy_last_accepting_state) = yy_current_state;
-				(yy_last_accepting_cpos) = yy_cp;
-				}
-
-			++yy_cp;
-			}
-
-		yy_current_state = -yy_current_state;
-
-yy_find_action:
-		yy_act = yy_accept[yy_current_state];
-
-		YY_DO_BEFORE_ACTION;
-
-do_action:	/* This label is used only to access EOF actions. */
-
-		switch ( yy_act )
-	{ /* beginning of action switch */
-			case 0: /* must back up */
-			/* undo the effects of YY_DO_BEFORE_ACTION */
-			*yy_cp = (yy_hold_char);
-			yy_cp = (yy_last_accepting_cpos) + 1;
-			yy_current_state = (yy_last_accepting_state);
-			goto yy_find_action;
-
-case 1:
-YY_RULE_SETUP
-#line 150 "wcsulex.l"
-{
-	  /* Pretend initial whitespace doesn't exist. */
-	  yy_set_bol(1);
-	}
-	YY_BREAK
-case 2:
-YY_RULE_SETUP
-#line 155 "wcsulex.l"
-{
-	  if (bracket++) {
-	    BEGIN(FLUSH);
-	  } else {
-	    yy_set_bol(1);
-	  }
-	}
-	YY_BREAK
-case 3:
-YY_RULE_SETUP
-#line 163 "wcsulex.l"
-{
-	  status = wcserr_set(WCSERR_SET(UNITSERR_BAD_NUM_MULTIPLIER),
-	    "Invalid exponent in '%s'", unitstr);
-	  BEGIN(FLUSH);
-	}
-	YY_BREAK
-case 4:
-YY_RULE_SETUP
-#line 169 "wcsulex.l"
-{
-	  factor = 10.0;
-	  BEGIN(EXPON);
-	}
-	YY_BREAK
-case 5:
-YY_RULE_SETUP
-#line 174 "wcsulex.l"
-{
-	  *func = 1;
-	  unput('(');
-	  BEGIN(PAREN);
-	}
-	YY_BREAK
-case 6:
-YY_RULE_SETUP
-#line 180 "wcsulex.l"
-{
-	  *func = 2;
-	  unput('(');
-	  BEGIN(PAREN);
-	}
-	YY_BREAK
-case 7:
-YY_RULE_SETUP
-#line 186 "wcsulex.l"
-{
-	  *func = 3;
-	  unput('(');
-	  BEGIN(PAREN);
-	}
-	YY_BREAK
-case 8:
-YY_RULE_SETUP
-#line 192 "wcsulex.l"
-{
-	  /* Leading binary multiply. */
-	  status = wcserr_set(WCSERR_SET(UNITSERR_DANGLING_BINOP),
-	    "Dangling binary operator in '%s'", unitstr);
-	  BEGIN(FLUSH);
-	}
-	YY_BREAK
-case 9:
-YY_RULE_SETUP
-#line 199 "wcsulex.l"
-/* Discard whitespace in INITIAL context. */
-	YY_BREAK
-case 10:
-YY_RULE_SETUP
-#line 201 "wcsulex.l"
-{
-	  expon /= 2.0;
-	  unput('(');
-	  BEGIN(PAREN);
-	}
-	YY_BREAK
-case 11:
-YY_RULE_SETUP
-#line 207 "wcsulex.l"
-{
-	  /* Gather terms in parentheses. */
-	  yyless(0);
-	  BEGIN(PAREN);
-	}
-	YY_BREAK
-case 12:
-YY_RULE_SETUP
-#line 213 "wcsulex.l"
-{
-	  if (operator++) {
-	    BEGIN(FLUSH);
-	  }
-	}
-	YY_BREAK
-case 13:
-#line 220 "wcsulex.l"
-case 14:
-YY_RULE_SETUP
-#line 220 "wcsulex.l"
-{
-	  if (operator++) {
-	    BEGIN(FLUSH);
-	  } else {
-	    expon *= -1.0;
-	  }
-	}
-	YY_BREAK
-case 15:
-YY_RULE_SETUP
-#line 228 "wcsulex.l"
-{
-	  operator = 0;
-	  yyless(0);
-	  BEGIN(UNITS);
-	}
-	YY_BREAK
-case 16:
-#line 235 "wcsulex.l"
-case 17:
-#line 236 "wcsulex.l"
-case 18:
-YY_RULE_SETUP
-#line 236 "wcsulex.l"
-{
-	  operator = 0;
-	  yyless(0);
-	  BEGIN(PREFIX);
-	}
-	YY_BREAK
-case 19:
-YY_RULE_SETUP
-#line 242 "wcsulex.l"
-{
-	  bracket = !bracket;
-	  BEGIN(FLUSH);
-	}
-	YY_BREAK
-case 20:
-YY_RULE_SETUP
-#line 247 "wcsulex.l"
-{
-	  status = wcserr_set(WCSERR_SET(UNITSERR_BAD_INITIAL_SYMBOL),
-	    "Invalid symbol in INITIAL context in '%s'", unitstr);
-	  BEGIN(FLUSH);
-	}
-	YY_BREAK
-case 21:
-YY_RULE_SETUP
-#line 253 "wcsulex.l"
-{
-	  paren++;
-	  operator = 0;
-	  yymore();
-	}
-	YY_BREAK
-case 22:
-YY_RULE_SETUP
-#line 259 "wcsulex.l"
-{
-	  paren--;
-	  if (paren) {
-	    /* Not balanced yet. */
-	    yymore();
-	
-	  } else {
-	    /* Balanced; strip off the outer parentheses and recurse. */
-	    wcsulextext[wcsulexleng-1] = '\0';
-	
-	    buf = YY_CURRENT_BUFFER;
-	    status = wcsulexe(wcsulextext+1, &func_r, &factor_r, types, err);
-	    wcsulex_switch_to_buffer(buf);
-	
-	    if (func_r) {
-	      status = wcserr_set(WCSERR_SET(UNITSERR_FUNCTION_CONTEXT),
-	        "Function in invalid context in '%s'", unitstr);
-	    }
-	
-	    if (status) {
-	      BEGIN(FLUSH);
-	    } else {
-	      factor *= factor_r;
-	      BEGIN(EXPON);
-	    }
-	  }
-	}
-	YY_BREAK
-case 23:
-/* rule 23 can match eol */
-YY_RULE_SETUP
-#line 287 "wcsulex.l"
-{
-	  yymore();
-	}
-	YY_BREAK
-case 24:
-YY_RULE_SETUP
-#line 291 "wcsulex.l"
-{
-	  factor = 1e-1;
-	  BEGIN(UNITS);
-	}
-	YY_BREAK
-case 25:
-YY_RULE_SETUP
-#line 296 "wcsulex.l"
-{
-	  factor = 1e-2;
-	  BEGIN(UNITS);
-	}
-	YY_BREAK
-case 26:
-YY_RULE_SETUP
-#line 301 "wcsulex.l"
-{
-	  factor = 1e-3;
-	  BEGIN(UNITS);
-	}
-	YY_BREAK
-case 27:
-YY_RULE_SETUP
-#line 306 "wcsulex.l"
-{
-	  factor = 1e-6;
-	  BEGIN(UNITS);
-	}
-	YY_BREAK
-case 28:
-YY_RULE_SETUP
-#line 311 "wcsulex.l"
-{
-	  factor = 1e-9;
-	  BEGIN(UNITS);
-	}
-	YY_BREAK
-case 29:
-YY_RULE_SETUP
-#line 316 "wcsulex.l"
-{
-	  factor = 1e-12;
-	  BEGIN(UNITS);
-	}
-	YY_BREAK
-case 30:
-YY_RULE_SETUP
-#line 321 "wcsulex.l"
-{
-	  factor = 1e-15;
-	  BEGIN(UNITS);
-	}
-	YY_BREAK
-case 31:
-YY_RULE_SETUP
-#line 326 "wcsulex.l"
-{
-	  factor = 1e-18;
-	  BEGIN(UNITS);
-	}
-	YY_BREAK
-case 32:
-YY_RULE_SETUP
-#line 331 "wcsulex.l"
-{
-	  factor = 1e-21;
-	  BEGIN(UNITS);
-	}
-	YY_BREAK
-case 33:
-YY_RULE_SETUP
-#line 336 "wcsulex.l"
-{
-	  factor = 1e-24;
-	  BEGIN(UNITS);
-	}
-	YY_BREAK
-case 34:
-YY_RULE_SETUP
-#line 341 "wcsulex.l"
-{
-	  factor = 1e+1;
-	  BEGIN(UNITS);
-	}
-	YY_BREAK
-case 35:
-YY_RULE_SETUP
-#line 346 "wcsulex.l"
-{
-	  factor = 1e+2;
-	  BEGIN(UNITS);
-	}
-	YY_BREAK
-case 36:
-YY_RULE_SETUP
-#line 351 "wcsulex.l"
-{
-	  factor = 1e+3;
-	  BEGIN(UNITS);
-	}
-	YY_BREAK
-case 37:
-YY_RULE_SETUP
-#line 356 "wcsulex.l"
-{
-	  factor = 1e+6;
-	  BEGIN(UNITS);
-	}
-	YY_BREAK
-case 38:
-YY_RULE_SETUP
-#line 361 "wcsulex.l"
-{
-	  factor = 1e+9;
-	  BEGIN(UNITS);
-	}
-	YY_BREAK
-case 39:
-YY_RULE_SETUP
-#line 366 "wcsulex.l"
-{
-	  factor = 1e+12;
-	  BEGIN(UNITS);
-	}
-	YY_BREAK
-case 40:
-YY_RULE_SETUP
-#line 371 "wcsulex.l"
-{
-	  factor = 1e+15;
-	  BEGIN(UNITS);
-	}
-	YY_BREAK
-case 41:
-YY_RULE_SETUP
-#line 376 "wcsulex.l"
-{
-	  factor = 1e+18;
-	  BEGIN(UNITS);
-	}
-	YY_BREAK
-case 42:
-YY_RULE_SETUP
-#line 381 "wcsulex.l"
-{
-	  factor = 1e+21;
-	  BEGIN(UNITS);
-	}
-	YY_BREAK
-case 43:
-YY_RULE_SETUP
-#line 386 "wcsulex.l"
-{
-	  factor = 1e+24;
-	  BEGIN(UNITS);
-	}
-	YY_BREAK
-case 44:
-YY_RULE_SETUP
-#line 391 "wcsulex.l"
-{
-	  /* Internal parser error. */
-	  status = wcserr_set(WCSERR_SET(UNITSERR_PARSER_ERROR),
-	    "Internal units parser error parsing '%s'", unitstr);
-	  BEGIN(FLUSH);
-	}
-	YY_BREAK
-case 45:
-YY_RULE_SETUP
-#line 398 "wcsulex.l"
-{
-	  /* Ampere. */
-	  types[WCSUNITS_CHARGE] += 1.0;
-	  types[WCSUNITS_TIME]   -= 1.0;
-	  BEGIN(EXPON);
-	}
-	YY_BREAK
-case 46:
-YY_RULE_SETUP
-#line 405 "wcsulex.l"
-{
-	  /* Year (annum). */
-	  factor *= 31557600.0;
-	  types[WCSUNITS_TIME] += 1.0;
-	  BEGIN(EXPON);
-	}
-	YY_BREAK
-case 47:
-YY_RULE_SETUP
-#line 412 "wcsulex.l"
-{
-	  /* Analogue-to-digital converter units. */
-	  types[WCSUNITS_COUNT] += 1.0;
-	  BEGIN(EXPON);
-	}
-	YY_BREAK
-case 48:
-YY_RULE_SETUP
-#line 418 "wcsulex.l"
-{
-	  /* Angstrom. */
-	  factor *= 1e-10;
-	  types[WCSUNITS_LENGTH] += 1.0;
-	  BEGIN(EXPON);
-	}
-	YY_BREAK
-case 49:
-YY_RULE_SETUP
-#line 425 "wcsulex.l"
-{
-	  /* Minute of arc. */
-	  factor /= 60.0;
-	  types[WCSUNITS_PLANE_ANGLE] += 1.0;
-	  BEGIN(EXPON);
-	}
-	YY_BREAK
-case 50:
-YY_RULE_SETUP
-#line 432 "wcsulex.l"
-{
-	  /* Second of arc. */
-	  factor /= 3600.0;
-	  types[WCSUNITS_PLANE_ANGLE] += 1.0;
-	  BEGIN(EXPON);
-	}
-	YY_BREAK
-case 51:
-YY_RULE_SETUP
-#line 439 "wcsulex.l"
-{
-	  /* Astronomical unit. */
-	  factor *= 1.49598e+11;
-	  types[WCSUNITS_LENGTH] += 1.0;
-	  BEGIN(EXPON);
-	}
-	YY_BREAK
-case 52:
-YY_RULE_SETUP
-#line 446 "wcsulex.l"
-{
-	  /* Barn. */
-	  factor *= 1e-28;
-	  types[WCSUNITS_LENGTH] += 2.0;
-	  BEGIN(EXPON);
-	}
-	YY_BREAK
-case 53:
-YY_RULE_SETUP
-#line 453 "wcsulex.l"
-{
-	  /* Beam, as in Jy/beam. */
-	  types[WCSUNITS_BEAM] += 1.0;
-	  BEGIN(EXPON);
-	}
-	YY_BREAK
-case 54:
-YY_RULE_SETUP
-#line 459 "wcsulex.l"
-{
-	  /* Bin (e.g. histogram). */
-	  types[WCSUNITS_BIN] += 1.0;
-	  BEGIN(EXPON);
-	}
-	YY_BREAK
-case 55:
-YY_RULE_SETUP
-#line 465 "wcsulex.l"
-{
-	  /* Bit. */
-	  types[WCSUNITS_BIT] += 1.0;
-	  BEGIN(EXPON);
-	}
-	YY_BREAK
-case 56:
-YY_RULE_SETUP
-#line 471 "wcsulex.l"
-{
-	  /* Byte. */
-	  factor *= 8.0;
-	  types[WCSUNITS_BIT] += 1.0;
-	  BEGIN(EXPON);
-	}
-	YY_BREAK
-case 57:
-YY_RULE_SETUP
-#line 478 "wcsulex.l"
-{
-	  /* Coulomb. */
-	  types[WCSUNITS_CHARGE] += 1.0;
-	  BEGIN(EXPON);
-	}
-	YY_BREAK
-case 58:
-YY_RULE_SETUP
-#line 484 "wcsulex.l"
-{
-	  /* Candela. */
-	  types[WCSUNITS_LUMINTEN] += 1.0;
-	  BEGIN(EXPON);
-	}
-	YY_BREAK
-case 59:
-YY_RULE_SETUP
-#line 490 "wcsulex.l"
-{
-	  /* Channel. */
-	  types[WCSUNITS_BIN] += 1.0;
-	  BEGIN(EXPON);
-	}
-	YY_BREAK
-case 60:
-YY_RULE_SETUP
-#line 496 "wcsulex.l"
-{
-	  /* Count. */
-	  types[WCSUNITS_COUNT] += 1.0;
-	  BEGIN(EXPON);
-	}
-	YY_BREAK
-case 61:
-YY_RULE_SETUP
-#line 502 "wcsulex.l"
-{
-	  /* Debye. */
-	  factor *= 1e-29 / 3.0;
-	  types[WCSUNITS_CHARGE] += 1.0;
-	  types[WCSUNITS_LENGTH] += 1.0;
-	  BEGIN(EXPON);
-	}
-	YY_BREAK
-case 62:
-YY_RULE_SETUP
-#line 510 "wcsulex.l"
-{
-	  /* Day. */
-	  factor *= 86400.0;
-	  types[WCSUNITS_TIME] += 1.0;
-	  BEGIN(EXPON);
-	}
-	YY_BREAK
-case 63:
-YY_RULE_SETUP
-#line 517 "wcsulex.l"
-{
-	  /* Degree. */
-	  types[WCSUNITS_PLANE_ANGLE] += 1.0;
-	  BEGIN(EXPON);
-	}
-	YY_BREAK
-case 64:
-YY_RULE_SETUP
-#line 523 "wcsulex.l"
-{
-	  /* Erg. */
-	  factor *= 1e-7;
-	  types[WCSUNITS_MASS]   += 1.0;
-	  types[WCSUNITS_LENGTH] += 2.0;
-	  types[WCSUNITS_TIME]   -= 2.0;
-	  BEGIN(EXPON);
-	}
-	YY_BREAK
-case 65:
-YY_RULE_SETUP
-#line 532 "wcsulex.l"
-{
-	  /* Electron volt. */
-	  factor *= 1.6021765e-19;
-	  types[WCSUNITS_MASS]   += 1.0;
-	  types[WCSUNITS_LENGTH] += 2.0;
-	  types[WCSUNITS_TIME]   -= 2.0;
-	  BEGIN(EXPON);
-	}
-	YY_BREAK
-case 66:
-YY_RULE_SETUP
-#line 541 "wcsulex.l"
-{
-	  /* Farad. */
-	  types[WCSUNITS_MASS]   -= 1.0;
-	  types[WCSUNITS_LENGTH] -= 2.0;
-	  types[WCSUNITS_TIME]   += 3.0;
-	  types[WCSUNITS_CHARGE] += 2.0;
-	  BEGIN(EXPON);
-	}
-	YY_BREAK
-case 67:
-YY_RULE_SETUP
-#line 550 "wcsulex.l"
-{
-	  /* Gauss. */
-	  factor *= 1e-4;
-	  types[WCSUNITS_MASS]   += 1.0;
-	  types[WCSUNITS_TIME]   += 1.0;
-	  types[WCSUNITS_CHARGE] -= 1.0;
-	  BEGIN(EXPON);
-	}
-	YY_BREAK
-case 68:
-YY_RULE_SETUP
-#line 559 "wcsulex.l"
-{
-	  /* Gram. */
-	  factor *= 1e-3;
-	  types[WCSUNITS_MASS] += 1.0;
-	  BEGIN(EXPON);
-	}
-	YY_BREAK
-case 69:
-YY_RULE_SETUP
-#line 566 "wcsulex.l"
-{
-	  /* Henry. */
-	  types[WCSUNITS_MASS]   += 1.0;
-	  types[WCSUNITS_LENGTH] += 2.0;
-	  types[WCSUNITS_TIME]   += 2.0;
-	  types[WCSUNITS_CHARGE] -= 2.0;
-	  BEGIN(EXPON);
-	}
-	YY_BREAK
-case 70:
-YY_RULE_SETUP
-#line 575 "wcsulex.l"
-{
-	  /* Hour. */
-	  factor *= 3600.0;
-	  types[WCSUNITS_TIME] += 1.0;
-	  BEGIN(EXPON);
-	}
-	YY_BREAK
-case 71:
-YY_RULE_SETUP
-#line 582 "wcsulex.l"
-{
-	  /* Hertz. */
-	  types[WCSUNITS_TIME] -= 1.0;
-	  BEGIN(EXPON);
-	}
-	YY_BREAK
-case 72:
-YY_RULE_SETUP
-#line 588 "wcsulex.l"
-{
-	  /* Joule. */
-	  types[WCSUNITS_MASS]   += 1.0;
-	  types[WCSUNITS_LENGTH] += 2.0;
-	  types[WCSUNITS_TIME]   -= 2.0;
-	  BEGIN(EXPON);
-	}
-	YY_BREAK
-case 73:
-YY_RULE_SETUP
-#line 596 "wcsulex.l"
-{
-	  /* Jansky. */
-	  factor *= 1e-26;
-	  types[WCSUNITS_MASS] += 1.0;
-	  types[WCSUNITS_TIME] -= 2.0;
-	  BEGIN(EXPON);
-	}
-	YY_BREAK
-case 74:
-YY_RULE_SETUP
-#line 604 "wcsulex.l"
-{
-	  /* Kelvin. */
-	  types[WCSUNITS_TEMPERATURE] += 1.0;
-	  BEGIN(EXPON);
-	}
-	YY_BREAK
-case 75:
-YY_RULE_SETUP
-#line 610 "wcsulex.l"
-{
-	  /* Lumen. */
-	  types[WCSUNITS_LUMINTEN]    += 1.0;
-	  types[WCSUNITS_SOLID_ANGLE] += 1.0;
-	  BEGIN(EXPON);
-	}
-	YY_BREAK
-case 76:
-YY_RULE_SETUP
-#line 617 "wcsulex.l"
-{
-	  /* Lux. */
-	  types[WCSUNITS_LUMINTEN]    += 1.0;
-	  types[WCSUNITS_SOLID_ANGLE] += 1.0;
-	  types[WCSUNITS_LENGTH]      -= 2.0;
-	  BEGIN(EXPON);
-	}
-	YY_BREAK
-case 77:
-YY_RULE_SETUP
-#line 625 "wcsulex.l"
-{
-	  /* Light year. */
-	  factor *= 2.99792458e8 * 31557600.0;
-	  types[WCSUNITS_LENGTH] += 1.0;
-	  BEGIN(EXPON);
-	}
-	YY_BREAK
-case 78:
-YY_RULE_SETUP
-#line 632 "wcsulex.l"
-{
-	  /* Metre. */
-	  types[WCSUNITS_LENGTH] += 1.0;
-	  BEGIN(EXPON);
-	}
-	YY_BREAK
-case 79:
-YY_RULE_SETUP
-#line 638 "wcsulex.l"
-{
-	  /* Stellar magnitude. */
-	  types[WCSUNITS_MAGNITUDE] += 1.0;
-	  BEGIN(EXPON);
-	}
-	YY_BREAK
-case 80:
-YY_RULE_SETUP
-#line 644 "wcsulex.l"
-{
-	  /* Milli-arcsec. */
-	  factor /= 3600e+3;
-	  types[WCSUNITS_PLANE_ANGLE] += 1.0;
-	  BEGIN(EXPON);
-	}
-	YY_BREAK
-case 81:
-YY_RULE_SETUP
-#line 651 "wcsulex.l"
-{
-	  /* Minute. */
-	  factor *= 60.0;
-	  types[WCSUNITS_TIME] += 1.0;
-	  BEGIN(EXPON);
-	}
-	YY_BREAK
-case 82:
-YY_RULE_SETUP
-#line 658 "wcsulex.l"
-{
-	  /* Mole. */
-	  types[WCSUNITS_MOLE] += 1.0;
-	  BEGIN(EXPON);
-	}
-	YY_BREAK
-case 83:
-YY_RULE_SETUP
-#line 664 "wcsulex.l"
-{
-	  /* Newton. */
-	  types[WCSUNITS_MASS]   += 1.0;
-	  types[WCSUNITS_LENGTH] += 1.0;
-	  types[WCSUNITS_TIME]   -= 2.0;
-	  BEGIN(EXPON);
-	}
-	YY_BREAK
-case 84:
-YY_RULE_SETUP
-#line 672 "wcsulex.l"
-{
-	  /* Ohm. */
-	  types[WCSUNITS_MASS]   += 1.0;
-	  types[WCSUNITS_LENGTH] += 2.0;
-	  types[WCSUNITS_TIME]   -= 1.0;
-	  types[WCSUNITS_CHARGE] -= 2.0;
-	  BEGIN(EXPON);
-	}
-	YY_BREAK
-case 85:
-YY_RULE_SETUP
-#line 681 "wcsulex.l"
-{
-	  /* Pascal. */
-	  types[WCSUNITS_MASS]   += 1.0;
-	  types[WCSUNITS_LENGTH] -= 1.0;
-	  types[WCSUNITS_TIME]   -= 2.0;
-	  BEGIN(EXPON);
-	}
-	YY_BREAK
-case 86:
-YY_RULE_SETUP
-#line 689 "wcsulex.l"
-{
-	  /* Parsec. */
-	  factor *= 3.0857e16;
-	  types[WCSUNITS_LENGTH] += 1.0;
-	  BEGIN(EXPON);
-	}
-	YY_BREAK
-case 87:
-YY_RULE_SETUP
-#line 696 "wcsulex.l"
-{
-	  /* Photon. */
-	  types[WCSUNITS_COUNT] += 1.0;
-	  BEGIN(EXPON);
-	}
-	YY_BREAK
-case 88:
-YY_RULE_SETUP
-#line 702 "wcsulex.l"
-{
-	  /* Pixel. */
-	  types[WCSUNITS_PIXEL] += 1.0;
-	  BEGIN(EXPON);
-	}
-	YY_BREAK
-case 89:
-YY_RULE_SETUP
-#line 708 "wcsulex.l"
-{
-	  /* Rayleigh. */
-	  factor *= 1e10 / (4.0 * PI);
-	  types[WCSUNITS_LENGTH]      -= 2.0;
-	  types[WCSUNITS_TIME]        -= 1.0;
-	  types[WCSUNITS_SOLID_ANGLE] -= 1.0;
-	  BEGIN(EXPON);
-	}
-	YY_BREAK
-case 90:
-YY_RULE_SETUP
-#line 717 "wcsulex.l"
-{
-	  /* Radian. */
-	  factor *= 180.0 / PI;
-	  types[WCSUNITS_PLANE_ANGLE] += 1.0;
-	  BEGIN(EXPON);
-	}
-	YY_BREAK
-case 91:
-YY_RULE_SETUP
-#line 724 "wcsulex.l"
-{
-	  /* Rydberg. */
-	  factor *= 13.605692 * 1.6021765e-19;
-	  types[WCSUNITS_MASS]   += 1.0;
-	  types[WCSUNITS_LENGTH] += 2.0;
-	  types[WCSUNITS_TIME]   -= 2.0;
-	  BEGIN(EXPON);
-	}
-	YY_BREAK
-case 92:
-YY_RULE_SETUP
-#line 733 "wcsulex.l"
-{
-	  /* Siemen. */
-	  types[WCSUNITS_MASS]   -= 1.0;
-	  types[WCSUNITS_LENGTH] -= 2.0;
-	  types[WCSUNITS_TIME]   += 1.0;
-	  types[WCSUNITS_CHARGE] += 2.0;
-	  BEGIN(EXPON);
-	}
-	YY_BREAK
-case 93:
-YY_RULE_SETUP
-#line 742 "wcsulex.l"
-{
-	  /* Second. */
-	  types[WCSUNITS_TIME] += 1.0;
-	  BEGIN(EXPON);
-	}
-	YY_BREAK
-case 94:
-YY_RULE_SETUP
-#line 748 "wcsulex.l"
-{
-	  /* Solar luminosity. */
-	  factor *= 3.8268e26;
-	  types[WCSUNITS_MASS]   += 1.0;
-	  types[WCSUNITS_LENGTH] += 2.0;
-	  types[WCSUNITS_TIME]   -= 3.0;
-	  BEGIN(EXPON);
-	}
-	YY_BREAK
-case 95:
-YY_RULE_SETUP
-#line 757 "wcsulex.l"
-{
-	  /* Solar mass. */
-	  factor *= 1.9891e30;
-	  types[WCSUNITS_MASS] += 1.0;
-	  BEGIN(EXPON);
-	}
-	YY_BREAK
-case 96:
-YY_RULE_SETUP
-#line 764 "wcsulex.l"
-{
-	  /* Solar radius. */
-	  factor *= 6.9599e8;
-	  types[WCSUNITS_LENGTH] += 1.0;
-	  BEGIN(EXPON);
-	}
-	YY_BREAK
-case 97:
-YY_RULE_SETUP
-#line 771 "wcsulex.l"
-{
-	  /* Steradian. */
-	  types[WCSUNITS_SOLID_ANGLE] += 1.0;
-	  BEGIN(EXPON);
-	}
-	YY_BREAK
-case 98:
-YY_RULE_SETUP
-#line 777 "wcsulex.l"
-{
-	  /* Sun (with respect to). */
-	  types[WCSUNITS_SOLRATIO] += 1.0;
-	  BEGIN(EXPON);
-	}
-	YY_BREAK
-case 99:
-YY_RULE_SETUP
-#line 783 "wcsulex.l"
-{
-	  /* Tesla. */
-	  types[WCSUNITS_MASS]   += 1.0;
-	  types[WCSUNITS_TIME]   += 1.0;
-	  types[WCSUNITS_CHARGE] -= 1.0;
-	  BEGIN(EXPON);
-	}
-	YY_BREAK
-case 100:
-YY_RULE_SETUP
-#line 791 "wcsulex.l"
-{
-	  /* Unified atomic mass unit. */
-	  factor *= 1.6605387e-27;
-	  types[WCSUNITS_MASS] += 1.0;
-	  BEGIN(EXPON);
-	}
-	YY_BREAK
-case 101:
-YY_RULE_SETUP
-#line 798 "wcsulex.l"
-{
-	  /* Volt. */
-	  types[WCSUNITS_MASS]   += 1.0;
-	  types[WCSUNITS_LENGTH] += 1.0;
-	  types[WCSUNITS_TIME]   -= 2.0;
-	  types[WCSUNITS_CHARGE] -= 1.0;
-	  BEGIN(EXPON);
-	}
-	YY_BREAK
-case 102:
-YY_RULE_SETUP
-#line 807 "wcsulex.l"
-{
-	  /* Voxel. */
-	  types[WCSUNITS_VOXEL] += 1.0;
-	  BEGIN(EXPON);
-	}
-	YY_BREAK
-case 103:
-YY_RULE_SETUP
-#line 813 "wcsulex.l"
-{
-	  /* Watt. */
-	  types[WCSUNITS_MASS]   += 1.0;
-	  types[WCSUNITS_LENGTH] += 2.0;
-	  types[WCSUNITS_TIME]   -= 3.0;
-	  BEGIN(EXPON);
-	}
-	YY_BREAK
-case 104:
-YY_RULE_SETUP
-#line 821 "wcsulex.l"
-{
-	  /* Weber. */
-	  types[WCSUNITS_MASS]   += 1.0;
-	  types[WCSUNITS_LENGTH] += 2.0;
-	  types[WCSUNITS_TIME]   += 1.0;
-	  types[WCSUNITS_CHARGE] -= 1.0;
-	  BEGIN(EXPON);
-	}
-	YY_BREAK
-case 105:
-YY_RULE_SETUP
-#line 830 "wcsulex.l"
-{
-	  /* Internal parser error. */
-	  status = wcserr_set(WCSERR_SET(UNITSERR_PARSER_ERROR),
-	    "Internal units parser error parsing '%s'", unitstr);
-	  BEGIN(FLUSH);
-	}
-	YY_BREAK
-case 106:
-YY_RULE_SETUP
-#line 837 "wcsulex.l"
-{
-	  /* Exponentiation. */
-	  if (operator++) {
-	    BEGIN(FLUSH);
-	  }
-	}
-	YY_BREAK
-case 107:
-YY_RULE_SETUP
-#line 844 "wcsulex.l"
-{
-	  sscanf(wcsulextext, " %d", &i);
-	  expon *= (double)i;
-	  add(&factor, types, &expon, scale, units);
-	  operator = 0;
-	  BEGIN(INITIAL);
-	}
-	YY_BREAK
-case 108:
-YY_RULE_SETUP
-#line 852 "wcsulex.l"
-{
-	  sscanf(wcsulextext, " (%d)", &i);
-	  expon *= (double)i;
-	  add(&factor, types, &expon, scale, units);
-	  operator = 0;
-	  BEGIN(INITIAL);
-	}
-	YY_BREAK
-case 109:
-YY_RULE_SETUP
-#line 860 "wcsulex.l"
-{
-	  sscanf(wcsulextext, " (%d/%d)", &i, &j);
-	  expon *= (double)i / (double)j;
-	  add(&factor, types, &expon, scale, units);
-	  operator = 0;
-	  BEGIN(INITIAL);
-	}
-	YY_BREAK
-case 110:
-YY_RULE_SETUP
-#line 868 "wcsulex.l"
-{
-	  sscanf(wcsulextext, " (%lf)", &dexp);
-	  expon *= dexp;
-	  add(&factor, types, &expon, scale, units);
-	  operator = 0;
-	  BEGIN(INITIAL);
-	}
-	YY_BREAK
-case 111:
-YY_RULE_SETUP
-#line 876 "wcsulex.l"
-{
-	  /* Multiply. */
-	  if (operator++) {
-	    BEGIN(FLUSH);
-	  } else {
-	    add(&factor, types, &expon, scale, units);
-	    BEGIN(INITIAL);
-	  }
-	}
-	YY_BREAK
-case 112:
-YY_RULE_SETUP
-#line 886 "wcsulex.l"
-{
-	  /* Multiply. */
-	  if (operator) {
-	    BEGIN(FLUSH);
-	  } else {
-	    add(&factor, types, &expon, scale, units);
-	    unput('(');
-	    BEGIN(INITIAL);
-	  }
-	}
-	YY_BREAK
-case 113:
-YY_RULE_SETUP
-#line 897 "wcsulex.l"
-{
-	  /* Multiply. */
-	  if (operator) {
-	    BEGIN(FLUSH);
-	  } else {
-	    add(&factor, types, &expon, scale, units);
-	    BEGIN(INITIAL);
-	  }
-	}
-	YY_BREAK
-case 114:
-YY_RULE_SETUP
-#line 907 "wcsulex.l"
-{
-	  /* Divide. */
-	  if (operator++) {
-	    BEGIN(FLUSH);
-	  } else {
-	    add(&factor, types, &expon, scale, units);
-	    expon = -1.0;
-	    BEGIN(INITIAL);
-	  }
-	}
-	YY_BREAK
-case 115:
-YY_RULE_SETUP
-#line 918 "wcsulex.l"
-{
-	  add(&factor, types, &expon, scale, units);
-	  bracket = !bracket;
-	  BEGIN(FLUSH);
-	}
-	YY_BREAK
-case 116:
-YY_RULE_SETUP
-#line 924 "wcsulex.l"
-{
-	  status = wcserr_set(WCSERR_SET(UNITSERR_BAD_EXPON_SYMBOL),
-	    "Invalid symbol in EXPON context in '%s'", unitstr);
-	  BEGIN(FLUSH);
-	}
-	YY_BREAK
-case 117:
-YY_RULE_SETUP
-#line 930 "wcsulex.l"
-{
-	  /* Discard any remaining input. */
-	}
-	YY_BREAK
-case YY_STATE_EOF(INITIAL):
-case YY_STATE_EOF(PAREN):
-case YY_STATE_EOF(PREFIX):
-case YY_STATE_EOF(UNITS):
-case YY_STATE_EOF(EXPON):
-case YY_STATE_EOF(FLUSH):
-#line 934 "wcsulex.l"
-{
-	  /* End-of-string. */
-	  if (YY_START == EXPON) {
-	    add(&factor, types, &expon, scale, units);
-	  }
-	
-	  wcsulexlex_destroy();
-	
-	  if (bracket) {
-	    status = wcserr_set(WCSERR_SET(UNITSERR_UNBAL_BRACKET),
-	      "Unbalanced bracket in '%s'", unitstr);
-	  } else if (paren) {
-	    status = wcserr_set(WCSERR_SET(UNITSERR_UNBAL_PAREN),
-	      "Unbalanced parenthesis in '%s'", unitstr);
-	  } else if (operator == 1) {
-	    status = wcserr_set(WCSERR_SET(UNITSERR_DANGLING_BINOP),
-	      "Dangling binary operator in '%s'", unitstr);
-	  } else if (operator) {
-	    status = wcserr_set(WCSERR_SET(UNITSERR_CONSEC_BINOPS),
-	      "Consecutive binary operators in '%s'", unitstr);
-#ifdef DEBUG
-	  } else {
-	    fprintf(stderr, "EOS\n");
-#endif
-	  }
-	
-	  if (status) {
-	    for (i = 0; i < WCSUNITS_NTYPE; i++) {
-	      units[i] = 0.0;
-	      *scale = 0.0;
-	    }
-	  }
-	
-	  return status;
-	}
-	YY_BREAK
-case 118:
-YY_RULE_SETUP
-#line 970 "wcsulex.l"
-ECHO;
-	YY_BREAK
-#line 8410 "wcsulex.c"
-
-	case YY_END_OF_BUFFER:
-		{
-		/* Amount of text matched not including the EOB char. */
-		int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;
-
-		/* Undo the effects of YY_DO_BEFORE_ACTION. */
-		*yy_cp = (yy_hold_char);
-		YY_RESTORE_YY_MORE_OFFSET
-
-		if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
-			{
-			/* We're scanning a new file or input source.  It's
-			 * possible that this happened because the user
-			 * just pointed wcsulexin at a new source and called
-			 * wcsulexlex().  If so, then we have to assure
-			 * consistency between YY_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.
-			 */
-			(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
-			YY_CURRENT_BUFFER_LVALUE->yy_input_file = wcsulexin;
-			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
-			}
-
-		/* Note that here we test for yy_c_buf_p "<=" to the position
-		 * of the first EOB in the buffer, since yy_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 ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
-			{ /* This was really a NUL. */
-			yy_state_type yy_next_state;
-
-			(yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;
-
-			yy_current_state = yy_get_previous_state(  );
-
-			/* Okay, we're now positioned to make the NUL
-			 * transition.  We couldn't have
-			 * yy_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).
-			 */
-
-			yy_next_state = yy_try_NUL_trans( yy_current_state );
-
-			yy_bp = (yytext_ptr) + YY_MORE_ADJ;
-
-			if ( yy_next_state )
-				{
-				/* Consume the NUL. */
-				yy_cp = ++(yy_c_buf_p);
-				yy_current_state = yy_next_state;
-				goto yy_match;
-				}
-
-			else
-				{
-				yy_cp = (yy_c_buf_p);
-				goto yy_find_action;
-				}
-			}
-
-		else switch ( yy_get_next_buffer(  ) )
-			{
-			case EOB_ACT_END_OF_FILE:
-				{
-				(yy_did_buffer_switch_on_eof) = 0;
-
-				if ( wcsulexwrap( ) )
-					{
-					/* Note: because we've taken care in
-					 * yy_get_next_buffer() to have set up
-					 * wcsulextext, we can now set up
-					 * yy_c_buf_p so that if some total
-					 * hoser (like flex itself) wants to
-					 * call the scanner after we return the
-					 * YY_NULL, it'll still work - another
-					 * YY_NULL will get returned.
-					 */
-					(yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;
-
-					yy_act = YY_STATE_EOF(YY_START);
-					goto do_action;
-					}
-
-				else
-					{
-					if ( ! (yy_did_buffer_switch_on_eof) )
-						YY_NEW_FILE;
-					}
-				break;
-				}
-
-			case EOB_ACT_CONTINUE_SCAN:
-				(yy_c_buf_p) =
-					(yytext_ptr) + yy_amount_of_matched_text;
-
-				yy_current_state = yy_get_previous_state(  );
-
-				yy_cp = (yy_c_buf_p);
-				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
-				goto yy_match;
-
-			case EOB_ACT_LAST_MATCH:
-				(yy_c_buf_p) =
-				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];
-
-				yy_current_state = yy_get_previous_state(  );
-
-				yy_cp = (yy_c_buf_p);
-				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
-				goto yy_find_action;
-			}
-		break;
-		}
-
-	default:
-		YY_FATAL_ERROR(
-			"fatal flex scanner internal error--no action found" );
-	} /* end of action switch */
-		} /* end of scanning one token */
-} /* end of wcsulexlex */
-
-/* yy_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 yy_get_next_buffer (void)
-{
-    	register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
-	register char *source = (yytext_ptr);
-	register int number_to_move, i;
-	int ret_val;
-
-	if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
-		YY_FATAL_ERROR(
-		"fatal flex scanner internal error--end of buffer missed" );
-
-	if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
-		{ /* Don't try to fill the buffer, so this is an EOF. */
-		if ( (yy_c_buf_p) - (yytext_ptr) - YY_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) ((yy_c_buf_p) - (yytext_ptr)) - 1;
-
-	for ( i = 0; i < number_to_move; ++i )
-		*(dest++) = *(source++);
-
-	if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
-		/* don't do the read, it's not guaranteed to return an EOF,
-		 * just force an EOF
-		 */
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
-
-	else
-		{
-			int num_to_read =
-			YY_CURRENT_BUFFER_LVALUE->yy_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 */
-			YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
-
-			int yy_c_buf_p_offset =
-				(int) ((yy_c_buf_p) - b->yy_ch_buf);
-
-			if ( b->yy_is_our_buffer )
-				{
-				int new_size = b->yy_buf_size * 2;
-
-				if ( new_size <= 0 )
-					b->yy_buf_size += b->yy_buf_size / 8;
-				else
-					b->yy_buf_size *= 2;
-
-				b->yy_ch_buf = (char *)
-					/* Include room in for 2 EOB chars. */
-					wcsulexrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2  );
-				}
-			else
-				/* Can't grow it, we don't own it. */
-				b->yy_ch_buf = 0;
-
-			if ( ! b->yy_ch_buf )
-				YY_FATAL_ERROR(
-				"fatal error - scanner input buffer overflow" );
-
-			(yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset];
-
-			num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
-						number_to_move - 1;
-
-			}
-
-		if ( num_to_read > YY_READ_BUF_SIZE )
-			num_to_read = YY_READ_BUF_SIZE;
-
-		/* Read in more data. */
-		YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
-			(yy_n_chars), (size_t) num_to_read );
-
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
-		}
-
-	if ( (yy_n_chars) == 0 )
-		{
-		if ( number_to_move == YY_MORE_ADJ )
-			{
-			ret_val = EOB_ACT_END_OF_FILE;
-			wcsulexrestart(wcsulexin  );
-			}
-
-		else
-			{
-			ret_val = EOB_ACT_LAST_MATCH;
-			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
-				YY_BUFFER_EOF_PENDING;
-			}
-		}
-
-	else
-		ret_val = EOB_ACT_CONTINUE_SCAN;
-
-	if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
-		/* Extend the array by 50%, plus the number we really need. */
-		yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1);
-		YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) wcsulexrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size  );
-		if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
-			YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
-	}
-
-	(yy_n_chars) += number_to_move;
-	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
-	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
-
-	(yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
-
-	return ret_val;
-}
-
-/* yy_get_previous_state - get the state just before the EOB char was reached */
-
-    static yy_state_type yy_get_previous_state (void)
-{
-	register yy_state_type yy_current_state;
-	register char *yy_cp;
-    
-	yy_current_state = (yy_start);
-	yy_current_state += YY_AT_BOL();
-
-	for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
-		{
-		if ( *yy_cp )
-			{
-			yy_current_state = yy_nxt[yy_current_state][YY_SC_TO_UI(*yy_cp)];
-			}
-		else
-			yy_current_state = yy_NUL_trans[yy_current_state];
-		if ( yy_accept[yy_current_state] )
-			{
-			(yy_last_accepting_state) = yy_current_state;
-			(yy_last_accepting_cpos) = yy_cp;
-			}
-		}
-
-	return yy_current_state;
-}
-
-/* yy_try_NUL_trans - try to make a transition on the NUL character
- *
- * synopsis
- *	next_state = yy_try_NUL_trans( current_state );
- */
-    static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state )
-{
-	register int yy_is_jam;
-    	register char *yy_cp = (yy_c_buf_p);
-
-	yy_current_state = yy_NUL_trans[yy_current_state];
-	yy_is_jam = (yy_current_state == 0);
-
-	if ( ! yy_is_jam )
-		{
-		if ( yy_accept[yy_current_state] )
-			{
-			(yy_last_accepting_state) = yy_current_state;
-			(yy_last_accepting_cpos) = yy_cp;
-			}
-		}
-
-	return yy_is_jam ? 0 : yy_current_state;
-}
-
-    static void yyunput (int c, register char * yy_bp )
-{
-	register char *yy_cp;
-    
-    yy_cp = (yy_c_buf_p);
-
-	/* undo effects of setting up wcsulextext */
-	*yy_cp = (yy_hold_char);
-
-	if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
-		{ /* need to shift things up to make room */
-		/* +2 for EOB chars. */
-		register int number_to_move = (yy_n_chars) + 2;
-		register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
-					YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
-		register char *source =
-				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
-
-		while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
-			*--dest = *--source;
-
-		yy_cp += (int) (dest - source);
-		yy_bp += (int) (dest - source);
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars =
-			(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size;
-
-		if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
-			YY_FATAL_ERROR( "flex scanner push-back overflow" );
-		}
-
-	*--yy_cp = (char) c;
-
-	(yytext_ptr) = yy_bp;
-	(yy_hold_char) = *yy_cp;
-	(yy_c_buf_p) = yy_cp;
-}
-
-#ifndef YY_NO_INPUT
-#ifdef __cplusplus
-    static int yyinput (void)
-#else
-    static int input  (void)
-#endif
-
-{
-	int c;
-    
-	*(yy_c_buf_p) = (yy_hold_char);
-
-	if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
-		{
-		/* yy_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 ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
-			/* This was really a NUL. */
-			*(yy_c_buf_p) = '\0';
-
-		else
-			{ /* need more input */
-			int offset = (yy_c_buf_p) - (yytext_ptr);
-			++(yy_c_buf_p);
-
-			switch ( yy_get_next_buffer(  ) )
-				{
-				case EOB_ACT_LAST_MATCH:
-					/* This happens because yy_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. */
-					wcsulexrestart(wcsulexin );
-
-					/*FALLTHROUGH*/
-
-				case EOB_ACT_END_OF_FILE:
-					{
-					if ( wcsulexwrap( ) )
-						return EOF;
-
-					if ( ! (yy_did_buffer_switch_on_eof) )
-						YY_NEW_FILE;
-#ifdef __cplusplus
-					return yyinput();
-#else
-					return input();
-#endif
-					}
-
-				case EOB_ACT_CONTINUE_SCAN:
-					(yy_c_buf_p) = (yytext_ptr) + offset;
-					break;
-				}
-			}
-		}
-
-	c = *(unsigned char *) (yy_c_buf_p);	/* cast for 8-bit char's */
-	*(yy_c_buf_p) = '\0';	/* preserve wcsulextext */
-	(yy_hold_char) = *++(yy_c_buf_p);
-
-	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = (c == '\n');
-
-	return c;
-}
-#endif	/* ifndef YY_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 wcsulexrestart  (FILE * input_file )
-{
-    
-	if ( ! YY_CURRENT_BUFFER ){
-        wcsulexensure_buffer_stack ();
-		YY_CURRENT_BUFFER_LVALUE =
-            wcsulex_create_buffer(wcsulexin,YY_BUF_SIZE );
-	}
-
-	wcsulex_init_buffer(YY_CURRENT_BUFFER,input_file );
-	wcsulex_load_buffer_state( );
-}
-
-/** Switch to a different input buffer.
- * @param new_buffer The new input buffer.
- * 
- */
-    void wcsulex_switch_to_buffer  (YY_BUFFER_STATE  new_buffer )
-{
-    
-	/* TODO. We should be able to replace this entire function body
-	 * with
-	 *		wcsulexpop_buffer_state();
-	 *		wcsulexpush_buffer_state(new_buffer);
-     */
-	wcsulexensure_buffer_stack ();
-	if ( YY_CURRENT_BUFFER == new_buffer )
-		return;
-
-	if ( YY_CURRENT_BUFFER )
-		{
-		/* Flush out information for old buffer. */
-		*(yy_c_buf_p) = (yy_hold_char);
-		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
-		}
-
-	YY_CURRENT_BUFFER_LVALUE = new_buffer;
-	wcsulex_load_buffer_state( );
-
-	/* We don't actually know whether we did this switch during
-	 * EOF (wcsulexwrap()) processing, but the only time this flag
-	 * is looked at is after wcsulexwrap() is called, so it's safe
-	 * to go ahead and always set it.
-	 */
-	(yy_did_buffer_switch_on_eof) = 1;
-}
-
-static void wcsulex_load_buffer_state  (void)
-{
-    	(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
-	(yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
-	wcsulexin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
-	(yy_hold_char) = *(yy_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 YY_BUF_SIZE.
- * 
- * @return the allocated buffer state.
- */
-    YY_BUFFER_STATE wcsulex_create_buffer  (FILE * file, int  size )
-{
-	YY_BUFFER_STATE b;
-    
-	b = (YY_BUFFER_STATE) wcsulexalloc(sizeof( struct yy_buffer_state )  );
-	if ( ! b )
-		YY_FATAL_ERROR( "out of dynamic memory in wcsulex_create_buffer()" );
-
-	b->yy_buf_size = size;
-
-	/* yy_ch_buf has to be 2 characters longer than the size given because
-	 * we need to put in 2 end-of-buffer characters.
-	 */
-	b->yy_ch_buf = (char *) wcsulexalloc(b->yy_buf_size + 2  );
-	if ( ! b->yy_ch_buf )
-		YY_FATAL_ERROR( "out of dynamic memory in wcsulex_create_buffer()" );
-
-	b->yy_is_our_buffer = 1;
-
-	wcsulex_init_buffer(b,file );
-
-	return b;
-}
-
-/** Destroy the buffer.
- * @param b a buffer created with wcsulex_create_buffer()
- * 
- */
-    void wcsulex_delete_buffer (YY_BUFFER_STATE  b )
-{
-    
-	if ( ! b )
-		return;
-
-	if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
-		YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
-
-	if ( b->yy_is_our_buffer )
-		wcsulexfree((void *) b->yy_ch_buf  );
-
-	wcsulexfree((void *) b  );
-}
-
-/* Initializes or reinitializes a buffer.
- * This function is sometimes called more than once on the same buffer,
- * such as during a wcsulexrestart() or at EOF.
- */
-    static void wcsulex_init_buffer  (YY_BUFFER_STATE  b, FILE * file )
-
-{
-	int oerrno = errno;
-    
-	wcsulex_flush_buffer(b );
-
-	b->yy_input_file = file;
-	b->yy_fill_buffer = 1;
-
-    /* If b is the current buffer, then wcsulex_init_buffer was _probably_
-     * called from wcsulexrestart() or through yy_get_next_buffer.
-     * In that case, we don't want to reset the lineno or column.
-     */
-    if (b != YY_CURRENT_BUFFER){
-        b->yy_bs_lineno = 1;
-        b->yy_bs_column = 0;
-    }
-
-        b->yy_is_interactive = 0;
-    
-	errno = oerrno;
-}
-
-/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
- * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
- * 
- */
-    void wcsulex_flush_buffer (YY_BUFFER_STATE  b )
-{
-    	if ( ! b )
-		return;
-
-	b->yy_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->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
-	b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
-
-	b->yy_buf_pos = &b->yy_ch_buf[0];
-
-	b->yy_at_bol = 1;
-	b->yy_buffer_status = YY_BUFFER_NEW;
-
-	if ( b == YY_CURRENT_BUFFER )
-		wcsulex_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 wcsulexpush_buffer_state (YY_BUFFER_STATE new_buffer )
-{
-    	if (new_buffer == NULL)
-		return;
-
-	wcsulexensure_buffer_stack();
-
-	/* This block is copied from wcsulex_switch_to_buffer. */
-	if ( YY_CURRENT_BUFFER )
-		{
-		/* Flush out information for old buffer. */
-		*(yy_c_buf_p) = (yy_hold_char);
-		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
-		}
-
-	/* Only push if top exists. Otherwise, replace top. */
-	if (YY_CURRENT_BUFFER)
-		(yy_buffer_stack_top)++;
-	YY_CURRENT_BUFFER_LVALUE = new_buffer;
-
-	/* copied from wcsulex_switch_to_buffer. */
-	wcsulex_load_buffer_state( );
-	(yy_did_buffer_switch_on_eof) = 1;
-}
-
-/** Removes and deletes the top of the stack, if present.
- *  The next element becomes the new top.
- *  
- */
-void wcsulexpop_buffer_state (void)
-{
-    	if (!YY_CURRENT_BUFFER)
-		return;
-
-	wcsulex_delete_buffer(YY_CURRENT_BUFFER );
-	YY_CURRENT_BUFFER_LVALUE = NULL;
-	if ((yy_buffer_stack_top) > 0)
-		--(yy_buffer_stack_top);
-
-	if (YY_CURRENT_BUFFER) {
-		wcsulex_load_buffer_state( );
-		(yy_did_buffer_switch_on_eof) = 1;
-	}
-}
-
-/* Allocates the stack if it does not exist.
- *  Guarantees space for at least one push.
- */
-static void wcsulexensure_buffer_stack (void)
-{
-	int num_to_alloc;
-    
-	if (!(yy_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;
-		(yy_buffer_stack) = (struct yy_buffer_state**)wcsulexalloc
-								(num_to_alloc * sizeof(struct yy_buffer_state*)
-								);
-		if ( ! (yy_buffer_stack) )
-			YY_FATAL_ERROR( "out of dynamic memory in wcsulexensure_buffer_stack()" );
-								  
-		memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
-				
-		(yy_buffer_stack_max) = num_to_alloc;
-		(yy_buffer_stack_top) = 0;
-		return;
-	}
-
-	if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
-
-		/* Increase the buffer to prepare for a possible push. */
-		int grow_size = 8 /* arbitrary grow size */;
-
-		num_to_alloc = (yy_buffer_stack_max) + grow_size;
-		(yy_buffer_stack) = (struct yy_buffer_state**)wcsulexrealloc
-								((yy_buffer_stack),
-								num_to_alloc * sizeof(struct yy_buffer_state*)
-								);
-		if ( ! (yy_buffer_stack) )
-			YY_FATAL_ERROR( "out of dynamic memory in wcsulexensure_buffer_stack()" );
-
-		/* zero only the new slots.*/
-		memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
-		(yy_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. 
- */
-YY_BUFFER_STATE wcsulex_scan_buffer  (char * base, yy_size_t  size )
-{
-	YY_BUFFER_STATE b;
-    
-	if ( size < 2 ||
-	     base[size-2] != YY_END_OF_BUFFER_CHAR ||
-	     base[size-1] != YY_END_OF_BUFFER_CHAR )
-		/* They forgot to leave room for the EOB's. */
-		return 0;
-
-	b = (YY_BUFFER_STATE) wcsulexalloc(sizeof( struct yy_buffer_state )  );
-	if ( ! b )
-		YY_FATAL_ERROR( "out of dynamic memory in wcsulex_scan_buffer()" );
-
-	b->yy_buf_size = size - 2;	/* "- 2" to take care of EOB's */
-	b->yy_buf_pos = b->yy_ch_buf = base;
-	b->yy_is_our_buffer = 0;
-	b->yy_input_file = 0;
-	b->yy_n_chars = b->yy_buf_size;
-	b->yy_is_interactive = 0;
-	b->yy_at_bol = 1;
-	b->yy_fill_buffer = 0;
-	b->yy_buffer_status = YY_BUFFER_NEW;
-
-	wcsulex_switch_to_buffer(b  );
-
-	return b;
-}
-
-/** Setup the input buffer state to scan a string. The next call to wcsulexlex() will
- * scan from a @e copy of @a str.
- * @param yystr 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
- *       wcsulex_scan_bytes() instead.
- */
-YY_BUFFER_STATE wcsulex_scan_string (yyconst char * yystr )
-{
-    
-	return wcsulex_scan_bytes(yystr,strlen(yystr) );
-}
-
-/** Setup the input buffer state to scan the given bytes. The next call to wcsulexlex() will
- * scan from a @e copy of @a bytes.
- * @param yybytes the byte buffer to scan
- * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
- * 
- * @return the newly allocated buffer state object.
- */
-YY_BUFFER_STATE wcsulex_scan_bytes  (yyconst char * yybytes, int  _yybytes_len )
-{
-	YY_BUFFER_STATE b;
-	char *buf;
-	yy_size_t n;
-	int i;
-    
-	/* Get memory for full buffer, including space for trailing EOB's. */
-	n = _yybytes_len + 2;
-	buf = (char *) wcsulexalloc(n  );
-	if ( ! buf )
-		YY_FATAL_ERROR( "out of dynamic memory in wcsulex_scan_bytes()" );
-
-	for ( i = 0; i < _yybytes_len; ++i )
-		buf[i] = yybytes[i];
-
-	buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
-
-	b = wcsulex_scan_buffer(buf,n );
-	if ( ! b )
-		YY_FATAL_ERROR( "bad buffer in wcsulex_scan_bytes()" );
-
-	/* It's okay to grow etc. this buffer, and we should throw it
-	 * away when we're done.
-	 */
-	b->yy_is_our_buffer = 1;
-
-	return b;
-}
-
-#ifndef YY_EXIT_FAILURE
-#define YY_EXIT_FAILURE 2
-#endif
-
-static void yy_fatal_error (yyconst char* msg )
-{
-    	(void) fprintf( stderr, "%s\n", msg );
-	exit( YY_EXIT_FAILURE );
-}
-
-/* Redefine yyless() so it works in section 3 code. */
-
-#undef yyless
-#define yyless(n) \
-	do \
-		{ \
-		/* Undo effects of setting up wcsulextext. */ \
-        int yyless_macro_arg = (n); \
-        YY_LESS_LINENO(yyless_macro_arg);\
-		wcsulextext[wcsulexleng] = (yy_hold_char); \
-		(yy_c_buf_p) = wcsulextext + yyless_macro_arg; \
-		(yy_hold_char) = *(yy_c_buf_p); \
-		*(yy_c_buf_p) = '\0'; \
-		wcsulexleng = yyless_macro_arg; \
-		} \
-	while ( 0 )
-
-/* Accessor  methods (get/set functions) to struct members. */
-
-/** Get the current line number.
- * 
- */
-int wcsulexget_lineno  (void)
-{
-        
-    return wcsulexlineno;
-}
-
-/** Get the input stream.
- * 
- */
-FILE *wcsulexget_in  (void)
-{
-        return wcsulexin;
-}
-
-/** Get the output stream.
- * 
- */
-FILE *wcsulexget_out  (void)
-{
-        return wcsulexout;
-}
-
-/** Get the length of the current token.
- * 
- */
-int wcsulexget_leng  (void)
-{
-        return wcsulexleng;
-}
-
-/** Get the current token.
- * 
- */
-
-char *wcsulexget_text  (void)
-{
-        return wcsulextext;
-}
-
-/** Set the current line number.
- * @param line_number
- * 
- */
-void wcsulexset_lineno (int  line_number )
-{
-    
-    wcsulexlineno = line_number;
-}
-
-/** Set the input stream. This does not discard the current
- * input buffer.
- * @param in_str A readable stream.
- * 
- * @see wcsulex_switch_to_buffer
- */
-void wcsulexset_in (FILE *  in_str )
-{
-        wcsulexin = in_str ;
-}
-
-void wcsulexset_out (FILE *  out_str )
-{
-        wcsulexout = out_str ;
-}
-
-int wcsulexget_debug  (void)
-{
-        return wcsulex_flex_debug;
-}
-
-void wcsulexset_debug (int  bdebug )
-{
-        wcsulex_flex_debug = bdebug ;
-}
-
-static int yy_init_globals (void)
-{
-        /* Initialization is the same as for the non-reentrant scanner.
-     * This function is called from wcsulexlex_destroy(), so don't allocate here.
-     */
-
-    (yy_buffer_stack) = 0;
-    (yy_buffer_stack_top) = 0;
-    (yy_buffer_stack_max) = 0;
-    (yy_c_buf_p) = (char *) 0;
-    (yy_init) = 0;
-    (yy_start) = 0;
-
-/* Defined in main.c */
-#ifdef YY_STDINIT
-    wcsulexin = stdin;
-    wcsulexout = stdout;
-#else
-    wcsulexin = (FILE *) 0;
-    wcsulexout = (FILE *) 0;
-#endif
-
-    /* For future reference: Set errno on error, since we are called by
-     * wcsulexlex_init()
-     */
-    return 0;
-}
-
-/* wcsulexlex_destroy is for both reentrant and non-reentrant scanners. */
-int wcsulexlex_destroy  (void)
-{
-    
-    /* Pop the buffer stack, destroying each element. */
-	while(YY_CURRENT_BUFFER){
-		wcsulex_delete_buffer(YY_CURRENT_BUFFER  );
-		YY_CURRENT_BUFFER_LVALUE = NULL;
-		wcsulexpop_buffer_state();
-	}
-
-	/* Destroy the stack itself. */
-	wcsulexfree((yy_buffer_stack) );
-	(yy_buffer_stack) = NULL;
-
-    /* Reset the globals. This is important in a non-reentrant scanner so the next time
-     * wcsulexlex() is called, initialization will occur. */
-    yy_init_globals( );
-
-    return 0;
-}
-
-/*
- * Internal utility routines.
- */
-
-#ifndef yytext_ptr
-static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
-{
-	register int i;
-	for ( i = 0; i < n; ++i )
-		s1[i] = s2[i];
-}
-#endif
-
-#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * s )
-{
-	register int n;
-	for ( n = 0; s[n]; ++n )
-		;
-
-	return n;
-}
-#endif
-
-void *wcsulexalloc (yy_size_t  size )
-{
-	return (void *) malloc( size );
-}
-
-void *wcsulexrealloc  (void * ptr, yy_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 wcsulexfree (void * ptr )
-{
-	free( (char *) ptr );	/* see wcsulexrealloc() for (char *) cast */
-}
-
-#define YYTABLES_NAME "yytables"
-
-#line 970 "wcsulex.l"
-
-
-
-/*----------------------------------------------------------------------------
-* Accumulate a term in a units specification and reset work variables.
-*---------------------------------------------------------------------------*/
-
-void add(
-  double *factor,
-  double types[],
-  double *expon,
-  double *scale,
-  double units[])
-
-{
-  int i;
-
-  *scale *= pow(*factor, *expon);
-
-  for (i = 0; i < WCSUNITS_NTYPE; i++) {
-    units[i] += *expon * types[i];
-    types[i] = 0.0;
-  }
-
-  *expon  = 1.0;
-  *factor = 1.0;
-
-  return;
-}
-
diff --git a/astropy/wcs/src/wcslib/C/flexed/wcsutrn.c b/astropy/wcs/src/wcslib/C/flexed/wcsutrn.c
deleted file mode 100644
index 472a6e0..0000000
--- a/astropy/wcs/src/wcslib/C/flexed/wcsutrn.c
+++ /dev/null
@@ -1,5644 +0,0 @@
-#line 2 "wcsutrn.c"
-
-#line 4 "wcsutrn.c"
-
-#define  YY_INT_ALIGNED short int
-
-/* A lexical scanner generated by flex */
-
-#define yy_create_buffer wcsutrn_create_buffer
-#define yy_delete_buffer wcsutrn_delete_buffer
-#define yy_flex_debug wcsutrn_flex_debug
-#define yy_init_buffer wcsutrn_init_buffer
-#define yy_flush_buffer wcsutrn_flush_buffer
-#define yy_load_buffer_state wcsutrn_load_buffer_state
-#define yy_switch_to_buffer wcsutrn_switch_to_buffer
-#define yyin wcsutrnin
-#define yyleng wcsutrnleng
-#define yylex wcsutrnlex
-#define yylineno wcsutrnlineno
-#define yyout wcsutrnout
-#define yyrestart wcsutrnrestart
-#define yytext wcsutrntext
-#define yywrap wcsutrnwrap
-#define yyalloc wcsutrnalloc
-#define yyrealloc wcsutrnrealloc
-#define yyfree wcsutrnfree
-
-#define FLEX_SCANNER
-#define YY_FLEX_MAJOR_VERSION 2
-#define YY_FLEX_MINOR_VERSION 5
-#define YY_FLEX_SUBMINOR_VERSION 35
-#if YY_FLEX_SUBMINOR_VERSION > 0
-#define FLEX_BETA
-#endif
-
-/* First, we deal with  platform-specific or compiler-specific issues. */
-
-/* begin standard C headers. */
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <stdlib.h>
-
-/* end standard C headers. */
-
-/* flex integer type definitions */
-
-#ifndef FLEXINT_H
-#define FLEXINT_H
-
-/* C99 systems have <inttypes.h>. 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 <inttypes.h>
-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;
-
-/* 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 /* ! C99 */
-
-#endif /* ! FLEXINT_H */
-
-#ifdef __cplusplus
-
-/* The "const" storage-class-modifier is valid. */
-#define YY_USE_CONST
-
-#else	/* ! __cplusplus */
-
-/* C99 requires __STDC__ to be defined as 1. */
-#if defined (__STDC__)
-
-#define YY_USE_CONST
-
-#endif	/* defined (__STDC__) */
-#endif	/* ! __cplusplus */
-
-#ifdef YY_USE_CONST
-#define yyconst const
-#else
-#define yyconst
-#endif
-
-/* Returned upon end-of-file. */
-#define YY_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 YY_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 (yy_start) = 1 + 2 *
-
-/* Translate the current start state into a value that can be later handed
- * to BEGIN to return to the state.  The YYSTATE alias is for lex
- * compatibility.
- */
-#define YY_START (((yy_start) - 1) / 2)
-#define YYSTATE YY_START
-
-/* Action number for EOF rule of a given start state. */
-#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
-
-/* Special action meaning "start processing a new file". */
-#define YY_NEW_FILE wcsutrnrestart(wcsutrnin  )
-
-#define YY_END_OF_BUFFER_CHAR 0
-
-/* Size of default input buffer. */
-#ifndef YY_BUF_SIZE
-#ifdef __ia64__
-/* On IA-64, the buffer size is 16k, not 8k.
- * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
- * Ditto for the __ia64__ case accordingly.
- */
-#define YY_BUF_SIZE 32768
-#else
-#define YY_BUF_SIZE 16384
-#endif /* __ia64__ */
-#endif
-
-/* The state buf must be large enough to hold one state per character in the main buffer.
- */
-#define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
-
-#ifndef YY_TYPEDEF_YY_BUFFER_STATE
-#define YY_TYPEDEF_YY_BUFFER_STATE
-typedef struct yy_buffer_state *YY_BUFFER_STATE;
-#endif
-
-extern int wcsutrnleng;
-
-extern FILE *wcsutrnin, *wcsutrnout;
-
-#define EOB_ACT_CONTINUE_SCAN 0
-#define EOB_ACT_END_OF_FILE 1
-#define EOB_ACT_LAST_MATCH 2
-
-#define YY_LESS_LINENO(n)
-    
-/* Return all but the first "n" matched characters back to the input stream. */
-#define yyless(n) \
-	do \
-		{ \
-		/* Undo effects of setting up wcsutrntext. */ \
-        int yyless_macro_arg = (n); \
-        YY_LESS_LINENO(yyless_macro_arg);\
-		*yy_cp = (yy_hold_char); \
-		YY_RESTORE_YY_MORE_OFFSET \
-		(yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
-		YY_DO_BEFORE_ACTION; /* set up wcsutrntext again */ \
-		} \
-	while ( 0 )
-
-#define unput(c) yyunput( c, (yytext_ptr)  )
-
-#ifndef YY_TYPEDEF_YY_SIZE_T
-#define YY_TYPEDEF_YY_SIZE_T
-typedef size_t yy_size_t;
-#endif
-
-#ifndef YY_STRUCT_YY_BUFFER_STATE
-#define YY_STRUCT_YY_BUFFER_STATE
-struct yy_buffer_state
-	{
-	FILE *yy_input_file;
-
-	char *yy_ch_buf;		/* input buffer */
-	char *yy_buf_pos;		/* current position in input buffer */
-
-	/* Size of input buffer in bytes, not including room for EOB
-	 * characters.
-	 */
-	yy_size_t yy_buf_size;
-
-	/* Number of characters read into yy_ch_buf, not including EOB
-	 * characters.
-	 */
-	int yy_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 yy_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 yy_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 yy_at_bol;
-
-    int yy_bs_lineno; /**< The line count. */
-    int yy_bs_column; /**< The column count. */
-    
-	/* Whether to try to fill the input buffer when we reach the
-	 * end of it.
-	 */
-	int yy_fill_buffer;
-
-	int yy_buffer_status;
-
-#define YY_BUFFER_NEW 0
-#define YY_BUFFER_NORMAL 1
-	/* When an EOF's been seen but there's still some text to process
-	 * then we mark the buffer as YY_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 wcsutrnrestart()), so that the user can continue scanning by
-	 * just pointing wcsutrnin at a new input file.
-	 */
-#define YY_BUFFER_EOF_PENDING 2
-
-	};
-#endif /* !YY_STRUCT_YY_BUFFER_STATE */
-
-/* Stack of input buffers. */
-static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
-static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
-static YY_BUFFER_STATE * yy_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 YY_CURRENT_BUFFER ( (yy_buffer_stack) \
-                          ? (yy_buffer_stack)[(yy_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 YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
-
-/* yy_hold_char holds the character lost when wcsutrntext is formed. */
-static char yy_hold_char;
-static int yy_n_chars;		/* number of characters read into yy_ch_buf */
-int wcsutrnleng;
-
-/* Points to current character in buffer. */
-static char *yy_c_buf_p = (char *) 0;
-static int yy_init = 0;		/* whether we need to initialize */
-static int yy_start = 0;	/* start state number */
-
-/* Flag which is used to allow wcsutrnwrap()'s to do buffer switches
- * instead of setting up a fresh wcsutrnin.  A bit of a hack ...
- */
-static int yy_did_buffer_switch_on_eof;
-
-void wcsutrnrestart (FILE *input_file  );
-void wcsutrn_switch_to_buffer (YY_BUFFER_STATE new_buffer  );
-YY_BUFFER_STATE wcsutrn_create_buffer (FILE *file,int size  );
-void wcsutrn_delete_buffer (YY_BUFFER_STATE b  );
-void wcsutrn_flush_buffer (YY_BUFFER_STATE b  );
-void wcsutrnpush_buffer_state (YY_BUFFER_STATE new_buffer  );
-void wcsutrnpop_buffer_state (void );
-
-static void wcsutrnensure_buffer_stack (void );
-static void wcsutrn_load_buffer_state (void );
-static void wcsutrn_init_buffer (YY_BUFFER_STATE b,FILE *file  );
-
-#define YY_FLUSH_BUFFER wcsutrn_flush_buffer(YY_CURRENT_BUFFER )
-
-YY_BUFFER_STATE wcsutrn_scan_buffer (char *base,yy_size_t size  );
-YY_BUFFER_STATE wcsutrn_scan_string (yyconst char *yy_str  );
-YY_BUFFER_STATE wcsutrn_scan_bytes (yyconst char *bytes,int len  );
-
-void *wcsutrnalloc (yy_size_t  );
-void *wcsutrnrealloc (void *,yy_size_t  );
-void wcsutrnfree (void *  );
-
-#define yy_new_buffer wcsutrn_create_buffer
-
-#define yy_set_interactive(is_interactive) \
-	{ \
-	if ( ! YY_CURRENT_BUFFER ){ \
-        wcsutrnensure_buffer_stack (); \
-		YY_CURRENT_BUFFER_LVALUE =    \
-            wcsutrn_create_buffer(wcsutrnin,YY_BUF_SIZE ); \
-	} \
-	YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
-	}
-
-#define yy_set_bol(at_bol) \
-	{ \
-	if ( ! YY_CURRENT_BUFFER ){\
-        wcsutrnensure_buffer_stack (); \
-		YY_CURRENT_BUFFER_LVALUE =    \
-            wcsutrn_create_buffer(wcsutrnin,YY_BUF_SIZE ); \
-	} \
-	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
-	}
-
-#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
-
-/* Begin user sect3 */
-
-#define wcsutrnwrap(n) 1
-#define YY_SKIP_YYWRAP
-
-typedef char YY_CHAR;
-
-FILE *wcsutrnin = (FILE *) 0, *wcsutrnout = (FILE *) 0;
-
-typedef int yy_state_type;
-
-extern int wcsutrnlineno;
-
-int wcsutrnlineno = 1;
-
-extern char *wcsutrntext;
-#define yytext_ptr wcsutrntext
-static yyconst flex_int16_t yy_nxt[][128] =
-    {
-    {
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-
-        0,    0,    0,    0,    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,    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,    9,    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,   10,   11,   12,   13,   12,
-
-       12,   14,   15,   12,   16,   17,   12,   18,   12,   19,
-       20,   12,   21,   22,   12,   12,   23,   12,   12,   24,
-       12,    8,    8,    8,    8,    8,    8,   25,   12,   12,
-       26,   12,   12,   12,   27,   12,   12,   28,   12,   29,
-       12,   12,   30,   12,   31,   32,   12,   12,   33,   12,
-       12,   34,   12,    8,    8,    8,    8,    8
-    },
-
-    {
-        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,   35,    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,   10,   11,   12,   13,   12,
-       12,   14,   15,   12,   16,   17,   12,   18,   12,   19,
-       20,   12,   21,   22,   12,   12,   23,   12,   12,   24,
-       12,   36,    8,    8,    8,    8,    8,   25,   12,   12,
-       26,   12,   12,   12,   27,   12,   12,   28,   12,   29,
-       12,   12,   30,   12,   31,   32,   12,   12,   33,   12,
-       12,   34,   12,    8,    8,    8,    8,    8
-    },
-
-    {
-        7,   37,   37,   37,   37,   37,   37,   37,   37,   37,
-
-       38,   37,   37,   37,   37,   37,   37,   37,   37,   37,
-       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
-       37,   37,   39,   37,   37,   37,   37,   37,   37,   37,
-       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
-       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
-       37,   37,   37,   37,   37,   40,   40,   40,   40,   40,
-       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
-       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
-       40,   37,   37,   37,   37,   37,   37,   40,   40,   40,
-       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
-
-       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
-       40,   40,   40,   37,   37,   37,   37,   37
-    },
-
-    {
-        7,   37,   37,   37,   37,   37,   37,   37,   37,   37,
-       38,   37,   37,   37,   37,   37,   37,   37,   37,   37,
-       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
-       37,   37,   39,   37,   37,   37,   37,   37,   37,   37,
-       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
-       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
-       37,   37,   37,   37,   37,   40,   40,   40,   40,   40,
-       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
-
-       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
-       40,   37,   37,   37,   37,   37,   37,   40,   40,   40,
-       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
-       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
-       40,   40,   40,   37,   37,   37,   37,   37
-    },
-
-    {
-        7,   41,   41,   41,   41,   41,   41,   41,   41,   41,
-       38,   41,   41,   41,   41,   41,   41,   41,   41,   41,
-       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
-       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
-       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
-
-       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
-       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
-       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
-       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
-       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
-       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
-       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
-       41,   41,   41,   41,   41,   41,   41,   41
-    },
-
-    {
-        7,   41,   41,   41,   41,   41,   41,   41,   41,   41,
-       38,   41,   41,   41,   41,   41,   41,   41,   41,   41,
-
-       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
-       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
-       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
-       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
-       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
-       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
-       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
-       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
-       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
-       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
-
-       41,   41,   41,   41,   41,   41,   41,   41
-    },
-
-    {
-       -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,   -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
-    },
-
-    {
-        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
-    },
-
-    {
-        7,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,
-       -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,
-       -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,
-
-       -9,   -9,   42,   -9,   -9,   -9,   -9,   -9,   -9,   -9,
-       -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,
-       -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,
-       -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,
-       -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,
-       -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,
-       -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,
-       -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,
-       -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,
-       -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9
-
-    },
-
-    {
-        7,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,
-      -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,
-      -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,
-      -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,
-      -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,
-      -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,
-      -10,  -10,  -10,  -10,  -10,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   44,   43,   43,   43,   43,   43,   43,   43,
-       43,  -10,  -10,  -10,  -10,  -10,  -10,   43,   43,   43,
-
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  -10,  -10,  -10,  -10,  -10
-    },
-
-    {
-        7,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,
-      -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,
-      -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,
-      -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,
-      -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,
-      -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,
-      -11,  -11,  -11,  -11,  -11,   43,   43,   43,   43,   45,
-
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,  -11,  -11,  -11,  -11,  -11,  -11,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   46,   43,  -11,  -11,  -11,  -11,  -11
-    },
-
-    {
-        7,  -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,  -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,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,  -12,  -12,  -12,  -12,  -12,  -12,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  -12,  -12,  -12,  -12,  -12
-    },
-
-    {
-        7,  -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,  -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,   47,   43,   43,   43,   48,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,  -13,  -13,  -13,  -13,  -13,  -13,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  -13,  -13,  -13,  -13,  -13
-    },
-
-    {
-        7,  -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,   43,   43,   43,   43,   43,
-       43,   43,   49,   43,   43,   43,   43,   43,   43,   43,
-
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,  -14,  -14,  -14,  -14,  -14,  -14,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  -14,  -14,  -14,  -14,  -14
-    },
-
-    {
-        7,  -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,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   50,   43,   43,   43,   43,   43,   43,   43,
-       51,  -15,  -15,  -15,  -15,  -15,  -15,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  -15,  -15,  -15,  -15,  -15
-    },
-
-    {
-        7,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
-      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
-
-      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
-      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
-      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
-      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
-      -16,  -16,  -16,  -16,  -16,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   52,
-       43,  -16,  -16,  -16,  -16,  -16,  -16,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43,   43,   43,  -16,  -16,  -16,  -16,  -16
-    },
-
-    {
-        7,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
-      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
-      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
-      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
-      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
-      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
-      -17,  -17,  -17,  -17,  -17,   43,   43,   43,   43,   53,
-       43,   43,   54,   43,   43,   43,   43,   55,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43,  -17,  -17,  -17,  -17,  -17,  -17,   43,   43,   43,
-       43,   56,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  -17,  -17,  -17,  -17,  -17
-    },
-
-    {
-        7,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,
-      -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,
-      -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,
-      -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,
-      -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,
-      -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,
-
-      -18,  -18,  -18,  -18,  -18,   43,   43,   43,   43,   57,
-       43,   43,   58,   59,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,  -18,  -18,  -18,  -18,  -18,  -18,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  -18,  -18,  -18,  -18,  -18
-    },
-
-    {
-        7,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,
-      -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,
-      -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,
-
-      -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,
-      -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,
-      -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,
-      -19,  -19,  -19,  -19,  -19,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,  -19,  -19,  -19,  -19,  -19,  -19,   43,   43,   43,
-       43,   43,   43,   43,   60,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  -19,  -19,  -19,  -19,  -19
-
-    },
-
-    {
-        7,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,
-      -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,
-      -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,
-      -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,
-      -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,
-      -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,
-      -20,  -20,  -20,  -20,  -20,   61,   43,   43,   43,   43,
-       43,   43,   43,   62,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,  -20,  -20,  -20,  -20,  -20,  -20,   63,   43,   43,
-
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  -20,  -20,  -20,  -20,  -20
-    },
-
-    {
-        7,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,
-      -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,
-      -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,
-      -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,
-      -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,
-      -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,
-      -21,  -21,  -21,  -21,  -21,   64,   43,   43,   43,   43,
-
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,  -21,  -21,  -21,  -21,  -21,  -21,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  -21,  -21,  -21,  -21,  -21
-    },
-
-    {
-        7,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,
-      -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,
-      -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,
-      -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,
-
-      -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,
-      -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,
-      -22,  -22,  -22,  -22,  -22,   43,   43,   43,   43,   65,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,  -22,  -22,  -22,  -22,  -22,  -22,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  -22,  -22,  -22,  -22,  -22
-    },
-
-    {
-        7,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
-
-      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
-      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
-      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
-      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
-      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
-      -23,  -23,  -23,  -23,  -23,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   66,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,  -23,  -23,  -23,  -23,  -23,  -23,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43,   67,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  -23,  -23,  -23,  -23,  -23
-    },
-
-    {
-        7,  -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,  -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,   43,   43,   43,   43,   68,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43,   43,   69,   43,   43,   43,   43,   43,   43,   43,
-       43,  -24,  -24,  -24,  -24,  -24,  -24,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  -24,  -24,  -24,  -24,  -24
-    },
-
-    {
-        7,  -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,  -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,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,  -25,  -25,  -25,  -25,  -25,  -25,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       70,   43,   43,   43,   71,   43,   43,   43,   43,   43,
-       43,   43,   43,  -25,  -25,  -25,  -25,  -25
-    },
-
-    {
-        7,  -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,  -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,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,  -26,  -26,  -26,  -26,  -26,  -26,   72,   43,   43,
-       43,   73,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43,   43,   43,  -26,  -26,  -26,  -26,  -26
-    },
-
-    {
-        7,  -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,  -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,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43,  -27,  -27,  -27,  -27,  -27,  -27,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   50,   43,   43,   43,   43,   43,
-       43,   43,   51,  -27,  -27,  -27,  -27,  -27
-    },
-
-    {
-        7,  -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,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,  -28,  -28,  -28,  -28,  -28,  -28,   43,   43,   43,
-       43,   56,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  -28,  -28,  -28,  -28,  -28
-    },
-
-    {
-        7,  -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,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,  -29,  -29,  -29,  -29,  -29,  -29,   43,   43,   43,
-       43,   74,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  -29,  -29,  -29,  -29,  -29
-
-    },
-
-    {
-        7,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
-      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
-      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
-      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
-      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
-      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
-      -30,  -30,  -30,  -30,  -30,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,  -30,  -30,  -30,  -30,  -30,  -30,   63,   43,   43,
-
-       43,   43,   43,   43,   43,   75,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  -30,  -30,  -30,  -30,  -30
-    },
-
-    {
-        7,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
-      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
-      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
-      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
-      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
-      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
-      -31,  -31,  -31,  -31,  -31,   43,   43,   43,   43,   43,
-
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,  -31,  -31,  -31,  -31,  -31,  -31,   76,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  -31,  -31,  -31,  -31,  -31
-    },
-
-    {
-        7,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
-      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
-      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
-      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
-
-      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
-      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
-      -32,  -32,  -32,  -32,  -32,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,  -32,  -32,  -32,  -32,  -32,  -32,   43,   43,   43,
-       43,   77,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  -32,  -32,  -32,  -32,  -32
-    },
-
-    {
-        7,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
-
-      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
-      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
-      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
-      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
-      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
-      -33,  -33,  -33,  -33,  -33,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,  -33,  -33,  -33,  -33,  -33,  -33,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43,   67,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  -33,  -33,  -33,  -33,  -33
-    },
-
-    {
-        7,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-      -34,  -34,  -34,  -34,  -34,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,  -34,  -34,  -34,  -34,  -34,  -34,   43,   43,   43,
-       43,   78,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  -34,  -34,  -34,  -34,  -34
-    },
-
-    {
-        7,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
-      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
-      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
-      -35,  -35,   79,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
-      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
-
-      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
-      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
-      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
-      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
-      -35,   80,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
-      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
-      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
-      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35
-    },
-
-    {
-        7,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
-      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
-
-      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
-      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
-      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
-      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
-      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
-      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
-      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
-      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
-      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
-      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
-
-      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36
-    },
-
-    {
-        7,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
-      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
-      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
-      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
-      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
-      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
-      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
-      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
-      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
-
-      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
-      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
-      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
-      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37
-    },
-
-    {
-        7,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
-      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
-      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
-      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
-      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
-      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
-
-      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
-      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
-      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
-      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
-      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
-      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
-      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38
-    },
-
-    {
-        7,   81,   81,   81,   81,   81,   81,   81,   81,   81,
-       81,   81,   81,   81,   81,   81,   81,   81,   81,   81,
-       81,   81,   81,   81,   81,   81,   81,   81,   81,   81,
-
-       81,   81,   82,   81,   81,   81,   81,   81,   81,   81,
-       81,   81,   81,   81,   81,   81,   81,   81,   81,   81,
-       81,   81,   81,   81,   81,   81,   81,   81,   81,   81,
-       81,   81,   81,   81,   81,   83,   83,   83,   83,   83,
-       83,   83,   83,   83,   83,   83,   83,   83,   83,   83,
-       83,   83,   83,   83,   83,   83,   83,   83,   83,   83,
-       83,   81,   81,   81,   81,   81,   81,   83,   83,   83,
-       83,   83,   83,   83,   83,   83,   83,   83,   83,   83,
-       83,   83,   83,   83,   83,   83,   83,   83,   83,   83,
-       83,   83,   83,   81,   81,   81,   81,   81
-
-    },
-
-    {
-        7,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
-      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
-      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
-      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
-      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
-      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
-      -40,  -40,  -40,  -40,  -40,   84,   84,   84,   84,   84,
-       84,   84,   84,   84,   84,   84,   84,   84,   84,   84,
-       84,   84,   84,   84,   84,   84,   84,   84,   84,   84,
-       84,  -40,  -40,  -40,  -40,  -40,  -40,   84,   84,   84,
-
-       84,   84,   84,   84,   84,   84,   84,   84,   84,   84,
-       84,   84,   84,   84,   84,   84,   84,   84,   84,   84,
-       84,   84,   84,  -40,  -40,  -40,  -40,  -40
-    },
-
-    {
-        7,   85,   85,   85,   85,   85,   85,   85,   85,   85,
-      -41,   85,   85,   85,   85,   85,   85,   85,   85,   85,
-       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
-       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
-       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
-       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
-       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
-
-       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
-       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
-       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
-       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
-       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
-       85,   85,   85,   85,   85,   85,   85,   85
-    },
-
-    {
-        7,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
-      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
-      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
-      -42,  -42,   42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
-
-      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
-      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
-      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
-      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
-      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
-      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
-      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
-      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
-      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42
-    },
-
-    {
-        7,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
-
-      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
-      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
-      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
-      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
-      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
-      -43,  -43,  -43,  -43,  -43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,  -43,  -43,  -43,  -43,  -43,  -43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  -43,  -43,  -43,  -43,  -43
-    },
-
-    {
-        7,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
-      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
-      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
-      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
-      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
-      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
-      -44,  -44,  -44,  -44,  -44,   43,   43,   86,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,  -44,  -44,  -44,  -44,  -44,  -44,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  -44,  -44,  -44,  -44,  -44
-    },
-
-    {
-        7,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
-      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
-      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
-      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
-      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
-
-      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
-      -45,  -45,  -45,  -45,  -45,   87,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,  -45,  -45,  -45,  -45,  -45,  -45,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  -45,  -45,  -45,  -45,  -45
-    },
-
-    {
-        7,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
-      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
-
-      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
-      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
-      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
-      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
-      -46,  -46,  -46,  -46,  -46,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,  -46,  -46,  -46,  -46,  -46,  -46,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   88,   43,   43,   43,
-
-       43,   43,   43,  -46,  -46,  -46,  -46,  -46
-    },
-
-    {
-        7,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
-      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
-      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
-      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
-      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
-      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
-      -47,  -47,  -47,  -47,  -47,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   89,
-
-       43,  -47,  -47,  -47,  -47,  -47,  -47,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  -47,  -47,  -47,  -47,  -47
-    },
-
-    {
-        7,  -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,   43,   43,   43,   43,   43,
-       43,   90,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,  -48,  -48,  -48,  -48,  -48,  -48,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  -48,  -48,  -48,  -48,  -48
-    },
-
-    {
-        7,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
-      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
-      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
-
-      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
-      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
-      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
-      -49,  -49,  -49,  -49,  -49,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       91,  -49,  -49,  -49,  -49,  -49,  -49,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  -49,  -49,  -49,  -49,  -49
-
-    },
-
-    {
-        7,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
-      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
-      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
-      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
-      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
-      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
-      -50,  -50,  -50,  -50,  -50,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,  -50,  -50,  -50,  -50,  -50,  -50,   43,   43,   43,
-
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  -50,  -50,  -50,  -50,  -50
-    },
-
-    {
-        7,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,  -51,  -51,  -51,  -51,   43,   43,   43,   43,   43,
-
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,  -51,  -51,  -51,  -51,  -51,  -51,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  -51,  -51,  -51,  -51,  -51
-    },
-
-    {
-        7,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
-      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
-      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
-      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
-
-      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
-      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
-      -52,  -52,  -52,  -52,  -52,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,  -52,  -52,  -52,  -52,  -52,  -52,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  -52,  -52,  -52,  -52,  -52
-    },
-
-    {
-        7,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
-
-      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
-      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
-      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
-      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
-      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
-      -53,  -53,  -53,  -53,  -53,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   92,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,  -53,  -53,  -53,  -53,  -53,  -53,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  -53,  -53,  -53,  -53,  -53
-    },
-
-    {
-        7,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
-      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
-      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
-      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
-      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
-      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
-      -54,  -54,  -54,  -54,  -54,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       93,  -54,  -54,  -54,  -54,  -54,  -54,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  -54,  -54,  -54,  -54,  -54
-    },
-
-    {
-        7,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
-      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
-      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
-      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
-      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
-
-      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
-      -55,  -55,  -55,  -55,  -55,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,  -55,  -55,  -55,  -55,  -55,  -55,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  -55,  -55,  -55,  -55,  -55
-    },
-
-    {
-        7,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
-      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
-
-      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
-      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
-      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
-      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
-      -56,  -56,  -56,  -56,  -56,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,  -56,  -56,  -56,  -56,  -56,  -56,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   94,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43,   43,   43,  -56,  -56,  -56,  -56,  -56
-    },
-
-    {
-        7,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
-      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
-      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
-      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
-      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
-      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
-      -57,  -57,  -57,  -57,  -57,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   95,   43,   43,   43,   43,   43,
-
-       43,  -57,  -57,  -57,  -57,  -57,  -57,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  -57,  -57,  -57,  -57,  -57
-    },
-
-    {
-        7,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
-      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
-      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
-      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
-      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
-      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
-
-      -58,  -58,  -58,  -58,  -58,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       96,  -58,  -58,  -58,  -58,  -58,  -58,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  -58,  -58,  -58,  -58,  -58
-    },
-
-    {
-        7,  -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,  -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,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   97,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,  -59,  -59,  -59,  -59,  -59,  -59,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  -59,  -59,  -59,  -59,  -59
-
-    },
-
-    {
-        7,  -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,
-      -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,
-      -60,  -60,  -60,  -60,  -60,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,  -60,  -60,  -60,  -60,  -60,  -60,   43,   43,   43,
-
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   98,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  -60,  -60,  -60,  -60,  -60
-    },
-
-    {
-        7,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
-      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
-      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
-      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
-      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
-      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
-      -61,  -61,  -61,  -61,  -61,   43,   43,   43,   43,   43,
-
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   99,   43,   43,   43,   43,   43,   43,
-       43,  -61,  -61,  -61,  -61,  -61,  -61,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  -61,  -61,  -61,  -61,  -61
-    },
-
-    {
-        7,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
-      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
-      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
-      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
-
-      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
-      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
-      -62,  -62,  -62,  -62,  -62,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,  100,   43,
-       43,  -62,  -62,  -62,  -62,  -62,  -62,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  -62,  -62,  -62,  -62,  -62
-    },
-
-    {
-        7,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
-
-      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
-      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
-      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
-      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
-      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
-      -63,  -63,  -63,  -63,  -63,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,  -63,  -63,  -63,  -63,  -63,  -63,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43,   43,   43,   43,   43,  101,   43,   43,   43,   43,
-       43,   43,   43,  -63,  -63,  -63,  -63,  -63
-    },
-
-    {
-        7,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
-      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
-      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
-      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
-      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
-      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
-      -64,  -64,  -64,  -64,  -64,   43,   43,   43,  102,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,  -64,  -64,  -64,  -64,  -64,  -64,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  -64,  -64,  -64,  -64,  -64
-    },
-
-    {
-        7,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
-      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
-      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
-      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
-      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
-
-      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
-      -65,  -65,  -65,  -65,  -65,   43,   43,  103,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,  -65,  -65,  -65,  -65,  -65,  -65,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  -65,  -65,  -65,  -65,  -65
-    },
-
-    {
-        7,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
-      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
-
-      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
-      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
-      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
-      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
-      -66,  -66,  -66,  -66,  -66,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,  104,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,  -66,  -66,  -66,  -66,  -66,  -66,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43,   43,   43,  -66,  -66,  -66,  -66,  -66
-    },
-
-    {
-        7,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-      -67,  -67,  -67,  -67,  -67,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43,  -67,  -67,  -67,  -67,  -67,  -67,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,  105,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  -67,  -67,  -67,  -67,  -67
-    },
-
-    {
-        7,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-
-      -68,  -68,  -68,  -68,  -68,  106,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,  -68,  -68,  -68,  -68,  -68,  -68,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  -68,  -68,  -68,  -68,  -68
-    },
-
-    {
-        7,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-
-      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-      -69,  -69,  -69,  -69,  -69,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,  -69,  -69,  -69,  -69,  -69,  -69,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  -69,  -69,  -69,  -69,  -69
-
-    },
-
-    {
-        7,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
-      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
-      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
-      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
-      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
-      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
-      -70,  -70,  -70,  -70,  -70,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,  -70,  -70,  -70,  -70,  -70,  -70,   43,   43,   43,
-
-       43,   43,   43,  107,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  -70,  -70,  -70,  -70,  -70
-    },
-
-    {
-        7,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
-      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
-      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
-      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
-      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
-      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
-      -71,  -71,  -71,  -71,  -71,   43,   43,   43,   43,   43,
-
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,  -71,  -71,  -71,  -71,  -71,  -71,   43,   43,  108,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  -71,  -71,  -71,  -71,  -71
-    },
-
-    {
-        7,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
-      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
-      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
-      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
-
-      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
-      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
-      -72,  -72,  -72,  -72,  -72,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,  -72,  -72,  -72,  -72,  -72,  -72,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,  109,   43,  -72,  -72,  -72,  -72,  -72
-    },
-
-    {
-        7,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
-
-      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
-      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
-      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
-      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
-      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
-      -73,  -73,  -73,  -73,  -73,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,  -73,  -73,  -73,  -73,  -73,  -73,   43,   43,   43,
-       43,   43,   43,  110,   43,   43,   43,   43,   43,   43,
-
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  -73,  -73,  -73,  -73,  -73
-    },
-
-    {
-        7,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
-      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
-      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
-      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
-      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
-      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
-      -74,  -74,  -74,  -74,  -74,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,  -74,  -74,  -74,  -74,  -74,  -74,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,  111,   43,   43,   43,
-       43,   43,   43,  -74,  -74,  -74,  -74,  -74
-    },
-
-    {
-        7,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
-      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
-      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
-      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
-      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
-
-      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
-      -75,  -75,  -75,  -75,  -75,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,  -75,  -75,  -75,  -75,  -75,  -75,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-      112,   43,   43,  -75,  -75,  -75,  -75,  -75
-    },
-
-    {
-        7,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
-      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
-
-      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
-      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
-      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
-      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
-      -76,  -76,  -76,  -76,  -76,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,  -76,  -76,  -76,  -76,  -76,  -76,   43,   43,   43,
-      113,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43,   43,   43,  -76,  -76,  -76,  -76,  -76
-    },
-
-    {
-        7,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
-      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
-      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
-      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
-      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
-      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
-      -77,  -77,  -77,  -77,  -77,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43,  -77,  -77,  -77,  -77,  -77,  -77,   43,   43,  114,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  -77,  -77,  -77,  -77,  -77
-    },
-
-    {
-        7,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
-      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
-      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
-      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
-      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
-      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
-
-      -78,  -78,  -78,  -78,  -78,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,  -78,  -78,  -78,  -78,  -78,  -78,  115,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  -78,  -78,  -78,  -78,  -78
-    },
-
-    {
-        7,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
-      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
-      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
-
-      -79,  -79,   79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
-      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
-      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
-      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
-      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
-      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
-      -79,   80,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
-      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
-      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
-      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79
-
-    },
-
-    {
-        7,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
-      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
-      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
-      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
-      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
-      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
-      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
-      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
-      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
-      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
-
-      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
-      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
-      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80
-    },
-
-    {
-        7,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
-      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
-      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
-      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
-      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
-      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
-      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
-
-      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
-      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
-      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
-      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
-      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
-      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81
-    },
-
-    {
-        7,   81,   81,   81,   81,   81,   81,   81,   81,   81,
-       81,   81,   81,   81,   81,   81,   81,   81,   81,   81,
-       81,   81,   81,   81,   81,   81,   81,   81,   81,   81,
-       81,   81,   82,   81,   81,   81,   81,   81,   81,   81,
-
-       81,   81,   81,   81,   81,   81,   81,   81,   81,   81,
-       81,   81,   81,   81,   81,   81,   81,   81,   81,   81,
-       81,   81,   81,   81,   81,   83,   83,   83,   83,   83,
-       83,   83,   83,   83,   83,   83,   83,   83,   83,   83,
-       83,   83,   83,   83,   83,   83,   83,   83,   83,   83,
-       83,   81,   81,   81,   81,   81,   81,   83,   83,   83,
-       83,   83,   83,   83,   83,   83,   83,   83,   83,   83,
-       83,   83,   83,   83,   83,   83,   83,   83,   83,   83,
-       83,   83,   83,   81,   81,   81,   81,   81
-    },
-
-    {
-        7,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
-
-      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
-      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
-      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
-      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
-      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
-      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
-      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
-      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
-      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
-      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
-
-      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
-      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83
-    },
-
-    {
-        7,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
-      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
-      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
-      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
-      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
-      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
-      -84,  -84,  -84,  -84,  -84,   84,   84,   84,   84,   84,
-       84,   84,   84,   84,   84,   84,   84,   84,   84,   84,
-
-       84,   84,   84,   84,   84,   84,   84,   84,   84,   84,
-       84,  -84,  -84,  -84,  -84,  -84,  -84,   84,   84,   84,
-       84,   84,   84,   84,   84,   84,   84,   84,   84,   84,
-       84,   84,   84,   84,   84,   84,   84,   84,   84,   84,
-       84,   84,   84,  -84,  -84,  -84,  -84,  -84
-    },
-
-    {
-        7,   85,   85,   85,   85,   85,   85,   85,   85,   85,
-      -85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
-       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
-       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
-       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
-
-       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
-       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
-       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
-       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
-       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
-       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
-       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
-       85,   85,   85,   85,   85,   85,   85,   85
-    },
-
-    {
-        7,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
-      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
-
-      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
-      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
-      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
-      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
-      -86,  -86,  -86,  -86,  -86,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,  116,   43,   43,
-       43,   43,   43,  117,   43,   43,   43,   43,   43,   43,
-       43,  -86,  -86,  -86,  -86,  -86,  -86,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43,   43,   43,  -86,  -86,  -86,  -86,  -86
-    },
-
-    {
-        7,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-      -87,  -87,  -87,  -87,  -87,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,  118,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43,  -87,  -87,  -87,  -87,  -87,  -87,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  -87,  -87,  -87,  -87,  -87
-    },
-
-    {
-        7,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
-      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
-      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
-      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
-      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
-      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
-
-      -88,  -88,  -88,  -88,  -88,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,  -88,  -88,  -88,  -88,  -88,  -88,   43,   43,   43,
-       43,  119,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  -88,  -88,  -88,  -88,  -88
-    },
-
-    {
-        7,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-
-      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-      -89,  -89,  -89,  -89,  -89,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  120,   43,   43,   43,   43,   43,   43,
-       43,  -89,  -89,  -89,  -89,  -89,  -89,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  -89,  -89,  -89,  -89,  -89
-
-    },
-
-    {
-        7,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
-      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
-      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
-      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
-      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
-      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
-      -90,  -90,  -90,  -90,  -90,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,  121,   43,   43,   43,   43,   43,   43,   43,
-       43,  -90,  -90,  -90,  -90,  -90,  -90,   43,   43,   43,
-
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  -90,  -90,  -90,  -90,  -90
-    },
-
-    {
-        7,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
-      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
-      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
-      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
-      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
-      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
-      -91,  -91,  -91,  -91,  -91,   43,   43,   43,   43,   43,
-
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,  -91,  -91,  -91,  -91,  -91,  -91,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  -91,  -91,  -91,  -91,  -91
-    },
-
-    {
-        7,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
-      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
-      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
-      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
-
-      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
-      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
-      -92,  -92,  -92,  -92,  -92,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,  122,   43,   43,   43,
-       43,  -92,  -92,  -92,  -92,  -92,  -92,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  -92,  -92,  -92,  -92,  -92
-    },
-
-    {
-        7,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-
-      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-      -93,  -93,  -93,  -93,  -93,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,  -93,  -93,  -93,  -93,  -93,  -93,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  -93,  -93,  -93,  -93,  -93
-    },
-
-    {
-        7,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
-      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
-      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
-      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
-      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
-      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
-      -94,  -94,  -94,  -94,  -94,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,  -94,  -94,  -94,  -94,  -94,  -94,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,  123,   43,
-       43,   43,   43,  -94,  -94,  -94,  -94,  -94
-    },
-
-    {
-        7,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
-      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
-      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
-      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
-      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
-
-      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
-      -95,  -95,  -95,  -95,  -95,   43,   43,   43,   43,  124,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,  125,   43,   43,   43,   43,   43,   43,   43,
-       43,  -95,  -95,  -95,  -95,  -95,  -95,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  -95,  -95,  -95,  -95,  -95
-    },
-
-    {
-        7,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
-      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
-
-      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
-      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
-      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
-      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
-      -96,  -96,  -96,  -96,  -96,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,  -96,  -96,  -96,  -96,  -96,  -96,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43,   43,   43,  -96,  -96,  -96,  -96,  -96
-    },
-
-    {
-        7,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
-      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
-      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
-      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
-      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
-      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
-      -97,  -97,  -97,  -97,  -97,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43,  -97,  -97,  -97,  -97,  -97,  -97,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  -97,  -97,  -97,  -97,  -97
-    },
-
-    {
-        7,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
-      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
-      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
-      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
-      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
-      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
-
-      -98,  -98,  -98,  -98,  -98,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,  -98,  -98,  -98,  -98,  -98,  -98,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  -98,  -98,  -98,  -98,  -98
-    },
-
-    {
-        7,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-
-      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-      -99,  -99,  -99,  -99,  -99,   43,   43,  126,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,  -99,  -99,  -99,  -99,  -99,  -99,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  -99,  -99,  -99,  -99,  -99
-
-    },
-
-    {
-        7, -100, -100, -100, -100, -100, -100, -100, -100, -100,
-     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
-     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
-     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
-     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
-     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
-     -100, -100, -100, -100, -100,   43,   43,   43,   43,  127,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -100, -100, -100, -100, -100, -100,   43,   43,   43,
-
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -100, -100, -100, -100, -100
-    },
-
-    {
-        7, -101, -101, -101, -101, -101, -101, -101, -101, -101,
-     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
-     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
-     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
-     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
-     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
-     -101, -101, -101, -101, -101,   43,   43,   43,   43,   43,
-
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -101, -101, -101, -101, -101, -101,   43,   43,  128,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -101, -101, -101, -101, -101
-    },
-
-    {
-        7, -102, -102, -102, -102, -102, -102, -102, -102, -102,
-     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
-     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
-     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
-
-     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
-     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
-     -102, -102, -102, -102, -102,   43,   43,   43,   43,   43,
-       43,   43,   43,  129,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -102, -102, -102, -102, -102, -102,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -102, -102, -102, -102, -102
-    },
-
-    {
-        7, -103, -103, -103, -103, -103, -103, -103, -103, -103,
-
-     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
-     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
-     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
-     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
-     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
-     -103, -103, -103, -103, -103,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,  130,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -103, -103, -103, -103, -103, -103,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -103, -103, -103, -103, -103
-    },
-
-    {
-        7, -104, -104, -104, -104, -104, -104, -104, -104, -104,
-     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
-     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
-     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
-     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
-     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
-     -104, -104, -104, -104, -104,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43,   43,   43,   43,  131,   43,   43,   43,   43,   43,
-       43, -104, -104, -104, -104, -104, -104,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -104, -104, -104, -104, -104
-    },
-
-    {
-        7, -105, -105, -105, -105, -105, -105, -105, -105, -105,
-     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
-     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
-     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
-     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
-
-     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
-     -105, -105, -105, -105, -105,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -105, -105, -105, -105, -105, -105,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,  132,   43,   43,   43,
-       43,   43,   43, -105, -105, -105, -105, -105
-    },
-
-    {
-        7, -106, -106, -106, -106, -106, -106, -106, -106, -106,
-     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
-
-     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
-     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
-     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
-     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
-     -106, -106, -106, -106, -106,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,  133,   43,   43,   43,   43,   43,   43,   43,
-       43, -106, -106, -106, -106, -106, -106,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43,   43,   43, -106, -106, -106, -106, -106
-    },
-
-    {
-        7, -107, -107, -107, -107, -107, -107, -107, -107, -107,
-     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
-     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
-     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
-     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
-     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
-     -107, -107, -107, -107, -107,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43, -107, -107, -107, -107, -107, -107,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,  134,   43,   43,   43,   43,
-       43,   43,   43, -107, -107, -107, -107, -107
-    },
-
-    {
-        7, -108, -108, -108, -108, -108, -108, -108, -108, -108,
-     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
-     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
-     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
-     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
-     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
-
-     -108, -108, -108, -108, -108,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -108, -108, -108, -108, -108, -108,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,  135,
-       43,   43,   43,   43,   43,  136,   43,   43,   43,   43,
-       43,   43,   43, -108, -108, -108, -108, -108
-    },
-
-    {
-        7, -109, -109, -109, -109, -109, -109, -109, -109, -109,
-     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
-     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
-
-     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
-     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
-     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
-     -109, -109, -109, -109, -109,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -109, -109, -109, -109, -109, -109,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,  137,   43,   43,   43,   43,
-       43,   43,   43, -109, -109, -109, -109, -109
-
-    },
-
-    {
-        7, -110, -110, -110, -110, -110, -110, -110, -110, -110,
-     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
-     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
-     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
-     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
-     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
-     -110, -110, -110, -110, -110,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -110, -110, -110, -110, -110, -110,   43,   43,   43,
-
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,  138,   43,   43,   43,   43,   43,
-       43,   43,   43, -110, -110, -110, -110, -110
-    },
-
-    {
-        7, -111, -111, -111, -111, -111, -111, -111, -111, -111,
-     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
-     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
-     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
-     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
-     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
-     -111, -111, -111, -111, -111,   43,   43,   43,   43,   43,
-
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -111, -111, -111, -111, -111, -111,   43,   43,   43,
-       43,  139,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,  140,   43,   43,   43,   43,   43,
-       43,   43,   43, -111, -111, -111, -111, -111
-    },
-
-    {
-        7, -112, -112, -112, -112, -112, -112, -112, -112, -112,
-     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
-     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
-     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
-
-     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
-     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
-     -112, -112, -112, -112, -112,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -112, -112, -112, -112, -112, -112,   43,   43,   43,
-       43,  141,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -112, -112, -112, -112, -112
-    },
-
-    {
-        7, -113, -113, -113, -113, -113, -113, -113, -113, -113,
-
-     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
-     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
-     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
-     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
-     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
-     -113, -113, -113, -113, -113,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -113, -113, -113, -113, -113, -113,   43,   43,   43,
-       43,   43,   43,   43,   43,  142,   43,   43,   43,   43,
-
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -113, -113, -113, -113, -113
-    },
-
-    {
-        7, -114, -114, -114, -114, -114, -114, -114, -114, -114,
-     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
-     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
-     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
-     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
-     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
-     -114, -114, -114, -114, -114,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -114, -114, -114, -114, -114, -114,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,  143,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -114, -114, -114, -114, -114
-    },
-
-    {
-        7, -115, -115, -115, -115, -115, -115, -115, -115, -115,
-     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
-     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
-     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
-     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
-
-     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
-     -115, -115, -115, -115, -115,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -115, -115, -115, -115, -115, -115,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,  144,   43,   43,   43,   43,   43,
-       43,   43,   43, -115, -115, -115, -115, -115
-    },
-
-    {
-        7, -116, -116, -116, -116, -116, -116, -116, -116, -116,
-     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
-
-     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
-     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
-     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
-     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
-     -116, -116, -116, -116, -116,   43,   43,   43,   43,   43,
-       43,   43,   43,  145,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -116, -116, -116, -116, -116, -116,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43,   43,   43, -116, -116, -116, -116, -116
-    },
-
-    {
-        7, -117, -117, -117, -117, -117, -117, -117, -117, -117,
-     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
-     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
-     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
-     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
-     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
-     -117, -117, -117, -117, -117,   43,   43,   43,   43,  146,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43, -117, -117, -117, -117, -117, -117,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -117, -117, -117, -117, -117
-    },
-
-    {
-        7, -118, -118, -118, -118, -118, -118, -118, -118, -118,
-     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
-     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
-     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
-     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
-     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
-
-     -118, -118, -118, -118, -118,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -118, -118, -118, -118, -118, -118,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -118, -118, -118, -118, -118
-    },
-
-    {
-        7, -119, -119, -119, -119, -119, -119, -119, -119, -119,
-     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
-     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
-
-     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
-     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
-     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
-     -119, -119, -119, -119, -119,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -119, -119, -119, -119, -119, -119,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -119, -119, -119, -119, -119
-
-    },
-
-    {
-        7, -120, -120, -120, -120, -120, -120, -120, -120, -120,
-     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
-     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
-     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
-     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
-     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
-     -120, -120, -120, -120, -120,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -120, -120, -120, -120, -120, -120,   43,   43,   43,
-
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -120, -120, -120, -120, -120
-    },
-
-    {
-        7, -121, -121, -121, -121, -121, -121, -121, -121, -121,
-     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
-     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
-     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
-     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
-     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
-     -121, -121, -121, -121, -121,   43,   43,   43,   43,  147,
-
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -121, -121, -121, -121, -121, -121,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -121, -121, -121, -121, -121
-    },
-
-    {
-        7, -122, -122, -122, -122, -122, -122, -122, -122, -122,
-     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
-     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
-     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
-
-     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
-     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
-     -122, -122, -122, -122, -122,   43,   43,   43,   43,   43,
-       43,   43,   43,  148,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -122, -122, -122, -122, -122, -122,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -122, -122, -122, -122, -122
-    },
-
-    {
-        7, -123, -123, -123, -123, -123, -123, -123, -123, -123,
-
-     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
-     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
-     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
-     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
-     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
-     -123, -123, -123, -123, -123,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -123, -123, -123, -123, -123, -123,   43,   43,   43,
-       43,   43,   43,   43,   43,  149,   43,   43,   43,   43,
-
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -123, -123, -123, -123, -123
-    },
-
-    {
-        7, -124, -124, -124, -124, -124, -124, -124, -124, -124,
-     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
-     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
-     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
-     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
-     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
-     -124, -124, -124, -124, -124,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43,   43,  150,   43,   43,   43,   43,   43,   43,   43,
-       43, -124, -124, -124, -124, -124, -124,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -124, -124, -124, -124, -124
-    },
-
-    {
-        7, -125, -125, -125, -125, -125, -125, -125, -125, -125,
-     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
-     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
-     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
-     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
-
-     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
-     -125, -125, -125, -125, -125,   43,   43,   43,   43,  151,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -125, -125, -125, -125, -125, -125,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -125, -125, -125, -125, -125
-    },
-
-    {
-        7, -126, -126, -126, -126, -126, -126, -126, -126, -126,
-     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
-
-     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
-     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
-     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
-     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
-     -126, -126, -126, -126, -126,  152,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -126, -126, -126, -126, -126, -126,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43,   43,   43, -126, -126, -126, -126, -126
-    },
-
-    {
-        7, -127, -127, -127, -127, -127, -127, -127, -127, -127,
-     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
-     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
-     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
-     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
-     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
-     -127, -127, -127, -127, -127,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,  153,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43, -127, -127, -127, -127, -127, -127,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -127, -127, -127, -127, -127
-    },
-
-    {
-        7, -128, -128, -128, -128, -128, -128, -128, -128, -128,
-     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
-     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
-     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
-     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
-     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
-
-     -128, -128, -128, -128, -128,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -128, -128, -128, -128, -128, -128,  154,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -128, -128, -128, -128, -128
-    },
-
-    {
-        7, -129, -129, -129, -129, -129, -129, -129, -129, -129,
-     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
-     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
-
-     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
-     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
-     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
-     -129, -129, -129, -129, -129,  155,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -129, -129, -129, -129, -129, -129,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -129, -129, -129, -129, -129
-
-    },
-
-    {
-        7, -130, -130, -130, -130, -130, -130, -130, -130, -130,
-     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
-     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
-     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
-     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
-     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
-     -130, -130, -130, -130, -130,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,  156,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -130, -130, -130, -130, -130, -130,   43,   43,   43,
-
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -130, -130, -130, -130, -130
-    },
-
-    {
-        7, -131, -131, -131, -131, -131, -131, -131, -131, -131,
-     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
-     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
-     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
-     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
-     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
-     -131, -131, -131, -131, -131,   43,   43,   43,   43,   43,
-
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  157,   43,   43,   43,   43,   43,   43,
-       43, -131, -131, -131, -131, -131, -131,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -131, -131, -131, -131, -131
-    },
-
-    {
-        7, -132, -132, -132, -132, -132, -132, -132, -132, -132,
-     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
-     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
-     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
-
-     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
-     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
-     -132, -132, -132, -132, -132,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -132, -132, -132, -132, -132, -132,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,  158,   43,   43,   43,   43,
-       43,   43,   43, -132, -132, -132, -132, -132
-    },
-
-    {
-        7, -133, -133, -133, -133, -133, -133, -133, -133, -133,
-
-     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
-     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
-     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
-     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
-     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
-     -133, -133, -133, -133, -133,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  159,   43,   43,   43,   43,   43,   43,
-       43, -133, -133, -133, -133, -133, -133,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -133, -133, -133, -133, -133
-    },
-
-    {
-        7, -134, -134, -134, -134, -134, -134, -134, -134, -134,
-     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
-     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
-     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
-     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
-     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
-     -134, -134, -134, -134, -134,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -134, -134, -134, -134, -134, -134,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,  160,   43,   43,   43,
-       43,   43,   43, -134, -134, -134, -134, -134
-    },
-
-    {
-        7, -135, -135, -135, -135, -135, -135, -135, -135, -135,
-     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
-     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
-     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
-     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
-
-     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
-     -135, -135, -135, -135, -135,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -135, -135, -135, -135, -135, -135,   43,   43,   43,
-       43,   43,   43,   43,   43,  161,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -135, -135, -135, -135, -135
-    },
-
-    {
-        7, -136, -136, -136, -136, -136, -136, -136, -136, -136,
-     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
-
-     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
-     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
-     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
-     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
-     -136, -136, -136, -136, -136,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -136, -136, -136, -136, -136, -136,   43,   43,   43,
-       43,  162,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43,   43,   43, -136, -136, -136, -136, -136
-    },
-
-    {
-        7, -137, -137, -137, -137, -137, -137, -137, -137, -137,
-     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
-     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
-     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
-     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
-     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
-     -137, -137, -137, -137, -137,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43, -137, -137, -137, -137, -137, -137,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -137, -137, -137, -137, -137
-    },
-
-    {
-        7, -138, -138, -138, -138, -138, -138, -138, -138, -138,
-     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
-     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
-     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
-     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
-     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
-
-     -138, -138, -138, -138, -138,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -138, -138, -138, -138, -138, -138,   43,   43,   43,
-       43,  163,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -138, -138, -138, -138, -138
-    },
-
-    {
-        7, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-
-     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-     -139, -139, -139, -139, -139,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -139, -139, -139, -139, -139, -139,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,  164,   43,   43,   43,   43,   43,
-       43,   43,   43, -139, -139, -139, -139, -139
-
-    },
-
-    {
-        7, -140, -140, -140, -140, -140, -140, -140, -140, -140,
-     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
-     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
-     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
-     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
-     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
-     -140, -140, -140, -140, -140,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -140, -140, -140, -140, -140, -140,   43,   43,   43,
-
-       43,  165,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -140, -140, -140, -140, -140
-    },
-
-    {
-        7, -141, -141, -141, -141, -141, -141, -141, -141, -141,
-     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
-     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
-     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
-     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
-     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
-     -141, -141, -141, -141, -141,   43,   43,   43,   43,   43,
-
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -141, -141, -141, -141, -141, -141,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,  166,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -141, -141, -141, -141, -141
-    },
-
-    {
-        7, -142, -142, -142, -142, -142, -142, -142, -142, -142,
-     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
-     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
-     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
-
-     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
-     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
-     -142, -142, -142, -142, -142,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -142, -142, -142, -142, -142, -142,  167,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -142, -142, -142, -142, -142
-    },
-
-    {
-        7, -143, -143, -143, -143, -143, -143, -143, -143, -143,
-
-     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
-     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
-     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
-     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
-     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
-     -143, -143, -143, -143, -143,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -143, -143, -143, -143, -143, -143,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-      168,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -143, -143, -143, -143, -143
-    },
-
-    {
-        7, -144, -144, -144, -144, -144, -144, -144, -144, -144,
-     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
-     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
-     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
-     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
-     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
-     -144, -144, -144, -144, -144,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -144, -144, -144, -144, -144, -144,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   69,   43,   43,   43,   43,
-       43,   43,   43, -144, -144, -144, -144, -144
-    },
-
-    {
-        7, -145, -145, -145, -145, -145, -145, -145, -145, -145,
-     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
-     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
-     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
-     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
-
-     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
-     -145, -145, -145, -145, -145,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,  169,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -145, -145, -145, -145, -145, -145,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -145, -145, -145, -145, -145
-    },
-
-    {
-        7, -146, -146, -146, -146, -146, -146, -146, -146, -146,
-     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
-
-     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
-     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
-     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
-     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
-     -146, -146, -146, -146, -146,   43,   43,  170,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -146, -146, -146, -146, -146, -146,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43,   43,   43, -146, -146, -146, -146, -146
-    },
-
-    {
-        7, -147, -147, -147, -147, -147, -147, -147, -147, -147,
-     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
-     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
-     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
-     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
-     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
-     -147, -147, -147, -147, -147,   43,   43,   43,   43,  171,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43, -147, -147, -147, -147, -147, -147,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -147, -147, -147, -147, -147
-    },
-
-    {
-        7, -148, -148, -148, -148, -148, -148, -148, -148, -148,
-     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
-     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
-     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
-     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
-     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
-
-     -148, -148, -148, -148, -148,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,  172,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -148, -148, -148, -148, -148, -148,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -148, -148, -148, -148, -148
-    },
-
-    {
-        7, -149, -149, -149, -149, -149, -149, -149, -149, -149,
-     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
-     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
-
-     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
-     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
-     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
-     -149, -149, -149, -149, -149,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -149, -149, -149, -149, -149, -149,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-      173,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -149, -149, -149, -149, -149
-
-    },
-
-    {
-        7, -150, -150, -150, -150, -150, -150, -150, -150, -150,
-     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
-     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
-     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
-     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
-     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
-     -150, -150, -150, -150, -150,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  174,   43,   43,   43,   43,   43,   43,
-       43, -150, -150, -150, -150, -150, -150,   43,   43,   43,
-
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -150, -150, -150, -150, -150
-    },
-
-    {
-        7, -151, -151, -151, -151, -151, -151, -151, -151, -151,
-     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
-     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
-     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
-     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
-     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
-     -151, -151, -151, -151, -151,   43,   43,   43,   43,   43,
-
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  175,   43,   43,   43,   43,   43,   43,
-       43, -151, -151, -151, -151, -151, -151,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -151, -151, -151, -151, -151
-    },
-
-    {
-        7, -152, -152, -152, -152, -152, -152, -152, -152, -152,
-     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
-     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
-     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
-
-     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
-     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
-     -152, -152, -152, -152, -152,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,  176,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -152, -152, -152, -152, -152, -152,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -152, -152, -152, -152, -152
-    },
-
-    {
-        7, -153, -153, -153, -153, -153, -153, -153, -153, -153,
-
-     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
-     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
-     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
-     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
-     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
-     -153, -153, -153, -153, -153,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  177,   43,   43,   43,   43,   43,   43,
-       43, -153, -153, -153, -153, -153, -153,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -153, -153, -153, -153, -153
-    },
-
-    {
-        7, -154, -154, -154, -154, -154, -154, -154, -154, -154,
-     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
-     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
-     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
-     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
-     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
-     -154, -154, -154, -154, -154,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -154, -154, -154, -154, -154, -154,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,  178,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -154, -154, -154, -154, -154
-    },
-
-    {
-        7, -155, -155, -155, -155, -155, -155, -155, -155, -155,
-     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
-     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
-     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
-     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
-
-     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
-     -155, -155, -155, -155, -155,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,  179,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -155, -155, -155, -155, -155, -155,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -155, -155, -155, -155, -155
-    },
-
-    {
-        7, -156, -156, -156, -156, -156, -156, -156, -156, -156,
-     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
-
-     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
-     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
-     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
-     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
-     -156, -156, -156, -156, -156,   43,   43,   43,  180,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -156, -156, -156, -156, -156, -156,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43,   43,   43, -156, -156, -156, -156, -156
-    },
-
-    {
-        7, -157, -157, -157, -157, -157, -157, -157, -157, -157,
-     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
-     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
-     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
-     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
-     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
-     -157, -157, -157, -157, -157,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43, -157, -157, -157, -157, -157, -157,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -157, -157, -157, -157, -157
-    },
-
-    {
-        7, -158, -158, -158, -158, -158, -158, -158, -158, -158,
-     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
-     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
-     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
-     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
-     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
-
-     -158, -158, -158, -158, -158,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -158, -158, -158, -158, -158, -158,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -158, -158, -158, -158, -158
-    },
-
-    {
-        7, -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, -159, -159, -159,
-     -159, -159, -159, -159, -159,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -159, -159, -159, -159, -159, -159,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -159, -159, -159, -159, -159
-
-    },
-
-    {
-        7, -160, -160, -160, -160, -160, -160, -160, -160, -160,
-     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
-     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
-     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
-     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
-     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
-     -160, -160, -160, -160, -160,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -160, -160, -160, -160, -160, -160,   43,   43,   43,
-
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,  181,   43,   43,   43,   43,   43,
-       43,   43,   43, -160, -160, -160, -160, -160
-    },
-
-    {
-        7, -161, -161, -161, -161, -161, -161, -161, -161, -161,
-     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
-     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
-     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
-     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
-     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
-     -161, -161, -161, -161, -161,   43,   43,   43,   43,   43,
-
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -161, -161, -161, -161, -161, -161,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-      182,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -161, -161, -161, -161, -161
-    },
-
-    {
-        7, -162, -162, -162, -162, -162, -162, -162, -162, -162,
-     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
-     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
-     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
-
-     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
-     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
-     -162, -162, -162, -162, -162,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -162, -162, -162, -162, -162, -162,   43,   43,  183,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -162, -162, -162, -162, -162
-    },
-
-    {
-        7, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-
-     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-     -163, -163, -163, -163, -163,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -163, -163, -163, -163, -163, -163,   43,   43,   43,
-       43,  184,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -163, -163, -163, -163, -163
-    },
-
-    {
-        7, -164, -164, -164, -164, -164, -164, -164, -164, -164,
-     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
-     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
-     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
-     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
-     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
-     -164, -164, -164, -164, -164,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -164, -164, -164, -164, -164, -164,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,  185,   43,   43,   43,   43,
-       43,   43,   43, -164, -164, -164, -164, -164
-    },
-
-    {
-        7, -165, -165, -165, -165, -165, -165, -165, -165, -165,
-     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
-     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
-     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
-     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
-
-     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
-     -165, -165, -165, -165, -165,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -165, -165, -165, -165, -165, -165,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,  186,   43,   43,   43,   43,
-       43,   43,   43, -165, -165, -165, -165, -165
-    },
-
-    {
-        7, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-
-     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-     -166, -166, -166, -166, -166,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -166, -166, -166, -166, -166, -166,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,  177,   43,   43,   43,   43,
-
-       43,   43,   43, -166, -166, -166, -166, -166
-    },
-
-    {
-        7, -167, -167, -167, -167, -167, -167, -167, -167, -167,
-     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
-     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
-     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
-     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
-     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
-     -167, -167, -167, -167, -167,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43, -167, -167, -167, -167, -167, -167,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-      187,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -167, -167, -167, -167, -167
-    },
-
-    {
-        7, -168, -168, -168, -168, -168, -168, -168, -168, -168,
-     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
-     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
-     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
-     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
-     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
-
-     -168, -168, -168, -168, -168,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -168, -168, -168, -168, -168, -168,   43,   43,   43,
-      188,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -168, -168, -168, -168, -168
-    },
-
-    {
-        7, -169, -169, -169, -169, -169, -169, -169, -169, -169,
-     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
-     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
-
-     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
-     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
-     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
-     -169, -169, -169, -169, -169,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  189,   43,   43,   43,   43,   43,   43,
-       43, -169, -169, -169, -169, -169, -169,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -169, -169, -169, -169, -169
-
-    },
-
-    {
-        7, -170, -170, -170, -170, -170, -170, -170, -170, -170,
-     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
-     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
-     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
-     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
-     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
-     -170, -170, -170, -170, -170,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  190,   43,   43,   43,   43,   43,   43,
-       43, -170, -170, -170, -170, -170, -170,   43,   43,   43,
-
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -170, -170, -170, -170, -170
-    },
-
-    {
-        7, -171, -171, -171, -171, -171, -171, -171, -171, -171,
-     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
-     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
-     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
-     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
-     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
-     -171, -171, -171, -171, -171,   43,   43,   43,   43,   43,
-
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  191,   43,   43,   43,   43,   43,   43,
-       43, -171, -171, -171, -171, -171, -171,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -171, -171, -171, -171, -171
-    },
-
-    {
-        7, -172, -172, -172, -172, -172, -172, -172, -172, -172,
-     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
-     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
-     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
-
-     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
-     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
-     -172, -172, -172, -172, -172,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  192,   43,   43,   43,   43,   43,   43,
-       43, -172, -172, -172, -172, -172, -172,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -172, -172, -172, -172, -172
-    },
-
-    {
-        7, -173, -173, -173, -173, -173, -173, -173, -173, -173,
-
-     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
-     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
-     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
-     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
-     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
-     -173, -173, -173, -173, -173,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -173, -173, -173, -173, -173, -173,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43,   43,   43,   43,   43,  193,   43,   43,   43,   43,
-       43,   43,   43, -173, -173, -173, -173, -173
-    },
-
-    {
-        7, -174, -174, -174, -174, -174, -174, -174, -174, -174,
-     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
-     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
-     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
-     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
-     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
-     -174, -174, -174, -174, -174,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -174, -174, -174, -174, -174, -174,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -174, -174, -174, -174, -174
-    },
-
-    {
-        7, -175, -175, -175, -175, -175, -175, -175, -175, -175,
-     -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
-     -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
-     -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
-     -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
-
-     -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
-     -175, -175, -175, -175, -175,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -175, -175, -175, -175, -175, -175,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -175, -175, -175, -175, -175
-    },
-
-    {
-        7, -176, -176, -176, -176, -176, -176, -176, -176, -176,
-     -176, -176, -176, -176, -176, -176, -176, -176, -176, -176,
-
-     -176, -176, -176, -176, -176, -176, -176, -176, -176, -176,
-     -176, -176, -176, -176, -176, -176, -176, -176, -176, -176,
-     -176, -176, -176, -176, -176, -176, -176, -176, -176, -176,
-     -176, -176, -176, -176, -176, -176, -176, -176, -176, -176,
-     -176, -176, -176, -176, -176,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  194,   43,   43,   43,   43,   43,   43,
-       43, -176, -176, -176, -176, -176, -176,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43,   43,   43, -176, -176, -176, -176, -176
-    },
-
-    {
-        7, -177, -177, -177, -177, -177, -177, -177, -177, -177,
-     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
-     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
-     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
-     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
-     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
-     -177, -177, -177, -177, -177,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43, -177, -177, -177, -177, -177, -177,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -177, -177, -177, -177, -177
-    },
-
-    {
-        7, -178, -178, -178, -178, -178, -178, -178, -178, -178,
-     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
-     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
-     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
-     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
-     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
-
-     -178, -178, -178, -178, -178,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -178, -178, -178, -178, -178, -178,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,  195,   43,   43,   43,   43,
-       43,   43,   43, -178, -178, -178, -178, -178
-    },
-
-    {
-        7, -179, -179, -179, -179, -179, -179, -179, -179, -179,
-     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
-     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
-
-     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
-     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
-     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
-     -179, -179, -179, -179, -179,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  196,   43,   43,   43,   43,   43,   43,
-       43, -179, -179, -179, -179, -179, -179,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -179, -179, -179, -179, -179
-
-    },
-
-    {
-        7, -180, -180, -180, -180, -180, -180, -180, -180, -180,
-     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
-     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
-     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
-     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
-     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
-     -180, -180, -180, -180, -180,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,  197,   43,   43,   43,   43,   43,   43,
-       43, -180, -180, -180, -180, -180, -180,   43,   43,   43,
-
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -180, -180, -180, -180, -180
-    },
-
-    {
-        7, -181, -181, -181, -181, -181, -181, -181, -181, -181,
-     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
-     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
-     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
-     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
-     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
-     -181, -181, -181, -181, -181,   43,   43,   43,   43,   43,
-
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -181, -181, -181, -181, -181, -181,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,  198,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -181, -181, -181, -181, -181
-    },
-
-    {
-        7, -182, -182, -182, -182, -182, -182, -182, -182, -182,
-     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
-     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
-     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
-
-     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
-     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
-     -182, -182, -182, -182, -182,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -182, -182, -182, -182, -182, -182,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,  189,   43,   43,   43,   43,
-       43,   43,   43, -182, -182, -182, -182, -182
-    },
-
-    {
-        7, -183, -183, -183, -183, -183, -183, -183, -183, -183,
-
-     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
-     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
-     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
-     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
-     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
-     -183, -183, -183, -183, -183,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -183, -183, -183, -183, -183, -183,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43,   43,   43,   43,   43,  190,   43,   43,   43,   43,
-       43,   43,   43, -183, -183, -183, -183, -183
-    },
-
-    {
-        7, -184, -184, -184, -184, -184, -184, -184, -184, -184,
-     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
-     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
-     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
-     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
-     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
-     -184, -184, -184, -184, -184,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -184, -184, -184, -184, -184, -184,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,  199,   43,   43,   43,   43,
-       43,   43,   43, -184, -184, -184, -184, -184
-    },
-
-    {
-        7, -185, -185, -185, -185, -185, -185, -185, -185, -185,
-     -185, -185, -185, -185, -185, -185, -185, -185, -185, -185,
-     -185, -185, -185, -185, -185, -185, -185, -185, -185, -185,
-     -185, -185, -185, -185, -185, -185, -185, -185, -185, -185,
-     -185, -185, -185, -185, -185, -185, -185, -185, -185, -185,
-
-     -185, -185, -185, -185, -185, -185, -185, -185, -185, -185,
-     -185, -185, -185, -185, -185,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -185, -185, -185, -185, -185, -185,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -185, -185, -185, -185, -185
-    },
-
-    {
-        7, -186, -186, -186, -186, -186, -186, -186, -186, -186,
-     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
-
-     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
-     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
-     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
-     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
-     -186, -186, -186, -186, -186,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -186, -186, -186, -186, -186, -186,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43,   43,   43, -186, -186, -186, -186, -186
-    },
-
-    {
-        7, -187, -187, -187, -187, -187, -187, -187, -187, -187,
-     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
-     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
-     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
-     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
-     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
-     -187, -187, -187, -187, -187,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43, -187, -187, -187, -187, -187, -187,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,  200,   43,   43,   43,   43,
-       43,   43,   43, -187, -187, -187, -187, -187
-    },
-
-    {
-        7, -188, -188, -188, -188, -188, -188, -188, -188, -188,
-     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
-     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
-     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
-     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
-     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
-
-     -188, -188, -188, -188, -188,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -188, -188, -188, -188, -188, -188,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,  201,   43,   43,   43,   43,
-       43,   43,   43, -188, -188, -188, -188, -188
-    },
-
-    {
-        7, -189, -189, -189, -189, -189, -189, -189, -189, -189,
-     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
-     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
-
-     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
-     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
-     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
-     -189, -189, -189, -189, -189,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -189, -189, -189, -189, -189, -189,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -189, -189, -189, -189, -189
-
-    },
-
-    {
-        7, -190, -190, -190, -190, -190, -190, -190, -190, -190,
-     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
-     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
-     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
-     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
-     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
-     -190, -190, -190, -190, -190,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -190, -190, -190, -190, -190, -190,   43,   43,   43,
-
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -190, -190, -190, -190, -190
-    },
-
-    {
-        7, -191, -191, -191, -191, -191, -191, -191, -191, -191,
-     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
-     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
-     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
-     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
-     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
-     -191, -191, -191, -191, -191,   43,   43,   43,   43,   43,
-
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -191, -191, -191, -191, -191, -191,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -191, -191, -191, -191, -191
-    },
-
-    {
-        7, -192, -192, -192, -192, -192, -192, -192, -192, -192,
-     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
-     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
-     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
-
-     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
-     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
-     -192, -192, -192, -192, -192,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -192, -192, -192, -192, -192, -192,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -192, -192, -192, -192, -192
-    },
-
-    {
-        7, -193, -193, -193, -193, -193, -193, -193, -193, -193,
-
-     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
-     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
-     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
-     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
-     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
-     -193, -193, -193, -193, -193,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -193, -193, -193, -193, -193, -193,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -193, -193, -193, -193, -193
-    },
-
-    {
-        7, -194, -194, -194, -194, -194, -194, -194, -194, -194,
-     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
-     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
-     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
-     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
-     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
-     -194, -194, -194, -194, -194,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -194, -194, -194, -194, -194, -194,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -194, -194, -194, -194, -194
-    },
-
-    {
-        7, -195, -195, -195, -195, -195, -195, -195, -195, -195,
-     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
-     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
-     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
-     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
-
-     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
-     -195, -195, -195, -195, -195,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -195, -195, -195, -195, -195, -195,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -195, -195, -195, -195, -195
-    },
-
-    {
-        7, -196, -196, -196, -196, -196, -196, -196, -196, -196,
-     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
-
-     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
-     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
-     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
-     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
-     -196, -196, -196, -196, -196,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -196, -196, -196, -196, -196, -196,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43,   43,   43, -196, -196, -196, -196, -196
-    },
-
-    {
-        7, -197, -197, -197, -197, -197, -197, -197, -197, -197,
-     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
-     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
-     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
-     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
-     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
-     -197, -197, -197, -197, -197,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-
-       43, -197, -197, -197, -197, -197, -197,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -197, -197, -197, -197, -197
-    },
-
-    {
-        7, -198, -198, -198, -198, -198, -198, -198, -198, -198,
-     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
-     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
-     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
-     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
-     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
-
-     -198, -198, -198, -198, -198,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -198, -198, -198, -198, -198, -198,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,  202,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -198, -198, -198, -198, -198
-    },
-
-    {
-        7, -199, -199, -199, -199, -199, -199, -199, -199, -199,
-     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
-     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
-
-     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
-     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
-     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
-     -199, -199, -199, -199, -199,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -199, -199, -199, -199, -199, -199,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -199, -199, -199, -199, -199
-
-    },
-
-    {
-        7, -200, -200, -200, -200, -200, -200, -200, -200, -200,
-     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
-     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
-     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
-     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
-     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
-     -200, -200, -200, -200, -200,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -200, -200, -200, -200, -200, -200,   43,   43,   43,
-
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -200, -200, -200, -200, -200
-    },
-
-    {
-        7, -201, -201, -201, -201, -201, -201, -201, -201, -201,
-     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
-     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
-     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
-     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
-     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
-     -201, -201, -201, -201, -201,   43,   43,   43,   43,   43,
-
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -201, -201, -201, -201, -201, -201,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -201, -201, -201, -201, -201
-    },
-
-    {
-        7, -202, -202, -202, -202, -202, -202, -202, -202, -202,
-     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
-     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
-     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
-
-     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
-     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
-     -202, -202, -202, -202, -202,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43, -202, -202, -202, -202, -202, -202,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43, -202, -202, -202, -202, -202
-    },
-
-    } ;
-
-static yy_state_type yy_get_previous_state (void );
-static yy_state_type yy_try_NUL_trans (yy_state_type current_state  );
-static int yy_get_next_buffer (void );
-static void yy_fatal_error (yyconst char msg[]  );
-
-/* Done after the current pattern has been matched and before the
- * corresponding action - sets up wcsutrntext.
- */
-#define YY_DO_BEFORE_ACTION \
-	(yytext_ptr) = yy_bp; \
-	wcsutrnleng = (size_t) (yy_cp - yy_bp); \
-	(yy_hold_char) = *yy_cp; \
-	*yy_cp = '\0'; \
-	(yy_c_buf_p) = yy_cp;
-
-#define YY_NUM_RULES 37
-#define YY_END_OF_BUFFER 38
-/* This struct is not used in this scanner,
-   but its presence is necessary. */
-struct yy_trans_info
-	{
-	flex_int32_t yy_verify;
-	flex_int32_t yy_nxt;
-	};
-static yyconst flex_int16_t yy_accept[203] =
-    {   0,
-        0,    0,    0,    0,   36,   36,   38,    3,    2,   31,
-       31,   31,   10,   31,   14,   31,   31,   20,   31,   31,
-       31,   28,   31,   31,   31,   31,   31,   31,   31,   31,
-       31,   31,   31,   31,    2,    1,   35,   37,   35,   32,
-       36,    2,   31,   31,   31,   31,   31,   31,   31,   13,
-       15,   17,   31,   31,   19,   31,   31,   31,   31,   31,
-       31,   31,   31,   31,   31,   31,   31,   31,   30,   31,
-       31,   31,   31,   31,   31,   31,   31,   31,    2,    1,
-       33,   33,   34,   32,   36,   31,   31,   31,    9,   11,
-       12,   31,   16,   31,   31,   22,   21,   23,   31,   31,
-
-       31,   26,   27,   31,   31,   31,   31,   31,    9,   31,
-       31,   31,   31,   27,   31,   31,   31,    7,    8,    9,
-       31,   31,   31,   31,   31,   31,   31,   31,   31,   31,
-       29,   29,   30,   31,   31,   31,    9,   31,   31,   31,
-       31,   31,   31,   30,   31,   31,   31,   31,   31,   20,
-       20,   31,   25,   31,   31,   31,   29,   29,   30,   31,
-       31,   31,   31,   20,   20,   31,   31,   31,    5,    6,
-       11,   18,   18,   20,   20,   24,   25,   24,   26,   27,
-       31,   31,   31,   11,   20,   20,   26,   27,    5,    6,
-       11,   18,   18,   24,   24,   26,   27,   31,   11,   26,
-
-       27,    4
-    } ;
-
-static yyconst yy_state_type yy_NUL_trans[203] =
-    {   0,
-        8,    8,   37,   37,   41,   41,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,   81,    0,
-       85,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,   81,    0,    0,   85,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-
-        0,    0
-    } ;
-
-extern int wcsutrn_flex_debug;
-int wcsutrn_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 yymore() yymore_used_but_not_detected
-#define YY_MORE_ADJ 0
-#define YY_RESTORE_YY_MORE_OFFSET
-char *wcsutrntext;
-#line 1 "wcsutrn.l"
-/*============================================================================
-
-  WCSLIB 4.10 - an implementation of the FITS WCS standard.
-  Copyright (C) 1995-2012, Mark Calabretta
-
-  This file is part of WCSLIB.
-
-  WCSLIB is free software: you can redistribute it and/or modify it under the
-  terms of the GNU Lesser General Public License as published by the Free
-  Software Foundation, either version 3 of the License, or (at your option)
-  any later version.
-
-  WCSLIB 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 Lesser General Public License for
-  more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with WCSLIB.  If not, see <http://www.gnu.org/licenses/>.
-
-  Correspondence concerning WCSLIB may be directed to:
-    Internet email: mcalabre at atnf.csiro.au
-    Postal address: Dr. Mark Calabretta
-                    Australia Telescope National Facility, CSIRO
-                    PO Box 76
-                    Epping NSW 1710
-                    AUSTRALIA
-
-  Author: Mark Calabretta, Australia Telescope National Facility
-  http://www.atnf.csiro.au/~mcalabre/index.html
-  $Id: wcsutrn.c,v 4.10 2012/02/05 23:41:44 cal103 Exp $
-*=============================================================================
-*
-* wcsutrn.l is a Flex description file containing the definition of a lexical
-* scanner that translates non-standard FITS units specifications.
-*
-* It requires Flex v2.5.4 or later.
-*
-* Refer to wcsunits.h for a description of the user interface and operating
-* notes.
-*
-*===========================================================================*/
-/* Options. */
-/* Exclusive start states. */
-
-#line 55 "wcsutrn.l"
-/* To get the prototype for fileno() from stdio.h when gcc is invoked with
- * -std=c89 (same as -ansi) or -std=c99 since we do not define YY_INPUT. */
-#define _POSIX_SOURCE 1
-
-#include <setjmp.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "wcserr.h"
-#include "wcsunits.h"
-
-#define YY_DECL int wcsutrne(int ctrl, char unitstr[], struct wcserr **err)
-
-/* Used in preempting the call to exit() by yy_fatal_error(). */
-jmp_buf wcsutrn_abort_jmp_env;
-#define exit(status) longjmp(wcsutrn_abort_jmp_env, status)
-
-#line 4048 "wcsutrn.c"
-
-#define INITIAL 0
-#define NEXT 1
-#define FLUSH 2
-
-#ifndef YY_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 <unistd.h>
-#endif
-
-#ifndef YY_EXTRA_TYPE
-#define YY_EXTRA_TYPE void *
-#endif
-
-static int yy_init_globals (void );
-
-/* Accessor methods to globals.
-   These are made visible to non-reentrant scanners for convenience. */
-
-int wcsutrnlex_destroy (void );
-
-int wcsutrnget_debug (void );
-
-void wcsutrnset_debug (int debug_flag  );
-
-YY_EXTRA_TYPE wcsutrnget_extra (void );
-
-void wcsutrnset_extra (YY_EXTRA_TYPE user_defined  );
-
-FILE *wcsutrnget_in (void );
-
-void wcsutrnset_in  (FILE * in_str  );
-
-FILE *wcsutrnget_out (void );
-
-void wcsutrnset_out  (FILE * out_str  );
-
-int wcsutrnget_leng (void );
-
-char *wcsutrnget_text (void );
-
-int wcsutrnget_lineno (void );
-
-void wcsutrnset_lineno (int line_number  );
-
-/* Macros after this point can all be overridden by user definitions in
- * section 1.
- */
-
-#ifndef YY_SKIP_YYWRAP
-#ifdef __cplusplus
-extern "C" int wcsutrnwrap (void );
-#else
-extern int wcsutrnwrap (void );
-#endif
-#endif
-
-    static void yyunput (int c,char *buf_ptr  );
-    
-#ifndef yytext_ptr
-static void yy_flex_strncpy (char *,yyconst char *,int );
-#endif
-
-#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * );
-#endif
-
-#ifndef YY_NO_INPUT
-
-#ifdef __cplusplus
-static int yyinput (void );
-#else
-static int input (void );
-#endif
-
-#endif
-
-/* Amount of stuff to slurp up with each read. */
-#ifndef YY_READ_BUF_SIZE
-#ifdef __ia64__
-/* On IA-64, the buffer size is 16k, not 8k */
-#define YY_READ_BUF_SIZE 16384
-#else
-#define YY_READ_BUF_SIZE 8192
-#endif /* __ia64__ */
-#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( wcsutrntext, wcsutrnleng, 1, wcsutrnout )) {} } while (0)
-#endif
-
-/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
- * is returned in "result".
- */
-#ifndef YY_INPUT
-#define YY_INPUT(buf,result,max_size) \
-	errno=0; \
-	while ( (result = read( fileno(wcsutrnin), (char *) buf, max_size )) < 0 ) \
-	{ \
-		if( errno != EINTR) \
-		{ \
-			YY_FATAL_ERROR( "input in flex scanner failed" ); \
-			break; \
-		} \
-		errno=0; \
-		clearerr(wcsutrnin); \
-	}\
-\
-
-#endif
-
-/* No semi-colon after return; correct usage is to write "yyterminate();" -
- * we don't want an extra ';' after the "return" because that will cause
- * some compilers to complain about unreachable statements.
- */
-#ifndef yyterminate
-#define yyterminate() return YY_NULL
-#endif
-
-/* Number of entries by which start-condition stack grows. */
-#ifndef YY_START_STACK_INCR
-#define YY_START_STACK_INCR 25
-#endif
-
-/* Report a fatal error. */
-#ifndef YY_FATAL_ERROR
-#define YY_FATAL_ERROR(msg) yy_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 YY_DECL
-#define YY_DECL_IS_OURS 1
-
-extern int wcsutrnlex (void);
-
-#define YY_DECL int wcsutrnlex (void)
-#endif /* !YY_DECL */
-
-/* Code executed at the beginning of each rule, after wcsutrntext and wcsutrnleng
- * have been set up.
- */
-#ifndef YY_USER_ACTION
-#define YY_USER_ACTION
-#endif
-
-/* Code executed at the end of each rule. */
-#ifndef YY_BREAK
-#define YY_BREAK break;
-#endif
-
-#define YY_RULE_SETUP \
-	if ( wcsutrnleng > 0 ) \
-		YY_CURRENT_BUFFER_LVALUE->yy_at_bol = \
-				(wcsutrntext[wcsutrnleng - 1] == '\n'); \
-	YY_USER_ACTION
-
-/** The main scanner function which does all the work.
- */
-YY_DECL
-{
-	register yy_state_type yy_current_state;
-	register char *yy_cp, *yy_bp;
-	register int yy_act;
-    
-#line 75 "wcsutrn.l"
-
-	static const char *function = "wcsutrne";
-
-	char orig[80], subs[80];
-	int bracket = 0;
-	int unsafe  = 0;
-	int status  = -1;
-	YY_BUFFER_STATE inbuff;
-	int wcsutrnlex_destroy(void);
-	
-	*orig = '\0';
-	*subs = '\0';
-	
-	inbuff = wcsutrn_scan_string(unitstr);
-	*unitstr = '\0';
-	
-	/* Return here via longjmp() invoked by yy_fatal_error(). */
-	if (setjmp(wcsutrn_abort_jmp_env)) {
-	  return wcserr_set(WCSERR_SET(UNITSERR_PARSER_ERROR),
-	    "Internal units translator error parsing '%s'", unitstr);
-	}
-	
-	BEGIN(INITIAL);
-	
-#ifdef DEBUG
-	fprintf(stderr, "\n%s ->\n", unitstr);
-#endif
-
-#line 4253 "wcsutrn.c"
-
-	if ( !(yy_init) )
-		{
-		(yy_init) = 1;
-
-#ifdef YY_USER_INIT
-		YY_USER_INIT;
-#endif
-
-		if ( ! (yy_start) )
-			(yy_start) = 1;	/* first start state */
-
-		if ( ! wcsutrnin )
-			wcsutrnin = stdin;
-
-		if ( ! wcsutrnout )
-			wcsutrnout = stdout;
-
-		if ( ! YY_CURRENT_BUFFER ) {
-			wcsutrnensure_buffer_stack ();
-			YY_CURRENT_BUFFER_LVALUE =
-				wcsutrn_create_buffer(wcsutrnin,YY_BUF_SIZE );
-		}
-
-		wcsutrn_load_buffer_state( );
-		}
-
-	while ( 1 )		/* loops until end-of-file is reached */
-		{
-		yy_cp = (yy_c_buf_p);
-
-		/* Support of wcsutrntext. */
-		*yy_cp = (yy_hold_char);
-
-		/* yy_bp points to the position in yy_ch_buf of the start of
-		 * the current run.
-		 */
-		yy_bp = yy_cp;
-
-		yy_current_state = (yy_start);
-		yy_current_state += YY_AT_BOL();
-yy_match:
-		while ( (yy_current_state = yy_nxt[yy_current_state][ YY_SC_TO_UI(*yy_cp) ]) > 0 )
-			++yy_cp;
-
-		yy_current_state = -yy_current_state;
-
-yy_find_action:
-		yy_act = yy_accept[yy_current_state];
-
-		YY_DO_BEFORE_ACTION;
-
-do_action:	/* This label is used only to access EOF actions. */
-
-		switch ( yy_act )
-	{ /* beginning of action switch */
-case 1:
-YY_RULE_SETUP
-#line 103 "wcsutrn.l"
-{
-	  /* Looks like a keycomment. */
-	  strcat(unitstr, "[");
-	  bracket = 1;
-	}
-	YY_BREAK
-case 2:
-YY_RULE_SETUP
-#line 109 "wcsutrn.l"
-/* Discard leading whitespace. */
-	YY_BREAK
-case 3:
-/* rule 3 can match eol */
-YY_RULE_SETUP
-#line 111 "wcsutrn.l"
-{
-	  /* Non-alphabetic character. */
-	  strcat(unitstr, wcsutrntext);
-	  if (bracket && *wcsutrntext == ']') {
-	    BEGIN(FLUSH);
-	  }
-	}
-	YY_BREAK
-case 4:
-YY_RULE_SETUP
-#line 119 "wcsutrn.l"
-{
-	  strcpy(orig, wcsutrntext);
-	  strcpy(subs, "Angstrom");
-	  BEGIN(NEXT);
-	}
-	YY_BREAK
-case 5:
-YY_RULE_SETUP
-#line 125 "wcsutrn.l"
-{
-	  strcpy(orig, wcsutrntext);
-	  strcpy(subs, "arcmin");
-	  BEGIN(NEXT);
-	}
-	YY_BREAK
-case 6:
-YY_RULE_SETUP
-#line 131 "wcsutrn.l"
-{
-	  strcpy(orig, wcsutrntext);
-	  strcpy(subs, "arcsec");
-	  BEGIN(NEXT);
-	}
-	YY_BREAK
-case 7:
-YY_RULE_SETUP
-#line 137 "wcsutrn.l"
-{
-	  strcpy(orig, wcsutrntext);
-	  strcpy(subs, "beam");
-	  BEGIN(NEXT);
-	}
-	YY_BREAK
-case 8:
-YY_RULE_SETUP
-#line 143 "wcsutrn.l"
-{
-	  strcpy(orig, wcsutrntext);
-	  strcpy(subs, "byte");
-	  BEGIN(NEXT);
-	}
-	YY_BREAK
-case 9:
-YY_RULE_SETUP
-#line 149 "wcsutrn.l"
-{
-	  strcpy(orig, wcsutrntext);
-	  strcpy(subs, "d");
-	  BEGIN(NEXT);
-	}
-	YY_BREAK
-case 10:
-YY_RULE_SETUP
-#line 155 "wcsutrn.l"
-{
-	  unsafe = 1;
-	  strcpy(orig, wcsutrntext);
-	  strcpy(subs, (ctrl & 4) ? "d" : "D");
-	  BEGIN(NEXT);
-	}
-	YY_BREAK
-case 11:
-YY_RULE_SETUP
-#line 162 "wcsutrn.l"
-{
-	  strcpy(orig, wcsutrntext);
-	  strcpy(subs, "deg");
-	  BEGIN(NEXT);
-	}
-	YY_BREAK
-case 12:
-YY_RULE_SETUP
-#line 168 "wcsutrn.l"
-{
-	  strcpy(orig, wcsutrntext);
-	  strcpy(subs, "GHz");
-	  BEGIN(NEXT);
-	}
-	YY_BREAK
-case 13:
-YY_RULE_SETUP
-#line 174 "wcsutrn.l"
-{
-	  strcpy(orig, wcsutrntext);
-	  strcpy(subs, "h");
-	  BEGIN(NEXT);
-	}
-	YY_BREAK
-case 14:
-YY_RULE_SETUP
-#line 180 "wcsutrn.l"
-{
-	  unsafe = 1;
-	  strcpy(orig, wcsutrntext);
-	  strcpy(subs, (ctrl & 2) ? "h" : "H");
-	  BEGIN(NEXT);
-	}
-	YY_BREAK
-case 15:
-YY_RULE_SETUP
-#line 187 "wcsutrn.l"
-{
-	  strcpy(orig, wcsutrntext);
-	  strcpy(subs, "Hz");
-	  BEGIN(NEXT);
-	}
-	YY_BREAK
-case 16:
-YY_RULE_SETUP
-#line 193 "wcsutrn.l"
-{
-	  strcpy(orig, wcsutrntext);
-	  strcpy(subs, "kHz");
-	  BEGIN(NEXT);
-	}
-	YY_BREAK
-case 17:
-YY_RULE_SETUP
-#line 199 "wcsutrn.l"
-{
-	  strcpy(orig, wcsutrntext);
-	  strcpy(subs, "Jy");
-	  BEGIN(NEXT);
-	}
-	YY_BREAK
-case 18:
-YY_RULE_SETUP
-#line 205 "wcsutrn.l"
-{
-	  strcpy(orig, wcsutrntext);
-	  strcpy(subs, "K");
-	  BEGIN(NEXT);
-	}
-	YY_BREAK
-case 19:
-YY_RULE_SETUP
-#line 211 "wcsutrn.l"
-{
-	  strcpy(orig, wcsutrntext);
-	  strcpy(subs, "km");
-	  BEGIN(NEXT);
-	}
-	YY_BREAK
-case 20:
-YY_RULE_SETUP
-#line 217 "wcsutrn.l"
-{
-	  strcpy(orig, wcsutrntext);
-	  strcpy(subs, "m");
-	  BEGIN(NEXT);
-	}
-	YY_BREAK
-case 21:
-YY_RULE_SETUP
-#line 223 "wcsutrn.l"
-{
-	  strcpy(orig, wcsutrntext);
-	  strcpy(subs, "min");
-	  BEGIN(NEXT);
-	}
-	YY_BREAK
-case 22:
-YY_RULE_SETUP
-#line 229 "wcsutrn.l"
-{
-	  strcpy(orig, wcsutrntext);
-	  strcpy(subs, "MHz");
-	  BEGIN(NEXT);
-	}
-	YY_BREAK
-case 23:
-YY_RULE_SETUP
-#line 235 "wcsutrn.l"
-{
-	  strcpy(orig, wcsutrntext);
-	  strcpy(subs, "ohm");
-	  BEGIN(NEXT);
-	}
-	YY_BREAK
-case 24:
-YY_RULE_SETUP
-#line 241 "wcsutrn.l"
-{
-	  strcpy(orig, wcsutrntext);
-	  strcpy(subs, "Pa");
-	  BEGIN(NEXT);
-	}
-	YY_BREAK
-case 25:
-YY_RULE_SETUP
-#line 247 "wcsutrn.l"
-{
-	  strcpy(orig, wcsutrntext);
-	  strcpy(subs, "pixel");
-	  BEGIN(NEXT);
-	}
-	YY_BREAK
-case 26:
-YY_RULE_SETUP
-#line 253 "wcsutrn.l"
-{
-	  strcpy(orig, wcsutrntext);
-	  strcpy(subs, "rad");
-	  BEGIN(NEXT);
-	}
-	YY_BREAK
-case 27:
-YY_RULE_SETUP
-#line 259 "wcsutrn.l"
-{
-	  strcpy(orig, wcsutrntext);
-	  strcpy(subs, "s");
-	  BEGIN(NEXT);
-	}
-	YY_BREAK
-case 28:
-YY_RULE_SETUP
-#line 265 "wcsutrn.l"
-{
-	  unsafe = 1;
-	  strcpy(orig, wcsutrntext);
-	  strcpy(subs, (ctrl & 1) ? "s" : "S");
-	  BEGIN(NEXT);
-	}
-	YY_BREAK
-case 29:
-YY_RULE_SETUP
-#line 272 "wcsutrn.l"
-{
-	  strcpy(orig, wcsutrntext);
-	  strcpy(subs, "V");
-	  BEGIN(NEXT);
-	}
-	YY_BREAK
-case 30:
-YY_RULE_SETUP
-#line 278 "wcsutrn.l"
-{
-	  strcpy(orig, wcsutrntext);
-	  strcpy(subs, "yr");
-	  BEGIN(NEXT);
-	}
-	YY_BREAK
-case 31:
-YY_RULE_SETUP
-#line 284 "wcsutrn.l"
-{
-	  /* Not a recognized alias. */
-	  strcpy(orig, wcsutrntext);
-	  strcpy(subs, orig);
-	  BEGIN(NEXT);
-	}
-	YY_BREAK
-case 32:
-YY_RULE_SETUP
-#line 291 "wcsutrn.l"
-{
-	  /* Reject the alias match. */
-	  strcat(orig, wcsutrntext);
-	  strcpy(subs, orig);
-	}
-	YY_BREAK
-case 33:
-/* rule 33 can match eol */
-YY_RULE_SETUP
-#line 297 "wcsutrn.l"
-{
-	  /* Discard separating whitespace. */
-	  unput(wcsutrntext[wcsutrnleng-1]);
-	}
-	YY_BREAK
-case 34:
-YY_RULE_SETUP
-#line 302 "wcsutrn.l"
-{
-	  /* Compress separating whitespace. */
-	  strcat(unitstr, subs);
-	  strcat(unitstr, " ");
-	  if (strcmp(orig, subs)) status = 0;
-	  unput(wcsutrntext[wcsutrnleng-1]);
-	  *subs = '\0';
-	  BEGIN(INITIAL);
-	}
-	YY_BREAK
-case 35:
-YY_RULE_SETUP
-#line 312 "wcsutrn.l"
-{
-	  /* Copy anything else unchanged. */
-	  strcat(unitstr, subs);
-	  if (strcmp(orig, subs)) status = 0;
-	  unput(*wcsutrntext);
-	  *subs = '\0';
-	  BEGIN(INITIAL);
-	}
-	YY_BREAK
-case 36:
-YY_RULE_SETUP
-#line 321 "wcsutrn.l"
-{
-	  /* Copy out remaining input. */
-	  strcat(unitstr, wcsutrntext);
-	}
-	YY_BREAK
-case YY_STATE_EOF(INITIAL):
-case YY_STATE_EOF(NEXT):
-case YY_STATE_EOF(FLUSH):
-#line 326 "wcsutrn.l"
-{
-	  /* End-of-string. */
-	  if (*subs) {
-	    strcat(unitstr, subs);
-	    if (strcmp(orig, subs)) status = 0;
-	  }
-	
-	  wcsutrnlex_destroy();
-	  if (unsafe) {
-	    return wcserr_set(WCSERR_SET(UNITSERR_UNSAFE_TRANS),
-	      "Unsafe unit translation in '%s'", unitstr);
-	  }
-	  return status;
-	}
-	YY_BREAK
-case 37:
-YY_RULE_SETUP
-#line 341 "wcsutrn.l"
-ECHO;
-	YY_BREAK
-#line 4667 "wcsutrn.c"
-
-	case YY_END_OF_BUFFER:
-		{
-		/* Amount of text matched not including the EOB char. */
-		int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;
-
-		/* Undo the effects of YY_DO_BEFORE_ACTION. */
-		*yy_cp = (yy_hold_char);
-		YY_RESTORE_YY_MORE_OFFSET
-
-		if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
-			{
-			/* We're scanning a new file or input source.  It's
-			 * possible that this happened because the user
-			 * just pointed wcsutrnin at a new source and called
-			 * wcsutrnlex().  If so, then we have to assure
-			 * consistency between YY_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.
-			 */
-			(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
-			YY_CURRENT_BUFFER_LVALUE->yy_input_file = wcsutrnin;
-			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
-			}
-
-		/* Note that here we test for yy_c_buf_p "<=" to the position
-		 * of the first EOB in the buffer, since yy_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 ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
-			{ /* This was really a NUL. */
-			yy_state_type yy_next_state;
-
-			(yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;
-
-			yy_current_state = yy_get_previous_state(  );
-
-			/* Okay, we're now positioned to make the NUL
-			 * transition.  We couldn't have
-			 * yy_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).
-			 */
-
-			yy_next_state = yy_try_NUL_trans( yy_current_state );
-
-			yy_bp = (yytext_ptr) + YY_MORE_ADJ;
-
-			if ( yy_next_state )
-				{
-				/* Consume the NUL. */
-				yy_cp = ++(yy_c_buf_p);
-				yy_current_state = yy_next_state;
-				goto yy_match;
-				}
-
-			else
-				{
-				yy_cp = (yy_c_buf_p);
-				goto yy_find_action;
-				}
-			}
-
-		else switch ( yy_get_next_buffer(  ) )
-			{
-			case EOB_ACT_END_OF_FILE:
-				{
-				(yy_did_buffer_switch_on_eof) = 0;
-
-				if ( wcsutrnwrap( ) )
-					{
-					/* Note: because we've taken care in
-					 * yy_get_next_buffer() to have set up
-					 * wcsutrntext, we can now set up
-					 * yy_c_buf_p so that if some total
-					 * hoser (like flex itself) wants to
-					 * call the scanner after we return the
-					 * YY_NULL, it'll still work - another
-					 * YY_NULL will get returned.
-					 */
-					(yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;
-
-					yy_act = YY_STATE_EOF(YY_START);
-					goto do_action;
-					}
-
-				else
-					{
-					if ( ! (yy_did_buffer_switch_on_eof) )
-						YY_NEW_FILE;
-					}
-				break;
-				}
-
-			case EOB_ACT_CONTINUE_SCAN:
-				(yy_c_buf_p) =
-					(yytext_ptr) + yy_amount_of_matched_text;
-
-				yy_current_state = yy_get_previous_state(  );
-
-				yy_cp = (yy_c_buf_p);
-				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
-				goto yy_match;
-
-			case EOB_ACT_LAST_MATCH:
-				(yy_c_buf_p) =
-				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];
-
-				yy_current_state = yy_get_previous_state(  );
-
-				yy_cp = (yy_c_buf_p);
-				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
-				goto yy_find_action;
-			}
-		break;
-		}
-
-	default:
-		YY_FATAL_ERROR(
-			"fatal flex scanner internal error--no action found" );
-	} /* end of action switch */
-		} /* end of scanning one token */
-} /* end of wcsutrnlex */
-
-/* yy_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 yy_get_next_buffer (void)
-{
-    	register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
-	register char *source = (yytext_ptr);
-	register int number_to_move, i;
-	int ret_val;
-
-	if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
-		YY_FATAL_ERROR(
-		"fatal flex scanner internal error--end of buffer missed" );
-
-	if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
-		{ /* Don't try to fill the buffer, so this is an EOF. */
-		if ( (yy_c_buf_p) - (yytext_ptr) - YY_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) ((yy_c_buf_p) - (yytext_ptr)) - 1;
-
-	for ( i = 0; i < number_to_move; ++i )
-		*(dest++) = *(source++);
-
-	if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
-		/* don't do the read, it's not guaranteed to return an EOF,
-		 * just force an EOF
-		 */
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
-
-	else
-		{
-			int num_to_read =
-			YY_CURRENT_BUFFER_LVALUE->yy_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 */
-			YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
-
-			int yy_c_buf_p_offset =
-				(int) ((yy_c_buf_p) - b->yy_ch_buf);
-
-			if ( b->yy_is_our_buffer )
-				{
-				int new_size = b->yy_buf_size * 2;
-
-				if ( new_size <= 0 )
-					b->yy_buf_size += b->yy_buf_size / 8;
-				else
-					b->yy_buf_size *= 2;
-
-				b->yy_ch_buf = (char *)
-					/* Include room in for 2 EOB chars. */
-					wcsutrnrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2  );
-				}
-			else
-				/* Can't grow it, we don't own it. */
-				b->yy_ch_buf = 0;
-
-			if ( ! b->yy_ch_buf )
-				YY_FATAL_ERROR(
-				"fatal error - scanner input buffer overflow" );
-
-			(yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset];
-
-			num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
-						number_to_move - 1;
-
-			}
-
-		if ( num_to_read > YY_READ_BUF_SIZE )
-			num_to_read = YY_READ_BUF_SIZE;
-
-		/* Read in more data. */
-		YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
-			(yy_n_chars), (size_t) num_to_read );
-
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
-		}
-
-	if ( (yy_n_chars) == 0 )
-		{
-		if ( number_to_move == YY_MORE_ADJ )
-			{
-			ret_val = EOB_ACT_END_OF_FILE;
-			wcsutrnrestart(wcsutrnin  );
-			}
-
-		else
-			{
-			ret_val = EOB_ACT_LAST_MATCH;
-			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
-				YY_BUFFER_EOF_PENDING;
-			}
-		}
-
-	else
-		ret_val = EOB_ACT_CONTINUE_SCAN;
-
-	if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
-		/* Extend the array by 50%, plus the number we really need. */
-		yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1);
-		YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) wcsutrnrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size  );
-		if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
-			YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
-	}
-
-	(yy_n_chars) += number_to_move;
-	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
-	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
-
-	(yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
-
-	return ret_val;
-}
-
-/* yy_get_previous_state - get the state just before the EOB char was reached */
-
-    static yy_state_type yy_get_previous_state (void)
-{
-	register yy_state_type yy_current_state;
-	register char *yy_cp;
-    
-	yy_current_state = (yy_start);
-	yy_current_state += YY_AT_BOL();
-
-	for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
-		{
-		if ( *yy_cp )
-			{
-			yy_current_state = yy_nxt[yy_current_state][YY_SC_TO_UI(*yy_cp)];
-			}
-		else
-			yy_current_state = yy_NUL_trans[yy_current_state];
-		}
-
-	return yy_current_state;
-}
-
-/* yy_try_NUL_trans - try to make a transition on the NUL character
- *
- * synopsis
- *	next_state = yy_try_NUL_trans( current_state );
- */
-    static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state )
-{
-	register int yy_is_jam;
-    
-	yy_current_state = yy_NUL_trans[yy_current_state];
-	yy_is_jam = (yy_current_state == 0);
-
-	return yy_is_jam ? 0 : yy_current_state;
-}
-
-    static void yyunput (int c, register char * yy_bp )
-{
-	register char *yy_cp;
-    
-    yy_cp = (yy_c_buf_p);
-
-	/* undo effects of setting up wcsutrntext */
-	*yy_cp = (yy_hold_char);
-
-	if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
-		{ /* need to shift things up to make room */
-		/* +2 for EOB chars. */
-		register int number_to_move = (yy_n_chars) + 2;
-		register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
-					YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
-		register char *source =
-				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
-
-		while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
-			*--dest = *--source;
-
-		yy_cp += (int) (dest - source);
-		yy_bp += (int) (dest - source);
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars =
-			(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size;
-
-		if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
-			YY_FATAL_ERROR( "flex scanner push-back overflow" );
-		}
-
-	*--yy_cp = (char) c;
-
-	(yytext_ptr) = yy_bp;
-	(yy_hold_char) = *yy_cp;
-	(yy_c_buf_p) = yy_cp;
-}
-
-#ifndef YY_NO_INPUT
-#ifdef __cplusplus
-    static int yyinput (void)
-#else
-    static int input  (void)
-#endif
-
-{
-	int c;
-    
-	*(yy_c_buf_p) = (yy_hold_char);
-
-	if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
-		{
-		/* yy_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 ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
-			/* This was really a NUL. */
-			*(yy_c_buf_p) = '\0';
-
-		else
-			{ /* need more input */
-			int offset = (yy_c_buf_p) - (yytext_ptr);
-			++(yy_c_buf_p);
-
-			switch ( yy_get_next_buffer(  ) )
-				{
-				case EOB_ACT_LAST_MATCH:
-					/* This happens because yy_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. */
-					wcsutrnrestart(wcsutrnin );
-
-					/*FALLTHROUGH*/
-
-				case EOB_ACT_END_OF_FILE:
-					{
-					if ( wcsutrnwrap( ) )
-						return EOF;
-
-					if ( ! (yy_did_buffer_switch_on_eof) )
-						YY_NEW_FILE;
-#ifdef __cplusplus
-					return yyinput();
-#else
-					return input();
-#endif
-					}
-
-				case EOB_ACT_CONTINUE_SCAN:
-					(yy_c_buf_p) = (yytext_ptr) + offset;
-					break;
-				}
-			}
-		}
-
-	c = *(unsigned char *) (yy_c_buf_p);	/* cast for 8-bit char's */
-	*(yy_c_buf_p) = '\0';	/* preserve wcsutrntext */
-	(yy_hold_char) = *++(yy_c_buf_p);
-
-	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = (c == '\n');
-
-	return c;
-}
-#endif	/* ifndef YY_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 wcsutrnrestart  (FILE * input_file )
-{
-    
-	if ( ! YY_CURRENT_BUFFER ){
-        wcsutrnensure_buffer_stack ();
-		YY_CURRENT_BUFFER_LVALUE =
-            wcsutrn_create_buffer(wcsutrnin,YY_BUF_SIZE );
-	}
-
-	wcsutrn_init_buffer(YY_CURRENT_BUFFER,input_file );
-	wcsutrn_load_buffer_state( );
-}
-
-/** Switch to a different input buffer.
- * @param new_buffer The new input buffer.
- * 
- */
-    void wcsutrn_switch_to_buffer  (YY_BUFFER_STATE  new_buffer )
-{
-    
-	/* TODO. We should be able to replace this entire function body
-	 * with
-	 *		wcsutrnpop_buffer_state();
-	 *		wcsutrnpush_buffer_state(new_buffer);
-     */
-	wcsutrnensure_buffer_stack ();
-	if ( YY_CURRENT_BUFFER == new_buffer )
-		return;
-
-	if ( YY_CURRENT_BUFFER )
-		{
-		/* Flush out information for old buffer. */
-		*(yy_c_buf_p) = (yy_hold_char);
-		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
-		}
-
-	YY_CURRENT_BUFFER_LVALUE = new_buffer;
-	wcsutrn_load_buffer_state( );
-
-	/* We don't actually know whether we did this switch during
-	 * EOF (wcsutrnwrap()) processing, but the only time this flag
-	 * is looked at is after wcsutrnwrap() is called, so it's safe
-	 * to go ahead and always set it.
-	 */
-	(yy_did_buffer_switch_on_eof) = 1;
-}
-
-static void wcsutrn_load_buffer_state  (void)
-{
-    	(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
-	(yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
-	wcsutrnin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
-	(yy_hold_char) = *(yy_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 YY_BUF_SIZE.
- * 
- * @return the allocated buffer state.
- */
-    YY_BUFFER_STATE wcsutrn_create_buffer  (FILE * file, int  size )
-{
-	YY_BUFFER_STATE b;
-    
-	b = (YY_BUFFER_STATE) wcsutrnalloc(sizeof( struct yy_buffer_state )  );
-	if ( ! b )
-		YY_FATAL_ERROR( "out of dynamic memory in wcsutrn_create_buffer()" );
-
-	b->yy_buf_size = size;
-
-	/* yy_ch_buf has to be 2 characters longer than the size given because
-	 * we need to put in 2 end-of-buffer characters.
-	 */
-	b->yy_ch_buf = (char *) wcsutrnalloc(b->yy_buf_size + 2  );
-	if ( ! b->yy_ch_buf )
-		YY_FATAL_ERROR( "out of dynamic memory in wcsutrn_create_buffer()" );
-
-	b->yy_is_our_buffer = 1;
-
-	wcsutrn_init_buffer(b,file );
-
-	return b;
-}
-
-/** Destroy the buffer.
- * @param b a buffer created with wcsutrn_create_buffer()
- * 
- */
-    void wcsutrn_delete_buffer (YY_BUFFER_STATE  b )
-{
-    
-	if ( ! b )
-		return;
-
-	if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
-		YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
-
-	if ( b->yy_is_our_buffer )
-		wcsutrnfree((void *) b->yy_ch_buf  );
-
-	wcsutrnfree((void *) b  );
-}
-
-/* Initializes or reinitializes a buffer.
- * This function is sometimes called more than once on the same buffer,
- * such as during a wcsutrnrestart() or at EOF.
- */
-    static void wcsutrn_init_buffer  (YY_BUFFER_STATE  b, FILE * file )
-
-{
-	int oerrno = errno;
-    
-	wcsutrn_flush_buffer(b );
-
-	b->yy_input_file = file;
-	b->yy_fill_buffer = 1;
-
-    /* If b is the current buffer, then wcsutrn_init_buffer was _probably_
-     * called from wcsutrnrestart() or through yy_get_next_buffer.
-     * In that case, we don't want to reset the lineno or column.
-     */
-    if (b != YY_CURRENT_BUFFER){
-        b->yy_bs_lineno = 1;
-        b->yy_bs_column = 0;
-    }
-
-        b->yy_is_interactive = 0;
-    
-	errno = oerrno;
-}
-
-/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
- * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
- * 
- */
-    void wcsutrn_flush_buffer (YY_BUFFER_STATE  b )
-{
-    	if ( ! b )
-		return;
-
-	b->yy_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->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
-	b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
-
-	b->yy_buf_pos = &b->yy_ch_buf[0];
-
-	b->yy_at_bol = 1;
-	b->yy_buffer_status = YY_BUFFER_NEW;
-
-	if ( b == YY_CURRENT_BUFFER )
-		wcsutrn_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 wcsutrnpush_buffer_state (YY_BUFFER_STATE new_buffer )
-{
-    	if (new_buffer == NULL)
-		return;
-
-	wcsutrnensure_buffer_stack();
-
-	/* This block is copied from wcsutrn_switch_to_buffer. */
-	if ( YY_CURRENT_BUFFER )
-		{
-		/* Flush out information for old buffer. */
-		*(yy_c_buf_p) = (yy_hold_char);
-		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
-		}
-
-	/* Only push if top exists. Otherwise, replace top. */
-	if (YY_CURRENT_BUFFER)
-		(yy_buffer_stack_top)++;
-	YY_CURRENT_BUFFER_LVALUE = new_buffer;
-
-	/* copied from wcsutrn_switch_to_buffer. */
-	wcsutrn_load_buffer_state( );
-	(yy_did_buffer_switch_on_eof) = 1;
-}
-
-/** Removes and deletes the top of the stack, if present.
- *  The next element becomes the new top.
- *  
- */
-void wcsutrnpop_buffer_state (void)
-{
-    	if (!YY_CURRENT_BUFFER)
-		return;
-
-	wcsutrn_delete_buffer(YY_CURRENT_BUFFER );
-	YY_CURRENT_BUFFER_LVALUE = NULL;
-	if ((yy_buffer_stack_top) > 0)
-		--(yy_buffer_stack_top);
-
-	if (YY_CURRENT_BUFFER) {
-		wcsutrn_load_buffer_state( );
-		(yy_did_buffer_switch_on_eof) = 1;
-	}
-}
-
-/* Allocates the stack if it does not exist.
- *  Guarantees space for at least one push.
- */
-static void wcsutrnensure_buffer_stack (void)
-{
-	int num_to_alloc;
-    
-	if (!(yy_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;
-		(yy_buffer_stack) = (struct yy_buffer_state**)wcsutrnalloc
-								(num_to_alloc * sizeof(struct yy_buffer_state*)
-								);
-		if ( ! (yy_buffer_stack) )
-			YY_FATAL_ERROR( "out of dynamic memory in wcsutrnensure_buffer_stack()" );
-								  
-		memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
-				
-		(yy_buffer_stack_max) = num_to_alloc;
-		(yy_buffer_stack_top) = 0;
-		return;
-	}
-
-	if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
-
-		/* Increase the buffer to prepare for a possible push. */
-		int grow_size = 8 /* arbitrary grow size */;
-
-		num_to_alloc = (yy_buffer_stack_max) + grow_size;
-		(yy_buffer_stack) = (struct yy_buffer_state**)wcsutrnrealloc
-								((yy_buffer_stack),
-								num_to_alloc * sizeof(struct yy_buffer_state*)
-								);
-		if ( ! (yy_buffer_stack) )
-			YY_FATAL_ERROR( "out of dynamic memory in wcsutrnensure_buffer_stack()" );
-
-		/* zero only the new slots.*/
-		memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
-		(yy_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. 
- */
-YY_BUFFER_STATE wcsutrn_scan_buffer  (char * base, yy_size_t  size )
-{
-	YY_BUFFER_STATE b;
-    
-	if ( size < 2 ||
-	     base[size-2] != YY_END_OF_BUFFER_CHAR ||
-	     base[size-1] != YY_END_OF_BUFFER_CHAR )
-		/* They forgot to leave room for the EOB's. */
-		return 0;
-
-	b = (YY_BUFFER_STATE) wcsutrnalloc(sizeof( struct yy_buffer_state )  );
-	if ( ! b )
-		YY_FATAL_ERROR( "out of dynamic memory in wcsutrn_scan_buffer()" );
-
-	b->yy_buf_size = size - 2;	/* "- 2" to take care of EOB's */
-	b->yy_buf_pos = b->yy_ch_buf = base;
-	b->yy_is_our_buffer = 0;
-	b->yy_input_file = 0;
-	b->yy_n_chars = b->yy_buf_size;
-	b->yy_is_interactive = 0;
-	b->yy_at_bol = 1;
-	b->yy_fill_buffer = 0;
-	b->yy_buffer_status = YY_BUFFER_NEW;
-
-	wcsutrn_switch_to_buffer(b  );
-
-	return b;
-}
-
-/** Setup the input buffer state to scan a string. The next call to wcsutrnlex() will
- * scan from a @e copy of @a str.
- * @param yystr 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
- *       wcsutrn_scan_bytes() instead.
- */
-YY_BUFFER_STATE wcsutrn_scan_string (yyconst char * yystr )
-{
-    
-	return wcsutrn_scan_bytes(yystr,strlen(yystr) );
-}
-
-/** Setup the input buffer state to scan the given bytes. The next call to wcsutrnlex() will
- * scan from a @e copy of @a bytes.
- * @param yybytes the byte buffer to scan
- * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
- * 
- * @return the newly allocated buffer state object.
- */
-YY_BUFFER_STATE wcsutrn_scan_bytes  (yyconst char * yybytes, int  _yybytes_len )
-{
-	YY_BUFFER_STATE b;
-	char *buf;
-	yy_size_t n;
-	int i;
-    
-	/* Get memory for full buffer, including space for trailing EOB's. */
-	n = _yybytes_len + 2;
-	buf = (char *) wcsutrnalloc(n  );
-	if ( ! buf )
-		YY_FATAL_ERROR( "out of dynamic memory in wcsutrn_scan_bytes()" );
-
-	for ( i = 0; i < _yybytes_len; ++i )
-		buf[i] = yybytes[i];
-
-	buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
-
-	b = wcsutrn_scan_buffer(buf,n );
-	if ( ! b )
-		YY_FATAL_ERROR( "bad buffer in wcsutrn_scan_bytes()" );
-
-	/* It's okay to grow etc. this buffer, and we should throw it
-	 * away when we're done.
-	 */
-	b->yy_is_our_buffer = 1;
-
-	return b;
-}
-
-#ifndef YY_EXIT_FAILURE
-#define YY_EXIT_FAILURE 2
-#endif
-
-static void yy_fatal_error (yyconst char* msg )
-{
-    	(void) fprintf( stderr, "%s\n", msg );
-	exit( YY_EXIT_FAILURE );
-}
-
-/* Redefine yyless() so it works in section 3 code. */
-
-#undef yyless
-#define yyless(n) \
-	do \
-		{ \
-		/* Undo effects of setting up wcsutrntext. */ \
-        int yyless_macro_arg = (n); \
-        YY_LESS_LINENO(yyless_macro_arg);\
-		wcsutrntext[wcsutrnleng] = (yy_hold_char); \
-		(yy_c_buf_p) = wcsutrntext + yyless_macro_arg; \
-		(yy_hold_char) = *(yy_c_buf_p); \
-		*(yy_c_buf_p) = '\0'; \
-		wcsutrnleng = yyless_macro_arg; \
-		} \
-	while ( 0 )
-
-/* Accessor  methods (get/set functions) to struct members. */
-
-/** Get the current line number.
- * 
- */
-int wcsutrnget_lineno  (void)
-{
-        
-    return wcsutrnlineno;
-}
-
-/** Get the input stream.
- * 
- */
-FILE *wcsutrnget_in  (void)
-{
-        return wcsutrnin;
-}
-
-/** Get the output stream.
- * 
- */
-FILE *wcsutrnget_out  (void)
-{
-        return wcsutrnout;
-}
-
-/** Get the length of the current token.
- * 
- */
-int wcsutrnget_leng  (void)
-{
-        return wcsutrnleng;
-}
-
-/** Get the current token.
- * 
- */
-
-char *wcsutrnget_text  (void)
-{
-        return wcsutrntext;
-}
-
-/** Set the current line number.
- * @param line_number
- * 
- */
-void wcsutrnset_lineno (int  line_number )
-{
-    
-    wcsutrnlineno = line_number;
-}
-
-/** Set the input stream. This does not discard the current
- * input buffer.
- * @param in_str A readable stream.
- * 
- * @see wcsutrn_switch_to_buffer
- */
-void wcsutrnset_in (FILE *  in_str )
-{
-        wcsutrnin = in_str ;
-}
-
-void wcsutrnset_out (FILE *  out_str )
-{
-        wcsutrnout = out_str ;
-}
-
-int wcsutrnget_debug  (void)
-{
-        return wcsutrn_flex_debug;
-}
-
-void wcsutrnset_debug (int  bdebug )
-{
-        wcsutrn_flex_debug = bdebug ;
-}
-
-static int yy_init_globals (void)
-{
-        /* Initialization is the same as for the non-reentrant scanner.
-     * This function is called from wcsutrnlex_destroy(), so don't allocate here.
-     */
-
-    (yy_buffer_stack) = 0;
-    (yy_buffer_stack_top) = 0;
-    (yy_buffer_stack_max) = 0;
-    (yy_c_buf_p) = (char *) 0;
-    (yy_init) = 0;
-    (yy_start) = 0;
-
-/* Defined in main.c */
-#ifdef YY_STDINIT
-    wcsutrnin = stdin;
-    wcsutrnout = stdout;
-#else
-    wcsutrnin = (FILE *) 0;
-    wcsutrnout = (FILE *) 0;
-#endif
-
-    /* For future reference: Set errno on error, since we are called by
-     * wcsutrnlex_init()
-     */
-    return 0;
-}
-
-/* wcsutrnlex_destroy is for both reentrant and non-reentrant scanners. */
-int wcsutrnlex_destroy  (void)
-{
-    
-    /* Pop the buffer stack, destroying each element. */
-	while(YY_CURRENT_BUFFER){
-		wcsutrn_delete_buffer(YY_CURRENT_BUFFER  );
-		YY_CURRENT_BUFFER_LVALUE = NULL;
-		wcsutrnpop_buffer_state();
-	}
-
-	/* Destroy the stack itself. */
-	wcsutrnfree((yy_buffer_stack) );
-	(yy_buffer_stack) = NULL;
-
-    /* Reset the globals. This is important in a non-reentrant scanner so the next time
-     * wcsutrnlex() is called, initialization will occur. */
-    yy_init_globals( );
-
-    return 0;
-}
-
-/*
- * Internal utility routines.
- */
-
-#ifndef yytext_ptr
-static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
-{
-	register int i;
-	for ( i = 0; i < n; ++i )
-		s1[i] = s2[i];
-}
-#endif
-
-#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * s )
-{
-	register int n;
-	for ( n = 0; s[n]; ++n )
-		;
-
-	return n;
-}
-#endif
-
-void *wcsutrnalloc (yy_size_t  size )
-{
-	return (void *) malloc( size );
-}
-
-void *wcsutrnrealloc  (void * ptr, yy_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 wcsutrnfree (void * ptr )
-{
-	free( (char *) ptr );	/* see wcsutrnrealloc() for (char *) cast */
-}
-
-#define YYTABLES_NAME "yytables"
-
-#line 341 "wcsutrn.l"
-
-
-
diff --git a/astropy/wcs/src/wcslib/C/getwcstab.c b/astropy/wcs/src/wcslib/C/getwcstab.c
deleted file mode 100644
index 6fdf985..0000000
--- a/astropy/wcs/src/wcslib/C/getwcstab.c
+++ /dev/null
@@ -1,160 +0,0 @@
-/*============================================================================
-
-  WCSLIB 4.10 - an implementation of the FITS WCS standard.
-  Copyright (C) 1995-2012, Mark Calabretta
-
-  This file is part of WCSLIB.
-
-  WCSLIB is free software: you can redistribute it and/or modify it under the
-  terms of the GNU Lesser General Public License as published by the Free
-  Software Foundation, either version 3 of the License, or (at your option)
-  any later version.
-
-  WCSLIB 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 Lesser General Public License for
-  more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with WCSLIB.  If not, see <http://www.gnu.org/licenses/>.
-
-  Correspondence concerning WCSLIB may be directed to:
-    Internet email: mcalabre at atnf.csiro.au
-    Postal address: Dr. Mark Calabretta
-                    Australia Telescope National Facility, CSIRO
-                    PO Box 76
-                    Epping NSW 1710
-                    AUSTRALIA
-
-  Author: Mark Calabretta, Australia Telescope National Facility
-  http://www.atnf.csiro.au/~mcalabre/index.html
-  $Id: getwcstab.c,v 4.10 2012/02/05 23:41:44 cal103 Exp $
-*===========================================================================*/
-
-#include <stdlib.h>
-#include <string.h>
-
-#include <fitsio.h>
-
-#include "getwcstab.h"
-
-/*--------------------------------------------------------------------------*/
-
-int fits_read_wcstab(
-  fitsfile   *fptr,
-  int  nwtb,
-  wtbarr *wtb,
-  int  *status)
-
-{
-  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;
-}
diff --git a/astropy/wcs/src/wcslib/C/getwcstab.h b/astropy/wcs/src/wcslib/C/getwcstab.h
deleted file mode 100644
index 2e021bf..0000000
--- a/astropy/wcs/src/wcslib/C/getwcstab.h
+++ /dev/null
@@ -1,195 +0,0 @@
-/*============================================================================
-
-  WCSLIB 4.10 - an implementation of the FITS WCS standard.
-  Copyright (C) 1995-2012, Mark Calabretta
-
-  This file is part of WCSLIB.
-
-  WCSLIB is free software: you can redistribute it and/or modify it under the
-  terms of the GNU Lesser General Public License as published by the Free
-  Software Foundation, either version 3 of the License, or (at your option)
-  any later version.
-
-  WCSLIB 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 Lesser General Public License for
-  more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with WCSLIB.  If not, see <http://www.gnu.org/licenses/>.
-
-  Correspondence concerning WCSLIB may be directed to:
-    Internet email: mcalabre at atnf.csiro.au
-    Postal address: Dr. Mark Calabretta
-                    Australia Telescope National Facility, CSIRO
-                    PO Box 76
-                    Epping NSW 1710
-                    AUSTRALIA
-
-  Author: Mark Calabretta, Australia Telescope National Facility
-  http://www.atnf.csiro.au/~mcalabre/index.html
-  $Id: getwcstab.h,v 4.10 2012/02/05 23:41:44 cal103 Exp $
-*=============================================================================
-*
-* Summary of the getwcstab routines
-* ---------------------------------
-* fits_read_wcstab(), an implementation of a FITS table reading routine for
-* 'TAB' coordinates, is provided for CFITSIO programmers.  It has been
-* incorporated into CFITSIO as of v3.006 with the definitions in this file,
-* getwcstab.h, moved into fitsio.h.
-*
-* fits_read_wcstab() is not included in the WCSLIB object library but the
-* source code is presented here as it may be useful for programmers using an
-* older version of CFITSIO than 3.006, or as a programming template for
-* non-CFITSIO programmers.
-*
-*
-* fits_read_wcstab() - FITS 'TAB' table reading routine
-* ----------------------------------------------------
-* fits_read_wcstab() extracts arrays from a binary table required in
-* constructing 'TAB' coordinates.
-*
-* Given:
-*   fptr      fitsfile *
-*                       Pointer to the file handle returned, for example, by
-*                       the fits_open_file() routine in CFITSIO.
-*
-*   nwtb      int       Number of arrays to be read from the binary table(s).
-*
-* Given and returned:
-*   wtb       wtbarr *  Address of the first element of an array of wtbarr
-*                       typedefs.  This wtbarr typedef is defined to match the
-*                       wtbarr struct defined in WCSLIB.  An array of such
-*                       structs returned by the WCSLIB function wcstab() as
-*                       discussed in the notes below.
-*
-* Returned:
-*   status    int *     CFITSIO status value.
-*
-* Function return value:
-*             int       CFITSIO status value.
-*
-* Notes:
-*   In order to maintain WCSLIB and CFITSIO as independent libraries it is 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 wtbarr structs defined in wcs.h within WCSLIB.
-*
-*   The problem therefore is to define the wtbarr 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().
-*
-*   The solution adopted is for WCSLIB to define "struct wtbarr" while
-*   fitsio.h defines "typedef wtbarr" as an 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 name spaces in C; Appendix A, Sect. A11.1 (p227) of
-*   the K&R ANSI edition states that:
-*
-*     Identifiers fall into several name spaces that do not interfere with one
-*     another; the same identifier may be used for different purposes, even in
-*     the same scope, if the uses are in different name spaces.  These classes
-*     are: objects, functions, typedef names, and enum constants; labels; tags
-*     of structures, unions, and enumerations; and members of each structure
-*     or union individually.
-*
-*   Therefore, declarations within WCSLIB look like
-*
-=     struct wtbarr *w;
-*
-*   while within CFITSIO they are simply
-*
-=     wtbarr *w;
-*
-*   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.
-*
-*   When using WCSLIB and CFITSIO together in C++ the situation is complicated
-*   by the fact that typedefs and structs share the same namespace; C++
-*   Annotated Reference Manual, Sect. 7.1.3 (p105).  In that case the wtbarr
-*   struct in wcs.h is renamed by preprocessor macro substitution to wtbarr_s
-*   to distinguish it from the typedef defined in fitsio.h.  However, the
-*   scope of this macro substitution is limited to wcs.h itself and CFITSIO
-*   programmer code, whether in C++ or C, should always use the wtbarr
-*   typedef.
-*
-*
-* wtbarr typedef
-* --------------
-* The wtbarr typedef is defined as a struct containing the following members:
-*
-*   int i
-*     Image axis number.
-*
-*   int m
-*     Array axis number for index vectors.
-*
-*   int kind
-*     Character identifying the array type:
-*       - c: coordinate array,
-*       - i: index vector.
-*
-*   char extnam[72]
-*     EXTNAME identifying the binary table extension.
-*
-*   int extver
-*     EXTVER identifying the binary table extension.
-*
-*   int extlev
-*     EXTLEV identifying the binary table extension.
-*
-*   char ttype[72]
-*     TTYPEn identifying the column of the binary table that contains the
-*     array.
-*
-*   long row
-*     Table row number.
-*
-*   int ndim
-*     Expected dimensionality of the array.
-*
-*   int *dimlen
-*     Address of the first element of an array of int of length ndim into
-*     which the array axis lengths are to be written.
-*
-*   double **arrayp
-*     Pointer to an array of double which is to be allocated by the user
-*     and into which the array is to be written.
-*
-*===========================================================================*/
-
-#ifndef WCSLIB_GETWCSTAB
-#define WCSLIB_GETWCSTAB
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <fitsio.h>
-
-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;
-
-
-int fits_read_wcstab(fitsfile *fptr, int nwtb, wtbarr *wtb, int *status);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* WCSLIB_GETWCSTAB */
diff --git a/astropy/wcs/src/wcslib/C/lin.c b/astropy/wcs/src/wcslib/C/lin.c
deleted file mode 100644
index fed0b62..0000000
--- a/astropy/wcs/src/wcslib/C/lin.c
+++ /dev/null
@@ -1,753 +0,0 @@
-/*============================================================================
-
-  WCSLIB 4.10 - an implementation of the FITS WCS standard.
-  Copyright (C) 1995-2012, Mark Calabretta
-
-  This file is part of WCSLIB.
-
-  WCSLIB is free software: you can redistribute it and/or modify it under the
-  terms of the GNU Lesser General Public License as published by the Free
-  Software Foundation, either version 3 of the License, or (at your option)
-  any later version.
-
-  WCSLIB 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 Lesser General Public License for
-  more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with WCSLIB.  If not, see <http://www.gnu.org/licenses/>.
-
-  Correspondence concerning WCSLIB may be directed to:
-    Internet email: mcalabre at atnf.csiro.au
-    Postal address: Dr. Mark Calabretta
-                    Australia Telescope National Facility, CSIRO
-                    PO Box 76
-                    Epping NSW 1710
-                    AUSTRALIA
-
-  Author: Mark Calabretta, Australia Telescope National Facility
-  http://www.atnf.csiro.au/~mcalabre/index.html
-  $Id: lin.c,v 4.10 2012/02/05 23:41:44 cal103 Exp $
-*===========================================================================*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <math.h>
-
-#include "wcserr.h"
-#include "wcsprintf.h"
-#include "lin.h"
-
-const int LINSET = 137;
-
-/* Map status return value to message. */
-const char *lin_errmsg[] = {
-  "Success",
-  "Null linprm pointer passed",
-  "Memory allocation failed",
-  "PCi_ja matrix is singular"};
-
-/* Convenience macro for invoking wcserr_set(). */
-#define LIN_ERRMSG(status) WCSERR_SET(status), lin_errmsg[status]
-
-/*--------------------------------------------------------------------------*/
-
-int linini(alloc, naxis, lin)
-
-int alloc, naxis;
-struct linprm *lin;
-
-{
-  static const char *function = "linini";
-
-  int i, j;
-  double *pc;
-  struct wcserr **err;
-
-  if (lin == 0x0) return LINERR_NULL_POINTER;
-
-  /* Initialize error message handling. */
-  err = &(lin->err);
-  if (lin->flag != -1) {
-    if (lin->err) free(lin->err);
-  }
-  lin->err = 0x0;
-
-
-  /* Initialize memory management. */
-  if (lin->flag == -1 || lin->m_flag != LINSET) {
-    lin->m_flag  = 0;
-    lin->m_naxis = 0x0;
-    lin->m_crpix = 0x0;
-    lin->m_pc    = 0x0;
-    lin->m_cdelt = 0x0;
-  }
-
-
-  if (naxis < 1) {
-    return wcserr_set(WCSERR_SET(LINERR_MEMORY),
-      "naxis must be positive (got %d)", naxis);
-  }
-
-
-  /* Allocate memory for arrays if required. */
-  if (alloc ||
-     lin->crpix == 0x0 ||
-     lin->pc    == 0x0 ||
-     lin->cdelt == 0x0) {
-
-    /* Was sufficient allocated previously? */
-    if (lin->m_flag == LINSET && lin->m_naxis < naxis) {
-      /* No, free it. */
-      linfree(lin);
-    }
-
-    if (alloc || lin->crpix == 0x0) {
-      if (lin->m_crpix) {
-        /* In case the caller fiddled with it. */
-        lin->crpix = lin->m_crpix;
-
-      } else {
-        if (!(lin->crpix = calloc(naxis, sizeof(double)))) {
-          return wcserr_set(LIN_ERRMSG(LINERR_MEMORY));
-        }
-
-        lin->m_flag  = LINSET;
-        lin->m_naxis = naxis;
-        lin->m_crpix = lin->crpix;
-      }
-    }
-
-    if (alloc || lin->pc == 0x0) {
-      if (lin->m_pc) {
-        /* In case the caller fiddled with it. */
-        lin->pc = lin->m_pc;
-
-      } else {
-        if (!(lin->pc = calloc(naxis*naxis, sizeof(double)))) {
-          linfree(lin);
-          return wcserr_set(LIN_ERRMSG(LINERR_MEMORY));
-        }
-
-        lin->m_flag  = LINSET;
-        lin->m_naxis = naxis;
-        lin->m_pc    = lin->pc;
-      }
-    }
-
-    if (alloc || lin->cdelt == 0x0) {
-      if (lin->m_cdelt) {
-        /* In case the caller fiddled with it. */
-        lin->cdelt = lin->m_cdelt;
-
-      } else {
-        if (!(lin->cdelt = calloc(naxis, sizeof(double)))) {
-          linfree(lin);
-          return wcserr_set(LIN_ERRMSG(LINERR_MEMORY));
-        }
-
-        lin->m_flag  = LINSET;
-        lin->m_naxis = naxis;
-        lin->m_cdelt = lin->cdelt;
-      }
-    }
-  }
-
-  /* Free memory allocated by linset(). */
-  if (lin->flag == LINSET) {
-    if (lin->piximg) free(lin->piximg);
-    if (lin->imgpix) free(lin->imgpix);
-  }
-
-  lin->piximg = 0x0;
-  lin->imgpix = 0x0;
-  lin->i_naxis = 0x0;
-
-  lin->flag  = 0;
-  lin->naxis = naxis;
-
-
-  /* CRPIXja defaults to 0.0. */
-  for (j = 0; j < naxis; j++) {
-    lin->crpix[j] = 0.0;
-  }
-
-
-  /* PCi_ja defaults to the unit matrix. */
-  pc = lin->pc;
-  for (i = 0; i < naxis; i++) {
-    for (j = 0; j < naxis; j++) {
-      if (j == i) {
-        *pc = 1.0;
-      } else {
-        *pc = 0.0;
-      }
-      pc++;
-    }
-  }
-
-
-  /* CDELTia defaults to 1.0. */
-  for (i = 0; i < naxis; i++) {
-    lin->cdelt[i] = 1.0;
-  }
-
-
-  return 0;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int lincpy(alloc, linsrc, lindst)
-
-int alloc;
-const struct linprm *linsrc;
-struct linprm *lindst;
-
-{
-  static const char *function = "lincpy";
-
-  int i, j, naxis, status;
-  const double *srcp;
-  double *dstp;
-  struct wcserr **err;
-
-  if (linsrc == 0x0) return LINERR_NULL_POINTER;
-  if (lindst == 0x0) return LINERR_NULL_POINTER;
-  err = &(lindst->err);
-
-  naxis = linsrc->naxis;
-  if (naxis < 1) {
-    return wcserr_set(WCSERR_SET(LINERR_MEMORY),
-      "naxis must be positive (got %d)", naxis);
-  }
-
-  if ((status = linini(alloc, naxis, lindst))) {
-    return status;
-  }
-
-  srcp = linsrc->crpix;
-  dstp = lindst->crpix;
-  for (j = 0; j < naxis; j++) {
-    *(dstp++) = *(srcp++);
-  }
-
-  srcp = linsrc->pc;
-  dstp = lindst->pc;
-  for (i = 0; i < naxis; i++) {
-    for (j = 0; j < naxis; j++) {
-      *(dstp++) = *(srcp++);
-    }
-  }
-
-  srcp = linsrc->cdelt;
-  dstp = lindst->cdelt;
-  for (i = 0; i < naxis; i++) {
-    *(dstp++) = *(srcp++);
-  }
-
-  return 0;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int linfree(lin)
-
-struct linprm *lin;
-
-{
-  if (lin == 0x0) return LINERR_NULL_POINTER;
-
-  if (lin->flag != -1) {
-    /* Free memory allocated by linini(). */
-    if (lin->m_flag == LINSET) {
-      if (lin->crpix == lin->m_crpix) lin->crpix = 0x0;
-      if (lin->pc    == lin->m_pc)    lin->pc    = 0x0;
-      if (lin->cdelt == lin->m_cdelt) lin->cdelt = 0x0;
-
-      if (lin->m_crpix) free(lin->m_crpix);
-      if (lin->m_pc)    free(lin->m_pc);
-      if (lin->m_cdelt) free(lin->m_cdelt);
-    }
-  }
-
-  lin->m_flag  = 0;
-  lin->m_naxis = 0;
-  lin->m_crpix = 0x0;
-  lin->m_pc    = 0x0;
-  lin->m_cdelt = 0x0;
-
-
-  /* Free memory allocated by linset(). */
-  if (lin->flag == LINSET) {
-    if (lin->piximg) free(lin->piximg);
-    if (lin->imgpix) free(lin->imgpix);
-  }
-
-  lin->piximg = 0x0;
-  lin->imgpix = 0x0;
-  lin->i_naxis = 0;
-
-  if (lin->err) free(lin->err);
-  lin->err = 0x0;
-
-  lin->flag = 0;
-
-  return 0;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int linprt(lin)
-
-const struct linprm *lin;
-
-{
-  int i, j, k;
-
-  if (lin == 0x0) return LINERR_NULL_POINTER;
-
-  if (lin->flag != LINSET) {
-    wcsprintf("The linprm struct is UNINITIALIZED.\n");
-    return 0;
-  }
-
-  wcsprintf("       flag: %d\n", lin->flag);
-  wcsprintf("      naxis: %d\n", lin->naxis);
-  WCSPRINTF_PTR("      crpix: ", lin->crpix, "\n");
-  wcsprintf("            ");
-  for (i = 0; i < lin->naxis; i++) {
-    wcsprintf("  %- 11.5g", lin->crpix[i]);
-  }
-  wcsprintf("\n");
-
-  k = 0;
-  WCSPRINTF_PTR("         pc: ", lin->pc, "\n");
-  for (i = 0; i < lin->naxis; i++) {
-    wcsprintf("    pc[%d][]:", i);
-    for (j = 0; j < lin->naxis; j++) {
-      wcsprintf("  %- 11.5g", lin->pc[k++]);
-    }
-    wcsprintf("\n");
-  }
-
-  WCSPRINTF_PTR("      cdelt: ", lin->cdelt, "\n");
-  wcsprintf("            ");
-  for (i = 0; i < lin->naxis; i++) {
-    wcsprintf("  %- 11.5g", lin->cdelt[i]);
-  }
-  wcsprintf("\n");
-
-  wcsprintf("      unity: %d\n", lin->unity);
-
-  WCSPRINTF_PTR("        err: ", lin->err, "\n");
-  if (lin->err) {
-    wcserr_prt(lin->err, "             ");
-  }
-
-  if (lin->piximg == 0x0) {
-    wcsprintf("     piximg: (nil)\n");
-  } else {
-    k = 0;
-    for (i = 0; i < lin->naxis; i++) {
-      wcsprintf("piximg[%d][]:", i);
-      for (j = 0; j < lin->naxis; j++) {
-        wcsprintf("  %- 11.5g", lin->piximg[k++]);
-      }
-      wcsprintf("\n");
-    }
-  }
-
-  if (lin->imgpix == 0x0) {
-    wcsprintf("     imgpix: (nil)\n");
-  } else {
-    k = 0;
-    for (i = 0; i < lin->naxis; i++) {
-      wcsprintf("imgpix[%d][]:", i);
-      for (j = 0; j < lin->naxis; j++) {
-        wcsprintf("  %- 11.5g", lin->imgpix[k++]);
-      }
-      wcsprintf("\n");
-    }
-  }
-
-  wcsprintf("     m_flag: %d\n", lin->m_flag);
-  wcsprintf("    m_naxis: %d\n", lin->m_naxis);
-  WCSPRINTF_PTR("    m_crpix: ", lin->m_crpix, "");
-  if (lin->m_crpix == lin->crpix) wcsprintf("  (= crpix)");
-  wcsprintf("\n");
-  WCSPRINTF_PTR("       m_pc: ", lin->m_pc, "");
-  if (lin->m_pc == lin->pc) wcsprintf("  (= pc)");
-  wcsprintf("\n");
-  WCSPRINTF_PTR("    m_cdelt: ", lin->m_cdelt, "");
-  if (lin->m_cdelt == lin->cdelt) wcsprintf("  (= cdelt)");
-  wcsprintf("\n");
-
-  return 0;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int linset(lin)
-
-struct linprm *lin;
-
-{
-  static const char *function = "linset";
-
-  int i, j, n, status;
-  double *pc, *piximg;
-  struct wcserr **err;
-
-  if (lin == 0x0) return LINERR_NULL_POINTER;
-  err = &(lin->err);
-
-  n = lin->naxis;
-
-  /* Check for a unit matrix. */
-  lin->unity = 1;
-  pc = lin->pc;
-  for (i = 0; i < n; i++) {
-    for (j = 0; j < n; j++) {
-      if (j == i) {
-        if (*(pc++) != 1.0) {
-          lin->unity = 0;
-          break;
-        }
-      } else {
-        if (*(pc++) != 0.0) {
-          lin->unity = 0;
-          break;
-        }
-      }
-    }
-  }
-
-
-  if (lin->unity) {
-    if (lin->flag == LINSET) {
-      /* Free memory that may have been allocated previously. */
-      if (lin->piximg) free(lin->piximg);
-      if (lin->imgpix) free(lin->imgpix);
-    }
-
-    lin->piximg = 0x0;
-    lin->imgpix = 0x0;
-    lin->i_naxis = 0;
-
-  } else {
-    if (lin->flag != LINSET || lin->i_naxis < n) {
-      if (lin->flag == LINSET) {
-        /* Free memory that may have been allocated previously. */
-        if (lin->piximg) free(lin->piximg);
-        if (lin->imgpix) free(lin->imgpix);
-      }
-
-      /* Allocate memory for internal arrays. */
-      if (!(lin->piximg = calloc(n*n, sizeof(double)))) {
-        return wcserr_set(LIN_ERRMSG(LINERR_MEMORY));
-      }
-
-      if (!(lin->imgpix = calloc(n*n, sizeof(double)))) {
-        free(lin->piximg);
-        return wcserr_set(LIN_ERRMSG(LINERR_MEMORY));
-      }
-
-      lin->i_naxis = n;
-    }
-
-    /* Compute the pixel-to-image transformation matrix. */
-    pc     = lin->pc;
-    piximg = lin->piximg;
-    for (i = 0; i < n; i++) {
-      for (j = 0; j < n; j++) {
-        *(piximg++) = lin->cdelt[i] * (*(pc++));
-      }
-    }
-
-    /* Compute the image-to-pixel transformation matrix. */
-    if ((status = matinv(n, lin->piximg, lin->imgpix))) {
-      return wcserr_set(LIN_ERRMSG(status));
-    }
-  }
-
-
-  lin->flag = LINSET;
-
-  return 0;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int linp2x(lin, ncoord, nelem, pixcrd, imgcrd)
-
-struct linprm *lin;
-int ncoord, nelem;
-const double pixcrd[];
-double imgcrd[];
-
-{
-  int i, j, k, n, status;
-  double temp;
-  register const double *pix;
-  register double *img, *piximg;
-
-
-  /* Initialize. */
-  if (lin == 0x0) return LINERR_NULL_POINTER;
-  if (lin->flag != LINSET) {
-    if ((status = linset(lin))) return status;
-  }
-
-  n = lin->naxis;
-
-
-  /* Convert pixel coordinates to intermediate world coordinates. */
-  pix = pixcrd;
-  img = imgcrd;
-
-  if (lin->unity) {
-    for (k = 0; k < ncoord; k++) {
-      for (i = 0; i < n; i++) {
-        *(img++) = lin->cdelt[i] * (*(pix++) - lin->crpix[i]);
-      }
-
-      pix += (nelem - n);
-      img += (nelem - n);
-    }
-
-  } else {
-    for (k = 0; k < ncoord; k++) {
-      for (i = 0; i < n; i++) {
-        img[i] = 0.0;
-      }
-
-      for (j = 0; j < n; j++) {
-        /* Column-wise multiplication allows this to be cached. */
-        temp = *(pix++) - lin->crpix[j];
-
-        piximg = lin->piximg + j;
-        for (i = 0; i < n; i++, piximg += n) {
-          img[i] += *piximg * temp;
-        }
-      }
-
-      pix += (nelem - n);
-      img += nelem;
-    }
-  }
-
-  return 0;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int linx2p(lin, ncoord, nelem, imgcrd, pixcrd)
-
-struct linprm *lin;
-int ncoord, nelem;
-const double imgcrd[];
-double pixcrd[];
-
-{
-  int i, j, k, n, status;
-  register const double *img;
-  register double *imgpix, *pix;
-
-
-  /* Initialize. */
-  if (lin == 0x0) return LINERR_NULL_POINTER;
-  if (lin->flag != LINSET) {
-    if ((status = linset(lin))) return status;
-  }
-
-  n = lin->naxis;
-
-
-  /* Convert intermediate world coordinates to pixel coordinates. */
-  img = imgcrd;
-  pix = pixcrd;
-
-  if (lin->unity) {
-    for (k = 0; k < ncoord; k++) {
-      for (j = 0; j < n; j++) {
-        *(pix++) = (*(img++) / lin->cdelt[j]) + lin->crpix[j];
-      }
-
-      pix += (nelem - n);
-      img += (nelem - n);
-    }
-
-  } else {
-    for (k = 0; k < ncoord; k++) {
-      imgpix = lin->imgpix;
-
-      for (j = 0; j < n; j++) {
-        *pix = 0.0;
-        for (i = 0; i < n; i++) {
-          *pix += *imgpix * img[i];
-          imgpix++;
-        }
-
-        *(pix++) += lin->crpix[j];
-      }
-
-      pix += (nelem - n);
-      img += nelem;
-    }
-  }
-
-  return 0;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int matinv(int n, const double mat[], double inv[])
-
-{
-  register int i, ij, ik, j, k, kj, pj;
-  int    itemp, *mxl, *lxm, pivot;
-  double colmax, *lu, *rowmax, dtemp;
-
-
-  /* Allocate memory for internal arrays. */
-  if (!(mxl = calloc(n, sizeof(int)))) {
-    return LINERR_MEMORY;
-  }
-  if (!(lxm = calloc(n, sizeof(int)))) {
-    free(mxl);
-    return LINERR_MEMORY;
-  }
-
-  if (!(rowmax = calloc(n, sizeof(double)))) {
-    free(mxl);
-    free(lxm);
-    return LINERR_MEMORY;
-  }
-
-  if (!(lu = calloc(n*n, sizeof(double)))) {
-    free(mxl);
-    free(lxm);
-    free(rowmax);
-    return LINERR_MEMORY;
-  }
-
-
-  /* Initialize arrays. */
-  for (i = 0, ij = 0; i < n; i++) {
-    /* Vector that records row interchanges. */
-    mxl[i] = i;
-
-    rowmax[i] = 0.0;
-
-    for (j = 0; j < n; j++, ij++) {
-      dtemp = fabs(mat[ij]);
-      if (dtemp > rowmax[i]) rowmax[i] = dtemp;
-
-      lu[ij] = mat[ij];
-    }
-
-    /* A row of zeroes indicates a singular matrix. */
-    if (rowmax[i] == 0.0) {
-      free(mxl);
-      free(lxm);
-      free(rowmax);
-      free(lu);
-      return LINERR_SINGULAR_MTX;
-    }
-  }
-
-
-  /* Form the LU triangular factorization using scaled partial pivoting. */
-  for (k = 0; k < n; k++) {
-    /* Decide whether to pivot. */
-    colmax = fabs(lu[k*n+k]) / rowmax[k];
-    pivot = k;
-
-    for (i = k+1; i < n; i++) {
-      ik = i*n + k;
-      dtemp = fabs(lu[ik]) / rowmax[i];
-      if (dtemp > colmax) {
-        colmax = dtemp;
-        pivot = i;
-      }
-    }
-
-    if (pivot > k) {
-      /* We must pivot, interchange the rows of the design matrix. */
-      for (j = 0, pj = pivot*n, kj = k*n; j < n; j++, pj++, kj++) {
-        dtemp = lu[pj];
-        lu[pj] = lu[kj];
-        lu[kj] = dtemp;
-      }
-
-      /* Amend the vector of row maxima. */
-      dtemp = rowmax[pivot];
-      rowmax[pivot] = rowmax[k];
-      rowmax[k] = dtemp;
-
-      /* Record the interchange for later use. */
-      itemp = mxl[pivot];
-      mxl[pivot] = mxl[k];
-      mxl[k] = itemp;
-    }
-
-    /* Gaussian elimination. */
-    for (i = k+1; i < n; i++) {
-      ik = i*n + k;
-
-      /* Nothing to do if lu[ik] is zero. */
-      if (lu[ik] != 0.0) {
-        /* Save the scaling factor. */
-        lu[ik] /= lu[k*n+k];
-
-        /* Subtract rows. */
-        for (j = k+1; j < n; j++) {
-          lu[i*n+j] -= lu[ik]*lu[k*n+j];
-        }
-      }
-    }
-  }
-
-
-  /* mxl[i] records which row of mat corresponds to row i of lu.  */
-  /* lxm[i] records which row of lu  corresponds to row i of mat. */
-  for (i = 0; i < n; i++) {
-    lxm[mxl[i]] = i;
-  }
-
-
-  /* Determine the inverse matrix. */
-  for (i = 0, ij = 0; i < n; i++) {
-    for (j = 0; j < n; j++, ij++) {
-      inv[ij] = 0.0;
-    }
-  }
-
-  for (k = 0; k < n; k++) {
-    inv[lxm[k]*n+k] = 1.0;
-
-    /* Forward substitution. */
-    for (i = lxm[k]+1; i < n; i++) {
-      for (j = lxm[k]; j < i; j++) {
-        inv[i*n+k] -= lu[i*n+j]*inv[j*n+k];
-      }
-    }
-
-    /* Backward substitution. */
-    for (i = n-1; i >= 0; i--) {
-      for (j = i+1; j < n; j++) {
-        inv[i*n+k] -= lu[i*n+j]*inv[j*n+k];
-      }
-      inv[i*n+k] /= lu[i*n+i];
-    }
-   }
-
-   free(mxl);
-   free(lxm);
-   free(rowmax);
-   free(lu);
-
-   return 0;
-}
diff --git a/astropy/wcs/src/wcslib/C/lin.h b/astropy/wcs/src/wcslib/C/lin.h
deleted file mode 100644
index 8c8526a..0000000
--- a/astropy/wcs/src/wcslib/C/lin.h
+++ /dev/null
@@ -1,454 +0,0 @@
-/*============================================================================
-
-  WCSLIB 4.10 - an implementation of the FITS WCS standard.
-  Copyright (C) 1995-2012, Mark Calabretta
-
-  This file is part of WCSLIB.
-
-  WCSLIB is free software: you can redistribute it and/or modify it under the
-  terms of the GNU Lesser General Public License as published by the Free
-  Software Foundation, either version 3 of the License, or (at your option)
-  any later version.
-
-  WCSLIB 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 Lesser General Public License for
-  more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with WCSLIB.  If not, see <http://www.gnu.org/licenses/>.
-
-  Correspondence concerning WCSLIB may be directed to:
-    Internet email: mcalabre at atnf.csiro.au
-    Postal address: Dr. Mark Calabretta
-                    Australia Telescope National Facility, CSIRO
-                    PO Box 76
-                    Epping NSW 1710
-                    AUSTRALIA
-
-  Author: Mark Calabretta, Australia Telescope National Facility
-  http://www.atnf.csiro.au/~mcalabre/index.html
-  $Id: lin.h,v 4.10 2012/02/05 23:41:44 cal103 Exp $
-*=============================================================================
-*
-* WCSLIB 4.10 - C routines that implement the FITS World Coordinate System
-* (WCS) standard.  Refer to
-*
-*   "Representations of world coordinates in FITS",
-*   Greisen, E.W., & Calabretta, M.R. 2002, A&A, 395, 1061 (Paper I)
-*
-* Refer to the README file provided with WCSLIB for an overview of the
-* library.
-*
-*
-* Summary of the lin routines
-* ---------------------------
-* These routines apply the linear transformation defined by the FITS WCS
-* standard.  They are based on the linprm struct which contains all
-* information needed for the computations.  The struct contains some members
-* that must be set by the user, and others that are maintained by these
-* routines, somewhat like a C++ class but with no encapsulation.
-*
-* Three routines, linini(), lincpy(), and linfree() are provided to manage the
-* linprm struct, and another, linprt(), prints its contents.
-*
-* A setup routine, linset(), computes intermediate values in the linprm struct
-* from parameters in it that were supplied by the user.  The struct always
-* needs to be set up by linset() but need not be called explicitly - refer to
-* the explanation of linprm::flag.
-*
-* linp2x() and linx2p() implement the WCS linear transformations.
-*
-* An auxiliary matrix inversion routine, matinv(), is included.  It uses
-* LU-triangular factorization with scaled partial pivoting.
-*
-*
-* linini() - Default constructor for the linprm struct
-* ----------------------------------------------------
-* linini() allocates memory for arrays in a linprm struct and sets all members
-* of the struct to default values.
-*
-* PLEASE NOTE: every linprm struct should be initialized by linini(), possibly
-* repeatedly.  On the first invokation, and only the first invokation,
-* linprm::flag must be set to -1 to initialize memory management, regardless
-* of whether linini() will actually be used to allocate memory.
-*
-* Given:
-*   alloc     int       If true, allocate memory unconditionally for arrays in
-*                       the linprm struct.
-*
-*                       If false, it is assumed that pointers to these arrays
-*                       have been set by the user except if they are null
-*                       pointers in which case memory will be allocated for
-*                       them regardless.  (In other words, setting alloc true
-*                       saves having to initalize these pointers to zero.)
-*
-*   naxis     int       The number of world coordinate axes, used to determine
-*                       array sizes.
-*
-* Given and returned:
-*   lin       struct linprm*
-*                       Linear transformation parameters.  Note that, in order
-*                       to initialize memory management linprm::flag should be
-*                       set to -1 when lin is initialized for the first time
-*                       (memory leaks may result if it had already been
-*                       initialized).
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         1: Null linprm pointer passed.
-*                         2: Memory allocation failed.
-*
-*                       For returns > 1, a detailed error message is set in
-*                       linprm::err if enabled, see wcserr_enable().
-*
-*
-* lincpy() - Copy routine for the linprm struct
-* ---------------------------------------------
-* lincpy() does a deep copy of one linprm struct to another, using linini() to
-* allocate memory for its arrays if required.  Only the "information to be
-* provided" part of the struct is copied; a call to linset() is required to
-* initialize the remainder.
-*
-* Given:
-*   alloc     int       If true, allocate memory for the crpix, pc, and cdelt
-*                       arrays in the destination.  Otherwise, it is assumed
-*                       that pointers to these arrays have been set by the
-*                       user except if they are null pointers in which case
-*                       memory will be allocated for them regardless.
-*
-*   linsrc    const struct linprm*
-*                       Struct to copy from.
-*
-* Given and returned:
-*   lindst    struct linprm*
-*                       Struct to copy to.  linprm::flag should be set to -1
-*                       if lindst was not previously initialized (memory leaks
-*                       may result if it was previously initialized).
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         1: Null linprm pointer passed.
-*                         2: Memory allocation failed.
-*
-*                       For returns > 1, a detailed error message is set in
-*                       linprm::err if enabled, see wcserr_enable().
-*
-*
-* linfree() - Destructor for the linprm struct
-* --------------------------------------------
-* linfree() frees memory allocated for the linprm arrays by linini() and/or
-* linset().  linini() keeps a record of the memory it allocates and linfree()
-* will only attempt to free this.
-*
-* PLEASE NOTE: linfree() must not be invoked on a linprm struct that was not
-* initialized by linini().
-*
-* Given:
-*   lin       struct linprm*
-*                       Linear transformation parameters.
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         1: Null linprm pointer passed.
-*
-*
-* linprt() - Print routine for the linprm struct
-* ----------------------------------------------
-* linprt() prints the contents of a linprm struct using wcsprintf().  Mainly
-* intended for diagnostic purposes.
-*
-* Given:
-*   lin       const struct linprm*
-*                       Linear transformation parameters.
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         1: Null linprm pointer passed.
-*
-*
-* linset() - Setup routine for the linprm struct
-* ----------------------------------------------
-* linset(), if necessary, allocates memory for the linprm::piximg and
-* linprm::imgpix arrays and sets up the linprm struct according to information
-* supplied within it - refer to the explanation of linprm::flag.
-*
-* Note that this routine need not be called directly; it will be invoked by
-* linp2x() and linx2p() if the linprm::flag is anything other than a
-* predefined magic value.
-*
-* Given and returned:
-*   lin       struct linprm*
-*                       Linear transformation parameters.
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         1: Null linprm pointer passed.
-*                         2: Memory allocation failed.
-*                         3: PCi_ja matrix is singular.
-*
-*                       For returns > 1, a detailed error message is set in
-*                       linprm::err if enabled, see wcserr_enable().
-*
-*
-* linp2x() - Pixel-to-world linear transformation
-* -----------------------------------------------
-* linp2x() transforms pixel coordinates to intermediate world coordinates.
-*
-* Given and returned:
-*   lin       struct linprm*
-*                       Linear transformation parameters.
-*
-* Given:
-*   ncoord,
-*   nelem     int       The number of coordinates, each of vector length nelem
-*                       but containing lin.naxis coordinate elements.
-*
-*   pixcrd    const double[ncoord][nelem]
-*                       Array of pixel coordinates.
-*
-* Returned:
-*   imgcrd    double[ncoord][nelem]
-*                       Array of intermediate world coordinates.
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         1: Null linprm pointer passed.
-*                         2: Memory allocation failed.
-*                         3: PCi_ja matrix is singular.
-*
-*                       For returns > 1, a detailed error message is set in
-*                       linprm::err if enabled, see wcserr_enable().
-*
-*
-* linx2p() - World-to-pixel linear transformation
-* -----------------------------------------------
-* linx2p() transforms intermediate world coordinates to pixel coordinates.
-*
-* Given and returned:
-*   lin       struct linprm*
-*                       Linear transformation parameters.
-*
-* Given:
-*   ncoord,
-*   nelem     int       The number of coordinates, each of vector length nelem
-*                       but containing lin.naxis coordinate elements.
-*
-*   imgcrd   const double[ncoord][nelem]
-*                       Array of intermediate world coordinates.
-*
-* Returned:
-*   pixcrd    double[ncoord][nelem]
-*                       Array of pixel coordinates.
-*
-*             int       Status return value:
-*                         0: Success.
-*                         1: Null linprm pointer passed.
-*                         2: Memory allocation failed.
-*                         3: PCi_ja matrix is singular.
-*
-*                       For returns > 1, a detailed error message is set in
-*                       linprm::err if enabled, see wcserr_enable().
-*
-*
-* linprm struct - Linear transformation parameters
-* ------------------------------------------------
-* The linprm struct contains all of the information required to perform a
-* linear transformation.  It consists of certain members that must be set by
-* the user ("given") and others that are set by the WCSLIB routines
-* ("returned").
-*
-*   int flag
-*     (Given and returned) This flag must be set to zero whenever any of the
-*     following members of the linprm struct are set or modified:
-*
-*       - linprm::naxis (q.v., not normally set by the user),
-*       - linprm::pc,
-*       - linprm::cdelt.
-*
-*     This signals the initialization routine, linset(), to recompute the
-*     returned members of the linprm struct.  linset() will reset flag to
-*     indicate that this has been done.
-*
-*     PLEASE NOTE: flag should be set to -1 when linini() is called for the
-*     first time for a particular linprm struct in order to initialize memory
-*     management.  It must ONLY be used on the first initialization otherwise
-*     memory leaks may result.
-*
-*   int naxis
-*     (Given or returned) Number of pixel and world coordinate elements.
-*
-*     If linini() is used to initialize the linprm struct (as would normally
-*     be the case) then it will set naxis from the value passed to it as a
-*     function argument.  The user should not subsequently modify it.
-*
-*   double *crpix
-*     (Given) Pointer to the first element of an array of double containing
-*     the coordinate reference pixel, CRPIXja.
-*
-*   double *pc
-*     (Given) Pointer to the first element of the PCi_ja (pixel coordinate)
-*     transformation matrix.  The expected order is
-*
-=       struct linprm lin;
-=       lin.pc = {PC1_1, PC1_2, PC2_1, PC2_2};
-*
-*     This may be constructed conveniently from a 2-D array via
-*
-=       double m[2][2] = {{PC1_1, PC1_2},
-=                         {PC2_1, PC2_2}};
-*
-*     which is equivalent to
-*
-=       double m[2][2];
-=       m[0][0] = PC1_1;
-=       m[0][1] = PC1_2;
-=       m[1][0] = PC2_1;
-=       m[1][1] = PC2_2;
-*
-*     The storage order for this 2-D array is the same as for the 1-D array,
-*     whence
-*
-=       lin.pc = *m;
-*
-*     would be legitimate.
-*
-*   double *cdelt
-*     (Given) Pointer to the first element of an array of double containing
-*     the coordinate increments, CDELTia.
-*
-*   int unity
-*     (Returned) True if the linear transformation matrix is unity.
-*
-*   int padding
-*     (An unused variable inserted for alignment purposes only.)
-*
-*   double *piximg
-*     (Returned) Pointer to the first element of the matrix containing the
-*     product of the CDELTia diagonal matrix and the PCi_ja matrix.
-*
-*   double *imgpix
-*     (Returned) Pointer to the first element of the inverse of the
-*     linprm::piximg matrix.
-*
-*   struct wcserr *err
-*     (Returned) If enabled, when an error status is returned this struct
-*     contains detailed information about the error, see wcserr_enable().
-*
-*   int i_naxis
-*     (For internal use only.)
-*   int m_flag
-*     (For internal use only.)
-*   int m_naxis
-*     (For internal use only.)
-*   int m_padding
-*     (For internal use only.)
-*   double *m_crpix
-*     (For internal use only.)
-*   double *m_pc
-*     (For internal use only.)
-*   double *m_cdelt
-*     (For internal use only.)
-*   void *padding2
-*     (For internal use only.)
-*
-*
-* Global variable: const char *lin_errmsg[] - Status return messages
-* ------------------------------------------------------------------
-* Error messages to match the status value returned from each function.
-*
-*===========================================================================*/
-
-#ifndef WCSLIB_LIN
-#define WCSLIB_LIN
-
-#include "wcserr.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-extern const char *lin_errmsg[];
-
-enum lin_errmsg_enum {
-  LINERR_SUCCESS      = 0,	/* Success. */
-  LINERR_NULL_POINTER = 1,	/* Null linprm pointer passed. */
-  LINERR_MEMORY       = 2,	/* Memory allocation failed. */
-  LINERR_SINGULAR_MTX = 3 	/* PCi_ja matrix is singular. */
-};
-
-struct linprm {
-  /* Initialization flag (see the prologue above).                          */
-  /*------------------------------------------------------------------------*/
-  int flag;			/* Set to zero to force initialization.     */
-
-  /* Parameters to be provided (see the prologue above).                    */
-  /*------------------------------------------------------------------------*/
-  int naxis;			/* The number of axes, given by NAXIS.      */
-  double *crpix;		/* CRPIXja keywords for each pixel axis.    */
-  double *pc;			/* PCi_ja  linear transformation matrix.    */
-  double *cdelt;		/* CDELTia keywords for each coord axis.    */
-
-  /* Information derived from the parameters supplied.                      */
-  /*------------------------------------------------------------------------*/
-  double *piximg;		/* Product of CDELTia and PCi_ja matrices.  */
-  double *imgpix;		/* Inverse of the piximg matrix.            */
-  int    unity;			/* True if the PCi_ja matrix is unity.      */
-
-  /* Error handling                                                         */
-  /*------------------------------------------------------------------------*/
-  int    padding;		/* (Dummy inserted for alignment purposes.) */
-  struct wcserr *err;
-
-  /* Private - the remainder are for memory management.                     */
-  /*------------------------------------------------------------------------*/
-  int    i_naxis;
-  int    m_flag, m_naxis, m_padding;
-  double *m_crpix, *m_pc, *m_cdelt;
-  void   *padding2;
-};
-
-/* Size of the linprm struct in int units, used by the Fortran wrappers. */
-#define LINLEN (sizeof(struct linprm)/sizeof(int))
-
-
-int linini(int alloc, int naxis, struct linprm *lin);
-
-int lincpy(int alloc, const struct linprm *linsrc, struct linprm *lindst);
-
-int linfree(struct linprm *lin);
-
-int linprt(const struct linprm *lin);
-
-int linset(struct linprm *lin);
-
-int linp2x(struct linprm *lin, int ncoord, int nelem, const double pixcrd[],
-           double imgcrd[]);
-
-int linx2p(struct linprm *lin, int ncoord, int nelem, const double imgcrd[],
-           double pixcrd[]);
-
-int matinv(int n, const double mat[], double inv[]);
-
-
-/* Deprecated. */
-#define linini_errmsg lin_errmsg
-#define lincpy_errmsg lin_errmsg
-#define linfree_errmsg lin_errmsg
-#define linprt_errmsg lin_errmsg
-#define linset_errmsg lin_errmsg
-#define linp2x_errmsg lin_errmsg
-#define linx2p_errmsg lin_errmsg
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* WCSLIB_LIN */
diff --git a/astropy/wcs/src/wcslib/C/log.c b/astropy/wcs/src/wcslib/C/log.c
deleted file mode 100644
index 9193564..0000000
--- a/astropy/wcs/src/wcslib/C/log.c
+++ /dev/null
@@ -1,118 +0,0 @@
-/*============================================================================
-
-  WCSLIB 4.10 - an implementation of the FITS WCS standard.
-  Copyright (C) 1995-2012, Mark Calabretta
-
-  This file is part of WCSLIB.
-
-  WCSLIB is free software: you can redistribute it and/or modify it under the
-  terms of the GNU Lesser General Public License as published by the Free
-  Software Foundation, either version 3 of the License, or (at your option)
-  any later version.
-
-  WCSLIB 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 Lesser General Public License for
-  more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with WCSLIB.  If not, see <http://www.gnu.org/licenses/>.
-
-  Correspondence concerning WCSLIB may be directed to:
-    Internet email: mcalabre at atnf.csiro.au
-    Postal address: Dr. Mark Calabretta
-                    Australia Telescope National Facility, CSIRO
-                    PO Box 76
-                    Epping NSW 1710
-                    AUSTRALIA
-
-  Author: Mark Calabretta, Australia Telescope National Facility
-  http://www.atnf.csiro.au/~mcalabre/index.html
-  $Id: log.c,v 4.10 2012/02/05 23:41:44 cal103 Exp $
-*===========================================================================*/
-
-#include <math.h>
-
-#include "log.h"
-
-/* Map status return value to message. */
-const char *log_errmsg[] = {
-  "Success",
-  "",
-  "Invalid log-coordinate reference value",
-  "One or more of the x coordinates were invalid",
-  "One or more of the world coordinates were invalid"};
-
-
-/*--------------------------------------------------------------------------*/
-
-int logx2s(
-  double crval,
-  int nx,
-  int sx,
-  int slogc,
-  const double x[],
-  double logc[],
-  int stat[])
-
-{
-  register int ix;
-  register int *statp;
-  register const double *xp;
-  register double *logcp;
-
-
-  if (crval <= 0.0) {
-    return LOGERR_BAD_LOG_REF_VAL;
-  }
-
-  xp = x;
-  logcp = logc;
-  statp = stat;
-  for (ix = 0; ix < nx; ix++, xp += sx, logcp += slogc) {
-    *logcp = crval * exp((*xp) / crval);
-    *(statp++) = 0;
-  }
-
-  return 0;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int logs2x(
-  double crval,
-  int nlogc,
-  int slogc,
-  int sx,
-  const double logc[],
-  double x[],
-  int stat[])
-
-{
-  int status;
-  register int ilogc;
-  register int *statp;
-  register const double *logcp;
-  register double *xp;
-
-
-  if (crval <= 0.0) {
-    return LOGERR_BAD_LOG_REF_VAL;
-  }
-
-  xp = x;
-  logcp = logc;
-  statp = stat;
-  status = 0;
-  for (ilogc = 0; ilogc < nlogc; ilogc++, logcp += slogc, xp += sx) {
-    if (*logcp > 0.0) {
-      *xp = crval * log(*logcp / crval);
-      *(statp++) = 0;
-    } else {
-      *(statp++) = 1;
-      status = LOGERR_BAD_WORLD;
-    }
-  }
-
-  return status;
-}
diff --git a/astropy/wcs/src/wcslib/C/log.h b/astropy/wcs/src/wcslib/C/log.h
deleted file mode 100644
index 609777d..0000000
--- a/astropy/wcs/src/wcslib/C/log.h
+++ /dev/null
@@ -1,172 +0,0 @@
-/*============================================================================
-
-  WCSLIB 4.10 - an implementation of the FITS WCS standard.
-  Copyright (C) 1995-2012, Mark Calabretta
-
-  This file is part of WCSLIB.
-
-  WCSLIB is free software: you can redistribute it and/or modify it under the
-  terms of the GNU Lesser General Public License as published by the Free
-  Software Foundation, either version 3 of the License, or (at your option)
-  any later version.
-
-  WCSLIB 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 Lesser General Public License for
-  more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with WCSLIB.  If not, see <http://www.gnu.org/licenses/>.
-
-  Correspondence concerning WCSLIB may be directed to:
-    Internet email: mcalabre at atnf.csiro.au
-    Postal address: Dr. Mark Calabretta
-                    Australia Telescope National Facility, CSIRO
-                    PO Box 76
-                    Epping NSW 1710
-                    AUSTRALIA
-
-  Author: Mark Calabretta, Australia Telescope National Facility
-  http://www.atnf.csiro.au/~mcalabre/index.html
-  $Id: log.h,v 4.10 2012/02/05 23:41:44 cal103 Exp $
-*=============================================================================
-*
-* WCSLIB 4.10 - C routines that implement logarithmic coordinate systems as
-* defined by the FITS World Coordinate System (WCS) standard.  Refer to
-*
-*   "Representations of world coordinates in FITS",
-*   Greisen, E.W., & Calabretta, M.R. 2002, A&A, 395, 1061 (Paper I)
-*
-*   "Representations of spectral coordinates in FITS",
-*   Greisen, E.W., Calabretta, M.R., Valdes, F.G., & Allen, S.L.
-*   2006, A&A, 446, 747 (Paper III)
-*
-* Refer to the README file provided with WCSLIB for an overview of the
-* library.
-*
-*
-* Summary of the log routines
-* ---------------------------
-* These routines implement the part of the FITS WCS standard that deals with
-* logarithmic coordinates.  They define methods to be used for computing
-* logarithmic world coordinates from intermediate world coordinates (a linear
-* transformation of image pixel coordinates), and vice versa.
-*
-* logx2s() and logs2x() implement the WCS logarithmic coordinate
-* transformations.
-*
-* Argument checking:
-* ------------------
-* The input log-coordinate values are only checked for values that would
-* result in floating point exceptions and the same is true for the
-* log-coordinate reference value.
-*
-* Accuracy:
-* ---------
-* No warranty is given for the accuracy of these routines (refer to the
-* copyright notice); intending users must satisfy for themselves their
-* adequacy for the intended purpose.  However, closure effectively to within
-* double precision rounding error was demonstrated by test routine tlog.c
-* which accompanies this software.
-*
-*
-* logx2s() - Transform to logarithmic coordinates
-* -----------------------------------------------
-* logx2s() transforms intermediate world coordinates to logarithmic
-* coordinates.
-*
-* Given and returned:
-*   crval     double    Log-coordinate reference value (CRVALia).
-*
-* Given:
-*   nx        int       Vector length.
-*
-*   sx        int       Vector stride.
-*
-*   slogc     int       Vector stride.
-*
-*   x         const double[]
-*                       Intermediate world coordinates, in SI units.
-*
-* Returned:
-*   logc      double[]  Logarithmic coordinates, in SI units.
-*
-*   stat      int[]     Status return value status for each vector element:
-*                         0: Success.
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         2: Invalid log-coordinate reference value.
-*
-*
-* logs2x() - Transform logarithmic coordinates
-* --------------------------------------------
-* logs2x() transforms logarithmic world coordinates to intermediate world
-* coordinates.
-*
-* Given and returned:
-*   crval     double    Log-coordinate reference value (CRVALia).
-*
-* Given:
-*   nlogc     int       Vector length.
-*
-*   slogc     int       Vector stride.
-*
-*   sx        int       Vector stride.
-*
-*   logc      const double[]
-*                       Logarithmic coordinates, in SI units.
-*
-* Returned:
-*   x         double[]  Intermediate world coordinates, in SI units.
-*
-*   stat      int[]     Status return value status for each vector element:
-*                         0: Success.
-*                         1: Invalid value of logc.
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         2: Invalid log-coordinate reference value.
-*                         4: One or more of the world-coordinate values
-*                            are incorrect, as indicated by the stat vector.
-*
-*
-* Global variable: const char *log_errmsg[] - Status return messages
-* ------------------------------------------------------------------
-* Error messages to match the status value returned from each function.
-*
-*===========================================================================*/
-
-#ifndef WCSLIB_LOG
-#define WCSLIB_LOG
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern const char *log_errmsg[];
-
-enum log_errmsg_enum {
-  LOGERR_SUCCESS         = 0,	/* Success. */
-  LOGERR_NULL_POINTER    = 1,	/* Null pointer passed. */
-  LOGERR_BAD_LOG_REF_VAL = 2,	/* Invalid log-coordinate reference value. */
-  LOGERR_BAD_X           = 3,	/* One or more of the x coordinates were
-				   invalid. */
-  LOGERR_BAD_WORLD       = 4 	/* One or more of the world coordinates were
-				   invalid. */
-};
-
-int logx2s(double crval, int nx, int sx, int slogc, const double x[],
-           double logc[], int stat[]);
-
-int logs2x(double crval, int nlogc, int slogc, int sx, const double logc[],
-           double x[], int stat[]);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* WCSLIB_LOG */
diff --git a/astropy/wcs/src/wcslib/C/prj.c b/astropy/wcs/src/wcslib/C/prj.c
deleted file mode 100644
index a4d6932..0000000
--- a/astropy/wcs/src/wcslib/C/prj.c
+++ /dev/null
@@ -1,7853 +0,0 @@
-/*============================================================================
-
-  WCSLIB 4.10 - an implementation of the FITS WCS standard.
-  Copyright (C) 1995-2012, Mark Calabretta
-
-  This file is part of WCSLIB.
-
-  WCSLIB is free software: you can redistribute it and/or modify it under the
-  terms of the GNU Lesser General Public License as published by the Free
-  Software Foundation, either version 3 of the License, or (at your option)
-  any later version.
-
-  WCSLIB 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 Lesser General Public License for
-  more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with WCSLIB.  If not, see <http://www.gnu.org/licenses/>.
-
-  Correspondence concerning WCSLIB may be directed to:
-    Internet email: mcalabre at atnf.csiro.au
-    Postal address: Dr. Mark Calabretta
-                    Australia Telescope National Facility, CSIRO
-                    PO Box 76
-                    Epping NSW 1710
-                    AUSTRALIA
-
-  Author: Mark Calabretta, Australia Telescope National Facility
-  http://www.atnf.csiro.au/~mcalabre/index.html
-  $Id: prj.c,v 4.10 2012/02/05 23:41:44 cal103 Exp $
-*===========================================================================*/
-
-#include <math.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "wcserr.h"
-#include "wcsmath.h"
-#include "wcsprintf.h"
-#include "wcstrig.h"
-#include "wcsutil.h"
-#include "prj.h"
-
-
-/* Projection categories. */
-const int ZENITHAL          = 1;
-const int CYLINDRICAL       = 2;
-const int PSEUDOCYLINDRICAL = 3;
-const int CONVENTIONAL      = 4;
-const int CONIC             = 5;
-const int POLYCONIC         = 6;
-const int QUADCUBE          = 7;
-const int HEALPIX           = 8;
-
-const char prj_categories[9][32] =
-  {"undefined", "zenithal", "cylindrical", "pseudocylindrical",
-  "conventional", "conic", "polyconic", "quadcube", "HEALPix"};
-
-
-/* Projection codes. */
-const int  prj_ncode = 27;
-const char prj_codes[27][4] =
-  {"AZP", "SZP", "TAN", "STG", "SIN", "ARC", "ZPN", "ZEA", "AIR", "CYP",
-   "CEA", "CAR", "MER", "COP", "COE", "COD", "COO", "SFL", "PAR", "MOL",
-   "AIT", "BON", "PCO", "TSC", "CSC", "QSC", "HPX"};
-
-const int AZP = 101;
-const int SZP = 102;
-const int TAN = 103;
-const int STG = 104;
-const int SIN = 105;
-const int ARC = 106;
-const int ZPN = 107;
-const int ZEA = 108;
-const int AIR = 109;
-const int CYP = 201;
-const int CEA = 202;
-const int CAR = 203;
-const int MER = 204;
-const int SFL = 301;
-const int PAR = 302;
-const int MOL = 303;
-const int AIT = 401;
-const int COP = 501;
-const int COE = 502;
-const int COD = 503;
-const int COO = 504;
-const int BON = 601;
-const int PCO = 602;
-const int TSC = 701;
-const int CSC = 702;
-const int QSC = 703;
-const int HPX = 801;
-
-
-/* Map status return value to message. */
-const char *prj_errmsg[] = {
-  "Success",
-  "Null prjprm pointer passed",
-  "Invalid projection parameters",
-  "One or more of the (x,y) coordinates were invalid",
-  "One or more of the (phi,theta) coordinates were invalid"};
-
-/* Convenience macros for generating common error messages. */
-#define PRJERR_BAD_PARAM_SET(function) \
-  wcserr_set(&(prj->err), PRJERR_BAD_PARAM, function, __FILE__, __LINE__, \
-    "Invalid parameters for %s projection", prj->name);
-
-#define PRJERR_BAD_PIX_SET(function) \
-  wcserr_set(&(prj->err), PRJERR_BAD_PIX, function, __FILE__, __LINE__, \
-    "One or more of the (x, y) coordinates were invalid for %s projection", \
-    prj->name);
-
-#define PRJERR_BAD_WORLD_SET(function) \
-  wcserr_set(&(prj->err), PRJERR_BAD_WORLD, function, __FILE__, __LINE__, \
-    "One or more of the (lat, lng) coordinates were invalid for " \
-    "%s projection", prj->name);
-
-#define copysign(X, Y) ((Y) < 0.0 ? -fabs(X) : fabs(X))
-
-
-/*============================================================================
-* Generic routines.
-*
-* prjini initializes a prjprm struct to default values.
-*
-* prjprt prints the contents of a prjprm struct.
-*
-* prjset invokes the specific initialization routine based on the projection
-*        code in the prjprm struct.
-*
-* prjx2s invokes the specific deprojection routine based on the pointer-to-
-*        function stored in the prjprm struct.
-*
-* prjs2x invokes the specific projection routine based on the pointer-to-
-*        function stored in the prjprm struct.
-*
-*---------------------------------------------------------------------------*/
-
-int prjini(prj)
-
-struct prjprm *prj;
-
-{
-  register int k;
-
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-
-  prj->flag = 0;
-
-  strcpy(prj->code, "   ");
-  prj->pv[0]  = 0.0;
-  prj->pv[1]  = UNDEFINED;
-  prj->pv[2]  = UNDEFINED;
-  prj->pv[3]  = UNDEFINED;
-  for (k = 4; k < PVN; prj->pv[k++] = 0.0);
-  prj->r0     = 0.0;
-  prj->phi0   = UNDEFINED;
-  prj->theta0 = UNDEFINED;
-  prj->bounds = 1;
-
-  strcpy(prj->name, "undefined");
-  for (k = 9; k < 40; prj->name[k++] = '\0');
-  prj->category  = 0;
-  prj->pvrange   = 0;
-  prj->simplezen = 0;
-  prj->equiareal = 0;
-  prj->conformal = 0;
-  prj->global    = 0;
-  prj->divergent = 0;
-  prj->x0 = 0.0;
-  prj->y0 = 0.0;
-  for (k = 0; k < 10; prj->w[k++] = 0.0);
-  prj->m = 0;
-  prj->n = 0;
-
-  prj->err = 0x0;
-
-  return 0;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int prjfree(prj)
-
-struct prjprm *prj;
-
-{
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-
-  if (prj->err) free(prj->err);
-  prj->err = 0x0;
-
-  return 0;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int prjprt(prj)
-
-const struct prjprm *prj;
-
-{
-  char hext[32];
-  int  i, n;
-
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-
-  wcsprintf("       flag: %d\n",  prj->flag);
-  wcsprintf("       code: \"%s\"\n",  prj->code);
-  wcsprintf("         r0: %9f\n", prj->r0);
-  wcsprintf("         pv:");
-  if (prj->pvrange) {
-    n = (prj->pvrange)%100;
-
-    if (prj->pvrange/100) {
-      wcsprintf(" (0)");
-    } else {
-      wcsprintf(" %- 11.5g", prj->pv[0]);
-      n--;
-    }
-
-    for (i = 1; i <= n; i++) {
-      if (i%5 == 1) {
-        wcsprintf("\n           ");
-      }
-
-      if (undefined(prj->pv[i])) {
-        wcsprintf("  UNDEFINED   ");
-      } else {
-        wcsprintf("  %- 11.5g", prj->pv[i]);
-      }
-    }
-    wcsprintf("\n");
-  } else {
-    wcsprintf(" (not used)\n");
-  }
-  if (undefined(prj->phi0)) {
-    wcsprintf("       phi0: UNDEFINED\n");
-  } else {
-    wcsprintf("       phi0: %9f\n", prj->phi0);
-  }
-  if (undefined(prj->theta0)) {
-    wcsprintf("     theta0: UNDEFINED\n");
-  } else {
-    wcsprintf("     theta0: %9f\n", prj->theta0);
-  }
-  wcsprintf("     bounds: %d\n",  prj->bounds);
-
-  wcsprintf("\n");
-  wcsprintf("       name: \"%s\"\n", prj->name);
-  wcsprintf("   category: %d (%s)\n", prj->category,
-                                      prj_categories[prj->category]);
-  wcsprintf("    pvrange: %d\n", prj->pvrange);
-  wcsprintf("  simplezen: %d\n", prj->simplezen);
-  wcsprintf("  equiareal: %d\n", prj->equiareal);
-  wcsprintf("  conformal: %d\n", prj->conformal);
-  wcsprintf("     global: %d\n", prj->global);
-  wcsprintf("  divergent: %d\n", prj->divergent);
-  wcsprintf("         x0: %f\n", prj->x0);
-  wcsprintf("         y0: %f\n", prj->y0);
-
-  WCSPRINTF_PTR("        err: ", prj->err, "\n");
-  if (prj->err) {
-    wcserr_prt(prj->err, "             ");
-  }
-
-  wcsprintf("        w[]:");
-  for (i = 0; i < 5; i++) {
-    wcsprintf("  %- 11.5g", prj->w[i]);
-  }
-  wcsprintf("\n            ");
-  for (i = 5; i < 10; i++) {
-    wcsprintf("  %- 11.5g", prj->w[i]);
-  }
-  wcsprintf("\n");
-  wcsprintf("          m: %d\n", prj->m);
-  wcsprintf("          n: %d\n", prj->n);
-  wcsprintf("     prjx2s: %s\n",
-    wcsutil_fptr2str((int (*)(void))prj->prjx2s, hext));
-  wcsprintf("     prjs2x: %s\n",
-    wcsutil_fptr2str((int (*)(void))prj->prjs2x, hext));
-
-  return 0;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int prjset(prj)
-
-struct prjprm *prj;
-
-{
-  static const char *function = "prjset";
-
-  int status;
-  struct wcserr **err;
-
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-  err = &(prj->err);
-
-  /* Invoke the relevant initialization routine. */
-  prj->code[3] = '\0';
-  if (strcmp(prj->code, "AZP") == 0) {
-    status = azpset(prj);
-  } else if (strcmp(prj->code, "SZP") == 0) {
-    status = szpset(prj);
-  } else if (strcmp(prj->code, "TAN") == 0) {
-    status = tanset(prj);
-  } else if (strcmp(prj->code, "STG") == 0) {
-    status = stgset(prj);
-  } else if (strcmp(prj->code, "SIN") == 0) {
-    status = sinset(prj);
-  } else if (strcmp(prj->code, "ARC") == 0) {
-    status = arcset(prj);
-  } else if (strcmp(prj->code, "ZPN") == 0) {
-    status = zpnset(prj);
-  } else if (strcmp(prj->code, "ZEA") == 0) {
-    status = zeaset(prj);
-  } else if (strcmp(prj->code, "AIR") == 0) {
-    status = airset(prj);
-  } else if (strcmp(prj->code, "CYP") == 0) {
-    status = cypset(prj);
-  } else if (strcmp(prj->code, "CEA") == 0) {
-    status = ceaset(prj);
-  } else if (strcmp(prj->code, "CAR") == 0) {
-    status = carset(prj);
-  } else if (strcmp(prj->code, "MER") == 0) {
-    status = merset(prj);
-  } else if (strcmp(prj->code, "SFL") == 0) {
-    status = sflset(prj);
-  } else if (strcmp(prj->code, "PAR") == 0) {
-    status = parset(prj);
-  } else if (strcmp(prj->code, "MOL") == 0) {
-    status = molset(prj);
-  } else if (strcmp(prj->code, "AIT") == 0) {
-    status = aitset(prj);
-  } else if (strcmp(prj->code, "COP") == 0) {
-    status = copset(prj);
-  } else if (strcmp(prj->code, "COE") == 0) {
-    status = coeset(prj);
-  } else if (strcmp(prj->code, "COD") == 0) {
-    status = codset(prj);
-  } else if (strcmp(prj->code, "COO") == 0) {
-    status = cooset(prj);
-  } else if (strcmp(prj->code, "BON") == 0) {
-    status = bonset(prj);
-  } else if (strcmp(prj->code, "PCO") == 0) {
-    status = pcoset(prj);
-  } else if (strcmp(prj->code, "TSC") == 0) {
-    status = tscset(prj);
-  } else if (strcmp(prj->code, "CSC") == 0) {
-    status = cscset(prj);
-  } else if (strcmp(prj->code, "QSC") == 0) {
-    status = qscset(prj);
-  } else if (strcmp(prj->code, "HPX") == 0) {
-    status = hpxset(prj);
-  } else {
-    /* Unrecognized projection code. */
-    status = wcserr_set(WCSERR_SET(PRJERR_BAD_PARAM),
-               "Unrecognized projection code '%s'", prj->code);
-  }
-
-  return status;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int prjx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)
-
-struct prjprm *prj;
-int nx, ny, sxy, spt;
-const double x[], y[];
-double phi[], theta[];
-int stat[];
-
-{
-  int status;
-
-  /* Initialize. */
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-  if (prj->flag == 0) {
-    if ((status = prjset(prj))) return status;
-  }
-
-  return prj->prjx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat);
-}
-
-/*--------------------------------------------------------------------------*/
-
-int prjs2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)
-
-struct prjprm *prj;
-int nphi, ntheta, spt, sxy;
-const double phi[], theta[];
-double x[], y[];
-int stat[];
-
-{
-  int status;
-
-  /* Initialize. */
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-  if (prj->flag == 0) {
-    if ((status = prjset(prj))) return status;
-  }
-
-  return prj->prjs2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat);
-}
-
-/*============================================================================
-* Internal helper routine used by the *set() routines that forces
-* (x,y) = (0,0) at (phi0,theta0).
-*---------------------------------------------------------------------------*/
-
-int prjoff(prj, phi0, theta0)
-
-struct prjprm *prj;
-const double phi0, theta0;
-
-{
-  int    stat;
-  double x0, y0;
-
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-
-  prj->x0 = 0.0;
-  prj->y0 = 0.0;
-
-  if (undefined(prj->phi0) || undefined(prj->theta0)) {
-    /* Set both to the projection-specific default if either undefined. */
-    prj->phi0   = phi0;
-    prj->theta0 = theta0;
-
-  } else {
-    if (prj->prjs2x(prj, 1, 1, 1, 1, &(prj->phi0), &(prj->theta0), &x0, &y0,
-                    &stat)) {
-      return PRJERR_BAD_PARAM_SET("prjoff");
-    }
-
-    prj->x0 = x0;
-    prj->y0 = y0;
-  }
-
-  return 0;
-}
-
-/*============================================================================
-*   AZP: zenithal/azimuthal perspective projection.
-*
-*   Given:
-*      prj->pv[1]   Distance parameter, mu in units of r0.
-*      prj->pv[2]   Tilt angle, gamma in degrees.
-*
-*   Given and/or returned:
-*      prj->r0      Reset to 180/pi if 0.
-*      prj->phi0    Reset to  0.0 if undefined.
-*      prj->theta0  Reset to 90.0 if undefined.
-*
-*   Returned:
-*      prj->flag     AZP
-*      prj->code    "AZP"
-*      prj->x0      Offset in x.
-*      prj->y0      Offset in y.
-*      prj->w[0]    r0*(mu+1)
-*      prj->w[1]    tan(gamma)
-*      prj->w[2]    sec(gamma)
-*      prj->w[3]    cos(gamma)
-*      prj->w[4]    sin(gamma)
-*      prj->w[5]    asin(-1/mu) for |mu| >= 1, -90 otherwise
-*      prj->w[6]    mu*cos(gamma)
-*      prj->w[7]    1 if |mu*cos(gamma)| < 1, 0 otherwise
-*      prj->prjx2s  Pointer to azpx2s().
-*      prj->prjs2x  Pointer to azps2x().
-*===========================================================================*/
-
-int azpset(prj)
-
-struct prjprm *prj;
-
-{
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-
-  prj->flag = AZP;
-  strcpy(prj->code, "AZP");
-
-  if (undefined(prj->pv[1])) prj->pv[1] = 0.0;
-  if (undefined(prj->pv[2])) prj->pv[2] = 0.0;
-  if (prj->r0 == 0.0) prj->r0 = R2D;
-
-  strcpy(prj->name, "zenithal/azimuthal perspective");
-  prj->category  = ZENITHAL;
-  prj->pvrange   = 102;
-  prj->simplezen = prj->pv[2] == 0.0;
-  prj->equiareal = 0;
-  prj->conformal = 0;
-  prj->global    = 0;
-  prj->divergent = prj->pv[1] <= 1.0;
-
-  prj->w[0] = prj->r0*(prj->pv[1] + 1.0);
-  if (prj->w[0] == 0.0) {
-    return PRJERR_BAD_PARAM_SET("azpset");
-  }
-
-  prj->w[3] = cosd(prj->pv[2]);
-  if (prj->w[3] == 0.0) {
-    return PRJERR_BAD_PARAM_SET("azpset");
-  }
-
-  prj->w[2] = 1.0/prj->w[3];
-  prj->w[4] = sind(prj->pv[2]);
-  prj->w[1] = prj->w[4] / prj->w[3];
-
-  if (fabs(prj->pv[1]) > 1.0) {
-    prj->w[5] = asind(-1.0/prj->pv[1]);
-  } else {
-    prj->w[5] = -90.0;
-  }
-
-  prj->w[6] = prj->pv[1] * prj->w[3];
-  prj->w[7] = (fabs(prj->w[6]) < 1.0) ? 1.0 : 0.0;
-
-  prj->prjx2s = azpx2s;
-  prj->prjs2x = azps2x;
-
-  return prjoff(prj, 0.0, 90.0);
-}
-
-/*--------------------------------------------------------------------------*/
-
-int azpx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)
-
-struct prjprm *prj;
-int nx, ny, sxy, spt;
-const double x[], y[];
-double phi[], theta[];
-int stat[];
-
-{
-  int mx, my, rowlen, rowoff, status;
-  double a, b, q, r, s, t, xj, yj, yc, yc2;
-  const double tol = 1.0e-13;
-  register int ix, iy, *statp;
-  register const double *xp, *yp;
-  register double *phip, *thetap;
-
-
-  /* Initialize. */
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-  if (prj->flag != AZP) {
-    if ((status = azpset(prj))) return status;
-  }
-
-  if (ny > 0) {
-    mx = nx;
-    my = ny;
-  } else {
-    mx = 1;
-    my = 1;
-    ny = nx;
-  }
-
-  status = 0;
-
-
-  /* Do x dependence. */
-  xp = x;
-  rowoff = 0;
-  rowlen = nx*spt;
-  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
-    xj = *xp + prj->x0;
-
-    phip = phi + rowoff;
-    for (iy = 0; iy < my; iy++) {
-      *phip = xj;
-      phip += rowlen;
-    }
-  }
-
-
-  /* Do y dependence. */
-  yp = y;
-  phip   = phi;
-  thetap = theta;
-  statp  = stat;
-  for (iy = 0; iy < ny; iy++, yp += sxy) {
-    yj = *yp + prj->y0;
-
-    yc  = yj*prj->w[3];
-    yc2 = yc*yc;
-
-    q = prj->w[0] + yj*prj->w[4];
-
-    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
-      xj = *phip;
-
-      r = sqrt(xj*xj + yc2);
-      if (r == 0.0) {
-        *phip = 0.0;
-        *thetap = 90.0;
-        *(statp++) = 0;
-
-      } else {
-        *phip = atan2d(xj, -yc);
-
-        s = r / q;
-        t = s*prj->pv[1]/sqrt(s*s + 1.0);
-
-        s = atan2d(1.0, s);
-
-        if (fabs(t) > 1.0) {
-          if (fabs(t) > 1.0+tol) {
-            *thetap = 0.0;
-            *(statp++) = 1;
-            if (!status) status = PRJERR_BAD_PIX_SET("azpx2s");
-            continue;
-          }
-          t = copysign(90.0, t);
-        } else {
-          t = asind(t);
-        }
-
-        a = s - t;
-        b = s + t + 180.0;
-
-        if (a > 90.0) a -= 360.0;
-        if (b > 90.0) b -= 360.0;
-
-        *thetap = (a > b) ? a : b;
-        *(statp++) = 0;
-      }
-    }
-  }
-
-  return status;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int azps2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)
-
-struct prjprm *prj;
-int nphi, ntheta, spt, sxy;
-const double phi[], theta[];
-double x[], y[];
-int stat[];
-
-{
-  int mphi, mtheta, rowlen, rowoff, status;
-  double a, b, cosphi, costhe, r, s, sinphi, sinthe, t;
-  register int iphi, itheta, istat, *statp;
-  register const double *phip, *thetap;
-  register double *xp, *yp;
-
-
-  /* Initialize. */
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-  if (prj->flag != AZP) {
-    if ((status = azpset(prj))) return status;
-  }
-
-  if (ntheta > 0) {
-    mphi   = nphi;
-    mtheta = ntheta;
-  } else {
-    mphi   = 1;
-    mtheta = 1;
-    ntheta = nphi;
-  }
-
-  status = 0;
-
-
-  /* Do phi dependence. */
-  phip = phi;
-  rowoff = 0;
-  rowlen = nphi*sxy;
-  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
-    sincosd(*phip, &sinphi, &cosphi);
-
-    xp = x + rowoff;
-    yp = y + rowoff;
-    for (itheta = 0; itheta < mtheta; itheta++) {
-      *xp = sinphi;
-      *yp = cosphi;
-      xp += rowlen;
-      yp += rowlen;
-    }
-  }
-
-
-  /* Do theta dependence. */
-  thetap = theta;
-  xp = x;
-  yp = y;
-  statp = stat;
-  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
-    sincosd(*thetap, &sinthe, &costhe);
-
-    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
-      s = prj->w[1]*(*yp);
-      t = (prj->pv[1] + sinthe) + costhe*s;
-
-      if (t == 0.0) {
-        *xp = 0.0;
-        *yp = 0.0;
-        *(statp++) = 1;
-        if (!status) status = PRJERR_BAD_WORLD_SET("azps2x");
-
-      } else {
-        r = prj->w[0]*costhe/t;
-
-        /* Bounds checking. */
-        istat = 0;
-        if (prj->bounds) {
-          if (*thetap < prj->w[5]) {
-            /* Overlap. */
-            istat  = 1;
-            if (!status) status = PRJERR_BAD_WORLD_SET("azps2x");
-
-          } else if (prj->w[7] > 0.0) {
-            /* Divergence. */
-            t = prj->pv[1] / sqrt(1.0 + s*s);
-
-            if (fabs(t) <= 1.0) {
-              s = atand(-s);
-              t = asind(t);
-              a = s - t;
-              b = s + t + 180.0;
-
-              if (a > 90.0) a -= 360.0;
-              if (b > 90.0) b -= 360.0;
-
-              if (*thetap < ((a > b) ? a : b)) {
-                istat  = 1;
-                if (!status) status = PRJERR_BAD_WORLD_SET("azps2x");
-              }
-            }
-          }
-        }
-
-        *xp =  r*(*xp) - prj->x0;
-        *yp = -r*(*yp)*prj->w[2] - prj->y0;
-        *(statp++) = istat;
-      }
-    }
-  }
-
-  return status;
-}
-
-/*============================================================================
-*   SZP: slant zenithal perspective projection.
-*
-*   Given:
-*      prj->pv[1]   Distance of the point of projection from the centre of the
-*                   generating sphere, mu in units of r0.
-*      prj->pv[2]   Native longitude, phi_c, and ...
-*      prj->pv[3]   Native latitude, theta_c, on the planewards side of the
-*                   intersection of the line through the point of projection
-*                   and the centre of the generating sphere, phi_c in degrees.
-*
-*   Given and/or returned:
-*      prj->r0      Reset to 180/pi if 0.
-*      prj->phi0    Reset to  0.0 if undefined.
-*      prj->theta0  Reset to 90.0 if undefined.
-*
-*   Returned:
-*      prj->flag     SZP
-*      prj->code    "SZP"
-*      prj->x0      Fiducial offset in x.
-*      prj->y0      Fiducial offset in y.
-*      prj->w[0]    1/r0
-*      prj->w[1]    xp = -mu*cos(theta_c)*sin(phi_c)
-*      prj->w[2]    yp =  mu*cos(theta_c)*cos(phi_c)
-*      prj->w[3]    zp =  mu*sin(theta_c) + 1
-*      prj->w[4]    r0*xp
-*      prj->w[5]    r0*yp
-*      prj->w[6]    r0*zp
-*      prj->w[7]    (zp - 1)^2
-*      prj->w[8]    asin(1-zp) if |1 - zp| < 1, -90 otherwise
-*      prj->prjx2s  Pointer to szpx2s().
-*      prj->prjs2x  Pointer to szps2x().
-*===========================================================================*/
-
-int szpset(prj)
-
-struct prjprm *prj;
-
-{
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-
-  prj->flag = SZP;
-  strcpy(prj->code, "SZP");
-
-  if (undefined(prj->pv[1])) prj->pv[1] =  0.0;
-  if (undefined(prj->pv[2])) prj->pv[2] =  0.0;
-  if (undefined(prj->pv[3])) prj->pv[3] = 90.0;
-  if (prj->r0 == 0.0) prj->r0 = R2D;
-
-  strcpy(prj->name, "slant zenithal perspective");
-  prj->category  = ZENITHAL;
-  prj->pvrange   = 103;
-  prj->simplezen = prj->pv[3] == 90.0;
-  prj->equiareal = 0;
-  prj->conformal = 0;
-  prj->global    = 0;
-  prj->divergent = prj->pv[1] <= 1.0;
-
-  prj->w[0] = 1.0/prj->r0;
-
-  prj->w[3] = prj->pv[1] * sind(prj->pv[3]) + 1.0;
-  if (prj->w[3] == 0.0) {
-    return PRJERR_BAD_PARAM_SET("szpset");
-  }
-
-  prj->w[1] = -prj->pv[1] * cosd(prj->pv[3]) * sind(prj->pv[2]);
-  prj->w[2] =  prj->pv[1] * cosd(prj->pv[3]) * cosd(prj->pv[2]);
-  prj->w[4] =  prj->r0 * prj->w[1];
-  prj->w[5] =  prj->r0 * prj->w[2];
-  prj->w[6] =  prj->r0 * prj->w[3];
-  prj->w[7] =  (prj->w[3] - 1.0) * prj->w[3] - 1.0;
-
-  if (fabs(prj->w[3] - 1.0) < 1.0) {
-    prj->w[8] = asind(1.0 - prj->w[3]);
-  } else {
-    prj->w[8] = -90.0;
-  }
-
-  prj->prjx2s = szpx2s;
-  prj->prjs2x = szps2x;
-
-  return prjoff(prj, 0.0, 90.0);
-}
-
-/*--------------------------------------------------------------------------*/
-
-int szpx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)
-
-struct prjprm *prj;
-int nx, ny, sxy, spt;
-const double x[], y[];
-double phi[], theta[];
-int stat[];
-
-{
-  int mx, my, rowlen, rowoff, status;
-  double a, b, c, d, r2, sinth1, sinth2, sinthe, t, x1, xr, xy, y1, yr, z;
-  const double tol = 1.0e-13;
-  register int ix, iy, *statp;
-  register const double *xp, *yp;
-  register double *phip, *thetap;
-
-
-  /* Initialize. */
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-  if (prj->flag != SZP) {
-    if ((status = szpset(prj))) return status;
-  }
-
-  if (ny > 0) {
-    mx = nx;
-    my = ny;
-  } else {
-    mx = 1;
-    my = 1;
-    ny = nx;
-  }
-
-  status = 0;
-
-
-  /* Do x dependence. */
-  xp = x;
-  rowoff = 0;
-  rowlen = nx*spt;
-  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
-    xr = (*xp + prj->x0)*prj->w[0];
-
-    phip = phi + rowoff;
-    for (iy = 0; iy < my; iy++) {
-      *phip = xr;
-      phip += rowlen;
-    }
-  }
-
-
-  /* Do y dependence. */
-  yp = y;
-  phip   = phi;
-  thetap = theta;
-  statp  = stat;
-  for (iy = 0; iy < ny; iy++, yp += sxy) {
-    yr = (*yp + prj->y0)*prj->w[0];
-
-    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
-      xr = *phip;
-      r2 = xr*xr + yr*yr;
-
-      x1 = (xr - prj->w[1])/prj->w[3];
-      y1 = (yr - prj->w[2])/prj->w[3];
-      xy = xr*x1 + yr*y1;
-
-      if (r2 < 1.0e-10) {
-        /* Use small angle formula. */
-        z = r2/2.0;
-        *thetap = 90.0 - R2D*sqrt(r2/(1.0 + xy));
-
-      } else {
-        t = x1*x1 + y1*y1;
-        a = t + 1.0;
-        b = xy - t;
-        c = r2 - xy - xy + t - 1.0;
-        d = b*b - a*c;
-
-        /* Check for a solution. */
-        if (d < 0.0) {
-          *phip = 0.0;
-          *thetap = 0.0;
-          *(statp++) = 1;
-          if (!status) status = PRJERR_BAD_PIX_SET("szpx2s");
-          continue;
-        }
-        d = sqrt(d);
-
-        /* Choose solution closest to pole. */
-        sinth1 = (-b + d)/a;
-        sinth2 = (-b - d)/a;
-        sinthe = (sinth1 > sinth2) ? sinth1 : sinth2;
-        if (sinthe > 1.0) {
-          if (sinthe-1.0 < tol) {
-            sinthe = 1.0;
-          } else {
-            sinthe = (sinth1 < sinth2) ? sinth1 : sinth2;
-          }
-        }
-
-        if (sinthe < -1.0) {
-          if (sinthe+1.0 > -tol) {
-            sinthe = -1.0;
-          }
-        }
-
-        if (sinthe > 1.0 || sinthe < -1.0) {
-          *phip   = 0.0;
-          *thetap = 0.0;
-          *(statp++) = 1;
-          if (!status) status = PRJERR_BAD_PIX_SET("szpx2s");
-          continue;
-        }
-
-        *thetap = asind(sinthe);
-
-        z = 1.0 - sinthe;
-      }
-
-      *phip = atan2d(xr - x1*z, -(yr - y1*z));
-      *(statp++) = 0;
-    }
-  }
-
-  return status;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int szps2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)
-
-struct prjprm *prj;
-int nphi, ntheta, spt, sxy;
-const double phi[], theta[];
-double x[], y[];
-int stat[];
-
-{
-  int mphi, mtheta, rowlen, rowoff, status;
-  double a, b, cosphi, r, s, sinphi, t, u, v;
-  register int iphi, itheta, istat, *statp;
-  register const double *phip, *thetap;
-  register double *xp, *yp;
-
-
-  /* Initialize. */
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-  if (prj->flag != SZP) {
-    if ((status = szpset(prj))) return status;
-  }
-
-  if (ntheta > 0) {
-    mphi   = nphi;
-    mtheta = ntheta;
-  } else {
-    mphi   = 1;
-    mtheta = 1;
-    ntheta = nphi;
-  }
-
-  status = 0;
-
-
-  /* Do phi dependence. */
-  phip = phi;
-  rowoff = 0;
-  rowlen = nphi*sxy;
-  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
-    sincosd(*phip, &sinphi, &cosphi);
-
-    xp = x + rowoff;
-    yp = y + rowoff;
-    for (itheta = 0; itheta < mtheta; itheta++) {
-      *xp = sinphi;
-      *yp = cosphi;
-      xp += rowlen;
-      yp += rowlen;
-    }
-  }
-
-
-  /* Do theta dependence. */
-  thetap = theta;
-  xp = x;
-  yp = y;
-  statp = stat;
-  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
-    s = 1.0 - sind(*thetap);
-    t = prj->w[3] - s;
-
-    if (t == 0.0) {
-      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
-        *xp = 0.0;
-        *yp = 0.0;
-        *(statp++) = 1;
-      }
-
-      if (!status) status = PRJERR_BAD_WORLD_SET("szps2x");
-
-    } else {
-      r = prj->w[6]*cosd(*thetap)/t;
-      u = prj->w[4]*s/t + prj->x0;
-      v = prj->w[5]*s/t + prj->y0;
-
-      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
-        /* Bounds checking. */
-        istat = 0;
-        if (prj->bounds) {
-          if (*thetap < prj->w[8]) {
-            /* Divergence. */
-            istat  = 1;
-            if (!status) status = PRJERR_BAD_WORLD_SET("szps2x");
-
-          } else if (fabs(prj->pv[1]) > 1.0) {
-            /* Overlap. */
-            s = prj->w[1]*(*xp) - prj->w[2]*(*yp);
-            t = 1.0/sqrt(prj->w[7] + s*s);
-
-            if (fabs(t) <= 1.0) {
-              s = atan2d(s, prj->w[3] - 1.0);
-              t = asind(t);
-              a = s - t;
-              b = s + t + 180.0;
-
-              if (a > 90.0) a -= 360.0;
-              if (b > 90.0) b -= 360.0;
-
-              if (*thetap < ((a > b) ? a : b)) {
-                istat  = 1;
-                if (!status) status = PRJERR_BAD_WORLD_SET("szps2x");
-              }
-            }
-          }
-        }
-
-        *xp =  r*(*xp) - u;
-        *yp = -r*(*yp) - v;
-        *(statp++) = istat;
-      }
-    }
-  }
-
-  return status;
-}
-
-
-/*============================================================================
-*   TAN: gnomonic projection.
-*
-*   Given and/or returned:
-*      prj->r0      Reset to 180/pi if 0.
-*      prj->phi0    Reset to  0.0 if undefined.
-*      prj->theta0  Reset to 90.0 if undefined.
-*
-*   Returned:
-*      prj->flag     TAN
-*      prj->code    "TAN"
-*      prj->x0      Fiducial offset in x.
-*      prj->y0      Fiducial offset in y.
-*      prj->prjx2s  Pointer to tanx2s().
-*      prj->prjs2x  Pointer to tans2x().
-*===========================================================================*/
-
-int tanset(prj)
-
-struct prjprm *prj;
-
-{
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-
-  prj->flag = TAN;
-  strcpy(prj->code, "TAN");
-
-  if (prj->r0 == 0.0) prj->r0 = R2D;
-
-  strcpy(prj->name, "gnomonic");
-  prj->category  = ZENITHAL;
-  prj->pvrange   = 0;
-  prj->simplezen = 1;
-  prj->equiareal = 0;
-  prj->conformal = 0;
-  prj->global    = 0;
-  prj->divergent = 1;
-
-  prj->prjx2s = tanx2s;
-  prj->prjs2x = tans2x;
-
-  return prjoff(prj, 0.0, 90.0);
-}
-
-/*--------------------------------------------------------------------------*/
-
-int tanx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)
-
-struct prjprm *prj;
-int nx, ny, sxy, spt;
-const double x[], y[];
-double phi[], theta[];
-int stat[];
-
-{
-  int mx, my, rowlen, rowoff, status;
-  double r, xj, yj, yj2;
-  register int ix, iy, *statp;
-  register const double *xp, *yp;
-  register double *phip, *thetap;
-
-
-  /* Initialize. */
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-  if (prj->flag != TAN) {
-    if ((status = tanset(prj))) return status;
-  }
-
-  if (ny > 0) {
-    mx = nx;
-    my = ny;
-  } else {
-    mx = 1;
-    my = 1;
-    ny = nx;
-  }
-
-
-  /* Do x dependence. */
-  xp = x;
-  rowoff = 0;
-  rowlen = nx*spt;
-  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
-    xj = *xp + prj->x0;
-
-    phip = phi + rowoff;
-    for (iy = 0; iy < my; iy++) {
-      *phip = xj;
-      phip += rowlen;
-    }
-  }
-
-
-  /* Do y dependence. */
-  yp = y;
-  phip   = phi;
-  thetap = theta;
-  statp  = stat;
-  for (iy = 0; iy < ny; iy++, yp += sxy) {
-    yj  = *yp + prj->y0;
-    yj2 = yj*yj;
-
-    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
-      xj = *phip;
-
-      r = sqrt(xj*xj + yj2);
-      if (r == 0.0) {
-        *phip = 0.0;
-      } else {
-        *phip = atan2d(xj, -yj);
-      }
-
-      *thetap = atan2d(prj->r0, r);
-      *(statp++) = 0;
-    }
-  }
-
-  return 0;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int tans2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)
-
-struct prjprm *prj;
-int nphi, ntheta, spt, sxy;
-const double phi[], theta[];
-double x[], y[];
-int stat[];
-
-{
-  int mphi, mtheta, rowlen, rowoff, status;
-  double cosphi, r, s, sinphi;
-  register int iphi, itheta, istat, *statp;
-  register const double *phip, *thetap;
-  register double *xp, *yp;
-
-
-  /* Initialize. */
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-  if (prj->flag != TAN) {
-    if ((status = tanset(prj))) return status;
-  }
-
-  if (ntheta > 0) {
-    mphi   = nphi;
-    mtheta = ntheta;
-  } else {
-    mphi   = 1;
-    mtheta = 1;
-    ntheta = nphi;
-  }
-
-  status = 0;
-
-
-  /* Do phi dependence. */
-  phip = phi;
-  rowoff = 0;
-  rowlen = nphi*sxy;
-  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
-    sincosd(*phip, &sinphi, &cosphi);
-
-    xp = x + rowoff;
-    yp = y + rowoff;
-    for (itheta = 0; itheta < mtheta; itheta++) {
-      *xp = sinphi;
-      *yp = cosphi;
-      xp += rowlen;
-      yp += rowlen;
-    }
-  }
-
-
-  /* Do theta dependence. */
-  thetap = theta;
-  xp = x;
-  yp = y;
-  statp = stat;
-  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
-    s = sind(*thetap);
-    if (s == 0.0) {
-      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
-        *xp = 0.0;
-        *yp = 0.0;
-        *(statp++) = 1;
-      }
-      if (!status) status = PRJERR_BAD_WORLD_SET("tans2x");
-
-    } else {
-      r =  prj->r0*cosd(*thetap)/s;
-
-      istat = 0;
-      if (prj->bounds && s < 0.0) {
-        istat  = 1;
-        if (!status) status = PRJERR_BAD_WORLD_SET("tans2x");
-      }
-
-      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
-        *xp =  r*(*xp) - prj->x0;
-        *yp = -r*(*yp) - prj->y0;
-        *(statp++) = istat;
-      }
-    }
-  }
-
-  return status;
-}
-
-/*============================================================================
-*   STG: stereographic projection.
-*
-*   Given and/or returned:
-*      prj->r0      Reset to 180/pi if 0.
-*      prj->phi0    Reset to  0.0 if undefined.
-*      prj->theta0  Reset to 90.0 if undefined.
-*
-*   Returned:
-*      prj->flag     STG
-*      prj->code    "STG"
-*      prj->x0      Fiducial offset in x.
-*      prj->y0      Fiducial offset in y.
-*      prj->w[0]    2*r0
-*      prj->w[1]    1/(2*r0)
-*      prj->prjx2s  Pointer to stgx2s().
-*      prj->prjs2x  Pointer to stgs2x().
-*===========================================================================*/
-
-int stgset(prj)
-
-struct prjprm *prj;
-
-{
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-
-  prj->flag = STG;
-  strcpy(prj->code, "STG");
-
-  strcpy(prj->name, "stereographic");
-  prj->category  = ZENITHAL;
-  prj->pvrange   = 0;
-  prj->simplezen = 1;
-  prj->equiareal = 0;
-  prj->conformal = 1;
-  prj->global    = 0;
-  prj->divergent = 1;
-
-  if (prj->r0 == 0.0) {
-    prj->r0 = R2D;
-    prj->w[0] = 360.0/PI;
-    prj->w[1] = PI/360.0;
-  } else {
-    prj->w[0] = 2.0*prj->r0;
-    prj->w[1] = 1.0/prj->w[0];
-  }
-
-  prj->prjx2s = stgx2s;
-  prj->prjs2x = stgs2x;
-
-  return prjoff(prj, 0.0, 90.0);
-}
-
-/*--------------------------------------------------------------------------*/
-
-int stgx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)
-
-struct prjprm *prj;
-int nx, ny, sxy, spt;
-const double x[], y[];
-double phi[], theta[];
-int stat[];
-
-{
-  int mx, my, rowlen, rowoff, status;
-  double r, xj, yj, yj2;
-  register int ix, iy, *statp;
-  register const double *xp, *yp;
-  register double *phip, *thetap;
-
-
-  /* Initialize. */
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-  if (prj->flag != STG) {
-    if ((status = stgset(prj))) return status;
-  }
-
-  if (ny > 0) {
-    mx = nx;
-    my = ny;
-  } else {
-    mx = 1;
-    my = 1;
-    ny = nx;
-  }
-
-
-  /* Do x dependence. */
-  xp = x;
-  rowoff = 0;
-  rowlen = nx*spt;
-  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
-    xj = *xp + prj->x0;
-
-    phip = phi + rowoff;
-    for (iy = 0; iy < my; iy++) {
-      *phip = xj;
-      phip += rowlen;
-    }
-  }
-
-
-  /* Do y dependence. */
-  yp = y;
-  phip   = phi;
-  thetap = theta;
-  statp  = stat;
-  for (iy = 0; iy < ny; iy++, yp += sxy) {
-    yj  = *yp + prj->y0;
-    yj2 = yj*yj;
-
-    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
-      xj  = *phip;
-
-      r = sqrt(xj*xj + yj2);
-      if (r == 0.0) {
-        *phip = 0.0;
-      } else {
-        *phip = atan2d(xj, -yj);
-      }
-
-      *thetap = 90.0 - 2.0*atand(r*prj->w[1]);
-      *(statp++) = 0;
-    }
-  }
-
-  return 0;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int stgs2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)
-
-struct prjprm *prj;
-int nphi, ntheta, spt, sxy;
-const double phi[], theta[];
-double x[], y[];
-int stat[];
-
-{
-  int mphi, mtheta, rowlen, rowoff, status;
-  double cosphi, r, s, sinphi;
-  register int iphi, itheta, *statp;
-  register const double *phip, *thetap;
-  register double *xp, *yp;
-
-
-  /* Initialize. */
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-  if (prj->flag != STG) {
-    if ((status = stgset(prj))) return status;
-  }
-
-  if (ntheta > 0) {
-    mphi   = nphi;
-    mtheta = ntheta;
-  } else {
-    mphi   = 1;
-    mtheta = 1;
-    ntheta = nphi;
-  }
-
-  status = 0;
-
-
-  /* Do phi dependence. */
-  phip = phi;
-  rowoff = 0;
-  rowlen = nphi*sxy;
-  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
-    sincosd(*phip, &sinphi, &cosphi);
-
-    xp = x + rowoff;
-    yp = y + rowoff;
-    for (itheta = 0; itheta < mtheta; itheta++) {
-      *xp = sinphi;
-      *yp = cosphi;
-      xp += rowlen;
-      yp += rowlen;
-    }
-  }
-
-
-  /* Do theta dependence. */
-  thetap = theta;
-  xp = x;
-  yp = y;
-  statp = stat;
-  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
-    s = 1.0 + sind(*thetap);
-    if (s == 0.0) {
-      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
-        *xp = 0.0;
-        *yp = 0.0;
-        *(statp++) = 1;
-      }
-      if (!status) status = PRJERR_BAD_WORLD_SET("stgs2x");
-
-    } else {
-      r = prj->w[0]*cosd(*thetap)/s;
-
-      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
-        *xp =  r*(*xp) - prj->x0;
-        *yp = -r*(*yp) - prj->y0;
-        *(statp++) = 0;
-      }
-    }
-  }
-
-  return status;
-}
-
-/*============================================================================
-*   SIN: orthographic/synthesis projection.
-*
-*   Given:
-*      prj->pv[1:2] Obliqueness parameters, xi and eta.
-*
-*   Given and/or returned:
-*      prj->r0      Reset to 180/pi if 0.
-*      prj->phi0    Reset to  0.0 if undefined.
-*      prj->theta0  Reset to 90.0 if undefined.
-*
-*   Returned:
-*      prj->flag     SIN
-*      prj->code    "SIN"
-*      prj->x0      Fiducial offset in x.
-*      prj->y0      Fiducial offset in y.
-*      prj->w[0]    1/r0
-*      prj->w[1]    xi**2 + eta**2
-*      prj->w[2]    xi**2 + eta**2 + 1
-*      prj->w[3]    xi**2 + eta**2 - 1
-*      prj->prjx2s  Pointer to sinx2s().
-*      prj->prjs2x  Pointer to sins2x().
-*===========================================================================*/
-
-int sinset(prj)
-
-struct prjprm *prj;
-
-{
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-
-  prj->flag = SIN;
-  strcpy(prj->code, "SIN");
-
-  if (undefined(prj->pv[1])) prj->pv[1] = 0.0;
-  if (undefined(prj->pv[2])) prj->pv[2] = 0.0;
-  if (prj->r0 == 0.0) prj->r0 = R2D;
-
-  strcpy(prj->name, "orthographic/synthesis");
-  prj->category  = ZENITHAL;
-  prj->pvrange   = 102;
-  prj->simplezen = (prj->pv[1] == 0.0 && prj->pv[2] == 0.0);
-  prj->equiareal = 0;
-  prj->conformal = 0;
-  prj->global    = 0;
-  prj->divergent = 0;
-
-  prj->w[0] = 1.0/prj->r0;
-  prj->w[1] = prj->pv[1]*prj->pv[1] + prj->pv[2]*prj->pv[2];
-  prj->w[2] = prj->w[1] + 1.0;
-  prj->w[3] = prj->w[1] - 1.0;
-
-  prj->prjx2s = sinx2s;
-  prj->prjs2x = sins2x;
-
-  return prjoff(prj, 0.0, 90.0);
-}
-
-/*--------------------------------------------------------------------------*/
-
-int sinx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)
-
-struct prjprm *prj;
-int nx, ny, sxy, spt;
-const double x[], y[];
-double phi[], theta[];
-int stat[];
-
-{
-  int mx, my, rowlen, rowoff, status;
-  const double tol = 1.0e-13;
-  double a, b, c, d, eta, r2, sinth1, sinth2, sinthe, x0, xi, x1, xy, y0, y02,
-         y1, z;
-  register int ix, iy, *statp;
-  register const double *xp, *yp;
-  register double *phip, *thetap;
-
-
-  /* Initialize. */
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-  if (prj->flag != SIN) {
-    if ((status = sinset(prj))) return status;
-  }
-
-  xi  = prj->pv[1];
-  eta = prj->pv[2];
-
-  if (ny > 0) {
-    mx = nx;
-    my = ny;
-  } else {
-    mx = 1;
-    my = 1;
-    ny = nx;
-  }
-
-  status = 0;
-
-
-  /* Do x dependence. */
-  xp = x;
-  rowoff = 0;
-  rowlen = nx*spt;
-  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
-    x0 = (*xp + prj->x0)*prj->w[0];
-
-    phip = phi + rowoff;
-    for (iy = 0; iy < my; iy++) {
-      *phip = x0;
-      phip += rowlen;
-    }
-  }
-
-
-  /* Do y dependence. */
-  yp = y;
-  phip   = phi;
-  thetap = theta;
-  statp  = stat;
-  for (iy = 0; iy < ny; iy++, yp += sxy) {
-    y0 = (*yp + prj->y0)*prj->w[0];
-    y02 = y0*y0;
-
-    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
-      /* Compute intermediaries. */
-      x0 = *phip;
-      r2 = x0*x0 + y02;
-
-      if (prj->w[1] == 0.0) {
-        /* Orthographic projection. */
-        if (r2 != 0.0) {
-          *phip = atan2d(x0, -y0);
-        } else {
-          *phip = 0.0;
-        }
-
-        if (r2 < 0.5) {
-          *thetap = acosd(sqrt(r2));
-        } else if (r2 <= 1.0) {
-          *thetap = asind(sqrt(1.0 - r2));
-        } else {
-          *(statp++) = 1;
-          if (!status) status = PRJERR_BAD_PIX_SET("sinx2s")
-          continue;
-        }
-
-      } else {
-        /* "Synthesis" projection. */
-        xy = x0*xi + y0*eta;
-
-        if (r2 < 1.0e-10) {
-          /* Use small angle formula. */
-          z = r2/2.0;
-          *thetap = 90.0 - R2D*sqrt(r2/(1.0 + xy));
-
-        } else {
-          a = prj->w[2];
-          b = xy - prj->w[1];
-          c = r2 - xy - xy + prj->w[3];
-          d = b*b - a*c;
-
-          /* Check for a solution. */
-          if (d < 0.0) {
-            *phip = 0.0;
-            *thetap = 0.0;
-            *(statp++) = 1;
-            if (!status) status = PRJERR_BAD_PIX_SET("sinx2s")
-            continue;
-          }
-          d = sqrt(d);
-
-          /* Choose solution closest to pole. */
-          sinth1 = (-b + d)/a;
-          sinth2 = (-b - d)/a;
-          sinthe = (sinth1 > sinth2) ? sinth1 : sinth2;
-          if (sinthe > 1.0) {
-            if (sinthe-1.0 < tol) {
-              sinthe = 1.0;
-            } else {
-              sinthe = (sinth1 < sinth2) ? sinth1 : sinth2;
-            }
-          }
-
-          if (sinthe < -1.0) {
-            if (sinthe+1.0 > -tol) {
-              sinthe = -1.0;
-            }
-          }
-
-          if (sinthe > 1.0 || sinthe < -1.0) {
-            *phip = 0.0;
-            *thetap = 0.0;
-            *(statp++) = 1;
-            if (!status) status = PRJERR_BAD_PIX_SET("sinx2s")
-            continue;
-          }
-
-          *thetap = asind(sinthe);
-          z = 1.0 - sinthe;
-        }
-
-        x1 = -y0 + eta*z;
-        y1 =  x0 -  xi*z;
-        if (x1 == 0.0 && y1 == 0.0) {
-          *phip = 0.0;
-        } else {
-          *phip = atan2d(y1,x1);
-        }
-      }
-
-      *(statp++) = 0;
-    }
-  }
-
-  return status;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int sins2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)
-
-struct prjprm *prj;
-int nphi, ntheta, spt, sxy;
-const double phi[], theta[];
-double x[], y[];
-int stat[];
-
-{
-  int mphi, mtheta, rowlen, rowoff, status;
-  double cosphi, costhe, sinphi, r, t, z, z1, z2;
-  register int iphi, itheta, istat, *statp;
-  register const double *phip, *thetap;
-  register double *xp, *yp;
-
-
-  /* Initialize. */
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-  if (prj->flag != SIN) {
-    if ((status = sinset(prj))) return status;
-  }
-
-  if (ntheta > 0) {
-    mphi   = nphi;
-    mtheta = ntheta;
-  } else {
-    mphi   = 1;
-    mtheta = 1;
-    ntheta = nphi;
-  }
-
-  status = 0;
-
-
-  /* Do phi dependence. */
-  phip = phi;
-  rowoff = 0;
-  rowlen = nphi*sxy;
-  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
-    sincosd(*phip, &sinphi, &cosphi);
-
-    xp = x + rowoff;
-    yp = y + rowoff;
-    for (itheta = 0; itheta < mtheta; itheta++) {
-      *xp = sinphi;
-      *yp = cosphi;
-      xp += rowlen;
-      yp += rowlen;
-    }
-  }
-
-
-  /* Do theta dependence. */
-  thetap = theta;
-  xp = x;
-  yp = y;
-  statp = stat;
-  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
-    t = (90.0 - fabs(*thetap))*D2R;
-    if (t < 1.0e-5) {
-      if (*thetap > 0.0) {
-         z = t*t/2.0;
-      } else {
-         z = 2.0 - t*t/2.0;
-      }
-      costhe = t;
-    } else {
-      z = 1.0 - sind(*thetap);
-      costhe = cosd(*thetap);
-    }
-    r = prj->r0*costhe;
-
-    if (prj->w[1] == 0.0) {
-      /* Orthographic projection. */
-      istat = 0;
-      if (prj->bounds && *thetap < 0.0) {
-        istat  = 1;
-        if (!status) status = PRJERR_BAD_WORLD_SET("sins2x");
-      }
-
-      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
-        *xp =  r*(*xp) - prj->x0;
-        *yp = -r*(*yp) - prj->y0;
-        *(statp++) = istat;
-      }
-
-    } else {
-      /* "Synthesis" projection. */
-      z *= prj->r0;
-      z1 = prj->pv[1]*z - prj->x0;
-      z2 = prj->pv[2]*z - prj->y0;
-
-      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
-        istat = 0;
-        if (prj->bounds) {
-          t = -atand(prj->pv[1]*(*xp) - prj->pv[2]*(*yp));
-          if (*thetap < t) {
-            istat  = 1;
-            if (!status) status = PRJERR_BAD_WORLD_SET("sins2x");
-          }
-        }
-
-        *xp =  r*(*xp) + z1;
-        *yp = -r*(*yp) + z2;
-        *(statp++) = istat;
-      }
-    }
-  }
-
-  return status;
-}
-
-/*============================================================================
-*   ARC: zenithal/azimuthal equidistant projection.
-*
-*   Given and/or returned:
-*      prj->r0      Reset to 180/pi if 0.
-*      prj->phi0    Reset to  0.0 if undefined.
-*      prj->theta0  Reset to 90.0 if undefined.
-*
-*   Returned:
-*      prj->flag     ARC
-*      prj->code    "ARC"
-*      prj->x0      Fiducial offset in x.
-*      prj->y0      Fiducial offset in y.
-*      prj->w[0]    r0*(pi/180)
-*      prj->w[1]    (180/pi)/r0
-*      prj->prjx2s  Pointer to arcx2s().
-*      prj->prjs2x  Pointer to arcs2x().
-*===========================================================================*/
-
-int arcset(prj)
-
-struct prjprm *prj;
-
-{
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-
-  prj->flag = ARC;
-  strcpy(prj->code, "ARC");
-
-  strcpy(prj->name, "zenithal/azimuthal equidistant");
-  prj->category  = ZENITHAL;
-  prj->pvrange   = 0;
-  prj->simplezen = 1;
-  prj->equiareal = 0;
-  prj->conformal = 0;
-  prj->global    = 1;
-  prj->divergent = 0;
-
-  if (prj->r0 == 0.0) {
-    prj->r0 = R2D;
-    prj->w[0] = 1.0;
-    prj->w[1] = 1.0;
-  } else {
-    prj->w[0] = prj->r0*D2R;
-    prj->w[1] = 1.0/prj->w[0];
-  }
-
-  prj->prjx2s = arcx2s;
-  prj->prjs2x = arcs2x;
-
-  return prjoff(prj, 0.0, 90.0);
-}
-
-/*--------------------------------------------------------------------------*/
-
-int arcx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)
-
-struct prjprm *prj;
-int nx, ny, sxy, spt;
-const double x[], y[];
-double phi[], theta[];
-int stat[];
-
-{
-  int mx, my, rowlen, rowoff, status;
-  double r, xj, yj, yj2;
-  register int ix, iy, *statp;
-  register const double *xp, *yp;
-  register double *phip, *thetap;
-
-
-  /* Initialize. */
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-  if (prj->flag != ARC) {
-    if ((status = arcset(prj))) return status;
-  }
-
-  if (ny > 0) {
-    mx = nx;
-    my = ny;
-  } else {
-    mx = 1;
-    my = 1;
-    ny = nx;
-  }
-
-
-  /* Do x dependence. */
-  xp = x;
-  rowoff = 0;
-  rowlen = nx*spt;
-  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
-    xj = *xp + prj->x0;
-
-    phip = phi + rowoff;
-    for (iy = 0; iy < my; iy++) {
-      *phip = xj;
-      phip += rowlen;
-    }
-  }
-
-
-  /* Do y dependence. */
-  yp = y;
-  phip   = phi;
-  thetap = theta;
-  statp  = stat;
-  for (iy = 0; iy < ny; iy++, yp += sxy) {
-    yj  = *yp + prj->y0;
-    yj2 = yj*yj;
-
-    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
-      xj = *phip;
-
-      r = sqrt(xj*xj + yj2);
-      if (r == 0.0) {
-        *phip = 0.0;
-        *thetap = 90.0;
-      } else {
-        *phip = atan2d(xj, -yj);
-        *thetap = 90.0 - r*prj->w[1];
-      }
-
-      *(statp++) = 0;
-    }
-  }
-
-  return 0;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int arcs2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)
-
-struct prjprm *prj;
-int nphi, ntheta, spt, sxy;
-const double phi[], theta[];
-double x[], y[];
-int stat[];
-
-{
-  int mphi, mtheta, rowlen, rowoff, status;
-  double cosphi, r, sinphi;
-  register int iphi, itheta, *statp;
-  register const double *phip, *thetap;
-  register double *xp, *yp;
-
-
-  /* Initialize. */
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-  if (prj->flag != ARC) {
-    if ((status = arcset(prj))) return status;
-  }
-
-  if (ntheta > 0) {
-    mphi   = nphi;
-    mtheta = ntheta;
-  } else {
-    mphi   = 1;
-    mtheta = 1;
-    ntheta = nphi;
-  }
-
-
-  /* Do phi dependence. */
-  phip = phi;
-  rowoff = 0;
-  rowlen = nphi*sxy;
-  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
-    sincosd(*phip, &sinphi, &cosphi);
-
-    xp = x + rowoff;
-    yp = y + rowoff;
-    for (itheta = 0; itheta < mtheta; itheta++) {
-      *xp = sinphi;
-      *yp = cosphi;
-      xp += rowlen;
-      yp += rowlen;
-    }
-  }
-
-
-  /* Do theta dependence. */
-  thetap = theta;
-  xp = x;
-  yp = y;
-  statp = stat;
-  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
-    r =  prj->w[0]*(90.0 - *thetap);
-
-    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
-      *xp =  r*(*xp) - prj->x0;
-      *yp = -r*(*yp) - prj->y0;
-      *(statp++) = 0;
-    }
-  }
-
-  return 0;
-}
-
-/*============================================================================
-*   ZPN: zenithal/azimuthal polynomial projection.
-*
-*   Given:
-*      prj->pv[]    Polynomial coefficients.
-*
-*   Given and/or returned:
-*      prj->r0      Reset to 180/pi if 0.
-*      prj->phi0    Reset to  0.0 if undefined.
-*      prj->theta0  Reset to 90.0 if undefined.
-*
-*   Returned:
-*      prj->flag     ZPN
-*      prj->code    "ZPN"
-*      prj->x0      Fiducial offset in x.
-*      prj->y0      Fiducial offset in y.
-*      prj->n       Degree of the polynomial, N.
-*      prj->w[0]    Co-latitude of the first point of inflection, radian.
-*      prj->w[1]    Radius of the first point of inflection (N > 1), radian.
-*      prj->prjx2s  Pointer to zpnx2s().
-*      prj->prjs2x  Pointer to zpns2x().
-*===========================================================================*/
-
-int zpnset(prj)
-
-struct prjprm *prj;
-
-{
-  int j, k, m;
-  double d, d1, d2, r, zd, zd1, zd2;
-  const double tol = 1.0e-13;
-
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-
-  strcpy(prj->code, "ZPN");
-  prj->flag = ZPN;
-
-  if (undefined(prj->pv[1])) prj->pv[1] = 0.0;
-  if (undefined(prj->pv[2])) prj->pv[2] = 0.0;
-  if (undefined(prj->pv[3])) prj->pv[3] = 0.0;
-  if (prj->r0 == 0.0) prj->r0 = R2D;
-
-  strcpy(prj->name, "zenithal/azimuthal polynomial");
-  prj->category  = ZENITHAL;
-  prj->pvrange   = 30;
-  prj->simplezen = 1;
-  prj->equiareal = 0;
-  prj->conformal = 0;
-  prj->global    = 0;
-  prj->divergent = 0;
-
-  /* Find the highest non-zero coefficient. */
-  for (k = PVN-1; k >= 0 && prj->pv[k] == 0.0; k--);
-  if (k < 0) {
-    return PRJERR_BAD_PARAM_SET("zpnset");
-  }
-
-  prj->n = k;
-
-  if (k < 2) {
-    /* No point of inflection. */
-    prj->w[0] = PI;
-
-  } else {
-    /* Find the point of inflection closest to the pole. */
-    zd1 = 0.0;
-    d1  = prj->pv[1];
-    if (d1 <= 0.0) {
-      return PRJERR_BAD_PARAM_SET("zpnset");
-    }
-
-    /* Find the point where the derivative first goes negative. */
-    for (j = 0; j < 180; j++) {
-      zd2 = j*D2R;
-      d2  = 0.0;
-      for (m = k; m > 0; m--) {
-        d2 = d2*zd2 + m*prj->pv[m];
-      }
-
-      if (d2 <= 0.0) break;
-      zd1 = zd2;
-      d1  = d2;
-    }
-
-    if (j == 180) {
-      /* No negative derivative -> no point of inflection. */
-      zd = PI;
-      prj->global = 1;
-    } else {
-      /* Find where the derivative is zero. */
-      for (j = 1; j <= 10; j++) {
-        zd = zd1 - d1*(zd2-zd1)/(d2-d1);
-
-        d = 0.0;
-        for (m = k; m > 0; m--) {
-          d = d*zd + m*prj->pv[m];
-        }
-
-        if (fabs(d) < tol) break;
-
-        if (d < 0.0) {
-          zd2 = zd;
-          d2  = d;
-        } else {
-          zd1 = zd;
-          d1  = d;
-        }
-      }
-    }
-
-    r = 0.0;
-    for (m = k; m >= 0; m--) {
-      r = r*zd + prj->pv[m];
-    }
-    prj->w[0] = zd;
-    prj->w[1] = r;
-  }
-
-  prj->prjx2s = zpnx2s;
-  prj->prjs2x = zpns2x;
-
-  return prjoff(prj, 0.0, 90.0);
-}
-
-/*--------------------------------------------------------------------------*/
-
-int zpnx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)
-
-struct prjprm *prj;
-int nx, ny, sxy, spt;
-const double x[], y[];
-double phi[], theta[];
-int stat[];
-
-{
-  int j, k, m, mx, my, rowlen, rowoff, status;
-  double a, b, c, d, lambda, r, r1, r2, rt, xj, yj, yj2, zd, zd1, zd2;
-  const double tol = 1.0e-13;
-  register int ix, iy, *statp;
-  register const double *xp, *yp;
-  register double *phip, *thetap;
-
-
-  /* Initialize. */
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-  if (prj->flag != ZPN) {
-    if ((status = zpnset(prj))) return status;
-  }
-
-  k = prj->n;
-
-  if (ny > 0) {
-    mx = nx;
-    my = ny;
-  } else {
-    mx = 1;
-    my = 1;
-    ny = nx;
-  }
-
-  status = 0;
-
-
-  /* Do x dependence. */
-  xp = x;
-  rowoff = 0;
-  rowlen = nx*spt;
-  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
-    xj = *xp + prj->x0;
-
-    phip = phi + rowoff;
-    for (iy = 0; iy < my; iy++) {
-      *phip = xj;
-      phip += rowlen;
-    }
-  }
-
-
-  /* Do y dependence. */
-  yp = y;
-  phip   = phi;
-  thetap = theta;
-  statp  = stat;
-  for (iy = 0; iy < ny; iy++, yp += sxy) {
-    yj  = *yp + prj->y0;
-    yj2 = yj*yj;
-
-    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
-      xj = *phip;
-
-      r = sqrt(xj*xj + yj2)/prj->r0;
-      if (r == 0.0) {
-        *phip = 0.0;
-      } else {
-        *phip = atan2d(xj, -yj);
-      }
-
-      if (k < 1) {
-        /* Constant - no solution. */
-        return PRJERR_BAD_PARAM_SET("zpnx2s");
-      } else if (k == 1) {
-        /* Linear. */
-        zd = (r - prj->pv[0])/prj->pv[1];
-      } else if (k == 2) {
-        /* Quadratic. */
-        a = prj->pv[2];
-        b = prj->pv[1];
-        c = prj->pv[0] - r;
-
-        d = b*b - 4.0*a*c;
-        if (d < 0.0) {
-          *thetap = 0.0;
-          *(statp++) = 1;
-          if (!status) status = PRJERR_BAD_PIX_SET("zpnx2s");
-          continue;
-        }
-        d = sqrt(d);
-
-        /* Choose solution closest to pole. */
-        zd1 = (-b + d)/(2.0*a);
-        zd2 = (-b - d)/(2.0*a);
-        zd  = (zd1<zd2) ? zd1 : zd2;
-        if (zd < -tol) zd = (zd1>zd2) ? zd1 : zd2;
-        if (zd < 0.0) {
-          if (zd < -tol) {
-            *thetap = 0.0;
-            *(statp++) = 1;
-            if (!status) status = PRJERR_BAD_PIX_SET("zpnx2s");
-            continue;
-          }
-          zd = 0.0;
-        } else if (zd > PI) {
-          if (zd > PI+tol) {
-            *thetap = 0.0;
-            *(statp++) = 1;
-            if (!status) status = PRJERR_BAD_PIX_SET("zpnx2s");
-            continue;
-          }
-          zd = PI;
-        }
-      } else {
-        /* Higher order - solve iteratively. */
-        zd1 = 0.0;
-        r1  = prj->pv[0];
-        zd2 = prj->w[0];
-        r2  = prj->w[1];
-
-        if (r < r1) {
-          if (r < r1-tol) {
-            *thetap = 0.0;
-            *(statp++) = 1;
-            if (!status) status = PRJERR_BAD_PIX_SET("zpnx2s");
-            continue;
-          }
-          zd = zd1;
-        } else if (r > r2) {
-          if (r > r2+tol) {
-            *thetap = 0.0;
-            *(statp++) = 1;
-            if (!status) status = PRJERR_BAD_PIX_SET("zpnx2s");
-            continue;
-          }
-          zd = zd2;
-        } else {
-          /* Disect the interval. */
-          for (j = 0; j < 100; j++) {
-            lambda = (r2 - r)/(r2 - r1);
-            if (lambda < 0.1) {
-              lambda = 0.1;
-            } else if (lambda > 0.9) {
-              lambda = 0.9;
-            }
-
-            zd = zd2 - lambda*(zd2 - zd1);
-
-            rt = 0.0;
-            for (m = k; m >= 0; m--) {
-              rt = (rt * zd) + prj->pv[m];
-            }
-
-            if (rt < r) {
-              if (r-rt < tol) break;
-              r1 = rt;
-              zd1 = zd;
-            } else {
-              if (rt-r < tol) break;
-              r2 = rt;
-              zd2 = zd;
-            }
-
-            if (fabs(zd2-zd1) < tol) break;
-          }
-        }
-      }
-
-      *thetap = 90.0 - zd*R2D;
-      *(statp++) = 0;
-    }
-  }
-
-  return status;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int zpns2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)
-
-struct prjprm *prj;
-int nphi, ntheta, spt, sxy;
-const double phi[], theta[];
-double x[], y[];
-int stat[];
-
-{
-  int m, mphi, mtheta, rowlen, rowoff, status;
-  double cosphi, r, s, sinphi;
-  register int iphi, itheta, istat, *statp;
-  register const double *phip, *thetap;
-  register double *xp, *yp;
-
-
-  /* Initialize. */
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-  if (prj->flag != ZPN) {
-    if ((status = zpnset(prj))) return status;
-  }
-
-  if (ntheta > 0) {
-    mphi   = nphi;
-    mtheta = ntheta;
-  } else {
-    mphi   = 1;
-    mtheta = 1;
-    ntheta = nphi;
-  }
-
-  status = 0;
-
-
-  /* Do phi dependence. */
-  phip = phi;
-  rowoff = 0;
-  rowlen = nphi*sxy;
-  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
-    sincosd(*phip, &sinphi, &cosphi);
-
-    xp = x + rowoff;
-    yp = y + rowoff;
-    for (itheta = 0; itheta < mtheta; itheta++) {
-      *xp = sinphi;
-      *yp = cosphi;
-      xp += rowlen;
-      yp += rowlen;
-    }
-  }
-
-
-  /* Do theta dependence. */
-  thetap = theta;
-  xp = x;
-  yp = y;
-  statp = stat;
-  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
-    s = (90.0 - *thetap)*D2R;
-
-    r = 0.0;
-    for (m = prj->n; m >= 0; m--) {
-      r = r*s + prj->pv[m];
-    }
-    r *= prj->r0;
-
-    istat = 0;
-    if (prj->bounds && s > prj->w[0]) {
-      istat  = 1;
-      if (!status) status = PRJERR_BAD_WORLD_SET("zpns2x");
-    }
-
-    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
-      *xp =  r*(*xp) - prj->x0;
-      *yp = -r*(*yp) - prj->y0;
-      *(statp++) = istat;
-    }
-  }
-
-  return status;
-}
-
-/*============================================================================
-*   ZEA: zenithal/azimuthal equal area projection.
-*
-*   Given and/or returned:
-*      prj->r0      Reset to 180/pi if 0.
-*      prj->phi0    Reset to  0.0 if undefined.
-*      prj->theta0  Reset to 90.0 if undefined.
-*
-*   Returned:
-*      prj->flag     ZEA
-*      prj->code    "ZEA"
-*      prj->x0      Fiducial offset in x.
-*      prj->y0      Fiducial offset in y.
-*      prj->w[0]    2*r0
-*      prj->w[1]    1/(2*r0)
-*      prj->prjx2s  Pointer to zeax2s().
-*      prj->prjs2x  Pointer to zeas2x().
-*===========================================================================*/
-
-int zeaset(prj)
-
-struct prjprm *prj;
-
-{
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-
-  prj->flag = ZEA;
-  strcpy(prj->code, "ZEA");
-
-  strcpy(prj->name, "zenithal/azimuthal equal area");
-  prj->category  = ZENITHAL;
-  prj->pvrange   = 0;
-  prj->simplezen = 1;
-  prj->equiareal = 1;
-  prj->conformal = 0;
-  prj->global    = 1;
-  prj->divergent = 0;
-
-  if (prj->r0 == 0.0) {
-    prj->r0 = R2D;
-    prj->w[0] = 360.0/PI;
-    prj->w[1] = PI/360.0;
-  } else {
-    prj->w[0] = 2.0*prj->r0;
-    prj->w[1] = 1.0/prj->w[0];
-  }
-
-  prj->prjx2s = zeax2s;
-  prj->prjs2x = zeas2x;
-
-  return prjoff(prj, 0.0, 90.0);
-}
-
-/*--------------------------------------------------------------------------*/
-
-int zeax2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)
-
-struct prjprm *prj;
-int nx, ny, sxy, spt;
-const double x[], y[];
-double phi[], theta[];
-int stat[];
-
-{
-  int mx, my, rowlen, rowoff, status;
-  double r, s, xj, yj, yj2;
-  const double tol = 1.0e-12;
-  register int ix, iy, *statp;
-  register const double *xp, *yp;
-  register double *phip, *thetap;
-
-
-  /* Initialize. */
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-  if (prj->flag != ZEA) {
-    if ((status = zeaset(prj))) return status;
-  }
-
-  if (ny > 0) {
-    mx = nx;
-    my = ny;
-  } else {
-    mx = 1;
-    my = 1;
-    ny = nx;
-  }
-
-  status = 0;
-
-
-  /* Do x dependence. */
-  xp = x;
-  rowoff = 0;
-  rowlen = nx*spt;
-  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
-    xj = *xp + prj->x0;
-
-    phip = phi + rowoff;
-    for (iy = 0; iy < my; iy++) {
-      *phip = xj;
-      phip += rowlen;
-    }
-  }
-
-
-  /* Do y dependence. */
-  yp = y;
-  phip   = phi;
-  thetap = theta;
-  statp  = stat;
-  for (iy = 0; iy < ny; iy++, yp += sxy) {
-    yj  = *yp + prj->y0;
-    yj2 = yj*yj;
-
-    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
-      xj  = *phip;
-
-      r = sqrt(xj*xj + yj2);
-      if (r == 0.0) {
-        *phip = 0.0;
-      } else {
-        *phip = atan2d(xj, -yj);
-      }
-
-      s = r*prj->w[1];
-      if (fabs(s) > 1.0) {
-        if (fabs(r - prj->w[0]) < tol) {
-          *thetap = -90.0;
-        } else {
-          *thetap = 0.0;
-          *(statp++) = 1;
-          if (!status) status = PRJERR_BAD_PIX_SET("zeax2s");
-          continue;
-        }
-      } else {
-        *thetap = 90.0 - 2.0*asind(s);
-      }
-
-      *(statp++) = 0;
-    }
-  }
-
-  return status;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int zeas2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)
-
-struct prjprm *prj;
-int nphi, ntheta, spt, sxy;
-const double phi[], theta[];
-double x[], y[];
-int stat[];
-
-{
-  int mphi, mtheta, rowlen, rowoff, status;
-  double cosphi, r, sinphi;
-  register int iphi, itheta, *statp;
-  register const double *phip, *thetap;
-  register double *xp, *yp;
-
-
-  /* Initialize. */
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-  if (prj->flag != ZEA) {
-    if ((status = zeaset(prj))) return status;
-  }
-
-  if (ntheta > 0) {
-    mphi   = nphi;
-    mtheta = ntheta;
-  } else {
-    mphi   = 1;
-    mtheta = 1;
-    ntheta = nphi;
-  }
-
-
-  /* Do phi dependence. */
-  phip = phi;
-  rowoff = 0;
-  rowlen = nphi*sxy;
-  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
-    sincosd(*phip, &sinphi, &cosphi);
-
-    xp = x + rowoff;
-    yp = y + rowoff;
-    for (itheta = 0; itheta < mtheta; itheta++) {
-      *xp = sinphi;
-      *yp = cosphi;
-      xp += rowlen;
-      yp += rowlen;
-    }
-  }
-
-
-  /* Do theta dependence. */
-  thetap = theta;
-  xp = x;
-  yp = y;
-  statp = stat;
-  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
-    r =  prj->w[0]*sind((90.0 - *thetap)/2.0);
-
-    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
-      *xp =  r*(*xp) - prj->x0;
-      *yp = -r*(*yp) - prj->y0;
-      *(statp++) = 0;
-    }
-  }
-
-  return 0;
-}
-
-/*============================================================================
-*   AIR: Airy's projection.
-*
-*   Given:
-*      prj->pv[1]   Latitude theta_b within which the error is minimized, in
-*                   degrees.
-*
-*   Given and/or returned:
-*      prj->r0      Reset to 180/pi if 0.
-*      prj->phi0    Reset to  0.0 if undefined.
-*      prj->theta0  Reset to 90.0 if undefined.
-*
-*   Returned:
-*      prj->flag     AIR
-*      prj->code    "AIR"
-*      prj->x0      Fiducial offset in x.
-*      prj->y0      Fiducial offset in y.
-*      prj->w[0]    2*r0
-*      prj->w[1]    ln(cos(xi_b))/tan(xi_b)**2, where xi_b = (90-theta_b)/2
-*      prj->w[2]    1/2 - prj->w[1]
-*      prj->w[3]    2*r0*prj->w[2]
-*      prj->w[4]    tol, cutoff for using small angle approximation, in
-*                   radians.
-*      prj->w[5]    prj->w[2]*tol
-*      prj->w[6]    (180/pi)/prj->w[2]
-*      prj->prjx2s  Pointer to airx2s().
-*      prj->prjs2x  Pointer to airs2x().
-*===========================================================================*/
-
-int airset(prj)
-
-struct prjprm *prj;
-
-{
-  const double tol = 1.0e-4;
-  double cosxi;
-
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-
-  prj->flag = AIR;
-  strcpy(prj->code, "AIR");
-
-  if (undefined(prj->pv[1])) prj->pv[1] = 90.0;
-  if (prj->r0 == 0.0) prj->r0 = R2D;
-
-  strcpy(prj->name, "Airy's zenithal");
-  prj->category  = ZENITHAL;
-  prj->pvrange   = 101;
-  prj->simplezen = 1;
-  prj->equiareal = 0;
-  prj->conformal = 0;
-  prj->global    = 0;
-  prj->divergent = 1;
-
-  prj->w[0] = 2.0*prj->r0;
-  if (prj->pv[1] == 90.0) {
-    prj->w[1] = -0.5;
-    prj->w[2] =  1.0;
-  } else if (prj->pv[1] > -90.0) {
-    cosxi = cosd((90.0 - prj->pv[1])/2.0);
-    prj->w[1] = log(cosxi)*(cosxi*cosxi)/(1.0-cosxi*cosxi);
-    prj->w[2] = 0.5 - prj->w[1];
-  } else {
-    return PRJERR_BAD_PARAM_SET("airset");
-  }
-
-  prj->w[3] = prj->w[0] * prj->w[2];
-  prj->w[4] = tol;
-  prj->w[5] = prj->w[2]*tol;
-  prj->w[6] = R2D/prj->w[2];
-
-  prj->prjx2s = airx2s;
-  prj->prjs2x = airs2x;
-
-  return prjoff(prj, 0.0, 90.0);
-}
-
-/*--------------------------------------------------------------------------*/
-
-int airx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)
-
-struct prjprm *prj;
-int nx, ny, sxy, spt;
-const double x[], y[];
-double phi[], theta[];
-int stat[];
-
-{
-  int k, mx, my, rowlen, rowoff, status;
-  double cosxi, lambda, r, r1, r2, rt, tanxi, x1, x2, xi, xj, yj, yj2;
-  const double tol = 1.0e-12;
-  register int ix, iy, *statp;
-  register const double *xp, *yp;
-  register double *phip, *thetap;
-
-
-  /* Initialize. */
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-  if (prj->flag != AIR) {
-    if ((status = airset(prj))) return status;
-  }
-
-  if (ny > 0) {
-    mx = nx;
-    my = ny;
-  } else {
-    mx = 1;
-    my = 1;
-    ny = nx;
-  }
-
-  status = 0;
-
-
-  /* Do x dependence. */
-  xp = x;
-  rowoff = 0;
-  rowlen = nx*spt;
-  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
-    xj = *xp + prj->x0;
-
-    phip = phi + rowoff;
-    for (iy = 0; iy < my; iy++) {
-      *phip = xj;
-      phip += rowlen;
-    }
-  }
-
-
-  /* Do y dependence. */
-  yp = y;
-  phip   = phi;
-  thetap = theta;
-  statp  = stat;
-  for (iy = 0; iy < ny; iy++, yp += sxy) {
-    yj  = *yp + prj->y0;
-    yj2 = yj*yj;
-
-    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
-      xj = *phip;
-
-      r = sqrt(xj*xj + yj2)/prj->w[0];
-      if (r == 0.0) {
-        *phip = 0.0;
-      } else {
-        *phip = atan2d(xj, -yj);
-      }
-
-
-      if (r == 0.0) {
-        xi = 0.0;
-      } else if (r < prj->w[5]) {
-        xi = r*prj->w[6];
-      } else {
-        /* Find a solution interval. */
-        x1 = x2 = 1.0;
-        r1 = r2 = 0.0;
-        for (k = 0; k < 30; k++) {
-          x2 = x1/2.0;
-          tanxi = sqrt(1.0-x2*x2)/x2;
-          r2 = -(log(x2)/tanxi + prj->w[1]*tanxi);
-
-          if (r2 >= r) break;
-          x1 = x2;
-          r1 = r2;
-        }
-        if (k == 30) {
-          *thetap = 0.0;
-          *(statp++) = 1;
-          if (!status) status = PRJERR_BAD_PIX_SET("airx2s");
-          continue;
-        }
-
-        for (k = 0; k < 100; k++) {
-          /* Weighted division of the interval. */
-          lambda = (r2-r)/(r2-r1);
-          if (lambda < 0.1) {
-            lambda = 0.1;
-          } else if (lambda > 0.9) {
-            lambda = 0.9;
-          }
-          cosxi = x2 - lambda*(x2-x1);
-
-          tanxi = sqrt(1.0-cosxi*cosxi)/cosxi;
-          rt = -(log(cosxi)/tanxi + prj->w[1]*tanxi);
-
-          if (rt < r) {
-            if (r-rt < tol) break;
-            r1 = rt;
-            x1 = cosxi;
-          } else {
-            if (rt-r < tol) break;
-            r2 = rt;
-            x2 = cosxi;
-          }
-        }
-        if (k == 100) {
-          *thetap = 0.0;
-          *(statp++) = 1;
-          if (!status) status = PRJERR_BAD_PIX_SET("airx2s");
-          continue;
-        }
-
-        xi = acosd(cosxi);
-      }
-
-      *thetap = 90.0 - 2.0*xi;
-      *(statp++) = 0;
-    }
-  }
-
-  return status;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int airs2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)
-
-struct prjprm *prj;
-int nphi, ntheta, spt, sxy;
-const double phi[], theta[];
-double x[], y[];
-int stat[];
-
-{
-  int mphi, mtheta, rowlen, rowoff, status;
-  double cosphi, cosxi, r, tanxi, xi, sinphi;
-  register int iphi, itheta, istat, *statp;
-  register const double *phip, *thetap;
-  register double *xp, *yp;
-
-
-  /* Initialize. */
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-  if (prj->flag != AIR) {
-    if ((status = airset(prj))) return status;
-  }
-
-  if (ntheta > 0) {
-    mphi   = nphi;
-    mtheta = ntheta;
-  } else {
-    mphi   = 1;
-    mtheta = 1;
-    ntheta = nphi;
-  }
-
-  status = 0;
-
-
-  /* Do phi dependence. */
-  phip = phi;
-  rowoff = 0;
-  rowlen = nphi*sxy;
-  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
-    sincosd(*phip, &sinphi, &cosphi);
-
-    xp = x + rowoff;
-    yp = y + rowoff;
-    for (itheta = 0; itheta < mtheta; itheta++) {
-      *xp = sinphi;
-      *yp = cosphi;
-      xp += rowlen;
-      yp += rowlen;
-    }
-  }
-
-
-  /* Do theta dependence. */
-  thetap = theta;
-  xp = x;
-  yp = y;
-  statp = stat;
-  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
-    istat = 0;
-
-    if (*thetap == 90.0) {
-      r = 0.0;
-    } else if (*thetap > -90.0) {
-      xi = D2R*(90.0 - *thetap)/2.0;
-      if (xi < prj->w[4]) {
-        r = xi*prj->w[3];
-      } else {
-        cosxi = cosd((90.0 - *thetap)/2.0);
-        tanxi = sqrt(1.0-cosxi*cosxi)/cosxi;
-        r = -prj->w[0]*(log(cosxi)/tanxi + prj->w[1]*tanxi);
-      }
-    } else {
-      r = 0.0;
-      istat  = 1;
-      if (!status) status = PRJERR_BAD_WORLD_SET("airs2x");
-    }
-
-    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
-      *xp =  r*(*xp) - prj->x0;
-      *yp = -r*(*yp) - prj->y0;
-      *(statp++) = istat;
-    }
-  }
-
-  return status;
-}
-
-/*============================================================================
-*   CYP: cylindrical perspective projection.
-*
-*   Given:
-*      prj->pv[1]   Distance of point of projection from the centre of the
-*                   generating sphere, mu, in units of r0.
-*      prj->pv[2]   Radius of the cylinder of projection, lambda, in units of
-*                   r0.
-*
-*   Given and/or returned:
-*      prj->r0      Reset to 180/pi if 0.
-*      prj->phi0    Reset to 0.0 if undefined.
-*      prj->theta0  Reset to 0.0 if undefined.
-*
-*   Returned:
-*      prj->flag     CYP
-*      prj->code    "CYP"
-*      prj->x0      Fiducial offset in x.
-*      prj->y0      Fiducial offset in y.
-*      prj->w[0]    r0*lambda*(pi/180)
-*      prj->w[1]    (180/pi)/(r0*lambda)
-*      prj->w[2]    r0*(mu + lambda)
-*      prj->w[3]    1/(r0*(mu + lambda))
-*      prj->prjx2s  Pointer to cypx2s().
-*      prj->prjs2x  Pointer to cyps2x().
-*===========================================================================*/
-
-int cypset(prj)
-
-struct prjprm *prj;
-
-{
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-
-  prj->flag = CYP;
-  strcpy(prj->code, "CYP");
-
-  if (undefined(prj->pv[1])) prj->pv[1] = 1.0;
-  if (undefined(prj->pv[2])) prj->pv[2] = 1.0;
-
-  strcpy(prj->name, "cylindrical perspective");
-  prj->category  = CYLINDRICAL;
-  prj->pvrange   = 102;
-  prj->simplezen = 0;
-  prj->equiareal = 0;
-  prj->conformal = 0;
-  prj->global    = prj->pv[1] < -1.0 || 0.0 < prj->pv[1];
-  prj->divergent = !prj->global;
-
-  if (prj->r0 == 0.0) {
-    prj->r0 = R2D;
-
-    prj->w[0] = prj->pv[2];
-    if (prj->w[0] == 0.0) {
-      return PRJERR_BAD_PARAM_SET("cypset");
-    }
-
-    prj->w[1] = 1.0/prj->w[0];
-
-    prj->w[2] = R2D*(prj->pv[1] + prj->pv[2]);
-    if (prj->w[2] == 0.0) {
-      return PRJERR_BAD_PARAM_SET("cypset");
-    }
-
-    prj->w[3] = 1.0/prj->w[2];
-  } else {
-    prj->w[0] = prj->r0*prj->pv[2]*D2R;
-    if (prj->w[0] == 0.0) {
-      return PRJERR_BAD_PARAM_SET("cypset");
-    }
-
-    prj->w[1] = 1.0/prj->w[0];
-
-    prj->w[2] = prj->r0*(prj->pv[1] + prj->pv[2]);
-    if (prj->w[2] == 0.0) {
-      return PRJERR_BAD_PARAM_SET("cypset");
-    }
-
-    prj->w[3] = 1.0/prj->w[2];
-  }
-
-  prj->prjx2s = cypx2s;
-  prj->prjs2x = cyps2x;
-
-  return prjoff(prj, 0.0, 0.0);
-}
-
-/*--------------------------------------------------------------------------*/
-
-int cypx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)
-
-struct prjprm *prj;
-int nx, ny, sxy, spt;
-const double x[], y[];
-double phi[], theta[];
-int stat[];
-
-{
-  int mx, my, rowlen, rowoff, status;
-  double eta, s, t;
-  register int ix, iy, *statp;
-  register const double *xp, *yp;
-  register double *phip, *thetap;
-
-
-  /* Initialize. */
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-  if (prj->flag != CYP) {
-    if ((status = cypset(prj))) return status;
-  }
-
-  if (ny > 0) {
-    mx = nx;
-    my = ny;
-  } else {
-    mx = 1;
-    my = 1;
-    ny = nx;
-  }
-
-
-  /* Do x dependence. */
-  xp = x;
-  rowoff = 0;
-  rowlen = nx*spt;
-  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
-    s = prj->w[1]*(*xp + prj->x0);
-
-    phip = phi + rowoff;
-    for (iy = 0; iy < my; iy++) {
-      *phip = s;
-      phip += rowlen;
-    }
-  }
-
-
-  /* Do y dependence. */
-  yp = y;
-  thetap = theta;
-  statp = stat;
-  for (iy = 0; iy < ny; iy++, yp += sxy) {
-    eta = prj->w[3]*(*yp + prj->y0);
-    t = atan2d(eta,1.0) + asind(eta*prj->pv[1]/sqrt(eta*eta+1.0));
-
-    for (ix = 0; ix < mx; ix++, thetap += spt) {
-      *thetap = t;
-      *(statp++) = 0;
-    }
-  }
-
-  return 0;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int cyps2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)
-
-struct prjprm *prj;
-int nphi, ntheta, spt, sxy;
-const double phi[], theta[];
-double x[], y[];
-int stat[];
-
-{
-  int mphi, mtheta, rowlen, rowoff, status;
-  double eta, xi;
-  register int iphi, itheta, istat, *statp;
-  register const double *phip, *thetap;
-  register double *xp, *yp;
-
-
-  /* Initialize. */
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-  if (prj->flag != CYP) {
-    if ((status = cypset(prj))) return status;
-  }
-
-  if (ntheta > 0) {
-    mphi   = nphi;
-    mtheta = ntheta;
-  } else {
-    mphi   = 1;
-    mtheta = 1;
-    ntheta = nphi;
-  }
-
-  status = 0;
-
-
-  /* Do phi dependence. */
-  phip = phi;
-  rowoff = 0;
-  rowlen = nphi*sxy;
-  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
-    xi = prj->w[0]*(*phip) - prj->x0;
-
-    xp = x + rowoff;
-    for (itheta = 0; itheta < mtheta; itheta++) {
-      *xp = xi;
-      xp += rowlen;
-    }
-  }
-
-
-  /* Do theta dependence. */
-  thetap = theta;
-  yp = y;
-  statp = stat;
-  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
-    eta = prj->pv[1] + cosd(*thetap);
-
-    istat = 0;
-    if (eta == 0.0) {
-      istat  = 1;
-      if (!status) status = PRJERR_BAD_WORLD_SET("cyps2x");
-
-    } else {
-      eta = prj->w[2]*sind(*thetap)/eta;
-    }
-
-    eta -= prj->y0;
-    for (iphi = 0; iphi < mphi; iphi++, yp += sxy) {
-      *yp = eta;
-      *(statp++) = istat;
-    }
-  }
-
-  return status;
-}
-
-/*============================================================================
-*   CEA: cylindrical equal area projection.
-*
-*   Given:
-*      prj->pv[1]   Square of the cosine of the latitude at which the
-*                   projection is conformal, lambda.
-*
-*   Given and/or returned:
-*      prj->r0      Reset to 180/pi if 0.
-*      prj->phi0    Reset to 0.0 if undefined.
-*      prj->theta0  Reset to 0.0 if undefined.
-*
-*   Returned:
-*      prj->flag     CEA
-*      prj->code    "CEA"
-*      prj->x0      Fiducial offset in x.
-*      prj->y0      Fiducial offset in y.
-*      prj->w[0]    r0*(pi/180)
-*      prj->w[1]    (180/pi)/r0
-*      prj->w[2]    r0/lambda
-*      prj->w[3]    lambda/r0
-*      prj->prjx2s  Pointer to ceax2s().
-*      prj->prjs2x  Pointer to ceas2x().
-*===========================================================================*/
-
-int ceaset(prj)
-
-struct prjprm *prj;
-
-{
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-
-  prj->flag = CEA;
-  strcpy(prj->code, "CEA");
-
-  if (undefined(prj->pv[1])) prj->pv[1] = 1.0;
-
-  strcpy(prj->name, "cylindrical equal area");
-  prj->category  = CYLINDRICAL;
-  prj->pvrange   = 101;
-  prj->simplezen = 0;
-  prj->equiareal = 1;
-  prj->conformal = 0;
-  prj->global    = 1;
-  prj->divergent = 0;
-
-  if (prj->r0 == 0.0) {
-    prj->r0 = R2D;
-    prj->w[0] = 1.0;
-    prj->w[1] = 1.0;
-    if (prj->pv[1] <= 0.0 || prj->pv[1] > 1.0) {
-      return PRJERR_BAD_PARAM_SET("ceaset");
-    }
-    prj->w[2] = prj->r0/prj->pv[1];
-    prj->w[3] = prj->pv[1]/prj->r0;
-  } else {
-    prj->w[0] = prj->r0*D2R;
-    prj->w[1] = R2D/prj->r0;
-    if (prj->pv[1] <= 0.0 || prj->pv[1] > 1.0) {
-      return PRJERR_BAD_PARAM_SET("ceaset");
-    }
-    prj->w[2] = prj->r0/prj->pv[1];
-    prj->w[3] = prj->pv[1]/prj->r0;
-  }
-
-  prj->prjx2s = ceax2s;
-  prj->prjs2x = ceas2x;
-
-  return prjoff(prj, 0.0, 0.0);
-}
-
-/*--------------------------------------------------------------------------*/
-
-int ceax2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)
-
-struct prjprm *prj;
-int nx, ny, sxy, spt;
-const double x[], y[];
-double phi[], theta[];
-int stat[];
-
-{
-  int mx, my, rowlen, rowoff, status;
-  double s;
-  const double tol = 1.0e-13;
-  register int istat, ix, iy, *statp;
-  register const double *xp, *yp;
-  register double *phip, *thetap;
-
-
-  /* Initialize. */
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-  if (prj->flag != CEA) {
-    if ((status = ceaset(prj))) return status;
-  }
-
-  if (ny > 0) {
-    mx = nx;
-    my = ny;
-  } else {
-    mx = 1;
-    my = 1;
-    ny = nx;
-  }
-
-  status = 0;
-
-
-  /* Do x dependence. */
-  xp = x;
-  rowoff = 0;
-  rowlen = nx*spt;
-  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
-    s = prj->w[1]*(*xp + prj->x0);
-
-    phip = phi + rowoff;
-    for (iy = 0; iy < my; iy++) {
-      *phip = s;
-      phip += rowlen;
-    }
-  }
-
-
-  /* Do y dependence. */
-  yp = y;
-  thetap = theta;
-  statp = stat;
-  for (iy = 0; iy < ny; iy++, yp += sxy) {
-    s = prj->w[3]*(*yp + prj->y0);
-
-    istat = 0;
-    if (fabs(s) > 1.0) {
-      if (fabs(s) > 1.0+tol) {
-        s = 0.0;
-        istat  = 1;
-        if (!status) status = PRJERR_BAD_PIX_SET("ceax2s");
-      } else {
-        s = copysign(90.0, s);
-      }
-    } else {
-      s = asind(s);
-    }
-
-    for (ix = 0; ix < mx; ix++, thetap += spt) {
-      *thetap = s;
-      *(statp++) = istat;
-    }
-  }
-
-  return status;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int ceas2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)
-
-struct prjprm *prj;
-int nphi, ntheta, spt, sxy;
-const double phi[], theta[];
-double x[], y[];
-int stat[];
-
-{
-  int mphi, mtheta, rowlen, rowoff, status;
-  double eta, xi;
-  register int iphi, itheta, *statp;
-  register const double *phip, *thetap;
-  register double *xp, *yp;
-
-
-  /* Initialize. */
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-  if (prj->flag != CEA) {
-    if ((status = ceaset(prj))) return status;
-  }
-
-  if (ntheta > 0) {
-    mphi   = nphi;
-    mtheta = ntheta;
-  } else {
-    mphi   = 1;
-    mtheta = 1;
-    ntheta = nphi;
-  }
-
-
-  /* Do phi dependence. */
-  phip = phi;
-  rowoff = 0;
-  rowlen = nphi*sxy;
-  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
-    xi = prj->w[0]*(*phip) - prj->x0;
-
-    xp = x + rowoff;
-    for (itheta = 0; itheta < mtheta; itheta++) {
-      *xp = xi;
-      xp += rowlen;
-    }
-  }
-
-
-  /* Do theta dependence. */
-  thetap = theta;
-  yp = y;
-  statp = stat;
-  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
-    eta = prj->w[2]*sind(*thetap) - prj->y0;
-
-    for (iphi = 0; iphi < mphi; iphi++, yp += sxy) {
-      *yp = eta;
-      *(statp++) = 0;
-    }
-  }
-
-  return 0;
-}
-
-/*============================================================================
-*   CAR: Plate carree projection.
-*
-*   Given and/or returned:
-*      prj->r0      Reset to 180/pi if 0.
-*      prj->phi0    Reset to 0.0 if undefined.
-*      prj->theta0  Reset to 0.0 if undefined.
-*
-*   Returned:
-*      prj->flag     CAR
-*      prj->code    "CAR"
-*      prj->x0      Fiducial offset in x.
-*      prj->y0      Fiducial offset in y.
-*      prj->w[0]    r0*(pi/180)
-*      prj->w[1]    (180/pi)/r0
-*      prj->prjx2s  Pointer to carx2s().
-*      prj->prjs2x  Pointer to cars2x().
-*===========================================================================*/
-
-int carset(prj)
-
-struct prjprm *prj;
-
-{
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-
-  prj->flag = CAR;
-  strcpy(prj->code, "CAR");
-
-  strcpy(prj->name, "plate caree");
-  prj->category  = CYLINDRICAL;
-  prj->pvrange   = 0;
-  prj->simplezen = 0;
-  prj->equiareal = 0;
-  prj->conformal = 0;
-  prj->global    = 1;
-  prj->divergent = 0;
-
-  if (prj->r0 == 0.0) {
-    prj->r0 = R2D;
-    prj->w[0] = 1.0;
-    prj->w[1] = 1.0;
-  } else {
-    prj->w[0] = prj->r0*D2R;
-    prj->w[1] = 1.0/prj->w[0];
-  }
-
-  prj->prjx2s = carx2s;
-  prj->prjs2x = cars2x;
-
-  return prjoff(prj, 0.0, 0.0);
-}
-
-/*--------------------------------------------------------------------------*/
-
-int carx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)
-
-struct prjprm *prj;
-int nx, ny, sxy, spt;
-const double x[], y[];
-double phi[], theta[];
-int stat[];
-
-{
-  int mx, my, rowlen, rowoff, status;
-  double s, t;
-  register int ix, iy, *statp;
-  register const double *xp, *yp;
-  register double *phip, *thetap;
-
-
-  /* Initialize. */
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-  if (prj->flag != CAR) {
-    if ((status = carset(prj))) return status;
-  }
-
-  if (ny > 0) {
-    mx = nx;
-    my = ny;
-  } else {
-    mx = 1;
-    my = 1;
-    ny = nx;
-  }
-
-
-  /* Do x dependence. */
-  xp = x;
-  rowoff = 0;
-  rowlen = nx*spt;
-  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
-    s = prj->w[1]*(*xp + prj->x0);
-
-    phip = phi + rowoff;
-    for (iy = 0; iy < my; iy++) {
-      *phip = s;
-      phip += rowlen;
-    }
-  }
-
-
-  /* Do y dependence. */
-  yp = y;
-  thetap = theta;
-  statp = stat;
-  for (iy = 0; iy < ny; iy++, yp += sxy) {
-    t = prj->w[1]*(*yp + prj->y0);
-
-    for (ix = 0; ix < mx; ix++, thetap += spt) {
-      *thetap = t;
-      *(statp++) = 0;
-    }
-  }
-
-  return 0;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int cars2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)
-
-struct prjprm *prj;
-int nphi, ntheta, spt, sxy;
-const double phi[], theta[];
-double x[], y[];
-int stat[];
-
-{
-  int mphi, mtheta, rowlen, rowoff, status;
-  double eta, xi;
-  register int iphi, itheta, *statp;
-  register const double *phip, *thetap;
-  register double *xp, *yp;
-
-
-  /* Initialize. */
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-  if (prj->flag != CAR) {
-    if ((status = carset(prj))) return status;
-  }
-
-  if (ntheta > 0) {
-    mphi   = nphi;
-    mtheta = ntheta;
-  } else {
-    mphi   = 1;
-    mtheta = 1;
-    ntheta = nphi;
-  }
-
-
-  /* Do phi dependence. */
-  phip = phi;
-  rowoff = 0;
-  rowlen = nphi*sxy;
-  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
-    xi = prj->w[0]*(*phip) - prj->x0;
-
-    xp = x + rowoff;
-    for (itheta = 0; itheta < mtheta; itheta++) {
-      *xp = xi;
-      xp += rowlen;
-    }
-  }
-
-
-  /* Do theta dependence. */
-  thetap = theta;
-  yp = y;
-  statp = stat;
-  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
-    eta = prj->w[0]*(*thetap) - prj->y0;
-
-    for (iphi = 0; iphi < mphi; iphi++, yp += sxy) {
-      *yp = eta;
-      *(statp++) = 0;
-    }
-  }
-
-  return 0;
-}
-
-/*============================================================================
-*   MER: Mercator's projection.
-*
-*   Given and/or returned:
-*      prj->r0      Reset to 180/pi if 0.
-*      prj->phi0    Reset to 0.0 if undefined.
-*      prj->theta0  Reset to 0.0 if undefined.
-*
-*   Returned:
-*      prj->flag     MER
-*      prj->code    "MER"
-*      prj->x0      Fiducial offset in x.
-*      prj->y0      Fiducial offset in y.
-*      prj->w[0]    r0*(pi/180)
-*      prj->w[1]    (180/pi)/r0
-*      prj->prjx2s  Pointer to merx2s().
-*      prj->prjs2x  Pointer to mers2x().
-*===========================================================================*/
-
-int merset(prj)
-
-struct prjprm *prj;
-
-{
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-
-  prj->flag = MER;
-  strcpy(prj->code, "MER");
-
-  strcpy(prj->name, "Mercator's");
-  prj->category  = CYLINDRICAL;
-  prj->pvrange   = 0;
-  prj->simplezen = 0;
-  prj->equiareal = 0;
-  prj->conformal = 1;
-  prj->global    = 0;
-  prj->divergent = 1;
-
-  if (prj->r0 == 0.0) {
-    prj->r0 = R2D;
-    prj->w[0] = 1.0;
-    prj->w[1] = 1.0;
-  } else {
-    prj->w[0] = prj->r0*D2R;
-    prj->w[1] = 1.0/prj->w[0];
-  }
-
-  prj->prjx2s = merx2s;
-  prj->prjs2x = mers2x;
-
-  return prjoff(prj, 0.0, 0.0);
-}
-
-/*--------------------------------------------------------------------------*/
-
-int merx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)
-
-struct prjprm *prj;
-int nx, ny, sxy, spt;
-const double x[], y[];
-double phi[], theta[];
-int stat[];
-
-{
-  int mx, my, rowlen, rowoff, status;
-  double s, t;
-  register int ix, iy, *statp;
-  register const double *xp, *yp;
-  register double *phip, *thetap;
-
-
-  /* Initialize. */
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-  if (prj->flag != MER) {
-    if ((status = merset(prj))) return status;
-  }
-
-  if (ny > 0) {
-    mx = nx;
-    my = ny;
-  } else {
-    mx = 1;
-    my = 1;
-    ny = nx;
-  }
-
-
-  /* Do x dependence. */
-  xp = x;
-  rowoff = 0;
-  rowlen = nx*spt;
-  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
-    s = prj->w[1]*(*xp + prj->x0);
-
-    phip = phi + rowoff;
-    for (iy = 0; iy < my; iy++) {
-      *phip = s;
-      phip += rowlen;
-    }
-  }
-
-
-  /* Do y dependence. */
-  yp = y;
-  thetap = theta;
-  statp  = stat;
-  for (iy = 0; iy < ny; iy++, yp += sxy) {
-    t = 2.0*atand(exp((*yp + prj->y0)/prj->r0)) - 90.0;
-
-    for (ix = 0; ix < mx; ix++, thetap += spt) {
-      *thetap = t;
-      *(statp++) = 0;
-    }
-  }
-
-  return 0;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int mers2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)
-
-struct prjprm *prj;
-int nphi, ntheta, spt, sxy;
-const double phi[], theta[];
-double x[], y[];
-int stat[];
-
-{
-  int mphi, mtheta, rowlen, rowoff, status;
-  double eta, xi;
-  register int iphi, itheta, istat, *statp;
-  register const double *phip, *thetap;
-  register double *xp, *yp;
-
-
-  /* Initialize. */
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-  if (prj->flag != MER) {
-    if ((status = merset(prj))) return status;
-  }
-
-  if (ntheta > 0) {
-    mphi   = nphi;
-    mtheta = ntheta;
-  } else {
-    mphi   = 1;
-    mtheta = 1;
-    ntheta = nphi;
-  }
-
-  status = 0;
-
-
-  /* Do phi dependence. */
-  phip = phi;
-  rowoff = 0;
-  rowlen = nphi*sxy;
-  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
-    xi  = prj->w[0]*(*phip) - prj->x0;
-
-    xp = x + rowoff;
-    for (itheta = 0; itheta < mtheta; itheta++) {
-      *xp = xi;
-      xp += rowlen;
-    }
-  }
-
-
-  /* Do theta dependence. */
-  thetap = theta;
-  yp = y;
-  statp = stat;
-  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
-    istat = 0;
-
-    if (*thetap <= -90.0 || *thetap >= 90.0) {
-      eta = 0.0;
-      istat  = 1;
-      if (!status) status = PRJERR_BAD_WORLD_SET("mers2x");
-    } else {
-      eta = prj->r0*log(tand((*thetap+90.0)/2.0)) - prj->y0;
-    }
-
-    for (iphi = 0; iphi < mphi; iphi++, yp += sxy) {
-      *yp = eta;
-      *(statp++) = istat;
-    }
-  }
-
-  return status;
-}
-
-/*============================================================================
-*   SFL: Sanson-Flamsteed ("global sinusoid") projection.
-*
-*   Given and/or returned:
-*      prj->r0      Reset to 180/pi if 0.
-*      prj->phi0    Reset to 0.0 if undefined.
-*      prj->theta0  Reset to 0.0 if undefined.
-*
-*   Returned:
-*      prj->flag     SFL
-*      prj->code    "SFL"
-*      prj->x0      Fiducial offset in x.
-*      prj->y0      Fiducial offset in y.
-*      prj->w[0]    r0*(pi/180)
-*      prj->w[1]    (180/pi)/r0
-*      prj->prjx2s  Pointer to sflx2s().
-*      prj->prjs2x  Pointer to sfls2x().
-*===========================================================================*/
-
-int sflset(prj)
-
-struct prjprm *prj;
-
-{
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-
-  prj->flag = SFL;
-  strcpy(prj->code, "SFL");
-
-  strcpy(prj->name, "Sanson-Flamsteed");
-  prj->category  = PSEUDOCYLINDRICAL;
-  prj->pvrange   = 0;
-  prj->simplezen = 0;
-  prj->equiareal = 1;
-  prj->conformal = 0;
-  prj->global    = 1;
-  prj->divergent = 0;
-
-  if (prj->r0 == 0.0) {
-    prj->r0 = R2D;
-    prj->w[0] = 1.0;
-    prj->w[1] = 1.0;
-  } else {
-    prj->w[0] = prj->r0*D2R;
-    prj->w[1] = 1.0/prj->w[0];
-  }
-
-  prj->prjx2s = sflx2s;
-  prj->prjs2x = sfls2x;
-
-  return prjoff(prj, 0.0, 0.0);
-}
-
-/*--------------------------------------------------------------------------*/
-
-int sflx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)
-
-struct prjprm *prj;
-int nx, ny, sxy, spt;
-const double x[], y[];
-double phi[], theta[];
-int stat[];
-
-{
-  int mx, my, rowlen, rowoff, status;
-  double s, t, yj;
-  register int ix, iy, *statp;
-  register const double *xp, *yp;
-  register double *phip, *thetap;
-
-
-  /* Initialize. */
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-  if (prj->flag != SFL) {
-    if ((status = sflset(prj))) return status;
-  }
-
-  if (ny > 0) {
-    mx = nx;
-    my = ny;
-  } else {
-    mx = 1;
-    my = 1;
-    ny = nx;
-  }
-
-  status = 0;
-
-
-  /* Do x dependence. */
-  xp = x;
-  rowoff = 0;
-  rowlen = nx*spt;
-  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
-    s = prj->w[1]*(*xp + prj->x0);
-
-    phip = phi + rowoff;
-    for (iy = 0; iy < my; iy++) {
-      *phip = s;
-      phip += rowlen;
-    }
-  }
-
-
-  /* Do y dependence. */
-  yp = y;
-  phip   = phi;
-  thetap = theta;
-  statp  = stat;
-  for (iy = 0; iy < ny; iy++, yp += sxy) {
-    yj = *yp + prj->y0;
-    s = cos(yj/prj->r0);
-
-    if (s == 0.0) {
-      if (!status) status = PRJERR_BAD_PIX_SET("sflx2s");
-    } else {
-      s = 1.0/s;
-    }
-
-    t = prj->w[1]*yj;
-
-    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
-      *phip  *= s;
-      *thetap = t;
-      *(statp++) = 0;
-    }
-  }
-
-  return status;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int sfls2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)
-
-struct prjprm *prj;
-int nphi, ntheta, spt, sxy;
-const double phi[], theta[];
-double x[], y[];
-int stat[];
-
-{
-  int mphi, mtheta, rowlen, rowoff, status;
-  double eta, xi;
-  register int iphi, itheta, *statp;
-  register const double *phip, *thetap;
-  register double *xp, *yp;
-
-
-  /* Initialize. */
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-  if (prj->flag != SFL) {
-    if ((status = sflset(prj))) return status;
-  }
-
-  if (ntheta > 0) {
-    mphi   = nphi;
-    mtheta = ntheta;
-  } else {
-    mphi   = 1;
-    mtheta = 1;
-    ntheta = nphi;
-  }
-
-
-  /* Do phi dependence. */
-  phip = phi;
-  rowoff = 0;
-  rowlen = nphi*sxy;
-  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
-    xi = prj->w[0]*(*phip);
-
-    xp = x + rowoff;
-    for (itheta = 0; itheta < mtheta; itheta++) {
-      *xp = xi;
-      xp += rowlen;
-    }
-  }
-
-
-  /* Do theta dependence. */
-  thetap = theta;
-  xp = x;
-  yp = y;
-  statp = stat;
-  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
-    xi  = cosd(*thetap);
-    eta = prj->w[0]*(*thetap) - prj->y0;
-
-    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
-      *xp = xi*(*xp) - prj->x0;
-      *yp = eta;
-      *(statp++) = 0;
-    }
-  }
-
-  return 0;
-}
-
-/*============================================================================
-*   PAR: parabolic projection.
-*
-*   Given and/or returned:
-*      prj->r0      Reset to 180/pi if 0.
-*      prj->phi0    Reset to 0.0 if undefined.
-*      prj->theta0  Reset to 0.0 if undefined.
-*
-*   Returned:
-*      prj->flag     PAR
-*      prj->code    "PAR"
-*      prj->x0      Fiducial offset in x.
-*      prj->y0      Fiducial offset in y.
-*      prj->w[0]    r0*(pi/180)
-*      prj->w[1]    (180/pi)/r0
-*      prj->w[2]    pi*r0
-*      prj->w[3]    1/(pi*r0)
-*      prj->prjx2s  Pointer to parx2s().
-*      prj->prjs2x  Pointer to pars2x().
-*===========================================================================*/
-
-int parset(prj)
-
-struct prjprm *prj;
-
-{
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-
-  prj->flag = PAR;
-  strcpy(prj->code, "PAR");
-
-  strcpy(prj->name, "parabolic");
-  prj->category  = PSEUDOCYLINDRICAL;
-  prj->pvrange   = 0;
-  prj->simplezen = 0;
-  prj->equiareal = 1;
-  prj->conformal = 0;
-  prj->global    = 1;
-  prj->divergent = 0;
-
-  if (prj->r0 == 0.0) {
-    prj->r0 = R2D;
-    prj->w[0] = 1.0;
-    prj->w[1] = 1.0;
-    prj->w[2] = 180.0;
-    prj->w[3] = 1.0/prj->w[2];
-  } else {
-    prj->w[0] = prj->r0*D2R;
-    prj->w[1] = 1.0/prj->w[0];
-    prj->w[2] = PI*prj->r0;
-    prj->w[3] = 1.0/prj->w[2];
-  }
-
-  prj->prjx2s = parx2s;
-  prj->prjs2x = pars2x;
-
-  return prjoff(prj, 0.0, 0.0);
-}
-
-/*--------------------------------------------------------------------------*/
-
-int parx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)
-
-struct prjprm *prj;
-int nx, ny, sxy, spt;
-const double x[], y[];
-double phi[], theta[];
-int stat[];
-
-{
-  int mx, my, rowlen, rowoff, status;
-  double r, s, t, xj;
-  const double tol = 1.0e-13;
-  register int istat, ix, iy, *statp;
-  register const double *xp, *yp;
-  register double *phip, *thetap;
-
-
-  /* Initialize. */
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-  if (prj->flag != PAR) {
-    if ((status = parset(prj))) return status;
-  }
-
-  if (ny > 0) {
-    mx = nx;
-    my = ny;
-  } else {
-    mx = 1;
-    my = 1;
-    ny = nx;
-  }
-
-  status = 0;
-
-
-  /* Do x dependence. */
-  xp = x;
-  rowoff = 0;
-  rowlen = nx*spt;
-  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
-    xj = *xp + prj->x0;
-    s = prj->w[1]*xj;
-    t = fabs(xj) - tol;
-
-    phip   = phi   + rowoff;
-    thetap = theta + rowoff;
-    for (iy = 0; iy < my; iy++) {
-      *phip   = s;
-      *thetap = t;
-      phip   += rowlen;
-      thetap += rowlen;
-    }
-  }
-
-
-  /* Do y dependence. */
-  yp = y;
-  phip   = phi;
-  thetap = theta;
-  statp  = stat;
-  for (iy = 0; iy < ny; iy++, yp += sxy) {
-    r = prj->w[3]*(*yp + prj->y0);
-
-    istat = 0;
-    if (r > 1.0 || r < -1.0) {
-      s = 0.0;
-      t = 0.0;
-      istat  = 1;
-      if (!status) status = PRJERR_BAD_PIX_SET("parx2s");
-
-    } else {
-      s = 1.0 - 4.0*r*r;
-      if (s == 0.0) {
-        /* Deferred test. */
-        istat = -1;
-      } else {
-        s = 1.0/s;
-      }
-
-      t = 3.0*asind(r);
-    }
-
-    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
-      if (istat < 0) {
-        if (*thetap < 0.0) {
-          *(statp++) = 0;
-        } else {
-          *(statp++) = 1;
-          if (!status) status = PRJERR_BAD_PIX_SET("parx2s");
-        }
-      }
-
-      *phip  *= s;
-      *thetap = t;
-    }
-  }
-
-  return status;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int pars2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)
-
-struct prjprm *prj;
-int nphi, ntheta, spt, sxy;
-const double phi[], theta[];
-double x[], y[];
-int stat[];
-
-{
-  int mphi, mtheta, rowlen, rowoff, status;
-  double eta, s, xi;
-  register int iphi, itheta, *statp;
-  register const double *phip, *thetap;
-  register double *xp, *yp;
-
-
-  /* Initialize. */
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-  if (prj->flag != PAR) {
-    if ((status = parset(prj))) return status;
-  }
-
-  if (ntheta > 0) {
-    mphi   = nphi;
-    mtheta = ntheta;
-  } else {
-    mphi   = 1;
-    mtheta = 1;
-    ntheta = nphi;
-  }
-
-
-  /* Do phi dependence. */
-  phip = phi;
-  rowoff = 0;
-  rowlen = nphi*sxy;
-  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
-    xi = prj->w[0]*(*phip);
-
-    xp = x + rowoff;
-    for (itheta = 0; itheta < mtheta; itheta++) {
-      *xp = xi;
-      xp += rowlen;
-    }
-  }
-
-
-  /* Do theta dependence. */
-  thetap = theta;
-  xp = x;
-  yp = y;
-  statp = stat;
-  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
-    s = sind((*thetap)/3.0);
-    xi = (1.0 - 4.0*s*s);
-    eta = prj->w[2]*s - prj->y0;
-
-    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
-      *xp = xi*(*xp) - prj->x0;
-      *yp = eta;
-      *(statp++) = 0;
-    }
-  }
-
-  return 0;
-}
-
-/*============================================================================
-*   MOL: Mollweide's projection.
-*
-*   Given and/or returned:
-*      prj->r0      Reset to 180/pi if 0.
-*      prj->phi0    Reset to 0.0 if undefined.
-*      prj->theta0  Reset to 0.0 if undefined.
-*
-*   Returned:
-*      prj->flag     MOL
-*      prj->code    "MOL"
-*      prj->x0      Fiducial offset in x.
-*      prj->y0      Fiducial offset in y.
-*      prj->w[0]    sqrt(2)*r0
-*      prj->w[1]    sqrt(2)*r0/90
-*      prj->w[2]    1/(sqrt(2)*r0)
-*      prj->w[3]    90/r0
-*      prj->prjx2s  Pointer to molx2s().
-*      prj->prjs2x  Pointer to mols2x().
-*===========================================================================*/
-
-int molset(prj)
-
-struct prjprm *prj;
-
-{
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-
-  prj->flag = MOL;
-  strcpy(prj->code, "MOL");
-
-  if (prj->r0 == 0.0) prj->r0 = R2D;
-
-  strcpy(prj->name, "Mollweide's");
-  prj->category  = PSEUDOCYLINDRICAL;
-  prj->pvrange   = 0;
-  prj->simplezen = 0;
-  prj->equiareal = 1;
-  prj->conformal = 0;
-  prj->global    = 1;
-  prj->divergent = 0;
-
-  prj->w[0] = SQRT2*prj->r0;
-  prj->w[1] = prj->w[0]/90.0;
-  prj->w[2] = 1.0/prj->w[0];
-  prj->w[3] = 90.0/prj->r0;
-  prj->w[4] = 2.0/PI;
-
-  prj->prjx2s = molx2s;
-  prj->prjs2x = mols2x;
-
-  return prjoff(prj, 0.0, 0.0);
-}
-
-/*--------------------------------------------------------------------------*/
-
-int molx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)
-
-struct prjprm *prj;
-int nx, ny, sxy, spt;
-const double x[], y[];
-double phi[], theta[];
-int stat[];
-
-{
-  int mx, my, rowlen, rowoff, status;
-  double r, s, t, xj, y0, yj, z;
-  const double tol = 1.0e-12;
-  register int istat, ix, iy, *statp;
-  register const double *xp, *yp;
-  register double *phip, *thetap;
-
-
-  /* Initialize. */
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-  if (prj->flag != MOL) {
-    if ((status = molset(prj))) return status;
-  }
-
-  if (ny > 0) {
-    mx = nx;
-    my = ny;
-  } else {
-    mx = 1;
-    my = 1;
-    ny = nx;
-  }
-
-  status = 0;
-
-
-  /* Do x dependence. */
-  xp = x;
-  rowoff = 0;
-  rowlen = nx*spt;
-  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
-    xj = *xp + prj->x0;
-    s = prj->w[3]*xj;
-    t = fabs(xj) - tol;
-
-    phip   = phi   + rowoff;
-    thetap = theta + rowoff;
-    for (iy = 0; iy < my; iy++) {
-      *phip   = s;
-      *thetap = t;
-      phip   += rowlen;
-      thetap += rowlen;
-    }
-  }
-
-
-  /* Do y dependence. */
-  yp = y;
-  phip   = phi;
-  thetap = theta;
-  statp  = stat;
-  for (iy = 0; iy < ny; iy++, yp += sxy) {
-    yj = *yp + prj->y0;
-    y0 = yj/prj->r0;
-    r  = 2.0 - y0*y0;
-
-    istat = 0;
-    if (r <= tol) {
-      if (r < -tol) {
-        istat  = 1;
-        if (!status) status = PRJERR_BAD_PIX_SET("molx2s");
-      } else {
-        /* OK if fabs(x) < tol whence phi = 0.0. */
-        istat = -1;
-      }
-
-      r = 0.0;
-      s = 0.0;
-
-    } else {
-      r = sqrt(r);
-      s = 1.0/r;
-    }
-
-    z = yj*prj->w[2];
-    if (fabs(z) > 1.0) {
-      if (fabs(z) > 1.0+tol) {
-        z = 0.0;
-        istat  = 1;
-        if (!status) status = PRJERR_BAD_PIX_SET("molx2s");
-      } else {
-        z = copysign(1.0, z) + y0*r/PI;
-      }
-    } else {
-      z = asin(z)*prj->w[4] + y0*r/PI;
-    }
-
-    if (fabs(z) > 1.0) {
-      if (fabs(z) > 1.0+tol) {
-        z = 0.0;
-        istat  = 1;
-        if (!status) status = PRJERR_BAD_PIX_SET("molx2s");
-      } else {
-        z = copysign(1.0, z);
-      }
-    }
-
-    t = asind(z);
-
-    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
-      if (istat < 0) {
-        if (*thetap < 0.0) {
-          *(statp++) = 0;
-        } else {
-          *(statp++) = 1;
-          if (!status) status = PRJERR_BAD_PIX_SET("molx2s");
-        }
-      }
-
-      *phip  *= s;
-      *thetap = t;
-    }
-  }
-
-  return status;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int mols2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)
-
-struct prjprm *prj;
-int nphi, ntheta, spt, sxy;
-const double phi[], theta[];
-double x[], y[];
-int stat[];
-
-{
-  int k, mphi, mtheta, rowlen, rowoff, status;
-  double eta, gamma, resid, u, v, v0, v1, xi;
-  const double tol = 1.0e-13;
-  register int iphi, itheta, *statp;
-  register const double *phip, *thetap;
-  register double *xp, *yp;
-
-
-  /* Initialize. */
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-  if (prj->flag != MOL) {
-    if ((status = molset(prj))) return status;
-  }
-
-  if (ntheta > 0) {
-    mphi   = nphi;
-    mtheta = ntheta;
-  } else {
-    mphi   = 1;
-    mtheta = 1;
-    ntheta = nphi;
-  }
-
-
-  /* Do phi dependence. */
-  phip = phi;
-  rowoff = 0;
-  rowlen = nphi*sxy;
-  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
-    xi = prj->w[1]*(*phip);
-
-    xp = x + rowoff;
-    for (itheta = 0; itheta < mtheta; itheta++) {
-      *xp = xi;
-      xp += rowlen;
-    }
-  }
-
-
-  /* Do theta dependence. */
-  thetap = theta;
-  xp = x;
-  yp = y;
-  statp = stat;
-  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
-    if (fabs(*thetap) == 90.0) {
-      xi  = 0.0;
-      eta = copysign(prj->w[0], *thetap);
-    } else if (*thetap == 0.0) {
-      xi  = 1.0;
-      eta = 0.0;
-    } else {
-      u  = PI*sind(*thetap);
-      v0 = -PI;
-      v1 =  PI;
-      v  = u;
-      for (k = 0; k < 100; k++) {
-        resid = (v - u) + sin(v);
-        if (resid < 0.0) {
-          if (resid > -tol) break;
-          v0 = v;
-        } else {
-          if (resid < tol) break;
-          v1 = v;
-        }
-        v = (v0 + v1)/2.0;
-      }
-
-      gamma = v/2.0;
-      xi  = cos(gamma);
-      eta = prj->w[0]*sin(gamma);
-    }
-
-    eta -= prj->y0;
-    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
-      *xp = xi*(*xp) - prj->x0;
-      *yp = eta;
-      *(statp++) = 0;
-    }
-  }
-
-  return 0;
-}
-
-/*============================================================================
-*   AIT: Hammer-Aitoff projection.
-*
-*   Given and/or returned:
-*      prj->r0      Reset to 180/pi if 0.
-*      prj->phi0    Reset to 0.0 if undefined.
-*      prj->theta0  Reset to 0.0 if undefined.
-*
-*   Returned:
-*      prj->flag     AIT
-*      prj->code    "AIT"
-*      prj->x0      Fiducial offset in x.
-*      prj->y0      Fiducial offset in y.
-*      prj->w[0]    2*r0**2
-*      prj->w[1]    1/(2*r0)**2
-*      prj->w[2]    1/(4*r0)**2
-*      prj->w[3]    1/(2*r0)
-*      prj->prjx2s  Pointer to aitx2s().
-*      prj->prjs2x  Pointer to aits2x().
-*===========================================================================*/
-
-int aitset(prj)
-
-struct prjprm *prj;
-
-{
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-
-  prj->flag = AIT;
-  strcpy(prj->code, "AIT");
-
-  if (prj->r0 == 0.0) prj->r0 = R2D;
-
-  strcpy(prj->name, "Hammer-Aitoff");
-  prj->category  = CONVENTIONAL;
-  prj->pvrange   = 0;
-  prj->simplezen = 0;
-  prj->equiareal = 1;
-  prj->conformal = 0;
-  prj->global    = 1;
-  prj->divergent = 0;
-
-  prj->w[0] = 2.0*prj->r0*prj->r0;
-  prj->w[1] = 1.0/(2.0*prj->w[0]);
-  prj->w[2] = prj->w[1]/4.0;
-  prj->w[3] = 1.0/(2.0*prj->r0);
-
-  prj->prjx2s = aitx2s;
-  prj->prjs2x = aits2x;
-
-  return prjoff(prj, 0.0, 0.0);
-}
-
-/*--------------------------------------------------------------------------*/
-
-int aitx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)
-
-struct prjprm *prj;
-int nx, ny, sxy, spt;
-const double x[], y[];
-double phi[], theta[];
-int stat[];
-
-{
-  int mx, my, rowlen, rowoff, status;
-  double s, t, x0, xj, y0, yj, yj2, z;
-  const double tol = 1.0e-13;
-  register int ix, iy, istat, *statp;
-  register const double *xp, *yp;
-  register double *phip, *thetap;
-
-
-  /* Initialize. */
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-  if (prj->flag != AIT) {
-    if ((status = aitset(prj))) return status;
-  }
-
-  if (ny > 0) {
-    mx = nx;
-    my = ny;
-  } else {
-    mx = 1;
-    my = 1;
-    ny = nx;
-  }
-
-  status = 0;
-
-
-  /* Do x dependence. */
-  xp = x;
-  rowoff = 0;
-  rowlen = nx*spt;
-  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
-    xj = *xp + prj->x0;
-    s  = 1.0 - xj*xj*prj->w[2];
-    t  = xj*prj->w[3];
-
-    phip   = phi   + rowoff;
-    thetap = theta + rowoff;
-    for (iy = 0; iy < my; iy++) {
-      *phip   = s;
-      *thetap = t;
-      phip   += rowlen;
-      thetap += rowlen;
-    }
-  }
-
-
-  /* Do y dependence. */
-  yp = y;
-  phip   = phi;
-  thetap = theta;
-  statp  = stat;
-  for (iy = 0; iy < ny; iy++, yp += sxy) {
-    yj  = *yp + prj->y0;
-    yj2 = yj*yj*prj->w[1];
-
-    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
-      s = *phip - yj2;
-
-      istat = 0;
-      if (s < 0.5) {
-        if (s < 0.5-tol) {
-          istat  = 1;
-          if (!status) status = PRJERR_BAD_PIX_SET("aitx2s");
-        }
-
-        s = 0.5;
-      }
-
-      z = sqrt(s);
-      x0 = 2.0*z*z - 1.0;
-      y0 = z*(*thetap);
-      if (x0 == 0.0 && y0 == 0.0) {
-        *phip = 0.0;
-      } else {
-        *phip = 2.0*atan2d(y0, x0);
-      }
-
-      t = z*yj/prj->r0;
-      if (fabs(t) > 1.0) {
-        if (fabs(t) > 1.0+tol) {
-          istat  = 1;
-          if (!status) status = PRJERR_BAD_PIX_SET("aitx2s");
-        }
-        t = copysign(90.0, t);
-
-      } else {
-        t = asind(t);
-      }
-
-      *thetap = t;
-      *(statp++) = istat;
-    }
-  }
-
-  return status;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int aits2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)
-
-struct prjprm *prj;
-int nphi, ntheta, spt, sxy;
-const double phi[], theta[];
-double x[], y[];
-int stat[];
-
-{
-  int mphi, mtheta, rowlen, rowoff, status;
-  double cosphi, costhe, sinphi, sinthe, w;
-  register int iphi, itheta, *statp;
-  register const double *phip, *thetap;
-  register double *xp, *yp;
-
-
-  /* Initialize. */
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-  if (prj->flag != AIT) {
-    if ((status = aitset(prj))) return status;
-  }
-
-  if (ntheta > 0) {
-    mphi   = nphi;
-    mtheta = ntheta;
-  } else {
-    mphi   = 1;
-    mtheta = 1;
-    ntheta = nphi;
-  }
-
-
-  /* Do phi dependence. */
-  phip = phi;
-  rowoff = 0;
-  rowlen = nphi*sxy;
-  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
-    w = (*phip)/2.0;
-    sincosd(w, &sinphi, &cosphi);
-
-    xp = x + rowoff;
-    yp = y + rowoff;
-    for (itheta = 0; itheta < mtheta; itheta++) {
-      *xp = sinphi;
-      *yp = cosphi;
-      xp += rowlen;
-      yp += rowlen;
-    }
-  }
-
-
-  /* Do theta dependence. */
-  thetap = theta;
-  xp = x;
-  yp = y;
-  statp = stat;
-  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
-    sincosd(*thetap, &sinthe, &costhe);
-
-    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
-      w = sqrt(prj->w[0]/(1.0 + costhe*(*yp)));
-      *xp = 2.0*w*costhe*(*xp) - prj->x0;
-      *yp = w*sinthe - prj->y0;
-      *(statp++) = 0;
-    }
-  }
-
-  return 0;
-}
-
-/*============================================================================
-*   COP: conic perspective projection.
-*
-*   Given:
-*      prj->pv[1]   sigma = (theta2+theta1)/2
-*      prj->pv[2]   delta = (theta2-theta1)/2, where theta1 and theta2 are the
-*                   latitudes of the standard parallels, in degrees.
-*
-*   Given and/or returned:
-*      prj->r0      Reset to 180/pi if 0.
-*      prj->phi0    Reset to sigma if undefined.
-*      prj->theta0  Reset to sigma if undefined.
-*
-*   Returned:
-*      prj->flag     COP
-*      prj->code    "COP"
-*      prj->x0      Fiducial offset in x.
-*      prj->y0      Fiducial offset in y.
-*      prj->w[0]    C  = sin(sigma)
-*      prj->w[1]    1/C
-*      prj->w[2]    Y0 = r0*cos(delta)*cot(sigma)
-*      prj->w[3]    r0*cos(delta)
-*      prj->w[4]    1/(r0*cos(delta)
-*      prj->w[5]    cot(sigma)
-*      prj->prjx2s  Pointer to copx2s().
-*      prj->prjs2x  Pointer to cops2x().
-*===========================================================================*/
-
-int copset(prj)
-
-struct prjprm *prj;
-
-{
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-
-  prj->flag = COP;
-  strcpy(prj->code, "COP");
-  strcpy(prj->name, "conic perspective");
-
-  if (undefined(prj->pv[1])) {
-    return PRJERR_BAD_PARAM_SET("copset");
-  }
-  if (undefined(prj->pv[2])) prj->pv[2] = 0.0;
-  if (prj->r0 == 0.0) prj->r0 = R2D;
-
-  prj->category  = CONIC;
-  prj->pvrange   = 102;
-  prj->simplezen = 0;
-  prj->equiareal = 0;
-  prj->conformal = 0;
-  prj->global    = 0;
-  prj->divergent = 1;
-
-  prj->w[0] = sind(prj->pv[1]);
-  if (prj->w[0] == 0.0) {
-    return PRJERR_BAD_PARAM_SET("copset");
-  }
-
-  prj->w[1] = 1.0/prj->w[0];
-
-  prj->w[3] = prj->r0*cosd(prj->pv[2]);
-  if (prj->w[3] == 0.0) {
-    return PRJERR_BAD_PARAM_SET("copset");
-  }
-
-  prj->w[4] = 1.0/prj->w[3];
-  prj->w[5] = 1.0/tand(prj->pv[1]);
-
-  prj->w[2] = prj->w[3]*prj->w[5];
-
-  prj->prjx2s = copx2s;
-  prj->prjs2x = cops2x;
-
-  return prjoff(prj, 0.0, prj->pv[1]);
-}
-
-/*--------------------------------------------------------------------------*/
-
-int copx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)
-
-struct prjprm *prj;
-int nx, ny, sxy, spt;
-const double x[], y[];
-double phi[], theta[];
-int stat[];
-
-{
-  int mx, my, rowlen, rowoff, status;
-  double alpha, dy, dy2, r, xj;
-  register int ix, iy, *statp;
-  register const double *xp, *yp;
-  register double *phip, *thetap;
-
-  /* Initialize. */
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-  if (prj->flag != COP) {
-    if ((status = copset(prj))) return status;
-  }
-
-  if (ny > 0) {
-    mx = nx;
-    my = ny;
-  } else {
-    mx = 1;
-    my = 1;
-    ny = nx;
-  }
-
-
-  /* Do x dependence. */
-  xp = x;
-  rowoff = 0;
-  rowlen = nx*spt;
-  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
-    xj = *xp + prj->x0;
-
-    phip = phi + rowoff;
-    for (iy = 0; iy < my; iy++) {
-      *phip = xj;
-      phip += rowlen;
-    }
-  }
-
-
-  /* Do y dependence. */
-  yp = y;
-  phip   = phi;
-  thetap = theta;
-  statp  = stat;
-  for (iy = 0; iy < ny; iy++, yp += sxy) {
-    dy  = prj->w[2] - (*yp + prj->y0);
-    dy2 = dy*dy;
-
-    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
-      xj = *phip;
-
-      r = sqrt(xj*xj + dy2);
-      if (prj->pv[1] < 0.0) r = -r;
-
-      if (r == 0.0) {
-        alpha = 0.0;
-      } else {
-        alpha = atan2d(xj/r, dy/r);
-      }
-
-      *phip = alpha*prj->w[1];
-      *thetap = prj->pv[1] + atand(prj->w[5] - r*prj->w[4]);
-      *(statp++) = 0;
-    }
-  }
-
-  return 0;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int cops2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)
-
-struct prjprm *prj;
-int nphi, ntheta, spt, sxy;
-const double phi[], theta[];
-double x[], y[];
-int stat[];
-
-{
-  int mphi, mtheta, rowlen, rowoff, status;
-  double alpha, cosalpha, r, s, t, sinalpha, y0;
-  register int iphi, itheta, istat, *statp;
-  register const double *phip, *thetap;
-  register double *xp, *yp;
-
-  /* Initialize. */
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-  if (prj->flag != COP) {
-    if ((status = copset(prj))) return status;
-  }
-
-  if (ntheta > 0) {
-    mphi   = nphi;
-    mtheta = ntheta;
-  } else {
-    mphi   = 1;
-    mtheta = 1;
-    ntheta = nphi;
-  }
-
-  status = 0;
-
-
-  /* Do phi dependence. */
-  phip = phi;
-  rowoff = 0;
-  rowlen = nphi*sxy;
-  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
-    alpha = prj->w[0]*(*phip);
-    sincosd(alpha, &sinalpha, &cosalpha);
-
-    xp = x + rowoff;
-    yp = y + rowoff;
-    for (itheta = 0; itheta < mtheta; itheta++) {
-      *xp = sinalpha;
-      *yp = cosalpha;
-      xp += rowlen;
-      yp += rowlen;
-    }
-  }
-
-
-  /* Do theta dependence. */
-  thetap = theta;
-  xp = x;
-  yp = y;
-  statp = stat;
-  y0 = prj->y0 - prj->w[2];
-  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
-    t = *thetap - prj->pv[1];
-    s = cosd(t);
-
-    istat = 0;
-    if (s == 0.0) {
-      r = 0.0;
-      istat  = 1;
-      if (!status) status = PRJERR_BAD_WORLD_SET("cops2x");
-
-    } else {
-      r = prj->w[2] - prj->w[3]*sind(t)/s;
-
-      if (prj->bounds && r*prj->w[0] < 0.0) {
-        istat  = 1;
-        if (!status) status = PRJERR_BAD_WORLD_SET("cops2x");
-      }
-    }
-
-    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
-      *xp =  r*(*xp) - prj->x0;
-      *yp = -r*(*yp) - y0;
-      *(statp++) = istat;
-    }
-  }
-
-  return status;
-}
-
-/*============================================================================
-*   COE: conic equal area projection.
-*
-*   Given:
-*      prj->pv[1]   sigma = (theta2+theta1)/2
-*      prj->pv[2]   delta = (theta2-theta1)/2, where theta1 and theta2 are the
-*                   latitudes of the standard parallels, in degrees.
-*
-*   Given and/or returned:
-*      prj->r0      Reset to 180/pi if 0.
-*      prj->phi0    Reset to sigma if undefined.
-*      prj->theta0  Reset to sigma if undefined.
-*
-*   Returned:
-*      prj->flag     COE
-*      prj->code    "COE"
-*      prj->x0      Fiducial offset in x.
-*      prj->y0      Fiducial offset in y.
-*      prj->w[0]    C = (sin(theta1) + sin(theta2))/2
-*      prj->w[1]    1/C
-*      prj->w[2]    Y0 = chi*sqrt(psi - 2C*sind(sigma))
-*      prj->w[3]    chi = r0/C
-*      prj->w[4]    psi = 1 + sin(theta1)*sin(theta2)
-*      prj->w[5]    2C
-*      prj->w[6]    (1 + sin(theta1)*sin(theta2))*(r0/C)**2
-*      prj->w[7]    C/(2*r0**2)
-*      prj->w[8]    chi*sqrt(psi + 2C)
-*      prj->prjx2s  Pointer to coex2s().
-*      prj->prjs2x  Pointer to coes2x().
-*===========================================================================*/
-
-int coeset(prj)
-
-struct prjprm *prj;
-
-{
-  double theta1, theta2;
-
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-
-  prj->flag = COE;
-  strcpy(prj->code, "COE");
-  strcpy(prj->name, "conic equal area");
-
-  if (undefined(prj->pv[1])) {
-    return PRJERR_BAD_PARAM_SET("coeset");
-  }
-  if (undefined(prj->pv[2])) prj->pv[2] = 0.0;
-  if (prj->r0 == 0.0) prj->r0 = R2D;
-
-  prj->category  = CONIC;
-  prj->pvrange   = 102;
-  prj->simplezen = 0;
-  prj->equiareal = 1;
-  prj->conformal = 0;
-  prj->global    = 1;
-  prj->divergent = 0;
-
-  theta1 = prj->pv[1] - prj->pv[2];
-  theta2 = prj->pv[1] + prj->pv[2];
-
-  prj->w[0] = (sind(theta1) + sind(theta2))/2.0;
-  if (prj->w[0] == 0.0) {
-    return PRJERR_BAD_PARAM_SET("coeset");
-  }
-
-  prj->w[1] = 1.0/prj->w[0];
-
-  prj->w[3] = prj->r0/prj->w[0];
-  prj->w[4] = 1.0 + sind(theta1)*sind(theta2);
-  prj->w[5] = 2.0*prj->w[0];
-  prj->w[6] = prj->w[3]*prj->w[3]*prj->w[4];
-  prj->w[7] = 1.0/(2.0*prj->r0*prj->w[3]);
-  prj->w[8] = prj->w[3]*sqrt(prj->w[4] + prj->w[5]);
-
-  prj->w[2] = prj->w[3]*sqrt(prj->w[4] - prj->w[5]*sind(prj->pv[1]));
-
-  prj->prjx2s = coex2s;
-  prj->prjs2x = coes2x;
-
-  return prjoff(prj, 0.0, prj->pv[1]);
-}
-
-/*--------------------------------------------------------------------------*/
-
-int coex2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)
-
-struct prjprm *prj;
-int nx, ny, sxy, spt;
-const double x[], y[];
-double phi[], theta[];
-int stat[];
-
-{
-  int mx, my, rowlen, rowoff, status;
-  double alpha, dy, dy2, r, t, w, xj;
-  const double tol = 1.0e-12;
-  register int ix, iy, istat, *statp;
-  register const double *xp, *yp;
-  register double *phip, *thetap;
-
-  /* Initialize. */
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-  if (prj->flag != COE) {
-    if ((status = coeset(prj))) return status;
-  }
-
-  if (ny > 0) {
-    mx = nx;
-    my = ny;
-  } else {
-    mx = 1;
-    my = 1;
-    ny = nx;
-  }
-
-  status = 0;
-
-
-  /* Do x dependence. */
-  xp = x;
-  rowoff = 0;
-  rowlen = nx*spt;
-  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
-    xj = *xp + prj->x0;
-
-    phip = phi + rowoff;
-    for (iy = 0; iy < my; iy++) {
-      *phip = xj;
-      phip += rowlen;
-    }
-  }
-
-
-  /* Do y dependence. */
-  yp = y;
-  phip   = phi;
-  thetap = theta;
-  statp  = stat;
-  for (iy = 0; iy < ny; iy++, yp += sxy) {
-    dy  = prj->w[2] - (*yp + prj->y0);
-    dy2 = dy*dy;
-
-    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
-      xj = *phip;
-
-      r = sqrt(xj*xj + dy2);
-      if (prj->pv[1] < 0.0) r = -r;
-
-      if (r == 0.0) {
-        alpha = 0.0;
-      } else {
-        alpha = atan2d(xj/r, dy/r);
-      }
-
-      istat = 0;
-      if (fabs(r - prj->w[8]) < tol) {
-        t = -90.0;
-      } else {
-        w = (prj->w[6] - r*r)*prj->w[7];
-        if (fabs(w) > 1.0) {
-          if (fabs(w-1.0) < tol) {
-            t = 90.0;
-          } else if (fabs(w+1.0) < tol) {
-            t = -90.0;
-          } else {
-            t = 0.0;
-            istat  = 1;
-            if (!status) status = PRJERR_BAD_PIX_SET("coex2s");
-          }
-        } else {
-          t = asind(w);
-        }
-      }
-
-      *phip = alpha*prj->w[1];
-      *thetap = t;
-      *(statp++) = istat;
-    }
-  }
-
-  return status;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int coes2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)
-
-struct prjprm *prj;
-int nphi, ntheta, spt, sxy;
-const double phi[], theta[];
-double x[], y[];
-int stat[];
-
-{
-  int mphi, mtheta, rowlen, rowoff, status;
-  double alpha, cosalpha, r, sinalpha, y0;
-  register int iphi, itheta, *statp;
-  register const double *phip, *thetap;
-  register double *xp, *yp;
-
-  /* Initialize. */
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-  if (prj->flag != COE) {
-    if ((status = coeset(prj))) return status;
-  }
-
-  if (ntheta > 0) {
-    mphi   = nphi;
-    mtheta = ntheta;
-  } else {
-    mphi   = 1;
-    mtheta = 1;
-    ntheta = nphi;
-  }
-
-
-  /* Do phi dependence. */
-  phip = phi;
-  rowoff = 0;
-  rowlen = nphi*sxy;
-  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
-    alpha = prj->w[0]*(*phip);
-    sincosd(alpha, &sinalpha, &cosalpha);
-
-    xp = x + rowoff;
-    yp = y + rowoff;
-    for (itheta = 0; itheta < mtheta; itheta++) {
-      *xp = sinalpha;
-      *yp = cosalpha;
-      xp += rowlen;
-      yp += rowlen;
-    }
-  }
-
-
-  /* Do theta dependence. */
-  thetap = theta;
-  xp = x;
-  yp = y;
-  statp = stat;
-  y0 = prj->y0 - prj->w[2];
-  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
-    if (*thetap == -90.0) {
-      r = prj->w[8];
-    } else {
-      r = prj->w[3]*sqrt(prj->w[4] - prj->w[5]*sind(*thetap));
-    }
-
-    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
-      *xp =  r*(*xp) - prj->x0;
-      *yp = -r*(*yp) - y0;
-      *(statp++) = 0;
-    }
-  }
-
-  return 0;
-}
-
-/*============================================================================
-*   COD: conic equidistant projection.
-*
-*   Given:
-*      prj->pv[1]   sigma = (theta2+theta1)/2
-*      prj->pv[2]   delta = (theta2-theta1)/2, where theta1 and theta2 are the
-*                   latitudes of the standard parallels, in degrees.
-*
-*   Given and/or returned:
-*      prj->r0      Reset to 180/pi if 0.
-*      prj->phi0    Reset to sigma if undefined.
-*      prj->theta0  Reset to sigma if undefined.
-*
-*   Returned:
-*      prj->flag     COD
-*      prj->code    "COD"
-*      prj->x0      Fiducial offset in x.
-*      prj->y0      Fiducial offset in y.
-*      prj->w[0]    C = r0*sin(sigma)*sin(delta)/delta
-*      prj->w[1]    1/C
-*      prj->w[2]    Y0 = delta*cot(delta)*cot(sigma)
-*      prj->w[3]    Y0 + sigma
-*      prj->prjx2s  Pointer to codx2s().
-*      prj->prjs2x  Pointer to cods2x().
-*===========================================================================*/
-
-int codset(prj)
-
-struct prjprm *prj;
-
-{
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-
-  prj->flag = COD;
-  strcpy(prj->code, "COD");
-  strcpy(prj->name, "conic equidistant");
-
-  if (undefined(prj->pv[1])) {
-    return PRJERR_BAD_PARAM_SET("codset");
-  }
-  if (undefined(prj->pv[2])) prj->pv[2] = 0.0;
-  if (prj->r0 == 0.0) prj->r0 = R2D;
-
-  prj->category  = CONIC;
-  prj->pvrange   = 102;
-  prj->simplezen = 0;
-  prj->equiareal = 0;
-  prj->conformal = 0;
-  prj->global    = 1;
-  prj->divergent = 0;
-
-  if (prj->pv[2] == 0.0) {
-    prj->w[0] = prj->r0*sind(prj->pv[1])*D2R;
-  } else {
-    prj->w[0] = prj->r0*sind(prj->pv[1])*sind(prj->pv[2])/prj->pv[2];
-  }
-
-  if (prj->w[0] == 0.0) {
-    return PRJERR_BAD_PARAM_SET("codset");
-  }
-
-  prj->w[1] = 1.0/prj->w[0];
-  prj->w[2] = prj->r0*cosd(prj->pv[2])*cosd(prj->pv[1])/prj->w[0];
-  prj->w[3] = prj->w[2] + prj->pv[1];
-
-  prj->prjx2s = codx2s;
-  prj->prjs2x = cods2x;
-
-  return prjoff(prj, 0.0, prj->pv[1]);
-}
-
-/*--------------------------------------------------------------------------*/
-
-int codx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)
-
-struct prjprm *prj;
-int nx, ny, sxy, spt;
-const double x[], y[];
-double phi[], theta[];
-int stat[];
-
-{
-  int mx, my, rowlen, rowoff, status;
-  double alpha, dy, dy2, r, xj;
-  register int ix, iy, *statp;
-  register const double *xp, *yp;
-  register double *phip, *thetap;
-
-  /* Initialize. */
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-  if (prj->flag != COD) {
-    if ((status = codset(prj))) return status;
-  }
-
-  if (ny > 0) {
-    mx = nx;
-    my = ny;
-  } else {
-    mx = 1;
-    my = 1;
-    ny = nx;
-  }
-
-
-  /* Do x dependence. */
-  xp = x;
-  rowoff = 0;
-  rowlen = nx*spt;
-  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
-    xj = *xp + prj->x0;
-
-    phip = phi + rowoff;
-    for (iy = 0; iy < my; iy++) {
-      *phip = xj;
-      phip += rowlen;
-    }
-  }
-
-
-  /* Do y dependence. */
-  yp = y;
-  phip   = phi;
-  thetap = theta;
-  statp  = stat;
-  for (iy = 0; iy < ny; iy++, yp += sxy) {
-    dy  = prj->w[2] - (*yp + prj->y0);
-    dy2 = dy*dy;
-
-    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
-      xj = *phip;
-
-      r = sqrt(xj*xj + dy2);
-      if (prj->pv[1] < 0.0) r = -r;
-
-      if (r == 0.0) {
-        alpha = 0.0;
-      } else {
-        alpha = atan2d(xj/r, dy/r);
-      }
-
-      *phip = alpha*prj->w[1];
-      *thetap = prj->w[3] - r;
-      *(statp++) = 0;
-    }
-  }
-
-  return 0;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int cods2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)
-
-struct prjprm *prj;
-int nphi, ntheta, spt, sxy;
-const double phi[], theta[];
-double x[], y[];
-int stat[];
-
-{
-  int mphi, mtheta, rowlen, rowoff, status;
-  double alpha, cosalpha, r, sinalpha, y0;
-  register int iphi, itheta, *statp;
-  register const double *phip, *thetap;
-  register double *xp, *yp;
-
-  /* Initialize. */
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-  if (prj->flag != COD) {
-    if ((status = codset(prj))) return status;
-  }
-
-  if (ntheta > 0) {
-    mphi   = nphi;
-    mtheta = ntheta;
-  } else {
-    mphi   = 1;
-    mtheta = 1;
-    ntheta = nphi;
-  }
-
-
-  /* Do phi dependence. */
-  phip = phi;
-  rowoff = 0;
-  rowlen = nphi*sxy;
-  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
-    alpha = prj->w[0]*(*phip);
-    sincosd(alpha, &sinalpha, &cosalpha);
-
-    xp = x + rowoff;
-    yp = y + rowoff;
-    for (itheta = 0; itheta < mtheta; itheta++) {
-      *xp = sinalpha;
-      *yp = cosalpha;
-      xp += rowlen;
-      yp += rowlen;
-    }
-  }
-
-
-  /* Do theta dependence. */
-  thetap = theta;
-  xp = x;
-  yp = y;
-  statp = stat;
-  y0 = prj->y0 - prj->w[2];
-  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
-    r = prj->w[3] - *thetap;
-
-    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
-      *xp =  r*(*xp) - prj->x0;
-      *yp = -r*(*yp) - y0;
-      *(statp++) = 0;
-    }
-  }
-
-  return 0;
-}
-
-/*============================================================================
-*   COO: conic orthomorphic projection.
-*
-*   Given:
-*      prj->pv[1]   sigma = (theta2+theta1)/2
-*      prj->pv[2]   delta = (theta2-theta1)/2, where theta1 and theta2 are the
-*                   latitudes of the standard parallels, in degrees.
-*
-*   Given and/or returned:
-*      prj->r0      Reset to 180/pi if 0.
-*      prj->phi0    Reset to sigma if undefined.
-*      prj->theta0  Reset to sigma if undefined.
-*
-*   Returned:
-*      prj->flag     COO
-*      prj->code    "COO"
-*      prj->x0      Fiducial offset in x.
-*      prj->y0      Fiducial offset in y.
-*      prj->w[0]    C = ln(cos(theta2)/cos(theta1))/ln(tan(tau2)/tan(tau1))
-*                       where tau1 = (90 - theta1)/2
-*                             tau2 = (90 - theta2)/2
-*      prj->w[1]    1/C
-*      prj->w[2]    Y0 = psi*tan((90-sigma)/2)**C
-*      prj->w[3]    psi = (r0*cos(theta1)/C)/tan(tau1)**C
-*      prj->w[4]    1/psi
-*      prj->prjx2s  Pointer to coox2s().
-*      prj->prjs2x  Pointer to coos2x().
-*===========================================================================*/
-
-int cooset(prj)
-
-struct prjprm *prj;
-
-{
-  double cos1, cos2, tan1, tan2, theta1, theta2;
-
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-
-  prj->flag = COO;
-  strcpy(prj->code, "COO");
-  strcpy(prj->name, "conic orthomorphic");
-
-  if (undefined(prj->pv[1])) {
-    return PRJERR_BAD_PARAM_SET("cooset");
-  }
-  if (undefined(prj->pv[2])) prj->pv[2] = 0.0;
-  if (prj->r0 == 0.0) prj->r0 = R2D;
-
-  prj->category  = CONIC;
-  prj->pvrange   = 102;
-  prj->simplezen = 0;
-  prj->equiareal = 0;
-  prj->conformal = 1;
-  prj->global    = 0;
-  prj->divergent = 1;
-
-  theta1 = prj->pv[1] - prj->pv[2];
-  theta2 = prj->pv[1] + prj->pv[2];
-
-  tan1 = tand((90.0 - theta1)/2.0);
-  cos1 = cosd(theta1);
-
-  if (theta1 == theta2) {
-    prj->w[0] = sind(theta1);
-  } else {
-    tan2 = tand((90.0 - theta2)/2.0);
-    cos2 = cosd(theta2);
-    prj->w[0] = log(cos2/cos1)/log(tan2/tan1);
-  }
-  if (prj->w[0] == 0.0) {
-    return PRJERR_BAD_PARAM_SET("cooset");
-  }
-
-  prj->w[1] = 1.0/prj->w[0];
-
-  prj->w[3] = prj->r0*(cos1/prj->w[0])/pow(tan1,prj->w[0]);
-  if (prj->w[3] == 0.0) {
-    return PRJERR_BAD_PARAM_SET("cooset");
-  }
-  prj->w[2] = prj->w[3]*pow(tand((90.0 - prj->pv[1])/2.0),prj->w[0]);
-  prj->w[4] = 1.0/prj->w[3];
-
-  prj->prjx2s = coox2s;
-  prj->prjs2x = coos2x;
-
-  return prjoff(prj, 0.0, prj->pv[1]);
-}
-
-/*--------------------------------------------------------------------------*/
-
-int coox2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)
-
-struct prjprm *prj;
-int nx, ny, sxy, spt;
-const double x[], y[];
-double phi[], theta[];
-int stat[];
-
-{
-  int mx, my, rowlen, rowoff, status;
-  double alpha, dy, dy2, r, t, xj;
-  register int ix, iy, istat, *statp;
-  register const double *xp, *yp;
-  register double *phip, *thetap;
-
-  /* Initialize. */
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-  if (prj->flag != COO) {
-    if ((status = cooset(prj))) return status;
-  }
-
-  if (ny > 0) {
-    mx = nx;
-    my = ny;
-  } else {
-    mx = 1;
-    my = 1;
-    ny = nx;
-  }
-
-  status = 0;
-
-
-  /* Do x dependence. */
-  xp = x;
-  rowoff = 0;
-  rowlen = nx*spt;
-  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
-    xj = *xp + prj->x0;
-
-    phip = phi + rowoff;
-    for (iy = 0; iy < my; iy++) {
-      *phip = xj;
-      phip += rowlen;
-    }
-  }
-
-
-  /* Do y dependence. */
-  yp = y;
-  phip   = phi;
-  thetap = theta;
-  statp  = stat;
-  for (iy = 0; iy < ny; iy++, yp += sxy) {
-    dy  = prj->w[2] - (*yp + prj->y0);
-    dy2 = dy*dy;
-
-    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
-      xj = *phip;
-
-      r = sqrt(xj*xj + dy2);
-      if (prj->pv[1] < 0.0) r = -r;
-
-      if (r == 0.0) {
-        alpha = 0.0;
-      } else {
-        alpha = atan2d(xj/r, dy/r);
-      }
-
-      istat = 0;
-      if (r == 0.0) {
-        if (prj->w[0] < 0.0) {
-          t = -90.0;
-        } else {
-          t = 0.0;
-          istat  = 1;
-          if (!status) status = PRJERR_BAD_PIX_SET("coox2s");
-        }
-      } else {
-        t = 90.0 - 2.0*atand(pow(r*prj->w[4],prj->w[1]));
-      }
-
-      *phip = alpha*prj->w[1];
-      *thetap = t;
-      *(statp++) = istat;
-    }
-  }
-
-  return status;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int coos2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)
-
-struct prjprm *prj;
-int nphi, ntheta, spt, sxy;
-const double phi[], theta[];
-double x[], y[];
-int stat[];
-
-{
-  int mphi, mtheta, rowlen, rowoff, status;
-  double alpha, cosalpha, r, sinalpha, y0;
-  register int iphi, itheta, istat, *statp;
-  register const double *phip, *thetap;
-  register double *xp, *yp;
-
-  /* Initialize. */
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-  if (prj->flag != COO) {
-    if ((status = cooset(prj))) return status;
-  }
-
-  if (ntheta > 0) {
-    mphi   = nphi;
-    mtheta = ntheta;
-  } else {
-    mphi   = 1;
-    mtheta = 1;
-    ntheta = nphi;
-  }
-
-  status = 0;
-
-
-  /* Do phi dependence. */
-  phip = phi;
-  rowoff = 0;
-  rowlen = nphi*sxy;
-  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
-    alpha = prj->w[0]*(*phip);
-    sincosd(alpha, &sinalpha, &cosalpha);
-
-    xp = x + rowoff;
-    yp = y + rowoff;
-    for (itheta = 0; itheta < mtheta; itheta++) {
-      *xp = sinalpha;
-      *yp = cosalpha;
-      xp += rowlen;
-      yp += rowlen;
-    }
-  }
-
-
-  /* Do theta dependence. */
-  thetap = theta;
-  xp = x;
-  yp = y;
-  statp = stat;
-  y0 = prj->y0 - prj->w[2];
-  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
-    istat = 0;
-
-    if (*thetap == -90.0) {
-      r = 0.0;
-      if (prj->w[0] >= 0.0) {
-        istat  = 1;
-        if (!status) status = PRJERR_BAD_WORLD_SET("coos2x");
-      }
-    } else {
-      r = prj->w[3]*pow(tand((90.0 - *thetap)/2.0),prj->w[0]);
-    }
-
-    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
-      *xp =  r*(*xp) - prj->x0;
-      *yp = -r*(*yp) - y0;
-      *(statp++) = istat;
-    }
-  }
-
-  return status;
-}
-
-/*============================================================================
-*   BON: Bonne's projection.
-*
-*   Given:
-*      prj->pv[1]   Bonne conformal latitude, theta1, in degrees.
-*
-*   Given and/or returned:
-*      prj->r0      Reset to 180/pi if 0.
-*      prj->phi0    Reset to 0.0 if undefined.
-*      prj->theta0  Reset to 0.0 if undefined.
-*
-*   Returned:
-*      prj->flag     BON
-*      prj->code    "BON"
-*      prj->x0      Fiducial offset in x.
-*      prj->y0      Fiducial offset in y.
-*      prj->w[1]    r0*pi/180
-*      prj->w[2]    Y0 = r0*(cot(theta1) + theta1*pi/180)
-*      prj->prjx2s  Pointer to bonx2s().
-*      prj->prjs2x  Pointer to bons2x().
-*===========================================================================*/
-
-int bonset(prj)
-
-struct prjprm *prj;
-
-{
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-
-  prj->flag = BON;
-  strcpy(prj->code, "BON");
-  strcpy(prj->name, "Bonne's");
-
-  if (undefined(prj->pv[1])) {
-    return PRJERR_BAD_PARAM_SET("bonset");
-  }
-
-  if (prj->pv[1] == 0.0) {
-    /* Sanson-Flamsteed. */
-    return sflset(prj);
-  }
-
-  prj->category  = POLYCONIC;
-  prj->pvrange   = 101;
-  prj->simplezen = 0;
-  prj->equiareal = 1;
-  prj->conformal = 0;
-  prj->global    = 1;
-  prj->divergent = 0;
-
-  if (prj->r0 == 0.0) {
-    prj->r0 = R2D;
-    prj->w[1] = 1.0;
-    prj->w[2] = prj->r0*cosd(prj->pv[1])/sind(prj->pv[1]) + prj->pv[1];
-  } else {
-    prj->w[1] = prj->r0*D2R;
-    prj->w[2] = prj->r0*(cosd(prj->pv[1])/sind(prj->pv[1]) + prj->pv[1]*D2R);
-  }
-
-  prj->prjx2s = bonx2s;
-  prj->prjs2x = bons2x;
-
-  return prjoff(prj, 0.0, 0.0);
-}
-
-/*--------------------------------------------------------------------------*/
-
-int bonx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)
-
-struct prjprm *prj;
-int nx, ny, sxy, spt;
-const double x[], y[];
-double phi[], theta[];
-int stat[];
-
-{
-  int mx, my, rowlen, rowoff, status;
-  double alpha, dy, dy2, costhe, r, s, t, xj;
-  register int ix, iy, *statp;
-  register const double *xp, *yp;
-  register double *phip, *thetap;
-
-
-  /* Initialize. */
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-  if (prj->pv[1] == 0.0) {
-    /* Sanson-Flamsteed. */
-    return sflx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat);
-  }
-
-  if (prj->flag != BON) {
-    if ((status = bonset(prj))) return status;
-  }
-
-  if (ny > 0) {
-    mx = nx;
-    my = ny;
-  } else {
-    mx = 1;
-    my = 1;
-    ny = nx;
-  }
-
-
-  /* Do x dependence. */
-  xp = x;
-  rowoff = 0;
-  rowlen = nx*spt;
-  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
-    xj = *xp + prj->x0;
-
-    phip = phi + rowoff;
-    for (iy = 0; iy < my; iy++) {
-      *phip = xj;
-      phip += rowlen;
-    }
-  }
-
-
-  /* Do y dependence. */
-  yp = y;
-  phip   = phi;
-  thetap = theta;
-  statp  = stat;
-  for (iy = 0; iy < ny; iy++, yp += sxy) {
-    dy  = prj->w[2] - (*yp + prj->y0);
-    dy2 = dy*dy;
-
-    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
-      xj = *phip;
-
-      r = sqrt(xj*xj + dy2);
-      if (prj->pv[1] < 0.0) r = -r;
-
-      if (r == 0.0) {
-        alpha = 0.0;
-      } else {
-        alpha = atan2d(xj/r, dy/r);
-      }
-
-      t = (prj->w[2] - r)/prj->w[1];
-      costhe = cosd(t);
-      if (costhe == 0.0) {
-        s = 0.0;
-      } else {
-        s = alpha*(r/prj->r0)/costhe;
-      }
-
-      *phip = s;
-      *thetap = t;
-      *(statp++) = 0;
-    }
-  }
-
-  return 0;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int bons2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)
-
-struct prjprm *prj;
-int nphi, ntheta, spt, sxy;
-const double phi[], theta[];
-double x[], y[];
-int stat[];
-
-{
-  int mphi, mtheta, rowlen, rowoff, status;
-  double alpha, cosalpha, r, s, sinalpha, y0;
-  register int iphi, itheta, *statp;
-  register const double *phip, *thetap;
-  register double *xp, *yp;
-
-  /* Initialize. */
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-  if (prj->pv[1] == 0.0) {
-    /* Sanson-Flamsteed. */
-    return sfls2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat);
-  }
-
-  if (prj->flag != BON) {
-    if ((status = bonset(prj))) return status;
-  }
-
-  if (ntheta > 0) {
-    mphi   = nphi;
-    mtheta = ntheta;
-  } else {
-    mphi   = 1;
-    mtheta = 1;
-    ntheta = nphi;
-  }
-
-  y0 = prj->y0 - prj->w[2];
-
-
-  /* Do phi dependence. */
-  phip = phi;
-  rowoff = 0;
-  rowlen = nphi*sxy;
-  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
-    s = prj->r0*(*phip);
-
-    xp = x + rowoff;
-    for (itheta = 0; itheta < mtheta; itheta++) {
-      *xp = s;
-      xp += rowlen;
-    }
-  }
-
-
-  /* Do theta dependence. */
-  thetap = theta;
-  xp = x;
-  yp = y;
-  statp = stat;
-  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
-    r = prj->w[2] - prj->w[1]*(*thetap);
-    s = cosd(*thetap)/r;
-
-    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
-      alpha = s*(*xp);
-      sincosd(alpha, &sinalpha, &cosalpha);
-      *xp =  r*sinalpha - prj->x0;
-      *yp = -r*cosalpha - y0;
-      *(statp++) = 0;
-    }
-  }
-
-  return 0;
-}
-
-/*============================================================================
-*   PCO: polyconic projection.
-*
-*   Given and/or returned:
-*      prj->r0      Reset to 180/pi if 0.
-*      prj->phi0    Reset to 0.0 if undefined.
-*      prj->theta0  Reset to 0.0 if undefined.
-*
-*   Returned:
-*      prj->flag     PCO
-*      prj->code    "PCO"
-*      prj->x0      Fiducial offset in x.
-*      prj->y0      Fiducial offset in y.
-*      prj->w[0]    r0*(pi/180)
-*      prj->w[1]    1/r0
-*      prj->w[2]    2*r0
-*      prj->prjx2s  Pointer to pcox2s().
-*      prj->prjs2x  Pointer to pcos2x().
-*===========================================================================*/
-
-int pcoset(prj)
-
-struct prjprm *prj;
-
-{
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-
-  prj->flag = PCO;
-  strcpy(prj->code, "PCO");
-
-  strcpy(prj->name, "polyconic");
-  prj->category  = POLYCONIC;
-  prj->pvrange   = 0;
-  prj->simplezen = 0;
-  prj->equiareal = 0;
-  prj->conformal = 0;
-  prj->global    = 1;
-  prj->divergent = 0;
-
-  if (prj->r0 == 0.0) {
-    prj->r0 = R2D;
-    prj->w[0] = 1.0;
-    prj->w[1] = 1.0;
-    prj->w[2] = 360.0/PI;
-  } else {
-    prj->w[0] = prj->r0*D2R;
-    prj->w[1] = 1.0/prj->w[0];
-    prj->w[2] = 2.0*prj->r0;
-  }
-
-  prj->prjx2s = pcox2s;
-  prj->prjs2x = pcos2x;
-
-  return prjoff(prj, 0.0, 0.0);
-}
-
-/*--------------------------------------------------------------------------*/
-
-int pcox2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)
-
-struct prjprm *prj;
-int nx, ny, sxy, spt;
-const double x[], y[];
-double phi[], theta[];
-int stat[];
-
-{
-  int mx, my, rowlen, rowoff, status;
-  double f, fneg, fpos, lambda, tanthe, the, theneg, thepos, w, x1, xj, xx,
-         yj, ymthe, y1;
-  const double tol = 1.0e-12;
-  register int ix, iy, k, *statp;
-  register const double *xp, *yp;
-  register double *phip, *thetap;
-
-
-  /* Initialize. */
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-  if (prj->flag != PCO) {
-    if ((status = pcoset(prj))) return status;
-  }
-
-  if (ny > 0) {
-    mx = nx;
-    my = ny;
-  } else {
-    mx = 1;
-    my = 1;
-    ny = nx;
-  }
-
-
-  /* Do x dependence. */
-  xp = x;
-  rowoff = 0;
-  rowlen = nx*spt;
-  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
-    xj = *xp + prj->x0;
-
-    phip = phi + rowoff;
-    for (iy = 0; iy < my; iy++) {
-      *phip = xj;
-      phip += rowlen;
-    }
-  }
-
-
-  /* Do y dependence. */
-  yp = y;
-  phip   = phi;
-  thetap = theta;
-  statp  = stat;
-  for (iy = 0; iy < ny; iy++, yp += sxy) {
-    yj = *yp + prj->y0;
-    w  = fabs(yj*prj->w[1]);
-
-    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
-      xj = *phip;
-
-      if (w < tol) {
-        *phip = xj*prj->w[1];
-        *thetap = 0.0;
-
-      } else if (fabs(w-90.0) < tol) {
-        *phip = 0.0;
-        *thetap = copysign(90.0, yj);
-
-      } else {
-        /* Iterative solution using weighted division of the interval. */
-        if (yj > 0.0) {
-          thepos =  90.0;
-        } else {
-          thepos = -90.0;
-        }
-        theneg = 0.0;
-
-        xx = xj*xj;
-        ymthe = yj - prj->w[0]*thepos;
-        fpos = xx + ymthe*ymthe;
-        fneg = -999.0;
-
-        for (k = 0; k < 64; k++) {
-          if (fneg < -100.0) {
-            /* Equal division of the interval. */
-            the = (thepos+theneg)/2.0;
-          } else {
-            /* Weighted division of the interval. */
-            lambda = fpos/(fpos-fneg);
-            if (lambda < 0.1) {
-              lambda = 0.1;
-            } else if (lambda > 0.9) {
-              lambda = 0.9;
-            }
-            the = thepos - lambda*(thepos-theneg);
-          }
-
-          /* Compute the residue. */
-          ymthe = yj - prj->w[0]*(the);
-          tanthe = tand(the);
-          f = xx + ymthe*(ymthe - prj->w[2]/tanthe);
-
-          /* Check for convergence. */
-          if (fabs(f) < tol) break;
-          if (fabs(thepos-theneg) < tol) break;
-
-          /* Redefine the interval. */
-          if (f > 0.0) {
-            thepos = the;
-            fpos = f;
-          } else {
-            theneg = the;
-            fneg = f;
-          }
-        }
-
-        x1 = prj->r0 - ymthe*tanthe;
-        y1 = xj*tanthe;
-        if (x1 == 0.0 && y1 == 0.0) {
-          *phip = 0.0;
-        } else {
-          *phip = atan2d(y1, x1)/sind(the);
-        }
-
-        *thetap = the;
-      }
-
-      *(statp++) = 0;
-    }
-  }
-
-  return 0;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int pcos2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)
-
-struct prjprm *prj;
-int nphi, ntheta, spt, sxy;
-const double phi[], theta[];
-double x[], y[];
-int stat[];
-
-{
-  int mphi, mtheta, rowlen, rowoff, status;
-  double alpha, costhe, cotthe, sinthe, therad;
-  register int iphi, itheta, *statp;
-  register const double *phip, *thetap;
-  register double *xp, *yp;
-
-  /* Initialize. */
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-  if (prj->flag != PCO) {
-    if ((status = pcoset(prj))) return status;
-  }
-
-  if (ntheta > 0) {
-    mphi   = nphi;
-    mtheta = ntheta;
-  } else {
-    mphi   = 1;
-    mtheta = 1;
-    ntheta = nphi;
-  }
-
-
-  /* Do phi dependence. */
-  phip = phi;
-  rowoff = 0;
-  rowlen = nphi*sxy;
-  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
-    xp = x + rowoff;
-    for (itheta = 0; itheta < mtheta; itheta++) {
-      *xp = *phip;
-      xp += rowlen;
-    }
-  }
-
-
-  /* Do theta dependence. */
-  thetap = theta;
-  xp = x;
-  yp = y;
-  statp = stat;
-  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
-    therad = (*thetap)*D2R;
-    sincosd(*thetap, &sinthe, &costhe);
-
-    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
-      if (sinthe == 0.0) {
-        *xp =  prj->w[0]*(*xp) - prj->x0;
-        *yp = -prj->y0;
-      } else {
-        alpha  = (*xp)*sinthe;
-        cotthe = costhe/sinthe;
-        *xp = prj->r0*cotthe*sind(alpha) - prj->x0;
-        *yp = prj->r0*(cotthe*(1.0 - cosd(alpha)) + therad) - prj->y0;
-      }
-
-      *(statp++) = 0;
-    }
-  }
-
-  return 0;
-}
-
-/*============================================================================
-*   TSC: tangential spherical cube projection.
-*
-*   Given and/or returned:
-*      prj->r0      Reset to 180/pi if 0.
-*      prj->phi0    Reset to 0.0 if undefined.
-*      prj->theta0  Reset to 0.0 if undefined.
-*
-*   Returned:
-*      prj->flag     TSC
-*      prj->code    "TSC"
-*      prj->x0      Fiducial offset in x.
-*      prj->y0      Fiducial offset in y.
-*      prj->w[0]    r0*(pi/4)
-*      prj->w[1]    (4/pi)/r0
-*      prj->prjx2s  Pointer to tscx2s().
-*      prj->prjs2x  Pointer to tscs2x().
-*===========================================================================*/
-
-int tscset(prj)
-
-struct prjprm *prj;
-
-{
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-
-  prj->flag = TSC;
-  strcpy(prj->code, "TSC");
-
-  strcpy(prj->name, "tangential spherical cube");
-  prj->category  = QUADCUBE;
-  prj->pvrange   = 0;
-  prj->simplezen = 0;
-  prj->equiareal = 0;
-  prj->conformal = 0;
-  prj->global    = 1;
-  prj->divergent = 0;
-
-  if (prj->r0 == 0.0) {
-    prj->r0 = R2D;
-    prj->w[0] = 45.0;
-    prj->w[1] = 1.0/45.0;
-  } else {
-    prj->w[0] = prj->r0*PI/4.0;
-    prj->w[1] = 1.0/prj->w[0];
-  }
-
-  prj->prjx2s = tscx2s;
-  prj->prjs2x = tscs2x;
-
-  return prjoff(prj, 0.0, 0.0);
-}
-
-/*--------------------------------------------------------------------------*/
-
-int tscx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)
-
-struct prjprm *prj;
-int nx, ny, sxy, spt;
-const double x[], y[];
-double phi[], theta[];
-int stat[];
-
-{
-  int mx, my, rowlen, rowoff, status;
-  double l, m, n, xf, yf;
-  register int ix, iy, *statp;
-  register const double *xp, *yp;
-  register double *phip, *thetap;
-
-
-  /* Initialize. */
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-  if (prj->flag != TSC) {
-    if ((status = tscset(prj))) return status;
-  }
-
-  if (ny > 0) {
-    mx = nx;
-    my = ny;
-  } else {
-    mx = 1;
-    my = 1;
-    ny = nx;
-  }
-
-  status = 0;
-
-
-  /* Do x dependence. */
-  xp = x;
-  rowoff = 0;
-  rowlen = nx*spt;
-  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
-    xf = (*xp + prj->x0)*prj->w[1];
-
-    phip = phi + rowoff;
-    for (iy = 0; iy < my; iy++) {
-      *phip = xf;
-      phip += rowlen;
-    }
-  }
-
-
-  /* Do y dependence. */
-  yp = y;
-  phip   = phi;
-  thetap = theta;
-  statp  = stat;
-  for (iy = 0; iy < ny; iy++, yp += sxy) {
-    yf = (*yp + prj->y0)*prj->w[1];
-
-    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
-      xf = *phip;
-
-      /* Check bounds. */
-      if (fabs(xf) <= 1.0) {
-        if (fabs(yf) > 3.0) {
-          *phip = 0.0;
-          *thetap = 0.0;
-          *(statp++) = 1;
-          if (!status) status = PRJERR_BAD_PIX_SET("tscx2s");
-          continue;
-        }
-      } else {
-        if (fabs(xf) > 7.0 || fabs(yf) > 1.0) {
-          *phip = 0.0;
-          *thetap = 0.0;
-          *(statp++) = 1;
-          if (!status) status = PRJERR_BAD_PIX_SET("tscx2s");
-          continue;
-        }
-      }
-
-      /* Map negative faces to the other side. */
-      if (xf < -1.0) xf += 8.0;
-
-      /* Determine the face. */
-      if (xf > 5.0) {
-        /* face = 4 */
-        xf = xf - 6.0;
-        m  = -1.0/sqrt(1.0 + xf*xf + yf*yf);
-        l  = -m*xf;
-        n  = -m*yf;
-      } else if (xf > 3.0) {
-        /* face = 3 */
-        xf = xf - 4.0;
-        l  = -1.0/sqrt(1.0 + xf*xf + yf*yf);
-        m  =  l*xf;
-        n  = -l*yf;
-      } else if (xf > 1.0) {
-        /* face = 2 */
-        xf = xf - 2.0;
-        m  =  1.0/sqrt(1.0 + xf*xf + yf*yf);
-        l  = -m*xf;
-        n  =  m*yf;
-      } else if (yf > 1.0) {
-        /* face = 0 */
-        yf = yf - 2.0;
-        n  = 1.0/sqrt(1.0 + xf*xf + yf*yf);
-        l  = -n*yf;
-        m  =  n*xf;
-      } else if (yf < -1.0) {
-        /* face = 5 */
-        yf = yf + 2.0;
-        n  = -1.0/sqrt(1.0 + xf*xf + yf*yf);
-        l  = -n*yf;
-        m  = -n*xf;
-      } else {
-        /* face = 1 */
-        l  =  1.0/sqrt(1.0 + xf*xf + yf*yf);
-        m  =  l*xf;
-        n  =  l*yf;
-      }
-
-      if (l == 0.0 && m == 0.0) {
-        *phip = 0.0;
-      } else {
-        *phip = atan2d(m, l);
-      }
-
-      *thetap = asind(n);
-      *(statp++) = 0;
-    }
-  }
-
-  return status;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int tscs2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)
-
-struct prjprm *prj;
-int nphi, ntheta, spt, sxy;
-const double phi[], theta[];
-double x[], y[];
-int stat[];
-
-{
-  int face, mphi, mtheta, rowlen, rowoff, status;
-  double cosphi, costhe, l, m, n, sinphi, sinthe, x0, xf, y0, yf, zeta;
-  const double tol = 1.0e-12;
-  register int iphi, istat, itheta, *statp;
-  register const double *phip, *thetap;
-  register double *xp, *yp;
-
-  /* Initialize. */
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-  if (prj->flag != TSC) {
-    if ((status = tscset(prj))) return status;
-  }
-
-  if (ntheta > 0) {
-    mphi   = nphi;
-    mtheta = ntheta;
-  } else {
-    mphi   = 1;
-    mtheta = 1;
-    ntheta = nphi;
-  }
-
-  status = 0;
-
-
-  /* Do phi dependence. */
-  phip = phi;
-  rowoff = 0;
-  rowlen = nphi*sxy;
-  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
-    sincosd(*phip, &sinphi, &cosphi);
-
-    xp = x + rowoff;
-    yp = y + rowoff;
-    for (itheta = 0; itheta < mtheta; itheta++) {
-      *xp = cosphi;
-      *yp = sinphi;
-      xp += rowlen;
-      yp += rowlen;
-    }
-  }
-
-
-  /* Do theta dependence. */
-  thetap = theta;
-  xp = x;
-  yp = y;
-  statp = stat;
-  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
-    sincosd(*thetap, &sinthe, &costhe);
-
-    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
-      l = costhe*(*xp);
-      m = costhe*(*yp);
-      n = sinthe;
-
-      face = 0;
-      zeta = n;
-      if (l > zeta) {
-        face = 1;
-        zeta = l;
-      }
-      if (m > zeta) {
-        face = 2;
-        zeta = m;
-      }
-      if (-l > zeta) {
-        face = 3;
-        zeta = -l;
-      }
-      if (-m > zeta) {
-        face = 4;
-        zeta = -m;
-      }
-      if (-n > zeta) {
-        face = 5;
-        zeta = -n;
-      }
-
-      switch (face) {
-      case 1:
-        xf =  m/zeta;
-        yf =  n/zeta;
-        x0 =  0.0;
-        y0 =  0.0;
-        break;
-      case 2:
-        xf = -l/zeta;
-        yf =  n/zeta;
-        x0 =  2.0;
-        y0 =  0.0;
-        break;
-      case 3:
-        xf = -m/zeta;
-        yf =  n/zeta;
-        x0 =  4.0;
-        y0 =  0.0;
-        break;
-      case 4:
-        xf =  l/zeta;
-        yf =  n/zeta;
-        x0 =  6.0;
-        y0 =  0.0;
-        break;
-      case 5:
-        xf =  m/zeta;
-        yf =  l/zeta;
-        x0 =  0.0;
-        y0 = -2.0;
-        break;
-      default:
-        /* face == 0 */
-        xf =  m/zeta;
-        yf = -l/zeta;
-        x0 =  0.0;
-        y0 =  2.0;
-        break;
-      }
-
-      istat = 0;
-      if (fabs(xf) > 1.0) {
-        if (fabs(xf) > 1.0+tol) {
-          istat  = 1;
-          if (!status) status = PRJERR_BAD_WORLD_SET("tscs2x");
-        }
-        xf = copysign(1.0, xf);
-      }
-      if (fabs(yf) > 1.0) {
-        if (fabs(yf) > 1.0+tol) {
-          istat  = 1;
-          if (!status) status = PRJERR_BAD_WORLD_SET("tscs2x");
-        }
-        yf = copysign(1.0, yf);
-      }
-
-      *xp = prj->w[0]*(xf + x0) - prj->x0;
-      *yp = prj->w[0]*(yf + y0) - prj->y0;
-      *(statp++) = istat;
-    }
-  }
-
-  return status;
-}
-
-/*============================================================================
-*   CSC: COBE quadrilateralized spherical cube projection.
-*
-*   Given and/or returned:
-*      prj->r0      Reset to 180/pi if 0.
-*      prj->phi0    Reset to 0.0 if undefined.
-*      prj->theta0  Reset to 0.0 if undefined.
-*
-*   Returned:
-*      prj->flag     CSC
-*      prj->code    "CSC"
-*      prj->x0      Fiducial offset in x.
-*      prj->y0      Fiducial offset in y.
-*      prj->w[0]    r0*(pi/4)
-*      prj->w[1]    (4/pi)/r0
-*      prj->prjx2s  Pointer to cscx2s().
-*      prj->prjs2x  Pointer to cscs2x().
-*===========================================================================*/
-
-int cscset(prj)
-
-struct prjprm *prj;
-
-{
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-
-  prj->flag = CSC;
-  strcpy(prj->code, "CSC");
-
-  strcpy(prj->name, "COBE quadrilateralized spherical cube");
-  prj->category  = QUADCUBE;
-  prj->pvrange   = 0;
-  prj->simplezen = 0;
-  prj->equiareal = 0;
-  prj->conformal = 0;
-  prj->global    = 1;
-  prj->divergent = 0;
-
-  if (prj->r0 == 0.0) {
-    prj->r0 = R2D;
-    prj->w[0] = 45.0;
-    prj->w[1] = 1.0/45.0;
-  } else {
-    prj->w[0] = prj->r0*PI/4.0;
-    prj->w[1] = 1.0/prj->w[0];
-  }
-
-  prj->prjx2s = cscx2s;
-  prj->prjs2x = cscs2x;
-
-  return prjoff(prj, 0.0, 0.0);
-}
-
-/*--------------------------------------------------------------------------*/
-
-int cscx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)
-
-struct prjprm *prj;
-int nx, ny, sxy, spt;
-const double x[], y[];
-double phi[], theta[];
-int stat[];
-
-{
-  int face, mx, my, rowlen, rowoff, status;
-  double l, m, n;
-  register int ix, iy, *statp;
-  register const double *xp, *yp;
-  register double *phip, *thetap;
-
-  float     chi, psi, xf, xx, yf, yy, z0, z1, z2, z3, z4, z5, z6;
-  const float p00 = -0.27292696f;
-  const float p10 = -0.07629969f;
-  const float p20 = -0.22797056f;
-  const float p30 =  0.54852384f;
-  const float p40 = -0.62930065f;
-  const float p50 =  0.25795794f;
-  const float p60 =  0.02584375f;
-  const float p01 = -0.02819452f;
-  const float p11 = -0.01471565f;
-  const float p21 =  0.48051509f;
-  const float p31 = -1.74114454f;
-  const float p41 =  1.71547508f;
-  const float p51 = -0.53022337f;
-  const float p02 =  0.27058160f;
-  const float p12 = -0.56800938f;
-  const float p22 =  0.30803317f;
-  const float p32 =  0.98938102f;
-  const float p42 = -0.83180469f;
-  const float p03 = -0.60441560f;
-  const float p13 =  1.50880086f;
-  const float p23 = -0.93678576f;
-  const float p33 =  0.08693841f;
-  const float p04 =  0.93412077f;
-  const float p14 = -1.41601920f;
-  const float p24 =  0.33887446f;
-  const float p05 = -0.63915306f;
-  const float p15 =  0.52032238f;
-  const float p06 =  0.14381585f;
-
-  /* Initialize. */
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-  if (prj->flag != CSC) {
-    if ((status = cscset(prj))) return status;
-  }
-
-  if (ny > 0) {
-    mx = nx;
-    my = ny;
-  } else {
-    mx = 1;
-    my = 1;
-    ny = nx;
-  }
-
-  status = 0;
-
-
-  /* Do x dependence. */
-  xp = x;
-  rowoff = 0;
-  rowlen = nx*spt;
-  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
-    xf = (float)((*xp + prj->x0)*prj->w[1]);
-
-    phip = phi + rowoff;
-    for (iy = 0; iy < my; iy++) {
-      *phip = xf;
-      phip += rowlen;
-    }
-  }
-
-
-  /* Do y dependence. */
-  yp = y;
-  phip   = phi;
-  thetap = theta;
-  statp  = stat;
-  for (iy = 0; iy < ny; iy++, yp += sxy) {
-    yf = (float)((*yp + prj->y0)*prj->w[1]);
-
-    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
-      xf = (float)*phip;
-
-      /* Check bounds. */
-      if (fabs(xf) <= 1.0) {
-        if (fabs(yf) > 3.0) {
-          *phip = 0.0;
-          *thetap = 0.0;
-          *(statp++) = 1;
-          if (!status) status = PRJERR_BAD_PIX_SET("cscx2s");
-          continue;
-        }
-      } else {
-        if (fabs(xf) > 7.0 || fabs(yf) > 1.0) {
-          *phip = 0.0;
-          *thetap = 0.0;
-          *(statp++) = 1;
-          if (!status) status = PRJERR_BAD_PIX_SET("cscx2s");
-          continue;
-        }
-      }
-
-      /* Map negative faces to the other side. */
-      if (xf < -1.0f) xf += 8.0f;
-
-      /* Determine the face. */
-      if (xf > 5.0f) {
-        face = 4;
-        xf = xf - 6.0f;
-      } else if (xf > 3.0f) {
-        face = 3;
-        xf = xf - 4.0f;
-      } else if (xf > 1.0f) {
-        face = 2;
-        xf = xf - 2.0f;
-      } else if (yf > 1.0f) {
-        face = 0;
-        yf = yf - 2.0f;
-      } else if (yf < -1.0f) {
-        face = 5;
-        yf = yf + 2.0f;
-      } else {
-        face = 1;
-      }
-
-      xx  =  xf*xf;
-      yy  =  yf*yf;
-
-      z0 = p00 + xx*(p10 + xx*(p20 + xx*(p30 + xx*(p40 + xx*(p50 +
-                 xx*(p60))))));
-      z1 = p01 + xx*(p11 + xx*(p21 + xx*(p31 + xx*(p41 + xx*(p51)))));
-      z2 = p02 + xx*(p12 + xx*(p22 + xx*(p32 + xx*(p42))));
-      z3 = p03 + xx*(p13 + xx*(p23 + xx*(p33)));
-      z4 = p04 + xx*(p14 + xx*(p24));
-      z5 = p05 + xx*(p15);
-      z6 = p06;
-
-      chi = z0 + yy*(z1 + yy*(z2 + yy*(z3 + yy*(z4 + yy*(z5 + yy*z6)))));
-      chi = xf + xf*(1.0f - xx)*chi;
-
-      z0 = p00 + yy*(p10 + yy*(p20 + yy*(p30 + yy*(p40 + yy*(p50 +
-                 yy*(p60))))));
-      z1 = p01 + yy*(p11 + yy*(p21 + yy*(p31 + yy*(p41 + yy*(p51)))));
-      z2 = p02 + yy*(p12 + yy*(p22 + yy*(p32 + yy*(p42))));
-      z3 = p03 + yy*(p13 + yy*(p23 + yy*(p33)));
-      z4 = p04 + yy*(p14 + yy*(p24));
-      z5 = p05 + yy*(p15);
-      z6 = p06;
-
-      psi = z0 + xx*(z1 + xx*(z2 + xx*(z3 + xx*(z4 + xx*(z5 + xx*z6)))));
-      psi = yf + yf*(1.0f - yy)*psi;
-
-      switch (face) {
-      case 1:
-        l =  1.0/sqrt(chi*chi + psi*psi + 1.0);
-        m =  chi*l;
-        n =  psi*l;
-        break;
-      case 2:
-        m =  1.0/sqrt(chi*chi + psi*psi + 1.0);
-        l = -chi*m;
-        n =  psi*m;
-        break;
-      case 3:
-        l = -1.0/sqrt(chi*chi + psi*psi + 1.0);
-        m =  chi*l;
-        n = -psi*l;
-        break;
-      case 4:
-        m = -1.0/sqrt(chi*chi + psi*psi + 1.0);
-        l = -chi*m;
-        n = -psi*m;
-        break;
-      case 5:
-        n = -1.0/sqrt(chi*chi + psi*psi + 1.0);
-        l = -psi*n;
-        m = -chi*n;
-        break;
-      default:
-        /* face == 0 */
-        n =  1.0/sqrt(chi*chi + psi*psi + 1.0);
-        l = -psi*n;
-        m =  chi*n;
-        break;
-      }
-
-      if (l == 0.0 && m == 0.0) {
-        *phip = 0.0;
-      } else {
-        *phip = atan2d(m, l);
-      }
-
-      *thetap = asind(n);
-      *(statp++) = 0;
-    }
-  }
-
-  return status;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int cscs2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)
-
-struct prjprm *prj;
-int nphi, ntheta, spt, sxy;
-const double phi[], theta[];
-double x[], y[];
-int stat[];
-
-{
-  int face, mphi, mtheta, rowlen, rowoff, status;
-  double cosphi, costhe, eta, l, m, n, sinphi, sinthe, xi, zeta;
-  const float tol = 1.0e-7f;
-  register int iphi, istat, itheta, *statp;
-  register const double *phip, *thetap;
-  register double *xp, *yp;
-
-  float chi, chi2, chi2psi2, chi4, chipsi, psi, psi2, psi4, chi2co, psi2co,
-        x0, xf, y0, yf;
-  const float gstar  =  1.37484847732f;
-  const float mm     =  0.004869491981f;
-  const float gamma  = -0.13161671474f;
-  const float omega1 = -0.159596235474f;
-  const float d0  =  0.0759196200467f;
-  const float d1  = -0.0217762490699f;
-  const float c00 =  0.141189631152f;
-  const float c10 =  0.0809701286525f;
-  const float c01 = -0.281528535557f;
-  const float c11 =  0.15384112876f;
-  const float c20 = -0.178251207466f;
-  const float c02 =  0.106959469314f;
-
-
-  /* Initialize. */
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-  if (prj->flag != CSC) {
-    if ((status = cscset(prj))) return status;
-  }
-
-  if (ntheta > 0) {
-    mphi   = nphi;
-    mtheta = ntheta;
-  } else {
-    mphi   = 1;
-    mtheta = 1;
-    ntheta = nphi;
-  }
-
-  status = 0;
-
-
-  /* Do phi dependence. */
-  phip = phi;
-  rowoff = 0;
-  rowlen = nphi*sxy;
-  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
-    sincosd(*phip, &sinphi, &cosphi);
-
-    xp = x + rowoff;
-    yp = y + rowoff;
-    for (itheta = 0; itheta < mtheta; itheta++) {
-      *xp = cosphi;
-      *yp = sinphi;
-      xp += rowlen;
-      yp += rowlen;
-    }
-  }
-
-
-  /* Do theta dependence. */
-  thetap = theta;
-  xp = x;
-  yp = y;
-  statp = stat;
-  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
-    sincosd(*thetap, &sinthe, &costhe);
-
-    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
-      l = costhe*(*xp);
-      m = costhe*(*yp);
-      n = sinthe;
-
-      face = 0;
-      zeta = n;
-      if (l > zeta) {
-        face = 1;
-        zeta = l;
-      }
-      if (m > zeta) {
-        face = 2;
-        zeta = m;
-      }
-      if (-l > zeta) {
-        face = 3;
-        zeta = -l;
-      }
-      if (-m > zeta) {
-        face = 4;
-        zeta = -m;
-      }
-      if (-n > zeta) {
-        face = 5;
-        zeta = -n;
-      }
-
-      switch (face) {
-      case 1:
-        xi  =  m;
-        eta =  n;
-        x0  =  0.0;
-        y0  =  0.0;
-        break;
-      case 2:
-        xi  = -l;
-        eta =  n;
-        x0  =  2.0;
-        y0  =  0.0;
-        break;
-      case 3:
-        xi  = -m;
-        eta =  n;
-        x0  =  4.0;
-        y0  =  0.0;
-        break;
-      case 4:
-        xi  =  l;
-        eta =  n;
-        x0  =  6.0;
-        y0  =  0.0;
-        break;
-      case 5:
-        xi  =  m;
-        eta =  l;
-        x0  =  0.0;
-        y0  = -2.0;
-        break;
-      default:
-        /* face == 0 */
-        xi  =  m;
-        eta = -l;
-        x0  =  0.0;
-        y0  =  2.0;
-        break;
-      }
-
-      chi = (float)(xi/zeta);
-      psi = (float)(eta/zeta);
-
-      chi2 = chi*chi;
-      psi2 = psi*psi;
-      chi2co = 1.0f - chi2;
-      psi2co = 1.0f - psi2;
-
-      /* Avoid floating underflows. */
-      chipsi = fabsf(chi*psi);
-      chi4   = (chi2 > 1.0e-16f) ? chi2*chi2 : 0.0f;
-      psi4   = (psi2 > 1.0e-16f) ? psi2*psi2 : 0.0f;
-      chi2psi2 = (chipsi > 1.0e-16f) ? chi2*psi2 : 0.0f;
-
-      xf = chi*(chi2 + chi2co*(gstar + psi2*(gamma*chi2co + mm*chi2 +
-                psi2co*(c00 + c10*chi2 + c01*psi2 + c11*chi2psi2 + c20*chi4 +
-                c02*psi4)) + chi2*(omega1 - chi2co*(d0 + d1*chi2))));
-      yf = psi*(psi2 + psi2co*(gstar + chi2*(gamma*psi2co + mm*psi2 +
-                chi2co*(c00 + c10*psi2 + c01*chi2 + c11*chi2psi2 + c20*psi4 +
-                c02*chi4)) + psi2*(omega1 - psi2co*(d0 + d1*psi2))));
-
-      istat = 0;
-      if (fabs(xf) > 1.0) {
-        if (fabs(xf) > 1.0+tol) {
-          istat  = 1;
-          if (!status) status = PRJERR_BAD_WORLD_SET("cscs2x");
-        }
-        #ifndef _MSC_VER
-        xf = copysignf(1.0f, xf);
-        #else
-        xf = (float)copysign(1.0, (double)xf);
-        #endif
-      }
-      if (fabs(yf) > 1.0) {
-        if (fabs(yf) > 1.0+tol) {
-          istat  = 1;
-          if (!status) status = PRJERR_BAD_WORLD_SET("cscs2x");
-        }
-        #ifndef _MSC_VER
-        yf = copysignf(1.0f, yf);
-        #else
-        yf = (float)copysign(1.0, (double)yf);
-        #endif
-      }
-
-      *xp = prj->w[0]*(xf + x0) - prj->x0;
-      *yp = prj->w[0]*(yf + y0) - prj->y0;
-      *(statp++) = istat;
-    }
-  }
-
-  return status;
-}
-
-/*============================================================================
-*   QSC: quadrilaterilized spherical cube projection.
-*
-*   Given and/or returned:
-*      prj->r0      Reset to 180/pi if 0.
-*      prj->phi0    Reset to 0.0 if undefined.
-*      prj->theta0  Reset to 0.0 if undefined.
-*
-*   Returned:
-*      prj->flag     QSC
-*      prj->code    "QSC"
-*      prj->x0      Fiducial offset in x.
-*      prj->y0      Fiducial offset in y.
-*      prj->w[0]    r0*(pi/4)
-*      prj->w[1]    (4/pi)/r0
-*      prj->prjx2s  Pointer to qscx2s().
-*      prj->prjs2x  Pointer to qscs2x().
-*===========================================================================*/
-
-int qscset(prj)
-
-struct prjprm *prj;
-
-{
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-
-  prj->flag = QSC;
-  strcpy(prj->code, "QSC");
-
-  strcpy(prj->name, "quadrilateralized spherical cube");
-  prj->category  = QUADCUBE;
-  prj->pvrange   = 0;
-  prj->simplezen = 0;
-  prj->equiareal = 1;
-  prj->conformal = 0;
-  prj->global    = 1;
-  prj->divergent = 0;
-
-  if (prj->r0 == 0.0) {
-    prj->r0 = R2D;
-    prj->w[0] = 45.0;
-    prj->w[1] = 1.0/45.0;
-  } else {
-    prj->w[0] = prj->r0*PI/4.0;
-    prj->w[1] = 1.0/prj->w[0];
-  }
-
-  prj->prjx2s = qscx2s;
-  prj->prjs2x = qscs2x;
-
-  return prjoff(prj, 0.0, 0.0);
-}
-
-/*--------------------------------------------------------------------------*/
-
-int qscx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)
-
-struct prjprm *prj;
-int nx, ny, sxy, spt;
-const double x[], y[];
-double phi[], theta[];
-int stat[];
-
-{
-  int direct, face, mx, my, rowlen, rowoff, status;
-  double cosw, l, m, n, omega, sinw, tau, xf, yf, w, zeco, zeta;
-  const double tol = 1.0e-12;
-  register int ix, iy, *statp;
-  register const double *xp, *yp;
-  register double *phip, *thetap;
-
-
-  /* Initialize. */
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-  if (prj->flag != QSC) {
-    if ((status = qscset(prj))) return status;
-  }
-
-  if (ny > 0) {
-    mx = nx;
-    my = ny;
-  } else {
-    mx = 1;
-    my = 1;
-    ny = nx;
-  }
-
-  status = 0;
-
-
-  /* Do x dependence. */
-  xp = x;
-  rowoff = 0;
-  rowlen = nx*spt;
-  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
-    xf = (*xp + prj->x0)*prj->w[1];
-
-    phip = phi + rowoff;
-    for (iy = 0; iy < my; iy++) {
-      *phip = xf;
-      phip += rowlen;
-    }
-  }
-
-
-  /* Do y dependence. */
-  yp = y;
-  phip   = phi;
-  thetap = theta;
-  statp  = stat;
-  for (iy = 0; iy < ny; iy++, yp += sxy) {
-    yf = (*yp + prj->y0)*prj->w[1];
-
-    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
-      xf = *phip;
-
-      /* Check bounds. */
-      if (fabs(xf) <= 1.0) {
-        if (fabs(yf) > 3.0) {
-          *phip = 0.0;
-          *thetap = 0.0;
-          *(statp++) = 1;
-          if (!status) status = PRJERR_BAD_PIX_SET("qscx2s");
-          continue;
-        }
-      } else {
-        if (fabs(xf) > 7.0 || fabs(yf) > 1.0) {
-          *phip = 0.0;
-          *thetap = 0.0;
-          *(statp++) = 1;
-          if (!status) status = PRJERR_BAD_PIX_SET("qscx2s");
-          continue;
-        }
-      }
-
-      /* Map negative faces to the other side. */
-      if (xf < -1.0) xf += 8.0;
-
-      /* Determine the face. */
-      if (xf > 5.0) {
-        face = 4;
-        xf -= 6.0;
-      } else if (xf > 3.0) {
-        face = 3;
-        xf -= 4.0;
-      } else if (xf > 1.0) {
-        face = 2;
-        xf -= 2.0;
-      } else if (yf > 1.0) {
-        face = 0;
-        yf -= 2.0;
-      } else if (yf < -1.0) {
-        face = 5;
-        yf += 2.0;
-      } else {
-        face = 1;
-      }
-
-      direct = (fabs(xf) > fabs(yf));
-      if (direct) {
-        if (xf == 0.0) {
-          omega = 0.0;
-          tau  = 1.0;
-          zeta = 1.0;
-          zeco = 0.0;
-        } else {
-          w = 15.0*yf/xf;
-          omega = sind(w)/(cosd(w) - SQRT2INV);
-          tau  = 1.0 + omega*omega;
-          zeco = xf*xf*(1.0 - 1.0/sqrt(1.0 + tau));
-          zeta = 1.0 - zeco;
-        }
-      } else {
-        if (yf == 0.0) {
-          omega = 0.0;
-          tau  = 1.0;
-          zeta = 1.0;
-          zeco = 0.0;
-        } else {
-          w = 15.0*xf/yf;
-          sincosd(w, &sinw, &cosw);
-          omega = sinw/(cosw - SQRT2INV);
-          tau  = 1.0 + omega*omega;
-          zeco = yf*yf*(1.0 - 1.0/sqrt(1.0 + tau));
-          zeta = 1.0 - zeco;
-        }
-      }
-
-      if (zeta < -1.0) {
-        if (zeta < -1.0-tol) {
-          *phip = 0.0;
-          *thetap = 0.0;
-          *(statp++) = 1;
-          if (!status) status = PRJERR_BAD_PIX_SET("qscx2s");
-          continue;
-        }
-
-        zeta = -1.0;
-        zeco =  2.0;
-        w    =  0.0;
-      } else {
-        w = sqrt(zeco*(2.0-zeco)/tau);
-      }
-
-      switch (face) {
-      case 1:
-        l = zeta;
-        if (direct) {
-          m = w;
-          if (xf < 0.0) m = -m;
-          n = m*omega;
-        } else {
-          n = w;
-          if (yf < 0.0) n = -n;
-          m = n*omega;
-        }
-        break;
-      case 2:
-        m = zeta;
-        if (direct) {
-          l = w;
-          if (xf > 0.0) l = -l;
-          n = -l*omega;
-        } else {
-          n = w;
-          if (yf < 0.0) n = -n;
-          l = -n*omega;
-        }
-        break;
-      case 3:
-        l = -zeta;
-        if (direct) {
-          m = w;
-          if (xf > 0.0) m = -m;
-          n = -m*omega;
-        } else {
-          n = w;
-          if (yf < 0.0) n = -n;
-          m = -n*omega;
-        }
-        break;
-      case 4:
-        m = -zeta;
-        if (direct) {
-          l = w;
-          if (xf < 0.0) l = -l;
-          n = l*omega;
-        } else {
-          n = w;
-          if (yf < 0.0) n = -n;
-          l = n*omega;
-        }
-        break;
-      case 5:
-        n = -zeta;
-        if (direct) {
-          m = w;
-          if (xf < 0.0) m = -m;
-          l = m*omega;
-        } else {
-          l = w;
-          if (yf < 0.0) l = -l;
-          m = l*omega;
-        }
-        break;
-      default:
-        /* face == 0 */
-        n = zeta;
-        if (direct) {
-          m = w;
-          if (xf < 0.0) m = -m;
-          l = -m*omega;
-        } else {
-          l = w;
-          if (yf > 0.0) l = -l;
-          m = -l*omega;
-        }
-        break;
-      }
-
-      if (l == 0.0 && m == 0.0) {
-        *phip = 0.0;
-      } else {
-        *phip = atan2d(m, l);
-      }
-
-      *thetap = asind(n);
-      *(statp++) = 0;
-    }
-  }
-
-  return status;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int qscs2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)
-
-struct prjprm *prj;
-int nphi, ntheta, spt, sxy;
-const double phi[], theta[];
-double x[], y[];
-int stat[];
-
-{
-  int face, mphi, mtheta, rowlen, rowoff, status;
-  double cosphi, costhe, eta, l, m, n, omega, p, sinphi, sinthe, t, tau, x0,
-         xf, xi, y0, yf, zeco, zeta;
-  const double tol = 1.0e-12;
-  register int iphi, istat, itheta, *statp;
-  register const double *phip, *thetap;
-  register double *xp, *yp;
-
-
-  /* Initialize. */
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-  if (prj->flag != QSC) {
-    if ((status = qscset(prj))) return status;
-  }
-
-  if (ntheta > 0) {
-    mphi   = nphi;
-    mtheta = ntheta;
-  } else {
-    mphi   = 1;
-    mtheta = 1;
-    ntheta = nphi;
-  }
-
-  status = 0;
-
-
-  /* Do phi dependence. */
-  phip = phi;
-  rowoff = 0;
-  rowlen = nphi*sxy;
-  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
-    sincosd(*phip, &sinphi, &cosphi);
-
-    xp = x + rowoff;
-    yp = y + rowoff;
-    for (itheta = 0; itheta < mtheta; itheta++) {
-      *xp = cosphi;
-      *yp = sinphi;
-      xp += rowlen;
-      yp += rowlen;
-    }
-  }
-
-
-  /* Do theta dependence. */
-  thetap = theta;
-  xp = x;
-  yp = y;
-  statp = stat;
-  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
-    sincosd(*thetap, &sinthe, &costhe);
-
-    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
-      if (fabs(*thetap) == 90.0) {
-        *xp = -prj->x0;
-        *yp = copysign(2.0*prj->w[0], *thetap) - prj->y0;
-        *(statp++) = 0;
-        continue;
-      }
-
-      l = costhe*(*xp);
-      m = costhe*(*yp);
-      n = sinthe;
-
-      face = 0;
-      zeta = n;
-      if (l > zeta) {
-        face = 1;
-        zeta = l;
-      }
-      if (m > zeta) {
-        face = 2;
-        zeta = m;
-      }
-      if (-l > zeta) {
-        face = 3;
-        zeta = -l;
-      }
-      if (-m > zeta) {
-        face = 4;
-        zeta = -m;
-      }
-      if (-n > zeta) {
-        face = 5;
-        zeta = -n;
-      }
-
-      zeco = 1.0 - zeta;
-
-      switch (face) {
-      case 1:
-        xi  = m;
-        eta = n;
-        if (zeco < 1.0e-8) {
-          /* Small angle formula. */
-          t = (*thetap)*D2R;
-          p = atan2(*yp, *xp);
-          zeco = (p*p + t*t)/2.0;
-        }
-        x0 = 0.0;
-        y0 = 0.0;
-        break;
-      case 2:
-        xi  = -l;
-        eta =  n;
-        if (zeco < 1.0e-8) {
-          /* Small angle formula. */
-          t = (*thetap)*D2R;
-          p = atan2(*yp, *xp) - PI/2.0;
-          zeco = (p*p + t*t)/2.0;
-        }
-        x0 = 2.0;
-        y0 = 0.0;
-        break;
-      case 3:
-        xi  = -m;
-        eta =  n;
-        if (zeco < 1.0e-8) {
-          /* Small angle formula. */
-          t = (*thetap)*D2R;
-          p = atan2(*yp, *xp);
-          p -= copysign(PI, p);
-          zeco = (p*p + t*t)/2.0;
-        }
-        x0 = 4.0;
-        y0 = 0.0;
-        break;
-      case 4:
-        xi  = l;
-        eta = n;
-        if (zeco < 1.0e-8) {
-          /* Small angle formula. */
-          t = (*thetap)*D2R;
-          p = atan2(*yp, *xp) + PI/2.0;
-          zeco = (p*p + t*t)/2.0;
-        }
-        x0 = 6;
-        y0 = 0.0;
-        break;
-      case 5:
-        xi  =  m;
-        eta =  l;
-        if (zeco < 1.0e-8) {
-          /* Small angle formula. */
-          t = (*thetap + 90.0)*D2R;
-          zeco = t*t/2.0;
-        }
-        x0 =  0.0;
-        y0 = -2;
-         break;
-      default:
-        /* face == 0 */
-        xi  =  m;
-        eta = -l;
-        if (zeco < 1.0e-8) {
-          /* Small angle formula. */
-          t = (90.0 - *thetap)*D2R;
-          zeco = t*t/2.0;
-        }
-        x0 = 0.0;
-        y0 = 2.0;
-        break;
-      }
-
-      xf = 0.0;
-      yf = 0.0;
-      if (xi != 0.0 || eta != 0.0) {
-        if (-xi > fabs(eta)) {
-          omega = eta/xi;
-          tau = 1.0 + omega*omega;
-          xf  = -sqrt(zeco/(1.0 - 1.0/sqrt(1.0+tau)));
-          yf  = (xf/15.0)*(atand(omega) - asind(omega/sqrt(tau+tau)));
-        } else if (xi > fabs(eta)) {
-          omega = eta/xi;
-          tau = 1.0 + omega*omega;
-          xf  =  sqrt(zeco/(1.0 - 1.0/sqrt(1.0+tau)));
-          yf  = (xf/15.0)*(atand(omega) - asind(omega/sqrt(tau+tau)));
-        } else if (-eta >= fabs(xi)) {
-          omega = xi/eta;
-          tau = 1.0 + omega*omega;
-          yf  = -sqrt(zeco/(1.0 - 1.0/sqrt(1.0+tau)));
-          xf  = (yf/15.0)*(atand(omega) - asind(omega/sqrt(tau+tau)));
-        } else if (eta >= fabs(xi)) {
-          omega = xi/eta;
-          tau = 1.0 + omega*omega;
-          yf  =  sqrt(zeco/(1.0 - 1.0/sqrt(1.0+tau)));
-          xf  = (yf/15.0)*(atand(omega) - asind(omega/sqrt(tau+tau)));
-        }
-      }
-
-      istat = 0;
-      if (fabs(xf) > 1.0) {
-        if (fabs(xf) > 1.0+tol) {
-          istat  = 1;
-          if (!status) status = PRJERR_BAD_WORLD_SET("qscs2x");
-        }
-        xf = copysign(1.0, xf);
-      }
-      if (fabs(yf) > 1.0) {
-        if (fabs(yf) > 1.0+tol) {
-          istat  = 1;
-          if (!status) status = PRJERR_BAD_WORLD_SET("qscs2x");
-        }
-        yf = copysign(1.0, yf);
-      }
-
-      *xp = prj->w[0]*(xf + x0) - prj->x0;
-      *yp = prj->w[0]*(yf + y0) - prj->y0;
-      *(statp++) = istat;
-    }
-  }
-
-  return status;
-}
-
-/*============================================================================
-*   HPX: HEALPix projection.
-*
-*   Given:
-*      prj->pv[1]   H - the number of facets in longitude.
-*      prj->pv[2]   K - the number of facets in latitude
-*
-*   Given and/or returned:
-*      prj->r0      Reset to 180/pi if 0.
-*      prj->phi0    Reset to 0.0 if undefined.
-*      prj->theta0  Reset to 0.0 if undefined.
-*
-*   Returned:
-*      prj->flag     HPX
-*      prj->code    "HPX"
-*      prj->x0      Fiducial offset in x.
-*      prj->y0      Fiducial offset in y.
-*      prj->m       True if H is odd.
-*      prj->n       True if K is odd.
-*      prj->w[0]    r0*(pi/180)
-*      prj->w[1]    (180/pi)/r0
-*      prj->w[2]    (K-1)/K
-*      prj->w[3]    90*K/H
-*      prj->w[4]    (K+1)/2
-*      prj->w[5]    90*(K-1)/H
-*      prj->w[6]    180/H
-*      prj->w[7]    H/360
-*      prj->w[8]    r0*(pi/180)*(90*K/H)
-*      prj->w[9]    r0*(pi/180)*(180/H)
-*      prj->prjx2s  Pointer to hpxx2s().
-*      prj->prjs2x  Pointer to hpxs2x().
-*===========================================================================*/
-
-int hpxset(prj)
-
-struct prjprm *prj;
-
-{
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-
-  prj->flag = HPX;
-  strcpy(prj->code, "HPX");
-
-  if (undefined(prj->pv[1])) prj->pv[1] = 4.0;
-  if (undefined(prj->pv[2])) prj->pv[2] = 3.0;
-
-  strcpy(prj->name, "HEALPix");
-  prj->category  = HEALPIX;
-  prj->pvrange   = 102;
-  prj->simplezen = 0;
-  prj->equiareal = 1;
-  prj->conformal = 0;
-  prj->global    = 1;
-  prj->divergent = 0;
-
-  if (prj->pv[1] <= 0.0 || prj->pv[2] <= 0.0) {
-    return PRJERR_BAD_PARAM_SET("hpxset");
-  }
-
-  prj->m = ((int)(prj->pv[1]+0.5))%2;
-  prj->n = ((int)(prj->pv[2]+0.5))%2;
-
-  if (prj->r0 == 0.0) {
-    prj->r0 = R2D;
-    prj->w[0] = 1.0;
-    prj->w[1] = 1.0;
-  } else {
-    prj->w[0] = prj->r0*D2R;
-    prj->w[1] = R2D/prj->r0;
-  }
-
-  prj->w[2] = (prj->pv[2] - 1.0) / prj->pv[2];
-  prj->w[3] = 90.0 * prj->pv[2] / prj->pv[1];
-  prj->w[4] = (prj->pv[2] + 1.0) / 2.0;
-  prj->w[5] = 90.0 * (prj->pv[2] - 1.0) / prj->pv[1];
-  prj->w[6] = 180.0 / prj->pv[1];
-  prj->w[7] = prj->pv[1] / 360.0;
-  prj->w[8] = prj->w[3] * prj->w[0];
-  prj->w[9] = prj->w[6] * prj->w[0];
-
-  prj->prjx2s = hpxx2s;
-  prj->prjs2x = hpxs2x;
-
-  return prjoff(prj, 0.0, 0.0);
-}
-
-/*--------------------------------------------------------------------------*/
-
-int hpxx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)
-
-struct prjprm *prj;
-int nx, ny, sxy, spt;
-const double x[], y[];
-double phi[], theta[];
-int stat[];
-
-{
-  int h, mx, my, offset, rowlen, rowoff, status;
-  double absy, s, sigma, t, yr;
-  const double slim = prj->w[6] + 1e-12;
-  const double ylim = prj->w[9] * prj->w[4];
-  register int istat, ix, iy, *statp;
-  register const double *xp, *yp;
-  register double *phip, *thetap;
-
-
-  /* Initialize. */
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-  if (prj->flag != HPX) {
-    if ((status = hpxset(prj))) return status;
-  }
-
-  if (ny > 0) {
-    mx = nx;
-    my = ny;
-  } else {
-    mx = 1;
-    my = 1;
-    ny = nx;
-  }
-
-  status = 0;
-
-
-  /* Do x dependence. */
-  xp = x;
-  rowoff = 0;
-  rowlen = nx*spt;
-  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
-    s = prj->w[1] * (*xp + prj->x0);
-    /* x_c for K odd or theta > 0. */
-    t = -180.0 + (2.0 * floor((*xp + 180.0) * prj->w[7]) + 1.0) * prj->w[6];
-    t = prj->w[1] * (*xp - t);
-
-    phip   = phi + rowoff;
-    thetap = theta + rowoff;
-    for (iy = 0; iy < my; iy++) {
-      /* theta[] is used to hold (x - x_c). */
-      *phip   = s;
-      *thetap = t;
-      phip   += rowlen;
-      thetap += rowlen;
-    }
-  }
-
-
-  /* Do y dependence. */
-  yp = y;
-  phip   = phi;
-  thetap = theta;
-  statp  = stat;
-  for (iy = 0; iy < ny; iy++, yp += sxy) {
-    yr = prj->w[1]*(*yp + prj->y0);
-    absy = fabs(yr);
-
-    istat = 0;
-    if (absy <= prj->w[5]) {
-      /* Equatorial regime. */
-      t = asind(yr/prj->w[3]);
-      for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
-        *thetap = t;
-        *(statp++) = 0;
-      }
-
-    } else if (absy <= ylim) {
-      /* Polar regime. */
-      offset = (prj->n || *yp > 0.0) ? 0 : 1;
-
-      sigma = prj->w[4] - absy / prj->w[6];
-
-      if (sigma == 0.0) {
-        s = 1e9;
-        t = 90.0;
-
-      } else {
-        t = 1.0 - sigma*sigma/prj->pv[2];
-        if (t < -1.0) {
-          s = 0.0;
-          t = 0.0;
-          istat  = 1;
-          if (!status) status = PRJERR_BAD_PIX_SET("hpxx2s");
-        } else {
-          s = 1.0/sigma;
-          t = asind(t);
-        }
-      }
-      if (*yp < 0.0) t = -t;
-
-      for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
-        if (offset) {
-          /* Offset the southern polar half-facets for even K. */
-          h = (int)floor(*phip / prj->w[6]) + prj->m;
-          if (h%2) {
-            *thetap -= prj->w[6];
-          } else {
-            *thetap += prj->w[6];
-          }
-        }
-
-        /* Recall that theta[] holds (x - x_c). */
-        s *= *thetap;
-        if (fabs(s) < slim) {
-          if (s != 0.0) s -= *thetap;
-          *phip += s;
-          *thetap = t;
-          *(statp++) = istat;
-        } else {
-          /* Out-of-bounds. */
-          *phip   = 0.0;
-          *thetap = 0.0;
-          *(statp++) = 1;
-          if (!status) status = PRJERR_BAD_PIX_SET("hpxx2s");
-        }
-      }
-
-    } else {
-      /* Beyond latitude range. */
-      for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
-        *phip   = 0.0;
-        *thetap = 0.0;
-        *(statp++) = 1;
-      }
-      if (!status) status = PRJERR_BAD_PIX_SET("hpxx2s");
-    }
-  }
-
-  return status;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int hpxs2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)
-
-struct prjprm *prj;
-int nphi, ntheta, spt, sxy;
-const double phi[], theta[];
-double x[], y[];
-int stat[];
-
-{
-  int h, mphi, mtheta, offset, rowlen, rowoff, status;
-  double abssin, eta, sigma, sinthe, t, xi;
-  register int iphi, itheta, *statp;
-  register const double *phip, *thetap;
-  register double *xp, *yp;
-
-
-  /* Initialize. */
-  if (prj == 0x0) return PRJERR_NULL_POINTER;
-  if (prj->flag != HPX) {
-    if ((status = hpxset(prj))) return status;
-  }
-
-  if (ntheta > 0) {
-    mphi   = nphi;
-    mtheta = ntheta;
-  } else {
-    mphi   = 1;
-    mtheta = 1;
-    ntheta = nphi;
-  }
-
-
-  /* Do phi dependence. */
-  phip = phi;
-  rowoff = 0;
-  rowlen = nphi*sxy;
-  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
-    xi = prj->w[0] * (*phip) - prj->x0;
-
-    /* phi_c for K odd or theta > 0. */
-    t = -180.0 + (2.0*floor((*phip+180.0) * prj->w[7]) + 1.0) * prj->w[6];
-    t = prj->w[0] * (*phip - t);
-
-    xp = x + rowoff;
-    yp = y + rowoff;
-    for (itheta = 0; itheta < mtheta; itheta++) {
-      /* y[] is used to hold (phi - phi_c). */
-      *xp = xi;
-      *yp = t;
-      xp += rowlen;
-      yp += rowlen;
-    }
-  }
-
-
-  /* Do theta dependence. */
-  thetap = theta;
-  xp = x;
-  yp = y;
-  statp = stat;
-  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
-    sinthe = sind(*thetap);
-    abssin = fabs(sinthe);
-
-    if (abssin <= prj->w[2]) {
-      /* Equatorial regime. */
-      eta = prj->w[8] * sinthe - prj->y0;
-      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
-        *yp = eta;
-        *(statp++) = 0;
-      }
-
-    } else {
-      /* Polar regime. */
-      offset = (prj->n || *thetap > 0.0) ? 0 : 1;
-
-      sigma = sqrt(prj->pv[2]*(1.0 - abssin));
-      xi = sigma - 1.0;
-
-      eta = prj->w[9] * (prj->w[4] - sigma);
-      if (*thetap < 0) eta = -eta;
-      eta -= prj->y0;
-
-      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
-        if (offset) {
-          /* Offset the southern polar half-facets for even K. */
-          h = (int)floor((*xp + prj->x0) / prj->w[9]) + prj->m;
-          if (h%2) {
-            *yp -= prj->w[9];
-          } else {
-            *yp += prj->w[9];
-          }
-        }
-
-        /* Recall that y[] holds (phi - phi_c). */
-        *xp += *yp * xi;
-        *yp = eta;
-        *(statp++) = 0;
-
-        /* Put the phi = 180 meridian in the expected place. */
-        if (180.0 < *xp) *xp = 360.0 - *xp;
-      }
-    }
-  }
-
-  return 0;
-}
diff --git a/astropy/wcs/src/wcslib/C/prj.h b/astropy/wcs/src/wcslib/C/prj.h
deleted file mode 100644
index 92e07f2..0000000
--- a/astropy/wcs/src/wcslib/C/prj.h
+++ /dev/null
@@ -1,764 +0,0 @@
-/*============================================================================
-
-  WCSLIB 4.10 - an implementation of the FITS WCS standard.
-  Copyright (C) 1995-2012, Mark Calabretta
-
-  This file is part of WCSLIB.
-
-  WCSLIB is free software: you can redistribute it and/or modify it under the
-  terms of the GNU Lesser General Public License as published by the Free
-  Software Foundation, either version 3 of the License, or (at your option)
-  any later version.
-
-  WCSLIB 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 Lesser General Public License for
-  more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with WCSLIB.  If not, see <http://www.gnu.org/licenses/>.
-
-  Correspondence concerning WCSLIB may be directed to:
-    Internet email: mcalabre at atnf.csiro.au
-    Postal address: Dr. Mark Calabretta
-                    Australia Telescope National Facility, CSIRO
-                    PO Box 76
-                    Epping NSW 1710
-                    AUSTRALIA
-
-  Author: Mark Calabretta, Australia Telescope National Facility
-  http://www.atnf.csiro.au/~mcalabre/index.html
-  $Id: prj.h,v 4.10 2012/02/05 23:41:44 cal103 Exp $
-*=============================================================================
-*
-* WCSLIB 4.10 - C routines that implement the spherical map projections
-* recognized by the FITS World Coordinate System (WCS) standard.  Refer to
-*
-*   "Representations of world coordinates in FITS",
-*   Greisen, E.W., & Calabretta, M.R. 2002, A&A, 395, 1061 (Paper I)
-*
-*   "Representations of celestial coordinates in FITS",
-*   Calabretta, M.R., & Greisen, E.W. 2002, A&A, 395, 1077 (Paper II)
-*
-* Refer to the README file provided with WCSLIB for an overview of the
-* library.
-*
-*
-* Summary of the prj routines
-* ---------------------------
-* These routines implement the spherical map projections defined by the FITS
-* WCS standard.  They are based on the prjprm struct which contains all
-* information needed for the computations.  The struct contains some members
-* that must be set by the user, and others that are maintained by these
-* routines, somewhat like a C++ class but with no encapsulation.
-*
-* Routine prjini() is provided to initialize the prjprm struct with default
-* values, prjfree() reclaims any memory that may have been allocated to store
-* an error message, and prjprt() prints its contents.
-*
-* Setup routines for each projection with names of the form ???set(), where
-* "???" is the down-cased three-letter projection code, compute intermediate
-* values in the prjprm struct from parameters in it that were supplied by the
-* user.  The struct always needs to be set by the projection's setup routine
-* but that need not be called explicitly - refer to the explanation of
-* prjprm::flag.
-*
-* Each map projection is implemented via separate functions for the spherical
-* projection, ???s2x(), and deprojection, ???x2s().
-*
-* A set of driver routines, prjset(), prjx2s(), and prjs2x(), provides a
-* generic interface to the specific projection routines which they invoke
-* via pointers-to-functions stored in the prjprm struct.
-*
-* In summary, the routines are:
-*   - prjini()                Initialization routine for the prjprm struct.
-*   - prjprt()                Routine to print the prjprm struct.
-*
-*   - prjset(), prjx2s(), prjs2x():   Generic driver routines
-*
-*   - azpset(), azpx2s(), azps2x():   AZP (zenithal/azimuthal perspective)
-*   - szpset(), szpx2s(), szps2x():   SZP (slant zenithal perspective)
-*   - tanset(), tanx2s(), tans2x():   TAN (gnomonic)
-*   - stgset(), stgx2s(), stgs2x():   STG (stereographic)
-*   - sinset(), sinx2s(), sins2x():   SIN (orthographic/synthesis)
-*   - arcset(), arcx2s(), arcs2x():   ARC (zenithal/azimuthal equidistant)
-*   - zpnset(), zpnx2s(), zpns2x():   ZPN (zenithal/azimuthal polynomial)
-*   - zeaset(), zeax2s(), zeas2x():   ZEA (zenithal/azimuthal equal area)
-*   - airset(), airx2s(), airs2x():   AIR (Airy)
-*   - cypset(), cypx2s(), cyps2x():   CYP (cylindrical perspective)
-*   - ceaset(), ceax2s(), ceas2x():   CEA (cylindrical equal area)
-*   - carset(), carx2s(), cars2x():   CAR (Plate carree)
-*   - merset(), merx2s(), mers2x():   MER (Mercator)
-*   - sflset(), sflx2s(), sfls2x():   SFL (Sanson-Flamsteed)
-*   - parset(), parx2s(), pars2x():   PAR (parabolic)
-*   - molset(), molx2s(), mols2x():   MOL (Mollweide)
-*   - aitset(), aitx2s(), aits2x():   AIT (Hammer-Aitoff)
-*   - copset(), copx2s(), cops2x():   COP (conic perspective)
-*   - coeset(), coex2s(), coes2x():   COE (conic equal area)
-*   - codset(), codx2s(), cods2x():   COD (conic equidistant)
-*   - cooset(), coox2s(), coos2x():   COO (conic orthomorphic)
-*   - bonset(), bonx2s(), bons2x():   BON (Bonne)
-*   - pcoset(), pcox2s(), pcos2x():   PCO (polyconic)
-*   - tscset(), tscx2s(), tscs2x():   TSC (tangential spherical cube)
-*   - cscset(), cscx2s(), cscs2x():   CSC (COBE spherical cube)
-*   - qscset(), qscx2s(), qscs2x():   QSC (quadrilateralized spherical cube)
-*   - hpxset(), hpxx2s(), hpxs2x():   HPX (HEALPix)
-*
-* Argument checking (projection routines):
-* ----------------------------------------
-* The values of phi and theta (the native longitude and latitude) normally lie
-* in the range [-180,180] for phi, and [-90,90] for theta.  However, all
-* projection routines will accept any value of phi and will not normalize it.
-*
-* The projection routines do not explicitly check that theta lies within the
-* range [-90,90].  They do check for any value of theta that produces an
-* invalid argument to the projection equations (e.g. leading to division by
-* zero).  The projection routines for AZP, SZP, TAN, SIN, ZPN, and COP also
-* return error 2 if (phi,theta) corresponds to the overlapped (far) side of
-* the projection but also return the corresponding value of (x,y).  This
-* strict bounds checking may be relaxed at any time by setting prjprm::bounds
-* to 0 (rather than 1); the projections need not be reinitialized.
-*
-* Argument checking (deprojection routines):
-* ------------------------------------------
-* Error checking on the projected coordinates (x,y) is limited to that
-* required to ascertain whether a solution exists.  Where a solution does
-* exist no check is made that the value of phi and theta obtained lie within
-* the ranges [-180,180] for phi, and [-90,90] for theta.
-*
-* Accuracy:
-* ---------
-* No warranty is given for the accuracy of these routines (refer to the
-* copyright notice); intending users must satisfy for themselves their
-* adequacy for the intended purpose.  However, closure to a precision of at
-* least 1E-10 degree of longitude and latitude has been verified for typical
-* projection parameters on the 1 degree graticule of native longitude and
-* latitude (to within 5 degrees of any latitude where the projection may
-* diverge).  Refer to the tprj1.c and tprj2.c test routines that accompany
-* this software.
-*
-*
-* prjini() - Default constructor for the prjprm struct
-* ----------------------------------------------------
-* prjini() sets all members of a prjprm struct to default values.  It should
-* be used to initialize every prjprm struct.
-*
-* Returned:
-*   prj       struct prjprm*
-*                       Projection parameters.
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         1: Null prjprm pointer passed.
-*
-*
-* prjfree() - Destructor for the prjprm struct
-* --------------------------------------------
-* prjfree() frees any memory that may have been allocated to store an error
-* message in the prjprm struct.
-*
-* Given:
-*   prj       struct prjprm*
-*                       Projection parameters.
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         1: Null prjprm pointer passed.
-*
-*
-* prjprt() - Print routine for the prjprm struct
-* ----------------------------------------------
-* prjprt() prints the contents of a prjprm struct using wcsprintf().  Mainly
-* intended for diagnostic purposes.
-*
-* Given:
-*   prj       const struct prjprm*
-*                       Projection parameters.
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         1: Null prjprm pointer passed.
-*
-*
-* prjset() - Generic setup routine for the prjprm struct
-* ------------------------------------------------------
-* prjset() sets up a prjprm struct according to information supplied within
-* it.
-*
-* Note that this routine need not be called directly; it will be invoked by
-* prjx2s() and prjs2x() if prj.flag is anything other than a predefined magic
-* value.
-*
-* The one important distinction between prjset() and the setup routines for
-* the specific projections is that the projection code must be defined in the
-* prjprm struct in order for prjset() to identify the required projection.
-* Once prjset() has initialized the prjprm struct, prjx2s() and prjs2x() use
-* the pointers to the specific projection and deprojection routines contained
-* therein.
-*
-* Given and returned:
-*   prj       struct prjprm*
-*                       Projection parameters.
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         1: Null prjprm pointer passed.
-*                         2: Invalid projection parameters.
-*
-*                       For returns > 1, a detailed error message is set in
-*                       prjprm::err if enabled, see wcserr_enable().
-*
-*
-* prjx2s() - Generic Cartesian-to-spherical deprojection
-* ------------------------------------------------------
-* Deproject Cartesian (x,y) coordinates in the plane of projection to native
-* spherical coordinates (phi,theta).
-*
-* The projection is that specified by prjprm::code.
-*
-* Given and returned:
-*   prj       struct prjprm*
-*                       Projection parameters.
-*
-* Given:
-*   nx,ny     int       Vector lengths.
-*
-*   sxy,spt   int       Vector strides.
-*
-*   x,y       const double[]
-*                       Projected coordinates.
-*
-* Returned:
-*   phi,theta double[]  Longitude and latitude (phi,theta) of the projected
-*                       point in native spherical coordinates [deg].
-*
-*   stat      int[]     Status return value for each vector element:
-*                         0: Success.
-*                         1: Invalid value of (x,y).
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         1: Null prjprm pointer passed.
-*                         2: Invalid projection parameters.
-*                         3: One or more of the (x,y) coordinates were
-*                            invalid, as indicated by the stat vector.
-*
-*                       For returns > 1, a detailed error message is set in
-*                       prjprm::err if enabled, see wcserr_enable().
-*
-*
-* prjs2x() - Generic spherical-to-Cartesian projection
-* ----------------------------------------------------
-* Project native spherical coordinates (phi,theta) to Cartesian (x,y)
-* coordinates in the plane of projection.
-*
-* The projection is that specified by prjprm::code.
-*
-* Given and returned:
-*   prj       struct prjprm*
-*                       Projection parameters.
-*
-* Given:
-*   nphi,
-*   ntheta    int       Vector lengths.
-*
-*   spt,sxy   int       Vector strides.
-*
-*   phi,theta const double[]
-*                       Longitude and latitude (phi,theta) of the projected
-*                       point in native spherical coordinates [deg].
-*
-* Returned:
-*   x,y       double[]  Projected coordinates.
-*
-*   stat      int[]     Status return value for each vector element:
-*                         0: Success.
-*                         1: Invalid value of (phi,theta).
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         1: Null prjprm pointer passed.
-*                         2: Invalid projection parameters.
-*                         4: One or more of the (phi,theta) coordinates
-*                            were, invalid, as indicated by the stat vector.
-*
-*                       For returns > 1, a detailed error message is set in
-*                       prjprm::err if enabled, see wcserr_enable().
-*
-*
-* ???set() - Specific setup routines for the prjprm struct
-* --------------------------------------------------------
-* Set up a prjprm struct for a particular projection according to information
-* supplied within it.
-*
-* Given and returned:
-*   prj       struct prjprm*
-*                       Projection parameters.
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         1: Null prjprm pointer passed.
-*                         2: Invalid projection parameters.
-*
-*                       For returns > 1, a detailed error message is set in
-*                       prjprm::err if enabled, see wcserr_enable().
-*
-*
-* ???x2s() - Specific Cartesian-to-spherical deprojection routines
-* ----------------------------------------------------------------
-* Transform (x,y) coordinates in the plane of projection to native spherical
-* coordinates (phi,theta).
-*
-* Given and returned:
-*   prj       struct prjprm*
-*                       Projection parameters.
-*
-* Given:
-*   nx,ny     int       Vector lengths.
-*
-*   sxy,spt   int       Vector strides.
-*
-*   x,y       const double[]
-*                       Projected coordinates.
-*
-* Returned:
-*   phi,theta double[]  Longitude and latitude of the projected point in
-*                       native spherical coordinates [deg].
-*
-*   stat      int[]     Status return value for each vector element:
-*                         0: Success.
-*                         1: Invalid value of (x,y).
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         1: Null prjprm pointer passed.
-*                         2: Invalid projection parameters.
-*                         3: One or more of the (x,y) coordinates were
-*                            invalid, as indicated by the stat vector.
-*
-*                       For returns > 1, a detailed error message is set in
-*                       prjprm::err if enabled, see wcserr_enable().
-*
-*
-* ???s2x() - Specific spherical-to-Cartesian projection routines
-*---------------------------------------------------------------
-* Transform native spherical coordinates (phi,theta) to (x,y) coordinates in
-* the plane of projection.
-*
-* Given and returned:
-*   prj       struct prjprm*
-*                       Projection parameters.
-*
-* Given:
-*   nphi,
-*   ntheta    int       Vector lengths.
-*
-*   spt,sxy   int       Vector strides.
-*
-*   phi,theta const double[]
-*                       Longitude and latitude of the projected point in
-*                       native spherical coordinates [deg].
-*
-* Returned:
-*   x,y       double[]  Projected coordinates.
-*
-*   stat      int[]     Status return value for each vector element:
-*                         0: Success.
-*                         1: Invalid value of (phi,theta).
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         1: Null prjprm pointer passed.
-*                         2: Invalid projection parameters.
-*                         4: One or more of the (phi,theta) coordinates
-*                            were, invalid, as indicated by the stat vector.
-*
-*                       For returns > 1, a detailed error message is set in
-*                       prjprm::err if enabled, see wcserr_enable().
-*
-*
-* prjprm struct - Projection parameters
-* -------------------------------------
-* The prjprm struct contains all information needed to project or deproject
-* native spherical coordinates.  It consists of certain members that must be
-* set by the user ("given") and others that are set by the WCSLIB routines
-* ("returned").  Some of the latter are supplied for informational purposes
-* while others are for internal use only.
-*
-*   int flag
-*     (Given and returned) This flag must be set to zero whenever any of the
-*     following prjprm struct members are set or changed:
-*
-*       - prjprm::code,
-*       - prjprm::r0,
-*       - prjprm::pv[],
-*       - prjprm::phi0,
-*       - prjprm::theta0.
-*
-*     This signals the initialization routine (prjset() or ???set()) to
-*     recompute the returned members of the prjprm struct.  flag will then be
-*     reset to indicate that this has been done.
-*
-*     Note that flag need not be reset when prjprm::bounds is changed.
-*
-*   char code[4]
-*     (Given) Three-letter projection code defined by the FITS standard.
-*
-*   double r0
-*     (Given) The radius of the generating sphere for the projection, a linear
-*     scaling parameter.  If this is zero, it will be reset to its default
-*     value of 180/pi (the value for FITS WCS).
-*
-*   double pv[30]
-*     (Given) Projection parameters.  These correspond to the PVi_ma keywords
-*     in FITS, so pv[0] is PVi_0a, pv[1] is PVi_1a, etc., where i denotes the
-*     latitude-like axis.  Many projections use pv[1] (PVi_1a), some also use
-*     pv[2] (PVi_2a) and SZP uses pv[3] (PVi_3a).  ZPN is currently the only
-*     projection that uses any of the others.
-*
-*     Usage of the pv[] array as it applies to each projection is described in
-*     the prologue to each trio of projection routines in prj.c.
-*
-*   double phi0
-*     (Given) The native longitude, phi_0 [deg], and ...
-*   double theta0
-*     (Given) ... the native latitude, theta_0 [deg], of the reference point,
-*     i.e. the point (x,y) = (0,0).  If undefined (set to a magic value by
-*     prjini()) the initialization routine will set this to a
-*     projection-specific default.
-*
-*   int bounds
-*     (Given) Controls strict bounds checking for the AZP, SZP, TAN, SIN, ZPN,
-*     and COP projections; set to zero to disable checking.
-*
-* The remaining members of the prjprm struct are maintained by the setup
-* routines and must not be modified elsewhere:
-*
-*   char name[40]
-*     (Returned) Long name of the projection.
-*
-*     Provided for information only, not used by the projection routines.
-*
-*   int  category
-*     (Returned) Projection category matching the value of the relevant global
-*     variable:
-*
-*     - ZENITHAL,
-*     - CYLINDRICAL,
-*     - PSEUDOCYLINDRICAL,
-*     - CONVENTIONAL,
-*     - CONIC,
-*     - POLYCONIC,
-*     - QUADCUBE, and
-*     - HEALPIX.
-*
-*     The category name may be identified via the prj_categories character
-*     array, e.g.
-*
-=       struct prjprm prj;
-=         ...
-=       printf("%s\n", prj_categories[prj.category]);
-*
-*     Provided for information only, not used by the projection routines.
-*
-*   int  pvrange
-*     (Returned) Range of projection parameter indices: 100 times the first
-*     allowed index plus the number of parameters, e.g. TAN is 0 (no
-*     parameters), SZP is 103 (1 to 3), and ZPN is 30 (0 to 29).
-*
-*     Provided for information only, not used by the projection routines.
-*
-*   int  simplezen
-*     (Returned) True if the projection is a radially-symmetric zenithal
-*     projection.
-*
-*     Provided for information only, not used by the projection routines.
-*
-*   int  equiareal
-*     (Returned) True if the projection is equal area.
-*
-*     Provided for information only, not used by the projection routines.
-*
-*   int  conformal
-*     (Returned) True if the projection is conformal.
-*
-*     Provided for information only, not used by the projection routines.
-*
-*   int  global
-*     (Returned) True if the projection can represent the whole sphere in a
-*     finite, non-overlapped mapping.
-*
-*     Provided for information only, not used by the projection routines.
-*
-*   int  divergent
-*     (Returned) True if the projection diverges in latitude.
-*
-*     Provided for information only, not used by the projection routines.
-*
-*   double x0
-*     (Returned) The offset in x, and ...
-*   double y0
-*     (Returned) ... the offset in y used to force (x,y) = (0,0) at
-*     (phi_0,theta_0).
-*
-*   struct wcserr *err
-*     (Returned) If enabled, when an error status is returned this struct
-*     contains detailed information about the error, see wcserr_enable().
-*
-*   void *padding
-*     (An unused variable inserted for alignment purposes only.)
-*
-*   double w[10]
-*     (Returned) Intermediate floating-point values derived from the
-*     projection parameters, cached here to save recomputation.
-*
-*     Usage of the w[] array as it applies to each projection is described in
-*     the prologue to each trio of projection routines in prj.c.
-*
-*   int n
-*     (Returned) Intermediate integer value (used only for the ZPN and HPX
-*     projections).
-*
-*   int (*prjx2s)(PRJX2S_ARGS)
-*     (Returned) Pointer to the projection ...
-*   int (*prjs2x)(PRJ_ARGS)
-*     (Returned) ... and deprojection routines.
-*
-*
-* Global variable: const char *prj_errmsg[] - Status return messages
-* ------------------------------------------------------------------
-* Error messages to match the status value returned from each function.
-*
-*===========================================================================*/
-
-#ifndef WCSLIB_PROJ
-#define WCSLIB_PROJ
-
-#include "wcserr.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-/* Total number of projection parameters; 0 to PVN-1. */
-#define PVN 30
-
-extern const char *prj_errmsg[];
-
-enum prj_errmsg_enum {
-  PRJERR_SUCCESS      = 0,	/* Success. */
-  PRJERR_NULL_POINTER = 1,	/* Null prjprm pointer passed. */
-  PRJERR_BAD_PARAM    = 2,	/* Invalid projection parameters. */
-  PRJERR_BAD_PIX      = 3,	/* One or more of the (x, y) coordinates were
-				   invalid. */
-  PRJERR_BAD_WORLD    = 4	/* One or more of the (phi, theta) coordinates
-				   were invalid. */
-};
-
-extern const int CONIC, CONVENTIONAL, CYLINDRICAL, POLYCONIC,
-                 PSEUDOCYLINDRICAL, QUADCUBE, ZENITHAL, HEALPIX;
-extern const char prj_categories[9][32];
-
-extern const int  prj_ncode;
-extern const char prj_codes[27][4];
-
-#ifdef PRJX2S_ARGS
-#undef PRJX2S_ARGS
-#endif
-
-#ifdef PRJS2X_ARGS
-#undef PRJS2X_ARGS
-#endif
-
-/* For use in declaring deprojection function prototypes. */
-#define PRJX2S_ARGS struct prjprm *prj, int nx, int ny, int sxy, int spt, \
-const double x[], const double y[], double phi[], double theta[], int stat[]
-
-/* For use in declaring projection function prototypes. */
-#define PRJS2X_ARGS struct prjprm *prj, int nx, int ny, int sxy, int spt, \
-const double phi[], const double theta[], double x[], double y[], int stat[]
-
-
-struct prjprm {
-  /* Initialization flag (see the prologue above).                          */
-  /*------------------------------------------------------------------------*/
-  int    flag;			/* Set to zero to force initialization.     */
-
-  /* Parameters to be provided (see the prologue above).                    */
-  /*------------------------------------------------------------------------*/
-  char   code[4];		/* Three-letter projection code.            */
-  double r0;			/* Radius of the generating sphere.         */
-  double pv[PVN];		/* Projection parameters.                   */
-  double phi0, theta0;		/* Fiducial native coordinates.             */
-  int    bounds;		/* Enable strict bounds checking.           */
-
-  /* Information derived from the parameters supplied.                      */
-  /*------------------------------------------------------------------------*/
-  char   name[40];		/* Projection name.                         */
-  int    category;		/* Projection category.                     */
-  int    pvrange;		/* Range of projection parameter indices.   */
-  int    simplezen;		/* Is it a simple zenithal projection?      */
-  int    equiareal;		/* Is it an equal area projection?          */
-  int    conformal;		/* Is it a conformal projection?            */
-  int    global;		/* Can it map the whole sphere?             */
-  int    divergent;		/* Does the projection diverge in latitude? */
-  double x0, y0;		/* Fiducial offsets.                        */
-
-  /* Error handling                                                         */
-  /*------------------------------------------------------------------------*/
-  struct wcserr *err;
-
-  /* Private                                                                */
-  /*------------------------------------------------------------------------*/
-  void   *padding;		/* (Dummy inserted for alignment purposes.) */
-  double w[10];			/* Intermediate values.                     */
-  int    m, n;			/* Intermediate values.                     */
-
-  int (*prjx2s)(PRJX2S_ARGS);	/* Pointers to the spherical projection and */
-  int (*prjs2x)(PRJS2X_ARGS);	/* deprojection functions.                  */
-};
-
-/* Size of the prjprm struct in int units, used by the Fortran wrappers. */
-#define PRJLEN (sizeof(struct prjprm)/sizeof(int))
-
-
-/* Use the preprocessor to help declare function prototypes (see above). */
-int prjini(struct prjprm *prj);
-int prjfree(struct prjprm *prj);
-int prjprt(const struct prjprm *prj);
-
-int prjset(struct prjprm *prj);
-int prjx2s(PRJX2S_ARGS);
-int prjs2x(PRJS2X_ARGS);
-
-int azpset(struct prjprm *prj);
-int azpx2s(PRJX2S_ARGS);
-int azps2x(PRJS2X_ARGS);
-
-int szpset(struct prjprm *prj);
-int szpx2s(PRJX2S_ARGS);
-int szps2x(PRJS2X_ARGS);
-
-int tanset(struct prjprm *prj);
-int tanx2s(PRJX2S_ARGS);
-int tans2x(PRJS2X_ARGS);
-
-int stgset(struct prjprm *prj);
-int stgx2s(PRJX2S_ARGS);
-int stgs2x(PRJS2X_ARGS);
-
-int sinset(struct prjprm *prj);
-int sinx2s(PRJX2S_ARGS);
-int sins2x(PRJS2X_ARGS);
-
-int arcset(struct prjprm *prj);
-int arcx2s(PRJX2S_ARGS);
-int arcs2x(PRJS2X_ARGS);
-
-int zpnset(struct prjprm *prj);
-int zpnx2s(PRJX2S_ARGS);
-int zpns2x(PRJS2X_ARGS);
-
-int zeaset(struct prjprm *prj);
-int zeax2s(PRJX2S_ARGS);
-int zeas2x(PRJS2X_ARGS);
-
-int airset(struct prjprm *prj);
-int airx2s(PRJX2S_ARGS);
-int airs2x(PRJS2X_ARGS);
-
-int cypset(struct prjprm *prj);
-int cypx2s(PRJX2S_ARGS);
-int cyps2x(PRJS2X_ARGS);
-
-int ceaset(struct prjprm *prj);
-int ceax2s(PRJX2S_ARGS);
-int ceas2x(PRJS2X_ARGS);
-
-int carset(struct prjprm *prj);
-int carx2s(PRJX2S_ARGS);
-int cars2x(PRJS2X_ARGS);
-
-int merset(struct prjprm *prj);
-int merx2s(PRJX2S_ARGS);
-int mers2x(PRJS2X_ARGS);
-
-int sflset(struct prjprm *prj);
-int sflx2s(PRJX2S_ARGS);
-int sfls2x(PRJS2X_ARGS);
-
-int parset(struct prjprm *prj);
-int parx2s(PRJX2S_ARGS);
-int pars2x(PRJS2X_ARGS);
-
-int molset(struct prjprm *prj);
-int molx2s(PRJX2S_ARGS);
-int mols2x(PRJS2X_ARGS);
-
-int aitset(struct prjprm *prj);
-int aitx2s(PRJX2S_ARGS);
-int aits2x(PRJS2X_ARGS);
-
-int copset(struct prjprm *prj);
-int copx2s(PRJX2S_ARGS);
-int cops2x(PRJS2X_ARGS);
-
-int coeset(struct prjprm *prj);
-int coex2s(PRJX2S_ARGS);
-int coes2x(PRJS2X_ARGS);
-
-int codset(struct prjprm *prj);
-int codx2s(PRJX2S_ARGS);
-int cods2x(PRJS2X_ARGS);
-
-int cooset(struct prjprm *prj);
-int coox2s(PRJX2S_ARGS);
-int coos2x(PRJS2X_ARGS);
-
-int bonset(struct prjprm *prj);
-int bonx2s(PRJX2S_ARGS);
-int bons2x(PRJS2X_ARGS);
-
-int pcoset(struct prjprm *prj);
-int pcox2s(PRJX2S_ARGS);
-int pcos2x(PRJS2X_ARGS);
-
-int tscset(struct prjprm *prj);
-int tscx2s(PRJX2S_ARGS);
-int tscs2x(PRJS2X_ARGS);
-
-int cscset(struct prjprm *prj);
-int cscx2s(PRJX2S_ARGS);
-int cscs2x(PRJS2X_ARGS);
-
-int qscset(struct prjprm *prj);
-int qscx2s(PRJX2S_ARGS);
-int qscs2x(PRJS2X_ARGS);
-
-int hpxset(struct prjprm *prj);
-int hpxx2s(PRJX2S_ARGS);
-int hpxs2x(PRJS2X_ARGS);
-
-
-/* Deprecated. */
-#define prjini_errmsg prj_errmsg
-#define prjprt_errmsg prj_errmsg
-#define prjset_errmsg prj_errmsg
-#define prjx2s_errmsg prj_errmsg
-#define prjs2x_errmsg prj_errmsg
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* WCSLIB_PROJ */
diff --git a/astropy/wcs/src/wcslib/C/spc.c b/astropy/wcs/src/wcslib/C/spc.c
deleted file mode 100644
index ed8b037..0000000
--- a/astropy/wcs/src/wcslib/C/spc.c
+++ /dev/null
@@ -1,1369 +0,0 @@
-/*============================================================================
-
-  WCSLIB 4.10 - an implementation of the FITS WCS standard.
-  Copyright (C) 1995-2012, Mark Calabretta
-
-  This file is part of WCSLIB.
-
-  WCSLIB is free software: you can redistribute it and/or modify it under the
-  terms of the GNU Lesser General Public License as published by the Free
-  Software Foundation, either version 3 of the License, or (at your option)
-  any later version.
-
-  WCSLIB 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 Lesser General Public License for
-  more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with WCSLIB.  If not, see <http://www.gnu.org/licenses/>.
-
-  Correspondence concerning WCSLIB may be directed to:
-    Internet email: mcalabre at atnf.csiro.au
-    Postal address: Dr. Mark Calabretta
-                    Australia Telescope National Facility, CSIRO
-                    PO Box 76
-                    Epping NSW 1710
-                    AUSTRALIA
-
-  Author: Mark Calabretta, Australia Telescope National Facility
-  http://www.atnf.csiro.au/~mcalabre/index.html
-  $Id: spc.c,v 4.10 2012/02/05 23:41:44 cal103 Exp $
-*===========================================================================*/
-
-#include <math.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "wcserr.h"
-#include "wcsmath.h"
-#include "wcsprintf.h"
-#include "wcstrig.h"
-#include "wcsutil.h"
-#include "spc.h"
-#include "spx.h"
-
-/* Spectral algorithm codes. */
-#define F2S 100;		/* Axis linear in frequency.          */
-#define W2S 200;		/* Axis linear in vacuum wavelengths. */
-#define A2S 300;		/* Axis linear in air wavelengths.    */
-#define V2S 400;		/* Axis linear in velocity.           */
-#define GRI 500;		/* Grism in vacuum.                   */
-#define GRA 600;		/* Grism in air.                      */
-
-/* S-type spectral variables. */
-#define FREQ  0;		/* Frequency-like.                    */
-#define AFRQ  1;		/* Frequency-like.                    */
-#define ENER  2;		/* Frequency-like.                    */
-#define WAVN  3;		/* Frequency-like.                    */
-#define VRAD  4;		/* Frequency-like.                    */
-#define WAVE 10;		/* Vacuum wavelength-like.            */
-#define VOPT 11;		/* Vacuum wavelength-like.            */
-#define ZOPT 12;		/* Vacuum wavelength-like.            */
-#define AWAV 20;		/* Air wavelength-like.               */
-#define VELO 30;		/* Velocity-like.                     */
-#define BETA 31;		/* Velocity-like.                     */
-
-
-/* Map status return value to message. */
-const char *spc_errmsg[] = {
-  "Success",
-  "Null spcprm pointer passed",
-  "Invalid spectral parameters",
-  "One or more of x coordinates were invalid",
-  "One or more of the spec coordinates were invalid"};
-
-/* Convenience macro for invoking wcserr_set(). */
-#define SPC_ERRMSG(status) WCSERR_SET(status), spc_errmsg[status]
-
-
-#define C 2.99792458e8
-
-/*--------------------------------------------------------------------------*/
-
-int spcini(struct spcprm *spc)
-
-{
-  register int k;
-
-  if (spc == 0x0) return SPCERR_NULL_POINTER;
-
-  spc->flag = 0;
-
-  strcpy(spc->type, "    ");
-  strcpy(spc->code, "   ");
-
-  spc->crval = UNDEFINED;
-  spc->restfrq =  0.0;
-  spc->restwav =  0.0;
-
-  for (k = 0; k < 7; k++) {
-    spc->pv[k] = UNDEFINED;
-  }
-
-  for (k = 0; k < 6; k++) {
-    spc->w[k] = 0.0;
-  }
-
-  spc->isGrism = 0;
-
-  spc->err = 0x0;
-
-  spc->spxX2P = 0x0;
-  spc->spxP2S = 0x0;
-  spc->spxS2P = 0x0;
-  spc->spxP2X = 0x0;
-
-  return SPCERR_SUCCESS;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int spcfree(spc)
-
-struct spcprm *spc;
-
-{
-  if (spc == 0x0) return SPCERR_NULL_POINTER;
-
-  if (spc->err) free(spc->err);
-  spc->err = 0x0;
-
-  return SPCERR_SUCCESS;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int spcprt(const struct spcprm *spc)
-
-{
-  char hext[32];
-  int  i;
-
-  if (spc == 0x0) return SPCERR_NULL_POINTER;
-
-  wcsprintf("       flag: %d\n", spc->flag);
-  wcsprintf("       type: \"%s\"\n", spc->type);
-  wcsprintf("       code: \"%s\"\n", spc->code);
-  if (undefined(spc->crval)) {
-    wcsprintf("      crval: UNDEFINED\n");
-  } else {
-    wcsprintf("      crval: %- 11.4g\n", spc->crval);
-  }
-  wcsprintf("    restfrq: %f\n", spc->restfrq);
-  wcsprintf("    restwav: %f\n", spc->restwav);
-
-  wcsprintf("         pv:");
-  if (spc->isGrism) {
-    for (i = 0; i < 5; i++) {
-      if (undefined(spc->pv[i])) {
-        wcsprintf("  UNDEFINED   ");
-      } else {
-        wcsprintf("  %- 11.4g", spc->pv[i]);
-      }
-    }
-    wcsprintf("\n            ");
-    for (i = 5; i < 7; i++) {
-      if (undefined(spc->pv[i])) {
-        wcsprintf("  UNDEFINED   ");
-      } else {
-        wcsprintf("  %- 11.4g", spc->pv[i]);
-      }
-    }
-    wcsprintf("\n");
-
-  } else {
-    wcsprintf(" (not used)\n");
-  }
-
-  wcsprintf("          w:");
-  for (i = 0; i < 3; i++) {
-    wcsprintf("  %- 11.4g", spc->w[i]);
-  }
-  if (spc->isGrism) {
-    wcsprintf("\n            ");
-    for (i = 3; i < 6; i++) {
-      wcsprintf("  %- 11.4g", spc->w[i]);
-    }
-    wcsprintf("\n");
-  } else {
-    wcsprintf("  (remainder unused)\n");
-  }
-
-  wcsprintf("    isGrism: %d\n", spc->isGrism);
-
-  WCSPRINTF_PTR("        err: ", spc->err, "\n");
-  if (spc->err) {
-    wcserr_prt(spc->err, "             ");
-  }
-
-  wcsprintf("     spxX2P: %s\n",
-    wcsutil_fptr2str((int (*)(void))spc->spxX2P, hext));
-  wcsprintf("     spxP2S: %s\n",
-    wcsutil_fptr2str((int (*)(void))spc->spxP2S, hext));
-  wcsprintf("     spxS2P: %s\n",
-    wcsutil_fptr2str((int (*)(void))spc->spxS2P, hext));
-  wcsprintf("     spxP2X: %s\n",
-    wcsutil_fptr2str((int (*)(void))spc->spxP2X, hext));
-
-  return SPCERR_SUCCESS;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int spcset(struct spcprm *spc)
-
-{
-  static const char *function = "spcset";
-
-  char   ctype[9], ptype, xtype;
-  int    restreq, status;
-  double alpha, beta_r, crvalX, dn_r, dXdS, epsilon, G, m, lambda_r, n_r,
-         t, restfrq, restwav, theta;
-  struct wcserr **err;
-
-  if (spc == 0x0) return SPCERR_NULL_POINTER;
-  err = &(spc->err);
-
-  if (undefined(spc->crval)) {
-    return wcserr_set(WCSERR_SET(SPCERR_BAD_SPEC_PARAMS),
-      "Spectral crval is undefined");
-  }
-
-  spc->type[4] = '\0';
-  spc->code[3] = '\0';
-  spc->w[0] = 0.0;
-
-
-  /* Analyse the spectral axis type. */
-  sprintf(ctype, "%s-%s", spc->type, spc->code);
-  restfrq = spc->restfrq;
-  restwav = spc->restwav;
-  if ((status = spcspxe(ctype, spc->crval, restfrq, restwav, &ptype, &xtype,
-                        &restreq, &crvalX, &dXdS, &(spc->err)))) {
-    return status;
-  }
-
-  /* Satisfy rest frequency/wavelength requirements. */
-  if (restreq) {
-    if (restreq == 3 && restfrq == 0.0 && restwav == 0.0) {
-      /* VRAD-V2F, VOPT-V2W, and ZOPT-V2W require the rest frequency or */
-      /* wavelength for the S-P and P-X transformations but not for S-X */
-      /* so supply a phoney value. */
-      restwav = 1.0;
-    }
-
-    if (restfrq == 0.0) {
-      restfrq = C/restwav;
-    } else {
-      restwav = C/restfrq;
-    }
-
-    if (ptype == 'F') {
-      spc->w[0] = restfrq;
-    } else if (ptype != 'V') {
-      spc->w[0] = restwav;
-    } else {
-      if (xtype == 'F') {
-        spc->w[0] = restfrq;
-      } else {
-        spc->w[0] = restwav;
-      }
-    }
-  }
-
-  spc->w[1] = crvalX;
-  spc->w[2] = dXdS;
-
-
-  /* Set pointers-to-functions for the linear part of the transformation. */
-  if (ptype == 'F') {
-    if (strcmp(spc->type, "FREQ") == 0) {
-      /* Frequency. */
-      spc->flag = FREQ;
-      spc->spxP2S = 0x0;
-      spc->spxS2P = 0x0;
-
-    } else if (strcmp(spc->type, "AFRQ") == 0) {
-      /* Angular frequency. */
-      spc->flag = AFRQ;
-      spc->spxP2S = freqafrq;
-      spc->spxS2P = afrqfreq;
-
-    } else if (strcmp(spc->type, "ENER") == 0) {
-      /* Photon energy. */
-      spc->flag = ENER;
-      spc->spxP2S = freqener;
-      spc->spxS2P = enerfreq;
-
-    } else if (strcmp(spc->type, "WAVN") == 0) {
-      /* Wave number. */
-      spc->flag = WAVN;
-      spc->spxP2S = freqwavn;
-      spc->spxS2P = wavnfreq;
-
-    } else if (strcmp(spc->type, "VRAD") == 0) {
-      /* Radio velocity. */
-      spc->flag = VRAD;
-      spc->spxP2S = freqvrad;
-      spc->spxS2P = vradfreq;
-    }
-
-  } else if (ptype == 'W') {
-    if (strcmp(spc->type, "WAVE") == 0) {
-      /* Vacuum wavelengths. */
-      spc->flag = WAVE;
-      spc->spxP2S = 0x0;
-      spc->spxS2P = 0x0;
-
-    } else if (strcmp(spc->type, "VOPT") == 0) {
-      /* Optical velocity. */
-      spc->flag = VOPT;
-      spc->spxP2S = wavevopt;
-      spc->spxS2P = voptwave;
-
-    } else if (strcmp(spc->type, "ZOPT") == 0) {
-      /* Redshift. */
-      spc->flag = ZOPT;
-      spc->spxP2S = wavezopt;
-      spc->spxS2P = zoptwave;
-    }
-
-  } else if (ptype == 'A') {
-    if (strcmp(spc->type, "AWAV") == 0) {
-      /* Air wavelengths. */
-      spc->flag = AWAV;
-      spc->spxP2S = 0x0;
-      spc->spxS2P = 0x0;
-    }
-
-  } else if (ptype == 'V') {
-    if (strcmp(spc->type, "VELO") == 0) {
-      /* Relativistic velocity. */
-      spc->flag = VELO;
-      spc->spxP2S = 0x0;
-      spc->spxS2P = 0x0;
-
-    } else if (strcmp(spc->type, "BETA") == 0) {
-      /* Velocity ratio (v/c). */
-      spc->flag = BETA;
-      spc->spxP2S = velobeta;
-      spc->spxS2P = betavelo;
-    }
-  }
-
-
-  /* Set pointers-to-functions for the non-linear part of the spectral */
-  /* transformation.                                                   */
-  spc->isGrism = 0;
-  if (xtype == 'F') {
-    /* Axis is linear in frequency. */
-    if (ptype == 'F') {
-      spc->spxX2P = 0x0;
-      spc->spxP2X = 0x0;
-
-    } else if (ptype == 'W') {
-      spc->spxX2P = freqwave;
-      spc->spxP2X = wavefreq;
-
-    } else if (ptype == 'A') {
-      spc->spxX2P = freqawav;
-      spc->spxP2X = awavfreq;
-
-    } else if (ptype == 'V') {
-      spc->spxX2P = freqvelo;
-      spc->spxP2X = velofreq;
-    }
-
-    spc->flag += F2S;
-
-  } else if (xtype == 'W' || xtype == 'w') {
-    /* Axis is linear in vacuum wavelengths. */
-    if (ptype == 'F') {
-      spc->spxX2P = wavefreq;
-      spc->spxP2X = freqwave;
-
-    } else if (ptype == 'W') {
-      spc->spxX2P = 0x0;
-      spc->spxP2X = 0x0;
-
-    } else if (ptype == 'A') {
-      spc->spxX2P = waveawav;
-      spc->spxP2X = awavwave;
-
-    } else if (ptype == 'V') {
-      spc->spxX2P = wavevelo;
-      spc->spxP2X = velowave;
-    }
-
-    if (xtype == 'W') {
-      spc->flag += W2S;
-    } else {
-      /* Grism in vacuum. */
-      spc->isGrism = 1;
-      spc->flag += GRI;
-    }
-
-  } else if (xtype == 'A' || xtype == 'a') {
-    /* Axis is linear in air wavelengths. */
-    if (ptype == 'F') {
-      spc->spxX2P = awavfreq;
-      spc->spxP2X = freqawav;
-
-    } else if (ptype == 'W') {
-      spc->spxX2P = awavwave;
-      spc->spxP2X = waveawav;
-
-    } else if (ptype == 'A') {
-      spc->spxX2P = 0x0;
-      spc->spxP2X = 0x0;
-
-    } else if (ptype == 'V') {
-      spc->spxX2P = awavvelo;
-      spc->spxP2X = veloawav;
-    }
-
-    if (xtype == 'A') {
-      spc->flag += A2S;
-    } else {
-      /* Grism in air. */
-      spc->isGrism = 2;
-      spc->flag += GRA;
-    }
-
-  } else if (xtype == 'V') {
-    /* Axis is linear in relativistic velocity. */
-    if (ptype == 'F') {
-      spc->spxX2P = velofreq;
-      spc->spxP2X = freqvelo;
-
-    } else if (ptype == 'W') {
-      spc->spxX2P = velowave;
-      spc->spxP2X = wavevelo;
-
-    } else if (ptype == 'A') {
-      spc->spxX2P = veloawav;
-      spc->spxP2X = awavvelo;
-
-    } else if (ptype == 'V') {
-      spc->spxX2P = 0x0;
-      spc->spxP2X = 0x0;
-    }
-
-    spc->flag += V2S;
-  }
-
-
-  /* Check for grism axes. */
-  if (spc->isGrism) {
-    /* Axis is linear in "grism parameter"; work in wavelength. */
-    lambda_r = crvalX;
-
-    /* Set defaults. */
-    if (undefined(spc->pv[0])) spc->pv[0] = 0.0;
-    if (undefined(spc->pv[1])) spc->pv[1] = 0.0;
-    if (undefined(spc->pv[2])) spc->pv[2] = 0.0;
-    if (undefined(spc->pv[3])) spc->pv[3] = 1.0;
-    if (undefined(spc->pv[4])) spc->pv[4] = 0.0;
-    if (undefined(spc->pv[5])) spc->pv[5] = 0.0;
-    if (undefined(spc->pv[6])) spc->pv[6] = 0.0;
-
-    /* Compute intermediaries. */
-    G       = spc->pv[0];
-    m       = spc->pv[1];
-    alpha   = spc->pv[2];
-    n_r     = spc->pv[3];
-    dn_r    = spc->pv[4];
-    epsilon = spc->pv[5];
-    theta   = spc->pv[6];
-
-    t = G*m/cosd(epsilon);
-    beta_r = asind(t*lambda_r - n_r*sind(alpha));
-
-    t -= dn_r*sind(alpha);
-
-    spc->w[1] = -tand(theta);
-    spc->w[2] *= t / (cosd(beta_r)*cosd(theta)*cosd(theta));
-    spc->w[3] = beta_r + theta;
-    spc->w[4] = (n_r - dn_r*lambda_r)*sind(alpha);
-    spc->w[5] = 1.0 / t;
-  }
-
-
-  return SPCERR_SUCCESS;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int spcx2s(
-  struct spcprm *spc,
-  int nx,
-  int sx,
-  int sspec,
-  const double x[],
-  double spec[],
-  int stat[])
-
-{
-  static const char *function = "spcx2s";
-
-  int statP2S, status = SPCERR_SUCCESS, statX2P;
-  double beta;
-  register int ix;
-  register int *statp;
-  register const double *xp;
-  register double *specp;
-  struct wcserr **err;
-
-  /* Initialize. */
-  if (spc == 0x0) return SPCERR_NULL_POINTER;
-  err = &(spc->err);
-
-  if (spc->flag == 0) {
-    if ((status = spcset(spc))) return status;
-  }
-
-  /* Convert intermediate world coordinate x to X. */
-  xp = x;
-  specp = spec;
-  statp = stat;
-  for (ix = 0; ix < nx; ix++, xp += sx, specp += sspec) {
-    *specp = spc->w[1] + (*xp)*spc->w[2];
-    *(statp++) = 0;
-  }
-
-  /* If X is the grism parameter then convert it to wavelength. */
-  if (spc->isGrism) {
-    specp = spec;
-    for (ix = 0; ix < nx; ix++, specp += sspec) {
-      beta = atand(*specp) + spc->w[3];
-      *specp = (sind(beta) + spc->w[4]) * spc->w[5];
-    }
-  }
-
-  /* Apply the non-linear step of the algorithm chain to convert the    */
-  /* X-type spectral variable to P-type intermediate spectral variable. */
-  if (spc->spxX2P) {
-    if ((statX2P = spc->spxX2P(spc->w[0], nx, sspec, sspec, spec, spec,
-                               stat))) {
-      if (statX2P == SPXERR_BAD_INSPEC_COORD) {
-        status = SPCERR_BAD_X;
-      } else if (statX2P == SPXERR_BAD_SPEC_PARAMS) {
-        return wcserr_set(WCSERR_SET(SPCERR_BAD_SPEC_PARAMS),
-          "Invalid spectral parameters: Frequency or wavelength is 0");
-      } else {
-        return wcserr_set(SPC_ERRMSG(statX2P));
-      }
-    }
-  }
-
-  /* Apply the linear step of the algorithm chain to convert P-type  */
-  /* intermediate spectral variable to the required S-type variable. */
-  if (spc->spxP2S) {
-    if ((statP2S = spc->spxP2S(spc->w[0], nx, sspec, sspec, spec, spec,
-                               stat))) {
-      if (statP2S == SPXERR_BAD_INSPEC_COORD) {
-        status = SPCERR_BAD_X;
-      } else if (statP2S == SPXERR_BAD_SPEC_PARAMS) {
-        return wcserr_set(WCSERR_SET(SPCERR_BAD_SPEC_PARAMS),
-          "Invalid spectral parameters: Frequency or wavelength is 0");
-      } else {
-        return wcserr_set(SPC_ERRMSG(statP2S));
-      }
-    }
-  }
-
-  if (status) {
-    wcserr_set(SPC_ERRMSG(status));
-  }
-  return status;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int spcs2x(
-  struct spcprm *spc,
-  int nspec,
-  int sspec,
-  int sx,
-  const double spec[],
-  double x[],
-  int stat[])
-
-{
-  static const char *function = "spcs2x";
-
-  int statP2X, status = SPCERR_SUCCESS, statS2P;
-  double beta, s;
-  register int ispec;
-  register int *statp;
-  register const double *specp;
-  register double *xp;
-  struct wcserr **err;
-
-  /* Initialize. */
-  if (spc == 0x0) return SPCERR_NULL_POINTER;
-  err = &(spc->err);
-
-  if (spc->flag == 0) {
-    if ((status = spcset(spc))) return status;
-  }
-
-  /* Apply the linear step of the algorithm chain to convert the S-type */
-  /* spectral variable to P-type intermediate spectral variable.        */
-  if (spc->spxS2P) {
-    if ((statS2P = spc->spxS2P(spc->w[0], nspec, sspec, sx, spec, x, stat))) {
-      if (statS2P == SPXERR_BAD_INSPEC_COORD) {
-        status = SPCERR_BAD_SPEC;
-      } else if (statS2P == SPXERR_BAD_SPEC_PARAMS) {
-        return wcserr_set(WCSERR_SET(SPCERR_BAD_SPEC_PARAMS),
-          "Invalid spectral parameters: Frequency or wavelength is 0");
-      } else {
-        return wcserr_set(SPC_ERRMSG(statS2P));
-      }
-    }
-
-  } else {
-    /* Just a copy. */
-    xp = x;
-    specp = spec;
-    statp = stat;
-    for (ispec = 0; ispec < nspec; ispec++, specp += sspec, xp += sx) {
-      *xp = *specp;
-      *(statp++) = 0;
-    }
-  }
-
-
-  /* Apply the non-linear step of the algorithm chain to convert P-type */
-  /* intermediate spectral variable to X-type spectral variable. */
-  if (spc->spxP2X) {
-    if ((statP2X = spc->spxP2X(spc->w[0], nspec, sx, sx, x, x, stat))) {
-      if (statP2X == SPCERR_BAD_SPEC) {
-        status = SPCERR_BAD_SPEC;
-      } else if (statP2X == SPXERR_BAD_SPEC_PARAMS) {
-        return wcserr_set(WCSERR_SET(SPCERR_BAD_SPEC_PARAMS),
-          "Invalid spectral parameters: Frequency or wavelength is 0");
-      } else {
-        return wcserr_set(SPC_ERRMSG(statP2X));
-      }
-    }
-  }
-
-  if (spc->isGrism) {
-    /* Convert X-type spectral variable (wavelength) to grism parameter. */
-    xp = x;
-    statp = stat;
-    for (ispec = 0; ispec < nspec; ispec++, xp += sx, statp++) {
-      if (*statp) continue;
-
-      s = *xp/spc->w[5] - spc->w[4];
-      if (fabs(s) <= 1.0) {
-        beta = asind(s);
-        *xp = tand(beta - spc->w[3]);
-      } else {
-        *statp = 1;
-      }
-    }
-  }
-
-
-  /* Convert X-type spectral variable to intermediate world coordinate x. */
-  xp = x;
-  statp = stat;
-  for (ispec = 0; ispec < nspec; ispec++, xp += sx) {
-    if (*(statp++)) continue;
-
-    *xp -= spc->w[1];
-    *xp /= spc->w[2];
-  }
-
-  if (status) {
-    wcserr_set(SPC_ERRMSG(status));
-  }
-  return status;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int spctyp(
-  const char ctypei[9],
-  char stype[],
-  char scode[],
-  char sname[],
-  char units[],
-  char *ptype,
-  char *xtype,
-  int  *restreq)
-
-{
-  return spctype(
-    ctypei, stype, scode, sname, units, ptype, xtype, restreq, NULL);
-}
-
-/* : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :  */
-
-int spctype(
-  const char ctypei[9],
-  char stype[],
-  char scode[],
-  char sname[],
-  char units[],
-  char *ptype,
-  char *xtype,
-  int  *restreq,
-  struct wcserr **err)
-
-{
-  static const char *function = "spctype";
-
-  char ctype[9], ptype_t, sname_t[32], units_t[8], xtype_t;
-  int  restreq_t = 0;
-
-  /* Copy with blank padding. */
-  sprintf(ctype, "%-8.8s", ctypei);
-  ctype[8] = '\0';
-
-  /* Validate the S-type spectral variable. */
-  if (strncmp(ctype, "FREQ", 4) == 0) {
-    strcpy(sname_t, "Frequency");
-    strcpy(units_t, "Hz");
-    ptype_t = 'F';
-  } else if (strncmp(ctype, "AFRQ", 4) == 0) {
-    strcpy(sname_t, "Angular frequency");
-    strcpy(units_t, "rad/s");
-    ptype_t = 'F';
-  } else if (strncmp(ctype, "ENER", 4) == 0) {
-    strcpy(sname_t, "Photon energy");
-    strcpy(units_t, "J");
-    ptype_t = 'F';
-  } else if (strncmp(ctype, "WAVN", 4) == 0) {
-    strcpy(sname_t, "Wavenumber");
-    strcpy(units_t, "/m");
-    ptype_t = 'F';
-  } else if (strncmp(ctype, "VRAD", 4) == 0) {
-    strcpy(sname_t, "Radio velocity");
-    strcpy(units_t, "m/s");
-    ptype_t = 'F';
-    restreq_t = 1;
-  } else if (strncmp(ctype, "WAVE", 4) == 0) {
-    strcpy(sname_t, "Vacuum wavelength");
-    strcpy(units_t, "m");
-    ptype_t = 'W';
-  } else if (strncmp(ctype, "VOPT", 4) == 0) {
-    strcpy(sname_t, "Optical velocity");
-    strcpy(units_t, "m/s");
-    ptype_t = 'W';
-    restreq_t = 1;
-  } else if (strncmp(ctype, "ZOPT", 4) == 0) {
-    strcpy(sname_t, "Redshift");
-    strcpy(units_t, "");
-    ptype_t = 'W';
-    restreq_t = 1;
-  } else if (strncmp(ctype, "AWAV", 4) == 0) {
-    strcpy(sname_t, "Air wavelength");
-    strcpy(units_t, "m");
-    ptype_t = 'A';
-  } else if (strncmp(ctype, "VELO", 4) == 0) {
-    strcpy(sname_t, "Relativistic velocity");
-    strcpy(units_t, "m/s");
-    ptype_t = 'V';
-  } else if (strncmp(ctype, "BETA", 4) == 0) {
-    strcpy(sname_t, "Velocity ratio (v/c)");
-    strcpy(units_t, "");
-    ptype_t = 'V';
-  } else {
-    return wcserr_set(WCSERR_SET(SPCERR_BAD_SPEC_PARAMS),
-      "Unknown spectral type '%s'", ctype);
-  }
-
-
-  /* Determine X-type and validate the spectral algorithm code. */
-  if ((xtype_t = ctype[5]) == ' ') {
-    /* The algorithm code must be completely blank. */
-    if (strcmp(ctype+4, "    ") != 0) {
-      return wcserr_set(WCSERR_SET(SPCERR_BAD_SPEC_PARAMS),
-        "Invalid spectral algorithm '%s'", ctype+4);
-    }
-
-    xtype_t = ptype_t;
-
-  } else if (ctype[4] != '-') {
-    return wcserr_set(WCSERR_SET(SPCERR_BAD_SPEC_PARAMS),
-      "Invalid spectral type '%s'", ctype);
-
-  } else if (strcmp(ctype+5, "LOG") == 0 || strcmp(ctype+5, "TAB") == 0) {
-    /* Logarithmic or tabular axis, not linear in any spectral type. */
-
-  } else if (xtype_t == 'G') {
-    /* Validate the algorithm code. */
-    if (ctype[6] != 'R') {
-      return wcserr_set(WCSERR_SET(SPCERR_BAD_SPEC_PARAMS),
-        "Invalid spectral algorithm '%s'", xtype_t);
-    }
-
-    /* Grism coordinates... */
-    if (ctype[7] == 'I') {
-      /* ...in vacuum. */
-      xtype_t = 'w';
-    } else if (ctype[7] == 'A') {
-      /* ...in air. */
-      xtype_t = 'a';
-    } else {
-      return wcserr_set(WCSERR_SET(SPCERR_BAD_SPEC_PARAMS),
-        "Invalid spectral algorithm '%s'", xtype_t);
-    }
-
-  } else if (ctype[6] != '2') {
-    /* Algorithm code has invalid syntax. */
-    return wcserr_set(WCSERR_SET(SPCERR_BAD_SPEC_PARAMS),
-      "Invalid spectral algorithm syntax '%s'", xtype_t);
-  } else if (ctype[7] != ptype_t && ctype[7] != '?') {
-    /* The P-, and S-type variables are inconsistent. */
-    return wcserr_set(WCSERR_SET(SPCERR_BAD_SPEC_PARAMS),
-      "In spectral type '%s', P- and S-type variables are inconsistent",
-      ctype);
-
-  } else if (ctype[7] == ctype[5]) {
-    /* Degenerate algorithm code. */
-    sprintf(ctype+4, "    ");
-  }
-
-
-  /* Rest freq/wavelength required for transformation between P and X? */
-  if (strchr("FWAwa", (int)xtype_t)) {
-    if (ptype_t == 'V') {
-      restreq_t += 2;
-    }
-  } else if (xtype_t == 'V') {
-    if (strchr("FWAwa", (int)ptype_t)) {
-      restreq_t += 2;
-    }
-  } else if (strchr("LT", (int)xtype_t) == 0) {
-    /* Invalid X-type variable code. */
-    return wcserr_set(WCSERR_SET(SPCERR_BAD_SPEC_PARAMS),
-      "In spectral type '%s', invalid X-type variable code", ctype);
-  }
-
-
-  /* Copy results. */
-  if (stype) {
-    strncpy(stype, ctype, 4);
-    stype[4] = '\0';
-  }
-  if (scode) strcpy(scode, ctype+5);
-  if (sname) strcpy(sname, sname_t);
-  if (units) strcpy(units, units_t);
-  if (ptype) *ptype = ptype_t;
-  if (xtype) *xtype = xtype_t;
-  if (restreq) *restreq = restreq_t;
-
-
-  return SPCERR_SUCCESS;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int spcspx(
-  const char ctypeS[9],
-  double crvalS,
-  double restfrq,
-  double restwav,
-  char *ptype,
-  char *xtype,
-  int *restreq,
-  double *crvalX,
-  double *dXdS)
-
-{
-  return spcspxe(ctypeS, crvalS, restfrq, restwav, ptype, xtype, restreq,
-                 crvalX, dXdS, 0x0);
-}
-
-/* : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :  */
-
-int spcspxe(
-  const char ctypeS[9],
-  double crvalS,
-  double restfrq,
-  double restwav,
-  char *ptype,
-  char *xtype,
-  int *restreq,
-  double *crvalX,
-  double *dXdS,
-  struct wcserr **err)
-
-{
-  static const char *function = "spcspxe";
-
-  char scode[4], stype[5], type[8];
-  int  status;
-  double dPdS, dXdP;
-  struct spxprm spx;
-
-
-  /* Analyse the spectral axis code. */
-  if ((status = spctype(ctypeS, stype, scode, 0x0, 0x0, ptype, xtype, restreq,
-                        err))) {
-    return status;
-  }
-
-  if (strstr("LT", xtype)) {
-    /* Can't handle logarithmic or tabular coordinates. */
-    return wcserr_set(WCSERR_SET(SPCERR_BAD_SPEC_PARAMS),
-      "Can't handle logarithmic or tabular coordinates");
-  }
-
-  /* Do we have rest frequency and/or wavelength as required? */
-  if ((*restreq)%3 && restfrq == 0.0 && restwav == 0.0) {
-    return wcserr_set(WCSERR_SET(SPCERR_BAD_SPEC_PARAMS),
-      "Missing required rest frequency or wavelength");
-  }
-
-  /* Compute all spectral parameters and their derivatives. */
-  strcpy(type, stype);
-  spx.err = (err ? *err : 0x0);
-  if ((status = specx(type, crvalS, restfrq, restwav, &spx))) {
-    status = SPCERR_BAD_SPEC_PARAMS;
-    if (err) {
-      (*err)->status = status;
-    } else {
-      free(spx.err);
-    }
-    return status;
-  }
-
-
-  /* Transform S-P (linear) and P-X (non-linear). */
-  dPdS = 0.0;
-  dXdP = 0.0;
-  if (*ptype == 'F') {
-    if (strcmp(stype, "FREQ") == 0) {
-      dPdS = 1.0;
-    } else if (strcmp(stype, "AFRQ") == 0) {
-      dPdS = spx.dfreqafrq;
-    } else if (strcmp(stype, "ENER") == 0) {
-      dPdS = spx.dfreqener;
-    } else if (strcmp(stype, "WAVN") == 0) {
-      dPdS = spx.dfreqwavn;
-    } else if (strcmp(stype, "VRAD") == 0) {
-      dPdS = spx.dfreqvrad;
-    }
-
-    if (*xtype == 'F') {
-      *crvalX = spx.freq;
-      dXdP = 1.0;
-    } else if (*xtype == 'W' || *xtype == 'w') {
-      *crvalX = spx.wave;
-      dXdP = spx.dwavefreq;
-    } else if (*xtype == 'A' || *xtype == 'a') {
-      *crvalX = spx.awav;
-      dXdP = spx.dawavfreq;
-    } else if (*xtype == 'V') {
-      *crvalX = spx.velo;
-      dXdP = spx.dvelofreq;
-    }
-
-  } else if (*ptype == 'W' || *ptype == 'w') {
-    if (strcmp(stype, "WAVE") == 0) {
-      dPdS = 1.0;
-    } else if (strcmp(stype, "VOPT") == 0) {
-      dPdS = spx.dwavevopt;
-    } else if (strcmp(stype, "ZOPT") == 0) {
-      dPdS = spx.dwavezopt;
-    }
-
-    if (*xtype == 'F') {
-      *crvalX = spx.freq;
-      dXdP = spx.dfreqwave;
-    } else if (*xtype == 'W' || *xtype == 'w') {
-      *crvalX = spx.wave;
-      dXdP = 1.0;
-    } else if (*xtype == 'A' || *xtype == 'a') {
-      *crvalX = spx.awav;
-      dXdP = spx.dawavwave;
-    } else if (*xtype == 'V') {
-      *crvalX = spx.velo;
-      dXdP = spx.dvelowave;
-    }
-
-  } else if (*ptype == 'A' || *ptype == 'a') {
-    if (strcmp(stype, "AWAV") == 0) {
-      dPdS = 1.0;
-    }
-
-    if (*xtype == 'F') {
-      *crvalX = spx.freq;
-      dXdP = spx.dfreqawav;
-    } else if (*xtype == 'W' || *xtype == 'w') {
-      *crvalX = spx.wave;
-      dXdP = spx.dwaveawav;
-    } else if (*xtype == 'A' || *xtype == 'a') {
-      *crvalX = spx.awav;
-      dXdP = 1.0;
-    } else if (*xtype == 'V') {
-      *crvalX = spx.velo;
-      dXdP = spx.dveloawav;
-    }
-
-  } else if (*ptype == 'V') {
-    if (strcmp(stype, "VELO") == 0) {
-      dPdS = 1.0;
-    } else if (strcmp(stype, "BETA") == 0) {
-      dPdS = spx.dvelobeta;
-    }
-
-    if (*xtype == 'F') {
-      *crvalX = spx.freq;
-      dXdP = spx.dfreqvelo;
-    } else if (*xtype == 'W' || *xtype == 'w') {
-      *crvalX = spx.wave;
-      dXdP = spx.dwavevelo;
-    } else if (*xtype == 'A' || *xtype == 'a') {
-      *crvalX = spx.awav;
-      dXdP = spx.dawavvelo;
-    } else if (*xtype == 'V') {
-      *crvalX = spx.velo;
-      dXdP = 1.0;
-    }
-  }
-
-  *dXdS = dXdP * dPdS;
-
-  return SPCERR_SUCCESS;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int spcxps(
-  const char ctypeS[9],
-  double crvalX,
-  double restfrq,
-  double restwav,
-  char *ptype,
-  char *xtype,
-  int *restreq,
-  double *crvalS,
-  double *dSdX)
-
-{
-  return spcxpse(ctypeS, crvalX, restfrq, restwav, ptype, xtype, restreq,
-                 crvalS, dSdX, NULL);
-}
-
-/* : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :  */
-
-int spcxpse(
-  const char ctypeS[9],
-  double crvalX,
-  double restfrq,
-  double restwav,
-  char *ptype,
-  char *xtype,
-  int *restreq,
-  double *crvalS,
-  double *dSdX,
-  struct wcserr **err)
-
-{
-  static const char *function = "spcxpse";
-
-  char scode[4], stype[5], type[8];
-  int  status;
-  double dPdX, dSdP;
-  struct spxprm spx;
-
-  /* Analyse the spectral axis type. */
-  if ((status = spctype(ctypeS, stype, scode, 0x0, 0x0, ptype, xtype, restreq,
-                        err))) {
-    return status;
-  }
-
-  if (strstr("LT", xtype)) {
-    /* Can't handle logarithmic or tabular coordinates. */
-    return wcserr_set(WCSERR_SET(SPCERR_BAD_SPEC_PARAMS),
-      "Can't handle logarithmic or tabular coordinates");
-  }
-
-  /* Do we have rest frequency and/or wavelength as required? */
-  if ((*restreq)%3 && restfrq == 0.0 && restwav == 0.0) {
-    return wcserr_set(WCSERR_SET(SPCERR_BAD_SPEC_PARAMS),
-      "Missing required rest frequency or wavelength");
-  }
-
-  /* Compute all spectral parameters and their derivatives. */
-  if (*xtype == 'F') {
-    strcpy(type, "FREQ");
-  } else if (*xtype == 'W' || *xtype == 'w') {
-    strcpy(type, "WAVE");
-  } else if (*xtype == 'A' || *xtype == 'a') {
-    strcpy(type, "AWAV");
-  } else if (*xtype == 'V') {
-    strcpy(type, "VELO");
-  }
-
-  spx.err = (err ? *err : 0x0);
-  if (specx(type, crvalX, restfrq, restwav, &spx)) {
-    status = SPCERR_BAD_SPEC_PARAMS;
-    if (err) {
-      (*err)->status = status;
-    } else {
-      free(spx.err);
-    }
-    return status;
-  }
-
-
-  /* Transform X-P (non-linear) and P-S (linear). */
-  dPdX = 0.0;
-  dSdP = 0.0;
-  if (*ptype == 'F') {
-    if (*xtype == 'F') {
-      dPdX = 1.0;
-    } else if (*xtype == 'W' || *xtype == 'w') {
-      dPdX = spx.dfreqwave;
-    } else if (*xtype == 'A' || *xtype == 'a') {
-      dPdX = spx.dfreqawav;
-    } else if (*xtype == 'V') {
-      dPdX = spx.dfreqvelo;
-    }
-
-    if (strcmp(stype, "FREQ") == 0) {
-      *crvalS = spx.freq;
-      dSdP = 1.0;
-    } else if (strcmp(stype, "AFRQ") == 0) {
-      *crvalS = spx.afrq;
-      dSdP = spx.dafrqfreq;
-    } else if (strcmp(stype, "ENER") == 0) {
-      *crvalS = spx.ener;
-      dSdP = spx.denerfreq;
-    } else if (strcmp(stype, "WAVN") == 0) {
-      *crvalS = spx.wavn;
-      dSdP = spx.dwavnfreq;
-    } else if (strcmp(stype, "VRAD") == 0) {
-      *crvalS = spx.vrad;
-      dSdP = spx.dvradfreq;
-    }
-
-  } else if (*ptype == 'W') {
-    if (*xtype == 'F') {
-      dPdX = spx.dwavefreq;
-    } else if (*xtype == 'W' || *xtype == 'w') {
-      dPdX = 1.0;
-    } else if (*xtype == 'A' || *xtype == 'a') {
-      dPdX = spx.dwaveawav;
-    } else if (*xtype == 'V') {
-      dPdX = spx.dwavevelo;
-    }
-
-    if (strcmp(stype, "WAVE") == 0) {
-      *crvalS = spx.wave;
-      dSdP = 1.0;
-    } else if (strcmp(stype, "VOPT") == 0) {
-      *crvalS = spx.vopt;
-      dSdP = spx.dvoptwave;
-    } else if (strcmp(stype, "ZOPT") == 0) {
-      *crvalS = spx.zopt;
-      dSdP = spx.dzoptwave;
-    }
-
-  } else if (*ptype == 'A') {
-    if (*xtype == 'F') {
-      dPdX = spx.dawavfreq;
-    } else if (*xtype == 'W' || *xtype == 'w') {
-      dPdX = spx.dawavwave;
-    } else if (*xtype == 'A' || *xtype == 'a') {
-      dPdX = 1.0;
-    } else if (*xtype == 'V') {
-      dPdX = spx.dawavvelo;
-    }
-
-    if (strcmp(stype, "AWAV") == 0) {
-      *crvalS = spx.awav;
-      dSdP = 1.0;
-    }
-
-  } else if (*ptype == 'V') {
-    if (*xtype == 'F') {
-      dPdX = spx.dvelofreq;
-    } else if (*xtype == 'W' || *xtype == 'w') {
-      dPdX = spx.dvelowave;
-    } else if (*xtype == 'A' || *xtype == 'a') {
-      dPdX = spx.dveloawav;
-    } else if (*xtype == 'V') {
-      dPdX = 1.0;
-    }
-
-    if (strcmp(stype, "VELO") == 0) {
-      *crvalS = spx.velo;
-      dSdP = 1.0;
-    } else if (strcmp(stype, "BETA") == 0) {
-      *crvalS = spx.beta;
-      dSdP = spx.dbetavelo;
-    }
-  }
-
-  *dSdX = dSdP * dPdX;
-
-  return SPCERR_SUCCESS;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int spctrn(
-  const char ctypeS1[9],
-  double crvalS1,
-  double cdeltS1,
-  double restfrq,
-  double restwav,
-  char   ctypeS2[9],
-  double *crvalS2,
-  double *cdeltS2)
-
-{
-  return spctrne(ctypeS1, crvalS1, cdeltS1, restfrq, restwav,
-                 ctypeS2, crvalS2, cdeltS2, NULL);
-}
-
-/* : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :  */
-
-int spctrne(
-  const char ctypeS1[9],
-  double crvalS1,
-  double cdeltS1,
-  double restfrq,
-  double restwav,
-  char   ctypeS2[9],
-  double *crvalS2,
-  double *cdeltS2,
-  struct wcserr **err)
-
-{
-  static const char *function = "spctrne";
-
-  char *cp, ptype1, ptype2, xtype1, xtype2;
-  int  restreq, status;
-  double crvalX, dS2dX, dXdS1;
-
-  if ((status = spcspxe(ctypeS1, crvalS1, restfrq, restwav, &ptype1, &xtype1,
-                        &restreq, &crvalX, &dXdS1, err))) {
-    return status;
-  }
-
-  /* Blank fill. */
-  ctypeS2[8] = '\0';
-  for (cp = ctypeS2; *cp; cp++);
-  while (cp < ctypeS2+8) *(cp++) = ' ';
-
-  if (strncmp(ctypeS2+5, "???", 3) == 0) {
-    /* Set the algorithm code if required. */
-    if (xtype1 == 'w') {
-      strcpy(ctypeS2+5, "GRI");
-    } else if (xtype1 == 'a') {
-      strcpy(ctypeS2+5, "GRA");
-    } else {
-      ctypeS2[5] = xtype1;
-      ctypeS2[6] = '2';
-    }
-  }
-
-  if ((status = spcxpse(ctypeS2, crvalX, restfrq, restwav, &ptype2, &xtype2,
-                        &restreq, crvalS2, &dS2dX, err))) {
-    return status;
-  }
-
-  /* Are the X-types compatible? */
-  if (xtype2 != xtype1) {
-    return wcserr_set(WCSERR_SET(SPCERR_BAD_SPEC_PARAMS),
-      "Incompatible X-types '%c' and '%c'", xtype1, xtype2);
-  }
-
-  if (ctypeS2[7] == '?') {
-    if (ptype2 == xtype2) {
-      strcpy(ctypeS2+4, "    ");
-    } else {
-      ctypeS2[7] = ptype2;
-    }
-  }
-
-  *cdeltS2 = dS2dX * dXdS1 * cdeltS1;
-
-  return SPCERR_SUCCESS;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int spcaips(
-  const char ctypeA[9],
-  int  velref,
-  char ctype[9],
-  char specsys[9])
-
-{
-  const char *frames[] = {"LSRK", "BARYCENT", "TOPOCENT",
-                          "LSRD", "GEOCENTR", "SOURCE", "GALACTOC"};
-  char *fcode;
-  int  ivf, status;
-
-  /* Make a null-filled copy of ctypeA. */
-  if (ctype != ctypeA) strncpy(ctype, ctypeA, 8);
-  ctype[8] = '\0';
-  wcsutil_null_fill(9, ctype);
-  *specsys = '\0';
-
-  /* Is it a recognized AIPS-convention type? */
-  status = SPCERR_NO_CHANGE;
-  if (strncmp(ctype, "FREQ", 4) == 0 ||
-      strncmp(ctype, "VELO", 4) == 0 ||
-      strncmp(ctype, "FELO", 4) == 0) {
-    /* Look for the Doppler frame. */
-    if (*(fcode = ctype+4)) {
-      if (strcmp(fcode, "-LSR") == 0) {
-        strcpy(specsys, "LSRK");
-      } else if (strcmp(fcode, "-HEL") == 0) {
-        strcpy(specsys, "BARYCENT");
-      } else if (strcmp(fcode, "-OBS") == 0) {
-        strcpy(specsys, "TOPOCENT");
-      } else {
-        /* Not a recognized AIPS spectral type. */
-        return SPCERR_NO_CHANGE;
-      }
-
-      *fcode = '\0';
-      status = SPCERR_SUCCESS;
-    }
-
-    /* VELREF takes precedence if present. */
-    ivf = velref%256;
-    if (0 < ivf && ivf <= 7) {
-      strcpy(specsys, frames[ivf-1]);
-      status = SPCERR_SUCCESS;
-    } else if (ivf) {
-      status = SPCERR_BAD_SPEC_PARAMS;
-    }
-
-    if (strcmp(ctype, "VELO") == 0) {
-      /* Check that we found an AIPS-convention Doppler frame. */
-      if (*specsys) {
-        /* 'VELO' in AIPS means radio or optical depending on VELREF. */
-        ivf = velref/256;
-        if (ivf == 0) {
-          strcpy(ctype, "VOPT");
-        } else if (ivf == 1) {
-          strcpy(ctype, "VRAD");
-        } else {
-          status = SPCERR_BAD_SPEC_PARAMS;
-        }
-      }
-    } else if (strcmp(ctype, "FELO") == 0) {
-      /* Uniform in frequency but expressed as an optical velocity (strictly
-         we should also have found an AIPS-convention Doppler frame). */
-      strcpy(ctype, "VOPT-F2W");
-      if (status < 0) status = SPCERR_SUCCESS;
-    }
-  }
-
-  return status;
-}
diff --git a/astropy/wcs/src/wcslib/C/spc.h b/astropy/wcs/src/wcslib/C/spc.h
deleted file mode 100644
index 0a1883e..0000000
--- a/astropy/wcs/src/wcslib/C/spc.h
+++ /dev/null
@@ -1,890 +0,0 @@
-/*============================================================================
-
-  WCSLIB 4.10 - an implementation of the FITS WCS standard.
-  Copyright (C) 1995-2012, Mark Calabretta
-
-  This file is part of WCSLIB.
-
-  WCSLIB is free software: you can redistribute it and/or modify it under the
-  terms of the GNU Lesser General Public License as published by the Free
-  Software Foundation, either version 3 of the License, or (at your option)
-  any later version.
-
-  WCSLIB 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 Lesser General Public License for
-  more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with WCSLIB.  If not, see <http://www.gnu.org/licenses/>.
-
-  Correspondence concerning WCSLIB may be directed to:
-    Internet email: mcalabre at atnf.csiro.au
-    Postal address: Dr. Mark Calabretta
-                    Australia Telescope National Facility, CSIRO
-                    PO Box 76
-                    Epping NSW 1710
-                    AUSTRALIA
-
-  Author: Mark Calabretta, Australia Telescope National Facility
-  http://www.atnf.csiro.au/~mcalabre/index.html
-  $Id: spc.h,v 4.10 2012/02/05 23:41:44 cal103 Exp $
-*=============================================================================
-*
-* WCSLIB 4.10 - C routines that implement the spectral coordinate systems
-* recognized by the FITS World Coordinate System (WCS) standard.  Refer to
-*
-*   "Representations of world coordinates in FITS",
-*   Greisen, E.W., & Calabretta, M.R. 2002, A&A, 395, 1061 (Paper I)
-*
-*   "Representations of spectral coordinates in FITS",
-*   Greisen, E.W., Calabretta, M.R., Valdes, F.G., & Allen, S.L.
-*   2006, A&A, 446, 747 (Paper III)
-*
-* Refer to the README file provided with WCSLIB for an overview of the
-* library.
-*
-*
-* Summary of the spc routines
-* ---------------------------
-* These routines implement the part of the FITS WCS standard that deals with
-* spectral coordinates.  They define methods to be used for computing spectral
-* world coordinates from intermediate world coordinates (a linear
-* transformation of image pixel coordinates), and vice versa.  They are based
-* on the spcprm struct which contains all information needed for the
-* computations.  The struct contains some members that must be set by the
-* user, and others that are maintained by these routines, somewhat like a
-* C++ class but with no encapsulation.
-*
-* Routine spcini() is provided to initialize the spcprm struct with default
-* values, spcfree() reclaims any memory that may have been allocated to store
-* an error message, and spcprt() prints its contents.
-*
-* A setup routine, spcset(), computes intermediate values in the spcprm struct
-* from parameters in it that were supplied by the user.  The struct always
-* needs to be set up by spcset() but it need not be called explicitly - refer
-* to the explanation of spcprm::flag.
-*
-* spcx2s() and spcs2x() implement the WCS spectral coordinate transformations.
-* In fact, they are high level driver routines for the lower level spectral
-* coordinate transformation routines described in spx.h.
-*
-* A number of routines are provided to aid in analysing or synthesising sets
-* of FITS spectral axis keywords:
-*
-*   - spctype() checks a spectral CTYPEia keyword for validity and returns
-*     information derived from it.
-*
-*   - Spectral keyword analysis routine spcspxe() computes the values of the
-*     X-type spectral variables for the S-type variables supplied.
-*
-*   - Spectral keyword synthesis routine, spcxpse(), computes the S-type
-*     variables for the X-types supplied.
-*
-*   - Given a set of spectral keywords, a translation routine, spctrne(),
-*     produces the corresponding set for the specified spectral CTYPEia.
-*
-*   - spcaips() translates AIPS-convention spectral CTYPEia and VELREF
-*     keyvalues.
-*
-* Spectral variable types - S, P, and X:
-* --------------------------------------
-* A few words of explanation are necessary regarding spectral variable types
-* in FITS.
-*
-* Every FITS spectral axis has three associated spectral variables:
-*
-*   S-type: the spectral variable in which coordinates are to be
-*     expressed.  Each S-type is encoded as four characters and is
-*     linearly related to one of four basic types as follows:
-*
-*     F: frequency
-*       'FREQ':  frequency
-*       'AFRQ':  angular frequency
-*       'ENER':  photon energy
-*       'WAVN':  wave number
-*       'VRAD':  radio velocity
-*
-*     W: wavelength in vacuo
-*       'WAVE':  wavelength
-*       'VOPT':  optical velocity
-*       'ZOPT':  redshift
-*
-*     A: wavelength in air
-*       'AWAV':  wavelength in air
-*
-*     V: velocity
-*       'VELO':  relativistic velocity
-*       'BETA':  relativistic beta factor
-*
-*     The S-type forms the first four characters of the CTYPEia keyvalue,
-*     and CRVALia and CDELTia are expressed as S-type quantities so that
-*     they provide a first-order approximation to the S-type variable at
-*     the reference point.
-*
-*     Note that 'AFRQ', angular frequency, is additional to the variables
-*     defined in WCS Paper III.
-*
-*   P-type: the basic spectral variable (F, W, A, or V) with which the
-*     S-type variable is associated (see list above).
-*
-*     For non-grism axes, the P-type is encoded as the eighth character of
-*     CTYPEia.
-*
-*   X-type: the basic spectral variable (F, W, A, or V) for which the
-*     spectral axis is linear, grisms excluded (see below).
-*
-*     For non-grism axes, the X-type is encoded as the sixth character of
-*     CTYPEia.
-*
-*   Grisms: Grism axes have normal S-, and P-types but the axis is linear,
-*     not in any spectral variable, but in a special "grism parameter".
-*     The X-type spectral variable is either W or A for grisms in vacuo or
-*     air respectively, but is encoded as 'w' or 'a' to indicate that an
-*     additional transformation is required to convert to or from the
-*     grism parameter.  The spectral algorithm code for grisms also has a
-*     special encoding in CTYPEia, either 'GRI' (in vacuo) or 'GRA' (in air).
-*
-* In the algorithm chain, the non-linear transformation occurs between the
-* X-type and the P-type variables; the transformation between P-type and
-* S-type variables is always linear.
-*
-* When the P-type and X-type variables are the same, the spectral axis is
-* linear in the S-type variable and the second four characters of CTYPEia
-* are blank.  This can never happen for grism axes.
-*
-* As an example, correlating radio spectrometers always produce spectra that
-* are regularly gridded in frequency; a redshift scale on such a spectrum is
-* non-linear.  The required value of CTYPEia would be 'ZOPT-F2W', where the
-* desired S-type is 'ZOPT' (redshift), the P-type is necessarily 'W'
-* (wavelength), and the X-type is 'F' (frequency) by the nature of the
-* instrument.
-*
-* Argument checking:
-* ------------------
-* The input spectral values are only checked for values that would result in
-* floating point exceptions.  In particular, negative frequencies and
-* wavelengths are allowed, as are velocities greater than the speed of
-* light.  The same is true for the spectral parameters - rest frequency and
-* wavelength.
-*
-* Accuracy:
-* ---------
-* No warranty is given for the accuracy of these routines (refer to the
-* copyright notice); intending users must satisfy for themselves their
-* adequacy for the intended purpose.  However, closure effectively to within
-* double precision rounding error was demonstrated by test routine tspc.c
-* which accompanies this software.
-*
-*
-* spcini() - Default constructor for the spcprm struct
-* ----------------------------------------------------
-* spcini() sets all members of a spcprm struct to default values.  It should
-* be used to initialize every spcprm struct.
-*
-* Given and returned:
-*   spc       struct spcprm*
-*                       Spectral transformation parameters.
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         1: Null spcprm pointer passed.
-*
-*
-* spcfree() - Destructor for the spcprm struct
-* --------------------------------------------
-* spcfree() frees any memory that may have been allocated to store an error
-* message in the spcprm struct.
-*
-* Given:
-*   spc       struct spcprm*
-*                       Spectral transformation parameters.
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         1: Null spcprm pointer passed.
-*
-*
-* spcprt() - Print routine for the spcprm struct
-* ----------------------------------------------
-* spcprt() prints the contents of a spcprm struct using wcsprintf().  Mainly
-* intended for diagnostic purposes.
-*
-* Given:
-*   spc       const struct spcprm*
-*                       Spectral transformation parameters.
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         1: Null spcprm pointer passed.
-*
-*
-* spcset() - Setup routine for the spcprm struct
-* ----------------------------------------------
-* spcset() sets up a spcprm struct according to information supplied within
-* it.
-*
-* Note that this routine need not be called directly; it will be invoked by
-* spcx2s() and spcs2x() if spcprm::flag is anything other than a predefined
-* magic value.
-*
-* Given and returned:
-*   spc       struct spcprm*
-*                       Spectral transformation parameters.
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         1: Null spcprm pointer passed.
-*                         2: Invalid spectral parameters.
-*
-*                       For returns > 1, a detailed error message is set in
-*                       spcprm::err if enabled, see wcserr_enable().
-*
-*
-* spcx2s() - Transform to spectral coordinates
-* --------------------------------------------
-* spcx2s() transforms intermediate world coordinates to spectral coordinates.
-*
-* Given and returned:
-*   spc       struct spcprm*
-*                       Spectral transformation parameters.
-*
-* Given:
-*   nx        int       Vector length.
-*
-*   sx        int       Vector stride.
-*
-*   sspec     int       Vector stride.
-*
-*   x         const double[]
-*                       Intermediate world coordinates, in SI units.
-*
-* Returned:
-*   spec      double[]  Spectral coordinates, in SI units.
-*
-*   stat      int[]     Status return value status for each vector element:
-*                         0: Success.
-*                         1: Invalid value of x.
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         1: Null spcprm pointer passed.
-*                         2: Invalid spectral parameters.
-*                         3: One or more of the x coordinates were invalid,
-*                            as indicated by the stat vector.
-*
-*                       For returns > 1, a detailed error message is set in
-*                       spcprm::err if enabled, see wcserr_enable().
-*
-*
-* spcs2x() - Transform spectral coordinates
-* -----------------------------------------
-* spcs2x() transforms spectral world coordinates to intermediate world
-* coordinates.
-*
-* Given and returned:
-*   spc       struct spcprm*
-*                       Spectral transformation parameters.
-*
-* Given:
-*   nspec     int       Vector length.
-*
-*   sspec     int       Vector stride.
-*
-*   sx        int       Vector stride.
-*
-*   spec      const double[]
-*                       Spectral coordinates, in SI units.
-*
-* Returned:
-*   x         double[]  Intermediate world coordinates, in SI units.
-*
-*   stat      int[]     Status return value status for each vector element:
-*                         0: Success.
-*                         1: Invalid value of spec.
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         1: Null spcprm pointer passed.
-*                         2: Invalid spectral parameters.
-*                         4: One or more of the spec coordinates were
-*                            invalid, as indicated by the stat vector.
-*
-*                       For returns > 1, a detailed error message is set in
-*                       spcprm::err if enabled, see wcserr_enable().
-*
-*
-* spctype() - Spectral CTYPEia keyword analysis
-* ---------------------------------------------
-* spctype() checks whether a CTYPEia keyvalue is a valid spectral axis type
-* and if so returns information derived from it relating to the associated S-,
-* P-, and X-type spectral variables (see explanation above).
-*
-* The return arguments are guaranteed not be modified if CTYPEia is not a
-* valid spectral type; zero-pointers may be specified for any that are not of
-* interest.
-*
-* A deprecated form of this function, spctyp(), lacks the wcserr** parameter.
-*
-* Given:
-*   ctype     const char[9]
-*                       The CTYPEia keyvalue, (eight characters with null
-*                       termination).
-*
-* Returned:
-*   stype     char[]    The four-letter name of the S-type spectral variable
-*                       copied or translated from ctype.  If a non-zero
-*                       pointer is given, the array must accomodate a null-
-*                       terminated string of length 5.
-*
-*   scode     char[]    The three-letter spectral algorithm code copied or
-*                       translated from ctype.  Logarithmic ('LOG') and
-*                       tabular ('TAB') codes are also recognized.  If a
-*                       non-zero pointer is given, the array must accomodate a
-*                       null-terminated string of length 4.
-*
-*   sname     char[]    Descriptive name of the S-type spectral variable.
-*                       If a non-zero pointer is given, the array must
-*                       accomodate a null-terminated string of length 22.
-*
-*   units     char[]    SI units of the S-type spectral variable.  If a
-*                       non-zero pointer is given, the array must accomodate a
-*                       null-terminated string of length 8.
-*
-*   ptype     char*     Character code for the P-type spectral variable
-*                       derived from ctype, one of 'F', 'W', 'A', or 'V'.
-*
-*   xtype     char*     Character code for the X-type spectral variable
-*                       derived from ctype, one of 'F', 'W', 'A', or 'V'.
-*                       Also, 'w' and 'a' are synonymous to 'W' and 'A' for
-*                       grisms in vacuo and air respectively.  Set to 'L' or
-*                       'T' for logarithmic ('LOG') and tabular ('TAB') axes.
-*
-*   restreq   int*      Multivalued flag that indicates whether rest
-*                       frequency or wavelength is required to compute
-*                       spectral variables for this CTYPEia:
-*                         0: Not required.
-*                         1: Required for the conversion between S- and
-*                            P-types (e.g. 'ZOPT-F2W').
-*                         2: Required for the conversion between P- and
-*                            X-types (e.g. 'BETA-W2V').
-*                         3: Required for the conversion between S- and
-*                            P-types, and between P- and X-types, but not
-*                            between S- and X-types (this applies only for
-*                            'VRAD-V2F', 'VOPT-V2W', and 'ZOPT-V2W').
-*                        Thus the rest frequency or wavelength is required for
-*                        spectral coordinate computations (i.e. between S- and
-*                        X-types) only if restreq%3 != 0.
-*
-*   err       struct wcserr **
-*                       For function return values > 1, this struct will
-*                       contain a detailed error message.  May be NULL if an
-*                       error message is not desired.
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         2: Invalid spectral parameters (not a spectral
-*                            CTYPEia).
-*
-*
-* spcspxe() - Spectral keyword analysis
-* ------------------------------------
-* spcspxe() analyses the CTYPEia and CRVALia FITS spectral axis keyword values
-* and returns information about the associated X-type spectral variable.
-*
-* A deprecated form of this function, spcspx(), lacks the wcserr** parameter.
-*
-* Given:
-*   ctypeS    const char[9]
-*                       Spectral axis type, i.e. the CTYPEia keyvalue, (eight
-*                       characters with null termination).  For non-grism
-*                       axes, the character code for the P-type spectral
-*                       variable in the algorithm code (i.e. the eighth
-*                       character of CTYPEia) may be set to '?' (it will not
-*                       be reset).
-*
-*   crvalS    double    Value of the S-type spectral variable at the reference
-*                       point, i.e. the CRVALia keyvalue, SI units.
-*
-*   restfrq,
-*   restwav   double    Rest frequency [Hz] and rest wavelength in vacuo [m],
-*                       only one of which need be given, the other should be
-*                       set to zero.  Neither are required if the translation
-*                       is between wave-characteristic types, or between
-*                       velocity-characteristic types.  E.g., required for
-*                       'FREQ'     -> 'ZOPT-F2W', but not required for
-*                       'VELO-F2V' -> 'ZOPT-F2W'.
-*
-* Returned:
-*   ptype     char*     Character code for the P-type spectral variable
-*                       derived from ctypeS, one of 'F', 'W', 'A', or 'V'.
-*
-*   xtype     char*     Character code for the X-type spectral variable
-*                       derived from ctypeS, one of 'F', 'W', 'A', or 'V'.
-*                       Also, 'w' and 'a' are synonymous to 'W' and 'A' for
-*                       grisms in vacuo and air respectively; crvalX and dXdS
-*                       (see below) will conform to these.
-*
-*   restreq   int*      Multivalued flag that indicates whether rest frequency
-*                       or wavelength is required to compute spectral
-*                       variables for this CTYPEia, as for spctype().
-*
-*   crvalX    double*   Value of the X-type spectral variable at the reference
-*                       point, SI units.
-*
-*   dXdS      double*   The derivative, dX/dS, evaluated at the reference
-*                       point, SI units.  Multiply the CDELTia keyvalue by
-*                       this to get the pixel spacing in the X-type spectral
-*                       coordinate.
-*
-*   err       struct wcserr **
-*                       For function return values > 1, this struct will
-*                       contain a detailed error message.  May be NULL if an
-*                       error message is not desired.
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         2: Invalid spectral parameters.
-*
-*
-* spcxpse() - Spectral keyword synthesis
-* -------------------------------------
-* spcxpse(), for the spectral axis type specified and the value provided for
-* the X-type spectral variable at the reference point, deduces the value of
-* the FITS spectral axis keyword CRVALia and also the derivative dS/dX which
-* may be used to compute CDELTia.  See above for an explanation of the S-,
-* P-, and X-type spectral variables.
-*
-* A deprecated form of this function, spcxps(), lacks the wcserr** parameter.
-*
-* Given:
-*   ctypeS    const char[9]
-*                       The required spectral axis type, i.e. the CTYPEia
-*                       keyvalue, (eight characters with null termination).
-*                       For non-grism axes, the character code for the P-type
-*                       spectral variable in the algorithm code (i.e. the
-*                       eighth character of CTYPEia) may be set to '?' (it
-*                       will not be reset).
-*
-*   crvalX    double    Value of the X-type spectral variable at the reference
-*                       point (N.B. NOT the CRVALia keyvalue), SI units.
-*
-*   restfrq,
-*   restwav   double    Rest frequency [Hz] and rest wavelength in vacuo [m],
-*                       only one of which need be given, the other should be
-*                       set to zero.  Neither are required if the translation
-*                       is between wave-characteristic types, or between
-*                       velocity-characteristic types.  E.g., required for
-*                       'FREQ'     -> 'ZOPT-F2W', but not required for
-*                       'VELO-F2V' -> 'ZOPT-F2W'.
-*
-* Returned:
-*   ptype     char*     Character code for the P-type spectral variable
-*                       derived from ctypeS, one of 'F', 'W', 'A', or 'V'.
-*
-*   xtype     char*     Character code for the X-type spectral variable
-*                       derived from ctypeS, one of 'F', 'W', 'A', or 'V'.
-*                       Also, 'w' and 'a' are synonymous to 'W' and 'A' for
-*                       grisms; crvalX and cdeltX must conform to these.
-*
-*   restreq   int*      Multivalued flag that indicates whether rest frequency
-*                       or wavelength is required to compute spectral
-*                       variables for this CTYPEia, as for spctype().
-*
-*   crvalS    double*   Value of the S-type spectral variable at the reference
-*                       point (i.e. the appropriate CRVALia keyvalue), SI
-*                       units.
-*
-*   dSdX      double*   The derivative, dS/dX, evaluated at the reference
-*                       point, SI units.  Multiply this by the pixel spacing
-*                       in the X-type spectral coordinate to get the CDELTia
-*                       keyvalue.
-*
-*   err       struct wcserr **
-*                       For function return values > 1, this struct will
-*                       contain a detailed error message.  May be NULL if an
-*                       error message is not desired.
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         2: Invalid spectral parameters.
-*
-*
-* spctrne() - Spectral keyword translation
-* ---------------------------------------
-* spctrne() translates a set of FITS spectral axis keywords into the
-* corresponding set for the specified spectral axis type.  For example, a
-* 'FREQ' axis may be translated into 'ZOPT-F2W' and vice versa.
-*
-* A deprecated form of this function, spctrn(), lacks the wcserr** parameter.
-*
-* Given:
-*   ctypeS1   const char[9]
-*                       Spectral axis type, i.e. the CTYPEia keyvalue, (eight
-*                       characters with null termination).  For non-grism
-*                       axes, the character code for the P-type spectral
-*                       variable in the algorithm code (i.e. the eighth
-*                       character of CTYPEia) may be set to '?' (it will not
-*                       be reset).
-*
-*   crvalS1   double    Value of the S-type spectral variable at the reference
-*                       point, i.e. the CRVALia keyvalue, SI units.
-*
-*   cdeltS1   double    Increment of the S-type spectral variable at the
-*                       reference point, SI units.
-*
-*   restfrq,
-*   restwav   double    Rest frequency [Hz] and rest wavelength in vacuo [m],
-*                       only one of which need be given, the other should be
-*                       set to zero.  Neither are required if the translation
-*                       is between wave-characteristic types, or between
-*                       velocity-characteristic types.  E.g., required for
-*                       'FREQ'     -> 'ZOPT-F2W', but not required for
-*                       'VELO-F2V' -> 'ZOPT-F2W'.
-*
-* Given and returned:
-*   ctypeS2   char[9]   Required spectral axis type (eight characters with
-*                       null termination).  The first four characters are
-*                       required to be given and are never modified.  The
-*                       remaining four, the algorithm code, are completely
-*                       determined by, and must be consistent with, ctypeS1
-*                       and the first four characters of ctypeS2.  A non-zero
-*                       status value will be returned if they are inconsistent
-*                       (see below).  However, if the final three characters
-*                       are specified as "???", or if just the eighth
-*                       character is specified as '?', the correct algorithm
-*                       code will be substituted (applies for grism axes as
-*                       well as non-grism).
-*
-* Returned:
-*   crvalS2   double*   Value of the new S-type spectral variable at the
-*                       reference point, i.e. the new CRVALia keyvalue, SI
-*                       units.
-*
-*   cdeltS2   double*   Increment of the new S-type spectral variable at the
-*                       reference point, i.e. the new CDELTia keyvalue, SI
-*                       units.
-*
-*   err       struct wcserr **
-*                       For function return values > 1, this struct will
-*                       contain a detailed error message.  May be NULL if an
-*                       error message is not desired.
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         2: Invalid spectral parameters.
-*
-*                       A status value of 2 will be returned if restfrq or
-*                       restwav are not specified when required, or if ctypeS1
-*                       or ctypeS2 are self-inconsistent, or have different
-*                       spectral X-type variables.
-*
-*
-* spcaips() - Translate AIPS-convention spectral keywords
-* -------------------------------------------------------
-* spcaips() translates AIPS-convention spectral CTYPEia and VELREF keyvalues.
-*
-* Given:
-*   ctypeA    const char[9]
-*                       CTYPEia keyvalue possibly containing an
-*                       AIPS-convention spectral code (eight characters, need
-*                       not be null-terminated).
-*
-*   velref    int       AIPS-convention VELREF code.  It has the following
-*                       integer values:
-*                         1: LSR kinematic, originally described simply as
-*                            "LSR" without distinction between the kinematic
-*                            and dynamic definitions.
-*                         2: Barycentric, originally described as "HEL"
-*                            meaning heliocentric.
-*                         3: Topocentric, originally described as "OBS"
-*                            meaning geocentric but widely interpreted as
-*                            topocentric.
-*                       AIPS++ extensions to VELREF are also recognized:
-*                         4: LSR dynamic.
-*                         5: Geocentric.
-*                         6: Source rest frame.
-*                         7: Galactocentric.
-*
-*                       For an AIPS 'VELO' axis, a radio convention velocity
-*                       (VRAD) is denoted by adding 256 to VELREF, otherwise
-*                       an optical velocity (VOPT) is indicated (this is not
-*                       applicable to 'FREQ' or 'FELO' axes).  Setting velref
-*                       to 0 or 256 chooses between optical and radio velocity
-*                       without specifying a Doppler frame, provided that a
-*                       frame is encoded in ctypeA.  If not, i.e. for
-*                       ctypeA = 'VELO', ctype will be returned as 'VELO'.
-*
-*                       VELREF takes precedence over CTYPEia in defining the
-*                       Doppler frame, e.g.
-*
-=                         ctypeA = 'VELO-HEL'
-=                         velref = 1
-*
-*                       returns ctype = 'VOPT' with specsys set to 'LSRK'.
-*
-* Returned:
-*   ctype     char[9]   Translated CTYPEia keyvalue, or a copy of ctypeA if no
-*                       translation was performed (in which case any trailing
-*                       blanks in ctypeA will be replaced with nulls).
-*
-*   specsys   char[9]   Doppler reference frame indicated by VELREF or else
-*                       by CTYPEia with value corresponding to the SPECSYS
-*                       keyvalue in the FITS WCS standard.  May be returned
-*                       blank if neither specifies a Doppler frame, e.g.
-*                       ctypeA = 'FELO' and velref%256 == 0.
-*
-* Function return value:
-*             int       Status return value:
-*                        -1: No translation required (not an error).
-*                         0: Success.
-*                         2: Invalid value of VELREF.
-*
-*
-* spcprm struct - Spectral transformation parameters
-* --------------------------------------------------
-* The spcprm struct contains information required to transform spectral
-* coordinates.  It consists of certain members that must be set by the user
-* ("given") and others that are set by the WCSLIB routines ("returned").  Some
-* of the latter are supplied for informational purposes while others are for
-* internal use only.
-*
-*   int flag
-*     (Given and returned) This flag must be set to zero whenever any of the
-*     following spcprm structure members are set or changed:
-*
-*       - spcprm::type,
-*       - spcprm::code,
-*       - spcprm::crval,
-*       - spcprm::restfrq,
-*       - spcprm::restwav,
-*       - spcprm::pv[].
-*
-*     This signals the initialization routine, spcset(), to recompute the
-*     returned members of the spcprm struct.  spcset() will reset flag to
-*     indicate that this has been done.
-*
-*   char type[8]
-*     (Given) Four-letter spectral variable type, e.g "ZOPT" for
-*     CTYPEia = 'ZOPT-F2W'.  (Declared as char[8] for alignment reasons.)
-*
-*   char code[4]
-*     (Given) Three-letter spectral algorithm code, e.g "F2W" for
-*     CTYPEia = 'ZOPT-F2W'.
-*
-*   double crval
-*     (Given) Reference value (CRVALia), SI units.
-*
-*   double restfrq
-*     (Given) The rest frequency [Hz], and ...
-*
-*   double restwav
-*     (Given) ... the rest wavelength in vacuo [m], only one of which need be
-*     given, the other should be set to zero.  Neither are required if the
-*     X and S spectral variables are both wave-characteristic, or both
-*     velocity-characteristic, types.
-*
-*   double pv[7]
-*     (Given) Grism parameters for 'GRI' and 'GRA' algorithm codes:
-*       - 0: G, grating ruling density.
-*       - 1: m, interference order.
-*       - 2: alpha, angle of incidence [deg].
-*       - 3: n_r, refractive index at the reference wavelength, lambda_r.
-*       - 4: n'_r, dn/dlambda at the reference wavelength, lambda_r (/m).
-*       - 5: epsilon, grating tilt angle [deg].
-*       - 6: theta, detector tilt angle [deg].
-*
-* The remaining members of the spcprm struct are maintained by spcset() and
-* must not be modified elsewhere:
-*
-*   double w[6]
-*     (Returned) Intermediate values:
-*       - 0: Rest frequency or wavelength (SI).
-*       - 1: The value of the X-type spectral variable at the reference point
-*           (SI units).
-*       - 2: dX/dS at the reference point (SI units).
-*      The remainder are grism intermediates.
-*
-*   int isGrism
-*     (Returned) Grism coordinates?
-*       - 0: no,
-*       - 1: in vacuum,
-*       - 2: in air.
-*
-*   int padding1
-*     (An unused variable inserted for alignment purposes only.)
-*
-*   struct wcserr *err
-*     (Returned) If enabled, when an error status is returned this structure
-*     contains detailed information about the error, see wcserr_enable().
-*
-*   void *padding2
-*     (An unused variable inserted for alignment purposes only.)
-*   int (*spxX2P)(SPX_ARGS)
-*     (Returned) The first and ...
-*   int (*spxP2S)(SPX_ARGS)
-*     (Returned) ... the second of the pointers to the transformation
-*     functions in the two-step algorithm chain X -> P -> S in the
-*     pixel-to-spectral direction where the non-linear transformation is from
-*     X to P.  The argument list, SPX_ARGS, is defined in spx.h.
-*
-*   int (*spxS2P)(SPX_ARGS)
-*     (Returned) The first and ...
-*   int (*spxP2X)(SPX_ARGS)
-*     (Returned) ... the second of the pointers to the transformation
-*     functions in the two-step algorithm chain S -> P -> X in the
-*     spectral-to-pixel direction where the non-linear transformation is from
-*     P to X.  The argument list, SPX_ARGS, is defined in spx.h.
-*
-*
-* Global variable: const char *spc_errmsg[] - Status return messages
-* ------------------------------------------------------------------
-* Error messages to match the status value returned from each function.
-*
-*===========================================================================*/
-
-#ifndef WCSLIB_SPC
-#define WCSLIB_SPC
-
-#include "spx.h"
-#include "wcserr.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-extern const char *spc_errmsg[];
-
-enum spc_errmsg_enum {
-  SPCERR_NO_CHANGE       = -1,	/* No change. */
-  SPCERR_SUCCESS         =  0,	/* Success. */
-  SPCERR_NULL_POINTER    =  1,	/* Null spcprm pointer passed. */
-  SPCERR_BAD_SPEC_PARAMS =  2,	/* Invalid spectral parameters. */
-  SPCERR_BAD_X           =  3,	/* One or more of x coordinates were
-				   invalid. */
-  SPCERR_BAD_SPEC        =  4 	/* One or more of the spec coordinates were
-				   invalid. */
-};
-
-struct spcprm {
-  /* Initialization flag (see the prologue above).                          */
-  /*------------------------------------------------------------------------*/
-  int    flag;			/* Set to zero to force initialization.     */
-
-  /* Parameters to be provided (see the prologue above).                    */
-  /*------------------------------------------------------------------------*/
-  char   type[8];		/* Four-letter spectral variable type.      */
-  char   code[4];		/* Three-letter spectral algorithm code.    */
-
-  double crval;			/* Reference value (CRVALia), SI units.     */
-  double restfrq;		/* Rest frequency, Hz.                      */
-  double restwav;		/* Rest wavelength, m.                      */
-
-  double pv[7];			/* Grism parameters:                        */
-				/*   0: G, grating ruling density.          */
-				/*   1: m, interference order.              */
-				/*   2: alpha, angle of incidence.          */
-				/*   3: n_r, refractive index at lambda_r.  */
-				/*   4: n'_r, dn/dlambda at lambda_r.       */
-				/*   5: epsilon, grating tilt angle.        */
-				/*   6: theta, detector tilt angle.         */
-
-  /* Information derived from the parameters supplied.                      */
-  /*------------------------------------------------------------------------*/
-  double w[6];			/* Intermediate values.                     */
-				/*   0: Rest frequency or wavelength (SI).  */
-				/*   1: CRVALX (SI units).                  */
-				/*   2: CDELTX/CDELTia = dX/dS (SI units).  */
-				/* The remainder are grism intermediates.   */
-
-  int    isGrism;		/* Grism coordinates?  1: vacuum, 2: air.   */
-  int    padding1;		/* (Dummy inserted for alignment purposes.) */
-
-  /* Error handling                                                         */
-  /*------------------------------------------------------------------------*/
-  struct wcserr *err;
-
-  /* Private                                                                */
-  /*------------------------------------------------------------------------*/
-  void   *padding2;		/* (Dummy inserted for alignment purposes.) */
-  int (*spxX2P)(SPX_ARGS);	/* Pointers to the transformation functions */
-  int (*spxP2S)(SPX_ARGS);	/* in the two-step algorithm chain in the   */
-				/* pixel-to-spectral direction.             */
-
-  int (*spxS2P)(SPX_ARGS);	/* Pointers to the transformation functions */
-  int (*spxP2X)(SPX_ARGS);	/* in the two-step algorithm chain in the   */
-				/* spectral-to-pixel direction.             */
-};
-
-/* Size of the spcprm struct in int units, used by the Fortran wrappers. */
-#define SPCLEN (sizeof(struct spcprm)/sizeof(int))
-
-
-int spcini(struct spcprm *spc);
-
-int spcfree(struct spcprm *spc);
-
-int spcprt(const struct spcprm *spc);
-
-int spcset(struct spcprm *spc);
-
-int spcx2s(struct spcprm *spc, int nx, int sx, int sspec,
-           const double x[], double spec[], int stat[]);
-
-int spcs2x(struct spcprm *spc, int nspec, int sspec, int sx,
-           const double spec[], double x[], int stat[]);
-
-int spctype(const char ctype[], char stype[], char scode[], char sname[],
-            char units[], char *ptype, char *xtype, int *restreq,
-            struct wcserr **err);
-
-int spcspxe(const char ctypeS[], double crvalS, double restfrq,
-            double restwav, char *ptype, char *xtype, int *restreq,
-            double *crvalX, double *dXdS, struct wcserr **err);
-
-int spcxpse(const char ctypeS[], double crvalX, double restfrq,
-            double restwav, char *ptype, char *xtype, int *restreq,
-            double *crvalS, double *dSdX, struct wcserr **err);
-
-int spctrne(const char ctypeS1[], double crvalS1, double cdeltS1,
-            double restfrq, double restwav, char ctypeS2[], double *crvalS2,
-            double *cdeltS2, struct wcserr **err);
-
-int spcaips(const char ctypeA[], int velref, char ctype[], char specsys[]);
-
-
-/* Deprecated. */
-#define spcini_errmsg spc_errmsg
-#define spcprt_errmsg spc_errmsg
-#define spcset_errmsg spc_errmsg
-#define spcx2s_errmsg spc_errmsg
-#define spcs2x_errmsg spc_errmsg
-
-int spctyp(const char ctype[], char stype[], char scode[], char sname[],
-           char units[], char *ptype, char *xtype, int *restreq);
-int spcspx(const char ctypeS[], double crvalS, double restfrq, double restwav,
-           char *ptype, char *xtype, int *restreq, double *crvalX,
-           double *dXdS);
-int spcxps(const char ctypeS[], double crvalX, double restfrq, double restwav,
-           char *ptype, char *xtype, int *restreq, double *crvalS,
-           double *dSdX);
-int spctrn(const char ctypeS1[], double crvalS1, double cdeltS1,
-           double restfrq, double restwav, char ctypeS2[], double *crvalS2,
-           double *cdeltS2);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* WCSLIB_SPC */
diff --git a/astropy/wcs/src/wcslib/C/sph.c b/astropy/wcs/src/wcslib/C/sph.c
deleted file mode 100644
index 0ad4518..0000000
--- a/astropy/wcs/src/wcslib/C/sph.c
+++ /dev/null
@@ -1,466 +0,0 @@
-/*============================================================================
-
-  WCSLIB 4.10 - an implementation of the FITS WCS standard.
-  Copyright (C) 1995-2012, Mark Calabretta
-
-  This file is part of WCSLIB.
-
-  WCSLIB is free software: you can redistribute it and/or modify it under the
-  terms of the GNU Lesser General Public License as published by the Free
-  Software Foundation, either version 3 of the License, or (at your option)
-  any later version.
-
-  WCSLIB 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 Lesser General Public License for
-  more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with WCSLIB.  If not, see <http://www.gnu.org/licenses/>.
-
-  Correspondence concerning WCSLIB may be directed to:
-    Internet email: mcalabre at atnf.csiro.au
-    Postal address: Dr. Mark Calabretta
-                    Australia Telescope National Facility, CSIRO
-                    PO Box 76
-                    Epping NSW 1710
-                    AUSTRALIA
-
-  Author: Mark Calabretta, Australia Telescope National Facility
-  http://www.atnf.csiro.au/~mcalabre/index.html
-  $Id: sph.c,v 4.10 2012/02/05 23:41:44 cal103 Exp $
-*===========================================================================*/
-
-#include <math.h>
-#include "wcstrig.h"
-#include "sph.h"
-
-#define copysign(X, Y) ((Y) < 0.0 ? -fabs(X) : fabs(X))
-
-#define tol 1.0e-5
-
-/*--------------------------------------------------------------------------*/
-
-int sphx2s(
-  const double eul[5],
-  int nphi,
-  int ntheta,
-  int spt,
-  int sll,
-  const double phi[],
-  const double theta[],
-  double lng[],
-  double lat[])
-
-{
-  int mphi, mtheta, rowlen, rowoff;
-  double cosphi, costhe, costhe3, costhe4, dlng, dphi, sinphi, sinthe,
-         sinthe3, sinthe4, x, y, z;
-  register int iphi, itheta;
-  register const double *phip, *thetap;
-  register double *latp, *lngp;
-
-  if (ntheta > 0) {
-    mphi   = nphi;
-    mtheta = ntheta;
-  } else {
-    mphi   = 1;
-    mtheta = 1;
-    ntheta = nphi;
-  }
-
-
-  /* Check for a simple change in origin of longitude. */
-  if (eul[4] == 0.0) {
-    if (eul[1] == 0.0) {
-      dlng = fmod(eul[0] + 180.0 - eul[2], 360.0);
-
-      lngp = lng;
-      latp = lat;
-      phip   = phi;
-      thetap = theta;
-      for (itheta = 0; itheta < ntheta; itheta++) {
-        for (iphi = 0; iphi < mphi; iphi++) {
-          *lngp = *phip + dlng;
-          *latp = *thetap;
-
-          /* Normalize the celestial longitude. */
-          if (eul[0] >= 0.0) {
-            if (*lngp < 0.0) *lngp += 360.0;
-          } else {
-            if (*lngp > 0.0) *lngp -= 360.0;
-          }
-
-          if (*lngp > 360.0) {
-            *lngp -= 360.0;
-          } else if (*lngp < -360.0) {
-            *lngp += 360.0;
-          }
-
-          lngp   += sll;
-          latp   += sll;
-          phip   += spt;
-          thetap += spt;
-        }
-      }
-
-    } else {
-      dlng = fmod(eul[0] + eul[2], 360.0);
-
-      lngp = lng;
-      latp = lat;
-      phip   = phi;
-      thetap = theta;
-      for (itheta = 0; itheta < ntheta; itheta++) {
-        for (iphi = 0; iphi < mphi; iphi++) {
-          *lngp = dlng - *phip;
-          *latp = -(*thetap);
-
-          /* Normalize the celestial longitude. */
-          if (eul[0] >= 0.0) {
-            if (*lngp < 0.0) *lngp += 360.0;
-          } else {
-            if (*lngp > 0.0) *lngp -= 360.0;
-          }
-
-          if (*lngp > 360.0) {
-            *lngp -= 360.0;
-          } else if (*lngp < -360.0) {
-            *lngp += 360.0;
-          }
-
-          lngp   += sll;
-          latp   += sll;
-          phip   += spt;
-          thetap += spt;
-        }
-      }
-    }
-
-    return 0;
-  }
-
-
-  /* Do phi dependency. */
-  phip = phi;
-  rowoff = 0;
-  rowlen = nphi*sll;
-  for (iphi = 0; iphi < nphi; iphi++, rowoff += sll, phip += spt) {
-    dphi = *phip - eul[2];
-
-    lngp = lng + rowoff;
-    for (itheta = 0; itheta < mtheta; itheta++) {
-      *lngp = dphi;
-      lngp += rowlen;
-    }
-  }
-
-
-  /* Do theta dependency. */
-  thetap = theta;
-  lngp = lng;
-  latp = lat;
-  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
-    sincosd(*thetap, &sinthe, &costhe);
-    costhe3 = costhe*eul[3];
-    costhe4 = costhe*eul[4];
-    sinthe3 = sinthe*eul[3];
-    sinthe4 = sinthe*eul[4];
-
-    for (iphi = 0; iphi < mphi; iphi++, lngp += sll, latp += sll) {
-      dphi = *lngp;
-      sincosd(dphi, &sinphi, &cosphi);
-
-      /* Compute the celestial longitude. */
-      x = sinthe4 - costhe3*cosphi;
-      if (fabs(x) < tol) {
-        /* Rearrange formula to reduce roundoff errors. */
-        x = -cosd(*thetap + eul[1]) + costhe3*(1.0 - cosphi);
-      }
-
-      y = -costhe*sinphi;
-      if (x != 0.0 || y != 0.0) {
-        dlng = atan2d(y, x);
-      } else {
-        /* Change of origin of longitude. */
-        if (eul[1] < 90.0) {
-          dlng =  dphi + 180.0;
-        } else {
-          dlng = -dphi;
-        }
-      }
-      *lngp = eul[0] + dlng;
-
-      /* Normalize the celestial longitude. */
-      if (eul[0] >= 0.0) {
-        if (*lngp < 0.0) *lngp += 360.0;
-      } else {
-        if (*lngp > 0.0) *lngp -= 360.0;
-      }
-
-      if (*lngp > 360.0) {
-        *lngp -= 360.0;
-      } else if (*lngp < -360.0) {
-        *lngp += 360.0;
-      }
-
-      /* Compute the celestial latitude. */
-      if (fmod(dphi,180.0) == 0.0) {
-        *latp = *thetap + cosphi*eul[1];
-        if (*latp >  90.0) *latp =  180.0 - *latp;
-        if (*latp < -90.0) *latp = -180.0 - *latp;
-      } else {
-        z = sinthe3 + costhe4*cosphi;
-        if (fabs(z) > 0.99) {
-          /* Use an alternative formula for greater accuracy. */
-          *latp = copysign(acosd(sqrt(x*x+y*y)), z);
-        } else {
-          *latp = asind(z);
-        }
-      }
-    }
-  }
-
-  return 0;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int sphs2x(
-  const double eul[5],
-  int nlng,
-  int nlat,
-  int sll,
-  int spt,
-  const double lng[],
-  const double lat[],
-  double phi[],
-  double theta[])
-
-{
-  int mlat, mlng, rowlen, rowoff;
-  double coslat, coslat3, coslat4, coslng, dlng, dphi, sinlat, sinlat3,
-         sinlat4, sinlng, x, y, z;
-  register int ilat, ilng;
-  register const double *latp, *lngp;
-  register double *phip, *thetap;
-
-  if (nlat > 0) {
-    mlng = nlng;
-    mlat = nlat;
-  } else {
-    mlng = 1;
-    mlat = 1;
-    nlat = nlng;
-  }
-
-
-  /* Check for a simple change in origin of longitude. */
-  if (eul[4] == 0.0) {
-    if (eul[1] == 0.0) {
-      dphi = fmod(eul[2] - 180.0 - eul[0], 360.0);
-
-      lngp = lng;
-      latp = lat;
-      phip   = phi;
-      thetap = theta;
-      for (ilat = 0; ilat < nlat; ilat++) {
-        for (ilng = 0; ilng < mlng; ilng++) {
-          *phip = fmod(*lngp + dphi, 360.0);
-          *thetap = *latp;
-
-          /* Normalize the native longitude. */
-          if (*phip > 180.0) {
-            *phip -= 360.0;
-          } else if (*phip < -180.0) {
-            *phip += 360.0;
-          }
-
-          phip   += spt;
-          thetap += spt;
-          lngp   += sll;
-          latp   += sll;
-        }
-      }
-
-    } else {
-      dphi = fmod(eul[2] + eul[0], 360.0);
-
-      lngp = lng;
-      latp = lat;
-      phip   = phi;
-      thetap = theta;
-      for (ilat = 0; ilat < nlat; ilat++) {
-        for (ilng = 0; ilng < mlng; ilng++) {
-          *phip = fmod(dphi - *lngp, 360.0);
-          *thetap = -(*latp);
-
-          /* Normalize the native longitude. */
-          if (*phip > 180.0) {
-            *phip -= 360.0;
-          } else if (*phip < -180.0) {
-            *phip += 360.0;
-          }
-
-          phip   += spt;
-          thetap += spt;
-          lngp   += sll;
-          latp   += sll;
-        }
-      }
-    }
-
-    return 0;
-  }
-
-
-  /* Do lng dependency. */
-  lngp = lng;
-  rowoff = 0;
-  rowlen = nlng*spt;
-  for (ilng = 0; ilng < nlng; ilng++, rowoff += spt, lngp += sll) {
-    dlng = *lngp - eul[0];
-
-    phip = phi + rowoff;
-    thetap = theta;
-    for (ilat = 0; ilat < mlat; ilat++) {
-      *phip = dlng;
-      phip += rowlen;
-    }
-  }
-
-
-  /* Do lat dependency. */
-  latp = lat;
-  phip   = phi;
-  thetap = theta;
-  for (ilat = 0; ilat < nlat; ilat++, latp += sll) {
-    sincosd(*latp, &sinlat, &coslat);
-    coslat3 = coslat*eul[3];
-    coslat4 = coslat*eul[4];
-    sinlat3 = sinlat*eul[3];
-    sinlat4 = sinlat*eul[4];
-
-    for (ilng = 0; ilng < mlng; ilng++, phip += spt, thetap += spt) {
-      dlng = *phip;
-      sincosd(dlng, &sinlng, &coslng);
-
-      /* Compute the native longitude. */
-      x = sinlat4 - coslat3*coslng;
-      if (fabs(x) < tol) {
-        /* Rearrange formula to reduce roundoff errors. */
-        x = -cosd(*latp+eul[1]) + coslat3*(1.0 - coslng);
-      }
-
-      y = -coslat*sinlng;
-      if (x != 0.0 || y != 0.0) {
-        dphi = atan2d(y, x);
-      } else {
-        /* Change of origin of longitude. */
-        if (eul[1] < 90.0) {
-          dphi =  dlng - 180.0;
-        } else {
-          dphi = -dlng;
-        }
-      }
-      *phip = fmod(eul[2] + dphi, 360.0);
-
-      /* Normalize the native longitude. */
-      if (*phip > 180.0) {
-        *phip -= 360.0;
-      } else if (*phip < -180.0) {
-        *phip += 360.0;
-      }
-
-      /* Compute the native latitude. */
-      if (fmod(dlng,180.0) == 0.0) {
-        *thetap = *latp + coslng*eul[1];
-        if (*thetap >  90.0) *thetap =  180.0 - *thetap;
-        if (*thetap < -90.0) *thetap = -180.0 - *thetap;
-      } else {
-        z = sinlat3 + coslat4*coslng;
-        if (fabs(z) > 0.99) {
-          /* Use an alternative formula for greater accuracy. */
-          *thetap = copysign(acosd(sqrt(x*x+y*y)), z);
-        } else {
-          *thetap = asind(z);
-        }
-      }
-    }
-  }
-
-  return 0;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int sphdpa(
-  int nfield,
-  double lng0,
-  double lat0,
-  const double lng[],
-  const double lat[],
-  double dist[],
-  double pa[])
-
-{
-  int i;
-  double eul[5];
-
-  /* Set the Euler angles for the coordinate transformation. */
-  eul[0] = lng0;
-  eul[1] = 90.0 - lat0;
-  eul[2] = 0.0;
-  eul[3] = cosd(eul[1]);
-  eul[4] = sind(eul[1]);
-
-  /* Transform field points to the new system. */
-  sphs2x(eul, nfield, 0, 1, 1, lng, lat, pa, dist);
-
-  for (i = 0; i < nfield; i++) {
-    /* Angular distance is obtained from latitude in the new frame. */
-    dist[i] = 90.0 - dist[i];
-
-    /* Position angle is obtained from longitude in the new frame. */
-    pa[i] = -pa[i];
-    if (pa[i] < -180.0) pa[i] += 360.0;
-  }
-
-  return 0;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int sphpad(
-  int nfield,
-  double lng0,
-  double lat0,
-  const double dist[],
-  const double pa[],
-  double lng[],
-  double lat[])
-
-{
-  int i;
-  double eul[5];
-
-  /* Set the Euler angles for the coordinate transformation. */
-  eul[0] = lng0;
-  eul[1] = 90.0 - lat0;
-  eul[2] = 0.0;
-  eul[3] = cosd(eul[1]);
-  eul[4] = sind(eul[1]);
-
-  for (i = 0; i < nfield; i++) {
-    /* Latitude in the new frame is obtained from angular distance. */
-    lat[i] = 90.0 - dist[i];
-
-    /* Longitude in the new frame is obtained from position angle. */
-    lng[i] = -pa[i];
-  }
-
-  /* Transform field points to the old system. */
-  sphx2s(eul, nfield, 0, 1, 1, lng, lat, lng, lat);
-
-  return 0;
-}
diff --git a/astropy/wcs/src/wcslib/C/sph.h b/astropy/wcs/src/wcslib/C/sph.h
deleted file mode 100644
index 30b615d..0000000
--- a/astropy/wcs/src/wcslib/C/sph.h
+++ /dev/null
@@ -1,257 +0,0 @@
-/*============================================================================
-
-  WCSLIB 4.10 - an implementation of the FITS WCS standard.
-  Copyright (C) 1995-2012, Mark Calabretta
-
-  This file is part of WCSLIB.
-
-  WCSLIB is free software: you can redistribute it and/or modify it under the
-  terms of the GNU Lesser General Public License as published by the Free
-  Software Foundation, either version 3 of the License, or (at your option)
-  any later version.
-
-  WCSLIB 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 Lesser General Public License for
-  more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with WCSLIB.  If not, see <http://www.gnu.org/licenses/>.
-
-  Correspondence concerning WCSLIB may be directed to:
-    Internet email: mcalabre at atnf.csiro.au
-    Postal address: Dr. Mark Calabretta
-                    Australia Telescope National Facility, CSIRO
-                    PO Box 76
-                    Epping NSW 1710
-                    AUSTRALIA
-
-  Author: Mark Calabretta, Australia Telescope National Facility
-  http://www.atnf.csiro.au/~mcalabre/index.html
-  $Id: sph.h,v 4.10 2012/02/05 23:41:44 cal103 Exp $
-*=============================================================================
-*
-* WCSLIB 4.10 - C routines that implement the spherical coordinate
-* transformations used by the FITS World Coordinate System (WCS) standard.
-* Refer to
-*
-*   "Representations of world coordinates in FITS",
-*   Greisen, E.W., & Calabretta, M.R. 2002, A&A, 395, 1061 (Paper I)
-*
-*   "Representations of celestial coordinates in FITS",
-*   Calabretta, M.R., & Greisen, E.W. 2002, A&A, 395, 1077 (Paper II)
-*
-* Refer to the README file provided with WCSLIB for an overview of the
-* library.
-*
-*
-* Summary of the sph routines
-* ---------------------------
-* The WCS spherical coordinate transformations are implemented via separate
-* functions, sphx2s() and sphs2x(), for the transformation in each direction.
-*
-* A utility function, sphdpa(), computes the angular distances and position
-* angles from a given point on the sky to a number of other points.  sphpad()
-* does the complementary operation - computes the coordinates of points offset
-* by the given angular distances and position angles from a given point on the
-* sky.
-*
-*
-* sphx2s() - Rotation in the pixel-to-world direction
-* ---------------------------------------------------
-* sphx2s() transforms native coordinates of a projection to celestial
-* coordinates.
-*
-* Given:
-*   eul       const double[5]
-*                       Euler angles for the transformation:
-*                         0: Celestial longitude of the native pole [deg].
-*                         1: Celestial colatitude of the native pole, or
-*                            native colatitude of the celestial pole [deg].
-*                         2: Native longitude of the celestial pole [deg].
-*                         3: cos(eul[1])
-*                         4: sin(eul[1])
-*
-*   nphi,
-*   ntheta    int       Vector lengths.
-*
-*   spt,sxy   int       Vector strides.
-*
-*   phi,theta const double[]
-*                       Longitude and latitude in the native coordinate
-*                       system of the projection [deg].
-*
-* Returned:
-*   lng,lat   double[]  Celestial longitude and latitude [deg].  These may
-*                       refer to the same storage as phi and theta
-*                       respectively.
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*
-*
-* sphs2x() - Rotation in the world-to-pixel direction
-* ---------------------------------------------------
-* sphs2x() transforms celestial coordinates to the native coordinates of a
-* projection.
-*
-* Given:
-*   eul       const double[5]
-*                       Euler angles for the transformation:
-*                         0: Celestial longitude of the native pole [deg].
-*                         1: Celestial colatitude of the native pole, or
-*                            native colatitude of the celestial pole [deg].
-*                         2: Native longitude of the celestial pole [deg].
-*                         3: cos(eul[1])
-*                         4: sin(eul[1])
-*
-*   nlng,nlat int       Vector lengths.
-*
-*   sll,spt   int       Vector strides.
-*
-*   lng,lat   const double[]
-*                       Celestial longitude and latitude [deg].
-*
-* Returned:
-*   phi,theta double[]  Longitude and latitude in the native coordinate system
-*                       of the projection [deg].  These may refer to the same
-*                       storage as lng and lat respectively.
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*
-*
-* sphdpa() - Compute angular distance and position angle
-* ------------------------------------------------------
-* sphdpa() computes the angular distance and generalized position angle (see
-* notes) from a "reference" point to a number of "field" points on the sphere.
-* The points must be specified consistently in any spherical coordinate
-* system.
-*
-* sphdpa() is complementary to sphpad().
-*
-* Given:
-*   nfield    int       The number of field points.
-*
-*   lng0,lat0 double    Spherical coordinates of the reference point [deg].
-*
-*   lng,lat   const double[]
-*                       Spherical coordinates of the field points [deg].
-*
-* Returned:
-*   dist,pa   double[]  Angular distances and position angles [deg].  These
-*                       may refer to the same storage as lng and lat
-*                       respectively.
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*
-* Notes:
-*   sphdpa() uses sphs2x() to rotate coordinates so that the reference point
-*   is at the north pole of the new system with the north pole of the old
-*   system at zero longitude in the new.  The Euler angles required by
-*   sphs2x() for this rotation are
-*
-=     eul[0] = lng0;
-=     eul[1] = 90.0 - lat0;
-=     eul[2] =  0.0;
-*
-*   The angular distance and generalized position angle are readily obtained
-*   from the longitude and latitude of the field point in the new system.
-*   This applies even if the reference point is at one of the poles, in which
-*   case the "position angle" returned is as would be computed for a reference
-*   point at (lng0,+90-epsilon) or (lng0,-90+epsilon), in the limit as epsilon
-*   goes to zero.
-*
-*   It is evident that the coordinate system in which the two points are
-*   expressed is irrelevant to the determination of the angular separation
-*   between the points.  However, this is not true of the generalized position
-*   angle.
-*
-*   The generalized position angle is here defined as the angle of
-*   intersection of the great circle containing the reference and field points
-*   with that containing the reference point and the pole.  It has its normal
-*   meaning when the the reference and field points are specified in
-*   equatorial coordinates (right ascension and declination).
-*
-*   Interchanging the reference and field points changes the position angle in
-*   a non-intuitive way (because the sum of the angles of a spherical triangle
-*   normally exceeds 180 degrees).
-*
-*   The position angle is undefined if the reference and field points are
-*   coincident or antipodal.  This may be detected by checking for a distance
-*   of 0 or 180 degrees (within rounding tolerance).  sphdpa() will return an
-*   arbitrary position angle in such circumstances.
-*
-*
-* sphpad() - Compute field points offset from a given point
-* ---------------------------------------------------------
-* sphpad() computes the coordinates of a set of points that are offset by the
-* specified angular distances and position angles from a given "reference"
-* point on the sky.  The distances and position angles must be specified
-* consistently in any spherical coordinate system.
-*
-* sphpad() is complementary to sphdpa().
-*
-* Given:
-*   nfield    int       The number of field points.
-*
-*   lng0,lat0 double    Spherical coordinates of the reference point [deg].
-*
-*   dist,pa   const double[]
-*                       Angular distances and position angles [deg].
-*
-* Returned:
-*   lng,lat   double[]  Spherical coordinates of the field points [deg].
-*                       These may refer to the same storage as dist and pa
-*                       respectively.
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*
-* Notes:
-*   sphpad() is implemented analogously to sphdpa() although using sphx2s()
-*   for the inverse transformation.  In particular, when the reference point
-*   is at one of the poles, "position angle" is interpreted as though the
-*   reference point was at (lng0,+90-epsilon) or (lng0,-90+epsilon), in the
-*   limit as epsilon goes to zero.
-*
-*   Applying sphpad() with the distances and position angles computed by
-*   sphdpa() should return the original field points.
-*
-*===========================================================================*/
-
-#ifndef WCSLIB_SPH
-#define WCSLIB_SPH
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-int sphx2s(const double eul[5], int nphi, int ntheta, int spt, int sxy,
-           const double phi[], const double theta[],
-           double lng[], double lat[]);
-
-int sphs2x(const double eul[5], int nlng, int nlat, int sll , int spt,
-           const double lng[], const double lat[],
-           double phi[], double theta[]);
-
-int sphdpa(int nfield, double lng0, double lat0,
-           const double lng[], const double lat[],
-           double dist[], double pa[]);
-
-int sphpad(int nfield, double lng0, double lat0,
-           const double dist[], const double pa[],
-           double lng[], double lat[]);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* WCSLIB_SPH */
diff --git a/astropy/wcs/src/wcslib/C/spx.c b/astropy/wcs/src/wcslib/C/spx.c
deleted file mode 100644
index 99d7ec5..0000000
--- a/astropy/wcs/src/wcslib/C/spx.c
+++ /dev/null
@@ -1,1154 +0,0 @@
-/*============================================================================
-
-  WCSLIB 4.10 - an implementation of the FITS WCS standard.
-  Copyright (C) 1995-2012, Mark Calabretta
-
-  This file is part of WCSLIB.
-
-  WCSLIB is free software: you can redistribute it and/or modify it under the
-  terms of the GNU Lesser General Public License as published by the Free
-  Software Foundation, either version 3 of the License, or (at your option)
-  any later version.
-
-  WCSLIB 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 Lesser General Public License for
-  more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with WCSLIB.  If not, see <http://www.gnu.org/licenses/>.
-
-  Correspondence concerning WCSLIB may be directed to:
-    Internet email: mcalabre at atnf.csiro.au
-    Postal address: Dr. Mark Calabretta
-                    Australia Telescope National Facility, CSIRO
-                    PO Box 76
-                    Epping NSW 1710
-                    AUSTRALIA
-
-  Author: Mark Calabretta, Australia Telescope National Facility
-  http://www.atnf.csiro.au/~mcalabre/index.html
-  $Id: spx.c,v 4.10 2012/02/05 23:41:44 cal103 Exp $
-*===========================================================================*/
-
-#include <math.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "wcserr.h"
-#include "wcsmath.h"
-#include "spx.h"
-
-
-/* Map status return value to message. */
-const char *spx_errmsg[] = {
-  "Success",
-  "Null spxprm pointer passed",
-  "Invalid spectral parameters",
-  "Invalid spectral variable",
-  "One or more of the inspec coordinates were invalid"};
-
-/* Convenience macro for invoking wcserr_set(). */
-#define SPX_ERRMSG(status) WCSERR_SET(status), spx_errmsg[status]
-
-#define C 2.99792458e8
-#define h 6.6260755e-34
-
-/*============================================================================
-*   Spectral cross conversions; given one spectral coordinate it computes all
-*   the others, plus the required derivatives of each with respect to the
-*   others.
-*===========================================================================*/
-
-int specx(type, spec, restfrq, restwav, spx)
-
-const char *type;
-double spec, restfrq, restwav;
-struct spxprm *spx;
-
-{
-  static const char *function = "specx";
-
-  register int k;
-  int haverest;
-  double beta, dwaveawav, gamma, n, s, t, u;
-  struct wcserr **err;
-
-  if (spx == 0x0) return SPXERR_NULL_POINTER;
-  err = &(spx->err);
-
-  haverest = 1;
-  if (restfrq == 0.0) {
-    if (restwav == 0.0) {
-      /* No line rest frequency supplied. */
-      haverest = 0;
-
-      /* Temporarily set a dummy value for conversions. */
-      spx->restwav = 1.0;
-    } else {
-      spx->restwav = restwav;
-    }
-    spx->restfrq = C/spx->restwav;
-
-  } else {
-    spx->restfrq = restfrq;
-    spx->restwav = C/restfrq;
-  }
-
-  spx->err = 0x0;
-
-  /* Convert to frequency. */
-  spx->wavetype = 0;
-  spx->velotype = 0;
-  if (strcmp(type, "FREQ") == 0) {
-    if (spec == 0.0) {
-      return wcserr_set(WCSERR_SET(SPXERR_BAD_SPEC_VAR),
-        "Invalid spectral variable: frequency == 0");
-    }
-    spx->freq = spec;
-    spx->wavetype = 1;
-
-  } else if (strcmp(type, "AFRQ") == 0) {
-    if (spec == 0.0) {
-      return wcserr_set(WCSERR_SET(SPXERR_BAD_SPEC_VAR),
-        "Invalid spectral variable: frequency == 0");
-    }
-    spx->freq = spec/(2.0*PI);
-    spx->wavetype = 1;
-
-  } else if (strcmp(type, "ENER") == 0) {
-    if (spec == 0.0) {
-      return wcserr_set(WCSERR_SET(SPXERR_BAD_SPEC_VAR),
-        "Invalid spectral variable: frequency == 0");
-    }
-    spx->freq = spec/h;
-    spx->wavetype = 1;
-
-  } else if (strcmp(type, "WAVN") == 0) {
-    if (spec == 0.0) {
-      return wcserr_set(WCSERR_SET(SPXERR_BAD_SPEC_VAR),
-        "Invalid spectral variable: frequency == 0");
-    }
-    spx->freq = spec*C;
-    spx->wavetype = 1;
-
-  } else if (strcmp(type, "VRAD") == 0) {
-    spx->freq = spx->restfrq*(1.0 - spec/C);
-    spx->velotype = 1;
-
-  } else if (strcmp(type, "WAVE") == 0) {
-    if (spec == 0.0) {
-      return wcserr_set(WCSERR_SET(SPXERR_BAD_SPEC_VAR),
-        "Invalid spectral variable: frequency == 0");
-    }
-    spx->freq = C/spec;
-    spx->wavetype = 1;
-
-  } else if (strcmp(type, "VOPT") == 0) {
-    s = 1.0 + spec/C;
-    if (s == 0.0) {
-      return wcserr_set(WCSERR_SET(SPXERR_BAD_SPEC_VAR),
-        "Invalid spectral variable");
-    }
-    spx->freq = spx->restfrq/s;
-    spx->velotype = 1;
-
-  } else if (strcmp(type, "ZOPT") == 0) {
-    s = 1.0 + spec;
-    if (s == 0.0) {
-      return wcserr_set(WCSERR_SET(SPXERR_BAD_SPEC_VAR),
-        "Invalid spectral variable");
-    }
-    spx->freq = spx->restfrq/s;
-    spx->velotype = 1;
-
-  } else if (strcmp(type, "AWAV") == 0) {
-    if (spec == 0.0) {
-      return wcserr_set(WCSERR_SET(SPXERR_BAD_SPEC_VAR),
-        "Invalid spectral variable");
-    }
-    s = 1.0/spec;
-    s *= s;
-    n  =   2.554e8 / (0.41e14 - s);
-    n += 294.981e8 / (1.46e14 - s);
-    n += 1.000064328;
-    spx->freq = C/(spec*n);
-    spx->wavetype = 1;
-
-  } else if (strcmp(type, "VELO") == 0) {
-    beta = spec/C;
-    if (fabs(beta) == 1.0) {
-      return wcserr_set(WCSERR_SET(SPXERR_BAD_SPEC_VAR),
-        "Invalid spectral variable");
-    }
-    spx->freq = spx->restfrq*(1.0 - beta)/sqrt(1.0 - beta*beta);
-    spx->velotype = 1;
-
-  } else if (strcmp(type, "BETA") == 0) {
-    if (fabs(spec) == 1.0) {
-      return wcserr_set(WCSERR_SET(SPXERR_BAD_SPEC_VAR),
-        "Invalid spectral variable");
-    }
-    spx->freq = spx->restfrq*(1.0 - spec)/sqrt(1.0 - spec*spec);
-    spx->velotype = 1;
-
-  } else {
-    /* Unrecognized type. */
-    return wcserr_set(WCSERR_SET(SPXERR_BAD_SPEC_PARAMS),
-      "Unrecognized spectral type '%s'", type);
-  }
-
-
-  /* Convert frequency to the other spectral types. */
-  n = 1.0;
-  for (k = 0; k < 4; k++) {
-    s = n*spx->freq/C;
-    s *= s;
-    t = 0.41e14 - s;
-    u = 1.46e14 - s;
-    n = 1.000064328 + (2.554e8/t + 294.981e8/u);
-  }
-
-  dwaveawav = n - 2.0*s*(2.554e8/(t*t) + 294.981e8/(u*u));
-
-  s = spx->freq/spx->restfrq;
-
-  spx->ener = spx->freq*h;
-  spx->afrq = spx->freq*(2.0*PI);
-  spx->wavn = spx->freq/C;
-  spx->vrad = C*(1.0 - s);
-  spx->wave = C/spx->freq;
-  spx->awav = spx->wave/n;
-  spx->vopt = C*(1.0/s - 1.0);
-  spx->zopt = spx->vopt/C;
-  spx->velo = C*(1.0 - s*s)/(1.0 + s*s);
-  spx->beta = spx->velo/C;
-
-  /* Compute the required derivatives. */
-  gamma = 1.0/sqrt(1.0 - spx->beta*spx->beta);
-
-  spx->dfreqafrq = 1.0/(2.0*PI);
-  spx->dafrqfreq = 1.0/spx->dfreqafrq;
-
-  spx->dfreqener = 1.0/h;
-  spx->denerfreq = 1.0/spx->dfreqener;
-
-  spx->dfreqwavn = C;
-  spx->dwavnfreq = 1.0/spx->dfreqwavn;
-
-  spx->dfreqvrad = -spx->restfrq/C;
-  spx->dvradfreq = 1.0/spx->dfreqvrad;
-
-  spx->dfreqwave = -spx->freq/spx->wave;
-  spx->dwavefreq = 1.0/spx->dfreqwave;
-
-  spx->dfreqawav = spx->dfreqwave * dwaveawav;
-  spx->dawavfreq = 1.0/spx->dfreqawav;
-
-  spx->dfreqvelo = -gamma*spx->restfrq/(C + spx->velo);
-  spx->dvelofreq = 1.0/spx->dfreqvelo;
-
-  spx->dwavevopt = spx->restwav/C;
-  spx->dvoptwave = 1.0/spx->dwavevopt;
-
-  spx->dwavezopt = spx->restwav;
-  spx->dzoptwave = 1.0/spx->dwavezopt;
-
-  spx->dwaveawav = dwaveawav;
-  spx->dawavwave = 1.0/spx->dwaveawav;
-
-  spx->dwavevelo = gamma*spx->restwav/(C - spx->velo);
-  spx->dvelowave = 1.0/spx->dwavevelo;
-
-  spx->dawavvelo = spx->dwavevelo/dwaveawav;
-  spx->dveloawav = 1.0/spx->dawavvelo;
-
-  spx->dvelobeta = C;
-  spx->dbetavelo = 1.0/spx->dvelobeta;
-
-
-  /* Reset values if no line rest frequency was supplied. */
-  if (haverest) {
-    spx->wavetype = 1;
-    spx->velotype = 1;
-
-  } else {
-    spx->restfrq = 0.0;
-    spx->restwav = 0.0;
-
-    if (!spx->wavetype) {
-      /* Don't have wave characteristic types. */
-      spx->freq = 0.0;
-      spx->afrq = 0.0;
-      spx->ener = 0.0;
-      spx->wavn = 0.0;
-      spx->wave = 0.0;
-      spx->awav = 0.0;
-
-      spx->dfreqwave = 0.0;
-      spx->dwavefreq = 0.0;
-
-      spx->dfreqawav = 0.0;
-      spx->dawavfreq = 0.0;
-
-      spx->dwaveawav = 0.0;
-      spx->dawavwave = 0.0;
-
-    } else {
-      /* Don't have velocity types. */
-      spx->vrad = 0.0;
-      spx->vopt = 0.0;
-      spx->zopt = 0.0;
-      spx->velo = 0.0;
-      spx->beta = 0.0;
-    }
-
-    spx->dfreqvrad = 0.0;
-    spx->dvradfreq = 0.0;
-
-    spx->dfreqvelo = 0.0;
-    spx->dvelofreq = 0.0;
-
-    spx->dwavevopt = 0.0;
-    spx->dvoptwave = 0.0;
-
-    spx->dwavezopt = 0.0;
-    spx->dzoptwave = 0.0;
-
-    spx->dwavevelo = 0.0;
-    spx->dvelowave = 0.0;
-
-    spx->dawavvelo = 0.0;
-    spx->dveloawav = 0.0;
-  }
-
-  return 0;
-}
-
-
-/*============================================================================
-*   Conversions between frequency and vacuum wavelength.
-*===========================================================================*/
-
-int freqwave(dummy, nfreq, sfreq, swave, freq, wave, stat)
-
-double dummy;
-int nfreq, sfreq, swave;
-const double freq[];
-double wave[];
-int stat[];
-
-{
-  int status = 0;
-  register int ifreq, *statp;
-  register const double *freqp;
-  register double *wavep;
-
-  freqp = freq;
-  wavep = wave;
-  statp = stat;
-  for (ifreq = 0; ifreq < nfreq; ifreq++) {
-    if (*freqp != 0.0) {
-      *wavep = C/(*freqp);
-      *(statp++) = 0;
-    } else {
-      *(statp++) = 1;
-      status = SPXERR_BAD_INSPEC_COORD;
-    }
-
-    freqp += sfreq;
-    wavep += swave;
-  }
-
-  return status;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int wavefreq(dummy, nwave, swave, sfreq, wave, freq, stat)
-
-double dummy;
-int nwave, swave, sfreq;
-const double wave[];
-double freq[];
-int stat[];
-
-{
-  int status = 0;
-  register int iwave, *statp;
-  register const double *wavep;
-  register double *freqp;
-
-  wavep = wave;
-  freqp = freq;
-  statp = stat;
-  for (iwave = 0; iwave < nwave; iwave++) {
-    if (*wavep != 0.0) {
-      *freqp = C/(*wavep);
-      *(statp++) = 0;
-    } else {
-      *(statp++) = 1;
-      status = SPXERR_BAD_INSPEC_COORD;
-    }
-
-    wavep += swave;
-    freqp += sfreq;
-  }
-
-  return status;
-}
-
-/*============================================================================
-*   Conversions between frequency and air wavelength.
-*===========================================================================*/
-
-int freqawav(dummy, nfreq, sfreq, sawav, freq, awav, stat)
-
-double dummy;
-int nfreq, sfreq, sawav;
-const double freq[];
-double awav[];
-int stat[];
-
-{
-  int status;
-
-  if ((status = freqwave(dummy, nfreq, sfreq, sawav, freq, awav, stat))) {
-    return status;
-  }
-
-  return waveawav(dummy, nfreq, sawav, sawav, awav, awav, stat);
-}
-
-/*--------------------------------------------------------------------------*/
-
-int awavfreq(dummy, nawav, sawav, sfreq, awav, freq, stat)
-
-double dummy;
-int nawav, sawav, sfreq;
-const double awav[];
-double freq[];
-int stat[];
-
-{
-  int status;
-
-  if ((status = awavwave(dummy, nawav, sawav, sfreq, awav, freq, stat))) {
-    return status;
-  }
-
-  return wavefreq(dummy, nawav, sfreq, sfreq, freq, freq, stat);
-}
-
-/*============================================================================
-*   Conversions between frequency and relativistic velocity.
-*===========================================================================*/
-
-int freqvelo(restfrq, nfreq, sfreq, svelo, freq, velo, stat)
-
-double restfrq;
-int nfreq, sfreq, svelo;
-const double freq[];
-double velo[];
-int stat[];
-
-{
-  double r, s;
-  register int ifreq, *statp;
-  register const double *freqp;
-  register double *velop;
-
-  r = restfrq*restfrq;
-
-  freqp = freq;
-  velop = velo;
-  statp = stat;
-  for (ifreq = 0; ifreq < nfreq; ifreq++) {
-    s = *freqp * *freqp;
-    *velop = C*(r - s)/(r + s);
-    *(statp++) = 0;
-
-    freqp += sfreq;
-    velop += svelo;
-  }
-
-  return 0;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int velofreq(restfrq, nvelo, svelo, sfreq, velo, freq, stat)
-
-double restfrq;
-int nvelo, svelo, sfreq;
-const double velo[];
-double freq[];
-int stat[];
-
-{
-  int status = 0;
-  double s;
-  register int ivelo, *statp;
-  register const double *velop;
-  register double *freqp;
-
-  velop = velo;
-  freqp = freq;
-  statp = stat;
-  for (ivelo = 0; ivelo < nvelo; ivelo++) {
-    s = C + *velop;
-    if (s != 0.0) {
-      *freqp = restfrq*sqrt((C - *velop)/s);
-      *(statp++) = 0;
-    } else {
-      *(statp++) = 1;
-      status = SPXERR_BAD_INSPEC_COORD;
-    }
-
-    velop += svelo;
-    freqp += sfreq;
-  }
-
-  return status;
-}
-
-/*============================================================================
-*   Conversions between vacuum wavelength and air wavelength.
-*===========================================================================*/
-
-int waveawav(dummy, nwave, swave, sawav, wave, awav, stat)
-
-double dummy;
-int nwave, swave, sawav;
-const double wave[];
-double awav[];
-int stat[];
-
-{
-  int status = 0;
-  double n, s;
-  register int iwave, k, *statp;
-  register const double *wavep;
-  register double *awavp;
-
-  wavep = wave;
-  awavp = awav;
-  statp = stat;
-  for (iwave = 0; iwave < nwave; iwave++) {
-    if (*wavep != 0.0) {
-      n = 1.0;
-      for (k = 0; k < 4; k++) {
-        s  = n/(*wavep);
-        s *= s;
-        n  =   2.554e8 / (0.41e14 - s);
-        n += 294.981e8 / (1.46e14 - s);
-        n += 1.000064328;
-      }
-
-      *awavp = (*wavep)/n;
-      *(statp++) = 0;
-    } else {
-      *(statp++) = 1;
-      status = SPXERR_BAD_INSPEC_COORD;
-    }
-
-    wavep += swave;
-    awavp += sawav;
-  }
-
-  return status;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int awavwave(dummy, nawav, sawav, swave, awav, wave, stat)
-
-double dummy;
-int nawav, sawav, swave;
-const double awav[];
-double wave[];
-int stat[];
-
-{
-  int status = 0;
-  double n, s;
-  register int iawav, *statp;
-  register const double *awavp;
-  register double *wavep;
-
-  awavp = awav;
-  wavep = wave;
-  statp = stat;
-  for (iawav = 0; iawav < nawav; iawav++) {
-    if (*awavp != 0.0) {
-      s = 1.0/(*awavp);
-      s *= s;
-      n  =   2.554e8 / (0.41e14 - s);
-      n += 294.981e8 / (1.46e14 - s);
-      n += 1.000064328;
-      *wavep = (*awavp)*n;
-      *(statp++) = 0;
-    } else {
-      *(statp++) = 1;
-      status = SPXERR_BAD_INSPEC_COORD;
-    }
-
-    awavp += sawav;
-    wavep += swave;
-  }
-
-  return status;
-}
-
-/*============================================================================
-*   Conversions between vacuum wavelength and relativistic velocity.
-*===========================================================================*/
-
-int wavevelo(restwav, nwave, swave, svelo, wave, velo, stat)
-
-double restwav;
-int nwave, swave, svelo;
-const double wave[];
-double velo[];
-int stat[];
-
-{
-  double r, s;
-  register int iwave, *statp;
-  register const double *wavep;
-  register double *velop;
-
-  r = restwav*restwav;
-
-  wavep = wave;
-  velop = velo;
-  statp = stat;
-  for (iwave = 0; iwave < nwave; iwave++) {
-    s = *wavep * *wavep;
-    *velop = C*(s - r)/(s + r);
-    *(statp++) = 0;
-
-    wavep += swave;
-    velop += svelo;
-  }
-
-  return 0;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int velowave(restwav, nvelo, svelo, swave, velo, wave, stat)
-
-double restwav;
-int nvelo, svelo, swave;
-const double velo[];
-double wave[];
-int stat[];
-
-{
-  int status = 0;
-  double s;
-  register int ivelo, *statp;
-  register const double *velop;
-  register double *wavep;
-
-  velop = velo;
-  wavep = wave;
-  statp = stat;
-  for (ivelo = 0; ivelo < nvelo; ivelo++) {
-    s = C - *velop;
-    if (s != 0.0) {
-      *wavep = restwav*sqrt((C + *velop)/s);
-      *(statp++) = 0;
-    } else {
-      *(statp++) = 1;
-      status = SPXERR_BAD_INSPEC_COORD;
-    }
-
-    velop += svelo;
-    wavep += swave;
-  }
-
-  return status;
-}
-
-/*============================================================================
-*   Conversions between air wavelength and relativistic velocity.
-*===========================================================================*/
-
-int awavvelo(dummy, nawav, sawav, svelo, awav, velo, stat)
-
-double dummy;
-int nawav, sawav, svelo;
-const double awav[];
-double velo[];
-int stat[];
-
-{
-  int status;
-
-  if ((status = awavwave(dummy, nawav, sawav, svelo, awav, velo, stat))) {
-    return status;
-  }
-
-  return wavevelo(dummy, nawav, svelo, svelo, velo, velo, stat);
-}
-
-/*--------------------------------------------------------------------------*/
-
-int veloawav(dummy, nvelo, svelo, sawav, velo, awav, stat)
-
-double dummy;
-int nvelo, svelo, sawav;
-const double velo[];
-double awav[];
-int stat[];
-
-{
-  int status;
-
-  if ((status = velowave(dummy, nvelo, svelo, sawav, velo, awav, stat))) {
-    return status;
-  }
-
-  return waveawav(dummy, nvelo, sawav, sawav, awav, awav, stat);
-}
-
-/*============================================================================
-*   Conversions between frequency and angular frequency.
-*===========================================================================*/
-
-int freqafrq(dummy, nfreq, sfreq, safrq, freq, afrq, stat)
-
-double dummy;
-int nfreq, sfreq, safrq;
-const double freq[];
-double afrq[];
-int stat[];
-
-{
-  register int ifreq, *statp;
-  register const double *freqp;
-  register double *afrqp;
-
-  freqp = freq;
-  afrqp = afrq;
-  statp = stat;
-  for (ifreq = 0; ifreq < nfreq; ifreq++) {
-    *afrqp = (*freqp)*(2.0*PI);
-    *(statp++) = 0;
-
-    freqp += sfreq;
-    afrqp += safrq;
-  }
-
-  return 0;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int afrqfreq(dummy, nafrq, safrq, sfreq, afrq, freq, stat)
-
-double dummy;
-int nafrq, safrq, sfreq;
-const double afrq[];
-double freq[];
-int stat[];
-
-{
-  register int iafrq, *statp;
-  register const double *afrqp;
-  register double *freqp;
-
-  afrqp = afrq;
-  freqp = freq;
-  statp = stat;
-  for (iafrq = 0; iafrq < nafrq; iafrq++) {
-    *freqp = (*afrqp)/(2.0*PI);
-    *(statp++) = 0;
-
-    afrqp += safrq;
-    freqp += sfreq;
-  }
-
-  return 0;
-}
-
-/*============================================================================
-*   Conversions between frequency and energy.
-*===========================================================================*/
-
-int freqener(dummy, nfreq, sfreq, sener, freq, ener, stat)
-
-double dummy;
-int nfreq, sfreq, sener;
-const double freq[];
-double ener[];
-int stat[];
-
-{
-  register int ifreq, *statp;
-  register const double *freqp;
-  register double *enerp;
-
-  freqp = freq;
-  enerp = ener;
-  statp = stat;
-  for (ifreq = 0; ifreq < nfreq; ifreq++) {
-    *enerp = (*freqp)*h;
-    *(statp++) = 0;
-
-    freqp += sfreq;
-    enerp += sener;
-  }
-
-  return 0;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int enerfreq(dummy, nener, sener, sfreq, ener, freq, stat)
-
-double dummy;
-int nener, sener, sfreq;
-const double ener[];
-double freq[];
-int stat[];
-
-{
-  register int iener, *statp;
-  register const double *enerp;
-  register double *freqp;
-
-  enerp = ener;
-  freqp = freq;
-  statp = stat;
-  for (iener = 0; iener < nener; iener++) {
-    *freqp = (*enerp)/h;
-    *(statp++) = 0;
-
-    enerp += sener;
-    freqp += sfreq;
-  }
-
-  return 0;
-}
-
-/*============================================================================
-*   Conversions between frequency and wave number.
-*===========================================================================*/
-
-int freqwavn(dummy, nfreq, sfreq, swavn, freq, wavn, stat)
-
-double dummy;
-int nfreq, sfreq, swavn;
-const double freq[];
-double wavn[];
-int stat[];
-
-{
-  register int ifreq, *statp;
-  register const double *freqp;
-  register double *wavnp;
-
-  freqp = freq;
-  wavnp = wavn;
-  statp = stat;
-  for (ifreq = 0; ifreq < nfreq; ifreq++) {
-    *wavnp = (*freqp)/C;
-    *(statp++) = 0;
-
-    freqp += sfreq;
-    wavnp += swavn;
-  }
-
-  return 0;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int wavnfreq(dummy, nwavn, swavn, sfreq, wavn, freq, stat)
-
-double dummy;
-int nwavn, swavn, sfreq;
-const double wavn[];
-double freq[];
-int stat[];
-
-{
-  register int iwavn, *statp;
-  register const double *wavnp;
-  register double *freqp;
-
-  wavnp = wavn;
-  freqp = freq;
-  statp = stat;
-  for (iwavn = 0; iwavn < nwavn; iwavn++) {
-    *freqp = (*wavnp)*C;
-    *(statp++) = 0;
-
-    wavnp += swavn;
-    freqp += sfreq;
-  }
-
-  return 0;
-}
-
-/*============================================================================
-*   Conversions between frequency and radio velocity.
-*===========================================================================*/
-
-int freqvrad(restfrq, nfreq, sfreq, svrad, freq, vrad, stat)
-
-double restfrq;
-int nfreq, sfreq, svrad;
-const double freq[];
-double vrad[];
-int stat[];
-
-{
-  double r;
-  register int ifreq, *statp;
-  register const double *freqp;
-  register double *vradp;
-
-  if (restfrq == 0.0) {
-    return SPXERR_BAD_SPEC_PARAMS;
-  }
-  r = C/restfrq;
-
-  freqp = freq;
-  vradp = vrad;
-  statp = stat;
-  for (ifreq = 0; ifreq < nfreq; ifreq++) {
-    *vradp = r*(restfrq - *freqp);
-    *(statp++) = 0;
-
-    freqp += sfreq;
-    vradp += svrad;
-  }
-
-  return 0;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int vradfreq(restfrq, nvrad, svrad, sfreq, vrad, freq, stat)
-
-double restfrq;
-int nvrad, svrad, sfreq;
-const double vrad[];
-double freq[];
-int stat[];
-
-{
-  double r;
-  register int ivrad, *statp;
-  register const double *vradp;
-  register double *freqp;
-
-  r = restfrq/C;
-
-  vradp = vrad;
-  freqp = freq;
-  statp = stat;
-  for (ivrad = 0; ivrad < nvrad; ivrad++) {
-    *freqp = r*(C - *vradp);
-    *(statp++) = 0;
-    vradp += svrad;
-    freqp += sfreq;
-  }
-
-  return 0;
-}
-
-/*============================================================================
-*   Conversions between vacuum wavelength and optical velocity.
-*===========================================================================*/
-
-int wavevopt(restwav, nwave, swave, svopt, wave, vopt, stat)
-
-double restwav;
-int nwave, swave, svopt;
-const double wave[];
-double vopt[];
-int stat[];
-
-{
-  double r;
-  register int iwave, *statp;
-  register const double *wavep;
-  register double *voptp;
-
-  if (restwav == 0.0) {
-    return SPXERR_BAD_SPEC_PARAMS;
-  }
-  r = C/restwav;
-
-  wavep = wave;
-  voptp = vopt;
-  statp = stat;
-  for (iwave = 0; iwave < nwave; iwave++) {
-    *voptp = r*(*wavep) - C;
-    *(statp++) = 0;
-    wavep += swave;
-    voptp += svopt;
-  }
-
-  return 0;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int voptwave(restwav, nvopt, svopt, swave, vopt, wave, stat)
-
-double restwav;
-int nvopt, svopt, swave;
-const double vopt[];
-double wave[];
-int stat[];
-
-{
-  double r;
-  register int ivopt, *statp;
-  register const double *voptp;
-  register double *wavep;
-
-  r = restwav/C;
-
-  voptp = vopt;
-  wavep = wave;
-  statp = stat;
-  for (ivopt = 0; ivopt < nvopt; ivopt++) {
-    *wavep = r*(C + *voptp);
-    *(statp++) = 0;
-    voptp += svopt;
-    wavep += swave;
-  }
-
-  return 0;
-}
-
-/*============================================================================
-*   Conversions between vacuum wavelength and redshift.
-*===========================================================================*/
-
-int wavezopt(restwav, nwave, swave, szopt, wave, zopt, stat)
-
-double restwav;
-int nwave, swave, szopt;
-const double wave[];
-double zopt[];
-int stat[];
-
-{
-  double r;
-  register int iwave, *statp;
-  register const double *wavep;
-  register double *zoptp;
-
-  if (restwav == 0.0) {
-    return SPXERR_BAD_SPEC_PARAMS;
-  }
-  r = 1.0/restwav;
-
-  wavep = wave;
-  zoptp = zopt;
-  statp = stat;
-  for (iwave = 0; iwave < nwave; iwave++) {
-    *zoptp = r*(*wavep) - 1.0;
-    *(statp++) = 0;
-    wavep += swave;
-    zoptp += szopt;
-  }
-
-  return 0;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int zoptwave(restwav, nzopt, szopt, swave, zopt, wave, stat)
-
-double restwav;
-int nzopt, szopt, swave;
-const double zopt[];
-double wave[];
-int stat[];
-
-{
-  register int izopt, *statp;
-  register const double *zoptp;
-  register double *wavep;
-
-  zoptp = zopt;
-  wavep = wave;
-  statp = stat;
-  for (izopt = 0; izopt < nzopt; izopt++) {
-    *wavep = restwav*(1.0 + *zoptp);
-    *(statp++) = 0;
-    zoptp += szopt;
-    wavep += swave;
-  }
-
-  return 0;
-}
-
-/*============================================================================
-*   Conversions between relativistic velocity and beta (= v/c).
-*===========================================================================*/
-
-int velobeta(dummy, nvelo, svelo, sbeta, velo, beta, stat)
-
-double dummy;
-int nvelo, svelo, sbeta;
-const double velo[];
-double beta[];
-int stat[];
-
-{
-  register int ivelo, *statp;
-  register const double *velop;
-  register double *betap;
-
-  velop = velo;
-  betap = beta;
-  statp = stat;
-  for (ivelo = 0; ivelo < nvelo; ivelo++) {
-    *betap = (*velop)/C;
-    *(statp++) = 0;
-
-    velop += svelo;
-    betap += sbeta;
-  }
-
-  return 0;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int betavelo(dummy, nbeta, sbeta, svelo, beta, velo, stat)
-
-double dummy;
-int nbeta, sbeta, svelo;
-const double beta[];
-double velo[];
-int stat[];
-
-{
-  register int ibeta, *statp;
-  register const double *betap;
-  register double *velop;
-
-  betap = beta;
-  velop = velo;
-  statp = stat;
-  for (ibeta = 0; ibeta < nbeta; ibeta++) {
-    *velop = (*betap)*C;
-    *(statp++) = 0;
-
-    betap += sbeta;
-    velop += svelo;
-  }
-
-  return 0;
-}
diff --git a/astropy/wcs/src/wcslib/C/spx.h b/astropy/wcs/src/wcslib/C/spx.h
deleted file mode 100644
index c1a77e3..0000000
--- a/astropy/wcs/src/wcslib/C/spx.h
+++ /dev/null
@@ -1,544 +0,0 @@
-/*============================================================================
-
-  WCSLIB 4.10 - an implementation of the FITS WCS standard.
-  Copyright (C) 1995-2012, Mark Calabretta
-
-  This file is part of WCSLIB.
-
-  WCSLIB is free software: you can redistribute it and/or modify it under the
-  terms of the GNU Lesser General Public License as published by the Free
-  Software Foundation, either version 3 of the License, or (at your option)
-  any later version.
-
-  WCSLIB 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 Lesser General Public License for
-  more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with WCSLIB.  If not, see <http://www.gnu.org/licenses/>.
-
-  Correspondence concerning WCSLIB may be directed to:
-    Internet email: mcalabre at atnf.csiro.au
-    Postal address: Dr. Mark Calabretta
-                    Australia Telescope National Facility, CSIRO
-                    PO Box 76
-                    Epping NSW 1710
-                    AUSTRALIA
-
-  Author: Mark Calabretta, Australia Telescope National Facility
-  http://www.atnf.csiro.au/~mcalabre/index.html
-  $Id: spx.h,v 4.10 2012/02/05 23:41:44 cal103 Exp $
-*=============================================================================
-*
-* WCSLIB 4.10 - C routines that implement the spectral coordinate systems
-* recognized by the FITS World Coordinate System (WCS) standard.  Refer to
-*
-*   "Representations of world coordinates in FITS",
-*   Greisen, E.W., & Calabretta, M.R. 2002, A&A, 395, 1061 (Paper I)
-*
-*   "Representations of spectral coordinates in FITS",
-*   Greisen, E.W., Calabretta, M.R., Valdes, F.G., & Allen, S.L.
-*   2006, A&A, 446, 747 (Paper III)
-*
-* Refer to the README file provided with WCSLIB for an overview of the
-* library.
-*
-*
-* Summary of the spx routines
-* ---------------------------
-* specx() is a scalar routine that, given one spectral variable (e.g.
-* frequency), computes all the others (e.g. wavelength, velocity, etc.) plus
-* the required derivatives of each with respect to the others.  The results
-* are returned in the spxprm struct.
-*
-* The remaining routines are all vector conversions from one spectral
-* variable to another.  The API of these functions only differ in whether the
-* rest frequency or wavelength need be supplied.
-*
-* Non-linear:
-*   - freqwave()    frequency              ->  vacuum wavelength
-*   - wavefreq()    vacuum wavelength      ->  frequency
-*
-*   - freqawav()    frequency              ->  air wavelength
-*   - awavfreq()    air wavelength         ->  frequency
-*
-*   - freqvelo()    frequency              ->  relativistic velocity
-*   - velofreq()    relativistic velocity  ->  frequency
-*
-*   - waveawav()    vacuum wavelength      ->  air wavelength
-*   - awavwave()    air wavelength         ->  vacuum wavelength
-*
-*   - wavevelo()    vacuum wavelength      ->  relativistic velocity
-*   - velowave()    relativistic velocity  ->  vacuum wavelength
-*
-*   - awavvelo()    air wavelength         ->  relativistic velocity
-*   - veloawav()    relativistic velocity  ->  air wavelength
-*
-* Linear:
-*   - freqafrq()    frequency              ->  angular frequency
-*   - afrqfreq()    angular frequency      ->  frequency
-*
-*   - freqener()    frequency              ->  energy
-*   - enerfreq()    energy                 ->  frequency
-*
-*   - freqwavn()    frequency              ->  wave number
-*   - wavnfreq()    wave number            ->  frequency
-*
-*   - freqvrad()    frequency              ->  radio velocity
-*   - vradfreq()    radio velocity         ->  frequency
-*
-*   - wavevopt()    vacuum wavelength      ->  optical velocity
-*   - voptwave()    optical velocity       ->  vacuum wavelength
-*
-*   - wavezopt()    vacuum wavelength      ->  redshift
-*   - zoptwave()    redshift               ->  vacuum wavelength
-*
-*   - velobeta()    relativistic velocity  ->  beta (= v/c)
-*   - betavelo()    beta (= v/c)           ->  relativistic velocity
-*
-* These are the workhorse routines, to be used for fast transformations.
-* Conversions may be done "in place" by calling the routine with the output
-* vector set to the input.
-*
-* Argument checking:
-* ------------------
-* The input spectral values are only checked for values that would result
-* in floating point exceptions.  In particular, negative frequencies and
-* wavelengths are allowed, as are velocities greater than the speed of
-* light.  The same is true for the spectral parameters - rest frequency and
-* wavelength.
-*
-* Accuracy:
-* ---------
-* No warranty is given for the accuracy of these routines (refer to the
-* copyright notice); intending users must satisfy for themselves their
-* adequacy for the intended purpose.  However, closure effectively to within
-* double precision rounding error was demonstrated by test routine tspec.c
-* which accompanies this software.
-*
-*
-* specx() - Spectral cross conversions (scalar)
-* ---------------------------------------------
-* Given one spectral variable specx() computes all the others, plus the
-* required derivatives of each with respect to the others.
-*
-* Given:
-*   type      const char*
-*                       The type of spectral variable given by spec, FREQ,
-*                       AFRQ, ENER, WAVN, VRAD, WAVE, VOPT, ZOPT, AWAV, VELO,
-*                       or BETA (case sensitive).
-*
-*   spec      double    The spectral variable given, in SI units.
-*
-*   restfrq,
-*   restwav   double    Rest frequency [Hz] or rest wavelength in vacuo [m],
-*                       only one of which need be given.  The other should be
-*                       set to zero.  If both are zero, only a subset of the
-*                       spectral variables can be computed, the remainder are
-*                       set to zero.  Specifically, given one of FREQ, AFRQ,
-*                       ENER, WAVN, WAVE, or AWAV the others can be computed
-*                       without knowledge of the rest frequency.  Likewise,
-*                       VRAD, VOPT, ZOPT, VELO, and BETA.
-*
-* Given and returned:
-*   specs     struct spxprm*
-*                       Data structure containing all spectral variables and
-*                       their derivatives, in SI units.
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         1: Null spxprm pointer passed.
-*                         2: Invalid spectral parameters.
-*                         3: Invalid spectral variable.
-*
-*                       For returns > 1, a detailed error message is set in
-*                       spxprm::err if enabled, see wcserr_enable().
-*
-* freqafrq(), afrqfreq(), freqener(), enerfreq(), freqwavn(), wavnfreq(),
-* freqwave(), wavefreq(), freqawav(), awavfreq(), waveawav(), awavwave(),
-* velobeta(), and betavelo() implement vector conversions between wave-like
-* or velocity-like spectral types (i.e. conversions that do not need the rest
-* frequency or wavelength).  They all have the same API.
-*
-*
-* freqafrq() - Convert frequency to angular frequency (vector)
-* ------------------------------------------------------------
-* freqafrq() converts frequency to angular frequency.
-*
-* Given:
-*   param     double    Ignored.
-*
-*   nspec     int       Vector length.
-*
-*   instep,
-*   outstep   int       Vector strides.
-*
-*   inspec    const double[]
-*                       Input spectral variables, in SI units.
-*
-* Returned:
-*   outspec   double[]  Output spectral variables, in SI units.
-*
-*   stat      int[]     Status return value for each vector element:
-*                         0: Success.
-*                         1: Invalid value of inspec.
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         2: Invalid spectral parameters.
-*                         4: One or more of the inspec coordinates were
-*                            invalid, as indicated by the stat vector.
-*
-*
-* freqvelo(), velofreq(), freqvrad(), and vradfreq() implement vector
-* conversions between frequency and velocity spectral types.  They all have
-* the same API.
-*
-*
-* freqvelo() - Convert frequency to relativistic velocity (vector)
-* ----------------------------------------------------------------
-* freqvelo() converts frequency to relativistic velocity.
-*
-* Given:
-*   param     double    Rest frequency [Hz].
-*
-*   nspec     int       Vector length.
-*
-*   instep,
-*   outstep   int       Vector strides.
-*
-*   inspec    const double[]
-*                       Input spectral variables, in SI units.
-*
-* Returned:
-*   outspec   double[]  Output spectral variables, in SI units.
-*
-*   stat      int[]     Status return value for each vector element:
-*                         0: Success.
-*                         1: Invalid value of inspec.
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         2: Invalid spectral parameters.
-*                         4: One or more of the inspec coordinates were
-*                            invalid, as indicated by the stat vector.
-*
-*
-* wavevelo(), velowave(), awavvelo(), veloawav(), wavevopt(), voptwave(),
-* wavezopt(), and zoptwave() implement vector conversions between wavelength
-* and velocity spectral types.  They all have the same API.
-*
-*
-* wavevelo() - Conversions between wavelength and velocity types (vector)
-* -----------------------------------------------------------------------
-* wavevelo() converts vacuum wavelength to relativistic velocity.
-*
-* Given:
-*   param     double    Rest wavelength in vacuo [m].
-*
-*   nspec     int       Vector length.
-*
-*   instep,
-*   outstep   int       Vector strides.
-*
-*   inspec    const double[]
-*                       Input spectral variables, in SI units.
-*
-* Returned:
-*   outspec   double[]  Output spectral variables, in SI units.
-*
-*   stat      int[]     Status return value for each vector element:
-*                         0: Success.
-*                         1: Invalid value of inspec.
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         2: Invalid spectral parameters.
-*                         4: One or more of the inspec coordinates were
-*                            invalid, as indicated by the stat vector.
-*
-*
-* spxprm struct - Spectral variables and their derivatives
-* --------------------------------------------------------
-* The spxprm struct contains the value of all spectral variables and their
-* derivatives.   It is used solely by specx() which constructs it from
-* information provided via its function arguments.
-*
-* This struct should be considered read-only, no members need ever be set nor
-* should ever be modified by the user.
-*
-*   double restfrq
-*     (Returned) Rest frequency [Hz].
-*
-*   double restwav
-*     (Returned) Rest wavelength [m].
-*
-*   int wavetype
-*     (Returned) True if wave types have been computed, and ...
-*
-*   int velotype
-*     (Returned) ... true if velocity types have been computed; types are
-*     defined below.
-*
-*     If one or other of spxprm::restfrq and spxprm::restwav is given
-*     (non-zero) then all spectral variables may be computed.  If both are
-*     given, restfrq is used.  If restfrq and restwav are both zero, only wave
-*     characteristic xor velocity type spectral variables may be computed
-*     depending on the variable given.   These flags indicate what is
-*     available.
-*
-*   double freq
-*     (Returned) Frequency [Hz] (wavetype).
-*
-*   double afrq
-*     (Returned) Angular frequency [rad/s] (wavetype).
-*
-*   double ener
-*     (Returned) Photon energy [J] (wavetype).
-*
-*   double wavn
-*     (Returned) Wave number [/m] (wavetype).
-*
-*   double vrad
-*     (Returned) Radio velocity [m/s] (velotype).
-*
-*   double wave
-*     (Returned) Vacuum wavelength [m] (wavetype).
-*
-*   double vopt
-*     (Returned) Optical velocity [m/s] (velotype).
-*
-*   double zopt
-*     (Returned) Redshift [dimensionless] (velotype).
-*
-*   double awav
-*     (Returned) Air wavelength [m] (wavetype).
-*
-*   double velo
-*     (Returned) Relativistic velocity [m/s] (velotype).
-*
-*   double beta
-*     (Returned) Relativistic beta [dimensionless] (velotype).
-*
-*   double dfreqafrq
-*     (Returned) Derivative of frequency with respect to angular frequency
-*     [/rad] (constant, = 1 / 2*pi), and ...
-*   double dafrqfreq
-*     (Returned) ... vice versa [rad] (constant, = 2*pi, always available).
-*
-*   double dfreqener
-*     (Returned) Derivative of frequency with respect to photon energy
-*     [/J/s] (constant, = 1/h), and ...
-*   double denerfreq
-*     (Returned) ... vice versa [Js] (constant, = h, Planck's constant,
-*     always available).
-*
-*   double dfreqwavn
-*     (Returned) Derivative of frequency with respect to wave number [m/s]
-*     (constant, = c, the speed of light in vacuuo), and ...
-*   double dwavnfreq
-*     (Returned) ... vice versa [s/m] (constant, = 1/c, always available).
-*
-*   double dfreqvrad
-*     (Returned) Derivative of frequency with respect to radio velocity [/m],
-*     and ...
-*   double dvradfreq
-*     (Returned) ... vice versa [m] (wavetype && velotype).
-*
-*   double dfreqwave
-*     (Returned) Derivative of frequency with respect to vacuum wavelength
-*     [/m/s], and ...
-*   double dwavefreq
-*     (Returned) ... vice versa [m s] (wavetype).
-*
-*   double dfreqawav
-*     (Returned) Derivative of frequency with respect to air wavelength,
-*     [/m/s], and ...
-*   double dawavfreq
-*     (Returned) ... vice versa [m s] (wavetype).
-*
-*   double dfreqvelo
-*     (Returned) Derivative of frequency with respect to relativistic
-*     velocity [/m], and ...
-*   double dvelofreq
-*     (Returned) ... vice versa [m] (wavetype && velotype).
-*
-*   double dwavevopt
-*     (Returned) Derivative of vacuum wavelength with respect to optical
-*     velocity [s], and ...
-*   double dvoptwave
-*     (Returned) ... vice versa [/s] (wavetype && velotype).
-*
-*   double dwavezopt
-*     (Returned) Derivative of vacuum wavelength with respect to redshift [m],
-*     and ...
-*   double dzoptwave
-*     (Returned) ... vice versa [/m] (wavetype && velotype).
-*
-*   double dwaveawav
-*     (Returned) Derivative of vacuum wavelength with respect to air
-*     wavelength [dimensionless], and ...
-*   double dawavwave
-*     (Returned) ... vice versa [dimensionless] (wavetype).
-*
-*   double dwavevelo
-*     (Returned) Derivative of vacuum wavelength with respect to relativistic
-*     velocity [s], and ...
-*   double dvelowave
-*     (Returned) ... vice versa [/s] (wavetype && velotype).
-*
-*   double dawavvelo
-*     (Returned) Derivative of air wavelength with respect to relativistic
-*     velocity [s], and ...
-*   double dveloawav
-*     (Returned) ... vice versa [/s] (wavetype && velotype).
-*
-*   double dvelobeta
-*     (Returned) Derivative of relativistic velocity with respect to
-*     relativistic beta [m/s] (constant, = c, the speed of light in vacuu0),
-*     and ...
-*   double dbetavelo
-*     (Returned) ... vice versa [s/m] (constant, = 1/c, always available).
-*
-*   struct wcserr *err
-*     (Returned) If enabled, when an error status is returned this struct
-*     contains detailed information about the error, see wcserr_enable().
-*
-*   void *padding
-*     (An unused variable inserted for alignment purposes only.)
-*
-* Global variable: const char *spx_errmsg[] - Status return messages
-* ------------------------------------------------------------------
-* Error messages to match the status value returned from each function.
-*
-*===========================================================================*/
-
-#ifndef WCSLIB_SPEC
-#define WCSLIB_SPEC
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "wcserr.h"
-
-extern const char *spx_errmsg[];
-
-enum spx_errmsg {
-  SPXERR_SUCCESS          = 0,	/* Success. */
-  SPXERR_NULL_POINTER     = 1,	/* Null spxprm pointer passed. */
-  SPXERR_BAD_SPEC_PARAMS  = 2,	/* Invalid spectral parameters. */
-  SPXERR_BAD_SPEC_VAR     = 3,	/* Invalid spectral variable. */
-  SPXERR_BAD_INSPEC_COORD = 4 	/* One or more of the inspec coordinates were
-				   invalid. */
-};
-
-struct spxprm {
-  double restfrq, restwav;	/* Rest frequency [Hz] and wavelength [m].  */
-
-  int wavetype, velotype;	/* True if wave/velocity types have been    */
-				/* computed; types are defined below.       */
-
-  /* Spectral variables computed by specx().                                */
-  /*------------------------------------------------------------------------*/
-  double freq,			/* wavetype: Frequency [Hz].                */
-         afrq,			/* wavetype: Angular frequency [rad/s].     */
-         ener,			/* wavetype: Photon energy [J].             */
-         wavn,			/* wavetype: Wave number [/m].              */
-         vrad,			/* velotype: Radio velocity [m/s].          */
-         wave,			/* wavetype: Vacuum wavelength [m].         */
-         vopt,			/* velotype: Optical velocity [m/s].        */
-         zopt,			/* velotype: Redshift.                      */
-         awav,			/* wavetype: Air wavelength [m].            */
-         velo,			/* velotype: Relativistic velocity [m/s].   */
-         beta;			/* velotype: Relativistic beta.             */
-
-  /* Derivatives of spectral variables computed by specx().                 */
-  /*------------------------------------------------------------------------*/
-  double dfreqafrq, dafrqfreq,	/* Constant, always available.              */
-         dfreqener, denerfreq,	/* Constant, always available.              */
-         dfreqwavn, dwavnfreq,	/* Constant, always available.              */
-         dfreqvrad, dvradfreq,	/* wavetype && velotype.                    */
-         dfreqwave, dwavefreq,	/* wavetype.                                */
-         dfreqawav, dawavfreq,	/* wavetype.                                */
-         dfreqvelo, dvelofreq,	/* wavetype && velotype.                    */
-         dwavevopt, dvoptwave,	/* wavetype && velotype.                    */
-         dwavezopt, dzoptwave,	/* wavetype && velotype.                    */
-         dwaveawav, dawavwave,	/* wavetype.                                */
-         dwavevelo, dvelowave,	/* wavetype && velotype.                    */
-         dawavvelo, dveloawav,	/* wavetype && velotype.                    */
-         dvelobeta, dbetavelo;	/* Constant, always available.              */
-
-  /* Error handling                                                         */
-  /*------------------------------------------------------------------------*/
-  struct wcserr *err;
-
-  /* Private                                                                */
-  /*------------------------------------------------------------------------*/
-  void   *padding;		/* (Dummy inserted for alignment purposes.) */
-};
-
-/* Size of the spxprm struct in int units, used by the Fortran wrappers. */
-#define SPXLEN (sizeof(struct spxprm)/sizeof(int))
-
-
-int specx(const char *type, double spec, double restfrq, double restwav,
-          struct spxprm *specs);
-
-
-/* For use in declaring function prototypes, e.g. in spcprm. */
-#define SPX_ARGS double param, int nspec, int instep, int outstep, \
-    const double inspec[], double outspec[], int stat[]
-
-int freqafrq(SPX_ARGS);
-int afrqfreq(SPX_ARGS);
-
-int freqener(SPX_ARGS);
-int enerfreq(SPX_ARGS);
-
-int freqwavn(SPX_ARGS);
-int wavnfreq(SPX_ARGS);
-
-int freqwave(SPX_ARGS);
-int wavefreq(SPX_ARGS);
-
-int freqawav(SPX_ARGS);
-int awavfreq(SPX_ARGS);
-
-int waveawav(SPX_ARGS);
-int awavwave(SPX_ARGS);
-
-int velobeta(SPX_ARGS);
-int betavelo(SPX_ARGS);
-
-
-int freqvelo(SPX_ARGS);
-int velofreq(SPX_ARGS);
-
-int freqvrad(SPX_ARGS);
-int vradfreq(SPX_ARGS);
-
-
-int wavevelo(SPX_ARGS);
-int velowave(SPX_ARGS);
-
-int awavvelo(SPX_ARGS);
-int veloawav(SPX_ARGS);
-
-int wavevopt(SPX_ARGS);
-int voptwave(SPX_ARGS);
-
-int wavezopt(SPX_ARGS);
-int zoptwave(SPX_ARGS);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* WCSLIB_SPEC */
diff --git a/astropy/wcs/src/wcslib/C/tab.c b/astropy/wcs/src/wcslib/C/tab.c
deleted file mode 100644
index eacdbde..0000000
--- a/astropy/wcs/src/wcslib/C/tab.c
+++ /dev/null
@@ -1,1587 +0,0 @@
-/*============================================================================
-
-  WCSLIB 4.10 - an implementation of the FITS WCS standard.
-  Copyright (C) 1995-2012, Mark Calabretta
-
-  This file is part of WCSLIB.
-
-  WCSLIB is free software: you can redistribute it and/or modify it under the
-  terms of the GNU Lesser General Public License as published by the Free
-  Software Foundation, either version 3 of the License, or (at your option)
-  any later version.
-
-  WCSLIB 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 Lesser General Public License for
-  more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with WCSLIB.  If not, see <http://www.gnu.org/licenses/>.
-
-  Correspondence concerning WCSLIB may be directed to:
-    Internet email: mcalabre at atnf.csiro.au
-    Postal address: Dr. Mark Calabretta
-                    Australia Telescope National Facility, CSIRO
-                    PO Box 76
-                    Epping NSW 1710
-                    AUSTRALIA
-
-  Author: Mark Calabretta, Australia Telescope National Facility
-  http://www.atnf.csiro.au/~mcalabre/index.html
-  $Id: tab.c,v 4.10 2012/02/05 23:41:44 cal103 Exp $
-*===========================================================================*/
-
-#include <math.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "wcserr.h"
-#include "wcsmath.h"
-#include "wcsprintf.h"
-#include "tab.h"
-
-const int TABSET = 137;
-
-/* Map status return value to message. */
-const char *tab_errmsg[] = {
-  "Success",
-  "Null tabprm pointer passed",
-  "Memory allocation failed",
-  "Invalid tabular parameters",
-  "One or more of the x coordinates were invalid",
-  "One or more of the world coordinates were invalid"};
-
-/* Convenience macro for invoking wcserr_set(). */
-#define TAB_ERRMSG(status) WCSERR_SET(status), tab_errmsg[status]
-
-/*--------------------------------------------------------------------------*/
-
-int tabini(int alloc, int M, const int K[], struct tabprm *tab)
-
-{
-  static const char *function = "tabini";
-
-  int k, m, N;
-  double *dp;
-  struct wcserr **err;
-
-  if (tab == 0x0) return TABERR_NULL_POINTER;
-
-  /* Initialize error message handling. */
-  err = &(tab->err);
-  if (tab->err && tab->flag != -1) {
-    free(tab->err);
-  }
-  tab->err = 0x0;
-
-
-  if (M <= 0) {
-    return wcserr_set(WCSERR_SET(TABERR_BAD_PARAMS),
-      "M must be positive, got %d", M);
-  }
-
-  /* Determine the total number of elements in the coordinate array. */
-  if (K) {
-    N = M;
-
-    for (m = 0; m < M; m++) {
-      if (K[m] < 0) {
-        return wcserr_set(WCSERR_SET(TABERR_BAD_PARAMS),
-          "Invalid tabular parameters: Each element of K must be "
-          "non-negative, got %d", K[m]);
-      }
-
-      N *= K[m];
-    }
-
-  } else {
-    /* Axis lengths as yet unknown. */
-    N = 0;
-  }
-
-
-  /* Initialize memory management. */
-  if (tab->flag == -1 || tab->m_flag != TABSET) {
-    tab->m_flag  = 0;
-    tab->m_M     = 0;
-    tab->m_N     = 0;
-    tab->m_K     = 0x0;
-    tab->m_map   = 0x0;
-    tab->m_crval = 0x0;
-    tab->m_index = 0x0;
-    tab->m_indxs = 0x0;
-    tab->m_coord = 0x0;
-
-  } else {
-    /* Clear any outstanding signals set by wcstab(). */
-    for (m = 0; m < tab->m_M; m++) {
-      if (tab->m_indxs[m] == (double *)0x1) tab->m_indxs[m] = 0x0;
-    }
-
-    if (tab->m_coord == (double *)0x1) tab->m_coord = 0x0;
-  }
-
-  if (tab->flag == -1) {
-    tab->sense   = 0x0;
-    tab->p0      = 0x0;
-    tab->delta   = 0x0;
-    tab->extrema = 0x0;
-    tab->set_M   = 0;
-  }
-
-
-  /* Allocate memory for arrays if required. */
-  if (alloc ||
-     tab->K == 0x0 ||
-     tab->map == 0x0 ||
-     tab->crval == 0x0 ||
-     tab->index == 0x0 ||
-     tab->coord == 0x0) {
-
-    /* Was sufficient allocated previously? */
-    if (tab->m_flag == TABSET && (tab->m_M < M || tab->m_N < N)) {
-      /* No, free it. */
-      tabfree(tab);
-    }
-
-    if (alloc || tab->K == 0x0) {
-      if (tab->m_K) {
-        /* In case the caller fiddled with it. */
-        tab->K = tab->m_K;
-
-      } else {
-        if (!(tab->K = calloc(M, sizeof(int)))) {
-          return wcserr_set(TAB_ERRMSG(TABERR_MEMORY));
-        }
-
-        tab->m_flag = TABSET;
-        tab->m_M = M;
-        tab->m_K = tab->K;
-      }
-    }
-
-    if (alloc || tab->map == 0x0) {
-      if (tab->m_map) {
-        /* In case the caller fiddled with it. */
-        tab->map = tab->m_map;
-
-      } else {
-        if (!(tab->map = calloc(M, sizeof(int)))) {
-          return wcserr_set(TAB_ERRMSG(TABERR_MEMORY));
-        }
-
-        tab->m_flag = TABSET;
-        tab->m_M = M;
-        tab->m_map = tab->map;
-      }
-    }
-
-    if (alloc || tab->crval == 0x0) {
-      if (tab->m_crval) {
-        /* In case the caller fiddled with it. */
-        tab->crval = tab->m_crval;
-
-      } else {
-        if (!(tab->crval = calloc(M, sizeof(double)))) {
-          return wcserr_set(TAB_ERRMSG(TABERR_MEMORY));
-        }
-
-        tab->m_flag = TABSET;
-        tab->m_M = M;
-        tab->m_crval = tab->crval;
-      }
-    }
-
-    if (alloc || tab->index == 0x0) {
-      if (tab->m_index) {
-        /* In case the caller fiddled with it. */
-        tab->index = tab->m_index;
-
-      } else {
-        if (!(tab->index = calloc(M, sizeof(double *)))) {
-          return wcserr_set(TAB_ERRMSG(TABERR_MEMORY));
-        }
-
-        tab->m_flag = TABSET;
-        tab->m_M = M;
-        tab->m_N = N;
-        tab->m_index = tab->index;
-
-        if (!(tab->m_indxs = calloc(M, sizeof(double *)))) {
-          return wcserr_set(TAB_ERRMSG(TABERR_MEMORY));
-        }
-
-        /* Recall that calloc() initializes these pointers to zero. */
-        if (K) {
-          for (m = 0; m < M; m++) {
-            if (K[m]) {
-              if (!(tab->index[m] = calloc(K[m], sizeof(double)))) {
-                return wcserr_set(TAB_ERRMSG(TABERR_MEMORY));
-              }
-
-              tab->m_indxs[m] = tab->index[m];
-            }
-          }
-        }
-      }
-    }
-
-    if (alloc || tab->coord == 0x0) {
-      if (tab->m_coord) {
-        /* In case the caller fiddled with it. */
-        tab->coord = tab->m_coord;
-
-      } else if (N) {
-        if (!(tab->coord = calloc(N, sizeof(double)))) {
-          return wcserr_set(TAB_ERRMSG(TABERR_MEMORY));
-        }
-
-        tab->m_flag = TABSET;
-        tab->m_M = M;
-        tab->m_N = N;
-        tab->m_coord = tab->coord;
-      }
-    }
-  }
-
-  tab->flag = 0;
-  tab->M = M;
-
-  /* Set defaults. */
-  for (m = 0; m < M; m++) {
-    tab->map[m] = -1;
-    tab->crval[m] = 0.0;
-
-    if (K) {
-      tab->K[m] = K[m];
-      if ((dp = tab->index[m])) {
-        for (k = 0; k < K[m]; k++) {
-          *(dp++) = k;
-        }
-      }
-    } else {
-      tab->K[m] = 0;
-    }
-  }
-
-  /* Initialize the coordinate array. */
-  for (dp = tab->coord; dp < tab->coord + N; dp++) {
-    *dp = UNDEFINED;
-  }
-
-  return 0;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int tabmem(struct tabprm *tab)
-
-{
-  static const char *function = "tabmem";
-
-  int m, M, N;
-  struct wcserr **err;
-
-  if (tab == 0x0) return TABERR_NULL_POINTER;
-  err = &(tab->err);
-
-  if (tab->M == 0 || tab->K == 0x0) {
-    /* Should have been set by this time. */
-    return wcserr_set(WCSERR_SET(TABERR_MEMORY),
-      "Null pointers in tabprm struct");
-  }
-
-
-  N = M = tab->M;
-  for (m = 0; m < M; m++) {
-    if (tab->K[m] < 0) {
-      return wcserr_set(WCSERR_SET(TABERR_BAD_PARAMS),
-        "Invalid tabular parameters: Each element of K must be "
-        "non-negative, got %d", M);
-    }
-
-    N *= tab->K[m];
-  }
-
-
-  if (tab->m_M == 0) {
-    tab->m_M = M;
-  } else if (tab->m_M < M) {
-    /* Only possible if the user changed M. */
-    return wcserr_set(WCSERR_SET(TABERR_MEMORY),
-      "tabprm struct inconsistent");
-  }
-
-  if (tab->m_N == 0) {
-    tab->m_N = N;
-  } else if (tab->m_N < N) {
-    /* Only possible if the user changed K[]. */
-    return wcserr_set(WCSERR_SET(TABERR_MEMORY),
-      "tabprm struct inconsistent");
-  }
-
-  if (tab->m_K == 0x0) {
-    if ((tab->m_K = tab->K)) {
-      tab->m_flag = TABSET;
-    }
-  }
-
-  if (tab->m_map == 0x0) {
-    if ((tab->m_map = tab->map)) {
-      tab->m_flag = TABSET;
-    }
-  }
-
-  if (tab->m_crval == 0x0) {
-    if ((tab->m_crval = tab->crval)) {
-      tab->m_flag = TABSET;
-    }
-  }
-
-  if (tab->m_index == 0x0) {
-    if ((tab->m_index = tab->index)) {
-      tab->m_flag = TABSET;
-    }
-  }
-
-  for (m = 0; m < tab->m_M; m++) {
-    if (tab->m_indxs[m] == 0x0 || tab->m_indxs[m] == (double *)0x1) {
-      if ((tab->m_indxs[m] = tab->index[m])) {
-        tab->m_flag = TABSET;
-      }
-    }
-  }
-
-  if (tab->m_coord == 0x0 || tab->m_coord == (double *)0x1) {
-    if ((tab->m_coord = tab->coord)) {
-      tab->m_flag = TABSET;
-    }
-  }
-
-  tab->flag = 0;
-
-  return 0;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int tabcpy(int alloc, const struct tabprm *tabsrc, struct tabprm *tabdst)
-
-{
-  static const char *function = "tabcpy";
-
-  int k, m, M, n, N, status;
-  double *dstp, *srcp;
-  struct wcserr **err;
-
-  if (tabsrc == 0x0) return TABERR_NULL_POINTER;
-  if (tabdst == 0x0) return TABERR_NULL_POINTER;
-  err = &(tabdst->err);
-
-  M = tabsrc->M;
-  if (M <= 0) {
-    return wcserr_set(WCSERR_SET(TABERR_BAD_PARAMS),
-      "M must be positive, got %d", M);
-  }
-
-  if ((status = tabini(alloc, M, tabsrc->K, tabdst))) {
-    return status;
-  }
-
-  N = M;
-  for (m = 0; m < M; m++) {
-    tabdst->map[m]   = tabsrc->map[m];
-    tabdst->crval[m] = tabsrc->crval[m];
-    N *= tabsrc->K[m];
-  }
-
-  for (m = 0; m < M; m++) {
-    if ((srcp = tabsrc->index[m])) {
-      dstp = tabdst->index[m];
-      for (k = 0; k < tabsrc->K[m]; k++) {
-        *(dstp++) = *(srcp++);
-      }
-    }
-  }
-
-  srcp = tabsrc->coord;
-  dstp = tabdst->coord;
-  for (n = 0; n < N; n++) {
-    *(dstp++) = *(srcp++);
-  }
-
-  return 0;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int tabfree(struct tabprm *tab)
-
-{
-  int m;
-
-  if (tab == 0x0) return TABERR_NULL_POINTER;
-
-  if (tab->flag != -1) {
-    /* Clear any outstanding signals set by wcstab(). */
-    for (m = 0; m < tab->m_M; m++) {
-      if (tab->m_indxs[m] == (double *)0x1) tab->m_indxs[m] = 0x0;
-    }
-
-    if (tab->m_coord == (double *)0x1) tab->m_coord = 0x0;
-
-    /* Free memory allocated by tabini(). */
-    if (tab->m_flag == TABSET) {
-      if (tab->K     == tab->m_K)     tab->K = 0x0;
-      if (tab->map   == tab->m_map)   tab->map = 0x0;
-      if (tab->crval == tab->m_crval) tab->crval = 0x0;
-      if (tab->index == tab->m_index) tab->index = 0x0;
-      if (tab->coord == tab->m_coord) tab->coord = 0x0;
-
-      if (tab->m_K)     free(tab->m_K);
-      if (tab->m_map)   free(tab->m_map);
-      if (tab->m_crval) free(tab->m_crval);
-
-      if (tab->m_index) {
-        for (m = 0; m < tab->m_M; m++) {
-          if (tab->m_indxs[m]) free(tab->m_indxs[m]);
-        }
-        free(tab->m_index);
-        free(tab->m_indxs);
-      }
-
-      if (tab->m_coord) free(tab->m_coord);
-    }
-
-    /* Free memory allocated by tabset(). */
-    if (tab->sense)   free(tab->sense);
-    if (tab->p0)      free(tab->p0);
-    if (tab->delta)   free(tab->delta);
-    if (tab->extrema) free(tab->extrema);
-  }
-
-  tab->m_flag  = 0;
-  tab->m_M     = 0;
-  tab->m_N     = 0;
-  tab->m_K     = 0x0;
-  tab->m_map   = 0x0;
-  tab->m_crval = 0x0;
-  tab->m_index = 0x0;
-  tab->m_indxs = 0x0;
-  tab->m_coord = 0x0;
-
-  tab->sense   = 0x0;
-  tab->p0      = 0x0;
-  tab->delta   = 0x0;
-  tab->extrema = 0x0;
-  tab->set_M   = 0;
-
-  if (tab->err) free(tab->err);
-  tab->err = 0x0;
-
-  tab->flag = 0;
-
-  return 0;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int tabprt(const struct tabprm *tab)
-
-{
-  char   *cp, text[128];
-  int    j, k, m, n, nd;
-  double *dp;
-
-  if (tab == 0x0) return TABERR_NULL_POINTER;
-
-  if (tab->flag != TABSET) {
-    wcsprintf("The tabprm struct is UNINITIALIZED.\n");
-    return 0;
-  }
-
-  wcsprintf("       flag: %d\n", tab->flag);
-  wcsprintf("          M: %d\n", tab->M);
-
-  /* Array dimensions. */
-  WCSPRINTF_PTR("          K: ", tab->K, "\n");
-  wcsprintf("            ");
-  for (m = 0; m < tab->M; m++) {
-    wcsprintf("%6d", tab->K[m]);
-  }
-  wcsprintf("\n");
-
-  /* Map vector. */
-  WCSPRINTF_PTR("        map: ", tab->map, "\n");
-  wcsprintf("            ");
-  for (m = 0; m < tab->M; m++) {
-    wcsprintf("%6d", tab->map[m]);
-  }
-  wcsprintf("\n");
-
-  /* Reference index value. */
-  WCSPRINTF_PTR("      crval: ", tab->crval, "\n");
-  wcsprintf("            ");
-  for (m = 0; m < tab->M; m++) {
-    wcsprintf("  %- 11.5g", tab->crval[m]);
-  }
-  wcsprintf("\n");
-
-  /* Index vectors. */
-  WCSPRINTF_PTR("      index: ", tab->index, "\n");
-  for (m = 0; m < tab->M; m++) {
-    wcsprintf("   index[%d]: ", m);
-    WCSPRINTF_PTR("", tab->index[m], "");
-    if (tab->index[m]) {
-      for (k = 0; k < tab->K[m]; k++) {
-        if (k%5 == 0) {
-          wcsprintf("\n            ");
-        }
-        wcsprintf("  %- 11.5g", tab->index[m][k]);
-      }
-      wcsprintf("\n");
-    }
-  }
-
-  /* Coordinate array. */
-  WCSPRINTF_PTR("      coord: ", tab->coord, "\n");
-  dp = tab->coord;
-  for (n = 0; n < tab->nc; n++) {
-    /* Array index. */
-    j = n;
-    cp = text;
-    for (m = 0; m < tab->M; m++) {
-      nd = (tab->K[m] < 10) ? 1 : 2;
-      sprintf(cp, ",%*d", nd, j % tab->K[m] + 1);
-      j /= tab->K[m];
-      cp += strlen(cp);
-    }
-
-    wcsprintf("             (*%s)", text);
-    for (m = 0; m < tab->M; m++) {
-      wcsprintf("  %- 11.5g", *(dp++));
-    }
-    wcsprintf("\n");
-  }
-
-  wcsprintf("         nc: %d\n", tab->nc);
-
-  WCSPRINTF_PTR("      sense: ", tab->sense, "\n");
-  if (tab->sense) {
-    wcsprintf("            ");
-    for (m = 0; m < tab->M; m++) {
-      wcsprintf("%6d", tab->sense[m]);
-    }
-    wcsprintf("\n");
-  }
-
-  WCSPRINTF_PTR("         p0: ", tab->p0, "\n");
-  if (tab->p0) {
-    wcsprintf("            ");
-    for (m = 0; m < tab->M; m++) {
-      wcsprintf("%6d", tab->p0[m]);
-    }
-    wcsprintf("\n");
-  }
-
-  WCSPRINTF_PTR("      delta: ", tab->delta, "\n");
-  if (tab->delta) {
-    wcsprintf("            ");
-    for (m = 0; m < tab->M; m++) {
-      wcsprintf("  %- 11.5g", tab->delta[m]);
-    }
-    wcsprintf("\n");
-  }
-
-  WCSPRINTF_PTR("    extrema: ", tab->extrema, "\n");
-  dp = tab->extrema;
-  for (n = 0; n < tab->nc/tab->K[0]; n++) {
-    /* Array index. */
-    j = n;
-    cp = text;
-    *cp = '\0';
-    for (m = 1; m < tab->M; m++) {
-      nd = (tab->K[m] < 10) ? 1 : 2;
-      sprintf(cp, ",%*d", nd, j % tab->K[m] + 1);
-      j /= tab->K[m];
-      cp += strlen(cp);
-    }
-
-    wcsprintf("             (*,*%s)", text);
-    for (m = 0; m < 2*tab->M; m++) {
-      if (m == tab->M) wcsprintf("->  ");
-      wcsprintf("  %- 11.5g", *(dp++));
-    }
-    wcsprintf("\n");
-  }
-
-  WCSPRINTF_PTR("        err: ", tab->err, "\n");
-  if (tab->err) {
-    wcserr_prt(tab->err, "             ");
-  }
-
-  /* Memory management. */
-  wcsprintf("     m_flag: %d\n", tab->m_flag);
-  wcsprintf("        m_M: %d\n", tab->m_M);
-  wcsprintf("        m_N: %d\n", tab->m_N);
-
-  WCSPRINTF_PTR("        m_K: ", tab->m_K, "");
-  if (tab->m_K == tab->K) wcsprintf("  (= K)");
-  wcsprintf("\n");
-
-  WCSPRINTF_PTR("      m_map: ", tab->m_map, "");
-  if (tab->m_map == tab->map) wcsprintf("  (= map)");
-  wcsprintf("\n");
-
-  WCSPRINTF_PTR("    m_crval: ", tab->m_crval, "");
-  if (tab->m_crval == tab->crval) wcsprintf("  (= crval)");
-  wcsprintf("\n");
-
-  WCSPRINTF_PTR("    m_index: ", tab->m_index, "");
-  if (tab->m_index == tab->index) wcsprintf("  (= index)");
-  wcsprintf("\n");
-  for (m = 0; m < tab->M; m++) {
-    wcsprintf(" m_indxs[%d]: ", m);
-    WCSPRINTF_PTR("", tab->m_indxs[m], "");
-    if (tab->m_indxs[m] == tab->index[m]) wcsprintf("  (= index[%d])", m);
-    wcsprintf("\n");
-  }
-
-  WCSPRINTF_PTR("    m_coord: ", tab->m_coord, "");
-  if (tab->m_coord == tab->coord) wcsprintf("  (= coord)");
-  wcsprintf("\n");
-
-  return 0;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int tabset(struct tabprm *tab)
-
-{
-  static const char *function = "tabset";
-
-  int i, ic, k, *Km, m, M, ne;
-  double *dcrd, *dmax, *dmin, dPsi, dval, *Psi;
-  struct wcserr **err;
-
-  if (tab == 0x0) return TABERR_NULL_POINTER;
-  err = &(tab->err);
-
-  /* Check the number of tabular coordinate axes. */
-  if ((M = tab->M) < 1) {
-    return wcserr_set(WCSERR_SET(TABERR_BAD_PARAMS),
-      "Invalid tabular parameters: M must be positive, got %d", M);
-  }
-
-  /* Check the axis lengths. */
-  if (!tab->K) {
-    return wcserr_set(WCSERR_SET(TABERR_MEMORY),
-      "Null pointers in tabprm struct");
-  }
-
-  tab->nc = 1;
-  for (m = 0; m < M; m++) {
-    if (tab->K[m] < 1) {
-      return wcserr_set(WCSERR_SET(TABERR_BAD_PARAMS),
-        "Invalid tabular parameters: Each element of K must be positive, "
-        "got %d", tab->K[m]);
-    }
-
-    /* Number of coordinate vectors in the coordinate array. */
-    tab->nc *= tab->K[m];
-  }
-
-  /* Check that the map vector is sensible. */
-  if (!tab->map) {
-    return wcserr_set(WCSERR_SET(TABERR_MEMORY),
-      "Null pointers in tabprm struct");
-  }
-
-  for (m = 0; m < M; m++) {
-    i = tab->map[m];
-    if (i < 0) {
-      return wcserr_set(WCSERR_SET(TABERR_BAD_PARAMS),
-        "Invalid tabular parameters: Each element of map must be "
-        "non-negative, got %d", i);
-    }
-  }
-
-  /* Check memory allocation for the remaining vectors. */
-  if (!tab->crval || !tab->index || !tab->coord) {
-    return wcserr_set(WCSERR_SET(TABERR_MEMORY),
-      "Null pointers in tabprm struct");
-  }
-
-  /* Take memory if signalled to by wcstab(). */
-  for (m = 0; m < tab->m_M; m++) {
-    if (tab->m_indxs[m] == (double *)0x1 &&
-      (tab->m_indxs[m] = tab->index[m])) {
-      tab->m_flag = TABSET;
-    }
-  }
-
-  if (tab->m_coord == (double *)0x1 &&
-    (tab->m_coord = tab->coord)) {
-    tab->m_flag = TABSET;
-  }
-
-
-  /* Allocate memory for work vectors. */
-  if (tab->flag != TABSET || tab->set_M < M) {
-    /* Free memory that may have been allocated previously. */
-    if (tab->sense)   free(tab->sense);
-    if (tab->p0)      free(tab->p0);
-    if (tab->delta)   free(tab->delta);
-    if (tab->extrema) free(tab->extrema);
-
-    /* Allocate memory for internal arrays. */
-    if (!(tab->sense = calloc(M, sizeof(int)))) {
-      return wcserr_set(TAB_ERRMSG(TABERR_MEMORY));
-    }
-
-    if (!(tab->p0 = calloc(M, sizeof(int)))) {
-      free(tab->sense);
-      return wcserr_set(TAB_ERRMSG(TABERR_MEMORY));
-    }
-
-    if (!(tab->delta = calloc(M, sizeof(double)))) {
-      free(tab->sense);
-      free(tab->p0);
-      return wcserr_set(TAB_ERRMSG(TABERR_MEMORY));
-    }
-
-    ne = M * tab->nc * 2 / tab->K[0];
-    if (!(tab->extrema = calloc(ne, sizeof(double)))) {
-      free(tab->sense);
-      free(tab->p0);
-      free(tab->delta);
-      return wcserr_set(TAB_ERRMSG(TABERR_MEMORY));
-    }
-
-    tab->set_M = M;
-  }
-
-  /* Check that the index vectors are monotonic. */
-  Km = tab->K;
-  for (m = 0; m < M; m++, Km++) {
-    tab->sense[m] = 0;
-
-    if (*Km > 1) {
-      if ((Psi = tab->index[m]) == 0x0) {
-        /* Default indexing. */
-        tab->sense[m] = 1;
-
-      } else {
-        for (k = 0; k < *Km-1; k++) {
-          switch (tab->sense[m]) {
-          case 0:
-            if (Psi[k] < Psi[k+1]) {
-              /* Monotonic increasing. */
-              tab->sense[m] = 1;
-            } else if (Psi[k] > Psi[k+1]) {
-              /* Monotonic decreasing. */
-              tab->sense[m] = -1;
-            }
-            break;
-
-          case 1:
-            if (Psi[k] > Psi[k+1]) {
-              /* Should be monotonic increasing. */
-              free(tab->sense);
-              free(tab->p0);
-              free(tab->delta);
-              free(tab->extrema);
-              return wcserr_set(WCSERR_SET(TABERR_BAD_PARAMS),
-                "Invalid tabular parameters: Index vectors are not "
-                "monotonically increasing");
-            }
-            break;
-
-          case -1:
-            if (Psi[k] < Psi[k+1]) {
-              /* Should be monotonic decreasing. */
-              free(tab->sense);
-              free(tab->p0);
-              free(tab->delta);
-              free(tab->extrema);
-              return wcserr_set(WCSERR_SET(TABERR_BAD_PARAMS),
-                "Invalid tabular parameters: Index vectors are not "
-                "monotonically decreasing");
-            }
-            break;
-          }
-        }
-      }
-
-      if (tab->sense[m] == 0) {
-        free(tab->sense);
-        free(tab->p0);
-        free(tab->delta);
-        free(tab->extrema);
-        return wcserr_set(WCSERR_SET(TABERR_BAD_PARAMS),
-          "Invalid tabular parameters: Index vectors are not monotonic");
-      }
-    }
-  }
-
-  /* Find the extremal values of the coordinate elements in each row. */
-  dcrd = tab->coord;
-  dmin = tab->extrema;
-  dmax = tab->extrema + M;
-  for (ic = 0; ic < tab->nc; ic += tab->K[0]) {
-    for (m = 0; m < M; m++, dcrd++) {
-      if (tab->K[0] > 1) {
-        /* Extrapolate a little before the start of the row. */
-        Psi = tab->index[0];
-        if (Psi == 0x0) {
-          dPsi = 1.0;
-        } else {
-          dPsi = Psi[1] - Psi[0];
-        }
-
-        dval = *dcrd;
-        if (dPsi != 0.0) {
-          dval -= 0.5 * (*(dcrd+M) - *dcrd)/dPsi;
-        }
-
-        *(dmax+m) = *(dmin+m) = dval;
-      } else {
-        *(dmax+m) = *(dmin+m) = *dcrd;
-      }
-    }
-
-    dcrd -= M;
-    for (i = 0; i < tab->K[0]; i++) {
-      for (m = 0; m < M; m++, dcrd++) {
-        if (*(dmax+m) < *dcrd) *(dmax+m) = *dcrd;
-        if (*(dmin+m) > *dcrd) *(dmin+m) = *dcrd;
-
-        if (tab->K[0] > 1 && i == tab->K[0]-1) {
-          /* Extrapolate a little beyond the end of the row. */
-          Psi = tab->index[0];
-          if (Psi == 0x0) {
-            dPsi = 1.0;
-          } else {
-            dPsi = Psi[i] - Psi[i-1];
-          }
-
-          dval = *dcrd;
-          if (dPsi != 0.0) {
-            dval += 0.5 * (*dcrd - *(dcrd-M))/dPsi;
-          }
-
-          if (*(dmax+m) < dval) *(dmax+m) = dval;
-          if (*(dmin+m) > dval) *(dmin+m) = dval;
-        }
-      }
-    }
-
-    dmin += 2*M;
-    dmax += 2*M;
-  }
-
-  tab->flag = TABSET;
-
-  return 0;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int tabx2s(
-  struct tabprm *tab,
-  int ncoord,
-  int nelem,
-  const double x[],
-  double world[],
-  int stat[])
-
-{
-  static const char *function = "tabx2s";
-
-  int i, iv, k, *Km, m, M, n, nv, offset, p1, status;
-  double *coord, *Psi, psi_m, upsilon, wgt;
-  register int *statp;
-  register const double *xp;
-  register double *wp;
-  struct wcserr **err;
-
-  if (tab == 0x0) return TABERR_NULL_POINTER;
-  err = &(tab->err);
-
-  /* Initialize if required. */
-  if (tab->flag != TABSET) {
-    if ((status = tabset(tab))) return status;
-  }
-
-  /* This is used a lot. */
-  M = tab->M;
-
-  status = 0;
-  xp = x;
-  wp = world;
-  statp = stat;
-  for (n = 0; n < ncoord; n++) {
-    /* Determine the indexes. */
-    Km = tab->K;
-    for (m = 0; m < M; m++, Km++) {
-      /* N.B. psi_m and Upsilon_m are 1-relative FITS indexes. */
-      i = tab->map[m];
-      psi_m = *(xp+i) + tab->crval[m];
-
-      Psi = tab->index[m];
-      if (Psi == 0x0) {
-        /* Default indexing is simple. */
-        upsilon = psi_m;
-
-      } else {
-        /* To ease confusion, decrement Psi so that we can use 1-relative
-           C array indexing to match the 1-relative FITS indexing. */
-        Psi--;
-
-        if (*Km == 1) {
-          /* Index vector is degenerate. */
-          if (Psi[1]-0.5 <= psi_m && psi_m <= Psi[1]+0.5) {
-            upsilon = psi_m;
-          } else {
-            *statp = 1;
-            status = wcserr_set(TAB_ERRMSG(TABERR_BAD_X));
-            goto next;
-          }
-
-        } else {
-          /* Interpolate in the indexing vector. */
-          if (tab->sense[m] == 1) {
-            /* Monotonic increasing index values. */
-            if (psi_m < Psi[1]) {
-              if (Psi[1] - 0.5*(Psi[2]-Psi[1]) <= psi_m) {
-                /* Allow minor extrapolation. */
-                k = 1;
-
-              } else {
-                /* Index is out of range. */
-                *statp = 1;
-                status = wcserr_set(TAB_ERRMSG(TABERR_BAD_X));
-                goto next;
-              }
-
-            } else if (Psi[*Km] < psi_m) {
-              if (psi_m <= Psi[*Km] + 0.5*(Psi[*Km]-Psi[*Km-1])) {
-                /* Allow minor extrapolation. */
-                k = *Km - 1;
-
-              } else {
-                /* Index is out of range. */
-                *statp = 1;
-                status = wcserr_set(TAB_ERRMSG(TABERR_BAD_X));
-                goto next;
-              }
-
-            } else {
-              for (k = 1; k < *Km; k++) {
-                if (psi_m < Psi[k]) {
-                  continue;
-                }
-                if (Psi[k] == psi_m && psi_m < Psi[k+1]) {
-                  break;
-                }
-                if (Psi[k] < psi_m && psi_m <= Psi[k+1]) {
-                  break;
-                }
-              }
-            }
-
-          } else {
-            /* Monotonic decreasing index values. */
-            if (psi_m > Psi[1]) {
-              if (Psi[1] + 0.5*(Psi[1]-Psi[2]) >= psi_m) {
-                /* Allow minor extrapolation. */
-                k = 1;
-
-              } else {
-                /* Index is out of range. */
-                *statp = 1;
-                status = wcserr_set(TAB_ERRMSG(TABERR_BAD_X));
-                goto next;
-              }
-
-            } else if (psi_m < Psi[*Km]) {
-              if (Psi[*Km] - 0.5*(Psi[*Km-1]-Psi[*Km]) <= psi_m) {
-                /* Allow minor extrapolation. */
-                k = *Km - 1;
-
-              } else {
-                /* Index is out of range. */
-                *statp = 1;
-                status = wcserr_set(TAB_ERRMSG(TABERR_BAD_X));
-                goto next;
-              }
-
-            } else {
-              for (k = 1; k < *Km; k++) {
-                if (psi_m > Psi[k]) {
-                  continue;
-                }
-                if (Psi[k] == psi_m && psi_m > Psi[k+1]) {
-                  break;
-                }
-                if (Psi[k] > psi_m && psi_m >= Psi[k+1]) {
-                  break;
-                }
-              }
-            }
-          }
-
-          upsilon = k + (psi_m - Psi[k]) / (Psi[k+1] - Psi[k]);
-        }
-      }
-
-      if (upsilon < 0.5 || upsilon > *Km + 0.5) {
-        /* Index out of range. */
-        *statp = 1;
-        status = wcserr_set(TAB_ERRMSG(TABERR_BAD_X));
-        goto next;
-      }
-
-      /* Fiducial array indices and fractional offset.
-         p1 is 1-relative while tab::p0 is 0-relative. */
-      p1 = (int)floor(upsilon);
-      tab->p0[m] = p1 - 1;
-      tab->delta[m] = upsilon - p1;
-
-      if (p1 == 0) {
-        tab->p0[m] += 1;
-        tab->delta[m] -= 1.0;
-      } else if (p1 == *Km && *Km > 1) {
-        tab->p0[m] -= 1;
-        tab->delta[m] += 1.0;
-      }
-    }
-
-
-    /* Now interpolate in the coordinate array; the M-dimensional linear  */
-    /* interpolation algorithm is described in Sect. 3.4 of WCS Paper IV. */
-    for (m = 0; m < M; m++) {
-     i = tab->map[m];
-     *(wp+i) = 0.0;
-    }
-
-    /* Loop over the 2^M vertices surrounding P. */
-    nv = 1 << M;
-    for (iv = 0; iv < nv; iv++) {
-      /* Locate vertex in the coordinate array and compute its weight. */
-      offset = 0;
-      wgt = 1.0;
-      for (m = M-1; m >= 0; m--) {
-        offset *= tab->K[m];
-        offset += tab->p0[m];
-        if (iv & (1 << m)) {
-          if (tab->K[m] > 1) offset++;
-          wgt *= tab->delta[m];
-        } else {
-          wgt *= 1.0 - tab->delta[m];
-        }
-      }
-
-      if (wgt == 0.0) continue;
-
-      /* Add the contribution from this vertex to each element. */
-      coord = tab->coord + offset*M;
-      for (m = 0; m < M; m++) {
-        i = tab->map[m];
-        *(wp+i) += *(coord++) * wgt;
-      }
-
-      if (wgt == 1.0) break;
-    }
-
-    *statp = 0;
-
-next:
-    xp += nelem;
-    wp += nelem;
-    statp++;
-  }
-
-  return status;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int tabs2x(
-  struct tabprm* tab,
-  int ncoord,
-  int nelem,
-  const double world[],
-  double x[],
-  int stat[])
-
-{
-  static const char *function = "tabs2x";
-
-  int tabedge(struct tabprm *);
-  int tabrow(struct tabprm *, const double *);
-  int tabvox(struct tabprm *, const double *, int, double **, unsigned int *);
-
-  int edge, i, ic, iv, k, *Km, M, m, n, nv, offset, status;
-  double *dcrd, delta, *Psi, psi_m, **tabcoord, upsilon;
-  register int *statp;
-  register const double *wp;
-  register double *xp;
-  struct wcserr **err;
-
-  if (tab == 0x0) return TABERR_NULL_POINTER;
-  err = &(tab->err);
-
-  /* Initialize if required. */
-  if (tab->flag != TABSET) {
-    if ((status = tabset(tab))) return status;
-  }
-
-  /* This is used a lot. */
-  M = tab->M;
-
-  tabcoord = 0x0;
-  nv = 0;
-  if (M > 1) {
-    nv = 1 << M;
-    tabcoord = calloc(nv, sizeof(double *));
-  }
-
-
-  status = 0;
-  wp = world;
-  xp = x;
-  statp = stat;
-  for (n = 0; n < ncoord; n++) {
-    /* Locate this coordinate in the coordinate array. */
-    edge = 0;
-    for (m = 0; m < M; m++) {
-      tab->p0[m] = 0;
-    }
-
-    for (ic = 0; ic < tab->nc; ic++) {
-      if (tab->p0[0] == 0) {
-        /* New row, could it contain a solution? */
-        if (edge || tabrow(tab, wp)) {
-          /* No, skip it. */
-          ic += tab->K[0];
-          tab->p0[1]++;
-          edge = tabedge(tab);
-
-          /* Because ic will be incremented when the loop is reentered. */
-          ic--;
-          continue;
-        }
-      }
-
-      if (M == 1) {
-        /* Deal with the one-dimensional case separately for efficiency. */
-        if (*wp == tab->coord[0]) {
-          tab->p0[0] = 0;
-          tab->delta[0] = 0.0;
-          break;
-
-        } else if (ic < tab->nc - 1) {
-          if (((tab->coord[ic] <= *wp && *wp <= tab->coord[ic+1]) ||
-               (tab->coord[ic] >= *wp && *wp >= tab->coord[ic+1])) &&
-               (tab->index[0] == 0x0 ||
-                tab->index[0][ic] != tab->index[0][ic+1])) {
-            tab->p0[0] = ic;
-            tab->delta[0] = (*wp - tab->coord[ic]) /
-                            (tab->coord[ic+1] - tab->coord[ic]);
-            break;
-          }
-        }
-
-      } else {
-        /* Multi-dimensional tables are harder. */
-        if (!edge) {
-          /* Addresses of the coordinates for each corner of the "voxel". */
-          for (iv = 0; iv < nv; iv++) {
-            offset = 0;
-            for (m = M-1; m >= 0; m--) {
-              offset *= tab->K[m];
-              offset += tab->p0[m];
-              if ((iv & (1 << m)) && (tab->K[m] > 1)) offset++;
-            }
-            tabcoord[iv] = tab->coord + offset*M;
-          }
-
-          if (tabvox(tab, wp, 0, tabcoord, 0x0) == 0) {
-            /* Found a solution. */
-            break;
-          }
-        }
-
-        /* Next voxel. */
-        tab->p0[0]++;
-        edge = tabedge(tab);
-      }
-    }
-
-
-    if (ic == tab->nc) {
-      /* Coordinate not found; allow minor extrapolation. */
-      if (M == 1) {
-        /* Should there be a solution? */
-        if (tab->extrema[0] <= *wp && *wp <= tab->extrema[1]) {
-          dcrd = tab->coord;
-          for (i = 0; i < 2; i++) {
-            if (i) dcrd += tab->K[0] - 2;
-
-            delta = (*wp - *dcrd) / (*(dcrd+1) - *dcrd);
-
-            if (i == 0) {
-              if (-0.5 <= delta && delta <= 0.0) {
-                tab->p0[0] = 0;
-                tab->delta[0] = delta;
-                ic = 0;
-                break;
-              }
-            } else {
-              if (1.0 <= delta && delta <= 1.5) {
-                tab->p0[0] = tab->K[0] - 1;
-                tab->delta[0] = delta - 1.0;
-                ic = 0;
-              }
-            }
-          }
-        }
-
-      } else {
-        /* Multi-dimensional tables. */
-        /* >>> TBD <<< */
-      }
-    }
-
-
-    if (ic == tab->nc) {
-      /* Coordinate not found. */
-      *statp = 1;
-      status = wcserr_set(TAB_ERRMSG(TABERR_BAD_WORLD));
-    } else {
-      /* Determine the intermediate world coordinates. */
-      Km = tab->K;
-      for (m = 0; m < M; m++, Km++) {
-        /* N.B. Upsilon_m and psi_m are 1-relative FITS indexes. */
-        upsilon = (tab->p0[m] + 1) + tab->delta[m];
-
-        if (upsilon < 0.5 || upsilon > *Km + 0.5) {
-          /* Index out of range. */
-          *statp = 1;
-          status = wcserr_set(TAB_ERRMSG(TABERR_BAD_WORLD));
-
-        } else {
-          /* Do inverse lookup of the index vector. */
-          Psi = tab->index[m];
-          if (Psi == 0x0) {
-            /* Default indexing. */
-            psi_m = upsilon;
-
-          } else {
-            /* Decrement Psi and use 1-relative C array indexing to match the
-               1-relative FITS indexing. */
-            Psi--;
-
-            if (*Km == 1) {
-              /* Degenerate index vector. */
-              psi_m = Psi[1];
-            } else {
-              k = (int)(upsilon);
-              psi_m = Psi[k];
-              if (k < *Km) {
-                psi_m += (upsilon - k) * (Psi[k+1] - Psi[k]);
-              }
-            }
-          }
-
-          i = tab->map[m];
-          xp[i] = psi_m - tab->crval[m];
-        }
-      }
-      *statp = 0;
-    }
-
-    wp += nelem;
-    xp += nelem;
-    statp++;
-  }
-
-  if (M > 1) free(tabcoord);
-
-  return status;
-}
-
-/*----------------------------------------------------------------------------
-* Convenience routine to deal with of edge effects in tabprm::p0.
-*---------------------------------------------------------------------------*/
-
-int tabedge(struct tabprm* tab)
-
-{
-  int edge, *Km, m;
-
-  edge = 0;
-  Km = tab->K;
-  for (m = 0; m < tab->M; m++, Km++) {
-    if (tab->p0[m] == *Km) {
-      /* p0 has been incremented beyond the end of the row, point it to the
-         next one. */
-      tab->p0[m] = 0;
-      tab->p0[m+1]++;
-    } else if (tab->p0[m] == *Km - 1 && *Km > 1) {
-      /* p0 is sitting at the end of a non-degenerate row. */
-      edge = 1;
-    }
-  }
-
-  return edge;
-}
-
-/*----------------------------------------------------------------------------
-* Quick test to see whether the world coordinate indicated by wp could lie
-* somewhere along (or near) the row of the image indexed by tabprm::p0.
-* Return 0 if so, 1 otherwise.
-*
-* tabprm::p0 selects a particular row of the image, p0[0] being ignored (i.e.
-* treated as zero).  Adjacent rows that delimit a row of "voxels" are formed
-* by incrementing elements other than p0[0] in all binary combinations.  N.B.
-* these are not the same as the voxels (pixels) that are indexed by, and
-* centred on, integral pixel coordinates in FITS.
-*
-* To see why it is necessary to examine the adjacent rows, consider the 2-D
-* case where the first world coordinate element is constant along each row.
-* If the first element of wp has value 0.5, and its value in the row indexed
-* by p0 has value 0, and in the next row it has value 1, then it is clear that
-* the solution lies in neither row but somewhere between them.  Thus both rows
-* will be involved in finding the solution.
-*
-* tabprm::extrema is the address of the first element of a 1-D array that
-* records the minimum and maximum value of each element of the coordinate
-* vector in each row of the coordinate array, treated as though it were
-* defined as
-*
-*   double extrema[K_M]...[K_2][2][M]
-*
-* The minimum is recorded in the first element of the compressed K_1
-* dimension, then the maximum.
-*---------------------------------------------------------------------------*/
-
-int tabrow(struct tabprm* tab, const double *wp)
-
-{
-  int iv, M, m, nv, offset;
-  unsigned int eq, gt, lt;
-  const double tol = 1e-10;
-  double *cp, w;
-
-  M = tab->M;
-
-  /* The number of corners in a "voxel".  We need examine only half this
-     number of rows.  The extra factor of two will be used to select between
-     the minimal and maximal values in each row. */
-  nv = 1 << M;
-
-  eq = 0;
-  lt = 0;
-  gt = 0;
-  for (iv = 0; iv < nv; iv++) {
-    /* Find the index into tabprm::extrema for this row. */
-    offset = 0;
-    for (m = M-1; m > 0; m--) {
-      offset *= tab->K[m];
-      offset += tab->p0[m];
-
-      /* Select the row. */
-      if (iv & (1 << m)) {
-        if (tab->K[m] > 1) offset++;
-      }
-    }
-
-    /* The K_1 dimension has length 2 (see prologue). */
-    offset *= 2;
-
-    /* Select the minimum on even numbered iterations, else the maximum. */
-    if (iv & 1) offset++;
-
-    /* The last dimension has length M (see prologue). */
-    offset *= M;
-
-    /* Address of the extremal elements (min or max) for this row. */
-    cp = tab->extrema + offset;
-
-    /* For each coordinate element, we only need to find one row where its
-       minimum value is less than that of wp, and one row where the maximum
-       value is greater.  That doesn't mean that there is a solution, only
-       that there might be. */
-    for (m = 0; m < M; m++, cp++) {
-      /* Apply the axis mapping. */
-      w = wp[tab->map[m]];
-
-      /* Finally the test itself; set bits in the bitmask. */
-      if (fabs(*cp - w) < tol) {
-        eq |= (1 << m);
-      } else if (*cp < w) {
-        lt |= (1 << m);
-      } else if (*cp > w) {
-        gt |= (1 << m);
-      }
-    }
-
-    /* Have all bits been switched on? */
-    if ((lt | eq) == nv-1 && (gt | eq) == nv-1) {
-      /* A solution could lie within this row of voxels. */
-      return 0;
-    }
-  }
-
-  /* No solution in this row. */
-  return 1;
-}
-
-/*----------------------------------------------------------------------------
-* Does the world coordinate indicated by wp lie within the voxel indexed by
-* tabprm::p0?  If so, do a binary chop of the interior of the voxel to find
-* it and return 0, with tabprm::delta set to the solution.  Else return 1.
-*
-* As in tabrow(), a "voxel" is formed by incrementing the elements of
-* tabprm::p0 in all binary combinations.  Note that these are not the same as
-* the voxels (pixels) that are indexed by, and centred on, integral pixel
-* coordinates in FITS.
-*
-* tabvox() calls itself recursively.  When called from outside, level, being
-* the level of recursion, should be given as zero.  tabcoord is an array
-* holding the addresses of the coordinates for each corner of the voxel.
-* vox is the address of a work array (vox2) used during recursive calls to
-* dissect the voxel.  It is ignored when tabvox() is called from outside
-* (level == 0).
-*
-* It is assumed that the image dimensions are no greater than 16.
-----------------------------------------------------------------------------*/
-
-int tabvox(
-  struct tabprm* tab,
-  const double *wp,
-  int level,
-  double **tabcoord,
-  unsigned int *vox)
-
-{
-  int i, iv, jv, M, m, nv;
-  unsigned int eq, et, gt, lt, vox2[16];
-  const double tol = 1e-10;
-  double coord[16], *cp, dv, w, wgt;
-
-  M = tab->M;
-
-  /* The number of corners in a voxel. */
-  nv = 1 << M;
-
-  dv = 1.0;
-  for (i = 0; i < level; i++) {
-    dv /= 2.0;
-  }
-
-  /* Could the coordinate lie within this voxel (level == 0) or sub-voxel
-     (level > 0)?  We use the fact that with linear interpolation the
-     coordinate elements are extremal in a corner and test each one. */
-  lt = 0;
-  gt = 0;
-  eq = 0;
-  for (iv = 0; iv < nv; iv++) {
-    /* Select a corner of the sub-voxel. */
-    for (m = 0; m < M; m++) {
-      coord[m] = 0.0;
-      tab->delta[m] = level ? dv*vox[m] : 0.0;
-
-      if (iv & (1 << m)) {
-        tab->delta[m] += dv;
-      }
-    }
-
-    /* Compute the coordinates of this corner of the sub-voxel by linear
-       interpolation using the weighting algorithm described in Sect. 3.4 of
-       WCS Paper IV. */
-    for (jv = 0; jv < nv; jv++) {
-      /* Find the weight for this corner of the parent voxel. */
-      wgt = 1.0;
-      for (m = 0; m < M; m++) {
-        if (jv & (1 << m)) {
-          wgt *= tab->delta[m];
-        } else {
-          wgt *= 1.0 - tab->delta[m];
-        }
-      }
-
-      if (wgt == 0.0) continue;
-
-      /* Add its contribution to each coordinate element. */
-      cp = tabcoord[jv];
-      for (m = 0; m < M; m++) {
-        coord[m] += *(cp++) * wgt;
-      }
-
-      if (wgt == 1.0) break;
-    }
-
-    /* Coordinate elements are minimal or maximal in a corner. */
-    et = 0;
-    for (m = 0; m < M; m++) {
-      /* Apply the axis mapping. */
-      w = wp[tab->map[m]];
-
-      /* Finally the test itself; set bits in the bitmask. */
-      if (fabs(coord[m] - w) < tol) {
-        et |= (1 << m);
-      } else if (coord[m] < w) {
-        lt |= (1 << m);
-      } else if (coord[m] > w) {
-        gt |= (1 << m);
-      }
-    }
-
-    if (et == nv-1) {
-      /* We've stumbled across a solution in this corner of the sub-voxel. */
-      return 0;
-    }
-
-    eq |= et;
-  }
-
-  /* Could the coordinate lie within this sub-voxel? */
-  if ((lt | eq) == nv-1 && (gt | eq) == nv-1) {
-    /* Yes it could, but does it? */
-
-    /* Is it time to stop the recursion? */
-    if (level == 31) {
-      /* We have a solution, squeeze out the last bit of juice. */
-      dv /= 2.0;
-      for (m = 0; m < M; m++) {
-        tab->delta[m] = dv * (2.0*vox[m] + 1.0);
-      }
-
-      return 0;
-    }
-
-    /* Subdivide the sub-voxel and try again for each subdivision. */
-    for (iv = 0; iv < nv; iv++) {
-      /* Select the subdivision. */
-      for (m = 0; m < M; m++) {
-        vox2[m] = level ? 2*vox[m] : 0;
-        if (iv & (1 << m)) {
-          vox2[m]++;
-        }
-      }
-
-      /* Recurse. */
-      if (tabvox(tab, wp, level+1, tabcoord, vox2) == 0) {
-        return 0;
-      }
-    }
-  }
-
-  /* No solution in this sub-voxel. */
-  return 1;
-}
diff --git a/astropy/wcs/src/wcslib/C/tab.h b/astropy/wcs/src/wcslib/C/tab.h
deleted file mode 100644
index b868866..0000000
--- a/astropy/wcs/src/wcslib/C/tab.h
+++ /dev/null
@@ -1,586 +0,0 @@
-/*============================================================================
-
-  WCSLIB 4.10 - an implementation of the FITS WCS standard.
-  Copyright (C) 1995-2012, Mark Calabretta
-
-  This file is part of WCSLIB.
-
-  WCSLIB is free software: you can redistribute it and/or modify it under the
-  terms of the GNU Lesser General Public License as published by the Free
-  Software Foundation, either version 3 of the License, or (at your option)
-  any later version.
-
-  WCSLIB 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 Lesser General Public License for
-  more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with WCSLIB.  If not, see <http://www.gnu.org/licenses/>.
-
-  Correspondence concerning WCSLIB may be directed to:
-    Internet email: mcalabre at atnf.csiro.au
-    Postal address: Dr. Mark Calabretta
-                    Australia Telescope National Facility, CSIRO
-                    PO Box 76
-                    Epping NSW 1710
-                    AUSTRALIA
-
-  Author: Mark Calabretta, Australia Telescope National Facility
-  http://www.atnf.csiro.au/~mcalabre/index.html
-  $Id: tab.h,v 4.10 2012/02/05 23:41:44 cal103 Exp $
-*=============================================================================
-*
-* WCSLIB 4.10 - C routines that implement tabular coordinate systems as
-* defined by the FITS World Coordinate System (WCS) standard.  Refer to
-*
-*   "Representations of world coordinates in FITS",
-*   Greisen, E.W., & Calabretta, M.R. 2002, A&A, 395, 1061 (paper I)
-*
-*   "Representations of spectral coordinates in FITS",
-*   Greisen, E.W., Calabretta, M.R., Valdes, F.G., & Allen, S.L.
-*   2006, A&A, 446, 747 (Paper III)
-*
-* Refer to the README file provided with WCSLIB for an overview of the
-* library.
-*
-*
-* Summary of the tab routines
-* ---------------------------
-* These routines implement the part of the FITS WCS standard that deals with
-* tabular coordinates, i.e. coordinates that are defined via a lookup table.
-* They define methods to be used for computing tabular world coordinates from
-* intermediate world coordinates (a linear transformation of image pixel
-* coordinates), and vice versa.  They are based on the tabprm struct which
-* contains all information needed for the computations.  The struct contains
-* some members that must be set by the user, and others that are maintained
-* by these routines, somewhat like a C++ class but with no encapsulation.
-*
-* tabini(), tabmem(), tabcpy(), and tabfree() are provided to manage the
-* tabprm struct, and another, tabprt(), to print its contents.
-*
-* A setup routine, tabset(), computes intermediate values in the tabprm struct
-* from parameters in it that were supplied by the user.  The struct always
-* needs to be set up by tabset() but it need not be called explicitly - refer
-* to the explanation of tabprm::flag.
-*
-* tabx2s() and tabs2x() implement the WCS tabular coordinate transformations.
-*
-* Accuracy:
-* ---------
-* No warranty is given for the accuracy of these routines (refer to the
-* copyright notice); intending users must satisfy for themselves their
-* adequacy for the intended purpose.  However, closure effectively to within
-* double precision rounding error was demonstrated by test routine ttab.c
-* which accompanies this software.
-*
-*
-* tabini() - Default constructor for the tabprm struct
-* ----------------------------------------------------
-* tabini() allocates memory for arrays in a tabprm struct and sets all members
-* of the struct to default values.
-*
-* PLEASE NOTE: every tabprm struct should be initialized by tabini(), possibly
-* repeatedly.  On the first invokation, and only the first invokation, the
-* flag member of the tabprm struct must be set to -1 to initialize memory
-* management, regardless of whether tabini() will actually be used to allocate
-* memory.
-*
-* Given:
-*   alloc     int       If true, allocate memory unconditionally for arrays in
-*                       the tabprm struct.
-*
-*                       If false, it is assumed that pointers to these arrays
-*                       have been set by the user except if they are null
-*                       pointers in which case memory will be allocated for
-*                       them regardless.  (In other words, setting alloc true
-*                       saves having to initalize these pointers to zero.)
-*
-*   M         int       The number of tabular coordinate axes.
-*
-*   K         const int[]
-*                       Vector of length M whose elements (K_1, K_2,... K_M)
-*                       record the lengths of the axes of the coordinate array
-*                       and of each indexing vector.  M and K[] are used to
-*                       determine the length of the various tabprm arrays and
-*                       therefore the amount of memory to allocate for them.
-*                       Their values are copied into the tabprm struct.
-*
-*                       It is permissible to set K (i.e. the address of the
-*                       array) to zero which has the same effect as setting
-*                       each element of K[] to zero.  In this case no memory
-*                       will be allocated for the index vectors or coordinate
-*                       array in the tabprm struct.  These together with the
-*                       K vector must be set separately before calling
-*                       tabset().
-*
-* Given and returned:
-*   tab       struct tabprm*
-*                       Tabular transformation parameters.  Note that, in
-*                       order to initialize memory management tabprm::flag
-*                       should be set to -1 when tab is initialized for the
-*                       first time (memory leaks may result if it had already
-*                       been initialized).
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         1: Null tabprm pointer passed.
-*                         2: Memory allocation failed.
-*                         3: Invalid tabular parameters.
-*
-*                       For returns > 1, a detailed error message is set in
-*                       tabprm::err if enabled, see wcserr_enable().
-*
-*
-* tabmem() - Acquire tabular memory
-* ---------------------------------
-* tabmem() takes control of memory allocated by the user for arrays in the
-* tabprm struct.
-*
-* Given and returned:
-*   tab       struct tabprm*
-*                       Tabular transformation parameters.
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         1: Null tabprm pointer passed.
-*                         2: Memory allocation failed.
-*
-*                       For returns > 1, a detailed error message is set in
-*                       tabprm::err if enabled, see wcserr_enable().
-*
-*
-* tabcpy() - Copy routine for the tabprm struct
-* ---------------------------------------------
-* tabcpy() does a deep copy of one tabprm struct to another, using tabini() to
-* allocate memory for its arrays if required.  Only the "information to be
-* provided" part of the struct is copied; a call to tabset() is required to
-* set up the remainder.
-*
-* Given:
-*   alloc     int       If true, allocate memory unconditionally for arrays in
-*                       the tabprm struct.
-*
-*                       If false, it is assumed that pointers to these arrays
-*                       have been set by the user except if they are null
-*                       pointers in which case memory will be allocated for
-*                       them regardless.  (In other words, setting alloc true
-*                       saves having to initalize these pointers to zero.)
-*
-*   tabsrc    const struct tabprm*
-*                       Struct to copy from.
-*
-* Given and returned:
-*   tabdst    struct tabprm*
-*                       Struct to copy to.  tabprm::flag should be set to -1
-*                       if tabdst was not previously initialized (memory leaks
-*                       may result if it was previously initialized).
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         1: Null tabprm pointer passed.
-*                         2: Memory allocation failed.
-*
-*                       For returns > 1, a detailed error message is set in
-*                       tabprm::err (associated with tabdst) if enabled, see
-*                       wcserr_enable().
-*
-*
-* tabfree() - Destructor for the tabprm struct
-* --------------------------------------------
-* tabfree() frees memory allocated for the tabprm arrays by tabini().
-* tabini() records the memory it allocates and tabfree() will only attempt to
-* free this.
-*
-* PLEASE NOTE: tabfree() must not be invoked on a tabprm struct that was not
-* initialized by tabini().
-*
-* Returned:
-*   tab       struct tabprm*
-*                       Coordinate transformation parameters.
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         1: Null tabprm pointer passed.
-*
-*
-* tabprt() - Print routine for the tabprm struct
-* ----------------------------------------------
-* tabprt() prints the contents of a tabprm struct using wcsprintf().  Mainly
-* intended for diagnostic purposes.
-*
-* Given:
-*   tab       const struct tabprm*
-*                       Tabular transformation parameters.
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         1: Null tabprm pointer passed.
-*
-*
-* tabset() - Setup routine for the tabprm struct
-* -----------------------------------------------
-* tabset() allocates memory for work arrays in the tabprm struct and sets up
-* the struct according to information supplied within it.
-*
-* Note that this routine need not be called directly; it will be invoked by
-* tabx2s() and tabs2x() if tabprm::flag is anything other than a predefined
-* magic value.
-*
-* Given and returned:
-*   tab       struct tabprm*
-*                       Tabular transformation parameters.
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         1: Null tabprm pointer passed.
-*                         3: Invalid tabular parameters.
-*
-*                       For returns > 1, a detailed error message is set in
-*                       tabprm::err if enabled, see wcserr_enable().
-*
-*
-* tabx2s() - Pixel-to-world transformation
-* ----------------------------------------
-* tabx2s() transforms intermediate world coordinates to world coordinates
-* using coordinate lookup.
-*
-* Given and returned:
-*   tab       struct tabprm*
-*                       Tabular transformation parameters.
-*
-* Given:
-*   ncoord,
-*   nelem     int       The number of coordinates, each of vector length
-*                       nelem.
-*
-*   x         const double[ncoord][nelem]
-*                       Array of intermediate world coordinates, SI units.
-*
-* Returned:
-*   world     double[ncoord][nelem]
-*                       Array of world coordinates, in SI units.
-*
-*   stat      int[ncoord]
-*                       Status return value status for each coordinate:
-*                         0: Success.
-*                         1: Invalid intermediate world coordinate.
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         1: Null tabprm pointer passed.
-*                         3: Invalid tabular parameters.
-*                         4: One or more of the x coordinates were invalid,
-*                            as indicated by the stat vector.
-*
-*                       For returns > 1, a detailed error message is set in
-*                       tabprm::err if enabled, see wcserr_enable().
-*
-*
-* tabs2x() - World-to-pixel transformation
-* ----------------------------------------
-* tabs2x() transforms world coordinates to intermediate world coordinates.
-*
-* Given and returned:
-*   tab       struct tabprm*
-*                       Tabular transformation parameters.
-*
-* Given:
-*   ncoord,
-*   nelem     int       The number of coordinates, each of vector length
-*                       nelem.
-*   world     const double[ncoord][nelem]
-*                       Array of world coordinates, in SI units.
-*
-* Returned:
-*   x         double[ncoord][nelem]
-*                       Array of intermediate world coordinates, SI units.
-*   stat      int[ncoord]
-*                       Status return value status for each vector element:
-*                         0: Success.
-*                         1: Invalid world coordinate.
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         1: Null tabprm pointer passed.
-*                         3: Invalid tabular parameters.
-*                         5: One or more of the world coordinates were
-*                            invalid, as indicated by the stat vector.
-*
-*                       For returns > 1, a detailed error message is set in
-*                       tabprm::err if enabled, see wcserr_enable().
-*
-*
-* tabprm struct - Tabular transformation parameters
-* -------------------------------------------------
-* The tabprm struct contains information required to transform tabular
-* coordinates.  It consists of certain members that must be set by the user
-* ("given") and others that are set by the WCSLIB routines ("returned").  Some
-* of the latter are supplied for informational purposes while others are for
-* internal use only.
-*
-*   int flag
-*     (Given and returned) This flag must be set to zero whenever any of the
-*     following tabprm structure members are set or changed:
-*
-*       - tabprm::M (q.v., not normally set by the user),
-*       - tabprm::K (q.v., not normally set by the user),
-*       - tabprm::map,
-*       - tabprm::crval,
-*       - tabprm::index,
-*       - tabprm::coord.
-*
-*     This signals the initialization routine, tabset(), to recompute the
-*     returned members of the tabprm struct.  tabset() will reset flag to
-*     indicate that this has been done.
-*
-*     PLEASE NOTE: flag should be set to -1 when tabini() is called for the
-*     first time for a particular tabprm struct in order to initialize memory
-*     management.  It must ONLY be used on the first initialization otherwise
-*     memory leaks may result.
-*
-*   int M
-*     (Given or returned) Number of tabular coordinate axes.
-*
-*     If tabini() is used to initialize the linprm struct (as would normally
-*     be the case) then it will set M from the value passed to it as a
-*     function argument.  The user should not subsequently modify it.
-*
-*   int *K
-*     (Given or returned) Pointer to the first element of a vector of length
-*     tabprm::M whose elements (K_1, K_2,... K_M) record the lengths of the
-*     axes of the coordinate array and of each indexing vector.
-*
-*     If tabini() is used to initialize the linprm struct (as would normally
-*     be the case) then it will set K from the array passed to it as a
-*     function argument.  The user should not subsequently modify it.
-*
-*   int *map
-*     (Given) Pointer to the first element of a vector of length tabprm::M
-*     that defines the association between axis m in the M-dimensional
-*     coordinate array (1 <= m <= M) and the indices of the intermediate world
-*     coordinate and world coordinate arrays, x[] and world[], in the argument
-*     lists for tabx2s() and tabs2x().
-*
-*     When x[] and world[] contain the full complement of coordinate elements
-*     in image-order, as will usually be the case, then map[m-1] == i-1 for
-*     axis i in the N-dimensional image (1 <= i <= N).  In terms of the FITS
-*     keywords
-*
-*       map[PVi_3a - 1] == i - 1.
-*
-*     However, a different association may result if x[], for example, only
-*     contains a (relevant) subset of intermediate world coordinate elements.
-*     For example, if M == 1 for an image with N > 1, it is possible to fill
-*     x[] with the relevant coordinate element with nelem set to 1.  In this
-*     case map[0] = 0 regardless of the value of i.
-*
-*   double *crval
-*     (Given) Pointer to the first element of a vector of length tabprm::M
-*     whose elements contain the index value for the reference pixel for each
-*     of the tabular coordinate axes.
-*
-*   double **index
-*     (Given) Pointer to the first element of a vector of length tabprm::M of
-*     pointers to vectors of lengths (K_1, K_2,... K_M) of 0-relative indexes
-*     (see tabprm::K).
-*
-*     The address of any or all of these index vectors may be set to zero,
-*     i.e.
-*
-=       index[m] == 0;
-*
-*     this is interpreted as default indexing, i.e.
-*
-=       index[m][k] = k;
-*
-*   double *coord
-*     (Given) Pointer to the first element of the tabular coordinate array,
-*     treated as though it were defined as
-*
-=       double coord[K_M]...[K_2][K_1][M];
-*
-*     (see tabprm::K) i.e. with the M dimension varying fastest so that the
-*     M elements of a coordinate vector are stored contiguously in memory.
-*
-*   int nc
-*     (Returned) Total number of coordinate vectors in the coordinate array
-*     being the product K_1 * K_2 * ... * K_M (see tabprm::K).
-*
-*   int padding
-*     (An unused variable inserted for alignment purposes only.)
-*
-*   int *sense
-*     (Returned) Pointer to the first element of a vector of length tabprm::M
-*     whose elements indicate whether the corresponding indexing vector is
-*     monotonic increasing (+1), or decreasing (-1).
-*
-*   int *p0
-*     (Returned) Pointer to the first element of a vector of length tabprm::M
-*     of interpolated indices into the coordinate array such that Upsilon_m,
-*     as defined in Paper III, is equal to (p0[m] + 1) + tabprm::delta[m].
-*
-*   double *delta
-*     (Returned) Pointer to the first element of a vector of length tabprm::M
-*     of interpolated indices into the coordinate array such that Upsilon_m,
-*     as defined in Paper III, is equal to (tabprm::p0[m] + 1) + delta[m].
-*
-*   double *extrema
-*     (Returned) Pointer to the first element of an array that records the
-*     minimum and maximum value of each element of the coordinate vector in
-*     each row of the coordinate array, treated as though it were defined as
-*
-=       double extrema[K_M]...[K_2][2][M]
-*
-*     (see tabprm::K).  The minimum is recorded in the first element of the
-*     compressed K_1 dimension, then the maximum.  This array is used by the
-*     inverse table lookup function, tabs2x(), to speed up table searches.
-*
-*   struct wcserr *err
-*     (Returned) If enabled, when an error status is returned this struct
-*     contains detailed information about the error, see wcserr_enable().
-*
-*   int m_flag
-*     (For internal use only.)
-*   int m_M
-*     (For internal use only.)
-*   int m_N
-*     (For internal use only.)
-*   int set_M
-*     (For internal use only.)
-*   int m_K
-*     (For internal use only.)
-*   int m_map
-*     (For internal use only.)
-*   int m_crval
-*     (For internal use only.)
-*   int m_index
-*     (For internal use only.)
-*   int m_indxs
-*     (For internal use only.)
-*   int m_coord
-*     (For internal use only.)
-*
-*
-* Global variable: const char *tab_errmsg[] - Status return messages
-* ------------------------------------------------------------------
-* Error messages to match the status value returned from each function.
-*
-*===========================================================================*/
-
-#ifndef WCSLIB_TAB
-#define WCSLIB_TAB
-
-#include "wcserr.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-extern const char *tab_errmsg[];
-
-enum tab_errmsg_enum {
-  TABERR_SUCCESS      = 0,	/* Success. */
-  TABERR_NULL_POINTER = 1,	/* Null tabprm pointer passed. */
-  TABERR_MEMORY       = 2,	/* Memory allocation failed. */
-  TABERR_BAD_PARAMS   = 3,	/* Invalid tabular parameters. */
-  TABERR_BAD_X        = 4,	/* One or more of the x coordinates were
-				   invalid. */
-  TABERR_BAD_WORLD    = 5	/* One or more of the world coordinates were
-				   invalid. */
-};
-
-struct tabprm {
-  /* Initialization flag (see the prologue above).                          */
-  /*------------------------------------------------------------------------*/
-  int    flag;			/* Set to zero to force initialization.     */
-
-  /* Parameters to be provided (see the prologue above).                    */
-  /*------------------------------------------------------------------------*/
-  int    M;			/* Number of tabular coordinate axes.       */
-  int    *K;			/* Vector of length M whose elements        */
-				/* (K_1, K_2,... K_M) record the lengths of */
-				/* the axes of the coordinate array and of  */
-				/* each indexing vector.                    */
-  int    *map;			/* Vector of length M usually such that     */
-				/* map[m-1] == i-1 for coordinate array     */
-				/* axis m and image axis i (see above).     */
-  double *crval;		/* Vector of length M containing the index  */
-				/* value for the reference pixel for each   */
-				/* of the tabular coordinate axes.          */
-  double **index;		/* Vector of pointers to M indexing vectors */
-				/* of lengths (K_1, K_2,... K_M).           */
-  double *coord;		/* (1+M)-dimensional tabular coordinate     */
-				/* array (see above).                       */
-
-  /* Information derived from the parameters supplied.                      */
-  /*------------------------------------------------------------------------*/
-  int    nc;			/* Number of coordinate vectors (of length  */
-				/* M) in the coordinate array.              */
-  int    padding;		/* (Dummy inserted for alignment purposes.) */
-  int    *sense;		/* Vector of M flags that indicate whether  */
-				/* the Mth indexing vector is monotonic     */
-				/* increasing, or else decreasing.          */
-  int    *p0;			/* Vector of M indices.                     */
-  double *delta;		/* Vector of M increments.                  */
-  double *extrema;		/* (1+M)-dimensional array of coordinate    */
-				/* extrema.                                 */
-
-  /* Error handling                                                         */
-  /*------------------------------------------------------------------------*/
-  struct wcserr *err;
-
-  /* Private - the remainder are for memory management.                     */
-  /*------------------------------------------------------------------------*/
-  int    m_flag, m_M, m_N;
-  int    set_M;
-  int    *m_K, *m_map;
-  double *m_crval, **m_index, **m_indxs, *m_coord;
-};
-
-/* Size of the tabprm struct in int units, used by the Fortran wrappers. */
-#define TABLEN (sizeof(struct tabprm)/sizeof(int))
-
-
-int tabini(int alloc, int M, const int K[], struct tabprm *tab);
-
-int tabmem(struct tabprm *tab);
-
-int tabcpy(int alloc, const struct tabprm *tabsrc, struct tabprm *tabdst);
-
-int tabfree(struct tabprm *tab);
-
-int tabprt(const struct tabprm *tab);
-
-int tabset(struct tabprm *tab);
-
-int tabx2s(struct tabprm *tab, int ncoord, int nelem, const double x[],
-           double world[], int stat[]);
-
-int tabs2x(struct tabprm *tab, int ncoord, int nelem, const double world[],
-           double x[], int stat[]);
-
-
-/* Deprecated. */
-#define tabini_errmsg tab_errmsg
-#define tabcpy_errmsg tab_errmsg
-#define tabfree_errmsg tab_errmsg
-#define tabprt_errmsg tab_errmsg
-#define tabset_errmsg tab_errmsg
-#define tabx2s_errmsg tab_errmsg
-#define tabs2x_errmsg tab_errmsg
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* WCSLIB_TAB */
diff --git a/astropy/wcs/src/wcslib/C/wcs.c b/astropy/wcs/src/wcslib/C/wcs.c
deleted file mode 100644
index 80583dd..0000000
--- a/astropy/wcs/src/wcslib/C/wcs.c
+++ /dev/null
@@ -1,3230 +0,0 @@
-/*============================================================================
-
-  WCSLIB 4.10 - an implementation of the FITS WCS standard.
-  Copyright (C) 1995-2012, Mark Calabretta
-
-  This file is part of WCSLIB.
-
-  WCSLIB is free software: you can redistribute it and/or modify it under the
-  terms of the GNU Lesser General Public License as published by the Free
-  Software Foundation, either version 3 of the License, or (at your option)
-  any later version.
-
-  WCSLIB 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 Lesser General Public License for
-  more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with WCSLIB.  If not, see <http://www.gnu.org/licenses/>.
-
-  Correspondence concerning WCSLIB may be directed to:
-    Internet email: mcalabre at atnf.csiro.au
-    Postal address: Dr. Mark Calabretta
-                    Australia Telescope National Facility, CSIRO
-                    PO Box 76
-                    Epping NSW 1710
-                    AUSTRALIA
-
-  Author: Mark Calabretta, Australia Telescope National Facility
-  http://www.atnf.csiro.au/~mcalabre/index.html
-  $Id: wcs.c,v 4.10 2012/02/05 23:41:44 cal103 Exp $
-*===========================================================================*/
-
-#include <math.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "wcserr.h"
-#include "wcsmath.h"
-#include "wcsprintf.h"
-#include "wcstrig.h"
-#include "wcsunits.h"
-#include "wcsutil.h"
-#include "lin.h"
-#include "log.h"
-#include "spc.h"
-#include "prj.h"
-#include "sph.h"
-#include "cel.h"
-#include "tab.h"
-#include "wcs.h"
-
-const int WCSSET = 137;
-
-/* Maximum number of PVi_ma and PSi_ma keywords. */
-int NPVMAX = 64;
-int NPSMAX =  8;
-
-/* Map status return value to message. */
-const char *wcs_errmsg[] = {
-  "Success",
-  "Null wcsprm pointer passed",
-  "Memory allocation failed",
-  "Linear transformation matrix is singular",
-  "Inconsistent or unrecognized coordinate axis types",
-  "Invalid parameter value",
-  "Invalid coordinate transformation parameters",
-  "Ill-conditioned coordinate transformation parameters",
-  "One or more of the pixel coordinates were invalid",
-  "One or more of the world coordinates were invalid",
-  "Invalid world coordinate",
-  "No solution found in the specified interval",
-  "Invalid subimage specification",
-  "Non-separable subimage coordinate system"};
-
-/* Convenience macro for invoking wcserr_set(). */
-#define WCS_ERRMSG(status) WCSERR_SET(status), wcs_errmsg[status]
-
-#ifndef signbit
-#define signbit(X) ((X) < 0.0 ? 1 : 0)
-#endif
-
-/* Internal helper functions, not for general use. */
-static int wcs_types(struct wcsprm *);
-static int wcs_units(struct wcsprm *);
-
-/*--------------------------------------------------------------------------*/
-
-int wcsnpv(int npvmax) { if (npvmax >= 0) NPVMAX = npvmax; return NPVMAX; }
-int wcsnps(int npsmax) { if (npsmax >= 0) NPSMAX = npsmax; return NPSMAX; }
-
-/*--------------------------------------------------------------------------*/
-
-int wcsini(int alloc, int naxis, struct wcsprm *wcs)
-
-{
-  static const char *function = "wcsini";
-
-  int i, j, k, status;
-  double *cd;
-  struct wcserr **err;
-
-  if (wcs == 0x0) return WCSERR_NULL_POINTER;
-
-  /* Initialize error message handling. */
-  err = &(wcs->err);
-  if (wcs->flag != -1) {
-    if (wcs->err) free(wcs->err);
-    if (wcs->lin.err) free(wcs->lin.err);
-    if (wcs->cel.err) free(wcs->cel.err);
-    if (wcs->spc.err) free(wcs->spc.err);
-    if (wcs->cel.prj.err) free(wcs->cel.prj.err);
-  }
-  wcs->err = 0x0;
-  wcs->lin.err = 0x0;
-  wcs->cel.err = 0x0;
-  wcs->spc.err = 0x0;
-  wcs->cel.prj.err = 0x0;
-
-
-  /* Initialize pointers. */
-  if (wcs->flag == -1 || wcs->m_flag != WCSSET) {
-    if (wcs->flag == -1) {
-      wcs->types = 0x0;
-      wcs->lin.flag = -1;
-      wcs->tab = 0x0;
-    }
-
-    /* Initialize memory management. */
-    wcs->m_flag  = 0;
-    wcs->m_naxis = 0;
-    wcs->m_crpix = 0x0;
-    wcs->m_pc    = 0x0;
-    wcs->m_cdelt = 0x0;
-    wcs->m_crval = 0x0;
-    wcs->m_cunit = 0x0;
-    wcs->m_ctype = 0x0;
-    wcs->m_pv    = 0x0;
-    wcs->m_ps    = 0x0;
-    wcs->m_cd    = 0x0;
-    wcs->m_crota = 0x0;
-    wcs->m_colax = 0x0;
-    wcs->m_cname = 0x0;
-    wcs->m_crder = 0x0;
-    wcs->m_csyer = 0x0;
-    wcs->m_tab   = 0x0;
-    wcs->m_wtb   = 0x0;
-  }
-
-  if (naxis <= 0) {
-    return wcserr_set(WCSERR_SET(WCSERR_MEMORY),
-      "naxis must be positive (got %d)", naxis);
-  }
-
-
-  /* Allocate memory for arrays if required. */
-  if (alloc ||
-     wcs->crpix == 0x0 ||
-     wcs->pc    == 0x0 ||
-     wcs->cdelt == 0x0 ||
-     wcs->crval == 0x0 ||
-     wcs->cunit == 0x0 ||
-     wcs->ctype == 0x0 ||
-     (NPVMAX && wcs->pv == 0x0) ||
-     (NPSMAX && wcs->ps == 0x0) ||
-     wcs->cd    == 0x0 ||
-     wcs->crota == 0x0 ||
-     wcs->colax == 0x0 ||
-     wcs->cname == 0x0 ||
-     wcs->crder == 0x0 ||
-     wcs->csyer == 0x0) {
-
-    /* Was sufficient allocated previously? */
-    if (wcs->m_flag == WCSSET &&
-       (wcs->m_naxis < naxis  ||
-        wcs->npvmax  < NPVMAX ||
-        wcs->npsmax  < NPSMAX)) {
-      /* No, free it. */
-      wcsfree(wcs);
-    }
-
-
-    if (alloc || wcs->crpix == 0x0) {
-      if (wcs->m_crpix) {
-        /* In case the caller fiddled with it. */
-        wcs->crpix = wcs->m_crpix;
-
-      } else {
-        if (!(wcs->crpix = calloc(naxis, sizeof(double)))) {
-          return wcserr_set(WCS_ERRMSG(WCSERR_MEMORY));
-        }
-
-        wcs->m_flag  = WCSSET;
-        wcs->m_naxis = naxis;
-        wcs->m_crpix = wcs->crpix;
-      }
-    }
-
-    if (alloc || wcs->pc == 0x0) {
-      if (wcs->m_pc) {
-        /* In case the caller fiddled with it. */
-        wcs->pc = wcs->m_pc;
-
-      } else {
-        if (!(wcs->pc = calloc(naxis*naxis, sizeof(double)))) {
-          wcsfree(wcs);
-          return wcserr_set(WCS_ERRMSG(WCSERR_MEMORY));
-        }
-
-        wcs->m_flag  = WCSSET;
-        wcs->m_naxis = naxis;
-        wcs->m_pc    = wcs->pc;
-      }
-    }
-
-    if (alloc || wcs->cdelt == 0x0) {
-      if (wcs->m_cdelt) {
-        /* In case the caller fiddled with it. */
-        wcs->cdelt = wcs->m_cdelt;
-
-      } else {
-        if (!(wcs->cdelt = calloc(naxis, sizeof(double)))) {
-          wcsfree(wcs);
-          return wcserr_set(WCS_ERRMSG(WCSERR_MEMORY));
-        }
-
-        wcs->m_flag  = WCSSET;
-        wcs->m_naxis = naxis;
-        wcs->m_cdelt = wcs->cdelt;
-      }
-    }
-
-    if (alloc || wcs->crval == 0x0) {
-      if (wcs->m_crval) {
-        /* In case the caller fiddled with it. */
-        wcs->crval = wcs->m_crval;
-
-      } else {
-        if (!(wcs->crval = calloc(naxis, sizeof(double)))) {
-          wcsfree(wcs);
-          return wcserr_set(WCS_ERRMSG(WCSERR_MEMORY));
-        }
-
-        wcs->m_flag  = WCSSET;
-        wcs->m_naxis = naxis;
-        wcs->m_crval = wcs->crval;
-      }
-    }
-
-    if (alloc || wcs->cunit == 0x0) {
-      if (wcs->m_cunit) {
-        /* In case the caller fiddled with it. */
-        wcs->cunit = wcs->m_cunit;
-
-      } else {
-        if (!(wcs->cunit = calloc(naxis, sizeof(char [72])))) {
-          wcsfree(wcs);
-          return wcserr_set(WCS_ERRMSG(WCSERR_MEMORY));
-        }
-
-        wcs->m_flag  = WCSSET;
-        wcs->m_naxis = naxis;
-        wcs->m_cunit = wcs->cunit;
-      }
-    }
-
-    if (alloc || wcs->ctype == 0x0) {
-      if (wcs->m_ctype) {
-        /* In case the caller fiddled with it. */
-        wcs->ctype = wcs->m_ctype;
-
-      } else {
-        if (!(wcs->ctype = calloc(naxis, sizeof(char [72])))) {
-          wcsfree(wcs);
-          return wcserr_set(WCS_ERRMSG(WCSERR_MEMORY));
-        }
-
-        wcs->m_flag  = WCSSET;
-        wcs->m_naxis = naxis;
-        wcs->m_ctype = wcs->ctype;
-      }
-    }
-
-    if (alloc || wcs->pv == 0x0) {
-      if (wcs->m_pv) {
-        /* In case the caller fiddled with it. */
-        wcs->pv = wcs->m_pv;
-
-      } else {
-        if (NPVMAX) {
-          if (!(wcs->pv = calloc(NPVMAX, sizeof(struct pvcard)))) {
-            wcsfree(wcs);
-            return wcserr_set(WCS_ERRMSG(WCSERR_MEMORY));
-          }
-        } else {
-          wcs->pv = (struct pvcard *)0;
-        }
-
-        wcs->npvmax  = NPVMAX;
-
-        wcs->m_flag  = WCSSET;
-        wcs->m_naxis = naxis;
-        wcs->m_pv    = wcs->pv;
-      }
-    }
-
-    if (alloc || wcs->ps == 0x0) {
-      if (wcs->m_ps) {
-        /* In case the caller fiddled with it. */
-        wcs->ps = wcs->m_ps;
-
-      } else {
-        if (NPSMAX) {
-          if (!(wcs->ps = calloc(NPSMAX, sizeof(struct pscard)))) {
-            wcsfree(wcs);
-            return wcserr_set(WCS_ERRMSG(WCSERR_MEMORY));
-          }
-        } else {
-          wcs->ps = (struct pscard *)0;
-        }
-
-        wcs->npsmax  = NPSMAX;
-
-        wcs->m_flag  = WCSSET;
-        wcs->m_naxis = naxis;
-        wcs->m_ps    = wcs->ps;
-      }
-    }
-
-    if (alloc || wcs->cd == 0x0) {
-      if (wcs->m_cd) {
-        /* In case the caller fiddled with it. */
-        wcs->cd = wcs->m_cd;
-
-      } else {
-        if (!(wcs->cd = calloc(naxis*naxis, sizeof(double)))) {
-          wcsfree(wcs);
-          return wcserr_set(WCS_ERRMSG(WCSERR_MEMORY));
-        }
-
-        wcs->m_flag  = WCSSET;
-        wcs->m_naxis = naxis;
-        wcs->m_cd    = wcs->cd;
-      }
-    }
-
-    if (alloc || wcs->crota == 0x0) {
-      if (wcs->m_crota) {
-        /* In case the caller fiddled with it. */
-        wcs->crota = wcs->m_crota;
-
-      } else {
-        if (!(wcs->crota = calloc(naxis, sizeof(double)))) {
-          wcsfree(wcs);
-          return wcserr_set(WCS_ERRMSG(WCSERR_MEMORY));
-        }
-
-        wcs->m_flag  = WCSSET;
-        wcs->m_naxis = naxis;
-        wcs->m_crota = wcs->crota;
-      }
-    }
-
-    if (alloc || wcs->colax == 0x0) {
-      if (wcs->m_colax) {
-        /* In case the caller fiddled with it. */
-        wcs->colax = wcs->m_colax;
-
-      } else {
-        if (!(wcs->colax = calloc(naxis, sizeof(int)))) {
-          wcsfree(wcs);
-          return wcserr_set(WCS_ERRMSG(WCSERR_MEMORY));
-        }
-
-        wcs->m_flag  = WCSSET;
-        wcs->m_naxis = naxis;
-        wcs->m_colax = wcs->colax;
-      }
-    }
-
-    if (alloc || wcs->cname == 0x0) {
-      if (wcs->m_cname) {
-        /* In case the caller fiddled with it. */
-        wcs->cname = wcs->m_cname;
-
-      } else {
-        if (!(wcs->cname = calloc(naxis, sizeof(char [72])))) {
-          wcsfree(wcs);
-          return wcserr_set(WCS_ERRMSG(WCSERR_MEMORY));
-        }
-
-        wcs->m_flag  = WCSSET;
-        wcs->m_naxis = naxis;
-        wcs->m_cname = wcs->cname;
-      }
-    }
-
-    if (alloc || wcs->crder == 0x0) {
-      if (wcs->m_crder) {
-        /* In case the caller fiddled with it. */
-        wcs->crder = wcs->m_crder;
-
-      } else {
-        if (!(wcs->crder = calloc(naxis, sizeof(double)))) {
-          wcsfree(wcs);
-          return wcserr_set(WCS_ERRMSG(WCSERR_MEMORY));
-        }
-
-        wcs->m_flag  = WCSSET;
-        wcs->m_naxis = naxis;
-        wcs->m_crder = wcs->crder;
-      }
-    }
-
-    if (alloc || wcs->csyer == 0x0) {
-      if (wcs->m_csyer) {
-        /* In case the caller fiddled with it. */
-        wcs->csyer = wcs->m_csyer;
-
-      } else {
-        if (!(wcs->csyer = calloc(naxis, sizeof(double)))) {
-          wcsfree(wcs);
-          return wcserr_set(WCS_ERRMSG(WCSERR_MEMORY));
-        }
-
-        wcs->m_flag  = WCSSET;
-        wcs->m_naxis = naxis;
-        wcs->m_csyer = wcs->csyer;
-      }
-    }
-  }
-
-
-  wcs->flag  = 0;
-  wcs->naxis = naxis;
-
-
-  /* Set defaults for the linear transformation. */
-  wcs->lin.crpix  = wcs->crpix;
-  wcs->lin.pc     = wcs->pc;
-  wcs->lin.cdelt  = wcs->cdelt;
-  wcs->lin.m_flag = 0;
-  if ((status = linini(0, naxis, &(wcs->lin)))) {
-    return wcserr_set(WCS_ERRMSG(status));
-  }
-
-
-  /* CRVALia defaults to 0.0. */
-  for (i = 0; i < naxis; i++) {
-    wcs->crval[i] = 0.0;
-  }
-
-
-  /* CUNITia and CTYPEia are blank by default. */
-  for (i = 0; i < naxis; i++) {
-    memset(wcs->cunit[i], 0, 72);
-    memset(wcs->ctype[i], 0, 72);
-  }
-
-
-  /* Set defaults for the celestial transformation parameters. */
-  wcs->lonpole = UNDEFINED;
-  wcs->latpole = +90.0;
-
-  /* Set defaults for the spectral transformation parameters. */
-  wcs->restfrq = 0.0;
-  wcs->restwav = 0.0;
-
-  /* Default parameter values. */
-  wcs->npv = 0;
-  for (k = 0; k < wcs->npvmax; k++) {
-    wcs->pv[k].i = 0;
-    wcs->pv[k].m = 0;
-    wcs->pv[k].value = 0.0;
-  }
-
-  wcs->nps = 0;
-  for (k = 0; k < wcs->npsmax; k++) {
-    wcs->ps[k].i = 0;
-    wcs->ps[k].m = 0;
-    memset(wcs->ps[k].value, 0, 72);
-  }
-
-  /* Defaults for alternate linear transformations. */
-  cd = wcs->cd;
-  for (i = 0; i < naxis; i++) {
-    for (j = 0; j < naxis; j++) {
-      *(cd++) = 0.0;
-    }
-  }
-  for (i = 0; i < naxis; i++) {
-    wcs->crota[i] = 0.0;
-  }
-  wcs->altlin = 0;
-  wcs->velref = 0;
-
-  /* Defaults for auxiliary coordinate system information. */
-  memset(wcs->alt, 0, 4);
-  wcs->alt[0] = ' ';
-  wcs->colnum = 0;
-
-  memset(wcs->wcsname, 0, 72);
-  for (i = 0; i < naxis; i++) {
-    wcs->colax[i] = 0;
-    memset(wcs->cname[i], 0, 72);
-    wcs->crder[i] = UNDEFINED;
-    wcs->csyer[i] = UNDEFINED;
-  }
-  memset(wcs->radesys, 0, 72);
-  wcs->equinox    = UNDEFINED;
-  memset(wcs->specsys, 0, 72);
-  memset(wcs->ssysobs, 0, 72);
-  wcs->velosys    = UNDEFINED;
-  memset(wcs->ssyssrc, 0, 72);
-  wcs->zsource    = UNDEFINED;
-  wcs->obsgeo[0]  = UNDEFINED;
-  wcs->obsgeo[1]  = UNDEFINED;
-  wcs->obsgeo[2]  = UNDEFINED;
-  memset(wcs->dateobs, 0, 72);
-  memset(wcs->dateavg, 0, 72);
-  wcs->mjdobs     = UNDEFINED;
-  wcs->mjdavg     = UNDEFINED;
-
-  wcs->ntab = 0;
-  wcs->tab  = 0x0;
-  wcs->nwtb = 0;
-  wcs->wtb  = 0x0;
-
-  /* Reset derived values. */
-  strcpy(wcs->lngtyp, "    ");
-  strcpy(wcs->lattyp, "    ");
-  wcs->lng  = -1;
-  wcs->lat  = -1;
-  wcs->spec = -1;
-  wcs->cubeface = -1;
-
-  celini(&(wcs->cel));
-  spcini(&(wcs->spc));
-
-  return 0;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int wcssub(
-  int alloc,
-  const struct wcsprm *wcssrc,
-  int *nsub,
-  int axes[],
-  struct wcsprm *wcsdst)
-
-{
-  static const char *function = "wcssub";
-
-  char *c, ctypei[16];
-  int  axis, cubeface, dealloc, dummy, i, itab, j, k, latitude, longitude, m,
-       *map = 0x0, msub, naxis, npv, nps, other, spectral, status, stokes;
-  const double *srcp;
-  double *dstp;
-  struct tabprm *tabp;
-  struct wcserr **err;
-
-  if (wcssrc == 0x0) return WCSERR_NULL_POINTER;
-  err = &(wcsdst->err);
-
-  if ((naxis = wcssrc->naxis) <= 0) {
-    return wcserr_set(WCSERR_SET(WCSERR_MEMORY),
-      "naxis must be positive (got %d)", naxis);
-  }
-
-  if (!(map = calloc(naxis, sizeof(int)))) {
-    return wcserr_set(WCS_ERRMSG(WCSERR_MEMORY));
-  }
-
-  if (nsub == 0x0) {
-    nsub = &dummy;
-    *nsub = naxis;
-  } else if (*nsub == 0) {
-    *nsub = naxis;
-  }
-
-  if ((dealloc = (axes == 0x0))) {
-    /* Construct an index array. */
-    if (!(axes = calloc(naxis, sizeof(int)))) {
-      free(map);
-      return wcserr_set(WCS_ERRMSG(WCSERR_MEMORY));
-    }
-
-    for (i = 0; i < naxis; i++) {
-      axes[i] = i+1;
-    }
-  }
-
-  /* So that we don't try to free an uninitialized pointer on cleanup. */
-  wcsdst->m_tab = 0x0;
-
-
-  msub = 0;
-  for (j = 0; j < *nsub; j++) {
-    axis = axes[j];
-
-    if (abs(axis) > 0x1000) {
-      /* Subimage extraction by type. */
-      k = abs(axis) & 0xFF;
-
-      longitude = k & WCSSUB_LONGITUDE;
-      latitude  = k & WCSSUB_LATITUDE;
-      cubeface  = k & WCSSUB_CUBEFACE;
-      spectral  = k & WCSSUB_SPECTRAL;
-      stokes    = k & WCSSUB_STOKES;
-
-      if ((other = (axis < 0))) {
-        longitude = !longitude;
-        latitude  = !latitude;
-        cubeface  = !cubeface;
-        spectral  = !spectral;
-        stokes    = !stokes;
-      }
-
-      for (i = 0; i < naxis; i++) {
-        strncpy (ctypei, (char *)(wcssrc->ctype + i), 8);
-        ctypei[8] = '\0';
-
-        /* Find the last non-blank character. */
-        c = ctypei + 8;
-        while (c-- > ctypei) {
-          if (*c == ' ') *c = '\0';
-          if (*c != '\0') break;
-        }
-
-        if (
-          strcmp(ctypei,   "RA")  == 0 ||
-          strcmp(ctypei+1, "LON") == 0 ||
-          strcmp(ctypei+2, "LN")  == 0 ||
-          strncmp(ctypei,   "RA---", 5) == 0 ||
-          strncmp(ctypei+1, "LON-", 4) == 0 ||
-          strncmp(ctypei+2, "LN-", 3) == 0) {
-          if (!longitude) {
-            continue;
-          }
-
-        } else if (
-          strcmp(ctypei,   "DEC") == 0 ||
-          strcmp(ctypei+1, "LAT") == 0 ||
-          strcmp(ctypei+2, "LT")  == 0 ||
-          strncmp(ctypei,   "DEC--", 5) == 0 ||
-          strncmp(ctypei+1, "LAT-", 4) == 0 ||
-          strncmp(ctypei+2, "LT-", 3) == 0) {
-          if (!latitude) {
-            continue;
-          }
-
-        } else if (strcmp(ctypei, "CUBEFACE") == 0) {
-          if (!cubeface) {
-            continue;
-          }
-
-        } else if ((
-          strncmp(ctypei, "FREQ", 4) == 0 ||
-          strncmp(ctypei, "ENER", 4) == 0 ||
-          strncmp(ctypei, "WAVN", 4) == 0 ||
-          strncmp(ctypei, "VRAD", 4) == 0 ||
-          strncmp(ctypei, "WAVE", 4) == 0 ||
-          strncmp(ctypei, "VOPT", 4) == 0 ||
-          strncmp(ctypei, "ZOPT", 4) == 0 ||
-          strncmp(ctypei, "AWAV", 4) == 0 ||
-          strncmp(ctypei, "VELO", 4) == 0 ||
-          strncmp(ctypei, "BETA", 4) == 0) &&
-          (ctypei[4] == '\0' || ctypei[4] == '-')) {
-          if (!spectral) {
-            continue;
-          }
-
-        } else if (strcmp(ctypei, "STOKES") == 0) {
-          if (!stokes) {
-            continue;
-          }
-
-        } else if (!other) {
-          continue;
-        }
-
-        /* This axis is wanted, but has it already been added? */
-        for (k = 0; k < msub; k++) {
-          if (map[k] == i+1) {
-            break;
-          }
-        }
-        if (k == msub) map[msub++] = i+1;
-      }
-
-    } else if (0 < axis && axis <= naxis) {
-      /* Check that the requested axis has not already been added. */
-      for (k = 0; k < msub; k++) {
-        if (map[k] == axis) {
-          break;
-        }
-      }
-      if (k == msub) map[msub++] = axis;
-
-    } else if (axis == 0) {
-      /* Graft on a new axis. */
-      map[msub++] = 0;
-
-    } else {
-      status = wcserr_set(WCS_ERRMSG(WCSERR_BAD_SUBIMAGE));
-      goto cleanup;
-    }
-  }
-
-  if ((*nsub = msub) == 0) {
-    status = 0;
-    goto cleanup;
-  }
-
-  for (i = 0; i < *nsub; i++) {
-    axes[i] = map[i];
-  }
-
-
-  /* Construct the inverse axis map:
-     axes[i] == j means that output axis i+1 comes from input axis j,
-     axes[i] == 0 means to create a new axis,
-      map[i] == j means that input axis i+1 goes to output axis j,
-      map[i] == 0 means that input axis i+1 is not used. */
-  for (i = 0; i < naxis; i++) {
-    map[i] = 0;
-  }
-
-  for (i = 0; i < *nsub; i++) {
-    if (axes[i] > 0) {
-      map[axes[i]-1] = i+1;
-    }
-  }
-
-  /* Check that the subimage coordinate system is separable. */
-  if (*nsub < naxis) {
-    srcp = wcssrc->pc;
-    for (i = 0; i < naxis; i++) {
-      for (j = 0; j < naxis; j++) {
-        if (*(srcp++) == 0.0 || j == i) continue;
-
-        if ((map[i] == 0) != (map[j] == 0)) {
-          status = wcserr_set(WCS_ERRMSG(WCSERR_NON_SEPARABLE));
-          goto cleanup;
-        }
-      }
-    }
-  }
-
-
-  /* Initialize the destination. */
-  npv = NPVMAX;
-  nps = NPSMAX;
-
-  NPVMAX = 0;
-  for (k = 0; k < wcssrc->npv; k++) {
-    i = wcssrc->pv[k].i;
-    if (i == 0 || (i > 0 && map[i-1])) {
-      NPVMAX++;
-    }
-  }
-
-  NPSMAX = 0;
-  for (k = 0; k < wcssrc->nps; k++) {
-    i = wcssrc->ps[k].i;
-    if (i > 0 && map[i-1]) {
-      NPSMAX++;
-    }
-  }
-
-  status = wcsini(alloc, *nsub, wcsdst);
-
-  NPVMAX = npv;
-  NPSMAX = nps;
-
-  if (status) {
-    goto cleanup;
-  }
-
-
-  /* Linear transformation. */
-  srcp = wcssrc->crpix;
-  dstp = wcsdst->crpix;
-  for (j = 0; j < *nsub; j++, dstp++) {
-    if (axes[j] > 0) {
-      k = axes[j] - 1;
-      *dstp = *(srcp+k);
-    }
-  }
-
-  srcp = wcssrc->pc;
-  dstp = wcsdst->pc;
-  for (i = 0; i < *nsub; i++) {
-    if (axes[i] > 0) {
-      for (j = 0; j < *nsub; j++, dstp++) {
-        if (axes[j] > 0) {
-          k = (axes[i]-1)*naxis + (axes[j]-1);
-          *dstp = *(srcp+k);
-        }
-      }
-    }
-  }
-
-  srcp = wcssrc->cdelt;
-  dstp = wcsdst->cdelt;
-  for (i = 0; i < *nsub; i++, dstp++) {
-    if (axes[i] > 0) {
-      k = axes[i] - 1;
-      *dstp = *(srcp+k);
-    }
-  }
-
-  /* Coordinate reference value. */
-  srcp = wcssrc->crval;
-  dstp = wcsdst->crval;
-  for (i = 0; i < *nsub; i++, dstp++) {
-    if (axes[i] > 0) {
-      k = axes[i] - 1;
-      *dstp = *(srcp+k);
-    }
-  }
-
-  /* Coordinate units and type. */
-  for (i = 0; i < *nsub; i++) {
-    if (axes[i] > 0) {
-      k = axes[i] - 1;
-      strncpy(wcsdst->cunit[i], wcssrc->cunit[k], 72);
-      strncpy(wcsdst->ctype[i], wcssrc->ctype[k], 72);
-    }
-  }
-
-  /* Celestial and spectral transformation parameters. */
-  wcsdst->lonpole = wcssrc->lonpole;
-  wcsdst->latpole = wcssrc->latpole;
-  wcsdst->restfrq = wcssrc->restfrq;
-  wcsdst->restwav = wcssrc->restwav;
-
-  /* Parameter values. */
-  npv = 0;
-  for (k = 0; k < wcssrc->npv; k++) {
-    i = wcssrc->pv[k].i;
-    if (i == 0 || (i > 0 && map[i-1])) {
-      /* i == 0 is a special code for the latitude axis. */
-      wcsdst->pv[npv] = wcssrc->pv[k];
-      wcsdst->pv[npv].i = map[i-1];
-      npv++;
-    }
-  }
-  wcsdst->npv = npv;
-
-  nps = 0;
-  for (k = 0; k < wcssrc->nps; k++) {
-    i = wcssrc->ps[k].i;
-    if (i > 0 && map[i-1]) {
-      wcsdst->ps[nps] = wcssrc->ps[k];
-      wcsdst->ps[nps].i = map[i-1];
-      nps++;
-    }
-  }
-  wcsdst->nps = nps;
-
-  /* Alternate linear transformations. */
-  srcp = wcssrc->cd;
-  dstp = wcsdst->cd;
-  for (i = 0; i < *nsub; i++) {
-    if (axes[i] > 0) {
-      for (j = 0; j < *nsub; j++, dstp++) {
-        if (axes[j] > 0) {
-          k = (axes[i]-1)*naxis + (axes[j]-1);
-          *dstp = *(srcp+k);
-        }
-      }
-    }
-  }
-
-  srcp = wcssrc->crota;
-  dstp = wcsdst->crota;
-  for (i = 0; i < *nsub; i++, dstp++) {
-    if (axes[i] > 0) {
-      k = axes[i] - 1;
-      *dstp = *(srcp+k);
-    }
-  }
-
-  wcsdst->altlin = wcssrc->altlin;
-  wcsdst->velref = wcssrc->velref;
-
-  /* Auxiliary coordinate system information. */
-  strncpy(wcsdst->alt, wcssrc->alt, 4);
-  wcsdst->colnum = wcssrc->colnum;
-
-  strncpy(wcsdst->wcsname, wcssrc->wcsname, 72);
-  for (i = 0; i < *nsub; i++) {
-    if (axes[i] > 0) {
-      k = axes[i] - 1;
-      wcsdst->colax[i] = wcssrc->colax[k];
-      strncpy(wcsdst->cname[i], wcssrc->cname[k], 72);
-      wcsdst->crder[i] = wcssrc->crder[k];
-      wcsdst->csyer[i] = wcssrc->csyer[k];
-    }
-  }
-
-  strncpy(wcsdst->radesys, wcssrc->radesys, 72);
-  wcsdst->equinox = wcssrc->equinox;
-
-  strncpy(wcsdst->specsys, wcssrc->specsys, 72);
-  strncpy(wcsdst->ssysobs, wcssrc->ssysobs, 72);
-  wcsdst->velosys = wcssrc->velosys;
-  strncpy(wcsdst->ssyssrc, wcssrc->ssyssrc, 72);
-  wcsdst->zsource = wcssrc->zsource;
-
-  wcsdst->obsgeo[0] = wcssrc->obsgeo[0];
-  wcsdst->obsgeo[1] = wcssrc->obsgeo[1];
-  wcsdst->obsgeo[2] = wcssrc->obsgeo[2];
-
-  strncpy(wcsdst->dateobs, wcssrc->dateobs, 72);
-  strncpy(wcsdst->dateavg, wcssrc->dateavg, 72);
-  wcsdst->mjdobs = wcssrc->mjdobs;
-  wcsdst->mjdavg = wcssrc->mjdavg;
-
-
-  /* Coordinate lookup tables; only copy what's needed. */
-  wcsdst->ntab = 0;
-  for (itab = 0; itab < wcssrc->ntab; itab++) {
-    /* Is this table wanted? */
-    for (m = 0; m < wcssrc->tab[itab].M; m++) {
-      i = wcssrc->tab[itab].map[m];
-
-      if (map[i-1]) {
-        wcsdst->ntab++;
-        break;
-      }
-    }
-  }
-
-  if (wcsdst->ntab) {
-    /* Allocate memory for tabprm structs. */
-    if (!(wcsdst->tab = calloc(wcsdst->ntab, sizeof(struct tabprm)))) {
-      wcsdst->ntab = 0;
-
-      status = wcserr_set(WCS_ERRMSG(WCSERR_MEMORY));
-      goto cleanup;
-    }
-
-    wcsdst->m_tab = wcsdst->tab;
-  }
-
-  tabp = wcsdst->tab;
-  for (itab = 0; itab < wcssrc->ntab; itab++) {
-    for (m = 0; m < wcssrc->tab[itab].M; m++) {
-      i = wcssrc->tab[itab].map[m];
-
-      if (map[i-1]) {
-        if ((status = tabcpy(1, wcssrc->tab + itab, tabp))) {
-          wcserr_set(WCS_ERRMSG(status));
-          goto cleanup;
-        }
-
-        tabp++;
-        break;
-      }
-    }
-  }
-
-
-cleanup:
-  if (map) free(map);
-  if (dealloc) {
-    free(axes);
-  }
-
-  if (status && wcsdst->m_tab) free(wcsdst->m_tab);
-
-  return status;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int wcsfree(struct wcsprm *wcs)
-
-{
-  int j;
-
-  if (wcs == 0x0) return WCSERR_NULL_POINTER;
-
-  if (wcs->flag == -1) {
-    wcs->lin.flag = -1;
-
-  } else {
-    /* Free memory allocated by wcsini(). */
-    if (wcs->m_flag == WCSSET) {
-      if (wcs->crpix == wcs->m_crpix) wcs->crpix = 0x0;
-      if (wcs->pc    == wcs->m_pc)    wcs->pc    = 0x0;
-      if (wcs->cdelt == wcs->m_cdelt) wcs->cdelt = 0x0;
-      if (wcs->crval == wcs->m_crval) wcs->crval = 0x0;
-      if (wcs->cunit == wcs->m_cunit) wcs->cunit = 0x0;
-      if (wcs->ctype == wcs->m_ctype) wcs->ctype = 0x0;
-      if (wcs->pv    == wcs->m_pv)    wcs->pv    = 0x0;
-      if (wcs->ps    == wcs->m_ps)    wcs->ps    = 0x0;
-      if (wcs->cd    == wcs->m_cd)    wcs->cd    = 0x0;
-      if (wcs->crota == wcs->m_crota) wcs->crota = 0x0;
-      if (wcs->colax == wcs->m_colax) wcs->colax = 0x0;
-      if (wcs->cname == wcs->m_cname) wcs->cname = 0x0;
-      if (wcs->crder == wcs->m_crder) wcs->crder = 0x0;
-      if (wcs->csyer == wcs->m_csyer) wcs->csyer = 0x0;
-      if (wcs->tab   == wcs->m_tab)   wcs->tab   = 0x0;
-      if (wcs->wtb   == wcs->m_wtb)   wcs->wtb   = 0x0;
-
-      if (wcs->m_crpix)  free(wcs->m_crpix);
-      if (wcs->m_pc)     free(wcs->m_pc);
-      if (wcs->m_cdelt)  free(wcs->m_cdelt);
-      if (wcs->m_crval)  free(wcs->m_crval);
-      if (wcs->m_cunit)  free(wcs->m_cunit);
-      if (wcs->m_ctype)  free(wcs->m_ctype);
-      if (wcs->m_pv)     free(wcs->m_pv);
-      if (wcs->m_ps)     free(wcs->m_ps);
-      if (wcs->m_cd)     free(wcs->m_cd);
-      if (wcs->m_crota)  free(wcs->m_crota);
-      if (wcs->m_colax)  free(wcs->m_colax);
-      if (wcs->m_cname)  free(wcs->m_cname);
-      if (wcs->m_crder)  free(wcs->m_crder);
-      if (wcs->m_csyer)  free(wcs->m_csyer);
-
-      /* Free memory allocated by wcstab(). */
-      if (wcs->m_tab) {
-        for (j = 0; j < wcs->ntab; j++) {
-          tabfree(wcs->m_tab + j);
-        }
-
-        free(wcs->m_tab);
-      }
-      if (wcs->m_wtb) free(wcs->m_wtb);
-    }
-
-    /* Free memory allocated by wcsset(). */
-    if (wcs->types) free(wcs->types);
-
-    if (wcs->lin.crpix == wcs->m_crpix) wcs->lin.crpix = 0x0;
-    if (wcs->lin.pc    == wcs->m_pc)    wcs->lin.pc    = 0x0;
-    if (wcs->lin.cdelt == wcs->m_cdelt) wcs->lin.cdelt = 0x0;
-  }
-
-  wcs->m_flag   = 0;
-  wcs->m_naxis  = 0x0;
-  wcs->m_crpix  = 0x0;
-  wcs->m_pc     = 0x0;
-  wcs->m_cdelt  = 0x0;
-  wcs->m_crval  = 0x0;
-  wcs->m_cunit  = 0x0;
-  wcs->m_ctype  = 0x0;
-  wcs->m_pv     = 0x0;
-  wcs->m_ps     = 0x0;
-  wcs->m_cd     = 0x0;
-  wcs->m_crota  = 0x0;
-  wcs->m_colax  = 0x0;
-  wcs->m_cname  = 0x0;
-  wcs->m_crder  = 0x0;
-  wcs->m_csyer  = 0x0;
-
-  wcs->ntab  = 0;
-  wcs->m_tab = 0x0;
-  wcs->nwtb  = 0;
-  wcs->m_wtb = 0x0;
-
-  wcs->types = 0x0;
-
-  wcs->flag = 0;
-
-  if (wcs->err) free(wcs->err);
-  wcs->err = 0x0;
-
-  linfree(&(wcs->lin));
-  celfree(&(wcs->cel));
-  spcfree(&(wcs->spc));
-
-  return 0;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int wcsprt(const struct wcsprm *wcs)
-
-{
-  int i, j, k;
-  struct wtbarr *wtbp;
-
-  if (wcs == 0x0) return WCSERR_NULL_POINTER;
-
-  if (wcs->flag != WCSSET) {
-    wcsprintf("The wcsprm struct is UNINITIALIZED.\n");
-    return 0;
-  }
-
-  wcsprintf("       flag: %d\n", wcs->flag);
-  wcsprintf("      naxis: %d\n", wcs->naxis);
-  WCSPRINTF_PTR("      crpix: ", wcs->crpix, "\n");
-  wcsprintf("            ");
-  for (i = 0; i < wcs->naxis; i++) {
-    wcsprintf("  %- 11.5g", wcs->crpix[i]);
-  }
-  wcsprintf("\n");
-
-  /* Linear transformation. */
-  k = 0;
-  WCSPRINTF_PTR("         pc: ", wcs->pc, "\n");
-  for (i = 0; i < wcs->naxis; i++) {
-    wcsprintf("    pc[%d][]:", i);
-    for (j = 0; j < wcs->naxis; j++) {
-      wcsprintf("  %- 11.5g", wcs->pc[k++]);
-    }
-    wcsprintf("\n");
-  }
-
-  /* Coordinate increment at reference point. */
-  WCSPRINTF_PTR("      cdelt: ", wcs->cdelt, "\n");
-  wcsprintf("            ");
-  for (i = 0; i < wcs->naxis; i++) {
-    wcsprintf("  %- 11.5g", wcs->cdelt[i]);
-  }
-  wcsprintf("\n");
-
-  /* Coordinate value at reference point. */
-  WCSPRINTF_PTR("      crval: ", wcs->crval, "\n");
-  wcsprintf("            ");
-  for (i = 0; i < wcs->naxis; i++) {
-    wcsprintf("  %- 11.5g", wcs->crval[i]);
-  }
-  wcsprintf("\n");
-
-  /* Coordinate units and type. */
-  WCSPRINTF_PTR("      cunit: ", wcs->cunit, "\n");
-  for (i = 0; i < wcs->naxis; i++) {
-    wcsprintf("             \"%s\"\n", wcs->cunit[i]);
-  }
-
-  WCSPRINTF_PTR("      ctype: ", wcs->ctype, "\n");
-  for (i = 0; i < wcs->naxis; i++) {
-    wcsprintf("             \"%s\"\n", wcs->ctype[i]);
-  }
-
-  /* Celestial and spectral transformation parameters. */
-  if (undefined(wcs->lonpole)) {
-    wcsprintf("    lonpole: UNDEFINED\n");
-  } else {
-    wcsprintf("    lonpole: %9f\n", wcs->lonpole);
-  }
-  wcsprintf("    latpole: %9f\n", wcs->latpole);
-  wcsprintf("    restfrq: %f\n", wcs->restfrq);
-  wcsprintf("    restwav: %f\n", wcs->restwav);
-
-  /* Parameter values. */
-  wcsprintf("        npv: %d\n", wcs->npv);
-  wcsprintf("     npvmax: %d\n", wcs->npvmax);
-  WCSPRINTF_PTR("         pv: ", wcs->pv, "\n");
-  for (i = 0; i < wcs->npv; i++) {
-    wcsprintf("             %3d%4d  %- 11.5g\n", (wcs->pv[i]).i,
-      (wcs->pv[i]).m, (wcs->pv[i]).value);
-  }
-  wcsprintf("        nps: %d\n", wcs->nps);
-  wcsprintf("     npsmax: %d\n", wcs->npsmax);
-  WCSPRINTF_PTR("         ps: ", wcs->ps, "\n");
-  for (i = 0; i < wcs->nps; i++) {
-    wcsprintf("             %3d%4d  %s\n", (wcs->ps[i]).i,
-      (wcs->ps[i]).m, (wcs->ps[i]).value);
-  }
-
-  /* Alternate linear transformations. */
-  k = 0;
-  WCSPRINTF_PTR("         cd: ", wcs->cd, "\n");
-  if (wcs->cd) {
-    for (i = 0; i < wcs->naxis; i++) {
-      wcsprintf("    cd[%d][]:", i);
-      for (j = 0; j < wcs->naxis; j++) {
-        wcsprintf("  %- 11.5g", wcs->cd[k++]);
-      }
-      wcsprintf("\n");
-    }
-  }
-
-  WCSPRINTF_PTR("      crota: ", wcs->crota, "\n");
-  if (wcs->crota) {
-    wcsprintf("            ");
-    for (i = 0; i < wcs->naxis; i++) {
-      wcsprintf("  %- 11.5g", wcs->crota[i]);
-    }
-    wcsprintf("\n");
-  }
-
-  wcsprintf("     altlin: %d\n", wcs->altlin);
-  wcsprintf("     velref: %d\n", wcs->velref);
-
-
-
-  /* Auxiliary coordinate system information. */
-  wcsprintf("        alt: '%c'\n", wcs->alt[0]);
-  wcsprintf("     colnum: %d\n", wcs->colnum);
-
-  WCSPRINTF_PTR("      colax: ", wcs->colax, "\n");
-  if (wcs->colax) {
-    wcsprintf("           ");
-    for (i = 0; i < wcs->naxis; i++) {
-      wcsprintf("  %5d", wcs->colax[i]);
-    }
-    wcsprintf("\n");
-  }
-
-  if (wcs->wcsname[0] == '\0') {
-    wcsprintf("    wcsname: UNDEFINED\n");
-  } else {
-    wcsprintf("    wcsname: \"%s\"\n", wcs->wcsname);
-  }
-
-  WCSPRINTF_PTR("      cname: ", wcs->cname, "\n");
-  if (wcs->cname) {
-    for (i = 0; i < wcs->naxis; i++) {
-      if (wcs->cname[i][0] == '\0') {
-        wcsprintf("             UNDEFINED\n");
-      } else {
-        wcsprintf("             \"%s\"\n", wcs->cname[i]);
-      }
-    }
-  }
-
-  WCSPRINTF_PTR("      crder: ", wcs->crder, "\n");
-  if (wcs->crder) {
-    wcsprintf("           ");
-    for (i = 0; i < wcs->naxis; i++) {
-      if (undefined(wcs->crder[i])) {
-        wcsprintf("  UNDEFINED   ");
-      } else {
-        wcsprintf("  %- 11.5g", wcs->crder[i]);
-      }
-    }
-    wcsprintf("\n");
-  }
-
-  WCSPRINTF_PTR("      csyer: ", wcs->csyer, "\n");
-  if (wcs->csyer) {
-    wcsprintf("           ");
-    for (i = 0; i < wcs->naxis; i++) {
-      if (undefined(wcs->csyer[i])) {
-        wcsprintf("  UNDEFINED   ");
-      } else {
-        wcsprintf("  %- 11.5g", wcs->csyer[i]);
-      }
-    }
-    wcsprintf("\n");
-  }
-
-  if (wcs->radesys[0] == '\0') {
-    wcsprintf("    radesys: UNDEFINED\n");
-  } else {
-    wcsprintf("    radesys: \"%s\"\n", wcs->radesys);
-  }
-
-  if (undefined(wcs->equinox)) {
-    wcsprintf("    equinox: UNDEFINED\n");
-  } else {
-    wcsprintf("    equinox: %9f\n", wcs->equinox);
-  }
-
-  if (wcs->specsys[0] == '\0') {
-    wcsprintf("    specsys: UNDEFINED\n");
-  } else {
-    wcsprintf("    specsys: \"%s\"\n", wcs->specsys);
-  }
-
-  if (wcs->ssysobs[0] == '\0') {
-    wcsprintf("    ssysobs: UNDEFINED\n");
-  } else {
-    wcsprintf("    ssysobs: \"%s\"\n", wcs->ssysobs);
-  }
-
-  if (undefined(wcs->velosys)) {
-    wcsprintf("    velosys: UNDEFINED\n");
-  } else {
-    wcsprintf("    velosys: %9f\n", wcs->velosys);
-  }
-
-  if (wcs->ssyssrc[0] == '\0') {
-    wcsprintf("    ssyssrc: UNDEFINED\n");
-  } else {
-    wcsprintf("    ssyssrc: \"%s\"\n", wcs->ssyssrc);
-  }
-
-  if (undefined(wcs->zsource)) {
-    wcsprintf("    zsource: UNDEFINED\n");
-  } else {
-    wcsprintf("    zsource: %9f\n", wcs->zsource);
-  }
-
-  wcsprintf("     obsgeo: ");
-  for (i = 0; i < 3; i++) {
-    if (undefined(wcs->obsgeo[i])) {
-      wcsprintf("UNDEFINED     ");
-    } else {
-      wcsprintf("%- 11.5g  ", wcs->obsgeo[i]);
-    }
-  }
-  wcsprintf("\n");
-
-  if (wcs->dateobs[0] == '\0') {
-    wcsprintf("    dateobs: UNDEFINED\n");
-  } else {
-    wcsprintf("    dateobs: \"%s\"\n", wcs->dateobs);
-  }
-
-  if (wcs->dateavg[0] == '\0') {
-    wcsprintf("    dateavg: UNDEFINED\n");
-  } else {
-    wcsprintf("    dateavg: \"%s\"\n", wcs->dateavg);
-  }
-
-  if (undefined(wcs->mjdobs)) {
-    wcsprintf("     mjdobs: UNDEFINED\n");
-  } else {
-    wcsprintf("     mjdobs: %9f\n", wcs->mjdobs);
-  }
-
-  if (undefined(wcs->mjdavg)) {
-    wcsprintf("     mjdavg: UNDEFINED\n");
-  } else {
-    wcsprintf("     mjdavg: %9f\n", wcs->mjdavg);
-  }
-
-  wcsprintf("       ntab: %d\n", wcs->ntab);
-  WCSPRINTF_PTR("        tab: ", wcs->tab, "");
-  if (wcs->tab != 0x0) wcsprintf("  (see below)");
-  wcsprintf("\n");
-  wcsprintf("       nwtb: %d\n", wcs->nwtb);
-  WCSPRINTF_PTR("        wtb: ", wcs->wtb, "");
-  if (wcs->wtb != 0x0) wcsprintf("  (see below)");
-  wcsprintf("\n");
-
-  /* Derived values. */
-  WCSPRINTF_PTR("      types: ", wcs->types, "\n           ");
-  for (i = 0; i < wcs->naxis; i++) {
-    wcsprintf("%5d", wcs->types[i]);
-  }
-  wcsprintf("\n");
-
-  wcsprintf("     lngtyp: \"%s\"\n", wcs->lngtyp);
-  wcsprintf("     lattyp: \"%s\"\n", wcs->lattyp);
-  wcsprintf("        lng: %d\n", wcs->lng);
-  wcsprintf("        lat: %d\n", wcs->lat);
-  wcsprintf("       spec: %d\n", wcs->spec);
-  wcsprintf("   cubeface: %d\n", wcs->cubeface);
-
-  WCSPRINTF_PTR("        err: ", wcs->err, "\n");
-  if (wcs->err) {
-    wcserr_prt(wcs->err, "             ");
-  }
-
-  wcsprintf("        lin: (see below)\n");
-  wcsprintf("        cel: (see below)\n");
-  wcsprintf("        spc: (see below)\n");
-
-  /* Memory management. */
-  wcsprintf("     m_flag: %d\n", wcs->m_flag);
-  wcsprintf("    m_naxis: %d\n", wcs->m_naxis);
-  WCSPRINTF_PTR("    m_crpix: ", wcs->m_crpix, "");
-  if (wcs->m_crpix == wcs->crpix) wcsprintf("  (= crpix)");
-  wcsprintf("\n");
-  WCSPRINTF_PTR("       m_pc: ", wcs->m_pc, "");
-  if (wcs->m_pc == wcs->pc) wcsprintf("  (= pc)");
-  wcsprintf("\n");
-  WCSPRINTF_PTR("    m_cdelt: ", wcs->m_cdelt, "");
-  if (wcs->m_cdelt == wcs->cdelt) wcsprintf("  (= cdelt)");
-  wcsprintf("\n");
-  WCSPRINTF_PTR("    m_crval: ", wcs->m_crval, "");
-  if (wcs->m_crval == wcs->crval) wcsprintf("  (= crval)");
-  wcsprintf("\n");
-  WCSPRINTF_PTR("    m_cunit: ", wcs->m_cunit, "");
-  if (wcs->m_cunit == wcs->cunit) wcsprintf("  (= cunit)");
-  wcsprintf("\n");
-  WCSPRINTF_PTR("    m_ctype: ", wcs->m_ctype, "");
-  if (wcs->m_ctype == wcs->ctype) wcsprintf("  (= ctype)");
-  wcsprintf("\n");
-  WCSPRINTF_PTR("       m_pv: ", wcs->m_pv, "");
-  if (wcs->m_pv == wcs->pv) wcsprintf("  (= pv)");
-  wcsprintf("\n");
-  WCSPRINTF_PTR("       m_ps: ", wcs->m_ps, "");
-  if (wcs->m_ps == wcs->ps) wcsprintf("  (= ps)");
-  wcsprintf("\n");
-  WCSPRINTF_PTR("       m_cd: ", wcs->m_cd, "");
-  if (wcs->m_cd == wcs->cd) wcsprintf("  (= cd)");
-  wcsprintf("\n");
-  WCSPRINTF_PTR("    m_crota: ", wcs->m_crota, "");
-  if (wcs->m_crota == wcs->crota) wcsprintf("  (= crota)");
-  wcsprintf("\n");
-  wcsprintf("\n");
-  WCSPRINTF_PTR("    m_colax: ", wcs->m_colax, "");
-  if (wcs->m_colax == wcs->colax) wcsprintf("  (= colax)");
-  wcsprintf("\n");
-  WCSPRINTF_PTR("    m_cname: ", wcs->m_cname, "");
-  if (wcs->m_cname == wcs->cname) wcsprintf("  (= cname)");
-  wcsprintf("\n");
-  WCSPRINTF_PTR("    m_crder: ", wcs->m_crder, "");
-  if (wcs->m_crder == wcs->crder) wcsprintf("  (= crder)");
-  wcsprintf("\n");
-  WCSPRINTF_PTR("    m_csyer: ", wcs->m_csyer, "");
-  if (wcs->m_csyer == wcs->csyer) wcsprintf("  (= csyer)");
-  wcsprintf("\n");
-  WCSPRINTF_PTR("      m_tab: ", wcs->m_tab, "");
-  if (wcs->m_tab == wcs->tab) wcsprintf("  (= tab)");
-  wcsprintf("\n");
-  WCSPRINTF_PTR("      m_wtb: ", wcs->m_wtb, "");
-  if (wcs->m_wtb == wcs->wtb) wcsprintf("  (= wtb)");
-  wcsprintf("\n");
-
-  /* Tabular transformation parameters. */
-  if ((wtbp = wcs->wtb)) {
-    for (j = 0; j < wcs->nwtb; j++, wtbp++) {
-      wcsprintf("\n");
-      wcsprintf("wtb[%d].*\n", j);
-      wcsprintf("          i: %d\n", wtbp->i);
-      wcsprintf("          m: %d\n", wtbp->m);
-      wcsprintf("       kind: %c\n", wtbp->kind);
-      wcsprintf("     extnam: %s\n", wtbp->extnam);
-      wcsprintf("     extver: %d\n", wtbp->extver);
-      wcsprintf("     extlev: %d\n", wtbp->extlev);
-      wcsprintf("      ttype: %s\n", wtbp->ttype);
-      wcsprintf("        row: %ld\n", wtbp->row);
-      wcsprintf("       ndim: %d\n", wtbp->ndim);
-      WCSPRINTF_PTR("     dimlen: ", wtbp->dimlen, "\n");
-      WCSPRINTF_PTR("     arrayp: ", wtbp->arrayp, " -> ");
-      WCSPRINTF_PTR("", *(wtbp->arrayp), "\n");
-    }
-  }
-
-  if (wcs->tab) {
-    for (j = 0; j < wcs->ntab; j++) {
-      wcsprintf("\n");
-      wcsprintf("tab[%d].*\n", j);
-      tabprt(wcs->tab + j);
-    }
-  }
-
-  /* Linear transformation parameters. */
-  wcsprintf("\n");
-  wcsprintf("   lin.*\n");
-  linprt(&(wcs->lin));
-
-  /* Celestial transformation parameters. */
-  wcsprintf("\n");
-  wcsprintf("   cel.*\n");
-  celprt(&(wcs->cel));
-
-  /* Spectral transformation parameters. */
-  wcsprintf("\n");
-  wcsprintf("   spc.*\n");
-  spcprt(&(wcs->spc));
-
-  return 0;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int wcsperr(const struct wcsprm *wcs, const char *prefix)
-
-{
-  int j;
-
-  if (wcs == 0x0) return WCSERR_NULL_POINTER;
-
-  if (!wcserr_prt(wcs->err, prefix)) {
-    wcserr_prt(wcs->lin.err, prefix);
-    wcserr_prt(wcs->cel.err, prefix);
-    wcserr_prt(wcs->cel.prj.err, prefix);
-    wcserr_prt(wcs->spc.err, prefix);
-    if (wcs->tab) {
-      for (j = 0; j < wcs->ntab; j++) {
-        wcserr_prt((wcs->tab + j)->err, prefix);
-      }
-    }
-  }
-
-  return 0;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int wcsset(struct wcsprm *wcs)
-
-{
-  static const char *function = "wcsset";
-
-  char scode[4], stype[5];
-  int i, j, k, m, naxis, status;
-  double lambda, rho;
-  double *cd, *pc;
-  struct celprm *wcscel = &(wcs->cel);
-  struct prjprm *wcsprj = &(wcscel->prj);
-  struct spcprm *wcsspc = &(wcs->spc);
-  struct wcserr **err;
-
-
-  if (wcs == 0x0) return WCSERR_NULL_POINTER;
-  err = &(wcs->err);
-
-  /* Determine axis types from CTYPEia. */
-  if ((status = wcs_types(wcs))) {
-    return status;
-  }
-
-  /* Convert to canonical units. */
-  if ((status = wcs_units(wcs))) {
-    return status;
-  }
-
-
-  /* Non-linear celestial axes present? */
-  if (wcs->lng >= 0 && wcs->types[wcs->lng] == 2200) {
-    celini(wcscel);
-
-    /* CRVALia, LONPOLEa, and LATPOLEa keyvalues. */
-    wcscel->ref[0] = wcs->crval[wcs->lng];
-    wcscel->ref[1] = wcs->crval[wcs->lat];
-    wcscel->ref[2] = wcs->lonpole;
-    wcscel->ref[3] = wcs->latpole;
-
-    /* PVi_ma keyvalues. */
-    for (k = 0; k < wcs->npv; k++) {
-      i = wcs->pv[k].i - 1;
-      m = wcs->pv[k].m;
-
-      if (i == -1) {
-        /* From a PROJPn keyword. */
-        i = wcs->lat;
-      }
-
-      if (i == wcs->lat) {
-        /* PVi_ma associated with latitude axis. */
-        if (m < 30) {
-          wcsprj->pv[m] = wcs->pv[k].value;
-        }
-
-      } else if (i == wcs->lng) {
-        /* PVi_ma associated with longitude axis. */
-        switch (m) {
-        case 0:
-          wcscel->offset = (wcs->pv[k].value != 0.0);
-          break;
-        case 1:
-          wcscel->phi0   = wcs->pv[k].value;
-          break;
-        case 2:
-          wcscel->theta0 = wcs->pv[k].value;
-          break;
-        case 3:
-          /* If present, overrides LONPOLEa. */
-          wcscel->ref[2] = wcs->pv[k].value;
-          break;
-        case 4:
-          /* If present, overrides LATPOLEa. */
-          wcscel->ref[3] = wcs->pv[k].value;
-          break;
-        default:
-          return wcserr_set(WCSERR_SET(WCSERR_BAD_COORD_TRANS),
-            "PV%i_%i%s: Unrecognized coordinate transformation parameter",
-            i+1, m, wcs->alt);
-          break;
-        }
-      }
-    }
-
-    /* Do simple alias translations. */
-    if (strncmp(wcs->ctype[wcs->lng]+5, "GLS", 3) == 0) {
-      wcscel->offset = 1;
-      wcscel->phi0   = 0.0;
-      wcscel->theta0 = wcs->crval[wcs->lat];
-      strcpy(wcsprj->code, "SFL");
-
-    } else if (strncmp(wcs->ctype[wcs->lng]+5, "NCP", 3) == 0) {
-      /* Convert NCP to SIN. */
-      if (wcscel->ref[1] == 0.0) {
-        return wcserr_set(WCSERR_SET(WCSERR_BAD_PARAM),
-          "Invalid projection: NCP blows up on the equator");
-      }
-
-      strcpy(wcsprj->code, "SIN");
-      wcsprj->pv[1] = 0.0;
-      wcsprj->pv[2] = cosd(wcscel->ref[1])/sind(wcscel->ref[1]);
-
-    } else {
-      strncpy(wcsprj->code, wcs->ctype[wcs->lng]+5, 3);
-      wcsprj->code[3] = '\0';
-    }
-
-    /* Initialize the celestial transformation routines. */
-    wcsprj->r0 = 0.0;
-    if ((status = celset(wcscel))) {
-      return wcserr_set(WCS_ERRMSG(status+3));
-    }
-
-    /* Update LONPOLE, LATPOLE, and PVi_ma keyvalues. */
-    wcs->lonpole = wcscel->ref[2];
-    wcs->latpole = wcscel->ref[3];
-
-    for (k = 0; k < wcs->npv; k++) {
-      i = wcs->pv[k].i - 1;
-      m = wcs->pv[k].m;
-
-      if (i == wcs->lng) {
-        switch (m) {
-        case 1:
-          wcs->pv[k].value = wcscel->phi0;
-          break;
-        case 2:
-          wcs->pv[k].value = wcscel->theta0;
-          break;
-        case 3:
-          wcs->pv[k].value = wcscel->ref[2];
-          break;
-        case 4:
-          wcs->pv[k].value = wcscel->ref[3];
-          break;
-        }
-      }
-    }
-  }
-
-
-  /* Non-linear spectral axis present? */
-  if (wcs->spec >= 0 && wcs->types[wcs->spec] == 3300) {
-    spcini(wcsspc);
-    if ((status = spctype(wcs->ctype[wcs->spec], stype, scode, 0x0, 0x0, 0x0,
-                          0x0, 0x0, err))) {
-      return status;
-    }
-    strcpy(wcsspc->type, stype);
-    strcpy(wcsspc->code, scode);
-
-    /* CRVALia, RESTFRQa, and RESTWAVa keyvalues. */
-    wcsspc->crval = wcs->crval[wcs->spec];
-    wcsspc->restfrq = wcs->restfrq;
-    wcsspc->restwav = wcs->restwav;
-
-    /* PVi_ma keyvalues. */
-    for (k = 0; k < wcs->npv; k++) {
-      i = wcs->pv[k].i - 1;
-      m = wcs->pv[k].m;
-
-      if (i == wcs->spec) {
-        /* PVi_ma associated with grism axis. */
-        if (m < 7) {
-          wcsspc->pv[m] = wcs->pv[k].value;
-        }
-      }
-    }
-
-    /* Initialize the spectral transformation routines. */
-    if ((status = spcset(wcsspc))) {
-      return wcserr_set(WCS_ERRMSG(status+3));
-    }
-  }
-
-
-  /* Tabular axes present? */
-  for (j = 0; j < wcs->ntab; j++) {
-    if ((status = tabset(wcs->tab + j))) {
-      return wcserr_set(WCS_ERRMSG(status+3));
-    }
-  }
-
-
-  /* Initialize the linear transformation. */
-  naxis = wcs->naxis;
-  wcs->altlin &= 7;
-  if (wcs->altlin > 1 && !(wcs->altlin & 1)) {
-    pc = wcs->pc;
-
-    if (wcs->altlin & 2) {
-      /* Copy CDi_ja to PCi_ja and reset CDELTia. */
-      cd = wcs->cd;
-      for (i = 0; i < naxis; i++) {
-        for (j = 0; j < naxis; j++) {
-          *(pc++) = *(cd++);
-        }
-        wcs->cdelt[i] = 1.0;
-      }
-
-    } else if (wcs->altlin & 4) {
-      /* Construct PCi_ja from CROTAia. */
-      if ((i = wcs->lng) >= 0 && (j = wcs->lat) >= 0) {
-        rho = wcs->crota[j];
-
-        if (wcs->cdelt[i] == 0.0) {
-          return wcserr_set(WCSERR_SET(WCSERR_SINGULAR_MTX),
-            "Singular transformation matrix, CDELT%d is zero", i+1);
-        }
-        lambda = wcs->cdelt[j]/wcs->cdelt[i];
-
-        *(pc + i*naxis + i) = *(pc + j*naxis + j) = cosd(rho);
-        *(pc + i*naxis + j) = *(pc + j*naxis + i) = sind(rho);
-        *(pc + i*naxis + j) *= -lambda;
-        *(pc + j*naxis + i) /=  lambda;
-      }
-    }
-  }
-
-  wcs->lin.crpix  = wcs->crpix;
-  wcs->lin.pc     = wcs->pc;
-  wcs->lin.cdelt  = wcs->cdelt;
-  if ((status = linset(&(wcs->lin)))) {
-    return wcserr_set(WCS_ERRMSG(status));
-  }
-
-
-  /* Strip off trailing blanks and null-fill auxiliary string members. */
-  wcsutil_null_fill(4, wcs->alt);
-  wcsutil_null_fill(72, wcs->wcsname);
-  for (i = 0; i < naxis; i++) {
-    wcsutil_null_fill(72, wcs->cname[i]);
-  }
-  wcsutil_null_fill(72, wcs->radesys);
-  wcsutil_null_fill(72, wcs->specsys);
-  wcsutil_null_fill(72, wcs->ssysobs);
-  wcsutil_null_fill(72, wcs->ssyssrc);
-  wcsutil_null_fill(72, wcs->dateobs);
-  wcsutil_null_fill(72, wcs->dateavg);
-
-  wcs->flag = WCSSET;
-
-  return 0;
-}
-
-/* : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :  */
-
-int wcs_types(struct wcsprm *wcs)
-
-{
-  static const char *function = "wcs_types";
-
-  const int  nalias = 2;
-  const char aliases [2][4] = {"NCP", "GLS"};
-
-  const char *alt = "";
-  char ctypei[16], pcode[4], requir[9], scode[4], specsys[9];
-  int i, j, m, naxis, *ndx = 0x0, type;
-  struct wcserr **err;
-
-  if (wcs == 0x0) return WCSERR_NULL_POINTER;
-  err = &(wcs->err);
-
-  /* Parse the CTYPEia keyvalues. */
-  pcode[0]  = '\0';
-  requir[0] = '\0';
-  wcs->lng  = -1;
-  wcs->lat  = -1;
-  wcs->spec = -1;
-  wcs->cubeface = -1;
-
-  if (*(wcs->alt) != ' ') alt = wcs->alt;
-
-
-  naxis = wcs->naxis;
-  if (wcs->types) free(wcs->types);
-  wcs->types = calloc(naxis, sizeof(int));
-  if (wcs->types == NULL) {
-    return wcserr_set(WCS_ERRMSG(WCSERR_MEMORY));
-  }
-
-  for (i = 0; i < naxis; i++) {
-    /* Null fill. */
-    wcsutil_null_fill(72, wcs->ctype[i]);
-
-    strncpy(ctypei, wcs->ctype[i], 15);
-    ctypei[15] = '\0';
-
-    /* Check for early Paper IV syntax (e.g. '-SIP' used by Spitzer). */
-    if (strlen(ctypei) == 12 && ctypei[8] == '-') {
-      /* Excise the "4-3-3" or "8-3"-form distortion code. */
-      ctypei[8] = '\0';
-
-      /* Remove trailing dashes from "8-3"-form codes. */
-      for (j = 7; j > 0; j--) {
-        if (ctypei[j] != '-') break;
-        ctypei[j] = '\0';
-      }
-    }
-
-    /* Logarithmic or tabular axis? */
-    wcs->types[i] = 0;
-    if (strcmp(ctypei+4, "-LOG") == 0) {
-      /* Logarithmic axis. */
-      wcs->types[i] = 400;
-
-    } else if (strcmp(ctypei+4, "-TAB") == 0) {
-      /* Tabular axis. */
-      wcs->types[i] = 500;
-    }
-
-    if (wcs->types[i]) {
-      /* Could have -LOG or -TAB with celestial or spectral types. */
-      ctypei[4] = '\0';
-
-      /* Take care of things like 'FREQ-LOG' or 'RA---TAB'. */
-      for (j = 3; j >= 0; j--) {
-        if (ctypei[j] != '-') break;
-        ctypei[j] = '\0';
-      }
-    }
-
-    /* Translate AIPS spectral types for spctyp(). */
-    if (spcaips(ctypei, wcs->velref, ctypei, specsys) == 0) {
-      strcpy(wcs->ctype[i], ctypei);
-      if (wcs->specsys[0] == '\0') strcpy(wcs->specsys, specsys);
-    }
-
-    /* Process linear axes. */
-    if (!(strlen(ctypei) == 8 && ctypei[4] == '-') ||
-        (strlen(ctypei) > 8 && ctypei[8] == '-')) {
-      /* Identify Stokes, celestial and spectral types. */
-      if (strcmp(ctypei, "STOKES") == 0) {
-        /* STOKES axis. */
-        wcs->types[i] = 1100;
-
-      } else if (strcmp(ctypei, "RA")  == 0 ||
-        strcmp(ctypei+1, "LON") == 0 ||
-        strcmp(ctypei+2, "LN")  == 0) {
-        /* Longitude axis. */
-        if (wcs->lng < 0) wcs->lng = i;
-        wcs->types[i] += 2000;
-
-      } else if (strcmp(ctypei,   "DEC") == 0 ||
-                 strcmp(ctypei+1, "LAT") == 0 ||
-                 strcmp(ctypei+2, "LT")  == 0) {
-        /* Latitude axis. */
-        if (wcs->lat < 0) wcs->lat = i;
-        wcs->types[i] += 2001;
-
-      } else if (strcmp(ctypei, "CUBEFACE") == 0) {
-        /* CUBEFACE axis. */
-        if (wcs->cubeface == -1) {
-          wcs->types[i] = 2102;
-          wcs->cubeface = i;
-        } else {
-          /* Multiple CUBEFACE axes! */
-          return wcserr_set(WCSERR_SET(WCSERR_BAD_CTYPE),
-            "Multiple CUBEFACE axes (in CTYPE%d%.1s and CTYPE%d%.1s)",
-            wcs->cubeface+1, alt, i+1, alt);
-        }
-
-      } else if (spctyp(ctypei, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0) == 0) {
-        /* Spectral axis. */
-        if (wcs->spec < 0) wcs->spec = i;
-        wcs->types[i] += 3000;
-      }
-
-      continue;
-    }
-
-
-    /* CTYPEia is in "4-3" form; is it a recognized spectral type? */
-    if (spctyp(ctypei, 0x0, scode, 0x0, 0x0, 0x0, 0x0, 0x0) == 0) {
-      /* Non-linear spectral axis found. */
-      wcs->types[i] = 3300;
-
-      /* Check uniqueness. */
-      if (wcs->spec >= 0) {
-        return wcserr_set(WCSERR_SET(WCSERR_BAD_CTYPE),
-          "Multiple spectral axes (in CTYPE%d%.1s and CTYPE%d%.1s)",
-          wcs->spec+1, alt, i+1, alt);
-      }
-
-      wcs->spec = i;
-
-      continue;
-    }
-
-
-    /* Is it a recognized celestial projection? */
-    for (j = 0; j < prj_ncode; j++) {
-      if (strncmp(ctypei+5, prj_codes[j], 3) == 0) break;
-    }
-
-    if (j == prj_ncode) {
-      /* Not a standard projection code, maybe it's an alias. */
-      for (j = 0; j < nalias; j++) {
-        if (strncmp(ctypei+5, aliases[j], 3) == 0) break;
-      }
-
-      if (j == nalias) {
-        /* Not a recognized algorithm code of any type. */
-        wcs->types[i] = -1;
-        return wcserr_set(WCSERR_SET(WCSERR_BAD_CTYPE),
-          "Unrecognized projection code (%s in CTYPE%d%.1s)",
-          ctypei+5, i+1, alt);
-      }
-    }
-
-    /* Parse the celestial axis type. */
-    wcs->types[i] = 2200;
-    if (*pcode == '\0') {
-      /* The first of the two celestial axes. */
-      sprintf(pcode, "%.3s", ctypei+5);
-
-      if (strncmp(ctypei, "RA--", 4) == 0) {
-        wcs->lng = i;
-        strcpy(wcs->lngtyp, "RA");
-        strcpy(wcs->lattyp, "DEC");
-        ndx = &wcs->lat;
-        sprintf(requir, "DEC--%s", pcode);
-      } else if (strncmp(ctypei, "DEC-", 4) == 0) {
-        wcs->lat = i;
-        strcpy(wcs->lngtyp, "RA");
-        strcpy(wcs->lattyp, "DEC");
-        ndx = &wcs->lng;
-        sprintf(requir, "RA---%s", pcode);
-      } else if (strncmp(ctypei+1, "LON", 3) == 0) {
-        wcs->lng = i;
-        sprintf(wcs->lngtyp, "%cLON", ctypei[0]);
-        sprintf(wcs->lattyp, "%cLAT", ctypei[0]);
-        ndx = &wcs->lat;
-        sprintf(requir, "%s-%s", wcs->lattyp, pcode);
-      } else if (strncmp(ctypei+1, "LAT", 3) == 0) {
-        wcs->lat = i;
-        sprintf(wcs->lngtyp, "%cLON", ctypei[0]);
-        sprintf(wcs->lattyp, "%cLAT", ctypei[0]);
-        ndx = &wcs->lng;
-        sprintf(requir, "%s-%s", wcs->lngtyp, pcode);
-      } else if (strncmp(ctypei+2, "LN", 2) == 0) {
-        wcs->lng = i;
-        sprintf(wcs->lngtyp, "%c%cLN", ctypei[0], ctypei[1]);
-        sprintf(wcs->lattyp, "%c%cLT", ctypei[0], ctypei[1]);
-        ndx = &wcs->lat;
-        sprintf(requir, "%s-%s", wcs->lattyp, pcode);
-      } else if (strncmp(ctypei+2, "LT", 2) == 0) {
-        wcs->lat = i;
-        sprintf(wcs->lngtyp, "%c%cLN", ctypei[0], ctypei[1]);
-        sprintf(wcs->lattyp, "%c%cLT", ctypei[0], ctypei[1]);
-        ndx = &wcs->lng;
-        sprintf(requir, "%s-%s", wcs->lngtyp, pcode);
-      } else {
-        /* Unrecognized celestial type. */
-        wcs->types[i] = -1;
-
-        wcs->lng = -1;
-        wcs->lat = -1;
-        return wcserr_set(WCSERR_SET(WCSERR_BAD_CTYPE),
-          "Unrecognized celestial type (%5s in CTYPE%d%.1s)",
-          ctypei, i+1, alt);
-      }
-
-      if (wcs->lat >= 0) wcs->types[i]++;
-
-    } else {
-      /* Looking for the complementary celestial axis. */
-      if (wcs->lat < 0) wcs->types[i]++;
-
-      if (strncmp(ctypei, requir, 8) != 0) {
-        /* Inconsistent projection types. */
-        wcs->lng = -1;
-        wcs->lat = -1;
-        return wcserr_set(WCSERR_SET(WCSERR_BAD_CTYPE), "Inconsistent "
-          "projection types (expected %s, got %s in CTYPE%d%.1s)", requir,
-          ctypei, i+1, alt);
-      }
-
-      *ndx = i;
-      requir[0] = '\0';
-    }
-  }
-
-  /* Do we have a complementary pair of celestial axes? */
-  if (strcmp(requir, "")) {
-    /* Unmatched celestial axis. */
-    wcs->lng = -1;
-    wcs->lat = -1;
-    return wcserr_set(WCSERR_SET(WCSERR_BAD_CTYPE),
-      "Unmatched celestial axes");
-  }
-
-  /* Table group numbers. */
-  for (j = 0; j < wcs->ntab; j++) {
-    for (m = 0; m < wcs->tab[j].M; m++) {
-      /* Get image axis number. */
-      i = wcs->tab[j].map[m];
-
-      type = (wcs->types[i] / 100) % 10;
-      if (type != 5) {
-        return wcserr_set(WCSERR_SET(WCSERR_BAD_CTYPE),
-          "Table parameters set for non-table axis type");
-      }
-      wcs->types[i] += 10 * j;
-    }
-  }
-
-  return 0;
-}
-
-/* : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :  */
-
-int wcs_units(struct wcsprm *wcs)
-
-{
-  static const char *function = "wcs_units";
-
-  char ctype[9], units[16];
-  int  i, j, naxis;
-  double scale, offset, power;
-  struct wcserr *uniterr = 0x0, **err;
-
-  if (wcs == 0x0) return WCSERR_NULL_POINTER;
-  err = &(wcs->err);
-
-  naxis = wcs->naxis;
-  for (i = 0; i < naxis; i++) {
-    /* Use types set by wcs_types(). */
-    switch (wcs->types[i]/1000) {
-    case 2:
-      /* Celestial axis. */
-      strcpy(units, "deg");
-      break;
-
-    case 3:
-      /* Spectral axis. */
-      strncpy(ctype, wcs->ctype[i], 8);
-      ctype[8] = '\0';
-      spctyp(ctype, 0x0, 0x0, 0x0, units, 0x0, 0x0, 0x0);
-      break;
-
-    default:
-      continue;
-    }
-
-    /* Tabular axis, CDELTia and CRVALia relate to indices. */
-    if ((wcs->types[i]/100)%10 == 5) {
-      continue;
-    }
-
-    wcsutil_null_fill(72, wcs->cunit[i]);
-    if (wcs->cunit[i][0]) {
-      if (wcsunitse(wcs->cunit[i], units, &scale, &offset, &power,
-                    &uniterr)) {
-        wcserr_set(WCSERR_SET(WCSERR_BAD_COORD_TRANS),
-          "In CUNIT%d%.1s: %s", i, (*wcs->alt)?wcs->alt:"", uniterr->msg);
-        free(uniterr);
-        return WCSERR_BAD_COORD_TRANS;
-      }
-
-      if (scale != 1.0) {
-        wcs->cdelt[i] *= scale;
-        wcs->crval[i] *= scale;
-
-        for (j = 0; j < naxis; j++) {
-          *(wcs->cd + i*naxis + j) *= scale;
-        }
-
-        strcpy(wcs->cunit[i], units);
-      }
-
-    } else {
-      strcpy(wcs->cunit[i], units);
-    }
-  }
-
-  return 0;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int wcsp2s(
-  struct wcsprm *wcs,
-  int ncoord,
-  int nelem,
-  const double pixcrd[],
-  double imgcrd[],
-  double phi[],
-  double theta[],
-  double world[],
-  int stat[])
-
-{
-  static const char *function = "wcsp2s";
-
-  int    bits, face, i, iso_x, iso_y, istat, *istatp, itab, k, m, nx, ny,
-        *statp, status, type;
-  double crvali, offset;
-  register double *img, *wrl;
-  struct celprm *wcscel = &(wcs->cel);
-  struct prjprm *wcsprj = &(wcscel->prj);
-  struct wcserr **err;
-
-  /* Initialize if required. */
-  if (wcs == 0x0) return WCSERR_NULL_POINTER;
-  err = &(wcs->err);
-
-  if (wcs->flag != WCSSET) {
-    if ((status = wcsset(wcs))) return status;
-  }
-
-  /* Sanity check. */
-  if (ncoord < 1 || (ncoord > 1 && nelem < wcs->naxis)) {
-    return wcserr_set(WCSERR_SET(WCSERR_BAD_CTYPE),
-      "ncoord and/or nelem inconsistent with the wcsprm");
-  }
-
-
-  /* Apply pixel-to-world linear transformation. */
-  if ((status = linp2x(&(wcs->lin), ncoord, nelem, pixcrd, imgcrd))) {
-    return wcserr_set(WCS_ERRMSG(status));
-  }
-
-  /* Initialize status vectors. */
-  if (!(istatp = calloc(ncoord, sizeof(int)))) {
-    return wcserr_set(WCS_ERRMSG(WCSERR_MEMORY));
-  }
-
-  stat[0] = 0;
-  wcsutil_setAli(ncoord, 1, stat);
-
-
-  /* Convert intermediate world coordinates to world coordinates. */
-  for (i = 0; i < wcs->naxis; i++) {
-    /* Extract the second digit of the axis type code. */
-    type = (wcs->types[i] / 100) % 10;
-
-    if (type <= 1) {
-      /* Linear or quantized coordinate axis. */
-      img = imgcrd + i;
-      wrl = world  + i;
-      crvali = wcs->crval[i];
-      for (k = 0; k < ncoord; k++) {
-        *wrl = *img + crvali;
-        img += nelem;
-        wrl += nelem;
-      }
-
-    } else if (wcs->types[i] == 2200) {
-      /* Convert celestial coordinates; do we have a CUBEFACE axis? */
-      if (wcs->cubeface != -1) {
-        /* Separation between faces. */
-        if (wcsprj->r0 == 0.0) {
-          offset = 90.0;
-        } else {
-          offset = wcsprj->r0*PI/2.0;
-        }
-
-        /* Lay out faces in a plane. */
-        img = imgcrd;
-        statp = stat;
-        bits = (1 << i) | (1 << wcs->lat);
-        for (k = 0; k < ncoord; k++, statp++) {
-          face = (int)(*(img+wcs->cubeface) + 0.5);
-          if (fabs(*(img+wcs->cubeface) - face) > 1e-10) {
-            *statp |= bits;
-            status = wcserr_set(WCS_ERRMSG(WCSERR_BAD_PIX));
-
-          } else {
-            *statp = 0;
-
-            switch (face) {
-            case 0:
-              *(img+wcs->lat) += offset;
-              break;
-            case 1:
-              break;
-            case 2:
-              *(img+i) += offset;
-              break;
-            case 3:
-              *(img+i) += offset*2;
-              break;
-            case 4:
-              *(img+i) += offset*3;
-              break;
-            case 5:
-              *(img+wcs->lat) -= offset;
-              break;
-            default:
-              *statp |= bits;
-              status = wcserr_set(WCS_ERRMSG(WCSERR_BAD_PIX));
-            }
-          }
-
-          img += nelem;
-        }
-      }
-
-      /* Check for constant x and/or y. */
-      nx = ncoord;
-      ny = 0;
-
-      if ((iso_x = wcsutil_allEq(ncoord, nelem, imgcrd+i))) {
-        nx = 1;
-        ny = ncoord;
-      }
-      if ((iso_y = wcsutil_allEq(ncoord, nelem, imgcrd+wcs->lat))) {
-        ny = 1;
-      }
-
-      /* Transform projection plane coordinates to celestial coordinates. */
-      if ((istat = celx2s(wcscel, nx, ny, nelem, nelem, imgcrd+i,
-                          imgcrd+wcs->lat, phi, theta, world+i,
-                          world+wcs->lat, istatp))) {
-        if (istat == CELERR_BAD_PIX) {
-          status = wcserr_set(WCS_ERRMSG(WCSERR_BAD_PIX));
-        } else {
-          status = wcserr_set(WCS_ERRMSG(istat+3));
-          goto cleanup;
-        }
-      }
-
-      /* If x and y were both constant, replicate values. */
-      if (iso_x && iso_y) {
-        wcsutil_setAll(ncoord, nelem, world+i);
-        wcsutil_setAll(ncoord, nelem, world+wcs->lat);
-        wcsutil_setAll(ncoord, 1, phi);
-        wcsutil_setAll(ncoord, 1, theta);
-        wcsutil_setAli(ncoord, 1, istatp);
-      }
-
-      if (istat == 5) {
-        bits = (1 << i) | (1 << wcs->lat);
-        wcsutil_setBit(ncoord, istatp, bits, stat);
-      }
-
-    } else if (type == 3 || type == 4) {
-      /* Check for constant x. */
-      nx = ncoord;
-      if ((iso_x = wcsutil_allEq(ncoord, nelem, imgcrd+i))) {
-        nx = 1;
-      }
-
-      istat = 0;
-      if (wcs->types[i] == 3300) {
-        /* Spectral coordinates. */
-        istat = spcx2s(&(wcs->spc), nx, nelem, nelem, imgcrd+i, world+i,
-                       istatp);
-        if (istat == SPCERR_BAD_X) {
-          status = wcserr_set(WCS_ERRMSG(WCSERR_BAD_PIX));
-        } else if (istat) {
-          status = wcserr_set(WCS_ERRMSG(istat+3));
-          goto cleanup;
-        }
-      } else if (type == 4) {
-        /* Logarithmic coordinates. */
-        istat = logx2s(wcs->crval[i], nx, nelem, nelem, imgcrd+i, world+i,
-                       istatp);
-        if (istat == LOGERR_BAD_X) {
-          if (*err == 0x0) {
-            wcserr_set(WCS_ERRMSG(WCSERR_BAD_PIX));
-          }
-        } else if (istat == LOGERR_BAD_LOG_REF_VAL) {
-          wcserr_set(WCSERR_SET(WCSERR_BAD_PARAM), log_errmsg[istat]);
-          goto cleanup;
-        }
-      }
-
-      /* If x was constant, replicate values. */
-      if (iso_x) {
-        wcsutil_setAll(ncoord, nelem, world+i);
-        wcsutil_setAli(ncoord, 1, istatp);
-      }
-
-      if (istat == 3) {
-        wcsutil_setBit(ncoord, istatp, 1 << i, stat);
-      }
-    }
-  }
-
-
-  /* Do tabular coordinates. */
-  for (itab = 0; itab < wcs->ntab; itab++) {
-    istat = tabx2s(wcs->tab + itab, ncoord, nelem, imgcrd, world, istatp);
-
-    if (istat == TABERR_BAD_X) {
-      status = wcserr_set(WCS_ERRMSG(WCSERR_BAD_PIX));
-
-      bits = 0;
-      for (m = 0; m < wcs->tab[itab].M; m++) {
-        bits |= 1 << wcs->tab[itab].map[m];
-      }
-      wcsutil_setBit(ncoord, istatp, bits, stat);
-
-    } else if (istat) {
-      if (istat == TABERR_BAD_PARAMS) istat = WCSERR_BAD_PARAM;
-      status = wcserr_set(WCS_ERRMSG(istat));
-      goto cleanup;
-    }
-  }
-
-
-  /* Zero the unused world coordinate elements. */
-  for (i = wcs->naxis; i < nelem; i++) {
-    world[i] = 0.0;
-    wcsutil_setAll(ncoord, nelem, world+i);
-  }
-
-cleanup:
-  free(istatp);
-  return status;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int wcss2p(
-  struct wcsprm* wcs,
-  int ncoord,
-  int nelem,
-  const double world[],
-  double phi[],
-  double theta[],
-  double imgcrd[],
-  double pixcrd[],
-  int stat[])
-
-{
-  static const char *function = "wcss2p";
-
-  int    bits, i, isolat, isolng, isospec, istat, *istatp, itab, k, m, nlat,
-         nlng, nwrld, status, type;
-  double crvali, offset;
-  register const double *wrl;
-  register double *img;
-  struct celprm *wcscel = &(wcs->cel);
-  struct prjprm *wcsprj = &(wcscel->prj);
-  struct wcserr **err;
-
-
-  /* Initialize if required. */
-  if (wcs == 0x0) return WCSERR_NULL_POINTER;
-  err = &(wcs->err);
-
-  if (wcs->flag != WCSSET) {
-    if ((status = wcsset(wcs))) return status;
-  }
-
-  /* Sanity check. */
-  if (ncoord < 1 || (ncoord > 1 && nelem < wcs->naxis)) {
-    return wcserr_set(WCSERR_SET(WCSERR_BAD_CTYPE),
-      "ncoord and/or nelem inconsistent with the wcsprm");
-  }
-
-  /* Initialize status vectors. */
-  if (!(istatp = calloc(ncoord, sizeof(int)))) {
-    return wcserr_set(WCS_ERRMSG(WCSERR_MEMORY));
-  }
-
-  status = 0;
-  stat[0] = 0;
-  wcsutil_setAli(ncoord, 1, stat);
-
-
-  /* Convert world coordinates to intermediate world coordinates. */
-  for (i = 0; i < wcs->naxis; i++) {
-    /* Extract the second digit of the axis type code. */
-    type = (wcs->types[i] / 100) % 10;
-
-    if (type <= 1) {
-      /* Linear or quantized coordinate axis. */
-      wrl = world  + i;
-      img = imgcrd + i;
-      crvali = wcs->crval[i];
-      for (k = 0; k < ncoord; k++) {
-        *img = *wrl - crvali;
-        wrl += nelem;
-        img += nelem;
-      }
-
-    } else if (wcs->types[i] == 2200) {
-      /* Celestial coordinates; check for constant lng and/or lat. */
-      nlng = ncoord;
-      nlat = 0;
-
-      if ((isolng = wcsutil_allEq(ncoord, nelem, world+i))) {
-        nlng = 1;
-        nlat = ncoord;
-      }
-      if ((isolat = wcsutil_allEq(ncoord, nelem, world+wcs->lat))) {
-        nlat = 1;
-      }
-
-      /* Transform celestial coordinates to projection plane coordinates. */
-      if ((istat = cels2x(wcscel, nlng, nlat, nelem, nelem, world+i,
-                          world+wcs->lat, phi, theta, imgcrd+i,
-                          imgcrd+wcs->lat, istatp))) {
-        if (istat == CELERR_BAD_WORLD) {
-          status = wcserr_set(WCS_ERRMSG(WCSERR_BAD_WORLD));
-        } else {
-          status = wcserr_set(WCS_ERRMSG(istat+3));
-          goto cleanup;
-        }
-      }
-
-      /* If lng and lat were both constant, replicate values. */
-      if (isolng && isolat) {
-        wcsutil_setAll(ncoord, nelem, imgcrd+i);
-        wcsutil_setAll(ncoord, nelem, imgcrd+wcs->lat);
-        wcsutil_setAll(ncoord, 1, phi);
-        wcsutil_setAll(ncoord, 1, theta);
-        wcsutil_setAli(ncoord, 1, istatp);
-      }
-
-      if (istat == CELERR_BAD_WORLD) {
-        bits = (1 << i) | (1 << wcs->lat);
-        wcsutil_setBit(ncoord, istatp, bits, stat);
-      }
-
-      /* Do we have a CUBEFACE axis? */
-      if (wcs->cubeface != -1) {
-        /* Separation between faces. */
-        if (wcsprj->r0 == 0.0) {
-          offset = 90.0;
-        } else {
-          offset = wcsprj->r0*PI/2.0;
-        }
-
-        /* Stack faces in a cube. */
-        img = imgcrd;
-        for (k = 0; k < ncoord; k++) {
-          if (*(img+wcs->lat) < -0.5*offset) {
-            *(img+wcs->lat) += offset;
-            *(img+wcs->cubeface) = 5.0;
-          } else if (*(img+wcs->lat) > 0.5*offset) {
-            *(img+wcs->lat) -= offset;
-            *(img+wcs->cubeface) = 0.0;
-          } else if (*(img+i) > 2.5*offset) {
-            *(img+i) -= 3.0*offset;
-            *(img+wcs->cubeface) = 4.0;
-          } else if (*(img+i) > 1.5*offset) {
-            *(img+i) -= 2.0*offset;
-            *(img+wcs->cubeface) = 3.0;
-          } else if (*(img+i) > 0.5*offset) {
-            *(img+i) -= offset;
-            *(img+wcs->cubeface) = 2.0;
-          } else {
-            *(img+wcs->cubeface) = 1.0;
-          }
-
-          img += nelem;
-        }
-      }
-
-    } else if (type == 3 || type == 4) {
-      /* Check for constancy. */
-      nwrld = ncoord;
-      if ((isospec = wcsutil_allEq(ncoord, nelem, world+i))) {
-        nwrld = 1;
-      }
-
-      istat = 0;
-      if (wcs->types[i] == 3300) {
-        /* Spectral coordinates. */
-        istat = spcs2x(&(wcs->spc), nwrld, nelem, nelem, world+i,
-                       imgcrd+i, istatp);
-        if (istat == SPCERR_BAD_SPEC) {
-          status = wcserr_set(WCS_ERRMSG(WCSERR_BAD_WORLD));
-        } else if (istat) {
-          status = wcserr_set(WCS_ERRMSG(istat+3));
-          goto cleanup;
-        }
-      } else if (type == 4) {
-        /* Logarithmic coordinates. */
-        istat = logs2x(wcs->crval[i], nwrld, nelem, nelem, world+i,
-                       imgcrd+i, istatp);
-        if (istat == LOGERR_BAD_WORLD) {
-          status = wcserr_set(WCS_ERRMSG(WCSERR_BAD_WORLD));
-        } else if (istat == LOGERR_BAD_LOG_REF_VAL) {
-          status = wcserr_set(WCSERR_SET(WCSERR_BAD_PARAM),
-                     log_errmsg[istat]);
-          goto cleanup;
-        }
-      }
-
-      /* If constant, replicate values. */
-      if (isospec) {
-        wcsutil_setAll(ncoord, nelem, imgcrd+i);
-        wcsutil_setAli(ncoord, 1, istatp);
-      }
-
-      if (istat == 4) {
-        wcsutil_setBit(ncoord, istatp, 1 << i, stat);
-      }
-    }
-  }
-
-
-  /* Do tabular coordinates. */
-  for (itab = 0; itab < wcs->ntab; itab++) {
-    istat = tabs2x(wcs->tab + itab, ncoord, nelem, world, imgcrd, istatp);
-
-    if (istat == TABERR_BAD_WORLD) {
-      status = wcserr_set(WCS_ERRMSG(WCSERR_BAD_WORLD));
-
-      bits = 0;
-      for (m = 0; m < wcs->tab[itab].M; m++) {
-        bits |= 1 << wcs->tab[itab].map[m];
-      }
-      wcsutil_setBit(ncoord, istatp, bits, stat);
-
-    } else if (istat) {
-      if (istat == TABERR_BAD_PARAMS) istat = WCSERR_BAD_PARAM;
-      status = wcserr_set(WCS_ERRMSG(istat));
-      goto cleanup;
-    }
-  }
-
-
-  /* Zero the unused intermediate world coordinate elements. */
-  for (i = wcs->naxis; i < nelem; i++) {
-    imgcrd[i] = 0.0;
-    wcsutil_setAll(ncoord, nelem, imgcrd+i);
-  }
-
-
-  /* Apply world-to-pixel linear transformation. */
-  if ((istat = linx2p(&(wcs->lin), ncoord, nelem, imgcrd, pixcrd))) {
-    status = wcserr_set(WCS_ERRMSG(istat));
-    goto cleanup;
-  }
-
-cleanup:
-  free(istatp);
-  return status;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int wcsmix(
-  struct wcsprm *wcs,
-  int mixpix,
-  int mixcel,
-  const double vspan[2],
-  double vstep,
-  int viter,
-  double world[],
-  double phi[],
-  double theta[],
-  double imgcrd[],
-  double pixcrd[])
-
-{
-  static const char *function = "wcsmix";
-
-  const int niter = 60;
-  int    crossed, istep, iter, j, k, nstep, retry, stat[1], status;
-  const double tol  = 1.0e-10;
-  const double tol2 = 100.0*tol;
-  double *worldlat, *worldlng;
-  double lambda, span[2], step;
-  double pixmix;
-  double dlng, lng, lng0, lng0m, lng1, lng1m;
-  double dlat, lat, lat0, lat0m, lat1, lat1m;
-  double d, d0, d0m, d1, d1m, dx = 0.0;
-  double dabs, dmin, lmin;
-  double dphi, phi0, phi1;
-  struct celprm *wcscel = &(wcs->cel);
-  struct wcsprm wcs0;
-  struct wcserr **err;
-
-  /* Initialize if required. */
-  if (wcs == 0x0) return WCSERR_NULL_POINTER;
-  err = &(wcs->err);
-
-  if (wcs->flag != WCSSET) {
-    if ((status = wcsset(wcs))) return status;
-  }
-
-  worldlng = world + wcs->lng;
-  worldlat = world + wcs->lat;
-
-
-  /* Check vspan. */
-  if (vspan[0] <= vspan[1]) {
-    span[0] = vspan[0];
-    span[1] = vspan[1];
-  } else {
-    /* Swap them. */
-    span[0] = vspan[1];
-    span[1] = vspan[0];
-  }
-
-  /* Check vstep. */
-  step = fabs(vstep);
-  if (step == 0.0) {
-    step = (span[1] - span[0])/10.0;
-    if (step > 1.0 || step == 0.0) step = 1.0;
-  }
-
-  /* Check viter. */
-  nstep = viter;
-  if (nstep < 5) {
-    nstep = 5;
-  } else if (nstep > 10) {
-    nstep = 10;
-  }
-
-  /* Given pixel element. */
-  pixmix = pixcrd[mixpix];
-
-  /* Iterate on the step size. */
-  for (istep = 0; istep <= nstep; istep++) {
-    if (istep) step /= 2.0;
-
-    /* Iterate on the sky coordinate between the specified range. */
-    if (mixcel == 1) {
-      /* Celestial longitude is given. */
-
-      /* Check whether the solution interval is a crossing interval. */
-      lat0 = span[0];
-      *worldlat = lat0;
-      if ((status = wcss2p(wcs, 1, 0, world, phi, theta, imgcrd, pixcrd,
-                           stat))) {
-        if (status == WCSERR_BAD_WORLD) {
-          status = wcserr_set(WCS_ERRMSG(WCSERR_BAD_WORLD_COORD));
-        }
-        return status;
-      }
-      d0 = pixcrd[mixpix] - pixmix;
-
-      dabs = fabs(d0);
-      if (dabs < tol) return 0;
-
-      lat1 = span[1];
-      *worldlat = lat1;
-      if ((status = wcss2p(wcs, 1, 0, world, phi, theta, imgcrd, pixcrd,
-                           stat))) {
-        if (status == WCSERR_BAD_WORLD) {
-          status = wcserr_set(WCS_ERRMSG(WCSERR_BAD_WORLD_COORD));
-        }
-        return status;
-      }
-      d1 = pixcrd[mixpix] - pixmix;
-
-      dabs = fabs(d1);
-      if (dabs < tol) return 0;
-
-      lmin = lat1;
-      dmin = dabs;
-
-      /* Check for a crossing point. */
-      if (signbit(d0) != signbit(d1)) {
-        crossed = 1;
-        dx = d1;
-      } else {
-        crossed = 0;
-        lat0 = span[1];
-      }
-
-      for (retry = 0; retry < 4; retry++) {
-        /* Refine the solution interval. */
-        while (lat0 > span[0]) {
-          lat0 -= step;
-          if (lat0 < span[0]) lat0 = span[0];
-          *worldlat = lat0;
-          if ((status = wcss2p(wcs, 1, 0, world, phi, theta, imgcrd, pixcrd,
-                               stat))) {
-            if (status == WCSERR_BAD_WORLD) {
-              status = wcserr_set(WCS_ERRMSG(WCSERR_BAD_WORLD_COORD));
-            }
-            return status;
-          }
-          d0 = pixcrd[mixpix] - pixmix;
-
-          /* Check for a solution. */
-          dabs = fabs(d0);
-          if (dabs < tol) return 0;
-
-          /* Record the point of closest approach. */
-          if (dabs < dmin) {
-            lmin = lat0;
-            dmin = dabs;
-          }
-
-          /* Check for a crossing point. */
-          if (signbit(d0) != signbit(d1)) {
-            crossed = 2;
-            dx = d0;
-            break;
-          }
-
-          /* Advance to the next subinterval. */
-          lat1 = lat0;
-          d1 = d0;
-        }
-
-        if (crossed) {
-          /* A crossing point was found. */
-          for (iter = 0; iter < niter; iter++) {
-            /* Use regula falsi division of the interval. */
-            lambda = d0/(d0-d1);
-            if (lambda < 0.1) {
-              lambda = 0.1;
-            } else if (lambda > 0.9) {
-              lambda = 0.9;
-            }
-
-            dlat = lat1 - lat0;
-            lat = lat0 + lambda*dlat;
-            *worldlat = lat;
-            if ((status = wcss2p(wcs, 1, 0, world, phi, theta, imgcrd, pixcrd,
-                                 stat))) {
-              if (status == WCSERR_BAD_WORLD) {
-                status = wcserr_set(WCS_ERRMSG(WCSERR_BAD_WORLD_COORD));
-              }
-              return status;
-            }
-
-            /* Check for a solution. */
-            d = pixcrd[mixpix] - pixmix;
-            dabs = fabs(d);
-            if (dabs < tol) return 0;
-
-            if (dlat < tol) {
-              /* An artifact of numerical imprecision. */
-              if (dabs < tol2) return 0;
-
-              /* Must be a discontinuity. */
-              break;
-            }
-
-            /* Record the point of closest approach. */
-            if (dabs < dmin) {
-              lmin = lat;
-              dmin = dabs;
-            }
-
-            if (signbit(d0) == signbit(d)) {
-              lat0 = lat;
-              d0 = d;
-            } else {
-              lat1 = lat;
-              d1 = d;
-            }
-          }
-
-          /* No convergence, must have been a discontinuity. */
-          if (crossed == 1) lat0 = span[1];
-          lat1 = lat0;
-          d1 = dx;
-          crossed = 0;
-
-        } else {
-          /* No crossing point; look for a tangent point. */
-          if (lmin == span[0]) break;
-          if (lmin == span[1]) break;
-
-          lat = lmin;
-          lat0 = lat - step;
-          if (lat0 < span[0]) lat0 = span[0];
-          lat1 = lat + step;
-          if (lat1 > span[1]) lat1 = span[1];
-
-          *worldlat = lat0;
-          if ((status = wcss2p(wcs, 1, 0, world, phi, theta, imgcrd, pixcrd,
-                               stat))) {
-            if (status == WCSERR_BAD_WORLD) {
-              status = wcserr_set(WCS_ERRMSG(WCSERR_BAD_WORLD_COORD));
-            }
-            return status;
-          }
-          d0 = fabs(pixcrd[mixpix] - pixmix);
-
-          d  = dmin;
-
-          *worldlat = lat1;
-          if ((status = wcss2p(wcs, 1, 0, world, phi, theta, imgcrd, pixcrd,
-                               stat))) {
-            if (status == WCSERR_BAD_WORLD) {
-              status = wcserr_set(WCS_ERRMSG(WCSERR_BAD_WORLD_COORD));
-            }
-            return status;
-          }
-          d1 = fabs(pixcrd[mixpix] - pixmix);
-
-          for (iter = 0; iter < niter; iter++) {
-            lat0m = (lat0 + lat)/2.0;
-            *worldlat = lat0m;
-            if ((status = wcss2p(wcs, 1, 0, world, phi, theta, imgcrd, pixcrd,
-                                 stat))) {
-              if (status == WCSERR_BAD_WORLD) {
-                status = wcserr_set(WCS_ERRMSG(WCSERR_BAD_WORLD_COORD));
-              }
-              return status;
-            }
-            d0m = fabs(pixcrd[mixpix] - pixmix);
-
-            if (d0m < tol) return 0;
-
-            lat1m = (lat1 + lat)/2.0;
-            *worldlat = lat1m;
-            if ((status = wcss2p(wcs, 1, 0, world, phi, theta, imgcrd, pixcrd,
-                                 stat))) {
-              if (status == WCSERR_BAD_WORLD) {
-                status = wcserr_set(WCS_ERRMSG(WCSERR_BAD_WORLD_COORD));
-              }
-              return status;
-            }
-            d1m = fabs(pixcrd[mixpix] - pixmix);
-
-            if (d1m < tol) return 0;
-
-            if (d0m < d && d0m <= d1m) {
-              lat1 = lat;
-              d1   = d;
-              lat  = lat0m;
-              d    = d0m;
-            } else if (d1m < d) {
-              lat0 = lat;
-              d0   = d;
-              lat  = lat1m;
-              d    = d1m;
-            } else {
-              lat0 = lat0m;
-              d0   = d0m;
-              lat1 = lat1m;
-              d1   = d1m;
-            }
-          }
-        }
-      }
-
-    } else {
-      /* Celestial latitude is given. */
-
-      /* Check whether the solution interval is a crossing interval. */
-      lng0 = span[0];
-      *worldlng = lng0;
-      if ((status = wcss2p(wcs, 1, 0, world, phi, theta, imgcrd, pixcrd,
-                           stat))) {
-        if (status == WCSERR_BAD_WORLD) {
-          status = wcserr_set(WCS_ERRMSG(WCSERR_BAD_WORLD_COORD));
-        }
-        return status;
-      }
-      d0 = pixcrd[mixpix] - pixmix;
-
-      dabs = fabs(d0);
-      if (dabs < tol) return 0;
-
-      lng1 = span[1];
-      *worldlng = lng1;
-      if ((status = wcss2p(wcs, 1, 0, world, phi, theta, imgcrd, pixcrd,
-                           stat))) {
-        if (status == WCSERR_BAD_WORLD) {
-          status = wcserr_set(WCS_ERRMSG(WCSERR_BAD_WORLD_COORD));
-        }
-        return status;
-      }
-      d1 = pixcrd[mixpix] - pixmix;
-
-      dabs = fabs(d1);
-      if (dabs < tol) return 0;
-      lmin = lng1;
-      dmin = dabs;
-
-      /* Check for a crossing point. */
-      if (signbit(d0) != signbit(d1)) {
-        crossed = 1;
-        dx = d1;
-      } else {
-        crossed = 0;
-        lng0 = span[1];
-      }
-
-      for (retry = 0; retry < 4; retry++) {
-        /* Refine the solution interval. */
-        while (lng0 > span[0]) {
-          lng0 -= step;
-          if (lng0 < span[0]) lng0 = span[0];
-          *worldlng = lng0;
-          if ((status = wcss2p(wcs, 1, 0, world, phi, theta, imgcrd, pixcrd,
-                               stat))) {
-            if (status == WCSERR_BAD_WORLD) {
-              status = wcserr_set(WCS_ERRMSG(WCSERR_BAD_WORLD_COORD));
-            }
-            return status;
-          }
-          d0 = pixcrd[mixpix] - pixmix;
-
-          /* Check for a solution. */
-          dabs = fabs(d0);
-          if (dabs < tol) return 0;
-
-          /* Record the point of closest approach. */
-          if (dabs < dmin) {
-            lmin = lng0;
-            dmin = dabs;
-          }
-
-          /* Check for a crossing point. */
-          if (signbit(d0) != signbit(d1)) {
-            crossed = 2;
-            dx = d0;
-            break;
-          }
-
-          /* Advance to the next subinterval. */
-          lng1 = lng0;
-          d1 = d0;
-        }
-
-        if (crossed) {
-          /* A crossing point was found. */
-          for (iter = 0; iter < niter; iter++) {
-            /* Use regula falsi division of the interval. */
-            lambda = d0/(d0-d1);
-            if (lambda < 0.1) {
-              lambda = 0.1;
-            } else if (lambda > 0.9) {
-              lambda = 0.9;
-            }
-
-            dlng = lng1 - lng0;
-            lng = lng0 + lambda*dlng;
-            *worldlng = lng;
-            if ((status = wcss2p(wcs, 1, 0, world, phi, theta, imgcrd, pixcrd,
-                                 stat))) {
-              if (status == WCSERR_BAD_WORLD) {
-                status = wcserr_set(WCS_ERRMSG(WCSERR_BAD_WORLD_COORD));
-              }
-              return status;
-            }
-
-            /* Check for a solution. */
-            d = pixcrd[mixpix] - pixmix;
-            dabs = fabs(d);
-            if (dabs < tol) return 0;
-
-            if (dlng < tol) {
-              /* An artifact of numerical imprecision. */
-              if (dabs < tol2) return 0;
-
-              /* Must be a discontinuity. */
-              break;
-            }
-
-            /* Record the point of closest approach. */
-            if (dabs < dmin) {
-              lmin = lng;
-              dmin = dabs;
-            }
-
-            if (signbit(d0) == signbit(d)) {
-              lng0 = lng;
-              d0 = d;
-            } else {
-              lng1 = lng;
-              d1 = d;
-            }
-          }
-
-          /* No convergence, must have been a discontinuity. */
-          if (crossed == 1) lng0 = span[1];
-          lng1 = lng0;
-          d1 = dx;
-          crossed = 0;
-
-        } else {
-          /* No crossing point; look for a tangent point. */
-          if (lmin == span[0]) break;
-          if (lmin == span[1]) break;
-
-          lng = lmin;
-          lng0 = lng - step;
-          if (lng0 < span[0]) lng0 = span[0];
-          lng1 = lng + step;
-          if (lng1 > span[1]) lng1 = span[1];
-
-          *worldlng = lng0;
-          if ((status = wcss2p(wcs, 1, 0, world, phi, theta, imgcrd, pixcrd,
-                               stat))) {
-            if (status == WCSERR_BAD_WORLD) {
-              status = wcserr_set(WCS_ERRMSG(WCSERR_BAD_WORLD_COORD));
-            }
-            return status;
-          }
-          d0 = fabs(pixcrd[mixpix] - pixmix);
-
-          d  = dmin;
-
-          *worldlng = lng1;
-          if ((status = wcss2p(wcs, 1, 0, world, phi, theta, imgcrd, pixcrd,
-                               stat))) {
-            if (status == WCSERR_BAD_WORLD) {
-              status = wcserr_set(WCS_ERRMSG(WCSERR_BAD_WORLD_COORD));
-            }
-            return status;
-          }
-          d1 = fabs(pixcrd[mixpix] - pixmix);
-
-          for (iter = 0; iter < niter; iter++) {
-            lng0m = (lng0 + lng)/2.0;
-            *worldlng = lng0m;
-            if ((status = wcss2p(wcs, 1, 0, world, phi, theta, imgcrd, pixcrd,
-                                 stat))) {
-              if (status == WCSERR_BAD_WORLD) {
-                status = wcserr_set(WCS_ERRMSG(WCSERR_BAD_WORLD_COORD));
-              }
-              return status;
-            }
-            d0m = fabs(pixcrd[mixpix] - pixmix);
-
-            if (d0m < tol) return 0;
-
-            lng1m = (lng1 + lng)/2.0;
-            *worldlng = lng1m;
-            if ((status = wcss2p(wcs, 1, 0, world, phi, theta, imgcrd, pixcrd,
-                                 stat))) {
-              if (status == WCSERR_BAD_WORLD) {
-                status = wcserr_set(WCS_ERRMSG(WCSERR_BAD_WORLD_COORD));
-              }
-              return status;
-            }
-            d1m = fabs(pixcrd[mixpix] - pixmix);
-
-            if (d1m < tol) return 0;
-
-            if (d0m < d && d0m <= d1m) {
-              lng1 = lng;
-              d1   = d;
-              lng  = lng0m;
-              d    = d0m;
-            } else if (d1m < d) {
-              lng0 = lng;
-              d0   = d;
-              lng  = lng1m;
-              d    = d1m;
-            } else {
-              lng0 = lng0m;
-              d0   = d0m;
-              lng1 = lng1m;
-              d1   = d1m;
-            }
-          }
-        }
-      }
-    }
-  }
-
-
-  /* Set cel0 to the unity transformation. */
-  wcs0 = *wcs;
-  wcs0.cel.euler[0] = -90.0;
-  wcs0.cel.euler[1] =   0.0;
-  wcs0.cel.euler[2] =  90.0;
-  wcs0.cel.euler[3] =   1.0;
-  wcs0.cel.euler[4] =   0.0;
-
-  /* No convergence, check for aberrant behaviour at a native pole. */
-  *theta = -90.0;
-  for (j = 1; j <= 2; j++) {
-    /* Could the celestial coordinate element map to a native pole? */
-    *phi = 0.0;
-    *theta = -*theta;
-    sphx2s(wcscel->euler, 1, 1, 1, 1, phi, theta, &lng, &lat);
-
-    if (mixcel == 1) {
-      if (fabs(fmod(*worldlng-lng, 360.0)) > tol) continue;
-      if (lat < span[0]) continue;
-      if (lat > span[1]) continue;
-      *worldlat = lat;
-    } else {
-      if (fabs(*worldlat-lat) > tol) continue;
-      if (lng < span[0]) lng += 360.0;
-      if (lng > span[1]) lng -= 360.0;
-      if (lng < span[0]) continue;
-      if (lng > span[1]) continue;
-      *worldlng = lng;
-    }
-
-    /* Is there a solution for the given pixel coordinate element? */
-    lng = *worldlng;
-    lat = *worldlat;
-
-    /* Feed native coordinates to wcss2p() with cel0 set to unity. */
-    *worldlng = -180.0;
-    *worldlat = *theta;
-    if ((status = wcss2p(&wcs0, 1, 0, world, phi, theta, imgcrd, pixcrd,
-                         stat))) {
-      if (wcs->err) free(wcs->err);
-      wcs->err = wcs0.err;
-      if (status == WCSERR_BAD_WORLD) {
-        status = wcserr_set(WCS_ERRMSG(WCSERR_BAD_WORLD_COORD));
-      }
-      return status;
-    }
-    d0 = pixcrd[mixpix] - pixmix;
-
-    /* Check for a solution. */
-    if (fabs(d0) < tol) {
-      /* Recall saved world coordinates. */
-      *worldlng = lng;
-      *worldlat = lat;
-      return 0;
-    }
-
-    /* Search for a crossing interval. */
-    phi0 = -180.0;
-    for (k = -179; k <= 180; k++) {
-      phi1 = (double) k;
-      *worldlng = phi1;
-      if ((status = wcss2p(&wcs0, 1, 0, world, phi, theta, imgcrd, pixcrd,
-                           stat))) {
-        if (wcs->err) free(wcs->err);
-        wcs->err = wcs0.err;
-        if (status == WCSERR_BAD_WORLD) {
-          status = wcserr_set(WCS_ERRMSG(WCSERR_BAD_WORLD_COORD));
-        }
-        return status;
-      }
-      d1 = pixcrd[mixpix] - pixmix;
-
-      /* Check for a solution. */
-      dabs = fabs(d1);
-      if (dabs < tol) {
-        /* Recall saved world coordinates. */
-        *worldlng = lng;
-        *worldlat = lat;
-        return 0;
-      }
-
-      /* Is it a crossing interval? */
-      if (signbit(d0) != signbit(d1)) break;
-
-      phi0 = phi1;
-      d0 = d1;
-    }
-
-    for (iter = 1; iter <= niter; iter++) {
-      /* Use regula falsi division of the interval. */
-      lambda = d0/(d0-d1);
-      if (lambda < 0.1) {
-        lambda = 0.1;
-      } else if (lambda > 0.9) {
-        lambda = 0.9;
-      }
-
-      dphi = phi1 - phi0;
-      *worldlng = phi0 + lambda*dphi;
-      if ((status = wcss2p(&wcs0, 1, 0, world, phi, theta, imgcrd, pixcrd,
-                           stat))) {
-        if (wcs->err) free(wcs->err);
-        wcs->err = wcs0.err;
-        if (status == WCSERR_BAD_WORLD) {
-          status = wcserr_set(WCS_ERRMSG(WCSERR_BAD_WORLD_COORD));
-        }
-        return status;
-      }
-
-      /* Check for a solution. */
-      d = pixcrd[mixpix] - pixmix;
-      dabs = fabs(d);
-      if (dabs < tol || (dphi < tol && dabs < tol2)) {
-        /* Recall saved world coordinates. */
-        *worldlng = lng;
-        *worldlat = lat;
-        return 0;
-      }
-
-      if (signbit(d0) == signbit(d)) {
-        phi0 = *worldlng;
-        d0 = d;
-      } else {
-        phi1 = *worldlng;
-        d1 = d;
-      }
-    }
-  }
-
-
-  /* No solution. */
-  return wcserr_set(WCS_ERRMSG(WCSERR_NO_SOLUTION));
-}
-
-/*--------------------------------------------------------------------------*/
-
-int wcssptr(
-  struct wcsprm *wcs,
-  int  *i,
-  char ctype[9])
-
-{
-  static const char *function = "wcssptr";
-
-  int    j, status;
-  double cdelt, crval;
-  struct wcserr **err;
-
-  /* Initialize if required. */
-  if (wcs == 0x0) return WCSERR_NULL_POINTER;
-  err = &(wcs->err);
-
-  if (wcs->flag != WCSSET) {
-    if ((status = wcsset(wcs))) return status;
-  }
-
-  if ((j = *i) < 0) {
-    if ((j = wcs->spec) < 0) {
-      /* Look for a linear spectral axis. */
-      for (j = 0; j < wcs->naxis; j++) {
-        if (wcs->types[j]/100 == 30) {
-          break;
-        }
-      }
-
-      if (j >= wcs->naxis) {
-        /* No spectral axis. */
-        return wcserr_set(WCSERR_SET(WCSERR_BAD_SUBIMAGE),
-          "No spectral axis found.");
-      }
-    }
-
-    *i = j;
-  }
-
-  /* Translate the spectral axis. */
-  if (spctrne(wcs->ctype[j], wcs->crval[j], wcs->cdelt[j], wcs->restfrq,
-              wcs->restwav, ctype, &crval, &cdelt, &(wcs->spc.err))) {
-    return wcserr_set(WCS_ERRMSG(WCSERR_BAD_COORD_TRANS));
-  }
-
-
-  /* Translate keyvalues. */
-  wcs->flag = 0;
-  wcs->cdelt[j] = cdelt;
-  wcs->crval[j] = crval;
-  spctyp(ctype, 0x0, 0x0, 0x0, wcs->cunit[j], 0x0, 0x0, 0x0);
-  strcpy(wcs->ctype[j], ctype);
-
-  /* This keeps things tidy if the spectral axis is linear. */
-  spcini(&(wcs->spc));
-
-  return 0;
-}
diff --git a/astropy/wcs/src/wcslib/C/wcs.h b/astropy/wcs/src/wcslib/C/wcs.h
deleted file mode 100644
index 9567b5f..0000000
--- a/astropy/wcs/src/wcslib/C/wcs.h
+++ /dev/null
@@ -1,1540 +0,0 @@
-/*============================================================================
-
-  WCSLIB 4.10 - an implementation of the FITS WCS standard.
-  Copyright (C) 1995-2012, Mark Calabretta
-
-  This file is part of WCSLIB.
-
-  WCSLIB is free software: you can redistribute it and/or modify it under the
-  terms of the GNU Lesser General Public License as published by the Free
-  Software Foundation, either version 3 of the License, or (at your option)
-  any later version.
-
-  WCSLIB 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 Lesser General Public License for
-  more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with WCSLIB.  If not, see <http://www.gnu.org/licenses/>.
-
-  Correspondence concerning WCSLIB may be directed to:
-    Internet email: mcalabre at atnf.csiro.au
-    Postal address: Dr. Mark Calabretta
-                    Australia Telescope National Facility, CSIRO
-                    PO Box 76
-                    Epping NSW 1710
-                    AUSTRALIA
-
-  Author: Mark Calabretta, Australia Telescope National Facility
-  http://www.atnf.csiro.au/~mcalabre/index.html
-  $Id: wcs.h,v 4.10 2012/02/05 23:41:44 cal103 Exp $
-*=============================================================================
-*
-* WCSLIB 4.10 - C routines that implement the FITS World Coordinate System
-* (WCS) standard.  Refer to
-*
-*   "Representations of world coordinates in FITS",
-*   Greisen, E.W., & Calabretta, M.R. 2002, A&A, 395, 1061 (Paper I)
-*
-*   "Representations of celestial coordinates in FITS",
-*   Calabretta, M.R., & Greisen, E.W. 2002, A&A, 395, 1077 (Paper II)
-*
-*   "Representations of spectral coordinates in FITS",
-*   Greisen, E.W., Calabretta, M.R., Valdes, F.G., & Allen, S.L.
-*   2006, A&A, 446, 747 (Paper III)
-*
-* Refer to the README file provided with WCSLIB for an overview of the
-* library.
-*
-*
-* Summary of the wcs routines
-* ---------------------------
-* These routines implement the FITS World Coordinate System (WCS) standard
-* which defines methods to be used for computing world coordinates from image
-* pixel coordinates, and vice versa.  They are based on the wcsprm struct
-* which contains all information needed for the computations.  The struct
-* contains some members that must be set by the user, and others that are
-* maintained by these routines, somewhat like a C++ class but with no
-* encapsulation.
-*
-* Three routines, wcsini(), wcssub(), and wcsfree() are provided to manage the
-* wcsprm struct and another, wcsprt(), to prints its contents.  Refer to the
-* description of the wcsprm struct for an explanation of the anticipated usage
-* of these routines.  wcscopy(), which does a deep copy of one wcsprm struct
-* to another, is defined as a preprocessor macro function that invokes
-* wcssub().
-*
-* wcsperr() prints the error message(s) (if any) stored in a wcsprm struct,
-* and the linprm, celprm, prjprm, spcprm, and tabprm structs that it contains.
-*
-* A setup routine, wcsset(), computes intermediate values in the wcsprm struct
-* from parameters in it that were supplied by the user.  The struct always
-* needs to be set up by wcsset() but this need not be called explicitly -
-* refer to the explanation of wcsprm::flag.
-*
-* wcsp2s() and wcss2p() implement the WCS world coordinate transformations.
-* In fact, they are high level driver routines for the WCS linear,
-* logarithmic, celestial, spectral and tabular transformation routines
-* described in lin.h, log.h, cel.h, spc.h and tab.h.
-*
-* Given either the celestial longitude or latitude plus an element of the
-* pixel coordinate a hybrid routine, wcsmix(), iteratively solves for the
-* unknown elements.
-*
-* wcssptr() translates the spectral axis in a wcsprm struct.  For example, a
-* 'FREQ' axis may be translated into 'ZOPT-F2W' and vice versa.
-*
-* Quadcube projections:
-* ---------------------
-*   The quadcube projections (TSC, CSC, QSC) may be represented in FITS in
-*   either of two ways:
-*
-*     a: The six faces may be laid out in one plane and numbered as follows:
-*
-=                                 0
-=
-=                        4  3  2  1  4  3  2
-=
-=                                 5
-*
-*        Faces 2, 3 and 4 may appear on one side or the other (or both).  The
-*        world-to-pixel routines map faces 2, 3 and 4 to the left but the
-*        pixel-to-world routines accept them on either side.
-*
-*     b: The "COBE" convention in which the six faces are stored in a
-*        three-dimensional structure using a CUBEFACE axis indexed from
-*        0 to 5 as above.
-*
-*   These routines support both methods; wcsset() determines which is being
-*   used by the presence or absence of a CUBEFACE axis in ctype[].  wcsp2s()
-*   and wcss2p() translate the CUBEFACE axis representation to the single
-*   plane representation understood by the lower-level WCSLIB projection
-*   routines.
-*
-*
-* wcsini() - Default constructor for the wcsprm struct
-* ----------------------------------------------------
-* wcsini() optionally allocates memory for arrays in a wcsprm struct and sets
-* all members of the struct to default values.  Memory is allocated for up to
-* NPVMAX PVi_ma keywords or NPSMAX PSi_ma keywords per WCS representation.
-* These may be changed via wcsnpv() and wcsnps() before wcsini() is called.
-*
-* PLEASE NOTE: every wcsprm struct should be initialized by wcsini(), possibly
-* repeatedly.  On the first invokation, and only the first invokation,
-* wcsprm::flag must be set to -1 to initialize memory management, regardless
-* of whether wcsini() will actually be used to allocate memory.
-*
-* Given:
-*   alloc     int       If true, allocate memory unconditionally for the
-*                       crpix, etc. arrays.
-*
-*                       If false, it is assumed that pointers to these arrays
-*                       have been set by the user except if they are null
-*                       pointers in which case memory will be allocated for
-*                       them regardless.  (In other words, setting alloc true
-*                       saves having to initalize these pointers to zero.)
-*
-*   naxis     int       The number of world coordinate axes.  This is used to
-*                       determine the length of the various wcsprm vectors and
-*                       matrices and therefore the amount of memory to
-*                       allocate for them.
-*
-* Given and returned:
-*   wcs       struct wcsprm*
-*                       Coordinate transformation parameters.
-*
-*                       Note that, in order to initialize memory management,
-*                       wcsprm::flag should be set to -1 when wcs is
-*                       initialized for the first time (memory leaks may
-*                       result if it had already been initialized).
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         1: Null wcsprm pointer passed.
-*                         2: Memory allocation failed.
-*
-*                       For returns > 1, a detailed error message is set in
-*                       wcsprm::err if enabled, see wcserr_enable().
-*
-*
-* wcsnpv() - Memory allocation for PVi_ma
-* ---------------------------------------
-* wcsnpv() changes the value of NPVMAX (default 64).  This global variable
-* controls the number of PVi_ma keywords that wcsini() should allocate space
-* for.
-*
-* PLEASE NOTE: This function is not thread-safe.
-*
-* Given:
-*   n         int       Value of NPVMAX; ignored if < 0.
-*
-* Function return value:
-*             int       Current value of NPVMAX.
-*
-*
-* wcsnps() - Memory allocation for PSi_ma
-* ---------------------------------------
-* wcsnps() changes the values of NPSMAX (default 8).  This global variable
-* controls the number of PSi_ma keywords that wcsini() should allocate space
-* for.
-*
-* PLEASE NOTE: This function is not thread-safe.
-*
-* Given:
-*   n         int       Value of NPSMAX; ignored if < 0.
-*
-* Function return value:
-*             int       Current value of NPSMAX.
-*
-*
-* wcssub() - Subimage extraction routine for the wcsprm struct
-* ------------------------------------------------------------
-* wcssub() extracts the coordinate description for a subimage from a wcsprm
-* struct.  It does a deep copy, using wcsini() to allocate memory for its
-* arrays if required.  Only the "information to be provided" part of the
-* struct is extracted; a call to wcsset() is required to set up the remainder.
-*
-* The world coordinate system of the subimage must be separable in the sense
-* that the world coordinates at any point in the subimage must depend only on
-* the pixel coordinates of the axes extracted.  In practice, this means that
-* the PCi_ja matrix of the original image must not contain non-zero
-* off-diagonal terms that associate any of the subimage axes with any of the
-* non-subimage axes.
-*
-* Note that while the required elements of the tabprm array are extracted, the
-* wtbarr array is not.  (Thus it is not appropriate to call wcssub() after
-* wcstab() but before filling the tabprm structs - refer to wcshdr.h.)
-*
-* wcssub() can also add axes to a wcsprm struct.  The new axes will be created
-* using the defaults set by wcsini() which produce a simple, unnamed, linear
-* axis with world coordinate equal to the pixel coordinate.  These default
-* values can be changed in before invoking wcsset().
-*
-* Given:
-*   alloc     int       If true, allocate memory for the crpix, etc. arrays in
-*                       the destination.  Otherwise, it is assumed that
-*                       pointers to these arrays have been set by the user
-*                       except if they are null pointers in which case memory
-*                       will be allocated for them regardless.
-*
-*   wcssrc    const struct wcsprm*
-*                       Struct to extract from.
-*
-* Given and returned:
-*   nsub      int*
-*   axes      int[]     Vector of length *nsub containing the image axis
-*                       numbers (1-relative) to extract.  Order is
-*                       significant; axes[0] is the axis number of the input
-*                       image that corresponds to the first axis in the
-*                       subimage, etc.
-*
-*                       Use an axis number of 0 to create a new axis using
-*                       the defaults set by wcsini().
-*
-*                       nsub (the pointer) may be set to zero, and so also may
-*                       nsub, to indicate the number of axes in the input
-*                       image; the number of axes will be returned if
-*                       nsub != 0x0.  axes itself (the pointer) may be set to
-*                       zero to indicate the first *nsub axes in their
-*                       original order.
-*
-*                       Set both nsub and axes to zero to do a deep copy of
-*                       one wcsprm struct to another.
-*
-*                       Subimage extraction by coordinate axis type may be
-*                       done by setting the elements of axes[] to the
-*                       following special preprocessor macro values:
-*
-*                         WCSSUB_LONGITUDE: Celestial longitude.
-*                         WCSSUB_LATITUDE:  Celestial latitude.
-*                         WCSSUB_CUBEFACE:  Quadcube CUBEFACE axis.
-*                         WCSSUB_SPECTRAL:  Spectral axis.
-*                         WCSSUB_STOKES:    Stokes axis.
-*
-*                       Refer to the notes (below) for further usage examples.
-*
-*                       On return, *nsub will contain the number of axes in
-*                       the subimage; this may be zero if there were no axes
-*                       of the required type(s) (in which case no memory will
-*                       be allocated).  axes[] will contain the axis numbers
-*                       that were extracted, or 0 for newly created axes.  The
-*                       vector length must be sufficient to contain all axis
-*                       numbers.  No checks are performed to verify that the
-*                       coordinate axes are consistent, this is done by
-*                       wcsset().
-*
-*   wcsdst    struct wcsprm*
-*                       Struct describing the subimage.  wcsprm::flag should
-*                       be set to -1 if wcsdst was not previously initialized
-*                       (memory leaks may result if it was previously
-*                       initialized).
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         1: Null wcsprm pointer passed.
-*                         2: Memory allocation failed.
-*                        12: Invalid subimage specification.
-*                        13: Non-separable subimage coordinate system.
-*
-*                       For returns > 1, a detailed error message is set in
-*                       wcsprm::err if enabled, see wcserr_enable().
-*
-* Notes:
-*   Combinations of subimage axes of particular types may be extracted in the
-*   same order as they occur in the input image by combining preprocessor
-*   codes, for example
-*
-=     *nsub = 1;
-=     axes[0] = WCSSUB_LONGITUDE | WCSSUB_LATITUDE | WCSSUB_SPECTRAL;
-*
-*   would extract the longitude, latitude, and spectral axes in the same order
-*   as the input image.  If one of each were present, *nsub = 3 would be
-*   returned.
-*
-*   For convenience, WCSSUB_CELESTIAL is defined as the combination
-*   WCSSUB_LONGITUDE | WCSSUB_LATITUDE | WCSSUB_CUBEFACE.
-*
-*   The codes may also be negated to extract all but the types specified, for
-*   example
-*
-=     *nsub = 4;
-=     axes[0] = WCSSUB_LONGITUDE;
-=     axes[1] = WCSSUB_LATITUDE;
-=     axes[2] = WCSSUB_CUBEFACE;
-=     axes[3] = -(WCSSUB_SPECTRAL | WCSSUB_STOKES);
-*
-*   The last of these specifies all axis types other than spectral or Stokes.
-*   Extraction is done in the order specified by axes[] a longitude axis (if
-*   present) would be extracted first (via axes[0]) and not subsequently (via
-*   axes[3]).  Likewise for the latitude and cubeface axes in this example.
-*
-*   From the foregoing, it is apparent that the value of *nsub returned may be
-*   less than or greater than that given.  However, it will never exceed the
-*   number of axes in the input image (plus the number of newly-created axes
-*   if any were specified on input).
-*
-*
-* wcscopy() macro - Copy routine for the wcsprm struct
-* ----------------------------------------------------
-* wcscopy() does a deep copy of one wcsprm struct to another.  As of
-* WCSLIB 3.6, it is implemented as a preprocessor macro that invokes
-* wcssub() with the nsub and axes pointers both set to zero.
-*
-*
-* wcsfree() - Destructor for the wcsprm struct
-* --------------------------------------------
-* wcsfree() frees memory allocated for the wcsprm arrays by wcsini() and/or
-* wcsset().  wcsini() records the memory it allocates and wcsfree() will only
-* attempt to free this.
-*
-* PLEASE NOTE: wcsfree() must not be invoked on a wcsprm struct that was not
-* initialized by wcsini().
-*
-* Returned:
-*   wcs       struct wcsprm*
-*                       Coordinate transformation parameters.
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         1: Null wcsprm pointer passed.
-*
-*
-* wcsprt() - Print routine for the wcsprm struct
-* ----------------------------------------------
-* wcsprt() prints the contents of a wcsprm struct using wcsprintf().  Mainly
-* intended for diagnostic purposes.
-*
-* Given:
-*   wcs       const struct wcsprm*
-*                       Coordinate transformation parameters.
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         1: Null wcsprm pointer passed.
-*
-*
-* wcsperr() - Print error messages from a wcsprm struct
-* -----------------------------------------------------
-* wcsperr() prints the error message(s), if any, stored in a wcsprm struct,
-* and the linprm, celprm, prjprm, spcprm, and tabprm structs that it contains.
-* If there are no errors then nothing is printed.  It uses wcserr_prt(), q.v.
-*
-* Given:
-*   wcs       const struct wcsprm*
-*                       Coordinate transformation parameters.
-*
-*   prefix    const char *
-*                       If non-NULL, each output line will be prefixed with
-*                       this string.
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         1: Null wcsprm pointer passed.
-*
-*
-* wcsset() - Setup routine for the wcsprm struct
-* ----------------------------------------------
-* wcsset() sets up a wcsprm struct according to information supplied within
-* it (refer to the description of the wcsprm struct).
-*
-* wcsset() recognizes the NCP projection and converts it to the equivalent SIN
-* projection and likewise translates GLS into SFL.  It also translates the
-* AIPS spectral types ('FREQ-LSR', 'FELO-HEL', etc.), possibly changing the
-* input header keywords wcsprm::ctype and/or wcsprm::specsys if necessary.
-*
-* Note that this routine need not be called directly; it will be invoked by
-* wcsp2s() and wcss2p() if the wcsprm::flag is anything other than a
-* predefined magic value.
-*
-* Given and returned:
-*   wcs       struct wcsprm*
-*                       Coordinate transformation parameters.
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         1: Null wcsprm pointer passed.
-*                         2: Memory allocation failed.
-*                         3: Linear transformation matrix is singular.
-*                         4: Inconsistent or unrecognized coordinate axis
-*                            types.
-*                         5: Invalid parameter value.
-*                         6: Invalid coordinate transformation parameters.
-*                         7: Ill-conditioned coordinate transformation
-*                            parameters.
-*
-*                       For returns > 1, a detailed error message is set in
-*                       wcsprm::err if enabled, see wcserr_enable().
-*
-*
-* wcsp2s() - Pixel-to-world transformation
-* ----------------------------------------
-* wcsp2s() transforms pixel coordinates to world coordinates.
-*
-* Given and returned:
-*   wcs       struct wcsprm*
-*                       Coordinate transformation parameters.
-*
-* Given:
-*   ncoord,
-*   nelem     int       The number of coordinates, each of vector length
-*                       nelem but containing wcs.naxis coordinate elements.
-*                       Thus nelem must equal or exceed the value of the
-*                       NAXIS keyword unless ncoord == 1, in which case nelem
-*                       is not used.
-*
-*   pixcrd    const double[ncoord][nelem]
-*                       Array of pixel coordinates.
-*
-* Returned:
-*   imgcrd    double[ncoord][nelem]
-*                       Array of intermediate world coordinates.  For
-*                       celestial axes, imgcrd[][wcs.lng] and
-*                       imgcrd[][wcs.lat] are the projected x-, and
-*                       y-coordinates in pseudo "degrees".  For spectral
-*                       axes, imgcrd[][wcs.spec] is the intermediate spectral
-*                       coordinate, in SI units.
-*
-*   phi,theta double[ncoord]
-*                       Longitude and latitude in the native coordinate system
-*                       of the projection [deg].
-*
-*   world     double[ncoord][nelem]
-*                       Array of world coordinates.  For celestial axes,
-*                       world[][wcs.lng] and world[][wcs.lat] are the
-*                       celestial longitude and latitude [deg].  For
-*                       spectral axes, imgcrd[][wcs.spec] is the intermediate
-*                       spectral coordinate, in SI units.
-*
-*   stat      int[ncoord]
-*                       Status return value for each coordinate:
-*                         0: Success.
-*                         1+: A bit mask indicating invalid pixel coordinate
-*                            element(s).
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         1: Null wcsprm pointer passed.
-*                         2: Memory allocation failed.
-*                         3: Linear transformation matrix is singular.
-*                         4: Inconsistent or unrecognized coordinate axis
-*                            types.
-*                         5: Invalid parameter value.
-*                         6: Invalid coordinate transformation parameters.
-*                         7: Ill-conditioned coordinate transformation
-*                            parameters.
-*                         8: One or more of the pixel coordinates were
-*                            invalid, as indicated by the stat vector.
-*
-*                       For returns > 1, a detailed error message is set in
-*                       wcsprm::err if enabled, see wcserr_enable().
-*
-*
-* wcss2p() - World-to-pixel transformation
-* ----------------------------------------
-* wcss2p() transforms world coordinates to pixel coordinates.
-*
-* Given and returned:
-*   wcs       struct wcsprm*
-*                       Coordinate transformation parameters.
-*
-* Given:
-*   ncoord,
-*   nelem     int       The number of coordinates, each of vector length nelem
-*                       but containing wcs.naxis coordinate elements.  Thus
-*                       nelem must equal or exceed the value of the NAXIS
-*                       keyword unless ncoord == 1, in which case nelem is not
-*                       used.
-*
-*   world     const double[ncoord][nelem]
-*                       Array of world coordinates.  For celestial axes,
-*                       world[][wcs.lng] and world[][wcs.lat] are the
-*                       celestial longitude and latitude [deg]. For spectral
-*                       axes, world[][wcs.spec] is the spectral coordinate, in
-*                       SI units.
-*
-* Returned:
-*   phi,theta double[ncoord]
-*                       Longitude and latitude in the native coordinate
-*                       system of the projection [deg].
-*
-*   imgcrd    double[ncoord][nelem]
-*                       Array of intermediate world coordinates.  For
-*                       celestial axes, imgcrd[][wcs.lng] and
-*                       imgcrd[][wcs.lat] are the projected x-, and
-*                       y-coordinates in pseudo "degrees".  For quadcube
-*                       projections with a CUBEFACE axis the face number is
-*                       also returned in imgcrd[][wcs.cubeface].  For
-*                       spectral axes, imgcrd[][wcs.spec] is the intermediate
-*                       spectral coordinate, in SI units.
-*
-*   pixcrd    double[ncoord][nelem]
-*                       Array of pixel coordinates.
-*
-*   stat      int[ncoord]
-*                       Status return value for each coordinate:
-*                         0: Success.
-*                         1+: A bit mask indicating invalid world coordinate
-*                            element(s).
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         1: Null wcsprm pointer passed.
-*                         2: Memory allocation failed.
-*                         3: Linear transformation matrix is singular.
-*                         4: Inconsistent or unrecognized coordinate axis
-*                            types.
-*                         5: Invalid parameter value.
-*                         6: Invalid coordinate transformation parameters.
-*                         7: Ill-conditioned coordinate transformation
-*                            parameters.
-*                         9: One or more of the world coordinates were
-*                            invalid, as indicated by the stat vector.
-*
-*                       For returns > 1, a detailed error message is set in
-*                       wcsprm::err if enabled, see wcserr_enable().
-*
-*
-* wcsmix() - Hybrid coordinate transformation
-* -------------------------------------------
-* wcsmix(), given either the celestial longitude or latitude plus an element
-* of the pixel coordinate, solves for the remaining elements by iterating on
-* the unknown celestial coordinate element using wcss2p().  Refer also to the
-* notes below.
-*
-* Given and returned:
-*   wcs       struct wcsprm*
-*                       Indices for the celestial coordinates obtained
-*                       by parsing the wcsprm::ctype[].
-*
-* Given:
-*   mixpix    int       Which element of the pixel coordinate is given.
-*
-*   mixcel    int       Which element of the celestial coordinate is given:
-*                         1: Celestial longitude is given in
-*                            world[wcs.lng], latitude returned in
-*                            world[wcs.lat].
-*                         2: Celestial latitude is given in
-*                            world[wcs.lat], longitude returned in
-*                            world[wcs.lng].
-*
-*   vspan     const double[2]
-*                       Solution interval for the celestial coordinate [deg].
-*                       The ordering of the two limits is irrelevant.
-*                       Longitude ranges may be specified with any convenient
-*                       normalization, for example [-120,+120] is the same as
-*                       [240,480], except that the solution will be returned
-*                       with the same normalization, i.e. lie within the
-*                       interval specified.
-*
-*   vstep     const double
-*                       Step size for solution search [deg].  If zero, a
-*                       sensible, although perhaps non-optimal default will be
-*                       used.
-*
-*   viter     int       If a solution is not found then the step size will be
-*                       halved and the search recommenced.  viter controls how
-*                       many times the step size is halved.  The allowed range
-*                       is 5 - 10.
-*
-* Given and returned:
-*   world     double[naxis]
-*                       World coordinate elements.  world[wcs.lng] and
-*                       world[wcs.lat] are the celestial longitude and
-*                       latitude [deg].  Which is given and which returned
-*                       depends on the value of mixcel.  All other elements
-*                       are given.
-*
-* Returned:
-*   phi,theta double[naxis]
-*                       Longitude and latitude in the native coordinate
-*                       system of the projection [deg].
-*
-*   imgcrd    double[naxis]
-*                       Image coordinate elements.  imgcrd[wcs.lng] and
-*                       imgcrd[wcs.lat] are the projected x-, and
-*                       y-coordinates in pseudo "degrees".
-*
-* Given and returned:
-*   pixcrd    double[naxis]
-*                       Pixel coordinate.  The element indicated by mixpix is
-*                       given and the remaining elements are returned.
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         1: Null wcsprm pointer passed.
-*                         2: Memory allocation failed.
-*                         3: Linear transformation matrix is singular.
-*                         4: Inconsistent or unrecognized coordinate axis
-*                            types.
-*                         5: Invalid parameter value.
-*                         6: Invalid coordinate transformation parameters.
-*                         7: Ill-conditioned coordinate transformation
-*                            parameters.
-*                        10: Invalid world coordinate.
-*                        11: No solution found in the specified interval.
-*
-*                       For returns > 1, a detailed error message is set in
-*                       wcsprm::err if enabled, see wcserr_enable().
-*
-* Notes:
-*   Initially the specified solution interval is checked to see if it's a
-*   "crossing" interval.  If it isn't, a search is made for a crossing
-*   solution by iterating on the unknown celestial coordinate starting at the
-*   upper limit of the solution interval and decrementing by the specified
-*   step size.  A crossing is indicated if the trial value of the pixel
-*   coordinate steps through the value specified.  If a crossing interval is
-*   found then the solution is determined by a modified form of "regula falsi"
-*   division of the crossing interval.  If no crossing interval was found
-*   within the specified solution interval then a search is made for a
-*   "non-crossing" solution as may arise from a point of tangency.  The
-*   process is complicated by having to make allowance for the discontinuities
-*   that occur in all map projections.
-*
-*   Once one solution has been determined others may be found by subsequent
-*   invokations of wcsmix() with suitably restricted solution intervals.
-*
-*   Note the circumstance that arises when the solution point lies at a native
-*   pole of a projection in which the pole is represented as a finite curve,
-*   for example the zenithals and conics.  In such cases two or more valid
-*   solutions may exist but wcsmix() only ever returns one.
-*
-*   Because of its generality wcsmix() is very compute-intensive.  For
-*   compute-limited applications more efficient special-case solvers could be
-*   written for simple projections, for example non-oblique cylindrical
-*   projections.
-*
-*
-* wcssptr() - Spectral axis translation
-* -------------------------------------
-* wcssptr() translates the spectral axis in a wcsprm struct.  For example, a
-* 'FREQ' axis may be translated into 'ZOPT-F2W' and vice versa.
-*
-* Given and returned:
-*   wcs       struct wcsprm*
-*                       Coordinate transformation parameters.
-*
-*   i         int*      Index of the spectral axis (0-relative).  If given < 0
-*                       it will be set to the first spectral axis identified
-*                       from the ctype[] keyvalues in the wcsprm struct.
-*
-*   ctype     char[9]   Desired spectral CTYPEia.  Wildcarding may be used as
-*                       for the ctypeS2 argument to spctrn() as described in
-*                       the prologue of spc.h, i.e. if the final three
-*                       characters are specified as "???", or if just the
-*                       eighth character is specified as '?', the correct
-*                       algorithm code will be substituted and returned.
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         1: Null wcsprm pointer passed.
-*                         2: Memory allocation failed.
-*                         3: Linear transformation matrix is singular.
-*                         4: Inconsistent or unrecognized coordinate axis
-*                            types.
-*                         5: Invalid parameter value.
-*                         6: Invalid coordinate transformation parameters.
-*                         7: Ill-conditioned coordinate transformation
-*                            parameters.
-*                        12: Invalid subimage specification (no spectral
-*                            axis).
-*
-*                       For returns > 1, a detailed error message is set in
-*                       wcsprm::err if enabled, see wcserr_enable().
-*
-*
-* wcsprm struct - Coordinate transformation parameters
-* ----------------------------------------------------
-* The wcsprm struct contains information required to transform world
-* coordinates.  It consists of certain members that must be set by the user
-* ("given") and others that are set by the WCSLIB routines ("returned").
-* Some of the former are not actually required for transforming coordinates.
-* These are described as "auxiliary"; the struct simply provides a place to
-* store them, though they may be used by wcshdo() in constructing a FITS
-* header from a wcsprm struct.  Some of the returned values are supplied for
-* informational purposes and others are for internal use only as indicated.
-*
-* In practice, it is expected that a WCS parser would scan the FITS header to
-* determine the number of coordinate axes.  It would then use wcsini() to
-* allocate memory for arrays in the wcsprm struct and set default values.
-* Then as it reread the header and identified each WCS keyrecord it would load
-* the value into the relevant wcsprm array element.  This is essentially what
-* wcspih() does - refer to the prologue of wcshdr.h.  As the final step,
-* wcsset() is invoked, either directly or indirectly, to set the derived
-* members of the wcsprm struct.  wcsset() strips off trailing blanks in all
-* string members and null-fills the character array.
-*
-*   int flag
-*     (Given and returned) This flag must be set to zero whenever any of the
-*     following wcsprm struct members are set or changed:
-*
-*       - wcsprm::naxis (q.v., not normally set by the user),
-*       - wcsprm::crpix,
-*       - wcsprm::pc,
-*       - wcsprm::cdelt,
-*       - wcsprm::crval,
-*       - wcsprm::cunit,
-*       - wcsprm::ctype,
-*       - wcsprm::lonpole,
-*       - wcsprm::latpole,
-*       - wcsprm::restfrq,
-*       - wcsprm::restwav,
-*       - wcsprm::npv,
-*       - wcsprm::pv,
-*       - wcsprm::nps,
-*       - wcsprm::ps,
-*       - wcsprm::cd,
-*       - wcsprm::crota,
-*       - wcsprm::altlin.
-*
-*     This signals the initialization routine, wcsset(), to recompute the
-*     returned members of the celprm struct.  celset() will reset flag to
-*     indicate that this has been done.
-*
-*     PLEASE NOTE: flag should be set to -1 when wcsini() is called for the
-*     first time for a particular wcsprm struct in order to initialize memory
-*     management.  It must ONLY be used on the first initialization otherwise
-*     memory leaks may result.
-*
-*   int naxis
-*     (Given or returned) Number of pixel and world coordinate elements.
-*
-*     If wcsini() is used to initialize the linprm struct (as would normally
-*     be the case) then it will set naxis from the value passed to it as a
-*     function argument.  The user should not subsequently modify it.
-*
-*   double *crpix
-*     (Given) Address of the first element of an array of double containing
-*     the coordinate reference pixel, CRPIXja.
-*
-*   double *pc
-*     (Given) Address of the first element of the PCi_ja (pixel coordinate)
-*     transformation matrix.  The expected order is
-*
-=       struct wcsprm wcs;
-=       wcs.pc = {PC1_1, PC1_2, PC2_1, PC2_2};
-*
-*     This may be constructed conveniently from a 2-D array via
-*
-=       double m[2][2] = {{PC1_1, PC1_2},
-=                         {PC2_1, PC2_2}};
-*
-*     which is equivalent to
-*
-=       double m[2][2];
-=       m[0][0] = PC1_1;
-=       m[0][1] = PC1_2;
-=       m[1][0] = PC2_1;
-=       m[1][1] = PC2_2;
-*
-*     The storage order for this 2-D array is the same as for the 1-D array,
-*     whence
-*
-=       wcs.pc = *m;
-*
-*     would be legitimate.
-*
-*   double *cdelt
-*     (Given) Address of the first element of an array of double containing
-*     the coordinate increments, CDELTia.
-*
-*   double *crval
-*     (Given) Address of the first element of an array of double containing
-*     the coordinate reference values, CRVALia.
-*
-*   char (*cunit)[72]
-*     (Given) Address of the first element of an array of char[72] containing
-*     the CUNITia keyvalues which define the units of measurement of the
-*     CRVALia, CDELTia, and CDi_ja keywords.
-*
-*     As CUNITia is an optional header keyword, cunit[][72] may be left blank
-*     but otherwise is expected to contain a standard units specification as
-*     defined by WCS Paper I.  Utility function wcsutrn(), described in
-*     wcsunits.h, is available to translate commonly used non-standard units
-*     specifications but this must be done as a separate step before invoking
-*     wcsset().
-*
-*     For celestial axes, if cunit[][72] is not blank, wcsset() uses
-*     wcsunits() to parse it and scale cdelt[], crval[], and cd[][*] to
-*     degrees.  It then resets cunit[][72] to "deg".
-*
-*     For spectral axes, if cunit[][72] is not blank, wcsset() uses wcsunits()
-*     to parse it and scale cdelt[], crval[], and cd[][*] to SI units.  It
-*     then resets cunit[][72] accordingly.
-*
-*     wcsset() ignores cunit[][72] for other coordinate types; cunit[][72] may
-*     be used to label coordinate values.
-*
-*     These variables accomodate the longest allowed string-valued FITS
-*     keyword, being limited to 68 characters, plus the null-terminating
-*     character.
-*
-*   char (*ctype)[72]
-*     (Given) Address of the first element of an array of char[72] containing
-*     the coordinate axis types, CTYPEia.
-*
-*     The ctype[][72] keyword values must be in upper case and there must be
-*     zero or one pair of matched celestial axis types, and zero or one
-*     spectral axis.  The ctype[][72] strings should be padded with blanks on
-*     the right and null-terminated so that they are at least eight characters
-*     in length.
-*
-*     These variables accomodate the longest allowed string-valued FITS
-*     keyword, being limited to 68 characters, plus the null-terminating
-*     character.
-*
-*   double lonpole
-*     (Given and returned) The native longitude of the celestial pole, phi_p,
-*     given by LONPOLEa [deg] or by PVi_2a [deg] attached to the longitude
-*     axis which takes precedence if defined, and ...
-*   double latpole
-*     (Given and returned) ... the native latitude of the celestial pole,
-*     theta_p, given by LATPOLEa [deg] or by PVi_3a [deg] attached to the
-*     longitude axis which takes precedence if defined.
-*
-*     lonpole and latpole may be left to default to values set by wcsini()
-*     (see celprm::ref), but in any case they will be reset by wcsset() to
-*     the values actually used.  Note therefore that if the wcsprm struct is
-*     reused without resetting them, whether directly or via wcsini(), they
-*     will no longer have their default values.
-*
-*   double restfrq
-*     (Given) The rest frequency [Hz], and/or ...
-*   double restwav
-*     (Given) ... the rest wavelength in vacuuo [m], only one of which need be
-*     given, the other should be set to zero.
-*
-*   int npv
-*     (Given) The number of entries in the wcsprm::pv[] array.
-*
-*   int npvmax
-*     (Given or returned) The length of the wcsprm::pv[] array.
-*
-*     npvmax will be set by wcsini() if it allocates memory for wcsprm::pv[],
-*     otherwise it must be set by the user.  See also wcsnpv().
-*
-*   struct pvcard *pv
-*     (Given or returned) Address of the first element of an array of length
-*     npvmax of pvcard structs.  Set by wcsini() if it allocates memory for
-*     pv[], otherwise it must be set by the user.  See also wcsnpv().
-*
-*     As a FITS header parser encounters each PVi_ma keyword it should load it
-*     into a pvcard struct in the array and increment npv.  wcsset()
-*     interprets these as required.
-*
-*     Note that, if they were not given, wcsset() resets the entries for
-*     PVi_1a, PVi_2a, PVi_3a, and PVi_4a for longitude axis i to match
-*     phi_0 and theta_0 (the native longitude and latitude of the reference
-*     point), LONPOLEa and LATPOLEa respectively.
-*
-*   int nps
-*     (Given) The number of entries in the wcsprm::ps[] array.
-*
-*   int npsmax
-*     (Given or returned) The length of the wcsprm::ps[] array.
-*
-*     npsmax will be set by wcsini() if it allocates memory for wcsprm::ps[],
-*     otherwise it must be set by the user.  See also wcsnps().
-*
-*   struct pscard *ps
-*     (Given or returned) Address of the first element of an array of length
-*     npsmax of pscard structs.  Set by wcsini() if it allocates memory for
-*     ps[], otherwise it must be set by the user.  See also wcsnps().
-*
-*     As a FITS header parser encounters each PSi_ma keyword it should load it
-*     into a pscard struct in the array and increment nps.  wcsset()
-*     interprets these as required (currently no PSi_ma keyvalues are
-*     recognized).
-*
-*   double *cd
-*     (Given) For historical compatibility, the wcsprm struct supports two
-*     alternate specifications of the linear transformation matrix, those
-*     associated with the CDi_ja keywords, and ...
-*   double *crota
-*     (Given) ... those associated with the CROTAia keywords.  Although these
-*     may not formally co-exist with PCi_ja, the approach taken here is simply
-*     to ignore them if given in conjunction with PCi_ja.
-*
-*   int altlin
-*     (Given) altlin is a bit flag that denotes which of the PCi_ja, CDi_ja
-*     and CROTAia keywords are present in the header:
-*
-*     - Bit 0: PCi_ja is present.
-*
-*     - Bit 1: CDi_ja is present.
-*
-*       Matrix elements in the IRAF convention are
-*       equivalent to the product CDi_ja = CDELTia * PCi_ja, but the
-*       defaults differ from that of the PCi_ja matrix.  If one or more
-*       CDi_ja keywords are present then all unspecified CDi_ja default to
-*       zero.  If no CDi_ja (or CROTAia) keywords are present, then the
-*       header is assumed to be in PCi_ja form whether or not any PCi_ja
-*       keywords are present since this results in an interpretation of
-*       CDELTia consistent with the original FITS specification.
-*
-*       While CDi_ja may not formally co-exist with PCi_ja, it may co-exist
-*       with CDELTia and CROTAia which are to be ignored.
-*
-*     - Bit 2: CROTAia is present.
-*
-*       In the AIPS convention, CROTAia may only be
-*       associated with the latitude axis of a celestial axis pair.  It
-*       specifies a rotation in the image plane that is applied AFTER the
-*       CDELTia; any other CROTAia keywords are ignored.
-*
-*       CROTAia may not formally co-exist with PCi_ja.
-*
-*       CROTAia and CDELTia may formally co-exist with CDi_ja but if so are to
-*       be ignored.
-*
-*     CDi_ja and CROTAia keywords, if found, are to be stored in the
-*     wcsprm::cd and wcsprm::crota arrays which are dimensioned similarly to
-*     wcsprm::pc and wcsprm::cdelt.  FITS
-*     header parsers should use the following procedure:
-*
-*     - Whenever a PCi_ja  keyword is encountered: altlin |= 1;
-*
-*     - Whenever a CDi_ja  keyword is encountered: altlin |= 2;
-*
-*     - Whenever a CROTAia keyword is encountered: altlin |= 4;
-*
-*     If none of these bits are set the PCi_ja representation results, i.e.
-*     wcsprm::pc and wcsprm::cdelt will be used as given.
-*
-*     These alternate specifications of the linear transformation matrix are
-*     translated immediately to PCi_ja by wcsset() and are invisible to the
-*     lower-level WCSLIB routines.  In particular, wcsset() resets
-*     wcsprm::cdelt to unity if CDi_ja is present (and no PCi_ja).
-*
-*     If CROTAia are present but none is associated with the latitude axis
-*     (and no PCi_ja or CDi_ja), then wcsset() reverts to a unity PCi_ja
-*     matrix.
-*
-*   int velref
-*     (Given) AIPS velocity code VELREF, refer to spcaips().
-*
-*   char alt[4]
-*     (Given, auxiliary) Character code for alternate coordinate descriptions
-*     (i.e. the 'a' in keyword names such as CTYPEia).  This is blank for the
-*     primary coordinate description, or one of the 26 upper-case letters,
-*     A-Z.
-*
-*     An array of four characters is provided for alignment purposes, only the
-*     first is used.
-*
-*   int colnum
-*     (Given, auxiliary) Where the coordinate representation is associated
-*     with an image-array column in a FITS binary table, this variable may be
-*     used to record the relevant column number.
-*
-*     It should be set to zero for an image header or pixel list.
-*
-*   int *colax
-*     (Given, auxiliary) Address of the first element of an array of int
-*     recording the column numbers for each axis in a pixel list.
-*
-*     The array elements should be set to zero for an image header or image
-*     array in a binary table.
-*
-*   char (*cname)[72]
-*     (Given, auxiliary) The address of the first element of an array of
-*     char[72] containing the coordinate axis names, CNAMEia.
-*
-*     These variables accomodate the longest allowed string-valued FITS
-*     keyword, being limited to 68 characters, plus the null-terminating
-*     character.
-*
-*   double *crder
-*     (Given, auxiliary) Address of the first element of an array of double
-*     recording the random error in the coordinate value, CRDERia.
-*   double *csyer
-*     (Given, auxiliary) Address of the first element of an array of double
-*     recording the systematic error in the coordinate value, CSYERia.
-*
-*   char dateavg[72]
-*     (Given, auxiliary) The date of a representative mid-point of the
-*     observation in ISO format, yyyy-mm-ddThh:mm:ss.
-*   char dateobs[72]
-*     (Given, auxiliary) The date of the start of the observation unless
-*     otherwise explained in the comment field of the DATE-OBS keyword, in
-*     ISO format, yyyy-mm-ddThh:mm:ss.
-*
-*   double equinox
-*     (Given, auxiliary) The equinox associated with dynamical equatorial or
-*     ecliptic coordinate systems, EQUINOXa (or EPOCH in older headers).  Not
-*     applicable to ICRS equatorial or ecliptic coordinates.
-*
-*   double mjdavg
-*     (Given, auxiliary) Modified Julian Date (MJD = JD - 2400000.5), MJD-AVG,
-*     corresponding to DATE-AVG.
-*   double mjdobs
-*     (Given, auxiliary) Modified Julian Date (MJD = JD - 2400000.5), MJD-OBS,
-*     corresponding to DATE-OBS.
-*
-*   double obsgeo[3]
-*     (Given, auxiliary) Location of the observer in a standard terrestrial
-*     reference frame, OBSGEO-X, OBSGEO-Y, OBSGEO-Z [m].
-*
-*   char radesys[72]
-*     (Given, auxiliary) The equatorial or ecliptic coordinate system type,
-*     RADESYSa.
-*
-*   char specsys[72]
-*     (Given, auxiliary) Spectral reference frame (standard of rest),
-*     SPECSYSa, and ...
-*   char ssysobs[72]
-*     (Given, auxiliary) ... the actual frame in which there is no
-*     differential variation in the spectral coordinate across the
-*     field-of-view, SSYSOBSa.
-*   double velosys
-*     (Given, auxiliary) The relative radial velocity [m/s] between the
-*     observer and the selected standard of rest in the direction of the
-*     celestial reference coordinate, VELOSYSa.
-*
-*   double zsource
-*     (Given, auxiliary) The redshift, ZSOURCEa, of the source, and ...
-*   char ssyssrc[72]
-*     (Given, auxiliary) ... the spectral reference frame (standard of rest)
-*     in which this was measured, SSYSSRCa.
-*
-*   double velangl
-*     (Given, auxiliary) The angle [deg] that should be used to decompose an
-*     observed velocity into radial and transverse components.
-*
-*   char wcsname[72]
-*     (Given, auxiliary) The name given to the coordinate representation,
-*     WCSNAMEa.  This variable accomodates the longest allowed string-valued
-*     FITS keyword, being limited to 68 characters, plus the null-terminating
-*     character.
-*
-*   int ntab
-*     (Given) See wcsprm::tab.
-*
-*   int nwtb
-*     (Given) See wcsprm::wtb.
-*
-*   struct tabprm *tab
-*     (Given) Address of the first element of an array of ntab tabprm structs
-*     for which memory has been allocated.  These are used to store tabular
-*     transformation parameters.
-*
-*     Although technically wcsprm::ntab and tab are "given", they will
-*     normally be set by invoking wcstab(), whether directly or indirectly.
-*
-*     The tabprm structs contain some members that must be supplied and others
-*     that are derived.  The information to be supplied comes primarily from
-*     arrays stored in one or more FITS binary table extensions.  These
-*     arrays, referred to here as "wcstab arrays", are themselves located by
-*     parameters stored in the FITS image header.
-*
-*   struct wtbarr *wtb
-*     (Given) Address of the first element of an array of nwtb wtbarr structs
-*     for which memory has been allocated.  These are used in extracting
-*     wcstab arrays from a FITS binary table.
-*
-*     Although technically wcsprm::nwtb and wtb are "given", they will
-*     normally be set by invoking wcstab(), whether directly or indirectly.
-*
-*   char lngtyp[8]
-*     (Returned) Four-character WCS celestial longitude and ...
-*   char lattyp[8]
-*     (Returned) ... latitude axis types. e.g. "RA", "DEC", "GLON", "GLAT",
-*     etc. extracted from 'RA--', 'DEC-', 'GLON', 'GLAT', etc. in the first
-*     four characters of CTYPEia but with trailing dashes removed.  (Declared
-*     as char[8] for alignment reasons.)
-*
-*   int lng
-*     (Returned) Index for the longitude coordinate, and ...
-*   int lat
-*     (Returned) ... index for the latitude coordinate, and ...
-*   int spec
-*     (Returned) ... index for the spectral coordinate in the imgcrd[][] and
-*     world[][] arrays in the API of wcsp2s(), wcss2p() and wcsmix().
-*
-*     These may also serve as indices into the pixcrd[][] array provided that
-*     the PCi_ja matrix does not transpose axes.
-*
-*   int cubeface
-*     (Returned) Index into the pixcrd[][] array for the CUBEFACE axis.  This
-*     is used for quadcube projections where the cube faces are stored on a
-*     separate axis (see wcs.h).
-*
-*   int *types
-*     (Returned) Address of the first element of an array of int containing a
-*     four-digit type code for each axis.
-*
-*     - First digit (i.e. 1000s):
-*       - 0: Non-specific coordinate type.
-*       - 1: Stokes coordinate.
-*       - 2: Celestial coordinate (including CUBEFACE).
-*       - 3: Spectral coordinate.
-*
-*     - Second digit (i.e. 100s):
-*       - 0: Linear axis.
-*       - 1: Quantized axis (STOKES, CUBEFACE).
-*       - 2: Non-linear celestial axis.
-*       - 3: Non-linear spectral axis.
-*       - 4: Logarithmic axis.
-*       - 5: Tabular axis.
-*
-*     - Third digit (i.e. 10s):
-*       - 0: Group number, e.g. lookup table number, being an index into the
-*            tabprm array (see above).
-*
-*     - The fourth digit is used as a qualifier depending on the axis type.
-*
-*       - For celestial axes:
-*         - 0: Longitude coordinate.
-*         - 1: Latitude coordinate.
-*         - 2: CUBEFACE number.
-*
-*       - For lookup tables: the axis number in a multidimensional table.
-*
-*     CTYPEia in "4-3" form with unrecognized algorithm code will have its
-*     type set to -1 and generate an error.
-*
-*   void *padding
-*     (An unused variable inserted for alignment purposes only.)
-*
-*   struct linprm lin
-*     (Returned) Linear transformation parameters (usage is described in the
-*     prologue to lin.h).
-*
-*   struct celprm cel
-*     (Returned) Celestial transformation parameters (usage is described in
-*     the prologue to cel.h).
-*
-*   struct spcprm spc
-*     (Returned) Spectral transformation parameters (usage is described in the
-*     prologue to spc.h).
-*
-*   struct wcserr *err
-*     (Returned) If enabled, when an error status is returned this struct
-*     contains detailed information about the error, see wcserr_enable().
-*
-*   void *m_padding
-*     (For internal use only.)
-*   int m_flag
-*     (For internal use only.)
-*   int m_naxis
-*     (For internal use only.)
-*   double *m_crpix
-*     (For internal use only.)
-*   double *m_pc
-*     (For internal use only.)
-*   double *m_cdelt
-*     (For internal use only.)
-*   double *m_crval
-*     (For internal use only.)
-*   char (*m_cunit)[72]
-*     (For internal use only.)
-*   char (*m_ctype)[72]
-*     (For internal use only.)
-*   struct pvcard *m_pv
-*     (For internal use only.)
-*   struct pscard *m_ps
-*     (For internal use only.)
-*   double *m_cd
-*     (For internal use only.)
-*   double *m_crota
-*     (For internal use only.)
-*   int *m_colax
-*     (For internal use only.)
-*   char (*m_cname)[72]
-*     (For internal use only.)
-*   double *m_crder
-*     (For internal use only.)
-*   double *m_csyer
-*     (For internal use only.)
-*   struct tabprm *m_tab
-*     (For internal use only.)
-*   struct wtbarr *m_wtb
-*     (For internal use only.)
-*
-*
-* pscard struct - Store for PSi_ma keyrecords
-* -------------------------------------------
-* The pscard struct is used to pass the parsed contents of PSi_ma keyrecords
-* to wcsset() via the wcsprm struct.
-*
-* All members of this struct are to be set by the user.
-*
-*   int i
-*     (Given) Axis number (1-relative), as in the FITS PSi_ma keyword.
-*
-*   int m
-*     (Given) Parameter number (non-negative), as in the FITS PSi_ma keyword.
-*
-*   char value[72]
-*     (Given) Parameter value.
-*
-*
-* pvcard struct - Store for PVi_ma keyrecords
-* -------------------------------------------
-* The pvcard struct is used to pass the parsed contents of PVi_ma keyrecords
-* to wcsset() via the wcsprm struct.
-*
-* All members of this struct are to be set by the user.
-*
-*   int i
-*     (Given) Axis number (1-relative), as in the FITS PVi_ma keyword.  If
-*     i == 0, wcsset() will replace it with the latitude axis number.
-*
-*   int m
-*     (Given) Parameter number (non-negative), as in the FITS PVi_ma keyword.
-*
-*   double value
-*     (Given) Parameter value.
-*
-*
-* wtbarr struct - Extraction of coordinate lookup tables from BINTABLE
-* --------------------------------------------------------------------
-* Function wcstab(), which is invoked automatically by wcspih(), sets up an
-* array of wtbarr structs to assist in extracting coordinate lookup tables
-* from a binary table extension (BINTABLE) and copying them into the tabprm
-* structs stored in wcsprm.  Refer to the usage notes for wcspih() and
-* wcstab() in wcshdr.h, and also the prologue to tab.h.
-*
-* For C++ usage, because of a name space conflict with the wtbarr typedef
-* defined in CFITSIO header fitsio.h, the wtbarr struct is renamed to wtbarr_s
-* by preprocessor macro substitution with scope limited to wcs.h itself.
-*
-*   int i
-*     (Given) Image axis number.
-*
-*   int m
-*     (Given) wcstab array axis number for index vectors.
-*
-*   int kind
-*     (Given) Character identifying the wcstab array type:
-*       - c: coordinate array,
-*       - i: index vector.
-*
-*   char extnam[72]
-*     (Given) EXTNAME identifying the binary table extension.
-*
-*   int extver
-*     (Given) EXTVER identifying the binary table extension.
-*
-*   int extlev
-*     (Given) EXTLEV identifying the binary table extension.
-*
-*   char ttype[72]
-*     (Given) TTYPEn identifying the column of the binary table that contains
-*     the wcstab array.
-*
-*   long row
-*     (Given) Table row number.
-*
-*   int ndim
-*     (Given) Expected dimensionality of the wcstab array.
-*
-*   int *dimlen
-*     (Given) Address of the first element of an array of int of length ndim
-*     into which the wcstab array axis lengths are to be written.
-*
-*   double **arrayp
-*     (Given) Pointer to an array of double which is to be allocated by the
-*     user and into which the wcstab array is to be written.
-*
-*
-* Global variable: const char *wcs_errmsg[] - Status return messages
-* ------------------------------------------------------------------
-* Error messages to match the status value returned from each function.
-*
-*===========================================================================*/
-
-#ifndef WCSLIB_WCS
-#define WCSLIB_WCS
-
-#include "lin.h"
-#include "cel.h"
-#include "spc.h"
-#include "tab.h"
-#include "wcserr.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define WCSSUB_LONGITUDE 0x1001
-#define WCSSUB_LATITUDE  0x1002
-#define WCSSUB_CUBEFACE  0x1004
-#define WCSSUB_CELESTIAL 0x1007
-#define WCSSUB_SPECTRAL  0x1008
-#define WCSSUB_STOKES    0x1010
-
-
-extern const char *wcs_errmsg[];
-
-enum wcs_errmsg_enum {
-  WCSERR_SUCCESS         =  0,	/* Success. */
-  WCSERR_NULL_POINTER    =  1,	/* Null wcsprm pointer passed. */
-  WCSERR_MEMORY          =  2,	/* Memory allocation failed. */
-  WCSERR_SINGULAR_MTX    =  3,	/* Linear transformation matrix is
-				   singular. */
-  WCSERR_BAD_CTYPE       =  4,	/* Inconsistent or unrecognized coordinate
-				   axis types. */
-  WCSERR_BAD_PARAM       =  5,	/* Invalid parameter value. */
-  WCSERR_BAD_COORD_TRANS =  6,	/* Invalid coordinate transformation
-				   parameters. */
-  WCSERR_ILL_COORD_TRANS =  7,	/* Ill-conditioned coordinate transformation
-				   parameters. */
-  WCSERR_BAD_PIX         =  8,	/* One or more of the pixel coordinates were
-				   invalid. */
-  WCSERR_BAD_WORLD       =  9,	/* One or more of the world coordinates were
-				   invalid. */
-  WCSERR_BAD_WORLD_COORD = 10,	/* Invalid world coordinate. */
-  WCSERR_NO_SOLUTION     = 11,	/* No solution found in the specified
-				   interval. */
-  WCSERR_BAD_SUBIMAGE    = 12,	/* Invalid subimage specification. */
-  WCSERR_NON_SEPARABLE   = 13	/* Non-separable subimage coordinate
-				   system. */
-};
-
-
-/* Struct used for storing PVi_ma keywords. */
-struct pvcard {
-  int i;			/* Axis number, as in PVi_ma (1-relative).  */
-  int m;			/* Parameter number, ditto  (0-relative).   */
-  double value;			/* Parameter value.                         */
-};
-
-/* Struct used for storing PSi_ma keywords. */
-struct pscard {
-  int i;			/* Axis number, as in PSi_ma (1-relative).  */
-  int m;			/* Parameter number, ditto  (0-relative).   */
-  char value[72];		/* Parameter value.                         */
-};
-
-				/* For extracting wcstab arrays.  Matches   */
-				/* the wtbarr typedef defined in CFITSIO    */
-				/* header fitsio.h.                         */
-#ifdef __cplusplus
-#define wtbarr wtbarr_s		/* See prologue above.                      */
-#endif
-struct wtbarr {
-  int  i;			/* Image axis number.                       */
-  int  m;			/* Array axis number for index vectors.     */
-  int  kind;			/* wcstab array type.                       */
-  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 wcstab 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 wcstab array.     */
-};
-
-
-struct wcsprm {
-  /* Initialization flag (see the prologue above).                          */
-  /*------------------------------------------------------------------------*/
-  int    flag;			/* Set to zero to force initialization.     */
-
-  /* FITS header keyvalues to be provided (see the prologue above).         */
-  /*------------------------------------------------------------------------*/
-  int    naxis;			/* Number of axes (pixel and coordinate).   */
-  double *crpix;		/* CRPIXja keyvalues for each pixel axis.   */
-  double *pc;			/* PCi_ja  linear transformation matrix.    */
-  double *cdelt;		/* CDELTia keyvalues for each coord axis.   */
-  double *crval;		/* CRVALia keyvalues for each coord axis.   */
-
-  char   (*cunit)[72];		/* CUNITia keyvalues for each coord axis.   */
-  char   (*ctype)[72];		/* CTYPEia keyvalues for each coord axis.   */
-
-  double lonpole;		/* LONPOLEa keyvalue.                       */
-  double latpole;		/* LATPOLEa keyvalue.                       */
-
-  double restfrq;		/* RESTFRQa keyvalue.                       */
-  double restwav;		/* RESTWAVa keyvalue.                       */
-
-  int    npv;			/* Number of PVi_ma keywords, and the       */
-  int    npvmax;		/* number for which space was allocated.    */
-  struct pvcard *pv;		/* PVi_ma keywords for each i and m.        */
-
-  int    nps;			/* Number of PSi_ma keywords, and the       */
-  int    npsmax;		/* number for which space was allocated.    */
-  struct pscard *ps;		/* PSi_ma keywords for each i and m.        */
-
-  /* Alternative header keyvalues (see the prologue above).                 */
-  /*------------------------------------------------------------------------*/
-  double *cd;			/* CDi_ja linear transformation matrix.     */
-  double *crota;		/* CROTAia keyvalues for each coord axis.   */
-  int    altlin;		/* Alternative representations              */
-				/*   Bit 0: PCi_ja  is present,             */
-				/*   Bit 1: CDi_ja  is present,             */
-				/*   Bit 2: CROTAia is present.             */
-  int    velref;		/* AIPS velocity code, VELREF.              */
-
-  /* Auxiliary coordinate system information, not used by WCSLIB.           */
-  char   alt[4];
-  int    colnum;
-  int    *colax;
-
-  char   (*cname)[72];
-  double *crder;
-  double *csyer;
-  char   dateavg[72];
-  char   dateobs[72];
-  double equinox;
-  double mjdavg;
-  double mjdobs;
-  double obsgeo[3];
-  char   radesys[72];
-  char   specsys[72];
-  char   ssysobs[72];
-  double velosys;
-  double zsource;
-  char   ssyssrc[72];
-  double velangl;
-  char   wcsname[72];
-
-  /* Coordinate lookup tables (see the prologue above).                     */
-  /*------------------------------------------------------------------------*/
-  int    ntab;			/* Number of separate tables.               */
-  int    nwtb;			/* Number of wtbarr structs.                */
-  struct tabprm *tab;		/* Tabular transformation parameters.       */
-  struct wtbarr *wtb;		/* Array of wtbarr structs.                 */
-
-  /* Information derived from the FITS header keyvalues by wcsset().        */
-  /*------------------------------------------------------------------------*/
-  char   lngtyp[8], lattyp[8];	/* Celestial axis types, e.g. RA, DEC.      */
-  int    lng, lat, spec;	/* Longitude, latitude and spectral axis    */
-				/* indices (0-relative).                    */
-  int    cubeface;		/* True if there is a CUBEFACE axis.        */
-  int    *types;		/* Coordinate type codes for each axis.     */
-  void   *padding;		/* (Dummy inserted for alignment purposes.) */
-
-  struct linprm lin;		/* Linear    transformation parameters.     */
-  struct celprm cel;		/* Celestial transformation parameters.     */
-  struct spcprm spc;		/* Spectral  transformation parameters.     */
-
-  /* Error handling                                                         */
-  /*------------------------------------------------------------------------*/
-  struct wcserr *err;
-
-  /* Private - the remainder are for memory management.                     */
-  /*------------------------------------------------------------------------*/
-  void   *m_padding;
-  int    m_flag, m_naxis;
-  double *m_crpix, *m_pc, *m_cdelt, *m_crval;
-  char  (*m_cunit)[72], (*m_ctype)[72];
-  struct pvcard *m_pv;
-  struct pscard *m_ps;
-  double *m_cd, *m_crota;
-  int    *m_colax;
-  char  (*m_cname)[72];
-  double *m_crder, *m_csyer;
-  struct tabprm *m_tab;
-  struct wtbarr *m_wtb;
-};
-
-/* Size of the wcsprm struct in int units, used by the Fortran wrappers. */
-#define WCSLEN (sizeof(struct wcsprm)/sizeof(int))
-
-
-int wcsnpv(int n);
-
-int wcsnps(int n);
-
-int wcsini(int alloc, int naxis, struct wcsprm *wcs);
-
-int wcssub(int alloc, const struct wcsprm *wcssrc, int *nsub, int axes[],
-           struct wcsprm *wcsdst);
-
-int wcsfree(struct wcsprm *wcs);
-
-int wcsprt(const struct wcsprm *wcs);
-
-int wcsperr(const struct wcsprm *wcs, const char *prefix);
-
-int wcsset(struct wcsprm *wcs);
-
-int wcsp2s(struct wcsprm *wcs, int ncoord, int nelem, const double pixcrd[],
-           double imgcrd[], double phi[], double theta[], double world[],
-           int stat[]);
-
-int wcss2p(struct wcsprm *wcs, int ncoord, int nelem, const double world[],
-           double phi[], double theta[], double imgcrd[], double pixcrd[],
-           int stat[]);
-
-int wcsmix(struct wcsprm *wcs, int mixpix, int mixcel, const double vspan[],
-           double vstep, int viter, double world[], double phi[],
-           double theta[], double imgcrd[], double pixcrd[]);
-
-int wcssptr(struct wcsprm *wcs, int *i, char ctype[9]);
-
-/* Defined mainly for backwards compatibility, use wcssub() instead. */
-#define wcscopy(alloc, wcssrc, wcsdst) wcssub(alloc, wcssrc, 0x0, 0x0, wcsdst)
-
-
-/* Deprecated. */
-#define wcsini_errmsg wcs_errmsg
-#define wcssub_errmsg wcs_errmsg
-#define wcscopy_errmsg wcs_errmsg
-#define wcsfree_errmsg wcs_errmsg
-#define wcsprt_errmsg wcs_errmsg
-#define wcsset_errmsg wcs_errmsg
-#define wcsp2s_errmsg wcs_errmsg
-#define wcss2p_errmsg wcs_errmsg
-#define wcsmix_errmsg wcs_errmsg
-
-#ifdef __cplusplus
-#undef wtbarr
-}
-#endif
-
-#endif /* WCSLIB_WCS */
diff --git a/astropy/wcs/src/wcslib/C/wcsbth.l b/astropy/wcs/src/wcslib/C/wcsbth.l
deleted file mode 100644
index 7e09066..0000000
--- a/astropy/wcs/src/wcslib/C/wcsbth.l
+++ /dev/null
@@ -1,2568 +0,0 @@
-/*============================================================================
-
-  WCSLIB 4.10 - an implementation of the FITS WCS standard.
-  Copyright (C) 1995-2012, Mark Calabretta
-
-  This file is part of WCSLIB.
-
-  WCSLIB is free software: you can redistribute it and/or modify it under the
-  terms of the GNU Lesser General Public License as published by the Free
-  Software Foundation, either version 3 of the License, or (at your option)
-  any later version.
-
-  WCSLIB 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 Lesser General Public License for
-  more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with WCSLIB.  If not, see <http://www.gnu.org/licenses/>.
-
-  Correspondence concerning WCSLIB may be directed to:
-    Internet email: mcalabre at atnf.csiro.au
-    Postal address: Dr. Mark Calabretta
-                    Australia Telescope National Facility, CSIRO
-                    PO Box 76
-                    Epping NSW 1710
-                    AUSTRALIA
-
-  Author: Mark Calabretta, Australia Telescope National Facility
-  http://www.atnf.csiro.au/~mcalabre/index.html
-  $Id: wcsbth.l,v 4.10 2012/02/05 23:41:44 cal103 Exp $
-*=============================================================================
-*
-* wcsbth.l is a Flex description file containing the definition of a lexical
-* scanner for parsing the WCS keyrecords for one or more image arrays and/or
-* pixel lists in a FITS binary table header.  It can also handle primary image
-* and image extension headers.
-*
-* wcsbth.l requires Flex v2.5.4 or later.  Refer to wcshdr.h for a description
-* of the user interface and operating notes.
-*
-* Implementation notes
-* --------------------
-* wcsbth() may be invoked with an option that causes it to recognise the
-* image-header form of WCS keywords as defaults for each alternate coordinate
-* representation (up to 27).  By design, with this option enabled wcsbth() can
-* also handle primary image and image extension headers, effectively treating
-* them as a single-column binary table though with WCS keywords of a different
-* form.
-*
-* NAXIS is always 2 for binary tables, it refers to the two-dimensional nature
-* of the table.  Thus NAXIS does not count the number of image axes in either
-* image arrays or pixels lists and for the latter there is not even a formal
-* equivalent of WCSAXESa.  Hence NAXIS is always ignored and a first pass
-* through the header is required to determine the number of images, the number
-* of alternate coordinate representations for each image (up to 27), and the
-* number of coordinate axes in each representation; this pass also counts the
-* number of iPVn_ma and iPSn_ma or TVk_ma and TSk_ma keywords in each
-* representation.
-*
-* On completion of the first pass, the association between column number and
-* axis number is defined for each representation of a pixel list.  Memory is
-* allocated for an array of the required number of wcsprm structs and each of
-* these is initialized appropriately.  These structs are filled in the second
-* pass.
-*
-* It is permissible for a scalar table column to contain degenerate (single-
-* point) image arrays and simultaneously form one axis of a pixel list.
-*
-* The parser does not check for duplicated keywords, for most keywords it
-* accepts the last encountered.
-*
-* wcsbth() does not currently handle the Green Bank convention.
-*
-*===========================================================================*/
-
-/* Options. */
-%option full
-%option never-interactive
-%option noyywrap
-%option outfile="wcsbth.c"
-%option prefix="wcsbth"
-
-/* Indices for parameterized keywords. */
-I0	[0-9]
-I1	[1-9]
-I2	[1-9][0-9]
-I3	[1-9][0-9]{2}
-I4	[1-9][0-9]{3}
-
-/* Alternate coordinate system identifier. */
-ALT	[ A-Z]
-
-/* Keyvalue data types. */
-INTEGER	[+-]?[0-9]+
-FLOAT	[+-]?([0-9]+\.?[0-9]*|\.[0-9]+)([eE][+-]?[0-9]+)?
-STRING	'([^']|'')*'
-
-/* Exclusive start states. */
-%x CCCCCia   iCCCna iCCCCn    TCCCna TCCCCn
-%x CCi_ja    ijCCna           TCn_ka TCCn_ka
-%x CROTAi           iCROTn           TCROTn
-%x CCi_ma    iCn_ma iCCn_ma   TCn_ma TCCn_ma
-%x PROJPm
-%x CCCCCCCC CCCCCCCa
-%x CCCCna   CCCCCna
-%x CCCCn    CCCCCn
-%x VALUE INTEGER_VAL FLOAT_VAL STRING_VAL
-%x COMMENT DISCARD ERROR FLUSH
-
-%{
-#include <math.h>
-#include <setjmp.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "wcs.h"
-#include "wcshdr.h"
-#include "wcsmath.h"
-
-			/* Codes used for keyvalue data types. */
-#define INTEGER 0
-#define FLOAT   1
-#define STRING  2
-
-			/* Bit masks used for keyword types:        */
-#define IMGAUX  0x1	/* Auxiliary image header, e.g. LONPOLEa or */
-			/* DATE-OBS.                                */
-#define IMGAXIS 0x2	/* Image header with axis number, e.g.      */
-			/* CTYPEia.                                 */
-#define IMGHEAD 0x3	/* Image header of either type.             */
-#define BIMGARR 0x4	/* Binary table image array with axis       */
-			/* number, e.g. iCTYna.                     */
-#define PIXLIST 0x8	/* Pixel list, e.g. TCTYna.                 */
-#define BINTAB  0xC	/* Shared binary table image array (without */
-			/* axis number) or pixel list, e.g. LONPna  */
-			/* or OBSGXn.                               */
-
-#define YY_DECL int wcsbth(char *header, int nkeyrec, int relax, int ctrl, \
-                           int keysel, int *colsel, int *nreject, int *nwcs, \
-			   struct wcsprm **wcs)
-
-#define YY_INPUT(inbuff, count, bufsize) \
-	{ \
-	  if (wcsbth_nkeyrec) { \
-	    strncpy(inbuff, wcsbth_hdr, 80); \
-	    inbuff[80] = '\n'; \
-	    wcsbth_hdr += 80; \
-	    wcsbth_nkeyrec--; \
-	    count = 81; \
-	  } else { \
-	    count = YY_NULL; \
-	  } \
-	}
-
-/* A convenience macro to get around incompatibilities between unput() and
-   yyless(): put yytext followed by a blank back onto the input stream. */
-#define WCSBTH_PUTBACK \
-  sprintf(stmp, "%s ", yytext); \
-  itmp = strlen(stmp); \
-  while (itmp) unput(stmp[--itmp]);
-
-/* These global variables are required by YY_INPUT. */
-char *wcsbth_hdr;
-int  wcsbth_nkeyrec;
-
-/* Used in preempting the call to exit() by yy_fatal_error(). */
-jmp_buf wcsbth_abort_jmp_env;
-#define exit(status) longjmp(wcsbth_abort_jmp_env, status)
-
-/* Struct used internally for header bookkeeping. */
-struct wcsbth_alts {
-  int ncol, ialt, icol, imgherit;
-  short int (*arridx)[27];
-  short int pixidx[27];
-  short int pad1;
-  unsigned int *pixlist;
-
-  unsigned char (*npv)[27];
-  unsigned char (*nps)[27];
-  unsigned char pixnpv[27];
-  unsigned char pixnps[27];
-  unsigned char pad2[2];
-};
-
-int wcsbth_pass1(int keytype, int i, int j, int n, int k, char a, char ptype,
-        struct wcsbth_alts *alts);
-int wcsbth_init1(struct wcsbth_alts *alts, int *nwcs, struct wcsprm **wcs);
-
-struct wcsprm *wcsbth_idx(struct wcsprm *wcs, struct wcsbth_alts *alts,
-        int keytype, int n, char a);
-int wcsbth_colax(struct wcsprm *wcs, struct wcsbth_alts *alts, int k, char a);
-
-int wcsbth_epoch(void *wptr);
-int wcsbth_vsource(void *wptr);
-
-int wcsbth_final(struct wcsbth_alts *alts, int *nwcs, struct wcsprm **wcs);
-
-%}
-
-%%
-	/* Keyword indices, as used in the WCS papers, e.g. iVn_ma, TPn_ka. */
-	char a;
-	int  i, j, k, m, n;
-	
-	char *cptr, *errmsg, errtxt[80], exclude[1000], *extkey, *hptr, ptype,
-	     stmp[16];
-	int  altlin, ialt, icol, incl, ipass, ipx, itmp, ix, jx, keytype,
-	     nsel, npass, status, valtype, voff;
-	void   *vptr, *wptr;
-	struct wcsbth_alts alts;
-	struct wcsprm *wcsp, wcstem;
-	int (*special)(void *);
-	int yylex_destroy(void);
-	
-	/* The data structures produced. */
-	*nwcs = 0;
-	*wcs  = 0x0;
-	
-	/* Parameters used to implement YY_INPUT. */
-	wcsbth_hdr = header;
-	wcsbth_nkeyrec = nkeyrec;
-	
-	/* Our handle on the input stream. */
-	hptr = header;
-	*nreject = 0;
-	
-	/* Keyword parameters. */
-	i = j = 0;
-	n = k = 0;
-	m = 0;
-	a = ' ';
-	
-	/* Header bookkeeping. */
-	alts.ncol = 0;
-	alts.arridx  = 0x0;
-	alts.pixlist = 0x0;
-	alts.npv = 0x0;
-	alts.nps = 0x0;
-	
-	for (ialt = 0; ialt < 27; ialt++) {
-	  alts.pixidx[ialt] = 0;
-	  alts.pixnpv[ialt] = 0;
-	  alts.pixnps[ialt] = 0;
-	}
-	
-	/* For decoding the keyvalue. */
-	keytype =  0;
-	valtype = -1;
-	vptr    = 0x0;
-	
-	/* For keywords that require special handling. */
-	altlin = 0;
-	ptype  = ' ';
-	special = 0x0;
-	
-	/* Selection by column number. */
-	nsel = colsel ? colsel[0] : 0;
-	incl = (nsel > 0);
-	for (icol = 0; icol < 1000; icol++) {
-	  exclude[icol] = incl;
-	}
-	for (icol = 1; icol <= abs(nsel); icol++) {
-	  itmp = colsel[icol];
-	  if (0 < itmp && itmp < 1000) {
-	    exclude[itmp] = !incl;
-	  }
-	}
-	exclude[0] = 0;
-	
-	/* Selection by keyword type. */
-	itmp = keysel;
-	keysel = 0;
-	if (itmp) {
-	  if (itmp & WCSHDR_IMGHEAD) keysel |= IMGHEAD;
-	  if (itmp & WCSHDR_BIMGARR) keysel |= BIMGARR;
-	  if (itmp & WCSHDR_PIXLIST) keysel |= PIXLIST;
-	}
-	if (keysel == 0) {
-	  keysel = IMGHEAD | BINTAB;
-	}
-	
-	/* Control variables. */
-	ipass = 1;
-	npass = 2;
-	
-	/* Return here via longjmp() invoked by yy_fatal_error(). */
-	if (setjmp(wcsbth_abort_jmp_env)) {
-	  return 4;
-	}
-	
-	BEGIN(INITIAL);
-
-
-^TFIELDS" = "" "*{INTEGER} {
-	  if (ipass == 1) {
-	    if (alts.ncol == 0) {
-	      sscanf(yytext, "TFIELDS = %d", &(alts.ncol));
-	      BEGIN(FLUSH);
-	    } else {
-	      errmsg = "Duplicate or out-of-sequence TFIELDS keyword";
-	      BEGIN(ERROR);
-	    }
-	
-	  } else {
-	    BEGIN(FLUSH);
-	  }
-	}
-
-^WCSAXES{ALT}=" "" "*{INTEGER} {
-	  keytype = IMGAXIS;
-	
-	  if (!(keytype & keysel)) {
-	    /* Ignore this key type. */
-	    BEGIN(DISCARD);
-	
-	  } else {
-	    if (relax & WCSHDR_ALLIMG) {
-	      if (ipass == 1) {
-	        sscanf(yytext, "WCSAXES%c= %d", &a, &i);
-	        wcsbth_pass1(IMGAXIS, i, 0, 0, 0, a, ' ', &alts);
-	      }
-	
-	      BEGIN(FLUSH);
-	
-	    } else if (relax & WCSHDR_reject) {
-	      errmsg = "Image-header keyword WCSAXESa in binary table";
-	      BEGIN(ERROR);
-	
-	    } else {
-	      /* Pretend we don't recognize it. */
-	      BEGIN(DISCARD);
-	    }
-	  }
-	}
-
-^WCAX{I1}{ALT}"  = "" "*{INTEGER} |
-^WCAX{I2}{ALT}" = "" "*{INTEGER}  |
-^WCAX{I3}{ALT}"= "" "*{INTEGER} {
-	  keytype = BIMGARR;
-	
-	  /* Note that a blank in the sscanf() format string matches zero or
-	     more of them in the input. */
-	  sscanf(yytext, "WCAX%d%c = %d", &n, &a, &i);
-	
-	  if (!(keytype & keysel) || exclude[n]) {
-	    /* Ignore this key type or column. */
-	    BEGIN(DISCARD);
-	  } else {
-	    if (ipass == 1) {
-	      wcsbth_pass1(BIMGARR, i, 0, n, 0, a, ' ', &alts);
-	    }
-	    BEGIN(FLUSH);
-	  }
-	}
-
-^WCST{I1}{ALT}"  = "" "*{STRING} |
-^WCST{I2}{ALT}" = "" "*{STRING} |
-^WCST{I3}{ALT}"= "" "*{STRING} {
-	  /* Cross-reference supplier. */
-	  keytype = BIMGARR;
-	  errmsg = "Cross-references are not currently implemented";
-	  BEGIN(ERROR);
-	}
-
-^WCSX{I1}{ALT}"  = "" "*{STRING} |
-^WCSX{I2}{ALT}" = "" "*{STRING} |
-^WCSX{I3}{ALT}"= "" "*{STRING} {
-	  /* Cross-reference consumer. */
-	  keytype = BIMGARR;
-	  errmsg = "Cross-references are not currently implemented";
-	  BEGIN(ERROR);
-	}
-
-^CRPIX	{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.crpix);
-	
-	  extkey = "CRPIXja";
-	  BEGIN(CCCCCia);
-	}
-
-^{I1}CRP  |
-^{I1}CRPX {
-	  valtype = FLOAT;
-	  vptr = &(wcstem.crpix);
-	
-	  sscanf(yytext, "%d", &i);
-	
-	  if (yyleng == 4) {
-	    BEGIN(iCCCna);
-	  } else {
-	    extkey = "jCRPXn";
-	    BEGIN(iCCCCn);
-	  }
-	}
-
-^TCRP	|
-^TCRPX	{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.crpix);
-	
-	  if (yyleng == 4) {
-	    BEGIN(TCCCna);
-	  } else {
-	    extkey = "TCRPXn";
-	    BEGIN(TCCCCn);
-	  }
-	}
-
-^PC	{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.pc);
-	  altlin = 1;
-	
-	  extkey = "PCi_ja";
-	  BEGIN(CCi_ja);
-	}
-
-^{I2}PC	{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.pc);
-	  altlin = 1;
-	
-	  sscanf(yytext, "%1d%1d", &i, &j);
-	
-	  BEGIN(ijCCna);
-	}
-
-^TP	|
-^TPC	{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.pc);
-	  altlin = 1;
-	
-	  if (yyleng == 2) {
-	    BEGIN(TCn_ka);
-	  } else {
-	    extkey = "TPCn_ka";
-	    BEGIN(TCCn_ka);
-	  }
-	}
-
-^CD	{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.cd);
-	  altlin = 2;
-	
-	  extkey = "CDi_ja";
-	  BEGIN(CCi_ja);
-	}
-
-^{I2}CD	{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.cd);
-	  altlin = 2;
-	
-	  sscanf(yytext, "%1d%1d", &i, &j);
-	
-	  BEGIN(ijCCna);
-	}
-
-^TC	|
-^TCD	{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.cd);
-	  altlin = 2;
-	
-	  if (yyleng == 2) {
-	    BEGIN(TCn_ka);
-	  } else {
-	    extkey = "TCDn_ka";
-	    BEGIN(TCCn_ka);
-	  }
-	}
-
-^CDELT	{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.cdelt);
-	
-	  extkey = "CDELTia";
-	  BEGIN(CCCCCia);
-	}
-
-^{I1}CDE  |
-^{I1}CDLT {
-	  valtype = FLOAT;
-	  vptr = &(wcstem.cdelt);
-	
-	  sscanf(yytext, "%d", &i);
-	
-	  if (yyleng == 4) {
-	    BEGIN(iCCCna);
-	  } else {
-	    extkey = "iCDLTn";
-	    BEGIN(iCCCCn);
-	  }
-	}
-
-^TCDE	|
-^TCDLT	{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.cdelt);
-	
-	  if (yyleng == 4) {
-	    BEGIN(TCCCna);
-	  } else {
-	    extkey = "TCDLTn";
-	    BEGIN(TCCCCn);
-	  }
-	}
-
-^CROTA	{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.crota);
-	  altlin = 4;
-	
-	  extkey = "CROTAi";
-	  BEGIN(CROTAi);
-	}
-
-^{I1}CROT {
-	  valtype = FLOAT;
-	  vptr = &(wcstem.crota);
-	  altlin = 4;
-	
-	  sscanf(yytext, "%d", &i);
-	
-	  extkey = "iCROTn";
-	  BEGIN(iCROTn);
-	}
-
-^TCROT	{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.crota);
-	  altlin = 4;
-	
-	  extkey = "TCROTn";
-	  BEGIN(TCROTn);
-	}
-
-^CUNIT	{
-	  valtype = STRING;
-	  vptr = &(wcstem.cunit);
-	
-	  extkey = "CUNITia";
-	  BEGIN(CCCCCia);
-	}
-
-^{I1}CUN  |
-^{I1}CUNI {
-	  valtype = STRING;
-	  vptr = &(wcstem.cunit);
-	
-	  sscanf(yytext, "%d", &i);
-	
-	  if (yyleng == 4) {
-	    BEGIN(iCCCna);
-	  } else {
-	    extkey = "iCUNIn";
-	    BEGIN(iCCCCn);
-	  }
-	}
-
-^TCUN	|
-^TCUNI	{
-	  valtype = STRING;
-	  vptr = &(wcstem.cunit);
-	
-	  if (yyleng == 4) {
-	    BEGIN(TCCCna);
-	  } else {
-	    extkey = "TCUNIn";
-	    BEGIN(TCCCCn);
-	  }
-	}
-
-^CTYPE	{
-	  valtype = STRING;
-	  vptr = &(wcstem.ctype);
-	
-	  extkey = "CTYPEia";
-	  BEGIN(CCCCCia);
-	}
-
-^{I1}CTY  |
-^{I1}CTYP {
-	  valtype = STRING;
-	  vptr = &(wcstem.ctype);
-	
-	  sscanf(yytext, "%d", &i);
-	
-	  if (yyleng == 4) {
-	    BEGIN(iCCCna);
-	  } else {
-	    extkey = "iCTYPn";
-	    BEGIN(iCCCCn);
-	  }
-	}
-
-^TCTY	|
-^TCTYP	{
-	  valtype = STRING;
-	  vptr = &(wcstem.ctype);
-	
-	  if (yyleng == 4) {
-	    BEGIN(TCCCna);
-	  } else {
-	    extkey = "TCTYPn";
-	    BEGIN(TCCCCn);
-	  }
-	}
-
-^CRVAL	{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.crval);
-	
-	  extkey = "CRVALia";
-	  BEGIN(CCCCCia);
-	}
-
-^{I1}CRV  |
-^{I1}CRVL {
-	  valtype = FLOAT;
-	  vptr = &(wcstem.crval);
-	
-	  sscanf(yytext, "%d", &i);
-	
-	  if (yyleng == 4) {
-	    BEGIN(iCCCna);
-	  } else {
-	    extkey = "iCRVLn";
-	    BEGIN(iCCCCn);
-	  }
-	}
-
-^TCRV	|
-^TCRVL	{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.crval);
-	
-	  if (yyleng == 4) {
-	    BEGIN(TCCCna);
-	  } else {
-	    extkey = "TCRVLn";
-	    BEGIN(TCCCCn);
-	  }
-	}
-
-^LONPOLE |
-^LONP	{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.lonpole);
-	
-	  if (yyleng == 7) {
-	    extkey = "LONPOLEa";
-	    BEGIN(CCCCCCCa);
-	  } else {
-	    BEGIN(CCCCna);
-	  }
-	}
-
-^LATPOLE |
-^LATP	{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.latpole);
-	
-	  if (yyleng == 7) {
-	    extkey = "LATPOLEa";
-	    BEGIN(CCCCCCCa);
-	  } else {
-	    BEGIN(CCCCna);
-	  }
-	}
-
-^RESTFRQ  |
-^RESTFREQ |
-^RFRQ	{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.restfrq);
-	
-	  if (yyleng == 8) {
-	    unput(' ');
-	    extkey = "RESTFREQ";
-	    BEGIN(CCCCCCCa);
-	  } else if (yyleng == 7) {
-	    extkey = "RESTFRQa";
-	    BEGIN(CCCCCCCa);
-	  } else {
-	    BEGIN(CCCCna);
-	  }
-	}
-
-^RESTWAV |
-^RWAV	{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.restwav);
-	
-	  if (yyleng == 7) {
-	    extkey = "RESTWAVa";
-	    BEGIN(CCCCCCCa);
-	  } else {
-	    BEGIN(CCCCna);
-	  }
-	}
-
-^PV	{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.pv);
-	  ptype = 'v';
-	
-	  extkey = "PVi_ma";
-	  BEGIN(CCi_ma);
-	}
-
-^{I1}V	|
-^{I1}PV	{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.pv);
-	  ptype = 'v';
-	
-	  sscanf(yytext, "%d", &i);
-	
-	  if (yyleng == 2) {
-	    BEGIN(iCn_ma);
-	  } else {
-	    extkey = "iPVn_ma";
-	    BEGIN(iCCn_ma);
-	  }
-	}
-
-^TV	|
-^TPV	{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.pv);
-	  ptype = 'v';
-	
-	  if (yyleng == 2) {
-	    BEGIN(TCn_ma);
-	  } else {
-	    extkey = "TPVn_ma";
-	    BEGIN(TCCn_ma);
-	  }
-	}
-
-^PROJP	{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.pv);
-	  ptype = 'v';
-	
-	  BEGIN(PROJPm);
-	}
-
-^PS	{
-	  valtype = STRING;
-	  vptr = &(wcstem.ps);
-	  ptype = 's';
-	
-	  extkey = "PSi_ma";
-	  BEGIN(CCi_ma);
-	}
-
-^{I1}S	|
-^{I1}PS	{
-	  valtype = STRING;
-	  vptr = &(wcstem.ps);
-	  ptype = 's';
-	
-	  sscanf(yytext, "%d", &i);
-	
-	  if (yyleng == 2) {
-	    BEGIN(iCn_ma);
-	  } else {
-	    extkey = "iPSn_ma";
-	    BEGIN(iCCn_ma);
-	  }
-	}
-
-^TS	|
-^TPS	{
-	  valtype = STRING;
-	  vptr = &(wcstem.ps);
-	  ptype = 's';
-	
-	  if (yyleng == 2) {
-	    BEGIN(TCn_ma);
-	  } else {
-	    extkey = "TPSn_ma";
-	    BEGIN(TCCn_ma);
-	  }
-	}
-
-^CNAME	{
-	  valtype = STRING;
-	  vptr = &(wcstem.cname);
-	
-	  extkey = "CNAMEia";
-	  BEGIN(CCCCCia);
-	}
-
-^{I1}CNA  |
-^{I1}CNAM {
-	  valtype = STRING;
-	  vptr = &(wcstem.cname);
-	
-	  sscanf(yytext, "%d", &i);
-	
-	  if (yyleng == 4) {
-	    BEGIN(iCCCna);
-	  } else {
-	    if (!(relax & WCSHDR_CNAMn)) vptr = 0x0;
-	    extkey = "iCNAMn";
-	    BEGIN(iCCCCn);
-	  }
-	}
-
-^TCNA	|
-^TCNAM	{
-	  valtype = STRING;
-	  vptr = &(wcstem.cname);
-	
-	  if (yyleng == 4) {
-	    BEGIN(TCCCna);
-	  } else {
-	    if (!(relax & WCSHDR_CNAMn)) vptr = 0x0;
-	    extkey = "TCNAMn";
-	    BEGIN(TCCCCn);
-	  }
-	}
-
-^CRDER	{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.crder);
-	
-	  extkey = "CRDERia";
-	  BEGIN(CCCCCia);
-	}
-
-^{I1}CRD |
-^{I1}CRDE {
-	  valtype = FLOAT;
-	  vptr = &(wcstem.crder);
-	
-	  sscanf(yytext, "%d", &i);
-	
-	  if (yyleng == 4) {
-	    BEGIN(iCCCna);
-	  } else {
-	    if (!(relax & WCSHDR_CNAMn)) vptr = 0x0;
-	    extkey = "iCRDEn";
-	    BEGIN(iCCCCn);
-	  }
-	}
-
-^TCRD	|
-^TCRDE	{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.crder);
-	
-	  if (yyleng == 4) {
-	    BEGIN(TCCCna);
-	  } else {
-	    if (!(relax & WCSHDR_CNAMn)) vptr = 0x0;
-	    extkey = "TCRDEn";
-	    BEGIN(TCCCCn);
-	  }
-	}
-
-^CSYER	{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.csyer);
-	
-	  extkey = "CSYERia";
-	  BEGIN(CCCCCia);
-	}
-
-^{I1}CSY  |
-^{I1}CSYE {
-	  valtype = FLOAT;
-	  vptr = &(wcstem.csyer);
-	
-	  sscanf(yytext, "%d", &i);
-	
-	  if (yyleng == 4) {
-	    BEGIN(iCCCna);
-	  } else {
-	    if (!(relax & WCSHDR_CNAMn)) vptr = 0x0;
-	    extkey = "iCSYEn";
-	    BEGIN(iCCCCn);
-	  }
-	}
-
-^TCSY	|
-^TCSYE	{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.csyer);
-	
-	  if (yyleng == 4) {
-	    BEGIN(TCCCna);
-	  } else {
-	    if (!(relax & WCSHDR_CNAMn)) vptr = 0x0;
-	    extkey = "TCSYEn";
-	    BEGIN(TCCCCn);
-	  }
-	}
-
-^DATE-AVG |
-^DAVG   {
-	  valtype = STRING;
-	  vptr = wcstem.dateavg;
-	
-	  if (yyleng == 8) {
-	    extkey = "DATE-AVG";
-	    BEGIN(CCCCCCCC);
-	  } else {
-	    BEGIN(CCCCn);
-	  }
-	}
-
-^DATE-OBS {
-	  valtype = STRING;
-	  vptr = wcstem.dateobs;
-	
-	  extkey = "DATE-OBS";
-	  BEGIN(CCCCCCCC);
-	}
-
-^DOBS{I1}"   " |
-^DOBS{I2}"  "  |
-^DOBS{I3}" " {
-	  if (relax & WCSHDR_DOBSn) {
-	    valtype = STRING;
-	    vptr = wcstem.dateobs;
-	
-	    yyless(4);
-	    BEGIN(CCCCn);
-	
-	  } else {
-	    keytype = BINTAB;
-	    if (relax & WCSHDR_reject) {
-	      errmsg = "DOBSna keyword is non-standard";
-	      BEGIN(ERROR);
-	    } else {
-	      BEGIN(DISCARD);
-	    }
-	  }
-	}
-
-^EPOCH{ALT}"  " {
-	  sscanf(yytext, "EPOCH%c", &a);
-	
-	  if (a == ' ' || (relax & WCSHDR_EPOCHa)) {
-	    valtype = FLOAT;
-	    vptr = &(wcstem.equinox);
-	    special = wcsbth_epoch;
-	
-	    unput(a);
-	    extkey = "EPOCH";
-	    BEGIN(CCCCCCCa);
-	
-	  } else {
-	    keytype = IMGAUX;
-	    if (relax & WCSHDR_reject) {
-	      errmsg = "EPOCH keyword may not have an alternate version code";
-	      BEGIN(ERROR);
-	    } else {
-	      BEGIN(DISCARD);
-	    }
-	  }
-	}
-
-^EQUINOX |
-^EQUI	{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.equinox);
-	
-	  if (yyleng == 7) {
-	    extkey = "EQUINOXa";
-	    BEGIN(CCCCCCCa);
-	  } else {
-	    BEGIN(CCCCna);
-	  }
-	}
-
-^MJD-AVG" " |
-^MJDA	{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.mjdavg);
-	
-	  if (yyleng == 8) {
-	    extkey = "MJD-AVG";
-	    BEGIN(CCCCCCCC);
-	  } else {
-	    BEGIN(CCCCn);
-	  }
-	}
-
-^MJD-OBS" " |
-^MJDOB	{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.mjdobs);
-	
-	  if (yyleng == 8) {
-	    extkey = "MJD-OBS";
-	    BEGIN(CCCCCCCC);
-	  } else {
-	    BEGIN(CCCCCn);
-	  }
-	}
-
-^OBSGEO-X |
-^OBSGX	{
-	  valtype = FLOAT;
-	  vptr = wcstem.obsgeo;
-	
-	  if (yyleng == 8) {
-	    extkey = "OBSGEO-X";
-	    BEGIN(CCCCCCCC);
-	  } else {
-	    BEGIN(CCCCCn);
-	  }
-	}
-
-^OBSGEO-Y |
-^OBSGY	{
-	  valtype = FLOAT;
-	  vptr = wcstem.obsgeo + 1;
-	
-	  if (yyleng == 8) {
-	    extkey = "OBSGEO-Y";
-	    BEGIN(CCCCCCCC);
-	  } else {
-	    BEGIN(CCCCCn);
-	  }
-	}
-
-^OBSGEO-Z |
-^OBSGZ	{
-	  valtype = FLOAT;
-	  vptr = wcstem.obsgeo + 2;
-	
-	  if (yyleng == 8) {
-	    extkey = "OBSGEO-Z";
-	    BEGIN(CCCCCCCC);
-	  } else {
-	    BEGIN(CCCCCn);
-	  }
-	}
-
-^RADESYS |
-^RADE	{
-	  valtype = STRING;
-	  vptr = wcstem.radesys;
-	
-	  if (yyleng == 7) {
-	    extkey = "RADESYSa";
-	    BEGIN(CCCCCCCa);
-	  } else {
-	    BEGIN(CCCCna);
-	  }
-	}
-
-^RADECSYS {
-	  if (relax & WCSHDR_RADECSYS) {
-	    valtype = STRING;
-	    vptr = wcstem.radesys;
-	
-	    unput(' ');
-	    extkey = "RADECSYS";
-	    BEGIN(CCCCCCCa);
-	
-	  } else {
-	    keytype = IMGAUX;
-	    if (relax & WCSHDR_reject) {
-	      errmsg = "RADECSYS keyword is non-standard";
-	      BEGIN(ERROR);
-	    } else {
-	      BEGIN(DISCARD);
-	    }
-	  }
-	}
-
-^SPECSYS |
-^SPEC	{
-	  valtype = STRING;
-	  vptr = wcstem.specsys;
-	
-	  if (yyleng == 7) {
-	    extkey = "SPECSYSa";
-	    BEGIN(CCCCCCCa);
-	  } else {
-	    BEGIN(CCCCna);
-	  }
-	}
-
-^SSYSOBS |
-^SOBS	{
-	  valtype = STRING;
-	  vptr = wcstem.ssysobs;
-	
-	  if (yyleng == 7) {
-	    extkey = "SSYSOBSa";
-	    BEGIN(CCCCCCCa);
-	  } else {
-	    BEGIN(CCCCna);
-	  }
-	}
-
-^SSYSSRC |
-^SSRC	{
-	  valtype = STRING;
-	  vptr = wcstem.ssyssrc;
-	
-	  if (yyleng == 7) {
-	    extkey = "SSYSSRCa";
-	    BEGIN(CCCCCCCa);
-	  } else {
-	    BEGIN(CCCCna);
-	  }
-	}
-
-^VELOSYS |
-^VSYS	{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.velosys);
-	
-	  if (yyleng == 7) {
-	    extkey = "VELOSYSa";
-	    BEGIN(CCCCCCCa);
-	  } else {
-	    BEGIN(CCCCna);
-	  }
-	}
-
-^VELANGL |
-^VANG	{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.velangl);
-	
-	  if (yyleng == 7) {
-	    extkey = "VELANGLa";
-	    BEGIN(CCCCCCCa);
-	  } else {
-	    BEGIN(CCCCna);
-	  }
-	}
-
-^VELREF{ALT}" " {
-	  sscanf(yytext, "VELREF%c", &a);
-	
-	  if (a == ' ' || (relax & WCSHDR_VELREFa)) {
-	    valtype = INTEGER;
-	    vptr = &(wcstem.velref);
-	
-	    unput(a);
-	    extkey = "VELREF";
-	    BEGIN(CCCCCCCa);
-	
-	  } else {
-	    keytype = IMGAUX;
-	    if (relax & WCSHDR_reject) {
-	      errmsg = "VELREF keyword may not have an alternate version code";
-	      BEGIN(ERROR);
-	    } else {
-	      BEGIN(DISCARD);
-	    }
-	  }
-	}
-
-^VSOURCE{ALT} {
-	  if (relax & WCSHDR_VSOURCE) {
-	    valtype = FLOAT;
-	    vptr = &(wcstem.zsource);
-	    special = wcsbth_vsource;
-	
-	    yyless(7);
-	    extkey = "VSOURCEa";
-	    BEGIN(CCCCCCCa);
-	
-	  } else {
-	    keytype = IMGAUX;
-	    if (relax & WCSHDR_reject) {
-	      errmsg = "VSOURCEa keyword is deprecated";
-	      BEGIN(ERROR);
-	    } else {
-	      BEGIN(DISCARD);
-	    }
-	  }
-	}
-
-^VSOU{I1}{ALT}"  " |
-^VSOU{I2}{ALT}" "  |
-^VSOU{I3}{ALT} {
-	  if (relax & WCSHDR_VSOURCE) {
-	    valtype = FLOAT;
-	    vptr = &(wcstem.zsource);
-	    special = wcsbth_vsource;
-	
-	    yyless(4);
-	    BEGIN(CCCCna);
-	
-	  } else {
-	    keytype = BINTAB;
-	    if (relax & WCSHDR_reject) {
-	      errmsg = "VSOUna keyword is deprecated";
-	      BEGIN(ERROR);
-	    } else {
-	      /* Pretend we don't recognize it. */
-	      BEGIN(DISCARD);
-	    }
-	  }
-	}
-
-^WCSNAME |
-^WCSN	 |
-^TWCS	{
-	  valtype = STRING;
-	  vptr = wcstem.wcsname;
-	
-	  if (yyleng == 7) {
-	    extkey = "WCSNAMEa";
-	    BEGIN(CCCCCCCa);
-	  } else {
-	    BEGIN(CCCCna);
-	  }
-	}
-
-^ZSOURCE |
-^ZSOU	{
-	  valtype = FLOAT;
-	  vptr = &(wcstem.zsource);
-	
-	  if (yyleng == 7) {
-	    extkey = "ZSOURCEa";
-	    BEGIN(CCCCCCCa);
-	  } else {
-	    BEGIN(CCCCna);
-	  }
-	}
-
-^END" "{77} {
-	  yyless(0);
-	  if (wcsbth_nkeyrec) {
-	    wcsbth_nkeyrec = 0;
-	    errmsg = "Keyrecords following the END keyrecord were ignored";
-	    BEGIN(ERROR);
-	  } else {
-	    BEGIN(DISCARD);
-	  }
-	}
-
-^.	{
-	  yyless(0);
-	  BEGIN(DISCARD);
-	}
-
-<CCCCCia>{I1}{ALT}" " |
-<CCCCCia>{I2}{ALT} {
-	  /* Image-header keyword. */
-	  keytype = IMGAXIS;
-	  if (relax & WCSHDR_ALLIMG) {
-	    sscanf(yytext, "%d%c", &i, &a);
-	    BEGIN(VALUE);
-	
-	  } else if (relax & WCSHDR_reject) {
-	    errmsg = errtxt;
-	    sprintf(errmsg,
-	      "Image-header keyword %s in binary table", extkey);
-	    BEGIN(ERROR);
-	
-	  } else {
-	    /* Pretend we don't recognize it. */
-	    BEGIN(DISCARD);
-	  }
-	}
-
-<CCCCCia>{I3} {
-	  /* Invalid axis number in image-header keyword. */
-	  keytype = IMGAXIS;
-	  if (relax & WCSHDR_ALLIMG) {
-	    /* Will also be flagged by <VALUE> as invalid. */
-	    sscanf(yytext, "%3d", &i);
-	    BEGIN(VALUE);
-	
-	  } else {
-	    /* Pretend we don't recognize it. */
-	    BEGIN(DISCARD);
-	  }
-	}
-
-<iCCCCn>{I1}"  " |
-<iCCCCn>{I2}" "  |
-<iCCCCn>{I3}     |
-<TCCCCn>{I1}"  " |
-<TCCCCn>{I2}" "  |
-<TCCCCn>{I3} {
-	  if (vptr) {
-	    WCSBTH_PUTBACK;
-	    BEGIN((YY_START == iCCCCn) ? iCCCna : TCCCna);
-	  } else {
-	    keytype = (YY_START == iCCCCn) ? BIMGARR : PIXLIST;
-	    if (relax & WCSHDR_reject) {
-	      errmsg = errtxt;
-	      sprintf(errmsg, "%s keyword is non-standard", extkey);
-	      BEGIN(ERROR);
-	    } else {
-	      BEGIN(DISCARD);
-	    }
-	  }
-	}
-
-<iCCCCn>{I1}[A-Z]" " |
-<iCCCCn>{I2}[A-Z]    |
-<TCCCCn>{I1}[A-Z]" " |
-<TCCCCn>{I2}[A-Z] {
-	  if (vptr && (relax & WCSHDR_LONGKEY)) {
-	    WCSBTH_PUTBACK;
-	    BEGIN((YY_START == iCCCCn) ? iCCCna : TCCCna);
-	
-	  } else {
-	    keytype = (YY_START == iCCCna) ? BIMGARR : PIXLIST;
-	    if (relax & WCSHDR_reject) {
-	      errmsg = errtxt;
-	      if (!vptr) {
-	        sprintf(errmsg, "%s keyword is non-standard", extkey);
-	      } else {
-	        sprintf(errmsg,
-	          "%s keyword may not have an alternate version code", extkey);
-	      }
-	      BEGIN(ERROR);
-	
-	    } else {
-	      /* Pretend we don't recognize it. */
-	      BEGIN(DISCARD);
-	    }
-	  }
-	}
-
-<iCCCCn>. |
-<TCCCCn>. {
-	  BEGIN(DISCARD);
-	}
-
-<iCCCna>{I1}{ALT}"  " |
-<iCCCna>{I2}{ALT}" "  |
-<iCCCna>{I3}{ALT}     |
-<TCCCna>{I1}{ALT}"  " |
-<TCCCna>{I2}{ALT}" "  |
-<TCCCna>{I3}{ALT} {
-	  sscanf(yytext, "%d%c", &n, &a);
-	  if (YY_START == TCCCna) i = wcsbth_colax(*wcs, &alts, n, a);
-	  keytype = (YY_START == iCCCna) ? BIMGARR : PIXLIST;
-	  BEGIN(VALUE);
-	}
-
-<iCCCna>. |
-<TCCCna>. {
-	  BEGIN(DISCARD);
-	}
-
-<CCi_ja>{I1}_{I1}{ALT}"  " |
-<CCi_ja>{I1}_{I2}{ALT}" " |
-<CCi_ja>{I2}_{I1}{ALT}" " |
-<CCi_ja>{I2}_{I2}{ALT} {
-	  /* Image-header keyword. */
-	  if (relax & WCSHDR_ALLIMG) {
-	    sscanf(yytext, "%d_%d%c", &i, &j, &a);
-	    keytype = IMGAXIS;
-	    BEGIN(VALUE);
-	
-	  } else if (relax & WCSHDR_reject) {
-	    errmsg = errtxt;
-	    sprintf(errmsg,
-	      "Image-header keyword %s in binary table", extkey);
-	    BEGIN(ERROR);
-	
-	  } else {
-	    /* Pretend we don't recognize it. */
-	    BEGIN(DISCARD);
-	  }
-	}
-
-<CCi_ja>{I1}_{I3}{ALT} |
-<CCi_ja>{I3}_{I1}{ALT} |
-<CCi_ja>{I1}_{I4} |
-<CCi_ja>{I2}_{I3} |
-<CCi_ja>{I3}_{I2} |
-<CCi_ja>{I4}_{I1} {
-	  /* Invalid axis number in image-header keyword. */
-	  if (relax & WCSHDR_ALLIMG) {
-	    /* Will be flagged by <VALUE> as invalid. */
-	    sscanf(yytext, "%d_%d", &i, &j);
-	    keytype = IMGAXIS;
-	    BEGIN(VALUE);
-	
-	  } else {
-	    /* Pretend we don't recognize it. */
-	    BEGIN(DISCARD);
-	  }
-	}
-
-<CCi_ja>{I0}{6} {
-	  /* This covers the defunct forms CD00i00j and PC00i00j. */
-	  if (((relax & WCSHDR_PC00i00j) && (altlin == 1)) ||
-	      ((relax & WCSHDR_CD00i00j) && (altlin == 2))) {
-	    sscanf(yytext, "%3d%3d", &i, &j);
-	    a = ' ';
-	    keytype = IMGAXIS;
-	    BEGIN(VALUE);
-	
-	  } else if (relax & WCSHDR_reject) {
-	    errmsg = errtxt;
-	    sprintf(errmsg, "Defunct form of %si_ja keyword",
-	                     (altlin==1) ? "PC" : "CD");
-	    BEGIN(ERROR);
-	
-	  } else {
-	    /* Pretend we don't recognize it. */
-	    BEGIN(DISCARD);
-	  }
-	}
-
-<CCi_ja>. {
-	  BEGIN(DISCARD);
-	}
-
-<ijCCna>{I1}{ALT}"  " |
-<ijCCna>{I2}{ALT}" "  |
-<ijCCna>{I3}{ALT} {
-	  sscanf(yytext, "%d%c", &n, &a);
-	  keytype = BIMGARR;
-	  BEGIN(VALUE);
-	}
-
-<TCCn_ka>{I1}_{I1}{ALT}" " |
-<TCCn_ka>{I1}_{I2}{ALT} |
-<TCCn_ka>{I2}_{I1}{ALT} |
-<TCCn_ka>{I1}_{I3} |
-<TCCn_ka>{I2}_{I2} |
-<TCCn_ka>{I3}_{I1} {
-	  if (relax & WCSHDR_LONGKEY) {
-	    WCSBTH_PUTBACK;
-	    BEGIN(TCn_ka);
-	
-	  } else if (relax & WCSHDR_reject) {
-	    errmsg = errtxt;
-	    sprintf(errmsg, "%s keyword is non-standard", extkey);
-	    BEGIN(ERROR);
-	
-	  } else {
-	    /* Pretend we don't recognize it. */
-	    BEGIN(DISCARD);
-	  }
-	}
-
-<TCCn_ka>. {
-	  BEGIN(DISCARD);
-	}
-
-<TCn_ka>{I1}_{I1}{ALT}"  " |
-<TCn_ka>{I1}_{I2}{ALT}" " |
-<TCn_ka>{I2}_{I1}{ALT}" " |
-<TCn_ka>{I1}_{I3}{ALT} |
-<TCn_ka>{I2}_{I2}{ALT} |
-<TCn_ka>{I3}_{I1}{ALT} {
-	  sscanf(yytext, "%d_%d%c", &n, &k, &a);
-	  i = wcsbth_colax(*wcs, &alts, n, a);
-	  j = wcsbth_colax(*wcs, &alts, k, a);
-	  keytype = PIXLIST;
-	  BEGIN(VALUE);
-	}
-
-<TCn_ka>{I1}_{I4} |
-<TCn_ka>{I2}_{I3} |
-<TCn_ka>{I3}_{I2} |
-<TCn_ka>{I4}_{I1} {
-	  sscanf(yytext, "%d_%d", &n, &k);
-	  a = ' ';
-	  i = wcsbth_colax(*wcs, &alts, n, a);
-	  j = wcsbth_colax(*wcs, &alts, k, a);
-	  keytype = PIXLIST;
-	  BEGIN(VALUE);
-	}
-
-<TCn_ka>. {
-	  BEGIN(DISCARD);
-	}
-
-<CROTAi>{I1}"  " |
-<CROTAi>{I2}" " {
-	  yyless(0);
-	  BEGIN(CCCCCia);
-	}
-
-<CROTAi>{I1}[A-Z]" " |
-<CROTAi>{I2}[A-Z] {
-	  if (relax & WCSHDR_CROTAia) {
-	    yyless(0);
-	    BEGIN(CCCCCia);
-	
-	  } else if (relax & WCSHDR_reject) {
-	    errmsg = "CROTAn keyword may not have an alternate version code";
-	    BEGIN(ERROR);
-	
-	  } else {
-	    /* Pretend we don't recognize it. */
-	    BEGIN(DISCARD);
-	  }
-	}
-
-<CROTAi>. {
-	  BEGIN(DISCARD);
-	}
-
-<iCROTn>{I1}"  " |
-<iCROTn>{I2}" "  |
-<iCROTn>{I3}     |
-<TCROTn>{I1}"  " |
-<TCROTn>{I2}" "  |
-<TCROTn>{I3} {
-	  WCSBTH_PUTBACK;
-	  BEGIN((YY_START == iCROTn) ? iCCCna : TCCCna);
-	}
-
-<iCROTn>{I1}[A-Z]" " |
-<iCROTn>{I2}[A-Z]    |
-<TCROTn>{I1}[A-Z]" " |
-<TCROTn>{I2}[A-Z] {
-	  if (relax & WCSHDR_CROTAia) {
-	    WCSBTH_PUTBACK;
-	    BEGIN((YY_START == iCROTn) ? iCCCna : TCCCna);
-	
-	  } else if (relax & WCSHDR_reject) {
-	    errmsg = errtxt;
-	    sprintf(errmsg,
-	      "%s keyword may not have an alternate version code", extkey);
-	    BEGIN(ERROR);
-	
-	  } else {
-	    /* Pretend we don't recognize it. */
-	    BEGIN(DISCARD);
-	  }
-	}
-
-<iCROTn>. |
-<TCROTn>. {
-	  BEGIN(DISCARD);
-	}
-
-<CCCCCCCa>{ALT} |
-<CCCCCCCC>. {
-	  /* Image-header keyword. */
-	  if (relax & (WCSHDR_AUXIMG | WCSHDR_ALLIMG)) {
-	    if (YY_START == CCCCCCCa) {
-	      sscanf(yytext, "%c", &a);
-	    } else {
-	      a = 0;
-	      unput(yytext[0]);
-	    }
-	    keytype = IMGAUX;
-	    BEGIN(VALUE);
-	
-	  } else if (relax & WCSHDR_reject) {
-	    errmsg = errtxt;
-	    sprintf(errmsg,
-	      "Image-header keyword %s in binary table", extkey);
-	    BEGIN(ERROR);
-	
-	  } else {
-	    /* Pretend we don't recognize it. */
-	    BEGIN(DISCARD);
-	  }
-	}
-
-<CCCCCCCa>. {
-	  BEGIN(DISCARD);
-	}
-
-<CCCCna>{I1}{ALT}"  " |
-<CCCCna>{I2}{ALT}" "  |
-<CCCCna>{I3}{ALT}     |
-<CCCCCna>{I1}{ALT}" " |
-<CCCCCna>{I2}{ALT} {
-	  sscanf(yytext, "%d%c", &n, &a);
-	  keytype = BINTAB;
-	  BEGIN(VALUE);
-	}
-
-<CCCCCna>{I3} {
-	  sscanf(yytext, "%d", &n);
-	  a = ' ';
-	  keytype = BINTAB;
-	  BEGIN(VALUE);
-	}
-
-<CCCCna>. |
-<CCCCCna>. {
-	  BEGIN(DISCARD);
-	}
-
-<CCCCn>{I1}"   " |
-<CCCCn>{I2}"  "  |
-<CCCCn>{I3}" "   |
-<CCCCn>{I4}      |
-<CCCCCn>{I1}"  " |
-<CCCCCn>{I2}" "  |
-<CCCCCn>{I3} {
-	  sscanf(yytext, "%d", &n);
-	  a = 0;
-	  keytype = BINTAB;
-	  BEGIN(VALUE);
-	}
-
-<CCCCn>. |
-<CCCCCn>. {
-	  BEGIN(DISCARD);
-	}
-
-<CCi_ma>{I1}_{I0}{ALT}"  " |
-<CCi_ma>{I1}_{I2}{ALT}" " |
-<CCi_ma>{I2}_{I0}{ALT}" " |
-<CCi_ma>{I2}_{I2}{ALT} {
-	  /* Image-header keyword. */
-	  if (relax & WCSHDR_ALLIMG) {
-	    sscanf(yytext, "%d_%d%c", &i, &m, &a);
-	    keytype = IMGAXIS;
-	    BEGIN(VALUE);
-	
-	  } else if (relax & WCSHDR_reject) {
-	    errmsg = errtxt;
-	    sprintf(errmsg,
-	      "Image-header keyword %s in binary table", extkey);
-	    BEGIN(ERROR);
-	
-	  } else {
-	    /* Pretend we don't recognize it. */
-	    BEGIN(DISCARD);
-	  }
-	}
-
-<CCi_ma>{I1}_{I3}{ALT} |
-<CCi_ma>{I3}_{I0}{ALT} |
-<CCi_ma>{I1}_{I4} |
-<CCi_ma>{I2}_{I3} |
-<CCi_ma>{I3}_{I2} |
-<CCi_ma>{I4}_{I0} {
-	  /* Invalid parameter in image-header keyword. */
-	  if (relax & WCSHDR_ALLIMG) {
-	    /* Will be flagged by <VALUE> as invalid. */
-	    sscanf(yytext, "%d_%d", &i, &m);
-	    keytype = IMGAXIS;
-	    BEGIN(VALUE);
-	
-	  } else {
-	    /* Pretend we don't recognize it. */
-	    BEGIN(DISCARD);
-	  }
-	}
-
-<CCi_ma>. {
-	  BEGIN(DISCARD);
-	}
-
-<iCCn_ma>{I1}_{I0}{ALT}" " |
-<iCCn_ma>{I1}_{I2}{ALT}    |
-<iCCn_ma>{I1}_{I3}         |
-<iCCn_ma>{I2}_{I0}{ALT}    |
-<iCCn_ma>{I2}_{I2}         |
-<iCCn_ma>{I3}_{I0}         |
-<TCCn_ma>{I1}_{I0}{ALT}" " |
-<TCCn_ma>{I1}_{I2}{ALT}    |
-<TCCn_ma>{I1}_{I3}         |
-<TCCn_ma>{I2}_{I0}{ALT}    |
-<TCCn_ma>{I2}_{I2}         |
-<TCCn_ma>{I3}_{I0} {
-	  if (relax & WCSHDR_LONGKEY) {
-	    WCSBTH_PUTBACK;
-	    BEGIN((YY_START == iCCn_ma) ? iCn_ma : TCn_ma);
-	
-	  } else if (relax & WCSHDR_reject) {
-	    errmsg = errtxt;
-	    sprintf(errmsg, "%s keyword is non-standard", extkey);
-	    BEGIN(ERROR);
-	
-	  } else {
-	    /* Pretend we don't recognize it. */
-	    BEGIN(DISCARD);
-	  }
-	}
-
-<iCCn_ma>. |
-<TCCn_ma>. {
-	  BEGIN(DISCARD);
-	}
-
-<iCn_ma>{I1}_{I0}{ALT}"  " |
-<iCn_ma>{I1}_{I2}{ALT}" "  |
-<iCn_ma>{I1}_{I3}{ALT}     |
-<iCn_ma>{I2}_{I0}{ALT}" "  |
-<iCn_ma>{I2}_{I2}{ALT}     |
-<iCn_ma>{I3}_{I0}{ALT}     |
-<TCn_ma>{I1}_{I0}{ALT}"  " |
-<TCn_ma>{I1}_{I2}{ALT}" "  |
-<TCn_ma>{I1}_{I3}{ALT}     |
-<TCn_ma>{I2}_{I0}{ALT}" "  |
-<TCn_ma>{I2}_{I2}{ALT}     |
-<TCn_ma>{I3}_{I0}{ALT} {
-	  sscanf(yytext, "%d_%d%c", &n, &m, &a);
-	  if (YY_START == TCn_ma) i = wcsbth_colax(*wcs, &alts, n, a);
-	  keytype = (YY_START == iCn_ma) ? BIMGARR : PIXLIST;
-	  BEGIN(VALUE);
-	}
-
-<iCn_ma>{I1}_{I4} |
-<iCn_ma>{I2}_{I3} |
-<iCn_ma>{I3}_{I2} |
-<iCn_ma>{I4}_{I0} |
-<TCn_ma>{I1}_{I4} |
-<TCn_ma>{I2}_{I3} |
-<TCn_ma>{I3}_{I2} |
-<TCn_ma>{I4}_{I0} {
-	  /* Invalid combinations will be flagged by <VALUE>. */
-	  sscanf(yytext, "%d_%d", &n, &m);
-	  a = ' ';
-	  if (YY_START == TCn_ma) i = wcsbth_colax(*wcs, &alts, n, a);
-	  keytype = (YY_START == iCn_ma) ? BIMGARR : PIXLIST;
-	  BEGIN(VALUE);
-	}
-
-<iCn_ma>. |
-<TCn_ma>. {
-	  BEGIN(DISCARD);
-	}
-
-<PROJPm>{I0}"  " {
-	  if (relax & WCSHDR_PROJPn) {
-	    sscanf(yytext, "%d", &m);
-	    i = 0;
-	    a = ' ';
-	    keytype = IMGAXIS;
-	    BEGIN(VALUE);
-	
-	  } else if (relax & WCSHDR_reject) {
-	    errmsg = "PROJPn keyword is defunct";
-	    BEGIN(ERROR);
-	
-	  } else {
-	    /* Pretend we don't recognize it. */
-	    BEGIN(DISCARD);
-	  }
-	}
-
-<PROJPm>. {
-	  BEGIN(DISCARD);
-	}
-
-<VALUE>=" "+ {
-	  /* Do checks on i, j, m, n, k. */
-	  if (!(keytype & keysel)) {
-	    /* Selection by keyword type. */
-	    BEGIN(DISCARD);
-	
-	  } else if (exclude[n] || exclude[k]) {
-	    /* One or other column is not selected. */
-	    if (k && (exclude[n] != exclude[k])) {
-	      /* For keywords such as TCn_ka, both columns must be excluded.
-	         User error, so return immediately. */
-	      yylex_destroy();
-	      return 3;
-	
-	    } else {
-	      BEGIN(DISCARD);
-	    }
-	
-	  } else if (i > 99 || j > 99 || m > 99 || n > 999 || k > 999) {
-	    if (relax & WCSHDR_reject) {
-	      errmsg = errtxt;
-	      if (i > 99 || j > 99) {
-	        sprintf(errmsg, "Axis number exceeds 99");
-	      } else if (m > 99) {
-	        sprintf(errmsg, "Parameter number exceeds 99");
-	      } else if (n > 999 || k > 999) {
-	        sprintf(errmsg, "Column number exceeds 999");
-	      }
-	      BEGIN(ERROR);
-	
-	    } else {
-	      /* Pretend we don't recognize it. */
-	      BEGIN(DISCARD);
-	    }
-	
-	  } else if (ipass == 2 && npass == 3 && (keytype & BINTAB)) {
-	    /* Skip keyvalues that won't be inherited. */
-	    BEGIN(FLUSH);
-	
-	  } else if (ipass == 3 && (keytype & IMGHEAD)) {
-	    /* IMGHEAD keytypes are always dealt with on the second pass. */
-	    BEGIN(FLUSH);
-	
-	  } else if (vptr) {
-	    alts.icol = 0;
-	    alts.ialt = 0;
-	    voff = (char *)vptr - (char *)(&wcstem);
-	
-	    if (valtype == INTEGER) {
-	      BEGIN(INTEGER_VAL);
-	    } else if (valtype == FLOAT) {
-	      BEGIN(FLOAT_VAL);
-	    } else if (valtype == STRING) {
-	      BEGIN(STRING_VAL);
-	    } else {
-	      errmsg = errtxt;
-	      sprintf(errmsg, "Internal parser ERROR, bad data type: %d",
-	        valtype);
-	      BEGIN(ERROR);
-	    }
-	
-	  } else {
-	    errmsg = "Internal parser ERROR, null pointer";
-	    BEGIN(ERROR);
-	  }
-	}
-
-<VALUE>. {
-	  errmsg = "Invalid KEYWORD = VALUE syntax";
-	  BEGIN(ERROR);
-	}
-
-<INTEGER_VAL>{INTEGER} {
-	  if (ipass == 1) {
-	    /* Do first-pass bookkeeping. */
-	    wcsbth_pass1(keytype, i, j, n, k, a, ptype, &alts);
-	    BEGIN(FLUSH);
-	
-	  } else {
-	    /* Update each coordinate representation. */
-	    while ((wcsp = wcsbth_idx(*wcs, &alts, keytype, n, a))) {
-	      wptr = (void *)((char *)wcsp + voff);
-	
-	      /* Read the keyvalue. */
-	      if (special) {
-	        special(wptr);
-	      } else {
-	        sscanf(yytext, "%d", (int *)wptr);
-	      }
-	    }
-	
-	    BEGIN(COMMENT);
-	  }
-	}
-
-<INTEGER_VAL>. {
-	  errmsg = "An integer value was expected";
-	  BEGIN(ERROR);
-	}
-
-<FLOAT_VAL>{FLOAT} {
-	  if (ipass == 1) {
-	    /* Do first-pass bookkeeping. */
-	    wcsbth_pass1(keytype, i, j, n, k, a, ptype, &alts);
-	    BEGIN(FLUSH);
-	
-	  } else {
-	    /* Update each coordinate representation. */
-	    while ((wcsp = wcsbth_idx(*wcs, &alts, keytype, n, a))) {
-	      wptr = (void *)((char *)wcsp + voff);
-	
-	      /* Apply keyword parameterization. */
-	      if (ptype == 'v') {
-	        ipx = wcsp->npv++;
-	        wcsp->pv[ipx].i = i;
-	        wcsp->pv[ipx].m = m;
-	        wptr = &(wcsp->pv[ipx].value);
-	
-	      } else if (j) {
-	        /* Is the de-reference necessary? */
-	        wptr = *((double **)wptr) + (i - 1)*(wcsp->naxis) + (j - 1);
-	
-	      } else if (i) {
-	        wptr = *((double **)wptr) + (i - 1);
-	      }
-	
-	      /* Read the keyvalue. */
-	      if (special) {
-	        special(wptr);
-	      } else {
-	        sscanf(yytext, "%lf", (double *)wptr);
-	      }
-	
-	      /* Flag the presence of PC, or CD and/or CROTA. */
-	      if (altlin) {
-	        wcsp->altlin |= altlin;
-	        altlin = 0;
-	      }
-	    }
-	
-	    BEGIN(COMMENT);
-	  }
-	}
-
-<FLOAT_VAL>. {
-	  errmsg = "A floating-point value was expected";
-	  BEGIN(ERROR);
-	}
-
-<STRING_VAL>{STRING} {
-	  if (ipass == 1) {
-	    /* Do first-pass bookkeeping. */
-	    wcsbth_pass1(keytype, i, j, n, k, a, ptype, &alts);
-	    BEGIN(FLUSH);
-	
-	  } else {
-	    /* Update each coordinate representation. */
-	    while ((wcsp = wcsbth_idx(*wcs, &alts, keytype, n, a))) {
-	      wptr = (void *)((char *)wcsp + voff);
-	
-	      /* Apply keyword parameterization. */
-	      if (ptype == 's') {
-	        ipx = wcsp->nps++;
-	        wcsp->ps[ipx].i = i;
-	        wcsp->ps[ipx].m = m;
-	        wptr = wcsp->ps[ipx].value;
-	
-	      } else if (j) {
-	        wptr = *((char (**)[72])wptr) +
-	                (i - 1)*(wcsp->naxis) + (j - 1);
-	
-	      } else if (i) {
-	        wptr = *((char (**)[72])wptr) + (i - 1);
-	      }
-	
-	      /* Read the keyvalue. */
-	      cptr = (char *)wptr;
-	      strcpy(cptr, yytext+1);
-	
-	      /* Squeeze out repeated quotes. */
-	      ix = 0;
-	      for (jx = 0; jx < 72; jx++) {
-	        if (ix < jx) {
-	          cptr[ix] = cptr[jx];
-	        }
-	
-	        if (cptr[jx] == '\0') {
-	          if (ix) cptr[ix-1] = '\0';
-	          break;
-	        } else if (cptr[jx] == '\'' && cptr[jx+1] == '\'') {
-	          jx++;
-	        }
-	
-	        ix++;
-	      }
-	    }
-	
-	    BEGIN(COMMENT);
-	  }
-	}
-
-<STRING_VAL>. {
-	  errmsg = "A string value was expected";
-	  BEGIN(ERROR);
-	}
-
-<COMMENT>" "*\/.* |
-<COMMENT>" "* {
-	  BEGIN(FLUSH);
-	}
-
-<COMMENT>. {
-	  errmsg = "Malformed keycomment";
-	  BEGIN(ERROR);
-	}
-
-<DISCARD>.* {
-	  if (ipass == npass) {
-	    if (ctrl < 0) {
-	      /* Preserve discards. */
-	      if (hptr < wcsbth_hdr-80) {
-	        strncpy(hptr, wcsbth_hdr-80, 80);
-	      }
-	      hptr += 80;
-	
-	    } else if (ctrl > 2) {
-	      fprintf(stderr, "%.80s\n  Discarded.\n", wcsbth_hdr-80);
-	    }
-	  }
-	
-	  BEGIN(FLUSH);
-	}
-
-<ERROR>.* {
-	  (*nreject)++;
-	  if (ipass == npass) {
-	    if (ctrl == -1) {
-	      if (hptr < wcsbth_hdr-80) {
-	        /* Preserve rejects. */
-	        strncpy(hptr, wcsbth_hdr-80, 80);
-	      }
-	      hptr += 80;
-	    }
-	
-	    if (abs(ctrl) > 1) {
-	      fprintf(stderr, "%.80s\n%4d: %s.\n", wcsbth_hdr-80, *nreject,
-	        errmsg);
-	    }
-	  }
-	
-	  BEGIN(FLUSH);
-	}
-
-<FLUSH>.*\n {
-	  /* Throw away the rest of the line and reset for the next one. */
-	  i = j = 0;
-	  n = k = 0;
-	  m = 0;
-	  a = ' ';
-	
-	  keytype =  0;
-	  valtype = -1;
-	  vptr    = 0x0;
-	
-	  altlin = 0;
-	  ptype  = ' ';
-	  special = 0x0;
-	  BEGIN(INITIAL);
-	}
-
-<<EOF>>	 {
-	  /* End-of-input. */
-	  if (ipass == 1) {
-	    if ((status = wcsbth_init1(&alts, nwcs, wcs)) || *nwcs == 0) {
-	      yylex_destroy();
-	      return status;
-	    }
-
-	    if (alts.imgherit) npass = 3;
-	
-	    if (abs(ctrl) > 2) {
-	      if (*nwcs == 1) {
-	        fprintf(stderr, "Found one coordinate representation.\n");
-	      } else {
-	        fprintf(stderr, "Found %d coordinate representations.\n",
-	          *nwcs);
-	      }
-	    }
-	  }
-	
-	  if (ipass++ < npass) {
-	    wcsbth_hdr = header;
-	    wcsbth_nkeyrec = nkeyrec;
-	    *nreject = 0;
-	
-	    i = j = 0;
-	    k = n = 0;
-	    m = 0;
-	    a = ' ';
-	
-	    keytype =  0;
-	    valtype = -1;
-	    vptr    = 0x0;
-	
-	    altlin = 0;
-	    ptype  = ' ';
-	    special = 0x0;
-	
-	    yyrestart(yyin);
-	
-	  } else {
-	    yylex_destroy();
-	
-	    if (ctrl < 0) {
-	      *hptr = '\0';
-	    } else if (ctrl == 1) {
-	      fprintf(stderr, "%d WCS keyrecords were rejected.\n", *nreject);
-	    }
-	
-	    return wcsbth_final(&alts, nwcs, wcs);
-	  }
-	}
-
-%%
-
-/*----------------------------------------------------------------------------
-* Perform first-pass tasks:
-*
-* 1) Count the number of coordinate axes in each of the 27 possible alternate
-*    image-header coordinate representations.  Also count the number of PVi_ma
-*    and PSi_ma keywords in each representation.
-*
-* 2) Determine the number of binary table columns that have an image array
-*    with a coordinate representation (up to 999), and count the number of
-*    coordinate axes in each of the 27 possible alternates.  Also count the
-*    number of iVn_ma and iSn_ma keywords in each representation.
-*
-* 3) Determine the number of alternate pixel list coordinate representations
-*    (up to 27) and the table columns associated with each.  Also count the
-*    number of TVn_ma and TSn_ma keywords in each representation.
-*
-* In the first pass alts->arridx[icol][27] is used to determine the number of
-* axes in each of 27 possible image-header coordinate descriptions (icol == 0)
-* and each of the 27 possible coordinate representations for an image array in
-* each column.
-*
-* The elements of alts->pixlist[icol] are used as bit arrays to flag which of
-* the 27 possible pixel list coordinate representations are associated with
-* each table column.
-*---------------------------------------------------------------------------*/
-
-int wcsbth_pass1(
-  int keytype,
-  int i,
-  int j,
-  int n,
-  int k,
-  char a,
-  char ptype,
-  struct wcsbth_alts *alts)
-
-{
-  int ialt, icol, mask, ncol;
-
-  if (a == 0) {
-    /* Keywords such as DATE-OBS go along for the ride. */
-    return 0;
-  }
-
-  ncol = alts->ncol;
-
-  /* Do we need to allocate memory for alts? */
-  if (alts->arridx == 0x0) {
-    if (ncol == 0) {
-      /* Can only happen if TFIELDS is missing or out-of-sequence.  If n and
-         k are both zero then we may be processing an image header so leave
-         ncol alone - the array will be realloc'd later if required. */
-      if (n || k) {
-        /* The header is mangled, assume the worst. */
-        ncol = 999;
-      }
-    }
-
-    if (!(alts->arridx  =  calloc((1 + ncol)*27, sizeof(short int))) ||
-        !(alts->npv     =  calloc((1 + ncol)*27, sizeof(unsigned char)))  ||
-        !(alts->nps     =  calloc((1 + ncol)*27, sizeof(unsigned char)))  ||
-        !(alts->pixlist =  calloc((1 + ncol),    sizeof(unsigned int)))) {
-      if (alts->arridx)  free(alts->arridx);
-      if (alts->npv)     free(alts->npv);
-      if (alts->nps)     free(alts->nps);
-      if (alts->pixlist) free(alts->pixlist);
-      return 2;
-    }
-
-    alts->ncol = ncol;
-
-  } else if (n > ncol || k > ncol) {
-    /* Can only happen if TFIELDS or the WCS keyword is wrong; carry on. */
-    ncol = 999;
-    if (!(alts->arridx  = realloc(alts->arridx,
-                                    27*(1 + ncol)*sizeof(short int))) ||
-        !(alts->npv     = realloc(alts->npv,
-                                    27*(1 + ncol)*sizeof(unsigned char)))  ||
-        !(alts->nps     = realloc(alts->nps,
-                                    27*(1 + ncol)*sizeof(unsigned char)))  ||
-        !(alts->pixlist = realloc(alts->pixlist,
-                                       (1 + ncol)*sizeof(unsigned int)))) {
-      if (alts->arridx)  free(alts->arridx);
-      if (alts->npv)     free(alts->npv);
-      if (alts->nps)     free(alts->nps);
-      if (alts->pixlist) free(alts->pixlist);
-      return 2;
-    }
-
-    /* Since realloc() doesn't initialize the extra memory. */
-    for (icol = (1 + alts->ncol); icol < (1 + ncol); icol++) {
-      for (ialt = 0; ialt < 27; ialt++) {
-        alts->arridx[icol][ialt] = 0;
-        alts->npv[icol][ialt] = 0;
-        alts->nps[icol][ialt] = 0;
-        alts->pixlist[icol]   = 0;
-      }
-    }
-
-    alts->ncol = ncol;
-  }
-
-  ialt = 0;
-  if (a != ' ') {
-    ialt = a - 'A' + 1;
-  }
-
-  /* A BINTAB keytype such as LONPna, in conjunction with an IMGAXIS keytype
-     causes a table column to be recognized as an image array. */
-  if (keytype & IMGHEAD || keytype & BIMGARR) {
-    /* n == 0 is expected for IMGHEAD keywords. */
-    if (i == 0 && j == 0) {
-      if (alts->arridx[n][ialt] == 0) {
-        /* Flag that an auxiliary keyword was seen. */
-        alts->arridx[n][ialt] = -1;
-      }
-
-    } else {
-      /* Record the maximum axis number found. */
-      if (alts->arridx[n][ialt] < i) {
-        alts->arridx[n][ialt] = i;
-      }
-
-      if (alts->arridx[n][ialt] < j) {
-        alts->arridx[n][ialt] = j;
-      }
-    }
-
-    if (ptype == 'v') {
-      alts->npv[n][ialt]++;
-    } else if (ptype == 's') {
-      alts->nps[n][ialt]++;
-    }
-  }
-
-  /* BINTAB keytypes, which apply both to pixel lists as well as binary table
-     image arrays, never contribute to recognizing a table column as a pixel
-     list axis.  A PIXLIST keytype is required for that. */
-  if (keytype == PIXLIST) {
-    mask = 1 << ialt;
-
-    /* n > 0 for PIXLIST keytypes. */
-    alts->pixlist[n] |= mask;
-    if (k) alts->pixlist[k] |= mask;
-
-    /* Used as a flag over all columns. */
-    alts->pixlist[0] |= mask;
-
-    if (ptype == 'v') {
-      alts->pixnpv[ialt]++;
-    } else if (ptype == 's') {
-      alts->pixnps[ialt]++;
-    }
-  }
-
-  return 0;
-}
-
-
-/*----------------------------------------------------------------------------
-* Perform initializations at the end of the first pass:
-*
-* 1) Determine the required number of wcsprm structs, allocate memory for
-*    an array of them and initialize each one.
-*---------------------------------------------------------------------------*/
-
-int wcsbth_init1(
-  struct wcsbth_alts *alts,
-  int *nwcs,
-  struct wcsprm **wcs)
-
-{
-  int ialt, icol, inherit[27], ix, mask, ncol, npsmax, npvmax, status = 0;
-  struct wcsprm *wcsp;
-
-
-  if (alts->arridx == 0x0) {
-    *nwcs = 0;
-    return 0;
-  }
-
-  /* Determine the number of axes in each pixel list representation. */
-  ncol = alts->ncol;
-  for (ialt = 0, mask = 1; ialt < 27; ialt++, mask <<= 1) {
-    alts->pixidx[ialt] = 0;
-
-    if (alts->pixlist[0] | mask) {
-      for (icol = 1; icol <= ncol; icol++) {
-        if (alts->pixlist[icol] & mask) {
-          alts->pixidx[ialt]++;
-        }
-      }
-    }
-  }
-
-  /* Find the total number of coordinate representations. */
-  *nwcs = 0;
-  alts->imgherit = 0;
-  for (ialt = 0; ialt < 27; ialt++) {
-    inherit[ialt] = 0;
-
-    for (icol = 1; icol <= ncol; icol++) {
-      if (alts->arridx[icol][ialt] < 0) {
-        /* No BIMGARR keytype but there's at least one BINTAB. */
-        if (alts->arridx[0][ialt] > 0) {
-          /* There is an IMGAXIS keytype that we will inherit, so count this
-             representation. */
-          alts->arridx[icol][ialt] = alts->arridx[0][ialt];
-        } else {
-          alts->arridx[icol][ialt] = 0;
-        }
-      }
-
-      if (alts->arridx[icol][ialt]) {
-        if (alts->arridx[0][ialt]) {
-          /* All IMGHEAD keywords are inherited for this ialt. */
-          inherit[ialt] = 1;
-
-          if (alts->arridx[icol][ialt] < alts->arridx[0][ialt]) {
-            /* The extra axes are also inherited. */
-            alts->arridx[icol][ialt] = alts->arridx[0][ialt];
-          }
-        }
-
-        (*nwcs)++;
-      }
-    }
-
-    /* Count every "a" found in any IMGHEAD keyword... */
-    if (alts->arridx[0][ialt]) {
-      if (inherit[ialt]) {
-        /* ...but not if the IMGHEAD keywords will be inherited. */
-        alts->arridx[0][ialt] = 0;
-        alts->imgherit = 1;
-      } else {
-        (*nwcs)++;
-      }
-    }
-
-    /* We need a struct for every "a" found in a PIXLIST keyword. */
-    if (alts->pixidx[ialt]) {
-      (*nwcs)++;
-    }
-  }
-
-
-  if (*nwcs) {
-    /* Allocate memory for the required number of wcsprm structs. */
-    if (!(*wcs = calloc(*nwcs, sizeof(struct wcsprm)))) {
-      return 2;
-    }
-
-    /* Record the current values of NPVMAX and NPSMAX. */
-    npvmax = wcsnpv(-1);
-    npsmax = wcsnps(-1);
-
-    /* Initialize each wcsprm struct. */
-    wcsp = *wcs;
-    *nwcs = 0;
-    for (icol = 0; icol <= ncol; icol++) {
-      for (ialt = 0; ialt < 27; ialt++) {
-        if (alts->arridx[icol][ialt]) {
-          /* Image-header representations that are not for inheritance
-             (icol == 0) or binary table image array representations. */
-          wcsp->flag = -1;
-          wcsnpv(alts->npv[icol][ialt]);
-          wcsnps(alts->nps[icol][ialt]);
-          if ((status = wcsini(1, (int)(alts->arridx[icol][ialt]), wcsp))) {
-            wcsvfree(nwcs, wcs);
-            break;
-          }
-
-          /* Record the alternate version code. */
-          if (ialt) {
-            wcsp->alt[0] = 'A' + ialt - 1;
-          }
-
-          /* Record the table column number. */
-          wcsp->colnum = icol;
-
-          /* On the second pass alts->arridx[icol][27] indexes the array of
-             wcsprm structs. */
-          alts->arridx[icol][ialt] = (*nwcs)++;
-
-          wcsp++;
-
-        } else {
-          /* Signal that this column has no WCS for this "a". */
-          alts->arridx[icol][ialt] = -1;
-        }
-      }
-    }
-
-    for (ialt = 0; ialt < 27; ialt++) {
-      if (alts->pixidx[ialt]) {
-        /* Pixel lists representations. */
-        wcsp->flag = -1;
-        wcsnpv(alts->pixnpv[ialt]);
-        wcsnps(alts->pixnps[ialt]);
-        if ((status = wcsini(1, (int)(alts->pixidx[ialt]), wcsp))) {
-          wcsvfree(nwcs, wcs);
-          break;
-        }
-
-        /* Record the alternate version code. */
-        if (ialt) {
-          wcsp->alt[0] = 'A' + ialt - 1;
-        }
-
-        /* Record the pixel list column numbers. */
-        mask = (1 << ialt);
-        for (icol = 1, ix = 0; icol <= ncol; icol++) {
-          if (alts->pixlist[icol] & mask) {
-            wcsp->colax[ix++] = icol;
-          }
-        }
-
-        /* alts->pixidx[] indexes the array of wcsprm structs. */
-        alts->pixidx[ialt] = (*nwcs)++;
-
-        wcsp++;
-
-      } else {
-        /* Signal that this column is not a pixel list axis for this "a". */
-        alts->pixidx[ialt] = -1;
-      }
-    }
-
-    /* Restore the original values of NPVMAX and NPSMAX. */
-    wcsnpv(npvmax);
-    wcsnps(npsmax);
-  }
-
-  return status;
-}
-
-
-/*----------------------------------------------------------------------------
-* Return a pointer to the next wcsprm struct for a particular column number
-* and alternate.
-*---------------------------------------------------------------------------*/
-
-struct wcsprm *wcsbth_idx(
-  struct wcsprm *wcs,
-  struct wcsbth_alts *alts,
-  int  keytype,
-  int  n,
-  char a)
-
-{
-  const char as[] = " ABCDEFGHIJKLMNOPQRSTUVWXYZ";
-  int iwcs;
-
-  if (!wcs) return 0x0;
-
-  iwcs = -1;
-  for (; iwcs < 0 && alts->ialt < 27; alts->ialt++) {
-    /* Note that a == 0 applies to every alternate, otherwise this
-       loop simply determines the appropriate value of alts->ialt. */
-    if (a && a != as[alts->ialt]) continue;
-
-    if (keytype & (IMGHEAD | BIMGARR)) {
-      for (; iwcs < 0 && alts->icol <= alts->ncol; alts->icol++) {
-        /* Image header keywords, n == 0, apply to all columns, otherwise this
-           loop simply determines the appropriate value of alts->icol. */
-        if (n && n != alts->icol) continue;
-        iwcs = alts->arridx[alts->icol][alts->ialt];
-      }
-
-      /* Break out of the loop to stop alts->ialt from being incremented. */
-      if (iwcs >= 0) break;
-
-      /* Start from scratch for the next alts->ialt. */
-      alts->icol = 0;
-    }
-
-    if (keytype & (IMGAUX | PIXLIST)) {
-      iwcs = alts->pixidx[alts->ialt];
-    }
-  }
-
-  return (iwcs >= 0) ? (wcs + iwcs) : 0x0;
-}
-
-
-/*----------------------------------------------------------------------------
-* Return the axis number associated with the specified column number in a
-* particular pixel list coordinate representation.
-*---------------------------------------------------------------------------*/
-
-int wcsbth_colax(
-  struct wcsprm *wcs,
-  struct wcsbth_alts *alts,
-  int n,
-  char a)
-
-{
-  int ix;
-  struct wcsprm *wcsp;
-
-  if (!wcs) return 0;
-
-  wcsp = wcs;
-  if (a != ' ') {
-    wcsp += alts->pixidx[a-'A'+1];
-  }
-
-  for (ix = 0; ix < wcsp->naxis; ix++) {
-    if (wcsp->colax[ix] == n) {
-      return ++ix;
-    }
-  }
-
-  return 0;
-}
-
-
-/*----------------------------------------------------------------------------
-* Interpret EPOCH keywords.
-*---------------------------------------------------------------------------*/
-
-int wcsbth_epoch(void *wptr)
-
-{
-  double *equinox;
-
-  /* If EQUINOXa is currently undefined then set it from EPOCHa. */
-  equinox = (double *)wptr;
-  if (undefined(*equinox)) {
-    sscanf(yytext, "%lf", equinox);
-  }
-
-  return 0;
-}
-
-
-/*----------------------------------------------------------------------------
-* Interpret VSOURCE keywords.
-*---------------------------------------------------------------------------*/
-
-int wcsbth_vsource(void *wptr)
-
-{
-  double beta, c = 299792458.0, vsource, *zsource;
-
-  /* If ZSOURCEa is currently undefined then set it from VSOURCEa. */
-  zsource = (double *)wptr;
-  if (undefined(*zsource)) {
-    sscanf(yytext, "%lf", &vsource);
-
-    /* Convert relativistic Doppler velocity to redshift. */
-    beta = vsource/c;
-    *zsource = (1.0 + beta)/sqrt(1.0 - beta*beta) - 1.0;
-  }
-
-  return 0;
-}
-
-
-/*----------------------------------------------------------------------------
-* Tie up loose ends.
-*---------------------------------------------------------------------------*/
-
-int wcsbth_final(
-  struct wcsbth_alts *alts,
-  int *nwcs,
-  struct wcsprm **wcs)
-
-{
-  int ialt, status;
-
-  if (alts->arridx)  free(alts->arridx);
-  if (alts->npv)     free(alts->npv);
-  if (alts->nps)     free(alts->nps);
-  if (alts->pixlist) free(alts->pixlist);
-
-  for (ialt = 0; ialt < *nwcs; ialt++) {
-    /* Interpret -TAB header keywords. */
-    if ((status = wcstab(*wcs+ialt))) {
-       wcsvfree(nwcs, wcs);
-       return status;
-    }
-  }
-
-  return 0;
-}
diff --git a/astropy/wcs/src/wcslib/C/wcserr.c b/astropy/wcs/src/wcslib/C/wcserr.c
deleted file mode 100644
index abee9ea..0000000
--- a/astropy/wcs/src/wcslib/C/wcserr.c
+++ /dev/null
@@ -1,160 +0,0 @@
-/*============================================================================
-
-  WCSLIB 4.10 - an implementation of the FITS WCS standard.
-  Copyright (C) 1995-2012, Mark Calabretta
-
-  This file is part of WCSLIB.
-
-  WCSLIB is free software: you can redistribute it and/or modify it under the
-  terms of the GNU Lesser General Public License as published by the Free
-  Software Foundation, either version 3 of the License, or (at your option)
-  any later version.
-
-  WCSLIB 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 Lesser General Public License for
-  more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with WCSLIB.  If not, see <http://www.gnu.org/licenses/>.
-
-  Correspondence concerning WCSLIB may be directed to:
-    Internet email: mcalabre at atnf.csiro.au
-    Postal address: Dr. Mark Calabretta
-                    Australia Telescope National Facility, CSIRO
-                    PO Box 76
-                    Epping NSW 1710
-                    AUSTRALIA
-
-  Author: Mark Calabretta, Australia Telescope National Facility
-  Module author: Michael Droettboom
-  http://www.atnf.csiro.au/~mcalabre/index.html
-  $Id: wcserr.c,v 4.10 2012/02/05 23:41:44 cal103 Exp $
-*===========================================================================*/
-
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "wcserr.h"
-#include "wcsprintf.h"
-
-static int wcserr_enabled = 0;
-
-/*--------------------------------------------------------------------------*/
-
-int wcserr_enable(int enable)
-
-{
-  return wcserr_enabled = (enable ? 1 : 0);
-}
-
-/*--------------------------------------------------------------------------*/
-
-int wcserr_prt(
-  const struct wcserr *err,
-  const char *prefix)
-
-{
-  if (!wcserr_enabled) {
-    wcsprintf("Error messaging is not enabled, use wcserr_enable().\n");
-    return 2;
-  }
-
-  if (err == 0x0) {
-    return 0;
-  }
-
-  if (err->status) {
-    if (prefix == 0x0) prefix = "";
-
-    if (err->status > 0) {
-      wcsprintf("%sERROR %d in %s() at line %d of file %s:\n%s%s.\n",
-        prefix, err->status, err->function, err->line_no, err->file, prefix,
-        err->msg);
-    } else {
-      /* An informative message only. */
-      wcsprintf("%sINFORMATIVE message from %s() at line %d of file "
-        "%s:\n%s%s.\n", prefix, err->function, err->line_no, err->file,
-        prefix, err->msg);
-    }
-  }
-
-  return 0;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int wcserr_clear(
-  struct wcserr **err)
-
-{
-  if (*err) free(*err);
-  *err = 0x0;
-
-  return 0;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int wcserr_set(
-  struct wcserr **err,
-  int status,
-  const char *function,
-  const char *file,
-  int line_no,
-  const char *format,
-  ...)
-
-{
-  va_list argp;
-
-  if (!wcserr_enabled) return status;
-
-  if (err == 0x0) {
-    return status;
-  }
-
-  if (status) {
-    if (*err == 0x0) {
-      *err = calloc(1, sizeof(struct wcserr));
-    }
-
-    (*err)->status   = status;
-    (*err)->function = function;
-    (*err)->file     = file;
-    (*err)->line_no  = line_no;
-
-    va_start(argp, format);
-    vsnprintf((*err)->msg, WCSERR_MSG_LENGTH, format, argp);
-    va_end(argp);
-
-  } else {
-    if (*err) free(*err);
-    *err = 0x0;
-  }
-
-  return status;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int wcserr_copy(
-  const struct wcserr *src,
-  struct wcserr *dst)
-
-{
-  if (src == 0x0) {
-    if (dst) {
-      memset(dst, 0, sizeof(struct wcserr));
-    }
-    return 0;
-  }
-
-  if (dst) {
-    memcpy(dst, src, sizeof(struct wcserr));
-  }
-
-  return src->status;
-}
diff --git a/astropy/wcs/src/wcslib/C/wcserr.h b/astropy/wcs/src/wcslib/C/wcserr.h
deleted file mode 100644
index a5bce0c..0000000
--- a/astropy/wcs/src/wcslib/C/wcserr.h
+++ /dev/null
@@ -1,251 +0,0 @@
-/*============================================================================
-
-  WCSLIB 4.10 - an implementation of the FITS WCS standard.
-  Copyright (C) 1995-2012, Mark Calabretta
-
-  This file is part of WCSLIB.
-
-  WCSLIB is free software: you can redistribute it and/or modify it under the
-  terms of the GNU Lesser General Public License as published by the Free
-  Software Foundation, either version 3 of the License, or (at your option)
-  any later version.
-
-  WCSLIB 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 Lesser General Public License for
-  more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with WCSLIB.  If not, see <http://www.gnu.org/licenses/>.
-
-  Correspondence concerning WCSLIB may be directed to:
-    Internet email: mcalabre at atnf.csiro.au
-    Postal address: Dr. Mark Calabretta
-                    Australia Telescope National Facility, CSIRO
-                    PO Box 76
-                    Epping NSW 1710
-                    AUSTRALIA
-
-  Author: Mark Calabretta, Australia Telescope National Facility
-  Module author: Michael Droettboom
-  http://www.atnf.csiro.au/~mcalabre/index.html
-  $Id: wcserr.h,v 4.10 2012/02/05 23:41:44 cal103 Exp $
-*=============================================================================
-*
-* Summary of the wcserr routines
-* ------------------------------
-* Most of the structs in WCSLIB contain a pointer to a wcserr struct as a
-* member.  Functions in WCSLIB that return an error status code can also
-* allocate and set a detailed error message in this struct which also
-* identifies the function, source file, and line number where the error
-* occurred.
-*
-* For example:
-*
-=     struct prjprm prj;
-=     wcserr_enable(1);
-=     if (prjini(&prj)) {
-=       // Print the error message to stderr.
-=       wcsprintf_set(stderr);
-=       wcserr_prt(prj.err, 0x0);
-=     }
-*
-* A number of utility functions used in managing the wcserr struct are for
-* internal use only.  They are documented here solely as an aid to
-* understanding the code.  They are not intended for external use - the API
-* may change without notice!
-*
-*
-* wcserr struct - Error message handling
-* --------------------------------------
-* The wcserr struct contains the numeric error code, a textual description of
-* the error, and information about the function, source file, and line number
-* where the error was generated.
-*
-*   int status
-*     Numeric status code associated with the error, the meaning of which
-*     depends on the function that generated it.  See the documentation for
-*     the particular function.
-*
-*   int line_no
-*     Line number where the error occurred as given by the __LINE__
-*     preprocessor macro.
-*
-*   const char *function
-*     Name of the function where the error occurred.
-*
-*   const char *file
-*     Name of the source file where the error occurred as given by the
-*     __FILE__ preprocessor macro.
-*
-*   char msg[WCSERR_MSG_LENGTH]
-*     Informative error message.
-*
-*
-* wcserr_enable() - Enable/disable error messaging
-* ------------------------------------------------
-* wcserr_enable() enables or disables wcserr error messaging.  By default it
-* is disabled.
-*
-* PLEASE NOTE: This function is not thread-safe.
-*
-* Given:
-*   enable    int       If true (non-zero), enable error messaging, else
-*                       disable it.
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Error messaging is disabled.
-*                         1: Error messaging is enabled.
-*
-*
-* wcserr_prt() - Print a wcserr struct
-* ------------------------------------
-* wcserr_prt() prints the error message (if any) contained in a wcserr struct.
-* It uses the wcsprintf() functions.
-*
-* Given:
-*   err       const struct wcserr*
-*                       The error object.  If NULL, nothing is printed.
-*
-*   prefix    const char *
-*                       If non-NULL, each output line will be prefixed with
-*                       this string.
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         2: Error messaging is not enabled.
-*
-*
-* wcserr_clear() - Clear a wcserr struct
-* --------------------------------------
-* wcserr_clear() clears the error (if any) contained in a wcserr struct.
-*
-* Given and returned:
-*   err       struct wcserr**
-*                       The error object.  If NULL, nothing is done.  Set to
-*                       NULL on return.
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*
-*
-* wcserr_set() - Fill in the contents of an error object
-* ------------------------------------------------------
-* INTERNAL USE ONLY.
-*
-* wcserr_set() fills a wcserr struct with information about an error.
-*
-* A convenience macro, WCSERR_SET, provides the source file and line number
-* information automatically.
-*
-* Given and returned:
-*   err       struct wcserr**
-*                       Error object.
-*
-*                       If err is NULL, returns the status code given without
-*                       setting an error message.
-*
-*                       If *err is NULL, allocates memory for a wcserr struct
-*                       (provided that status is non-zero).
-*
-* Given:
-*   status    int       Numeric status code to set.  If 0, then *err will be
-*                       deleted and *err will be returned as NULL.
-*
-*   function  const char *
-*                       Name of the function generating the error.  This
-*                       must point to a constant string, i.e. in the
-*                       initialized read-only data section ("data") of the
-*                       executable.
-*
-*   file      const char *
-*                       Name of the source file generating the error.  This
-*                       must point to a constant string, i.e. in the
-*                       initialized read-only data section ("data") of the
-*                       executable such as given by the __FILE__ preprocessor
-*                       macro.
-*
-*   line_no   int       Line number in the source file generating the error
-*                       such as given by the __LINE__ preprocessor macro.
-*
-*   format    const char *
-*                       Format string of the error message.  May contain
-*                       printf-style %-formatting codes.
-*
-*   ...       mixed     The remaining variable arguments are applied (like
-*                       printf) to the format string to generate the error
-*                       message.
-*
-* Function return value:
-*             int       The status return code passed in.
-*
-*
-* wcserr_copy() - Copy an error object
-* ------------------------------------
-* INTERNAL USE ONLY.
-*
-* wcserr_copy() copies one error object to another.  Use of this function
-* should be avoided in general since the function, source file, and line
-* number information copied to the destination may lose its context.
-*
-* Given:
-*   src       const struct wcserr*
-*                       Source error object.  If src is NULL, dst is cleared.
-*
-* Returned:
-*   dst       struct wcserr*
-*                       Destination error object.  If NULL, no copy is made.
-*
-* Function return value:
-*             int       Numeric status code of the source error object.
-*
-*
-* WCSERR_SET() macro - Fill in the contents of an error object
-* ------------------------------------------------------------
-* INTERNAL USE ONLY.
-*
-* WCSERR_SET() is a preprocessor macro that helps to fill in the argument list
-* of wcserr_set().  It takes status as an argument of its own and provides the
-* name of the source file and the line number at the point where invoked.  It
-* assumes that the err and function arguments of wcserr_set() will be provided
-* by variables of the same names.
-*
-*===========================================================================*/
-
-#ifndef WCSLIB_WCSERR
-#define WCSLIB_WCSERR
-
-#define WCSERR_MSG_LENGTH 160
-
-struct wcserr {
-  int  status;			/* Status code for the error.               */
-  int  line_no;			/* Line number where the error occurred.    */
-  const char *function;		/* Function name.                           */
-  const char *file;		/* Source file name.                        */
-  char msg[WCSERR_MSG_LENGTH];	/* Informative error message.               */
-};
-
-/* Size of the wcserr struct in int units, used by the Fortran wrappers. */
-#define ERRLEN (sizeof(struct wcserr)/sizeof(int))
-
-int wcserr_enable(int enable);
-
-int wcserr_prt(const struct wcserr *err, const char *prefix);
-
-int wcserr_clear(struct wcserr **err);
-
-
-/* INTERNAL USE ONLY -------------------------------------------------------*/
-
-int wcserr_set(struct wcserr **err, int status, const char *function,
-  const char *file, int line_no, const char *format, ...);
-
-int wcserr_copy(const struct wcserr *src, struct wcserr *dst);
-
-/* Convenience macro for invoking wcserr_set(). */
-#define WCSERR_SET(status) err, status, function, __FILE__, __LINE__
-
-#endif /* WSCLIB_WCSERR */
diff --git a/astropy/wcs/src/wcslib/C/wcsfix.c b/astropy/wcs/src/wcslib/C/wcsfix.c
deleted file mode 100644
index 9199682..0000000
--- a/astropy/wcs/src/wcslib/C/wcsfix.c
+++ /dev/null
@@ -1,726 +0,0 @@
-/*============================================================================
-
-  WCSLIB 4.10 - an implementation of the FITS WCS standard.
-  Copyright (C) 1995-2012, Mark Calabretta
-
-  This file is part of WCSLIB.
-
-  WCSLIB is free software: you can redistribute it and/or modify it under the
-  terms of the GNU Lesser General Public License as published by the Free
-  Software Foundation, either version 3 of the License, or (at your option)
-  any later version.
-
-  WCSLIB 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 Lesser General Public License for
-  more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with WCSLIB.  If not, see <http://www.gnu.org/licenses/>.
-
-  Correspondence concerning WCSLIB may be directed to:
-    Internet email: mcalabre at atnf.csiro.au
-    Postal address: Dr. Mark Calabretta
-                    Australia Telescope National Facility, CSIRO
-                    PO Box 76
-                    Epping NSW 1710
-                    AUSTRALIA
-
-  Author: Mark Calabretta, Australia Telescope National Facility
-  http://www.atnf.csiro.au/~mcalabre/index.html
-  $Id: wcsfix.c,v 4.10 2012/02/05 23:41:44 cal103 Exp $
-*===========================================================================*/
-
-#include <math.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "wcserr.h"
-#include "wcsmath.h"
-#include "wcsutil.h"
-#include "sph.h"
-#include "wcs.h"
-#include "wcsunits.h"
-#include "wcsfix.h"
-
-extern const int WCSSET;
-
-/* Maximum number of coordinate axes that can be handled. */
-#define NMAX 16
-
-/* Map status return value to message. */
-const char *wcsfix_errmsg[] = {
-  "Success",
-  "Null wcsprm pointer passed",
-  "Memory allocation failed",
-  "Linear transformation matrix is singular",
-  "Inconsistent or unrecognized coordinate axis types",
-  "Invalid parameter value",
-  "Invalid coordinate transformation parameters",
-  "Ill-conditioned coordinate transformation parameters",
-  "All of the corner pixel coordinates are invalid",
-  "Could not determine reference pixel coordinate",
-  "Could not determine reference pixel value"};
-
-/* Convenience macro for invoking wcserr_set(). */
-#define WCSFIX_ERRMSG(status) WCSERR_SET(status), wcsfix_errmsg[status]
-
-/*--------------------------------------------------------------------------*/
-
-int wcsfix(int ctrl, const int naxis[], struct wcsprm *wcs, int stat[])
-
-{
-  int status = 0;
-
-  if ((stat[CDFIX] = cdfix(wcs)) > 0) {
-    status = 1;
-  }
-
-  if ((stat[DATFIX] = datfix(wcs)) > 0) {
-    status = 1;
-  }
-
-  if ((stat[UNITFIX] = unitfix(ctrl, wcs)) > 0) {
-    status = 1;
-  }
-
-  if ((stat[SPCFIX] = spcfix(wcs)) > 0) {
-    status = 1;
-  }
-
-  if ((stat[CELFIX] = celfix(wcs)) > 0) {
-    status = 1;
-  }
-
-  if ((stat[CYLFIX] = cylfix(naxis, wcs)) > 0) {
-    status = 1;
-  }
-
-  return status;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int wcsfixi(int ctrl, const int naxis[], struct wcsprm *wcs, int stat[],
-            struct wcserr info[])
-
-{
-  int ifix, status = 0;
-  struct wcserr err;
-
-  /* Handling the status values returned from the sub-fixers is trickier than
-  it might seem, especially considering that wcs->err may contain an error
-  status on input which should be preserved if no translation errors occur.
-  The simplest way seems to be to save a copy of wcs->err and clear it before
-  each sub-fixer.  The last real error to occur, excluding informative
-  messages, is the one returned.
-
-  To get informative messages from spcfix() it must precede celfix() and
-  cylfix().  The latter call wcsset() which also translates AIPS-convention
-  spectral axes. */
-  wcserr_copy(wcs->err, &err);
-
-  for (ifix = CDFIX; ifix < NWCSFIX; ifix++) {
-    /* Clear (delete) wcs->err. */
-    wcserr_clear(&(wcs->err));
-
-    switch (ifix) {
-    case CDFIX:
-      stat[ifix] = cdfix(wcs);
-      break;
-    case DATFIX:
-      stat[ifix] = datfix(wcs);
-      break;
-    case UNITFIX:
-      stat[ifix] = unitfix(ctrl, wcs);
-      break;
-    case SPCFIX:
-      stat[ifix] = spcfix(wcs);
-      break;
-    case CELFIX:
-      stat[ifix] = celfix(wcs);
-      break;
-    case CYLFIX:
-      stat[ifix] = cylfix(naxis, wcs);
-      break;
-    default:
-      continue;
-    }
-
-    if (stat[ifix] == FIXERR_NO_CHANGE) {
-      /* No change => no message. */
-      wcserr_copy(0x0, info+ifix);
-
-    } else if (stat[ifix] == FIXERR_SUCCESS) {
-      /* Successful translation, but there may be an informative message. */
-      if (wcs->err && wcs->err->status < 0) {
-        wcserr_copy(wcs->err, info+ifix);
-      } else {
-        wcserr_copy(0x0, info+ifix);
-      }
-
-    } else {
-      /* An informative message or error message. */
-      wcserr_copy(wcs->err, info+ifix);
-
-      if ((status = (stat[ifix] > 0))) {
-        /* It was an error, replace the previous one. */
-        wcserr_copy(wcs->err, &err);
-      }
-    }
-  }
-
-  /* Restore the last error to occur. */
-  if (err.status) {
-    wcserr_copy(&err, wcs->err);
-  } else {
-    wcserr_clear(&(wcs->err));
-  }
-
-  return status;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int cdfix(struct wcsprm *wcs)
-
-{
-  int  i, k, naxis, status = FIXERR_NO_CHANGE;
-  double *cd;
-
-  if (wcs == 0x0) return FIXERR_NULL_POINTER;
-
-  if ((wcs->altlin & 1) || !(wcs->altlin & 2)) {
-    /* Either we have PCi_ja or there are no CDi_ja. */
-    return FIXERR_NO_CHANGE;
-  }
-
-  naxis = wcs->naxis;
-  status = FIXERR_NO_CHANGE;
-  for (i = 0; i < naxis; i++) {
-    /* Row of zeros? */
-    cd = wcs->cd + i * naxis;
-    for (k = 0; k < naxis; k++, cd++) {
-      if (*cd != 0.0) goto next;
-    }
-
-    /* Column of zeros? */
-    cd = wcs->cd + i;
-    for (k = 0; k < naxis; k++, cd += naxis) {
-      if (*cd != 0.0) goto next;
-    }
-
-    cd = wcs->cd + i * (naxis + 1);
-    *cd = 1.0;
-    status = FIXERR_SUCCESS;
-
-next: ;
-  }
-
-  return status;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int datfix(struct wcsprm *wcs)
-
-{
-  static const char *function = "datfix";
-
-  char orig_dateobs[72];
-  char *dateobs;
-  int  day, dd, hour = 0, jd, minute = 0, month, msec, n4, year;
-  double mjdobs, sec = 0.0, t;
-  struct wcserr **err;
-
-  if (wcs == 0x0) return FIXERR_NULL_POINTER;
-  err = &(wcs->err);
-
-  dateobs = wcs->dateobs;
-  strncpy(orig_dateobs, dateobs, 72);
-  if (dateobs[0] == '\0') {
-    if (undefined(wcs->mjdobs)) {
-     /* No date information was provided. */
-      return FIXERR_NO_CHANGE;
-
-    } else {
-      /* Calendar date from MJD. */
-      jd = 2400001 + (int)wcs->mjdobs;
-
-      n4 =  4*(jd + ((2*((4*jd - 17918)/146097)*3)/4 + 1)/2 - 37);
-      dd = 10*(((n4-237)%1461)/4) + 5;
-
-      year  = n4/1461 - 4712;
-      month = (2 + dd/306)%12 + 1;
-      day   = (dd%306)/10 + 1;
-      sprintf(dateobs, "%.4d-%.2d-%.2d", year, month, day);
-
-      /* Write time part only if non-zero. */
-      if ((t = wcs->mjdobs - (int)wcs->mjdobs) > 0.0) {
-        t *= 24.0;
-        hour = (int)t;
-        t = 60.0 * (t - hour);
-        minute = (int)t;
-        sec    = 60.0 * (t - minute);
-
-        /* Round to 1ms. */
-        dd = 60000*(60*hour + minute) + (int)(1000*(sec+0.0005));
-        hour = dd / 3600000;
-        dd -= 3600000 * hour;
-        minute = dd / 60000;
-        msec = dd - 60000 * minute;
-        sprintf(dateobs+10, "T%.2d:%.2d:%.2d", hour, minute, msec/1000);
-
-        /* Write fractions of a second only if non-zero. */
-        if (msec%1000) {
-          sprintf(dateobs+19, ".%.3d", msec%1000);
-        }
-      }
-    }
-
-  } else {
-    if (strlen(dateobs) < 8) {
-      /* Can't be a valid date. */
-      return wcserr_set(WCSERR_SET(FIXERR_BAD_PARAM),
-        "Invalid parameter value: date string too short '%s'", dateobs);
-    }
-
-    /* Identify the date format. */
-    if (dateobs[4] == '-' && dateobs[7] == '-') {
-      /* Standard year-2000 form: CCYY-MM-DD[Thh:mm:ss[.sss...]] */
-      if (sscanf(dateobs, "%4d-%2d-%2d", &year, &month, &day) < 3) {
-        return wcserr_set(WCSERR_SET(FIXERR_BAD_PARAM),
-          "Invalid parameter value: invalid date '%s'", dateobs);
-      }
-
-      if (dateobs[10] == 'T') {
-        if (sscanf(dateobs+11, "%2d:%2d:%lf", &hour, &minute, &sec) < 3) {
-          return wcserr_set(WCSERR_SET(FIXERR_BAD_PARAM),
-            "Invalid parameter value: invalid time '%s'", dateobs+11);
-        }
-      } else if (dateobs[10] == ' ') {
-        hour = 0;
-        minute = 0;
-        sec = 0.0;
-        if (sscanf(dateobs+11, "%2d:%2d:%lf", &hour, &minute, &sec) == 3) {
-          dateobs[10] = 'T';
-        } else {
-          sprintf(dateobs+10, "T%.2d:%.2d:%04.1f", hour, minute, sec);
-        }
-      }
-
-    } else if (dateobs[4] == '/' && dateobs[7] == '/') {
-      /* Also allow CCYY/MM/DD[Thh:mm:ss[.sss...]] */
-      if (sscanf(dateobs, "%4d/%2d/%2d", &year, &month, &day) < 3) {
-        return wcserr_set(WCSERR_SET(FIXERR_BAD_PARAM),
-          "Invalid parameter value: invalid date '%s'", dateobs);
-      }
-
-      if (dateobs[10] == 'T') {
-        if (sscanf(dateobs+11, "%2d:%2d:%lf", &hour, &minute, &sec) < 3) {
-          return wcserr_set(WCSERR_SET(FIXERR_BAD_PARAM),
-            "Invalid parameter value: invalid time '%s'", dateobs+11);
-        }
-      } else if (dateobs[10] == ' ') {
-        hour = 0;
-        minute = 0;
-        sec = 0.0;
-        if (sscanf(dateobs+11, "%2d:%2d:%lf", &hour, &minute, &sec) == 3) {
-          dateobs[10] = 'T';
-        } else {
-          sprintf(dateobs+10, "T%.2d:%.2d:%04.1f", hour, minute, sec);
-        }
-      }
-
-      /* Looks ok, fix it up. */
-      dateobs[4]  = '-';
-      dateobs[7]  = '-';
-
-    } else {
-      if (dateobs[2] == '/' && dateobs[5] == '/') {
-        /* Old format date: DD/MM/YY, also allowing DD/MM/CCYY. */
-        if (sscanf(dateobs, "%2d/%2d/%4d", &day, &month, &year) < 3) {
-          return wcserr_set(WCSERR_SET(FIXERR_BAD_PARAM),
-            "Invalid parameter value: invalid date '%s'", dateobs);
-        }
-
-      } else if (dateobs[2] == '-' && dateobs[5] == '-') {
-        /* Also recognize DD-MM-YY and DD-MM-CCYY */
-        if (sscanf(dateobs, "%2d-%2d-%4d", &day, &month, &year) < 3) {
-          return wcserr_set(WCSERR_SET(FIXERR_BAD_PARAM),
-            "Invalid parameter value: invalid date '%s'", dateobs);
-        }
-
-      } else {
-        /* Not a valid date format. */
-        return wcserr_set(WCSERR_SET(FIXERR_BAD_PARAM),
-          "Invalid parameter value: invalid date '%s'", dateobs);
-      }
-
-      if (year < 100) year += 1900;
-
-      /* Doesn't have a time. */
-      sprintf(dateobs, "%.4d-%.2d-%.2d", year, month, day);
-    }
-
-    /* Compute MJD. */
-    mjdobs = (double)((1461*(year - (12-month)/10 + 4712))/4
-             + (306*((month+9)%12) + 5)/10
-             - (3*((year - (12-month)/10 + 4900)/100))/4
-             + day - 2399904)
-             + (hour + (minute + sec/60.0)/60.0)/24.0;
-
-    if (undefined(wcs->mjdobs)) {
-      wcs->mjdobs = mjdobs;
-    } else {
-      /* Check for consistency. */
-      if (fabs(mjdobs - wcs->mjdobs) > 0.5) {
-        return wcserr_set(WCSERR_SET(FIXERR_BAD_PARAM),
-          "Invalid parameter value: inconsistent date '%s'", dateobs);
-      }
-    }
-  }
-
-  if (strncmp(orig_dateobs, dateobs, 72)) {
-    wcserr_set(WCSERR_SET(FIXERR_DATE_FIX),
-      "Changed '%s' to '%s'", orig_dateobs, dateobs);
-
-    return FIXERR_SUCCESS;
-  }
-
-  return FIXERR_NO_CHANGE;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int unitfix(int ctrl, struct wcsprm *wcs)
-
-{
-  int  i, k, status = FIXERR_NO_CHANGE;
-  char orig_unit[80], msg[WCSERR_MSG_LENGTH];
-  const char *function = "unitfix";
-  struct wcserr **err;
-
-  if (wcs == 0x0) return FIXERR_NULL_POINTER;
-  err = &(wcs->err);
-
-  strcpy(msg, "Changed units: ");
-  for (i = 0; i < wcs->naxis; i++) {
-    strncpy(orig_unit, wcs->cunit[i], 80);
-    if (wcsutrne(ctrl, wcs->cunit[i], &(wcs->err)) == 0) {
-      k = strlen(msg);
-      sprintf(msg+k, "'%s' -> '%s', ", orig_unit, wcs->cunit[i]);
-      status = FIXERR_UNITS_ALIAS;
-    }
-  }
-
-  if (status == FIXERR_UNITS_ALIAS) {
-    k = strlen(msg) - 2;
-    msg[k] = '\0';
-    wcserr_set(WCSERR_SET(FIXERR_UNITS_ALIAS), msg);
-
-    status = FIXERR_SUCCESS;
-  }
-
-  return status;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int spcfix(struct wcsprm *wcs)
-
-{
-  static const char *function = "spcfix";
-
-  char ctype[9], specsys[9];
-  int  i, status;
-  struct wcserr **err;
-
-  if (wcs == 0x0) return FIXERR_NULL_POINTER;
-  err = &(wcs->err);
-
-  for (i = 0; i < wcs->naxis; i++) {
-    /* Translate an AIPS-convention spectral type if present. */
-    status = spcaips(wcs->ctype[i], wcs->velref, ctype, specsys);
-    if (status == 0) {
-      /* An AIPS type was found but it may match what we already have. */
-      status = FIXERR_NO_CHANGE;
-
-      /* Was specsys translated? */
-      if (wcs->specsys[0] == '\0' && *specsys) {
-        strncpy(wcs->specsys, specsys, 9);
-        wcserr_set(WCSERR_SET(FIXERR_SPC_UPDATE),
-          "Changed SPECSYS to '%s'", specsys);
-        status = FIXERR_SUCCESS;
-      }
-
-      /* Was ctype translated?  Have to null-fill for comparing them. */
-      wcsutil_null_fill(9, wcs->ctype[i]);
-      if (strncmp(wcs->ctype[i], ctype, 9)) {
-        /* ctype was translated... */
-        if (status == FIXERR_SUCCESS) {
-          /* ...and specsys was also. */
-          wcserr_set(WCSERR_SET(FIXERR_SPC_UPDATE),
-            "Changed CTYPE%d from '%s' to '%s', and SPECSYS to '%s'",
-            i+1, wcs->ctype[i], ctype, wcs->specsys);
-        } else {
-          wcserr_set(WCSERR_SET(FIXERR_SPC_UPDATE),
-            "Changed CTYPE%d from '%s' to '%s'", i+1, wcs->ctype[i], ctype);
-          status = FIXERR_SUCCESS;
-        }
-
-        strncpy(wcs->ctype[i], ctype, 9);
-      }
-
-      /* Tidy up. */
-      if (status == FIXERR_SUCCESS) {
-        wcsutil_null_fill(72, wcs->ctype[i]);
-        wcsutil_null_fill(72, wcs->specsys);
-      }
-
-      /* No need to check for others, wcsset() will fail if so. */
-      return status;
-
-    } else if (status == SPCERR_BAD_SPEC_PARAMS) {
-      /* An AIPS spectral type was found but with invalid velref. */
-      return wcserr_set(WCSERR_SET(FIXERR_BAD_PARAM),
-        "Invalid parameter value: velref = %d", wcs->velref);
-    }
-  }
-
-  return FIXERR_NO_CHANGE;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int celfix(struct wcsprm *wcs)
-
-{
-  static const char *function = "celfix";
-
-  int k, status;
-  struct celprm *wcscel = &(wcs->cel);
-  struct prjprm *wcsprj = &(wcscel->prj);
-  struct wcserr **err;
-
-  if (wcs == 0x0) return FIXERR_NULL_POINTER;
-  err = &(wcs->err);
-
-  /* Initialize if required. */
-  if (wcs->flag != WCSSET) {
-    if ((status = wcsset(wcs))) return status;
-  }
-
-  /* Was an NCP or GLS projection code translated? */
-  if (wcs->lat >= 0) {
-    /* Check ctype. */
-    if (strcmp(wcs->ctype[wcs->lat]+5, "NCP") == 0) {
-      strcpy(wcs->ctype[wcs->lng]+5, "SIN");
-      strcpy(wcs->ctype[wcs->lat]+5, "SIN");
-
-      if (wcs->npvmax < wcs->npv + 2) {
-        /* Allocate space for two more PVi_ja keyvalues. */
-        if (wcs->m_flag == WCSSET && wcs->pv == wcs->m_pv) {
-          if (!(wcs->pv = calloc(wcs->npv+2, sizeof(struct pvcard)))) {
-            wcs->pv = wcs->m_pv;
-            return wcserr_set(WCSFIX_ERRMSG(FIXERR_MEMORY));
-          }
-
-          wcs->npvmax = wcs->npv + 2;
-          wcs->m_flag = WCSSET;
-
-          for (k = 0; k < wcs->npv; k++) {
-            wcs->pv[k] = wcs->m_pv[k];
-          }
-
-          if (wcs->m_pv) free(wcs->m_pv);
-          wcs->m_pv = wcs->pv;
-
-        } else {
-          return wcserr_set(WCSFIX_ERRMSG(FIXERR_MEMORY));
-        }
-      }
-
-      wcs->pv[wcs->npv].i = wcs->lat + 1;
-      wcs->pv[wcs->npv].m = 1;
-      wcs->pv[wcs->npv].value = wcsprj->pv[1];
-      (wcs->npv)++;
-
-      wcs->pv[wcs->npv].i = wcs->lat + 1;
-      wcs->pv[wcs->npv].m = 2;
-      wcs->pv[wcs->npv].value = wcsprj->pv[2];
-      (wcs->npv)++;
-
-      return FIXERR_SUCCESS;
-
-    } else if (strcmp(wcs->ctype[wcs->lat]+5, "GLS") == 0) {
-      strcpy(wcs->ctype[wcs->lng]+5, "SFL");
-      strcpy(wcs->ctype[wcs->lat]+5, "SFL");
-
-      if (wcs->crval[wcs->lng] != 0.0 || wcs->crval[wcs->lat] != 0.0) {
-        /* In the AIPS convention, setting the reference longitude and
-         * latitude for GLS does not create an oblique graticule.  A non-zero
-         * reference longitude introduces an offset in longitude in the normal
-         * way, whereas a non-zero reference latitude simply translates the
-         * reference point (i.e. the map as a whole) to that latitude.  This
-         * might be effected by adjusting CRPIXja but that is complicated by
-         * the linear transformation and instead is accomplished here by
-         * setting theta_0. */
-        if (wcs->npvmax < wcs->npv + 2) {
-          /* Allocate space for three more PVi_ja keyvalues. */
-          if (wcs->m_flag == WCSSET && wcs->pv == wcs->m_pv) {
-            if (!(wcs->pv = calloc(wcs->npv+3, sizeof(struct pvcard)))) {
-              wcs->pv = wcs->m_pv;
-              return wcserr_set(WCSFIX_ERRMSG(FIXERR_MEMORY));
-            }
-
-            wcs->npvmax = wcs->npv + 3;
-            wcs->m_flag = WCSSET;
-
-            for (k = 0; k < wcs->npv; k++) {
-              wcs->pv[k] = wcs->m_pv[k];
-            }
-
-            if (wcs->m_pv) free(wcs->m_pv);
-            wcs->m_pv = wcs->pv;
-
-          } else {
-            return wcserr_set(WCSFIX_ERRMSG(FIXERR_MEMORY));
-          }
-        }
-
-        wcs->pv[wcs->npv].i = wcs->lng + 1;
-        wcs->pv[wcs->npv].m = 0;
-        wcs->pv[wcs->npv].value = 1.0;
-        (wcs->npv)++;
-
-        /* Note that the reference longitude is still zero. */
-        wcs->pv[wcs->npv].i = wcs->lng + 1;
-        wcs->pv[wcs->npv].m = 1;
-        wcs->pv[wcs->npv].value = 0.0;
-        (wcs->npv)++;
-
-        wcs->pv[wcs->npv].i = wcs->lng + 1;
-        wcs->pv[wcs->npv].m = 2;
-        wcs->pv[wcs->npv].value = wcs->crval[wcs->lat];
-        (wcs->npv)++;
-      }
-
-      return FIXERR_SUCCESS;
-    }
-  }
-
-  return FIXERR_NO_CHANGE;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int cylfix(const int naxis[], struct wcsprm *wcs)
-
-{
-  static const char *function = "cylfix";
-
-  unsigned short icnr, indx[NMAX], ncnr;
-  int    j, k, stat[4], status;
-  double img[4][NMAX], lat, lng, phi[4], phi0, phimax, phimin, pix[4][NMAX],
-         *pixj, theta[4], theta0, world[4][NMAX], x, y;
-  struct wcserr **err;
-
-  if (naxis == 0x0) return FIXERR_NO_CHANGE;
-  if (wcs == 0x0) return FIXERR_NULL_POINTER;
-  err = &(wcs->err);
-
-  /* Initialize if required. */
-  if (wcs->flag != WCSSET) {
-    if ((status = wcsset(wcs))) return status;
-  }
-
-  /* Check that we have a cylindrical projection. */
-  if (wcs->cel.prj.category != CYLINDRICAL) return FIXERR_NO_CHANGE;
-  if (wcs->naxis < 2) return FIXERR_NO_CHANGE;
-
-
-  /* Compute the native longitude in each corner of the image. */
-  ncnr = 1 << wcs->naxis;
-
-  for (k = 0; k < NMAX; k++) {
-    indx[k] = 1 << k;
-  }
-
-  phimin =  1.0e99;
-  phimax = -1.0e99;
-  for (icnr = 0; icnr < ncnr;) {
-    /* Do four corners at a time. */
-    for (j = 0; j < 4; j++, icnr++) {
-      pixj = pix[j];
-
-      for (k = 0; k < wcs->naxis; k++) {
-        if (icnr & indx[k]) {
-          *(pixj++) = naxis[k] + 0.5;
-        } else {
-          *(pixj++) = 0.5;
-        }
-      }
-    }
-
-    if (!(status = wcsp2s(wcs, 4, NMAX, pix[0], img[0], phi, theta, world[0],
-                          stat))) {
-      for (j = 0; j < 4; j++) {
-        if (phi[j] < phimin) phimin = phi[j];
-        if (phi[j] > phimax) phimax = phi[j];
-      }
-    }
-  }
-
-  if (phimin > phimax) return status;
-
-  /* Any changes needed? */
-  if (phimin >= -180.0 && phimax <= 180.0) return FIXERR_NO_CHANGE;
-
-
-  /* Compute the new reference pixel coordinates. */
-  phi0 = (phimin + phimax) / 2.0;
-  theta0 = 0.0;
-
-  if ((status = prjs2x(&(wcs->cel.prj), 1, 1, 1, 1, &phi0, &theta0, &x, &y,
-                       stat))) {
-    if (status == PRJERR_BAD_PARAM) {
-      return wcserr_set(WCSFIX_ERRMSG(FIXERR_BAD_PARAM));
-    }
-    return wcserr_set(WCSFIX_ERRMSG(FIXERR_NO_REF_PIX_COORD));
-  }
-
-  for (k = 0; k < wcs->naxis; k++) {
-    img[0][k] = 0.0;
-  }
-  img[0][wcs->lng] = x;
-  img[0][wcs->lat] = y;
-
-  if ((status = linx2p(&(wcs->lin), 1, 0, img[0], pix[0]))) {
-    return wcserr_set(WCSFIX_ERRMSG(status));
-  }
-
-
-  /* Compute celestial coordinates at the new reference pixel. */
-  if ((status = wcsp2s(wcs, 1, 0, pix[0], img[0], phi, theta, world[0],
-                       stat))) {
-    if (wcs->err->status == WCSERR_BAD_PIX) {
-      wcs->err->status = FIXERR_NO_REF_PIX_COORD;
-    }
-    return wcs->err->status;
-  }
-
-  /* Compute native coordinates of the celestial pole. */
-  lng =  0.0;
-  lat = 90.0;
-  (void)sphs2x(wcs->cel.euler, 1, 1, 1, 1, &lng, &lat, phi, theta);
-
-  wcs->crpix[wcs->lng] = pix[0][wcs->lng];
-  wcs->crpix[wcs->lat] = pix[0][wcs->lat];
-  wcs->crval[wcs->lng] = world[0][wcs->lng];
-  wcs->crval[wcs->lat] = world[0][wcs->lat];
-  wcs->lonpole = phi[0] - phi0;
-
-  return wcsset(wcs);
-}
diff --git a/astropy/wcs/src/wcslib/C/wcsfix.h b/astropy/wcs/src/wcslib/C/wcsfix.h
deleted file mode 100644
index 0f7f26c..0000000
--- a/astropy/wcs/src/wcslib/C/wcsfix.h
+++ /dev/null
@@ -1,404 +0,0 @@
-/*============================================================================
-
-  WCSLIB 4.10 - an implementation of the FITS WCS standard.
-  Copyright (C) 1995-2012, Mark Calabretta
-
-  This file is part of WCSLIB.
-
-  WCSLIB is free software: you can redistribute it and/or modify it under the
-  terms of the GNU Lesser General Public License as published by the Free
-  Software Foundation, either version 3 of the License, or (at your option)
-  any later version.
-
-  WCSLIB 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 Lesser General Public License for
-  more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with WCSLIB.  If not, see <http://www.gnu.org/licenses/>.
-
-  Correspondence concerning WCSLIB may be directed to:
-    Internet email: mcalabre at atnf.csiro.au
-    Postal address: Dr. Mark Calabretta
-                    Australia Telescope National Facility, CSIRO
-                    PO Box 76
-                    Epping NSW 1710
-                    AUSTRALIA
-
-  Author: Mark Calabretta, Australia Telescope National Facility
-  http://www.atnf.csiro.au/~mcalabre/index.html
-  $Id: wcsfix.h,v 4.10 2012/02/05 23:41:44 cal103 Exp $
-*=============================================================================
-*
-* WCSLIB 4.10 - C routines that implement the FITS World Coordinate System
-* (WCS) standard.  Refer to
-*
-*   "Representations of world coordinates in FITS",
-*   Greisen, E.W., & Calabretta, M.R. 2002, A&A, 395, 1061 (Paper I)
-*
-*   "Representations of celestial coordinates in FITS",
-*   Calabretta, M.R., & Greisen, E.W. 2002, A&A, 395, 1077 (Paper II)
-*
-*   "Representations of spectral coordinates in FITS",
-*   Greisen, E.W., Calabretta, M.R., Valdes, F.G., & Allen, S.L.
-*   2006, A&A, 446, 747 (Paper III)
-*
-* Refer to the README file provided with WCSLIB for an overview of the
-* library.
-*
-*
-* Summary of the wcsfix routines
-* ------------------------------
-* Routines in this suite identify and translate various forms of non-standard
-* construct that are known to occur in FITS WCS headers.  These range from the
-* translation of non-standard values for standard WCS keywords, to the repair
-* of malformed coordinate representations.
-*
-* Non-standard keyvalues:
-* -----------------------
-*   AIPS-convention celestial projection types, NCP and GLS, and spectral
-*   types, 'FREQ-LSR', 'FELO-HEL', etc., set in CTYPEia are translated
-*   on-the-fly by wcsset() but without modifying the relevant ctype[], pv[] or
-*   specsys members of the wcsprm struct.  That is, only the information
-*   extracted from ctype[] is translated when wcsset() fills in wcsprm::cel
-*   (celprm struct) or wcsprm::spc (spcprm struct).
-*
-*   On the other hand, these routines do change the values of wcsprm::ctype[],
-*   wcsprm::pv[], wcsprm::specsys and other wcsprm struct members as
-*   appropriate to produce the same result as if the FITS header itself had
-*   been translated.
-*
-*   Auxiliary WCS header information not used directly by WCSLIB may also be
-*   translated.  For example, the older DATE-OBS date format (wcsprm::dateobs)
-*   is recast to year-2000 standard form, and MJD-OBS (wcsprm::mjdobs) will be
-*   deduced from it if not already set.
-*
-*   Certain combinations of keyvalues that result in malformed coordinate
-*   systems, as described in Sect. 7.3.4 of Paper I, may also be repaired.
-*   These are handled by cylfix().
-*
-* Non-standard keywords:
-* ----------------------
-*   The AIPS-convention CROTAn keywords are recognized as quasi-standard and
-*   as such are accomodated by the wcsprm::crota[] and translated to
-*   wcsprm::pc[][] by wcsset().  These are not dealt with here, nor are any
-*   other non-standard keywords since these routines work only on the contents
-*   of a wcsprm struct and do not deal with FITS headers per se.  In
-*   particular, they do not identify or translate CD00i00j, PC00i00j, PROJPn,
-*   EPOCH, VELREF or VSOURCEa keywords; this may be done by the FITS WCS
-*   header parser supplied with WCSLIB, refer to wcshdr.h.
-*
-* wcsfix() and wcsfixi() apply all of the corrections handled by the following
-* specific functions which may also be invoked separately:
-*
-*   - cdfix(): Sets the diagonal element of the CDi_ja matrix to 1.0 if all
-*     CDi_ja keywords associated with a particular axis are omitted.
-*
-*   - datfix(): recast an older DATE-OBS date format in dateobs to year-2000
-*     standard form and derive mjdobs from it if not already set.
-*     Alternatively, if mjdobs is set and dateobs isn't, then derive dateobs
-*     from it.
-*
-*   - unitfix(): translate some commonly used but non-standard unit strings in
-*     the CUNITia keyvalues, e.g. 'DEG' -> 'deg'.
-*
-*   - spcfix(): translate AIPS-convention spectral types, 'FREQ-LSR',
-*     'FELO-HEL', etc., in ctype[] as set from CTYPEia.
-*
-*   - celfix(): translate AIPS-convention celestial projection types, NCP and
-*     GLS, in ctype[] as set from CTYPEia.
-*
-*   - cylfix(): fixes WCS keyvalues for malformed cylindrical projections that
-*     suffer from the problem described in Sect. 7.3.4 of Paper I.
-*
-*
-* wcsfix() - Translate a non-standard WCS struct
-* ----------------------------------------------
-* wcsfix() is identical to wcsfixi(), but lacks the info argument.
-*
-*
-* wcsfixi() - Translate a non-standard WCS struct
-* -----------------------------------------------
-* wcsfix() applies all of the corrections handled separately by cdfix(),
-* datfix(), unitfix(), spcfix(), celfix(), and cylfix().
-*
-* Given:
-*   ctrl      int       Do potentially unsafe translations of non-standard
-*                       unit strings as described in the usage notes to
-*                       wcsutrn().
-*
-*   naxis     const int []
-*                       Image axis lengths.  If this array pointer is set to
-*                       zero then cylfix() will not be invoked.
-*
-* Given and returned:
-*   wcs       struct wcsprm*
-*                       Coordinate transformation parameters.
-*
-* Returned:
-*   stat      int [NWCSFIX]
-*                       Status returns from each of the functions.  Use the
-*                       preprocessor macros NWCSFIX to dimension this vector
-*                       and CDFIX, DATFIX, UNITFIX, SPCFIX, CELFIX, and CYLFIX
-*                       to access its elements.  A status value of -2 is set
-*                       for functions that were not invoked.
-*
-*   info      struct wcserr [NWCSFIX]
-*                       Status messages from each of the functions.  Use the
-*                       preprocessor macros NWCSFIX to dimension this vector
-*                       and CDFIX, DATFIX, UNITFIX, SPCFIX, CELFIX, and CYLFIX
-*                       to access its elements.
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         1: One or more of the translation functions
-*                            returned an error.
-*
-*
-* cdfix() - Fix erroneously omitted CDi_ja keywords
-* -------------------------------------------------
-* cdfix() sets the diagonal element of the CDi_ja matrix to unity if all
-* CDi_ja keywords associated with a given axis were omitted.  According to
-* Paper I, if any CDi_ja keywords at all are given in a FITS header then those
-* not given default to zero.  This results in a singular matrix with an
-* intersecting row and column of zeros.
-*
-* Given and returned:
-*   wcs       struct wcsprm*
-*                       Coordinate transformation parameters.
-*
-* Function return value:
-*             int       Status return value:
-*                        -1: No change required (not an error).
-*                         0: Success.
-*                         1: Null wcsprm pointer passed.
-*
-*
-* datfix() - Translate DATE-OBS and derive MJD-OBS or vice versa
-* --------------------------------------------------------------
-* datfix() translates the old DATE-OBS date format set in wcsprm::dateobs to
-* year-2000 standard form (yyyy-mm-ddThh:mm:ss) and derives MJD-OBS from it if
-* not already set.  Alternatively, if wcsprm::mjdobs is set and
-* wcsprm::dateobs isn't, then datfix() derives wcsprm::dateobs from it.  If
-* both are set but disagree by more than half a day then status 5 is returned.
-*
-* Given and returned:
-*   wcs       struct wcsprm*
-*                       Coordinate transformation parameters.  wcsprm::dateobs
-*                       and/or wcsprm::mjdobs may be changed.
-*
-* Function return value:
-*             int       Status return value:
-*                        -1: No change required (not an error).
-*                         0: Success.
-*                         1: Null wcsprm pointer passed.
-*                         5: Invalid parameter value.
-*
-*                       For returns > 1, a detailed error message is set in
-*                       wcsprm::err if enabled, see wcserr_enable().
-*
-* Notes:
-*   The MJD algorithms used by datfix() are from D.A. Hatcher, 1984, QJRAS,
-*   25, 53-55, as modified by P.T. Wallace for use in SLALIB subroutines CLDJ
-*   and DJCL.
-*
-*
-* unitfix() - Correct aberrant CUNITia keyvalues
-* ----------------------------------------------
-* unitfix() applies wcsutrn() to translate non-standard CUNITia keyvalues,
-* e.g. 'DEG' -> 'deg', also stripping off unnecessary whitespace.
-*
-* Given:
-*   ctrl      int       Do potentially unsafe translations described in the
-*                       usage notes to wcsutrn().
-*
-* Given and returned:
-*   wcs       struct wcsprm*
-*                       Coordinate transformation parameters.
-*
-* Function return value:
-*             int       Status return value:
-*                        -1: No change required (not an error).
-*                         0: Success (an alias was applied).
-*                         1: Null wcsprm pointer passed.
-*
-*                       When units are translated (i.e. status 0), status -2
-*                       is set in the wcserr struct to allow an informative
-*                       message to be returned.
-*
-*
-* spcfix() - Translate AIPS-convention spectral types
-* ---------------------------------------------------
-* spcfix() translates AIPS-convention spectral coordinate types,
-* '{FREQ,FELO,VELO}-{LSR,HEL,OBS}' (e.g. 'FREQ-OBS', 'FELO-HEL', 'VELO-LSR')
-* set in wcsprm::ctype[], subject to VELREF set in wcsprm::velref.
-*
-* Note that if wcs::specsys is already set then it will not be overridden.
-*
-* Given and returned:
-*   wcs       struct wcsprm*
-*                       Coordinate transformation parameters.  wcsprm::ctype[]
-*                       and/or wcsprm::specsys may be changed.
-*
-* Function return value:
-*             int       Status return value:
-*                        -1: No change required (not an error).
-*                         0: Success.
-*                         1: Null wcsprm pointer passed.
-*                         2: Memory allocation failed.
-*                         3: Linear transformation matrix is singular.
-*                         4: Inconsistent or unrecognized coordinate axis
-*                            types.
-*                         5: Invalid parameter value.
-*                         6: Invalid coordinate transformation parameters.
-*                         7: Ill-conditioned coordinate transformation
-*                            parameters.
-*
-*                       For returns > 1, a detailed error message is set in
-*                       wcsprm::err if enabled, see wcserr_enable().
-*
-*
-* celfix() - Translate AIPS-convention celestial projection types
-* ---------------------------------------------------------------
-* celfix() translates AIPS-convention celestial projection types, NCP and
-* GLS, set in the ctype[] member of the wcsprm struct.
-*
-* Two additional pv[] keyvalues are created when translating NCP.  If the
-* pv[] array was initially allocated by wcsini() then the array will be
-* expanded if necessary.  Otherwise, error 2 will be returned if two empty
-* slots are not already available for use.
-*
-* Given and returned:
-*   wcs       struct wcsprm*
-*                       Coordinate transformation parameters.  wcsprm::ctype[]
-*                       and/or wcsprm::pv[] may be changed.
-*
-* Function return value:
-*             int       Status return value:
-*                        -1: No change required (not an error).
-*                         0: Success.
-*                         1: Null wcsprm pointer passed.
-*                         2: Memory allocation failed.
-*                         3: Linear transformation matrix is singular.
-*                         4: Inconsistent or unrecognized coordinate axis
-*                            types.
-*                         5: Invalid parameter value.
-*                         6: Invalid coordinate transformation parameters.
-*                         7: Ill-conditioned coordinate transformation
-*                            parameters.
-*
-*                       For returns > 1, a detailed error message is set in
-*                       wcsprm::err if enabled, see wcserr_enable().
-*
-*
-* cylfix() - Fix malformed cylindrical projections
-* ------------------------------------------------
-* cylfix() fixes WCS keyvalues for malformed cylindrical projections that
-* suffer from the problem described in Sect. 7.3.4 of Paper I.
-*
-* Given:
-*   naxis     const int []
-*                       Image axis lengths.
-*
-* Given and returned:
-*   wcs       struct wcsprm*
-*                       Coordinate transformation parameters.
-*
-* Function return value:
-*             int       Status return value:
-*                        -1: No change required (not an error).
-*                         0: Success.
-*                         1: Null wcsprm pointer passed.
-*                         2: Memory allocation failed.
-*                         3: Linear transformation matrix is singular.
-*                         4: Inconsistent or unrecognized coordinate axis
-*                            types.
-*                         5: Invalid parameter value.
-*                         6: Invalid coordinate transformation parameters.
-*                         7: Ill-conditioned coordinate transformation
-*                            parameters.
-*                         8: All of the corner pixel coordinates are invalid.
-*                         9: Could not determine reference pixel coordinate.
-*                        10: Could not determine reference pixel value.
-*
-*                       For returns > 1, a detailed error message is set in
-*                       wcsprm::err if enabled, see wcserr_enable().
-*
-*
-* Global variable: const char *wcsfix_errmsg[] - Status return messages
-* ---------------------------------------------------------------------
-* Error messages to match the status value returned from each function.
-*
-*===========================================================================*/
-
-#ifndef WCSLIB_WCSFIX
-#define WCSLIB_WCSFIX
-
-#include "wcs.h"
-#include "wcserr.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define CDFIX    0
-#define DATFIX   1
-#define UNITFIX  2
-#define SPCFIX   3
-#define CELFIX   4
-#define CYLFIX   5
-#define NWCSFIX  6
-
-extern const char *wcsfix_errmsg[];
-#define cylfix_errmsg wcsfix_errmsg
-
-enum wcsfix_errmsg_enum {
-  FIXERR_DATE_FIX         = -4, /* The date formatting has been fixed up. */
-  FIXERR_SPC_UPDATE       = -3, /* Spectral axis type modified. */
-  FIXERR_UNITS_ALIAS      = -2,	/* Units alias translation. */
-  FIXERR_NO_CHANGE        = -1,	/* No change. */
-  FIXERR_SUCCESS          =  0,	/* Success. */
-  FIXERR_NULL_POINTER     =  1,	/* Null wcsprm pointer passed. */
-  FIXERR_MEMORY           =  2,	/* Memory allocation failed. */
-  FIXERR_SINGULAR_MTX     =  3,	/* Linear transformation matrix is
-				   singular. */
-  FIXERR_BAD_CTYPE        =  4,	/* Inconsistent or unrecognized coordinate
-				   axis types. */
-  FIXERR_BAD_PARAM        =  5,	/* Invalid parameter value. */
-  FIXERR_BAD_COORD_TRANS  =  6,	/* Invalid coordinate transformation
-				   parameters. */
-  FIXERR_ILL_COORD_TRANS  =  7,	/* Ill-conditioned coordinate transformation
-				   parameters. */
-  FIXERR_BAD_CORNER_PIX   =  8,	/* All of the corner pixel coordinates are
-				   invalid. */
-  FIXERR_NO_REF_PIX_COORD =  9,	/* Could not determine reference pixel
-				   coordinate. */
-  FIXERR_NO_REF_PIX_VAL   = 10	/* Could not determine reference pixel
-				   value. */
-};
-
-int wcsfix(int ctrl, const int naxis[], struct wcsprm *wcs, int stat[]);
-
-int wcsfixi(int ctrl, const int naxis[], struct wcsprm *wcs, int stat[],
-            struct wcserr info[]);
-
-int cdfix(struct wcsprm *wcs);
-
-int datfix(struct wcsprm *wcs);
-
-int unitfix(int ctrl, struct wcsprm *wcs);
-
-int spcfix(struct wcsprm *wcs);
-
-int celfix(struct wcsprm *wcs);
-
-int cylfix(const int naxis[], struct wcsprm *wcs);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* WCSLIB_WCSFIX */
diff --git a/astropy/wcs/src/wcslib/C/wcshdr.c b/astropy/wcs/src/wcslib/C/wcshdr.c
deleted file mode 100644
index 4a643d7..0000000
--- a/astropy/wcs/src/wcslib/C/wcshdr.c
+++ /dev/null
@@ -1,1079 +0,0 @@
-/*============================================================================
-
-  WCSLIB 4.10 - an implementation of the FITS WCS standard.
-  Copyright (C) 1995-2012, Mark Calabretta
-
-  This file is part of WCSLIB.
-
-  WCSLIB is free software: you can redistribute it and/or modify it under the
-  terms of the GNU Lesser General Public License as published by the Free
-  Software Foundation, either version 3 of the License, or (at your option)
-  any later version.
-
-  WCSLIB 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 Lesser General Public License for
-  more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with WCSLIB.  If not, see <http://www.gnu.org/licenses/>.
-
-  Correspondence concerning WCSLIB may be directed to:
-    Internet email: mcalabre at atnf.csiro.au
-    Postal address: Dr. Mark Calabretta
-                    Australia Telescope National Facility, CSIRO
-                    PO Box 76
-                    Epping NSW 1710
-                    AUSTRALIA
-
-  Author: Mark Calabretta, Australia Telescope National Facility
-  http://www.atnf.csiro.au/~mcalabre/index.html
-  $Id: wcshdr.c,v 4.10 2012/02/05 23:41:44 cal103 Exp $
-*===========================================================================*/
-
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "wcsutil.h"
-#include "wcsmath.h"
-#include "wcshdr.h"
-#include "tab.h"
-#include "wcs.h"
-
-extern const int WCSSET;
-
-/* Map status return value to message. */
-const char *wcshdr_errmsg[] = {
-  "Success",
-  "Null wcsprm pointer passed",
-  "Memory allocation failed",
-  "Invalid column selection",
-  "Fatal error returned by Flex parser",
-  "Invalid tabular parameters"};
-
-/* Convenience macro for invoking wcserr_set(). */
-#define WCSHDR_ERRMSG(status) WCSERR_SET(status), wcshdr_errmsg[status]
-
-static void wcshdo_util(int, const char [], const char [], int, const char [],
-  int, int, int, char, int, int [], char [], const char [], int *, char **,
-  int *);
-
-/*--------------------------------------------------------------------------*/
-
-int wcstab(struct wcsprm *wcs)
-
-{
-  static const char *function = "wcstab";
-
-  char (*PSi_0a)[72] = 0x0, (*PSi_1a)[72] = 0x0, (*PSi_2a)[72] = 0x0;
-  int  *PVi_1a = 0x0, *PVi_2a = 0x0, *PVi_3a = 0x0, *tabax, *tabidx = 0x0;
-  int   getcrd, i, ip, itab, itabax, j, jtabax, m, naxis, ntabax, status;
-  struct wtbarr *wtbp;
-  struct tabprm *tabp;
-  struct wcserr **err;
-
-  if (wcs == 0x0) return WCSHDRERR_NULL_POINTER;
-  err = &(wcs->err);
-
-  /* Free memory previously allocated by wcstab(). */
-  if (wcs->flag != -1 && wcs->m_flag == WCSSET) {
-    if (wcs->wtb == wcs->m_wtb) wcs->wtb = 0x0;
-    if (wcs->tab == wcs->m_tab) wcs->tab = 0x0;
-
-    if (wcs->m_wtb) free(wcs->m_wtb);
-    if (wcs->m_tab) {
-      for (j = 0; j < wcs->ntab; j++) {
-        tabfree(wcs->m_tab + j);
-      }
-
-      free(wcs->m_tab);
-    }
-  }
-
-  wcs->ntab = 0;
-  wcs->nwtb = 0;
-  wcs->wtb  = 0x0;
-  wcs->tab  = 0x0;
-
-
-  /* Determine the number of -TAB axes. */
-  naxis = wcs->naxis;
-  if (!(tabax = calloc(naxis, sizeof(int)))) {
-    return wcserr_set(WCSHDR_ERRMSG(WCSHDRERR_MEMORY));
-  }
-
-  ntabax = 0;
-  for (i = 0; i < naxis; i++) {
-    /* Null fill. */
-    wcsutil_null_fill(72, wcs->ctype[i]);
-
-    if (!strcmp(wcs->ctype[i]+4, "-TAB")) {
-      tabax[i] = ntabax++;
-    } else {
-      tabax[i] = -1;
-    }
-  }
-
-  if (ntabax == 0) {
-    /* No lookup tables. */
-    status = 0;
-    goto cleanup;
-  }
-
-
-  /* Collect information from the PSi_ma and PVi_ma keyvalues. */
-  if (!((PSi_0a = calloc(ntabax, sizeof(char[72]))) &&
-        (PVi_1a = calloc(ntabax, sizeof(int)))      &&
-        (PVi_2a = calloc(ntabax, sizeof(int)))      &&
-        (PSi_1a = calloc(ntabax, sizeof(char[72]))) &&
-        (PSi_2a = calloc(ntabax, sizeof(char[72]))) &&
-        (PVi_3a = calloc(ntabax, sizeof(int)))      &&
-        (tabidx = calloc(ntabax, sizeof(int))))) {
-    status = wcserr_set(WCSHDR_ERRMSG(WCSHDRERR_MEMORY));
-    goto cleanup;
-  }
-
-  for (itabax = 0; itabax < ntabax; itabax++) {
-    /* Remember that calloc() zeroes allocated memory. */
-    PVi_1a[itabax] = 1;
-    PVi_2a[itabax] = 1;
-    PVi_3a[itabax] = 1;
-  }
-
-  for (ip = 0; ip < wcs->nps; ip++) {
-    itabax = tabax[wcs->ps[ip].i - 1];
-    if (itabax >= 0) {
-      switch (wcs->ps[ip].m) {
-      case 0:
-        /* EXTNAME. */
-        strcpy(PSi_0a[itabax], wcs->ps[ip].value);
-        wcsutil_null_fill(72, PSi_0a[itabax]);
-        break;
-      case 1:
-        /* TTYPEn for coordinate array. */
-        strcpy(PSi_1a[itabax], wcs->ps[ip].value);
-        wcsutil_null_fill(72, PSi_1a[itabax]);
-        break;
-      case 2:
-        /* TTYPEn for index vector. */
-        strcpy(PSi_2a[itabax], wcs->ps[ip].value);
-        wcsutil_null_fill(72, PSi_2a[itabax]);
-        break;
-      }
-    }
-  }
-
-  for (ip = 0; ip < wcs->npv; ip++) {
-    itabax = tabax[wcs->pv[ip].i - 1];
-    if (itabax >= 0) {
-      switch (wcs->pv[ip].m) {
-      case 1:
-        /* EXTVER. */
-        PVi_1a[itabax] = (int)(wcs->pv[ip].value + 0.5);
-        break;
-      case 2:
-        /* EXTLEVEL. */
-        PVi_2a[itabax] = (int)(wcs->pv[ip].value + 0.5);
-        break;
-      case 3:
-        /* Table axis number. */
-        PVi_3a[itabax] = (int)(wcs->pv[ip].value + 0.5);
-        break;
-      }
-    }
-  }
-
-
-  /* Determine the number of independent tables. */
-  for (itabax = 0; itabax < ntabax; itabax++) {
-    /* These have no defaults. */
-    if (!PSi_0a[itabax][0] || !PSi_1a[itabax][0]) {
-      status = wcserr_set(WCSERR_SET(WCSHDRERR_BAD_TABULAR_PARAMS),
-        "Invalid tabular parameters: PSi_0a and PSi_1a must be specified");
-      goto cleanup;
-    }
-
-    tabidx[itabax] = -1;
-    for (jtabax = 0; jtabax < i; jtabax++) {
-      /* EXTNAME, EXTVER, EXTLEVEL, and TTYPEn for the coordinate array */
-      /* must match for each axis of a multi-dimensional lookup table.  */
-      if (strcmp(PSi_0a[itabax], PSi_0a[jtabax]) == 0 &&
-          strcmp(PSi_1a[itabax], PSi_1a[jtabax]) == 0 &&
-          PVi_1a[itabax] == PVi_1a[jtabax] &&
-          PVi_2a[itabax] == PVi_2a[jtabax]) {
-        tabidx[itabax] = tabidx[jtabax];
-        break;
-      }
-    }
-
-    if (jtabax == itabax) {
-      tabidx[itabax] = wcs->ntab;
-      wcs->ntab++;
-    }
-  }
-
-  if (!(wcs->tab = calloc(wcs->ntab, sizeof(struct tabprm)))) {
-    status = wcserr_set(WCSHDR_ERRMSG(WCSHDRERR_MEMORY));
-    goto cleanup;
-  }
-  wcs->m_tab = wcs->tab;
-
-  /* Table dimensionality; find the largest axis number. */
-  for (itabax = 0; itabax < ntabax; itabax++) {
-    tabp = wcs->tab + tabidx[itabax];
-
-    /* PVi_3a records the 1-relative table axis number. */
-    if (PVi_3a[itabax] > tabp->M) {
-      tabp->M = PVi_3a[itabax];
-    }
-  }
-
-  for (itab = 0; itab < wcs->ntab; itab++) {
-    if ((status = tabini(1, wcs->tab[itab].M, 0, wcs->tab + itab))) {
-      if (status == 3) status = 5;
-      wcserr_set(WCSHDR_ERRMSG(status));
-      goto cleanup;
-    }
-  }
-
-
-  /* Copy parameters into the tabprm structs. */
-  for (i = 0; i < naxis; i++) {
-    if ((itabax = tabax[i]) < 0) {
-      /* Not a -TAB axis. */
-      continue;
-    }
-
-    /* PVi_3a records the 1-relative table axis number. */
-    m = PVi_3a[itabax] - 1;
-
-    tabp = wcs->tab + tabidx[itabax];
-    tabp->map[m] = i;
-    tabp->crval[m] = wcs->crval[i];
-  }
-
-  /* Check for completeness. */
-  for (itab = 0; itab < wcs->ntab; itab++) {
-    for (m = 0; m < wcs->tab[itab].M; m++) {
-      if (wcs->tab[itab].map[m] < 0) {
-        status = wcserr_set(WCSERR_SET(WCSHDRERR_BAD_TABULAR_PARAMS),
-          "Invalid tabular parameters: the axis mapping is undefined");
-        goto cleanup;
-      }
-    }
-  }
-
-
-  /* Set up for reading the arrays; how many arrays are there? */
-  for (itabax = 0; itabax < ntabax; itabax++) {
-    /* Does this -TAB axis have a non-degenerate index array? */
-    if (PSi_2a[itabax][0]) {
-      wcs->nwtb++;
-    }
-  }
-
-  /* Add one coordinate array for each table. */
-  wcs->nwtb += wcs->ntab;
-
-  /* Allocate memory for structs to be returned. */
-  if (!(wcs->wtb = calloc(wcs->nwtb, sizeof(struct wtbarr)))) {
-    wcs->nwtb = 0;
-
-    status = wcserr_set(WCSHDR_ERRMSG(WCSHDRERR_MEMORY));
-    goto cleanup;
-  }
-  wcs->m_wtb = wcs->wtb;
-
-  /* Set pointers for the index and coordinate arrays. */
-  wtbp = wcs->wtb;
-  for (itab = 0; itab < wcs->ntab; itab++) {
-    getcrd = 1;
-    for (itabax = 0; itabax < ntabax; itabax++) {
-      if (tabidx[itabax] != itab) continue;
-
-      if (getcrd) {
-        /* Coordinate array. */
-        wtbp->i = itabax + 1;
-        wtbp->m = PVi_3a[itabax];
-        wtbp->kind = 'c';
-
-        strcpy(wtbp->extnam, PSi_0a[itabax]);
-        wtbp->extver = PVi_1a[itabax];
-        wtbp->extlev = PVi_2a[itabax];
-        strcpy(wtbp->ttype, PSi_1a[itabax]);
-        wtbp->row    = 1L;
-        wtbp->ndim   = wcs->tab[itab].M + 1;
-        wtbp->dimlen = wcs->tab[itab].K;
-        wtbp->arrayp = &(wcs->tab[itab].coord);
-
-        /* Signal for tabset() to take this memory. */
-        wcs->tab[itab].m_coord = (double *)0x1;
-
-        wtbp++;
-        getcrd = 0;
-      }
-
-      if (PSi_2a[itabax][0]) {
-        /* Index array. */
-        wtbp->i = itabax + 1;
-        wtbp->m = PVi_3a[itabax];
-        wtbp->kind = 'i';
-
-        m = wtbp->m - 1;
-        strcpy(wtbp->extnam, PSi_0a[itabax]);
-        wtbp->extver = PVi_1a[itabax];
-        wtbp->extlev = PVi_2a[itabax];
-        strcpy(wtbp->ttype, PSi_2a[itabax]);
-        wtbp->row    = 1L;
-        wtbp->ndim   = 1;
-        wtbp->dimlen = wcs->tab[itab].K + m;
-        wtbp->arrayp = wcs->tab[itab].index + m;
-
-        /* Signal for tabset() to take this memory. */
-        wcs->tab[itab].m_indxs[m] = (double *)0x1;
-
-        wtbp++;
-      }
-    }
-  }
-
-  status = 0;
-
-cleanup:
-  if (tabax)  free(tabax);
-  if (tabidx) free(tabidx);
-  if (PSi_0a) free(PSi_0a);
-  if (PVi_1a) free(PVi_1a);
-  if (PVi_2a) free(PVi_2a);
-  if (PSi_1a) free(PSi_1a);
-  if (PSi_2a) free(PSi_2a);
-  if (PVi_3a) free(PVi_3a);
-
-  if (status) {
-    if (wcs->tab) free(wcs->tab);
-    if (wcs->wtb) free(wcs->wtb);
-  }
-
-  return status;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int wcsidx(int nwcs, struct wcsprm **wcs, int alts[27])
-
-{
-  int a, iwcs;
-  struct wcsprm *wcsp;
-
-  for (a = 0; a < 27; a++) {
-    alts[a] = -1;
-  }
-
-  if (wcs == 0x0) {
-    return WCSHDRERR_NULL_POINTER;
-  }
-
-  wcsp = *wcs;
-  for (iwcs = 0; iwcs < nwcs; iwcs++, wcsp++) {
-    if (wcsp->colnum || wcsp->colax[0]) continue;
-
-    if (wcsp->alt[0] == ' ') {
-      a = 0;
-    } else {
-      a = wcsp->alt[0] - 'A' + 1;
-    }
-
-    alts[a] = iwcs;
-  }
-
-  return 0;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int wcsbdx(int nwcs, struct wcsprm **wcs, int type, short alts[1000][28])
-
-{
-  short  *ip;
-  int    a, i, icol, iwcs;
-  struct wcsprm *wcsp;
-
-  for (ip = alts[0]; ip < alts[0] + 28*1000; ip++) {
-    *ip = -1;
-  }
-
-  for (icol = 0; icol < 1000; icol++) {
-    alts[icol][27] = 0;
-  }
-
-  if (wcs == 0x0) {
-    return WCSHDRERR_NULL_POINTER;
-  }
-
-  wcsp = *wcs;
-  for (iwcs = 0; iwcs < nwcs; iwcs++, wcsp++) {
-    if (wcsp->alt[0] == ' ') {
-      a = 0;
-    } else {
-      a = wcsp->alt[0] - 'A' + 1;
-    }
-
-    if (type) {
-      /* Pixel list. */
-      if (wcsp->colax[0]) {
-        for (i = 0; i < wcsp->naxis; i++) {
-          alts[wcsp->colax[i]][a]  = iwcs;
-          alts[wcsp->colax[i]][27]++;
-        }
-      } else if (!wcsp->colnum) {
-        alts[0][a]  = iwcs;
-        alts[0][27]++;
-      }
-
-    } else {
-      /* Binary table image array. */
-      if (wcsp->colnum) {
-        alts[wcsp->colnum][a] = iwcs;
-        alts[wcsp->colnum][27]++;
-      } else if (!wcsp->colax[0]) {
-        alts[0][a]  = iwcs;
-        alts[0][27]++;
-      }
-    }
-  }
-
-  return 0;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int wcsvfree(int *nwcs, struct wcsprm **wcs)
-
-{
-  int a, status = 0;
-  struct wcsprm *wcsp;
-
-  if (wcs == 0x0) {
-    return WCSHDRERR_NULL_POINTER;
-  }
-
-  wcsp = *wcs;
-  for (a = 0; a < *nwcs; a++, wcsp++) {
-    status |= wcsfree(wcsp);
-  }
-
-  free(*wcs);
-
-  *nwcs = 0;
-  *wcs = 0x0;
-
-  return status;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int wcshdo(int relax, struct wcsprm *wcs, int *nkeyrec, char **header)
-
-/* ::: CUBEFACE and STOKES handling? */
-
-{
-  static const char *function = "wcshdo";
-
-  char alt, comment[72], keyvalue[72], keyword[16], obsg[8] = "OBSG?",
-       obsgeo[8] = "OBSGEO-?", ptype, xtype, xyz[] = "XYZ";
-  int  bintab, col0, *colax, colnum, i, j, k, naxis, pixlist, primage,
-       status = 0;
-  struct wcserr **err;
-
-  *nkeyrec = 0;
-  *header  = 0x0;
-
-  if (wcs == 0x0) return WCSHDRERR_NULL_POINTER;
-  err = &(wcs->err);
-
-  if (wcs->flag != WCSSET) {
-    if ((status = wcsset(wcs))) return status;
-  }
-
-  if ((naxis = wcs->naxis) == 0) {
-    return 0;
-  }
-
-
-  /* These are mainly for convenience. */
-  alt = wcs->alt[0];
-  if (alt == ' ') alt = '\0';
-  colnum = wcs->colnum;
-  colax  = wcs->colax;
-
-  primage = 0;
-  bintab  = 0;
-  pixlist = 0;
-  if (colnum) {
-    bintab  = 1;
-    col0 = colnum;
-  } else if (colax[0]) {
-    pixlist = 1;
-    col0 = colax[0];
-  } else {
-    primage = 1;
-  }
-
-
-  /* WCS dimension. */
-  if (!pixlist) {
-    sprintf(keyvalue, "%20d", naxis);
-    wcshdo_util(relax, "WCSAXES", "WCAX", 0, 0x0, 0, 0, 0, alt, colnum, colax,
-      keyvalue, "Number of coordinate axes", nkeyrec, header, &status);
-  }
-
-  /* Reference pixel coordinates. */
-  for (j = 0; j < naxis; j++) {
-    sprintf(keyvalue, "%20.12G", wcs->crpix[j]);
-    wcshdo_util(relax, "CRPIX", "CRP", WCSHDO_CRPXna, "CRPX", 0, j+1, 0, alt,
-      colnum, colax, keyvalue, "Pixel coordinate of reference point",
-      nkeyrec, header, &status);
-  }
-
-  /* Linear transformation matrix. */
-  k = 0;
-  for (i = 0; i < naxis; i++) {
-    for (j = 0; j < naxis; j++, k++) {
-      if (i == j) {
-        if (wcs->pc[k] == 1.0) continue;
-      } else {
-        if (wcs->pc[k] == 0.0) continue;
-      }
-
-      sprintf(keyvalue, "%20.12G", wcs->pc[k]);
-      wcshdo_util(relax, "PC", bintab ? "PC" : "P", WCSHDO_TPCn_ka,
-        bintab ? 0x0 : "PC", i+1, j+1, 0, alt, colnum, colax, keyvalue,
-        "Coordinate transformation matrix element",
-        nkeyrec, header, &status);
-    }
-  }
-
-  /* Coordinate increment at reference point. */
-  for (i = 0; i < naxis; i++) {
-    sprintf(keyvalue, "%20.12G", wcs->cdelt[i]);
-    comment[0] = '\0';
-    if (wcs->cunit[i][0]) sprintf(comment, "[%s] ", wcs->cunit[i]);
-    strcat(comment, "Coordinate increment at reference point");
-    wcshdo_util(relax, "CDELT", "CDE", WCSHDO_CRPXna, "CDLT", i+1, 0, 0, alt,
-      colnum, colax, keyvalue, comment, nkeyrec, header, &status);
-  }
-
-  /* Units of coordinate increment and reference value. */
-  for (i = 0; i < naxis; i++) {
-    if (wcs->cunit[i][0] == '\0') continue;
-
-    sprintf(keyvalue, "'%s'", wcs->cunit[i]);
-    wcshdo_util(relax, "CUNIT", "CUN", WCSHDO_CRPXna, "CUNI", i+1, 0, 0, alt,
-      colnum, colax, keyvalue, "Units of coordinate increment and value",
-      nkeyrec, header, &status);
-  }
-
-  /* Coordinate type. */
-  for (i = 0; i < naxis; i++) {
-    if (wcs->ctype[i][0] == '\0') continue;
-
-    sprintf(keyvalue, "'%s'", wcs->ctype[i]);
-    strcpy(comment, "Coordinate type code");
-    if (i == wcs->lng || i == wcs->lat) {
-      if (strncmp(wcs->ctype[i], "RA--", 4) == 0) {
-        strcpy(comment, "Right ascension, ");
-      } else if (strncmp(wcs->ctype[i], "DEC-", 4) == 0) {
-        strcpy(comment, "Declination, ");
-      } else if (strncmp(wcs->ctype[i]+1, "LON", 3) == 0 ||
-                 strncmp(wcs->ctype[i]+1, "LAT", 3) == 0) {
-        switch (wcs->ctype[i][0]) {
-        case 'G':
-          strcpy(comment, "galactic ");
-          break;
-        case 'E':
-          strcpy(comment, "ecliptic ");
-        case 'H':
-          strcpy(comment, "helioecliptic ");
-        case 'S':
-          strcpy(comment, "supergalactic ");
-        }
-
-        if (i == wcs->lng) {
-          strcat(comment, "longitude, ");
-        } else {
-          strcat(comment, "latitude, ");
-        }
-
-        wcs->ctype[i][0] = toupper(wcs->ctype[i][0]);
-      }
-
-      strcat(comment, wcs->cel.prj.name);
-      strcat(comment, " projection");
-
-    } else if (i == wcs->spec) {
-      spctyp(wcs->ctype[i], 0x0, 0x0, comment, 0x0, &ptype, &xtype, 0x0);
-      if (ptype == xtype) {
-        strcat(comment, " (linear)");
-      } else {
-        switch (xtype) {
-        case 'F':
-          strcat(comment, " (linear in frequency)");
-          break;
-        case 'V':
-          strcat(comment, " (linear in velocity)");
-          break;
-        case 'W':
-          strcat(comment, " (linear in wavelength)");
-          break;
-        }
-      }
-    }
-
-    wcshdo_util(relax, "CTYPE", "CTY", WCSHDO_CRPXna, "CTYP", i+1, 0, 0, alt,
-      colnum, colax, keyvalue, comment, nkeyrec, header, &status);
-  }
-
-  /* Coordinate value at reference point. */
-  for (i = 0; i < naxis; i++) {
-    sprintf(keyvalue, "%20.12G", wcs->crval[i]);
-    comment[0] = '\0';
-    if (wcs->cunit[i][0]) sprintf(comment, "[%s] ", wcs->cunit[i]);
-    strcat(comment, "Coordinate value at reference point");
-    wcshdo_util(relax, "CRVAL", "CRV", WCSHDO_CRPXna, "CRVL", i+1, 0, 0, alt,
-      colnum, colax, keyvalue, comment, nkeyrec, header, &status);
-  }
-
-  /* Parameter values. */
-  for (k = 0; k < wcs->npv; k++) {
-    sprintf(keyvalue, "%20.12G", (wcs->pv[k]).value);
-    if ((wcs->pv[k]).i == (wcs->lng + 1)) {
-      switch ((wcs->pv[k]).m) {
-      case 1:
-        strcpy(comment, "[deg] Native longitude of the reference point");
-        break;
-      case 2:
-        strcpy(comment, "[deg] Native latitude  of the reference point");
-        break;
-      case 3:
-        if (primage) {
-          sprintf(keyword, "LONPOLE%c", alt);
-        } else if (bintab) {
-          sprintf(keyword, "LONP%d%c", colnum, alt);
-        } else {
-          sprintf(keyword, "LONP%d%c", colax[(wcs->pv[k]).i - 1], alt);
-        }
-        sprintf(comment, "[deg] alias for %s (has precedence)", keyword);
-        break;
-      case 4:
-        if (primage) {
-          sprintf(keyword, "LATPOLE%c", alt);
-        } else if (bintab) {
-          sprintf(keyword, "LATP%d%c", colnum, alt);
-        } else {
-          sprintf(keyword, "LATP%d%c", colax[(wcs->pv[k]).i - 1], alt);
-        }
-        sprintf(comment, "[deg] alias for %s (has precedence)", keyword);
-        break;
-      }
-    } else if ((wcs->pv[k]).i == (wcs->lat + 1)) {
-      sprintf(comment, "%s projection parameter", wcs->cel.prj.code);
-    } else {
-      strcpy(comment, "Coordinate transformation parameter");
-    }
-
-    wcshdo_util(relax, "PV", "V", WCSHDO_PVn_ma, "PV", wcs->pv[k].i, -1,
-      wcs->pv[k].m, alt, colnum, colax, keyvalue, comment,
-      nkeyrec, header, &status);
-  }
-
-  for (k = 0; k < wcs->nps; k++) {
-    sprintf(keyvalue, "'%s'", (wcs->ps[k]).value);
-
-    wcshdo_util(relax, "PS", "S", WCSHDO_PVn_ma, "PS", wcs->ps[k].i, -1,
-      wcs->ps[k].m, alt, colnum, colax, keyvalue,
-      "Coordinate transformation parameter",
-      nkeyrec, header, &status);
-  }
-
-  /* Celestial and spectral transformation parameters. */
-  if (!undefined(wcs->lonpole)) {
-    sprintf(keyvalue, "%20.12G", wcs->lonpole);
-    wcshdo_util(relax, "LONPOLE", "LONP", 0, 0x0, 0, 0, 0, alt,
-      colnum, colax, keyvalue, "[deg] Native longitude of celestial pole",
-      nkeyrec, header, &status);
-  }
-
-  if (!undefined(wcs->latpole)) {
-    sprintf(keyvalue, "%20.12G", wcs->latpole);
-    wcshdo_util(relax, "LATPOLE", "LATP", 0, 0x0, 0, 0, 0, alt,
-      colnum, colax, keyvalue, "[deg] Native latitude of celestial pole",
-      nkeyrec, header, &status);
-  }
-
-  if (!undefined(wcs->restfrq)) {
-    sprintf(keyvalue, "%20.12G", wcs->restfrq);
-    wcshdo_util(relax, "RESTFRQ", "RFRQ", 0, 0x0, 0, 0, 0, alt,
-      colnum, colax, keyvalue, "[Hz] Line rest frequency",
-      nkeyrec, header, &status);
-  }
-
-  if (!undefined(wcs->restwav)) {
-    sprintf(keyvalue, "%20.12G", wcs->restwav);
-    wcshdo_util(relax, "RESTWAV", "RWAV", 0, 0x0, 0, 0, 0, alt,
-      colnum, colax, keyvalue, "[Hz] Line rest wavelength",
-      nkeyrec, header, &status);
-  }
-
-  /* Coordinate system title. */
-  if (wcs->wcsname[0]) {
-    sprintf(keyvalue, "'%s'", wcs->wcsname);
-    if (bintab) {
-      wcshdo_util(relax, "WCSNAME", "WCSN", 0, 0x0, 0, 0, 0, alt,
-        colnum, colax, keyvalue, "Coordinate system title",
-        nkeyrec, header, &status);
-    } else {
-      /* TWCS was a mistake. */
-      wcshdo_util(relax, "WCSNAME", "TWCS", WCSHDO_WCSNna, "WCSN", 0, 0, 0,
-        alt, colnum, colax, keyvalue, "Coordinate system title",
-        nkeyrec, header, &status);
-    }
-  }
-
-  /* Coordinate axis title. */
-  if (wcs->cname) {
-    for (i = 0; i < naxis; i++) {
-      if (wcs->cname[i][0] == '\0') continue;
-
-      sprintf(keyvalue, "'%s'", wcs->cname[i]);
-      wcshdo_util(relax, "CNAME", "CNA", WCSHDO_CNAMna, "CNAM", i+1, 0, 0,
-        alt, colnum, colax, keyvalue, "Axis name for labelling purposes",
-        nkeyrec, header, &status);
-    }
-  }
-
-  /* Random error in coordinate. */
-  if (wcs->crder) {
-    for (i = 0; i < naxis; i++) {
-      if (undefined(wcs->crder[i])) continue;
-
-      sprintf(keyvalue, "%20.12G", wcs->crder[i]);
-      comment[0] = '\0';
-      if (wcs->cunit[i][0]) sprintf(comment, "[%s] ", wcs->cunit[i]);
-      strcat(comment, "Random error in coordinate");
-      wcshdo_util(relax, "CRDER", "CRD", WCSHDO_CNAMna, "CRDE", i+1, 0, 0,
-        alt, colnum, colax, keyvalue, comment, nkeyrec, header, &status);
-    }
-  }
-
-  /* Systematic error in coordinate. */
-  if (wcs->csyer) {
-    for (i = 0; i < naxis; i++) {
-      if (undefined(wcs->csyer[i])) continue;
-
-      sprintf(keyvalue, "%20.12G", wcs->csyer[i]);
-      comment[0] = '\0';
-      if (wcs->cunit[i][0]) sprintf(comment, "[%s] ", wcs->cunit[i]);
-      strcat(comment, "Systematic error in coordinate");
-      wcshdo_util(relax, "CSYER", "CSY", WCSHDO_CNAMna, "CSYE", i+1, 0, 0,
-        alt, colnum, colax, keyvalue, comment, nkeyrec, header, &status);
-    }
-  }
-
-  /* Equatorial coordinate system type. */
-  if (wcs->radesys[0]) {
-    sprintf(keyvalue, "'%s'", wcs->radesys);
-    wcshdo_util(relax, "RADESYS", "RADE", 0, 0x0, 0, 0, 0, alt,
-      colnum, colax, keyvalue, "Equatorial coordinate system",
-      nkeyrec, header, &status);
-  }
-
-  /* Equinox of equatorial coordinate system. */
-  if (!undefined(wcs->equinox)) {
-    sprintf(keyvalue, "%20.12G", wcs->equinox);
-    wcshdo_util(relax, "EQUINOX", "EQUI", 0, 0x0, 0, 0, 0, alt,
-      colnum, colax, keyvalue, "[yr] Equinox of equatorial coordinates",
-      nkeyrec, header, &status);
-  }
-
-  /* Reference frame of spectral coordinates. */
-  if (wcs->specsys[0]) {
-    sprintf(keyvalue, "'%s'", wcs->specsys);
-    wcshdo_util(relax, "SPECSYS", "SPEC", 0, 0x0, 0, 0, 0, alt,
-      colnum, colax, keyvalue, "Reference frame of spectral coordinates",
-      nkeyrec, header, &status);
-  }
-
-  /* Reference frame of spectral observation. */
-  if (wcs->ssysobs[0]) {
-    sprintf(keyvalue, "'%s'", wcs->ssysobs);
-    wcshdo_util(relax, "SSYSOBS", "SOBS", 0, 0x0, 0, 0, 0, alt,
-      colnum, colax, keyvalue, "Reference frame of spectral observation",
-      nkeyrec, header, &status);
-  }
-
-  /* Observer's velocity towards source. */
-  if (!undefined(wcs->velosys)) {
-    sprintf(keyvalue, "%20.12G", wcs->velosys);
-    wcshdo_util(relax, "VELOSYS", "VSYS", 0, 0x0, 0, 0, 0, alt,
-      colnum, colax, keyvalue, "[m/s] Velocity towards source",
-      nkeyrec, header, &status);
-  }
-
-  /* Reference frame of source redshift. */
-  if (wcs->ssyssrc[0]) {
-    sprintf(keyvalue, "'%s'", wcs->ssyssrc);
-    wcshdo_util(relax, "SSYSSRC", "SSRC", 0, 0x0, 0, 0, 0, alt,
-      colnum, colax, keyvalue, "Reference frame of source redshift",
-      nkeyrec, header, &status);
-  }
-
-  /* Redshift of the source. */
-  if (!undefined(wcs->zsource)) {
-    sprintf(keyvalue, "%20.12G", wcs->zsource);
-    wcshdo_util(relax, "ZSOURCE", "ZSOU", 0, 0x0, 0, 0, 0, alt,
-      colnum, colax, keyvalue, "Redshift of the source",
-      nkeyrec, header, &status);
-  }
-
-  /* Observatory coordinates. */
-  for (k = 0; k < 3; k++) {
-    if (undefined(wcs->obsgeo[k])) continue;
-
-    sprintf(keyvalue, "%20.12G", wcs->obsgeo[k]);
-    sprintf(comment, "[m] ITRF observatory %c-coordinate", xyz[k]);
-    obsgeo[7] = xyz[k];
-    obsg[4]   = xyz[k];
-    wcshdo_util(relax, obsgeo, obsg, 0, 0x0, 0, 0, 0, ' ',
-      colnum, colax, keyvalue, comment, nkeyrec, header, &status);
-  }
-
-  /* MJD of observation. */
-  if (!undefined(wcs->mjdobs)) {
-    sprintf(keyvalue, "%20.12G", wcs->mjdobs);
-
-    strcpy(comment, "[d] MJD of observation");
-    if (wcs->dateobs[0]) {
-      if (primage || (relax & 1) == 0) {
-        sprintf(comment+22, " matching DATE-OBS");
-      } else {
-        sprintf(comment+22, " matching DOBS%d", col0);
-      }
-    }
-
-    wcshdo_util(relax, "MJD-OBS", "MJDOB", 0, 0x0, 0, 0, 0, ' ',
-      colnum, colax, keyvalue, comment, nkeyrec, header, &status);
-  }
-
-  /* MJD mid-observation time. */
-  if (!undefined(wcs->mjdavg)) {
-    sprintf(keyvalue, "%20.12G", wcs->mjdavg);
-
-    strcpy(comment, "[d] MJD mid-observation");
-    if (wcs->dateavg[0]) {
-      if (primage) {
-        sprintf(comment+23, " matching DATE-AVG");
-      } else {
-        sprintf(comment+23, " matching DAVG%d", col0);
-      }
-    }
-
-    wcshdo_util(relax, "MJD-AVG", "MJDA", 0, 0x0, 0, 0, 0, ' ',
-      colnum, colax, keyvalue, comment, nkeyrec, header, &status);
-  }
-
-  /* ISO-8601 date corresponding to MJD-OBS. */
-  if (wcs->dateobs[0]) {
-    sprintf(keyvalue, "'%s'", wcs->dateobs);
-
-    strcpy(comment, "ISO-8601 observation date");
-    if (!undefined(wcs->mjdobs)) {
-      if (primage) {
-        sprintf(comment+25, " matching MJD-OBS");
-      } else {
-        sprintf(comment+25, " matching MJDOB%d", col0);
-      }
-    }
-
-    if (relax & 1) {
-      /* Allow DOBSn. */
-      wcshdo_util(relax, "DATE-OBS", "DOBS", WCSHDO_DOBSn, 0x0, 0, 0, 0,
-        ' ', colnum, colax, keyvalue, comment, nkeyrec, header, &status);
-    } else {
-      /* Force DATE-OBS. */
-      wcshdo_util(relax, "DATE-OBS", 0x0, 0, 0x0, 0, 0, 0, ' ', 0,
-        0x0, keyvalue, comment, nkeyrec, header, &status);
-    }
-  }
-
-  /* ISO-8601 date corresponding to MJD-OBS. */
-  if (wcs->dateavg[0]) {
-    sprintf(keyvalue, "'%s'", wcs->dateavg);
-
-    strcpy(comment, "ISO-8601 mid-observation date");
-    if (!undefined(wcs->mjdavg)) {
-      if (primage) {
-        sprintf(comment+29, " matching MJD-AVG");
-      } else {
-        sprintf(comment+29, " matching MJDA%d", col0);
-      }
-    }
-
-    wcshdo_util(relax, "DATE-AVG", "DAVG", 0, 0x0, 0, 0, 0, ' ',
-      colnum, colax, keyvalue, comment, nkeyrec, header, &status);
-  }
-
-  if (status == WCSHDRERR_MEMORY) {
-    wcserr_set(WCSHDR_ERRMSG(status));
-  }
-  return status;
-}
-
-/*--------------------------------------------------------------------------*/
-
-void wcshdo_util(
-  int relax,
-  const char pikey[],
-  const char tbkey[],
-  int level,
-  const char tlkey[],
-  int i,
-  int j,
-  int m,
-  char alt,
-  int  btcol,
-  int  plcol[],
-  char keyvalue[],
-  const char keycomment[],
-  int  *nkeyrec,
-  char **header,
-  int  *status)
-
-{
-  char ch0, ch1, *hptr, keyword[16], *kptr;
-  int  nbyte, nc = 47, nv;
-
-  if (*status) return;
-
-  /* Reallocate memory in blocks of 2880 bytes. */
-  if ((*nkeyrec)%32 == 0) {
-    nbyte = ((*nkeyrec)/32 + 1) * 2880;
-    if (!(hptr = realloc(*header, nbyte))) {
-      *status = WCSHDRERR_MEMORY;
-      return;
-    }
-
-    *header = hptr;
-  }
-
-  /* Construct the keyword. */
-  if (alt == ' ') alt = '\0';
-  if (btcol) {
-    /* Binary table image array. */
-    if (i > 0 && j) {
-      if (j > 0) {
-        sprintf(keyword, "%d%d%s%d%c", i, j, tbkey, btcol, alt);
-      } else {
-        sprintf(keyword, "%d%s%d_%d%c", i, tbkey, btcol, m, alt);
-      }
-    } else if (i > 0) {
-      sprintf(keyword, "%d%s%d%c", i, tbkey, btcol, alt);
-    } else if (j > 0) {
-      sprintf(keyword, "%d%s%d%c", j, tbkey, btcol, alt);
-    } else {
-      sprintf(keyword, "%s%d%c", tbkey, btcol, alt);
-    }
-
-    if ((strlen(keyword) < 8) && tlkey && (relax & level)) {
-      /* Use the long form. */
-      if (i > 0 && j) {
-        if (j > 0) {
-          sprintf(keyword, "%d%d%s%d%c", i, j, tlkey, btcol, alt);
-        } else {
-          sprintf(keyword, "%d%s%d_%d%c", i, tlkey, btcol, m, alt);
-        }
-      } else if (i > 0) {
-        sprintf(keyword, "%d%s%d%c", i, tlkey, btcol, alt);
-      } else if (j > 0) {
-        sprintf(keyword, "%d%s%d%c", j, tlkey, btcol, alt);
-      } else {
-        sprintf(keyword, "%s%d%c", tlkey, btcol, alt);
-      }
-    }
-
-  } else if (plcol && plcol[0]) {
-    /* Pixel list. */
-    if (i > 0 && j) {
-      if (j > 0) {
-        sprintf(keyword, "T%s%d_%d%c", tbkey, plcol[i-1], plcol[j-1], alt);
-      } else {
-        sprintf(keyword, "T%s%d_%d%c", tbkey, plcol[i-1], m, alt);
-      }
-    } else if (i > 0) {
-      sprintf(keyword, "T%s%d%c", tbkey, plcol[i-1], alt);
-    } else if (j > 0) {
-      sprintf(keyword, "T%s%d%c", tbkey, plcol[j-1], alt);
-    } else {
-      sprintf(keyword, "%s%d%c", tbkey, plcol[0], alt);
-    }
-
-    if ((strlen(keyword) < 8) && tlkey && (relax & level)) {
-      /* Use the long form. */
-      if (i > 0 && j) {
-        if (j > 0) {
-          sprintf(keyword, "T%s%d_%d%c", tlkey, plcol[i-1], plcol[j-1], alt);
-        } else {
-          sprintf(keyword, "T%s%d_%d%c", tlkey, plcol[i-1], m, alt);
-        }
-      } else if (i > 0) {
-        sprintf(keyword, "T%s%d%c", tlkey, plcol[i-1], alt);
-      } else if (j > 0) {
-        sprintf(keyword, "T%s%d%c", tlkey, plcol[j-1], alt);
-      } else {
-        sprintf(keyword, "%s%d%c", tlkey, plcol[0], alt);
-      }
-    }
-  } else {
-    if (i > 0 && j) {
-      if (j > 0) {
-        sprintf(keyword, "%s%d_%d%c", pikey, i, j, alt);
-      } else {
-        sprintf(keyword, "%s%d_%d%c", pikey, i, m, alt);
-      }
-    } else if (i > 0) {
-      sprintf(keyword, "%s%d%c", pikey, i, alt);
-    } else if (j > 0) {
-      sprintf(keyword, "%s%d%c", pikey, j, alt);
-    } else {
-      sprintf(keyword, "%s%c", pikey, alt);
-    }
-  }
-
-  /* Double-up single-quotes in the keyvalue. */
-  hptr = keyvalue + 1;
-  while (*hptr) {
-    if (*hptr == '\'') {
-      kptr = hptr++;
-      if (*hptr) {
-        ch0 = *kptr;
-        while (*kptr) {
-          ch1 = *(++kptr);
-          *kptr = ch0;
-          ch0 = ch1;
-        }
-      }
-    }
-
-    hptr++;
-  }
-
-  if ((nv = strlen(keyvalue) > 20)) {
-    /* Rob the keycomment to make space for the keyvalue. */
-    nc -= (nv - 20);
-  }
-
-  hptr = *header + (80 * ((*nkeyrec)++));
-  sprintf(hptr, "%-8.8s= %-20s / %-*.*s", keyword, keyvalue, nc, nc,
-    keycomment);
-}
diff --git a/astropy/wcs/src/wcslib/C/wcshdr.h b/astropy/wcs/src/wcslib/C/wcshdr.h
deleted file mode 100644
index 18948a9..0000000
--- a/astropy/wcs/src/wcslib/C/wcshdr.h
+++ /dev/null
@@ -1,1133 +0,0 @@
-/*============================================================================
-
-  WCSLIB 4.10 - an implementation of the FITS WCS standard.
-  Copyright (C) 1995-2012, Mark Calabretta
-
-  This file is part of WCSLIB.
-
-  WCSLIB is free software: you can redistribute it and/or modify it under the
-  terms of the GNU Lesser General Public License as published by the Free
-  Software Foundation, either version 3 of the License, or (at your option)
-  any later version.
-
-  WCSLIB 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 Lesser General Public License for
-  more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with WCSLIB.  If not, see <http://www.gnu.org/licenses/>.
-
-  Correspondence concerning WCSLIB may be directed to:
-    Internet email: mcalabre at atnf.csiro.au
-    Postal address: Dr. Mark Calabretta
-                    Australia Telescope National Facility, CSIRO
-                    PO Box 76
-                    Epping NSW 1710
-                    AUSTRALIA
-
-  Author: Mark Calabretta, Australia Telescope National Facility
-  http://www.atnf.csiro.au/~mcalabre/index.html
-  $Id: wcshdr.h,v 4.10 2012/02/05 23:41:44 cal103 Exp $
-*=============================================================================
-*
-* WCSLIB 4.10 - C routines that implement the FITS World Coordinate System
-* (WCS) standard.  Refer to
-*
-*   "Representations of world coordinates in FITS",
-*   Greisen, E.W., & Calabretta, M.R. 2002, A&A, 395, 1061 (Paper I)
-*
-*   "Representations of celestial coordinates in FITS",
-*   Calabretta, M.R., & Greisen, E.W. 2002, A&A, 395, 1077 (Paper II)
-*
-*   "Representations of spectral coordinates in FITS",
-*   Greisen, E.W., Calabretta, M.R., Valdes, F.G., & Allen, S.L.
-*   2006, A&A, 446, 747 (Paper III)
-*
-* Refer to the README file provided with WCSLIB for an overview of the
-* library.
-*
-*
-* Summary of the wcshdr routines
-* ------------------------------
-* Routines in this suite are aimed at extracting WCS information from a FITS
-* file.  They provide the high-level interface between the FITS file and the
-* WCS coordinate transformation routines.
-*
-* Additionally, function wcshdo() is provided to write out the contents of a
-* wcsprm struct as a FITS header.
-*
-* Briefly, the anticipated sequence of operations is as follows:
-*
-*   - 1: Open the FITS file and read the image or binary table header, e.g.
-*        using CFITSIO routine fits_hdr2str().
-*
-*   - 2: Parse the header using wcspih() or wcsbth(); they will automatically
-*        interpret 'TAB' header keywords using wcstab().
-*
-*   - 3: Allocate memory for, and read 'TAB' arrays from the binary table
-*        extension, e.g. using CFITSIO routine fits_read_wcstab() - refer to
-*        the prologue of getwcstab.h.  wcsset() will automatically take
-*        control of this allocated memory, in particular causing it to be
-*        free'd by wcsfree().
-*
-*   - 4: Translate non-standard WCS usage using wcsfix(), see wcsfix.h.
-*
-*   - 5: Initialize wcsprm struct(s) using wcsset() and calculate coordinates
-*        using wcsp2s() and/or wcss2p().  Refer to the prologue of wcs.h for a
-*        description of these and other high-level WCS coordinate
-*        transformation routines.
-*
-*   - 6: Clean up by freeing memory with wcsvfree().
-*
-* In detail:
-*
-* - wcspih() is a high-level FITS WCS routine that parses an image header.  It
-*   returns an array of up to 27 wcsprm structs on each of which it invokes
-*   wcstab().
-*
-* - wcsbth() is the analogue of wcspih() for use with binary tables; it
-*   handles image array and pixel list keywords.  As an extension of the FITS
-*   WCS standard, it also recognizes image header keywords which may be used
-*   to provide default values via an inheritance mechanism.
-*
-* - wcstab() assists in filling in members of the wcsprm struct associated
-*   with coordinate lookup tables ('TAB').  These are based on arrays stored
-*   in a FITS binary table extension (BINTABLE) that are located by PVi_ma
-*   keywords in the image header.
-*
-* - wcsidx() and wcsbdx() are utility routines that return the index for a
-*   specified alternate coordinate descriptor in the array of wcsprm structs
-*   returned by wcspih() or wcsbth().
-*
-* - wcsvfree() deallocates memory for an array of wcsprm structs, such as
-*   returned by wcspih() or wcsbth().
-*
-* - wcshdo() writes out a wcsprm struct as a FITS header.
-*
-*
-* wcspih() - FITS WCS parser routine for image headers
-* ----------------------------------------------------
-* wcspih() is a high-level FITS WCS routine that parses an image header,
-* either that of a primary HDU or of an image extension.  All WCS keywords
-* defined in Papers I, II, and III are recognized, and also those used by the
-* AIPS convention and certain other keywords that existed in early drafts of
-* the WCS papers as explained in wcsbth() note 5.
-*
-* Given a character array containing a FITS image header, wcspih() identifies
-* and reads all WCS keywords for the primary coordinate representation and up
-* to 26 alternate representations.  It returns this information as an array of
-* wcsprm structs.
-*
-* wcspih() invokes wcstab() on each of the wcsprm structs that it returns.
-*
-* Use wcsbth() in preference to wcspih() for FITS headers of unknown type;
-* wcsbth() can parse image headers as well as binary table and pixel list
-* headers.
-*
-* Given and returned:
-*   header    char[]    Character array containing the (entire) FITS image
-*                       header from which to identify and construct the
-*                       coordinate representations, for example, as might be
-*                       obtained conveniently via the CFITSIO routine
-*                       fits_hdr2str().
-*
-*                       Each header "keyrecord" (formerly "card image")
-*                       consists of exactly 80 7-bit ASCII printing characters
-*                       in the range 0x20 to 0x7e (which excludes NUL, BS,
-*                       TAB, LF, FF and CR) especially noting that the
-*                       keyrecords are NOT null-terminated.
-*
-*                       For negative values of ctrl (see below), header[] is
-*                       modified so that WCS keyrecords processed by wcspih()
-*                       are removed from it.
-*
-* Given:
-*   nkeyrec   int       Number of keyrecords in header[].
-*
-*   relax     int       Degree of permissiveness:
-*                         0: Recognize only FITS keywords defined by the
-*                            published WCS standard.
-*                         WCSHDR_all: Admit all recognized informal
-*                            extensions of the WCS standard.
-*                       Fine-grained control of the degree of permissiveness
-*                       is also possible as explained in wcsbth() note 5.
-*
-*   ctrl      int       Error reporting and other control options for invalid
-*                       WCS and other header keyrecords:
-*                           0: Do not report any rejected header keyrecords.
-*                           1: Produce a one-line message stating the number
-*                              of WCS keyrecords rejected (nreject).
-*                           2: Report each rejected keyrecord and the reason
-*                              why it was rejected.
-*                           3: As above, but also report all non-WCS
-*                              keyrecords that were discarded, and the number
-*                              of coordinate representations (nwcs) found.
-*                       The report is written to stderr.
-*
-*                       For ctrl < 0, WCS keyrecords processed by wcspih()
-*                       are removed from header[]:
-*                          -1: Remove only valid WCS keyrecords whose values
-*                              were successfully extracted, nothing is
-*                              reported.
-*                          -2: Also remove WCS keyrecords that were rejected,
-*                              reporting each one and the reason that it was
-*                              rejected.
-*                          -3: As above, and also report the number of
-*                              coordinate representations (nwcs) found.
-*                         -11: Same as -1 but preserving the basic keywords
-*                              '{DATE,MJD}-{OBS,AVG}' and 'OBSGEO-{X,Y,Z}'.
-*                       If any keyrecords are removed from header[] it will
-*                       be null-terminated (NUL not being a legal FITS header
-*                       character), otherwise it will contain its original
-*                       complement of nkeyrec keyrecords and possibly not be
-*                       null-terminated.
-*
-* Returned:
-*   nreject   int*      Number of WCS keywords rejected for syntax errors,
-*                       illegal values, etc.  Keywords not recognized as WCS
-*                       keywords are simply ignored.  Refer also to wcsbth()
-*                       note 5.
-*
-*   nwcs      int*      Number of coordinate representations found.
-*
-*   wcs       struct wcsprm**
-*                       Pointer to an array of wcsprm structs containing up to
-*                       27 coordinate representations.
-*
-*                       Memory for the array is allocated by wcspih() which
-*                       also invokes wcsini() for each struct to allocate
-*                       memory for internal arrays and initialize their
-*                       members to default values.  Refer also to wcsbth()
-*                       note 8.  Note that wcsset() is not invoked on these
-*                       structs.
-*
-*                       This allocated memory must be freed by the user, first
-*                       by invoking wcsfree() for each struct, and then by
-*                       freeing the array itself.  A routine, wcsvfree(), is
-*                       provided to do this (see below).
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         1: Null wcsprm pointer passed.
-*                         2: Memory allocation failed.
-*                         4: Fatal error returned by Flex parser.
-*
-* Notes:
-*   Refer to wcsbth() notes 1, 2, 3, 5, 7, and 8.
-*
-*
-* wcsbth() - FITS WCS parser routine for binary table and image headers
-* ---------------------------------------------------------------------
-* wcsbth() is a high-level FITS WCS routine that parses a binary table header.
-* It handles image array and pixel list WCS keywords which may be present
-* together in one header.
-*
-* As an extension of the FITS WCS standard, wcsbth() also recognizes image
-* header keywords in a binary table header.  These may be used to provide
-* default values via an inheritance mechanism discussed in note 5 (c.f.
-* WCSHDR_AUXIMG and WCSHDR_ALLIMG), or may instead result in wcsprm structs
-* that are not associated with any particular column.  Thus wcsbth() can
-* handle primary image and image extension headers in addition to binary table
-* headers (it ignores NAXIS and does not rely on the presence of the TFIELDS
-* keyword).
-*
-* All WCS keywords defined in Papers I, II, and III are recognized, and also
-* those used by the AIPS convention and certain other keywords that existed in
-* early drafts of the WCS papers as explained in note 5 below.
-*
-* wcsbth() sets the colnum or colax[] members of the wcsprm structs that it
-* returns with the column number of an image array or the column numbers
-* associated with each pixel coordinate element in a pixel list.  wcsprm
-* structs that are not associated with any particular column, as may be
-* derived from image header keywords, have colnum == 0.
-*
-* Note 6 below discusses the number of wcsprm structs returned by wcsbth(),
-* and the circumstances in which image header keywords cause a struct to be
-* created.  See also note 9 concerning the number of separate images that may
-* be stored in a pixel list.
-*
-* The API to wcsbth() is similar to that of wcspih() except for the addition
-* of extra arguments that may be used to restrict its operation.  Like
-* wcspih(), wcsbth() invokes wcstab() on each of the wcsprm structs that it
-* returns.
-*
-* Given and returned:
-*   header    char[]    Character array containing the (entire) FITS binary
-*                       table, primary image, or image extension header from
-*                       which to identify and construct the coordinate
-*                       representations, for example, as might be obtained
-*                       conveniently via the CFITSIO routine fits_hdr2str().
-*
-*                       Each header "keyrecord" (formerly "card image")
-*                       consists of exactly 80 7-bit ASCII printing
-*                       characters in the range 0x20 to 0x7e (which excludes
-*                       NUL, BS, TAB, LF, FF and CR) especially noting that
-*                       the keyrecords are NOT null-terminated.
-*
-*                       For negative values of ctrl (see below), header[] is
-*                       modified so that WCS keyrecords processed by wcsbth()
-*                       are removed from it.
-*
-* Given:
-*   nkeyrec   int       Number of keyrecords in header[].
-*
-*   relax     int       Degree of permissiveness:
-*                         0: Recognize only FITS keywords defined by the
-*                            published WCS standard.
-*                         WCSHDR_all: Admit all recognized informal
-*                            extensions of the WCS standard.
-*                       Fine-grained control of the degree of permissiveness
-*                       is also possible, as explained in note 5 below.
-*
-*   ctrl      int       Error reporting and other control options for invalid
-*                       WCS and other header keyrecords:
-*                           0: Do not report any rejected header keyrecords.
-*                           1: Produce a one-line message stating the number
-*                              of WCS keyrecords rejected (nreject).
-*                           2: Report each rejected keyrecord and the reason
-*                              why it was rejected.
-*                           3: As above, but also report all non-WCS
-*                              keyrecords that were discarded, and the number
-*                              of coordinate representations (nwcs) found.
-*                       The report is written to stderr.
-*
-*                       For ctrl < 0, WCS keyrecords processed by wcsbth()
-*                       are removed from header[]:
-*                          -1: Remove only valid WCS keyrecords whose values
-*                              were successfully extracted, nothing is
-*                              reported.
-*                          -2: Also remove WCS keyrecords that were rejected,
-*                              reporting each one and the reason that it was
-*                              rejected.
-*                          -3: As above, and also report the number of
-*                              coordinate representations (nwcs) found.
-*                         -11: Same as -1 but preserving the basic keywords
-*                              '{DATE,MJD}-{OBS,AVG}' and 'OBSGEO-{X,Y,Z}'.
-*                       If any keyrecords are removed from header[] it will
-*                       be null-terminated (NUL not being a legal FITS header
-*                       character), otherwise it will contain its original
-*                       complement of nkeyrec keyrecords and possibly not be
-*                       null-terminated.
-*
-*   keysel    int       Vector of flag bits that may be used to restrict the
-*                       keyword types considered:
-*                         WCSHDR_IMGHEAD: Image header keywords.
-*                         WCSHDR_BIMGARR: Binary table image array.
-*                         WCSHDR_PIXLIST: Pixel list keywords.
-*                       If zero, there is no restriction.
-*
-*                       Keywords such as EQUIna or RFRQna that are common to
-*                       binary table image arrays and pixel lists (including
-*                       WCSNna and TWCSna, as explained in note 4 below) are
-*                       selected by both WCSHDR_BIMGARR and WCSHDR_PIXLIST.
-*                       Thus if inheritance via WCSHDR_ALLIMG is enabled as
-*                       discussed in note 5 and one of these shared keywords
-*                       is present, then WCSHDR_IMGHEAD and WCSHDR_PIXLIST
-*                       alone may be sufficient to cause the construction of
-*                       coordinate descriptions for binary table image arrays.
-*
-*   colsel    int*      Pointer to an array of table column numbers used to
-*                       restrict the keywords considered by wcsbth().
-*
-*                       A null pointer may be specified to indicate that there
-*                       is no restriction.  Otherwise, the magnitude of
-*                       cols[0] specifies the length of the array:
-*                         cols[0] > 0: the columns are included,
-*                         cols[0] < 0: the columns are excluded.
-*
-*                       For the pixel list keywords TPn_ka and TCn_ka (and
-*                       TPCn_ka and TCDn_ka if WCSHDR_LONGKEY is enabled), it
-*                       is an error for one column to be selected but not the
-*                       other.  This is unlike the situation with invalid
-*                       keyrecords, which are simply rejected, because the
-*                       error is not intrinsic to the header itself but
-*                       arises in the way that it is processed.
-*
-* Returned:
-*   nreject   int*      Number of WCS keywords rejected for syntax errors,
-*                       illegal values, etc.  Keywords not recognized as WCS
-*                       keywords are simply ignored, refer also to note 5
-*                       below.
-*
-*   nwcs      int*      Number of coordinate representations found.
-*
-*   wcs       struct wcsprm**
-*                       Pointer to an array of wcsprm structs containing up
-*                       to 27027 coordinate representations, refer to note 6
-*                       below.
-*
-*                       Memory for the array is allocated by wcsbth() which
-*                       also invokes wcsini() for each struct to allocate
-*                       memory for internal arrays and initialize their
-*                       members to default values.  Refer also to note 8
-*                       below.  Note that wcsset() is not invoked on these
-*                       structs.
-*
-*                       This allocated memory must be freed by the user, first
-*                       by invoking wcsfree() for each struct, and then by
-*                       freeing the array itself.  A routine, wcsvfree(), is
-*                       provided to do this (see below).
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         1: Null wcsprm pointer passed.
-*                         2: Memory allocation failed.
-*                         3: Invalid column selection.
-*                         4: Fatal error returned by Flex parser.
-*
-* Notes:
-*   1: wcspih() determines the number of coordinate axes independently for
-*      each alternate coordinate representation (denoted by the "a" value in
-*      keywords like CTYPEia) from the higher of
-*
-*        a: NAXIS,
-*        b: WCSAXESa,
-*        c: The highest axis number in any parameterized WCS keyword.  The
-*           keyvalue, as well as the keyword, must be syntactically valid
-*           otherwise it will not be considered.
-*
-*      If none of these keyword types is present, i.e. if the header only
-*      contains auxiliary WCS keywords for a particular coordinate
-*      representation, then no coordinate description is constructed for it.
-*
-*      wcsbth() is similar except that it ignores the NAXIS keyword if given
-*      an image header to process.
-*
-*      The number of axes, which is returned as a member of the wcsprm
-*      struct, may differ for different coordinate representations of the
-*      same image.
-*
-*   2: wcspih() and wcsbth() enforce correct FITS "keyword = value" syntax
-*      with regard to "= " occurring in columns 9 and 10.
-*
-*      However, they do recognize free-format character (NOST 100-2.0,
-*      Sect. 5.2.1), integer (Sect. 5.2.3), and floating-point values
-*      (Sect. 5.2.4) for all keywords.
-*
-*   3: Where CROTAn, CDi_ja, and PCi_ja occur together in one header wcspih()
-*      and wcsbth() treat them as described in the prologue to wcs.h.
-*
-*   4: WCS Paper I mistakenly defined the pixel list form of WCSNAMEa as
-*      TWCSna instead of WCSNna; the 'T' is meant to substitute for the axis
-*      number in the binary table form of the keyword - note that keywords
-*      defined in WCS Papers II and III that are not parameterised by axis
-*      number have identical forms for binary tables and pixel lists.
-*      Consequently wcsbth() always treats WCSNna and TWCSna as equivalent.
-*
-*   5: wcspih() and wcsbth() interpret the "relax" argument as a vector of
-*      flag bits to provide fine-grained control over what non-standard WCS
-*      keywords to accept.  The flag bits are subject to change in future and
-*      should be set by using the preprocessor macros (see below) for the
-*      purpose.
-*
-*      - WCSHDR_none: Don't accept any extensions (not even those in the
-*              errata).  Treat non-conformant keywords in the same way as
-*              non-WCS keywords in the header, i.e. simply ignore them.
-*
-*      - WCSHDR_all: Accept all extensions recognized by the parser.
-*
-*      - WCSHDR_reject: Reject non-standard keywords (that are not otherwise
-*              accepted).  A message will optionally be printed on stderr, as
-*              determined by the ctrl argument, and nreject will be
-*              incremented.
-*
-*              This flag may be used to signal the presence of non-standard
-*              keywords, otherwise they are simply passed over as though they
-*              did not exist in the header.
-*
-*              Useful for testing conformance of a FITS header to the WCS
-*              standard.
-*
-*      - WCSHDR_CROTAia: Accept CROTAia (wcspih()),
-*                               iCROTna (wcsbth()),
-*                               TCROTna (wcsbth()).
-*      - WCSHDR_EPOCHa:  Accept EPOCHa.
-*      - WCSHDR_VELREFa: Accept VELREFa.
-*              wcspih() always recognizes the AIPS-convention keywords,
-*              CROTAn, EPOCH, and VELREF for the primary representation
-*              (a = ' ') but alternates are non-standard.
-*
-*              wcsbth() accepts EPOCHa and VELREFa only if WCSHDR_AUXIMG is
-*              also enabled.
-*
-*      - WCSHDR_CD00i00j: Accept CD00i00j (wcspih()).
-*      - WCSHDR_PC00i00j: Accept PC00i00j (wcspih()).
-*      - WCSHDR_PROJPn:   Accept PROJPn   (wcspih()).
-*              These appeared in early drafts of WCS Paper I+II (before they
-*              were split) and are equivalent to CDi_ja, PCi_ja, and PVi_ma
-*              for the primary representation (a = ' ').  PROJPn is
-*              equivalent to PVi_ma with m = n <= 9, and is associated
-*              exclusively with the latitude axis.
-*
-*      - WCSHDR_RADECSYS: Accept RADECSYS.  This appeared in early drafts of
-*              WCS Paper I+II and was subsequently replaced by RADESYSa.
-*
-*              wcsbth() accepts RADECSYS only if WCSHDR_AUXIMG is also
-*              enabled.
-*
-*      - WCSHDR_VSOURCE: Accept VSOURCEa or VSOUna (wcsbth()).  This appeared
-*              in early drafts of WCS Paper III and was subsequently dropped
-*              in favour of ZSOURCEa and ZSOUna.
-*
-*              wcsbth() accepts VSOURCEa only if WCSHDR_AUXIMG is also
-*              enabled.
-*
-*      - WCSHDR_DOBSn (wcsbth() only): Allow DOBSn, the column-specific analogue
-*              of DATE-OBS.  By an oversight this was never formally defined
-*              in the standard.
-*
-*      - WCSHDR_LONGKEY (wcsbth() only): Accept long forms of the alternate
-*              binary table and pixel list WCS keywords, i.e. with "a" non-
-*              blank.  Specifically
-*
-#                jCRPXna  TCRPXna  :  jCRPXn  jCRPna  TCRPXn  TCRPna  CRPIXja
-#                   -     TPCn_ka  :    -     ijPCna    -     TPn_ka  PCi_ja
-#                   -     TCDn_ka  :    -     ijCDna    -     TCn_ka  CDi_ja
-#                iCDLTna  TCDLTna  :  iCDLTn  iCDEna  TCDLTn  TCDEna  CDELTia
-#                iCUNIna  TCUNIna  :  iCUNIn  iCUNna  TCUNIn  TCUNna  CUNITia
-#                iCTYPna  TCTYPna  :  iCTYPn  iCTYna  TCTYPn  TCTYna  CTYPEia
-#                iCRVLna  TCRVLna  :  iCRVLn  iCRVna  TCRVLn  TCRVna  CRVALia
-#                iPVn_ma  TPVn_ma  :    -     iVn_ma    -     TVn_ma  PVi_ma
-#                iPSn_ma  TPSn_ma  :    -     iSn_ma    -     TSn_ma  PSi_ma
-*
-*              where the primary and standard alternate forms together with
-*              the image-header equivalent are shown rightwards of the colon.
-*
-*              The long form of these keywords could be described as quasi-
-*              standard.  TPCn_ka, iPVn_ma, and TPVn_ma appeared by mistake
-*              in the examples in WCS Paper II and subsequently these and
-*              also TCDn_ka, iPSn_ma and TPSn_ma were legitimized by the
-*              errata to the WCS papers.
-*
-*              Strictly speaking, the other long forms are non-standard and
-*              in fact have never appeared in any draft of the WCS papers nor
-*              in the errata.  However, as natural extensions of the primary
-*              form they are unlikely to be written with any other intention.
-*              Thus it should be safe to accept them provided, of course,
-*              that the resulting keyword does not exceed the 8-character
-*              limit.
-*
-*              If WCSHDR_CNAMn is enabled then also accept
-*
-#                iCNAMna  TCNAMna  :   ---   iCNAna    ---   TCNAna  CNAMEia
-#                iCRDEna  TCRDEna  :   ---   iCRDna    ---   TCRDna  CRDERia
-#                iCSYEna  TCSYEna  :   ---   iCSYna    ---   TCSYna  CSYERia
-*
-*              Note that CNAMEia, CRDERia, CSYERia, and their variants are
-*              not used by WCSLIB but are stored in the wcsprm struct as
-*              auxiliary information.
-*
-*      - WCSHDR_CNAMn (wcsbth() only): Accept iCNAMn, iCRDEn, iCSYEn, TCNAMn,
-*              TCRDEn, and TCSYEn, i.e. with "a" blank.  While non-standard,
-*              these are the obvious analogues of iCTYPn, TCTYPn, etc.
-*
-*      - WCSHDR_AUXIMG (wcsbth() only): Allow the image-header form of an
-*              auxiliary WCS keyword with representation-wide scope to
-*              provide a default value for all images.  This default may be
-*              overridden by the column-specific form of the keyword.
-*
-*              For example, a keyword like EQUINOXa would apply to all image
-*              arrays in a binary table, or all pixel list columns with
-*              alternate representation "a" unless overridden by EQUIna.
-*
-*              Specifically the keywords are:
-*
-#                LATPOLEa  for LATPna
-#                LONPOLEa  for LONPna
-#                RESTFREQ  for RFRQna
-#                RESTFRQa  for RFRQna
-#                RESTWAVa  for RWAVna
-*
-*              whose keyvalues are actually used by WCSLIB, and also keywords
-*              that provide auxiliary information that is simply stored in
-*              the wcsprm struct:
-*
-#                EPOCH         -       ... (No column-specific form.)
-#                EPOCHa        -       ... Only if WCSHDR_EPOCHa is set.
-#                EQUINOXa  for EQUIna
-#                RADESYSa  for RADEna
-#                RADECSYS  for RADEna  ... Only if WCSHDR_RADECSYS is set.
-#                SPECSYSa  for SPECna
-#                SSYSOBSa  for SOBSna
-#                SSYSSRCa  for SSRCna
-#                VELOSYSa  for VSYSna
-#                VELANGLa  for VANGna
-#                VELREF        -       ... (No column-specific form.)
-#                VELREFa       -       ... Only if WCSHDR_VELREFa is set.
-#                VSOURCEa  for VSOUna  ... Only if WCSHDR_VSOURCE is set.
-#                WCSNAMEa  for WCSNna  ... Or TWCSna (see below).
-#                ZSOURCEa  for ZSOUna
-*
-#                DATE-AVG  for DAVGn
-#                DATE-OBS  for DOBSn
-#                MJD-AVG   for MJDAn
-#                MJD-OBS   for MJDOBn
-#                OBSGEO-X  for OBSGXn
-#                OBSGEO-Y  for OBSGYn
-#                OBSGEO-Z  for OBSGZn
-*
-*              where the image-header keywords on the left provide default
-*              values for the column specific keywords on the right.
-*
-*              Keywords in the last group, such as MJD-OBS, apply to all
-*              alternate representations, so MJD-OBS would provide a default
-*              value for all images in the header.
-*
-*              This auxiliary inheritance mechanism applies to binary table
-*              image arrays and pixel lists alike.  Most of these keywords
-*              have no default value, the exceptions being LONPOLEa and
-*              LATPOLEa, and also RADESYSa and EQUINOXa which provide
-*              defaults for each other.  Thus the only potential difficulty
-*              in using WCSHDR_AUXIMG is that of erroneously inheriting one
-*              of these four keywords.
-*
-*              Unlike WCSHDR_ALLIMG, the existence of one (or all) of these
-*              auxiliary WCS image header keywords will not by itself cause a
-*              wcsprm struct to be created for alternate representation "a".
-*              This is because they do not provide sufficient information to
-*              create a non-trivial coordinate representation when used in
-*              conjunction with the default values of those keywords, such as
-*              CTYPEia, that are parameterized by axis number.
-*
-*      - WCSHDR_ALLIMG (wcsbth() only): Allow the image-header form of *all*
-*              image header WCS keywords to provide a default value for all
-*              image arrays in a binary table (n.b. not pixel list).  This
-*              default may be overridden by the column-specific form of the
-*              keyword.
-*
-*              For example, a keyword like CRPIXja would apply to all image
-*              arrays in a binary table with alternate representation "a"
-*              unless overridden by jCRPna.
-*
-*              Specifically the keywords are those listed above for
-*              WCSHDR_AUXIMG plus
-*
-#                WCSAXESa  for WCAXna
-*
-*              which defines the coordinate dimensionality, and the following
-*              keywords which are parameterized by axis number:
-*
-#                CRPIXja   for jCRPna
-#                PCi_ja    for ijPCna
-#                CDi_ja    for ijCDna
-#                CDELTia   for iCDEna
-#                CROTAi    for iCROTn
-#                CROTAia        -      ... Only if WCSHDR_CROTAia is set.
-#                CUNITia   for iCUNna
-#                CTYPEia   for iCTYna
-#                CRVALia   for iCRVna
-#                PVi_ma    for iVn_ma
-#                PSi_ma    for iSn_ma
-*
-#                CNAMEia   for iCNAna
-#                CRDERia   for iCRDna
-#                CSYERia   for iCSYna
-*
-*              where the image-header keywords on the left provide default
-*              values for the column specific keywords on the right.
-*
-*              This full inheritance mechanism only applies to binary table
-*              image arrays, not pixel lists, because in the latter case
-*              there is no well-defined association between coordinate axis
-*              number and column number.
-*
-*              Note that CNAMEia, CRDERia, CSYERia, and their variants are
-*              not used by WCSLIB but are stored in the wcsprm struct as
-*              auxiliary information.
-*
-*              Note especially that at least one wcsprm struct will be
-*              returned for each "a" found in one of the image header
-*              keywords listed above:
-*
-*              - If the image header keywords for "a" ARE NOT inherited by a
-*                binary table, then the struct will not be associated with
-*                any particular table column number and it is up to the user
-*                to provide an association.
-*
-*              - If the image header keywords for "a" ARE inherited by a
-*                binary table image array, then those keywords are considered
-*                to be "exhausted" and do not result in a separate wcsprm
-*                struct.
-*
-*      For example, to accept CD00i00j and PC00i00j and reject all other
-*      extensions, use
-*
-=        relax = WCSHDR_reject | WCSHDR_CD00i00j | WCSHDR_PC00i00j;
-*
-*      The parser always treats EPOCH as subordinate to EQUINOXa if both are
-*      present, and VSOURCEa is always subordinate to ZSOURCEa.
-*
-*      Likewise, VELREF is subordinate to the formalism of WCS Paper III, see
-*      spcaips().
-*
-*      Neither wcspih() nor wcsbth() currently recognize the AIPS-convention
-*      keywords ALTRPIX or ALTRVAL which effectively define an alternative
-*      representation for a spectral axis.
-*
-*   6: Depending on what flags have been set in its "relax" argument,
-*      wcsbth() could return as many as 27027 wcsprm structs:
-*
-*      - Up to 27 unattached representations derived from image header
-*        keywords.
-*
-*      - Up to 27 structs for each of up to 999 columns containing an image
-*        arrays.
-*
-*      - Up to 27 structs for a pixel list.
-*
-*      Note that it is considered legitimate for a column to contain an image
-*      array and also form part of a pixel list, and in particular that
-*      wcsbth() does not check the TFORM keyword for a pixel list column to
-*      check that it is scalar.
-*
-*      In practice, of course, a realistic binary table header is unlikely to
-*      contain more than a handful of images.
-*
-*      In order for wcsbth() to create a wcsprm struct for a particular
-*      coordinate representation, at least one WCS keyword that defines an
-*      axis number must be present, either directly or by inheritance if
-*      WCSHDR_ALLIMG is set.
-*
-*      When the image header keywords for an alternate representation are
-*      inherited by a binary table image array via WCSHDR_ALLIMG, those
-*      keywords are considered to be "exhausted" and do not result in a
-*      separate wcsprm struct.  Otherwise they do.
-*
-*   7: Neither wcspih() nor wcsbth() check for duplicated keywords, in most
-*      cases they accept the last encountered.
-*
-*   8: wcspih() and wcsbth() use wcsnpv() and wcsnps() (refer to the prologue
-*      of wcs.h) to match the size of the pv[] and ps[] arrays in the wcsprm
-*      structs to the number in the header.  Consequently there are no unused
-*      elements in the pv[] and ps[] arrays, indeed they will often be of
-*      zero length.
-*
-*   9: The FITS WCS standard for pixel lists assumes that a pixel list
-*      defines one and only one image, i.e. that each row of the binary table
-*      refers to just one event, e.g. the detection of a single photon or
-*      neutrino.
-*
-*      In the absence of a formal mechanism for identifying the columns
-*      containing pixel coordinates (as opposed to pixel values or ancillary
-*      data recorded at the time the photon or neutrino was detected),
-*      Paper I discusses how the WCS keywords themselves may be used to
-*      identify them.
-*
-*      In practice, however, pixel lists have been used to store multiple
-*      images.  Besides not specifying how to identify columns, the pixel
-*      list convention is also silent on the method to be used to associate
-*      table columns with image axes.
-*
-*      wcsbth() simply collects all WCS keywords for a particular coordinate
-*      representation (i.e. the "a" value in TCTYna) into one wcsprm struct.
-*      However, these alternates need not be associated with the same table
-*      columns and this allows a pixel list to contain up to 27 separate
-*      images.  As usual, if one of these representations happened to contain
-*      more than two celestial axes, for example, then an error would result
-*      when wcsset() is invoked on it.  In this case the "colsel" argument
-*      could be used to restrict the columns used to construct the
-*      representation so that it only contained one pair of celestial axes.
-*
-*
-* wcstab() - Tabular construction routine
-* ---------------------------------------
-* wcstab() assists in filling in the information in the wcsprm struct relating
-* to coordinate lookup tables.
-*
-* Tabular coordinates ('TAB') present certain difficulties in that the main
-* components of the lookup table - the multidimensional coordinate array plus
-* an index vector for each dimension - are stored in a FITS binary table
-* extension (BINTABLE).  Information required to locate these arrays is stored
-* in PVi_ma and PSi_ma keywords in the image header.
-*
-* wcstab() parses the PVi_ma and PSi_ma keywords associated with each 'TAB'
-* axis and allocates memory in the wcsprm struct for the required number of
-* tabprm structs.  It sets as much of the tabprm struct as can be gleaned from
-* the image header, and also sets up an array of wtbarr structs (described in
-* the prologue of wcs.h) to assist in extracting the required arrays from the
-* BINTABLE extension(s).
-*
-* It is then up to the user to allocate memory for, and copy arrays from the
-* BINTABLE extension(s) into the tabprm structs.  A CFITSIO routine,
-* fits_read_wcstab(), has been provided for this purpose, see getwcstab.h.
-* wcsset() will automatically take control of this allocated memory, in
-* particular causing it to be free'd by wcsfree(); the user must not attempt
-* to free it after wcsset() has been called.
-*
-* Note that wcspih() and wcsbth() automatically invoke wcstab() on each of the
-* wcsprm structs that they return.
-*
-* Given and returned:
-*   wcs       struct wcsprm*
-*                       Coordinate transformation parameters (see below).
-*
-*                       wcstab() sets ntab, tab, nwtb and wtb, allocating
-*                       memory for the tab and wtb arrays.  This allocated
-*                       memory will be free'd automatically by wcsfree().
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         1: Null wcsprm pointer passed.
-*                         2: Memory allocation failed.
-*                         3: Invalid tabular parameters.
-*
-*                       For returns > 1, a detailed error message is set in
-*                       wcsprm::err if enabled, see wcserr_enable().
-*
-*
-* wcsidx() - Index alternate coordinate representations
-* -----------------------------------------------------
-* wcsidx() returns an array of 27 indices for the alternate coordinate
-* representations in the array of wcsprm structs returned by wcspih().  For
-* the array returned by wcsbth() it returns indices for the unattached
-* (colnum == 0) representations derived from image header keywords - use
-* wcsbdx() for those derived from binary table image arrays or pixel lists
-* keywords.
-*
-* Given:
-*   nwcs      int       Number of coordinate representations in the array.
-*
-*   wcs       const struct wcsprm**
-*                       Pointer to an array of wcsprm structs returned by
-*                       wcspih() or wcsbth().
-*
-* Returned:
-*   alts      int[27]   Index of each alternate coordinate representation in
-*                       the array: alts[0] for the primary, alts[1] for 'A',
-*                       etc., set to -1 if not present.
-*
-*                       For example, if there was no 'P' representation then
-*
-=                         alts['P'-'A'+1] == -1;
-*
-*                       Otherwise, the address of its wcsprm struct would be
-*
-=                         wcs + alts['P'-'A'+1];
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         1: Null wcsprm pointer passed.
-*
-*
-* wcsbdx() - Index alternate coordinate representions
-* ---------------------------------------------------
-* wcsbdx() returns an array of 999 x 27 indices for the alternate coordinate
-* representions for binary table image arrays xor pixel lists in the array of
-* wcsprm structs returned by wcsbth().  Use wcsidx() for the unattached
-* representations derived from image header keywords.
-*
-* Given:
-*   nwcs      int       Number of coordinate representations in the array.
-*
-*   wcs       const struct wcsprm**
-*                       Pointer to an array of wcsprm structs returned by
-*                       wcsbth().
-*
-*   type      int       Select the type of coordinate representation:
-*                         0: binary table image arrays,
-*                         1: pixel lists.
-*
-* Returned:
-*   alts      short[1000][28]
-*                       Index of each alternate coordinate represention in the
-*                       array: alts[col][0] for the primary, alts[col][1] for
-*                       'A', to alts[col][26] for 'Z', where col is the
-*                       1-relative column number, and col == 0 is used for
-*                       unattached image headers.  Set to -1 if not present.
-*
-*                       alts[col][27] counts the number of coordinate
-*                       representations of the chosen type for each column.
-*
-*                       For example, if there was no 'P' represention for
-*                       column 13 then
-*
-=                         alts[13]['P'-'A'+1] == -1;
-*
-*                       Otherwise, the address of its wcsprm struct would be
-*
-=                         wcs + alts[13]['P'-'A'+1];
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         1: Null wcsprm pointer passed.
-*
-*
-* wcsvfree() - Free the array of wcsprm structs
-* ---------------------------------------------
-* wcsvfree() frees the memory allocated by wcspih() or wcsbth() for the array
-* of wcsprm structs, first invoking wcsfree() on each of the array members.
-*
-* Given and returned:
-*   nwcs      int*      Number of coordinate representations found; set to 0
-*                       on return.
-*
-*   wcs       struct wcsprm**
-*                       Pointer to the array of wcsprm structs; set to 0 on
-*                       return.
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         1: Null wcsprm pointer passed.
-*
-*
-* wcshdo() - Write out a wcsprm struct as a FITS header
-* -----------------------------------------------------
-* wcshdo() translates a wcsprm struct into a FITS header.  If the colnum
-* member of the struct is non-zero then a binary table image array header will
-* be produced.  Otherwise, if the colax[] member of the struct is set non-zero
-* then a pixel list header will be produced.  Otherwise, a primary image or
-* image extension header will be produced.
-*
-* If the struct was originally constructed from a header, e.g. by wcspih(),
-* the output header will almost certainly differ in a number of respects:
-*
-*   - The output header only contains WCS-related keywords.  In particular, it
-*     does not contain syntactically-required keywords such as SIMPLE, NAXIS,
-*     BITPIX, or END.
-*
-*   - Deprecated (e.g. CROTAn) or non-standard usage will be translated to
-*     standard (this is partially dependent on whether wcsfix() was applied).
-*
-*   - Quantities will be converted to the units used internally, basically SI
-*     with the addition of degrees.
-*
-*   - Floating-point quantities may be given to a different decimal precision.
-*
-*   - Elements of the PCi_ja matrix will be written if and only if they differ
-*     from the unit matrix.  Thus, if the matrix is unity then no elements
-*     will be written.
-*
-*   - Additional keywords such as WCSAXESa, CUNITia, LONPOLEa and LATPOLEa may
-*     appear.
-*
-*   - The original keycomments will be lost, although wcshdo() tries hard to
-*     write meaningful comments.
-*
-*   - Keyword order may be changed.
-*
-* Keywords can be translated between the image array, binary table, and pixel
-* lists forms by manipulating the colnum or colax[] members of the wcsprm
-* struct.
-*
-* Given:
-*   relax     int       Degree of permissiveness:
-*                          0: Recognize only FITS keywords defined by the
-*                             published WCS standard.
-*                         -1: Admit all informal extensions of the WCS
-*                             standard.
-*                       Fine-grained control of the degree of permissiveness
-*                       is also possible as explained in the notes below.
-*
-* Given and returned:
-*   wcs       struct wcsprm*
-*                       Pointer to a wcsprm struct containing coordinate
-*                       transformation parameters.  Will be initialized if
-*                       necessary.
-*
-* Returned:
-*   nkeyrec   int*      Number of FITS header keyrecords returned in the
-*                       "header" array.
-*
-*   header    char**    Pointer to an array of char holding the header.
-*                       Storage for the array is allocated by wcshdo() in
-*                       blocks of 2880 bytes (32 x 80-character keyrecords)
-*                       and must be free'd by the user to avoid memory leaks.
-*
-*                       Each keyrecord is 80 characters long and is *NOT*
-*                       null-terminated, so the first keyrecord starts at
-*                       (*header)[0], the second at (*header)[80], etc.
-*
-* Function return value:
-*             int       Status return value (associated with wcs_errmsg[]):
-*                         0: Success.
-*                         1: Null wcsprm pointer passed.
-*                         2: Memory allocation failed.
-*                         3: Linear transformation matrix is singular.
-*                         4: Inconsistent or unrecognized coordinate axis
-*                            types.
-*                         5: Invalid parameter value.
-*                         6: Invalid coordinate transformation parameters.
-*                         7: Ill-conditioned coordinate transformation
-*                            parameters.
-*
-*                       For returns > 1, a detailed error message is set in
-*                       wcsprm::err if enabled, see wcserr_enable().
-*
-* Notes:
-*   wcshdo() interprets the "relax" argument as a vector of flag bits to
-*   provide fine-grained control over what non-standard WCS keywords to write.
-*   The flag bits are subject to change in future and should be set by using
-*   the preprocessor macros (see below) for the purpose.
-*
-*   - WCSHDO_none: Don't use any extensions.
-*
-*   - WCSHDO_all: Write all recognized extensions, equivalent to setting each
-*           flag bit.
-*
-*   - WCSHDO_safe: Write all extensions that are considered to be safe and
-*           recommended.
-*
-*   - WCSHDO_DOBSn: Write DOBSn, the column-specific analogue of DATE-OBS for
-*           use in binary tables and pixel lists.  WCS Paper III introduced
-*           DATE-AVG and DAVGn but by an oversight DOBSn (the obvious analogy)
-*           was never formally defined by the standard.  The alternative to
-*           using DOBSn is to write DATE-OBS which applies to the whole table.
-*           This usage is considered to be safe and is recommended.
-*
-*   - WCSHDO_TPCn_ka: WCS Paper I defined
-*
-*           - TPn_ka and TCn_ka for pixel lists
-*
-*           but WCS Paper II uses TPCn_ka in one example and subsequently the
-*           errata for the WCS papers legitimized the use of
-*
-*           - TPCn_ka and TCDn_ka for pixel lists
-*
-*           provided that the keyword does not exceed eight characters.  This
-*           usage is considered to be safe and is recommended because of the
-*           non-mnemonic terseness of the shorter forms.
-*
-*   - WCSHDO_PVn_ma: WCS Paper I defined
-*
-*           - iVn_ma and iSn_ma for bintables and
-*           - TVn_ma and TSn_ma for pixel lists
-*
-*           but WCS Paper II uses iPVn_ma and TPVn_ma in the examples and
-*           subsequently the errata for the WCS papers legitimized the use of
-*
-*           - iPVn_ma and iPSn_ma for bintables and
-*           - TPVn_ma and TPSn_ma for pixel lists
-*
-*           provided that the keyword does not exceed eight characters.  This
-*           usage is considered to be safe and is recommended because of the
-*           non-mnemonic terseness of the shorter forms.
-*
-*   - WCSHDO_CRPXna: For historical reasons WCS Paper I defined
-*
-*           - jCRPXn, iCDLTn, iCUNIn, iCTYPn, and iCRVLn for bintables and
-*           - TCRPXn, TCDLTn, TCUNIn, TCTYPn, and TCRVLn for pixel lists
-*
-*           for use without an alternate version specifier.  However, because
-*           of the eight-character keyword constraint, in order to accommodate
-*           column numbers greater than 99 WCS Paper I also defined
-*
-*           - jCRPna, iCDEna, iCUNna, iCTYna and iCRVna for bintables and
-*           - TCRPna, TCDEna, TCUNna, TCTYna and TCRVna for pixel lists
-*
-*           for use with an alternate version specifier (the "a").  Like the
-*           PC, CD, PV, and PS keywords there is an obvious tendency to
-*           confuse these two forms for column numbers up to 99.  It is very
-*           unlikely that any parser would reject keywords in the first set
-*           with a non-blank alternate version specifier so this usage is
-*           considered to be safe and is recommended.
-*
-*   - WCSHDO_CNAMna: WCS Papers I and III defined
-*
-*           - iCNAna,  iCRDna,  and iCSYna  for bintables and
-*           - TCNAna,  TCRDna,  and TCSYna  for pixel lists
-*
-*           By analogy with the above, the long forms would be
-*
-*           - iCNAMna, iCRDEna, and iCSYEna for bintables and
-*           - TCNAMna, TCRDEna, and TCSYEna for pixel lists
-*
-*           Note that these keywords provide auxiliary information only, none
-*           of them are needed to compute world coordinates.  This usage is
-*           potentially unsafe and is not recommended at this time.
-*
-*   - WCSHDO_WCSNna: In light of wcsbth() note 4, write WCSNna instead of
-*           TWCSna for pixel lists.  While wcsbth() treats WCSNna and TWCSna
-*           as equivalent, other parsers may not.  Consequently, this usage
-*           is potentially unsafe and is not recommended at this time.
-*
-*
-* Global variable: const char *wcshdr_errmsg[] - Status return messages
-* ---------------------------------------------------------------------
-* Error messages to match the status value returned from each function.
-* Use wcs_errmsg[] for status returns from wcshdo().
-*
-*===========================================================================*/
-
-#ifndef WCSLIB_WCSHDR
-#define WCSLIB_WCSHDR
-
-#include "wcs.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define WCSHDR_none     0x00000000
-#define WCSHDR_all      0x000FFFFF
-#define WCSHDR_reject   0x10000000
-
-#define WCSHDR_CROTAia  0x00000001
-#define WCSHDR_EPOCHa   0x00000002
-#define WCSHDR_VELREFa  0x00000004
-#define WCSHDR_CD00i00j 0x00000008
-#define WCSHDR_PC00i00j 0x00000010
-#define WCSHDR_PROJPn   0x00000020
-#define WCSHDR_RADECSYS 0x00000040
-#define WCSHDR_VSOURCE  0x00000080
-#define WCSHDR_DOBSn    0x00000100
-#define WCSHDR_LONGKEY  0x00000200
-#define WCSHDR_CNAMn    0x00000400
-#define WCSHDR_AUXIMG   0x00000800
-#define WCSHDR_ALLIMG   0x00001000
-
-#define WCSHDR_IMGHEAD  0x00010000
-#define WCSHDR_BIMGARR  0x00020000
-#define WCSHDR_PIXLIST  0x00040000
-
-#define WCSHDO_none     0x00
-#define WCSHDO_all      0xFF
-#define WCSHDO_safe     0x0F
-#define WCSHDO_DOBSn    0x01
-#define WCSHDO_TPCn_ka  0x02
-#define WCSHDO_PVn_ma   0x04
-#define WCSHDO_CRPXna   0x08
-#define WCSHDO_CNAMna   0x10
-#define WCSHDO_WCSNna   0x20
-
-
-extern const char *wcshdr_errmsg[];
-
-enum wcshdr_errmsg_enum {
-  WCSHDRERR_SUCCESS            = 0,	/* Success. */
-  WCSHDRERR_NULL_POINTER       = 1,	/* Null wcsprm pointer passed. */
-  WCSHDRERR_MEMORY             = 2,	/* Memory allocation failed. */
-  WCSHDRERR_BAD_COLUMN         = 3,	/* Invalid column selection. */
-  WCSHDRERR_PARSER             = 4,	/* Fatal error returned by Flex
-					   parser. */
-  WCSHDRERR_BAD_TABULAR_PARAMS = 5 	/* Invalid tabular parameters. */
-};
-
-int wcspih(char *header, int nkeyrec, int relax, int ctrl, int *nreject,
-           int *nwcs, struct wcsprm **wcs);
-
-int wcsbth(char *header, int nkeyrec, int relax, int ctrl, int keysel,
-           int *colsel, int *nreject, int *nwcs, struct wcsprm **wcs);
-
-int wcstab(struct wcsprm *wcs);
-
-int wcsidx(int nwcs, struct wcsprm **wcs, int alts[27]);
-
-int wcsbdx(int nwcs, struct wcsprm **wcs, int type, short alts[1000][28]);
-
-int wcsvfree(int *nwcs, struct wcsprm **wcs);
-
-int wcshdo(int relax, struct wcsprm *wcs, int *nkeyrec, char **header);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* WCSLIB_WCSHDR */
diff --git a/astropy/wcs/src/wcslib/C/wcslib.h b/astropy/wcs/src/wcslib/C/wcslib.h
deleted file mode 100644
index 3263818..0000000
--- a/astropy/wcs/src/wcslib/C/wcslib.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*============================================================================
-
-  WCSLIB 4.10 - an implementation of the FITS WCS standard.
-  Copyright (C) 1995-2012, Mark Calabretta
-
-  This file is part of WCSLIB.
-
-  WCSLIB is free software: you can redistribute it and/or modify it under the
-  terms of the GNU Lesser General Public License as published by the Free
-  Software Foundation, either version 3 of the License, or (at your option)
-  any later version.
-
-  WCSLIB 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 Lesser General Public License for
-  more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with WCSLIB.  If not, see <http://www.gnu.org/licenses/>.
-
-  Correspondence concerning WCSLIB may be directed to:
-    Internet email: mcalabre at atnf.csiro.au
-    Postal address: Dr. Mark Calabretta
-                    Australia Telescope National Facility, CSIRO
-                    PO Box 76
-                    Epping NSW 1710
-                    AUSTRALIA
-
-  Author: Mark Calabretta, Australia Telescope National Facility
-  http://www.atnf.csiro.au/~mcalabre/index.html
-  $Id: wcslib.h,v 4.10 2012/02/05 23:41:44 cal103 Exp $
-*=============================================================================
-*
-* WCSLIB 4.10 - C routines that implement the FITS World Coordinate System
-* (WCS) standard.
-*
-* Summary of wcslib.h
-* -------------------
-* This header file is provided purely for convenience.  Use it to include all
-* of the separate WCSLIB headers.
-*
-*===========================================================================*/
-
-#ifndef WCSLIB_WCSLIB
-#define WCSLIB_WCSLIB
-
-#include "cel.h"
-#include "fitshdr.h"
-#include "lin.h"
-#include "log.h"
-#include "prj.h"
-#include "spc.h"
-#include "sph.h"
-#include "spx.h"
-#include "tab.h"
-#include "wcs.h"
-#include "wcserr.h"
-#include "wcsfix.h"
-#include "wcshdr.h"
-#include "wcsmath.h"
-#include "wcsprintf.h"
-#include "wcstrig.h"
-#include "wcsunits.h"
-#include "wcsutil.h"
-
-#endif /* WCSLIB_WCSLIB */
diff --git a/astropy/wcs/src/wcslib/C/wcsmath.h b/astropy/wcs/src/wcslib/C/wcsmath.h
deleted file mode 100644
index 77a8aac..0000000
--- a/astropy/wcs/src/wcslib/C/wcsmath.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*============================================================================
-
-  WCSLIB 4.10 - an implementation of the FITS WCS standard.
-  Copyright (C) 1995-2012, Mark Calabretta
-
-  This file is part of WCSLIB.
-
-  WCSLIB is free software: you can redistribute it and/or modify it under the
-  terms of the GNU Lesser General Public License as published by the Free
-  Software Foundation, either version 3 of the License, or (at your option)
-  any later version.
-
-  WCSLIB 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 Lesser General Public License for
-  more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with WCSLIB.  If not, see <http://www.gnu.org/licenses/>.
-
-  Correspondence concerning WCSLIB may be directed to:
-    Internet email: mcalabre at atnf.csiro.au
-    Postal address: Dr. Mark Calabretta
-                    Australia Telescope National Facility, CSIRO
-                    PO Box 76
-                    Epping NSW 1710
-                    AUSTRALIA
-
-  Author: Mark Calabretta, Australia Telescope National Facility
-  http://www.atnf.csiro.au/~mcalabre/index.html
-  $Id: wcsmath.h,v 4.10 2012/02/05 23:41:44 cal103 Exp $
-*=============================================================================
-*
-* Summary of wcsmath.h
-* --------------------
-* Definition of mathematical constants used by WCSLIB.
-*
-*===========================================================================*/
-
-#ifndef WCSLIB_WCSMATH
-#define WCSLIB_WCSMATH
-
-#ifdef PI
-#undef PI
-#endif
-
-#ifdef D2R
-#undef D2R
-#endif
-
-#ifdef R2D
-#undef R2D
-#endif
-
-#ifdef SQRT2
-#undef SQRT2
-#endif
-
-#ifdef SQRT2INV
-#undef SQRT2INV
-#endif
-
-#define PI 3.141592653589793238462643
-#define D2R PI/180.0
-#define R2D 180.0/PI
-#define SQRT2 1.4142135623730950488
-#define SQRT2INV 1.0/SQRT2
-
-#ifdef UNDEFINED
-#undef UNDEFINED
-#endif
-
-#define UNDEFINED 987654321.0e99
-#define undefined(value) (value == UNDEFINED)
-
-#endif /* WCSLIB_WCSMATH */
diff --git a/astropy/wcs/src/wcslib/C/wcspih.l b/astropy/wcs/src/wcslib/C/wcspih.l
deleted file mode 100644
index b0db833..0000000
--- a/astropy/wcs/src/wcslib/C/wcspih.l
+++ /dev/null
@@ -1,1180 +0,0 @@
-/*============================================================================
-
-  WCSLIB 4.10 - an implementation of the FITS WCS standard.
-  Copyright (C) 1995-2012, Mark Calabretta
-
-  This file is part of WCSLIB.
-
-  WCSLIB is free software: you can redistribute it and/or modify it under the
-  terms of the GNU Lesser General Public License as published by the Free
-  Software Foundation, either version 3 of the License, or (at your option)
-  any later version.
-
-  WCSLIB 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 Lesser General Public License for
-  more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with WCSLIB.  If not, see <http://www.gnu.org/licenses/>.
-
-  Correspondence concerning WCSLIB may be directed to:
-    Internet email: mcalabre at atnf.csiro.au
-    Postal address: Dr. Mark Calabretta
-                    Australia Telescope National Facility, CSIRO
-                    PO Box 76
-                    Epping NSW 1710
-                    AUSTRALIA
-
-  Author: Mark Calabretta, Australia Telescope National Facility
-  http://www.atnf.csiro.au/~mcalabre/index.html
-  $Id: wcspih.l,v 4.10 2012/02/05 23:41:44 cal103 Exp $
-*=============================================================================
-*
-* wcspih.l is a Flex description file containing the definition of a lexical
-* scanner for parsing the WCS keyrecords from a FITS primary image or image
-* extension header.
-*
-* wcspih.l requires Flex v2.5.4 or later.  Refer to wcshdr.h for a description
-* of the user interface and operating notes.
-*
-* Implementation notes
-* --------------------
-* Use of the WCSAXESa keyword is not mandatory.  Its default value is "the
-* larger of NAXIS and the largest index of these keywords [i.e. CRPIXj, PCi_j
-* or CDi_j, CDELTi, CTYPEi, CRVALi, and CUNITi] found in the FITS header".
-* Consequently the definition of WCSAXESa effectively invalidates the use of
-* NAXIS for determining the number of coordinate axes and forces a preliminary
-* pass through the header to determine the "largest index" in headers where
-* WCSAXESa was omitted.
-*
-* Furthermore, since the use of WCSAXESa is optional, there is no way to
-* determine the number of coordinate representations (the "a" value) other
-* than by parsing all of the WCS keywords in the header; even if WCSAXESa was
-* specified for some representations it cannot be known in advance whether it
-* was specified for all of those present in the header.
-*
-* Hence the definition of WCSAXESa forces the scanner to be implemented in two
-* passes.  The first pass is used to determine the number of coordinate
-* representations (up to 27) and the number of coordinate axes in each.
-* Effectively WCSAXESa is ignored unless it exceeds the "largest index" in
-* which case the keywords for the extra axes assume their default values.  The
-* number of PVi_ma and PSi_ma keywords in each representation is also counted
-* in the first pass.
-*
-* On completion of the first pass, memory is allocated for an array of the
-* required number of wcsprm structs and each of these is initialized
-* appropriately.  These structs are filled in the second pass.
-*
-* The parser does not check for duplicated keywords, it accepts the last
-* encountered.
-*
-*===========================================================================*/
-
-/* Options. */
-%option full
-%option never-interactive
-%option noyywrap
-%option outfile="wcspih.c"
-%option prefix="wcspih"
-
-/* Indices for parameterized keywords. */
-I0	[0-9]
-I1	[1-9]
-I2	[1-9][0-9]
-I3	[1-9][0-9]{2}
-I4	[1-9][0-9]{3}
-
-/* Alternate coordinate system identifier. */
-ALT	[ A-Z]
-
-/* Keyvalue data types. */
-INTEGER	[+-]?[0-9]+
-FLOAT	[+-]?([0-9]+\.?[0-9]*|\.[0-9]+)([eE][+-]?[0-9]+)?
-STRING	'([^']|'')*'
-
-/* Exclusive start states. */
-%x CROTAi PROJPn
-%x CCCCCia CCi_ja CCi_ma CCCCCCCa CCCCCCCC
-%x VALUE
-%x INTEGER_VAL FLOAT_VAL STRING_VAL
-%x COMMENT
-%x DISCARD ERROR FLUSH
-
-%{
-#include <math.h>
-#include <setjmp.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "wcs.h"
-#include "wcshdr.h"
-#include "wcsmath.h"
-
-#define INTEGER 0
-#define FLOAT   1
-#define STRING  2
-
-#define YY_DECL int wcspih(char *header, int nkeyrec, int relax, int ctrl, \
-                           int *nreject, int *nwcs, struct wcsprm **wcs)
-
-#define YY_INPUT(inbuff, count, bufsize) \
-	{ \
-	  if (wcspih_nkeyrec) { \
-	    strncpy(inbuff, wcspih_hdr, 80); \
-	    inbuff[80] = '\n'; \
-	    wcspih_hdr += 80; \
-	    wcspih_nkeyrec--; \
-	    count = 81; \
-	  } else { \
-	    count = YY_NULL; \
-	  } \
-	}
-
-/* These global variables are required by YY_INPUT. */
-char *wcspih_hdr;
-int  wcspih_nkeyrec;
-
-int wcspih_final(int alts[], double epoch[], double vsource[], int *nwcs,
-        struct wcsprm **wcs);
-int wcspih_inits(int naxis, int alts[], int npv[], int nps[], int *nwcs,
-        struct wcsprm **wcs);
-void wcspih_naxes(int naxis, int i, int j, char a, int alts[], int *npptr);
-
-/* Used in preempting the call to exit() by yy_fatal_error(). */
-jmp_buf wcspih_abort_jmp_env;
-#define exit(status) longjmp(wcspih_abort_jmp_env, status)
-
-%}
-
-%%
-	/* Keyword indices, as used in the WCS papers, e.g. PCi_ja, PVi_ma. */
-	char a;
-	int  i, j, m;
-	
-	char *cptr, *errmsg, errtxt[80], *hptr, *keep;
-	int  altlin, alts[27], ialt, idx, ipx, ix, jx, naxis, *npptr,
-	     nps[27], npv[27], pass, status, valtype, voff;
-	double epoch[27], vsource[27];
-	void *vptr, *wptr;
-	struct wcsprm *wcsp;
-	int yylex_destroy(void);
-	
-	naxis = 0;
-	for (ialt = 0; ialt < 27; ialt++) {
-	  alts[ialt] = 0;
-	  npv[ialt] = 0;
-	  nps[ialt] = 0;
-	  epoch[ialt]   = UNDEFINED;
-	  vsource[ialt] = UNDEFINED;
-	}
-	
-	/* Parameters used to implement YY_INPUT. */
-	wcspih_hdr = header;
-	wcspih_nkeyrec = nkeyrec;
-	
-	/* Our handle on the input stream. */
-	hptr = header;
-	keep = 0x0;
-	*nreject = 0;
-	
-	/* Keyword parameters. */
-	i = j = m = 0;
-	a = ' ';
-	
-	/* For decoding the keyvalue. */
-	valtype = -1;
-	idx     = -1;
-	vptr    = 0x0;
-	
-	/* For keywords that require special handling. */
-	altlin = 0;
-	npptr  = 0x0;
-	
-	/* The data structures produced. */
-	*nwcs = 0;
-	*wcs  = 0x0;
-	
-	pass = 1;
-	
-	/* Return here via longjmp() invoked by yy_fatal_error(). */
-	if (setjmp(wcspih_abort_jmp_env)) {
-	  return 3;
-	}
-	
-	BEGIN(INITIAL);
-
-
-^NAXIS"   = "" "*{INTEGER} {
-	  if (pass == 1) {
-	    sscanf(yytext, "NAXIS   = %d", &naxis);
-	  }
-	
-	  if (naxis < 0) {
-	    errmsg = errtxt;
-	    sprintf(errmsg, "Negative value of NAXIS ignored: %d", naxis);
-	    naxis = 0;
-	    BEGIN(ERROR);
-	  } else {
-	    BEGIN(DISCARD);
-	  }
-	}
-
-^WCSAXES{ALT}=" "" "*{INTEGER} {
-	  if (pass == 1) {
-	    sscanf(yytext, "WCSAXES%c= %d", &a, &i);
-	    wcspih_naxes(naxis, i, 0, a, alts, 0);
-	  }
-	  BEGIN(FLUSH);
-	}
-
-^CRPIX	{
-	  valtype = FLOAT;
-	  if (pass == 2) vptr = &((*wcs)->crpix);
-	  BEGIN(CCCCCia);
-	}
-
-^PC	{
-	  valtype = FLOAT;
-	  if (pass == 2) vptr = &((*wcs)->pc);
-	  altlin = 1;
-	  BEGIN(CCi_ja);
-	}
-
-^CD	{
-	  valtype = FLOAT;
-	  if (pass == 2) vptr = &((*wcs)->cd);
-	  altlin = 2;
-	  BEGIN(CCi_ja);
-	}
-
-^CDELT	{
-	  valtype = FLOAT;
-	  if (pass == 2) vptr = &((*wcs)->cdelt);
-	  BEGIN(CCCCCia);
-	}
-
-^CROTA	{
-	  valtype = FLOAT;
-	  if (pass == 2) vptr = &((*wcs)->crota);
-	  altlin = 4;
-	  BEGIN(CROTAi);
-	}
-
-^CUNIT	{
-	  valtype = STRING;
-	  if (pass == 2) vptr = &((*wcs)->cunit);
-	  BEGIN(CCCCCia);
-	}
-
-^CTYPE	{
-	  valtype = STRING;
-	  if (pass == 2) vptr = &((*wcs)->ctype);
-	  BEGIN(CCCCCia);
-	}
-
-^CRVAL	{
-	  valtype = FLOAT;
-	  if (pass == 2) vptr = &((*wcs)->crval);
-	  BEGIN(CCCCCia);
-	}
-
-^LONPOLE {
-	  valtype = FLOAT;
-	  if (pass == 2) vptr = &((*wcs)->lonpole);
-	  BEGIN(CCCCCCCa);
-	}
-
-^LATPOLE {
-	  valtype = FLOAT;
-	  if (pass == 2) vptr = &((*wcs)->latpole);
-	  BEGIN(CCCCCCCa);
-	}
-
-^RESTFRQ {
-	  valtype = FLOAT;
-	  if (pass == 2) vptr = &((*wcs)->restfrq);
-	  BEGIN(CCCCCCCa);
-	}
-
-^RESTFREQ {
-	  valtype = FLOAT;
-	  if (pass == 2) vptr = &((*wcs)->restfrq);
-	  unput(' ');
-	  BEGIN(CCCCCCCa);
-	}
-
-^RESTWAV {
-	  valtype = FLOAT;
-	  if (pass == 2) vptr = &((*wcs)->restwav);
-	  BEGIN(CCCCCCCa);
-	}
-
-^PV	{
-	  valtype = FLOAT;
-	  if (pass == 2) vptr = &((*wcs)->pv);
-	  npptr = npv;
-	  BEGIN(CCi_ma);
-	}
-
-^PROJP	{
-	  valtype = FLOAT;
-	  if (pass == 2) vptr = &((*wcs)->pv);
-	  npptr = npv;
-	  BEGIN(PROJPn);
-	}
-
-^PS	{
-	  valtype = STRING;
-	  if (pass == 2) vptr = &((*wcs)->ps);
-	  npptr = nps;
-	  BEGIN(CCi_ma);
-	}
-
-^CNAME	{
-	  valtype = STRING;
-	  if (pass == 2) vptr = &((*wcs)->cname);
-	  BEGIN(CCCCCia);
-	}
-
-^CRDER	{
-	  valtype = FLOAT;
-	  if (pass == 2) vptr = &((*wcs)->crder);
-	  BEGIN(CCCCCia);
-	}
-
-^CSYER	{
-	  valtype = FLOAT;
-	  if (pass == 2) vptr = &((*wcs)->csyer);
-	  BEGIN(CCCCCia);
-	}
-
-^DATE-AVG {
-	  valtype = STRING;
-	  if (pass == 2) vptr = (*wcs)->dateavg;
-	  if (ctrl < -10) keep = wcspih_hdr - 80;
-	  BEGIN(CCCCCCCC);
-	}
-
-^DATE-OBS {
-	  valtype = STRING;
-	  if (pass == 2) vptr = (*wcs)->dateobs;
-	  if (ctrl < -10) keep = wcspih_hdr - 80;
-	  BEGIN(CCCCCCCC);
-	}
-
-^EPOCH{ALT}"  " {
-	  sscanf(yytext, "EPOCH%c", &a);
-	
-	  if (a == ' ' || relax & WCSHDR_EPOCHa) {
-	    valtype = FLOAT;
-	    if (pass == 2) {
-	      vptr = epoch;
-	      if (a >= 'A') {
-	        vptr = (void *)((double *)vptr + alts[a-'A'+1]);
-	      }
-	    }
-	
-	    unput(' ');
-	    BEGIN(CCCCCCCa);
-	
-	  } else if (relax & WCSHDR_reject) {
-	    errmsg = "EPOCH keyword may not have an alternate version code";
-	    BEGIN(ERROR);
-	
-	  } else {
-	    BEGIN(DISCARD);
-	  }
-	}
-
-^EQUINOX {
-	  valtype = FLOAT;
-	  if (pass == 2) vptr = &((*wcs)->equinox);
-	  BEGIN(CCCCCCCa);
-	}
-
-^MJD-AVG" " {
-	  valtype = FLOAT;
-	  if (pass == 2) vptr = &((*wcs)->mjdavg);
-	  if (ctrl < -10) keep = wcspih_hdr - 80;
-	  BEGIN(CCCCCCCC);
-	}
-
-^MJD-OBS" " {
-	  valtype = FLOAT;
-	  if (pass == 2) vptr = &((*wcs)->mjdobs);
-	  if (ctrl < -10) keep = wcspih_hdr - 80;
-	  BEGIN(CCCCCCCC);
-	}
-
-^OBSGEO-X {
-	  valtype = FLOAT;
-	  if (pass == 2) vptr = (*wcs)->obsgeo;
-	  if (ctrl < -10) keep = wcspih_hdr - 80;
-	  BEGIN(CCCCCCCC);
-	}
-
-^OBSGEO-Y {
-	  valtype = FLOAT;
-	  if (pass == 2) vptr = (*wcs)->obsgeo + 1;
-	  if (ctrl < -10) keep = wcspih_hdr - 80;
-	  BEGIN(CCCCCCCC);
-	}
-
-^OBSGEO-Z {
-	  valtype = FLOAT;
-	  if (pass == 2) vptr = (*wcs)->obsgeo + 2;
-	  if (ctrl < -10) keep = wcspih_hdr - 80;
-	  BEGIN(CCCCCCCC);
-	}
-
-^RADESYS {
-	  valtype = STRING;
-	  if (pass == 2) vptr = (*wcs)->radesys;
-	  BEGIN(CCCCCCCa);
-	}
-
-^RADECSYS {
-	  if (relax & WCSHDR_RADECSYS) {
-	    valtype = STRING;
-	    if (pass == 2) vptr = (*wcs)->radesys;
-	    unput(' ');
-	    BEGIN(CCCCCCCa);
-	
-	  } else if (relax & WCSHDR_reject) {
-	    errmsg = "RADECSYS is non-standard, use RADESYSa";
-	    BEGIN(ERROR);
-	
-	  } else {
-	    BEGIN(DISCARD);
-	  }
-	}
-
-^SPECSYS {
-	  valtype = STRING;
-	  if (pass == 2) vptr = (*wcs)->specsys;
-	  BEGIN(CCCCCCCa);
-	}
-
-^SSYSOBS {
-	  valtype = STRING;
-	  if (pass == 2) vptr = (*wcs)->ssysobs;
-	  BEGIN(CCCCCCCa);
-	}
-
-^SSYSSRC {
-	  valtype = STRING;
-	  if (pass == 2) vptr = (*wcs)->ssyssrc;
-	  BEGIN(CCCCCCCa);
-	}
-
-^VELANGL {
-	  valtype = FLOAT;
-	  if (pass == 2) vptr = &((*wcs)->velangl);
-	  BEGIN(CCCCCCCa);
-	}
-
-^VELOSYS {
-	  valtype = FLOAT;
-	  if (pass == 2) vptr = &((*wcs)->velosys);
-	  BEGIN(CCCCCCCa);
-	}
-
-^VELREF{ALT}" " {
-	  sscanf(yytext, "VELREF%c", &a);
-	
-	  if (a == ' ' || relax & WCSHDR_VELREFa) {
-	    valtype = INTEGER;
-	    if (pass == 2) vptr = &((*wcs)->velref);
-	
-	    unput(a);
-	    BEGIN(CCCCCCCa);
-	
-	  } else if (relax & WCSHDR_reject) {
-	    errmsg = "VELREF keyword may not have an alternate version code";
-	    BEGIN(ERROR);
-	
-	  } else {
-	    BEGIN(DISCARD);
-	  }
-	}
-
-^VSOURCE{ALT} {
-	  sscanf(yytext, "VSOURCE%c", &a);
-	
-	  if (relax & WCSHDR_VSOURCE) {
-	    valtype = FLOAT;
-	    if (pass == 2) {
-	      vptr = vsource;
-	      if (a >= 'A') {
-	        vptr = (void *)((double *)vptr + alts[a-'A'+1]);
-	      }
-	    }
-	
-	    unput(' ');
-	    BEGIN(CCCCCCCa);
-	
-	  } else if (relax & WCSHDR_reject) {
-	    errmsg = "Deprecated VSOURCEa keyword rejected";
-	    BEGIN(ERROR);
-	
-	  } else {
-	    BEGIN(DISCARD);
-	  }
-	}
-
-^WCSNAME {
-	  valtype = STRING;
-	  if (pass == 2) vptr = (*wcs)->wcsname;
-	  BEGIN(CCCCCCCa);
-	}
-
-^ZSOURCE {
-	  valtype = FLOAT;
-	  if (pass == 2) vptr = &((*wcs)->zsource);
-	  BEGIN(CCCCCCCa);
-	}
-
-^END" "{77} {
-	  yyless(0);
-	  if (wcspih_nkeyrec) {
-	    wcspih_nkeyrec = 0;
-	    errmsg = "Keyrecords following the END keyrecord were ignored";
-	    BEGIN(ERROR);
-	  } else {
-	    BEGIN(DISCARD);
-	  }
-	}
-
-^.	{
-	  BEGIN(DISCARD);
-	}
-
-<CCCCCia>{I1}{ALT}" " |
-<CCCCCia>{I2}{ALT} {
-	  sscanf(yytext, "%d%c", &i, &a);
-	  idx = i - 1;
-	  BEGIN(VALUE);
-	}
-
-<CCCCCia>{I3} {
-	  /* Invalid axis number will be caught by <VALUE>. */
-	  sscanf(yytext, "%3d", &i);
-	  BEGIN(VALUE);
-	}
-
-<CCCCCia>. {
-	  BEGIN(DISCARD);
-	}
-
-<CCi_ja>{I1}_{I1}{ALT}"  " |
-<CCi_ja>{I1}_{I2}{ALT}" " |
-<CCi_ja>{I2}_{I1}{ALT}" " |
-<CCi_ja>{I2}_{I2}{ALT} {
-	  sscanf(yytext, "%d_%d%c", &i, &j, &a);
-	  if (pass == 2) {
-	    wcsp = *wcs;
-	    if (a != ' ') {
-	      wcsp += alts[a-'A'+1];
-	    }
-	
-	    idx = (i-1)*(wcsp->naxis) + j - 1;
-	  }
-	  BEGIN(VALUE);
-	}
-
-<CCi_ja>{I1}_{I3}{ALT} |
-<CCi_ja>{I3}_{I1}{ALT} |
-<CCi_ja>{I1}_{I4} |
-<CCi_ja>{I2}_{I3} |
-<CCi_ja>{I3}_{I2} |
-<CCi_ja>{I4}_{I1} {
-	  /* Invalid axis numbers will be caught by <VALUE>. */
-	  sscanf(yytext, "%d_%d", &i, &j);
-	  BEGIN(VALUE);
-	}
-
-<CCi_ja>{I0}{6} {
-	  /* This covers the defunct forms CD00i00j and PC00i00j. */
-	  if (((relax & WCSHDR_PC00i00j) && (altlin == 1)) ||
-	      ((relax & WCSHDR_CD00i00j) && (altlin == 2))) {
-	    sscanf(yytext, "%3d%3d", &i, &j);
-	    a = ' ';
-	    if (pass == 2) {
-	      idx = (i-1)*((*wcs)->naxis) + j - 1;
-	    }
-	    BEGIN(VALUE);
-	
-	  } else if (relax & WCSHDR_reject) {
-	    errmsg = errtxt;
-	    sprintf(errmsg, "Defunct form of %si_ja keyword",
-	                     (altlin==1) ? "PC" : "CD");
-	    BEGIN(ERROR);
-	
-	  } else {
-	    BEGIN(DISCARD);
-	  }
-	}
-
-<CCi_ja>. {
-	  BEGIN(DISCARD);
-	}
-
-<CROTAi>{I1}{ALT}" " |
-<CROTAi>{I2}{ALT} {
-	  sscanf(yytext, "%d%c", &i, &a);
-	  if (a == ' ' || relax & WCSHDR_CROTAia) {
-	    idx = i - 1;
-	    BEGIN(VALUE);
-	
-	  } else if (relax & WCSHDR_reject) {
-	    errmsg = "CROTAn keyword may not have an alternate version code";
-	    BEGIN(ERROR);
-	
-	  } else {
-	    BEGIN(DISCARD);
-	  }
-	}
-
-<CROTAi>{I3} {
-	  sscanf(yytext, "%d", &i);
-	  a = ' ';
-	  idx = i - 1;
-	  BEGIN(VALUE);
-	}
-
-<CROTAi>. {
-	  BEGIN(DISCARD);
-	}
-
-<CCCCCCCa>{ALT} |
-<CCCCCCCC>. {
-	  idx = -1;
-	
-	  if (YY_START == CCCCCCCa) {
-	    sscanf(yytext, "%c", &a);
-	  } else {
-	    unput(yytext[0]);
-	    a = 0;
-	  }
-	  BEGIN(VALUE);
-	}
-
-<CCCCCCCa>. {
-	  BEGIN(DISCARD);
-	}
-
-<CCi_ma>{I1}_{I0}{ALT}"  " |
-<CCi_ma>{I1}_{I2}{ALT}" " |
-<CCi_ma>{I2}_{I0}{ALT}" " |
-<CCi_ma>{I2}_{I2}{ALT} {
-	  sscanf(yytext, "%d_%d%c", &i, &m, &a);
-	  idx = -1;
-	  BEGIN(VALUE);
-	}
-
-<CCi_ma>{I1}_{I3}{ALT} |
-<CCi_ma>{I3}_{I0}{ALT} |
-<CCi_ma>{I1}_{I4} |
-<CCi_ma>{I2}_{I3} |
-<CCi_ma>{I3}_{I2} |
-<CCi_ma>{I4}_{I0} {
-	  /* Invalid parameters will be caught by <VALUE>. */
-	  sscanf(yytext, "%d_%d", &i, &m);
-	  BEGIN(VALUE);
-	}
-
-<CCi_ma>. {
-	  BEGIN(DISCARD);
-	}
-
-<PROJPn>{I0}"  " {
-	  if (relax & WCSHDR_PROJPn) {
-	    sscanf(yytext, "%d", &m);
-	    i = 0;
-	    a = ' ';
-	    idx = -1;
-	    BEGIN(VALUE);
-	
-	  } else if (relax & WCSHDR_reject) {
-	    errmsg = "Defunct PROJPn keyword rejected";
-	    BEGIN(ERROR);
-	
-	  } else {
-	    BEGIN(DISCARD);
-	  }
-	}
-
-<PROJPn>. {
-	  BEGIN(DISCARD);
-	}
-
-<VALUE>=" "+ {
-	  /* Do checks on i, j & m. */
-	  if (i > 99 || j > 99 || m > 99) {
-	    if (relax & WCSHDR_reject) {
-	      errmsg = errtxt;
-	      if (i > 99 || j > 99) {
-	        sprintf(errmsg, "Axis number exceeds 99");
-	      } else if (m > 99) {
-	        sprintf(errmsg, "Parameter number exceeds 99");
-	      }
-	      BEGIN(ERROR);
-	
-	    } else {
-	      /* Pretend we don't recognize it. */
-	      BEGIN(DISCARD);
-	    }
-	
-	  } else {
-	    if (valtype == INTEGER) {
-	      BEGIN(INTEGER_VAL);
-	    } else if (valtype == FLOAT) {
-	      BEGIN(FLOAT_VAL);
-	    } else if (valtype == STRING) {
-	      BEGIN(STRING_VAL);
-	    } else {
-	      errmsg = errtxt;
-	      sprintf(errmsg, "Internal parser ERROR, bad data type: %d",
-	        valtype);
-	      BEGIN(ERROR);
-	    }
-	  }
-	}
-
-<VALUE>. {
-	  errmsg = "Invalid KEYWORD = VALUE syntax";
-	  BEGIN(ERROR);
-	}
-
-<INTEGER_VAL>{INTEGER} {
-	  if (pass == 1) {
-	    wcspih_naxes(naxis, i, j, a, alts, npptr);
-	    BEGIN(FLUSH);
-	
-	  } else {
-	    if (vptr) {
-	      /* Determine the coordinate representation. */
-	      for (ialt = 0; ialt < *nwcs; ialt++) {
-	        /* The loop here is for keywords that apply */
-	        /* to every alternate; these have a == 0. */
-	        if (a >= 'A') {
-	          ialt = alts[a-'A'+1];
-	        }
-	
-	        wptr = vptr;
-	        if (ialt) {
-	          voff = (char *)(*wcs+ialt) - (char *)(*wcs);
-	          wptr = (void *)((char *)vptr + voff);
-	        }
-	
-	        /* Apply keyword parameterization. */
-	        if (idx >= 0) {
-	          wptr = *((int **)wptr) + idx;
-	        }
-	
-	        /* Read the keyvalue. */
-	        sscanf(yytext, "%d", (int *)wptr);
-	
-	        if (a) break;
-	      }
-	
-	      BEGIN(COMMENT);
-	
-	    } else {
-	      errmsg = "Internal parser ERROR, null int pointer";
-	      BEGIN(ERROR);
-	    }
-	  }
-	}
-
-<INTEGER_VAL>. {
-	  errmsg = "An integer value was expected";
-	  BEGIN(ERROR);
-	}
-
-<FLOAT_VAL>{FLOAT} {
-	  if (pass == 1) {
-	    wcspih_naxes(naxis, i, j, a, alts, npptr);
-	    BEGIN(FLUSH);
-	
-	  } else {
-	    if (vptr) {
-	      /* Determine the coordinate representation. */
-	      for (ialt = 0; ialt < *nwcs; ialt++) {
-	        /* The loop here is for keywords like MJD-OBS that */
-	        /* apply to every alternate; these have a == 0.  */
-	        if (a >= 'A') {
-	          ialt = alts[a-'A'+1];
-	        }
-	
-	        wptr = vptr;
-	        if (ialt) {
-	          voff = (char *)(*wcs+ialt) - (char *)(*wcs);
-	          wptr = (void *)((char *)vptr + voff);
-	        }
-	
-	        /* Apply keyword parameterization. */
-	        if (idx >= 0) {
-	          wptr = *((double **)wptr) + idx;
-	
-	        } else if (npptr == npv) {
-	          ipx = (*wcs+ialt)->npv++;
-	          (*wcs+ialt)->pv[ipx].i = i;
-	          (*wcs+ialt)->pv[ipx].m = m;
-	          wptr = &((*wcs+ialt)->pv[ipx].value);
-	        }
-	
-	        /* Read the keyvalue. */
-	        sscanf(yytext, "%lf", (double *)wptr);
-	
-	        /* Flag the presence of PCi_ja, or CDi_ja and/or CROTAia. */
-	        if (altlin) {
-	          (*wcs+ialt)->altlin |= altlin;
-	          altlin = 0;
-	        }
-	
-	        if (a) break;
-	      }
-	
-	      BEGIN(COMMENT);
-	
-	    } else {
-	      errmsg = "Internal parser ERROR, null float pointer";
-	      BEGIN(ERROR);
-	    }
-	  }
-	}
-
-<FLOAT_VAL>. {
-	  errmsg = "A floating-point value was expected";
-	  BEGIN(ERROR);
-	}
-
-<STRING_VAL>{STRING} {
-	  if (pass == 1) {
-	    wcspih_naxes(naxis, i, j, a, alts, npptr);
-	    BEGIN(FLUSH);
-	
-	  } else {
-	    if (vptr) {
-	      /* Determine the coordinate representation. */
-	      for (ialt = 0; ialt < *nwcs; ialt++) {
-	        /* The loop here is for keywords like DATE-OBS that */
-	        /* apply to every alternate; these have a == 0.   */
-	        if (a >= 'A') {
-	          ialt = alts[a-'A'+1];
-	        }
-	
-	        wptr = vptr;
-	        if (ialt) {
-	          voff = (char *)(*wcs+ialt) - (char *)(*wcs);
-	          wptr = (void *)((char *)vptr + voff);
-	        }
-	
-	        /* Apply keyword parameterization. */
-	        if (idx >= 0) {
-	          wptr = *((char (**)[72])wptr) + idx;
-	
-	        } else if (npptr == nps) {
-	          ipx = (*wcs+ialt)->nps++;
-	          (*wcs+ialt)->ps[ipx].i = i;
-	          (*wcs+ialt)->ps[ipx].m = m;
-	          wptr = (*wcs+ialt)->ps[ipx].value;
-	        }
-	
-	        /* Read the keyvalue. */
-	        cptr = (char *)wptr;
-	        strcpy(cptr, yytext+1);
-	
-	        /* Squeeze out repeated quotes. */
-	        ix = 0;
-	        for (jx = 0; jx < 72; jx++) {
-	          if (ix < jx) {
-	            cptr[ix] = cptr[jx];
-	          }
-	
-	          if (cptr[jx] == '\0') {
-	            if (ix) cptr[ix-1] = '\0';
-	            break;
-	          } else if (cptr[jx] == '\'' && cptr[jx+1] == '\'') {
-	            jx++;
-	          }
-	
-	          ix++;
-	        }
-	
-	        if (a) break;
-	      }
-	
-	      BEGIN(COMMENT);
-	
-	    } else {
-	      errmsg = "Internal parser ERROR, null string pointer";
-	      BEGIN(ERROR);
-	    }
-	  }
-	}
-
-<STRING_VAL>. {
-	  errmsg = "A string value was expected";
-	  BEGIN(ERROR);
-	}
-
-<COMMENT>" "*\/.* |
-<COMMENT>" "* {
-	  BEGIN(FLUSH);
-	}
-
-<COMMENT>. {
-	  errmsg = "Malformed keycomment";
-	  BEGIN(ERROR);
-	}
-
-<DISCARD>.* {
-	  if (pass == 2) {
-	    if (ctrl < 0) {
-	      /* Preserve discards. */
-	      keep = wcspih_hdr - 80;
-	
-	    } else if (ctrl > 2) {
-	      fprintf(stderr, "%.80s\n  Discarded.\n", wcspih_hdr-80);
-	    }
-	  }
-	  BEGIN(FLUSH);
-	}
-
-<ERROR>.* {
-	  (*nreject)++;
-	  if (pass == 2) {
-	    if (ctrl%10 == -1) {
-	      /* Preserve rejects. */
-	      keep = wcspih_hdr - 80;
-	    }
-	
-	    if (abs(ctrl%10) > 1) {
-	      fprintf(stderr, "%.80s\n%4d: %s.\n", wcspih_hdr-80, *nreject,
-	        errmsg);
-	    }
-	  }
-	  BEGIN(FLUSH);
-	}
-
-<FLUSH>.*\n {
-	  if (pass == 2 && keep) {
-	    if (hptr < keep) {
-	      strncpy(hptr, keep, 80);
-	    }
-	    hptr += 80;
-	  }
-	
-	  i = j = m = 0;
-	  a = ' ';
-	  valtype = -1;
-	  keep = 0x0;
-	  altlin = 0;
-	  npptr = 0x0;
-	  BEGIN(INITIAL);
-	}
-
-<<EOF>>	 {
-	  /* End-of-input. */
-	  if (pass == 1) {
-	    if ((status = wcspih_inits(naxis, alts, npv, nps, nwcs, wcs)) ||
-	         *nwcs == 0) {
-	      yylex_destroy();
-	      return status;
-	    }
-	
-	    if (abs(ctrl%10) > 2) {
-	      if (*nwcs == 1) {
-	        fprintf(stderr, "Found one coordinate representation.\n");
-	      } else {
-	        fprintf(stderr, "Found %d coordinate representations.\n",
-	          *nwcs);
-	      }
-	    }
-	
-	    wcspih_hdr = header;
-	    wcspih_nkeyrec = nkeyrec;
-	    *nreject = 0;
-	
-	    pass = 2;
-	    i = j = m = 0;
-	    a = ' ';
-	    valtype = -1;
-	
-	    yyrestart(yyin);
-	
-	  } else {
-	    yylex_destroy();
-	
-	    if (ctrl < 0) {
-	      *hptr = '\0';
-	    } else if (ctrl == 1) {
-	      fprintf(stderr, "%d WCS keyrecords were rejected.\n",
-	        *nreject);
-	    }
-	
-	    return wcspih_final(alts, epoch, vsource, nwcs, wcs);
-	  }
-	}
-
-%%
-
-/*----------------------------------------------------------------------------
-* Determine the number of coordinate representations (up to 27) and the
-* number of coordinate axes in each, and count the number of PVi_ma and
-* PSi_ma keywords in each representation.
-*---------------------------------------------------------------------------*/
-
-void wcspih_naxes(int naxis, int i, int j, char a, int alts[], int *npptr)
-
-{
-  /* On the first pass alts[] is used to determine the number of axes */
-  /* for each of the 27 possible alternate coordinate descriptions.   */
-  int ialt, *ip;
-
-  if (a == 0) {
-    return;
-  }
-
-  ialt = 0;
-  if (a != ' ') {
-    ialt = a - 'A' + 1;
-  }
-
-  ip = alts + ialt;
-
-  if (*ip < naxis) {
-    *ip = naxis;
-  }
-
-  /* i or j can be greater than naxis. */
-  if (*ip < i) {
-    *ip = i;
-  }
-
-  if (*ip < j) {
-    *ip = j;
-  }
-
-  if (npptr) {
-    npptr[ialt]++;
-  }
-}
-
-
-/*----------------------------------------------------------------------------
-* Allocate memory for an array of the required number of wcsprm structs and
-* initialize each of them.
-*---------------------------------------------------------------------------*/
-
-int wcspih_inits(
-  int naxis,
-  int alts[],
-  int npv[],
-  int nps[],
-  int *nwcs,
-  struct wcsprm **wcs)
-
-{
-  int ialt, npsmax, npvmax, status = 0;
-  struct wcsprm *wcsp;
-
-  /* Find the number of coordinate descriptions. */
-  *nwcs = 0;
-  for (ialt = 0; ialt < 27; ialt++) {
-    if (alts[ialt]) (*nwcs)++;
-  }
-
-  if (!(*nwcs) && naxis) {
-    /* NAXIS is non-zero but there were no WCS keywords with an alternate
-       version code; create a default WCS with blank alternate version. */
-    wcspih_naxes(naxis, 0, 0, ' ', alts, 0x0);
-    *nwcs = 1;
-  }
-
-  if (*nwcs) {
-    /* Allocate memory for the required number of wcsprm structs. */
-    if (!(*wcs = calloc(*nwcs, sizeof(struct wcsprm)))) {
-      return 2;
-    }
-
-    /* Record the current values of NPVMAX and NPSMAX. */
-    npvmax = wcsnpv(-1);
-    npsmax = wcsnps(-1);
-
-    /* Initialize each wcsprm struct. */
-    wcsp = *wcs;
-    *nwcs = 0;
-    for (ialt = 0; ialt < 27; ialt++) {
-      if (alts[ialt]) {
-        wcsp->flag = -1;
-        wcsnpv(npv[ialt]);
-        wcsnps(nps[ialt]);
-        if ((status = wcsini(1, alts[ialt], wcsp))) {
-          wcsvfree(nwcs, wcs);
-          break;
-        }
-
-        /* Record the alternate version code. */
-        if (ialt) {
-          wcsp->alt[0] = 'A' + ialt - 1;
-        }
-
-        /* On the second pass alts[] indexes the array of wcsprm structs. */
-        alts[ialt] = (*nwcs)++;
-
-        wcsp++;
-      }
-    }
-
-    /* Restore the original values of NPVMAX and NPSMAX. */
-    wcsnpv(npvmax);
-    wcsnps(npsmax);
-  }
-
-  return status;
-}
-
-
-/*----------------------------------------------------------------------------
-* Interpret special keywords encountered for each coordinate representation.
-*---------------------------------------------------------------------------*/
-
-int wcspih_final(
-  int alts[],
-  double epoch[],
-  double vsource[],
-  int *nwcs,
-  struct wcsprm **wcs)
-
-{
-  int ialt, status;
-  double beta, c = 299792458.0;
-
-  for (ialt = 0; ialt < *nwcs; ialt++) {
-    /* Check for EPOCH overriding EQUINOXa. */
-    if (undefined((*wcs+ialt)->equinox) && !undefined(epoch[ialt])) {
-      /* Set EQUINOXa. */
-      (*wcs+ialt)->equinox = epoch[ialt];
-    }
-
-    /* Check for VSOURCEa overriding ZSOURCEa. */
-    if (undefined((*wcs+ialt)->zsource) && !undefined(vsource[ialt])) {
-      /* Convert relativistic Doppler velocity to redshift. */
-      beta = vsource[ialt]/c;
-      (*wcs+ialt)->zsource = (1.0+beta)/sqrt(1.0 - beta*beta) - 1.0;
-    }
-
-    /* Interpret -TAB header keywords. */
-    if ((status = wcstab(*wcs+ialt))) {
-       wcsvfree(nwcs, wcs);
-       return status;
-    }
-  }
-
-  return 0;
-}
diff --git a/astropy/wcs/src/wcslib/C/wcsprintf.c b/astropy/wcs/src/wcslib/C/wcsprintf.c
deleted file mode 100644
index 6105aa4..0000000
--- a/astropy/wcs/src/wcslib/C/wcsprintf.c
+++ /dev/null
@@ -1,124 +0,0 @@
-/*============================================================================
-
-  WCSLIB 4.10 - an implementation of the FITS WCS standard.
-  Copyright (C) 1995-2012, Mark Calabretta
-
-  This file is part of WCSLIB.
-
-  WCSLIB is free software: you can redistribute it and/or modify it under the
-  terms of the GNU Lesser General Public License as published by the Free
-  Software Foundation, either version 3 of the License, or (at your option)
-  any later version.
-
-  WCSLIB 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 Lesser General Public License for
-  more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with WCSLIB.  If not, see <http://www.gnu.org/licenses/>.
-
-  Correspondence concerning WCSLIB may be directed to:
-    Internet email: mcalabre at atnf.csiro.au
-    Postal address: Dr. Mark Calabretta
-                    Australia Telescope National Facility, CSIRO
-                    PO Box 76
-                    Epping NSW 1710
-                    AUSTRALIA
-
-  Author: Mark Calabretta, Australia Telescope National Facility
-  http://www.atnf.csiro.au/~mcalabre/index.html
-  $Id: wcsprintf.c,v 4.10 2012/02/05 23:41:44 cal103 Exp $
-*===========================================================================*/
-
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "wcsprintf.h"
-
-static FILE  *wcsprintf_file = 0x0;
-static char  *wcsprintf_buff = 0x0;
-static char  *wcsprintf_bufp = 0x0;
-static size_t wcsprintf_size = 0;
-
-/*--------------------------------------------------------------------------*/
-
-int wcsprintf_set(FILE *wcsout)
-{
-  if (wcsout != 0x0) {
-    /* Output to file. */
-    wcsprintf_file = wcsout;
-
-    if (wcsprintf_buff != 0x0) {
-      /* Release the buffer. */
-      free(wcsprintf_buff);
-      wcsprintf_buff = 0x0;
-    }
-
-  } else {
-    /* Output to buffer. */
-    if (wcsprintf_buff == 0x0) {
-      /* Allocate a buffer. */
-      wcsprintf_buff = malloc(1024);
-      if (wcsprintf_buff == NULL) {
-        return 1;
-      }
-      wcsprintf_size = 1024;
-    }
-
-    /* Reset pointer to the start of the buffer. */
-    wcsprintf_bufp = wcsprintf_buff;
-    *wcsprintf_bufp = '\0';
-  }
-
-  return 0;
-}
-
-/*--------------------------------------------------------------------------*/
-
-const char *wcsprintf_buf(void)
-{
-  return wcsprintf_buff;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int wcsprintf(const char *format, ...)
-{
-  int  nbytes;
-  size_t  used;
-  va_list arg_list;
-
-  if (wcsprintf_buff == 0x0 && wcsprintf_file == 0x0) {
-    /* Send output to stdout if wcsprintf_set() hasn't been called. */
-    wcsprintf_file = stdout;
-  }
-
-  va_start(arg_list, format);
-
-  if (wcsprintf_file) {
-    /* Output to file. */
-    nbytes = vfprintf(wcsprintf_file, format, arg_list);
-
-  } else {
-    /* Output to buffer. */
-    used = wcsprintf_bufp - wcsprintf_buff;
-    if (wcsprintf_size - used < 128) {
-      /* Expand the buffer. */
-      wcsprintf_size += 1024;
-      wcsprintf_buff = realloc(wcsprintf_buff, wcsprintf_size);
-      if (wcsprintf_buff == NULL) {
-        return 1;
-      }
-      wcsprintf_bufp = wcsprintf_buff + used;
-    }
-
-    nbytes = vsprintf(wcsprintf_bufp, format, arg_list);
-    wcsprintf_bufp += nbytes;
-  }
-
-  va_end(arg_list);
-
-  return nbytes;
-}
diff --git a/astropy/wcs/src/wcslib/C/wcsprintf.h b/astropy/wcs/src/wcslib/C/wcsprintf.h
deleted file mode 100644
index f88ebe3..0000000
--- a/astropy/wcs/src/wcslib/C/wcsprintf.h
+++ /dev/null
@@ -1,131 +0,0 @@
-/*============================================================================
-
-  WCSLIB 4.10 - an implementation of the FITS WCS standard.
-  Copyright (C) 1995-2012, Mark Calabretta
-
-  This file is part of WCSLIB.
-
-  WCSLIB is free software: you can redistribute it and/or modify it under the
-  terms of the GNU Lesser General Public License as published by the Free
-  Software Foundation, either version 3 of the License, or (at your option)
-  any later version.
-
-  WCSLIB 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 Lesser General Public License for
-  more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with WCSLIB.  If not, see <http://www.gnu.org/licenses/>.
-
-  Correspondence concerning WCSLIB may be directed to:
-    Internet email: mcalabre at atnf.csiro.au
-    Postal address: Dr. Mark Calabretta
-                    Australia Telescope National Facility, CSIRO
-                    PO Box 76
-                    Epping NSW 1710
-                    AUSTRALIA
-
-  Author: Mark Calabretta, Australia Telescope National Facility
-  http://www.atnf.csiro.au/~mcalabre/index.html
-  $Id: wcsprintf.h,v 4.10 2012/02/05 23:41:44 cal103 Exp $
-*=============================================================================
-*
-* WCSLIB 4.10 - C routines that implement the FITS World Coordinate System
-* (WCS) standard.
-*
-* Summary of the wcsprintf routines
-* ---------------------------------
-* These routines allow diagnostic output from celprt(), linprt(), prjprt(),
-* spcprt(), tabprt(), wcsprt(), and wcserr_prt() to be redirected to a file or
-* captured in a string buffer.  Those routines all use wcsprintf() for output.
-*
-*
-* wcsprintf() - Print function used by WCSLIB diagnostic routines
-* ---------------------------------------------------------------
-* wcsprintf() is used by the celprt(), linprt(), prjprt(), spcprt(), tabprt(),
-* wcsprt(), and wcserr_prt() routines.  Its output may be redirected to a file
-* or string buffer via wcsprintf_set().  By default output goes to stdout.
-*
-* Given:
-*   format    char*     Format string, passed to one of the printf(3) family
-*                       of stdio library functions.
-*
-*   ...       mixed     Argument list matching format, as per printf(3).
-*
-* Function return value:
-*             int       Number of bytes written.
-*
-*
-* wcsprintf_set() - Set output disposition for wcsprintf()
-* --------------------------------------------------------
-* wcsprintf_set() sets the output disposition for wcsprintf() which is used by
-* the celprt(), linprt(), prjprt(), spcprt(), tabprt(), wcsprt(), and
-* wcserr_prt() routines.
-*
-* Output goes to stdout by default if wcsprintf_set() has not been called.
-*
-* Given:
-*   wcsout    FILE*     Pointer to an output stream that has been opened for
-*                       writing, e.g. by the fopen() stdio library function,
-*                       or one of the predefined stdio output streams - stdout
-*                       and stderr.  If zero (NULL), output is written to an
-*                       internally-allocated string buffer, the address of
-*                       which may be obtained by wcsprintf_buf().
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*
-*
-* wcsprintf_buf() - Get the address of the internal string buffer
-* ---------------------------------------------------------------
-* wcsprintf_buf() returns the address of the internal string buffer created
-* when wcsprintf_set() is invoked with its FILE* argument set to zero.
-*
-* Function return value:
-*             const char *
-*                       Address of the internal string buffer.  The user may
-*                       free this buffer by calling wcsprintf_set() with a
-*                       valid FILE*, e.g. stdout.  The free() stdlib library
-*                       function must NOT be invoked on this const pointer.
-*
-*
-* WCSPRINTF_PTR() macro - Print addresses in a consistent way
-* -----------------------------------------------------------
-* WCSPRINTF_PTR() is a preprocessor macro used to print addresses in a
-* consistent way.
-*
-* On some systems the "%p" format descriptor renders a NULL pointer as the
-* string "0x0".  On others, however, it produces "0" or even "(nil)".  On
-* some systems a non-zero address is prefixed with "0x", on others, not.
-*
-* The WCSPRINTF_PTR() macro ensures that a NULL pointer is always rendered as
-* "0x0" and that non-zero addresses are prefixed with "0x" thus providing
-* consistency, for example, for comparing the output of test programs.
-*
-*===========================================================================*/
-
-#ifndef WCSLIB_WCSPRINTF
-#define WCSLIB_WCSPRINTF
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define WCSPRINTF_PTR(str1, ptr, str2) \
-  if (ptr) { \
-    wcsprintf("%s%#lx%s", (str1), (unsigned long)(ptr), (str2)); \
-  } else { \
-    wcsprintf("%s0x0%s", (str1), (str2)); \
-  }
-
-int wcsprintf_set(FILE *wcsout);
-int wcsprintf(const char *format, ...);
-const char *wcsprintf_buf(void);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* WCSLIB_WCSPRINTF */
diff --git a/astropy/wcs/src/wcslib/C/wcstrig.c b/astropy/wcs/src/wcslib/C/wcstrig.c
deleted file mode 100644
index a6c77a8..0000000
--- a/astropy/wcs/src/wcslib/C/wcstrig.c
+++ /dev/null
@@ -1,225 +0,0 @@
-/*============================================================================
-
-  WCSLIB 4.10 - an implementation of the FITS WCS standard.
-  Copyright (C) 1995-2012, Mark Calabretta
-
-  This file is part of WCSLIB.
-
-  WCSLIB is free software: you can redistribute it and/or modify it under the
-  terms of the GNU Lesser General Public License as published by the Free
-  Software Foundation, either version 3 of the License, or (at your option)
-  any later version.
-
-  WCSLIB 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 Lesser General Public License for
-  more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with WCSLIB.  If not, see <http://www.gnu.org/licenses/>.
-
-  Correspondence concerning WCSLIB may be directed to:
-    Internet email: mcalabre at atnf.csiro.au
-    Postal address: Dr. Mark Calabretta
-                    Australia Telescope National Facility, CSIRO
-                    PO Box 76
-                    Epping NSW 1710
-                    AUSTRALIA
-
-  Author: Mark Calabretta, Australia Telescope National Facility
-  http://www.atnf.csiro.au/~mcalabre/index.html
-  $Id: wcstrig.c,v 4.10 2012/02/05 23:41:44 cal103 Exp $
-*===========================================================================*/
-
-#include <math.h>
-#include <stdlib.h>
-#include "wcsmath.h"
-#include "wcstrig.h"
-
-double cosd(angle)
-
-double angle;
-
-{
-  int i;
-
-  if (fmod(angle,90.0) == 0.0) {
-    i = abs((int)floor(angle/90.0 + 0.5))%4;
-    switch (i) {
-    case 0:
-      return 1.0;
-    case 1:
-      return 0.0;
-    case 2:
-      return -1.0;
-    case 3:
-      return 0.0;
-    }
-  }
-
-  return cos(angle*D2R);
-}
-
-/*--------------------------------------------------------------------------*/
-
-double sind(angle)
-
-double angle;
-
-{
-  int i;
-
-  if (fmod(angle,90.0) == 0.0) {
-    i = abs((int)floor(angle/90.0 - 0.5))%4;
-    switch (i) {
-    case 0:
-      return 1.0;
-    case 1:
-      return 0.0;
-    case 2:
-      return -1.0;
-    case 3:
-      return 0.0;
-    }
-  }
-
-  return sin(angle*D2R);
-}
-
-/*--------------------------------------------------------------------------*/
-
-void sincosd(double angle, double *s, double *c)
-
-{
-  int i;
-
-  if (fmod(angle,90.0) == 0.0) {
-    i = abs((int)floor(angle/90.0 + 0.5))%4;
-    switch (i) {
-    case 0:
-      *s = 0.0;
-      *c = 1.0;
-      return;
-    case 1:
-      *s = (angle > 0.0) ? 1.0 : -1.0;
-      *c = 0.0;
-      return;
-    case 2:
-      *s =  0.0;
-      *c = -1.0;
-      return;
-    case 3:
-      *s = (angle > 0.0) ? -1.0 : 1.0;
-      *c = 0.0;
-      return;
-    }
-  }
-
-#ifdef HAVE_SINCOS
-  sincos(angle*D2R, s, c);
-#else
-  *s = sin(angle*D2R);
-  *c = cos(angle*D2R);
-#endif
-
-  return;
-}
-
-/*--------------------------------------------------------------------------*/
-
-double tand(angle)
-
-double angle;
-
-{
-  double resid;
-
-  resid = fmod(angle,360.0);
-  if (resid == 0.0 || fabs(resid) == 180.0) {
-    return 0.0;
-  } else if (resid == 45.0 || resid == 225.0) {
-    return 1.0;
-  } else if (resid == -135.0 || resid == -315.0) {
-    return -1.0;
-  }
-
-  return tan(angle*D2R);
-}
-
-/*--------------------------------------------------------------------------*/
-
-double acosd(v)
-
-double v;
-
-{
-  if (v >= 1.0) {
-    if (v-1.0 <  WCSTRIG_TOL) return 0.0;
-  } else if (v == 0.0) {
-    return 90.0;
-  } else if (v <= -1.0) {
-    if (v+1.0 > -WCSTRIG_TOL) return 180.0;
-  }
-
-  return acos(v)*R2D;
-}
-
-/*--------------------------------------------------------------------------*/
-
-double asind(v)
-
-double v;
-
-{
-  if (v <= -1.0) {
-    if (v+1.0 > -WCSTRIG_TOL) return -90.0;
-  } else if (v == 0.0) {
-    return 0.0;
-  } else if (v >= 1.0) {
-    if (v-1.0 <  WCSTRIG_TOL) return 90.0;
-  }
-
-  return asin(v)*R2D;
-}
-
-/*--------------------------------------------------------------------------*/
-
-double atand(v)
-
-double v;
-
-{
-  if (v == -1.0) {
-    return -45.0;
-  } else if (v == 0.0) {
-    return 0.0;
-  } else if (v == 1.0) {
-    return 45.0;
-  }
-
-  return atan(v)*R2D;
-}
-
-/*--------------------------------------------------------------------------*/
-
-double atan2d(y, x)
-
-double x, y;
-
-{
-  if (y == 0.0) {
-    if (x >= 0.0) {
-      return 0.0;
-    } else if (x < 0.0) {
-      return 180.0;
-    }
-  } else if (x == 0.0) {
-    if (y > 0.0) {
-      return 90.0;
-    } else if (y < 0.0) {
-      return -90.0;
-    }
-   }
-
-   return atan2(y,x)*R2D;
-}
diff --git a/astropy/wcs/src/wcslib/C/wcstrig.h b/astropy/wcs/src/wcslib/C/wcstrig.h
deleted file mode 100644
index ac2c71d..0000000
--- a/astropy/wcs/src/wcslib/C/wcstrig.h
+++ /dev/null
@@ -1,218 +0,0 @@
-/*============================================================================
-
-  WCSLIB 4.10 - an implementation of the FITS WCS standard.
-  Copyright (C) 1995-2012, Mark Calabretta
-
-  This file is part of WCSLIB.
-
-  WCSLIB is free software: you can redistribute it and/or modify it under the
-  terms of the GNU Lesser General Public License as published by the Free
-  Software Foundation, either version 3 of the License, or (at your option)
-  any later version.
-
-  WCSLIB 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 Lesser General Public License for
-  more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with WCSLIB.  If not, see <http://www.gnu.org/licenses/>.
-
-  Correspondence concerning WCSLIB may be directed to:
-    Internet email: mcalabre at atnf.csiro.au
-    Postal address: Dr. Mark Calabretta
-                    Australia Telescope National Facility, CSIRO
-                    PO Box 76
-                    Epping NSW 1710
-                    AUSTRALIA
-
-  Author: Mark Calabretta, Australia Telescope National Facility
-  http://www.atnf.csiro.au/~mcalabre/index.html
-  $Id: wcstrig.h,v 4.10 2012/02/05 23:41:44 cal103 Exp $
-*=============================================================================
-*
-* Summary of the wcstrig routines
-* -------------------------------
-* When dealing with celestial coordinate systems and spherical projections
-* (some moreso than others) it is often desirable to use an angular measure
-* that provides an exact representation of the latitude of the north or south
-* pole.  The WCSLIB routines use the following trigonometric functions that
-* take or return angles in degrees:
-*
-*   - cosd()
-*   - sind()
-*   - tand()
-*   - acosd()
-*   - asind()
-*   - atand()
-*   - atan2d()
-*   - sincosd()
-*
-* These "trigd" routines are expected to handle angles that are a multiple of
-* 90 degrees returning an exact result.  Some C implementations provide these
-* as part of a system library and in such cases it may (or may not!) be
-* preferable to use them.  WCSLIB provides wrappers on the standard trig
-* functions based on radian measure, adding tests for multiples of 90 degrees.
-*
-* However, wcstrig.h also provides the choice of using preprocessor macro
-* implementations of the trigd functions that don't test for multiples of
-* 90 degrees (compile with -DWCSTRIG_MACRO).  These are typically 20% faster
-* but may lead to problems near the poles.
-*
-*
-* cosd() - Cosine of an angle in degrees
-* --------------------------------------
-* cosd() returns the cosine of an angle given in degrees.
-*
-* Given:
-*   angle     double    [deg].
-*
-* Function return value:
-*             double    Cosine of the angle.
-*
-*
-* sind() - Sine of an angle in degrees
-* ------------------------------------
-* sind() returns the sine of an angle given in degrees.
-*
-* Given:
-*   angle     double    [deg].
-*
-* Function return value:
-*             double    Sine of the angle.
-*
-*
-* sincosd() - Sine and cosine of an angle in degrees
-* --------------------------------------------------
-* sincosd() returns the sine and cosine of an angle given in degrees.
-*
-* Given:
-*   angle     double    [deg].
-*
-* Returned:
-*   sin       *double   Sine of the angle.
-*
-*   cos       *double   Cosine of the angle.
-*
-* Function return value:
-*             void
-*
-*
-* tand() - Tangent of an angle in degrees
-* ---------------------------------------
-* tand() returns the tangent of an angle given in degrees.
-*
-* Given:
-*   angle     double    [deg].
-*
-* Function return value:
-*             double    Tangent of the angle.
-*
-*
-* acosd() - Inverse cosine, returning angle in degrees
-* ----------------------------------------------------
-* acosd() returns the inverse cosine in degrees.
-*
-* Given:
-*   x         double    in the range [-1,1].
-*
-* Function return value:
-*             double    Inverse cosine of x [deg].
-*
-*
-* asind() - Inverse sine, returning angle in degrees
-* --------------------------------------------------
-* asind() returns the inverse sine in degrees.
-*
-* Given:
-*   y         double    in the range [-1,1].
-*
-* Function return value:
-*             double    Inverse sine of y [deg].
-*
-*
-* atand() - Inverse tangent, returning angle in degrees
-* -----------------------------------------------------
-* atand() returns the inverse tangent in degrees.
-*
-* Given:
-*   s         double
-*
-* Function return value:
-*             double    Inverse tangent of s [deg].
-*
-*
-* atan2d() - Polar angle of (x,y), in degrees
-* -------------------------------------------
-* atan2d() returns the polar angle, beta, in degrees, of polar coordinates
-* (rho,beta) corresponding Cartesian coordinates (x,y).  It is equivalent to
-* the arg(x,y) function of WCS Paper II, though with transposed arguments.
-*
-* Given:
-*   y         double    Cartesian y-coordinate.
-*
-*   x         double    Cartesian x-coordinate.
-*
-* Function return value:
-*             double    Polar angle of (x,y) [deg].
-*
-*===========================================================================*/
-
-#ifndef WCSLIB_WCSTRIG
-#define WCSLIB_WCSTRIG
-
-#include <math.h>
-
-#include "wcsconfig.h"
-
-#ifdef HAVE_SINCOS
-  void sincos(double angle, double *sin, double *cos);
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-#ifdef WCSTRIG_MACRO
-
-/* Macro implementation of the trigd functions. */
-#include "wcsmath.h"
-
-#define cosd(X) cos((X)*D2R)
-#define sind(X) sin((X)*D2R)
-#define tand(X) tan((X)*D2R)
-#define acosd(X) acos(X)*R2D
-#define asind(X) asin(X)*R2D
-#define atand(X) atan(X)*R2D
-#define atan2d(Y,X) atan2(Y,X)*R2D
-#ifdef HAVE_SINCOS
-  #define sincosd(X,S,C) sincos((X)*D2R,(S),(C))
-#else
-  #define sincosd(X,S,C) *(S) = sin((X)*D2R); *(C) = cos((X)*D2R);
-#endif
-
-#else
-
-/* Use WCSLIB wrappers or native trigd functions. */
-
-double cosd(double angle);
-double sind(double angle);
-void sincosd(double angle, double *sin, double *cos);
-double tand(double angle);
-double acosd(double x);
-double asind(double y);
-double atand(double s);
-double atan2d(double y, double x);
-
-/* Domain tolerance for asin() and acos() functions. */
-#define WCSTRIG_TOL 1e-10
-
-#endif /* WCSTRIG_MACRO */
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* WCSLIB_WCSTRIG */
diff --git a/astropy/wcs/src/wcslib/C/wcsulex.l b/astropy/wcs/src/wcslib/C/wcsulex.l
deleted file mode 100644
index cb8fb21..0000000
--- a/astropy/wcs/src/wcslib/C/wcsulex.l
+++ /dev/null
@@ -1,997 +0,0 @@
-/*============================================================================
-
-  WCSLIB 4.10 - an implementation of the FITS WCS standard.
-  Copyright (C) 1995-2012, Mark Calabretta
-
-  This file is part of WCSLIB.
-
-  WCSLIB is free software: you can redistribute it and/or modify it under the
-  terms of the GNU Lesser General Public License as published by the Free
-  Software Foundation, either version 3 of the License, or (at your option)
-  any later version.
-
-  WCSLIB 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 Lesser General Public License for
-  more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with WCSLIB.  If not, see <http://www.gnu.org/licenses/>.
-
-  Correspondence concerning WCSLIB may be directed to:
-    Internet email: mcalabre at atnf.csiro.au
-    Postal address: Dr. Mark Calabretta
-                    Australia Telescope National Facility, CSIRO
-                    PO Box 76
-                    Epping NSW 1710
-                    AUSTRALIA
-
-  Author: Mark Calabretta, Australia Telescope National Facility
-  http://www.atnf.csiro.au/~mcalabre/index.html
-  $Id: wcsulex.l,v 4.10 2012/02/05 23:41:44 cal103 Exp $
-*=============================================================================
-*
-* wcsulex.l is a Flex description file containing the definition of a
-* recursive, multi-buffered lexical scanner that parses FITS units
-* specifications.
-*
-* It requires Flex v2.5.4 or later.
-*
-* Refer to wcsunits.h for a description of the user interface and operating
-* notes.
-*
-*===========================================================================*/
-
-/* Options. */
-%option full
-%option never-interactive
-%option noyywrap
-%option outfile="wcsulex.c"
-%option prefix="wcsulex"
-
-/* Exponents. */
-INTEGER	  [+-]?[1-9][0-9]*
-FRAC	  {INTEGER}"/"[1-9][0-9]*
-FLOAT	  [+-]?([0-9]+\.?[0-9]*|\.[0-9]+)
-
-/* Metric prefixes. */
-SUB3	  [munpfazy]
-SUBPREFIX [dc]|{SUB3}
-SUP3	  [kMGTPEZY]
-SUPPREFIX da|h|{SUP3}
-PREFIX	  {SUBPREFIX}|{SUPPREFIX}
-
-/* Basic and derived SI units. */
-BASIC	  m|s|g|rad|sr|K|A|mol|cd
-DERIVED	  Hz|J|W|V|N|Pa|C|[Oo]hm|S|F|Wb|T|H|lm|lx
-SI_UNIT	  {BASIC}|{DERIVED}
-
-/* Additional recognized units: all metric prefixes allowed. */
-ADD_ALL	  eV|Jy|R|G|barn
-
-/* Additional recognized units: only super-metric prefixes allowed. */
-ADD_SUP	  a|yr|pc|bit|[bB]yte
-
-/* Additional recognized units: only sub-metric prefixes allowed. */
-ADD_SUB	  mag
-
-/* Additional recognized units for which NO metric prefixes are allowed. */
-GENERAL	  deg|arcmin|arcsec|mas|d|h|min|erg|Ry|u|D
-ASTRO	  [Aa]ngstrom|AU|lyr|beam|solRad|solMass|solLum|Sun
-DEVICE	  adu|bin|chan|count|ct|photon|ph|pixel|pix|voxel
-ADD_NONE  {GENERAL}|{ASTRO}|{DEVICE}
-
-/* All additional recognized units. */
-ADD_UNIT  {ADD_ALL}|{ADD_SUP}|{ADD_SUB}|{ADD_NONE}
-
-/* Exclusive start states. */
-%x PAREN PREFIX UNITS EXPON FLUSH
-
-%{
-/* To get the prototype for fileno() from stdio.h when gcc is invoked with
- * -std=c89 (same as -ansi) or -std=c99 since we do not define YY_INPUT. */
-#define _POSIX_SOURCE 1
-
-#include <math.h>
-#include <setjmp.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "wcserr.h"
-#include "wcsmath.h"
-#include "wcsunits.h"
-
-#define YY_DECL int wcsulexe(const char unitstr[], int *func, double *scale, \
-                             double units[], struct wcserr **err)
-
-/* Used in preempting the call to exit() by yy_fatal_error(). */
-jmp_buf wcsulex_abort_jmp_env;
-#define exit(status) longjmp(wcsulex_abort_jmp_env, status)
-
-%}
-
-%%
-	static const char *function = "wcsulexe";
-
-	int bracket  = 0;
-	int operator = 0;
-	int paren    = 0;
-	int status   = 0;
-	int func_r, i, j;
-	double dexp, expon, factor, factor_r, types[WCSUNITS_NTYPE];
-	YY_BUFFER_STATE buf;
-	void add(double *factor, double types[], double *expon, double *scale,
-	    double units[]);
-	int yylex_destroy(void);
-	
-	*func = 0;
-	for (i = 0; i < WCSUNITS_NTYPE; i++) {
-	  units[i] = 0.0;
-	  types[i] = 0.0;
-	}
-	expon  = 1.0;
-	factor = 1.0;
-	*scale = 1.0;
-	
-	yy_scan_string(unitstr);
-	
-	/* Return here via longjmp() invoked by yy_fatal_error(). */
-	if (setjmp(wcsulex_abort_jmp_env)) {
-	  return wcserr_set(WCSERR_SET(UNITSERR_PARSER_ERROR),
-	    "Internal units parser error parsing '%s'", unitstr);
-	}
-	
-	BEGIN(INITIAL);
-	
-	#ifdef DEBUG
-	fprintf(stderr, "\n%s ->\n", unitstr);
-	#endif
-
-^" "+	{
-	  /* Pretend initial whitespace doesn't exist. */
-	  yy_set_bol(1);
-	}
-
-^"["	{
-	  if (bracket++) {
-	    BEGIN(FLUSH);
-	  } else {
-	    yy_set_bol(1);
-	  }
-	}
-
-^10[0-9] {
-	  status = wcserr_set(WCSERR_SET(UNITSERR_BAD_NUM_MULTIPLIER),
-	    "Invalid exponent in '%s'", unitstr);
-	  BEGIN(FLUSH);
-	}
-
-^10	{
-	  factor = 10.0;
-	  BEGIN(EXPON);
-	}
-
-^log" "*"(" {
-	  *func = 1;
-	  unput('(');
-	  BEGIN(PAREN);
-	}
-
-^ln" "*"(" {
-	  *func = 2;
-	  unput('(');
-	  BEGIN(PAREN);
-	}
-
-^exp" "*"(" {
-	  *func = 3;
-	  unput('(');
-	  BEGIN(PAREN);
-	}
-
-^[*.]	{
-	  /* Leading binary multiply. */
-	  status = wcserr_set(WCSERR_SET(UNITSERR_DANGLING_BINOP),
-	    "Dangling binary operator in '%s'", unitstr);
-	  BEGIN(FLUSH);
-	}
-
-" "+	  /* Discard whitespace in INITIAL context. */
-
-sqrt" "*"(" {
-	  expon /= 2.0;
-	  unput('(');
-	  BEGIN(PAREN);
-	}
-
-"("	{
-	  /* Gather terms in parentheses. */
-	  yyless(0);
-	  BEGIN(PAREN);
-	}
-
-[*.]	{
-	  if (operator++) {
-	    BEGIN(FLUSH);
-	  }
-	}
-
-^1"/" |
-"/"	{
-	  if (operator++) {
-	    BEGIN(FLUSH);
-	  } else {
-	    expon *= -1.0;
-	  }
-	}
-
-{SI_UNIT}|{ADD_UNIT} {
-	  operator = 0;
-	  yyless(0);
-	  BEGIN(UNITS);
-	}
-
-{PREFIX}({SI_UNIT}|{ADD_ALL}) |
-{SUPPREFIX}{ADD_SUP} |
-{SUBPREFIX}{ADD_SUB} {
-	  operator = 0;
-	  yyless(0);
-	  BEGIN(PREFIX);
-	}
-
-"]"	{
-	  bracket = !bracket;
-	  BEGIN(FLUSH);
-	}
-
-.	{
-	  status = wcserr_set(WCSERR_SET(UNITSERR_BAD_INITIAL_SYMBOL),
-	    "Invalid symbol in INITIAL context in '%s'", unitstr);
-	  BEGIN(FLUSH);
-	}
-
-<PAREN>"(" {
-	  paren++;
-	  operator = 0;
-	  yymore();
-	}
-
-<PAREN>")" {
-	  paren--;
-	  if (paren) {
-	    /* Not balanced yet. */
-	    yymore();
-	
-	  } else {
-	    /* Balanced; strip off the outer parentheses and recurse. */
-	    yytext[yyleng-1] = '\0';
-	
-	    buf = YY_CURRENT_BUFFER;
-	    status = wcsulexe(yytext+1, &func_r, &factor_r, types, err);
-	    yy_switch_to_buffer(buf);
-	
-	    if (func_r) {
-	      status = wcserr_set(WCSERR_SET(UNITSERR_FUNCTION_CONTEXT),
-	        "Function in invalid context in '%s'", unitstr);
-	    }
-	
-	    if (status) {
-	      BEGIN(FLUSH);
-	    } else {
-	      factor *= factor_r;
-	      BEGIN(EXPON);
-	    }
-	  }
-	}
-
-<PAREN>[^()]+ {
-	  yymore();
-	}
-
-<PREFIX>d {
-	  factor = 1e-1;
-	  BEGIN(UNITS);
-	}
-
-<PREFIX>c {
-	  factor = 1e-2;
-	  BEGIN(UNITS);
-	}
-
-<PREFIX>m {
-	  factor = 1e-3;
-	  BEGIN(UNITS);
-	}
-
-<PREFIX>u {
-	  factor = 1e-6;
-	  BEGIN(UNITS);
-	}
-
-<PREFIX>n {
-	  factor = 1e-9;
-	  BEGIN(UNITS);
-	}
-
-<PREFIX>p {
-	  factor = 1e-12;
-	  BEGIN(UNITS);
-	}
-
-<PREFIX>f {
-	  factor = 1e-15;
-	  BEGIN(UNITS);
-	}
-
-<PREFIX>a {
-	  factor = 1e-18;
-	  BEGIN(UNITS);
-	}
-
-<PREFIX>z {
-	  factor = 1e-21;
-	  BEGIN(UNITS);
-	}
-
-<PREFIX>y {
-	  factor = 1e-24;
-	  BEGIN(UNITS);
-	}
-
-<PREFIX>da {
-	  factor = 1e+1;
-	  BEGIN(UNITS);
-	}
-
-<PREFIX>h {
-	  factor = 1e+2;
-	  BEGIN(UNITS);
-	}
-
-<PREFIX>k {
-	  factor = 1e+3;
-	  BEGIN(UNITS);
-	}
-
-<PREFIX>M {
-	  factor = 1e+6;
-	  BEGIN(UNITS);
-	}
-
-<PREFIX>G {
-	  factor = 1e+9;
-	  BEGIN(UNITS);
-	}
-
-<PREFIX>T {
-	  factor = 1e+12;
-	  BEGIN(UNITS);
-	}
-
-<PREFIX>P {
-	  factor = 1e+15;
-	  BEGIN(UNITS);
-	}
-
-<PREFIX>E {
-	  factor = 1e+18;
-	  BEGIN(UNITS);
-	}
-
-<PREFIX>Z {
-	  factor = 1e+21;
-	  BEGIN(UNITS);
-	}
-
-<PREFIX>Y {
-	  factor = 1e+24;
-	  BEGIN(UNITS);
-	}
-
-<PREFIX>. {
-	  /* Internal parser error. */
-	  status = wcserr_set(WCSERR_SET(UNITSERR_PARSER_ERROR),
-	    "Internal units parser error parsing '%s'", unitstr);
-	  BEGIN(FLUSH);
-	}
-
-<UNITS>A {
-	  /* Ampere. */
-	  types[WCSUNITS_CHARGE] += 1.0;
-	  types[WCSUNITS_TIME]   -= 1.0;
-	  BEGIN(EXPON);
-	}
-
-<UNITS>a|yr {
-	  /* Year (annum). */
-	  factor *= 31557600.0;
-	  types[WCSUNITS_TIME] += 1.0;
-	  BEGIN(EXPON);
-	}
-
-<UNITS>adu {
-	  /* Analogue-to-digital converter units. */
-	  types[WCSUNITS_COUNT] += 1.0;
-	  BEGIN(EXPON);
-	}
-
-<UNITS>[Aa]ngstrom {
-	  /* Angstrom. */
-	  factor *= 1e-10;
-	  types[WCSUNITS_LENGTH] += 1.0;
-	  BEGIN(EXPON);
-	}
-
-<UNITS>arcmin {
-	  /* Minute of arc. */
-	  factor /= 60.0;
-	  types[WCSUNITS_PLANE_ANGLE] += 1.0;
-	  BEGIN(EXPON);
-	}
-
-<UNITS>arcsec {
-	  /* Second of arc. */
-	  factor /= 3600.0;
-	  types[WCSUNITS_PLANE_ANGLE] += 1.0;
-	  BEGIN(EXPON);
-	}
-
-<UNITS>AU {
-	  /* Astronomical unit. */
-	  factor *= 1.49598e+11;
-	  types[WCSUNITS_LENGTH] += 1.0;
-	  BEGIN(EXPON);
-	}
-
-<UNITS>barn {
-	  /* Barn. */
-	  factor *= 1e-28;
-	  types[WCSUNITS_LENGTH] += 2.0;
-	  BEGIN(EXPON);
-	}
-
-<UNITS>beam {
-	  /* Beam, as in Jy/beam. */
-	  types[WCSUNITS_BEAM] += 1.0;
-	  BEGIN(EXPON);
-	}
-
-<UNITS>bin {
-	  /* Bin (e.g. histogram). */
-	  types[WCSUNITS_BIN] += 1.0;
-	  BEGIN(EXPON);
-	}
-
-<UNITS>bit {
-	  /* Bit. */
-	  types[WCSUNITS_BIT] += 1.0;
-	  BEGIN(EXPON);
-	}
-
-<UNITS>[bB]yte {
-	  /* Byte. */
-	  factor *= 8.0;
-	  types[WCSUNITS_BIT] += 1.0;
-	  BEGIN(EXPON);
-	}
-
-<UNITS>C {
-	  /* Coulomb. */
-	  types[WCSUNITS_CHARGE] += 1.0;
-	  BEGIN(EXPON);
-	}
-
-<UNITS>cd {
-	  /* Candela. */
-	  types[WCSUNITS_LUMINTEN] += 1.0;
-	  BEGIN(EXPON);
-	}
-
-<UNITS>chan {
-	  /* Channel. */
-	  types[WCSUNITS_BIN] += 1.0;
-	  BEGIN(EXPON);
-	}
-
-<UNITS>count|ct {
-	  /* Count. */
-	  types[WCSUNITS_COUNT] += 1.0;
-	  BEGIN(EXPON);
-	}
-
-<UNITS>D {
-	  /* Debye. */
-	  factor *= 1e-29 / 3.0;
-	  types[WCSUNITS_CHARGE] += 1.0;
-	  types[WCSUNITS_LENGTH] += 1.0;
-	  BEGIN(EXPON);
-	}
-
-<UNITS>d {
-	  /* Day. */
-	  factor *= 86400.0;
-	  types[WCSUNITS_TIME] += 1.0;
-	  BEGIN(EXPON);
-	}
-
-<UNITS>deg {
-	  /* Degree. */
-	  types[WCSUNITS_PLANE_ANGLE] += 1.0;
-	  BEGIN(EXPON);
-	}
-
-<UNITS>erg {
-	  /* Erg. */
-	  factor *= 1e-7;
-	  types[WCSUNITS_MASS]   += 1.0;
-	  types[WCSUNITS_LENGTH] += 2.0;
-	  types[WCSUNITS_TIME]   -= 2.0;
-	  BEGIN(EXPON);
-	}
-
-<UNITS>eV {
-	  /* Electron volt. */
-	  factor *= 1.6021765e-19;
-	  types[WCSUNITS_MASS]   += 1.0;
-	  types[WCSUNITS_LENGTH] += 2.0;
-	  types[WCSUNITS_TIME]   -= 2.0;
-	  BEGIN(EXPON);
-	}
-
-<UNITS>F {
-	  /* Farad. */
-	  types[WCSUNITS_MASS]   -= 1.0;
-	  types[WCSUNITS_LENGTH] -= 2.0;
-	  types[WCSUNITS_TIME]   += 3.0;
-	  types[WCSUNITS_CHARGE] += 2.0;
-	  BEGIN(EXPON);
-	}
-
-<UNITS>G {
-	  /* Gauss. */
-	  factor *= 1e-4;
-	  types[WCSUNITS_MASS]   += 1.0;
-	  types[WCSUNITS_TIME]   += 1.0;
-	  types[WCSUNITS_CHARGE] -= 1.0;
-	  BEGIN(EXPON);
-	}
-
-<UNITS>g {
-	  /* Gram. */
-	  factor *= 1e-3;
-	  types[WCSUNITS_MASS] += 1.0;
-	  BEGIN(EXPON);
-	}
-
-<UNITS>H {
-	  /* Henry. */
-	  types[WCSUNITS_MASS]   += 1.0;
-	  types[WCSUNITS_LENGTH] += 2.0;
-	  types[WCSUNITS_TIME]   += 2.0;
-	  types[WCSUNITS_CHARGE] -= 2.0;
-	  BEGIN(EXPON);
-	}
-
-<UNITS>h {
-	  /* Hour. */
-	  factor *= 3600.0;
-	  types[WCSUNITS_TIME] += 1.0;
-	  BEGIN(EXPON);
-	}
-
-<UNITS>Hz {
-	  /* Hertz. */
-	  types[WCSUNITS_TIME] -= 1.0;
-	  BEGIN(EXPON);
-	}
-
-<UNITS>J {
-	  /* Joule. */
-	  types[WCSUNITS_MASS]   += 1.0;
-	  types[WCSUNITS_LENGTH] += 2.0;
-	  types[WCSUNITS_TIME]   -= 2.0;
-	  BEGIN(EXPON);
-	}
-
-<UNITS>Jy {
-	  /* Jansky. */
-	  factor *= 1e-26;
-	  types[WCSUNITS_MASS] += 1.0;
-	  types[WCSUNITS_TIME] -= 2.0;
-	  BEGIN(EXPON);
-	}
-
-<UNITS>K {
-	  /* Kelvin. */
-	  types[WCSUNITS_TEMPERATURE] += 1.0;
-	  BEGIN(EXPON);
-	}
-
-<UNITS>lm {
-	  /* Lumen. */
-	  types[WCSUNITS_LUMINTEN]    += 1.0;
-	  types[WCSUNITS_SOLID_ANGLE] += 1.0;
-	  BEGIN(EXPON);
-	}
-
-<UNITS>lx {
-	  /* Lux. */
-	  types[WCSUNITS_LUMINTEN]    += 1.0;
-	  types[WCSUNITS_SOLID_ANGLE] += 1.0;
-	  types[WCSUNITS_LENGTH]      -= 2.0;
-	  BEGIN(EXPON);
-	}
-
-<UNITS>lyr {
-	  /* Light year. */
-	  factor *= 2.99792458e8 * 31557600.0;
-	  types[WCSUNITS_LENGTH] += 1.0;
-	  BEGIN(EXPON);
-	}
-
-<UNITS>m {
-	  /* Metre. */
-	  types[WCSUNITS_LENGTH] += 1.0;
-	  BEGIN(EXPON);
-	}
-
-<UNITS>mag {
-	  /* Stellar magnitude. */
-	  types[WCSUNITS_MAGNITUDE] += 1.0;
-	  BEGIN(EXPON);
-	}
-
-<UNITS>mas {
-	  /* Milli-arcsec. */
-	  factor /= 3600e+3;
-	  types[WCSUNITS_PLANE_ANGLE] += 1.0;
-	  BEGIN(EXPON);
-	}
-
-<UNITS>min {
-	  /* Minute. */
-	  factor *= 60.0;
-	  types[WCSUNITS_TIME] += 1.0;
-	  BEGIN(EXPON);
-	}
-
-<UNITS>mol {
-	  /* Mole. */
-	  types[WCSUNITS_MOLE] += 1.0;
-	  BEGIN(EXPON);
-	}
-
-<UNITS>N {
-	  /* Newton. */
-	  types[WCSUNITS_MASS]   += 1.0;
-	  types[WCSUNITS_LENGTH] += 1.0;
-	  types[WCSUNITS_TIME]   -= 2.0;
-	  BEGIN(EXPON);
-	}
-
-<UNITS>[Oo]hm {
-	  /* Ohm. */
-	  types[WCSUNITS_MASS]   += 1.0;
-	  types[WCSUNITS_LENGTH] += 2.0;
-	  types[WCSUNITS_TIME]   -= 1.0;
-	  types[WCSUNITS_CHARGE] -= 2.0;
-	  BEGIN(EXPON);
-	}
-
-<UNITS>Pa {
-	  /* Pascal. */
-	  types[WCSUNITS_MASS]   += 1.0;
-	  types[WCSUNITS_LENGTH] -= 1.0;
-	  types[WCSUNITS_TIME]   -= 2.0;
-	  BEGIN(EXPON);
-	}
-
-<UNITS>pc {
-	  /* Parsec. */
-	  factor *= 3.0857e16;
-	  types[WCSUNITS_LENGTH] += 1.0;
-	  BEGIN(EXPON);
-	}
-
-<UNITS>photon|ph {
-	  /* Photon. */
-	  types[WCSUNITS_COUNT] += 1.0;
-	  BEGIN(EXPON);
-	}
-
-<UNITS>pixel|pix {
-	  /* Pixel. */
-	  types[WCSUNITS_PIXEL] += 1.0;
-	  BEGIN(EXPON);
-	}
-
-<UNITS>R {
-	  /* Rayleigh. */
-	  factor *= 1e10 / (4.0 * PI);
-	  types[WCSUNITS_LENGTH]      -= 2.0;
-	  types[WCSUNITS_TIME]        -= 1.0;
-	  types[WCSUNITS_SOLID_ANGLE] -= 1.0;
-	  BEGIN(EXPON);
-	}
-
-<UNITS>rad {
-	  /* Radian. */
-	  factor *= 180.0 / PI;
-	  types[WCSUNITS_PLANE_ANGLE] += 1.0;
-	  BEGIN(EXPON);
-	}
-
-<UNITS>Ry {
-	  /* Rydberg. */
-	  factor *= 13.605692 * 1.6021765e-19;
-	  types[WCSUNITS_MASS]   += 1.0;
-	  types[WCSUNITS_LENGTH] += 2.0;
-	  types[WCSUNITS_TIME]   -= 2.0;
-	  BEGIN(EXPON);
-	}
-
-<UNITS>S {
-	  /* Siemen. */
-	  types[WCSUNITS_MASS]   -= 1.0;
-	  types[WCSUNITS_LENGTH] -= 2.0;
-	  types[WCSUNITS_TIME]   += 1.0;
-	  types[WCSUNITS_CHARGE] += 2.0;
-	  BEGIN(EXPON);
-	}
-
-<UNITS>s {
-	  /* Second. */
-	  types[WCSUNITS_TIME] += 1.0;
-	  BEGIN(EXPON);
-	}
-
-<UNITS>solLum {
-	  /* Solar luminosity. */
-	  factor *= 3.8268e26;
-	  types[WCSUNITS_MASS]   += 1.0;
-	  types[WCSUNITS_LENGTH] += 2.0;
-	  types[WCSUNITS_TIME]   -= 3.0;
-	  BEGIN(EXPON);
-	}
-
-<UNITS>solMass {
-	  /* Solar mass. */
-	  factor *= 1.9891e30;
-	  types[WCSUNITS_MASS] += 1.0;
-	  BEGIN(EXPON);
-	}
-
-<UNITS>solRad {
-	  /* Solar radius. */
-	  factor *= 6.9599e8;
-	  types[WCSUNITS_LENGTH] += 1.0;
-	  BEGIN(EXPON);
-	}
-
-<UNITS>sr {
-	  /* Steradian. */
-	  types[WCSUNITS_SOLID_ANGLE] += 1.0;
-	  BEGIN(EXPON);
-	}
-
-<UNITS>Sun {
-	  /* Sun (with respect to). */
-	  types[WCSUNITS_SOLRATIO] += 1.0;
-	  BEGIN(EXPON);
-	}
-
-<UNITS>T {
-	  /* Tesla. */
-	  types[WCSUNITS_MASS]   += 1.0;
-	  types[WCSUNITS_TIME]   += 1.0;
-	  types[WCSUNITS_CHARGE] -= 1.0;
-	  BEGIN(EXPON);
-	}
-
-<UNITS>u {
-	  /* Unified atomic mass unit. */
-	  factor *= 1.6605387e-27;
-	  types[WCSUNITS_MASS] += 1.0;
-	  BEGIN(EXPON);
-	}
-
-<UNITS>V {
-	  /* Volt. */
-	  types[WCSUNITS_MASS]   += 1.0;
-	  types[WCSUNITS_LENGTH] += 1.0;
-	  types[WCSUNITS_TIME]   -= 2.0;
-	  types[WCSUNITS_CHARGE] -= 1.0;
-	  BEGIN(EXPON);
-	}
-
-<UNITS>voxel {
-	  /* Voxel. */
-	  types[WCSUNITS_VOXEL] += 1.0;
-	  BEGIN(EXPON);
-	}
-
-<UNITS>W {
-	  /* Watt. */
-	  types[WCSUNITS_MASS]   += 1.0;
-	  types[WCSUNITS_LENGTH] += 2.0;
-	  types[WCSUNITS_TIME]   -= 3.0;
-	  BEGIN(EXPON);
-	}
-
-<UNITS>Wb {
-	  /* Weber. */
-	  types[WCSUNITS_MASS]   += 1.0;
-	  types[WCSUNITS_LENGTH] += 2.0;
-	  types[WCSUNITS_TIME]   += 1.0;
-	  types[WCSUNITS_CHARGE] -= 1.0;
-	  BEGIN(EXPON);
-	}
-
-<UNITS>. {
-	  /* Internal parser error. */
-	  status = wcserr_set(WCSERR_SET(UNITSERR_PARSER_ERROR),
-	    "Internal units parser error parsing '%s'", unitstr);
-	  BEGIN(FLUSH);
-	}
-
-<EXPON>" "*("**"|^) {
-	  /* Exponentiation. */
-	  if (operator++) {
-	    BEGIN(FLUSH);
-	  }
-	}
-
-<EXPON>" "*{INTEGER} {
-	  sscanf(yytext, " %d", &i);
-	  expon *= (double)i;
-	  add(&factor, types, &expon, scale, units);
-	  operator = 0;
-	  BEGIN(INITIAL);
-	}
-
-<EXPON>" "*"("" "*{INTEGER}" "*")" {
-	  sscanf(yytext, " (%d)", &i);
-	  expon *= (double)i;
-	  add(&factor, types, &expon, scale, units);
-	  operator = 0;
-	  BEGIN(INITIAL);
-	}
-
-<EXPON>" "*"("" "*{FRAC}" "*")" {
-	  sscanf(yytext, " (%d/%d)", &i, &j);
-	  expon *= (double)i / (double)j;
-	  add(&factor, types, &expon, scale, units);
-	  operator = 0;
-	  BEGIN(INITIAL);
-	}
-
-<EXPON>" "*"("" "*{FLOAT}" "*")" {
-	  sscanf(yytext, " (%lf)", &dexp);
-	  expon *= dexp;
-	  add(&factor, types, &expon, scale, units);
-	  operator = 0;
-	  BEGIN(INITIAL);
-	}
-
-<EXPON>" "*[.*]" "* {
-	  /* Multiply. */
-	  if (operator++) {
-	    BEGIN(FLUSH);
-	  } else {
-	    add(&factor, types, &expon, scale, units);
-	    BEGIN(INITIAL);
-	  }
-	}
-
-<EXPON>" "*"(" {
-	  /* Multiply. */
-	  if (operator) {
-	    BEGIN(FLUSH);
-	  } else {
-	    add(&factor, types, &expon, scale, units);
-	    unput('(');
-	    BEGIN(INITIAL);
-	  }
-	}
-
-<EXPON>" "+ {
-	  /* Multiply. */
-	  if (operator) {
-	    BEGIN(FLUSH);
-	  } else {
-	    add(&factor, types, &expon, scale, units);
-	    BEGIN(INITIAL);
-	  }
-	}
-
-<EXPON>" "*"/"" "* {
-	  /* Divide. */
-	  if (operator++) {
-	    BEGIN(FLUSH);
-	  } else {
-	    add(&factor, types, &expon, scale, units);
-	    expon = -1.0;
-	    BEGIN(INITIAL);
-	  }
-	}
-
-<EXPON>" "*"]" {
-	  add(&factor, types, &expon, scale, units);
-	  bracket = !bracket;
-	  BEGIN(FLUSH);
-	}
-
-<EXPON>. {
-	  status = wcserr_set(WCSERR_SET(UNITSERR_BAD_EXPON_SYMBOL),
-	    "Invalid symbol in EXPON context in '%s'", unitstr);
-	  BEGIN(FLUSH);
-	}
-
-<FLUSH>.* {
-	  /* Discard any remaining input. */
-	}
-
-<<EOF>>	{
-	  /* End-of-string. */
-	  if (YY_START == EXPON) {
-	    add(&factor, types, &expon, scale, units);
-	  }
-	
-	  yylex_destroy();
-	
-	  if (bracket) {
-	    status = wcserr_set(WCSERR_SET(UNITSERR_UNBAL_BRACKET),
-	      "Unbalanced bracket in '%s'", unitstr);
-	  } else if (paren) {
-	    status = wcserr_set(WCSERR_SET(UNITSERR_UNBAL_PAREN),
-	      "Unbalanced parenthesis in '%s'", unitstr);
-	  } else if (operator == 1) {
-	    status = wcserr_set(WCSERR_SET(UNITSERR_DANGLING_BINOP),
-	      "Dangling binary operator in '%s'", unitstr);
-	  } else if (operator) {
-	    status = wcserr_set(WCSERR_SET(UNITSERR_CONSEC_BINOPS),
-	      "Consecutive binary operators in '%s'", unitstr);
-	  #ifdef DEBUG
-	  } else {
-	    fprintf(stderr, "EOS\n");
-	  #endif
-	  }
-	
-	  if (status) {
-	    for (i = 0; i < WCSUNITS_NTYPE; i++) {
-	      units[i] = 0.0;
-	      *scale = 0.0;
-	    }
-	  }
-	
-	  return status;
-	}
-
-%%
-
-/*----------------------------------------------------------------------------
-* Accumulate a term in a units specification and reset work variables.
-*---------------------------------------------------------------------------*/
-
-void add(
-  double *factor,
-  double types[],
-  double *expon,
-  double *scale,
-  double units[])
-
-{
-  int i;
-
-  *scale *= pow(*factor, *expon);
-
-  for (i = 0; i < WCSUNITS_NTYPE; i++) {
-    units[i] += *expon * types[i];
-    types[i] = 0.0;
-  }
-
-  *expon  = 1.0;
-  *factor = 1.0;
-
-  return;
-}
diff --git a/astropy/wcs/src/wcslib/C/wcsunits.c b/astropy/wcs/src/wcslib/C/wcsunits.c
deleted file mode 100644
index ee05db2..0000000
--- a/astropy/wcs/src/wcslib/C/wcsunits.c
+++ /dev/null
@@ -1,231 +0,0 @@
-/*============================================================================
-
-  WCSLIB 4.10 - an implementation of the FITS WCS standard.
-  Copyright (C) 1995-2012, Mark Calabretta
-
-  This file is part of WCSLIB.
-
-  WCSLIB is free software: you can redistribute it and/or modify it under the
-  terms of the GNU Lesser General Public License as published by the Free
-  Software Foundation, either version 3 of the License, or (at your option)
-  any later version.
-
-  WCSLIB 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 Lesser General Public License for
-  more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with WCSLIB.  If not, see <http://www.gnu.org/licenses/>.
-
-  Correspondence concerning WCSLIB may be directed to:
-    Internet email: mcalabre at atnf.csiro.au
-    Postal address: Dr. Mark Calabretta
-                    Australia Telescope National Facility, CSIRO
-                    PO Box 76
-                    Epping NSW 1710
-                    AUSTRALIA
-
-  Author: Mark Calabretta, Australia Telescope National Facility
-  http://www.atnf.csiro.au/~mcalabre/index.html
-  $Id: wcsunits.c,v 4.10 2012/02/05 23:41:44 cal103 Exp $
-*===========================================================================*/
-
-#include <math.h>
-
-#include "wcsunits.h"
-
-/* Map status return value to message. */
-const char *wcsunits_errmsg[] = {
-  "Success",
-  "Invalid numeric multiplier",
-  "Dangling binary operator",
-  "Invalid symbol in INITIAL context",
-  "Function in invalid context",
-  "Invalid symbol in EXPON context",
-  "Unbalanced bracket",
-  "Unbalanced parenthesis",
-  "Consecutive binary operators",
-  "Internal parser error",
-  "Non-conformant unit specifications",
-  "Non-conformant functions",
-  "Potentially unsafe translation"};
-
-
-/* Unit types. */
-const char *wcsunits_types[] = {
-  "plane angle",
-  "solid angle",
-  "charge",
-  "mole",
-  "temperature",
-  "luminous intensity",
-  "mass",
-  "length",
-  "time",
-  "beam",
-  "bin",
-  "bit",
-  "count",
-  "stellar magnitude",
-  "pixel",
-  "solar ratio",
-  "voxel"};
-
-const char *wcsunits_units[] = {
-  "degree",
-  "steradian",
-  "Coulomb",
-  "mole",
-  "Kelvin",
-  "candela",
-  "kilogram",
-  "metre",
-  "second",
-  "", "", "", "", "", "", "", ""};
-
-const char *wcsunits_funcs[] = {
-  "none",
-  "log",
-  "ln",
-  "exp"};
-
-/*--------------------------------------------------------------------------*/
-
-int wcsunits(
-  const char have[],
-  const char want[],
-  double *scale,
-  double *offset,
-  double *power)
-
-{
-  return wcsunitse(
-    have, want, scale, offset, power, 0x0);
-}
-
-/* : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :  */
-
-int wcsunitse(
-  const char have[],
-  const char want[],
-  double *scale,
-  double *offset,
-  double *power,
-  struct wcserr **err)
-
-{
-  static const char *function = "wcsunitse";
-
-  int    func1, func2, i, status;
-  double scale1, scale2, units1[WCSUNITS_NTYPE], units2[WCSUNITS_NTYPE];
-
-  if ((status = wcsulexe(have, &func1, &scale1, units1, err))) {
-    return status;
-  }
-
-  if ((status = wcsulexe(want, &func2, &scale2, units2, err))) {
-    return status;
-  }
-
-  /* Check conformance. */
-  for (i = 0; i < WCSUNITS_NTYPE; i++) {
-    if (units1[i] != units2[i]) {
-      return wcserr_set(WCSERR_SET(UNITSERR_BAD_UNIT_SPEC),
-        "Mismatched units type '%s': have '%s', want '%s'",
-        wcsunits_types[i], have, want);
-    }
-  }
-
-  *scale  = 0.0;
-  *offset = 0.0;
-  *power  = 1.0;
-
-  switch (func1) {
-  case 0:
-    /* No function. */
-    if (func2) {
-      return wcserr_set(WCSERR_SET(UNITSERR_BAD_FUNCS),
-        "Mismatched unit functions: have '%s' (%s), want '%s' (%s)",
-        have, wcsunits_funcs[func1], want, wcsunits_funcs[func2]);
-    }
-
-    *scale = scale1 / scale2;
-    break;
-
-  case 1:
-    /* log(). */
-    if (func2 == 1) {
-      /* log(). */
-      *scale  = 1.0;
-      *offset = log10(scale1 / scale2);
-
-    } else if (func2 == 2) {
-      /* ln(). */
-      *scale  = log(10.0);
-      *offset = log(scale1 / scale2);
-
-    } else {
-      return wcserr_set(WCSERR_SET(UNITSERR_BAD_FUNCS),
-        "Mismatched unit functions: have '%s' (%s), want '%s' (%s)",
-        have, wcsunits_funcs[func1], want, wcsunits_funcs[func2]);
-    }
-
-    break;
-
-  case 2:
-    /* ln(). */
-    if (func2 == 1) {
-      /* log(). */
-      *scale  = 1.0 / log(10.0);
-      *offset = log(scale1 / scale2);
-
-    } else if (func2 == 2) {
-      /* ln(). */
-      *scale  = 1.0;
-      *offset = log(scale1 / scale2);
-
-    } else {
-      return wcserr_set(WCSERR_SET(UNITSERR_BAD_FUNCS),
-        "Mismatched unit functions: have '%s' (%s), want '%s' (%s)",
-        have, wcsunits_funcs[func1], want, wcsunits_funcs[func2]);
-    }
-
-    break;
-
-  case 3:
-    /* exp(). */
-    if (func2 != 3) {
-      return wcserr_set(WCSERR_SET(UNITSERR_BAD_FUNCS),
-        "Mismatched unit functions: have '%s' (%s), want '%s' (%s)",
-        have, wcsunits_funcs[func1], want, wcsunits_funcs[func2]);
-    }
-
-    *scale = 1.0;
-    *power = scale1 / scale2;
-    break;
-
-  default:
-    /* Internal parser error. */
-    return wcserr_set(WCSERR_SET(UNITSERR_PARSER_ERROR),
-      "Internal units parser error");
-  }
-
-  return 0;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int wcsutrn(int ctrl, char unitstr[])
-
-{
-  return wcsutrne(ctrl, unitstr, 0x0);
-}
-
-/*--------------------------------------------------------------------------*/
-
-int wcsulex(const char unitstr[], int *func, double *scale, double units[])
-
-{
-  return wcsulexe(unitstr, func, scale, units, 0x0);
-}
diff --git a/astropy/wcs/src/wcslib/C/wcsunits.h b/astropy/wcs/src/wcslib/C/wcsunits.h
deleted file mode 100644
index e15e7e5..0000000
--- a/astropy/wcs/src/wcslib/C/wcsunits.h
+++ /dev/null
@@ -1,412 +0,0 @@
-/*============================================================================
-
-  WCSLIB 4.10 - an implementation of the FITS WCS standard.
-  Copyright (C) 1995-2012, Mark Calabretta
-
-  This file is part of WCSLIB.
-
-  WCSLIB is free software: you can redistribute it and/or modify it under the
-  terms of the GNU Lesser General Public License as published by the Free
-  Software Foundation, either version 3 of the License, or (at your option)
-  any later version.
-
-  WCSLIB 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 Lesser General Public License for
-  more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with WCSLIB.  If not, see <http://www.gnu.org/licenses/>.
-
-  Correspondence concerning WCSLIB may be directed to:
-    Internet email: mcalabre at atnf.csiro.au
-    Postal address: Dr. Mark Calabretta
-                    Australia Telescope National Facility, CSIRO
-                    PO Box 76
-                    Epping NSW 1710
-                    AUSTRALIA
-
-  Author: Mark Calabretta, Australia Telescope National Facility
-  http://www.atnf.csiro.au/~mcalabre/index.html
-  $Id: wcsunits.h,v 4.10 2012/02/05 23:41:44 cal103 Exp $
-*=============================================================================
-*
-* WCSLIB 4.10 - C routines that implement the FITS World Coordinate System
-* (WCS) standard.  Refer to
-*
-*   "Representations of world coordinates in FITS",
-*   Greisen, E.W., & Calabretta, M.R. 2002, A&A, 395, 1061 (Paper I)
-*
-* The Flexible Image Transport System (FITS), a data format widely used in
-* astronomy for data interchange and archive, is described in
-*
-*   "Definition of The Flexible Image Transport System (FITS)",
-*   Hanisch, R.J., Farris, A., Greisen, E.W., et al. 2001, A&A, 376, 359
-*
-* which formalizes NOST 100-2.0, a document produced by the NASA/Science
-* Office of Standards and Technology, see http://fits.gsfc.nasa.gov.
-*
-* Refer to the README file provided with WCSLIB for an overview of the
-* library.
-*
-*
-* Summary of the wcsunits routines
-* --------------------------------
-* Routines in this suite deal with units specifications and conversions:
-*
-*   - wcsunitse(): given two unit specifications, derive the conversion from
-*     one to the other.
-*
-*   - wcsutrne(): translates certain commonly used but non-standard unit
-*     strings.  It is intended to be called before wcsulexe() which only
-*     handles standard FITS units specifications.
-*
-*   - wcsulexe(): parses a standard FITS units specification of arbitrary
-*     complexity, deriving the conversion to canonical units.
-*
-*
-* wcsunitse() - FITS units specification conversion
-* -------------------------------------------------
-* wcsunitse() derives the conversion from one system of units to another.
-*
-* A deprecated form of this function, wcsunits(), lacks the wcserr**
-* parameter.
-*
-* Given:
-*   have      const char []
-*                       FITS units specification to convert from (null-
-*                       terminated), with or without surrounding square
-*                       brackets (for inline specifications); text following
-*                       the closing bracket is ignored.
-*
-*   want      const char []
-*                       FITS units specification to convert to (null-
-*                       terminated), with or without surrounding square
-*                       brackets (for inline specifications); text following
-*                       the closing bracket is ignored.
-*
-* Returned:
-*   scale,
-*   offset,
-*   power     double*   Convert units using
-*
-=                         pow(scale*value + offset, power);
-*
-*                       Normally offset is zero except for log() or ln()
-*                       conversions, e.g. "log(MHz)" to "ln(Hz)".  Likewise,
-*                       power is normally unity except for exp() conversions,
-*                       e.g. "exp(ms)" to "exp(/Hz)".  Thus conversions
-*                       ordinarily consist of
-*
-=                         value *= scale;
-*
-*   err       struct wcserr **
-*                       If enabled, for function return values > 1, this
-*                       struct will contain a detailed error message, see
-*                       wcserr_enable().  May be NULL if an error message is
-*                       not desired.
-*
-* Function return value:
-*             int       Status return value:
-*                          0: Success.
-*                        1-9: Status return from wcsulexe().
-*                         10: Non-conformant unit specifications.
-*                         11: Non-conformant functions.
-*
-*                       scale is zeroed on return if an error occurs.
-*
-*
-* wcsutrne() - Translation of non-standard unit specifications
-* ------------------------------------------------------------
-* wcsutrne() translates certain commonly used but non-standard unit strings,
-* e.g. "DEG", "MHZ", "KELVIN", that are not recognized by wcsulexe(), refer to
-* the notes below for a full list.  Compounds are also recognized, e.g.
-* "JY/BEAM" and "KM/SEC/SEC".  Extraneous embedded blanks are removed.
-*
-* A deprecated form of this function, wcsutrn(), lacks the wcserr** parameter.
-*
-* Given:
-*   ctrl      int       Although "S" is commonly used to represent seconds,
-*                       its translation to "s" is potentially unsafe since the
-*                       standard recognizes "S" formally as Siemens, however
-*                       rarely that may be used.  The same applies to "H" for
-*                       hours (Henry), and "D" for days (Debye).  This
-*                       bit-flag controls what to do in such cases:
-*                         1: Translate "S" to "s".
-*                         2: Translate "H" to "h".
-*                         4: Translate "D" to "d".
-*                       Thus ctrl == 0 doesn't do any unsafe translations,
-*                       whereas ctrl == 7 does all of them.
-*
-* Given and returned:
-*   unitstr   char []   Null-terminated character array containing the units
-*                       specification to be translated.
-*
-*                       Inline units specifications in the a FITS header
-*                       keycomment are also handled.  If the first non-blank
-*                       character in unitstr is '[' then the unit string is
-*                       delimited by its matching ']'.  Blanks preceding '['
-*                       will be stripped off, but text following the closing
-*                       bracket will be preserved without modification.
-*
-*   err       struct wcserr **
-*                       If enabled, for function return values > 1, this
-*                       struct will contain a detailed error message, see
-*                       wcserr_enable().  May be NULL if an error message is
-*                       not desired.
-*
-* Function return value:
-*             int       Status return value:
-*                        -1: No change was made, other than stripping blanks
-*                            (not an error).
-*                         0: Success.
-*                         9: Internal parser error.
-*                        12: Potentially unsafe translation, whether applied
-*                             or not (see notes).
-*
-* Notes:
-*   Translation of non-standard unit specifications: apart from leading and
-*   trailing blanks, a case-sensitive match is required for the aliases listed
-*   below, in particular the only recognized aliases with metric prefixes are
-*   "KM", "KHZ", "MHZ", and "GHZ".  Potentially unsafe translations of "D",
-*   "H", and "S", shown in parentheses, are optional.
-*
-=     Unit       Recognized aliases
-=     ----       -------------------------------------------------------------
-=     Angstrom   angstrom
-=     arcmin     arcmins, ARCMIN, ARCMINS
-=     arcsec     arcsecs, ARCSEC, ARCSECS
-=     beam       BEAM
-=     byte       Byte
-=     d          day, days, (D), DAY, DAYS
-=     deg        degree, degrees, DEG, DEGREE, DEGREES
-=     GHz        GHZ
-=     h          hr, (H), HR
-=     Hz         hz, HZ
-=     kHz        KHZ
-=     Jy         JY
-=     K          kelvin, kelvins, Kelvin, Kelvins, KELVIN, KELVINS
-=     km         KM
-=     m          metre, meter, metres, meters, M, METRE, METER, METRES, METERS
-=     min        MIN
-=     MHz        MHZ
-=     Ohm        ohm
-=     Pa         pascal, pascals, Pascal, Pascals, PASCAL, PASCALS
-=     pixel      pixels, PIXEL, PIXELS
-=     rad        radian, radians, RAD, RADIAN, RADIANS
-=     s          sec, second, seconds, (S), SEC, SECOND, SECONDS
-=     V          volt, volts, Volt, Volts, VOLT, VOLTS
-=     yr         year, years, YR, YEAR, YEARS
-*
-*   The aliases "angstrom", "ohm", and "Byte" for (Angstrom, Ohm, and byte)
-*   are recognized by wcsulexe() itself as an unofficial extension of the
-*   standard, but they are converted to the standard form here.
-*
-*
-* wcsulexe() - FITS units specification parser
-* --------------------------------------------
-* wcsulexe() parses a standard FITS units specification of arbitrary
-* complexity, deriving the scale factor required to convert to canonical
-* units - basically SI with degrees and "dimensionless" additions such as
-* byte, pixel and count.
-*
-* A deprecated form of this function, wcsulex(), lacks the wcserr** parameter.
-*
-* Given:
-*   unitstr   const char []
-*                       Null-terminated character array containing the units
-*                       specification, with or without surrounding square
-*                       brackets (for inline specifications); text following
-*                       the closing bracket is ignored.
-*
-* Returned:
-*   func      int*      Special function type, see note 4:
-*                         0: None
-*                         1: log()  ...base 10
-*                         2: ln()   ...base e
-*                         3: exp()
-*
-*   scale     double*   Scale factor for the unit specification; multiply a
-*                       value expressed in the given units by this factor to
-*                       convert it to canonical units.
-*
-*   units     double[WCSUNITS_NTYPE]
-*                       A units specification is decomposed into powers of 16
-*                       fundamental unit types: angle, mass, length, time,
-*                       count, pixel, etc.  Preprocessor macro WCSUNITS_NTYPE
-*                       is defined to dimension this vector, and others such
-*                       WCSUNITS_PLANE_ANGLE, WCSUNITS_LENGTH, etc. to access
-*                       its elements.
-*
-*                       Corresponding character strings, wcsunits_types[] and
-*                       wcsunits_units[], are predefined to describe each
-*                       quantity and its canonical units.
-*
-*   err       struct wcserr **
-*                       If enabled, for function return values > 1, this
-*                       struct will contain a detailed error message, see
-*                       wcserr_enable().  May be NULL if an error message is
-*                       not desired.
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Success.
-*                         1: Invalid numeric multiplier.
-*                         2: Dangling binary operator.
-*                         3: Invalid symbol in INITIAL context.
-*                         4: Function in invalid context.
-*                         5: Invalid symbol in EXPON context.
-*                         6: Unbalanced bracket.
-*                         7: Unbalanced parenthesis.
-*                         8: Consecutive binary operators.
-*                         9: Internal parser error.
-*
-*                       scale and units[] are zeroed on return if an error
-*                       occurs.
-*
-* Notes:
-*   1: wcsulexe() is permissive in accepting whitespace in all contexts in a
-*      units specification where it does not create ambiguity (e.g. not
-*      between a metric prefix and a basic unit string), including in strings
-*      like "log (m ** 2)" which is formally disallowed.
-*
-*   2: Supported extensions:
-*      - "angstrom" (OGIP usage) is allowed in addition to "Angstrom".
-*      - "ohm"      (OGIP usage) is allowed in addition to "Ohm".
-*      - "Byte"   (common usage) is allowed in addition to "byte".
-*
-*   3: Table 6 of WCS Paper I lists eleven units for which metric prefixes are
-*      allowed.  However, in this implementation only prefixes greater than
-*      unity are allowed for "a" (annum), "yr" (year), "pc" (parsec), "bit",
-*      and "byte", and only prefixes less than unity are allowed for "mag"
-*      (stellar magnitude).
-*
-*      Metric prefix "P" (peta) is specifically forbidden for "a" (annum) to
-*      avoid confusion with "Pa" (Pascal, not peta-annum).  Note that metric
-*      prefixes are specifically disallowed for "h" (hour) and "d" (day) so
-*      that "ph" (photons) cannot be interpreted as pico-hours, nor "cd"
-*      (candela) as centi-days.
-*
-*   4: Function types log(), ln() and exp() may only occur at the start of the
-*      units specification.  The scale and units[] returned for these refers
-*      to the string inside the function "argument", e.g. to "MHz" in log(MHz)
-*      for which a scale of 1e6 will be returned.
-*
-*
-* Global variable: const char *wcsunits_errmsg[] - Status return messages
-* -----------------------------------------------------------------------
-* Error messages to match the status value returned from each function.
-*
-*
-* Global variable: const char *wcsunits_types[] - Names of physical quantities
-* ----------------------------------------------------------------------------
-* Names for physical quantities to match the units vector returned by
-* wcsulexe():
-*   -  0: plane angle
-*   -  1: solid angle
-*   -  2: charge
-*   -  3: mole
-*   -  4: temperature
-*   -  5: luminous intensity
-*   -  6: mass
-*   -  7: length
-*   -  8: time
-*   -  9: beam
-*   - 10: bin
-*   - 11: bit
-*   - 12: count
-*   - 13: stellar magnitude
-*   - 14: pixel
-*   - 15: solar ratio
-*   - 16: voxel
-*
-*
-* Global variable: const char *wcsunits_units[] - Names of units
-* --------------------------------------------------------------
-* Names for the units (SI) to match the units vector returned by wcsulexe():
-*   -  0: degree
-*   -  1: steradian
-*   -  2: Coulomb
-*   -  3: mole
-*   -  4: Kelvin
-*   -  5: candela
-*   -  6: kilogram
-*   -  7: metre
-*   -  8: second
-*
-* The remainder are dimensionless.
-*===========================================================================*/
-
-#ifndef WCSLIB_WCSUNITS
-#define WCSLIB_WCSUNITS
-
-#include "wcserr.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-extern const char *wcsunits_errmsg[];
-
-enum wcsunits_errmsg_enum {
-  UNITSERR_SUCCESS            =  0,	/* Success. */
-  UNITSERR_BAD_NUM_MULTIPLIER =  1,	/* Invalid numeric multiplier. */
-  UNITSERR_DANGLING_BINOP     =  2,	/* Dangling binary operator. */
-  UNITSERR_BAD_INITIAL_SYMBOL =  3,	/* Invalid symbol in INITIAL
-					   context. */
-  UNITSERR_FUNCTION_CONTEXT   =  4,	/* Function in invalid context. */
-  UNITSERR_BAD_EXPON_SYMBOL   =  5,	/* Invalid symbol in EXPON context. */
-  UNITSERR_UNBAL_BRACKET      =  6,	/* Unbalanced bracket. */
-  UNITSERR_UNBAL_PAREN        =  7,	/* Unbalanced parenthesis. */
-  UNITSERR_CONSEC_BINOPS      =  8,	/* Consecutive binary operators. */
-  UNITSERR_PARSER_ERROR       =  9,	/* Internal parser error. */
-  UNITSERR_BAD_UNIT_SPEC      = 10,	/* Non-conformant unit
-					   specifications. */
-  UNITSERR_BAD_FUNCS          = 11,	/* Non-conformant functions. */
-  UNITSERR_UNSAFE_TRANS       = 12	/* Potentially unsafe translation. */
-};
-
-extern const char *wcsunits_types[];
-extern const char *wcsunits_units[];
-
-#define WCSUNITS_PLANE_ANGLE 0
-#define WCSUNITS_SOLID_ANGLE 1
-#define WCSUNITS_CHARGE      2
-#define WCSUNITS_MOLE        3
-#define WCSUNITS_TEMPERATURE 4
-#define WCSUNITS_LUMINTEN    5
-#define WCSUNITS_MASS        6
-#define WCSUNITS_LENGTH      7
-#define WCSUNITS_TIME        8
-#define WCSUNITS_BEAM        9
-#define WCSUNITS_BIN        10
-#define WCSUNITS_BIT        11
-#define WCSUNITS_COUNT      12
-#define WCSUNITS_MAGNITUDE  13
-#define WCSUNITS_PIXEL      14
-#define WCSUNITS_SOLRATIO   15
-#define WCSUNITS_VOXEL      16
-
-#define WCSUNITS_NTYPE      17
-
-
-int wcsunitse(const char have[], const char want[], double *scale,
-              double *offset, double *power, struct wcserr **err);
-
-int wcsutrne(int ctrl, char unitstr[], struct wcserr **err);
-
-int wcsulexe(const char unitstr[], int *func, double *scale, double units[],
-             struct wcserr **err);
-
-/* Deprecated. */
-int wcsunits(const char have[], const char want[], double *scale,
-             double *offset, double *power);
-int wcsutrn(int ctrl, char unitstr[]);
-int wcsulex(const char unitstr[], int *func, double *scale, double units[]);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* WCSLIB_WCSUNITS */
diff --git a/astropy/wcs/src/wcslib/C/wcsutil.c b/astropy/wcs/src/wcslib/C/wcsutil.c
deleted file mode 100644
index 5db41fe..0000000
--- a/astropy/wcs/src/wcslib/C/wcsutil.c
+++ /dev/null
@@ -1,186 +0,0 @@
-/*============================================================================
-
-  WCSLIB 4.10 - an implementation of the FITS WCS standard.
-  Copyright (C) 1995-2012, Mark Calabretta
-
-  This file is part of WCSLIB.
-
-  WCSLIB is free software: you can redistribute it and/or modify it under the
-  terms of the GNU Lesser General Public License as published by the Free
-  Software Foundation, either version 3 of the License, or (at your option)
-  any later version.
-
-  WCSLIB 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 Lesser General Public License for
-  more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with WCSLIB.  If not, see <http://www.gnu.org/licenses/>.
-
-  Correspondence concerning WCSLIB may be directed to:
-    Internet email: mcalabre at atnf.csiro.au
-    Postal address: Dr. Mark Calabretta
-                    Australia Telescope National Facility, CSIRO
-                    PO Box 76
-                    Epping NSW 1710
-                    AUSTRALIA
-
-  Author: Mark Calabretta, Australia Telescope National Facility
-  http://www.atnf.csiro.au/~mcalabre/index.html
-  $Id: wcsutil.c,v 4.10 2012/02/05 23:41:44 cal103 Exp $
-*===========================================================================*/
-
-#include <stdio.h>
-#include <string.h>
-
-#include "wcsutil.h"
-
-/*--------------------------------------------------------------------------*/
-
-void wcsutil_blank_fill(int n, char c[])
-
-{
-  int k;
-
-  for (k = strlen(c); k < n; k++) {
-    c[k] = ' ';
-  }
-
-  return;
-}
-
-/*--------------------------------------------------------------------------*/
-
-void wcsutil_null_fill(int n, char c[])
-
-{
-  int j, k;
-
-  if (n <= 0) return;
-
-  /* Null-fill the string. */
-  *(c+n-1) = '\0';
-  for (j = 0; j < n; j++) {
-    if (c[j] == '\0') {
-      for (k = j+1; k < n; k++) {
-        c[k] = '\0';
-      }
-      break;
-    }
-  }
-
-  for (k = j-1; k > 0; k--) {
-    if (c[k] != ' ') break;
-    c[k] = '\0';
-  }
-
-   return;
-}
-
-/*--------------------------------------------------------------------------*/
-
-int wcsutil_allEq(int nvec, int nelem, const double *first)
-
-{
-  double v0;
-  const double *vp;
-
-  if (nvec <= 0 || nelem <= 0) return 0;
-
-  v0 = *first;
-  for (vp = first+nelem; vp < first + nvec*nelem; vp += nelem) {
-    if (*vp != v0) return 0;
-  }
-
-  return 1;
-}
-
-/*--------------------------------------------------------------------------*/
-
-void wcsutil_setAll(int nvec, int nelem, double *first)
-
-{
-  double v0, *vp;
-
-  if (nvec <= 0 || nelem <= 0) return;
-
-  v0 = *first;
-  for (vp = first+nelem; vp < first + nvec*nelem; vp += nelem) {
-    *vp = v0;
-  }
-}
-
-/*--------------------------------------------------------------------------*/
-
-void wcsutil_setAli(int nvec, int nelem, int *first)
-
-{
-  int v0, *vp;
-
-  if (nvec <= 0 || nelem <= 0) return;
-
-  v0 = *first;
-  for (vp = first+nelem; vp < first + nvec*nelem; vp += nelem) {
-    *vp = v0;
-  }
-}
-
-/*--------------------------------------------------------------------------*/
-
-void wcsutil_setBit(int nelem, const int *sel, int bits, int *array)
-
-{
-  int *arrp;
-
-  if (bits == 0 || nelem <= 0) return;
-
-  if (sel == 0x0) {
-    /* All elements selected. */
-    for (arrp = array; arrp < array + nelem; arrp++) {
-      *arrp |= bits;
-    }
-
-  } else {
-    /* Some elements selected. */
-    for (arrp = array; arrp < array + nelem; arrp++) {
-      if (*(sel++)) *arrp |= bits;
-    }
-  }
-}
-
-/*--------------------------------------------------------------------------*/
-
-char *wcsutil_fptr2str(int (*func)(void), char hext[])
-
-{
-  unsigned char *p = (unsigned char *)(&func);
-  char *t = hext;
-  int i, *(ip[2]), j[2], le = 1, gotone = 0;
-
-  /* Test for little-endian addresses. */
-  ip[0] = j;
-  ip[1] = j + 1;
-  if ((unsigned char *)ip[0] < (unsigned char *)ip[1]) {
-    /* Little-endian, reverse it. */
-    p += sizeof(func) - 1;
-    le = -1;
-  }
-
-  sprintf(t, "0x0");
-  t += 2;
-
-  for (i = 0; i < sizeof(func); i++) {
-    /* Skip leading zeroes. */
-    if (*p) gotone = 1;
-
-    if (gotone) {
-      sprintf(t, "%02x", *p);
-      t += 2;
-    }
-
-    p += le;
-  }
-
-  return hext;
-}
diff --git a/astropy/wcs/src/wcslib/C/wcsutil.h b/astropy/wcs/src/wcslib/C/wcsutil.h
deleted file mode 100644
index 072f5e7..0000000
--- a/astropy/wcs/src/wcslib/C/wcsutil.h
+++ /dev/null
@@ -1,229 +0,0 @@
-/*============================================================================
-
-  WCSLIB 4.10 - an implementation of the FITS WCS standard.
-  Copyright (C) 1995-2012, Mark Calabretta
-
-  This file is part of WCSLIB.
-
-  WCSLIB is free software: you can redistribute it and/or modify it under the
-  terms of the GNU Lesser General Public License as published by the Free
-  Software Foundation, either version 3 of the License, or (at your option)
-  any later version.
-
-  WCSLIB 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 Lesser General Public License for
-  more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with WCSLIB.  If not, see <http://www.gnu.org/licenses/>.
-
-  Correspondence concerning WCSLIB may be directed to:
-    Internet email: mcalabre at atnf.csiro.au
-    Postal address: Dr. Mark Calabretta
-                    Australia Telescope National Facility, CSIRO
-                    PO Box 76
-                    Epping NSW 1710
-                    AUSTRALIA
-
-  Author: Mark Calabretta, Australia Telescope National Facility
-  http://www.atnf.csiro.au/~mcalabre/index.html
-  $Id: wcsutil.h,v 4.10 2012/02/05 23:41:44 cal103 Exp $
-*=============================================================================
-*
-* Summary of the wcsutil routines
-* -------------------------------
-* Simple utility functions for internal use only by WCSLIB.  They are
-* documented here solely as an aid to understanding the code.  They are not
-* intended for external use - the API may change without notice!
-*
-*
-* wcsutil_blank_fill() - Fill a character string with blanks
-* ----------------------------------------------------------
-* INTERNAL USE ONLY.
-*
-* wcsutil_blank_fill() pads a character string with blanks starting with the
-* terminating NULL character.
-*
-* Used by the Fortran wrapper functions in translating C character strings
-* into Fortran CHARACTER variables.
-*
-* Given:
-*   n         int       Length of the character array, c[].
-*
-* Given and returned:
-*   c         char[]    The character string.  It will not be null-terminated
-*                       on return.
-*
-* Function return value:
-*             void
-*
-*
-* wcsutil_null_fill() - Fill a character string with NULLs
-* --------------------------------------------------------
-* INTERNAL USE ONLY.
-*
-* wcsutil_null_fill() strips off trailing blanks and pads the character array
-* holding the string with NULL characters.
-*
-* Used mainly to make character strings intelligible in the GNU debugger which
-* prints the rubbish following the terminating NULL, obscuring the valid part
-* of the string.
-*
-* Given:
-*   n         int       Number of characters.
-*
-* Given and returned:
-*   c         char[]    The character string.
-*
-* Function return value:
-*             void
-*
-*
-* wcsutil_allEq() - Test for equality of a particular vector element
-* ------------------------------------------------------------------
-* INTERNAL USE ONLY.
-*
-* wcsutil_allEq() tests for equality of a particular element in a set of
-* vectors.
-*
-* Given:
-*   nvec      int       The number of vectors.
-*
-*   nelem     int       The length of each vector.
-*
-*   first     const double*
-*                       Pointer to the first element to test in the array.
-*                       The elements tested for equality are
-*
-=                         *first == *(first + nelem)
-=                                == *(first + nelem*2)
-=                                           :
-=                                == *(first + nelem*(nvec-1));
-*
-*                       The array might be dimensioned as
-*
-=                         double v[nvec][nelem];
-*
-* Function return value:
-*             int       Status return value:
-*                         0: Not all equal.
-*                         1: All equal.
-*
-*
-* wcsutil_setAll() - Set a particular vector element
-* --------------------------------------------------
-* INTERNAL USE ONLY.
-*
-* wcsutil_setAll() sets the value of a particular element in a set of vectors.
-*
-* Given:
-*   nvec      int       The number of vectors.
-*
-*   nelem     int       The length of each vector.
-*
-* Given and returned:
-*   first     double*   Pointer to the first element in the array, the value
-*                       of which is used to set the others
-*
-=                         *(first + nelem) = *first;
-=                         *(first + nelem*2) = *first;
-=                                 :
-=                         *(first + nelem*(nvec-1)) = *first;
-*
-*                       The array might be dimensioned as
-*
-=                         double v[nvec][nelem];
-*
-* Function return value:
-*             void
-*
-*
-* wcsutil_setAli() - Set a particular vector element
-* --------------------------------------------------
-* INTERNAL USE ONLY.
-*
-* wcsutil_setAli() sets the value of a particular element in a set of vectors.
-*
-* Given:
-*   nvec      int       The number of vectors.
-*
-*   nelem     int       The length of each vector.
-*
-* Given and returned:
-*   first     int*      Pointer to the first element in the array, the value
-*                       of which is used to set the others
-*
-=                         *(first + nelem) = *first;
-=                         *(first + nelem*2) = *first;
-=                                 :
-=                         *(first + nelem*(nvec-1)) = *first;
-*
-*                       The array might be dimensioned as
-*
-=                         int v[nvec][nelem];
-*
-* Function return value:
-*             void
-*
-*
-* wcsutil_setBit() - Set bits in selected elements of an array
-* ------------------------------------------------------------
-* INTERNAL USE ONLY.
-*
-* wcsutil_setBit() sets bits in selected elements of an array.
-*
-* Given:
-*   nelem     int       Number of elements in the array.
-*
-*   sel       const int*
-*                       Address of a selection array of length nelem.  May
-*                       be specified as the null pointer in which case all
-*                       elements are selected.
-*
-*   bits      int       Bit mask.
-*
-* Given and returned:
-*   array     int*      Address of the array of length nelem.
-*
-* Function return value:
-*             void
-*
-*
-* wcsutil_fptr2str() - Translate pointer-to-function to string
-* ------------------------------------------------------------
-* INTERNAL USE ONLY.
-*
-* wcsutil_fptr2str() translates a pointer-to-function to hexadecimal string
-* representation for output.  It is used by the various routines that print
-* the contents of WCSLIB structs.  Note that it is not strictly legal to
-* type-pun a function pointer to void*.
-*
-* See stackoverflow.com/questions/2741683/how-to-format-a-function-pointer
-*
-* Given:
-*   fptr      int (*)() Pointer to function.
-*
-* Returned:
-*   hext      char[]    Null-terminated string.  Should be at least 19 bytes
-*                       in size to accomodate a 64-bit address (16 bytes in
-*                       hex), plus the leading "0x" and trailing '\0'.
-*
-* Function return value:
-*             char *    The address of hext.
-*
-*===========================================================================*/
-
-#ifndef WCSLIB_WCSUTIL
-#define WCSLIB_WCSUTIL
-
-void wcsutil_blank_fill(int n, char c[]);
-void wcsutil_null_fill (int n, char c[]);
-
-int  wcsutil_allEq (int nvec, int nelem, const double *first);
-void wcsutil_setAll(int nvec, int nelem, double *first);
-void wcsutil_setAli(int nvec, int nelem, int *first);
-void wcsutil_setBit(int nelem, const int *sel, int bits, int *array);
-char *wcsutil_fptr2str(int (*func)(void), char hext[]);
-
-#endif /* WCSLIB_WCSUTIL */
diff --git a/astropy/wcs/src/wcslib/C/wcsutrn.l b/astropy/wcs/src/wcslib/C/wcsutrn.l
deleted file mode 100644
index 22b6bd7..0000000
--- a/astropy/wcs/src/wcslib/C/wcsutrn.l
+++ /dev/null
@@ -1,341 +0,0 @@
-/*============================================================================
-
-  WCSLIB 4.10 - an implementation of the FITS WCS standard.
-  Copyright (C) 1995-2012, Mark Calabretta
-
-  This file is part of WCSLIB.
-
-  WCSLIB is free software: you can redistribute it and/or modify it under the
-  terms of the GNU Lesser General Public License as published by the Free
-  Software Foundation, either version 3 of the License, or (at your option)
-  any later version.
-
-  WCSLIB 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 Lesser General Public License for
-  more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with WCSLIB.  If not, see <http://www.gnu.org/licenses/>.
-
-  Correspondence concerning WCSLIB may be directed to:
-    Internet email: mcalabre at atnf.csiro.au
-    Postal address: Dr. Mark Calabretta
-                    Australia Telescope National Facility, CSIRO
-                    PO Box 76
-                    Epping NSW 1710
-                    AUSTRALIA
-
-  Author: Mark Calabretta, Australia Telescope National Facility
-  http://www.atnf.csiro.au/~mcalabre/index.html
-  $Id: wcsutrn.l,v 4.10 2012/02/05 23:41:44 cal103 Exp $
-*=============================================================================
-*
-* wcsutrn.l is a Flex description file containing the definition of a lexical
-* scanner that translates non-standard FITS units specifications.
-*
-* It requires Flex v2.5.4 or later.
-*
-* Refer to wcsunits.h for a description of the user interface and operating
-* notes.
-*
-*===========================================================================*/
-
-/* Options. */
-%option full
-%option never-interactive
-%option noyywrap
-%option outfile="wcsutrn.c"
-%option prefix="wcsutrn"
-
-/* Exclusive start states. */
-%x NEXT FLUSH
-
-%{
-/* To get the prototype for fileno() from stdio.h when gcc is invoked with
- * -std=c89 (same as -ansi) or -std=c99 since we do not define YY_INPUT. */
-#define _POSIX_SOURCE 1
-
-#include <setjmp.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "wcserr.h"
-#include "wcsunits.h"
-
-#define YY_DECL int wcsutrne(int ctrl, char unitstr[], struct wcserr **err)
-
-/* Used in preempting the call to exit() by yy_fatal_error(). */
-jmp_buf wcsutrn_abort_jmp_env;
-#define exit(status) longjmp(wcsutrn_abort_jmp_env, status)
-
-%}
-
-%%
-	static const char *function = "wcsutrne";
-
-	char orig[80], subs[80];
-	int bracket = 0;
-	int unsafe  = 0;
-	int status  = -1;
-	YY_BUFFER_STATE inbuff;
-	int yylex_destroy(void);
-	
-	*orig = '\0';
-	*subs = '\0';
-	
-	inbuff = yy_scan_string(unitstr);
-	*unitstr = '\0';
-	
-	/* Return here via longjmp() invoked by yy_fatal_error(). */
-	if (setjmp(wcsutrn_abort_jmp_env)) {
-	  return wcserr_set(WCSERR_SET(UNITSERR_PARSER_ERROR),
-	    "Internal units translator error parsing '%s'", unitstr);
-	}
-	
-	BEGIN(INITIAL);
-	
-	#ifdef DEBUG
-	fprintf(stderr, "\n%s ->\n", unitstr);
-	#endif
-
-^" "*"[" {
-	  /* Looks like a keycomment. */
-	  strcat(unitstr, "[");
-	  bracket = 1;
-	}
-
-" "+	  /* Discard leading whitespace. */
-
-[^A-Za-z] {
-	  /* Non-alphabetic character. */
-	  strcat(unitstr, yytext);
-	  if (bracket && *yytext == ']') {
-	    BEGIN(FLUSH);
-	  }
-	}
-
-angstrom {
-	  strcpy(orig, yytext);
-	  strcpy(subs, "Angstrom");
-	  BEGIN(NEXT);
-	}
-
-arcmins|ARCMINS? {
-	  strcpy(orig, yytext);
-	  strcpy(subs, "arcmin");
-	  BEGIN(NEXT);
-	}
-
-arcsecs|ARCSECS? {
-	  strcpy(orig, yytext);
-	  strcpy(subs, "arcsec");
-	  BEGIN(NEXT);
-	}
-
-BEAM	{
-	  strcpy(orig, yytext);
-	  strcpy(subs, "beam");
-	  BEGIN(NEXT);
-	}
-
-Byte	{
-	  strcpy(orig, yytext);
-	  strcpy(subs, "byte");
-	  BEGIN(NEXT);
-	}
-
-days?|DAYS? {
-	  strcpy(orig, yytext);
-	  strcpy(subs, "d");
-	  BEGIN(NEXT);
-	}
-
-D	{
-	  unsafe = 1;
-	  strcpy(orig, yytext);
-	  strcpy(subs, (ctrl & 4) ? "d" : "D");
-	  BEGIN(NEXT);
-	}
-
-degrees?|DEG|DEGREES? {
-	  strcpy(orig, yytext);
-	  strcpy(subs, "deg");
-	  BEGIN(NEXT);
-	}
-
-GHZ	{
-	  strcpy(orig, yytext);
-	  strcpy(subs, "GHz");
-	  BEGIN(NEXT);
-	}
-
-hr|HR	{
-	  strcpy(orig, yytext);
-	  strcpy(subs, "h");
-	  BEGIN(NEXT);
-	}
-
-H	{
-	  unsafe = 1;
-	  strcpy(orig, yytext);
-	  strcpy(subs, (ctrl & 2) ? "h" : "H");
-	  BEGIN(NEXT);
-	}
-
-hz|HZ	{
-	  strcpy(orig, yytext);
-	  strcpy(subs, "Hz");
-	  BEGIN(NEXT);
-	}
-
-KHZ	{
-	  strcpy(orig, yytext);
-	  strcpy(subs, "kHz");
-	  BEGIN(NEXT);
-	}
-
-JY	{
-	  strcpy(orig, yytext);
-	  strcpy(subs, "Jy");
-	  BEGIN(NEXT);
-	}
-
-[kK]elvins?|KELVINS? {
-	  strcpy(orig, yytext);
-	  strcpy(subs, "K");
-	  BEGIN(NEXT);
-	}
-
-KM	{
-	  strcpy(orig, yytext);
-	  strcpy(subs, "km");
-	  BEGIN(NEXT);
-	}
-
-metres?|meters?|M|METRES?|METERS? {
-	  strcpy(orig, yytext);
-	  strcpy(subs, "m");
-	  BEGIN(NEXT);
-	}
-
-MIN	{
-	  strcpy(orig, yytext);
-	  strcpy(subs, "min");
-	  BEGIN(NEXT);
-	}
-
-MHZ	{
-	  strcpy(orig, yytext);
-	  strcpy(subs, "MHz");
-	  BEGIN(NEXT);
-	}
-
-Ohm	{
-	  strcpy(orig, yytext);
-	  strcpy(subs, "ohm");
-	  BEGIN(NEXT);
-	}
-
-[pP]ascals?|PASCALS? {
-	  strcpy(orig, yytext);
-	  strcpy(subs, "Pa");
-	  BEGIN(NEXT);
-	}
-
-pixels|PIXELS? {
-	  strcpy(orig, yytext);
-	  strcpy(subs, "pixel");
-	  BEGIN(NEXT);
-	}
-
-radians?|RAD|RADIANS? {
-	  strcpy(orig, yytext);
-	  strcpy(subs, "rad");
-	  BEGIN(NEXT);
-	}
-
-sec|seconds?|SEC|SECONDS? {
-	  strcpy(orig, yytext);
-	  strcpy(subs, "s");
-	  BEGIN(NEXT);
-	}
-
-S	{
-	  unsafe = 1;
-	  strcpy(orig, yytext);
-	  strcpy(subs, (ctrl & 1) ? "s" : "S");
-	  BEGIN(NEXT);
-	}
-
-[vV]olts?|VOLTS? {
-	  strcpy(orig, yytext);
-	  strcpy(subs, "V");
-	  BEGIN(NEXT);
-	}
-
-years?|YR|YEARS? {
-	  strcpy(orig, yytext);
-	  strcpy(subs, "yr");
-	  BEGIN(NEXT);
-	}
-
-[A-Za-z]+ {
-	  /* Not a recognized alias. */
-	  strcpy(orig, yytext);
-	  strcpy(subs, orig);
-	  BEGIN(NEXT);
-	}
-
-<NEXT>[A-Za-z]+ {
-	  /* Reject the alias match. */
-	  strcat(orig, yytext);
-	  strcpy(subs, orig);
-	}
-
-<NEXT>" "+[^A-Za-z] {
-	  /* Discard separating whitespace. */
-	  unput(yytext[yyleng-1]);
-	}
-
-<NEXT>" "+[A-Za-z] {
-	  /* Compress separating whitespace. */
-	  strcat(unitstr, subs);
-	  strcat(unitstr, " ");
-	  if (strcmp(orig, subs)) status = 0;
-	  unput(yytext[yyleng-1]);
-	  *subs = '\0';
-	  BEGIN(INITIAL);
-	}
-
-<NEXT>.	{
-	  /* Copy anything else unchanged. */
-	  strcat(unitstr, subs);
-	  if (strcmp(orig, subs)) status = 0;
-	  unput(*yytext);
-	  *subs = '\0';
-	  BEGIN(INITIAL);
-	}
-
-<FLUSH>.* {
-	  /* Copy out remaining input. */
-	  strcat(unitstr, yytext);
-	}
-
-<<EOF>>	{
-	  /* End-of-string. */
-	  if (*subs) {
-	    strcat(unitstr, subs);
-	    if (strcmp(orig, subs)) status = 0;
-	  }
-	
-	  yylex_destroy();
-	  if (unsafe) {
-	    return wcserr_set(WCSERR_SET(UNITSERR_UNSAFE_TRANS),
-	      "Unsafe unit translation in '%s'", unitstr);
-	  }
-	  return status;
-	}
-
-%%
diff --git a/astropy/wcs/src/wcslib/CHANGES b/astropy/wcs/src/wcslib/CHANGES
deleted file mode 100644
index 9e95efe..0000000
--- a/astropy/wcs/src/wcslib/CHANGES
+++ /dev/null
@@ -1,1862 +0,0 @@
-WCSLIB version 4.10 (2012/02/06)
---------------------------------
-
-* C library
-
-  - datfix() and spcfix() now return informative messages when dates and
-    AIPS-convention spectral axes are translated (changes contributed by
-    Michael Droettboom).  spcaips() now returns an error status for
-    invalid values of VELREF.
-
-  - wcssub() has been augmented with the ability to add new axes onto a
-    wcsprm struct.
-
-
-WCSLIB version 4.9 (2012/01/24)
--------------------------------
-
-* C library
-
-  - Fixes to wcsfixi() for collecting the messages properly in the info
-    array (from Michael Droettboom).
-
-  - Handle certain malformed date strings more gracefully in datfix().
-
-  - Make informative messages printed by wcserr_prt() a bit more
-    informative.
-
-
-WCSLIB version 4.8.4 (2011/12/05)
----------------------------------
-
-* C library
-
-  - Fixed the pseudo-random number generator in twcstab.c - gcc 4.6 with
-    '-O2' baulked at testing for signed integer overflow.
-
-* Installation
-
-  - In configure.ac, the Fortran compiler's libraries must be added to
-    the link list when checking for the PGPLOT libraries since gcc is
-    driving the linker.  Likewise in C/GNUmakefile when linking test
-    programs that use PGPLOT.
-
-  - Use 'make CHECK=nopgplot check' to run only the non-graphical tests
-    (even if PGPLOT is available).
-
-  - After compiling and running the tests, 'make check' now summarizes
-    the non-graphical test results and stops if any failed.
-
-
-WCSLIB version 4.8.3 (2011/11/17)
----------------------------------
-
-* C library
-
-  - Minor generalization of the wcserr diagnostics to allow the return
-    of informative messages which are associated with negative status
-    values.  wcserr_prt() will now recognize and print them as such.
-    Added wcserr_clear() to reset (clear) a wcserr struct.
-
-  - Modified unitfix() to return an informative message if a units
-    alias is applied, and wcsfixi() to allow such messages to be
-    propagated through the info array (from Michael Droettboom).
-
-  - Modified twcsfix.c to use wcserr diagnostics, in particular to
-    report units alias translations.
-
-* Fortran wrappers
-
-  - In wcsfix_(), interpret *naxis == 0 as meaning naxis == 0x0, thus
-    causing cylfix() to be skipped.
-
-  - Modified twcsfix.f to reflect changes made to twcsfix.c.
-
-
-WCSLIB version 4.8.2 (2011/10/04)
----------------------------------
-
-* Installation
-
-  - Changes for Debian package generation contributed by Ole Streicher:
-    - Corrections to 'configure' reported by 'lintian'.
-    - Generate man pages for the utility programs and install them.
-
-
-WCSLIB version 4.8.1 (2011/09/19)
----------------------------------
-
-* Installation
-
-  - Set SONAME in the sharable library in accordance with
-    tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html
-    (reported by Ole Streicher, Debian package maintainer).  The
-    sharable library will again be installed with full release number
-    and with a symbolic link from SONAME pointing to it.  If defined,
-    SHRLN will point to SONAME.
-
-
-WCSLIB version 4.8 (2011/08/15)
--------------------------------
-
-* C library
-
-  - New error diagnostics mechanism contributed by Michael Droettboom:
-
-    Most functions that return a numeric status (error) code now also
-    write a detailed error message to a wcserr struct attached to the
-    passed-in *prm struct.  See wcserr.h for more information.
-
-    Functions that didn't have a *prm struct as an argument have no
-    direct way to return an error message.  Therefore, these functions
-    now have duplicate versions with the suffix "e" that take an
-    additional "struct wcserr *" parameter.  These functions are:
-
-        spcspx()    ->  spcspxe()
-        spctrn()    ->  spctrne()
-        spctyp()    ->  spctype()
-        spcxps()    ->  spcxpse()
-        wcsulex()   ->  wcsulexe()
-        wcsunits()  ->  wcsunitse()
-        wcsutrn()   ->  wcsutrne()
-
-    A new function wcsfixi() was added which is identical to wcsfix()
-    but in addition stores all of the detailed textual messages about
-    the fixes that were performed.
-
-  - In wcssub(), ensure that wcstab->m_tab has been initialized
-    before trying to free it on status return 12 or 13 (reported by
-    Hans Terlow).
-
-  - Bug fixes:
-    - In sphx2s() and sphs2x() for the case where |eul[1]| = 180.0.
-    - For parsing AIPS-convention VELREF in wcsbth().
-    - In spcaips() for translating AIPS-convention CTYPEia without
-      Doppler frame.
-
-  - Non-graphical test programs now simply report "PASS" if they satisfy
-    the reporting tolerance for closure residuals, etc.  Their full
-    output is reported otherwise.  Run 'make MODE=interactive check' to
-    revert to the previous behaviour of reporting the full output for
-    tests that succeed.
-
-  - Eliminated compiler warnings about type-punning of pointer-to-
-    function.
-
-* Fortran wrappers
-
-    Extensive modifications to track the new error handling mechanism
-    in the C library.
-
-* Installation
-
-  - configure now prefers gfortran over g77 if available.
-
-  - Don't rely on "." being in the PATH if config.status needs to be
-    run in the pgsbox and utils makefile (reported by Peter Teuben).
-
-
-WCSLIB version 4.7 (2011/02/07)
--------------------------------
-
-* C library
-
-  - Bug fix in celset() for interpreting LATPOLEa when LONPOLEa = phi0.
-    Crept in at version 4.4.
-
-  - Fixed the bounds test on y in hpxx2s() (HEALPix projection) for
-    unconventional values of H and K.  In hpxx2s() and hpxs2x(),
-    corrected the offset of the southern polar half-facets for
-    even K.  In hpxs2x(), put the phi = 180 meridian in the expected
-    place.
-
-  - Bug fixes in tabx2s() and tabs2x() for default indexes (reported
-    by David Berry).  In tabs2x(), if no solution is found then do
-    minor extrapolation past the ends of each row (1-D case only).
-    Sped up tabs2x() by about 50%.
-
-  - New functions wcsprintf(), wcsprintf_set(), and wcsprintf_buf(),
-    declared in wcsprintf.h, provide control over the disposition of
-    output from celprt(), linprt(), prjprt(), spcprt(), tabprt(), and
-    wcsprt() routines.  Prompted by Michael Droettboom, with an initial
-    implementation.
-
-* Fortran wrappers
-
-  - In the various test programs, used EQUIVALENCEs to ensure that the
-    CEL, LIN, PRJ, etc. arrays are aligned on a DOUBLE PRECISION
-    boundary.
-
-* PGSBOX
-
-  - Bug fix for the case where NG1 == 0 and GRID1(0) < 0, and likewise
-    for NG2 and GRID2.
-
-* Utilities
-
-  - In wcsware, added a '-w' option to convert world coordinates
-    obtained from stdin to pixel coordinates using wcss2p().  Allow
-    multiple sets of input coordinates with the '-x' and '-w' options
-    and report the value of the intermediate world coordinates.
-
-* User manual
-
-  - Fixed list formatting for function return values < 0 or > 9.
-
-  - New section for wcsprintf() and related routines.
-
-* Installation
-
-  - Changes prompted by Sébastien Fabbro for the Gentoo Linux package:
-      a) autoconf updates,
-      b) respect LDFLAGS when building the shared library,
-      c) install documentation,
-      d) recognise DESTDIR for doing a staged installation.
-
-  - As of this release, the minor WCSLIB version number (second field)
-    will be incremented if and only if a change is made that affects the
-    library itself, not the documentation or utilities.  The version
-    number on the installed libraries and header files will omit the
-    patch number (third field).
-
-
-WCSLIB version 4.6.3 (2010/11/24)
----------------------------------
-
-* C library
-
-  - Bug fix in wcsbth() for handling the inheritance of image header
-    keywords (uncovered by valgrind, reported by Jim Lewis).
-
-
-WCSLIB version 4.6.2 (2010/11/22)
----------------------------------
-
-* C library
-
-  - Fixed a memory leak in wcsbth.l (reported by Jim Lewis).
-
-
-WCSLIB version 4.6.1 (2010/11/18)
----------------------------------
-
-* Fortran wrappers
-
-  - Fixed typos in cel_f.c, celget[cdi] -> celgt[cdi].
-
-
-WCSLIB version 4.6 (2010/11/16)
--------------------------------
-
-* C library
-
-  - In wcsulex.l and wcsutrn.l, stdlib.h must be included explicitly
-    before the redefinition of exit() - most versions of flex do include
-    it upfront but some don't (reported by Peter Williams).
-
-* Fortran wrappers
-
-  - Changes intended to avert nuisance compiler warnings that could
-    potentially obscure warnings indicative of a genuine problem:
-
-    - To stop messages about unused variables when the relevant compiler
-      option is set, e.g. 'g77 -Wunused', the various *_ERRMSG arrays
-      defined in the Fortran include files and (formerly) initialized
-      therein via DATA statements, e.g. PRJ_ERRMSG in prj.inc, have now
-      been placed into COMMON blocks with names such as PRJ_DATA, and
-      are initialized via DATA statements in BLOCK DATA subprograms
-      defined in separate files, e.g. prj_data.f.
-
-    - To stop messages about subroutines being invoked with inconsistent
-      argument lists if the relevant compiler option is not set, e.g.
-      'g77 -Wno-globals', the C wrapper functions that take 'void *'
-      arguments now have separate forms for INTEGER, DOUBLE PRECISION,
-      and CHARACTER arguments that simply invoke the generic function.
-      Application code must be modified to take advantage of this.
-
-* User manual
-
-  - In the section on the Fortran wrappers in the manual, warn about the
-    need for the INTEGER array holding a data structure to be aligned on
-    a DOUBLE PRECISION boundary.
-
-
-WCSLIB version 4.5.6 (2010/10/28)
----------------------------------
-
-* Installation
-
-  - Fixed the search for CFITSIO and PGPLOT library and include
-    directories.
-
-
-WCSLIB version 4.5.5 (2010/10/14)
----------------------------------
-
-* Installation
-
-  - Build the PGSBOX sharable library.
-
-
-WCSLIB version 4.5.4 (2010/09/28)
----------------------------------
-
-* C library
-
-  - In wcshdo(), according to the FITS standard, "Letters in the
-    exponential form ('E' or 'D') shall be upper case" (reported by
-    Michael Droettboom).
-
-
-WCSLIB version 4.5.3 (2010/09/23)
----------------------------------
-
-* Utilities
-
-  - Various improvements to wcsgrid: correct the scaling set via
-    cpgwnad(); label angles other than RA,Dec in decimal degrees;
-    draw the projection boundary for projections other than zenithals.
-
-
-WCSLIB version 4.5.2 (2010/09/23)
----------------------------------
-
-* C library
-
-  - Fixed the translation of GLS to SFL in wcsset() and celfix() when
-    the reference longitude is non-zero - it introduces an offset in
-    longitude in the normal way.  (This undoes part of the change
-    applied in version 4.4.)
-
-
-WCSLIB version 4.5.1 (2010/08/12)
----------------------------------
-
-* C library
-
-  - New utility function, sphpad(), computes the coordinates of points
-    offset by given angular distances and position angles from a given
-    point on the sky (complementary to sphdpa()).
-
-* Fortran wrappers
-
-  - New wrapper function:
-    - SPHPAD for sphpad().
-
-
-WCSLIB version 4.5 (2010/07/16)
--------------------------------
-
-* C library
-
-  - Fixed the interpretation of VELREF when translating AIPS-convention
-    spectral types.  Such translation is now handled by a new special-
-    purpose function, spcaips().  The wcsprm struct has been augmented
-    with an entry for velref which is filled by wcspih() and wcsbth().
-    Previously, selection by VELREF of the radio or optical velocity
-    convention for type VELO was not properly handled.
-
-* Fortran wrappers
-
-  - New wrapper function:
-    - SPCAIPS for spcaips().
-
-  - Changed spc.inc, spc_f.c, wcs.inc and wcs_f.c to track VELREF
-    changes.
-
-  - Declared functions external in the include files to avoid compiler
-    warnings about unused variables (if the particular option is set).
-
-* Utilities
-
-  - Added a '-q' option to fitshdr to quit after a specified number
-    of HDUs.
-
-
-WCSLIB version 4.4.4 (2009/09/14)
----------------------------------
-
-* Installation
-
-  - Added more configure options for controlling the build:
-    --disable-fortran, --disable-utils, --without-cfitsio, and
-    --without-pgplot.
-
-
-WCSLIB version 4.4.3 (2009/09/03)
----------------------------------
-
-* C library
-
-  - Set wave number units to "/m" in spctyp(), was "1/m" which is not
-    strictly legal and wasn't handled by wcsulex() (reported by
-    Hans Terlow).  Also fixed a number of units specifications in the
-    prologue of spx.h to conform with Paper I usage.
-
-  - In wcsulex(), allow unit strings like "1/m" in addition to "/m",
-    provided that the superfluous "1" is the first non-blank character
-    in the expression, or parenthesised sub-expression.
-
-  - In wcssptr(), ensure that i is always reset if given < 0.
-
-* User manual
-
-  - Augmented the list of FITS WCS and related software in the manual.
-
-
-WCSLIB version 4.4.2 (2009/08/13)
----------------------------------
-
-* C library
-
-  - In sphx2s() and sphs2x(), handle the case where |eul[1]| = 180.0
-    separately for speed and accuracy.  This change also fixes a rare
-    and subtle bug in cels2x() that occurs when celprm::isolat is set
-    and the magnitude of the first latitude in the lat[] vector exceeds
-    90 deg (reported by Hans Terlouw).
-
-* Installation
-
-  - Fix relating to creation of symlinks when installing the libraries.
-
-
-WCSLIB version 4.4.1 (2009/08/11)
----------------------------------
-
-* Installation
-
-  - Fixes for installation of the CHANGES file and for the creation of a
-    symbolic link for the sharable library if one already exists.
-
-
-WCSLIB version 4.4 (2009/08/10)
--------------------------------
-
-* C library
-
-  - Creation of WCSLIB user manual from the header file prologues using
-    a special-purpose parser, doxextr, and sed scripts to generate input
-    for doxygen.  This required minor formatting changes to all
-    prologues plus miscellaneous changes such as naming of arguments in
-    function prototypes.
-
-  - Bug fix in wcsset() that affected handling of PROJPn (deprecated)
-    and PVi_ma attached to the longitude (not latitude) axis.  Guard
-    against long strings when copying the projection code.  In
-    wcs_types(), allow for early Paper IV distortion codes (e.g.
-    "RA---TAN-SIP") when parsing CTYPEia.
-
-  - Use sincos() whereever possible for a ~15% speedup (patches for
-    cel.c, prj.c and sph.c supplied by Michael Droettboom).  configure
-    checks for, and uses it automatically if available.
-
-  - Fixed the translation of GLS to SFL in wcsset() and celfix() when
-    the reference longitude and latitude are non-zero.  (In the AIPS
-    convention, this simply translates the reference point, i.e. the map
-    as a whole, to those coordinates without creating an oblique grid.)
-
-  - Bug fix in prjoff(), a utility function used by the prj routines.
-    It forces (x,y) = (0,0) at (phi_0,theta_0) when the latter are set
-    by PVi_[012]a attached to the longitude (not latitude) axis.  Rarely
-    used in practice.
-
-  - New utility function, sphdpa(), computes the distance and position
-    angle from a point on the sphere to a set of field points.
-
-  - In sphx2s() and sphx2s(), handle a simple change in origin of
-    longitude using a short-cut calculation for speed and accuracy.
-    Similarly in celset(), check whether phip == phi0 when computing
-    latp and if so use a short-cut that ensures latp == 90.0 (exactly)
-    if lat0 == theta0.  The resulting spherical rotation then becomes a
-    simple change in origin of longitude.  In particular, these changes
-    should assist PGSBOX in drawing grid lines of +/-180 longitude, to
-    prevent flip-flopping between one and the other.
-
-  - wcsbth() & wcspih(): resolved an inconsistency between the
-    documentation and code by renamimg WCSHDR_VSOURCEa as
-    WCSHDR_VSOURCE.
-
-  - Flex code: moved declaration of helper functions out of global
-    scope.
-
-  - Fixed the call to wcss2p() in twcshdr (in a section of code not
-    usually exercised).
-
-* Fortran wrappers
-
-  - New wrapper functions:
-    - WCSBTH for wcsbth(),
-    - WCSBDX for wcsbdx(),
-    - CDFIX  for cdfix(),
-    - SPHDPA for sphdpa().
-
-  - Updated WCSLEN (in wcs.inc) and added WCS_COLAX and WCS_VELANGL to
-    match changes to wcsprm made in v4.3 with corresponding changes to
-    the wrapper functions.  Likewise updated TABLEN (in tab.inc) for
-    changes to tabprm, and added CEL_LATPREQ for celprm.
-
-  - Struct lengths (WCSLEN, PRJLEN, etc.) are now long enough to
-    accomodate 64-bit machines.
-
-  - Updated the flag bits for the RELAX argument in wcshdr.inc to
-    reflect changes to wcshdr.h made in v4.3.  Renamed WCSHDR_VSOURCEa
-    to WCSHDR_VSOURCE for consistency with the C library.
-
-* PGSBOX
-
-  - Improved grid labelling, particularly in minimizing the number of
-    fields required in sexagesimal labels.
-
-* Utilities
-
-  - New utility program:
-
-    - wcsware extracts the WCS keywords for an image from the specified
-      FITS file, constructs wcsprm structs for each coordinate
-      representation found, and performs a variety of operations using
-      them.
-
-  - Old utility programs (first appeared in 4.3 but were not recorded):
-
-    - HPXcvt reorganises HEALPix data into a 2-D FITS image with HPX
-      coordinate system.
-
-    - wcsgrid extracts the WCS keywords for an image from the specified
-      FITS file and uses pgsbox() to plot a 2-D coordinate graticule for
-      each alternate representation found.
-
-    - fitshdr lists headers from a FITS file specified on the command
-      line, or else on stdin, printing them as 80-character keyrecords
-      without trailing blanks.
-
-* Installation
-
-  - New configure options, --with-pgplotinc, --with-pgplotlib,
-    --with-cfitsioinc and --with-cfitsiolib allow additional directories
-    to be added to the library and include file search path.
-
-  - Miscellaneous fixes and improvements to the installation process.
-
-  - Generate a metadata file for pkg-config.
-
-  - Added 'make MODE=interactive check' to run the test programs in
-    interactive mode rather than batch.
-
-  - Merged the separate CHANGES files for C, Fortran and PGSBOX into
-    one (this), with a new section for utilities.
-
-
-WCSLIB version 4.3.3 (2009/04/30)
----------------------------------
-
-* C library
-
-  - fitshdr.l, wcsbth.l, and wcspih.l: use setjmp/longjmp to preempt
-    the call to exit() which is hard-coded in function yy_fatal_error()
-    supplied by flex.
-
-  - wcspih.l: if NAXIS is non-zero but there were no WCS keywords at
-    all in the header then create a default WCS with blank alternate
-    version.
-
-
-WCSLIB version 4.3.2 (2009/03/16)
----------------------------------
-
-* C library
-
-  - utils/GNUmakefile: create BINDIR if necessary prior to installing
-    utilities.
-
-
-WCSLIB version 4.3.1 (2008/09/08)
----------------------------------
-
-* Installation
-
-  - Top-level GNUmakefile: install header files.
-
-
-WCSLIB version 4.3 (2007/12/27)
--------------------------------
-
-* C library
-
-  - A new general WCS header parser wcsbth() handles binary table image
-    arrays and pixel lists as well as image array headers.  Added
-    "colax" to the wcsprm struct to record the column numbers for each
-    axis in a pixel list.
-
-  - New function wcsbdx() is the analog of wcsidx() for the array of
-    wcsprm structs returned by wcsbth().
-
-  - New function wcshdo() writes out a wcsprm struct as a FITS header.
-
-  - Changes to wcspih():
-    - Bug fix, check for a == 0 (indication of a keyword that applies
-      to all alternates) in internal helper function wcspih_naxes()
-      (reported by Craig Markwardt).
-    - Added a new ctrl option to remove valid WCS keyrecords except for
-      those with a more general role, namely {DATE,MJD}-{OBS,AVG} and
-      OBSGEO-{X,Y,Z} (suggested by Jim Lewis).
-    - Added a rule for VELANGLa.  Also added "velangl" to the wcsprm
-      struct.
-    - Do checks on the i, k & m keyword parameters in <VALUE>.
-    - Fixed the test for repeated blanks in the NAXIS and WCSAXES
-      patterns.
-    - Fixed three <CCi_ma> rules to allow m == 0.
-    - Reworked the implementation notes in the prologue.
-
-  - The flex scanners, fitshdr.l, wcsbth.l, wcspih.l, wcsulex.l, and
-    wcsutrn.l, invoke yylex_destroy() before returning to avoid a 16kiB
-    memory leak.  This was reported by several people, however it may be
-    problematic depending on the version of flex used - version 2.5.9 or
-    later is required.  If this is not available, C sources pre-
-    generated by flex 2.5.33 will be used.
-
-  - In wcs.c, don't define the signbit macro if already defined (for
-    MacOSX).
-
-  - In wcs.h, documented wtbarr namespace issues in C++.
-
-  - In wcsset(), always set wcsprm.cunit[i], if possible (primarily for
-    use by wcshdo()).
-
-  - In wcsfix.c, parenthesised a boolean expression that was otherwise
-    incorrect.
-
-  - Fixed an obscure floating point rounding error in celset() that
-    appeared with -O2 optimization in gcc v3.3.5 (Linux).
-
-  - prjset() now correctly propagates the status value returned by the
-    specific projection-setting functions (reported by Bill Pence).
-
-  - Bug fix in hpxx2s(), also added bounds checking.  Minor efficiencies
-    in carx2s() and merx2s().
-
-  - In the various functions that print the contents of the structs, use
-    the "%p" printf conversion specifier to print addresses rather than
-    casting the pointer to int and using "#x".  The latter does not work
-    on 64-bit machines where sizeof(int) != sizeof(void*).
-
-  - Reorganized the various structs to get alignment on 64-bit machines.
-
-  - All header file prologues now reference the README file for an
-    overview of the library.
-
-  - Miscellaneous portability fixes for 64-bit, MacOSX, OSF compiler,
-    etc.
-
-  - Elimination of compiler warnings, e.g. parenthesised assignments
-    used as truth values (a favourite gcc gripe!), etc.
-
-  - Process flex descriptions using a newer version of flex, primarily
-    for MacOSX.  However, the processed files are now only used when
-    flex 2.5.9 or later is not available.
-
-  - Removed WCSLIB 2.x backwards-compatibility measures from lin.h,
-    prj.h, prj.c, and sph.h.
-
-* Fortran wrappers
-
-  - (No substantive changes.)
-
-* PGSBOX
-
-  - Miscellaneous improvements to PGSBOX.
-
-* General
-
-  - Switched licensing to LGPL 3.0.
-
-  - In comment text, replaced use of the obsolete term "card" with
-    "keyrecord" which consists of a "keyword", "keyvalue", and
-    "keycomment".
-
-* Installation
-
-  - General improvements to the installation process: autoconf-related
-    portability improvements, particularly relating to Fortran name
-    mangling; makefile rules for building the shared library, for
-    processing flex descriptions; don't rely on "." being in the PATH
-    when running tests.
-
-
-WCSLIB version 4.2 (2005/09/23)
--------------------------------
-
-* C library
-
-  - Brought the installation process under control of GNU autoconf,
-    the top-level makefile now builds and tests everything, and the C
-    library has a config.h in which WCS_INT64 is set.  Added an INSTALL
-    file.
-
-  - Merged the FORTRAN, C and PGSBOX READMEs into one top-level README.
-
-  - Extensions for -TAB coordinate handling: in tabx2s() and tabs2x(),
-    allow extrapolation by half a cell at either end of the index and
-    coordinate tables; fits_read_wcstab() (in getwcstab.{h,c}) allows
-    TDIMn to be omitted for 1-D lookup tables for which it has the form
-    '(1,K)', i.e. describing a degenerate 2-D array; wcsprt() now prints
-    the wtbarr structs in wcsprm.
-
-  - Bug fixes for -TAB coordinate handling: in tabx2s() and tabs2x()
-    the incorrect indexing variable, m instead of i, was used for
-    tab->crval[]; wcsp2s() and wcss2p() returned prematurely in the
-    tabular coordinate loop; in wcstab(), removed an extraneous
-    assignment to wtbp->kind for index arrays.
-
-  - In wcsp2s() and wcss2p(), elements of the stat[] vector that had
-    been set were being reset incorrectly to zero.  The stat[] values
-    are now set as flag bits for each coordinate element.
-
-  - Added cdfix() to the wcsfix() suite to fix erroneously omitted
-    CDi_ja cards.
-
-  - PGSBOX is now compiled into a separate object library, and is
-    installed alongside WCSLIB.
-
-  - Eliminated several instances of non-ANSI C library functions and
-    header files and some residual K&R C usage.  The Sun C compiler
-    complained about const int definitions of initializers used in
-    variable declarations in some of the test programs; changed these
-    to preprocessor macros.
-
-* Fortran wrappers
-
-  - Fixed handling of 64-bit integer keyvalues in keyget_().
-
-  - Fixed output formatting of 64-bit integer keyvalues in tfitshdr.f.
-
-  - Fixed minor syntax errors in twcsfix.f and tpih1.f reported by the
-    Sun Fortran compiler.
-
-  - The output of each test program now identifies the source file.
-
-* PGSBOX
-
-  - (No substantive changes.)
-
-
-WCSLIB version 4.1 (2005/08/31)
--------------------------------
-
-* C library
-
-  Summary of added functionality:
-
-  - -TAB coordinate axes are now fully implemented in the WCSLIB driver
-    functions (in wcs.{h,c}); multiple -TAB axes are supported.  A new
-    function, wcstab(), which is automatically invoked by wcspih(),
-    parses -TAB-related header cards and sets up structs for a separate
-    routine that reads the necessary arrays from a FITS binary table
-    extension.
-
-    An implementation of this routine in CFITSIO, fits_read_wcstab(),
-    is provided.  Note however that the interface of this function is
-    experimental, and the code itself must be considered beta-release in
-    WCSLIB 4.1.
-
-  - Units specifications, either from CNAMEia or inline comments (with
-    brackets), of arbitrary complexity are now fully implemented via a
-    parser, wcsulex(), and converter, wcsunits().  This is invoked
-    automatically by wcsset().
-
-  - Translators for non-standard WCS constructs are provided.  These
-    cover date formats, units specifications, defunct celestial
-    projection types, AIPS spectral axis types, and the repair of
-    malformed cylindrical coordinate systems.
-
-  - wcspih() now has options to remove the WCS cards it has processed
-    from the header and a new generic FITS header parser, fitshdr(), may
-    be used to parse the remaining non-WCS cards.  In addition to the
-    more basic types, it handles 64-bit and 'very long' (70 digit)
-    integer keyvalues, and also continued string keyvalues.  It also
-    does keyword matching and extracts units specifications in inline
-    comments.
-
-  - -LOG coordinates are now implemented independently of spectral
-    coordinate types.  Multiple -LOG axes are supported.
-
-  - New function wcssptr() translates the spectral axis in a wcsprm
-    struct to the required type.
-
-  - The README file now gives an introduction to, and complete overview
-    of, WCSLIB.  It provides a point of entry to programming with
-    WCSLIB.  Complete descriptions and usage notes for all functions are
-    contained in the header files.
-
-  - The FORTRAN wrappers and test programs are now completely up-to-date
-    with respect to the C implementation.
-
-  - All code, including the FORTRAN wrappers, PGSBOX, and all test
-    programs, now pass 'purify' without memory leaks, uninitialized
-    memory reads, memory access violations, or other memory faults.
-
-  Change notes:
-
-  - Added options to wcspih() to remove WCS cards from the input header
-    leaving only non-WCS cards behind.  Modified test programs tpih1.c
-    and tpih2.c to use CFITSIO optionally via preprocessor macro
-    DO_CFITSIO.
-
-  - New function wcstab() in wcshdr.{h,c} parses -TAB-related header
-    cards and sets up structs for a separate routine that reads the
-    necessary arrays from a FITS binary table extension.  New
-    test/demo program twcstab.c using header defined in wcstab.cards.
-
-  - CFITSIO implementation, fits_read_wcstab() in getwcstab.{h,c}, of a
-    function, independent of WCSLIB, for extracting arrays from a binary
-    table as required in constructing -TAB coordinates.
-
-  - New units specification parser, wcsulex() in wcsunits.h and
-    wcsulex.l, and converter, wcsunits() in wcsunits.{h,c}.  New
-    test/demo program tunits.c.
-
-  - New parser for non-standard units specifications, wcsutrn() in
-    wcsunits.h and wcsutrn.l, also tested by tunits.c.
-
-  - New functions datfix(), unitfix() (which applies wcsutrn()),
-    celfix(), and spcfix() join cylfix() in wcsfix.{h,c} to translate
-    various forms of non-standard or quasi-standard FITS WCS keyvalues
-    in a wcsprm struct.  wcsfix() applies all of these in sequence.
-    New test/demo program twcsfix.c, with wcsfix() also now invoked by
-    tpih1.c.
-
-  - New generic FITS header parser, fitshdr() in fitshdr.{h,l}.  New
-    test/demo program tfitshdr.c uses wcs.cards with extra non-WCS
-    cards added.
-
-  - -LOG coordinates are now treated as a coordinate type separate from
-    spectral coordinates, implemented via log.{h,c} and test program
-    tlog.c.  The logarithmic functions were removed from spx.{h,c}, and
-    spc.c.
-
-  - Extensive changes to wcs.{h,c} to support multiple -TAB and -LOG
-    coordinate axes and units conversion.  Substantially changed the
-    test program, twcs.c, to test the more general functionality.
-
-  - New function wcssptr() in wcs.{h,c} translates the spectral axis in
-    a wcsprm struct.
-
-  - Added DATE-AVG to wcsprm.  Also ntab, tab, nwtb, and wtb required
-    for -TAB implementation.  Define struct wtbarr.
-
-  - Added a types[] member to the wcsprm struct to identify axis
-    coordinate types using a four-digit code.
-
-  - Use memset() in wcsini() to null-fill character arrays in the wcsprm
-    struct so that they don't appear to be padded with garbage when
-    displayed by gdb.
-
-  - Do alias translation for AIPS-convention spectral types in wcsset()
-    using spctyp().  If wcsset() finds a CTYPEia in "4-3" form with an
-    unrecognized algorithm code it now returns an error rather than
-    assume that it's a linear axis.  wcsset() now also resets lonpole
-    and latpole to the values actually used.
-
-  - Modified spctyp() to translate AIPS-convention spectral ctypes, and
-    modified the argument list to return the parsed spectral type and
-    algorithm code.  The return arguments will not be modified if
-    CTYPEia is not a valid spectral type; zero-pointers may be specified
-    for any that are not of interest.  Removed the external const
-    variables, spc_codes and spc_ncode, as their function is now
-    fulfilled by spctyp().
-
-  - Fixed a bug in spctrn() in resolving ctypeS2 wildcarding.
-
-  - Added latpreq member to the celprm struct, set by celset() to
-    indicate how LATPOLE is used.  Augmented tcel2.c to report it.
-
-  - New function tabmem() in tab.{h,c} takes control of user-allocated
-    memory.
-
-  - tabini() allows K == 0 and also K[m] == 0 to initialize partially
-    the tabprm struct (for wcstab()).  It now does fine-grained
-    bookkeeping of memory allocation for the index arrays and allocates
-    each individually.  tabprm.index[] == 0x0 is recognized as default
-    indexing in tabset(), tabx2s() and tabs2x().
-
-  - The *prt() functions report parameters to an extra decimal place.
-
-  - tabprt() prints the array index for elements of the coordinate and
-    index vectors.
-
-  - Set the 0th element in all *_errmsg arrays to "Success".
-
-  - Extracted string utility functions used by WCSLIB into
-    wcsutil.{h,c}.
-
-  - Removed support for K&R C.
-
-* Fortran wrappers
-
-  - The FORTRAN wrappers and test programs are now completely up-to-date
-    with respect to the C implementation.
-
-  - New include files, wrappers, and test programs:
-    fitshdr.inc, fitshdr_f.c, getwcstab.inc, getwcstab_f.c, log.inc,
-    log_f.c, sph.inc, tab.inc, tab_f.c, tfitshdr.f, tlog.f, ttab1.f,
-    ttab2.f, ttab3.f, tunits.f, twcsfix.f, twcstab.f, wcsfix.inc,
-    wcsfix_f.c, wcsunits.inc, wcsunits_f.c.
-
-  - Updates to reflect changes to the C library and test programs:
-    cel.inc, cel_f.c, prj.inc, spc.inc, spc_f.c, spx.inc, spx_f.c,
-    tlin.f, tpih1.f, tpih2.f, tprj1.f, tprj2.f, tspc.f, tsph.f, tspx.f,
-    twcs.f, twcsmix.f, twcssub.f, wcs.inc, wcs_f.c, wcshdr.inc,
-    wcshdr_f.c.
-
-  - Added *_ERRMSG arrays containing status messages to all include
-    files.
-
-  - Removed support for K&R C.
-
-* PGSBOX
-
-  - Fixed a subtle though benign memory fault identified by 'purify'.
-
-  - Reset LATPOLE in the COE example in cpgtest.f when drawing the
-    second (native) grid because it will have been set to a non-default
-    value by wcsset() when the first grid was drawn; set wcs.flag to -1
-    before wcsinit() and call wcsfree() at the end.  Similarly for
-    pgtest.f.
-
-
-WCSLIB version 4.0 (2005/02/07)
--------------------------------
-
-* C library
-
-  - Implemented tabular coordinates (-TAB).  New files: tab.h and tab.c,
-    and test programs ttab[123].c.  These have not been incorporated
-    into the higher-level (wcs.h) functions at this stage.
-
-  - New spectral functions: spchek() checks a spectral algorithm code
-    for legitimacy; from the spectral keywords given, spcspx() derives
-    the corresponding CRVALi and CDELTi keywords for the underlying P-,
-    and X-type spectral coordinates; spcxps() does the opposite;
-    spctrn() combines spcspx() and spcxps() to translate one set of
-    spectral keywords into another, e.g.  'FREQ' -> 'ZOPT-F2W'.
-
-  - Implemented the HEALPix (HPX) projection in the prj functions.
-
-  - Added a new function, wcsidx(), to return an array that indexes the
-    alternate coordinate descriptions found by wcspih() (suggested by
-    Bill Pence, NASA/Goddard).  Modified tpih1.c to exercise it.
-
-  - In wcsp2s() and wcss2p(), check that nelem equals or exceeds
-    wcs.naxis; emphasised this in the usage notes for these functions
-    in tab.h (suggested by Bill Pence, NASA/Goddard).
-
-  - Moved the macros used for UNDEFINED values and the corresponding
-    macro test function, undefined(), to wcsmath.h for general use.
-    Previously, UNDEFINED values were only used internally, but they are
-    now visible in some of the structs, particularly values of undefined
-    auxiliary header cards in the wcsprm struct.
-
-  - Remove const from the double args in the specx() prototype in spx.h
-    to match the definition in spx.c (reported by Bryan Irby,
-    NASA/Goddard).
-
-  - Fixed the interaction between the FLAVOUR and PGPLOTLIB definitions
-    in the C and FORTRAN Makefiles by introducing a separate variable,
-    DO_PLOTS, to control whether to exercise test programs that require
-    PGPLOT (reported by Bill Pence, NASA/Goddard).
-
-* Fortran wrappers
-
-  - New wrapper defined in wcshdr_f.c: wcsidx_().  Modified test program
-    tpih1.f to use it.
-
-* PGSBOX
-
-  - (No substantive changes.)
-
-* General
-
-  - Changed the copyright notice in all library routines from LGPL to
-    GPL as recommended by the FSF (http://www.gnu.org/licenses/why-not-
-    lgpl.html).
-
-* Installation
-
-  - General improvements to the installation process: fixed the
-    interaction between the FLAVOUR and PGPLOTLIB definitions in the
-    Makefile by introducing a separate variable, DO_PLOTS, to control
-    whether to exercise test programs that require PGPLOT (reported by
-    Bill Pence, NASA/Goddard).  Added an "install" target to the
-    Makefile.
-
-
-WCSLIB version 3.6 (2004/08/25)
--------------------------------
-
-* C library
-
-  - New service routine, wcssub() extracts the coordinate description
-    for a subimage from a wcsprm struct.  wcscopy() is now implemented
-    as a preprocessor macro that invokes wcssub().  New test program,
-    twcssub.c, tests wcssub().
-
-  - In wcspih():
-
-    1) Fixed handling of string-valued keywords where the inline comment
-       contains a single-quote character (').
-
-    2) Fixed the address arithmetic for EPOCH and VELREF.
-
-    3) Translate VSOURCEa into ZSOURCEa if required.
-
-    4) Recognize SSYSSRCa.
-
-    5) Support free-format string keyvalues, as well as integer and
-       floating-point keyvalues; documented this in the prologue of
-       wcshdr.h.
-
-    6) Allow header cards without inline comments.
-
-    7) Fixed function prototyping in wcspih.l (i.e. ANSI and non-ANSI
-       forms were potentially mixed).
-
-    8) Catch an unhandled newline character on the END card that was
-       echoed to stdout.
-
-    9) In error messages, print "ERROR" (uppercase) - POSIX standard.
-
-  - Modified wcs.cards to explain and test free-format keyvalues, and
-    also augmented the inline comment on illegal WCS cards that are to
-    be rejected, and WCS-like cards to be discarded.  Added a header
-    card with no inline comment.
-
-  - Removed vsource from the wcsprm struct and added ssyssrc.
-
-  - In wcsini(), fixed a problem with memory management for wcs.pv when
-    NPVMAX is zero; likewise for wcs.ps and NPSMAX.
-
-  - In wcsprt(), don't print auxiliary coordinate system information in
-    arrays with zero address.
-
-  - In wcss2p(), status == 9 (one or more invalid world coordinates) was
-    not returned appropriately.
-
-  - Renamed twcs1.c to twcs.c, and twcs2.c to twcsmix.c.
-
-  - "Error status/code/number" is now referred to consistently as the
-    "status return value".
-
-  - Some vestiges of K&R C were removed: preprocessor definition of
-    const, and K&R function prototypes.
-
-* Fortran wrappers
-
-  - New wrapper defined in wcs_f.c: wcssub_().  New test program,
-    twcssub.f.
-
-  - Renamed twcs1.f to twcs.f, and twcs2.f to twcsmix.f.
-
-* PGSBOX
-
-  - (No substantive changes.)
-
-* Installation
-
-  - Worked over the C, FORTRAN, and PGSBOX makefiles, in particular to
-    make them all consistent.
-
-
-WCSLIB version 3.5 (2004/06/28)
--------------------------------
-
-* C library
-
-  - WCSLIB now provides a function, wcspih() implemented as a Flex
-    description, that parses a FITS image header, either that of a
-    primary HDU or an image extension.  Given a character array
-    containing the header it identifies and reads all WCS cards for
-    the primary coordinate description and up to 26 alternate
-    descriptions and returns this information as an array of wcsprm
-    structs.  A service routine, wcsvfree(), is provided to free the
-    memory allocated by wcspih().  The relevant header file for these
-    functions is wcshdr.h.
-
-    Test programs, tpih1 and tpih2, are provided to verify wcspih.  The
-    first simply prints the contents of the structs using wcsprt().  The
-    second uses cpgsbox() to draw coordinate graticules.  A FITS WCS
-    test header has been developed to provide input to these test
-    programs.  It is implemented as a list of card images, wcs.cards,
-    one card per line, together with a program, tofits, that compiles
-    these into a valid FITS file.  tpih1 uses its own code to read this,
-    whereas tpih2 uses the fits_hdr2str() function from CFITSIO.
-
-  - Removed twcsprt, tpih exercises wcsprt() much more thoroughly than
-    twcsprt ever did.  Modified twcs1 to print the size of the various
-    structs as twcsprt used to.
-
-  - Although they are not used in any coordinate calculations, the
-    wcsprm struct now provides data members for storing all of the
-    auxiliary FITS WCS header cards defined in Papers I, II, and III,
-    such as WCSNAMEa, EQUINOXa, and CNAMEia.  Members are also provided
-    for storing the alternate descriptor code (the "a" in CTYPEia), and
-    the binary table column number.  These are supported by the high
-    level WCSLIB routines, wcsini(), wcscopy(), wcsfree(), and wcsprt().
-    Refer to wcs.h for details.
-
-  - The number of PVi_ma cards for which wcsini() allocates memory is
-    now set by a global variable, NPVMAX (previously a C-preprocessor
-    macro).  This defaults to 64 but may be changed by a new function,
-    wcsnpv().  The wcsprm struct contains a new member, npvmax, that
-    records the value of this number at the time the struct was
-    initialized.  This is in addition to npv which records the actual
-    number of cards that were encountered.
-
-    Similarly, NPSMAX (default 8) is used for the number of PSi_ma
-    cards, and it may be changed via wcsnps().
-
-    The axis number, i, in the pvcard struct used for storing PVi_ma
-    cards may now be set to 0 to indicate the latitude axis.
-
-  - calloc() is now used in place of malloc() in allocating memory for
-    arrays, and inclusion of malloc.h has been replaced with stdlib.h
-    for all platforms.
-
-    wcsfree() checks that wcs.flag != -1 before testing wcs.m_flag when
-    freeing memory allocated by wcsini() in case the struct is
-    uninitialized.  Similarly for linfree().
-
-  - In prj.h, renamed C-preprocessor macros INI, PRT, SET, X2S and S2X
-    to PRJINI, PRJPRT, PRJSET, PRJX2S and PRJS2X to reduce the
-    likelihood of namespace clashes.  Similarly in spc.h.
-
-    Also, in prj.c, changed the name of helper routine offset() to
-    prjoff() to reduce the likelihood of global namespace conflicts.
-
-  - In line with bonx2s() and bons2x(), bonset() now recognizes the
-    equatorial case of Bonne's projection as Sanson-Flamsteed, mainly so
-    that the auxiliary information in the prjprm struct more accurately
-    reflects the truth.  Modified tcel2 to exercise this by using an
-    equatorial Bonne projection in place of the Hammer-Aitov.
-
-  - zpns2x() used prj.w[0] for bounds checking, though this had not been
-    set by zpnset() for polynomials of degree N < 3.  Consequently,
-    bounds checking for N < 3 was unreliable (reported by David Berry,
-    STARLINK).
-
-  - Changed some variable names in tscs2x(), cscx2s(), cscs2x(),
-    qscx2s(), and qscs2x() to match Paper II, and likewise changed some
-    inequality tests in qscs2x() without changing the results.
-
-  - Minor tidying up of output formatting in prjprt().
-
-  - Added the alternate version code to FITS WCS keywords mentioned in
-    comments, e.g. CTYPEi changed to CTYPEia.
-
-* Fortran wrappers
-
-  - New wrappers defined in wcshdr_f.c: wcspih_() and wcsvfree_(), and
-    also a new service function, wcsvcopy_().
-
-    New test programs, TPIH1 and TPIH2, being analogues of tpih1 and
-    tpih2.  Removed TWCSPRT.
-
-  - In wcs_f.c, new wrappers wcsnpv_() and wcsnps_(); modified wcsput_()
-    and wcsget_() to handle new members of the wcsprm struct.  Also
-    modified wcsput_() to null-fill all char[] members of the wcsprm
-    struct, and likewise wcsget_() to blank-fill them.
-
-  - Modified wcs.inc to support changes to the wcsprm struct.
-
-* PGSBOX
-
-  - In PGSBOX, increased the dimension of the WORLD and XY vectors from
-    2 to 9 to accomodate higher-dimensional coordinate representations
-    of up to 9 elements.  Similarly for pgwcsl().  The assumption
-    (presently) is that the first two world, and pixel, coordinate
-    elements are the relevant ones; the others are all set to zero when
-    pgwcsl() initializes and otherwise ignored.
-
-    Assigned some variables in DATA to stop compiler messages about
-    uninitialized variables.
-
-  - Generalized the Makefile, bringing it into line with the WCSLIB
-    Makefile, and adding separate targets for compiling and running the
-    test programs.  The default target now simply compiles pgsbox.c and
-    cpgsbox.c.  A separate target compiles pgwcsl.c and inserts it into
-    ../C/libwcs.a.
-
-
-WCSLIB version 3.4 (2004/02/11)
--------------------------------
-
-* C library
-
-  - In aitx2s(), apply the boundary condition 0.5 <= Z^2 <= 1 given
-    after Eq. (109) in WCS Paper II to detect outlying pixels.
-
-  - Fixed several special-case bugs in celset():
-
-    1) For theta_0 = 90, in substituting the default value for phi_p
-       (LONPOLE),
-
-       a) for the special case when delta_0 = 90, celset() provided the
-          wrong value (180 instead of 0),
-
-       b) celset() neglected to add phi_0 (normally 0).
-
-    2) For theta_0 != 90,
-
-       a) for the special case when delta_0 = -90, celset() incorrectly
-          computed delta_p (as theta_0 instead of -theta_0),
-
-       b) for the special case when delta_p = +90 (or -90), celset()
-          neglected to subtract (or add) phi_0 (normally 0).
-
-    3) For |delta_0| = 90, celset() incorrectly allowed the particular,
-       invalid, value of phi_p (LONPOLE) that put the other pole at the
-       fiducial point.
-
-    4) For theta_0 = 0, delta_0 = 0 LATPOLE determines delta_p
-       completely.  For LATPOLE > 90 celset() now sets delta_p to 90,
-       and for LATPOLE < -90 it sets it to -90.
-
-  - Additional refinements in celset():
-
-    1) cel->ref[2] is normalized in the range [-180,180].
-
-    2) Account for rounding error in the computation of delta_p.
-
-  - sphx2s() and sphs2x() incorrectly handled the "change in the origin
-    of longitude" special case that arises when delta_p = -90, in the
-    even more restrictive case where |theta| = 90 also; it applied
-    Eq. (3) instead of Eq. (4) of Paper II.
-
-  - Added a new test program, tcel2.c, to exercise celset() more
-    thoroughly.  Renamed the original tcel.c to tcel1.c and modified the
-    Makefile to suit.
-
-* Fortran wrappers
-
-  - (No changes.)
-
-* PGSBOX
-
-  - (No substantive changes.)
-
-
-WCSLIB version 3.3 (2003/10/21)
--------------------------------
-
-* C library
-
-  - In celset(), the default value for phi_p (LONPOLE) is
-
-       phi_p = phi_0 + ((delta_0 < theta_0) ?  180.0 : 0.0)
-
-    Previously phi_0 (which is normally zero) was not added (reported by
-    David Berry, STARLINK).
-
-  - wcsprt() and linprt() now check that the structs have been
-    initialized.
-
-  - In wcsini(), when the wcsprm flag is -1 also set the linprm flag to
-    -1 to force initialization of the memory managed by linset().
-
-  - wcsset() now explicitly initializes the celprm and spcprm structs
-    via celini() and spcini().
-
-  - Fixed syntax errors in the macro definitions of linrev_errmsg and
-    linfwd_errmsg.
-
-  - In Makefile, added the -ansi option to gcc to force it to behave
-    like a strict ANSI C compiler, specifically in setting the __STDC__
-    preprocessor macro.
-
-* Fortran wrappers
-
-  - (No changes.)
-
-* PGSBOX
-
-  - PGSBOX now recognizes status returns -1, -2, and -3 from NLFUNC for
-    opcodes +2 and +1 which cause it to accept the returned (x,y)
-    coordinates but not consider them as one end of a crossing segment
-    for labelling world coordinate 1, 2, or both.
-
-  - PGSBOX now takes care not to lose vertical tick marks (and hence
-    labels) at the left or right edge of the frame.  Likewise for
-    horizontal tick marks at the top or bottom edge of the frame.
-
-  - Tightened up the test in PGSBOX for cycles in angle to catch the
-    case where the coordinate value spans a full 360 degrees.
-
-  - PGSBOX will no longer accept frame crossings that are too oblique;
-    floating point rounding errors may cause grid lines that should
-    otherwise track along the frame to weave down it from side-to-side
-    resulting in spurious crossing points.
-
-  - Fixed a bug in pgwcsl_() for processing simple linear coordinates.
-
-  - pgwcsl_() now returns error -2 if the latitude is outside -90 to +90
-    for opcodes +2 and +1.
-
-  - Amended the translation of status return codes from WCSLIB in
-    pgwcsl_().
-
-  - Provided a header file for pgwcsl_() (mainly for C++ usage).
-
-  - Added extra test plots to PGTEST and cpgtest.
-
-  - Added extra functionality to the Makefile.
-
-
-WCSLIB version 3.2 (2003/09/09)
--------------------------------
-
-* C library
-
-  - Added the facility of setting the flag member of a wcsprm struct to
-    -1 before calling wcsini() for the first time in order to initialize
-    memory management.  Likewise for linprm and linini().
-
-  - Renamed wcscpy() to wcscopy() to avoid a conflict with the Posix
-    "wide character string" function of the same name (wchar.h).  In
-    particular, this is used by the GNU C++ string class.
-
-  - The higher level functions (wcs, cel, spc) no longer return
-    prematurely if some of the input coordinate values are invalid.
-
-  - All functions now test whether a null pointer for the particular
-    struct (wcsprm, celprm, etc.) has been passed to them.
-
-  - Function return codes have been rationalized into a consistent set
-    within each of the wcs, cel, lin, prj, spc, and spx suites of
-    functions.  Error messages to match these error codes are now
-    encoded in a single character array, e.g. wcs_errmsg and prj_errmsg,
-    instead of a separate array for each function.  Macro definitions
-    for the older character arrays (e.g. wcsini_errmsg) have been
-    provided for backward compatibility.
-
-  - Declared prj_stat as extern in prj.h.
-
-* Fortran wrappers
-
-  - (No changes.)
-
-* PGSBOX
-
-  - Added an ENTRY point, PGLBOX, that provides a simplified interface
-    to PGSBOX for linear axes without having to specify an NLFUNC or the
-    associated parameters.
-
-
-WCSLIB version 3.1 (2003/04/29)
--------------------------------
-
-* C library
-
-  - Added "global" and "divergent" prjprm struct informational members
-    to record whether the projection is capable of mapping the whole
-    sphere, and whether it is divergent in latitude.
-
-  - Function cylfix() provided to fix WCS FITS header cards for
-    malformed cylindrical projections (c.f. Paper II, Sect. 7.3.4).
-
-  - Added support for CUNITi cards to wcsprm (but not currently
-    implemented).
-
-  - Added macro implementations of the trigd functions to wcstrig.h,
-    enabled if WCSTRIG_MACRO is defined.
-
-  - Improved printing of the WCSLIB structs.
-
-  - Added macro definitions for the lengths of the WCSLIB structs
-    measured in sizeof(int) units (mainly for the FORTRAN wrappers).
-
-* Fortran wrappers
-
-  - FORTRAN is now supported via a set of wrappers on the C library.
-    Refer to the README file.
-
-* PGSBOX
-
-
-
-WCSLIB version 3.0 beta release (2003/04/01)
---------------------------------------------
-
-* C library
-
-  - Fully vectorized function interfaces (C preprocessor macros are
-    available to implement the scalar interfaces of the proj.c, sph.c,
-    and lin.c routines from WCSLIB 2.x).
-
-  - Implementation of Paper II, Sect. 2.5: User-specified
-    (phi0, theta0).
-
-  - Implementation of Paper III (excluding "-TAB").
-
-  - Memory management is now implemented in the upper-level (wcs.c)
-    routines.
-
-  - New extensible design should accomodate Paper IV (and any other)
-    without further change to the function interfaces.
-
-* PGSBOX
-
-  - Added a C wrapper function, cpgsbox(), and C test/demo program,
-    cpgtest, that duplicates PGTEST and serves as a C coding template.
-
-  - Added calendar date axes.
-
-  - Sped up the max/min search - if only tickmarks are required there is
-    no need to search the interior of the image.
-
-  - Return margin widths in CACHE(,NC).
-
-  - Fixed a buglet that caused ticks at the frame edges to be skipped.
-
-  - Return error 3 if CACHE overflows.
-
-  - Adapted PGWCSL for WCSLIB 3.x - it is now a C function (for
-    interfacing to WCSLIB) with a FORTRAN-like interface (for PGSBOX).
-
-
-WCSLIB version 2.9 (2002/04/03)
--------------------------------
-
-* C library
-
-  - Fixed a bug with alias translation in wcsset().
-
-  - Added a conditional compilation directive to lin.c for Apple's
-    MacOS X.
-
-* Fortran library
-
-  - Fixed CUBEFACE handling in WCSSET.
-
-
-WCSLIB version 2.8 (2001/11/16)
--------------------------------
-
-* C library
-
-  - Added support for the SZP projection with szpset(), szpfwd() and
-    szprev(), and generalized AZP with support for the tilt parameter,
-    gamma.
-
-  - Added phi0 to the prjprm struct, this is set by the projection
-    initialization routines along with theta0.
-
-  - Fixed a problem in wcsmix() caused by numerical imprecision that
-    could cause it not to recognize when convergence was reached; break
-    out of the loop early if a discontinuity is detected.
-
-  - Clarified the usage of vspan in the prologue to wcsmix().
-
-  - Fixed comments relating to LATPOLE in the prologue to cel.c and
-    tcel.c, and replaced references to LONGPOLE with LONPOLE.
-
-  - Augmented the error reports in twcs2.
-
-  - Modified projex() in tproj1 and prjplt() in tproj2 to make use of
-    the information stored in the prjprm struct.
-
-* Fortran library
-
-  - Added support for the SZP projection with SZPSET, SZPFWD and SZPREV,
-    and generalized AZP with support for the tilt parameter, gamma.
-
-  - Changed the call sequence to PRJSET to return PHI0 along with
-    THETA0.
-
-  - Fixed a problem in WCSMIX caused by numerical imprecision that could
-    cause it not to recognize when convergence was reached; break out of
-    the loop early if a discontinuity is detected.
-
-  - Clarified the usage of VSPAN in the prologue to WCSMIX.
-
-  - Fixed comments relating to LATPOLE in the prologue to CEL and TCEL,
-    and replaced references to LONGPOLE with LONPOLE.
-
-  - Augmented the error reports in TWCS2.
-
-  - Modified PROJEX in TPROJ1 and PRJPLT in TPROJ2 to use the generic
-    driver routines PRJSET, PRJFWD and PRJREV.  PRJPLT also now uses the
-    projection type encoded in PRJ(11).
-
-
-WCSLIB version 2.7 (2001/02/19)
--------------------------------
-
-* C library
-
-  - Added generic driver routines prjset(), prjfwd() and prjrev().
-    These invoke specific projection routines via the pointer-to-
-    function elements, prjfwd and prjrev, transferred to the prjprm
-    struct from celprm.
-
-  - Added code (3-letter projection code) and theta0 (reference
-    latitude) elements to prjprm.
-
-  - The projection code for the Sanson-Flamsteed projection is now SFL.
-    The upper-level routines, wcsset(), wcsfwd(), and wcsrev(),
-    recognize GLS as an alias for this.
-
-  - wcsset() now recognizes 'xyLN/xyLT' axis pairs.
-
-  - Two bugs in the translation from NCP to SIN in wcsfwd() and wcsrev()
-    were fixed: (1) the projection parameter was computed incorrectly
-    and (2) they did not honour prj->flag set to -1 to disable strict
-    bounds checking.
-
-  - A bug in wcsmix() was fixed - it was relying on the wcsprm struct to
-    have been initialized beforehand.
-
-  - The test programs now use the cpgplot interface to PGPLOT, the old
-    tpgc.c and tpgf.f wrappers have been removed.
-
-* Fortran library
-
-  - Added generic driver routines PRJSET, PRJFWD and PRJREV.  These are
-    keyed to specific projection routines via the value of PRJ(11) which
-    now differs for each projection.
-
-  - The projection code for the Sanson-Flamsteed projection is now SFL.
-    The upper-level routines, WCSSET, WCSFWD, and WCSREV, recognize GLS
-    as an alias for this.
-
-  - WCSSET now recognizes 'xyLN/xyLT' axis pairs.
-
-  - A bug in the translation from NCP to SIN in WCSFWD and WCSREV was
-    fixed; they did not honour PRJ(11) set to -1 to disable strict
-    bounds checking.
-
-  - A bug in WCSMIX was fixed - it was relying on the WCS array to have
-    been initialized beforehand.
-
-
-WCSLIB version 2.6 (2000/05/10)
--------------------------------
-
-* C library
-
-  - Check for invalid (x,y) in zearev().
-
-  - In wcsmath.h, guard against prior definition of PI and other
-    preprocessor variables.
-
-* Fortran library
-
-  - Check for invalid (X,Y) in ZEAREV.
-
-  - Declare COSD and SIND in WCSFWD and WCSREV, reported by Clive Page
-    (cgp at star.le.ac.uk).
-
-
-WCSLIB version 2.5 (1999/12/14)
--------------------------------
-
-* C library
-
-  - Added copyright notice to header files and prefixed include guard
-    names with "WCSLIB_".
-
-  - Fixed cube face handling in wcsfwd() and wcsrev() (reported by
-    Doug Mink, CfA).  Allow more general face layout in the inverse
-    quadcube projections.
-
-  - Fixed the problem in wcsmix() where it failed to find a valid
-    solution when the solution point lay at a native pole of a
-    projection in which the pole is represented as a finite interval.
-    However, wcsmix() will only ever return one solution even when two
-    or more valid solutions may exist.
-
-  - wcsmix() now accepts viter in the range 5 - 10, the specified value
-    will be pushed up or down into this range if necessary.
-
-  - The projection routines for AZP, TAN, SIN, ZPN, and COP now return
-    error 2 if (phi,theta) correspond to the overlapped (far) side of
-    the projection.  This strict bounds checking can be switched off by
-    setting prj->flag to -1 (rather than 0) when the projections are
-    initialized.
-
-  - The upper level routines, wcsset(), wcsfwd(), wcsrev(), and
-    wcsmix(), now recognize the NCP projection and convert it to the
-    equivalent SIN projection.  The lower level routines do not
-    recognize NCP.
-
-  - Extracted definitions of mathematical constants (PI etc.) from
-    proj.h into wcsmath.h in order to avoid conflicts with their
-    definition in math.h in some systems (such as Linux).
-
-  - Describe the two alternate representations of the quadcube
-    projections (i.e. faces laid out or stacked) in the prologue of
-    wcs.c.
-
-* Fortran library
-
-  - Fixed cube face handling in WCSFWD and WCSREV, reported by Doug Mink
-    (dmink at cfa.harvard.edu).  Allow more general face layout in the
-    inverse quadcube projections.
-
-  - Fixed the problem in WCSMIX where it failed to find a valid solution
-    when the solution point lay at a native pole of a projection in
-    which the pole is represented as a finite interval.  However, WCSMIX
-    will only ever return one solution even when two or more valid
-    solutions may exist.
-
-  - WCSMIX now accepts VITER in the range 5 - 10, the specified value
-    will be pushed up or down into this range if necessary.
-
-  - The projection routines for AZP, TAN, SIN, ZPN, and COP now return
-    error 2 if (phi,theta) correspond to the overlapped (far) side of
-    the projection.  This strict bounds checking can be switched off by
-    setting PRJ(11) to -1 (rather than 0) when the projections are
-    initialized.
-
-  - The upper level routines, WCSSET, WCSFWD, WCSREV, and WCSMIX, now
-    recognize the NCP projection and convert it to the equivalent SIN
-    projection.  The lower level routines do not recognize NCP.
-
-  - Describe the two alternate representations of the quadcube
-    projections (i.e. faces laid out or stacked) in the prologue of
-    wcs.f.
-
-
-WCSLIB version 2.4 (1996/09/23)
--------------------------------
-
-* C library
-
-  - In sinrev(), cscrev(), qscrev(), and tscrev(), return error 2 if
-    (x,y) do not lie within the perimeter of the projection.  In
-    sinrev(), stop the computation of phi for the "synthesis" projection
-    being applied to the pure "orthographic" case (reported by
-    David Berry, STARLINK).
-
-  - (Internal change) Renamed variables l <-> m in the quadcube
-    projections to accord with standard usage (and revised WCS draft
-    paper).
-
-* Fortran library
-
-  - In SINREV, CSCREV, QSCREV, and TSCREV, return error 2 if (X,Y) do
-    not lie within the perimeter of the projection.  In SINREV, stop the
-    computation of PHI for the "synthesis" projection being applied to
-    the pure "orthographic" case.  Reported by David Berry
-    (dsb at ast.man.ac.uk).
-
-  - (Internal change) Renamed variables L <-> M in the quadcube
-    projections to accord with standard usage (and revised WCS draft
-    paper).
-
-  - (Internal change) Stopped PRJ(11) doing double service in any
-    projection.  It is now set and tested for a specific magic value
-    rather than simply being non-zero.
-
-
-WCSLIB version 2.3 (1996/06/24)
--------------------------------
-
-* C library
-
-  - Fixed two bugs in zpnset().  The first led to an incorrect
-    determination of the degree of the polynomial and would mainly have
-    affected the efficiency of zpnrev().  The second affected the
-    determination of the boundary of the projection but would only have
-    been significant for projections with a point of inflection between
-    9 and 10 degrees of the pole.  Reported by David Berry, STARLINK.
-
-  - Replaced usage of alloca() in lin.c with malloc() and free() for
-    portability as suggested by Klaus Banse, ESO (kbanse at eso.org).
-
-  - Allow for C implementations that provide their own versions of
-    cosd(), sind(), tand(), acosd(), asind(), atand(), and atan2d().
-    From Klaus Banse, ESO (kbanse at eso.org).
-
-  - Implemented the CUBEFACE axis for quadcube projections.
-
-  - Made all function prototypes const-correct.
-
-  - Adapted the header files to C++ usage.
-
-  - Added a new test program, twcs1, to verify closure of wcsfwd() and
-    wcsrev().  The old twcs test program is now called twcs2.
-
-  - Added external arrays of error messages indexed by function return
-    value.  For example, extern const char *wcsmix_errmsg[] for
-    wcsmix().  Messages for the many proj.c functions are in
-    prjfwd_errmsg[], etc.
-
-* Fortran library
-
-  - Implemented the CUBEFACE axis for quadcube projections.
-
-  - Added a new test program, TWCS1, to verify closure of WCSFWD and
-    WCSREV.  The old TWCS test program is now called TWCS2.
-
-
-WCSLIB version 2.2 (1996/01/18)
--------------------------------
-
-* C library
-
-  - Amended the projection equations for the conics (COP, COD, COE, COO)
-    and Bonne's projection (BON) to correctly handle southern hemisphere
-    projections with PROJP1 < 0 (reported by Lindsay Davis, NOAO).
-    Revised tproj1 and tproj2 to test such cases.
-
-* Fortran library
-
-  - Amended the projection equations for the conics (COP, COD, COE, COO)
-    and Bonne's projection (BON) to correctly handle southern hemisphere
-    projections with PROJP1 < 0 (reported by Lindsay Davis, NOAO).
-    Revised TPROJ1 and TPROJ2 to test such cases.
-
-  - Increased the dimension of the WCS array from WCS(0:2) to WCS(0:3)
-    to allow for future handling of the CUBEFACE keyword - WCS(3) will
-    store an index to the CUBEFACE axis.  This affects the call
-    sequences of WCSSET, WCSFWD, WCSREV, and WCSMIX.
-
-
-WCSLIB version 2.1 (1995/11/17)
--------------------------------
-
-* C library
-
-  The main change of interest to programmers is that of changed argument
-  lists for wcsfwd() and wcsrev() as described below.
-
-  - The WCS linear transformations are now implemented in WCSLIB,
-    complete with matrix inverter.  The new files are lin.c, lin.h, and
-    test program tlin.c.
-
-  - Given either the celestial longitude or latitude plus an element of
-    the pixel coordinate a new routine, wcsmix(), solves for the
-    remaining elements by iterating on the unknown celestial coordinate
-    element using wcsfwd().
-
-  - The high level driver routines wcsfwd(), wcsrev(), and wcsmix() now
-    apply the full WCS algorithm chain (except for pixel regularization
-    table), including parsing the CTYPEn header cards and computing non-
-    celestial elements of the world coordinate.  This required a change
-    to their argument lists which now more closely reflect the sequence
-    of algorithms applied.  A new routine, wcsset(), parses the CTYPEn.
-
-  - The high level driver routines of WCSLIB 1.0 are available as
-    intermediate level drivers celset(), celfwd(), and celrev(), but
-    note that their argument lists have been extended to return native
-    coordinates.  The related struct is now called celprm instead of
-    wcsprm.
-
-  - The reference point for conic projections is now at the midpoint of
-    the standard parallels.  The FITS header cards PROJP1 and PROJP2 now
-    give the half-sum (midpoint) and half-difference of the latitudes of
-    the standard parallels; previously they gave the latitudes of the
-    standard parallels themselves.  The change is reflected in this
-    release of WCSLIB.
-
-  - A bug in celset() (formerly wcsset()) that misapplied WCS draft
-    equations 7 has been fixed (thanks to Rick Ebert IPAC/JPL and
-    Lindsey Davis, NOAO for reporting this).  This affected the
-    computation of Euler angles for the celestial coordinate
-    transformation for those projections that have their reference point
-    away from the native pole.  In investigating this a deficiency with
-    the formalism was discovered that led to the introduction of a
-    LATPOLE FITS header card which may be used to disambiguate where
-    CRVAL1, CRVAL2, and LONGPOLE do not uniquely determine the latitude
-    of the native pole.  The celprm struct (formerly wcsprm) has been
-    extended to accomodate LATPOLE.
-
-  - Default values of LONGPOLE and LATPOLE are now supported and their
-    use is recommended where appropriate.
-
-  - Numerical precision was being lost near the native poles in the SIN,
-    AIR, and QSC projections and this has been recovered (reported by
-    Lindsey Davis, NOAO).  Floating underflows in CSC are now avoided.
-
-  - Numerical precision was also lost in certain circumstances in the
-    spherical coordinate transformation routines and this has been
-    fixed.
-
-  - The test programs have been enhanced in various ways and the library
-    has been validated on an SGI machine using both 32-bit and 64-bit
-    compilers.
-
-* Fortran library
-
-  The main change of interest to programmers is that of changed call
-  sequences for WCSFWD and WCSREV as described below.
-
-  - The WCS linear transformations are now implemented in WCSLIB,
-    complete with matrix inverter.  The new files are lin.f and test
-    program tlin.f.
-
-  - Given either the celestial longitude or latitude plus an element of
-    the pixel coordinate a new routine, WCSMIX, solves for the remaining
-    elements by iterating on the unknown celestial coordinate element
-    using WCSFWD.
-
-  - The high level driver routines WCSFWD, WCSREV, and WCSMIX now apply
-    the full WCS algorithm chain (except for pixel regularization
-    table), including parsing the CTYPEn header cards and computing non-
-    celestial elements of the world coordinate.  This required a change
-    to their call sequences which now more closely reflect the sequence
-    of algorithms applied.  A new routine, WCSSET, parses the CTYPEn.
-
-  - The high level driver routines of WCSLIB 1.0 are available as
-    intermediate level drivers CELSET, CELFWD, and CELREV, but note
-    that their call sequences have been extended to return native
-    coordinates.  The related parameter array is now called CEL instead
-    of WCS.
-
-  - The reference point for conic projections is now at the midpoint of
-    the standard parallels.  The FITS header cards PROJP1 and PROJP2 now
-    give the half-sum (midpoint) and half-difference of the latitudes of
-    the standard parallels; previously they gave the latitudes of the
-    standard parallels themselves.  The change is reflected in this
-    release of WCSLIB.
-
-  - A bug in CELSET (formerly WCSSET) that misapplied WCS draft
-    equations 7 has been fixed (thanks to Rick Ebert IPAC/JPL and
-    Lindsey Davis, NOAO for reporting this).  This affected the
-    computation of Euler angles for the celestial coordinate
-    transformation for those projections that have their reference point
-    away from the native pole.  In investigating this a deficiency with
-    the formalism was discovered that led to the introduction of a
-    LATPOLE FITS header card which may be used to disambiguate where
-    CRVAL1, CRVAL2, and LONGPOLE do not uniquely determine the latitude
-    of the native pole.  The CEL parameter array (formerly WCS) has been
-    extended to accomodate LATPOLE as CEL(4), and the flag variable is
-    now CEL(5) (formerly WCS(4)).
-
-  - Default values of LONGPOLE and LATPOLE are now supported and their
-    use is recommended where appropriate.
-
-  - Numerical precision was being lost near the native poles in the SIN,
-    AIR, and QSC projections and this has been recovered (reported by
-    Lindsey Davis, NOAO).  Floating underflows in CSC are now avoided.
-
-  - Numerical precision was also lost in certain circumstances in the
-    spherical coordinate transformation routines and this has been
-    fixed.
-
-  - The test programs have been enhanced in various ways and the
-    library has been validated on an SGI machine using both 32-bit and
-    64-bit compilers.
-
-
-WCSLIB version 1.0 (1995/01/31)
--------------------------------
-
-* C library
-
-  Initial release.
-
-* Fortran library
-
-  Initial release.
-
-------------------------------------------------------------------------
-$Id: CHANGES,v 4.10 2012/02/05 23:41:45 cal103 Exp $
diff --git a/astropy/wcs/src/wcslib/GNUmakefile b/astropy/wcs/src/wcslib/GNUmakefile
deleted file mode 100644
index 4b737ff..0000000
--- a/astropy/wcs/src/wcslib/GNUmakefile
+++ /dev/null
@@ -1,200 +0,0 @@
-#-----------------------------------------------------------------------------
-# GNU makefile for building WCSLIB 4.10
-#
-# Summary of the main targets
-# ---------------------------
-#   all:       Do 'make all' in each subdirectory (excluding ./doxygen).
-#   check:     Do 'make check' in each subdirectory (compile and run tests).
-#   tests:     Do 'make tests' in each subdirectory (compile test programs but
-#              don't run them).
-#   install:   Do 'make install' in each subdirectory.
-#   clean:     Recursively delete intermediate files produced as part of the
-#              build, e.g. object modules, core dumps, etc.
-#   cleaner:   Recursively clean, and also delete test executables, test
-#              input and output, and intermediates produced in compiling the
-#              programmers' manual.
-#   distclean (or realclean): Recursively delete all platform-dependent files
-#              generated during the build, preserving only the programmers'
-#              manual and man pages (which are normally provided pre-built).
-#              It is the one to use between builds for multiple platforms.
-#   cleanest:  Like distclean, but deletes everything that can be regenerated
-#              from the source files, including the programmers' manual and
-#              man pages, but excluding 'configure'.
-#   show:      Print the values of important variables used in this and the
-#              other makefiles.
-#   writable:  Run chmod recursively to make all sources writable.
-#
-# Notes:
-#   1) If you need to make changes then preferably modify makedefs.in instead.
-#
-#   2) Refer also to the makefiles in subdirectories, particularly
-#      C/GNUmakefile.
-#
-# Author: Mark Calabretta, Australia Telescope National Facility
-# http://www.atnf.csiro.au/~mcalabre/index.html
-# $Id: GNUmakefile,v 4.10 2012/02/05 23:41:45 cal103 Exp $
-#-----------------------------------------------------------------------------
-# Get configure settings.
-include makedefs
-
-ifeq "$(CHECK)" "nopgplot"
-  TSTDIRS := $(filter-out pgsbox,$(TSTDIRS))
-endif
-
-.PHONY : build check chmod clean cleaner cleanest distclean install \
-         realclean show tests writable
-
-build :
-	-@ for DIR in $(SUBDIRS) ; do \
-	     echo '' ; \
-	     $(TIMER) ; \
-	     $(MAKE) -k -C $$DIR build ; \
-	   done
-
-check tests :: show
-	-@ echo ''
-	-@ $(TIMER)
-	 @ for DIR in $(SUBDIRS) ; do \
-	     echo '' ; \
-	     $(MAKE) -i -C $$DIR cleaner ; \
-	   done
-	-@ echo ''
-	 @ for DIR in $(TSTDIRS) ; do \
-	     echo '' ; \
-	     $(TIMER) ; \
-	     $(MAKE) -k -C $$DIR $@ ; \
-	   done
-
-check ::
-	-@ echo ''
-	-@ echo 'Summary of results for non-graphical tests'
-	-@ echo '------------------------------------------'
-	-@ cat ./*/test_results
-	 @ if grep 'FAIL:' ./*/test_results > /dev/null ; then \
-	     exit 1 ; \
-	   else \
-	     exit 0 ; \
-	   fi
-
-install :
-	 @ for DIR in $(INSTDIR) ; do \
-	     $(MAKE) -k -C $$DIR $@ ; \
-	   done
-	   $(INSTALL) -m 444 wcsconfig.h wcsconfig_f77.h $(INCDIR)
-	-  if [ ! -d "$(DOCDIR)" ] ; then \
-	     $(INSTALL) -d -m 2775 $(DOCDIR) ; \
-	   fi
-	   $(INSTALL) -m 444 CHANGES COPYING* README $(DOCDIR)
-	-  if [ ! -d "$(PDFDIR)" ] ; then \
-	     $(INSTALL) -d -m 2775 $(PDFDIR) ; \
-	   fi
-	   $(INSTALL) -m 444 wcslib.pdf $(PDFDIR)
-	-  if [ ! -d "$(HTMLDIR)/html" ] ; then \
-	     $(INSTALL) -d -m 2775 $(HTMLDIR)/html ; \
-	   fi
-	   $(INSTALL) -m 444 html/* $(HTMLDIR)/html
-	   if [ ! -d "$(LIBDIR)/pkgconfig" ] ; then \
-	     $(INSTALL) -d -m 2775 $(LIBDIR)/pkgconfig ; \
-	   fi
-	   $(INSTALL) -m 444 wcslib.pc $(LIBDIR)/pkgconfig/wcslib.pc
-
-clean cleaner :
-	   for DIR in $(SUBDIRS) doxygen ; do \
-	     $(MAKE) -C $$DIR $@ ; \
-	   done
-
-cleanest distclean realclean :
-	   for DIR in $(SUBDIRS) doxygen ; do \
-	     $(MAKE) -C $$DIR $@ ; \
-	   done
-	-  $(RM) *.log
-	-  $(RM) -r autom4te.cache autoscan.log
-	-  $(RM) confdefs.h conftest.*
-	-  $(RM) config.log config.status configure.lineno
-	-  $(RM) makedefs wcslib.pc
-	-  $(RM) wcsconfig.h wcsconfig_*.h
-	-  $(RM) wcslib-*.tar.gz
-
-show ::
-	-@ echo 'Subdirectories to be built...'
-	-@ echo '  SUBDIRS     := $(SUBDIRS)'
-	-@ echo '  TSTDIRS     := $(TSTDIRS)'
-	-@ echo ''
-
-writable :
-	  chmod -R u+w .
-
-GNUmakefile : makedefs ;
-
-makedefs : makedefs.in config.status
-	-@ echo ''
-	-@ $(TIMER)
-	   ./config.status
-
-config.status : configure
-	-@ echo ''
-	-@ $(TIMER)
-	-@ echo ''
-	-@ echo "Environment variables that affect 'configure':"
-	-@ echo "  CC       = $${CC-(undefined)}"
-	-@ echo "  CFLAGS   = $${CFLAGS-(undefined)}"
-	-@ echo "  CPP      = $${CPP-(undefined)}"
-	-@ echo "  CPPFLAGS = $${CPPFLAGS-(undefined)}"
-	-@ echo "  F77      = $${F77-(undefined)}"
-	-@ echo "  FFLAGS   = $${FFLAGS-(undefined)}"
-	-@ echo "  LDFLAGS  = $${LDFLAGS-(undefined)}"
-	-@ echo ''
-	   ./configure --no-create
-
-
-#-----------------------------------------------------------------------------
-# These are for code management.
-
-.PHONY : dist
-
-dist :
-	   $(MAKE) -C doxygen cleanest build
-	   $(MAKE) -C utils man
-	   $(MAKE) distclean
-	-@ echo $(WCSLIBPKG)/C/RCS        >  wcslib.X
-	-@ echo $(WCSLIBPKG)/C/flexed/RCS >> wcslib.X
-	-@ echo $(WCSLIBPKG)/C/test/RCS   >> wcslib.X
-	-@ echo $(WCSLIBPKG)/doxygen/RCS  >> wcslib.X
-	-@ echo $(WCSLIBPKG)/Fortran/RCS  >> wcslib.X
-	-@ echo $(WCSLIBPKG)/Fortran/test/RCS >> wcslib.X
-	-@ echo $(WCSLIBPKG)/makedefs     >> wcslib.X
-	-@ echo $(WCSLIBPKG)/other        >> wcslib.X
-	-@ echo $(WCSLIBPKG)/pgsbox/RCS   >> wcslib.X
-	-@ echo $(WCSLIBPKG)/RCS          >> wcslib.X
-	-@ echo $(WCSLIBPKG)/TODO         >> wcslib.X
-	-@ echo $(WCSLIBPKG)/utils/RCS    >> wcslib.X
-	-@ echo $(WCSLIBPKG)/wcslib.T     >> wcslib.X
-	-@ echo $(WCSLIBPKG)/wcslib.X     >> wcslib.X
-	   rm -f $(WCSLIBPKG).tar.bz2
-	   tar cf - -C .. -X wcslib.X $(WCSLIBPKG) | \
-	     tar t | \
-	     grep -v '/$$' | \
-	     sort > wcslib.T
-	   rm -f wcslib.X
-	   tar cvf $(WCSLIBPKG).tar -C .. -T wcslib.T
-	   rm -f wcslib.T
-	   bzip2 $(WCSLIBPKG).tar
-	   chmod 444 $(WCSLIBPKG).tar.bz2
-
-install_dist :
-	   cp -fp $(WCSLIBPKG).tar.bz2 /nfs/ftp/software/wcslib/
-	   mv -f  $(WCSLIBPKG).tar.bz2 ../wcslib-releases/
-	   (cd /nfs/ftp/software/wcslib/ && \
-	     rm -f wcslib.tar.bz2 && \
-	     ln -s $(WCSLIBPKG).tar.bz2 wcslib.tar.bz2)
-	   cp -fp CHANGES wcslib.pdf ~/public_html/WCS/
-	   rsync --archive --delete html/ ~/public_html/WCS/wcslib/
-
-configure : configure.ac
-	-@ echo ''
-	-@ $(TIMER)
-	   autoconf
-
-# Code development overrides must be included specifically before 'configure'
-# generates makedefs.
--include flavours
diff --git a/astropy/wcs/src/wcslib/INSTALL b/astropy/wcs/src/wcslib/INSTALL
deleted file mode 100644
index d3f907c..0000000
--- a/astropy/wcs/src/wcslib/INSTALL
+++ /dev/null
@@ -1,327 +0,0 @@
-------------------------------------------------------------------------------
-WCSLIB 4.10 and PGSBOX 4.10 INSTALLATION
---------------------------------------
-
-WCSLIB requires an ANSI C compiler with standard ANSI C environment, that is,
-a standard C library and header files as defined in Appendix B of Kernigan &
-Ritchie, 2nd ed.
-
-Installation of WCSLIB is handled by GNU autoconf; GNU make (referred to here
-as 'gmake') must be used.  The WCSLIB distribution also includes PGSBOX (refer
-to the README file), to unpack it type
-
-  zcat wcslib-4.10.tar.gz | tar pvxf -
-  cd wcslib-4.10
-
-then if you do not need to specify any configuration options, simply run
-
-  gmake
-
-This will run 'configure' to generate "makedefs" which is included by the top-
-level GNUmakefile and those in each subdirectory, and then build 'libwcs.a',
-which includes both the C library and Fortran wrappers, and also libpgsbox.a.
-
-(WARNING: The build may fail with gmake 3.79, upgrade to 3.79.1 or later.)
-
-configure tries to determine the location of the PGPLOT and CFITSIO libraries
-required by some programs in the test suite.  If it fails to find them you
-can, if you wish, tailor the few variables found at the start of "makedefs".
-Of course you do not need to exercise the test suite in order to build and
-install the library - if configure fails to find anything required for that it
-will issue an explicit error message.
-
-To build and exercise the test suite use
-
-  gmake check
-
-To install the object libraries and header files, do
-
-  gmake install
-
-
-TWEAKING THE INSTALLATION DEFAULTS
-----------------------------------
-
-By default the library and header files are installed in the lib and include
-subdirectories of /usr/local/.  To change this, or any other options, run
-configure separately before gmake:
-
-  ./configure --prefix=/some/other/dir
-  gmake
-
-Use
-
-  ./configure --help
-
-to list configure's options.  Useful options are
-
-  --with-pgplotinc
-  --with-pgplotlib
-  --with-cfitsioinc
-  --with-cfitsiolib
-
-Which allow additional directories to be added to the library and include
-file search path.
-
-Installation of WCSLIB differs a little from most packages in that all
-configurable makefile variables are defined in a single file, "makedefs",
-which configure generates from "makedefs.in".  If you need to redefine any of
-the makefile variables you can modify makedefs, or preferably makedefs.in.
-The makefile will automatically detect this and re-run config.status to
-re-generate a new makedefs.  configure also creates four header files:
-
-  wcsconfig.h: Contains general purpose preprocessor definitions.  It is
-    included by the other wcsconfig header files.
-
-  wcsconfig_f77.h: By common convention the WCSLIB Fortran wrappers have
-    been written (in C) using function names in lower case with an
-    underscore ("_") suffix.  wcsconfig_f77.h defines a preprocessor macro,
-    F77_FUNC(name,NAME), that may redefine these to suit different name
-    mangling schemes used by some Fortran compilers.
-
-  wcsconfig_tests.h: Contains C preprocessor definitions for compiling the
-    test/demo programs.
-
-  wcsconfig_utils.h: Contains C preprocessor macro definitions for compiling
-    the utility programs provided with WCSLIB.
-
-If you do have trouble building the library please send me config.log.
-
-
-The INSTALL file provided with GNU autoconf 2.53 is appended without change.
-
-
-Author: Mark Calabretta, Australia Telescope National Facility
-http://www.atnf.csiro.au/~mcalabre/index.html
-$Id: INSTALL,v 4.10 2012/02/05 23:41:45 cal103 Exp $
-
-==============================================================================
-
-Copyright 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software
-Foundation, Inc.
-
-   This file is free documentation; the Free Software Foundation gives
-unlimited permission to copy, distribute and modify it.
-
-Basic Installation
-==================
-
-   These are generic installation instructions.
-
-   The `configure' shell script attempts to guess correct values for
-various system-dependent variables used during compilation.  It uses
-those values to create a `Makefile' in each directory of the package.
-It may also create one or more `.h' files containing system-dependent
-definitions.  Finally, it creates a shell script `config.status' that
-you can run in the future to recreate the current configuration, and a
-file `config.log' containing compiler output (useful mainly for
-debugging `configure').
-
-   It can also use an optional file (typically called `config.cache'
-and enabled with `--cache-file=config.cache' or simply `-C') that saves
-the results of its tests to speed up reconfiguring.  (Caching is
-disabled by default to prevent problems with accidental use of stale
-cache files.)
-
-   If you need to do unusual things to compile the package, please try
-to figure out how `configure' could check whether to do them, and mail
-diffs or instructions to the address given in the `README' so they can
-be considered for the next release.  If you are using the cache, and at
-some point `config.cache' contains results you don't want to keep, you
-may remove or edit it.
-
-   The file `configure.ac' (or `configure.in') is used to create
-`configure' by a program called `autoconf'.  You only need
-`configure.ac' if you want to change it or regenerate `configure' using
-a newer version of `autoconf'.
-
-The simplest way to compile this package is:
-
-  1. `cd' to the directory containing the package's source code and type
-     `./configure' to configure the package for your system.  If you're
-     using `csh' on an old version of System V, you might need to type
-     `sh ./configure' instead to prevent `csh' from trying to execute
-     `configure' itself.
-
-     Running `configure' takes awhile.  While running, it prints some
-     messages telling which features it is checking for.
-
-  2. Type `make' to compile the package.
-
-  3. Optionally, type `make check' to run any self-tests that come with
-     the package.
-
-  4. Type `make install' to install the programs and any data files and
-     documentation.
-
-  5. You can remove the program binaries and object files from the
-     source code directory by typing `make clean'.  To also remove the
-     files that `configure' created (so you can compile the package for
-     a different kind of computer), type `make distclean'.  There is
-     also a `make maintainer-clean' target, but that is intended mainly
-     for the package's developers.  If you use it, you may have to get
-     all sorts of other programs in order to regenerate files that came
-     with the distribution.
-
-Compilers and Options
-=====================
-
-   Some systems require unusual options for compilation or linking that
-the `configure' script does not know about.  Run `./configure --help'
-for details on some of the pertinent environment variables.
-
-   You can give `configure' initial values for variables by setting
-them in the environment.  You can do that on the command line like this:
-
-     ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix
-
-   *Note Defining Variables::, for more details.
-
-Compiling For Multiple Architectures
-====================================
-
-   You can compile the package for more than one kind of computer at the
-same time, by placing the object files for each architecture in their
-own directory.  To do this, you must use a version of `make' that
-supports the `VPATH' variable, such as GNU `make'.  `cd' to the
-directory where you want the object files and executables to go and run
-the `configure' script.  `configure' automatically checks for the
-source code in the directory that `configure' is in and in `..'.
-
-   If you have to use a `make' that does not support the `VPATH'
-variable, you have to compile the package for one architecture at a
-time in the source code directory.  After you have installed the
-package for one architecture, use `make distclean' before reconfiguring
-for another architecture.
-
-Installation Names
-==================
-
-   By default, `make install' will install the package's files in
-`/usr/local/bin', `/usr/local/man', etc.  You can specify an
-installation prefix other than `/usr/local' by giving `configure' the
-option `--prefix=PATH'.
-
-   You can specify separate installation prefixes for
-architecture-specific files and architecture-independent files.  If you
-give `configure' the option `--exec-prefix=PATH', the package will use
-PATH as the prefix for installing programs and libraries.
-Documentation and other data files will still use the regular prefix.
-
-   In addition, if you use an unusual directory layout you can give
-options like `--bindir=PATH' to specify different values for particular
-kinds of files.  Run `configure --help' for a list of the directories
-you can set and what kinds of files go in them.
-
-   If the package supports it, you can cause programs to be installed
-with an extra prefix or suffix on their names by giving `configure' the
-option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
-
-Optional Features
-=================
-
-   Some packages pay attention to `--enable-FEATURE' options to
-`configure', where FEATURE indicates an optional part of the package.
-They may also pay attention to `--with-PACKAGE' options, where PACKAGE
-is something like `gnu-as' or `x' (for the X Window System).  The
-`README' should mention any `--enable-' and `--with-' options that the
-package recognizes.
-
-   For packages that use the X Window System, `configure' can usually
-find the X include and library files automatically, but if it doesn't,
-you can use the `configure' options `--x-includes=DIR' and
-`--x-libraries=DIR' to specify their locations.
-
-Specifying the System Type
-==========================
-
-   There may be some features `configure' cannot figure out
-automatically, but needs to determine by the type of machine the package
-will run on.  Usually, assuming the package is built to be run on the
-_same_ architectures, `configure' can figure that out, but if it prints
-a message saying it cannot guess the machine type, give it the
-`--build=TYPE' option.  TYPE can either be a short name for the system
-type, such as `sun4', or a canonical name which has the form:
-
-     CPU-COMPANY-SYSTEM
-
-where SYSTEM can have one of these forms:
-
-     OS KERNEL-OS
-
-   See the file `config.sub' for the possible values of each field.  If
-`config.sub' isn't included in this package, then this package doesn't
-need to know the machine type.
-
-   If you are _building_ compiler tools for cross-compiling, you should
-use the `--target=TYPE' option to select the type of system they will
-produce code for.
-
-   If you want to _use_ a cross compiler, that generates code for a
-platform different from the build platform, you should specify the
-"host" platform (i.e., that on which the generated programs will
-eventually be run) with `--host=TYPE'.
-
-Sharing Defaults
-================
-
-   If you want to set default values for `configure' scripts to share,
-you can create a site shell script called `config.site' that gives
-default values for variables like `CC', `cache_file', and `prefix'.
-`configure' looks for `PREFIX/share/config.site' if it exists, then
-`PREFIX/etc/config.site' if it exists.  Or, you can set the
-`CONFIG_SITE' environment variable to the location of the site script.
-A warning: not all `configure' scripts look for a site script.
-
-Defining Variables
-==================
-
-   Variables not defined in a site shell script can be set in the
-environment passed to `configure'.  However, some packages may run
-configure again during the build, and the customized values of these
-variables may be lost.  In order to avoid this problem, you should set
-them in the `configure' command line, using `VAR=value'.  For example:
-
-     ./configure CC=/usr/local2/bin/gcc
-
-will cause the specified gcc to be used as the C compiler (unless it is
-overridden in the site shell script).
-
-`configure' Invocation
-======================
-
-   `configure' recognizes the following options to control how it
-operates.
-
-`--help'
-`-h'
-     Print a summary of the options to `configure', and exit.
-
-`--version'
-`-V'
-     Print the version of Autoconf used to generate the `configure'
-     script, and exit.
-
-`--cache-file=FILE'
-     Enable the cache: use and save the results of the tests in FILE,
-     traditionally `config.cache'.  FILE defaults to `/dev/null' to
-     disable caching.
-
-`--config-cache'
-`-C'
-     Alias for `--cache-file=config.cache'.
-
-`--quiet'
-`--silent'
-`-q'
-     Do not print messages saying which checks are being made.  To
-     suppress all normal output, redirect it to `/dev/null' (any error
-     messages will still be shown).
-
-`--srcdir=DIR'
-     Look for the package's source code in directory DIR.  Usually
-     `configure' can determine that directory automatically.
-
-`configure' also accepts some other, not widely useful, options.  Run
-`configure --help' for more details.
-
diff --git a/astropy/wcs/src/wcslib/README b/astropy/wcs/src/wcslib/README
deleted file mode 100644
index 44262c1..0000000
--- a/astropy/wcs/src/wcslib/README
+++ /dev/null
@@ -1,51 +0,0 @@
-------------------------------------------------------------------------------
-                         WCSLIB 4.10 and PGSBOX 4.10
-------------------------------------------------------------------------------
-    WCSLIB 4.10 - an implementation of the FITS WCS standard.
-    Copyright (C) 1995-2012, Mark Calabretta
-
-    This file is part of WCSLIB.
-
-    WCSLIB is free software: you can redistribute it and/or modify it under
-    the terms of the GNU Lesser General Public License as published by the
-    Free Software Foundation, either version 3 of the License, or (at your
-    option) any later version.
-
-    WCSLIB 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 Lesser General Public License for
-    more details.
-
-    You should have received a copy of the GNU Lesser General Public License
-    along with WCSLIB.  If not, see <http://www.gnu.org/licenses/>.
-
-    Correspondence concerning WCSLIB may be directed to:
-       Internet email: mcalabre at atnf.csiro.au
-       Postal address: Dr. Mark Calabretta
-                       Australia Telescope National Facility, CSIRO
-                       PO Box 76
-                       Epping NSW 1710
-                       AUSTRALIA
-------------------------------------------------------------------------------
-
-Please refer to
-
-  ./INSTALL		...Installation instructions.
-
-  ./html/index.html	...The WCSLIB programmer's manual in HTML format.
-  ./wcslib.pdf		...The WCSLIB programmer's manual in PDF format.
-
-  ./CHANGES		...Log of changes made to WCSLIB.
-
-  ./THANKS		...List of contributors to WCSLIB.
-
-  ./VALIDATION		...List of platforms on which the installation
-			   procedures and test suite were exercised.
-
-  ./COPYING		...A copy of the GNU General Public License, v3.0.
-  ./COPYING.LESSER	...A copy of the Lesser GNU General Public License.
-
-
-Author: Mark Calabretta, Australia Telescope National Facility
-http://www.atnf.csiro.au/~mcalabre/index.html
-$Id: README,v 4.10 2012/02/05 23:41:45 cal103 Exp $
diff --git a/astropy/wcs/src/wcslib/THANKS b/astropy/wcs/src/wcslib/THANKS
deleted file mode 100644
index d73f5b7..0000000
--- a/astropy/wcs/src/wcslib/THANKS
+++ /dev/null
@@ -1,81 +0,0 @@
-I would like to acknowledge the following people who have contributed
-to WCSLIB and/or PGSBOX in some way since 1995 - via bug reports,
-patches, suggestions for improvements, positive feedback, etc.
-
-James M. Anderson (MPIfR)
-Robbie Auld (Cardiff U.)
-Klaus Banse (ESO)
-David Barnes (ATNF/CSIRO)
-David Berry (STARLINK & JAC)
-Emmanuel Bertin (IAP)
-Jeremy Brewer (U. Pittsburgh)
-Wim Brouw (ATNF/CSIRO)
-Peter Bunclark (IoA, U. Cambridge)
-Pan Chai (GSFC/NASA)
-Charles Copley
-Neil Crighton
-Cesar Enrique Garcia Dabo (ESO)
-Lindsey Davis (NOAO)
-Ger van Diepen (ASTRON)
-Patrick Dowler (CADC/NRC)
-Michael Droettboom (STScI)
-Rick Ebert (IPAC/NASA)
-Ken Ebisawa (GSFC/NASA)
-Sébastien Fabbro (Gentoo linux maintainer)
-Bob Garwood (NRAO)
-Brian Glendenning (NRAO)
-Eric Greisen (NRAO)
-Michael Halle (AM/Harvard)
-Booth Hartley (IPAC/NASA)
-Phil Hodge (STScI)
-Bryan Irby (GSFC/NASA)
-Justin Jonas (Rhodes U.)
-Yves Jung (ESO)
-David Kaplan (KITP/UCSB)
-Daniel S. Katz (JPL/NASA)
-Neil Killeen (ATNF/CSIRO)
-David King (NRAO)
-Paul F. Kunz (SLAC/Stanford U.)
-Jonas Møller Larsen (ESO)
-Jim Lewis (IoA, U. Cambridge)
-Marco Lombardi (ESO)
-Lars Kristian Lundin (ESO)
-Robert Lupton (Princeton U.)
-Craig Markwardt (GSFC/NASA)
-Malte Marquarding (ATNF/CSIRO)
-Tom Marsh (U. Warwick)
-Sean Mattingly (IPAC/NASA)
-Dave McConnell (ATNF/CSIRO)
-Thomas A. McGlynn (GSFC/NASA)
-Michelle Miller (NOAO)
-Doug Mink (CfA)
-August Muench (CfA)
-Fergal Mullally (Princeton U.)
-Clive Page (U. Leicester)
-Sergio Pascual (U. Complutense de Madrid)
-Bill Pence (NASA/GSFC)
-Olivier Perdereau (LAL/IN2P3)
-Dirk Petry (ESO)
-Ray Plante (NCSA/UIUC)
-Niruj Mohan Ramanujam (Leiden Obs)
-Harold Ravlin (U. Illinois)
-Boud Roukema (TCfA)
-Keith A. Scollick (GSFC/NASA)
-Arno Schoenmakers (ASTRON)
-Hanno Spreeuw (ASTRON)
-Ole Streicher (Debian maintainer)
-Hans Terlouw (Kapteyn, Groningen)
-Peter Teuben (U. Maryland)
-Harro Verkouter (JIVE)
-John C. Vernaleo (GSFC/NASA)
-Martin Vogelaar (Kapteyn, Groningen)
-Stephen Walton (CSUN)
-Boyd Waters NRAO)
-Randall Wayth (Curtin U.)
-Matthew Whiting (ATNF/CSIRO)
-Peter Williams (UCB)
-Daren Scot Wilson (NRAO)
-Tony Wong (ATNF/CSIRO)
-
-
-$Id: THANKS,v 4.10 2012/02/05 23:41:45 cal103 Exp $
diff --git a/astropy/wcs/src/wcslib/VALIDATION b/astropy/wcs/src/wcslib/VALIDATION
deleted file mode 100644
index 3cb8fce..0000000
--- a/astropy/wcs/src/wcslib/VALIDATION
+++ /dev/null
@@ -1,197 +0,0 @@
-Platforms on which the installation procedures and test suite were
-exercised
-
-
-WCSLIB version 4.10 (2012/02/06)
---------------------------------
-
-* Dell Latitude D630 (Intel Centrino, i686) running Debian linux 5.0.9 (lenny)
-  uname -r (kernel version): 2.6.32-bpo.5-686
-  gcc --version: gcc --version: g
-  gfortran --version: GNU Fortran (Debian 4.3.2-1.1) 4.3.2
-
-
-WCSLIB version 4.8 (2011/08/15)
--------------------------------
-
-* Dell Latitude D620 (Intel Centrino Duo, i686), Debian linux 4.0 (etch)
-  uname -r (kernel version): 2.6.24-1-686 (32-bit)
-  gcc --version: gcc (GCC) 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)
-  g77 --version: GNU Fortran (GCC) 3.4.6 (Debian 3.4.6-5)
-
-
-* Dell PowerEdge 2950 (Intel Xeon, 8 x X5460), Debian linux 5.0.8 (lenny)
-  uname -r (kernel version): 2.6.26-2-amd64 (64-bit)
-  gcc --version: gcc (Debian 4.3.2-1.1) 4.3.2
-  gfortran --version: GNU Fortran (Debian 4.3.2-1.1) 4.3.2
-
-
-* Marvell SheevaPlug (Feroceon 88FR131 rev 1 ARM v5L), Debian linux 6.0 
-  (squeeze)
-  uname -r (kernel version): 2.6.32-5-kirkwood
-  gcc --version: gcc (Debian 4.4.5-8) 4.4.5
-  gfortran --version: GNU Fortran (Debian 4.4.5-8) 4.4.5
-
-
-* Mac mini (Intel Core 2 Duo) running Mac OS X 10.6.2 (10C540)
-  uname -r (Darwin kernel version): 10.2.0
-  gcc --version: i686-apple-darwin10-gcc-4.2.1 (GCC) 4.2.1
-                 (Apple Inc. build 5646)
-  gfortran --version: GNU Fortran (GCC) 4.5.0 20100107 (experimental)
-
-
-* Enterprise 450 Model 2250 (Sparc, sun4u 64-bit), SunOS 5.9 (Solaris 9)
-  uname -r (SunOS version): 5.9
-  gcc --version: gcc (GCC) 4.5.1
-  gfortran --version: GNU Fortran (GCC) 4.5.1
-
-
-WCSLIB version 4.7 (2011/02/07)
--------------------------------
-
-* Dell Latitude D630 (Intel Centrino, i686) running Debian linux 4.0 (etch)
-  uname -r (kernel version): 2.6.24-1-686
-  gcc --version: gcc (GCC) 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)
-  g77 --version: GNU Fortran (GCC) 3.4.6 (Debian 3.4.6-5)
-
-
-* Sun SunFire V20z (AMD Opteron, x86_64) running Debian linux 4.0 (etch)
-  uname -r (kernel version): 2.6.18-6-amd64
-  gcc --version: gcc (GCC) 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)
-  g77 --version: GNU Fortran (GCC) 3.4.6 (Debian 3.4.6-5)
-
-
-* Enterprise 450 Model 2250 (Sparc, sun4u 64-bit), SunOS 5.9 (Solaris 9)
-  uname -r (SunOS version): 5.9
-  gcc --version: gcc (GCC) 4.5.1
-  gfortran --version: GNU Fortran (GCC) 4.5.1
-
-    and
-
-  cc -V: cc: Sun WorkShop 6 update 2 C 5.3 Patch 111679-14 2004/02/20
-  f77 -V: f77: Sun WorkShop 6 update 2 FORTRAN 77 5.3 Patch 111691-07
-          2004/04/23
-
-
-* Mac Xserve (Quad-Core Intel Xeon) running Mac OS X 10.6.5 (10H575)
-  uname -r (Darwin kernel version): 10.5.0
-  gcc --version: 4.2.1 (Apple Inc. build 5664)
-  gfortran --version: GNU Fortran (GCC) 4.5.0 20100107 (experimental)
-
-
-* Mac mini (Intel Core 2 Duo) running Mac OS X 10.6.2 (10C540)
-  uname -r (Darwin kernel version): 10.2.0
-  gcc --version: i686-apple-darwin10-gcc-4.2.1 (GCC) 4.2.1
-                 (Apple Inc. build 5646)
-  gfortran --version: GNU Fortran (GCC) 4.5.0 20100107 (experimental)
-
-
-* Mac mini (Intel Core Duo) running Mac OS X 10.4.9 (8P2137)
-  uname -r (Darwin kernel version): 8.9.1
-  gcc --version: gcc (GCC) 4.3.0 20070316 (experimental)
-  g77 --version: GNU Fortran (GCC) 3.4.0
-
-
-WCSLIB version 4.5 (2010/07/16)
--------------------------------
-
-* Dell Latitude D630 (Intel Centrino, i686) running Debian linux 4.0 (etch)
-  uname -r (kernel version): 2.6.24-1-686
-  gcc --version: gcc (GCC) 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)
-  g77 --version: GNU Fortran (GCC) 3.4.6 (Debian 3.4.6-5)
-
-    and
-
-  gcc --version: gcc (GCC) 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)
-  ifort -V: Intel(R) Fortran Compiler for 32-bit applications, Version 8.1
-            Build 20041118Z Package ID: l_fc_pc_8.1.023
-
-
-* Mac mini (Intel Core 2 Duo, i386) running Mac OS X 10.6.2 (10C540)
-  uname -r (Darwin kernel version): 10.2.0
-  gcc --version: i686-apple-darwin10-gcc-4.2.1 (GCC) 4.2.1
-                 (Apple Inc. build 5646)
-  gfortran --version: GNU Fortran (GCC) 4.5.0 20100107 (experimental)
-
-
-* Mac mini (Intel Core Duo, i386) running Mac OS X 10.4.9 (8P2137)
-  uname -r (Darwin kernel version): 8.9.1
-  gcc --version: gcc (GCC) 4.3.0 20070316 (experimental)
-  g77 --version: GNU Fortran (GCC) 3.4.0
-
-    and
-
-  gcc --version: gcc (GCC) 4.3.0 20070316 (experimental)
-  gfortran --version: GNU Fortran (GCC) 4.3.0 20070316 (experimental)
-
-
-* Sun SunFire V20z (AMD Opteron, x86_64) running Debian linux 4.0 (etch)
-  uname -r (kernel version): 2.6.18-6-amd64
-  gcc --version: gcc (GCC) 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)
-  g77 --version: GNU Fortran (GCC) 3.4.6 (Debian 3.4.6-5)
-
-    and
-
-  gcc --version: gcc (GCC) 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)
-  gfortran --version: GNU Fortran 95 (GCC) 4.1.2 20061115 (prerelease)
-                      (Debian 4.1.1-21)
-
-
-* Sun Ultra-60 (Sparc, sun4u) running SunOS 5.6 (Solaris 2.6)
-  uname -r (SunOS version): 5.6
-  gcc --version: 2.95.3
-  g77 --version: GNU Fortran 0.5.25 20010315 (release)
-
-    and
-
-  cc -V: cc: Sun WorkShop 6 update 2 C 5.3 Patch 111679-14 2004/02/20
-  f77 -V: f77: Sun WorkShop 6 update 2 FORTRAN 77 5.3 Patch 111691-07
-          2004/04/23
-
-
-
-WCSLIB version 4.4 (2009/08/06)
--------------------------------
-
-* Dell Latitude D630 (Intel Centrino, i686) running Debian linux 4.0 (etch)
-  uname -r (kernel version): 2.6.24-1-686
-  gcc --version: gcc (GCC) 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)
-  g77 --version: GNU Fortran (GCC) 3.4.6 (Debian 3.4.6-5)
-
-
-* Mac mini (Intel Core Duo, i386) running Mac OS X 10.4.9 (8P2137)
-  uname -r (Darwin kernel version): 8.9.1
-  gcc --version: gcc (GCC) 4.3.0 20070316 (experimental)
-  g77 --version: GNU Fortran (GCC) 3.4.0
-
-    and
-
-  gcc --version: gcc (GCC) 4.3.0 20070316 (experimental)
-  gfortran --version: GNU Fortran (GCC) 4.3.0 20070316 (experimental)
-
-
-* Sun SunFire V20z (AMD Opteron, x86_64) running Debian linux 4.0 (etch)
-  uname -r (kernel version): 2.6.18-6-amd64
-  gcc --version: gcc (GCC) 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)
-  g77 --version: GNU Fortran (GCC) 3.4.6 (Debian 3.4.6-5)
-
-    and
-
-  gcc --version: gcc (GCC) 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)
-  gfortran --version: GNU Fortran 95 (GCC) 4.1.2 20061115 (prerelease)
-                      (Debian 4.1.1-21)
-
-
-* Sun SunBlade 1000 (Sparc, sun4u) running SunOS 5.8 (Solaris 2.8)
-  uname -r (SunOS version): 5.8
-  gcc --version: 2.95.3
-  g77 --version: GNU Fortran 0.5.25 20010315 (release)
-
-    and
-
-  cc -V: cc: Sun WorkShop 6 update 2 C 5.3 Patch 111679-14 2004/02/20
-  f77 -V: f77: Sun WorkShop 6 update 2 FORTRAN 77 5.3 Patch 111691-07
-          2004/04/23
-
-------------------------------------------------------------------------------
-$Id: VALIDATION,v 4.10 2012/02/05 23:41:45 cal103 Exp $
diff --git a/astropy/wcs/src/wcslib/configure b/astropy/wcs/src/wcslib/configure
deleted file mode 100755
index ada1941..0000000
--- a/astropy/wcs/src/wcslib/configure
+++ /dev/null
@@ -1,13252 +0,0 @@
-#! /bin/sh
-# From configure.ac Revision: 4.10 .
-# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.61 for WCSLIB 4.10.
-#
-# Report bugs to <mcalabre at atnf.csiro.au>.
-#
-# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
-# 2002, 2003, 2004, 2005, 2006 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=:
-  # Zsh 3.x and 4.x performs 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
-
-
-
-
-# PATH needs CR
-# 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
-
-# The user is always right.
-if test "${PATH_SEPARATOR+set}" != set; then
-  echo "#! /bin/sh" >conf$$.sh
-  echo  "exit 0"   >>conf$$.sh
-  chmod +x conf$$.sh
-  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
-    PATH_SEPARATOR=';'
-  else
-    PATH_SEPARATOR=:
-  fi
-  rm -f conf$$.sh
-fi
-
-# Support unset when possible.
-if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
-  as_unset=unset
-else
-  as_unset=false
-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.)
-as_nl='
-'
-IFS=" ""	$as_nl"
-
-# Find who we are.  Look in the path if we contain no directory separator.
-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
-  echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
-  { (exit 1); exit 1; }
-fi
-
-# Work around bugs in pre-3.0 UWIN ksh.
-for as_var in ENV MAIL MAILPATH
-do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
-done
-PS1='$ '
-PS2='> '
-PS4='+ '
-
-# NLS nuisances.
-for as_var in \
-  LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
-  LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
-  LC_TELEPHONE LC_TIME
-do
-  if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
-    eval $as_var=C; export $as_var
-  else
-    ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
-  fi
-done
-
-# Required to use basename.
-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
-
-
-# Name of the executable.
-as_me=`$as_basename -- "$0" ||
-$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
-	 X"$0" : 'X\(//\)$' \| \
-	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
-echo X/"$0" |
-    sed '/^.*\/\([^/][^/]*\)\/*$/{
-	    s//\1/
-	    q
-	  }
-	  /^X\/\(\/\/\)$/{
-	    s//\1/
-	    q
-	  }
-	  /^X\/\(\/\).*/{
-	    s//\1/
-	    q
-	  }
-	  s/.*/./; q'`
-
-# CDPATH.
-$as_unset CDPATH
-
-
-if test "x$CONFIG_SHELL" = x; then
-  if (eval ":") 2>/dev/null; then
-  as_have_required=yes
-else
-  as_have_required=no
-fi
-
-  if test $as_have_required = yes && 	 (eval ":
-(as_func_return () {
-  (exit \$1)
-}
-as_func_success () {
-  as_func_return 0
-}
-as_func_failure () {
-  as_func_return 1
-}
-as_func_ret_success () {
-  return 0
-}
-as_func_ret_failure () {
-  return 1
-}
-
-exitcode=0
-if as_func_success; then
-  :
-else
-  exitcode=1
-  echo as_func_success failed.
-fi
-
-if as_func_failure; then
-  exitcode=1
-  echo as_func_failure succeeded.
-fi
-
-if as_func_ret_success; then
-  :
-else
-  exitcode=1
-  echo as_func_ret_success failed.
-fi
-
-if as_func_ret_failure; then
-  exitcode=1
-  echo as_func_ret_failure succeeded.
-fi
-
-if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
-  :
-else
-  exitcode=1
-  echo positional parameters were not saved.
-fi
-
-test \$exitcode = 0) || { (exit 1); exit 1; }
-
-(
-  as_lineno_1=\$LINENO
-  as_lineno_2=\$LINENO
-  test \"x\$as_lineno_1\" != \"x\$as_lineno_2\" &&
-  test \"x\`expr \$as_lineno_1 + 1\`\" = \"x\$as_lineno_2\") || { (exit 1); exit 1; }
-") 2> /dev/null; then
-  :
-else
-  as_candidate_shells=
-    as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  case $as_dir in
-	 /*)
-	   for as_base in sh bash ksh sh5; do
-	     as_candidate_shells="$as_candidate_shells $as_dir/$as_base"
-	   done;;
-       esac
-done
-IFS=$as_save_IFS
-
-
-      for as_shell in $as_candidate_shells $SHELL; do
-	 # Try only shells that exist, to save several forks.
-	 if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
-		{ ("$as_shell") 2> /dev/null <<\_ASEOF
-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
-  emulate sh
-  NULLCMD=:
-  # Zsh 3.x and 4.x performs 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
-
-
-:
-_ASEOF
-}; then
-  CONFIG_SHELL=$as_shell
-	       as_have_required=yes
-	       if { "$as_shell" 2> /dev/null <<\_ASEOF
-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
-  emulate sh
-  NULLCMD=:
-  # Zsh 3.x and 4.x performs 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_func_return () {
-  (exit $1)
-}
-as_func_success () {
-  as_func_return 0
-}
-as_func_failure () {
-  as_func_return 1
-}
-as_func_ret_success () {
-  return 0
-}
-as_func_ret_failure () {
-  return 1
-}
-
-exitcode=0
-if as_func_success; then
-  :
-else
-  exitcode=1
-  echo as_func_success failed.
-fi
-
-if as_func_failure; then
-  exitcode=1
-  echo as_func_failure succeeded.
-fi
-
-if as_func_ret_success; then
-  :
-else
-  exitcode=1
-  echo as_func_ret_success failed.
-fi
-
-if as_func_ret_failure; then
-  exitcode=1
-  echo as_func_ret_failure succeeded.
-fi
-
-if ( set x; as_func_ret_success y && test x = "$1" ); then
-  :
-else
-  exitcode=1
-  echo positional parameters were not saved.
-fi
-
-test $exitcode = 0) || { (exit 1); exit 1; }
-
-(
-  as_lineno_1=$LINENO
-  as_lineno_2=$LINENO
-  test "x$as_lineno_1" != "x$as_lineno_2" &&
-  test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2") || { (exit 1); exit 1; }
-
-_ASEOF
-}; then
-  break
-fi
-
-fi
-
-      done
-
-      if test "x$CONFIG_SHELL" != x; then
-  for as_var in BASH_ENV ENV
-        do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
-        done
-        export CONFIG_SHELL
-        exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"}
-fi
-
-
-    if test $as_have_required = no; then
-  echo This script requires a shell more modern than all the
-      echo shells that I found on your system.  Please install a
-      echo modern shell, or manually run the script under such a
-      echo shell if you do have one.
-      { (exit 1); exit 1; }
-fi
-
-
-fi
-
-fi
-
-
-
-(eval "as_func_return () {
-  (exit \$1)
-}
-as_func_success () {
-  as_func_return 0
-}
-as_func_failure () {
-  as_func_return 1
-}
-as_func_ret_success () {
-  return 0
-}
-as_func_ret_failure () {
-  return 1
-}
-
-exitcode=0
-if as_func_success; then
-  :
-else
-  exitcode=1
-  echo as_func_success failed.
-fi
-
-if as_func_failure; then
-  exitcode=1
-  echo as_func_failure succeeded.
-fi
-
-if as_func_ret_success; then
-  :
-else
-  exitcode=1
-  echo as_func_ret_success failed.
-fi
-
-if as_func_ret_failure; then
-  exitcode=1
-  echo as_func_ret_failure succeeded.
-fi
-
-if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
-  :
-else
-  exitcode=1
-  echo positional parameters were not saved.
-fi
-
-test \$exitcode = 0") || {
-  echo No shell found that supports shell functions.
-  echo Please tell autoconf at gnu.org about your system,
-  echo including any error possibly output before this
-  echo message
-}
-
-
-
-  as_lineno_1=$LINENO
-  as_lineno_2=$LINENO
-  test "x$as_lineno_1" != "x$as_lineno_2" &&
-  test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
-
-  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
-  # uniformly replaced by the line number.  The first 'sed' inserts a
-  # line-number line after each line using $LINENO; the second 'sed'
-  # does the real work.  The second script uses 'N' to pair each
-  # line-number line with the line containing $LINENO, and appends
-  # trailing '-' during substitution so that $LINENO is not a special
-  # case at line end.
-  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
-  # scripts with optimization help from Paolo Bonzini.  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" ||
-    { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
-   { (exit 1); exit 1; }; }
-
-  # 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
-}
-
-
-if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
-  as_dirname=dirname
-else
-  as_dirname=false
-fi
-
-ECHO_C= ECHO_N= ECHO_T=
-case `echo -n x` in
--n*)
-  case `echo 'x\c'` in
-  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
-  *)   ECHO_C='\c';;
-  esac;;
-*)
-  ECHO_N='-n';;
-esac
-
-if expr a : '\(a\)' >/dev/null 2>&1 &&
-   test "X`expr 00001 : '.*\(...\)'`" = X001; then
-  as_expr=expr
-else
-  as_expr=false
-fi
-
-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
-fi
-echo >conf$$.file
-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 -p'.
-  ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
-    as_ln_s='cp -p'
-elif ln conf$$.file conf$$ 2>/dev/null; then
-  as_ln_s=ln
-else
-  as_ln_s='cp -p'
-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=:
-else
-  test -d ./-p && rmdir ./-p
-  as_mkdir_p=false
-fi
-
-if test -x / >/dev/null 2>&1; then
-  as_test_x='test -x'
-else
-  if ls -dL / >/dev/null 2>&1; then
-    as_ls_L_option=L
-  else
-    as_ls_L_option=
-  fi
-  as_test_x='
-    eval sh -c '\''
-      if test -d "$1"; then
-        test -d "$1/.";
-      else
-	case $1 in
-        -*)set "./$1";;
-	esac;
-	case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in
-	???[sx]*):;;*)false;;esac;fi
-    '\'' sh
-  '
-fi
-as_executable_p=$as_test_x
-
-# 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 7<&0 </dev/null 6>&1
-
-# Name of the host.
-# hostname on some systems (SVR3.2, 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=
-SHELL=${CONFIG_SHELL-/bin/sh}
-
-# Identity of this package.
-PACKAGE_NAME='WCSLIB'
-PACKAGE_TARNAME='wcslib-4.10'
-PACKAGE_VERSION='4.10'
-PACKAGE_STRING='WCSLIB 4.10'
-PACKAGE_BUGREPORT='mcalabre at atnf.csiro.au'
-
-ac_unique_file="C/wcs.h"
-# Factoring default headers for most tests.
-ac_includes_default="\
-#include <stdio.h>
-#ifdef HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-#ifdef HAVE_SYS_STAT_H
-# include <sys/stat.h>
-#endif
-#ifdef STDC_HEADERS
-# include <stdlib.h>
-# include <stddef.h>
-#else
-# ifdef HAVE_STDLIB_H
-#  include <stdlib.h>
-# endif
-#endif
-#ifdef HAVE_STRING_H
-# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
-#  include <memory.h>
-# endif
-# include <string.h>
-#endif
-#ifdef HAVE_STRINGS_H
-# include <strings.h>
-#endif
-#ifdef HAVE_INTTYPES_H
-# include <inttypes.h>
-#endif
-#ifdef HAVE_STDINT_H
-# include <stdint.h>
-#endif
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#endif"
-
-ac_subst_vars='SHELL
-PATH_SEPARATOR
-PACKAGE_NAME
-PACKAGE_TARNAME
-PACKAGE_VERSION
-PACKAGE_STRING
-PACKAGE_BUGREPORT
-exec_prefix
-prefix
-program_transform_name
-bindir
-sbindir
-libexecdir
-datarootdir
-datadir
-sysconfdir
-sharedstatedir
-localstatedir
-includedir
-oldincludedir
-docdir
-infodir
-htmldir
-dvidir
-pdfdir
-psdir
-libdir
-localedir
-mandir
-DEFS
-ECHO_C
-ECHO_N
-ECHO_T
-LIBS
-build_alias
-host_alias
-target_alias
-LIBVER
-build
-build_cpu
-build_vendor
-build_os
-ARCH
-FLEX
-CC
-CFLAGS
-LDFLAGS
-CPPFLAGS
-ac_ct_CC
-EXEEXT
-OBJEXT
-CPP
-GREP
-EGREP
-LIBOBJS
-F77
-FFLAGS
-ac_ct_F77
-FLIBS
-RANLIB
-SHRLIB
-SONAME
-SHRFLAGS
-SHRLD
-SHRSFX
-SHRLN
-LN_S
-INSTALL_PROGRAM
-INSTALL_SCRIPT
-INSTALL_DATA
-XMKMF
-CFITSIOINC
-CFITSIOLIB
-GETWCSTAB
-PGPLOTINC
-PGPLOTLIB
-SUBDIRS
-TSTDIRS
-INSTDIR
-LTLIBOBJS'
-ac_subst_files=''
-      ac_precious_vars='build_alias
-host_alias
-target_alias
-CC
-CFLAGS
-LDFLAGS
-LIBS
-CPPFLAGS
-CPP
-F77
-FFLAGS
-XMKMF'
-
-
-# Initialize some variables set by options.
-ac_init_help=
-ac_init_version=false
-# 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_TARNAME}'
-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=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_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
-    # Reject names that are not valid shell variable names.
-    expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null &&
-      { echo "$as_me: error: invalid feature name: $ac_feature" >&2
-   { (exit 1); exit 1; }; }
-    ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'`
-    eval enable_$ac_feature=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_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
-    # Reject names that are not valid shell variable names.
-    expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null &&
-      { echo "$as_me: error: invalid feature name: $ac_feature" >&2
-   { (exit 1); exit 1; }; }
-    ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'`
-    eval enable_$ac_feature=\$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_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
-    # Reject names that are not valid shell variable names.
-    expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null &&
-      { echo "$as_me: error: invalid package name: $ac_package" >&2
-   { (exit 1); exit 1; }; }
-    ac_package=`echo $ac_package | sed 's/[-.]/_/g'`
-    eval with_$ac_package=\$ac_optarg ;;
-
-  -without-* | --without-*)
-    ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
-    # Reject names that are not valid shell variable names.
-    expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null &&
-      { echo "$as_me: error: invalid package name: $ac_package" >&2
-   { (exit 1); exit 1; }; }
-    ac_package=`echo $ac_package | sed 's/[-.]/_/g'`
-    eval with_$ac_package=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 ;;
-
-  -*) { echo "$as_me: error: unrecognized option: $ac_option
-Try \`$0 --help' for more information." >&2
-   { (exit 1); exit 1; }; }
-    ;;
-
-  *=*)
-    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
-    # Reject names that are not valid shell variable names.
-    expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
-      { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
-   { (exit 1); exit 1; }; }
-    eval $ac_envvar=\$ac_optarg
-    export $ac_envvar ;;
-
-  *)
-    # FIXME: should be removed in autoconf 3.0.
-    echo "$as_me: WARNING: you should use --build, --host, --target" >&2
-    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
-      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'`
-  { echo "$as_me: error: missing argument to $ac_option" >&2
-   { (exit 1); exit 1; }; }
-fi
-
-# Be sure to have absolute directory names.
-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
-  case $ac_val in
-    [\\/$]* | ?:[\\/]* )  continue;;
-    NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
-  esac
-  { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
-   { (exit 1); exit 1; }; }
-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
-    echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
-    If a cross compiler is detected then cross compile mode will be used." >&2
-  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 .` ||
-  { echo "$as_me: error: Working directory cannot be determined" >&2
-   { (exit 1); exit 1; }; }
-test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
-  { echo "$as_me: error: pwd does not report name of working directory" >&2
-   { (exit 1); exit 1; }; }
-
-
-# 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 -- "$0" ||
-$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
-	 X"$0" : 'X\(//\)[^/]' \| \
-	 X"$0" : 'X\(//\)$' \| \
-	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
-echo X"$0" |
-    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 .."
-  { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
-   { (exit 1); exit 1; }; }
-fi
-ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
-ac_abs_confdir=`(
-	cd "$srcdir" && test -r "./$ac_unique_file" || { echo "$as_me: error: $ac_msg" >&2
-   { (exit 1); exit 1; }; }
-	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 WCSLIB 4.10 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/wcslib-4.10]
-  --htmldir=DIR          html documentation [DOCDIR]
-  --dvidir=DIR           dvi documentation [DOCDIR]
-  --pdfdir=DIR           pdf documentation [DOCDIR]
-  --psdir=DIR            ps documentation [DOCDIR]
-_ACEOF
-
-  cat <<\_ACEOF
-
-X features:
-  --x-includes=DIR    X include files are in DIR
-  --x-libraries=DIR   X library files are in DIR
-
-System types:
-  --build=BUILD     configure for building on BUILD [guessed]
-_ACEOF
-fi
-
-if test -n "$ac_init_help"; then
-  case $ac_init_help in
-     short | recursive ) echo "Configuration of WCSLIB 4.10:";;
-   esac
-  cat <<\_ACEOF
-
-Optional Features:
-  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
-  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
-  --enable-fortran=ARG    Fortran compiler to use
-  --disable-fortran       don't build the Fortran wrappers or PGSBOX
-  --disable-largefile     omit support for large files
-  --disable-utils         don't build the WCS utilities
-
-Optional Packages:
-  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
-  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
-  --without-cfitsio       eschew CFITSIO
-  --with-cfitsiolib=DIR   directory containing cfitsio library
-  --with-cfitsioinc=DIR   directory containing cfitsio header files
-  --without-pgplot        eschew PGPLOT
-  --with-pgplotlib=DIR    directory containing pgplot library
-  --with-pgplotinc=DIR    directory containing pgplot header files
-  --with-x                use the X Window System
-
-Some influential environment variables:
-  CC          C compiler command
-  CFLAGS      C compiler flags
-  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
-              nonstandard directory <lib dir>
-  LIBS        libraries to pass to the linker, e.g. -l<library>
-  CPPFLAGS    C/C++/Objective C preprocessor flags, e.g. -I<include dir> if
-              you have headers in a nonstandard directory <include dir>
-  CPP         C preprocessor
-  F77         Fortran 77 compiler command
-  FFLAGS      Fortran 77 compiler flags
-  XMKMF       Path to xmkmf, Makefile generator for X Window System
-
-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 <mcalabre at atnf.csiro.au>.
-_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" || continue
-    ac_builddir=.
-
-case "$ac_dir" in
-.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
-*)
-  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
-  # A ".." for each directory in $ac_dir_suffix.
-  ac_top_builddir_sub=`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
-      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
-WCSLIB configure 4.10
-generated by GNU Autoconf 2.61
-
-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
-2002, 2003, 2004, 2005, 2006 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
-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 WCSLIB $as_me 4.10, which was
-generated by GNU Autoconf 2.61.  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=.
-  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=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
-    esac
-    case $ac_pass in
-    1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
-    2)
-      ac_configure_args1="$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
-      ac_configure_args="$ac_configure_args '$ac_arg'"
-      ;;
-    esac
-  done
-done
-$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
-$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export 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
-
-    cat <<\_ASBOX
-## ---------------- ##
-## Cache variables. ##
-## ---------------- ##
-_ASBOX
-    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_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5
-echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;;
-      esac
-      case $ac_var in #(
-      _ | IFS | as_nl) ;; #(
-      *) $as_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
-
-    cat <<\_ASBOX
-## ----------------- ##
-## Output variables. ##
-## ----------------- ##
-_ASBOX
-    echo
-    for ac_var in $ac_subst_vars
-    do
-      eval ac_val=\$$ac_var
-      case $ac_val in
-      *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
-      esac
-      echo "$ac_var='\''$ac_val'\''"
-    done | sort
-    echo
-
-    if test -n "$ac_subst_files"; then
-      cat <<\_ASBOX
-## ------------------- ##
-## File substitutions. ##
-## ------------------- ##
-_ASBOX
-      echo
-      for ac_var in $ac_subst_files
-      do
-	eval ac_val=\$$ac_var
-	case $ac_val in
-	*\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
-	esac
-	echo "$ac_var='\''$ac_val'\''"
-      done | sort
-      echo
-    fi
-
-    if test -s confdefs.h; then
-      cat <<\_ASBOX
-## ----------- ##
-## confdefs.h. ##
-## ----------- ##
-_ASBOX
-      echo
-      cat confdefs.h
-      echo
-    fi
-    test "$ac_signal" != 0 &&
-      echo "$as_me: caught signal $ac_signal"
-    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'; { (exit 1); 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
-
-# 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
-
-
-# Let the site file select an alternate cache file if it wants to.
-# Prefer explicitly selected file to automatically selected ones.
-if test -n "$CONFIG_SITE"; then
-  set x "$CONFIG_SITE"
-elif test "x$prefix" != xNONE; then
-  set x "$prefix/share/config.site" "$prefix/etc/config.site"
-else
-  set x "$ac_default_prefix/share/config.site" \
-	"$ac_default_prefix/etc/config.site"
-fi
-shift
-for ac_site_file
-do
-  if test -r "$ac_site_file"; then
-    { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
-echo "$as_me: loading site script $ac_site_file" >&6;}
-    sed 's/^/| /' "$ac_site_file" >&5
-    . "$ac_site_file"
-  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.
-  if test -f "$cache_file"; then
-    { echo "$as_me:$LINENO: loading cache $cache_file" >&5
-echo "$as_me: loading cache $cache_file" >&6;}
-    case $cache_file in
-      [\\/]* | ?:[\\/]* ) . "$cache_file";;
-      *)                      . "./$cache_file";;
-    esac
-  fi
-else
-  { echo "$as_me:$LINENO: creating cache $cache_file" >&5
-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,)
-      { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
-echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
-      ac_cache_corrupted=: ;;
-    ,set)
-      { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
-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
-	{ echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
-echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
-	{ echo "$as_me:$LINENO:   former value:  $ac_old_val" >&5
-echo "$as_me:   former value:  $ac_old_val" >&2;}
-	{ echo "$as_me:$LINENO:   current value: $ac_new_val" >&5
-echo "$as_me:   current value: $ac_new_val" >&2;}
-	ac_cache_corrupted=:
-      fi;;
-  esac
-  # Pass precious variables to config.status.
-  if test "$ac_new_set" = set; then
-    case $ac_new_val in
-    *\'*) ac_arg=$ac_var=`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.
-      *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
-    esac
-  fi
-done
-if $ac_cache_corrupted; then
-  { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
-echo "$as_me: error: changes in the environment can compromise the build" >&2;}
-  { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
-echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
-   { (exit 1); exit 1; }; }
-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
-
-
-
-
-
-
-cat >>confdefs.h <<_ACEOF
-#define WCSLIB_VERSION $PACKAGE_VERSION
-_ACEOF
-
-
-# Library version number, same as package version.
-LIBVER="$PACKAGE_VERSION"
-
-
-
-ac_aux_dir=
-for ac_dir in config "$srcdir"/config; 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
-  { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in config \"$srcdir\"/config" >&5
-echo "$as_me: error: cannot find install-sh or install.sh in config \"$srcdir\"/config" >&2;}
-   { (exit 1); exit 1; }; }
-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.
-
-
-
-# Get the system type.
-# Make sure we can run config.sub.
-$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
-  { { echo "$as_me:$LINENO: error: cannot run $SHELL $ac_aux_dir/config.sub" >&5
-echo "$as_me: error: cannot run $SHELL $ac_aux_dir/config.sub" >&2;}
-   { (exit 1); exit 1; }; }
-
-{ echo "$as_me:$LINENO: checking build system type" >&5
-echo $ECHO_N "checking build system type... $ECHO_C" >&6; }
-if test "${ac_cv_build+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&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 &&
-  { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5
-echo "$as_me: error: cannot guess build type; you must specify one" >&2;}
-   { (exit 1); exit 1; }; }
-ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
-  { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&5
-echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&2;}
-   { (exit 1); exit 1; }; }
-
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_build" >&5
-echo "${ECHO_T}$ac_cv_build" >&6; }
-case $ac_cv_build in
-*-*-*) ;;
-*) { { echo "$as_me:$LINENO: error: invalid value of canonical build" >&5
-echo "$as_me: error: invalid value of canonical build" >&2;}
-   { (exit 1); exit 1; }; };;
-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
-
-
-ARCH="${build_cpu}-$build_os"
-
-
-
-# Look for Flex.
-# Extract the first word of "flex", so it can be a program name with args.
-set dummy flex; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_prog_FLEX+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  if test -n "$FLEX"; then
-  ac_cv_prog_FLEX="$FLEX" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
-    ac_cv_prog_FLEX="flex"
-    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-done
-IFS=$as_save_IFS
-
-fi
-fi
-FLEX=$ac_cv_prog_FLEX
-if test -n "$FLEX"; then
-  { echo "$as_me:$LINENO: result: $FLEX" >&5
-echo "${ECHO_T}$FLEX" >&6; }
-else
-  { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-
-
-if test "x$FLEX" = xflex ; then
-  # Version 2.5.9 or later is required.
-  V=`flex --version | awk '{print $NF}'`
-  W=`echo $V | awk -F. '{if ((($1*100 + $2)*100 + $3) < 20509) print "no"}'`
-  if test "x$W" != x ; then
-    { echo "$as_me:$LINENO: Flex version $V is too old, ignored." >&5
-echo "$as_me: Flex version $V is too old, ignored." >&6;}
-    FLEX=
-  else
-    { echo "$as_me:$LINENO: Using Flex version $V." >&5
-echo "$as_me: Using Flex version $V." >&6;}
-  fi
-fi
-
-if test "x$FLEX" = x ; then
-  { echo "$as_me:$LINENO: WARNING: Flex version 2.5.9 or later does not appear to be
-           available, will use pre-generated sources." >&5
-echo "$as_me: WARNING: Flex version 2.5.9 or later does not appear to be
-           available, will use pre-generated sources." >&2;}
-fi
-
-
-# Look for an ANSI C compiler.
-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
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_prog_CC+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
-    ac_cv_prog_CC="${ac_tool_prefix}gcc"
-    echo "$as_me:$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
-  { echo "$as_me:$LINENO: result: $CC" >&5
-echo "${ECHO_T}$CC" >&6; }
-else
-  { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}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
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
-    ac_cv_prog_ac_ct_CC="gcc"
-    echo "$as_me:$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
-  { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
-echo "${ECHO_T}$ac_ct_CC" >&6; }
-else
-  { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-
-  if test "x$ac_ct_CC" = x; then
-    CC=""
-  else
-    case $cross_compiling:$ac_tool_warned in
-yes:)
-{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet.  If you think this
-configuration is useful to you, please write to autoconf at gnu.org." >&5
-echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet.  If you think this
-configuration is useful to you, please write to autoconf at gnu.org." >&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
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_prog_CC+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
-    ac_cv_prog_CC="${ac_tool_prefix}cc"
-    echo "$as_me:$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
-  { echo "$as_me:$LINENO: result: $CC" >&5
-echo "${ECHO_T}$CC" >&6; }
-else
-  { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}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
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_prog_CC+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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"
-    echo "$as_me:$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
-  { echo "$as_me:$LINENO: result: $CC" >&5
-echo "${ECHO_T}$CC" >&6; }
-else
-  { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}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
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_prog_CC+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
-    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
-    echo "$as_me:$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
-  { echo "$as_me:$LINENO: result: $CC" >&5
-echo "${ECHO_T}$CC" >&6; }
-else
-  { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}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
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
-    ac_cv_prog_ac_ct_CC="$ac_prog"
-    echo "$as_me:$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
-  { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
-echo "${ECHO_T}$ac_ct_CC" >&6; }
-else
-  { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}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:)
-{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet.  If you think this
-configuration is useful to you, please write to autoconf at gnu.org." >&5
-echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet.  If you think this
-configuration is useful to you, please write to autoconf at gnu.org." >&2;}
-ac_tool_warned=yes ;;
-esac
-    CC=$ac_ct_CC
-  fi
-fi
-
-fi
-
-
-test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
-See \`config.log' for more details." >&5
-echo "$as_me: error: no acceptable C compiler found in \$PATH
-See \`config.log' for more details." >&2;}
-   { (exit 1); exit 1; }; }
-
-# Provide some information about the compiler.
-echo "$as_me:$LINENO: checking for C compiler version" >&5
-ac_compiler=`set X $ac_compile; echo $2`
-{ (ac_try="$ac_compiler --version >&5"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compiler --version >&5") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }
-{ (ac_try="$ac_compiler -v >&5"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compiler -v >&5") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }
-{ (ac_try="$ac_compiler -V >&5"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compiler -V >&5") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }
-
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-ac_clean_files_save=$ac_clean_files
-ac_clean_files="$ac_clean_files a.out 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.
-{ echo "$as_me:$LINENO: checking for C compiler default output file name" >&5
-echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6; }
-ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
-#
-# List of possible output files, starting from the most likely.
-# The algorithm is not robust to junk in `.', hence go to wildcards (a.*)
-# only as a last resort.  b.out is created by i960 compilers.
-ac_files='a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out'
-#
-# The IRIX 6 linker writes into existing files which may not be
-# executable, retaining their permissions.  Remove them first so a
-# subsequent execution test works.
-ac_rmfiles=
-for ac_file in $ac_files
-do
-  case $ac_file in
-    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link_default") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; 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 | *.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
-
-{ echo "$as_me:$LINENO: result: $ac_file" >&5
-echo "${ECHO_T}$ac_file" >&6; }
-if test -z "$ac_file"; then
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-{ { echo "$as_me:$LINENO: error: C compiler cannot create executables
-See \`config.log' for more details." >&5
-echo "$as_me: error: C compiler cannot create executables
-See \`config.log' for more details." >&2;}
-   { (exit 77); exit 77; }; }
-fi
-
-ac_exeext=$ac_cv_exeext
-
-# Check that the compiler produces executables we can run.  If not, either
-# the compiler is broken, or we cross compile.
-{ echo "$as_me:$LINENO: checking whether the C compiler works" >&5
-echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6; }
-# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
-# If not cross compiling, check that we can run a simple program.
-if test "$cross_compiling" != yes; then
-  if { ac_try='./$ac_file'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-    cross_compiling=no
-  else
-    if test "$cross_compiling" = maybe; then
-	cross_compiling=yes
-    else
-	{ { echo "$as_me:$LINENO: error: cannot run C compiled programs.
-If you meant to cross compile, use \`--host'.
-See \`config.log' for more details." >&5
-echo "$as_me: error: cannot run C compiled programs.
-If you meant to cross compile, use \`--host'.
-See \`config.log' for more details." >&2;}
-   { (exit 1); exit 1; }; }
-    fi
-  fi
-fi
-{ echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-
-rm -f a.out a.exe conftest$ac_cv_exeext b.out
-ac_clean_files=$ac_clean_files_save
-# Check that the compiler produces executables we can run.  If not, either
-# the compiler is broken, or we cross compile.
-{ echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
-echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6; }
-{ echo "$as_me:$LINENO: result: $cross_compiling" >&5
-echo "${ECHO_T}$cross_compiling" >&6; }
-
-{ echo "$as_me:$LINENO: checking for suffix of executables" >&5
-echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6; }
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; 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 | *.o | *.obj ) ;;
-    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
-	  break;;
-    * ) break;;
-  esac
-done
-else
-  { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link
-See \`config.log' for more details." >&5
-echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
-See \`config.log' for more details." >&2;}
-   { (exit 1); exit 1; }; }
-fi
-
-rm -f conftest$ac_cv_exeext
-{ echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
-echo "${ECHO_T}$ac_cv_exeext" >&6; }
-
-rm -f conftest.$ac_ext
-EXEEXT=$ac_cv_exeext
-ac_exeext=$EXEEXT
-{ echo "$as_me:$LINENO: checking for suffix of object files" >&5
-echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6; }
-if test "${ac_cv_objext+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; 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 ) ;;
-    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
-       break;;
-  esac
-done
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
-See \`config.log' for more details." >&5
-echo "$as_me: error: cannot compute suffix of object files: cannot compile
-See \`config.log' for more details." >&2;}
-   { (exit 1); exit 1; }; }
-fi
-
-rm -f conftest.$ac_cv_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
-echo "${ECHO_T}$ac_cv_objext" >&6; }
-OBJEXT=$ac_cv_objext
-ac_objext=$OBJEXT
-{ echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
-echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6; }
-if test "${ac_cv_c_compiler_gnu+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-
-int
-main ()
-{
-#ifndef __GNUC__
-       choke me
-#endif
-
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  ac_compiler_gnu=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	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
-{ echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
-echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6; }
-GCC=`test $ac_compiler_gnu = yes && echo yes`
-ac_test_CFLAGS=${CFLAGS+set}
-ac_save_CFLAGS=$CFLAGS
-{ echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
-echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6; }
-if test "${ac_cv_prog_cc_g+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&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 >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  ac_cv_prog_cc_g=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	CFLAGS=""
-      cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  :
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	ac_c_werror_flag=$ac_save_c_werror_flag
-	 CFLAGS="-g"
-	 cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  ac_cv_prog_cc_g=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-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
-{ echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
-echo "${ECHO_T}$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
-{ echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5
-echo $ECHO_N "checking for $CC option to accept ISO C89... $ECHO_C" >&6; }
-if test "${ac_cv_prog_cc_c89+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  ac_cv_prog_cc_c89=no
-ac_save_CC=$CC
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <stdarg.h>
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-/* 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"
-  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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  ac_cv_prog_cc_c89=$ac_arg
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-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)
-    { echo "$as_me:$LINENO: result: none needed" >&5
-echo "${ECHO_T}none needed" >&6; } ;;
-  xno)
-    { echo "$as_me:$LINENO: result: unsupported" >&5
-echo "${ECHO_T}unsupported" >&6; } ;;
-  *)
-    CC="$CC $ac_cv_prog_cc_c89"
-    { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5
-echo "${ECHO_T}$ac_cv_prog_cc_c89" >&6; } ;;
-esac
-
-
-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
-{ echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
-echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6; }
-# On Suns, sometimes $CPP names a directory.
-if test -n "$CPP" && test -d "$CPP"; then
-  CPP=
-fi
-if test -z "$CPP"; then
-  if test "${ac_cv_prog_CPP+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&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 <limits.h> to <assert.h> if __STDC__ is defined, since
-  # <limits.h> 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 >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-		     Syntax error
-_ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } >/dev/null && {
-	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       }; then
-  :
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-  # Broken: fails on valid input.
-continue
-fi
-
-rm -f conftest.err conftest.$ac_ext
-
-  # OK, works on sane cases.  Now check whether nonexistent headers
-  # can be detected and how.
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <ac_nonexistent.h>
-_ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } >/dev/null && {
-	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       }; then
-  # Broken: success on invalid input.
-continue
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-  # Passes both tests.
-ac_preproc_ok=:
-break
-fi
-
-rm -f conftest.err conftest.$ac_ext
-
-done
-# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
-rm -f 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
-{ echo "$as_me:$LINENO: result: $CPP" >&5
-echo "${ECHO_T}$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 <limits.h> to <assert.h> if __STDC__ is defined, since
-  # <limits.h> 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 >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-		     Syntax error
-_ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } >/dev/null && {
-	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       }; then
-  :
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-  # Broken: fails on valid input.
-continue
-fi
-
-rm -f conftest.err conftest.$ac_ext
-
-  # OK, works on sane cases.  Now check whether nonexistent headers
-  # can be detected and how.
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <ac_nonexistent.h>
-_ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } >/dev/null && {
-	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       }; then
-  # Broken: success on invalid input.
-continue
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-  # Passes both tests.
-ac_preproc_ok=:
-break
-fi
-
-rm -f conftest.err conftest.$ac_ext
-
-done
-# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
-rm -f conftest.err conftest.$ac_ext
-if $ac_preproc_ok; then
-  :
-else
-  { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check
-See \`config.log' for more details." >&5
-echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
-See \`config.log' for more details." >&2;}
-   { (exit 1); exit 1; }; }
-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
-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
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_prog_CC+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
-    ac_cv_prog_CC="${ac_tool_prefix}gcc"
-    echo "$as_me:$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
-  { echo "$as_me:$LINENO: result: $CC" >&5
-echo "${ECHO_T}$CC" >&6; }
-else
-  { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}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
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
-    ac_cv_prog_ac_ct_CC="gcc"
-    echo "$as_me:$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
-  { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
-echo "${ECHO_T}$ac_ct_CC" >&6; }
-else
-  { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-
-  if test "x$ac_ct_CC" = x; then
-    CC=""
-  else
-    case $cross_compiling:$ac_tool_warned in
-yes:)
-{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet.  If you think this
-configuration is useful to you, please write to autoconf at gnu.org." >&5
-echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet.  If you think this
-configuration is useful to you, please write to autoconf at gnu.org." >&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
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_prog_CC+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
-    ac_cv_prog_CC="${ac_tool_prefix}cc"
-    echo "$as_me:$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
-  { echo "$as_me:$LINENO: result: $CC" >&5
-echo "${ECHO_T}$CC" >&6; }
-else
-  { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}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
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_prog_CC+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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"
-    echo "$as_me:$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
-  { echo "$as_me:$LINENO: result: $CC" >&5
-echo "${ECHO_T}$CC" >&6; }
-else
-  { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}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
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_prog_CC+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
-    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
-    echo "$as_me:$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
-  { echo "$as_me:$LINENO: result: $CC" >&5
-echo "${ECHO_T}$CC" >&6; }
-else
-  { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}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
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
-    ac_cv_prog_ac_ct_CC="$ac_prog"
-    echo "$as_me:$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
-  { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
-echo "${ECHO_T}$ac_ct_CC" >&6; }
-else
-  { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}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:)
-{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet.  If you think this
-configuration is useful to you, please write to autoconf at gnu.org." >&5
-echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet.  If you think this
-configuration is useful to you, please write to autoconf at gnu.org." >&2;}
-ac_tool_warned=yes ;;
-esac
-    CC=$ac_ct_CC
-  fi
-fi
-
-fi
-
-
-test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
-See \`config.log' for more details." >&5
-echo "$as_me: error: no acceptable C compiler found in \$PATH
-See \`config.log' for more details." >&2;}
-   { (exit 1); exit 1; }; }
-
-# Provide some information about the compiler.
-echo "$as_me:$LINENO: checking for C compiler version" >&5
-ac_compiler=`set X $ac_compile; echo $2`
-{ (ac_try="$ac_compiler --version >&5"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compiler --version >&5") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }
-{ (ac_try="$ac_compiler -v >&5"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compiler -v >&5") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }
-{ (ac_try="$ac_compiler -V >&5"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compiler -V >&5") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }
-
-{ echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
-echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6; }
-if test "${ac_cv_c_compiler_gnu+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-
-int
-main ()
-{
-#ifndef __GNUC__
-       choke me
-#endif
-
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  ac_compiler_gnu=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	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
-{ echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
-echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6; }
-GCC=`test $ac_compiler_gnu = yes && echo yes`
-ac_test_CFLAGS=${CFLAGS+set}
-ac_save_CFLAGS=$CFLAGS
-{ echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
-echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6; }
-if test "${ac_cv_prog_cc_g+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&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 >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  ac_cv_prog_cc_g=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	CFLAGS=""
-      cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  :
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	ac_c_werror_flag=$ac_save_c_werror_flag
-	 CFLAGS="-g"
-	 cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  ac_cv_prog_cc_g=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-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
-{ echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
-echo "${ECHO_T}$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
-{ echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5
-echo $ECHO_N "checking for $CC option to accept ISO C89... $ECHO_C" >&6; }
-if test "${ac_cv_prog_cc_c89+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  ac_cv_prog_cc_c89=no
-ac_save_CC=$CC
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <stdarg.h>
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-/* 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"
-  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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  ac_cv_prog_cc_c89=$ac_arg
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-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)
-    { echo "$as_me:$LINENO: result: none needed" >&5
-echo "${ECHO_T}none needed" >&6; } ;;
-  xno)
-    { echo "$as_me:$LINENO: result: unsupported" >&5
-echo "${ECHO_T}unsupported" >&6; } ;;
-  *)
-    CC="$CC $ac_cv_prog_cc_c89"
-    { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5
-echo "${ECHO_T}$ac_cv_prog_cc_c89" >&6; } ;;
-esac
-
-
-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
-
-   case $ac_cv_prog_cc_stdc in
-  no) ac_cv_prog_cc_c99=no; ac_cv_prog_cc_c89=no ;;
-  *) { echo "$as_me:$LINENO: checking for $CC option to accept ISO C99" >&5
-echo $ECHO_N "checking for $CC option to accept ISO C99... $ECHO_C" >&6; }
-if test "${ac_cv_prog_cc_c99+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  ac_cv_prog_cc_c99=no
-ac_save_CC=$CC
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <stdarg.h>
-#include <stdbool.h>
-#include <stdlib.h>
-#include <wchar.h>
-#include <stdio.h>
-
-// Check varargs macros.  These examples are taken from C99 6.10.3.5.
-#define debug(...) fprintf (stderr, __VA_ARGS__)
-#define showlist(...) puts (#__VA_ARGS__)
-#define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__))
-static void
-test_varargs_macros (void)
-{
-  int x = 1234;
-  int y = 5678;
-  debug ("Flag");
-  debug ("X = %d\n", x);
-  showlist (The first, second, and third items.);
-  report (x>y, "x is %d but y is %d", x, y);
-}
-
-// Check long long types.
-#define BIG64 18446744073709551615ull
-#define BIG32 4294967295ul
-#define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0)
-#if !BIG_OK
-  your preprocessor is broken;
-#endif
-#if BIG_OK
-#else
-  your preprocessor is broken;
-#endif
-static long long int bignum = -9223372036854775807LL;
-static unsigned long long int ubignum = BIG64;
-
-struct incomplete_array
-{
-  int datasize;
-  double data[];
-};
-
-struct named_init {
-  int number;
-  const wchar_t *name;
-  double average;
-};
-
-typedef const char *ccp;
-
-static inline int
-test_restrict (ccp restrict text)
-{
-  // See if C++-style comments work.
-  // Iterate through items via the restricted pointer.
-  // Also check for declarations in for loops.
-  for (unsigned int i = 0; *(text+i) != '\0'; ++i)
-    continue;
-  return 0;
-}
-
-// Check varargs and va_copy.
-static void
-test_varargs (const char *format, ...)
-{
-  va_list args;
-  va_start (args, format);
-  va_list args_copy;
-  va_copy (args_copy, args);
-
-  const char *str;
-  int number;
-  float fnumber;
-
-  while (*format)
-    {
-      switch (*format++)
-	{
-	case 's': // string
-	  str = va_arg (args_copy, const char *);
-	  break;
-	case 'd': // int
-	  number = va_arg (args_copy, int);
-	  break;
-	case 'f': // float
-	  fnumber = va_arg (args_copy, double);
-	  break;
-	default:
-	  break;
-	}
-    }
-  va_end (args_copy);
-  va_end (args);
-}
-
-int
-main ()
-{
-
-  // Check bool.
-  _Bool success = false;
-
-  // Check restrict.
-  if (test_restrict ("String literal") == 0)
-    success = true;
-  char *restrict newvar = "Another string";
-
-  // Check varargs.
-  test_varargs ("s, d' f .", "string", 65, 34.234);
-  test_varargs_macros ();
-
-  // Check flexible array members.
-  struct incomplete_array *ia =
-    malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10));
-  ia->datasize = 10;
-  for (int i = 0; i < ia->datasize; ++i)
-    ia->data[i] = i * 1.234;
-
-  // Check named initializers.
-  struct named_init ni = {
-    .number = 34,
-    .name = L"Test wide string",
-    .average = 543.34343,
-  };
-
-  ni.number = 58;
-
-  int dynamic_array[ni.number];
-  dynamic_array[ni.number - 1] = 543;
-
-  // work around unused variable warnings
-  return (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == 'x'
-	  || dynamic_array[ni.number - 1] != 543);
-
-  ;
-  return 0;
-}
-_ACEOF
-for ac_arg in '' -std=gnu99 -c99 -qlanglvl=extc99
-do
-  CC="$ac_save_CC $ac_arg"
-  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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  ac_cv_prog_cc_c99=$ac_arg
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext
-  test "x$ac_cv_prog_cc_c99" != "xno" && break
-done
-rm -f conftest.$ac_ext
-CC=$ac_save_CC
-
-fi
-# AC_CACHE_VAL
-case "x$ac_cv_prog_cc_c99" in
-  x)
-    { echo "$as_me:$LINENO: result: none needed" >&5
-echo "${ECHO_T}none needed" >&6; } ;;
-  xno)
-    { echo "$as_me:$LINENO: result: unsupported" >&5
-echo "${ECHO_T}unsupported" >&6; } ;;
-  *)
-    CC="$CC $ac_cv_prog_cc_c99"
-    { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c99" >&5
-echo "${ECHO_T}$ac_cv_prog_cc_c99" >&6; } ;;
-esac
-if test "x$ac_cv_prog_cc_c99" != xno; then
-  ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99
-else
-  { echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5
-echo $ECHO_N "checking for $CC option to accept ISO C89... $ECHO_C" >&6; }
-if test "${ac_cv_prog_cc_c89+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  ac_cv_prog_cc_c89=no
-ac_save_CC=$CC
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <stdarg.h>
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-/* 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"
-  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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  ac_cv_prog_cc_c89=$ac_arg
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-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)
-    { echo "$as_me:$LINENO: result: none needed" >&5
-echo "${ECHO_T}none needed" >&6; } ;;
-  xno)
-    { echo "$as_me:$LINENO: result: unsupported" >&5
-echo "${ECHO_T}unsupported" >&6; } ;;
-  *)
-    CC="$CC $ac_cv_prog_cc_c89"
-    { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5
-echo "${ECHO_T}$ac_cv_prog_cc_c89" >&6; } ;;
-esac
-if test "x$ac_cv_prog_cc_c89" != xno; then
-  ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89
-else
-  ac_cv_prog_cc_stdc=no
-fi
-
-
-fi
-
- ;;
-esac
-  { echo "$as_me:$LINENO: checking for $CC option to accept ISO Standard C" >&5
-echo $ECHO_N "checking for $CC option to accept ISO Standard C... $ECHO_C" >&6; }
-  if test "${ac_cv_prog_cc_stdc+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-fi
-
-  case $ac_cv_prog_cc_stdc in
-  no) { echo "$as_me:$LINENO: result: unsupported" >&5
-echo "${ECHO_T}unsupported" >&6; } ;;
-  '') { echo "$as_me:$LINENO: result: none needed" >&5
-echo "${ECHO_T}none needed" >&6; } ;;
-  *) { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5
-echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6; } ;;
-esac
-
-
-
-{ echo "$as_me:$LINENO: checking for an ANSI C-conforming const" >&5
-echo $ECHO_N "checking for an ANSI C-conforming const... $ECHO_C" >&6; }
-if test "${ac_cv_c_const+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-
-int
-main ()
-{
-/* FIXME: Include the comments suggested by Paul. */
-#ifndef __cplusplus
-  /* Ultrix mips cc rejects this.  */
-  typedef int charset[2];
-  const charset cs;
-  /* SunOS 4.1.1 cc rejects this.  */
-  char const *const *pcpcc;
-  char **ppc;
-  /* NEC SVR4.0.2 mips cc rejects this.  */
-  struct point {int x, y;};
-  static struct point const zero = {0,0};
-  /* AIX XL C 1.02.0.0 rejects this.
-     It does not let you subtract one const X* pointer from another in
-     an arm of an if-expression whose if-part is not a constant
-     expression */
-  const char *g = "string";
-  pcpcc = &g + (g ? g-g : 0);
-  /* HPUX 7.0 cc rejects these. */
-  ++pcpcc;
-  ppc = (char**) pcpcc;
-  pcpcc = (char const *const *) ppc;
-  { /* SCO 3.2v4 cc rejects this.  */
-    char *t;
-    char const *s = 0 ? (char *) 0 : (char const *) 0;
-
-    *t++ = 0;
-    if (s) return 0;
-  }
-  { /* Someone thinks the Sun supposedly-ANSI compiler will reject this.  */
-    int x[] = {25, 17};
-    const int *foo = &x[0];
-    ++foo;
-  }
-  { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
-    typedef const int *iptr;
-    iptr p = 0;
-    ++p;
-  }
-  { /* AIX XL C 1.02.0.0 rejects this saying
-       "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
-    struct s { int j; const int *ap[3]; };
-    struct s *b; b->j = 5;
-  }
-  { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
-    const int foo = 10;
-    if (!foo) return 0;
-  }
-  return !cs[0] && !zero.x;
-#endif
-
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  ac_cv_c_const=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	ac_cv_c_const=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_c_const" >&5
-echo "${ECHO_T}$ac_cv_c_const" >&6; }
-if test $ac_cv_c_const = no; then
-
-cat >>confdefs.h <<\_ACEOF
-#define const
-_ACEOF
-
-fi
-
-
-{ echo "$as_me:$LINENO: checking for grep that handles long lines and -e" >&5
-echo $ECHO_N "checking for grep that handles long lines and -e... $ECHO_C" >&6; }
-if test "${ac_cv_path_GREP+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  # Extract the first word of "grep ggrep" to use in msg output
-if test -z "$GREP"; then
-set dummy grep ggrep; ac_prog_name=$2
-if test "${ac_cv_path_GREP+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  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"
-    { test -f "$ac_path_GREP" && $as_test_x "$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
-  echo $ECHO_N "0123456789$ECHO_C" >"conftest.in"
-  while :
-  do
-    cat "conftest.in" "conftest.in" >"conftest.tmp"
-    mv "conftest.tmp" "conftest.in"
-    cp "conftest.in" "conftest.nl"
-    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
-    ac_count=`expr $ac_count + 1`
-    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
-
-
-fi
-
-GREP="$ac_cv_path_GREP"
-if test -z "$GREP"; then
-  { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5
-echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;}
-   { (exit 1); exit 1; }; }
-fi
-
-else
-  ac_cv_path_GREP=$GREP
-fi
-
-
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_path_GREP" >&5
-echo "${ECHO_T}$ac_cv_path_GREP" >&6; }
- GREP="$ac_cv_path_GREP"
-
-
-{ echo "$as_me:$LINENO: checking for egrep" >&5
-echo $ECHO_N "checking for egrep... $ECHO_C" >&6; }
-if test "${ac_cv_path_EGREP+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
-   then ac_cv_path_EGREP="$GREP -E"
-   else
-     # Extract the first word of "egrep" to use in msg output
-if test -z "$EGREP"; then
-set dummy egrep; ac_prog_name=$2
-if test "${ac_cv_path_EGREP+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  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"
-    { test -f "$ac_path_EGREP" && $as_test_x "$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
-  echo $ECHO_N "0123456789$ECHO_C" >"conftest.in"
-  while :
-  do
-    cat "conftest.in" "conftest.in" >"conftest.tmp"
-    mv "conftest.tmp" "conftest.in"
-    cp "conftest.in" "conftest.nl"
-    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
-    ac_count=`expr $ac_count + 1`
-    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
-
-
-fi
-
-EGREP="$ac_cv_path_EGREP"
-if test -z "$EGREP"; then
-  { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5
-echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;}
-   { (exit 1); exit 1; }; }
-fi
-
-else
-  ac_cv_path_EGREP=$EGREP
-fi
-
-
-   fi
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_path_EGREP" >&5
-echo "${ECHO_T}$ac_cv_path_EGREP" >&6; }
- EGREP="$ac_cv_path_EGREP"
-
-
-{ echo "$as_me:$LINENO: checking for ANSI C header files" >&5
-echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6; }
-if test "${ac_cv_header_stdc+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <float.h>
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  ac_cv_header_stdc=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	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 >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <string.h>
-
-_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 -r conftest*
-
-fi
-
-if test $ac_cv_header_stdc = yes; then
-  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <stdlib.h>
-
-_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 -r 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 >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <ctype.h>
-#include <stdlib.h>
-#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
-rm -f conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  :
-else
-  echo "$as_me: program exited with status $ac_status" >&5
-echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-( exit $ac_status )
-ac_cv_header_stdc=no
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
-fi
-
-
-fi
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
-echo "${ECHO_T}$ac_cv_header_stdc" >&6; }
-if test $ac_cv_header_stdc = yes; then
-
-cat >>confdefs.h <<\_ACEOF
-#define STDC_HEADERS 1
-_ACEOF
-
-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=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
-{ echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-$ac_includes_default
-
-#include <$ac_header>
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  eval "$as_ac_Header=yes"
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	eval "$as_ac_Header=no"
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-ac_res=`eval echo '${'$as_ac_Header'}'`
-	       { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-if test `eval echo '${'$as_ac_Header'}'` = yes; then
-  cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-
-done
-
-
-{ echo "$as_me:$LINENO: checking for size_t" >&5
-echo $ECHO_N "checking for size_t... $ECHO_C" >&6; }
-if test "${ac_cv_type_size_t+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-$ac_includes_default
-typedef size_t ac__type_new_;
-int
-main ()
-{
-if ((ac__type_new_ *) 0)
-  return 0;
-if (sizeof (ac__type_new_))
-  return 0;
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  ac_cv_type_size_t=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	ac_cv_type_size_t=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_type_size_t" >&5
-echo "${ECHO_T}$ac_cv_type_size_t" >&6; }
-if test $ac_cv_type_size_t = yes; then
-  :
-else
-
-cat >>confdefs.h <<_ACEOF
-#define size_t unsigned int
-_ACEOF
-
-fi
-
-if test "x$ac_cv_prog_cc_stdc" = xno -o \
-        "x$ac_cv_c_const"      = xno -o \
-        "x$ac_cv_type_size_t"  = xno; then
-  { { echo "$as_me:$LINENO: error:
-    -------------------------------------------------------
-    An ANSI standard C library is required to build WCSLIB.
-
-    ERROR: WCSLIB configuration failure.
-    -------------------------------------------------------" >&5
-echo "$as_me: error:
-    -------------------------------------------------------
-    An ANSI standard C library is required to build WCSLIB.
-
-    ERROR: WCSLIB configuration failure.
-    -------------------------------------------------------" >&2;}
-   { (exit 1); exit 1; }; }
-fi
-
-# Check for data types (suggested by autoscan - off_t is only required by
-# fitshdr).
-{ echo "$as_me:$LINENO: checking for off_t" >&5
-echo $ECHO_N "checking for off_t... $ECHO_C" >&6; }
-if test "${ac_cv_type_off_t+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-$ac_includes_default
-typedef off_t ac__type_new_;
-int
-main ()
-{
-if ((ac__type_new_ *) 0)
-  return 0;
-if (sizeof (ac__type_new_))
-  return 0;
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  ac_cv_type_off_t=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	ac_cv_type_off_t=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_type_off_t" >&5
-echo "${ECHO_T}$ac_cv_type_off_t" >&6; }
-if test $ac_cv_type_off_t = yes; then
-  :
-else
-
-cat >>confdefs.h <<_ACEOF
-#define off_t long int
-_ACEOF
-
-fi
-
-
-  { echo "$as_me:$LINENO: checking for int8_t" >&5
-echo $ECHO_N "checking for int8_t... $ECHO_C" >&6; }
-if test "${ac_cv_c_int8_t+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  ac_cv_c_int8_t=no
-     for ac_type in 'int8_t' 'int' 'long int' \
-	 'long long int' 'short int' 'signed char'; do
-       cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-$ac_includes_default
-int
-main ()
-{
-static int test_array [1 - 2 * !(0 < ($ac_type) (((($ac_type) 1 << (8 - 2)) - 1) * 2 + 1))];
-test_array [0] = 0
-
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-$ac_includes_default
-int
-main ()
-{
-static int test_array [1 - 2 * !(($ac_type) (((($ac_type) 1 << (8 - 2)) - 1) * 2 + 1)
-	         < ($ac_type) (((($ac_type) 1 << (8 - 2)) - 1) * 2 + 2))];
-test_array [0] = 0
-
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  :
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	case $ac_type in
-  int8_t) ac_cv_c_int8_t=yes ;;
-  *) ac_cv_c_int8_t=$ac_type ;;
-esac
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-       test "$ac_cv_c_int8_t" != no && break
-     done
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_c_int8_t" >&5
-echo "${ECHO_T}$ac_cv_c_int8_t" >&6; }
-  case $ac_cv_c_int8_t in #(
-  no|yes) ;; #(
-  *)
-
-cat >>confdefs.h <<_ACEOF
-#define int8_t $ac_cv_c_int8_t
-_ACEOF
-;;
-  esac
-
-
-  { echo "$as_me:$LINENO: checking for int16_t" >&5
-echo $ECHO_N "checking for int16_t... $ECHO_C" >&6; }
-if test "${ac_cv_c_int16_t+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  ac_cv_c_int16_t=no
-     for ac_type in 'int16_t' 'int' 'long int' \
-	 'long long int' 'short int' 'signed char'; do
-       cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-$ac_includes_default
-int
-main ()
-{
-static int test_array [1 - 2 * !(0 < ($ac_type) (((($ac_type) 1 << (16 - 2)) - 1) * 2 + 1))];
-test_array [0] = 0
-
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-$ac_includes_default
-int
-main ()
-{
-static int test_array [1 - 2 * !(($ac_type) (((($ac_type) 1 << (16 - 2)) - 1) * 2 + 1)
-	         < ($ac_type) (((($ac_type) 1 << (16 - 2)) - 1) * 2 + 2))];
-test_array [0] = 0
-
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  :
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	case $ac_type in
-  int16_t) ac_cv_c_int16_t=yes ;;
-  *) ac_cv_c_int16_t=$ac_type ;;
-esac
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-       test "$ac_cv_c_int16_t" != no && break
-     done
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_c_int16_t" >&5
-echo "${ECHO_T}$ac_cv_c_int16_t" >&6; }
-  case $ac_cv_c_int16_t in #(
-  no|yes) ;; #(
-  *)
-
-cat >>confdefs.h <<_ACEOF
-#define int16_t $ac_cv_c_int16_t
-_ACEOF
-;;
-  esac
-
-
-  { echo "$as_me:$LINENO: checking for int32_t" >&5
-echo $ECHO_N "checking for int32_t... $ECHO_C" >&6; }
-if test "${ac_cv_c_int32_t+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  ac_cv_c_int32_t=no
-     for ac_type in 'int32_t' 'int' 'long int' \
-	 'long long int' 'short int' 'signed char'; do
-       cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-$ac_includes_default
-int
-main ()
-{
-static int test_array [1 - 2 * !(0 < ($ac_type) (((($ac_type) 1 << (32 - 2)) - 1) * 2 + 1))];
-test_array [0] = 0
-
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-$ac_includes_default
-int
-main ()
-{
-static int test_array [1 - 2 * !(($ac_type) (((($ac_type) 1 << (32 - 2)) - 1) * 2 + 1)
-	         < ($ac_type) (((($ac_type) 1 << (32 - 2)) - 1) * 2 + 2))];
-test_array [0] = 0
-
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  :
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	case $ac_type in
-  int32_t) ac_cv_c_int32_t=yes ;;
-  *) ac_cv_c_int32_t=$ac_type ;;
-esac
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-       test "$ac_cv_c_int32_t" != no && break
-     done
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_c_int32_t" >&5
-echo "${ECHO_T}$ac_cv_c_int32_t" >&6; }
-  case $ac_cv_c_int32_t in #(
-  no|yes) ;; #(
-  *)
-
-cat >>confdefs.h <<_ACEOF
-#define int32_t $ac_cv_c_int32_t
-_ACEOF
-;;
-  esac
-
-
-  { echo "$as_me:$LINENO: checking for uint8_t" >&5
-echo $ECHO_N "checking for uint8_t... $ECHO_C" >&6; }
-if test "${ac_cv_c_uint8_t+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  ac_cv_c_uint8_t=no
-     for ac_type in 'uint8_t' 'unsigned int' 'unsigned long int' \
-	 'unsigned long long int' 'unsigned short int' 'unsigned char'; do
-       cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-$ac_includes_default
-int
-main ()
-{
-static int test_array [1 - 2 * !(($ac_type) -1 >> (8 - 1) == 1)];
-test_array [0] = 0
-
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  case $ac_type in
-  uint8_t) ac_cv_c_uint8_t=yes ;;
-  *) ac_cv_c_uint8_t=$ac_type ;;
-esac
-
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-       test "$ac_cv_c_uint8_t" != no && break
-     done
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_c_uint8_t" >&5
-echo "${ECHO_T}$ac_cv_c_uint8_t" >&6; }
-  case $ac_cv_c_uint8_t in #(
-  no|yes) ;; #(
-  *)
-
-cat >>confdefs.h <<\_ACEOF
-#define _UINT8_T 1
-_ACEOF
-
-
-cat >>confdefs.h <<_ACEOF
-#define uint8_t $ac_cv_c_uint8_t
-_ACEOF
-;;
-  esac
-
-
-  { echo "$as_me:$LINENO: checking for uint16_t" >&5
-echo $ECHO_N "checking for uint16_t... $ECHO_C" >&6; }
-if test "${ac_cv_c_uint16_t+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  ac_cv_c_uint16_t=no
-     for ac_type in 'uint16_t' 'unsigned int' 'unsigned long int' \
-	 'unsigned long long int' 'unsigned short int' 'unsigned char'; do
-       cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-$ac_includes_default
-int
-main ()
-{
-static int test_array [1 - 2 * !(($ac_type) -1 >> (16 - 1) == 1)];
-test_array [0] = 0
-
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  case $ac_type in
-  uint16_t) ac_cv_c_uint16_t=yes ;;
-  *) ac_cv_c_uint16_t=$ac_type ;;
-esac
-
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-       test "$ac_cv_c_uint16_t" != no && break
-     done
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_c_uint16_t" >&5
-echo "${ECHO_T}$ac_cv_c_uint16_t" >&6; }
-  case $ac_cv_c_uint16_t in #(
-  no|yes) ;; #(
-  *)
-
-
-cat >>confdefs.h <<_ACEOF
-#define uint16_t $ac_cv_c_uint16_t
-_ACEOF
-;;
-  esac
-
-
-  { echo "$as_me:$LINENO: checking for uint32_t" >&5
-echo $ECHO_N "checking for uint32_t... $ECHO_C" >&6; }
-if test "${ac_cv_c_uint32_t+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  ac_cv_c_uint32_t=no
-     for ac_type in 'uint32_t' 'unsigned int' 'unsigned long int' \
-	 'unsigned long long int' 'unsigned short int' 'unsigned char'; do
-       cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-$ac_includes_default
-int
-main ()
-{
-static int test_array [1 - 2 * !(($ac_type) -1 >> (32 - 1) == 1)];
-test_array [0] = 0
-
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  case $ac_type in
-  uint32_t) ac_cv_c_uint32_t=yes ;;
-  *) ac_cv_c_uint32_t=$ac_type ;;
-esac
-
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-       test "$ac_cv_c_uint32_t" != no && break
-     done
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_c_uint32_t" >&5
-echo "${ECHO_T}$ac_cv_c_uint32_t" >&6; }
-  case $ac_cv_c_uint32_t in #(
-  no|yes) ;; #(
-  *)
-
-cat >>confdefs.h <<\_ACEOF
-#define _UINT32_T 1
-_ACEOF
-
-
-cat >>confdefs.h <<_ACEOF
-#define uint32_t $ac_cv_c_uint32_t
-_ACEOF
-;;
-  esac
-
-
-# Check for ANSI C headers.
-{ echo "$as_me:$LINENO: checking for ANSI C header files" >&5
-echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6; }
-if test "${ac_cv_header_stdc+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <float.h>
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  ac_cv_header_stdc=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	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 >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <string.h>
-
-_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 -r conftest*
-
-fi
-
-if test $ac_cv_header_stdc = yes; then
-  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <stdlib.h>
-
-_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 -r 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 >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <ctype.h>
-#include <stdlib.h>
-#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
-rm -f conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  :
-else
-  echo "$as_me: program exited with status $ac_status" >&5
-echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-( exit $ac_status )
-ac_cv_header_stdc=no
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
-fi
-
-
-fi
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
-echo "${ECHO_T}$ac_cv_header_stdc" >&6; }
-if test $ac_cv_header_stdc = yes; then
-
-cat >>confdefs.h <<\_ACEOF
-#define STDC_HEADERS 1
-_ACEOF
-
-fi
-
-
-
-
-
-
-
-
-
-
-for ac_header in ctype.h errno.h limits.h math.h setjmp.h stdarg.h stdio.h \
-                  stdlib.h string.h
-do
-as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
-  { echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-fi
-ac_res=`eval echo '${'$as_ac_Header'}'`
-	       { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-else
-  # Is the header compilable?
-{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
-echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-$ac_includes_default
-#include <$ac_header>
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  ac_header_compiler=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	ac_header_compiler=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
-echo "${ECHO_T}$ac_header_compiler" >&6; }
-
-# Is the header present?
-{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
-echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <$ac_header>
-_ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } >/dev/null && {
-	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       }; then
-  ac_header_preproc=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-  ac_header_preproc=no
-fi
-
-rm -f conftest.err conftest.$ac_ext
-{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
-echo "${ECHO_T}$ac_header_preproc" >&6; }
-
-# So?  What about this header?
-case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
-  yes:no: )
-    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
-echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
-    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
-    ac_header_preproc=yes
-    ;;
-  no:yes:* )
-    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
-echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
-    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
-echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
-    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
-echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
-    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
-echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
-    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
-    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
-echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
-    ( cat <<\_ASBOX
-## ------------------------------------- ##
-## Report this to mcalabre at atnf.csiro.au ##
-## ------------------------------------- ##
-_ASBOX
-     ) | sed "s/^/$as_me: WARNING:     /" >&2
-    ;;
-esac
-{ echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  eval "$as_ac_Header=\$ac_header_preproc"
-fi
-ac_res=`eval echo '${'$as_ac_Header'}'`
-	       { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-
-fi
-if test `eval echo '${'$as_ac_Header'}'` = yes; then
-  cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-
-done
-
-if test "x$ac_cv_header_stdc" = xno; then
-  { { echo "$as_me:$LINENO: error:
-    -------------------------------------------------------------------
-    An ANSI standard C library is required to build WCSLIB.  One of the
-    ANSI C header files it requires is missing or unusable.
-
-    ERROR: WCSLIB configuration failure.
-    -------------------------------------------------------------------" >&5
-echo "$as_me: error:
-    -------------------------------------------------------------------
-    An ANSI standard C library is required to build WCSLIB.  One of the
-    ANSI C header files it requires is missing or unusable.
-
-    ERROR: WCSLIB configuration failure.
-    -------------------------------------------------------------------" >&2;}
-   { (exit 1); exit 1; }; }
-fi
-
-# Checks for ANSI C library functions (suggested by autoscan - fseeko and
-# stat are only required by fitshdr).
-
-{ echo "$as_me:$LINENO: checking for floor in -lm" >&5
-echo $ECHO_N "checking for floor in -lm... $ECHO_C" >&6; }
-if test "${ac_cv_lib_m_floor+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  ac_check_lib_save_LIBS=$LIBS
-LIBS="-lm  $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* 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 floor ();
-int
-main ()
-{
-return floor ();
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest$ac_exeext &&
-       $as_test_x conftest$ac_exeext; then
-  ac_cv_lib_m_floor=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	ac_cv_lib_m_floor=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
-      conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_lib_m_floor" >&5
-echo "${ECHO_T}$ac_cv_lib_m_floor" >&6; }
-if test $ac_cv_lib_m_floor = yes; then
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBM 1
-_ACEOF
-
-  LIBS="-lm $LIBS"
-
-fi
-
-{ echo "$as_me:$LINENO: checking for _LARGEFILE_SOURCE value needed for large files" >&5
-echo $ECHO_N "checking for _LARGEFILE_SOURCE value needed for large files... $ECHO_C" >&6; }
-if test "${ac_cv_sys_largefile_source+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  while :; do
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <stdio.h>
-int
-main ()
-{
-return fseeko (stdin, 0, 0) && (fseeko) (stdin, 0, 0);
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest$ac_exeext &&
-       $as_test_x conftest$ac_exeext; then
-  ac_cv_sys_largefile_source=no; break
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
-      conftest$ac_exeext conftest.$ac_ext
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#define _LARGEFILE_SOURCE 1
-#include <stdio.h>
-int
-main ()
-{
-return fseeko (stdin, 0, 0) && (fseeko) (stdin, 0, 0);
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest$ac_exeext &&
-       $as_test_x conftest$ac_exeext; then
-  ac_cv_sys_largefile_source=1; break
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
-      conftest$ac_exeext conftest.$ac_ext
-  ac_cv_sys_largefile_source=unknown
-  break
-done
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_sys_largefile_source" >&5
-echo "${ECHO_T}$ac_cv_sys_largefile_source" >&6; }
-case $ac_cv_sys_largefile_source in #(
-  no | unknown) ;;
-  *)
-cat >>confdefs.h <<_ACEOF
-#define _LARGEFILE_SOURCE $ac_cv_sys_largefile_source
-_ACEOF
-;;
-esac
-rm -f -r conftest*
-
-# We used to try defining _XOPEN_SOURCE=500 too, to work around a bug
-# in glibc 2.1.3, but that breaks too many other things.
-# If you want fseeko and ftello with glibc, upgrade to a fixed glibc.
-if test $ac_cv_sys_largefile_source != unknown; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_FSEEKO 1
-_ACEOF
-
-fi
-
-
-for ac_header in stdlib.h
-do
-as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
-  { echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-fi
-ac_res=`eval echo '${'$as_ac_Header'}'`
-	       { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-else
-  # Is the header compilable?
-{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
-echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-$ac_includes_default
-#include <$ac_header>
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  ac_header_compiler=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	ac_header_compiler=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
-echo "${ECHO_T}$ac_header_compiler" >&6; }
-
-# Is the header present?
-{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
-echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <$ac_header>
-_ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } >/dev/null && {
-	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       }; then
-  ac_header_preproc=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-  ac_header_preproc=no
-fi
-
-rm -f conftest.err conftest.$ac_ext
-{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
-echo "${ECHO_T}$ac_header_preproc" >&6; }
-
-# So?  What about this header?
-case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
-  yes:no: )
-    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
-echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
-    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
-    ac_header_preproc=yes
-    ;;
-  no:yes:* )
-    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
-echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
-    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
-echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
-    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
-echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
-    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
-echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
-    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
-    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
-echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
-    ( cat <<\_ASBOX
-## ------------------------------------- ##
-## Report this to mcalabre at atnf.csiro.au ##
-## ------------------------------------- ##
-_ASBOX
-     ) | sed "s/^/$as_me: WARNING:     /" >&2
-    ;;
-esac
-{ echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  eval "$as_ac_Header=\$ac_header_preproc"
-fi
-ac_res=`eval echo '${'$as_ac_Header'}'`
-	       { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-
-fi
-if test `eval echo '${'$as_ac_Header'}'` = yes; then
-  cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-
-done
-
-{ echo "$as_me:$LINENO: checking for GNU libc compatible malloc" >&5
-echo $ECHO_N "checking for GNU libc compatible malloc... $ECHO_C" >&6; }
-if test "${ac_cv_func_malloc_0_nonnull+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  if test "$cross_compiling" = yes; then
-  ac_cv_func_malloc_0_nonnull=no
-else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#if defined STDC_HEADERS || defined HAVE_STDLIB_H
-# include <stdlib.h>
-#else
-char *malloc ();
-#endif
-
-int
-main ()
-{
-return ! malloc (0);
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  ac_cv_func_malloc_0_nonnull=yes
-else
-  echo "$as_me: program exited with status $ac_status" >&5
-echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-( exit $ac_status )
-ac_cv_func_malloc_0_nonnull=no
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
-fi
-
-
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_func_malloc_0_nonnull" >&5
-echo "${ECHO_T}$ac_cv_func_malloc_0_nonnull" >&6; }
-if test $ac_cv_func_malloc_0_nonnull = yes; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_MALLOC 1
-_ACEOF
-
-else
-  cat >>confdefs.h <<\_ACEOF
-#define HAVE_MALLOC 0
-_ACEOF
-
-   case " $LIBOBJS " in
-  *" malloc.$ac_objext "* ) ;;
-  *) LIBOBJS="$LIBOBJS malloc.$ac_objext"
- ;;
-esac
-
-
-cat >>confdefs.h <<\_ACEOF
-#define malloc rpl_malloc
-_ACEOF
-
-fi
-
-
-
-
-for ac_header in stdlib.h
-do
-as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
-  { echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-fi
-ac_res=`eval echo '${'$as_ac_Header'}'`
-	       { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-else
-  # Is the header compilable?
-{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
-echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-$ac_includes_default
-#include <$ac_header>
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  ac_header_compiler=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	ac_header_compiler=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
-echo "${ECHO_T}$ac_header_compiler" >&6; }
-
-# Is the header present?
-{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
-echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <$ac_header>
-_ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } >/dev/null && {
-	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       }; then
-  ac_header_preproc=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-  ac_header_preproc=no
-fi
-
-rm -f conftest.err conftest.$ac_ext
-{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
-echo "${ECHO_T}$ac_header_preproc" >&6; }
-
-# So?  What about this header?
-case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
-  yes:no: )
-    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
-echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
-    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
-    ac_header_preproc=yes
-    ;;
-  no:yes:* )
-    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
-echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
-    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
-echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
-    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
-echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
-    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
-echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
-    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
-    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
-echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
-    ( cat <<\_ASBOX
-## ------------------------------------- ##
-## Report this to mcalabre at atnf.csiro.au ##
-## ------------------------------------- ##
-_ASBOX
-     ) | sed "s/^/$as_me: WARNING:     /" >&2
-    ;;
-esac
-{ echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  eval "$as_ac_Header=\$ac_header_preproc"
-fi
-ac_res=`eval echo '${'$as_ac_Header'}'`
-	       { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-
-fi
-if test `eval echo '${'$as_ac_Header'}'` = yes; then
-  cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-
-done
-
-{ echo "$as_me:$LINENO: checking for GNU libc compatible realloc" >&5
-echo $ECHO_N "checking for GNU libc compatible realloc... $ECHO_C" >&6; }
-if test "${ac_cv_func_realloc_0_nonnull+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  if test "$cross_compiling" = yes; then
-  ac_cv_func_realloc_0_nonnull=no
-else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#if defined STDC_HEADERS || defined HAVE_STDLIB_H
-# include <stdlib.h>
-#else
-char *realloc ();
-#endif
-
-int
-main ()
-{
-return ! realloc (0, 0);
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  ac_cv_func_realloc_0_nonnull=yes
-else
-  echo "$as_me: program exited with status $ac_status" >&5
-echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-( exit $ac_status )
-ac_cv_func_realloc_0_nonnull=no
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
-fi
-
-
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_func_realloc_0_nonnull" >&5
-echo "${ECHO_T}$ac_cv_func_realloc_0_nonnull" >&6; }
-if test $ac_cv_func_realloc_0_nonnull = yes; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_REALLOC 1
-_ACEOF
-
-else
-  cat >>confdefs.h <<\_ACEOF
-#define HAVE_REALLOC 0
-_ACEOF
-
-   case " $LIBOBJS " in
-  *" realloc.$ac_objext "* ) ;;
-  *) LIBOBJS="$LIBOBJS realloc.$ac_objext"
- ;;
-esac
-
-
-cat >>confdefs.h <<\_ACEOF
-#define realloc rpl_realloc
-_ACEOF
-
-fi
-
-
-
-{ echo "$as_me:$LINENO: checking for function prototypes" >&5
-echo $ECHO_N "checking for function prototypes... $ECHO_C" >&6; }
-if test "$ac_cv_prog_cc_c89" != no; then
-  { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-
-cat >>confdefs.h <<\_ACEOF
-#define PROTOTYPES 1
-_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define __PROTOTYPES 1
-_ACEOF
-
-else
-  { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-
-{ echo "$as_me:$LINENO: checking whether setvbuf arguments are reversed" >&5
-echo $ECHO_N "checking whether setvbuf arguments are reversed... $ECHO_C" >&6; }
-if test "${ac_cv_func_setvbuf_reversed+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  ac_cv_func_setvbuf_reversed=no
-   cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <stdio.h>
-#	  ifdef PROTOTYPES
-	   int (setvbuf) (FILE *, int, char *, size_t);
-#	  endif
-int
-main ()
-{
-char buf; return setvbuf (stdout, _IOLBF, &buf, 1);
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest$ac_exeext &&
-       $as_test_x conftest$ac_exeext; then
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <stdio.h>
-#	     ifdef PROTOTYPES
-	      int (setvbuf) (FILE *, int, char *, size_t);
-#	     endif
-int
-main ()
-{
-char buf; return setvbuf (stdout, &buf, _IOLBF, 1);
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest$ac_exeext &&
-       $as_test_x conftest$ac_exeext; then
-  # It compiles and links either way, so it must not be declared
-	 # with a prototype and most likely this is a K&R C compiler.
-	 # Try running it.
-	 if test "$cross_compiling" = yes; then
-  : # Assume setvbuf is not reversed when cross-compiling.
-else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-$ac_includes_default
-int
-main ()
-{
-/* This call has the arguments reversed.
-		   A reversed system may check and see that the address of buf
-		   is not _IOLBF, _IONBF, or _IOFBF, and return nonzero.  */
-		char buf;
-		if (setvbuf (stdout, _IOLBF, &buf, 1) != 0)
-		  return 1;
-		putchar ('\r');
-		return 0; /* Non-reversed systems SEGV here.  */
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  ac_cv_func_setvbuf_reversed=yes
-else
-  echo "$as_me: program exited with status $ac_status" >&5
-echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
-fi
-
-
-	ac_cv_func_setvbuf_reversed=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
-      conftest$ac_exeext conftest.$ac_ext
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
-      conftest$ac_exeext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_func_setvbuf_reversed" >&5
-echo "${ECHO_T}$ac_cv_func_setvbuf_reversed" >&6; }
-if test $ac_cv_func_setvbuf_reversed = yes; then
-
-cat >>confdefs.h <<\_ACEOF
-#define SETVBUF_REVERSED 1
-_ACEOF
-
-fi
-
-{ echo "$as_me:$LINENO: checking whether lstat dereferences a symlink specified with a trailing slash" >&5
-echo $ECHO_N "checking whether lstat dereferences a symlink specified with a trailing slash... $ECHO_C" >&6; }
-if test "${ac_cv_func_lstat_dereferences_slashed_symlink+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  rm -f conftest.sym conftest.file
-echo >conftest.file
-if test "$as_ln_s" = "ln -s" && ln -s conftest.file conftest.sym; then
-  if test "$cross_compiling" = yes; then
-  ac_cv_func_lstat_dereferences_slashed_symlink=no
-else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-$ac_includes_default
-int
-main ()
-{
-struct stat sbuf;
-     /* Linux will dereference the symlink and fail.
-	That is better in the sense that it means we will not
-	have to compile and use the lstat wrapper.  */
-     return lstat ("conftest.sym/", &sbuf) == 0;
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  ac_cv_func_lstat_dereferences_slashed_symlink=yes
-else
-  echo "$as_me: program exited with status $ac_status" >&5
-echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-( exit $ac_status )
-ac_cv_func_lstat_dereferences_slashed_symlink=no
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
-fi
-
-
-else
-  # If the `ln -s' command failed, then we probably don't even
-  # have an lstat function.
-  ac_cv_func_lstat_dereferences_slashed_symlink=no
-fi
-rm -f conftest.sym conftest.file
-
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_func_lstat_dereferences_slashed_symlink" >&5
-echo "${ECHO_T}$ac_cv_func_lstat_dereferences_slashed_symlink" >&6; }
-
-test $ac_cv_func_lstat_dereferences_slashed_symlink = yes &&
-
-cat >>confdefs.h <<_ACEOF
-#define LSTAT_FOLLOWS_SLASHED_SYMLINK 1
-_ACEOF
-
-
-if test $ac_cv_func_lstat_dereferences_slashed_symlink = no; then
-  case " $LIBOBJS " in
-  *" lstat.$ac_objext "* ) ;;
-  *) LIBOBJS="$LIBOBJS lstat.$ac_objext"
- ;;
-esac
-
-fi
-
-{ echo "$as_me:$LINENO: checking whether stat accepts an empty string" >&5
-echo $ECHO_N "checking whether stat accepts an empty string... $ECHO_C" >&6; }
-if test "${ac_cv_func_stat_empty_string_bug+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  if test "$cross_compiling" = yes; then
-  ac_cv_func_stat_empty_string_bug=yes
-else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-$ac_includes_default
-int
-main ()
-{
-struct stat sbuf;
-  return stat ("", &sbuf) == 0;
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  ac_cv_func_stat_empty_string_bug=no
-else
-  echo "$as_me: program exited with status $ac_status" >&5
-echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-( exit $ac_status )
-ac_cv_func_stat_empty_string_bug=yes
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
-fi
-
-
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_func_stat_empty_string_bug" >&5
-echo "${ECHO_T}$ac_cv_func_stat_empty_string_bug" >&6; }
-if test $ac_cv_func_stat_empty_string_bug = yes; then
-  case " $LIBOBJS " in
-  *" stat.$ac_objext "* ) ;;
-  *) LIBOBJS="$LIBOBJS stat.$ac_objext"
- ;;
-esac
-
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_STAT_EMPTY_STRING_BUG 1
-_ACEOF
-
-fi
-
-
-for ac_func in vprintf
-do
-as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
-{ echo "$as_me:$LINENO: checking for $ac_func" >&5
-echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
-if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
-   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
-#define $ac_func innocuous_$ac_func
-
-/* System header to define __stub macros and hopefully few prototypes,
-    which can conflict with char $ac_func (); below.
-    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
-    <limits.h> exists even on freestanding compilers.  */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef $ac_func
-
-/* 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 $ac_func ();
-/* The GNU C library defines this for functions which it implements
-    to always fail with ENOSYS.  Some functions are actually named
-    something starting with __ and the normal name is an alias.  */
-#if defined __stub_$ac_func || defined __stub___$ac_func
-choke me
-#endif
-
-int
-main ()
-{
-return $ac_func ();
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest$ac_exeext &&
-       $as_test_x conftest$ac_exeext; then
-  eval "$as_ac_var=yes"
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	eval "$as_ac_var=no"
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
-      conftest$ac_exeext conftest.$ac_ext
-fi
-ac_res=`eval echo '${'$as_ac_var'}'`
-	       { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-if test `eval echo '${'$as_ac_var'}'` = yes; then
-  cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-{ echo "$as_me:$LINENO: checking for _doprnt" >&5
-echo $ECHO_N "checking for _doprnt... $ECHO_C" >&6; }
-if test "${ac_cv_func__doprnt+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-/* Define _doprnt to an innocuous variant, in case <limits.h> declares _doprnt.
-   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
-#define _doprnt innocuous__doprnt
-
-/* System header to define __stub macros and hopefully few prototypes,
-    which can conflict with char _doprnt (); below.
-    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
-    <limits.h> exists even on freestanding compilers.  */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef _doprnt
-
-/* 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 _doprnt ();
-/* The GNU C library defines this for functions which it implements
-    to always fail with ENOSYS.  Some functions are actually named
-    something starting with __ and the normal name is an alias.  */
-#if defined __stub__doprnt || defined __stub____doprnt
-choke me
-#endif
-
-int
-main ()
-{
-return _doprnt ();
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest$ac_exeext &&
-       $as_test_x conftest$ac_exeext; then
-  ac_cv_func__doprnt=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	ac_cv_func__doprnt=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
-      conftest$ac_exeext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_func__doprnt" >&5
-echo "${ECHO_T}$ac_cv_func__doprnt" >&6; }
-if test $ac_cv_func__doprnt = yes; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_DOPRNT 1
-_ACEOF
-
-fi
-
-fi
-done
-
-
-
-
-
-
-
-
-for ac_func in floor memset pow sqrt strchr strstr
-do
-as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
-{ echo "$as_me:$LINENO: checking for $ac_func" >&5
-echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
-if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
-   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
-#define $ac_func innocuous_$ac_func
-
-/* System header to define __stub macros and hopefully few prototypes,
-    which can conflict with char $ac_func (); below.
-    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
-    <limits.h> exists even on freestanding compilers.  */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef $ac_func
-
-/* 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 $ac_func ();
-/* The GNU C library defines this for functions which it implements
-    to always fail with ENOSYS.  Some functions are actually named
-    something starting with __ and the normal name is an alias.  */
-#if defined __stub_$ac_func || defined __stub___$ac_func
-choke me
-#endif
-
-int
-main ()
-{
-return $ac_func ();
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest$ac_exeext &&
-       $as_test_x conftest$ac_exeext; then
-  eval "$as_ac_var=yes"
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	eval "$as_ac_var=no"
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
-      conftest$ac_exeext conftest.$ac_ext
-fi
-ac_res=`eval echo '${'$as_ac_var'}'`
-	       { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-if test `eval echo '${'$as_ac_var'}'` = yes; then
-  cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
-
-# System libraries that may be required by WCSLIB itself.
-# SunOS, extra maths functions.
-{ echo "$as_me:$LINENO: checking for cosd in -lsunmath" >&5
-echo $ECHO_N "checking for cosd in -lsunmath... $ECHO_C" >&6; }
-if test "${ac_cv_lib_sunmath_cosd+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  ac_check_lib_save_LIBS=$LIBS
-LIBS="-lsunmath  $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* 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 cosd ();
-int
-main ()
-{
-return cosd ();
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest$ac_exeext &&
-       $as_test_x conftest$ac_exeext; then
-  ac_cv_lib_sunmath_cosd=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	ac_cv_lib_sunmath_cosd=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
-      conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_lib_sunmath_cosd" >&5
-echo "${ECHO_T}$ac_cv_lib_sunmath_cosd" >&6; }
-if test $ac_cv_lib_sunmath_cosd = yes; then
-  LIBS="-lsunmath $LIBS"
-fi
-
-
-# See if we can find sincos().
-
-for ac_func in sincos
-do
-as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
-{ echo "$as_me:$LINENO: checking for $ac_func" >&5
-echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
-if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
-   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
-#define $ac_func innocuous_$ac_func
-
-/* System header to define __stub macros and hopefully few prototypes,
-    which can conflict with char $ac_func (); below.
-    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
-    <limits.h> exists even on freestanding compilers.  */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef $ac_func
-
-/* 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 $ac_func ();
-/* The GNU C library defines this for functions which it implements
-    to always fail with ENOSYS.  Some functions are actually named
-    something starting with __ and the normal name is an alias.  */
-#if defined __stub_$ac_func || defined __stub___$ac_func
-choke me
-#endif
-
-int
-main ()
-{
-return $ac_func ();
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest$ac_exeext &&
-       $as_test_x conftest$ac_exeext; then
-  eval "$as_ac_var=yes"
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	eval "$as_ac_var=no"
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
-      conftest$ac_exeext conftest.$ac_ext
-fi
-ac_res=`eval echo '${'$as_ac_var'}'`
-	       { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-if test `eval echo '${'$as_ac_var'}'` = yes; then
-  cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
-
-# Check the size and availability of integer data types.
-{ echo "$as_me:$LINENO: checking for int" >&5
-echo $ECHO_N "checking for int... $ECHO_C" >&6; }
-if test "${ac_cv_type_int+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-$ac_includes_default
-typedef int ac__type_new_;
-int
-main ()
-{
-if ((ac__type_new_ *) 0)
-  return 0;
-if (sizeof (ac__type_new_))
-  return 0;
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  ac_cv_type_int=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	ac_cv_type_int=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_type_int" >&5
-echo "${ECHO_T}$ac_cv_type_int" >&6; }
-
-# The cast to long int works around a bug in the HP C Compiler
-# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
-# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
-# This bug is HP SR number 8606223364.
-{ echo "$as_me:$LINENO: checking size of int" >&5
-echo $ECHO_N "checking size of int... $ECHO_C" >&6; }
-if test "${ac_cv_sizeof_int+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  if test "$cross_compiling" = yes; then
-  # Depending upon the size, compute the lo and hi bounds.
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-$ac_includes_default
-   typedef int ac__type_sizeof_;
-int
-main ()
-{
-static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= 0)];
-test_array [0] = 0
-
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  ac_lo=0 ac_mid=0
-  while :; do
-    cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-$ac_includes_default
-   typedef int ac__type_sizeof_;
-int
-main ()
-{
-static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)];
-test_array [0] = 0
-
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  ac_hi=$ac_mid; break
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	ac_lo=`expr $ac_mid + 1`
-			if test $ac_lo -le $ac_mid; then
-			  ac_lo= ac_hi=
-			  break
-			fi
-			ac_mid=`expr 2 '*' $ac_mid + 1`
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-  done
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-$ac_includes_default
-   typedef int ac__type_sizeof_;
-int
-main ()
-{
-static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) < 0)];
-test_array [0] = 0
-
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  ac_hi=-1 ac_mid=-1
-  while :; do
-    cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-$ac_includes_default
-   typedef int ac__type_sizeof_;
-int
-main ()
-{
-static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= $ac_mid)];
-test_array [0] = 0
-
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  ac_lo=$ac_mid; break
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	ac_hi=`expr '(' $ac_mid ')' - 1`
-			if test $ac_mid -le $ac_hi; then
-			  ac_lo= ac_hi=
-			  break
-			fi
-			ac_mid=`expr 2 '*' $ac_mid`
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-  done
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	ac_lo= ac_hi=
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-# Binary search between lo and hi bounds.
-while test "x$ac_lo" != "x$ac_hi"; do
-  ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo`
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-$ac_includes_default
-   typedef int ac__type_sizeof_;
-int
-main ()
-{
-static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)];
-test_array [0] = 0
-
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  ac_hi=$ac_mid
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	ac_lo=`expr '(' $ac_mid ')' + 1`
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-done
-case $ac_lo in
-?*) ac_cv_sizeof_int=$ac_lo;;
-'') if test "$ac_cv_type_int" = yes; then
-     { { echo "$as_me:$LINENO: error: cannot compute sizeof (int)
-See \`config.log' for more details." >&5
-echo "$as_me: error: cannot compute sizeof (int)
-See \`config.log' for more details." >&2;}
-   { (exit 77); exit 77; }; }
-   else
-     ac_cv_sizeof_int=0
-   fi ;;
-esac
-else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-$ac_includes_default
-   typedef int ac__type_sizeof_;
-static long int longval () { return (long int) (sizeof (ac__type_sizeof_)); }
-static unsigned long int ulongval () { return (long int) (sizeof (ac__type_sizeof_)); }
-#include <stdio.h>
-#include <stdlib.h>
-int
-main ()
-{
-
-  FILE *f = fopen ("conftest.val", "w");
-  if (! f)
-    return 1;
-  if (((long int) (sizeof (ac__type_sizeof_))) < 0)
-    {
-      long int i = longval ();
-      if (i != ((long int) (sizeof (ac__type_sizeof_))))
-	return 1;
-      fprintf (f, "%ld\n", i);
-    }
-  else
-    {
-      unsigned long int i = ulongval ();
-      if (i != ((long int) (sizeof (ac__type_sizeof_))))
-	return 1;
-      fprintf (f, "%lu\n", i);
-    }
-  return ferror (f) || fclose (f) != 0;
-
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  ac_cv_sizeof_int=`cat conftest.val`
-else
-  echo "$as_me: program exited with status $ac_status" >&5
-echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-( exit $ac_status )
-if test "$ac_cv_type_int" = yes; then
-     { { echo "$as_me:$LINENO: error: cannot compute sizeof (int)
-See \`config.log' for more details." >&5
-echo "$as_me: error: cannot compute sizeof (int)
-See \`config.log' for more details." >&2;}
-   { (exit 77); exit 77; }; }
-   else
-     ac_cv_sizeof_int=0
-   fi
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
-fi
-rm -f conftest.val
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_sizeof_int" >&5
-echo "${ECHO_T}$ac_cv_sizeof_int" >&6; }
-
-
-
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF_INT $ac_cv_sizeof_int
-_ACEOF
-
-
-{ echo "$as_me:$LINENO: checking for long int" >&5
-echo $ECHO_N "checking for long int... $ECHO_C" >&6; }
-if test "${ac_cv_type_long_int+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-$ac_includes_default
-typedef long int ac__type_new_;
-int
-main ()
-{
-if ((ac__type_new_ *) 0)
-  return 0;
-if (sizeof (ac__type_new_))
-  return 0;
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  ac_cv_type_long_int=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	ac_cv_type_long_int=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_type_long_int" >&5
-echo "${ECHO_T}$ac_cv_type_long_int" >&6; }
-
-# The cast to long int works around a bug in the HP C Compiler
-# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
-# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
-# This bug is HP SR number 8606223364.
-{ echo "$as_me:$LINENO: checking size of long int" >&5
-echo $ECHO_N "checking size of long int... $ECHO_C" >&6; }
-if test "${ac_cv_sizeof_long_int+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  if test "$cross_compiling" = yes; then
-  # Depending upon the size, compute the lo and hi bounds.
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-$ac_includes_default
-   typedef long int ac__type_sizeof_;
-int
-main ()
-{
-static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= 0)];
-test_array [0] = 0
-
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  ac_lo=0 ac_mid=0
-  while :; do
-    cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-$ac_includes_default
-   typedef long int ac__type_sizeof_;
-int
-main ()
-{
-static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)];
-test_array [0] = 0
-
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  ac_hi=$ac_mid; break
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	ac_lo=`expr $ac_mid + 1`
-			if test $ac_lo -le $ac_mid; then
-			  ac_lo= ac_hi=
-			  break
-			fi
-			ac_mid=`expr 2 '*' $ac_mid + 1`
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-  done
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-$ac_includes_default
-   typedef long int ac__type_sizeof_;
-int
-main ()
-{
-static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) < 0)];
-test_array [0] = 0
-
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  ac_hi=-1 ac_mid=-1
-  while :; do
-    cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-$ac_includes_default
-   typedef long int ac__type_sizeof_;
-int
-main ()
-{
-static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= $ac_mid)];
-test_array [0] = 0
-
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  ac_lo=$ac_mid; break
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	ac_hi=`expr '(' $ac_mid ')' - 1`
-			if test $ac_mid -le $ac_hi; then
-			  ac_lo= ac_hi=
-			  break
-			fi
-			ac_mid=`expr 2 '*' $ac_mid`
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-  done
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	ac_lo= ac_hi=
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-# Binary search between lo and hi bounds.
-while test "x$ac_lo" != "x$ac_hi"; do
-  ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo`
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-$ac_includes_default
-   typedef long int ac__type_sizeof_;
-int
-main ()
-{
-static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)];
-test_array [0] = 0
-
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  ac_hi=$ac_mid
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	ac_lo=`expr '(' $ac_mid ')' + 1`
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-done
-case $ac_lo in
-?*) ac_cv_sizeof_long_int=$ac_lo;;
-'') if test "$ac_cv_type_long_int" = yes; then
-     { { echo "$as_me:$LINENO: error: cannot compute sizeof (long int)
-See \`config.log' for more details." >&5
-echo "$as_me: error: cannot compute sizeof (long int)
-See \`config.log' for more details." >&2;}
-   { (exit 77); exit 77; }; }
-   else
-     ac_cv_sizeof_long_int=0
-   fi ;;
-esac
-else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-$ac_includes_default
-   typedef long int ac__type_sizeof_;
-static long int longval () { return (long int) (sizeof (ac__type_sizeof_)); }
-static unsigned long int ulongval () { return (long int) (sizeof (ac__type_sizeof_)); }
-#include <stdio.h>
-#include <stdlib.h>
-int
-main ()
-{
-
-  FILE *f = fopen ("conftest.val", "w");
-  if (! f)
-    return 1;
-  if (((long int) (sizeof (ac__type_sizeof_))) < 0)
-    {
-      long int i = longval ();
-      if (i != ((long int) (sizeof (ac__type_sizeof_))))
-	return 1;
-      fprintf (f, "%ld\n", i);
-    }
-  else
-    {
-      unsigned long int i = ulongval ();
-      if (i != ((long int) (sizeof (ac__type_sizeof_))))
-	return 1;
-      fprintf (f, "%lu\n", i);
-    }
-  return ferror (f) || fclose (f) != 0;
-
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  ac_cv_sizeof_long_int=`cat conftest.val`
-else
-  echo "$as_me: program exited with status $ac_status" >&5
-echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-( exit $ac_status )
-if test "$ac_cv_type_long_int" = yes; then
-     { { echo "$as_me:$LINENO: error: cannot compute sizeof (long int)
-See \`config.log' for more details." >&5
-echo "$as_me: error: cannot compute sizeof (long int)
-See \`config.log' for more details." >&2;}
-   { (exit 77); exit 77; }; }
-   else
-     ac_cv_sizeof_long_int=0
-   fi
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
-fi
-rm -f conftest.val
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_sizeof_long_int" >&5
-echo "${ECHO_T}$ac_cv_sizeof_long_int" >&6; }
-
-
-
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF_LONG_INT $ac_cv_sizeof_long_int
-_ACEOF
-
-
-{ echo "$as_me:$LINENO: checking for long long int" >&5
-echo $ECHO_N "checking for long long int... $ECHO_C" >&6; }
-if test "${ac_cv_type_long_long_int+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-$ac_includes_default
-typedef long long int ac__type_new_;
-int
-main ()
-{
-if ((ac__type_new_ *) 0)
-  return 0;
-if (sizeof (ac__type_new_))
-  return 0;
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  ac_cv_type_long_long_int=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	ac_cv_type_long_long_int=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_type_long_long_int" >&5
-echo "${ECHO_T}$ac_cv_type_long_long_int" >&6; }
-
-# The cast to long int works around a bug in the HP C Compiler
-# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
-# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
-# This bug is HP SR number 8606223364.
-{ echo "$as_me:$LINENO: checking size of long long int" >&5
-echo $ECHO_N "checking size of long long int... $ECHO_C" >&6; }
-if test "${ac_cv_sizeof_long_long_int+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  if test "$cross_compiling" = yes; then
-  # Depending upon the size, compute the lo and hi bounds.
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-$ac_includes_default
-   typedef long long int ac__type_sizeof_;
-int
-main ()
-{
-static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= 0)];
-test_array [0] = 0
-
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  ac_lo=0 ac_mid=0
-  while :; do
-    cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-$ac_includes_default
-   typedef long long int ac__type_sizeof_;
-int
-main ()
-{
-static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)];
-test_array [0] = 0
-
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  ac_hi=$ac_mid; break
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	ac_lo=`expr $ac_mid + 1`
-			if test $ac_lo -le $ac_mid; then
-			  ac_lo= ac_hi=
-			  break
-			fi
-			ac_mid=`expr 2 '*' $ac_mid + 1`
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-  done
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-$ac_includes_default
-   typedef long long int ac__type_sizeof_;
-int
-main ()
-{
-static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) < 0)];
-test_array [0] = 0
-
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  ac_hi=-1 ac_mid=-1
-  while :; do
-    cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-$ac_includes_default
-   typedef long long int ac__type_sizeof_;
-int
-main ()
-{
-static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= $ac_mid)];
-test_array [0] = 0
-
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  ac_lo=$ac_mid; break
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	ac_hi=`expr '(' $ac_mid ')' - 1`
-			if test $ac_mid -le $ac_hi; then
-			  ac_lo= ac_hi=
-			  break
-			fi
-			ac_mid=`expr 2 '*' $ac_mid`
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-  done
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	ac_lo= ac_hi=
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-# Binary search between lo and hi bounds.
-while test "x$ac_lo" != "x$ac_hi"; do
-  ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo`
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-$ac_includes_default
-   typedef long long int ac__type_sizeof_;
-int
-main ()
-{
-static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)];
-test_array [0] = 0
-
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  ac_hi=$ac_mid
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	ac_lo=`expr '(' $ac_mid ')' + 1`
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-done
-case $ac_lo in
-?*) ac_cv_sizeof_long_long_int=$ac_lo;;
-'') if test "$ac_cv_type_long_long_int" = yes; then
-     { { echo "$as_me:$LINENO: error: cannot compute sizeof (long long int)
-See \`config.log' for more details." >&5
-echo "$as_me: error: cannot compute sizeof (long long int)
-See \`config.log' for more details." >&2;}
-   { (exit 77); exit 77; }; }
-   else
-     ac_cv_sizeof_long_long_int=0
-   fi ;;
-esac
-else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-$ac_includes_default
-   typedef long long int ac__type_sizeof_;
-static long int longval () { return (long int) (sizeof (ac__type_sizeof_)); }
-static unsigned long int ulongval () { return (long int) (sizeof (ac__type_sizeof_)); }
-#include <stdio.h>
-#include <stdlib.h>
-int
-main ()
-{
-
-  FILE *f = fopen ("conftest.val", "w");
-  if (! f)
-    return 1;
-  if (((long int) (sizeof (ac__type_sizeof_))) < 0)
-    {
-      long int i = longval ();
-      if (i != ((long int) (sizeof (ac__type_sizeof_))))
-	return 1;
-      fprintf (f, "%ld\n", i);
-    }
-  else
-    {
-      unsigned long int i = ulongval ();
-      if (i != ((long int) (sizeof (ac__type_sizeof_))))
-	return 1;
-      fprintf (f, "%lu\n", i);
-    }
-  return ferror (f) || fclose (f) != 0;
-
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  ac_cv_sizeof_long_long_int=`cat conftest.val`
-else
-  echo "$as_me: program exited with status $ac_status" >&5
-echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-( exit $ac_status )
-if test "$ac_cv_type_long_long_int" = yes; then
-     { { echo "$as_me:$LINENO: error: cannot compute sizeof (long long int)
-See \`config.log' for more details." >&5
-echo "$as_me: error: cannot compute sizeof (long long int)
-See \`config.log' for more details." >&2;}
-   { (exit 77); exit 77; }; }
-   else
-     ac_cv_sizeof_long_long_int=0
-   fi
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
-fi
-rm -f conftest.val
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_sizeof_long_long_int" >&5
-echo "${ECHO_T}$ac_cv_sizeof_long_long_int" >&6; }
-
-
-
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF_LONG_LONG_INT $ac_cv_sizeof_long_long_int
-_ACEOF
-
-
-
-# 64-bit integer data type; use long long int preferentially since that
-# accords with "%lld" formatting used in fitshdr.l, e.g.
-#                int   size_t  long int  long long int
-#                ---   ------  --------  -------------
-#   gcc x86:      32     32       32          64
-#   gcc x86_64:   32     64       64          64
-if test "x$ac_cv_sizeof_long_long_int" = x8; then
-
-cat >>confdefs.h <<\_ACEOF
-#define WCSLIB_INT64 long long int
-_ACEOF
-
-elif test "x$ac_cv_sizeof_long_int" = x8; then
-
-cat >>confdefs.h <<\_ACEOF
-#define WCSLIB_INT64 long int
-_ACEOF
-
-elif test "x$ac_cv_sizeof_int" = x8; then
-
-cat >>confdefs.h <<\_ACEOF
-#define WCSLIB_INT64 int
-_ACEOF
-
-fi
-
-# Does printf() have the z modifier for size_t type?  Important for 64-bit.
-{ echo "$as_me:$LINENO: checking for printf z format modifier for size_t type" >&5
-echo $ECHO_N "checking for printf z format modifier for size_t type... $ECHO_C" >&6; }
-if test "$cross_compiling" = yes; then
-
-cat >>confdefs.h <<\_ACEOF
-#define MODZ ""
-_ACEOF
-
-    { echo "$as_me:$LINENO: result: assumed not" >&5
-echo "${ECHO_T}assumed not" >&6; }
-
-else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-$ac_includes_default
-int
-main ()
-{
-char buf[64];
-                     if (sprintf(buf, "%zu", (size_t)1) != 1)
-                       return 1;
-                     else if (strcmp(buf, "1"))
-                       return 2;
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-
-cat >>confdefs.h <<\_ACEOF
-#define MODZ "z"
-_ACEOF
-
-    { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-else
-  echo "$as_me: program exited with status $ac_status" >&5
-echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-( exit $ac_status )
-
-cat >>confdefs.h <<\_ACEOF
-#define MODZ ""
-_ACEOF
-
-    { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
-fi
-
-
-
-
-# Starting values, may be augmented later.
-SUBDIRS="C"
-TSTDIRS="C"
-INSTDIR="C"
-
-
-# Ways of specifying the Fortran compiler, in order of precedence:
-#   configure --enable-fortran=<compiler>
-#   F77=<compiler> configure    ...bash
-#
-# Ways of disabling Fortran:
-#   configure --disable-fortran
-#   configure --enable-fortran=no
-#   F77=no configure            ...bash
-# Check whether --enable-fortran was given.
-if test "${enable_fortran+set}" = set; then
-  enableval=$enable_fortran;
-fi
-
-# Check whether --enable-fortran was given.
-if test "${enable_fortran+set}" = set; then
-  enableval=$enable_fortran;
-fi
-
-if test "x$enable_fortran" != x -a "x$enable_fortran" != xyes ; then
-  F77="$enable_fortran"
-fi
-
-if test "x$F77" = xno ; then
-  F77=
-
-  { echo "$as_me:$LINENO: WARNING: Compilation of Fortran wrappers and PGSBOX disabled" >&5
-echo "$as_me: WARNING: Compilation of Fortran wrappers and PGSBOX disabled" >&2;}
-
-else
-  if test "x$F77" = x ; then
-    # Look for a Fortran compiler.
-    ac_ext=f
-ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5'
-ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_f77_compiler_gnu
-if test -n "$ac_tool_prefix"; then
-  for ac_prog in gfortran g77 f77 ifort xlf frt pgf77 fl32 af77 fort77 f90 \
-                 xlf90 pgf90 epcf90 f95 fort xlf95 lf95 g95
-  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
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_prog_F77+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  if test -n "$F77"; then
-  ac_cv_prog_F77="$F77" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
-    ac_cv_prog_F77="$ac_tool_prefix$ac_prog"
-    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-done
-IFS=$as_save_IFS
-
-fi
-fi
-F77=$ac_cv_prog_F77
-if test -n "$F77"; then
-  { echo "$as_me:$LINENO: result: $F77" >&5
-echo "${ECHO_T}$F77" >&6; }
-else
-  { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-
-
-    test -n "$F77" && break
-  done
-fi
-if test -z "$F77"; then
-  ac_ct_F77=$F77
-  for ac_prog in gfortran g77 f77 ifort xlf frt pgf77 fl32 af77 fort77 f90 \
-                 xlf90 pgf90 epcf90 f95 fort xlf95 lf95 g95
-do
-  # Extract the first word of "$ac_prog", so it can be a program name with args.
-set dummy $ac_prog; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_prog_ac_ct_F77+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  if test -n "$ac_ct_F77"; then
-  ac_cv_prog_ac_ct_F77="$ac_ct_F77" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
-    ac_cv_prog_ac_ct_F77="$ac_prog"
-    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-done
-IFS=$as_save_IFS
-
-fi
-fi
-ac_ct_F77=$ac_cv_prog_ac_ct_F77
-if test -n "$ac_ct_F77"; then
-  { echo "$as_me:$LINENO: result: $ac_ct_F77" >&5
-echo "${ECHO_T}$ac_ct_F77" >&6; }
-else
-  { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-
-
-  test -n "$ac_ct_F77" && break
-done
-
-  if test "x$ac_ct_F77" = x; then
-    F77=""
-  else
-    case $cross_compiling:$ac_tool_warned in
-yes:)
-{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet.  If you think this
-configuration is useful to you, please write to autoconf at gnu.org." >&5
-echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet.  If you think this
-configuration is useful to you, please write to autoconf at gnu.org." >&2;}
-ac_tool_warned=yes ;;
-esac
-    F77=$ac_ct_F77
-  fi
-fi
-
-
-# Provide some information about the compiler.
-echo "$as_me:$LINENO: checking for Fortran 77 compiler version" >&5
-ac_compiler=`set X $ac_compile; echo $2`
-{ (ac_try="$ac_compiler --version >&5"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compiler --version >&5") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }
-{ (ac_try="$ac_compiler -v >&5"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compiler -v >&5") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }
-{ (ac_try="$ac_compiler -V >&5"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compiler -V >&5") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }
-rm -f a.out
-
-# If we don't use `.F' as extension, the preprocessor is not run on the
-# input file.  (Note that this only needs to work for GNU compilers.)
-ac_save_ext=$ac_ext
-ac_ext=F
-{ echo "$as_me:$LINENO: checking whether we are using the GNU Fortran 77 compiler" >&5
-echo $ECHO_N "checking whether we are using the GNU Fortran 77 compiler... $ECHO_C" >&6; }
-if test "${ac_cv_f77_compiler_gnu+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  cat >conftest.$ac_ext <<_ACEOF
-      program main
-#ifndef __GNUC__
-       choke me
-#endif
-
-      end
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_f77_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  ac_compiler_gnu=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	ac_compiler_gnu=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-ac_cv_f77_compiler_gnu=$ac_compiler_gnu
-
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_f77_compiler_gnu" >&5
-echo "${ECHO_T}$ac_cv_f77_compiler_gnu" >&6; }
-ac_ext=$ac_save_ext
-ac_test_FFLAGS=${FFLAGS+set}
-ac_save_FFLAGS=$FFLAGS
-FFLAGS=
-{ echo "$as_me:$LINENO: checking whether $F77 accepts -g" >&5
-echo $ECHO_N "checking whether $F77 accepts -g... $ECHO_C" >&6; }
-if test "${ac_cv_prog_f77_g+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  FFLAGS=-g
-cat >conftest.$ac_ext <<_ACEOF
-      program main
-
-      end
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_f77_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  ac_cv_prog_f77_g=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	ac_cv_prog_f77_g=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_prog_f77_g" >&5
-echo "${ECHO_T}$ac_cv_prog_f77_g" >&6; }
-if test "$ac_test_FFLAGS" = set; then
-  FFLAGS=$ac_save_FFLAGS
-elif test $ac_cv_prog_f77_g = yes; then
-  if test "x$ac_cv_f77_compiler_gnu" = xyes; then
-    FFLAGS="-g -O2"
-  else
-    FFLAGS="-g"
-  fi
-else
-  if test "x$ac_cv_f77_compiler_gnu" = xyes; then
-    FFLAGS="-O2"
-  else
-    FFLAGS=
-  fi
-fi
-
-G77=`test $ac_compiler_gnu = yes && echo yes`
-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
-
-  fi
-
-  if test "x$F77" = x; then
-    { echo "$as_me:$LINENO: WARNING:
-      ------------------------------------------------------------------
-      Fortran compiler not found, will skip Fortran wrappers and PGSBOX.
-      ------------------------------------------------------------------" >&5
-echo "$as_me: WARNING:
-      ------------------------------------------------------------------
-      Fortran compiler not found, will skip Fortran wrappers and PGSBOX.
-      ------------------------------------------------------------------" >&2;}
-
-    # Best guess at Fortran name mangling for use if a compiler does ever
-    # become available.
-    cat >>confdefs.h <<\_ACEOF
-#define F77_FUNC(name,NAME) name ## _
-_ACEOF
-
-
-  else
-    if test "x$ac_cv_f77_compiler_gnu" = xyes ; then
-      if test "x$F77" = xg77 -o "x$F77" = xf77 ; then
-        # Not recognized by gfortran.
-        FFLAGS="$FFLAGS -Wno-globals"
-      fi
-    fi
-
-    { echo "$as_me:$LINENO: checking whether $F77 accepts -I" >&5
-echo $ECHO_N "checking whether $F77 accepts -I... $ECHO_C" >&6; }
-    ac_ext=f
-ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5'
-ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_f77_compiler_gnu
-
-    FFLAGS_save=$FFLAGS
-    FFLAGS=-I.
-
-cat >conftest.$ac_ext <<_ACEOF
-      program main
-
-      end
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_f77_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  FFLAGS="$FFLAGS_save -I."; { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	FFLAGS="$FFLAGS_save"; { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-    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
-
-
-    # Libraries required by the Fortran compiler itself (sets FLIBS).
-    # Required by utilities and test programs written in C that link to
-    # Fortran object modules such as pgsbox.
-    ac_ext=f
-ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5'
-ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_f77_compiler_gnu
-{ echo "$as_me:$LINENO: checking how to get verbose linking output from $F77" >&5
-echo $ECHO_N "checking how to get verbose linking output from $F77... $ECHO_C" >&6; }
-if test "${ac_cv_prog_f77_v+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  cat >conftest.$ac_ext <<_ACEOF
-      program main
-
-      end
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_f77_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  ac_cv_prog_f77_v=
-# Try some options frequently used verbose output
-for ac_verb in -v -verbose --verbose -V -\#\#\#; do
-  cat >conftest.$ac_ext <<_ACEOF
-      program main
-
-      end
-_ACEOF
-
-# Compile and link our simple test program by passing a flag (argument
-# 1 to this macro) to the Fortran compiler in order to get
-# "verbose" output that we can then parse for the Fortran linker
-# flags.
-ac_save_FFLAGS=$FFLAGS
-FFLAGS="$FFLAGS $ac_verb"
-eval "set x $ac_link"
-shift
-echo "$as_me:$LINENO: $*" >&5
-ac_f77_v_output=`eval $ac_link 5>&1 2>&1 | grep -v 'Driving:'`
-echo "$ac_f77_v_output" >&5
-FFLAGS=$ac_save_FFLAGS
-
-rm -f -r conftest*
-
-# On HP/UX there is a line like: "LPATH is: /foo:/bar:/baz" where
-# /foo, /bar, and /baz are search directories for the Fortran linker.
-# Here, we change these into -L/foo -L/bar -L/baz (and put it first):
-ac_f77_v_output="`echo $ac_f77_v_output |
-	grep 'LPATH is:' |
-	sed 's,.*LPATH is\(: *[^ ]*\).*,\1,;s,: */, -L/,g'` $ac_f77_v_output"
-
-# FIXME: we keep getting bitten by quoted arguments; a more general fix
-#        that detects unbalanced quotes in FLIBS should be implemented
-#        and (ugh) tested at some point.
-case $ac_f77_v_output in
-  # If we are using xlf then replace all the commas with spaces.
-  *xlfentry*)
-    ac_f77_v_output=`echo $ac_f77_v_output | sed 's/,/ /g'` ;;
-
-  # With Intel ifc, ignore the quoted -mGLOB_options_string stuff (quoted
-  # $LIBS confuse us, and the libraries appear later in the output anyway).
-  *mGLOB_options_string*)
-    ac_f77_v_output=`echo $ac_f77_v_output | sed 's/"-mGLOB[^"]*"/ /g'` ;;
-
-  # Portland Group compiler has singly- or doubly-quoted -cmdline argument
-  # Singly-quoted arguments were reported for versions 5.2-4 and 6.0-4.
-  # Doubly-quoted arguments were reported for "PGF90/x86 Linux/x86 5.0-2".
-  *-cmdline\ * | *-ignore\ * | *-def\ *)
-    ac_f77_v_output=`echo $ac_f77_v_output | sed "\
-        s/-cmdline  *'[^']*'/ /g; s/-cmdline  *\"[^\"]*\"/ /g
-        s/-ignore  *'[^']*'/ /g; s/-ignore  *\"[^\"]*\"/ /g
-        s/-def  *'[^']*'/ /g; s/-def  *\"[^\"]*\"/ /g"` ;;
-
-  # If we are using Cray Fortran then delete quotes.
-  *cft90*)
-    ac_f77_v_output=`echo $ac_f77_v_output | sed 's/"//g'` ;;
-esac
-
-
-  # look for -l* and *.a constructs in the output
-  for ac_arg in $ac_f77_v_output; do
-     case $ac_arg in
-        [\\/]*.a | ?:[\\/]*.a | -[lLRu]*)
-          ac_cv_prog_f77_v=$ac_verb
-          break 2 ;;
-     esac
-  done
-done
-if test -z "$ac_cv_prog_f77_v"; then
-   { echo "$as_me:$LINENO: WARNING: cannot determine how to obtain linking information from $F77" >&5
-echo "$as_me: WARNING: cannot determine how to obtain linking information from $F77" >&2;}
-fi
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	{ echo "$as_me:$LINENO: WARNING: compilation failed" >&5
-echo "$as_me: WARNING: compilation failed" >&2;}
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_prog_f77_v" >&5
-echo "${ECHO_T}$ac_cv_prog_f77_v" >&6; }
-{ echo "$as_me:$LINENO: checking for Fortran 77 libraries of $F77" >&5
-echo $ECHO_N "checking for Fortran 77 libraries of $F77... $ECHO_C" >&6; }
-if test "${ac_cv_f77_libs+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  if test "x$FLIBS" != "x"; then
-  ac_cv_f77_libs="$FLIBS" # Let the user override the test.
-else
-
-cat >conftest.$ac_ext <<_ACEOF
-      program main
-
-      end
-_ACEOF
-
-# Compile and link our simple test program by passing a flag (argument
-# 1 to this macro) to the Fortran compiler in order to get
-# "verbose" output that we can then parse for the Fortran linker
-# flags.
-ac_save_FFLAGS=$FFLAGS
-FFLAGS="$FFLAGS $ac_cv_prog_f77_v"
-eval "set x $ac_link"
-shift
-echo "$as_me:$LINENO: $*" >&5
-ac_f77_v_output=`eval $ac_link 5>&1 2>&1 | grep -v 'Driving:'`
-echo "$ac_f77_v_output" >&5
-FFLAGS=$ac_save_FFLAGS
-
-rm -f -r conftest*
-
-# On HP/UX there is a line like: "LPATH is: /foo:/bar:/baz" where
-# /foo, /bar, and /baz are search directories for the Fortran linker.
-# Here, we change these into -L/foo -L/bar -L/baz (and put it first):
-ac_f77_v_output="`echo $ac_f77_v_output |
-	grep 'LPATH is:' |
-	sed 's,.*LPATH is\(: *[^ ]*\).*,\1,;s,: */, -L/,g'` $ac_f77_v_output"
-
-# FIXME: we keep getting bitten by quoted arguments; a more general fix
-#        that detects unbalanced quotes in FLIBS should be implemented
-#        and (ugh) tested at some point.
-case $ac_f77_v_output in
-  # If we are using xlf then replace all the commas with spaces.
-  *xlfentry*)
-    ac_f77_v_output=`echo $ac_f77_v_output | sed 's/,/ /g'` ;;
-
-  # With Intel ifc, ignore the quoted -mGLOB_options_string stuff (quoted
-  # $LIBS confuse us, and the libraries appear later in the output anyway).
-  *mGLOB_options_string*)
-    ac_f77_v_output=`echo $ac_f77_v_output | sed 's/"-mGLOB[^"]*"/ /g'` ;;
-
-  # Portland Group compiler has singly- or doubly-quoted -cmdline argument
-  # Singly-quoted arguments were reported for versions 5.2-4 and 6.0-4.
-  # Doubly-quoted arguments were reported for "PGF90/x86 Linux/x86 5.0-2".
-  *-cmdline\ * | *-ignore\ * | *-def\ *)
-    ac_f77_v_output=`echo $ac_f77_v_output | sed "\
-        s/-cmdline  *'[^']*'/ /g; s/-cmdline  *\"[^\"]*\"/ /g
-        s/-ignore  *'[^']*'/ /g; s/-ignore  *\"[^\"]*\"/ /g
-        s/-def  *'[^']*'/ /g; s/-def  *\"[^\"]*\"/ /g"` ;;
-
-  # If we are using Cray Fortran then delete quotes.
-  *cft90*)
-    ac_f77_v_output=`echo $ac_f77_v_output | sed 's/"//g'` ;;
-esac
-
-
-
-ac_cv_f77_libs=
-
-# Save positional arguments (if any)
-ac_save_positional="$@"
-
-set X $ac_f77_v_output
-while test $# != 1; do
-  shift
-  ac_arg=$1
-  case $ac_arg in
-        [\\/]*.a | ?:[\\/]*.a)
-            ac_exists=false
-  for ac_i in $ac_cv_f77_libs; do
-    if test x"$ac_arg" = x"$ac_i"; then
-      ac_exists=true
-      break
-    fi
-  done
-
-  if test x"$ac_exists" = xtrue; then
-  :
-else
-  ac_cv_f77_libs="$ac_cv_f77_libs $ac_arg"
-fi
-
-          ;;
-        -bI:*)
-            ac_exists=false
-  for ac_i in $ac_cv_f77_libs; do
-    if test x"$ac_arg" = x"$ac_i"; then
-      ac_exists=true
-      break
-    fi
-  done
-
-  if test x"$ac_exists" = xtrue; then
-  :
-else
-  if test "$ac_compiler_gnu" = yes; then
-  for ac_link_opt in $ac_arg; do
-    ac_cv_f77_libs="$ac_cv_f77_libs -Xlinker $ac_link_opt"
-  done
-else
-  ac_cv_f77_libs="$ac_cv_f77_libs $ac_arg"
-fi
-fi
-
-          ;;
-          # Ignore these flags.
-        -lang* | -lcrt*.o | -lc | -lgcc* | -lSystem | -libmil | -LANG:=* | -LIST:* | -LNO:*)
-          ;;
-        -lkernel32)
-          test x"$CYGWIN" != xyes && ac_cv_f77_libs="$ac_cv_f77_libs $ac_arg"
-          ;;
-        -[LRuYz])
-          # These flags, when seen by themselves, take an argument.
-          # We remove the space between option and argument and re-iterate
-          # unless we find an empty arg or a new option (starting with -)
-	  case $2 in
-	     "" | -*);;
-	     *)
-		ac_arg="$ac_arg$2"
-		shift; shift
-		set X $ac_arg "$@"
-		;;
-	  esac
-          ;;
-        -YP,*)
-          for ac_j in `echo $ac_arg | sed -e 's/-YP,/-L/;s/:/ -L/g'`; do
-              ac_exists=false
-  for ac_i in $ac_cv_f77_libs; do
-    if test x"$ac_j" = x"$ac_i"; then
-      ac_exists=true
-      break
-    fi
-  done
-
-  if test x"$ac_exists" = xtrue; then
-  :
-else
-  ac_arg="$ac_arg $ac_j"
-                               ac_cv_f77_libs="$ac_cv_f77_libs $ac_j"
-fi
-
-          done
-          ;;
-        -[lLR]*)
-            ac_exists=false
-  for ac_i in $ac_cv_f77_libs; do
-    if test x"$ac_arg" = x"$ac_i"; then
-      ac_exists=true
-      break
-    fi
-  done
-
-  if test x"$ac_exists" = xtrue; then
-  :
-else
-  ac_cv_f77_libs="$ac_cv_f77_libs $ac_arg"
-fi
-
-          ;;
-	-zallextract*| -zdefaultextract)
-	  ac_cv_f77_libs="$ac_cv_f77_libs $ac_arg"
-	  ;;
-          # Ignore everything else.
-  esac
-done
-# restore positional arguments
-set X $ac_save_positional; shift
-
-# We only consider "LD_RUN_PATH" on Solaris systems.  If this is seen,
-# then we insist that the "run path" must be an absolute path (i.e. it
-# must begin with a "/").
-case `(uname -sr) 2>/dev/null` in
-   "SunOS 5"*)
-      ac_ld_run_path=`echo $ac_f77_v_output |
-                        sed -n 's,^.*LD_RUN_PATH *= *\(/[^ ]*\).*$,-R\1,p'`
-      test "x$ac_ld_run_path" != x &&
-        if test "$ac_compiler_gnu" = yes; then
-  for ac_link_opt in $ac_ld_run_path; do
-    ac_cv_f77_libs="$ac_cv_f77_libs -Xlinker $ac_link_opt"
-  done
-else
-  ac_cv_f77_libs="$ac_cv_f77_libs $ac_ld_run_path"
-fi
-      ;;
-esac
-fi # test "x$[]_AC_LANG_PREFIX[]LIBS" = "x"
-
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_f77_libs" >&5
-echo "${ECHO_T}$ac_cv_f77_libs" >&6; }
-FLIBS="$ac_cv_f77_libs"
-
-
-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
-
-
-    # F77 name mangling (defines the F77_FUNC preprocessor macro).
-    ac_ext=f
-ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5'
-ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_f77_compiler_gnu
-
-{ echo "$as_me:$LINENO: checking for dummy main to link with Fortran 77 libraries" >&5
-echo $ECHO_N "checking for dummy main to link with Fortran 77 libraries... $ECHO_C" >&6; }
-if test "${ac_cv_f77_dummy_main+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  ac_f77_dm_save_LIBS=$LIBS
- LIBS="$LIBS $FLIBS"
- ac_fortran_dm_var=F77_DUMMY_MAIN
- 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
-
- # First, try linking without a dummy main:
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-
-#ifdef F77_DUMMY_MAIN
-
-#  ifdef __cplusplus
-     extern "C"
-#  endif
-   int F77_DUMMY_MAIN() { return 1; }
-
-#endif
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest$ac_exeext &&
-       $as_test_x conftest$ac_exeext; then
-  ac_cv_fortran_dummy_main=none
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	ac_cv_fortran_dummy_main=unknown
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
-      conftest$ac_exeext conftest.$ac_ext
-
- if test $ac_cv_fortran_dummy_main = unknown; then
-   for ac_func in MAIN__ MAIN_ __main MAIN _MAIN __MAIN main_ main__ _main; do
-     cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#define $ac_fortran_dm_var $ac_func
-#ifdef F77_DUMMY_MAIN
-
-#  ifdef __cplusplus
-     extern "C"
-#  endif
-   int F77_DUMMY_MAIN() { return 1; }
-
-#endif
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest$ac_exeext &&
-       $as_test_x conftest$ac_exeext; then
-  ac_cv_fortran_dummy_main=$ac_func; break
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
-      conftest$ac_exeext conftest.$ac_ext
-   done
- fi
- ac_ext=f
-ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5'
-ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_f77_compiler_gnu
- ac_cv_f77_dummy_main=$ac_cv_fortran_dummy_main
- rm -f -r conftest*
- LIBS=$ac_f77_dm_save_LIBS
-
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_f77_dummy_main" >&5
-echo "${ECHO_T}$ac_cv_f77_dummy_main" >&6; }
-F77_DUMMY_MAIN=$ac_cv_f77_dummy_main
-if test "$F77_DUMMY_MAIN" != unknown; then
-  if test $F77_DUMMY_MAIN != none; then
-
-cat >>confdefs.h <<_ACEOF
-#define F77_DUMMY_MAIN $F77_DUMMY_MAIN
-_ACEOF
-
-  if test "x$ac_cv_fc_dummy_main" = "x$ac_cv_f77_dummy_main"; then
-
-cat >>confdefs.h <<\_ACEOF
-#define FC_DUMMY_MAIN_EQ_F77 1
-_ACEOF
-
-  fi
-fi
-else
-  { { echo "$as_me:$LINENO: error: linking to Fortran libraries from C fails
-See \`config.log' for more details." >&5
-echo "$as_me: error: linking to Fortran libraries from C fails
-See \`config.log' for more details." >&2;}
-   { (exit 1); exit 1; }; }
-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=f
-ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5'
-ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_f77_compiler_gnu
-{ echo "$as_me:$LINENO: checking for Fortran 77 name-mangling scheme" >&5
-echo $ECHO_N "checking for Fortran 77 name-mangling scheme... $ECHO_C" >&6; }
-if test "${ac_cv_f77_mangling+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  cat >conftest.$ac_ext <<_ACEOF
-      subroutine foobar()
-      return
-      end
-      subroutine foo_bar()
-      return
-      end
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_f77_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  mv conftest.$ac_objext cfortran_test.$ac_objext
-
-  ac_save_LIBS=$LIBS
-  LIBS="cfortran_test.$ac_objext $LIBS $FLIBS"
-
-  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_success=no
-  for ac_foobar in foobar FOOBAR; do
-    for ac_underscore in "" "_"; do
-      ac_func="$ac_foobar$ac_underscore"
-      cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* 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 $ac_func ();
-#ifdef F77_DUMMY_MAIN
-
-#  ifdef __cplusplus
-     extern "C"
-#  endif
-   int F77_DUMMY_MAIN() { return 1; }
-
-#endif
-int
-main ()
-{
-return $ac_func ();
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest$ac_exeext &&
-       $as_test_x conftest$ac_exeext; then
-  ac_success=yes; break 2
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
-      conftest$ac_exeext conftest.$ac_ext
-    done
-  done
-  ac_ext=f
-ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5'
-ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_f77_compiler_gnu
-
-  if test "$ac_success" = "yes"; then
-     case $ac_foobar in
-	foobar)
-	   ac_case=lower
-	   ac_foo_bar=foo_bar
-	   ;;
-	FOOBAR)
-	   ac_case=upper
-	   ac_foo_bar=FOO_BAR
-	   ;;
-     esac
-
-     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_success_extra=no
-     for ac_extra in "" "_"; do
-	ac_func="$ac_foo_bar$ac_underscore$ac_extra"
-	cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* 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 $ac_func ();
-#ifdef F77_DUMMY_MAIN
-
-#  ifdef __cplusplus
-     extern "C"
-#  endif
-   int F77_DUMMY_MAIN() { return 1; }
-
-#endif
-int
-main ()
-{
-return $ac_func ();
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest$ac_exeext &&
-       $as_test_x conftest$ac_exeext; then
-  ac_success_extra=yes; break
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
-      conftest$ac_exeext conftest.$ac_ext
-     done
-     ac_ext=f
-ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5'
-ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_f77_compiler_gnu
-
-     if test "$ac_success_extra" = "yes"; then
-	ac_cv_f77_mangling="$ac_case case"
-        if test -z "$ac_underscore"; then
-           ac_cv_f77_mangling="$ac_cv_f77_mangling, no underscore"
-	else
-           ac_cv_f77_mangling="$ac_cv_f77_mangling, underscore"
-        fi
-        if test -z "$ac_extra"; then
-           ac_cv_f77_mangling="$ac_cv_f77_mangling, no extra underscore"
-	else
-           ac_cv_f77_mangling="$ac_cv_f77_mangling, extra underscore"
-        fi
-      else
-	ac_cv_f77_mangling="unknown"
-      fi
-  else
-     ac_cv_f77_mangling="unknown"
-  fi
-
-  LIBS=$ac_save_LIBS
-  rm -f -r cfortran_test* conftest*
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	{ { echo "$as_me:$LINENO: error: cannot compile a simple Fortran program
-See \`config.log' for more details." >&5
-echo "$as_me: error: cannot compile a simple Fortran program
-See \`config.log' for more details." >&2;}
-   { (exit 1); exit 1; }; }
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_f77_mangling" >&5
-echo "${ECHO_T}$ac_cv_f77_mangling" >&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
-
-ac_ext=f
-ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5'
-ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_f77_compiler_gnu
-
-
-case $ac_cv_f77_mangling in
-  "lower case, no underscore, no extra underscore")
-          cat >>confdefs.h <<\_ACEOF
-#define F77_FUNC(name,NAME) name
-_ACEOF
-
-          cat >>confdefs.h <<\_ACEOF
-#define F77_FUNC_(name,NAME) name
-_ACEOF
- ;;
-  "lower case, no underscore, extra underscore")
-          cat >>confdefs.h <<\_ACEOF
-#define F77_FUNC(name,NAME) name
-_ACEOF
-
-          cat >>confdefs.h <<\_ACEOF
-#define F77_FUNC_(name,NAME) name ## _
-_ACEOF
- ;;
-  "lower case, underscore, no extra underscore")
-          cat >>confdefs.h <<\_ACEOF
-#define F77_FUNC(name,NAME) name ## _
-_ACEOF
-
-          cat >>confdefs.h <<\_ACEOF
-#define F77_FUNC_(name,NAME) name ## _
-_ACEOF
- ;;
-  "lower case, underscore, extra underscore")
-          cat >>confdefs.h <<\_ACEOF
-#define F77_FUNC(name,NAME) name ## _
-_ACEOF
-
-          cat >>confdefs.h <<\_ACEOF
-#define F77_FUNC_(name,NAME) name ## __
-_ACEOF
- ;;
-  "upper case, no underscore, no extra underscore")
-          cat >>confdefs.h <<\_ACEOF
-#define F77_FUNC(name,NAME) NAME
-_ACEOF
-
-          cat >>confdefs.h <<\_ACEOF
-#define F77_FUNC_(name,NAME) NAME
-_ACEOF
- ;;
-  "upper case, no underscore, extra underscore")
-          cat >>confdefs.h <<\_ACEOF
-#define F77_FUNC(name,NAME) NAME
-_ACEOF
-
-          cat >>confdefs.h <<\_ACEOF
-#define F77_FUNC_(name,NAME) NAME ## _
-_ACEOF
- ;;
-  "upper case, underscore, no extra underscore")
-          cat >>confdefs.h <<\_ACEOF
-#define F77_FUNC(name,NAME) NAME ## _
-_ACEOF
-
-          cat >>confdefs.h <<\_ACEOF
-#define F77_FUNC_(name,NAME) NAME ## _
-_ACEOF
- ;;
-  "upper case, underscore, extra underscore")
-          cat >>confdefs.h <<\_ACEOF
-#define F77_FUNC(name,NAME) NAME ## _
-_ACEOF
-
-          cat >>confdefs.h <<\_ACEOF
-#define F77_FUNC_(name,NAME) NAME ## __
-_ACEOF
- ;;
-  *)
-          { echo "$as_me:$LINENO: WARNING: unknown Fortran name-mangling scheme" >&5
-echo "$as_me: WARNING: unknown Fortran name-mangling scheme" >&2;}
-          ;;
-esac
-
-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
-
-
-    SUBDIRS="C Fortran"
-    TSTDIRS="C Fortran"
-    INSTDIR="Fortran"
-  fi
-fi
-
-
-# System-dependent system libraries (for building the sharable library).
-#-----------------------------------------------------------------------
-# Darwin (contains stubs for long double).
-as_ac_Lib=`echo "ac_cv_lib_SystemStubs_printf\$LDBLStub" | $as_tr_sh`
-{ echo "$as_me:$LINENO: checking for printf\$LDBLStub in -lSystemStubs" >&5
-echo $ECHO_N "checking for printf\$LDBLStub in -lSystemStubs... $ECHO_C" >&6; }
-if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  ac_check_lib_save_LIBS=$LIBS
-LIBS="-lSystemStubs  $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* 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 printf\$LDBLStub ();
-#ifdef F77_DUMMY_MAIN
-
-#  ifdef __cplusplus
-     extern "C"
-#  endif
-   int F77_DUMMY_MAIN() { return 1; }
-
-#endif
-int
-main ()
-{
-return printf\$LDBLStub ();
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest$ac_exeext &&
-       $as_test_x conftest$ac_exeext; then
-  eval "$as_ac_Lib=yes"
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	eval "$as_ac_Lib=no"
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
-      conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-ac_res=`eval echo '${'$as_ac_Lib'}'`
-	       { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-if test `eval echo '${'$as_ac_Lib'}'` = yes; then
-  LIBS="$LIBS -lSystemStubs"
-fi
-
-
-
-# Library and installation utilities.
-#------------------------------------
-# Static library generation.
-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
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_prog_RANLIB+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
-    ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
-    echo "$as_me:$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
-  { echo "$as_me:$LINENO: result: $RANLIB" >&5
-echo "${ECHO_T}$RANLIB" >&6; }
-else
-  { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}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
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
-    ac_cv_prog_ac_ct_RANLIB="ranlib"
-    echo "$as_me:$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
-  { echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5
-echo "${ECHO_T}$ac_ct_RANLIB" >&6; }
-else
-  { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-
-  if test "x$ac_ct_RANLIB" = x; then
-    RANLIB=":"
-  else
-    case $cross_compiling:$ac_tool_warned in
-yes:)
-{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet.  If you think this
-configuration is useful to you, please write to autoconf at gnu.org." >&5
-echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet.  If you think this
-configuration is useful to you, please write to autoconf at gnu.org." >&2;}
-ac_tool_warned=yes ;;
-esac
-    RANLIB=$ac_ct_RANLIB
-  fi
-else
-  RANLIB="$ac_cv_prog_RANLIB"
-fi
-
-
-# Shared library generation.
-if test "x$ac_cv_c_compiler_gnu" = xyes ; then
-  SHVER=`echo "$LIBVER" | sed -e 's/\..*$//'`
-
-  # Note that -fPIC is on by default for Macs, this just makes it obvious.
-  SHRFLAGS="-fPIC"
-  SHRLD="\$(CC) \$(SHRFLAGS)"
-
-  case "$build_os" in
-  darwin*)
-    SHRLIB="libwcs.$LIBVER.dylib"
-    SONAME="libwcs.$SHVER.dylib"
-    SHRLD="$SHRLD -dynamiclib -single_module"
-    SHRLD="$SHRLD -compatibility_version $SHVER -current_version $LIBVER"
-    SHRLN=
-
-    case "$build_cpu" in
-    powerpc*)
-      # Switch off -fPIC (not applicable for PowerPC Macs).
-      CFLAGS="$CFLAGS -mdynamic-no-pic"
-      ;;
-    esac
-    ;;
-  *)
-    # Covers Linux and Solaris at least.
-    SHRLIB="libwcs.so.$LIBVER"
-    SONAME="libwcs.so.$SHVER"
-    SHRLD="$SHRLD -shared -Wl,-h\$(SONAME) -lm"
-    SHRLN="libwcs.so"
-    ;;
-  esac
-
-else
-  SHRLIB=
-  SONAME=
-  SHRFLAGS=
-  SHRLD=
-  SHRSFX=
-  SHRLN=
-fi
-
-
-
-
-
-
-
-
-# Installation utilities.
-{ echo "$as_me:$LINENO: checking whether ln -s works" >&5
-echo $ECHO_N "checking whether ln -s works... $ECHO_C" >&6; }
-LN_S=$as_ln_s
-if test "$LN_S" = "ln -s"; then
-  { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-else
-  { echo "$as_me:$LINENO: result: no, using $LN_S" >&5
-echo "${ECHO_T}no, using $LN_S" >&6; }
-fi
-
-# Find a good install program.  We prefer a C program (faster),
-# so one script is as good as another.  But avoid the broken or
-# incompatible versions:
-# SysV /etc/install, /usr/sbin/install
-# SunOS /usr/etc/install
-# IRIX /sbin/install
-# AIX /bin/install
-# AmigaOS /C/install, which installs bootblocks on floppy discs
-# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
-# AFS /usr/afsws/bin/install, which mishandles nonexistent args
-# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
-# OS/2's system install, which has a completely different semantic
-# ./install, which can be erroneously created by make from ./install.sh.
-{ echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5
-echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6; }
-if test -z "$INSTALL"; then
-if test "${ac_cv_path_install+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  # Account for people who put trailing slashes in PATH elements.
-case $as_dir/ in
-  ./ | .// | /cC/* | \
-  /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
-  ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \
-  /usr/ucb/* ) ;;
-  *)
-    # OSF1 and SCO ODT 3.0 have their own names for install.
-    # Don't use installbsd from OSF since it installs stuff as root
-    # by default.
-    for ac_prog in ginstall scoinst install; do
-      for ac_exec_ext in '' $ac_executable_extensions; do
-	if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then
-	  if test $ac_prog = install &&
-	    grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
-	    # AIX install.  It has an incompatible calling convention.
-	    :
-	  elif test $ac_prog = install &&
-	    grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
-	    # program-specific install script used by HP pwplus--don't use.
-	    :
-	  else
-	    ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
-	    break 3
-	  fi
-	fi
-      done
-    done
-    ;;
-esac
-done
-IFS=$as_save_IFS
-
-
-fi
-  if test "${ac_cv_path_install+set}" = set; then
-    INSTALL=$ac_cv_path_install
-  else
-    # As a last resort, use the slow shell script.  Don't cache a
-    # value for INSTALL within a source directory, because that will
-    # break other packages using the cache if that directory is
-    # removed, or if the value is a relative name.
-    INSTALL=$ac_install_sh
-  fi
-fi
-{ echo "$as_me:$LINENO: result: $INSTALL" >&5
-echo "${ECHO_T}$INSTALL" >&6; }
-
-# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
-# It thinks the first close brace ends the variable substitution.
-test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
-
-test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
-
-test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
-
-
-{ echo "$as_me:$LINENO: End of primary configuration.
-" >&5
-echo "$as_me: End of primary configuration.
-" >&6;}
-
-
-# The following are required to build utilities and test programs.
-# ----------------------------------------------------------------
-{ echo "$as_me:$LINENO: Looking for libraries etc. for utilities and test suite..." >&5
-echo "$as_me: Looking for libraries etc. for utilities and test suite..." >&6;}
-
-# Check for other quasi-standard header files.
-
-for ac_header in unistd.h
-do
-as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
-  { echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-fi
-ac_res=`eval echo '${'$as_ac_Header'}'`
-	       { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-else
-  # Is the header compilable?
-{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
-echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-$ac_includes_default
-#include <$ac_header>
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  ac_header_compiler=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	ac_header_compiler=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
-echo "${ECHO_T}$ac_header_compiler" >&6; }
-
-# Is the header present?
-{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
-echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <$ac_header>
-_ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } >/dev/null && {
-	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       }; then
-  ac_header_preproc=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-  ac_header_preproc=no
-fi
-
-rm -f conftest.err conftest.$ac_ext
-{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
-echo "${ECHO_T}$ac_header_preproc" >&6; }
-
-# So?  What about this header?
-case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
-  yes:no: )
-    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
-echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
-    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
-    ac_header_preproc=yes
-    ;;
-  no:yes:* )
-    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
-echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
-    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
-echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
-    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
-echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
-    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
-echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
-    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
-    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
-echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
-    ( cat <<\_ASBOX
-## ------------------------------------- ##
-## Report this to mcalabre at atnf.csiro.au ##
-## ------------------------------------- ##
-_ASBOX
-     ) | sed "s/^/$as_me: WARNING:     /" >&2
-    ;;
-esac
-{ echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  eval "$as_ac_Header=\$ac_header_preproc"
-fi
-ac_res=`eval echo '${'$as_ac_Header'}'`
-	       { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-
-fi
-if test `eval echo '${'$as_ac_Header'}'` = yes; then
-  cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-
-done
-
-
-# Large file support.
-{ echo "$as_me:$LINENO: checking for _LARGEFILE_SOURCE value needed for large files" >&5
-echo $ECHO_N "checking for _LARGEFILE_SOURCE value needed for large files... $ECHO_C" >&6; }
-if test "${ac_cv_sys_largefile_source+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  while :; do
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <stdio.h>
-#ifdef F77_DUMMY_MAIN
-
-#  ifdef __cplusplus
-     extern "C"
-#  endif
-   int F77_DUMMY_MAIN() { return 1; }
-
-#endif
-int
-main ()
-{
-return fseeko (stdin, 0, 0) && (fseeko) (stdin, 0, 0);
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest$ac_exeext &&
-       $as_test_x conftest$ac_exeext; then
-  ac_cv_sys_largefile_source=no; break
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
-      conftest$ac_exeext conftest.$ac_ext
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#define _LARGEFILE_SOURCE 1
-#include <stdio.h>
-#ifdef F77_DUMMY_MAIN
-
-#  ifdef __cplusplus
-     extern "C"
-#  endif
-   int F77_DUMMY_MAIN() { return 1; }
-
-#endif
-int
-main ()
-{
-return fseeko (stdin, 0, 0) && (fseeko) (stdin, 0, 0);
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest$ac_exeext &&
-       $as_test_x conftest$ac_exeext; then
-  ac_cv_sys_largefile_source=1; break
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
-      conftest$ac_exeext conftest.$ac_ext
-  ac_cv_sys_largefile_source=unknown
-  break
-done
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_sys_largefile_source" >&5
-echo "${ECHO_T}$ac_cv_sys_largefile_source" >&6; }
-case $ac_cv_sys_largefile_source in #(
-  no | unknown) ;;
-  *)
-cat >>confdefs.h <<_ACEOF
-#define _LARGEFILE_SOURCE $ac_cv_sys_largefile_source
-_ACEOF
-;;
-esac
-rm -f -r conftest*
-
-# We used to try defining _XOPEN_SOURCE=500 too, to work around a bug
-# in glibc 2.1.3, but that breaks too many other things.
-# If you want fseeko and ftello with glibc, upgrade to a fixed glibc.
-if test $ac_cv_sys_largefile_source != unknown; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_FSEEKO 1
-_ACEOF
-
-fi
-
-# Check whether --enable-largefile was given.
-if test "${enable_largefile+set}" = set; then
-  enableval=$enable_largefile;
-fi
-
-if test "$enable_largefile" != no; then
-
-  { echo "$as_me:$LINENO: checking for special C compiler options needed for large files" >&5
-echo $ECHO_N "checking for special C compiler options needed for large files... $ECHO_C" >&6; }
-if test "${ac_cv_sys_largefile_CC+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  ac_cv_sys_largefile_CC=no
-     if test "$GCC" != yes; then
-       ac_save_CC=$CC
-       while :; do
-	 # IRIX 6.2 and later do not support large files by default,
-	 # so use the C compiler's -n32 option if that helps.
-	 cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <sys/types.h>
- /* Check that off_t can represent 2**63 - 1 correctly.
-    We can't simply define LARGE_OFF_T to be 9223372036854775807,
-    since some C++ compilers masquerading as C compilers
-    incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
-  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
-		       && LARGE_OFF_T % 2147483647 == 1)
-		      ? 1 : -1];
-#ifdef F77_DUMMY_MAIN
-
-#  ifdef __cplusplus
-     extern "C"
-#  endif
-   int F77_DUMMY_MAIN() { return 1; }
-
-#endif
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-	 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  break
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext
-	 CC="$CC -n32"
-	 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  ac_cv_sys_largefile_CC=' -n32'; break
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext
-	 break
-       done
-       CC=$ac_save_CC
-       rm -f conftest.$ac_ext
-    fi
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_sys_largefile_CC" >&5
-echo "${ECHO_T}$ac_cv_sys_largefile_CC" >&6; }
-  if test "$ac_cv_sys_largefile_CC" != no; then
-    CC=$CC$ac_cv_sys_largefile_CC
-  fi
-
-  { echo "$as_me:$LINENO: checking for _FILE_OFFSET_BITS value needed for large files" >&5
-echo $ECHO_N "checking for _FILE_OFFSET_BITS value needed for large files... $ECHO_C" >&6; }
-if test "${ac_cv_sys_file_offset_bits+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  while :; do
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <sys/types.h>
- /* Check that off_t can represent 2**63 - 1 correctly.
-    We can't simply define LARGE_OFF_T to be 9223372036854775807,
-    since some C++ compilers masquerading as C compilers
-    incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
-  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
-		       && LARGE_OFF_T % 2147483647 == 1)
-		      ? 1 : -1];
-#ifdef F77_DUMMY_MAIN
-
-#  ifdef __cplusplus
-     extern "C"
-#  endif
-   int F77_DUMMY_MAIN() { return 1; }
-
-#endif
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  ac_cv_sys_file_offset_bits=no; break
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#define _FILE_OFFSET_BITS 64
-#include <sys/types.h>
- /* Check that off_t can represent 2**63 - 1 correctly.
-    We can't simply define LARGE_OFF_T to be 9223372036854775807,
-    since some C++ compilers masquerading as C compilers
-    incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
-  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
-		       && LARGE_OFF_T % 2147483647 == 1)
-		      ? 1 : -1];
-#ifdef F77_DUMMY_MAIN
-
-#  ifdef __cplusplus
-     extern "C"
-#  endif
-   int F77_DUMMY_MAIN() { return 1; }
-
-#endif
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  ac_cv_sys_file_offset_bits=64; break
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-  ac_cv_sys_file_offset_bits=unknown
-  break
-done
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_sys_file_offset_bits" >&5
-echo "${ECHO_T}$ac_cv_sys_file_offset_bits" >&6; }
-case $ac_cv_sys_file_offset_bits in #(
-  no | unknown) ;;
-  *)
-cat >>confdefs.h <<_ACEOF
-#define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits
-_ACEOF
-;;
-esac
-rm -f -r conftest*
-  if test $ac_cv_sys_file_offset_bits = unknown; then
-    { echo "$as_me:$LINENO: checking for _LARGE_FILES value needed for large files" >&5
-echo $ECHO_N "checking for _LARGE_FILES value needed for large files... $ECHO_C" >&6; }
-if test "${ac_cv_sys_large_files+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  while :; do
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <sys/types.h>
- /* Check that off_t can represent 2**63 - 1 correctly.
-    We can't simply define LARGE_OFF_T to be 9223372036854775807,
-    since some C++ compilers masquerading as C compilers
-    incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
-  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
-		       && LARGE_OFF_T % 2147483647 == 1)
-		      ? 1 : -1];
-#ifdef F77_DUMMY_MAIN
-
-#  ifdef __cplusplus
-     extern "C"
-#  endif
-   int F77_DUMMY_MAIN() { return 1; }
-
-#endif
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  ac_cv_sys_large_files=no; break
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#define _LARGE_FILES 1
-#include <sys/types.h>
- /* Check that off_t can represent 2**63 - 1 correctly.
-    We can't simply define LARGE_OFF_T to be 9223372036854775807,
-    since some C++ compilers masquerading as C compilers
-    incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
-  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
-		       && LARGE_OFF_T % 2147483647 == 1)
-		      ? 1 : -1];
-#ifdef F77_DUMMY_MAIN
-
-#  ifdef __cplusplus
-     extern "C"
-#  endif
-   int F77_DUMMY_MAIN() { return 1; }
-
-#endif
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  ac_cv_sys_large_files=1; break
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-  ac_cv_sys_large_files=unknown
-  break
-done
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_sys_large_files" >&5
-echo "${ECHO_T}$ac_cv_sys_large_files" >&6; }
-case $ac_cv_sys_large_files in #(
-  no | unknown) ;;
-  *)
-cat >>confdefs.h <<_ACEOF
-#define _LARGE_FILES $ac_cv_sys_large_files
-_ACEOF
-;;
-esac
-rm -f -r conftest*
-  fi
-fi
-
-
-
-# Extra places to look for third-party libraries and header files.
-LIBDIRS=
-
-
-# Check whether --with-cfitsio was given.
-if test "${with_cfitsio+set}" = set; then
-  withval=$with_cfitsio;
-fi
-
-if test "x$with_cfitsio" = xno ; then
-  { echo "$as_me:$LINENO: WARNING: CFITSIO disabled" >&5
-echo "$as_me: WARNING: CFITSIO disabled" >&2;}
-else
-
-# Check whether --with-cfitsiolib was given.
-if test "${with_cfitsiolib+set}" = set; then
-  withval=$with_cfitsiolib;
-fi
-
-  if test "x$with_cfitsiolib" != x ; then
-    LIBDIRS="$LIBDIRS $with_cfitsiolib"
-  fi
-
-
-# Check whether --with-cfitsioinc was given.
-if test "${with_cfitsioinc+set}" = set; then
-  withval=$with_cfitsioinc;
-fi
-
-  if test "x$with_cfitsioinc" != x ; then
-    CFITSIO_INCDIRS="$with_cfitsioinc"
-  fi
-
-  CFITSIO_INCDIRS="$CFITSIO_INCDIRS   \
-           /usr/local/cfitsio/include \
-           /local/cfitsio/include"
-
-  LIBDIRS="$LIBDIRS           \
-           /usr/local/cfitsio/lib \
-           /local/cfitsio/lib"
-fi
-
-
-# Check whether --with-pgplot was given.
-if test "${with_pgplot+set}" = set; then
-  withval=$with_pgplot;
-fi
-
-if test "x$with_pgplot" = xno ; then
-  { echo "$as_me:$LINENO: WARNING: PGPLOT disabled" >&5
-echo "$as_me: WARNING: PGPLOT disabled" >&2;}
-else
-
-# Check whether --with-pgplotlib was given.
-if test "${with_pgplotlib+set}" = set; then
-  withval=$with_pgplotlib;
-fi
-
-  if test "x$with_pgplotlib" != x ; then
-    LIBDIRS="$LIBDIRS $with_pgplotlib"
-  fi
-
-
-# Check whether --with-pgplotinc was given.
-if test "${with_pgplotinc+set}" = set; then
-  withval=$with_pgplotinc;
-fi
-
-  if test "x$with_pgplotinc" != x ; then
-    PGPLOT_INCDIRS="$with_pgplotinc"
-  fi
-
-  PGPLOT_INCDIRS="$PGPLOT_INCDIRS    \
-           /usr/local/pgplot/include \
-           /local/pgplot/include"
-
-  LIBDIRS="$LIBDIRS           \
-           /usr/local/pgplot/lib  \
-           /local/pgplot/lib"
-fi
-
-
-if test "x$with_cfitsio" != xno -o \
-        "x$with_pgplot"  != xno ; then
-  LIBDIRS="$LIBDIRS           \
-           /usr/local/lib     \
-           /local/lib         \
-           /opt/local/lib     \
-           /opt/SUNWspro/lib  \
-           /sw/lib"
-
-  for LIBDIR in $LIBDIRS ; do
-    as_ac_File=`echo "ac_cv_file_$LIBDIR" | $as_tr_sh`
-{ echo "$as_me:$LINENO: checking for $LIBDIR" >&5
-echo $ECHO_N "checking for $LIBDIR... $ECHO_C" >&6; }
-if { as_var=$as_ac_File; eval "test \"\${$as_var+set}\" = set"; }; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  test "$cross_compiling" = yes &&
-  { { echo "$as_me:$LINENO: error: cannot check for file existence when cross compiling" >&5
-echo "$as_me: error: cannot check for file existence when cross compiling" >&2;}
-   { (exit 1); exit 1; }; }
-if test -r "$LIBDIR"; then
-  eval "$as_ac_File=yes"
-else
-  eval "$as_ac_File=no"
-fi
-fi
-ac_res=`eval echo '${'$as_ac_File'}'`
-	       { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-if test `eval echo '${'$as_ac_File'}'` = yes; then
-  LDFLAGS="$LDFLAGS -L$LIBDIR"
-else
-  continue
-fi
-
-  done
-
-  # Generic include directories.
-  INCDIRS="/usr/local/include \
-           /local/include     \
-           /opt/local/include \
-           /sw/include        \
-           /local             \
-           /usr/include"
-
-
-  # CFITSIO.
-  if test "x$with_cfitsio" != xno ; then
-    # Search for CFITSIO.
-    for INCDIR in $CFITSIO_INCDIRS $INCDIRS ; do
-      as_ac_File=`echo "ac_cv_file_$INCDIR/cfitsio/fitsio.h" | $as_tr_sh`
-{ echo "$as_me:$LINENO: checking for $INCDIR/cfitsio/fitsio.h" >&5
-echo $ECHO_N "checking for $INCDIR/cfitsio/fitsio.h... $ECHO_C" >&6; }
-if { as_var=$as_ac_File; eval "test \"\${$as_var+set}\" = set"; }; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  test "$cross_compiling" = yes &&
-  { { echo "$as_me:$LINENO: error: cannot check for file existence when cross compiling" >&5
-echo "$as_me: error: cannot check for file existence when cross compiling" >&2;}
-   { (exit 1); exit 1; }; }
-if test -r "$INCDIR/cfitsio/fitsio.h"; then
-  eval "$as_ac_File=yes"
-else
-  eval "$as_ac_File=no"
-fi
-fi
-ac_res=`eval echo '${'$as_ac_File'}'`
-	       { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-if test `eval echo '${'$as_ac_File'}'` = yes; then
-  CFITSIOINC="-I$INCDIR/cfitsio"; break
-fi
-
-      as_ac_File=`echo "ac_cv_file_$INCDIR/fitsio.h" | $as_tr_sh`
-{ echo "$as_me:$LINENO: checking for $INCDIR/fitsio.h" >&5
-echo $ECHO_N "checking for $INCDIR/fitsio.h... $ECHO_C" >&6; }
-if { as_var=$as_ac_File; eval "test \"\${$as_var+set}\" = set"; }; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  test "$cross_compiling" = yes &&
-  { { echo "$as_me:$LINENO: error: cannot check for file existence when cross compiling" >&5
-echo "$as_me: error: cannot check for file existence when cross compiling" >&2;}
-   { (exit 1); exit 1; }; }
-if test -r "$INCDIR/fitsio.h"; then
-  eval "$as_ac_File=yes"
-else
-  eval "$as_ac_File=no"
-fi
-fi
-ac_res=`eval echo '${'$as_ac_File'}'`
-	       { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-if test `eval echo '${'$as_ac_File'}'` = yes; then
-  CFITSIOINC="-I$INCDIR"; break
-fi
-
-    done
-
-    { echo "$as_me:$LINENO: checking for recv in -lsocket" >&5
-echo $ECHO_N "checking for recv in -lsocket... $ECHO_C" >&6; }
-if test "${ac_cv_lib_socket_recv+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  ac_check_lib_save_LIBS=$LIBS
-LIBS="-lsocket $LIBS $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* 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 recv ();
-#ifdef F77_DUMMY_MAIN
-
-#  ifdef __cplusplus
-     extern "C"
-#  endif
-   int F77_DUMMY_MAIN() { return 1; }
-
-#endif
-int
-main ()
-{
-return recv ();
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest$ac_exeext &&
-       $as_test_x conftest$ac_exeext; then
-  ac_cv_lib_socket_recv=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	ac_cv_lib_socket_recv=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
-      conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_lib_socket_recv" >&5
-echo "${ECHO_T}$ac_cv_lib_socket_recv" >&6; }
-if test $ac_cv_lib_socket_recv = yes; then
-  CFITSIOLIB="-lsocket"
-fi
-
-    { echo "$as_me:$LINENO: checking for ffopen in -lcfitsio" >&5
-echo $ECHO_N "checking for ffopen in -lcfitsio... $ECHO_C" >&6; }
-if test "${ac_cv_lib_cfitsio_ffopen+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  ac_check_lib_save_LIBS=$LIBS
-LIBS="-lcfitsio $CFITSIOLIB $LIBS $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* 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 ffopen ();
-#ifdef F77_DUMMY_MAIN
-
-#  ifdef __cplusplus
-     extern "C"
-#  endif
-   int F77_DUMMY_MAIN() { return 1; }
-
-#endif
-int
-main ()
-{
-return ffopen ();
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest$ac_exeext &&
-       $as_test_x conftest$ac_exeext; then
-  ac_cv_lib_cfitsio_ffopen=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	ac_cv_lib_cfitsio_ffopen=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
-      conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_lib_cfitsio_ffopen" >&5
-echo "${ECHO_T}$ac_cv_lib_cfitsio_ffopen" >&6; }
-if test $ac_cv_lib_cfitsio_ffopen = yes; then
-  CFITSIOLIB="-lcfitsio $CFITSIOLIB"
-fi
-
-
-    if test "x$CFITSIOINC" = x -o "x$CFITSIOLIB" = x; then
-      { echo "$as_me:$LINENO: WARNING: CFITSIO not found, skipping CFITSIO-dependent tests." >&5
-echo "$as_me: WARNING: CFITSIO not found, skipping CFITSIO-dependent tests." >&2;}
-    else
-      { echo "$as_me:$LINENO: CFITSIO appears to be available." >&5
-echo "$as_me: CFITSIO appears to be available." >&6;}
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_CFITSIO 1
-_ACEOF
-
-
-      # Check for fits_read_wcstab, present in CFITSIO 3.004beta and later.
-      { echo "$as_me:$LINENO: checking for fits_read_wcstab in -lcfitsio" >&5
-echo $ECHO_N "checking for fits_read_wcstab in -lcfitsio... $ECHO_C" >&6; }
-if test "${ac_cv_lib_cfitsio_fits_read_wcstab+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  ac_check_lib_save_LIBS=$LIBS
-LIBS="-lcfitsio $CFITSIOLIB $LIBS $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* 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 fits_read_wcstab ();
-#ifdef F77_DUMMY_MAIN
-
-#  ifdef __cplusplus
-     extern "C"
-#  endif
-   int F77_DUMMY_MAIN() { return 1; }
-
-#endif
-int
-main ()
-{
-return fits_read_wcstab ();
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest$ac_exeext &&
-       $as_test_x conftest$ac_exeext; then
-  ac_cv_lib_cfitsio_fits_read_wcstab=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	ac_cv_lib_cfitsio_fits_read_wcstab=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
-      conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_lib_cfitsio_fits_read_wcstab" >&5
-echo "${ECHO_T}$ac_cv_lib_cfitsio_fits_read_wcstab" >&6; }
-if test $ac_cv_lib_cfitsio_fits_read_wcstab = yes; then
-  GETWCSTAB=
-else
-  GETWCSTAB=getwcstab.o
-fi
-
-      if test "x$GETWCSTAB" != x ; then
-        { echo "$as_me:$LINENO: WARNING: fits_read_wcstab not found in CFITSIO, will use
-                        getwcstab.c to compile test programs." >&5
-echo "$as_me: WARNING: fits_read_wcstab not found in CFITSIO, will use
-                        getwcstab.c to compile test programs." >&2;}
-      fi
-    fi
-  fi
-
-  # PGPLOT.
-  if test "x$F77" != x -a "x$with_pgplot" != xno ; then
-    # Search for PGPLOT.
-    for INCDIR in $PGPLOT_INCDIRS $INCDIRS ; do
-      as_ac_File=`echo "ac_cv_file_$INCDIR/pgplot/cpgplot.h" | $as_tr_sh`
-{ echo "$as_me:$LINENO: checking for $INCDIR/pgplot/cpgplot.h" >&5
-echo $ECHO_N "checking for $INCDIR/pgplot/cpgplot.h... $ECHO_C" >&6; }
-if { as_var=$as_ac_File; eval "test \"\${$as_var+set}\" = set"; }; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  test "$cross_compiling" = yes &&
-  { { echo "$as_me:$LINENO: error: cannot check for file existence when cross compiling" >&5
-echo "$as_me: error: cannot check for file existence when cross compiling" >&2;}
-   { (exit 1); exit 1; }; }
-if test -r "$INCDIR/pgplot/cpgplot.h"; then
-  eval "$as_ac_File=yes"
-else
-  eval "$as_ac_File=no"
-fi
-fi
-ac_res=`eval echo '${'$as_ac_File'}'`
-	       { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-if test `eval echo '${'$as_ac_File'}'` = yes; then
-  PGPLOTINC="-I$INCDIR/pgplot"; break
-fi
-
-      as_ac_File=`echo "ac_cv_file_$INCDIR/cpgplot.h" | $as_tr_sh`
-{ echo "$as_me:$LINENO: checking for $INCDIR/cpgplot.h" >&5
-echo $ECHO_N "checking for $INCDIR/cpgplot.h... $ECHO_C" >&6; }
-if { as_var=$as_ac_File; eval "test \"\${$as_var+set}\" = set"; }; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  test "$cross_compiling" = yes &&
-  { { echo "$as_me:$LINENO: error: cannot check for file existence when cross compiling" >&5
-echo "$as_me: error: cannot check for file existence when cross compiling" >&2;}
-   { (exit 1); exit 1; }; }
-if test -r "$INCDIR/cpgplot.h"; then
-  eval "$as_ac_File=yes"
-else
-  eval "$as_ac_File=no"
-fi
-fi
-ac_res=`eval echo '${'$as_ac_File'}'`
-	       { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-if test `eval echo '${'$as_ac_File'}'` = yes; then
-  PGPLOTINC="-I$INCDIR"; break
-fi
-
-    done
-
-    # FLIBS (found above via AC_F77_LIBRARY_LDFLAGS) only helps if PGPLOT was
-    # built using the same Fortran compiler that we are using here.
-
-    # PGPLOT compiled by the SUN Fortran compiler but linked with something
-    # else.
-    { echo "$as_me:$LINENO: checking for iand_ in -lM77" >&5
-echo $ECHO_N "checking for iand_ in -lM77... $ECHO_C" >&6; }
-if test "${ac_cv_lib_M77_iand_+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  ac_check_lib_save_LIBS=$LIBS
-LIBS="-lM77 $PGPLOTLIB $LIBS $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* 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 iand_ ();
-#ifdef F77_DUMMY_MAIN
-
-#  ifdef __cplusplus
-     extern "C"
-#  endif
-   int F77_DUMMY_MAIN() { return 1; }
-
-#endif
-int
-main ()
-{
-return iand_ ();
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest$ac_exeext &&
-       $as_test_x conftest$ac_exeext; then
-  ac_cv_lib_M77_iand_=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	ac_cv_lib_M77_iand_=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
-      conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_lib_M77_iand_" >&5
-echo "${ECHO_T}$ac_cv_lib_M77_iand_" >&6; }
-if test $ac_cv_lib_M77_iand_ = yes; then
-  PGPLOTLIB="-lM77 $PGPLOTLIB"
-fi
-
-    { echo "$as_me:$LINENO: checking for f77_init in -lF77" >&5
-echo $ECHO_N "checking for f77_init in -lF77... $ECHO_C" >&6; }
-if test "${ac_cv_lib_F77_f77_init+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  ac_check_lib_save_LIBS=$LIBS
-LIBS="-lF77 $PGPLOTLIB $LIBS $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* 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 f77_init ();
-#ifdef F77_DUMMY_MAIN
-
-#  ifdef __cplusplus
-     extern "C"
-#  endif
-   int F77_DUMMY_MAIN() { return 1; }
-
-#endif
-int
-main ()
-{
-return f77_init ();
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest$ac_exeext &&
-       $as_test_x conftest$ac_exeext; then
-  ac_cv_lib_F77_f77_init=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	ac_cv_lib_F77_f77_init=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
-      conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_lib_F77_f77_init" >&5
-echo "${ECHO_T}$ac_cv_lib_F77_f77_init" >&6; }
-if test $ac_cv_lib_F77_f77_init = yes; then
-  PGPLOTLIB="-lF77 $PGPLOTLIB"
-fi
-
-
-    if test "x$F77" != xg77; then
-      # For PGPLOT compiled with g77 but linked with something else.
-      { echo "$as_me:$LINENO: checking for main in -lfrtbegin" >&5
-echo $ECHO_N "checking for main in -lfrtbegin... $ECHO_C" >&6; }
-if test "${ac_cv_lib_frtbegin_main+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  ac_check_lib_save_LIBS=$LIBS
-LIBS="-lfrtbegin $PGPLOTLIB $LIBS $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-
-
-#ifdef F77_DUMMY_MAIN
-
-#  ifdef __cplusplus
-     extern "C"
-#  endif
-   int F77_DUMMY_MAIN() { return 1; }
-
-#endif
-int
-main ()
-{
-return main ();
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest$ac_exeext &&
-       $as_test_x conftest$ac_exeext; then
-  ac_cv_lib_frtbegin_main=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	ac_cv_lib_frtbegin_main=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
-      conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_lib_frtbegin_main" >&5
-echo "${ECHO_T}$ac_cv_lib_frtbegin_main" >&6; }
-if test $ac_cv_lib_frtbegin_main = yes; then
-  PGPLOTLIB="-lfrtbegin $PGPLOTLIB"
-fi
-
-      { echo "$as_me:$LINENO: checking for gerror_ in -lg2c" >&5
-echo $ECHO_N "checking for gerror_ in -lg2c... $ECHO_C" >&6; }
-if test "${ac_cv_lib_g2c_gerror_+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  ac_check_lib_save_LIBS=$LIBS
-LIBS="-lg2c $PGPLOTLIB $LIBS $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* 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 gerror_ ();
-#ifdef F77_DUMMY_MAIN
-
-#  ifdef __cplusplus
-     extern "C"
-#  endif
-   int F77_DUMMY_MAIN() { return 1; }
-
-#endif
-int
-main ()
-{
-return gerror_ ();
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest$ac_exeext &&
-       $as_test_x conftest$ac_exeext; then
-  ac_cv_lib_g2c_gerror_=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	ac_cv_lib_g2c_gerror_=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
-      conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_lib_g2c_gerror_" >&5
-echo "${ECHO_T}$ac_cv_lib_g2c_gerror_" >&6; }
-if test $ac_cv_lib_g2c_gerror_ = yes; then
-  PGPLOTLIB="-lg2c $PGPLOTLIB"
-fi
-
-    fi
-
-    if test "x$F77" != xgfortran; then
-      # For PGPLOT compiled with gfortran but linked with something else.
-      # Note that if gfortran itself is driving the linker it can be harmful
-      # to add -lgfortran to the link list without also adding -lgfortranbegin.
-      # Doing so stops gfortran from adding -lgfortranbegin which is needed to
-      # resolve "main".
-      { echo "$as_me:$LINENO: checking for _gfortran_abort in -lgfortran" >&5
-echo $ECHO_N "checking for _gfortran_abort in -lgfortran... $ECHO_C" >&6; }
-if test "${ac_cv_lib_gfortran__gfortran_abort+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  ac_check_lib_save_LIBS=$LIBS
-LIBS="-lgfortran $PGPLOTLIB $LIBS $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* 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 _gfortran_abort ();
-#ifdef F77_DUMMY_MAIN
-
-#  ifdef __cplusplus
-     extern "C"
-#  endif
-   int F77_DUMMY_MAIN() { return 1; }
-
-#endif
-int
-main ()
-{
-return _gfortran_abort ();
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest$ac_exeext &&
-       $as_test_x conftest$ac_exeext; then
-  ac_cv_lib_gfortran__gfortran_abort=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	ac_cv_lib_gfortran__gfortran_abort=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
-      conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_lib_gfortran__gfortran_abort" >&5
-echo "${ECHO_T}$ac_cv_lib_gfortran__gfortran_abort" >&6; }
-if test $ac_cv_lib_gfortran__gfortran_abort = yes; then
-  PGPLOTLIB="-lgfortran $PGPLOTLIB"
-fi
-
-    fi
-
-    # Search for X11 includes and libraries.
-    { echo "$as_me:$LINENO: checking for X" >&5
-echo $ECHO_N "checking for X... $ECHO_C" >&6; }
-
-
-# Check whether --with-x was given.
-if test "${with_x+set}" = set; then
-  withval=$with_x;
-fi
-
-# $have_x is `yes', `no', `disabled', or empty when we do not yet know.
-if test "x$with_x" = xno; then
-  # The user explicitly disabled X.
-  have_x=disabled
-else
-  case $x_includes,$x_libraries in #(
-    *\'*) { { echo "$as_me:$LINENO: error: Cannot use X directory names containing '" >&5
-echo "$as_me: error: Cannot use X directory names containing '" >&2;}
-   { (exit 1); exit 1; }; };; #(
-    *,NONE | NONE,*) if test "${ac_cv_have_x+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  # One or both of the vars are not set, and there is no cached value.
-ac_x_includes=no ac_x_libraries=no
-rm -f -r conftest.dir
-if mkdir conftest.dir; then
-  cd conftest.dir
-  cat >Imakefile <<'_ACEOF'
-incroot:
-	@echo incroot='${INCROOT}'
-usrlibdir:
-	@echo usrlibdir='${USRLIBDIR}'
-libdir:
-	@echo libdir='${LIBDIR}'
-_ACEOF
-  if (export CC; ${XMKMF-xmkmf}) >/dev/null 2>/dev/null && test -f Makefile; then
-    # GNU make sometimes prints "make[1]: Entering...", which would confuse us.
-    for ac_var in incroot usrlibdir libdir; do
-      eval "ac_im_$ac_var=\`\${MAKE-make} $ac_var 2>/dev/null | sed -n 's/^$ac_var=//p'\`"
-    done
-    # Open Windows xmkmf reportedly sets LIBDIR instead of USRLIBDIR.
-    for ac_extension in a so sl dylib la dll; do
-      if test ! -f "$ac_im_usrlibdir/libX11.$ac_extension" &&
-	 test -f "$ac_im_libdir/libX11.$ac_extension"; then
-	ac_im_usrlibdir=$ac_im_libdir; break
-      fi
-    done
-    # Screen out bogus values from the imake configuration.  They are
-    # bogus both because they are the default anyway, and because
-    # using them would break gcc on systems where it needs fixed includes.
-    case $ac_im_incroot in
-	/usr/include) ac_x_includes= ;;
-	*) test -f "$ac_im_incroot/X11/Xos.h" && ac_x_includes=$ac_im_incroot;;
-    esac
-    case $ac_im_usrlibdir in
-	/usr/lib | /lib) ;;
-	*) test -d "$ac_im_usrlibdir" && ac_x_libraries=$ac_im_usrlibdir ;;
-    esac
-  fi
-  cd ..
-  rm -f -r conftest.dir
-fi
-
-# Standard set of common directories for X headers.
-# Check X11 before X11Rn because it is often a symlink to the current release.
-ac_x_header_dirs='
-/usr/X11/include
-/usr/X11R6/include
-/usr/X11R5/include
-/usr/X11R4/include
-
-/usr/include/X11
-/usr/include/X11R6
-/usr/include/X11R5
-/usr/include/X11R4
-
-/usr/local/X11/include
-/usr/local/X11R6/include
-/usr/local/X11R5/include
-/usr/local/X11R4/include
-
-/usr/local/include/X11
-/usr/local/include/X11R6
-/usr/local/include/X11R5
-/usr/local/include/X11R4
-
-/usr/X386/include
-/usr/x386/include
-/usr/XFree86/include/X11
-
-/usr/include
-/usr/local/include
-/usr/unsupported/include
-/usr/athena/include
-/usr/local/x11r5/include
-/usr/lpp/Xamples/include
-
-/usr/openwin/include
-/usr/openwin/share/include'
-
-if test "$ac_x_includes" = no; then
-  # Guess where to find include files, by looking for Xlib.h.
-  # First, try using that file with no special directory specified.
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <X11/Xlib.h>
-_ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } >/dev/null && {
-	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       }; then
-  # We can compile using X headers with no special include directory.
-ac_x_includes=
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-  for ac_dir in $ac_x_header_dirs; do
-  if test -r "$ac_dir/X11/Xlib.h"; then
-    ac_x_includes=$ac_dir
-    break
-  fi
-done
-fi
-
-rm -f conftest.err conftest.$ac_ext
-fi # $ac_x_includes = no
-
-if test "$ac_x_libraries" = no; then
-  # Check for the libraries.
-  # See if we find them without any special options.
-  # Don't add to $LIBS permanently.
-  ac_save_LIBS=$LIBS
-  LIBS="-lX11 $LIBS"
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <X11/Xlib.h>
-#ifdef F77_DUMMY_MAIN
-
-#  ifdef __cplusplus
-     extern "C"
-#  endif
-   int F77_DUMMY_MAIN() { return 1; }
-
-#endif
-int
-main ()
-{
-XrmInitialize ()
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest$ac_exeext &&
-       $as_test_x conftest$ac_exeext; then
-  LIBS=$ac_save_LIBS
-# We can link X programs with no special library path.
-ac_x_libraries=
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	LIBS=$ac_save_LIBS
-for ac_dir in `echo "$ac_x_includes $ac_x_header_dirs" | sed s/include/lib/g`
-do
-  # Don't even attempt the hair of trying to link an X program!
-  for ac_extension in a so sl dylib la dll; do
-    if test -r "$ac_dir/libX11.$ac_extension"; then
-      ac_x_libraries=$ac_dir
-      break 2
-    fi
-  done
-done
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
-      conftest$ac_exeext conftest.$ac_ext
-fi # $ac_x_libraries = no
-
-case $ac_x_includes,$ac_x_libraries in #(
-  no,* | *,no | *\'*)
-    # Didn't find X, or a directory has "'" in its name.
-    ac_cv_have_x="have_x=no";; #(
-  *)
-    # Record where we found X for the cache.
-    ac_cv_have_x="have_x=yes\
-	ac_x_includes='$ac_x_includes'\
-	ac_x_libraries='$ac_x_libraries'"
-esac
-fi
-;; #(
-    *) have_x=yes;;
-  esac
-  eval "$ac_cv_have_x"
-fi # $with_x != no
-
-if test "$have_x" != yes; then
-  { echo "$as_me:$LINENO: result: $have_x" >&5
-echo "${ECHO_T}$have_x" >&6; }
-  no_x=yes
-else
-  # If each of the values was on the command line, it overrides each guess.
-  test "x$x_includes" = xNONE && x_includes=$ac_x_includes
-  test "x$x_libraries" = xNONE && x_libraries=$ac_x_libraries
-  # Update the cache value to reflect the command line values.
-  ac_cv_have_x="have_x=yes\
-	ac_x_includes='$x_includes'\
-	ac_x_libraries='$x_libraries'"
-  { echo "$as_me:$LINENO: result: libraries $x_libraries, headers $x_includes" >&5
-echo "${ECHO_T}libraries $x_libraries, headers $x_includes" >&6; }
-fi
-
-    if test "x$no_x" = x; then
-      if test "x$ac_x_libraries" != x ; then
-        # Not needed for systems that keep the X11 libraries in /usr/lib.
-        LDFLAGS="$LDFLAGS -L$ac_x_libraries"
-      fi
-      PGPLOTLIB="-lX11 $PGPLOTLIB"
-    fi
-
-    # It is possible that other libraries may be required depending on what
-    # graphics drivers were installed with PGPLOT.
-    { echo "$as_me:$LINENO: checking for deflate in -lz" >&5
-echo $ECHO_N "checking for deflate in -lz... $ECHO_C" >&6; }
-if test "${ac_cv_lib_z_deflate+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  ac_check_lib_save_LIBS=$LIBS
-LIBS="-lz $PGPLOTLIB $LIBS $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* 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 deflate ();
-#ifdef F77_DUMMY_MAIN
-
-#  ifdef __cplusplus
-     extern "C"
-#  endif
-   int F77_DUMMY_MAIN() { return 1; }
-
-#endif
-int
-main ()
-{
-return deflate ();
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest$ac_exeext &&
-       $as_test_x conftest$ac_exeext; then
-  ac_cv_lib_z_deflate=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	ac_cv_lib_z_deflate=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
-      conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_lib_z_deflate" >&5
-echo "${ECHO_T}$ac_cv_lib_z_deflate" >&6; }
-if test $ac_cv_lib_z_deflate = yes; then
-  PGPLOTLIB="-lz $PGPLOTLIB"
-fi
-
-    { echo "$as_me:$LINENO: checking for png_error in -lpng" >&5
-echo $ECHO_N "checking for png_error in -lpng... $ECHO_C" >&6; }
-if test "${ac_cv_lib_png_png_error+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  ac_check_lib_save_LIBS=$LIBS
-LIBS="-lpng $PGPLOTLIB $LIBS $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* 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 png_error ();
-#ifdef F77_DUMMY_MAIN
-
-#  ifdef __cplusplus
-     extern "C"
-#  endif
-   int F77_DUMMY_MAIN() { return 1; }
-
-#endif
-int
-main ()
-{
-return png_error ();
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest$ac_exeext &&
-       $as_test_x conftest$ac_exeext; then
-  ac_cv_lib_png_png_error=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	ac_cv_lib_png_png_error=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
-      conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_lib_png_png_error" >&5
-echo "${ECHO_T}$ac_cv_lib_png_png_error" >&6; }
-if test $ac_cv_lib_png_png_error = yes; then
-  PGPLOTLIB="-lpng $PGPLOTLIB"
-fi
-
-    { echo "$as_me:$LINENO: checking for pgbeg_ in -lpgplot" >&5
-echo $ECHO_N "checking for pgbeg_ in -lpgplot... $ECHO_C" >&6; }
-if test "${ac_cv_lib_pgplot_pgbeg_+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  ac_check_lib_save_LIBS=$LIBS
-LIBS="-lpgplot $PGPLOTLIB $FLIBS $LIBS $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* 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 pgbeg_ ();
-#ifdef F77_DUMMY_MAIN
-
-#  ifdef __cplusplus
-     extern "C"
-#  endif
-   int F77_DUMMY_MAIN() { return 1; }
-
-#endif
-int
-main ()
-{
-return pgbeg_ ();
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest$ac_exeext &&
-       $as_test_x conftest$ac_exeext; then
-  ac_cv_lib_pgplot_pgbeg_=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	ac_cv_lib_pgplot_pgbeg_=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
-      conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_lib_pgplot_pgbeg_" >&5
-echo "${ECHO_T}$ac_cv_lib_pgplot_pgbeg_" >&6; }
-if test $ac_cv_lib_pgplot_pgbeg_ = yes; then
-  PGPLOTLIB="-lpgplot $PGPLOTLIB"
-fi
-
-    { echo "$as_me:$LINENO: checking for cpgbeg in -lcpgplot" >&5
-echo $ECHO_N "checking for cpgbeg in -lcpgplot... $ECHO_C" >&6; }
-if test "${ac_cv_lib_cpgplot_cpgbeg+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  ac_check_lib_save_LIBS=$LIBS
-LIBS="-lcpgplot $PGPLOTLIB $FLIBS $LIBS $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* 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 cpgbeg ();
-#ifdef F77_DUMMY_MAIN
-
-#  ifdef __cplusplus
-     extern "C"
-#  endif
-   int F77_DUMMY_MAIN() { return 1; }
-
-#endif
-int
-main ()
-{
-return cpgbeg ();
-  ;
-  return 0;
-}
-_ACEOF
-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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest$ac_exeext &&
-       $as_test_x conftest$ac_exeext; then
-  ac_cv_lib_cpgplot_cpgbeg=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	ac_cv_lib_cpgplot_cpgbeg=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
-      conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_lib_cpgplot_cpgbeg" >&5
-echo "${ECHO_T}$ac_cv_lib_cpgplot_cpgbeg" >&6; }
-if test $ac_cv_lib_cpgplot_cpgbeg = yes; then
-  PGPLOTLIB="-lcpgplot $PGPLOTLIB"
-else
-  PGPLOTLIB=
-fi
-
-
-    # Only need the PGPLOT include file to build PGSBOX.
-    if test "x$PGPLOTINC" != x; then
-      SUBDIRS="$SUBDIRS pgsbox"
-      INSTDIR="pgsbox"
-    fi
-
-    # Also need the PGPLOT library to build pgtest and cpgtest.
-    if test "x$PGPLOTLIB" = x; then
-      { echo "$as_me:$LINENO: WARNING: PGPLOT not found, skipping PGPLOT-dependent tests." >&5
-echo "$as_me: WARNING: PGPLOT not found, skipping PGPLOT-dependent tests." >&2;}
-    else
-      { echo "$as_me:$LINENO: PGPLOT appears to be available." >&5
-echo "$as_me: PGPLOT appears to be available." >&6;}
-
-      TSTDIRS="$TSTDIRS pgsbox"
-    fi
-  fi
-fi
-
-
-# Utilities are compiled last since they need the libraries.
-# Ways of disabling them:
-#   configure --disable-utils
-#   configure --enable-utils=no
-# Check whether --enable-utils was given.
-if test "${enable_utils+set}" = set; then
-  enableval=$enable_utils;
-fi
-
-if test "x$enable_utils" != xno ; then
-  SUBDIRS="$SUBDIRS utils"
-  INSTDIR="$INSTDIR utils"
-else
-  { echo "$as_me:$LINENO: WARNING: Compilation of WCS utilities disabled" >&5
-echo "$as_me: WARNING: Compilation of WCS utilities disabled" >&2;}
-fi
-
-
-
-
-
-
-
-
-
-
-
-
-
-{ echo "$as_me:$LINENO: End of auxiliary configuration.
-" >&5
-echo "$as_me: End of auxiliary configuration.
-" >&6;}
-
-
-# Do it.
-{ echo "$as_me:$LINENO: Configuring files..." >&5
-echo "$as_me: Configuring files..." >&6;}
-ac_config_files="$ac_config_files makedefs wcslib.pc"
-
-ac_config_headers="$ac_config_headers wcsconfig.h wcsconfig_f77.h wcsconfig_tests.h wcsconfig_utils.h"
-
-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_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5
-echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;;
-      esac
-      case $ac_var in #(
-      _ | IFS | as_nl) ;; #(
-      *) $as_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
-    test "x$cache_file" != "x/dev/null" &&
-      { echo "$as_me:$LINENO: updating cache $cache_file" >&5
-echo "$as_me: updating cache $cache_file" >&6;}
-    cat confcache >$cache_file
-  else
-    { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5
-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}'
-
-DEFS=-DHAVE_CONFIG_H
-
-ac_libobjs=
-ac_ltlibobjs=
-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=`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.
-  ac_libobjs="$ac_libobjs \${LIBOBJDIR}$ac_i\$U.$ac_objext"
-  ac_ltlibobjs="$ac_ltlibobjs \${LIBOBJDIR}$ac_i"'$U.lo'
-done
-LIBOBJS=$ac_libobjs
-
-LTLIBOBJS=$ac_ltlibobjs
-
-
-
-: ${CONFIG_STATUS=./config.status}
-ac_clean_files_save=$ac_clean_files
-ac_clean_files="$ac_clean_files $CONFIG_STATUS"
-{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
-echo "$as_me: creating $CONFIG_STATUS" >&6;}
-cat >$CONFIG_STATUS <<_ACEOF
-#! $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}
-_ACEOF
-
-cat >>$CONFIG_STATUS <<\_ACEOF
-## --------------------- ##
-## 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=:
-  # Zsh 3.x and 4.x performs 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
-
-
-
-
-# PATH needs CR
-# 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
-
-# The user is always right.
-if test "${PATH_SEPARATOR+set}" != set; then
-  echo "#! /bin/sh" >conf$$.sh
-  echo  "exit 0"   >>conf$$.sh
-  chmod +x conf$$.sh
-  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
-    PATH_SEPARATOR=';'
-  else
-    PATH_SEPARATOR=:
-  fi
-  rm -f conf$$.sh
-fi
-
-# Support unset when possible.
-if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
-  as_unset=unset
-else
-  as_unset=false
-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.)
-as_nl='
-'
-IFS=" ""	$as_nl"
-
-# Find who we are.  Look in the path if we contain no directory separator.
-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
-  echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
-  { (exit 1); exit 1; }
-fi
-
-# Work around bugs in pre-3.0 UWIN ksh.
-for as_var in ENV MAIL MAILPATH
-do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
-done
-PS1='$ '
-PS2='> '
-PS4='+ '
-
-# NLS nuisances.
-for as_var in \
-  LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
-  LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
-  LC_TELEPHONE LC_TIME
-do
-  if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
-    eval $as_var=C; export $as_var
-  else
-    ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
-  fi
-done
-
-# Required to use basename.
-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
-
-
-# Name of the executable.
-as_me=`$as_basename -- "$0" ||
-$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
-	 X"$0" : 'X\(//\)$' \| \
-	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
-echo X/"$0" |
-    sed '/^.*\/\([^/][^/]*\)\/*$/{
-	    s//\1/
-	    q
-	  }
-	  /^X\/\(\/\/\)$/{
-	    s//\1/
-	    q
-	  }
-	  /^X\/\(\/\).*/{
-	    s//\1/
-	    q
-	  }
-	  s/.*/./; q'`
-
-# CDPATH.
-$as_unset CDPATH
-
-
-
-  as_lineno_1=$LINENO
-  as_lineno_2=$LINENO
-  test "x$as_lineno_1" != "x$as_lineno_2" &&
-  test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
-
-  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
-  # uniformly replaced by the line number.  The first 'sed' inserts a
-  # line-number line after each line using $LINENO; the second 'sed'
-  # does the real work.  The second script uses 'N' to pair each
-  # line-number line with the line containing $LINENO, and appends
-  # trailing '-' during substitution so that $LINENO is not a special
-  # case at line end.
-  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
-  # scripts with optimization help from Paolo Bonzini.  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" ||
-    { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
-   { (exit 1); exit 1; }; }
-
-  # 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
-}
-
-
-if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
-  as_dirname=dirname
-else
-  as_dirname=false
-fi
-
-ECHO_C= ECHO_N= ECHO_T=
-case `echo -n x` in
--n*)
-  case `echo 'x\c'` in
-  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
-  *)   ECHO_C='\c';;
-  esac;;
-*)
-  ECHO_N='-n';;
-esac
-
-if expr a : '\(a\)' >/dev/null 2>&1 &&
-   test "X`expr 00001 : '.*\(...\)'`" = X001; then
-  as_expr=expr
-else
-  as_expr=false
-fi
-
-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
-fi
-echo >conf$$.file
-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 -p'.
-  ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
-    as_ln_s='cp -p'
-elif ln conf$$.file conf$$ 2>/dev/null; then
-  as_ln_s=ln
-else
-  as_ln_s='cp -p'
-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=:
-else
-  test -d ./-p && rmdir ./-p
-  as_mkdir_p=false
-fi
-
-if test -x / >/dev/null 2>&1; then
-  as_test_x='test -x'
-else
-  if ls -dL / >/dev/null 2>&1; then
-    as_ls_L_option=L
-  else
-    as_ls_L_option=
-  fi
-  as_test_x='
-    eval sh -c '\''
-      if test -d "$1"; then
-        test -d "$1/.";
-      else
-	case $1 in
-        -*)set "./$1";;
-	esac;
-	case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in
-	???[sx]*):;;*)false;;esac;fi
-    '\'' sh
-  '
-fi
-as_executable_p=$as_test_x
-
-# 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
-
-# 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 WCSLIB $as_me 4.10, which was
-generated by GNU Autoconf 2.61.  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
-
-cat >>$CONFIG_STATUS <<_ACEOF
-# Files that config.status was made for.
-config_files="$ac_config_files"
-config_headers="$ac_config_headers"
-
-_ACEOF
-
-cat >>$CONFIG_STATUS <<\_ACEOF
-ac_cs_usage="\
-\`$as_me' instantiates files from templates according to the
-current configuration.
-
-Usage: $0 [OPTIONS] [FILE]...
-
-  -h, --help       print this help, then exit
-  -V, --version    print version number and configuration settings, then exit
-  -q, --quiet      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
-  --header=FILE[:TEMPLATE]
-		   instantiate the configuration header FILE
-
-Configuration files:
-$config_files
-
-Configuration headers:
-$config_headers
-
-Report bugs to <bug-autoconf at gnu.org>."
-
-_ACEOF
-cat >>$CONFIG_STATUS <<_ACEOF
-ac_cs_version="\\
-WCSLIB config.status 4.10
-configured by $0, generated by GNU Autoconf 2.61,
-  with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
-
-Copyright (C) 2006 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'
-INSTALL='$INSTALL'
-_ACEOF
-
-cat >>$CONFIG_STATUS <<\_ACEOF
-# If no file are specified by the user, then we need to provide default
-# value.  By we need to know if files were specified by the user.
-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=$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 )
-    echo "$ac_cs_version"; exit ;;
-  --debug | --debu | --deb | --de | --d | -d )
-    debug=: ;;
-  --file | --fil | --fi | --f )
-    $ac_shift
-    CONFIG_FILES="$CONFIG_FILES $ac_optarg"
-    ac_need_defaults=false;;
-  --header | --heade | --head | --hea )
-    $ac_shift
-    CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
-    ac_need_defaults=false;;
-  --he | --h)
-    # Conflict between --help and --header
-    { echo "$as_me: error: ambiguous option: $1
-Try \`$0 --help' for more information." >&2
-   { (exit 1); exit 1; }; };;
-  --help | --hel | -h )
-    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.
-  -*) { echo "$as_me: error: unrecognized option: $1
-Try \`$0 --help' for more information." >&2
-   { (exit 1); exit 1; }; } ;;
-
-  *) ac_config_targets="$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
-if \$ac_cs_recheck; then
-  echo "running CONFIG_SHELL=$SHELL $SHELL $0 "$ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
-  CONFIG_SHELL=$SHELL
-  export CONFIG_SHELL
-  exec $SHELL "$0"$ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
-fi
-
-_ACEOF
-cat >>$CONFIG_STATUS <<\_ACEOF
-exec 5>>config.log
-{
-  echo
-  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
-## Running $as_me. ##
-_ASBOX
-  echo "$ac_log"
-} >&5
-
-_ACEOF
-cat >>$CONFIG_STATUS <<_ACEOF
-_ACEOF
-
-cat >>$CONFIG_STATUS <<\_ACEOF
-
-# Handling of arguments.
-for ac_config_target in $ac_config_targets
-do
-  case $ac_config_target in
-    "makedefs") CONFIG_FILES="$CONFIG_FILES makedefs" ;;
-    "wcslib.pc") CONFIG_FILES="$CONFIG_FILES wcslib.pc" ;;
-    "wcsconfig.h") CONFIG_HEADERS="$CONFIG_HEADERS wcsconfig.h" ;;
-    "wcsconfig_f77.h") CONFIG_HEADERS="$CONFIG_HEADERS wcsconfig_f77.h" ;;
-    "wcsconfig_tests.h") CONFIG_HEADERS="$CONFIG_HEADERS wcsconfig_tests.h" ;;
-    "wcsconfig_utils.h") CONFIG_HEADERS="$CONFIG_HEADERS wcsconfig_utils.h" ;;
-
-  *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
-echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
-   { (exit 1); exit 1; }; };;
-  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
-  test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
-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=
-  trap 'exit_status=$?
-  { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status
-' 0
-  trap '{ (exit 1); exit 1; }' 1 2 13 15
-}
-# Create a (secure) tmp directory for tmp files.
-
-{
-  tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
-  test -n "$tmp" && test -d "$tmp"
-}  ||
-{
-  tmp=./conf$$-$RANDOM
-  (umask 077 && mkdir "$tmp")
-} ||
-{
-   echo "$me: cannot create a temporary directory in ." >&2
-   { (exit 1); exit 1; }
-}
-
-#
-# Set up the sed scripts for CONFIG_FILES section.
-#
-
-# No need to generate the scripts if there are no CONFIG_FILES.
-# This happens for instance when ./config.status config.h
-if test -n "$CONFIG_FILES"; then
-
-_ACEOF
-
-
-
-ac_delim='%!_!# '
-for ac_last_try in false false false false false :; do
-  cat >conf$$subs.sed <<_ACEOF
-SHELL!$SHELL$ac_delim
-PATH_SEPARATOR!$PATH_SEPARATOR$ac_delim
-PACKAGE_NAME!$PACKAGE_NAME$ac_delim
-PACKAGE_TARNAME!$PACKAGE_TARNAME$ac_delim
-PACKAGE_VERSION!$PACKAGE_VERSION$ac_delim
-PACKAGE_STRING!$PACKAGE_STRING$ac_delim
-PACKAGE_BUGREPORT!$PACKAGE_BUGREPORT$ac_delim
-exec_prefix!$exec_prefix$ac_delim
-prefix!$prefix$ac_delim
-program_transform_name!$program_transform_name$ac_delim
-bindir!$bindir$ac_delim
-sbindir!$sbindir$ac_delim
-libexecdir!$libexecdir$ac_delim
-datarootdir!$datarootdir$ac_delim
-datadir!$datadir$ac_delim
-sysconfdir!$sysconfdir$ac_delim
-sharedstatedir!$sharedstatedir$ac_delim
-localstatedir!$localstatedir$ac_delim
-includedir!$includedir$ac_delim
-oldincludedir!$oldincludedir$ac_delim
-docdir!$docdir$ac_delim
-infodir!$infodir$ac_delim
-htmldir!$htmldir$ac_delim
-dvidir!$dvidir$ac_delim
-pdfdir!$pdfdir$ac_delim
-psdir!$psdir$ac_delim
-libdir!$libdir$ac_delim
-localedir!$localedir$ac_delim
-mandir!$mandir$ac_delim
-DEFS!$DEFS$ac_delim
-ECHO_C!$ECHO_C$ac_delim
-ECHO_N!$ECHO_N$ac_delim
-ECHO_T!$ECHO_T$ac_delim
-LIBS!$LIBS$ac_delim
-build_alias!$build_alias$ac_delim
-host_alias!$host_alias$ac_delim
-target_alias!$target_alias$ac_delim
-LIBVER!$LIBVER$ac_delim
-build!$build$ac_delim
-build_cpu!$build_cpu$ac_delim
-build_vendor!$build_vendor$ac_delim
-build_os!$build_os$ac_delim
-ARCH!$ARCH$ac_delim
-FLEX!$FLEX$ac_delim
-CC!$CC$ac_delim
-CFLAGS!$CFLAGS$ac_delim
-LDFLAGS!$LDFLAGS$ac_delim
-CPPFLAGS!$CPPFLAGS$ac_delim
-ac_ct_CC!$ac_ct_CC$ac_delim
-EXEEXT!$EXEEXT$ac_delim
-OBJEXT!$OBJEXT$ac_delim
-CPP!$CPP$ac_delim
-GREP!$GREP$ac_delim
-EGREP!$EGREP$ac_delim
-LIBOBJS!$LIBOBJS$ac_delim
-F77!$F77$ac_delim
-FFLAGS!$FFLAGS$ac_delim
-ac_ct_F77!$ac_ct_F77$ac_delim
-FLIBS!$FLIBS$ac_delim
-RANLIB!$RANLIB$ac_delim
-SHRLIB!$SHRLIB$ac_delim
-SONAME!$SONAME$ac_delim
-SHRFLAGS!$SHRFLAGS$ac_delim
-SHRLD!$SHRLD$ac_delim
-SHRSFX!$SHRSFX$ac_delim
-SHRLN!$SHRLN$ac_delim
-LN_S!$LN_S$ac_delim
-INSTALL_PROGRAM!$INSTALL_PROGRAM$ac_delim
-INSTALL_SCRIPT!$INSTALL_SCRIPT$ac_delim
-INSTALL_DATA!$INSTALL_DATA$ac_delim
-XMKMF!$XMKMF$ac_delim
-CFITSIOINC!$CFITSIOINC$ac_delim
-CFITSIOLIB!$CFITSIOLIB$ac_delim
-GETWCSTAB!$GETWCSTAB$ac_delim
-PGPLOTINC!$PGPLOTINC$ac_delim
-PGPLOTLIB!$PGPLOTLIB$ac_delim
-SUBDIRS!$SUBDIRS$ac_delim
-TSTDIRS!$TSTDIRS$ac_delim
-INSTDIR!$INSTDIR$ac_delim
-LTLIBOBJS!$LTLIBOBJS$ac_delim
-_ACEOF
-
-  if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 80; then
-    break
-  elif $ac_last_try; then
-    { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
-echo "$as_me: error: could not make $CONFIG_STATUS" >&2;}
-   { (exit 1); exit 1; }; }
-  else
-    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
-  fi
-done
-
-ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed`
-if test -n "$ac_eof"; then
-  ac_eof=`echo "$ac_eof" | sort -nru | sed 1q`
-  ac_eof=`expr $ac_eof + 1`
-fi
-
-cat >>$CONFIG_STATUS <<_ACEOF
-cat >"\$tmp/subs-1.sed" <<\CEOF$ac_eof
-/@[a-zA-Z_][a-zA-Z_0-9]*@/!b end
-_ACEOF
-sed '
-s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g
-s/^/s,@/; s/!/@,|#_!!_#|/
-:n
-t n
-s/'"$ac_delim"'$/,g/; t
-s/$/\\/; p
-N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n
-' >>$CONFIG_STATUS <conf$$subs.sed
-rm -f conf$$subs.sed
-cat >>$CONFIG_STATUS <<_ACEOF
-:end
-s/|#_!!_#|//g
-CEOF$ac_eof
-_ACEOF
-
-
-# VPATH may cause trouble with some makes, so we remove $(srcdir),
-# ${srcdir} and @srcdir@ 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[	 ]*=/{
-s/:*\$(srcdir):*/:/
-s/:*\${srcdir}:*/:/
-s/:*@srcdir@:*/:/
-s/^\([^=]*=[	 ]*\):*/\1/
-s/:*$//
-s/^[^=]*=[	 ]*$//
-}'
-fi
-
-cat >>$CONFIG_STATUS <<\_ACEOF
-fi # test -n "$CONFIG_FILES"
-
-
-for ac_tag in  :F $CONFIG_FILES  :H $CONFIG_HEADERS
-do
-  case $ac_tag in
-  :[FHLC]) ac_mode=$ac_tag; continue;;
-  esac
-  case $ac_mode$ac_tag in
-  :[FHL]*:*);;
-  :L* | :C*:*) { { echo "$as_me:$LINENO: error: Invalid tag $ac_tag." >&5
-echo "$as_me: error: Invalid tag $ac_tag." >&2;}
-   { (exit 1); exit 1; }; };;
-  :[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="$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 ||
-	   { { echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5
-echo "$as_me: error: cannot find input file: $ac_f" >&2;}
-   { (exit 1); exit 1; }; };;
-      esac
-      ac_file_inputs="$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 "`IFS=:
-	  echo $* | sed 's|^[^:]*/||;s|:[^:]*/|, |g'`" by configure."
-    if test x"$ac_file" != x-; then
-      configure_input="$ac_file.  $configure_input"
-      { echo "$as_me:$LINENO: creating $ac_file" >&5
-echo "$as_me: creating $ac_file" >&6;}
-    fi
-
-    case $ac_tag in
-    *:-:* | *:-) cat >"$tmp/stdin";;
-    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 ||
-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"
-  case $as_dir in #(
-  -*) as_dir=./$as_dir;;
-  esac
-  test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || {
-    as_dirs=
-    while :; do
-      case $as_dir in #(
-      *\'*) as_qdir=`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 ||
-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" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5
-echo "$as_me: error: cannot create directory $as_dir" >&2;}
-   { (exit 1); exit 1; }; }; }
-  ac_builddir=.
-
-case "$ac_dir" in
-.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
-*)
-  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
-  # A ".." for each directory in $ac_dir_suffix.
-  ac_top_builddir_sub=`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
-  #
-
-  case $INSTALL in
-  [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
-  *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
-  esac
-_ACEOF
-
-cat >>$CONFIG_STATUS <<\_ACEOF
-# 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=
-
-case `sed -n '/datarootdir/ {
-  p
-  q
-}
-/@datadir@/p
-/@docdir@/p
-/@infodir@/p
-/@localedir@/p
-/@mandir@/p
-' $ac_file_inputs` in
-*datarootdir*) ac_datarootdir_seen=yes;;
-*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
-  { echo "$as_me:$LINENO: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
-echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
-_ACEOF
-cat >>$CONFIG_STATUS <<_ACEOF
-  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
-  sed "$ac_vpsub
-$extrasub
-_ACEOF
-cat >>$CONFIG_STATUS <<\_ACEOF
-:t
-/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
-s&@configure_input@&$configure_input&;t t
-s&@top_builddir@&$ac_top_builddir_sub&;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
-s&@INSTALL@&$ac_INSTALL&;t t
-$ac_datarootdir_hack
-" $ac_file_inputs | sed -f "$tmp/subs-1.sed" >$tmp/out
-
-test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
-  { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } &&
-  { ac_out=`sed -n '/^[	 ]*datarootdir[	 ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } &&
-  { echo "$as_me:$LINENO: WARNING: $ac_file contains a reference to the variable \`datarootdir'
-which seems to be undefined.  Please make sure it is defined." >&5
-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 "$tmp/stdin"
-  case $ac_file in
-  -) cat "$tmp/out"; rm -f "$tmp/out";;
-  *) rm -f "$ac_file"; mv "$tmp/out" $ac_file;;
-  esac
- ;;
-  :H)
-  #
-  # CONFIG_HEADER
-  #
-_ACEOF
-
-# Transform confdefs.h into a sed script `conftest.defines', that
-# substitutes the proper values into config.h.in to produce config.h.
-rm -f conftest.defines conftest.tail
-# First, append a space to every undef/define line, to ease matching.
-echo 's/$/ /' >conftest.defines
-# Then, protect against being on the right side of a sed subst, or in
-# an unquoted here document, in config.status.  If some macros were
-# called several times there might be several #defines for the same
-# symbol, which is useless.  But do not sort them, since the last
-# AC_DEFINE must be honored.
-ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
-# These sed commands are passed to sed as "A NAME B PARAMS C VALUE D", where
-# NAME is the cpp macro being defined, VALUE is the value it is being given.
-# PARAMS is the parameter list in the macro definition--in most cases, it's
-# just an empty string.
-ac_dA='s,^\\([	 #]*\\)[^	 ]*\\([	 ]*'
-ac_dB='\\)[	 (].*,\\1define\\2'
-ac_dC=' '
-ac_dD=' ,'
-
-uniq confdefs.h |
-  sed -n '
-	t rset
-	:rset
-	s/^[	 ]*#[	 ]*define[	 ][	 ]*//
-	t ok
-	d
-	:ok
-	s/[\\&,]/\\&/g
-	s/^\('"$ac_word_re"'\)\(([^()]*)\)[	 ]*\(.*\)/ '"$ac_dA"'\1'"$ac_dB"'\2'"${ac_dC}"'\3'"$ac_dD"'/p
-	s/^\('"$ac_word_re"'\)[	 ]*\(.*\)/'"$ac_dA"'\1'"$ac_dB$ac_dC"'\2'"$ac_dD"'/p
-  ' >>conftest.defines
-
-# Remove the space that was appended to ease matching.
-# Then replace #undef with comments.  This is necessary, for
-# example, in the case of _POSIX_SOURCE, which is predefined and required
-# on some systems where configure will not decide to define it.
-# (The regexp can be short, since the line contains either #define or #undef.)
-echo 's/ $//
-s,^[	 #]*u.*,/* & */,' >>conftest.defines
-
-# Break up conftest.defines:
-ac_max_sed_lines=50
-
-# First sed command is:	 sed -f defines.sed $ac_file_inputs >"$tmp/out1"
-# Second one is:	 sed -f defines.sed "$tmp/out1" >"$tmp/out2"
-# Third one will be:	 sed -f defines.sed "$tmp/out2" >"$tmp/out1"
-# et cetera.
-ac_in='$ac_file_inputs'
-ac_out='"$tmp/out1"'
-ac_nxt='"$tmp/out2"'
-
-while :
-do
-  # Write a here document:
-    cat >>$CONFIG_STATUS <<_ACEOF
-    # First, check the format of the line:
-    cat >"\$tmp/defines.sed" <<\\CEOF
-/^[	 ]*#[	 ]*undef[	 ][	 ]*$ac_word_re[	 ]*\$/b def
-/^[	 ]*#[	 ]*define[	 ][	 ]*$ac_word_re[(	 ]/b def
-b
-:def
-_ACEOF
-  sed ${ac_max_sed_lines}q conftest.defines >>$CONFIG_STATUS
-  echo 'CEOF
-    sed -f "$tmp/defines.sed"' "$ac_in >$ac_out" >>$CONFIG_STATUS
-  ac_in=$ac_out; ac_out=$ac_nxt; ac_nxt=$ac_in
-  sed 1,${ac_max_sed_lines}d conftest.defines >conftest.tail
-  grep . conftest.tail >/dev/null || break
-  rm -f conftest.defines
-  mv conftest.tail conftest.defines
-done
-rm -f conftest.defines conftest.tail
-
-echo "ac_result=$ac_in" >>$CONFIG_STATUS
-cat >>$CONFIG_STATUS <<\_ACEOF
-  if test x"$ac_file" != x-; then
-    echo "/* $configure_input  */" >"$tmp/config.h"
-    cat "$ac_result" >>"$tmp/config.h"
-    if diff $ac_file "$tmp/config.h" >/dev/null 2>&1; then
-      { echo "$as_me:$LINENO: $ac_file is unchanged" >&5
-echo "$as_me: $ac_file is unchanged" >&6;}
-    else
-      rm -f $ac_file
-      mv "$tmp/config.h" $ac_file
-    fi
-  else
-    echo "/* $configure_input  */"
-    cat "$ac_result"
-  fi
-  rm -f "$tmp/out12"
- ;;
-
-
-  esac
-
-done # for ac_tag
-
-
-{ (exit 0); exit 0; }
-_ACEOF
-chmod +x $CONFIG_STATUS
-ac_clean_files=$ac_clean_files_save
-
-
-# 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 || { (exit 1); exit 1; }
-fi
-
diff --git a/astropy/wcs/src/wcslib/configure.ac b/astropy/wcs/src/wcslib/configure.ac
deleted file mode 100644
index a9d2fd7..0000000
--- a/astropy/wcs/src/wcslib/configure.ac
+++ /dev/null
@@ -1,522 +0,0 @@
-#-----------------------------------------------------------------------------
-# Process this file with autoconf-2.53 or later to produce a configure script.
-#-----------------------------------------------------------------------------
-# N.B. it is necessary to run autoconf on a Mac in order for configure to
-# locate the X11 dylibs for PGPLOT.  Use autoconf-2.61 in MacOSX 10.6.2 or
-# later to avoid spurious messages about deleting conftest.dSYM when
-# configuring in MacOSX 10.6.
-#
-# Author: Mark Calabretta, Australia Telescope National Facility
-# http://www.atnf.csiro.au/~mcalabre/index.html
-# $Id: configure.ac,v 4.10 2012/02/05 23:41:45 cal103 Exp $
-#-----------------------------------------------------------------------------
-
-AC_INIT([WCSLIB], [4.10], [mcalabre at atnf.csiro.au], [wcslib-4.10])
-AC_PREREQ([2.53])
-AC_REVISION([$Revision: 4.10 $])
-AC_SUBST([PACKAGE_VERSION])
-AC_DEFINE_UNQUOTED([WCSLIB_VERSION], [$PACKAGE_VERSION], [Define wcslib version])
-
-# Library version number, same as package version.
-LIBVER="$PACKAGE_VERSION"
-AC_SUBST([LIBVER])
-
-AC_CONFIG_SRCDIR([C/wcs.h])
-AC_CONFIG_AUX_DIR([config])
-
-# Get the system type.
-AC_CANONICAL_BUILD
-ARCH="${build_cpu}-$build_os"
-AC_SUBST([ARCH])
-
-
-# Look for Flex.
-AC_CHECK_PROG([FLEX], [flex], [flex], [], [], [])
-if test "x$FLEX" = xflex ; then
-  # Version 2.5.9 or later is required.
-  V=`flex --version | awk '{print $NF}'`
-  W=`echo $V | awk -F. '{if ((($1*100 + $2)*100 + $3) < 20509) print "no"}'`
-  if test "x$W" != x ; then
-    AC_MSG_NOTICE([Flex version $V is too old, ignored.])
-    FLEX=
-  else
-    AC_MSG_NOTICE([Using Flex version $V.])
-  fi
-fi
-
-if test "x$FLEX" = x ; then
-  AC_MSG_WARN([Flex version 2.5.9 or later does not appear to be
-           available, will use pre-generated sources.])
-fi
-
-
-# Look for an ANSI C compiler.
-AC_PROG_CPP
-AC_PROG_CC
-AC_PROG_CC_STDC
-AC_C_CONST
-AC_TYPE_SIZE_T
-if test "x$ac_cv_prog_cc_stdc" = xno -o \
-        "x$ac_cv_c_const"      = xno -o \
-        "x$ac_cv_type_size_t"  = xno; then
-  AC_MSG_ERROR([
-    -------------------------------------------------------
-    An ANSI standard C library is required to build WCSLIB.
-
-    ERROR: WCSLIB configuration failure.
-    -------------------------------------------------------], [1])
-fi
-
-# Check for data types (suggested by autoscan - off_t is only required by
-# fitshdr).
-AC_TYPE_OFF_T
-AC_TYPE_INT8_T
-AC_TYPE_INT16_T
-AC_TYPE_INT32_T
-AC_TYPE_UINT8_T
-AC_TYPE_UINT16_T
-AC_TYPE_UINT32_T
-
-# Check for ANSI C headers.
-AC_HEADER_STDC
-AC_CHECK_HEADERS([ctype.h errno.h limits.h math.h setjmp.h stdarg.h stdio.h \
-                  stdlib.h string.h])
-if test "x$ac_cv_header_stdc" = xno; then
-  AC_MSG_ERROR([
-    -------------------------------------------------------------------
-    An ANSI standard C library is required to build WCSLIB.  One of the
-    ANSI C header files it requires is missing or unusable.
-
-    ERROR: WCSLIB configuration failure.
-    -------------------------------------------------------------------], [1])
-fi
-
-# Checks for ANSI C library functions (suggested by autoscan - fseeko and
-# stat are only required by fitshdr).
-AC_CHECK_LIB([m], [floor])
-AC_FUNC_FSEEKO
-AC_FUNC_MALLOC
-AC_FUNC_REALLOC
-AC_FUNC_SETVBUF_REVERSED
-AC_FUNC_STAT
-AC_FUNC_VPRINTF
-AC_CHECK_FUNCS([floor memset pow sqrt strchr strstr])
-
-# System libraries that may be required by WCSLIB itself.
-# SunOS, extra maths functions.
-AC_CHECK_LIB([sunmath], [cosd], [LIBS="-lsunmath $LIBS"], [], [])
-
-# See if we can find sincos().
-AC_CHECK_FUNCS([sincos])
-
-# Check the size and availability of integer data types.
-AC_CHECK_SIZEOF([int])
-AC_CHECK_SIZEOF([long int])
-AC_CHECK_SIZEOF([long long int])
-
-# 64-bit integer data type; use long long int preferentially since that
-# accords with "%lld" formatting used in fitshdr.l, e.g.
-#                int   size_t  long int  long long int
-#                ---   ------  --------  -------------
-#   gcc x86:      32     32       32          64
-#   gcc x86_64:   32     64       64          64
-if test "x$ac_cv_sizeof_long_long_int" = x8; then
-  AC_DEFINE([WCSLIB_INT64], [long long int], [64-bit integer data type.])
-elif test "x$ac_cv_sizeof_long_int" = x8; then
-  AC_DEFINE([WCSLIB_INT64], [long int], [64-bit integer data type.])
-elif test "x$ac_cv_sizeof_int" = x8; then
-  AC_DEFINE([WCSLIB_INT64], [int], [64-bit integer data type.])
-fi
-
-# Does printf() have the z modifier for size_t type?  Important for 64-bit.
-AC_MSG_CHECKING([for printf z format modifier for size_t type])
-AC_RUN_IFELSE(
-  [AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT],
-                   [[char buf[64];
-                     if (sprintf(buf, "%zu", (size_t)1) != 1)
-                       return 1;
-                     else if (strcmp(buf, "1"))
-                       return 2;]])],
-  AC_DEFINE([MODZ], ["z"], [printf format modifier for size_t type.])
-    AC_MSG_RESULT(yes),
-  AC_DEFINE([MODZ], [""],  [printf format modifier for size_t type.])
-    AC_MSG_RESULT(no),
-  AC_DEFINE([MODZ], [""],  [printf format modifier for size_t type.])
-    AC_MSG_RESULT(assumed not)
-)
-
-
-# Starting values, may be augmented later.
-SUBDIRS="C"
-TSTDIRS="C"
-INSTDIR="C"
-
-
-# Ways of specifying the Fortran compiler, in order of precedence:
-#   configure --enable-fortran=<compiler>
-#   F77=<compiler> configure    ...bash
-#
-# Ways of disabling Fortran:
-#   configure --disable-fortran
-#   configure --enable-fortran=no
-#   F77=no configure            ...bash
-AC_ARG_ENABLE([fortran], [AS_HELP_STRING([--enable-fortran=ARG],
-            [Fortran compiler to use])], [])
-AC_ARG_ENABLE([fortran], [AS_HELP_STRING([--disable-fortran],
-            [don't build the Fortran wrappers or PGSBOX])], [])
-if test "x$enable_fortran" != x -a "x$enable_fortran" != xyes ; then
-  F77="$enable_fortran"
-fi
-
-if test "x$F77" = xno ; then
-  F77=
-
-  AC_MSG_WARN([Compilation of Fortran wrappers and PGSBOX disabled])
-
-else
-  if test "x$F77" = x ; then
-    # Look for a Fortran compiler.
-    AC_PROG_F77([gfortran g77 f77 ifort xlf frt pgf77 fl32 af77 fort77 f90 \
-                 xlf90 pgf90 epcf90 f95 fort xlf95 lf95 g95])
-  fi
-
-  if test "x$F77" = x; then
-    AC_MSG_WARN([
-      ------------------------------------------------------------------
-      Fortran compiler not found, will skip Fortran wrappers and PGSBOX.
-      ------------------------------------------------------------------])
-
-    # Best guess at Fortran name mangling for use if a compiler does ever
-    # become available.
-    AC_DEFINE([F77_FUNC(name,NAME)], [name ## _])
-
-  else
-    if test "x$ac_cv_f77_compiler_gnu" = xyes ; then
-      if test "x$F77" = xg77 -o "x$F77" = xf77 ; then
-        # Not recognized by gfortran.
-        FFLAGS="$FFLAGS -Wno-globals"
-      fi
-    fi
-
-    AC_MSG_CHECKING(whether $F77 accepts -I)
-    AC_LANG_PUSH(Fortran 77)
-    FFLAGS_save=$FFLAGS
-    FFLAGS=-I.
-    AC_COMPILE_IFELSE(AC_LANG_PROGRAM([], []),
-      [FFLAGS="$FFLAGS_save -I."; AC_MSG_RESULT(yes)],
-      [FFLAGS="$FFLAGS_save"; AC_MSG_RESULT(no)])
-    AC_LANG_POP()
-
-    # Libraries required by the Fortran compiler itself (sets FLIBS).
-    # Required by utilities and test programs written in C that link to
-    # Fortran object modules such as pgsbox.
-    AC_F77_LIBRARY_LDFLAGS
-
-    # F77 name mangling (defines the F77_FUNC preprocessor macro).
-    AC_F77_WRAPPERS
-
-    SUBDIRS="C Fortran"
-    TSTDIRS="C Fortran"
-    INSTDIR="Fortran"
-  fi
-fi
-
-
-# System-dependent system libraries (for building the sharable library).
-#-----------------------------------------------------------------------
-# Darwin (contains stubs for long double).
-AC_CHECK_LIB([SystemStubs], [printf\$LDBLStub], [LIBS="$LIBS -lSystemStubs"],
-             [], [])
-
-
-# Library and installation utilities.
-#------------------------------------
-# Static library generation.
-AC_PROG_RANLIB
-
-# Shared library generation.
-if test "x$ac_cv_c_compiler_gnu" = xyes ; then
-  SHVER=`echo "$LIBVER" | sed -e 's/\..*$//'`
-
-  # Note that -fPIC is on by default for Macs, this just makes it obvious.
-  SHRFLAGS="-fPIC"
-  SHRLD="\$(CC) \$(SHRFLAGS)"
-
-  case "$build_os" in
-  darwin*)
-    SHRLIB="libwcs.$LIBVER.dylib"
-    SONAME="libwcs.$SHVER.dylib"
-    SHRLD="$SHRLD -dynamiclib -single_module"
-    SHRLD="$SHRLD -compatibility_version $SHVER -current_version $LIBVER"
-    SHRLN=
-
-    case "$build_cpu" in
-    powerpc*)
-      # Switch off -fPIC (not applicable for PowerPC Macs).
-      CFLAGS="$CFLAGS -mdynamic-no-pic"
-      ;;
-    esac
-    ;;
-  *)
-    # Covers Linux and Solaris at least.
-    SHRLIB="libwcs.so.$LIBVER"
-    SONAME="libwcs.so.$SHVER"
-    SHRLD="$SHRLD -shared -Wl,-h\$(SONAME) -lm"
-    SHRLN="libwcs.so"
-    ;;
-  esac
-
-else
-  SHRLIB=
-  SONAME=
-  SHRFLAGS=
-  SHRLD=
-  SHRSFX=
-  SHRLN=
-fi
-
-AC_SUBST([SHRLIB])
-AC_SUBST([SONAME])
-AC_SUBST([SHRFLAGS])
-AC_SUBST([SHRLD])
-AC_SUBST([SHRSFX])
-AC_SUBST([SHRLN])
-
-# Installation utilities.
-AC_PROG_LN_S
-AC_PROG_INSTALL
-
-AC_MSG_NOTICE([End of primary configuration.
-])
-
-
-# The following are required to build utilities and test programs.
-# ----------------------------------------------------------------
-AC_MSG_NOTICE([Looking for libraries etc. for utilities and test suite...])
-
-# Check for other quasi-standard header files.
-AC_CHECK_HEADERS([unistd.h])
-
-# Large file support.
-AC_FUNC_FSEEKO
-AC_SYS_LARGEFILE
-
-
-# Extra places to look for third-party libraries and header files.
-LIBDIRS=
-
-AC_ARG_WITH([cfitsio], [AS_HELP_STRING([--without-cfitsio],
-            [eschew CFITSIO])], [])
-if test "x$with_cfitsio" = xno ; then
-  AC_MSG_WARN([CFITSIO disabled])
-else
-  AC_ARG_WITH([cfitsiolib], [AS_HELP_STRING([--with-cfitsiolib=DIR],
-              [directory containing cfitsio library])], [])
-  if test "x$with_cfitsiolib" != x ; then
-    LIBDIRS="$LIBDIRS $with_cfitsiolib"
-  fi
-
-  AC_ARG_WITH([cfitsioinc], [AS_HELP_STRING([--with-cfitsioinc=DIR],
-              [directory containing cfitsio header files])], [])
-  if test "x$with_cfitsioinc" != x ; then
-    CFITSIO_INCDIRS="$with_cfitsioinc"
-  fi
-
-  CFITSIO_INCDIRS="$CFITSIO_INCDIRS   \
-           /usr/local/cfitsio/include \
-           /local/cfitsio/include"
-
-  LIBDIRS="$LIBDIRS           \
-           /usr/local/cfitsio/lib \
-           /local/cfitsio/lib"
-fi
-
-AC_ARG_WITH([pgplot], [AS_HELP_STRING([--without-pgplot],
-            [eschew PGPLOT])], [])
-if test "x$with_pgplot" = xno ; then
-  AC_MSG_WARN([PGPLOT disabled])
-else
-  AC_ARG_WITH([pgplotlib], [AS_HELP_STRING([--with-pgplotlib=DIR],
-              [directory containing pgplot library])], [])
-  if test "x$with_pgplotlib" != x ; then
-    LIBDIRS="$LIBDIRS $with_pgplotlib"
-  fi
-
-  AC_ARG_WITH([pgplotinc], [AS_HELP_STRING([--with-pgplotinc=DIR],
-              [directory containing pgplot header files])], [])
-  if test "x$with_pgplotinc" != x ; then
-    PGPLOT_INCDIRS="$with_pgplotinc"
-  fi
-
-  PGPLOT_INCDIRS="$PGPLOT_INCDIRS    \
-           /usr/local/pgplot/include \
-           /local/pgplot/include"
-
-  LIBDIRS="$LIBDIRS           \
-           /usr/local/pgplot/lib  \
-           /local/pgplot/lib"
-fi
-
-
-if test "x$with_cfitsio" != xno -o \
-        "x$with_pgplot"  != xno ; then
-  LIBDIRS="$LIBDIRS           \
-           /usr/local/lib     \
-           /local/lib         \
-           /opt/local/lib     \
-           /opt/SUNWspro/lib  \
-           /sw/lib"
-
-  for LIBDIR in $LIBDIRS ; do
-    AC_CHECK_FILE([$LIBDIR], [LDFLAGS="$LDFLAGS -L$LIBDIR"], [continue])
-  done
-
-  # Generic include directories.
-  INCDIRS="/usr/local/include \
-           /local/include     \
-           /opt/local/include \
-           /sw/include        \
-           /local             \
-           /usr/include"
-
-
-  # CFITSIO.
-  if test "x$with_cfitsio" != xno ; then
-    # Search for CFITSIO.
-    for INCDIR in $CFITSIO_INCDIRS $INCDIRS ; do
-      AC_CHECK_FILE([$INCDIR/cfitsio/fitsio.h],
-                    [CFITSIOINC="-I$INCDIR/cfitsio"; break])
-      AC_CHECK_FILE([$INCDIR/fitsio.h], [CFITSIOINC="-I$INCDIR"; break])
-    done
-
-    AC_CHECK_LIB([socket],  [recv],   [CFITSIOLIB="-lsocket"], [], [$LIBS])
-    AC_CHECK_LIB([cfitsio], [ffopen], [CFITSIOLIB="-lcfitsio $CFITSIOLIB"], [],
-                 [$CFITSIOLIB $LIBS])
-
-    if test "x$CFITSIOINC" = x -o "x$CFITSIOLIB" = x; then
-      AC_MSG_WARN([CFITSIO not found, skipping CFITSIO-dependent tests.])
-    else
-      AC_MSG_NOTICE([CFITSIO appears to be available.])
-      AC_DEFINE([HAVE_CFITSIO], [1], [Define to 1 if CFITSIO is available.])
-
-      # Check for fits_read_wcstab, present in CFITSIO 3.004beta and later.
-      AC_CHECK_LIB([cfitsio], [fits_read_wcstab], [GETWCSTAB=],
-                   [GETWCSTAB=getwcstab.o], [$CFITSIOLIB $LIBS])
-      if test "x$GETWCSTAB" != x ; then
-        AC_MSG_WARN([fits_read_wcstab not found in CFITSIO, will use
-                        getwcstab.c to compile test programs.])
-      fi
-    fi
-  fi
-
-  # PGPLOT.
-  if test "x$F77" != x -a "x$with_pgplot" != xno ; then
-    # Search for PGPLOT.
-    for INCDIR in $PGPLOT_INCDIRS $INCDIRS ; do
-      AC_CHECK_FILE([$INCDIR/pgplot/cpgplot.h],
-                    [PGPLOTINC="-I$INCDIR/pgplot"; break])
-      AC_CHECK_FILE([$INCDIR/cpgplot.h], [PGPLOTINC="-I$INCDIR"; break])
-    done
-
-    # FLIBS (found above via AC_F77_LIBRARY_LDFLAGS) only helps if PGPLOT was
-    # built using the same Fortran compiler that we are using here.
-
-    # PGPLOT compiled by the SUN Fortran compiler but linked with something
-    # else.
-    AC_CHECK_LIB([M77],     [iand_],     [PGPLOTLIB="-lM77 $PGPLOTLIB"],
-                 [], [$PGPLOTLIB $LIBS])
-    AC_CHECK_LIB([F77],     [f77_init],  [PGPLOTLIB="-lF77 $PGPLOTLIB"],
-                 [], [$PGPLOTLIB $LIBS])
-
-    if test "x$F77" != xg77; then
-      # For PGPLOT compiled with g77 but linked with something else.
-      AC_CHECK_LIB([frtbegin], [main],     [PGPLOTLIB="-lfrtbegin $PGPLOTLIB"],
-                   [], [$PGPLOTLIB $LIBS])
-      AC_CHECK_LIB([g2c],      [gerror_],  [PGPLOTLIB="-lg2c $PGPLOTLIB"],
-                   [], [$PGPLOTLIB $LIBS])
-    fi
-
-    if test "x$F77" != xgfortran; then
-      # For PGPLOT compiled with gfortran but linked with something else.
-      # Note that if gfortran itself is driving the linker it can be harmful
-      # to add -lgfortran to the link list without also adding -lgfortranbegin.
-      # Doing so stops gfortran from adding -lgfortranbegin which is needed to
-      # resolve "main".
-      AC_CHECK_LIB([gfortran], [_gfortran_abort],
-                   [PGPLOTLIB="-lgfortran $PGPLOTLIB"], [],
-                   [$PGPLOTLIB $LIBS])
-    fi
-
-    # Search for X11 includes and libraries.
-    AC_PATH_X
-    if test "x$no_x" = x; then
-      if test "x$ac_x_libraries" != x ; then
-        # Not needed for systems that keep the X11 libraries in /usr/lib.
-        LDFLAGS="$LDFLAGS -L$ac_x_libraries"
-      fi
-      PGPLOTLIB="-lX11 $PGPLOTLIB"
-    fi
-
-    # It is possible that other libraries may be required depending on what
-    # graphics drivers were installed with PGPLOT.
-    AC_CHECK_LIB([z],       [deflate],   [PGPLOTLIB="-lz $PGPLOTLIB"],
-                 [], [$PGPLOTLIB $LIBS])
-    AC_CHECK_LIB([png],     [png_error], [PGPLOTLIB="-lpng $PGPLOTLIB"],
-                 [], [$PGPLOTLIB $LIBS])
-    AC_CHECK_LIB([pgplot],  [pgbeg_],    [PGPLOTLIB="-lpgplot $PGPLOTLIB"],
-                 [], [$PGPLOTLIB $FLIBS $LIBS])
-    AC_CHECK_LIB([cpgplot], [cpgbeg],    [PGPLOTLIB="-lcpgplot $PGPLOTLIB"],
-                 [PGPLOTLIB=], [$PGPLOTLIB $FLIBS $LIBS])
-
-    # Only need the PGPLOT include file to build PGSBOX.
-    if test "x$PGPLOTINC" != x; then
-      SUBDIRS="$SUBDIRS pgsbox"
-      INSTDIR="pgsbox"
-    fi
-
-    # Also need the PGPLOT library to build pgtest and cpgtest.
-    if test "x$PGPLOTLIB" = x; then
-      AC_MSG_WARN([PGPLOT not found, skipping PGPLOT-dependent tests.])
-    else
-      AC_MSG_NOTICE([PGPLOT appears to be available.])
-
-      TSTDIRS="$TSTDIRS pgsbox"
-    fi
-  fi
-fi
-
-
-# Utilities are compiled last since they need the libraries.
-# Ways of disabling them:
-#   configure --disable-utils
-#   configure --enable-utils=no
-AC_ARG_ENABLE([utils], [AS_HELP_STRING([--disable-utils],
-            [don't build the WCS utilities])], [])
-if test "x$enable_utils" != xno ; then
-  SUBDIRS="$SUBDIRS utils"
-  INSTDIR="$INSTDIR utils"
-else
-  AC_MSG_WARN([Compilation of WCS utilities disabled])
-fi
-
-
-AC_SUBST([CFITSIOINC])
-AC_SUBST([CFITSIOLIB])
-AC_SUBST([GETWCSTAB])
-
-AC_SUBST([PGPLOTINC])
-AC_SUBST([PGPLOTLIB])
-
-AC_SUBST([SUBDIRS])
-AC_SUBST([TSTDIRS])
-AC_SUBST([INSTDIR])
-
-AC_MSG_NOTICE([End of auxiliary configuration.
-])
-
-
-# Do it.
-AC_MSG_NOTICE([Configuring files...])
-AC_CONFIG_FILES([makedefs wcslib.pc])
-AC_CONFIG_HEADERS([wcsconfig.h wcsconfig_f77.h wcsconfig_tests.h wcsconfig_utils.h])
-AC_OUTPUT
diff --git a/astropy/wcs/src/wcslib/flavours b/astropy/wcs/src/wcslib/flavours
deleted file mode 100644
index 723045c..0000000
--- a/astropy/wcs/src/wcslib/flavours
+++ /dev/null
@@ -1,160 +0,0 @@
-#-----------------------------------------------------------------------------
-# Makefile overrides for various combinations of architecture, operating
-# system and compiler.  Used for development and testing only, not required
-# for building WCSLIB.
-#
-# Variables like CC and CFLAGS are exported into the environment so that they
-# will be seen by 'configure'.  Thus, normal usage is as follows:
-#
-#   make distclean
-#   make FLAVOUR=Linux configure
-#   make
-#
-# Reminder: add '-d' to FLFLAGS for debugging.
-#
-# $Id: flavours,v 4.10 2012/02/05 23:41:45 cal103 Exp $
-#-----------------------------------------------------------------------------
-
-# The list of FLAVOURs can be set on the command line.
-F := $(shell echo $(FLAVOURS) | tr a-z A-Z)
-ifeq "$F" ""
-  F :=
-  FLAVOURS := ""
-endif
-
-ifeq "$F" "LINUX"
-  override FLAVOURS := "" Linux Linuxp
-endif
-
-ifeq "$F" "SUN"
-  override FLAVOURS := "" SUN/GNU SUN/GNU3 SUN/GNUp SUN/ANSI
-endif
-
-ifeq "$F" "PURE"
-  override FLAVOURS := SUN/Pure SUN/Quant
-endif
-
-F :=
-
-
-# Various C standards handled by features.h in Linux.
-FEATURES :=
-ifeq "$(notdir $(shell pwd))" "utils"
-  # To get off_t for fseeko() usage in fitshdr when gcc is invoked with the
-  # -std=c89 (same as -ansi) or the -std=c99 options.
-  FEATURES := -D_XOPEN_SOURCE
-endif
-
-
-# Linux with gcc/gfortran (also works for Darwin).
-ifeq "$(FLAVOUR)" "Linux"
-  F := $(FLAVOUR)
-  export CC       := gcc -std=c89 -pedantic
-  export CPPFLAGS := $(FEATURES)
-  export CFLAGS   := -g -O0 -Wall -Wpadded -Wno-long-long
-  export FFLAGS   := -g -O0 -fimplicit-none -Wall -I.
-         VALGRIND := valgrind -v --leak-check=yes
-endif
-
-ifeq "$(FLAVOUR)" "Linuxp"
-  F := $(FLAVOUR)
-  export CC       := gcc -std=c89 -pedantic
-  export CPPFLAGS := $(FEATURES)
-  export CFLAGS   := -pg -g -O -Wall -Wpadded -Wno-long-long
-  export FFLAGS   := -pg -a -g -O -fimplicit-none -Wall -I.
-  export LDFLAGS  := -pg -g $(filter -L%, $(LDFLAGS))
-  override EXTRA_CLEAN := gmon.out bb.out
-endif
-
-
-# Solaris with gcc/gfortran 4.x (lynx).
-ifeq "$(FLAVOUR)" "SUN/GNU"
-  F := $(FLAVOUR)
-  export CC       := gcc -std=c89
-  export CPPFLAGS := $(FEATURES)
-  export CFLAGS   := -g -Wall -Wpadded -Wno-long-long
-  export F77      := gfortran
-  export FFLAGS   := -g -fimplicit-none -Wall -I.
-  LD      := gcc
-endif
-
-ifeq "$(FLAVOUR)" "SUN/GNU3"
-  F := $(FLAVOUR)
-  export CC       := gcc-3.1.1 -std=c89
-  export CPPFLAGS := $(FEATURES)
-  export CFLAGS   := -g -Wall -Wpadded -Wno-long-long
-  export F77      := g77-3.1.1
-  export FFLAGS   := -g -Wimplicit -Wunused -Wno-globals -I.
-  LD      := gcc-3.1.1
-endif
-
-ifeq "$(FLAVOUR)" "SUN/GNUp"
-  F := $(FLAVOUR)
-  export CC       := gcc -std=c89 -pedantic
-  export CPPFLAGS := $(FEATURES)
-  export CFLAGS   := -pg -a -g -O -Wall -Wpadded -Wno-long-long
-  export FFLAGS   := -pg -a -g -O -fimplicit-none -Wall -I.
-  export LDFLAGS  := -pg -a -g $(filter -L%, $(LDFLAGS))
-  override EXTRA_CLEAN := gmon.out bb.out
-endif
-
-
-# Solaris with SUN cc/f77.
-ifeq "$(FLAVOUR)" "SUN/ANSI"
-  F := $(FLAVOUR)
-  WCSTRIG := NATIVE
-  export CC       := cc
-  export CFLAGS   := -g -I/usr/local/include
-  export F77      := f77
-  export FFLAGS   := -g -erroff=WDECL_LOCAL_NOTUSED
-  LD      := f77
-endif
-
-
-# Purify and quantify in Solaris.
-ifeq "$(FLAVOUR)" "SUN/Pure"
-  F := $(FLAVOUR)
-  WCSTRIG := NATIVE
-  export CC       := purify gcc
-  export CFLAGS   := -g
-  export F77      := purify gcc
-  export FFLAGS   := -g -Wimplicit -Wno-globals -I.
-  export LDFLAGS  := $(filter -L%, $(LDFLAGS))
-  override EXTRA_CLEAN := *_pure_p*.[ao] *.pcv .pure ../C/*_pure_p*.[ao]
-endif
-
-ifeq "$(FLAVOUR)" "SUN/Quant"
-  F := $(FLAVOUR)
-  WCSTRIG := NATIVE
-  export CC       := quantify gcc
-  export CFLAGS   := -g
-  export F77      := quantify gcc
-  export FFLAGS   := -g -Wimplicit -Wno-globals -I.
-  export LDFLAGS  := $(filter -L%, $(LDFLAGS))
-  override EXTRA_CLEAN := *_pure_q*.[ao] .pure
-endif
-
-ifneq "$F" "$(FLAVOUR)"
-  override FLAVOUR := unrecognised
-endif
-
-# gmake uses FC in place of configure's F77.
-ifdef F77
-  FC := $(F77)
-endif
-
-ifndef TIMER
-  TIMER := date +"%a %Y/%m/%d %X %z, executing on $$HOST"
-endif
-
-ifdef FLAVOUR
-  TIMER := $(TIMER) ; echo "    with $(FLAVOUR) FLAVOUR."
-endif
-
-show ::
-	-@ echo 'For code development...'
-	-@ echo '  FLAVOURS    := $(FLAVOURS)'
-	-@ echo '  FLAVOUR     := $(FLAVOUR)'
-	-@ echo '  VALGRIND    := $(VALGRIND)'
-	-@ echo '  EXTRA_CLEAN := $(EXTRA_CLEAN)'
-	-@ echo ''
diff --git a/astropy/wcs/src/wcslib/makedefs.in b/astropy/wcs/src/wcslib/makedefs.in
deleted file mode 100644
index 2a55eeb..0000000
--- a/astropy/wcs/src/wcslib/makedefs.in
+++ /dev/null
@@ -1,238 +0,0 @@
-#-----------------------------------------------------------------------------
-# GNU makefile definitions for building WCSLIB 4.10
-#
-# makedefs is generated from makedefs.in by configure.  It contains variable
-# definitions and some general-purpose rules for building WCSLIB.
-#
-# Targets defined here
-# --------------------
-#   printenv:  Print the environment as seen within makefile rules.
-#   show:      Print the values of all makefile variables used.
-#
-# Notes:
-#   1) If you need to make changes then it may be preferable to modify
-#      makedefs.in (not makedefs).  The makefile will detect this and
-#      automatically re-run config.status to regenerate makedefs.
-#
-#   2) There are three choices for trigd functions - cosd(), sind(), tand(),
-#      acosd(), asind(), atand(), and atan2d(), made by setting WCSTRIG:
-#
-#      1: Use the wrapper functions supplied with WCSLIB (default):
-#         WCSTRIG := WRAPPER
-#
-#      2: Use native trigd functions supplied in a mathematics library such
-#         as libsunmath (you will also need to add the library to the LIBS
-#         variable below):
-#         WCSTRIG := NATIVE
-#
-#      3: Use C preprocessor macro implementations of the trigd functions
-#         (this method is typically 20% faster but may lead to rounding
-#         errors near the poles):
-#         WCSTRIG := MACRO
-#
-#   3) Variables for creating the shared (dynamic) library are currently
-#      only set by 'configure' if the GNU C compiler is used.  However,
-#      you can set these variables by hand, preferably in makedefs.in.
-#
-#      Shared libraries require position-independent code (PIC) which imposes
-#      a performance overhead.  Consequently the static libraries are
-#      compiled separately without this option.
-#
-#      The shared library will be installed with version number, e.g. as
-#      libwcs.so.4.10 or libwcs.4.10.dylib with or without the symlink
-#      required to make it visible to the linker (controlled by the SHRLN
-#      variable).  On Macs it is deliberately not created because its very
-#      existence precludes static linking with the cctools linker.  You can
-#      still link dynamically by using -lwcs.4.10.
-#
-#   4) PGPLOT is Tim Pearson's Fortran graphics library with separate C
-#      interface available from astro.caltech.edu.  It is only required by
-#      one utility, wcsgrid, and the test programs that plot test grids
-#      (tprj2, tcel1, tcel2, tspc, ttab2, ttab3, twcsmix, and tpih2).  You can
-#      skip these by setting PGPLOTLIB to blank.
-#
-#      It is difficult for configure to deduce what auxiliary graphics
-#      libraries may be needed for PGPLOT since it depends on which of many
-#      possible graphics drivers were selected when PGPLOT was installed.
-#      Therefore it is quite likely that you will need to add additional
-#      libraries to PGPLOTLIB.
-#
-#   5) CFITSIO is Bill Pence's FITS I/O library written in C with Fortran
-#      wrappers, available from http://heasarc.gsfc.nasa.gov/fitsio.
-#
-#      CFITSIO is required by three utilities, HPXcvt, wcsgrid, and wcsware,
-#      and also by the test programs twcstab and twcshdr.  wcsware and the
-#      test programs use fits_read_wcstab() which is implemented by
-#      getwcstab.c.  However, this implementation is included in CFITSIO post
-#      3.004beta, so getwcstab.c is required here only for older releases
-#      (controlled by variable GETWCSTAB).  getwcstab.o itself is not inserted
-#      into the WCSLIB object library.
-#
-#      If available, CFITSIO is also optionally used for test programs
-#      tfitshdr, tbth1, tpih1 and tpih2 by setting preprocessor macro
-#      -DDO_CFITSIO.
-#
-# Author: Mark Calabretta, Australia Telescope National Facility
-# http://www.atnf.csiro.au/~mcalabre/index.html
-# $Id: makedefs.in,v 4.10 2012/02/05 23:41:45 cal103 Exp $
-#-----------------------------------------------------------------------------
-# Version.
-  LIBVER    := @LIBVER@
-  WCSLIBPKG := wcslib- at PACKAGE_VERSION@
-
-# System architecture.
-  ARCH     := @ARCH@
-
-# Flex and options.
-  FLEX     := @FLEX@
-  FLFLAGS  :=
-
-# C preprocessor and options.
-  CPP      := @CPP@
-  CPPFLAGS := @DEFS@
-  WCSTRIG  := WRAPPER
-
-# C compiler and options.
-  CC       := @CC@
-  CFLAGS   := @CFLAGS@
-
-# Fortran compiler and options.
-  FC       := @F77@
-  FFLAGS   := @FFLAGS@
-
-# Static object library.
-  WCSLIB   := libwcs-$(LIBVER).a
-  RANLIB   := @RANLIB@
-
-# Shared (dynamic) library (see note 3 above).
-  SHRLIB   := @SHRLIB@
-  SONAME   := @SONAME@
-  SHRFLAGS := @SHRFLAGS@
-  SHRLD    := @SHRLD@
-  SHRLN    := @SHRLN@
-
-# What subdirectories to build.
-  SUBDIRS  := @SUBDIRS@
-  TSTDIRS  := @TSTDIRS@
-
-# Top of the 'make install' hierarchy: pgsbox -> Fortran -> C.
-  INSTDIR  := @INSTDIR@
-
-# Installation utilities and locations.
-  LN_S     := @LN_S@
-  INSTALL  := @INSTALL@
-
-  # Needed for the definitions provided by autoconf.
-  prefix          := @prefix@
-  exec_prefix     := @exec_prefix@
-  datarootdir     := @datarootdir@
-  PACKAGE_TARNAME := @PACKAGE_TARNAME@
-  docdir          := @docdir@
-
-  LIBDIR   := $(DESTDIR)@libdir@
-  BINDIR   := $(DESTDIR)@bindir@
-  INCDIR   := $(DESTDIR)@includedir@/wcslib-$(LIBVER)
-  INCLINK  := $(DESTDIR)@includedir@/wcslib
-  DOCDIR   := $(DESTDIR)@docdir@
-  HTMLDIR  := $(DESTDIR)@htmldir@
-  PDFDIR   := $(DESTDIR)@pdfdir@
-  MANDIR   := $(DESTDIR)@mandir@
-
-# For putting timestamps in the build log.
-  TIMER    := date +"%a %Y/%m/%d %X %z, executing on $$HOST"
-
-
-# The remaining options are for building utilities and test programs.
-# -------------------------------------------------------------------
-# Linker options (use CC for linking).
-  LD       = $(CC)
-  LDFLAGS := @LDFLAGS@
-
-# PGPLOT (see note 4 above).
-  PGPLOTINC := @PGPLOTINC@
-  PGPLOTLIB := @PGPLOTLIB@
-
-# CFITSIO (see note 5 above).
-  CFITSIOINC := @CFITSIOINC@
-  CFITSIOLIB := @CFITSIOLIB@
-  GETWCSTAB  := @GETWCSTAB@
-
-# Libraries required by the above Fortran compiler.
-  FLIBS := @FLIBS@
-
-# Libraries required by WCSLIB itself.
-  LIBS := @LIBS@
-
-
-#-----------------------------------------------------------------------------
-# You shouldn't need to change anything below here.
-#-----------------------------------------------------------------------------
-
-SHELL := /bin/sh
-VPATH := ..
-
-# Common targets.
-.PHONY : all build printenv show
-
-all : show build
-
-# Print the environment as seen by makefile rules.
-printenv :
-	-@ printenv | sort
-
-# Print variable definitions.
-show :: wcsconfig.h
-	-@ echo ''
-	-@ uname -a
-	-@ echo ''
-	-@ $(MAKE) --version | head -1
-	-@ echo '  MAKEFLAGS   := $(MAKEFLAGS)'
-	-@ echo ''
-	-@ echo 'For building and installing $(WCSLIBPKG)...'
-	-@ echo '  ARCH        := $(ARCH)'
-	-@ echo '  FLEX        := $(FLEX)'
-	-@ echo '  FLFLAGS     := $(FLFLAGS)'
-	-@ echo '  CPP         := $(CPP)'
-	-@ echo '  CPPFLAGS    := $(CPPFLAGS)'
-	-@ echo '  WCSTRIG     := $(WCSTRIG)'
-	-@ echo '  CC          := $(CC)'
-	-@ echo '  CFLAGS      := $(CFLAGS)'
-	-@ echo '  FC          := $(FC)'
-	-@ echo '  FFLAGS      := $(FFLAGS)'
-	-@ echo '  WCSLIB      := $(WCSLIB)'
-	-@ echo '  RANLIB      := $(RANLIB)'
-	-@ echo '  SHRLIB      := $(SHRLIB)'
-	-@ echo '  SONAME      := $(SONAME)'
-	-@ echo '  SHRFLAGS    := $(SHRFLAGS)'
-	-@ echo '  SHRLD       := $(SHRLD)'
-	-@ echo '  SHRLN       := $(SHRLN)'
-	-@ echo '  LN_S        := $(LN_S)'
-	-@ echo '  INSTALL     := $(INSTALL)'
-	-@ echo '  LIBDIR      := $(LIBDIR)'
-	-@ echo '  BINDIR      := $(BINDIR)'
-	-@ echo '  INCDIR      := $(INCDIR)'
-	-@ echo '  INCLINK     := $(INCLINK)'
-	-@ echo '  DOCDIR      := $(DOCDIR)'
-	-@ echo '  HTMLDIR     := $(HTMLDIR)'
-	-@ echo '  PDFDIR      := $(PDFDIR)'
-	-@ echo '  MANDIR      := $(MANDIR)'
-	-@ echo '  TIMER       := $(TIMER)'
-	-@ echo ''
-	-@ echo 'Important wcsconfig.h defines...'
-	-@ echo "  `grep HAVE_SINCOS $<`"
-	-@ echo "  `grep WCSLIB_INT64 $<`"
-	-@ echo ''
-	-@ echo 'To build utilities and test programs...'
-	-@ echo '  LD          := $(LD)'
-	-@ echo '  LDFLAGS     := $(LDFLAGS)'
-	-@ echo '  PGPLOTINC   := $(PGPLOTINC)'
-	-@ echo '  PGPLOTLIB   := $(PGPLOTLIB)'
-	-@ echo '  CFITSIOINC  := $(CFITSIOINC)'
-	-@ echo '  CFITSIOLIB  := $(CFITSIOLIB)'
-	-@ echo '  GETWCSTAB   := $(GETWCSTAB)'
-	-@ echo '  FLIBS       := $(FLIBS)'
-	-@ echo '  LIBS        := $(LIBS)'
-	-@ echo ''
-
-# Code development overrides, for use in the code subdirectories.
--include ../flavours
diff --git a/astropy/wcs/src/wcslib/wcsconfig.h.in b/astropy/wcs/src/wcslib/wcsconfig.h.in
deleted file mode 100644
index d28f4d7..0000000
--- a/astropy/wcs/src/wcslib/wcsconfig.h.in
+++ /dev/null
@@ -1,18 +0,0 @@
-/*============================================================================
-*
-*   wcsconfig.h is generated from wcsconfig.h.in by 'configure'.  It contains
-*   C preprocessor macro definitions for compiling WCSLIB 4.10
-*
-*   Author: Mark Calabretta, Australia Telescope National Facility
-*   http://www.atnf.csiro.au/~mcalabre/index.html
-*   $Id: wcsconfig.h.in,v 4.10 2012/02/05 23:41:45 cal103 Exp $
-*===========================================================================*/
-
-/* WCSLIB library version number. */
-#undef WCSLIB_VERSION
-
-/* Define to 1 if sincos() is available. */
-#undef HAVE_SINCOS
-
-/* 64-bit integer data type. */
-#undef WCSLIB_INT64
diff --git a/astropy/wcs/src/wcslib/wcsconfig_f77.h.in b/astropy/wcs/src/wcslib/wcsconfig_f77.h.in
deleted file mode 100644
index 16e2dee..0000000
--- a/astropy/wcs/src/wcslib/wcsconfig_f77.h.in
+++ /dev/null
@@ -1,21 +0,0 @@
-/*============================================================================
-*
-*   wcsconfig_f77.h is generated from wcsconfig_f77.h.in by 'configure'.  It
-*   contains C preprocessor definitions for building the WCSLIB 4.10 Fortran
-*   wrappers.
-*
-*   Author: Mark Calabretta, Australia Telescope National Facility
-*   http://www.atnf.csiro.au/~mcalabre/index.html
-*   $Id: wcsconfig_f77.h.in,v 4.10 2012/02/05 23:41:45 cal103 Exp $
-*===========================================================================*/
-
-/* Integer array type large enough to hold an address.  Set here to int[2] for
- * 64-bit addresses, but could be defined as int* on 32-bit machines. */
-typedef int iptr[2];
-
-/* Macro for mangling Fortran subroutine names that do not contain
- * underscores.  Typically a name like "WCSINI" (case-insensitive) will become
- * something like "wcsini_" (case-sensitive).  The Fortran wrappers, which are
- * written in C, are preprocessed into names that match the latter.  The macro
- * takes two arguments which specify the name in lower and upper case. */
-#undef F77_FUNC
diff --git a/astropy/wcs/src/wcslib/wcsconfig_tests.h.in b/astropy/wcs/src/wcslib/wcsconfig_tests.h.in
deleted file mode 100644
index 5718397..0000000
--- a/astropy/wcs/src/wcslib/wcsconfig_tests.h.in
+++ /dev/null
@@ -1,18 +0,0 @@
-/*============================================================================
-*
-*   wcsconfig_test.h is generated from wcsconfig_test.h.in by 'configure'.  It
-*   contains C preprocessor definitions for compiling the WCSLIB 4.10 test/demo
-*   programs.
-*
-*   Author: Mark Calabretta, Australia Telescope National Facility
-*   http://www.atnf.csiro.au/~mcalabre/index.html
-*   $Id: wcsconfig_tests.h.in,v 4.10 2012/02/05 23:41:45 cal103 Exp $
-*===========================================================================*/
-
-#include <wcsconfig.h>
-
-/* Define to 1 if the CFITSIO library is available. */
-#undef HAVE_CFITSIO
-
-/* Define to the printf format modifier for size_t type. */
-#undef MODZ
diff --git a/astropy/wcs/src/wcslib/wcsconfig_utils.h.in b/astropy/wcs/src/wcslib/wcsconfig_utils.h.in
deleted file mode 100644
index fed6215..0000000
--- a/astropy/wcs/src/wcslib/wcsconfig_utils.h.in
+++ /dev/null
@@ -1,35 +0,0 @@
-/*============================================================================
-*
-*   wcsconfig_utils.h is generated from wcsconfig_utils.h.in by 'configure'.
-*   It contains C preprocessor macro definitions for compiling the WCSLIB 4.10
-*   utilities.
-*
-*   Author: Mark Calabretta, Australia Telescope National Facility
-*   http://www.atnf.csiro.au/~mcalabre/index.html
-*   $Id: wcsconfig_utils.h.in,v 4.10 2012/02/05 23:41:45 cal103 Exp $
-*===========================================================================*/
-
-#include <wcsconfig.h>
-
-/* Definitions for Large File Support (LFS), i.e. files larger than 2GiB, for
- * the fitshdr utility. */
-
-/* Define to 1 if fseeko() is available (for small or large files). */
-#undef HAVE_FSEEKO
-
-/* Define _LARGEFILE_SOURCE to get prototypes from stdio.h for the LFS
- * functions fseeko() and ftello() which use an off_t argument in place of a
- * long. */
-#undef _LARGEFILE_SOURCE
-
-/* There seems to be a bug in autoconf that causes _LARGEFILE_SOURCE not to be
- * set in Linux.  This dreadful kludge gets around it for now. */
-#if (defined HAVE_FSEEKO && !defined _LARGEFILE_SOURCE)
-#define _LARGEFILE_SOURCE
-#endif
-
-/* Number of bits in a file offset (off_t) on systems where it can be set. */
-#undef _FILE_OFFSET_BITS
-
-/* Define for large files needed on AIX-type systems. */
-#undef _LARGE_FILES
diff --git a/astropy/wcs/src/wcslib_wrap.c b/astropy/wcs/src/wcslib_wrap.c
index 8ab99f0..c02bc65 100644
--- a/astropy/wcs/src/wcslib_wrap.c
+++ b/astropy/wcs/src/wcslib_wrap.c
@@ -9,6 +9,7 @@
 #include "wcslib_tabprm_wrap.h"
 #include "wcslib_wtbarr_wrap.h"
 #include "wcslib_units_wrap.h"
+#include "unit_list_proxy.h"
 #include <structmember.h> /* from Python */
 
 #include <wcs.h>
@@ -2237,23 +2238,6 @@ PyWcsprm_set_cubeface(
   return set_int("cubeface", value, &self->x.cubeface);
 }
 
-static int
-unit_verify(char* val) {
-
-  int status, func;
-  double scale, units[WCSUNITS_NTYPE];
-  struct wcserr *err = NULL;
-
-  status = wcsulexe(val, &func, &scale, units, &err);
-  if (status == 0) {
-    return 1;
-  } else {
-    wcserr_units_to_python_exc(err);
-    free(err);
-    return 0;
-  }
-}
-
 /*@null@*/ static PyObject*
 PyWcsprm_get_cunit(
     PyWcsprm* self,
@@ -2263,9 +2247,8 @@ PyWcsprm_get_cunit(
     return NULL;
   }
 
-  return get_str_list_verified(
-    "cunit", self->x.cunit, (Py_ssize_t)self->x.naxis, 68, (PyObject*)self,
-    unit_verify);
+  return get_unit_list(
+    "cunit", self->x.cunit, (Py_ssize_t)self->x.naxis, (PyObject*)self);
 }
 
 static int
@@ -2280,9 +2263,8 @@ PyWcsprm_set_cunit(
 
   note_change(self);
 
-  return set_str_list_verified(
-    "cunit", value, (Py_ssize_t)self->x.naxis, 0, self->x.cunit,
-    unit_verify);
+  return set_unit_list(
+    (PyObject *)self, "cunit", value, (Py_ssize_t)self->x.naxis, self->x.cunit);
 }
 
 /*@null@*/ static PyObject*
@@ -3155,7 +3137,7 @@ PyTypeObject PyWcsprmType = {
   PyObject_HEAD_INIT(NULL)
   0,                            /*ob_size*/
   #endif
-  "astropy.wcs._Wcsprm",              /*tp_name*/
+  "astropy.wcs.Wcsprm",              /*tp_name*/
   sizeof(PyWcsprm),             /*tp_basicsize*/
   0,                            /*tp_itemsize*/
   (destructor)PyWcsprm_dealloc, /*tp_dealloc*/
@@ -3210,7 +3192,7 @@ _setup_wcsprm_type(
   wcserr_enable(1);
 
   return (
-    PyModule_AddObject(m, "_Wcsprm", (PyObject *)&PyWcsprmType) ||
+    PyModule_AddObject(m, "Wcsprm", (PyObject *)&PyWcsprmType) ||
     CONSTANT(WCSSUB_LONGITUDE) ||
     CONSTANT(WCSSUB_LATITUDE)  ||
     CONSTANT(WCSSUB_CUBEFACE)  ||
diff --git a/astropy/wcs/tests/data/locale.hdr b/astropy/wcs/tests/data/locale.hdr
new file mode 100644
index 0000000..bf210f2
--- /dev/null
+++ b/astropy/wcs/tests/data/locale.hdr
@@ -0,0 +1 @@
+WCSAXES =                    2 / Number of coordinate axes                      CRPIX1  =               1920.5 / Pixel coordinate of reference point            CRPIX2  =               1920.5 / Pixel coordinate of reference point            CDELT1  =   -0.000416666666667 / [deg] Coordinate increment at reference point  CDELT2  =    0.000416666666667 / [deg] Coordinate increment at reference point  CUNIT1  = 'deg'                / Units of coordinate increment and value        CUNIT2  = 'deg'                / Units of coordinate increment and value        CTYPE1  = 'RA---TAN'           / Right ascension, gnomonic projection           CTYPE2  = 'DEC--TAN'           / Declination, gnomonic projection               CRVAL1  =               36.661 / [deg] Coordinate value at reference point      CRVAL2  =                -4.48 / [deg] Coordinate value at reference point      LONPOLE =                  180 / [deg] Native longitude of celestial pole       LATPOLE =                -4.48 / [deg] Native latitude of celestial pole        RESTFRQ =                    0 / [Hz] Line rest frequency                       RESTWAV =                    0 / [Hz] Line rest wavelength                      EQUINOX =                 2000 / [yr] Equinox of equatorial coordinates         END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             
\ No newline at end of file
diff --git a/astropy/wcs/tests/data/nonstandard_units.hdr b/astropy/wcs/tests/data/nonstandard_units.hdr
index 680fc88..95405ce 100644
--- a/astropy/wcs/tests/data/nonstandard_units.hdr
+++ b/astropy/wcs/tests/data/nonstandard_units.hdr
@@ -1,16 +1 @@
-CD1_2   =            -3.72E-05
-CD1_3   =                    0
-CD1_1   =            -4.12E-05
-CUNIT3  = 'HZ      '
-CUNIT2  = 'deg     '
-CTYPE1  = 'RA---TAN'
-NAXIS   =                    3
-CTYPE3  = 'AWAV    '
-CD2_1   =            -3.72E-05
-CTYPE2  = 'DEC--TAN'
-CD2_3   =                    0
-CD2_2   =             4.12E-05
-CUNIT1  = 'deg     '
-CD3_1   =                    0
-CD3_2   =                    0
-CD3_3   =                  0.2
\ No newline at end of file
+CD1_2   =            -3.72E-05                                                  CD1_3   =                    0                                                  CD1_1   =            -4.12E-05                                                  CUNIT3  = 'HZ      '                                                            CUNIT2  = 'deg     '                                                            CTYPE1  = 'RA---TAN'                                                            NAXIS   =                    3                                                  CTYPE3  = 'AWAV    '                                                            CD2_1   =            -3.72E-05                                                  CTYPE2  = 'DEC--TAN'                                                            CD2_3   =                    0                                                  CD2_2   =             4.12E-05                                                  CUNIT1  = 'deg     '                                                            CD3_1   =                    0                                                  CD3_2   =                    0                                                  CD3_3   =                  0.2                                                  END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             
\ No newline at end of file
diff --git a/astropy/wcs/tests/test_pickle.py b/astropy/wcs/tests/test_pickle.py
index ec67c5c..2f440e4 100644
--- a/astropy/wcs/tests/test_pickle.py
+++ b/astropy/wcs/tests/test_pickle.py
@@ -4,7 +4,7 @@ import cPickle
 import numpy as np
 from numpy.testing import assert_array_almost_equal
 
-from ...config import get_data_contents, get_data_fileobj
+from ...utils.data import get_pkg_data_contents, get_pkg_data_fileobj
 from ...io import fits
 from ...tests.helper import pytest
 from ... import wcs
@@ -17,51 +17,56 @@ def test_basic():
 
 
 def test_dist():
-    hdulist = fits.open(get_data_fileobj(os.path.join("data", "dist.fits")))
-    wcs1 = wcs.WCS(hdulist[0].header, hdulist)
-    assert wcs1.det2im2 is not None
-    s = cPickle.dumps(wcs1)
-    wcs2 = cPickle.loads(s)
+    with get_pkg_data_fileobj(
+            os.path.join("data", "dist.fits"), encoding='binary') as test_file:
+        hdulist = fits.open(test_file)
+        wcs1 = wcs.WCS(hdulist[0].header, hdulist)
+        assert wcs1.det2im2 is not None
+        s = cPickle.dumps(wcs1)
+        wcs2 = cPickle.loads(s)
 
-    x = np.random.rand(2 ** 16, wcs1.wcs.naxis)
-    world1 = wcs1.all_pix2world(x, 1)
-    world2 = wcs2.all_pix2world(x, 1)
+        x = np.random.rand(2 ** 16, wcs1.wcs.naxis)
+        world1 = wcs1.all_pix2world(x, 1)
+        world2 = wcs2.all_pix2world(x, 1)
 
-    assert_array_almost_equal(world1, world2)
+        assert_array_almost_equal(world1, world2)
 
 
 def test_sip():
-    hdulist = fits.open(get_data_fileobj(os.path.join("data", "sip.fits")),
-                        ignore_missing_end=True)
-    wcs1 = wcs.WCS(hdulist[0].header)
-    assert wcs1.sip is not None
-    s = cPickle.dumps(wcs1)
-    wcs2 = cPickle.loads(s)
+    with get_pkg_data_fileobj(
+            os.path.join("data", "sip.fits"), encoding='binary') as test_file:
+        hdulist = fits.open(test_file, ignore_missing_end=True)
+        wcs1 = wcs.WCS(hdulist[0].header)
+        assert wcs1.sip is not None
+        s = cPickle.dumps(wcs1)
+        wcs2 = cPickle.loads(s)
 
-    x = np.random.rand(2 ** 16, wcs1.wcs.naxis)
-    world1 = wcs1.all_pix2world(x, 1)
-    world2 = wcs2.all_pix2world(x, 1)
+        x = np.random.rand(2 ** 16, wcs1.wcs.naxis)
+        world1 = wcs1.all_pix2world(x, 1)
+        world2 = wcs2.all_pix2world(x, 1)
 
-    assert_array_almost_equal(world1, world2)
+        assert_array_almost_equal(world1, world2)
 
 
 def test_sip2():
-    hdulist = fits.open(get_data_fileobj(os.path.join("data", "sip2.fits")),
-                        ignore_missing_end=True)
-    wcs1 = wcs.WCS(hdulist[0].header)
-    assert wcs1.sip is not None
-    s = cPickle.dumps(wcs1)
-    wcs2 = cPickle.loads(s)
+    with get_pkg_data_fileobj(
+            os.path.join("data", "sip2.fits"), encoding='binary') as test_file:
+        hdulist = fits.open(test_file, ignore_missing_end=True)
+        wcs1 = wcs.WCS(hdulist[0].header)
+        assert wcs1.sip is not None
+        s = cPickle.dumps(wcs1)
+        wcs2 = cPickle.loads(s)
 
-    x = np.random.rand(2 ** 16, wcs1.wcs.naxis)
-    world1 = wcs1.all_pix2world(x, 1)
-    world2 = wcs2.all_pix2world(x, 1)
+        x = np.random.rand(2 ** 16, wcs1.wcs.naxis)
+        world1 = wcs1.all_pix2world(x, 1)
+        world2 = wcs2.all_pix2world(x, 1)
 
-    assert_array_almost_equal(world1, world2)
+        assert_array_almost_equal(world1, world2)
 
 
 def test_wcs():
-    header = get_data_contents(os.path.join("data", "outside_sky.hdr"))
+    header = get_pkg_data_contents(
+        os.path.join("data", "outside_sky.hdr"), encoding='binary')
 
     wcs1 = wcs.WCS(header)
     s = cPickle.dumps(wcs1)
diff --git a/astropy/wcs/tests/test_profiling.py b/astropy/wcs/tests/test_profiling.py
index 8bc517b..7ba0e02 100644
--- a/astropy/wcs/tests/test_profiling.py
+++ b/astropy/wcs/tests/test_profiling.py
@@ -5,21 +5,21 @@ import sys
 import numpy as np
 from numpy.testing import assert_array_almost_equal
 
-from ...config import get_data_filenames, get_data_contents
+from ...utils.data import get_pkg_data_filenames, get_pkg_data_contents
 
 from ... import wcs
 
 
 def test_maps():
     def test_map(filename):
-        header = get_data_contents(os.path.join("maps", filename))
+        header = get_pkg_data_contents(os.path.join("maps", filename))
         wcsobj = wcs.WCS(header)
 
         x = np.random.rand(2 ** 12, wcsobj.wcs.naxis)
         world = wcsobj.wcs_pix2world(x, 1)
         pix = wcsobj.wcs_world2pix(x, 1)
 
-    hdr_file_list = list(get_data_filenames("maps", "*.hdr"))
+    hdr_file_list = list(get_pkg_data_filenames("maps", "*.hdr"))
 
     # actually perform a test for each one
     for filename in hdr_file_list:
@@ -51,14 +51,14 @@ def test_maps():
 
 def test_spectra():
     def test_spectrum(filename):
-        header = get_data_contents(os.path.join("spectra", filename))
+        header = get_pkg_data_contents(os.path.join("spectra", filename))
         wcsobj = wcs.WCS(header)
 
         x = np.random.rand(2 ** 16, wcsobj.wcs.naxis)
         world = wcsobj.wcs_pix2world(x, 1)
         pix = wcsobj.wcs_world2pix(x, 1)
 
-    hdr_file_list = list(get_data_filenames("spectra", "*.hdr"))
+    hdr_file_list = list(get_pkg_data_filenames("spectra", "*.hdr"))
 
     # actually perform a test for each one
     for filename in hdr_file_list:
diff --git a/astropy/wcs/tests/test_wcs.py b/astropy/wcs/tests/test_wcs.py
index 05f099e..f0ebaee 100644
--- a/astropy/wcs/tests/test_wcs.py
+++ b/astropy/wcs/tests/test_wcs.py
@@ -4,10 +4,13 @@ import sys
 import warnings
 
 import numpy as np
-from numpy.testing import assert_array_almost_equal
+from numpy.testing import (
+    assert_array_almost_equal, assert_array_almost_equal_nulp)
 
+from ...tests.helper import raises
 from ... import wcs
-from ...config import get_data_filenames, get_data_contents, get_data_filename
+from ...utils.data import (
+    get_pkg_data_filenames, get_pkg_data_contents, get_pkg_data_filename)
 from ...tests.helper import pytest
 
 
@@ -19,7 +22,8 @@ def test_maps():
 
         # the test parameter is the base name of the file to use; find
         # the file in the installed wcs test directory
-        header = get_data_contents(os.path.join("maps", filename))
+        header = get_pkg_data_contents(
+            os.path.join("maps", filename), encoding='binary')
         wcsobj = wcs.WCS(header)
 
         world = wcsobj.wcs_pix2world([[97, 97]], 1)
@@ -31,7 +35,7 @@ def test_maps():
         assert_array_almost_equal(pix, [[97, 97]], decimal=0)
 
     # get the list of the hdr files that we want to test
-    hdr_file_list = list(get_data_filenames("maps", "*.hdr"))
+    hdr_file_list = list(get_pkg_data_filenames("maps", "*.hdr"))
 
     # actually perform a test for each one
     for filename in hdr_file_list:
@@ -69,7 +73,8 @@ def test_spectra():
 
         # the test parameter is the base name of the file to use; find
         # the file in the installed wcs test directory
-        header = get_data_contents(os.path.join("spectra", filename))
+        header = get_pkg_data_contents(
+            os.path.join("spectra", filename), encoding='binary')
 
         wcsobj = wcs.WCS(header)
 
@@ -77,7 +82,7 @@ def test_spectra():
         assert len(all) == 9
 
     # get the list of the hdr files that we want to test
-    hdr_file_list = list(get_data_filenames("spectra", "*.hdr"))
+    hdr_file_list = list(get_pkg_data_filenames("spectra", "*.hdr"))
 
     # actually perform a test for each one
     for filename in hdr_file_list:
@@ -115,8 +120,8 @@ derived_units = "Hz J W V N Pa C Ohm ohm S F Wb T H lm lx".split()
 add_all_units = "eV Jy R G barn".split()
 add_sup_units = "a yr pc bit byte Byte".split()
 add_sub_units = "mag".split()
-general_units = \
-              "deg arcmin arcsec mas d h min erg Ry u D DEGREE DEGREES".split()
+general_units = (
+    "deg arcmin arcsec mas d h min erg Ry u D DEGREE DEGREES".split())
 astro_units = "Angstrom angstrom AU lyr beam solRad solMass solLum Sun".split()
 device_units = "adu bin chan count ct photon ph pixel pix voxel".split()
 
@@ -148,7 +153,7 @@ def test_all_units():
 
     # list of all the units to test
     all = sorted(basic_units + derived_units + add_all_units + add_sup_units
-            + add_sub_units + general_units + astro_units + device_units)
+                 + add_sub_units + general_units + astro_units + device_units)
 
     # Pandokia has non-case-sensitve test names; since the unit name is
     # showing up in the test name, we want to disambiguate any name collisions.
@@ -206,13 +211,14 @@ def test_fixes():
     From github issue #36
     """
     def run():
-        header = get_data_contents('data/nonstandard_units.hdr')
+        header = get_pkg_data_contents(
+            'data/nonstandard_units.hdr', encoding='binary')
         w = wcs.WCS(header)
 
     with warnings.catch_warnings(record=True) as w:
         warnings.simplefilter("always")
         run()
-        assert len(w) == 3
+        assert len(w) == 2
         for item in w:
             assert issubclass(item.category, wcs.FITSFixedWarning)
             if 'unitfix' in str(item.message):
@@ -223,23 +229,122 @@ def test_outside_sky():
     """
     From github issue #107
     """
-    header = get_data_contents('data/outside_sky.hdr')
+    header = get_pkg_data_contents(
+        'data/outside_sky.hdr', encoding='binary')
     w = wcs.WCS(header)
 
-    assert np.all(np.isnan(w.wcs_pix2world([[100.,500.]], 0)))  # outside sky
-    assert np.all(np.isnan(w.wcs_pix2world([[200.,200.]], 0)))  # outside sky
-    assert not np.any(np.isnan(w.wcs_pix2world([[1000.,1000.]], 0)))
+    assert np.all(np.isnan(w.wcs_pix2world([[100., 500.]], 0)))  # outside sky
+    assert np.all(np.isnan(w.wcs_pix2world([[200., 200.]], 0)))  # outside sky
+    assert not np.any(np.isnan(w.wcs_pix2world([[1000., 1000.]], 0)))
 
 
 def test_load_fits_path():
-    fits = get_data_filename('data/sip.fits')
+    fits = get_pkg_data_filename('data/sip.fits')
     w = wcs.WCS(fits)
 
 
 def test_backward_compatible():
-    fits = get_data_filename('data/sip.fits')
+    fits = get_pkg_data_filename('data/sip.fits')
     w = wcs.WCS(fits)
 
     data = np.random.rand(100, 2)
     assert np.all(w.wcs_pix2world(data, 0) == w.wcs_pix2sky(data, 0))
     assert np.all(w.wcs_world2pix(data, 0) == w.wcs_sky2pix(data, 0))
+
+
+def test_dict_init():
+    """
+    Test that WCS can be initialized with a dict-like object
+    """
+
+    # Dictionary with no actual WCS, returns identity transform
+    w = wcs.WCS({})
+
+    xp, yp = w.wcs_world2pix(41., 2., 1)
+
+    assert_array_almost_equal_nulp(xp, 41., 10)
+    assert_array_almost_equal_nulp(yp, 2., 10)
+
+    # Valid WCS
+    w = wcs.WCS({'CTYPE1': 'GLON-CAR',
+                 'CTYPE2': 'GLAT-CAR',
+                 'CUNIT1': 'deg',
+                 'CUNIT2': 'deg',
+                 'CRPIX1': 1,
+                 'CRPIX2': 1,
+                 'CRVAL1': 40.,
+                 'CRVAL2': 0.,
+                 'CDELT1': -0.1,
+                 'CDELT2': 0.1})
+
+    xp, yp = w.wcs_world2pix(41., 2., 0)
+
+    assert_array_almost_equal_nulp(xp, -10., 10)
+    assert_array_almost_equal_nulp(yp, 20., 10)
+
+
+ at raises(TypeError)
+def test_extra_kwarg():
+    """
+    Issue #444
+    """
+    w = wcs.WCS()
+    data = np.random.rand(100, 2)
+    w.wcs_pix2sky(data, origin=1)
+
+
+def test_3d_shapes():
+    """
+    Issue #444
+    """
+    w = wcs.WCS(naxis=3)
+    data = np.random.rand(100, 3)
+    result = w.wcs_pix2sky(data, 1)
+    assert result.shape == (100, 3)
+    result = w.wcs_pix2sky(
+        data[..., 0], data[..., 1], data[..., 2], 1)
+    assert len(result) == 3
+
+
+def test_preserve_shape():
+    w = wcs.WCS(naxis=2)
+
+    x = np.random.random((2,3,4))
+    y = np.random.random((2,3,4))
+
+    xw, yw = w.wcs_pix2world(x, y, 1)
+
+    assert xw.shape == (2,3,4)
+    assert yw.shape == (2,3,4)
+
+    xp, yp = w.wcs_world2pix(x, y, 1)
+
+    assert xp.shape == (2,3,4)
+    assert yp.shape == (2,3,4)
+
+
+def test_broadcasting():
+    w = wcs.WCS(naxis=2)
+
+    x = np.random.random((2,3,4))
+    y = 1
+
+    xp, yp = w.wcs_world2pix(x, y, 1)
+
+    assert xp.shape == (2,3,4)
+    assert yp.shape == (2,3,4)
+
+
+def test_shape_mismatch():
+    w = wcs.WCS(naxis=2)
+
+    x = np.random.random((2,3,4))
+    y = np.random.random((3,2,4))
+
+    with pytest.raises(ValueError) as exc:
+        xw, yw = w.wcs_pix2world(x, y, 1)
+    assert exc.value.args[0] == "Coordinate arrays are not broadcastable to each other"
+
+    with pytest.raises(ValueError) as exc:
+        xp, yp = w.wcs_world2pix(x, y, 1)
+    assert exc.value.args[0] == "Coordinate arrays are not broadcastable to each other"
diff --git a/astropy/wcs/tests/test_wcsprm.py b/astropy/wcs/tests/test_wcsprm.py
index 99437cf..a04d00c 100644
--- a/astropy/wcs/tests/test_wcsprm.py
+++ b/astropy/wcs/tests/test_wcsprm.py
@@ -1,15 +1,17 @@
 from __future__ import print_function
 
-import os
-import sys
+import locale
+import re
+import warnings
 
-from astropy.tests.helper import raises
 from numpy.testing import assert_array_equal
 import numpy as np
 
+from ...tests.helper import pytest, raises
 from .. import wcs
 from .. import _wcs
-from ...config import get_data_contents, get_data_fileobj
+from ...utils.data import get_pkg_data_contents, get_pkg_data_fileobj
+from ... import units as u
 
 
 def b(s):
@@ -19,7 +21,7 @@ def b(s):
 
 
 def test_alt():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     assert w.alt == b(" ")
     w.alt = b("X")
     assert w.alt == b("X")
@@ -29,23 +31,23 @@ def test_alt():
 
 @raises(ValueError)
 def test_alt_invalid1():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     w.alt = b("$")
 
 
 @raises(ValueError)
 def test_alt_invalid2():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     w.alt = b("  ")
 
 
 def test_axis_types():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     assert_array_equal(w.axis_types, [0, 0])
 
 
 def test_cd():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     w.cd = [[1, 0], [0, 1]]
     assert w.cd.dtype == np.float
     assert w.has_cd() == True
@@ -56,14 +58,14 @@ def test_cd():
 
 @raises(AttributeError)
 def test_cd_missing():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     assert w.has_cd() == False
     w.cd
 
 
 @raises(AttributeError)
 def test_cd_missing2():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     w.cd = [[1, 0], [0, 1]]
     assert w.has_cd() == True
     del w.cd
@@ -73,12 +75,12 @@ def test_cd_missing2():
 
 @raises(ValueError)
 def test_cd_invalid():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     w.cd = [1, 0, 0, 1]
 
 
 def test_cdelt():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     assert_array_equal(w.cdelt, [1, 1])
     w.cdelt = [42, 54]
     assert_array_equal(w.cdelt, [42, 54])
@@ -86,12 +88,12 @@ def test_cdelt():
 
 @raises(TypeError)
 def test_cdelt_delete():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     del w.cdelt
 
 
 def test_cel_offset():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     assert w.cel_offset is False
     w.cel_offset = 'foo'
     assert w.cel_offset is True
@@ -102,12 +104,12 @@ def test_cel_offset():
 def test_celfix():
     # TODO: We need some data with -NCP or -GLS projections to test
     # with.  For now, this is just a smoke test
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     assert w.celfix() == -1
 
 
 def test_cname():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     # Test that this works as an iterator
     for x in w.cname:
         assert x == b('')
@@ -118,12 +120,12 @@ def test_cname():
 
 @raises(TypeError)
 def test_cname_invalid():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     w.cname = [42, 54]
 
 
 def test_colax():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     assert w.colax.dtype == np.intc
     assert_array_equal(w.colax, [0, 0])
     w.colax = [42, 54]
@@ -133,7 +135,7 @@ def test_colax():
 
 
 def test_colnum():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     assert w.colnum == 0
     w.colnum = 42
     assert w.colnum == 42
@@ -141,12 +143,12 @@ def test_colnum():
 
 @raises(TypeError)
 def test_colnum_invalid():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     w.colnum = 'foo'
 
 
 def test_crder():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     assert w.crder.dtype == np.float
     assert np.all(np.isnan(w.crder))
     w.crder[0] = 0
@@ -155,7 +157,7 @@ def test_crder():
 
 
 def test_crota():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     w.crota = [1, 0]
     assert w.crota.dtype == np.float
     assert w.has_crota() == True
@@ -166,14 +168,14 @@ def test_crota():
 
 @raises(AttributeError)
 def test_crota_missing():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     assert w.has_crota() == False
     w.crota
 
 
 @raises(AttributeError)
 def test_crota_missing2():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     w.crota = [1, 0]
     assert w.has_crota() == True
     del w.crota
@@ -182,7 +184,7 @@ def test_crota_missing2():
 
 
 def test_crpix():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     assert w.crpix.dtype == np.float
     assert_array_equal(w.crpix, [0, 0])
     w.crpix = [42, 54]
@@ -192,7 +194,7 @@ def test_crpix():
 
 
 def test_crval():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     assert w.crval.dtype == np.float
     assert_array_equal(w.crval, [0, 0])
     w.crval = [42, 54]
@@ -202,7 +204,7 @@ def test_crval():
 
 
 def test_csyer():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     assert w.crder.dtype == np.float
     assert np.all(np.isnan(w.crder))
     w.crder[0] = 0
@@ -211,7 +213,7 @@ def test_csyer():
 
 
 def test_ctype():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     assert list(w.ctype) == [b(''), b('')]
     w.ctype = [b('RA---TAN'), b('DEC--TAN')]
     assert_array_equal(w.axis_types, [2200, 2201])
@@ -230,49 +232,63 @@ def test_ctype():
 
 
 def test_cubeface():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     assert w.cubeface == -1
 
 
 def test_cunit():
-    w = _wcs._Wcsprm()
-    assert list(w.cunit) == [b(''), b('')]
-    w.cunit = [b('m'), b('km')]
+    w = _wcs.Wcsprm()
+    assert list(w.cunit) == [u.Unit(''), u.Unit('')]
+    w.cunit = [u.m, 'km']
+    assert w.cunit[0] == u.m
+    assert w.cunit[1] == u.km
 
 
 @raises(ValueError)
 def test_cunit_invalid():
-    w = _wcs._Wcsprm()
-    w.cunit[0] = b('foo')
+    w = _wcs.Wcsprm()
+    w.cunit[0] = 'foo'
 
 
 @raises(ValueError)
 def test_cunit_invalid2():
-    w = _wcs._Wcsprm()
-    w.cunit = [b('foo'), b('bar')]
+    w = _wcs.Wcsprm()
+    w.cunit = ['foo', 'bar']
+
+
+def test_unit():
+    w = wcs.WCS()
+    w.wcs.cunit[0] = u.erg
+    assert w.wcs.cunit[0] == u.erg
+
+
+def test_unit2():
+    w = wcs.WCS()
+    myunit = u.Unit("FOOBAR", parse_strict="warn")
+    w.wcs.cunit[0] = myunit
 
 
 def test_cylfix():
     # TODO: We need some data with broken cylindrical projections to
     # test with.  For now, this is just a smoke test.
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     assert w.cylfix() == -1
 
 
 def test_dateavg():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     assert w.dateavg == b('')
     # TODO: When dateavg is verified, check that it works
 
 
 def test_dateobs():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     assert w.dateobs == b('')
     # TODO: When dateavg is verified, check that it works
 
 
 def test_datfix():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     w.dateobs = b('31/12/99')
     assert w.datfix() == 0
     assert w.dateobs == b('1999-12-31')
@@ -280,7 +296,7 @@ def test_datfix():
 
 
 def test_equinox():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     assert np.isnan(w.equinox)
     w.equinox = 0
     assert w.equinox == 0
@@ -289,7 +305,7 @@ def test_equinox():
 
 
 def test_fix():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     assert w.fix() == {
         'cdfix': 'No change',
         'cylfix': 'No change',
@@ -300,7 +316,7 @@ def test_fix():
 
 
 def test_fix2():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     w.dateobs = b('31/12/99')
     assert w.fix() == {
         'cdfix': 'No change',
@@ -314,7 +330,7 @@ def test_fix2():
 
 
 def test_fix3():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     w.dateobs = b('31/12/F9')
     assert w.fix() == {
         'cdfix': 'No change',
@@ -329,46 +345,46 @@ def test_fix3():
 
 def test_get_ps():
     # TODO: We need some data with PSi_ma keywords
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     assert len(w.get_ps()) == 0
 
 
 def test_get_pv():
     # TODO: We need some data with PVi_ma keywords
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     assert len(w.get_pv()) == 0
 
 
 @raises(AssertionError)
 def test_imgpix_matrix():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     w.imgpix_matrix
 
 
 @raises(AttributeError)
 def test_imgpix_matrix():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     w.imgpix_matrix = None
 
 
 def test_isunity():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     assert(w.is_unity())
 
 
 def test_lat():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     assert w.lat == -1
 
 
 @raises(AttributeError)
 def test_lat_set():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     w.lat = 0
 
 
 def test_latpole():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     assert w.latpole == 90.0
     w.latpole = 45.0
     assert w.latpole == 45.0
@@ -377,41 +393,41 @@ def test_latpole():
 
 
 def test_lattyp():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     print(repr(w.lattyp))
     assert w.lattyp == b("    ")
 
 
 @raises(AttributeError)
 def test_lattyp_set():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     w.lattyp = 0
 
 
 def test_lng():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     assert w.lng == -1
 
 
 @raises(AttributeError)
 def test_lng_set():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     w.lng = 0
 
 
 def test_lngtyp():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     assert w.lngtyp == b("    ")
 
 
 @raises(AttributeError)
 def test_lngtyp_set():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     w.lngtyp = 0
 
 
 def test_lonpole():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     assert np.isnan(w.lonpole)
     w.lonpole = 45.0
     assert w.lonpole == 45.0
@@ -420,7 +436,7 @@ def test_lonpole():
 
 
 def test_mjdavg():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     assert np.isnan(w.mjdavg)
     w.mjdavg = 45.0
     assert w.mjdavg == 45.0
@@ -429,7 +445,7 @@ def test_mjdavg():
 
 
 def test_mjdobs():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     assert np.isnan(w.mjdobs)
     w.mjdobs = 45.0
     assert w.mjdobs == 45.0
@@ -438,25 +454,25 @@ def test_mjdobs():
 
 
 def test_name():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     assert w.name == b('')
     w.name = b('foo')
     assert w.name == b('foo')
 
 
 def test_naxis():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     assert w.naxis == 2
 
 
 @raises(AttributeError)
 def test_naxis_set():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     w.naxis = 4
 
 
 def test_obsgeo():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     assert np.all(np.isnan(w.obsgeo))
     w.obsgeo = [1, 2, 3]
     assert_array_equal(w.obsgeo, [1, 2, 3])
@@ -465,7 +481,7 @@ def test_obsgeo():
 
 
 def test_pc():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     assert w.has_pc()
     assert_array_equal(w.pc, [[1, 0], [0, 1]])
     w.cd = [[1, 0], [0, 1]]
@@ -477,14 +493,14 @@ def test_pc():
 
 @raises(AttributeError)
 def test_pc_missing():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     w.cd = [[1, 0], [0, 1]]
     assert not w.has_pc()
     w.pc
 
 
 def test_phi0():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     assert np.isnan(w.phi0)
     w.phi0 = 42.0
     assert w.phi0 == 42.0
@@ -494,89 +510,90 @@ def test_phi0():
 
 @raises(AssertionError)
 def test_piximg_matrix():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     w.piximg_matrix
 
 
 @raises(AttributeError)
 def test_piximg_matrix():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     w.piximg_matrix = None
 
 
 def test_print_contents():
     # In general, this is human-consumable, so we don't care if the
     # content changes, just check the type
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     assert isinstance(str(w), str)
 
 
 def test_radesys():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     assert w.radesys == b('')
     w.radesys = b('foo')
     assert w.radesys == b('foo')
 
 
 def test_restfrq():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     assert w.restfrq == 0.0
     w.restfrq = np.nan
     assert np.isnan(w.restfrq)
 
 
 def test_restwav():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     assert w.restwav == 0.0
     w.restwav = np.nan
     assert np.isnan(w.restwav)
 
 
 def test_set_ps():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     data = [(0, 0, "param1"), (1, 1, "param2")]
     w.set_ps(data)
     assert w.get_ps() == data
 
 
 def test_set_ps_realloc():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     w.set_ps([(0, 0, "param1")] * 16)
 
 
 def test_set_pv():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     data = [(0, 0, 42.), (1, 1, 54.)]
     w.set_pv(data)
     assert w.get_pv() == data
 
 
 def test_set_pv_realloc():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     w.set_pv([(0, 0, 42.)] * 16)
 
 
 def test_spcfix():
     # TODO: We need some data with broken spectral headers here to
     # really test
-    header = get_data_contents('spectra/orion-velo-1.hdr')
-    w = _wcs._Wcsprm(header)
+    header = get_pkg_data_contents(
+        'spectra/orion-velo-1.hdr', encoding='binary')
+    w = _wcs.Wcsprm(header)
     assert w.spcfix() == -1
 
 
 def test_spec():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     assert w.spec == -1
 
 
 @raises(AttributeError)
 def test_spec_set():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     w.spec = 0
 
 
 def test_specsys():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     assert w.specsys == b('')
     w.specsys = b('foo')
     assert w.specsys == b('foo')
@@ -588,27 +605,27 @@ def test_sptr():
 
 
 def test_ssysobs():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     assert w.ssysobs == b('')
     w.ssysobs = b('foo')
     assert w.ssysobs == b('foo')
 
 
 def test_ssyssrc():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     assert w.ssyssrc == b('')
     w.ssyssrc = b('foo')
     assert w.ssyssrc == b('foo')
 
 
 def test_tab():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     assert len(w.tab) == 0
     # TODO: Inject some headers that have tables and test
 
 
 def test_theta0():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     assert np.isnan(w.theta0)
     w.theta0 = 42.0
     assert w.theta0 == 42.0
@@ -617,12 +634,12 @@ def test_theta0():
 
 
 def test_toheader():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     assert isinstance(w.to_header(), str)
 
 
 def test_velangl():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     assert w.velangl == 0.0
     w.velangl = 42.0
     assert w.velangl == 42.0
@@ -631,7 +648,7 @@ def test_velangl():
 
 
 def test_velosys():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     assert np.isnan(w.velosys)
     w.velosys = 42.0
     assert w.velosys == 42.0
@@ -640,7 +657,7 @@ def test_velosys():
 
 
 def test_zsource():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     assert np.isnan(w.zsource)
     w.zsource = 42.0
     assert w.zsource == 42.0
@@ -649,16 +666,16 @@ def test_zsource():
 
 
 def test_cd_3d():
-    header = get_data_contents('data/3d_cd.hdr')
-    w = _wcs._Wcsprm(header)
+    header = get_pkg_data_contents('data/3d_cd.hdr', encoding='binary')
+    w = _wcs.Wcsprm(header)
     assert w.cd.shape == (3, 3)
     assert w.get_pc().shape == (3, 3)
     assert w.get_cdelt().shape == (3,)
 
 
 def test_get_pc():
-    header = get_data_contents('data/3d_cd.hdr')
-    w = _wcs._Wcsprm(header)
+    header = get_pkg_data_contents('data/3d_cd.hdr', encoding='binary')
+    w = _wcs.Wcsprm(header)
     pc = w.get_pc()
     try:
         pc[0, 0] = 42
@@ -667,15 +684,35 @@ def test_get_pc():
     else:
         raise AssertionError()
 
+
 @raises(_wcs.SingularMatrixError)
 def test_detailed_err():
-    w = _wcs._Wcsprm()
+    w = _wcs.Wcsprm()
     w.pc = [[0, 0], [0, 0]]
     w.set()
 
 
 def test_header_parse():
     from astropy.io import fits
-    hdulist = fits.open(get_data_fileobj('data/header_newlines.fits'))
-    w = wcs.WCS(hdulist[0].header)
-    assert w.wcs.ctype[0] == b'RA---TAN-SIP'
+    with get_pkg_data_fileobj(
+            'data/header_newlines.fits', encoding='binary') as test_file:
+        hdulist = fits.open(test_file)
+        w = wcs.WCS(hdulist[0].header)
+        assert w.wcs.ctype[0] == b'RA---TAN-SIP'
+
+
+def test_locale():
+    orig_locale = locale.getlocale(locale.LC_NUMERIC)[0]
+
+    try:
+        locale.setlocale(locale.LC_NUMERIC, 'fr_FR')
+    except:
+        pytest.xfail(
+            "Can't set to 'fr_FR' locale, perhaps because it is not installed "
+            "on this system")
+    try:
+        header = get_pkg_data_contents('data/locale.hdr', encoding='binary')
+        w = _wcs.Wcsprm(header)
+        assert re.search("[0-9]+,[0-9]*", w.to_header()) is None
+    finally:
+        locale.setlocale(locale.LC_NUMERIC, orig_locale)
diff --git a/astropy/wcs/wcs.py b/astropy/wcs/wcs.py
index 6494546..259d3fc 100644
--- a/astropy/wcs/wcs.py
+++ b/astropy/wcs/wcs.py
@@ -45,12 +45,13 @@ try:
     from . import _wcs
 except ImportError:
     _wcs = None
-from ..utils import deprecated
+from ..utils import deprecated, deprecated_attribute
+from .. import log
 
 if _wcs is not None:
     assert _wcs._sanity_check(), \
-           "astropy.wcs did not pass its sanity check for your build " \
-           "on your platform."
+        "astropy.wcs did not pass its sanity check for your build " \
+        "on your platform."
 
 if sys.version_info[0] >= 3:  # pragma: py3
     string_types = (bytes, str)
@@ -68,7 +69,7 @@ if _wcs is not None:
     DistortionLookupTable = _wcs.DistortionLookupTable
     Sip = _wcs.Sip
     UnitConverter = _wcs.UnitConverter
-    Wcsprm = _wcs._Wcsprm
+    Wcsprm = _wcs.Wcsprm
     Tabprm = _wcs.Tabprm
     # Copy all the constants from the C extension into this module's namespace
     for key, val in _wcs.__dict__.items():
@@ -77,6 +78,10 @@ if _wcs is not None:
             key.startswith('WCSHDO')):
             locals()[key] = val
             __all__.append(key)
+
+    UnitConverter = deprecated(
+        '0.2', name='UnitConverter', alternative='astropy.units')(
+            UnitConverter)
 else:
     WCSBase = object
     Wcsprm = object
@@ -86,6 +91,10 @@ else:
     Tabprm = object
 
 
+# Additional relax bit flags
+WCSHDO_SIP = 0x10000
+
+
 def _parse_keysel(keysel):
     keysel_flags = 0
     if keysel is not None:
@@ -122,7 +131,7 @@ class WCS(WCSBase):
 
     Parameters
     ----------
-    header : astropy.io.fits header object, string or None, optional
+    header : astropy.io.fits header object, string, dict-like, or None, optional
         If *header* is not provided or None, the object will be
         initialized to default values.
 
@@ -210,14 +219,40 @@ class WCS(WCSBase):
 
     Notes
     -----
-    astropy.wcs supports arbitrary *n* dimensions for the core WCS
-    (the transformations handled by WCSLIB).  However, the Paper IV
-    lookup table and SIP distortions must be two dimensional.
-    Therefore, if you try to create a WCS object where the core WCS
-    has a different number of dimensions than 2 and that object also
-    contains a Paper IV lookup table or SIP distortion, a `ValueError`
-    exception will be raised.  To avoid this, consider using the
-    *naxis* kwarg to select two dimensions from the core WCS.
+
+    1. astropy.wcs supports arbitrary *n* dimensions for the core WCS
+       (the transformations handled by WCSLIB).  However, the Paper IV
+       lookup table and SIP distortions must be two dimensional.
+       Therefore, if you try to create a WCS object where the core WCS
+       has a different number of dimensions than 2 and that object
+       also contains a Paper IV lookup table or SIP distortion, a
+       `ValueError` exception will be raised.  To avoid this, consider
+       using the *naxis* kwarg to select two dimensions from the core
+       WCS.
+
+    2. The number of coordinate axes in the transformation is not
+       determined directly from the ``NAXIS`` keyword but instead from
+       the highest of:
+
+           - ``NAXIS`` keyword
+
+           - ``WCSAXESa`` keyword
+
+           - The highest axis number in any parameterized WCS keyword.
+             The keyvalue, as well as the keyword, must be
+             syntactically valid otherwise it will not be considered.
+
+       If none of these keyword types is present, i.e. if the header
+       only contains auxiliary WCS keywords for a particular
+       coordinate representation, then no coordinate description is
+       constructed for it.
+
+       The number of axes, which is set as the `naxis` member, may
+       differ for different coordinate representations of the same
+       image.
+
+    3. When the header includes duplicate keywords, in most cases the
+       last encountered is used.
     """
 
     def __init__(self, header=None, fobj=None, key=' ', minerr=0.0,
@@ -226,8 +261,8 @@ class WCS(WCSBase):
         if header is None:
             if naxis is None:
                 naxis = 2
-            wcsprm = _wcs._Wcsprm(header=None, key=key,
-                                  relax=relax, naxis=naxis)
+            wcsprm = _wcs.Wcsprm(header=None, key=key,
+                                 relax=relax, naxis=naxis)
             self.naxis = wcsprm.naxis
             # Set some reasonable defaults.
             det2im = (None, None)
@@ -244,27 +279,42 @@ class WCS(WCSBase):
                             "argument 1 and a FITS file object to argument 2")
                     fobj = fits.open(header)
                     header = fobj[0].header
-                    header_string = repr(header.ascard).encode('latin1')
+                    header_string = header.tostring()
                 else:
                     header_string = header
             elif isinstance(header, fits.Header):
-                header_string = repr(header.ascard).encode('latin1')
+                header_string = header.tostring()
             else:
-                raise TypeError(
-                    "header must be a string or an astropy.io.fits.Header "
-                    "object")
+                try:
+                    # Accept any dict-like object
+                    new_header = fits.Header()
+                    for dict_key in header:
+                        new_header[dict_key] = header[dict_key]
+                    header_string = new_header.tostring()
+                except TypeError:
+                    raise TypeError(
+                        "header must be a string, an astropy.io.fits.Header "
+                        "object, or a dict-like object")
+
+            if isinstance(header_string, unicode):
+                header_bytes = header_string.encode('ascii')
+                header_string = header_string
+            else:
+                header_bytes = header_string
+                header_string = header_string.decode('ascii')
+
             try:
-                wcsprm = _wcs._Wcsprm(header=header_string, key=key,
-                                      relax=relax, keysel=keysel_flags,
-                                      colsel=colsel)
+                wcsprm = _wcs.Wcsprm(header=header_bytes, key=key,
+                                     relax=relax, keysel=keysel_flags,
+                                     colsel=colsel)
             except _wcs.NoWcsKeywordsFoundError:
                 # The header may have SIP or distortions, but no core
                 # WCS.  That isn't an error -- we want a "default"
                 # (identity) core Wcs transformation in that case.
                 if colsel is None:
-                    wcsprm = _wcs._Wcsprm(header=None, key=key,
-                                          relax=relax, keysel=keysel_flags,
-                                          colsel=colsel)
+                    wcsprm = _wcs.Wcsprm(header=None, key=key,
+                                         relax=relax, keysel=keysel_flags,
+                                         colsel=colsel)
                 else:
                     raise
 
@@ -272,7 +322,9 @@ class WCS(WCSBase):
                 wcsprm = wcsprm.sub(naxis)
             self.naxis = wcsprm.naxis
 
-            det2im = self._read_det2im_kw(header, fobj)
+            header = fits.Header.fromstring(header_string)
+
+            det2im = self._read_det2im_kw(header, fobj, err=minerr)
             cpdis = self._read_distortion_kw(
                 header, fobj, dist='CPDIS', err=minerr)
             sip = self._read_sip_kw(header)
@@ -287,6 +339,13 @@ distortion, you must select or reduce these to 2 dimensions using the
 naxis kwarg.
 """.format(wcsprm.naxis))
 
+            header_naxis = header.get('NAXIS', None)
+            if header_naxis is not None and header_naxis < wcsprm.naxis:
+                log.info(
+                    "The WCS transformation has more axes ({0:d}) than the "
+                    "image it is associated with ({1:d})".format(
+                        wcsprm.naxis, header_naxis))
+
         if fix:
             fixes = wcsprm.fix()
             for key, val in fixes.iteritems():
@@ -297,7 +356,7 @@ naxis kwarg.
                         format(key, val),
                         FITSFixedWarning)
 
-        self.get_naxis(header)
+        self._get_naxis(header)
         WCSBase.__init__(self, sip, cpdis, wcsprm, det2im)
 
     def __copy__(self):
@@ -347,9 +406,9 @@ naxis kwarg.
         copy.naxis = copy.wcs.naxis
         return copy
     if _wcs is not None:
-        sub.__doc__ = _wcs._Wcsprm.sub.__doc__
+        sub.__doc__ = _wcs.Wcsprm.sub.__doc__
 
-    def calcFootprint(self, header=None, undistort=True):
+    def calcFootprint(self, header=None, undistort=True, axes=None):
         """
         Calculates the footprint of the image on the sky.
 
@@ -365,22 +424,31 @@ naxis kwarg.
             If `True`, take SIP and distortion lookup table into
             account
 
+        axes : length 2 sequence ints, optional
+            If provided, use the given sequence as the shape of the
+            image.  Otherwise, use the ``NAXIS1`` and ``NAXIS2``
+            keywords from the header that was used to create this
+            `WCS` object.
+
         Returns
         -------
         coord : (4, 2) array of (*x*, *y*) coordinates.
         """
-        if header is None:
-            try:
-                # classes that inherit from WCS and define naxis1/2
-                # do not require a header parameter
-                naxis1 = self.naxis1
-                naxis2 = self.naxis2
-            except AttributeError:
-                print("Need a valid header in order to calculate footprint\n")
-                return None
+        if axes is not None:
+            naxis1, naxis2 = axes
         else:
-            naxis1 = header.get('NAXIS1', None)
-            naxis2 = header.get('NAXIS2', None)
+            if header is None:
+                try:
+                    # classes that inherit from WCS and define naxis1/2
+                    # do not require a header parameter
+                    naxis1 = self._naxis1
+                    naxis2 = self._naxis2
+                except AttributeError:
+                    print("Need a valid header in order to calculate footprint\n")
+                    return None
+            else:
+                naxis1 = header.get('NAXIS1', None)
+                naxis2 = header.get('NAXIS2', None)
 
         corners = np.zeros(shape=(4, 2), dtype=np.float64)
         if naxis1 is None or naxis2 is None:
@@ -399,7 +467,7 @@ naxis kwarg.
         else:
             return self.wcs_pix2world(corners, 1)
 
-    def _read_det2im_kw(self, header, fobj):
+    def _read_det2im_kw(self, header, fobj, err=0.0):
         """
         Create a `Paper IV`_ type lookup table for detector to image
         plane correction.
@@ -415,6 +483,10 @@ naxis kwarg.
         if not isinstance(fobj, fits.HDUList):
             return (None, None)
 
+        d_error = header.get('D2IMERR', 0.0)
+        if d_error < err:
+            return (None, None)
+
         try:
             d2im_data = fobj[('D2IMARR', 1)].data
         except KeyError:
@@ -547,21 +619,46 @@ naxis kwarg.
             if cpdis is None:
                 return
 
-            hdulist[0].header.update('{0}{1:d}'.format(dist, num), 'LOOKUP')
-            hdulist[0].header.update('{0}{1:d}.EXTVER'.format(d_kw, num),
-                                     len(hdulist))
-            hdulist[0].header.update('{0}{1:d}.AXIS.{1:d}'.format(d_kw, num),
-                                     num)
+            hdulist[0].header.update(
+                '{0}{1:d}'.format(dist, num),
+                ('LOOKUP', 'Prior distortion function type'))
+            hdulist[0].header.update(
+                '{0}{1:d}.EXTVER'.format(d_kw, num),
+                (num, 'Version number of WCSDVARR extension'))
+            hdulist[0].header.update(
+                '{0}{1:d}.NAXES'.format(d_kw, num),
+                (len(cpdis.data.shape),
+                 'Number of independent variables in distortion function'))
+
+            for i in range(cpdis.data.ndim):
+                hdulist[0].header.update(
+                    '{0}{1:d}.AXIS.{2:d}'.format(d_kw, num, i + 1),
+                    (i + 1, 'Axis number of the jth independent variable in a '
+                     'distortion function'))
 
             image = fits.ImageHDU(cpdis.data, name='WCSDVARR')
             header = image.header
 
-            header.update('CRPIX1', cpdis.crpix[0])
-            header.update('CRPIX2', cpdis.crpix[1])
-            header.update('CRVAL1', cpdis.crval[0])
-            header.update('CRVAL2', cpdis.crval[1])
-            header.update('CDELT1', cpdis.cdelt[0])
-            header.update('CDELT2', cpdis.cdelt[1])
+            header.update(
+                'CRPIX1',
+                (cpdis.crpix[0], 'Coordinate system reference pixel'))
+            header.update(
+                'CRPIX2',
+                (cpdis.crpix[1], 'Coordinate system reference pixel'))
+            header.update(
+                'CRVAL1',
+                (cpdis.crval[0], 'Coordinate system value at reference pixel'))
+            header.update(
+                'CRVAL2',
+                (cpdis.crval[1], 'Coordinate system value at reference pixel'))
+            header.update(
+                'CDELT1',
+                (cpdis.cdelt[0], 'Coordinate increment along axis'))
+            header.update(
+                'CDELT2',
+                (cpdis.cdelt[1], 'Coordinate increment along axis'))
+            image.update_ext_version(
+                int(hdulist[0].header['{0}{1:d}.EXTVER'.format(d_kw, num)]))
 
             hdulist.append(image)
 
@@ -659,7 +756,8 @@ naxis kwarg.
             for i in range(size):
                 for j in range(size - i):
                     if a[i, j] != 0.0:
-                        keywords['{0}_{1:d}_{2:d}'.format(name, i, j)] = a[i, j]
+                        keywords[
+                            '{0}_{1:d}_{2:d}'.format(name, i, j)] = a[i, j]
 
         write_array('A', self.sip.a)
         write_array('B', self.sip.b)
@@ -735,7 +833,11 @@ naxis kwarg.
         A helper function to support reading either a pair of arrays
         or a single Nx2 array.
         """
-        ra_dec_order = kwargs.get('ra_dec_order')
+        ra_dec_order = kwargs.pop('ra_dec_order', False)
+        if len(kwargs):
+            raise TypeError("Unexpected keyword argument {0!r}".format(
+                kwargs.keys()[0]))
+
         if len(args) == 2:
             xy, origin = args
             try:
@@ -743,37 +845,46 @@ naxis kwarg.
                 origin = int(origin)
             except:
                 raise TypeError(
-                    "When providing two arguments, they must be (xy, origin)")
+                    "When providing two arguments, they must be "
+                    "(coords[N][{0}], origin)".format(self.naxis))
             if ra_dec_order and sky == 'input':
                 xy = self._denormalize_sky(xy)
             result = func(xy, origin)
             if ra_dec_order and sky == 'output':
                 result = self._normalize_sky(result)
             return result
-        elif len(args) == 3:
-            x, y, origin = args
+        elif len(args) == self.naxis + 1:
+            axes = args[:-1]
+            origin = args[-1]
             try:
-                x = np.asarray(x)
-                y = np.asarray(y)
+                axes = [np.asarray(x) for x in axes]
                 origin = int(origin)
             except:
                 raise TypeError(
-                    "When providing three arguments, they must be " +
-                    "(x, y, origin)")
-            if x.size != y.size:
-                raise ValueError("x and y arrays are not the same size")
-            length = x.size
-            xy = np.hstack((x.reshape((length, 1)),
-                            y.reshape((length, 1))))
+                    "When providing more than two arguments, they must be " +
+                    "a 1-D array for each axis, followed by an origin.")
+
+            try:
+                axes = np.broadcast_arrays(*axes)
+            except ValueError:
+                raise ValueError(
+                    "Coordinate arrays are not broadcastable to each other")
+
+            xy = np.hstack([x.reshape((x.size, 1)) for x in axes])
+
             if ra_dec_order and sky == 'input':
                 xy = self._denormalize_sky(xy)
             sky = func(xy, origin)
             if ra_dec_order and sky == 'output':
                 sky = self._normalize_sky_output(sky)
-                return sky[:, 0], sky[:, 1]
-            return [sky[:, i] for i in range(sky.shape[1])]
+                return (sky[:, 0].reshape(axes[0].shape),
+                        sky[:, 1].reshape(axes[0].shape))
+            return [sky[:, i].reshape(axes[0].shape)
+                    for i in range(sky.shape[1])]
+
         raise TypeError(
-            "Expected 2 or 3 arguments, {0} given".format(len(args)))
+            "Expected 2 or {0} arguments, {0} given".format(
+                self.naxis + 1, len(args)))
 
     def all_pix2world(self, *args, **kwargs):
         return self._array_converter(
@@ -839,7 +950,7 @@ naxis kwarg.
 
         InvalidTransformError
             Ill-conditioned coordinate transformation parameters.
-        """.format(__.TWO_OR_THREE_ARGS('naxis', 8),
+        """.format(__.TWO_OR_MORE_ARGS('naxis', 8),
                    __.RA_DEC_ORDER(8),
                    __.RETURNS('sky coordinates, in degrees', 8))
 
@@ -912,7 +1023,7 @@ naxis kwarg.
         `~astropy.wcs.Wcsprm.lattyp` and `~astropy.wcs.Wcsprm.lngtyp`
         members can be used to determine the order of the axes.
 
-        """.format(__.TWO_OR_THREE_ARGS('naxis', 8),
+        """.format(__.TWO_OR_MORE_ARGS('naxis', 8),
                    __.RA_DEC_ORDER(8),
                    __.RETURNS('world coordinates, in degrees', 8))
 
@@ -979,7 +1090,7 @@ naxis kwarg.
 
         InvalidTransformError
             Ill-conditioned coordinate transformation parameters.
-        """.format(__.TWO_OR_THREE_ARGS('naxis', 8),
+        """.format(__.TWO_OR_MORE_ARGS('naxis', 8),
                    __.RA_DEC_ORDER(8),
                    __.RETURNS('pixel coordinates', 8))
 
@@ -987,8 +1098,8 @@ naxis kwarg.
     def wcs_sky2pix(self, *args, **kwargs):
         return self.wcs_world2pix(*args, **kwargs)
 
-    def pix2foc(self, *args, **kwargs):
-        return self._array_converter(self._pix2foc, None, *args, **kwargs)
+    def pix2foc(self, *args):
+        return self._array_converter(self._pix2foc, None, *args)
     pix2foc.__doc__ = """
         Convert pixel coordinates to focal plane coordinates using the
         `SIP`_ polynomial distortion convention and `Paper IV`_
@@ -1011,11 +1122,11 @@ naxis kwarg.
 
         ValueError
             Invalid coordinate transformation parameters.
-        """.format(__.TWO_OR_THREE_ARGS('2', 8),
+        """.format(__.TWO_OR_MORE_ARGS('2', 8),
                    __.RETURNS('focal coordinates', 8))
 
-    def p4_pix2foc(self, *args, **kwargs):
-        return self._array_converter(self._p4_pix2foc, None, *args, **kwargs)
+    def p4_pix2foc(self, *args):
+        return self._array_converter(self._p4_pix2foc, None, *args)
     p4_pix2foc.__doc__ = """
         Convert pixel coordinates to focal plane coordinates using
         `Paper IV`_ table-lookup distortion correction.
@@ -1037,11 +1148,11 @@ naxis kwarg.
 
         ValueError
             Invalid coordinate transformation parameters.
-        """.format(__.TWO_OR_THREE_ARGS('2', 8),
+        """.format(__.TWO_OR_MORE_ARGS('2', 8),
                    __.RETURNS('focal coordinates', 8))
 
-    def det2im(self, *args, **kwargs):
-        return self._array_converter(self._det2im, None, *args, **kwargs)
+    def det2im(self, *args):
+        return self._array_converter(self._det2im, None, *args)
     det2im.__doc__ = """
         Convert detector coordinates to image plane coordinates using
         `Paper IV`_ table-lookup distortion correction.
@@ -1063,10 +1174,10 @@ naxis kwarg.
 
         ValueError
             Invalid coordinate transformation parameters.
-        """.format(__.TWO_OR_THREE_ARGS('2', 8),
+        """.format(__.TWO_OR_MORE_ARGS('2', 8),
                    __.RETURNS('pixel coordinates', 8))
 
-    def sip_pix2foc(self, *args, **kwargs):
+    def sip_pix2foc(self, *args):
         if self.sip is None:
             if len(args) == 2:
                 return args[0]
@@ -1074,7 +1185,7 @@ naxis kwarg.
                 return args[:2]
             else:
                 raise TypeError("Wrong number of arguments")
-        return self._array_converter(self.sip.pix2foc, None, *args, **kwargs)
+        return self._array_converter(self.sip.pix2foc, None, *args)
     sip_pix2foc.__doc__ = """
         Convert pixel coordinates to focal plane coordinates using the
         `SIP`_ polynomial distortion convention.
@@ -1102,10 +1213,10 @@ naxis kwarg.
 
         ValueError
             Invalid coordinate transformation parameters.
-        """.format(__.TWO_OR_THREE_ARGS('2', 8),
+        """.format(__.TWO_OR_MORE_ARGS('2', 8),
                    __.RETURNS('focal coordinates', 8))
 
-    def sip_foc2pix(self, *args, **kwargs):
+    def sip_foc2pix(self, *args):
         if self.sip is None:
             if len(args) == 2:
                 return args[0]
@@ -1113,7 +1224,7 @@ naxis kwarg.
                 return args[:2]
             else:
                 raise TypeError("Wrong number of arguments")
-        return self._array_converter(self.sip.foc2pix, None, *args, **kwargs)
+        return self._array_converter(self.sip.foc2pix, None, *args)
     sip_foc2pix.__doc__ = """
         Convert focal plane coordinates to pixel coordinates using the
         `SIP`_ polynomial distortion convention.
@@ -1139,7 +1250,7 @@ naxis kwarg.
 
         ValueError
             Invalid coordinate transformation parameters.
-        """.format(__.TWO_OR_THREE_ARGS('2', 8),
+        """.format(__.TWO_OR_MORE_ARGS('2', 8),
                    __.RETURNS('pixel coordinates', 8))
 
     def to_fits(self, relax=False):
@@ -1245,13 +1356,19 @@ naxis kwarg.
           8. Keyword order may be changed.
         """
 
+        do_sip = (relax is True or
+                  relax == WCSHDO_all or
+                  (relax & WCSHDO_SIP))
+        if relax not in (True, False):
+            relax &= ~WCSHDO_SIP
+
         if self.wcs is not None:
             header_string = self.wcs.to_header(relax)
             header = fits.Header.fromstring(header_string)
         else:
             header = fits.Header()
 
-        if self.sip is not None:
+        if do_sip and self.sip is not None:
             for key, val in self._write_sip_kw().items():
                 header.update(key, val)
 
@@ -1295,12 +1412,19 @@ naxis kwarg.
         f.write(') # color={0}, width={1:d} \n'.format(color, width))
         f.close()
 
+    naxis1 = deprecated_attribute('naxis1', '0.2')
+    naxis2 = deprecated_attribute('naxis2', '0.2')
+
+    @deprecated('0.2', message='This method should not be public')
     def get_naxis(self, header=None):
-        self.naxis1 = 0.0
-        self.naxis2 = 0.0
-        if header != None and not isinstance(header, string_types):
-            self.naxis1 = header.get('NAXIS1', 0.0)
-            self.naxis2 = header.get('NAXIS2', 0.0)
+        return self._get_naxis(header=header)
+
+    def _get_naxis(self, header=None):
+        self._naxis1 = 0
+        self._naxis2 = 0
+        if header is not None and not isinstance(header, string_types):
+            self.naxis1 = header.get('NAXIS1', 0)
+            self.naxis2 = header.get('NAXIS2', 0)
 
     def rotateCD(self, theta):
         _theta = np.deg2rad(theta)
@@ -1329,7 +1453,7 @@ naxis kwarg.
 
     def get_axis_types(self):
         """
-        Similar to `self.wcsprm.axis_types <_wcs._Wcsprm.axis_types>`
+        Similar to `self.wcsprm.axis_types <_wcs.Wcsprm.axis_types>`
         but provides the information in a more Python-friendly format.
 
         Returns
diff --git a/cextern/cfitsio/License.txt b/cextern/cfitsio/License.txt
new file mode 100644
index 0000000..2f5f48d
--- /dev/null
+++ b/cextern/cfitsio/License.txt
@@ -0,0 +1,25 @@
+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.
diff --git a/cextern/cfitsio/adler32.c b/cextern/cfitsio/adler32.c
new file mode 100644
index 0000000..172de60
--- /dev/null
+++ b/cextern/cfitsio/adler32.c
@@ -0,0 +1,167 @@
+/* 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);
+}
diff --git a/cextern/cfitsio/buffers.c b/cextern/cfitsio/buffers.c
new file mode 100644
index 0000000..8d80f46
--- /dev/null
+++ b/cextern/cfitsio/buffers.c
@@ -0,0 +1,1371 @@
+/*  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 <string.h>
+#include <stdlib.h>
+#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);
+
+    cptr = (char *)buffer;
+    ntodo =  (long) nbytes;
+
+    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[81];
+
+    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)
+            {
+                 sprintf(message,
+                 "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);
+}
+
diff --git a/cextern/cfitsio/cfileio.c b/cextern/cfitsio/cfileio.c
new file mode 100644
index 0000000..ca081a0
--- /dev/null
+++ b/cextern/cfitsio/cfileio.c
@@ -0,0 +1,6859 @@
+/*  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 <string.h>
+#include <stdlib.h>
+#include <math.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stddef.h>  /* apparently needed to define size_t */
+#include "fitsio2.h"
+#include "group.h"
+
+#define MAX_PREFIX_LEN 20  /* max length of file type prefix (e.g. 'http://') */
+#define MAX_DRIVERS 24     /* 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);
+
+
+#ifdef _REENTRANT
+
+pthread_mutex_t Fitsio_InitLock = PTHREAD_MUTEX_INITIALIZER;
+
+#endif
+
+/*--------------------------------------------------------------------------*/
+int fitsio_init_lock(void)
+{
+  static int need_to_init = 1;
+  
+#ifdef _REENTRANT
+
+  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 */
+
+    assert(!pthread_mutexattr_init(&mutex_init));
+#ifdef linux
+    assert(!pthread_mutexattr_settype(&mutex_init,
+				     PTHREAD_MUTEX_RECURSIVE_NP));
+#else
+    assert(!pthread_mutexattr_settype(&mutex_init,
+				     PTHREAD_MUTEX_RECURSIVE));
+#endif
+
+    assert(!pthread_mutex_init(&Fitsio_Lock,&mutex_init));
+    need_to_init = 0;
+  }
+
+  FFUNLOCK1(Fitsio_InitLock);
+
+#endif
+
+    return(0);
+}
+/*--------------------------------------------------------------------------*/
+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)
+        {
+          sprintf(errmsg,
+          " extension number %d doesn't exist or couldn't be opened.",extnum);
+          ffpmsg(errmsg);
+        }
+        else
+        {
+          sprintf(errmsg,
+          " extension with EXTNAME = %s,", extname);
+          ffpmsg(errmsg);
+
+          if (extvers)
+          {
+             sprintf(errmsg,
+             "           and with EXTVERS = %d,", extvers);
+             ffpmsg(errmsg);
+          }
+
+          if (movetotype != ANY_HDU)
+          {
+             sprintf(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 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(double version,   /* I - CFITSIO version number, from the    */
+                                 /*     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 version of fitsio.h used to build the CFITSIO library
+  is the same as the version used in building the application program that
+  links to the library.
+*/
+{
+    if (version != CFITSIO_VERSION)
+    {
+        printf("ERROR: Mismatch in the version of the fitsio.h include file used to build\n");
+	printf("the CFITSIO library, and the version included by the application program:\n");
+	printf("   Version used to build the CFITSIO library   = %f\n",CFITSIO_VERSION);
+	printf("   Version included by the application program = %f\n",version);
+	
+        *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];
+    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';
+    }
+    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. */
+	
+        fits_parse_input_filename(url, urltype, infile, outfile, extspec,
+              rowfilter, binspec, colspec, pixfilter, 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)
+        {
+          sprintf(errmsg,
+          " extension number %d doesn't exist or couldn't be opened.",extnum);
+          ffpmsg(errmsg);
+        }
+        else
+        {
+          sprintf(errmsg,
+          " extension with EXTNAME = %s,", extname);
+          ffpmsg(errmsg);
+
+          if (extvers)
+          {
+             sprintf(errmsg,
+             "           and with EXTVERS = %d,", extvers);
+             ffpmsg(errmsg);
+          }
+
+          if (movetotype != ANY_HDU)
+          {
+             sprintf(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")) &&
+                    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 */
+
+       /* add some HISTORY; fits_copy_image_cell also wrote HISTORY keywords */
+       
+/*  disable this; leave it up to calling routine to write any HISTORY keywords
+       if (*extname)
+        sprintf(card,"HISTORY  in HDU '%.16s' of file '%.36s'",extname,infile);
+       else
+        sprintf(card,"HISTORY  in HDU %d of file '%.45s'", extnum, infile);
+
+       ffprec(*fptr, card, status);
+*/
+    }
+
+    /* --------------------------------------------------------------------- */
+    /* 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);
+
+          return *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);
+       }
+    }
+
+    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(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(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);
+}
+/*--------------------------------------------------------------------------*/
+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[FLEN_FILENAME], 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 */
+
+    /* parse expression and get first clause, if more than 1 */
+
+    while ((slen = fits_get_token(&cptr, ";", clause, NULL)) > 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 );
+                    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 );
+                    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 );
+                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");
+		    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) 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 );
+               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 );
+                      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 );
+                        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");
+                        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 (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 );
+             return(*status);
+           }
+         }
+       }
+    }
+
+    if( colindex ) free( colindex );
+    if( file_expr ) free( file_expr );
+    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  */
+    sprintf(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;
+      sprintf(tform, "%.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<naxis; ii++) if (naxes[ii] != naxes1[ii]) {
+	ffpmsg("Input image dimensions and output table cell dimensions do not match.");
+	return (*status = BAD_DIMEN);
+      }
+
+      ffgtclll(newptr, colnum, &typecode1, &repeat1, &width1, status);
+      if ((*status > 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;
+
+    sprintf(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);
+    sprintf(filename+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;
+    long tilesize[MAX_COMPRESS_DIM] = {0,1,1,1,1,1};
+    float qlevel = 0.0, 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++;
+                  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 != 0.0)
+        fits_set_quantize_level(fptr, qlevel, 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.
+*/
+{
+    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;
+
+    if (*status > 0)
+        return(*status);
+
+    if (*status == CREATE_DISK_FILE)
+    {
+       create_disk_file = 1;
+       *status = 0;
+    }
+
+    *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 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);
+    }
+
+    /* 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 *size),
+	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 is big and ugly and should be redesigned someday!
+*/
+{
+	return fits_parse_input_filename(url, urltype, infilex, outfile,
+               extspec, rowfilterx, binspec, colspec, 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 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;
+
+
+    /* 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';
+ 
+    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 (!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, 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")]
+
+         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;
+
+           if (*tmptr == '@')  /* test for leading @ symbol */
+               hasAt = 1;
+
+           if ( !strncasecmp(tmptr, "col ", 4) )
+              colStart = 1;
+
+           if ( !strncasecmp(tmptr, "bin", 3) )
+              binStart = 1;
+
+           if ( !strncasecmp(tmptr, "pix", 3) )
+              pixStart = 1;
+
+           if ( !strncasecmp(tmptr, "gtifilter(", 10) ||
+                !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 ||
+                (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 */
+    }
+
+
+    /* 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;
+   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 ) {
+      sprintf(line,"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 ((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'))  {
+	        strcpy(tval, token);
+
+	        /*  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 = 0;
+
+    if (!fptr)
+        return(*status = NULL_INPUT_PTR);
+    else if ((fptr->Fptr)->validcode != VALIDSTRUC) /* check for magic value */
+        return(*status = BAD_FILEPTR); 
+
+    ffchdu(fptr, status);    /* close the current HDU, ignore any errors */
+    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, &tstatus);
+
+       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.
+*/
+{
+    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);
+}
diff --git a/cextern/cfitsio/changes.txt b/cextern/cfitsio/changes.txt
new file mode 100644
index 0000000..71ea413
--- /dev/null
+++ b/cextern/cfitsio/changes.txt
@@ -0,0 +1,3807 @@
+                   Log of Changes Made to CFITSIO
+
+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.
+
+   - Implimented 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 running
+     on x86 PCs) where byte-swapping is required.  This has no effect on big-endian 
+     machines (e.g., Macs).  Even faster 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 chracters).
+
+   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 histrogram image will have a floating
+     point datatype, not the default integer datatype as is the case when no
+     weigth 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 convension, 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 chracters)
+
+    - 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 writen 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 chracter.
+     
+   - 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 casee 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 explicted 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 <usistd.h>" 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 imput 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/<version number>
+
+   - 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
diff --git a/cextern/cfitsio/checksum.c b/cextern/cfitsio/checksum.c
new file mode 100644
index 0000000..c52b9ef
--- /dev/null
+++ b/cextern/cfitsio/checksum.c
@@ -0,0 +1,508 @@
+/*  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 <string.h>
+#include <stdlib.h>
+#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 */ 
+        sprintf(datasum, "%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);
+}
+
diff --git a/cextern/cfitsio/crc32.c b/cextern/cfitsio/crc32.c
new file mode 100644
index 0000000..08843ff
--- /dev/null
+++ b/cextern/cfitsio/crc32.c
@@ -0,0 +1,440 @@
+/* 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 <rbrown64 at csc.com.au> 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 <stdio.h>
+#  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 <limits.h>
+#    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);
+}
diff --git a/cextern/cfitsio/crc32.h b/cextern/cfitsio/crc32.h
new file mode 100644
index 0000000..8053b61
--- /dev/null
+++ b/cextern/cfitsio/crc32.h
@@ -0,0 +1,441 @@
+/* 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
+  }
+};
diff --git a/cextern/cfitsio/deflate.c b/cextern/cfitsio/deflate.c
new file mode 100644
index 0000000..1c6a00c
--- /dev/null
+++ b/cextern/cfitsio/deflate.c
@@ -0,0 +1,1832 @@
+/* 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)<<s->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;
+}
diff --git a/cextern/cfitsio/deflate.h b/cextern/cfitsio/deflate.h
new file mode 100644
index 0000000..6ac0a1e
--- /dev/null
+++ b/cextern/cfitsio/deflate.h
@@ -0,0 +1,340 @@
+/* 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 */
diff --git a/cextern/cfitsio/drvrfile.c b/cextern/cfitsio/drvrfile.c
new file mode 100644
index 0000000..7cfa9c1
--- /dev/null
+++ b/cextern/cfitsio/drvrfile.c
@@ -0,0 +1,900 @@
+/*  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 <string.h>
+#include <stdlib.h>
+#include "fitsio2.h"
+
+#if defined(unix) || defined(__unix__)  || defined(__unix)
+#include <pwd.h>         /* needed in file_openfile */
+
+#ifdef REPLACE_LINKS
+#include <sys/types.h>
+#include <sys/stat.h>
+#endif
+
+#endif
+
+#ifdef HAVE_FTRUNCATE
+#if defined(unix) || defined(__unix__)  || defined(__unix)
+#include <unistd.h>  /* 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];
+
+    *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))
+      {
+        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 (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   */
+         (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);
+}
+
+
+
+
diff --git a/cextern/cfitsio/drvrgsiftp.c b/cextern/cfitsio/drvrgsiftp.c
new file mode 100644
index 0000000..ab9aaed
--- /dev/null
+++ b/cextern/cfitsio/drvrgsiftp.c
@@ -0,0 +1,522 @@
+
+/*  This file, drvrgsiftp.c contains driver routines for gsiftp files. */
+/*  Andrea Barisani <lcars at si.inaf.it>                                 */
+/* Taffoni Giuliano <taffoni at oats.inaf.it>                             */
+#ifdef HAVE_NET_SERVICES
+#ifdef HAVE_GSIFTP
+
+#include <sys/types.h>
+#include <string.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <setjmp.h>
+#include "fitsio2.h"
+
+#include <globus_ftp_client.h>
+
+#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,
+            &parallelism);
+    }
+   
+    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,
+            &parallelism);
+    }
+   
+    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
diff --git a/cextern/cfitsio/drvrgsiftp.h b/cextern/cfitsio/drvrgsiftp.h
new file mode 100644
index 0000000..bd0ec0d
--- /dev/null
+++ b/cextern/cfitsio/drvrgsiftp.h
@@ -0,0 +1,21 @@
+#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
diff --git a/cextern/cfitsio/drvrmem.c b/cextern/cfitsio/drvrmem.c
new file mode 100644
index 0000000..4ef23b7
--- /dev/null
+++ b/cextern/cfitsio/drvrmem.c
@@ -0,0 +1,1184 @@
+/*  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 <string.h>
+#include <stdlib.h>
+#include <stddef.h>  /* apparently needed to define size_t */
+#include "fitsio2.h"
+
+/* 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);
+
+#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;
+    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 */
+
+        fseek(diskfile, 0, 2);            /* move to end 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 */
+	finalsize  = buffer[0];
+	finalsize |= buffer[1] << 8;
+	finalsize |= buffer[2] << 16;
+	finalsize |= buffer[3] << 24;
+
+        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 */
+	finalsize  = buffer[0];
+	finalsize |= buffer[1] << 8;
+	finalsize |= buffer[2] << 16;
+	finalsize |= buffer[3] << 24;
+
+        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 */
+    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*/
+    } 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);
+}
diff --git a/cextern/cfitsio/drvrnet.c b/cextern/cfitsio/drvrnet.c
new file mode 100644
index 0000000..f0e1a42
--- /dev/null
+++ b/cextern/cfitsio/drvrnet.c
@@ -0,0 +1,2741 @@
+/*  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
+
+
+   <HTML><HEAD>
+   <TITLE>301 Moved Permanently</TITLE>
+   </HEAD><BODY>
+   <H1>Moved Permanently</H1>
+   The document has moved <A HREF="http://heasarc.gsfc.nasa.gov/FTP/software/ftools/release/other/image.fits.gz">here</A>.<P>
+   </BODY></HTML>
+
+   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 <A> 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.
+
+
+
+   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
+
+   <len><opcode><optional information>
+
+   All binary information is transfered in network format, so use htonl and 
+   ntohl to convert back and forth.
+
+   <len> :== 4 byte length, in network format, the len doesn't include the
+         length of <len>
+   <opcode> :== one of the message opcodes below, 4 bytes, network format
+   <optional info> :== depends on opcode
+
+   The response is of the same form with the same opcode sent.  Success is
+   indicated by <optional info> 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, <optional info> 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 <optional info>. Once
+   again the trailing null is sent.  Once again a ROOTD_AUTH message is 
+   returned
+
+   ROOTD_OPEN - <optional info> 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 <optional info> 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 <optional info> 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 <optional info> 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 at 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 <string.h>
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#if defined(unix) || defined(__unix__)  || defined(__unix)
+#include <unistd.h>  
+#endif
+
+#include <signal.h>
+#include <setjmp.h>
+#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;
+
+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 ftp_open_network(char *url, FILE **ftpfile, FILE **command, 
+			    int *sock);
+
+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 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;
+
+/*--------------------------------------------------------------------------*/
+/* 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 newfilename[MAXLEN];
+  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 */
+
+  /* Does the file have a .Z or .gz in it */
+  /* Also, if file has a '?' in it (probably cgi script) */
+  if (strstr(filename,".Z") || strstr(filename,".gz") || 
+      strstr(filename,"?")) {
+    alarm(NETTIMEOUT);
+    if (http_open_network(filename,&httpfile,contentencoding,
+			       &contentlength)) {
+      alarm(0);
+      ffpmsg("Unable to open http file (http_open):");
+      ffpmsg(filename);
+      goto error;
+    } 
+  } else {
+  
+    if (strlen(filename) >= MAXLEN - 4) {
+	  ffpmsg("http file name is too long (http_open)");
+          ffpmsg(filename);
+	  goto error;
+    }
+  
+    alarm(NETTIMEOUT);
+    /* Try the .gz one */    
+    strcpy(newfilename,filename);
+    strcat(newfilename,".gz");
+    
+    if (http_open_network(newfilename,&httpfile,contentencoding,
+			  &contentlength)) {
+      alarm(0);
+      /* Now the .Z one */
+      strcpy(newfilename,filename);
+      strcat(newfilename,".Z");
+      alarm(NETTIMEOUT);
+      if (http_open_network(newfilename,&httpfile,contentencoding,
+			    &contentlength)) {
+	alarm(0);
+	alarm(NETTIMEOUT);
+	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) {
+      sprintf(errorstr,"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;
+
+  /* cfileio made a mistake, should set the netoufile first otherwise 
+     we don't know where to write the output file */
+
+  flen = strlen(netoutfile);
+  if (!flen)  {
+      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;
+
+  /* cfileio made a mistake, we need to know where to write the file */
+  flen = strlen(netoutfile);
+  if (!flen) {
+      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) {
+      sprintf(errorstr,
+	      "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 lenght 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;
+  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)) {
+    sprintf(errorstr,"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)) {
+      sprintf(errorstr,"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)
+    sprintf(tmpstr,"GET http://%s:%-d%s HTTP/1.0\r\n",host,port,fn);
+  else
+    sprintf(tmpstr,"GET %s HTTP/1.0\r\n",fn);
+
+  if (strcmp(userpass, "")) {
+    encode64(strlen(userpass), userpass, MAXLEN, tmpstr2);
+    sprintf(tmpstr1, "Authorization: Basic %s\r\n", tmpstr2);
+
+    if (strlen(tmpstr) + strlen(tmpstr1) > MAXLEN - 1)
+        return (FILE_NOT_OPENED);
+
+    strcat(tmpstr,tmpstr1);
+  }
+
+  sprintf(tmpstr1,"User-Agent: HEASARC/CFITSIO/%-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 */
+  sprintf(tmpstr1,"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))) {
+    sprintf (errorstr,"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, 301, temporary redirect, or 302 perm redirect */
+  sscanf(recbuf,"%s %d",tmpstr,&status);
+  if (status != 200){
+    if (status == 301 || status == 302) {
+      /* got a redirect */
+      if (status == 301) {
+	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,"<A HREF=\"");
+	if (scratchstr != NULL) {
+	  /* Ok, we found the beginning of the anchor */
+	  scratchstr += 9; /* skip the <A HREF=" bits */
+	  scratchstr += 7; /* skip http://, we die if it's really ftp:// */
+	  strcpy(turl,strtok(scratchstr,"\""));
+	  sprintf(errorstr,"to %s\n",turl);
+	  ffpmsg(errorstr);
+	  fclose (*httpfile);
+	  return 
+	    http_open_network(turl,httpfile,contentencoding,contentlength);
+	}
+      }
+      /* if we get here then we couldnt' decide the redirect */
+      ffpmsg("but we were unable to find the redirected url in the servers response");
+    }
+/*    sprintf(errorstr, 
+	    "(http_open_network) Status not 200, was %d\nLine was %s\n",
+	    status,recbuf); 
+    ffpmsg(errorstr);
+*/
+    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 
+   file is uncompressed if necessary */
+
+int ftp_open(char *filename, int rwmode, int *handle)
+{
+
+  FILE *ftpfile;
+  FILE *command;
+  int sock;
+  char newfilename[MAXLEN];
+  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);
+  strcpy(newfilename,filename);
+  /* Does the file have a .Z or .gz in it */
+  if (strstr(newfilename,".Z") || strstr(newfilename,".gz")) {
+    alarm(NETTIMEOUT);
+    if (ftp_open_network(filename,&ftpfile,&command,&sock)) {
+
+      alarm(0);
+      ffpmsg("Unable to open ftp file (ftp_open)");
+      ffpmsg(filename);
+      goto error;
+    } 
+  } else {
+    /* Try the .gz one */
+    strcpy(newfilename,filename);
+    strcat(newfilename,".gz");
+    alarm(NETTIMEOUT);
+    if (ftp_open_network(newfilename,&ftpfile,&command,&sock)) {
+      
+      alarm(0);
+      strcpy(newfilename,filename);
+      strcat(newfilename,".Z");
+      alarm(NETTIMEOUT);
+      if (ftp_open_network(newfilename,&ftpfile,&command,&sock)) {
+	
+	/* Now as given */
+	alarm(0);
+	strcpy(newfilename,filename);
+	alarm(NETTIMEOUT);
+	if (ftp_open_network(newfilename,&ftpfile,&command,&sock)) {
+	  alarm(0);
+	  ffpmsg("Unable to open ftp file (ftp_open)");
+          ffpmsg(newfilename);
+	  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(newfilename,".gz") || 
+      strstr(newfilename,".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--;
+
+  NET_SendRaw(sock,"QUIT\n",5,NET_DEFAULT);
+  fclose(command);
+  closecommandfile--;
+
+  signal(SIGALRM, SIG_DFL);
+  alarm(0);
+
+  return mem_seek(*handle,0);
+
+ error:
+  alarm(0); /* clear it */
+  if (closecommandfile) {
+    fclose(command);
+  }
+  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--;
+  
+  NET_SendRaw(sock,"QUIT\n",5,NET_DEFAULT);
+  fclose(command);
+  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);
+  }
+  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 */
+    NET_SendRaw(sock,"QUIT\n",5,NET_DEFAULT);
+    fclose(command);
+    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);
+  }
+  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 */
+
+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 ip[SHORTLEN];
+  char turl[MAXLEN];
+  int port;
+
+  /* parse the URL */
+  if (strlen(filename) > MAXLEN - 7) {
+    ffpmsg("ftp filename is too long (ftp_open)");
+    return (FILE_NOT_OPENED);
+  }
+
+  strcpy(turl,"ftp://");
+  strcat(turl,filename);
+  if (NET_ParseUrl(turl,proto,host,&port,fn)) {
+    sprintf(errorstr,"URL Parse Error (ftp_open) %s",filename);
+    ffpmsg(errorstr);
+    return (FILE_NOT_OPENED);
+  }
+#ifdef DEBUG
+  printf ("proto, %s, host, %s, port %d, fn %s\n",proto,host,port,fn);
+#endif
+  
+  port = 21;
+  /* we might have a user name */
+  username = "anonymous";
+  password = "user at 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;
+  }
+  
+#ifdef DEBUG
+  printf("User %s pass %s\n",username,password); 
+#endif
+  
+  /* 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)");
+    return (FILE_NOT_OPENED);
+    
+  }
+
+  /* Wait for the 220 response */
+  if (ftp_status(*command,"220 ")) {
+    ffpmsg ("error connecting to remote server, no 220 seen (ftp_open)");
+    fclose(*command);
+    return (FILE_NOT_OPENED);
+  }
+  
+  /* Send the user name and wait for the right response */
+  sprintf(tmpstr,"USER %s\n",username);
+  status = NET_SendRaw(*sock,tmpstr,strlen(tmpstr),NET_DEFAULT);
+  
+  if (ftp_status(*command,"331 ")) {
+    ffpmsg ("USER error no 331 seen (ftp_open)");
+    fclose(*command);
+    return (FILE_NOT_OPENED);
+    
+  }
+  
+  /* Send the password and wait for the right response */
+  sprintf(tmpstr,"PASS %s\n",password);
+  status = NET_SendRaw(*sock,tmpstr,strlen(tmpstr),NET_DEFAULT);
+  
+  if (ftp_status(*command,"230 ")) {
+    ffpmsg ("PASS error, no 230 seen (ftp_open)");
+    fclose(*command);
+    return (FILE_NOT_OPENED);
+  }
+  
+  
+  /* now do the cwd command */
+  newfn = strrchr(fn,'/');
+  if (newfn == NULL) {
+    strcpy(tmpstr,"CWD /\n");
+    newfn = fn;
+  } else {
+    *newfn = '\0';
+    newfn++;
+    if (strlen(fn) == 0) {
+      strcpy(tmpstr,"CWD /\n");
+    } else {
+      /* remove the leading slash */
+      if (fn[0] == '/') {
+	sprintf(tmpstr,"CWD %s\n",&fn[1]);
+      } else {
+	sprintf(tmpstr,"CWD %s\n",fn);
+      } 
+    }
+  }
+  
+#ifdef DEBUG
+  printf("CWD command is %s\n",tmpstr);
+#endif
+  status = NET_SendRaw(*sock,tmpstr,strlen(tmpstr),NET_DEFAULT);
+  
+  if (ftp_status(*command,"250 ")) {
+    ffpmsg ("CWD error, no 250 seen (ftp_open)");
+    fclose(*command);
+    return (FILE_NOT_OPENED);
+  }
+  
+  if (!strlen(newfn)) {
+    ffpmsg("Null file name (ftp_open)");
+    fclose(*command);
+    return (FILE_NOT_OPENED);
+  }
+  
+ 
+  /* Always use binary mode */
+  sprintf(tmpstr,"TYPE I\n");
+  status = NET_SendRaw(*sock,tmpstr,strlen(tmpstr),NET_DEFAULT);
+  
+  if (ftp_status(*command,"200 ")) {
+    ffpmsg ("TYPE I error, 200 not seen (ftp_open)");
+    fclose(*command);
+    return (FILE_NOT_OPENED);
+  }
+ 
+  status = NET_SendRaw(*sock,"PASV\n",5,NET_DEFAULT);
+  if (!(fgets(recbuf,MAXLEN,*command))) {
+    ffpmsg ("PASV error (ftp_open)");
+    fclose(*command);
+    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)");
+      fclose(*command);
+      return (FILE_NOT_OPENED);
+    }
+    
+    *passive = '\0';
+    passive++;
+    ip[0] = '\0';
+      
+    /* Messy parsing of response from PASV *command */
+    
+    if (!(tstr = strtok(passive,",)"))) {
+      ffpmsg ("PASV error (ftp_open)");
+      fclose(*command);
+      return (FILE_NOT_OPENED);
+    }
+    strcpy(ip,tstr);
+    strcat(ip,".");
+    
+    if (!(tstr = strtok(NULL,",)"))) {
+      ffpmsg ("PASV error (ftp_open)");
+      fclose(*command);
+      return (FILE_NOT_OPENED);
+    }
+    strcat(ip,tstr);
+    strcat(ip,".");
+    
+    if (!(tstr = strtok(NULL,",)"))) {
+      ffpmsg ("PASV error (ftp_open)");
+      fclose(*command);
+      return (FILE_NOT_OPENED);
+    }
+    strcat(ip,tstr);
+    strcat(ip,".");
+    
+    if (!(tstr = strtok(NULL,",)"))) {
+      ffpmsg ("PASV error (ftp_open)");
+      fclose(*command);
+      return (FILE_NOT_OPENED);
+    }
+    strcat(ip,tstr);
+    
+    /* Done the ip number, now do the port # */
+    if (!(tstr = strtok(NULL,",)"))) {
+      ffpmsg ("PASV error (ftp_open)");
+      fclose(*command);
+      return (FILE_NOT_OPENED);
+    }
+    sscanf(tstr,"%d",&port);
+    port *= 256;
+    
+    if (!(tstr = strtok(NULL,",)"))) {
+      ffpmsg ("PASV error (ftp_open)");
+      fclose(*command);
+      return (FILE_NOT_OPENED);
+    }
+    sscanf(tstr,"%d",&tmpint);
+    port += tmpint;
+    
+    
+    if (!strlen(newfn)) {
+      ffpmsg("Null file name (ftp_open)");
+      fclose(*command);
+      return (FILE_NOT_OPENED);
+    }
+    
+
+#ifdef DEBUG
+    puts("connection to passive port");
+#endif
+    /* 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)");
+      fclose(*command);
+      return (FILE_NOT_OPENED);
+    }
+
+    /* now we return */
+
+    /* Send the retrieve command */
+    sprintf(tmpstr,"RETR %s\n",newfn);
+    status = NET_SendRaw(*sock,tmpstr,strlen(tmpstr),NET_DEFAULT);
+
+#ifdef DEBUG
+    puts("Sent RETR command");
+#endif
+    if (ftp_status(*command,"150 ")) {
+    /*  ffpmsg ("RETR error, most likely file is not there (ftp_open)"); */
+      fclose(*command);
+#ifdef DEBUG
+      puts("File not there");
+#endif
+      return (FILE_NOT_OPENED);
+    }
+    return 0;
+  }
+  
+  /* no passive mode */
+
+  NET_SendRaw(*sock,"QUIT\n",5,NET_DEFAULT);
+  fclose(*command);
+  return (FILE_NOT_OPENED);
+}
+
+/*--------------------------------------------------------------------------*/
+/* return a socket which results from connection to hostname on port port */
+static 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("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;
+     }
+#ifdef DEBUG
+     printf ("send raw, sent %d bytes\n",nsent);
+#endif
+   }
+#ifdef DEBUG
+   printf ("send raw end, sent %d bytes\n",n);
+#endif
+   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;
+}
+
+/*--------------------------------------------------------------------------*/
+
+/* Small helper functions to set the netoutfile static string */
+/* Called by cfileio after parsing the output file off of the input file url */
+
+int http_checkfile (char *urltype, char *infile, char *outfile1)
+{
+  char newinfile[MAXLEN];
+  FILE *httpfile;
+  char contentencoding[MAXLEN];
+  int contentlength;
+  
+  /* default to http:// if there is no output file */
+    
+  strcpy(urltype,"http://");
+
+  if (strlen(outfile1)) {
+    /* there is an output file */
+
+    /* 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 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; don't open it */
+      strcpy(urltype,"httpfile://");
+      return 0;
+    }
+
+    if (!http_open_network(infile,&httpfile,contentencoding,&contentlength)) {
+      fclose(httpfile);
+      /* It's there, we're happy */
+      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;
+    }
+
+    /* Ok, let's try the .gz one */
+    strcpy(newinfile,infile);
+    strcat(newinfile,".gz");
+    if (!http_open_network(newinfile,&httpfile,contentencoding,
+			   &contentlength)) {
+      fclose(httpfile);
+      strcpy(infile,newinfile);
+      /* It's there, we're happy, and, it's compressed  */
+      /* It's compressed */
+      if (strstr(outfile1,".gz") || (strstr(outfile1,".Z"))) {
+	strcpy(urltype,"httpcompress://");
+      } else {
+	strcpy(urltype,"httpfile://");
+      }
+      return 0;
+    }
+    
+    /* Ok, let's try the .Z one */
+    strcpy(newinfile,infile);
+    strcat(newinfile,".Z");
+    if (!http_open_network(newinfile,&httpfile,contentencoding,
+			   &contentlength)) {
+      fclose(httpfile);
+      strcpy(infile,newinfile);
+      /* It's there, we're happy, and, it's compressed  */
+      if (strstr(outfile1,".gz") || (strstr(outfile1,".Z"))) {
+	strcpy(urltype,"httpcompress://");
+      } else {
+	strcpy(urltype,"httpfile://");
+      }
+      return 0;
+    }
+    
+  } 
+  return 0;
+}
+/*--------------------------------------------------------------------------*/
+int ftp_checkfile (char *urltype, char *infile, char *outfile1)
+{
+  char newinfile[MAXLEN];
+  FILE *ftpfile;
+  FILE *command;
+  int sock;
+
+  
+  /* default to ftp://   */
+    
+  strcpy(urltype,"ftp://");
+
+  if (strlen(outfile1)) {
+    /* there is an output file */
+
+    /* 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 (!ftp_open_network(infile,&ftpfile,&command,&sock)) {
+      fclose(ftpfile);
+      fclose(command);
+      /* It's there, we're happy */
+      if (strstr(infile,".gz") || (strstr(infile,".Z"))) {
+	/* It's compressed */
+	if (strstr(outfile1,".gz") || (strstr(outfile1,".Z"))) {
+	  strcpy(urltype,"ftpcompress://");
+	} else {
+	  strcpy(urltype,"ftpfile://");
+	}
+      } else {
+	strcpy(urltype,"ftpfile://");
+      }
+      return 0;
+    }
+
+    /* Ok, let's try the .gz one */
+    strcpy(newinfile,infile);
+    strcat(newinfile,".gz");
+    if (!ftp_open_network(newinfile,&ftpfile,&command,&sock)) {
+      fclose(ftpfile);
+      fclose(command);
+      strcpy(infile,newinfile);
+      /* It's there, we're happy, and, it's compressed  */
+      if (strstr(outfile1,".gz") || (strstr(outfile1,".Z"))) {
+	strcpy(urltype,"ftpcompress://");
+      } else {
+	strcpy(urltype,"ftpfile://");
+      }
+      return 0;
+    }
+    
+    /* Ok, let's try the .Z one */
+    strcpy(newinfile,infile);
+    strcat(newinfile,".Z");
+    if (!ftp_open_network(newinfile,&ftpfile,&command,&sock)) {
+      fclose(ftpfile);
+      fclose(command);
+      strcpy(infile,newinfile);
+      if (strstr(outfile1,".gz") || (strstr(outfile1,".Z"))) {
+	strcpy(urltype,"ftpcompress://");
+      } else {
+	strcpy(urltype,"ftpfile://");
+      }
+      return 0;
+    }
+    
+  } 
+  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];
+  int len;
+
+  len = strlen(statusstr);
+  while (1) {
+    if (!(fgets(recbuf,MAXLEN,ftp))) {
+#ifdef DEBUG
+      puts("error reading response in ftp_status");
+#endif
+      return 1; /* error reading */
+    }
+    
+#ifdef DEBUG
+    printf("ftp_status, return string was %s\n",recbuf);
+#endif
+
+    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 */
+      return 1; 
+    }
+  }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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 */
+  sprintf(msg,"%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);
+  }
+#ifdef DEBUG
+  printf("root_read, op %d astat %d\n",op,astat);
+#endif
+  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 */
+  sprintf(msg,"%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);
+#ifdef DEBUG
+  printf("root_read, op %d astat %d\n",op,astat);
+#endif
+  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)) {
+    sprintf(errorstr,"URL Parse Error (root_open) %s",url);
+    ffpmsg(errorstr);
+    return (FILE_NOT_OPENED);
+  }
+  
+#ifdef DEBUG
+  printf("Connecting to %s on port %d\n",host,port);
+#endif
+  /* Connect to the remote host */
+  *sock = NET_TcpConnect(host,port);
+  if (*sock < 0) {
+    ffpmsg("Couldn't connect to host (http_open_network)");
+    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);
+  }
+  
+#ifdef DEBUG
+  printf("op is %d and authstat is %d\n",op,authstat);
+#endif
+  
+  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<strlen(recbuf);ii++) {
+    recbuf[ii] = ~recbuf[ii];
+  }
+  
+  status = root_send_buffer(*sock, ROOTD_PASS, recbuf, strlen(recbuf));
+  if (status < 0) {
+    ffpmsg("error talking to remote system sending password");
+    return (FILE_NOT_OPENED);
+  }
+  
+  status = root_recv_buffer(*sock,&op,(char *)&authstat,4);
+  if (status < 0) {
+    ffpmsg("error talking to remote system acking password");
+    return (FILE_NOT_OPENED);
+  }
+  
+#ifdef DEBUG
+  printf("op is %d and authstat is %d\n",op,authstat);
+#endif
+  if (op != ROOTD_AUTH) {
+    ffpmsg("ERROR on ROOTD_PASS");
+    ffpmsg(recbuf);
+    return (FILE_NOT_OPENED);
+  }
+  
+  /* now the file open request */
+  strcpy(recbuf,fn);
+  strcat(recbuf," ");
+  strcat(recbuf,rwmode);
+
+  status = root_send_buffer(*sock, ROOTD_OPEN, recbuf, strlen(recbuf));
+  if (status < 0) {
+    ffpmsg("error talking to remote system on open ");
+    return (FILE_NOT_OPENED);
+  }
+
+  status = root_recv_buffer(*sock,&op,(char *)&authstat,4);
+  if (status < 0) {
+    ffpmsg("error talking to remote system on open");
+    return (FILE_NOT_OPENED);
+  }
+
+#ifdef DEBUG
+  printf("op is %d and recbuf is %d\n",op,authstat);
+#endif
+  
+  if ((op != ROOTD_OPEN) && (authstat != 0)) {
+    ffpmsg("ERROR on ROOTD_OPEN");
+    ffpmsg(recbuf);
+    return (FILE_NOT_OPENED);
+  }
+
+  return 0;
+
+}
+
+static int root_send_buffer(int sock, int op, char *buffer, int buflen)
+{
+  /* send a buffer, the form is
+     <len>
+     <op>
+     <buffer>
+
+     <len> 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);
+
+#ifdef DEBUG
+  printf("len sent is %x\n",hdr[0]);
+#endif
+
+  hdr[1] = htonl(op);
+#ifdef DEBUG
+  printf("op sent is %x\n",hdr[1]);
+#endif
+  
+
+#ifdef DEBUG
+  printf("Sending op %d and length of %d\n",op,len);
+#endif
+
+  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
+     <len>
+     <op>
+     <buffer>
+
+  */
+
+  int recv1 = 0;
+  int len;
+  int status;
+  char recbuf[MAXLEN];
+
+  status = NET_RecvRaw(sock,&len,4);
+#ifdef DEBUG
+  printf("Recv: status from rec is %d\n",status);
+#endif
+  if (status < 0) {
+    return status;
+  }
+  recv1 += status;
+
+  len = ntohl(len);
+#ifdef DEBUG
+  printf ("Recv: length is %d\n",len);
+#endif
+
+  /* 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);
+#ifdef DEBUG
+  printf ("Recv: Operation is %d\n",*op);
+#endif
+  
+  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<s_len); ++byte) {
+      sr <<= 8;
+      sr |= (*(src+triad+byte) & 0xff);
+    }
+
+    /* shift left to next 6 bit alignment*/
+    sr <<= (6-((8*byte)%6))%6;
+
+    if (d_len < 4)
+      return 1;
+
+    *(dst+0) = *(dst+1) = *(dst+2) = *(dst+3) = '=';
+    switch(byte) {
+    case 3:
+      *(dst+3) = base64[sr&0x3f];
+      sr >>= 6;
+    case 2:
+      *(dst+2) = base64[sr&0x3f];
+      sr >>= 6;
+    case 1:
+      *(dst+1) = base64[sr&0x3f];
+      sr >>= 6;
+      *(dst+0) = base64[sr&0x3f];
+    }
+    dst += 4;
+    d_len -= 4;
+  }
+
+  *dst = '\0';
+  return 0;
+}
+
+
+#endif
diff --git a/cextern/cfitsio/drvrsmem.c b/cextern/cfitsio/drvrsmem.c
new file mode 100644
index 0000000..c5fda75
--- /dev/null
+++ b/cextern/cfitsio/drvrsmem.c
@@ -0,0 +1,973 @@
+/*              S H A R E D   M E M O R Y   D R I V E R
+                =======================================
+
+                  by Jerzy.Borkowski at obs.unige.ch
+
+09-Mar-98 : initial version 1.0 released
+23-Mar-98 : shared_malloc now accepts new handle as an argument
+23-Mar-98 : shmem://0, shmem://1, etc changed to shmem://h0, etc due to bug
+            in url parser.
+10-Apr-98 : code cleanup
+13-May-99 : delayed initialization added, global table deleted on exit when
+            no shmem segments remain, and last process terminates
+*/
+
+#ifdef HAVE_SHMEM_SERVICES
+#include "fitsio2.h"                         /* drvrsmem.h is included by it */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#if defined(unix) || defined(__unix__)  || defined(__unix)
+#include <unistd.h> 
+#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<shared_maxseg; i++)
+        { if (0 == shared_lt[i].tcnt) continue; /* we're not using this segment, skip this ... */
+          if (-1 != shared_lt[i].lkcnt) continue;  /* seg not R/W locked by us, skip this ... */
+
+          r = shared_destroy_entry(i);          /* destroy unconditionally sema & segment */
+          if (shared_debug) 
+            { if (SHARED_OK == r) printf(" [%d]", i);
+              else printf(" [error on %d !!!!]", i);
+
+            }
+        }
+       free((void *)shared_lt);                 /* free local table */
+       shared_lt = NULL;
+     }
+   if (NULL != shared_gt)                       /* detach global index table */
+     { oktodelete = 0;
+       filelocked = 0;
+       if (shared_debug) printf(" detaching globalsharedtable");
+       if (SHARED_INVALID != shared_fd)
+
+       flk.l_type = F_WRLCK;                    /* lock whole lock file */
+       flk.l_whence = 0;
+       flk.l_start = 0;
+       flk.l_len = shared_maxseg;
+       if (-1 != fcntl(shared_fd, F_SETLK, &flk))
+         { filelocked = 1;                      /* success, scan global table, to see if there are any segs */
+           segmentspresent = 0;                 /* assume, there are no segs in the system */
+           for (j=0; j<shared_maxseg; j++)
+            { if (SHARED_INVALID != shared_gt[j].key)
+                { segmentspresent = 1;          /* yes, there is at least one */
+                  break;
+                }
+            }
+           if (0 == segmentspresent)            /* if there are no segs ... */
+             if (0 == shmctl(shared_gt_h, IPC_STAT, &ds)) /* get number of processes attached to table */
+               { if (ds.shm_nattch <= 1) oktodelete = 1; /* if only one (we), then it is safe (but see text 4 lines later) to unlink */
+               }
+         }
+       shmdt((char *)shared_gt);                /* detach global table */
+       if (oktodelete)                          /* delete global table from system, if no shm seg present */
+         { shmctl(shared_gt_h, IPC_RMID, 0);    /* there is a race condition here - time window between shmdt and shmctl */
+           shared_gt_h = SHARED_INVALID;
+         }
+       shared_gt = NULL;
+       if (filelocked)                          /* if we locked, we need to unlock */
+         { flk.l_type = F_UNLCK;
+           flk.l_whence = 0;
+           flk.l_start = 0;
+           flk.l_len = shared_maxseg;
+           fcntl(shared_fd, F_SETLK, &flk);
+         }
+     }
+   shared_gt_h = SHARED_INVALID;
+
+   if (SHARED_INVALID != shared_fd)             /* close lock file */
+     { if (shared_debug) printf(" closing lockfile");
+       close(shared_fd);
+       shared_fd = SHARED_INVALID;
+     }
+
+   
+   shared_kbase = 0;
+   shared_maxseg = 0;
+   shared_range = 0;
+   shared_init_called = 0;
+
+   if (shared_debug) printf(" <<done>>\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=");
+       sprintf(buf, "%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<shared_maxseg; i++) shared_clear_entry(i);       /* since we are master, init data */
+           if (shared_debug) printf("master");
+         }
+     }
+
+   if (NULL == shared_lt)                       /* initialize local table */
+     { if (shared_debug) printf(" localtableinit=");
+       if (NULL == (shared_lt = (SHARED_LTAB *)malloc(shared_maxseg * sizeof(SHARED_LTAB)))) return(SHARED_NOMEM);
+       for (i=0; i<shared_maxseg; i++)
+        { shared_lt[i].p = NULL;                /* not mapped */
+          shared_lt[i].tcnt = 0;                /* unused (or zero threads using this seg) */
+          shared_lt[i].lkcnt = 0;               /* segment is unlocked */
+          shared_lt[i].seekpos = 0L;            /* r/w pointer at the beginning of file */
+        }
+       if (shared_debug) printf("ok");
+     }
+
+   atexit(shared_cleanup);                      /* we want shared_cleanup to be called at exit or abort */
+
+   if (shared_debug) printf(" <<done>>\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<shared_maxseg; i++)
+    { if (-1 != id) if (i != id) continue;
+      if (shared_lt[i].tcnt) continue;          /* somebody (we) is using it */
+      if (SHARED_INVALID == shared_gt[i].key) continue; /* unused slot */
+      if (shared_mux(i, SHARED_NOWAIT | SHARED_RDWRITE)) continue; /* acquire exclusive access to segment, but do not wait */
+      r2 = shared_process_count(shared_gt[i].sem);
+      if ((shared_gt[i].nprocdebug > 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_maxseg; i++)
+    { if (-1 != id) if (i != id) continue;
+      if (SHARED_INVALID == shared_gt[i].key) continue; /* unused slot */
+      switch (shared_mux(i, SHARED_NOWAIT | SHARED_RDONLY)) /* acquire exclusive access to segment, but do not wait */
+
+       { case SHARED_AGAIN:
+                printf("!%3d %08lx %4d  %8d", i, (unsigned long int)shared_gt[i].key,
+                                shared_gt[i].nprocdebug, shared_gt[i].size);
+                if (SHARED_RESIZE & shared_gt[i].attr) printf(" RESIZABLE");
+                if (SHARED_PERSIST & shared_gt[i].attr) printf(" PERSIST");
+                printf("\n");
+                break;
+         case SHARED_OK:
+                printf(" %3d %08lx %4d  %8d", i, (unsigned long int)shared_gt[i].key,
+
+                                shared_gt[i].nprocdebug, shared_gt[i].size);
+                if (SHARED_RESIZE & shared_gt[i].attr) printf(" RESIZABLE");
+                if (SHARED_PERSIST & shared_gt[i].attr) printf(" PERSIST");
+                printf("\n");
+                shared_demux(i, SHARED_RDONLY);
+                break;
+         default:
+                continue;
+       }
+    }
+   if (shared_debug) printf(" done\n");
+   return(r);                                           /* table full */
+ }
+
+int     shared_getaddr(int id, char **address)
+ { int i;
+   char segname[10];
+
+   if (NULL == shared_gt) return(SHARED_NOTINIT);       /* not initialized */
+   if (NULL == shared_lt) return(SHARED_NOTINIT);       /* not initialized */
+ 
+   strcpy(segname,"h");
+   sprintf(segname+1,"%d", id);
+ 
+   if (smem_open(segname,0,&i)) return(SHARED_BADARG);
+ 
+   *address = ((char *)(((DAL_SHM_SEGHEAD *)(shared_lt[i].p + 1)) + 1));
+ /*  smem_close(i); */
+   return(SHARED_OK);
+ }
+
+
+int     shared_uncond_delete(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_uncond_delete:");
+   r = SHARED_OK;
+   for (i=0; i<shared_maxseg; i++)
+    { if (-1 != id) if (i != id) continue;
+      if (shared_attach(i))
+        { if (-1 != id) printf("no such handle\n");
+          continue;
+        }
+      printf("handle %d:", i);
+      if (NULL == shared_lock(i, SHARED_RDWRITE | SHARED_NOWAIT)) 
+        { printf(" cannot lock in RW mode, not deleted\n");
+          continue;
+        }
+      if (shared_set_attr(i, SHARED_RESIZE) >= 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
diff --git a/cextern/cfitsio/drvrsmem.h b/cextern/cfitsio/drvrsmem.h
new file mode 100644
index 0000000..52ac7d7
--- /dev/null
+++ b/cextern/cfitsio/drvrsmem.h
@@ -0,0 +1,179 @@
+/*		S H A R E D   M E M O R Y   D R I V E R
+		=======================================
+
+		  by Jerzy.Borkowski at obs.unige.ch
+
+09-Mar-98 : initial version 1.0 released
+23-Mar-98 : shared_malloc now accepts new handle as an argument
+*/
+
+
+#include <sys/ipc.h>		/* this is necessary for Solaris/Linux */
+#include <sys/shm.h>
+#include <sys/sem.h>
+
+#ifdef _AIX
+#include <fcntl.h>
+#else
+#include <sys/fcntl.h>
+#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
diff --git a/cextern/cfitsio/editcol.c b/cextern/cfitsio/editcol.c
new file mode 100644
index 0000000..dc82f02
--- /dev/null
+++ b/cextern/cfitsio/editcol.c
@@ -0,0 +1,2474 @@
+/*  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 <string.h>
+#include <ctype.h>
+#include <stdlib.h>
+#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)
+    {
+        sprintf(message,
+        "Illegal value for BITPIX keyword: %d", bitpix);
+        ffpmsg(message);
+        return(*status = BAD_BITPIX);
+    }
+
+    if (naxis < 0 || naxis > 999)
+    {
+        sprintf(message,
+        "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)
+        {
+            sprintf(message,
+            "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 */
+                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);
+
+      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 sprintf is platform dependent ( %lld, %ld, %I64d ) */
+
+    sprintf(tfm,"%.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, anynull;
+    long tfields, repeat, width, 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 */
+
+    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 columns to or from IMAGE HDUs (ffcpcl)");
+       return(*status = NOT_TABLE);
+    }
+
+    if ( (infptr->Fptr)->hdutype == BINARY_TBL &&  (outfptr->Fptr)->hdutype == 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 ((infptr->Fptr)->hdutype == ASCII_TBL && (outfptr->Fptr)->hdutype == 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);
+        }
+
+        /* 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 ((infptr->Fptr)->hdutype == ASCII_TBL && (outfptr->Fptr)->hdutype == 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;
+    }
+
+    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 - 1) / 8 + 1;  /* convert from bits to bytes */
+    else if (typecode == TSTRING && (infptr->Fptr)->hdutype == 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);
+}
diff --git a/cextern/cfitsio/edithdu.c b/cextern/cfitsio/edithdu.c
new file mode 100644
index 0000000..385bbe9
--- /dev/null
+++ b/cextern/cfitsio/edithdu.c
@@ -0,0 +1,883 @@
+/*  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 <string.h>
+#include <stdlib.h>
+#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) )  /* 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
+    {
+        sprintf(errmsg,
+        "Illegal value for BITPIX keyword: %d", bitpix);
+        ffpmsg(errmsg);
+        return(*status = BAD_BITPIX);  /* illegal bitpix value */
+    }
+    if (naxis < 0 || naxis > 999)
+    {
+        sprintf(errmsg,
+        "Illegal value for NAXIS keyword: %d", naxis);
+        ffpmsg(errmsg);
+        return(*status = BAD_NAXIS);
+    }
+
+    for (ii = 0; ii < naxis; ii++)
+    {
+        if (naxes[ii] < 0)
+        {
+            sprintf(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[81], 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)
+    {
+        sprintf(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 && *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[81], 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)
+    {
+        sprintf(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 && *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);
+}
+
diff --git a/cextern/cfitsio/eval.l b/cextern/cfitsio/eval.l
new file mode 100644
index 0000000..c6e3cf8
--- /dev/null
+++ b/cextern/cfitsio/eval.l
@@ -0,0 +1,545 @@
+%{
+/************************************************************************/
+/*                                                                      */
+/*                       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 <math.h>
+#include <string.h>
+#include <ctype.h>
+#ifdef sparc
+#include <malloc.h>
+#else
+#include <stdlib.h>
+#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(        !strcasecmp(yytext,"#PI") ) {
+		     yylval.dbl = (double)(4) * atan((double)(1));
+		     return( DOUBLE );
+		  } else if( !strcasecmp(yytext,"#E") ) {
+		     yylval.dbl = exp((double)(1));
+		     return( DOUBLE );
+		  } else if( !strcasecmp(yytext,"#DEG") ) {
+		     yylval.dbl = ((double)4)*atan((double)1)/((double)180);
+		     return( DOUBLE );
+		  } else if( !strcasecmp(yytext,"#ROW") ) {
+		     return( ROWREF );
+		  } else if( !strcasecmp(yytext,"#NULL") ) {
+		     return( NULLREF );
+		  } else if( !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 ((n<nbytes)&&(gParse.expr[gParse.index] != '\0'));
+     if( gParse.expr[gParse.index] == '\0' ) gParse.is_eobuf = 1;
+ }
+ buf[n] = '\0';
+ return(n);
+}
+
+int yyGetVariable( char *varName, YYSTYPE *thelval )
+{
+   int varNum, type;
+   char errMsg[MAXVARNAME+25];
+
+   varNum = find_variable( varName );
+   if( varNum<0 ) {
+      if( gParse.getData ) {
+	 type = (*gParse.getData)( varName, thelval );
+      } else {
+	 type = pERROR;
+	 gParse.status = PARSE_SYNTAX_ERR;
+	 strcpy (errMsg,"Unable to find data: ");
+	 strncat(errMsg, varName, MAXVARNAME);
+	 ffpmsg (errMsg);
+      }
+   } else {
+      /*  Convert variable type into expression type  */
+      switch( gParse.varData[ varNum ].type ) {
+      case LONG:
+      case DOUBLE:   type =  COLUMN;  break;
+      case BOOLEAN:  type = BCOLUMN;  break;
+      case STRING:   type = SCOLUMN;  break;
+      case BITSTR:   type =  BITCOL;  break;
+      default:
+	 type = pERROR;
+	 gParse.status = PARSE_SYNTAX_ERR;
+	 strcpy (errMsg,"Bad datatype for data: ");
+	 strncat(errMsg, varName, MAXVARNAME);
+	 ffpmsg (errMsg);
+	 break;
+      }
+      thelval->lng = varNum;
+   }
+   return( type );
+}
+
+static int find_variable(char *varName)
+{
+   int i;
+ 
+   if( gParse.nCols )
+      for( i=0; i<gParse.nCols; i++ ) {
+         if( ! strncasecmp(gParse.varData[i].name,varName,MAXVARNAME) ) {
+            return( i );
+         }
+      }
+   return( -1 );
+}
+
+#if defined(vms) || defined(__vms) || defined(WIN32) || defined(__WIN32__) || defined(macintosh)
+
+/* ================================================================== */
+/* A hack for nonunix machines, which lack strcasecmp and strncasecmp */
+/* ================================================================== */
+
+int 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 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);
+}
+
+#endif
diff --git a/cextern/cfitsio/eval.y b/cextern/cfitsio/eval.y
new file mode 100644
index 0000000..1f5fd99
--- /dev/null
+++ b/cextern/cfitsio/eval.y
@@ -0,0 +1,5837 @@
+%{
+/************************************************************************/
+/*                                                                      */
+/*                       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 <time.h>
+
+#include <stdlib.h>
+
+#ifndef alloca
+#define alloca malloc
+#endif
+
+   /*  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 <log>   BOOLEAN        /* First 3 must be in order of        */
+%token <lng>   LONG           /* increasing promotion for later use */
+%token <dbl>   DOUBLE
+%token <str>   STRING
+%token <str>   BITSTR
+%token <str>   FUNCTION
+%token <str>   BFUNCTION      /* Bit function */
+%token <str>   IFUNCTION      /* Integer function */
+%token <str>   GTIFILTER
+%token <str>   REGFILTER
+%token <lng>   COLUMN
+%token <lng>   BCOLUMN
+%token <lng>   SCOLUMN
+%token <lng>   BITCOL
+%token <lng>   ROWREF
+%token <lng>   NULLREF
+%token <lng>   SNULLREF
+
+%type <Node>  expr
+%type <Node>  bexpr
+%type <Node>  sexpr
+%type <Node>  bits
+%type <Node>  vector
+%type <Node>  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($5) )  Copy_Dims($$, $5);
+                  TYPE($1) = TYPE($3);
+                  if( ! Test_Dims($1,$$) ) {
+                     yyerror("Incompatible dimensions in '?:' condition");
+		     YYERROR;
+                  }
+                  TYPE($1) = BOOLEAN;
+                  if( SIZE($$)<SIZE($1) )  Copy_Dims($$, $1);
+                }
+       | bexpr '?' bexpr ':' 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($5) )  Copy_Dims($$, $5);
+                  TYPE($1) = TYPE($3);
+                  if( ! Test_Dims($1,$$) ) {
+                     yyerror("Incompatible dimensions in '?:' condition");
+		     YYERROR;
+                  }
+                  TYPE($1) = BOOLEAN;
+                  if( SIZE($$)<SIZE($1) )  Copy_Dims($$, $1);
+                }
+       | bexpr '?' expr ':' bexpr
+                {
+                  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($5) )  Copy_Dims($$, $5);
+                  TYPE($1) = TYPE($3);
+                  if( ! Test_Dims($1,$$) ) {
+                     yyerror("Incompatible dimensions in '?:' condition");
+		     YYERROR;
+                  }
+                  TYPE($1) = BOOLEAN;
+                  if( SIZE($$)<SIZE($1) )  Copy_Dims($$, $1);
+                }
+       | FUNCTION ')'
+                { if (FSTRCMP($1,"RANDOM(") == 0) {  /* Scalar RANDOM() */
+                     srand( (unsigned int) time(NULL) );
+                     $$ = New_Func( DOUBLE, rnd_fct, 0, 0, 0, 0, 0, 0, 0, 0 );
+		  } else if (FSTRCMP($1,"RANDOMN(") == 0) {/*Scalar RANDOMN()*/
+		     srand( (unsigned int) time(NULL) );
+		     $$ = New_Func( DOUBLE, gasrnd_fct, 0, 0, 0, 0, 0, 0, 0, 0 );
+                  } else {
+                     yyerror("Function() not supported");
+		     YYERROR;
+		  }
+                  TEST($$); 
+                }
+       | FUNCTION bexpr ')'
+                { if (FSTRCMP($1,"SUM(") == 0) {
+		     $$ = New_Func( LONG, sum_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
+                  } else if (FSTRCMP($1,"NELEM(") == 0) {
+                     $$ = New_Const( LONG, &( SIZE($2) ), sizeof(long) );
+                  } else if (FSTRCMP($1,"ACCUM(") == 0) {
+		    long zero = 0;
+		    $$ = New_BinOp( LONG , $2, ACCUM, New_Const( LONG, &zero, sizeof(zero) ));
+		  } else {
+                     yyerror("Function(bool) not supported");
+		     YYERROR;
+		  }
+                  TEST($$); 
+		}
+       | FUNCTION sexpr ')'
+                { if (FSTRCMP($1,"NELEM(") == 0) {
+                     $$ = New_Const( LONG, &( SIZE($2) ), sizeof(long) );
+		  } else if (FSTRCMP($1,"NVALID(") == 0) {
+		     $$ = New_Func( LONG, nonnull_fct, 1, $2,
+				    0, 0, 0, 0, 0, 0 );
+		  } else {
+                     yyerror("Function(str) not supported");
+		     YYERROR;
+		  }
+                  TEST($$); 
+		}
+       | FUNCTION bits ')'
+                { if (FSTRCMP($1,"NELEM(") == 0) {
+                     $$ = New_Const( LONG, &( SIZE($2) ), sizeof(long) );
+		} else if (FSTRCMP($1,"NVALID(") == 0) { /* Bit arrays do not have NULL */
+                     $$ = New_Const( LONG, &( SIZE($2) ), sizeof(long) );
+		} else if (FSTRCMP($1,"SUM(") == 0) {
+		     $$ = New_Func( LONG, sum_fct, 1, $2,
+				    0, 0, 0, 0, 0, 0 );
+		} else if (FSTRCMP($1,"MIN(") == 0) {
+		     $$ = New_Func( TYPE($2),  /* Force 1D result */
+				    min1_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
+		     /* Note: $2 is a vector so the result can never
+		        be a constant.  Therefore it will never be set
+		        inside New_Func(), and it is safe to set SIZE() */
+		     SIZE($$) = 1;
+		} else if (FSTRCMP($1,"ACCUM(") == 0) {
+		    long zero = 0;
+		    $$ = New_BinOp( LONG , $2, ACCUM, New_Const( LONG, &zero, sizeof(zero) ));
+		} else if (FSTRCMP($1,"MAX(") == 0) {
+		     $$ = New_Func( TYPE($2),  /* Force 1D result */
+				    max1_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
+		     /* Note: $2 is a vector so the result can never
+		        be a constant.  Therefore it will never be set
+		        inside New_Func(), and it is safe to set SIZE() */
+		     SIZE($$) = 1;
+		} else {
+                     yyerror("Function(bits) not supported");
+		     YYERROR;
+		  }
+                  TEST($$); 
+		}
+       | FUNCTION expr ')'
+                { if (FSTRCMP($1,"SUM(") == 0)
+		     $$ = New_Func( TYPE($2), sum_fct, 1, $2,
+				    0, 0, 0, 0, 0, 0 );
+		  else if (FSTRCMP($1,"AVERAGE(") == 0)
+		     $$ = New_Func( DOUBLE, average_fct, 1, $2,
+				    0, 0, 0, 0, 0, 0 );
+		  else if (FSTRCMP($1,"STDDEV(") == 0)
+		     $$ = New_Func( DOUBLE, stddev_fct, 1, $2,
+				    0, 0, 0, 0, 0, 0 );
+		  else if (FSTRCMP($1,"MEDIAN(") == 0)
+		     $$ = New_Func( TYPE($2), median_fct, 1, $2,
+				    0, 0, 0, 0, 0, 0 );
+		  else if (FSTRCMP($1,"NELEM(") == 0)
+                     $$ = New_Const( LONG, &( SIZE($2) ), sizeof(long) );
+		  else if (FSTRCMP($1,"NVALID(") == 0)
+		     $$ = New_Func( LONG, nonnull_fct, 1, $2,
+				    0, 0, 0, 0, 0, 0 );
+		  else if   ((FSTRCMP($1,"ACCUM(") == 0) && (TYPE($2) == LONG)) {
+		    long zero = 0;
+		    $$ = New_BinOp( LONG ,   $2, ACCUM, New_Const( LONG,   &zero, sizeof(zero) ));
+		  } else if ((FSTRCMP($1,"ACCUM(") == 0) && (TYPE($2) == DOUBLE)) {
+		    double zero = 0;
+		    $$ = New_BinOp( DOUBLE , $2, ACCUM, New_Const( DOUBLE, &zero, sizeof(zero) ));
+		  } else if ((FSTRCMP($1,"SEQDIFF(") == 0) && (TYPE($2) == LONG)) {
+		    long zero = 0;
+		    $$ = New_BinOp( LONG ,   $2, DIFF, New_Const( LONG,   &zero, sizeof(zero) ));
+		  } else if ((FSTRCMP($1,"SEQDIFF(") == 0) && (TYPE($2) == DOUBLE)) {
+		    double zero = 0;
+		    $$ = New_BinOp( DOUBLE , $2, DIFF, New_Const( DOUBLE, &zero, sizeof(zero) ));
+		  } else if (FSTRCMP($1,"ABS(") == 0)
+		     $$ = New_Func( 0, abs_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
+ 		  else if (FSTRCMP($1,"MIN(") == 0)
+		     $$ = New_Func( TYPE($2),  /* Force 1D result */
+				    min1_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
+		  else if (FSTRCMP($1,"MAX(") == 0)
+		     $$ = New_Func( TYPE($2),  /* Force 1D result */
+				    max1_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
+		  else if (FSTRCMP($1,"RANDOM(") == 0) { /* Vector RANDOM() */
+                     srand( (unsigned int) time(NULL) );
+                     $$ = New_Func( 0, rnd_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
+		     TEST($$);
+		     TYPE($$) = DOUBLE;
+		  } else if (FSTRCMP($1,"RANDOMN(") == 0) {
+		     srand( (unsigned int) time(NULL) ); /* Vector RANDOMN() */
+		     $$ = New_Func( 0, gasrnd_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
+		     TEST($$);
+		     TYPE($$) = DOUBLE;
+                  } 
+  		  else {  /*  These all take DOUBLE arguments  */
+		     if( TYPE($2) != DOUBLE ) $2 = New_Unary( DOUBLE, 0, $2 );
+                     if (FSTRCMP($1,"SIN(") == 0)
+			$$ = New_Func( 0, sin_fct,  1, $2, 0, 0, 0, 0, 0, 0 );
+		     else if (FSTRCMP($1,"COS(") == 0)
+			$$ = New_Func( 0, cos_fct,  1, $2, 0, 0, 0, 0, 0, 0 );
+		     else if (FSTRCMP($1,"TAN(") == 0)
+			$$ = New_Func( 0, tan_fct,  1, $2, 0, 0, 0, 0, 0, 0 );
+		     else if (FSTRCMP($1,"ARCSIN(") == 0
+			      || FSTRCMP($1,"ASIN(") == 0)
+			$$ = New_Func( 0, asin_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
+		     else if (FSTRCMP($1,"ARCCOS(") == 0
+			      || FSTRCMP($1,"ACOS(") == 0)
+			$$ = New_Func( 0, acos_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
+		     else if (FSTRCMP($1,"ARCTAN(") == 0
+			      || FSTRCMP($1,"ATAN(") == 0)
+			$$ = New_Func( 0, atan_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
+		     else if (FSTRCMP($1,"SINH(") == 0)
+			$$ = New_Func( 0, sinh_fct,  1, $2, 0, 0, 0, 0, 0, 0 );
+		     else if (FSTRCMP($1,"COSH(") == 0)
+			$$ = New_Func( 0, cosh_fct,  1, $2, 0, 0, 0, 0, 0, 0 );
+		     else if (FSTRCMP($1,"TANH(") == 0)
+			$$ = New_Func( 0, tanh_fct,  1, $2, 0, 0, 0, 0, 0, 0 );
+		     else if (FSTRCMP($1,"EXP(") == 0)
+			$$ = New_Func( 0, exp_fct,  1, $2, 0, 0, 0, 0, 0, 0 );
+		     else if (FSTRCMP($1,"LOG(") == 0)
+			$$ = New_Func( 0, log_fct,  1, $2, 0, 0, 0, 0, 0, 0 );
+		     else if (FSTRCMP($1,"LOG10(") == 0)
+			$$ = New_Func( 0, log10_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
+		     else if (FSTRCMP($1,"SQRT(") == 0)
+			$$ = New_Func( 0, sqrt_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
+		     else if (FSTRCMP($1,"ROUND(") == 0)
+			$$ = New_Func( 0, round_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
+		     else if (FSTRCMP($1,"FLOOR(") == 0)
+			$$ = New_Func( 0, floor_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
+		     else if (FSTRCMP($1,"CEIL(") == 0)
+			$$ = New_Func( 0, ceil_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
+		     else if (FSTRCMP($1,"RANDOMP(") == 0) {
+		       srand( (unsigned int) time(NULL) );
+		       $$ = New_Func( 0, poirnd_fct, 1, $2, 
+				      0, 0, 0, 0, 0, 0 );
+		       TYPE($$) = LONG;
+		     } else {
+			yyerror("Function(expr) not supported");
+			YYERROR;
+		     }
+		  }
+                  TEST($$); 
+                }
+       | IFUNCTION sexpr ',' sexpr ')'
+                { 
+		  if (FSTRCMP($1,"STRSTR(") == 0) {
+		    $$ = New_Func( LONG, strpos_fct, 2, $2, $4, 0, 
+				   0, 0, 0, 0 );
+		    TEST($$);
+		  }
+                }
+       | FUNCTION expr ',' expr ')'
+                { 
+		   if (FSTRCMP($1,"DEFNULL(") == 0) {
+		      if( SIZE($2)>=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) ) Copy_Dims($$, $4);
+		     } else {
+			yyerror("Dimensions of arctan2 arguments "
+				"are not compatible");
+			YYERROR;
+		     }
+		   } else if (FSTRCMP($1,"MIN(") == 0) {
+		      PROMOTE( $2, $4 );
+		      if( Test_Dims( $2, $4 ) ) {
+			$$ = New_Func( 0, min2_fct, 2, $2, $4, 0, 0, 0, 0, 0 );
+			TEST($$);
+			if( SIZE($2)<SIZE($4) ) Copy_Dims($$, $4);
+		      } else {
+			yyerror("Dimensions of min(a,b) arguments "
+				"are not compatible");
+			YYERROR;
+		      }
+		   } else if (FSTRCMP($1,"MAX(") == 0) {
+		      PROMOTE( $2, $4 );
+		      if( Test_Dims( $2, $4 ) ) {
+			$$ = New_Func( 0, max2_fct, 2, $2, $4, 0, 0, 0, 0, 0 );
+			TEST($$);
+			if( SIZE($2)<SIZE($4) ) Copy_Dims($$, $4);
+		      } else {
+			yyerror("Dimensions of max(a,b) arguments "
+				"are not compatible");
+			YYERROR;
+		      }
+#if 0
+		   } else if (FSTRCMP($1,"STRSTR(") == 0) {
+		     if( TYPE($2) != STRING || TYPE($4) != STRING) {
+		       yyerror("Arguments to strstr(s,r) must be strings");
+		       YYERROR;
+		     }
+		     $$ = New_Func( LONG, strpos_fct, 2, $2, $4, 0, 
+				    0, 0, 0, 0 );
+		     TEST($$);
+#endif
+		   } else {
+		      yyerror("Function(expr,expr) not supported");
+		      YYERROR;
+		   }
+                }
+       | FUNCTION expr ',' expr ',' expr ',' expr ')'
+                { 
+		  if (FSTRCMP($1,"ANGSEP(") == 0) {
+		    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( TYPE($8) != DOUBLE ) $8 = New_Unary( DOUBLE, 0, $8 );
+		    if( Test_Dims( $2, $4 ) && Test_Dims( $4, $6 ) && 
+			Test_Dims( $6, $8 ) ) {
+		      $$ = New_Func( 0, angsep_fct, 4, $2, $4, $6, $8,0,0,0 );
+		      TEST($$); 
+		      if( SIZE($2)<SIZE($4) ) Copy_Dims($$, $4);
+		      if( SIZE($4)<SIZE($6) ) Copy_Dims($$, $6);
+		      if( SIZE($6)<SIZE($8) ) Copy_Dims($$, $8);
+		    } else {
+		      yyerror("Dimensions of ANGSEP arguments "
+			      "are not compatible");
+		      YYERROR;
+		    }
+		   } else {
+		      yyerror("Function(expr,expr,expr,expr) not supported");
+		      YYERROR;
+		   }
+                }
+       | expr '[' expr ']'
+                { $$ = New_Deref( $1, 1, $3,  0,  0,  0,   0 ); TEST($$); }
+       | expr '[' expr ',' expr ']'
+                { $$ = New_Deref( $1, 2, $3, $5,  0,  0,   0 ); TEST($$); }
+       | expr '[' expr ',' expr ',' expr ']'
+                { $$ = New_Deref( $1, 3, $3, $5, $7,  0,   0 ); TEST($$); }
+       | expr '[' expr ',' expr ',' expr ',' expr ']'
+                { $$ = New_Deref( $1, 4, $3, $5, $7, $9,   0 ); TEST($$); }
+       | expr '[' expr ',' expr ',' expr ',' expr ',' expr ']'
+                { $$ = New_Deref( $1, 5, $3, $5, $7, $9, $11 ); TEST($$); }
+       | INTCAST expr
+		{ $$ = New_Unary( LONG,   INTCAST, $2 );  TEST($$);  }
+       | INTCAST bexpr
+                { $$ = New_Unary( LONG,   INTCAST, $2 );  TEST($$);  }
+       | FLTCAST expr
+		{ $$ = New_Unary( DOUBLE, FLTCAST, $2 );  TEST($$);  }
+       | FLTCAST bexpr
+                { $$ = New_Unary( DOUBLE, FLTCAST, $2 );  TEST($$);  }
+       ;
+
+bexpr:   BOOLEAN
+                { $$ = New_Const( BOOLEAN, &($1), sizeof(char) ); TEST($$); }
+       | BCOLUMN
+                { $$ = New_Column( $1 ); TEST($$); }
+       | BCOLUMN '{' expr '}'
+                {
+                  if( TYPE($3) != LONG
+		      || OPER($3) != CONST_OP ) {
+		     yyerror("Offset argument must be a constant integer");
+		     YYERROR;
+		  }
+                  $$ = New_Offset( $1, $3 ); TEST($$);
+                }
+       | bits EQ bits
+                { $$ = New_BinOp( BOOLEAN, $1, EQ,  $3 ); TEST($$);
+		  SIZE($$) = 1;                                     }
+       | bits NE bits
+                { $$ = New_BinOp( BOOLEAN, $1, NE,  $3 ); TEST($$); 
+		  SIZE($$) = 1;                                     }
+       | bits LT bits
+                { $$ = New_BinOp( BOOLEAN, $1, LT,  $3 ); TEST($$); 
+		  SIZE($$) = 1;                                     }
+       | bits LTE bits
+                { $$ = New_BinOp( BOOLEAN, $1, LTE, $3 ); TEST($$); 
+		  SIZE($$) = 1;                                     }
+       | bits GT bits
+                { $$ = New_BinOp( BOOLEAN, $1, GT,  $3 ); TEST($$); 
+		  SIZE($$) = 1;                                     }
+       | bits GTE bits
+                { $$ = New_BinOp( BOOLEAN, $1, GTE, $3 ); TEST($$); 
+		  SIZE($$) = 1;                                     }
+       | expr GT expr
+                { PROMOTE($1,$3); $$ = New_BinOp( BOOLEAN, $1, GT,  $3 );
+                  TEST($$);                                               }
+       | expr LT expr
+                { PROMOTE($1,$3); $$ = New_BinOp( BOOLEAN, $1, LT,  $3 );
+                  TEST($$);                                               }
+       | expr GTE expr
+                { PROMOTE($1,$3); $$ = New_BinOp( BOOLEAN, $1, GTE, $3 );
+                  TEST($$);                                               }
+       | expr LTE expr
+                { PROMOTE($1,$3); $$ = New_BinOp( BOOLEAN, $1, LTE, $3 );
+                  TEST($$);                                               }
+       | expr '~' expr
+                { PROMOTE($1,$3); $$ = New_BinOp( BOOLEAN, $1, '~', $3 );
+                  TEST($$);                                               }
+       | expr EQ expr
+                { PROMOTE($1,$3); $$ = New_BinOp( BOOLEAN, $1, EQ,  $3 );
+                  TEST($$);                                               }
+       | expr NE expr
+                { PROMOTE($1,$3); $$ = New_BinOp( BOOLEAN, $1, NE,  $3 );
+                  TEST($$);                                               }
+       | sexpr EQ sexpr
+                { $$ = New_BinOp( BOOLEAN, $1, EQ,  $3 ); TEST($$);
+                  SIZE($$) = 1; }
+       | sexpr NE sexpr
+                { $$ = New_BinOp( BOOLEAN, $1, NE,  $3 ); TEST($$);
+                  SIZE($$) = 1; }
+       | sexpr GT sexpr
+                { $$ = New_BinOp( BOOLEAN, $1, GT,  $3 ); TEST($$);
+                  SIZE($$) = 1; }
+       | sexpr GTE sexpr
+                { $$ = New_BinOp( BOOLEAN, $1, GTE, $3 ); TEST($$);
+                  SIZE($$) = 1; }
+       | sexpr LT sexpr
+                { $$ = New_BinOp( BOOLEAN, $1, LT,  $3 ); TEST($$);
+                  SIZE($$) = 1; }
+       | sexpr LTE sexpr
+                { $$ = New_BinOp( BOOLEAN, $1, LTE, $3 ); TEST($$);
+                  SIZE($$) = 1; }
+       | bexpr AND bexpr
+                { $$ = New_BinOp( BOOLEAN, $1, AND, $3 ); TEST($$); }
+       | bexpr OR bexpr
+                { $$ = New_BinOp( BOOLEAN, $1, OR,  $3 ); TEST($$); }
+       | bexpr EQ bexpr
+                { $$ = New_BinOp( BOOLEAN, $1, EQ,  $3 ); TEST($$); }
+       | bexpr NE bexpr
+                { $$ = New_BinOp( BOOLEAN, $1, NE,  $3 ); TEST($$); }
+
+       | expr '=' expr ':' expr
+                { PROMOTE($1,$3); PROMOTE($1,$5); PROMOTE($3,$5);
+		  $3 = New_BinOp( BOOLEAN, $3, LTE, $1 );
+                  $5 = New_BinOp( BOOLEAN, $1, LTE, $5 );
+                  $$ = New_BinOp( BOOLEAN, $3, AND, $5 );
+                  TEST($$);                                         }
+
+       | bexpr '?' bexpr ':' bexpr
+                {
+                  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($5) )  Copy_Dims($$, $5);
+                  if( ! Test_Dims($1,$$) ) {
+                     yyerror("Incompatible dimensions in '?:' condition");
+		     YYERROR;
+                  }
+                  if( SIZE($$)<SIZE($1) )  Copy_Dims($$, $1);
+                }
+
+       | BFUNCTION expr ')'
+                {
+		   if (FSTRCMP($1,"ISNULL(") == 0) {
+		      $$ = New_Func( 0, isnull_fct, 1, $2, 0, 0,
+				     0, 0, 0, 0 );
+		      TEST($$); 
+                      /* Use expression's size, but return BOOLEAN */
+		      TYPE($$) = BOOLEAN;
+		   } else {
+		      yyerror("Boolean Function(expr) not supported");
+		      YYERROR;
+		   }
+		}
+       | BFUNCTION bexpr ')'
+                {
+		   if (FSTRCMP($1,"ISNULL(") == 0) {
+		      $$ = New_Func( 0, isnull_fct, 1, $2, 0, 0,
+				     0, 0, 0, 0 );
+		      TEST($$); 
+                      /* Use expression's size, but return BOOLEAN */
+		      TYPE($$) = BOOLEAN;
+		   } else {
+		      yyerror("Boolean Function(expr) not supported");
+		      YYERROR;
+		   }
+		}
+       | BFUNCTION sexpr ')'
+                {
+		   if (FSTRCMP($1,"ISNULL(") == 0) {
+		      $$ = New_Func( BOOLEAN, isnull_fct, 1, $2, 0, 0,
+				     0, 0, 0, 0 );
+		      TEST($$); 
+		   } else {
+		      yyerror("Boolean Function(expr) not supported");
+		      YYERROR;
+		   }
+		}
+       | FUNCTION bexpr ',' bexpr ')'
+                {
+		   if (FSTRCMP($1,"DEFNULL(") == 0) {
+		      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($$)<SIZE($2) )  Copy_Dims($$, $2);
+		     if( SIZE($2)<SIZE($4) )  Copy_Dims($$, $4);
+		     if( SIZE($4)<SIZE($6) )  Copy_Dims($$, $6);
+		   }
+		}
+       | BFUNCTION expr ',' expr ',' 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( TYPE($8) != DOUBLE ) $8 = New_Unary( DOUBLE, 0, $8 );
+		   if( TYPE($10)!= DOUBLE ) $10= New_Unary( DOUBLE, 0, $10);
+		   if( ! (Test_Dims( $2, $4 ) && Test_Dims( $4, $6 ) && 
+			  Test_Dims( $6, $8 ) && Test_Dims( $8, $10 )) ) {
+		     yyerror("Dimensions of CIRCLE arguments "
+			     "are not compatible");
+		     YYERROR;
+		   } else {
+		     if (FSTRCMP($1,"CIRCLE(") == 0) {
+		       $$ = New_Func( BOOLEAN, circle_fct, 5, $2, $4, $6, $8,
+				      $10, 0, 0 );
+		     } else {
+		       yyerror("Boolean Function not supported");
+		       YYERROR;
+		     }
+		     TEST($$); 
+		     if( SIZE($$)<SIZE($2) )  Copy_Dims($$, $2);
+		     if( SIZE($2)<SIZE($4) )  Copy_Dims($$, $4);
+		     if( SIZE($4)<SIZE($6) )  Copy_Dims($$, $6);
+		     if( SIZE($6)<SIZE($8) )  Copy_Dims($$, $8);
+		     if( SIZE($8)<SIZE($10) ) Copy_Dims($$, $10);
+		   }
+		}
+       | BFUNCTION expr ',' expr ',' expr ',' expr ',' 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( TYPE($8) != DOUBLE ) $8 = New_Unary( DOUBLE, 0, $8 );
+		   if( TYPE($10)!= DOUBLE ) $10= New_Unary( DOUBLE, 0, $10);
+		   if( TYPE($12)!= DOUBLE ) $12= New_Unary( DOUBLE, 0, $12);
+		   if( TYPE($14)!= DOUBLE ) $14= New_Unary( DOUBLE, 0, $14);
+		   if( ! (Test_Dims( $2, $4 ) && Test_Dims( $4, $6 ) && 
+			  Test_Dims( $6, $8 ) && Test_Dims( $8, $10 ) &&
+			  Test_Dims($10,$12 ) && Test_Dims($12, $14 ) ) ) {
+		     yyerror("Dimensions of BOX or ELLIPSE arguments "
+			     "are not compatible");
+		     YYERROR;
+		   } else {
+		     if (FSTRCMP($1,"BOX(") == 0) {
+		       $$ = New_Func( BOOLEAN, box_fct, 7, $2, $4, $6, $8,
+				      $10, $12, $14 );
+		     } else if (FSTRCMP($1,"ELLIPSE(") == 0) {
+		       $$ = New_Func( BOOLEAN, elps_fct, 7, $2, $4, $6, $8,
+				      $10, $12, $14 );
+		     } else {
+		       yyerror("SAO Image Function not supported");
+		       YYERROR;
+		     }
+		     TEST($$); 
+		     if( SIZE($$)<SIZE($2) )  Copy_Dims($$, $2);
+		     if( SIZE($2)<SIZE($4) )  Copy_Dims($$, $4);
+		     if( SIZE($4)<SIZE($6) )  Copy_Dims($$, $6);
+		     if( SIZE($6)<SIZE($8) )  Copy_Dims($$, $8);
+		     if( SIZE($8)<SIZE($10) ) Copy_Dims($$, $10);
+		     if( SIZE($10)<SIZE($12) ) Copy_Dims($$, $12);
+		     if( SIZE($12)<SIZE($14) ) Copy_Dims($$, $14);
+		   }
+		}
+
+       | GTIFILTER ')'
+                { /* Use defaults for all elements */
+                   $$ = New_GTI( "", -99, "*START*", "*STOP*" );
+                   TEST($$);                                        }
+       | GTIFILTER STRING ')'
+                { /* Use defaults for all except filename */
+                   $$ = New_GTI( $2, -99, "*START*", "*STOP*" );
+                   TEST($$);                                        }
+       | GTIFILTER STRING ',' expr ')'
+                {  $$ = New_GTI( $2, $4, "*START*", "*STOP*" );
+                   TEST($$);                                        }
+       | GTIFILTER STRING ',' expr ',' STRING ',' STRING ')'
+                {  $$ = New_GTI( $2, $4, $6, $8 );
+                   TEST($$);                                        }
+
+       | REGFILTER STRING ')'
+                { /* Use defaults for all except filename */
+                   $$ = New_REG( $2, -99, -99, "" );
+                   TEST($$);                                        }
+       | REGFILTER STRING ',' expr ',' expr ')'
+                {  $$ = New_REG( $2, $4, $6, "" );
+                   TEST($$);                                        }
+       | REGFILTER STRING ',' expr ',' expr ',' STRING ')'
+                {  $$ = New_REG( $2, $4, $6, $8 );
+                   TEST($$);                                        }
+
+       | bexpr '[' expr ']'
+                { $$ = New_Deref( $1, 1, $3,  0,  0,  0,   0 ); TEST($$); }
+       | bexpr '[' expr ',' expr ']'
+                { $$ = New_Deref( $1, 2, $3, $5,  0,  0,   0 ); TEST($$); }
+       | bexpr '[' expr ',' expr ',' expr ']'
+                { $$ = New_Deref( $1, 3, $3, $5, $7,  0,   0 ); TEST($$); }
+       | bexpr '[' expr ',' expr ',' expr ',' expr ']'
+                { $$ = New_Deref( $1, 4, $3, $5, $7, $9,   0 ); TEST($$); }
+       | bexpr '[' expr ',' expr ',' expr ',' expr ',' expr ']'
+                { $$ = New_Deref( $1, 5, $3, $5, $7, $9, $11 ); TEST($$); }
+       | NOT bexpr
+                { $$ = New_Unary( BOOLEAN, NOT, $2 ); TEST($$); }
+       | '(' bexpr ')'
+                { $$ = $2; }
+       ;
+
+sexpr:   STRING
+                { $$ = New_Const( STRING, $1, strlen($1)+1 ); TEST($$);
+                  SIZE($$) = strlen($1); }
+       | SCOLUMN
+                { $$ = New_Column( $1 ); TEST($$); }
+       | SCOLUMN '{' expr '}'
+                {
+                  if( TYPE($3) != LONG
+		      || OPER($3) != CONST_OP ) {
+		     yyerror("Offset argument must be a constant integer");
+		     YYERROR;
+		  }
+                  $$ = New_Offset( $1, $3 ); TEST($$);
+                }
+       | SNULLREF
+                { $$ = New_Func( STRING, null_fct, 0, 0, 0, 0, 0, 0, 0, 0 ); }
+       | '(' sexpr ')'
+                { $$ = $2; }
+       | sexpr '+' sexpr
+                { 
+		  if (SIZE($1)+SIZE($3) >= 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)<SIZE($5) )  Copy_Dims($$, $5);
+                }
+
+       | FUNCTION sexpr ',' sexpr ')'
+                { 
+		  if (FSTRCMP($1,"DEFNULL(") == 0) {
+		     int outSize;
+		     /* 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($2);
+		     if (SIZE($4) > 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; i<gParse.varData[ColNum].naxis; i++ )
+	 this->value.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; i<gParse.varData[ColNum].naxis; i++ )
+	 this->value.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; i<that->value.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; i<that1->value.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; i<that->value.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; idx<nDim; idx++ )
+	 constant = (constant && theDim[idx]->operation==CONST_OP);
+
+      for( idx=0; idx<nDim; idx++ )
+	 if( theDim[idx]->value.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; idx<this->value.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)<SIZE(NodeY) )  Copy_Dims(n, NodeY);
+
+      /* Init Region node to be treated as a "constant" */
+
+      that0                = gParse.Nodes + Node0;
+      that0->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; i<this->nSubNodes; 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; i<that1->value.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; i<that2->value.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;
+
+   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<gParse.nNodes; i++ ) {
+     if(    OPER(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_<Action> 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)<gParse.nRows ) {
+	       this->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; i<rows; i++) {
+	       sptr1 = that1->value.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; i<elem; i++) {
+	  if (!that1->value.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; i<elem; i++) {
+	     if (!that1->value.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; i<elem; i++) {
+	    if (!that1->value.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; i<elem; i++) {
+	    curr = that1->value.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; i<elem; i++) {
+	    if (!that1->value.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; i<elem; i++) {
+	    curr = that1->value.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 */
+
+
+  
+/*
+This (commented out) algorithm uses the Low of Cosines, which becomes
+ unstable for angles less than 0.1 arcsec. 
+ 
+  cd = sin(dec1*deg)*sin(dec2*deg) 
+    + cos(dec1*deg)*cos(dec2*deg)*cos((ra1-ra2)*deg);
+  if (cd < (-1)) cd = -1;
+  if (cd > (+1)) cd = +1;
+  return acos(cd)/deg;
+*/
+
+  /* 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 double ran1()
+{
+  static double dval = 0.0;
+  double rndVal;
+
+  if (dval == 0.0) {
+    if( rand()<32768 && rand()<32768 )
+      dval =      32768.0;
+    else
+      dval = 2147483648.0;
+  }
+
+  rndVal = (double)rand();
+  while( rndVal > dval ) dval *= 2.0;
+  return rndVal/dval;
+}
+
+/* Gaussian deviate routine from Numerical Recipes */
+static double gasdev()
+{
+  static int iset = 0;
+  static double gset;
+  double fac, rsq, v1, v2;
+
+  if (iset == 0) {
+    do {
+      v1 = 2.0*ran1()-1.0;
+      v2 = 2.0*ran1()-1.0;
+      rsq = v1*v1 + v2*v2;
+    } while (rsq >= 1.0 || rsq == 0.0);
+    fac = sqrt(-2.0*log(rsq)/rsq);
+    gset = v1*fac;
+    iset = 1;
+    return v2*fac;
+  } else {
+    iset = 0;
+    return gset;
+  }
+
+}
+
+/* lgamma function - from Numerical Recipes */
+
+float gammaln(float xx)
+     /* Returns the value ln Gamma[(xx)] for xx > 0. */
+{
+  /* 
+     Internal arithmetic will be done in double precision, a nicety
+     that you can omit if five-figure accuracy is good enough. */
+  double x,y,tmp,ser;
+  static double cof[6]={76.18009172947146,-86.50532032941677,
+			24.01409824083091,-1.231739572450155,
+			0.1208650973866179e-2,-0.5395239384953e-5};
+  int j;
+  y=x=xx;
+  tmp=x+5.5;
+  tmp -= (x+0.5)*log(tmp);
+  ser=1.000000000190015;
+  for (j=0;j<=5;j++) ser += cof[j]/++y;
+  return (float) -tmp+log(2.5066282746310005*ser/x);
+}
+
+/* Poisson deviate - derived from Numerical Recipes */
+static long poidev(double xm)
+{
+  static double sq, alxm, g, oldm = -1.0;
+  static double pi = 0;
+  double em, t, y;
+
+  if (pi == 0) pi = ((double)4)*atan((double)1);
+
+  if (xm < 20.0) {
+    if (xm != oldm) {
+      oldm = xm;
+      g = exp(-xm);
+    }
+    em = -1;
+    t = 1.0;
+    do {
+      em += 1;
+      t *= ran1();
+    } while (t > g);
+  } else {
+    if (xm != oldm) {
+      oldm = xm;
+      sq = sqrt(2.0*xm);
+      alxm = log(xm);
+      g = xm*alxm-gammaln( (float) (xm+1.0));
+    }
+    do {
+      do {
+	y = tan(pi*ran1());
+	em = sq*y+xm;
+      } while (em < 0.0);
+      em = floor(em);
+      t = 0.9*(1.0+y*y)*exp(em*alxm-gammaln( (float) (em+1.0) )-g);
+    } while (ran1() > t);
+  }
+
+  /* Return integer version */
+  return (long int) floor(em+0.5);
+}
+
+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 = poidev(pVals[0].data.dbl);
+	    else
+	      this->value.data.lng = poidev(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] = ran1();
+	     this->value.undef[elem] = 0;
+	    }
+	    break;
+
+	 case gasrnd_fct:
+	    while( elem-- ) {
+	       this->value.data.dblptr[elem] = gasdev();
+	       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] = poidev(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] = 
+		      poidev(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] = poidev(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] = 
+		      poidev(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<row; irow++) {
+		  long *p = mptr;
+		  int nelem1 = nelem;
+		  int count = 0;
+
+		  while ( nelem1-- ) { 
+		    if (*uptr == 0) {
+		      *p++ = *dptr;   /* Only advance the dest pointer if we copied */
+		    }
+		    dptr ++;  /* Advance the source pointer ... */
+		    uptr ++;  /* ... and source "undef" pointer */
+		  }
+		  
+		  nelem1 = (p - mptr);  /* Number of accepted data points */
+		  if (nelem1 > 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<row; irow++) {
+		  double *p = mptr;
+		  int nelem1 = nelem;
+
+		  while ( nelem1-- ) { 
+		    if (*uptr == 0) {
+		      *p++ = *dptr;   /* Only advance the dest pointer if we copied */
+		    }
+		    dptr ++;  /* Advance the source pointer ... */
+		    uptr ++;  /* ... and source "undef" pointer */
+		  }
+
+		  nelem1 = (p - mptr);  /* Number of accepted data points */
+		  if (nelem1 > 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; row<gParse.nRows; row++ ) {
+	       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 */
+	       }
+	       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; row<gParse.nRows; row++ ) {
+	      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;
+	      elem += theVar->value.nelem+1;
+	    }	       
+	 } else {
+	    elem = this->value.nelem * (dimVals[0]-1);
+	    for( row=0; row<gParse.nRows; row++ ) {
+	       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 );
+	       elem += theVar->value.nelem;
+	    }	       
+	 }
+      
+      } else if( theVar->value.naxis==nDims ) {
+
+	 /* Dereference completely using an expression for the indices */
+
+	 for( row=0; row<gParse.nRows; row++ ) {
+
+	    for( i=0; i<nDims; i++ ) {
+	       if( !isConst[i] ) {
+		  if( theDims[i]->value.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; row<gParse.nRows; row++ ) {
+
+	    /* Index cannot be a constant */
+
+	    if( theDims[0]->value.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; i<nDims; i++ )
+      if( theDims[i]->operation>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]<start[gti] || 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] ) {
+	       if( evtTime<=stop[gti-1] )
+		  gti -= step;
+	       else {
+		  gti = -1L;
+		  break;
+	       }
+	    } else {
+	       break;
+	    }
+	 }
+      } else
+	 gti = -1L;
+      
+   } else { /*  Use "SLOW" linear search  */
+      gti = nGTI;
+      while( gti-- )
+	 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; node<this->nSubNodes; 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[256];
+ char chr1, chr2;
+
+ l1 = strlen(bits1);
+ l2 = strlen(bits2);
+ if (l1 < l2)
+   {
+    length = 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)
+   {
+    length = l1;
+    ldiff = l1 - l2;
+    i=0;
+    while( ldiff-- ) stream[i++] = '0';
+    while( l2--    ) stream[i++] = *(bits2++);
+    stream[i] = '\0';
+    bits2 = stream;
+   }
+ else
+    length = l1;
+
+ 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;
+       }
+ return (result);
+}
+
+static void bitand(char *result,char *bitstrm1,char *bitstrm2)
+{
+ int i, l1, l2, ldiff;
+ char stream[256];
+ char chr1, chr2;
+
+ l1 = strlen(bitstrm1);
+ l2 = strlen(bitstrm2);
+ 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++;
+    }
+ *result = '\0';
+}
+
+static void bitor(char *result,char *bitstrm1,char *bitstrm2)
+{
+ int i, l1, l2, ldiff;
+ char stream[256];
+ char chr1, chr2;
+
+ l1 = strlen(bitstrm1);
+ l2 = strlen(bitstrm2);
+ 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++;
+    }
+ *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;
+ char stream[256];
+ char chr1, chr2;
+
+ l1 = strlen(bitstrm1);
+ l2 = strlen(bitstrm2);
+ 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')) )
+	  return( 0 );
+    }
+ 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);
+}
diff --git a/cextern/cfitsio/eval_defs.h b/cextern/cfitsio/eval_defs.h
new file mode 100644
index 0000000..09c066b
--- /dev/null
+++ b/cextern/cfitsio/eval_defs.h
@@ -0,0 +1,163 @@
+#include <stdio.h>
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+#if defined(__sgi) || defined(__hpux)
+#include <alloca.h>
+#endif
+#ifdef sparc
+#include <malloc.h>
+#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
diff --git a/cextern/cfitsio/eval_f.c b/cextern/cfitsio/eval_f.c
new file mode 100644
index 0000000..f9bdd05
--- /dev/null
+++ b/cextern/cfitsio/eval_f.c
@@ -0,0 +1,2823 @@
+/************************************************************************/
+/*                                                                      */
+/*                       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 <limits.h>
+#include <ctype.h>
+#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; elem<nrows; elem++ )
+         row_status[elem] = result;
+   } else {
+      firstrow     = (firstrow>1 ? 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; elem<Info.maxRows; elem++ ) {
+            if( row_status[elem]==1 ) ++*n_good_rows;
+         }
+      }
+   }
+
+   ffcprs();
+   FFUNLOCK;
+   return(*status);
+}
+
+/*--------------------------------------------------------------------------*/
+int ffsrow( fitsfile *infptr,   /* I - Input FITS file                      */
+            fitsfile *outfptr,  /* I - Output FITS file                     */
+            char     *expr,     /* I - Boolean expression                   */
+            int      *status )  /* O - Error status                         */
+/*                                                                          */
+/* 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   */
+/* files are the same, delete the FALSE rows (preserve the TRUE rows).      */
+/* Can copy rows between extensions of the same file, *BUT* if output       */
+/* extension is before the input extension, the second extension *MUST* be  */
+/* opened using ffreopen, so that CFITSIO can handle changing file lengths. */
+/*--------------------------------------------------------------------------*/
+{
+   parseInfo Info;
+   int naxis, constant;
+   long nelem, rdlen, naxes[MAXDIMS], maxrows, nbuff, nGood, inloc, outloc;
+   LONGLONG ntodo, inbyteloc, outbyteloc, hsize;
+   long freespace;
+   unsigned char *buffer, result;
+   struct {
+      LONGLONG rowLength, numRows, heapSize;
+      LONGLONG dataStart, heapStart;
+   } inExt, outExt;
+
+   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;
+
+   /**********************************************************************/
+   /* Make sure expression evaluates to the right type... logical scalar */
+   /**********************************************************************/
+
+   if( Info.datatype!=TLOGICAL || nelem!=1 ) {
+      ffcprs();
+      ffpmsg("Expression does not evaluate to a logical scalar.");
+      FFUNLOCK;
+      return( *status = PARSE_BAD_TYPE );
+   }
+
+   /***********************************************************/
+   /*  Extract various table information from each extension  */
+   /***********************************************************/
+
+   if( infptr->HDUposition != (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<inExt.numRows; ntodo++ )
+         ((char*)Info.dataPtr)[ntodo] = result;
+      nGood = (long) (result ? inExt.numRows : 0);
+
+   } else {
+
+      ffiter( gParse.nCols, gParse.colData, 0L, 0L,
+              parse_data, (void*)&Info, status );
+
+      nGood = 0;
+      for( ntodo = 0; ntodo<inExt.numRows; ntodo++ )
+         if( ((char*)Info.dataPtr)[ntodo] ) nGood++;
+   }
+
+   if( *status ) {
+      /* Error... Do nothing */
+   } else {
+      rdlen  = (long) inExt.rowLength;
+      buffer = (unsigned char *)malloc(maxvalue(500000,rdlen) * sizeof(char) );
+      if( buffer==NULL ) {
+         ffcprs();
+         FFUNLOCK;
+         return( *status=MEMORY_ALLOCATION );
+      }
+      maxrows = maxvalue( (500000L/rdlen), 1);
+      nbuff = 0;
+      inloc = 1;
+      if( infptr==outfptr ) { /* Skip initial good rows if input==output file */
+         while( ((char*)Info.dataPtr)[inloc-1] ) inloc++;
+         outloc = inloc;
+      } else {
+         outloc = (long) (outExt.numRows + 1);
+         if (outloc > 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( nelements<nelem1 ) {
+      ffcprs();
+      ffpmsg("Array not large enough to hold at least one row of data.");
+      FFUNLOCK;
+      return( *status = PARSE_LRG_VECTOR );
+   }
+
+   firstrow = (firstrow>1 ? 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++;
+
+      } 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 ) {
+               sprintf(tform,"%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:      sprintf(tform,"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;
+            sprintf(tform,"%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<nRngs; i++ ) {
+         Info.dataPtr = NULL;
+         Info.maxRows = end[i]-start[i]+1;
+
+          /*
+            If there is only 1 range, and it includes all the rows,
+            and there are 10 or more rows, then set nPerLp = 0 so
+            that the iterator function will dynamically choose the
+            most efficient number of rows to process in each loop.
+            Otherwise, set nPerLp to the number of rows in this range.
+         */
+
+         if( (Info.maxRows >= 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:
+         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 && i<maxdim; i++ )
+      naxes[i] = result->value.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<gParse.nCols; col++ ) {
+         if( gParse.varData[col].undef == NULL ) continue;
+         if( gParse.varData[col].type  == BITSTR )
+           FREE( ((char**)gParse.varData[col].data)[0] );
+         free( gParse.varData[col].undef );
+      }
+      FREE( gParse.varData );
+      gParse.nCols = 0;
+   }
+
+   if( gParse.nNodes > 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; kk<ntodo; kk++ )
+                for( jj=0; jj<repeat; jj++ )
+                   ffcvtn( gParse.datatype,
+                           &(result->value.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; kk<ntodo; kk++ )
+                   for( jj=0; jj<repeat; jj++ ) {
+                      ffcvtn( gParse.datatype,
+                              (char*)result->value.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; kk<ntodo; kk++ ) {
+                   ffcvtn( gParse.datatype,
+                           (char*)result->value.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; kk<ntodo; kk++ ) {
+                for( jj=0; jj<result->value.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; kk<ntodo; kk++ )
+                   for( jj=0; jj<result->value.nelem; jj++ ) {
+                      ((char*)Data)[ jj+kk*result->value.nelem ] =
+                         ( result->value.data.str[jj]=='1' );
+                   }
+             } else {
+                for( kk=0; kk<ntodo; kk++ )
+                   for( jj=0; jj<result->value.nelem; jj++ ) {
+                      ((char*)Data)[ jj+kk*result->value.nelem ] =
+                         ( result->value.data.strptr[kk][jj]=='1' );
+                   }
+             }
+             break; 
+          case TSTRING:
+             if( constant ) {
+                for( jj=0; jj<ntodo; jj++ ) {
+                   strcpy( ((char**)Data)[jj], result->value.data.str );
+                }
+             } else {
+                for( jj=0; jj<ntodo; jj++ ) {
+                   strcpy( ((char**)Data)[jj], result->value.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; jj<ntodo; jj++ )
+                   strcpy( ((char**)Data)[jj], result->value.data.str );
+             } else {
+                for( jj=0; jj<ntodo; jj++ )
+                   if( result->value.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->maxRows<totalrows) {
+                  return (-1);
+           }
+    }
+
+    return(gParse.status);  /* return successful status */
+}
+
+static void Setup_DataArrays( int nCols, iteratorCol *cols,
+                              long fRow, long nRows )
+    /***********************************************************************/
+    /*  Setup the varData array in gParse to contain the fits column data. */
+    /*  Then, allocate and initialize the necessary UNDEF arrays for each  */
+    /*  column used by the parser.                                         */
+    /***********************************************************************/
+{
+   int     i;
+   long    nelem, len, row, idx;
+   char  **bitStrs;
+   char  **sptr;
+   char   *barray;
+   long   *iarray;
+   double *rarray;
+   char msg[80];
+
+   gParse.firstDataRow = fRow;
+   gParse.nDataRows    = nRows;
+
+   /*  Resize and fill in UNDEF arrays for each column  */
+
+   for( i=0; i<nCols; i++ ) {
+
+      iteratorCol *icol = cols + i;
+      DataInfo *varData = gParse.varData + i;
+
+      if( icol->iotype == 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; row<nRows; row++ ) {
+            bitStrs[row] = bitStrs[0] + row*(nelem+1);
+            idx = (row)*( (nelem+7)/8 ) + 1;
+            for(len=0; len<nelem; len++) {
+               if( ((char*)icol->array)[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:
+         sprintf(msg, "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<ntodo; i++ )
+            if( ((unsigned char*)input)[i] )
+                ((unsigned char*)output)[i] = 1;
+            else
+                ((unsigned char*)output)[i] = 0;
+         break;
+      case TSHORT:
+         for( i=0; i<ntodo; i++ )
+            if( ((short*)input)[i] )
+                ((unsigned char*)output)[i] = 1;
+            else
+                ((unsigned char*)output)[i] = 0;
+         break;
+      case TLONG:
+         for( i=0; i<ntodo; i++ )
+            if( ((long*)input)[i] )
+                ((unsigned char*)output)[i] = 1;
+            else
+                ((unsigned char*)output)[i] = 0;
+         break;
+      case TFLOAT:
+         for( i=0; i<ntodo; i++ )
+            if( ((float*)input)[i] )
+                ((unsigned char*)output)[i] = 1;
+            else
+                ((unsigned char*)output)[i] = 0;
+         break;
+      case TDOUBLE:
+         for( i=0; i<ntodo; i++ )
+            if( ((double*)input)[i] )
+                ((unsigned char*)output)[i] = 1;
+            else
+                ((unsigned char*)output)[i] = 0;
+         break;
+      default:
+         *status = BAD_DATATYPE;
+         break;
+      }
+      for(i=0;i<ntodo;i++) {
+         if( undef[i] ) {
+            ((unsigned char*)output)[i] = *(unsigned char*)nulval;
+            *anynull = 1;
+         }
+      }
+      break;
+
+   case TBYTE:
+      switch( inputType ) {
+      case TLOGICAL:
+      case TBYTE:
+         for( i=0; i<ntodo; i++ )
+            ((unsigned char*)output)[i] = ((unsigned char*)input)[i];
+         break;
+      case TSHORT:
+         fffi2i1((short*)input,ntodo,1.,0.,0,0,0,NULL,NULL,(unsigned char*)output,status);
+         break;
+      case TLONG:
+         for (i = 0; i < ntodo; i++) {
+            if( undef[i] ) {
+               ((unsigned char*)output)[i] = *(unsigned char*)nulval;
+               *anynull = 1;
+            } else {
+               if( ((long*)input)[i] < 0 ) {
+                  *status = OVERFLOW_ERR;
+                  ((unsigned char*)output)[i] = 0;
+               } else if( ((long*)input)[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<ntodo;i++) {
+         if( undef[i] ) {
+            ((unsigned char*)output)[i] = *(unsigned char*)nulval;
+            *anynull = 1;
+         }
+      }
+      break;
+
+   case TSHORT:
+      switch( inputType ) {
+      case TLOGICAL:
+      case TBYTE:
+         for( i=0; i<ntodo; i++ )
+            ((short*)output)[i] = ((unsigned char*)input)[i];
+         break;
+      case TSHORT:
+         for( i=0; i<ntodo; i++ )
+            ((short*)output)[i] = ((short*)input)[i];
+         break;
+      case TLONG:
+         for (i = 0; i < ntodo; i++) {
+            if( undef[i] ) {
+               ((short*)output)[i] = *(short*)nulval;
+               *anynull = 1;
+            } else {
+               if( ((long*)input)[i] < SHRT_MIN ) {
+                  *status = OVERFLOW_ERR;
+                  ((short*)output)[i] = SHRT_MIN;
+               } else if ( ((long*)input)[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<ntodo;i++) {
+         if( undef[i] ) {
+            ((short*)output)[i] = *(short*)nulval;
+            *anynull = 1;
+         }
+      }
+      break;
+
+   case TINT:
+      switch( inputType ) {
+      case TLOGICAL:
+      case TBYTE:
+         for( i=0; i<ntodo; i++ )
+            ((int*)output)[i] = ((unsigned char*)input)[i];
+         break;
+      case TSHORT:
+         for( i=0; i<ntodo; i++ )
+            ((int*)output)[i] = ((short*)input)[i];
+         break;
+      case TLONG:
+         for( i=0; i<ntodo; i++ )
+            ((int*)output)[i] = ((long*)input)[i];
+         break;
+      case TFLOAT:
+         fffr4int((float*)input,ntodo,1.,0.,0,0,NULL,NULL,
+                  (int*)output,status);
+         break;
+      case TDOUBLE:
+         fffr8int((double*)input,ntodo,1.,0.,0,0,NULL,NULL,
+                  (int*)output,status);
+         break;
+      default:
+         *status = BAD_DATATYPE;
+         break;
+      }
+      for(i=0;i<ntodo;i++) {
+         if( undef[i] ) {
+            ((int*)output)[i] = *(int*)nulval;
+            *anynull = 1;
+         }
+      }
+      break;
+
+   case TLONG:
+      switch( inputType ) {
+      case TLOGICAL:
+      case TBYTE:
+         for( i=0; i<ntodo; i++ )
+            ((long*)output)[i] = ((unsigned char*)input)[i];
+         break;
+      case TSHORT:
+         for( i=0; i<ntodo; i++ )
+            ((long*)output)[i] = ((short*)input)[i];
+         break;
+      case TLONG:
+         for( i=0; i<ntodo; i++ )
+            ((long*)output)[i] = ((long*)input)[i];
+         break;
+      case TFLOAT:
+         fffr4i4((float*)input,ntodo,1.,0.,0,0,NULL,NULL,
+                 (long*)output,status);
+         break;
+      case TDOUBLE:
+         fffr8i4((double*)input,ntodo,1.,0.,0,0,NULL,NULL,
+                 (long*)output,status);
+         break;
+      default:
+         *status = BAD_DATATYPE;
+         break;
+      }
+      for(i=0;i<ntodo;i++) {
+         if( undef[i] ) {
+            ((long*)output)[i] = *(long*)nulval;
+            *anynull = 1;
+         }
+      }
+      break;
+
+   case TLONGLONG:
+      switch( inputType ) {
+      case TLOGICAL:
+      case TBYTE:
+         for( i=0; i<ntodo; i++ )
+            ((LONGLONG*)output)[i] = ((unsigned char*)input)[i];
+         break;
+      case TSHORT:
+         for( i=0; i<ntodo; i++ )
+            ((LONGLONG*)output)[i] = ((short*)input)[i];
+         break;
+      case TLONG:
+         for( i=0; i<ntodo; i++ )
+            ((LONGLONG*)output)[i] = ((long*)input)[i];
+         break;
+      case TFLOAT:
+         fffr4i8((float*)input,ntodo,1.,0.,0,0,NULL,NULL,
+                 (LONGLONG*)output,status);
+         break;
+      case TDOUBLE:
+         fffr8i8((double*)input,ntodo,1.,0.,0,0,NULL,NULL,
+                 (LONGLONG*)output,status);
+
+         break;
+      default:
+         *status = BAD_DATATYPE;
+         break;
+      }
+      for(i=0;i<ntodo;i++) {
+         if( undef[i] ) {
+            ((LONGLONG*)output)[i] = *(LONGLONG*)nulval;
+            *anynull = 1;
+         }
+      }
+      break;
+
+   case TFLOAT:
+      switch( inputType ) {
+      case TLOGICAL:
+      case TBYTE:
+         for( i=0; i<ntodo; i++ )
+            ((float*)output)[i] = ((unsigned char*)input)[i];
+         break;
+      case TSHORT:
+         for( i=0; i<ntodo; i++ )
+            ((float*)output)[i] = ((short*)input)[i];
+         break;
+      case TLONG:
+         for( i=0; i<ntodo; i++ )
+            ((float*)output)[i] = (float) ((long*)input)[i];
+         break;
+      case TFLOAT:
+         for( i=0; i<ntodo; i++ )
+            ((float*)output)[i] = ((float*)input)[i];
+         break;
+      case TDOUBLE:
+         fffr8r4((double*)input,ntodo,1.,0.,0,0,NULL,NULL,
+                 (float*)output,status);
+         break;
+      default:
+         *status = BAD_DATATYPE;
+         break;
+      }
+      for(i=0;i<ntodo;i++) {
+         if( undef[i] ) {
+            ((float*)output)[i] = *(float*)nulval;
+            *anynull = 1;
+         }
+      }
+      break;
+
+   case TDOUBLE:
+      switch( inputType ) {
+      case TLOGICAL:
+      case TBYTE:
+         for( i=0; i<ntodo; i++ )
+            ((double*)output)[i] = ((unsigned char*)input)[i];
+         break;
+      case TSHORT:
+         for( i=0; i<ntodo; i++ )
+            ((double*)output)[i] = ((short*)input)[i];
+         break;
+      case TLONG:
+         for( i=0; i<ntodo; i++ )
+            ((double*)output)[i] = ((long*)input)[i];
+         break;
+      case TFLOAT:
+         for( i=0; i<ntodo; i++ )
+            ((double*)output)[i] = ((float*)input)[i];
+         break;
+      case TDOUBLE:
+         for( i=0; i<ntodo; i++ )
+            ((double*)output)[i] = ((double*)input)[i];
+         break;
+      default:
+         *status = BAD_DATATYPE;
+         break;
+      }
+      for(i=0;i<ntodo;i++) {
+         if( undef[i] ) {
+            ((double*)output)[i] = *(double*)nulval;
+            *anynull = 1;
+         }
+      }
+      break;
+
+   default:
+      *status = BAD_DATATYPE;
+      break;
+   }
+
+   return ( *status );
+}
+
+/*---------------------------------------------------------------------------*/
+int fffrwc( fitsfile *fptr,        /* I - Input FITS file                    */
+            char     *expr,        /* I - Boolean expression                 */
+            char     *timeCol,     /* I - Name of time column                */
+            char     *parCol,      /* I - Name of parameter column           */
+            char     *valCol,      /* I - Name of value column               */
+            long     ntimes,       /* I - Number of distinct times in file   */
+            double   *times,       /* O - Array of times in file             */
+            char     *time_status, /* O - Array of boolean results           */
+            int      *status )     /* O - Error status                       */
+/*                                                                           */
+/* Evaluate a boolean expression for each time in a compressed file,         */
+/* returning an array of flags indicating which times evaluated to TRUE/FALSE*/
+/*---------------------------------------------------------------------------*/
+{
+   parseInfo Info;
+   long alen, width;
+   int parNo, typecode;
+   int naxis, constant, nCol=0;
+   long nelem, naxes[MAXDIMS], elem;
+   char result;
+
+   if( *status ) return( *status );
+
+   fits_get_colnum( fptr, CASEINSEN, timeCol, &gParse.timeCol, status );
+   fits_get_colnum( fptr, CASEINSEN, parCol,  &gParse.parCol , status );
+   fits_get_colnum( fptr, CASEINSEN, valCol,  &gParse.valCol, status );
+   if( *status ) return( *status );
+   
+   if( ffiprs( fptr, 1, expr, MAXDIMS, &Info.datatype, &nelem,
+               &naxis, naxes, status ) ) {
+      ffcprs();
+      return( *status );
+   }
+   if( nelem<0 ) {
+      constant = 1;
+      nelem = -nelem;
+      nCol = gParse.nCols;
+      gParse.nCols = 0;    /*  Ignore all column references  */
+   } else
+      constant = 0;
+
+   if( Info.datatype!=TLOGICAL || nelem!=1 ) {
+      ffcprs();
+      ffpmsg("Expression does not evaluate to a logical scalar.");
+      return( *status = PARSE_BAD_TYPE );
+   }
+
+   /*******************************************/
+   /* Allocate data arrays for each parameter */
+   /*******************************************/
+   
+   parNo = gParse.nCols;
+   while( parNo-- ) {
+      switch( gParse.colData[parNo].datatype ) {
+      case TLONG:
+         if( (gParse.colData[parNo].array =
+              (long *)malloc( (ntimes+1)*sizeof(long) )) )
+            ((long*)gParse.colData[parNo].array)[0] = 1234554321;
+         else
+            *status = MEMORY_ALLOCATION;
+         break;
+      case TDOUBLE:
+         if( (gParse.colData[parNo].array =
+              (double *)malloc( (ntimes+1)*sizeof(double) )) )
+            ((double*)gParse.colData[parNo].array)[0] = DOUBLENULLVALUE;
+         else
+            *status = MEMORY_ALLOCATION;
+         break;
+      case TSTRING:
+         if( !fits_get_coltype( fptr, gParse.valCol, &typecode,
+                                &alen, &width, status ) ) {
+            alen++;
+            if( (gParse.colData[parNo].array =
+                 (char **)malloc( (ntimes+1)*sizeof(char*) )) ) {
+               if( (((char **)gParse.colData[parNo].array)[0] =
+                    (char *)malloc( (ntimes+1)*sizeof(char)*alen )) ) {
+                  for( elem=1; elem<=ntimes; elem++ )
+                     ((char **)gParse.colData[parNo].array)[elem] =
+                        ((char **)gParse.colData[parNo].array)[elem-1]+alen;
+                  ((char **)gParse.colData[parNo].array)[0][0] = '\0';
+               } else {
+                  free( gParse.colData[parNo].array );
+                  *status = MEMORY_ALLOCATION;
+               }
+            } else {
+               *status = MEMORY_ALLOCATION;
+            }
+         }
+         break;
+      }
+      if( *status ) {
+         while( parNo-- ) {
+            if( gParse.colData[parNo].datatype==TSTRING )
+               FREE( ((char **)gParse.colData[parNo].array)[0] );
+            FREE( gParse.colData[parNo].array );
+         }
+         return( *status );
+      }
+   }
+   
+   /**********************************************************************/
+   /* Read data from columns needed for the expression and then parse it */
+   /**********************************************************************/
+   
+   if( !uncompress_hkdata( fptr, ntimes, times, status ) ) {
+      if( constant ) {
+         result = gParse.Nodes[gParse.resultNode].value.data.log;
+         elem = ntimes;
+         while( elem-- ) time_status[elem] = result;
+      } else {
+         Info.dataPtr  = time_status;
+         Info.nullPtr  = NULL;
+         Info.maxRows  = ntimes;
+         *status       = parse_data( ntimes, 0, 1, ntimes, gParse.nCols,
+                                     gParse.colData, (void*)&Info );
+      }
+   }
+   
+   /************/
+   /* Clean up */
+   /************/
+   
+   parNo = gParse.nCols;
+   while ( parNo-- ) {
+      if( gParse.colData[parNo].datatype==TSTRING )
+         FREE( ((char **)gParse.colData[parNo].array)[0] );
+      FREE( gParse.colData[parNo].array );
+   }
+   
+   if( constant ) gParse.nCols = nCol;
+
+   ffcprs();
+   return(*status);
+}
+
+/*---------------------------------------------------------------------------*/
+int uncompress_hkdata( fitsfile *fptr,
+                       long     ntimes,
+                       double   *times,
+                       int      *status )
+/*                                                                           */
+/* description                                                               */
+/*---------------------------------------------------------------------------*/
+{
+   char parName[256], *sPtr[1], found[1000];
+   int parNo, anynul;
+   long naxis2, row, currelem;
+   double currtime, newtime;
+
+   sPtr[0] = parName;
+   currelem = 0;
+   currtime = -1e38;
+
+   parNo=gParse.nCols;
+   while( parNo-- ) found[parNo] = 0;
+
+   if( ffgkyj( fptr, "NAXIS2", &naxis2, NULL, status ) ) return( *status );
+
+   for( row=1; row<=naxis2; row++ ) {
+      if( ffgcvd( fptr, gParse.timeCol, row, 1L, 1L, 0.0,
+                  &newtime, &anynul, status ) ) return( *status );
+      if( newtime != currtime ) {
+         /*  New time encountered... propogate parameters to next row  */
+         if( currelem==ntimes ) {
+            ffpmsg("Found more unique time stamps than caller indicated");
+            return( *status = PARSE_BAD_COL );
+         }
+         times[currelem++] = currtime = newtime;
+         parNo = gParse.nCols;
+         while( parNo-- ) {
+            switch( gParse.colData[parNo].datatype ) {
+            case TLONG:
+               ((long*)gParse.colData[parNo].array)[currelem] =
+                  ((long*)gParse.colData[parNo].array)[currelem-1];
+               break;
+            case TDOUBLE:
+               ((double*)gParse.colData[parNo].array)[currelem] =
+                  ((double*)gParse.colData[parNo].array)[currelem-1];
+               break;
+            case TSTRING:
+               strcpy( ((char **)gParse.colData[parNo].array)[currelem],
+                       ((char **)gParse.colData[parNo].array)[currelem-1] );
+               break;
+            }
+         }
+      }
+
+      if( ffgcvs( fptr, gParse.parCol, row, 1L, 1L, "",
+                  sPtr, &anynul, status ) ) return( *status );
+      parNo = gParse.nCols;
+      while( parNo-- )
+         if( !strcasecmp( parName, gParse.varData[parNo].name ) ) break;
+
+      if( parNo>=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( currelem<ntimes ) {
+      ffpmsg("Found fewer unique time stamps than caller indicated");
+      return( *status = PARSE_BAD_COL );
+   }
+
+   /*  Check for any parameters which were not located in the table  */
+   parNo = gParse.nCols;
+   while( parNo-- )
+      if( !found[parNo] ) {
+         sprintf( parName, "Parameter not found: %-30s", 
+                  gParse.varData[parNo].name );
+         ffpmsg( parName );
+         *status = PARSE_SYNTAX_ERR;
+      }
+   return( *status );
+}
+
+/*---------------------------------------------------------------------------*/
+int ffffrw( fitsfile *fptr,         /* I - Input FITS file                   */
+            char     *expr,         /* I - Boolean expression                */
+            long     *rownum,       /* O - First row of table to eval to T   */
+            int      *status )      /* O - Error status                      */
+/*                                                                           */
+/* Evaluate a boolean expression, returning the row number of the first      */
+/* row which evaluates to TRUE                                               */
+/*---------------------------------------------------------------------------*/
+{
+   int naxis, constant, dtype;
+   long nelem, naxes[MAXDIMS];
+   char result;
+
+   if( *status ) return( *status );
+
+   FFLOCK;
+   if( ffiprs( fptr, 0, expr, MAXDIMS, &dtype, &nelem, &naxis,
+               naxes, status ) ) {
+      ffcprs();
+      FFUNLOCK;
+      return( *status );
+   }
+   if( nelem<0 ) {
+      constant = 1;
+      nelem = -nelem;
+   } else
+      constant = 0;
+
+   if( dtype!=TLOGICAL || nelem!=1 ) {
+      ffcprs();
+      ffpmsg("Expression does not evaluate to a logical scalar.");
+      FFUNLOCK;
+      return( *status = PARSE_BAD_TYPE );
+   }
+
+   *rownum = 0;
+   if( constant ) { /* No need to call parser... have result from ffiprs */
+      result = gParse.Nodes[gParse.resultNode].value.data.log;
+      if( result ) {
+         /*  Make sure there is at least 1 row in table  */
+         ffgnrw( fptr, &nelem, status );
+         if( nelem )
+            *rownum = 1;
+      }
+   } else {
+      if( ffiter( gParse.nCols, gParse.colData, 0, 0,
+                  ffffrw_work, (void*)rownum, status ) == -1 )
+         *status = 0;  /* -1 indicates exitted without error before end... OK */
+   }
+
+   ffcprs();
+   FFUNLOCK;
+   return(*status);
+}
+
+/*---------------------------------------------------------------------------*/
+int ffffrw_work(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 searches for the        */
+/* first row which evaluates to TRUE.                                        */
+/*---------------------------------------------------------------------------*/
+{
+    long idx;
+    Node *result;
+
+    Evaluate_Parser( firstrow, nrows );
+
+    if( !gParse.status ) {
+
+       result = gParse.Nodes + gParse.resultNode;
+       if( result->operation==CONST_OP ) {
+
+          if( result->value.data.log ) {
+             *(long*)userPtr = firstrow;
+             return( -1 );
+          }
+
+       } else {
+
+          for( idx=0; idx<nrows; idx++ )
+             if( result->value.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:
+         sprintf(temp, "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 (!strcasecmp(colName, gParse.pixFilter->tag[i]))
+         colnum = i;
+   }
+   if (colnum < 0) {
+      sprintf(temp, "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. 
+      */
+      sprintf(temp,"TZERO%d",colnum);
+      istatus = 0;
+      if(fits_read_key(fptr,TDOUBLE,temp,&tzero,NULL,&istatus)) {
+          tzero = 0.0;
+      } 
+      sprintf(temp,"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 ) {
+	sprintf(temp, "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) {
+        sprintf(temp, "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  */
+         sprintf(keyvalue, "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; row<nRows; row++ ) {
+         idx = (row)*( (nelem+7)/8 ) + 1;
+         for(len=0; len<nelem; len++) {
+            if( bytes[idx] & (1<<(7-len%8)) )
+               bitStrs[row][len] = '1';
+            else
+               bitStrs[row][len] = '0';
+            if( len%8==7 ) idx++;
+         }
+         bitStrs[row][len] = '\0';
+      }
+
+      FREE( (char *)bytes );
+      break;
+   case TSTRING:
+      ffgcfs(var->fptr, 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:
+      sprintf(msg,"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)) {
+            sprintf(msg, "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)) {
+            sprintf(msg, "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:
+           sprintf(msg, "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:
+         sprintf(msg, "pixel_filter: unexpected constant result type [%d]\n",
+                Info.datatype);
+         ffpmsg(msg);
+      }
+   }
+
+CLEANUP:
+   ffcprs();
+   FFUNLOCK;
+   return (*status);
+}
diff --git a/cextern/cfitsio/eval_l.c b/cextern/cfitsio/eval_l.c
new file mode 100644
index 0000000..7dcb5dc
--- /dev/null
+++ b/cextern/cfitsio/eval_l.c
@@ -0,0 +1,2252 @@
+/* A lexical scanner generated by flex */
+
+/* Scanner skeleton version:
+ * $Header: /software/lheasoft/lheavc/hip/cfitsio/eval_l.c,v 3.47 2009/09/04 18:35:05 pence Exp $
+ */
+
+#define FLEX_SCANNER
+#define FF_FLEX_MAJOR_VERSION 2
+#define FF_FLEX_MINOR_VERSION 5
+
+#include <stdio.h>
+
+
+/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */
+#ifdef c_plusplus
+#ifndef __cplusplus
+#define __cplusplus
+#endif
+#endif
+
+
+#ifdef __cplusplus
+
+#include <stdlib.h>
+#include <unistd.h>
+
+/* Use prototypes in function declarations. */
+#define FF_USE_PROTOS
+
+/* The "const" storage-class-modifier is valid. */
+#define FF_USE_CONST
+
+#else	/* ! __cplusplus */
+
+#if __STDC__
+
+#define FF_USE_PROTOS
+#define FF_USE_CONST
+
+#endif	/* __STDC__ */
+#endif	/* ! __cplusplus */
+
+#ifdef __TURBOC__
+ #pragma warn -rch
+ #pragma warn -use
+#include <io.h>
+#include <stdlib.h>
+#define FF_USE_CONST
+#define FF_USE_PROTOS
+#endif
+
+#ifdef FF_USE_CONST
+#define ffconst const
+#else
+#define ffconst
+#endif
+
+
+#ifdef FF_USE_PROTOS
+#define FF_PROTO(proto) proto
+#else
+#define FF_PROTO(proto) ()
+#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. */
+#define FF_BUF_SIZE 16384
+
+typedef struct ff_buffer_state *FF_BUFFER_STATE;
+
+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
+
+/* The funky do-while in the following #define is used to turn the definition
+ * int a single C statement (which needs a semi-colon terminator).  This
+ * avoids problems with code like:
+ *
+ * 	if ( condition_holds )
+ *		ffless( 5 );
+ *	else
+ *		do_something_else();
+ *
+ * Prior to using the do-while the compiler would get upset at the
+ * "else" because it interpreted the "if" statement as being all
+ * done when it reached the ';' after the ffless() call.
+ */
+
+/* Return all but the first 'n' matched characters back to the input stream. */
+
+#define ffless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up fftext. */ \
+		*ff_cp = ff_hold_char; \
+		FF_RESTORE_FF_MORE_OFFSET \
+		ff_c_buf_p = ff_cp = ff_bp + n - FF_MORE_ADJ; \
+		FF_DO_BEFORE_ACTION; /* set up fftext again */ \
+		} \
+	while ( 0 )
+
+#define unput(c) ffunput( c, fftext_ptr )
+
+/* The following is because we cannot portably get our hands on size_t
+ * (without autoconf's help, which isn't available because we want
+ * flex-generated scanners to compile on their own).
+ */
+typedef unsigned int ff_size_t;
+
+
+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;
+
+	/* 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
+	};
+
+static FF_BUFFER_STATE ff_current_buffer = 0;
+
+/* 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".
+ */
+#define FF_CURRENT_BUFFER ff_current_buffer
+
+
+/* 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 = 1;		/* 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 FF_PROTO(( FILE *input_file ));
+
+void ff_switch_to_buffer FF_PROTO(( FF_BUFFER_STATE new_buffer ));
+void ff_load_buffer_state FF_PROTO(( void ));
+FF_BUFFER_STATE ff_create_buffer FF_PROTO(( FILE *file, int size ));
+void ff_delete_buffer FF_PROTO(( FF_BUFFER_STATE b ));
+void ff_init_buffer FF_PROTO(( FF_BUFFER_STATE b, FILE *file ));
+void ff_flush_buffer FF_PROTO(( FF_BUFFER_STATE b ));
+#define FF_FLUSH_BUFFER ff_flush_buffer( ff_current_buffer )
+
+FF_BUFFER_STATE ff_scan_buffer FF_PROTO(( char *base, ff_size_t size ));
+FF_BUFFER_STATE ff_scan_string FF_PROTO(( ffconst char *ff_str ));
+FF_BUFFER_STATE ff_scan_bytes FF_PROTO(( ffconst char *bytes, int len ));
+
+static void *ff_flex_alloc FF_PROTO(( ff_size_t ));
+static void *ff_flex_realloc FF_PROTO(( void *, ff_size_t ));
+static void ff_flex_free FF_PROTO(( void * ));
+
+#define ff_new_buffer ff_create_buffer
+
+#define ff_set_interactive(is_interactive) \
+	{ \
+	if ( ! ff_current_buffer ) \
+		ff_current_buffer = ff_create_buffer( ffin, FF_BUF_SIZE ); \
+	ff_current_buffer->ff_is_interactive = is_interactive; \
+	}
+
+#define ff_set_bol(at_bol) \
+	{ \
+	if ( ! ff_current_buffer ) \
+		ff_current_buffer = ff_create_buffer( ffin, FF_BUF_SIZE ); \
+	ff_current_buffer->ff_at_bol = at_bol; \
+	}
+
+#define FF_AT_BOL() (ff_current_buffer->ff_at_bol)
+
+typedef unsigned char FF_CHAR;
+FILE *ffin = (FILE *) 0, *ffout = (FILE *) 0;
+typedef int ff_state_type;
+extern char *fftext;
+#define fftext_ptr fftext
+
+static ff_state_type ff_get_previous_state FF_PROTO(( void ));
+static ff_state_type ff_try_NUL_trans FF_PROTO(( ff_state_type current_state ));
+static int ff_get_next_buffer FF_PROTO(( void ));
+static void ff_fatal_error FF_PROTO(( 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 = (int) (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
+static ffconst short int 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 int 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 int 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 short int 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 short int 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 short int 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 short int 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;
+
+/* 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"
+#define INITIAL 0
+#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 <math.h>
+#include <string.h>
+#include <ctype.h>
+#ifdef sparc
+#include <malloc.h>
+#else
+#include <stdlib.h>
+#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" );
+
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef FF_SKIP_FFWRAP
+#ifdef __cplusplus
+extern "C" int ffwrap FF_PROTO(( void ));
+#else
+extern int ffwrap FF_PROTO(( void ));
+#endif
+#endif
+
+#ifndef FF_NO_UNPUT
+static void ffunput FF_PROTO(( int c, char *buf_ptr ));
+#endif
+
+#ifndef fftext_ptr
+static void ff_flex_strncpy FF_PROTO(( char *, ffconst char *, int ));
+#endif
+
+#ifdef FF_NEED_STRLEN
+static int ff_flex_strlen FF_PROTO(( ffconst char * ));
+#endif
+
+#ifndef FF_NO_INPUT
+#ifdef __cplusplus
+static int ffinput FF_PROTO(( void ));
+#else
+static int input FF_PROTO(( void ));
+#endif
+#endif
+
+#if FF_STACK_USED
+static int ff_start_stack_ptr = 0;
+static int ff_start_stack_depth = 0;
+static int *ff_start_stack = 0;
+#ifndef FF_NO_PUSH_STATE
+static void ff_push_state FF_PROTO(( int new_state ));
+#endif
+#ifndef FF_NO_POP_STATE
+static void ff_pop_state FF_PROTO(( void ));
+#endif
+#ifndef FF_NO_TOP_STATE
+static int ff_top_state FF_PROTO(( void ));
+#endif
+
+#else
+#define FF_NO_PUSH_STATE 1
+#define FF_NO_POP_STATE 1
+#define FF_NO_TOP_STATE 1
+#endif
+
+#ifdef FF_MALLOC_DECL
+FF_MALLOC_DECL
+#else
+#if __STDC__
+#ifndef __cplusplus
+#include <stdlib.h>
+#endif
+#else
+/* Just try to get by without declaring the routines.  This will fail
+ * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int)
+ * or sizeof(void*) != sizeof(int).
+ */
+#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 (void) fwrite( fftext, ffleng, 1, ffout )
+#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->ff_is_interactive ) \
+		{ \
+		int c = '*', 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 if ( ((result = fread( buf, 1, max_size, ffin )) == 0) \
+		  && ferror( ffin ) ) \
+		FF_FATAL_ERROR( "input in flex scanner failed" );
+#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
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef FF_DECL
+#define FF_DECL int fflex FF_PROTO(( void ))
+#endif
+
+/* 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
+
+FF_DECL
+	{
+	register ff_state_type ff_current_state;
+	register char *ff_cp, *ff_bp;
+	register int ff_act;
+
+#line 142 "eval.l"
+
+
+
+	if ( ff_init )
+		{
+		ff_init = 0;
+
+#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 )
+			ff_current_buffer =
+				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(        !strcasecmp(fftext,"#PI") ) {
+		     fflval.dbl = (double)(4) * atan((double)(1));
+		     return( DOUBLE );
+		  } else if( !strcasecmp(fftext,"#E") ) {
+		     fflval.dbl = exp((double)(1));
+		     return( DOUBLE );
+		  } else if( !strcasecmp(fftext,"#DEG") ) {
+		     fflval.dbl = ((double)4)*atan((double)1)/((double)180);
+		     return( DOUBLE );
+		  } else if( !strcasecmp(fftext,"#ROW") ) {
+		     return( ROWREF );
+		  } else if( !strcasecmp(fftext,"#NULL") ) {
+		     return( NULLREF );
+		  } else if( !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:
+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
+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->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->ff_n_chars;
+			ff_current_buffer->ff_input_file = ffin;
+			ff_current_buffer->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->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->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()
+	{
+	register char *dest = ff_current_buffer->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->ff_ch_buf[ff_n_chars + 1] )
+		FF_FATAL_ERROR(
+		"fatal flex scanner internal error--end of buffer missed" );
+
+	if ( ff_current_buffer->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->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->ff_n_chars = ff_n_chars = 0;
+
+	else
+		{
+		int num_to_read =
+			ff_current_buffer->ff_buf_size - number_to_move - 1;
+
+		while ( num_to_read <= 0 )
+			{ /* Not enough room in the buffer - grow it. */
+#ifdef FF_USES_REJECT
+			FF_FATAL_ERROR(
+"input buffer overflow, can't enlarge buffer because scanner uses REJECT" );
+#else
+
+			/* 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. */
+					ff_flex_realloc( (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->ff_buf_size -
+						number_to_move - 1;
+#endif
+			}
+
+		if ( num_to_read > FF_READ_BUF_SIZE )
+			num_to_read = FF_READ_BUF_SIZE;
+
+		/* Read in more data. */
+		FF_INPUT( (&ff_current_buffer->ff_ch_buf[number_to_move]),
+			ff_n_chars, num_to_read );
+
+		ff_current_buffer->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->ff_buffer_status =
+				FF_BUFFER_EOF_PENDING;
+			}
+		}
+
+	else
+		ret_val = EOB_ACT_CONTINUE_SCAN;
+
+	ff_n_chars += number_to_move;
+	ff_current_buffer->ff_ch_buf[ff_n_chars] = FF_END_OF_BUFFER_CHAR;
+	ff_current_buffer->ff_ch_buf[ff_n_chars + 1] = FF_END_OF_BUFFER_CHAR;
+
+	fftext_ptr = &ff_current_buffer->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()
+	{
+	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 );
+ */
+
+#ifdef FF_USE_PROTOS
+static ff_state_type ff_try_NUL_trans( ff_state_type ff_current_state )
+#else
+static ff_state_type ff_try_NUL_trans( ff_current_state )
+ff_state_type ff_current_state;
+#endif
+	{
+	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;
+	}
+
+
+#ifndef FF_NO_UNPUT
+#ifdef FF_USE_PROTOS
+static void ffunput( int c, register char *ff_bp )
+#else
+static void ffunput( c, ff_bp )
+int c;
+register char *ff_bp;
+#endif
+	{
+	register char *ff_cp = ff_c_buf_p;
+
+	/* undo effects of setting up fftext */
+	*ff_cp = ff_hold_char;
+
+	if ( ff_cp < ff_current_buffer->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->ff_ch_buf[
+					ff_current_buffer->ff_buf_size + 2];
+		register char *source =
+				&ff_current_buffer->ff_ch_buf[number_to_move];
+
+		while ( source > ff_current_buffer->ff_ch_buf )
+			*--dest = *--source;
+
+		ff_cp += (int) (dest - source);
+		ff_bp += (int) (dest - source);
+		ff_current_buffer->ff_n_chars =
+			ff_n_chars = ff_current_buffer->ff_buf_size;
+
+		if ( ff_cp < ff_current_buffer->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;
+	}
+#endif	/* ifndef FF_NO_UNPUT */
+
+
+#ifdef __cplusplus
+static int ffinput()
+#else
+static int input()
+#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->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 );
+
+					/* fall through */
+
+				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;
+	}
+
+
+#ifdef FF_USE_PROTOS
+void ffrestart( FILE *input_file )
+#else
+void ffrestart( input_file )
+FILE *input_file;
+#endif
+	{
+	if ( ! ff_current_buffer )
+		ff_current_buffer = ff_create_buffer( ffin, FF_BUF_SIZE );
+
+	ff_init_buffer( ff_current_buffer, input_file );
+	ff_load_buffer_state();
+	}
+
+
+#ifdef FF_USE_PROTOS
+void ff_switch_to_buffer( FF_BUFFER_STATE new_buffer )
+#else
+void ff_switch_to_buffer( new_buffer )
+FF_BUFFER_STATE new_buffer;
+#endif
+	{
+	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->ff_buf_pos = ff_c_buf_p;
+		ff_current_buffer->ff_n_chars = ff_n_chars;
+		}
+
+	ff_current_buffer = 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;
+	}
+
+
+#ifdef FF_USE_PROTOS
+void ff_load_buffer_state( void )
+#else
+void ff_load_buffer_state()
+#endif
+	{
+	ff_n_chars = ff_current_buffer->ff_n_chars;
+	fftext_ptr = ff_c_buf_p = ff_current_buffer->ff_buf_pos;
+	ffin = ff_current_buffer->ff_input_file;
+	ff_hold_char = *ff_c_buf_p;
+	}
+
+
+#ifdef FF_USE_PROTOS
+FF_BUFFER_STATE ff_create_buffer( FILE *file, int size )
+#else
+FF_BUFFER_STATE ff_create_buffer( file, size )
+FILE *file;
+int size;
+#endif
+	{
+	FF_BUFFER_STATE b;
+
+	b = (FF_BUFFER_STATE) ff_flex_alloc( 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 *) ff_flex_alloc( 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;
+	}
+
+
+#ifdef FF_USE_PROTOS
+void ff_delete_buffer( FF_BUFFER_STATE b )
+#else
+void ff_delete_buffer( b )
+FF_BUFFER_STATE b;
+#endif
+	{
+	if ( ! b )
+		return;
+
+	if ( b == ff_current_buffer )
+		ff_current_buffer = (FF_BUFFER_STATE) 0;
+
+	if ( b->ff_is_our_buffer )
+		ff_flex_free( (void *) b->ff_ch_buf );
+
+	ff_flex_free( (void *) b );
+	}
+
+
+#ifndef FF_ALWAYS_INTERACTIVE
+#ifndef FF_NEVER_INTERACTIVE
+extern int isatty FF_PROTO(( int ));
+#endif
+#endif
+
+#ifdef FF_USE_PROTOS
+void ff_init_buffer( FF_BUFFER_STATE b, FILE *file )
+#else
+void ff_init_buffer( b, file )
+FF_BUFFER_STATE b;
+FILE *file;
+#endif
+
+
+	{
+	ff_flush_buffer( b );
+
+	b->ff_input_file = file;
+	b->ff_fill_buffer = 1;
+
+#if FF_ALWAYS_INTERACTIVE
+	b->ff_is_interactive = 1;
+#else
+#if FF_NEVER_INTERACTIVE
+	b->ff_is_interactive = 0;
+#else
+	b->ff_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
+#endif
+#endif
+	}
+
+
+#ifdef FF_USE_PROTOS
+void ff_flush_buffer( FF_BUFFER_STATE b )
+#else
+void ff_flush_buffer( b )
+FF_BUFFER_STATE b;
+#endif
+
+	{
+	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();
+	}
+
+
+#ifndef FF_NO_SCAN_BUFFER
+#ifdef FF_USE_PROTOS
+FF_BUFFER_STATE ff_scan_buffer( char *base, ff_size_t size )
+#else
+FF_BUFFER_STATE ff_scan_buffer( base, size )
+char *base;
+ff_size_t size;
+#endif
+	{
+	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) ff_flex_alloc( 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;
+	}
+#endif
+
+
+#ifndef FF_NO_SCAN_STRING
+#ifdef FF_USE_PROTOS
+FF_BUFFER_STATE ff_scan_string( ffconst char *ff_str )
+#else
+FF_BUFFER_STATE ff_scan_string( ff_str )
+ffconst char *ff_str;
+#endif
+	{
+	int len;
+	for ( len = 0; ff_str[len]; ++len )
+		;
+
+	return ff_scan_bytes( ff_str, len );
+	}
+#endif
+
+
+#ifndef FF_NO_SCAN_BYTES
+#ifdef FF_USE_PROTOS
+FF_BUFFER_STATE ff_scan_bytes( ffconst char *bytes, int len )
+#else
+FF_BUFFER_STATE ff_scan_bytes( bytes, len )
+ffconst char *bytes;
+int len;
+#endif
+	{
+	FF_BUFFER_STATE b;
+	char *buf;
+	ff_size_t n;
+	int i;
+
+	/* Get memory for full buffer, including space for trailing EOB's. */
+	n = len + 2;
+	buf = (char *) ff_flex_alloc( n );
+	if ( ! buf )
+		FF_FATAL_ERROR( "out of dynamic memory in ff_scan_bytes()" );
+
+	for ( i = 0; i < len; ++i )
+		buf[i] = bytes[i];
+
+	buf[len] = buf[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;
+	}
+#endif
+
+
+#ifndef FF_NO_PUSH_STATE
+#ifdef FF_USE_PROTOS
+static void ff_push_state( int new_state )
+#else
+static void ff_push_state( new_state )
+int new_state;
+#endif
+	{
+	if ( ff_start_stack_ptr >= ff_start_stack_depth )
+		{
+		ff_size_t new_size;
+
+		ff_start_stack_depth += FF_START_STACK_INCR;
+		new_size = ff_start_stack_depth * sizeof( int );
+
+		if ( ! ff_start_stack )
+			ff_start_stack = (int *) ff_flex_alloc( new_size );
+
+		else
+			ff_start_stack = (int *) ff_flex_realloc(
+					(void *) ff_start_stack, new_size );
+
+		if ( ! ff_start_stack )
+			FF_FATAL_ERROR(
+			"out of memory expanding start-condition stack" );
+		}
+
+	ff_start_stack[ff_start_stack_ptr++] = FF_START;
+
+	BEGIN(new_state);
+	}
+#endif
+
+
+#ifndef FF_NO_POP_STATE
+static void ff_pop_state()
+	{
+	if ( --ff_start_stack_ptr < 0 )
+		FF_FATAL_ERROR( "start-condition stack underflow" );
+
+	BEGIN(ff_start_stack[ff_start_stack_ptr]);
+	}
+#endif
+
+
+#ifndef FF_NO_TOP_STATE
+static int ff_top_state()
+	{
+	return ff_start_stack[ff_start_stack_ptr - 1];
+	}
+#endif
+
+#ifndef FF_EXIT_FAILURE
+#define FF_EXIT_FAILURE 2
+#endif
+
+#ifdef FF_USE_PROTOS
+static void ff_fatal_error( ffconst char msg[] )
+#else
+static void ff_fatal_error( msg )
+char msg[];
+#endif
+	{
+	(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. */ \
+		fftext[ffleng] = ff_hold_char; \
+		ff_c_buf_p = fftext + n; \
+		ff_hold_char = *ff_c_buf_p; \
+		*ff_c_buf_p = '\0'; \
+		ffleng = n; \
+		} \
+	while ( 0 )
+
+
+/* Internal utility routines. */
+
+#ifndef fftext_ptr
+#ifdef FF_USE_PROTOS
+static void ff_flex_strncpy( char *s1, ffconst char *s2, int n )
+#else
+static void ff_flex_strncpy( s1, s2, n )
+char *s1;
+ffconst char *s2;
+int n;
+#endif
+	{
+	register int i;
+	for ( i = 0; i < n; ++i )
+		s1[i] = s2[i];
+	}
+#endif
+
+#ifdef FF_NEED_STRLEN
+#ifdef FF_USE_PROTOS
+static int ff_flex_strlen( ffconst char *s )
+#else
+static int ff_flex_strlen( s )
+ffconst char *s;
+#endif
+	{
+	register int n;
+	for ( n = 0; s[n]; ++n )
+		;
+
+	return n;
+	}
+#endif
+
+
+#ifdef FF_USE_PROTOS
+static void *ff_flex_alloc( ff_size_t size )
+#else
+static void *ff_flex_alloc( size )
+ff_size_t size;
+#endif
+	{
+	return (void *) malloc( size );
+	}
+
+#ifdef FF_USE_PROTOS
+static void *ff_flex_realloc( void *ptr, ff_size_t size )
+#else
+static void *ff_flex_realloc( ptr, size )
+void *ptr;
+ff_size_t size;
+#endif
+	{
+	/* 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 );
+	}
+
+#ifdef FF_USE_PROTOS
+static void ff_flex_free( void *ptr )
+#else
+static void ff_flex_free( ptr )
+void *ptr;
+#endif
+	{
+	free( ptr );
+	}
+
+#if FF_MAIN
+int main()
+	{
+	fflex();
+	return 0;
+	}
+#endif
+#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 ((n<nbytes)&&(gParse.expr[gParse.index] != '\0'));
+     if( gParse.expr[gParse.index] == '\0' ) gParse.is_eobuf = 1;
+ }
+ buf[n] = '\0';
+ return(n);
+}
+
+int ffGetVariable( char *varName, FFSTYPE *thelval )
+{
+   int varNum, type;
+   char errMsg[MAXVARNAME+25];
+
+   varNum = find_variable( varName );
+   if( varNum<0 ) {
+      if( gParse.getData ) {
+	 type = (*gParse.getData)( varName, thelval );
+      } else {
+	 type = pERROR;
+	 gParse.status = PARSE_SYNTAX_ERR;
+	 strcpy (errMsg,"Unable to find data: ");
+	 strncat(errMsg, varName, MAXVARNAME);
+	 ffpmsg (errMsg);
+      }
+   } else {
+      /*  Convert variable type into expression type  */
+      switch( gParse.varData[ varNum ].type ) {
+      case LONG:
+      case DOUBLE:   type =  COLUMN;  break;
+      case BOOLEAN:  type = BCOLUMN;  break;
+      case STRING:   type = SCOLUMN;  break;
+      case BITSTR:   type =  BITCOL;  break;
+      default:
+	 type = pERROR;
+	 gParse.status = PARSE_SYNTAX_ERR;
+	 strcpy (errMsg,"Bad datatype for data: ");
+	 strncat(errMsg, varName, MAXVARNAME);
+	 ffpmsg (errMsg);
+	 break;
+      }
+      thelval->lng = varNum;
+   }
+   return( type );
+}
+
+static int find_variable(char *varName)
+{
+   int i;
+ 
+   if( gParse.nCols )
+      for( i=0; i<gParse.nCols; i++ ) {
+         if( ! strncasecmp(gParse.varData[i].name,varName,MAXVARNAME) ) {
+            return( i );
+         }
+      }
+   return( -1 );
+}
+
+#if defined(vms) || defined(__vms) || defined(WIN32) || defined(__WIN32__) || defined(macintosh)
+
+/* ================================================================== */
+/* A hack for nonunix machines, which lack strcasecmp and strncasecmp */
+/* ================================================================== */
+
+int 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 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);
+}
+
+#endif
diff --git a/cextern/cfitsio/eval_tab.h b/cextern/cfitsio/eval_tab.h
new file mode 100644
index 0000000..aed4459
--- /dev/null
+++ b/cextern/cfitsio/eval_tab.h
@@ -0,0 +1,42 @@
+typedef union {
+    int    Node;        /* Index of Node */
+    double dbl;         /* real value    */
+    long   lng;         /* integer value */
+    char   log;         /* logical value */
+    char   str[MAX_STRLEN];    /* string value  */
+} FFSTYPE;
+#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	EQ	277
+#define	NE	278
+#define	GT	279
+#define	LT	280
+#define	LTE	281
+#define	GTE	282
+#define	POWER	283
+#define	NOT	284
+#define	INTCAST	285
+#define	FLTCAST	286
+#define	UMINUS	287
+#define	ACCUM	288
+#define	DIFF	289
+
+
+extern FFSTYPE fflval;
diff --git a/cextern/cfitsio/eval_y.c b/cextern/cfitsio/eval_y.c
new file mode 100644
index 0000000..e18cf11
--- /dev/null
+++ b/cextern/cfitsio/eval_y.c
@@ -0,0 +1,7333 @@
+
+/*  A Bison parser, made from eval.y
+ by  GNU Bison version 1.25
+  */
+
+#define FFBISON 1  /* Identify Bison output.  */
+
+#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	EQ	277
+#define	NE	278
+#define	GT	279
+#define	LT	280
+#define	LTE	281
+#define	GTE	282
+#define	POWER	283
+#define	NOT	284
+#define	INTCAST	285
+#define	FLTCAST	286
+#define	UMINUS	287
+#define	ACCUM	288
+#define	DIFF	289
+
+#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 <time.h>
+
+#include <stdlib.h>
+
+#ifndef alloca
+#define alloca malloc
+#endif
+
+   /*  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 "eval.y"
+typedef union {
+    int    Node;        /* Index of Node */
+    double dbl;         /* real value    */
+    long   lng;         /* integer value */
+    char   log;         /* logical value */
+    char   str[MAX_STRLEN];    /* string value  */
+} FFSTYPE;
+#include <stdio.h>
+
+#ifndef __cplusplus
+#ifndef __STDC__
+#define const
+#endif
+#endif
+
+
+
+#define	FFFINAL		290
+#define	FFFLAG		-32768
+#define	FFNTBASE	54
+
+#define FFTRANSLATE(x) ((unsigned)(x) <= 289 ? fftranslate[x] : 62)
+
+static const char 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,    30,     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,    28,    29,    31,    32,
+    33,    34,    42,    43,    44,    45,    46,    48,    49
+};
+
+#if FFDEBUG != 0
+static const short ffprhs[] = {     0,
+     0,     1,     4,     6,     9,    12,    15,    18,    21,    24,
+    28,    31,    35,    39,    43,    46,    49,    51,    53,    58,
+    62,    66,    70,    75,    82,    91,   102,   115,   118,   122,
+   124,   126,   128,   133,   135,   137,   141,   145,   149,   153,
+   157,   161,   164,   167,   171,   175,   179,   185,   191,   197,
+   200,   204,   208,   212,   216,   222,   228,   238,   243,   250,
+   259,   270,   283,   286,   289,   292,   295,   297,   299,   304,
+   308,   312,   316,   320,   324,   328,   332,   336,   340,   344,
+   348,   352,   356,   360,   364,   368,   372,   376,   380,   384,
+   388,   392,   396,   402,   408,   412,   416,   420,   426,   434,
+   446,   462,   465,   469,   475,   485,   489,   497,   507,   512,
+   519,   528,   539,   552,   555,   559,   561,   563,   568,   570,
+   574,   578,   584,   590
+};
+
+static const short ffrhs[] = {    -1,
+    54,    55,     0,    50,     0,    58,    50,     0,    59,    50,
+     0,    61,    50,     0,    60,    50,     0,     1,    50,     0,
+    23,    59,     0,    56,    20,    59,     0,    23,    58,     0,
+    57,    20,    58,     0,    57,    20,    59,     0,    56,    20,
+    58,     0,    57,    24,     0,    56,    24,     0,     7,     0,
+    16,     0,    16,    23,    58,    24,     0,    60,    41,    60,
+     0,    60,    40,    60,     0,    60,    35,    60,     0,    60,
+    47,    58,    51,     0,    60,    47,    58,    20,    58,    51,
+     0,    60,    47,    58,    20,    58,    20,    58,    51,     0,
+    60,    47,    58,    20,    58,    20,    58,    20,    58,    51,
+     0,    60,    47,    58,    20,    58,    20,    58,    20,    58,
+    20,    58,    51,     0,    43,    60,     0,    52,    60,    53,
+     0,     4,     0,     5,     0,    13,     0,    13,    23,    58,
+    24,     0,    17,     0,    18,     0,    58,    37,    58,     0,
+    58,    35,    58,     0,    58,    36,    58,     0,    58,    38,
+    58,     0,    58,    39,    58,     0,    58,    42,    58,     0,
+    35,    58,     0,    36,    58,     0,    52,    58,    53,     0,
+    58,    38,    59,     0,    59,    38,    58,     0,    59,    25,
+    58,    22,    58,     0,    59,    25,    59,    22,    58,     0,
+    59,    25,    58,    22,    59,     0,     8,    53,     0,     8,
+    59,    53,     0,     8,    61,    53,     0,     8,    60,    53,
+     0,     8,    58,    53,     0,    10,    61,    20,    61,    53,
+     0,     8,    58,    20,    58,    53,     0,     8,    58,    20,
+    58,    20,    58,    20,    58,    53,     0,    58,    47,    58,
+    51,     0,    58,    47,    58,    20,    58,    51,     0,    58,
+    47,    58,    20,    58,    20,    58,    51,     0,    58,    47,
+    58,    20,    58,    20,    58,    20,    58,    51,     0,    58,
+    47,    58,    20,    58,    20,    58,    20,    58,    20,    58,
+    51,     0,    44,    58,     0,    44,    59,     0,    45,    58,
+     0,    45,    59,     0,     3,     0,    14,     0,    14,    23,
+    58,    24,     0,    60,    28,    60,     0,    60,    29,    60,
+     0,    60,    32,    60,     0,    60,    33,    60,     0,    60,
+    31,    60,     0,    60,    34,    60,     0,    58,    31,    58,
+     0,    58,    32,    58,     0,    58,    34,    58,     0,    58,
+    33,    58,     0,    58,    30,    58,     0,    58,    28,    58,
+     0,    58,    29,    58,     0,    61,    28,    61,     0,    61,
+    29,    61,     0,    61,    31,    61,     0,    61,    34,    61,
+     0,    61,    32,    61,     0,    61,    33,    61,     0,    59,
+    27,    59,     0,    59,    26,    59,     0,    59,    28,    59,
+     0,    59,    29,    59,     0,    58,    21,    58,    22,    58,
+     0,    59,    25,    59,    22,    59,     0,     9,    58,    53,
+     0,     9,    59,    53,     0,     9,    61,    53,     0,     8,
+    59,    20,    59,    53,     0,     9,    58,    20,    58,    20,
+    58,    53,     0,     9,    58,    20,    58,    20,    58,    20,
+    58,    20,    58,    53,     0,     9,    58,    20,    58,    20,
+    58,    20,    58,    20,    58,    20,    58,    20,    58,    53,
+     0,    11,    53,     0,    11,     6,    53,     0,    11,     6,
+    20,    58,    53,     0,    11,     6,    20,    58,    20,     6,
+    20,     6,    53,     0,    12,     6,    53,     0,    12,     6,
+    20,    58,    20,    58,    53,     0,    12,     6,    20,    58,
+    20,    58,    20,     6,    53,     0,    59,    47,    58,    51,
+     0,    59,    47,    58,    20,    58,    51,     0,    59,    47,
+    58,    20,    58,    20,    58,    51,     0,    59,    47,    58,
+    20,    58,    20,    58,    20,    58,    51,     0,    59,    47,
+    58,    20,    58,    20,    58,    20,    58,    20,    58,    51,
+     0,    43,    59,     0,    52,    59,    53,     0,     6,     0,
+    15,     0,    15,    23,    58,    24,     0,    19,     0,    52,
+    61,    53,     0,    61,    35,    61,     0,    59,    25,    61,
+    22,    61,     0,     8,    61,    20,    61,    53,     0,     8,
+    61,    20,    58,    20,    58,    53,     0
+};
+
+#endif
+
+#if FFDEBUG != 0
+static const short ffrline[] = { 0,
+   241,   242,   245,   246,   252,   258,   264,   270,   273,   275,
+   288,   290,   303,   314,   328,   332,   336,   340,   342,   351,
+   354,   357,   366,   368,   370,   372,   374,   376,   379,   383,
+   385,   387,   389,   398,   400,   402,   405,   408,   411,   414,
+   417,   420,   422,   424,   426,   430,   434,   453,   472,   491,
+   504,   518,   530,   561,   659,   667,   729,   753,   755,   757,
+   759,   761,   763,   765,   767,   769,   773,   775,   777,   786,
+   789,   792,   795,   798,   801,   804,   807,   810,   813,   816,
+   819,   822,   825,   828,   831,   834,   837,   840,   843,   845,
+   847,   849,   852,   859,   876,   889,   902,   913,   929,   953,
+   981,  1018,  1022,  1026,  1029,  1033,  1037,  1040,  1044,  1046,
+  1048,  1050,  1052,  1054,  1056,  1060,  1063,  1065,  1074,  1076,
+  1078,  1087,  1106,  1125
+};
+#endif
+
+
+#if FFDEBUG != 0 || defined (FFERROR_VERBOSE)
+
+static const char * const fftname[] = {   "$","error","$undefined.","BOOLEAN",
+"LONG","DOUBLE","STRING","BITSTR","FUNCTION","BFUNCTION","IFUNCTION","GTIFILTER",
+"REGFILTER","COLUMN","BCOLUMN","SCOLUMN","BITCOL","ROWREF","NULLREF","SNULLREF",
+"','","'='","':'","'{'","'}'","'?'","OR","AND","EQ","NE","'~'","GT","LT","LTE",
+"GTE","'+'","'-'","'%'","'*'","'/'","'|'","'&'","POWER","NOT","INTCAST","FLTCAST",
+"UMINUS","'['","ACCUM","DIFF","'\\n'","']'","'('","')'","lines","line","bvector",
+"vector","expr","bexpr","bits","sexpr", NULL
+};
+#endif
+
+static const short ffr1[] = {     0,
+    54,    54,    55,    55,    55,    55,    55,    55,    56,    56,
+    57,    57,    57,    57,    58,    59,    60,    60,    60,    60,
+    60,    60,    60,    60,    60,    60,    60,    60,    60,    58,
+    58,    58,    58,    58,    58,    58,    58,    58,    58,    58,
+    58,    58,    58,    58,    58,    58,    58,    58,    58,    58,
+    58,    58,    58,    58,    58,    58,    58,    58,    58,    58,
+    58,    58,    58,    58,    58,    58,    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,    59,    59,    59,    59,    59,    59,    59,
+    59,    59,    59,    59,    59,    61,    61,    61,    61,    61,
+    61,    61,    61,    61
+};
+
+static const short ffr2[] = {     0,
+     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
+};
+
+static const short ffdefact[] = {     1,
+     0,     0,    67,    30,    31,   116,    17,     0,     0,     0,
+     0,     0,    32,    68,   117,    18,    34,    35,   119,     0,
+     0,     0,     0,     0,     0,     3,     0,     2,     0,     0,
+     0,     0,     0,     0,     8,    50,     0,     0,     0,     0,
+     0,     0,     0,     0,     0,     0,     0,     0,   102,     0,
+     0,     0,     0,     0,    11,     9,     0,    42,    43,   114,
+    28,    63,    64,    65,    66,     0,     0,     0,     0,     0,
+    16,     0,    15,     0,     0,     0,     0,     0,     0,     0,
+     0,     0,     0,     0,     0,     0,     0,     0,     4,     0,
+     0,     0,     0,     0,     0,     0,     5,     0,     0,     0,
+     0,     0,     0,     0,     0,     0,     0,     7,     0,     0,
+     0,     0,     0,     0,     0,     6,     0,    54,     0,    51,
+    53,     0,    52,     0,    95,    96,    97,     0,     0,   103,
+     0,   106,     0,     0,     0,     0,    44,   115,    29,   120,
+    14,    10,    12,    13,     0,    81,    82,    80,    76,    77,
+    79,    78,    37,    38,    36,    39,    45,    40,    41,     0,
+     0,     0,     0,    90,    89,    91,    92,    46,     0,     0,
+     0,    70,    71,    74,    72,    73,    75,    22,    21,    20,
+     0,    83,    84,    85,    87,    88,    86,   121,     0,     0,
+     0,     0,     0,     0,     0,     0,    33,    69,   118,    19,
+     0,     0,    58,     0,     0,     0,     0,   109,    28,     0,
+     0,    23,     0,    56,    98,     0,   123,     0,    55,     0,
+   104,     0,    93,     0,    47,    49,    48,    94,   122,     0,
+     0,     0,     0,     0,     0,     0,     0,    59,     0,   110,
+     0,    24,     0,   124,     0,    99,     0,     0,   107,     0,
+     0,     0,     0,     0,     0,     0,     0,    60,     0,   111,
+     0,    25,    57,     0,   105,   108,     0,     0,     0,     0,
+     0,    61,     0,   112,     0,    26,     0,   100,     0,     0,
+     0,     0,    62,   113,    27,     0,     0,   101,     0,     0
+};
+
+static const short ffdefgoto[] = {     1,
+    28,    29,    30,    45,    46,    43,    57
+};
+
+static const short ffpact[] = {-32768,
+   301,   -41,-32768,-32768,-32768,-32768,-32768,   351,   402,   402,
+    -5,    12,     8,    33,    34,    41,-32768,-32768,-32768,   402,
+   402,   402,   402,   402,   402,-32768,   402,-32768,   -18,     9,
+  1092,   403,  1438,    79,-32768,-32768,   428,   143,   294,    10,
+   456,   224,  1478,   125,  1390,  1436,  1523,    -6,-32768,     2,
+   402,   402,   402,   402,  1390,  1436,  1129,    19,    19,    20,
+    21,    19,    20,    19,    20,   623,   240,   344,  1120,   402,
+-32768,   402,-32768,   402,   402,   402,   402,   402,   402,   402,
+   402,   402,   402,   402,   402,   402,   402,   402,-32768,   402,
+   402,   402,   402,   402,   402,   402,-32768,    -3,    -3,    -3,
+    -3,    -3,    -3,    -3,    -3,    -3,   402,-32768,   402,   402,
+   402,   402,   402,   402,   402,-32768,   402,-32768,   402,-32768,
+-32768,   402,-32768,   402,-32768,-32768,-32768,   402,   402,-32768,
+   402,-32768,  1266,  1286,  1306,  1326,-32768,-32768,-32768,-32768,
+  1390,  1436,  1390,  1436,  1348,  1503,  1503,  1503,    23,    23,
+    23,    23,   160,   160,   160,   -15,    20,   -15,   -15,   732,
+  1370,  1413,  1531,   146,   -13,   -35,   -35,   -15,   756,    -3,
+    -3,   -30,   -30,   -30,   -30,   -30,   -30,    50,    21,    21,
+   780,    67,    67,    11,    11,    11,    11,-32768,   484,  1118,
+  1146,  1415,  1166,  1424,   512,  1186,-32768,-32768,-32768,-32768,
+   402,   402,-32768,   402,   402,   402,   402,-32768,    21,  1480,
+   402,-32768,   402,-32768,-32768,   402,-32768,   402,-32768,    66,
+-32768,   402,  1461,   804,  1461,  1436,  1461,  1436,  1129,   828,
+   852,  1206,   650,   540,    68,   568,   402,-32768,   402,-32768,
+   402,-32768,   402,-32768,   402,-32768,    86,    87,-32768,   876,
+   900,   924,   677,  1226,    52,    56,   402,-32768,   402,-32768,
+   402,-32768,-32768,   402,-32768,-32768,   948,   972,   996,   596,
+   402,-32768,   402,-32768,   402,-32768,   402,-32768,  1020,  1044,
+  1068,  1246,-32768,-32768,-32768,   402,   704,-32768,   126,-32768
+};
+
+static const short ffpgoto[] = {-32768,
+-32768,-32768,-32768,    -1,    95,   124,    27
+};
+
+
+#define	FFLAST		1566
+
+
+static const short fftable[] = {    31,
+    48,    70,    95,     7,   104,    71,    37,    41,    35,   105,
+   106,    96,    16,   129,    93,    94,   107,    50,    55,    58,
+    59,   131,    62,    64,    95,    66,    87,    34,    72,   122,
+    51,    88,    73,    96,    40,    44,    47,   109,   110,   170,
+   111,   112,   113,   114,   115,   115,   130,    49,   171,   133,
+   134,   135,   136,    69,   132,    52,    53,    82,    83,    84,
+    85,    86,   123,    54,    87,    88,    96,   107,   141,    88,
+   143,   235,   145,   146,   147,   148,   149,   150,   151,   152,
+   153,   154,   155,   156,   158,   159,   160,   247,   161,   105,
+   106,   255,   256,   168,   169,    32,   107,   111,   112,   113,
+   114,   115,    38,    42,   265,   181,   109,   110,   266,   111,
+   112,   113,   114,   115,    56,   189,   163,    60,    63,    65,
+   191,    67,   193,     0,    33,   290,     0,   195,   116,   196,
+     0,    39,     0,     0,     0,   182,   183,   184,   185,   186,
+   187,   188,     0,     0,     0,     0,    61,     0,   192,     0,
+    68,     0,   109,   110,   194,   111,   112,   113,   114,   115,
+     0,     0,   119,     0,   142,     0,   144,    90,    91,    92,
+    93,    94,    92,    93,    94,     0,     0,   127,     0,   157,
+    95,     0,     0,    95,   162,   164,   165,   166,   167,    96,
+     0,     0,    96,     0,     0,   120,     0,    85,    86,   223,
+   224,    87,   225,   227,     0,   230,    88,     0,     0,   231,
+     0,   232,     0,   190,   233,     0,   234,     0,     0,     0,
+   236,   172,   173,   174,   175,   176,   177,   178,   179,   180,
+     0,     0,   229,     0,     0,   250,     0,   251,     0,   252,
+     0,   253,     0,   254,     0,     0,     0,     0,    90,    91,
+    92,    93,    94,     0,     0,   267,     0,   268,     0,   269,
+     0,    95,   270,     0,    90,    91,    92,    93,    94,   279,
+    96,   280,     0,   281,     0,   282,   126,    95,     0,     0,
+     0,     0,     0,     0,   287,     0,    96,     0,     0,     0,
+     0,     0,   138,   209,   210,     0,     0,     0,   226,   228,
+   289,     2,     0,     3,     4,     5,     6,     7,     8,     9,
+    10,    11,    12,    13,    14,    15,    16,    17,    18,    19,
+     0,    98,    99,    20,   100,   101,   102,   103,   104,     0,
+     0,     0,     0,   105,   106,    21,    22,     0,     0,     0,
+   107,     0,     0,    23,    24,    25,   121,     0,     0,     0,
+    26,     0,    27,     3,     4,     5,     6,     7,     8,     9,
+    10,    11,    12,    13,    14,    15,    16,    17,    18,    19,
+     0,    98,    99,    20,   100,   101,   102,   103,   104,     0,
+     0,     0,     0,   105,   106,    21,    22,     0,     0,     0,
+   107,     0,     0,    23,    24,    25,   139,     0,     0,     0,
+     0,     0,    27,    36,     3,     4,     5,     6,     7,     8,
+     9,    10,    11,    12,    13,    14,    15,    16,    17,    18,
+    19,     0,     0,     0,    20,     0,     0,    90,    91,    92,
+    93,    94,     0,     0,     0,     0,    21,    22,     0,     0,
+    95,     0,     0,     0,    23,    24,    25,   117,    74,    96,
+     0,     0,    97,    27,     0,    75,    76,    77,    78,    79,
+    80,    81,    82,    83,    84,    85,    86,     0,     0,    87,
+     0,     0,     0,     0,    88,   124,    74,     0,     0,     0,
+   118,     0,     0,    75,    76,    77,    78,    79,    80,    81,
+    82,    83,    84,    85,    86,     0,     0,    87,     0,     0,
+     0,     0,    88,   213,    74,     0,     0,     0,   125,     0,
+     0,    75,    76,    77,    78,    79,    80,    81,    82,    83,
+    84,    85,    86,     0,     0,    87,     0,     0,     0,     0,
+    88,   220,    74,     0,     0,     0,   214,     0,     0,    75,
+    76,    77,    78,    79,    80,    81,    82,    83,    84,    85,
+    86,     0,     0,    87,     0,     0,     0,     0,    88,   245,
+    74,     0,     0,     0,   221,     0,     0,    75,    76,    77,
+    78,    79,    80,    81,    82,    83,    84,    85,    86,     0,
+     0,    87,     0,     0,     0,     0,    88,   248,    74,     0,
+     0,     0,   246,     0,     0,    75,    76,    77,    78,    79,
+    80,    81,    82,    83,    84,    85,    86,     0,     0,    87,
+     0,     0,     0,     0,    88,   277,    74,     0,     0,     0,
+   249,     0,     0,    75,    76,    77,    78,    79,    80,    81,
+    82,    83,    84,    85,    86,     0,     0,    87,     0,     0,
+     0,     0,    88,    74,     0,     0,     0,     0,   278,     0,
+    75,    76,    77,    78,    79,    80,    81,    82,    83,    84,
+    85,    86,     0,     0,    87,     0,     0,     0,     0,    88,
+    74,     0,     0,     0,     0,   137,     0,    75,    76,    77,
+    78,    79,    80,    81,    82,    83,    84,    85,    86,     0,
+     0,    87,     0,     0,     0,     0,    88,    74,     0,     0,
+     0,     0,   244,     0,    75,    76,    77,    78,    79,    80,
+    81,    82,    83,    84,    85,    86,     0,     0,    87,     0,
+     0,     0,     0,    88,    74,     0,     0,     0,     0,   263,
+     0,    75,    76,    77,    78,    79,    80,    81,    82,    83,
+    84,    85,    86,     0,     0,    87,     0,     0,     0,     0,
+    88,   202,    74,     0,     0,     0,   288,     0,     0,    75,
+    76,    77,    78,    79,    80,    81,    82,    83,    84,    85,
+    86,     0,     0,    87,     0,   207,    74,     0,    88,     0,
+     0,     0,   203,    75,    76,    77,    78,    79,    80,    81,
+    82,    83,    84,    85,    86,     0,     0,    87,     0,   211,
+    74,     0,    88,     0,     0,     0,   208,    75,    76,    77,
+    78,    79,    80,    81,    82,    83,    84,    85,    86,     0,
+     0,    87,     0,   237,    74,     0,    88,     0,     0,     0,
+   212,    75,    76,    77,    78,    79,    80,    81,    82,    83,
+    84,    85,    86,     0,     0,    87,     0,   239,    74,     0,
+    88,     0,     0,     0,   238,    75,    76,    77,    78,    79,
+    80,    81,    82,    83,    84,    85,    86,     0,     0,    87,
+     0,   241,    74,     0,    88,     0,     0,     0,   240,    75,
+    76,    77,    78,    79,    80,    81,    82,    83,    84,    85,
+    86,     0,     0,    87,     0,   257,    74,     0,    88,     0,
+     0,     0,   242,    75,    76,    77,    78,    79,    80,    81,
+    82,    83,    84,    85,    86,     0,     0,    87,     0,   259,
+    74,     0,    88,     0,     0,     0,   258,    75,    76,    77,
+    78,    79,    80,    81,    82,    83,    84,    85,    86,     0,
+     0,    87,     0,   261,    74,     0,    88,     0,     0,     0,
+   260,    75,    76,    77,    78,    79,    80,    81,    82,    83,
+    84,    85,    86,     0,     0,    87,     0,   271,    74,     0,
+    88,     0,     0,     0,   262,    75,    76,    77,    78,    79,
+    80,    81,    82,    83,    84,    85,    86,     0,     0,    87,
+     0,   273,    74,     0,    88,     0,     0,     0,   272,    75,
+    76,    77,    78,    79,    80,    81,    82,    83,    84,    85,
+    86,     0,     0,    87,     0,   275,    74,     0,    88,     0,
+     0,     0,   274,    75,    76,    77,    78,    79,    80,    81,
+    82,    83,    84,    85,    86,     0,     0,    87,     0,     0,
+    74,     0,    88,     0,     0,     0,   276,    75,    76,    77,
+    78,    79,    80,    81,    82,    83,    84,    85,    86,     0,
+     0,    87,     0,     0,    74,     0,    88,     0,     0,     0,
+   283,    75,    76,    77,    78,    79,    80,    81,    82,    83,
+    84,    85,    86,     0,     0,    87,     0,     0,    74,     0,
+    88,     0,     0,     0,   284,    75,    76,    77,    78,    79,
+    80,    81,    82,    83,    84,    85,    86,     0,     0,    87,
+     0,     0,    74,     0,    88,     0,     0,     0,   285,    75,
+    76,    77,    78,    79,    80,    81,    82,    83,    84,    85,
+    86,     0,     0,    87,     0,     0,     0,     0,    88,     0,
+     0,    89,    90,    91,    92,    93,    94,   109,   110,     0,
+   111,   112,   113,   114,   115,    95,   109,   110,     0,   111,
+   112,   113,   114,   115,    96,   216,    74,     0,     0,     0,
+   215,     0,   140,    75,    76,    77,    78,    79,    80,    81,
+    82,    83,    84,    85,    86,   218,    74,    87,     0,     0,
+     0,     0,    88,    75,    76,    77,    78,    79,    80,    81,
+    82,    83,    84,    85,    86,   222,    74,    87,     0,     0,
+     0,     0,    88,    75,    76,    77,    78,    79,    80,    81,
+    82,    83,    84,    85,    86,   243,    74,    87,     0,     0,
+     0,     0,    88,    75,    76,    77,    78,    79,    80,    81,
+    82,    83,    84,    85,    86,   264,    74,    87,     0,     0,
+     0,     0,    88,    75,    76,    77,    78,    79,    80,    81,
+    82,    83,    84,    85,    86,   286,    74,    87,     0,     0,
+     0,     0,    88,    75,    76,    77,    78,    79,    80,    81,
+    82,    83,    84,    85,    86,     0,    74,    87,     0,   197,
+     0,     0,    88,    75,    76,    77,    78,    79,    80,    81,
+    82,    83,    84,    85,    86,     0,    74,    87,     0,   198,
+     0,     0,    88,    75,    76,    77,    78,    79,    80,    81,
+    82,    83,    84,    85,    86,     0,    74,    87,     0,   199,
+     0,     0,    88,    75,    76,    77,    78,    79,    80,    81,
+    82,    83,    84,    85,    86,     0,    74,    87,     0,   200,
+     0,     0,    88,    75,    76,    77,    78,    79,    80,    81,
+    82,    83,    84,    85,    86,     0,     0,    87,    74,   201,
+     0,     0,    88,     0,     0,    75,    76,    77,    78,    79,
+    80,    81,    82,    83,    84,    85,    86,     0,     0,    87,
+    74,   204,     0,     0,    88,     0,     0,    75,    76,    77,
+    78,    79,    80,    81,    82,    83,    84,    85,    86,     0,
+    74,    87,     0,     0,     0,     0,    88,    75,    76,    77,
+    78,    79,    80,    81,    82,    83,    84,    85,    86,     0,
+     0,    87,     0,     0,   205,     0,    88,    90,    91,    92,
+    93,    94,   109,   110,     0,   111,   112,   113,   114,   115,
+    95,   109,   110,     0,   111,   112,   113,   114,   115,    96,
+    90,    91,    92,    93,    94,    98,    99,   217,   100,   101,
+   102,   103,   104,    95,     0,     0,   219,   105,   106,     0,
+     0,     0,    96,     0,   107,     0,     0,   108,    75,    76,
+    77,    78,    79,    80,    81,    82,    83,    84,    85,    86,
+     0,     0,    87,     0,     0,    98,    99,    88,   100,   101,
+   102,   103,   104,     0,   104,     0,     0,   105,   106,   105,
+   106,     0,     0,     0,   107,     0,   107,     0,     0,     0,
+     0,     0,   139,    78,    79,    80,    81,    82,    83,    84,
+    85,    86,   128,     0,    87,     0,     0,     0,     0,    88,
+   109,   110,   206,   111,   112,   113,   114,   115,   109,   110,
+     0,   111,   112,   113,   114,   115
+};
+
+static const short ffcheck[] = {     1,
+     6,    20,    38,     7,    35,    24,     8,     9,    50,    40,
+    41,    47,    16,    20,    28,    29,    47,     6,    20,    21,
+    22,    20,    24,    25,    38,    27,    42,     1,    20,    20,
+    23,    47,    24,    47,     8,     9,    10,    28,    29,    43,
+    31,    32,    33,    34,    35,    35,    53,    53,    52,    51,
+    52,    53,    54,    27,    53,    23,    23,    35,    36,    37,
+    38,    39,    53,    23,    42,    47,    47,    47,    70,    47,
+    72,     6,    74,    75,    76,    77,    78,    79,    80,    81,
+    82,    83,    84,    85,    86,    87,    88,    20,    90,    40,
+    41,     6,     6,    95,    96,     1,    47,    31,    32,    33,
+    34,    35,     8,     9,    53,   107,    28,    29,    53,    31,
+    32,    33,    34,    35,    20,   117,    90,    23,    24,    25,
+   122,    27,   124,    -1,     1,     0,    -1,   129,    50,   131,
+    -1,     8,    -1,    -1,    -1,   109,   110,   111,   112,   113,
+   114,   115,    -1,    -1,    -1,    -1,    23,    -1,   122,    -1,
+    27,    -1,    28,    29,   128,    31,    32,    33,    34,    35,
+    -1,    -1,    20,    -1,    70,    -1,    72,    25,    26,    27,
+    28,    29,    27,    28,    29,    -1,    -1,    53,    -1,    85,
+    38,    -1,    -1,    38,    90,    91,    92,    93,    94,    47,
+    -1,    -1,    47,    -1,    -1,    53,    -1,    38,    39,   201,
+   202,    42,   204,   205,    -1,   207,    47,    -1,    -1,   211,
+    -1,   213,    -1,   119,   216,    -1,   218,    -1,    -1,    -1,
+   222,    98,    99,   100,   101,   102,   103,   104,   105,   106,
+    -1,    -1,   206,    -1,    -1,   237,    -1,   239,    -1,   241,
+    -1,   243,    -1,   245,    -1,    -1,    -1,    -1,    25,    26,
+    27,    28,    29,    -1,    -1,   257,    -1,   259,    -1,   261,
+    -1,    38,   264,    -1,    25,    26,    27,    28,    29,   271,
+    47,   273,    -1,   275,    -1,   277,    53,    38,    -1,    -1,
+    -1,    -1,    -1,    -1,   286,    -1,    47,    -1,    -1,    -1,
+    -1,    -1,    53,   170,   171,    -1,    -1,    -1,   204,   205,
+     0,     1,    -1,     3,     4,     5,     6,     7,     8,     9,
+    10,    11,    12,    13,    14,    15,    16,    17,    18,    19,
+    -1,    28,    29,    23,    31,    32,    33,    34,    35,    -1,
+    -1,    -1,    -1,    40,    41,    35,    36,    -1,    -1,    -1,
+    47,    -1,    -1,    43,    44,    45,    53,    -1,    -1,    -1,
+    50,    -1,    52,     3,     4,     5,     6,     7,     8,     9,
+    10,    11,    12,    13,    14,    15,    16,    17,    18,    19,
+    -1,    28,    29,    23,    31,    32,    33,    34,    35,    -1,
+    -1,    -1,    -1,    40,    41,    35,    36,    -1,    -1,    -1,
+    47,    -1,    -1,    43,    44,    45,    53,    -1,    -1,    -1,
+    -1,    -1,    52,    53,     3,     4,     5,     6,     7,     8,
+     9,    10,    11,    12,    13,    14,    15,    16,    17,    18,
+    19,    -1,    -1,    -1,    23,    -1,    -1,    25,    26,    27,
+    28,    29,    -1,    -1,    -1,    -1,    35,    36,    -1,    -1,
+    38,    -1,    -1,    -1,    43,    44,    45,    20,    21,    47,
+    -1,    -1,    50,    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,    -1,    -1,    -1,    -1,    47,    -1,
+    -1,    50,    25,    26,    27,    28,    29,    28,    29,    -1,
+    31,    32,    33,    34,    35,    38,    28,    29,    -1,    31,
+    32,    33,    34,    35,    47,    20,    21,    -1,    -1,    -1,
+    53,    -1,    53,    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,    22,    -1,    47,    25,    26,    27,
+    28,    29,    28,    29,    -1,    31,    32,    33,    34,    35,
+    38,    28,    29,    -1,    31,    32,    33,    34,    35,    47,
+    25,    26,    27,    28,    29,    28,    29,    53,    31,    32,
+    33,    34,    35,    38,    -1,    -1,    53,    40,    41,    -1,
+    -1,    -1,    47,    -1,    47,    -1,    -1,    50,    28,    29,
+    30,    31,    32,    33,    34,    35,    36,    37,    38,    39,
+    -1,    -1,    42,    -1,    -1,    28,    29,    47,    31,    32,
+    33,    34,    35,    -1,    35,    -1,    -1,    40,    41,    40,
+    41,    -1,    -1,    -1,    47,    -1,    47,    -1,    -1,    -1,
+    -1,    -1,    53,    31,    32,    33,    34,    35,    36,    37,
+    38,    39,    20,    -1,    42,    -1,    -1,    -1,    -1,    47,
+    28,    29,    22,    31,    32,    33,    34,    35,    28,    29,
+    -1,    31,    32,    33,    34,    35
+};
+/* -*-C-*-  Note some compilers choke on comments on `#line' lines.  */
+#line 3 "/usr1/local/share/bison.simple"
+
+/* Skeleton output parser for bison,
+   Copyright (C) 1984, 1989, 1990 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 2, 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, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* As a special exception, when this file is copied by Bison into a
+   Bison output file, you may use that output file without restriction.
+   This special exception was added by the Free Software Foundation
+   in version 1.24 of Bison.  */
+
+#ifndef alloca
+#ifdef __GNUC__
+#define alloca __builtin_alloca
+#else /* not GNU C.  */
+#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi)
+#include <alloca.h>
+#else /* not sparc */
+#if defined (MSDOS) && !defined (__TURBOC__)
+#include <malloc.h>
+#else /* not MSDOS, or __TURBOC__ */
+#if defined(_AIX)
+#include <malloc.h>
+ #pragma alloca
+#else /* not MSDOS, __TURBOC__, or _AIX */
+#ifdef __hpux
+#ifdef __cplusplus
+extern "C" {
+void *alloca (unsigned int);
+};
+#else /* not __cplusplus */
+void *alloca ();
+#endif /* not __cplusplus */
+#endif /* __hpux */
+#endif /* not _AIX */
+#endif /* not MSDOS, or __TURBOC__ */
+#endif /* not sparc.  */
+#endif /* not GNU C.  */
+#endif /* alloca not defined.  */
+
+/* This is the parser code that is written into each bison parser
+  when the %semantic_parser declaration is not specified in the grammar.
+  It was written by Richard Stallman by simplifying the hairy parser
+  used when %semantic_parser is specified.  */
+
+/* Note: there must be only one dollar sign in this file.
+   It is replaced by the list of actions, each action
+   as one case of the switch.  */
+
+#define fferrok		(fferrstatus = 0)
+#define ffclearin	(ffchar = FFEMPTY)
+#define FFEMPTY		-2
+#define FFEOF		0
+#define FFACCEPT	return(0)
+#define FFABORT 	return(1)
+#define FFERROR		goto fferrlab1
+/* 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);			\
+      ffchar1 = FFTRANSLATE (ffchar);				\
+      FFPOPSTACK;						\
+      goto ffbackup;						\
+    }								\
+  else								\
+    { fferror ("syntax error: cannot back up"); FFERROR; }	\
+while (0)
+
+#define FFTERROR	1
+#define FFERRCODE	256
+
+#ifndef FFPURE
+#define FFLEX		fflex()
+#endif
+
+#ifdef FFPURE
+#ifdef FFLSP_NEEDED
+#ifdef FFLEX_PARAM
+#define FFLEX		fflex(&fflval, &fflloc, FFLEX_PARAM)
+#else
+#define FFLEX		fflex(&fflval, &fflloc)
+#endif
+#else /* not FFLSP_NEEDED */
+#ifdef FFLEX_PARAM
+#define FFLEX		fflex(&fflval, FFLEX_PARAM)
+#else
+#define FFLEX		fflex(&fflval)
+#endif
+#endif /* not FFLSP_NEEDED */
+#endif
+
+/* If nonreentrant, generate the variables here */
+
+#ifndef FFPURE
+
+int	ffchar;			/*  the lookahead symbol		*/
+FFSTYPE	fflval;			/*  the semantic value of the		*/
+				/*  lookahead symbol			*/
+
+#ifdef FFLSP_NEEDED
+FFLTYPE fflloc;			/*  location data for the lookahead	*/
+				/*  symbol				*/
+#endif
+
+int ffnerrs;			/*  number of parse errors so far       */
+#endif  /* not FFPURE */
+
+#if FFDEBUG != 0
+int ffdebug;			/*  nonzero means print parse trace	*/
+/* Since this is uninitialized, it does not stop multiple parsers
+   from coexisting.  */
+#endif
+
+/*  FFINITDEPTH indicates the initial size of the parser's stacks	*/
+
+#ifndef	FFINITDEPTH
+#define FFINITDEPTH 200
+#endif
+
+/*  FFMAXDEPTH is the maximum size the stacks can grow to
+    (effective only if the built-in stack extension method is used).  */
+
+#if FFMAXDEPTH == 0
+#undef FFMAXDEPTH
+#endif
+
+#ifndef FFMAXDEPTH
+#define FFMAXDEPTH 10000
+#endif
+
+/* Prevent warning if -Wstrict-prototypes.  */
+#ifdef __GNUC__
+int ffparse (void);
+#endif
+
+#if __GNUC__ > 1		/* GNU C and GNU C++ define this.  */
+#define __ff_memcpy(TO,FROM,COUNT)	__builtin_memcpy(TO,FROM,COUNT)
+#else				/* not GNU C or C++ */
+#ifndef __cplusplus
+
+/* This is the most reliable way to avoid incompatibilities
+   in available built-in functions on various systems.  */
+static void
+__ff_memcpy (to, from, count)
+     char *to;
+     char *from;
+     int count;
+{
+  register char *f = from;
+  register char *t = to;
+  register int i = count;
+
+  while (i-- > 0)
+    *t++ = *f++;
+}
+
+#else /* __cplusplus */
+
+/* This is the most reliable way to avoid incompatibilities
+   in available built-in functions on various systems.  */
+static void
+__ff_memcpy (char *to, char *from, int count)
+{
+  register char *f = from;
+  register char *t = to;
+  register int i = count;
+
+  while (i-- > 0)
+    *t++ = *f++;
+}
+
+#endif
+#endif
+
+#line 196 "/usr1/local/share/bison.simple"
+
+/* The user can define FFPARSE_PARAM as the name of an argument to be passed
+   into ffparse.  The argument should have type void *.
+   It should actually point to an object.
+   Grammar actions can access the variable by casting it
+   to the proper pointer type.  */
+
+#ifdef FFPARSE_PARAM
+#ifdef __cplusplus
+#define FFPARSE_PARAM_ARG void *FFPARSE_PARAM
+#define FFPARSE_PARAM_DECL
+#else /* not __cplusplus */
+#define FFPARSE_PARAM_ARG FFPARSE_PARAM
+#define FFPARSE_PARAM_DECL void *FFPARSE_PARAM;
+#endif /* not __cplusplus */
+#else /* not FFPARSE_PARAM */
+#define FFPARSE_PARAM_ARG
+#define FFPARSE_PARAM_DECL
+#endif /* not FFPARSE_PARAM */
+
+int
+ffparse(FFPARSE_PARAM_ARG)
+     FFPARSE_PARAM_DECL
+{
+  register int ffstate;
+  register int ffn;
+  register short *ffssp;
+  register FFSTYPE *ffvsp;
+  int fferrstatus;	/*  number of tokens to shift before error messages enabled */
+  int ffchar1 = 0;		/*  lookahead token as an internal (translated) token number */
+
+  short	ffssa[FFINITDEPTH];	/*  the state stack			*/
+  FFSTYPE ffvsa[FFINITDEPTH];	/*  the semantic value stack		*/
+
+  short *ffss = ffssa;		/*  refer to the stacks thru separate pointers */
+  FFSTYPE *ffvs = ffvsa;	/*  to allow ffoverflow to reallocate them elsewhere */
+
+#ifdef FFLSP_NEEDED
+  FFLTYPE fflsa[FFINITDEPTH];	/*  the location stack			*/
+  FFLTYPE *ffls = fflsa;
+  FFLTYPE *fflsp;
+
+#define FFPOPSTACK   (ffvsp--, ffssp--, fflsp--)
+#else
+#define FFPOPSTACK   (ffvsp--, ffssp--)
+#endif
+
+  int ffstacksize = FFINITDEPTH;
+
+#ifdef FFPURE
+  int ffchar;
+  FFSTYPE fflval;
+  int ffnerrs;
+#ifdef FFLSP_NEEDED
+  FFLTYPE fflloc;
+#endif
+#endif
+
+  FFSTYPE ffval;		/*  the variable used to return		*/
+				/*  semantic values from the action	*/
+				/*  routines				*/
+
+  int fflen;
+
+#if FFDEBUG != 0
+  if (ffdebug)
+    fprintf(stderr, "Starting parse\n");
+#endif
+
+  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 - 1;
+  ffvsp = ffvs;
+#ifdef FFLSP_NEEDED
+  fflsp = ffls;
+#endif
+
+/* Push a new state, which is found in  ffstate  .  */
+/* In all cases, when you get here, the value and location stacks
+   have just been pushed. so pushing a state here evens the stacks.  */
+ffnewstate:
+
+  *++ffssp = ffstate;
+
+  if (ffssp >= ffss + ffstacksize - 1)
+    {
+      /* 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;
+      short *ffss1 = ffss;
+#ifdef FFLSP_NEEDED
+      FFLTYPE *ffls1 = ffls;
+#endif
+
+      /* Get the current used size of the three stacks, in elements.  */
+      int size = ffssp - ffss + 1;
+
+#ifdef ffoverflow
+      /* Each stack pointer address is followed by the size of
+	 the data in use in that stack, in bytes.  */
+#ifdef FFLSP_NEEDED
+      /* This used to be a conditional around just the two extra args,
+	 but that might be undefined if ffoverflow is a macro.  */
+      ffoverflow("parser stack overflow",
+		 &ffss1, size * sizeof (*ffssp),
+		 &ffvs1, size * sizeof (*ffvsp),
+		 &ffls1, size * sizeof (*fflsp),
+		 &ffstacksize);
+#else
+      ffoverflow("parser stack overflow",
+		 &ffss1, size * sizeof (*ffssp),
+		 &ffvs1, size * sizeof (*ffvsp),
+		 &ffstacksize);
+#endif
+
+      ffss = ffss1; ffvs = ffvs1;
+#ifdef FFLSP_NEEDED
+      ffls = ffls1;
+#endif
+#else /* no ffoverflow */
+      /* Extend the stack our own way.  */
+      if (ffstacksize >= FFMAXDEPTH)
+	{
+	  fferror("parser stack overflow");
+	  return 2;
+	}
+      ffstacksize *= 2;
+      if (ffstacksize > FFMAXDEPTH)
+	ffstacksize = FFMAXDEPTH;
+      ffss = (short *) alloca (ffstacksize * sizeof (*ffssp));
+      __ff_memcpy ((char *)ffss, (char *)ffss1, size * sizeof (*ffssp));
+      ffvs = (FFSTYPE *) alloca (ffstacksize * sizeof (*ffvsp));
+      __ff_memcpy ((char *)ffvs, (char *)ffvs1, size * sizeof (*ffvsp));
+#ifdef FFLSP_NEEDED
+      ffls = (FFLTYPE *) alloca (ffstacksize * sizeof (*fflsp));
+      __ff_memcpy ((char *)ffls, (char *)ffls1, size * sizeof (*fflsp));
+#endif
+#endif /* no ffoverflow */
+
+      ffssp = ffss + size - 1;
+      ffvsp = ffvs + size - 1;
+#ifdef FFLSP_NEEDED
+      fflsp = ffls + size - 1;
+#endif
+
+#if FFDEBUG != 0
+      if (ffdebug)
+	fprintf(stderr, "Stack size increased to %d\n", ffstacksize);
+#endif
+
+      if (ffssp >= ffss + ffstacksize - 1)
+	FFABORT;
+    }
+
+#if FFDEBUG != 0
+  if (ffdebug)
+    fprintf(stderr, "Entering state %d\n", ffstate);
+#endif
+
+  goto ffbackup;
+ ffbackup:
+
+/* Do appropriate processing given the current state.  */
+/* Read a lookahead token if we need one and don't already have one.  */
+/* ffresume: */
+
+  /* First try to decide what to do without reference to lookahead token.  */
+
+  ffn = ffpact[ffstate];
+  if (ffn == FFFLAG)
+    goto ffdefault;
+
+  /* Not known => get a lookahead token if don't already have one.  */
+
+  /* ffchar is either FFEMPTY or FFEOF
+     or a valid token in external form.  */
+
+  if (ffchar == FFEMPTY)
+    {
+#if FFDEBUG != 0
+      if (ffdebug)
+	fprintf(stderr, "Reading a token: ");
+#endif
+      ffchar = FFLEX;
+    }
+
+  /* Convert token to internal form (in ffchar1) for indexing tables with */
+
+  if (ffchar <= 0)		/* This means end of input. */
+    {
+      ffchar1 = 0;
+      ffchar = FFEOF;		/* Don't call FFLEX any more */
+
+#if FFDEBUG != 0
+      if (ffdebug)
+	fprintf(stderr, "Now at end of input.\n");
+#endif
+    }
+  else
+    {
+      ffchar1 = FFTRANSLATE(ffchar);
+
+#if FFDEBUG != 0
+      if (ffdebug)
+	{
+	  fprintf (stderr, "Next token is %d (%s", ffchar, fftname[ffchar1]);
+	  /* Give the individual parser a way to print the precise meaning
+	     of a token, for further debugging info.  */
+#ifdef FFPRINT
+	  FFPRINT (stderr, ffchar, fflval);
+#endif
+	  fprintf (stderr, ")\n");
+	}
+#endif
+    }
+
+  ffn += ffchar1;
+  if (ffn < 0 || ffn > FFLAST || ffcheck[ffn] != ffchar1)
+    goto ffdefault;
+
+  ffn = fftable[ffn];
+
+  /* ffn is what to do for this token type in this state.
+     Negative => reduce, -ffn is rule number.
+     Positive => shift, ffn is new state.
+       New state is final state => don't bother to shift,
+       just return success.
+     0, or most negative number => error.  */
+
+  if (ffn < 0)
+    {
+      if (ffn == FFFLAG)
+	goto fferrlab;
+      ffn = -ffn;
+      goto ffreduce;
+    }
+  else if (ffn == 0)
+    goto fferrlab;
+
+  if (ffn == FFFINAL)
+    FFACCEPT;
+
+  /* Shift the lookahead token.  */
+
+#if FFDEBUG != 0
+  if (ffdebug)
+    fprintf(stderr, "Shifting token %d (%s), ", ffchar, fftname[ffchar1]);
+#endif
+
+  /* Discard the token being shifted unless it is eof.  */
+  if (ffchar != FFEOF)
+    ffchar = FFEMPTY;
+
+  *++ffvsp = fflval;
+#ifdef FFLSP_NEEDED
+  *++fflsp = fflloc;
+#endif
+
+  /* count tokens shifted since error; after three, turn off error status.  */
+  if (fferrstatus) fferrstatus--;
+
+  ffstate = ffn;
+  goto ffnewstate;
+
+/* Do the default action for the current state.  */
+ffdefault:
+
+  ffn = ffdefact[ffstate];
+  if (ffn == 0)
+    goto fferrlab;
+
+/* Do a reduction.  ffn is the number of a rule to reduce with.  */
+ffreduce:
+  fflen = ffr2[ffn];
+  if (fflen > 0)
+    ffval = ffvsp[1-fflen]; /* implement default value of the action */
+
+#if FFDEBUG != 0
+  if (ffdebug)
+    {
+      int i;
+
+      fprintf (stderr, "Reducing via rule %d (line %d), ",
+	       ffn, ffrline[ffn]);
+
+      /* Print the symbols being reduced, and their result.  */
+      for (i = ffprhs[ffn]; ffrhs[i] > 0; i++)
+	fprintf (stderr, "%s ", fftname[ffrhs[i]]);
+      fprintf (stderr, " -> %s\n", fftname[ffr1[ffn]]);
+    }
+#endif
+
+
+  switch (ffn) {
+
+case 3:
+#line 245 "eval.y"
+{;
+    break;}
+case 4:
+#line 247 "eval.y"
+{ if( ffvsp[-1].Node<0 ) {
+		     fferror("Couldn't build node structure: out of memory?");
+		     FFERROR;  }
+                  gParse.resultNode = ffvsp[-1].Node;
+		;
+    break;}
+case 5:
+#line 253 "eval.y"
+{ if( ffvsp[-1].Node<0 ) {
+		     fferror("Couldn't build node structure: out of memory?");
+		     FFERROR;  }
+                  gParse.resultNode = ffvsp[-1].Node;
+		;
+    break;}
+case 6:
+#line 259 "eval.y"
+{ if( ffvsp[-1].Node<0 ) {
+		     fferror("Couldn't build node structure: out of memory?");
+		     FFERROR;  } 
+                  gParse.resultNode = ffvsp[-1].Node;
+		;
+    break;}
+case 7:
+#line 265 "eval.y"
+{ if( ffvsp[-1].Node<0 ) {
+		     fferror("Couldn't build node structure: out of memory?");
+		     FFERROR;  }
+                  gParse.resultNode = ffvsp[-1].Node;
+		;
+    break;}
+case 8:
+#line 270 "eval.y"
+{  fferrok;  ;
+    break;}
+case 9:
+#line 274 "eval.y"
+{ ffval.Node = New_Vector( ffvsp[0].Node ); TEST(ffval.Node); ;
+    break;}
+case 10:
+#line 276 "eval.y"
+{
+                  if( gParse.Nodes[ffvsp[-2].Node].nSubNodes >= MAXSUBS ) {
+		     ffvsp[-2].Node = Close_Vec( ffvsp[-2].Node ); TEST(ffvsp[-2].Node);
+		     ffval.Node = New_Vector( ffvsp[-2].Node ); TEST(ffval.Node);
+                  } else {
+                     ffval.Node = ffvsp[-2].Node;
+                  }
+		  gParse.Nodes[ffval.Node].SubNodes[ gParse.Nodes[ffval.Node].nSubNodes++ ]
+		     = ffvsp[0].Node;
+                ;
+    break;}
+case 11:
+#line 289 "eval.y"
+{ ffval.Node = New_Vector( ffvsp[0].Node ); TEST(ffval.Node); ;
+    break;}
+case 12:
+#line 291 "eval.y"
+{
+                  if( TYPE(ffvsp[-2].Node) < TYPE(ffvsp[0].Node) )
+                     TYPE(ffvsp[-2].Node) = TYPE(ffvsp[0].Node);
+                  if( gParse.Nodes[ffvsp[-2].Node].nSubNodes >= MAXSUBS ) {
+		     ffvsp[-2].Node = Close_Vec( ffvsp[-2].Node ); TEST(ffvsp[-2].Node);
+		     ffval.Node = New_Vector( ffvsp[-2].Node ); TEST(ffval.Node);
+                  } else {
+                     ffval.Node = ffvsp[-2].Node;
+                  }
+		  gParse.Nodes[ffval.Node].SubNodes[ gParse.Nodes[ffval.Node].nSubNodes++ ]
+		     = ffvsp[0].Node;
+                ;
+    break;}
+case 13:
+#line 304 "eval.y"
+{
+                  if( gParse.Nodes[ffvsp[-2].Node].nSubNodes >= MAXSUBS ) {
+		     ffvsp[-2].Node = Close_Vec( ffvsp[-2].Node ); TEST(ffvsp[-2].Node);
+		     ffval.Node = New_Vector( ffvsp[-2].Node ); TEST(ffval.Node);
+                  } else {
+                     ffval.Node = ffvsp[-2].Node;
+                  }
+		  gParse.Nodes[ffval.Node].SubNodes[ gParse.Nodes[ffval.Node].nSubNodes++ ]
+		     = ffvsp[0].Node;
+                ;
+    break;}
+case 14:
+#line 315 "eval.y"
+{
+                  TYPE(ffvsp[-2].Node) = TYPE(ffvsp[0].Node);
+                  if( gParse.Nodes[ffvsp[-2].Node].nSubNodes >= MAXSUBS ) {
+		     ffvsp[-2].Node = Close_Vec( ffvsp[-2].Node ); TEST(ffvsp[-2].Node);
+		     ffval.Node = New_Vector( ffvsp[-2].Node ); TEST(ffval.Node);
+                  } else {
+                     ffval.Node = ffvsp[-2].Node;
+                  }
+		  gParse.Nodes[ffval.Node].SubNodes[ gParse.Nodes[ffval.Node].nSubNodes++ ]
+		     = ffvsp[0].Node;
+                ;
+    break;}
+case 15:
+#line 329 "eval.y"
+{ ffval.Node = Close_Vec( ffvsp[-1].Node ); TEST(ffval.Node); ;
+    break;}
+case 16:
+#line 333 "eval.y"
+{ ffval.Node = Close_Vec( ffvsp[-1].Node ); TEST(ffval.Node); ;
+    break;}
+case 17:
+#line 337 "eval.y"
+{
+                  ffval.Node = New_Const( BITSTR, ffvsp[0].str, strlen(ffvsp[0].str)+1 ); TEST(ffval.Node);
+		  SIZE(ffval.Node) = strlen(ffvsp[0].str); ;
+    break;}
+case 18:
+#line 341 "eval.y"
+{ ffval.Node = New_Column( ffvsp[0].lng ); TEST(ffval.Node); ;
+    break;}
+case 19:
+#line 343 "eval.y"
+{
+                  if( TYPE(ffvsp[-1].Node) != LONG
+		      || OPER(ffvsp[-1].Node) != CONST_OP ) {
+		     fferror("Offset argument must be a constant integer");
+		     FFERROR;
+		  }
+                  ffval.Node = New_Offset( ffvsp[-3].lng, ffvsp[-1].Node ); TEST(ffval.Node);
+                ;
+    break;}
+case 20:
+#line 352 "eval.y"
+{ ffval.Node = New_BinOp( BITSTR, ffvsp[-2].Node, '&', ffvsp[0].Node ); TEST(ffval.Node);
+                  SIZE(ffval.Node) = ( SIZE(ffvsp[-2].Node)>SIZE(ffvsp[0].Node) ? SIZE(ffvsp[-2].Node) : SIZE(ffvsp[0].Node) );  ;
+    break;}
+case 21:
+#line 355 "eval.y"
+{ ffval.Node = New_BinOp( BITSTR, ffvsp[-2].Node, '|', ffvsp[0].Node ); TEST(ffval.Node);
+                  SIZE(ffval.Node) = ( SIZE(ffvsp[-2].Node)>SIZE(ffvsp[0].Node) ? SIZE(ffvsp[-2].Node) : SIZE(ffvsp[0].Node) );  ;
+    break;}
+case 22:
+#line 358 "eval.y"
+{ 
+		  if (SIZE(ffvsp[-2].Node)+SIZE(ffvsp[0].Node) >= MAX_STRLEN) {
+		    fferror("Combined bit string size exceeds " MAX_STRLEN_S " bits");
+		    FFERROR;
+		  }
+		  ffval.Node = New_BinOp( BITSTR, ffvsp[-2].Node, '+', ffvsp[0].Node ); TEST(ffval.Node);
+                  SIZE(ffval.Node) = SIZE(ffvsp[-2].Node) + SIZE(ffvsp[0].Node); 
+		;
+    break;}
+case 23:
+#line 367 "eval.y"
+{ ffval.Node = New_Deref( ffvsp[-3].Node, 1, ffvsp[-1].Node,  0,  0,  0,   0 ); TEST(ffval.Node); ;
+    break;}
+case 24:
+#line 369 "eval.y"
+{ ffval.Node = New_Deref( ffvsp[-5].Node, 2, ffvsp[-3].Node, ffvsp[-1].Node,  0,  0,   0 ); TEST(ffval.Node); ;
+    break;}
+case 25:
+#line 371 "eval.y"
+{ ffval.Node = New_Deref( ffvsp[-7].Node, 3, ffvsp[-5].Node, ffvsp[-3].Node, ffvsp[-1].Node,  0,   0 ); TEST(ffval.Node); ;
+    break;}
+case 26:
+#line 373 "eval.y"
+{ ffval.Node = New_Deref( ffvsp[-9].Node, 4, ffvsp[-7].Node, ffvsp[-5].Node, ffvsp[-3].Node, ffvsp[-1].Node,   0 ); TEST(ffval.Node); ;
+    break;}
+case 27:
+#line 375 "eval.y"
+{ ffval.Node = New_Deref( ffvsp[-11].Node, 5, ffvsp[-9].Node, ffvsp[-7].Node, ffvsp[-5].Node, ffvsp[-3].Node, ffvsp[-1].Node ); TEST(ffval.Node); ;
+    break;}
+case 28:
+#line 377 "eval.y"
+{ ffval.Node = New_Unary( BITSTR, NOT, ffvsp[0].Node ); TEST(ffval.Node);     ;
+    break;}
+case 29:
+#line 380 "eval.y"
+{ ffval.Node = ffvsp[-1].Node; ;
+    break;}
+case 30:
+#line 384 "eval.y"
+{ ffval.Node = New_Const( LONG,   &(ffvsp[0].lng), sizeof(long)   ); TEST(ffval.Node); ;
+    break;}
+case 31:
+#line 386 "eval.y"
+{ ffval.Node = New_Const( DOUBLE, &(ffvsp[0].dbl), sizeof(double) ); TEST(ffval.Node); ;
+    break;}
+case 32:
+#line 388 "eval.y"
+{ ffval.Node = New_Column( ffvsp[0].lng ); TEST(ffval.Node); ;
+    break;}
+case 33:
+#line 390 "eval.y"
+{
+                  if( TYPE(ffvsp[-1].Node) != LONG
+		      || OPER(ffvsp[-1].Node) != CONST_OP ) {
+		     fferror("Offset argument must be a constant integer");
+		     FFERROR;
+		  }
+                  ffval.Node = New_Offset( ffvsp[-3].lng, ffvsp[-1].Node ); TEST(ffval.Node);
+                ;
+    break;}
+case 34:
+#line 399 "eval.y"
+{ ffval.Node = New_Func( LONG, row_fct,  0, 0, 0, 0, 0, 0, 0, 0 ); ;
+    break;}
+case 35:
+#line 401 "eval.y"
+{ ffval.Node = New_Func( LONG, null_fct, 0, 0, 0, 0, 0, 0, 0, 0 ); ;
+    break;}
+case 36:
+#line 403 "eval.y"
+{ PROMOTE(ffvsp[-2].Node,ffvsp[0].Node); ffval.Node = New_BinOp( TYPE(ffvsp[-2].Node), ffvsp[-2].Node, '%', ffvsp[0].Node );
+		  TEST(ffval.Node);                                                ;
+    break;}
+case 37:
+#line 406 "eval.y"
+{ PROMOTE(ffvsp[-2].Node,ffvsp[0].Node); ffval.Node = New_BinOp( TYPE(ffvsp[-2].Node), ffvsp[-2].Node, '+', ffvsp[0].Node );
+		  TEST(ffval.Node);                                                ;
+    break;}
+case 38:
+#line 409 "eval.y"
+{ PROMOTE(ffvsp[-2].Node,ffvsp[0].Node); ffval.Node = New_BinOp( TYPE(ffvsp[-2].Node), ffvsp[-2].Node, '-', ffvsp[0].Node ); 
+		  TEST(ffval.Node);                                                ;
+    break;}
+case 39:
+#line 412 "eval.y"
+{ PROMOTE(ffvsp[-2].Node,ffvsp[0].Node); ffval.Node = New_BinOp( TYPE(ffvsp[-2].Node), ffvsp[-2].Node, '*', ffvsp[0].Node ); 
+		  TEST(ffval.Node);                                                ;
+    break;}
+case 40:
+#line 415 "eval.y"
+{ PROMOTE(ffvsp[-2].Node,ffvsp[0].Node); ffval.Node = New_BinOp( TYPE(ffvsp[-2].Node), ffvsp[-2].Node, '/', ffvsp[0].Node ); 
+		  TEST(ffval.Node);                                                ;
+    break;}
+case 41:
+#line 418 "eval.y"
+{ PROMOTE(ffvsp[-2].Node,ffvsp[0].Node); ffval.Node = New_BinOp( TYPE(ffvsp[-2].Node), ffvsp[-2].Node, POWER, ffvsp[0].Node );
+		  TEST(ffval.Node);                                                ;
+    break;}
+case 42:
+#line 421 "eval.y"
+{ ffval.Node = ffvsp[0].Node; ;
+    break;}
+case 43:
+#line 423 "eval.y"
+{ ffval.Node = New_Unary( TYPE(ffvsp[0].Node), UMINUS, ffvsp[0].Node ); TEST(ffval.Node); ;
+    break;}
+case 44:
+#line 425 "eval.y"
+{ ffval.Node = ffvsp[-1].Node; ;
+    break;}
+case 45:
+#line 427 "eval.y"
+{ ffvsp[0].Node = New_Unary( TYPE(ffvsp[-2].Node), 0, ffvsp[0].Node );
+                  ffval.Node = New_BinOp( TYPE(ffvsp[-2].Node), ffvsp[-2].Node, '*', ffvsp[0].Node ); 
+		  TEST(ffval.Node);                                ;
+    break;}
+case 46:
+#line 431 "eval.y"
+{ ffvsp[-2].Node = New_Unary( TYPE(ffvsp[0].Node), 0, ffvsp[-2].Node );
+                  ffval.Node = New_BinOp( TYPE(ffvsp[0].Node), ffvsp[-2].Node, '*', ffvsp[0].Node );
+                  TEST(ffval.Node);                                ;
+    break;}
+case 47:
+#line 435 "eval.y"
+{
+                  PROMOTE(ffvsp[-2].Node,ffvsp[0].Node);
+                  if( ! Test_Dims(ffvsp[-2].Node,ffvsp[0].Node) ) {
+                     fferror("Incompatible dimensions in '?:' arguments");
+		     FFERROR;
+                  }
+                  ffval.Node = New_Func( 0, ifthenelse_fct, 3, ffvsp[-2].Node, ffvsp[0].Node, ffvsp[-4].Node,
+                                 0, 0, 0, 0 );
+                  TEST(ffval.Node);
+                  if( SIZE(ffvsp[-2].Node)<SIZE(ffvsp[0].Node) )  Copy_Dims(ffval.Node, ffvsp[0].Node);
+                  TYPE(ffvsp[-4].Node) = TYPE(ffvsp[-2].Node);
+                  if( ! Test_Dims(ffvsp[-4].Node,ffval.Node) ) {
+                     fferror("Incompatible dimensions in '?:' condition");
+		     FFERROR;
+                  }
+                  TYPE(ffvsp[-4].Node) = BOOLEAN;
+                  if( SIZE(ffval.Node)<SIZE(ffvsp[-4].Node) )  Copy_Dims(ffval.Node, ffvsp[-4].Node);
+                ;
+    break;}
+case 48:
+#line 454 "eval.y"
+{
+                  PROMOTE(ffvsp[-2].Node,ffvsp[0].Node);
+                  if( ! Test_Dims(ffvsp[-2].Node,ffvsp[0].Node) ) {
+                     fferror("Incompatible dimensions in '?:' arguments");
+		     FFERROR;
+                  }
+                  ffval.Node = New_Func( 0, ifthenelse_fct, 3, ffvsp[-2].Node, ffvsp[0].Node, ffvsp[-4].Node,
+                                 0, 0, 0, 0 );
+                  TEST(ffval.Node);
+                  if( SIZE(ffvsp[-2].Node)<SIZE(ffvsp[0].Node) )  Copy_Dims(ffval.Node, ffvsp[0].Node);
+                  TYPE(ffvsp[-4].Node) = TYPE(ffvsp[-2].Node);
+                  if( ! Test_Dims(ffvsp[-4].Node,ffval.Node) ) {
+                     fferror("Incompatible dimensions in '?:' condition");
+		     FFERROR;
+                  }
+                  TYPE(ffvsp[-4].Node) = BOOLEAN;
+                  if( SIZE(ffval.Node)<SIZE(ffvsp[-4].Node) )  Copy_Dims(ffval.Node, ffvsp[-4].Node);
+                ;
+    break;}
+case 49:
+#line 473 "eval.y"
+{
+                  PROMOTE(ffvsp[-2].Node,ffvsp[0].Node);
+                  if( ! Test_Dims(ffvsp[-2].Node,ffvsp[0].Node) ) {
+                     fferror("Incompatible dimensions in '?:' arguments");
+		     FFERROR;
+                  }
+                  ffval.Node = New_Func( 0, ifthenelse_fct, 3, ffvsp[-2].Node, ffvsp[0].Node, ffvsp[-4].Node,
+                                 0, 0, 0, 0 );
+                  TEST(ffval.Node);
+                  if( SIZE(ffvsp[-2].Node)<SIZE(ffvsp[0].Node) )  Copy_Dims(ffval.Node, ffvsp[0].Node);
+                  TYPE(ffvsp[-4].Node) = TYPE(ffvsp[-2].Node);
+                  if( ! Test_Dims(ffvsp[-4].Node,ffval.Node) ) {
+                     fferror("Incompatible dimensions in '?:' condition");
+		     FFERROR;
+                  }
+                  TYPE(ffvsp[-4].Node) = BOOLEAN;
+                  if( SIZE(ffval.Node)<SIZE(ffvsp[-4].Node) )  Copy_Dims(ffval.Node, ffvsp[-4].Node);
+                ;
+    break;}
+case 50:
+#line 492 "eval.y"
+{ if (FSTRCMP(ffvsp[-1].str,"RANDOM(") == 0) {  /* Scalar RANDOM() */
+                     srand( (unsigned int) time(NULL) );
+                     ffval.Node = New_Func( DOUBLE, rnd_fct, 0, 0, 0, 0, 0, 0, 0, 0 );
+		  } else if (FSTRCMP(ffvsp[-1].str,"RANDOMN(") == 0) {/*Scalar RANDOMN()*/
+		     srand( (unsigned int) time(NULL) );
+		     ffval.Node = New_Func( DOUBLE, gasrnd_fct, 0, 0, 0, 0, 0, 0, 0, 0 );
+                  } else {
+                     fferror("Function() not supported");
+		     FFERROR;
+		  }
+                  TEST(ffval.Node); 
+                ;
+    break;}
+case 51:
+#line 505 "eval.y"
+{ if (FSTRCMP(ffvsp[-2].str,"SUM(") == 0) {
+		     ffval.Node = New_Func( LONG, sum_fct, 1, ffvsp[-1].Node, 0, 0, 0, 0, 0, 0 );
+                  } else if (FSTRCMP(ffvsp[-2].str,"NELEM(") == 0) {
+                     ffval.Node = New_Const( LONG, &( SIZE(ffvsp[-1].Node) ), sizeof(long) );
+                  } else if (FSTRCMP(ffvsp[-2].str,"ACCUM(") == 0) {
+		    long zero = 0;
+		    ffval.Node = New_BinOp( LONG , ffvsp[-1].Node, ACCUM, New_Const( LONG, &zero, sizeof(zero) ));
+		  } else {
+                     fferror("Function(bool) not supported");
+		     FFERROR;
+		  }
+                  TEST(ffval.Node); 
+		;
+    break;}
+case 52:
+#line 519 "eval.y"
+{ if (FSTRCMP(ffvsp[-2].str,"NELEM(") == 0) {
+                     ffval.Node = New_Const( LONG, &( SIZE(ffvsp[-1].Node) ), sizeof(long) );
+		  } else if (FSTRCMP(ffvsp[-2].str,"NVALID(") == 0) {
+		     ffval.Node = New_Func( LONG, nonnull_fct, 1, ffvsp[-1].Node,
+				    0, 0, 0, 0, 0, 0 );
+		  } else {
+                     fferror("Function(str) not supported");
+		     FFERROR;
+		  }
+                  TEST(ffval.Node); 
+		;
+    break;}
+case 53:
+#line 531 "eval.y"
+{ if (FSTRCMP(ffvsp[-2].str,"NELEM(") == 0) {
+                     ffval.Node = New_Const( LONG, &( SIZE(ffvsp[-1].Node) ), sizeof(long) );
+		} else if (FSTRCMP(ffvsp[-2].str,"NVALID(") == 0) { /* Bit arrays do not have NULL */
+                     ffval.Node = New_Const( LONG, &( SIZE(ffvsp[-1].Node) ), sizeof(long) );
+		} else if (FSTRCMP(ffvsp[-2].str,"SUM(") == 0) {
+		     ffval.Node = New_Func( LONG, sum_fct, 1, ffvsp[-1].Node,
+				    0, 0, 0, 0, 0, 0 );
+		} else if (FSTRCMP(ffvsp[-2].str,"MIN(") == 0) {
+		     ffval.Node = New_Func( TYPE(ffvsp[-1].Node),  /* Force 1D result */
+				    min1_fct, 1, ffvsp[-1].Node, 0, 0, 0, 0, 0, 0 );
+		     /* Note: $2 is a vector so the result can never
+		        be a constant.  Therefore it will never be set
+		        inside New_Func(), and it is safe to set SIZE() */
+		     SIZE(ffval.Node) = 1;
+		} else if (FSTRCMP(ffvsp[-2].str,"ACCUM(") == 0) {
+		    long zero = 0;
+		    ffval.Node = New_BinOp( LONG , ffvsp[-1].Node, ACCUM, New_Const( LONG, &zero, sizeof(zero) ));
+		} else if (FSTRCMP(ffvsp[-2].str,"MAX(") == 0) {
+		     ffval.Node = New_Func( TYPE(ffvsp[-1].Node),  /* Force 1D result */
+				    max1_fct, 1, ffvsp[-1].Node, 0, 0, 0, 0, 0, 0 );
+		     /* Note: $2 is a vector so the result can never
+		        be a constant.  Therefore it will never be set
+		        inside New_Func(), and it is safe to set SIZE() */
+		     SIZE(ffval.Node) = 1;
+		} else {
+                     fferror("Function(bits) not supported");
+		     FFERROR;
+		  }
+                  TEST(ffval.Node); 
+		;
+    break;}
+case 54:
+#line 562 "eval.y"
+{ if (FSTRCMP(ffvsp[-2].str,"SUM(") == 0)
+		     ffval.Node = New_Func( TYPE(ffvsp[-1].Node), sum_fct, 1, ffvsp[-1].Node,
+				    0, 0, 0, 0, 0, 0 );
+		  else if (FSTRCMP(ffvsp[-2].str,"AVERAGE(") == 0)
+		     ffval.Node = New_Func( DOUBLE, average_fct, 1, ffvsp[-1].Node,
+				    0, 0, 0, 0, 0, 0 );
+		  else if (FSTRCMP(ffvsp[-2].str,"STDDEV(") == 0)
+		     ffval.Node = New_Func( DOUBLE, stddev_fct, 1, ffvsp[-1].Node,
+				    0, 0, 0, 0, 0, 0 );
+		  else if (FSTRCMP(ffvsp[-2].str,"MEDIAN(") == 0)
+		     ffval.Node = New_Func( TYPE(ffvsp[-1].Node), median_fct, 1, ffvsp[-1].Node,
+				    0, 0, 0, 0, 0, 0 );
+		  else if (FSTRCMP(ffvsp[-2].str,"NELEM(") == 0)
+                     ffval.Node = New_Const( LONG, &( SIZE(ffvsp[-1].Node) ), sizeof(long) );
+		  else if (FSTRCMP(ffvsp[-2].str,"NVALID(") == 0)
+		     ffval.Node = New_Func( LONG, nonnull_fct, 1, ffvsp[-1].Node,
+				    0, 0, 0, 0, 0, 0 );
+		  else if   ((FSTRCMP(ffvsp[-2].str,"ACCUM(") == 0) && (TYPE(ffvsp[-1].Node) == LONG)) {
+		    long zero = 0;
+		    ffval.Node = New_BinOp( LONG ,   ffvsp[-1].Node, ACCUM, New_Const( LONG,   &zero, sizeof(zero) ));
+		  } else if ((FSTRCMP(ffvsp[-2].str,"ACCUM(") == 0) && (TYPE(ffvsp[-1].Node) == DOUBLE)) {
+		    double zero = 0;
+		    ffval.Node = New_BinOp( DOUBLE , ffvsp[-1].Node, ACCUM, New_Const( DOUBLE, &zero, sizeof(zero) ));
+		  } else if ((FSTRCMP(ffvsp[-2].str,"SEQDIFF(") == 0) && (TYPE(ffvsp[-1].Node) == LONG)) {
+		    long zero = 0;
+		    ffval.Node = New_BinOp( LONG ,   ffvsp[-1].Node, DIFF, New_Const( LONG,   &zero, sizeof(zero) ));
+		  } else if ((FSTRCMP(ffvsp[-2].str,"SEQDIFF(") == 0) && (TYPE(ffvsp[-1].Node) == DOUBLE)) {
+		    double zero = 0;
+		    ffval.Node = New_BinOp( DOUBLE , ffvsp[-1].Node, DIFF, New_Const( DOUBLE, &zero, sizeof(zero) ));
+		  } else if (FSTRCMP(ffvsp[-2].str,"ABS(") == 0)
+		     ffval.Node = New_Func( 0, abs_fct, 1, ffvsp[-1].Node, 0, 0, 0, 0, 0, 0 );
+ 		  else if (FSTRCMP(ffvsp[-2].str,"MIN(") == 0)
+		     ffval.Node = New_Func( TYPE(ffvsp[-1].Node),  /* Force 1D result */
+				    min1_fct, 1, ffvsp[-1].Node, 0, 0, 0, 0, 0, 0 );
+		  else if (FSTRCMP(ffvsp[-2].str,"MAX(") == 0)
+		     ffval.Node = New_Func( TYPE(ffvsp[-1].Node),  /* Force 1D result */
+				    max1_fct, 1, ffvsp[-1].Node, 0, 0, 0, 0, 0, 0 );
+		  else if (FSTRCMP(ffvsp[-2].str,"RANDOM(") == 0) { /* Vector RANDOM() */
+                     srand( (unsigned int) time(NULL) );
+                     ffval.Node = New_Func( 0, rnd_fct, 1, ffvsp[-1].Node, 0, 0, 0, 0, 0, 0 );
+		     TEST(ffval.Node);
+		     TYPE(ffval.Node) = DOUBLE;
+		  } else if (FSTRCMP(ffvsp[-2].str,"RANDOMN(") == 0) {
+		     srand( (unsigned int) time(NULL) ); /* Vector RANDOMN() */
+		     ffval.Node = New_Func( 0, gasrnd_fct, 1, ffvsp[-1].Node, 0, 0, 0, 0, 0, 0 );
+		     TEST(ffval.Node);
+		     TYPE(ffval.Node) = DOUBLE;
+                  } 
+  		  else {  /*  These all take DOUBLE arguments  */
+		     if( TYPE(ffvsp[-1].Node) != DOUBLE ) ffvsp[-1].Node = New_Unary( DOUBLE, 0, ffvsp[-1].Node );
+                     if (FSTRCMP(ffvsp[-2].str,"SIN(") == 0)
+			ffval.Node = New_Func( 0, sin_fct,  1, ffvsp[-1].Node, 0, 0, 0, 0, 0, 0 );
+		     else if (FSTRCMP(ffvsp[-2].str,"COS(") == 0)
+			ffval.Node = New_Func( 0, cos_fct,  1, ffvsp[-1].Node, 0, 0, 0, 0, 0, 0 );
+		     else if (FSTRCMP(ffvsp[-2].str,"TAN(") == 0)
+			ffval.Node = New_Func( 0, tan_fct,  1, ffvsp[-1].Node, 0, 0, 0, 0, 0, 0 );
+		     else if (FSTRCMP(ffvsp[-2].str,"ARCSIN(") == 0
+			      || FSTRCMP(ffvsp[-2].str,"ASIN(") == 0)
+			ffval.Node = New_Func( 0, asin_fct, 1, ffvsp[-1].Node, 0, 0, 0, 0, 0, 0 );
+		     else if (FSTRCMP(ffvsp[-2].str,"ARCCOS(") == 0
+			      || FSTRCMP(ffvsp[-2].str,"ACOS(") == 0)
+			ffval.Node = New_Func( 0, acos_fct, 1, ffvsp[-1].Node, 0, 0, 0, 0, 0, 0 );
+		     else if (FSTRCMP(ffvsp[-2].str,"ARCTAN(") == 0
+			      || FSTRCMP(ffvsp[-2].str,"ATAN(") == 0)
+			ffval.Node = New_Func( 0, atan_fct, 1, ffvsp[-1].Node, 0, 0, 0, 0, 0, 0 );
+		     else if (FSTRCMP(ffvsp[-2].str,"SINH(") == 0)
+			ffval.Node = New_Func( 0, sinh_fct,  1, ffvsp[-1].Node, 0, 0, 0, 0, 0, 0 );
+		     else if (FSTRCMP(ffvsp[-2].str,"COSH(") == 0)
+			ffval.Node = New_Func( 0, cosh_fct,  1, ffvsp[-1].Node, 0, 0, 0, 0, 0, 0 );
+		     else if (FSTRCMP(ffvsp[-2].str,"TANH(") == 0)
+			ffval.Node = New_Func( 0, tanh_fct,  1, ffvsp[-1].Node, 0, 0, 0, 0, 0, 0 );
+		     else if (FSTRCMP(ffvsp[-2].str,"EXP(") == 0)
+			ffval.Node = New_Func( 0, exp_fct,  1, ffvsp[-1].Node, 0, 0, 0, 0, 0, 0 );
+		     else if (FSTRCMP(ffvsp[-2].str,"LOG(") == 0)
+			ffval.Node = New_Func( 0, log_fct,  1, ffvsp[-1].Node, 0, 0, 0, 0, 0, 0 );
+		     else if (FSTRCMP(ffvsp[-2].str,"LOG10(") == 0)
+			ffval.Node = New_Func( 0, log10_fct, 1, ffvsp[-1].Node, 0, 0, 0, 0, 0, 0 );
+		     else if (FSTRCMP(ffvsp[-2].str,"SQRT(") == 0)
+			ffval.Node = New_Func( 0, sqrt_fct, 1, ffvsp[-1].Node, 0, 0, 0, 0, 0, 0 );
+		     else if (FSTRCMP(ffvsp[-2].str,"ROUND(") == 0)
+			ffval.Node = New_Func( 0, round_fct, 1, ffvsp[-1].Node, 0, 0, 0, 0, 0, 0 );
+		     else if (FSTRCMP(ffvsp[-2].str,"FLOOR(") == 0)
+			ffval.Node = New_Func( 0, floor_fct, 1, ffvsp[-1].Node, 0, 0, 0, 0, 0, 0 );
+		     else if (FSTRCMP(ffvsp[-2].str,"CEIL(") == 0)
+			ffval.Node = New_Func( 0, ceil_fct, 1, ffvsp[-1].Node, 0, 0, 0, 0, 0, 0 );
+		     else if (FSTRCMP(ffvsp[-2].str,"RANDOMP(") == 0) {
+		       srand( (unsigned int) time(NULL) );
+		       ffval.Node = New_Func( 0, poirnd_fct, 1, ffvsp[-1].Node, 
+				      0, 0, 0, 0, 0, 0 );
+		       TYPE(ffval.Node) = LONG;
+		     } else {
+			fferror("Function(expr) not supported");
+			FFERROR;
+		     }
+		  }
+                  TEST(ffval.Node); 
+                ;
+    break;}
+case 55:
+#line 660 "eval.y"
+{ 
+		  if (FSTRCMP(ffvsp[-4].str,"STRSTR(") == 0) {
+		    ffval.Node = New_Func( LONG, strpos_fct, 2, ffvsp[-3].Node, ffvsp[-1].Node, 0, 
+				   0, 0, 0, 0 );
+		    TEST(ffval.Node);
+		  }
+                ;
+    break;}
+case 56:
+#line 668 "eval.y"
+{ 
+		   if (FSTRCMP(ffvsp[-4].str,"DEFNULL(") == 0) {
+		      if( SIZE(ffvsp[-3].Node)>=SIZE(ffvsp[-1].Node) && Test_Dims( ffvsp[-3].Node, ffvsp[-1].Node ) ) {
+			 PROMOTE(ffvsp[-3].Node,ffvsp[-1].Node);
+			 ffval.Node = New_Func( 0, defnull_fct, 2, ffvsp[-3].Node, ffvsp[-1].Node, 0,
+					0, 0, 0, 0 );
+			 TEST(ffval.Node); 
+		      } else {
+			 fferror("Dimensions of DEFNULL arguments "
+				 "are not compatible");
+			 FFERROR;
+		      }
+		   } else if (FSTRCMP(ffvsp[-4].str,"ARCTAN2(") == 0) {
+		     if( TYPE(ffvsp[-3].Node) != DOUBLE ) ffvsp[-3].Node = New_Unary( DOUBLE, 0, ffvsp[-3].Node );
+		     if( TYPE(ffvsp[-1].Node) != DOUBLE ) ffvsp[-1].Node = New_Unary( DOUBLE, 0, ffvsp[-1].Node );
+		     if( Test_Dims( ffvsp[-3].Node, ffvsp[-1].Node ) ) {
+			ffval.Node = New_Func( 0, atan2_fct, 2, ffvsp[-3].Node, ffvsp[-1].Node, 0, 0, 0, 0, 0 );
+			TEST(ffval.Node); 
+			if( SIZE(ffvsp[-3].Node)<SIZE(ffvsp[-1].Node) ) Copy_Dims(ffval.Node, ffvsp[-1].Node);
+		     } else {
+			fferror("Dimensions of arctan2 arguments "
+				"are not compatible");
+			FFERROR;
+		     }
+		   } else if (FSTRCMP(ffvsp[-4].str,"MIN(") == 0) {
+		      PROMOTE( ffvsp[-3].Node, ffvsp[-1].Node );
+		      if( Test_Dims( ffvsp[-3].Node, ffvsp[-1].Node ) ) {
+			ffval.Node = New_Func( 0, min2_fct, 2, ffvsp[-3].Node, ffvsp[-1].Node, 0, 0, 0, 0, 0 );
+			TEST(ffval.Node);
+			if( SIZE(ffvsp[-3].Node)<SIZE(ffvsp[-1].Node) ) Copy_Dims(ffval.Node, ffvsp[-1].Node);
+		      } else {
+			fferror("Dimensions of min(a,b) arguments "
+				"are not compatible");
+			FFERROR;
+		      }
+		   } else if (FSTRCMP(ffvsp[-4].str,"MAX(") == 0) {
+		      PROMOTE( ffvsp[-3].Node, ffvsp[-1].Node );
+		      if( Test_Dims( ffvsp[-3].Node, ffvsp[-1].Node ) ) {
+			ffval.Node = New_Func( 0, max2_fct, 2, ffvsp[-3].Node, ffvsp[-1].Node, 0, 0, 0, 0, 0 );
+			TEST(ffval.Node);
+			if( SIZE(ffvsp[-3].Node)<SIZE(ffvsp[-1].Node) ) Copy_Dims(ffval.Node, ffvsp[-1].Node);
+		      } else {
+			fferror("Dimensions of max(a,b) arguments "
+				"are not compatible");
+			FFERROR;
+		      }
+#if 0
+		   } else if (FSTRCMP(ffvsp[-4].str,"STRSTR(") == 0) {
+		     if( TYPE(ffvsp[-3].Node) != STRING || TYPE(ffvsp[-1].Node) != STRING) {
+		       fferror("Arguments to strstr(s,r) must be strings");
+		       FFERROR;
+		     }
+		     ffval.Node = New_Func( LONG, strpos_fct, 2, ffvsp[-3].Node, ffvsp[-1].Node, 0, 
+				    0, 0, 0, 0 );
+		     TEST(ffval.Node);
+#endif
+		   } else {
+		      fferror("Function(expr,expr) not supported");
+		      FFERROR;
+		   }
+                ;
+    break;}
+case 57:
+#line 730 "eval.y"
+{ 
+		  if (FSTRCMP(ffvsp[-8].str,"ANGSEP(") == 0) {
+		    if( TYPE(ffvsp[-7].Node) != DOUBLE ) ffvsp[-7].Node = New_Unary( DOUBLE, 0, ffvsp[-7].Node );
+		    if( TYPE(ffvsp[-5].Node) != DOUBLE ) ffvsp[-5].Node = New_Unary( DOUBLE, 0, ffvsp[-5].Node );
+		    if( TYPE(ffvsp[-3].Node) != DOUBLE ) ffvsp[-3].Node = New_Unary( DOUBLE, 0, ffvsp[-3].Node );
+		    if( TYPE(ffvsp[-1].Node) != DOUBLE ) ffvsp[-1].Node = New_Unary( DOUBLE, 0, ffvsp[-1].Node );
+		    if( Test_Dims( ffvsp[-7].Node, ffvsp[-5].Node ) && Test_Dims( ffvsp[-5].Node, ffvsp[-3].Node ) && 
+			Test_Dims( ffvsp[-3].Node, ffvsp[-1].Node ) ) {
+		      ffval.Node = New_Func( 0, angsep_fct, 4, ffvsp[-7].Node, ffvsp[-5].Node, ffvsp[-3].Node, ffvsp[-1].Node,0,0,0 );
+		      TEST(ffval.Node); 
+		      if( SIZE(ffvsp[-7].Node)<SIZE(ffvsp[-5].Node) ) Copy_Dims(ffval.Node, ffvsp[-5].Node);
+		      if( SIZE(ffvsp[-5].Node)<SIZE(ffvsp[-3].Node) ) Copy_Dims(ffval.Node, ffvsp[-3].Node);
+		      if( SIZE(ffvsp[-3].Node)<SIZE(ffvsp[-1].Node) ) Copy_Dims(ffval.Node, ffvsp[-1].Node);
+		    } else {
+		      fferror("Dimensions of ANGSEP arguments "
+			      "are not compatible");
+		      FFERROR;
+		    }
+		   } else {
+		      fferror("Function(expr,expr,expr,expr) not supported");
+		      FFERROR;
+		   }
+                ;
+    break;}
+case 58:
+#line 754 "eval.y"
+{ ffval.Node = New_Deref( ffvsp[-3].Node, 1, ffvsp[-1].Node,  0,  0,  0,   0 ); TEST(ffval.Node); ;
+    break;}
+case 59:
+#line 756 "eval.y"
+{ ffval.Node = New_Deref( ffvsp[-5].Node, 2, ffvsp[-3].Node, ffvsp[-1].Node,  0,  0,   0 ); TEST(ffval.Node); ;
+    break;}
+case 60:
+#line 758 "eval.y"
+{ ffval.Node = New_Deref( ffvsp[-7].Node, 3, ffvsp[-5].Node, ffvsp[-3].Node, ffvsp[-1].Node,  0,   0 ); TEST(ffval.Node); ;
+    break;}
+case 61:
+#line 760 "eval.y"
+{ ffval.Node = New_Deref( ffvsp[-9].Node, 4, ffvsp[-7].Node, ffvsp[-5].Node, ffvsp[-3].Node, ffvsp[-1].Node,   0 ); TEST(ffval.Node); ;
+    break;}
+case 62:
+#line 762 "eval.y"
+{ ffval.Node = New_Deref( ffvsp[-11].Node, 5, ffvsp[-9].Node, ffvsp[-7].Node, ffvsp[-5].Node, ffvsp[-3].Node, ffvsp[-1].Node ); TEST(ffval.Node); ;
+    break;}
+case 63:
+#line 764 "eval.y"
+{ ffval.Node = New_Unary( LONG,   INTCAST, ffvsp[0].Node );  TEST(ffval.Node);  ;
+    break;}
+case 64:
+#line 766 "eval.y"
+{ ffval.Node = New_Unary( LONG,   INTCAST, ffvsp[0].Node );  TEST(ffval.Node);  ;
+    break;}
+case 65:
+#line 768 "eval.y"
+{ ffval.Node = New_Unary( DOUBLE, FLTCAST, ffvsp[0].Node );  TEST(ffval.Node);  ;
+    break;}
+case 66:
+#line 770 "eval.y"
+{ ffval.Node = New_Unary( DOUBLE, FLTCAST, ffvsp[0].Node );  TEST(ffval.Node);  ;
+    break;}
+case 67:
+#line 774 "eval.y"
+{ ffval.Node = New_Const( BOOLEAN, &(ffvsp[0].log), sizeof(char) ); TEST(ffval.Node); ;
+    break;}
+case 68:
+#line 776 "eval.y"
+{ ffval.Node = New_Column( ffvsp[0].lng ); TEST(ffval.Node); ;
+    break;}
+case 69:
+#line 778 "eval.y"
+{
+                  if( TYPE(ffvsp[-1].Node) != LONG
+		      || OPER(ffvsp[-1].Node) != CONST_OP ) {
+		     fferror("Offset argument must be a constant integer");
+		     FFERROR;
+		  }
+                  ffval.Node = New_Offset( ffvsp[-3].lng, ffvsp[-1].Node ); TEST(ffval.Node);
+                ;
+    break;}
+case 70:
+#line 787 "eval.y"
+{ ffval.Node = New_BinOp( BOOLEAN, ffvsp[-2].Node, EQ,  ffvsp[0].Node ); TEST(ffval.Node);
+		  SIZE(ffval.Node) = 1;                                     ;
+    break;}
+case 71:
+#line 790 "eval.y"
+{ ffval.Node = New_BinOp( BOOLEAN, ffvsp[-2].Node, NE,  ffvsp[0].Node ); TEST(ffval.Node); 
+		  SIZE(ffval.Node) = 1;                                     ;
+    break;}
+case 72:
+#line 793 "eval.y"
+{ ffval.Node = New_BinOp( BOOLEAN, ffvsp[-2].Node, LT,  ffvsp[0].Node ); TEST(ffval.Node); 
+		  SIZE(ffval.Node) = 1;                                     ;
+    break;}
+case 73:
+#line 796 "eval.y"
+{ ffval.Node = New_BinOp( BOOLEAN, ffvsp[-2].Node, LTE, ffvsp[0].Node ); TEST(ffval.Node); 
+		  SIZE(ffval.Node) = 1;                                     ;
+    break;}
+case 74:
+#line 799 "eval.y"
+{ ffval.Node = New_BinOp( BOOLEAN, ffvsp[-2].Node, GT,  ffvsp[0].Node ); TEST(ffval.Node); 
+		  SIZE(ffval.Node) = 1;                                     ;
+    break;}
+case 75:
+#line 802 "eval.y"
+{ ffval.Node = New_BinOp( BOOLEAN, ffvsp[-2].Node, GTE, ffvsp[0].Node ); TEST(ffval.Node); 
+		  SIZE(ffval.Node) = 1;                                     ;
+    break;}
+case 76:
+#line 805 "eval.y"
+{ PROMOTE(ffvsp[-2].Node,ffvsp[0].Node); ffval.Node = New_BinOp( BOOLEAN, ffvsp[-2].Node, GT,  ffvsp[0].Node );
+                  TEST(ffval.Node);                                               ;
+    break;}
+case 77:
+#line 808 "eval.y"
+{ PROMOTE(ffvsp[-2].Node,ffvsp[0].Node); ffval.Node = New_BinOp( BOOLEAN, ffvsp[-2].Node, LT,  ffvsp[0].Node );
+                  TEST(ffval.Node);                                               ;
+    break;}
+case 78:
+#line 811 "eval.y"
+{ PROMOTE(ffvsp[-2].Node,ffvsp[0].Node); ffval.Node = New_BinOp( BOOLEAN, ffvsp[-2].Node, GTE, ffvsp[0].Node );
+                  TEST(ffval.Node);                                               ;
+    break;}
+case 79:
+#line 814 "eval.y"
+{ PROMOTE(ffvsp[-2].Node,ffvsp[0].Node); ffval.Node = New_BinOp( BOOLEAN, ffvsp[-2].Node, LTE, ffvsp[0].Node );
+                  TEST(ffval.Node);                                               ;
+    break;}
+case 80:
+#line 817 "eval.y"
+{ PROMOTE(ffvsp[-2].Node,ffvsp[0].Node); ffval.Node = New_BinOp( BOOLEAN, ffvsp[-2].Node, '~', ffvsp[0].Node );
+                  TEST(ffval.Node);                                               ;
+    break;}
+case 81:
+#line 820 "eval.y"
+{ PROMOTE(ffvsp[-2].Node,ffvsp[0].Node); ffval.Node = New_BinOp( BOOLEAN, ffvsp[-2].Node, EQ,  ffvsp[0].Node );
+                  TEST(ffval.Node);                                               ;
+    break;}
+case 82:
+#line 823 "eval.y"
+{ PROMOTE(ffvsp[-2].Node,ffvsp[0].Node); ffval.Node = New_BinOp( BOOLEAN, ffvsp[-2].Node, NE,  ffvsp[0].Node );
+                  TEST(ffval.Node);                                               ;
+    break;}
+case 83:
+#line 826 "eval.y"
+{ ffval.Node = New_BinOp( BOOLEAN, ffvsp[-2].Node, EQ,  ffvsp[0].Node ); TEST(ffval.Node);
+                  SIZE(ffval.Node) = 1; ;
+    break;}
+case 84:
+#line 829 "eval.y"
+{ ffval.Node = New_BinOp( BOOLEAN, ffvsp[-2].Node, NE,  ffvsp[0].Node ); TEST(ffval.Node);
+                  SIZE(ffval.Node) = 1; ;
+    break;}
+case 85:
+#line 832 "eval.y"
+{ ffval.Node = New_BinOp( BOOLEAN, ffvsp[-2].Node, GT,  ffvsp[0].Node ); TEST(ffval.Node);
+                  SIZE(ffval.Node) = 1; ;
+    break;}
+case 86:
+#line 835 "eval.y"
+{ ffval.Node = New_BinOp( BOOLEAN, ffvsp[-2].Node, GTE, ffvsp[0].Node ); TEST(ffval.Node);
+                  SIZE(ffval.Node) = 1; ;
+    break;}
+case 87:
+#line 838 "eval.y"
+{ ffval.Node = New_BinOp( BOOLEAN, ffvsp[-2].Node, LT,  ffvsp[0].Node ); TEST(ffval.Node);
+                  SIZE(ffval.Node) = 1; ;
+    break;}
+case 88:
+#line 841 "eval.y"
+{ ffval.Node = New_BinOp( BOOLEAN, ffvsp[-2].Node, LTE, ffvsp[0].Node ); TEST(ffval.Node);
+                  SIZE(ffval.Node) = 1; ;
+    break;}
+case 89:
+#line 844 "eval.y"
+{ ffval.Node = New_BinOp( BOOLEAN, ffvsp[-2].Node, AND, ffvsp[0].Node ); TEST(ffval.Node); ;
+    break;}
+case 90:
+#line 846 "eval.y"
+{ ffval.Node = New_BinOp( BOOLEAN, ffvsp[-2].Node, OR,  ffvsp[0].Node ); TEST(ffval.Node); ;
+    break;}
+case 91:
+#line 848 "eval.y"
+{ ffval.Node = New_BinOp( BOOLEAN, ffvsp[-2].Node, EQ,  ffvsp[0].Node ); TEST(ffval.Node); ;
+    break;}
+case 92:
+#line 850 "eval.y"
+{ ffval.Node = New_BinOp( BOOLEAN, ffvsp[-2].Node, NE,  ffvsp[0].Node ); TEST(ffval.Node); ;
+    break;}
+case 93:
+#line 853 "eval.y"
+{ PROMOTE(ffvsp[-4].Node,ffvsp[-2].Node); PROMOTE(ffvsp[-4].Node,ffvsp[0].Node); PROMOTE(ffvsp[-2].Node,ffvsp[0].Node);
+		  ffvsp[-2].Node = New_BinOp( BOOLEAN, ffvsp[-2].Node, LTE, ffvsp[-4].Node );
+                  ffvsp[0].Node = New_BinOp( BOOLEAN, ffvsp[-4].Node, LTE, ffvsp[0].Node );
+                  ffval.Node = New_BinOp( BOOLEAN, ffvsp[-2].Node, AND, ffvsp[0].Node );
+                  TEST(ffval.Node);                                         ;
+    break;}
+case 94:
+#line 860 "eval.y"
+{
+                  if( ! Test_Dims(ffvsp[-2].Node,ffvsp[0].Node) ) {
+                     fferror("Incompatible dimensions in '?:' arguments");
+		     FFERROR;
+                  }
+                  ffval.Node = New_Func( 0, ifthenelse_fct, 3, ffvsp[-2].Node, ffvsp[0].Node, ffvsp[-4].Node,
+                                 0, 0, 0, 0 );
+                  TEST(ffval.Node);
+                  if( SIZE(ffvsp[-2].Node)<SIZE(ffvsp[0].Node) )  Copy_Dims(ffval.Node, ffvsp[0].Node);
+                  if( ! Test_Dims(ffvsp[-4].Node,ffval.Node) ) {
+                     fferror("Incompatible dimensions in '?:' condition");
+		     FFERROR;
+                  }
+                  if( SIZE(ffval.Node)<SIZE(ffvsp[-4].Node) )  Copy_Dims(ffval.Node, ffvsp[-4].Node);
+                ;
+    break;}
+case 95:
+#line 877 "eval.y"
+{
+		   if (FSTRCMP(ffvsp[-2].str,"ISNULL(") == 0) {
+		      ffval.Node = New_Func( 0, isnull_fct, 1, ffvsp[-1].Node, 0, 0,
+				     0, 0, 0, 0 );
+		      TEST(ffval.Node); 
+                      /* Use expression's size, but return BOOLEAN */
+		      TYPE(ffval.Node) = BOOLEAN;
+		   } else {
+		      fferror("Boolean Function(expr) not supported");
+		      FFERROR;
+		   }
+		;
+    break;}
+case 96:
+#line 890 "eval.y"
+{
+		   if (FSTRCMP(ffvsp[-2].str,"ISNULL(") == 0) {
+		      ffval.Node = New_Func( 0, isnull_fct, 1, ffvsp[-1].Node, 0, 0,
+				     0, 0, 0, 0 );
+		      TEST(ffval.Node); 
+                      /* Use expression's size, but return BOOLEAN */
+		      TYPE(ffval.Node) = BOOLEAN;
+		   } else {
+		      fferror("Boolean Function(expr) not supported");
+		      FFERROR;
+		   }
+		;
+    break;}
+case 97:
+#line 903 "eval.y"
+{
+		   if (FSTRCMP(ffvsp[-2].str,"ISNULL(") == 0) {
+		      ffval.Node = New_Func( BOOLEAN, isnull_fct, 1, ffvsp[-1].Node, 0, 0,
+				     0, 0, 0, 0 );
+		      TEST(ffval.Node); 
+		   } else {
+		      fferror("Boolean Function(expr) not supported");
+		      FFERROR;
+		   }
+		;
+    break;}
+case 98:
+#line 914 "eval.y"
+{
+		   if (FSTRCMP(ffvsp[-4].str,"DEFNULL(") == 0) {
+		      if( SIZE(ffvsp[-3].Node)>=SIZE(ffvsp[-1].Node) && Test_Dims( ffvsp[-3].Node, ffvsp[-1].Node ) ) {
+			 ffval.Node = New_Func( 0, defnull_fct, 2, ffvsp[-3].Node, ffvsp[-1].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 99:
+#line 930 "eval.y"
+{
+		   if( TYPE(ffvsp[-5].Node) != DOUBLE ) ffvsp[-5].Node = New_Unary( DOUBLE, 0, ffvsp[-5].Node );
+		   if( TYPE(ffvsp[-3].Node) != DOUBLE ) ffvsp[-3].Node = New_Unary( DOUBLE, 0, ffvsp[-3].Node );
+		   if( TYPE(ffvsp[-1].Node) != DOUBLE ) ffvsp[-1].Node = New_Unary( DOUBLE, 0, ffvsp[-1].Node );
+		   if( ! (Test_Dims( ffvsp[-5].Node, ffvsp[-3].Node ) && Test_Dims( ffvsp[-3].Node, ffvsp[-1].Node ) ) ) {
+		       fferror("Dimensions of NEAR arguments "
+			       "are not compatible");
+		       FFERROR;
+		   } else {
+		     if (FSTRCMP(ffvsp[-6].str,"NEAR(") == 0) {
+		       ffval.Node = New_Func( BOOLEAN, near_fct, 3, ffvsp[-5].Node, ffvsp[-3].Node, ffvsp[-1].Node,
+				      0, 0, 0, 0 );
+		     } else {
+		       fferror("Boolean Function not supported");
+		       FFERROR;
+		     }
+		     TEST(ffval.Node); 
+
+		     if( SIZE(ffval.Node)<SIZE(ffvsp[-5].Node) )  Copy_Dims(ffval.Node, ffvsp[-5].Node);
+		     if( SIZE(ffvsp[-5].Node)<SIZE(ffvsp[-3].Node) )  Copy_Dims(ffval.Node, ffvsp[-3].Node);
+		     if( SIZE(ffvsp[-3].Node)<SIZE(ffvsp[-1].Node) )  Copy_Dims(ffval.Node, ffvsp[-1].Node);
+		   }
+		;
+    break;}
+case 100:
+#line 954 "eval.y"
+{
+		   if( TYPE(ffvsp[-9].Node) != DOUBLE ) ffvsp[-9].Node = New_Unary( DOUBLE, 0, ffvsp[-9].Node );
+		   if( TYPE(ffvsp[-7].Node) != DOUBLE ) ffvsp[-7].Node = New_Unary( DOUBLE, 0, ffvsp[-7].Node );
+		   if( TYPE(ffvsp[-5].Node) != DOUBLE ) ffvsp[-5].Node = New_Unary( DOUBLE, 0, ffvsp[-5].Node );
+		   if( TYPE(ffvsp[-3].Node) != DOUBLE ) ffvsp[-3].Node = New_Unary( DOUBLE, 0, ffvsp[-3].Node );
+		   if( TYPE(ffvsp[-1].Node)!= DOUBLE ) ffvsp[-1].Node= New_Unary( DOUBLE, 0, ffvsp[-1].Node);
+		   if( ! (Test_Dims( ffvsp[-9].Node, ffvsp[-7].Node ) && Test_Dims( ffvsp[-7].Node, ffvsp[-5].Node ) && 
+			  Test_Dims( ffvsp[-5].Node, ffvsp[-3].Node ) && Test_Dims( ffvsp[-3].Node, ffvsp[-1].Node )) ) {
+		     fferror("Dimensions of CIRCLE arguments "
+			     "are not compatible");
+		     FFERROR;
+		   } else {
+		     if (FSTRCMP(ffvsp[-10].str,"CIRCLE(") == 0) {
+		       ffval.Node = New_Func( BOOLEAN, circle_fct, 5, ffvsp[-9].Node, ffvsp[-7].Node, ffvsp[-5].Node, ffvsp[-3].Node,
+				      ffvsp[-1].Node, 0, 0 );
+		     } else {
+		       fferror("Boolean Function not supported");
+		       FFERROR;
+		     }
+		     TEST(ffval.Node); 
+		     if( SIZE(ffval.Node)<SIZE(ffvsp[-9].Node) )  Copy_Dims(ffval.Node, ffvsp[-9].Node);
+		     if( SIZE(ffvsp[-9].Node)<SIZE(ffvsp[-7].Node) )  Copy_Dims(ffval.Node, ffvsp[-7].Node);
+		     if( SIZE(ffvsp[-7].Node)<SIZE(ffvsp[-5].Node) )  Copy_Dims(ffval.Node, ffvsp[-5].Node);
+		     if( SIZE(ffvsp[-5].Node)<SIZE(ffvsp[-3].Node) )  Copy_Dims(ffval.Node, ffvsp[-3].Node);
+		     if( SIZE(ffvsp[-3].Node)<SIZE(ffvsp[-1].Node) ) Copy_Dims(ffval.Node, ffvsp[-1].Node);
+		   }
+		;
+    break;}
+case 101:
+#line 982 "eval.y"
+{
+		   if( TYPE(ffvsp[-13].Node) != DOUBLE ) ffvsp[-13].Node = New_Unary( DOUBLE, 0, ffvsp[-13].Node );
+		   if( TYPE(ffvsp[-11].Node) != DOUBLE ) ffvsp[-11].Node = New_Unary( DOUBLE, 0, ffvsp[-11].Node );
+		   if( TYPE(ffvsp[-9].Node) != DOUBLE ) ffvsp[-9].Node = New_Unary( DOUBLE, 0, ffvsp[-9].Node );
+		   if( TYPE(ffvsp[-7].Node) != DOUBLE ) ffvsp[-7].Node = New_Unary( DOUBLE, 0, ffvsp[-7].Node );
+		   if( TYPE(ffvsp[-5].Node)!= DOUBLE ) ffvsp[-5].Node= New_Unary( DOUBLE, 0, ffvsp[-5].Node);
+		   if( TYPE(ffvsp[-3].Node)!= DOUBLE ) ffvsp[-3].Node= New_Unary( DOUBLE, 0, ffvsp[-3].Node);
+		   if( TYPE(ffvsp[-1].Node)!= DOUBLE ) ffvsp[-1].Node= New_Unary( DOUBLE, 0, ffvsp[-1].Node);
+		   if( ! (Test_Dims( ffvsp[-13].Node, ffvsp[-11].Node ) && Test_Dims( ffvsp[-11].Node, ffvsp[-9].Node ) && 
+			  Test_Dims( ffvsp[-9].Node, ffvsp[-7].Node ) && Test_Dims( ffvsp[-7].Node, ffvsp[-5].Node ) &&
+			  Test_Dims(ffvsp[-5].Node,ffvsp[-3].Node ) && Test_Dims(ffvsp[-3].Node, ffvsp[-1].Node ) ) ) {
+		     fferror("Dimensions of BOX or ELLIPSE arguments "
+			     "are not compatible");
+		     FFERROR;
+		   } else {
+		     if (FSTRCMP(ffvsp[-14].str,"BOX(") == 0) {
+		       ffval.Node = New_Func( BOOLEAN, box_fct, 7, ffvsp[-13].Node, ffvsp[-11].Node, ffvsp[-9].Node, ffvsp[-7].Node,
+				      ffvsp[-5].Node, ffvsp[-3].Node, ffvsp[-1].Node );
+		     } else if (FSTRCMP(ffvsp[-14].str,"ELLIPSE(") == 0) {
+		       ffval.Node = New_Func( BOOLEAN, elps_fct, 7, ffvsp[-13].Node, ffvsp[-11].Node, ffvsp[-9].Node, ffvsp[-7].Node,
+				      ffvsp[-5].Node, ffvsp[-3].Node, ffvsp[-1].Node );
+		     } else {
+		       fferror("SAO Image Function not supported");
+		       FFERROR;
+		     }
+		     TEST(ffval.Node); 
+		     if( SIZE(ffval.Node)<SIZE(ffvsp[-13].Node) )  Copy_Dims(ffval.Node, ffvsp[-13].Node);
+		     if( SIZE(ffvsp[-13].Node)<SIZE(ffvsp[-11].Node) )  Copy_Dims(ffval.Node, ffvsp[-11].Node);
+		     if( SIZE(ffvsp[-11].Node)<SIZE(ffvsp[-9].Node) )  Copy_Dims(ffval.Node, ffvsp[-9].Node);
+		     if( SIZE(ffvsp[-9].Node)<SIZE(ffvsp[-7].Node) )  Copy_Dims(ffval.Node, ffvsp[-7].Node);
+		     if( SIZE(ffvsp[-7].Node)<SIZE(ffvsp[-5].Node) ) Copy_Dims(ffval.Node, ffvsp[-5].Node);
+		     if( SIZE(ffvsp[-5].Node)<SIZE(ffvsp[-3].Node) ) Copy_Dims(ffval.Node, ffvsp[-3].Node);
+		     if( SIZE(ffvsp[-3].Node)<SIZE(ffvsp[-1].Node) ) Copy_Dims(ffval.Node, ffvsp[-1].Node);
+		   }
+		;
+    break;}
+case 102:
+#line 1019 "eval.y"
+{ /* Use defaults for all elements */
+                   ffval.Node = New_GTI( "", -99, "*START*", "*STOP*" );
+                   TEST(ffval.Node);                                        ;
+    break;}
+case 103:
+#line 1023 "eval.y"
+{ /* Use defaults for all except filename */
+                   ffval.Node = New_GTI( ffvsp[-1].str, -99, "*START*", "*STOP*" );
+                   TEST(ffval.Node);                                        ;
+    break;}
+case 104:
+#line 1027 "eval.y"
+{  ffval.Node = New_GTI( ffvsp[-3].str, ffvsp[-1].Node, "*START*", "*STOP*" );
+                   TEST(ffval.Node);                                        ;
+    break;}
+case 105:
+#line 1030 "eval.y"
+{  ffval.Node = New_GTI( ffvsp[-7].str, ffvsp[-5].Node, ffvsp[-3].str, ffvsp[-1].str );
+                   TEST(ffval.Node);                                        ;
+    break;}
+case 106:
+#line 1034 "eval.y"
+{ /* Use defaults for all except filename */
+                   ffval.Node = New_REG( ffvsp[-1].str, -99, -99, "" );
+                   TEST(ffval.Node);                                        ;
+    break;}
+case 107:
+#line 1038 "eval.y"
+{  ffval.Node = New_REG( ffvsp[-5].str, ffvsp[-3].Node, ffvsp[-1].Node, "" );
+                   TEST(ffval.Node);                                        ;
+    break;}
+case 108:
+#line 1041 "eval.y"
+{  ffval.Node = New_REG( ffvsp[-7].str, ffvsp[-5].Node, ffvsp[-3].Node, ffvsp[-1].str );
+                   TEST(ffval.Node);                                        ;
+    break;}
+case 109:
+#line 1045 "eval.y"
+{ ffval.Node = New_Deref( ffvsp[-3].Node, 1, ffvsp[-1].Node,  0,  0,  0,   0 ); TEST(ffval.Node); ;
+    break;}
+case 110:
+#line 1047 "eval.y"
+{ ffval.Node = New_Deref( ffvsp[-5].Node, 2, ffvsp[-3].Node, ffvsp[-1].Node,  0,  0,   0 ); TEST(ffval.Node); ;
+    break;}
+case 111:
+#line 1049 "eval.y"
+{ ffval.Node = New_Deref( ffvsp[-7].Node, 3, ffvsp[-5].Node, ffvsp[-3].Node, ffvsp[-1].Node,  0,   0 ); TEST(ffval.Node); ;
+    break;}
+case 112:
+#line 1051 "eval.y"
+{ ffval.Node = New_Deref( ffvsp[-9].Node, 4, ffvsp[-7].Node, ffvsp[-5].Node, ffvsp[-3].Node, ffvsp[-1].Node,   0 ); TEST(ffval.Node); ;
+    break;}
+case 113:
+#line 1053 "eval.y"
+{ ffval.Node = New_Deref( ffvsp[-11].Node, 5, ffvsp[-9].Node, ffvsp[-7].Node, ffvsp[-5].Node, ffvsp[-3].Node, ffvsp[-1].Node ); TEST(ffval.Node); ;
+    break;}
+case 114:
+#line 1055 "eval.y"
+{ ffval.Node = New_Unary( BOOLEAN, NOT, ffvsp[0].Node ); TEST(ffval.Node); ;
+    break;}
+case 115:
+#line 1057 "eval.y"
+{ ffval.Node = ffvsp[-1].Node; ;
+    break;}
+case 116:
+#line 1061 "eval.y"
+{ ffval.Node = New_Const( STRING, ffvsp[0].str, strlen(ffvsp[0].str)+1 ); TEST(ffval.Node);
+                  SIZE(ffval.Node) = strlen(ffvsp[0].str); ;
+    break;}
+case 117:
+#line 1064 "eval.y"
+{ ffval.Node = New_Column( ffvsp[0].lng ); TEST(ffval.Node); ;
+    break;}
+case 118:
+#line 1066 "eval.y"
+{
+                  if( TYPE(ffvsp[-1].Node) != LONG
+		      || OPER(ffvsp[-1].Node) != CONST_OP ) {
+		     fferror("Offset argument must be a constant integer");
+		     FFERROR;
+		  }
+                  ffval.Node = New_Offset( ffvsp[-3].lng, ffvsp[-1].Node ); TEST(ffval.Node);
+                ;
+    break;}
+case 119:
+#line 1075 "eval.y"
+{ ffval.Node = New_Func( STRING, null_fct, 0, 0, 0, 0, 0, 0, 0, 0 ); ;
+    break;}
+case 120:
+#line 1077 "eval.y"
+{ ffval.Node = ffvsp[-1].Node; ;
+    break;}
+case 121:
+#line 1079 "eval.y"
+{ 
+		  if (SIZE(ffvsp[-2].Node)+SIZE(ffvsp[0].Node) >= MAX_STRLEN) {
+		    fferror("Combined string size exceeds " MAX_STRLEN_S " characters");
+		    FFERROR;
+		  }
+		  ffval.Node = New_BinOp( STRING, ffvsp[-2].Node, '+', ffvsp[0].Node );  TEST(ffval.Node);
+		  SIZE(ffval.Node) = SIZE(ffvsp[-2].Node) + SIZE(ffvsp[0].Node);
+		;
+    break;}
+case 122:
+#line 1088 "eval.y"
+{
+		  int outSize;
+                  if( SIZE(ffvsp[-4].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[-2].Node);
+		  if (SIZE(ffvsp[0].Node) > outSize) outSize = SIZE(ffvsp[0].Node);
+                  ffval.Node = New_FuncSize( 0, ifthenelse_fct, 3, ffvsp[-2].Node, ffvsp[0].Node, ffvsp[-4].Node,
+				     0, 0, 0, 0, outSize);
+		  
+                  TEST(ffval.Node);
+                  if( SIZE(ffvsp[-2].Node)<SIZE(ffvsp[0].Node) )  Copy_Dims(ffval.Node, ffvsp[0].Node);
+                ;
+    break;}
+case 123:
+#line 1107 "eval.y"
+{ 
+		  if (FSTRCMP(ffvsp[-4].str,"DEFNULL(") == 0) {
+		     int outSize;
+		     /* 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].Node);
+		     if (SIZE(ffvsp[-1].Node) > outSize) outSize = SIZE(ffvsp[-1].Node);
+		     
+		     ffval.Node = New_FuncSize( 0, defnull_fct, 2, ffvsp[-3].Node, ffvsp[-1].Node, 0,
+					0, 0, 0, 0, outSize );
+		     TEST(ffval.Node); 
+		     if( SIZE(ffvsp[-1].Node)>SIZE(ffvsp[-3].Node) ) SIZE(ffval.Node) = SIZE(ffvsp[-1].Node);
+		  } else {
+		     fferror("Function(string,string) not supported");
+		     FFERROR;
+		  }
+		;
+    break;}
+case 124:
+#line 1126 "eval.y"
+{ 
+		  if (FSTRCMP(ffvsp[-6].str,"STRMID(") == 0) {
+		    int len;
+		    if( TYPE(ffvsp[-3].Node) != LONG || SIZE(ffvsp[-3].Node) != 1 ||
+			TYPE(ffvsp[-1].Node) != LONG || SIZE(ffvsp[-1].Node) != 1) {
+		      fferror("When using STRMID(S,P,N), P and N must be integers (and not vector columns)");
+		      FFERROR;
+		    }
+		    if (OPER(ffvsp[-1].Node) == CONST_OP) {
+		      /* Constant value: use that directly */
+		      len = (gParse.Nodes[ffvsp[-1].Node].value.data.lng);
+		    } else {
+		      /* Variable value: use the maximum possible (from $2) */
+		      len = SIZE(ffvsp[-5].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[-5].Node, ffvsp[-3].Node,ffvsp[-1].Node,0,0,0,0,len);
+		    TEST(ffval.Node);
+		  } else {
+		     fferror("Function(string,expr,expr) not supported");
+		     FFERROR;
+		  }
+		;
+    break;}
+}
+   /* the action file gets copied in in place of this dollarsign */
+#line 498 "/usr1/local/share/bison.simple"
+
+  ffvsp -= fflen;
+  ffssp -= fflen;
+#ifdef FFLSP_NEEDED
+  fflsp -= fflen;
+#endif
+
+#if FFDEBUG != 0
+  if (ffdebug)
+    {
+      short *ssp1 = ffss - 1;
+      fprintf (stderr, "state stack now");
+      while (ssp1 != ffssp)
+	fprintf (stderr, " %d", *++ssp1);
+      fprintf (stderr, "\n");
+    }
+#endif
+
+  *++ffvsp = ffval;
+
+#ifdef FFLSP_NEEDED
+  fflsp++;
+  if (fflen == 0)
+    {
+      fflsp->first_line = fflloc.first_line;
+      fflsp->first_column = fflloc.first_column;
+      fflsp->last_line = (fflsp-1)->last_line;
+      fflsp->last_column = (fflsp-1)->last_column;
+      fflsp->text = 0;
+    }
+  else
+    {
+      fflsp->last_line = (fflsp+fflen-1)->last_line;
+      fflsp->last_column = (fflsp+fflen-1)->last_column;
+    }
+#endif
+
+  /* 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 - FFNTBASE] + *ffssp;
+  if (ffstate >= 0 && ffstate <= FFLAST && ffcheck[ffstate] == *ffssp)
+    ffstate = fftable[ffstate];
+  else
+    ffstate = ffdefgoto[ffn - FFNTBASE];
+
+  goto ffnewstate;
+
+fferrlab:   /* here on detecting error */
+
+  if (! fferrstatus)
+    /* If not already recovering from an error, report this error.  */
+    {
+      ++ffnerrs;
+
+#ifdef FFERROR_VERBOSE
+      ffn = ffpact[ffstate];
+
+      if (ffn > FFFLAG && ffn < FFLAST)
+	{
+	  int size = 0;
+	  char *msg;
+	  int x, count;
+
+	  count = 0;
+	  /* Start X at -ffn if nec to avoid negative indexes in ffcheck.  */
+	  for (x = (ffn < 0 ? -ffn : 0);
+	       x < (sizeof(fftname) / sizeof(char *)); x++)
+	    if (ffcheck[x + ffn] == x)
+	      size += strlen(fftname[x]) + 15, count++;
+	  msg = (char *) malloc(size + 15);
+	  if (msg != 0)
+	    {
+	      strcpy(msg, "parse error");
+
+	      if (count < 5)
+		{
+		  count = 0;
+		  for (x = (ffn < 0 ? -ffn : 0);
+		       x < (sizeof(fftname) / sizeof(char *)); x++)
+		    if (ffcheck[x + ffn] == x)
+		      {
+			strcat(msg, count == 0 ? ", expecting `" : " or `");
+			strcat(msg, fftname[x]);
+			strcat(msg, "'");
+			count++;
+		      }
+		}
+	      fferror(msg);
+	      free(msg);
+	    }
+	  else
+	    fferror ("parse error; also virtual memory exceeded");
+	}
+      else
+#endif /* FFERROR_VERBOSE */
+	fferror("parse error");
+    }
+
+  goto fferrlab1;
+fferrlab1:   /* here on error raised explicitly by an action */
+
+  if (fferrstatus == 3)
+    {
+      /* if just tried and failed to reuse lookahead token after an error, discard it.  */
+
+      /* return failure if at end of input */
+      if (ffchar == FFEOF)
+	FFABORT;
+
+#if FFDEBUG != 0
+      if (ffdebug)
+	fprintf(stderr, "Discarding token %d (%s).\n", ffchar, fftname[ffchar1]);
+#endif
+
+      ffchar = FFEMPTY;
+    }
+
+  /* Else will try to reuse lookahead token
+     after shifting the error token.  */
+
+  fferrstatus = 3;		/* Each real token shifted decrements this */
+
+  goto fferrhandle;
+
+fferrdefault:  /* current state does not do anything special for the error token. */
+
+#if 0
+  /* This is wrong; only states that explicitly want error tokens
+     should shift them.  */
+  ffn = ffdefact[ffstate];  /* If its default is to accept any token, ok.  Otherwise pop it.*/
+  if (ffn) goto ffdefault;
+#endif
+
+fferrpop:   /* pop the current state because it cannot handle the error token */
+
+  if (ffssp == ffss) FFABORT;
+  ffvsp--;
+  ffstate = *--ffssp;
+#ifdef FFLSP_NEEDED
+  fflsp--;
+#endif
+
+#if FFDEBUG != 0
+  if (ffdebug)
+    {
+      short *ssp1 = ffss - 1;
+      fprintf (stderr, "Error: state stack now");
+      while (ssp1 != ffssp)
+	fprintf (stderr, " %d", *++ssp1);
+      fprintf (stderr, "\n");
+    }
+#endif
+
+fferrhandle:
+
+  ffn = ffpact[ffstate];
+  if (ffn == FFFLAG)
+    goto fferrdefault;
+
+  ffn += FFTERROR;
+  if (ffn < 0 || ffn > FFLAST || ffcheck[ffn] != FFTERROR)
+    goto fferrdefault;
+
+  ffn = fftable[ffn];
+  if (ffn < 0)
+    {
+      if (ffn == FFFLAG)
+	goto fferrpop;
+      ffn = -ffn;
+      goto ffreduce;
+    }
+  else if (ffn == 0)
+    goto fferrpop;
+
+  if (ffn == FFFINAL)
+    FFACCEPT;
+
+#if FFDEBUG != 0
+  if (ffdebug)
+    fprintf(stderr, "Shifting error token, ");
+#endif
+
+  *++ffvsp = fflval;
+#ifdef FFLSP_NEEDED
+  *++fflsp = fflloc;
+#endif
+
+  ffstate = ffn;
+  goto ffnewstate;
+}
+#line 1155 "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; i<gParse.varData[ColNum].naxis; i++ )
+	 this->value.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; i<gParse.varData[ColNum].naxis; i++ )
+	 this->value.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; i<that->value.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; i<that1->value.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; i<that->value.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; idx<nDim; idx++ )
+	 constant = (constant && theDim[idx]->operation==CONST_OP);
+
+      for( idx=0; idx<nDim; idx++ )
+	 if( theDim[idx]->value.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; idx<this->value.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)<SIZE(NodeY) )  Copy_Dims(n, NodeY);
+
+      /* Init Region node to be treated as a "constant" */
+
+      that0                = gParse.Nodes + Node0;
+      that0->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; i<this->nSubNodes; 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; i<that1->value.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; i<that2->value.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;
+
+   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<gParse.nNodes; i++ ) {
+     if(    OPER(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_<Action> 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)<gParse.nRows ) {
+	       this->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; i<rows; i++) {
+	       sptr1 = that1->value.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; i<elem; i++) {
+	  if (!that1->value.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; i<elem; i++) {
+	     if (!that1->value.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; i<elem; i++) {
+	    if (!that1->value.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; i<elem; i++) {
+	    curr = that1->value.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; i<elem; i++) {
+	    if (!that1->value.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; i<elem; i++) {
+	    curr = that1->value.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 */
+
+
+  
+/*
+This (commented out) algorithm uses the Low of Cosines, which becomes
+ unstable for angles less than 0.1 arcsec. 
+ 
+  cd = sin(dec1*deg)*sin(dec2*deg) 
+    + cos(dec1*deg)*cos(dec2*deg)*cos((ra1-ra2)*deg);
+  if (cd < (-1)) cd = -1;
+  if (cd > (+1)) cd = +1;
+  return acos(cd)/deg;
+*/
+
+  /* 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 double ran1()
+{
+  static double dval = 0.0;
+  double rndVal;
+
+  if (dval == 0.0) {
+    if( rand()<32768 && rand()<32768 )
+      dval =      32768.0;
+    else
+      dval = 2147483648.0;
+  }
+
+  rndVal = (double)rand();
+  while( rndVal > dval ) dval *= 2.0;
+  return rndVal/dval;
+}
+
+/* Gaussian deviate routine from Numerical Recipes */
+static double gasdev()
+{
+  static int iset = 0;
+  static double gset;
+  double fac, rsq, v1, v2;
+
+  if (iset == 0) {
+    do {
+      v1 = 2.0*ran1()-1.0;
+      v2 = 2.0*ran1()-1.0;
+      rsq = v1*v1 + v2*v2;
+    } while (rsq >= 1.0 || rsq == 0.0);
+    fac = sqrt(-2.0*log(rsq)/rsq);
+    gset = v1*fac;
+    iset = 1;
+    return v2*fac;
+  } else {
+    iset = 0;
+    return gset;
+  }
+
+}
+
+/* lgamma function - from Numerical Recipes */
+
+float gammaln(float xx)
+     /* Returns the value ln Gamma[(xx)] for xx > 0. */
+{
+  /* 
+     Internal arithmetic will be done in double precision, a nicety
+     that you can omit if five-figure accuracy is good enough. */
+  double x,y,tmp,ser;
+  static double cof[6]={76.18009172947146,-86.50532032941677,
+			24.01409824083091,-1.231739572450155,
+			0.1208650973866179e-2,-0.5395239384953e-5};
+  int j;
+  y=x=xx;
+  tmp=x+5.5;
+  tmp -= (x+0.5)*log(tmp);
+  ser=1.000000000190015;
+  for (j=0;j<=5;j++) ser += cof[j]/++y;
+  return (float) -tmp+log(2.5066282746310005*ser/x);
+}
+
+/* Poisson deviate - derived from Numerical Recipes */
+static long poidev(double xm)
+{
+  static double sq, alxm, g, oldm = -1.0;
+  static double pi = 0;
+  double em, t, y;
+
+  if (pi == 0) pi = ((double)4)*atan((double)1);
+
+  if (xm < 20.0) {
+    if (xm != oldm) {
+      oldm = xm;
+      g = exp(-xm);
+    }
+    em = -1;
+    t = 1.0;
+    do {
+      em += 1;
+      t *= ran1();
+    } while (t > g);
+  } else {
+    if (xm != oldm) {
+      oldm = xm;
+      sq = sqrt(2.0*xm);
+      alxm = log(xm);
+      g = xm*alxm-gammaln( (float) (xm+1.0));
+    }
+    do {
+      do {
+	y = tan(pi*ran1());
+	em = sq*y+xm;
+      } while (em < 0.0);
+      em = floor(em);
+      t = 0.9*(1.0+y*y)*exp(em*alxm-gammaln( (float) (em+1.0) )-g);
+    } while (ran1() > t);
+  }
+
+  /* Return integer version */
+  return (long int) floor(em+0.5);
+}
+
+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 = poidev(pVals[0].data.dbl);
+	    else
+	      this->value.data.lng = poidev(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] = ran1();
+	     this->value.undef[elem] = 0;
+	    }
+	    break;
+
+	 case gasrnd_fct:
+	    while( elem-- ) {
+	       this->value.data.dblptr[elem] = gasdev();
+	       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] = poidev(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] = 
+		      poidev(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] = poidev(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] = 
+		      poidev(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<row; irow++) {
+		  long *p = mptr;
+		  int nelem1 = nelem;
+		  int count = 0;
+
+		  while ( nelem1-- ) { 
+		    if (*uptr == 0) {
+		      *p++ = *dptr;   /* Only advance the dest pointer if we copied */
+		    }
+		    dptr ++;  /* Advance the source pointer ... */
+		    uptr ++;  /* ... and source "undef" pointer */
+		  }
+		  
+		  nelem1 = (p - mptr);  /* Number of accepted data points */
+		  if (nelem1 > 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<row; irow++) {
+		  double *p = mptr;
+		  int nelem1 = nelem;
+
+		  while ( nelem1-- ) { 
+		    if (*uptr == 0) {
+		      *p++ = *dptr;   /* Only advance the dest pointer if we copied */
+		    }
+		    dptr ++;  /* Advance the source pointer ... */
+		    uptr ++;  /* ... and source "undef" pointer */
+		  }
+
+		  nelem1 = (p - mptr);  /* Number of accepted data points */
+		  if (nelem1 > 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; row<gParse.nRows; row++ ) {
+	       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 */
+	       }
+	       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; row<gParse.nRows; row++ ) {
+	      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;
+	      elem += theVar->value.nelem+1;
+	    }	       
+	 } else {
+	    elem = this->value.nelem * (dimVals[0]-1);
+	    for( row=0; row<gParse.nRows; row++ ) {
+	       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 );
+	       elem += theVar->value.nelem;
+	    }	       
+	 }
+      
+      } else if( theVar->value.naxis==nDims ) {
+
+	 /* Dereference completely using an expression for the indices */
+
+	 for( row=0; row<gParse.nRows; row++ ) {
+
+	    for( i=0; i<nDims; i++ ) {
+	       if( !isConst[i] ) {
+		  if( theDims[i]->value.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; row<gParse.nRows; row++ ) {
+
+	    /* Index cannot be a constant */
+
+	    if( theDims[0]->value.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; i<nDims; i++ )
+      if( theDims[i]->operation>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]<start[gti] || 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] ) {
+	       if( evtTime<=stop[gti-1] )
+		  gti -= step;
+	       else {
+		  gti = -1L;
+		  break;
+	       }
+	    } else {
+	       break;
+	    }
+	 }
+      } else
+	 gti = -1L;
+      
+   } else { /*  Use "SLOW" linear search  */
+      gti = nGTI;
+      while( gti-- )
+	 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; node<this->nSubNodes; 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[256];
+ char chr1, chr2;
+
+ l1 = strlen(bits1);
+ l2 = strlen(bits2);
+ if (l1 < l2)
+   {
+    length = 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)
+   {
+    length = l1;
+    ldiff = l1 - l2;
+    i=0;
+    while( ldiff-- ) stream[i++] = '0';
+    while( l2--    ) stream[i++] = *(bits2++);
+    stream[i] = '\0';
+    bits2 = stream;
+   }
+ else
+    length = l1;
+
+ 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;
+       }
+ return (result);
+}
+
+static void bitand(char *result,char *bitstrm1,char *bitstrm2)
+{
+ int i, l1, l2, ldiff;
+ char stream[256];
+ char chr1, chr2;
+
+ l1 = strlen(bitstrm1);
+ l2 = strlen(bitstrm2);
+ 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++;
+    }
+ *result = '\0';
+}
+
+static void bitor(char *result,char *bitstrm1,char *bitstrm2)
+{
+ int i, l1, l2, ldiff;
+ char stream[256];
+ char chr1, chr2;
+
+ l1 = strlen(bitstrm1);
+ l2 = strlen(bitstrm2);
+ 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++;
+    }
+ *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;
+ char stream[256];
+ char chr1, chr2;
+
+ l1 = strlen(bitstrm1);
+ l2 = strlen(bitstrm2);
+ 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')) )
+	  return( 0 );
+    }
+ 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);
+}
diff --git a/cextern/cfitsio/fits_hcompress.c b/cextern/cfitsio/fits_hcompress.c
new file mode 100644
index 0000000..96a6b12
--- /dev/null
+++ b/cextern/cfitsio/fits_hcompress.c
@@ -0,0 +1,1858 @@
+/*  #########################################################################
+These routines to apply the H-compress compression algorithm to a 2-D Fits
+image were written by R. White at the STScI and were obtained from the STScI at
+http://www.stsci.edu/software/hcompress.html
+
+This source file is a concatination of the following sources files in the
+original distribution 
+ htrans.c 
+ digitize.c 
+ encode.c 
+ qwrite.c 
+ doencode.c 
+ bit_output.c 
+ qtree_encode.c
+
+The following modifications have been made to the original code:
+
+  - commented out redundant "include" statements
+  - added the noutchar global variable 
+  - changed all the 'extern' declarations to 'static', since all the routines are in
+    the same source file
+  - changed the first parameter in encode (and in lower level routines from a file stream
+    to a char array
+  - modifid the encode routine to return the size of the compressed array of bytes
+  - changed calls to printf and perror to call the CFITSIO ffpmsg routine
+  - modified the mywrite routine, and lower level byte writing routines,  to copy 
+    the output bytes to a char array, instead of writing them to a file stream
+  - replace "exit" statements with "return" statements
+  - changed the function declarations to the more modern ANSI C style
+
+ ############################################################################  */
+ 
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <stdlib.h>
+#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<<log2n) ) {
+		log2n += 1;
+	}
+	/*
+	 * get temporary storage for shuffling elements
+	 */
+	tmp = (int *) malloc(((nmax+1)/2)*sizeof(int));
+	if(tmp == (int *) NULL) {
+	        ffpmsg("htrans: insufficient memory");
+		return(DATA_COMPRESSION_ERR);
+	}
+	/*
+	 * set up rounding and shifting masks
+	 */
+	shift = 0;
+	mask  = -2;
+	mask2 = mask << 1;
+	prnd  = 1;
+	prnd2 = prnd << 1;
+	nrnd2 = prnd2 - 1;
+	/*
+	 * do log2n reductions
+	 *
+	 * We're indexing a as a 2-D array with dimensions (nx,ny).
+	 */
+	nxtop = nx;
+	nytop = ny;
+
+	for (k = 0; k<log2n; k++) {
+		oddx = nxtop % 2;
+		oddy = nytop % 2;
+		for (i = 0; i<nxtop-oddx; i += 2) {
+			s00 = i*ny;				/* s00 is index of a[i,j]	*/
+			s10 = s00+ny;			/* s10 is index of a[i+1,j]	*/
+			for (j = 0; j<nytop-oddy; j += 2) {
+				/*
+				 * Divide h0,hx,hy,hc by 2 (1 the first time through).
+				 */
+				h0 = (a[s10+1] + a[s10] + a[s00+1] + a[s00]) >> 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<nytop-oddy; j += 2) {
+				h0 = (a[s00+1] + a[s00]) << (1-shift);
+				hy = (a[s00+1] - a[s00]) << (1-shift);
+				a[s00+1] = ( (hy>=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<nxtop; i++) {
+			shuffle(&a[ny*i],nytop,1,tmp);
+		}
+		for (j = 0; j<nytop; j++) {
+			shuffle(&a[j],nxtop,ny,tmp);
+		}
+		/*
+		 * image size reduced by 2 (round up if odd)
+		 */
+		nxtop = (nxtop+1)>>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<<log2n) ) {
+		log2n += 1;
+	}
+	/*
+	 * get temporary storage for shuffling elements
+	 */
+	tmp = (LONGLONG *) malloc(((nmax+1)/2)*sizeof(LONGLONG));
+	if(tmp == (LONGLONG *) NULL) {
+	        ffpmsg("htrans64: insufficient memory");
+		return(DATA_COMPRESSION_ERR);
+	}
+	/*
+	 * set up rounding and shifting masks
+	 */
+	shift = 0;
+	mask  = (LONGLONG) -2;
+	mask2 = mask << 1;
+	prnd  = (LONGLONG) 1;
+	prnd2 = prnd << 1;
+	nrnd2 = prnd2 - 1;
+	/*
+	 * do log2n reductions
+	 *
+	 * We're indexing a as a 2-D array with dimensions (nx,ny).
+	 */
+	nxtop = nx;
+	nytop = ny;
+
+	for (k = 0; k<log2n; k++) {
+		oddx = nxtop % 2;
+		oddy = nytop % 2;
+		for (i = 0; i<nxtop-oddx; i += 2) {
+			s00 = i*ny;				/* s00 is index of a[i,j]	*/
+			s10 = s00+ny;			/* s10 is index of a[i+1,j]	*/
+			for (j = 0; j<nytop-oddy; j += 2) {
+				/*
+				 * Divide h0,hx,hy,hc by 2 (1 the first time through).
+				 */
+				h0 = (a[s10+1] + a[s10] + a[s00+1] + a[s00]) >> 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<nytop-oddy; j += 2) {
+				h0 = (a[s00+1] + a[s00]) << (1-shift);
+				hy = (a[s00+1] - a[s00]) << (1-shift);
+				a[s00+1] = ( (hy>=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<nxtop; i++) {
+			shuffle64(&a[ny*i],nytop,1,tmp);
+		}
+		for (j = 0; j<nytop; j++) {
+			shuffle64(&a[j],nxtop,ny,tmp);
+		}
+		/*
+		 * image size reduced by 2 (round up if odd)
+		 */
+		nxtop = (nxtop+1)>>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; i<n; i += 2) {
+		*p1 = *p2;
+		p1 += n2;
+		p2 += (n2+n2);
+	}
+	/*
+	 * put odd elements into 2nd half
+	 */
+	pt = tmp;
+	for (i = 1; i<n; i += 2) {
+		*p1 = *pt;
+		p1 += n2;
+		pt += 1;
+	}
+}
+/* ######################################################################### */
+static void
+shuffle64(LONGLONG a[], int n, int n2, LONGLONG tmp[])
+{
+
+/* 
+LONGLONG a[];	 array to shuffle					
+int n;		 number of elements to shuffle	
+int n2;		 second dimension					
+LONGLONG tmp[];	 scratch storage					
+*/
+
+int i;
+LONGLONG *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; i<n; i += 2) {
+		*p1 = *p2;
+		p1 += n2;
+		p2 += (n2+n2);
+	}
+	/*
+	 * put odd elements into 2nd half
+	 */
+	pt = tmp;
+	for (i = 1; i<n; i += 2) {
+		*p1 = *pt;
+		p1 += n2;
+		pt += 1;
+	}
+}
+/* ######################################################################### */
+/* ######################################################################### */
+/* Copyright (c) 1993 Association of Universities for Research 
+ * in Astronomy. All rights reserved. Produced under National   
+ * Aeronautics and Space Administration Contract No. NAS5-26555.
+ */
+/* digitize.c	digitize H-transform
+ *
+ * Programmer: R. White		Date: 11 March 1991
+ */
+
+/* ######################################################################### */
+static void  
+digitize(int a[], int nx, int ny, int scale)
+{
+int d, *p;
+
+	/*
+	 * round to multiple of scale
+	 */
+	if (scale <= 1) return;
+	d=(scale+1)/2-1;
+	for (p=a; p <= &a[nx*ny-1]; p++) *p = ((*p>0) ? (*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
+	 */
+	signbits = (unsigned char *) malloc((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<nel; i++) {
+		if (a[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<nel; i++) {
+		q = (j>=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<<nbitplanes[q]) ) {
+			nbitplanes[q] += 1;
+		}
+	}
+*/
+
+	/*
+	 * write nbitplanes
+	 */
+	if (0 == qwrite(outfile, (char *) nbitplanes, sizeof(nbitplanes))) {
+	        *nlength = noutchar;
+		ffpmsg("encode: output buffer too small");
+		return(DATA_COMPRESSION_ERR);
+        }
+	 
+	/*
+	 * write coded array
+	 */
+	stat = doencode(outfile, a, nx, ny, nbitplanes);
+	/*
+	 * write sign bits
+	 */
+
+	if (nsign > 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 *) malloc((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<nel; i++) {
+		if (a[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<nel; i++) {
+		q = (j>=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)<<nbitplanes[q]) ) {
+			nbitplanes[q] += 1;
+		}
+	}
+*/
+
+	/*
+	 * write nbitplanes
+	 */
+
+	if (0 == qwrite(outfile, (char *) nbitplanes, sizeof(nbitplanes))) {
+	        *nlength = noutchar;
+		ffpmsg("encode: output buffer too small");
+		return(DATA_COMPRESSION_ERR);
+        }
+	 
+	/*
+	 * write coded array
+	 */
+	stat = doencode64(outfile, a, nx, ny, nbitplanes);
+	/*
+	 * write sign bits
+	 */
+
+	if (nsign > 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<<n)-1) ); */
+	buffer2 |= ( bits & (*(mask+n)) );
+	bits_to_go2 -= n;
+	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 += 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<<bits_to_go2,outfile); */
+
+	        outfile[noutchar] = (buffer2<<bits_to_go2);
+		if (noutchar < noutmax) noutchar++;
+
+		/* count the garbage bits too */
+		bitcount += bits_to_go2;
+	}
+}
+/* ######################################################################### */
+/* ######################################################################### */
+/* Copyright (c) 1993 Association of Universities for Research 
+ * in Astronomy. All rights reserved. Produced under National   
+ * Aeronautics and Space Administration Contract No. NAS5-26555.
+ */
+/* qtree_encode.c	Encode values in quadrant of 2-D array using binary
+ *					quadtree coding for each bit plane.  Assumes array is
+ *					positive.
+ *
+ * Programmer: R. White		Date: 15 May 1991
+ */
+
+/*
+ * Huffman code values and number of bits in each code
+ */
+static int code[16] =
+	{
+	0x3e, 0x00, 0x01, 0x08, 0x02, 0x09, 0x1a, 0x1b,
+	0x03, 0x1c, 0x0a, 0x1d, 0x0b, 0x1e, 0x3f, 0x0c
+	};
+static int ncode[16] =
+	{
+	6,    3,    3,    4,    3,    4,    5,    5,
+	3,    5,    4,    5,    4,    5,    6,    4
+	};
+
+/*
+ * variables for bit output to buffer when Huffman coding
+ */
+static int bitbuffer, bits_to_go3;
+
+/*
+ * macros to write out 4-bit nybble, Huffman code for this value
+ */
+
+
+/* ######################################################################### */
+static int
+qtree_encode(char *outfile, int a[], int n, int nqx, int nqy, int nbitplanes)
+{
+
+/*
+int 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, bmax, nqmax, nqx2, nqy2, nx, ny;
+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<<log2n)) {
+		log2n += 1;
+	}
+	/*
+	 * initialize buffer point, max buffer size
+	 */
+	nqx2 = (nqx+1)/2;
+	nqy2 = (nqy+1)/2;
+	bmax = (nqx2*nqy2+1)/2;
+	/*
+	 * We're indexing A as a 2-D array with dimensions (nqx,nqy).
+	 * Scratch is 2-D with dimensions (nqx/2,nqy/2) rounded up.
+	 * Buffer is used to store string of codes for output.
+	 */
+	scratch = (unsigned char *) malloc(2*bmax);
+	buffer = (unsigned char *) malloc(bmax);
+	if ((scratch == (unsigned char *) NULL) ||
+		(buffer  == (unsigned char *) NULL)) {		
+		ffpmsg("qtree_encode: insufficient memory");
+		return(DATA_COMPRESSION_ERR);
+	}
+	/*
+	 * now encode each bit plane, starting with the top
+	 */
+	for (bit=nbitplanes-1; bit >= 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<log2n; k++) {
+			qtree_reduce(scratch,ny,nx,ny,scratch);
+			nx = (nx+1)>>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<<bits_to_go3)-1),
+					bits_to_go3);
+			} else {
+				/*
+				 * have to write a zero nybble if there are no 1's in array
+				 */
+				output_huffman(outfile,0);
+			}
+		} else {
+			if (bits_to_go3>0) {
+				/*
+				 * put out the last few bits
+				 */
+				output_nbits(outfile, bitbuffer & ((1<<bits_to_go3)-1),
+					bits_to_go3);
+			}
+			for (i=b-1; i>=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<<log2n)) {
+		log2n += 1;
+	}
+	/*
+	 * initialize buffer point, max buffer size
+	 */
+	nqx2 = (nqx+1)/2;
+	nqy2 = (nqy+1)/2;
+	bmax = (( nqx2)* ( nqy2)+1)/2;
+	/*
+	 * We're indexing A as a 2-D array with dimensions (nqx,nqy).
+	 * Scratch is 2-D with dimensions (nqx/2,nqy/2) rounded up.
+	 * Buffer is used to store string of codes for output.
+	 */
+	scratch = (unsigned char *) malloc(2*bmax);
+	buffer = (unsigned char *) malloc(bmax);
+	if ((scratch == (unsigned char *) NULL) ||
+		(buffer  == (unsigned char *) NULL)) {
+		ffpmsg("qtree_encode64: insufficient memory");
+		return(DATA_COMPRESSION_ERR);
+	}
+	/*
+	 * now encode each bit plane, starting with the top
+	 */
+	for (bit=nbitplanes-1; bit >= 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<log2n; k++) {
+			qtree_reduce(scratch,ny,nx,ny,scratch);
+			nx = (nx+1)>>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<<bits_to_go3)-1),
+					bits_to_go3);
+			} else {
+				/*
+				 * have to write a zero nybble if there are no 1's in array
+				 */
+				output_huffman(outfile,0);
+			}
+		} else {
+			if (bits_to_go3>0) {
+				/*
+				 * put out the last few bits
+				 */
+				output_nbits(outfile, bitbuffer & ((1<<bits_to_go3)-1),
+					bits_to_go3);
+			}
+			for (i=b-1; i>=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;
+	b1 = b0<<1;
+	b2 = b0<<2;
+	b3 = b0<<3;
+	k = 0;							/* k is index of b[i/2,j/2]	*/
+	for (i = 0; i<nx-1; i += 2) {
+		s00 = n*i;					/* s00 is index of a[i,j]	*/
+/* tried using s00+n directly in the statements, but this had no effect on performance */
+		s10 = s00+n;				/* s10 is index of a[i+1,j]	*/
+		for (j = 0; j<ny-1; j += 2) {
+
+/*
+ this was not any faster..
+ 
+         b[k] = (a[s00]  & b0) ? 
+	            (a[s00+1] & b0) ?
+	                (a[s10] & b0)   ?
+		            (a[s10+1] & b0) ? 15 : 14
+                         :  (a[s10+1] & b0) ? 13 : 12
+		      : (a[s10] & b0)   ?
+		            (a[s10+1] & b0) ? 11 : 10
+                         :  (a[s10+1] & b0) ?  9 :  8
+	          : (a[s00+1] & b0) ?
+	                (a[s10] & b0)   ?
+		            (a[s10+1] & b0) ? 7 : 6
+                         :  (a[s10+1] & b0) ? 5 : 4
+
+		      : (a[s10] & b0)   ?
+		            (a[s10+1] & b0) ? 3 : 2
+                         :  (a[s10+1] & b0) ? 1 : 0;
+*/
+
+/*
+this alternative way of calculating b[k] was slowwer than the original code
+		    if ( a[s00]     & b0)
+			if ( a[s00+1]     & b0)
+			    if ( a[s10]     & b0)
+				if ( a[s10+1]     & b0)
+					b[k] = 15;
+				else
+					b[k] = 14;
+			    else
+				if ( a[s10+1]     & b0)
+					b[k] = 13;
+				else
+					b[k] = 12;
+			else
+			    if ( a[s10]     & b0)
+				if ( a[s10+1]     & b0)
+					b[k] = 11;
+				else
+					b[k] = 10;
+			    else
+				if ( a[s10+1]     & b0)
+					b[k] = 9;
+				else
+					b[k] = 8;
+		    else
+			if ( a[s00+1]     & b0)
+			    if ( a[s10]     & b0)
+				if ( a[s10+1]     & b0)
+					b[k] = 7;
+				else
+					b[k] = 6;
+			    else
+				if ( a[s10+1]     & b0)
+					b[k] = 5;
+				else
+					b[k] = 4;
+			else
+			    if ( a[s10]     & b0)
+				if ( a[s10+1]     & b0)
+					b[k] = 3;
+				else
+					b[k] = 2;
+			    else
+				if ( a[s10+1]     & b0)
+					b[k] = 1;
+				else
+					b[k] = 0;
+*/
+			
+
+
+			b[k] = ( ( a[s10+1]     & b0)
+				   | ((a[s10  ]<<1) & b1)
+				   | ((a[s00+1]<<2) & b2)
+				   | ((a[s00  ]<<3) & b3) ) >> 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<ny-1; j += 2) {
+			b[k] = ( ((a[s00+1]<<2) & b2)
+				   | ((a[s00  ]<<3) & b3) ) >> 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;
+	b1 = b0<<1;
+	b2 = b0<<2;
+	b3 = b0<<3;
+	k = 0;							/* k is index of b[i/2,j/2]	*/
+	for (i = 0; i<nx-1; i += 2) {
+		s00 = n*i;					/* s00 is index of a[i,j]	*/
+		s10 = s00+n;				/* s10 is index of a[i+1,j]	*/
+		for (j = 0; j<ny-1; j += 2) {
+			b[k] = (unsigned char) (( ( a[s10+1]     & b0)
+				   | ((a[s10  ]<<1) & b1)
+				   | ((a[s00+1]<<2) & b2)
+				   | ((a[s00  ]<<3) & b3) ) >> 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<ny-1; j += 2) {
+			b[k] = (unsigned char) (( ((a[s00+1]<<2) & b2)
+				   | ((a[s00  ]<<3) & b3) ) >> 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<nx-1; i += 2) {
+		s00 = n*i;					/* s00 is index of a[i,j]	*/
+		s10 = s00+n;				/* s10 is index of a[i+1,j]	*/
+		for (j = 0; j<ny-1; j += 2) {
+			b[k] =	(a[s10+1] != 0)
+				| ( (a[s10  ] != 0) << 1)
+				| ( (a[s00+1] != 0) << 2)
+				| ( (a[s00  ] != 0) << 3);
+			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  ] != 0) << 1)
+				  | ( (a[s00  ] != 0) << 3);
+			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<ny-1; j += 2) {
+			b[k] =  ( (a[s00+1] != 0) << 2)
+				  | ( (a[s00  ] != 0) << 3);
+			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  ] != 0) << 3);
+			k += 1;
+		}
+	}
+}
+
+/* ######################################################################### */
+static void
+write_bdirect(char *outfile, int a[], int n,int nqx, int nqy, unsigned char scratch[], int bit)
+{
+
+	/*
+	 * Write the direct bitmap warning code
+	 */
+	output_nybble(outfile,0x0);
+	/*
+	 * Copy A to scratch array (again!), packing 4 bits/nybble
+	 */
+	qtree_onebit(a,n,nqx,nqy,scratch,bit);
+	/*
+	 * write to outfile
+	 */
+/*
+int i;
+	for (i = 0; i < ((nqx+1)/2) * ((nqy+1)/2); i++) {
+		output_nybble(outfile,scratch[i]);
+	}
+*/
+	output_nnybble(outfile, ((nqx+1)/2) * ((nqy+1)/2), scratch);
+
+}
+/* ######################################################################### */
+static void
+write_bdirect64(char *outfile, LONGLONG a[], int n,int nqx, int nqy, unsigned char scratch[], int bit)
+{
+
+	/*
+	 * Write the direct bitmap warning code
+	 */
+	output_nybble(outfile,0x0);
+	/*
+	 * Copy A to scratch array (again!), packing 4 bits/nybble
+	 */
+	qtree_onebit64(a,n,nqx,nqy,scratch,bit);
+	/*
+	 * write to outfile
+	 */
+/*
+int i;
+	for (i = 0; i < ((nqx+1)/2) * ((nqy+1)/2); i++) {
+		output_nybble(outfile,scratch[i]);
+	}
+*/
+	output_nnybble(outfile, ((nqx+1)/2) * ((nqy+1)/2), scratch);
+}
diff --git a/cextern/cfitsio/fits_hdecompress.c b/cextern/cfitsio/fits_hdecompress.c
new file mode 100644
index 0000000..2086d38
--- /dev/null
+++ b/cextern/cfitsio/fits_hdecompress.c
@@ -0,0 +1,2618 @@
+/*  #########################################################################
+These routines to apply the H-compress decompression algorithm to a 2-D Fits
+image were written by R. White at the STScI and were obtained from the STScI at
+http://www.stsci.edu/software/hcompress.html
+
+This source file is a concatination of the following sources files in the
+original distribution 
+  hinv.c 
+  hsmooth.c 
+  undigitize.c 
+  decode.c 
+  dodecode.c 
+  qtree_decode.c 
+  qread.c 
+  bit_input.c
+
+
+The following modifications have been made to the original code:
+
+  - commented out redundant "include" statements
+  - added the nextchar global variable 
+  - changed all the 'extern' declarations to 'static', since all the routines are in
+    the same source file
+  - changed the first parameter in decode (and in lower level routines from a file stream
+    to a char array
+  - modified the myread routine, and lower level byte reading routines,  to copy 
+    the input bytes to a char array, instead of reading them from a file stream
+  - changed the function declarations to the more modern ANSI C style
+  - changed calls to printf and perror to call the CFITSIO ffpmsg routine
+  - replace "exit" statements with "return" statements
+
+ ############################################################################  */
+ 
+#include <stdio.h>
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+#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<<log2n) ) {
+		log2n += 1;
+	}
+	/*
+	 * get temporary storage for shuffling elements
+	 */  
+	tmp = (int *) malloc(((nmax+1)/2)*sizeof(int));
+	if (tmp == (int *) NULL) {
+		ffpmsg("hinv: insufficient memory");
+		return(DATA_DECOMPRESSION_ERR);
+	}
+	/*
+	 * set up masks, rounding parameters
+	 */
+	shift  = 1;
+	bit0   = 1 << (log2n - 1);
+	bit1   = bit0 << 1;
+	bit2   = bit0 << 2;
+	mask0  = -bit0;
+	mask1  = mask0 << 1;
+	mask2  = mask0 << 2;
+	prnd0  = bit0 >> 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<<log2n;
+	for (k = log2n-1; k>=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<nxtop; i++) {
+			unshuffle(&a[ny*i],nytop,1,tmp);
+		}
+		for (j = 0; j<nytop; j++) {
+			unshuffle(&a[j],nxtop,ny,tmp);
+		}
+		/*
+		 * smooth by interpolating coefficients if SMOOTH != 0
+		 */
+		if (smooth) hsmooth(a,nxtop,nytop,ny,scale);
+		oddx = nxtop % 2;
+		oddy = nytop % 2;
+		for (i = 0; i<nxtop-oddx; i += 2) {
+			s00 = ny*i;				/* s00 is index of a[i,j]	*/
+			s10 = s00+ny;			/* s10 is index of a[i+1,j]	*/
+			for (j = 0; j<nytop-oddy; j += 2) {
+				h0 = a[s00  ];
+				hx = a[s10  ];
+				hy = a[s00+1];
+				hc = a[s10+1];
+				/*
+				 * round hx and hy to multiple of bit1, hc to multiple of bit0
+				 * h0 is already a multiple of bit2
+				 */
+				hx = (hx + ((hx >= 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<nytop-oddy; j += 2) {
+				h0 = a[s00  ];
+				hy = a[s00+1];
+				hy = ((hy >= 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<<log2n) ) {
+		log2n += 1;
+	}
+	/*
+	 * get temporary storage for shuffling elements
+	 */  
+	tmp = (LONGLONG *) malloc(((nmax+1)/2)*sizeof(LONGLONG));
+	if (tmp == (LONGLONG *) NULL) {
+		ffpmsg("hinv64: insufficient memory");
+		return(DATA_DECOMPRESSION_ERR);
+	}
+	/*
+	 * set up masks, rounding parameters
+	 */
+	shift  = 1;
+	bit0   = ((LONGLONG) 1) << (log2n - 1);
+	bit1   = bit0 << 1;
+	bit2   = bit0 << 2;
+	mask0  = -bit0;
+	mask1  = mask0 << 1;
+	mask2  = mask0 << 2;
+	prnd0  = bit0 >> 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<<log2n;
+	for (k = log2n-1; k>=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<nxtop; i++) {
+			unshuffle64(&a[ny*i],nytop,1,tmp);
+		}
+		for (j = 0; j<nytop; j++) {
+			unshuffle64(&a[j],nxtop,ny,tmp);
+		}
+		/*
+		 * smooth by interpolating coefficients if SMOOTH != 0
+		 */
+		if (smooth) hsmooth64(a,nxtop,nytop,ny,scale);
+		oddx = nxtop % 2;
+		oddy = nytop % 2;
+		for (i = 0; i<nxtop-oddx; i += 2) {
+			s00 = ny*i;				/* s00 is index of a[i,j]	*/
+			s10 = s00+ny;			/* s10 is index of a[i+1,j]	*/
+			for (j = 0; j<nytop-oddy; j += 2) {
+				h0 = a[s00  ];
+				hx = a[s10  ];
+				hy = a[s00+1];
+				hc = a[s10+1];
+				/*
+				 * round hx and hy to multiple of bit1, hc to multiple of bit0
+				 * h0 is already a multiple of bit2
+				 */
+				hx = (hx + ((hx >= 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<nytop-oddy; j += 2) {
+				h0 = a[s00  ];
+				hy = a[s00+1];
+				hy = ((hy >= 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<n; i++) {
+		*pt = *p1;
+		p1 += n2;
+		pt += 1;
+	}
+	/*
+	 * distribute 1st half of array to even elements
+	 */
+	p2 = &a[ n2*(nhalf-1) ];		/* pointer to a[i]			*/
+	p1 = &a[(n2*(nhalf-1))<<1];		/* pointer to a[2*i]		*/
+	for (i=nhalf-1; 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<n; i += 2) {
+		*p1 = *pt;
+		p1 += (n2+n2);
+		pt += 1;
+	}
+}
+/*  ############################################################################  */
+static void
+unshuffle64(LONGLONG a[], int n, int n2, LONGLONG tmp[])
+/*
+LONGLONG a[];	 array to shuffle					
+int n;		 number of elements to shuffle	
+int n2;		 second dimension					
+LONGLONG tmp[];	 scratch storage					
+*/
+{
+int i;
+int nhalf;
+LONGLONG *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<n; i++) {
+		*pt = *p1;
+		p1 += n2;
+		pt += 1;
+	}
+	/*
+	 * distribute 1st half of array to even elements
+	 */
+	p2 = &a[ n2*(nhalf-1) ];		/* pointer to a[i]			*/
+	p1 = &a[(n2*(nhalf-1))<<1];		/* pointer to a[2*i]		*/
+	for (i=nhalf-1; 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<n; i += 2) {
+		*p1 = *pt;
+		p1 += (n2+n2);
+		pt += 1;
+	}
+}
+
+/*  ############################################################################  */
+/*  ############################################################################  */
+
+/* Copyright (c) 1993 Association of Universities for Research 
+ * in Astronomy. All rights reserved. Produced under National   
+ * Aeronautics and Space Administration Contract No. NAS5-26555.
+ */
+/* hsmooth.c	Smooth H-transform image by adjusting coefficients toward
+ *				interpolated values
+ *
+ * Programmer: R. White		Date: 13 April 1992
+ */
+
+/*  ############################################################################  */
+static void 
+hsmooth(int a[], int nxtop, int nytop, int ny, int scale)
+/*
+int 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, diff, dmax, dmin, s, smax;
+int hm, h0, hp, hmm, hpm, hmp, hpp, hx2, hy2;
+int 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<nxtop-2; i += 2) {
+		s00 = ny*i;				/* s00 is index of a[i,j]	*/
+		s10 = s00+ny;			/* s10 is index of a[i+1,j]	*/
+		for (j = 0; j<nytop; j += 2) {
+			/*
+			 * hp is h0 (mean value) in next x zone, hm is h0 in previous x zone
+			 */
+			hm = a[s00-ny2];
+			h0 = a[s00];
+			hp = a[s00+ny2];
+			/*
+			 * diff = 8 * hx slope that would match h0 in neighboring zones
+			 */
+			diff = hp-hm;
+			/*
+			 * monotonicity constraints on diff
+			 */
+			dmax = max( min( (hp-h0), (h0-hm) ), 0 ) << 2;
+			dmin = min( max( (hp-h0), (h0-hm) ), 0 ) << 2;
+			/*
+			 * if monotonicity would set slope = 0 then don't change hx.
+			 * note dmax>=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<nxtop; i += 2) {
+		s00 = ny*i+2;
+		s10 = s00+ny;
+		for (j = 2; j<nytop-2; j += 2) {
+			hm = a[s00-2];
+			h0 = a[s00];
+			hp = a[s00+2];
+			diff = hp-hm;
+			dmax = max( min( (hp-h0), (h0-hm) ), 0 ) << 2;
+			dmin = min( max( (hp-h0), (h0-hm) ), 0 ) << 2;
+			if (dmin < dmax) {
+				diff = max( min(diff, dmax), dmin);
+				s = diff-(a[s00+1]<<3);
+				s = (s>=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<nxtop-2; i += 2) {
+		s00 = ny*i+2;
+		s10 = s00+ny;
+		for (j = 2; j<nytop-2; j += 2) {
+			/*
+			 * ------------------    y
+			 * | hmp |    | hpp |    |
+			 * ------------------    |
+			 * |     | h0 |     |    |
+			 * ------------------    -------x
+			 * | hmm |    | hpm |
+			 * ------------------
+			 */
+			hmm = a[s00-ny2-2];
+			hpm = a[s00+ny2-2];
+			hmp = a[s00-ny2+2];
+			hpp = a[s00+ny2+2];
+			h0  = a[s00];
+			/*
+			 * diff = 64 * hc value that would match h0 in neighboring zones
+			 */
+			diff = hpp + hmm - hmp - hpm;
+			/*
+			 * 2 times x,y slopes in this zone
+			 */
+			hx2 = a[s10  ]<<1;
+			hy2 = a[s00+1]<<1;
+			/*
+			 * monotonicity constraints on diff
+			 */
+			m1 = min(max(hpp-h0,0)-hx2-hy2, max(h0-hpm,0)+hx2-hy2);
+			m2 = min(max(h0-hmp,0)-hx2+hy2, max(hmm-h0,0)+hx2+hy2);
+			dmax = min(m1,m2) << 4;
+			m1 = max(min(hpp-h0,0)-hx2-hy2, min(h0-hpm,0)+hx2-hy2);
+			m2 = max(min(h0-hmp,0)-hx2+hy2, min(hmm-h0,0)+hx2+hy2);
+			dmin = max(m1,m2) << 4;
+			/*
+			 * if monotonicity would set slope = 0 then don't change hc.
+			 * note dmax>=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<nxtop-2; i += 2) {
+		s00 = ny*i;				/* s00 is index of a[i,j]	*/
+		s10 = s00+ny;			/* s10 is index of a[i+1,j]	*/
+		for (j = 0; j<nytop; j += 2) {
+			/*
+			 * hp is h0 (mean value) in next x zone, hm is h0 in previous x zone
+			 */
+			hm = a[s00-ny2];
+			h0 = a[s00];
+			hp = a[s00+ny2];
+			/*
+			 * diff = 8 * hx slope that would match h0 in neighboring zones
+			 */
+			diff = hp-hm;
+			/*
+			 * monotonicity constraints on diff
+			 */
+			dmax = max( min( (hp-h0), (h0-hm) ), 0 ) << 2;
+			dmin = min( max( (hp-h0), (h0-hm) ), 0 ) << 2;
+			/*
+			 * if monotonicity would set slope = 0 then don't change hx.
+			 * note dmax>=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<nxtop; i += 2) {
+		s00 = ny*i+2;
+		s10 = s00+ny;
+		for (j = 2; j<nytop-2; j += 2) {
+			hm = a[s00-2];
+			h0 = a[s00];
+			hp = a[s00+2];
+			diff = hp-hm;
+			dmax = max( min( (hp-h0), (h0-hm) ), 0 ) << 2;
+			dmin = min( max( (hp-h0), (h0-hm) ), 0 ) << 2;
+			if (dmin < dmax) {
+				diff = max( min(diff, dmax), dmin);
+				s = diff-(a[s00+1]<<3);
+				s = (s>=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<nxtop-2; i += 2) {
+		s00 = ny*i+2;
+		s10 = s00+ny;
+		for (j = 2; j<nytop-2; j += 2) {
+			/*
+			 * ------------------    y
+			 * | hmp |    | hpp |    |
+			 * ------------------    |
+			 * |     | h0 |     |    |
+			 * ------------------    -------x
+			 * | hmm |    | hpm |
+			 * ------------------
+			 */
+			hmm = a[s00-ny2-2];
+			hpm = a[s00+ny2-2];
+			hmp = a[s00-ny2+2];
+			hpp = a[s00+ny2+2];
+			h0  = a[s00];
+			/*
+			 * diff = 64 * hc value that would match h0 in neighboring zones
+			 */
+			diff = hpp + hmm - hmp - hpm;
+			/*
+			 * 2 times x,y slopes in this zone
+			 */
+			hx2 = a[s10  ]<<1;
+			hy2 = a[s00+1]<<1;
+			/*
+			 * monotonicity constraints on diff
+			 */
+			m1 = min(max(hpp-h0,0)-hx2-hy2, max(h0-hpm,0)+hx2-hy2);
+			m2 = min(max(h0-hmp,0)-hx2+hy2, max(hmm-h0,0)+hx2+hy2);
+			dmax = min(m1,m2) << 4;
+			m1 = max(min(hpp-h0,0)-hx2-hy2, min(h0-hpm,0)+hx2-hy2);
+			m2 = max(min(h0-hmp,0)-hx2+hy2, min(hmm-h0,0)+hx2+hy2);
+			dmin = max(m1,m2) << 4;
+			/*
+			 * if monotonicity would set slope = 0 then don't change hc.
+			 * note dmax>=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 nel, 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	*/
+	
+	nel = (*nx) * (*ny);
+
+	/* 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 nel, 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	*/
+	
+	nel = (*nx) * (*ny);
+
+	/* 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; i<nel; i++) a[i] = 0;
+	/*
+	 * Initialize bit input
+	 */
+	start_inputing_bits();
+	/*
+	 * read bit planes for each quadrant
+	 */
+	stat = qtree_decode(infile, &a[0],          ny, nx2,  ny2,  nbitplanes[0]);
+        if (stat) return(stat);
+	
+	stat = qtree_decode(infile, &a[ny2],        ny, nx2,  ny/2, nbitplanes[1]);
+        if (stat) return(stat);
+	
+	stat = qtree_decode(infile, &a[ny*nx2],     ny, nx/2, ny2,  nbitplanes[1]);
+        if (stat) return(stat);
+	
+	stat = qtree_decode(infile, &a[ny*nx2+ny2], ny, nx/2, ny/2, nbitplanes[2]);
+        if (stat) return(stat);
+	
+	/*
+	 * make sure there is an EOF symbol (nybble=0) at end
+	 */
+	if (input_nybble(infile) != 0) {
+		ffpmsg("dodecode: bad bit plane values");
+		return(DATA_DECOMPRESSION_ERR);
+	}
+	/*
+	 * now get the sign bits
+	 * Re-initialize bit input
+	 */
+	start_inputing_bits();
+	for (i=0; i<nel; i++) {
+		if (a[i]) {
+			/* tried putting the input_bit code in-line here, instead of */
+			/* calling the function, but it made no difference in the speed */
+			if (input_bit(infile)) a[i] = -a[i];
+		}
+	}
+	return(0);
+}
+/*  ############################################################################  */
+static int
+dodecode64(unsigned char *infile, LONGLONG a[], int nx, int ny, unsigned char nbitplanes[3])
+
+/* LONGLONG 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; i<nel; i++) a[i] = 0;
+	/*
+	 * Initialize bit input
+	 */
+	start_inputing_bits();
+	/*
+	 * read bit planes for each quadrant
+	 */
+	stat = qtree_decode64(infile, &a[0],          ny, nx2,  ny2,  nbitplanes[0]);
+        if (stat) return(stat);
+	
+	stat = qtree_decode64(infile, &a[ny2],        ny, nx2,  ny/2, nbitplanes[1]);
+        if (stat) return(stat);
+	
+	stat = qtree_decode64(infile, &a[ny*nx2],     ny, nx/2, ny2,  nbitplanes[1]);
+        if (stat) return(stat);
+	
+	stat = qtree_decode64(infile, &a[ny*nx2+ny2], ny, nx/2, ny/2, nbitplanes[2]);
+        if (stat) return(stat);
+	
+	/*
+	 * make sure there is an EOF symbol (nybble=0) at end
+	 */
+	if (input_nybble(infile) != 0) {
+		ffpmsg("dodecode64: bad bit plane values");
+		return(DATA_DECOMPRESSION_ERR);
+	}
+	/*
+	 * now get the sign bits
+	 * Re-initialize bit input
+	 */
+	start_inputing_bits();
+	for (i=0; i<nel; i++) {
+		if (a[i]) {
+			if (input_bit(infile) != 0) a[i] = -a[i];
+		}
+	}
+	return(0);
+}
+
+/*  ############################################################################  */
+/*  ############################################################################  */
+/* Copyright (c) 1993 Association of Universities for Research 
+ * in Astronomy. All rights reserved. Produced under National   
+ * Aeronautics and Space Administration Contract No. NAS5-26555.
+ */
+/* qtree_decode.c	Read stream of codes from infile and construct bit planes
+ *					in quadrant of 2-D array using binary quadtree coding
+ *
+ * Programmer: R. White		Date: 7 May 1991
+ */
+
+/*  ############################################################################  */
+static int
+qtree_decode(unsigned char *infile, int a[], int n, int nqx, int nqy, int nbitplanes)
+
+/*
+char *infile;
+int 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<<log2n)) {
+		log2n += 1;
+	}
+	/*
+	 * allocate scratch array for working space
+	 */
+	nqx2=(nqx+1)/2;
+	nqy2=(nqy+1)/2;
+	scratch = (unsigned char *) malloc(nqx2*nqy2);
+	if (scratch == (unsigned char *) NULL) {
+		ffpmsg("qtree_decode: insufficient memory");
+		return(DATA_DECOMPRESSION_ERR);
+	}
+	/*
+	 * now decode each bit plane, starting at the top
+	 * A is assumed to be initialized to zero
+	 */
+	for (bit = nbitplanes-1; bit >= 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<<log2n;
+			for (k = 1; k<log2n; k++) {
+				/*
+				 * this somewhat cryptic code generates the sequence
+				 * n[k-1] = (n[k]+1)/2 where n[log2n]=nqx or nqy
+				 */
+				c = c>>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<<log2n)) {
+		log2n += 1;
+	}
+	/*
+	 * allocate scratch array for working space
+	 */
+	nqx2=(nqx+1)/2;
+	nqy2=(nqy+1)/2;
+	scratch = (unsigned char *) malloc(nqx2*nqy2);
+	if (scratch == (unsigned char *) NULL) {
+		ffpmsg("qtree_decode64: insufficient memory");
+		return(DATA_DECOMPRESSION_ERR);
+	}
+	/*
+	 * now decode each bit plane, starting at the top
+	 * A is assumed to be initialized to zero
+	 */
+	for (bit = nbitplanes-1; bit >= 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<<log2n;
+			for (k = 1; k<log2n; k++) {
+				/*
+				 * this somewhat cryptic code generates the sequence
+				 * n[k-1] = (n[k]+1)/2 where n[log2n]=nqx or nqy
+				 */
+				c = c>>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<nx-1; i += 2) {
+
+  /* Note:
+     Unlike the case in qtree_bitins, this code runs faster on a 32-bit linux
+     machine using the s10 intermediate variable, rather that using s00+n. 
+     Go figure!
+  */
+		s00 = n*i;				/* s00 is index of b[i,j]	*/
+		s10 = s00+n;				/* s10 is index of b[i+1,j]	*/
+
+		for (j = 0; j<ny-1; j += 2) {
+
+		    switch (b[s00]) {
+		    case(0):
+			b[s10+1] = 0;
+			b[s10  ] = 0;
+			b[s00+1] = 0;
+			b[s00  ] = 0;
+
+			break;
+		    case(1):
+			b[s10+1] = 1;
+			b[s10  ] = 0;
+			b[s00+1] = 0;
+			b[s00  ] = 0;
+
+			break;
+		    case(2):
+			b[s10+1] = 0;
+			b[s10  ] = 1;
+			b[s00+1] = 0;
+			b[s00  ] = 0;
+
+			break;
+		    case(3):
+			b[s10+1] = 1;
+			b[s10  ] = 1;
+			b[s00+1] = 0;
+			b[s00  ] = 0;
+
+			break;
+		    case(4):
+			b[s10+1] = 0;
+			b[s10  ] = 0;
+			b[s00+1] = 1;
+			b[s00  ] = 0;
+
+			break;
+		    case(5):
+			b[s10+1] = 1;
+			b[s10  ] = 0;
+			b[s00+1] = 1;
+			b[s00  ] = 0;
+
+			break;
+		    case(6):
+			b[s10+1] = 0;
+			b[s10  ] = 1;
+			b[s00+1] = 1;
+			b[s00  ] = 0;
+
+			break;
+		    case(7):
+			b[s10+1] = 1;
+			b[s10  ] = 1;
+			b[s00+1] = 1;
+			b[s00  ] = 0;
+
+			break;
+		    case(8):
+			b[s10+1] = 0;
+			b[s10  ] = 0;
+			b[s00+1] = 0;
+			b[s00  ] = 1;
+
+			break;
+		    case(9):
+			b[s10+1] = 1;
+			b[s10  ] = 0;
+			b[s00+1] = 0;
+			b[s00  ] = 1;
+			break;
+		    case(10):
+			b[s10+1] = 0;
+			b[s10  ] = 1;
+			b[s00+1] = 0;
+			b[s00  ] = 1;
+
+			break;
+		    case(11):
+			b[s10+1] = 1;
+			b[s10  ] = 1;
+			b[s00+1] = 0;
+			b[s00  ] = 1;
+
+			break;
+		    case(12):
+			b[s10+1] = 0;
+			b[s10  ] = 0;
+			b[s00+1] = 1;
+			b[s00  ] = 1;
+
+			break;
+		    case(13):
+			b[s10+1] = 1;
+			b[s10  ] = 0;
+			b[s00+1] = 1;
+			b[s00  ] = 1;
+
+			break;
+		    case(14):
+			b[s10+1] = 0;
+			b[s10  ] = 1;
+			b[s00+1] = 1;
+			b[s00  ] = 1;
+
+			break;
+		    case(15):
+			b[s10+1] = 1;
+			b[s10  ] = 1;
+			b[s00+1] = 1;
+			b[s00  ] = 1;
+
+			break;
+		    }
+/*
+			b[s10+1] =  b[s00]     & 1;
+			b[s10  ] = (b[s00]>>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<ny-1; j += 2) {
+                        /* not worth converting this to use 16 case statements */
+			b[s00+1] = (b[s00]>>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<nx-1; i += 2) {
+		s00 = n*i;				/* s00 is index of b[i,j]	*/
+
+  /* Note:
+     this code appears to run very slightly faster on a 32-bit linux
+     machine using s00+n rather than the s10 intermediate variable
+  */
+  /*		s10 = s00+n;	*/			/* s10 is index of b[i+1,j]	*/
+		for (j = 0; j<ny-1; j += 2) {
+
+		    switch (a[k]) {
+		    case(0):
+			break;
+		    case(1):
+			b[s00+n+1] |= plane_val;
+			break;
+		    case(2):
+			b[s00+n  ] |= plane_val;
+			break;
+		    case(3):
+			b[s00+n+1] |= plane_val;
+			b[s00+n  ] |= plane_val;
+			break;
+		    case(4):
+			b[s00+1] |= plane_val;
+			break;
+		    case(5):
+			b[s00+n+1] |= plane_val;
+			b[s00+1] |= plane_val;
+			break;
+		    case(6):
+			b[s00+n  ] |= plane_val;
+			b[s00+1] |= plane_val;
+			break;
+		    case(7):
+			b[s00+n+1] |= plane_val;
+			b[s00+n  ] |= plane_val;
+			b[s00+1] |= plane_val;
+			break;
+		    case(8):
+			b[s00  ] |= plane_val;
+			break;
+		    case(9):
+			b[s00+n+1] |= plane_val;
+			b[s00  ] |= plane_val;
+			break;
+		    case(10):
+			b[s00+n  ] |= plane_val;
+			b[s00  ] |= plane_val;
+			break;
+		    case(11):
+			b[s00+n+1] |= plane_val;
+			b[s00+n  ] |= plane_val;
+			b[s00  ] |= plane_val;
+			break;
+		    case(12):
+			b[s00+1] |= plane_val;
+			b[s00  ] |= plane_val;
+			break;
+		    case(13):
+			b[s00+n+1] |= plane_val;
+			b[s00+1] |= plane_val;
+			b[s00  ] |= plane_val;
+			break;
+		    case(14):
+			b[s00+n  ] |= plane_val;
+			b[s00+1] |= plane_val;
+			b[s00  ] |= plane_val;
+			break;
+		    case(15):
+			b[s00+n+1] |= plane_val;
+			b[s00+n  ] |= plane_val;
+			b[s00+1] |= plane_val;
+			b[s00  ] |= plane_val;
+			break;
+		    }
+
+/*
+			b[s10+1] |= ( a[k]     & 1) << bit;
+			b[s10  ] |= ((a[k]>>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<ny-1; j += 2) {
+
+		    switch (a[k]) {
+		    case(0):
+			break;
+		    case(1):
+			break;
+		    case(2):
+			break;
+		    case(3):
+			break;
+		    case(4):
+			b[s00+1] |= plane_val;
+			break;
+		    case(5):
+			b[s00+1] |= plane_val;
+			break;
+		    case(6):
+			b[s00+1] |= plane_val;
+			break;
+		    case(7):
+			b[s00+1] |= plane_val;
+			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+1] |= plane_val;
+			b[s00  ] |= plane_val;
+			break;
+		    case(13):
+			b[s00+1] |= plane_val;
+			b[s00  ] |= plane_val;
+			break;
+		    case(14):
+			b[s00+1] |= plane_val;
+			b[s00  ] |= plane_val;
+			break;
+		    case(15):
+			b[s00+1] |= plane_val;
+			b[s00  ] |= plane_val;
+			break;
+		    }
+
+/*
+			b[s00+1] |= ((a[k]>>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;
+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<nx-1; i += 2) {
+		s00 = n*i;					/* s00 is index of b[i,j]		*/
+
+  /* Note:
+     this code appears to run very slightly faster on a 32-bit linux
+     machine using s00+n rather than the s10 intermediate variable
+  */
+  /*		s10 = s00+n;	*/			/* s10 is index of b[i+1,j]	*/
+		for (j = 0; j<ny-1; j += 2) {
+
+		    switch (a[k]) {
+		    case(0):
+			break;
+		    case(1):
+			b[s00+n+1] |= plane_val;
+			break;
+		    case(2):
+			b[s00+n  ] |= plane_val;
+			break;
+		    case(3):
+			b[s00+n+1] |= plane_val;
+			b[s00+n  ] |= plane_val;
+			break;
+		    case(4):
+			b[s00+1] |= plane_val;
+			break;
+		    case(5):
+			b[s00+n+1] |= plane_val;
+			b[s00+1] |= plane_val;
+			break;
+		    case(6):
+			b[s00+n  ] |= plane_val;
+			b[s00+1] |= plane_val;
+			break;
+		    case(7):
+			b[s00+n+1] |= plane_val;
+			b[s00+n  ] |= plane_val;
+			b[s00+1] |= plane_val;
+			break;
+		    case(8):
+			b[s00  ] |= plane_val;
+			break;
+		    case(9):
+			b[s00+n+1] |= plane_val;
+			b[s00  ] |= plane_val;
+			break;
+		    case(10):
+			b[s00+n  ] |= plane_val;
+			b[s00  ] |= plane_val;
+			break;
+		    case(11):
+			b[s00+n+1] |= plane_val;
+			b[s00+n  ] |= plane_val;
+			b[s00  ] |= plane_val;
+			break;
+		    case(12):
+			b[s00+1] |= plane_val;
+			b[s00  ] |= plane_val;
+			break;
+		    case(13):
+			b[s00+n+1] |= plane_val;
+			b[s00+1] |= plane_val;
+			b[s00  ] |= plane_val;
+			break;
+		    case(14):
+			b[s00+n  ] |= plane_val;
+			b[s00+1] |= plane_val;
+			b[s00  ] |= plane_val;
+			break;
+		    case(15):
+			b[s00+n+1] |= plane_val;
+			b[s00+n  ] |= plane_val;
+			b[s00+1] |= plane_val;
+			b[s00  ] |= plane_val;
+			break;
+		    }
+
+/*
+			b[s10+1] |= ((LONGLONG) ( a[k]     & 1)) << bit;
+			b[s10  ] |= ((((LONGLONG)a[k])>>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<ny-1; j += 2) {
+
+		    switch (a[k]) {
+		    case(0):
+			break;
+		    case(1):
+			break;
+		    case(2):
+			break;
+		    case(3):
+			break;
+		    case(4):
+			b[s00+1] |= plane_val;
+			break;
+		    case(5):
+			b[s00+1] |= plane_val;
+			break;
+		    case(6):
+			b[s00+1] |= plane_val;
+			break;
+		    case(7):
+			b[s00+1] |= plane_val;
+			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+1] |= plane_val;
+			b[s00  ] |= plane_val;
+			break;
+		    case(13):
+			b[s00+1] |= plane_val;
+			b[s00  ] |= plane_val;
+			break;
+		    case(14):
+			b[s00+1] |= plane_val;
+			b[s00  ] |= plane_val;
+			break;
+		    case(15):
+			b[s00+1] |= plane_val;
+			b[s00  ] |= plane_val;
+			break;
+		    }
+
+/*
+			b[s00+1] |= ((((LONGLONG)a[k])>>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<<c);
+	}
+	/*
+	 * get the next bit
+	 */
+	c = input_bit(infile) | (c<<1);
+	if (c < 13) {
+		/*
+		 * OK, 4 bits is enough
+		 */
+		switch (c) {
+			case  8 : return(3);
+			case  9 : return(5);
+			case 10 : return(10);
+			case 11 : return(12);
+			case 12 : return(15);
+		}
+	}
+	/*
+	 * get yet another bit
+	 */
+	c = input_bit(infile) | (c<<1);
+	if (c < 31) {
+		/*
+		 * OK, 5 bits is enough
+		 */
+		switch (c) {
+			case 26 : return(6);
+			case 27 : return(7);
+			case 28 : return(9);
+			case 29 : return(11);
+			case 30 : return(13);
+		}
+	}
+	/*
+	 * need the 6th bit
+	 */
+	c = input_bit(infile) | (c<<1);
+	if (c == 62) {
+		return(0);
+	} else {
+		return(14);
+	}
+}
+
+/*  ############################################################################  */
+/*  ############################################################################  */
+/* Copyright (c) 1993 Association of Universities for Research 
+ * in Astronomy. All rights reserved. Produced under National   
+ * Aeronautics and Space Administration Contract No. NAS5-26555.
+ */
+/* qread.c	Read binary data
+ *
+ * Programmer: R. White		Date: 11 March 1991
+ */
+
+static int readint(unsigned char *infile)
+{
+int a,i;
+unsigned char b[4];
+
+	/* Read integer A one byte at a time from infile.
+	 *
+	 * This is portable from Vax to Sun since it eliminates the
+	 * need for byte-swapping.
+	 *
+         *  This routine is only called to read the first 3 values
+	 *  in the compressed file, so it doesn't have to be 
+	 *  super-efficient
+	 */
+	for (i=0; i<4; i++) qread(infile,(char *) &b[i],1);
+	a = b[0];
+	for (i=1; i<4; i++) a = (a<<8) + b[i];
+	return(a);
+}
+
+/*  ############################################################################  */
+static LONGLONG readlonglong(unsigned char *infile)
+{
+int i;
+LONGLONG a;
+unsigned char b[8];
+
+	/* Read integer A one byte at a time from infile.
+	 *
+	 * This is portable from Vax to Sun since it eliminates the
+	 * need for byte-swapping.
+	 *
+         *  This routine is only called to read the first 3 values
+	 *  in the compressed file, so it doesn't have to be 
+	 *  super-efficient
+	 */
+	for (i=0; i<8; i++) qread(infile,(char *) &b[i],1);
+	a = b[0];
+	for (i=1; i<8; i++) a = (a<<8) + b[i];
+	return(a);
+}
+
+/*  ############################################################################  */
+static void qread(unsigned char *file, char buffer[], int n)
+{
+    /*
+     * read n bytes from file into buffer
+     *
+     */
+
+    memcpy(buffer, &file[nextchar], n);
+    nextchar += 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.
+ */
+
+/* BIT INPUT ROUTINES */
+
+/* THE BIT BUFFER */
+
+static int buffer2;			/* Bits waiting to be input	*/
+static int bits_to_go;			/* Number of bits still in buffer */
+
+/* INITIALIZE BIT INPUT */
+
+/*  ############################################################################  */
+static void start_inputing_bits(void)
+{
+	/*
+	 * Buffer starts out with no bits in it
+	 */
+	bits_to_go = 0;
+}
+
+/*  ############################################################################  */
+/* INPUT A BIT */
+
+static int input_bit(unsigned char *infile)
+{
+	if (bits_to_go == 0) {			/* Read the next byte if no	*/
+
+		buffer2 = infile[nextchar];
+		nextchar++;
+		
+		bits_to_go = 8;
+	}
+	/*
+	 * Return the next bit
+	 */
+	bits_to_go -= 1;
+	return((buffer2>>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<<n)-1) ); */
+	return( (buffer2>>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 ); 
+}
diff --git a/cextern/cfitsio/fitscore.c b/cextern/cfitsio/fitscore.c
new file mode 100644
index 0000000..cf82614
--- /dev/null
+++ b/cextern/cfitsio/fitscore.c
@@ -0,0 +1,9242 @@
+/*  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 <string.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <math.h>
+#include <ctype.h>
+#include <errno.h>
+/* stddef.h is apparently needed to define size_t with some compilers ?? */
+#include <stddef.h>
+#include <locale.h>
+#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.30;
+
+/*       11 Apr 2012
+
+   Previous releases:
+      *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[81], 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  */
+                    sprintf(msg,
+                       "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  */
+            sprintf(msg, "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[81];
+
+    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)
+        {
+            sprintf(msg, 
+           "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], *cptr;
+    int tstatus = -1, nblank = 0;
+
+    if (*status > 0)
+        return(*status);
+
+    *tmpname = '\0';
+    *card = '\0';
+
+    while(*(keyname + nblank) == ' ')  /* skip leading blanks in the name */
+        nblank++;
+
+    strncat(tmpname, keyname + nblank, FLEN_KEYWORD - 1);
+
+    len = strlen(value);        
+    namelen = strlen(tmpname);
+
+    if (namelen)
+    {
+        cptr = tmpname + namelen - 1;
+
+        while(*cptr == ' ')  /* skip trailing blanks */
+        {
+            *cptr = '\0';
+            cptr--;
+        }
+
+        namelen = cptr - tmpname + 1;
+    }
+    
+    if (namelen <= 8  && (fftkey(keyname, &tstatus) <= 0) )
+    {
+        /* a normal 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
+    {
+        /* use the ESO HIERARCH convention for longer keyword names */
+
+        /* 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);
+        }
+
+        /* Don't repeat HIERARCH if the keyword already contains it */
+        if (FSTRNCMP(tmpname, "HIERARCH ", 9) && 
+            FSTRNCMP(tmpname, "hierarch ", 9))
+            strcat(card, "HIERARCH ");
+        else
+            namelen -= 9;  /* deleted the string 'HIERARCH ' */
+
+        strcat(card, tmpname);
+
+        if (namelen + 12 + len > 80) {
+            /* save 1 char by not putting a space before the equals sign */
+            strcat(card, "= ");
+            namelen += 11;
+        } else {
+            strcat(card, " = ");
+            namelen += 12;
+        }
+    }
+
+    if (len > 0)
+    {
+        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) */
+        }
+      }
+    }
+    return(*status);
+}
+/*--------------------------------------------------------------------------*/
+int ffmkey(fitsfile *fptr,    /* I - FITS file pointer  */
+           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;
+
+    /* 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] = ' ';
+
+    for (ii=0; ii < 8; 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".
+*/
+{
+    char suffix[16];
+    size_t rootlen;
+
+    keyname[0] = '\0';            /* initialize output name to null */
+    rootlen = strlen(keyroot);
+
+    if (rootlen == 0 || rootlen > 7 || value < 0 )
+       return(*status = 206);
+
+    sprintf(suffix, "%d", value); /* construct keyword suffix */
+
+    if ( strlen(suffix) + rootlen > 8)
+       return(*status = 206);
+
+    strcpy(keyname, keyroot);   /* copy root string to name string */
+    strcat(keyname, suffix);    /* append suffix to the root */
+    return(*status);
+}
+/*--------------------------------------------------------------------------*/
+int ffnkey(int value,       /* I - index number to be appended to root name */
+           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);
+
+    sprintf(keyname, "%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, "        ", 8) == 0 ||
+        FSTRNCMP(&card[8],      "= ", 2) != 0  ) /* no '= ' in cols 9-10 */
+    {
+        /*  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
+    {
+        valpos = 10;  /* starting position of the value field */
+    }
+
+    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, mval, lval;
+    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
+    {
+        sprintf(message,
+                "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;
+        sprintf(message,"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
+    {
+        sprintf(message,
+        "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
+    {
+        sprintf(message,
+        "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];
+    static int startcol;
+    int tstatus, ii, founde, foundw, match, exact, unique;
+    long ivalue;
+    tcolumn *colptr;
+
+    if (*status <= 0)
+    {
+        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 += (startcol);      /* offset to starting column */
+
+    founde = FALSE;   /* initialize 'found exact match' flag */
+    foundw = FALSE;   /* initialize 'found wildcard match' flag */
+    unique = FALSE;
+
+    for (ii = 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 */
+               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;
+               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)
+            {
+              sprintf(errmsg, "ffgcnn could not find column: %.45s", templt);
+              ffpmsg(errmsg);
+            }
+        }
+    }
+    
+    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);
+      *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;
+        
+      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;
+    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)->tiledata) {
+	       free((fptr->Fptr)->tiledata);
+	       (fptr->Fptr)->tiledata = 0;
+	       (fptr->Fptr)->tilerow = 0;
+	       (fptr->Fptr)->tiledatasize = 0;
+	       (fptr->Fptr)->tiletype = 0;
+        }
+
+        if ((fptr->Fptr)->tilenullarray) {
+	       free((fptr->Fptr)->tilenullarray);
+	       (fptr->Fptr)->tilenullarray = 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 */
+
+        /* free the tile-compressed image cache, if it exists */
+        if ((fptr->Fptr)->tiledata) {
+	       free((fptr->Fptr)->tiledata);
+	       (fptr->Fptr)->tiledata = 0;
+	       (fptr->Fptr)->tilerow = 0;
+	       (fptr->Fptr)->tiledatasize = 0;
+	       (fptr->Fptr)->tiletype = 0;
+        }
+
+        if ((fptr->Fptr)->tilenullarray) {
+	       free((fptr->Fptr)->tilenullarray);
+	       (fptr->Fptr)->tilenullarray = 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;
+    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[81];
+
+    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).");
+       sprintf(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)->tiledata) {
+	       free((fptr->Fptr)->tiledata);
+	       (fptr->Fptr)->tiledata = 0;
+	       (fptr->Fptr)->tilerow = 0;
+	       (fptr->Fptr)->tiledatasize = 0;
+	       (fptr->Fptr)->tiletype = 0;
+     }
+
+     if ((fptr->Fptr)->tilenullarray) {
+	       free((fptr->Fptr)->tilenullarray);
+	       (fptr->Fptr)->tilenullarray = 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 */
+            sprintf(message,"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 */
+            sprintf(message,"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 */
+            sprintf(message,"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 )
+        {
+            sprintf(message,"Column %d is too wide to fit in table (ffainit)",
+            ii+1);
+            ffpmsg(message);
+            sprintf(message, " 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;
+    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)->tiledata) {
+	       free((fptr->Fptr)->tiledata);
+	       (fptr->Fptr)->tiledata = 0;
+	       (fptr->Fptr)->tilerow = 0;
+	       (fptr->Fptr)->tiledatasize = 0;
+	       (fptr->Fptr)->tiletype = 0;
+    }
+
+    if ((fptr->Fptr)->tilenullarray) {
+	       free((fptr->Fptr)->tilenullarray);
+	       (fptr->Fptr)->tilenullarray = 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 */
+            sprintf(message,"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 +
+         ( (rowlen * nrows + pcount + 2879) / 2880 * 2880 );
+
+    /* determine the byte offset to the beginning of each column */
+    ffgtbc(fptr, &totalwidth, status);
+
+    if (totalwidth != rowlen)
+    {
+        sprintf(message,
+        "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 {
+		sprintf(message,
+		"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)
+        {
+            sprintf(message,
+            "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)
+        {
+            sprintf(message,
+            "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)
+        {
+            sprintf(message,
+            "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) 
+            {
+                sprintf(message,
+                "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) 
+        {
+            sprintf(message,
+            "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[81];
+    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 */
+        {
+          sprintf(message, "Image group number is less than 1: %.0f",
+                (double) firstrow);
+          ffpmsg(message);
+          return(*status = BAD_ROW_NUM);
+        }
+        else
+        {
+          sprintf(message, "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)
+    {
+        sprintf(message, "Starting element number less than 1: %ld",
+               (long) firstelem);
+        ffpmsg(message);
+        return(*status = BAD_ELEM_NUM);
+    }
+    else if (nelem < 0)
+    {
+        sprintf(message, "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)
+    {
+        sprintf(message, "Specified column number is out of range: %d",
+                colnum);
+        ffpmsg(message);
+        sprintf(message, "  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) {
+            sprintf(message,
+        "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)
+        {
+            sprintf(message,
+        "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)
+                    {
+                       sprintf(message,
+                       "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)
+              {
+                sprintf(message, 
+                  "Attempted to read from group %ld of the HDU,", (long) firstrow);
+                ffpmsg(message);
+
+                sprintf(message, 
+                  "however the HDU only contains %ld group(s).",
+                   (long) ((fptr->Fptr)->numrows) );
+                ffpmsg(message);
+              }
+              else
+              {
+                ffpmsg("Attempt to read past end of array:");
+                sprintf(message, 
+                  "  Image has  %ld elements;", (long) *repeat);
+                ffpmsg(message);
+
+                sprintf(message, 
+                "  Tried to read %ld elements starting at element %ld.",
+                (long) nelem, (long) firstelem);
+                ffpmsg(message);
+              }
+            }
+            else
+            {
+              ffpmsg("Attempt to read past end of table:");
+              sprintf(message, 
+                "  Table has %.0f rows with %.0f elements per row;",
+                    (double) ((fptr->Fptr)->numrows), (double) *repeat);
+              ffpmsg(message);
+
+              sprintf(message, 
+              "  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.
+          */           
+            *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)
+            {
+                sprintf(message,
+                "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 */
+                {
+                  sprintf(message,
+       "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");
+            sprintf(message, 
+                "  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)
+        {
+            sprintf(message, 
+         "Starting element to read in variable length column is too large: %ld",
+                    (long) firstelem);
+            ffpmsg(message);
+            sprintf(message, 
+         "  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[81];
+
+    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 )
+    {
+        sprintf(message,"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 */
+                sprintf(message,
+                "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[81];
+    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) )
+    {
+        sprintf(message,"Failed to create temporary file for the heap");
+        ffpmsg(message);
+        return(*status);
+    }
+    if ( ffcopy(fptr, tptr, 0, status) )
+    {
+        sprintf(message,"Failed to create copy of the heap");
+        ffpmsg(message);
+        ffclos(tptr, status);
+        return(*status);
+    }
+
+    buffer = (char *) malloc(buffsize);  /* allocate initial buffer */
+    if (!buffer)
+    {
+        sprintf(message,"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 */
+                {
+                  sprintf(message,
+       "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 stdriver;
+
+    /* 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)->tiledata) {
+	       free((fptr->Fptr)->tiledata);
+	       (fptr->Fptr)->tiledata = 0;
+	       (fptr->Fptr)->tilerow = 0;
+	       (fptr->Fptr)->tiledatasize = 0;
+	       (fptr->Fptr)->tiletype = 0;
+            }
+
+            if ((fptr->Fptr)->tilenullarray) {
+	       free((fptr->Fptr)->tilenullarray);
+	       (fptr->Fptr)->tilenullarray = 0;
+            }
+        }
+    }
+
+    if (*status > 0 && *status != NO_CLOSE_ERROR)
+    {
+        sprintf(message,
+        "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)
+      {
+        sprintf(message,
+        "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) */
+
+          sprintf(lenval, "(%.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 )          */
+
+              sprintf(valstring, "%.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<nblank;i++) {
+      ffgbyt(fptr,80,rec,status);
+      if( !strncmp(rec, "END     ", 8) ) {
+         if( gotend ) {
+            /*   There is a duplicate END record   */
+            *status=BAD_HEADER_FILL;
+            ffpmsg("Warning: Header fill area contains duplicate END card:");
+         }
+         gotend=TRUE;
+         if( strncmp( rec+8, blanks+8, 72) ) {
+            /*   END keyword has extra characters   */
+            *status=END_JUNK;
+            ffpmsg(
+            "Warning: END keyword contains extraneous non-blank characters:");
+         }
+      } else if( gotend ) {
+         if( strncmp( rec, blanks, 80 ) ) {
+            /*   The fill area contains extraneous characters   */
+            *status=BAD_HEADER_FILL;
+            ffpmsg(
+         "Warning: Header fill area contains extraneous non-blank characters:");
+         }
+      }
+
+      if( *status > 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;i<nfill;i++) {
+      if( chbuff[i] != chfill ) {
+         *status=BAD_DATA_FILL;
+         if( (fptr->Fptr)->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_offset = (fptr->Fptr)->request_dither_offset;
+    }
+
+    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) */
+
+                sprintf(message,
+                "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 experimental 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
+
+   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 (*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(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 */
+    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(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(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(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(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(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(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(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(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(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 = 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(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(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] != '\'')
+    {
+        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(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;
+
+    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;   
+    }
+
+    if (errno == ERANGE)
+    {
+        strcpy(msg,"Error in ffc2rr converting string to float: ");
+        strncat(msg,cval,30);
+        ffpmsg(msg);
+
+        *status = NUM_OVERFLOW;
+        errno = 0;
+    }
+
+    return(*status);
+}
+/*--------------------------------------------------------------------------*/
+int ffc2dd(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;
+
+    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;   
+    }
+
+    if (errno == ERANGE)
+    {
+        strcpy(msg,"Error in ffc2dd converting string to double: ");
+        strncat(msg,cval,30);
+        ffpmsg(msg);
+
+        *status = NUM_OVERFLOW;
+        errno = 0;
+    }
+
+    return(*status);
+}
diff --git a/cextern/cfitsio/fitsio.h b/cextern/cfitsio/fitsio.h
new file mode 100644
index 0000000..9425630
--- /dev/null
+++ b/cextern/cfitsio/fitsio.h
@@ -0,0 +1,1930 @@
+/*  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.30
+#define CFITSIO_MINOR 30
+#define CFITSIO_MAJOR 3
+
+#include <stdio.h>
+
+/* 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 <sys/types.h>  /* apparently needed on debian linux systems */
+#endif                    /* to define off_t                           */
+
+#include <stdlib.h>  /* apparently needed to define size_t with gcc 2.8.1 */
+#include <limits.h>  /* 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 the 2nd test, below,         */
+/*  i.e, "(defined(linux) && defined(__off_t_defined))" */
+#if defined(_OFF_T) || (defined(linux) && defined(__off_t_defined)) || defined(_MIPS_SZLONG) || defined(__APPLE__) || defined(_AIX)
+#    define OFF_T off_t
+#elif 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   72  /* 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 type codes */
+#define SUBTRACTIVE_DITHER_1 1
+#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  0
+
+#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 */
+    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 */
+    int request_compress_type;  /* requested image compression algorithm */
+    long request_tilesize[MAX_COMPRESS_DIM]; /* requested tiling size */
+
+    float request_hcomp_scale;    /* requested HCOMPRESS scale factor */
+    int request_hcomp_smooth;     /* requested HCOMPRESS smooth parameter */
+    int request_quantize_dither ; /* requested dithering mode when quantizing */
+                                  /* floating point images to integer */
+    int request_dither_offset;    /* starting offset into the array of random dithering */
+    int request_lossy_int_compress;  /* lossy compress integer image as if float image? */
+
+    int compressimg; /* 1 if HDU contains a compressed image, else 0 */
+    int quantize_dither;   /* floating point pixel quantization algorithm */
+    char zcmptype[12];      /* compression type string */
+    int compress_type;      /* type of compression algorithm */
+    int zbitpix;            /* FITS data type of image (BITPIX) */
+    int zndim;              /* dimension of image */
+    long znaxis[MAX_COMPRESS_DIM];  /* length of each axis */
+    long tilesize[MAX_COMPRESS_DIM]; /* size of compression tiles */
+    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: pixels/block */
+    int rice_bytepix;       /* 2nd compression parameter: bytes/pixel */
+    float quantize_level;   /* floating point quantization level */
+    int dither_offset;      /* starting offset into the array of random dithering */
+    float hcomp_scale;      /* 1st hcompress compression parameter */
+    int hcomp_smooth;       /* 2nd hcompress compression parameter */
+
+    int  tilerow;           /* row number of the uncompressed tiledata */
+    long tiledatasize;       /* length of the tile data in bytes */
+    int tiletype;           /* datatype of the tile (TINT, TSHORT, etc) */
+    void *tiledata;         /* uncompressed tile of data, for row tilerow */
+    char *tilenullarray;    /* optional array of null value flags */
+    int tileanynull;        /* anynulls in this 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;
+
+int fits_read_wcstab(fitsfile *fptr, int nwtb, wtbarr *wtb, int *status);
+
+#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 );
+fitsfile* CUnit2FITS(int unit);
+
+/*----------------  FITS file URL parsing routines -------------*/
+int fits_get_token(char **ptr, char *delimiter, char *token, int *isanumber);
+char *fits_split_names(char *list);
+int ffiurl(  char *url,  char *urltype, char *infile,
+                    char *outfile, char *extspec, char *rowfilter,
+                    char *binspec, char *colspec, int *status);
+int ffifile (char *url,  char *urltype, char *infile,
+                    char *outfile, char *extspec, char *rowfilter,
+                    char *binspec, char *colspec, char *pixfilter, int *status);
+int ffrtnm(char *url, char *rootname, int *status);
+int ffexist(const char *infile, int *exists, int *status);
+int ffexts(char *extspec, int *extnum,  char *extname, int *extvers,
+          int *hdutype, char *colname, char *rowexpress, int *status);
+int ffextn(char *url, int *extension_num, int *status);
+int ffurlt(fitsfile *fptr, char *urlType, int *status);
+int 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 ffbinr(char **binspec, char *colname, double *minin, 
+                        double *maxin, double *binsizein, char *minname,
+                        char *maxname, char *binname, int *status);
+int fits_copy_cell2image(fitsfile *fptr, fitsfile *newptr, char *colname,
+                      long rownum, int *status);
+int fits_copy_image2cell(fitsfile *fptr, fitsfile *newptr, char *colname,
+                      long rownum, int copykeyflag, int *status);
+int fits_copy_pixlist2image(fitsfile *infptr, fitsfile *outfptr, int firstkey,       /* I - first HDU record number to start with */
+           int naxis, int *colnum, int *status);
+int ffimport_file( char *filename, char **contents, int *status );
+int ffrwrg( char *rowlist, LONGLONG maxrows, int maxranges, int *numranges,
+      long *minrow, long *maxrow, int *status);
+int ffrwrgll( char *rowlist, LONGLONG maxrows, int maxranges, int *numranges,
+      LONGLONG *minrow, LONGLONG *maxrow, int *status);
+/*----------------  FITS file I/O routines -------------*/
+int fits_init_cfitsio(void);
+int 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 ffopen(fitsfile **fptr, const char *filename, int iomode, int *status);
+int ffopentest(double version, fitsfile **fptr, const char *filename, int iomode, int *status);
+
+int ffdopn(fitsfile **fptr, const char *filename, int iomode, int *status);
+int fftopn(fitsfile **fptr, const char *filename, int iomode, int *status);
+int ffiopn(fitsfile **fptr, const char *filename, int iomode, int *status);
+int ffdkopn(fitsfile **fptr, const char *filename, int iomode, int *status);
+int ffreopen(fitsfile *openfptr, fitsfile **newfptr, int *status); 
+int ffinit(  fitsfile **fptr, const char *filename, int *status);
+int ffdkinit(fitsfile **fptr, const char *filename, int *status);
+int ffimem(fitsfile **fptr,  void **buffptr,
+           size_t *buffsize, size_t deltasize,
+           void *(*mem_realloc)(void *p, size_t newsize),
+           int *status);
+int fftplt(fitsfile **fptr, const char *filename, const char *tempname,
+           int *status);
+int ffflus(fitsfile *fptr, int *status);
+int ffflsh(fitsfile *fptr, int clearbuf, int *status);
+int ffclos(fitsfile *fptr, int *status);
+int ffdelt(fitsfile *fptr, int *status);
+int ffflnm(fitsfile *fptr, char *filename, int *status);
+int ffflmd(fitsfile *fptr, int *filemode, int *status);
+int fits_delete_iraf_file(char *filename, int *status);
+
+/*---------------- utility routines -------------*/
+
+float ffvers(float *version);
+void ffupch(char *string);
+void ffgerr(int status, char *errtext);
+void ffpmsg(const char *err_message);
+void ffpmrk(void);
+int  ffgmsg(char *err_message);
+void ffcmsg(void);
+void ffcmrk(void);
+void ffrprt(FILE *stream, int status);
+void ffcmps(char *templt, char *colname, int  casesen, int *match,
+           int *exact);
+int fftkey(const char *keyword, int *status);
+int fftrec(char *card, int *status);
+int ffnchk(fitsfile *fptr, int *status);
+int ffkeyn(const char *keyroot, int value, char *keyname, int *status);
+int ffnkey(int value, char *keyroot, char *keyname, int *status);
+int ffgkcl(char *card);
+int ffdtyp(char *cval, char *dtype, int *status);
+int ffinttyp(char *cval, int *datatype, int *negative, int *status);
+int ffpsvc(char *card, char *value, char *comm, int *status);
+int ffgknm(char *card, char *name, int *length, int *status);
+int ffgthd(char *tmplt, char *card, int *hdtype, int *status);
+int 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 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 ffasfm(char *tform, int *datacode, long *width, int *decim, int *status);
+int ffbnfm(char *tform, int *datacode, long *repeat, long *width, int *status);
+int ffbnfmll(char *tform, int *datacode, LONGLONG *repeat, long *width, int *status);
+int ffgabc(int tfields, char **tform, int space, long *rowlen, long *tbcol,
+           int *status);
+int 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 ffmbyt(fitsfile *fptr, LONGLONG bytpos, int ignore_err, int *status);
+/*----------------- write single keywords --------------*/
+int ffpky(fitsfile *fptr, int datatype, const char *keyname, void *value,
+          const char *comm, int *status);
+int ffprec(fitsfile *fptr, const char *card, int *status);
+int ffpcom(fitsfile *fptr, const char *comm, int *status);
+int ffpunt(fitsfile *fptr, const char *keyname, char *unit, int *status);
+int ffphis(fitsfile *fptr, const char *history, int *status);
+int ffpdat(fitsfile *fptr, int *status);
+int ffverifydate(int year, int month, int day, int *status);
+int ffgstm(char *timestr, int *timeref, int *status);
+int ffgsdt(int *day, int *month, int *year, int *status);
+int ffdt2s(int year, int month, int day, char *datestr, int *status);
+int fftm2s(int year, int month, int day, int hour, int minute, double second,
+          int decimals, char *datestr, int *status);
+int ffs2dt(char *datestr, int *year, int *month, int *day, int *status);
+int ffs2tm(char *datestr, int *year, int *month, int *day, int *hour,
+          int *minute, double *second, int *status);
+int ffpkyu(fitsfile *fptr, const char *keyname, const char *comm, int *status);
+int ffpkys(fitsfile *fptr, const char *keyname, char *value, const char *comm,int *status);
+int ffpkls(fitsfile *fptr, const char *keyname, const char *value, const char *comm,int *status);
+int ffplsw(fitsfile *fptr, int *status);
+int ffpkyl(fitsfile *fptr, const char *keyname, int  value, const char *comm, int *status);
+int ffpkyj(fitsfile *fptr, const char *keyname, LONGLONG value, const char *comm, int *status);
+int ffpkyf(fitsfile *fptr, const char *keyname, float value, int decim, const char *comm,
+          int *status);
+int ffpkye(fitsfile *fptr, const char *keyname, float  value, int decim, const char *comm,
+          int *status);
+int ffpkyg(fitsfile *fptr, const char *keyname, double value, int decim, const char *comm,
+          int *status);
+int ffpkyd(fitsfile *fptr, const char *keyname, double value, int decim, const char *comm,
+          int *status);
+int ffpkyc(fitsfile *fptr, const char *keyname, float *value, int decim, const char *comm,
+          int *status);
+int ffpkym(fitsfile *fptr, const char *keyname, double *value, int decim, const char *comm,
+          int *status);
+int ffpkfc(fitsfile *fptr, const char *keyname, float *value, int decim, const char *comm,
+          int *status);
+int ffpkfm(fitsfile *fptr, const char *keyname, double *value, int decim, const char *comm,
+          int *status);
+int ffpkyt(fitsfile *fptr, const char *keyname, long intval, double frac, const char *comm,
+          int *status);
+int ffptdm( fitsfile *fptr, int colnum, int naxis, long naxes[], int *status);
+int ffptdmll( fitsfile *fptr, int colnum, int naxis, LONGLONG naxes[], int *status);
+
+/*----------------- write array of keywords --------------*/
+int ffpkns(fitsfile *fptr, const char *keyroot, int nstart, int nkey, char *value[],
+           char *comm[], int *status);
+int ffpknl(fitsfile *fptr, const char *keyroot, int nstart, int nkey, int *value,
+           char *comm[], int *status);
+int ffpknj(fitsfile *fptr, const char *keyroot, int nstart, int nkey, long *value,
+           char *comm[], int *status);
+int ffpknjj(fitsfile *fptr, const char *keyroot, int nstart, int nkey, LONGLONG *value,
+           char *comm[], int *status);
+int ffpknf(fitsfile *fptr, const char *keyroot, int nstart, int nkey, float *value,
+           int decim, char *comm[], int *status);
+int ffpkne(fitsfile *fptr, const char *keyroot, int nstart, int nkey, float *value,
+           int decim, char *comm[], int *status);
+int ffpkng(fitsfile *fptr, const char *keyroot, int nstart, int nkey, double *value,
+           int decim, char *comm[], int *status);
+int ffpknd(fitsfile *fptr, const char *keyroot, int nstart, int nkey, double *value,
+           int decim, char *comm[], int *status);
+int ffcpky(fitsfile *infptr,fitsfile *outfptr,int incol,int outcol,
+           char *rootname, int *status); 
+
+/*----------------- write required header keywords --------------*/
+int ffphps( fitsfile *fptr, int bitpix, int naxis, long naxes[], int *status);
+int ffphpsll( fitsfile *fptr, int bitpix, int naxis, LONGLONG naxes[], int *status);
+int ffphpr( fitsfile *fptr, int simple, int bitpix, int naxis, long naxes[],
+            LONGLONG pcount, LONGLONG gcount, int extend, int *status);
+int ffphprll( fitsfile *fptr, int simple, int bitpix, int naxis, LONGLONG naxes[],
+            LONGLONG pcount, LONGLONG gcount, int extend, int *status);
+int ffphtb(fitsfile *fptr, LONGLONG naxis1, LONGLONG naxis2, int tfields, char **ttype,
+          long *tbcol, char **tform, char **tunit, const char *extname, int *status);
+int ffphbn(fitsfile *fptr, LONGLONG naxis2, int tfields, char **ttype,
+          char **tform, char **tunit, const char *extname, LONGLONG pcount, int *status);
+int ffphext( fitsfile *fptr, const char *xtension, int bitpix, int naxis, long naxes[],
+            LONGLONG pcount, LONGLONG gcount, int *status);
+/*----------------- write template keywords --------------*/
+int ffpktp(fitsfile *fptr, const char *filename, int *status);
+
+/*------------------ get header information --------------*/
+int ffghsp(fitsfile *fptr, int *nexist, int *nmore, int *status);
+int ffghps(fitsfile *fptr, int *nexist, int *position, int *status);
+ 
+/*------------------ move position in header -------------*/
+int ffmaky(fitsfile *fptr, int nrec, int *status);
+int ffmrky(fitsfile *fptr, int nrec, int *status);
+ 
+/*------------------ read single keywords -----------------*/
+int ffgnxk(fitsfile *fptr, char **inclist, int ninc, char **exclist,
+           int nexc, char *card, int  *status);
+int ffgrec(fitsfile *fptr, int nrec,      char *card, int *status);
+int ffgcrd(fitsfile *fptr, const char *keyname, char *card, int *status);
+int ffgstr(fitsfile *fptr, const char *string, char *card, int *status);
+int ffgunt(fitsfile *fptr, const char *keyname, char *unit, int  *status);
+int ffgkyn(fitsfile *fptr, int nkey, char *keyname, char *keyval, char *comm,
+           int *status);
+int ffgkey(fitsfile *fptr, const char *keyname, char *keyval, char *comm,
+           int *status);
+ 
+int ffgky( fitsfile *fptr, int datatype, const char *keyname, void *value,
+           char *comm, int *status);
+int ffgkys(fitsfile *fptr, const char *keyname, char *value, char *comm, int *status);
+int ffgkls(fitsfile *fptr, const char *keyname, char **value, char *comm, int *status);
+int fffkls(char *value, int *status);
+int ffgkyl(fitsfile *fptr, const char *keyname, int *value, char *comm, int *status);
+int ffgkyj(fitsfile *fptr, const char *keyname, long *value, char *comm, int *status);
+int ffgkyjj(fitsfile *fptr, const char *keyname, LONGLONG *value, char *comm, int *status);
+int ffgkye(fitsfile *fptr, const char *keyname, float *value, char *comm,int *status);
+int ffgkyd(fitsfile *fptr, const char *keyname, double *value,char *comm,int *status);
+int ffgkyc(fitsfile *fptr, const char *keyname, float *value, char *comm,int *status);
+int ffgkym(fitsfile *fptr, const char *keyname, double *value,char *comm,int *status);
+int ffgkyt(fitsfile *fptr, const char *keyname, long *ivalue, double *dvalue,
+           char *comm, int *status);
+int ffgtdm(fitsfile *fptr, int colnum, int maxdim, int *naxis, long naxes[],
+           int *status);
+int ffgtdmll(fitsfile *fptr, int colnum, int maxdim, int *naxis, LONGLONG naxes[],
+           int *status);
+int ffdtdm(fitsfile *fptr, char *tdimstr, int colnum, int maxdim,
+           int *naxis, long naxes[], int *status);
+int ffdtdmll(fitsfile *fptr, char *tdimstr, int colnum, int maxdim,
+           int *naxis, LONGLONG naxes[], int *status);
+
+/*------------------ read array of keywords -----------------*/
+int ffgkns(fitsfile *fptr, const char *keyname, int nstart, int nmax, char *value[],
+           int *nfound,  int *status);
+int ffgknl(fitsfile *fptr, const char *keyname, int nstart, int nmax, int *value,
+           int *nfound, int *status);
+int ffgknj(fitsfile *fptr, const char *keyname, int nstart, int nmax, long *value,
+           int *nfound, int *status);
+int ffgknjj(fitsfile *fptr, const char *keyname, int nstart, int nmax, LONGLONG *value,
+           int *nfound, int *status);
+int ffgkne(fitsfile *fptr, const char *keyname, int nstart, int nmax, float *value,
+           int *nfound, int *status);
+int ffgknd(fitsfile *fptr, const char *keyname, int nstart, int nmax, double *value,
+           int *nfound, int *status);
+int ffh2st(fitsfile *fptr, char **header, int  *status);
+int ffhdr2str( fitsfile *fptr,  int exclude_comm, char **exclist,
+   int nexc, char **header, int *nkeys, int  *status);
+int ffcnvthdr2str( fitsfile *fptr,  int exclude_comm, char **exclist,
+   int nexc, char **header, int *nkeys, int  *status);
+
+/*----------------- read required header keywords --------------*/
+int ffghpr(fitsfile *fptr, int maxdim, int *simple, int *bitpix, int *naxis,
+          long naxes[], long *pcount, long *gcount, int *extend, int *status);
+ 
+int ffghprll(fitsfile *fptr, int maxdim, int *simple, int *bitpix, int *naxis,
+          LONGLONG naxes[], long *pcount, long *gcount, int *extend, int *status);
+
+int ffghtb(fitsfile *fptr,int maxfield, long *naxis1, long *naxis2,
+           int *tfields, char **ttype, long *tbcol, char **tform, char **tunit,
+           char *extname,  int *status);
+
+int ffghtbll(fitsfile *fptr,int maxfield, LONGLONG *naxis1, LONGLONG *naxis2,
+           int *tfields, char **ttype, LONGLONG *tbcol, char **tform, char **tunit,
+           char *extname,  int *status);
+ 
+ 
+int ffghbn(fitsfile *fptr, int maxfield, long *naxis2, int *tfields,
+           char **ttype, char **tform, char **tunit, char *extname,
+           long *pcount, int *status);
+
+int ffghbnll(fitsfile *fptr, int maxfield, LONGLONG *naxis2, int *tfields,
+           char **ttype, char **tform, char **tunit, char *extname,
+           LONGLONG *pcount, int *status);
+
+/*--------------------- update keywords ---------------*/
+int ffuky(fitsfile *fptr, int datatype, const char *keyname, void *value,
+          char *comm, int *status);
+int ffucrd(fitsfile *fptr, const char *keyname, char *card, int *status);
+int ffukyu(fitsfile *fptr, const char *keyname, char *comm, int *status);
+int ffukys(fitsfile *fptr, const char *keyname, char *value, char *comm, int *status);
+int ffukls(fitsfile *fptr, const char *keyname, char *value, char *comm, int *status);
+int ffukyl(fitsfile *fptr, const char *keyname, int value, char *comm, int *status);
+int ffukyj(fitsfile *fptr, const char *keyname, LONGLONG value, char *comm, int *status);
+int ffukyf(fitsfile *fptr, const char *keyname, float value, int decim, char *comm,
+          int *status);
+int ffukye(fitsfile *fptr, const char *keyname, float value, int decim, char *comm,
+          int *status);
+int ffukyg(fitsfile *fptr, const char *keyname, double value, int decim, char *comm,
+          int *status);
+int ffukyd(fitsfile *fptr, const char *keyname, double value, int decim, char *comm,
+          int *status);
+int ffukyc(fitsfile *fptr, const char *keyname, float *value, int decim, char *comm,
+          int *status);
+int ffukym(fitsfile *fptr, const char *keyname, double *value, int decim, char *comm,
+          int *status);
+int ffukfc(fitsfile *fptr, const char *keyname, float *value, int decim, char *comm,
+          int *status);
+int ffukfm(fitsfile *fptr, const char *keyname, double *value, int decim, char *comm,
+          int *status);
+
+/*--------------------- modify keywords ---------------*/
+int ffmrec(fitsfile *fptr, int nkey, char *card, int *status);
+int ffmcrd(fitsfile *fptr, const char *keyname, char *card, int *status);
+int ffmnam(fitsfile *fptr, const char *oldname, const char *newname, int *status);
+int ffmcom(fitsfile *fptr, const char *keyname, char *comm, int *status);
+int ffmkyu(fitsfile *fptr, const char *keyname, char *comm, int *status);
+int ffmkys(fitsfile *fptr, const char *keyname, char *value, char *comm,int *status);
+int ffmkls(fitsfile *fptr, const char *keyname, char *value, char *comm,int *status);
+int ffmkyl(fitsfile *fptr, const char *keyname, int value, char *comm, int *status);
+int ffmkyj(fitsfile *fptr, const char *keyname, LONGLONG value, char *comm, int *status);
+int ffmkyf(fitsfile *fptr, const char *keyname, float value, int decim, char *comm,
+          int *status);
+int ffmkye(fitsfile *fptr, const char *keyname, float value, int decim, char *comm,
+          int *status);
+int ffmkyg(fitsfile *fptr, const char *keyname, double value, int decim, char *comm,
+          int *status);
+int ffmkyd(fitsfile *fptr, const char *keyname, double value, int decim, char *comm,
+          int *status);
+int ffmkyc(fitsfile *fptr, const char *keyname, float *value, int decim, char *comm,
+          int *status);
+int ffmkym(fitsfile *fptr, const char *keyname, double *value, int decim, char *comm,
+          int *status);
+int ffmkfc(fitsfile *fptr, const char *keyname, float *value, int decim, char *comm,
+          int *status);
+int ffmkfm(fitsfile *fptr, const char *keyname, double *value, int decim, char *comm,
+          int *status);
+ 
+/*--------------------- insert keywords ---------------*/
+int ffirec(fitsfile *fptr, int nkey, char *card, int *status);
+int ffikey(fitsfile *fptr, char *card, int *status);
+int ffikyu(fitsfile *fptr, const char *keyname, char *comm, int *status);
+int ffikys(fitsfile *fptr, const char *keyname, char *value, char *comm,int *status);
+int ffikls(fitsfile *fptr, const char *keyname, char *value, char *comm,int *status);
+int ffikyl(fitsfile *fptr, const char *keyname, int value, char *comm, int *status);
+int ffikyj(fitsfile *fptr, const char *keyname, LONGLONG value, char *comm, int *status);
+int ffikyf(fitsfile *fptr, const char *keyname, float value, int decim, char *comm,
+          int *status);
+int ffikye(fitsfile *fptr, const char *keyname, float value, int decim, char *comm,
+          int *status);
+int ffikyg(fitsfile *fptr, const char *keyname, double value, int decim, char *comm,
+          int *status);
+int ffikyd(fitsfile *fptr, const char *keyname, double value, int decim, char *comm,
+          int *status);
+int ffikyc(fitsfile *fptr, const char *keyname, float *value, int decim, char *comm,
+          int *status);
+int ffikym(fitsfile *fptr, const char *keyname, double *value, int decim, char *comm,
+          int *status);
+int ffikfc(fitsfile *fptr, const char *keyname, float *value, int decim, char *comm,
+          int *status);
+int ffikfm(fitsfile *fptr, const char *keyname, double *value, int decim, char *comm,
+          int *status);
+
+/*--------------------- delete keywords ---------------*/
+int ffdkey(fitsfile *fptr, const char *keyname, int *status);
+int ffdstr(fitsfile *fptr, const char *string, int *status);
+int ffdrec(fitsfile *fptr, int keypos, int *status);
+ 
+/*--------------------- get HDU information -------------*/
+int ffghdn(fitsfile *fptr, int *chdunum);
+int ffghdt(fitsfile *fptr, int *exttype, int *status);
+int ffghad(fitsfile *fptr, long *headstart, long *datastart, long *dataend,
+           int *status);
+int ffghadll(fitsfile *fptr, LONGLONG *headstart, LONGLONG *datastart,
+           LONGLONG *dataend, int *status);
+int ffghof(fitsfile *fptr, OFF_T *headstart, OFF_T *datastart, OFF_T *dataend,
+           int *status);
+int ffgipr(fitsfile *fptr, int maxaxis, int *imgtype, int *naxis,
+           long *naxes, int *status);
+int ffgiprll(fitsfile *fptr, int maxaxis, int *imgtype, int *naxis,
+           LONGLONG *naxes, int *status);
+int ffgidt(fitsfile *fptr, int *imgtype, int *status);
+int ffgiet(fitsfile *fptr, int *imgtype, int *status);
+int ffgidm(fitsfile *fptr, int *naxis,  int *status);
+int ffgisz(fitsfile *fptr, int nlen, long *naxes, int *status);
+int ffgiszll(fitsfile *fptr, int nlen, LONGLONG *naxes, int *status);
+
+/*--------------------- HDU operations -------------*/
+int ffmahd(fitsfile *fptr, int hdunum, int *exttype, int *status);
+int ffmrhd(fitsfile *fptr, int hdumov, int *exttype, int *status);
+int ffmnhd(fitsfile *fptr, int exttype, char *hduname, int hduvers,
+           int *status);
+int ffthdu(fitsfile *fptr, int *nhdu, int *status);
+int ffcrhd(fitsfile *fptr, int *status);
+int ffcrim(fitsfile *fptr, int bitpix, int naxis, long *naxes, int *status);
+int ffcrimll(fitsfile *fptr, int bitpix, int naxis, LONGLONG *naxes, int *status);
+int ffcrtb(fitsfile *fptr, int tbltype, LONGLONG naxis2, int tfields, char **ttype,
+           char **tform, char **tunit, const char *extname, int *status);
+int ffiimg(fitsfile *fptr, int bitpix, int naxis, long *naxes, int *status);
+int ffiimgll(fitsfile *fptr, int bitpix, int naxis, LONGLONG *naxes, int *status);
+int ffitab(fitsfile *fptr, LONGLONG naxis1, LONGLONG naxis2, int tfields, char **ttype,
+           long *tbcol, char **tform, char **tunit, const char *extname, int *status);
+int ffibin(fitsfile *fptr, LONGLONG naxis2, int tfields, char **ttype, char **tform,
+           char **tunit, const char *extname, LONGLONG pcount, int *status);
+int ffrsim(fitsfile *fptr, int bitpix, int naxis, long *naxes, int *status);
+int ffrsimll(fitsfile *fptr, int bitpix, int naxis, LONGLONG *naxes, int *status);
+int ffdhdu(fitsfile *fptr, int *hdutype, int *status);
+int ffcopy(fitsfile *infptr, fitsfile *outfptr, int morekeys, int *status);
+int ffcpfl(fitsfile *infptr, fitsfile *outfptr, int prev, int cur, int follow,
+            int *status);
+int ffcphd(fitsfile *infptr, fitsfile *outfptr, int *status);
+int ffcpdt(fitsfile *infptr, fitsfile *outfptr, int *status);
+int ffchfl(fitsfile *fptr, int *status);
+int ffcdfl(fitsfile *fptr, int *status);
+int ffwrhdu(fitsfile *fptr, FILE *outstream, int *status);
+
+int ffrdef(fitsfile *fptr, int *status);
+int ffhdef(fitsfile *fptr, int morekeys, int *status);
+int ffpthp(fitsfile *fptr, long theap, int *status);
+ 
+int ffcsum(fitsfile *fptr, long nrec, unsigned long *sum, int *status);
+void ffesum(unsigned long sum, int complm, char *ascii);
+unsigned long ffdsum(char *ascii, int complm, unsigned long *sum);
+int ffpcks(fitsfile *fptr, int *status);
+int ffupck(fitsfile *fptr, int *status);
+int ffvcks(fitsfile *fptr, int *datastatus, int *hdustatus, int *status);
+int ffgcks(fitsfile *fptr, unsigned long *datasum, unsigned long *hdusum,
+    int *status);
+ 
+/*--------------------- define scaling or null values -------------*/
+int ffpscl(fitsfile *fptr, double scale, double zero, int *status);
+int ffpnul(fitsfile *fptr, LONGLONG nulvalue, int *status);
+int fftscl(fitsfile *fptr, int colnum, double scale, double zero, int *status);
+int fftnul(fitsfile *fptr, int colnum, LONGLONG nulvalue, int *status);
+int ffsnul(fitsfile *fptr, int colnum, char *nulstring, int *status);
+ 
+/*--------------------- get column information -------------*/
+int ffgcno(fitsfile *fptr, int casesen, char *templt, int  *colnum,
+           int *status);
+int ffgcnn(fitsfile *fptr, int casesen, char *templt, char *colname,
+           int *colnum, int *status);
+ 
+int ffgtcl(fitsfile *fptr, int colnum, int *typecode, long *repeat,
+           long *width, int *status);
+int ffgtclll(fitsfile *fptr, int colnum, int *typecode, LONGLONG *repeat,
+           LONGLONG *width, int *status);
+int ffeqty(fitsfile *fptr, int colnum, int *typecode, long *repeat,
+           long *width, int *status);
+int ffeqtyll(fitsfile *fptr, int colnum, int *typecode, LONGLONG *repeat,
+           LONGLONG *width, int *status);
+int ffgncl(fitsfile *fptr, int  *ncols, int *status);
+int ffgnrw(fitsfile *fptr, long *nrows, int *status);
+int ffgnrwll(fitsfile *fptr, LONGLONG *nrows, int *status);
+int ffgacl(fitsfile *fptr, int colnum, char *ttype, long *tbcol,
+           char *tunit, char *tform, double *tscal, double *tzero,
+           char *tnull, char *tdisp, int *status);
+int ffgbcl(fitsfile *fptr, int colnum, char *ttype, char *tunit,
+           char *dtype, long *repeat, double *tscal, double *tzero,
+           long *tnull, char *tdisp, int  *status);
+int ffgbclll(fitsfile *fptr, int colnum, char *ttype, char *tunit,
+           char *dtype, LONGLONG *repeat, double *tscal, double *tzero,
+           LONGLONG *tnull, char *tdisp, int  *status);
+int ffgrsz(fitsfile *fptr, long *nrows, int *status);
+int ffgcdw(fitsfile *fptr, int colnum, int *width, int *status);
+
+/*--------------------- read primary array or image elements -------------*/
+int ffgpxv(fitsfile *fptr, int  datatype, long *firstpix, LONGLONG nelem,
+          void *nulval, void *array, int *anynul, int *status);
+int ffgpxvll(fitsfile *fptr, int  datatype, LONGLONG *firstpix, LONGLONG nelem,
+          void *nulval, void *array, int *anynul, int *status);
+int ffgpxf(fitsfile *fptr, int  datatype, long *firstpix, LONGLONG nelem,
+           void *array, char *nullarray, int *anynul, int *status);
+int ffgpxfll(fitsfile *fptr, int  datatype, LONGLONG *firstpix, LONGLONG nelem,
+           void *array, char *nullarray, int *anynul, int *status);
+int ffgsv(fitsfile *fptr, int datatype, long *blc, long *trc, long *inc,
+          void *nulval, void *array, int *anynul, int  *status);
+
+int ffgpv(fitsfile *fptr, int  datatype, LONGLONG firstelem, LONGLONG nelem,
+          void *nulval, void *array, int *anynul, int  *status);
+int ffgpf(fitsfile *fptr, int  datatype, LONGLONG firstelem, LONGLONG nelem,
+          void *array, char *nullarray, int  *anynul, int  *status);
+int ffgpvb(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, unsigned
+           char nulval, unsigned char *array, int *anynul, int *status);
+int ffgpvsb(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, signed
+           char nulval, signed char *array, int *anynul, int *status);
+int ffgpvui(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem,
+           unsigned short nulval, unsigned short *array, int *anynul, 
+           int *status);
+int ffgpvi(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem,
+           short nulval, short *array, int *anynul, int *status);
+int ffgpvuj(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem,
+           unsigned long nulval, unsigned long *array, int *anynul, 
+           int *status);
+int ffgpvj(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem,
+           long nulval, long *array, int *anynul, int *status);
+int ffgpvjj(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem,
+           LONGLONG nulval, LONGLONG *array, int *anynul, int *status);
+int ffgpvuk(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem,
+           unsigned int nulval, unsigned int *array, int *anynul, int *status);
+int ffgpvk(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem,
+           int nulval, int *array, int *anynul, int *status);
+int ffgpve(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem,
+           float nulval, float *array, int *anynul, int *status);
+int ffgpvd(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem,
+           double nulval, double *array, int *anynul, int *status);
+ 
+int ffgpfb(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem,
+           unsigned char *array, char *nularray, int *anynul, int *status);
+int ffgpfsb(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem,
+           signed char *array, char *nularray, int *anynul, int *status);
+int ffgpfui(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem,
+           unsigned short *array, char *nularray, int *anynul, int *status);
+int ffgpfi(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem,
+           short *array, char *nularray, int *anynul, int *status);
+int ffgpfuj(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem,
+           unsigned long *array, char *nularray, int *anynul, int *status);
+int ffgpfj(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem,
+           long *array, char *nularray, int *anynul, int *status);
+int ffgpfjj(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem,
+           LONGLONG *array, char *nularray, int *anynul, int *status);
+int ffgpfuk(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem,
+           unsigned int *array, char *nularray, int *anynul, int *status);
+int ffgpfk(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem,
+           int *array, char *nularray, int *anynul, int *status);
+int ffgpfe(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem,
+           float *array, char *nularray, int *anynul, int *status);
+int ffgpfd(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem,
+           double *array, char *nularray, int *anynul, int *status);
+ 
+int ffg2db(fitsfile *fptr, long group, unsigned char nulval, LONGLONG ncols,
+           LONGLONG naxis1, LONGLONG naxis2, unsigned char *array,
+           int *anynul, int *status);
+int ffg2dsb(fitsfile *fptr, long group, signed char nulval, LONGLONG ncols,
+           LONGLONG naxis1, LONGLONG naxis2, signed char *array,
+           int *anynul, int *status);
+int ffg2dui(fitsfile *fptr, long group, unsigned short nulval, LONGLONG ncols,
+           LONGLONG naxis1, LONGLONG naxis2, unsigned short *array,
+           int *anynul, int *status);
+int ffg2di(fitsfile *fptr, long group, short nulval, LONGLONG ncols,
+           LONGLONG naxis1, LONGLONG naxis2, short *array,
+           int *anynul, int *status);
+int ffg2duj(fitsfile *fptr, long group, unsigned long nulval, LONGLONG ncols,
+           LONGLONG naxis1, LONGLONG naxis2, unsigned long *array,
+           int *anynul, int *status);
+int ffg2dj(fitsfile *fptr, long group, long nulval, LONGLONG ncols,
+           LONGLONG naxis1, LONGLONG naxis2, long *array,
+           int *anynul, int *status);
+int ffg2djj(fitsfile *fptr, long group, LONGLONG nulval, LONGLONG ncols,
+           LONGLONG naxis1, LONGLONG naxis2, LONGLONG *array,
+           int *anynul, int *status);
+int ffg2duk(fitsfile *fptr, long group, unsigned int nulval, LONGLONG ncols,
+           LONGLONG naxis1, LONGLONG naxis2, unsigned int *array,
+           int *anynul, int *status);
+int ffg2dk(fitsfile *fptr, long group, int nulval, LONGLONG ncols,
+           LONGLONG naxis1, LONGLONG naxis2, int *array,
+           int *anynul, int *status);
+int ffg2de(fitsfile *fptr, long group, float nulval, LONGLONG ncols,
+           LONGLONG naxis1, LONGLONG naxis2, float *array,
+           int *anynul, int *status);
+int ffg2dd(fitsfile *fptr, long group, double nulval, LONGLONG ncols,
+           LONGLONG naxis1, LONGLONG naxis2, double *array,
+           int *anynul, int *status);
+ 
+int 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 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 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 ffg3di(fitsfile *fptr, long group, short nulval, LONGLONG ncols,
+           LONGLONG nrows, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3,
+           short *array, int *anynul, int *status);
+int 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 ffg3dj(fitsfile *fptr, long group, long nulval, LONGLONG ncols,
+           LONGLONG nrows, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3,
+           long *array, int *anynul, int *status);
+int ffg3djj(fitsfile *fptr, long group, LONGLONG nulval, LONGLONG ncols,
+           LONGLONG nrows, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3,
+           LONGLONG *array, int *anynul, int *status);
+int 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 ffg3dk(fitsfile *fptr, long group, int nulval, LONGLONG ncols,
+           LONGLONG nrows, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3,
+           int *array, int *anynul, int *status);
+int ffg3de(fitsfile *fptr, long group, float nulval, LONGLONG ncols,
+           LONGLONG nrows, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3,
+           float *array, int *anynul, int *status);
+int ffg3dd(fitsfile *fptr, long group, double nulval, LONGLONG ncols,
+           LONGLONG nrows, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3,
+           double *array, int *anynul, int *status);
+ 
+int 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 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 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 ffgsvi(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc,
+  long *trc, long *inc, short nulval, short *array, int *anynul, int *status);
+int 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 ffgsvj(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc,
+  long *trc, long *inc, long nulval, long *array, int *anynul, int *status);
+int ffgsvjj(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc,
+  long *trc, long *inc, LONGLONG nulval, LONGLONG *array, int *anynul,
+  int *status);
+int 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 ffgsvk(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc,
+  long *trc, long *inc, int nulval, int *array, int *anynul, int *status);
+int ffgsve(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc,
+  long *trc, long *inc, float nulval, float *array, int *anynul, int *status);
+int ffgsvd(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc,
+  long *trc, long *inc, double nulval, double *array, int *anynul,
+  int *status);
+ 
+int 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 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 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 ffgsfi(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc,
+  long *trc, long *inc, short *array, char *flagval, int *anynul, int *status);
+int 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 ffgsfj(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc,
+  long  *trc, long *inc, long *array, char *flagval, int *anynul, int *status);
+int ffgsfjj(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc,
+  long  *trc, long *inc, LONGLONG *array, char *flagval, int *anynul,
+  int *status);
+int 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 ffgsfk(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc,
+  long  *trc, long *inc, int *array, char *flagval, int *anynul, int *status);
+int ffgsfe(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc,
+  long *trc, long *inc, float *array, char *flagval, int *anynul, int *status);
+int ffgsfd(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc,
+  long *trc, long *inc, double *array, char *flagval, int *anynul,
+  int *status);
+ 
+int ffggpb(fitsfile *fptr, long group, long firstelem, long nelem,
+           unsigned char *array, int *status);
+int ffggpsb(fitsfile *fptr, long group, long firstelem, long nelem,
+           signed char *array, int *status);
+int ffggpui(fitsfile *fptr, long group, long firstelem, long nelem,
+           unsigned short *array, int *status);
+int ffggpi(fitsfile *fptr, long group, long firstelem, long nelem,
+           short *array, int *status);
+int ffggpuj(fitsfile *fptr, long group, long firstelem, long nelem,
+           unsigned long *array, int *status);
+int ffggpj(fitsfile *fptr, long group, long firstelem, long nelem,
+           long *array, int *status);
+int ffggpjj(fitsfile *fptr, long group, long firstelem, long nelem,
+           LONGLONG *array, int *status);
+int ffggpuk(fitsfile *fptr, long group, long firstelem, long nelem,
+           unsigned int *array, int *status);
+int ffggpk(fitsfile *fptr, long group, long firstelem, long nelem,
+           int *array, int *status);
+int ffggpe(fitsfile *fptr, long group, long firstelem, long nelem,
+           float *array, int *status);
+int ffggpd(fitsfile *fptr, long group, long firstelem, long nelem,
+           double *array, int *status);
+ 
+/*--------------------- read column elements -------------*/
+int ffgcv( fitsfile *fptr, int datatype, int colnum, LONGLONG firstrow,
+           LONGLONG firstelem, LONGLONG nelem, void *nulval, void *array, int *anynul,
+           int  *status);
+int ffgcf( fitsfile *fptr, int datatype, int colnum, LONGLONG firstrow,
+           LONGLONG firstelem, LONGLONG nelem, void *array, char *nullarray,
+           int *anynul, int *status);
+int ffgcvs(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem,
+           LONGLONG nelem, char *nulval, char **array, int *anynul, int *status);
+int ffgcl (fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem,
+           LONGLONG nelem, char *array, int  *status);
+int ffgcvl (fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem,
+           LONGLONG nelem, char nulval, char *array, int *anynul, int  *status);
+int ffgcvb(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem,
+           LONGLONG nelem, unsigned char nulval, unsigned char *array,
+           int *anynul, int *status);
+int ffgcvsb(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem,
+           LONGLONG nelem, signed char nulval, signed char *array,
+           int *anynul, int *status);
+int ffgcvui(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem,
+           LONGLONG nelem, unsigned short nulval, unsigned short *array, 
+           int *anynul, int *status);
+int ffgcvi(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem,
+           LONGLONG nelem, short nulval, short *array, int *anynul, int *status);
+int ffgcvuj(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem,
+           LONGLONG nelem, unsigned long nulval, unsigned long *array, int *anynul,
+           int *status);
+int ffgcvj(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem,
+           LONGLONG nelem, long nulval, long *array, int *anynul, int *status);
+int ffgcvjj(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem,
+           LONGLONG nelem, LONGLONG nulval, LONGLONG *array, int *anynul,
+           int *status);
+int ffgcvuk(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem,
+           LONGLONG nelem, unsigned int nulval, unsigned int *array, int *anynul,
+           int *status);
+int ffgcvk(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem,
+           LONGLONG nelem, int nulval, int *array, int *anynul, int *status);
+int ffgcve(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem,
+           LONGLONG nelem, float nulval, float *array, int *anynul, int *status);
+int ffgcvd(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem,
+         LONGLONG nelem, double nulval, double *array, int *anynul, int *status);
+int ffgcvc(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem,
+           LONGLONG nelem, float nulval, float *array, int *anynul, int *status);
+int ffgcvm(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem,
+         LONGLONG nelem, double nulval, double *array, int *anynul, int *status);
+
+int ffgcx(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstbit,
+            LONGLONG nbits, char *larray, int *status);
+int ffgcxui(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG nrows,
+            long firstbit, int nbits, unsigned short *array, int *status);
+int ffgcxuk(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG nrows,
+            long firstbit, int nbits, unsigned int *array, int *status);
+
+int ffgcfs(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, 
+      LONGLONG nelem, char **array, char *nularray, int *anynul, int *status);
+int ffgcfl(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem,
+      LONGLONG nelem, char *array, char *nularray, int *anynul, int *status);
+int ffgcfb(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, 
+      LONGLONG nelem, unsigned char *array, char *nularray, int *anynul, int *status);
+int ffgcfsb(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem,
+      LONGLONG nelem, signed char *array, char *nularray, int *anynul, int *status);
+int ffgcfui(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem,
+      LONGLONG nelem, unsigned short *array, char *nularray, int *anynul, 
+      int *status);
+int ffgcfi(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem,
+      LONGLONG nelem, short *array, char *nularray, int *anynul, int *status);
+int ffgcfuj(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem,
+      LONGLONG nelem, unsigned long *array, char *nularray, int *anynul,
+      int *status);
+int ffgcfj(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem,
+      LONGLONG nelem, long *array, char *nularray, int *anynul, int *status);
+int ffgcfjj(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem,
+      LONGLONG nelem, LONGLONG *array, char *nularray, int *anynul, int *status);
+int ffgcfuk(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem,
+      LONGLONG nelem, unsigned int *array, char *nularray, int *anynul,
+      int *status);
+int ffgcfk(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem,
+      LONGLONG nelem, int *array, char *nularray, int *anynul, int *status);
+int ffgcfe(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem,
+      LONGLONG nelem, float *array, char *nularray, int *anynul, int *status);
+int ffgcfd(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem,
+      LONGLONG nelem, double *array, char *nularray, int *anynul, int *status);
+int ffgcfc(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem,
+      LONGLONG nelem, float *array, char *nularray, int *anynul, int *status);
+int ffgcfm(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem,
+      LONGLONG nelem, double *array, char *nularray, int *anynul, int *status);
+ 
+int ffgdes(fitsfile *fptr, int colnum, LONGLONG rownum, long *length,
+           long *heapaddr, int *status);
+int ffgdesll(fitsfile *fptr, int colnum, LONGLONG rownum, LONGLONG *length,
+           LONGLONG *heapaddr, int *status);
+int ffgdess(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG nrows, long *length,
+           long *heapaddr, int *status);
+int ffgdessll(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG nrows, LONGLONG *length,
+           LONGLONG *heapaddr, int *status);
+int ffpdes(fitsfile *fptr, int colnum, LONGLONG rownum, LONGLONG length,
+           LONGLONG heapaddr, int *status);
+int fftheap(fitsfile *fptr, LONGLONG *heapsize, LONGLONG *unused, LONGLONG *overlap,
+            int *valid, int *status);
+int ffcmph(fitsfile *fptr, int *status);
+
+int ffgtbb(fitsfile *fptr, LONGLONG firstrow, LONGLONG firstchar, LONGLONG nchars,
+           unsigned char *values, int *status);
+
+int ffgextn(fitsfile *fptr, LONGLONG offset, LONGLONG nelem, void *array, int *status);
+int ffpextn(fitsfile *fptr, LONGLONG offset, LONGLONG nelem, void *array, int *status);
+
+/*------------ write primary array or image elements -------------*/
+int ffppx(fitsfile *fptr, int datatype, long *firstpix, LONGLONG nelem,
+          void *array, int *status);
+int ffppxll(fitsfile *fptr, int datatype, LONGLONG *firstpix, LONGLONG nelem,
+          void *array, int *status);
+int ffppxn(fitsfile *fptr, int datatype, long *firstpix, LONGLONG nelem,
+          void *array, void *nulval, int *status);
+int ffppxnll(fitsfile *fptr, int datatype, LONGLONG *firstpix, LONGLONG nelem,
+          void *array, void *nulval, int *status);
+int ffppr(fitsfile *fptr, int datatype, LONGLONG  firstelem,
+           LONGLONG nelem, void *array, int *status);
+int ffpprb(fitsfile *fptr, long group, LONGLONG firstelem,
+           LONGLONG nelem, unsigned char *array, int *status);
+int ffpprsb(fitsfile *fptr, long group, LONGLONG firstelem,
+           LONGLONG nelem, signed char *array, int *status);
+int ffpprui(fitsfile *fptr, long group, LONGLONG firstelem,
+           LONGLONG nelem, unsigned short *array, int *status);
+int ffppri(fitsfile *fptr, long group, LONGLONG firstelem,
+           LONGLONG nelem, short *array, int *status);
+int ffppruj(fitsfile *fptr, long group, LONGLONG firstelem,
+           LONGLONG nelem, unsigned long *array, int *status);
+int ffpprj(fitsfile *fptr, long group, LONGLONG firstelem,
+           LONGLONG nelem, long *array, int *status);
+int ffppruk(fitsfile *fptr, long group, LONGLONG firstelem,
+           LONGLONG nelem, unsigned int *array, int *status);
+int ffpprk(fitsfile *fptr, long group, LONGLONG firstelem,
+           LONGLONG nelem, int *array, int *status);
+int ffppre(fitsfile *fptr, long group, LONGLONG firstelem,
+           LONGLONG nelem, float *array, int *status);
+int ffpprd(fitsfile *fptr, long group, LONGLONG firstelem,
+           LONGLONG nelem, double *array, int *status);
+int ffpprjj(fitsfile *fptr, long group, LONGLONG firstelem,
+           LONGLONG nelem, LONGLONG *array, int *status);
+
+int ffppru(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem,
+           int *status);
+int ffpprn(fitsfile *fptr, LONGLONG firstelem, LONGLONG nelem, int *status);
+ 
+int ffppn(fitsfile *fptr, int datatype, LONGLONG  firstelem, LONGLONG nelem,
+          void  *array, void *nulval, int  *status);
+int ffppnb(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem,
+           unsigned char *array, unsigned char nulval, int *status);
+int ffppnsb(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem,
+           signed char *array, signed char nulval, int *status);
+int ffppnui(fitsfile *fptr, long group, LONGLONG firstelem,
+           LONGLONG nelem, unsigned short *array, unsigned short nulval,
+           int *status);
+int ffppni(fitsfile *fptr, long group, LONGLONG firstelem,
+           LONGLONG nelem, short *array, short nulval, int *status);
+int ffppnj(fitsfile *fptr, long group, LONGLONG firstelem,
+           LONGLONG nelem, long *array, long nulval, int *status);
+int ffppnuj(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem,
+           unsigned long *array, unsigned long nulval, int *status);
+int ffppnuk(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem,
+           unsigned int *array, unsigned int nulval, int *status);
+int ffppnk(fitsfile *fptr, long group, LONGLONG firstelem,
+           LONGLONG nelem, int *array, int nulval, int *status);
+int ffppne(fitsfile *fptr, long group, LONGLONG firstelem,
+           LONGLONG nelem, float *array, float nulval, int *status);
+int ffppnd(fitsfile *fptr, long group, LONGLONG firstelem,
+           LONGLONG nelem, double *array, double nulval, int *status);
+int ffppnjj(fitsfile *fptr, long group, LONGLONG firstelem,
+           LONGLONG nelem, LONGLONG *array, LONGLONG nulval, int *status);
+
+int ffp2db(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG naxis1,
+           LONGLONG naxis2, unsigned char *array, int *status);
+int ffp2dsb(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG naxis1,
+           LONGLONG naxis2, signed char *array, int *status);
+int ffp2dui(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG naxis1,
+           LONGLONG naxis2, unsigned short *array, int *status);
+int ffp2di(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG naxis1,
+           LONGLONG naxis2, short *array, int *status);
+int ffp2duj(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG naxis1,
+           LONGLONG naxis2, unsigned long *array, int *status);
+int ffp2dj(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG naxis1,
+           LONGLONG naxis2, long *array, int *status);
+int ffp2duk(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG naxis1,
+           LONGLONG naxis2, unsigned int *array, int *status);
+int ffp2dk(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG naxis1,
+           LONGLONG naxis2, int *array, int *status);
+int ffp2de(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG naxis1,
+           LONGLONG naxis2, float *array, int *status);
+int ffp2dd(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG naxis1,
+           LONGLONG naxis2, double *array, int *status);
+int ffp2djj(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG naxis1,
+           LONGLONG naxis2, LONGLONG *array, int *status);
+
+int ffp3db(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1,
+           LONGLONG naxis2, LONGLONG naxis3, unsigned char *array, int *status);
+int ffp3dsb(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1,
+           LONGLONG naxis2, LONGLONG naxis3, signed char *array, int *status);
+int ffp3dui(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1,
+           LONGLONG naxis2, LONGLONG naxis3, unsigned short *array, int *status);
+int ffp3di(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1,
+           LONGLONG naxis2, LONGLONG naxis3, short *array, int *status);
+int ffp3duj(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1,
+           LONGLONG naxis2, LONGLONG naxis3, unsigned long *array, int *status);
+int ffp3dj(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1,
+           LONGLONG naxis2, LONGLONG naxis3, long *array, int *status);
+int ffp3duk(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1,
+           LONGLONG naxis2, LONGLONG naxis3, unsigned int *array, int *status);
+int ffp3dk(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1,
+           LONGLONG naxis2, LONGLONG naxis3, int *array, int *status);
+int ffp3de(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1,
+           LONGLONG naxis2, LONGLONG naxis3, float *array, int *status);
+int ffp3dd(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1,
+           LONGLONG naxis2, LONGLONG naxis3, double *array, int *status);
+int ffp3djj(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1,
+           LONGLONG naxis2, LONGLONG naxis3, LONGLONG *array, int *status);
+
+int ffpss(fitsfile *fptr, int datatype,
+           long *fpixel, long *lpixel, void *array, int *status);
+int ffpssb(fitsfile *fptr, long group, long naxis, long *naxes,
+           long *fpixel, long *lpixel, unsigned char *array, int *status);
+int ffpsssb(fitsfile *fptr, long group, long naxis, long *naxes,
+           long *fpixel, long *lpixel, signed char *array, int *status);
+int ffpssui(fitsfile *fptr, long group, long naxis, long *naxes,
+           long *fpixel, long *lpixel, unsigned short *array, int *status);
+int ffpssi(fitsfile *fptr, long group, long naxis, long *naxes,
+           long *fpixel, long *lpixel, short *array, int *status);
+int ffpssuj(fitsfile *fptr, long group, long naxis, long *naxes,
+           long *fpixel, long *lpixel, unsigned long *array, int *status);
+int ffpssj(fitsfile *fptr, long group, long naxis, long *naxes,
+           long *fpixel, long *lpixel, long *array, int *status);
+int ffpssuk(fitsfile *fptr, long group, long naxis, long *naxes,
+           long *fpixel, long *lpixel, unsigned int *array, int *status);
+int ffpssk(fitsfile *fptr, long group, long naxis, long *naxes,
+           long *fpixel, long *lpixel, int *array, int *status);
+int ffpsse(fitsfile *fptr, long group, long naxis, long *naxes,
+           long *fpixel, long *lpixel, float *array, int *status);
+int ffpssd(fitsfile *fptr, long group, long naxis, long *naxes,
+           long *fpixel, long *lpixel, double *array, int *status);
+int ffpssjj(fitsfile *fptr, long group, long naxis, long *naxes,
+           long *fpixel, long *lpixel, LONGLONG *array, int *status);
+
+int ffpgpb(fitsfile *fptr, long group, long firstelem,
+           long nelem, unsigned char *array, int *status);
+int ffpgpsb(fitsfile *fptr, long group, long firstelem,
+           long nelem, signed char *array, int *status);
+int ffpgpui(fitsfile *fptr, long group, long firstelem,
+           long nelem, unsigned short *array, int *status);
+int ffpgpi(fitsfile *fptr, long group, long firstelem,
+           long nelem, short *array, int *status);
+int ffpgpuj(fitsfile *fptr, long group, long firstelem,
+           long nelem, unsigned long *array, int *status);
+int ffpgpj(fitsfile *fptr, long group, long firstelem,
+           long nelem, long *array, int *status);
+int ffpgpuk(fitsfile *fptr, long group, long firstelem,
+           long nelem, unsigned int *array, int *status);
+int ffpgpk(fitsfile *fptr, long group, long firstelem,
+           long nelem, int *array, int *status);
+int ffpgpe(fitsfile *fptr, long group, long firstelem,
+           long nelem, float *array, int *status);
+int ffpgpd(fitsfile *fptr, long group, long firstelem,
+           long nelem, double *array, int *status);
+int ffpgpjj(fitsfile *fptr, long group, long firstelem,
+           long nelem, LONGLONG *array, int *status);
+
+/*--------------------- iterator functions -------------*/
+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);
+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);
+
+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);
+
+int 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 ffpcl(fitsfile *fptr, int datatype, int colnum, LONGLONG firstrow,
+          LONGLONG firstelem, LONGLONG nelem, void *array, int *status);
+int ffpcls(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem,
+           LONGLONG nelem, char **array, int *status);
+int ffpcll(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem,
+           LONGLONG nelem, char *array, int *status);
+int ffpclb(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem,
+           LONGLONG nelem, unsigned char *array, int *status);
+int ffpclsb(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem,
+           LONGLONG nelem, signed char *array, int *status);
+int ffpclui(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem,
+           LONGLONG nelem, unsigned short *array, int *status);
+int ffpcli(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem,
+           LONGLONG nelem, short *array, int *status);
+int ffpcluj(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem,
+           LONGLONG nelem, unsigned long *array, int *status);
+int ffpclj(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem,
+           LONGLONG nelem, long *array, int *status);
+int ffpcluk(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem,
+           LONGLONG nelem, unsigned int *array, int *status);
+int ffpclk(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem,
+           LONGLONG nelem, int *array, int *status);
+int ffpcle(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem,
+           LONGLONG nelem, float *array, int *status);
+int ffpcld(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem,
+           LONGLONG nelem, double *array, int *status);
+int ffpclc(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem,
+           LONGLONG nelem, float *array, int *status);
+int ffpclm(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem,
+           LONGLONG nelem, double *array, int *status);
+int ffpclu(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem,
+           LONGLONG nelem, int *status);
+int ffprwu(fitsfile *fptr, LONGLONG firstrow, LONGLONG nrows, int *status);
+int ffpcljj(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem,
+           LONGLONG nelem, LONGLONG *array, int *status);
+int ffpclx(fitsfile *fptr, int colnum, LONGLONG frow, long fbit, long nbit,
+            char *larray, int *status);
+
+int ffpcn(fitsfile *fptr, int datatype, int colnum, LONGLONG firstrow, LONGLONG firstelem,
+          LONGLONG nelem, void *array, void *nulval, int *status);
+int ffpcns( fitsfile *fptr, int  colnum, LONGLONG  firstrow, LONGLONG  firstelem,
+            LONGLONG  nelem, char **array, char  *nulvalue, int  *status);
+int ffpcnl( fitsfile *fptr, int  colnum, LONGLONG  firstrow, LONGLONG  firstelem,
+            LONGLONG  nelem, char *array, char  nulvalue,  int  *status);
+int ffpcnb(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem,
+           LONGLONG nelem, unsigned char *array, unsigned char nulvalue,
+           int *status);
+int ffpcnsb(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem,
+           LONGLONG nelem, signed char *array, signed char nulvalue,
+           int *status);
+int ffpcnui(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem,
+           LONGLONG nelem, unsigned short *array, unsigned short nulvalue,
+           int *status);
+int ffpcni(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem,
+           LONGLONG nelem, short *array, short nulvalue, int *status);
+int ffpcnuj(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem,
+           LONGLONG nelem, unsigned long *array, unsigned long nulvalue,
+           int *status);
+int ffpcnj(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem,
+           LONGLONG nelem, long *array, long nulvalue, int *status);
+int ffpcnuk(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem,
+           LONGLONG nelem, unsigned int *array, unsigned int nulvalue,
+           int *status);
+int ffpcnk(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem,
+           LONGLONG nelem, int *array, int nulvalue, int *status);
+int ffpcne(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem,
+           LONGLONG nelem, float *array, float nulvalue, int *status);
+int ffpcnd(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem,
+           LONGLONG nelem, double *array, double nulvalue, int *status);
+int ffpcnjj(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem,
+           LONGLONG nelem, LONGLONG *array, LONGLONG nulvalue, int *status);
+int ffptbb(fitsfile *fptr, LONGLONG firstrow, LONGLONG firstchar, LONGLONG nchars,
+           unsigned char *values, int *status);
+ 
+int ffirow(fitsfile *fptr, LONGLONG firstrow, LONGLONG nrows, int *status);
+int ffdrow(fitsfile *fptr, LONGLONG firstrow, LONGLONG nrows, int *status);
+int ffdrrg(fitsfile *fptr, char *ranges, int *status);
+int ffdrws(fitsfile *fptr, long *rownum,  long nrows, int *status);
+int ffdrwsll(fitsfile *fptr, LONGLONG *rownum,  LONGLONG nrows, int *status);
+int fficol(fitsfile *fptr, int numcol, char *ttype, char *tform, int *status);
+int fficls(fitsfile *fptr, int firstcol, int ncols, char **ttype,
+           char **tform, int *status);
+int ffmvec(fitsfile *fptr, int colnum, LONGLONG newveclen, int *status);
+int ffdcol(fitsfile *fptr, int numcol, int *status);
+int ffcpcl(fitsfile *infptr, fitsfile *outfptr, int incol, int outcol, 
+           int create_col, int *status);
+int ffcprw(fitsfile *infptr, fitsfile *outfptr, LONGLONG firstrow, 
+           LONGLONG nrows, int *status);
+
+/*--------------------- WCS Utilities ------------------*/
+int ffgics(fitsfile *fptr, double *xrval, double *yrval, double *xrpix,
+           double *yrpix, double *xinc, double *yinc, double *rot,
+           char *type, int *status);
+int ffgicsa(fitsfile *fptr, char version, double *xrval, double *yrval, double *xrpix,
+           double *yrpix, double *xinc, double *yinc, double *rot,
+           char *type, int *status);
+int 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 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 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 ffgiwcs(fitsfile *fptr,  char **header, int *status); 
+int ffgtwcs(fitsfile *fptr, int xcol, int ycol, char **header, int *status);
+
+/*--------------------- lexical parsing routines ------------------*/
+int fftexp( fitsfile *fptr, char *expr, int maxdim,
+	    int *datatype, long *nelem, int *naxis,
+	    long *naxes, int *status );
+
+int fffrow( fitsfile *infptr, char *expr,
+	    long firstrow, long nrows,
+            long *n_good_rows, char *row_status, int *status);
+
+int ffffrw( fitsfile *fptr, char *expr, long *rownum, int *status);
+
+int fffrwc( fitsfile *fptr, char *expr, char *timeCol,    
+            char *parCol, char *valCol, long ntimes,      
+            double *times, char *time_status, int  *status );
+
+int ffsrow( fitsfile *infptr, fitsfile *outfptr, char *expr, 
+            int *status);
+
+int ffcrow( fitsfile *fptr, int datatype, char *expr,
+	    long firstrow, long nelements, void *nulval,
+	    void *array, int *anynul, int *status );
+
+int ffcalc_rng( fitsfile *infptr, char *expr, fitsfile *outfptr,
+               char *parName, char *parInfo, int nRngs,
+                 long *start, long *end, int *status );
+
+int 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 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 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);
+
+int fits_select_image_section(fitsfile **fptr, char *outfile,
+           char *imagesection, int *status);
+int fits_copy_image_section(fitsfile *infptr, fitsfile *outfile,
+           char *imagesection, int *status);
+
+int 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 fits_write_keys_histo(fitsfile *fptr,  fitsfile *histptr, 
+      int naxis, int *colnum, int *status);  
+int fits_rebin_wcs( fitsfile *fptr, int naxis, float *amin,  float *binsize, 
+      int *status);      
+int 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 fits_pixel_filter (PixelFilter * filter, int * status);
+
+
+/*--------------------- grouping routines ------------------*/
+
+int ffgtcr(fitsfile *fptr, char *grpname, int grouptype, int *status);
+int ffgtis(fitsfile *fptr, char *grpname, int grouptype, int *status);
+int ffgtch(fitsfile *gfptr, int grouptype, int *status);
+int ffgtrm(fitsfile *gfptr, int rmopt, int *status);
+int ffgtcp(fitsfile *infptr, fitsfile *outfptr, int cpopt, int *status);
+int ffgtmg(fitsfile *infptr, fitsfile *outfptr, int mgopt, int *status);
+int ffgtcm(fitsfile *gfptr, int cmopt, int *status);
+int ffgtvf(fitsfile *gfptr, long *firstfailed, int *status);
+int ffgtop(fitsfile *mfptr,int group,fitsfile **gfptr,int *status);
+int ffgtam(fitsfile *gfptr, fitsfile *mfptr, int hdupos, int *status);
+int ffgtnm(fitsfile *gfptr, long *nmembers, int *status);
+int ffgmng(fitsfile *mfptr, long *nmembers, int *status);
+int ffgmop(fitsfile *gfptr, long member, fitsfile **mfptr, int *status);
+int ffgmcp(fitsfile *gfptr, fitsfile *mfptr, long member, int cpopt, 
+	   int *status);
+int ffgmtf(fitsfile *infptr, fitsfile *outfptr,	long member, int tfopt,	       
+	   int *status);
+int ffgmrm(fitsfile *fptr, long member, int rmopt, int *status);
+
+/*--------------------- group template parser routines ------------------*/
+
+int	fits_execute_template(fitsfile *ff, char *ngp_template, int *status);
+
+int 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 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 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 fits_set_compression_type(fitsfile *fptr, int ctype, int *status);
+int fits_set_tile_dim(fitsfile *fptr, int ndim, long *dims, int *status);
+int fits_set_noise_bits(fitsfile *fptr, int noisebits, int *status);
+int fits_set_quantize_level(fitsfile *fptr, float qlevel, int *status);
+int fits_set_hcomp_scale(fitsfile *fptr, float scale, int *status);
+int fits_set_hcomp_smooth(fitsfile *fptr, int smooth, int *status);
+int fits_set_quantize_dither(fitsfile *fptr, int dither, 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);
+
+int fits_get_compression_type(fitsfile *fptr, int *ctype, int *status);
+int fits_get_tile_dim(fitsfile *fptr, int ndim, long *dims, int *status);
+int fits_get_quantize_level(fitsfile *fptr, float *qlevel, int *status);
+int fits_get_noise_bits(fitsfile *fptr, int *noisebits, int *status);
+int fits_get_hcomp_scale(fitsfile *fptr, float *scale, int *status);
+int fits_get_hcomp_smooth(fitsfile *fptr, int *smooth, int *status);
+int fits_get_dither_offset(fitsfile *fptr, int *offset, int *status);
+
+int fits_img_compress(fitsfile *infptr, fitsfile *outfptr, int *status);
+int fits_compress_img(fitsfile *infptr, fitsfile *outfptr, int compress_type,
+         long *tilesize, int parm1, int parm2, int *status);
+int fits_is_compressed_image(fitsfile *fptr, int *status);
+int fits_is_reentrant(void);
+int fits_decompress_img (fitsfile *infptr, fitsfile *outfptr, int *status);
+int fits_img_decompress_header(fitsfile *infptr, fitsfile *outfptr, int *status);
+int fits_img_decompress (fitsfile *infptr, fitsfile *outfptr, int *status);
+
+/* H-compress routines */
+int fits_hcompress(int *a, int nx, int ny, int scale, char *output, 
+    long *nbytes, int *status);
+int fits_hcompress64(LONGLONG *a, int nx, int ny, int scale, char *output, 
+    long *nbytes, int *status);
+int fits_hdecompress(unsigned char *input, int smooth, int *a, int *nx, 
+       int *ny, int *scale, int *status);
+int fits_hdecompress64(unsigned char *input, int smooth, LONGLONG *a, int *nx, 
+       int *ny, int *scale, int *status);
+
+int fits_transpose_table(fitsfile *infptr, fitsfile *outfptr, int *status);
+int fits_compress_table_fast(fitsfile *infptr, fitsfile *outfptr, int *status);
+int fits_compress_table_best(fitsfile *infptr, fitsfile *outfptr, int *status);
+int fits_compress_table_rice(fitsfile *infptr, fitsfile *outfptr, int *status);
+int fits_uncompress_table(fitsfile *infptr, fitsfile *outfptr, int *status);
+int fits_gzip_datablocks(fitsfile *fptr, size_t *size, int *status);
+
+/*  The following exclusion if __CINT__ is defined is needed for ROOT */
+#ifndef __CINT__
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+#endif
+
diff --git a/cextern/cfitsio/fitsio2.h b/cextern/cfitsio/fitsio2.h
new file mode 100644
index 0000000..b6fd66c
--- /dev/null
+++ b/cextern/cfitsio/fitsio2.h
@@ -0,0 +1,1205 @@
+#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 <pthread.h>
+#include <assert.h>
+extern pthread_mutex_t Fitsio_Lock;
+extern int Fitsio_Pthread_Status;
+
+#define FFLOCK1(lockname)   (assert(!(Fitsio_Pthread_Status = pthread_mutex_lock(&lockname))))
+#define FFUNLOCK1(lockname) (assert(!(Fitsio_Pthread_Status = pthread_mutex_unlock(&lockname))))
+#define FFLOCK   FFLOCK1(Fitsio_Lock)
+#define FFUNLOCK FFUNLOCK1(Fitsio_Lock)
+
+#else
+#define FFLOCK
+#define FFUNLOCK
+#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  300   /* maximum number of FITS files that can be opened */
+        /* CFITSIO will allocate (NMAXFILES * 80) bytes of memory */
+
+#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__)
+                  /*  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__) /* IBM 64-bit AIX powerpc*/
+                              /* could also test for __ppc64__ or __PPC64 */
+#define BYTESWAPPED FALSE
+#define MACHINE NATIVE
+#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 ffmkky(const char *keyname, char *keyval, const char *comm, char *card, int *status);
+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(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(char *cval, long *ival, int *status);
+int ffc2jj(char *cval, LONGLONG *ival, int *status);
+int ffc2ll(char *cval, int *lval, int *status);
+int ffc2rr(char *cval, float *fval, int *status);
+int ffc2dd(char *cval, double *dval, int *status);
+int ffc2x(char *cval, char *dtype, long *ival, int *lval, char *sval,
+          double *dval, int *status);
+int ffc2s(char *instr, char *outstr, int *status);
+int ffc2i(char *cval, long *ival, int *status);
+int ffc2j(char *cval, LONGLONG *ival, int *status);
+int ffc2r(char *cval, float *fval, int *status);
+int ffc2d(char *cval, double *dval, int *status);
+int ffc2l(char *cval, int *lval, int *status);
+void ffxmsg(int action, char *err_message);
+int ffgcnt(fitsfile *fptr, char *value, 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, 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 ffrhdu(fitsfile *fptr, int *hdutype, int *status);
+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_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 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 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 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 *size),
+	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);
+
+/* 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
+
+#if defined(vms) || defined(__vms) || defined(WIN32) || defined(__WIN32__) || (defined(macintosh) && !defined(TARGET_API_MAC_CARBON))
+/* A hack for nonunix machines, which lack strcasecmp and strncasecmp */
+int strcasecmp (const char *s1, const char *s2       );
+int strncasecmp(const char *s1, const char *s2, size_t n);
+#endif
+
+/* end of the entire "ifndef _FITSIO2_H" block */
+#endif
diff --git a/cextern/cfitsio/getcol.c b/cextern/cfitsio/getcol.c
new file mode 100644
index 0000000..f40b91d
--- /dev/null
+++ b/cextern/cfitsio/getcol.c
@@ -0,0 +1,1055 @@
+
+/*  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 <stdlib.h>
+#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.
+*/
+{
+    void *nulval;         /* dummy argument */
+    double dnulval = 0.;
+
+    if (*status > 0)           /* inherit input status value if > 0 */
+        return(*status);
+
+    nulval = &dnulval;  /* set to a harmless value; this is never used */
+
+    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, *(double *)
+              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, (char *)
+             nulval, (char **) array, nullarray, anynul, status);
+    }
+    else
+      *status = BAD_DATATYPE;
+
+    return(*status);
+}
+
diff --git a/cextern/cfitsio/getcolb.c b/cextern/cfitsio/getcolb.c
new file mode 100644
index 0000000..4fff57d
--- /dev/null
+++ b/cextern/cfitsio/getcolb.c
@@ -0,0 +1,2001 @@
+/*  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 <math.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+#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)
+    {
+        sprintf(msg, "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
+        {
+          sprintf(msg, "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)
+    {
+        sprintf(msg, "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])
+      {
+        sprintf(msg, "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, maxelem, 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;
+    char tform[20];
+    char message[81];
+    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, &maxelem, &startpos, &elemnum, &incre,
+         &repeat, &rowlen, &hdutype, &tnull, snull, status);
+
+    /* 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 */
+        maxelem = (int) nelem;          /* data directly into output buffer.    */
+
+        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 */
+                sprintf(message, 
+                   "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)
+            sprintf(message,
+            "Error reading elements %.0f thru %.0f from column %d (ffgclb).",
+              dtemp+1., dtemp+ntodo, colnum);
+          else
+            sprintf(message,
+            "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 */
+           memcpy(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[81];
+    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 */
+        {
+          sprintf(message, "Cannot read number from ASCII table");
+          ffpmsg(message);
+          sprintf(message, "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);
+}
diff --git a/cextern/cfitsio/getcold.c b/cextern/cfitsio/getcold.c
new file mode 100644
index 0000000..8c33931
--- /dev/null
+++ b/cextern/cfitsio/getcold.c
@@ -0,0 +1,1676 @@
+/*  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 <math.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+#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)
+    {
+        sprintf(msg, "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
+        {
+          sprintf(msg, "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)
+    {
+        sprintf(msg, "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])
+      {
+        sprintf(msg, "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. 
+*/
+{
+    long 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, maxelem;
+    long twidth, incre;
+    long ii, xwidth, ntodo;
+    int convert, nulcheck, readcheck = 0;
+    LONGLONG repeat, startpos, elemnum, readptr, tnull;
+    LONGLONG rowlen, rownum, remain, next, rowincre;
+    char tform[20];
+    char message[81];
+    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, &maxelem, &startpos, &elemnum, &incre,
+         &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0 )
+         return(*status);
+
+    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 */
+        maxelem = (int) nelem;           /* data directly into output buffer.    */
+
+        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 */
+                sprintf(message, 
+                   "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)
+            sprintf(message,
+            "Error reading elements %.0f thru %.0f from column %d (ffgcld).",
+              dtemp+1., dtemp+ntodo, colnum);
+          else
+            sprintf(message,
+            "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 */
+        {       
+            memcpy(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[81];
+    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 */
+        {
+          sprintf(message, "Cannot read number from ASCII table");
+          ffpmsg(message);
+          sprintf(message, "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);
+}
diff --git a/cextern/cfitsio/getcole.c b/cextern/cfitsio/getcole.c
new file mode 100644
index 0000000..441c657
--- /dev/null
+++ b/cextern/cfitsio/getcole.c
@@ -0,0 +1,1679 @@
+/*  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 <math.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+#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, ii, jj;
+    LONGLONG narray, nfits;
+    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)
+    {
+        sprintf(msg, "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
+        {
+          sprintf(msg, "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)
+    {
+        sprintf(msg, "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])
+      {
+        sprintf(msg, "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. 
+*/
+{
+    long 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, maxelem, 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;
+    char tform[20];
+    char message[81];
+    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, &maxelem, &startpos, &elemnum, &incre,
+         &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0 )
+         return(*status);
+
+    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 */
+        maxelem = (int) nelem;          /* data directly into output buffer.    */
+
+        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 */
+                sprintf(message, 
+                   "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)
+            sprintf(message,
+            "Error reading elements %.0f thru %.0f from column %d (ffgcle).",
+              dtemp+1., dtemp+ntodo, colnum);
+          else
+            sprintf(message,
+            "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 */
+        {       
+            memcpy(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[81];
+    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 */
+        {
+          sprintf(message, "Cannot read number from ASCII table");
+          ffpmsg(message);
+          sprintf(message, "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);
+}
diff --git a/cextern/cfitsio/getcoli.c b/cextern/cfitsio/getcoli.c
new file mode 100644
index 0000000..e3386e8
--- /dev/null
+++ b/cextern/cfitsio/getcoli.c
@@ -0,0 +1,1901 @@
+/*  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 <math.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+#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)
+    {
+        sprintf(msg, "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
+        {
+          sprintf(msg, "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)
+    {
+        sprintf(msg, "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])
+      {
+        sprintf(msg, "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, maxelem, 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;
+    char tform[20];
+    char message[81];
+    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, &maxelem, &startpos, &elemnum, &incre,
+         &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0 )
+         return(*status);
+
+    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 */
+        maxelem = (int) nelem;          /* data directly into output buffer.    */
+
+        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 */
+                sprintf(message, 
+                   "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)
+            sprintf(message,
+            "Error reading elements %.0f thru %.0f from column %d (ffgcli).",
+              dtemp+1, dtemp+ntodo, colnum);
+          else
+            sprintf(message,
+            "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 */
+        {       
+            memcpy(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[81];
+    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 */
+        {
+          sprintf(message, "Cannot read number from ASCII table");
+          ffpmsg(message);
+          sprintf(message, "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);
+}
diff --git a/cextern/cfitsio/getcolj.c b/cextern/cfitsio/getcolj.c
new file mode 100644
index 0000000..2d90913
--- /dev/null
+++ b/cextern/cfitsio/getcolj.c
@@ -0,0 +1,3726 @@
+/*  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 <math.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+#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)
+    {
+        sprintf(msg, "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
+        {
+          sprintf(msg, "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)
+    {
+        sprintf(msg, "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])
+      {
+        sprintf(msg, "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, maxelem, 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;
+    char tform[20];
+    char message[81];
+    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, &maxelem, &startpos, &elemnum, &incre,
+         &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0 )
+         return(*status);
+
+    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 */
+        maxelem = (int) nelem;          /* data directly into output buffer.    */
+
+        if (nulcheck == 0 && scale == 1. && zero == 0. && LONGSIZE == 32)
+            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)
+                    fffi4i4((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);
+                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 */
+                sprintf(message, 
+                   "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)
+            sprintf(message,
+            "Error reading elements %.0f thru %.0f from column %d (ffgclj).",
+              dtemp+1., dtemp+ntodo, colnum);
+          else
+            sprintf(message,
+            "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;
+
+  Process the array of data in reverse order, to handle the case where
+  the input data is 4-bytes and the output is  8-bytes and the conversion
+  is being done in place in the same array.
+*/
+{
+    long ii;
+    double dvalue;
+
+    if (nullcheck == 0)     /* no null checking required */
+    {
+        if (scale == 1. && zero == 0.)      /* no scaling */
+        {       
+            for (ii = ntodo - 1; ii >= 0; ii--)
+                output[ii] = (long) input[ii];   /* copy input to output */
+        }
+        else             /* must scale the data */
+        {
+            for (ii = ntodo - 1; ii >= 0; 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 = ntodo - 1; ii >= 0; 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 = ntodo - 1; ii >= 0; 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[81];
+    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 */
+        {
+          sprintf(message, "Cannot read number from ASCII table");
+          ffpmsg(message);
+          sprintf(message, "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)
+    {
+        sprintf(msg, "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
+        {
+          sprintf(msg, "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)
+    {
+        sprintf(msg, "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])
+      {
+        sprintf(msg, "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, maxelem, 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;
+    char tform[20];
+    char message[81];
+    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, &maxelem, &startpos, &elemnum, &incre,
+         &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0 )
+         return(*status);
+
+    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 */
+        maxelem = (int) nelem;          /* data directly into output buffer.    */
+
+        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 */
+                sprintf(message, 
+                   "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)
+            sprintf(message,
+            "Error reading elements %.0f thru %.0f from column %d (ffgclj).",
+              dtemp+1., dtemp+ntodo, colnum);
+          else
+            sprintf(message,
+            "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[81];
+    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 */
+        {
+          sprintf(message, "Cannot read number from ASCII table");
+          ffpmsg(message);
+          sprintf(message, "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);
+}
diff --git a/cextern/cfitsio/getcolk.c b/cextern/cfitsio/getcolk.c
new file mode 100644
index 0000000..4b4447e
--- /dev/null
+++ b/cextern/cfitsio/getcolk.c
@@ -0,0 +1,1894 @@
+/*  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 <math.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+#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)
+    {
+        sprintf(msg, "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
+        {
+          sprintf(msg, "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)
+    {
+        sprintf(msg, "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])
+      {
+        sprintf(msg, "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, maxelem, 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;
+    char tform[20];
+    char message[81];
+    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, &maxelem, &startpos, &elemnum, &incre,
+         &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0 )
+         return(*status);
+
+    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 */
+        maxelem = (int) nelem;          /* data directly into output buffer.    */
+
+        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 */
+                sprintf(message, 
+                   "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)
+            sprintf(message,
+            "Error reading elements %.0f thru %.0f from column %d (ffgclk).",
+              dtemp+1., dtemp+ntodo, colnum);
+          else
+            sprintf(message,
+            "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[81];
+    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 */
+        {
+          sprintf(message, "Cannot read number from ASCII table");
+          ffpmsg(message);
+          sprintf(message, "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);
+}
diff --git a/cextern/cfitsio/getcoll.c b/cextern/cfitsio/getcoll.c
new file mode 100644
index 0000000..427247d
--- /dev/null
+++ b/cextern/cfitsio/getcoll.c
@@ -0,0 +1,614 @@
+/*  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 <stdlib.h>
+#include <string.h>
+#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 */
+        {
+          array[next] = (char) *buffptr;
+        }
+      }
+
+      if (*status > 0)  /* test for error during previous read operation */
+      {
+	dtemp = (double) next;
+        sprintf(message,
+          "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[81];
+
+    if (*status > 0 || nrows == 0)
+        return(*status);
+
+    /*  check input parameters */
+    if (firstrow < 1)
+    {
+          sprintf(message, "Starting row number is less than 1: %ld (ffgcxui)",
+                (long) firstrow);
+          ffpmsg(message);
+          return(*status = BAD_ROW_NUM);
+    }
+    else if (input_first_bit < 1)
+    {
+          sprintf(message, "Starting bit number is less than 1: %ld (ffgcxui)",
+                input_first_bit);
+          ffpmsg(message);
+          return(*status = BAD_ELEM_NUM);
+    }
+    else if (input_nbits > 16)
+    {
+          sprintf(message, "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)
+    {
+      sprintf(message, "Specified column number is out of range: %d (ffgcxui)",
+                colnum);
+        ffpmsg(message);
+        sprintf(message, "  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[81];
+
+    if (*status > 0 || nrows == 0)
+        return(*status);
+
+    /*  check input parameters */
+    if (firstrow < 1)
+    {
+          sprintf(message, "Starting row number is less than 1: %ld (ffgcxuk)",
+                (long) firstrow);
+          ffpmsg(message);
+          return(*status = BAD_ROW_NUM);
+    }
+    else if (input_first_bit < 1)
+    {
+          sprintf(message, "Starting bit number is less than 1: %ld (ffgcxuk)",
+                input_first_bit);
+          ffpmsg(message);
+          return(*status = BAD_ELEM_NUM);
+    }
+    else if (input_nbits > 32)
+    {
+          sprintf(message, "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)
+    {
+      sprintf(message, "Specified column number is out of range: %d (ffgcxuk)",
+                colnum);
+        ffpmsg(message);
+        sprintf(message, "  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);
+}
diff --git a/cextern/cfitsio/getcols.c b/cextern/cfitsio/getcols.c
new file mode 100644
index 0000000..7033d6c
--- /dev/null
+++ b/cextern/cfitsio/getcols.c
@@ -0,0 +1,835 @@
+/*  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 <stdlib.h>
+#include <string.h>
+/* stddef.h is apparently needed to define size_t */
+#include <stddef.h>
+#include <ctype.h>
+#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;
+    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)
+    {
+        sprintf(message, "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);
+
+    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
+             sprintf(tmpstr, 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
+             sprintf(tmpstr, 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
+             sprintf(tmpstr, 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
+             sprintf(tmpstr, cform, darray[jj]);
+
+           strncat(array[ii], tmpstr, dwidth);
+           strcat(array[ii], ")");
+           jj++;
+         }
+      }
+
+      free(darray);  /* free the memory */
+    }
+    else if (tcode == 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 */
+        sprintf(tmpstr, "%20I64d", llarray[ii]);
+#elif (USE_LL_SUFFIX == 1)
+        sprintf(tmpstr, "%20lld", llarray[ii]);
+#else
+        sprintf(tmpstr, "%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
+            {
+               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)
+                sprintf(tmpstr, cform, (int) darray[ii]);
+              else
+                sprintf(tmpstr, 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)
+    {
+        sprintf(message, "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
+        {
+           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' */
+                  {
+                     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)
+    {
+        sprintf(message, "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;
+         sprintf(message,
+          "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);
+}
+
diff --git a/cextern/cfitsio/getcolsb.c b/cextern/cfitsio/getcolsb.c
new file mode 100644
index 0000000..f750681
--- /dev/null
+++ b/cextern/cfitsio/getcolsb.c
@@ -0,0 +1,1991 @@
+/*  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 <math.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+#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)
+    {
+        sprintf(msg, "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
+        {
+          sprintf(msg, "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)
+    {
+        sprintf(msg, "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])
+      {
+        sprintf(msg, "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[81];
+    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 */
+                sprintf(message, 
+                   "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)
+            sprintf(message,
+            "Error reading elements %.0f thru %.0f from column %d (ffgclsb).",
+              dtemp+1., dtemp+ntodo, colnum);
+          else
+            sprintf(message,
+            "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[81];
+    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 */
+        {
+          sprintf(message, "Cannot read number from ASCII table");
+          ffpmsg(message);
+          sprintf(message, "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);
+}
diff --git a/cextern/cfitsio/getcolui.c b/cextern/cfitsio/getcolui.c
new file mode 100644
index 0000000..6de4efc
--- /dev/null
+++ b/cextern/cfitsio/getcolui.c
@@ -0,0 +1,1907 @@
+/*  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 <math.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+#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)
+    {
+        sprintf(msg, "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])
+      {
+        sprintf(msg, "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)
+    {
+        sprintf(msg, "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])
+      {
+        sprintf(msg, "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, maxelem, hdutype, xcode, decimals;
+    long twidth, incre;
+    long ii, xwidth, ntodo;
+    int nulcheck;
+    LONGLONG repeat, startpos, elemnum, readptr, tnull;
+    LONGLONG rowlen, rownum, remain, next, rowincre;
+    char tform[20];
+    char message[81];
+    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, &maxelem, &startpos, &elemnum, &incre,
+         &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0 )
+         return(*status);
+
+    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 */
+        maxelem = (int) nelem;          /* data directly into output buffer.    */
+    }
+
+    /*---------------------------------------------------------------------*/
+    /*  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 */
+                sprintf(message, 
+                   "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)
+            sprintf(message,
+            "Error reading elements %.0f thru %.0f from column %d (ffgclui).",
+              dtemp+1., dtemp+ntodo, colnum);
+          else
+            sprintf(message,
+            "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[81];
+    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 */
+        {
+          sprintf(message, "Cannot read number from ASCII table");
+          ffpmsg(message);
+          sprintf(message, "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);
+}
diff --git a/cextern/cfitsio/getcoluj.c b/cextern/cfitsio/getcoluj.c
new file mode 100644
index 0000000..bb69134
--- /dev/null
+++ b/cextern/cfitsio/getcoluj.c
@@ -0,0 +1,1901 @@
+/*  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 <math.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+#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)
+    {
+        sprintf(msg, "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])
+      {
+        sprintf(msg, "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)
+    {
+        sprintf(msg, "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])
+      {
+        sprintf(msg, "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, maxelem, hdutype, xcode, decimals;
+    long twidth, incre;
+    long ii, xwidth, ntodo;
+    int nulcheck;
+    LONGLONG repeat, startpos, elemnum, readptr, tnull;
+    LONGLONG rowlen, rownum, remain, next, rowincre;
+    char tform[20];
+    char message[81];
+    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, &maxelem, &startpos, &elemnum, &incre,
+         &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0 )
+         return(*status);
+
+    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:                        */
+    {                             /* no type convertion required, so read */
+        maxelem = (int) nelem;          /* data directly into output buffer.    */
+    }
+
+    /*---------------------------------------------------------------------*/
+    /*  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);
+                fffi4u4((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);
+                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 */
+                sprintf(message, 
+                   "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)
+            sprintf(message,
+            "Error reading elements %.0f thru %.0f from column %d (ffgcluj).",
+              dtemp+1., dtemp+ntodo, colnum);
+          else
+            sprintf(message,
+            "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;
+
+  Process the array of data in reverse order, to handle the case where
+  the input data is 4-bytes and the output is  8-bytes and the conversion
+  is being done in place in the same array.
+*/
+{
+    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 = ntodo - 1; ii >= 0; ii--)
+               output[ii] =  ( *(unsigned int *) &input[ii] ) ^ 0x80000000;
+        }
+        else if (scale == 1. && zero == 0.)      /* no scaling */
+        {       
+            for (ii = ntodo - 1; ii >= 0; 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 = ntodo - 1; ii >= 0; 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 = ntodo - 1; ii >= 0; 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 = ntodo - 1; ii >= 0; 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 = ntodo - 1; ii >= 0; 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[81];
+    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 */
+        {
+          sprintf(message, "Cannot read number from ASCII table");
+          ffpmsg(message);
+          sprintf(message, "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);
+}
diff --git a/cextern/cfitsio/getcoluk.c b/cextern/cfitsio/getcoluk.c
new file mode 100644
index 0000000..36d32e0
--- /dev/null
+++ b/cextern/cfitsio/getcoluk.c
@@ -0,0 +1,1916 @@
+/*  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 <math.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+#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)
+    {
+        sprintf(msg, "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])
+      {
+        sprintf(msg, "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)
+    {
+        sprintf(msg, "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])
+      {
+        sprintf(msg, "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, maxelem, hdutype, xcode, decimals;
+    long twidth, incre;
+    long ii, xwidth, ntodo;
+    int nulcheck;
+    LONGLONG repeat, startpos, elemnum, readptr, tnull;
+    LONGLONG rowlen, rownum, remain, next, rowincre;
+    char tform[20];
+    char message[81];
+    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, &maxelem, &startpos, &elemnum, &incre,
+         &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0 )
+         return(*status);
+
+    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       */
+        maxelem = (int) nelem;          /* data directly into output buffer.    */
+    }
+
+    /*---------------------------------------------------------------------*/
+    /*  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 */
+                sprintf(message, 
+                   "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)
+            sprintf(message,
+            "Error reading elements %.0f thru %.0f from column %d (ffgcluk).",
+              dtemp+1., dtemp+ntodo, colnum);
+          else
+            sprintf(message,
+            "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[81];
+    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 */
+        {
+          sprintf(message, "Cannot read number from ASCII table");
+          ffpmsg(message);
+          sprintf(message, "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);
+}
diff --git a/cextern/cfitsio/getkey.c b/cextern/cfitsio/getkey.c
new file mode 100644
index 0000000..3184779
--- /dev/null
+++ b/cextern/cfitsio/getkey.c
@@ -0,0 +1,3241 @@
+/*  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 <string.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <ctype.h>
+/* stddef.h is apparently needed to define size_t */
+#include <stddef.h>
+#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);
+
+  *nexist = (int) (( ((fptr->Fptr)->headend) - ((fptr->Fptr)->headstart[(fptr->Fptr)->curhdu]) ) / 80);
+  *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);
+        sprintf(message, "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;
+
+    *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 < 8; ii++)
+        {
+           /* look for string terminator, or a blank */
+           if (*(card+ii) != ' ' && *(card+ii) !='\0')
+           {
+               *(name+ii) = *(card+ii);
+           }
+           else
+           {
+               name[ii] = '\0';
+               *length = ii;
+               return(*status);
+           }
+        }
+
+        /* if we got here, keyword is 8 characters long */
+        name[8] = '\0';
+        *length = 8;
+    }
+
+    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 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           */
+            int  *status)       /* IO - error status             */
+/*
+  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];
+    int contin;
+    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 (!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, 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;
+        }
+        else
+            contin = 0;
+      }
+    }
+    return(*status);
+}
+/*--------------------------------------------------------------------------*/
+int fffree( char *value,       /* I - pointer to keyword value  */
+            int  *status)      /* IO - error status             */
+/*
+  Free the memory that was allocated by ffgkls for the long string keyword value.
+*/
+{
+    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    */
+            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], comm[FLEN_COMMENT];
+
+    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  */
+        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[81];
+    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 */
+    {
+      sprintf(message, "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[81];
+    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 */
+    {
+      sprintf(message, "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 */
+    {
+     sprintf(sbuff,"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];
+
+    if (*status > 0)
+        return(*status);
+
+    *nfound = 0;
+    nend = nstart + nmax - 1;
+
+    keyroot[0] = '\0';
+    strncat(keyroot, keyname, 8);
+     
+    lenroot = strlen(keyroot);
+    if (lenroot == 0 || lenroot > 7)     /*  root must be 1 - 7 chars 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';
+          strncat(keyindex, &card[lenroot], 8-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];
+
+    if (*status > 0)
+        return(*status);
+
+    *nfound = 0;
+    nend = nstart + nmax - 1;
+
+    keyroot[0] = '\0';
+    strncat(keyroot, keyname, 8);
+
+    lenroot = strlen(keyroot);
+    if (lenroot == 0 || lenroot > 7)     /*  root must be 1 - 7 chars 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';
+          strncat(keyindex, &card[lenroot], 8-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];
+
+    if (*status > 0)
+        return(*status);
+
+    *nfound = 0;
+    nend = nstart + nmax - 1;
+
+    keyroot[0] = '\0';
+    strncat(keyroot, keyname, 8);
+
+    lenroot = strlen(keyroot);
+    if (lenroot == 0 || lenroot > 7)     /* root must be 1 - 7 chars 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';
+          strncat(keyindex, &card[lenroot], 8-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];
+
+    if (*status > 0)
+        return(*status);
+
+    *nfound = 0;
+    nend = nstart + nmax - 1;
+
+    keyroot[0] = '\0';
+    strncat(keyroot, keyname, 8);
+
+    lenroot = strlen(keyroot);
+    if (lenroot == 0 || lenroot > 7)     /* root must be 1 - 7 chars 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';
+          strncat(keyindex, &card[lenroot], 8-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];
+
+    if (*status > 0)
+        return(*status);
+
+    *nfound = 0;
+    nend = nstart + nmax - 1;
+
+    keyroot[0] = '\0';
+    strncat(keyroot, keyname, 8);
+
+    lenroot = strlen(keyroot);
+    if (lenroot == 0 || lenroot > 7)     /*  root must be 1 - 7 chars 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';
+          strncat(keyindex, &card[lenroot], 8-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];
+
+    if (*status > 0)
+        return(*status);
+
+    *nfound = 0;
+    nend = nstart + nmax - 1;
+
+    keyroot[0] = '\0';
+    strncat(keyroot, keyname, 8);
+
+    lenroot = strlen(keyroot);
+    if (lenroot == 0 || lenroot > 7)     /*  root must be 1 - 7 chars 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';
+          strncat(keyindex, &card[lenroot], 8-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.
+*/
+{
+    long dimsize, totalpix = 1;
+    char *loc, *lastloc, message[81];
+    tcolumn *colptr;
+
+    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] = (long) colptr->trepeat; /* default length = repeat */
+    }
+    else
+    {
+        *naxis = 0;
+
+        loc = strchr(tdimstr, '(' );  /* find the opening quote */
+        if (!loc)
+        {
+            sprintf(message, "Illegal TDIM keyword value: %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 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)
+        {
+            sprintf(message, "Illegal TDIM keyword value: %s", tdimstr);
+            return(*status = BAD_TDIM);
+        }
+
+        if ((colptr->tdatatype > 0) && ((long) colptr->trepeat != totalpix))
+        {
+          sprintf(message,
+          "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[81];
+    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)
+        {
+            sprintf(message, "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)
+        {
+            sprintf(message, "Illegal TDIM keyword value: %s", tdimstr);
+            return(*status = BAD_TDIM);
+        }
+
+        if ((colptr->tdatatype > 0) && (colptr->trepeat != totalpix))
+        {
+          sprintf(message,
+          "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[81];
+    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") ) )
+            {
+                sprintf(message,
+                "This is not a TABLE extension: %s", value);
+                ffpmsg(message);
+                return(*status = NOT_ATABLE);
+            }
+    }
+
+    else  /* error: 1st keyword of extension != XTENSION */
+    {
+        sprintf(message,
+        "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)
+    {
+       sprintf(message, "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[81];
+    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") ) )
+            {
+                sprintf(message,
+                "This is not a TABLE extension: %s", value);
+                ffpmsg(message);
+                return(*status = NOT_ATABLE);
+            }
+    }
+
+    else  /* error: 1st keyword of extension != XTENSION */
+    {
+        sprintf(message,
+        "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)
+    {
+       sprintf(message, "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[81];
+    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")
+                 ) )
+            {
+                sprintf(message,
+                "This is not a BINTABLE extension: %s", value);
+                ffpmsg(message);
+                return(*status = NOT_BTABLE);
+            }
+    }
+
+    else  /* error: 1st keyword of extension != XTENSION */
+    {
+        sprintf(message,
+        "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[81];
+    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")
+                 ) )
+            {
+                sprintf(message,
+                "This is not a BINTABLE extension: %s", value);
+                ffpmsg(message);
+                return(*status = NOT_BTABLE);
+            }
+    }
+
+    else  /* error: 1st keyword of extension != XTENSION */
+    {
+        sprintf(message,
+        "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
+        {
+            sprintf(message,
+                   "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 */
+                sprintf(message,
+                   "This is not an IMAGE extension: %s", value);
+                ffpmsg(message);
+            }
+        }
+
+        else  /* error: 1st keyword of extension != XTENSION */
+        {
+            sprintf(message,
+            "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"))
+        {
+            sprintf(message,
+            "Second keyword of the extension is not BITPIX: %s", name);
+            ffpmsg(message);
+            return(*status = NO_BITPIX);
+        }
+
+        if (ffc2ii(value,  &longbitpix, status) > 0)
+        {
+            sprintf(message,
+            "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)
+        {
+            sprintf(message,
+            "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)
+        {
+            sprintf(message,"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 */
+        {
+          sprintf(message,
+              "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;
+
+                sprintf(message,
+                "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;
+
+                sprintf(message,
+                "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;
+
+                sprintf(message,
+                "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 */
+            {
+                sprintf(message,
+                "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 */
+            {
+                sprintf(message,
+                "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;
+
+                sprintf(message,
+                "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)
+        {
+            sprintf(message,
+              "ffgtkn found unexpected keyword or value for keyword no. %d.",
+              numkey);
+            ffpmsg(message);
+
+            sprintf(message,
+              " Expected positive integer keyword %s, but instead", name);
+            ffpmsg(message);
+
+            sprintf(message,
+              " 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)
+        {
+            sprintf(message,
+              "ffgtknjj found unexpected keyword or value for keyword no. %d.",
+              numkey);
+            ffpmsg(message);
+
+            sprintf(message,
+              " Expected positive integer keyword %s, but instead", name);
+            ffpmsg(message);
+
+            sprintf(message,
+              " 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)
+    {
+        sprintf(message,
+          "fftkyn found unexpected keyword or value for keyword no. %d.",
+          numkey);
+        ffpmsg(message);
+
+        sprintf(message,
+          " Expected keyword %s with value %s, but", name, value);
+        ffpmsg(message);
+
+        sprintf(message,
+          " 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 <blank> 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);
+}
diff --git a/cextern/cfitsio/group.c b/cextern/cfitsio/group.c
new file mode 100644
index 0000000..2883e72
--- /dev/null
+++ b/cextern/cfitsio/group.c
@@ -0,0 +1,6463 @@
+/*  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 <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#if defined(WIN32) || defined(__WIN32__)
+#include <direct.h>   /* defines the getcwd function on Windows PCs */
+#endif
+
+#if defined(unix) || defined(__unix__)  || defined(__unix)
+#include <unistd.h>  /* 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(strcasecmp(ttype[i],"MEMBER_POSITION") == 0 ||
+	     strcasecmp(ttype[i],"MEMBER_VERSION")  == 0)
+	    {
+	      sprintf(keyword,"TFORM%d",i+1);
+	      *status = fits_read_key_str(fptr,keyword,keyvalue,comment,
+					  status);
+	 
+	      sprintf(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(strcasecmp(ttype[i],"MEMBER_POSITION") == 0 ||
+	     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);
+	      
+	      sprintf(keyword,"TFORM%d",colnum);
+
+	      *status = fits_read_key_str(gfptr,keyword,keyvalue,comment,
+					  status);
+	 
+	      sprintf(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(strcasecmp(ttype[i],"MEMBER_XTENSION") == 0 ||
+		  strcasecmp(ttype[i],"MEMBER_NAME")     == 0 ||
+		  strcasecmp(ttype[i],"MEMBER_URI_TYPE") == 0 ||
+		  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(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;
+	  sprintf(errstr,"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;
+	  sprintf(errstr,
+		  "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;
+	  sprintf(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
+      */
+
+      sprintf(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;
+	      sprintf(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 */
+
+	  sprintf(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;
+
+	      sprintf(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(strcasecmp(groupAccess1,"file://")  &&
+	                                   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(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(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(strcasecmp(groupAccess1,"file://") == 0 &&
+		                      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)
+	{
+	  sprintf(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 */
+
+		  sprintf(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 */
+
+	  sprintf(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 */
+
+	  sprintf(keyword,"GRPID%d",(int)ngroups);
+	  fits_insert_key_lng(tmpfptr,keyword,groupExtver,
+			      "EXTVER of Group containing this HDU",status);
+
+	  sprintf(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(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)
+    {	  
+      sprintf(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 */
+
+	      sprintf(newKeyword,"GRPID%d",newIndex);
+	      fits_modify_name(mfptr,keyword,newKeyword,status);
+
+	      /* If present, update the GRPLCn keyword index */
+
+	      sprintf(keyword,"GRPLC%d",index);
+	      sprintf(newKeyword,"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(strcasecmp(xtension,"PRIMARY")       == 0) hdutype = IMAGE_HDU; 
+	  else if(strcasecmp(xtension,"IMAGE")    == 0) hdutype = IMAGE_HDU; 
+	  else if(strcasecmp(xtension,"TABLE")    == 0) hdutype = ASCII_TBL; 
+	  else if(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(strcasecmp(uri,"URL") != 0)
+		{
+		  *status = FILE_NOT_OPENED;
+		  sprintf(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(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(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 */
+		  
+		  sprintf(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
+		      */
+		      
+		      sprintf(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
+			  */
+			  
+			  sprintf(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)
+		{
+		  sprintf(keyword,"GRPID%d",found);
+		  *status = fits_delete_key(mfptr,keyword,status);
+		  
+		  sprintf(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(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;
+	      sprintf(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)
+	    {
+	      sprintf(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)
+	    {
+	      sprintf(keyword,"GRPID%d",(int)index);
+	      fits_delete_key(mfptr,keyword,status);
+	      
+	      sprintf(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(strcasecmp(tmpPtr[0],xtension) != 0) continue;
+	}
+	  
+      if(extnameCol  != 0)
+	{
+	  fits_read_col_str(gfptr,extnameCol,i,1,1,nstr,tmpPtr,&dummy,status);
+	  if(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(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(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(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)
+	{
+	  sprintf(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(strcasecmp(keyvalue,"MEMBER_XTENSION") != 0 &&
+	     strcasecmp(keyvalue,"MEMBER_NAME")     != 0 &&
+	     strcasecmp(keyvalue,"MEMBER_VERSION")  != 0 &&
+	     strcasecmp(keyvalue,"MEMBER_POSITION") != 0 &&
+	     strcasecmp(keyvalue,"MEMBER_LOCATION") != 0 &&
+	     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;
+#elif defined(VMS) || defined(vms) || defined(__vms)
+  int i;
+  char *tmpStr;
+#elif defined(macintosh)
+  char *tmpStr;
+#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 = strtok(buff,"/"), outpath[0] = 0;
+                                 tmpStr != NULL; tmpStr = strtok(NULL,"/"))
+    {
+      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 = strtok(buff,"/"), outpath[0] = 0; 
+                                 tmpStr != NULL; tmpStr = strtok(NULL,"/"))
+    {
+
+      if(strcasecmp(tmpStr,"FILE:") == 0)
+	{
+	  /* the next token should contain the DECnet machine name */
+
+	  tmpStr = strtok(NULL,"/");
+	  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 = strtok(buff,"/"), outpath[0] = 0;
+                                 tmpStr != NULL; tmpStr = strtok(NULL,"/"))
+    {
+      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(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(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(strcasecmp(tmpStr3,"memkeep://")      == 0)      
+	{
+	  strcpy(tmpStr3,"mem://");
+	  *tmpStr4 = 0;
+	  *tmpStr2 = 0;
+	  tmpIOstate = 1;
+	}
+
+      /* file residing in shared memory */
+
+      else if(strcasecmp(tmpStr3,"shmem://")        == 0)        
+	{
+	  *tmpStr4   = 0;
+	  *tmpStr2   = 0;
+	  tmpIOstate = 1;
+	}
+      
+      /* file accessed via the ROOT network protocol */
+
+      else if(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(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(strcasecmp(tmpStr3,"httpfile://")     == 0)     
+	{
+	  strcpy(tmpStr1,outfile);
+	  strcpy(tmpStr3,"file://");
+	  strcpy(tmpStr4,"http://");
+	  tmpIOstate = 1;
+	}
+      
+      /* FTP accessd file written locally to disk */
+
+      else if(strcasecmp(tmpStr3,"ftpfile://")      == 0)      
+	{
+	  strcpy(tmpStr1,outfile);
+	  strcpy(tmpStr3,"file://");
+	  strcpy(tmpStr4,"ftp://");
+	  tmpIOstate = 1;
+	}
+      
+      /* file from STDIN written to disk */
+
+      else if(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(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(strcasecmp(tmpStr3,"http://")         == 0)         
+	{
+	  *tmpStr1 = 0;
+	  strcpy(tmpStr3,"mem://");
+	  strcpy(tmpStr4,"http://");
+	  tmpIOstate = 0;
+	}
+      
+      /* HTTP accessed compressed file transferred into memory */
+
+      else if(strcasecmp(tmpStr3,"httpcompress://") == 0) 
+	{
+	  *tmpStr1 = 0;
+	  strcpy(tmpStr3,"mem://");
+	  strcpy(tmpStr4,"http://");
+	  tmpIOstate = 0;
+	}
+      
+      /* FTP accessed file transferred into memory */
+      
+      else if(strcasecmp(tmpStr3,"ftp://")          == 0)          
+	{
+	  *tmpStr1 = 0;
+	  strcpy(tmpStr3,"mem://");
+	  strcpy(tmpStr4,"ftp://");
+	  tmpIOstate = 0;
+	}
+      
+      /* FTP accessed compressed file transferred into memory */
+
+      else if(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(strcasecmp(tmpStr3,"stdin://")        == 0)        
+	{
+	  *status = URL_PARSE_ERROR;
+	  ffpmsg("cannot make vaild URL from stdin:// (fits_get_url)");
+	  *tmpStr1 = *tmpStr2 = 0;
+	}
+
+      else if(strcasecmp(tmpStr3,"stdout://")       == 0)       
+	{
+	  *status = URL_PARSE_ERROR;
+	  ffpmsg("cannot make vaild URL from stdout:// (fits_get_url)");
+	  *tmpStr1 = *tmpStr2 = 0;
+	}
+
+      else if(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;
+
+  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 = strtok(inURL, "/"); /* 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 = strtok(NULL, "/"); /* 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(strncasecmp(tmpStr,"MEM:",4)   == 0 ||
+                	                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 <URL: http://www.w3.org>
+     */
+{
+  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 <URL: http://www.w3.org>
+     */
+
+{
+    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);
+    }
+}
diff --git a/cextern/cfitsio/group.h b/cextern/cfitsio/group.h
new file mode 100644
index 0000000..f7aae5b
--- /dev/null
+++ b/cextern/cfitsio/group.h
@@ -0,0 +1,65 @@
+#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);
+
diff --git a/cextern/cfitsio/grparser.c b/cextern/cfitsio/grparser.c
new file mode 100644
index 0000000..a5091ea
--- /dev/null
+++ b/cextern/cfitsio/grparser.c
@@ -0,0 +1,1379 @@
+/*		T E M P L A T E   P A R S E R
+		=============================
+
+		by Jerzy.Borkowski at 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 <string.h> 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 <stdio.h>
+#include <stdlib.h>
+
+#ifdef sparc
+#include <malloc.h>
+#include <memory.h>
+#endif
+
+#include <string.h>
+#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<ngp_extver_tab_size; i++)
+    { if (0 == strcmp(extname, ngp_extver_tab[i].extname))
+        { *version = (++ngp_extver_tab[i].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;
+   *version = ngp_extver_tab[ngp_extver_tab_size].version = 1;
+
+   ngp_extver_tab_size++;
+
+   return(NGP_OK);
+ }
+
+int	ngp_set_extver(char *extname, int version)
+ { NGP_EXTVER_TAB *p;
+   char 	*p2;
+   int		i;
+
+   if (NULL == extname) 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<ngp_extver_tab_size; i++)
+    { if (0 == strcmp(extname, ngp_extver_tab[i].extname))
+        { if (version > 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<ngp_extver_tab_size; i++)
+    { if (NULL != ngp_extver_tab[i].extname)
+        { ngp_free(ngp_extver_tab[i].extname);
+          ngp_extver_tab[i].extname = NULL;
+        }
+      ngp_extver_tab[i].version = 0;
+    }
+   ngp_free(ngp_extver_tab);
+   ngp_extver_tab = NULL;
+   ngp_extver_tab_size = 0;
+   return(NGP_OK);
+ }
+
+	/* compare strings, case does not matter */
+
+int	ngp_strcasecmp(char *p1, char *p2)
+ { char c1, c2;
+
+   for (;;)
+    {
+      c1 = *p1;
+      if ((c1 >= 'a') && (c1 <= 'z')) c1 += ('A' - 'a');
+
+      c2 = *p2;
+      if ((c2 >= 'a') && (c2 <= 'z')) c2 += ('A' - 'a');
+
+      if (c1 < c2) return(-1);
+      if (c1 > c2) return(1);
+      if (0 == c1) return(0);
+      p1++;
+      p2++;
+    }
+ }
+
+int	ngp_strcasencmp(char *p1, char *p2, int n)
+ { char c1, c2;
+   int ii;
+
+   for (ii=0;ii<n;ii++)
+    {
+      c1 = *p1;
+      if ((c1 >= 'a') && (c1 <= 'z')) c1 += ('A' - 'a');
+
+      c2 = *p2;
+      if ((c2 >= 'a') && (c2 <= 'z')) c2 += ('A' - 'a');
+
+      if (c1 < c2) return(-1);
+      if (c1 > c2) return(1);
+      if (0 == c1) return(0);
+      p1++;
+      p2++;
+    }
+    return(0);
+ }
+
+	/* read one line from file */
+
+int	ngp_line_from_file(FILE *fp, char **p)
+ { int	c, r, llen, allocsize, alen;
+   char	*p2;
+
+   if (NULL == fp) return(NGP_NUL_PTR);		/* check for stupid args */
+   if (NULL == p) return(NGP_NUL_PTR);		/* more foolproof checks */
+   
+   r = NGP_OK;					/* initialize stuff, reset err code */
+   llen = 0;					/* 0 characters read so far */
+   *p = (char *)ngp_alloc(1);			/* preallocate 1 byte */
+   allocsize = 1;				/* signal that we have allocated 1 byte */
+   if (NULL == *p) return(NGP_NO_MEMORY);	/* if this failed, system is in dire straits */
+
+   for (;;)
+    { c = getc(fp);				/* get next character */
+      if ('\r' == c) continue;			/* carriage return character ?  Just ignore it */
+      if (EOF == c)				/* EOF signalled ? */
+        { 
+          if (ferror(fp)) r = NGP_READ_ERR;	/* was it real error or simply EOF ? */
+	  if (0 == llen) return(NGP_EOF);	/* signal EOF only if 0 characters read so far */
+          break;
+        }
+      if ('\n' == c) break;			/* end of line character ? */
+      
+      llen++;					/* we have new character, make room for it */
+      alen = ((llen + NGP_ALLOCCHUNK) / NGP_ALLOCCHUNK) * NGP_ALLOCCHUNK;
+      if (alen > 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( 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 ((!ngp_strcasecmp("HISTORY", cl->name))
+    || (!ngp_strcasecmp("COMMENT", cl->name))
+    || (!ngp_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 (!ngp_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];
+
+   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 = strtok(envfiles, ":"); NULL != p2; p2 = strtok(NULL, ":"))
+            {
+	      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 ((!ngp_strcasecmp("T", ngp_curline.value)) || (!ngp_strcasecmp("F", ngp_curline.value)))
+                { ngp_linkey.type = NGP_TTYPE_BOOL;
+                  ngp_linkey.value.b = (ngp_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; i<ngph->tokcnt; 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;
+			  }
+			sprintf(buf, "%-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; i<ngph->tokcnt; 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; j<NGP_MAX_ARRAY_DIM; j++)	/* 0 for table, 6 for group */
+    { 
+      my_tform = NULL;
+      my_ttype = "";
+    
+      for (i=0; ; i++)
+       { if (1 == sscanf(ngph->tok[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++;
+			          }
+			        sprintf(ngp_linkey.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<NGP_MAX_ARRAY_DIM; i++) ngph_size[i] = 0;
+       ngph_dim = 0;
+
+       for (i=0; i<ngph.tokcnt; i++)
+        { if (!strcmp("XTENSION", ngph.tok[i].name))
+            { if (NGP_TTYPE_STRING == ngph.tok[i].type)
+                { if (!ngp_strcasencmp("BINTABLE", ngph.tok[i].value.s,8)) ngph_node_type = NGP_NODE_BTABLE;
+                  if (!ngp_strcasencmp("TABLE", ngph.tok[i].value.s,5)) ngph_node_type = NGP_NODE_ATABLE;
+                  if (!ngp_strcasencmp("IMAGE", ngph.tok[i].value.s,5)) ngph_node_type = NGP_NODE_IMAGE;
+                }
+            }
+          else if (!strcmp("SIMPLE", ngph.tok[i].name))
+            { if (NGP_TTYPE_BOOL == ngph.tok[i].type)
+                { if (ngph.tok[i].value.b) ngph_node_type = NGP_NODE_IMAGE;
+                }
+            }
+          else if (!strcmp("BITPIX", ngph.tok[i].name))
+            { if (NGP_TTYPE_INT == ngph.tok[i].type)  ngph_bitpix = ngph.tok[i].value.i;
+            }
+          else if (!strcmp("NAXIS", ngph.tok[i].name))
+            { if (NGP_TTYPE_INT == ngph.tok[i].type)  ngph_dim = ngph.tok[i].value.i;
+            }
+          else if (!strcmp("EXTNAME", ngph.tok[i].name))	/* assign EXTNAME, I hope struct does not move */
+            { if (NGP_TTYPE_STRING == ngph.tok[i].type)  ngph_extname = ngph.tok[i].value.s;
+            }
+          else if (1 == sscanf(ngph.tok[i].name, "NAXIS%d%c", &j, &ngph_ctmp))
+            { if (NGP_TTYPE_INT == ngph.tok[i].type)
+		if ((j>=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
+			  { sprintf(grnm, "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++;
+			          }
+			        sprintf(ngp_linkey.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
+			  { sprintf(grnm, "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);
+ }
diff --git a/cextern/cfitsio/grparser.h b/cextern/cfitsio/grparser.h
new file mode 100644
index 0000000..56bdea0
--- /dev/null
+++ b/cextern/cfitsio/grparser.h
@@ -0,0 +1,185 @@
+/*		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 at 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_strcasecmp(char *p1, char *p2);
+int	ngp_strcasencmp(char *p1, char *p2, int n);
+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
diff --git a/cextern/cfitsio/histo.c b/cextern/cfitsio/histo.c
new file mode 100644
index 0000000..6af856f
--- /dev/null
+++ b/cextern/cfitsio/histo.c
@@ -0,0 +1,2221 @@
+/*   Globally defined histogram parameters */
+#include <string.h>
+#include <ctype.h>
+#include <math.h>
+#include <stdlib.h>
+#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);
+}
+/*--------------------------------------------------------------------------*/
+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);
+}
+
diff --git a/cextern/cfitsio/imcompress.c b/cextern/cfitsio/imcompress.c
new file mode 100644
index 0000000..6330bf8
--- /dev/null
+++ b/cextern/cfitsio/imcompress.c
@@ -0,0 +1,9247 @@
+# include <stdio.h>
+# include <stdlib.h>
+# include <string.h>
+# include <math.h>
+# include <ctype.h>
+# include <time.h>
+# include "fitsio2.h"
+
+#define NULL_VALUE -2147483647 /* value used to represent undefined 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][60];
+float trans_ratio[999];
+
+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 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 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 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 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 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 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_gzip_heap(fitsfile *infptr, fitsfile *outfptr, 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_gunzip_heap(fitsfile *infptr, fitsfile *outfptr, int *status);
+
+/*---------------------------------------------------------------------------*/
+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.
+*/
+    (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;
+        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)->quantize_level = NO_QUANTIZE;
+    } else {
+
+        (fptr->Fptr)->quantize_level = qlevel;
+
+    }
+    return(*status);
+}
+/*--------------------------------------------------------------------------*/
+int fits_set_quantize_dither(fitsfile *fptr,  /* I - FITS file pointer   */
+           int dither,        /* dither type      */
+           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
+   used the default  SUBTRACTIVE_DITHER_1 (which is equivalent to dither = 1).
+   A value of -1 means do not apply any dither.
+*/
+
+    if (dither == 0) dither = 1;
+    (fptr->Fptr)->request_quantize_dither = dither;
+    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                */
+{
+/*
+   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 (offset > 0)
+       (fptr->Fptr)->request_dither_offset = ((offset - 1) % 10000 ) + 1; 
+    else
+       (fptr->Fptr)->request_dither_offset = offset; 
+
+    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;
+        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 that
+  The image is
+   divided into tiles, and each tile is compressed and stored in a row
+   of at variable length binary table column.
+*/
+    (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 that
+  The image is
+   divided into tiles, and each tile is compressed and stored in a row
+   of at variable length binary table column.
+*/
+
+    (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_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;
+    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;
+        return(*status);
+    }
+
+    for (ii = 0; ii < ndim; ii++)
+    {
+        dims[ii] = (fptr->Fptr)->request_tilesize[ii];
+    }
+
+    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)->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)->quantize_level == NO_QUANTIZE) {
+      *qlevel = 0;
+    } else {
+      *qlevel = (fptr->Fptr)->quantize_level;
+    }
+
+    return(*status);
+}
+/*--------------------------------------------------------------------------*/
+int fits_get_dither_offset(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_offset;
+    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];
+
+    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);
+    }
+
+    /* 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);
+
+    return (*status);
+}
+/*--------------------------------------------------------------------------*/
+int fits_compress_img_OBSOLETE(fitsfile *infptr, /* pointer to image to be compressed */
+                 fitsfile *outfptr, /* empty HDU for output compressed image */
+                 int compress_type, /* compression type code               */
+                                    /*  RICE_1, HCOMPRESS_1, etc.          */
+                 long *intilesize,    /* size in each dimension of the tiles */
+                                    /* NULL pointer means tile by rows */
+		 int blocksize,     /* compression parameter: blocksize  */
+                 int nbits,         /* compression parameter: nbits  */
+                 int *status)       /* IO - error status               */
+
+/*
+  !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!!
+   This routine is obsolete and should not be used.  The 
+   ftools 'fimgzip' task used to call this routine (but that task has been deleted); 
+
+  The name of the routine was changed 4/27/2011, to see if anyone complains.
+  If not, then this routine should be deleted from the source code.
+  !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!!
+  
+   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.
+*/
+{
+    int bitpix, naxis;
+    long naxes[MAX_COMPRESS_DIM];
+
+    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);
+    }
+
+    /* 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_imheader(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 */
+    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);
+
+    /* 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);
+
+    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 */
+    
+    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)->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);
+       }
+    }
+    
+    /* 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] == 0) ){
+	     
+	    /* 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] == 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 (actual_tilesize[ii] <= 0) {
+	    /* tile size of 0 means use the image size of that dimension */
+            actual_tilesize[ii] = naxes[ii];
+	}
+    }
+
+    /* ---- set up array of TFORM strings -------------------------------*/
+    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)->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 */
+       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);
+    }
+
+    /* 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  */
+	   
+        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++)
+        {
+            sprintf (keyname, "ZNAXIS%d", ii+1);
+            ffpkyj (outfptr, keyname, naxes[ii],
+			"length of original image axis", status);
+        }
+    }
+                      
+    for (ii = 0;  ii < naxis;  ii++)
+    {
+        sprintf (keyname, "ZTILE%d", ii+1);
+        ffpkyj (outfptr, keyname, actual_tilesize[ii],
+			"size of tiles to be compressed", status);
+    }
+
+    if (bitpix < 0) {
+       
+	if ((outfptr->Fptr)->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_dither = -1, use dithering by default */
+	    /* when quantizing floating point images. */
+	
+	    if ( (outfptr->Fptr)->request_quantize_dither == 0) 
+              (outfptr->Fptr)->request_quantize_dither = SUBTRACTIVE_DITHER_1;
+       
+	    if ((outfptr->Fptr)->request_quantize_dither == 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_offset), 
+	       "dithering offset when quantizing floats", 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 */
+    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)) {
+         ffpmsg("Lossless compression of floating point images must use GZIP");
+         return(*status = DATA_COMPRESSION_ERR);
+       }
+    }
+
+    /* free the previously saved tile if the input tile is for the same row */
+    if ((outfptr->Fptr)->tilerow == row) {
+        if ((outfptr->Fptr)->tiledata) {
+            free((outfptr->Fptr)->tiledata);
+        }
+	  
+        if ((outfptr->Fptr)->tilenullarray) {
+            free((outfptr->Fptr)->tilenullarray);
+        }
+
+        (outfptr->Fptr)->tiledata = 0;
+        (outfptr->Fptr)->tilenullarray = 0;
+        (outfptr->Fptr)->tilerow = 0;
+        (outfptr->Fptr)->tiledatasize = 0;
+        (outfptr->Fptr)->tiletype = 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 */
+                lldata = (LONGLONG *) idata;
+		
+                for (ii = tilelen - 1; ii >= 0; ii--) {
+		    lldata[ii] = idata[ii];
+		}
+
+                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) {
+                 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 = 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 if (datatype == TDOUBLE) {
+
+               /* allocate buffer for the compressed tile bytes */
+	       /* make it 10% larger than the original uncompressed data */
+               clen = 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, "1PE");
+        } 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 */
+               for (ii = tilelen - 1; ii >= 0; ii--) 
+                   idata[ii] = (int) sbuff[ii];
+           }
+       } 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 */
+               for (ii = tilelen - 1; ii >= 0; ii--) 
+                   idata[ii] = (int) sbuff[ii] + 32768;
+             }
+           } 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 */
+               for (ii = tilelen - 1; ii >= 0; ii--) 
+                   idata[ii] = (int) sbuff[ii];
+             }
+           }
+        }
+        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 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 */
+               for (ii = tilelen - 1; ii >= 0; ii--)
+		       idata[ii] = ((int) usbuff[ii]) - 32768;
+           }
+        }
+
+        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*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.  */
+
+    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 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.  */
+
+    int flagval, *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 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.  */
+
+    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 */
+               for (ii = tilelen - 1; ii >= 0; ii--) 
+                   idata[ii] = (int) usbbuff[ii];
+           }
+       }
+
+       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*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.  */
+
+    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 */
+               for (ii = tilelen - 1; ii >= 0; ii--) 
+                   idata[ii] = ((int) sbbuff[ii]) + 128;
+           }
+       }
+ 
+       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 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.  */
+
+    int flagval, *idata;
+    long irow, ii;
+    float floatnull;
+    unsigned char *usbbuff;
+    unsigned long dithersum;
+    int iminval = 0, imaxval = 0;  /* min and max quantized integers */
+
+           *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_dither == SUBTRACTIVE_DITHER_1) {
+	      
+	          /* see if the dithering offset value needs to be initialized */                  
+	          if ((outfptr->Fptr)->request_dither_offset == 0 && (outfptr->Fptr)->dither_offset == 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_offset */
+		     /* 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_offset = 
+		       (( (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_offset), 
+	                        NULL, status);
+
+	          } else if ((outfptr->Fptr)->request_dither_offset < 0 && (outfptr->Fptr)->dither_offset < 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_offset = ((int) (dithersum % 10000)) + 1;
+		
+                     /* update the header keyword with this new value */
+		     fits_update_key(outfptr, TINT, "ZDITHER0", &((outfptr->Fptr)->dither_offset), 
+	                        NULL, status);
+		  }
+
+                  /* subtract 1 to convert from 1-based to 0-based element number */
+	          irow = row + (outfptr->Fptr)->dither_offset - 1; /* dither the quantized values */
+
+	      } else {
+	          irow = 0;  /* do not dither the quantized values */
+              }
+	      
+              *flag = fits_quantize_float (irow, (float *) tiledata, tilenx, tileny,
+                   nullcheck, floatnull, (outfptr->Fptr)->quantize_level, 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 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.  */
+
+    int flagval, *idata;
+    long irow, ii;
+    double doublenull;
+    unsigned char *usbbuff;
+    unsigned long dithersum;
+    int iminval = 0, imaxval = 0;  /* min and max quantized integers */
+
+           *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_dither == SUBTRACTIVE_DITHER_1) {
+
+	          /* see if the dithering offset value needs to be initialized (see above) */                  
+	          if ((outfptr->Fptr)->request_dither_offset == 0 && (outfptr->Fptr)->dither_offset == 0) {
+
+		     (outfptr->Fptr)->dither_offset = 
+		       (( (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_offset), 
+	                        NULL, status);
+
+	          } else if ((outfptr->Fptr)->request_dither_offset < 0 && (outfptr->Fptr)->dither_offset < 0) {
+
+		     usbbuff = (unsigned char *) tiledata;
+		     dithersum = 0;
+		     for (ii = 0; ii < 8 * tilelen; ii++) {
+		         dithersum += usbbuff[ii];
+	             }
+		     (outfptr->Fptr)->dither_offset = ((int) (dithersum % 10000)) + 1;
+		
+                     /* update the header keyword with this new value */
+		     fits_update_key(outfptr, TINT, "ZDITHER0", &((outfptr->Fptr)->dither_offset), 
+	                        NULL, status);
+		  }
+
+	          irow = row + (outfptr->Fptr)->dither_offset - 1; /* dither the quantized values */
+
+	      } else {
+	          irow = 0;  /* do not dither the quantized values */
+	      }
+
+            *flag = fits_quantize_double (irow, (double *) tiledata, tilenx, tileny,
+               nullcheck, doublenull, (outfptr->Fptr)->quantize_level, 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 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];
+    int ii, i5, i4, i3, i2, i1, i0, ndim, irow, 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, datatype = 0, 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.
+*/
+{
+    int 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];
+    int ii, i5, i4, i3, i2, i1, i0, ndim, irow, 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]);
+*/   
+              /* 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.
+*/
+{
+    int 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];
+    int ii, i5, i4, i3, i2, i1, i0, ndim, irow, pixlen, tilenul;
+    void *buffer;
+    char *bnullarray = 0;
+    double testnullval = 0.;
+    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);
+    }
+
+    /* 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);
+    }
+
+    /* 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") )
+        (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_dither = 0;
+    } else {
+        if (!FSTRCMP(value, "NONE") )
+            (infptr->Fptr)->quantize_level = NO_QUANTIZE;
+        else if (!FSTRCMP(value, "SUBTRACTIVE_DITHER_1") )
+            (infptr->Fptr)->quantize_dither = SUBTRACTIVE_DITHER_1;
+        else
+            (infptr->Fptr)->quantize_dither = 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_offset = 1;  
+    } else {
+        (infptr->Fptr)->dither_offset = 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 */
+        sprintf (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 */
+	sprintf (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;
+    }
+
+    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);
+
+	fits_write_history(outfptr, 
+	    "Image was compressed by CFITSIO using scaled integer quantization:", status);
+	sprintf(card2, "  q = %f / quantized level scaling parameter", 
+	    (outfptr->Fptr)->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",  "-"       },
+			   {"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;          /* 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;
+    float fnulval=0;
+    float *tempfloat = 0;
+    double dnulval=0;
+    double bscale, bzero, actual_bzero, dummy = 0;    /* scaling parameters */
+    long nelem = 0, offset = 0, tilesize;      /* number of bytes */
+    int smooth, nx, ny, scale;  /* hcompress parameters */
+
+    if (*status > 0)
+       return(*status);
+
+    /* **************************************************************** */
+    /* check if this tile was cached; if so, just copy it out */
+    if (nrow == (infptr->Fptr)->tilerow && datatype == (infptr->Fptr)->tiletype ) {
+
+         memcpy(buffer, (infptr->Fptr)->tiledata, (infptr->Fptr)->tiledatasize);
+	 
+	 if (nullcheck == 2)
+             memcpy(bnullarray, (infptr->Fptr)->tilenullarray, tilelen);
+
+         *anynul = (infptr->Fptr)->tileanynull;
+         return(*status);
+    }
+
+    /* **************************************************************** */
+    /* get length of the compressed byte stream */
+    ffgdes (infptr, (infptr->Fptr)->cn_compressed, nrow, &nelem, &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 (nelem == 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 */   
+            ffgdes (infptr, (infptr->Fptr)->cn_uncompressed, nrow, &nelem,
+               &offset, status);
+
+            if (nelem == 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, nelem, 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, nelem, 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 */   
+
+            ffgdes (infptr, (infptr->Fptr)->cn_gzip_data, nrow, &nelem,
+               &offset, status);
+
+            if (nelem == 0 && offset == 0) /* this should never happen */
+	        return (*status = NO_COMPRESSED_TILE);
+
+	    /* allocate memory for the compressed tile of data */
+            cbuf = (unsigned char *) malloc (nelem);  
+            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, nelem, &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, nelem,
+                     (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, nelem,
+                  (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 (nelem * sizeof (short));
+    } else {
+        cbuf = (unsigned char *) malloc (nelem);
+    }
+    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, nelem, &snull, (short *) cbuf, NULL, status);
+    } else {
+       fits_read_col(infptr, TBYTE, (infptr->Fptr)->cn_compressed, nrow,
+             1, nelem, &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, nelem, (unsigned char *)idata,
+                        tilelen, blocksize);
+            tiledatatype = TBYTE;
+        } else if ((infptr->Fptr)->rice_bytepix == 2 ) {
+            *status = fits_rdecomp_short (cbuf, nelem, (unsigned short *)idata,
+                        tilelen, blocksize);
+            tiledatatype = TSHORT;
+        } else {
+            *status = fits_rdecomp (cbuf, nelem, (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, nelem,
+             (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) nelem, 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 &&
+	    bzero == 0. && actual_bzero == 32768.) {
+	    /* special case where unsigned 16-bit integers have been */
+	    /* offset by +32768 when using PLIO */
+            fffi4i2(idata, tilelen, bscale, -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);
+          }
+        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)
+          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)
+          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_dither == SUBTRACTIVE_DITHER_1) {
+
+         /* use the new dithering algorithm (introduced in July 2009) */
+
+         if (tiledatatype == TINT)
+          unquantize_i4r4(nrow + (infptr->Fptr)->dither_offset - 1, idata, 
+	   tilelen, bscale, bzero, nullcheck, tnull,
+           fnulval, bnullarray, anynul,
+            (float *) buffer, status);
+         else if (tiledatatype == TSHORT)
+          unquantize_i2r4(nrow + (infptr->Fptr)->dither_offset - 1, (short *)idata, 
+	   tilelen, bscale, bzero, nullcheck, (short) tnull,
+           fnulval, bnullarray, anynul,
+            (float *) buffer, status);
+         else if (tiledatatype == TBYTE)
+          unquantize_i1r4(nrow + (infptr->Fptr)->dither_offset - 1, (unsigned char *)idata, 
+	   tilelen, bscale, bzero, nullcheck, (unsigned char) tnull,
+           fnulval, bnullarray, anynul,
+            (float *) buffer, status);
+
+        } else {  /* use the old "round to nearest level" quantization algorithm */
+
+         if (tiledatatype == TINT)
+          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_dither == SUBTRACTIVE_DITHER_1) {
+
+         /* use the new dithering algorithm (introduced in July 2009) */
+         if (tiledatatype == TINT)
+          unquantize_i4r8(nrow + (infptr->Fptr)->dither_offset - 1, idata,
+	   tilelen, bscale, bzero, nullcheck, tnull,
+           dnulval, bnullarray, anynul,
+            (double *) buffer, status);
+         else if (tiledatatype == TSHORT)
+          unquantize_i2r8(nrow + (infptr->Fptr)->dither_offset - 1, (short *)idata,
+	   tilelen, bscale, bzero, nullcheck, (short) tnull,
+           dnulval, bnullarray, anynul,
+            (double *) buffer, status);
+         else if (tiledatatype == TBYTE)
+          unquantize_i1r8(nrow + (infptr->Fptr)->dither_offset - 1, (unsigned char *)idata,
+	   tilelen, bscale, bzero, nullcheck, (unsigned char) tnull,
+           dnulval, bnullarray, anynul,
+            (double *) buffer, status);
+
+        } else {  /* use the old "round to nearest level" quantization algorithm */
+
+         if (tiledatatype == TINT)
+          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)
+          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)
+          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)
+          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)->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 ||
+        datatype != (infptr->Fptr)->tiletype )  {
+
+        if ((infptr->Fptr)->tiledata) {
+            free((infptr->Fptr)->tiledata);	    
+        }
+	
+        (infptr->Fptr)->tiledata = 0;
+
+        if ((infptr->Fptr)->tilenullarray) {
+            free((infptr->Fptr)->tilenullarray);
+        }
+	
+        (infptr->Fptr)->tilenullarray = 0;
+        (infptr->Fptr)->tilerow = 0;
+        (infptr->Fptr)->tiledatasize = 0;
+        (infptr->Fptr)->tiletype = 0;
+
+        /* allocate new array(s) */
+	(infptr->Fptr)->tiledata = malloc(tilesize);
+	if ((infptr->Fptr)->tiledata == 0)
+	   return (*status);
+
+        if (nullcheck == 2) {  /* also need array of null pixel flags */
+	    (infptr->Fptr)->tilenullarray = malloc(tilelen);
+	    if ((infptr->Fptr)->tilenullarray == 0)
+	        return (*status);
+        }
+
+        (infptr->Fptr)->tiledatasize = tilesize;
+        (infptr->Fptr)->tiletype = datatype;
+      }
+
+      /* copy the tile array(s) into cache buffer */
+      memcpy((infptr->Fptr)->tiledata, buffer, tilesize);
+
+      if (nullcheck == 2) {
+	    if ((infptr->Fptr)->tilenullarray == 0)  {
+       	      (infptr->Fptr)->tilenullarray = malloc(tilelen);
+            }
+            memcpy((infptr->Fptr)->tilenullarray, bnullarray, tilelen);
+      }
+
+      (infptr->Fptr)->tilerow = nrow;
+      (infptr->Fptr)->tileanynull = *anynul;
+    }
+
+    return (*status);
+}
+/*--------------------------------------------------------------------------*/
+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 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++)
+            {
+                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
+                {
+                    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 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++)
+            {
+                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
+                {
+                    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 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++)
+            {
+                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
+                {
+                    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 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++)
+            {
+                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
+                {
+                    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 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++)
+            {
+                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
+                {
+                    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 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++)
+            {
+                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
+                {
+                    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);
+}
+/*--------------------------------------------------------------------------*/
+int fits_transpose_table(fitsfile *infptr, fitsfile *outfptr, int *status)
+
+/*
+  Transpose the elements in the input table columns from row-major order into
+  column-major order, and write to the output table (which may be the same as
+  the input table).   For example, a table with 10000 rows and 2 '1I' columns
+  will be transformed into a 1 row table with 2 '10000I' columns.
+  
+  In addition, compress each column of data and write as a 1-row variable length
+  array column.
+*/
+{ 
+    LONGLONG nrows, incolwidth[999], inrepeat[999], outcolstart[1000], outbytespan[999];
+    LONGLONG headstart, datastart, dataend, startbyte, jj, kk, naxis1;
+    long repeat, width, pcount;
+    int ii, ncols, coltype, hdutype, ltrue = 1;
+    char *buffer, *cptr, keyname[9], tform[40], colcode[999], colname[999][50];
+    char comm[FLEN_COMMENT], *compressed_data;
+    size_t dlen, datasize;
+    float cratio[999];
+    
+    if (*status > 0)
+        return(*status);
+    
+    fits_get_hdu_type(infptr, &hdutype, status);
+    if (hdutype != BINARY_TBL) {
+        *status = NOT_BTABLE;
+        return(*status);
+    }
+        
+    fits_get_num_rowsll(infptr, &nrows, status);
+    fits_get_num_cols(infptr, &ncols, status);
+    fits_read_key(infptr, TLONGLONG, "NAXIS1", &naxis1, NULL, status);
+    if (*status > 0)
+        return(*status);
+
+    if (nrows < 1  || ncols < 1) {
+	/* just copy the HDU if the table has 0 columns or rows */
+	if (infptr != outfptr) {  /* copy input header to the output */
+		fits_copy_hdu (infptr, outfptr, 0, status);
+	}
+	return(*status);
+    }
+ 
+    /* allocate space for the transposed table */
+    buffer = calloc((size_t) naxis1, (size_t) nrows);
+    if (!buffer) {
+        ffpmsg("Could not allocate buffer for transformed table");
+        *status = MEMORY_ALLOCATION;
+        return(*status);
+    }
+
+    if (infptr != outfptr) {  /* copy input header to the output */
+	fits_copy_header(infptr, outfptr, status);
+    }
+
+    outcolstart[0] = 0;
+ 
+    /* do initial setup for each column */
+    for (ii = 0; ii < ncols; ii++) {
+
+	/* get the column name */
+	fits_make_keyn("TTYPE", ii+1, keyname, status);
+	fits_read_key(outfptr, TSTRING, keyname, colname[ii], comm, status);
+
+	/* get the column type, repeat count, and unit width */
+	fits_make_keyn("TFORM", ii+1, keyname, status);
+	fits_read_key(outfptr, TSTRING, keyname, tform, comm, status);
+
+	/* preserve the original TFORM value and comment string */
+	keyname[0] = 'Z';
+	fits_write_key(outfptr, TSTRING, keyname, tform, comm, status);
+	keyname[0] = 'T';
+ 
+        fits_binary_tform(tform, &coltype, &repeat, &width, status);
+
+   	/* BIT columns are a difficult case */
+	 /* round up to a multiple of 8 bits */
+/*
+	if (coltype == TBIT) {  
+	    repeat = (repeat + 7) / 8 * 8; 
+	}
+*/
+
+	cptr = tform;
+	while(isdigit(*cptr)) cptr++;
+	colcode[ii] = *cptr; /* save the column type code */
+
+        /* all columns are now VLAs */
+	fits_modify_key_str(outfptr, keyname, "1PB", "&", status);
+
+	if (coltype == TBIT) {
+	    repeat = (repeat + 7) / 8;  /* convert from bits to bytes */
+	} else if (coltype == TSTRING) {
+	    width = 1;  /* ignore the optional 'w' in 'rAw' format */
+	} else if (coltype < 0) {  /* pointer to variable length array */
+	    width = 8;
+	    if (colcode[ii] == 'Q') width = 16;  /* this is a 'Q' not a 'P' column */
+	    repeat = 1;
+	}
+
+	inrepeat[ii] = repeat;
+	
+	/* width (in bytes) of each element and field in the INPUT row-major table */
+	incolwidth[ii] = repeat * width;
+	
+	/* starting offset of each field in the OUTPUT column-major table */
+	outcolstart[ii + 1] = outcolstart[ii] + incolwidth[ii] * nrows;
+
+	/* length of each sequence of bytes, after sorting them in signicant order */
+	outbytespan[ii] = (incolwidth[ii] * nrows) / width;
+    }
+
+    /* the transformed table has only 1 row */
+    /* output table width 8 bytes per column */
+    fits_modify_key_lng(outfptr, "NAXIS2", 1, "&", status);
+    fits_modify_key_lng(outfptr, "NAXIS1", ncols * 8, "&", status);
+
+    /* move to the start of the input table */
+    fits_get_hduaddrll(infptr, &headstart, &datastart, &dataend, status);
+    ffmbyt(infptr, datastart, 0, status);
+
+    /* now transpose the table into an array in memory */
+    for (jj = 0; jj < nrows; jj++)   {    /* loop over rows */
+      for (ii = 0; ii < ncols; ii++) {  /* loop over columns */
+      
+	kk = 0;	
+
+	    cptr = buffer + (outcolstart[ii] + (jj * incolwidth[ii]));   /* addr to copy to */
+
+	    startbyte = (infptr->Fptr)->bytepos;  /* save the starting byte location */
+
+	    ffgbyt(infptr, incolwidth[ii], cptr, status);  /* copy all the bytes */
+
+	    if (incolwidth[ii] >= MINDIRECT) { /* have to explicitly move to next byte */
+		ffmbyt(infptr, startbyte + incolwidth[ii], 0, status);
+	    }
+      }
+    }
+
+    fits_set_hdustruc(outfptr, status);
+    
+    /* now compress each column with GZIP and write out to output table */
+    for (ii = 0; ii < ncols; ii++) {  /* loop over columns */
+
+	datasize = (size_t) (outcolstart[ii + 1] - outcolstart[ii]);
+
+	/* allocate memory for the compressed data */
+	compressed_data = malloc(datasize);
+	if (!compressed_data) {
+            ffpmsg("data memory allocation error");
+	    return(-1);
+	}
+
+	/* gzip compress the data */
+	compress2mem_from_mem(buffer + outcolstart[ii], datasize,
+	    &compressed_data,  &datasize, realloc, 
+	    &dlen, 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, 1, 1, dlen, compressed_data, status);
+
+        cratio[ii] = (float) datasize / (float) dlen;	
+	free(compressed_data);   /* don't need the compressed data any more */
+	
+	sprintf(results[ii]," %3d %10.10s %4d %c  %5.2f", ii+1, colname[ii], (int) inrepeat[ii],colcode[ii],cratio[ii]);
+	trans_ratio[ii] = cratio[ii];
+    }
+
+    /* save the original PCOUNT value */
+    fits_read_key(infptr, TLONG, "PCOUNT", &pcount, comm, status);
+    fits_write_key(outfptr, TLONG, "ZPCOUNT", &pcount, comm, status);
+
+    fits_write_key(outfptr, TLONGLONG, "ZNAXIS1", &naxis1, "original rows width",
+	status);
+    fits_write_key(outfptr, TLONGLONG, "ZNAXIS2", &nrows, "original number of rows",
+	status);
+
+    fits_write_key(outfptr, TLOGICAL, "TVIRTUAL", &ltrue, 
+        "this is a virtual table", status);
+    fits_write_key(outfptr, TSTRING, "ZMETHOD", "TRANSPOSED_SHUFFLED_GZIP",
+	   "table compression method", status);
+
+    fits_set_hdustruc(outfptr, status);
+
+    /* copy the heap from input to output file */
+    fits_gzip_heap(infptr, outfptr, status);
+       	
+    free(buffer);
+    return(*status);
+}
+/*--------------------------------------------------------------------------*/
+int fits_compress_table_rice(fitsfile *infptr, fitsfile *outfptr, int *status)
+
+/*
+  Transpose the elements in the input table columns from row-major order into
+  column-major order, and write to the output table (which may be the same as
+  the input table).   For example, a table with 10000 rows and 2 '1I' columns
+  will be transformed into a 1 row table with 2 '10000I' columns.
+  
+  Integer columns are then compressed with Rice; all other columns compressed
+  with GZIP.  In addition, the bytes in the floating point numeric data values 
+  (columns with TFORM =  E, and D) are 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.   Thus, if you
+  have 3 4-byte numeric values, the bytes 012301230123 get shuffled to
+  000111222333
+*/
+{ 
+    LONGLONG nrows, incolwidth[999], inrepeat[999], outcolstart[1000], outbytespan[999];
+    LONGLONG headstart, datastart, dataend, startbyte, jj, kk, naxis1;
+    long repeat, width, pcount;
+    int ii, ncols, coltype, hdutype, ltrue = 1;
+    char *buffer, *cptr, keyname[9], tform[40], colcode[999], tempstring[20];
+    char comm[FLEN_COMMENT], *compressed_data;
+    float cratio[999];
+    
+    size_t dlen, datasize;
+
+    if (*status > 0)
+        return(*status);
+    
+    fits_get_hdu_type(infptr, &hdutype, status);
+    if (hdutype != BINARY_TBL) {
+        *status = NOT_BTABLE;
+        return(*status);
+    }
+        
+    fits_get_num_rowsll(infptr, &nrows, status);
+    fits_get_num_cols(infptr, &ncols, status);
+    fits_read_key(infptr, TLONGLONG, "NAXIS1", &naxis1, NULL, status);
+    if (*status > 0)
+        return(*status);
+
+    if (nrows < 1  || ncols < 1) {
+	/* just copy the HDU if the table has 0 columns or rows */
+	if (infptr != outfptr) {  /* copy input header to the output */
+		fits_copy_hdu (infptr, outfptr, 0, status);
+	}
+	return(*status);
+    }
+   
+    /* allocate space for the transposed table */
+    buffer = calloc((size_t) naxis1, (size_t) nrows);
+    if (!buffer) {
+        ffpmsg("Could not allocate buffer for transformed table");
+        *status = MEMORY_ALLOCATION;
+        return(*status);
+    }
+
+    if (infptr != outfptr) {  /* copy input header to the output */
+	fits_copy_header(infptr, outfptr, status);
+    }
+
+    outcolstart[0] = 0;
+    for (ii = 0; ii < ncols; ii++) {
+
+	/* get the column type, repeat count, and unit width */
+	fits_make_keyn("TFORM", ii+1, keyname, status);
+	fits_read_key(outfptr, TSTRING, keyname, tform, comm, status);
+
+	/* preserve the original TFORM value and comment string */
+	keyname[0] = 'Z';
+	fits_write_key(outfptr, TSTRING, keyname, tform, comm, status);
+	keyname[0] = 'T';
+ 
+        fits_binary_tform(tform, &coltype, &repeat, &width, status);
+
+   	/* BIT columns are a difficult case */
+	 /* round up to a multiple of 8 bits */
+/*
+	if (coltype == TBIT) {  
+	    repeat = (repeat + 7) / 8 * 8; 
+	}
+*/
+	cptr = tform;
+	while(isdigit(*cptr)) cptr++;
+	colcode[ii] = *cptr; /* save the column type code */
+
+/* all columns are now VLAs */
+	fits_modify_key_str(outfptr, keyname, "1PB", "&", status);
+
+	if (coltype == TBIT) {
+	    repeat = (repeat + 7) / 8;  /* convert from bits to bytes */
+	} else if (coltype == TSTRING) {
+	    width = 1;  /* ignore the optional 'w' in 'rAw' format */
+	} else if (coltype < 0) {  /* pointer to variable length array */
+	    width = 8;
+	    if (colcode[ii] == 'Q') width = 16;  /* this is a 'Q' not a 'P' column */
+	    repeat = 1;
+	}
+
+	inrepeat[ii] = repeat;
+	
+	/* width (in bytes) of each element and field in the INPUT row-major table */
+	incolwidth[ii] = repeat * width;
+	
+	/* starting offset of each field in the OUTPUT column-major table */
+	outcolstart[ii + 1] = outcolstart[ii] + incolwidth[ii] * nrows;
+
+	/* length of each sequence of bytes, after sorting them in signicant order */
+	outbytespan[ii] = (incolwidth[ii] * nrows) / width;
+    }
+
+    /* the transformed table has only 1 row */
+    /* output table width 8 bytes per column */
+
+    fits_modify_key_lng(outfptr, "NAXIS2", 1, "&", status);
+    fits_modify_key_lng(outfptr, "NAXIS1", ncols * 8, "&", status);
+
+    /* move to the start of the input table */
+    fits_get_hduaddrll(infptr, &headstart, &datastart, &dataend, status);
+    ffmbyt(infptr, datastart, 0, status);
+
+    for (jj = 0; jj < nrows; jj++)   {    /* loop over rows */
+      for (ii = 0; ii < ncols; ii++) {  /* loop over columns */
+      
+	kk = 0;	
+
+	switch (colcode[ii]) {
+	/* separate the byte planes for the 2-byte, 4-byte, and 8-byte numeric columns */
+
+	case 'E':
+	  while(kk < incolwidth[ii]) {
+	    cptr = buffer + (outcolstart[ii] + (jj * inrepeat[ii]) + kk/4);  
+	    ffgbyt(infptr, 1, cptr, status);  /* copy 1 byte */
+	    cptr += outbytespan[ii];  
+	    ffgbyt(infptr, 1, cptr, status);  /* copy 1 byte */
+	    cptr += outbytespan[ii];  
+	    ffgbyt(infptr, 1, cptr, status);  /* copy 1 byte */
+	    cptr += outbytespan[ii];  
+	    ffgbyt(infptr, 1, cptr, status);  /* copy 1 byte */
+	    kk += 4;
+	  }
+	  break;
+
+	case 'D':
+	case 'K':
+	  while(kk < incolwidth[ii]) {
+	    cptr = buffer + (outcolstart[ii] + (jj * inrepeat[ii]) + kk/8);  
+	    ffgbyt(infptr, 1, cptr, status);  /* copy 1 byte */
+	    cptr += outbytespan[ii];  
+	    ffgbyt(infptr, 1, cptr, status);  /* copy 1 byte */
+	    cptr += outbytespan[ii];  
+	    ffgbyt(infptr, 1, cptr, status);  /* copy 1 byte */
+	    cptr += outbytespan[ii];  
+	    ffgbyt(infptr, 1, cptr, status);  /* copy 1 byte */
+	    cptr += outbytespan[ii];  
+	    ffgbyt(infptr, 1, cptr, status);  /* copy 1 byte */
+	    cptr += outbytespan[ii];  
+	    ffgbyt(infptr, 1, cptr, status);  /* copy 1 byte */
+	    cptr += outbytespan[ii];  
+	    ffgbyt(infptr, 1, cptr, status);  /* copy 1 byte */
+	    cptr += outbytespan[ii];  
+	    ffgbyt(infptr, 1, cptr, status);  /* copy 1 byte */
+	    kk += 8;
+	  }
+	  break;
+
+	default: /* don't bother separating the bytes for other column types */
+	    cptr = buffer + (outcolstart[ii] + (jj * incolwidth[ii]));   /* addr to copy to */
+	    startbyte = (infptr->Fptr)->bytepos;  /* save the starting byte location */
+
+	    ffgbyt(infptr, incolwidth[ii], cptr, status);  /* copy all the bytes */
+
+	    if (incolwidth[ii] >= MINDIRECT) { /* have to explicitly move to next byte */
+		ffmbyt(infptr, startbyte + incolwidth[ii], 0, status);
+	    }
+	}
+      }
+    }
+
+    fits_set_hdustruc(outfptr, status);
+    
+    for (ii = 0; ii < ncols; ii++) {  /* loop over columns */
+
+	datasize = (size_t) (outcolstart[ii + 1] - outcolstart[ii]);
+	/* allocate memory for the compressed data */
+	compressed_data = malloc(datasize*2);
+	if (!compressed_data) {
+            ffpmsg("data memory allocation error");
+	    return(-1);
+	}
+
+
+	switch (colcode[ii]) {
+
+
+	case 'I':
+#if BYTESWAPPED
+                ffswap2((short *) (buffer + outcolstart[ii]),  datasize / 2); 
+#endif
+  	        dlen = fits_rcomp_short ((short *)(buffer + outcolstart[ii]), datasize / 2, (unsigned char *) compressed_data,
+                       datasize * 2, 32);
+
+	  	fits_make_keyn("ZCTYP", ii+1, keyname, status);
+	  	fits_write_key(outfptr, TSTRING, keyname, "RICE_1",
+	     	     "compression algorithm for column", status);
+
+	  break;
+
+	case 'J':
+
+#if BYTESWAPPED
+                ffswap4((int *) (buffer + outcolstart[ii]),  datasize / 4); 
+#endif
+   	        dlen = fits_rcomp ((int *)(buffer + outcolstart[ii]), datasize / 4, (unsigned char *) compressed_data,
+                       datasize * 2, 32);
+
+	  	fits_make_keyn("ZCTYP", ii+1, keyname, status);
+	  	fits_write_key(outfptr, TSTRING, keyname, "RICE_1",
+	     	     "compression algorithm for column", status);
+	  break;
+
+	case 'B':
+  	        dlen = fits_rcomp_byte ((signed char *)(buffer + outcolstart[ii]), datasize, (unsigned char *) compressed_data,
+                       datasize * 2, 32);
+
+	  	fits_make_keyn("ZCTYP", ii+1, keyname, status);
+	  	fits_write_key(outfptr, TSTRING, keyname, "RICE_1",
+	     	     "compression algorithm for column", status);
+	  break;
+
+	default: 
+		/* gzip compress the data */
+		compress2mem_from_mem(buffer + outcolstart[ii], datasize,
+	    		&compressed_data,  &datasize, realloc, &dlen, status);        
+
+
+	  	fits_make_keyn("ZCTYP", ii+1, keyname, status);
+	  	fits_write_key(outfptr, TSTRING, keyname, "GZIP_2",
+	     	     "compression algorithm for column", status);
+
+	} /* end of switch block */
+
+	if (dlen != 0)
+	cratio[ii] = (float) datasize / (float) dlen;  /* compression ratio of the column */
+
+	/* 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, 1, 1, dlen, compressed_data, status);
+	
+	free(compressed_data);   /* don't need the compressed data any more */
+/*	printf("   %c  %5.2f\n",colcode[ii],cratio[ii]); */
+
+	    sprintf(tempstring,"  %5.2f\n",cratio[ii]);
+/*
+        if (colcode[ii] == 'I' || colcode[ii] == 'J' || colcode[ii] == 'B') 
+	    sprintf(tempstring,"  %5.2f\n",cratio[ii]);
+	else
+	    sprintf(tempstring," \n");	
+*/
+	strcat(results[ii],tempstring);
+    }  /* end of loop over ncols */
+
+    printf("                       Trans   Shuf   Rice\n");
+    for (ii = 0; ii < ncols; ii++) {  /* loop over columns */
+      printf("%s", results[ii]);
+    }
+    
+    /* save the original PCOUNT value */
+    fits_read_key(infptr, TLONG, "PCOUNT", &pcount, comm, status);
+    fits_write_key(outfptr, TLONG, "ZPCOUNT", &pcount, comm, status);
+
+	
+    fits_write_key(outfptr, TLONGLONG, "ZNAXIS1", &naxis1, "original rows width",
+	status);
+    fits_write_key(outfptr, TLONGLONG, "ZNAXIS2", &nrows, "original number of rows",
+	status);
+
+    fits_write_key(outfptr, TLOGICAL, "ZTABLE", &ltrue, 
+        "this is a compressed table", status);
+
+    free(buffer);
+
+    fits_gzip_heap(infptr, outfptr, status);
+    fits_set_hdustruc(outfptr, status);
+       	
+    return(*status);
+}
+/*--------------------------------------------------------------------------*/
+int fits_compress_table_fast(fitsfile *infptr, fitsfile *outfptr, int *status)
+
+/*
+  Compress the input FITS binary table using the 'fast' method, which consists
+  of (a) transposing the rows and columns, and (b) shuffling the bytes for
+  the I, J, K, E, and D columns  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.   Thus, if you have 3 4-byte numeric
+  values, the bytes 012301230123 get shuffled to 000111222333
+
+  Finally, (c) compress each column of bytes with gzip and copy to the output table.
+  
+*/
+{ 
+    LONGLONG nrows, incolwidth[999], inrepeat[999], outcolstart[1000], outbytespan[999];
+    LONGLONG headstart, datastart, dataend, startbyte, jj, kk, naxis1;
+    long repeat, width, pcount;
+    int ii, ncols, coltype, hdutype, ltrue = 1;
+    char *buffer, *cptr, keyname[9], tform[40], colcode[999];
+    char comm[FLEN_COMMENT], *compressed_data, tempstring[20];
+    size_t dlen, datasize;
+    float cratio[999];
+    
+    if (*status > 0)
+        return(*status);
+    
+    fits_get_hdu_type(infptr, &hdutype, status);
+    if (hdutype != BINARY_TBL) {
+        *status = NOT_BTABLE;
+        return(*status);
+    }
+        
+    fits_get_num_rowsll(infptr, &nrows, status);
+    fits_get_num_cols(infptr, &ncols, status);
+    fits_read_key(infptr, TLONGLONG, "NAXIS1", &naxis1, NULL, status);
+    if (*status > 0)
+        return(*status);
+
+    if (nrows < 1  || ncols < 1) {
+	/* just copy the HDU if the table has 0 columns or rows */
+	if (infptr != outfptr) {  /* copy input header to the output */
+		fits_copy_hdu (infptr, outfptr, 0, status);
+	}
+	return(*status);
+    }
+ 
+    /* allocate space for the transposed table */
+    buffer = calloc((size_t) naxis1, (size_t) nrows);
+    if (!buffer) {
+        ffpmsg("Could not allocate buffer for transformed table");
+        *status = MEMORY_ALLOCATION;
+        return(*status);
+    }
+
+    if (infptr != outfptr) {  /* copy input header to the output */
+	fits_copy_header(infptr, outfptr, status);
+    }
+
+    fits_write_key_log(outfptr, "ZTABLE", 1, 
+          "extension contains compressed binary table", status);
+
+    fits_write_key(outfptr, TLONGLONG, "ZTILELEN", &nrows,
+          "number of rows in each tile", status);
+
+    fits_write_key(outfptr, TLONGLONG, "ZNAXIS1", &naxis1, "original rows width",
+	status);
+    fits_write_key(outfptr, TLONGLONG, "ZNAXIS2", &nrows, "original number of rows",
+	status);
+
+    /* save the original PCOUNT value */
+    fits_read_key(infptr, TLONG, "PCOUNT", &pcount, comm, status);
+    fits_write_key(outfptr, TLONG, "ZPCOUNT", &pcount, comm, status);
+
+    /* reset the PCOUNT keyword to zero */
+    pcount = 0;
+    fits_modify_key_lng(outfptr, "PCOUNT", pcount, NULL, status);
+
+    outcolstart[0] = 0;
+    for (ii = 0; ii < ncols; ii++) {
+
+	/* get the column type, repeat count, and unit width */
+	fits_make_keyn("TFORM", ii+1, keyname, status);
+	fits_read_key(outfptr, TSTRING, keyname, tform, comm, status);
+
+	/* preserve the original TFORM value and comment string */
+	keyname[0] = 'Z';
+	fits_write_key(outfptr, TSTRING, keyname, tform, comm, status);
+	keyname[0] = 'T';
+ 
+       /* all columns are now VLAs */
+	fits_modify_key_str(outfptr, keyname, "1PB", "&", status);
+
+ 	fits_make_keyn("ZCTYP", ii+1, keyname, status);
+	fits_write_key(outfptr, TSTRING, keyname, "GZIP_2",
+	     "compression algorithm for column", status);
+
+        fits_binary_tform(tform, &coltype, &repeat, &width, status);
+
+	cptr = tform;
+	while(isdigit(*cptr)) cptr++;
+	colcode[ii] = *cptr; /* save the column type code */
+
+	if (coltype == TBIT) {
+	    repeat = (repeat + 7) / 8;  /* convert from bits to bytes */
+	} else if (coltype == TSTRING) {
+	    width = 1;  /* ignore the optional 'w' in 'rAw' format */
+	} else if (coltype < 0) {  /* pointer to variable length array */
+	    width = 8;
+	    if (colcode[ii] == 'Q') width = 16;  /* this is a 'Q' not a 'P' column */
+	    repeat = 1;
+	}
+
+	inrepeat[ii] = repeat;
+	
+	/* width (in bytes) of each element and field in the INPUT row-major table */
+	incolwidth[ii] = repeat * width;
+	
+	/* starting offset of each field in the OUTPUT column-major table */
+	outcolstart[ii + 1] = outcolstart[ii] + incolwidth[ii] * nrows;
+
+	/* length of each sequence of bytes, after sorting them in signicant order */
+	outbytespan[ii] = (incolwidth[ii] * nrows) / width;
+
+    }
+
+    /* the transformed table has only 1 row */
+    /* output table width 8 bytes per column */
+
+    fits_modify_key_lng(outfptr, "NAXIS2", 1, "&", status);
+    fits_modify_key_lng(outfptr, "NAXIS1", ncols * 8, "&", status);
+
+    /* move to the start of the input table */
+    fits_get_hduaddrll(infptr, &headstart, &datastart, &dataend, status);
+    ffmbyt(infptr, datastart, 0, status);
+
+    for (jj = 0; jj < nrows; jj++)   {    /* loop over rows */
+      for (ii = 0; ii < ncols; ii++) {  /* loop over columns */
+      
+	kk = 0;	
+
+	switch (colcode[ii]) {
+	/* separate the byte planes for the 2-byte, 4-byte, and 8-byte numeric columns */
+	case 'I':
+	  while(kk < incolwidth[ii]) {
+
+	    cptr = buffer + (outcolstart[ii] + (jj * inrepeat[ii]) + kk/2);  
+	    ffgbyt(infptr, 1, cptr, status);  /* copy 1st byte */
+	    cptr += outbytespan[ii];  
+	    ffgbyt(infptr, 1, cptr, status);  /* copy 2nd byte */
+	    kk += 2;
+	  }
+
+	  break;
+	
+	case 'J':
+	case 'E':
+	  while(kk < incolwidth[ii]) {
+	    cptr = buffer + (outcolstart[ii] + (jj * inrepeat[ii]) + kk/4);  
+	    ffgbyt(infptr, 1, cptr, status);  /* copy 1 byte */
+	    cptr += outbytespan[ii];  
+	    ffgbyt(infptr, 1, cptr, status);  /* copy 1 byte */
+	    cptr += outbytespan[ii];  
+	    ffgbyt(infptr, 1, cptr, status);  /* copy 1 byte */
+	    cptr += outbytespan[ii];  
+	    ffgbyt(infptr, 1, cptr, status);  /* copy 1 byte */
+	    kk += 4;
+	  }
+	  break;
+
+	case 'D':
+	case 'K':
+	  while(kk < incolwidth[ii]) {
+	    cptr = buffer + (outcolstart[ii] + (jj * inrepeat[ii]) + kk/8);  
+	    ffgbyt(infptr, 1, cptr, status);  /* copy 1 byte */
+	    cptr += outbytespan[ii];  
+	    ffgbyt(infptr, 1, cptr, status);  /* copy 1 byte */
+	    cptr += outbytespan[ii];  
+	    ffgbyt(infptr, 1, cptr, status);  /* copy 1 byte */
+	    cptr += outbytespan[ii];  
+	    ffgbyt(infptr, 1, cptr, status);  /* copy 1 byte */
+	    cptr += outbytespan[ii];  
+	    ffgbyt(infptr, 1, cptr, status);  /* copy 1 byte */
+	    cptr += outbytespan[ii];  
+	    ffgbyt(infptr, 1, cptr, status);  /* copy 1 byte */
+	    cptr += outbytespan[ii];  
+	    ffgbyt(infptr, 1, cptr, status);  /* copy 1 byte */
+	    cptr += outbytespan[ii];  
+	    ffgbyt(infptr, 1, cptr, status);  /* copy 1 byte */
+	    kk += 8;
+	  }
+	  break;
+
+	default: /* don't bother separating the bytes for other column types */
+	    cptr = buffer + (outcolstart[ii] + (jj * incolwidth[ii]));   /* addr to copy to */
+
+	    startbyte = (infptr->Fptr)->bytepos;  /* save the starting byte location */
+
+	    ffgbyt(infptr, incolwidth[ii], cptr, status);  /* copy all the bytes */
+
+	    if (incolwidth[ii] >= MINDIRECT) { /* have to explicitly move to next byte */
+		ffmbyt(infptr, startbyte + incolwidth[ii], 0, status);
+	    }
+	}
+      }
+    }
+
+    fits_set_hdustruc(outfptr, status);
+    
+    /* now compress each column */
+    for (ii = 0; ii < ncols; ii++) {  /* loop over columns */
+
+	/* write the compression type code for this column */
+	switch (colcode[ii]) {
+	case 'I':
+	case 'J':
+	case 'K':
+	case 'E':
+	case 'D':
+	  fits_make_keyn("ZCTYP", ii+1, keyname, status);
+	  fits_write_key(outfptr, TSTRING, keyname, "GZIP_2",
+	     "compression algorithm for column", status);
+	  break;
+	default:
+	  fits_make_keyn("ZCTYP", ii+1, keyname, status);
+	  fits_write_key(outfptr, TSTRING, keyname, "GZIP_1",
+	     "compression algorithm for column", status);
+        }
+
+	datasize = (size_t) (outcolstart[ii + 1] - outcolstart[ii]);
+
+	/* allocate memory for the compressed data */
+	compressed_data = malloc(datasize);
+	if (!compressed_data) {
+            ffpmsg("data memory allocation error");
+	    return(-1);
+	}
+
+	/* gzip compress the data */
+	compress2mem_from_mem(buffer + outcolstart[ii], datasize,
+	    &compressed_data,  &datasize, realloc, 
+	    &dlen, 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, 1, 1, dlen, compressed_data, status);
+
+        cratio[ii] = (float) datasize / (float) dlen;	
+	free(compressed_data);   /* don't need the compressed data any more */
+
+	sprintf(tempstring,"  %5.2f",cratio[ii]);
+
+	strcat(results[ii],tempstring);
+    }
+
+    free(buffer);
+
+    /* shuffle and compress the input heap and append to the output file */
+
+    fits_gzip_heap(infptr, outfptr, status);
+    fits_set_hdustruc(outfptr, status);
+
+    return(*status);
+}
+/*--------------------------------------------------------------------------*/
+int fits_compress_table_best(fitsfile *infptr, fitsfile *outfptr, int *status)
+
+/*
+  Compress the input FITS binary table using the 'best' compression method, i.e,
+  whichever method produces the highest compression for each column.
+  
+  First, transpose the rows and columns in the table, then, depending on the 
+  data type of the column, try the different compression methods to see
+  which one produces the highest amount of compression.
+  
+*/
+{ 
+    LONGLONG nrows, incolwidth[999], inrepeat[999], outcolstart[1000], outbytespan[999];
+    LONGLONG headstart, datastart, dataend, startbyte, jj, naxis1;
+    long repeat, width, pcount;
+    int ii, ncols, coltype, hdutype, ltrue = 1;
+    char *buffer, *cptr, keyname[9], tform[40], colcode[999];
+    char comm[FLEN_COMMENT];
+    char *gzip1_data = 0, *gzip2_data = 0, *rice_data = 0;
+    size_t gzip1_len, gzip2_len, rice_len, datasize, buffsize;
+    
+    if (*status > 0)
+        return(*status);
+    
+    fits_get_hdu_type(infptr, &hdutype, status);
+    if (hdutype != BINARY_TBL) {
+        *status = NOT_BTABLE;
+        return(*status);
+    }
+        
+    fits_get_num_rowsll(infptr, &nrows, status);
+    fits_get_num_cols(infptr, &ncols, status);
+    fits_read_key(infptr, TLONGLONG, "NAXIS1", &naxis1, NULL, status);
+    if (*status > 0)
+        return(*status);
+
+    if (nrows < 1  || ncols < 1) {
+	/* just copy the HDU if the table has 0 columns or rows */
+	if (infptr != outfptr) {  /* copy input header to the output */
+		fits_copy_hdu (infptr, outfptr, 0, status);
+	}
+	return(*status);
+    }
+ 
+    /* allocate space for the transposed table */
+    buffer = calloc((size_t) naxis1, (size_t) nrows);
+    if (!buffer) {
+        ffpmsg("Could not allocate buffer for transformed table");
+        *status = MEMORY_ALLOCATION;
+        return(*status);
+    }
+
+    if (infptr != outfptr) {  /* copy input header to the output */
+	fits_copy_header(infptr, outfptr, status);
+    }
+
+    fits_write_key_log(outfptr, "ZTABLE", 1, 
+          "extension contains compressed binary table", status);
+
+    fits_write_key(outfptr, TLONGLONG, "ZTILELEN", &nrows,
+          "number of rows in each tile", status);
+
+    fits_write_key(outfptr, TLONGLONG, "ZNAXIS1", &naxis1, "original rows width",
+	status);
+    fits_write_key(outfptr, TLONGLONG, "ZNAXIS2", &nrows, "original number of rows",
+	status);
+
+    /* save the original PCOUNT value */
+    fits_read_key(infptr, TLONG, "PCOUNT", &pcount, comm, status);
+    fits_write_key(outfptr, TLONG, "ZPCOUNT", &pcount, comm, status);
+    /* reset the PCOUNT keyword to zero */
+    pcount = 0;
+    fits_modify_key_lng(outfptr, "PCOUNT", pcount, NULL, status);
+
+    /* Modify the TFORMn keywords; all columns become variable-length arrays. */
+    /* Save the original TFORMn values in the corresponding ZFORMn keyword.   */
+    outcolstart[0] = 0;
+    for (ii = 0; ii < ncols; ii++) {
+
+	/* get the column type, repeat count, and unit width */
+	fits_make_keyn("TFORM", ii+1, keyname, status);
+	fits_read_key(outfptr, TSTRING, keyname, tform, comm, status);
+
+	/* preserve the original TFORM value and comment string */
+	keyname[0] = 'Z';
+	fits_write_key(outfptr, TSTRING, keyname, tform, comm, status);
+	keyname[0] = 'T';
+ 
+       /* all columns are now VLAs */
+	fits_modify_key_str(outfptr, keyname, "1PB", "&", status);
+
+        fits_binary_tform(tform, &coltype, &repeat, &width, status);
+
+	cptr = tform;
+	while(isdigit(*cptr)) cptr++;
+	colcode[ii] = *cptr; /* save the column type code */
+
+        /* deal with special cases */
+	if (coltype == TBIT) {
+	    repeat = (repeat + 7) / 8;  /* convert from bits to bytes */
+	} else if (coltype == TSTRING) {
+	    width = 1;  /* ignore the optional 'w' in 'rAw' format */
+	} else if (coltype < 0) {  /* pointer to variable length array */
+	    repeat = 1;
+
+	    if (colcode[ii] == 'Q')
+	       width = 16;  /* this is a 'Q' column */
+	    else
+	       width = 8;  /* this is a 'P' column */
+	}
+
+	inrepeat[ii] = repeat;
+	
+	/* width (in bytes) of each element and field in the INPUT row-major table */
+	incolwidth[ii] = repeat * width;
+	
+	/* starting offset of each field in the OUTPUT column-major table */
+	outcolstart[ii + 1] = outcolstart[ii] + incolwidth[ii] * nrows;
+
+	/* length of each sequence of bytes, after sorting them in signicant order */
+	outbytespan[ii] = (incolwidth[ii] * nrows) / width;
+    }
+
+    /* the transformed table has only 1 row */
+    /* output table width 8 bytes per column */
+
+    fits_modify_key_lng(outfptr, "NAXIS2", 1, "&", status);
+    fits_modify_key_lng(outfptr, "NAXIS1", ncols * 8, "&", status);
+
+    /* move to the start of the input table */
+    fits_get_hduaddrll(infptr, &headstart, &datastart, &dataend, status);
+    ffmbyt(infptr, datastart, 0, status);
+
+    /* now transpose the rows and columns in the table into an array in memory */
+    for (jj = 0; jj < nrows; jj++)   {    /* loop over rows */
+        for (ii = 0; ii < ncols; ii++) {  /* loop over columns */
+      
+	    cptr = buffer + (outcolstart[ii] + (jj * incolwidth[ii])); /* output address */
+	    startbyte = (infptr->Fptr)->bytepos;  /* save the starting byte location */
+	    ffgbyt(infptr, incolwidth[ii], cptr, status);  /* copy the column element */
+
+	    if (incolwidth[ii] >= MINDIRECT) { /* have to explicitly move to next byte */
+		ffmbyt(infptr, startbyte + incolwidth[ii], 0, status);
+	    }
+        }
+    }
+
+    fits_set_hdustruc(outfptr, status);  /* reinitialize internal pointers */
+    
+    /* Now compress each column.  Depending on the column data type, try */
+    /* all the various available compression algorithms, then choose the one */
+    /* that gives the most compression. */
+    for (ii = 0; ii < ncols; ii++) {  /* loop over columns */
+
+	datasize = (size_t) (outcolstart[ii + 1] - outcolstart[ii]);
+
+	/* allocate memory for the gzip compressed data */
+	gzip1_data = malloc(datasize);
+	if (!gzip1_data) {
+            ffpmsg("data memory allocation error");
+	    return(-1);
+	}
+	buffsize = datasize;
+
+	/*  First, simply compress the bytes with gzip (GZIP_1 algorithm code). */
+	/*  This algorithm can be applied to every type of column. */
+	compress2mem_from_mem(buffer + outcolstart[ii], datasize,
+	    &gzip1_data,  &buffsize, realloc, &gzip1_len, status);        
+	
+	/* depending on the data type, try other compression methods */
+	switch (colcode[ii]) {
+
+	case 'I':   /* 2-byte Integer columns */
+
+		/************* first, try rice compression *****************/
+		rice_data = malloc(datasize * 2);  /* memory for the compressed bytes */
+		if (!rice_data) {
+                    ffpmsg("data memory allocation error");
+		    return(-1);
+		}
+
+#if BYTESWAPPED
+		/* have to swap the bytes on little endian machines */
+                ffswap2((short *) (buffer + outcolstart[ii]),  datasize / 2); 
+#endif
+  	        rice_len = fits_rcomp_short ((short *)(buffer + outcolstart[ii]), datasize / 2, 
+		   (unsigned char *) rice_data, datasize * 2, 32);
+	
+#if BYTESWAPPED
+		/* un-swap the bytes, to restore the original order */
+                ffswap2((short *) (buffer + outcolstart[ii]),  datasize / 2); 
+#endif
+	   
+		/************* Second, try shuffled gzip compression *****************/
+		fits_shuffle_2bytes(buffer + outcolstart[ii], datasize / 2, status);
+
+		/* allocate memory for the shuffled gzip compressed data */
+		gzip2_data = malloc(datasize);
+		if (!gzip2_data) {
+                    ffpmsg("data memory allocation error");
+		    return(-1);
+		}
+		buffsize = datasize;
+
+		compress2mem_from_mem(buffer + outcolstart[ii], datasize,
+		    &gzip2_data,  &buffsize, realloc, &gzip2_len, status);        
+           break;
+
+	case 'J':   /* 4-byte Integer columns */
+
+		/************* first, try rice compression *****************/
+		rice_data = malloc(datasize * 2);  /* memory for the compressed bytes */
+		if (!rice_data) {
+                    ffpmsg("data memory allocation error");
+		    return(-1);
+		}
+#if BYTESWAPPED
+		/* have to swap the bytes on little endian machines */
+                ffswap4((int *) (buffer + outcolstart[ii]),  datasize / 4); 
+#endif
+  	        rice_len = fits_rcomp ((int *)(buffer + outcolstart[ii]), datasize / 4, 
+		   (unsigned char *) rice_data, datasize * 2, 32);
+	
+#if BYTESWAPPED
+		/* un-swap the bytes, to restore the original order */
+                ffswap4((int *) (buffer + outcolstart[ii]),  datasize / 4); 
+#endif
+	   
+		/************* Second, try shuffled gzip compression *****************/
+		fits_shuffle_4bytes(buffer + outcolstart[ii], datasize / 4, status);
+
+		/* allocate memory for the shuffled gzip compressed data */
+		gzip2_data = malloc(datasize);
+		if (!gzip2_data) {
+                    ffpmsg("data memory allocation error");
+		    return(-1);
+		}
+		buffsize = datasize;
+
+		compress2mem_from_mem(buffer + outcolstart[ii], datasize,
+		    &gzip2_data,  &buffsize, realloc, &gzip2_len, status);        
+           break;
+
+	case 'E':   /* 4-byte floating-point */
+
+		/************* try shuffled gzip compression *****************/
+		fits_shuffle_4bytes(buffer + outcolstart[ii], datasize / 4, status);
+
+		/* allocate memory for the gzip compressed data */
+		gzip2_data = malloc(datasize);
+		if (!gzip2_data) {
+                    ffpmsg("data memory allocation error");
+		    return(-1);
+		}
+		buffsize = datasize;
+		
+		compress2mem_from_mem(buffer + outcolstart[ii], datasize,
+		    &gzip2_data,  &buffsize, realloc, &gzip2_len, status);        
+
+		rice_len = 100 * datasize;  /* rice is not applicable to R*4 data */
+
+	   break;
+
+	case 'K':
+	case 'D':  /* 8-byte floating-point or integers */
+
+		/************* try shuffled gzip compression *****************/
+		fits_shuffle_8bytes(buffer + outcolstart[ii], datasize / 8, status);
+
+		/* allocate memory for the gzip compressed data */
+		gzip2_data = malloc(datasize);
+		if (!gzip2_data) {
+                    ffpmsg("data memory allocation error");
+		    return(-1);
+		}
+		buffsize = datasize;
+
+		compress2mem_from_mem(buffer + outcolstart[ii], datasize,
+		    &gzip2_data,  &buffsize, realloc, &gzip2_len, status);        
+
+		rice_len = 100 * datasize;  /* rice is not applicable to R*8 or I*8 data */
+
+	   break;
+
+	default:  /* L, X, B, A, C, M, P, Q type columns: no other compression options */
+		rice_len = 100 * datasize;   /* rice is not applicable */
+		gzip2_len = 100 * datasize;  /* shuffled-gzip is not applicable */
+
+	}  /* end of switch block */
+
+	/* now write the compressed bytes from the best algorithm */
+	fits_set_tscale(outfptr, ii + 1, 1.0, 0.0, status);  /* turn off any data scaling, first */
+	if (gzip1_len <= gzip2_len && gzip1_len <= rice_len) {
+
+	    fits_write_col(outfptr, TBYTE, ii + 1, 1, 1, gzip1_len, gzip1_data, status);
+	    fits_make_keyn("ZCTYP", ii+1, keyname, status);
+	    fits_write_key(outfptr, TSTRING, keyname, "GZIP_1",
+	         "compression algorithm for column", status);
+	} else if (gzip2_len <= gzip1_len && gzip2_len <= rice_len) {
+	    fits_write_col(outfptr, TBYTE, ii + 1, 1, 1, gzip2_len, gzip2_data, status);
+	    fits_make_keyn("ZCTYP", ii+1, keyname, status);
+	    fits_write_key(outfptr, TSTRING, keyname, "GZIP_2",
+	         "compression algorithm for column", status);
+	} else {
+	    fits_write_col(outfptr, TBYTE, ii + 1, 1, 1, rice_len, rice_data, status);
+	    fits_make_keyn("ZCTYP", ii+1, keyname, status);
+	    fits_write_key(outfptr, TSTRING, keyname, "RICE_1",
+	         "compression algorithm for column", status);
+	}
+
+	/* free the temporary memory */
+	if (gzip1_data) free(gzip1_data);   
+	if (gzip2_data) free(gzip2_data);   
+	gzip1_data = 0;
+	gzip2_data = 0;
+    }
+
+    free(buffer);
+
+    /* shuffle and compress the input heap and append to the output file */
+
+    fits_gzip_heap(infptr, outfptr, status);
+    fits_set_hdustruc(outfptr, status);
+
+    return(*status);
+}
+/*--------------------------------------------------------------------------*/
+int fits_uncompress_table(fitsfile *infptr, fitsfile *outfptr, int *status)
+
+/*
+  Uncompress the table that was compressed with fits_compress_table_fast or
+  fits_compress_table_best.
+*/
+{ 
+    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, dataend;
+    long repeat, width, vla_repeat;
+    int  ncols, coltype, hdutype, anynull, tstatus, zctype[999];
+    char *buffer, *transbuffer, *cptr, keyname[9], tform[40], colcode[999];
+    long  pcount, zheapptr, naxis1, naxis2, ii, jj;
+    char *ptr, comm[FLEN_COMMENT], zvalue[FLEN_VALUE];
+    size_t dlen, fullsize;
+    
+    /**** do initial sanity checks *****/
+    if (*status > 0)
+        return(*status);
+     
+    fits_get_hdu_type(infptr, &hdutype, status);
+    if (hdutype != BINARY_TBL) {
+        *status = NOT_BTABLE;
+        return(*status);
+    }
+ 
+    fits_get_num_rowsll(infptr, &nrows, status);
+    fits_get_num_cols(infptr, &ncols, status);
+
+    if (nrows != 1  || (ncols < 1)) {
+	/* just copy the HDU if the table does not have 1 row and 
+	   more than 0 columns */
+	if (infptr != outfptr) { 
+		fits_copy_hdu (infptr, outfptr, 0, status);
+	}
+	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 = 1;
+        return(*status);
+    }
+
+    fits_read_key(infptr, TLONG, "ZNAXIS2", &naxis2, comm, status);
+    if (*status > 0) {
+        ffpmsg("Could not find the required ZNAXIS2 keyword");
+        *status = 1;
+        return(*status);
+    }
+
+    fits_read_key(infptr, TLONG, "ZPCOUNT", &pcount, comm, status);
+    if (*status > 0) {
+        ffpmsg("Could not find the required ZPCOUNT keyword");
+        *status = 1;
+        return(*status);
+    }
+
+    tstatus = 0;
+    fits_read_key(infptr, TLONG, "ZHEAPPTR", &zheapptr, comm, &tstatus);
+    if (tstatus > 0) {
+        zheapptr = 0;  /* uncompressed table has no heap */
+    }
+
+    /**** recreate the uncompressed table header keywords ****/
+    fits_copy_header(infptr, outfptr, status);
+
+    /* reset the NAXISn keywords to what they were in the original uncompressed table */
+    fits_modify_key_lng(outfptr, "NAXIS1", naxis1, "&", status);
+    fits_modify_key_lng(outfptr, "NAXIS2", naxis2, "&", status);
+    fits_modify_key_lng(outfptr, "PCOUNT", pcount, "&", status);
+
+    fits_delete_key(outfptr, "ZTABLE", status);
+    fits_delete_key(outfptr, "ZNAXIS1", status);
+    fits_delete_key(outfptr, "ZNAXIS2", status);
+    fits_delete_key(outfptr, "ZPCOUNT", status);
+    fits_delete_key(outfptr, "ZTILELEN", status);
+    tstatus = 0;
+    fits_delete_key(outfptr, "ZHEAPPTR", &tstatus);
+
+    /**** get the compression method that was used for each column ****/
+    for (ii = 0; ii < ncols; ii++) {
+
+	/* 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);
+	}
+    }
+
+    /**** allocate space for the full transposed and untransposed table ****/
+    fullsize = naxis1 * naxis2;
+    transbuffer = malloc(fullsize);
+    if (!transbuffer) {
+        ffpmsg("Could not allocate buffer for shuffled table");
+        *status = MEMORY_ALLOCATION;
+        return(*status);
+    }
+
+    buffer = malloc(fullsize);
+    if (!buffer) {
+        ffpmsg("Could not allocate buffer for unshuffled table");
+        *status = MEMORY_ALLOCATION;
+        return(*status);
+    }
+
+    /*** loop over each column: read and uncompress the bytes ****/
+    rmajor_colstart[0] = 0;
+    cmajor_colstart[0] = 0;
+    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 */
+        keyname[0] = 'T';
+	fits_modify_key_str(outfptr, keyname, tform, comm, 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, &coltype, &repeat, &width, status);
+
+	/* deal with special cases */
+	if (coltype == TBIT) { 
+	    repeat = (repeat + 7) / 8 ;   /* convert from bits to bytes */
+	} else if (coltype == TSTRING) {
+	    width = 1;
+	} else if (coltype < 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 */
+	}
+
+	rmajor_repeat[ii] = repeat;
+	cmajor_repeat[ii] = repeat * naxis2;
+
+	/* width (in bytes) of each field in the row-major table */
+	rmajor_colwidth[ii] = rmajor_repeat[ii] * width;
+
+	/* starting offset of each field in the column-major table */
+	cmajor_colstart[ii + 1] = cmajor_colstart[ii] + rmajor_colwidth[ii] * naxis2;
+
+	/* length of each sequence of bytes, after sorting them in signicant order */
+	cmajor_bytespan[ii] = (rmajor_colwidth[ii] * naxis2) / width;
+
+	/* starting offset of each field in the  row-major table */
+	rmajor_colstart[ii + 1] = rmajor_colstart[ii] + rmajor_colwidth[ii];
+
+	/* read compressed bytes from input table */
+	fits_read_descript(infptr, ii + 1, 1, &vla_repeat, NULL, status);
+	
+	/* allocate memory and read in the compressed bytes */
+	ptr = malloc(vla_repeat);
+	if (!ptr) {
+            ffpmsg("Could not allocate buffer for compressed bytes");
+            *status = MEMORY_ALLOCATION;
+            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, 1, 1, vla_repeat, 0, (unsigned char *) ptr, &anynull, status);
+
+        cptr = transbuffer + cmajor_colstart[ii];
+	
+	fullsize = (size_t) (cmajor_colstart[ii+1] - cmajor_colstart[ii]);
+
+	switch (colcode[ii]) {
+	/* separate the byte planes for the 2-byte, 4-byte, and 8-byte numeric columns */
+
+
+	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: 
+	    /* 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);
+    }
+
+    /* now transpose the rows and columns (from transbuffer to buffer) */
+    ptr = transbuffer;
+    for (ii = 0; ii < ncols; ii++) {  /* loop over columns */
+
+      if ((zctype[ii] == GZIP_2)) {  /*  need to unshuffle the bytes */
+
+	switch (colcode[ii]) {
+	
+	/* recombine the byte planes for the 2-byte, 4-byte, and 8-byte numeric columns */
+
+	case 'I':
+	  /* get the 1st byte of each I*2 value */
+          for (jj = 0; jj < naxis2; jj++) {  /* loop over number of rows in the output table */
+	    cptr = 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 < naxis2; jj++) {  /* loop over number of rows in the output table */
+	    cptr = 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 < naxis2; jj++) {  /* loop over number of rows in the output table */
+	    cptr = 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 < naxis2; jj++) {  /* loop over number of rows in the output table */
+	    cptr = 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 < naxis2; jj++) {  /* loop over number of rows in the output table */
+	    cptr = 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 < naxis2; jj++) {  /* loop over number of rows in the output table */
+	    cptr = 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 < naxis2; jj++) {  /* loop over number of rows in the output table */
+	    cptr = 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 < naxis2; jj++) {  /* loop over number of rows in the output table */
+	    cptr = 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 < naxis2; jj++) {  /* loop over number of rows in the output table */
+	    cptr = 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 < naxis2; jj++) {  /* loop over number of rows in the output table */
+	    cptr = 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 < naxis2; jj++) {  /* loop over number of rows in the output table */
+	    cptr = 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 < naxis2; jj++) {  /* loop over number of rows in the output table */
+	    cptr = 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 < naxis2; jj++) {  /* loop over number of rows in the output table */
+	    cptr = 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 < naxis2; jj++) {  /* loop over number of rows in the output table */
+	    cptr = 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 use of GZIP_2 to compress a column");
+	    *status = DATA_DECOMPRESSION_ERR;
+            return(*status);
+
+        }  /* end of switch */
+
+      } else {  /* not GZIP_2, so just transpose the bytes */
+
+          for (jj = 0; jj < naxis2; jj++) {  /* loop over number of rows in the output table */
+	    cptr = buffer + (rmajor_colstart[ii] + jj * rmajor_colstart[ncols]);   /* addr to copy to */
+	    memcpy(cptr, ptr, (size_t) rmajor_colwidth[ii]);
+	 
+	    ptr += (rmajor_colwidth[ii]);
+	  }
+      }
+
+    }  /* end of ncols loop */
+
+    /* copy the buffer of data to the output data unit */
+    fits_get_hduaddrll(outfptr, &headstart, &datastart, &dataend, status);        
+    ffmbyt(outfptr, datastart, 1, status);
+    ffpbyt(outfptr, naxis1 * naxis2, buffer, status);
+    free(buffer);
+    free(transbuffer);
+	
+    /* reset internal table structure parameters */
+    fits_set_hdustruc(outfptr, status);
+
+    /* unshuffle the heap, if it exists */
+    fits_gunzip_heap(infptr, outfptr, status);
+
+    return(*status);
+}
+
+/*--------------------------------------------------------------------------*/
+int fits_gzip_datablocks(fitsfile *fptr, size_t *size, int *status)
+/*
+  GZIP compress all the data blocks in the binary table HDU.
+  Store the size of the compressed byte stream in the PCOUNT keyword.  
+  Save the original PCOUNT value in the ZPCOUNT keyword.  
+*/
+{ 
+    long headstart, datastart, dataend;
+    char *ptr, *cptr, *iptr;
+    size_t dlen, datasize, ii;
+
+    /* allocate memory for the data and the compressed data */
+    fits_get_hduaddr(fptr, &headstart, &datastart, &dataend, status); 
+    datasize = dataend - datastart;
+    ptr = malloc(datasize);
+    cptr = malloc(datasize);
+    if (!ptr || !cptr) {
+        ffpmsg("data memory allocation error in fits_gzip_datablocks\n");
+	return(-1);
+    }
+
+    /* copy the data into memory */
+    ffmbyt(fptr,datastart, REPORT_EOF, status);
+    iptr = ptr;
+    for (ii = 0; ii < datasize; ii+= 2880) {
+	ffgbyt(fptr, 2880, iptr, status);
+	iptr += 2880;
+    }
+	
+    /* gzip compress the data */
+    compress2mem_from_mem(ptr, datasize,
+	&cptr,  &datasize, realloc, 
+	&dlen, status);        
+
+    *size = dlen;
+
+    free(cptr);   /* don't need the compressed data any more */
+    free(ptr);  /* don't need the original data any more */
+   
+    return(*status);
+}
+/*--------------------------------------------------------------------------*/
+static int fits_gzip_heap(fitsfile *infptr, fitsfile *outfptr, int *status)
+
+/*
+  Compress the binary table heap in the input file and write it to the output file.
+  First, shuffle the bytes for the numeric arrays in the heap, so that
+  the bytes are sorted in order of decreasing significance.  Then gzip
+  the entire heap as a single block of data.  Then append this compressed heap
+  to the end of any existing data in the output file heap.
+*/
+{ 
+    LONGLONG datastart, dataend, nrows, naxis1, heapsize, length, offset, pcount, jj;
+    int coltype, ncols, ii;
+    char *heap, *compheap, card[FLEN_CARD];
+    size_t theapsize, compsize;
+    
+    if (*status > 0)
+        return(*status);
+
+    /* insert a set of COMMENT keyword to indicate that this is a compressed table */
+    fits_read_card(outfptr, "TFIELDS", card, status);
+    fits_insert_card(outfptr, "COMMENT [FPACK] This is a compressed binary table generated by fpack.", status);
+    fits_insert_card(outfptr, "COMMENT [FPACK] It can be uncompressed using funpack.", status);
+    fits_insert_card(outfptr, "COMMENT [FPACK] fpack and funpack are available from the HEASARC Web site.", status);     
+    
+    /* get the size of the heap (value of PCOUNT keyword) */
+    fits_read_key(infptr, TLONGLONG, "PCOUNT", &heapsize, NULL, status);
+
+    /* return if there is no heap */
+    if (*status != 0 || heapsize == 0)
+        return(*status);
+
+    /* allocate memory for the heap and compressed heap */
+         
+    heap = malloc((size_t) heapsize);
+    if (!heap) {
+        ffpmsg("Could not allocate buffer for the heap (fits_gzip_heap");
+        *status = MEMORY_ALLOCATION;
+        return(*status);
+    }
+
+    compheap = malloc((size_t) heapsize);
+    if (!compheap) {
+        ffpmsg("Could not allocate buffer for compressed heap (fits_gzip_heap");
+ 	free(heap);
+        *status = MEMORY_ALLOCATION;
+        return(*status);
+    }
+
+    fits_get_hduaddrll(infptr, NULL, &datastart, NULL, status); 
+    fits_get_num_rowsll(infptr, &nrows, status);
+    fits_get_num_cols(infptr, &ncols, status);
+    fits_read_key(infptr, TLONGLONG, "NAXIS1", &naxis1, NULL, status);
+
+    /* move to start of the heap and copy the heap into memory */
+    ffmbyt(infptr, datastart + (nrows * naxis1), REPORT_EOF, status);
+    ffgbyt(infptr, heapsize, heap, status);
+    
+    /* shuffle the bytes for the numeric columns */
+    for (ii = 1; ii <= ncols; ii++) {
+
+        fits_get_coltype(infptr, ii, &coltype, NULL, NULL, status);
+
+	if (coltype >= 0) continue;   /* only interested in variable length columns */
+	
+	coltype = coltype * (-1);
+	
+	switch (coltype) {
+	/* shuffle the bytes for the 2-byte, 4-byte, and 8-byte numeric columns */
+	case TSHORT:
+
+	  for (jj = 1; jj <= nrows; jj++) {
+	    fits_read_descriptll(infptr, ii, jj, &length, &offset, status);
+	    fits_shuffle_2bytes(heap + offset, length, status);    
+	  }
+	  break;
+	
+	case TLONG:
+	case TFLOAT:
+	  for (jj = 1; jj <= nrows; jj++) {
+	    fits_read_descriptll(infptr, ii, jj, &length, &offset, status);
+	    fits_shuffle_4bytes(heap + offset, length, status);    
+	  }
+	  break;
+
+	case TDOUBLE:
+	case TLONGLONG:
+	  for (jj = 1; jj <= nrows; jj++) {
+	    fits_read_descriptll(infptr, ii, jj, &length, &offset, status);
+	    fits_shuffle_8bytes(heap + offset, length,  status);    
+	  }
+	  break;
+
+	default: /* don't have to do anything for other column types */
+	  break;
+
+	}   /* end of switch block */
+    }
+
+    /* gzip compress the shuffled heap */
+    theapsize = (size_t) heapsize;
+    compress2mem_from_mem(heap, (size_t) heapsize, &compheap,  &theapsize, 
+                          realloc, &compsize, status);        
+    free(heap);  /* don't need the uncompresse heap any more */
+    
+    /* update the internal pointers */
+    fits_set_hdustruc(outfptr, status);
+    
+    /* save offset to the start of the compressed heap, relative to the
+       start of the main data table in the ZHEAPPTR keyword, and
+       update PCOUNT to the new extended heap size */
+       
+    fits_read_key(outfptr, TLONGLONG, "PCOUNT", &pcount, NULL, status);
+    fits_get_num_rowsll(outfptr, &nrows, status);
+    fits_read_key(outfptr, TLONGLONG, "NAXIS1", &naxis1, NULL, status);
+
+    fits_write_key_lng(outfptr, "ZHEAPPTR", (LONGLONG) ((nrows * naxis1) + pcount), 
+                   "byte offset to compressed heap", status);
+    fits_modify_key_lng(outfptr, "PCOUNT", pcount + compsize, NULL, status);
+
+    /* now append the compressed heap to the heap in the output file */
+    dataend = (outfptr->Fptr)->datastart + (outfptr->Fptr)->heapstart + 
+                    (outfptr->Fptr)->heapsize;
+
+    ffmbyt(outfptr, dataend, IGNORE_EOF, status);
+    ffpbyt(outfptr, compsize, compheap, status);
+    free(compheap);   
+    
+    /* also update the internal pointer to the heap size */
+    (outfptr->Fptr)->heapsize = (outfptr->Fptr)->heapsize + compsize;
+
+    /* update the internal pointers again */
+    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_gunzip_heap(fitsfile *infptr, fitsfile *outfptr, int *status)
+
+/*
+   inverse of the fits_gzip_heap function: uncompress and unshuffle the heap
+   in the input file and write it to the output file
+*/
+{ 
+    LONGLONG datastart, nrows, naxis1, length, offset, pcount, jj;
+    LONGLONG zpcount, zheapptr, cheapsize;
+    int coltype, ncols, ii;
+    char *heap, *compheap;
+    size_t arraysize, theapsize;
+
+    if (*status > 0)
+        return(*status);
+
+    /* first, delete any COMMENT keywords written by fits_gzip_heap */
+    while (*status == 0) {
+        fits_delete_str(outfptr, "COMMENT [FPACK]", status);
+    }
+    if (*status == KEY_NO_EXIST) *status = 0;
+
+    /* ZPCOUNT = size of original uncompressed heap */
+    fits_read_key(infptr, TLONGLONG, "ZPCOUNT", &zpcount, NULL, status);
+
+    /* just return if there is no heap */
+    if (*status != 0 || zpcount == 0)
+        return(*status);
+
+    fits_get_num_rowsll(infptr, &nrows, status);
+    fits_read_key(infptr, TLONGLONG, "NAXIS1", &naxis1, NULL, status);
+
+    /* ZHEAPPTR = offset to the start of the compressed heap */
+    fits_read_key(infptr, TLONGLONG, "ZHEAPPTR", &zheapptr, NULL, status);
+
+    /* PCOUNT = total size of the compressed 2D table plus the compressed heap */
+    fits_read_key(infptr, TLONGLONG, "PCOUNT", &pcount, NULL, status);
+
+    /* size of the compressed heap */
+    cheapsize = pcount - (zheapptr - (naxis1 * nrows));
+
+    /* allocate memory for the heap and uncompressed heap */
+    arraysize = (size_t) zpcount;
+    heap = malloc(arraysize);
+    if (!heap) {
+        ffpmsg("Could not allocate buffer for the heap (fits_gunzip_heap");
+        *status = MEMORY_ALLOCATION;
+        return(*status);
+    }
+
+    compheap = malloc((size_t) cheapsize);
+    if (!compheap) {
+        ffpmsg("Could not allocate buffer for compressed heap (fits_gunzip_heap");
+ 	free(heap);
+        *status = MEMORY_ALLOCATION;
+        return(*status);
+    }
+
+    fits_get_hduaddrll(infptr, NULL, &datastart, NULL, status); 
+
+    /* read the compressed heap into memory */
+    ffmbyt(infptr, datastart + zheapptr, REPORT_EOF, status);
+    ffgbyt(infptr, cheapsize, compheap, status);
+
+    /* uncompress the heap */
+    theapsize = (size_t) zpcount;
+    uncompress2mem_from_mem(compheap, (size_t) cheapsize, &heap, &arraysize, 
+        realloc, &theapsize, status);        
+
+    free(compheap);   /* don't need the compressed heap any more */
+
+    if (theapsize != zpcount) {
+       /* something is wrong */
+       ffpmsg("uncompressed heap size != to ZPCOUNT");
+       free(heap);
+       *status = MEMORY_ALLOCATION;
+       return(*status);
+    }
+
+    /* get dimensions of the uncompressed table */
+    fits_get_num_rowsll(outfptr, &nrows, status);
+    fits_read_key(outfptr, TLONGLONG, "NAXIS1", &naxis1, NULL, status);
+    fits_get_num_cols(outfptr, &ncols, status);
+
+    for (ii = ncols; ii > 0; ii--) {
+
+        fits_get_coltype(outfptr, ii, &coltype, NULL, NULL, status);
+
+	if (coltype >= 0) continue;   /* only interested in variable length columns */
+	
+	coltype = coltype * (-1);
+	
+	switch (coltype) {
+	/* recombine the byte planes for the 2-byte, 4-byte, and 8-byte numeric columns */
+	case TSHORT:
+
+	  for (jj = nrows; jj > 0; jj--) {
+	    fits_read_descriptll(outfptr, ii, jj, &length, &offset, status);
+	    fits_unshuffle_2bytes(heap + offset, length, status);    
+	  }
+	  break;
+	
+	case TLONG:
+	case TFLOAT:
+	  for (jj = nrows; jj > 0; jj--) {
+	    fits_read_descriptll(outfptr, ii, jj, &length, &offset, status);
+	    fits_unshuffle_4bytes(heap + offset, length, status);    
+	  }
+	  break;
+
+	case TDOUBLE:
+	case TLONGLONG:
+	  for (jj = nrows; jj > 0; jj--) {
+	    fits_read_descriptll(outfptr, ii, jj, &length, &offset, status);
+	    fits_unshuffle_8bytes(heap + offset, length,  status);    
+	  }
+	  break;
+
+	default: /* don't need to recombine bytes for other column types */
+	  break;
+
+	}   /* end of switch block */
+    }
+
+    /* copy the unshuffled heap back to the output file */
+    fits_get_hduaddrll(outfptr, NULL, &datastart, NULL, status); 
+
+    ffmbyt(outfptr, datastart + (nrows * naxis1), IGNORE_EOF, status);
+    ffpbyt(outfptr, zpcount, heap, status);
+
+    free(heap);   
+
+    /* also update the internal pointer to the heap size */
+    (outfptr->Fptr)->heapsize = zpcount;
+
+    /* update the internal pointers again */
+    fits_set_hdustruc(outfptr, status);
+ 
+    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);
+}
diff --git a/cextern/cfitsio/infback.c b/cextern/cfitsio/infback.c
new file mode 100644
index 0000000..af3a8c9
--- /dev/null
+++ b/cextern/cfitsio/infback.c
@@ -0,0 +1,632 @@
+/* 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;
+}
diff --git a/cextern/cfitsio/inffast.c b/cextern/cfitsio/inffast.c
new file mode 100644
index 0000000..2f1d60b
--- /dev/null
+++ b/cextern/cfitsio/inffast.c
@@ -0,0 +1,340 @@
+/* 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 */
diff --git a/cextern/cfitsio/inffast.h b/cextern/cfitsio/inffast.h
new file mode 100644
index 0000000..e5c1aa4
--- /dev/null
+++ b/cextern/cfitsio/inffast.h
@@ -0,0 +1,11 @@
+/* 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));
diff --git a/cextern/cfitsio/inffixed.h b/cextern/cfitsio/inffixed.h
new file mode 100644
index 0000000..75ed4b5
--- /dev/null
+++ b/cextern/cfitsio/inffixed.h
@@ -0,0 +1,94 @@
+    /* 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}
+    };
diff --git a/cextern/cfitsio/inflate.c b/cextern/cfitsio/inflate.c
new file mode 100644
index 0000000..a8431ab
--- /dev/null
+++ b/cextern/cfitsio/inflate.c
@@ -0,0 +1,1480 @@
+/* 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 <stdio.h>
+
+/*
+   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));
+}
diff --git a/cextern/cfitsio/inflate.h b/cextern/cfitsio/inflate.h
new file mode 100644
index 0000000..95f4986
--- /dev/null
+++ b/cextern/cfitsio/inflate.h
@@ -0,0 +1,122 @@
+/* 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 */
+};
diff --git a/cextern/cfitsio/inftrees.c b/cextern/cfitsio/inftrees.c
new file mode 100644
index 0000000..11e9c52
--- /dev/null
+++ b/cextern/cfitsio/inftrees.c
@@ -0,0 +1,330 @@
+/* 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;
+}
diff --git a/cextern/cfitsio/inftrees.h b/cextern/cfitsio/inftrees.h
new file mode 100644
index 0000000..baa53a0
--- /dev/null
+++ b/cextern/cfitsio/inftrees.h
@@ -0,0 +1,62 @@
+/* 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));
diff --git a/cextern/cfitsio/iraffits.c b/cextern/cfitsio/iraffits.c
new file mode 100644
index 0000000..d8fc06b
--- /dev/null
+++ b/cextern/cfitsio/iraffits.c
@@ -0,0 +1,2073 @@
+/*------------------------------------------------------------------------*/
+/*                                                                        */
+/*  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 <stdio.h>		/* define stderr, FD, and NULL */
+#include <stdlib.h>
+#include <stddef.h>  /* stddef.h is apparently needed to define size_t */
+#include <string.h>
+
+#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(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, 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 (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);
+
+/*--------------------------------------------------------------------------*/
+int fits_delete_iraf_file(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 (
+    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[81];
+    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) {
+	sprintf(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) {
+	sprintf(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[81];
+    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) {
+	sprintf(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) {
+	sprintf(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) {
+	sprintf(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[81];
+
+    /* 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) {
+	sprintf(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:
+	    sprintf(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 (
+    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 */
+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 <keyword>= <value> {/ <comment>} */
+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 <keyword>= <value> {/ <comment>} */
+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 <keyword>= <value> {/ <comment>} */
+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;
+	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 = strtok (v1,cwhite);
+		    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 <keyword>= <value> {/ <comment>}
+		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 <keyword>= <value> {/ <comment>}
+		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
+			   <keyword>= <value> {/ <comment>}
+			   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 */
+    sprintf (value,"%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);
+	    }
+
+}
diff --git a/cextern/cfitsio/longnam.h b/cextern/cfitsio/longnam.h
new file mode 100644
index 0000000..cac8da4
--- /dev/null
+++ b/cextern/cfitsio/longnam.h
@@ -0,0 +1,592 @@
+#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 the same version
+   as included when compiling the application program
+*/
+#define fits_open_file(A, B, C, D)  ffopentest( CFITSIO_VERSION, A, B, C, D)
+
+#define fits_open_data      ffdopn
+#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_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_read_key_longstr  ffgkls
+#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
+
+#endif
diff --git a/cextern/cfitsio/modkey.c b/cextern/cfitsio/modkey.c
new file mode 100644
index 0000000..e6fe03a
--- /dev/null
+++ b/cextern/cfitsio/modkey.c
@@ -0,0 +1,1706 @@
+/*  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 <string.h>
+/* stddef.h is apparently needed to define size_t */
+#include <ctype.h>
+#include <stddef.h>
+#include <stdlib.h>
+#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            */
+           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       */
+           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       */
+           char *value,       /* I - keyword value      */
+           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       */
+           char *value,       /* I - keyword value      */
+           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      */
+           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      */
+           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     */         
+           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     */
+           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     */
+           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     */
+           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     */         
+           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     */
+           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     */
+           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     */
+           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       */
+           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 */
+           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       */
+           char *card,        /* I - card string value  */
+           int *status)       /* IO - error status      */
+{
+    char tcard[FLEN_CARD], valstring[FLEN_CARD], comm[FLEN_CARD], value[FLEN_CARD];
+    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);
+
+    /* check for string value which may be continued over multiple keywords */
+    ffc2s(valstring, value, status);   /* remove quotes and trailing spaces */
+    len = strlen(value);
+
+    while (len && value[len - 1] == '&')  /* ampersand used as continuation char */
+    {
+        ffgcnt(fptr, value, 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       */
+           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        */
+           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 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 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       */
+           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       */
+           char *value,       /* I - keyword value      */
+           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];
+    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);
+
+    /* check if old string value was continued over multiple keywords */
+    ffc2s(oldval, valstring, status); /* remove quotes and trailing spaces */
+    len = strlen(valstring);
+
+    while (len && valstring[len - 1] == '&')  /* ampersand is continuation char */
+    {
+        ffgcnt(fptr, valstring, 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 */
+            char *value,        /* I - keyword value            */
+            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
+    {
+        /* This a HIERARCH keyword */
+        if (FSTRNCMP(cptr, "HIERARCH ", 9) && 
+            FSTRNCMP(cptr, "hierarch ", 9))
+            nchar = 66 - nquote - namelen;
+        else
+            nchar = 75 - nquote - namelen;  /* don't count 'HIERARCH' twice */
+
+    }
+
+    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      */
+           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      */
+           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     */
+           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     */
+           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     */
+           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     */
+           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     */
+           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     */
+           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     */
+           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     */
+           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       */
+           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       */
+           char *value,       /* I - keyword value      */
+           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 */
+            char *value,        /* I - keyword value            */
+            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
+    {
+        /* This a HIERARCH keyword */
+        if (FSTRNCMP(cptr, "HIERARCH ", 9) && 
+            FSTRNCMP(cptr, "hierarch ", 9))
+            nchar = 66 - nquote - namelen;
+        else
+            nchar = 75 - nquote - namelen;  /* don't count 'HIERARCH' twice */
+
+    }
+
+    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      */
+           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      */
+           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     */
+           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     */
+           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     */
+           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     */
+           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     */
+           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     */
+           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     */
+           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     */
+           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 */
+           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  */
+           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;
+    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] = ' ';
+
+    for (ii=0; ii < 8; 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];
+
+    if (*status > 0)           /* inherit input status value if > 0 */
+        return(*status);
+
+    if (ffgkey(fptr, keyname, valstring, comm, status) > 0) /* read keyword */
+    {
+        sprintf(message, "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 */
+
+    /* check for string value which may be continued over multiple keywords */
+    ffc2s(valstring, value, status);   /* remove quotes and trailing spaces */
+    len = strlen(value);
+
+    while (len && value[len - 1] == '&')  /* ampersand used as continuation char */
+    {
+        ffgcnt(fptr, value, 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];
+
+    if (*status > 0)           /* inherit input status value if > 0 */
+        return(*status);
+
+    if (ffgstr(fptr, string, card, status) > 0) /* read keyword */
+    {
+        sprintf(message, "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);
+    ffc2s(valstring, value, status);   /* remove quotes and trailing spaces */
+    len = strlen(value);
+
+    while (len && value[len - 1] == '&')  /* ampersand used as continuation char */
+    {
+        ffgcnt(fptr, value, 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)
+    {
+        sprintf(message, "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);
+}
+
diff --git a/cextern/cfitsio/pliocomp.c b/cextern/cfitsio/pliocomp.c
new file mode 100644
index 0000000..682599f
--- /dev/null
+++ b/cextern/cfitsio/pliocomp.c
@@ -0,0 +1,331 @@
+/* stdlib is needed for the abs function */
+#include <stdlib.h>
+/*
+   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, 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_ */
+
diff --git a/cextern/cfitsio/putcol.c b/cextern/cfitsio/putcol.c
new file mode 100644
index 0000000..0bfc927
--- /dev/null
+++ b/cextern/cfitsio/putcol.c
@@ -0,0 +1,1929 @@
+/*  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 <string.h>
+#include <stdlib.h>
+#include <limits.h>
+#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) {
+	      sprintf(message,
+              "Variable length array not allowed for output column number %d (ffiter)",
+                    jj + 1);
+	    } else {
+            sprintf(message,
+                   "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)
+            {
+                sprintf(message,
+                "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)
+            {
+                sprintf(message,
+                "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) )
+                {
+                    sprintf(message,
+                      "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)
+            {
+                sprintf(message,
+                  "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) {
+ 	        sprintf(message,
+                "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)
+            {
+                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)
+            {
+                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)
+          {
+              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)
+          {
+              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)
+          {
+              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)
+          {
+              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)
+          {
+              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)
+          {
+              tnull = minvalue(tnull, INT32_MAX);
+              tnull = maxvalue(tnull, 0);
+              col[jj].null.uintnull = (unsigned int) tnull;
+          }
+          else
+          {
+              col[jj].null.intnull = 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)
+          {
+              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)
+          {
+              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)
+          {
+              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)
+          {
+              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)
+          {
+              col[jj].null.longlongnull = tnull;
+          }
+          else
+          {
+              col[jj].null.longlongnull = LONGLONG_MIN;   /* use minimum as null */
+          }
+          break;
+
+         default:
+          sprintf(message,
+                  "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);
+}
+
diff --git a/cextern/cfitsio/putcolb.c b/cextern/cfitsio/putcolb.c
new file mode 100644
index 0000000..120cca8
--- /dev/null
+++ b/cextern/cfitsio/putcolb.c
@@ -0,0 +1,1012 @@
+/*  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 <limits.h>
+#include <string.h>
+#include <stdlib.h>
+#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, maxelem, hdutype, writeraw;
+    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 */
+
+    /*
+      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;
+        maxelem = (int) nelem;  /* we can write the entire array at one time */
+    }
+    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  */
+                sprintf(message, 
+                       "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 */
+        {
+          sprintf(message,
+          "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;
+    long  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);
+}
diff --git a/cextern/cfitsio/putcold.c b/cextern/cfitsio/putcold.c
new file mode 100644
index 0000000..b0c135a
--- /dev/null
+++ b/cextern/cfitsio/putcold.c
@@ -0,0 +1,1059 @@
+/*  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 <limits.h>
+#include <string.h>
+#include <stdlib.h>
+#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, maxelem, hdutype, writeraw;
+    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 */
+
+    /*
+      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;
+        maxelem = (int) nelem;  /* we can write the entire array at one time */
+    }
+    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  */
+                sprintf(message, 
+                      "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 */
+        {
+          sprintf(message,
+          "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;
+    long  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);
+}
diff --git a/cextern/cfitsio/putcole.c b/cextern/cfitsio/putcole.c
new file mode 100644
index 0000000..c13f04c
--- /dev/null
+++ b/cextern/cfitsio/putcole.c
@@ -0,0 +1,1073 @@
+/*  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 <limits.h>
+#include <string.h>
+#include <stdlib.h>
+#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, maxelem, hdutype, writeraw;
+    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 */
+
+    /*
+       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;
+        maxelem = (int) nelem;  /* we can write the entire array at one time */
+    }
+    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  */
+                sprintf(message, 
+                       "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 */
+        {
+          sprintf(message,
+          "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;
+    long  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);
+}
diff --git a/cextern/cfitsio/putcoli.c b/cextern/cfitsio/putcoli.c
new file mode 100644
index 0000000..bddc459
--- /dev/null
+++ b/cextern/cfitsio/putcoli.c
@@ -0,0 +1,985 @@
+/*  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 <limits.h>
+#include <string.h>
+#include <stdlib.h>
+#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, maxelem, hdutype, writeraw;
+    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 */
+
+    /*
+      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;
+        maxelem = (int) nelem;  /* we can write the entire array at one time */
+    }
+    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  */
+                sprintf(message, 
+                    "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 */
+        {
+         sprintf(message,
+          "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;
+    long  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, *tptr;
+    
+    cptr = output;
+    tptr = 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);
+}
diff --git a/cextern/cfitsio/putcolj.c b/cextern/cfitsio/putcolj.c
new file mode 100644
index 0000000..b7f6713
--- /dev/null
+++ b/cextern/cfitsio/putcolj.c
@@ -0,0 +1,1990 @@
+/*  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 <limits.h>
+#include <string.h>
+#include <stdlib.h>
+#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, maxelem, hdutype, writeraw;
+    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 */
+
+    /*
+       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;
+        maxelem = (int) nelem;  /* we can write the entire array at one time */
+    }
+    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  */
+                sprintf(message, 
+                     "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 */
+        {
+          sprintf(message,
+          "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;
+    long  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, maxelem, hdutype, writeraw;
+    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 */
+
+    /*
+       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;
+        maxelem = (int) nelem;  /* we can write the entire array at one time */
+    }
+    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  */
+                sprintf(message, 
+                     "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 */
+        {
+          sprintf(message,
+          "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;
+    long  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);
+}
diff --git a/cextern/cfitsio/putcolk.c b/cextern/cfitsio/putcolk.c
new file mode 100644
index 0000000..005a142
--- /dev/null
+++ b/cextern/cfitsio/putcolk.c
@@ -0,0 +1,1012 @@
+/*  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 <limits.h>
+#include <string.h>
+#include <stdlib.h>
+#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, maxelem, hdutype, writeraw;
+    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))
+        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, &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 */
+
+    /*
+       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;
+        maxelem = (int) nelem;  /* we can write the entire array at one time */
+    }
+    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  */
+                sprintf(message, 
+                     "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 */
+        {
+          sprintf(message,
+          "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;
+    long  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);
+}
diff --git a/cextern/cfitsio/putcoll.c b/cextern/cfitsio/putcoll.c
new file mode 100644
index 0000000..b26e911
--- /dev/null
+++ b/cextern/cfitsio/putcoll.c
@@ -0,0 +1,369 @@
+/*  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 <string.h>
+#include <stdlib.h>
+#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 */
+      {
+        sprintf(message,
+           "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;
+    long  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};
+    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).        */
+
+        if (tcode == -TBIT)
+            ffpdes(fptr, colnum, frow, (long) repeat, offset, 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;
+    }
+}
+
diff --git a/cextern/cfitsio/putcols.c b/cextern/cfitsio/putcols.c
new file mode 100644
index 0000000..86d624e
--- /dev/null
+++ b/cextern/cfitsio/putcols.c
@@ -0,0 +1,303 @@
+/*  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 <string.h>
+#include <stdlib.h>
+#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)
+    {
+        sprintf(message, "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 */
+      {
+         sprintf(message,
+          "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 */
+      {
+         sprintf(message,
+          "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, 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);
+}
diff --git a/cextern/cfitsio/putcolsb.c b/cextern/cfitsio/putcolsb.c
new file mode 100644
index 0000000..25ee5d1
--- /dev/null
+++ b/cextern/cfitsio/putcolsb.c
@@ -0,0 +1,974 @@
+/*  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 <limits.h>
+#include <string.h>
+#include <stdlib.h>
+#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  */
+                sprintf(message, 
+                       "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 */
+        {
+          sprintf(message,
+          "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;
+    long  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);
+}
diff --git a/cextern/cfitsio/putcolu.c b/cextern/cfitsio/putcolu.c
new file mode 100644
index 0000000..90227f0
--- /dev/null
+++ b/cextern/cfitsio/putcolu.c
@@ -0,0 +1,629 @@
+/*  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 <string.h>
+#include <stdlib.h>
+#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;
+    long 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
+         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  */
+                sprintf(message, 
+                   "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 */
+        {
+           sprintf(message,
+             "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;
+    long 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  */
+                sprintf(message, 
+                   "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 */
+        {
+           sprintf(message,
+             "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;
+}
+
diff --git a/cextern/cfitsio/putcolui.c b/cextern/cfitsio/putcolui.c
new file mode 100644
index 0000000..e52b176
--- /dev/null
+++ b/cextern/cfitsio/putcolui.c
@@ -0,0 +1,969 @@
+/*  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 <limits.h>
+#include <string.h>
+#include <stdlib.h>
+#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  */
+                sprintf(message, 
+                    "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 */
+        {
+         sprintf(message,
+          "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;
+    long  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);
+}
diff --git a/cextern/cfitsio/putcoluj.c b/cextern/cfitsio/putcoluj.c
new file mode 100644
index 0000000..9f89f10
--- /dev/null
+++ b/cextern/cfitsio/putcoluj.c
@@ -0,0 +1,977 @@
+/*  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 <limits.h>
+#include <string.h>
+#include <stdlib.h>
+#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  */
+                sprintf(message, 
+                     "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 */
+        {
+          sprintf(message,
+          "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;
+    long  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);
+}
diff --git a/cextern/cfitsio/putcoluk.c b/cextern/cfitsio/putcoluk.c
new file mode 100644
index 0000000..dd92fe3
--- /dev/null
+++ b/cextern/cfitsio/putcoluk.c
@@ -0,0 +1,993 @@
+/*  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 <limits.h>
+#include <string.h>
+#include <stdlib.h>
+#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  */
+                sprintf(message, 
+                     "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 */
+        {
+          sprintf(message,
+          "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;
+    long  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);
+}
diff --git a/cextern/cfitsio/putkey.c b/cextern/cfitsio/putkey.c
new file mode 100644
index 0000000..2a88096
--- /dev/null
+++ b/cextern/cfitsio/putkey.c
@@ -0,0 +1,3085 @@
+/*  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 <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <time.h>
+/* stddef.h is apparently needed to define size_t */
+#include <stddef.h>
+#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[81];
+
+    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
+    {
+        sprintf(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;
+
+    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] = ' ';
+
+    for (ii=0; ii < 8; 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 */
+            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;
+
+    if (*status > 0)           /* inherit input status value if > 0 */
+        return(*status);
+
+    remain = maxvalue(strlen(value), 1); /* no. of chars to write (at least 1) */    
+    /* 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
+    {
+        /* This a HIERARCH keyword */
+        if (FSTRNCMP(cptr, "HIERARCH ", 9) && 
+            FSTRNCMP(cptr, "hierarch ", 9))
+            nchar = 66 - nquote - namelen;
+        else
+            nchar = 75 - nquote - namelen;  /* don't count 'HIERARCH' twice */
+
+    }
+
+    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);  /* 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 */
+        }
+
+        ffprec(fptr, card, status);  /* write the keyword */
+
+        contin = 1;
+        remain -= nchar;
+        next  += nchar;
+
+        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 */
+        }
+    }
+    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[81];
+    
+
+    if (year < 0 || year > 9999)
+    {
+       sprintf(errmsg, 
+       "input year value = %d is out of range 0 - 9999", year);
+       ffpmsg(errmsg);
+       return(*status = BAD_DATE);
+    }
+    else if (month < 1 || month > 12)
+    {
+       sprintf(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)
+        {
+           sprintf(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)
+        {
+           sprintf(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);
+		   
+ 	        sprintf(errmsg, 
+           "input day value = %d is out of range 1 - 28 for February %d (not leap year)", day, year);
+                ffpmsg(errmsg);
+	    } else {
+                sprintf(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[81];
+
+    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)
+    {
+       sprintf(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)
+    {
+       sprintf(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)
+    {
+       sprintf(errmsg, 
+       "input second value is out of range 0 - 60.999: %f (fftm2s)", second);
+       ffpmsg(errmsg);
+       return(*status = BAD_DATE);
+    }
+    else if (decimals > 25)
+    {
+       sprintf(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[81];
+
+    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)
+       {
+          sprintf(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)
+       {
+          sprintf(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.)
+       {
+          sprintf(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[81];
+    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);
+        }
+
+        sprintf(value, "%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)
+      {
+        sprintf(message,
+        "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 )            */
+
+        sprintf(value, "%.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)
+      {
+        sprintf(message,
+        "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)
+    {
+        sprintf(message,
+        "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)
+    {
+        sprintf(message,
+        "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)
+        {
+            sprintf(message,
+            "Illegal negative value for NAXIS%d keyword: %.0f", ii + 1, (double) (naxes[ii]));
+            ffpmsg(message);
+            return(*status = BAD_NAXES);
+        }
+
+        sprintf(&comm[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 */
+        {
+          sprintf(comm, "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;
+
+        sprintf(comm, "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)
+    {
+      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')
+           /* 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 */
+        {
+          sprintf(comm, "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)
+    {
+      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)
+    {
+        sprintf(message,
+        "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)
+        {
+            sprintf(message,
+            "Illegal negative value for NAXIS%d keyword: %.0f", ii + 1, (double) (naxes[ii]));
+            ffpmsg(message);
+            return(*status = BAD_NAXES);
+        }
+
+        sprintf(&comm[20], "%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(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);
+}
+
diff --git a/cextern/cfitsio/quantize.c b/cextern/cfitsio/quantize.c
new file mode 100644
index 0000000..8fe6acc
--- /dev/null
+++ b/cextern/cfitsio/quantize.c
@@ -0,0 +1,3888 @@
+/*
+  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 <stdio.h>
+# include <stdlib.h>
+# include <math.h>
+# include <limits.h>
+# include <float.h>
+
+#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 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 idata[], double *bscale,
+	double *bzero, int *iminval, int *imaxval) {
+
+/* arguments:
+long row            i: if positive, tile number = row number in the binary table
+                       (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 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, anynulls = 0, iseed;
+	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 ((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++) {
+	    
+		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) {
+		    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 idata[], double *bscale,
+	double *bzero, int *iminval, int *imaxval) {
+
+/* arguments:
+long row            i: tile number = row number in the binary table
+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
+int noise_bits      i: quantization level (number of bits)
+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, anynulls = 0, iseed;
+	long i, nx, ngood = 0;
+	double stdev, noise2, noise3, noise5;	/* 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 ((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++) {
+
+		idata[i] =  NINT((((double) fdata[i] - zeropt) / delta) + fits_rand_value[nextrand] - 0.5);
+
+                nextrand++;
+		if (nextrand == N_RANDOM) {
+                    iseed++;
+	            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) {
+		    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++;
+	                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, 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_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, 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_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 < 5) {
+		/* 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 */
+
+		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;
+		}
+			
+		/* 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 */
+
+		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 */
+
+		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 */
+
+		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 */
+
+		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 + 8);
+
+		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 < 5) {
+		/* 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 */
+
+		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;
+		}
+			
+		/* 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 */
+
+		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 */
+
+		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 */
+
+		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 */
+
+		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 + 8);
+
+		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 < 5) {
+		/* 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 */
+
+		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;
+		}
+			
+		/* 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 */
+
+		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 */
+
+		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 */
+
+		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 */
+
+		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 + 8);
+
+		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 < 5) {
+		/* 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 */
+
+		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;
+		}
+			
+		/* 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 */
+
+		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 */
+
+		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 */
+
+		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 */
+
+		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 + 8);
+
+		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
+
+
diff --git a/cextern/cfitsio/region.c b/cextern/cfitsio/region.c
new file mode 100644
index 0000000..3ec5bc2
--- /dev/null
+++ b/cextern/cfitsio/region.c
@@ -0,0 +1,1747 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <ctype.h>
+#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 ) {
+      sprintf(currLine,"Could not open Region file %s.",filename);
+      ffpmsg( currLine );
+      free( currLine );
+      free( aRgn );
+      return( *status = FILE_NOT_OPENED );
+   }
+   
+   /*  Read in file, line by line  */
+
+   while( fgets(currLine,allocLen,rgnFile) != NULL ) {
+
+      /*  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( !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( !strncasecmp( currLoc, "pixel", 5 ) ) {
+               cFmt = pixel_fmt;
+            } else if( !strncasecmp( currLoc, "degree", 6 ) ) {
+               cFmt = degree_fmt;
+            } else if( !strncasecmp( currLoc, "hhmmss", 6 ) ) {
+               cFmt = hhmmss_fmt;
+            } else if( !strncasecmp( currLoc, "hms", 3 ) ) {
+               cFmt = hhmmss_fmt;
+            } else {
+               ffpmsg("Unknown format code encountered in region file.");
+               *status = PARSE_SYNTAX_ERR;
+               goto error;
+            }
+         }
+
+      } else if( !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( !strncasecmp( namePtr, "image;", 6 ) ) {
+				namePtr += 6;
+				cFmt = pixel_fmt;
+            } else if( !strncasecmp( namePtr, "physical;", 9 ) ) {
+                                namePtr += 9;
+                                cFmt = pixel_fmt;
+            } else if( !strncasecmp( namePtr, "linear;", 7 ) ) {
+                                namePtr += 7;
+                                cFmt = pixel_fmt;
+            } else if( !strncasecmp( namePtr, "fk4;", 4 ) ) {
+				namePtr += 4;
+				cFmt = degree_fmt;
+            } else if( !strncasecmp( namePtr, "fk5;", 4 ) ) {
+				namePtr += 4;
+				cFmt = degree_fmt;
+            } else if( !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( !strncasecmp( namePtr, "fk5", 3 ) ) {
+				cFmt = degree_fmt;
+                                continue;  /* supports POW region file format */
+            } else if( !strncasecmp( namePtr, "fk4", 3 ) ) {
+				cFmt = degree_fmt;
+                                continue;  /* supports POW region file format */
+            } else if( !strncasecmp( namePtr, "icrs", 4 ) ) {
+				cFmt = degree_fmt;
+                                continue;  /* supports POW region file format */
+            } else if( !strncasecmp( namePtr, "image", 5 ) ) {
+				cFmt = pixel_fmt;
+                                continue;  /* supports POW region file format */
+            } else if( !strncasecmp( namePtr, "physical", 8 ) ) {
+				cFmt = pixel_fmt;
+                                continue;  /* supports POW region file format */
+
+
+            } else if( !strncasecmp( namePtr, "galactic;", 9 ) ) {
+               ffpmsg( "Galactic region coordinates not supported" );
+               ffpmsg( namePtr );
+               *status = PARSE_SYNTAX_ERR;
+               goto error;
+            } else if( !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(        !strcasecmp( namePtr, "circle"  ) ) {
+               newShape->shape = circle_rgn;
+               if( nParams != 3 )
+                  *status = PARSE_SYNTAX_ERR;
+               nCoords = 2;
+            } else if( !strcasecmp( namePtr, "annulus" ) ) {
+               newShape->shape = annulus_rgn;
+               if( nParams != 4 )
+                  *status = PARSE_SYNTAX_ERR;
+               nCoords = 2;
+            } else if( !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( !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( !strcasecmp( namePtr, "box"    ) 
+                    || !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( !strcasecmp( namePtr, "rectangle"    )
+                    || !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( !strcasecmp( namePtr, "diamond"    )
+                    || !strcasecmp( namePtr, "rotdiamond" )
+                    || !strcasecmp( namePtr, "rhombus"    )
+                    || !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( !strcasecmp( namePtr, "sector"  )
+                    || !strcasecmp( namePtr, "pie"     ) ) {
+               newShape->shape = sector_rgn;
+               if( nParams != 4 )
+                  *status = PARSE_SYNTAX_ERR;
+               nCoords = 2;
+            } else if( !strcasecmp( namePtr, "point"   ) ) {
+               newShape->shape = point_rgn;
+               if( nParams != 2 )
+                  *status = PARSE_SYNTAX_ERR;
+               nCoords = 2;
+            } else if( !strcasecmp( namePtr, "line"    ) ) {
+               newShape->shape = line_rgn;
+               if( nParams != 4 )
+                  *status = PARSE_SYNTAX_ERR;
+               nCoords = 4;
+            } else if( !strcasecmp( namePtr, "polygon" ) ) {
+               newShape->shape = poly_rgn;
+               if( nParams < 6 || (nParams&1) )
+                  *status = PARSE_SYNTAX_ERR;
+               nCoords = nParams;
+            } else if( !strcasecmp( namePtr, "panda" ) ) {
+               newShape->shape = panda_rgn;
+               if( nParams != 8 )
+                  *status = PARSE_SYNTAX_ERR;
+               nCoords = 2;
+            } else if( !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( !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; i<nCoords; i+=2 ) {
+
+               pX = paramPtr;
+               while( *paramPtr!=',' ) paramPtr++;
+               *(paramPtr++) = '\0';
+
+               pY = paramPtr;
+               while( *paramPtr!=',' && *paramPtr != '\0' ) paramPtr++;
+               *(paramPtr++) = '\0';
+
+               if( strchr(pX, ':' ) ) {
+                  /*  Read in special format & convert to decimal degrees  */
+                  cFmt = hhmmss_fmt;
+                  mm = 0;
+                  ss = 0.;
+                  hh = strtol(pX, &endp, 10);
+                  if (endp && *endp==':') {
+                      pX = endp + 1;
+                      mm = strtol(pX, &endp, 10);
+                      if (endp && *endp==':') {
+                          pX = endp + 1;
+                          ss = atof( pX );
+                      }
+                  }
+                  X = 15. * (hh + mm/60. + ss/3600.); /* convert to degrees */
+
+                  mm = 0;
+                  ss = 0.;
+                  negdec = 0;
+
+                  while( isspace(*pY) ) pY++;
+                  if (*pY=='-') {
+                      negdec = 1;
+                      pY++;
+                  }
+                  dd = strtol(pY, &endp, 10);
+                  if (endp && *endp==':') {
+                      pY = endp + 1;
+                      mm = strtol(pY, &endp, 10);
+                      if (endp && *endp==':') {
+                          pY = endp + 1;
+                          ss = atof( pY );
+                      }
+                  }
+                  if (negdec)
+                     Y = -dd - mm/60. - ss/3600.; /* convert to degrees */
+                  else
+                     Y = dd + mm/60. + ss/3600.;
+
+               } else {
+                  X = atof( pX );
+                  Y = atof( pY );
+               }
+               if (i==0) {   /* save 1st coord. in case needed later */
+                   xsave = X;
+                   ysave = Y;
+               }
+
+               if( cFmt!=pixel_fmt ) {
+                  /*  Convert to pixels  */
+                  if( wcs==NULL || ! wcs->exists ) {
+                     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( ; i<nParams; i++ ) {
+               pX = paramPtr;
+               while( *paramPtr!=',' && *paramPtr != '\0' ) paramPtr++;
+               *(paramPtr++) = '\0';
+               coords[i] = strtod( pX, &endp );
+
+	       if (endp && (*endp=='"' || *endp=='\'' || *endp=='d') ) {
+		  div = 1.0;
+		  if ( *endp=='"' ) div = 3600.0;
+		  if ( *endp=='\'' ) div = 60.0;
+		  /* parameter given in arcsec so convert to pixels. */
+		  /* Increment first Y coordinate by this amount then calc */
+		  /* the distance in pixels from the original coordinate. */
+		  /* NOTE: This assumes the pixels are square!! */
+		  if (ysave < 0.)
+		     Y = ysave + coords[i]/div;  /* don't exceed -90 */
+		  else
+		     Y = ysave - coords[i]/div;  /* don't exceed +90 */
+
+		  X = xsave;
+		  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;
+		  }
+		 
+		  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);
+	      }
+	    }
+
+	    /* 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; i<Rgn->nShapes; 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( X<Shapes->xmin || X>Shapes->xmax
+             || Y<Shapes->ymin || 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; i<Rgn->nShapes; 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; i<nPts; i+=2 ) {
+      prevX = nextX;
+      prevY = nextY;
+
+      nextX = Pts[i];
+      nextY = Pts[i+1];
+
+      if( (y>prevY && y>=nextY) || (y<prevY && y<=nextY)
+          || (x>prevX && 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 ( i<aRgn->nShapes ) {
+
+    /* 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; i<aRgn->nShapes; 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;
+  }
+
+  /*  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;
+
+  }
+
+  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;
+
+  }
+
+  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, Ysave, 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;
+
+  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], &regwcs->xrefval,  &regwcs->yrefval,
+		&regwcs->xrefpix, &regwcs->yrefpix, &regwcs->xinc, &regwcs->yinc,
+		&regwcs->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<9; 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; j<npos; j++) {
+      if ( ffgcvd(fptr, icol[0], i, j+1, 1, DOUBLENULLVALUE, coords, &anynul, status) ) {
+	ffpmsg("Failed to read X 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;
+	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; j<npos; j++) {
+	ffwldp(coords[2*j], coords[2*j+1], regwcs->xrefval, 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;
+    }
+
+    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; j<npos; j++) {
+	  Y = Ysave + (*coords);
+	  X = Xsave;
+	  ffwldp(X, Y, regwcs->xrefval, 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;
+    }
+
+    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; j<npos; j++) *(coords++) += Theta;
+      } else {
+	coords += npos;
+      }
+    }
+
+  /* read the component number */
+
+    if (got_component) {
+      if ( ffgcv(fptr, TINT, icol[5], i, 1, 1, 0, &newShape->comp, &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 );
+}
+
diff --git a/cextern/cfitsio/region.h b/cextern/cfitsio/region.h
new file mode 100644
index 0000000..516c4fd
--- /dev/null
+++ b/cextern/cfitsio/region.h
@@ -0,0 +1,82 @@
+/***************************************************************/
+/*                   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);
+
+
diff --git a/cextern/cfitsio/ricecomp.c b/cextern/cfitsio/ricecomp.c
new file mode 100644
index 0000000..d5a11a4
--- /dev/null
+++ b/cextern/cfitsio/ricecomp.c
@@ -0,0 +1,1382 @@
+/*
+  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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+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);
+
+/* 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<<fsbits;
+
+    /*
+     * Set up buffer pointers
+     */
+    buffer->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<nx; i += nblock) {
+	/* last block may be shorter */
+	if (nx-i < nblock) thisblock = nx-i;
+	/*
+	 * Compute differences of adjacent pixels and map them to unsigned values.
+	 * Note that this may overflow the integer variables -- that's
+	 * OK, because we can recover when decompressing.  If we were
+	 * compressing shorts or bytes, would want to do this arithmetic
+	 * with short/byte working variables (though diff will still be
+	 * passed as an int.)
+	 *
+	 * compute sum of mapped pixel values at same time
+	 * use double precision for sum to allow 32-bit integer inputs
+	 */
+	pixelsum = 0.0;
+	for (j=0; j<thisblock; j++) {
+	    nextpix = a[i+j];
+	    pdiff = nextpix - lastpix;
+	    diff[j] = (unsigned int) ((pdiff<0) ? ~(pdiff<<1) : (pdiff<<1));
+	    pixelsum += diff[j];
+	    lastpix = nextpix;
+	}
+
+	/*
+	 * compute number of bits to split from sum
+	 */
+	dpsum = (pixelsum - (thisblock/2) - 1)/thisblock;
+	if (dpsum < 0) dpsum = 0.0;
+	psum = ((unsigned int) 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; j<thisblock; j++) {
+		if (output_nbits(buffer, diff[j], bbits) == EOF) {
+                    ffpmsg("rice_encode: end of buffer");
+                    free(diff);
+		    return(-1);
+		}
+	    }
+	} else if (fs == 0 && pixelsum == 0) {
+	    /*
+	     * special low entropy case when FS = 0 and pixelsum=0 (all
+	     * pixels in block are zero.)
+	     * Output a 0 and return
+	     */
+	    if (output_nbits(buffer, 0, fsbits) == EOF) {
+                ffpmsg("rice_encode: end of buffer");
+                free(diff);
+		return(-1);
+	    }
+	} else {
+	    /* normal case: not either very high or very low entropy */
+	    if (output_nbits(buffer, fs+1, fsbits) == EOF) {
+                ffpmsg("rice_encode: end of buffer");
+                free(diff);
+		return(-1);
+	    }
+	    fsmask = (1<<fs) - 1;
+	    /*
+	     * local copies of bit buffer to improve optimization
+	     */
+	    lbitbuffer = buffer->bitbuffer;
+	    lbits_to_go = buffer->bits_to_go;
+	    for (j=0; j<thisblock; j++) {
+		v = diff[j];
+		top = v >> 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<<fsbits;
+
+    /*
+     * Set up buffer pointers
+     */
+    buffer->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<nx; i += nblock) {
+	/* last block may be shorter */
+	if (nx-i < nblock) thisblock = nx-i;
+	/*
+	 * Compute differences of adjacent pixels and map them to unsigned values.
+	 * Note that this may overflow the integer variables -- that's
+	 * OK, because we can recover when decompressing.  If we were
+	 * compressing shorts or bytes, would want to do this arithmetic
+	 * with short/byte working variables (though diff will still be
+	 * passed as an int.)
+	 *
+	 * compute sum of mapped pixel values at same time
+	 * use double precision for sum to allow 32-bit integer inputs
+	 */
+	pixelsum = 0.0;
+	for (j=0; j<thisblock; j++) {
+	    nextpix = a[i+j];
+	    pdiff = nextpix - lastpix;
+	    diff[j] = (unsigned int) ((pdiff<0) ? ~(pdiff<<1) : (pdiff<<1));
+	    pixelsum += diff[j];
+	    lastpix = nextpix;
+	}
+	/*
+	 * compute number of bits to split from sum
+	 */
+	dpsum = (pixelsum - (thisblock/2) - 1)/thisblock;
+	if (dpsum < 0) dpsum = 0.0;
+/*	psum = ((unsigned int) dpsum ) >> 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) {
+	    /* 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; j<thisblock; j++) {
+		if (output_nbits(buffer, diff[j], bbits) == EOF) {
+                    ffpmsg("rice_encode: end of buffer");
+                    free(diff);
+		    return(-1);
+		}
+	    }
+	} else if (fs == 0 && pixelsum == 0) {
+	    /*
+	     * special low entropy case when FS = 0 and pixelsum=0 (all
+	     * pixels in block are zero.)
+	     * Output a 0 and return
+	     */
+	    if (output_nbits(buffer, 0, fsbits) == EOF) {
+                ffpmsg("rice_encode: end of buffer");
+                free(diff);
+		return(-1);
+	    }
+	} else {
+	    /* normal case: not either very high or very low entropy */
+	    if (output_nbits(buffer, fs+1, fsbits) == EOF) {
+                ffpmsg("rice_encode: end of buffer");
+                free(diff);
+		return(-1);
+	    }
+	    fsmask = (1<<fs) - 1;
+	    /*
+	     * local copies of bit buffer to improve optimization
+	     */
+	    lbitbuffer = buffer->bitbuffer;
+	    lbits_to_go = buffer->bits_to_go;
+	    for (j=0; j<thisblock; j++) {
+		v = diff[j];
+		top = v >> 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<<fsbits;
+
+    /*
+     * Set up buffer pointers
+     */
+    buffer->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<nx; i += nblock) {
+	/* last block may be shorter */
+	if (nx-i < nblock) thisblock = nx-i;
+	/*
+	 * Compute differences of adjacent pixels and map them to unsigned values.
+	 * Note that this may overflow the integer variables -- that's
+	 * OK, because we can recover when decompressing.  If we were
+	 * compressing shorts or bytes, would want to do this arithmetic
+	 * with short/byte working variables (though diff will still be
+	 * passed as an int.)
+	 *
+	 * compute sum of mapped pixel values at same time
+	 * use double precision for sum to allow 32-bit integer inputs
+	 */
+	pixelsum = 0.0;
+	for (j=0; j<thisblock; j++) {
+	    nextpix = a[i+j];
+	    pdiff = nextpix - lastpix;
+	    diff[j] = (unsigned int) ((pdiff<0) ? ~(pdiff<<1) : (pdiff<<1));
+	    pixelsum += diff[j];
+	    lastpix = nextpix;
+	}
+	/*
+	 * compute number of bits to split from sum
+	 */
+	dpsum = (pixelsum - (thisblock/2) - 1)/thisblock;
+	if (dpsum < 0) dpsum = 0.0;
+/*	psum = ((unsigned int) dpsum ) >> 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; j<thisblock; j++) {
+		if (output_nbits(buffer, diff[j], bbits) == EOF) {
+                    ffpmsg("rice_encode: end of buffer");
+                    free(diff);
+		    return(-1);
+		}
+	    }
+	} else if (fs == 0 && pixelsum == 0) {
+	    /*
+	     * special low entropy case when FS = 0 and pixelsum=0 (all
+	     * pixels in block are zero.)
+	     * Output a 0 and return
+	     */
+	    if (output_nbits(buffer, 0, fsbits) == EOF) {
+                ffpmsg("rice_encode: end of buffer");
+                free(diff);
+		return(-1);
+	    }
+	} else {
+	    /* normal case: not either very high or very low entropy */
+	    if (output_nbits(buffer, fs+1, fsbits) == EOF) {
+                ffpmsg("rice_encode: end of buffer");
+                free(diff);
+		return(-1);
+	    }
+	    fsmask = (1<<fs) - 1;
+	    /*
+	     * local copies of bit buffer to improve optimization
+	     */
+	    lbitbuffer = buffer->bitbuffer;
+	    lbits_to_go = buffer->bits_to_go;
+	    for (j=0; j<thisblock; j++) {
+		v = diff[j];
+		top = v >> 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<<lbits_to_go)-1); */
+	lbitbuffer |= (bits>>(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<<n)-1) ); */
+    lbitbuffer |= ( bits & *(mask+n) );
+    lbits_to_go -= n;
+    while (lbits_to_go <= 0) {
+	/*
+	 * bitbuffer full, put out top 8 bits
+	 */
+	putcbuf((lbitbuffer>>(-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<<buffer->bits_to_go,buffer);
+	
+/*	if (putcbuf(buffer->bitbuffer<<buffer->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 <stdio.h>
+#include <stdlib.h>
+*/
+
+/*---------------------------------------------------------------------------*/
+/* 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;
+static int *nonzero_count = (int *)NULL;
+
+   /*
+     * 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<<fsbits;
+
+    FFLOCK;
+    if (nonzero_count == (int *) NULL) {
+	/*
+	 * nonzero_count is lookup table giving number of bits
+	 * in 8-bit values not including leading zeros
+	 */
+
+        /*  NOTE!!!  This memory never gets freed  */
+	nonzero_count = (int *) malloc(256*sizeof(int));
+	if (nonzero_count == (int *) NULL) {
+            ffpmsg("rdecomp: insufficient memory");
+            FFUNLOCK;
+	    return 1;
+	}
+	nzero = 8;
+	k = 128;
+	for (i=255; i>=0; ) {
+	    for ( ; i>=k; i--) nonzero_count[i] = nzero;
+	    k = k/2;
+	    nzero--;
+	}
+    }
+    FFUNLOCK;
+
+    /*
+     * Decode in blocks of nblock pixels
+     */
+
+    /* first 4 bytes of input buffer contain the value of the first */
+    /* 4 byte integer value, without any encoding */
+    
+    lastpix = 0;
+    bytevalue = c[0];
+    lastpix = lastpix | (bytevalue<<24);
+    bytevalue = c[1];
+    lastpix = lastpix | (bytevalue<<16);
+    bytevalue = c[2];
+    lastpix = lastpix | (bytevalue<<8);
+    bytevalue = c[3];
+    lastpix = lastpix | bytevalue;
+
+    c += 4;  
+    cend = c + clen - 4;
+
+    b = *c++;		    /* bit buffer			*/
+    nbits = 8;		    /* number of bits remaining in b	*/
+    for (i = 0; i<nx; ) {
+	/* get the FS value from first fsbits */
+	nbits -= fsbits;
+	while (nbits < 0) {
+	    b = (b<<8) | (*c++);
+	    nbits += 8;
+	}
+	fs = (b >> nbits) - 1;
+
+	b &= (1<<nbits)-1;
+	/* loop over the next block */
+	imax = i + nblock;
+	if (imax > nx) imax = nx;
+	if (fs<0) {
+	    /* low-entropy case, all zero differences */
+	    for ( ; i<imax; i++) array[i] = lastpix;
+	} else if (fs==fsmax) {
+	    /* high-entropy case, directly coded pixel values */
+	    for ( ; i<imax; i++) {
+		k = bbits - nbits;
+		diff = b<<k;
+		for (k -= 8; k >= 0; k -= 8) {
+		    b = *c++;
+		    diff |= b<<k;
+		}
+		if (nbits>0) {
+		    b = *c++;
+		    diff |= b>>(-k);
+		    b &= (1<<nbits)-1;
+		} else {
+		    b = 0;
+		}
+		/*
+		 * undo mapping and differencing
+		 * Note that some of these operations will overflow the
+		 * unsigned int arithmetic -- that's OK, it all works
+		 * out to give the right answers in the output file.
+		 */
+		if ((diff & 1) == 0) {
+		    diff = diff>>1;
+		} else {
+		    diff = ~(diff>>1);
+		}
+		array[i] = diff+lastpix;
+		lastpix = array[i];
+	    }
+	} else {
+	    /* normal case, Rice coding */
+	    for ( ; i<imax; i++) {
+		/* count number of leading zeros */
+		while (b == 0) {
+		    nbits += 8;
+		    b = *c++;
+		}
+		nzero = nbits - nonzero_count[b];
+		nbits -= nzero+1;
+		/* flip the leading one-bit */
+		b ^= 1<<nbits;
+		/* get the FS trailing bits */
+		nbits -= fs;
+		while (nbits < 0) {
+		    b = (b<<8) | (*c++);
+		    nbits += 8;
+		}
+		diff = (nzero<<fs) | (b>>nbits);
+		b &= (1<<nbits)-1;
+
+		/* undo mapping and differencing */
+		if ((diff & 1) == 0) {
+		    diff = diff>>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;
+static int *nonzero_count = (int *)NULL;
+
+   /*
+     * 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<<fsbits;
+
+    FFLOCK;
+    if (nonzero_count == (int *) NULL) {
+	/*
+	 * nonzero_count is lookup table giving number of bits
+	 * in 8-bit values not including leading zeros
+	 */
+
+        /*  NOTE!!!  This memory never gets freed  */
+	nonzero_count = (int *) malloc(256*sizeof(int));
+	if (nonzero_count == (int *) NULL) {
+            ffpmsg("rdecomp: insufficient memory");
+	    FFUNLOCK;
+	    return 1;
+	}
+	nzero = 8;
+	k = 128;
+	for (i=255; i>=0; ) {
+	    for ( ; i>=k; i--) nonzero_count[i] = nzero;
+	    k = k/2;
+	    nzero--;
+	}
+    }
+    FFUNLOCK;
+    /*
+     * Decode in blocks of nblock pixels
+     */
+
+    /* first 2 bytes of input buffer contain the value of the first */
+    /* 2 byte integer value, without any encoding */
+    
+    lastpix = 0;
+    bytevalue = c[0];
+    lastpix = lastpix | (bytevalue<<8);
+    bytevalue = c[1];
+    lastpix = lastpix | bytevalue;
+
+    c += 2;  
+    cend = c + clen - 2;
+
+    b = *c++;		    /* bit buffer			*/
+    nbits = 8;		    /* number of bits remaining in b	*/
+    for (i = 0; i<nx; ) {
+	/* get the FS value from first fsbits */
+	nbits -= fsbits;
+	while (nbits < 0) {
+	    b = (b<<8) | (*c++);
+	    nbits += 8;
+	}
+	fs = (b >> nbits) - 1;
+
+	b &= (1<<nbits)-1;
+	/* loop over the next block */
+	imax = i + nblock;
+	if (imax > nx) imax = nx;
+	if (fs<0) {
+	    /* low-entropy case, all zero differences */
+	    for ( ; i<imax; i++) array[i] = lastpix;
+	} else if (fs==fsmax) {
+	    /* high-entropy case, directly coded pixel values */
+	    for ( ; i<imax; i++) {
+		k = bbits - nbits;
+		diff = b<<k;
+		for (k -= 8; k >= 0; k -= 8) {
+		    b = *c++;
+		    diff |= b<<k;
+		}
+		if (nbits>0) {
+		    b = *c++;
+		    diff |= b>>(-k);
+		    b &= (1<<nbits)-1;
+		} else {
+		    b = 0;
+		}
+   
+		/*
+		 * undo mapping and differencing
+		 * Note that some of these operations will overflow the
+		 * unsigned int arithmetic -- that's OK, it all works
+		 * out to give the right answers in the output file.
+		 */
+		if ((diff & 1) == 0) {
+		    diff = diff>>1;
+		} else {
+		    diff = ~(diff>>1);
+		}
+		array[i] = diff+lastpix;
+		lastpix = array[i];
+	    }
+	} else {
+	    /* normal case, Rice coding */
+	    for ( ; i<imax; i++) {
+		/* count number of leading zeros */
+		while (b == 0) {
+		    nbits += 8;
+		    b = *c++;
+		}
+		nzero = nbits - nonzero_count[b];
+		nbits -= nzero+1;
+		/* flip the leading one-bit */
+		b ^= 1<<nbits;
+		/* get the FS trailing bits */
+		nbits -= fs;
+		while (nbits < 0) {
+		    b = (b<<8) | (*c++);
+		    nbits += 8;
+		}
+		diff = (nzero<<fs) | (b>>nbits);
+		b &= (1<<nbits)-1;
+
+		/* undo mapping and differencing */
+		if ((diff & 1) == 0) {
+		    diff = diff>>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;
+static int *nonzero_count = (int *)NULL;
+
+   /*
+     * 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<<fsbits;
+
+    FFLOCK;
+    if (nonzero_count == (int *) NULL) {
+	/*
+	 * nonzero_count is lookup table giving number of bits
+	 * in 8-bit values not including leading zeros
+	 */
+
+        /*  NOTE!!!  This memory never gets freed  */
+	nonzero_count = (int *) malloc(256*sizeof(int));
+	if (nonzero_count == (int *) NULL) {
+            ffpmsg("rdecomp: insufficient memory");
+	    FFUNLOCK;
+	    return 1;
+	}
+	nzero = 8;
+	k = 128;
+	for (i=255; i>=0; ) {
+	    for ( ; i>=k; i--) nonzero_count[i] = nzero;
+	    k = k/2;
+	    nzero--;
+	}
+    }
+    FFUNLOCK;
+    /*
+     * Decode in blocks of nblock pixels
+     */
+
+    /* first byte of input buffer contain the value of the first */
+    /* byte integer value, without any encoding */
+    
+    lastpix = c[0];
+    c += 1;  
+    cend = c + clen - 1;
+
+    b = *c++;		    /* bit buffer			*/
+    nbits = 8;		    /* number of bits remaining in b	*/
+    for (i = 0; i<nx; ) {
+	/* get the FS value from first fsbits */
+	nbits -= fsbits;
+	while (nbits < 0) {
+	    b = (b<<8) | (*c++);
+	    nbits += 8;
+	}
+	fs = (b >> nbits) - 1;
+
+	b &= (1<<nbits)-1;
+	/* loop over the next block */
+	imax = i + nblock;
+	if (imax > nx) imax = nx;
+	if (fs<0) {
+	    /* low-entropy case, all zero differences */
+	    for ( ; i<imax; i++) array[i] = lastpix;
+	} else if (fs==fsmax) {
+	    /* high-entropy case, directly coded pixel values */
+	    for ( ; i<imax; i++) {
+		k = bbits - nbits;
+		diff = b<<k;
+		for (k -= 8; k >= 0; k -= 8) {
+		    b = *c++;
+		    diff |= b<<k;
+		}
+		if (nbits>0) {
+		    b = *c++;
+		    diff |= b>>(-k);
+		    b &= (1<<nbits)-1;
+		} else {
+		    b = 0;
+		}
+   
+		/*
+		 * undo mapping and differencing
+		 * Note that some of these operations will overflow the
+		 * unsigned int arithmetic -- that's OK, it all works
+		 * out to give the right answers in the output file.
+		 */
+		if ((diff & 1) == 0) {
+		    diff = diff>>1;
+		} else {
+		    diff = ~(diff>>1);
+		}
+		array[i] = diff+lastpix;
+		lastpix = array[i];
+	    }
+	} else {
+	    /* normal case, Rice coding */
+	    for ( ; i<imax; i++) {
+		/* count number of leading zeros */
+		while (b == 0) {
+		    nbits += 8;
+		    b = *c++;
+		}
+		nzero = nbits - nonzero_count[b];
+		nbits -= nzero+1;
+		/* flip the leading one-bit */
+		b ^= 1<<nbits;
+		/* get the FS trailing bits */
+		nbits -= fs;
+		while (nbits < 0) {
+		    b = (b<<8) | (*c++);
+		    nbits += 8;
+		}
+		diff = (nzero<<fs) | (b>>nbits);
+		b &= (1<<nbits)-1;
+
+		/* undo mapping and differencing */
+		if ((diff & 1) == 0) {
+		    diff = diff>>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;
+}
diff --git a/cextern/cfitsio/scalnull.c b/cextern/cfitsio/scalnull.c
new file mode 100644
index 0000000..d2f2924
--- /dev/null
+++ b/cextern/cfitsio/scalnull.c
@@ -0,0 +1,229 @@
+/*  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 <string.h>
+#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);
+}
diff --git a/cextern/cfitsio/swapproc.c b/cextern/cfitsio/swapproc.c
new file mode 100644
index 0000000..cc69d6e
--- /dev/null
+++ b/cextern/cfitsio/swapproc.c
@@ -0,0 +1,247 @@
+/*  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 <string.h>
+#include <stdlib.h>
+#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 <tmmintrin.h>
+/* 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 <emmintrin.h>
+/* 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
diff --git a/cextern/cfitsio/trees.c b/cextern/cfitsio/trees.c
new file mode 100644
index 0000000..8436126
--- /dev/null
+++ b/cextern/cfitsio/trees.c
@@ -0,0 +1,1242 @@
+/* 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 <ctype.h>
+#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<<extra_lbits[code]); n++) {
+            _length_code[length++] = (uch)code;
+        }
+    }
+    Assert (length == 256, "tr_static_init: length != 256");
+    /* Note that the length 255 (match length 258) can be represented
+     * in two different ways: code 284 + 5 bits or code 285, so we
+     * overwrite length_code[255] to use the best encoding:
+     */
+    _length_code[length-1] = (uch)code;
+
+    /* Initialize the mapping dist (0..32K) -> dist code (0..29) */
+    dist = 0;
+    for (code = 0 ; code < 16; code++) {
+        base_dist[code] = dist;
+        for (n = 0; n < (1<<extra_dbits[code]); n++) {
+            _dist_code[dist++] = (uch)code;
+        }
+    }
+    Assert (dist == 256, "tr_static_init: dist != 256");
+    dist >>= 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 <stdio.h>
+#  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<<MAX_BITS)-1,
+            "inconsistent bit counts");
+    Tracev((stderr,"\ngen_codes: max_code %d ", max_code));
+
+    for (n = 0;  n <= max_code; n++) {
+        int len = tree[n].Len;
+        if (len == 0) continue;
+        /* Now reverse the bits */
+        tree[n].Code = bi_reverse(next_code[len]++, len);
+
+        Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ",
+             n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1));
+    }
+}
+
+/* ===========================================================================
+ * Construct one Huffman tree and assigns the code bit strings and lengths.
+ * Update the total bit length for the current block.
+ * IN assertion: the field freq is set for all tree elements.
+ * OUT assertions: the fields len and code are set to the optimal bit length
+ *     and corresponding code. The length opt_len is updated; static_len is
+ *     also updated if stree is not null. The field max_code is set.
+ */
+local void build_tree(s, desc)
+    deflate_state *s;
+    tree_desc *desc; /* the tree descriptor */
+{
+    ct_data *tree         = desc->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++);
+    }
+}
diff --git a/cextern/cfitsio/trees.h b/cextern/cfitsio/trees.h
new file mode 100644
index 0000000..d35639d
--- /dev/null
+++ b/cextern/cfitsio/trees.h
@@ -0,0 +1,128 @@
+/* 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
+};
+
diff --git a/cextern/cfitsio/uncompr.c b/cextern/cfitsio/uncompr.c
new file mode 100644
index 0000000..769f83e
--- /dev/null
+++ b/cextern/cfitsio/uncompr.c
@@ -0,0 +1,57 @@
+/* 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;
+}
diff --git a/cextern/cfitsio/wcssub.c b/cextern/cfitsio/wcssub.c
new file mode 100644
index 0000000..afb8e5c
--- /dev/null
+++ b/cextern/cfitsio/wcssub.c
@@ -0,0 +1,1043 @@
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+#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);
+}
diff --git a/cextern/cfitsio/wcsutil.c b/cextern/cfitsio/wcsutil.c
new file mode 100644
index 0000000..01d80f9
--- /dev/null
+++ b/cextern/cfitsio/wcsutil.c
@@ -0,0 +1,502 @@
+#include <math.h>
+#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)<deps)
+	    return(*status = 501);
+          rat = l * (1.0+dz) / (2.0 * rat);
+          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)
+	    return(*status = 501);
+          mg = 2.0 * (sin(dect) * cos0 - cos(dect) * sin0 * cos(rat)) / mg;
+          if (fabs(mg-m)>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))<deps) return(*status = 501);
+            da = l * dz / (2.0 * geo1 * cos(dd));
+            if (fabs(da)>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)<deps)
+	   return(*status = 501);
+         dd = 2.0 / dd;
+         l = l * dd;
+         m = dd * (sins * cos(dec0) - coss * sin(dec0) * cos(da));
+
+        } else  {
+          return(*status = 504);
+        }
+ 
+    } else if (*cptr == 'A') {
+
+      if (*(cptr + 1) == 'R' &&  *(cptr + 2) == 'C') { /* ARC */
+         m = sins * sin(dec0) + coss * cos(dec0) * cos(ra-ra0);
+         if (m<-1.0) m = -1.0;
+         if (m>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)<deps)
+	     return(*status = 503);
+         l = 2.0 * geo1 * cos(dec) * sin(da) / dt;
+         m = geo2 * sin(dec) / dt - geo3;
+
+        } else  {
+          return(*status = 504);
+        }
+ 
+    } else if (*cptr == 'N') { /* -NCP North celestial pole*/
+         if (*(cptr + 1) != 'C' ||  *(cptr + 2) != 'P') {
+             return(*status = 504);
+         }
+
+         if (dec0==0.0) 
+	     return(*status = 501);  /* can't stand the equator */
+         else
+	   m = (cos(dec0) - coss * cos(ra-ra0)) / sin(dec0);
+
+    } else if (*cptr == 'G') {   /* -GLS global sinusoid */
+         if (*(cptr + 1) != 'L' ||  *(cptr + 2) != 'S') {
+             return(*status = 504);
+         }
+
+         dt = ra - ra0;
+         if (fabs(dec)>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<deps)
+	   return(*status = 502);
+         m = geo2 * log (dt) - geo3;
+
+    } else  {
+      return(*status = 504);
+    }
+
+    /*   convert to degrees  */
+    dx = l / D2R;
+    dy = m / D2R;
+
+    /*  Correct for rotation */
+    dz = dx*cosr + dy*sinr;
+    dy = dy*cosr - dx*sinr;
+    dx = dz;
+
+    /*     convert to pixels  */
+    *xpix = dx / xinc + xrefpix;
+    *ypix = dy / yinc + yrefpix;
+    return(*status);
+}
diff --git a/cextern/cfitsio/zcompress.c b/cextern/cfitsio/zcompress.c
new file mode 100644
index 0000000..b8d7e79
--- /dev/null
+++ b/cextern/cfitsio/zcompress.c
@@ -0,0 +1,504 @@
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include "zlib.h"  
+
+unsigned int GZBUFSIZE = 115200;  /* 40 FITS blocks */
+int 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 */
+
+    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 = *buffsize;
+
+    /* 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 */
+                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;
+
+        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);
+}
diff --git a/cextern/cfitsio/zconf.h b/cextern/cfitsio/zconf.h
new file mode 100644
index 0000000..142c330
--- /dev/null
+++ b/cextern/cfitsio/zconf.h
@@ -0,0 +1,426 @@
+/* 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 <windows.h>
+     /* 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 <sys/types.h>    /* 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 <unistd.h>       /* for SEEK_* and off_t */
+#  ifdef VMS
+#    include <unixio.h>     /* 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 */
diff --git a/cextern/cfitsio/zlib.h b/cextern/cfitsio/zlib.h
new file mode 100644
index 0000000..bfbba83
--- /dev/null
+++ b/cextern/cfitsio/zlib.h
@@ -0,0 +1,1613 @@
+/* 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 at gzip.org          madler at 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 */
diff --git a/cextern/cfitsio/zuncompress.c b/cextern/cfitsio/zuncompress.c
new file mode 100644
index 0000000..c73ee6d
--- /dev/null
+++ b/cextern/cfitsio/zuncompress.c
@@ -0,0 +1,603 @@
+/* gzcompress.h -- definitions for the .Z decompression routine used in CFITSIO */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#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<<BITS);
+#else
+    static DECLARE(ush, tab_prefix0, 1L<<(BITS-1));
+    static DECLARE(ush, tab_prefix1, 1L<<(BITS-1));
+#endif
+
+		/* local variables */
+
+/* 11/25/98: added 'static' to local variable definitions, to avoid */
+/* conflict with external source files */
+
+static int maxbits = BITS;   /* max bits per code for LZW */
+static int method = DEFLATED;/* compression method */
+static int exit_code = OK;   /* program exit code */
+static int last_member;      /* set for .zip and .Z files */
+static long bytes_in;             /* number of input bytes */
+static long bytes_out;            /* number of output bytes */
+static char ifname[128];          /* input file name */
+static FILE *ifd;               /* input file descriptor */
+static FILE *ofd;               /* output file descriptor */
+static void **memptr;          /* memory location for uncompressed file */
+static size_t *memsize;        /* size (bytes) of memory allocated for file */
+void *(*realloc_fn)(void *p, size_t newsize);  /* reallocation function */
+static unsigned insize;     /* valid bytes in inbuf */
+static unsigned inptr;      /* index of next byte to be processed in inbuf */
+
+/* prototype for the following functions */
+int zuncompress2mem(char *filename, 
+             FILE *diskfile, 
+             char **buffptr, 
+             size_t *buffsize, 
+             void *(*mem_realloc)(void *p, size_t newsize),
+             size_t *filesize,
+             int *status);
+
+/*--------------------------------------------------------------------------*/
+int zuncompress2mem(char *filename,  /* name of input file                 */
+             FILE *indiskfile,     /* 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 file into memory.  Fill whatever amount of memory has
+  already been allocated, then realloc more memory, using the supplied
+  input function, if necessary.
+*/
+{
+    char magic[2]; /* magic header */
+
+    if (*status > 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<<BITS)); -- prefix code */
+#  define tab_prefixof(i) tab_prefix[i]
+#  define clear_tab_prefixof()	memzero(tab_prefix, 256);
+#else
+   /* DECLARE(ush, tab_prefix0, (1<<(BITS-1)); -- prefix for even codes */
+   /* DECLARE(ush, tab_prefix1, (1<<(BITS-1)); -- prefix for odd  codes */
+   ush *tab_prefix[2];
+#  define tab_prefixof(i) tab_prefix[(i)&1][(i)>>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<<n_bits)-1;
+    oldcode = -1;
+    finchar = 0;
+    outpos = 0;
+    posbits = inptr<<3;
+
+    free_ent = ((block_mode) ? FIRST : 256);
+    
+    clear_tab_prefixof(); /* Initialize the first 256 entries in the table. */
+    
+    for (code = 255 ; code >= 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<<n_bits)-1;
+		goto resetbuf;
+	    }
+	    input(inbuf,posbits,code,n_bits,bitmask);
+	    Tracev((stderr, "%d ", code));
+
+	    if (oldcode == -1) {
+		if (code >= 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<<n_bits)-1;
+		goto resetbuf;
+	    }
+	    incode = code;
+	    stackp = de_stack;
+	    
+	    if (code >= 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);
+}
diff --git a/cextern/cfitsio/zutil.c b/cextern/cfitsio/zutil.c
new file mode 100644
index 0000000..15645c5
--- /dev/null
+++ b/cextern/cfitsio/zutil.c
@@ -0,0 +1,316 @@
+/* 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 */
diff --git a/cextern/cfitsio/zutil.h b/cextern/cfitsio/zutil.h
new file mode 100644
index 0000000..1f5a6c0
--- /dev/null
+++ b/cextern/cfitsio/zutil.h
@@ -0,0 +1,272 @@
+/* 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 <stddef.h>
+#  endif
+#  include <string.h>
+#  include <stdlib.h>
+#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 <alloc.h>
+#    endif
+#  else /* MSC or DJGPP */
+#    include <malloc.h>
+#  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 <malloc.h>
+#  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 <unix.h> /* 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 <stdio.h>
+   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 */
diff --git a/cextern/sofa/sofa.c b/cextern/sofa/sofa.c
new file mode 100644
index 0000000..707eda5
--- /dev/null
+++ b/cextern/sofa/sofa.c
@@ -0,0 +1,49467 @@
+#include "sofam.h"
+#include <stdlib.h>
+
+void iauA2af(int ndp, double angle, char *sign, int idmsf[4])
+/*
+**  - - - - - - - -
+**   i a u A 2 a f
+**  - - - - - - - -
+**
+**  Decompose radians into degrees, arcminutes, arcseconds, fraction.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  vector/matrix support function.
+**
+**  Given:
+**     ndp     int     resolution (Note 1)
+**     angle   double  angle in radians
+**
+**  Returned:
+**     sign    char    '+' or '-'
+**     idmsf   int[4]  degrees, arcminutes, arcseconds, fraction
+**
+**  Called:
+**     iauD2tf      decompose days to hms
+**
+**  Notes:
+**
+**  1) The argument ndp is interpreted as follows:
+**
+**     ndp         resolution
+**      :      ...0000 00 00
+**     -7         1000 00 00
+**     -6          100 00 00
+**     -5           10 00 00
+**     -4            1 00 00
+**     -3            0 10 00
+**     -2            0 01 00
+**     -1            0 00 10
+**      0            0 00 01
+**      1            0 00 00.1
+**      2            0 00 00.01
+**      3            0 00 00.001
+**      :            0 00 00.000...
+**
+**  2) The largest positive useful value for ndp is determined by the
+**     size of angle, the format of doubles on the target platform, and
+**     the risk of overflowing idmsf[3].  On a typical platform, for
+**     angle up to 2pi, the available floating-point precision might
+**     correspond to ndp=12.  However, the practical limit is typically
+**     ndp=9, set by the capacity of a 32-bit int, or ndp=4 if int is
+**     only 16 bits.
+**
+**  3) The absolute value of angle may exceed 2pi.  In cases where it
+**     does not, it is up to the caller to test for and handle the
+**     case where angle is very nearly 2pi and rounds up to 360 degrees,
+**     by testing for idmsf[0]=360 and setting idmsf[0-3] to zero.
+**
+**  This revision:  2008 May 27
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+/* Hours to degrees * radians to turns */
+   const double F = 15.0 / D2PI;
+
+
+/* Scale then use days to h,m,s function. */
+   iauD2tf(ndp, angle*F, sign, idmsf);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauA2tf(int ndp, double angle, char *sign, int ihmsf[4])
+/*
+**  - - - - - - - -
+**   i a u A 2 t f
+**  - - - - - - - -
+**
+**  Decompose radians into hours, minutes, seconds, fraction.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  vector/matrix support function.
+**
+**  Given:
+**     ndp     int     resolution (Note 1)
+**     angle   double  angle in radians
+**
+**  Returned:
+**     sign    char    '+' or '-'
+**     ihmsf   int[4]  hours, minutes, seconds, fraction
+**
+**  Called:
+**     iauD2tf      decompose days to hms
+**
+**  Notes:
+**
+**  1) The argument ndp is interpreted as follows:
+**
+**     ndp         resolution
+**      :      ...0000 00 00
+**     -7         1000 00 00
+**     -6          100 00 00
+**     -5           10 00 00
+**     -4            1 00 00
+**     -3            0 10 00
+**     -2            0 01 00
+**     -1            0 00 10
+**      0            0 00 01
+**      1            0 00 00.1
+**      2            0 00 00.01
+**      3            0 00 00.001
+**      :            0 00 00.000...
+**
+**  2) The largest positive useful value for ndp is determined by the
+**     size of angle, the format of doubles on the target platform, and
+**     the risk of overflowing ihmsf[3].  On a typical platform, for
+**     angle up to 2pi, the available floating-point precision might
+**     correspond to ndp=12.  However, the practical limit is typically
+**     ndp=9, set by the capacity of a 32-bit int, or ndp=4 if int is
+**     only 16 bits.
+**
+**  3) The absolute value of angle may exceed 2pi.  In cases where it
+**     does not, it is up to the caller to test for and handle the
+**     case where angle is very nearly 2pi and rounds up to 24 hours,
+**     by testing for ihmsf[0]=24 and setting ihmsf(0-3) to zero.
+**
+**  This revision:  2008 May 11
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+/* Scale then use days to h,m,s function. */
+   iauD2tf(ndp, angle/D2PI, sign, ihmsf);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+
+int iauAf2a(char s, int ideg, int iamin, double asec, double *rad)
+/*
+**  - - - - - - - -
+**   i a u A f 2 a
+**  - - - - - - - -
+**
+**  Convert degrees, arcminutes, arcseconds to radians.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     s         char    sign:  '-' = negative, otherwise positive
+**     ideg      int     degrees
+**     iamin     int     arcminutes
+**     asec      double  arcseconds
+**
+**  Returned:
+**     rad       double  angle in radians
+**
+**  Returned (function value):
+**               int     status:  0 = OK
+**                                1 = ideg outside range 0-359
+**                                2 = iamin outside range 0-59
+**                                3 = asec outside range 0-59.999...
+**
+**  Notes:
+**
+**  1)  The result is computed even if any of the range checks fail.
+**
+**  2)  Negative ideg, iamin and/or asec produce a warning status, but
+**      the absolute value is used in the conversion.
+**
+**  3)  If there are multiple errors, the status value reflects only the
+**      first, the smallest taking precedence.
+**
+**  This revision:  2012 February 13
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+
+/* Compute the interval. */
+   *rad  = ( s == '-' ? -1.0 : 1.0 ) *
+           ( 60.0 * ( 60.0 * ( (double) abs(ideg) ) +
+                             ( (double) abs(iamin) ) ) +
+                                        fabs(asec) ) * DAS2R;
+
+/* Validate arguments and return status. */
+   if ( ideg < 0 || ideg > 359 ) return 1;
+   if ( iamin < 0 || iamin > 59 ) return 2;
+   if ( asec < 0.0 || asec >= 60.0 ) return 3;
+   return 0;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+double iauAnp(double a)
+/*
+**  - - - - - - -
+**   i a u A n p
+**  - - - - - - -
+**
+**  Normalize angle into the range 0 <= a < 2pi.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  vector/matrix support function.
+**
+**  Given:
+**     a        double     angle (radians)
+**
+**  Returned (function value):
+**              double     angle in range 0-2pi
+**
+**  This revision:  2008 May 16
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double w;
+
+
+   w = fmod(a, D2PI);
+   if (w < 0) w += D2PI;
+
+   return w;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+double iauAnpm(double a)
+/*
+**  - - - - - - - -
+**   i a u A n p m
+**  - - - - - - - -
+**
+**  Normalize angle into the range -pi <= a < +pi.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  vector/matrix support function.
+**
+**  Given:
+**     a        double     angle (radians)
+**
+**  Returned (function value):
+**              double     angle in range +/-pi
+**
+**  This revision:  2008 May 16
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double w;
+
+
+   w = fmod(a, D2PI);
+   if (fabs(w) >= DPI) w -= dsign(D2PI, a);
+
+   return w;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauBi00(double *dpsibi, double *depsbi, double *dra)
+/*
+**  - - - - - - - -
+**   i a u B i 0 0
+**  - - - - - - - -
+**
+**  Frame bias components of IAU 2000 precession-nutation models (part
+**  of MHB2000 with additions).
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  canonical model.
+**
+**  Returned:
+**     dpsibi,depsbi  double  longitude and obliquity corrections
+**     dra            double  the ICRS RA of the J2000.0 mean equinox
+**
+**  Notes:
+**
+**  1) The frame bias corrections in longitude and obliquity (radians)
+**     are required in order to correct for the offset between the GCRS
+**     pole and the mean J2000.0 pole.  They define, with respect to the
+**     GCRS frame, a J2000.0 mean pole that is consistent with the rest
+**     of the IAU 2000A precession-nutation model.
+**
+**  2) In addition to the displacement of the pole, the complete
+**     description of the frame bias requires also an offset in right
+**     ascension.  This is not part of the IAU 2000A model, and is from
+**     Chapront et al. (2002).  It is returned in radians.
+**
+**  3) This is a supplemented implementation of one aspect of the IAU
+**     2000A nutation model, formally adopted by the IAU General
+**     Assembly in 2000, namely MHB2000 (Mathews et al. 2002).
+**
+**  References:
+**
+**     Chapront, J., Chapront-Touze, M. & Francou, G., Astron.
+**     Astrophys., 387, 700, 2002.
+**
+**     Mathews, P.M., Herring, T.A., Buffet, B.A., "Modeling of nutation
+**     and precession   New nutation series for nonrigid Earth and
+**     insights into the Earth's interior", J.Geophys.Res., 107, B4,
+**     2002.  The MHB2000 code itself was obtained on 9th September 2002
+**     from ftp://maia.usno.navy.mil/conv2000/chapter5/IAU2000A.
+**
+**  This revision:  2009 December 17
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+/* The frame bias corrections in longitude and obliquity */
+   const double DPBIAS = -0.041775  * DAS2R,
+                DEBIAS = -0.0068192 * DAS2R;
+
+/* The ICRS RA of the J2000.0 equinox (Chapront et al., 2002) */
+   const double DRA0 = -0.0146 * DAS2R;
+
+
+/* Return the results (which are fixed). */
+   *dpsibi = DPBIAS;
+   *depsbi = DEBIAS;
+   *dra = DRA0;
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauBp00(double date1, double date2,
+             double rb[3][3], double rp[3][3], double rbp[3][3])
+/*
+**  - - - - - - - -
+**   i a u B p 0 0
+**  - - - - - - - -
+**
+**  Frame bias and precession, IAU 2000.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  canonical model.
+**
+**  Given:
+**     date1,date2  double         TT as a 2-part Julian Date (Note 1)
+**
+**  Returned:
+**     rb           double[3][3]   frame bias matrix (Note 2)
+**     rp           double[3][3]   precession matrix (Note 3)
+**     rbp          double[3][3]   bias-precession matrix (Note 4)
+**
+**  Notes:
+**
+**  1) The TT date date1+date2 is a Julian Date, apportioned in any
+**     convenient way between the two arguments.  For example,
+**     JD(TT)=2450123.7 could be expressed in any of these ways,
+**     among others:
+**
+**             date1         date2
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in
+**     cases where the loss of several decimal digits of resolution
+**     is acceptable.  The J2000 method is best matched to the way
+**     the argument is handled internally and will deliver the
+**     optimum resolution.  The MJD method and the date & time methods
+**     are both good compromises between resolution and convenience.
+**
+**  2) The matrix rb transforms vectors from GCRS to mean J2000.0 by
+**     applying frame bias.
+**
+**  3) The matrix rp transforms vectors from J2000.0 mean equator and
+**     equinox to mean equator and equinox of date by applying
+**     precession.
+**
+**  4) The matrix rbp transforms vectors from GCRS to mean equator and
+**     equinox of date by applying frame bias then precession.  It is
+**     the product rp x rb.
+**
+**  5) It is permissible to re-use the same array in the returned
+**     arguments.  The arrays are filled in the order given.
+**
+**  Called:
+**     iauBi00      frame bias components, IAU 2000
+**     iauPr00      IAU 2000 precession adjustments
+**     iauIr        initialize r-matrix to identity
+**     iauRx        rotate around X-axis
+**     iauRy        rotate around Y-axis
+**     iauRz        rotate around Z-axis
+**     iauCr        copy r-matrix
+**     iauRxr       product of two r-matrices
+**
+**  Reference:
+**     "Expressions for the Celestial Intermediate Pole and Celestial
+**     Ephemeris Origin consistent with the IAU 2000A precession-
+**     nutation model", Astron.Astrophys. 400, 1145-1154 (2003)
+**
+**     n.b. The celestial ephemeris origin (CEO) was renamed "celestial
+**          intermediate origin" (CIO) by IAU 2006 Resolution 2.
+**
+**  This revision:  2010 January 18
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+/* J2000.0 obliquity (Lieske et al. 1977) */
+   const double EPS0 = 84381.448 * DAS2R;
+
+   double t, dpsibi, depsbi;
+   double dra0, psia77, oma77, chia, dpsipr, depspr, psia, oma,
+          rbw[3][3];
+
+
+/* Interval between fundamental epoch J2000.0 and current date (JC). */
+   t = ((date1 - DJ00) + date2) / DJC;
+
+/* Frame bias. */
+   iauBi00(&dpsibi, &depsbi, &dra0);
+
+/* Precession angles (Lieske et al. 1977) */
+   psia77 = (5038.7784 + (-1.07259 + (-0.001147) * t) * t) * t * DAS2R;
+   oma77  =       EPS0 + ((0.05127 + (-0.007726) * t) * t) * t * DAS2R;
+   chia   = (  10.5526 + (-2.38064 + (-0.001125) * t) * t) * t * DAS2R;
+
+/* Apply IAU 2000 precession corrections. */
+   iauPr00(date1, date2, &dpsipr,  &depspr);
+   psia = psia77 + dpsipr;
+   oma  = oma77  + depspr;
+
+/* Frame bias matrix: GCRS to J2000.0. */
+   iauIr(rbw);
+   iauRz(dra0, rbw);
+   iauRy(dpsibi * sin(EPS0), rbw);
+   iauRx(-depsbi, rbw);
+   iauCr(rbw, rb);
+
+/* Precession matrix: J2000.0 to mean of date. */
+   iauIr(rp);
+   iauRx(EPS0,  rp);
+   iauRz(-psia, rp);
+   iauRx(-oma,  rp);
+   iauRz(chia,  rp);
+
+/* Bias-precession matrix: GCRS to mean of date. */
+   iauRxr(rp, rbw, rbp);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauBp06(double date1, double date2,
+             double rb[3][3], double rp[3][3], double rbp[3][3])
+/*
+**  - - - - - - - -
+**   i a u B p 0 6
+**  - - - - - - - -
+**
+**  Frame bias and precession, IAU 2006.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     date1,date2  double         TT as a 2-part Julian Date (Note 1)
+**
+**  Returned:
+**     rb           double[3][3]   frame bias matrix (Note 2)
+**     rp           double[3][3]   precession matrix (Note 3)
+**     rbp          double[3][3]   bias-precession matrix (Note 4)
+**
+**  Notes:
+**
+**  1) The TT date date1+date2 is a Julian Date, apportioned in any
+**     convenient way between the two arguments.  For example,
+**     JD(TT)=2450123.7 could be expressed in any of these ways,
+**     among others:
+**
+**             date1         date2
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in
+**     cases where the loss of several decimal digits of resolution
+**     is acceptable.  The J2000 method is best matched to the way
+**     the argument is handled internally and will deliver the
+**     optimum resolution.  The MJD method and the date & time methods
+**     are both good compromises between resolution and convenience.
+**
+**  2) The matrix rb transforms vectors from GCRS to mean J2000.0 by
+**     applying frame bias.
+**
+**  3) The matrix rp transforms vectors from mean J2000.0 to mean of
+**     date by applying precession.
+**
+**  4) The matrix rbp transforms vectors from GCRS to mean of date by
+**     applying frame bias then precession.  It is the product rp x rb.
+**
+**  Called:
+**     iauPfw06     bias-precession F-W angles, IAU 2006
+**     iauFw2m      F-W angles to r-matrix
+**     iauPmat06    PB matrix, IAU 2006
+**     iauTr        transpose r-matrix
+**     iauRxr       product of two r-matrices
+**
+**  References:
+**
+**     Capitaine, N. & Wallace, P.T., 2006, Astron.Astrophys. 450, 855
+**
+**     Wallace, P.T. & Capitaine, N., 2006, Astron.Astrophys. 459, 981
+**
+**  This revision:  2009 December 17
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double gamb, phib, psib, epsa, rbt[3][3];
+
+
+/* B matrix. */
+   iauPfw06(DJM0, DJM00, &gamb, &phib, &psib, &epsa);
+   iauFw2m(gamb, phib, psib, epsa, rb);
+
+/* PxB matrix. */
+   iauPmat06(date1, date2, rbp);
+
+/* P matrix. */
+   iauTr(rb, rbt);
+   iauRxr(rbp, rbt, rp);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauBpn2xy(double rbpn[3][3], double *x, double *y)
+/*
+**  - - - - - - - - - -
+**   i a u B p n 2 x y
+**  - - - - - - - - - -
+**
+**  Extract from the bias-precession-nutation matrix the X,Y coordinates
+**  of the Celestial Intermediate Pole.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     rbpn      double[3][3]  celestial-to-true matrix (Note 1)
+**
+**  Returned:
+**     x,y       double        Celestial Intermediate Pole (Note 2)
+**
+**  Notes:
+**
+**  1) The matrix rbpn transforms vectors from GCRS to true equator (and
+**     CIO or equinox) of date, and therefore the Celestial Intermediate
+**     Pole unit vector is the bottom row of the matrix.
+**
+**  2) The arguments x,y are components of the Celestial Intermediate
+**     Pole unit vector in the Geocentric Celestial Reference System.
+**
+**  Reference:
+**
+**     "Expressions for the Celestial Intermediate Pole and Celestial
+**     Ephemeris Origin consistent with the IAU 2000A precession-
+**     nutation model", Astron.Astrophys. 400, 1145-1154
+**     (2003)
+**
+**     n.b. The celestial ephemeris origin (CEO) was renamed "celestial
+**          intermediate origin" (CIO) by IAU 2006 Resolution 2.
+**
+**  This revision:  2010 January 18
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+/* Extract the X,Y coordinates. */
+   *x = rbpn[2][0];
+   *y = rbpn[2][1];
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauC2i00a(double date1, double date2, double rc2i[3][3])
+/*
+**  - - - - - - - - - -
+**   i a u C 2 i 0 0 a
+**  - - - - - - - - - -
+**
+**  Form the celestial-to-intermediate matrix for a given date using the
+**  IAU 2000A precession-nutation model.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     date1,date2 double       TT as a 2-part Julian Date (Note 1)
+**
+**  Returned:
+**     rc2i        double[3][3] celestial-to-intermediate matrix (Note 2)
+**
+**  Notes:
+**
+**  1) The TT date date1+date2 is a Julian Date, apportioned in any
+**     convenient way between the two arguments.  For example,
+**     JD(TT)=2450123.7 could be expressed in any of these ways,
+**     among others:
+**
+**            date1          date2
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in
+**     cases where the loss of several decimal digits of resolution
+**     is acceptable.  The J2000 method is best matched to the way
+**     the argument is handled internally and will deliver the
+**     optimum resolution.  The MJD method and the date & time methods
+**     are both good compromises between resolution and convenience.
+**
+**  2) The matrix rc2i is the first stage in the transformation from
+**     celestial to terrestrial coordinates:
+**
+**        [TRS]  =  RPOM * R_3(ERA) * rc2i * [CRS]
+**
+**               =  rc2t * [CRS]
+**
+**     where [CRS] is a vector in the Geocentric Celestial Reference
+**     System and [TRS] is a vector in the International Terrestrial
+**     Reference System (see IERS Conventions 2003), ERA is the Earth
+**     Rotation Angle and RPOM is the polar motion matrix.
+**
+**  3) A faster, but slightly less accurate result (about 1 mas), can be
+**     obtained by using instead the iauC2i00b function.
+**
+**  Called:
+**     iauPnm00a    classical NPB matrix, IAU 2000A
+**     iauC2ibpn    celestial-to-intermediate matrix, given NPB matrix
+**
+**  References:
+**
+**     "Expressions for the Celestial Intermediate Pole and Celestial
+**     Ephemeris Origin consistent with the IAU 2000A precession-
+**     nutation model", Astron.Astrophys. 400, 1145-1154
+**     (2003)
+**
+**     n.b. The celestial ephemeris origin (CEO) was renamed "celestial
+**          intermediate origin" (CIO) by IAU 2006 Resolution 2.
+**
+**     McCarthy, D. D., Petit, G. (eds.), IERS Conventions (2003),
+**     IERS Technical Note No. 32, BKG (2004)
+**
+**  This revision:  2010 January 18
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double rbpn[3][3];
+
+
+/* Obtain the celestial-to-true matrix (IAU 2000A). */
+   iauPnm00a(date1, date2, rbpn);
+
+/* Form the celestial-to-intermediate matrix. */
+   iauC2ibpn(date1, date2, rbpn, rc2i);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauC2i00b(double date1, double date2, double rc2i[3][3])
+/*
+**  - - - - - - - - - -
+**   i a u C 2 i 0 0 b
+**  - - - - - - - - - -
+**
+**  Form the celestial-to-intermediate matrix for a given date using the
+**  IAU 2000B precession-nutation model.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     date1,date2 double       TT as a 2-part Julian Date (Note 1)
+**
+**  Returned:
+**     rc2i        double[3][3] celestial-to-intermediate matrix (Note 2)
+**
+**  Notes:
+**
+**  1) The TT date date1+date2 is a Julian Date, apportioned in any
+**     convenient way between the two arguments.  For example,
+**     JD(TT)=2450123.7 could be expressed in any of these ways,
+**     among others:
+**
+**            date1          date2
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in
+**     cases where the loss of several decimal digits of resolution
+**     is acceptable.  The J2000 method is best matched to the way
+**     the argument is handled internally and will deliver the
+**     optimum resolution.  The MJD method and the date & time methods
+**     are both good compromises between resolution and convenience.
+**
+**  2) The matrix rc2i is the first stage in the transformation from
+**     celestial to terrestrial coordinates:
+**
+**        [TRS]  =  RPOM * R_3(ERA) * rc2i * [CRS]
+**
+**               =  rc2t * [CRS]
+**
+**     where [CRS] is a vector in the Geocentric Celestial Reference
+**     System and [TRS] is a vector in the International Terrestrial
+**     Reference System (see IERS Conventions 2003), ERA is the Earth
+**     Rotation Angle and RPOM is the polar motion matrix.
+**
+**  3) The present function is faster, but slightly less accurate (about
+**     1 mas), than the iauC2i00a function.
+**
+**  Called:
+**     iauPnm00b    classical NPB matrix, IAU 2000B
+**     iauC2ibpn    celestial-to-intermediate matrix, given NPB matrix
+**
+**  References:
+**
+**     "Expressions for the Celestial Intermediate Pole and Celestial
+**     Ephemeris Origin consistent with the IAU 2000A precession-
+**     nutation model", Astron.Astrophys. 400, 1145-1154
+**     (2003)
+**
+**     n.b. The celestial ephemeris origin (CEO) was renamed "celestial
+**          intermediate origin" (CIO) by IAU 2006 Resolution 2.
+**
+**     McCarthy, D. D., Petit, G. (eds.), IERS Conventions (2003),
+**     IERS Technical Note No. 32, BKG (2004)
+**
+**  This revision:  2010 January 18
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double rbpn[3][3];
+
+
+/* Obtain the celestial-to-true matrix (IAU 2000B). */
+   iauPnm00b(date1, date2, rbpn);
+
+/* Form the celestial-to-intermediate matrix. */
+   iauC2ibpn(date1, date2, rbpn, rc2i);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauC2i06a(double date1, double date2, double rc2i[3][3])
+/*
+**  - - - - - - - - - -
+**   i a u _ c 2 i 0 6 a
+**  - - - - - - - - - -
+**
+**  Form the celestial-to-intermediate matrix for a given date using the
+**  IAU 2006 precession and IAU 2000A nutation models.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     date1,date2 double       TT as a 2-part Julian Date (Note 1)
+**
+**  Returned:
+**     rc2i        double[3][3] celestial-to-intermediate matrix (Note 2)
+**
+**  Notes:
+**
+**  1) The TT date date1+date2 is a Julian Date, apportioned in any
+**     convenient way between the two arguments.  For example,
+**     JD(TT)=2450123.7 could be expressed in any of these ways,
+**     among others:
+**
+**            date1          date2
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in
+**     cases where the loss of several decimal digits of resolution
+**     is acceptable.  The J2000 method is best matched to the way
+**     the argument is handled internally and will deliver the
+**     optimum resolution.  The MJD method and the date & time methods
+**     are both good compromises between resolution and convenience.
+**
+**  2) The matrix rc2i is the first stage in the transformation from
+**     celestial to terrestrial coordinates:
+**
+**        [TRS]  =  RPOM * R_3(ERA) * rc2i * [CRS]
+**
+**               =  RC2T * [CRS]
+**
+**     where [CRS] is a vector in the Geocentric Celestial Reference
+**     System and [TRS] is a vector in the International Terrestrial
+**     Reference System (see IERS Conventions 2003), ERA is the Earth
+**     Rotation Angle and RPOM is the polar motion matrix.
+**
+**  Called:
+**     iauPnm06a    classical NPB matrix, IAU 2006/2000A
+**     iauBpn2xy    extract CIP X,Y coordinates from NPB matrix
+**     iauS06       the CIO locator s, Given X,Y, IAU 2006
+**     iauC2ixys    celestial-to-intermediate matrix, Given X,Y and s
+**
+**  References:
+**
+**     McCarthy, D. D., Petit, G. (eds.), 2004, IERS Conventions (2003),
+**     IERS Technical Note No. 32, BKG
+**
+**  This revision:  2008 May 13
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double rbpn[3][3], x, y, s;
+
+
+/* Obtain the celestial-to-true matrix (IAU 2006/2000A). */
+   iauPnm06a(date1, date2, rbpn);
+
+/* Extract the X,Y coordinates. */
+   iauBpn2xy(rbpn, &x, &y);
+
+/* Obtain the CIO locator. */
+   s = iauS06(date1, date2, x, y);
+
+/* Form the celestial-to-intermediate matrix. */
+   iauC2ixys(x, y, s, rc2i);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauC2ibpn(double date1, double date2, double rbpn[3][3],
+               double rc2i[3][3])
+/*
+**  - - - - - - - - - -
+**   i a u C 2 i b p n
+**  - - - - - - - - - -
+**
+**  Form the celestial-to-intermediate matrix for a given date given
+**  the bias-precession-nutation matrix.  IAU 2000.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     date1,date2 double       TT as a 2-part Julian Date (Note 1)
+**     rbpn        double[3][3] celestial-to-true matrix (Note 2)
+**
+**  Returned:
+**     rc2i        double[3][3] celestial-to-intermediate matrix (Note 3)
+**
+**  Notes:
+**
+**  1) The TT date date1+date2 is a Julian Date, apportioned in any
+**     convenient way between the two arguments.  For example,
+**     JD(TT)=2450123.7 could be expressed in any of these ways,
+**     among others:
+**
+**            date1          date2
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in
+**     cases where the loss of several decimal digits of resolution
+**     is acceptable.  The J2000 method is best matched to the way
+**     the argument is handled internally and will deliver the
+**     optimum resolution.  The MJD method and the date & time methods
+**     are both good compromises between resolution and convenience.
+**
+**  2) The matrix rbpn transforms vectors from GCRS to true equator (and
+**     CIO or equinox) of date.  Only the CIP (bottom row) is used.
+**
+**  3) The matrix rc2i is the first stage in the transformation from
+**     celestial to terrestrial coordinates:
+**
+**        [TRS] = RPOM * R_3(ERA) * rc2i * [CRS]
+**
+**              = RC2T * [CRS]
+**
+**     where [CRS] is a vector in the Geocentric Celestial Reference
+**     System and [TRS] is a vector in the International Terrestrial
+**     Reference System (see IERS Conventions 2003), ERA is the Earth
+**     Rotation Angle and RPOM is the polar motion matrix.
+**
+**  4) Although its name does not include "00", This function is in fact
+**     specific to the IAU 2000 models.
+**
+**  Called:
+**     iauBpn2xy    extract CIP X,Y coordinates from NPB matrix
+**     iauC2ixy     celestial-to-intermediate matrix, given X,Y
+**
+**  References:
+**     "Expressions for the Celestial Intermediate Pole and Celestial
+**     Ephemeris Origin consistent with the IAU 2000A precession-
+**     nutation model", Astron.Astrophys. 400, 1145-1154 (2003)
+**
+**     n.b. The celestial ephemeris origin (CEO) was renamed "celestial
+**          intermediate origin" (CIO) by IAU 2006 Resolution 2.
+**
+**     McCarthy, D. D., Petit, G. (eds.), IERS Conventions (2003),
+**     IERS Technical Note No. 32, BKG (2004)
+**
+**  This revision:  2010 January 18
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double x, y;
+
+
+/* Extract the X,Y coordinates. */
+   iauBpn2xy(rbpn, &x, &y);
+
+/* Form the celestial-to-intermediate matrix (n.b. IAU 2000 specific). */
+   iauC2ixy(date1, date2, x, y, rc2i);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauC2ixy(double date1, double date2, double x, double y,
+              double rc2i[3][3])
+/*
+**  - - - - - - - - -
+**   i a u C 2 i x y
+**  - - - - - - - - -
+**
+**  Form the celestial to intermediate-frame-of-date matrix for a given
+**  date when the CIP X,Y coordinates are known.  IAU 2000.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     date1,date2 double       TT as a 2-part Julian Date (Note 1)
+**     x,y         double       Celestial Intermediate Pole (Note 2)
+**
+**  Returned:
+**     rc2i        double[3][3] celestial-to-intermediate matrix (Note 3)
+**
+**  Notes:
+**
+**  1) The TT date date1+date2 is a Julian Date, apportioned in any
+**     convenient way between the two arguments.  For example,
+**     JD(TT)=2450123.7 could be expressed in any of these ways,
+**     among others:
+**
+**            date1          date2
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in
+**     cases where the loss of several decimal digits of resolution
+**     is acceptable.  The J2000 method is best matched to the way
+**     the argument is handled internally and will deliver the
+**     optimum resolution.  The MJD method and the date & time methods
+**     are both good compromises between resolution and convenience.
+**
+**  2) The Celestial Intermediate Pole coordinates are the x,y components
+**     of the unit vector in the Geocentric Celestial Reference System.
+**
+**  3) The matrix rc2i is the first stage in the transformation from
+**     celestial to terrestrial coordinates:
+**
+**        [TRS] = RPOM * R_3(ERA) * rc2i * [CRS]
+**
+**              = RC2T * [CRS]
+**
+**     where [CRS] is a vector in the Geocentric Celestial Reference
+**     System and [TRS] is a vector in the International Terrestrial
+**     Reference System (see IERS Conventions 2003), ERA is the Earth
+**     Rotation Angle and RPOM is the polar motion matrix.
+**
+**  4) Although its name does not include "00", This function is in fact
+**     specific to the IAU 2000 models.
+**
+**  Called:
+**     iauC2ixys    celestial-to-intermediate matrix, given X,Y and s
+**     iauS00       the CIO locator s, given X,Y, IAU 2000A
+**
+**  Reference:
+**
+**     McCarthy, D. D., Petit, G. (eds.), IERS Conventions (2003),
+**     IERS Technical Note No. 32, BKG (2004)
+**
+**  This revision:  2008 May 11
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+
+{
+/* Compute s and then the matrix. */
+   iauC2ixys(x, y, iauS00(date1, date2, x, y), rc2i);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauC2ixys(double x, double y, double s, double rc2i[3][3])
+/*
+**  - - - - - - - - - -
+**   i a u C 2 i x y s
+**  - - - - - - - - - -
+**
+**  Form the celestial to intermediate-frame-of-date matrix given the CIP
+**  X,Y and the CIO locator s.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     x,y      double         Celestial Intermediate Pole (Note 1)
+**     s        double         the CIO locator s (Note 2)
+**
+**  Returned:
+**     rc2i     double[3][3]   celestial-to-intermediate matrix (Note 3)
+**
+**  Notes:
+**
+**  1) The Celestial Intermediate Pole coordinates are the x,y
+**     components of the unit vector in the Geocentric Celestial
+**     Reference System.
+**
+**  2) The CIO locator s (in radians) positions the Celestial
+**     Intermediate Origin on the equator of the CIP.
+**
+**  3) The matrix rc2i is the first stage in the transformation from
+**     celestial to terrestrial coordinates:
+**
+**        [TRS] = RPOM * R_3(ERA) * rc2i * [CRS]
+**
+**              = RC2T * [CRS]
+**
+**     where [CRS] is a vector in the Geocentric Celestial Reference
+**     System and [TRS] is a vector in the International Terrestrial
+**     Reference System (see IERS Conventions 2003), ERA is the Earth
+**     Rotation Angle and RPOM is the polar motion matrix.
+**
+**  Called:
+**     iauIr        initialize r-matrix to identity
+**     iauRz        rotate around Z-axis
+**     iauRy        rotate around Y-axis
+**
+**  Reference:
+**
+**     McCarthy, D. D., Petit, G. (eds.), IERS Conventions (2003),
+**     IERS Technical Note No. 32, BKG (2004)
+**
+**  This revision:  2008 May 11
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double r2, e, d;
+
+
+/* Obtain the spherical angles E and d. */
+   r2 = x*x + y*y;
+   e = (r2 != 0.0) ? atan2(y, x) : 0.0;
+   d = atan(sqrt(r2 / (1.0 - r2)));
+
+/* Form the matrix. */
+   iauIr(rc2i);
+   iauRz(e, rc2i);
+   iauRy(d, rc2i);
+   iauRz(-(e+s), rc2i);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauC2s(double p[3], double *theta, double *phi)
+/*
+**  - - - - - - -
+**   i a u C 2 s
+**  - - - - - - -
+**
+**  P-vector to spherical coordinates.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  vector/matrix support function.
+**
+**  Given:
+**     p      double[3]    p-vector
+**
+**  Returned:
+**     theta  double       longitude angle (radians)
+**     phi    double       latitude angle (radians)
+**
+**  Notes:
+**
+**  1) The vector p can have any magnitude; only its direction is used.
+**
+**  2) If p is null, zero theta and phi are returned.
+**
+**  3) At either pole, zero theta is returned.
+**
+**  This revision:  2008 May 11
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double x, y, z, d2;
+
+
+   x  = p[0];
+   y  = p[1];
+   z  = p[2];
+   d2 = x*x + y*y;
+
+   *theta = (d2 == 0.0) ? 0.0 : atan2(y, x);
+   *phi = (z == 0.0) ? 0.0 : atan2(z, sqrt(d2));
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauC2t00a(double tta, double ttb, double uta, double utb,
+               double xp, double yp, double rc2t[3][3])
+/*
+**  - - - - - - - - - -
+**   i a u C 2 t 0 0 a
+**  - - - - - - - - - -
+**
+**  Form the celestial to terrestrial matrix given the date, the UT1 and
+**  the polar motion, using the IAU 2000A nutation model.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     tta,ttb  double         TT as a 2-part Julian Date (Note 1)
+**     uta,utb  double         UT1 as a 2-part Julian Date (Note 1)
+**     xp,yp    double         coordinates of the pole (radians, Note 2)
+**
+**  Returned:
+**     rc2t     double[3][3]   celestial-to-terrestrial matrix (Note 3)
+**
+**  Notes:
+**
+**  1) The TT and UT1 dates tta+ttb and uta+utb are Julian Dates,
+**     apportioned in any convenient way between the arguments uta and
+**     utb.  For example, JD(UT1)=2450123.7 could be expressed in any of
+**     these ways, among others:
+**
+**             uta            utb
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in
+**     cases where the loss of several decimal digits of resolution is
+**     acceptable.  The J2000 and MJD methods are good compromises
+**     between resolution and convenience.  In the case of uta,utb, the
+**     date & time method is best matched to the Earth rotation angle
+**     algorithm used:  maximum precision is delivered when the uta
+**     argument is for 0hrs UT1 on the day in question and the utb
+**     argument lies in the range 0 to 1, or vice versa.
+**
+**  2) The arguments xp and yp are the coordinates (in radians) of the
+**     Celestial Intermediate Pole with respect to the International
+**     Terrestrial Reference System (see IERS Conventions 2003),
+**     measured along the meridians to 0 and 90 deg west respectively.
+**
+**  3) The matrix rc2t transforms from celestial to terrestrial
+**     coordinates:
+**
+**        [TRS] = RPOM * R_3(ERA) * RC2I * [CRS]
+**
+**              = rc2t * [CRS]
+**
+**     where [CRS] is a vector in the Geocentric Celestial Reference
+**     System and [TRS] is a vector in the International Terrestrial
+**     Reference System (see IERS Conventions 2003), RC2I is the
+**     celestial-to-intermediate matrix, ERA is the Earth rotation
+**     angle and RPOM is the polar motion matrix.
+**
+**  4) A faster, but slightly less accurate result (about 1 mas), can
+**     be obtained by using instead the iauC2t00b function.
+**
+**  Called:
+**     iauC2i00a    celestial-to-intermediate matrix, IAU 2000A
+**     iauEra00     Earth rotation angle, IAU 2000
+**     iauSp00      the TIO locator s', IERS 2000
+**     iauPom00     polar motion matrix
+**     iauC2tcio    form CIO-based celestial-to-terrestrial matrix
+**
+**  Reference:
+**
+**     McCarthy, D. D., Petit, G. (eds.), IERS Conventions (2003),
+**     IERS Technical Note No. 32, BKG (2004)
+**
+**  This revision:  2009 April 1
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double rc2i[3][3], era, sp, rpom[3][3];
+
+
+/* Form the celestial-to-intermediate matrix for this TT (IAU 2000A). */
+   iauC2i00a(tta, ttb, rc2i );
+
+/* Predict the Earth rotation angle for this UT1. */
+   era = iauEra00(uta, utb);
+
+/* Estimate s'. */
+   sp = iauSp00(tta, ttb);
+
+/* Form the polar motion matrix. */
+   iauPom00(xp, yp, sp, rpom);
+
+/* Combine to form the celestial-to-terrestrial matrix. */
+   iauC2tcio(rc2i, era, rpom, rc2t);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauC2t00b(double tta, double ttb, double uta, double utb,
+               double xp, double yp, double rc2t[3][3])
+/*
+**  - - - - - - - - - -
+**   i a u C 2 t 0 0 b
+**  - - - - - - - - - -
+**
+**  Form the celestial to terrestrial matrix given the date, the UT1 and
+**  the polar motion, using the IAU 2000B nutation model.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     tta,ttb  double         TT as a 2-part Julian Date (Note 1)
+**     uta,utb  double         UT1 as a 2-part Julian Date (Note 1)
+**     xp,yp    double         coordinates of the pole (radians, Note 2)
+**
+**  Returned:
+**     rc2t     double[3][3]   celestial-to-terrestrial matrix (Note 3)
+**
+**  Notes:
+**
+**  1) The TT and UT1 dates tta+ttb and uta+utb are Julian Dates,
+**     apportioned in any convenient way between the arguments uta and
+**     utb.  For example, JD(UT1)=2450123.7 could be expressed in any of
+**     these ways, among others:
+**
+**             uta            utb
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in
+**     cases where the loss of several decimal digits of resolution is
+**     acceptable.  The J2000 and MJD methods are good compromises
+**     between resolution and convenience.  In the case of uta,utb, the
+**     date & time method is best matched to the Earth rotation angle
+**     algorithm used:  maximum precision is delivered when the uta
+**     argument is for 0hrs UT1 on the day in question and the utb
+**     argument lies in the range 0 to 1, or vice versa.
+**
+**  2) The arguments xp and yp are the coordinates (in radians) of the
+**     Celestial Intermediate Pole with respect to the International
+**     Terrestrial Reference System (see IERS Conventions 2003),
+**     measured along the meridians to 0 and 90 deg west respectively.
+**
+**  3) The matrix rc2t transforms from celestial to terrestrial
+**     coordinates:
+**
+**        [TRS] = RPOM * R_3(ERA) * RC2I * [CRS]
+**
+**              = rc2t * [CRS]
+**
+**     where [CRS] is a vector in the Geocentric Celestial Reference
+**     System and [TRS] is a vector in the International Terrestrial
+**     Reference System (see IERS Conventions 2003), RC2I is the
+**     celestial-to-intermediate matrix, ERA is the Earth rotation
+**     angle and RPOM is the polar motion matrix.
+**
+**  4) The present function is faster, but slightly less accurate (about
+**     1 mas), than the iauC2t00a function.
+**
+**  Called:
+**     iauC2i00b    celestial-to-intermediate matrix, IAU 2000B
+**     iauEra00     Earth rotation angle, IAU 2000
+**     iauPom00     polar motion matrix
+**     iauC2tcio    form CIO-based celestial-to-terrestrial matrix
+**
+**  Reference:
+**
+**     McCarthy, D. D., Petit, G. (eds.), IERS Conventions (2003),
+**     IERS Technical Note No. 32, BKG (2004)
+**
+**  This revision:  2009 April 1
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double rc2i[3][3], era, rpom[3][3];
+
+
+/* Form the celestial-to-intermediate matrix for this TT (IAU 2000B). */
+   iauC2i00b(tta, ttb, rc2i);
+
+/* Predict the Earth rotation angle for this UT1. */
+   era = iauEra00(uta, utb);
+
+/* Form the polar motion matrix (neglecting s'). */
+   iauPom00(xp, yp, 0.0, rpom);
+
+/* Combine to form the celestial-to-terrestrial matrix. */
+   iauC2tcio(rc2i, era, rpom, rc2t);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauC2t06a(double tta, double ttb, double uta, double utb,
+               double xp, double yp, double rc2t[3][3])
+/*
+**  - - - - - - - - - -
+**   i a u C 2 t 0 6 a
+**  - - - - - - - - - -
+**
+**  Form the celestial to terrestrial matrix given the date, the UT1 and
+**  the polar motion, using the IAU 2006 precession and IAU 2000A
+**  nutation models.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     tta,ttb  double         TT as a 2-part Julian Date (Note 1)
+**     uta,utb  double         UT1 as a 2-part Julian Date (Note 1)
+**     xp,yp    double         coordinates of the pole (radians, Note 2)
+**
+**  Returned:
+**     rc2t     double[3][3]   celestial-to-terrestrial matrix (Note 3)
+**
+**  Notes:
+**
+**  1) The TT and UT1 dates tta+ttb and uta+utb are Julian Dates,
+**     apportioned in any convenient way between the arguments uta and
+**     utb.  For example, JD(UT1)=2450123.7 could be expressed in any of
+**     these ways, among others:
+**
+**             uta            utb
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in
+**     cases where the loss of several decimal digits of resolution is
+**     acceptable.  The J2000 and MJD methods are good compromises
+**     between resolution and convenience.  In the case of uta,utb, the
+**     date & time method is best matched to the Earth rotation angle
+**     algorithm used:  maximum precision is delivered when the uta
+**     argument is for 0hrs UT1 on the day in question and the utb
+**     argument lies in the range 0 to 1, or vice versa.
+**
+**  2) The arguments xp and yp are the coordinates (in radians) of the
+**     Celestial Intermediate Pole with respect to the International
+**     Terrestrial Reference System (see IERS Conventions 2003),
+**     measured along the meridians to 0 and 90 deg west respectively.
+**
+**  3) The matrix rc2t transforms from celestial to terrestrial
+**     coordinates:
+**
+**        [TRS] = RPOM * R_3(ERA) * RC2I * [CRS]
+**
+**              = rc2t * [CRS]
+**
+**     where [CRS] is a vector in the Geocentric Celestial Reference
+**     System and [TRS] is a vector in the International Terrestrial
+**     Reference System (see IERS Conventions 2003), RC2I is the
+**     celestial-to-intermediate matrix, ERA is the Earth rotation
+**     angle and RPOM is the polar motion matrix.
+**
+**  Called:
+**     iauC2i06a    celestial-to-intermediate matrix, IAU 2006/2000A
+**     iauEra00     Earth rotation angle, IAU 2000
+**     iauSp00      the TIO locator s', IERS 2000
+**     iauPom00     polar motion matrix
+**     iauC2tcio    form CIO-based celestial-to-terrestrial matrix
+**
+**  Reference:
+**
+**     McCarthy, D. D., Petit, G. (eds.), 2004, IERS Conventions (2003),
+**     IERS Technical Note No. 32, BKG
+**
+**  This revision:  2009 April 1
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double rc2i[3][3], era, sp, rpom[3][3];
+
+
+/* Form the celestial-to-intermediate matrix for this TT. */
+   iauC2i06a(tta, ttb, rc2i);
+
+/* Predict the Earth rotation angle for this UT1. */
+   era = iauEra00(uta, utb);
+
+/* Estimate s'. */
+   sp = iauSp00(tta, ttb);
+
+/* Form the polar motion matrix. */
+   iauPom00(xp, yp, sp, rpom);
+
+/* Combine to form the celestial-to-terrestrial matrix. */
+   iauC2tcio(rc2i, era, rpom, rc2t);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauC2tcio(double rc2i[3][3], double era, double rpom[3][3],
+               double rc2t[3][3])
+/*
+**  - - - - - - - - - -
+**   i a u C 2 t c i o
+**  - - - - - - - - - -
+**
+**  Assemble the celestial to terrestrial matrix from CIO-based
+**  components (the celestial-to-intermediate matrix, the Earth Rotation
+**  Angle and the polar motion matrix).
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     rc2i     double[3][3]    celestial-to-intermediate matrix
+**     era      double          Earth rotation angle
+**     rpom     double[3][3]    polar-motion matrix
+**
+**  Returned:
+**     rc2t     double[3][3]    celestial-to-terrestrial matrix
+**
+**  Notes:
+**
+**  1) This function constructs the rotation matrix that transforms
+**     vectors in the celestial system into vectors in the terrestrial
+**     system.  It does so starting from precomputed components, namely
+**     the matrix which rotates from celestial coordinates to the
+**     intermediate frame, the Earth rotation angle and the polar motion
+**     matrix.  One use of the present function is when generating a
+**     series of celestial-to-terrestrial matrices where only the Earth
+**     Rotation Angle changes, avoiding the considerable overhead of
+**     recomputing the precession-nutation more often than necessary to
+**     achieve given accuracy objectives.
+**
+**  2) The relationship between the arguments is as follows:
+**
+**        [TRS] = RPOM * R_3(ERA) * rc2i * [CRS]
+**
+**              = rc2t * [CRS]
+**
+**     where [CRS] is a vector in the Geocentric Celestial Reference
+**     System and [TRS] is a vector in the International Terrestrial
+**     Reference System (see IERS Conventions 2003).
+**
+**  Called:
+**     iauCr        copy r-matrix
+**     iauRz        rotate around Z-axis
+**     iauRxr       product of two r-matrices
+**
+**  Reference:
+**
+**     McCarthy, D. D., Petit, G. (eds.), 2004, IERS Conventions (2003),
+**     IERS Technical Note No. 32, BKG
+**
+**  This revision:  2008 May 11
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double r[3][3];
+
+
+/* Construct the matrix. */
+   iauCr(rc2i, r);
+   iauRz(era, r);
+   iauRxr(rpom, r, rc2t);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauC2teqx(double rbpn[3][3], double gst, double rpom[3][3],
+               double rc2t[3][3])
+/*
+**  - - - - - - - - - -
+**   i a u C 2 t e q x
+**  - - - - - - - - - -
+**
+**  Assemble the celestial to terrestrial matrix from equinox-based
+**  components (the celestial-to-true matrix, the Greenwich Apparent
+**  Sidereal Time and the polar motion matrix).
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     rbpn     double[3][3]    celestial-to-true matrix
+**     gst      double          Greenwich (apparent) Sidereal Time
+**     rpom     double[3][3]    polar-motion matrix
+**
+**  Returned:
+**     rc2t     double[3][3]    celestial-to-terrestrial matrix (Note 2)
+**
+**  Notes:
+**
+**  1) This function constructs the rotation matrix that transforms
+**     vectors in the celestial system into vectors in the terrestrial
+**     system.  It does so starting from precomputed components, namely
+**     the matrix which rotates from celestial coordinates to the
+**     true equator and equinox of date, the Greenwich Apparent Sidereal
+**     Time and the polar motion matrix.  One use of the present function
+**     is when generating a series of celestial-to-terrestrial matrices
+**     where only the Sidereal Time changes, avoiding the considerable
+**     overhead of recomputing the precession-nutation more often than
+**     necessary to achieve given accuracy objectives.
+**
+**  2) The relationship between the arguments is as follows:
+**
+**        [TRS] = rpom * R_3(gst) * rbpn * [CRS]
+**
+**              = rc2t * [CRS]
+**
+**     where [CRS] is a vector in the Geocentric Celestial Reference
+**     System and [TRS] is a vector in the International Terrestrial
+**     Reference System (see IERS Conventions 2003).
+**
+**  Called:
+**     iauCr        copy r-matrix
+**     iauRz        rotate around Z-axis
+**     iauRxr       product of two r-matrices
+**
+**  Reference:
+**
+**     McCarthy, D. D., Petit, G. (eds.), IERS Conventions (2003),
+**     IERS Technical Note No. 32, BKG (2004)
+**
+**  This revision:  2008 May 11
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double r[3][3];
+
+
+/* Construct the matrix. */
+   iauCr(rbpn, r);
+   iauRz(gst, r);
+   iauRxr(rpom, r, rc2t);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauC2tpe(double tta, double ttb, double uta, double utb,
+              double dpsi, double deps, double xp, double yp,
+              double rc2t[3][3])
+/*
+**  - - - - - - - - -
+**   i a u C 2 t p e
+**  - - - - - - - - -
+**
+**  Form the celestial to terrestrial matrix given the date, the UT1,
+**  the nutation and the polar motion.  IAU 2000.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     tta,ttb    double        TT as a 2-part Julian Date (Note 1)
+**     uta,utb    double        UT1 as a 2-part Julian Date (Note 1)
+**     dpsi,deps  double        nutation (Note 2)
+**     xp,yp      double        coordinates of the pole (radians, Note 3)
+**
+**  Returned:
+**     rc2t       double[3][3]  celestial-to-terrestrial matrix (Note 4)
+**
+**  Notes:
+**
+**  1) The TT and UT1 dates tta+ttb and uta+utb are Julian Dates,
+**     apportioned in any convenient way between the arguments uta and
+**     utb.  For example, JD(UT1)=2450123.7 could be expressed in any of
+**     these ways, among others:
+**
+**             uta            utb
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in
+**     cases where the loss of several decimal digits of resolution is
+**     acceptable.  The J2000 and MJD methods are good compromises
+**     between resolution and convenience.  In the case of uta,utb, the
+**     date & time method is best matched to the Earth rotation angle
+**     algorithm used:  maximum precision is delivered when the uta
+**     argument is for 0hrs UT1 on the day in question and the utb
+**     argument lies in the range 0 to 1, or vice versa.
+**
+**  2) The caller is responsible for providing the nutation components;
+**     they are in longitude and obliquity, in radians and are with
+**     respect to the equinox and ecliptic of date.  For high-accuracy
+**     applications, free core nutation should be included as well as
+**     any other relevant corrections to the position of the CIP.
+**
+**  3) The arguments xp and yp are the coordinates (in radians) of the
+**     Celestial Intermediate Pole with respect to the International
+**     Terrestrial Reference System (see IERS Conventions 2003),
+**     measured along the meridians to 0 and 90 deg west respectively.
+**
+**  4) The matrix rc2t transforms from celestial to terrestrial
+**     coordinates:
+**
+**        [TRS] = RPOM * R_3(GST) * RBPN * [CRS]
+**
+**              = rc2t * [CRS]
+**
+**     where [CRS] is a vector in the Geocentric Celestial Reference
+**     System and [TRS] is a vector in the International Terrestrial
+**     Reference System (see IERS Conventions 2003), RBPN is the
+**     bias-precession-nutation matrix, GST is the Greenwich (apparent)
+**     Sidereal Time and RPOM is the polar motion matrix.
+**
+**  5) Although its name does not include "00", This function is in fact
+**     specific to the IAU 2000 models.
+**
+**  Called:
+**     iauPn00      bias/precession/nutation results, IAU 2000
+**     iauGmst00    Greenwich mean sidereal time, IAU 2000
+**     iauSp00      the TIO locator s', IERS 2000
+**     iauEe00      equation of the equinoxes, IAU 2000
+**     iauPom00     polar motion matrix
+**     iauC2teqx    form equinox-based celestial-to-terrestrial matrix
+**
+**  Reference:
+**
+**     McCarthy, D. D., Petit, G. (eds.), IERS Conventions (2003),
+**     IERS Technical Note No. 32, BKG (2004)
+**
+**  This revision:  2009 April 1
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double epsa, rb[3][3], rp[3][3], rbp[3][3], rn[3][3],
+          rbpn[3][3], gmst, ee, sp, rpom[3][3];
+
+
+/* Form the celestial-to-true matrix for this TT. */
+   iauPn00(tta, ttb, dpsi, deps, &epsa, rb, rp, rbp, rn, rbpn);
+
+/* Predict the Greenwich Mean Sidereal Time for this UT1 and TT. */
+   gmst = iauGmst00(uta, utb, tta, ttb);
+
+/* Predict the equation of the equinoxes given TT and nutation. */
+   ee = iauEe00(tta, ttb, epsa, dpsi);
+
+/* Estimate s'. */
+   sp = iauSp00(tta, ttb);
+
+/* Form the polar motion matrix. */
+   iauPom00(xp, yp, sp, rpom);
+
+/* Combine to form the celestial-to-terrestrial matrix. */
+   iauC2teqx(rbpn, gmst + ee, rpom, rc2t);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauC2txy(double tta, double ttb, double uta, double utb,
+              double x, double y, double xp, double yp,
+              double rc2t[3][3])
+/*
+**  - - - - - - - - -
+**   i a u C 2 t x y
+**  - - - - - - - - -
+**
+**  Form the celestial to terrestrial matrix given the date, the UT1,
+**  the CIP coordinates and the polar motion.  IAU 2000.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     tta,ttb  double         TT as a 2-part Julian Date (Note 1)
+**     uta,utb  double         UT1 as a 2-part Julian Date (Note 1)
+**     x,y      double         Celestial Intermediate Pole (Note 2)
+**     xp,yp    double         coordinates of the pole (radians, Note 3)
+**
+**  Returned:
+**     rc2t     double[3][3]   celestial-to-terrestrial matrix (Note 4)
+**
+**  Notes:
+**
+**  1) The TT and UT1 dates tta+ttb and uta+utb are Julian Dates,
+**     apportioned in any convenient way between the arguments uta and
+**     utb.  For example, JD(UT1)=2450123.7 could be expressed in any o
+**     these ways, among others:
+**
+**             uta            utb
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in
+**     cases where the loss of several decimal digits of resolution is
+**     acceptable.  The J2000 and MJD methods are good compromises
+**     between resolution and convenience.  In the case of uta,utb, the
+**     date & time method is best matched to the Earth rotation angle
+**     algorithm used:  maximum precision is delivered when the uta
+**     argument is for 0hrs UT1 on the day in question and the utb
+**     argument lies in the range 0 to 1, or vice versa.
+**
+**  2) The Celestial Intermediate Pole coordinates are the x,y
+**     components of the unit vector in the Geocentric Celestial
+**     Reference System.
+**
+**  3) The arguments xp and yp are the coordinates (in radians) of the
+**     Celestial Intermediate Pole with respect to the International
+**     Terrestrial Reference System (see IERS Conventions 2003),
+**     measured along the meridians to 0 and 90 deg west respectively.
+**
+**  4) The matrix rc2t transforms from celestial to terrestrial
+**     coordinates:
+**
+**        [TRS] = RPOM * R_3(ERA) * RC2I * [CRS]
+**
+**              = rc2t * [CRS]
+**
+**     where [CRS] is a vector in the Geocentric Celestial Reference
+**     System and [TRS] is a vector in the International Terrestrial
+**     Reference System (see IERS Conventions 2003), ERA is the Earth
+**     Rotation Angle and RPOM is the polar motion matrix.
+**
+**  5) Although its name does not include "00", This function is in fact
+**     specific to the IAU 2000 models.
+**
+**  Called:
+**     iauC2ixy     celestial-to-intermediate matrix, given X,Y
+**     iauEra00     Earth rotation angle, IAU 2000
+**     iauSp00      the TIO locator s', IERS 2000
+**     iauPom00     polar motion matrix
+**     iauC2tcio    form CIO-based celestial-to-terrestrial matrix
+**
+** Reference:
+**
+**     McCarthy, D. D., Petit, G. (eds.), IERS Conventions (2003),
+**     IERS Technical Note No. 32, BKG (2004)
+**
+**  This revision:  2009 April 1
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double rc2i[3][3], era, sp, rpom[3][3];
+
+
+/* Form the celestial-to-intermediate matrix for this TT. */
+   iauC2ixy(tta, ttb, x, y, rc2i);
+
+/* Predict the Earth rotation angle for this UT1. */
+   era = iauEra00(uta, utb);
+
+/* Estimate s'. */
+   sp = iauSp00(tta, ttb);
+
+/* Form the polar motion matrix. */
+   iauPom00(xp, yp, sp, rpom);
+
+/* Combine to form the celestial-to-terrestrial matrix. */
+   iauC2tcio(rc2i, era, rpom, rc2t);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+int iauCal2jd(int iy, int im, int id, double *djm0, double *djm)
+/*
+**  - - - - - - - - - -
+**   i a u C a l 2 j d
+**  - - - - - - - - - -
+**
+**  Gregorian Calendar to Julian Date.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     iy,im,id  int     year, month, day in Gregorian calendar (Note 1)
+**
+**  Returned:
+**     djm0      double  MJD zero-point: always 2400000.5
+**     djm       double  Modified Julian Date for 0 hrs
+**
+**  Returned (function value):
+**               int     status:
+**                           0 = OK
+**                          -1 = bad year   (Note 3: JD not computed)
+**                          -2 = bad month  (JD not computed)
+**                          -3 = bad day    (JD computed)
+**
+**  Notes:
+**
+**  1) The algorithm used is valid from -4800 March 1, but this
+**     implementation rejects dates before -4799 January 1.
+**
+**  2) The Julian Date is returned in two pieces, in the usual SOFA
+**     manner, which is designed to preserve time resolution.  The
+**     Julian Date is available as a single number by adding djm0 and
+**     djm.
+**
+**  3) In early eras the conversion is from the "Proleptic Gregorian
+**     Calendar";  no account is taken of the date(s) of adoption of
+**     the Gregorian Calendar, nor is the AD/BC numbering convention
+**     observed.
+**
+**  Reference:
+**
+**     Explanatory Supplement to the Astronomical Almanac,
+**     P. Kenneth Seidelmann (ed), University Science Books (1992),
+**     Section 12.92 (p604).
+**
+**  This revision:  2009 October 19
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   int j, ly, my;
+   long iypmy;
+
+/* Earliest year allowed (4800BC) */
+   const int IYMIN = -4799;
+
+/* Month lengths in days */
+   static const int mtab[]
+                     = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+
+
+/* Preset status. */
+   j = 0;
+
+/* Validate year and month. */
+   if (iy < IYMIN) return -1;
+   if (im < 1 || im > 12) return -2;
+
+/* If February in a leap year, 1, otherwise 0. */
+   ly = ((im == 2) && !(iy%4) && (iy%100 || !(iy%400)));
+
+/* Validate day, taking into account leap years. */
+   if ( (id < 1) || (id > (mtab[im-1] + ly))) j = -3;
+
+/* Return result. */
+   my = (im - 14) / 12;
+   iypmy = (long) (iy + my);
+   *djm0 = 2400000.5;
+   *djm = (double)((1461L * (iypmy + 4800L)) / 4L
+                 + (367L * (long) (im - 2 - 12 * my)) / 12L
+                 - (3L * ((iypmy + 4900L) / 100L)) / 4L
+                 + (long) id - 2432076L);
+
+/* Return status. */
+   return j;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauCp(double p[3], double c[3])
+/*
+**  - - - - - -
+**   i a u C p
+**  - - - - - -
+**
+**  Copy a p-vector.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  vector/matrix support function.
+**
+**  Given:
+**     p        double[3]     p-vector to be copied
+**
+**  Returned:
+**     c        double[3]     copy
+**
+**  This revision:  2008 May 11
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   c[0] = p[0];
+   c[1] = p[1];
+   c[2] = p[2];
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauCpv(double pv[2][3], double c[2][3])
+/*
+**  - - - - - - -
+**   i a u C p v
+**  - - - - - - -
+**
+**  Copy a position/velocity vector.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  vector/matrix support function.
+**
+**  Given:
+**     pv     double[2][3]    position/velocity vector to be copied
+**
+**  Returned:
+**     c      double[2][3]    copy
+**
+**  Called:
+**     iauCp        copy p-vector
+**
+**  This revision:  2008 May 11
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   iauCp(pv[0], c[0]);
+   iauCp(pv[1], c[1]);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauCr(double r[3][3], double c[3][3])
+/*
+**  - - - - - -
+**   i a u C r
+**  - - - - - -
+**
+**  Copy an r-matrix.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  vector/matrix support function.
+**
+**  Given:
+**     r        double[3][3]    r-matrix to be copied
+**
+**  Returned:
+**   char[]     double[3][3]    copy
+**
+**  Called:
+**     iauCp        copy p-vector
+**
+**  This revision:  2008 May 11
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   iauCp(r[0], c[0]);
+   iauCp(r[1], c[1]);
+   iauCp(r[2], c[2]);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+#include <string.h>
+
+int iauD2dtf(const char *scale, int ndp, double d1, double d2,
+             int *iy, int *im, int *id, int ihmsf[4])
+/*
+**  - - - - - - - - -
+**   i a u D 2 d t f
+**  - - - - - - - - -
+**
+**  Format for output a 2-part Julian Date (or in the case of UTC a
+**  quasi-JD form that includes special provision for leap seconds).
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     scale     char[]  time scale ID (Note 1)
+**     ndp       int     resolution (Note 2)
+**     d1,d2     double  time as a 2-part Julian Date (Notes 3,4)
+**
+**  Returned:
+**     iy,im,id  int     year, month, day in Gregorian calendar (Note 5)
+**     ihmsf     int[4]  hours, minutes, seconds, fraction (Note 1)
+**
+**  Returned (function value):
+**               int     status: +1 = dubious year (Note 5)
+**                                0 = OK
+**                               -1 = unacceptable date (Note 6)
+**
+**  Notes:
+**
+**  1) scale identifies the time scale.  Only the value "UTC" (in upper
+**     case) is significant, and enables handling of leap seconds (see
+**     Note 4).
+**
+**  2) ndp is the number of decimal places in the seconds field, and can
+**     have negative as well as positive values, such as:
+**
+**     ndp         resolution
+**     -4            1 00 00
+**     -3            0 10 00
+**     -2            0 01 00
+**     -1            0 00 10
+**      0            0 00 01
+**      1            0 00 00.1
+**      2            0 00 00.01
+**      3            0 00 00.001
+**
+**     The limits are platform dependent, but a safe range is -5 to +9.
+**
+**  3) d1+d2 is Julian Date, apportioned in any convenient way between
+**     the two arguments, for example where d1 is the Julian Day Number
+**     and d2 is the fraction of a day.  In the case of UTC, where the
+**     use of JD is problematical, special conventions apply:  see the
+**     next note.
+**
+**  4) JD cannot unambiguously represent UTC during a leap second unless
+**     special measures are taken.  The SOFA internal convention is that
+**     the quasi-JD day represents UTC days whether the length is 86399,
+**     86400 or 86401 SI seconds.
+**
+**  5) The warning status "dubious year" flags UTCs that predate the
+**     introduction of the time scale and that are too far in the future
+**     to be trusted.  See iauDat for further details.
+**
+**  6) For calendar conventions and limitations, see iauCal2jd.
+**
+**  Called:
+**     iauJd2cal    JD to Gregorian calendar
+**     iauD2tf      decompose days to hms
+**     iauDat       delta(AT) = TAI-UTC
+**
+**  This revision:  2012 February 12
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   int leap;
+   char s;
+   int iy1, im1, id1, js, iy2, im2, id2, ihmsf1[4], i;
+   double a1, b1, fd, dat1, w, dat2, ddt;
+
+/* The two-part JD. */
+   a1 = d1;
+   b1 = d2;
+
+/* Provisional calendar date. */
+   js = iauJd2cal(a1, b1, &iy1, &im1, &id1, &fd);
+   if ( js ) return js < 0 ? -1 : js;
+
+/* Is this a leap second day? */
+   leap = 0;
+   if ( ! strcmp(scale,"UTC") ) {
+
+   /* TAI-UTC today. */
+      js = iauDat(iy1, im1, id1, fd, &dat1);
+      if ( js < 0 ) return -1;
+
+   /* TAI-UTC tomorrow (at noon, to avoid rounding effects). */
+      js = iauJd2cal(a1+1.5, b1-fd, &iy2, &im2, &id2, &w);
+      js = iauDat(iy2, im2, id2, 0.0, &dat2);
+      if ( js < 0 ) return -1;
+
+   /* The change in TAI-UTC (seconds). */
+      ddt = dat2 - dat1;
+
+   /* If leap second day, scale the fraction of a day into SI. */
+      leap = fabs(ddt) > 0.5;
+      if (leap) fd += fd * ddt/DAYSEC;
+   }
+
+/* Provisional time of day. */
+   iauD2tf ( ndp, fd, &s, ihmsf1 );
+
+/* Is this a leap second day? */
+   if ( ! leap ) {
+
+   /* No.  Has the time rounded up to 24h? */
+      if ( ihmsf1[0] > 23 ) {
+
+      /* Yes.  We will need tomorrow's calendar date. */
+         js = iauJd2cal(a1+1.5, b1-fd, &iy2, &im2, &id2, &w);
+
+      /* Use 0h tomorrow. */
+         iy1 = iy2;
+         im1 = im2;
+         id1 = id2;
+         for ( i = 0; i < 4; i++ ) {
+            ihmsf1[i] = 0;
+         }
+      }
+   } else {
+
+   /* This is a leap second day.  Has the time reached or passed 24h? */
+      if ( ihmsf1[0] > 23 ) {
+
+      /* Yes.  Use 23 59 60... */
+         ihmsf1[0] = 23;
+         ihmsf1[1] = 59;
+         ihmsf1[2] = 60;
+      }
+   }
+
+/* Results. */
+   *iy = iy1;
+   *im = im1;
+   *id = id1;
+   for ( i = 0; i < 4; i++ ) {
+      ihmsf[i] = ihmsf1[i];
+   }
+
+/* Status. */
+   return js < 0 ? -1 : js;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauD2tf(int ndp, double days, char *sign, int ihmsf[4])
+/*
+**  - - - - - - - -
+**   i a u D 2 t f
+**  - - - - - - - -
+**
+**  Decompose days to hours, minutes, seconds, fraction.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  vector/matrix support function.
+**
+**  Given:
+**     ndp     int     resolution (Note 1)
+**     days    double  interval in days
+**
+**  Returned:
+**     sign    char    '+' or '-'
+**     ihmsf   int[4]  hours, minutes, seconds, fraction
+**
+**  Notes:
+**
+**  1) The argument ndp is interpreted as follows:
+**
+**     ndp         resolution
+**      :      ...0000 00 00
+**     -7         1000 00 00
+**     -6          100 00 00
+**     -5           10 00 00
+**     -4            1 00 00
+**     -3            0 10 00
+**     -2            0 01 00
+**     -1            0 00 10
+**      0            0 00 01
+**      1            0 00 00.1
+**      2            0 00 00.01
+**      3            0 00 00.001
+**      :            0 00 00.000...
+**
+**  2) The largest positive useful value for ndp is determined by the
+**     size of days, the format of double on the target platform, and
+**     the risk of overflowing ihmsf[3].  On a typical platform, for
+**     days up to 1.0, the available floating-point precision might
+**     correspond to ndp=12.  However, the practical limit is typically
+**     ndp=9, set by the capacity of a 32-bit int, or ndp=4 if int is
+**     only 16 bits.
+**
+**  3) The absolute value of days may exceed 1.0.  In cases where it
+**     does not, it is up to the caller to test for and handle the
+**     case where days is very nearly 1.0 and rounds up to 24 hours,
+**     by testing for ihmsf[0]=24 and setting ihmsf[0-3] to zero.
+**
+**  This revision:  2008 May 17
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   int nrs, n;
+   double rs, rm, rh, a, w, ah, am, as, af;
+
+
+/* Handle sign. */
+   *sign = (char) ( ( days >= 0.0 ) ? '+' : '-' );
+
+/* Interval in seconds. */
+   a = DAYSEC * fabs(days);
+
+/* Pre-round if resolution coarser than 1s (then pretend ndp=1). */
+   if (ndp < 0) {
+      nrs = 1;
+      for (n = 1; n <= -ndp; n++) {
+          nrs *= (n == 2 || n == 4) ? 6 : 10;
+      }
+      rs = (double) nrs;
+      w = a / rs;
+      a = rs * dnint(w);
+   }
+
+/* Express the unit of each field in resolution units. */
+   nrs = 1;
+   for (n = 1; n <= ndp; n++) {
+      nrs *= 10;
+   }
+   rs = (double) nrs;
+   rm = rs * 60.0;
+   rh = rm * 60.0;
+
+/* Round the interval and express in resolution units. */
+   a = dnint(rs * a);
+
+/* Break into fields. */
+   ah = a / rh;
+   ah = dint(ah);
+   a -= ah * rh;
+   am = a / rm;
+   am = dint(am);
+   a -= am * rm;
+   as = a / rs;
+   as = dint(as);
+   af = a - as * rs;
+
+/* Return results. */
+   ihmsf[0] = (int) ah;
+   ihmsf[1] = (int) am;
+   ihmsf[2] = (int) as;
+   ihmsf[3] = (int) af;
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+int iauDat(int iy, int im, int id, double fd, double *deltat )
+/*
+**  - - - - - - -
+**   i a u D a t
+**  - - - - - - -
+**
+**  For a given UTC date, calculate delta(AT) = TAI-UTC.
+**
+**     :------------------------------------------:
+**     :                                          :
+**     :                 IMPORTANT                :
+**     :                                          :
+**     :  A new version of this function must be  :
+**     :  produced whenever a new leap second is  :
+**     :  announced.  There are four items to     :
+**     :  change on each such occasion:           :
+**     :                                          :
+**     :  1) A new line must be added to the set  :
+**     :     of statements that initialize the    :
+**     :     array "changes".                     :
+**     :                                          :
+**     :  2) The parameter IYV must be set to     :
+**     :     the current year.                    :
+**     :                                          :
+**     :  3) The "Latest leap second" comment     :
+**     :     below must be set to the new leap    :
+**     :     second date.                         :
+**     :                                          :
+**     :  4) The "This revision" comment, later,  :
+**     :     must be set to the current date.     :
+**     :                                          :
+**     :  Change (2) must also be carried out     :
+**     :  whenever the function is re-issued,     :
+**     :  even if no leap seconds have been       :
+**     :  added.                                  :
+**     :                                          :
+**     :  Latest leap second:  2012 June 30       :
+**     :                                          :
+**     :__________________________________________:
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     iy     int      UTC:  year (Notes 1 and 2)
+**     im     int            month (Note 2)
+**     id     int            day (Notes 2 and 3)
+**     fd     double         fraction of day (Note 4)
+**
+**  Returned:
+**     deltat double   TAI minus UTC, seconds
+**
+**  Returned (function value):
+**            int      status (Note 5):
+**                       1 = dubious year (Note 1)
+**                       0 = OK
+**                      -1 = bad year
+**                      -2 = bad month
+**                      -3 = bad day (Note 3)
+**                      -4 = bad fraction (Note 4)
+**
+**  Notes:
+**
+**  1) UTC began at 1960 January 1.0 (JD 2436934.5) and it is improper
+**     to call the function with an earlier date.  If this is attempted,
+**     zero is returned together with a warning status.
+**
+**     Because leap seconds cannot, in principle, be predicted in
+**     advance, a reliable check for dates beyond the valid range is
+**     impossible.  To guard against gross errors, a year five or more
+**     after the release year of the present function (see parameter
+**     IYV) is considered dubious.  In this case a warning status is
+**     returned but the result is computed in the normal way.
+**
+**     For both too-early and too-late years, the warning status is
+**     j=+1.  This is distinct from the error status j=-1, which
+**     signifies a year so early that JD could not be computed.
+**
+**  2) If the specified date is for a day which ends with a leap second,
+**     the UTC-TAI value returned is for the period leading up to the
+**     leap second.  If the date is for a day which begins as a leap
+**     second ends, the UTC-TAI returned is for the period following the
+**     leap second.
+**
+**  3) The day number must be in the normal calendar range, for example
+**     1 through 30 for April.  The "almanac" convention of allowing
+**     such dates as January 0 and December 32 is not supported in this
+**     function, in order to avoid confusion near leap seconds.
+**
+**  4) The fraction of day is used only for dates before the
+**     introduction of leap seconds, the first of which occurred at the
+**     end of 1971.  It is tested for validity (zero to less than 1 is
+**     the valid range) even if not used;  if invalid, zero is used and
+**     status j=-4 is returned.  For many applications, setting fd to
+**     zero is acceptable;  the resulting error is always less than 3 ms
+**     (and occurs only pre-1972).
+**
+**  5) The status value returned in the case where there are multiple
+**     errors refers to the first error detected.  For example, if the
+**     month and day are 13 and 32 respectively, j=-2 (bad month)
+**     will be returned.
+**
+**  6) In cases where a valid result is not available, zero is returned.
+**
+**  References:
+**
+**  1) For dates from 1961 January 1 onwards, the expressions from the
+**     file ftp://maia.usno.navy.mil/ser7/tai-utc.dat are used.
+**
+**  2) The 5ms timestep at 1961 January 1 is taken from 2.58.1 (p87) of
+**     the 1992 Explanatory Supplement.
+**
+**  Called:
+**     iauCal2jd    Gregorian calendar to Julian Day number
+**
+**  This revision:  2012 January 5
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+/* Release year for this version of iauDat */
+#define IYV (2012)
+
+/* Reference dates (MJD) and drift rates (s/day), pre leap seconds */
+   static const double drift[][2] = {
+      { 37300.0, 0.0012960 },
+      { 37300.0, 0.0012960 },
+      { 37300.0, 0.0012960 },
+      { 37665.0, 0.0011232 },
+      { 37665.0, 0.0011232 },
+      { 38761.0, 0.0012960 },
+      { 38761.0, 0.0012960 },
+      { 38761.0, 0.0012960 },
+      { 38761.0, 0.0012960 },
+      { 38761.0, 0.0012960 },
+      { 38761.0, 0.0012960 },
+      { 38761.0, 0.0012960 },
+      { 39126.0, 0.0025920 },
+      { 39126.0, 0.0025920 }
+   };
+
+/* Number of Delta(AT) expressions before leap seconds were introduced */
+#define NERA1 ((int) (sizeof drift / sizeof (double) / 2))
+
+/* Dates and Delta(AT)s */
+   static const struct {
+      int iyear, month;
+      double delat;
+   } changes[] = {
+      { 1960,  1,  1.4178180 },
+      { 1961,  1,  1.4228180 },
+      { 1961,  8,  1.3728180 },
+      { 1962,  1,  1.8458580 },
+      { 1963, 11,  1.9458580 },
+      { 1964,  1,  3.2401300 },
+      { 1964,  4,  3.3401300 },
+      { 1964,  9,  3.4401300 },
+      { 1965,  1,  3.5401300 },
+      { 1965,  3,  3.6401300 },
+      { 1965,  7,  3.7401300 },
+      { 1965,  9,  3.8401300 },
+      { 1966,  1,  4.3131700 },
+      { 1968,  2,  4.2131700 },
+      { 1972,  1, 10.0       },
+      { 1972,  7, 11.0       },
+      { 1973,  1, 12.0       },
+      { 1974,  1, 13.0       },
+      { 1975,  1, 14.0       },
+      { 1976,  1, 15.0       },
+      { 1977,  1, 16.0       },
+      { 1978,  1, 17.0       },
+      { 1979,  1, 18.0       },
+      { 1980,  1, 19.0       },
+      { 1981,  7, 20.0       },
+      { 1982,  7, 21.0       },
+      { 1983,  7, 22.0       },
+      { 1985,  7, 23.0       },
+      { 1988,  1, 24.0       },
+      { 1990,  1, 25.0       },
+      { 1991,  1, 26.0       },
+      { 1992,  7, 27.0       },
+      { 1993,  7, 28.0       },
+      { 1994,  7, 29.0       },
+      { 1996,  1, 30.0       },
+      { 1997,  7, 31.0       },
+      { 1999,  1, 32.0       },
+      { 2006,  1, 33.0       },
+      { 2009,  1, 34.0       },
+      { 2012,  7, 35.0       }
+   };
+
+/* Number of Delta(AT) changes */
+   const int NDAT = sizeof changes / sizeof changes[0];
+
+/* Miscellaneous local variables */
+   int j, i, m;
+   double da, djm0, djm;
+
+
+/* Initialize the result to zero. */
+   *deltat = da = 0.0;
+
+/* If invalid fraction of a day, set error status and give up. */
+   if (fd < 0.0 || fd >= 1.0) return -4;
+
+/* Convert the date into an MJD. */
+   j = iauCal2jd(iy, im, id, &djm0, &djm);
+
+/* If invalid year, month, or day, give up. */
+   if (j < 0) return j;
+
+/* If pre-UTC year, set warning status and give up. */
+   if (iy < changes[0].iyear) return 1;
+
+/* If suspiciously late year, set warning status but proceed. */
+   if (iy > IYV + 5) j = 1;
+
+/* Combine year and month to form a date-ordered integer... */
+   m = 12*iy + im;
+
+/* ...and use it to find the preceding table entry. */
+   for (i = NDAT-1; i >=0; i--) {
+      if (m >= (12 * changes[i].iyear + changes[i].month)) break;
+   }
+
+/* Get the Delta(AT). */
+   da = changes[i].delat;
+
+/* If pre-1972, adjust for drift. */
+   if (i < NERA1) da += (djm + fd - drift[i][0]) * drift[i][1];
+
+/* Return the Delta(AT) value. */
+   *deltat = da;
+
+/* Return the status. */
+   return j;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+double iauDtdb(double date1, double date2,
+               double ut, double elong, double u, double v)
+/*
+**  - - - - - - - -
+**   i a u D t d b
+**  - - - - - - - -
+**
+**  An approximation to TDB-TT, the difference between barycentric
+**  dynamical time and terrestrial time, for an observer on the Earth.
+**
+**  The different time scales - proper, coordinate and realized - are
+**  related to each other:
+**
+**            TAI             <-  physically realized
+**             :
+**          offset            <-  observed (nominally +32.184s)
+**             :
+**            TT              <-  terrestrial time
+**             :
+**    rate adjustment (L_G)   <-  definition of TT
+**             :
+**            TCG             <-  time scale for GCRS
+**             :
+**      "periodic" terms      <-  iauDtdb  is an implementation
+**             :
+**    rate adjustment (L_C)   <-  function of solar-system ephemeris
+**             :
+**            TCB             <-  time scale for BCRS
+**             :
+**    rate adjustment (-L_B)  <-  definition of TDB
+**             :
+**            TDB             <-  TCB scaled to track TT
+**             :
+**      "periodic" terms      <-  -iauDtdb is an approximation
+**             :
+**            TT              <-  terrestrial time
+**
+**  Adopted values for the various constants can be found in the IERS
+**  Conventions (McCarthy & Petit 2003).
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support routine.
+**
+**  Given:
+**     date1,date2   double  date, TDB (Notes 1-3)
+**     ut            double  universal time (UT1, fraction of one day)
+**     elong         double  longitude (east positive, radians)
+**     u             double  distance from Earth spin axis (km)
+**     v             double  distance north of equatorial plane (km)
+**
+**  Returned (function value):
+**                   double  TDB-TT (seconds)
+**
+**  Notes:
+**
+**  1) The date date1+date2 is a Julian Date, apportioned in any
+**     convenient way between the two arguments.  For example,
+**     JD(TT)=2450123.7 could be expressed in any of these ways,
+**     among others:
+**
+**            date1          date2
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in
+**     cases where the loss of several decimal digits of resolution
+**     is acceptable.  The J2000 method is best matched to the way
+**     the argument is handled internally and will deliver the
+**     optimum resolution.  The MJD method and the date & time methods
+**     are both good compromises between resolution and convenience.
+**
+**     Although the date is, formally, barycentric dynamical time (TDB),
+**     the terrestrial dynamical time (TT) can be used with no practical
+**     effect on the accuracy of the prediction.
+**
+**  2) TT can be regarded as a coordinate time that is realized as an
+**     offset of 32.184s from International Atomic Time, TAI.  TT is a
+**     specific linear transformation of geocentric coordinate time TCG,
+**     which is the time scale for the Geocentric Celestial Reference
+**     System, GCRS.
+**
+**  3) TDB is a coordinate time, and is a specific linear transformation
+**     of barycentric coordinate time TCB, which is the time scale for
+**     the Barycentric Celestial Reference System, BCRS.
+**
+**  4) The difference TCG-TCB depends on the masses and positions of the
+**     bodies of the solar system and the velocity of the Earth.  It is
+**     dominated by a rate difference, the residual being of a periodic
+**     character.  The latter, which is modeled by the present function,
+**     comprises a main (annual) sinusoidal term of amplitude
+**     approximately 0.00166 seconds, plus planetary terms up to about
+**     20 microseconds, and lunar and diurnal terms up to 2 microseconds.
+**     These effects come from the changing transverse Doppler effect
+**     and gravitational red-shift as the observer (on the Earth's
+**     surface) experiences variations in speed (with respect to the
+**     BCRS) and gravitational potential.
+**
+**  5) TDB can be regarded as the same as TCB but with a rate adjustment
+**     to keep it close to TT, which is convenient for many applications.
+**     The history of successive attempts to define TDB is set out in
+**     Resolution 3 adopted by the IAU General Assembly in 2006, which
+**     defines a fixed TDB(TCB) transformation that is consistent with
+**     contemporary solar-system ephemerides.  Future ephemerides will
+**     imply slightly changed transformations between TCG and TCB, which
+**     could introduce a linear drift between TDB and TT;  however, any
+**     such drift is unlikely to exceed 1 nanosecond per century.
+**
+**  6) The geocentric TDB-TT model used in the present function is that of
+**     Fairhead & Bretagnon (1990), in its full form.  It was originally
+**     supplied by Fairhead (private communications with P.T.Wallace,
+**     1990) as a Fortran subroutine.  The present C function contains an
+**     adaptation of the Fairhead code.  The numerical results are
+**     essentially unaffected by the changes, the differences with
+**     respect to the Fairhead & Bretagnon original being at the 1e-20 s
+**     level.
+**
+**     The topocentric part of the model is from Moyer (1981) and
+**     Murray (1983), with fundamental arguments adapted from
+**     Simon et al. 1994.  It is an approximation to the expression
+**     ( v / c ) . ( r / c ), where v is the barycentric velocity of
+**     the Earth, r is the geocentric position of the observer and
+**     c is the speed of light.
+**
+**     By supplying zeroes for u and v, the topocentric part of the
+**     model can be nullified, and the function will return the Fairhead
+**     & Bretagnon result alone.
+**
+**  7) During the interval 1950-2050, the absolute accuracy is better
+**     than +/- 3 nanoseconds relative to time ephemerides obtained by
+**     direct numerical integrations based on the JPL DE405 solar system
+**     ephemeris.
+**
+**  8) It must be stressed that the present function is merely a model,
+**     and that numerical integration of solar-system ephemerides is the
+**     definitive method for predicting the relationship between TCG and
+**     TCB and hence between TT and TDB.
+**
+**  References:
+**
+**     Fairhead, L., & Bretagnon, P., Astron.Astrophys., 229, 240-247
+**     (1990).
+**
+**     IAU 2006 Resolution 3.
+**
+**     McCarthy, D. D., Petit, G. (eds.), IERS Conventions (2003),
+**     IERS Technical Note No. 32, BKG (2004)
+**
+**     Moyer, T.D., Cel.Mech., 23, 33 (1981).
+**
+**     Murray, C.A., Vectorial Astrometry, Adam Hilger (1983).
+**
+**     Seidelmann, P.K. et al., Explanatory Supplement to the
+**     Astronomical Almanac, Chapter 2, University Science Books (1992).
+**
+**     Simon, J.L., Bretagnon, P., Chapront, J., Chapront-Touze, M.,
+**     Francou, G. & Laskar, J., Astron.Astrophys., 282, 663-683 (1994).
+**
+**  This revision:  2012 February 14
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double t, tsol, w, elsun, emsun, d, elj, els, wt, w0, w1, w2, w3, w4,
+          wf, wj;
+   int j;
+
+/*
+** =====================
+** Fairhead et al. model
+** =====================
+**
+** 787 sets of three coefficients.
+**
+** Each set is
+**    amplitude (microseconds)
+**      frequency (radians per Julian millennium since J2000.0)
+**      phase (radians)
+**
+** Sets   1-474 are the T**0 terms
+**  "   475-679  "   "  T**1
+**  "   680-764  "   "  T**2
+**  "   765-784  "   "  T**3
+**  "   785-787  "   "  T**4
+*/
+
+   static const double fairhd[787][3] = {
+   /* 1, 10 */
+      { 1656.674564e-6,     6283.075849991,  6.240054195 },
+      {   22.417471e-6,     5753.384884897,  4.296977442 },
+      {   13.839792e-6,    12566.151699983,  6.196904410 },
+      {    4.770086e-6,      529.690965095,  0.444401603 },
+      {    4.676740e-6,     6069.776754553,  4.021195093 },
+      {    2.256707e-6,      213.299095438,  5.543113262 },
+      {    1.694205e-6,      -3.523118349,   5.025132748 },
+      {    1.554905e-6,    77713.771467920,  5.198467090 },
+      {    1.276839e-6,     7860.419392439,  5.988822341 },
+      {    1.193379e-6,     5223.693919802,  3.649823730 },
+   /* 11, 20 */
+      {    1.115322e-6,     3930.209696220,  1.422745069 },
+      {    0.794185e-6,    11506.769769794,  2.322313077 },
+      {    0.447061e-6,       26.298319800,  3.615796498 },
+      {    0.435206e-6,     -398.149003408,  4.349338347 },
+      {    0.600309e-6,     1577.343542448,  2.678271909 },
+      {    0.496817e-6,     6208.294251424,  5.696701824 },
+      {    0.486306e-6,     5884.926846583,  0.520007179 },
+      {    0.432392e-6,       74.781598567,  2.435898309 },
+      {    0.468597e-6,     6244.942814354,  5.866398759 },
+      {    0.375510e-6,     5507.553238667,  4.103476804 },
+   /* 21, 30 */
+      {    0.243085e-6,     -775.522611324,  3.651837925 },
+      {    0.173435e-6,    18849.227549974,  6.153743485 },
+      {    0.230685e-6,     5856.477659115,  4.773852582 },
+      {    0.203747e-6,    12036.460734888,  4.333987818 },
+      {    0.143935e-6,     -796.298006816,  5.957517795 },
+      {    0.159080e-6,    10977.078804699,  1.890075226 },
+      {    0.119979e-6,       38.133035638,  4.551585768 },
+      {    0.118971e-6,     5486.777843175,  1.914547226 },
+      {    0.116120e-6,     1059.381930189,  0.873504123 },
+      {    0.137927e-6,    11790.629088659,  1.135934669 },
+   /* 31, 40 */
+      {    0.098358e-6,     2544.314419883,  0.092793886 },
+      {    0.101868e-6,    -5573.142801634,  5.984503847 },
+      {    0.080164e-6,      206.185548437,  2.095377709 },
+      {    0.079645e-6,     4694.002954708,  2.949233637 },
+      {    0.062617e-6,       20.775395492,  2.654394814 },
+      {    0.075019e-6,     2942.463423292,  4.980931759 },
+      {    0.064397e-6,     5746.271337896,  1.280308748 },
+      {    0.063814e-6,     5760.498431898,  4.167901731 },
+      {    0.048042e-6,     2146.165416475,  1.495846011 },
+      {    0.048373e-6,      155.420399434,  2.251573730 },
+   /* 41, 50 */
+      {    0.058844e-6,      426.598190876,  4.839650148 },
+      {    0.046551e-6,       -0.980321068,  0.921573539 },
+      {    0.054139e-6,    17260.154654690,  3.411091093 },
+      {    0.042411e-6,     6275.962302991,  2.869567043 },
+      {    0.040184e-6,       -7.113547001,  3.565975565 },
+      {    0.036564e-6,     5088.628839767,  3.324679049 },
+      {    0.040759e-6,    12352.852604545,  3.981496998 },
+      {    0.036507e-6,      801.820931124,  6.248866009 },
+      {    0.036955e-6,     3154.687084896,  5.071801441 },
+      {    0.042732e-6,      632.783739313,  5.720622217 },
+   /* 51, 60 */
+      {    0.042560e-6,   161000.685737473,  1.270837679 },
+      {    0.040480e-6,    15720.838784878,  2.546610123 },
+      {    0.028244e-6,    -6286.598968340,  5.069663519 },
+      {    0.033477e-6,     6062.663207553,  4.144987272 },
+      {    0.034867e-6,      522.577418094,  5.210064075 },
+      {    0.032438e-6,     6076.890301554,  0.749317412 },
+      {    0.030215e-6,     7084.896781115,  3.389610345 },
+      {    0.029247e-6,   -71430.695617928,  4.183178762 },
+      {    0.033529e-6,     9437.762934887,  2.404714239 },
+      {    0.032423e-6,     8827.390269875,  5.541473556 },
+   /* 61, 70 */
+      {    0.027567e-6,     6279.552731642,  5.040846034 },
+      {    0.029862e-6,    12139.553509107,  1.770181024 },
+      {    0.022509e-6,    10447.387839604,  1.460726241 },
+      {    0.020937e-6,     8429.241266467,  0.652303414 },
+      {    0.020322e-6,      419.484643875,  3.735430632 },
+      {    0.024816e-6,    -1194.447010225,  1.087136918 },
+      {    0.025196e-6,     1748.016413067,  2.901883301 },
+      {    0.021691e-6,    14143.495242431,  5.952658009 },
+      {    0.017673e-6,     6812.766815086,  3.186129845 },
+      {    0.022567e-6,     6133.512652857,  3.307984806 },
+   /* 71, 80 */
+      {    0.016155e-6,    10213.285546211,  1.331103168 },
+      {    0.014751e-6,     1349.867409659,  4.308933301 },
+      {    0.015949e-6,     -220.412642439,  4.005298270 },
+      {    0.015974e-6,    -2352.866153772,  6.145309371 },
+      {    0.014223e-6,    17789.845619785,  2.104551349 },
+      {    0.017806e-6,       73.297125859,  3.475975097 },
+      {    0.013671e-6,     -536.804512095,  5.971672571 },
+      {    0.011942e-6,     8031.092263058,  2.053414715 },
+      {    0.014318e-6,    16730.463689596,  3.016058075 },
+      {    0.012462e-6,      103.092774219,  1.737438797 },
+   /* 81, 90 */
+      {    0.010962e-6,        3.590428652,  2.196567739 },
+      {    0.015078e-6,    19651.048481098,  3.969480770 },
+      {    0.010396e-6,      951.718406251,  5.717799605 },
+      {    0.011707e-6,    -4705.732307544,  2.654125618 },
+      {    0.010453e-6,     5863.591206116,  1.913704550 },
+      {    0.012420e-6,     4690.479836359,  4.734090399 },
+      {    0.011847e-6,     5643.178563677,  5.489005403 },
+      {    0.008610e-6,     3340.612426700,  3.661698944 },
+      {    0.011622e-6,     5120.601145584,  4.863931876 },
+      {    0.010825e-6,      553.569402842,  0.842715011 },
+   /* 91, 100 */
+      {    0.008666e-6,     -135.065080035,  3.293406547 },
+      {    0.009963e-6,      149.563197135,  4.870690598 },
+      {    0.009858e-6,     6309.374169791,  1.061816410 },
+      {    0.007959e-6,      316.391869657,  2.465042647 },
+      {    0.010099e-6,      283.859318865,  1.942176992 },
+      {    0.007147e-6,     -242.728603974,  3.661486981 },
+      {    0.007505e-6,     5230.807466803,  4.920937029 },
+      {    0.008323e-6,    11769.853693166,  1.229392026 },
+      {    0.007490e-6,    -6256.777530192,  3.658444681 },
+      {    0.009370e-6,   149854.400134205,  0.673880395 },
+   /* 101, 110 */
+      {    0.007117e-6,       38.027672636,  5.294249518 },
+      {    0.007857e-6,    12168.002696575,  0.525733528 },
+      {    0.007019e-6,     6206.809778716,  0.837688810 },
+      {    0.006056e-6,      955.599741609,  4.194535082 },
+      {    0.008107e-6,    13367.972631107,  3.793235253 },
+      {    0.006731e-6,     5650.292110678,  5.639906583 },
+      {    0.007332e-6,       36.648562930,  0.114858677 },
+      {    0.006366e-6,     4164.311989613,  2.262081818 },
+      {    0.006858e-6,     5216.580372801,  0.642063318 },
+      {    0.006919e-6,     6681.224853400,  6.018501522 },
+   /* 111, 120 */
+      {    0.006826e-6,     7632.943259650,  3.458654112 },
+      {    0.005308e-6,    -1592.596013633,  2.500382359 },
+      {    0.005096e-6,    11371.704689758,  2.547107806 },
+      {    0.004841e-6,     5333.900241022,  0.437078094 },
+      {    0.005582e-6,     5966.683980335,  2.246174308 },
+      {    0.006304e-6,    11926.254413669,  2.512929171 },
+      {    0.006603e-6,    23581.258177318,  5.393136889 },
+      {    0.005123e-6,       -1.484472708,  2.999641028 },
+      {    0.004648e-6,     1589.072895284,  1.275847090 },
+      {    0.005119e-6,     6438.496249426,  1.486539246 },
+   /* 121, 130 */
+      {    0.004521e-6,     4292.330832950,  6.140635794 },
+      {    0.005680e-6,    23013.539539587,  4.557814849 },
+      {    0.005488e-6,       -3.455808046,  0.090675389 },
+      {    0.004193e-6,     7234.794256242,  4.869091389 },
+      {    0.003742e-6,     7238.675591600,  4.691976180 },
+      {    0.004148e-6,     -110.206321219,  3.016173439 },
+      {    0.004553e-6,    11499.656222793,  5.554998314 },
+      {    0.004892e-6,     5436.993015240,  1.475415597 },
+      {    0.004044e-6,     4732.030627343,  1.398784824 },
+      {    0.004164e-6,    12491.370101415,  5.650931916 },
+   /* 131, 140 */
+      {    0.004349e-6,    11513.883316794,  2.181745369 },
+      {    0.003919e-6,    12528.018664345,  5.823319737 },
+      {    0.003129e-6,     6836.645252834,  0.003844094 },
+      {    0.004080e-6,    -7058.598461315,  3.690360123 },
+      {    0.003270e-6,       76.266071276,  1.517189902 },
+      {    0.002954e-6,     6283.143160294,  4.447203799 },
+      {    0.002872e-6,       28.449187468,  1.158692983 },
+      {    0.002881e-6,      735.876513532,  0.349250250 },
+      {    0.003279e-6,     5849.364112115,  4.893384368 },
+      {    0.003625e-6,     6209.778724132,  1.473760578 },
+   /* 141, 150 */
+      {    0.003074e-6,      949.175608970,  5.185878737 },
+      {    0.002775e-6,     9917.696874510,  1.030026325 },
+      {    0.002646e-6,    10973.555686350,  3.918259169 },
+      {    0.002575e-6,    25132.303399966,  6.109659023 },
+      {    0.003500e-6,      263.083923373,  1.892100742 },
+      {    0.002740e-6,    18319.536584880,  4.320519510 },
+      {    0.002464e-6,      202.253395174,  4.698203059 },
+      {    0.002409e-6,        2.542797281,  5.325009315 },
+      {    0.003354e-6,   -90955.551694697,  1.942656623 },
+      {    0.002296e-6,     6496.374945429,  5.061810696 },
+   /* 151, 160 */
+      {    0.003002e-6,     6172.869528772,  2.797822767 },
+      {    0.003202e-6,    27511.467873537,  0.531673101 },
+      {    0.002954e-6,    -6283.008539689,  4.533471191 },
+      {    0.002353e-6,      639.897286314,  3.734548088 },
+      {    0.002401e-6,    16200.772724501,  2.605547070 },
+      {    0.003053e-6,   233141.314403759,  3.029030662 },
+      {    0.003024e-6,    83286.914269554,  2.355556099 },
+      {    0.002863e-6,    17298.182327326,  5.240963796 },
+      {    0.002103e-6,    -7079.373856808,  5.756641637 },
+      {    0.002303e-6,    83996.847317911,  2.013686814 },
+   /* 161, 170 */
+      {    0.002303e-6,    18073.704938650,  1.089100410 },
+      {    0.002381e-6,       63.735898303,  0.759188178 },
+      {    0.002493e-6,     6386.168624210,  0.645026535 },
+      {    0.002366e-6,        3.932153263,  6.215885448 },
+      {    0.002169e-6,    11015.106477335,  4.845297676 },
+      {    0.002397e-6,     6243.458341645,  3.809290043 },
+      {    0.002183e-6,     1162.474704408,  6.179611691 },
+      {    0.002353e-6,     6246.427287062,  4.781719760 },
+      {    0.002199e-6,     -245.831646229,  5.956152284 },
+      {    0.001729e-6,     3894.181829542,  1.264976635 },
+   /* 171, 180 */
+      {    0.001896e-6,    -3128.388765096,  4.914231596 },
+      {    0.002085e-6,       35.164090221,  1.405158503 },
+      {    0.002024e-6,    14712.317116458,  2.752035928 },
+      {    0.001737e-6,     6290.189396992,  5.280820144 },
+      {    0.002229e-6,      491.557929457,  1.571007057 },
+      {    0.001602e-6,    14314.168113050,  4.203664806 },
+      {    0.002186e-6,      454.909366527,  1.402101526 },
+      {    0.001897e-6,    22483.848574493,  4.167932508 },
+      {    0.001825e-6,    -3738.761430108,  0.545828785 },
+      {    0.001894e-6,     1052.268383188,  5.817167450 },
+   /* 181, 190 */
+      {    0.001421e-6,       20.355319399,  2.419886601 },
+      {    0.001408e-6,    10984.192351700,  2.732084787 },
+      {    0.001847e-6,    10873.986030480,  2.903477885 },
+      {    0.001391e-6,    -8635.942003763,  0.593891500 },
+      {    0.001388e-6,       -7.046236698,  1.166145902 },
+      {    0.001810e-6,   -88860.057071188,  0.487355242 },
+      {    0.001288e-6,    -1990.745017041,  3.913022880 },
+      {    0.001297e-6,    23543.230504682,  3.063805171 },
+      {    0.001335e-6,     -266.607041722,  3.995764039 },
+      {    0.001376e-6,    10969.965257698,  5.152914309 },
+   /* 191, 200 */
+      {    0.001745e-6,   244287.600007027,  3.626395673 },
+      {    0.001649e-6,    31441.677569757,  1.952049260 },
+      {    0.001416e-6,     9225.539273283,  4.996408389 },
+      {    0.001238e-6,     4804.209275927,  5.503379738 },
+      {    0.001472e-6,     4590.910180489,  4.164913291 },
+      {    0.001169e-6,     6040.347246017,  5.841719038 },
+      {    0.001039e-6,     5540.085789459,  2.769753519 },
+      {    0.001004e-6,     -170.672870619,  0.755008103 },
+      {    0.001284e-6,    10575.406682942,  5.306538209 },
+      {    0.001278e-6,       71.812653151,  4.713486491 },
+   /* 201, 210 */
+      {    0.001321e-6,    18209.330263660,  2.624866359 },
+      {    0.001297e-6,    21228.392023546,  0.382603541 },
+      {    0.000954e-6,     6282.095528923,  0.882213514 },
+      {    0.001145e-6,     6058.731054289,  1.169483931 },
+      {    0.000979e-6,     5547.199336460,  5.448375984 },
+      {    0.000987e-6,    -6262.300454499,  2.656486959 },
+      {    0.001070e-6,  -154717.609887482,  1.827624012 },
+      {    0.000991e-6,     4701.116501708,  4.387001801 },
+      {    0.001155e-6,      -14.227094002,  3.042700750 },
+      {    0.001176e-6,      277.034993741,  3.335519004 },
+   /* 211, 220 */
+      {    0.000890e-6,    13916.019109642,  5.601498297 },
+      {    0.000884e-6,    -1551.045222648,  1.088831705 },
+      {    0.000876e-6,     5017.508371365,  3.969902609 },
+      {    0.000806e-6,    15110.466119866,  5.142876744 },
+      {    0.000773e-6,    -4136.910433516,  0.022067765 },
+      {    0.001077e-6,      175.166059800,  1.844913056 },
+      {    0.000954e-6,    -6284.056171060,  0.968480906 },
+      {    0.000737e-6,     5326.786694021,  4.923831588 },
+      {    0.000845e-6,     -433.711737877,  4.749245231 },
+      {    0.000819e-6,     8662.240323563,  5.991247817 },
+   /* 221, 230 */
+      {    0.000852e-6,      199.072001436,  2.189604979 },
+      {    0.000723e-6,    17256.631536341,  6.068719637 },
+      {    0.000940e-6,     6037.244203762,  6.197428148 },
+      {    0.000885e-6,    11712.955318231,  3.280414875 },
+      {    0.000706e-6,    12559.038152982,  2.824848947 },
+      {    0.000732e-6,     2379.164473572,  2.501813417 },
+      {    0.000764e-6,    -6127.655450557,  2.236346329 },
+      {    0.000908e-6,      131.541961686,  2.521257490 },
+      {    0.000907e-6,    35371.887265976,  3.370195967 },
+      {    0.000673e-6,     1066.495477190,  3.876512374 },
+   /* 231, 240 */
+      {    0.000814e-6,    17654.780539750,  4.627122566 },
+      {    0.000630e-6,       36.027866677,  0.156368499 },
+      {    0.000798e-6,      515.463871093,  5.151962502 },
+      {    0.000798e-6,      148.078724426,  5.909225055 },
+      {    0.000806e-6,      309.278322656,  6.054064447 },
+      {    0.000607e-6,      -39.617508346,  2.839021623 },
+      {    0.000601e-6,      412.371096874,  3.984225404 },
+      {    0.000646e-6,    11403.676995575,  3.852959484 },
+      {    0.000704e-6,    13521.751441591,  2.300991267 },
+      {    0.000603e-6,   -65147.619767937,  4.140083146 },
+   /* 241, 250 */
+      {    0.000609e-6,    10177.257679534,  0.437122327 },
+      {    0.000631e-6,     5767.611978898,  4.026532329 },
+      {    0.000576e-6,    11087.285125918,  4.760293101 },
+      {    0.000674e-6,    14945.316173554,  6.270510511 },
+      {    0.000726e-6,     5429.879468239,  6.039606892 },
+      {    0.000710e-6,    28766.924424484,  5.672617711 },
+      {    0.000647e-6,    11856.218651625,  3.397132627 },
+      {    0.000678e-6,    -5481.254918868,  6.249666675 },
+      {    0.000618e-6,    22003.914634870,  2.466427018 },
+      {    0.000738e-6,     6134.997125565,  2.242668890 },
+   /* 251, 260 */
+      {    0.000660e-6,      625.670192312,  5.864091907 },
+      {    0.000694e-6,     3496.032826134,  2.668309141 },
+      {    0.000531e-6,     6489.261398429,  1.681888780 },
+      {    0.000611e-6,  -143571.324284214,  2.424978312 },
+      {    0.000575e-6,    12043.574281889,  4.216492400 },
+      {    0.000553e-6,    12416.588502848,  4.772158039 },
+      {    0.000689e-6,     4686.889407707,  6.224271088 },
+      {    0.000495e-6,     7342.457780181,  3.817285811 },
+      {    0.000567e-6,     3634.621024518,  1.649264690 },
+      {    0.000515e-6,    18635.928454536,  3.945345892 },
+   /* 261, 270 */
+      {    0.000486e-6,     -323.505416657,  4.061673868 },
+      {    0.000662e-6,    25158.601719765,  1.794058369 },
+      {    0.000509e-6,      846.082834751,  3.053874588 },
+      {    0.000472e-6,   -12569.674818332,  5.112133338 },
+      {    0.000461e-6,     6179.983075773,  0.513669325 },
+      {    0.000641e-6,    83467.156352816,  3.210727723 },
+      {    0.000520e-6,    10344.295065386,  2.445597761 },
+      {    0.000493e-6,    18422.629359098,  1.676939306 },
+      {    0.000478e-6,     1265.567478626,  5.487314569 },
+      {    0.000472e-6,      -18.159247265,  1.999707589 },
+   /* 271, 280 */
+      {    0.000559e-6,    11190.377900137,  5.783236356 },
+      {    0.000494e-6,     9623.688276691,  3.022645053 },
+      {    0.000463e-6,     5739.157790895,  1.411223013 },
+      {    0.000432e-6,    16858.482532933,  1.179256434 },
+      {    0.000574e-6,    72140.628666286,  1.758191830 },
+      {    0.000484e-6,    17267.268201691,  3.290589143 },
+      {    0.000550e-6,     4907.302050146,  0.864024298 },
+      {    0.000399e-6,       14.977853527,  2.094441910 },
+      {    0.000491e-6,      224.344795702,  0.878372791 },
+      {    0.000432e-6,    20426.571092422,  6.003829241 },
+   /* 281, 290 */
+      {    0.000481e-6,     5749.452731634,  4.309591964 },
+      {    0.000480e-6,     5757.317038160,  1.142348571 },
+      {    0.000485e-6,     6702.560493867,  0.210580917 },
+      {    0.000426e-6,     6055.549660552,  4.274476529 },
+      {    0.000480e-6,     5959.570433334,  5.031351030 },
+      {    0.000466e-6,    12562.628581634,  4.959581597 },
+      {    0.000520e-6,    39302.096962196,  4.788002889 },
+      {    0.000458e-6,    12132.439962106,  1.880103788 },
+      {    0.000470e-6,    12029.347187887,  1.405611197 },
+      {    0.000416e-6,    -7477.522860216,  1.082356330 },
+   /* 291, 300 */
+      {    0.000449e-6,    11609.862544012,  4.179989585 },
+      {    0.000465e-6,    17253.041107690,  0.353496295 },
+      {    0.000362e-6,    -4535.059436924,  1.583849576 },
+      {    0.000383e-6,    21954.157609398,  3.747376371 },
+      {    0.000389e-6,       17.252277143,  1.395753179 },
+      {    0.000331e-6,    18052.929543158,  0.566790582 },
+      {    0.000430e-6,    13517.870106233,  0.685827538 },
+      {    0.000368e-6,    -5756.908003246,  0.731374317 },
+      {    0.000330e-6,    10557.594160824,  3.710043680 },
+      {    0.000332e-6,    20199.094959633,  1.652901407 },
+   /* 301, 310 */
+      {    0.000384e-6,    11933.367960670,  5.827781531 },
+      {    0.000387e-6,    10454.501386605,  2.541182564 },
+      {    0.000325e-6,    15671.081759407,  2.178850542 },
+      {    0.000318e-6,      138.517496871,  2.253253037 },
+      {    0.000305e-6,     9388.005909415,  0.578340206 },
+      {    0.000352e-6,     5749.861766548,  3.000297967 },
+      {    0.000311e-6,     6915.859589305,  1.693574249 },
+      {    0.000297e-6,    24072.921469776,  1.997249392 },
+      {    0.000363e-6,     -640.877607382,  5.071820966 },
+      {    0.000323e-6,    12592.450019783,  1.072262823 },
+   /* 311, 320 */
+      {    0.000341e-6,    12146.667056108,  4.700657997 },
+      {    0.000290e-6,     9779.108676125,  1.812320441 },
+      {    0.000342e-6,     6132.028180148,  4.322238614 },
+      {    0.000329e-6,     6268.848755990,  3.033827743 },
+      {    0.000374e-6,    17996.031168222,  3.388716544 },
+      {    0.000285e-6,     -533.214083444,  4.687313233 },
+      {    0.000338e-6,     6065.844601290,  0.877776108 },
+      {    0.000276e-6,       24.298513841,  0.770299429 },
+      {    0.000336e-6,    -2388.894020449,  5.353796034 },
+      {    0.000290e-6,     3097.883822726,  4.075291557 },
+   /* 321, 330 */
+      {    0.000318e-6,      709.933048357,  5.941207518 },
+      {    0.000271e-6,    13095.842665077,  3.208912203 },
+      {    0.000331e-6,     6073.708907816,  4.007881169 },
+      {    0.000292e-6,      742.990060533,  2.714333592 },
+      {    0.000362e-6,    29088.811415985,  3.215977013 },
+      {    0.000280e-6,    12359.966151546,  0.710872502 },
+      {    0.000267e-6,    10440.274292604,  4.730108488 },
+      {    0.000262e-6,      838.969287750,  1.327720272 },
+      {    0.000250e-6,    16496.361396202,  0.898769761 },
+      {    0.000325e-6,    20597.243963041,  0.180044365 },
+   /* 331, 340 */
+      {    0.000268e-6,     6148.010769956,  5.152666276 },
+      {    0.000284e-6,     5636.065016677,  5.655385808 },
+      {    0.000301e-6,     6080.822454817,  2.135396205 },
+      {    0.000294e-6,     -377.373607916,  3.708784168 },
+      {    0.000236e-6,     2118.763860378,  1.733578756 },
+      {    0.000234e-6,     5867.523359379,  5.575209112 },
+      {    0.000268e-6,  -226858.238553767,  0.069432392 },
+      {    0.000265e-6,   167283.761587465,  4.369302826 },
+      {    0.000280e-6,    28237.233459389,  5.304829118 },
+      {    0.000292e-6,    12345.739057544,  4.096094132 },
+   /* 341, 350 */
+      {    0.000223e-6,    19800.945956225,  3.069327406 },
+      {    0.000301e-6,    43232.306658416,  6.205311188 },
+      {    0.000264e-6,    18875.525869774,  1.417263408 },
+      {    0.000304e-6,    -1823.175188677,  3.409035232 },
+      {    0.000301e-6,      109.945688789,  0.510922054 },
+      {    0.000260e-6,      813.550283960,  2.389438934 },
+      {    0.000299e-6,   316428.228673312,  5.384595078 },
+      {    0.000211e-6,     5756.566278634,  3.789392838 },
+      {    0.000209e-6,     5750.203491159,  1.661943545 },
+      {    0.000240e-6,    12489.885628707,  5.684549045 },
+   /* 351, 360 */
+      {    0.000216e-6,     6303.851245484,  3.862942261 },
+      {    0.000203e-6,     1581.959348283,  5.549853589 },
+      {    0.000200e-6,     5642.198242609,  1.016115785 },
+      {    0.000197e-6,      -70.849445304,  4.690702525 },
+      {    0.000227e-6,     6287.008003254,  2.911891613 },
+      {    0.000197e-6,      533.623118358,  1.048982898 },
+      {    0.000205e-6,    -6279.485421340,  1.829362730 },
+      {    0.000209e-6,   -10988.808157535,  2.636140084 },
+      {    0.000208e-6,     -227.526189440,  4.127883842 },
+      {    0.000191e-6,      415.552490612,  4.401165650 },
+   /* 361, 370 */
+      {    0.000190e-6,    29296.615389579,  4.175658539 },
+      {    0.000264e-6,    66567.485864652,  4.601102551 },
+      {    0.000256e-6,    -3646.350377354,  0.506364778 },
+      {    0.000188e-6,    13119.721102825,  2.032195842 },
+      {    0.000185e-6,     -209.366942175,  4.694756586 },
+      {    0.000198e-6,    25934.124331089,  3.832703118 },
+      {    0.000195e-6,     4061.219215394,  3.308463427 },
+      {    0.000234e-6,     5113.487598583,  1.716090661 },
+      {    0.000188e-6,     1478.866574064,  5.686865780 },
+      {    0.000222e-6,    11823.161639450,  1.942386641 },
+   /* 371, 380 */
+      {    0.000181e-6,    10770.893256262,  1.999482059 },
+      {    0.000171e-6,     6546.159773364,  1.182807992 },
+      {    0.000206e-6,       70.328180442,  5.934076062 },
+      {    0.000169e-6,    20995.392966449,  2.169080622 },
+      {    0.000191e-6,    10660.686935042,  5.405515999 },
+      {    0.000228e-6,    33019.021112205,  4.656985514 },
+      {    0.000184e-6,    -4933.208440333,  3.327476868 },
+      {    0.000220e-6,     -135.625325010,  1.765430262 },
+      {    0.000166e-6,    23141.558382925,  3.454132746 },
+      {    0.000191e-6,     6144.558353121,  5.020393445 },
+   /* 381, 390 */
+      {    0.000180e-6,     6084.003848555,  0.602182191 },
+      {    0.000163e-6,    17782.732072784,  4.960593133 },
+      {    0.000225e-6,    16460.333529525,  2.596451817 },
+      {    0.000222e-6,     5905.702242076,  3.731990323 },
+      {    0.000204e-6,      227.476132789,  5.636192701 },
+      {    0.000159e-6,    16737.577236597,  3.600691544 },
+      {    0.000200e-6,     6805.653268085,  0.868220961 },
+      {    0.000187e-6,    11919.140866668,  2.629456641 },
+      {    0.000161e-6,      127.471796607,  2.862574720 },
+      {    0.000205e-6,     6286.666278643,  1.742882331 },
+   /* 391, 400 */
+      {    0.000189e-6,      153.778810485,  4.812372643 },
+      {    0.000168e-6,    16723.350142595,  0.027860588 },
+      {    0.000149e-6,    11720.068865232,  0.659721876 },
+      {    0.000189e-6,     5237.921013804,  5.245313000 },
+      {    0.000143e-6,     6709.674040867,  4.317625647 },
+      {    0.000146e-6,     4487.817406270,  4.815297007 },
+      {    0.000144e-6,     -664.756045130,  5.381366880 },
+      {    0.000175e-6,     5127.714692584,  4.728443327 },
+      {    0.000162e-6,     6254.626662524,  1.435132069 },
+      {    0.000187e-6,    47162.516354635,  1.354371923 },
+   /* 401, 410 */
+      {    0.000146e-6,    11080.171578918,  3.369695406 },
+      {    0.000180e-6,     -348.924420448,  2.490902145 },
+      {    0.000148e-6,      151.047669843,  3.799109588 },
+      {    0.000157e-6,     6197.248551160,  1.284375887 },
+      {    0.000167e-6,      146.594251718,  0.759969109 },
+      {    0.000133e-6,    -5331.357443741,  5.409701889 },
+      {    0.000154e-6,       95.979227218,  3.366890614 },
+      {    0.000148e-6,    -6418.140930027,  3.384104996 },
+      {    0.000128e-6,    -6525.804453965,  3.803419985 },
+      {    0.000130e-6,    11293.470674356,  0.939039445 },
+   /* 411, 420 */
+      {    0.000152e-6,    -5729.506447149,  0.734117523 },
+      {    0.000138e-6,      210.117701700,  2.564216078 },
+      {    0.000123e-6,     6066.595360816,  4.517099537 },
+      {    0.000140e-6,    18451.078546566,  0.642049130 },
+      {    0.000126e-6,    11300.584221356,  3.485280663 },
+      {    0.000119e-6,    10027.903195729,  3.217431161 },
+      {    0.000151e-6,     4274.518310832,  4.404359108 },
+      {    0.000117e-6,     6072.958148291,  0.366324650 },
+      {    0.000165e-6,    -7668.637425143,  4.298212528 },
+      {    0.000117e-6,    -6245.048177356,  5.379518958 },
+   /* 421, 430 */
+      {    0.000130e-6,    -5888.449964932,  4.527681115 },
+      {    0.000121e-6,     -543.918059096,  6.109429504 },
+      {    0.000162e-6,     9683.594581116,  5.720092446 },
+      {    0.000141e-6,     6219.339951688,  0.679068671 },
+      {    0.000118e-6,    22743.409379516,  4.881123092 },
+      {    0.000129e-6,     1692.165669502,  0.351407289 },
+      {    0.000126e-6,     5657.405657679,  5.146592349 },
+      {    0.000114e-6,      728.762966531,  0.520791814 },
+      {    0.000120e-6,       52.596639600,  0.948516300 },
+      {    0.000115e-6,       65.220371012,  3.504914846 },
+   /* 431, 440 */
+      {    0.000126e-6,     5881.403728234,  5.577502482 },
+      {    0.000158e-6,   163096.180360983,  2.957128968 },
+      {    0.000134e-6,    12341.806904281,  2.598576764 },
+      {    0.000151e-6,    16627.370915377,  3.985702050 },
+      {    0.000109e-6,     1368.660252845,  0.014730471 },
+      {    0.000131e-6,     6211.263196841,  0.085077024 },
+      {    0.000146e-6,     5792.741760812,  0.708426604 },
+      {    0.000146e-6,      -77.750543984,  3.121576600 },
+      {    0.000107e-6,     5341.013788022,  0.288231904 },
+      {    0.000138e-6,     6281.591377283,  2.797450317 },
+   /* 441, 450 */
+      {    0.000113e-6,    -6277.552925684,  2.788904128 },
+      {    0.000115e-6,     -525.758811831,  5.895222200 },
+      {    0.000138e-6,     6016.468808270,  6.096188999 },
+      {    0.000139e-6,    23539.707386333,  2.028195445 },
+      {    0.000146e-6,    -4176.041342449,  4.660008502 },
+      {    0.000107e-6,    16062.184526117,  4.066520001 },
+      {    0.000142e-6,    83783.548222473,  2.936315115 },
+      {    0.000128e-6,     9380.959672717,  3.223844306 },
+      {    0.000135e-6,     6205.325306007,  1.638054048 },
+      {    0.000101e-6,     2699.734819318,  5.481603249 },
+   /* 451, 460 */
+      {    0.000104e-6,     -568.821874027,  2.205734493 },
+      {    0.000103e-6,     6321.103522627,  2.440421099 },
+      {    0.000119e-6,     6321.208885629,  2.547496264 },
+      {    0.000138e-6,     1975.492545856,  2.314608466 },
+      {    0.000121e-6,      137.033024162,  4.539108237 },
+      {    0.000123e-6,    19402.796952817,  4.538074405 },
+      {    0.000119e-6,    22805.735565994,  2.869040566 },
+      {    0.000133e-6,    64471.991241142,  6.056405489 },
+      {    0.000129e-6,      -85.827298831,  2.540635083 },
+      {    0.000131e-6,    13613.804277336,  4.005732868 },
+   /* 461, 470 */
+      {    0.000104e-6,     9814.604100291,  1.959967212 },
+      {    0.000112e-6,    16097.679950283,  3.589026260 },
+      {    0.000123e-6,     2107.034507542,  1.728627253 },
+      {    0.000121e-6,    36949.230808424,  6.072332087 },
+      {    0.000108e-6,   -12539.853380183,  3.716133846 },
+      {    0.000113e-6,    -7875.671863624,  2.725771122 },
+      {    0.000109e-6,     4171.425536614,  4.033338079 },
+      {    0.000101e-6,     6247.911759770,  3.441347021 },
+      {    0.000113e-6,     7330.728427345,  0.656372122 },
+      {    0.000113e-6,    51092.726050855,  2.791483066 },
+   /* 471, 480 */
+      {    0.000106e-6,     5621.842923210,  1.815323326 },
+      {    0.000101e-6,      111.430161497,  5.711033677 },
+      {    0.000103e-6,      909.818733055,  2.812745443 },
+      {    0.000101e-6,     1790.642637886,  1.965746028 },
+
+   /* T */
+      {  102.156724e-6,     6283.075849991,  4.249032005 },
+      {    1.706807e-6,    12566.151699983,  4.205904248 },
+      {    0.269668e-6,      213.299095438,  3.400290479 },
+      {    0.265919e-6,      529.690965095,  5.836047367 },
+      {    0.210568e-6,       -3.523118349,  6.262738348 },
+      {    0.077996e-6,     5223.693919802,  4.670344204 },
+   /* 481, 490 */
+      {    0.054764e-6,     1577.343542448,  4.534800170 },
+      {    0.059146e-6,       26.298319800,  1.083044735 },
+      {    0.034420e-6,     -398.149003408,  5.980077351 },
+      {    0.032088e-6,    18849.227549974,  4.162913471 },
+      {    0.033595e-6,     5507.553238667,  5.980162321 },
+      {    0.029198e-6,     5856.477659115,  0.623811863 },
+      {    0.027764e-6,      155.420399434,  3.745318113 },
+      {    0.025190e-6,     5746.271337896,  2.980330535 },
+      {    0.022997e-6,     -796.298006816,  1.174411803 },
+      {    0.024976e-6,     5760.498431898,  2.467913690 },
+   /* 491, 500 */
+      {    0.021774e-6,      206.185548437,  3.854787540 },
+      {    0.017925e-6,     -775.522611324,  1.092065955 },
+      {    0.013794e-6,      426.598190876,  2.699831988 },
+      {    0.013276e-6,     6062.663207553,  5.845801920 },
+      {    0.011774e-6,    12036.460734888,  2.292832062 },
+      {    0.012869e-6,     6076.890301554,  5.333425680 },
+      {    0.012152e-6,     1059.381930189,  6.222874454 },
+      {    0.011081e-6,       -7.113547001,  5.154724984 },
+      {    0.010143e-6,     4694.002954708,  4.044013795 },
+      {    0.009357e-6,     5486.777843175,  3.416081409 },
+   /* 501, 510 */
+      {    0.010084e-6,      522.577418094,  0.749320262 },
+      {    0.008587e-6,    10977.078804699,  2.777152598 },
+      {    0.008628e-6,     6275.962302991,  4.562060226 },
+      {    0.008158e-6,     -220.412642439,  5.806891533 },
+      {    0.007746e-6,     2544.314419883,  1.603197066 },
+      {    0.007670e-6,     2146.165416475,  3.000200440 },
+      {    0.007098e-6,       74.781598567,  0.443725817 },
+      {    0.006180e-6,     -536.804512095,  1.302642751 },
+      {    0.005818e-6,     5088.628839767,  4.827723531 },
+      {    0.004945e-6,    -6286.598968340,  0.268305170 },
+   /* 511, 520 */
+      {    0.004774e-6,     1349.867409659,  5.808636673 },
+      {    0.004687e-6,     -242.728603974,  5.154890570 },
+      {    0.006089e-6,     1748.016413067,  4.403765209 },
+      {    0.005975e-6,    -1194.447010225,  2.583472591 },
+      {    0.004229e-6,      951.718406251,  0.931172179 },
+      {    0.005264e-6,      553.569402842,  2.336107252 },
+      {    0.003049e-6,     5643.178563677,  1.362634430 },
+      {    0.002974e-6,     6812.766815086,  1.583012668 },
+      {    0.003403e-6,    -2352.866153772,  2.552189886 },
+      {    0.003030e-6,      419.484643875,  5.286473844 },
+   /* 521, 530 */
+      {    0.003210e-6,       -7.046236698,  1.863796539 },
+      {    0.003058e-6,     9437.762934887,  4.226420633 },
+      {    0.002589e-6,    12352.852604545,  1.991935820 },
+      {    0.002927e-6,     5216.580372801,  2.319951253 },
+      {    0.002425e-6,     5230.807466803,  3.084752833 },
+      {    0.002656e-6,     3154.687084896,  2.487447866 },
+      {    0.002445e-6,    10447.387839604,  2.347139160 },
+      {    0.002990e-6,     4690.479836359,  6.235872050 },
+      {    0.002890e-6,     5863.591206116,  0.095197563 },
+      {    0.002498e-6,     6438.496249426,  2.994779800 },
+   /* 531, 540 */
+      {    0.001889e-6,     8031.092263058,  3.569003717 },
+      {    0.002567e-6,      801.820931124,  3.425611498 },
+      {    0.001803e-6,   -71430.695617928,  2.192295512 },
+      {    0.001782e-6,        3.932153263,  5.180433689 },
+      {    0.001694e-6,    -4705.732307544,  4.641779174 },
+      {    0.001704e-6,    -1592.596013633,  3.997097652 },
+      {    0.001735e-6,     5849.364112115,  0.417558428 },
+      {    0.001643e-6,     8429.241266467,  2.180619584 },
+      {    0.001680e-6,       38.133035638,  4.164529426 },
+      {    0.002045e-6,     7084.896781115,  0.526323854 },
+   /* 541, 550 */
+      {    0.001458e-6,     4292.330832950,  1.356098141 },
+      {    0.001437e-6,       20.355319399,  3.895439360 },
+      {    0.001738e-6,     6279.552731642,  0.087484036 },
+      {    0.001367e-6,    14143.495242431,  3.987576591 },
+      {    0.001344e-6,     7234.794256242,  0.090454338 },
+      {    0.001438e-6,    11499.656222793,  0.974387904 },
+      {    0.001257e-6,     6836.645252834,  1.509069366 },
+      {    0.001358e-6,    11513.883316794,  0.495572260 },
+      {    0.001628e-6,     7632.943259650,  4.968445721 },
+      {    0.001169e-6,      103.092774219,  2.838496795 },
+   /* 551, 560 */
+      {    0.001162e-6,     4164.311989613,  3.408387778 },
+      {    0.001092e-6,     6069.776754553,  3.617942651 },
+      {    0.001008e-6,    17789.845619785,  0.286350174 },
+      {    0.001008e-6,      639.897286314,  1.610762073 },
+      {    0.000918e-6,    10213.285546211,  5.532798067 },
+      {    0.001011e-6,    -6256.777530192,  0.661826484 },
+      {    0.000753e-6,    16730.463689596,  3.905030235 },
+      {    0.000737e-6,    11926.254413669,  4.641956361 },
+      {    0.000694e-6,     3340.612426700,  2.111120332 },
+      {    0.000701e-6,     3894.181829542,  2.760823491 },
+   /* 561, 570 */
+      {    0.000689e-6,     -135.065080035,  4.768800780 },
+      {    0.000700e-6,    13367.972631107,  5.760439898 },
+      {    0.000664e-6,     6040.347246017,  1.051215840 },
+      {    0.000654e-6,     5650.292110678,  4.911332503 },
+      {    0.000788e-6,     6681.224853400,  4.699648011 },
+      {    0.000628e-6,     5333.900241022,  5.024608847 },
+      {    0.000755e-6,     -110.206321219,  4.370971253 },
+      {    0.000628e-6,     6290.189396992,  3.660478857 },
+      {    0.000635e-6,    25132.303399966,  4.121051532 },
+      {    0.000534e-6,     5966.683980335,  1.173284524 },
+   /* 571, 580 */
+      {    0.000543e-6,     -433.711737877,  0.345585464 },
+      {    0.000517e-6,    -1990.745017041,  5.414571768 },
+      {    0.000504e-6,     5767.611978898,  2.328281115 },
+      {    0.000485e-6,     5753.384884897,  1.685874771 },
+      {    0.000463e-6,     7860.419392439,  5.297703006 },
+      {    0.000604e-6,      515.463871093,  0.591998446 },
+      {    0.000443e-6,    12168.002696575,  4.830881244 },
+      {    0.000570e-6,      199.072001436,  3.899190272 },
+      {    0.000465e-6,    10969.965257698,  0.476681802 },
+      {    0.000424e-6,    -7079.373856808,  1.112242763 },
+   /* 581, 590 */
+      {    0.000427e-6,      735.876513532,  1.994214480 },
+      {    0.000478e-6,    -6127.655450557,  3.778025483 },
+      {    0.000414e-6,    10973.555686350,  5.441088327 },
+      {    0.000512e-6,     1589.072895284,  0.107123853 },
+      {    0.000378e-6,    10984.192351700,  0.915087231 },
+      {    0.000402e-6,    11371.704689758,  4.107281715 },
+      {    0.000453e-6,     9917.696874510,  1.917490952 },
+      {    0.000395e-6,      149.563197135,  2.763124165 },
+      {    0.000371e-6,     5739.157790895,  3.112111866 },
+      {    0.000350e-6,    11790.629088659,  0.440639857 },
+   /* 591, 600 */
+      {    0.000356e-6,     6133.512652857,  5.444568842 },
+      {    0.000344e-6,      412.371096874,  5.676832684 },
+      {    0.000383e-6,      955.599741609,  5.559734846 },
+      {    0.000333e-6,     6496.374945429,  0.261537984 },
+      {    0.000340e-6,     6055.549660552,  5.975534987 },
+      {    0.000334e-6,     1066.495477190,  2.335063907 },
+      {    0.000399e-6,    11506.769769794,  5.321230910 },
+      {    0.000314e-6,    18319.536584880,  2.313312404 },
+      {    0.000424e-6,     1052.268383188,  1.211961766 },
+      {    0.000307e-6,       63.735898303,  3.169551388 },
+   /* 601, 610 */
+      {    0.000329e-6,       29.821438149,  6.106912080 },
+      {    0.000357e-6,     6309.374169791,  4.223760346 },
+      {    0.000312e-6,    -3738.761430108,  2.180556645 },
+      {    0.000301e-6,      309.278322656,  1.499984572 },
+      {    0.000268e-6,    12043.574281889,  2.447520648 },
+      {    0.000257e-6,    12491.370101415,  3.662331761 },
+      {    0.000290e-6,      625.670192312,  1.272834584 },
+      {    0.000256e-6,     5429.879468239,  1.913426912 },
+      {    0.000339e-6,     3496.032826134,  4.165930011 },
+      {    0.000283e-6,     3930.209696220,  4.325565754 },
+   /* 611, 620 */
+      {    0.000241e-6,    12528.018664345,  3.832324536 },
+      {    0.000304e-6,     4686.889407707,  1.612348468 },
+      {    0.000259e-6,    16200.772724501,  3.470173146 },
+      {    0.000238e-6,    12139.553509107,  1.147977842 },
+      {    0.000236e-6,     6172.869528772,  3.776271728 },
+      {    0.000296e-6,    -7058.598461315,  0.460368852 },
+      {    0.000306e-6,    10575.406682942,  0.554749016 },
+      {    0.000251e-6,    17298.182327326,  0.834332510 },
+      {    0.000290e-6,     4732.030627343,  4.759564091 },
+      {    0.000261e-6,     5884.926846583,  0.298259862 },
+   /* 621, 630 */
+      {    0.000249e-6,     5547.199336460,  3.749366406 },
+      {    0.000213e-6,    11712.955318231,  5.415666119 },
+      {    0.000223e-6,     4701.116501708,  2.703203558 },
+      {    0.000268e-6,     -640.877607382,  0.283670793 },
+      {    0.000209e-6,     5636.065016677,  1.238477199 },
+      {    0.000193e-6,    10177.257679534,  1.943251340 },
+      {    0.000182e-6,     6283.143160294,  2.456157599 },
+      {    0.000184e-6,     -227.526189440,  5.888038582 },
+      {    0.000182e-6,    -6283.008539689,  0.241332086 },
+      {    0.000228e-6,    -6284.056171060,  2.657323816 },
+   /* 631, 640 */
+      {    0.000166e-6,     7238.675591600,  5.930629110 },
+      {    0.000167e-6,     3097.883822726,  5.570955333 },
+      {    0.000159e-6,     -323.505416657,  5.786670700 },
+      {    0.000154e-6,    -4136.910433516,  1.517805532 },
+      {    0.000176e-6,    12029.347187887,  3.139266834 },
+      {    0.000167e-6,    12132.439962106,  3.556352289 },
+      {    0.000153e-6,      202.253395174,  1.463313961 },
+      {    0.000157e-6,    17267.268201691,  1.586837396 },
+      {    0.000142e-6,    83996.847317911,  0.022670115 },
+      {    0.000152e-6,    17260.154654690,  0.708528947 },
+   /* 641, 650 */
+      {    0.000144e-6,     6084.003848555,  5.187075177 },
+      {    0.000135e-6,     5756.566278634,  1.993229262 },
+      {    0.000134e-6,     5750.203491159,  3.457197134 },
+      {    0.000144e-6,     5326.786694021,  6.066193291 },
+      {    0.000160e-6,    11015.106477335,  1.710431974 },
+      {    0.000133e-6,     3634.621024518,  2.836451652 },
+      {    0.000134e-6,    18073.704938650,  5.453106665 },
+      {    0.000134e-6,     1162.474704408,  5.326898811 },
+      {    0.000128e-6,     5642.198242609,  2.511652591 },
+      {    0.000160e-6,      632.783739313,  5.628785365 },
+   /* 651, 660 */
+      {    0.000132e-6,    13916.019109642,  0.819294053 },
+      {    0.000122e-6,    14314.168113050,  5.677408071 },
+      {    0.000125e-6,    12359.966151546,  5.251984735 },
+      {    0.000121e-6,     5749.452731634,  2.210924603 },
+      {    0.000136e-6,     -245.831646229,  1.646502367 },
+      {    0.000120e-6,     5757.317038160,  3.240883049 },
+      {    0.000134e-6,    12146.667056108,  3.059480037 },
+      {    0.000137e-6,     6206.809778716,  1.867105418 },
+      {    0.000141e-6,    17253.041107690,  2.069217456 },
+      {    0.000129e-6,    -7477.522860216,  2.781469314 },
+   /* 661, 670 */
+      {    0.000116e-6,     5540.085789459,  4.281176991 },
+      {    0.000116e-6,     9779.108676125,  3.320925381 },
+      {    0.000129e-6,     5237.921013804,  3.497704076 },
+      {    0.000113e-6,     5959.570433334,  0.983210840 },
+      {    0.000122e-6,     6282.095528923,  2.674938860 },
+      {    0.000140e-6,      -11.045700264,  4.957936982 },
+      {    0.000108e-6,    23543.230504682,  1.390113589 },
+      {    0.000106e-6,   -12569.674818332,  0.429631317 },
+      {    0.000110e-6,     -266.607041722,  5.501340197 },
+      {    0.000115e-6,    12559.038152982,  4.691456618 },
+   /* 671, 680 */
+      {    0.000134e-6,    -2388.894020449,  0.577313584 },
+      {    0.000109e-6,    10440.274292604,  6.218148717 },
+      {    0.000102e-6,     -543.918059096,  1.477842615 },
+      {    0.000108e-6,    21228.392023546,  2.237753948 },
+      {    0.000101e-6,    -4535.059436924,  3.100492232 },
+      {    0.000103e-6,       76.266071276,  5.594294322 },
+      {    0.000104e-6,      949.175608970,  5.674287810 },
+      {    0.000101e-6,    13517.870106233,  2.196632348 },
+      {    0.000100e-6,    11933.367960670,  4.056084160 },
+
+   /* T^2 */
+      {    4.322990e-6,     6283.075849991,  2.642893748 },
+   /* 681, 690 */
+      {    0.406495e-6,        0.000000000,  4.712388980 },
+      {    0.122605e-6,    12566.151699983,  2.438140634 },
+      {    0.019476e-6,      213.299095438,  1.642186981 },
+      {    0.016916e-6,      529.690965095,  4.510959344 },
+      {    0.013374e-6,       -3.523118349,  1.502210314 },
+      {    0.008042e-6,       26.298319800,  0.478549024 },
+      {    0.007824e-6,      155.420399434,  5.254710405 },
+      {    0.004894e-6,     5746.271337896,  4.683210850 },
+      {    0.004875e-6,     5760.498431898,  0.759507698 },
+      {    0.004416e-6,     5223.693919802,  6.028853166 },
+   /* 691, 700 */
+      {    0.004088e-6,       -7.113547001,  0.060926389 },
+      {    0.004433e-6,    77713.771467920,  3.627734103 },
+      {    0.003277e-6,    18849.227549974,  2.327912542 },
+      {    0.002703e-6,     6062.663207553,  1.271941729 },
+      {    0.003435e-6,     -775.522611324,  0.747446224 },
+      {    0.002618e-6,     6076.890301554,  3.633715689 },
+      {    0.003146e-6,      206.185548437,  5.647874613 },
+      {    0.002544e-6,     1577.343542448,  6.232904270 },
+      {    0.002218e-6,     -220.412642439,  1.309509946 },
+      {    0.002197e-6,     5856.477659115,  2.407212349 },
+   /* 701, 710 */
+      {    0.002897e-6,     5753.384884897,  5.863842246 },
+      {    0.001766e-6,      426.598190876,  0.754113147 },
+      {    0.001738e-6,     -796.298006816,  2.714942671 },
+      {    0.001695e-6,      522.577418094,  2.629369842 },
+      {    0.001584e-6,     5507.553238667,  1.341138229 },
+      {    0.001503e-6,     -242.728603974,  0.377699736 },
+      {    0.001552e-6,     -536.804512095,  2.904684667 },
+      {    0.001370e-6,     -398.149003408,  1.265599125 },
+      {    0.001889e-6,    -5573.142801634,  4.413514859 },
+      {    0.001722e-6,     6069.776754553,  2.445966339 },
+   /* 711, 720 */
+      {    0.001124e-6,     1059.381930189,  5.041799657 },
+      {    0.001258e-6,      553.569402842,  3.849557278 },
+      {    0.000831e-6,      951.718406251,  2.471094709 },
+      {    0.000767e-6,     4694.002954708,  5.363125422 },
+      {    0.000756e-6,     1349.867409659,  1.046195744 },
+      {    0.000775e-6,      -11.045700264,  0.245548001 },
+      {    0.000597e-6,     2146.165416475,  4.543268798 },
+      {    0.000568e-6,     5216.580372801,  4.178853144 },
+      {    0.000711e-6,     1748.016413067,  5.934271972 },
+      {    0.000499e-6,    12036.460734888,  0.624434410 },
+   /* 721, 730 */
+      {    0.000671e-6,    -1194.447010225,  4.136047594 },
+      {    0.000488e-6,     5849.364112115,  2.209679987 },
+      {    0.000621e-6,     6438.496249426,  4.518860804 },
+      {    0.000495e-6,    -6286.598968340,  1.868201275 },
+      {    0.000456e-6,     5230.807466803,  1.271231591 },
+      {    0.000451e-6,     5088.628839767,  0.084060889 },
+      {    0.000435e-6,     5643.178563677,  3.324456609 },
+      {    0.000387e-6,    10977.078804699,  4.052488477 },
+      {    0.000547e-6,   161000.685737473,  2.841633844 },
+      {    0.000522e-6,     3154.687084896,  2.171979966 },
+   /* 731, 740 */
+      {    0.000375e-6,     5486.777843175,  4.983027306 },
+      {    0.000421e-6,     5863.591206116,  4.546432249 },
+      {    0.000439e-6,     7084.896781115,  0.522967921 },
+      {    0.000309e-6,     2544.314419883,  3.172606705 },
+      {    0.000347e-6,     4690.479836359,  1.479586566 },
+      {    0.000317e-6,      801.820931124,  3.553088096 },
+      {    0.000262e-6,      419.484643875,  0.606635550 },
+      {    0.000248e-6,     6836.645252834,  3.014082064 },
+      {    0.000245e-6,    -1592.596013633,  5.519526220 },
+      {    0.000225e-6,     4292.330832950,  2.877956536 },
+   /* 741, 750 */
+      {    0.000214e-6,     7234.794256242,  1.605227587 },
+      {    0.000205e-6,     5767.611978898,  0.625804796 },
+      {    0.000180e-6,    10447.387839604,  3.499954526 },
+      {    0.000229e-6,      199.072001436,  5.632304604 },
+      {    0.000214e-6,      639.897286314,  5.960227667 },
+      {    0.000175e-6,     -433.711737877,  2.162417992 },
+      {    0.000209e-6,      515.463871093,  2.322150893 },
+      {    0.000173e-6,     6040.347246017,  2.556183691 },
+      {    0.000184e-6,     6309.374169791,  4.732296790 },
+      {    0.000227e-6,   149854.400134205,  5.385812217 },
+   /* 751, 760 */
+      {    0.000154e-6,     8031.092263058,  5.120720920 },
+      {    0.000151e-6,     5739.157790895,  4.815000443 },
+      {    0.000197e-6,     7632.943259650,  0.222827271 },
+      {    0.000197e-6,       74.781598567,  3.910456770 },
+      {    0.000138e-6,     6055.549660552,  1.397484253 },
+      {    0.000149e-6,    -6127.655450557,  5.333727496 },
+      {    0.000137e-6,     3894.181829542,  4.281749907 },
+      {    0.000135e-6,     9437.762934887,  5.979971885 },
+      {    0.000139e-6,    -2352.866153772,  4.715630782 },
+      {    0.000142e-6,     6812.766815086,  0.513330157 },
+   /* 761, 770 */
+      {    0.000120e-6,    -4705.732307544,  0.194160689 },
+      {    0.000131e-6,   -71430.695617928,  0.000379226 },
+      {    0.000124e-6,     6279.552731642,  2.122264908 },
+      {    0.000108e-6,    -6256.777530192,  0.883445696 },
+
+   /* T^3 */
+      {    0.143388e-6,     6283.075849991,  1.131453581 },
+      {    0.006671e-6,    12566.151699983,  0.775148887 },
+      {    0.001480e-6,      155.420399434,  0.480016880 },
+      {    0.000934e-6,      213.299095438,  6.144453084 },
+      {    0.000795e-6,      529.690965095,  2.941595619 },
+      {    0.000673e-6,     5746.271337896,  0.120415406 },
+   /* 771, 780 */
+      {    0.000672e-6,     5760.498431898,  5.317009738 },
+      {    0.000389e-6,     -220.412642439,  3.090323467 },
+      {    0.000373e-6,     6062.663207553,  3.003551964 },
+      {    0.000360e-6,     6076.890301554,  1.918913041 },
+      {    0.000316e-6,      -21.340641002,  5.545798121 },
+      {    0.000315e-6,     -242.728603974,  1.884932563 },
+      {    0.000278e-6,      206.185548437,  1.266254859 },
+      {    0.000238e-6,     -536.804512095,  4.532664830 },
+      {    0.000185e-6,      522.577418094,  4.578313856 },
+      {    0.000245e-6,    18849.227549974,  0.587467082 },
+   /* 781, 787 */
+      {    0.000180e-6,      426.598190876,  5.151178553 },
+      {    0.000200e-6,      553.569402842,  5.355983739 },
+      {    0.000141e-6,     5223.693919802,  1.336556009 },
+      {    0.000104e-6,     5856.477659115,  4.239842759 },
+
+   /* T^4 */
+      {    0.003826e-6,     6283.075849991,  5.705257275 },
+      {    0.000303e-6,    12566.151699983,  5.407132842 },
+      {    0.000209e-6,      155.420399434,  1.989815753 }
+   };
+
+
+/* Time since J2000.0 in Julian millennia. */
+   t = ((date1 - DJ00) + date2) / DJM;
+
+/* ================= */
+/* Topocentric terms */
+/* ================= */
+
+/* Convert UT to local solar time in radians. */
+   tsol = fmod(ut, 1.0) * D2PI + elong;
+
+/* FUNDAMENTAL ARGUMENTS:  Simon et al. 1994. */
+
+/* Combine time argument (millennia) with deg/arcsec factor. */
+   w = t / 3600.0;
+
+/* Sun Mean Longitude. */
+   elsun = fmod(280.46645683 + 1296027711.03429 * w, 360.0) * DD2R;
+
+/* Sun Mean Anomaly. */
+   emsun = fmod(357.52910918 + 1295965810.481 * w, 360.0) * DD2R;
+
+/* Mean Elongation of Moon from Sun. */
+   d = fmod(297.85019547 + 16029616012.090 * w, 360.0) * DD2R;
+
+/* Mean Longitude of Jupiter. */
+   elj = fmod(34.35151874 + 109306899.89453 * w, 360.0) * DD2R;
+
+/* Mean Longitude of Saturn. */
+   els = fmod(50.07744430 + 44046398.47038 * w, 360.0) * DD2R;
+
+/* TOPOCENTRIC TERMS:  Moyer 1981 and Murray 1983. */
+   wt =   +  0.00029e-10 * u * sin(tsol + elsun - els)
+          +  0.00100e-10 * u * sin(tsol - 2.0 * emsun)
+          +  0.00133e-10 * u * sin(tsol - d)
+          +  0.00133e-10 * u * sin(tsol + elsun - elj)
+          -  0.00229e-10 * u * sin(tsol + 2.0 * elsun + emsun)
+          -  0.02200e-10 * v * cos(elsun + emsun)
+          +  0.05312e-10 * u * sin(tsol - emsun)
+          -  0.13677e-10 * u * sin(tsol + 2.0 * elsun)
+          -  1.31840e-10 * v * cos(elsun)
+          +  3.17679e-10 * u * sin(tsol);
+
+/* ===================== */
+/* Fairhead et al. model */
+/* ===================== */
+
+/* T**0 */
+   w0 = 0;
+   for (j = 473; j >= 0; j--) {
+      w0 += fairhd[j][0] * sin(fairhd[j][1] * t + fairhd[j][2]);
+   }
+
+/* T**1 */
+   w1 = 0;
+   for (j = 678; j >= 474; j--) {
+      w1 += fairhd[j][0] * sin(fairhd[j][1] * t + fairhd[j][2]);
+   }
+
+/* T**2 */
+   w2 = 0;
+   for (j = 763; j >= 679; j--) {
+      w2 += fairhd[j][0] * sin(fairhd[j][1] * t + fairhd[j][2]);
+   }
+
+/* T**3 */
+   w3 = 0;
+   for (j = 783; j >= 764; j--) {
+      w3 += fairhd[j][0] * sin(fairhd[j][1] * t + fairhd[j][2]);
+   }
+
+/* T**4 */
+   w4 = 0;
+   for (j = 786; j >= 784; j--) {
+      w4 += fairhd[j][0] * sin(fairhd[j][1] * t + fairhd[j][2]);
+   }
+
+/* Multiply by powers of T and combine. */
+   wf = t * (t * (t * (t * w4 + w3) + w2) + w1) + w0;
+
+/* Adjustments to use JPL planetary masses instead of IAU. */
+   wj =   0.00065e-6 * sin(6069.776754 * t + 4.021194) +
+          0.00033e-6 * sin( 213.299095 * t + 5.543132) +
+        (-0.00196e-6 * sin(6208.294251 * t + 5.696701)) +
+        (-0.00173e-6 * sin(  74.781599 * t + 2.435900)) +
+          0.03638e-6 * t * t;
+
+/* ============ */
+/* Final result */
+/* ============ */
+
+/* TDB-TT in seconds. */
+   w = wt + wf + wj;
+
+   return w;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+#include <string.h>
+
+int iauDtf2d(const char *scale, int iy, int im, int id,
+             int ihr, int imn, double sec, double *d1, double *d2)
+/*
+**  - - - - - - - - -
+**   i a u D t f 2 d
+**  - - - - - - - - -
+**
+**  Encode date and time fields into 2-part Julian Date (or in the case
+**  of UTC a quasi-JD form that includes special provision for leap
+**  seconds).
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     scale     char[]  time scale ID (Note 1)
+**     iy,im,id  int     year, month, day in Gregorian calendar (Note 2)
+**     ihr,imn   int     hour, minute
+**     sec       double  seconds
+**
+**  Returned:
+**     d1,d2     double  2-part Julian Date (Notes 3,4)
+**
+**  Returned (function value):
+**               int     status: +3 = both of next two
+**                               +2 = time is after end of day (Note 5)
+**                               +1 = dubious year (Note 6)
+**                                0 = OK
+**                               -1 = bad year
+**                               -2 = bad month
+**                               -3 = bad day
+**                               -4 = bad hour
+**                               -5 = bad minute
+**                               -6 = bad second (<0)
+**
+**  Notes:
+**
+**  1) scale identifies the time scale.  Only the value "UTC" (in upper
+**     case) is significant, and enables handling of leap seconds (see
+**     Note 4).
+**
+**  2) For calendar conventions and limitations, see iauCal2jd.
+**
+**  3) The sum of the results, d1+d2, is Julian Date, where normally d1
+**     is the Julian Day Number and d2 is the fraction of a day.  In the
+**     case of UTC, where the use of JD is problematical, special
+**     conventions apply:  see the next note.
+**
+**  4) JD cannot unambiguously represent UTC during a leap second unless
+**     special measures are taken.  The SOFA internal convention is that
+**     the quasi-JD day represents UTC days whether the length is 86399,
+**     86400 or 86401 SI seconds.
+**
+**  5) The warning status "time is after end of day" usually means that
+**     the sec argument is greater than 60.0.  However, in a day ending
+**     in a leap second the limit changes to 61.0 (or 59.0 in the case
+**     of a negative leap second).
+**
+**  6) The warning status "dubious year" flags UTCs that predate the
+**     introduction of the time scale and that are too far in the future
+**     to be trusted.  See iauDat for further details.
+**
+**  7) Only in the case of continuous and regular time scales (TAI, TT,
+**     TCG, TCB and TDB) is the result d1+d2 a Julian Date, strictly
+**     speaking.  In the other cases (UT1 and UTC) the result must be
+**     used with circumspection;  in particular the difference between
+**     two such results cannot be interpreted as a precise time
+**     interval.
+**
+**  Called:
+**     iauCal2jd    Gregorian calendar to JD
+**     iauDat       delta(AT) = TAI-UTC
+**     iauJd2cal    JD to Gregorian calendar
+**
+**  This revision:  2012 February 12
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   int js, iy2, im2, id2;
+   double dj, w, day, seclim, dat1, dat2, ddt, time;
+
+
+/* Today's Julian Day Number. */
+   js = iauCal2jd(iy, im, id, &dj, &w);
+   if ( js ) return js;
+   dj += w;
+
+/* Day length and final minute length in seconds (provisional). */
+   day = DAYSEC;
+   seclim = 60;
+
+/* Deal with the UTC leap second case. */
+   if ( ! strcmp(scale,"UTC") ) {
+
+   /* TAI-UTC today. */
+      js = iauDat(iy, im, id, 0.0, &dat1);
+      if ( js < 0 ) return js;
+
+   /* TAI-UTC tomorrow. */
+      js = iauJd2cal ( dj, 1.0, &iy2, &im2, &id2, &w);
+      if ( js ) return js;
+      js = iauDat(iy2, im2, id2, 0.0, &dat2);
+      if ( js < 0 ) return js;
+
+   /* The change in TAI-UTC (seconds). */
+      ddt = dat2 - dat1;
+
+   /* If leap second day, correct the day and final minute lengths. */
+      if ( fabs(ddt) > 0.5 ) {
+         day += ddt;
+         if ( ihr == 23 && imn == 59 ) seclim += ddt;
+      }
+   }
+
+/* Validate the time. */
+   if ( ihr >= 0 && ihr <= 23 ) {
+      if ( imn >= 0 && imn <= 59 ) {
+         if ( sec >= 0 ) {
+            if ( sec >= seclim ) {
+               js += 2;
+            }
+         } else {
+            js = -6;
+         }
+      } else {
+         js = -5;
+      }
+   } else {
+      js = -4;
+   }
+   if ( js < 0 ) return js;
+
+/* The time in days. */
+   time  = ( 60.0 * ( (double) ( 60 * ihr + imn ) ) + sec ) / day;
+
+/* Return the date and time. */
+   *d1 = dj;
+   *d2 = time;
+
+/* Status. */
+   return js;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofa.h"
+
+double iauEe00(double date1, double date2, double epsa, double dpsi)
+/*
+**  - - - - - - - -
+**   i a u E e 0 0
+**  - - - - - - - -
+**
+**  The equation of the equinoxes, compatible with IAU 2000 resolutions,
+**  given the nutation in longitude and the mean obliquity.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  canonical model.
+**
+**  Given:
+**     date1,date2  double    TT as a 2-part Julian Date (Note 1)
+**     epsa         double    mean obliquity (Note 2)
+**     dpsi         double    nutation in longitude (Note 3)
+**
+**  Returned (function value):
+**                  double    equation of the equinoxes (Note 4)
+**
+**  Notes:
+**
+**  1) The TT date date1+date2 is a Julian Date, apportioned in any
+**     convenient way between the two arguments.  For example,
+**     JD(TT)=2450123.7 could be expressed in any of these ways,
+**     among others:
+**
+**            date1          date2
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in
+**     cases where the loss of several decimal digits of resolution
+**     is acceptable.  The J2000 method is best matched to the way
+**     the argument is handled internally and will deliver the
+**     optimum resolution.  The MJD method and the date & time methods
+**     are both good compromises between resolution and convenience.
+**
+**  2) The obliquity, in radians, is mean of date.
+**
+**  3) The result, which is in radians, operates in the following sense:
+**
+**        Greenwich apparent ST = GMST + equation of the equinoxes
+**
+**  4) The result is compatible with the IAU 2000 resolutions.  For
+**     further details, see IERS Conventions 2003 and Capitaine et al.
+**     (2002).
+**
+**  Called:
+**     iauEect00    equation of the equinoxes complementary terms
+**
+**  References:
+**
+**     Capitaine, N., Wallace, P.T. and McCarthy, D.D., "Expressions to
+**     implement the IAU 2000 definition of UT1", Astronomy &
+**     Astrophysics, 406, 1135-1149 (2003)
+**
+**     McCarthy, D. D., Petit, G. (eds.), IERS Conventions (2003),
+**     IERS Technical Note No. 32, BKG (2004)
+**
+**  This revision:  2008 May 16
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double ee;
+
+
+/* Equation of the equinoxes. */
+   ee = dpsi * cos(epsa) + iauEect00(date1, date2);
+
+   return ee;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofa.h"
+
+double iauEe00a(double date1, double date2)
+/*
+**  - - - - - - - - -
+**   i a u E e 0 0 a
+**  - - - - - - - - -
+**
+**  Equation of the equinoxes, compatible with IAU 2000 resolutions.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     date1,date2  double    TT as a 2-part Julian Date (Note 1)
+**
+**  Returned (function value):
+**                  double    equation of the equinoxes (Note 2)
+**
+**  Notes:
+**
+**  1) The TT date date1+date2 is a Julian Date, apportioned in any
+**     convenient way between the two arguments.  For example,
+**     JD(TT)=2450123.7 could be expressed in any of these ways,
+**     among others:
+**
+**            date1          date2
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in
+**     cases where the loss of several decimal digits of resolution
+**     is acceptable.  The J2000 method is best matched to the way
+**     the argument is handled internally and will deliver the
+**     optimum resolution.  The MJD method and the date & time methods
+**     are both good compromises between resolution and convenience.
+**
+**  2) The result, which is in radians, operates in the following sense:
+**
+**        Greenwich apparent ST = GMST + equation of the equinoxes
+**
+**  3) The result is compatible with the IAU 2000 resolutions.  For
+**     further details, see IERS Conventions 2003 and Capitaine et al.
+**     (2002).
+**
+**  Called:
+**     iauPr00      IAU 2000 precession adjustments
+**     iauObl80     mean obliquity, IAU 1980
+**     iauNut00a    nutation, IAU 2000A
+**     iauEe00      equation of the equinoxes, IAU 2000
+**
+**  References:
+**
+**     Capitaine, N., Wallace, P.T. and McCarthy, D.D., "Expressions to
+**     implement the IAU 2000 definition of UT1", Astronomy &
+**     Astrophysics, 406, 1135-1149 (2003).
+**
+**     McCarthy, D. D., Petit, G. (eds.), IERS Conventions (2003),
+**     IERS Technical Note No. 32, BKG (2004).
+**
+**  This revision:  2008 May 16
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double dpsipr, depspr, epsa, dpsi, deps, ee;
+
+
+/* IAU 2000 precession-rate adjustments. */
+   iauPr00(date1, date2, &dpsipr, &depspr);
+
+/* Mean obliquity, consistent with IAU 2000 precession-nutation. */
+   epsa = iauObl80(date1, date2) + depspr;
+
+/* Nutation in longitude. */
+   iauNut00a(date1, date2, &dpsi, &deps);
+
+/* Equation of the equinoxes. */
+   ee = iauEe00(date1, date2, epsa, dpsi);
+
+   return ee;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofa.h"
+
+double iauEe00b(double date1, double date2)
+/*
+**  - - - - - - - - -
+**   i a u E e 0 0 b
+**  - - - - - - - - -
+**
+**  Equation of the equinoxes, compatible with IAU 2000 resolutions but
+**  using the truncated nutation model IAU 2000B.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     date1,date2  double    TT as a 2-part Julian Date (Note 1)
+**
+**  Returned (function value):
+**                  double    equation of the equinoxes (Note 2)
+**
+**  Notes:
+**
+**  1) The TT date date1+date2 is a Julian Date, apportioned in any
+**     convenient way between the two arguments.  For example,
+**     JD(TT)=2450123.7 could be expressed in any of these ways,
+**     among others:
+**
+**            date1          date2
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in
+**     cases where the loss of several decimal digits of resolution
+**     is acceptable.  The J2000 method is best matched to the way
+**     the argument is handled internally and will deliver the
+**     optimum resolution.  The MJD method and the date & time methods
+**     are both good compromises between resolution and convenience.
+**
+**  2) The result, which is in radians, operates in the following sense:
+**
+**        Greenwich apparent ST = GMST + equation of the equinoxes
+**
+**  3) The result is compatible with the IAU 2000 resolutions except
+**     that accuracy has been compromised for the sake of speed.  For
+**     further details, see McCarthy & Luzum (2001), IERS Conventions
+**     2003 and Capitaine et al. (2003).
+**
+**  Called:
+**     iauPr00      IAU 2000 precession adjustments
+**     iauObl80     mean obliquity, IAU 1980
+**     iauNut00b    nutation, IAU 2000B
+**     iauEe00      equation of the equinoxes, IAU 2000
+**
+**  References:
+**
+**     Capitaine, N., Wallace, P.T. and McCarthy, D.D., "Expressions to
+**     implement the IAU 2000 definition of UT1", Astronomy &
+**     Astrophysics, 406, 1135-1149 (2003)
+**
+**     McCarthy, D.D. & Luzum, B.J., "An abridged model of the
+**     precession-nutation of the celestial pole", Celestial Mechanics &
+**     Dynamical Astronomy, 85, 37-49 (2003)
+**
+**     McCarthy, D. D., Petit, G. (eds.), IERS Conventions (2003),
+**     IERS Technical Note No. 32, BKG (2004)
+**
+**  This revision:  2008 May 18
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double dpsipr, depspr, epsa, dpsi, deps, ee;
+
+
+/* IAU 2000 precession-rate adjustments. */
+   iauPr00(date1, date2, &dpsipr, &depspr);
+
+/* Mean obliquity, consistent with IAU 2000 precession-nutation. */
+   epsa = iauObl80(date1, date2) + depspr;
+
+/* Nutation in longitude. */
+   iauNut00b(date1, date2, &dpsi, &deps);
+
+/* Equation of the equinoxes. */
+   ee = iauEe00(date1, date2, epsa, dpsi);
+
+   return ee;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofa.h"
+
+double iauEe06a(double date1, double date2)
+/*
+**  - - - - - - - - -
+**   i a u E e 0 6 a
+**  - - - - - - - - -
+**
+**  Equation of the equinoxes, compatible with IAU 2000 resolutions and
+**  IAU 2006/2000A precession-nutation.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     date1,date2  double    TT as a 2-part Julian Date (Note 1)
+**
+**  Returned (function value):
+**                  double    equation of the equinoxes (Note 2)
+**
+**  Notes:
+**
+**  1) The TT date date1+date2 is a Julian Date, apportioned in any
+**     convenient way between the two arguments.  For example,
+**     JD(TT)=2450123.7 could be expressed in any of these ways,
+**     among others:
+**
+**            date1          date2
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in
+**     cases where the loss of several decimal digits of resolution
+**     is acceptable.  The J2000 method is best matched to the way
+**     the argument is handled internally and will deliver the
+**     optimum resolution.  The MJD method and the date & time methods
+**     are both good compromises between resolution and convenience.
+**
+**  2) The result, which is in radians, operates in the following sense:
+**
+**        Greenwich apparent ST = GMST + equation of the equinoxes
+**
+**  Called:
+**     iauAnpm      normalize angle into range +/- pi
+**     iauGst06a    Greenwich apparent sidereal time, IAU 2006/2000A
+**     iauGmst06    Greenwich mean sidereal time, IAU 2006
+**
+**  Reference:
+**
+**     McCarthy, D. D., Petit, G. (eds.), 2004, IERS Conventions (2003),
+**     IERS Technical Note No. 32, BKG
+**
+**  This revision:  2008 May 18
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double gst06a, gmst06, ee;
+
+
+/* Apparent and mean sidereal times. */
+   gst06a = iauGst06a(0.0, 0.0, date1, date2);
+   gmst06 = iauGmst06(0.0, 0.0, date1, date2);
+
+/* Equation of the equinoxes. */
+   ee  = iauAnpm(gst06a - gmst06);
+
+   return ee;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+double iauEect00(double date1, double date2)
+/*
+**  - - - - - - - - - -
+**   i a u E e c t 0 0
+**  - - - - - - - - - -
+**
+**  Equation of the equinoxes complementary terms, consistent with
+**  IAU 2000 resolutions.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  canonical model.
+**
+**  Given:
+**     date1,date2  double   TT as a 2-part Julian Date (Note 1)
+**
+**  Returned (function value):
+**                  double   complementary terms (Note 2)
+**
+**  Notes:
+**
+**  1) The TT date date1+date2 is a Julian Date, apportioned in any
+**     convenient way between the two arguments.  For example,
+**     JD(TT)=2450123.7 could be expressed in any of these ways,
+**     among others:
+**
+**            date1          date2
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in
+**     cases where the loss of several decimal digits of resolution
+**     is acceptable.  The J2000 method is best matched to the way
+**     the argument is handled internally and will deliver the
+**     optimum resolution.  The MJD method and the date & time methods
+**     are both good compromises between resolution and convenience.
+**
+**  2) The "complementary terms" are part of the equation of the
+**     equinoxes (EE), classically the difference between apparent and
+**     mean Sidereal Time:
+**
+**        GAST = GMST + EE
+**
+**     with:
+**
+**        EE = dpsi * cos(eps)
+**
+**     where dpsi is the nutation in longitude and eps is the obliquity
+**     of date.  However, if the rotation of the Earth were constant in
+**     an inertial frame the classical formulation would lead to
+**     apparent irregularities in the UT1 timescale traceable to side-
+**     effects of precession-nutation.  In order to eliminate these
+**     effects from UT1, "complementary terms" were introduced in 1994
+**     (IAU, 1994) and took effect from 1997 (Capitaine and Gontier,
+**     1993):
+**
+**        GAST = GMST + CT + EE
+**
+**     By convention, the complementary terms are included as part of
+**     the equation of the equinoxes rather than as part of the mean
+**     Sidereal Time.  This slightly compromises the "geometrical"
+**     interpretation of mean sidereal time but is otherwise
+**     inconsequential.
+**
+**     The present function computes CT in the above expression,
+**     compatible with IAU 2000 resolutions (Capitaine et al., 2002, and
+**     IERS Conventions 2003).
+**
+**  Called:
+**     iauFal03     mean anomaly of the Moon
+**     iauFalp03    mean anomaly of the Sun
+**     iauFaf03     mean argument of the latitude of the Moon
+**     iauFad03     mean elongation of the Moon from the Sun
+**     iauFaom03    mean longitude of the Moon's ascending node
+**     iauFave03    mean longitude of Venus
+**     iauFae03     mean longitude of Earth
+**     iauFapa03    general accumulated precession in longitude
+**
+**  References:
+**
+**     Capitaine, N. & Gontier, A.-M., Astron. Astrophys., 275,
+**     645-650 (1993)
+**
+**     Capitaine, N., Wallace, P.T. and McCarthy, D.D., "Expressions to
+**     implement the IAU 2000 definition of UT1", Astronomy &
+**     Astrophysics, 406, 1135-1149 (2003)
+**
+**     IAU Resolution C7, Recommendation 3 (1994)
+**
+**     McCarthy, D. D., Petit, G. (eds.), IERS Conventions (2003),
+**     IERS Technical Note No. 32, BKG (2004)
+**
+**  This revision:  2009 December 17
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+/* Time since J2000.0, in Julian centuries */
+   double t;
+
+/* Miscellaneous */
+   int i, j;
+   double a, s0, s1;
+
+/* Fundamental arguments */
+   double fa[14];
+
+/* Returned value. */
+   double eect;
+
+/* ----------------------------------------- */
+/* The series for the EE complementary terms */
+/* ----------------------------------------- */
+
+   typedef struct {
+      int nfa[8];      /* coefficients of l,l',F,D,Om,LVe,LE,pA */
+      double s, c;     /* sine and cosine coefficients */
+   } TERM;
+
+/* Terms of order t^0 */
+   static const TERM e0[] = {
+
+   /* 1-10 */
+      {{ 0,  0,  0,  0,  1,  0,  0,  0}, 2640.96e-6, -0.39e-6 },
+      {{ 0,  0,  0,  0,  2,  0,  0,  0},   63.52e-6, -0.02e-6 },
+      {{ 0,  0,  2, -2,  3,  0,  0,  0},   11.75e-6,  0.01e-6 },
+      {{ 0,  0,  2, -2,  1,  0,  0,  0},   11.21e-6,  0.01e-6 },
+      {{ 0,  0,  2, -2,  2,  0,  0,  0},   -4.55e-6,  0.00e-6 },
+      {{ 0,  0,  2,  0,  3,  0,  0,  0},    2.02e-6,  0.00e-6 },
+      {{ 0,  0,  2,  0,  1,  0,  0,  0},    1.98e-6,  0.00e-6 },
+      {{ 0,  0,  0,  0,  3,  0,  0,  0},   -1.72e-6,  0.00e-6 },
+      {{ 0,  1,  0,  0,  1,  0,  0,  0},   -1.41e-6, -0.01e-6 },
+      {{ 0,  1,  0,  0, -1,  0,  0,  0},   -1.26e-6, -0.01e-6 },
+
+   /* 11-20 */
+      {{ 1,  0,  0,  0, -1,  0,  0,  0},   -0.63e-6,  0.00e-6 },
+      {{ 1,  0,  0,  0,  1,  0,  0,  0},   -0.63e-6,  0.00e-6 },
+      {{ 0,  1,  2, -2,  3,  0,  0,  0},    0.46e-6,  0.00e-6 },
+      {{ 0,  1,  2, -2,  1,  0,  0,  0},    0.45e-6,  0.00e-6 },
+      {{ 0,  0,  4, -4,  4,  0,  0,  0},    0.36e-6,  0.00e-6 },
+      {{ 0,  0,  1, -1,  1, -8, 12,  0},   -0.24e-6, -0.12e-6 },
+      {{ 0,  0,  2,  0,  0,  0,  0,  0},    0.32e-6,  0.00e-6 },
+      {{ 0,  0,  2,  0,  2,  0,  0,  0},    0.28e-6,  0.00e-6 },
+      {{ 1,  0,  2,  0,  3,  0,  0,  0},    0.27e-6,  0.00e-6 },
+      {{ 1,  0,  2,  0,  1,  0,  0,  0},    0.26e-6,  0.00e-6 },
+
+   /* 21-30 */
+      {{ 0,  0,  2, -2,  0,  0,  0,  0},   -0.21e-6,  0.00e-6 },
+      {{ 0,  1, -2,  2, -3,  0,  0,  0},    0.19e-6,  0.00e-6 },
+      {{ 0,  1, -2,  2, -1,  0,  0,  0},    0.18e-6,  0.00e-6 },
+      {{ 0,  0,  0,  0,  0,  8,-13, -1},   -0.10e-6,  0.05e-6 },
+      {{ 0,  0,  0,  2,  0,  0,  0,  0},    0.15e-6,  0.00e-6 },
+      {{ 2,  0, -2,  0, -1,  0,  0,  0},   -0.14e-6,  0.00e-6 },
+      {{ 1,  0,  0, -2,  1,  0,  0,  0},    0.14e-6,  0.00e-6 },
+      {{ 0,  1,  2, -2,  2,  0,  0,  0},   -0.14e-6,  0.00e-6 },
+      {{ 1,  0,  0, -2, -1,  0,  0,  0},    0.14e-6,  0.00e-6 },
+      {{ 0,  0,  4, -2,  4,  0,  0,  0},    0.13e-6,  0.00e-6 },
+
+   /* 31-33 */
+      {{ 0,  0,  2, -2,  4,  0,  0,  0},   -0.11e-6,  0.00e-6 },
+      {{ 1,  0, -2,  0, -3,  0,  0,  0},    0.11e-6,  0.00e-6 },
+      {{ 1,  0, -2,  0, -1,  0,  0,  0},    0.11e-6,  0.00e-6 }
+   };
+
+/* Terms of order t^1 */
+   static const TERM e1[] = {
+      {{ 0,  0,  0,  0,  1,  0,  0,  0},    -0.87e-6,  0.00e-6 }
+   };
+
+/* Number of terms in the series */
+   const int NE0 = (int) (sizeof e0 / sizeof (TERM));
+   const int NE1 = (int) (sizeof e1 / sizeof (TERM));
+
+/*--------------------------------------------------------------------*/
+
+/* Interval between fundamental epoch J2000.0 and current date (JC). */
+   t = ((date1 - DJ00) + date2) / DJC;
+
+/* Fundamental Arguments (from IERS Conventions 2003) */
+
+/* Mean anomaly of the Moon. */
+   fa[0] = iauFal03(t);
+
+/* Mean anomaly of the Sun. */
+   fa[1] = iauFalp03(t);
+
+/* Mean longitude of the Moon minus that of the ascending node. */
+   fa[2] = iauFaf03(t);
+
+/* Mean elongation of the Moon from the Sun. */
+   fa[3] = iauFad03(t);
+
+/* Mean longitude of the ascending node of the Moon. */
+   fa[4] = iauFaom03(t);
+
+/* Mean longitude of Venus. */
+   fa[5] = iauFave03(t);
+
+/* Mean longitude of Earth. */
+   fa[6] = iauFae03(t);
+
+/* General precession in longitude. */
+   fa[7] = iauFapa03(t);
+
+/* Evaluate the EE complementary terms. */
+   s0 = 0.0;
+   s1 = 0.0;
+
+   for (i = NE0-1; i >= 0; i--) {
+      a = 0.0;
+      for (j = 0; j < 8; j++) {
+         a += (double)(e0[i].nfa[j]) * fa[j];
+      }
+      s0 += e0[i].s * sin(a) + e0[i].c * cos(a);
+   }
+
+   for (i = NE1-1; i >= 0; i--) {
+      a = 0.0;
+      for (j = 0; j < 8; j++) {
+         a += (double)(e1[i].nfa[j]) * fa[j];
+      }
+      s1 += e1[i].s * sin(a) + e1[i].c * cos(a);
+   }
+
+   eect = (s0 + s1 * t ) * DAS2R;
+
+   return eect;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+int iauEform ( int n, double *a, double *f )
+/*
+**  - - - - - - - - -
+**   i a u E f o r m
+**  - - - - - - - - -
+**
+**  Earth reference ellipsoids.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards of Fundamental Astronomy) software collection.
+**
+**  Status:  canonical.
+**
+**  Given:
+**     n    int         ellipsoid identifier (Note 1)
+**
+**  Returned:
+**     a    double      equatorial radius (meters, Note 2)
+**     f    double      flattening (Note 2)
+**
+**  Returned (function value):
+**          int         status:  0 = OK
+**                              -1 = illegal identifier (Note 3)
+**
+**  Notes:
+**
+**  1) The identifier n is a number that specifies the choice of
+**     reference ellipsoid.  The following are supported:
+**
+**        n    ellipsoid
+**
+**        1     WGS84
+**        2     GRS80
+**        3     WGS72
+**
+**     The n value has no significance outside the SOFA software.  For
+**     convenience, symbols WGS84 etc. are defined in sofam.h.
+**
+**  2) The ellipsoid parameters are returned in the form of equatorial
+**     radius in meters (a) and flattening (f).  The latter is a number
+**     around 0.00335, i.e. around 1/298.
+**
+**  3) For the case where an unsupported n value is supplied, zero a and
+**     f are returned, as well as error status.
+**
+**  References:
+**
+**     Department of Defense World Geodetic System 1984, National
+**     Imagery and Mapping Agency Technical Report 8350.2, Third
+**     Edition, p3-2.
+**
+**     Moritz, H., Bull. Geodesique 66-2, 187 (1992).
+**
+**     The Department of Defense World Geodetic System 1972, World
+**     Geodetic System Committee, May 1974.
+**
+**     Explanatory Supplement to the Astronomical Almanac,
+**     P. Kenneth Seidelmann (ed), University Science Books (1992),
+**     p220.
+**
+**  This revision:  2012 February 23
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+
+/* Look up a and f for the specified reference ellipsoid. */
+   switch ( n ) {
+
+   case WGS84:
+      *a = 6378137.0;
+      *f = 1.0 / 298.257223563;
+      break;
+
+   case GRS80:
+      *a = 6378137.0;
+      *f = 1.0 / 298.257222101;
+      break;
+
+   case WGS72:
+      *a = 6378135.0;
+      *f = 1.0 / 298.26;
+      break;
+
+   default:
+
+   /* Invalid identifier. */
+      *a = 0.0;
+      *f = 0.0;
+      return -1;
+
+   }
+
+/* OK status. */
+   return 0;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+
+}
+#include "sofam.h"
+
+double iauEo06a(double date1, double date2)
+/*
+**  - - - - - - - - -
+**   i a u E o 0 6 a
+**  - - - - - - - - -
+**
+**  Equation of the origins, IAU 2006 precession and IAU 2000A nutation.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     date1,date2  double    TT as a 2-part Julian Date (Note 1)
+**
+**  Returned (function value):
+**                  double    equation of the origins in radians
+**
+**  Notes:
+**
+**  1) The TT date date1+date2 is a Julian Date, apportioned in any
+**     convenient way between the two arguments.  For example,
+**     JD(TT)=2450123.7 could be expressed in any of these ways,
+**     among others:
+**
+**            date1          date2
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in
+**     cases where the loss of several decimal digits of resolution
+**     is acceptable.  The J2000 method is best matched to the way
+**     the argument is handled internally and will deliver the
+**     optimum resolution.  The MJD method and the date & time methods
+**     are both good compromises between resolution and convenience.
+**
+**  2) The equation of the origins is the distance between the true
+**     equinox and the celestial intermediate origin and, equivalently,
+**     the difference between Earth rotation angle and Greenwich
+**     apparent sidereal time (ERA-GST).  It comprises the precession
+**     (since J2000.0) in right ascension plus the equation of the
+**     equinoxes (including the small correction terms).
+**
+**  Called:
+**     iauPnm06a    classical NPB matrix, IAU 2006/2000A
+**     iauBpn2xy    extract CIP X,Y coordinates from NPB matrix
+**     iauS06       the CIO locator s, given X,Y, IAU 2006
+**     iauEors      equation of the origins, Given NPB matrix and s
+**
+**  References:
+**
+**     Capitaine, N. & Wallace, P.T., 2006, Astron.Astrophys. 450, 855
+**
+**     Wallace, P.T. & Capitaine, N., 2006, Astron.Astrophys. 459, 981
+**
+**  This revision:  2008 May 16
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double r[3][3], x, y, s, eo;
+
+
+/* Classical nutation x precession x bias matrix. */
+   iauPnm06a(date1, date2, r);
+
+/* Extract CIP coordinates. */
+   iauBpn2xy(r, &x, &y);
+
+/* The CIO locator, s. */
+   s = iauS06(date1, date2, x, y);
+
+/* Solve for the EO. */
+   eo = iauEors(r, s);
+
+   return eo;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+double iauEors(double rnpb[3][3], double s)
+/*
+**  - - - - - - - -
+**   i a u E o r s
+**  - - - - - - - -
+**
+**  Equation of the origins, given the classical NPB matrix and the
+**  quantity s.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     rnpb  double[3][3]  classical nutation x precession x bias matrix
+**     s     double        the quantity s (the CIO locator)
+**
+**  Returned (function value):
+**           double        the equation of the origins in radians.
+**
+**  Notes:
+**
+**  1)  The equation of the origins is the distance between the true
+**      equinox and the celestial intermediate origin and, equivalently,
+**      the difference between Earth rotation angle and Greenwich
+**      apparent sidereal time (ERA-GST).  It comprises the precession
+**      (since J2000.0) in right ascension plus the equation of the
+**      equinoxes (including the small correction terms).
+**
+**  2)  The algorithm is from Wallace & Capitaine (2006).
+**
+** References:
+**
+**     Capitaine, N. & Wallace, P.T., 2006, Astron.Astrophys. 450, 855
+**
+**     Wallace, P. & Capitaine, N., 2006, Astron.Astrophys. 459, 981
+**
+**  This revision:  2008 May 26
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double x, ax, xs, ys, zs, p, q, eo;
+
+
+/* Evaluate Wallace & Capitaine (2006) expression (16). */
+   x = rnpb[2][0];
+   ax = x / (1.0 + rnpb[2][2]);
+   xs = 1.0 - ax * x;
+   ys = -ax * rnpb[2][1];
+   zs = -x;
+   p = rnpb[0][0] * xs + rnpb[0][1] * ys + rnpb[0][2] * zs;
+   q = rnpb[1][0] * xs + rnpb[1][1] * ys + rnpb[1][2] * zs;
+   eo = ((p != 0) || (q != 0)) ? s - atan2(q, p) : s;
+
+   return eo;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+double iauEpb(double dj1, double dj2)
+/*
+**  - - - - - - -
+**   i a u E p b
+**  - - - - - - -
+**
+**  Julian Date to Besselian Epoch.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     dj1,dj2    double     Julian Date (see note)
+**
+**  Returned (function value):
+**                double     Besselian Epoch.
+**
+**  Note:
+**
+**     The Julian Date is supplied in two pieces, in the usual SOFA
+**     manner, which is designed to preserve time resolution.  The
+**     Julian Date is available as a single number by adding dj1 and
+**     dj2.  The maximum resolution is achieved if dj1 is 2451545D0
+**     (J2000.0).
+**
+**  Reference:
+**
+**     Lieske,J.H., 1979. Astron.Astrophys.,73,282.
+**
+**  This revision:  2009 December 16
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+/* J2000.0 minus B1900.0 (2415019.81352) in Julian days */
+   static const double D1900 = 36524.68648;
+
+   double epb;
+
+
+   epb = 1900.0 + ((dj1 - DJ00) + (dj2 + D1900)) / DTY;
+
+   return epb;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauEpb2jd(double epb, double *djm0, double *djm)
+/*
+**  - - - - - - - - - -
+**   i a u E p b 2 j d
+**  - - - - - - - - - -
+**
+**  Besselian Epoch to Julian Date.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     epb      double    Besselian Epoch (e.g. 1957.3D0)
+**
+**  Returned:
+**     djm0     double    MJD zero-point: always 2400000.5
+**     djm      double    Modified Julian Date
+**
+**  Note:
+**
+**     The Julian Date is returned in two pieces, in the usual SOFA
+**     manner, which is designed to preserve time resolution.  The
+**     Julian Date is available as a single number by adding djm0 and
+**     djm.
+**
+**  Reference:
+**
+**     Lieske, J.H., 1979, Astron.Astrophys. 73, 282.
+**
+**  This revision:  2008 May 24
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   *djm0 = 2400000.5;
+   *djm  =   15019.81352 + (epb - 1900.0) * DTY;
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+double iauEpj(double dj1, double dj2)
+/*
+**  - - - - - - -
+**   i a u E p j
+**  - - - - - - -
+**
+**  Julian Date to Julian Epoch.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     dj1,dj2    double     Julian Date (see note)
+**
+**  Returned (function value):
+**                double     Julian Epoch
+**
+**  Note:
+**
+**     The Julian Date is supplied in two pieces, in the usual SOFA
+**     manner, which is designed to preserve time resolution.  The
+**     Julian Date is available as a single number by adding dj1 and
+**     dj2.  The maximum resolution is achieved if dj1 is 2451545D0
+**     (J2000.0).
+**
+**  Reference:
+**
+**     Lieske, J.H., 1979, Astron.Astrophys. 73, 282.
+**
+**  This revision:  2009 December 16
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double epj;
+
+
+   epj = 2000.0 + ((dj1 - DJ00) + dj2) / DJY;
+
+   return epj;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauEpj2jd(double epj, double *djm0, double *djm)
+/*
+**  - - - - - - - - - -
+**   i a u E p j 2 j d
+**  - - - - - - - - - -
+**
+**  Julian Epoch to Julian Date.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     epj      double    Julian Epoch (e.g. 1996.8D0)
+**
+**  Returned:
+**     djm0     double    MJD zero-point: always 2400000.5
+**     djm      double    Modified Julian Date
+**
+**  Note:
+**
+**     The Julian Date is returned in two pieces, in the usual SOFA
+**     manner, which is designed to preserve time resolution.  The
+**     Julian Date is available as a single number by adding djm0 and
+**     djm.
+**
+**  Reference:
+**
+**     Lieske, J.H., 1979, Astron.Astrophys. 73, 282.
+**
+**  This revision:  2008 May 11
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   *djm0 = 2400000.5;
+   *djm  =   51544.5 + (epj - 2000.0) * 365.25;
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+int iauEpv00(double date1, double date2,
+             double pvh[2][3], double pvb[2][3])
+/*
+**  - - - - - - - - -
+**   i a u E p v 0 0
+**  - - - - - - - - -
+**
+**  Earth position and velocity, heliocentric and barycentric, with
+**  respect to the Barycentric Celestial Reference System.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     date1,date2  double        TDB date (Note 1)
+**
+**  Returned:
+**     pvh          double[2][3]  heliocentric Earth position/velocity
+**     pvb          double[2][3]  barycentric Earth position/velocity
+**
+**  Returned (function value):
+**                  int           status: 0 = OK
+**                                       +1 = warning: date outside
+**                                            the range 1900-2100 AD
+**
+**  Notes:
+**
+**  1) The TDB date date1+date2 is a Julian Date, apportioned in any
+**     convenient way between the two arguments.  For example,
+**     JD(TDB)=2450123.7 could be expressed in any of these ways, among
+**     others:
+**
+**            date1          date2
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in cases
+**     where the loss of several decimal digits of resolution is
+**     acceptable.  The J2000 method is best matched to the way the
+**     argument is handled internally and will deliver the optimum
+**     resolution.  The MJD method and the date & time methods are both
+**     good compromises between resolution and convenience.  However,
+**     the accuracy of the result is more likely to be limited by the
+**     algorithm itself than the way the date has been expressed.
+**
+**     n.b. TT can be used instead of TDB in most applications.
+**
+**  2) On return, the arrays pvh and pvb contain the following:
+**
+**        pvh[0][0]  x       }
+**        pvh[0][1]  y       } heliocentric position, AU
+**        pvh[0][2]  z       }
+**
+**        pvh[1][0]  xdot    }
+**        pvh[1][1]  ydot    } heliocentric velocity, AU/d
+**        pvh[1][2]  zdot    }
+**
+**        pvb[0][0]  x       }
+**        pvb[0][1]  y       } barycentric position, AU
+**        pvb[0][2]  z       }
+**
+**        pvb[1][0]  xdot    }
+**        pvb[1][1]  ydot    } barycentric velocity, AU/d
+**        pvb[1][2]  zdot    }
+**
+**     The vectors are with respect to the Barycentric Celestial
+**     Reference System.  The time unit is one day in TDB.
+**
+**  3) The function is a SIMPLIFIED SOLUTION from the planetary theory
+**     VSOP2000 (X. Moisson, P. Bretagnon, 2001, Celes. Mechanics &
+**     Dyn. Astron., 80, 3/4, 205-213) and is an adaptation of original
+**     Fortran code supplied by P. Bretagnon (private comm., 2000).
+**
+**  4) Comparisons over the time span 1900-2100 with this simplified
+**     solution and the JPL DE405 ephemeris give the following results:
+**
+**                                RMS    max
+**           Heliocentric:
+**              position error    3.7   11.2   km
+**              velocity error    1.4    5.0   mm/s
+**
+**           Barycentric:
+**              position error    4.6   13.4   km
+**              velocity error    1.4    4.9   mm/s
+**
+**     Comparisons with the JPL DE406 ephemeris show that by 1800 and
+**     2200 the position errors are approximately double their 1900-2100
+**     size.  By 1500 and 2500 the deterioration is a factor of 10 and
+**     by 1000 and 3000 a factor of 60.  The velocity accuracy falls off
+**     at about half that rate.
+**
+**  5) It is permissible to use the same array for pvh and pvb, which
+**     will receive the barycentric values.
+**
+**  This revision:  2008 November 18
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+/*
+** Matrix elements for orienting the analytical model to DE405.
+**
+** The corresponding Euler angles are:
+**
+**                       d  '  "
+**   1st rotation    -  23 26 21.4091 about the x-axis  (obliquity)
+**   2nd rotation    +         0.0475 about the z-axis  (RA offset)
+**
+** These were obtained empirically, by comparisons with DE405 over
+** 1900-2100.
+*/
+   static const double am12 =  0.000000211284,
+                       am13 = -0.000000091603,
+                       am21 = -0.000000230286,
+                       am22 =  0.917482137087,
+                       am23 = -0.397776982902,
+                       am32 =  0.397776982902,
+                       am33 =  0.917482137087;
+
+/*
+** ----------------------
+** Ephemeris Coefficients
+** ----------------------
+**
+** The ephemeris consists of harmonic terms for predicting (i) the Sun
+** to Earth vector and (ii) the Solar-System-barycenter to Sun vector
+** respectively.  The coefficients are stored in arrays which, although
+** 1-demensional, contain groups of three.  Each triplet of
+** coefficients is the amplitude, phase and frequency for one term in
+** the model, and each array contains the number of terms called for by
+** the model.
+**
+** There are eighteen such arrays, named as follows:
+**
+**     array         model      power of T      component
+**
+**      e0x      Sun-to-Earth        0              x
+**      e0y      Sun-to-Earth        0              y
+**      e0z      Sun-to-Earth        0              z
+**
+**      e1x      Sun-to-Earth        1              x
+**      e1y      Sun-to-Earth        1              y
+**      e1z      Sun-to-Earth        1              z
+**
+**      e2x      Sun-to-Earth        2              x
+**      e2y      Sun-to-Earth        2              y
+**      e2z      Sun-to-Earth        2              z
+**
+**      s0x      SSB-to-Sun          0              x
+**      s0y      SSB-to-Sun          0              y
+**      s0z      SSB-to-Sun          0              z
+**
+**      s1x      SSB-to-Sun          1              x
+**      s1y      SSB-to-Sun          1              y
+**      s1z      SSB-to-Sun          1              z
+**
+**      s2x      SSB-to-Sun          2              x
+**      s2y      SSB-to-Sun          2              y
+**      s2z      SSB-to-Sun          2              z
+*/
+
+/* Sun-to-Earth, T^0, X */
+   static const double e0x[] = {
+      0.9998292878132e+00, 0.1753485171504e+01, 0.6283075850446e+01,
+      0.8352579567414e-02, 0.1710344404582e+01, 0.1256615170089e+02,
+      0.5611445335148e-02, 0.0000000000000e+00, 0.0000000000000e+00,
+      0.1046664295572e-03, 0.1667225416770e+01, 0.1884922755134e+02,
+      0.3110842534677e-04, 0.6687513390251e+00, 0.8399684731857e+02,
+      0.2552413503550e-04, 0.5830637358413e+00, 0.5296909721118e+00,
+      0.2137207845781e-04, 0.1092330954011e+01, 0.1577343543434e+01,
+      0.1680240182951e-04, 0.4955366134987e+00, 0.6279552690824e+01,
+      0.1679012370795e-04, 0.6153014091901e+01, 0.6286599010068e+01,
+      0.1445526946777e-04, 0.3472744100492e+01, 0.2352866153506e+01,
+
+      0.1091038246184e-04, 0.3689845786119e+01, 0.5223693906222e+01,
+      0.9344399733932e-05, 0.6073934645672e+01, 0.1203646072878e+02,
+      0.8993182910652e-05, 0.3175705249069e+01, 0.1021328554739e+02,
+      0.5665546034116e-05, 0.2152484672246e+01, 0.1059381944224e+01,
+      0.6844146703035e-05, 0.1306964099750e+01, 0.5753384878334e+01,
+      0.7346610905565e-05, 0.4354980070466e+01, 0.3981490189893e+00,
+      0.6815396474414e-05, 0.2218229211267e+01, 0.4705732307012e+01,
+      0.6112787253053e-05, 0.5384788425458e+01, 0.6812766822558e+01,
+      0.4518120711239e-05, 0.6087604012291e+01, 0.5884926831456e+01,
+      0.4521963430706e-05, 0.1279424524906e+01, 0.6256777527156e+01,
+
+      0.4497426764085e-05, 0.5369129144266e+01, 0.6309374173736e+01,
+      0.4062190566959e-05, 0.5436473303367e+00, 0.6681224869435e+01,
+      0.5412193480192e-05, 0.7867838528395e+00, 0.7755226100720e+00,
+      0.5469839049386e-05, 0.1461440311134e+01, 0.1414349524433e+02,
+      0.5205264083477e-05, 0.4432944696116e+01, 0.7860419393880e+01,
+      0.2149759935455e-05, 0.4502237496846e+01, 0.1150676975667e+02,
+      0.2279109618501e-05, 0.1239441308815e+01, 0.7058598460518e+01,
+      0.2259282939683e-05, 0.3272430985331e+01, 0.4694002934110e+01,
+      0.2558950271319e-05, 0.2265471086404e+01, 0.1216800268190e+02,
+      0.2561581447555e-05, 0.1454740653245e+01, 0.7099330490126e+00,
+
+      0.1781441115440e-05, 0.2962068630206e+01, 0.7962980379786e+00,
+      0.1612005874644e-05, 0.1473255041006e+01, 0.5486777812467e+01,
+      0.1818630667105e-05, 0.3743903293447e+00, 0.6283008715021e+01,
+      0.1818601377529e-05, 0.6274174354554e+01, 0.6283142985870e+01,
+      0.1554475925257e-05, 0.1624110906816e+01, 0.2513230340178e+02,
+      0.2090948029241e-05, 0.5852052276256e+01, 0.1179062909082e+02,
+      0.2000176345460e-05, 0.4072093298513e+01, 0.1778984560711e+02,
+      0.1289535917759e-05, 0.5217019331069e+01, 0.7079373888424e+01,
+      0.1281135307881e-05, 0.4802054538934e+01, 0.3738761453707e+01,
+      0.1518229005692e-05, 0.8691914742502e+00, 0.2132990797783e+00,
+
+      0.9450128579027e-06, 0.4601859529950e+01, 0.1097707878456e+02,
+      0.7781119494996e-06, 0.1844352816694e+01, 0.8827390247185e+01,
+      0.7733407759912e-06, 0.3582790154750e+01, 0.5507553240374e+01,
+      0.7350644318120e-06, 0.2695277788230e+01, 0.1589072916335e+01,
+      0.6535928827023e-06, 0.3651327986142e+01, 0.1176985366291e+02,
+      0.6324624183656e-06, 0.2241302375862e+01, 0.6262300422539e+01,
+      0.6298565300557e-06, 0.4407122406081e+01, 0.6303851278352e+01,
+      0.8587037089179e-06, 0.3024307223119e+01, 0.1672837615881e+03,
+      0.8299954491035e-06, 0.6192539428237e+01, 0.3340612434717e+01,
+      0.6311263503401e-06, 0.2014758795416e+01, 0.7113454667900e-02,
+
+      0.6005646745452e-06, 0.3399500503397e+01, 0.4136910472696e+01,
+      0.7917715109929e-06, 0.2493386877837e+01, 0.6069776770667e+01,
+      0.7556958099685e-06, 0.4159491740143e+01, 0.6496374930224e+01,
+      0.6773228244949e-06, 0.4034162934230e+01, 0.9437762937313e+01,
+      0.5370708577847e-06, 0.1562219163734e+01, 0.1194447056968e+01,
+      0.5710804266203e-06, 0.2662730803386e+01, 0.6282095334605e+01,
+      0.5709824583726e-06, 0.3985828430833e+01, 0.6284056366286e+01,
+      0.5143950896447e-06, 0.1308144688689e+01, 0.6290189305114e+01,
+      0.5088010604546e-06, 0.5352817214804e+01, 0.6275962395778e+01,
+      0.4960369085172e-06, 0.2644267922349e+01, 0.6127655567643e+01,
+
+      0.4803137891183e-06, 0.4008844192080e+01, 0.6438496133249e+01,
+      0.5731747768225e-06, 0.3794550174597e+01, 0.3154687086868e+01,
+      0.4735947960579e-06, 0.6107118308982e+01, 0.3128388763578e+01,
+      0.4808348796625e-06, 0.4771458618163e+01, 0.8018209333619e+00,
+      0.4115073743137e-06, 0.3327111335159e+01, 0.8429241228195e+01,
+      0.5230575889287e-06, 0.5305708551694e+01, 0.1336797263425e+02,
+      0.5133977889215e-06, 0.5784230738814e+01, 0.1235285262111e+02,
+      0.5065815825327e-06, 0.2052064793679e+01, 0.1185621865188e+02,
+      0.4339831593868e-06, 0.3644994195830e+01, 0.1726015463500e+02,
+      0.3952928638953e-06, 0.4930376436758e+01, 0.5481254917084e+01,
+
+      0.4898498111942e-06, 0.4542084219731e+00, 0.9225539266174e+01,
+      0.4757490209328e-06, 0.3161126388878e+01, 0.5856477690889e+01,
+      0.4727701669749e-06, 0.6214993845446e+00, 0.2544314396739e+01,
+      0.3800966681863e-06, 0.3040132339297e+01, 0.4265981595566e+00,
+      0.3257301077939e-06, 0.8064977360087e+00, 0.3930209696940e+01,
+      0.3255810528674e-06, 0.1974147981034e+01, 0.2146165377750e+01,
+      0.3252029748187e-06, 0.2845924913135e+01, 0.4164311961999e+01,
+      0.3255505635308e-06, 0.3017900824120e+01, 0.5088628793478e+01,
+      0.2801345211990e-06, 0.6109717793179e+01, 0.1256967486051e+02,
+      0.3688987740970e-06, 0.2911550235289e+01, 0.1807370494127e+02,
+
+      0.2475153429458e-06, 0.2179146025856e+01, 0.2629832328990e-01,
+      0.3033457749150e-06, 0.1994161050744e+01, 0.4535059491685e+01,
+      0.2186743763110e-06, 0.5125687237936e+01, 0.1137170464392e+02,
+      0.2764777032774e-06, 0.4822646860252e+00, 0.1256262854127e+02,
+      0.2199028768592e-06, 0.4637633293831e+01, 0.1255903824622e+02,
+      0.2046482824760e-06, 0.1467038733093e+01, 0.7084896783808e+01,
+      0.2611209147507e-06, 0.3044718783485e+00, 0.7143069561767e+02,
+      0.2286079656818e-06, 0.4764220356805e+01, 0.8031092209206e+01,
+      0.1855071202587e-06, 0.3383637774428e+01, 0.1748016358760e+01,
+      0.2324669506784e-06, 0.6189088449251e+01, 0.1831953657923e+02,
+
+      0.1709528015688e-06, 0.5874966729774e+00, 0.4933208510675e+01,
+      0.2168156875828e-06, 0.4302994009132e+01, 0.1044738781244e+02,
+      0.2106675556535e-06, 0.3800475419891e+01, 0.7477522907414e+01,
+      0.1430213830465e-06, 0.1294660846502e+01, 0.2942463415728e+01,
+      0.1388396901944e-06, 0.4594797202114e+01, 0.8635942003952e+01,
+      0.1922258844190e-06, 0.4943044543591e+00, 0.1729818233119e+02,
+      0.1888460058292e-06, 0.2426943912028e+01, 0.1561374759853e+03,
+      0.1789449386107e-06, 0.1582973303499e+00, 0.1592596075957e+01,
+      0.1360803685374e-06, 0.5197240440504e+01, 0.1309584267300e+02,
+      0.1504038014709e-06, 0.3120360916217e+01, 0.1649636139783e+02,
+
+      0.1382769533389e-06, 0.6164702888205e+01, 0.7632943190217e+01,
+      0.1438059769079e-06, 0.1437423770979e+01, 0.2042657109477e+02,
+      0.1326303260037e-06, 0.3609688799679e+01, 0.1213955354133e+02,
+      0.1159244950540e-06, 0.5463018167225e+01, 0.5331357529664e+01,
+      0.1433118149136e-06, 0.6028909912097e+01, 0.7342457794669e+01,
+      0.1234623148594e-06, 0.3109645574997e+01, 0.6279485555400e+01,
+      0.1233949875344e-06, 0.3539359332866e+01, 0.6286666145492e+01,
+      0.9927196061299e-07, 0.1259321569772e+01, 0.7234794171227e+01,
+      0.1242302191316e-06, 0.1065949392609e+01, 0.1511046609763e+02,
+      0.1098402195201e-06, 0.2192508743837e+01, 0.1098880815746e+02,
+
+      0.1158191395315e-06, 0.4054411278650e+01, 0.5729506548653e+01,
+      0.9048475596241e-07, 0.5429764748518e+01, 0.9623688285163e+01,
+      0.8889853269023e-07, 0.5046586206575e+01, 0.6148010737701e+01,
+      0.1048694242164e-06, 0.2628858030806e+01, 0.6836645152238e+01,
+      0.1112308378646e-06, 0.4177292719907e+01, 0.1572083878776e+02,
+      0.8631729709901e-07, 0.1601345232557e+01, 0.6418140963190e+01,
+      0.8527816951664e-07, 0.2463888997513e+01, 0.1471231707864e+02,
+      0.7892139456991e-07, 0.3154022088718e+01, 0.2118763888447e+01,
+      0.1051782905236e-06, 0.4795035816088e+01, 0.1349867339771e+01,
+      0.1048219943164e-06, 0.2952983395230e+01, 0.5999216516294e+01,
+
+      0.7435760775143e-07, 0.5420547991464e+01, 0.6040347114260e+01,
+      0.9869574106949e-07, 0.3695646753667e+01, 0.6566935184597e+01,
+      0.9156886364226e-07, 0.3922675306609e+01, 0.5643178611111e+01,
+      0.7006834356188e-07, 0.1233968624861e+01, 0.6525804586632e+01,
+      0.9806170182601e-07, 0.1919542280684e+01, 0.2122839202813e+02,
+      0.9052289673607e-07, 0.4615902724369e+01, 0.4690479774488e+01,
+      0.7554200867893e-07, 0.1236863719072e+01, 0.1253985337760e+02,
+      0.8215741286498e-07, 0.3286800101559e+00, 0.1097355562493e+02,
+      0.7185178575397e-07, 0.5880942158367e+01, 0.6245048154254e+01,
+      0.7130726476180e-07, 0.7674871987661e+00, 0.6321103546637e+01,
+
+      0.6650894461162e-07, 0.6987129150116e+00, 0.5327476111629e+01,
+      0.7396888823688e-07, 0.3576824794443e+01, 0.5368044267797e+00,
+      0.7420588884775e-07, 0.5033615245369e+01, 0.2354323048545e+02,
+      0.6141181642908e-07, 0.9449927045673e+00, 0.1296430071988e+02,
+      0.6373557924058e-07, 0.6206342280341e+01, 0.9517183207817e+00,
+      0.6359474329261e-07, 0.5036079095757e+01, 0.1990745094947e+01,
+      0.5740173582646e-07, 0.6105106371350e+01, 0.9555997388169e+00,
+      0.7019864084602e-07, 0.7237747359018e+00, 0.5225775174439e+00,
+      0.6398054487042e-07, 0.3976367969666e+01, 0.2407292145756e+02,
+      0.7797092650498e-07, 0.4305423910623e+01, 0.2200391463820e+02,
+
+      0.6466760000900e-07, 0.3500136825200e+01, 0.5230807360890e+01,
+      0.7529417043890e-07, 0.3514779246100e+01, 0.1842262939178e+02,
+      0.6924571140892e-07, 0.2743457928679e+01, 0.1554202828031e+00,
+      0.6220798650222e-07, 0.2242598118209e+01, 0.1845107853235e+02,
+      0.5870209391853e-07, 0.2332832707527e+01, 0.6398972393349e+00,
+      0.6263953473888e-07, 0.2191105358956e+01, 0.6277552955062e+01,
+      0.6257781390012e-07, 0.4457559396698e+01, 0.6288598745829e+01,
+      0.5697304945123e-07, 0.3499234761404e+01, 0.1551045220144e+01,
+      0.6335438746791e-07, 0.6441691079251e+00, 0.5216580451554e+01,
+      0.6377258441152e-07, 0.2252599151092e+01, 0.5650292065779e+01,
+
+      0.6484841818165e-07, 0.1992812417646e+01, 0.1030928125552e+00,
+      0.4735551485250e-07, 0.3744672082942e+01, 0.1431416805965e+02,
+      0.4628595996170e-07, 0.1334226211745e+01, 0.5535693017924e+00,
+      0.6258152336933e-07, 0.4395836159154e+01, 0.2608790314060e+02,
+      0.6196171366594e-07, 0.2587043007997e+01, 0.8467247584405e+02,
+      0.6159556952126e-07, 0.4782499769128e+01, 0.2394243902548e+03,
+      0.4987741172394e-07, 0.7312257619924e+00, 0.7771377146812e+02,
+      0.5459280703142e-07, 0.3001376372532e+01, 0.6179983037890e+01,
+      0.4863461189999e-07, 0.3767222128541e+01, 0.9027992316901e+02,
+      0.5349912093158e-07, 0.3663594450273e+01, 0.6386168663001e+01,
+
+      0.5673725607806e-07, 0.4331187919049e+01, 0.6915859635113e+01,
+      0.4745485060512e-07, 0.5816195745518e+01, 0.6282970628506e+01,
+      0.4745379005326e-07, 0.8323672435672e+00, 0.6283181072386e+01,
+      0.4049002796321e-07, 0.3785023976293e+01, 0.6254626709878e+01,
+      0.4247084014515e-07, 0.2378220728783e+01, 0.7875671926403e+01,
+      0.4026912363055e-07, 0.2864103423269e+01, 0.6311524991013e+01,
+      0.4062935011774e-07, 0.2415408595975e+01, 0.3634620989887e+01,
+      0.5347771048509e-07, 0.3343479309801e+01, 0.2515860172507e+02,
+      0.4829494136505e-07, 0.2821742398262e+01, 0.5760498333002e+01,
+      0.4342554404599e-07, 0.5624662458712e+01, 0.7238675589263e+01,
+
+      0.4021599184361e-07, 0.5557250275009e+00, 0.1101510648075e+02,
+      0.4104900474558e-07, 0.3296691780005e+01, 0.6709674010002e+01,
+      0.4376532905131e-07, 0.3814443999443e+01, 0.6805653367890e+01,
+      0.3314590480650e-07, 0.3560229189250e+01, 0.1259245002418e+02,
+      0.3232421839643e-07, 0.5185389180568e+01, 0.1066495398892e+01,
+      0.3541176318876e-07, 0.3921381909679e+01, 0.9917696840332e+01,
+      0.3689831242681e-07, 0.4190658955386e+01, 0.1192625446156e+02,
+      0.3890605376774e-07, 0.5546023371097e+01, 0.7478166569050e-01,
+      0.3038559339780e-07, 0.6231032794494e+01, 0.1256621883632e+02,
+      0.3137083969782e-07, 0.6207063419190e+01, 0.4292330755499e+01,
+
+      0.4024004081854e-07, 0.1195257375713e+01, 0.1334167431096e+02,
+      0.3300234879283e-07, 0.1804694240998e+01, 0.1057540660594e+02,
+      0.3635399155575e-07, 0.5597811343500e+01, 0.6208294184755e+01,
+      0.3032668691356e-07, 0.3191059366530e+01, 0.1805292951336e+02,
+      0.2809652069058e-07, 0.4094348032570e+01, 0.3523159621801e-02,
+      0.3696955383823e-07, 0.5219282738794e+01, 0.5966683958112e+01,
+      0.3562894142503e-07, 0.1037247544554e+01, 0.6357857516136e+01,
+      0.3510598524148e-07, 0.1430020816116e+01, 0.6599467742779e+01,
+      0.3617736142953e-07, 0.3002911403677e+01, 0.6019991944201e+01,
+      0.2624524910730e-07, 0.2437046757292e+01, 0.6702560555334e+01,
+
+      0.2535824204490e-07, 0.1581594689647e+01, 0.3141537925223e+02,
+      0.3519787226257e-07, 0.5379863121521e+01, 0.2505706758577e+03,
+      0.2578406709982e-07, 0.4904222639329e+01, 0.1673046366289e+02,
+      0.3423887981473e-07, 0.3646448997315e+01, 0.6546159756691e+01,
+      0.2776083886467e-07, 0.3307829300144e+01, 0.1272157198369e+02,
+      0.3379592818379e-07, 0.1747541251125e+01, 0.1494531617769e+02,
+      0.3050255426284e-07, 0.1784689432607e-01, 0.4732030630302e+01,
+      0.2652378350236e-07, 0.4420055276260e+01, 0.5863591145557e+01,
+      0.2374498173768e-07, 0.3629773929208e+01, 0.2388894113936e+01,
+      0.2716451255140e-07, 0.3079623706780e+01, 0.1202934727411e+02,
+
+      0.3038583699229e-07, 0.3312487903507e+00, 0.1256608456547e+02,
+      0.2220681228760e-07, 0.5265520401774e+01, 0.1336244973887e+02,
+      0.3044156540912e-07, 0.4766664081250e+01, 0.2908881142201e+02,
+      0.2731859923561e-07, 0.5069146530691e+01, 0.1391601904066e+02,
+      0.2285603018171e-07, 0.5954935112271e+01, 0.6076890225335e+01,
+      0.2025006454555e-07, 0.4061789589267e+01, 0.4701116388778e+01,
+      0.2012597519804e-07, 0.2485047705241e+01, 0.6262720680387e+01,
+      0.2003406962258e-07, 0.4163779209320e+01, 0.6303431020504e+01,
+      0.2207863441371e-07, 0.6923839133828e+00, 0.6489261475556e+01,
+      0.2481374305624e-07, 0.5944173595676e+01, 0.1204357418345e+02,
+
+      0.2130923288870e-07, 0.4641013671967e+01, 0.5746271423666e+01,
+      0.2446370543391e-07, 0.6125796518757e+01, 0.1495633313810e+00,
+      0.1932492759052e-07, 0.2234572324504e+00, 0.1352175143971e+02,
+      0.2600122568049e-07, 0.4281012405440e+01, 0.4590910121555e+01,
+      0.2431754047488e-07, 0.1429943874870e+00, 0.1162474756779e+01,
+      0.1875902869209e-07, 0.9781803816948e+00, 0.6279194432410e+01,
+      0.1874381139426e-07, 0.5670368130173e+01, 0.6286957268481e+01,
+      0.2156696047173e-07, 0.2008985006833e+01, 0.1813929450232e+02,
+      0.1965076182484e-07, 0.2566186202453e+00, 0.4686889479442e+01,
+      0.2334816372359e-07, 0.4408121891493e+01, 0.1002183730415e+02,
+
+      0.1869937408802e-07, 0.5272745038656e+01, 0.2427287361862e+00,
+      0.2436236460883e-07, 0.4407720479029e+01, 0.9514313292143e+02,
+      0.1761365216611e-07, 0.1943892315074e+00, 0.1351787002167e+02,
+      0.2156289480503e-07, 0.1418570924545e+01, 0.6037244212485e+01,
+      0.2164748979255e-07, 0.4724603439430e+01, 0.2301353951334e+02,
+      0.2222286670853e-07, 0.2400266874598e+01, 0.1266924451345e+02,
+      0.2070901414929e-07, 0.5230348028732e+01, 0.6528907488406e+01,
+      0.1792745177020e-07, 0.2099190328945e+01, 0.6819880277225e+01,
+      0.1841802068445e-07, 0.3467527844848e+00, 0.6514761976723e+02,
+      0.1578401631718e-07, 0.7098642356340e+00, 0.2077542790660e-01,
+
+      0.1561690152531e-07, 0.5943349620372e+01, 0.6272439236156e+01,
+      0.1558591045463e-07, 0.7040653478980e+00, 0.6293712464735e+01,
+      0.1737356469576e-07, 0.4487064760345e+01, 0.1765478049437e+02,
+      0.1434755619991e-07, 0.2993391570995e+01, 0.1102062672231e+00,
+      0.1482187806654e-07, 0.2278049198251e+01, 0.1052268489556e+01,
+      0.1424812827089e-07, 0.1682114725827e+01, 0.1311972100268e+02,
+      0.1380282448623e-07, 0.3262668602579e+01, 0.1017725758696e+02,
+      0.1811481244566e-07, 0.3187771221777e+01, 0.1887552587463e+02,
+      0.1504446185696e-07, 0.5650162308647e+01, 0.7626583626240e-01,
+      0.1740776154137e-07, 0.5487068607507e+01, 0.1965104848470e+02,
+
+      0.1374339536251e-07, 0.5745688172201e+01, 0.6016468784579e+01,
+      0.1761377477704e-07, 0.5748060203659e+01, 0.2593412433514e+02,
+      0.1535138225795e-07, 0.6226848505790e+01, 0.9411464614024e+01,
+      0.1788140543676e-07, 0.6189318878563e+01, 0.3301902111895e+02,
+      0.1375002807996e-07, 0.5371812884394e+01, 0.6327837846670e+00,
+      0.1242115758632e-07, 0.1471687569712e+01, 0.3894181736510e+01,
+      0.1450977333938e-07, 0.4143836662127e+01, 0.1277945078067e+02,
+      0.1297579575023e-07, 0.9003477661957e+00, 0.6549682916313e+01,
+      0.1462667934821e-07, 0.5760505536428e+01, 0.1863592847156e+02,
+      0.1381774374799e-07, 0.1085471729463e+01, 0.2379164476796e+01,
+
+      0.1682333169307e-07, 0.5409870870133e+01, 0.1620077269078e+02,
+      0.1190812918837e-07, 0.1397205174601e+01, 0.1149965630200e+02,
+      0.1221434762106e-07, 0.9001804809095e+00, 0.1257326515556e+02,
+      0.1549934644860e-07, 0.4262528275544e+01, 0.1820933031200e+02,
+      0.1252138953050e-07, 0.1411642012027e+01, 0.6993008899458e+01,
+      0.1237078905387e-07, 0.2844472403615e+01, 0.2435678079171e+02,
+      0.1446953389615e-07, 0.5295835522223e+01, 0.3813291813120e-01,
+      0.1388446457170e-07, 0.4969428135497e+01, 0.2458316379602e+00,
+      0.1019339179228e-07, 0.2491369561806e+01, 0.6112403035119e+01,
+      0.1258880815343e-07, 0.4679426248976e+01, 0.5429879531333e+01,
+
+      0.1297768238261e-07, 0.1074509953328e+01, 0.1249137003520e+02,
+      0.9913505718094e-08, 0.4735097918224e+01, 0.6247047890016e+01,
+      0.9830453155969e-08, 0.4158649187338e+01, 0.6453748665772e+01,
+      0.1192615865309e-07, 0.3438208613699e+01, 0.6290122169689e+01,
+      0.9835874798277e-08, 0.1913300781229e+01, 0.6319103810876e+01,
+      0.9639087569277e-08, 0.9487683644125e+00, 0.8273820945392e+01,
+      0.1175716107001e-07, 0.3228141664287e+01, 0.6276029531202e+01,
+      0.1018926508678e-07, 0.2216607854300e+01, 0.1254537627298e+02,
+      0.9500087869225e-08, 0.2625116459733e+01, 0.1256517118505e+02,
+      0.9664192916575e-08, 0.5860562449214e+01, 0.6259197520765e+01,
+
+      0.9612858712203e-08, 0.7885682917381e+00, 0.6306954180126e+01,
+      0.1117645675413e-07, 0.3932148831189e+01, 0.1779695906178e+02,
+      0.1158864052160e-07, 0.9995605521691e+00, 0.1778273215245e+02,
+      0.9021043467028e-08, 0.5263769742673e+01, 0.6172869583223e+01,
+      0.8836134773563e-08, 0.1496843220365e+01, 0.1692165728891e+01,
+      0.1045872200691e-07, 0.7009039517214e+00, 0.2204125344462e+00,
+      0.1211463487798e-07, 0.4041544938511e+01, 0.8257698122054e+02,
+      0.8541990804094e-08, 0.1447586692316e+01, 0.6393282117669e+01,
+      0.1038720703636e-07, 0.4594249718112e+00, 0.1550861511662e+02,
+      0.1126722351445e-07, 0.3925550579036e+01, 0.2061856251104e+00,
+
+      0.8697373859631e-08, 0.4411341856037e+01, 0.9491756770005e+00,
+      0.8869380028441e-08, 0.2402659724813e+01, 0.3903911373650e+01,
+      0.9247014693258e-08, 0.1401579743423e+01, 0.6267823317922e+01,
+      0.9205062930950e-08, 0.5245978000814e+01, 0.6298328382969e+01,
+      0.8000745038049e-08, 0.3590803356945e+01, 0.2648454860559e+01,
+      0.9168973650819e-08, 0.2470150501679e+01, 0.1498544001348e+03,
+      0.1075444949238e-07, 0.1328606161230e+01, 0.3694923081589e+02,
+      0.7817298525817e-08, 0.6162256225998e+01, 0.4804209201333e+01,
+      0.9541469226356e-08, 0.3942568967039e+01, 0.1256713221673e+02,
+      0.9821910122027e-08, 0.2360246287233e+00, 0.1140367694411e+02,
+
+      0.9897822023777e-08, 0.4619805634280e+01, 0.2280573557157e+02,
+      0.7737289283765e-08, 0.3784727847451e+01, 0.7834121070590e+01,
+      0.9260204034710e-08, 0.2223352487601e+01, 0.2787043132925e+01,
+      0.7320252888486e-08, 0.1288694636874e+01, 0.6282655592598e+01,
+      0.7319785780946e-08, 0.5359869567774e+01, 0.6283496108294e+01,
+      0.7147219933778e-08, 0.5516616675856e+01, 0.1725663147538e+02,
+      0.7946502829878e-08, 0.2630459984567e+01, 0.1241073141809e+02,
+      0.9001711808932e-08, 0.2849815827227e+01, 0.6281591679874e+01,
+      0.8994041507257e-08, 0.3795244450750e+01, 0.6284560021018e+01,
+      0.8298582787358e-08, 0.5236413127363e+00, 0.1241658836951e+02,
+
+      0.8526596520710e-08, 0.4794605424426e+01, 0.1098419223922e+02,
+      0.8209822103197e-08, 0.1578752370328e+01, 0.1096996532989e+02,
+      0.6357049861094e-08, 0.5708926113761e+01, 0.1596186371003e+01,
+      0.7370473179049e-08, 0.3842402530241e+01, 0.4061219149443e+01,
+      0.7232154664726e-08, 0.3067548981535e+01, 0.1610006857377e+03,
+      0.6328765494903e-08, 0.1313930030069e+01, 0.1193336791622e+02,
+      0.8030064908595e-08, 0.3488500408886e+01, 0.8460828644453e+00,
+      0.6275464259232e-08, 0.1532061626198e+01, 0.8531963191132e+00,
+      0.7051897446325e-08, 0.3285859929993e+01, 0.5849364236221e+01,
+      0.6161593705428e-08, 0.1477341999464e+01, 0.5573142801433e+01,
+
+      0.7754683957278e-08, 0.1586118663096e+01, 0.8662240327241e+01,
+      0.5889928990701e-08, 0.1304887868803e+01, 0.1232342296471e+02,
+      0.5705756047075e-08, 0.4555333589350e+01, 0.1258692712880e+02,
+      0.5964178808332e-08, 0.3001762842062e+01, 0.5333900173445e+01,
+      0.6712446027467e-08, 0.4886780007595e+01, 0.1171295538178e+02,
+      0.5941809275464e-08, 0.4701509603824e+01, 0.9779108567966e+01,
+      0.5466993627395e-08, 0.4588357817278e+01, 0.1884211409667e+02,
+      0.6340512090980e-08, 0.1164543038893e+01, 0.5217580628120e+02,
+      0.6325505710045e-08, 0.3919171259645e+01, 0.1041998632314e+02,
+      0.6164789509685e-08, 0.2143828253542e+01, 0.6151533897323e+01,
+
+      0.5263330812430e-08, 0.6066564434241e+01, 0.1885275071096e+02,
+      0.5597087780221e-08, 0.2926316429472e+01, 0.4337116142245e+00,
+      0.5396556236817e-08, 0.3244303591505e+01, 0.6286362197481e+01,
+      0.5396615148223e-08, 0.3404304703662e+01, 0.6279789503410e+01,
+      0.7091832443341e-08, 0.8532377803192e+00, 0.4907302013889e+01,
+      0.6572352589782e-08, 0.4901966774419e+01, 0.1176433076753e+02,
+      0.5960236060795e-08, 0.1874672315797e+01, 0.1422690933580e-01,
+      0.5125480043511e-08, 0.3735726064334e+01, 0.1245594543367e+02,
+      0.5928241866410e-08, 0.4502033899935e+01, 0.6414617803568e+01,
+      0.5249600357424e-08, 0.4372334799878e+01, 0.1151388321134e+02,
+
+      0.6059171276087e-08, 0.2581617302908e+01, 0.6062663316000e+01,
+      0.5295235081662e-08, 0.2974811513158e+01, 0.3496032717521e+01,
+      0.5820561875933e-08, 0.1796073748244e+00, 0.2838593341516e+00,
+      0.4754696606440e-08, 0.1981998136973e+01, 0.3104930017775e+01,
+      0.6385053548955e-08, 0.2559174171605e+00, 0.6133512519065e+01,
+      0.6589828273941e-08, 0.2750967106776e+01, 0.4087944051283e+02,
+      0.5383376567189e-08, 0.6325947523578e+00, 0.2248384854122e+02,
+      0.5928941683538e-08, 0.1672304519067e+01, 0.1581959461667e+01,
+      0.4816060709794e-08, 0.3512566172575e+01, 0.9388005868221e+01,
+      0.6003381586512e-08, 0.5610932219189e+01, 0.5326786718777e+01,
+
+      0.5504225393105e-08, 0.4037501131256e+01, 0.6503488384892e+01,
+      0.5353772620129e-08, 0.6122774968240e+01, 0.1735668374386e+03,
+      0.5786253768544e-08, 0.5527984999515e+01, 0.1350651127443e+00,
+      0.5065706702002e-08, 0.9980765573624e+00, 0.1248988586463e+02,
+      0.5972838885276e-08, 0.6044489493203e+01, 0.2673594526851e+02,
+      0.5323585877961e-08, 0.3924265998147e+01, 0.4171425416666e+01,
+      0.5210772682858e-08, 0.6220111376901e+01, 0.2460261242967e+02,
+      0.4726549040535e-08, 0.3716043206862e+01, 0.7232251527446e+01,
+      0.6029425105059e-08, 0.8548704071116e+00, 0.3227113045244e+03,
+      0.4481542826513e-08, 0.1426925072829e+01, 0.5547199253223e+01,
+
+      0.5836024505068e-08, 0.7135651752625e-01, 0.7285056171570e+02,
+      0.4137046613272e-08, 0.5330767643283e+01, 0.1087398597200e+02,
+      0.5171977473924e-08, 0.4494262335353e+00, 0.1884570439172e+02,
+      0.5694429833732e-08, 0.2952369582215e+01, 0.9723862754494e+02,
+      0.4009158925298e-08, 0.3500003416535e+01, 0.6244942932314e+01,
+      0.4784939596873e-08, 0.6196709413181e+01, 0.2929661536378e+02,
+      0.3983725022610e-08, 0.5103690031897e+01, 0.4274518229222e+01,
+      0.3870535232462e-08, 0.3187569587401e+01, 0.6321208768577e+01,
+      0.5140501213951e-08, 0.1668924357457e+01, 0.1232032006293e+02,
+      0.3849034819355e-08, 0.4445722510309e+01, 0.1726726808967e+02,
+
+      0.4002383075060e-08, 0.5226224152423e+01, 0.7018952447668e+01,
+      0.3890719543549e-08, 0.4371166550274e+01, 0.1491901785440e+02,
+      0.4887084607881e-08, 0.5973556689693e+01, 0.1478866649112e+01,
+      0.3739939287592e-08, 0.2089084714600e+01, 0.6922973089781e+01,
+      0.5031925918209e-08, 0.4658371936827e+01, 0.1715706182245e+02,
+      0.4387748764954e-08, 0.4825580552819e+01, 0.2331413144044e+03,
+      0.4147398098865e-08, 0.3739003524998e+01, 0.1376059875786e+02,
+      0.3719089993586e-08, 0.1148941386536e+01, 0.6297302759782e+01,
+      0.3934238461056e-08, 0.1559893008343e+01, 0.7872148766781e+01,
+      0.3672471375622e-08, 0.5516145383612e+01, 0.6268848941110e+01,
+
+      0.3768911277583e-08, 0.6116053700563e+01, 0.4157198507331e+01,
+      0.4033388417295e-08, 0.5076821746017e+01, 0.1567108171867e+02,
+      0.3764194617832e-08, 0.8164676232075e+00, 0.3185192151914e+01,
+      0.4840628226284e-08, 0.1360479453671e+01, 0.1252801878276e+02,
+      0.4949443923785e-08, 0.2725622229926e+01, 0.1617106187867e+03,
+      0.4117393089971e-08, 0.6054459628492e+00, 0.5642198095270e+01,
+      0.3925754020428e-08, 0.8570462135210e+00, 0.2139354194808e+02,
+      0.3630551757923e-08, 0.3552067338279e+01, 0.6294805223347e+01,
+      0.3627274802357e-08, 0.3096565085313e+01, 0.6271346477544e+01,
+      0.3806143885093e-08, 0.6367751709777e+00, 0.1725304118033e+02,
+
+      0.4433254641565e-08, 0.4848461503937e+01, 0.7445550607224e+01,
+      0.3712319846576e-08, 0.1331950643655e+01, 0.4194847048887e+00,
+      0.3849847534783e-08, 0.4958368297746e+00, 0.9562891316684e+00,
+      0.3483955430165e-08, 0.2237215515707e+01, 0.1161697602389e+02,
+      0.3961912730982e-08, 0.3332402188575e+01, 0.2277943724828e+02,
+      0.3419978244481e-08, 0.5785600576016e+01, 0.1362553364512e+02,
+      0.3329417758177e-08, 0.9812676559709e-01, 0.1685848245639e+02,
+      0.4207206893193e-08, 0.9494780468236e+00, 0.2986433403208e+02,
+      0.3268548976410e-08, 0.1739332095686e+00, 0.5749861718712e+01,
+      0.3321880082685e-08, 0.1423354800666e+01, 0.6279143387820e+01,
+
+      0.4503173010852e-08, 0.2314972675293e+00, 0.1385561574497e+01,
+      0.4316599090954e-08, 0.1012646782616e+00, 0.4176041334900e+01,
+      0.3283493323850e-08, 0.5233306881265e+01, 0.6287008313071e+01,
+      0.3164033542343e-08, 0.4005597257511e+01, 0.2099539292909e+02,
+      0.4159720956725e-08, 0.5365676242020e+01, 0.5905702259363e+01,
+      0.3565176892217e-08, 0.4284440620612e+01, 0.3932462625300e-02,
+      0.3514440950221e-08, 0.4270562636575e+01, 0.7335344340001e+01,
+      0.3540596871909e-08, 0.5953553201060e+01, 0.1234573916645e+02,
+      0.2960769905118e-08, 0.1115180417718e+01, 0.2670964694522e+02,
+      0.2962213739684e-08, 0.3863811918186e+01, 0.6408777551755e+00,
+
+      0.3883556700251e-08, 0.1268617928302e+01, 0.6660449441528e+01,
+      0.2919225516346e-08, 0.4908605223265e+01, 0.1375773836557e+01,
+      0.3115158863370e-08, 0.3744519976885e+01, 0.3802769619140e-01,
+      0.4099438144212e-08, 0.4173244670532e+01, 0.4480965020977e+02,
+      0.2899531858964e-08, 0.5910601428850e+01, 0.2059724391010e+02,
+      0.3289733429855e-08, 0.2488050078239e+01, 0.1081813534213e+02,
+      0.3933075612875e-08, 0.1122363652883e+01, 0.3773735910827e+00,
+      0.3021403764467e-08, 0.4951973724904e+01, 0.2982630633589e+02,
+      0.2798598949757e-08, 0.5117057845513e+01, 0.1937891852345e+02,
+      0.3397421302707e-08, 0.6104159180476e+01, 0.6923953605621e+01,
+
+      0.3720398002179e-08, 0.1184933429829e+01, 0.3066615496545e+02,
+      0.3598484186267e-08, 0.3505282086105e+01, 0.6147450479709e+01,
+      0.3694594027310e-08, 0.2286651088141e+01, 0.2636725487657e+01,
+      0.2680444152969e-08, 0.1871816775482e+00, 0.6816289982179e+01,
+      0.3497574865641e-08, 0.3143251755431e+01, 0.6418701221183e+01,
+      0.3130274129494e-08, 0.2462167316018e+01, 0.1235996607578e+02,
+      0.3241119069551e-08, 0.4256374004686e+01, 0.1652265972112e+02,
+      0.2601960842061e-08, 0.4970362941425e+01, 0.1045450126711e+02,
+      0.2690601527504e-08, 0.2372657824898e+01, 0.3163918923335e+00,
+      0.2908688152664e-08, 0.4232652627721e+01, 0.2828699048865e+02,
+
+      0.3120456131875e-08, 0.3925747001137e+00, 0.2195415756911e+02,
+      0.3148855423384e-08, 0.3093478330445e+01, 0.1172006883645e+02,
+      0.3051044261017e-08, 0.5560948248212e+01, 0.6055599646783e+01,
+      0.2826006876660e-08, 0.5072790310072e+01, 0.5120601093667e+01,
+      0.3100034191711e-08, 0.4998530231096e+01, 0.1799603123222e+02,
+      0.2398771640101e-08, 0.2561739802176e+01, 0.6255674361143e+01,
+      0.2384002842728e-08, 0.4087420284111e+01, 0.6310477339748e+01,
+      0.2842146517568e-08, 0.2515048217955e+01, 0.5469525544182e+01,
+      0.2847674371340e-08, 0.5235326497443e+01, 0.1034429499989e+02,
+      0.2903722140764e-08, 0.1088200795797e+01, 0.6510552054109e+01,
+
+      0.3187610710605e-08, 0.4710624424816e+01, 0.1693792562116e+03,
+      0.3048869992813e-08, 0.2857975896445e+00, 0.8390110365991e+01,
+      0.2860216950984e-08, 0.2241619020815e+01, 0.2243449970715e+00,
+      0.2701117683113e-08, 0.6651573305272e-01, 0.6129297044991e+01,
+      0.2509891590152e-08, 0.1285135324585e+01, 0.1044027435778e+02,
+      0.2623200252223e-08, 0.2981229834530e+00, 0.6436854655901e+01,
+      0.2622541669202e-08, 0.6122470726189e+01, 0.9380959548977e+01,
+      0.2818435667099e-08, 0.4251087148947e+01, 0.5934151399930e+01,
+      0.2365196797465e-08, 0.3465070460790e+01, 0.2470570524223e+02,
+      0.2358704646143e-08, 0.5791603815350e+01, 0.8671969964381e+01,
+
+      0.2388299481390e-08, 0.4142483772941e+01, 0.7096626156709e+01,
+      0.1996041217224e-08, 0.2101901889496e+01, 0.1727188400790e+02,
+      0.2687593060336e-08, 0.1526689456959e+01, 0.7075506709219e+02,
+      0.2618913670810e-08, 0.2397684236095e+01, 0.6632000300961e+01,
+      0.2571523050364e-08, 0.5751929456787e+00, 0.6206810014183e+01,
+      0.2582135006946e-08, 0.5595464352926e+01, 0.4873985990671e+02,
+      0.2372530190361e-08, 0.5092689490655e+01, 0.1590676413561e+02,
+      0.2357178484712e-08, 0.4444363527851e+01, 0.3097883698531e+01,
+      0.2451590394723e-08, 0.3108251687661e+01, 0.6612329252343e+00,
+      0.2370045949608e-08, 0.2608133861079e+01, 0.3459636466239e+02,
+
+      0.2268997267358e-08, 0.3639717753384e+01, 0.2844914056730e-01,
+      0.1731432137906e-08, 0.1741898445707e+00, 0.2019909489111e+02,
+      0.1629869741622e-08, 0.3902225646724e+01, 0.3035599730800e+02,
+      0.2206215801974e-08, 0.4971131250731e+01, 0.6281667977667e+01,
+      0.2205469554680e-08, 0.1677462357110e+01, 0.6284483723224e+01,
+      0.2148792362509e-08, 0.4236259604006e+01, 0.1980482729015e+02,
+      0.1873733657847e-08, 0.5926814998687e+01, 0.2876692439167e+02,
+      0.2026573758959e-08, 0.4349643351962e+01, 0.2449240616245e+02,
+      0.1807770325110e-08, 0.5700940482701e+01, 0.2045286941806e+02,
+      0.1881174408581e-08, 0.6601286363430e+00, 0.2358125818164e+02,
+
+      0.1368023671690e-08, 0.2211098592752e+01, 0.2473415438279e+02,
+      0.1720017916280e-08, 0.4942488551129e+01, 0.1679593901136e+03,
+      0.1702427665131e-08, 0.1452233856386e+01, 0.3338575901272e+03,
+      0.1414032510054e-08, 0.5525357721439e+01, 0.1624205518357e+03,
+      0.1652626045364e-08, 0.4108794283624e+01, 0.8956999012000e+02,
+      0.1642957769686e-08, 0.7344335209984e+00, 0.5267006960365e+02,
+      0.1614952403624e-08, 0.3541213951363e+01, 0.3332657872986e+02,
+      0.1535988291188e-08, 0.4031094072151e+01, 0.3852657435933e+02,
+      0.1593193738177e-08, 0.4185136203609e+01, 0.2282781046519e+03,
+      0.1074569126382e-08, 0.1720485636868e+01, 0.8397383534231e+02,
+
+      0.1074408214509e-08, 0.2758613420318e+01, 0.8401985929482e+02,
+      0.9700199670465e-09, 0.4216686842097e+01, 0.7826370942180e+02,
+      0.1258433517061e-08, 0.2575068876639e+00, 0.3115650189215e+03,
+      0.1240303229539e-08, 0.4800844956756e+00, 0.1784300471910e+03,
+      0.9018345948127e-09, 0.3896756361552e+00, 0.5886454391678e+02,
+      0.1135301432805e-08, 0.3700805023550e+00, 0.7842370451713e+02,
+      0.9215887951370e-09, 0.4364579276638e+01, 0.1014262087719e+03,
+      0.1055401054147e-08, 0.2156564222111e+01, 0.5660027930059e+02,
+      0.1008725979831e-08, 0.5454015785234e+01, 0.4245678405627e+02,
+      0.7217398104321e-09, 0.1597772562175e+01, 0.2457074661053e+03,
+
+      0.6912033134447e-09, 0.5824090621461e+01, 0.1679936946371e+03,
+      0.6833881523549e-09, 0.3578778482835e+01, 0.6053048899753e+02,
+      0.4887304205142e-09, 0.3724362812423e+01, 0.9656299901946e+02,
+      0.5173709754788e-09, 0.5422427507933e+01, 0.2442876000072e+03,
+      0.4671353097145e-09, 0.2396106924439e+01, 0.1435713242844e+03,
+      0.5652608439480e-09, 0.2804028838685e+01, 0.8365903305582e+02,
+      0.5604061331253e-09, 0.1638816006247e+01, 0.8433466158131e+02,
+      0.4712723365400e-09, 0.8979003224474e+00, 0.3164282286739e+03,
+      0.4909967465112e-09, 0.3210426725516e+01, 0.4059982187939e+03,
+      0.4771358267658e-09, 0.5308027211629e+01, 0.1805255418145e+03,
+
+      0.3943451445989e-09, 0.2195145341074e+01, 0.2568537517081e+03,
+      0.3952109120244e-09, 0.5081189491586e+01, 0.2449975330562e+03,
+      0.3788134594789e-09, 0.4345171264441e+01, 0.1568131045107e+03,
+      0.3738330190479e-09, 0.2613062847997e+01, 0.3948519331910e+03,
+      0.3099866678136e-09, 0.2846760817689e+01, 0.1547176098872e+03,
+      0.2002962716768e-09, 0.4921360989412e+01, 0.2268582385539e+03,
+      0.2198291338754e-09, 0.1130360117454e+00, 0.1658638954901e+03,
+      0.1491958330784e-09, 0.4228195232278e+01, 0.2219950288015e+03,
+      0.1475384076173e-09, 0.3005721811604e+00, 0.3052819430710e+03,
+      0.1661626624624e-09, 0.7830125621203e+00, 0.2526661704812e+03,
+
+      0.9015823460025e-10, 0.3807792942715e+01, 0.4171445043968e+03 };
+
+/* Sun-to-Earth, T^0, Y */
+   static const double e0y[] = {
+      0.9998921098898e+00, 0.1826583913846e+00, 0.6283075850446e+01,
+     -0.2442700893735e-01, 0.0000000000000e+00, 0.0000000000000e+00,
+      0.8352929742915e-02, 0.1395277998680e+00, 0.1256615170089e+02,
+      0.1046697300177e-03, 0.9641423109763e-01, 0.1884922755134e+02,
+      0.3110841876663e-04, 0.5381140401712e+01, 0.8399684731857e+02,
+      0.2570269094593e-04, 0.5301016407128e+01, 0.5296909721118e+00,
+      0.2147389623610e-04, 0.2662510869850e+01, 0.1577343543434e+01,
+      0.1680344384050e-04, 0.5207904119704e+01, 0.6279552690824e+01,
+      0.1679117312193e-04, 0.4582187486968e+01, 0.6286599010068e+01,
+      0.1440512068440e-04, 0.1900688517726e+01, 0.2352866153506e+01,
+
+      0.1135139664999e-04, 0.5273108538556e+01, 0.5223693906222e+01,
+      0.9345482571018e-05, 0.4503047687738e+01, 0.1203646072878e+02,
+      0.9007418719568e-05, 0.1605621059637e+01, 0.1021328554739e+02,
+      0.5671536712314e-05, 0.5812849070861e+00, 0.1059381944224e+01,
+      0.7451401861666e-05, 0.2807346794836e+01, 0.3981490189893e+00,
+      0.6393470057114e-05, 0.6029224133855e+01, 0.5753384878334e+01,
+      0.6814275881697e-05, 0.6472990145974e+00, 0.4705732307012e+01,
+      0.6113705628887e-05, 0.3813843419700e+01, 0.6812766822558e+01,
+      0.4503851367273e-05, 0.4527804370996e+01, 0.5884926831456e+01,
+      0.4522249141926e-05, 0.5991783029224e+01, 0.6256777527156e+01,
+
+      0.4501794307018e-05, 0.3798703844397e+01, 0.6309374173736e+01,
+      0.5514927480180e-05, 0.3961257833388e+01, 0.5507553240374e+01,
+      0.4062862799995e-05, 0.5256247296369e+01, 0.6681224869435e+01,
+      0.5414900429712e-05, 0.5499032014097e+01, 0.7755226100720e+00,
+      0.5463153987424e-05, 0.6173092454097e+01, 0.1414349524433e+02,
+      0.5071611859329e-05, 0.2870244247651e+01, 0.7860419393880e+01,
+      0.2195112094455e-05, 0.2952338617201e+01, 0.1150676975667e+02,
+      0.2279139233919e-05, 0.5951775132933e+01, 0.7058598460518e+01,
+      0.2278386100876e-05, 0.4845456398785e+01, 0.4694002934110e+01,
+      0.2559088003308e-05, 0.6945321117311e+00, 0.1216800268190e+02,
+
+      0.2561079286856e-05, 0.6167224608301e+01, 0.7099330490126e+00,
+      0.1792755796387e-05, 0.1400122509632e+01, 0.7962980379786e+00,
+      0.1818715656502e-05, 0.4703347611830e+01, 0.6283142985870e+01,
+      0.1818744924791e-05, 0.5086748900237e+01, 0.6283008715021e+01,
+      0.1554518791390e-05, 0.5331008042713e-01, 0.2513230340178e+02,
+      0.2063265737239e-05, 0.4283680484178e+01, 0.1179062909082e+02,
+      0.1497613520041e-05, 0.6074207826073e+01, 0.5486777812467e+01,
+      0.2000617940427e-05, 0.2501426281450e+01, 0.1778984560711e+02,
+      0.1289731195580e-05, 0.3646340599536e+01, 0.7079373888424e+01,
+      0.1282657998934e-05, 0.3232864804902e+01, 0.3738761453707e+01,
+
+      0.1528915968658e-05, 0.5581433416669e+01, 0.2132990797783e+00,
+      0.1187304098432e-05, 0.5453576453694e+01, 0.9437762937313e+01,
+      0.7842782928118e-06, 0.2823953922273e+00, 0.8827390247185e+01,
+      0.7352892280868e-06, 0.1124369580175e+01, 0.1589072916335e+01,
+      0.6570189360797e-06, 0.2089154042840e+01, 0.1176985366291e+02,
+      0.6324967590410e-06, 0.6704855581230e+00, 0.6262300422539e+01,
+      0.6298289872283e-06, 0.2836414855840e+01, 0.6303851278352e+01,
+      0.6476686465855e-06, 0.4852433866467e+00, 0.7113454667900e-02,
+      0.8587034651234e-06, 0.1453511005668e+01, 0.1672837615881e+03,
+      0.8068948788113e-06, 0.9224087798609e+00, 0.6069776770667e+01,
+
+      0.8353786011661e-06, 0.4631707184895e+01, 0.3340612434717e+01,
+      0.6009324532132e-06, 0.1829498827726e+01, 0.4136910472696e+01,
+      0.7558158559566e-06, 0.2588596800317e+01, 0.6496374930224e+01,
+      0.5809279504503e-06, 0.5516818853476e+00, 0.1097707878456e+02,
+      0.5374131950254e-06, 0.6275674734960e+01, 0.1194447056968e+01,
+      0.5711160507326e-06, 0.1091905956872e+01, 0.6282095334605e+01,
+      0.5710183170746e-06, 0.2415001635090e+01, 0.6284056366286e+01,
+      0.5144373590610e-06, 0.6020336443438e+01, 0.6290189305114e+01,
+      0.5103108927267e-06, 0.3775634564605e+01, 0.6275962395778e+01,
+      0.4960654697891e-06, 0.1073450946756e+01, 0.6127655567643e+01,
+
+      0.4786385689280e-06, 0.2431178012310e+01, 0.6438496133249e+01,
+      0.6109911263665e-06, 0.5343356157914e+01, 0.3154687086868e+01,
+      0.4839898944024e-06, 0.5830833594047e-01, 0.8018209333619e+00,
+      0.4734822623919e-06, 0.4536080134821e+01, 0.3128388763578e+01,
+      0.4834741473290e-06, 0.2585090489754e+00, 0.7084896783808e+01,
+      0.5134858581156e-06, 0.4213317172603e+01, 0.1235285262111e+02,
+      0.5064004264978e-06, 0.4814418806478e+00, 0.1185621865188e+02,
+      0.3753476772761e-06, 0.1599953399788e+01, 0.8429241228195e+01,
+      0.4935264014283e-06, 0.2157417556873e+01, 0.2544314396739e+01,
+      0.3950929600897e-06, 0.3359394184254e+01, 0.5481254917084e+01,
+
+      0.4895849789777e-06, 0.5165704376558e+01, 0.9225539266174e+01,
+      0.4215241688886e-06, 0.2065368800993e+01, 0.1726015463500e+02,
+      0.3796773731132e-06, 0.1468606346612e+01, 0.4265981595566e+00,
+      0.3114178142515e-06, 0.3615638079474e+01, 0.2146165377750e+01,
+      0.3260664220838e-06, 0.4417134922435e+01, 0.4164311961999e+01,
+      0.3976996123008e-06, 0.4700866883004e+01, 0.5856477690889e+01,
+      0.2801459672924e-06, 0.4538902060922e+01, 0.1256967486051e+02,
+      0.3638931868861e-06, 0.1334197991475e+01, 0.1807370494127e+02,
+      0.2487013269476e-06, 0.3749275558275e+01, 0.2629832328990e-01,
+      0.3034165481994e-06, 0.4236622030873e+00, 0.4535059491685e+01,
+
+      0.2676278825586e-06, 0.5970848007811e+01, 0.3930209696940e+01,
+      0.2764903818918e-06, 0.5194636754501e+01, 0.1256262854127e+02,
+      0.2485149930507e-06, 0.1002434207846e+01, 0.5088628793478e+01,
+      0.2199305540941e-06, 0.3066773098403e+01, 0.1255903824622e+02,
+      0.2571106500435e-06, 0.7588312459063e+00, 0.1336797263425e+02,
+      0.2049751817158e-06, 0.3444977434856e+01, 0.1137170464392e+02,
+      0.2599707296297e-06, 0.1873128542205e+01, 0.7143069561767e+02,
+      0.1785018072217e-06, 0.5015891306615e+01, 0.1748016358760e+01,
+      0.2324833891115e-06, 0.4618271239730e+01, 0.1831953657923e+02,
+      0.1709711119545e-06, 0.5300003455669e+01, 0.4933208510675e+01,
+
+      0.2107159351716e-06, 0.2229819815115e+01, 0.7477522907414e+01,
+      0.1750333080295e-06, 0.6161485880008e+01, 0.1044738781244e+02,
+      0.2000598210339e-06, 0.2967357299999e+01, 0.8031092209206e+01,
+      0.1380920248681e-06, 0.3027007923917e+01, 0.8635942003952e+01,
+      0.1412460470299e-06, 0.6037597163798e+01, 0.2942463415728e+01,
+      0.1888459803001e-06, 0.8561476243374e+00, 0.1561374759853e+03,
+      0.1788370542585e-06, 0.4869736290209e+01, 0.1592596075957e+01,
+      0.1360893296167e-06, 0.3626411886436e+01, 0.1309584267300e+02,
+      0.1506846530160e-06, 0.1550975377427e+01, 0.1649636139783e+02,
+      0.1800913376176e-06, 0.2075826033190e+01, 0.1729818233119e+02,
+
+      0.1436261390649e-06, 0.6148876420255e+01, 0.2042657109477e+02,
+      0.1220227114151e-06, 0.4382583879906e+01, 0.7632943190217e+01,
+      0.1337883603592e-06, 0.2036644327361e+01, 0.1213955354133e+02,
+      0.1159326650738e-06, 0.3892276994687e+01, 0.5331357529664e+01,
+      0.1352853128569e-06, 0.1447950649744e+01, 0.1673046366289e+02,
+      0.1433408296083e-06, 0.4457854692961e+01, 0.7342457794669e+01,
+      0.1234701666518e-06, 0.1538818147151e+01, 0.6279485555400e+01,
+      0.1234027192007e-06, 0.1968523220760e+01, 0.6286666145492e+01,
+      0.1244024091797e-06, 0.5779803499985e+01, 0.1511046609763e+02,
+      0.1097934945516e-06, 0.6210975221388e+00, 0.1098880815746e+02,
+
+      0.1254611329856e-06, 0.2591963807998e+01, 0.1572083878776e+02,
+      0.1158247286784e-06, 0.2483612812670e+01, 0.5729506548653e+01,
+      0.9039078252960e-07, 0.3857554579796e+01, 0.9623688285163e+01,
+      0.9108024978836e-07, 0.5826368512984e+01, 0.7234794171227e+01,
+      0.8887068108436e-07, 0.3475694573987e+01, 0.6148010737701e+01,
+      0.8632374035438e-07, 0.3059070488983e-01, 0.6418140963190e+01,
+      0.7893186992967e-07, 0.1583194837728e+01, 0.2118763888447e+01,
+      0.8297650201172e-07, 0.8519770534637e+00, 0.1471231707864e+02,
+      0.1019759578988e-06, 0.1319598738732e+00, 0.1349867339771e+01,
+      0.1010037696236e-06, 0.9937860115618e+00, 0.6836645152238e+01,
+
+      0.1047727548266e-06, 0.1382138405399e+01, 0.5999216516294e+01,
+      0.7351993881086e-07, 0.3833397851735e+01, 0.6040347114260e+01,
+      0.9868771092341e-07, 0.2124913814390e+01, 0.6566935184597e+01,
+      0.7007321959390e-07, 0.5946305343763e+01, 0.6525804586632e+01,
+      0.6861411679709e-07, 0.4574654977089e+01, 0.7238675589263e+01,
+      0.7554519809614e-07, 0.5949232686844e+01, 0.1253985337760e+02,
+      0.9541880448335e-07, 0.3495242990564e+01, 0.2122839202813e+02,
+      0.7185606722155e-07, 0.4310113471661e+01, 0.6245048154254e+01,
+      0.7131360871710e-07, 0.5480309323650e+01, 0.6321103546637e+01,
+      0.6651142021039e-07, 0.5411097713654e+01, 0.5327476111629e+01,
+
+      0.8538618213667e-07, 0.1827849973951e+01, 0.1101510648075e+02,
+      0.8634954288044e-07, 0.5443584943349e+01, 0.5643178611111e+01,
+      0.7449415051484e-07, 0.2011535459060e+01, 0.5368044267797e+00,
+      0.7421047599169e-07, 0.3464562529249e+01, 0.2354323048545e+02,
+      0.6140694354424e-07, 0.5657556228815e+01, 0.1296430071988e+02,
+      0.6353525143033e-07, 0.3463816593821e+01, 0.1990745094947e+01,
+      0.6221964013447e-07, 0.1532259498697e+01, 0.9517183207817e+00,
+      0.5852480257244e-07, 0.1375396598875e+01, 0.9555997388169e+00,
+      0.6398637498911e-07, 0.2405645801972e+01, 0.2407292145756e+02,
+      0.7039744069878e-07, 0.5397541799027e+01, 0.5225775174439e+00,
+
+      0.6977997694382e-07, 0.4762347105419e+01, 0.1097355562493e+02,
+      0.7460629558396e-07, 0.2711944692164e+01, 0.2200391463820e+02,
+      0.5376577536101e-07, 0.2352980430239e+01, 0.1431416805965e+02,
+      0.7530607893556e-07, 0.1943940180699e+01, 0.1842262939178e+02,
+      0.6822928971605e-07, 0.4337651846959e+01, 0.1554202828031e+00,
+      0.6220772380094e-07, 0.6716871369278e+00, 0.1845107853235e+02,
+      0.6586950799043e-07, 0.2229714460505e+01, 0.5216580451554e+01,
+      0.5873800565771e-07, 0.7627013920580e+00, 0.6398972393349e+00,
+      0.6264346929745e-07, 0.6202785478961e+00, 0.6277552955062e+01,
+      0.6257929115669e-07, 0.2886775596668e+01, 0.6288598745829e+01,
+
+      0.5343536033409e-07, 0.1977241012051e+01, 0.4690479774488e+01,
+      0.5587849781714e-07, 0.1922923484825e+01, 0.1551045220144e+01,
+      0.6905100845603e-07, 0.3570757164631e+01, 0.1030928125552e+00,
+      0.6178957066649e-07, 0.5197558947765e+01, 0.5230807360890e+01,
+      0.6187270224331e-07, 0.8193497368922e+00, 0.5650292065779e+01,
+      0.5385664291426e-07, 0.5406336665586e+01, 0.7771377146812e+02,
+      0.6329363917926e-07, 0.2837760654536e+01, 0.2608790314060e+02,
+      0.4546018761604e-07, 0.2933580297050e+01, 0.5535693017924e+00,
+      0.6196091049375e-07, 0.4157871494377e+01, 0.8467247584405e+02,
+      0.6159555108218e-07, 0.3211703561703e+01, 0.2394243902548e+03,
+
+      0.4995340539317e-07, 0.1459098102922e+01, 0.4732030630302e+01,
+      0.5457031243572e-07, 0.1430457676136e+01, 0.6179983037890e+01,
+      0.4863461418397e-07, 0.2196425916730e+01, 0.9027992316901e+02,
+      0.5342947626870e-07, 0.2086612890268e+01, 0.6386168663001e+01,
+      0.5674296648439e-07, 0.2760204966535e+01, 0.6915859635113e+01,
+      0.4745783120161e-07, 0.4245368971862e+01, 0.6282970628506e+01,
+      0.4745676961198e-07, 0.5544725787016e+01, 0.6283181072386e+01,
+      0.4049796869973e-07, 0.2213984363586e+01, 0.6254626709878e+01,
+      0.4248333596940e-07, 0.8075781952896e+00, 0.7875671926403e+01,
+      0.4027178070205e-07, 0.1293268540378e+01, 0.6311524991013e+01,
+
+      0.4066543943476e-07, 0.3986141175804e+01, 0.3634620989887e+01,
+      0.4858863787880e-07, 0.1276112738231e+01, 0.5760498333002e+01,
+      0.5277398263530e-07, 0.4916111741527e+01, 0.2515860172507e+02,
+      0.4105635656559e-07, 0.1725805864426e+01, 0.6709674010002e+01,
+      0.4376781925772e-07, 0.2243642442106e+01, 0.6805653367890e+01,
+      0.3235827894693e-07, 0.3614135118271e+01, 0.1066495398892e+01,
+      0.3073244740308e-07, 0.2460873393460e+01, 0.5863591145557e+01,
+      0.3088609271373e-07, 0.5678431771790e+01, 0.9917696840332e+01,
+      0.3393022279836e-07, 0.3814017477291e+01, 0.1391601904066e+02,
+      0.3038686508802e-07, 0.4660216229171e+01, 0.1256621883632e+02,
+
+      0.4019677752497e-07, 0.5906906243735e+01, 0.1334167431096e+02,
+      0.3288834998232e-07, 0.9536146445882e+00, 0.1620077269078e+02,
+      0.3889973794631e-07, 0.3942205097644e+01, 0.7478166569050e-01,
+      0.3050438987141e-07, 0.1624810271286e+01, 0.1805292951336e+02,
+      0.3601142564638e-07, 0.4030467142575e+01, 0.6208294184755e+01,
+      0.3689015557141e-07, 0.3648878818694e+01, 0.5966683958112e+01,
+      0.3563471893565e-07, 0.5749584017096e+01, 0.6357857516136e+01,
+      0.2776183170667e-07, 0.2630124187070e+01, 0.3523159621801e-02,
+      0.2922350530341e-07, 0.1790346403629e+01, 0.1272157198369e+02,
+      0.3511076917302e-07, 0.6142198301611e+01, 0.6599467742779e+01,
+
+      0.3619351007632e-07, 0.1432421386492e+01, 0.6019991944201e+01,
+      0.2561254711098e-07, 0.2302822475792e+01, 0.1259245002418e+02,
+      0.2626903942920e-07, 0.8660470994571e+00, 0.6702560555334e+01,
+      0.2550187397083e-07, 0.6069721995383e+01, 0.1057540660594e+02,
+      0.2535873526138e-07, 0.1079020331795e-01, 0.3141537925223e+02,
+      0.3519786153847e-07, 0.3809066902283e+01, 0.2505706758577e+03,
+      0.3424651492873e-07, 0.2075435114417e+01, 0.6546159756691e+01,
+      0.2372676630861e-07, 0.2057803120154e+01, 0.2388894113936e+01,
+      0.2710980779541e-07, 0.1510068488010e+01, 0.1202934727411e+02,
+      0.3038710889704e-07, 0.5043617528901e+01, 0.1256608456547e+02,
+
+      0.2220364130585e-07, 0.3694793218205e+01, 0.1336244973887e+02,
+      0.3025880825460e-07, 0.5450618999049e-01, 0.2908881142201e+02,
+      0.2784493486864e-07, 0.3381164084502e+01, 0.1494531617769e+02,
+      0.2294414142438e-07, 0.4382309025210e+01, 0.6076890225335e+01,
+      0.2012723294724e-07, 0.9142212256518e+00, 0.6262720680387e+01,
+      0.2036357831958e-07, 0.5676172293154e+01, 0.4701116388778e+01,
+      0.2003474823288e-07, 0.2592767977625e+01, 0.6303431020504e+01,
+      0.2207144900109e-07, 0.5404976271180e+01, 0.6489261475556e+01,
+      0.2481664905135e-07, 0.4373284587027e+01, 0.1204357418345e+02,
+      0.2674949182295e-07, 0.5859182188482e+01, 0.4590910121555e+01,
+
+      0.2450554720322e-07, 0.4555381557451e+01, 0.1495633313810e+00,
+      0.2601975986457e-07, 0.3933165584959e+01, 0.1965104848470e+02,
+      0.2199860022848e-07, 0.5227977189087e+01, 0.1351787002167e+02,
+      0.2448121172316e-07, 0.4858060353949e+01, 0.1162474756779e+01,
+      0.1876014864049e-07, 0.5690546553605e+01, 0.6279194432410e+01,
+      0.1874513219396e-07, 0.4099539297446e+01, 0.6286957268481e+01,
+      0.2156380842559e-07, 0.4382594769913e+00, 0.1813929450232e+02,
+      0.1981691240061e-07, 0.1829784152444e+01, 0.4686889479442e+01,
+      0.2329992648539e-07, 0.2836254278973e+01, 0.1002183730415e+02,
+      0.1765184135302e-07, 0.2803494925833e+01, 0.4292330755499e+01,
+
+      0.2436368366085e-07, 0.2836897959677e+01, 0.9514313292143e+02,
+      0.2164089203889e-07, 0.6127522446024e+01, 0.6037244212485e+01,
+      0.1847755034221e-07, 0.3683163635008e+01, 0.2427287361862e+00,
+      0.1674798769966e-07, 0.3316993867246e+00, 0.1311972100268e+02,
+      0.2222542124356e-07, 0.8294097805480e+00, 0.1266924451345e+02,
+      0.2071074505925e-07, 0.3659492220261e+01, 0.6528907488406e+01,
+      0.1608224471835e-07, 0.4774492067182e+01, 0.1352175143971e+02,
+      0.1857583439071e-07, 0.2873120597682e+01, 0.8662240327241e+01,
+      0.1793018836159e-07, 0.5282441177929e+00, 0.6819880277225e+01,
+      0.1575391221692e-07, 0.1320789654258e+01, 0.1102062672231e+00,
+
+      0.1840132009557e-07, 0.1917110916256e+01, 0.6514761976723e+02,
+      0.1760917288281e-07, 0.2972635937132e+01, 0.5746271423666e+01,
+      0.1561779518516e-07, 0.4372569261981e+01, 0.6272439236156e+01,
+      0.1558687885205e-07, 0.5416424926425e+01, 0.6293712464735e+01,
+      0.1951359382579e-07, 0.3094448898752e+01, 0.2301353951334e+02,
+      0.1569144275614e-07, 0.2802103689808e+01, 0.1765478049437e+02,
+      0.1479130389462e-07, 0.2136435020467e+01, 0.2077542790660e-01,
+      0.1467828510764e-07, 0.7072627435674e+00, 0.1052268489556e+01,
+      0.1627627337440e-07, 0.3947607143237e+01, 0.6327837846670e+00,
+      0.1503498479758e-07, 0.4079248909190e+01, 0.7626583626240e-01,
+
+      0.1297967708237e-07, 0.6269637122840e+01, 0.1149965630200e+02,
+      0.1374416896634e-07, 0.4175657970702e+01, 0.6016468784579e+01,
+      0.1783812325219e-07, 0.1476540547560e+01, 0.3301902111895e+02,
+      0.1525884228756e-07, 0.4653477715241e+01, 0.9411464614024e+01,
+      0.1451067396763e-07, 0.2573001128225e+01, 0.1277945078067e+02,
+      0.1297713111950e-07, 0.5612799618771e+01, 0.6549682916313e+01,
+      0.1462784012820e-07, 0.4189661623870e+01, 0.1863592847156e+02,
+      0.1384185980007e-07, 0.2656915472196e+01, 0.2379164476796e+01,
+      0.1221497599801e-07, 0.5612515760138e+01, 0.1257326515556e+02,
+      0.1560574525896e-07, 0.4783414317919e+01, 0.1887552587463e+02,
+
+      0.1544598372036e-07, 0.2694431138063e+01, 0.1820933031200e+02,
+      0.1531678928696e-07, 0.4105103489666e+01, 0.2593412433514e+02,
+      0.1349321503795e-07, 0.3082437194015e+00, 0.5120601093667e+01,
+      0.1252030290917e-07, 0.6124072334087e+01, 0.6993008899458e+01,
+      0.1459243816687e-07, 0.3733103981697e+01, 0.3813291813120e-01,
+      0.1226103625262e-07, 0.1267127706817e+01, 0.2435678079171e+02,
+      0.1019449641504e-07, 0.4367790112269e+01, 0.1725663147538e+02,
+      0.1380789433607e-07, 0.3387201768700e+01, 0.2458316379602e+00,
+      0.1019453421658e-07, 0.9204143073737e+00, 0.6112403035119e+01,
+      0.1297929434405e-07, 0.5786874896426e+01, 0.1249137003520e+02,
+
+      0.9912677786097e-08, 0.3164232870746e+01, 0.6247047890016e+01,
+      0.9829386098599e-08, 0.2586762413351e+01, 0.6453748665772e+01,
+      0.1226807746104e-07, 0.6239068436607e+01, 0.5429879531333e+01,
+      0.1192691755997e-07, 0.1867380051424e+01, 0.6290122169689e+01,
+      0.9836499227081e-08, 0.3424716293727e+00, 0.6319103810876e+01,
+      0.9642862564285e-08, 0.5661372990657e+01, 0.8273820945392e+01,
+      0.1165184404862e-07, 0.5768367239093e+01, 0.1778273215245e+02,
+      0.1175794418818e-07, 0.1657351222943e+01, 0.6276029531202e+01,
+      0.1018948635601e-07, 0.6458292350865e+00, 0.1254537627298e+02,
+      0.9500383606676e-08, 0.1054306140741e+01, 0.1256517118505e+02,
+
+      0.1227512202906e-07, 0.2505278379114e+01, 0.2248384854122e+02,
+      0.9664792009993e-08, 0.4289737277000e+01, 0.6259197520765e+01,
+      0.9613285666331e-08, 0.5500597673141e+01, 0.6306954180126e+01,
+      0.1117906736211e-07, 0.2361405953468e+01, 0.1779695906178e+02,
+      0.9611378640782e-08, 0.2851310576269e+01, 0.2061856251104e+00,
+      0.8845354852370e-08, 0.6208777705343e+01, 0.1692165728891e+01,
+      0.1054046966600e-07, 0.5413091423934e+01, 0.2204125344462e+00,
+      0.1215539124483e-07, 0.5613969479755e+01, 0.8257698122054e+02,
+      0.9932460955209e-08, 0.1106124877015e+01, 0.1017725758696e+02,
+      0.8785804715043e-08, 0.2869224476477e+01, 0.9491756770005e+00,
+
+      0.8538084097562e-08, 0.6159640899344e+01, 0.6393282117669e+01,
+      0.8648994369529e-08, 0.1374901198784e+01, 0.4804209201333e+01,
+      0.1039063219067e-07, 0.5171080641327e+01, 0.1550861511662e+02,
+      0.8867983926439e-08, 0.8317320304902e+00, 0.3903911373650e+01,
+      0.8327495955244e-08, 0.3605591969180e+01, 0.6172869583223e+01,
+      0.9243088356133e-08, 0.6114299196843e+01, 0.6267823317922e+01,
+      0.9205657357835e-08, 0.3675153683737e+01, 0.6298328382969e+01,
+      0.1033269714606e-07, 0.3313328813024e+01, 0.5573142801433e+01,
+      0.8001706275552e-08, 0.2019980960053e+01, 0.2648454860559e+01,
+      0.9171858254191e-08, 0.8992015524177e+00, 0.1498544001348e+03,
+
+      0.1075327150242e-07, 0.2898669963648e+01, 0.3694923081589e+02,
+      0.9884866689828e-08, 0.4946715904478e+01, 0.1140367694411e+02,
+      0.9541835576677e-08, 0.2371787888469e+01, 0.1256713221673e+02,
+      0.7739903376237e-08, 0.2213775190612e+01, 0.7834121070590e+01,
+      0.7311962684106e-08, 0.3429378787739e+01, 0.1192625446156e+02,
+      0.9724904869624e-08, 0.6195878564404e+01, 0.2280573557157e+02,
+      0.9251628983612e-08, 0.6511509527390e+00, 0.2787043132925e+01,
+      0.7320763787842e-08, 0.6001083639421e+01, 0.6282655592598e+01,
+      0.7320296650962e-08, 0.3789073265087e+01, 0.6283496108294e+01,
+      0.7947032271039e-08, 0.1059659582204e+01, 0.1241073141809e+02,
+
+      0.9005277053115e-08, 0.1280315624361e+01, 0.6281591679874e+01,
+      0.8995601652048e-08, 0.2224439106766e+01, 0.6284560021018e+01,
+      0.8288040568796e-08, 0.5234914433867e+01, 0.1241658836951e+02,
+      0.6359381347255e-08, 0.4137989441490e+01, 0.1596186371003e+01,
+      0.8699572228626e-08, 0.1758411009497e+01, 0.6133512519065e+01,
+      0.6456797542736e-08, 0.5919285089994e+01, 0.1685848245639e+02,
+      0.7424573475452e-08, 0.5414616938827e+01, 0.4061219149443e+01,
+      0.7235671196168e-08, 0.1496516557134e+01, 0.1610006857377e+03,
+      0.8104015182733e-08, 0.1919918242764e+01, 0.8460828644453e+00,
+      0.8098576535937e-08, 0.3819615855458e+01, 0.3894181736510e+01,
+
+      0.6275292346625e-08, 0.6244264115141e+01, 0.8531963191132e+00,
+      0.6052432989112e-08, 0.5037731872610e+00, 0.1567108171867e+02,
+      0.5705651535817e-08, 0.2984557271995e+01, 0.1258692712880e+02,
+      0.5789650115138e-08, 0.6087038140697e+01, 0.1193336791622e+02,
+      0.5512132153377e-08, 0.5855668994076e+01, 0.1232342296471e+02,
+      0.7388890819102e-08, 0.2443128574740e+01, 0.4907302013889e+01,
+      0.5467593991798e-08, 0.3017561234194e+01, 0.1884211409667e+02,
+      0.6388519802999e-08, 0.5887386712935e+01, 0.5217580628120e+02,
+      0.6106777149944e-08, 0.3483461059895e+00, 0.1422690933580e-01,
+      0.7383420275489e-08, 0.5417387056707e+01, 0.2358125818164e+02,
+
+      0.5505208141738e-08, 0.2848193644783e+01, 0.1151388321134e+02,
+      0.6310757462877e-08, 0.2349882520828e+01, 0.1041998632314e+02,
+      0.6166904929691e-08, 0.5728575944077e+00, 0.6151533897323e+01,
+      0.5263442042754e-08, 0.4495796125937e+01, 0.1885275071096e+02,
+      0.5591828082629e-08, 0.1355441967677e+01, 0.4337116142245e+00,
+      0.5397051680497e-08, 0.1673422864307e+01, 0.6286362197481e+01,
+      0.5396992745159e-08, 0.1833502206373e+01, 0.6279789503410e+01,
+      0.6572913000726e-08, 0.3331122065824e+01, 0.1176433076753e+02,
+      0.5123421866413e-08, 0.2165327142679e+01, 0.1245594543367e+02,
+      0.5930495725999e-08, 0.2931146089284e+01, 0.6414617803568e+01,
+
+      0.6431797403933e-08, 0.4134407994088e+01, 0.1350651127443e+00,
+      0.5003182207604e-08, 0.3805420303749e+01, 0.1096996532989e+02,
+      0.5587731032504e-08, 0.1082469260599e+01, 0.6062663316000e+01,
+      0.5935263407816e-08, 0.8384333678401e+00, 0.5326786718777e+01,
+      0.4756019827760e-08, 0.3552588749309e+01, 0.3104930017775e+01,
+      0.6599951172637e-08, 0.4320826409528e+01, 0.4087944051283e+02,
+      0.5902606868464e-08, 0.4811879454445e+01, 0.5849364236221e+01,
+      0.5921147809031e-08, 0.9942628922396e-01, 0.1581959461667e+01,
+      0.5505382581266e-08, 0.2466557607764e+01, 0.6503488384892e+01,
+      0.5353771071862e-08, 0.4551978748683e+01, 0.1735668374386e+03,
+
+      0.5063282210946e-08, 0.5710812312425e+01, 0.1248988586463e+02,
+      0.5926120403383e-08, 0.1333998428358e+01, 0.2673594526851e+02,
+      0.5211016176149e-08, 0.4649315360760e+01, 0.2460261242967e+02,
+      0.5347075084894e-08, 0.5512754081205e+01, 0.4171425416666e+01,
+      0.4872609773574e-08, 0.1308025299938e+01, 0.5333900173445e+01,
+      0.4727711321420e-08, 0.2144908368062e+01, 0.7232251527446e+01,
+      0.6029426018652e-08, 0.5567259412084e+01, 0.3227113045244e+03,
+      0.4321485284369e-08, 0.5230667156451e+01, 0.9388005868221e+01,
+      0.4476406760553e-08, 0.6134081115303e+01, 0.5547199253223e+01,
+      0.5835268277420e-08, 0.4783808492071e+01, 0.7285056171570e+02,
+
+      0.5172183602748e-08, 0.5161817911099e+01, 0.1884570439172e+02,
+      0.5693571465184e-08, 0.1381646203111e+01, 0.9723862754494e+02,
+      0.4060634965349e-08, 0.3876705259495e+00, 0.4274518229222e+01,
+      0.3967398770473e-08, 0.5029491776223e+01, 0.3496032717521e+01,
+      0.3943754005255e-08, 0.1923162955490e+01, 0.6244942932314e+01,
+      0.4781323427824e-08, 0.4633332586423e+01, 0.2929661536378e+02,
+      0.3871483781204e-08, 0.1616650009743e+01, 0.6321208768577e+01,
+      0.5141741733997e-08, 0.9817316704659e-01, 0.1232032006293e+02,
+      0.4002385978497e-08, 0.3656161212139e+01, 0.7018952447668e+01,
+      0.4901092604097e-08, 0.4404098713092e+01, 0.1478866649112e+01,
+
+      0.3740932630345e-08, 0.5181188732639e+00, 0.6922973089781e+01,
+      0.4387283718538e-08, 0.3254859566869e+01, 0.2331413144044e+03,
+      0.5019197802033e-08, 0.3086773224677e+01, 0.1715706182245e+02,
+      0.3834931695175e-08, 0.2797882673542e+01, 0.1491901785440e+02,
+      0.3760413942497e-08, 0.2892676280217e+01, 0.1726726808967e+02,
+      0.3719717204628e-08, 0.5861046025739e+01, 0.6297302759782e+01,
+      0.4145623530149e-08, 0.2168239627033e+01, 0.1376059875786e+02,
+      0.3932788425380e-08, 0.6271811124181e+01, 0.7872148766781e+01,
+      0.3686377476857e-08, 0.3936853151404e+01, 0.6268848941110e+01,
+      0.3779077950339e-08, 0.1404148734043e+01, 0.4157198507331e+01,
+
+      0.4091334550598e-08, 0.2452436180854e+01, 0.9779108567966e+01,
+      0.3926694536146e-08, 0.6102292739040e+01, 0.1098419223922e+02,
+      0.4841000253289e-08, 0.6072760457276e+01, 0.1252801878276e+02,
+      0.4949340130240e-08, 0.1154832815171e+01, 0.1617106187867e+03,
+      0.3761557737360e-08, 0.5527545321897e+01, 0.3185192151914e+01,
+      0.3647396268188e-08, 0.1525035688629e+01, 0.6271346477544e+01,
+      0.3932405074189e-08, 0.5570681040569e+01, 0.2139354194808e+02,
+      0.3631322501141e-08, 0.1981240601160e+01, 0.6294805223347e+01,
+      0.4130007425139e-08, 0.2050060880201e+01, 0.2195415756911e+02,
+      0.4433905965176e-08, 0.3277477970321e+01, 0.7445550607224e+01,
+
+      0.3851814176947e-08, 0.5210690074886e+01, 0.9562891316684e+00,
+      0.3485807052785e-08, 0.6653274904611e+00, 0.1161697602389e+02,
+      0.3979772816991e-08, 0.1767941436148e+01, 0.2277943724828e+02,
+      0.3402607460500e-08, 0.3421746306465e+01, 0.1087398597200e+02,
+      0.4049993000926e-08, 0.1127144787547e+01, 0.3163918923335e+00,
+      0.3420511182382e-08, 0.4214794779161e+01, 0.1362553364512e+02,
+      0.3640772365012e-08, 0.5324905497687e+01, 0.1725304118033e+02,
+      0.3323037987501e-08, 0.6135761838271e+01, 0.6279143387820e+01,
+      0.4503141663637e-08, 0.1802305450666e+01, 0.1385561574497e+01,
+      0.4314560055588e-08, 0.4812299731574e+01, 0.4176041334900e+01,
+
+      0.3294226949110e-08, 0.3657547059723e+01, 0.6287008313071e+01,
+      0.3215657197281e-08, 0.4866676894425e+01, 0.5749861718712e+01,
+      0.4129362656266e-08, 0.3809342558906e+01, 0.5905702259363e+01,
+      0.3137762976388e-08, 0.2494635174443e+01, 0.2099539292909e+02,
+      0.3514010952384e-08, 0.2699961831678e+01, 0.7335344340001e+01,
+      0.3327607571530e-08, 0.3318457714816e+01, 0.5436992986000e+01,
+      0.3541066946675e-08, 0.4382703582466e+01, 0.1234573916645e+02,
+      0.3216179847052e-08, 0.5271066317054e+01, 0.3802769619140e-01,
+      0.2959045059570e-08, 0.5819591585302e+01, 0.2670964694522e+02,
+      0.3884040326665e-08, 0.5980934960428e+01, 0.6660449441528e+01,
+
+      0.2922027539886e-08, 0.3337290282483e+01, 0.1375773836557e+01,
+      0.4110846382042e-08, 0.5742978187327e+01, 0.4480965020977e+02,
+      0.2934508411032e-08, 0.2278075804200e+01, 0.6408777551755e+00,
+      0.3966896193000e-08, 0.5835747858477e+01, 0.3773735910827e+00,
+      0.3286695827610e-08, 0.5838898193902e+01, 0.3932462625300e-02,
+      0.3720643094196e-08, 0.1122212337858e+01, 0.1646033343740e+02,
+      0.3285508906174e-08, 0.9182250996416e+00, 0.1081813534213e+02,
+      0.3753880575973e-08, 0.5174761973266e+01, 0.5642198095270e+01,
+      0.3022129385587e-08, 0.3381611020639e+01, 0.2982630633589e+02,
+      0.2798569205621e-08, 0.3546193723922e+01, 0.1937891852345e+02,
+
+      0.3397872070505e-08, 0.4533203197934e+01, 0.6923953605621e+01,
+      0.3708099772977e-08, 0.2756168198616e+01, 0.3066615496545e+02,
+      0.3599283541510e-08, 0.1934395469918e+01, 0.6147450479709e+01,
+      0.3688702753059e-08, 0.7149920971109e+00, 0.2636725487657e+01,
+      0.2681084724003e-08, 0.4899819493154e+01, 0.6816289982179e+01,
+      0.3495993460759e-08, 0.1572418915115e+01, 0.6418701221183e+01,
+      0.3130770324995e-08, 0.8912190180489e+00, 0.1235996607578e+02,
+      0.2744353821941e-08, 0.3800821940055e+01, 0.2059724391010e+02,
+      0.2842732906341e-08, 0.2644717440029e+01, 0.2828699048865e+02,
+      0.3046882682154e-08, 0.3987793020179e+01, 0.6055599646783e+01,
+
+      0.2399072455143e-08, 0.9908826440764e+00, 0.6255674361143e+01,
+      0.2384306274204e-08, 0.2516149752220e+01, 0.6310477339748e+01,
+      0.2977324500559e-08, 0.5849195642118e+01, 0.1652265972112e+02,
+      0.3062835258972e-08, 0.1681660100162e+01, 0.1172006883645e+02,
+      0.3109682589231e-08, 0.5804143987737e+00, 0.2751146787858e+02,
+      0.2903920355299e-08, 0.5800768280123e+01, 0.6510552054109e+01,
+      0.2823221989212e-08, 0.9241118370216e+00, 0.5469525544182e+01,
+      0.3187949696649e-08, 0.3139776445735e+01, 0.1693792562116e+03,
+      0.2922559771655e-08, 0.3549440782984e+01, 0.2630839062450e+00,
+      0.2436302066603e-08, 0.4735540696319e+01, 0.3946258593675e+00,
+
+      0.3049473043606e-08, 0.4998289124561e+01, 0.8390110365991e+01,
+      0.2863682575784e-08, 0.6709515671102e+00, 0.2243449970715e+00,
+      0.2641750517966e-08, 0.5410978257284e+01, 0.2986433403208e+02,
+      0.2704093466243e-08, 0.4778317207821e+01, 0.6129297044991e+01,
+      0.2445522177011e-08, 0.6009020662222e+01, 0.1171295538178e+02,
+      0.2623608810230e-08, 0.5010449777147e+01, 0.6436854655901e+01,
+      0.2079259704053e-08, 0.5980943768809e+01, 0.2019909489111e+02,
+      0.2820225596771e-08, 0.2679965110468e+01, 0.5934151399930e+01,
+      0.2365221950927e-08, 0.1894231148810e+01, 0.2470570524223e+02,
+      0.2359682077149e-08, 0.4220752950780e+01, 0.8671969964381e+01,
+
+      0.2387577137206e-08, 0.2571783940617e+01, 0.7096626156709e+01,
+      0.1982102089816e-08, 0.5169765997119e+00, 0.1727188400790e+02,
+      0.2687502389925e-08, 0.6239078264579e+01, 0.7075506709219e+02,
+      0.2207751669135e-08, 0.2031184412677e+01, 0.4377611041777e+01,
+      0.2618370214274e-08, 0.8266079985979e+00, 0.6632000300961e+01,
+      0.2591951887361e-08, 0.8819350522008e+00, 0.4873985990671e+02,
+      0.2375055656248e-08, 0.3520944177789e+01, 0.1590676413561e+02,
+      0.2472019978911e-08, 0.1551431908671e+01, 0.6612329252343e+00,
+      0.2368157127199e-08, 0.4178610147412e+01, 0.3459636466239e+02,
+      0.1764846605693e-08, 0.1506764000157e+01, 0.1980094587212e+02,
+
+      0.2291769608798e-08, 0.2118250611782e+01, 0.2844914056730e-01,
+      0.2209997316943e-08, 0.3363255261678e+01, 0.2666070658668e+00,
+      0.2292699097923e-08, 0.4200423956460e+00, 0.1484170571900e-02,
+      0.1629683015329e-08, 0.2331362582487e+01, 0.3035599730800e+02,
+      0.2206492862426e-08, 0.3400274026992e+01, 0.6281667977667e+01,
+      0.2205746568257e-08, 0.1066051230724e+00, 0.6284483723224e+01,
+      0.2026310767991e-08, 0.2779066487979e+01, 0.2449240616245e+02,
+      0.1762977622163e-08, 0.9951450691840e+00, 0.2045286941806e+02,
+      0.1368535049606e-08, 0.6402447365817e+00, 0.2473415438279e+02,
+      0.1720598775450e-08, 0.2303524214705e+00, 0.1679593901136e+03,
+
+      0.1702429015449e-08, 0.6164622655048e+01, 0.3338575901272e+03,
+      0.1414033197685e-08, 0.3954561185580e+01, 0.1624205518357e+03,
+      0.1573768958043e-08, 0.2028286308984e+01, 0.3144167757552e+02,
+      0.1650705184447e-08, 0.2304040666128e+01, 0.5267006960365e+02,
+      0.1651087618855e-08, 0.2538461057280e+01, 0.8956999012000e+02,
+      0.1616409518983e-08, 0.5111054348152e+01, 0.3332657872986e+02,
+      0.1537175173581e-08, 0.5601130666603e+01, 0.3852657435933e+02,
+      0.1593191980553e-08, 0.2614340453411e+01, 0.2282781046519e+03,
+      0.1499480170643e-08, 0.3624721577264e+01, 0.2823723341956e+02,
+      0.1493807843235e-08, 0.4214569879008e+01, 0.2876692439167e+02,
+
+      0.1074571199328e-08, 0.1496911744704e+00, 0.8397383534231e+02,
+      0.1074406983417e-08, 0.1187817671922e+01, 0.8401985929482e+02,
+      0.9757576855851e-09, 0.2655703035858e+01, 0.7826370942180e+02,
+      0.1258432887565e-08, 0.4969896184844e+01, 0.3115650189215e+03,
+      0.1240336343282e-08, 0.5192460776926e+01, 0.1784300471910e+03,
+      0.9016107005164e-09, 0.1960356923057e+01, 0.5886454391678e+02,
+      0.1135392360918e-08, 0.5082427809068e+01, 0.7842370451713e+02,
+      0.9216046089565e-09, 0.2793775037273e+01, 0.1014262087719e+03,
+      0.1061276615030e-08, 0.3726144311409e+01, 0.5660027930059e+02,
+      0.1010110596263e-08, 0.7404080708937e+00, 0.4245678405627e+02,
+
+      0.7217424756199e-09, 0.2697449980577e-01, 0.2457074661053e+03,
+      0.6912003846756e-09, 0.4253296276335e+01, 0.1679936946371e+03,
+      0.6871814664847e-09, 0.5148072412354e+01, 0.6053048899753e+02,
+      0.4887158016343e-09, 0.2153581148294e+01, 0.9656299901946e+02,
+      0.5161802866314e-09, 0.3852750634351e+01, 0.2442876000072e+03,
+      0.5652599559057e-09, 0.1233233356270e+01, 0.8365903305582e+02,
+      0.4710812608586e-09, 0.5610486976767e+01, 0.3164282286739e+03,
+      0.4909977500324e-09, 0.1639629524123e+01, 0.4059982187939e+03,
+      0.4772641839378e-09, 0.3737100368583e+01, 0.1805255418145e+03,
+      0.4487562567153e-09, 0.1158417054478e+00, 0.8433466158131e+02,
+
+      0.3943441230497e-09, 0.6243502862796e+00, 0.2568537517081e+03,
+      0.3952236913598e-09, 0.3510377382385e+01, 0.2449975330562e+03,
+      0.3788898363417e-09, 0.5916128302299e+01, 0.1568131045107e+03,
+      0.3738329328831e-09, 0.1042266763456e+01, 0.3948519331910e+03,
+      0.2451199165151e-09, 0.1166788435700e+01, 0.1435713242844e+03,
+      0.2436734402904e-09, 0.3254726114901e+01, 0.2268582385539e+03,
+      0.2213605274325e-09, 0.1687210598530e+01, 0.1658638954901e+03,
+      0.1491521204829e-09, 0.2657541786794e+01, 0.2219950288015e+03,
+      0.1474995329744e-09, 0.5013089805819e+01, 0.3052819430710e+03,
+      0.1661939475656e-09, 0.5495315428418e+01, 0.2526661704812e+03,
+
+      0.9015946748003e-10, 0.2236989966505e+01, 0.4171445043968e+03 };
+
+/* Sun-to-Earth, T^0, Z */
+   static const double e0z[] = {
+      0.2796207639075e-05, 0.3198701560209e+01, 0.8433466158131e+02,
+      0.1016042198142e-05, 0.5422360395913e+01, 0.5507553240374e+01,
+      0.8044305033647e-06, 0.3880222866652e+01, 0.5223693906222e+01,
+      0.4385347909274e-06, 0.3704369937468e+01, 0.2352866153506e+01,
+      0.3186156414906e-06, 0.3999639363235e+01, 0.1577343543434e+01,
+      0.2272412285792e-06, 0.3984738315952e+01, 0.1047747311755e+01,
+      0.1645620103007e-06, 0.3565412516841e+01, 0.5856477690889e+01,
+      0.1815836921166e-06, 0.4984507059020e+01, 0.6283075850446e+01,
+      0.1447461676364e-06, 0.3702753570108e+01, 0.9437762937313e+01,
+      0.1430760876382e-06, 0.3409658712357e+01, 0.1021328554739e+02,
+
+      0.1120445753226e-06, 0.4829561570246e+01, 0.1414349524433e+02,
+      0.1090232840797e-06, 0.2080729178066e+01, 0.6812766822558e+01,
+      0.9715727346551e-07, 0.3476295881948e+01, 0.4694002934110e+01,
+      0.1036267136217e-06, 0.4056639536648e+01, 0.7109288135493e+02,
+      0.8752665271340e-07, 0.4448159519911e+01, 0.5753384878334e+01,
+      0.8331864956004e-07, 0.4991704044208e+01, 0.7084896783808e+01,
+      0.6901658670245e-07, 0.4325358994219e+01, 0.6275962395778e+01,
+      0.9144536848998e-07, 0.1141826375363e+01, 0.6620890113188e+01,
+      0.7205085037435e-07, 0.3624344170143e+01, 0.5296909721118e+00,
+      0.7697874654176e-07, 0.5554257458998e+01, 0.1676215758509e+03,
+
+      0.5197545738384e-07, 0.6251760961735e+01, 0.1807370494127e+02,
+      0.5031345378608e-07, 0.2497341091913e+01, 0.4705732307012e+01,
+      0.4527110205840e-07, 0.2335079920992e+01, 0.6309374173736e+01,
+      0.4753355798089e-07, 0.7094148987474e+00, 0.5884926831456e+01,
+      0.4296951977516e-07, 0.1101916352091e+01, 0.6681224869435e+01,
+      0.3855341568387e-07, 0.1825495405486e+01, 0.5486777812467e+01,
+      0.5253930970990e-07, 0.4424740687208e+01, 0.7860419393880e+01,
+      0.4024630496471e-07, 0.5120498157053e+01, 0.1336797263425e+02,
+      0.4061069791453e-07, 0.6029771435451e+01, 0.3930209696940e+01,
+      0.3797883804205e-07, 0.4435193600836e+00, 0.3154687086868e+01,
+
+      0.2933033225587e-07, 0.5124157356507e+01, 0.1059381944224e+01,
+      0.3503000930426e-07, 0.5421830162065e+01, 0.6069776770667e+01,
+      0.3670096214050e-07, 0.4582101667297e+01, 0.1219403291462e+02,
+      0.2905609437008e-07, 0.1926566420072e+01, 0.1097707878456e+02,
+      0.2466827821713e-07, 0.6090174539834e+00, 0.6496374930224e+01,
+      0.2691647295332e-07, 0.1393432595077e+01, 0.2200391463820e+02,
+      0.2150554667946e-07, 0.4308671715951e+01, 0.5643178611111e+01,
+      0.2237481922680e-07, 0.8133968269414e+00, 0.8635942003952e+01,
+      0.1817741038157e-07, 0.3755205127454e+01, 0.3340612434717e+01,
+      0.2227820762132e-07, 0.2759558596664e+01, 0.1203646072878e+02,
+
+      0.1944713772307e-07, 0.5699645869121e+01, 0.1179062909082e+02,
+      0.1527340520662e-07, 0.1986749091746e+01, 0.3981490189893e+00,
+      0.1577282574914e-07, 0.3205017217983e+01, 0.5088628793478e+01,
+      0.1424738825424e-07, 0.6256747903666e+01, 0.2544314396739e+01,
+      0.1616563121701e-07, 0.2601671259394e+00, 0.1729818233119e+02,
+      0.1401210391692e-07, 0.4686939173506e+01, 0.7058598460518e+01,
+      0.1488726974214e-07, 0.2815862451372e+01, 0.2593412433514e+02,
+      0.1692626442388e-07, 0.4956894109797e+01, 0.1564752902480e+03,
+      0.1123571582910e-07, 0.2381192697696e+01, 0.3738761453707e+01,
+      0.9903308606317e-08, 0.4294851657684e+01, 0.9225539266174e+01,
+
+      0.9174533187191e-08, 0.3075171510642e+01, 0.4164311961999e+01,
+      0.8645985631457e-08, 0.5477534821633e+00, 0.8429241228195e+01,
+     -0.1085876492688e-07, 0.0000000000000e+00, 0.0000000000000e+00,
+      0.9264309077815e-08, 0.5968571670097e+01, 0.7079373888424e+01,
+      0.8243116984954e-08, 0.1489098777643e+01, 0.1044738781244e+02,
+      0.8268102113708e-08, 0.3512977691983e+01, 0.1150676975667e+02,
+      0.9043613988227e-08, 0.1290704408221e+00, 0.1101510648075e+02,
+      0.7432912038789e-08, 0.1991086893337e+01, 0.2608790314060e+02,
+      0.8586233727285e-08, 0.4238357924414e+01, 0.2986433403208e+02,
+      0.7612230060131e-08, 0.2911090150166e+01, 0.4732030630302e+01,
+
+      0.7097787751408e-08, 0.1908938392390e+01, 0.8031092209206e+01,
+      0.7640237040175e-08, 0.6129219000168e+00, 0.7962980379786e+00,
+      0.7070445688081e-08, 0.1380417036651e+01, 0.2146165377750e+01,
+      0.7690770957702e-08, 0.1680504249084e+01, 0.2122839202813e+02,
+      0.8051292542594e-08, 0.5127423484511e+01, 0.2942463415728e+01,
+      0.5902709104515e-08, 0.2020274190917e+01, 0.7755226100720e+00,
+      0.5134567496462e-08, 0.2606778676418e+01, 0.1256615170089e+02,
+      0.5525802046102e-08, 0.1613011769663e+01, 0.8018209333619e+00,
+      0.5880724784221e-08, 0.4604483417236e+01, 0.4690479774488e+01,
+      0.5211699081370e-08, 0.5718964114193e+01, 0.8827390247185e+01,
+
+      0.4891849573562e-08, 0.3689658932196e+01, 0.2132990797783e+00,
+      0.5150246069997e-08, 0.4099769855122e+01, 0.6480980550449e+02,
+      0.5102434319633e-08, 0.5660834602509e+01, 0.3379454372902e+02,
+      0.5083405254252e-08, 0.9842221218974e+00, 0.4136910472696e+01,
+      0.4206562585682e-08, 0.1341363634163e+00, 0.3128388763578e+01,
+      0.4663249683579e-08, 0.8130132735866e+00, 0.5216580451554e+01,
+      0.4099474416530e-08, 0.5791497770644e+01, 0.4265981595566e+00,
+      0.4628251220767e-08, 0.1249802769331e+01, 0.1572083878776e+02,
+      0.5024068728142e-08, 0.4795684802743e+01, 0.6290189305114e+01,
+      0.5120234327758e-08, 0.3810420387208e+01, 0.5230807360890e+01,
+
+      0.5524029815280e-08, 0.1029264714351e+01, 0.2397622045175e+03,
+      0.4757415718860e-08, 0.3528044781779e+01, 0.1649636139783e+02,
+      0.3915786131127e-08, 0.5593889282646e+01, 0.1589072916335e+01,
+      0.4869053149991e-08, 0.3299636454433e+01, 0.7632943190217e+01,
+      0.3649365703729e-08, 0.1286049002584e+01, 0.6206810014183e+01,
+      0.3992493949002e-08, 0.3100307589464e+01, 0.2515860172507e+02,
+      0.3320247477418e-08, 0.6212683940807e+01, 0.1216800268190e+02,
+      0.3287123739696e-08, 0.4699118445928e+01, 0.7234794171227e+01,
+      0.3472776811103e-08, 0.2630507142004e+01, 0.7342457794669e+01,
+      0.3423253294767e-08, 0.2946432844305e+01, 0.9623688285163e+01,
+
+      0.3896173898244e-08, 0.1224834179264e+01, 0.6438496133249e+01,
+      0.3388455337924e-08, 0.1543807616351e+01, 0.1494531617769e+02,
+      0.3062704716523e-08, 0.1191777572310e+01, 0.8662240327241e+01,
+      0.3270075600400e-08, 0.5483498767737e+01, 0.1194447056968e+01,
+      0.3101209215259e-08, 0.8000833804348e+00, 0.3772475342596e+02,
+      0.2780883347311e-08, 0.4077980721888e+00, 0.5863591145557e+01,
+      0.2903605931824e-08, 0.2617490302147e+01, 0.1965104848470e+02,
+      0.2682014743119e-08, 0.2634703158290e+01, 0.7238675589263e+01,
+      0.2534360108492e-08, 0.6102446114873e+01, 0.6836645152238e+01,
+      0.2392564882509e-08, 0.3681820208691e+01, 0.5849364236221e+01,
+
+      0.2656667254856e-08, 0.6216045388886e+01, 0.6133512519065e+01,
+      0.2331242096773e-08, 0.5864949777744e+01, 0.4535059491685e+01,
+      0.2287898363668e-08, 0.4566628532802e+01, 0.7477522907414e+01,
+      0.2336944521306e-08, 0.2442722126930e+01, 0.1137170464392e+02,
+      0.3156632236269e-08, 0.1626628050682e+01, 0.2509084901204e+03,
+      0.2982612402766e-08, 0.2803604512609e+01, 0.1748016358760e+01,
+      0.2774031674807e-08, 0.4654002897158e+01, 0.8223916695780e+02,
+      0.2295236548638e-08, 0.4326518333253e+01, 0.3378142627421e+00,
+      0.2190714699873e-08, 0.4519614578328e+01, 0.2908881142201e+02,
+      0.2191495845045e-08, 0.3012626912549e+01, 0.1673046366289e+02,
+
+      0.2492901628386e-08, 0.1290101424052e+00, 0.1543797956245e+03,
+      0.1993778064319e-08, 0.3864046799414e+01, 0.1778984560711e+02,
+      0.1898146479022e-08, 0.5053777235891e+01, 0.2042657109477e+02,
+      0.1918280127634e-08, 0.2222470192548e+01, 0.4165496312290e+02,
+      0.1916351061607e-08, 0.8719067257774e+00, 0.7737595720538e+02,
+      0.1834720181466e-08, 0.4031491098040e+01, 0.2358125818164e+02,
+      0.1249201523806e-08, 0.5938379466835e+01, 0.3301902111895e+02,
+      0.1477304050539e-08, 0.6544722606797e+00, 0.9548094718417e+02,
+      0.1264316431249e-08, 0.2059072853236e+01, 0.8399684731857e+02,
+      0.1203526495039e-08, 0.3644813532605e+01, 0.4558517281984e+02,
+
+      0.9221681059831e-09, 0.3241815055602e+01, 0.7805158573086e+02,
+      0.7849278367646e-09, 0.5043812342457e+01, 0.5217580628120e+02,
+      0.7983392077387e-09, 0.5000024502753e+01, 0.1501922143975e+03,
+      0.7925395431654e-09, 0.1398734871821e-01, 0.9061773743175e+02,
+      0.7640473285886e-09, 0.5067111723130e+01, 0.4951538251678e+02,
+      0.5398937754482e-09, 0.5597382200075e+01, 0.1613385000004e+03,
+      0.5626247550193e-09, 0.2601338209422e+01, 0.7318837597844e+02,
+      0.5525197197855e-09, 0.5814832109256e+01, 0.1432335100216e+03,
+      0.5407629837898e-09, 0.3384820609076e+01, 0.3230491187871e+03,
+      0.3856739119801e-09, 0.1072391840473e+01, 0.2334791286671e+03,
+
+      0.3856425239987e-09, 0.2369540393327e+01, 0.1739046517013e+03,
+      0.4350867755983e-09, 0.5255575751082e+01, 0.1620484330494e+03,
+      0.3844113924996e-09, 0.5482356246182e+01, 0.9757644180768e+02,
+      0.2854869155431e-09, 0.9573634763143e+00, 0.1697170704744e+03,
+      0.1719227671416e-09, 0.1887203025202e+01, 0.2265204242912e+03,
+      0.1527846879755e-09, 0.3982183931157e+01, 0.3341954043900e+03,
+      0.1128229264847e-09, 0.2787457156298e+01, 0.3119028331842e+03 };
+
+/* Sun-to-Earth, T^1, X */
+   static const double e1x[] = {
+      0.1234046326004e-05, 0.0000000000000e+00, 0.0000000000000e+00,
+      0.5150068824701e-06, 0.6002664557501e+01, 0.1256615170089e+02,
+      0.1290743923245e-07, 0.5959437664199e+01, 0.1884922755134e+02,
+      0.1068615564952e-07, 0.2015529654209e+01, 0.6283075850446e+01,
+      0.2079619142538e-08, 0.1732960531432e+01, 0.6279552690824e+01,
+      0.2078009243969e-08, 0.4915604476996e+01, 0.6286599010068e+01,
+      0.6206330058856e-09, 0.3616457953824e+00, 0.4705732307012e+01,
+      0.5989335313746e-09, 0.3802607304474e+01, 0.6256777527156e+01,
+      0.5958495663840e-09, 0.2845866560031e+01, 0.6309374173736e+01,
+      0.4866923261539e-09, 0.5213203771824e+01, 0.7755226100720e+00,
+
+      0.4267785823142e-09, 0.4368189727818e+00, 0.1059381944224e+01,
+      0.4610675141648e-09, 0.1837249181372e-01, 0.7860419393880e+01,
+      0.3626989993973e-09, 0.2161590545326e+01, 0.5753384878334e+01,
+      0.3563071194389e-09, 0.1452631954746e+01, 0.5884926831456e+01,
+      0.3557015642807e-09, 0.4470593393054e+01, 0.6812766822558e+01,
+      0.3210412089122e-09, 0.5195926078314e+01, 0.6681224869435e+01,
+      0.2875473577986e-09, 0.5916256610193e+01, 0.2513230340178e+02,
+      0.2842913681629e-09, 0.1149902426047e+01, 0.6127655567643e+01,
+      0.2751248215916e-09, 0.5502088574662e+01, 0.6438496133249e+01,
+      0.2481432881127e-09, 0.2921989846637e+01, 0.5486777812467e+01,
+
+      0.2059885976560e-09, 0.3718070376585e+01, 0.7079373888424e+01,
+      0.2015522342591e-09, 0.5979395259740e+01, 0.6290189305114e+01,
+      0.1995364084253e-09, 0.6772087985494e+00, 0.6275962395778e+01,
+      0.1957436436943e-09, 0.2899210654665e+01, 0.5507553240374e+01,
+      0.1651609818948e-09, 0.6228206482192e+01, 0.1150676975667e+02,
+      0.1822980550699e-09, 0.1469348746179e+01, 0.1179062909082e+02,
+      0.1675223159760e-09, 0.3813910555688e+01, 0.7058598460518e+01,
+      0.1706491764745e-09, 0.3004380506684e+00, 0.7113454667900e-02,
+      0.1392952362615e-09, 0.1440393973406e+01, 0.7962980379786e+00,
+      0.1209868266342e-09, 0.4150425791727e+01, 0.4694002934110e+01,
+
+      0.1009827202611e-09, 0.3290040429843e+01, 0.3738761453707e+01,
+      0.1047261388602e-09, 0.4229590090227e+01, 0.6282095334605e+01,
+      0.1047006652004e-09, 0.2418967680575e+01, 0.6284056366286e+01,
+      0.9609993143095e-10, 0.4627943659201e+01, 0.6069776770667e+01,
+      0.9590900593873e-10, 0.1894393939924e+01, 0.4136910472696e+01,
+      0.9146249188071e-10, 0.2010647519562e+01, 0.6496374930224e+01,
+      0.8545274480290e-10, 0.5529846956226e-01, 0.1194447056968e+01,
+      0.8224377881194e-10, 0.1254304102174e+01, 0.1589072916335e+01,
+      0.6183529510410e-10, 0.3360862168815e+01, 0.8827390247185e+01,
+      0.6259255147141e-10, 0.4755628243179e+01, 0.8429241228195e+01,
+
+      0.5539291694151e-10, 0.5371746955142e+01, 0.4933208510675e+01,
+      0.7328259466314e-10, 0.4927699613906e+00, 0.4535059491685e+01,
+      0.6017835843560e-10, 0.5776682001734e-01, 0.1255903824622e+02,
+      0.7079827775243e-10, 0.4395059432251e+01, 0.5088628793478e+01,
+      0.5170358878213e-10, 0.5154062619954e+01, 0.1176985366291e+02,
+      0.4872301838682e-10, 0.6289611648973e+00, 0.6040347114260e+01,
+      0.5249869411058e-10, 0.5617272046949e+01, 0.3154687086868e+01,
+      0.4716172354411e-10, 0.3965901800877e+01, 0.5331357529664e+01,
+      0.4871214940964e-10, 0.4627507050093e+01, 0.1256967486051e+02,
+      0.4598076850751e-10, 0.6023631226459e+01, 0.6525804586632e+01,
+
+      0.4562196089485e-10, 0.4138562084068e+01, 0.3930209696940e+01,
+      0.4325493872224e-10, 0.1330845906564e+01, 0.7632943190217e+01,
+      0.5673781176748e-10, 0.2558752615657e+01, 0.5729506548653e+01,
+      0.3961436642503e-10, 0.2728071734630e+01, 0.7234794171227e+01,
+      0.5101868209058e-10, 0.4113444965144e+01, 0.6836645152238e+01,
+      0.5257043167676e-10, 0.6195089830590e+01, 0.8031092209206e+01,
+      0.5076613989393e-10, 0.2305124132918e+01, 0.7477522907414e+01,
+      0.3342169352778e-10, 0.5415998155071e+01, 0.1097707878456e+02,
+      0.3545881983591e-10, 0.3727160564574e+01, 0.4164311961999e+01,
+      0.3364063738599e-10, 0.2901121049204e+00, 0.1137170464392e+02,
+
+      0.3357039670776e-10, 0.1652229354331e+01, 0.5223693906222e+01,
+      0.4307412268687e-10, 0.4938909587445e+01, 0.1592596075957e+01,
+      0.3405769115435e-10, 0.2408890766511e+01, 0.3128388763578e+01,
+      0.3001926198480e-10, 0.4862239006386e+01, 0.1748016358760e+01,
+      0.2778264787325e-10, 0.5241168661353e+01, 0.7342457794669e+01,
+      0.2676159480666e-10, 0.3423593942199e+01, 0.2146165377750e+01,
+      0.2954273399939e-10, 0.1881721265406e+01, 0.5368044267797e+00,
+      0.3309362888795e-10, 0.1931525677349e+01, 0.8018209333619e+00,
+      0.2810283608438e-10, 0.2414659495050e+01, 0.5225775174439e+00,
+      0.3378045637764e-10, 0.4238019163430e+01, 0.1554202828031e+00,
+
+      0.2558134979840e-10, 0.1828225235805e+01, 0.5230807360890e+01,
+      0.2273755578447e-10, 0.5858184283998e+01, 0.7084896783808e+01,
+      0.2294176037690e-10, 0.4514589779057e+01, 0.1726015463500e+02,
+      0.2533506099435e-10, 0.2355717851551e+01, 0.5216580451554e+01,
+      0.2716685375812e-10, 0.2221003625100e+01, 0.8635942003952e+01,
+      0.2419043435198e-10, 0.5955704951635e+01, 0.4690479774488e+01,
+      0.2521232544812e-10, 0.1395676848521e+01, 0.5481254917084e+01,
+      0.2630195021491e-10, 0.5727468918743e+01, 0.2629832328990e-01,
+      0.2548395840944e-10, 0.2628351859400e-03, 0.1349867339771e+01 };
+
+/* Sun-to-Earth, T^1, Y */
+   static const double e1y[] = {
+      0.9304690546528e-06, 0.0000000000000e+00, 0.0000000000000e+00,
+      0.5150715570663e-06, 0.4431807116294e+01, 0.1256615170089e+02,
+      0.1290825411056e-07, 0.4388610039678e+01, 0.1884922755134e+02,
+      0.4645466665386e-08, 0.5827263376034e+01, 0.6283075850446e+01,
+      0.2079625310718e-08, 0.1621698662282e+00, 0.6279552690824e+01,
+      0.2078189850907e-08, 0.3344713435140e+01, 0.6286599010068e+01,
+      0.6207190138027e-09, 0.5074049319576e+01, 0.4705732307012e+01,
+      0.5989826532569e-09, 0.2231842216620e+01, 0.6256777527156e+01,
+      0.5961360812618e-09, 0.1274975769045e+01, 0.6309374173736e+01,
+      0.4874165471016e-09, 0.3642277426779e+01, 0.7755226100720e+00,
+
+      0.4283834034360e-09, 0.5148765510106e+01, 0.1059381944224e+01,
+      0.4652389287529e-09, 0.4715794792175e+01, 0.7860419393880e+01,
+      0.3751707476401e-09, 0.6617207370325e+00, 0.5753384878334e+01,
+      0.3559998806198e-09, 0.6155548875404e+01, 0.5884926831456e+01,
+      0.3558447558857e-09, 0.2898827297664e+01, 0.6812766822558e+01,
+      0.3211116927106e-09, 0.3625813502509e+01, 0.6681224869435e+01,
+      0.2875609914672e-09, 0.4345435813134e+01, 0.2513230340178e+02,
+      0.2843109704069e-09, 0.5862263940038e+01, 0.6127655567643e+01,
+      0.2744676468427e-09, 0.3926419475089e+01, 0.6438496133249e+01,
+      0.2481285237789e-09, 0.1351976572828e+01, 0.5486777812467e+01,
+
+      0.2060338481033e-09, 0.2147556998591e+01, 0.7079373888424e+01,
+      0.2015822358331e-09, 0.4408358972216e+01, 0.6290189305114e+01,
+      0.2001195944195e-09, 0.5385829822531e+01, 0.6275962395778e+01,
+      0.1953667642377e-09, 0.1304933746120e+01, 0.5507553240374e+01,
+      0.1839744078713e-09, 0.6173567228835e+01, 0.1179062909082e+02,
+      0.1643334294845e-09, 0.4635942997523e+01, 0.1150676975667e+02,
+      0.1768051018652e-09, 0.5086283558874e+01, 0.7113454667900e-02,
+      0.1674874205489e-09, 0.2243332137241e+01, 0.7058598460518e+01,
+      0.1421445397609e-09, 0.6186899771515e+01, 0.7962980379786e+00,
+      0.1255163958267e-09, 0.5730238465658e+01, 0.4694002934110e+01,
+
+      0.1013945281961e-09, 0.1726055228402e+01, 0.3738761453707e+01,
+      0.1047294335852e-09, 0.2658801228129e+01, 0.6282095334605e+01,
+      0.1047103879392e-09, 0.8481047835035e+00, 0.6284056366286e+01,
+      0.9530343962826e-10, 0.3079267149859e+01, 0.6069776770667e+01,
+      0.9604637611690e-10, 0.3258679792918e+00, 0.4136910472696e+01,
+      0.9153518537177e-10, 0.4398599886584e+00, 0.6496374930224e+01,
+      0.8562458214922e-10, 0.4772686794145e+01, 0.1194447056968e+01,
+      0.8232525360654e-10, 0.5966220721679e+01, 0.1589072916335e+01,
+      0.6150223411438e-10, 0.1780985591923e+01, 0.8827390247185e+01,
+      0.6272087858000e-10, 0.3184305429012e+01, 0.8429241228195e+01,
+
+      0.5540476311040e-10, 0.3801260595433e+01, 0.4933208510675e+01,
+      0.7331901699361e-10, 0.5205948591865e+01, 0.4535059491685e+01,
+      0.6018528702791e-10, 0.4770139083623e+01, 0.1255903824622e+02,
+      0.5150530724804e-10, 0.3574796899585e+01, 0.1176985366291e+02,
+      0.6471933741811e-10, 0.2679787266521e+01, 0.5088628793478e+01,
+      0.5317460644174e-10, 0.9528763345494e+00, 0.3154687086868e+01,
+      0.4832187748783e-10, 0.5329322498232e+01, 0.6040347114260e+01,
+      0.4716763555110e-10, 0.2395235316466e+01, 0.5331357529664e+01,
+      0.4871509139861e-10, 0.3056663648823e+01, 0.1256967486051e+02,
+      0.4598417696768e-10, 0.4452762609019e+01, 0.6525804586632e+01,
+
+      0.5674189533175e-10, 0.9879680872193e+00, 0.5729506548653e+01,
+      0.4073560328195e-10, 0.5939127696986e+01, 0.7632943190217e+01,
+      0.5040994945359e-10, 0.4549875824510e+01, 0.8031092209206e+01,
+      0.5078185134679e-10, 0.7346659893982e+00, 0.7477522907414e+01,
+      0.3769343537061e-10, 0.1071317188367e+01, 0.7234794171227e+01,
+      0.4980331365299e-10, 0.2500345341784e+01, 0.6836645152238e+01,
+      0.3458236594757e-10, 0.3825159450711e+01, 0.1097707878456e+02,
+      0.3578859493602e-10, 0.5299664791549e+01, 0.4164311961999e+01,
+      0.3370504646419e-10, 0.5002316301593e+01, 0.1137170464392e+02,
+      0.3299873338428e-10, 0.2526123275282e+01, 0.3930209696940e+01,
+
+      0.4304917318409e-10, 0.3368078557132e+01, 0.1592596075957e+01,
+      0.3402418753455e-10, 0.8385495425800e+00, 0.3128388763578e+01,
+      0.2778460572146e-10, 0.3669905203240e+01, 0.7342457794669e+01,
+      0.2782710128902e-10, 0.2691664812170e+00, 0.1748016358760e+01,
+      0.2711725179646e-10, 0.4707487217718e+01, 0.5296909721118e+00,
+      0.2981760946340e-10, 0.3190260867816e+00, 0.5368044267797e+00,
+      0.2811672977772e-10, 0.3196532315372e+01, 0.7084896783808e+01,
+      0.2863454474467e-10, 0.2263240324780e+00, 0.5223693906222e+01,
+      0.3333464634051e-10, 0.3498451685065e+01, 0.8018209333619e+00,
+      0.3312991747609e-10, 0.5839154477412e+01, 0.1554202828031e+00,
+
+      0.2813255564006e-10, 0.8268044346621e+00, 0.5225775174439e+00,
+      0.2665098083966e-10, 0.3934021725360e+01, 0.5216580451554e+01,
+      0.2349795705216e-10, 0.5197620913779e+01, 0.2146165377750e+01,
+      0.2330352293961e-10, 0.2984999231807e+01, 0.1726015463500e+02,
+      0.2728001683419e-10, 0.6521679638544e+00, 0.8635942003952e+01,
+      0.2484061007669e-10, 0.3468955561097e+01, 0.5230807360890e+01,
+      0.2646328768427e-10, 0.1013724533516e+01, 0.2629832328990e-01,
+      0.2518630264831e-10, 0.6108081057122e+01, 0.5481254917084e+01,
+      0.2421901455384e-10, 0.1651097776260e+01, 0.1349867339771e+01,
+      0.6348533267831e-11, 0.3220226560321e+01, 0.8433466158131e+02 };
+
+/* Sun-to-Earth, T^1, Z */
+   static const double e1z[] = {
+      0.2278290449966e-05, 0.3413716033863e+01, 0.6283075850446e+01,
+      0.5429458209830e-07, 0.0000000000000e+00, 0.0000000000000e+00,
+      0.1903240492525e-07, 0.3370592358297e+01, 0.1256615170089e+02,
+      0.2385409276743e-09, 0.3327914718416e+01, 0.1884922755134e+02,
+      0.8676928342573e-10, 0.1824006811264e+01, 0.5223693906222e+01,
+      0.7765442593544e-10, 0.3888564279247e+01, 0.5507553240374e+01,
+      0.7066158332715e-10, 0.5194267231944e+01, 0.2352866153506e+01,
+      0.7092175288657e-10, 0.2333246960021e+01, 0.8399684731857e+02,
+      0.5357582213535e-10, 0.2224031176619e+01, 0.5296909721118e+00,
+      0.3828035865021e-10, 0.2156710933584e+01, 0.6279552690824e+01,
+
+      0.3824857220427e-10, 0.1529755219915e+01, 0.6286599010068e+01,
+      0.3286995181628e-10, 0.4879512900483e+01, 0.1021328554739e+02 };
+
+/* Sun-to-Earth, T^2, X */
+   static const double e2x[] = {
+     -0.4143818297913e-10, 0.0000000000000e+00, 0.0000000000000e+00,
+      0.2171497694435e-10, 0.4398225628264e+01, 0.1256615170089e+02,
+      0.9845398442516e-11, 0.2079720838384e+00, 0.6283075850446e+01,
+      0.9256833552682e-12, 0.4191264694361e+01, 0.1884922755134e+02,
+      0.1022049384115e-12, 0.5381133195658e+01, 0.8399684731857e+02 };
+
+/* Sun-to-Earth, T^2, Y */
+   static const double e2y[] = {
+      0.5063375872532e-10, 0.0000000000000e+00, 0.0000000000000e+00,
+      0.2173815785980e-10, 0.2827805833053e+01, 0.1256615170089e+02,
+      0.1010231999920e-10, 0.4634612377133e+01, 0.6283075850446e+01,
+      0.9259745317636e-12, 0.2620612076189e+01, 0.1884922755134e+02,
+      0.1022202095812e-12, 0.3809562326066e+01, 0.8399684731857e+02 };
+
+/* Sun-to-Earth, T^2, Z */
+   static const double e2z[] = {
+      0.9722666114891e-10, 0.5152219582658e+01, 0.6283075850446e+01,
+     -0.3494819171909e-11, 0.0000000000000e+00, 0.0000000000000e+00,
+      0.6713034376076e-12, 0.6440188750495e+00, 0.1256615170089e+02 };
+
+/* SSB-to-Sun, T^0, X */
+   static const double s0x[] = {
+      0.4956757536410e-02, 0.3741073751789e+01, 0.5296909721118e+00,
+      0.2718490072522e-02, 0.4016011511425e+01, 0.2132990797783e+00,
+      0.1546493974344e-02, 0.2170528330642e+01, 0.3813291813120e-01,
+      0.8366855276341e-03, 0.2339614075294e+01, 0.7478166569050e-01,
+      0.2936777942117e-03, 0.0000000000000e+00, 0.0000000000000e+00,
+      0.1201317439469e-03, 0.4090736353305e+01, 0.1059381944224e+01,
+      0.7578550887230e-04, 0.3241518088140e+01, 0.4265981595566e+00,
+      0.1941787367773e-04, 0.1012202064330e+01, 0.2061856251104e+00,
+      0.1889227765991e-04, 0.3892520416440e+01, 0.2204125344462e+00,
+      0.1937896968613e-04, 0.4797779441161e+01, 0.1495633313810e+00,
+
+      0.1434506110873e-04, 0.3868960697933e+01, 0.5225775174439e+00,
+      0.1406659911580e-04, 0.4759766557397e+00, 0.5368044267797e+00,
+      0.1179022300202e-04, 0.7774961520598e+00, 0.7626583626240e-01,
+      0.8085864460959e-05, 0.3254654471465e+01, 0.3664874755930e-01,
+      0.7622752967615e-05, 0.4227633103489e+01, 0.3961708870310e-01,
+      0.6209171139066e-05, 0.2791828325711e+00, 0.7329749511860e-01,
+      0.4366435633970e-05, 0.4440454875925e+01, 0.1589072916335e+01,
+      0.3792124889348e-05, 0.5156393842356e+01, 0.7113454667900e-02,
+      0.3154548963402e-05, 0.6157005730093e+01, 0.4194847048887e+00,
+      0.3088359882942e-05, 0.2494567553163e+01, 0.6398972393349e+00,
+
+      0.2788440902136e-05, 0.4934318747989e+01, 0.1102062672231e+00,
+      0.3039928456376e-05, 0.4895077702640e+01, 0.6283075850446e+01,
+      0.2272258457679e-05, 0.5278394064764e+01, 0.1030928125552e+00,
+      0.2162007057957e-05, 0.5802978019099e+01, 0.3163918923335e+00,
+      0.1767632855737e-05, 0.3415346595193e-01, 0.1021328554739e+02,
+      0.1349413459362e-05, 0.2001643230755e+01, 0.1484170571900e-02,
+      0.1170141900476e-05, 0.2424750491620e+01, 0.6327837846670e+00,
+      0.1054355266820e-05, 0.3123311487576e+01, 0.4337116142245e+00,
+      0.9800822461610e-06, 0.3026258088130e+01, 0.1052268489556e+01,
+      0.1091203749931e-05, 0.3157811670347e+01, 0.1162474756779e+01,
+
+      0.6960236715913e-06, 0.8219570542313e+00, 0.1066495398892e+01,
+      0.5689257296909e-06, 0.1323052375236e+01, 0.9491756770005e+00,
+      0.6613172135802e-06, 0.2765348881598e+00, 0.8460828644453e+00,
+      0.6277702517571e-06, 0.5794064466382e+01, 0.1480791608091e+00,
+      0.6304884066699e-06, 0.7323555380787e+00, 0.2243449970715e+00,
+      0.4897850467382e-06, 0.3062464235399e+01, 0.3340612434717e+01,
+      0.3759148598786e-06, 0.4588290469664e+01, 0.3516457698740e-01,
+      0.3110520548195e-06, 0.1374299536572e+01, 0.6373574839730e-01,
+      0.3064708359780e-06, 0.4222267485047e+01, 0.1104591729320e-01,
+      0.2856347168241e-06, 0.3714202944973e+01, 0.1510475019529e+00,
+
+      0.2840945514288e-06, 0.2847972875882e+01, 0.4110125927500e-01,
+      0.2378951599405e-06, 0.3762072563388e+01, 0.2275259891141e+00,
+      0.2714229481417e-06, 0.1036049980031e+01, 0.2535050500000e-01,
+      0.2323551717307e-06, 0.4682388599076e+00, 0.8582758298370e-01,
+      0.1881790512219e-06, 0.4790565425418e+01, 0.2118763888447e+01,
+      0.2261353968371e-06, 0.1669144912212e+01, 0.7181332454670e-01,
+      0.2214546389848e-06, 0.3937717281614e+01, 0.2968341143800e-02,
+      0.2184915594933e-06, 0.1129169845099e+00, 0.7775000683430e-01,
+      0.2000164937936e-06, 0.4030009638488e+01, 0.2093666171530e+00,
+      0.1966105136719e-06, 0.8745955786834e+00, 0.2172315424036e+00,
+
+      0.1904742332624e-06, 0.5919743598964e+01, 0.2022531624851e+00,
+      0.1657399705031e-06, 0.2549141484884e+01, 0.7358765972222e+00,
+      0.1574070533987e-06, 0.5277533020230e+01, 0.7429900518901e+00,
+      0.1832261651039e-06, 0.3064688127777e+01, 0.3235053470014e+00,
+      0.1733615346569e-06, 0.3011432799094e+01, 0.1385174140878e+00,
+      0.1549124014496e-06, 0.4005569132359e+01, 0.5154640627760e+00,
+      0.1637044713838e-06, 0.1831375966632e+01, 0.8531963191132e+00,
+      0.1123420082383e-06, 0.1180270407578e+01, 0.1990721704425e+00,
+      0.1083754165740e-06, 0.3414101320863e+00, 0.5439178814476e+00,
+      0.1156638012655e-06, 0.6130479452594e+00, 0.5257585094865e+00,
+
+      0.1142548785134e-06, 0.3724761948846e+01, 0.5336234347371e+00,
+      0.7921463895965e-07, 0.2435425589361e+01, 0.1478866649112e+01,
+      0.7428600285231e-07, 0.3542144398753e+01, 0.2164800718209e+00,
+      0.8323211246747e-07, 0.3525058072354e+01, 0.1692165728891e+01,
+      0.7257595116312e-07, 0.1364299431982e+01, 0.2101180877357e+00,
+      0.7111185833236e-07, 0.2460478875808e+01, 0.4155522422634e+00,
+      0.6868090383716e-07, 0.4397327670704e+01, 0.1173197218910e+00,
+      0.7226419974175e-07, 0.4042647308905e+01, 0.1265567569334e+01,
+      0.6955642383177e-07, 0.2865047906085e+01, 0.9562891316684e+00,
+      0.7492139296331e-07, 0.5014278994215e+01, 0.1422690933580e-01,
+
+      0.6598363128857e-07, 0.2376730020492e+01, 0.6470106940028e+00,
+      0.7381147293385e-07, 0.3272990384244e+01, 0.1581959461667e+01,
+      0.6402909624032e-07, 0.5302290955138e+01, 0.9597935788730e-01,
+      0.6237454263857e-07, 0.5444144425332e+01, 0.7084920306520e-01,
+      0.5241198544016e-07, 0.4215359579205e+01, 0.5265099800692e+00,
+      0.5144463853918e-07, 0.1218916689916e+00, 0.5328719641544e+00,
+      0.5868164772299e-07, 0.2369402002213e+01, 0.7871412831580e-01,
+      0.6233195669151e-07, 0.1254922242403e+01, 0.2608790314060e+02,
+      0.6068463791422e-07, 0.5679713760431e+01, 0.1114304132498e+00,
+      0.4359361135065e-07, 0.6097219641646e+00, 0.1375773836557e+01,
+
+      0.4686510366826e-07, 0.4786231041431e+01, 0.1143987543936e+00,
+      0.3758977287225e-07, 0.1167368068139e+01, 0.1596186371003e+01,
+      0.4282051974778e-07, 0.1519471064319e+01, 0.2770348281756e+00,
+      0.5153765386113e-07, 0.1860532322984e+01, 0.2228608264996e+00,
+      0.4575129387188e-07, 0.7632857887158e+00, 0.1465949902372e+00,
+      0.3326844933286e-07, 0.1298219485285e+01, 0.5070101000000e-01,
+      0.3748617450984e-07, 0.1046510321062e+01, 0.4903339079539e+00,
+      0.2816756661499e-07, 0.3434522346190e+01, 0.2991266627620e+00,
+      0.3412750405039e-07, 0.2523766270318e+01, 0.3518164938661e+00,
+      0.2655796761776e-07, 0.2904422260194e+01, 0.6256703299991e+00,
+
+      0.2963597929458e-07, 0.5923900431149e+00, 0.1099462426779e+00,
+      0.2539523734781e-07, 0.4851947722567e+01, 0.1256615170089e+02,
+      0.2283087914139e-07, 0.3400498595496e+01, 0.6681224869435e+01,
+      0.2321309799331e-07, 0.5789099148673e+01, 0.3368040641550e-01,
+      0.2549657649750e-07, 0.3991856479792e-01, 0.1169588211447e+01,
+      0.2290462303977e-07, 0.2788567577052e+01, 0.1045155034888e+01,
+      0.1945398522914e-07, 0.3290896998176e+01, 0.1155361302111e+01,
+      0.1849171512638e-07, 0.2698060129367e+01, 0.4452511715700e-02,
+      0.1647199834254e-07, 0.3016735644085e+01, 0.4408250688924e+00,
+      0.1529530765273e-07, 0.5573043116178e+01, 0.6521991896920e-01,
+
+      0.1433199339978e-07, 0.1481192356147e+01, 0.9420622223326e+00,
+      0.1729134193602e-07, 0.1422817538933e+01, 0.2108507877249e+00,
+      0.1716463931346e-07, 0.3469468901855e+01, 0.2157473718317e+00,
+      0.1391206061378e-07, 0.6122436220547e+01, 0.4123712502208e+00,
+      0.1404746661924e-07, 0.1647765641936e+01, 0.4258542984690e-01,
+      0.1410452399455e-07, 0.5989729161964e+01, 0.2258291676434e+00,
+      0.1089828772168e-07, 0.2833705509371e+01, 0.4226656969313e+00,
+      0.1047374564948e-07, 0.5090690007331e+00, 0.3092784376656e+00,
+      0.1358279126532e-07, 0.5128990262836e+01, 0.7923417740620e-01,
+      0.1020456476148e-07, 0.9632772880808e+00, 0.1456308687557e+00,
+
+      0.1033428735328e-07, 0.3223779318418e+01, 0.1795258541446e+01,
+      0.1412435841540e-07, 0.2410271572721e+01, 0.1525316725248e+00,
+      0.9722759371574e-08, 0.2333531395690e+01, 0.8434341241180e-01,
+      0.9657334084704e-08, 0.6199270974168e+01, 0.1272681024002e+01,
+      0.1083641148690e-07, 0.2864222292929e+01, 0.7032915397480e-01,
+      0.1067318403838e-07, 0.5833458866568e+00, 0.2123349582968e+00,
+      0.1062366201976e-07, 0.4307753989494e+01, 0.2142632012598e+00,
+      0.1236364149266e-07, 0.2873917870593e+01, 0.1847279083684e+00,
+      0.1092759489593e-07, 0.2959887266733e+01, 0.1370332435159e+00,
+      0.8912069362899e-08, 0.5141213702562e+01, 0.2648454860559e+01,
+
+      0.9656467707970e-08, 0.4532182462323e+01, 0.4376440768498e+00,
+      0.8098386150135e-08, 0.2268906338379e+01, 0.2880807454688e+00,
+      0.7857714675000e-08, 0.4055544260745e+01, 0.2037373330570e+00,
+      0.7288455940646e-08, 0.5357901655142e+01, 0.1129145838217e+00,
+      0.9450595950552e-08, 0.4264926963939e+01, 0.5272426800584e+00,
+      0.9381718247537e-08, 0.7489366976576e-01, 0.5321392641652e+00,
+      0.7079052646038e-08, 0.1923311052874e+01, 0.6288513220417e+00,
+      0.9259004415344e-08, 0.2970256853438e+01, 0.1606092486742e+00,
+      0.8259801499742e-08, 0.3327056314697e+01, 0.8389694097774e+00,
+      0.6476334355779e-08, 0.2954925505727e+01, 0.2008557621224e+01,
+
+      0.5984021492007e-08, 0.9138753105829e+00, 0.2042657109477e+02,
+      0.5989546863181e-08, 0.3244464082031e+01, 0.2111650433779e+01,
+      0.6233108606023e-08, 0.4995232638403e+00, 0.4305306221819e+00,
+      0.6877299149965e-08, 0.2834987233449e+01, 0.9561746721300e-02,
+      0.8311234227190e-08, 0.2202951835758e+01, 0.3801276407308e+00,
+      0.6599472832414e-08, 0.4478581462618e+01, 0.1063314406849e+01,
+      0.6160491096549e-08, 0.5145858696411e+01, 0.1368660381889e+01,
+      0.6164772043891e-08, 0.3762976697911e+00, 0.4234171675140e+00,
+      0.6363248684450e-08, 0.3162246718685e+01, 0.1253008786510e-01,
+      0.6448587520999e-08, 0.3442693302119e+01, 0.5287268506303e+00,
+
+      0.6431662283977e-08, 0.8977549136606e+00, 0.5306550935933e+00,
+      0.6351223158474e-08, 0.4306447410369e+01, 0.5217580628120e+02,
+      0.5476721393451e-08, 0.3888529177855e+01, 0.2221856701002e+01,
+      0.5341772572619e-08, 0.2655560662512e+01, 0.7466759693650e-01,
+      0.5337055758302e-08, 0.5164990735946e+01, 0.7489573444450e-01,
+      0.5373120816787e-08, 0.6041214553456e+01, 0.1274714967946e+00,
+      0.5392351705426e-08, 0.9177763485932e+00, 0.1055449481598e+01,
+      0.6688495850205e-08, 0.3089608126937e+01, 0.2213766559277e+00,
+      0.5072003660362e-08, 0.4311316541553e+01, 0.2132517061319e+00,
+      0.5070726650455e-08, 0.5790675464444e+00, 0.2133464534247e+00,
+
+      0.5658012950032e-08, 0.2703945510675e+01, 0.7287631425543e+00,
+      0.4835509924854e-08, 0.2975422976065e+01, 0.7160067364790e-01,
+      0.6479821978012e-08, 0.1324168733114e+01, 0.2209183458640e-01,
+      0.6230636494980e-08, 0.2860103632836e+01, 0.3306188016693e+00,
+      0.4649239516213e-08, 0.4832259763403e+01, 0.7796265773310e-01,
+      0.6487325792700e-08, 0.2726165825042e+01, 0.3884652414254e+00,
+      0.4682823682770e-08, 0.6966602455408e+00, 0.1073608853559e+01,
+      0.5704230804976e-08, 0.5669634104606e+01, 0.8731175355560e-01,
+      0.6125413585489e-08, 0.1513386538915e+01, 0.7605151500000e-01,
+      0.6035825038187e-08, 0.1983509168227e+01, 0.9846002785331e+00,
+
+      0.4331123462303e-08, 0.2782892992807e+01, 0.4297791515992e+00,
+      0.4681107685143e-08, 0.5337232886836e+01, 0.2127790306879e+00,
+      0.4669105829655e-08, 0.5837133792160e+01, 0.2138191288687e+00,
+      0.5138823602365e-08, 0.3080560200507e+01, 0.7233337363710e-01,
+      0.4615856664534e-08, 0.1661747897471e+01, 0.8603097737811e+00,
+      0.4496916702197e-08, 0.2112508027068e+01, 0.7381754420900e-01,
+      0.4278479042945e-08, 0.5716528462627e+01, 0.7574578717200e-01,
+      0.3840525503932e-08, 0.6424172726492e+00, 0.3407705765729e+00,
+      0.4866636509685e-08, 0.4919244697715e+01, 0.7722995774390e-01,
+      0.3526100639296e-08, 0.2550821052734e+01, 0.6225157782540e-01,
+
+      0.3939558488075e-08, 0.3939331491710e+01, 0.5268983110410e-01,
+      0.4041268772576e-08, 0.2275337571218e+01, 0.3503323232942e+00,
+      0.3948761842853e-08, 0.1999324200790e+01, 0.1451108196653e+00,
+      0.3258394550029e-08, 0.9121001378200e+00, 0.5296435984654e+00,
+      0.3257897048761e-08, 0.3428428660869e+01, 0.5297383457582e+00,
+      0.3842559031298e-08, 0.6132927720035e+01, 0.9098186128426e+00,
+      0.3109920095448e-08, 0.7693650193003e+00, 0.3932462625300e-02,
+      0.3132237775119e-08, 0.3621293854908e+01, 0.2346394437820e+00,
+      0.3942189421510e-08, 0.4841863659733e+01, 0.3180992042600e-02,
+      0.3796972285340e-08, 0.1814174994268e+01, 0.1862120789403e+00,
+
+      0.3995640233688e-08, 0.1386990406091e+01, 0.4549093064213e+00,
+      0.2875013727414e-08, 0.9178318587177e+00, 0.1905464808669e+01,
+      0.3073719932844e-08, 0.2688923811835e+01, 0.3628624111593e+00,
+      0.2731016580075e-08, 0.1188259127584e+01, 0.2131850110243e+00,
+      0.2729549896546e-08, 0.3702160634273e+01, 0.2134131485323e+00,
+      0.3339372892449e-08, 0.7199163960331e+00, 0.2007689919132e+00,
+      0.2898833764204e-08, 0.1916709364999e+01, 0.5291709230214e+00,
+      0.2894536549362e-08, 0.2424043195547e+01, 0.5302110212022e+00,
+      0.3096872473843e-08, 0.4445894977497e+01, 0.2976424921901e+00,
+      0.2635672326810e-08, 0.3814366984117e+01, 0.1485980103780e+01,
+
+      0.3649302697001e-08, 0.2924200596084e+01, 0.6044726378023e+00,
+      0.3127954585895e-08, 0.1842251648327e+01, 0.1084620721060e+00,
+      0.2616040173947e-08, 0.4155841921984e+01, 0.1258454114666e+01,
+      0.2597395859860e-08, 0.1158045978874e+00, 0.2103781122809e+00,
+      0.2593286172210e-08, 0.4771850408691e+01, 0.2162200472757e+00,
+      0.2481823585747e-08, 0.4608842558889e+00, 0.1062562936266e+01,
+      0.2742219550725e-08, 0.1538781127028e+01, 0.5651155736444e+00,
+      0.3199558469610e-08, 0.3226647822878e+00, 0.7036329877322e+00,
+      0.2666088542957e-08, 0.1967991731219e+00, 0.1400015846597e+00,
+      0.2397067430580e-08, 0.3707036669873e+01, 0.2125476091956e+00,
+
+      0.2376570772738e-08, 0.1182086628042e+01, 0.2140505503610e+00,
+      0.2547228007887e-08, 0.4906256820629e+01, 0.1534957940063e+00,
+      0.2265575594114e-08, 0.3414949866857e+01, 0.2235935264888e+00,
+      0.2464381430585e-08, 0.4599122275378e+01, 0.2091065926078e+00,
+      0.2433408527044e-08, 0.2830751145445e+00, 0.2174915669488e+00,
+      0.2443605509076e-08, 0.4212046432538e+01, 0.1739420156204e+00,
+      0.2319779262465e-08, 0.9881978408630e+00, 0.7530171478090e-01,
+      0.2284622835465e-08, 0.5565347331588e+00, 0.7426161660010e-01,
+      0.2467268750783e-08, 0.5655708150766e+00, 0.2526561439362e+00,
+      0.2808513492782e-08, 0.1418405053408e+01, 0.5636314030725e+00,
+
+      0.2329528932532e-08, 0.4069557545675e+01, 0.1056200952181e+01,
+      0.9698639532817e-09, 0.1074134313634e+01, 0.7826370942180e+02 };
+
+/* SSB-to-Sun, T^0, Y */
+   static const double s0y[] = {
+      0.4955392320126e-02, 0.2170467313679e+01, 0.5296909721118e+00,
+      0.2722325167392e-02, 0.2444433682196e+01, 0.2132990797783e+00,
+      0.1546579925346e-02, 0.5992779281546e+00, 0.3813291813120e-01,
+      0.8363140252966e-03, 0.7687356310801e+00, 0.7478166569050e-01,
+      0.3385792683603e-03, 0.0000000000000e+00, 0.0000000000000e+00,
+      0.1201192221613e-03, 0.2520035601514e+01, 0.1059381944224e+01,
+      0.7587125720554e-04, 0.1669954006449e+01, 0.4265981595566e+00,
+      0.1964155361250e-04, 0.5707743963343e+01, 0.2061856251104e+00,
+      0.1891900364909e-04, 0.2320960679937e+01, 0.2204125344462e+00,
+      0.1937373433356e-04, 0.3226940689555e+01, 0.1495633313810e+00,
+
+      0.1437139941351e-04, 0.2301626908096e+01, 0.5225775174439e+00,
+      0.1406267683099e-04, 0.5188579265542e+01, 0.5368044267797e+00,
+      0.1178703080346e-04, 0.5489483248476e+01, 0.7626583626240e-01,
+      0.8079835186041e-05, 0.1683751835264e+01, 0.3664874755930e-01,
+      0.7623253594652e-05, 0.2656400462961e+01, 0.3961708870310e-01,
+      0.6248667483971e-05, 0.4992775362055e+01, 0.7329749511860e-01,
+      0.4366353695038e-05, 0.2869706279678e+01, 0.1589072916335e+01,
+      0.3829101568895e-05, 0.3572131359950e+01, 0.7113454667900e-02,
+      0.3175733773908e-05, 0.4535372530045e+01, 0.4194847048887e+00,
+      0.3092437902159e-05, 0.9230153317909e+00, 0.6398972393349e+00,
+
+      0.2874168812154e-05, 0.3363143761101e+01, 0.1102062672231e+00,
+      0.3040119321826e-05, 0.3324250895675e+01, 0.6283075850446e+01,
+      0.2699723308006e-05, 0.2917882441928e+00, 0.1030928125552e+00,
+      0.2134832683534e-05, 0.4220997202487e+01, 0.3163918923335e+00,
+      0.1770412139433e-05, 0.4747318496462e+01, 0.1021328554739e+02,
+      0.1377264209373e-05, 0.4305058462401e+00, 0.1484170571900e-02,
+      0.1127814538960e-05, 0.8538177240740e+00, 0.6327837846670e+00,
+      0.1055608090130e-05, 0.1551800742580e+01, 0.4337116142245e+00,
+      0.9802673861420e-06, 0.1459646735377e+01, 0.1052268489556e+01,
+      0.1090329461951e-05, 0.1587351228711e+01, 0.1162474756779e+01,
+
+      0.6959590025090e-06, 0.5534442628766e+01, 0.1066495398892e+01,
+      0.5664914529542e-06, 0.6030673003297e+01, 0.9491756770005e+00,
+      0.6607787763599e-06, 0.4989507233927e+01, 0.8460828644453e+00,
+      0.6269725742838e-06, 0.4222951804572e+01, 0.1480791608091e+00,
+      0.6301889697863e-06, 0.5444316669126e+01, 0.2243449970715e+00,
+      0.4891042662861e-06, 0.1490552839784e+01, 0.3340612434717e+01,
+      0.3457083123290e-06, 0.3030475486049e+01, 0.3516457698740e-01,
+      0.3032559967314e-06, 0.2652038793632e+01, 0.1104591729320e-01,
+      0.2841133988903e-06, 0.1276744786829e+01, 0.4110125927500e-01,
+      0.2855564444432e-06, 0.2143368674733e+01, 0.1510475019529e+00,
+
+      0.2765157135038e-06, 0.5444186109077e+01, 0.6373574839730e-01,
+      0.2382312465034e-06, 0.2190521137593e+01, 0.2275259891141e+00,
+      0.2808060365077e-06, 0.5735195064841e+01, 0.2535050500000e-01,
+      0.2332175234405e-06, 0.9481985524859e-01, 0.7181332454670e-01,
+      0.2322488199659e-06, 0.5180499361533e+01, 0.8582758298370e-01,
+      0.1881850258423e-06, 0.3219788273885e+01, 0.2118763888447e+01,
+      0.2196111392808e-06, 0.2366941159761e+01, 0.2968341143800e-02,
+      0.2183810335519e-06, 0.4825445110915e+01, 0.7775000683430e-01,
+      0.2002733093326e-06, 0.2457148995307e+01, 0.2093666171530e+00,
+      0.1967111767229e-06, 0.5586291545459e+01, 0.2172315424036e+00,
+
+      0.1568473250543e-06, 0.3708003123320e+01, 0.7429900518901e+00,
+      0.1852528314300e-06, 0.4310638151560e+01, 0.2022531624851e+00,
+      0.1832111226447e-06, 0.1494665322656e+01, 0.3235053470014e+00,
+      0.1746805502310e-06, 0.1451378500784e+01, 0.1385174140878e+00,
+      0.1555730966650e-06, 0.1068040418198e+01, 0.7358765972222e+00,
+      0.1554883462559e-06, 0.2442579035461e+01, 0.5154640627760e+00,
+      0.1638380568746e-06, 0.2597913420625e+00, 0.8531963191132e+00,
+      0.1159938593640e-06, 0.5834512021280e+01, 0.1990721704425e+00,
+      0.1083427965695e-06, 0.5054033177950e+01, 0.5439178814476e+00,
+      0.1156480369431e-06, 0.5325677432457e+01, 0.5257585094865e+00,
+
+      0.1141308860095e-06, 0.2153403923857e+01, 0.5336234347371e+00,
+      0.7913146470946e-07, 0.8642846847027e+00, 0.1478866649112e+01,
+      0.7439752463733e-07, 0.1970628496213e+01, 0.2164800718209e+00,
+      0.7280277104079e-07, 0.6073307250609e+01, 0.2101180877357e+00,
+      0.8319567719136e-07, 0.1954371928334e+01, 0.1692165728891e+01,
+      0.7137705549290e-07, 0.8904989440909e+00, 0.4155522422634e+00,
+      0.6900825396225e-07, 0.2825717714977e+01, 0.1173197218910e+00,
+      0.7245757216635e-07, 0.2481677513331e+01, 0.1265567569334e+01,
+      0.6961165696255e-07, 0.1292955312978e+01, 0.9562891316684e+00,
+      0.7571804456890e-07, 0.3427517575069e+01, 0.1422690933580e-01,
+
+      0.6605425721904e-07, 0.8052192701492e+00, 0.6470106940028e+00,
+      0.7375477357248e-07, 0.1705076390088e+01, 0.1581959461667e+01,
+      0.7041664951470e-07, 0.4848356967891e+00, 0.9597935788730e-01,
+      0.6322199535763e-07, 0.3878069473909e+01, 0.7084920306520e-01,
+      0.5244380279191e-07, 0.2645560544125e+01, 0.5265099800692e+00,
+      0.5143125704988e-07, 0.4834486101370e+01, 0.5328719641544e+00,
+      0.5871866319373e-07, 0.7981472548900e+00, 0.7871412831580e-01,
+      0.6300822573871e-07, 0.5979398788281e+01, 0.2608790314060e+02,
+      0.6062154271548e-07, 0.4108655402756e+01, 0.1114304132498e+00,
+      0.4361912339976e-07, 0.5322624319280e+01, 0.1375773836557e+01,
+
+      0.4417005920067e-07, 0.6240817359284e+01, 0.2770348281756e+00,
+      0.4686806749936e-07, 0.3214977301156e+01, 0.1143987543936e+00,
+      0.3758892132305e-07, 0.5879809634765e+01, 0.1596186371003e+01,
+      0.5151351332319e-07, 0.2893377688007e+00, 0.2228608264996e+00,
+      0.4554683578572e-07, 0.5475427144122e+01, 0.1465949902372e+00,
+      0.3442381385338e-07, 0.5992034796640e+01, 0.5070101000000e-01,
+      0.2831093954933e-07, 0.5367350273914e+01, 0.3092784376656e+00,
+      0.3756267090084e-07, 0.5758171285420e+01, 0.4903339079539e+00,
+      0.2816374679892e-07, 0.1863718700923e+01, 0.2991266627620e+00,
+      0.3419307025569e-07, 0.9524347534130e+00, 0.3518164938661e+00,
+
+      0.2904250494239e-07, 0.5304471615602e+01, 0.1099462426779e+00,
+      0.2471734511206e-07, 0.1297069793530e+01, 0.6256703299991e+00,
+      0.2539620831872e-07, 0.3281126083375e+01, 0.1256615170089e+02,
+      0.2281017868007e-07, 0.1829122133165e+01, 0.6681224869435e+01,
+      0.2275319473335e-07, 0.5797198160181e+01, 0.3932462625300e-02,
+      0.2547755368442e-07, 0.4752697708330e+01, 0.1169588211447e+01,
+      0.2285979669317e-07, 0.1223205292886e+01, 0.1045155034888e+01,
+      0.1913386560994e-07, 0.1757532993389e+01, 0.1155361302111e+01,
+      0.1809020525147e-07, 0.4246116108791e+01, 0.3368040641550e-01,
+      0.1649213300201e-07, 0.1445162890627e+01, 0.4408250688924e+00,
+
+      0.1834972793932e-07, 0.1126917567225e+01, 0.4452511715700e-02,
+      0.1439550648138e-07, 0.6160756834764e+01, 0.9420622223326e+00,
+      0.1487645457041e-07, 0.4358761931792e+01, 0.4123712502208e+00,
+      0.1731729516660e-07, 0.6134456753344e+01, 0.2108507877249e+00,
+      0.1717747163567e-07, 0.1898186084455e+01, 0.2157473718317e+00,
+      0.1418190430374e-07, 0.4180286741266e+01, 0.6521991896920e-01,
+      0.1404844134873e-07, 0.7654053565412e-01, 0.4258542984690e-01,
+      0.1409842846538e-07, 0.4418612420312e+01, 0.2258291676434e+00,
+      0.1090948346291e-07, 0.1260615686131e+01, 0.4226656969313e+00,
+      0.1357577323612e-07, 0.3558248818690e+01, 0.7923417740620e-01,
+
+      0.1018154061960e-07, 0.5676087241256e+01, 0.1456308687557e+00,
+      0.1412073972109e-07, 0.8394392632422e+00, 0.1525316725248e+00,
+      0.1030938326496e-07, 0.1653593274064e+01, 0.1795258541446e+01,
+      0.1180081567104e-07, 0.1285802592036e+01, 0.7032915397480e-01,
+      0.9708510575650e-08, 0.7631889488106e+00, 0.8434341241180e-01,
+      0.9637689663447e-08, 0.4630642649176e+01, 0.1272681024002e+01,
+      0.1068910429389e-07, 0.5294934032165e+01, 0.2123349582968e+00,
+      0.1063716179336e-07, 0.2736266800832e+01, 0.2142632012598e+00,
+      0.1234858713814e-07, 0.1302891146570e+01, 0.1847279083684e+00,
+      0.8912631189738e-08, 0.3570415993621e+01, 0.2648454860559e+01,
+
+      0.1036378285534e-07, 0.4236693440949e+01, 0.1370332435159e+00,
+      0.9667798501561e-08, 0.2960768892398e+01, 0.4376440768498e+00,
+      0.8108314201902e-08, 0.6987781646841e+00, 0.2880807454688e+00,
+      0.7648364324628e-08, 0.2499017863863e+01, 0.2037373330570e+00,
+      0.7286136828406e-08, 0.3787426951665e+01, 0.1129145838217e+00,
+      0.9448237743913e-08, 0.2694354332983e+01, 0.5272426800584e+00,
+      0.9374276106428e-08, 0.4787121277064e+01, 0.5321392641652e+00,
+      0.7100226287462e-08, 0.3530238792101e+00, 0.6288513220417e+00,
+      0.9253056659571e-08, 0.1399478925664e+01, 0.1606092486742e+00,
+      0.6636432145504e-08, 0.3479575438447e+01, 0.1368660381889e+01,
+
+      0.6469975312932e-08, 0.1383669964800e+01, 0.2008557621224e+01,
+      0.7335849729765e-08, 0.1243698166898e+01, 0.9561746721300e-02,
+      0.8743421205855e-08, 0.3776164289301e+01, 0.3801276407308e+00,
+      0.5993635744494e-08, 0.5627122113596e+01, 0.2042657109477e+02,
+      0.5981008479693e-08, 0.1674336636752e+01, 0.2111650433779e+01,
+      0.6188535145838e-08, 0.5214925208672e+01, 0.4305306221819e+00,
+      0.6596074017566e-08, 0.2907653268124e+01, 0.1063314406849e+01,
+      0.6630815126226e-08, 0.2127643669658e+01, 0.8389694097774e+00,
+      0.6156772830040e-08, 0.5082160803295e+01, 0.4234171675140e+00,
+      0.6446960563014e-08, 0.1872100916905e+01, 0.5287268506303e+00,
+
+      0.6429324424668e-08, 0.5610276103577e+01, 0.5306550935933e+00,
+      0.6302232396465e-08, 0.1592152049607e+01, 0.1253008786510e-01,
+      0.6399244436159e-08, 0.2746214421532e+01, 0.5217580628120e+02,
+      0.5474965172558e-08, 0.2317666374383e+01, 0.2221856701002e+01,
+      0.5339293190692e-08, 0.1084724961156e+01, 0.7466759693650e-01,
+      0.5334733683389e-08, 0.3594106067745e+01, 0.7489573444450e-01,
+      0.5392665782110e-08, 0.5630254365606e+01, 0.1055449481598e+01,
+      0.6682075673789e-08, 0.1518480041732e+01, 0.2213766559277e+00,
+      0.5079130495960e-08, 0.2739765115711e+01, 0.2132517061319e+00,
+      0.5077759793261e-08, 0.5290711290094e+01, 0.2133464534247e+00,
+
+      0.4832037368310e-08, 0.1404473217200e+01, 0.7160067364790e-01,
+      0.6463279674802e-08, 0.6038381695210e+01, 0.2209183458640e-01,
+      0.6240592771560e-08, 0.1290170653666e+01, 0.3306188016693e+00,
+      0.4672013521493e-08, 0.3261895939677e+01, 0.7796265773310e-01,
+      0.6500650750348e-08, 0.1154522312095e+01, 0.3884652414254e+00,
+      0.6344161389053e-08, 0.6206111545062e+01, 0.7605151500000e-01,
+      0.4682518370646e-08, 0.5409118796685e+01, 0.1073608853559e+01,
+      0.5329460015591e-08, 0.1202985784864e+01, 0.7287631425543e+00,
+      0.5701588675898e-08, 0.4098715257064e+01, 0.8731175355560e-01,
+      0.6030690867211e-08, 0.4132033218460e+00, 0.9846002785331e+00,
+
+      0.4336256312655e-08, 0.1211415991827e+01, 0.4297791515992e+00,
+      0.4688498808975e-08, 0.3765479072409e+01, 0.2127790306879e+00,
+      0.4675578609335e-08, 0.4265540037226e+01, 0.2138191288687e+00,
+      0.4225578112158e-08, 0.5237566010676e+01, 0.3407705765729e+00,
+      0.5139422230028e-08, 0.1507173079513e+01, 0.7233337363710e-01,
+      0.4619995093571e-08, 0.9023957449848e-01, 0.8603097737811e+00,
+      0.4494776255461e-08, 0.5414930552139e+00, 0.7381754420900e-01,
+      0.4274026276788e-08, 0.4145735303659e+01, 0.7574578717200e-01,
+      0.5018141789353e-08, 0.3344408829055e+01, 0.3180992042600e-02,
+      0.4866163952181e-08, 0.3348534657607e+01, 0.7722995774390e-01,
+
+      0.4111986020501e-08, 0.4198823597220e+00, 0.1451108196653e+00,
+      0.3356142784950e-08, 0.5609144747180e+01, 0.1274714967946e+00,
+      0.4070575554551e-08, 0.7028411059224e+00, 0.3503323232942e+00,
+      0.3257451857278e-08, 0.5624697983086e+01, 0.5296435984654e+00,
+      0.3256973703026e-08, 0.1857842076707e+01, 0.5297383457582e+00,
+      0.3830771508640e-08, 0.4562887279931e+01, 0.9098186128426e+00,
+      0.3725024005962e-08, 0.2358058692652e+00, 0.1084620721060e+00,
+      0.3136763921756e-08, 0.2049731526845e+01, 0.2346394437820e+00,
+      0.3795147256194e-08, 0.2432356296933e+00, 0.1862120789403e+00,
+      0.2877342229911e-08, 0.5631101279387e+01, 0.1905464808669e+01,
+
+      0.3076931798805e-08, 0.1117615737392e+01, 0.3628624111593e+00,
+      0.2734765945273e-08, 0.5899826516955e+01, 0.2131850110243e+00,
+      0.2733405296885e-08, 0.2130562964070e+01, 0.2134131485323e+00,
+      0.2898552353410e-08, 0.3462387048225e+00, 0.5291709230214e+00,
+      0.2893736103681e-08, 0.8534352781543e+00, 0.5302110212022e+00,
+      0.3095717734137e-08, 0.2875061429041e+01, 0.2976424921901e+00,
+      0.2636190425832e-08, 0.2242512846659e+01, 0.1485980103780e+01,
+      0.3645512095537e-08, 0.1354016903958e+01, 0.6044726378023e+00,
+      0.2808173547723e-08, 0.6705114365631e-01, 0.6225157782540e-01,
+      0.2625012866888e-08, 0.4775705748482e+01, 0.5268983110410e-01,
+
+      0.2572233995651e-08, 0.2638924216139e+01, 0.1258454114666e+01,
+      0.2604238824792e-08, 0.4826358927373e+01, 0.2103781122809e+00,
+      0.2596886385239e-08, 0.3200388483118e+01, 0.2162200472757e+00,
+      0.3228057304264e-08, 0.5384848409563e+01, 0.2007689919132e+00,
+      0.2481601798252e-08, 0.5173373487744e+01, 0.1062562936266e+01,
+      0.2745977498864e-08, 0.6250966149853e+01, 0.5651155736444e+00,
+      0.2669878833811e-08, 0.4906001352499e+01, 0.1400015846597e+00,
+      0.3203986611711e-08, 0.5034333010005e+01, 0.7036329877322e+00,
+      0.3354961227212e-08, 0.6108262423137e+01, 0.4549093064213e+00,
+      0.2400407324558e-08, 0.2135399294955e+01, 0.2125476091956e+00,
+
+      0.2379905859802e-08, 0.5893721933961e+01, 0.2140505503610e+00,
+      0.2550844302187e-08, 0.3331940762063e+01, 0.1534957940063e+00,
+      0.2268824211001e-08, 0.1843418461035e+01, 0.2235935264888e+00,
+      0.2464700891204e-08, 0.3029548547230e+01, 0.2091065926078e+00,
+      0.2436814726024e-08, 0.4994717970364e+01, 0.2174915669488e+00,
+      0.2443623894745e-08, 0.2645102591375e+01, 0.1739420156204e+00,
+      0.2318701783838e-08, 0.5700547397897e+01, 0.7530171478090e-01,
+      0.2284448700256e-08, 0.5268898905872e+01, 0.7426161660010e-01,
+      0.2468848123510e-08, 0.5276280575078e+01, 0.2526561439362e+00,
+      0.2814052350303e-08, 0.6130168623475e+01, 0.5636314030725e+00,
+
+      0.2243662755220e-08, 0.6631692457995e+00, 0.8886590321940e-01,
+      0.2330795855941e-08, 0.2499435487702e+01, 0.1056200952181e+01,
+      0.9757679038404e-09, 0.5796846023126e+01, 0.7826370942180e+02 };
+
+/* SSB-to-Sun, T^0, Z */
+   static const double s0z[] = {
+      0.1181255122986e-03, 0.4607918989164e+00, 0.2132990797783e+00,
+      0.1127777651095e-03, 0.4169146331296e+00, 0.5296909721118e+00,
+      0.4777754401806e-04, 0.4582657007130e+01, 0.3813291813120e-01,
+      0.1129354285772e-04, 0.5758735142480e+01, 0.7478166569050e-01,
+     -0.1149543637123e-04, 0.0000000000000e+00, 0.0000000000000e+00,
+      0.3298730512306e-05, 0.5978801994625e+01, 0.4265981595566e+00,
+      0.2733376706079e-05, 0.7665413691040e+00, 0.1059381944224e+01,
+      0.9426389657270e-06, 0.3710201265838e+01, 0.2061856251104e+00,
+      0.8187517749552e-06, 0.3390675605802e+00, 0.2204125344462e+00,
+      0.4080447871819e-06, 0.4552296640088e+00, 0.5225775174439e+00,
+
+      0.3169973017028e-06, 0.3445455899321e+01, 0.5368044267797e+00,
+      0.2438098615549e-06, 0.5664675150648e+01, 0.3664874755930e-01,
+      0.2601897517235e-06, 0.1931894095697e+01, 0.1495633313810e+00,
+      0.2314558080079e-06, 0.3666319115574e+00, 0.3961708870310e-01,
+      0.1962549548002e-06, 0.3167411699020e+01, 0.7626583626240e-01,
+      0.2180518287925e-06, 0.1544420746580e+01, 0.7113454667900e-02,
+      0.1451382442868e-06, 0.1583756740070e+01, 0.1102062672231e+00,
+      0.1358439007389e-06, 0.5239941758280e+01, 0.6398972393349e+00,
+      0.1050585898028e-06, 0.2266958352859e+01, 0.3163918923335e+00,
+      0.1050029870186e-06, 0.2711495250354e+01, 0.4194847048887e+00,
+
+      0.9934920679800e-07, 0.1116208151396e+01, 0.1589072916335e+01,
+      0.1048395331560e-06, 0.3408619600206e+01, 0.1021328554739e+02,
+      0.8370147196668e-07, 0.3810459401087e+01, 0.2535050500000e-01,
+      0.7989856510998e-07, 0.3769910473647e+01, 0.7329749511860e-01,
+      0.5441221655233e-07, 0.2416994903374e+01, 0.1030928125552e+00,
+      0.4610812906784e-07, 0.5858503336994e+01, 0.4337116142245e+00,
+      0.3923022803444e-07, 0.3354170010125e+00, 0.1484170571900e-02,
+      0.2610725582128e-07, 0.5410600646324e+01, 0.6327837846670e+00,
+      0.2455279767721e-07, 0.6120216681403e+01, 0.1162474756779e+01,
+      0.2375530706525e-07, 0.6055443426143e+01, 0.1052268489556e+01,
+
+      0.1782967577553e-07, 0.3146108708004e+01, 0.8460828644453e+00,
+      0.1581687095238e-07, 0.6255496089819e+00, 0.3340612434717e+01,
+      0.1594657672461e-07, 0.3782604300261e+01, 0.1066495398892e+01,
+      0.1563448615040e-07, 0.1997775733196e+01, 0.2022531624851e+00,
+      0.1463624258525e-07, 0.1736316792088e+00, 0.3516457698740e-01,
+      0.1331585056673e-07, 0.4331941830747e+01, 0.9491756770005e+00,
+      0.1130634557637e-07, 0.6152017751825e+01, 0.2968341143800e-02,
+      0.1028949607145e-07, 0.2101792614637e+00, 0.2275259891141e+00,
+      0.1024074971618e-07, 0.4071833211074e+01, 0.5070101000000e-01,
+      0.8826956060303e-08, 0.4861633688145e+00, 0.2093666171530e+00,
+
+      0.8572230171541e-08, 0.5268190724302e+01, 0.4110125927500e-01,
+      0.7649332643544e-08, 0.5134543417106e+01, 0.2608790314060e+02,
+      0.8581673291033e-08, 0.2920218146681e+01, 0.1480791608091e+00,
+      0.8430589300938e-08, 0.3604576619108e+01, 0.2172315424036e+00,
+      0.7776165501012e-08, 0.3772942249792e+01, 0.6373574839730e-01,
+      0.8311070234408e-08, 0.6200412329888e+01, 0.3235053470014e+00,
+      0.6927365212582e-08, 0.4543353113437e+01, 0.8531963191132e+00,
+      0.6791574208598e-08, 0.2882188406238e+01, 0.7181332454670e-01,
+      0.5593100811839e-08, 0.1776646892780e+01, 0.7429900518901e+00,
+      0.4553381853021e-08, 0.3949617611240e+01, 0.7775000683430e-01,
+
+      0.5758000450068e-08, 0.3859251775075e+01, 0.1990721704425e+00,
+      0.4281283457133e-08, 0.1466294631206e+01, 0.2118763888447e+01,
+      0.4206935661097e-08, 0.5421776011706e+01, 0.1104591729320e-01,
+      0.4213751641837e-08, 0.3412048993322e+01, 0.2243449970715e+00,
+      0.5310506239878e-08, 0.5421641370995e+00, 0.5154640627760e+00,
+      0.3827450341320e-08, 0.8887314524995e+00, 0.1510475019529e+00,
+      0.4292435241187e-08, 0.1405043757194e+01, 0.1422690933580e-01,
+      0.3189780702289e-08, 0.1060049293445e+01, 0.1173197218910e+00,
+      0.3226611928069e-08, 0.6270858897442e+01, 0.2164800718209e+00,
+      0.2893897608830e-08, 0.5117563223301e+01, 0.6470106940028e+00,
+
+      0.3239852024578e-08, 0.4079092237983e+01, 0.2101180877357e+00,
+      0.2956892222200e-08, 0.1594917021704e+01, 0.3092784376656e+00,
+      0.2980177912437e-08, 0.5258787667564e+01, 0.4155522422634e+00,
+      0.3163725690776e-08, 0.3854589225479e+01, 0.8582758298370e-01,
+      0.2662262399118e-08, 0.3561326430187e+01, 0.5257585094865e+00,
+      0.2766689135729e-08, 0.3180732086830e+00, 0.1385174140878e+00,
+      0.2411600278464e-08, 0.3324798335058e+01, 0.5439178814476e+00,
+      0.2483527695131e-08, 0.4169069291947e+00, 0.5336234347371e+00,
+      0.7788777276590e-09, 0.1900569908215e+01, 0.5217580628120e+02 };
+
+/* SSB-to-Sun, T^1, X */
+   static const double s1x[] = {
+     -0.1296310361520e-07, 0.0000000000000e+00, 0.0000000000000e+00,
+      0.8975769009438e-08, 0.1128891609250e+01, 0.4265981595566e+00,
+      0.7771113441307e-08, 0.2706039877077e+01, 0.2061856251104e+00,
+      0.7538303866642e-08, 0.2191281289498e+01, 0.2204125344462e+00,
+      0.6061384579336e-08, 0.3248167319958e+01, 0.1059381944224e+01,
+      0.5726994235594e-08, 0.5569981398610e+01, 0.5225775174439e+00,
+      0.5616492836424e-08, 0.5057386614909e+01, 0.5368044267797e+00,
+      0.1010881584769e-08, 0.3473577116095e+01, 0.7113454667900e-02,
+      0.7259606157626e-09, 0.3651858593665e+00, 0.6398972393349e+00,
+      0.8755095026935e-09, 0.1662835408338e+01, 0.4194847048887e+00,
+
+      0.5370491182812e-09, 0.1327673878077e+01, 0.4337116142245e+00,
+      0.5743773887665e-09, 0.4250200846687e+01, 0.2132990797783e+00,
+      0.4408103140300e-09, 0.3598752574277e+01, 0.1589072916335e+01,
+      0.3101892374445e-09, 0.4887822983319e+01, 0.1052268489556e+01,
+      0.3209453713578e-09, 0.9702272295114e+00, 0.5296909721118e+00,
+      0.3017228286064e-09, 0.5484462275949e+01, 0.1066495398892e+01,
+      0.3200700038601e-09, 0.2846613338643e+01, 0.1495633313810e+00,
+      0.2137637279911e-09, 0.5692163292729e+00, 0.3163918923335e+00,
+      0.1899686386727e-09, 0.2061077157189e+01, 0.2275259891141e+00,
+      0.1401994545308e-09, 0.4177771136967e+01, 0.1102062672231e+00,
+
+      0.1578057810499e-09, 0.5782460597335e+01, 0.7626583626240e-01,
+      0.1237713253351e-09, 0.5705900866881e+01, 0.5154640627760e+00,
+      0.1313076837395e-09, 0.5163438179576e+01, 0.3664874755930e-01,
+      0.1184963304860e-09, 0.3054804427242e+01, 0.6327837846670e+00,
+      0.1238130878565e-09, 0.2317292575962e+01, 0.3961708870310e-01,
+      0.1015959527736e-09, 0.2194643645526e+01, 0.7329749511860e-01,
+      0.9017954423714e-10, 0.2868603545435e+01, 0.1990721704425e+00,
+      0.8668024955603e-10, 0.4923849675082e+01, 0.5439178814476e+00,
+      0.7756083930103e-10, 0.3014334135200e+01, 0.9491756770005e+00,
+      0.7536503401741e-10, 0.2704886279769e+01, 0.1030928125552e+00,
+
+      0.5483308679332e-10, 0.6010983673799e+01, 0.8531963191132e+00,
+      0.5184339620428e-10, 0.1952704573291e+01, 0.2093666171530e+00,
+      0.5108658712030e-10, 0.2958575786649e+01, 0.2172315424036e+00,
+      0.5019424524650e-10, 0.1736317621318e+01, 0.2164800718209e+00,
+      0.4909312625978e-10, 0.3167216416257e+01, 0.2101180877357e+00,
+      0.4456638901107e-10, 0.7697579923471e+00, 0.3235053470014e+00,
+      0.4227030350925e-10, 0.3490910137928e+01, 0.6373574839730e-01,
+      0.4095456040093e-10, 0.5178888984491e+00, 0.6470106940028e+00,
+      0.4990537041422e-10, 0.3323887668974e+01, 0.1422690933580e-01,
+      0.4321170010845e-10, 0.4288484987118e+01, 0.7358765972222e+00,
+
+      0.3544072091802e-10, 0.6021051579251e+01, 0.5265099800692e+00,
+      0.3480198638687e-10, 0.4600027054714e+01, 0.5328719641544e+00,
+      0.3440287244435e-10, 0.4349525970742e+01, 0.8582758298370e-01,
+      0.3330628322713e-10, 0.2347391505082e+01, 0.1104591729320e-01,
+      0.2973060707184e-10, 0.4789409286400e+01, 0.5257585094865e+00,
+      0.2932606766089e-10, 0.5831693799927e+01, 0.5336234347371e+00,
+      0.2876972310953e-10, 0.2692638514771e+01, 0.1173197218910e+00,
+      0.2827488278556e-10, 0.2056052487960e+01, 0.2022531624851e+00,
+      0.2515028239756e-10, 0.7411863262449e+00, 0.9597935788730e-01,
+      0.2853033744415e-10, 0.3948481024894e+01, 0.2118763888447e+01 };
+
+/* SSB-to-Sun, T^1, Y */
+   static const double s1y[] = {
+      0.8989047573576e-08, 0.5840593672122e+01, 0.4265981595566e+00,
+      0.7815938401048e-08, 0.1129664707133e+01, 0.2061856251104e+00,
+      0.7550926713280e-08, 0.6196589104845e+00, 0.2204125344462e+00,
+      0.6056556925895e-08, 0.1677494667846e+01, 0.1059381944224e+01,
+      0.5734142698204e-08, 0.4000920852962e+01, 0.5225775174439e+00,
+      0.5614341822459e-08, 0.3486722577328e+01, 0.5368044267797e+00,
+      0.1028678147656e-08, 0.1877141024787e+01, 0.7113454667900e-02,
+      0.7270792075266e-09, 0.5077167301739e+01, 0.6398972393349e+00,
+      0.8734141726040e-09, 0.9069550282609e-01, 0.4194847048887e+00,
+      0.5377371402113e-09, 0.6039381844671e+01, 0.4337116142245e+00,
+
+      0.4729719431571e-09, 0.2153086311760e+01, 0.2132990797783e+00,
+      0.4458052820973e-09, 0.5059830025565e+01, 0.5296909721118e+00,
+      0.4406855467908e-09, 0.2027971692630e+01, 0.1589072916335e+01,
+      0.3101659310977e-09, 0.3317677981860e+01, 0.1052268489556e+01,
+      0.3016749232545e-09, 0.3913703482532e+01, 0.1066495398892e+01,
+      0.3198541352656e-09, 0.1275513098525e+01, 0.1495633313810e+00,
+      0.2142065389871e-09, 0.5301351614597e+01, 0.3163918923335e+00,
+      0.1902615247592e-09, 0.4894943352736e+00, 0.2275259891141e+00,
+      0.1613410990871e-09, 0.2449891130437e+01, 0.1102062672231e+00,
+      0.1576992165097e-09, 0.4211421447633e+01, 0.7626583626240e-01,
+
+      0.1241637259894e-09, 0.4140803368133e+01, 0.5154640627760e+00,
+      0.1313974830355e-09, 0.3591920305503e+01, 0.3664874755930e-01,
+      0.1181697118258e-09, 0.1506314382788e+01, 0.6327837846670e+00,
+      0.1238239742779e-09, 0.7461405378404e+00, 0.3961708870310e-01,
+      0.1010107068241e-09, 0.6271010795475e+00, 0.7329749511860e-01,
+      0.9226316616509e-10, 0.1259158839583e+01, 0.1990721704425e+00,
+      0.8664946419555e-10, 0.3353244696934e+01, 0.5439178814476e+00,
+      0.7757230468978e-10, 0.1447677295196e+01, 0.9491756770005e+00,
+      0.7693168628139e-10, 0.1120509896721e+01, 0.1030928125552e+00,
+      0.5487897454612e-10, 0.4439380426795e+01, 0.8531963191132e+00,
+
+      0.5196118677218e-10, 0.3788856619137e+00, 0.2093666171530e+00,
+      0.5110853339935e-10, 0.1386879372016e+01, 0.2172315424036e+00,
+      0.5027804534813e-10, 0.1647881805466e+00, 0.2164800718209e+00,
+      0.4922485922674e-10, 0.1594315079862e+01, 0.2101180877357e+00,
+      0.6155599524400e-10, 0.0000000000000e+00, 0.0000000000000e+00,
+      0.4447147832161e-10, 0.5480720918976e+01, 0.3235053470014e+00,
+      0.4144691276422e-10, 0.1931371033660e+01, 0.6373574839730e-01,
+      0.4099950625452e-10, 0.5229611294335e+01, 0.6470106940028e+00,
+      0.5060541682953e-10, 0.1731112486298e+01, 0.1422690933580e-01,
+      0.4293615946300e-10, 0.2714571038925e+01, 0.7358765972222e+00,
+
+      0.3545659845763e-10, 0.4451041444634e+01, 0.5265099800692e+00,
+      0.3479112041196e-10, 0.3029385448081e+01, 0.5328719641544e+00,
+      0.3438516493570e-10, 0.2778507143731e+01, 0.8582758298370e-01,
+      0.3297341285033e-10, 0.7898709807584e+00, 0.1104591729320e-01,
+      0.2972585818015e-10, 0.3218785316973e+01, 0.5257585094865e+00,
+      0.2931707295017e-10, 0.4260731012098e+01, 0.5336234347371e+00,
+      0.2897198149403e-10, 0.1120753978101e+01, 0.1173197218910e+00,
+      0.2832293240878e-10, 0.4597682717827e+00, 0.2022531624851e+00,
+      0.2864348326612e-10, 0.2169939928448e+01, 0.9597935788730e-01,
+      0.2852714675471e-10, 0.2377659870578e+01, 0.2118763888447e+01 };
+
+/* SSB-to-Sun, T^1, Z */
+   static const double s1z[] = {
+      0.5444220475678e-08, 0.1803825509310e+01, 0.2132990797783e+00,
+      0.3883412695596e-08, 0.4668616389392e+01, 0.5296909721118e+00,
+      0.1334341434551e-08, 0.0000000000000e+00, 0.0000000000000e+00,
+      0.3730001266883e-09, 0.5401405918943e+01, 0.2061856251104e+00,
+      0.2894929197956e-09, 0.4932415609852e+01, 0.2204125344462e+00,
+      0.2857950357701e-09, 0.3154625362131e+01, 0.7478166569050e-01,
+      0.2499226432292e-09, 0.3657486128988e+01, 0.4265981595566e+00,
+      0.1937705443593e-09, 0.5740434679002e+01, 0.1059381944224e+01,
+      0.1374894396320e-09, 0.1712857366891e+01, 0.5368044267797e+00,
+      0.1217248678408e-09, 0.2312090870932e+01, 0.5225775174439e+00,
+
+      0.7961052740870e-10, 0.5283368554163e+01, 0.3813291813120e-01,
+      0.4979225949689e-10, 0.4298290471860e+01, 0.4194847048887e+00,
+      0.4388552286597e-10, 0.6145515047406e+01, 0.7113454667900e-02,
+      0.2586835212560e-10, 0.3019448001809e+01, 0.6398972393349e+00 };
+
+/* SSB-to-Sun, T^2, X */
+   static const double s2x[] = {
+      0.1603551636587e-11, 0.4404109410481e+01, 0.2061856251104e+00,
+      0.1556935889384e-11, 0.4818040873603e+00, 0.2204125344462e+00,
+      0.1182594414915e-11, 0.9935762734472e+00, 0.5225775174439e+00,
+      0.1158794583180e-11, 0.3353180966450e+01, 0.5368044267797e+00,
+      0.9597358943932e-12, 0.5567045358298e+01, 0.2132990797783e+00,
+      0.6511516579605e-12, 0.5630872420788e+01, 0.4265981595566e+00,
+      0.7419792747688e-12, 0.2156188581957e+01, 0.5296909721118e+00,
+      0.3951972655848e-12, 0.1981022541805e+01, 0.1059381944224e+01,
+      0.4478223877045e-12, 0.0000000000000e+00, 0.0000000000000e+00 };
+
+/* SSB-to-Sun, T^2, Y */
+   static const double s2y[] = {
+      0.1609114495091e-11, 0.2831096993481e+01, 0.2061856251104e+00,
+      0.1560330784946e-11, 0.5193058213906e+01, 0.2204125344462e+00,
+      0.1183535479202e-11, 0.5707003443890e+01, 0.5225775174439e+00,
+      0.1158183066182e-11, 0.1782400404928e+01, 0.5368044267797e+00,
+      0.1032868027407e-11, 0.4036925452011e+01, 0.2132990797783e+00,
+      0.6540142847741e-12, 0.4058241056717e+01, 0.4265981595566e+00,
+      0.7305236491596e-12, 0.6175401942957e+00, 0.5296909721118e+00,
+     -0.5580725052968e-12, 0.0000000000000e+00, 0.0000000000000e+00,
+      0.3946122651015e-12, 0.4108265279171e+00, 0.1059381944224e+01 };
+
+/* SSB-to-Sun, T^2, Z */
+   static const double s2z[] = {
+      0.3749920358054e-12, 0.3230285558668e+01, 0.2132990797783e+00,
+      0.2735037220939e-12, 0.6154322683046e+01, 0.5296909721118e+00 };
+
+/* Pointers to coefficient arrays, in x,y,z sets */
+   static const double *ce0[] = { e0x, e0y, e0z },
+                       *ce1[] = { e1x, e1y, e1z },
+                       *ce2[] = { e2x, e2y, e2z },
+                       *cs0[] = { s0x, s0y, s0z },
+                       *cs1[] = { s1x, s1y, s1z },
+                       *cs2[] = { s2x, s2y, s2z };
+   const double *coeffs;
+
+/* Numbers of terms for each component of the model, in x,y,z sets */
+   static const int ne0[3] = {(int)(sizeof e0x / sizeof (double) / 3),
+                              (int)(sizeof e0y / sizeof (double) / 3),
+                              (int)(sizeof e0z / sizeof (double) / 3) },
+                    ne1[3] = {(int)(sizeof e1x / sizeof (double) / 3),
+                              (int)(sizeof e1y / sizeof (double) / 3),
+                              (int)(sizeof e1z / sizeof (double) / 3) },
+                    ne2[3] = {(int)(sizeof e2x / sizeof (double) / 3),
+                              (int)(sizeof e2y / sizeof (double) / 3),
+                              (int)(sizeof e2z / sizeof (double) / 3) },
+                    ns0[3] = {(int)(sizeof s0x / sizeof (double) / 3),
+                              (int)(sizeof s0y / sizeof (double) / 3),
+                              (int)(sizeof s0z / sizeof (double) / 3) },
+                    ns1[3] = {(int)(sizeof s1x / sizeof (double) / 3),
+                              (int)(sizeof s1y / sizeof (double) / 3),
+                              (int)(sizeof s1z / sizeof (double) / 3) },
+                    ns2[3] = {(int)(sizeof s2x / sizeof (double) / 3),
+                              (int)(sizeof s2y / sizeof (double) / 3),
+                              (int)(sizeof s2z / sizeof (double) / 3) };
+   int nterms;
+
+/* Miscellaneous */
+   int jstat, i, j;
+   double t, t2, xyz, xyzd, a, b, c, ct, p, cp,
+          ph[3], vh[3], pb[3], vb[3], x, y, z;
+
+/*--------------------------------------------------------------------*/
+
+/* Time since reference epoch, Julian years. */
+   t = ((date1 - DJ00) + date2) / DJY;
+   t2 = t*t;
+
+/* Set status. */
+   jstat = fabs(t) <= 100.0 ? 0 : 1;
+
+/* X then Y then Z. */
+   for (i = 0; i < 3; i++) {
+
+   /* Initialize position and velocity component. */
+      xyz = 0.0;
+      xyzd = 0.0;
+
+   /* ------------------------------------------------ */
+   /* Obtain component of Sun to Earth ecliptic vector */
+   /* ------------------------------------------------ */
+
+   /* Sun to Earth, T^0 terms. */
+      coeffs = ce0[i];
+      nterms = ne0[i];
+      for (j = 0; j < nterms; j++) {
+         a = *coeffs++;
+         b = *coeffs++;
+         c = *coeffs++;
+         p = b + c*t;
+         xyz  += a*cos(p);
+         xyzd -= a*c*sin(p);
+      }
+
+   /* Sun to Earth, T^1 terms. */
+      coeffs = ce1[i];
+      nterms = ne1[i];
+      for (j = 0; j < nterms; j++) {
+         a = *coeffs++;
+         b = *coeffs++;
+         c = *coeffs++;
+         ct = c*t;
+         p = b + ct;
+         cp = cos(p);
+         xyz  += a*t*cp;
+         xyzd += a*( cp - ct*sin(p) );
+      }
+
+   /* Sun to Earth, T^2 terms. */
+      coeffs = ce2[i];
+      nterms = ne2[i];
+      for (j = 0; j < nterms; j++) {
+         a = *coeffs++;
+         b = *coeffs++;
+         c = *coeffs++;
+         ct = c*t;
+         p = b + ct;
+         cp = cos(p);
+         xyz  += a*t2*cp;
+         xyzd += a*t*( 2.0*cp - ct*sin(p) );
+      }
+
+   /* Heliocentric Earth position and velocity component. */
+      ph[i] = xyz;
+      vh[i] = xyzd / DJY;
+
+   /* ------------------------------------------------ */
+   /* Obtain component of SSB to Earth ecliptic vector */
+   /* ------------------------------------------------ */
+
+   /* SSB to Sun, T^0 terms. */
+      coeffs = cs0[i];
+      nterms = ns0[i];
+      for (j = 0; j < nterms; j++) {
+         a = *coeffs++;
+         b = *coeffs++;
+         c = *coeffs++;
+         p = b + c*t;
+         xyz  += a*cos(p);
+         xyzd -= a*c*sin(p);
+      }
+
+   /* SSB to Sun, T^1 terms. */
+      coeffs = cs1[i];
+      nterms = ns1[i];
+      for (j = 0; j < nterms; j++) {
+         a = *coeffs++;
+         b = *coeffs++;
+         c = *coeffs++;
+         ct = c*t;
+         p = b + ct;
+         cp = cos(p);
+         xyz  += a*t*cp;
+         xyzd += a*(cp - ct*sin(p));
+      }
+
+   /* SSB to Sun, T^2 terms. */
+      coeffs = cs2[i];
+      nterms = ns2[i];
+      for (j = 0; j < nterms; j++) {
+         a = *coeffs++;
+         b = *coeffs++;
+         c = *coeffs++;
+         ct = c*t;
+         p = b + ct;
+         cp = cos(p);
+         xyz  += a*t2*cp;
+         xyzd += a*t*(2.0*cp - ct*sin(p));
+     }
+
+   /* Barycentric Earth position and velocity component. */
+     pb[i] = xyz;
+     vb[i] = xyzd / DJY;
+
+   /* Next Cartesian component. */
+   }
+
+/* Rotate from ecliptic to BCRS coordinates. */
+
+   x = ph[0];
+   y = ph[1];
+   z = ph[2];
+   pvh[0][0] =      x + am12*y + am13*z;
+   pvh[0][1] = am21*x + am22*y + am23*z;
+   pvh[0][2] =          am32*y + am33*z;
+
+   x = vh[0];
+   y = vh[1];
+   z = vh[2];
+   pvh[1][0] =      x + am12*y + am13*z;
+   pvh[1][1] = am21*x + am22*y + am23*z;
+   pvh[1][2] =          am32*y + am33*z;
+
+   x = pb[0];
+   y = pb[1];
+   z = pb[2];
+   pvb[0][0] =      x + am12*y + am13*z;
+   pvb[0][1] = am21*x + am22*y + am23*z;
+   pvb[0][2] =          am32*y + am33*z;
+
+   x = vb[0];
+   y = vb[1];
+   z = vb[2];
+   pvb[1][0] =      x + am12*y + am13*z;
+   pvb[1][1] = am21*x + am22*y + am23*z;
+   pvb[1][2] =          am32*y + am33*z;
+
+/* Return the status. */
+   return jstat;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+double iauEqeq94(double date1, double date2)
+/*
+**  - - - - - - - - - -
+**   i a u E q e q 9 4
+**  - - - - - - - - - -
+**
+**  Equation of the equinoxes, IAU 1994 model.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  canonical model.
+**
+**  Given:
+**     date1,date2   double     TDB date (Note 1)
+**
+**  Returned (function value):
+**                   double     equation of the equinoxes (Note 2)
+**
+**  Notes:
+**
+**  1) The date date1+date2 is a Julian Date, apportioned in any
+**     convenient way between the two arguments.  For example,
+**     JD(TT)=2450123.7 could be expressed in any of these ways,
+**     among others:
+**
+**            date1          date2
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in
+**     cases where the loss of several decimal digits of resolution
+**     is acceptable.  The J2000 method is best matched to the way
+**     the argument is handled internally and will deliver the
+**     optimum resolution.  The MJD method and the date & time methods
+**     are both good compromises between resolution and convenience.
+**
+**  2) The result, which is in radians, operates in the following sense:
+**
+**        Greenwich apparent ST = GMST + equation of the equinoxes
+**
+**  Called:
+**     iauNut80     nutation, IAU 1980
+**     iauObl80     mean obliquity, IAU 1980
+**
+**  References:
+**
+**     IAU Resolution C7, Recommendation 3 (1994).
+**
+**     Capitaine, N. & Gontier, A.-M., 1993, Astron. Astrophys., 275,
+**     645-650.
+**
+**  This revision:  2008 May 24
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double t,  om,  dpsi,  deps,  eps0, ee;
+
+
+/* Interval between fundamental epoch J2000.0 and given date (JC). */
+   t = ((date1 - DJ00) + date2) / DJC;
+
+/* Longitude of the mean ascending node of the lunar orbit on the */
+/* ecliptic, measured from the mean equinox of date. */
+   om = iauAnpm((450160.280 + (-482890.539
+           + (7.455 + 0.008 * t) * t) * t) * DAS2R
+           + fmod(-5.0 * t, 1.0) * D2PI);
+
+/* Nutation components and mean obliquity. */
+   iauNut80(date1, date2, &dpsi, &deps);
+   eps0 = iauObl80(date1, date2);
+
+/* Equation of the equinoxes. */
+   ee = dpsi*cos(eps0) + DAS2R*(0.00264*sin(om) + 0.000063*sin(om+om));
+
+   return ee;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+double iauEra00(double dj1, double dj2)
+/*
+**  - - - - - - - - -
+**   i a u E r a 0 0
+**  - - - - - - - - -
+**
+**  Earth rotation angle (IAU 2000 model).
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  canonical model.
+**
+**  Given:
+**     dj1,dj2   double    UT1 as a 2-part Julian Date (see note)
+**
+**  Returned (function value):
+**               double    Earth rotation angle (radians), range 0-2pi
+**
+**  Notes:
+**
+**  1) The UT1 date dj1+dj2 is a Julian Date, apportioned in any
+**     convenient way between the arguments dj1 and dj2.  For example,
+**     JD(UT1)=2450123.7 could be expressed in any of these ways,
+**     among others:
+**
+**             dj1            dj2
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in
+**     cases where the loss of several decimal digits of resolution
+**     is acceptable.  The J2000 and MJD methods are good compromises
+**     between resolution and convenience.  The date & time method is
+**     best matched to the algorithm used:  maximum precision is
+**     delivered when the dj1 argument is for 0hrs UT1 on the day in
+**     question and the dj2 argument lies in the range 0 to 1, or vice
+**     versa.
+**
+**  2) The algorithm is adapted from Expression 22 of Capitaine et al.
+**     2000.  The time argument has been expressed in days directly,
+**     and, to retain precision, integer contributions have been
+**     eliminated.  The same formulation is given in IERS Conventions
+**     (2003), Chap. 5, Eq. 14.
+**
+**  Called:
+**     iauAnp       normalize angle into range 0 to 2pi
+**
+**  References:
+**
+**     Capitaine N., Guinot B. and McCarthy D.D, 2000, Astron.
+**     Astrophys., 355, 398-405.
+**
+**     McCarthy, D. D., Petit, G. (eds.), IERS Conventions (2003),
+**     IERS Technical Note No. 32, BKG (2004)
+**
+**  This revision:  2008 May 24
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double d1, d2, t, f, theta;
+
+
+/* Days since fundamental epoch. */
+   if (dj1 < dj2) {
+      d1 = dj1;
+      d2 = dj2;
+   } else {
+      d1 = dj2;
+      d2 = dj1;
+   }
+   t = d1 + (d2- DJ00);
+
+/* Fractional part of T (days). */
+   f = fmod(d1, 1.0) + fmod(d2, 1.0);
+
+/* Earth rotation angle at this UT1. */
+   theta = iauAnp(D2PI * (f + 0.7790572732640
+                            + 0.00273781191135448 * t));
+
+   return theta;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+double iauFad03(double t)
+/*
+**  - - - - - - - - -
+**   i a u F a d 0 3
+**  - - - - - - - - -
+**
+**  Fundamental argument, IERS Conventions (2003):
+**  mean elongation of the Moon from the Sun.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  canonical model.
+**
+**  Given:
+**     t     double    TDB, Julian centuries since J2000.0 (Note 1)
+**
+**  Returned (function value):
+**           double    D, radians (Note 2)
+**
+**  Notes:
+**
+**  1) Though t is strictly TDB, it is usually more convenient to use
+**     TT, which makes no significant difference.
+**
+**  2) The expression used is as adopted in IERS Conventions (2003) and
+**     is from Simon et al. (1994).
+**
+**  References:
+**
+**     McCarthy, D. D., Petit, G. (eds.), IERS Conventions (2003),
+**     IERS Technical Note No. 32, BKG (2004)
+**
+**     Simon, J.-L., Bretagnon, P., Chapront, J., Chapront-Touze, M.,
+**     Francou, G., Laskar, J. 1994, Astron.Astrophys. 282, 663-683
+**
+**  This revision:  2009 December 16
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double a;
+
+
+/* Mean elongation of the Moon from the Sun (IERS Conventions 2003). */
+   a = fmod(          1072260.703692 +
+             t * ( 1602961601.2090 +
+             t * (        - 6.3706 +
+             t * (          0.006593 +
+             t * (        - 0.00003169 ) ) ) ), TURNAS ) * DAS2R;
+
+   return a;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+double iauFae03(double t)
+/*
+**  - - - - - - - - -
+**   i a u F a e 0 3
+**  - - - - - - - - -
+**
+**  Fundamental argument, IERS Conventions (2003):
+**  mean longitude of Earth.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  canonical model.
+**
+**  Given:
+**     t     double    TDB, Julian centuries since J2000.0 (Note 1)
+**
+**  Returned (function value):
+**           double    mean longitude of Earth, radians (Note 2)
+**
+**  Notes:
+**
+**  1) Though t is strictly TDB, it is usually more convenient to use
+**     TT, which makes no significant difference.
+**
+**  2) The expression used is as adopted in IERS Conventions (2003) and
+**     comes from Souchay et al. (1999) after Simon et al. (1994).
+**
+**  References:
+**
+**     McCarthy, D. D., Petit, G. (eds.), IERS Conventions (2003),
+**     IERS Technical Note No. 32, BKG (2004)
+**
+**     Simon, J.-L., Bretagnon, P., Chapront, J., Chapront-Touze, M.,
+**     Francou, G., Laskar, J. 1994, Astron.Astrophys. 282, 663-683
+**
+**     Souchay, J., Loysel, B., Kinoshita, H., Folgueira, M. 1999,
+**     Astron.Astrophys.Supp.Ser. 135, 111
+**
+**  This revision:  2009 December 16
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double a;
+
+
+/* Mean longitude of Earth (IERS Conventions 2003). */
+   a = fmod(1.753470314 + 628.3075849991 * t, D2PI);
+
+   return a;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+double iauFaf03(double t)
+/*
+**  - - - - - - - - -
+**   i a u F a f 0 3
+**  - - - - - - - - -
+**
+**  Fundamental argument, IERS Conventions (2003):
+**  mean longitude of the Moon minus mean longitude of the ascending
+**  node.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  canonical model.
+**
+**  Given:
+**     t     double    TDB, Julian centuries since J2000.0 (Note 1)
+**
+**  Returned (function value):
+**           double    F, radians (Note 2)
+**
+**  Notes:
+**
+**  1) Though t is strictly TDB, it is usually more convenient to use
+**     TT, which makes no significant difference.
+**
+**  2) The expression used is as adopted in IERS Conventions (2003) and
+**     is from Simon et al. (1994).
+**
+**  References:
+**
+**     McCarthy, D. D., Petit, G. (eds.), IERS Conventions (2003),
+**     IERS Technical Note No. 32, BKG (2004)
+**
+**     Simon, J.-L., Bretagnon, P., Chapront, J., Chapront-Touze, M.,
+**     Francou, G., Laskar, J. 1994, Astron.Astrophys. 282, 663-683
+**
+**  This revision:  2009 December 16
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double a;
+
+
+/* Mean longitude of the Moon minus that of the ascending node */
+/* (IERS Conventions 2003).                                    */
+   a = fmod(           335779.526232 +
+             t * ( 1739527262.8478 +
+             t * (       - 12.7512 +
+             t * (        - 0.001037 +
+             t * (          0.00000417 ) ) ) ), TURNAS ) * DAS2R;
+
+   return a;
+
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+double iauFaju03(double t)
+/*
+**  - - - - - - - - - -
+**   i a u F a j u 0 3
+**  - - - - - - - - - -
+**
+**  Fundamental argument, IERS Conventions (2003):
+**  mean longitude of Jupiter.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  canonical model.
+**
+**  Given:
+**     t     double    TDB, Julian centuries since J2000.0 (Note 1)
+**
+**  Returned (function value):
+**           double    mean longitude of Jupiter, radians (Note 2)
+**
+**  Notes:
+**
+**  1) Though t is strictly TDB, it is usually more convenient to use
+**     TT, which makes no significant difference.
+**
+**  2) The expression used is as adopted in IERS Conventions (2003) and
+**     comes from Souchay et al. (1999) after Simon et al. (1994).
+**
+**  References:
+**
+**     McCarthy, D. D., Petit, G. (eds.), IERS Conventions (2003),
+**     IERS Technical Note No. 32, BKG (2004)
+**
+**     Simon, J.-L., Bretagnon, P., Chapront, J., Chapront-Touze, M.,
+**     Francou, G., Laskar, J. 1994, Astron.Astrophys. 282, 663-683
+**
+**     Souchay, J., Loysel, B., Kinoshita, H., Folgueira, M. 1999,
+**     Astron.Astrophys.Supp.Ser. 135, 111
+**
+**  This revision:  2009 December 16
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double a;
+
+
+/* Mean longitude of Jupiter (IERS Conventions 2003). */
+   a = fmod(0.599546497 + 52.9690962641 * t, D2PI);
+
+   return a;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+double iauFal03(double t)
+/*
+**  - - - - - - - - -
+**   i a u F a l 0 3
+**  - - - - - - - - -
+**
+**  Fundamental argument, IERS Conventions (2003):
+**  mean anomaly of the Moon.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  canonical model.
+**
+**  Given:
+**     t     double    TDB, Julian centuries since J2000.0 (Note 1)
+**
+**  Returned (function value):
+**           double    l, radians (Note 2)
+**
+**  Notes:
+**
+**  1) Though t is strictly TDB, it is usually more convenient to use
+**     TT, which makes no significant difference.
+**
+**  2) The expression used is as adopted in IERS Conventions (2003) and
+**     is from Simon et al. (1994).
+**
+**  References:
+**
+**     McCarthy, D. D., Petit, G. (eds.), IERS Conventions (2003),
+**     IERS Technical Note No. 32, BKG (2004)
+**
+**     Simon, J.-L., Bretagnon, P., Chapront, J., Chapront-Touze, M.,
+**     Francou, G., Laskar, J. 1994, Astron.Astrophys. 282, 663-683
+**
+**  This revision:  2009 December 16
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double a;
+
+
+/* Mean anomaly of the Moon (IERS Conventions 2003). */
+   a = fmod(           485868.249036  +
+             t * ( 1717915923.2178 +
+             t * (         31.8792 +
+             t * (          0.051635 +
+             t * (        - 0.00024470 ) ) ) ), TURNAS ) * DAS2R;
+
+   return a;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+double iauFalp03(double t)
+/*
+**  - - - - - - - - - -
+**   i a u F a l p 0 3
+**  - - - - - - - - - -
+**
+**  Fundamental argument, IERS Conventions (2003):
+**  mean anomaly of the Sun.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  canonical model.
+**
+**  Given:
+**     t     double    TDB, Julian centuries since J2000.0 (Note 1)
+**
+**  Returned (function value):
+**           double    l', radians (Note 2)
+**
+**  Notes:
+**
+**  1) Though t is strictly TDB, it is usually more convenient to use
+**     TT, which makes no significant difference.
+**
+**  2) The expression used is as adopted in IERS Conventions (2003) and
+**     is from Simon et al. (1994).
+**
+**  References:
+**
+**     McCarthy, D. D., Petit, G. (eds.), IERS Conventions (2003),
+**     IERS Technical Note No. 32, BKG (2004)
+**
+**     Simon, J.-L., Bretagnon, P., Chapront, J., Chapront-Touze, M.,
+**     Francou, G., Laskar, J. 1994, Astron.Astrophys. 282, 663-683
+**
+**  This revision:  2009 December 16
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double a;
+
+
+/* Mean anomaly of the Sun (IERS Conventions 2003). */
+   a = fmod(         1287104.793048 +
+             t * ( 129596581.0481 +
+             t * (       - 0.5532 +
+             t * (         0.000136 +
+             t * (       - 0.00001149 ) ) ) ), TURNAS ) * DAS2R;
+
+   return a;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+double iauFama03(double t)
+/*
+**  - - - - - - - - - -
+**   i a u F a m a 0 3
+**  - - - - - - - - - -
+**
+**  Fundamental argument, IERS Conventions (2003):
+**  mean longitude of Mars.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  canonical model.
+**
+**  Given:
+**     t     double    TDB, Julian centuries since J2000.0 (Note 1)
+**
+**  Returned (function value):
+**           double    mean longitude of Mars, radians (Note 2)
+**
+**  Notes:
+**
+**  1) Though t is strictly TDB, it is usually more convenient to use
+**     TT, which makes no significant difference.
+**
+**  2) The expression used is as adopted in IERS Conventions (2003) and
+**     comes from Souchay et al. (1999) after Simon et al. (1994).
+**
+**  References:
+**
+**     McCarthy, D. D., Petit, G. (eds.), IERS Conventions (2003),
+**     IERS Technical Note No. 32, BKG (2004)
+**
+**     Simon, J.-L., Bretagnon, P., Chapront, J., Chapront-Touze, M.,
+**     Francou, G., Laskar, J. 1994, Astron.Astrophys. 282, 663-683
+**
+**     Souchay, J., Loysel, B., Kinoshita, H., Folgueira, M. 1999,
+**     Astron.Astrophys.Supp.Ser. 135, 111
+**
+**  This revision:  2009 December 16
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double a;
+
+
+/* Mean longitude of Mars (IERS Conventions 2003). */
+   a = fmod(6.203480913 + 334.0612426700 * t, D2PI);
+
+   return a;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+double iauFame03(double t)
+/*
+**  - - - - - - - - - -
+**   i a u F a m e 0 3
+**  - - - - - - - - - -
+**
+**  Fundamental argument, IERS Conventions (2003):
+**  mean longitude of Mercury.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  canonical model.
+**
+**  Given:
+**     t     double    TDB, Julian centuries since J2000.0 (Note 1)
+**
+**  Returned (function value):
+**           double    mean longitude of Mercury, radians (Note 2)
+**
+**  Notes:
+**
+**  1) Though t is strictly TDB, it is usually more convenient to use
+**     TT, which makes no significant difference.
+**
+**  2) The expression used is as adopted in IERS Conventions (2003) and
+**     comes from Souchay et al. (1999) after Simon et al. (1994).
+**
+**  References:
+**
+**     McCarthy, D. D., Petit, G. (eds.), IERS Conventions (2003),
+**     IERS Technical Note No. 32, BKG (2004)
+**
+**     Simon, J.-L., Bretagnon, P., Chapront, J., Chapront-Touze, M.,
+**     Francou, G., Laskar, J. 1994, Astron.Astrophys. 282, 663-683
+**
+**     Souchay, J., Loysel, B., Kinoshita, H., Folgueira, M. 1999,
+**     Astron.Astrophys.Supp.Ser. 135, 111
+**
+**  This revision:  2009 December 16
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double a;
+
+
+/* Mean longitude of Mercury (IERS Conventions 2003). */
+   a = fmod(4.402608842 + 2608.7903141574 * t, D2PI);
+
+   return a;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+double iauFane03(double t)
+/*
+**  - - - - - - - - - -
+**   i a u F a n e 0 3
+**  - - - - - - - - - -
+**
+**  Fundamental argument, IERS Conventions (2003):
+**  mean longitude of Neptune.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  canonical model.
+**
+**  Given:
+**     t     double    TDB, Julian centuries since J2000.0 (Note 1)
+**
+**  Returned (function value):
+**           double    mean longitude of Neptune, radians (Note 2)
+**
+**  Notes:
+**
+**  1) Though t is strictly TDB, it is usually more convenient to use
+**     TT, which makes no significant difference.
+**
+**  2) The expression used is as adopted in IERS Conventions (2003) and
+**     is adapted from Simon et al. (1994).
+**
+**  References:
+**
+**     McCarthy, D. D., Petit, G. (eds.), IERS Conventions (2003),
+**     IERS Technical Note No. 32, BKG (2004)
+**
+**     Simon, J.-L., Bretagnon, P., Chapront, J., Chapront-Touze, M.,
+**     Francou, G., Laskar, J. 1994, Astron.Astrophys. 282, 663-683
+**
+**  This revision:  2009 December 16
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double a;
+
+
+/* Mean longitude of Neptune (IERS Conventions 2003). */
+   a = fmod(5.311886287 + 3.8133035638 * t, D2PI);
+
+   return a;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+double iauFaom03(double t)
+/*
+**  - - - - - - - - - -
+**   i a u F a o m 0 3
+**  - - - - - - - - - -
+**
+**  Fundamental argument, IERS Conventions (2003):
+**  mean longitude of the Moon's ascending node.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  canonical model.
+**
+**  Given:
+**     t     double    TDB, Julian centuries since J2000.0 (Note 1)
+**
+**  Returned (function value):
+**           double    Omega, radians (Note 2)
+**
+**  Notes:
+**
+**  1) Though t is strictly TDB, it is usually more convenient to use
+**     TT, which makes no significant difference.
+**
+**  2) The expression used is as adopted in IERS Conventions (2003) and
+**     is from Simon et al. (1994).
+**
+**  References:
+**
+**     McCarthy, D. D., Petit, G. (eds.), IERS Conventions (2003),
+**     IERS Technical Note No. 32, BKG (2004)
+**
+**     Simon, J.-L., Bretagnon, P., Chapront, J., Chapront-Touze, M.,
+**     Francou, G., Laskar, J. 1994, Astron.Astrophys. 282, 663-683
+**
+**  This revision:  2009 December 16
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double a;
+
+
+/* Mean longitude of the Moon's ascending node */
+/* (IERS Conventions 2003).                    */
+   a = fmod(          450160.398036 +
+             t * ( - 6962890.5431 +
+             t * (         7.4722 +
+             t * (         0.007702 +
+             t * (       - 0.00005939 ) ) ) ), TURNAS ) * DAS2R;
+
+   return a;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+double iauFapa03(double t)
+/*
+**  - - - - - - - - - -
+**   i a u F a p a 0 3
+**  - - - - - - - - - -
+**
+**  Fundamental argument, IERS Conventions (2003):
+**  general accumulated precession in longitude.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  canonical model.
+**
+**  Given:
+**     t     double    TDB, Julian centuries since J2000.0 (Note 1)
+**
+**  Returned (function value):
+**           double    general precession in longitude, radians (Note 2)
+**
+**  Notes:
+**
+**  1) Though t is strictly TDB, it is usually more convenient to use
+**     TT, which makes no significant difference.
+**
+**  2) The expression used is as adopted in IERS Conventions (2003).  It
+**     is taken from Kinoshita & Souchay (1990) and comes originally
+**     from Lieske et al. (1977).
+**
+**  References:
+**
+**     Kinoshita, H. and Souchay J. 1990, Celest.Mech. and Dyn.Astron.
+**     48, 187
+**
+**     Lieske, J.H., Lederle, T., Fricke, W. & Morando, B. 1977,
+**     Astron.Astrophys. 58, 1-16
+**
+**     McCarthy, D. D., Petit, G. (eds.), IERS Conventions (2003),
+**     IERS Technical Note No. 32, BKG (2004)
+**
+**  This revision:  2009 December 16
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double a;
+
+
+/* General accumulated precession in longitude. */
+   a = (0.024381750 + 0.00000538691 * t) * t;
+
+   return a;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+double iauFasa03(double t)
+/*
+**  - - - - - - - - - -
+**   i a u F a s a 0 3
+**  - - - - - - - - - -
+**
+**  Fundamental argument, IERS Conventions (2003):
+**  mean longitude of Saturn.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  canonical model.
+**
+**  Given:
+**     t     double    TDB, Julian centuries since J2000.0 (Note 1)
+**
+**  Returned (function value):
+**           double    mean longitude of Saturn, radians (Note 2)
+**
+**  Notes:
+**
+**  1) Though t is strictly TDB, it is usually more convenient to use
+**     TT, which makes no significant difference.
+**
+**  2) The expression used is as adopted in IERS Conventions (2003) and
+**     comes from Souchay et al. (1999) after Simon et al. (1994).
+**
+**  References:
+**
+**     McCarthy, D. D., Petit, G. (eds.), IERS Conventions (2003),
+**     IERS Technical Note No. 32, BKG (2004)
+**
+**     Simon, J.-L., Bretagnon, P., Chapront, J., Chapront-Touze, M.,
+**     Francou, G., Laskar, J. 1994, Astron.Astrophys. 282, 663-683
+**
+**     Souchay, J., Loysel, B., Kinoshita, H., Folgueira, M. 1999,
+**     Astron.Astrophys.Supp.Ser. 135, 111
+**
+**  This revision:  2009 December 16
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double a;
+
+
+/* Mean longitude of Saturn (IERS Conventions 2003). */
+   a = fmod(0.874016757 + 21.3299104960 * t, D2PI);
+
+   return a;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+double iauFaur03(double t)
+/*
+**  - - - - - - - - - -
+**   i a u F a u r 0 3
+**  - - - - - - - - - -
+**
+**  Fundamental argument, IERS Conventions (2003):
+**  mean longitude of Uranus.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  canonical model.
+**
+**  Given:
+**     t     double    TDB, Julian centuries since J2000.0 (Note 1)
+**
+**  Returned  (function value):
+**           double    mean longitude of Uranus, radians (Note 2)
+**
+**  Notes:
+**
+**  1) Though t is strictly TDB, it is usually more convenient to use
+**     TT, which makes no significant difference.
+**
+**  2) The expression used is as adopted in IERS Conventions (2003) and
+**     is adapted from Simon et al. (1994).
+**
+**  References:
+**
+**     McCarthy, D. D., Petit, G. (eds.), IERS Conventions (2003),
+**     IERS Technical Note No. 32, BKG (2004)
+**
+**     Simon, J.-L., Bretagnon, P., Chapront, J., Chapront-Touze, M.,
+**     Francou, G., Laskar, J. 1994, Astron.Astrophys. 282, 663-683
+**
+**  This revision:  2009 December 16
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double a;
+
+
+/* Mean longitude of Uranus (IERS Conventions 2003). */
+   a = fmod(5.481293872 + 7.4781598567 * t, D2PI);
+
+   return a;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+double iauFave03(double t)
+/*
+**  - - - - - - - - - -
+**   i a u F a v e 0 3
+**  - - - - - - - - - -
+**
+**  Fundamental argument, IERS Conventions (2003):
+**  mean longitude of Venus.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  canonical model.
+**
+**  Given:
+**     t     double    TDB, Julian centuries since J2000.0 (Note 1)
+**
+**  Returned (function value):
+**           double    mean longitude of Venus, radians (Note 2)
+**
+**  Notes:
+**
+**  1) Though t is strictly TDB, it is usually more convenient to use
+**     TT, which makes no significant difference.
+**
+**  2) The expression used is as adopted in IERS Conventions (2003) and
+**     comes from Souchay et al. (1999) after Simon et al. (1994).
+**
+**  References:
+**
+**     McCarthy, D. D., Petit, G. (eds.), IERS Conventions (2003),
+**     IERS Technical Note No. 32, BKG (2004)
+**
+**     Simon, J.-L., Bretagnon, P., Chapront, J., Chapront-Touze, M.,
+**     Francou, G., Laskar, J. 1994, Astron.Astrophys. 282, 663-683
+**
+**     Souchay, J., Loysel, B., Kinoshita, H., Folgueira, M. 1999,
+**     Astron.Astrophys.Supp.Ser. 135, 111
+**
+**  This revision:  2009 December 16
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double a;
+
+
+/* Mean longitude of Venus (IERS Conventions 2003). */
+   a = fmod(3.176146697 + 1021.3285546211 * t, D2PI);
+
+   return a;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauFk52h(double r5, double d5,
+              double dr5, double dd5, double px5, double rv5,
+              double *rh, double *dh,
+              double *drh, double *ddh, double *pxh, double *rvh)
+/*
+**  - - - - - - - - -
+**   i a u F k 5 2 h
+**  - - - - - - - - -
+**
+**  Transform FK5 (J2000.0) star data into the Hipparcos system.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given (all FK5, equinox J2000.0, epoch J2000.0):
+**     r5      double    RA (radians)
+**     d5      double    Dec (radians)
+**     dr5     double    proper motion in RA (dRA/dt, rad/Jyear)
+**     dd5     double    proper motion in Dec (dDec/dt, rad/Jyear)
+**     px5     double    parallax (arcsec)
+**     rv5     double    radial velocity (km/s, positive = receding)
+**
+**  Returned (all Hipparcos, epoch J2000.0):
+**     rh      double    RA (radians)
+**     dh      double    Dec (radians)
+**     drh     double    proper motion in RA (dRA/dt, rad/Jyear)
+**     ddh     double    proper motion in Dec (dDec/dt, rad/Jyear)
+**     pxh     double    parallax (arcsec)
+**     rvh     double    radial velocity (km/s, positive = receding)
+**
+**  Notes:
+**
+**  1) This function transforms FK5 star positions and proper motions
+**     into the system of the Hipparcos catalog.
+**
+**  2) The proper motions in RA are dRA/dt rather than
+**     cos(Dec)*dRA/dt, and are per year rather than per century.
+**
+**  3) The FK5 to Hipparcos transformation is modeled as a pure
+**     rotation and spin;  zonal errors in the FK5 catalog are not
+**     taken into account.
+**
+**  4) See also iauH2fk5, iauFk5hz, iauHfk5z.
+**
+**  Called:
+**     iauStarpv    star catalog data to space motion pv-vector
+**     iauFk5hip    FK5 to Hipparcos rotation and spin
+**     iauRxp       product of r-matrix and p-vector
+**     iauPxp       vector product of two p-vectors
+**     iauPpp       p-vector plus p-vector
+**     iauPvstar    space motion pv-vector to star catalog data
+**
+**  Reference:
+**
+**     F.Mignard & M.Froeschle, Astron. Astrophys. 354, 732-739 (2000).
+**
+**  This revision:  2009 December 17
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   int i;
+   double pv5[2][3], r5h[3][3], s5h[3], wxp[3], vv[3], pvh[2][3];
+
+
+/* FK5 barycentric position/velocity pv-vector (normalized). */
+   iauStarpv(r5, d5, dr5, dd5, px5, rv5, pv5);
+
+/* FK5 to Hipparcos orientation matrix and spin vector. */
+   iauFk5hip(r5h, s5h);
+
+/* Make spin units per day instead of per year. */
+   for ( i = 0; i < 3; s5h[i++] /= 365.25 );
+
+/* Orient the FK5 position into the Hipparcos system. */
+   iauRxp(r5h, pv5[0], pvh[0]);
+
+/* Apply spin to the position giving an extra space motion component. */
+   iauPxp(pv5[0], s5h, wxp);
+
+/* Add this component to the FK5 space motion. */
+   iauPpp(wxp, pv5[1], vv);
+
+/* Orient the FK5 space motion into the Hipparcos system. */
+   iauRxp(r5h, vv, pvh[1]);
+
+/* Hipparcos pv-vector to spherical. */
+   iauPvstar(pvh, rh, dh, drh, ddh, pxh, rvh);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauFk5hip(double r5h[3][3], double s5h[3])
+/*
+**  - - - - - - - - - -
+**   i a u F k 5 h i p
+**  - - - - - - - - - -
+**
+**  FK5 to Hipparcos rotation and spin.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Returned:
+**     r5h   double[3][3]  r-matrix: FK5 rotation wrt Hipparcos (Note 2)
+**     s5h   double[3]     r-vector: FK5 spin wrt Hipparcos (Note 3)
+**
+**  Notes:
+**
+**  1) This function models the FK5 to Hipparcos transformation as a
+**     pure rotation and spin;  zonal errors in the FK5 catalogue are
+**     not taken into account.
+**
+**  2) The r-matrix r5h operates in the sense:
+**
+**           P_Hipparcos = r5h x P_FK5
+**
+**     where P_FK5 is a p-vector in the FK5 frame, and P_Hipparcos is
+**     the equivalent Hipparcos p-vector.
+**
+**  3) The r-vector s5h represents the time derivative of the FK5 to
+**     Hipparcos rotation.  The units are radians per year (Julian,
+**     TDB).
+**
+**  Called:
+**     iauRv2m      r-vector to r-matrix
+**
+**  Reference:
+**
+**     F.Mignard & M.Froeschle, Astron. Astrophys. 354, 732-739 (2000).
+**
+**  This revision:  2009 March 14
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double v[3];
+
+/* FK5 wrt Hipparcos orientation and spin (radians, radians/year) */
+   double epx, epy, epz;
+   double omx, omy, omz;
+
+
+   epx = -19.9e-3 * DAS2R;
+   epy =  -9.1e-3 * DAS2R;
+   epz =  22.9e-3 * DAS2R;
+
+   omx = -0.30e-3 * DAS2R;
+   omy =  0.60e-3 * DAS2R;
+   omz =  0.70e-3 * DAS2R;
+
+/* FK5 to Hipparcos orientation expressed as an r-vector. */
+   v[0] = epx;
+   v[1] = epy;
+   v[2] = epz;
+
+/* Re-express as an r-matrix. */
+   iauRv2m(v, r5h);
+
+/* Hipparcos wrt FK5 spin expressed as an r-vector. */
+   s5h[0] = omx;
+   s5h[1] = omy;
+   s5h[2] = omz;
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauFk5hz(double r5, double d5, double date1, double date2,
+              double *rh, double *dh)
+/*
+**  - - - - - - - - -
+**   i a u F k 5 h z
+**  - - - - - - - - -
+**
+**  Transform an FK5 (J2000.0) star position into the system of the
+**  Hipparcos catalogue, assuming zero Hipparcos proper motion.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     r5           double   FK5 RA (radians), equinox J2000.0, at date
+**     d5           double   FK5 Dec (radians), equinox J2000.0, at date
+**     date1,date2  double   TDB date (Notes 1,2)
+**
+**  Returned:
+**     rh           double   Hipparcos RA (radians)
+**     dh           double   Hipparcos Dec (radians)
+**
+**  Notes:
+**
+**  1) This function converts a star position from the FK5 system to
+**     the Hipparcos system, in such a way that the Hipparcos proper
+**     motion is zero.  Because such a star has, in general, a non-zero
+**     proper motion in the FK5 system, the function requires the date
+**     at which the position in the FK5 system was determined.
+**
+**  2) The TT date date1+date2 is a Julian Date, apportioned in any
+**     convenient way between the two arguments.  For example,
+**     JD(TT)=2450123.7 could be expressed in any of these ways,
+**     among others:
+**
+**            date1          date2
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in
+**     cases where the loss of several decimal digits of resolution
+**     is acceptable.  The J2000 method is best matched to the way
+**     the argument is handled internally and will deliver the
+**     optimum resolution.  The MJD method and the date & time methods
+**     are both good compromises between resolution and convenience.
+**
+**  3) The FK5 to Hipparcos transformation is modeled as a pure
+**     rotation and spin;  zonal errors in the FK5 catalogue are not
+**     taken into account.
+**
+**  4) The position returned by this function is in the Hipparcos
+**     reference system but at date date1+date2.
+**
+**  5) See also iauFk52h, iauH2fk5, iauHfk5z.
+**
+**  Called:
+**     iauS2c       spherical coordinates to unit vector
+**     iauFk5hip    FK5 to Hipparcos rotation and spin
+**     iauSxp       multiply p-vector by scalar
+**     iauRv2m      r-vector to r-matrix
+**     iauTrxp      product of transpose of r-matrix and p-vector
+**     iauPxp       vector product of two p-vectors
+**     iauC2s       p-vector to spherical
+**     iauAnp       normalize angle into range 0 to 2pi
+**
+**  Reference:
+**
+**     F.Mignard & M.Froeschle, 2000, Astron.Astrophys. 354, 732-739.
+**
+**  This revision:  2009 December 17
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double t, p5e[3], r5h[3][3], s5h[3], vst[3], rst[3][3], p5[3],
+          ph[3], w;
+
+
+/* Interval from given date to fundamental epoch J2000.0 (JY). */
+   t = - ((date1 - DJ00) + date2) / DJY;
+
+/* FK5 barycentric position vector. */
+   iauS2c(r5, d5, p5e);
+
+/* FK5 to Hipparcos orientation matrix and spin vector. */
+   iauFk5hip(r5h, s5h);
+
+/* Accumulated Hipparcos wrt FK5 spin over that interval. */
+   iauSxp(t, s5h, vst);
+
+/* Express the accumulated spin as a rotation matrix. */
+   iauRv2m(vst, rst);
+
+/* Derotate the vector's FK5 axes back to date. */
+   iauTrxp(rst, p5e, p5);
+
+/* Rotate the vector into the Hipparcos system. */
+   iauRxp(r5h, p5, ph);
+
+/* Hipparcos vector to spherical. */
+   iauC2s(ph, &w, dh);
+   *rh = iauAnp(w);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauFw2m(double gamb, double phib, double psi, double eps,
+             double r[3][3])
+/*
+**  - - - - - - - -
+**   i a u F w 2 m
+**  - - - - - - - -
+**
+**  Form rotation matrix given the Fukushima-Williams angles.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     gamb     double         F-W angle gamma_bar (radians)
+**     phib     double         F-W angle phi_bar (radians)
+**     psi      double         F-W angle psi (radians)
+**     eps      double         F-W angle epsilon (radians)
+**
+**  Returned:
+**     r        double[3][3]   rotation matrix
+**
+**  Notes:
+**
+**  1) Naming the following points:
+**
+**           e = J2000.0 ecliptic pole,
+**           p = GCRS pole,
+**           E = ecliptic pole of date,
+**     and   P = CIP,
+**
+**     the four Fukushima-Williams angles are as follows:
+**
+**        gamb = gamma = epE
+**        phib = phi = pE
+**        psi = psi = pEP
+**        eps = epsilon = EP
+**
+**  2) The matrix representing the combined effects of frame bias,
+**     precession and nutation is:
+**
+**        NxPxB = R_1(-eps).R_3(-psi).R_1(phib).R_3(gamb)
+**
+**  3) Three different matrices can be constructed, depending on the
+**     supplied angles:
+**
+**     o  To obtain the nutation x precession x frame bias matrix,
+**        generate the four precession angles, generate the nutation
+**        components and add them to the psi_bar and epsilon_A angles,
+**        and call the present function.
+**
+**     o  To obtain the precession x frame bias matrix, generate the
+**        four precession angles and call the present function.
+**
+**     o  To obtain the frame bias matrix, generate the four precession
+**        angles for date J2000.0 and call the present function.
+**
+**     The nutation-only and precession-only matrices can if necessary
+**     be obtained by combining these three appropriately.
+**
+**  Called:
+**     iauIr        initialize r-matrix to identity
+**     iauRz        rotate around Z-axis
+**     iauRx        rotate around X-axis
+**
+**  Reference:
+**
+**     Hilton, J. et al., 2006, Celest.Mech.Dyn.Astron. 94, 351
+**
+**  This revision:  2009 December 17
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+/* Construct the matrix. */
+   iauIr(r);
+   iauRz(gamb, r);
+   iauRx(phib, r);
+   iauRz(-psi, r);
+   iauRx(-eps, r);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauFw2xy(double gamb, double phib, double psi, double eps,
+              double *x, double *y)
+/*
+**  - - - - - - - - -
+**   i a u F w 2 x y
+**  - - - - - - - - -
+**
+**  CIP X,Y given Fukushima-Williams bias-precession-nutation angles.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     gamb     double    F-W angle gamma_bar (radians)
+**     phib     double    F-W angle phi_bar (radians)
+**     psi      double    F-W angle psi (radians)
+**     eps      double    F-W angle epsilon (radians)
+**
+**  Returned:
+**     x,y      double    CIP X,Y ("radians")
+**
+**  Notes:
+**
+**  1) Naming the following points:
+**
+**           e = J2000.0 ecliptic pole,
+**           p = GCRS pole
+**           E = ecliptic pole of date,
+**     and   P = CIP,
+**
+**     the four Fukushima-Williams angles are as follows:
+**
+**        gamb = gamma = epE
+**        phib = phi = pE
+**        psi = psi = pEP
+**        eps = epsilon = EP
+**
+**  2) The matrix representing the combined effects of frame bias,
+**     precession and nutation is:
+**
+**        NxPxB = R_1(-epsA).R_3(-psi).R_1(phib).R_3(gamb)
+**
+**     X,Y are elements (3,1) and (3,2) of the matrix.
+**
+**  Called:
+**     iauFw2m      F-W angles to r-matrix
+**     iauBpn2xy    extract CIP X,Y coordinates from NPB matrix
+**
+**  Reference:
+**
+**     Hilton, J. et al., 2006, Celest.Mech.Dyn.Astron. 94, 351
+**
+**  This revision:  2009 December 17
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double r[3][3];
+
+
+/* Form NxPxB matrix. */
+   iauFw2m(gamb, phib, psi, eps, r);
+
+/* Extract CIP X,Y. */
+   iauBpn2xy(r, x, y);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+int iauGc2gd ( int n, double xyz[3],
+               double *elong, double *phi, double *height )
+/*
+**  - - - - - - - - -
+**   i a u G c 2 g d
+**  - - - - - - - - -
+**
+**  Transform geocentric coordinates to geodetic using the specified
+**  reference ellipsoid.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards of Fundamental Astronomy) software collection.
+**
+**  Status:  canonical transformation.
+**
+**  Given:
+**     n       int        ellipsoid identifier (Note 1)
+**     xyz     double[3]  geocentric vector (Note 2)
+**
+**  Returned:
+**     elong   double     longitude (radians, east +ve)
+**     phi     double     latitude (geodetic, radians, Note 3)
+**     height  double     height above ellipsoid (geodetic, Notes 2,3)
+**
+**  Returned (function value):
+**            int         status:  0 = OK
+**                                -1 = illegal identifier (Note 3)
+**                                -2 = internal error (Note 3)
+**
+**  Notes:
+**
+**  1) The identifier n is a number that specifies the choice of
+**     reference ellipsoid.  The following are supported:
+**
+**        n    ellipsoid
+**
+**        1     WGS84
+**        2     GRS80
+**        3     WGS72
+**
+**     The n value has no significance outside the SOFA software.  For
+**     convenience, symbols WGS84 etc. are defined in sofam.h.
+**
+**  2) The geocentric vector (xyz, given) and height (height, returned)
+**     are in meters.
+**
+**  3) An error status -1 means that the identifier n is illegal.  An
+**     error status -2 is theoretically impossible.  In all error cases,
+**     phi and height are both set to -1e9.
+**
+**  4) The inverse transformation is performed in the function iauGd2gc.
+**
+**  Called:
+**     iauEform     Earth reference ellipsoids
+**     iauGc2gde    geocentric to geodetic transformation, general
+**
+**  This revision:  2012 Febuary 23
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   int j;
+   double a, f;
+
+
+/* Obtain reference ellipsoid parameters. */
+   j = iauEform ( n, &a, &f );
+
+/* If OK, transform x,y,z to longitude, geodetic latitude, height. */
+   if ( j == 0 ) {
+      j = iauGc2gde ( a, f, xyz, elong, phi, height );
+      if ( j < 0 ) j = -2;
+   }
+
+/* Deal with any errors. */
+   if ( j < 0 ) {
+      *phi = -1e9;
+      *height = -1e9;
+   }
+
+/* Return the status. */
+   return j;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+
+}
+#include "sofam.h"
+
+int iauGc2gde ( double a, double f, double xyz[3],
+                double *elong, double *phi, double *height )
+/*
+**  - - - - - - - - - -
+**   i a u G c 2 g d e
+**  - - - - - - - - - -
+**
+**  Transform geocentric coordinates to geodetic for a reference
+**  ellipsoid of specified form.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     a       double     equatorial radius (Notes 2,4)
+**     f       double     flattening (Note 3)
+**     xyz     double[3]  geocentric vector (Note 4)
+**
+**  Returned:
+**     elong   double     longitude (radians, east +ve)
+**     phi     double     latitude (geodetic, radians)
+**     height  double     height above ellipsoid (geodetic, Note 4)
+**
+**  Returned (function value):
+**             int        status:  0 = OK
+**                                -1 = illegal f
+**                                -2 = illegal a
+**
+**  Notes:
+**
+**  1) This function is based on the GCONV2H Fortran subroutine by
+**     Toshio Fukushima (see reference).
+**
+**  2) The equatorial radius, a, can be in any units, but meters is
+**     the conventional choice.
+**
+**  3) The flattening, f, is (for the Earth) a value around 0.00335,
+**     i.e. around 1/298.
+**
+**  4) The equatorial radius, a, and the geocentric vector, xyz,
+**     must be given in the same units, and determine the units of
+**     the returned height, height.
+**
+**  5) If an error occurs (status < 0), elong, phi and height are
+**     unchanged.
+**
+**  6) The inverse transformation is performed in the function
+**     iauGd2gce.
+**
+**  7) The transformation for a standard ellipsoid (such as WGS84) can
+**     more conveniently be performed by calling iauGc2gd, which uses a
+**     numerical code to identify the required A and F values.
+**
+**  Reference:
+**
+**     Fukushima, T., "Transformation from Cartesian to geodetic
+**     coordinates accelerated by Halley's method", J.Geodesy (2006)
+**     79: 689-693
+**
+**  This revision:  2012 February 23
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double aeps2, e2, e4t, ec2, ec, b, x, y, z, p2, absz, p, s0, pn, zc,
+                 c0, c02, c03, s02, s03, a02, a0, a03, d0, f0, b0, s1,
+                 cc, s12, cc2;
+
+
+/* ------------- */
+/* Preliminaries */
+/* ------------- */
+
+/* Validate ellipsoid parameters. */
+   if ( f < 0.0 || f >= 1.0 ) return -1;
+   if ( a <= 0.0 ) return -2;
+
+/* Functions of ellipsoid parameters (with further validation of f). */
+   aeps2 = a*a * 1e-32;
+   e2 = (2.0 - f) * f;
+   e4t = e2*e2 * 1.5;
+   ec2 = 1.0 - e2;
+   if ( ec2 <= 0.0 ) return -1;
+   ec = sqrt(ec2);
+   b = a * ec;
+
+/* Cartesian components. */
+   x = xyz[0];
+   y = xyz[1];
+   z = xyz[2];
+
+/* Distance from polar axis squared. */
+   p2 = x*x + y*y;
+
+/* Longitude. */
+   *elong = p2 != 0.0 ? atan2(y, x) : 0.0;
+
+/* Unsigned z-coordinate. */
+   absz = fabs(z);
+
+/* Proceed unless polar case. */
+   if ( p2 > aeps2 ) {
+
+   /* Distance from polar axis. */
+      p = sqrt(p2);
+
+   /* Normalization. */
+      s0 = absz / a;
+      pn = p / a;
+      zc = ec * s0;
+
+   /* Prepare Newton correction factors. */
+      c0 = ec * pn;
+      c02 = c0 * c0;
+      c03 = c02 * c0;
+      s02 = s0 * s0;
+      s03 = s02 * s0;
+      a02 = c02 + s02;
+      a0 = sqrt(a02);
+      a03 = a02 * a0;
+      d0 = zc*a03 + e2*s03;
+      f0 = pn*a03 - e2*c03;
+
+   /* Prepare Halley correction factor. */
+      b0 = e4t * s02 * c02 * pn * (a0 - ec);
+      s1 = d0*f0 - b0*s0;
+      cc = ec * (f0*f0 - b0*c0);
+
+   /* Evaluate latitude and height. */
+      *phi = atan(s1/cc);
+      s12 = s1 * s1;
+      cc2 = cc * cc;
+      *height = (p*cc + absz*s1 - a * sqrt(ec2*s12 + cc2)) /
+                                                        sqrt(s12 + cc2);
+   } else {
+
+   /* Exception: pole. */
+      *phi = DPI / 2.0;
+      *height = absz - b;
+   }
+
+/* Restore sign of latitude. */
+   if ( z < 0 ) *phi = -*phi;
+
+/* OK status. */
+   return 0;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+
+}
+#include "sofam.h"
+
+int iauGd2gc ( int n, double elong, double phi, double height,
+               double xyz[3] )
+/*
+**  - - - - - - - - -
+**   i a u G d 2 g c
+**  - - - - - - - - -
+**
+**  Transform geodetic coordinates to geocentric using the specified
+**  reference ellipsoid.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards of Fundamental Astronomy) software collection.
+**
+**  Status:  canonical transformation.
+**
+**  Given:
+**     n       int        ellipsoid identifier (Note 1)
+**     elong   double     longitude (radians, east +ve)
+**     phi     double     latitude (geodetic, radians, Note 3)
+**     height  double     height above ellipsoid (geodetic, Notes 2,3)
+**
+**  Returned:
+**     xyz     double[3]  geocentric vector (Note 2)
+**
+**  Returned (function value):
+**             int        status:  0 = OK
+**                                -1 = illegal identifier (Note 3)
+**                                -2 = illegal case (Note 3)
+**
+**  Notes:
+**
+**  1) The identifier n is a number that specifies the choice of
+**     reference ellipsoid.  The following are supported:
+**
+**        n    ellipsoid
+**
+**        1     WGS84
+**        2     GRS80
+**        3     WGS72
+**
+**     The n value has no significance outside the SOFA software.  For
+**     convenience, symbols WGS84 etc. are defined in sofam.h.
+**
+**  2) The height (height, given) and the geocentric vector (xyz,
+**     returned) are in meters.
+**
+**  3) No validation is performed on the arguments elong, phi and
+**     height.  An error status -1 means that the identifier n is
+**     illegal.  An error status -2 protects against cases that would
+**     lead to arithmetic exceptions.  In all error cases, xyz is set
+**     to zeros.
+**
+**  4) The inverse transformation is performed in the function iauGc2gd.
+**
+**  Called:
+**     iauEform     Earth reference ellipsoids
+**     iauGd2gce    geodetic to geocentric transformation, general
+**     iauZp        zero p-vector
+**
+**  This revision:  2012 February 23
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   int j;
+   double a, f;
+
+
+/* Obtain reference ellipsoid parameters. */
+   j = iauEform ( n, &a, &f );
+
+/* If OK, transform longitude, geodetic latitude, height to x,y,z. */
+   if ( j == 0 ) {
+      j = iauGd2gce ( a, f, elong, phi, height, xyz );
+      if ( j != 0 ) j = -2;
+   }
+
+/* Deal with any errors. */
+   if ( j != 0 ) iauZp ( xyz );
+
+/* Return the status. */
+   return j;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+
+}
+#include "sofam.h"
+
+int iauGd2gce ( double a, double f, double elong, double phi,
+                double height, double xyz[3] )
+/*
+**  - - - - - - - - - -
+**   i a u G d 2 g c e
+**  - - - - - - - - - -
+**
+**  Transform geodetic coordinates to geocentric for a reference
+**  ellipsoid of specified form.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     a       double     equatorial radius (Notes 1,4)
+**     f       double     flattening (Notes 2,4)
+**     elong   double     longitude (radians, east +ve)
+**     phi     double     latitude (geodetic, radians, Note 4)
+**     height  double     height above ellipsoid (geodetic, Notes 3,4)
+**
+**  Returned:
+**     xyz     double[3]  geocentric vector (Note 3)
+**
+**  Returned (function value):
+**             int        status:  0 = OK
+**                                -1 = illegal case (Note 4)
+**  Notes:
+**
+**  1) The equatorial radius, a, can be in any units, but meters is
+**     the conventional choice.
+**
+**  2) The flattening, f, is (for the Earth) a value around 0.00335,
+**     i.e. around 1/298.
+**
+**  3) The equatorial radius, a, and the height, height, must be
+**     given in the same units, and determine the units of the
+**     returned geocentric vector, xyz.
+**
+**  4) No validation is performed on individual arguments.  The error
+**     status -1 protects against (unrealistic) cases that would lead
+**     to arithmetic exceptions.  If an error occurs, xyz is unchanged.
+**
+**  5) The inverse transformation is performed in the function
+**     iauGc2gde.
+**
+**  6) The transformation for a standard ellipsoid (such as WGS84) can
+**     more conveniently be performed by calling iauGd2gc,  which uses a
+**     numerical code to identify the required a and f values.
+**
+**  References:
+**
+**     Green, R.M., Spherical Astronomy, Cambridge University Press,
+**     (1985) Section 4.5, p96.
+**
+**     Explanatory Supplement to the Astronomical Almanac,
+**     P. Kenneth Seidelmann (ed), University Science Books (1992),
+**     Section 4.22, p202.
+**
+**  This revision:  2012 February 23
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double sp, cp, w, d, ac, as, r;
+
+
+/* Functions of geodetic latitude. */
+   sp = sin(phi);
+   cp = cos(phi);
+   w = 1.0 - f;
+   w = w * w;
+   d = cp*cp + w*sp*sp;
+   if ( d <= 0.0 ) return -1;
+   ac = a / sqrt(d);
+   as = w * ac;
+
+/* Geocentric vector. */
+   r = (ac + height) * cp;
+   xyz[0] = r * cos(elong);
+   xyz[1] = r * sin(elong);
+   xyz[2] = (as + height) * sp;
+
+/* Success. */
+   return 0;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+
+}
+#include "sofam.h"
+
+double iauGmst00(double uta, double utb, double tta, double ttb)
+/*
+**  - - - - - - - - - -
+**   i a u G m s t 0 0
+**  - - - - - - - - - -
+**
+**  Greenwich mean sidereal time (model consistent with IAU 2000
+**  resolutions).
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  canonical model.
+**
+**  Given:
+**     uta,utb    double    UT1 as a 2-part Julian Date (Notes 1,2)
+**     tta,ttb    double    TT as a 2-part Julian Date (Notes 1,2)
+**
+**  Returned (function value):
+**                double    Greenwich mean sidereal time (radians)
+**
+**  Notes:
+**
+**  1) The UT1 and TT dates uta+utb and tta+ttb respectively, are both
+**     Julian Dates, apportioned in any convenient way between the
+**     argument pairs.  For example, JD=2450123.7 could be expressed in
+**     any of these ways, among others:
+**
+**            Part A         Part B
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in
+**     cases where the loss of several decimal digits of resolution
+**     is acceptable (in the case of UT;  the TT is not at all critical
+**     in this respect).  The J2000 and MJD methods are good compromises
+**     between resolution and convenience.  For UT, the date & time
+**     method is best matched to the algorithm that is used by the Earth
+**     Rotation Angle function, called internally:  maximum precision is
+**     delivered when the uta argument is for 0hrs UT1 on the day in
+**     question and the utb argument lies in the range 0 to 1, or vice
+**     versa.
+**
+**  2) Both UT1 and TT are required, UT1 to predict the Earth rotation
+**     and TT to predict the effects of precession.  If UT1 is used for
+**     both purposes, errors of order 100 microarcseconds result.
+**
+**  3) This GMST is compatible with the IAU 2000 resolutions and must be
+**     used only in conjunction with other IAU 2000 compatible
+**     components such as precession-nutation and equation of the
+**     equinoxes.
+**
+**  4) The result is returned in the range 0 to 2pi.
+**
+**  5) The algorithm is from Capitaine et al. (2003) and IERS
+**     Conventions 2003.
+**
+**  Called:
+**     iauEra00     Earth rotation angle, IAU 2000
+**     iauAnp       normalize angle into range 0 to 2pi
+**
+**  References:
+**
+**     Capitaine, N., Wallace, P.T. and McCarthy, D.D., "Expressions to
+**     implement the IAU 2000 definition of UT1", Astronomy &
+**     Astrophysics, 406, 1135-1149 (2003)
+**
+**     McCarthy, D. D., Petit, G. (eds.), IERS Conventions (2003),
+**     IERS Technical Note No. 32, BKG (2004)
+**
+**  This revision:  2009 March 16
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double t, gmst;
+
+
+/* TT Julian centuries since J2000.0. */
+   t = ((tta - DJ00) + ttb) / DJC;
+
+/* Greenwich Mean Sidereal Time, IAU 2000. */
+   gmst = iauAnp(iauEra00(uta, utb) +
+                   (     0.014506   +
+                   (  4612.15739966 +
+                   (     1.39667721 +
+                   (    -0.00009344 +
+                   (     0.00001882 )
+          * t) * t) * t) * t) * DAS2R);
+
+   return gmst;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+double iauGmst06(double uta, double utb, double tta, double ttb)
+/*
+**  - - - - - - - - - -
+**   i a u G m s t 0 6
+**  - - - - - - - - - -
+**
+**  Greenwich mean sidereal time (consistent with IAU 2006 precession).
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  canonical model.
+**
+**  Given:
+**     uta,utb    double    UT1 as a 2-part Julian Date (Notes 1,2)
+**     tta,ttb    double    TT as a 2-part Julian Date (Notes 1,2)
+**
+**  Returned (function value):
+**                double    Greenwich mean sidereal time (radians)
+**
+**  Notes:
+**
+**  1) The UT1 and TT dates uta+utb and tta+ttb respectively, are both
+**     Julian Dates, apportioned in any convenient way between the
+**     argument pairs.  For example, JD=2450123.7 could be expressed in
+**     any of these ways, among others:
+**
+**            Part A        Part B
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in
+**     cases where the loss of several decimal digits of resolution
+**     is acceptable (in the case of UT;  the TT is not at all critical
+**     in this respect).  The J2000 and MJD methods are good compromises
+**     between resolution and convenience.  For UT, the date & time
+**     method is best matched to the algorithm that is used by the Earth
+**     rotation angle function, called internally:  maximum precision is
+**     delivered when the uta argument is for 0hrs UT1 on the day in
+**     question and the utb argument lies in the range 0 to 1, or vice
+**     versa.
+**
+**  2) Both UT1 and TT are required, UT1 to predict the Earth rotation
+**     and TT to predict the effects of precession.  If UT1 is used for
+**     both purposes, errors of order 100 microarcseconds result.
+**
+**  3) This GMST is compatible with the IAU 2006 precession and must not
+**     be used with other precession models.
+**
+**  4) The result is returned in the range 0 to 2pi.
+**
+**  Called:
+**     iauEra00     Earth rotation angle, IAU 2000
+**     iauAnp       normalize angle into range 0 to 2pi
+**
+**  Reference:
+**
+**     Capitaine, N., Wallace, P.T. & Chapront, J., 2005,
+**     Astron.Astrophys. 432, 355
+**
+**  This revision:  2008 May 24
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double t, gmst;
+
+
+/* TT Julian centuries since J2000.0. */
+   t = ((tta - DJ00) + ttb) / DJC;
+
+/* Greenwich mean sidereal time, IAU 2006. */
+   gmst = iauAnp(iauEra00(uta, utb) +
+                  (    0.014506     +
+                  (  4612.156534    +
+                  (     1.3915817   +
+                  (    -0.00000044  +
+                  (    -0.000029956 +
+                  (    -0.0000000368 )
+          * t) * t) * t) * t) * t) * DAS2R);
+
+   return gmst;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+double iauGmst82(double dj1, double dj2)
+/*
+**  - - - - - - - - - -
+**   i a u G m s t 8 2
+**  - - - - - - - - - -
+**
+**  Universal Time to Greenwich mean sidereal time (IAU 1982 model).
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  canonical model.
+**
+**  Given:
+**     dj1,dj2    double    UT1 Julian Date (see note)
+**
+**  Returned (function value):
+**                double    Greenwich mean sidereal time (radians)
+**
+**  Notes:
+**
+**  1) The UT1 date dj1+dj2 is a Julian Date, apportioned in any
+**     convenient way between the arguments dj1 and dj2.  For example,
+**     JD(UT1)=2450123.7 could be expressed in any of these ways,
+**     among others:
+**
+**             dj1            dj2
+**
+**         2450123.7D0        0D0        (JD method)
+**          2451545D0      -1421.3D0     (J2000 method)
+**         2400000.5D0     50123.2D0     (MJD method)
+**         2450123.5D0       0.2D0       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in
+**     cases where the loss of several decimal digits of resolution
+**     is acceptable.  The J2000 and MJD methods are good compromises
+**     between resolution and convenience.  The date & time method is
+**     best matched to the algorithm used:  maximum accuracy (or, at
+**     least, minimum noise) is delivered when the dj1 argument is for
+**     0hrs UT1 on the day in question and the dj2 argument lies in the
+**     range 0 to 1, or vice versa.
+**
+**  2) The algorithm is based on the IAU 1982 expression.  This is
+**     always described as giving the GMST at 0 hours UT1.  In fact, it
+**     gives the difference between the GMST and the UT, the steady
+**     4-minutes-per-day drawing-ahead of ST with respect to UT.  When
+**     whole days are ignored, the expression happens to equal the GMST
+**     at 0 hours UT1 each day.
+**
+**  3) In this function, the entire UT1 (the sum of the two arguments
+**     dj1 and dj2) is used directly as the argument for the standard
+**     formula, the constant term of which is adjusted by 12 hours to
+**     take account of the noon phasing of Julian Date.  The UT1 is then
+**     added, but omitting whole days to conserve accuracy.
+**
+**  Called:
+**     iauAnp       normalize angle into range 0 to 2pi
+**
+**  References:
+**
+**     Transactions of the International Astronomical Union,
+**     XVIII B, 67 (1983).
+**
+**     Aoki et al., Astron. Astrophys. 105, 359-361 (1982).
+**
+**  This revision:  2008 May 24
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+/* Coefficients of IAU 1982 GMST-UT1 model */
+   double A = 24110.54841  -  DAYSEC / 2.0;
+   double B = 8640184.812866;
+   double C = 0.093104;
+   double D =  -6.2e-6;
+
+/* Note: the first constant, A, has to be adjusted by 12 hours */
+/* because the UT1 is supplied as a Julian date, which begins  */
+/* at noon.                                                    */
+
+   double d1, d2, t, f, gmst;
+
+
+/* Julian centuries since fundamental epoch. */
+   if (dj1 < dj2) {
+      d1 = dj1;
+      d2 = dj2;
+   } else {
+      d1 = dj2;
+      d2 = dj1;
+   }
+   t = (d1 + (d2 - DJ00)) / DJC;
+
+/* Fractional part of JD(UT1), in seconds. */
+   f = DAYSEC * (fmod(d1, 1.0) + fmod(d2, 1.0));
+
+/* GMST at this UT1. */
+   gmst = iauAnp(DS2R * ((A + (B + (C + D * t) * t) * t) + f));
+
+   return gmst;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+double iauGst00a(double uta, double utb, double tta, double ttb)
+/*
+**  - - - - - - - - - -
+**   i a u G s t 0 0 a
+**  - - - - - - - - - -
+**
+**  Greenwich apparent sidereal time (consistent with IAU 2000
+**  resolutions).
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  canonical model.
+**
+**  Given:
+**     uta,utb    double    UT1 as a 2-part Julian Date (Notes 1,2)
+**     tta,ttb    double    TT as a 2-part Julian Date (Notes 1,2)
+**
+**  Returned (function value):
+**                double    Greenwich apparent sidereal time (radians)
+**
+**  Notes:
+**
+**  1) The UT1 and TT dates uta+utb and tta+ttb respectively, are both
+**     Julian Dates, apportioned in any convenient way between the
+**     argument pairs.  For example, JD=2450123.7 could be expressed in
+**     any of these ways, among others:
+**
+**            Part A        Part B
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in
+**     cases where the loss of several decimal digits of resolution
+**     is acceptable (in the case of UT;  the TT is not at all critical
+**     in this respect).  The J2000 and MJD methods are good compromises
+**     between resolution and convenience.  For UT, the date & time
+**     method is best matched to the algorithm that is used by the Earth
+**     Rotation Angle function, called internally:  maximum precision is
+**     delivered when the uta argument is for 0hrs UT1 on the day in
+**     question and the utb argument lies in the range 0 to 1, or vice
+**     versa.
+**
+**  2) Both UT1 and TT are required, UT1 to predict the Earth rotation
+**     and TT to predict the effects of precession-nutation.  If UT1 is
+**     used for both purposes, errors of order 100 microarcseconds
+**     result.
+**
+**  3) This GAST is compatible with the IAU 2000 resolutions and must be
+**     used only in conjunction with other IAU 2000 compatible
+**     components such as precession-nutation.
+**
+**  4) The result is returned in the range 0 to 2pi.
+**
+**  5) The algorithm is from Capitaine et al. (2003) and IERS
+**     Conventions 2003.
+**
+**  Called:
+**     iauGmst00    Greenwich mean sidereal time, IAU 2000
+**     iauEe00a     equation of the equinoxes, IAU 2000A
+**     iauAnp       normalize angle into range 0 to 2pi
+**
+**  References:
+**
+**     Capitaine, N., Wallace, P.T. and McCarthy, D.D., "Expressions to
+**     implement the IAU 2000 definition of UT1", Astronomy &
+**     Astrophysics, 406, 1135-1149 (2003)
+**
+**     McCarthy, D. D., Petit, G. (eds.), IERS Conventions (2003),
+**     IERS Technical Note No. 32, BKG (2004)
+**
+**  This revision:  2008 May 16
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double gmst00, ee00a, gst;
+
+
+   gmst00 = iauGmst00(uta, utb, tta, ttb);
+   ee00a = iauEe00a(tta, ttb);
+   gst = iauAnp(gmst00 + ee00a);
+
+   return gst;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+double iauGst00b(double uta, double utb)
+/*
+**  - - - - - - - - - -
+**   i a u G s t 0 0 b
+**  - - - - - - - - - -
+**
+**  Greenwich apparent sidereal time (consistent with IAU 2000
+**  resolutions but using the truncated nutation model IAU 2000B).
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     uta,utb    double    UT1 as a 2-part Julian Date (Notes 1,2)
+**
+**  Returned (function value):
+**                double    Greenwich apparent sidereal time (radians)
+**
+**  Notes:
+**
+**  1) The UT1 date uta+utb is a Julian Date, apportioned in any
+**     convenient way between the argument pair.  For example,
+**     JD=2450123.7 could be expressed in any of these ways, among
+**     others:
+**
+**             uta            utb
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in cases
+**     where the loss of several decimal digits of resolution is
+**     acceptable.  The J2000 and MJD methods are good compromises
+**     between resolution and convenience.  For UT, the date & time
+**     method is best matched to the algorithm that is used by the Earth
+**     Rotation Angle function, called internally:  maximum precision is
+**     delivered when the uta argument is for 0hrs UT1 on the day in
+**     question and the utb argument lies in the range 0 to 1, or vice
+**     versa.
+**
+**  2) The result is compatible with the IAU 2000 resolutions, except
+**     that accuracy has been compromised for the sake of speed and
+**     convenience in two respects:
+**
+**     . UT is used instead of TDB (or TT) to compute the precession
+**       component of GMST and the equation of the equinoxes.  This
+**       results in errors of order 0.1 mas at present.
+**
+**     . The IAU 2000B abridged nutation model (McCarthy & Luzum, 2001)
+**       is used, introducing errors of up to 1 mas.
+**
+**  3) This GAST is compatible with the IAU 2000 resolutions and must be
+**     used only in conjunction with other IAU 2000 compatible
+**     components such as precession-nutation.
+**
+**  4) The result is returned in the range 0 to 2pi.
+**
+**  5) The algorithm is from Capitaine et al. (2003) and IERS
+**     Conventions 2003.
+**
+**  Called:
+**     iauGmst00    Greenwich mean sidereal time, IAU 2000
+**     iauEe00b     equation of the equinoxes, IAU 2000B
+**     iauAnp       normalize angle into range 0 to 2pi
+**
+**  References:
+**
+**     Capitaine, N., Wallace, P.T. and McCarthy, D.D., "Expressions to
+**     implement the IAU 2000 definition of UT1", Astronomy &
+**     Astrophysics, 406, 1135-1149 (2003)
+**
+**     McCarthy, D.D. & Luzum, B.J., "An abridged model of the
+**     precession-nutation of the celestial pole", Celestial Mechanics &
+**     Dynamical Astronomy, 85, 37-49 (2003)
+**
+**     McCarthy, D. D., Petit, G. (eds.), IERS Conventions (2003),
+**     IERS Technical Note No. 32, BKG (2004)
+**
+**  This revision:  2008 May 16
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double gmst00, ee00b, gst;
+
+
+   gmst00 = iauGmst00(uta, utb, uta, utb);
+   ee00b = iauEe00b(uta, utb);
+   gst = iauAnp(gmst00 + ee00b);
+
+   return gst;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+double iauGst06(double uta, double utb, double tta, double ttb,
+                double rnpb[3][3])
+/*
+**  - - - - - - - - -
+**   i a u G s t 0 6
+**  - - - - - - - - -
+**
+**  Greenwich apparent sidereal time, IAU 2006, given the NPB matrix.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     uta,utb  double        UT1 as a 2-part Julian Date (Notes 1,2)
+**     tta,ttb  double        TT as a 2-part Julian Date (Notes 1,2)
+**     rnpb     double[3][3]  nutation x precession x bias matrix
+**
+**  Returned (function value):
+**              double        Greenwich apparent sidereal time (radians)
+**
+**  Notes:
+**
+**  1) The UT1 and TT dates uta+utb and tta+ttb respectively, are both
+**     Julian Dates, apportioned in any convenient way between the
+**     argument pairs.  For example, JD=2450123.7 could be expressed in
+**     any of these ways, among others:
+**
+**            Part A        Part B
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in
+**     cases where the loss of several decimal digits of resolution
+**     is acceptable (in the case of UT;  the TT is not at all critical
+**     in this respect).  The J2000 and MJD methods are good compromises
+**     between resolution and convenience.  For UT, the date & time
+**     method is best matched to the algorithm that is used by the Earth
+**     rotation angle function, called internally:  maximum precision is
+**     delivered when the uta argument is for 0hrs UT1 on the day in
+**     question and the utb argument lies in the range 0 to 1, or vice
+**     versa.
+**
+**  2) Both UT1 and TT are required, UT1 to predict the Earth rotation
+**     and TT to predict the effects of precession-nutation.  If UT1 is
+**     used for both purposes, errors of order 100 microarcseconds
+**     result.
+**
+**  3) Although the function uses the IAU 2006 series for s+XY/2, it is
+**     otherwise independent of the precession-nutation model and can in
+**     practice be used with any equinox-based NPB matrix.
+**
+**  4) The result is returned in the range 0 to 2pi.
+**
+**  Called:
+**     iauBpn2xy    extract CIP X,Y coordinates from NPB matrix
+**     iauS06       the CIO locator s, given X,Y, IAU 2006
+**     iauAnp       normalize angle into range 0 to 2pi
+**     iauEra00     Earth rotation angle, IAU 2000
+**     iauEors      equation of the origins, given NPB matrix and s
+**
+**  Reference:
+**
+**     Wallace, P.T. & Capitaine, N., 2006, Astron.Astrophys. 459, 981
+**
+**  This revision:  2008 May 24
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double x, y, s, era, eors, gst;
+
+
+/* Extract CIP coordinates. */
+   iauBpn2xy(rnpb, &x, &y);
+
+/* The CIO locator, s. */
+   s = iauS06(tta, ttb, x, y);
+
+/* Greenwich apparent sidereal time. */
+   era = iauEra00(uta, utb);
+   eors = iauEors(rnpb, s);
+   gst = iauAnp(era - eors);
+
+   return gst;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+double iauGst06a(double uta, double utb, double tta, double ttb)
+/*
+**  - - - - - - - - - -
+**   i a u G s t 0 6 a
+**  - - - - - - - - - -
+**
+**  Greenwich apparent sidereal time (consistent with IAU 2000 and 2006
+**  resolutions).
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  canonical model.
+**
+**  Given:
+**     uta,utb    double    UT1 as a 2-part Julian Date (Notes 1,2)
+**     tta,ttb    double    TT as a 2-part Julian Date (Notes 1,2)
+**
+**  Returned (function value):
+**                double    Greenwich apparent sidereal time (radians)
+**
+**  Notes:
+**
+**  1) The UT1 and TT dates uta+utb and tta+ttb respectively, are both
+**     Julian Dates, apportioned in any convenient way between the
+**     argument pairs.  For example, JD=2450123.7 could be expressed in
+**     any of these ways, among others:
+**
+**            Part A        Part B
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in
+**     cases where the loss of several decimal digits of resolution
+**     is acceptable (in the case of UT;  the TT is not at all critical
+**     in this respect).  The J2000 and MJD methods are good compromises
+**     between resolution and convenience.  For UT, the date & time
+**     method is best matched to the algorithm that is used by the Earth
+**     rotation angle function, called internally:  maximum precision is
+**     delivered when the uta argument is for 0hrs UT1 on the day in
+**     question and the utb argument lies in the range 0 to 1, or vice
+**     versa.
+**
+**  2) Both UT1 and TT are required, UT1 to predict the Earth rotation
+**     and TT to predict the effects of precession-nutation.  If UT1 is
+**     used for both purposes, errors of order 100 microarcseconds
+**     result.
+**
+**  3) This GAST is compatible with the IAU 2000/2006 resolutions and
+**     must be used only in conjunction with IAU 2006 precession and
+**     IAU 2000A nutation.
+**
+**  4) The result is returned in the range 0 to 2pi.
+**
+**  Called:
+**     iauPnm06a    classical NPB matrix, IAU 2006/2000A
+**     iauGst06     Greenwich apparent ST, IAU 2006, given NPB matrix
+**
+**  Reference:
+**
+**     Wallace, P.T. & Capitaine, N., 2006, Astron.Astrophys. 459, 981
+**
+**  This revision:  2008 May 16
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double rnpb[3][3], gst;
+
+
+/* Classical nutation x precession x bias matrix, IAU 2000A. */
+   iauPnm06a(tta, ttb, rnpb);
+
+/* Greenwich apparent sidereal time. */
+   gst = iauGst06(uta, utb, tta, ttb, rnpb);
+
+   return gst;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofa.h"
+
+double iauGst94(double uta, double utb)
+/*
+**  - - - - - - - - -
+**   i a u G s t 9 4
+**  - - - - - - - - -
+**
+**  Greenwich apparent sidereal time (consistent with IAU 1982/94
+**  resolutions).
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     uta,utb    double    UT1 as a 2-part Julian Date (Notes 1,2)
+**
+**  Returned (function value):
+**                double    Greenwich apparent sidereal time (radians)
+**
+**  Notes:
+**
+**  1) The UT1 date uta+utb is a Julian Date, apportioned in any
+**     convenient way between the argument pair.  For example,
+**     JD=2450123.7 could be expressed in any of these ways, among
+**     others:
+**
+**             uta            utb
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in cases
+**     where the loss of several decimal digits of resolution is
+**     acceptable.  The J2000 and MJD methods are good compromises
+**     between resolution and convenience.  For UT, the date & time
+**     method is best matched to the algorithm that is used by the Earth
+**     Rotation Angle function, called internally:  maximum precision is
+**     delivered when the uta argument is for 0hrs UT1 on the day in
+**     question and the utb argument lies in the range 0 to 1, or vice
+**     versa.
+**
+**  2) The result is compatible with the IAU 1982 and 1994 resolutions,
+**     except that accuracy has been compromised for the sake of
+**     convenience in that UT is used instead of TDB (or TT) to compute
+**     the equation of the equinoxes.
+**
+**  3) This GAST must be used only in conjunction with contemporaneous
+**     IAU standards such as 1976 precession, 1980 obliquity and 1982
+**     nutation.  It is not compatible with the IAU 2000 resolutions.
+**
+**  4) The result is returned in the range 0 to 2pi.
+**
+**  Called:
+**     iauGmst82    Greenwich mean sidereal time, IAU 1982
+**     iauEqeq94    equation of the equinoxes, IAU 1994
+**     iauAnp       normalize angle into range 0 to 2pi
+**
+**  References:
+**
+**     Explanatory Supplement to the Astronomical Almanac,
+**     P. Kenneth Seidelmann (ed), University Science Books (1992)
+**
+**     IAU Resolution C7, Recommendation 3 (1994)
+**
+**  This revision:  2008 May 16
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double gmst82, eqeq94, gst;
+
+
+   gmst82 = iauGmst82(uta, utb);
+   eqeq94 = iauEqeq94(uta, utb);
+   gst = iauAnp(gmst82  + eqeq94);
+
+   return gst;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauH2fk5(double rh, double dh,
+              double drh, double ddh, double pxh, double rvh,
+              double *r5, double *d5,
+              double *dr5, double *dd5, double *px5, double *rv5)
+/*
+**  - - - - - - - - -
+**   i a u H 2 f k 5
+**  - - - - - - - - -
+**
+**  Transform Hipparcos star data into the FK5 (J2000.0) system.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given (all Hipparcos, epoch J2000.0):
+**     rh      double    RA (radians)
+**     dh      double    Dec (radians)
+**     drh     double    proper motion in RA (dRA/dt, rad/Jyear)
+**     ddh     double    proper motion in Dec (dDec/dt, rad/Jyear)
+**     pxh     double    parallax (arcsec)
+**     rvh     double    radial velocity (km/s, positive = receding)
+**
+**  Returned (all FK5, equinox J2000.0, epoch J2000.0):
+**     r5      double    RA (radians)
+**     d5      double    Dec (radians)
+**     dr5     double    proper motion in RA (dRA/dt, rad/Jyear)
+**     dd5     double    proper motion in Dec (dDec/dt, rad/Jyear)
+**     px5     double    parallax (arcsec)
+**     rv5     double    radial velocity (km/s, positive = receding)
+**
+**  Notes:
+**
+**  1) This function transforms Hipparcos star positions and proper
+**     motions into FK5 J2000.0.
+**
+**  2) The proper motions in RA are dRA/dt rather than
+**     cos(Dec)*dRA/dt, and are per year rather than per century.
+**
+**  3) The FK5 to Hipparcos transformation is modeled as a pure
+**     rotation and spin;  zonal errors in the FK5 catalog are not
+**     taken into account.
+**
+**  4) See also iauFk52h, iauFk5hz, iauHfk5z.
+**
+**  Called:
+**     iauStarpv    star catalog data to space motion pv-vector
+**     iauFk5hip    FK5 to Hipparcos rotation and spin
+**     iauRv2m      r-vector to r-matrix
+**     iauRxp       product of r-matrix and p-vector
+**     iauTrxp      product of transpose of r-matrix and p-vector
+**     iauPxp       vector product of two p-vectors
+**     iauPmp       p-vector minus p-vector
+**     iauPvstar    space motion pv-vector to star catalog data
+**
+**  Reference:
+**
+**     F.Mignard & M.Froeschle, Astron. Astrophys. 354, 732-739 (2000).
+**
+**  This revision:  2009 December 17
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   int i;
+   double pvh[2][3], r5h[3][3], s5h[3], sh[3], wxp[3], vv[3], pv5[2][3];
+
+
+/* Hipparcos barycentric position/velocity pv-vector (normalized). */
+   iauStarpv(rh, dh, drh, ddh, pxh, rvh, pvh);
+
+/* FK5 to Hipparcos orientation matrix and spin vector. */
+   iauFk5hip(r5h, s5h);
+
+/* Make spin units per day instead of per year. */
+   for ( i = 0; i < 3; s5h[i++] /= 365.25 );
+
+/* Orient the spin into the Hipparcos system. */
+   iauRxp(r5h, s5h, sh);
+
+/* De-orient the Hipparcos position into the FK5 system. */
+   iauTrxp(r5h, pvh[0], pv5[0]);
+
+/* Apply spin to the position giving an extra space motion component. */
+   iauPxp(pvh[0], sh, wxp);
+
+/* Subtract this component from the Hipparcos space motion. */
+   iauPmp(pvh[1], wxp, vv);
+
+/* De-orient the Hipparcos space motion into the FK5 system. */
+   iauTrxp(r5h, vv, pv5[1]);
+
+/* FK5 pv-vector to spherical. */
+   iauPvstar(pv5, r5, d5, dr5, dd5, px5, rv5);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauHfk5z(double rh, double dh, double date1, double date2,
+              double *r5, double *d5, double *dr5, double *dd5)
+/*
+**  - - - - - - - - -
+**   i a u H f k 5 z
+**  - - - - - - - - -
+**
+**  Transform a Hipparcos star position into FK5 J2000.0, assuming
+**  zero Hipparcos proper motion.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     rh            double    Hipparcos RA (radians)
+**     dh            double    Hipparcos Dec (radians)
+**     date1,date2   double    TDB date (Note 1)
+**
+**  Returned (all FK5, equinox J2000.0, date date1+date2):
+**     r5            double    RA (radians)
+**     d5            double    Dec (radians)
+**     dr5           double    FK5 RA proper motion (rad/year, Note 4)
+**     dd5           double    Dec proper motion (rad/year, Note 4)
+**
+**  Notes:
+**
+**  1) The TT date date1+date2 is a Julian Date, apportioned in any
+**     convenient way between the two arguments.  For example,
+**     JD(TT)=2450123.7 could be expressed in any of these ways,
+**     among others:
+**
+**            date1          date2
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in
+**     cases where the loss of several decimal digits of resolution
+**     is acceptable.  The J2000 method is best matched to the way
+**     the argument is handled internally and will deliver the
+**     optimum resolution.  The MJD method and the date & time methods
+**     are both good compromises between resolution and convenience.
+**
+**  2) The proper motion in RA is dRA/dt rather than cos(Dec)*dRA/dt.
+**
+**  3) The FK5 to Hipparcos transformation is modeled as a pure rotation
+**     and spin;  zonal errors in the FK5 catalogue are not taken into
+**     account.
+**
+**  4) It was the intention that Hipparcos should be a close
+**     approximation to an inertial frame, so that distant objects have
+**     zero proper motion;  such objects have (in general) non-zero
+**     proper motion in FK5, and this function returns those fictitious
+**     proper motions.
+**
+**  5) The position returned by this function is in the FK5 J2000.0
+**     reference system but at date date1+date2.
+**
+**  6) See also iauFk52h, iauH2fk5, iauFk5zhz.
+**
+**  Called:
+**     iauS2c       spherical coordinates to unit vector
+**     iauFk5hip    FK5 to Hipparcos rotation and spin
+**     iauRxp       product of r-matrix and p-vector
+**     iauSxp       multiply p-vector by scalar
+**     iauRxr       product of two r-matrices
+**     iauTrxp      product of transpose of r-matrix and p-vector
+**     iauPxp       vector product of two p-vectors
+**     iauPv2s      pv-vector to spherical
+**     iauAnp       normalize angle into range 0 to 2pi
+**
+**  Reference:
+**
+**     F.Mignard & M.Froeschle, 2000, Astron.Astrophys. 354, 732-739.
+**
+**  This revision:  2009 December 17
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double t, ph[3], r5h[3][3], s5h[3], sh[3], vst[3],
+   rst[3][3], r5ht[3][3], pv5e[2][3], vv[3],
+   w, r, v;
+
+
+/* Time interval from fundamental epoch J2000.0 to given date (JY). */
+   t = ((date1 - DJ00) + date2) / DJY;
+
+/* Hipparcos barycentric position vector (normalized). */
+   iauS2c(rh, dh, ph);
+
+/* FK5 to Hipparcos orientation matrix and spin vector. */
+   iauFk5hip(r5h, s5h);
+
+/* Rotate the spin into the Hipparcos system. */
+   iauRxp(r5h, s5h, sh);
+
+/* Accumulated Hipparcos wrt FK5 spin over that interval. */
+   iauSxp(t, s5h, vst);
+
+/* Express the accumulated spin as a rotation matrix. */
+   iauRv2m(vst, rst);
+
+/* Rotation matrix:  accumulated spin, then FK5 to Hipparcos. */
+   iauRxr(r5h, rst, r5ht);
+
+/* De-orient & de-spin the Hipparcos position into FK5 J2000.0. */
+   iauTrxp(r5ht, ph, pv5e[0]);
+
+/* Apply spin to the position giving a space motion. */
+   iauPxp(sh, ph, vv);
+
+/* De-orient & de-spin the Hipparcos space motion into FK5 J2000.0. */
+   iauTrxp(r5ht, vv, pv5e[1]);
+
+/* FK5 position/velocity pv-vector to spherical. */
+   iauPv2s(pv5e, &w, d5, &r, dr5, dd5, &v);
+   *r5 = iauAnp(w);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauIr(double r[3][3])
+/*
+**  - - - - - -
+**   i a u I r
+**  - - - - - -
+**
+**  Initialize an r-matrix to the identity matrix.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  vector/matrix support function.
+**
+**  Returned:
+**     r       double[3][3]    r-matrix
+**
+**  Called:
+**     iauZr        zero r-matrix
+**
+**  This revision:  2008 May 11
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   iauZr(r);
+   r[0][0] = 1.0;
+   r[1][1] = 1.0;
+   r[2][2] = 1.0;
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+int iauJd2cal(double dj1, double dj2,
+              int *iy, int *im, int *id, double *fd)
+/*
+**  - - - - - - - - - -
+**   i a u J d 2 c a l
+**  - - - - - - - - - -
+**
+**  Julian Date to Gregorian year, month, day, and fraction of a day.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     dj1,dj2   double   Julian Date (Notes 1, 2)
+**
+**  Returned (arguments):
+**     iy        int      year
+**     im        int      month
+**     id        int      day
+**     fd        double   fraction of day
+**
+**  Returned (function value):
+**               int      status:
+**                           0 = OK
+**                          -1 = unacceptable date (Note 3)
+**
+**  Notes:
+**
+**  1) The earliest valid date is -68569.5 (-4900 March 1).  The
+**     largest value accepted is 10^9.
+**
+**  2) The Julian Date is apportioned in any convenient way between
+**     the arguments dj1 and dj2.  For example, JD=2450123.7 could
+**     be expressed in any of these ways, among others:
+**
+**            dj1             dj2
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**  3) In early eras the conversion is from the "proleptic Gregorian
+**     calendar";  no account is taken of the date(s) of adoption of
+**     the Gregorian calendar, nor is the AD/BC numbering convention
+**     observed.
+**
+**  Reference:
+**
+**     Explanatory Supplement to the Astronomical Almanac,
+**     P. Kenneth Seidelmann (ed), University Science Books (1992),
+**     Section 12.92 (p604).
+**
+**  This revision:  2008 May 26
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+/* Minimum and maximum allowed JD */
+   static const double djmin = -68569.5;
+   static const double djmax = 1e9;
+
+   long jd, l, n, i, k;
+   double dj, d1, d2, f1, f2, f, d;
+
+
+/* Verify date is acceptable. */
+   dj = dj1 + dj2;
+   if (dj < djmin || dj > djmax) return -1;
+
+/* Copy the date, big then small, and re-align to midnight. */
+   if (dj1 >= dj2) {
+      d1 = dj1;
+      d2 = dj2;
+   } else {
+      d1 = dj2;
+      d2 = dj1;
+   }
+   d2 -= 0.5;
+
+/* Separate day and fraction. */
+   f1 = fmod(d1, 1.0);
+   f2 = fmod(d2, 1.0);
+   f = fmod(f1 + f2, 1.0);
+   if (f < 0.0) f += 1.0;
+   d = floor(d1 - f1) + floor(d2 - f2) + floor(f1 + f2 - f);
+   jd = (long) floor(d) + 1L;
+
+/* Express day in Gregorian calendar. */
+   l = jd + 68569L;
+   n = (4L * l) / 146097L;
+   l -= (146097L * n + 3L) / 4L;
+   i = (4000L * (l + 1L)) / 1461001L;
+   l -= (1461L * i) / 4L - 31L;
+   k = (80L * l) / 2447L;
+   *id = (int) (l - (2447L * k) / 80L);
+   l = k / 11L;
+   *im = (int) (k + 2L - 12L * l);
+   *iy = (int) (100L * (n - 49L) + i + l);
+   *fd = f;
+
+   return 0;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+int iauJdcalf(int ndp, double dj1, double dj2, int iymdf[4])
+/*
+**  - - - - - - - - - -
+**   i a u J d c a l f
+**  - - - - - - - - - -
+**
+**  Julian Date to Gregorian Calendar, expressed in a form convenient
+**  for formatting messages:  rounded to a specified precision.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     ndp       int      number of decimal places of days in fraction
+**     dj1,dj2   double   dj1+dj2 = Julian Date (Note 1)
+**
+**  Returned:
+**     iymdf     int[4]   year, month, day, fraction in Gregorian
+**                        calendar
+**
+**  Returned (function value):
+**               int      status:
+**                          -1 = date out of range
+**                           0 = OK
+**                          +1 = NDP not 0-9 (interpreted as 0)
+**
+**  Notes:
+**
+**  1) The Julian Date is apportioned in any convenient way between
+**     the arguments dj1 and dj2.  For example, JD=2450123.7 could
+**     be expressed in any of these ways, among others:
+**
+**             dj1            dj2
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**  2) In early eras the conversion is from the "Proleptic Gregorian
+**     Calendar";  no account is taken of the date(s) of adoption of
+**     the Gregorian Calendar, nor is the AD/BC numbering convention
+**     observed.
+**
+**  3) Refer to the function iauJd2cal.
+**
+**  4) NDP should be 4 or less if internal overflows are to be
+**     avoided on machines which use 16-bit integers.
+**
+**  Called:
+**     iauJd2cal    JD to Gregorian calendar
+**
+**  Reference:
+**
+**     Explanatory Supplement to the Astronomical Almanac,
+**     P. Kenneth Seidelmann (ed), University Science Books (1992),
+**     Section 12.92 (p604).
+**
+**  This revision:  2010 July 27
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   int j, js;
+   double denom, d1, d2, f1, f2, f;
+
+
+/* Denominator of fraction (e.g. 100 for 2 decimal places). */
+   if ((ndp >= 0) && (ndp <= 9)) {
+      j = 0;
+      denom = pow(10.0, ndp);
+   } else {
+      j = 1;
+      denom = 1.0;
+   }
+
+/* Copy the date, big then small, and realign to midnight. */
+   if (dj1 >= dj2) {
+      d1 = dj1;
+      d2 = dj2;
+   } else {
+      d1 = dj2;
+      d2 = dj1;
+   }
+   d2 -= 0.5;
+
+/* Separate days and fractions. */
+   f1 = fmod(d1, 1.0);
+   f2 = fmod(d2, 1.0);
+   d1 = floor(d1 - f1);
+   d2 = floor(d2 - f2);
+
+/* Round the total fraction to the specified number of places. */
+   f = floor((f1+f2)*denom + 0.5) / denom;
+
+/* Re-assemble the rounded date and re-align to noon. */
+   d2 += f + 0.5;
+
+/* Convert to Gregorian calendar. */
+   js = iauJd2cal(d1, d2, &iymdf[0], &iymdf[1], &iymdf[2], &f);
+   if (js == 0) {
+      iymdf[3] = (int) (f * denom);
+   } else {
+      j = js;
+   }
+
+/* Return the status. */
+   return j;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauNum00a(double date1, double date2, double rmatn[3][3])
+/*
+**  - - - - - - - - - -
+**   i a u N u m 0 0 a
+**  - - - - - - - - - -
+**
+**  Form the matrix of nutation for a given date, IAU 2000A model.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     date1,date2  double          TT as a 2-part Julian Date (Note 1)
+**
+**  Returned:
+**     rmatn        double[3][3]    nutation matrix
+**
+**  Notes:
+**
+**  1) The TT date date1+date2 is a Julian Date, apportioned in any
+**     convenient way between the two arguments.  For example,
+**     JD(TT)=2450123.7 could be expressed in any of these ways,
+**     among others:
+**
+**            date1          date2
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in
+**     cases where the loss of several decimal digits of resolution
+**     is acceptable.  The J2000 method is best matched to the way
+**     the argument is handled internally and will deliver the
+**     optimum resolution.  The MJD method and the date & time methods
+**     are both good compromises between resolution and convenience.
+**
+**  2) The matrix operates in the sense V(true) = rmatn * V(mean), where
+**     the p-vector V(true) is with respect to the true equatorial triad
+**     of date and the p-vector V(mean) is with respect to the mean
+**     equatorial triad of date.
+**
+**  3) A faster, but slightly less accurate result (about 1 mas), can be
+**     obtained by using instead the iauNum00b function.
+**
+**  Called:
+**     iauPn00a     bias/precession/nutation, IAU 2000A
+**
+**  Reference:
+**
+**     Explanatory Supplement to the Astronomical Almanac,
+**     P. Kenneth Seidelmann (ed), University Science Books (1992),
+**     Section 3.222-3 (p114).
+**
+**  This revision:  2008 May 12
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double dpsi, deps, epsa, rb[3][3], rp[3][3], rbp[3][3], rbpn[3][3];
+
+
+/* Obtain the required matrix (discarding other results). */
+   iauPn00a(date1, date2,
+            &dpsi, &deps, &epsa, rb, rp, rbp, rmatn, rbpn);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauNum00b(double date1, double date2, double rmatn[3][3])
+/*
+**  - - - - - - - - - -
+**   i a u N u m 0 0 b
+**  - - - - - - - - - -
+**
+**  Form the matrix of nutation for a given date, IAU 2000B model.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     date1,date2  double         TT as a 2-part Julian Date (Note 1)
+**
+**  Returned:
+**     rmatn        double[3][3]   nutation matrix
+**
+**  Notes:
+**
+**  1) The TT date date1+date2 is a Julian Date, apportioned in any
+**     convenient way between the two arguments.  For example,
+**     JD(TT)=2450123.7 could be expressed in any of these ways,
+**     among others:
+**
+**            date1          date2
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in
+**     cases where the loss of several decimal digits of resolution
+**     is acceptable.  The J2000 method is best matched to the way
+**     the argument is handled internally and will deliver the
+**     optimum resolution.  The MJD method and the date & time methods
+**     are both good compromises between resolution and convenience.
+**
+**  2) The matrix operates in the sense V(true) = rmatn * V(mean), where
+**     the p-vector V(true) is with respect to the true equatorial triad
+**     of date and the p-vector V(mean) is with respect to the mean
+**     equatorial triad of date.
+**
+**  3) The present function is faster, but slightly less accurate (about
+**     1 mas), than the iauNum00a function.
+**
+**  Called:
+**     iauPn00b     bias/precession/nutation, IAU 2000B
+**
+**  Reference:
+**
+**     Explanatory Supplement to the Astronomical Almanac,
+**     P. Kenneth Seidelmann (ed), University Science Books (1992),
+**     Section 3.222-3 (p114).
+**
+**  This revision:  2008 May 12
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double dpsi, deps, epsa, rb[3][3], rp[3][3], rbp[3][3], rbpn[3][3];
+
+
+/* Obtain the required matrix (discarding other results). */
+   iauPn00b(date1, date2,
+            &dpsi, &deps, &epsa, rb, rp, rbp, rmatn, rbpn);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauNum06a(double date1, double date2, double rmatn[3][3])
+/*
+**  - - - - - - - - - -
+**   i a u N u m 0 6 a
+**  - - - - - - - - - -
+**
+**  Form the matrix of nutation for a given date, IAU 2006/2000A model.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     date1,date2   double          TT as a 2-part Julian Date (Note 1)
+**
+**  Returned:
+**     rmatn         double[3][3]    nutation matrix
+**
+**  Notes:
+**
+**  1) The TT date date1+date2 is a Julian Date, apportioned in any
+**     convenient way between the two arguments.  For example,
+**     JD(TT)=2450123.7 could be expressed in any of these ways,
+**     among others:
+**
+**            date1          date2
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in
+**     cases where the loss of several decimal digits of resolution
+**     is acceptable.  The J2000 method is best matched to the way
+**     the argument is handled internally and will deliver the
+**     optimum resolution.  The MJD method and the date & time methods
+**     are both good compromises between resolution and convenience.
+**
+**  2) The matrix operates in the sense V(true) = rmatn * V(mean), where
+**     the p-vector V(true) is with respect to the true equatorial triad
+**     of date and the p-vector V(mean) is with respect to the mean
+**     equatorial triad of date.
+**
+**  Called:
+**     iauObl06     mean obliquity, IAU 2006
+**     iauNut06a    nutation, IAU 2006/2000A
+**     iauNumat     form nutation matrix
+**
+**  Reference:
+**
+**     Explanatory Supplement to the Astronomical Almanac,
+**     P. Kenneth Seidelmann (ed), University Science Books (1992),
+**     Section 3.222-3 (p114).
+**
+**  This revision:  2008 May 12
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double eps, dp, de;
+
+
+/* Mean obliquity. */
+   eps = iauObl06(date1, date2);
+
+/* Nutation components. */
+   iauNut06a(date1, date2, &dp, &de);
+
+/* Nutation matrix. */
+   iauNumat(eps, dp, de, rmatn);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauNumat(double epsa, double dpsi, double deps, double rmatn[3][3])
+/*
+**  - - - - - - - - -
+**   i a u N u m a t
+**  - - - - - - - - -
+**
+**  Form the matrix of nutation.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     epsa        double         mean obliquity of date (Note 1)
+**     dpsi,deps   double         nutation (Note 2)
+**
+**  Returned:
+**     rmatn       double[3][3]   nutation matrix (Note 3)
+**
+**  Notes:
+**
+**
+**  1) The supplied mean obliquity epsa, must be consistent with the
+**     precession-nutation models from which dpsi and deps were obtained.
+**
+**  2) The caller is responsible for providing the nutation components;
+**     they are in longitude and obliquity, in radians and are with
+**     respect to the equinox and ecliptic of date.
+**
+**  3) The matrix operates in the sense V(true) = rmatn * V(mean),
+**     where the p-vector V(true) is with respect to the true
+**     equatorial triad of date and the p-vector V(mean) is with
+**     respect to the mean equatorial triad of date.
+**
+**  Called:
+**     iauIr        initialize r-matrix to identity
+**     iauRx        rotate around X-axis
+**     iauRz        rotate around Z-axis
+**
+**  Reference:
+**
+**     Explanatory Supplement to the Astronomical Almanac,
+**     P. Kenneth Seidelmann (ed), University Science Books (1992),
+**     Section 3.222-3 (p114).
+**
+**  This revision:  2008 May 11
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+/* Build the rotation matrix. */
+   iauIr(rmatn);
+   iauRx(epsa, rmatn);
+   iauRz(-dpsi, rmatn);
+   iauRx(-(epsa + deps), rmatn);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauNut00a(double date1, double date2, double *dpsi, double *deps)
+/*
+**  - - - - - - - - - -
+**   i a u N u t 0 0 a
+**  - - - - - - - - - -
+**
+**  Nutation, IAU 2000A model (MHB2000 luni-solar and planetary nutation
+**  with free core nutation omitted).
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  canonical model.
+**
+**  Given:
+**     date1,date2   double   TT as a 2-part Julian Date (Note 1)
+**
+**  Returned:
+**     dpsi,deps     double   nutation, luni-solar + planetary (Note 2)
+**
+**  Notes:
+**
+**  1) The TT date date1+date2 is a Julian Date, apportioned in any
+**     convenient way between the two arguments.  For example,
+**     JD(TT)=2450123.7 could be expressed in any of these ways,
+**     among others:
+**
+**            date1          date2
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in
+**     cases where the loss of several decimal digits of resolution
+**     is acceptable.  The J2000 method is best matched to the way
+**     the argument is handled internally and will deliver the
+**     optimum resolution.  The MJD method and the date & time methods
+**     are both good compromises between resolution and convenience.
+**
+**  2) The nutation components in longitude and obliquity are in radians
+**     and with respect to the equinox and ecliptic of date.  The
+**     obliquity at J2000.0 is assumed to be the Lieske et al. (1977)
+**     value of 84381.448 arcsec.
+**
+**     Both the luni-solar and planetary nutations are included.  The
+**     latter are due to direct planetary nutations and the
+**     perturbations of the lunar and terrestrial orbits.
+**
+**  3) The function computes the MHB2000 nutation series with the
+**     associated corrections for planetary nutations.  It is an
+**     implementation of the nutation part of the IAU 2000A precession-
+**     nutation model, formally adopted by the IAU General Assembly in
+**     2000, namely MHB2000 (Mathews et al. 2002), but with the free
+**     core nutation (FCN - see Note 4) omitted.
+**
+**  4) The full MHB2000 model also contains contributions to the
+**     nutations in longitude and obliquity due to the free-excitation
+**     of the free-core-nutation during the period 1979-2000.  These FCN
+**     terms, which are time-dependent and unpredictable, are NOT
+**     included in the present function and, if required, must be
+**     independently computed.  With the FCN corrections included, the
+**     present function delivers a pole which is at current epochs
+**     accurate to a few hundred microarcseconds.  The omission of FCN
+**     introduces further errors of about that size.
+**
+**  5) The present function provides classical nutation.  The MHB2000
+**     algorithm, from which it is adapted, deals also with (i) the
+**     offsets between the GCRS and mean poles and (ii) the adjustments
+**     in longitude and obliquity due to the changed precession rates.
+**     These additional functions, namely frame bias and precession
+**     adjustments, are supported by the SOFA functions iauBi00  and
+**     iauPr00.
+**
+**  6) The MHB2000 algorithm also provides "total" nutations, comprising
+**     the arithmetic sum of the frame bias, precession adjustments,
+**     luni-solar nutation and planetary nutation.  These total
+**     nutations can be used in combination with an existing IAU 1976
+**     precession implementation, such as iauPmat76,  to deliver GCRS-
+**     to-true predictions of sub-mas accuracy at current dates.
+**     However, there are three shortcomings in the MHB2000 model that
+**     must be taken into account if more accurate or definitive results
+**     are required (see Wallace 2002):
+**
+**       (i) The MHB2000 total nutations are simply arithmetic sums,
+**           yet in reality the various components are successive Euler
+**           rotations.  This slight lack of rigor leads to cross terms
+**           that exceed 1 mas after a century.  The rigorous procedure
+**           is to form the GCRS-to-true rotation matrix by applying the
+**           bias, precession and nutation in that order.
+**
+**      (ii) Although the precession adjustments are stated to be with
+**           respect to Lieske et al. (1977), the MHB2000 model does
+**           not specify which set of Euler angles are to be used and
+**           how the adjustments are to be applied.  The most literal
+**           and straightforward procedure is to adopt the 4-rotation
+**           epsilon_0, psi_A, omega_A, xi_A option, and to add DPSIPR
+**           to psi_A and DEPSPR to both omega_A and eps_A.
+**
+**     (iii) The MHB2000 model predates the determination by Chapront
+**           et al. (2002) of a 14.6 mas displacement between the
+**           J2000.0 mean equinox and the origin of the ICRS frame.  It
+**           should, however, be noted that neglecting this displacement
+**           when calculating star coordinates does not lead to a
+**           14.6 mas change in right ascension, only a small second-
+**           order distortion in the pattern of the precession-nutation
+**           effect.
+**
+**     For these reasons, the SOFA functions do not generate the "total
+**     nutations" directly, though they can of course easily be
+**     generated by calling iauBi00, iauPr00 and the present function
+**     and adding the results.
+**
+**  7) The MHB2000 model contains 41 instances where the same frequency
+**     appears multiple times, of which 38 are duplicates and three are
+**     triplicates.  To keep the present code close to the original MHB
+**     algorithm, this small inefficiency has not been corrected.
+**
+**  Called:
+**     iauFal03     mean anomaly of the Moon
+**     iauFaf03     mean argument of the latitude of the Moon
+**     iauFaom03    mean longitude of the Moon's ascending node
+**     iauFame03    mean longitude of Mercury
+**     iauFave03    mean longitude of Venus
+**     iauFae03     mean longitude of Earth
+**     iauFama03    mean longitude of Mars
+**     iauFaju03    mean longitude of Jupiter
+**     iauFasa03    mean longitude of Saturn
+**     iauFaur03    mean longitude of Uranus
+**     iauFapa03    general accumulated precession in longitude
+**
+**  References:
+**
+**     Chapront, J., Chapront-Touze, M. & Francou, G. 2002,
+**     Astron.Astrophys. 387, 700
+**
+**     Lieske, J.H., Lederle, T., Fricke, W. & Morando, B. 1977,
+**     Astron.Astrophys. 58, 1-16
+**
+**     Mathews, P.M., Herring, T.A., Buffet, B.A. 2002, J.Geophys.Res.
+**     107, B4.  The MHB_2000 code itself was obtained on 9th September
+**     2002 from ftp//maia.usno.navy.mil/conv2000/chapter5/IAU2000A.
+**
+**     Simon, J.-L., Bretagnon, P., Chapront, J., Chapront-Touze, M.,
+**     Francou, G., Laskar, J. 1994, Astron.Astrophys. 282, 663-683
+**
+**     Souchay, J., Loysel, B., Kinoshita, H., Folgueira, M. 1999,
+**     Astron.Astrophys.Supp.Ser. 135, 111
+**
+**     Wallace, P.T., "Software for Implementing the IAU 2000
+**     Resolutions", in IERS Workshop 5.1 (2002)
+**
+**  This revision:  2009 December 17
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   int i;
+   double t, el, elp, f, d, om, arg, dp, de, sarg, carg,
+          al, af, ad, aom, alme, alve, alea, alma,
+          alju, alsa, alur, alne, apa, dpsils, depsls,
+          dpsipl, depspl;
+
+/* Units of 0.1 microarcsecond to radians */
+   const double U2R = DAS2R / 1e7;
+
+/* ------------------------- */
+/* Luni-Solar nutation model */
+/* ------------------------- */
+
+/* The units for the sine and cosine coefficients are */
+/* 0.1 microarcsecond and the same per Julian century */
+
+   static const struct {
+      int nl,nlp,nf,nd,nom; /* coefficients of l,l',F,D,Om */
+      double sp,spt,cp;     /* longitude sin, t*sin, cos coefficients */
+      double ce,cet,se;     /* obliquity cos, t*cos, sin coefficients */
+   } xls[] = {
+
+   /* 1- 10 */
+      { 0, 0, 0, 0, 1,
+         -172064161.0, -174666.0, 33386.0, 92052331.0, 9086.0, 15377.0},
+      { 0, 0, 2,-2, 2,
+           -13170906.0, -1675.0, -13696.0, 5730336.0, -3015.0, -4587.0},
+      { 0, 0, 2, 0, 2,-2276413.0,-234.0,2796.0,978459.0,-485.0, 1374.0},
+      { 0, 0, 0, 0, 2,2074554.0, 207.0, -698.0,-897492.0,470.0, -291.0},
+      { 0, 1, 0, 0, 0,1475877.0,-3633.0,11817.0,73871.0,-184.0,-1924.0},
+      { 0, 1, 2,-2, 2,-516821.0,1226.0, -524.0,224386.0,-677.0, -174.0},
+      { 1, 0, 0, 0, 0, 711159.0,  73.0, -872.0,  -6750.0,  0.0,  358.0},
+      { 0, 0, 2, 0, 1,-387298.0,-367.0,  380.0, 200728.0, 18.0,  318.0},
+      { 1, 0, 2, 0, 2,-301461.0, -36.0,  816.0, 129025.0,-63.0,  367.0},
+      { 0,-1, 2,-2, 2, 215829.0,-494.0,  111.0, -95929.0,299.0,  132.0},
+
+   /* 11-20 */
+      { 0, 0, 2,-2, 1, 128227.0, 137.0,  181.0, -68982.0, -9.0,   39.0},
+      {-1, 0, 2, 0, 2, 123457.0,  11.0,   19.0, -53311.0, 32.0,   -4.0},
+      {-1, 0, 0, 2, 0, 156994.0,  10.0, -168.0,  -1235.0,  0.0,   82.0},
+      { 1, 0, 0, 0, 1,  63110.0,  63.0,   27.0, -33228.0,  0.0,   -9.0},
+      {-1, 0, 0, 0, 1, -57976.0, -63.0, -189.0,  31429.0,  0.0,  -75.0},
+      {-1, 0, 2, 2, 2, -59641.0, -11.0,  149.0,  25543.0,-11.0,   66.0},
+      { 1, 0, 2, 0, 1, -51613.0, -42.0,  129.0,  26366.0,  0.0,   78.0},
+      {-2, 0, 2, 0, 1,  45893.0,  50.0,   31.0, -24236.0,-10.0,   20.0},
+      { 0, 0, 0, 2, 0,  63384.0,  11.0, -150.0,  -1220.0,  0.0,   29.0},
+      { 0, 0, 2, 2, 2, -38571.0,  -1.0,  158.0,  16452.0,-11.0,   68.0},
+
+   /* 21-30 */
+      { 0,-2, 2,-2, 2,  32481.0,   0.0,    0.0, -13870.0,  0.0,    0.0},
+      {-2, 0, 0, 2, 0, -47722.0,   0.0,  -18.0,    477.0,  0.0,  -25.0},
+      { 2, 0, 2, 0, 2, -31046.0,  -1.0,  131.0,  13238.0,-11.0,   59.0},
+      { 1, 0, 2,-2, 2,  28593.0,   0.0,   -1.0, -12338.0, 10.0,   -3.0},
+      {-1, 0, 2, 0, 1,  20441.0,  21.0,   10.0, -10758.0,  0.0,   -3.0},
+      { 2, 0, 0, 0, 0,  29243.0,   0.0,  -74.0,   -609.0,  0.0,   13.0},
+      { 0, 0, 2, 0, 0,  25887.0,   0.0,  -66.0,   -550.0,  0.0,   11.0},
+      { 0, 1, 0, 0, 1, -14053.0, -25.0,   79.0,   8551.0, -2.0,  -45.0},
+      {-1, 0, 0, 2, 1,  15164.0,  10.0,   11.0,  -8001.0,  0.0,   -1.0},
+      { 0, 2, 2,-2, 2, -15794.0,  72.0,  -16.0,   6850.0,-42.0,   -5.0},
+
+   /* 31-40 */
+      { 0, 0,-2, 2, 0,  21783.0,   0.0,   13.0,   -167.0,  0.0,   13.0},
+      { 1, 0, 0,-2, 1, -12873.0, -10.0,  -37.0,   6953.0,  0.0,  -14.0},
+      { 0,-1, 0, 0, 1, -12654.0,  11.0,   63.0,   6415.0,  0.0,   26.0},
+      {-1, 0, 2, 2, 1, -10204.0,   0.0,   25.0,   5222.0,  0.0,   15.0},
+      { 0, 2, 0, 0, 0,  16707.0, -85.0,  -10.0,    168.0, -1.0,   10.0},
+      { 1, 0, 2, 2, 2,  -7691.0,   0.0,   44.0,   3268.0,  0.0,   19.0},
+      {-2, 0, 2, 0, 0, -11024.0,   0.0,  -14.0,    104.0,  0.0,    2.0},
+      { 0, 1, 2, 0, 2,   7566.0, -21.0,  -11.0,  -3250.0,  0.0,   -5.0},
+      { 0, 0, 2, 2, 1,  -6637.0, -11.0,   25.0,   3353.0,  0.0,   14.0},
+      { 0,-1, 2, 0, 2,  -7141.0,  21.0,    8.0,   3070.0,  0.0,    4.0},
+
+   /* 41-50 */
+      { 0, 0, 0, 2, 1,  -6302.0, -11.0,    2.0,   3272.0,  0.0,    4.0},
+      { 1, 0, 2,-2, 1,   5800.0,  10.0,    2.0,  -3045.0,  0.0,   -1.0},
+      { 2, 0, 2,-2, 2,   6443.0,   0.0,   -7.0,  -2768.0,  0.0,   -4.0},
+      {-2, 0, 0, 2, 1,  -5774.0, -11.0,  -15.0,   3041.0,  0.0,   -5.0},
+      { 2, 0, 2, 0, 1,  -5350.0,   0.0,   21.0,   2695.0,  0.0,   12.0},
+      { 0,-1, 2,-2, 1,  -4752.0, -11.0,   -3.0,   2719.0,  0.0,   -3.0},
+      { 0, 0, 0,-2, 1,  -4940.0, -11.0,  -21.0,   2720.0,  0.0,   -9.0},
+      {-1,-1, 0, 2, 0,   7350.0,   0.0,   -8.0,    -51.0,  0.0,    4.0},
+      { 2, 0, 0,-2, 1,   4065.0,   0.0,    6.0,  -2206.0,  0.0,    1.0},
+      { 1, 0, 0, 2, 0,   6579.0,   0.0,  -24.0,   -199.0,  0.0,    2.0},
+
+   /* 51-60 */
+      { 0, 1, 2,-2, 1,   3579.0,   0.0,    5.0,  -1900.0,  0.0,    1.0},
+      { 1,-1, 0, 0, 0,   4725.0,   0.0,   -6.0,    -41.0,  0.0,    3.0},
+      {-2, 0, 2, 0, 2,  -3075.0,   0.0,   -2.0,   1313.0,  0.0,   -1.0},
+      { 3, 0, 2, 0, 2,  -2904.0,   0.0,   15.0,   1233.0,  0.0,    7.0},
+      { 0,-1, 0, 2, 0,   4348.0,   0.0,  -10.0,    -81.0,  0.0,    2.0},
+      { 1,-1, 2, 0, 2,  -2878.0,   0.0,    8.0,   1232.0,  0.0,    4.0},
+      { 0, 0, 0, 1, 0,  -4230.0,   0.0,    5.0,    -20.0,  0.0,   -2.0},
+      {-1,-1, 2, 2, 2,  -2819.0,   0.0,    7.0,   1207.0,  0.0,    3.0},
+      {-1, 0, 2, 0, 0,  -4056.0,   0.0,    5.0,     40.0,  0.0,   -2.0},
+      { 0,-1, 2, 2, 2,  -2647.0,   0.0,   11.0,   1129.0,  0.0,    5.0},
+
+   /* 61-70 */
+      {-2, 0, 0, 0, 1,  -2294.0,   0.0,  -10.0,   1266.0,  0.0,   -4.0},
+      { 1, 1, 2, 0, 2,   2481.0,   0.0,   -7.0,  -1062.0,  0.0,   -3.0},
+      { 2, 0, 0, 0, 1,   2179.0,   0.0,   -2.0,  -1129.0,  0.0,   -2.0},
+      {-1, 1, 0, 1, 0,   3276.0,   0.0,    1.0,     -9.0,  0.0,    0.0},
+      { 1, 1, 0, 0, 0,  -3389.0,   0.0,    5.0,     35.0,  0.0,   -2.0},
+      { 1, 0, 2, 0, 0,   3339.0,   0.0,  -13.0,   -107.0,  0.0,    1.0},
+      {-1, 0, 2,-2, 1,  -1987.0,   0.0,   -6.0,   1073.0,  0.0,   -2.0},
+      { 1, 0, 0, 0, 2,  -1981.0,   0.0,    0.0,    854.0,  0.0,    0.0},
+      {-1, 0, 0, 1, 0,   4026.0,   0.0, -353.0,   -553.0,  0.0, -139.0},
+      { 0, 0, 2, 1, 2,   1660.0,   0.0,   -5.0,   -710.0,  0.0,   -2.0},
+
+   /* 71-80 */
+      {-1, 0, 2, 4, 2,  -1521.0,   0.0,    9.0,    647.0,  0.0,    4.0},
+      {-1, 1, 0, 1, 1,   1314.0,   0.0,    0.0,   -700.0,  0.0,    0.0},
+      { 0,-2, 2,-2, 1,  -1283.0,   0.0,    0.0,    672.0,  0.0,    0.0},
+      { 1, 0, 2, 2, 1,  -1331.0,   0.0,    8.0,    663.0,  0.0,    4.0},
+      {-2, 0, 2, 2, 2,   1383.0,   0.0,   -2.0,   -594.0,  0.0,   -2.0},
+      {-1, 0, 0, 0, 2,   1405.0,   0.0,    4.0,   -610.0,  0.0,    2.0},
+      { 1, 1, 2,-2, 2,   1290.0,   0.0,    0.0,   -556.0,  0.0,    0.0},
+      {-2, 0, 2, 4, 2,  -1214.0,   0.0,    5.0,    518.0,  0.0,    2.0},
+      {-1, 0, 4, 0, 2,   1146.0,   0.0,   -3.0,   -490.0,  0.0,   -1.0},
+      { 2, 0, 2,-2, 1,   1019.0,   0.0,   -1.0,   -527.0,  0.0,   -1.0},
+
+   /* 81-90 */
+      { 2, 0, 2, 2, 2,  -1100.0,   0.0,    9.0,    465.0,  0.0,    4.0},
+      { 1, 0, 0, 2, 1,   -970.0,   0.0,    2.0,    496.0,  0.0,    1.0},
+      { 3, 0, 0, 0, 0,   1575.0,   0.0,   -6.0,    -50.0,  0.0,    0.0},
+      { 3, 0, 2,-2, 2,    934.0,   0.0,   -3.0,   -399.0,  0.0,   -1.0},
+      { 0, 0, 4,-2, 2,    922.0,   0.0,   -1.0,   -395.0,  0.0,   -1.0},
+      { 0, 1, 2, 0, 1,    815.0,   0.0,   -1.0,   -422.0,  0.0,   -1.0},
+      { 0, 0,-2, 2, 1,    834.0,   0.0,    2.0,   -440.0,  0.0,    1.0},
+      { 0, 0, 2,-2, 3,   1248.0,   0.0,    0.0,   -170.0,  0.0,    1.0},
+      {-1, 0, 0, 4, 0,   1338.0,   0.0,   -5.0,    -39.0,  0.0,    0.0},
+      { 2, 0,-2, 0, 1,    716.0,   0.0,   -2.0,   -389.0,  0.0,   -1.0},
+
+   /* 91-100 */
+      {-2, 0, 0, 4, 0,   1282.0,   0.0,   -3.0,    -23.0,  0.0,    1.0},
+      {-1,-1, 0, 2, 1,    742.0,   0.0,    1.0,   -391.0,  0.0,    0.0},
+      {-1, 0, 0, 1, 1,   1020.0,   0.0,  -25.0,   -495.0,  0.0,  -10.0},
+      { 0, 1, 0, 0, 2,    715.0,   0.0,   -4.0,   -326.0,  0.0,    2.0},
+      { 0, 0,-2, 0, 1,   -666.0,   0.0,   -3.0,    369.0,  0.0,   -1.0},
+      { 0,-1, 2, 0, 1,   -667.0,   0.0,    1.0,    346.0,  0.0,    1.0},
+      { 0, 0, 2,-1, 2,   -704.0,   0.0,    0.0,    304.0,  0.0,    0.0},
+      { 0, 0, 2, 4, 2,   -694.0,   0.0,    5.0,    294.0,  0.0,    2.0},
+      {-2,-1, 0, 2, 0,  -1014.0,   0.0,   -1.0,      4.0,  0.0,   -1.0},
+      { 1, 1, 0,-2, 1,   -585.0,   0.0,   -2.0,    316.0,  0.0,   -1.0},
+
+   /* 101-110 */
+      {-1, 1, 0, 2, 0,   -949.0,   0.0,    1.0,      8.0,  0.0,   -1.0},
+      {-1, 1, 0, 1, 2,   -595.0,   0.0,    0.0,    258.0,  0.0,    0.0},
+      { 1,-1, 0, 0, 1,    528.0,   0.0,    0.0,   -279.0,  0.0,    0.0},
+      { 1,-1, 2, 2, 2,   -590.0,   0.0,    4.0,    252.0,  0.0,    2.0},
+      {-1, 1, 2, 2, 2,    570.0,   0.0,   -2.0,   -244.0,  0.0,   -1.0},
+      { 3, 0, 2, 0, 1,   -502.0,   0.0,    3.0,    250.0,  0.0,    2.0},
+      { 0, 1,-2, 2, 0,   -875.0,   0.0,    1.0,     29.0,  0.0,    0.0},
+      {-1, 0, 0,-2, 1,   -492.0,   0.0,   -3.0,    275.0,  0.0,   -1.0},
+      { 0, 1, 2, 2, 2,    535.0,   0.0,   -2.0,   -228.0,  0.0,   -1.0},
+      {-1,-1, 2, 2, 1,   -467.0,   0.0,    1.0,    240.0,  0.0,    1.0},
+
+   /* 111-120 */
+      { 0,-1, 0, 0, 2,    591.0,   0.0,    0.0,   -253.0,  0.0,    0.0},
+      { 1, 0, 2,-4, 1,   -453.0,   0.0,   -1.0,    244.0,  0.0,   -1.0},
+      {-1, 0,-2, 2, 0,    766.0,   0.0,    1.0,      9.0,  0.0,    0.0},
+      { 0,-1, 2, 2, 1,   -446.0,   0.0,    2.0,    225.0,  0.0,    1.0},
+      { 2,-1, 2, 0, 2,   -488.0,   0.0,    2.0,    207.0,  0.0,    1.0},
+      { 0, 0, 0, 2, 2,   -468.0,   0.0,    0.0,    201.0,  0.0,    0.0},
+      { 1,-1, 2, 0, 1,   -421.0,   0.0,    1.0,    216.0,  0.0,    1.0},
+      {-1, 1, 2, 0, 2,    463.0,   0.0,    0.0,   -200.0,  0.0,    0.0},
+      { 0, 1, 0, 2, 0,   -673.0,   0.0,    2.0,     14.0,  0.0,    0.0},
+      { 0,-1,-2, 2, 0,    658.0,   0.0,    0.0,     -2.0,  0.0,    0.0},
+
+   /* 121-130 */
+      { 0, 3, 2,-2, 2,   -438.0,   0.0,    0.0,    188.0,  0.0,    0.0},
+      { 0, 0, 0, 1, 1,   -390.0,   0.0,    0.0,    205.0,  0.0,    0.0},
+      {-1, 0, 2, 2, 0,    639.0, -11.0,   -2.0,    -19.0,  0.0,    0.0},
+      { 2, 1, 2, 0, 2,    412.0,   0.0,   -2.0,   -176.0,  0.0,   -1.0},
+      { 1, 1, 0, 0, 1,   -361.0,   0.0,    0.0,    189.0,  0.0,    0.0},
+      { 1, 1, 2, 0, 1,    360.0,   0.0,   -1.0,   -185.0,  0.0,   -1.0},
+      { 2, 0, 0, 2, 0,    588.0,   0.0,   -3.0,    -24.0,  0.0,    0.0},
+      { 1, 0,-2, 2, 0,   -578.0,   0.0,    1.0,      5.0,  0.0,    0.0},
+      {-1, 0, 0, 2, 2,   -396.0,   0.0,    0.0,    171.0,  0.0,    0.0},
+      { 0, 1, 0, 1, 0,    565.0,   0.0,   -1.0,     -6.0,  0.0,    0.0},
+
+   /* 131-140 */
+      { 0, 1, 0,-2, 1,   -335.0,   0.0,   -1.0,    184.0,  0.0,   -1.0},
+      {-1, 0, 2,-2, 2,    357.0,   0.0,    1.0,   -154.0,  0.0,    0.0},
+      { 0, 0, 0,-1, 1,    321.0,   0.0,    1.0,   -174.0,  0.0,    0.0},
+      {-1, 1, 0, 0, 1,   -301.0,   0.0,   -1.0,    162.0,  0.0,    0.0},
+      { 1, 0, 2,-1, 2,   -334.0,   0.0,    0.0,    144.0,  0.0,    0.0},
+      { 1,-1, 0, 2, 0,    493.0,   0.0,   -2.0,    -15.0,  0.0,    0.0},
+      { 0, 0, 0, 4, 0,    494.0,   0.0,   -2.0,    -19.0,  0.0,    0.0},
+      { 1, 0, 2, 1, 2,    337.0,   0.0,   -1.0,   -143.0,  0.0,   -1.0},
+      { 0, 0, 2, 1, 1,    280.0,   0.0,   -1.0,   -144.0,  0.0,    0.0},
+      { 1, 0, 0,-2, 2,    309.0,   0.0,    1.0,   -134.0,  0.0,    0.0},
+
+   /* 141-150 */
+      {-1, 0, 2, 4, 1,   -263.0,   0.0,    2.0,    131.0,  0.0,    1.0},
+      { 1, 0,-2, 0, 1,    253.0,   0.0,    1.0,   -138.0,  0.0,    0.0},
+      { 1, 1, 2,-2, 1,    245.0,   0.0,    0.0,   -128.0,  0.0,    0.0},
+      { 0, 0, 2, 2, 0,    416.0,   0.0,   -2.0,    -17.0,  0.0,    0.0},
+      {-1, 0, 2,-1, 1,   -229.0,   0.0,    0.0,    128.0,  0.0,    0.0},
+      {-2, 0, 2, 2, 1,    231.0,   0.0,    0.0,   -120.0,  0.0,    0.0},
+      { 4, 0, 2, 0, 2,   -259.0,   0.0,    2.0,    109.0,  0.0,    1.0},
+      { 2,-1, 0, 0, 0,    375.0,   0.0,   -1.0,     -8.0,  0.0,    0.0},
+      { 2, 1, 2,-2, 2,    252.0,   0.0,    0.0,   -108.0,  0.0,    0.0},
+      { 0, 1, 2, 1, 2,   -245.0,   0.0,    1.0,    104.0,  0.0,    0.0},
+
+   /* 151-160 */
+      { 1, 0, 4,-2, 2,    243.0,   0.0,   -1.0,   -104.0,  0.0,    0.0},
+      {-1,-1, 0, 0, 1,    208.0,   0.0,    1.0,   -112.0,  0.0,    0.0},
+      { 0, 1, 0, 2, 1,    199.0,   0.0,    0.0,   -102.0,  0.0,    0.0},
+      {-2, 0, 2, 4, 1,   -208.0,   0.0,    1.0,    105.0,  0.0,    0.0},
+      { 2, 0, 2, 0, 0,    335.0,   0.0,   -2.0,    -14.0,  0.0,    0.0},
+      { 1, 0, 0, 1, 0,   -325.0,   0.0,    1.0,      7.0,  0.0,    0.0},
+      {-1, 0, 0, 4, 1,   -187.0,   0.0,    0.0,     96.0,  0.0,    0.0},
+      {-1, 0, 4, 0, 1,    197.0,   0.0,   -1.0,   -100.0,  0.0,    0.0},
+      { 2, 0, 2, 2, 1,   -192.0,   0.0,    2.0,     94.0,  0.0,    1.0},
+      { 0, 0, 2,-3, 2,   -188.0,   0.0,    0.0,     83.0,  0.0,    0.0},
+
+   /* 161-170 */
+      {-1,-2, 0, 2, 0,    276.0,   0.0,    0.0,     -2.0,  0.0,    0.0},
+      { 2, 1, 0, 0, 0,   -286.0,   0.0,    1.0,      6.0,  0.0,    0.0},
+      { 0, 0, 4, 0, 2,    186.0,   0.0,   -1.0,    -79.0,  0.0,    0.0},
+      { 0, 0, 0, 0, 3,   -219.0,   0.0,    0.0,     43.0,  0.0,    0.0},
+      { 0, 3, 0, 0, 0,    276.0,   0.0,    0.0,      2.0,  0.0,    0.0},
+      { 0, 0, 2,-4, 1,   -153.0,   0.0,   -1.0,     84.0,  0.0,    0.0},
+      { 0,-1, 0, 2, 1,   -156.0,   0.0,    0.0,     81.0,  0.0,    0.0},
+      { 0, 0, 0, 4, 1,   -154.0,   0.0,    1.0,     78.0,  0.0,    0.0},
+      {-1,-1, 2, 4, 2,   -174.0,   0.0,    1.0,     75.0,  0.0,    0.0},
+      { 1, 0, 2, 4, 2,   -163.0,   0.0,    2.0,     69.0,  0.0,    1.0},
+
+   /* 171-180 */
+      {-2, 2, 0, 2, 0,   -228.0,   0.0,    0.0,      1.0,  0.0,    0.0},
+      {-2,-1, 2, 0, 1,     91.0,   0.0,   -4.0,    -54.0,  0.0,   -2.0},
+      {-2, 0, 0, 2, 2,    175.0,   0.0,    0.0,    -75.0,  0.0,    0.0},
+      {-1,-1, 2, 0, 2,   -159.0,   0.0,    0.0,     69.0,  0.0,    0.0},
+      { 0, 0, 4,-2, 1,    141.0,   0.0,    0.0,    -72.0,  0.0,    0.0},
+      { 3, 0, 2,-2, 1,    147.0,   0.0,    0.0,    -75.0,  0.0,    0.0},
+      {-2,-1, 0, 2, 1,   -132.0,   0.0,    0.0,     69.0,  0.0,    0.0},
+      { 1, 0, 0,-1, 1,    159.0,   0.0,  -28.0,    -54.0,  0.0,   11.0},
+      { 0,-2, 0, 2, 0,    213.0,   0.0,    0.0,     -4.0,  0.0,    0.0},
+      {-2, 0, 0, 4, 1,    123.0,   0.0,    0.0,    -64.0,  0.0,    0.0},
+
+   /* 181-190 */
+      {-3, 0, 0, 0, 1,   -118.0,   0.0,   -1.0,     66.0,  0.0,    0.0},
+      { 1, 1, 2, 2, 2,    144.0,   0.0,   -1.0,    -61.0,  0.0,    0.0},
+      { 0, 0, 2, 4, 1,   -121.0,   0.0,    1.0,     60.0,  0.0,    0.0},
+      { 3, 0, 2, 2, 2,   -134.0,   0.0,    1.0,     56.0,  0.0,    1.0},
+      {-1, 1, 2,-2, 1,   -105.0,   0.0,    0.0,     57.0,  0.0,    0.0},
+      { 2, 0, 0,-4, 1,   -102.0,   0.0,    0.0,     56.0,  0.0,    0.0},
+      { 0, 0, 0,-2, 2,    120.0,   0.0,    0.0,    -52.0,  0.0,    0.0},
+      { 2, 0, 2,-4, 1,    101.0,   0.0,    0.0,    -54.0,  0.0,    0.0},
+      {-1, 1, 0, 2, 1,   -113.0,   0.0,    0.0,     59.0,  0.0,    0.0},
+      { 0, 0, 2,-1, 1,   -106.0,   0.0,    0.0,     61.0,  0.0,    0.0},
+
+   /* 191-200 */
+      { 0,-2, 2, 2, 2,   -129.0,   0.0,    1.0,     55.0,  0.0,    0.0},
+      { 2, 0, 0, 2, 1,   -114.0,   0.0,    0.0,     57.0,  0.0,    0.0},
+      { 4, 0, 2,-2, 2,    113.0,   0.0,   -1.0,    -49.0,  0.0,    0.0},
+      { 2, 0, 0,-2, 2,   -102.0,   0.0,    0.0,     44.0,  0.0,    0.0},
+      { 0, 2, 0, 0, 1,    -94.0,   0.0,    0.0,     51.0,  0.0,    0.0},
+      { 1, 0, 0,-4, 1,   -100.0,   0.0,   -1.0,     56.0,  0.0,    0.0},
+      { 0, 2, 2,-2, 1,     87.0,   0.0,    0.0,    -47.0,  0.0,    0.0},
+      {-3, 0, 0, 4, 0,    161.0,   0.0,    0.0,     -1.0,  0.0,    0.0},
+      {-1, 1, 2, 0, 1,     96.0,   0.0,    0.0,    -50.0,  0.0,    0.0},
+      {-1,-1, 0, 4, 0,    151.0,   0.0,   -1.0,     -5.0,  0.0,    0.0},
+
+   /* 201-210 */
+      {-1,-2, 2, 2, 2,   -104.0,   0.0,    0.0,     44.0,  0.0,    0.0},
+      {-2,-1, 2, 4, 2,   -110.0,   0.0,    0.0,     48.0,  0.0,    0.0},
+      { 1,-1, 2, 2, 1,   -100.0,   0.0,    1.0,     50.0,  0.0,    0.0},
+      {-2, 1, 0, 2, 0,     92.0,   0.0,   -5.0,     12.0,  0.0,   -2.0},
+      {-2, 1, 2, 0, 1,     82.0,   0.0,    0.0,    -45.0,  0.0,    0.0},
+      { 2, 1, 0,-2, 1,     82.0,   0.0,    0.0,    -45.0,  0.0,    0.0},
+      {-3, 0, 2, 0, 1,    -78.0,   0.0,    0.0,     41.0,  0.0,    0.0},
+      {-2, 0, 2,-2, 1,    -77.0,   0.0,    0.0,     43.0,  0.0,    0.0},
+      {-1, 1, 0, 2, 2,      2.0,   0.0,    0.0,     54.0,  0.0,    0.0},
+      { 0,-1, 2,-1, 2,     94.0,   0.0,    0.0,    -40.0,  0.0,    0.0},
+
+   /* 211-220 */
+      {-1, 0, 4,-2, 2,    -93.0,   0.0,    0.0,     40.0,  0.0,    0.0},
+      { 0,-2, 2, 0, 2,    -83.0,   0.0,   10.0,     40.0,  0.0,   -2.0},
+      {-1, 0, 2, 1, 2,     83.0,   0.0,    0.0,    -36.0,  0.0,    0.0},
+      { 2, 0, 0, 0, 2,    -91.0,   0.0,    0.0,     39.0,  0.0,    0.0},
+      { 0, 0, 2, 0, 3,    128.0,   0.0,    0.0,     -1.0,  0.0,    0.0},
+      {-2, 0, 4, 0, 2,    -79.0,   0.0,    0.0,     34.0,  0.0,    0.0},
+      {-1, 0,-2, 0, 1,    -83.0,   0.0,    0.0,     47.0,  0.0,    0.0},
+      {-1, 1, 2, 2, 1,     84.0,   0.0,    0.0,    -44.0,  0.0,    0.0},
+      { 3, 0, 0, 0, 1,     83.0,   0.0,    0.0,    -43.0,  0.0,    0.0},
+      {-1, 0, 2, 3, 2,     91.0,   0.0,    0.0,    -39.0,  0.0,    0.0},
+
+   /* 221-230 */
+      { 2,-1, 2, 0, 1,    -77.0,   0.0,    0.0,     39.0,  0.0,    0.0},
+      { 0, 1, 2, 2, 1,     84.0,   0.0,    0.0,    -43.0,  0.0,    0.0},
+      { 0,-1, 2, 4, 2,    -92.0,   0.0,    1.0,     39.0,  0.0,    0.0},
+      { 2,-1, 2, 2, 2,    -92.0,   0.0,    1.0,     39.0,  0.0,    0.0},
+      { 0, 2,-2, 2, 0,    -94.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      {-1,-1, 2,-1, 1,     68.0,   0.0,    0.0,    -36.0,  0.0,    0.0},
+      { 0,-2, 0, 0, 1,    -61.0,   0.0,    0.0,     32.0,  0.0,    0.0},
+      { 1, 0, 2,-4, 2,     71.0,   0.0,    0.0,    -31.0,  0.0,    0.0},
+      { 1,-1, 0,-2, 1,     62.0,   0.0,    0.0,    -34.0,  0.0,    0.0},
+      {-1,-1, 2, 0, 1,    -63.0,   0.0,    0.0,     33.0,  0.0,    0.0},
+
+   /* 231-240 */
+      { 1,-1, 2,-2, 2,    -73.0,   0.0,    0.0,     32.0,  0.0,    0.0},
+      {-2,-1, 0, 4, 0,    115.0,   0.0,    0.0,     -2.0,  0.0,    0.0},
+      {-1, 0, 0, 3, 0,   -103.0,   0.0,    0.0,      2.0,  0.0,    0.0},
+      {-2,-1, 2, 2, 2,     63.0,   0.0,    0.0,    -28.0,  0.0,    0.0},
+      { 0, 2, 2, 0, 2,     74.0,   0.0,    0.0,    -32.0,  0.0,    0.0},
+      { 1, 1, 0, 2, 0,   -103.0,   0.0,   -3.0,      3.0,  0.0,   -1.0},
+      { 2, 0, 2,-1, 2,    -69.0,   0.0,    0.0,     30.0,  0.0,    0.0},
+      { 1, 0, 2, 1, 1,     57.0,   0.0,    0.0,    -29.0,  0.0,    0.0},
+      { 4, 0, 0, 0, 0,     94.0,   0.0,    0.0,     -4.0,  0.0,    0.0},
+      { 2, 1, 2, 0, 1,     64.0,   0.0,    0.0,    -33.0,  0.0,    0.0},
+
+   /* 241-250 */
+      { 3,-1, 2, 0, 2,    -63.0,   0.0,    0.0,     26.0,  0.0,    0.0},
+      {-2, 2, 0, 2, 1,    -38.0,   0.0,    0.0,     20.0,  0.0,    0.0},
+      { 1, 0, 2,-3, 1,    -43.0,   0.0,    0.0,     24.0,  0.0,    0.0},
+      { 1, 1, 2,-4, 1,    -45.0,   0.0,    0.0,     23.0,  0.0,    0.0},
+      {-1,-1, 2,-2, 1,     47.0,   0.0,    0.0,    -24.0,  0.0,    0.0},
+      { 0,-1, 0,-1, 1,    -48.0,   0.0,    0.0,     25.0,  0.0,    0.0},
+      { 0,-1, 0,-2, 1,     45.0,   0.0,    0.0,    -26.0,  0.0,    0.0},
+      {-2, 0, 0, 0, 2,     56.0,   0.0,    0.0,    -25.0,  0.0,    0.0},
+      {-2, 0,-2, 2, 0,     88.0,   0.0,    0.0,      2.0,  0.0,    0.0},
+      {-1, 0,-2, 4, 0,    -75.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+
+   /* 251-260 */
+      { 1,-2, 0, 0, 0,     85.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      { 0, 1, 0, 1, 1,     49.0,   0.0,    0.0,    -26.0,  0.0,    0.0},
+      {-1, 2, 0, 2, 0,    -74.0,   0.0,   -3.0,     -1.0,  0.0,   -1.0},
+      { 1,-1, 2,-2, 1,    -39.0,   0.0,    0.0,     21.0,  0.0,    0.0},
+      { 1, 2, 2,-2, 2,     45.0,   0.0,    0.0,    -20.0,  0.0,    0.0},
+      { 2,-1, 2,-2, 2,     51.0,   0.0,    0.0,    -22.0,  0.0,    0.0},
+      { 1, 0, 2,-1, 1,    -40.0,   0.0,    0.0,     21.0,  0.0,    0.0},
+      { 2, 1, 2,-2, 1,     41.0,   0.0,    0.0,    -21.0,  0.0,    0.0},
+      {-2, 0, 0,-2, 1,    -42.0,   0.0,    0.0,     24.0,  0.0,    0.0},
+      { 1,-2, 2, 0, 2,    -51.0,   0.0,    0.0,     22.0,  0.0,    0.0},
+
+   /* 261-270 */
+      { 0, 1, 2, 1, 1,    -42.0,   0.0,    0.0,     22.0,  0.0,    0.0},
+      { 1, 0, 4,-2, 1,     39.0,   0.0,    0.0,    -21.0,  0.0,    0.0},
+      {-2, 0, 4, 2, 2,     46.0,   0.0,    0.0,    -18.0,  0.0,    0.0},
+      { 1, 1, 2, 1, 2,    -53.0,   0.0,    0.0,     22.0,  0.0,    0.0},
+      { 1, 0, 0, 4, 0,     82.0,   0.0,    0.0,     -4.0,  0.0,    0.0},
+      { 1, 0, 2, 2, 0,     81.0,   0.0,   -1.0,     -4.0,  0.0,    0.0},
+      { 2, 0, 2, 1, 2,     47.0,   0.0,    0.0,    -19.0,  0.0,    0.0},
+      { 3, 1, 2, 0, 2,     53.0,   0.0,    0.0,    -23.0,  0.0,    0.0},
+      { 4, 0, 2, 0, 1,    -45.0,   0.0,    0.0,     22.0,  0.0,    0.0},
+      {-2,-1, 2, 0, 0,    -44.0,   0.0,    0.0,     -2.0,  0.0,    0.0},
+
+   /* 271-280 */
+      { 0, 1,-2, 2, 1,    -33.0,   0.0,    0.0,     16.0,  0.0,    0.0},
+      { 1, 0,-2, 1, 0,    -61.0,   0.0,    0.0,      1.0,  0.0,    0.0},
+      { 0,-1,-2, 2, 1,     28.0,   0.0,    0.0,    -15.0,  0.0,    0.0},
+      { 2,-1, 0,-2, 1,    -38.0,   0.0,    0.0,     19.0,  0.0,    0.0},
+      {-1, 0, 2,-1, 2,    -33.0,   0.0,    0.0,     21.0,  0.0,    0.0},
+      { 1, 0, 2,-3, 2,    -60.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      { 0, 1, 2,-2, 3,     48.0,   0.0,    0.0,    -10.0,  0.0,    0.0},
+      { 0, 0, 2,-3, 1,     27.0,   0.0,    0.0,    -14.0,  0.0,    0.0},
+      {-1, 0,-2, 2, 1,     38.0,   0.0,    0.0,    -20.0,  0.0,    0.0},
+      { 0, 0, 2,-4, 2,     31.0,   0.0,    0.0,    -13.0,  0.0,    0.0},
+
+   /* 281-290 */
+      {-2, 1, 0, 0, 1,    -29.0,   0.0,    0.0,     15.0,  0.0,    0.0},
+      {-1, 0, 0,-1, 1,     28.0,   0.0,    0.0,    -15.0,  0.0,    0.0},
+      { 2, 0, 2,-4, 2,    -32.0,   0.0,    0.0,     15.0,  0.0,    0.0},
+      { 0, 0, 4,-4, 4,     45.0,   0.0,    0.0,     -8.0,  0.0,    0.0},
+      { 0, 0, 4,-4, 2,    -44.0,   0.0,    0.0,     19.0,  0.0,    0.0},
+      {-1,-2, 0, 2, 1,     28.0,   0.0,    0.0,    -15.0,  0.0,    0.0},
+      {-2, 0, 0, 3, 0,    -51.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      { 1, 0,-2, 2, 1,    -36.0,   0.0,    0.0,     20.0,  0.0,    0.0},
+      {-3, 0, 2, 2, 2,     44.0,   0.0,    0.0,    -19.0,  0.0,    0.0},
+      {-3, 0, 2, 2, 1,     26.0,   0.0,    0.0,    -14.0,  0.0,    0.0},
+
+   /* 291-300 */
+      {-2, 0, 2, 2, 0,    -60.0,   0.0,    0.0,      2.0,  0.0,    0.0},
+      { 2,-1, 0, 0, 1,     35.0,   0.0,    0.0,    -18.0,  0.0,    0.0},
+      {-2, 1, 2, 2, 2,    -27.0,   0.0,    0.0,     11.0,  0.0,    0.0},
+      { 1, 1, 0, 1, 0,     47.0,   0.0,    0.0,     -1.0,  0.0,    0.0},
+      { 0, 1, 4,-2, 2,     36.0,   0.0,    0.0,    -15.0,  0.0,    0.0},
+      {-1, 1, 0,-2, 1,    -36.0,   0.0,    0.0,     20.0,  0.0,    0.0},
+      { 0, 0, 0,-4, 1,    -35.0,   0.0,    0.0,     19.0,  0.0,    0.0},
+      { 1,-1, 0, 2, 1,    -37.0,   0.0,    0.0,     19.0,  0.0,    0.0},
+      { 1, 1, 0, 2, 1,     32.0,   0.0,    0.0,    -16.0,  0.0,    0.0},
+      {-1, 2, 2, 2, 2,     35.0,   0.0,    0.0,    -14.0,  0.0,    0.0},
+
+   /* 301-310 */
+      { 3, 1, 2,-2, 2,     32.0,   0.0,    0.0,    -13.0,  0.0,    0.0},
+      { 0,-1, 0, 4, 0,     65.0,   0.0,    0.0,     -2.0,  0.0,    0.0},
+      { 2,-1, 0, 2, 0,     47.0,   0.0,    0.0,     -1.0,  0.0,    0.0},
+      { 0, 0, 4, 0, 1,     32.0,   0.0,    0.0,    -16.0,  0.0,    0.0},
+      { 2, 0, 4,-2, 2,     37.0,   0.0,    0.0,    -16.0,  0.0,    0.0},
+      {-1,-1, 2, 4, 1,    -30.0,   0.0,    0.0,     15.0,  0.0,    0.0},
+      { 1, 0, 0, 4, 1,    -32.0,   0.0,    0.0,     16.0,  0.0,    0.0},
+      { 1,-2, 2, 2, 2,    -31.0,   0.0,    0.0,     13.0,  0.0,    0.0},
+      { 0, 0, 2, 3, 2,     37.0,   0.0,    0.0,    -16.0,  0.0,    0.0},
+      {-1, 1, 2, 4, 2,     31.0,   0.0,    0.0,    -13.0,  0.0,    0.0},
+
+   /* 311-320 */
+      { 3, 0, 0, 2, 0,     49.0,   0.0,    0.0,     -2.0,  0.0,    0.0},
+      {-1, 0, 4, 2, 2,     32.0,   0.0,    0.0,    -13.0,  0.0,    0.0},
+      { 1, 1, 2, 2, 1,     23.0,   0.0,    0.0,    -12.0,  0.0,    0.0},
+      {-2, 0, 2, 6, 2,    -43.0,   0.0,    0.0,     18.0,  0.0,    0.0},
+      { 2, 1, 2, 2, 2,     26.0,   0.0,    0.0,    -11.0,  0.0,    0.0},
+      {-1, 0, 2, 6, 2,    -32.0,   0.0,    0.0,     14.0,  0.0,    0.0},
+      { 1, 0, 2, 4, 1,    -29.0,   0.0,    0.0,     14.0,  0.0,    0.0},
+      { 2, 0, 2, 4, 2,    -27.0,   0.0,    0.0,     12.0,  0.0,    0.0},
+      { 1, 1,-2, 1, 0,     30.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      {-3, 1, 2, 1, 2,    -11.0,   0.0,    0.0,      5.0,  0.0,    0.0},
+
+   /* 321-330 */
+      { 2, 0,-2, 0, 2,    -21.0,   0.0,    0.0,     10.0,  0.0,    0.0},
+      {-1, 0, 0, 1, 2,    -34.0,   0.0,    0.0,     15.0,  0.0,    0.0},
+      {-4, 0, 2, 2, 1,    -10.0,   0.0,    0.0,      6.0,  0.0,    0.0},
+      {-1,-1, 0, 1, 0,    -36.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      { 0, 0,-2, 2, 2,     -9.0,   0.0,    0.0,      4.0,  0.0,    0.0},
+      { 1, 0, 0,-1, 2,    -12.0,   0.0,    0.0,      5.0,  0.0,    0.0},
+      { 0,-1, 2,-2, 3,    -21.0,   0.0,    0.0,      5.0,  0.0,    0.0},
+      {-2, 1, 2, 0, 0,    -29.0,   0.0,    0.0,     -1.0,  0.0,    0.0},
+      { 0, 0, 2,-2, 4,    -15.0,   0.0,    0.0,      3.0,  0.0,    0.0},
+      {-2,-2, 0, 2, 0,    -20.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+
+   /* 331-340 */
+      {-2, 0,-2, 4, 0,     28.0,   0.0,    0.0,      0.0,  0.0,   -2.0},
+      { 0,-2,-2, 2, 0,     17.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      { 1, 2, 0,-2, 1,    -22.0,   0.0,    0.0,     12.0,  0.0,    0.0},
+      { 3, 0, 0,-4, 1,    -14.0,   0.0,    0.0,      7.0,  0.0,    0.0},
+      {-1, 1, 2,-2, 2,     24.0,   0.0,    0.0,    -11.0,  0.0,    0.0},
+      { 1,-1, 2,-4, 1,     11.0,   0.0,    0.0,     -6.0,  0.0,    0.0},
+      { 1, 1, 0,-2, 2,     14.0,   0.0,    0.0,     -6.0,  0.0,    0.0},
+      {-3, 0, 2, 0, 0,     24.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      {-3, 0, 2, 0, 2,     18.0,   0.0,    0.0,     -8.0,  0.0,    0.0},
+      {-2, 0, 0, 1, 0,    -38.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+
+   /* 341-350 */
+      { 0, 0,-2, 1, 0,    -31.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      {-3, 0, 0, 2, 1,    -16.0,   0.0,    0.0,      8.0,  0.0,    0.0},
+      {-1,-1,-2, 2, 0,     29.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      { 0, 1, 2,-4, 1,    -18.0,   0.0,    0.0,     10.0,  0.0,    0.0},
+      { 2, 1, 0,-4, 1,    -10.0,   0.0,    0.0,      5.0,  0.0,    0.0},
+      { 0, 2, 0,-2, 1,    -17.0,   0.0,    0.0,     10.0,  0.0,    0.0},
+      { 1, 0, 0,-3, 1,      9.0,   0.0,    0.0,     -4.0,  0.0,    0.0},
+      {-2, 0, 2,-2, 2,     16.0,   0.0,    0.0,     -6.0,  0.0,    0.0},
+      {-2,-1, 0, 0, 1,     22.0,   0.0,    0.0,    -12.0,  0.0,    0.0},
+      {-4, 0, 0, 2, 0,     20.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+
+   /* 351-360 */
+      { 1, 1, 0,-4, 1,    -13.0,   0.0,    0.0,      6.0,  0.0,    0.0},
+      {-1, 0, 2,-4, 1,    -17.0,   0.0,    0.0,      9.0,  0.0,    0.0},
+      { 0, 0, 4,-4, 1,    -14.0,   0.0,    0.0,      8.0,  0.0,    0.0},
+      { 0, 3, 2,-2, 2,      0.0,   0.0,    0.0,     -7.0,  0.0,    0.0},
+      {-3,-1, 0, 4, 0,     14.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      {-3, 0, 0, 4, 1,     19.0,   0.0,    0.0,    -10.0,  0.0,    0.0},
+      { 1,-1,-2, 2, 0,    -34.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      {-1,-1, 0, 2, 2,    -20.0,   0.0,    0.0,      8.0,  0.0,    0.0},
+      { 1,-2, 0, 0, 1,      9.0,   0.0,    0.0,     -5.0,  0.0,    0.0},
+      { 1,-1, 0, 0, 2,    -18.0,   0.0,    0.0,      7.0,  0.0,    0.0},
+
+   /* 361-370 */
+      { 0, 0, 0, 1, 2,     13.0,   0.0,    0.0,     -6.0,  0.0,    0.0},
+      {-1,-1, 2, 0, 0,     17.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      { 1,-2, 2,-2, 2,    -12.0,   0.0,    0.0,      5.0,  0.0,    0.0},
+      { 0,-1, 2,-1, 1,     15.0,   0.0,    0.0,     -8.0,  0.0,    0.0},
+      {-1, 0, 2, 0, 3,    -11.0,   0.0,    0.0,      3.0,  0.0,    0.0},
+      { 1, 1, 0, 0, 2,     13.0,   0.0,    0.0,     -5.0,  0.0,    0.0},
+      {-1, 1, 2, 0, 0,    -18.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      { 1, 2, 0, 0, 0,    -35.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      {-1, 2, 2, 0, 2,      9.0,   0.0,    0.0,     -4.0,  0.0,    0.0},
+      {-1, 0, 4,-2, 1,    -19.0,   0.0,    0.0,     10.0,  0.0,    0.0},
+
+   /* 371-380 */
+      { 3, 0, 2,-4, 2,    -26.0,   0.0,    0.0,     11.0,  0.0,    0.0},
+      { 1, 2, 2,-2, 1,      8.0,   0.0,    0.0,     -4.0,  0.0,    0.0},
+      { 1, 0, 4,-4, 2,    -10.0,   0.0,    0.0,      4.0,  0.0,    0.0},
+      {-2,-1, 0, 4, 1,     10.0,   0.0,    0.0,     -6.0,  0.0,    0.0},
+      { 0,-1, 0, 2, 2,    -21.0,   0.0,    0.0,      9.0,  0.0,    0.0},
+      {-2, 1, 0, 4, 0,    -15.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      {-2,-1, 2, 2, 1,      9.0,   0.0,    0.0,     -5.0,  0.0,    0.0},
+      { 2, 0,-2, 2, 0,    -29.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      { 1, 0, 0, 1, 1,    -19.0,   0.0,    0.0,     10.0,  0.0,    0.0},
+      { 0, 1, 0, 2, 2,     12.0,   0.0,    0.0,     -5.0,  0.0,    0.0},
+
+   /* 381-390 */
+      { 1,-1, 2,-1, 2,     22.0,   0.0,    0.0,     -9.0,  0.0,    0.0},
+      {-2, 0, 4, 0, 1,    -10.0,   0.0,    0.0,      5.0,  0.0,    0.0},
+      { 2, 1, 0, 0, 1,    -20.0,   0.0,    0.0,     11.0,  0.0,    0.0},
+      { 0, 1, 2, 0, 0,    -20.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      { 0,-1, 4,-2, 2,    -17.0,   0.0,    0.0,      7.0,  0.0,    0.0},
+      { 0, 0, 4,-2, 4,     15.0,   0.0,    0.0,     -3.0,  0.0,    0.0},
+      { 0, 2, 2, 0, 1,      8.0,   0.0,    0.0,     -4.0,  0.0,    0.0},
+      {-3, 0, 0, 6, 0,     14.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      {-1,-1, 0, 4, 1,    -12.0,   0.0,    0.0,      6.0,  0.0,    0.0},
+      { 1,-2, 0, 2, 0,     25.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+
+   /* 391-400 */
+      {-1, 0, 0, 4, 2,    -13.0,   0.0,    0.0,      6.0,  0.0,    0.0},
+      {-1,-2, 2, 2, 1,    -14.0,   0.0,    0.0,      8.0,  0.0,    0.0},
+      {-1, 0, 0,-2, 2,     13.0,   0.0,    0.0,     -5.0,  0.0,    0.0},
+      { 1, 0,-2,-2, 1,    -17.0,   0.0,    0.0,      9.0,  0.0,    0.0},
+      { 0, 0,-2,-2, 1,    -12.0,   0.0,    0.0,      6.0,  0.0,    0.0},
+      {-2, 0,-2, 0, 1,    -10.0,   0.0,    0.0,      5.0,  0.0,    0.0},
+      { 0, 0, 0, 3, 1,     10.0,   0.0,    0.0,     -6.0,  0.0,    0.0},
+      { 0, 0, 0, 3, 0,    -15.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      {-1, 1, 0, 4, 0,    -22.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      {-1,-1, 2, 2, 0,     28.0,   0.0,    0.0,     -1.0,  0.0,    0.0},
+
+   /* 401-410 */
+      {-2, 0, 2, 3, 2,     15.0,   0.0,    0.0,     -7.0,  0.0,    0.0},
+      { 1, 0, 0, 2, 2,     23.0,   0.0,    0.0,    -10.0,  0.0,    0.0},
+      { 0,-1, 2, 1, 2,     12.0,   0.0,    0.0,     -5.0,  0.0,    0.0},
+      { 3,-1, 0, 0, 0,     29.0,   0.0,    0.0,     -1.0,  0.0,    0.0},
+      { 2, 0, 0, 1, 0,    -25.0,   0.0,    0.0,      1.0,  0.0,    0.0},
+      { 1,-1, 2, 0, 0,     22.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      { 0, 0, 2, 1, 0,    -18.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      { 1, 0, 2, 0, 3,     15.0,   0.0,    0.0,      3.0,  0.0,    0.0},
+      { 3, 1, 0, 0, 0,    -23.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      { 3,-1, 2,-2, 2,     12.0,   0.0,    0.0,     -5.0,  0.0,    0.0},
+
+   /* 411-420 */
+      { 2, 0, 2,-1, 1,     -8.0,   0.0,    0.0,      4.0,  0.0,    0.0},
+      { 1, 1, 2, 0, 0,    -19.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      { 0, 0, 4,-1, 2,    -10.0,   0.0,    0.0,      4.0,  0.0,    0.0},
+      { 1, 2, 2, 0, 2,     21.0,   0.0,    0.0,     -9.0,  0.0,    0.0},
+      {-2, 0, 0, 6, 0,     23.0,   0.0,    0.0,     -1.0,  0.0,    0.0},
+      { 0,-1, 0, 4, 1,    -16.0,   0.0,    0.0,      8.0,  0.0,    0.0},
+      {-2,-1, 2, 4, 1,    -19.0,   0.0,    0.0,      9.0,  0.0,    0.0},
+      { 0,-2, 2, 2, 1,    -22.0,   0.0,    0.0,     10.0,  0.0,    0.0},
+      { 0,-1, 2, 2, 0,     27.0,   0.0,    0.0,     -1.0,  0.0,    0.0},
+      {-1, 0, 2, 3, 1,     16.0,   0.0,    0.0,     -8.0,  0.0,    0.0},
+
+   /* 421-430 */
+      {-2, 1, 2, 4, 2,     19.0,   0.0,    0.0,     -8.0,  0.0,    0.0},
+      { 2, 0, 0, 2, 2,      9.0,   0.0,    0.0,     -4.0,  0.0,    0.0},
+      { 2,-2, 2, 0, 2,     -9.0,   0.0,    0.0,      4.0,  0.0,    0.0},
+      {-1, 1, 2, 3, 2,     -9.0,   0.0,    0.0,      4.0,  0.0,    0.0},
+      { 3, 0, 2,-1, 2,     -8.0,   0.0,    0.0,      4.0,  0.0,    0.0},
+      { 4, 0, 2,-2, 1,     18.0,   0.0,    0.0,     -9.0,  0.0,    0.0},
+      {-1, 0, 0, 6, 0,     16.0,   0.0,    0.0,     -1.0,  0.0,    0.0},
+      {-1,-2, 2, 4, 2,    -10.0,   0.0,    0.0,      4.0,  0.0,    0.0},
+      {-3, 0, 2, 6, 2,    -23.0,   0.0,    0.0,      9.0,  0.0,    0.0},
+      {-1, 0, 2, 4, 0,     16.0,   0.0,    0.0,     -1.0,  0.0,    0.0},
+
+   /* 431-440 */
+      { 3, 0, 0, 2, 1,    -12.0,   0.0,    0.0,      6.0,  0.0,    0.0},
+      { 3,-1, 2, 0, 1,     -8.0,   0.0,    0.0,      4.0,  0.0,    0.0},
+      { 3, 0, 2, 0, 0,     30.0,   0.0,    0.0,     -2.0,  0.0,    0.0},
+      { 1, 0, 4, 0, 2,     24.0,   0.0,    0.0,    -10.0,  0.0,    0.0},
+      { 5, 0, 2,-2, 2,     10.0,   0.0,    0.0,     -4.0,  0.0,    0.0},
+      { 0,-1, 2, 4, 1,    -16.0,   0.0,    0.0,      7.0,  0.0,    0.0},
+      { 2,-1, 2, 2, 1,    -16.0,   0.0,    0.0,      7.0,  0.0,    0.0},
+      { 0, 1, 2, 4, 2,     17.0,   0.0,    0.0,     -7.0,  0.0,    0.0},
+      { 1,-1, 2, 4, 2,    -24.0,   0.0,    0.0,     10.0,  0.0,    0.0},
+      { 3,-1, 2, 2, 2,    -12.0,   0.0,    0.0,      5.0,  0.0,    0.0},
+
+   /* 441-450 */
+      { 3, 0, 2, 2, 1,    -24.0,   0.0,    0.0,     11.0,  0.0,    0.0},
+      { 5, 0, 2, 0, 2,    -23.0,   0.0,    0.0,      9.0,  0.0,    0.0},
+      { 0, 0, 2, 6, 2,    -13.0,   0.0,    0.0,      5.0,  0.0,    0.0},
+      { 4, 0, 2, 2, 2,    -15.0,   0.0,    0.0,      7.0,  0.0,    0.0},
+      { 0,-1, 1,-1, 1,      0.0,   0.0,-1988.0,      0.0,  0.0,-1679.0},
+      {-1, 0, 1, 0, 3,      0.0,   0.0,  -63.0,      0.0,  0.0,  -27.0},
+      { 0,-2, 2,-2, 3,     -4.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      { 1, 0,-1, 0, 1,      0.0,   0.0,    5.0,      0.0,  0.0,    4.0},
+      { 2,-2, 0,-2, 1,      5.0,   0.0,    0.0,     -3.0,  0.0,    0.0},
+      {-1, 0, 1, 0, 2,      0.0,   0.0,  364.0,      0.0,  0.0,  176.0},
+
+   /* 451-460 */
+      {-1, 0, 1, 0, 1,      0.0,   0.0,-1044.0,      0.0,  0.0, -891.0},
+      {-1,-1, 2,-1, 2,     -3.0,   0.0,    0.0,      1.0,  0.0,    0.0},
+      {-2, 2, 0, 2, 2,      4.0,   0.0,    0.0,     -2.0,  0.0,    0.0},
+      {-1, 0, 1, 0, 0,      0.0,   0.0,  330.0,      0.0,  0.0,    0.0},
+      {-4, 1, 2, 2, 2,      5.0,   0.0,    0.0,     -2.0,  0.0,    0.0},
+      {-3, 0, 2, 1, 1,      3.0,   0.0,    0.0,     -2.0,  0.0,    0.0},
+      {-2,-1, 2, 0, 2,     -3.0,   0.0,    0.0,      1.0,  0.0,    0.0},
+      { 1, 0,-2, 1, 1,     -5.0,   0.0,    0.0,      2.0,  0.0,    0.0},
+      { 2,-1,-2, 0, 1,      3.0,   0.0,    0.0,     -1.0,  0.0,    0.0},
+      {-4, 0, 2, 2, 0,      3.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+
+   /* 461-470 */
+      {-3, 1, 0, 3, 0,      3.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      {-1, 0,-1, 2, 0,      0.0,   0.0,    5.0,      0.0,  0.0,    0.0},
+      { 0,-2, 0, 0, 2,      0.0,   0.0,    0.0,      1.0,  0.0,    0.0},
+      { 0,-2, 0, 0, 2,      4.0,   0.0,    0.0,     -2.0,  0.0,    0.0},
+      {-3, 0, 0, 3, 0,      6.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      {-2,-1, 0, 2, 2,      5.0,   0.0,    0.0,     -2.0,  0.0,    0.0},
+      {-1, 0,-2, 3, 0,     -7.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      {-4, 0, 0, 4, 0,    -12.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      { 2, 1,-2, 0, 1,      5.0,   0.0,    0.0,     -3.0,  0.0,    0.0},
+      { 2,-1, 0,-2, 2,      3.0,   0.0,    0.0,     -1.0,  0.0,    0.0},
+
+   /* 471-480 */
+      { 0, 0, 1,-1, 0,     -5.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      {-1, 2, 0, 1, 0,      3.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      {-2, 1, 2, 0, 2,     -7.0,   0.0,    0.0,      3.0,  0.0,    0.0},
+      { 1, 1, 0,-1, 1,      7.0,   0.0,    0.0,     -4.0,  0.0,    0.0},
+      { 1, 0, 1,-2, 1,      0.0,   0.0,  -12.0,      0.0,  0.0,  -10.0},
+      { 0, 2, 0, 0, 2,      4.0,   0.0,    0.0,     -2.0,  0.0,    0.0},
+      { 1,-1, 2,-3, 1,      3.0,   0.0,    0.0,     -2.0,  0.0,    0.0},
+      {-1, 1, 2,-1, 1,     -3.0,   0.0,    0.0,      2.0,  0.0,    0.0},
+      {-2, 0, 4,-2, 2,     -7.0,   0.0,    0.0,      3.0,  0.0,    0.0},
+      {-2, 0, 4,-2, 1,     -4.0,   0.0,    0.0,      2.0,  0.0,    0.0},
+
+   /* 481-490 */
+      {-2,-2, 0, 2, 1,     -3.0,   0.0,    0.0,      1.0,  0.0,    0.0},
+      {-2, 0,-2, 4, 0,      0.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      { 1, 2, 2,-4, 1,     -3.0,   0.0,    0.0,      1.0,  0.0,    0.0},
+      { 1, 1, 2,-4, 2,      7.0,   0.0,    0.0,     -3.0,  0.0,    0.0},
+      {-1, 2, 2,-2, 1,     -4.0,   0.0,    0.0,      2.0,  0.0,    0.0},
+      { 2, 0, 0,-3, 1,      4.0,   0.0,    0.0,     -2.0,  0.0,    0.0},
+      {-1, 2, 0, 0, 1,     -5.0,   0.0,    0.0,      3.0,  0.0,    0.0},
+      { 0, 0, 0,-2, 0,      5.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      {-1,-1, 2,-2, 2,     -5.0,   0.0,    0.0,      2.0,  0.0,    0.0},
+      {-1, 1, 0, 0, 2,      5.0,   0.0,    0.0,     -2.0,  0.0,    0.0},
+
+   /* 491-500 */
+      { 0, 0, 0,-1, 2,     -8.0,   0.0,    0.0,      3.0,  0.0,    0.0},
+      {-2, 1, 0, 1, 0,      9.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      { 1,-2, 0,-2, 1,      6.0,   0.0,    0.0,     -3.0,  0.0,    0.0},
+      { 1, 0,-2, 0, 2,     -5.0,   0.0,    0.0,      2.0,  0.0,    0.0},
+      {-3, 1, 0, 2, 0,      3.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      {-1, 1,-2, 2, 0,     -7.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      {-1,-1, 0, 0, 2,     -3.0,   0.0,    0.0,      1.0,  0.0,    0.0},
+      {-3, 0, 0, 2, 0,      5.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      {-3,-1, 0, 2, 0,      3.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      { 2, 0, 2,-6, 1,     -3.0,   0.0,    0.0,      2.0,  0.0,    0.0},
+
+   /* 501-510 */
+      { 0, 1, 2,-4, 2,      4.0,   0.0,    0.0,     -2.0,  0.0,    0.0},
+      { 2, 0, 0,-4, 2,      3.0,   0.0,    0.0,     -1.0,  0.0,    0.0},
+      {-2, 1, 2,-2, 1,     -5.0,   0.0,    0.0,      2.0,  0.0,    0.0},
+      { 0,-1, 2,-4, 1,      4.0,   0.0,    0.0,     -2.0,  0.0,    0.0},
+      { 0, 1, 0,-2, 2,      9.0,   0.0,    0.0,     -3.0,  0.0,    0.0},
+      {-1, 0, 0,-2, 0,      4.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      { 2, 0,-2,-2, 1,      4.0,   0.0,    0.0,     -2.0,  0.0,    0.0},
+      {-4, 0, 2, 0, 1,     -3.0,   0.0,    0.0,      2.0,  0.0,    0.0},
+      {-1,-1, 0,-1, 1,     -4.0,   0.0,    0.0,      2.0,  0.0,    0.0},
+      { 0, 0,-2, 0, 2,      9.0,   0.0,    0.0,     -3.0,  0.0,    0.0},
+
+   /* 511-520 */
+      {-3, 0, 0, 1, 0,     -4.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      {-1, 0,-2, 1, 0,     -4.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      {-2, 0,-2, 2, 1,      3.0,   0.0,    0.0,     -2.0,  0.0,    0.0},
+      { 0, 0,-4, 2, 0,      8.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      {-2,-1,-2, 2, 0,      3.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      { 1, 0, 2,-6, 1,     -3.0,   0.0,    0.0,      2.0,  0.0,    0.0},
+      {-1, 0, 2,-4, 2,      3.0,   0.0,    0.0,     -1.0,  0.0,    0.0},
+      { 1, 0, 0,-4, 2,      3.0,   0.0,    0.0,     -1.0,  0.0,    0.0},
+      { 2, 1, 2,-4, 2,     -3.0,   0.0,    0.0,      1.0,  0.0,    0.0},
+      { 2, 1, 2,-4, 1,      6.0,   0.0,    0.0,     -3.0,  0.0,    0.0},
+
+   /* 521-530 */
+      { 0, 1, 4,-4, 4,      3.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      { 0, 1, 4,-4, 2,     -3.0,   0.0,    0.0,      1.0,  0.0,    0.0},
+      {-1,-1,-2, 4, 0,     -7.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      {-1,-3, 0, 2, 0,      9.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      {-1, 0,-2, 4, 1,     -3.0,   0.0,    0.0,      2.0,  0.0,    0.0},
+      {-2,-1, 0, 3, 0,     -3.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      { 0, 0,-2, 3, 0,     -4.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      {-2, 0, 0, 3, 1,     -5.0,   0.0,    0.0,      3.0,  0.0,    0.0},
+      { 0,-1, 0, 1, 0,    -13.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      {-3, 0, 2, 2, 0,     -7.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+
+   /* 531-540 */
+      { 1, 1,-2, 2, 0,     10.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      {-1, 1, 0, 2, 2,      3.0,   0.0,    0.0,     -1.0,  0.0,    0.0},
+      { 1,-2, 2,-2, 1,     10.0,   0.0,   13.0,      6.0,  0.0,   -5.0},
+      { 0, 0, 1, 0, 2,      0.0,   0.0,   30.0,      0.0,  0.0,   14.0},
+      { 0, 0, 1, 0, 1,      0.0,   0.0, -162.0,      0.0,  0.0, -138.0},
+      { 0, 0, 1, 0, 0,      0.0,   0.0,   75.0,      0.0,  0.0,    0.0},
+      {-1, 2, 0, 2, 1,     -7.0,   0.0,    0.0,      4.0,  0.0,    0.0},
+      { 0, 0, 2, 0, 2,     -4.0,   0.0,    0.0,      2.0,  0.0,    0.0},
+      {-2, 0, 2, 0, 2,      4.0,   0.0,    0.0,     -2.0,  0.0,    0.0},
+      { 2, 0, 0,-1, 1,      5.0,   0.0,    0.0,     -2.0,  0.0,    0.0},
+
+   /* 541-550 */
+      { 3, 0, 0,-2, 1,      5.0,   0.0,    0.0,     -3.0,  0.0,    0.0},
+      { 1, 0, 2,-2, 3,     -3.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      { 1, 2, 0, 0, 1,     -3.0,   0.0,    0.0,      2.0,  0.0,    0.0},
+      { 2, 0, 2,-3, 2,     -4.0,   0.0,    0.0,      2.0,  0.0,    0.0},
+      {-1, 1, 4,-2, 2,     -5.0,   0.0,    0.0,      2.0,  0.0,    0.0},
+      {-2,-2, 0, 4, 0,      6.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      { 0,-3, 0, 2, 0,      9.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      { 0, 0,-2, 4, 0,      5.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      {-1,-1, 0, 3, 0,     -7.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      {-2, 0, 0, 4, 2,     -3.0,   0.0,    0.0,      1.0,  0.0,    0.0},
+
+   /* 551-560 */
+      {-1, 0, 0, 3, 1,     -4.0,   0.0,    0.0,      2.0,  0.0,    0.0},
+      { 2,-2, 0, 0, 0,      7.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      { 1,-1, 0, 1, 0,     -4.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      {-1, 0, 0, 2, 0,      4.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      { 0,-2, 2, 0, 1,     -6.0,   0.0,   -3.0,      3.0,  0.0,    1.0},
+      {-1, 0, 1, 2, 1,      0.0,   0.0,   -3.0,      0.0,  0.0,   -2.0},
+      {-1, 1, 0, 3, 0,     11.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      {-1,-1, 2, 1, 2,      3.0,   0.0,    0.0,     -1.0,  0.0,    0.0},
+      { 0,-1, 2, 0, 0,     11.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      {-2, 1, 2, 2, 1,     -3.0,   0.0,    0.0,      2.0,  0.0,    0.0},
+
+   /* 561-570 */
+      { 2,-2, 2,-2, 2,     -1.0,   0.0,    3.0,      3.0,  0.0,   -1.0},
+      { 1, 1, 0, 1, 1,      4.0,   0.0,    0.0,     -2.0,  0.0,    0.0},
+      { 1, 0, 1, 0, 1,      0.0,   0.0,  -13.0,      0.0,  0.0,  -11.0},
+      { 1, 0, 1, 0, 0,      3.0,   0.0,    6.0,      0.0,  0.0,    0.0},
+      { 0, 2, 0, 2, 0,     -7.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      { 2,-1, 2,-2, 1,      5.0,   0.0,    0.0,     -3.0,  0.0,    0.0},
+      { 0,-1, 4,-2, 1,     -3.0,   0.0,    0.0,      1.0,  0.0,    0.0},
+      { 0, 0, 4,-2, 3,      3.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      { 0, 1, 4,-2, 1,      5.0,   0.0,    0.0,     -3.0,  0.0,    0.0},
+      { 4, 0, 2,-4, 2,     -7.0,   0.0,    0.0,      3.0,  0.0,    0.0},
+
+   /* 571-580 */
+      { 2, 2, 2,-2, 2,      8.0,   0.0,    0.0,     -3.0,  0.0,    0.0},
+      { 2, 0, 4,-4, 2,     -4.0,   0.0,    0.0,      2.0,  0.0,    0.0},
+      {-1,-2, 0, 4, 0,     11.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      {-1,-3, 2, 2, 2,     -3.0,   0.0,    0.0,      1.0,  0.0,    0.0},
+      {-3, 0, 2, 4, 2,      3.0,   0.0,    0.0,     -1.0,  0.0,    0.0},
+      {-3, 0, 2,-2, 1,     -4.0,   0.0,    0.0,      2.0,  0.0,    0.0},
+      {-1,-1, 0,-2, 1,      8.0,   0.0,    0.0,     -4.0,  0.0,    0.0},
+      {-3, 0, 0, 0, 2,      3.0,   0.0,    0.0,     -1.0,  0.0,    0.0},
+      {-3, 0,-2, 2, 0,     11.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      { 0, 1, 0,-4, 1,     -6.0,   0.0,    0.0,      3.0,  0.0,    0.0},
+
+   /* 581-590 */
+      {-2, 1, 0,-2, 1,     -4.0,   0.0,    0.0,      2.0,  0.0,    0.0},
+      {-4, 0, 0, 0, 1,     -8.0,   0.0,    0.0,      4.0,  0.0,    0.0},
+      {-1, 0, 0,-4, 1,     -7.0,   0.0,    0.0,      3.0,  0.0,    0.0},
+      {-3, 0, 0,-2, 1,     -4.0,   0.0,    0.0,      2.0,  0.0,    0.0},
+      { 0, 0, 0, 3, 2,      3.0,   0.0,    0.0,     -1.0,  0.0,    0.0},
+      {-1, 1, 0, 4, 1,      6.0,   0.0,    0.0,     -3.0,  0.0,    0.0},
+      { 1,-2, 2, 0, 1,     -6.0,   0.0,    0.0,      3.0,  0.0,    0.0},
+      { 0, 1, 0, 3, 0,      6.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      {-1, 0, 2, 2, 3,      6.0,   0.0,    0.0,     -1.0,  0.0,    0.0},
+      { 0, 0, 2, 2, 2,      5.0,   0.0,    0.0,     -2.0,  0.0,    0.0},
+
+   /* 591-600 */
+      {-2, 0, 2, 2, 2,     -5.0,   0.0,    0.0,      2.0,  0.0,    0.0},
+      {-1, 1, 2, 2, 0,     -4.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      { 3, 0, 0, 0, 2,     -4.0,   0.0,    0.0,      2.0,  0.0,    0.0},
+      { 2, 1, 0, 1, 0,      4.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      { 2,-1, 2,-1, 2,      6.0,   0.0,    0.0,     -3.0,  0.0,    0.0},
+      { 0, 0, 2, 0, 1,     -4.0,   0.0,    0.0,      2.0,  0.0,    0.0},
+      { 0, 0, 3, 0, 3,      0.0,   0.0,  -26.0,      0.0,  0.0,  -11.0},
+      { 0, 0, 3, 0, 2,      0.0,   0.0,  -10.0,      0.0,  0.0,   -5.0},
+      {-1, 2, 2, 2, 1,      5.0,   0.0,    0.0,     -3.0,  0.0,    0.0},
+      {-1, 0, 4, 0, 0,    -13.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+
+   /* 601-610 */
+      { 1, 2, 2, 0, 1,      3.0,   0.0,    0.0,     -2.0,  0.0,    0.0},
+      { 3, 1, 2,-2, 1,      4.0,   0.0,    0.0,     -2.0,  0.0,    0.0},
+      { 1, 1, 4,-2, 2,      7.0,   0.0,    0.0,     -3.0,  0.0,    0.0},
+      {-2,-1, 0, 6, 0,      4.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      { 0,-2, 0, 4, 0,      5.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      {-2, 0, 0, 6, 1,     -3.0,   0.0,    0.0,      2.0,  0.0,    0.0},
+      {-2,-2, 2, 4, 2,     -6.0,   0.0,    0.0,      2.0,  0.0,    0.0},
+      { 0,-3, 2, 2, 2,     -5.0,   0.0,    0.0,      2.0,  0.0,    0.0},
+      { 0, 0, 0, 4, 2,     -7.0,   0.0,    0.0,      3.0,  0.0,    0.0},
+      {-1,-1, 2, 3, 2,      5.0,   0.0,    0.0,     -2.0,  0.0,    0.0},
+
+   /* 611-620 */
+      {-2, 0, 2, 4, 0,     13.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      { 2,-1, 0, 2, 1,     -4.0,   0.0,    0.0,      2.0,  0.0,    0.0},
+      { 1, 0, 0, 3, 0,     -3.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      { 0, 1, 0, 4, 1,      5.0,   0.0,    0.0,     -2.0,  0.0,    0.0},
+      { 0, 1, 0, 4, 0,    -11.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      { 1,-1, 2, 1, 2,      5.0,   0.0,    0.0,     -2.0,  0.0,    0.0},
+      { 0, 0, 2, 2, 3,      4.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      { 1, 0, 2, 2, 2,      4.0,   0.0,    0.0,     -2.0,  0.0,    0.0},
+      {-1, 0, 2, 2, 2,     -4.0,   0.0,    0.0,      2.0,  0.0,    0.0},
+      {-2, 0, 4, 2, 1,      6.0,   0.0,    0.0,     -3.0,  0.0,    0.0},
+
+   /* 621-630 */
+      { 2, 1, 0, 2, 1,      3.0,   0.0,    0.0,     -2.0,  0.0,    0.0},
+      { 2, 1, 0, 2, 0,    -12.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      { 2,-1, 2, 0, 0,      4.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      { 1, 0, 2, 1, 0,     -3.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      { 0, 1, 2, 2, 0,     -4.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      { 2, 0, 2, 0, 3,      3.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      { 3, 0, 2, 0, 2,      3.0,   0.0,    0.0,     -1.0,  0.0,    0.0},
+      { 1, 0, 2, 0, 2,     -3.0,   0.0,    0.0,      1.0,  0.0,    0.0},
+      { 1, 0, 3, 0, 3,      0.0,   0.0,   -5.0,      0.0,  0.0,   -2.0},
+      { 1, 1, 2, 1, 1,     -7.0,   0.0,    0.0,      4.0,  0.0,    0.0},
+
+   /* 631-640 */
+      { 0, 2, 2, 2, 2,      6.0,   0.0,    0.0,     -3.0,  0.0,    0.0},
+      { 2, 1, 2, 0, 0,     -3.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      { 2, 0, 4,-2, 1,      5.0,   0.0,    0.0,     -3.0,  0.0,    0.0},
+      { 4, 1, 2,-2, 2,      3.0,   0.0,    0.0,     -1.0,  0.0,    0.0},
+      {-1,-1, 0, 6, 0,      3.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      {-3,-1, 2, 6, 2,     -3.0,   0.0,    0.0,      1.0,  0.0,    0.0},
+      {-1, 0, 0, 6, 1,     -5.0,   0.0,    0.0,      3.0,  0.0,    0.0},
+      {-3, 0, 2, 6, 1,     -3.0,   0.0,    0.0,      2.0,  0.0,    0.0},
+      { 1,-1, 0, 4, 1,     -3.0,   0.0,    0.0,      2.0,  0.0,    0.0},
+      { 1,-1, 0, 4, 0,     12.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+
+   /* 641-650 */
+      {-2, 0, 2, 5, 2,      3.0,   0.0,    0.0,     -1.0,  0.0,    0.0},
+      { 1,-2, 2, 2, 1,     -4.0,   0.0,    0.0,      2.0,  0.0,    0.0},
+      { 3,-1, 0, 2, 0,      4.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      { 1,-1, 2, 2, 0,      6.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      { 0, 0, 2, 3, 1,      5.0,   0.0,    0.0,     -3.0,  0.0,    0.0},
+      {-1, 1, 2, 4, 1,      4.0,   0.0,    0.0,     -2.0,  0.0,    0.0},
+      { 0, 1, 2, 3, 2,     -6.0,   0.0,    0.0,      3.0,  0.0,    0.0},
+      {-1, 0, 4, 2, 1,      4.0,   0.0,    0.0,     -2.0,  0.0,    0.0},
+      { 2, 0, 2, 1, 1,      6.0,   0.0,    0.0,     -3.0,  0.0,    0.0},
+      { 5, 0, 0, 0, 0,      6.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+
+   /* 651-660 */
+      { 2, 1, 2, 1, 2,     -6.0,   0.0,    0.0,      3.0,  0.0,    0.0},
+      { 1, 0, 4, 0, 1,      3.0,   0.0,    0.0,     -2.0,  0.0,    0.0},
+      { 3, 1, 2, 0, 1,      7.0,   0.0,    0.0,     -4.0,  0.0,    0.0},
+      { 3, 0, 4,-2, 2,      4.0,   0.0,    0.0,     -2.0,  0.0,    0.0},
+      {-2,-1, 2, 6, 2,     -5.0,   0.0,    0.0,      2.0,  0.0,    0.0},
+      { 0, 0, 0, 6, 0,      5.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      { 0,-2, 2, 4, 2,     -6.0,   0.0,    0.0,      3.0,  0.0,    0.0},
+      {-2, 0, 2, 6, 1,     -6.0,   0.0,    0.0,      3.0,  0.0,    0.0},
+      { 2, 0, 0, 4, 1,     -4.0,   0.0,    0.0,      2.0,  0.0,    0.0},
+      { 2, 0, 0, 4, 0,     10.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+
+   /* 661-670 */
+      { 2,-2, 2, 2, 2,     -4.0,   0.0,    0.0,      2.0,  0.0,    0.0},
+      { 0, 0, 2, 4, 0,      7.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      { 1, 0, 2, 3, 2,      7.0,   0.0,    0.0,     -3.0,  0.0,    0.0},
+      { 4, 0, 0, 2, 0,      4.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      { 2, 0, 2, 2, 0,     11.0,   0.0,    0.0,      0.0,  0.0,    0.0},
+      { 0, 0, 4, 2, 2,      5.0,   0.0,    0.0,     -2.0,  0.0,    0.0},
+      { 4,-1, 2, 0, 2,     -6.0,   0.0,    0.0,      2.0,  0.0,    0.0},
+      { 3, 0, 2, 1, 2,      4.0,   0.0,    0.0,     -2.0,  0.0,    0.0},
+      { 2, 1, 2, 2, 1,      3.0,   0.0,    0.0,     -2.0,  0.0,    0.0},
+      { 4, 1, 2, 0, 2,      5.0,   0.0,    0.0,     -2.0,  0.0,    0.0},
+
+   /* 671-678 */
+      {-1,-1, 2, 6, 2,     -4.0,   0.0,    0.0,      2.0,  0.0,    0.0},
+      {-1, 0, 2, 6, 1,     -4.0,   0.0,    0.0,      2.0,  0.0,    0.0},
+      { 1,-1, 2, 4, 1,     -3.0,   0.0,    0.0,      2.0,  0.0,    0.0},
+      { 1, 1, 2, 4, 2,      4.0,   0.0,    0.0,     -2.0,  0.0,    0.0},
+      { 3, 1, 2, 2, 2,      3.0,   0.0,    0.0,     -1.0,  0.0,    0.0},
+      { 5, 0, 2, 0, 1,     -3.0,   0.0,    0.0,      1.0,  0.0,    0.0},
+      { 2,-1, 2, 4, 2,     -3.0,   0.0,    0.0,      1.0,  0.0,    0.0},
+      { 2, 0, 2, 4, 1,     -3.0,   0.0,    0.0,      2.0,  0.0,    0.0}
+   };
+
+/* Number of terms in the luni-solar nutation model */
+   const int NLS = (int) (sizeof xls / sizeof xls[0]);
+
+/* ------------------------ */
+/* Planetary nutation model */
+/* ------------------------ */
+
+/* The units for the sine and cosine coefficients are */
+/* 0.1 microarcsecond                                 */
+
+   static const struct {
+      int nl,               /* coefficients of l, F, D and Omega */
+          nf,
+          nd,
+          nom,
+          nme,              /* coefficients of planetary longitudes */
+          nve,
+          nea,
+          nma,
+          nju,
+          nsa,
+          nur,
+          nne,
+          npa;              /* coefficient of general precession */
+      int sp,cp;            /* longitude sin, cos coefficients */
+      int se,ce;            /* obliquity sin, cos coefficients */
+   } xpl[] = {
+
+   /* 1-10 */
+      { 0, 0, 0, 0, 0,  0,  8,-16, 4, 5, 0, 0, 0, 1440,   0,    0,   0},
+      { 0, 0, 0, 0, 0,  0, -8, 16,-4,-5, 0, 0, 2,   56,-117,  -42, -40},
+      { 0, 0, 0, 0, 0,  0,  8,-16, 4, 5, 0, 0, 2,  125, -43,    0, -54},
+      { 0, 0, 0, 0, 0,  0,  0,  0, 0, 0,-1, 2, 2,    0,   5,    0,   0},
+      { 0, 0, 0, 0, 0,  0, -4,  8,-1,-5, 0, 0, 2,    3,  -7,   -3,   0},
+      { 0, 0, 0, 0, 0,  0,  4, -8, 3, 0, 0, 0, 1,    3,   0,    0,  -2},
+      { 0, 1,-1, 1, 0,  0,  3, -8, 3, 0, 0, 0, 0, -114,   0,    0,  61},
+      {-1, 0, 0, 0, 0, 10, -3,  0, 0, 0, 0, 0, 0, -219,  89,    0,   0},
+      { 0, 0, 0, 0, 0,  0,  0,  0,-2, 6,-3, 0, 2,   -3,   0,    0,   0},
+      { 0, 0, 0, 0, 0,  0,  4, -8, 3, 0, 0, 0, 0, -462,1604,    0,   0},
+
+   /* 11-20 */
+      { 0, 1,-1, 1, 0,  0, -5,  8,-3, 0, 0, 0, 0,   99,   0,    0, -53},
+      { 0, 0, 0, 0, 0,  0, -4,  8,-3, 0, 0, 0, 1,   -3,   0,    0,   2},
+      { 0, 0, 0, 0, 0,  0,  4, -8, 1, 5, 0, 0, 2,    0,   6,    2,   0},
+      { 0, 0, 0, 0, 0, -5,  6,  4, 0, 0, 0, 0, 2,    3,   0,    0,   0},
+      { 0, 0, 0, 0, 0,  0,  0,  0, 2,-5, 0, 0, 2,  -12,   0,    0,   0},
+      { 0, 0, 0, 0, 0,  0,  0,  0, 2,-5, 0, 0, 1,   14,-218,  117,   8},
+      { 0, 1,-1, 1, 0,  0, -1,  0, 2,-5, 0, 0, 0,   31,-481, -257, -17},
+      { 0, 0, 0, 0, 0,  0,  0,  0, 2,-5, 0, 0, 0, -491, 128,    0,   0},
+      { 0, 1,-1, 1, 0,  0, -1,  0,-2, 5, 0, 0, 0,-3084,5123, 2735,1647},
+      { 0, 0, 0, 0, 0,  0,  0,  0,-2, 5, 0, 0, 1,-1444,2409,-1286,-771},
+
+   /* 21-30 */
+      { 0, 0, 0, 0, 0,  0,  0,  0,-2, 5, 0, 0, 2,   11, -24,  -11,  -9},
+      { 2,-1,-1, 0, 0,  0,  3, -7, 0, 0, 0, 0, 0,   26,  -9,    0,   0},
+      { 1, 0,-2, 0, 0, 19,-21,  3, 0, 0, 0, 0, 0,  103, -60,    0,   0},
+      { 0, 1,-1, 1, 0,  2, -4,  0,-3, 0, 0, 0, 0,    0, -13,   -7,   0},
+      { 1, 0,-1, 1, 0,  0, -1,  0, 2, 0, 0, 0, 0,  -26, -29,  -16,  14},
+      { 0, 1,-1, 1, 0,  0, -1,  0,-4,10, 0, 0, 0,    9, -27,  -14,  -5},
+      {-2, 0, 2, 1, 0,  0,  2,  0, 0,-5, 0, 0, 0,   12,   0,    0,  -6},
+      { 0, 0, 0, 0, 0,  3, -7,  4, 0, 0, 0, 0, 0,   -7,   0,    0,   0},
+      { 0,-1, 1, 0, 0,  0,  1,  0, 1,-1, 0, 0, 0,    0,  24,    0,   0},
+      {-2, 0, 2, 1, 0,  0,  2,  0,-2, 0, 0, 0, 0,  284,   0,    0,-151},
+
+   /* 31-40 */
+      {-1, 0, 0, 0, 0, 18,-16,  0, 0, 0, 0, 0, 0,  226, 101,    0,   0},
+      {-2, 1, 1, 2, 0,  0,  1,  0,-2, 0, 0, 0, 0,    0,  -8,   -2,   0},
+      {-1, 1,-1, 1, 0, 18,-17,  0, 0, 0, 0, 0, 0,    0,  -6,   -3,   0},
+      {-1, 0, 1, 1, 0,  0,  2, -2, 0, 0, 0, 0, 0,    5,   0,    0,  -3},
+      { 0, 0, 0, 0, 0, -8, 13,  0, 0, 0, 0, 0, 2,  -41, 175,   76,  17},
+      { 0, 2,-2, 2, 0, -8, 11,  0, 0, 0, 0, 0, 0,    0,  15,    6,   0},
+      { 0, 0, 0, 0, 0, -8, 13,  0, 0, 0, 0, 0, 1,  425, 212, -133, 269},
+      { 0, 1,-1, 1, 0, -8, 12,  0, 0, 0, 0, 0, 0, 1200, 598,  319,-641},
+      { 0, 0, 0, 0, 0,  8,-13,  0, 0, 0, 0, 0, 0,  235, 334,    0,   0},
+      { 0, 1,-1, 1, 0,  8,-14,  0, 0, 0, 0, 0, 0,   11, -12,   -7,  -6},
+
+   /* 41-50 */
+      { 0, 0, 0, 0, 0,  8,-13,  0, 0, 0, 0, 0, 1,    5,  -6,    3,   3},
+      {-2, 0, 2, 1, 0,  0,  2,  0,-4, 5, 0, 0, 0,   -5,   0,    0,   3},
+      {-2, 0, 2, 2, 0,  3, -3,  0, 0, 0, 0, 0, 0,    6,   0,    0,  -3},
+      {-2, 0, 2, 0, 0,  0,  2,  0,-3, 1, 0, 0, 0,   15,   0,    0,   0},
+      { 0, 0, 0, 1, 0,  3, -5,  0, 2, 0, 0, 0, 0,   13,   0,    0,  -7},
+      {-2, 0, 2, 0, 0,  0,  2,  0,-4, 3, 0, 0, 0,   -6,  -9,    0,   0},
+      { 0,-1, 1, 0, 0,  0,  0,  2, 0, 0, 0, 0, 0,  266, -78,    0,   0},
+      { 0, 0, 0, 1, 0,  0, -1,  2, 0, 0, 0, 0, 0, -460,-435, -232, 246},
+      { 0, 1,-1, 2, 0,  0, -2,  2, 0, 0, 0, 0, 0,    0,  15,    7,   0},
+      {-1, 1, 0, 1, 0,  3, -5,  0, 0, 0, 0, 0, 0,   -3,   0,    0,   2},
+
+   /* 51-60 */
+      {-1, 0, 1, 0, 0,  3, -4,  0, 0, 0, 0, 0, 0,    0, 131,    0,   0},
+      {-2, 0, 2, 0, 0,  0,  2,  0,-2,-2, 0, 0, 0,    4,   0,    0,   0},
+      {-2, 2, 0, 2, 0,  0, -5,  9, 0, 0, 0, 0, 0,    0,   3,    0,   0},
+      { 0, 1,-1, 1, 0,  0, -1,  0, 0, 0,-1, 0, 0,    0,   4,    2,   0},
+      { 0, 0, 0, 0, 0,  0,  0,  0, 0, 0, 1, 0, 0,    0,   3,    0,   0},
+      { 0, 1,-1, 1, 0,  0, -1,  0, 0, 0, 0, 2, 0,  -17, -19,  -10,   9},
+      { 0, 0, 0, 0, 0,  0,  0,  0, 0, 0, 0, 2, 1,   -9, -11,    6,  -5},
+      { 0, 0, 0, 0, 0,  0,  0,  0, 0, 0, 0, 2, 2,   -6,   0,    0,   3},
+      {-1, 0, 1, 0, 0,  0,  3, -4, 0, 0, 0, 0, 0,  -16,   8,    0,   0},
+      { 0,-1, 1, 0, 0,  0,  1,  0, 0, 2, 0, 0, 0,    0,   3,    0,   0},
+
+   /* 61-70 */
+      { 0, 1,-1, 2, 0,  0, -1,  0, 0, 2, 0, 0, 0,   11,  24,   11,  -5},
+      { 0, 0, 0, 1, 0,  0, -9, 17, 0, 0, 0, 0, 0,   -3,  -4,   -2,   1},
+      { 0, 0, 0, 2, 0, -3,  5,  0, 0, 0, 0, 0, 0,    3,   0,    0,  -1},
+      { 0, 1,-1, 1, 0,  0, -1,  0,-1, 2, 0, 0, 0,    0,  -8,   -4,   0},
+      { 0, 0, 0, 0, 0,  0,  0,  0, 1,-2, 0, 0, 0,    0,   3,    0,   0},
+      { 1, 0,-2, 0, 0, 17,-16,  0,-2, 0, 0, 0, 0,    0,   5,    0,   0},
+      { 0, 1,-1, 1, 0,  0, -1,  0, 1,-3, 0, 0, 0,    0,   3,    2,   0},
+      {-2, 0, 2, 1, 0,  0,  5, -6, 0, 0, 0, 0, 0,   -6,   4,    2,   3},
+      { 0,-2, 2, 0, 0,  0,  9,-13, 0, 0, 0, 0, 0,   -3,  -5,    0,   0},
+      { 0, 1,-1, 2, 0,  0, -1,  0, 0, 1, 0, 0, 0,   -5,   0,    0,   2},
+
+   /* 71-80 */
+      { 0, 0, 0, 1, 0,  0,  0,  0, 0, 1, 0, 0, 0,    4,  24,   13,  -2},
+      { 0,-1, 1, 0, 0,  0,  1,  0, 0, 1, 0, 0, 0,  -42,  20,    0,   0},
+      { 0,-2, 2, 0, 0,  5, -6,  0, 0, 0, 0, 0, 0,  -10, 233,    0,   0},
+      { 0,-1, 1, 1, 0,  5, -7,  0, 0, 0, 0, 0, 0,   -3,   0,    0,   1},
+      {-2, 0, 2, 0, 0,  6, -8,  0, 0, 0, 0, 0, 0,   78, -18,    0,   0},
+      { 2, 1,-3, 1, 0, -6,  7,  0, 0, 0, 0, 0, 0,    0,   3,    1,   0},
+      { 0, 0, 0, 2, 0,  0,  0,  0, 1, 0, 0, 0, 0,    0,  -3,   -1,   0},
+      { 0,-1, 1, 1, 0,  0,  1,  0, 1, 0, 0, 0, 0,    0,  -4,   -2,   1},
+      { 0, 1,-1, 1, 0,  0, -1,  0, 0, 0, 2, 0, 0,    0,  -8,   -4,  -1},
+      { 0, 0, 0, 0, 0,  0,  0,  0, 0, 0, 2, 0, 1,    0,  -5,    3,   0},
+
+   /* 81-90 */
+      { 0, 0, 0, 0, 0,  0,  0,  0, 0, 0, 2, 0, 2,   -7,   0,    0,   3},
+      { 0, 0, 0, 0, 0,  0, -8, 15, 0, 0, 0, 0, 2,  -14,   8,    3,   6},
+      { 0, 0, 0, 0, 0,  0, -8, 15, 0, 0, 0, 0, 1,    0,   8,   -4,   0},
+      { 0, 1,-1, 1, 0,  0, -9, 15, 0, 0, 0, 0, 0,    0,  19,   10,   0},
+      { 0, 0, 0, 0, 0,  0,  8,-15, 0, 0, 0, 0, 0,   45, -22,    0,   0},
+      { 1,-1,-1, 0, 0,  0,  8,-15, 0, 0, 0, 0, 0,   -3,   0,    0,   0},
+      { 2, 0,-2, 0, 0,  2, -5,  0, 0, 0, 0, 0, 0,    0,  -3,    0,   0},
+      {-2, 0, 2, 0, 0,  0,  2,  0,-5, 5, 0, 0, 0,    0,   3,    0,   0},
+      { 2, 0,-2, 1, 0,  0, -6,  8, 0, 0, 0, 0, 0,    3,   5,    3,  -2},
+      { 2, 0,-2, 1, 0,  0, -2,  0, 3, 0, 0, 0, 0,   89, -16,   -9, -48},
+
+   /* 91-100 */
+      {-2, 1, 1, 0, 0,  0,  1,  0,-3, 0, 0, 0, 0,    0,   3,    0,   0},
+      {-2, 1, 1, 1, 0,  0,  1,  0,-3, 0, 0, 0, 0,   -3,   7,    4,   2},
+      {-2, 0, 2, 0, 0,  0,  2,  0,-3, 0, 0, 0, 0, -349, -62,    0,   0},
+      {-2, 0, 2, 0, 0,  0,  6, -8, 0, 0, 0, 0, 0,  -15,  22,    0,   0},
+      {-2, 0, 2, 0, 0,  0,  2,  0,-1,-5, 0, 0, 0,   -3,   0,    0,   0},
+      {-1, 0, 1, 0, 0,  0,  1,  0,-1, 0, 0, 0, 0,  -53,   0,    0,   0},
+      {-1, 1, 1, 1, 0,-20, 20,  0, 0, 0, 0, 0, 0,    5,   0,    0,  -3},
+      { 1, 0,-2, 0, 0, 20,-21,  0, 0, 0, 0, 0, 0,    0,  -8,    0,   0},
+      { 0, 0, 0, 1, 0,  0,  8,-15, 0, 0, 0, 0, 0,   15,  -7,   -4,  -8},
+      { 0, 2,-2, 1, 0,  0,-10, 15, 0, 0, 0, 0, 0,   -3,   0,    0,   1},
+
+   /* 101-110 */
+      { 0,-1, 1, 0, 0,  0,  1,  0, 1, 0, 0, 0, 0,  -21, -78,    0,   0},
+      { 0, 0, 0, 1, 0,  0,  0,  0, 1, 0, 0, 0, 0,   20, -70,  -37, -11},
+      { 0, 1,-1, 2, 0,  0, -1,  0, 1, 0, 0, 0, 0,    0,   6,    3,   0},
+      { 0, 1,-1, 1, 0,  0, -1,  0,-2, 4, 0, 0, 0,    5,   3,    2,  -2},
+      { 2, 0,-2, 1, 0, -6,  8,  0, 0, 0, 0, 0, 0,  -17,  -4,   -2,   9},
+      { 0,-2, 2, 1, 0,  5, -6,  0, 0, 0, 0, 0, 0,    0,   6,    3,   0},
+      { 0, 0, 0, 0, 0,  0,  0,  0, 0,-1, 0, 0, 1,   32,  15,   -8,  17},
+      { 0, 1,-1, 1, 0,  0, -1,  0, 0,-1, 0, 0, 0,  174,  84,   45, -93},
+      { 0, 0, 0, 0, 0,  0,  0,  0, 0, 1, 0, 0, 0,   11,  56,    0,   0},
+      { 0, 1,-1, 1, 0,  0, -1,  0, 0, 1, 0, 0, 0,  -66, -12,   -6,  35},
+
+   /* 111-120 */
+      { 0, 0, 0, 0, 0,  0,  0,  0, 0, 1, 0, 0, 1,   47,   8,    4, -25},
+      { 0, 0, 0, 0, 0,  0,  0,  0, 0, 1, 0, 0, 2,    0,   8,    4,   0},
+      { 0, 2,-2, 1, 0,  0, -9, 13, 0, 0, 0, 0, 0,   10, -22,  -12,  -5},
+      { 0, 0, 0, 1, 0,  0,  7,-13, 0, 0, 0, 0, 0,   -3,   0,    0,   2},
+      {-2, 0, 2, 0, 0,  0,  5, -6, 0, 0, 0, 0, 0,  -24,  12,    0,   0},
+      { 0, 0, 0, 0, 0,  0,  9,-17, 0, 0, 0, 0, 0,    5,  -6,    0,   0},
+      { 0, 0, 0, 0, 0,  0, -9, 17, 0, 0, 0, 0, 2,    3,   0,    0,  -2},
+      { 1, 0,-1, 1, 0,  0, -3,  4, 0, 0, 0, 0, 0,    4,   3,    1,  -2},
+      { 1, 0,-1, 1, 0, -3,  4,  0, 0, 0, 0, 0, 0,    0,  29,   15,   0},
+      { 0, 0, 0, 2, 0,  0, -1,  2, 0, 0, 0, 0, 0,   -5,  -4,   -2,   2},
+
+   /* 121-130 */
+      { 0,-1, 1, 1, 0,  0,  0,  2, 0, 0, 0, 0, 0,    8,  -3,   -1,  -5},
+      { 0,-2, 2, 0, 1,  0, -2,  0, 0, 0, 0, 0, 0,    0,  -3,    0,   0},
+      { 0, 0, 0, 0, 0,  3, -5,  0, 2, 0, 0, 0, 0,   10,   0,    0,   0},
+      {-2, 0, 2, 1, 0,  0,  2,  0,-3, 1, 0, 0, 0,    3,   0,    0,  -2},
+      {-2, 0, 2, 1, 0,  3, -3,  0, 0, 0, 0, 0, 0,   -5,   0,    0,   3},
+      { 0, 0, 0, 1, 0,  8,-13,  0, 0, 0, 0, 0, 0,   46,  66,   35, -25},
+      { 0,-1, 1, 0, 0,  8,-12,  0, 0, 0, 0, 0, 0,  -14,   7,    0,   0},
+      { 0, 2,-2, 1, 0, -8, 11,  0, 0, 0, 0, 0, 0,    0,   3,    2,   0},
+      {-1, 0, 1, 0, 0,  0,  2, -2, 0, 0, 0, 0, 0,   -5,   0,    0,   0},
+      {-1, 0, 0, 1, 0, 18,-16,  0, 0, 0, 0, 0, 0,  -68, -34,  -18,  36},
+
+   /* 131-140 */
+      { 0, 1,-1, 1, 0,  0, -1,  0,-1, 1, 0, 0, 0,    0,  14,    7,   0},
+      { 0, 0, 0, 1, 0,  3, -7,  4, 0, 0, 0, 0, 0,   10,  -6,   -3,  -5},
+      {-2, 1, 1, 1, 0,  0, -3,  7, 0, 0, 0, 0, 0,   -5,  -4,   -2,   3},
+      { 0, 1,-1, 2, 0,  0, -1,  0,-2, 5, 0, 0, 0,   -3,   5,    2,   1},
+      { 0, 0, 0, 1, 0,  0,  0,  0,-2, 5, 0, 0, 0,   76,  17,    9, -41},
+      { 0, 0, 0, 1, 0,  0, -4,  8,-3, 0, 0, 0, 0,   84, 298,  159, -45},
+      { 1, 0, 0, 1, 0,-10,  3,  0, 0, 0, 0, 0, 0,    3,   0,    0,  -1},
+      { 0, 2,-2, 1, 0,  0, -2,  0, 0, 0, 0, 0, 0,   -3,   0,    0,   2},
+      {-1, 0, 0, 1, 0, 10, -3,  0, 0, 0, 0, 0, 0,   -3,   0,    0,   1},
+      { 0, 0, 0, 1, 0,  0,  4, -8, 3, 0, 0, 0, 0,  -82, 292,  156,  44},
+
+   /* 141-150 */
+      { 0, 0, 0, 1, 0,  0,  0,  0, 2,-5, 0, 0, 0,  -73,  17,    9,  39},
+      { 0,-1, 1, 0, 0,  0,  1,  0, 2,-5, 0, 0, 0,   -9, -16,    0,   0},
+      { 2,-1,-1, 1, 0,  0,  3, -7, 0, 0, 0, 0, 0,    3,   0,   -1,  -2},
+      {-2, 0, 2, 0, 0,  0,  2,  0, 0,-5, 0, 0, 0,   -3,   0,    0,   0},
+      { 0, 0, 0, 1, 0, -3,  7, -4, 0, 0, 0, 0, 0,   -9,  -5,   -3,   5},
+      {-2, 0, 2, 0, 0,  0,  2,  0,-2, 0, 0, 0, 0, -439,   0,    0,   0},
+      { 1, 0, 0, 1, 0,-18, 16,  0, 0, 0, 0, 0, 0,   57, -28,  -15, -30},
+      {-2, 1, 1, 1, 0,  0,  1,  0,-2, 0, 0, 0, 0,    0,  -6,   -3,   0},
+      { 0, 1,-1, 2, 0, -8, 12,  0, 0, 0, 0, 0, 0,   -4,   0,    0,   2},
+      { 0, 0, 0, 1, 0, -8, 13,  0, 0, 0, 0, 0, 0,  -40,  57,   30,  21},
+
+   /* 151-160 */
+      { 0, 0, 0, 0, 0,  0,  1, -2, 0, 0, 0, 0, 1,   23,   7,    3, -13},
+      { 0, 1,-1, 1, 0,  0,  0, -2, 0, 0, 0, 0, 0,  273,  80,   43,-146},
+      { 0, 0, 0, 0, 0,  0,  1, -2, 0, 0, 0, 0, 0, -449, 430,    0,   0},
+      { 0, 1,-1, 1, 0,  0, -2,  2, 0, 0, 0, 0, 0,   -8, -47,  -25,   4},
+      { 0, 0, 0, 0, 0,  0, -1,  2, 0, 0, 0, 0, 1,    6,  47,   25,  -3},
+      {-1, 0, 1, 1, 0,  3, -4,  0, 0, 0, 0, 0, 0,    0,  23,   13,   0},
+      {-1, 0, 1, 1, 0,  0,  3, -4, 0, 0, 0, 0, 0,   -3,   0,    0,   2},
+      { 0, 1,-1, 1, 0,  0, -1,  0, 0,-2, 0, 0, 0,    3,  -4,   -2,  -2},
+      { 0, 1,-1, 1, 0,  0, -1,  0, 0, 2, 0, 0, 0,  -48,-110,  -59,  26},
+      { 0, 0, 0, 0, 0,  0,  0,  0, 0, 2, 0, 0, 1,   51, 114,   61, -27},
+
+   /* 161-170 */
+      { 0, 0, 0, 0, 0,  0,  0,  0, 0, 2, 0, 0, 2, -133,   0,    0,  57},
+      { 0, 1,-1, 0, 0,  3, -6,  0, 0, 0, 0, 0, 0,    0,   4,    0,   0},
+      { 0, 0, 0, 1, 0, -3,  5,  0, 0, 0, 0, 0, 0,  -21,  -6,   -3,  11},
+      { 0, 1,-1, 2, 0, -3,  4,  0, 0, 0, 0, 0, 0,    0,  -3,   -1,   0},
+      { 0, 0, 0, 1, 0,  0, -2,  4, 0, 0, 0, 0, 0,  -11, -21,  -11,   6},
+      { 0, 2,-2, 1, 0, -5,  6,  0, 0, 0, 0, 0, 0,  -18,-436, -233,   9},
+      { 0,-1, 1, 0, 0,  5, -7,  0, 0, 0, 0, 0, 0,   35,  -7,    0,   0},
+      { 0, 0, 0, 1, 0,  5, -8,  0, 0, 0, 0, 0, 0,    0,   5,    3,   0},
+      {-2, 0, 2, 1, 0,  6, -8,  0, 0, 0, 0, 0, 0,   11,  -3,   -1,  -6},
+      { 0, 0, 0, 1, 0,  0, -8, 15, 0, 0, 0, 0, 0,   -5,  -3,   -1,   3},
+
+   /* 171-180 */
+      {-2, 0, 2, 1, 0,  0,  2,  0,-3, 0, 0, 0, 0,  -53,  -9,   -5,  28},
+      {-2, 0, 2, 1, 0,  0,  6, -8, 0, 0, 0, 0, 0,    0,   3,    2,   1},
+      { 1, 0,-1, 1, 0,  0, -1,  0, 1, 0, 0, 0, 0,    4,   0,    0,  -2},
+      { 0, 0, 0, 0, 0,  0,  0,  0, 3,-5, 0, 0, 0,    0,  -4,    0,   0},
+      { 0, 1,-1, 1, 0,  0, -1,  0,-1, 0, 0, 0, 0,  -50, 194,  103,  27},
+      { 0, 0, 0, 0, 0,  0,  0,  0,-1, 0, 0, 0, 1,  -13,  52,   28,   7},
+      { 0, 0, 0, 0, 0,  0,  0,  0, 1, 0, 0, 0, 0,  -91, 248,    0,   0},
+      { 0, 0, 0, 0, 0,  0,  0,  0, 1, 0, 0, 0, 1,    6,  49,   26,  -3},
+      { 0, 1,-1, 1, 0,  0, -1,  0, 1, 0, 0, 0, 0,   -6, -47,  -25,   3},
+      { 0, 0, 0, 0, 0,  0,  0,  0, 1, 0, 0, 0, 1,    0,   5,    3,   0},
+
+   /* 181-190 */
+      { 0, 0, 0, 0, 0,  0,  0,  0, 1, 0, 0, 0, 2,   52,  23,   10, -23},
+      { 0, 1,-1, 2, 0,  0, -1,  0, 0,-1, 0, 0, 0,   -3,   0,    0,   1},
+      { 0, 0, 0, 1, 0,  0,  0,  0, 0,-1, 0, 0, 0,    0,   5,    3,   0},
+      { 0,-1, 1, 0, 0,  0,  1,  0, 0,-1, 0, 0, 0,   -4,   0,    0,   0},
+      { 0, 0, 0, 0, 0,  0, -7, 13, 0, 0, 0, 0, 2,   -4,   8,    3,   2},
+      { 0, 0, 0, 0, 0,  0,  7,-13, 0, 0, 0, 0, 0,   10,   0,    0,   0},
+      { 2, 0,-2, 1, 0,  0, -5,  6, 0, 0, 0, 0, 0,    3,   0,    0,  -2},
+      { 0, 2,-2, 1, 0,  0, -8, 11, 0, 0, 0, 0, 0,    0,   8,    4,   0},
+      { 0, 2,-2, 1,-1,  0,  2,  0, 0, 0, 0, 0, 0,    0,   8,    4,   1},
+      {-2, 0, 2, 0, 0,  0,  4, -4, 0, 0, 0, 0, 0,   -4,   0,    0,   0},
+
+   /* 191-200 */
+      { 0, 0, 0, 0, 0,  0,  0,  0, 2,-2, 0, 0, 0,   -4,   0,    0,   0},
+      { 0, 1,-1, 1, 0,  0, -1,  0, 0, 3, 0, 0, 0,   -8,   4,    2,   4},
+      { 0, 0, 0, 0, 0,  0,  0,  0, 0, 3, 0, 0, 1,    8,  -4,   -2,  -4},
+      { 0, 0, 0, 0, 0,  0,  0,  0, 0, 3, 0, 0, 2,    0,  15,    7,   0},
+      {-2, 0, 2, 0, 0,  3, -3,  0, 0, 0, 0, 0, 0, -138,   0,    0,   0},
+      { 0, 0, 0, 2, 0,  0, -4,  8,-3, 0, 0, 0, 0,    0,  -7,   -3,   0},
+      { 0, 0, 0, 2, 0,  0,  4, -8, 3, 0, 0, 0, 0,    0,  -7,   -3,   0},
+      { 2, 0,-2, 1, 0,  0, -2,  0, 2, 0, 0, 0, 0,   54,   0,    0, -29},
+      { 0, 1,-1, 2, 0,  0, -1,  0, 2, 0, 0, 0, 0,    0,  10,    4,   0},
+      { 0, 1,-1, 2, 0,  0,  0, -2, 0, 0, 0, 0, 0,   -7,   0,    0,   3},
+
+   /* 201-210 */
+      { 0, 0, 0, 1, 0,  0,  1, -2, 0, 0, 0, 0, 0,  -37,  35,   19,  20},
+      { 0,-1, 1, 0, 0,  0,  2, -2, 0, 0, 0, 0, 0,    0,   4,    0,   0},
+      { 0,-1, 1, 0, 0,  0,  1,  0, 0,-2, 0, 0, 0,   -4,   9,    0,   0},
+      { 0, 2,-2, 1, 0,  0, -2,  0, 0, 2, 0, 0, 0,    8,   0,    0,  -4},
+      { 0, 1,-1, 1, 0,  3, -6,  0, 0, 0, 0, 0, 0,   -9, -14,   -8,   5},
+      { 0, 0, 0, 0, 0,  3, -5,  0, 0, 0, 0, 0, 1,   -3,  -9,   -5,   3},
+      { 0, 0, 0, 0, 0,  3, -5,  0, 0, 0, 0, 0, 0, -145,  47,    0,   0},
+      { 0, 1,-1, 1, 0, -3,  4,  0, 0, 0, 0, 0, 0,  -10,  40,   21,   5},
+      { 0, 0, 0, 0, 0, -3,  5,  0, 0, 0, 0, 0, 1,   11, -49,  -26,  -7},
+      { 0, 0, 0, 0, 0, -3,  5,  0, 0, 0, 0, 0, 2,-2150,   0,    0, 932},
+
+   /* 211-220 */
+      { 0, 2,-2, 2, 0, -3,  3,  0, 0, 0, 0, 0, 0,  -12,   0,    0,   5},
+      { 0, 0, 0, 0, 0, -3,  5,  0, 0, 0, 0, 0, 2,   85,   0,    0, -37},
+      { 0, 0, 0, 0, 0,  0,  2, -4, 0, 0, 0, 0, 1,    4,   0,    0,  -2},
+      { 0, 1,-1, 1, 0,  0,  1, -4, 0, 0, 0, 0, 0,    3,   0,    0,  -2},
+      { 0, 0, 0, 0, 0,  0,  2, -4, 0, 0, 0, 0, 0,  -86, 153,    0,   0},
+      { 0, 0, 0, 0, 0,  0, -2,  4, 0, 0, 0, 0, 1,   -6,   9,    5,   3},
+      { 0, 1,-1, 1, 0,  0, -3,  4, 0, 0, 0, 0, 0,    9, -13,   -7,  -5},
+      { 0, 0, 0, 0, 0,  0, -2,  4, 0, 0, 0, 0, 1,   -8,  12,    6,   4},
+      { 0, 0, 0, 0, 0,  0, -2,  4, 0, 0, 0, 0, 2,  -51,   0,    0,  22},
+      { 0, 0, 0, 0, 0, -5,  8,  0, 0, 0, 0, 0, 2,  -11,-268, -116,   5},
+
+   /* 221-230 */
+      { 0, 2,-2, 2, 0, -5,  6,  0, 0, 0, 0, 0, 0,    0,  12,    5,   0},
+      { 0, 0, 0, 0, 0, -5,  8,  0, 0, 0, 0, 0, 2,    0,   7,    3,   0},
+      { 0, 0, 0, 0, 0, -5,  8,  0, 0, 0, 0, 0, 1,   31,   6,    3, -17},
+      { 0, 1,-1, 1, 0, -5,  7,  0, 0, 0, 0, 0, 0,  140,  27,   14, -75},
+      { 0, 0, 0, 0, 0, -5,  8,  0, 0, 0, 0, 0, 1,   57,  11,    6, -30},
+      { 0, 0, 0, 0, 0,  5, -8,  0, 0, 0, 0, 0, 0,  -14, -39,    0,   0},
+      { 0, 1,-1, 2, 0,  0, -1,  0,-1, 0, 0, 0, 0,    0,  -6,   -2,   0},
+      { 0, 0, 0, 1, 0,  0,  0,  0,-1, 0, 0, 0, 0,    4,  15,    8,  -2},
+      { 0,-1, 1, 0, 0,  0,  1,  0,-1, 0, 0, 0, 0,    0,   4,    0,   0},
+      { 0, 2,-2, 1, 0,  0, -2,  0, 1, 0, 0, 0, 0,   -3,   0,    0,   1},
+
+   /* 231-240 */
+      { 0, 0, 0, 0, 0,  0, -6, 11, 0, 0, 0, 0, 2,    0,  11,    5,   0},
+      { 0, 0, 0, 0, 0,  0,  6,-11, 0, 0, 0, 0, 0,    9,   6,    0,   0},
+      { 0, 0, 0, 0,-1,  0,  4,  0, 0, 0, 0, 0, 2,   -4,  10,    4,   2},
+      { 0, 0, 0, 0, 1,  0, -4,  0, 0, 0, 0, 0, 0,    5,   3,    0,   0},
+      { 2, 0,-2, 1, 0, -3,  3,  0, 0, 0, 0, 0, 0,   16,   0,    0,  -9},
+      {-2, 0, 2, 0, 0,  0,  2,  0, 0,-2, 0, 0, 0,   -3,   0,    0,   0},
+      { 0, 2,-2, 1, 0,  0, -7,  9, 0, 0, 0, 0, 0,    0,   3,    2,  -1},
+      { 0, 0, 0, 0, 0,  0,  0,  0, 4,-5, 0, 0, 2,    7,   0,    0,  -3},
+      { 0, 0, 0, 0, 0,  0,  0,  0, 2, 0, 0, 0, 0,  -25,  22,    0,   0},
+      { 0, 0, 0, 0, 0,  0,  0,  0, 2, 0, 0, 0, 1,   42, 223,  119, -22},
+
+   /* 241-250 */
+      { 0, 1,-1, 1, 0,  0, -1,  0, 2, 0, 0, 0, 0,  -27,-143,  -77,  14},
+      { 0, 0, 0, 0, 0,  0,  0,  0, 2, 0, 0, 0, 1,    9,  49,   26,  -5},
+      { 0, 0, 0, 0, 0,  0,  0,  0, 2, 0, 0, 0, 2,-1166,   0,    0, 505},
+      { 0, 2,-2, 2, 0,  0, -2,  0, 2, 0, 0, 0, 0,   -5,   0,    0,   2},
+      { 0, 0, 0, 0, 0,  0,  0,  0, 0, 5, 0, 0, 2,   -6,   0,    0,   3},
+      { 0, 0, 0, 1, 0,  3, -5,  0, 0, 0, 0, 0, 0,   -8,   0,    1,   4},
+      { 0,-1, 1, 0, 0,  3, -4,  0, 0, 0, 0, 0, 0,    0,  -4,    0,   0},
+      { 0, 2,-2, 1, 0, -3,  3,  0, 0, 0, 0, 0, 0,  117,   0,    0, -63},
+      { 0, 0, 0, 1, 0,  0,  2, -4, 0, 0, 0, 0, 0,   -4,   8,    4,   2},
+      { 0, 2,-2, 1, 0,  0, -4,  4, 0, 0, 0, 0, 0,    3,   0,    0,  -2},
+
+   /* 251-260 */
+      { 0, 1,-1, 2, 0, -5,  7,  0, 0, 0, 0, 0, 0,   -5,   0,    0,   2},
+      { 0, 0, 0, 0, 0,  0,  3, -6, 0, 0, 0, 0, 0,    0,  31,    0,   0},
+      { 0, 0, 0, 0, 0,  0, -3,  6, 0, 0, 0, 0, 1,   -5,   0,    1,   3},
+      { 0, 1,-1, 1, 0,  0, -4,  6, 0, 0, 0, 0, 0,    4,   0,    0,  -2},
+      { 0, 0, 0, 0, 0,  0, -3,  6, 0, 0, 0, 0, 1,   -4,   0,    0,   2},
+      { 0, 0, 0, 0, 0,  0, -3,  6, 0, 0, 0, 0, 2,  -24, -13,   -6,  10},
+      { 0,-1, 1, 0, 0,  2, -2,  0, 0, 0, 0, 0, 0,    3,   0,    0,   0},
+      { 0, 0, 0, 1, 0,  2, -3,  0, 0, 0, 0, 0, 0,    0, -32,  -17,   0},
+      { 0, 0, 0, 0, 0,  0, -5,  9, 0, 0, 0, 0, 2,    8,  12,    5,  -3},
+      { 0, 0, 0, 0, 0,  0, -5,  9, 0, 0, 0, 0, 1,    3,   0,    0,  -1},
+
+   /* 261-270 */
+      { 0, 0, 0, 0, 0,  0,  5, -9, 0, 0, 0, 0, 0,    7,  13,    0,   0},
+      { 0,-1, 1, 0, 0,  0,  1,  0,-2, 0, 0, 0, 0,   -3,  16,    0,   0},
+      { 0, 2,-2, 1, 0,  0, -2,  0, 2, 0, 0, 0, 0,   50,   0,    0, -27},
+      {-2, 1, 1, 1, 0,  0,  1,  0, 0, 0, 0, 0, 0,    0,  -5,   -3,   0},
+      { 0,-2, 2, 0, 0,  3, -3,  0, 0, 0, 0, 0, 0,   13,   0,    0,   0},
+      { 0, 0, 0, 0, 0, -6, 10,  0, 0, 0, 0, 0, 1,    0,   5,    3,   1},
+      { 0, 0, 0, 0, 0, -6, 10,  0, 0, 0, 0, 0, 2,   24,   5,    2, -11},
+      { 0, 0, 0, 0, 0, -2,  3,  0, 0, 0, 0, 0, 2,    5, -11,   -5,  -2},
+      { 0, 0, 0, 0, 0, -2,  3,  0, 0, 0, 0, 0, 1,   30,  -3,   -2, -16},
+      { 0, 1,-1, 1, 0, -2,  2,  0, 0, 0, 0, 0, 0,   18,   0,    0,  -9},
+
+   /* 271-280 */
+      { 0, 0, 0, 0, 0,  2, -3,  0, 0, 0, 0, 0, 0,    8, 614,    0,   0},
+      { 0, 0, 0, 0, 0,  2, -3,  0, 0, 0, 0, 0, 1,    3,  -3,   -1,  -2},
+      { 0, 0, 0, 0, 0,  0,  0,  0, 3, 0, 0, 0, 1,    6,  17,    9,  -3},
+      { 0, 1,-1, 1, 0,  0, -1,  0, 3, 0, 0, 0, 0,   -3,  -9,   -5,   2},
+      { 0, 0, 0, 0, 0,  0,  0,  0, 3, 0, 0, 0, 1,    0,   6,    3,  -1},
+      { 0, 0, 0, 0, 0,  0,  0,  0, 3, 0, 0, 0, 2, -127,  21,    9,  55},
+      { 0, 0, 0, 0, 0,  0,  4, -8, 0, 0, 0, 0, 0,    3,   5,    0,   0},
+      { 0, 0, 0, 0, 0,  0, -4,  8, 0, 0, 0, 0, 2,   -6, -10,   -4,   3},
+      { 0,-2, 2, 0, 0,  0,  2,  0,-2, 0, 0, 0, 0,    5,   0,    0,   0},
+      { 0, 0, 0, 0, 0,  0, -4,  7, 0, 0, 0, 0, 2,   16,   9,    4,  -7},
+
+   /* 281-290 */
+      { 0, 0, 0, 0, 0,  0, -4,  7, 0, 0, 0, 0, 1,    3,   0,    0,  -2},
+      { 0, 0, 0, 0, 0,  0,  4, -7, 0, 0, 0, 0, 0,    0,  22,    0,   0},
+      { 0, 0, 0, 1, 0, -2,  3,  0, 0, 0, 0, 0, 0,    0,  19,   10,   0},
+      { 0, 2,-2, 1, 0,  0, -2,  0, 3, 0, 0, 0, 0,    7,   0,    0,  -4},
+      { 0, 0, 0, 0, 0,  0, -5, 10, 0, 0, 0, 0, 2,    0,  -5,   -2,   0},
+      { 0, 0, 0, 1, 0, -1,  2,  0, 0, 0, 0, 0, 0,    0,   3,    1,   0},
+      { 0, 0, 0, 0, 0,  0,  0,  0, 4, 0, 0, 0, 2,   -9,   3,    1,   4},
+      { 0, 0, 0, 0, 0,  0, -3,  5, 0, 0, 0, 0, 2,   17,   0,    0,  -7},
+      { 0, 0, 0, 0, 0,  0, -3,  5, 0, 0, 0, 0, 1,    0,  -3,   -2,  -1},
+      { 0, 0, 0, 0, 0,  0,  3, -5, 0, 0, 0, 0, 0,  -20,  34,    0,   0},
+
+   /* 291-300 */
+      { 0, 0, 0, 0, 0,  1, -2,  0, 0, 0, 0, 0, 1,  -10,   0,    1,   5},
+      { 0, 1,-1, 1, 0,  1, -3,  0, 0, 0, 0, 0, 0,   -4,   0,    0,   2},
+      { 0, 0, 0, 0, 0,  1, -2,  0, 0, 0, 0, 0, 0,   22, -87,    0,   0},
+      { 0, 0, 0, 0, 0, -1,  2,  0, 0, 0, 0, 0, 1,   -4,   0,    0,   2},
+      { 0, 0, 0, 0, 0, -1,  2,  0, 0, 0, 0, 0, 2,   -3,  -6,   -2,   1},
+      { 0, 0, 0, 0, 0, -7, 11,  0, 0, 0, 0, 0, 2,  -16,  -3,   -1,   7},
+      { 0, 0, 0, 0, 0, -7, 11,  0, 0, 0, 0, 0, 1,    0,  -3,   -2,   0},
+      { 0,-2, 2, 0, 0,  4, -4,  0, 0, 0, 0, 0, 0,    4,   0,    0,   0},
+      { 0, 0, 0, 0, 0,  0,  2, -3, 0, 0, 0, 0, 0,  -68,  39,    0,   0},
+      { 0, 2,-2, 1, 0, -4,  4,  0, 0, 0, 0, 0, 0,   27,   0,    0, -14},
+
+   /* 301-310 */
+      { 0,-1, 1, 0, 0,  4, -5,  0, 0, 0, 0, 0, 0,    0,  -4,    0,   0},
+      { 0, 0, 0, 0, 0,  0,  1, -1, 0, 0, 0, 0, 0,  -25,   0,    0,   0},
+      { 0, 0, 0, 0, 0, -4,  7,  0, 0, 0, 0, 0, 1,  -12,  -3,   -2,   6},
+      { 0, 1,-1, 1, 0, -4,  6,  0, 0, 0, 0, 0, 0,    3,   0,    0,  -1},
+      { 0, 0, 0, 0, 0, -4,  7,  0, 0, 0, 0, 0, 2,    3,  66,   29,  -1},
+      { 0, 0, 0, 0, 0, -4,  6,  0, 0, 0, 0, 0, 2,  490,   0,    0,-213},
+      { 0, 0, 0, 0, 0, -4,  6,  0, 0, 0, 0, 0, 1,  -22,  93,   49,  12},
+      { 0, 1,-1, 1, 0, -4,  5,  0, 0, 0, 0, 0, 0,   -7,  28,   15,   4},
+      { 0, 0, 0, 0, 0, -4,  6,  0, 0, 0, 0, 0, 1,   -3,  13,    7,   2},
+      { 0, 0, 0, 0, 0,  4, -6,  0, 0, 0, 0, 0, 0,  -46,  14,    0,   0},
+
+   /* 311-320 */
+      {-2, 0, 2, 0, 0,  2, -2,  0, 0, 0, 0, 0, 0,   -5,   0,    0,   0},
+      { 0, 0, 0, 0, 0,  0,  0,  1, 0, 0, 0, 0, 0,    2,   1,    0,   0},
+      { 0,-1, 1, 0, 0,  1,  0,  0, 0, 0, 0, 0, 0,    0,  -3,    0,   0},
+      { 0, 0, 0, 1, 0,  1, -1,  0, 0, 0, 0, 0, 0,  -28,   0,    0,  15},
+      { 0, 0, 0, 0, 0,  0, -1,  0, 5, 0, 0, 0, 2,    5,   0,    0,  -2},
+      { 0, 0, 0, 0, 0,  0,  1, -3, 0, 0, 0, 0, 0,    0,   3,    0,   0},
+      { 0, 0, 0, 0, 0,  0, -1,  3, 0, 0, 0, 0, 2,  -11,   0,    0,   5},
+      { 0, 0, 0, 0, 0,  0, -7, 12, 0, 0, 0, 0, 2,    0,   3,    1,   0},
+      { 0, 0, 0, 0, 0, -1,  1,  0, 0, 0, 0, 0, 2,   -3,   0,    0,   1},
+      { 0, 0, 0, 0, 0, -1,  1,  0, 0, 0, 0, 0, 1,   25, 106,   57, -13},
+
+   /* 321-330 */
+      { 0, 1,-1, 1, 0, -1,  0,  0, 0, 0, 0, 0, 0,    5,  21,   11,  -3},
+      { 0, 0, 0, 0, 0,  1, -1,  0, 0, 0, 0, 0, 0, 1485,   0,    0,   0},
+      { 0, 0, 0, 0, 0,  1, -1,  0, 0, 0, 0, 0, 1,   -7, -32,  -17,   4},
+      { 0, 1,-1, 1, 0,  1, -2,  0, 0, 0, 0, 0, 0,    0,   5,    3,   0},
+      { 0, 0, 0, 0, 0,  0, -2,  5, 0, 0, 0, 0, 2,   -6,  -3,   -2,   3},
+      { 0, 0, 0, 0, 0,  0, -1,  0, 4, 0, 0, 0, 2,   30,  -6,   -2, -13},
+      { 0, 0, 0, 0, 0,  0,  1,  0,-4, 0, 0, 0, 0,   -4,   4,    0,   0},
+      { 0, 0, 0, 1, 0, -1,  1,  0, 0, 0, 0, 0, 0,  -19,   0,    0,  10},
+      { 0, 0, 0, 0, 0,  0, -6, 10, 0, 0, 0, 0, 2,    0,   4,    2,  -1},
+      { 0, 0, 0, 0, 0,  0, -6, 10, 0, 0, 0, 0, 0,    0,   3,    0,   0},
+
+   /* 331-340 */
+      { 0, 2,-2, 1, 0,  0, -3,  0, 3, 0, 0, 0, 0,    4,   0,    0,  -2},
+      { 0, 0, 0, 0, 0,  0, -3,  7, 0, 0, 0, 0, 2,    0,  -3,   -1,   0},
+      {-2, 0, 2, 0, 0,  4, -4,  0, 0, 0, 0, 0, 0,   -3,   0,    0,   0},
+      { 0, 0, 0, 0, 0,  0, -5,  8, 0, 0, 0, 0, 2,    5,   3,    1,  -2},
+      { 0, 0, 0, 0, 0,  0,  5, -8, 0, 0, 0, 0, 0,    0,  11,    0,   0},
+      { 0, 0, 0, 0, 0,  0, -1,  0, 3, 0, 0, 0, 2,  118,   0,    0, -52},
+      { 0, 0, 0, 0, 0,  0, -1,  0, 3, 0, 0, 0, 1,    0,  -5,   -3,   0},
+      { 0, 0, 0, 0, 0,  0,  1,  0,-3, 0, 0, 0, 0,  -28,  36,    0,   0},
+      { 0, 0, 0, 0, 0,  2, -4,  0, 0, 0, 0, 0, 0,    5,  -5,    0,   0},
+      { 0, 0, 0, 0, 0, -2,  4,  0, 0, 0, 0, 0, 1,   14, -59,  -31,  -8},
+
+   /* 341-350 */
+      { 0, 1,-1, 1, 0, -2,  3,  0, 0, 0, 0, 0, 0,    0,   9,    5,   1},
+      { 0, 0, 0, 0, 0, -2,  4,  0, 0, 0, 0, 0, 2, -458,   0,    0, 198},
+      { 0, 0, 0, 0, 0, -6,  9,  0, 0, 0, 0, 0, 2,    0, -45,  -20,   0},
+      { 0, 0, 0, 0, 0, -6,  9,  0, 0, 0, 0, 0, 1,    9,   0,    0,  -5},
+      { 0, 0, 0, 0, 0,  6, -9,  0, 0, 0, 0, 0, 0,    0,  -3,    0,   0},
+      { 0, 0, 0, 1, 0,  0,  1,  0,-2, 0, 0, 0, 0,    0,  -4,   -2,  -1},
+      { 0, 2,-2, 1, 0, -2,  2,  0, 0, 0, 0, 0, 0,   11,   0,    0,  -6},
+      { 0, 0, 0, 0, 0,  0, -4,  6, 0, 0, 0, 0, 2,    6,   0,    0,  -2},
+      { 0, 0, 0, 0, 0,  0,  4, -6, 0, 0, 0, 0, 0,  -16,  23,    0,   0},
+      { 0, 0, 0, 1, 0,  3, -4,  0, 0, 0, 0, 0, 0,    0,  -4,   -2,   0},
+
+   /* 351-360 */
+      { 0, 0, 0, 0, 0,  0, -1,  0, 2, 0, 0, 0, 2,   -5,   0,    0,   2},
+      { 0, 0, 0, 0, 0,  0,  1,  0,-2, 0, 0, 0, 0, -166, 269,    0,   0},
+      { 0, 0, 0, 1, 0,  0,  1,  0,-1, 0, 0, 0, 0,   15,   0,    0,  -8},
+      { 0, 0, 0, 0, 0, -5,  9,  0, 0, 0, 0, 0, 2,   10,   0,    0,  -4},
+      { 0, 0, 0, 0, 0,  0,  3, -4, 0, 0, 0, 0, 0,  -78,  45,    0,   0},
+      { 0, 0, 0, 0, 0, -3,  4,  0, 0, 0, 0, 0, 2,    0,  -5,   -2,   0},
+      { 0, 0, 0, 0, 0, -3,  4,  0, 0, 0, 0, 0, 1,    7,   0,    0,  -4},
+      { 0, 0, 0, 0, 0,  3, -4,  0, 0, 0, 0, 0, 0,   -5, 328,    0,   0},
+      { 0, 0, 0, 0, 0,  3, -4,  0, 0, 0, 0, 0, 1,    3,   0,    0,  -2},
+      { 0, 0, 0, 1, 0,  0,  2, -2, 0, 0, 0, 0, 0,    5,   0,    0,  -2},
+
+   /* 361-370 */
+      { 0, 0, 0, 1, 0,  0, -1,  0, 2, 0, 0, 0, 0,    0,   3,    1,   0},
+      { 0, 0, 0, 0, 0,  0,  1,  0, 0,-3, 0, 0, 0,   -3,   0,    0,   0},
+      { 0, 0, 0, 0, 0,  0,  1,  0, 1,-5, 0, 0, 0,   -3,   0,    0,   0},
+      { 0, 0, 0, 0, 0,  0, -1,  0, 1, 0, 0, 0, 1,    0,  -4,   -2,   0},
+      { 0, 0, 0, 0, 0,  0,  1,  0,-1, 0, 0, 0, 0,-1223, -26,    0,   0},
+      { 0, 0, 0, 0, 0,  0,  1,  0,-1, 0, 0, 0, 1,    0,   7,    3,   0},
+      { 0, 0, 0, 0, 0,  0,  1,  0,-3, 5, 0, 0, 0,    3,   0,    0,   0},
+      { 0, 0, 0, 1, 0, -3,  4,  0, 0, 0, 0, 0, 0,    0,   3,    2,   0},
+      { 0, 0, 0, 0, 0,  0,  1,  0, 0,-2, 0, 0, 0,   -6,  20,    0,   0},
+      { 0, 0, 0, 0, 0,  0,  2, -2, 0, 0, 0, 0, 0, -368,   0,    0,   0},
+
+   /* 371-380 */
+      { 0, 0, 0, 0, 0,  0,  1,  0, 0,-1, 0, 0, 0,  -75,   0,    0,   0},
+      { 0, 0, 0, 1, 0,  0, -1,  0, 1, 0, 0, 0, 0,   11,   0,    0,  -6},
+      { 0, 0, 0, 1, 0,  0, -2,  2, 0, 0, 0, 0, 0,    3,   0,    0,  -2},
+      { 0, 0, 0, 0, 0, -8, 14,  0, 0, 0, 0, 0, 2,   -3,   0,    0,   1},
+      { 0, 0, 0, 0, 0,  0,  1,  0, 2,-5, 0, 0, 0,  -13, -30,    0,   0},
+      { 0, 0, 0, 0, 0,  0,  5, -8, 3, 0, 0, 0, 0,   21,   3,    0,   0},
+      { 0, 0, 0, 0, 0,  0,  5, -8, 3, 0, 0, 0, 2,   -3,   0,    0,   1},
+      { 0, 0, 0, 0, 0,  0, -1,  0, 0, 0, 0, 0, 1,   -4,   0,    0,   2},
+      { 0, 0, 0, 0, 0,  0,  1,  0, 0, 0, 0, 0, 0,    8, -27,    0,   0},
+      { 0, 0, 0, 0, 0,  0,  3, -8, 3, 0, 0, 0, 0,  -19, -11,    0,   0},
+
+   /* 381-390 */
+      { 0, 0, 0, 0, 0,  0, -3,  8,-3, 0, 0, 0, 2,   -4,   0,    0,   2},
+      { 0, 0, 0, 0, 0,  0,  1,  0,-2, 5, 0, 0, 2,    0,   5,    2,   0},
+      { 0, 0, 0, 0, 0, -8, 12,  0, 0, 0, 0, 0, 2,   -6,   0,    0,   2},
+      { 0, 0, 0, 0, 0, -8, 12,  0, 0, 0, 0, 0, 0,   -8,   0,    0,   0},
+      { 0, 0, 0, 0, 0,  0,  1,  0, 1,-2, 0, 0, 0,   -1,   0,    0,   0},
+      { 0, 0, 0, 0, 0,  0,  1,  0, 0, 1, 0, 0, 2,  -14,   0,    0,   6},
+      { 0, 0, 0, 0, 0,  0,  0,  2, 0, 0, 0, 0, 0,    6,   0,    0,   0},
+      { 0, 0, 0, 0, 0,  0,  0,  2, 0, 0, 0, 0, 2,  -74,   0,    0,  32},
+      { 0, 0, 0, 0, 0,  0,  1,  0, 0, 2, 0, 0, 2,    0,  -3,   -1,   0},
+      { 0, 2,-2, 1, 0, -5,  5,  0, 0, 0, 0, 0, 0,    4,   0,    0,  -2},
+
+   /* 391-400 */
+      { 0, 0, 0, 0, 0,  0,  1,  0, 1, 0, 0, 0, 0,    8,  11,    0,   0},
+      { 0, 0, 0, 0, 0,  0,  1,  0, 1, 0, 0, 0, 1,    0,   3,    2,   0},
+      { 0, 0, 0, 0, 0,  0,  1,  0, 1, 0, 0, 0, 2, -262,   0,    0, 114},
+      { 0, 0, 0, 0, 0,  3, -6,  0, 0, 0, 0, 0, 0,    0,  -4,    0,   0},
+      { 0, 0, 0, 0, 0, -3,  6,  0, 0, 0, 0, 0, 1,   -7,   0,    0,   4},
+      { 0, 0, 0, 0, 0, -3,  6,  0, 0, 0, 0, 0, 2,    0, -27,  -12,   0},
+      { 0, 0, 0, 0, 0,  0, -1,  4, 0, 0, 0, 0, 2,  -19,  -8,   -4,   8},
+      { 0, 0, 0, 0, 0, -5,  7,  0, 0, 0, 0, 0, 2,  202,   0,    0, -87},
+      { 0, 0, 0, 0, 0, -5,  7,  0, 0, 0, 0, 0, 1,   -8,  35,   19,   5},
+      { 0, 1,-1, 1, 0, -5,  6,  0, 0, 0, 0, 0, 0,    0,   4,    2,   0},
+
+   /* 401-410 */
+      { 0, 0, 0, 0, 0,  5, -7,  0, 0, 0, 0, 0, 0,   16,  -5,    0,   0},
+      { 0, 2,-2, 1, 0,  0, -1,  0, 1, 0, 0, 0, 0,    5,   0,    0,  -3},
+      { 0, 0, 0, 0, 0,  0, -1,  0, 1, 0, 0, 0, 0,    0,  -3,    0,   0},
+      { 0, 0, 0, 0,-1,  0,  3,  0, 0, 0, 0, 0, 2,    1,   0,    0,   0},
+      { 0, 0, 0, 0, 0,  0,  1,  0, 2, 0, 0, 0, 2,  -35, -48,  -21,  15},
+      { 0, 0, 0, 0, 0,  0, -2,  6, 0, 0, 0, 0, 2,   -3,  -5,   -2,   1},
+      { 0, 0, 0, 1, 0,  2, -2,  0, 0, 0, 0, 0, 0,    6,   0,    0,  -3},
+      { 0, 0, 0, 0, 0,  0, -6,  9, 0, 0, 0, 0, 2,    3,   0,    0,  -1},
+      { 0, 0, 0, 0, 0,  0,  6, -9, 0, 0, 0, 0, 0,    0,  -5,    0,   0},
+      { 0, 0, 0, 0, 0, -2,  2,  0, 0, 0, 0, 0, 1,   12,  55,   29,  -6},
+
+   /* 411-420 */
+      { 0, 1,-1, 1, 0, -2,  1,  0, 0, 0, 0, 0, 0,    0,   5,    3,   0},
+      { 0, 0, 0, 0, 0,  2, -2,  0, 0, 0, 0, 0, 0, -598,   0,    0,   0},
+      { 0, 0, 0, 0, 0,  2, -2,  0, 0, 0, 0, 0, 1,   -3, -13,   -7,   1},
+      { 0, 0, 0, 0, 0,  0,  1,  0, 3, 0, 0, 0, 2,   -5,  -7,   -3,   2},
+      { 0, 0, 0, 0, 0,  0, -5,  7, 0, 0, 0, 0, 2,    3,   0,    0,  -1},
+      { 0, 0, 0, 0, 0,  0,  5, -7, 0, 0, 0, 0, 0,    5,  -7,    0,   0},
+      { 0, 0, 0, 1, 0, -2,  2,  0, 0, 0, 0, 0, 0,    4,   0,    0,  -2},
+      { 0, 0, 0, 0, 0,  0,  4, -5, 0, 0, 0, 0, 0,   16,  -6,    0,   0},
+      { 0, 0, 0, 0, 0,  1, -3,  0, 0, 0, 0, 0, 0,    8,  -3,    0,   0},
+      { 0, 0, 0, 0, 0, -1,  3,  0, 0, 0, 0, 0, 1,    8, -31,  -16,  -4},
+
+   /* 421-430 */
+      { 0, 1,-1, 1, 0, -1,  2,  0, 0, 0, 0, 0, 0,    0,   3,    1,   0},
+      { 0, 0, 0, 0, 0, -1,  3,  0, 0, 0, 0, 0, 2,  113,   0,    0, -49},
+      { 0, 0, 0, 0, 0, -7, 10,  0, 0, 0, 0, 0, 2,    0, -24,  -10,   0},
+      { 0, 0, 0, 0, 0, -7, 10,  0, 0, 0, 0, 0, 1,    4,   0,    0,  -2},
+      { 0, 0, 0, 0, 0,  0,  3, -3, 0, 0, 0, 0, 0,   27,   0,    0,   0},
+      { 0, 0, 0, 0, 0, -4,  8,  0, 0, 0, 0, 0, 2,   -3,   0,    0,   1},
+      { 0, 0, 0, 0, 0, -4,  5,  0, 0, 0, 0, 0, 2,    0,  -4,   -2,   0},
+      { 0, 0, 0, 0, 0, -4,  5,  0, 0, 0, 0, 0, 1,    5,   0,    0,  -2},
+      { 0, 0, 0, 0, 0,  4, -5,  0, 0, 0, 0, 0, 0,    0,  -3,    0,   0},
+      { 0, 0, 0, 0, 0,  0,  1,  1, 0, 0, 0, 0, 2,  -13,   0,    0,   6},
+
+   /* 431-440 */
+      { 0, 0, 0, 0, 0,  0, -2,  0, 5, 0, 0, 0, 2,    5,   0,    0,  -2},
+      { 0, 0, 0, 0, 0,  0,  0,  3, 0, 0, 0, 0, 2,  -18, -10,   -4,   8},
+      { 0, 0, 0, 0, 0,  1,  0,  0, 0, 0, 0, 0, 0,   -4, -28,    0,   0},
+      { 0, 0, 0, 0, 0,  1,  0,  0, 0, 0, 0, 0, 2,   -5,   6,    3,   2},
+      { 0, 0, 0, 0, 0, -9, 13,  0, 0, 0, 0, 0, 2,   -3,   0,    0,   1},
+      { 0, 0, 0, 0, 0,  0, -1,  5, 0, 0, 0, 0, 2,   -5,  -9,   -4,   2},
+      { 0, 0, 0, 0, 0,  0, -2,  0, 4, 0, 0, 0, 2,   17,   0,    0,  -7},
+      { 0, 0, 0, 0, 0,  0,  2,  0,-4, 0, 0, 0, 0,   11,   4,    0,   0},
+      { 0, 0, 0, 0, 0,  0, -2,  7, 0, 0, 0, 0, 2,    0,  -6,   -2,   0},
+      { 0, 0, 0, 0, 0,  0,  2,  0,-3, 0, 0, 0, 0,   83,  15,    0,   0},
+
+   /* 441-450 */
+      { 0, 0, 0, 0, 0, -2,  5,  0, 0, 0, 0, 0, 1,   -4,   0,    0,   2},
+      { 0, 0, 0, 0, 0, -2,  5,  0, 0, 0, 0, 0, 2,    0,-114,  -49,   0},
+      { 0, 0, 0, 0, 0, -6,  8,  0, 0, 0, 0, 0, 2,  117,   0,    0, -51},
+      { 0, 0, 0, 0, 0, -6,  8,  0, 0, 0, 0, 0, 1,   -5,  19,   10,   2},
+      { 0, 0, 0, 0, 0,  6, -8,  0, 0, 0, 0, 0, 0,   -3,   0,    0,   0},
+      { 0, 0, 0, 1, 0,  0,  2,  0,-2, 0, 0, 0, 0,   -3,   0,    0,   2},
+      { 0, 0, 0, 0, 0,  0, -3,  9, 0, 0, 0, 0, 2,    0,  -3,   -1,   0},
+      { 0, 0, 0, 0, 0,  0,  5, -6, 0, 0, 0, 0, 0,    3,   0,    0,   0},
+      { 0, 0, 0, 0, 0,  0,  5, -6, 0, 0, 0, 0, 2,    0,  -6,   -2,   0},
+      { 0, 0, 0, 0, 0,  0,  2,  0,-2, 0, 0, 0, 0,  393,   3,    0,   0},
+
+   /* 451-460 */
+      { 0, 0, 0, 0, 0,  0,  2,  0,-2, 0, 0, 0, 1,   -4,  21,   11,   2},
+      { 0, 0, 0, 0, 0,  0,  2,  0,-2, 0, 0, 0, 2,   -6,   0,   -1,   3},
+      { 0, 0, 0, 0, 0, -5, 10,  0, 0, 0, 0, 0, 2,   -3,   8,    4,   1},
+      { 0, 0, 0, 0, 0,  0,  4, -4, 0, 0, 0, 0, 0,    8,   0,    0,   0},
+      { 0, 0, 0, 0, 0,  0,  4, -4, 0, 0, 0, 0, 2,   18, -29,  -13,  -8},
+      { 0, 0, 0, 0, 0, -3,  3,  0, 0, 0, 0, 0, 1,    8,  34,   18,  -4},
+      { 0, 0, 0, 0, 0,  3, -3,  0, 0, 0, 0, 0, 0,   89,   0,    0,   0},
+      { 0, 0, 0, 0, 0,  3, -3,  0, 0, 0, 0, 0, 1,    3,  12,    6,  -1},
+      { 0, 0, 0, 0, 0,  3, -3,  0, 0, 0, 0, 0, 2,   54, -15,   -7, -24},
+      { 0, 0, 0, 0, 0,  0,  2,  0, 0,-3, 0, 0, 0,    0,   3,    0,   0},
+
+   /* 461-470 */
+      { 0, 0, 0, 0, 0,  0, -5, 13, 0, 0, 0, 0, 2,    3,   0,    0,  -1},
+      { 0, 0, 0, 0, 0,  0,  2,  0,-1, 0, 0, 0, 0,    0,  35,    0,   0},
+      { 0, 0, 0, 0, 0,  0,  2,  0,-1, 0, 0, 0, 2, -154, -30,  -13,  67},
+      { 0, 0, 0, 0, 0,  0,  2,  0, 0,-2, 0, 0, 0,   15,   0,    0,   0},
+      { 0, 0, 0, 0, 0,  0,  2,  0, 0,-2, 0, 0, 1,    0,   4,    2,   0},
+      { 0, 0, 0, 0, 0,  0,  3, -2, 0, 0, 0, 0, 0,    0,   9,    0,   0},
+      { 0, 0, 0, 0, 0,  0,  3, -2, 0, 0, 0, 0, 2,   80, -71,  -31, -35},
+      { 0, 0, 0, 0, 0,  0,  2,  0, 0,-1, 0, 0, 2,    0, -20,   -9,   0},
+      { 0, 0, 0, 0, 0,  0, -6, 15, 0, 0, 0, 0, 2,   11,   5,    2,  -5},
+      { 0, 0, 0, 0, 0, -8, 15,  0, 0, 0, 0, 0, 2,   61, -96,  -42, -27},
+
+   /* 471-480 */
+      { 0, 0, 0, 0, 0, -3,  9, -4, 0, 0, 0, 0, 2,   14,   9,    4,  -6},
+      { 0, 0, 0, 0, 0,  0,  2,  0, 2,-5, 0, 0, 2,  -11,  -6,   -3,   5},
+      { 0, 0, 0, 0, 0,  0, -2,  8,-1,-5, 0, 0, 2,    0,  -3,   -1,   0},
+      { 0, 0, 0, 0, 0,  0,  6, -8, 3, 0, 0, 0, 2,  123,-415, -180, -53},
+      { 0, 0, 0, 0, 0,  0,  2,  0, 0, 0, 0, 0, 0,    0,   0,    0, -35},
+      { 0, 0, 0, 0, 0,  0,  2,  0, 0, 0, 0, 0, 0,   -5,   0,    0,   0},
+      { 0, 0, 0, 0, 0,  0,  2,  0, 0, 0, 0, 0, 1,    7, -32,  -17,  -4},
+      { 0, 1,-1, 1, 0,  0,  1,  0, 0, 0, 0, 0, 0,    0,  -9,   -5,   0},
+      { 0, 0, 0, 0, 0,  0,  2,  0, 0, 0, 0, 0, 1,    0,  -4,    2,   0},
+      { 0, 0, 0, 0, 0,  0,  2,  0, 0, 0, 0, 0, 2,  -89,   0,    0,  38},
+
+   /* 481-490 */
+      { 0, 0, 0, 0, 0,  0, -6, 16,-4,-5, 0, 0, 2,    0, -86,  -19,  -6},
+      { 0, 0, 0, 0, 0,  0, -2,  8,-3, 0, 0, 0, 2,    0,   0,  -19,   6},
+      { 0, 0, 0, 0, 0,  0, -2,  8,-3, 0, 0, 0, 2, -123,-416, -180,  53},
+      { 0, 0, 0, 0, 0,  0,  6, -8, 1, 5, 0, 0, 2,    0,  -3,   -1,   0},
+      { 0, 0, 0, 0, 0,  0,  2,  0,-2, 5, 0, 0, 2,   12,  -6,   -3,  -5},
+      { 0, 0, 0, 0, 0,  3, -5,  4, 0, 0, 0, 0, 2,  -13,   9,    4,   6},
+      { 0, 0, 0, 0, 0, -8, 11,  0, 0, 0, 0, 0, 2,    0, -15,   -7,   0},
+      { 0, 0, 0, 0, 0, -8, 11,  0, 0, 0, 0, 0, 1,    3,   0,    0,  -1},
+      { 0, 0, 0, 0, 0, -8, 11,  0, 0, 0, 0, 0, 2,  -62, -97,  -42,  27},
+      { 0, 0, 0, 0, 0,  0, 11,  0, 0, 0, 0, 0, 2,  -11,   5,    2,   5},
+
+   /* 491-500 */
+      { 0, 0, 0, 0, 0,  0,  2,  0, 0, 1, 0, 0, 2,    0, -19,   -8,   0},
+      { 0, 0, 0, 0, 0,  3, -3,  0, 2, 0, 0, 0, 2,   -3,   0,    0,   1},
+      { 0, 2,-2, 1, 0,  0,  4, -8, 3, 0, 0, 0, 0,    0,   4,    2,   0},
+      { 0, 1,-1, 0, 0,  0,  1,  0, 0, 0, 0, 0, 0,    0,   3,    0,   0},
+      { 0, 2,-2, 1, 0,  0, -4,  8,-3, 0, 0, 0, 0,    0,   4,    2,   0},
+      { 0, 0, 0, 0, 0,  0,  1,  2, 0, 0, 0, 0, 2,  -85, -70,  -31,  37},
+      { 0, 0, 0, 0, 0,  0,  2,  0, 1, 0, 0, 0, 2,  163, -12,   -5, -72},
+      { 0, 0, 0, 0, 0, -3,  7,  0, 0, 0, 0, 0, 2,  -63, -16,   -7,  28},
+      { 0, 0, 0, 0, 0,  0,  0,  4, 0, 0, 0, 0, 2,  -21, -32,  -14,   9},
+      { 0, 0, 0, 0, 0, -5,  6,  0, 0, 0, 0, 0, 2,    0,  -3,   -1,   0},
+
+   /* 501-510 */
+      { 0, 0, 0, 0, 0, -5,  6,  0, 0, 0, 0, 0, 1,    3,   0,    0,  -2},
+      { 0, 0, 0, 0, 0,  5, -6,  0, 0, 0, 0, 0, 0,    0,   8,    0,   0},
+      { 0, 0, 0, 0, 0,  5, -6,  0, 0, 0, 0, 0, 2,    3,  10,    4,  -1},
+      { 0, 0, 0, 0, 0,  0,  2,  0, 2, 0, 0, 0, 2,    3,   0,    0,  -1},
+      { 0, 0, 0, 0, 0,  0, -1,  6, 0, 0, 0, 0, 2,    0,  -7,   -3,   0},
+      { 0, 0, 0, 0, 0,  0,  7, -9, 0, 0, 0, 0, 2,    0,  -4,   -2,   0},
+      { 0, 0, 0, 0, 0,  2, -1,  0, 0, 0, 0, 0, 0,    6,  19,    0,   0},
+      { 0, 0, 0, 0, 0,  2, -1,  0, 0, 0, 0, 0, 2,    5,-173,  -75,  -2},
+      { 0, 0, 0, 0, 0,  0,  6, -7, 0, 0, 0, 0, 2,    0,  -7,   -3,   0},
+      { 0, 0, 0, 0, 0,  0,  5, -5, 0, 0, 0, 0, 2,    7, -12,   -5,  -3},
+
+   /* 511-520 */
+      { 0, 0, 0, 0, 0, -1,  4,  0, 0, 0, 0, 0, 1,   -3,   0,    0,   2},
+      { 0, 0, 0, 0, 0, -1,  4,  0, 0, 0, 0, 0, 2,    3,  -4,   -2,  -1},
+      { 0, 0, 0, 0, 0, -7,  9,  0, 0, 0, 0, 0, 2,   74,   0,    0, -32},
+      { 0, 0, 0, 0, 0, -7,  9,  0, 0, 0, 0, 0, 1,   -3,  12,    6,   2},
+      { 0, 0, 0, 0, 0,  0,  4, -3, 0, 0, 0, 0, 2,   26, -14,   -6, -11},
+      { 0, 0, 0, 0, 0,  0,  3, -1, 0, 0, 0, 0, 2,   19,   0,    0,  -8},
+      { 0, 0, 0, 0, 0, -4,  4,  0, 0, 0, 0, 0, 1,    6,  24,   13,  -3},
+      { 0, 0, 0, 0, 0,  4, -4,  0, 0, 0, 0, 0, 0,   83,   0,    0,   0},
+      { 0, 0, 0, 0, 0,  4, -4,  0, 0, 0, 0, 0, 1,    0, -10,   -5,   0},
+      { 0, 0, 0, 0, 0,  4, -4,  0, 0, 0, 0, 0, 2,   11,  -3,   -1,  -5},
+
+   /* 521-530 */
+      { 0, 0, 0, 0, 0,  0,  2,  1, 0, 0, 0, 0, 2,    3,   0,    1,  -1},
+      { 0, 0, 0, 0, 0,  0, -3,  0, 5, 0, 0, 0, 2,    3,   0,    0,  -1},
+      { 0, 0, 0, 0, 0,  1,  1,  0, 0, 0, 0, 0, 0,   -4,   0,    0,   0},
+      { 0, 0, 0, 0, 0,  1,  1,  0, 0, 0, 0, 0, 1,    5, -23,  -12,  -3},
+      { 0, 0, 0, 0, 0,  1,  1,  0, 0, 0, 0, 0, 2, -339,   0,    0, 147},
+      { 0, 0, 0, 0, 0, -9, 12,  0, 0, 0, 0, 0, 2,    0, -10,   -5,   0},
+      { 0, 0, 0, 0, 0,  0,  3,  0,-4, 0, 0, 0, 0,    5,   0,    0,   0},
+      { 0, 2,-2, 1, 0,  1, -1,  0, 0, 0, 0, 0, 0,    3,   0,    0,  -1},
+      { 0, 0, 0, 0, 0,  0,  7, -8, 0, 0, 0, 0, 2,    0,  -4,   -2,   0},
+      { 0, 0, 0, 0, 0,  0,  3,  0,-3, 0, 0, 0, 0,   18,  -3,    0,   0},
+
+   /* 531-540 */
+      { 0, 0, 0, 0, 0,  0,  3,  0,-3, 0, 0, 0, 2,    9, -11,   -5,  -4},
+      { 0, 0, 0, 0, 0, -2,  6,  0, 0, 0, 0, 0, 2,   -8,   0,    0,   4},
+      { 0, 0, 0, 0, 0, -6,  7,  0, 0, 0, 0, 0, 1,    3,   0,    0,  -1},
+      { 0, 0, 0, 0, 0,  6, -7,  0, 0, 0, 0, 0, 0,    0,   9,    0,   0},
+      { 0, 0, 0, 0, 0,  0,  6, -6, 0, 0, 0, 0, 2,    6,  -9,   -4,  -2},
+      { 0, 0, 0, 0, 0,  0,  3,  0,-2, 0, 0, 0, 0,   -4, -12,    0,   0},
+      { 0, 0, 0, 0, 0,  0,  3,  0,-2, 0, 0, 0, 2,   67, -91,  -39, -29},
+      { 0, 0, 0, 0, 0,  0,  5, -4, 0, 0, 0, 0, 2,   30, -18,   -8, -13},
+      { 0, 0, 0, 0, 0,  3, -2,  0, 0, 0, 0, 0, 0,    0,   0,    0,   0},
+      { 0, 0, 0, 0, 0,  3, -2,  0, 0, 0, 0, 0, 2,    0,-114,  -50,   0},
+
+   /* 541-550 */
+      { 0, 0, 0, 0, 0,  0,  3,  0,-1, 0, 0, 0, 2,    0,   0,    0,  23},
+      { 0, 0, 0, 0, 0,  0,  3,  0,-1, 0, 0, 0, 2,  517,  16,    7,-224},
+      { 0, 0, 0, 0, 0,  0,  3,  0, 0,-2, 0, 0, 2,    0,  -7,   -3,   0},
+      { 0, 0, 0, 0, 0,  0,  4, -2, 0, 0, 0, 0, 2,  143,  -3,   -1, -62},
+      { 0, 0, 0, 0, 0,  0,  3,  0, 0,-1, 0, 0, 2,   29,   0,    0, -13},
+      { 0, 2,-2, 1, 0,  0,  1,  0,-1, 0, 0, 0, 0,   -4,   0,    0,   2},
+      { 0, 0, 0, 0, 0, -8, 16,  0, 0, 0, 0, 0, 2,   -6,   0,    0,   3},
+      { 0, 0, 0, 0, 0,  0,  3,  0, 2,-5, 0, 0, 2,    5,  12,    5,  -2},
+      { 0, 0, 0, 0, 0,  0,  7, -8, 3, 0, 0, 0, 2,  -25,   0,    0,  11},
+      { 0, 0, 0, 0, 0,  0, -5, 16,-4,-5, 0, 0, 2,   -3,   0,    0,   1},
+
+   /* 551-560 */
+      { 0, 0, 0, 0, 0,  0,  3,  0, 0, 0, 0, 0, 2,    0,   4,    2,   0},
+      { 0, 0, 0, 0, 0,  0, -1,  8,-3, 0, 0, 0, 2,  -22,  12,    5,  10},
+      { 0, 0, 0, 0, 0, -8, 10,  0, 0, 0, 0, 0, 2,   50,   0,    0, -22},
+      { 0, 0, 0, 0, 0, -8, 10,  0, 0, 0, 0, 0, 1,    0,   7,    4,   0},
+      { 0, 0, 0, 0, 0, -8, 10,  0, 0, 0, 0, 0, 2,    0,   3,    1,   0},
+      { 0, 0, 0, 0, 0,  0,  2,  2, 0, 0, 0, 0, 2,   -4,   4,    2,   2},
+      { 0, 0, 0, 0, 0,  0,  3,  0, 1, 0, 0, 0, 2,   -5, -11,   -5,   2},
+      { 0, 0, 0, 0, 0, -3,  8,  0, 0, 0, 0, 0, 2,    0,   4,    2,   0},
+      { 0, 0, 0, 0, 0, -5,  5,  0, 0, 0, 0, 0, 1,    4,  17,    9,  -2},
+      { 0, 0, 0, 0, 0,  5, -5,  0, 0, 0, 0, 0, 0,   59,   0,    0,   0},
+
+   /* 561-570 */
+      { 0, 0, 0, 0, 0,  5, -5,  0, 0, 0, 0, 0, 1,    0,  -4,   -2,   0},
+      { 0, 0, 0, 0, 0,  5, -5,  0, 0, 0, 0, 0, 2,   -8,   0,    0,   4},
+      { 0, 0, 0, 0, 0,  2,  0,  0, 0, 0, 0, 0, 0,   -3,   0,    0,   0},
+      { 0, 0, 0, 0, 0,  2,  0,  0, 0, 0, 0, 0, 1,    4, -15,   -8,  -2},
+      { 0, 0, 0, 0, 0,  2,  0,  0, 0, 0, 0, 0, 2,  370,  -8,    0,-160},
+      { 0, 0, 0, 0, 0,  0,  7, -7, 0, 0, 0, 0, 2,    0,   0,   -3,   0},
+      { 0, 0, 0, 0, 0,  0,  7, -7, 0, 0, 0, 0, 2,    0,   3,    1,   0},
+      { 0, 0, 0, 0, 0,  0,  6, -5, 0, 0, 0, 0, 2,   -6,   3,    1,   3},
+      { 0, 0, 0, 0, 0,  7, -8,  0, 0, 0, 0, 0, 0,    0,   6,    0,   0},
+      { 0, 0, 0, 0, 0,  0,  5, -3, 0, 0, 0, 0, 2,  -10,   0,    0,   4},
+
+   /* 571-580 */
+      { 0, 0, 0, 0, 0,  4, -3,  0, 0, 0, 0, 0, 2,    0,   9,    4,   0},
+      { 0, 0, 0, 0, 0,  1,  2,  0, 0, 0, 0, 0, 2,    4,  17,    7,  -2},
+      { 0, 0, 0, 0, 0, -9, 11,  0, 0, 0, 0, 0, 2,   34,   0,    0, -15},
+      { 0, 0, 0, 0, 0, -9, 11,  0, 0, 0, 0, 0, 1,    0,   5,    3,   0},
+      { 0, 0, 0, 0, 0,  0,  4,  0,-4, 0, 0, 0, 2,   -5,   0,    0,   2},
+      { 0, 0, 0, 0, 0,  0,  4,  0,-3, 0, 0, 0, 2,  -37,  -7,   -3,  16},
+      { 0, 0, 0, 0, 0, -6,  6,  0, 0, 0, 0, 0, 1,    3,  13,    7,  -2},
+      { 0, 0, 0, 0, 0,  6, -6,  0, 0, 0, 0, 0, 0,   40,   0,    0,   0},
+      { 0, 0, 0, 0, 0,  6, -6,  0, 0, 0, 0, 0, 1,    0,  -3,   -2,   0},
+      { 0, 0, 0, 0, 0,  0,  4,  0,-2, 0, 0, 0, 2, -184,  -3,   -1,  80},
+
+   /* 581-590 */
+      { 0, 0, 0, 0, 0,  0,  6, -4, 0, 0, 0, 0, 2,   -3,   0,    0,   1},
+      { 0, 0, 0, 0, 0,  3, -1,  0, 0, 0, 0, 0, 0,   -3,   0,    0,   0},
+      { 0, 0, 0, 0, 0,  3, -1,  0, 0, 0, 0, 0, 1,    0, -10,   -6,  -1},
+      { 0, 0, 0, 0, 0,  3, -1,  0, 0, 0, 0, 0, 2,   31,  -6,    0, -13},
+      { 0, 0, 0, 0, 0,  0,  4,  0,-1, 0, 0, 0, 2,   -3, -32,  -14,   1},
+      { 0, 0, 0, 0, 0,  0,  4,  0, 0,-2, 0, 0, 2,   -7,   0,    0,   3},
+      { 0, 0, 0, 0, 0,  0,  5, -2, 0, 0, 0, 0, 2,    0,  -8,   -4,   0},
+      { 0, 0, 0, 0, 0,  0,  4,  0, 0, 0, 0, 0, 0,    3,  -4,    0,   0},
+      { 0, 0, 0, 0, 0,  8, -9,  0, 0, 0, 0, 0, 0,    0,   4,    0,   0},
+      { 0, 0, 0, 0, 0,  5, -4,  0, 0, 0, 0, 0, 2,    0,   3,    1,   0},
+
+   /* 591-600 */
+      { 0, 0, 0, 0, 0,  2,  1,  0, 0, 0, 0, 0, 2,   19, -23,  -10,   2},
+      { 0, 0, 0, 0, 0,  2,  1,  0, 0, 0, 0, 0, 1,    0,   0,    0, -10},
+      { 0, 0, 0, 0, 0,  2,  1,  0, 0, 0, 0, 0, 1,    0,   3,    2,   0},
+      { 0, 0, 0, 0, 0, -7,  7,  0, 0, 0, 0, 0, 1,    0,   9,    5,  -1},
+      { 0, 0, 0, 0, 0,  7, -7,  0, 0, 0, 0, 0, 0,   28,   0,    0,   0},
+      { 0, 0, 0, 0, 0,  4, -2,  0, 0, 0, 0, 0, 1,    0,  -7,   -4,   0},
+      { 0, 0, 0, 0, 0,  4, -2,  0, 0, 0, 0, 0, 2,    8,  -4,    0,  -4},
+      { 0, 0, 0, 0, 0,  4, -2,  0, 0, 0, 0, 0, 0,    0,   0,   -2,   0},
+      { 0, 0, 0, 0, 0,  4, -2,  0, 0, 0, 0, 0, 0,    0,   3,    0,   0},
+      { 0, 0, 0, 0, 0,  0,  5,  0,-4, 0, 0, 0, 2,   -3,   0,    0,   1},
+
+   /* 601-610 */
+      { 0, 0, 0, 0, 0,  0,  5,  0,-3, 0, 0, 0, 2,   -9,   0,    1,   4},
+      { 0, 0, 0, 0, 0,  0,  5,  0,-2, 0, 0, 0, 2,    3,  12,    5,  -1},
+      { 0, 0, 0, 0, 0,  3,  0,  0, 0, 0, 0, 0, 2,   17,  -3,   -1,   0},
+      { 0, 0, 0, 0, 0, -8,  8,  0, 0, 0, 0, 0, 1,    0,   7,    4,   0},
+      { 0, 0, 0, 0, 0,  8, -8,  0, 0, 0, 0, 0, 0,   19,   0,    0,   0},
+      { 0, 0, 0, 0, 0,  5, -3,  0, 0, 0, 0, 0, 1,    0,  -5,   -3,   0},
+      { 0, 0, 0, 0, 0,  5, -3,  0, 0, 0, 0, 0, 2,   14,  -3,    0,  -1},
+      { 0, 0, 0, 0, 0, -9,  9,  0, 0, 0, 0, 0, 1,    0,   0,   -1,   0},
+      { 0, 0, 0, 0, 0, -9,  9,  0, 0, 0, 0, 0, 1,    0,   0,    0,  -5},
+      { 0, 0, 0, 0, 0, -9,  9,  0, 0, 0, 0, 0, 1,    0,   5,    3,   0},
+
+   /* 611-620 */
+      { 0, 0, 0, 0, 0,  9, -9,  0, 0, 0, 0, 0, 0,   13,   0,    0,   0},
+      { 0, 0, 0, 0, 0,  6, -4,  0, 0, 0, 0, 0, 1,    0,  -3,   -2,   0},
+      { 0, 0, 0, 0, 0,  0,  6,  0, 0, 0, 0, 0, 2,    2,   9,    4,   3},
+      { 0, 0, 0, 0, 0,  0,  6,  0, 0, 0, 0, 0, 0,    0,   0,    0,  -4},
+      { 0, 0, 0, 0, 0,  0,  6,  0, 0, 0, 0, 0, 0,    8,   0,    0,   0},
+      { 0, 0, 0, 0, 0,  0,  6,  0, 0, 0, 0, 0, 1,    0,   4,    2,   0},
+      { 0, 0, 0, 0, 0,  0,  6,  0, 0, 0, 0, 0, 2,    6,   0,    0,  -3},
+      { 0, 0, 0, 0, 0,  0,  6,  0, 0, 0, 0, 0, 0,    6,   0,    0,   0},
+      { 0, 0, 0, 0, 0,  0,  6,  0, 0, 0, 0, 0, 1,    0,   3,    1,   0},
+      { 0, 0, 0, 0, 0,  0,  6,  0, 0, 0, 0, 0, 2,    5,   0,    0,  -2},
+
+   /* 621-630 */
+      { 0, 0, 0, 0, 0,  0,  0,  0, 0, 0, 0, 0, 2,    3,   0,    0,  -1},
+      { 1, 0,-2, 0, 0,  0,  2,  0,-2, 0, 0, 0, 0,   -3,   0,    0,   0},
+      { 1, 0,-2, 0, 0,  2, -2,  0, 0, 0, 0, 0, 0,    6,   0,    0,   0},
+      { 1, 0,-2, 0, 0,  0,  1,  0,-1, 0, 0, 0, 0,    7,   0,    0,   0},
+      { 1, 0,-2, 0, 0,  1, -1,  0, 0, 0, 0, 0, 0,   -4,   0,    0,   0},
+      {-1, 0, 0, 0, 0,  3, -3,  0, 0, 0, 0, 0, 0,    4,   0,    0,   0},
+      {-1, 0, 0, 0, 0,  0,  2,  0,-2, 0, 0, 0, 0,    6,   0,    0,   0},
+      {-1, 0, 2, 0, 0,  0,  4, -8, 3, 0, 0, 0, 0,    0,  -4,    0,   0},
+      { 1, 0,-2, 0, 0,  0,  4, -8, 3, 0, 0, 0, 0,    0,  -4,    0,   0},
+      {-2, 0, 2, 0, 0,  0,  4, -8, 3, 0, 0, 0, 0,    5,   0,    0,   0},
+
+   /* 631-640 */
+      {-1, 0, 0, 0, 0,  0,  2,  0,-3, 0, 0, 0, 0,   -3,   0,    0,   0},
+      {-1, 0, 0, 0, 0,  0,  1,  0,-1, 0, 0, 0, 0,    4,   0,    0,   0},
+      {-1, 0, 0, 0, 0,  1, -1,  0, 0, 0, 0, 0, 0,   -5,   0,    0,   0},
+      {-1, 0, 2, 0, 0,  2, -2,  0, 0, 0, 0, 0, 0,    4,   0,    0,   0},
+      { 1,-1, 1, 0, 0,  0,  1,  0, 0, 0, 0, 0, 0,    0,   3,    0,   0},
+      {-1, 0, 2, 0, 0,  0,  2,  0,-3, 0, 0, 0, 0,   13,   0,    0,   0},
+      {-2, 0, 0, 0, 0,  0,  2,  0,-3, 0, 0, 0, 0,   21,  11,    0,   0},
+      { 1, 0, 0, 0, 0,  0,  4, -8, 3, 0, 0, 0, 0,    0,  -5,    0,   0},
+      {-1, 1,-1, 1, 0,  0, -1,  0, 0, 0, 0, 0, 0,    0,  -5,   -2,   0},
+      { 1, 1,-1, 1, 0,  0, -1,  0, 0, 0, 0, 0, 0,    0,   5,    3,   0},
+
+   /* 641-650 */
+      {-1, 0, 0, 0, 0,  0,  4, -8, 3, 0, 0, 0, 0,    0,  -5,    0,   0},
+      {-1, 0, 2, 1, 0,  0,  2,  0,-2, 0, 0, 0, 0,   -3,   0,    0,   2},
+      { 0, 0, 0, 0, 0,  0,  2,  0,-2, 0, 0, 0, 0,   20,  10,    0,   0},
+      {-1, 0, 2, 0, 0,  0,  2,  0,-2, 0, 0, 0, 0,  -34,   0,    0,   0},
+      {-1, 0, 2, 0, 0,  3, -3,  0, 0, 0, 0, 0, 0,  -19,   0,    0,   0},
+      { 1, 0,-2, 1, 0,  0, -2,  0, 2, 0, 0, 0, 0,    3,   0,    0,  -2},
+      { 1, 2,-2, 2, 0, -3,  3,  0, 0, 0, 0, 0, 0,   -3,   0,    0,   1},
+      { 1, 2,-2, 2, 0,  0, -2,  0, 2, 0, 0, 0, 0,   -6,   0,    0,   3},
+      { 1, 0, 0, 0, 0,  1, -1,  0, 0, 0, 0, 0, 0,   -4,   0,    0,   0},
+      { 1, 0, 0, 0, 0,  0,  1,  0,-1, 0, 0, 0, 0,    3,   0,    0,   0},
+
+   /* 651-660 */
+      { 0, 0,-2, 0, 0,  2, -2,  0, 0, 0, 0, 0, 0,    3,   0,    0,   0},
+      { 0, 0,-2, 0, 0,  0,  1,  0,-1, 0, 0, 0, 0,    4,   0,    0,   0},
+      { 0, 2, 0, 2, 0, -2,  2,  0, 0, 0, 0, 0, 0,    3,   0,    0,  -1},
+      { 0, 2, 0, 2, 0,  0, -1,  0, 1, 0, 0, 0, 0,    6,   0,    0,  -3},
+      { 0, 2, 0, 2, 0, -1,  1,  0, 0, 0, 0, 0, 0,   -8,   0,    0,   3},
+      { 0, 2, 0, 2, 0, -2,  3,  0, 0, 0, 0, 0, 0,    0,   3,    1,   0},
+      { 0, 0, 2, 0, 0,  0,  2,  0,-2, 0, 0, 0, 0,   -3,   0,    0,   0},
+      { 0, 1, 1, 2, 0,  0,  1,  0, 0, 0, 0, 0, 0,    0,  -3,   -2,   0},
+      { 1, 2, 0, 2, 0,  0,  1,  0, 0, 0, 0, 0, 0,  126, -63,  -27, -55},
+      {-1, 2, 0, 2, 0, 10, -3,  0, 0, 0, 0, 0, 0,   -5,   0,    1,   2},
+
+   /* 661-670 */
+      { 0, 1, 1, 1, 0,  0,  1,  0, 0, 0, 0, 0, 0,   -3,  28,   15,   2},
+      { 1, 2, 0, 2, 0,  0,  1,  0, 0, 0, 0, 0, 0,    5,   0,    1,  -2},
+      { 0, 2, 0, 2, 0,  0,  4, -8, 3, 0, 0, 0, 0,    0,   9,    4,   1},
+      { 0, 2, 0, 2, 0,  0, -4,  8,-3, 0, 0, 0, 0,    0,   9,    4,  -1},
+      {-1, 2, 0, 2, 0,  0, -4,  8,-3, 0, 0, 0, 0, -126, -63,  -27,  55},
+      { 2, 2,-2, 2, 0,  0, -2,  0, 3, 0, 0, 0, 0,    3,   0,    0,  -1},
+      { 1, 2, 0, 1, 0,  0, -2,  0, 3, 0, 0, 0, 0,   21, -11,   -6, -11},
+      { 0, 1, 1, 0, 0,  0,  1,  0, 0, 0, 0, 0, 0,    0,  -4,    0,   0},
+      {-1, 2, 0, 1, 0,  0,  1,  0, 0, 0, 0, 0, 0,  -21, -11,   -6,  11},
+      {-2, 2, 2, 2, 0,  0,  2,  0,-2, 0, 0, 0, 0,   -3,   0,    0,   1},
+
+   /* 671-680 */
+      { 0, 2, 0, 2, 0,  2, -3,  0, 0, 0, 0, 0, 0,    0,   3,    1,   0},
+      { 0, 2, 0, 2, 0,  1, -1,  0, 0, 0, 0, 0, 0,    8,   0,    0,  -4},
+      { 0, 2, 0, 2, 0,  0,  1,  0,-1, 0, 0, 0, 0,   -6,   0,    0,   3},
+      { 0, 2, 0, 2, 0,  2, -2,  0, 0, 0, 0, 0, 0,   -3,   0,    0,   1},
+      {-1, 2, 2, 2, 0,  0, -1,  0, 1, 0, 0, 0, 0,    3,   0,    0,  -1},
+      { 1, 2, 0, 2, 0, -1,  1,  0, 0, 0, 0, 0, 0,   -3,   0,    0,   1},
+      {-1, 2, 2, 2, 0,  0,  2,  0,-3, 0, 0, 0, 0,   -5,   0,    0,   2},
+      { 2, 2, 0, 2, 0,  0,  2,  0,-3, 0, 0, 0, 0,   24, -12,   -5, -11},
+      { 1, 2, 0, 2, 0,  0, -4,  8,-3, 0, 0, 0, 0,    0,   3,    1,   0},
+      { 1, 2, 0, 2, 0,  0,  4, -8, 3, 0, 0, 0, 0,    0,   3,    1,   0},
+
+   /* 681-687 */
+      { 1, 1, 1, 1, 0,  0,  1,  0, 0, 0, 0, 0, 0,    0,   3,    2,   0},
+      { 0, 2, 0, 2, 0,  0,  1,  0, 0, 0, 0, 0, 0,  -24, -12,   -5,  10},
+      { 2, 2, 0, 1, 0,  0,  1,  0, 0, 0, 0, 0, 0,    4,   0,   -1,  -2},
+      {-1, 2, 2, 2, 0,  0,  2,  0,-2, 0, 0, 0, 0,   13,   0,    0,  -6},
+      {-1, 2, 2, 2, 0,  3, -3,  0, 0, 0, 0, 0, 0,    7,   0,    0,  -3},
+      { 1, 2, 0, 2, 0,  1, -1,  0, 0, 0, 0, 0, 0,    3,   0,    0,  -1},
+      { 0, 2, 2, 2, 0,  0,  2,  0,-2, 0, 0, 0, 0,    3,   0,    0,  -1}
+   };
+
+/* Number of terms in the planetary nutation model */
+   const int NPL = (int) (sizeof xpl / sizeof xpl[0]);
+
+/*--------------------------------------------------------------------*/
+
+/* Interval between fundamental date J2000.0 and given date (JC). */
+   t = ((date1 - DJ00) + date2) / DJC;
+
+/* ------------------- */
+/* LUNI-SOLAR NUTATION */
+/* ------------------- */
+
+/* Fundamental (Delaunay) arguments */
+
+/* Mean anomaly of the Moon (IERS 2003). */
+   el = iauFal03(t);
+
+/* Mean anomaly of the Sun (MHB2000). */
+   elp = fmod(1287104.79305  +
+            t * (129596581.0481  +
+            t * (-0.5532  +
+            t * (0.000136  +
+            t * (-0.00001149)))), TURNAS) * DAS2R;
+
+/* Mean longitude of the Moon minus that of the ascending node */
+/* (IERS 2003. */
+   f = iauFaf03(t);
+
+/* Mean elongation of the Moon from the Sun (MHB2000). */
+   d = fmod(1072260.70369  +
+          t * (1602961601.2090  +
+          t * (-6.3706  +
+          t * (0.006593  +
+          t * (-0.00003169)))), TURNAS) * DAS2R;
+
+/* Mean longitude of the ascending node of the Moon (IERS 2003). */
+   om = iauFaom03(t);
+
+/* Initialize the nutation values. */
+   dp = 0.0;
+   de = 0.0;
+
+/* Summation of luni-solar nutation series (in reverse order). */
+   for (i = NLS-1; i >= 0; i--) {
+
+   /* Argument and functions. */
+      arg = fmod((double)xls[i].nl  * el +
+                 (double)xls[i].nlp * elp +
+                 (double)xls[i].nf  * f +
+                 (double)xls[i].nd  * d +
+                 (double)xls[i].nom * om, D2PI);
+      sarg = sin(arg);
+      carg = cos(arg);
+
+   /* Term. */
+      dp += (xls[i].sp + xls[i].spt * t) * sarg + xls[i].cp * carg;
+      de += (xls[i].ce + xls[i].cet * t) * carg + xls[i].se * sarg;
+   }
+
+/* Convert from 0.1 microarcsec units to radians. */
+   dpsils = dp * U2R;
+   depsls = de * U2R;
+
+/* ------------------ */
+/* PLANETARY NUTATION */
+/* ------------------ */
+
+/* n.b.  The MHB2000 code computes the luni-solar and planetary nutation */
+/* in different functions, using slightly different Delaunay */
+/* arguments in the two cases.  This behaviour is faithfully */
+/* reproduced here.  Use of the IERS 2003 expressions for both */
+/* cases leads to negligible changes, well below */
+/* 0.1 microarcsecond. */
+
+/* Mean anomaly of the Moon (MHB2000). */
+   al = fmod(2.35555598 + 8328.6914269554 * t, D2PI);
+
+/* Mean longitude of the Moon minus that of the ascending node */
+/*(MHB2000). */
+   af = fmod(1.627905234 + 8433.466158131 * t, D2PI);
+
+/* Mean elongation of the Moon from the Sun (MHB2000). */
+   ad = fmod(5.198466741 + 7771.3771468121 * t, D2PI);
+
+/* Mean longitude of the ascending node of the Moon (MHB2000). */
+   aom = fmod(2.18243920 - 33.757045 * t, D2PI);
+
+/* General accumulated precession in longitude (IERS 2003). */
+   apa = iauFapa03(t);
+
+/* Planetary longitudes, Mercury through Uranus (IERS 2003). */
+   alme = iauFame03(t);
+   alve = iauFave03(t);
+   alea = iauFae03(t);
+   alma = iauFama03(t);
+   alju = iauFaju03(t);
+   alsa = iauFasa03(t);
+   alur = iauFaur03(t);
+
+/* Neptune longitude (MHB2000). */
+   alne = fmod(5.321159000 + 3.8127774000 * t, D2PI);
+
+/* Initialize the nutation values. */
+   dp = 0.0;
+   de = 0.0;
+
+/* Summation of planetary nutation series (in reverse order). */
+   for (i = NPL-1; i >= 0; i--) {
+
+   /* Argument and functions. */
+      arg = fmod((double)xpl[i].nl  * al   +
+                 (double)xpl[i].nf  * af   +
+                 (double)xpl[i].nd  * ad   +
+                 (double)xpl[i].nom * aom  +
+                 (double)xpl[i].nme * alme +
+                 (double)xpl[i].nve * alve +
+                 (double)xpl[i].nea * alea +
+                 (double)xpl[i].nma * alma +
+                 (double)xpl[i].nju * alju +
+                 (double)xpl[i].nsa * alsa +
+                 (double)xpl[i].nur * alur +
+                 (double)xpl[i].nne * alne +
+                 (double)xpl[i].npa * apa, D2PI);
+      sarg = sin(arg);
+      carg = cos(arg);
+
+   /* Term. */
+      dp += (double)xpl[i].sp * sarg + (double)xpl[i].cp * carg;
+      de += (double)xpl[i].se * sarg + (double)xpl[i].ce * carg;
+
+   }
+
+/* Convert from 0.1 microarcsec units to radians. */
+   dpsipl = dp * U2R;
+   depspl = de * U2R;
+
+/* ------- */
+/* RESULTS */
+/* ------- */
+
+/* Add luni-solar and planetary components. */
+   *dpsi = dpsils + dpsipl;
+   *deps = depsls + depspl;
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauNut00b(double date1, double date2, double *dpsi, double *deps)
+/*
+**  - - - - - - - - - -
+**   i a u N u t 0 0 b
+**  - - - - - - - - - -
+**
+**  Nutation, IAU 2000B model.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  canonical model.
+**
+**  Given:
+**     date1,date2   double    TT as a 2-part Julian Date (Note 1)
+**
+**  Returned:
+**     dpsi,deps     double    nutation, luni-solar + planetary (Note 2)
+**
+**  Notes:
+**
+**  1) The TT date date1+date2 is a Julian Date, apportioned in any
+**     convenient way between the two arguments.  For example,
+**     JD(TT)=2450123.7 could be expressed in any of these ways,
+**     among others:
+**
+**            date1          date2
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in
+**     cases where the loss of several decimal digits of resolution
+**     is acceptable.  The J2000 method is best matched to the way
+**     the argument is handled internally and will deliver the
+**     optimum resolution.  The MJD method and the date & time methods
+**     are both good compromises between resolution and convenience.
+**
+**  2) The nutation components in longitude and obliquity are in radians
+**     and with respect to the equinox and ecliptic of date.  The
+**     obliquity at J2000.0 is assumed to be the Lieske et al. (1977)
+**     value of 84381.448 arcsec.  (The errors that result from using
+**     this function with the IAU 2006 value of 84381.406 arcsec can be
+**     neglected.)
+**
+**     The nutation model consists only of luni-solar terms, but
+**     includes also a fixed offset which compensates for certain long-
+**     period planetary terms (Note 7).
+**
+**  3) This function is an implementation of the IAU 2000B abridged
+**     nutation model formally adopted by the IAU General Assembly in
+**     2000.  The function computes the MHB_2000_SHORT luni-solar
+**     nutation series (Luzum 2001), but without the associated
+**     corrections for the precession rate adjustments and the offset
+**     between the GCRS and J2000.0 mean poles.
+**
+**  4) The full IAU 2000A (MHB2000) nutation model contains nearly 1400
+**     terms.  The IAU 2000B model (McCarthy & Luzum 2003) contains only
+**     77 terms, plus additional simplifications, yet still delivers
+**     results of 1 mas accuracy at present epochs.  This combination of
+**     accuracy and size makes the IAU 2000B abridged nutation model
+**     suitable for most practical applications.
+**
+**     The function delivers a pole accurate to 1 mas from 1900 to 2100
+**     (usually better than 1 mas, very occasionally just outside
+**     1 mas).  The full IAU 2000A model, which is implemented in the
+**     function iauNut00a (q.v.), delivers considerably greater accuracy
+**     at current dates;  however, to realize this improved accuracy,
+**     corrections for the essentially unpredictable free-core-nutation
+**     (FCN) must also be included.
+**
+**  5) The present function provides classical nutation.  The
+**     MHB_2000_SHORT algorithm, from which it is adapted, deals also
+**     with (i) the offsets between the GCRS and mean poles and (ii) the
+**     adjustments in longitude and obliquity due to the changed
+**     precession rates.  These additional functions, namely frame bias
+**     and precession adjustments, are supported by the SOFA functions
+**     iauBi00  and iauPr00.
+**
+**  6) The MHB_2000_SHORT algorithm also provides "total" nutations,
+**     comprising the arithmetic sum of the frame bias, precession
+**     adjustments, and nutation (luni-solar + planetary).  These total
+**     nutations can be used in combination with an existing IAU 1976
+**     precession implementation, such as iauPmat76,  to deliver GCRS-
+**     to-true predictions of mas accuracy at current epochs.  However,
+**     for symmetry with the iauNut00a  function (q.v. for the reasons),
+**     the SOFA functions do not generate the "total nutations"
+**     directly.  Should they be required, they could of course easily
+**     be generated by calling iauBi00, iauPr00 and the present function
+**     and adding the results.
+**
+**  7) The IAU 2000B model includes "planetary bias" terms that are
+**     fixed in size but compensate for long-period nutations.  The
+**     amplitudes quoted in McCarthy & Luzum (2003), namely
+**     Dpsi = -1.5835 mas and Depsilon = +1.6339 mas, are optimized for
+**     the "total nutations" method described in Note 6.  The Luzum
+**     (2001) values used in this SOFA implementation, namely -0.135 mas
+**     and +0.388 mas, are optimized for the "rigorous" method, where
+**     frame bias, precession and nutation are applied separately and in
+**     that order.  During the interval 1995-2050, the SOFA
+**     implementation delivers a maximum error of 1.001 mas (not
+**     including FCN).
+**
+**  References:
+**
+**     Lieske, J.H., Lederle, T., Fricke, W., Morando, B., "Expressions
+**     for the precession quantities based upon the IAU /1976/ system of
+**     astronomical constants", Astron.Astrophys. 58, 1-2, 1-16. (1977)
+**
+**     Luzum, B., private communication, 2001 (Fortran code
+**     MHB_2000_SHORT)
+**
+**     McCarthy, D.D. & Luzum, B.J., "An abridged model of the
+**     precession-nutation of the celestial pole", Cel.Mech.Dyn.Astron.
+**     85, 37-49 (2003)
+**
+**     Simon, J.-L., Bretagnon, P., Chapront, J., Chapront-Touze, M.,
+**     Francou, G., Laskar, J., Astron.Astrophys. 282, 663-683 (1994)
+**
+**  This revision:  2010 September 4
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double t, el, elp, f, d, om, arg, dp, de, sarg, carg,
+          dpsils, depsls, dpsipl, depspl;
+   int i;
+
+/* Units of 0.1 microarcsecond to radians */
+   static const double U2R = DAS2R / 1e7;
+
+/* ---------------------------------------- */
+/* Fixed offsets in lieu of planetary terms */
+/* ---------------------------------------- */
+
+   static const double DPPLAN = -0.135 * DMAS2R;
+   static const double DEPLAN =  0.388 * DMAS2R;
+
+/* --------------------------------------------------- */
+/* Luni-solar nutation: argument and term coefficients */
+/* --------------------------------------------------- */
+
+/* The units for the sine and cosine coefficients are */
+/* 0.1 microarcsec and the same per Julian century    */
+
+   static const struct {
+      int nl,nlp,nf,nd,nom; /* coefficients of l,l',F,D,Om */
+      double ps,pst,pc;     /* longitude sin, t*sin, cos coefficients */
+      double ec,ect,es;     /* obliquity cos, t*cos, sin coefficients */
+
+   } x[] = {
+
+   /* 1-10 */
+      { 0, 0, 0, 0,1,
+         -172064161.0, -174666.0, 33386.0, 92052331.0, 9086.0, 15377.0},
+      { 0, 0, 2,-2,2,
+           -13170906.0, -1675.0, -13696.0, 5730336.0, -3015.0, -4587.0},
+      { 0, 0, 2, 0,2,-2276413.0,-234.0, 2796.0, 978459.0,-485.0,1374.0},
+      { 0, 0, 0, 0,2,2074554.0,  207.0, -698.0,-897492.0, 470.0,-291.0},
+      { 0, 1, 0, 0,0,1475877.0,-3633.0,11817.0, 73871.0,-184.0,-1924.0},
+      { 0, 1, 2,-2,2,-516821.0, 1226.0, -524.0, 224386.0,-677.0,-174.0},
+      { 1, 0, 0, 0,0, 711159.0,   73.0, -872.0,  -6750.0,   0.0, 358.0},
+      { 0, 0, 2, 0,1,-387298.0, -367.0,  380.0, 200728.0,  18.0, 318.0},
+      { 1, 0, 2, 0,2,-301461.0,  -36.0,  816.0, 129025.0, -63.0, 367.0},
+      { 0,-1, 2,-2,2, 215829.0, -494.0,  111.0, -95929.0, 299.0, 132.0},
+
+   /* 11-20 */
+      { 0, 0, 2,-2,1, 128227.0,  137.0,  181.0, -68982.0,  -9.0,  39.0},
+      {-1, 0, 2, 0,2, 123457.0,   11.0,   19.0, -53311.0,  32.0,  -4.0},
+      {-1, 0, 0, 2,0, 156994.0,   10.0, -168.0,  -1235.0,   0.0,  82.0},
+      { 1, 0, 0, 0,1,  63110.0,   63.0,   27.0, -33228.0,   0.0,  -9.0},
+      {-1, 0, 0, 0,1, -57976.0,  -63.0, -189.0,  31429.0,   0.0, -75.0},
+      {-1, 0, 2, 2,2, -59641.0,  -11.0,  149.0,  25543.0, -11.0,  66.0},
+      { 1, 0, 2, 0,1, -51613.0,  -42.0,  129.0,  26366.0,   0.0,  78.0},
+      {-2, 0, 2, 0,1,  45893.0,   50.0,   31.0, -24236.0, -10.0,  20.0},
+      { 0, 0, 0, 2,0,  63384.0,   11.0, -150.0,  -1220.0,   0.0,  29.0},
+      { 0, 0, 2, 2,2, -38571.0,   -1.0,  158.0,  16452.0, -11.0,  68.0},
+
+   /* 21-30 */
+      { 0,-2, 2,-2,2,  32481.0,    0.0,    0.0, -13870.0,   0.0,   0.0},
+      {-2, 0, 0, 2,0, -47722.0,    0.0,  -18.0,    477.0,   0.0, -25.0},
+      { 2, 0, 2, 0,2, -31046.0,   -1.0,  131.0,  13238.0, -11.0,  59.0},
+      { 1, 0, 2,-2,2,  28593.0,    0.0,   -1.0, -12338.0,  10.0,  -3.0},
+      {-1, 0, 2, 0,1,  20441.0,   21.0,   10.0, -10758.0,   0.0,  -3.0},
+      { 2, 0, 0, 0,0,  29243.0,    0.0,  -74.0,   -609.0,   0.0,  13.0},
+      { 0, 0, 2, 0,0,  25887.0,    0.0,  -66.0,   -550.0,   0.0,  11.0},
+      { 0, 1, 0, 0,1, -14053.0,  -25.0,   79.0,   8551.0,  -2.0, -45.0},
+      {-1, 0, 0, 2,1,  15164.0,   10.0,   11.0,  -8001.0,   0.0,  -1.0},
+      { 0, 2, 2,-2,2, -15794.0,   72.0,  -16.0,   6850.0, -42.0,  -5.0},
+
+   /* 31-40 */
+      { 0, 0,-2, 2,0,  21783.0,    0.0,   13.0,   -167.0,   0.0,  13.0},
+      { 1, 0, 0,-2,1, -12873.0,  -10.0,  -37.0,   6953.0,   0.0, -14.0},
+      { 0,-1, 0, 0,1, -12654.0,   11.0,   63.0,   6415.0,   0.0,  26.0},
+      {-1, 0, 2, 2,1, -10204.0,    0.0,   25.0,   5222.0,   0.0,  15.0},
+      { 0, 2, 0, 0,0,  16707.0,  -85.0,  -10.0,    168.0,  -1.0,  10.0},
+      { 1, 0, 2, 2,2,  -7691.0,    0.0,   44.0,   3268.0,   0.0,  19.0},
+      {-2, 0, 2, 0,0, -11024.0,    0.0,  -14.0,    104.0,   0.0,   2.0},
+      { 0, 1, 2, 0,2,   7566.0,  -21.0,  -11.0,  -3250.0,   0.0,  -5.0},
+      { 0, 0, 2, 2,1,  -6637.0,  -11.0,   25.0,   3353.0,   0.0,  14.0},
+      { 0,-1, 2, 0,2,  -7141.0,   21.0,    8.0,   3070.0,   0.0,   4.0},
+
+   /* 41-50 */
+      { 0, 0, 0, 2,1,  -6302.0,  -11.0,    2.0,   3272.0,   0.0,   4.0},
+      { 1, 0, 2,-2,1,   5800.0,   10.0,    2.0,  -3045.0,   0.0,  -1.0},
+      { 2, 0, 2,-2,2,   6443.0,    0.0,   -7.0,  -2768.0,   0.0,  -4.0},
+      {-2, 0, 0, 2,1,  -5774.0,  -11.0,  -15.0,   3041.0,   0.0,  -5.0},
+      { 2, 0, 2, 0,1,  -5350.0,    0.0,   21.0,   2695.0,   0.0,  12.0},
+      { 0,-1, 2,-2,1,  -4752.0,  -11.0,   -3.0,   2719.0,   0.0,  -3.0},
+      { 0, 0, 0,-2,1,  -4940.0,  -11.0,  -21.0,   2720.0,   0.0,  -9.0},
+      {-1,-1, 0, 2,0,   7350.0,    0.0,   -8.0,    -51.0,   0.0,   4.0},
+      { 2, 0, 0,-2,1,   4065.0,    0.0,    6.0,  -2206.0,   0.0,   1.0},
+      { 1, 0, 0, 2,0,   6579.0,    0.0,  -24.0,   -199.0,   0.0,   2.0},
+
+   /* 51-60 */
+      { 0, 1, 2,-2,1,   3579.0,    0.0,    5.0,  -1900.0,   0.0,   1.0},
+      { 1,-1, 0, 0,0,   4725.0,    0.0,   -6.0,    -41.0,   0.0,   3.0},
+      {-2, 0, 2, 0,2,  -3075.0,    0.0,   -2.0,   1313.0,   0.0,  -1.0},
+      { 3, 0, 2, 0,2,  -2904.0,    0.0,   15.0,   1233.0,   0.0,   7.0},
+      { 0,-1, 0, 2,0,   4348.0,    0.0,  -10.0,    -81.0,   0.0,   2.0},
+      { 1,-1, 2, 0,2,  -2878.0,    0.0,    8.0,   1232.0,   0.0,   4.0},
+      { 0, 0, 0, 1,0,  -4230.0,    0.0,    5.0,    -20.0,   0.0,  -2.0},
+      {-1,-1, 2, 2,2,  -2819.0,    0.0,    7.0,   1207.0,   0.0,   3.0},
+      {-1, 0, 2, 0,0,  -4056.0,    0.0,    5.0,     40.0,   0.0,  -2.0},
+      { 0,-1, 2, 2,2,  -2647.0,    0.0,   11.0,   1129.0,   0.0,   5.0},
+
+   /* 61-70 */
+      {-2, 0, 0, 0,1,  -2294.0,    0.0,  -10.0,   1266.0,   0.0,  -4.0},
+      { 1, 1, 2, 0,2,   2481.0,    0.0,   -7.0,  -1062.0,   0.0,  -3.0},
+      { 2, 0, 0, 0,1,   2179.0,    0.0,   -2.0,  -1129.0,   0.0,  -2.0},
+      {-1, 1, 0, 1,0,   3276.0,    0.0,    1.0,     -9.0,   0.0,   0.0},
+      { 1, 1, 0, 0,0,  -3389.0,    0.0,    5.0,     35.0,   0.0,  -2.0},
+      { 1, 0, 2, 0,0,   3339.0,    0.0,  -13.0,   -107.0,   0.0,   1.0},
+      {-1, 0, 2,-2,1,  -1987.0,    0.0,   -6.0,   1073.0,   0.0,  -2.0},
+      { 1, 0, 0, 0,2,  -1981.0,    0.0,    0.0,    854.0,   0.0,   0.0},
+      {-1, 0, 0, 1,0,   4026.0,    0.0, -353.0,   -553.0,   0.0,-139.0},
+      { 0, 0, 2, 1,2,   1660.0,    0.0,   -5.0,   -710.0,   0.0,  -2.0},
+
+   /* 71-77 */
+      {-1, 0, 2, 4,2,  -1521.0,    0.0,    9.0,    647.0,   0.0,   4.0},
+      {-1, 1, 0, 1,1,   1314.0,    0.0,    0.0,   -700.0,   0.0,   0.0},
+      { 0,-2, 2,-2,1,  -1283.0,    0.0,    0.0,    672.0,   0.0,   0.0},
+      { 1, 0, 2, 2,1,  -1331.0,    0.0,    8.0,    663.0,   0.0,   4.0},
+      {-2, 0, 2, 2,2,   1383.0,    0.0,   -2.0,   -594.0,   0.0,  -2.0},
+      {-1, 0, 0, 0,2,   1405.0,    0.0,    4.0,   -610.0,   0.0,   2.0},
+      { 1, 1, 2,-2,2,   1290.0,    0.0,    0.0,   -556.0,   0.0,   0.0}
+   };
+
+/* Number of terms in the series */
+   const int NLS = (int) (sizeof x / sizeof x[0]);
+
+/*--------------------------------------------------------------------*/
+
+/* Interval between fundamental epoch J2000.0 and given date (JC). */
+   t = ((date1 - DJ00) + date2) / DJC;
+
+/* --------------------*/
+/* LUNI-SOLAR NUTATION */
+/* --------------------*/
+
+/* Fundamental (Delaunay) arguments from Simon et al. (1994) */
+
+/* Mean anomaly of the Moon. */
+   el = fmod(485868.249036 + (1717915923.2178) * t, TURNAS) * DAS2R;
+
+/* Mean anomaly of the Sun. */
+   elp = fmod(1287104.79305 + (129596581.0481) * t, TURNAS) * DAS2R;
+
+/* Mean argument of the latitude of the Moon. */
+   f = fmod(335779.526232 + (1739527262.8478) * t, TURNAS) * DAS2R;
+
+/* Mean elongation of the Moon from the Sun. */
+   d = fmod(1072260.70369 + (1602961601.2090) * t, TURNAS) * DAS2R;
+
+/* Mean longitude of the ascending node of the Moon. */
+   om = fmod(450160.398036 + (-6962890.5431) * t, TURNAS) * DAS2R;
+
+/* Initialize the nutation values. */
+   dp = 0.0;
+   de = 0.0;
+
+/* Summation of luni-solar nutation series (smallest terms first). */
+   for (i = NLS-1; i >= 0; i--) {
+
+   /* Argument and functions. */
+      arg = fmod( (double)x[i].nl  * el  +
+                  (double)x[i].nlp * elp +
+                  (double)x[i].nf  * f   +
+                  (double)x[i].nd  * d   +
+                  (double)x[i].nom * om, D2PI  );
+      sarg = sin(arg);
+      carg = cos(arg);
+
+   /* Term. */
+      dp += (x[i].ps + x[i].pst * t) * sarg + x[i].pc * carg;
+      de += (x[i].ec + x[i].ect * t) * carg + x[i].es * sarg;
+   }
+
+/* Convert from 0.1 microarcsec units to radians. */
+   dpsils = dp * U2R;
+   depsls = de * U2R;
+
+/* ------------------------------*/
+/* IN LIEU OF PLANETARY NUTATION */
+/* ------------------------------*/
+
+/* Fixed offset to correct for missing terms in truncated series. */
+   dpsipl = DPPLAN;
+   depspl = DEPLAN;
+
+/* --------*/
+/* RESULTS */
+/* --------*/
+
+/* Add luni-solar and planetary components. */
+   *dpsi = dpsils + dpsipl;
+   *deps = depsls + depspl;
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauNut06a(double date1, double date2, double *dpsi, double *deps)
+/*
+**  - - - - - - - - - -
+**   i a u N u t 0 6 a
+**  - - - - - - - - - -
+**
+**  IAU 2000A nutation with adjustments to match the IAU 2006
+**  precession.
+**
+**  Given:
+**     date1,date2   double   TT as a 2-part Julian Date (Note 1)
+**
+**  Returned:
+**     dpsi,deps     double   nutation, luni-solar + planetary (Note 2)
+**
+**  Status:  canonical model.
+**
+**  Notes:
+**
+**  1) The TT date date1+date2 is a Julian Date, apportioned in any
+**     convenient way between the two arguments.  For example,
+**     JD(TT)=2450123.7 could be expressed in any of these ways,
+**     among others:
+**
+**            date1          date2
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in
+**     cases where the loss of several decimal digits of resolution
+**     is acceptable.  The J2000 method is best matched to the way
+**     the argument is handled internally and will deliver the
+**     optimum resolution.  The MJD method and the date & time methods
+**     are both good compromises between resolution and convenience.
+**
+**  2) The nutation components in longitude and obliquity are in radians
+**     and with respect to the mean equinox and ecliptic of date,
+**     IAU 2006 precession model (Hilton et al. 2006, Capitaine et al.
+**     2005).
+**
+**  3) The function first computes the IAU 2000A nutation, then applies
+**     adjustments for (i) the consequences of the change in obliquity
+**     from the IAU 1980 ecliptic to the IAU 2006 ecliptic and (ii) the
+**     secular variation in the Earth's dynamical form factor J2.
+**
+**  4) The present function provides classical nutation, complementing
+**     the IAU 2000 frame bias and IAU 2006 precession.  It delivers a
+**     pole which is at current epochs accurate to a few tens of
+**     microarcseconds, apart from the free core nutation.
+**
+**  Called:
+**     iauNut00a    nutation, IAU 2000A
+**
+**  References:
+**
+**     Chapront, J., Chapront-Touze, M. & Francou, G. 2002,
+**     Astron.Astrophys. 387, 700
+**
+**     Lieske, J.H., Lederle, T., Fricke, W. & Morando, B. 1977,
+**     Astron.Astrophys. 58, 1-16
+**
+**     Mathews, P.M., Herring, T.A., Buffet, B.A. 2002, J.Geophys.Res.
+**     107, B4.  The MHB_2000 code itself was obtained on 9th September
+**     2002 from ftp//maia.usno.navy.mil/conv2000/chapter5/IAU2000A.
+**
+**     Simon, J.-L., Bretagnon, P., Chapront, J., Chapront-Touze, M.,
+**     Francou, G., Laskar, J. 1994, Astron.Astrophys. 282, 663-683
+**
+**     Souchay, J., Loysel, B., Kinoshita, H., Folgueira, M. 1999,
+**     Astron.Astrophys.Supp.Ser. 135, 111
+**
+**     Wallace, P.T., "Software for Implementing the IAU 2000
+**     Resolutions", in IERS Workshop 5.1 (2002)
+**
+**  This revision:  2011 April 3
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double t, fj2, dp, de;
+
+
+/* Interval between fundamental date J2000.0 and given date (JC). */
+   t = ((date1 - DJ00) + date2) / DJC;
+
+/* Factor correcting for secular variation of J2. */
+   fj2 = -2.7774e-6 * t;
+
+/* Obtain IAU 2000A nutation. */
+   iauNut00a(date1, date2, &dp, &de);
+
+/* Apply P03 adjustments (Wallace & Capitaine, 2006, Eqs.5). */
+   *dpsi = dp + dp * (0.4697e-6 + fj2);
+   *deps = de + de * fj2;
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauNut80(double date1, double date2, double *dpsi, double *deps)
+/*
+**  - - - - - - - - -
+**   i a u N u t 8 0
+**  - - - - - - - - -
+**
+**  Nutation, IAU 1980 model.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  canonical model.
+**
+**  Given:
+**     date1,date2   double    TT as a 2-part Julian Date (Note 1)
+**
+**  Returned:
+**     dpsi          double    nutation in longitude (radians)
+**     deps          double    nutation in obliquity (radians)
+**
+**  Notes:
+**
+**  1) The TT date date1+date2 is a Julian Date, apportioned in any
+**     convenient way between the two arguments.  For example,
+**     JD(TT)=2450123.7 could be expressed in any of these ways,
+**     among others:
+**
+**            date1          date2
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in
+**     cases where the loss of several decimal digits of resolution
+**     is acceptable.  The J2000 method is best matched to the way
+**     the argument is handled internally and will deliver the
+**     optimum resolution.  The MJD method and the date & time methods
+**     are both good compromises between resolution and convenience.
+**
+**  2) The nutation components are with respect to the ecliptic of
+**     date.
+**
+**  Called:
+**     iauAnpm      normalize angle into range +/- pi
+**
+**  Reference:
+**
+**     Explanatory Supplement to the Astronomical Almanac,
+**     P. Kenneth Seidelmann (ed), University Science Books (1992),
+**     Section 3.222 (p111).
+**
+**  This revision:  2008 September 30
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double t, el, elp, f, d, om, dp, de, arg, s, c;
+   int j;
+
+/* Units of 0.1 milliarcsecond to radians */
+   const double U2R = DAS2R / 1e4;
+
+/* ------------------------------------------------ */
+/* Table of multiples of arguments and coefficients */
+/* ------------------------------------------------ */
+
+/* The units for the sine and cosine coefficients are 0.1 mas and */
+/* the same per Julian century */
+
+   static const struct {
+      int nl,nlp,nf,nd,nom; /* coefficients of l,l',F,D,Om */
+      double sp,spt;        /* longitude sine, 1 and t coefficients */
+      double ce,cet;        /* obliquity cosine, 1 and t coefficients */
+   } x[] = {
+
+   /* 1-10 */
+      {  0,  0,  0,  0,  1, -171996.0, -174.2,  92025.0,    8.9 },
+      {  0,  0,  0,  0,  2,    2062.0,    0.2,   -895.0,    0.5 },
+      { -2,  0,  2,  0,  1,      46.0,    0.0,    -24.0,    0.0 },
+      {  2,  0, -2,  0,  0,      11.0,    0.0,      0.0,    0.0 },
+      { -2,  0,  2,  0,  2,      -3.0,    0.0,      1.0,    0.0 },
+      {  1, -1,  0, -1,  0,      -3.0,    0.0,      0.0,    0.0 },
+      {  0, -2,  2, -2,  1,      -2.0,    0.0,      1.0,    0.0 },
+      {  2,  0, -2,  0,  1,       1.0,    0.0,      0.0,    0.0 },
+      {  0,  0,  2, -2,  2,  -13187.0,   -1.6,   5736.0,   -3.1 },
+      {  0,  1,  0,  0,  0,    1426.0,   -3.4,     54.0,   -0.1 },
+
+   /* 11-20 */
+      {  0,  1,  2, -2,  2,    -517.0,    1.2,    224.0,   -0.6 },
+      {  0, -1,  2, -2,  2,     217.0,   -0.5,    -95.0,    0.3 },
+      {  0,  0,  2, -2,  1,     129.0,    0.1,    -70.0,    0.0 },
+      {  2,  0,  0, -2,  0,      48.0,    0.0,      1.0,    0.0 },
+      {  0,  0,  2, -2,  0,     -22.0,    0.0,      0.0,    0.0 },
+      {  0,  2,  0,  0,  0,      17.0,   -0.1,      0.0,    0.0 },
+      {  0,  1,  0,  0,  1,     -15.0,    0.0,      9.0,    0.0 },
+      {  0,  2,  2, -2,  2,     -16.0,    0.1,      7.0,    0.0 },
+      {  0, -1,  0,  0,  1,     -12.0,    0.0,      6.0,    0.0 },
+      { -2,  0,  0,  2,  1,      -6.0,    0.0,      3.0,    0.0 },
+
+   /* 21-30 */
+      {  0, -1,  2, -2,  1,      -5.0,    0.0,      3.0,    0.0 },
+      {  2,  0,  0, -2,  1,       4.0,    0.0,     -2.0,    0.0 },
+      {  0,  1,  2, -2,  1,       4.0,    0.0,     -2.0,    0.0 },
+      {  1,  0,  0, -1,  0,      -4.0,    0.0,      0.0,    0.0 },
+      {  2,  1,  0, -2,  0,       1.0,    0.0,      0.0,    0.0 },
+      {  0,  0, -2,  2,  1,       1.0,    0.0,      0.0,    0.0 },
+      {  0,  1, -2,  2,  0,      -1.0,    0.0,      0.0,    0.0 },
+      {  0,  1,  0,  0,  2,       1.0,    0.0,      0.0,    0.0 },
+      { -1,  0,  0,  1,  1,       1.0,    0.0,      0.0,    0.0 },
+      {  0,  1,  2, -2,  0,      -1.0,    0.0,      0.0,    0.0 },
+
+   /* 31-40 */
+      {  0,  0,  2,  0,  2,   -2274.0,   -0.2,    977.0,   -0.5 },
+      {  1,  0,  0,  0,  0,     712.0,    0.1,     -7.0,    0.0 },
+      {  0,  0,  2,  0,  1,    -386.0,   -0.4,    200.0,    0.0 },
+      {  1,  0,  2,  0,  2,    -301.0,    0.0,    129.0,   -0.1 },
+      {  1,  0,  0, -2,  0,    -158.0,    0.0,     -1.0,    0.0 },
+      { -1,  0,  2,  0,  2,     123.0,    0.0,    -53.0,    0.0 },
+      {  0,  0,  0,  2,  0,      63.0,    0.0,     -2.0,    0.0 },
+      {  1,  0,  0,  0,  1,      63.0,    0.1,    -33.0,    0.0 },
+      { -1,  0,  0,  0,  1,     -58.0,   -0.1,     32.0,    0.0 },
+      { -1,  0,  2,  2,  2,     -59.0,    0.0,     26.0,    0.0 },
+
+   /* 41-50 */
+      {  1,  0,  2,  0,  1,     -51.0,    0.0,     27.0,    0.0 },
+      {  0,  0,  2,  2,  2,     -38.0,    0.0,     16.0,    0.0 },
+      {  2,  0,  0,  0,  0,      29.0,    0.0,     -1.0,    0.0 },
+      {  1,  0,  2, -2,  2,      29.0,    0.0,    -12.0,    0.0 },
+      {  2,  0,  2,  0,  2,     -31.0,    0.0,     13.0,    0.0 },
+      {  0,  0,  2,  0,  0,      26.0,    0.0,     -1.0,    0.0 },
+      { -1,  0,  2,  0,  1,      21.0,    0.0,    -10.0,    0.0 },
+      { -1,  0,  0,  2,  1,      16.0,    0.0,     -8.0,    0.0 },
+      {  1,  0,  0, -2,  1,     -13.0,    0.0,      7.0,    0.0 },
+      { -1,  0,  2,  2,  1,     -10.0,    0.0,      5.0,    0.0 },
+
+   /* 51-60 */
+      {  1,  1,  0, -2,  0,      -7.0,    0.0,      0.0,    0.0 },
+      {  0,  1,  2,  0,  2,       7.0,    0.0,     -3.0,    0.0 },
+      {  0, -1,  2,  0,  2,      -7.0,    0.0,      3.0,    0.0 },
+      {  1,  0,  2,  2,  2,      -8.0,    0.0,      3.0,    0.0 },
+      {  1,  0,  0,  2,  0,       6.0,    0.0,      0.0,    0.0 },
+      {  2,  0,  2, -2,  2,       6.0,    0.0,     -3.0,    0.0 },
+      {  0,  0,  0,  2,  1,      -6.0,    0.0,      3.0,    0.0 },
+      {  0,  0,  2,  2,  1,      -7.0,    0.0,      3.0,    0.0 },
+      {  1,  0,  2, -2,  1,       6.0,    0.0,     -3.0,    0.0 },
+      {  0,  0,  0, -2,  1,      -5.0,    0.0,      3.0,    0.0 },
+
+   /* 61-70 */
+      {  1, -1,  0,  0,  0,       5.0,    0.0,      0.0,    0.0 },
+      {  2,  0,  2,  0,  1,      -5.0,    0.0,      3.0,    0.0 },
+      {  0,  1,  0, -2,  0,      -4.0,    0.0,      0.0,    0.0 },
+      {  1,  0, -2,  0,  0,       4.0,    0.0,      0.0,    0.0 },
+      {  0,  0,  0,  1,  0,      -4.0,    0.0,      0.0,    0.0 },
+      {  1,  1,  0,  0,  0,      -3.0,    0.0,      0.0,    0.0 },
+      {  1,  0,  2,  0,  0,       3.0,    0.0,      0.0,    0.0 },
+      {  1, -1,  2,  0,  2,      -3.0,    0.0,      1.0,    0.0 },
+      { -1, -1,  2,  2,  2,      -3.0,    0.0,      1.0,    0.0 },
+      { -2,  0,  0,  0,  1,      -2.0,    0.0,      1.0,    0.0 },
+
+   /* 71-80 */
+      {  3,  0,  2,  0,  2,      -3.0,    0.0,      1.0,    0.0 },
+      {  0, -1,  2,  2,  2,      -3.0,    0.0,      1.0,    0.0 },
+      {  1,  1,  2,  0,  2,       2.0,    0.0,     -1.0,    0.0 },
+      { -1,  0,  2, -2,  1,      -2.0,    0.0,      1.0,    0.0 },
+      {  2,  0,  0,  0,  1,       2.0,    0.0,     -1.0,    0.0 },
+      {  1,  0,  0,  0,  2,      -2.0,    0.0,      1.0,    0.0 },
+      {  3,  0,  0,  0,  0,       2.0,    0.0,      0.0,    0.0 },
+      {  0,  0,  2,  1,  2,       2.0,    0.0,     -1.0,    0.0 },
+      { -1,  0,  0,  0,  2,       1.0,    0.0,     -1.0,    0.0 },
+      {  1,  0,  0, -4,  0,      -1.0,    0.0,      0.0,    0.0 },
+
+   /* 81-90 */
+      { -2,  0,  2,  2,  2,       1.0,    0.0,     -1.0,    0.0 },
+      { -1,  0,  2,  4,  2,      -2.0,    0.0,      1.0,    0.0 },
+      {  2,  0,  0, -4,  0,      -1.0,    0.0,      0.0,    0.0 },
+      {  1,  1,  2, -2,  2,       1.0,    0.0,     -1.0,    0.0 },
+      {  1,  0,  2,  2,  1,      -1.0,    0.0,      1.0,    0.0 },
+      { -2,  0,  2,  4,  2,      -1.0,    0.0,      1.0,    0.0 },
+      { -1,  0,  4,  0,  2,       1.0,    0.0,      0.0,    0.0 },
+      {  1, -1,  0, -2,  0,       1.0,    0.0,      0.0,    0.0 },
+      {  2,  0,  2, -2,  1,       1.0,    0.0,     -1.0,    0.0 },
+      {  2,  0,  2,  2,  2,      -1.0,    0.0,      0.0,    0.0 },
+
+   /* 91-100 */
+      {  1,  0,  0,  2,  1,      -1.0,    0.0,      0.0,    0.0 },
+      {  0,  0,  4, -2,  2,       1.0,    0.0,      0.0,    0.0 },
+      {  3,  0,  2, -2,  2,       1.0,    0.0,      0.0,    0.0 },
+      {  1,  0,  2, -2,  0,      -1.0,    0.0,      0.0,    0.0 },
+      {  0,  1,  2,  0,  1,       1.0,    0.0,      0.0,    0.0 },
+      { -1, -1,  0,  2,  1,       1.0,    0.0,      0.0,    0.0 },
+      {  0,  0, -2,  0,  1,      -1.0,    0.0,      0.0,    0.0 },
+      {  0,  0,  2, -1,  2,      -1.0,    0.0,      0.0,    0.0 },
+      {  0,  1,  0,  2,  0,      -1.0,    0.0,      0.0,    0.0 },
+      {  1,  0, -2, -2,  0,      -1.0,    0.0,      0.0,    0.0 },
+
+   /* 101-106 */
+      {  0, -1,  2,  0,  1,      -1.0,    0.0,      0.0,    0.0 },
+      {  1,  1,  0, -2,  1,      -1.0,    0.0,      0.0,    0.0 },
+      {  1,  0, -2,  2,  0,      -1.0,    0.0,      0.0,    0.0 },
+      {  2,  0,  0,  2,  0,       1.0,    0.0,      0.0,    0.0 },
+      {  0,  0,  2,  4,  2,      -1.0,    0.0,      0.0,    0.0 },
+      {  0,  1,  0,  1,  0,       1.0,    0.0,      0.0,    0.0 }
+   };
+
+/* Number of terms in the series */
+   const int NT = (int) (sizeof x / sizeof x[0]);
+
+/*--------------------------------------------------------------------*/
+
+/* Interval between fundamental epoch J2000.0 and given date (JC). */
+   t = ((date1 - DJ00) + date2) / DJC;
+
+/* --------------------- */
+/* Fundamental arguments */
+/* --------------------- */
+
+/* Mean longitude of Moon minus mean longitude of Moon's perigee. */
+   el = iauAnpm(
+        (485866.733 + (715922.633 + (31.310 + 0.064 * t) * t) * t)
+        * DAS2R + fmod(1325.0 * t, 1.0) * D2PI);
+
+/* Mean longitude of Sun minus mean longitude of Sun's perigee. */
+   elp = iauAnpm(
+         (1287099.804 + (1292581.224 + (-0.577 - 0.012 * t) * t) * t)
+         * DAS2R + fmod(99.0 * t, 1.0) * D2PI);
+
+/* Mean longitude of Moon minus mean longitude of Moon's node. */
+   f = iauAnpm(
+       (335778.877 + (295263.137 + (-13.257 + 0.011 * t) * t) * t)
+       * DAS2R + fmod(1342.0 * t, 1.0) * D2PI);
+
+/* Mean elongation of Moon from Sun. */
+   d = iauAnpm(
+       (1072261.307 + (1105601.328 + (-6.891 + 0.019 * t) * t) * t)
+       * DAS2R + fmod(1236.0 * t, 1.0) * D2PI);
+
+/* Longitude of the mean ascending node of the lunar orbit on the */
+/* ecliptic, measured from the mean equinox of date. */
+   om = iauAnpm(
+        (450160.280 + (-482890.539 + (7.455 + 0.008 * t) * t) * t)
+        * DAS2R + fmod(-5.0 * t, 1.0) * D2PI);
+
+/* --------------- */
+/* Nutation series */
+/* --------------- */
+
+/* Initialize nutation components. */
+   dp = 0.0;
+   de = 0.0;
+
+/* Sum the nutation terms, ending with the biggest. */
+   for (j = NT-1; j >= 0; j--) {
+
+   /* Form argument for current term. */
+      arg = (double)x[j].nl  * el
+          + (double)x[j].nlp * elp
+          + (double)x[j].nf  * f
+          + (double)x[j].nd  * d
+          + (double)x[j].nom * om;
+
+   /* Accumulate current nutation term. */
+      s = x[j].sp + x[j].spt * t;
+      c = x[j].ce + x[j].cet * t;
+      if (s != 0.0) dp += s * sin(arg);
+      if (c != 0.0) de += c * cos(arg);
+   }
+
+/* Convert results from 0.1 mas units to radians. */
+   *dpsi = dp * U2R;
+   *deps = de * U2R;
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauNutm80(double date1, double date2, double rmatn[3][3])
+/*
+**  - - - - - - - - - -
+**   i a u N u t m 8 0
+**  - - - - - - - - - -
+**
+**  Form the matrix of nutation for a given date, IAU 1980 model.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     date1,date2    double          TDB date (Note 1)
+**
+**  Returned:
+**     rmatn          double[3][3]    nutation matrix
+**
+**  Notes:
+**
+**  1) The TT date date1+date2 is a Julian Date, apportioned in any
+**     convenient way between the two arguments.  For example,
+**     JD(TT)=2450123.7 could be expressed in any of these ways,
+**     among others:
+**
+**            date1          date2
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in
+**     cases where the loss of several decimal digits of resolution
+**     is acceptable.  The J2000 method is best matched to the way
+**     the argument is handled internally and will deliver the
+**     optimum resolution.  The MJD method and the date & time methods
+**     are both good compromises between resolution and convenience.
+**
+**  2) The matrix operates in the sense V(true) = rmatn * V(mean),
+**     where the p-vector V(true) is with respect to the true
+**     equatorial triad of date and the p-vector V(mean) is with
+**     respect to the mean equatorial triad of date.
+**
+**  Called:
+**     iauNut80     nutation, IAU 1980
+**     iauObl80     mean obliquity, IAU 1980
+**     iauNumat     form nutation matrix
+**
+**  This revision:  2008 May 12
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double dpsi, deps, epsa;
+
+
+/* Nutation components and mean obliquity. */
+   iauNut80(date1, date2, &dpsi, &deps);
+   epsa = iauObl80(date1, date2);
+
+/* Build the rotation matrix. */
+   iauNumat(epsa, dpsi, deps, rmatn);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+double iauObl06(double date1, double date2)
+/*
+**  - - - - - - - - -
+**   i a u O b l 0 6
+**  - - - - - - - - -
+**
+**  Mean obliquity of the ecliptic, IAU 2006 precession model.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  canonical model.
+**
+**  Given:
+**     date1,date2  double   TT as a 2-part Julian Date (Note 1)
+**
+**  Returned (function value):
+**                  double   obliquity of the ecliptic (radians, Note 2)
+**
+**  Notes:
+**
+**  1) The TT date date1+date2 is a Julian Date, apportioned in any
+**     convenient way between the two arguments.  For example,
+**     JD(TT)=2450123.7 could be expressed in any of these ways,
+**     among others:
+**
+**            date1          date2
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in
+**     cases where the loss of several decimal digits of resolution
+**     is acceptable.  The J2000 method is best matched to the way
+**     the argument is handled internally and will deliver the
+**     optimum resolution.  The MJD method and the date & time methods
+**     are both good compromises between resolution and convenience.
+**
+**  2) The result is the angle between the ecliptic and mean equator of
+**     date date1+date2.
+**
+**  Reference:
+**
+**     Hilton, J. et al., 2006, Celest.Mech.Dyn.Astron. 94, 351
+**
+**  This revision:  2009 March 16
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double t, eps0;
+
+
+/* Interval between fundamental date J2000.0 and given date (JC). */
+   t = ((date1 - DJ00) + date2) / DJC;
+
+/* Mean obliquity. */
+   eps0 = (84381.406     +
+          (-46.836769    +
+          ( -0.0001831   +
+          (  0.00200340  +
+          ( -0.000000576 +
+          ( -0.0000000434) * t) * t) * t) * t) * t) * DAS2R;
+
+   return eps0;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+double iauObl80(double date1, double date2)
+/*
+**  - - - - - - - - -
+**   i a u O b l 8 0
+**  - - - - - - - - -
+**
+**  Mean obliquity of the ecliptic, IAU 1980 model.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  canonical model.
+**
+**  Given:
+**     date1,date2   double    TT as a 2-part Julian Date (Note 1)
+**
+**  Returned (function value):
+**                   double    obliquity of the ecliptic (radians, Note 2)
+**
+**  Notes:
+**
+**  1) The TT date date1+date2 is a Julian Date, apportioned in any
+**     convenient way between the two arguments.  For example,
+**     JD(TT)=2450123.7 could be expressed in any of these ways,
+**     among others:
+**
+**            date1          date2
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in
+**     cases where the loss of several decimal digits of resolution
+**     is acceptable.  The J2000 method is best matched to the way
+**     the argument is handled internally and will deliver the
+**     optimum resolution.  The MJD method and the date & time methods
+**     are both good compromises between resolution and convenience.
+**
+**  2) The result is the angle between the ecliptic and mean equator of
+**     date date1+date2.
+**
+**  Reference:
+**
+**     Explanatory Supplement to the Astronomical Almanac,
+**     P. Kenneth Seidelmann (ed), University Science Books (1992),
+**     Expression 3.222-1 (p114).
+**
+**  This revision:  2009 March 16
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double t, eps0;
+
+
+/* Interval between fundamental epoch J2000.0 and given date (JC). */
+   t = ((date1 - DJ00) + date2) / DJC;
+
+/* Mean obliquity of date. */
+   eps0 = DAS2R * (84381.448  +
+                  (-46.8150   +
+                  (-0.00059   +
+                  ( 0.001813) * t) * t) * t);
+
+   return eps0;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauP06e(double date1, double date2,
+             double *eps0, double *psia, double *oma, double *bpa,
+             double *bqa, double *pia, double *bpia,
+             double *epsa, double *chia, double *za, double *zetaa,
+             double *thetaa, double *pa,
+             double *gam, double *phi, double *psi)
+/*
+**  - - - - - - - -
+**   i a u P 0 6 e
+**  - - - - - - - -
+**
+**  Precession angles, IAU 2006, equinox based.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  canonical models.
+**
+**  Given:
+**     date1,date2   double   TT as a 2-part Julian Date (Note 1)
+**
+**  Returned (see Note 2):
+**     eps0          double   epsilon_0
+**     psia          double   psi_A
+**     oma           double   omega_A
+**     bpa           double   P_A
+**     bqa           double   Q_A
+**     pia           double   pi_A
+**     bpia          double   Pi_A
+**     epsa          double   obliquity epsilon_A
+**     chia          double   chi_A
+**     za            double   z_A
+**     zetaa         double   zeta_A
+**     thetaa        double   theta_A
+**     pa            double   p_A
+**     gam           double   F-W angle gamma_J2000
+**     phi           double   F-W angle phi_J2000
+**     psi           double   F-W angle psi_J2000
+**
+**  Notes:
+**
+**  1) The TT date date1+date2 is a Julian Date, apportioned in any
+**     convenient way between the two arguments.  For example,
+**     JD(TT)=2450123.7 could be expressed in any of these ways,
+**     among others:
+**
+**            date1          date2
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in
+**     cases where the loss of several decimal digits of resolution
+**     is acceptable.  The J2000 method is best matched to the way
+**     the argument is handled internally and will deliver the
+**     optimum resolution.  The MJD method and the date & time methods
+**     are both good compromises between resolution and convenience.
+**
+**  2) This function returns the set of equinox based angles for the
+**     Capitaine et al. "P03" precession theory, adopted by the IAU in
+**     2006.  The angles are set out in Table 1 of Hilton et al. (2006):
+**
+**     eps0   epsilon_0   obliquity at J2000.0
+**     psia   psi_A       luni-solar precession
+**     oma    omega_A     inclination of equator wrt J2000.0 ecliptic
+**     bpa    P_A         ecliptic pole x, J2000.0 ecliptic triad
+**     bqa    Q_A         ecliptic pole -y, J2000.0 ecliptic triad
+**     pia    pi_A        angle between moving and J2000.0 ecliptics
+**     bpia   Pi_A        longitude of ascending node of the ecliptic
+**     epsa   epsilon_A   obliquity of the ecliptic
+**     chia   chi_A       planetary precession
+**     za     z_A         equatorial precession: -3rd 323 Euler angle
+**     zetaa  zeta_A      equatorial precession: -1st 323 Euler angle
+**     thetaa theta_A     equatorial precession: 2nd 323 Euler angle
+**     pa     p_A         general precession
+**     gam    gamma_J2000 J2000.0 RA difference of ecliptic poles
+**     phi    phi_J2000   J2000.0 codeclination of ecliptic pole
+**     psi    psi_J2000   longitude difference of equator poles, J2000.0
+**
+**     The returned values are all radians.
+**
+**  3) Hilton et al. (2006) Table 1 also contains angles that depend on
+**     models distinct from the P03 precession theory itself, namely the
+**     IAU 2000A frame bias and nutation.  The quoted polynomials are
+**     used in other SOFA functions:
+**
+**     . iauXy06  contains the polynomial parts of the X and Y series.
+**
+**     . iauS06  contains the polynomial part of the s+XY/2 series.
+**
+**     . iauPfw06  implements the series for the Fukushima-Williams
+**       angles that are with respect to the GCRS pole (i.e. the variants
+**       that include frame bias).
+**
+**  4) The IAU resolution stipulated that the choice of parameterization
+**     was left to the user, and so an IAU compliant precession
+**     implementation can be constructed using various combinations of
+**     the angles returned by the present function.
+**
+**  5) The parameterization used by SOFA is the version of the Fukushima-
+**     Williams angles that refers directly to the GCRS pole.  These
+**     angles may be calculated by calling the function iauPfw06.  SOFA
+**     also supports the direct computation of the CIP GCRS X,Y by
+**     series, available by calling iauXy06.
+**
+**  6) The agreement between the different parameterizations is at the
+**     1 microarcsecond level in the present era.
+**
+**  7) When constructing a precession formulation that refers to the GCRS
+**     pole rather than the dynamical pole, it may (depending on the
+**     choice of angles) be necessary to introduce the frame bias
+**     explicitly.
+**
+**  8) It is permissible to re-use the same variable in the returned
+**     arguments.  The quantities are stored in the stated order.
+**
+**  Reference:
+**
+**     Hilton, J. et al., 2006, Celest.Mech.Dyn.Astron. 94, 351
+**
+**  Called:
+**     iauObl06     mean obliquity, IAU 2006
+**
+**  This revision:  2011 December 6
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double t;
+
+
+/* Interval between fundamental date J2000.0 and given date (JC). */
+   t = ((date1 - DJ00) + date2) / DJC;
+
+/* Obliquity at J2000.0. */
+
+   *eps0 = 84381.406 * DAS2R;
+
+/* Luni-solar precession. */
+
+   *psia = ( 5038.481507     +
+           (   -1.0790069    +
+           (   -0.00114045   +
+           (    0.000132851  +
+           (   -0.0000000951 )
+           * t) * t) * t) * t) * t * DAS2R;
+
+/* Inclination of mean equator with respect to the J2000.0 ecliptic. */
+
+   *oma = *eps0 + ( -0.025754     +
+                  (  0.0512623    +
+                  ( -0.00772503   +
+                  ( -0.000000467  +
+                  (  0.0000003337 )
+                  * t) * t) * t) * t) * t * DAS2R;
+
+/* Ecliptic pole x, J2000.0 ecliptic triad. */
+
+   *bpa = (  4.199094     +
+          (  0.1939873    +
+          ( -0.00022466   +
+          ( -0.000000912  +
+          (  0.0000000120 )
+          * t) * t) * t) * t) * t * DAS2R;
+
+/* Ecliptic pole -y, J2000.0 ecliptic triad. */
+
+   *bqa = ( -46.811015     +
+          (   0.0510283    +
+          (   0.00052413   +
+          (  -0.000000646  +
+          (  -0.0000000172 )
+          * t) * t) * t) * t) * t * DAS2R;
+
+/* Angle between moving and J2000.0 ecliptics. */
+
+   *pia = ( 46.998973     +
+          ( -0.0334926    +
+          ( -0.00012559   +
+          (  0.000000113  +
+          ( -0.0000000022 )
+          * t) * t) * t) * t) * t * DAS2R;
+
+/* Longitude of ascending node of the moving ecliptic. */
+
+   *bpia = ( 629546.7936      +
+           (   -867.95758     +
+           (      0.157992    +
+           (     -0.0005371   +
+           (     -0.00004797  +
+           (      0.000000072 )
+           * t) * t) * t) * t) * t) * DAS2R;
+
+/* Mean obliquity of the ecliptic. */
+
+   *epsa = iauObl06(date1, date2);
+
+/* Planetary precession. */
+
+   *chia = ( 10.556403     +
+           ( -2.3814292    +
+           ( -0.00121197   +
+           (  0.000170663  +
+           ( -0.0000000560 )
+           * t) * t) * t) * t) * t * DAS2R;
+
+/* Equatorial precession: minus the third of the 323 Euler angles. */
+
+   *za = (   -2.650545     +
+         ( 2306.077181     +
+         (    1.0927348    +
+         (    0.01826837   +
+         (   -0.000028596  +
+         (   -0.0000002904 )
+         * t) * t) * t) * t) * t) * DAS2R;
+
+/* Equatorial precession: minus the first of the 323 Euler angles. */
+
+   *zetaa = (    2.650545     +
+            ( 2306.083227     +
+            (    0.2988499    +
+            (    0.01801828   +
+            (   -0.000005971  +
+            (   -0.0000003173 )
+            * t) * t) * t) * t) * t) * DAS2R;
+
+/* Equatorial precession: second of the 323 Euler angles. */
+
+   *thetaa = ( 2004.191903     +
+             (   -0.4294934    +
+             (   -0.04182264   +
+             (   -0.000007089  +
+             (   -0.0000001274 )
+             * t) * t) * t) * t) * t * DAS2R;
+
+/* General precession. */
+
+   *pa = ( 5028.796195     +
+         (    1.1054348    +
+         (    0.00007964   +
+         (   -0.000023857  +
+         (    0.0000000383 )
+         * t) * t) * t) * t) * t * DAS2R;
+
+/* Fukushima-Williams angles for precession. */
+
+   *gam = ( 10.556403     +
+          (  0.4932044    +
+          ( -0.00031238   +
+          ( -0.000002788  +
+          (  0.0000000260 )
+          * t) * t) * t) * t) * t * DAS2R;
+
+   *phi = *eps0 + ( -46.811015     +
+                  (   0.0511269    +
+                  (   0.00053289   +
+                  (  -0.000000440  +
+                  (  -0.0000000176 )
+                  * t) * t) * t) * t) * t * DAS2R;
+
+   *psi = ( 5038.481507     +
+          (    1.5584176    +
+          (   -0.00018522   +
+          (   -0.000026452  +
+          (   -0.0000000148 )
+          * t) * t) * t) * t) * t * DAS2R;
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauP2pv(double p[3], double pv[2][3])
+/*
+**  - - - - - - - -
+**   i a u P 2 p v
+**  - - - - - - - -
+**
+**  Extend a p-vector to a pv-vector by appending a zero velocity.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  vector/matrix support function.
+**
+**  Given:
+**     p        double[3]       p-vector
+**
+**  Returned:
+**     pv       double[2][3]    pv-vector
+**
+**  Called:
+**     iauCp        copy p-vector
+**     iauZp        zero p-vector
+**
+**  This revision:  2008 May 11
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   iauCp(p, pv[0]);
+   iauZp(pv[1]);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauP2s(double p[3], double *theta, double *phi, double *r)
+/*
+**  - - - - - - -
+**   i a u P 2 s
+**  - - - - - - -
+**
+**  P-vector to spherical polar coordinates.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  vector/matrix support function.
+**
+**  Given:
+**     p        double[3]    p-vector
+**
+**  Returned:
+**     theta    double       longitude angle (radians)
+**     phi      double       latitude angle (radians)
+**     r        double       radial distance
+**
+**  Notes:
+**
+**  1) If P is null, zero theta, phi and r are returned.
+**
+**  2) At either pole, zero theta is returned.
+**
+**  Called:
+**     iauC2s       p-vector to spherical
+**     iauPm        modulus of p-vector
+**
+**  This revision:  2008 May 22
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   iauC2s(p, theta, phi);
+   *r = iauPm(p);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+double iauPap(double a[3], double b[3])
+/*
+**  - - - - - - -
+**   i a u P a p
+**  - - - - - - -
+**
+**  Position-angle from two p-vectors.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  vector/matrix support function.
+**
+**  Given:
+**     a      double[3]  direction of reference point
+**     b      double[3]  direction of point whose PA is required
+**
+**  Returned (function value):
+**            double     position angle of b with respect to a (radians)
+**
+**  Notes:
+**
+**  1) The result is the position angle, in radians, of direction b with
+**     respect to direction a.  It is in the range -pi to +pi.  The
+**     sense is such that if b is a small distance "north" of a the
+**     position angle is approximately zero, and if b is a small
+**     distance "east" of a the position angle is approximately +pi/2.
+**
+**  2) The vectors a and b need not be of unit length.
+**
+**  3) Zero is returned if the two directions are the same or if either
+**     vector is null.
+**
+**  4) If vector a is at a pole, the result is ill-defined.
+**
+**  Called:
+**     iauPn        decompose p-vector into modulus and direction
+**     iauPm        modulus of p-vector
+**     iauPxp       vector product of two p-vectors
+**     iauPmp       p-vector minus p-vector
+**     iauPdp       scalar product of two p-vectors
+**
+**  This revision:  2008 May 25
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double am, au[3], bm, st, ct, xa, ya, za, eta[3], xi[3], a2b[3], pa;
+
+
+/* Modulus and direction of the a vector. */
+   iauPn(a, &am, au);
+
+/* Modulus of the b vector. */
+   bm = iauPm(b);
+
+/* Deal with the case of a null vector. */
+   if ((am == 0.0) || (bm == 0.0)) {
+      st = 0.0;
+      ct = 1.0;
+   } else {
+
+   /* The "north" axis tangential from a (arbitrary length). */
+      xa = a[0];
+      ya = a[1];
+      za = a[2];
+      eta[0] = -xa * za;
+      eta[1] = -ya * za;
+      eta[2] =  xa*xa + ya*ya;
+
+   /* The "east" axis tangential from a (same length). */
+      iauPxp(eta, au, xi);
+
+   /* The vector from a to b. */
+      iauPmp(b, a, a2b);
+
+   /* Resolve into components along the north and east axes. */
+      st = iauPdp(a2b, xi);
+      ct = iauPdp(a2b, eta);
+
+   /* Deal with degenerate cases. */
+      if ((st == 0.0) && (ct == 0.0)) ct = 1.0;
+   }
+
+/* Position angle. */
+   pa = atan2(st, ct);
+
+   return pa;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+double iauPas(double al, double ap, double bl, double bp)
+/*
+**  - - - - - - -
+**   i a u P a s
+**  - - - - - - -
+**
+**  Position-angle from spherical coordinates.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  vector/matrix support function.
+**
+**  Given:
+**     al     double     longitude of point A (e.g. RA) in radians
+**     ap     double     latitude of point A (e.g. Dec) in radians
+**     bl     double     longitude of point B
+**     bp     double     latitude of point B
+**
+**  Returned (function value):
+**            double     position angle of B with respect to A
+**
+**  Notes:
+**
+**  1) The result is the bearing (position angle), in radians, of point
+**     B with respect to point A.  It is in the range -pi to +pi.  The
+**     sense is such that if B is a small distance "east" of point A,
+**     the bearing is approximately +pi/2.
+**
+**  2) Zero is returned if the two points are coincident.
+**
+**  This revision:  2008 May 22
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double dl, x, y, pa;
+
+
+   dl = bl - al;
+   y = sin(dl) * cos(bp);
+   x = sin(bp) * cos(ap) - cos(bp) * sin(ap) * cos(dl);
+   pa = ((x != 0.0) || (y != 0.0)) ? atan2(y, x) : 0.0;
+
+   return pa;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauPb06(double date1, double date2,
+             double *bzeta, double *bz, double *btheta)
+/*
+**  - - - - - - - -
+**   i a u P b 0 6
+**  - - - - - - - -
+**
+**  This function forms three Euler angles which implement general
+**  precession from epoch J2000.0, using the IAU 2006 model.  Frame
+**  bias (the offset between ICRS and mean J2000.0) is included.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     date1,date2  double   TT as a 2-part Julian Date (Note 1)
+**
+**  Returned:
+**     bzeta        double   1st rotation: radians cw around z
+**     bz           double   3rd rotation: radians cw around z
+**     btheta       double   2nd rotation: radians ccw around y
+**
+**  Notes:
+**
+**  1) The TT date date1+date2 is a Julian Date, apportioned in any
+**     convenient way between the two arguments.  For example,
+**     JD(TT)=2450123.7 could be expressed in any of these ways,
+**     among others:
+**
+**            date1          date2
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in
+**     cases where the loss of several decimal digits of resolution
+**     is acceptable.  The J2000 method is best matched to the way
+**     the argument is handled internally and will deliver the
+**     optimum resolution.  The MJD method and the date & time methods
+**     are both good compromises between resolution and convenience.
+**
+**  2) The traditional accumulated precession angles zeta_A, z_A,
+**     theta_A cannot be obtained in the usual way, namely through
+**     polynomial expressions, because of the frame bias.  The latter
+**     means that two of the angles undergo rapid changes near this
+**     date.  They are instead the results of decomposing the
+**     precession-bias matrix obtained by using the Fukushima-Williams
+**     method, which does not suffer from the problem.  The
+**     decomposition returns values which can be used in the
+**     conventional formulation and which include frame bias.
+**
+**  3) The three angles are returned in the conventional order, which
+**     is not the same as the order of the corresponding Euler
+**     rotations.  The precession-bias matrix is
+**     R_3(-z) x R_2(+theta) x R_3(-zeta).
+**
+**  4) Should zeta_A, z_A, theta_A angles be required that do not
+**     contain frame bias, they are available by calling the SOFA
+**     function iauP06e.
+**
+**  Called:
+**     iauPmat06    PB matrix, IAU 2006
+**     iauRz        rotate around Z-axis
+**
+**  This revision:  2008 May 26
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double r[3][3], r31, r32;
+
+
+/* Precession matrix via Fukushima-Williams angles. */
+   iauPmat06(date1, date2, r);
+
+/* Solve for z. */
+   *bz = atan2(r[1][2], r[0][2]);
+
+/* Remove it from the matrix. */
+   iauRz(*bz, r);
+
+/* Solve for the remaining two angles. */
+   *bzeta = atan2 (r[1][0], r[1][1]);
+   r31 = r[2][0];
+   r32 = r[2][1];
+   *btheta = atan2(-dsign(sqrt(r31 * r31 + r32 * r32), r[0][2]),
+                   r[2][2]);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+double iauPdp(double a[3], double b[3])
+/*
+**  - - - - - - -
+**   i a u P d p
+**  - - - - - - -
+**
+**  p-vector inner (=scalar=dot) product.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  vector/matrix support function.
+**
+**  Given:
+**     a      double[3]     first p-vector
+**     b      double[3]     second p-vector
+**
+**  Returned (function value):
+**            double        a . b
+**
+**  This revision:  2008 May 22
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double w;
+
+
+   w  = a[0] * b[0]
+      + a[1] * b[1]
+      + a[2] * b[2];
+
+   return w;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauPfw06(double date1, double date2,
+              double *gamb, double *phib, double *psib, double *epsa)
+/*
+**  - - - - - - - - -
+**   i a u P f w 0 6
+**  - - - - - - - - -
+**
+**  Precession angles, IAU 2006 (Fukushima-Williams 4-angle formulation).
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  canonical model.
+**
+**  Given:
+**     date1,date2  double   TT as a 2-part Julian Date (Note 1)
+**
+**  Returned:
+**     gamb         double   F-W angle gamma_bar (radians)
+**     phib         double   F-W angle phi_bar (radians)
+**     psib         double   F-W angle psi_bar (radians)
+**     epsa         double   F-W angle epsilon_A (radians)
+**
+**  Notes:
+**
+**  1) The TT date date1+date2 is a Julian Date, apportioned in any
+**     convenient way between the two arguments.  For example,
+**     JD(TT)=2450123.7 could be expressed in any of these ways,
+**     among others:
+**
+**            date1          date2
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in
+**     cases where the loss of several decimal digits of resolution
+**     is acceptable.  The J2000 method is best matched to the way
+**     the argument is handled internally and will deliver the
+**     optimum resolution.  The MJD method and the date & time methods
+**     are both good compromises between resolution and convenience.
+**
+**  2) Naming the following points:
+**
+**           e = J2000.0 ecliptic pole,
+**           p = GCRS pole,
+**           E = mean ecliptic pole of date,
+**     and   P = mean pole of date,
+**
+**     the four Fukushima-Williams angles are as follows:
+**
+**        gamb = gamma_bar = epE
+**        phib = phi_bar = pE
+**        psib = psi_bar = pEP
+**        epsa = epsilon_A = EP
+**
+**  3) The matrix representing the combined effects of frame bias and
+**     precession is:
+**
+**        PxB = R_1(-epsa).R_3(-psib).R_1(phib).R_3(gamb)
+**
+**  4) The matrix representing the combined effects of frame bias,
+**     precession and nutation is simply:
+**
+**        NxPxB = R_1(-epsa-dE).R_3(-psib-dP).R_1(phib).R_3(gamb)
+**
+**     where dP and dE are the nutation components with respect to the
+**     ecliptic of date.
+**
+**  Reference:
+**
+**     Hilton, J. et al., 2006, Celest.Mech.Dyn.Astron. 94, 351
+**
+**  Called:
+**     iauObl06     mean obliquity, IAU 2006
+**
+**  This revision:  2009 December 17
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double t;
+
+
+/* Interval between fundamental date J2000.0 and given date (JC). */
+   t = ((date1 - DJ00) + date2) / DJC;
+
+/* P03 bias+precession angles. */
+   *gamb = (    -0.052928     +
+           (    10.556378     +
+           (     0.4932044    +
+           (    -0.00031238   +
+           (    -0.000002788  +
+           (     0.0000000260 )
+           * t) * t) * t) * t) * t) * DAS2R;
+   *phib = ( 84381.412819     +
+           (   -46.811016     +
+           (     0.0511268    +
+           (     0.00053289   +
+           (    -0.000000440  +
+           (    -0.0000000176 )
+           * t) * t) * t) * t) * t) * DAS2R;
+   *psib = (    -0.041775     +
+           (  5038.481484     +
+           (     1.5584175    +
+           (    -0.00018522   +
+           (    -0.000026452  +
+           (    -0.0000000148 )
+           * t) * t) * t) * t) * t) * DAS2R;
+   *epsa =  iauObl06(date1, date2);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+int iauPlan94(double date1, double date2, int np, double pv[2][3])
+/*
+**  - - - - - - - - - -
+**   i a u P l a n 9 4
+**  - - - - - - - - - -
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Approximate heliocentric position and velocity of a nominated major
+**  planet:  Mercury, Venus, EMB, Mars, Jupiter, Saturn, Uranus or
+**  Neptune (but not the Earth itself).
+**
+**  Given:
+**     date1  double       TDB date part A (Note 1)
+**     date2  double       TDB date part B (Note 1)
+**     np     int          planet (1=Mercury, 2=Venus, 3=EMB, 4=Mars,
+**                             5=Jupiter, 6=Saturn, 7=Uranus, 8=Neptune)
+**
+**  Returned (argument):
+**     pv     double[3][2] planet p,v (heliocentric, J2000.0, AU,AU/d)
+**
+**  Returned (function value):
+**            int          status: -1 = illegal NP (outside 1-8)
+**                                  0 = OK
+**                                 +1 = warning: year outside 1000-3000
+**                                 +2 = warning: failed to converge
+**
+**  Notes:
+**
+**  1) The date date1+date2 is in the TDB time scale (in practice TT can
+**     be used) and is a Julian Date, apportioned in any convenient way
+**     between the two arguments.  For example, JD(TDB)=2450123.7 could
+**     be expressed in any of these ways, among others:
+**
+**            date1          date2
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in cases
+**     where the loss of several decimal digits of resolution is
+**     acceptable.  The J2000 method is best matched to the way the
+**     argument is handled internally and will deliver the optimum
+**     resolution.  The MJD method and the date & time methods are both
+**     good compromises between resolution and convenience.  The limited
+**     accuracy of the present algorithm is such that any of the methods
+**     is satisfactory.
+**
+**  2) If an np value outside the range 1-8 is supplied, an error status
+**     (function value -1) is returned and the pv vector set to zeroes.
+**
+**  3) For np=3 the result is for the Earth-Moon Barycenter.  To obtain
+**     the heliocentric position and velocity of the Earth, use instead
+**     the SOFA function iauEpv00.
+**
+**  4) On successful return, the array pv contains the following:
+**
+**        pv[0][0]   x      }
+**        pv[1][0]   y      } heliocentric position, AU
+**        pv[2][0]   z      }
+**
+**        pv[0][1]   xdot   }
+**        pv[1][1]   ydot   } heliocentric velocity, AU/d
+**        pv[2][1]   zdot   }
+**
+**     The reference frame is equatorial and is with respect to the
+**     mean equator and equinox of epoch J2000.0.
+**
+**  5) The algorithm is due to J.L. Simon, P. Bretagnon, J. Chapront,
+**     M. Chapront-Touze, G. Francou and J. Laskar (Bureau des
+**     Longitudes, Paris, France).  From comparisons with JPL
+**     ephemeris DE102, they quote the following maximum errors
+**     over the interval 1800-2050:
+**
+**                     L (arcsec)    B (arcsec)      R (km)
+**
+**        Mercury          4             1             300
+**        Venus            5             1             800
+**        EMB              6             1            1000
+**        Mars            17             1            7700
+**        Jupiter         71             5           76000
+**        Saturn          81            13          267000
+**        Uranus          86             7          712000
+**        Neptune         11             1          253000
+**
+**     Over the interval 1000-3000, they report that the accuracy is no
+**     worse than 1.5 times that over 1800-2050.  Outside 1000-3000 the
+**     accuracy declines.
+**
+**     Comparisons of the present function with the JPL DE200 ephemeris
+**     give the following RMS errors over the interval 1960-2025:
+**
+**                      position (km)     velocity (m/s)
+**
+**        Mercury            334               0.437
+**        Venus             1060               0.855
+**        EMB               2010               0.815
+**        Mars              7690               1.98
+**        Jupiter          71700               7.70
+**        Saturn          199000              19.4
+**        Uranus          564000              16.4
+**        Neptune         158000              14.4
+**
+**     Comparisons against DE200 over the interval 1800-2100 gave the
+**     following maximum absolute differences.  (The results using
+**     DE406 were essentially the same.)
+**
+**                   L (arcsec)   B (arcsec)     R (km)   Rdot (m/s)
+**
+**        Mercury        7            1            500       0.7
+**        Venus          7            1           1100       0.9
+**        EMB            9            1           1300       1.0
+**        Mars          26            1           9000       2.5
+**        Jupiter       78            6          82000       8.2
+**        Saturn        87           14         263000      24.6
+**        Uranus        86            7         661000      27.4
+**        Neptune       11            2         248000      21.4
+**
+**  6) The present SOFA re-implementation of the original Simon et al.
+**     Fortran code differs from the original in the following respects:
+**
+**       *  C instead of Fortran.
+**
+**       *  The date is supplied in two parts.
+**
+**       *  The result is returned only in equatorial Cartesian form;
+**          the ecliptic longitude, latitude and radius vector are not
+**          returned.
+**
+**       *  The result is in the J2000.0 equatorial frame, not ecliptic.
+**
+**       *  More is done in-line: there are fewer calls to subroutines.
+**
+**       *  Different error/warning status values are used.
+**
+**       *  A different Kepler's-equation-solver is used (avoiding
+**          use of double precision complex).
+**
+**       *  Polynomials in t are nested to minimize rounding errors.
+**
+**       *  Explicit double constants are used to avoid mixed-mode
+**          expressions.
+**
+**     None of the above changes affects the result significantly.
+**
+**  7) The returned status indicates the most serious condition
+**     encountered during execution of the function.  Illegal np is
+**     considered the most serious, overriding failure to converge,
+**     which in turn takes precedence over the remote date warning.
+**
+**  Called:
+**     iauAnp       normalize angle into range 0 to 2pi
+**
+**  Reference:  Simon, J.L, Bretagnon, P., Chapront, J.,
+**              Chapront-Touze, M., Francou, G., and Laskar, J.,
+**              Astron. Astrophys. 282, 663 (1994).
+**
+**  This revision:  2009 December 17
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+/* Gaussian constant */
+   static const double GK = 0.017202098950;
+
+/* Sin and cos of J2000.0 mean obliquity (IAU 1976) */
+   static const double SINEPS = 0.3977771559319137;
+   static const double COSEPS = 0.9174820620691818;
+
+/* Maximum number of iterations allowed to solve Kepler's equation */
+   static const int KMAX = 10;
+
+   int jstat, i, k;
+   double t, da, dl, de, dp, di, dom, dmu, arga, argl, am,
+          ae, dae, ae2, at, r, v, si2, xq, xp, tl, xsw,
+          xcw, xm2, xf, ci2, xms, xmc, xpxq2, x, y, z;
+
+/* Planetary inverse masses */
+   static const double amas[] = { 6023600.0,       /* Mercury */
+                                   408523.5,       /* Venus   */
+                                   328900.5,       /* EMB     */
+                                  3098710.0,       /* Mars    */
+                                     1047.355,     /* Jupiter */
+                                     3498.5,       /* Saturn  */
+                                    22869.0,       /* Uranus  */
+                                    19314.0 };     /* Neptune */
+
+/*
+** Tables giving the mean Keplerian elements, limited to t^2 terms:
+**
+**   a       semi-major axis (AU)
+**   dlm     mean longitude (degree and arcsecond)
+**   e       eccentricity
+**   pi      longitude of the perihelion (degree and arcsecond)
+**   dinc    inclination (degree and arcsecond)
+**   omega   longitude of the ascending node (degree and arcsecond)
+*/
+
+   static const double a[][3] = {
+       {  0.3870983098,           0.0,     0.0 },  /* Mercury */
+       {  0.7233298200,           0.0,     0.0 },  /* Venus   */
+       {  1.0000010178,           0.0,     0.0 },  /* EMB     */
+       {  1.5236793419,         3e-10,     0.0 },  /* Mars    */
+       {  5.2026032092,     19132e-10, -39e-10 },  /* Jupiter */
+       {  9.5549091915, -0.0000213896, 444e-10 },  /* Saturn  */
+       { 19.2184460618,     -3716e-10, 979e-10 },  /* Uranus  */
+       { 30.1103868694,    -16635e-10, 686e-10 }   /* Neptune */
+   };
+
+   static const double dlm[][3] = {
+       { 252.25090552, 5381016286.88982,  -1.92789 },
+       { 181.97980085, 2106641364.33548,   0.59381 },
+       { 100.46645683, 1295977422.83429,  -2.04411 },
+       { 355.43299958,  689050774.93988,   0.94264 },
+       {  34.35151874,  109256603.77991, -30.60378 },
+       {  50.07744430,   43996098.55732,  75.61614 },
+       { 314.05500511,   15424811.93933,  -1.75083 },
+       { 304.34866548,    7865503.20744,   0.21103 }
+   };
+
+   static const double e[][3] = {
+       { 0.2056317526,  0.0002040653,    -28349e-10 },
+       { 0.0067719164, -0.0004776521,     98127e-10 },
+       { 0.0167086342, -0.0004203654, -0.0000126734 },
+       { 0.0934006477,  0.0009048438,    -80641e-10 },
+       { 0.0484979255,  0.0016322542, -0.0000471366 },
+       { 0.0555481426, -0.0034664062, -0.0000643639 },
+       { 0.0463812221, -0.0002729293,  0.0000078913 },
+       { 0.0094557470,  0.0000603263,           0.0 }
+   };
+
+   static const double pi[][3] = {
+       {  77.45611904,  5719.11590,   -4.83016 },
+       { 131.56370300,   175.48640, -498.48184 },
+       { 102.93734808, 11612.35290,   53.27577 },
+       { 336.06023395, 15980.45908,  -62.32800 },
+       {  14.33120687,  7758.75163,  259.95938 },
+       {  93.05723748, 20395.49439,  190.25952 },
+       { 173.00529106,  3215.56238,  -34.09288 },
+       {  48.12027554,  1050.71912,   27.39717 }
+   };
+
+   static const double dinc[][3] = {
+       { 7.00498625, -214.25629,   0.28977 },
+       { 3.39466189,  -30.84437, -11.67836 },
+       {        0.0,  469.97289,  -3.35053 },
+       { 1.84972648, -293.31722,  -8.11830 },
+       { 1.30326698,  -71.55890,  11.95297 },
+       { 2.48887878,   91.85195, -17.66225 },
+       { 0.77319689,  -60.72723,   1.25759 },
+       { 1.76995259,    8.12333,   0.08135 }
+   };
+
+   static const double omega[][3] = {
+       {  48.33089304,  -4515.21727,  -31.79892 },
+       {  76.67992019, -10008.48154,  -51.32614 },
+       { 174.87317577,  -8679.27034,   15.34191 },
+       {  49.55809321, -10620.90088, -230.57416 },
+       { 100.46440702,   6362.03561,  326.52178 },
+       { 113.66550252,  -9240.19942,  -66.23743 },
+       {  74.00595701,   2669.15033,  145.93964 },
+       { 131.78405702,   -221.94322,   -0.78728 }
+   };
+
+/* Tables for trigonometric terms to be added to the mean elements of */
+/* the semi-major axes */
+
+   static const double kp[][9] = {
+    {   69613, 75645, 88306, 59899, 15746, 71087, 142173,  3086,    0 },
+    {   21863, 32794, 26934, 10931, 26250, 43725,  53867, 28939,    0 },
+    {   16002, 21863, 32004, 10931, 14529, 16368,  15318, 32794,    0 },
+    {    6345,  7818, 15636,  7077,  8184, 14163,   1107,  4872,    0 },
+    {    1760,  1454,  1167,   880,   287,  2640,     19,  2047, 1454 },
+    {     574,     0,   880,   287,    19,  1760,   1167,   306,  574 },
+    {     204,     0,   177,  1265,     4,   385,    200,   208,  204 },
+    {       0,   102,   106,     4,    98,  1367,    487,   204,    0 }
+   };
+
+   static const double ca[][9] = {
+    {       4,    -13,    11,   -9,    -9,   -3,     -1,     4,     0 },
+    {    -156,     59,   -42,    6,    19,  -20,    -10,   -12,     0 },
+    {      64,   -152,    62,   -8,    32,  -41,     19,   -11,     0 },
+    {     124,    621,  -145,  208,    54,  -57,     30,    15,     0 },
+    {  -23437,  -2634,  6601, 6259, -1507,-1821,   2620, -2115, -1489 },
+    {   62911,-119919, 79336,17814,-24241,12068,   8306, -4893,  8902 },
+    {  389061,-262125,-44088, 8387,-22976,-2093,   -615, -9720,  6633 },
+    { -412235,-157046,-31430,37817, -9740,  -13,  -7449,  9644,     0 }
+   };
+
+   static const double sa[][9] = {
+    {     -29,    -1,     9,     6,    -6,     5,     4,     0,     0 },
+    {     -48,  -125,   -26,   -37,    18,   -13,   -20,    -2,     0 },
+    {    -150,   -46,    68,    54,    14,    24,   -28,    22,     0 },
+    {    -621,   532,  -694,   -20,   192,   -94,    71,   -73,     0 },
+    {  -14614,-19828, -5869,  1881, -4372, -2255,   782,   930,   913 },
+    {  139737,     0, 24667, 51123, -5102,  7429, -4095, -1976, -9566 },
+    { -138081,     0, 37205,-49039,-41901,-33872,-27037,-12474, 18797 },
+    {       0, 28492,133236, 69654, 52322,-49577,-26430, -3593,     0 }
+   };
+
+/* Tables giving the trigonometric terms to be added to the mean */
+/* elements of the mean longitudes */
+
+   static const double kq[][10] = {
+    {   3086,15746,69613,59899,75645,88306, 12661,  2658,    0,     0 },
+    {  21863,32794,10931,   73, 4387,26934,  1473,  2157,    0,     0 },
+    {     10,16002,21863,10931, 1473,32004,  4387,    73,    0,     0 },
+    {     10, 6345, 7818, 1107,15636, 7077,  8184,   532,   10,     0 },
+    {     19, 1760, 1454,  287, 1167,  880,   574,  2640,   19,  1454 },
+    {     19,  574,  287,  306, 1760,   12,    31,    38,   19,   574 },
+    {      4,  204,  177,    8,   31,  200,  1265,   102,    4,   204 },
+    {      4,  102,  106,    8,   98, 1367,   487,   204,    4,   102 }
+   };
+
+   static const double cl[][10] = {
+    {      21,   -95, -157,   41,   -5,   42,  23,  30,      0,     0 },
+    {    -160,  -313, -235,   60,  -74,  -76, -27,  34,      0,     0 },
+    {    -325,  -322,  -79,  232,  -52,   97,  55, -41,      0,     0 },
+    {    2268,  -979,  802,  602, -668,  -33, 345, 201,    -55,     0 },
+    {    7610, -4997,-7689,-5841,-2617, 1115,-748,-607,   6074,   354 },
+    {  -18549, 30125,20012, -730,  824,   23,1289,-352, -14767, -2062 },
+    { -135245,-14594, 4197,-4030,-5630,-2898,2540,-306,   2939,  1986 },
+    {   89948,  2103, 8963, 2695, 3682, 1648, 866,-154,  -1963,  -283 }
+   };
+
+   static const double sl[][10] = {
+    {   -342,   136,  -23,   62,   66,  -52, -33,    17,     0,     0 },
+    {    524,  -149,  -35,  117,  151,  122, -71,   -62,     0,     0 },
+    {   -105,  -137,  258,   35, -116,  -88,-112,   -80,     0,     0 },
+    {    854,  -205, -936, -240,  140, -341, -97,  -232,   536,     0 },
+    { -56980,  8016, 1012, 1448,-3024,-3710, 318,   503,  3767,   577 },
+    { 138606,-13478,-4964, 1441,-1319,-1482, 427,  1236, -9167, -1918 },
+    {  71234,-41116, 5334,-4935,-1848,   66, 434, -1748,  3780,  -701 },
+    { -47645, 11647, 2166, 3194,  679,    0,-244,  -419, -2531,    48 }
+   };
+
+/*--------------------------------------------------------------------*/
+
+/* Validate the planet number. */
+   if ((np < 1) || (np > 8)) {
+      jstat = -1;
+
+   /* Reset the result in case of failure. */
+      for (k = 0; k < 2; k++) {
+         for (i = 0; i < 3; i++) {
+            pv[k][i] = 0.0;
+         }
+      }
+
+   } else {
+
+   /* Decrement the planet number to start at zero. */
+      np--;
+
+   /* Time: Julian millennia since J2000.0. */
+      t = ((date1 - DJ00) + date2) / DJM;
+
+   /* OK status unless remote date. */
+      jstat = fabs(t) <= 1.0 ? 0 : 1;
+
+   /* Compute the mean elements. */
+      da = a[np][0] +
+          (a[np][1] +
+           a[np][2] * t) * t;
+      dl = (3600.0 * dlm[np][0] +
+                    (dlm[np][1] +
+                     dlm[np][2] * t) * t) * DAS2R;
+      de = e[np][0] +
+         ( e[np][1] +
+           e[np][2] * t) * t;
+      dp = iauAnpm((3600.0 * pi[np][0] +
+                            (pi[np][1] +
+                             pi[np][2] * t) * t) * DAS2R);
+      di = (3600.0 * dinc[np][0] +
+                    (dinc[np][1] +
+                     dinc[np][2] * t) * t) * DAS2R;
+      dom = iauAnpm((3600.0 * omega[np][0] +
+                             (omega[np][1] +
+                              omega[np][2] * t) * t) * DAS2R);
+
+   /* Apply the trigonometric terms. */
+      dmu = 0.35953620 * t;
+      for (k = 0; k < 8; k++) {
+         arga = kp[np][k] * dmu;
+         argl = kq[np][k] * dmu;
+         da += (ca[np][k] * cos(arga) +
+                sa[np][k] * sin(arga)) * 1e-7;
+         dl += (cl[np][k] * cos(argl) +
+                sl[np][k] * sin(argl)) * 1e-7;
+      }
+      arga = kp[np][8] * dmu;
+      da += t * (ca[np][8] * cos(arga) +
+                 sa[np][8] * sin(arga)) * 1e-7;
+      for (k = 8; k < 10; k++) {
+         argl = kq[np][k] * dmu;
+         dl += t * (cl[np][k] * cos(argl) +
+                    sl[np][k] * sin(argl)) * 1e-7;
+      }
+      dl = fmod(dl, D2PI);
+
+   /* Iterative soln. of Kepler's equation to get eccentric anomaly. */
+      am = dl - dp;
+      ae = am + de * sin(am);
+      k = 0;
+      dae = 1.0;
+      while (k < KMAX && fabs(dae) > 1e-12) {
+         dae = (am - ae + de * sin(ae)) / (1.0 - de * cos(ae));
+         ae += dae;
+         k++;
+         if (k == KMAX-1) jstat = 2;
+      }
+
+   /* True anomaly. */
+      ae2 = ae / 2.0;
+      at = 2.0 * atan2(sqrt((1.0 + de) / (1.0 - de)) * sin(ae2),
+                                                       cos(ae2));
+
+   /* Distance (AU) and speed (radians per day). */
+      r = da * (1.0 - de * cos(ae));
+      v = GK * sqrt((1.0 + 1.0 / amas[np]) / (da * da * da));
+
+      si2 = sin(di / 2.0);
+      xq = si2 * cos(dom);
+      xp = si2 * sin(dom);
+      tl = at + dp;
+      xsw = sin(tl);
+      xcw = cos(tl);
+      xm2 = 2.0 * (xp * xcw - xq * xsw);
+      xf = da / sqrt(1  -  de * de);
+      ci2 = cos(di / 2.0);
+      xms = (de * sin(dp) + xsw) * xf;
+      xmc = (de * cos(dp) + xcw) * xf;
+      xpxq2 = 2 * xp * xq;
+
+   /* Position (J2000.0 ecliptic x,y,z in AU). */
+      x = r * (xcw - xm2 * xp);
+      y = r * (xsw + xm2 * xq);
+      z = r * (-xm2 * ci2);
+
+   /* Rotate to equatorial. */
+      pv[0][0] = x;
+      pv[0][1] = y * COSEPS - z * SINEPS;
+      pv[0][2] = y * SINEPS + z * COSEPS;
+
+   /* Velocity (J2000.0 ecliptic xdot,ydot,zdot in AU/d). */
+      x = v * (( -1.0 + 2.0 * xp * xp) * xms + xpxq2 * xmc);
+      y = v * ((  1.0 - 2.0 * xq * xq) * xmc - xpxq2 * xms);
+      z = v * (2.0 * ci2 * (xp * xms + xq * xmc));
+
+   /* Rotate to equatorial. */
+      pv[1][0] = x;
+      pv[1][1] = y * COSEPS - z * SINEPS;
+      pv[1][2] = y * SINEPS + z * COSEPS;
+
+   }
+
+/* Return the status. */
+   return jstat;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+double iauPm(double p[3])
+/*
+**  - - - - - -
+**   i a u P m
+**  - - - - - -
+**
+**  Modulus of p-vector.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  vector/matrix support function.
+**
+**  Given:
+**     p      double[3]     p-vector
+**
+**  Returned (function value):
+**            double        modulus
+**
+**  This revision:  2008 May 22
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double w;
+
+
+   w  = sqrt( p[0] * p[0]
+            + p[1] * p[1]
+            + p[2] * p[2] );
+
+   return w;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauPmat00(double date1, double date2, double rbp[3][3])
+/*
+**  - - - - - - - - - -
+**   i a u P m a t 0 0
+**  - - - - - - - - - -
+**
+**  Precession matrix (including frame bias) from GCRS to a specified
+**  date, IAU 2000 model.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     date1,date2  double          TT as a 2-part Julian Date (Note 1)
+**
+**  Returned:
+**     rbp          double[3][3]    bias-precession matrix (Note 2)
+**
+**  Notes:
+**
+**  1) The TT date date1+date2 is a Julian Date, apportioned in any
+**     convenient way between the two arguments.  For example,
+**     JD(TT)=2450123.7 could be expressed in any of these ways,
+**     among others:
+**
+**            date1          date2
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in
+**     cases where the loss of several decimal digits of resolution
+**     is acceptable.  The J2000 method is best matched to the way
+**     the argument is handled internally and will deliver the
+**     optimum resolution.  The MJD method and the date & time methods
+**     are both good compromises between resolution and convenience.
+**
+**  2) The matrix operates in the sense V(date) = rbp * V(GCRS), where
+**     the p-vector V(GCRS) is with respect to the Geocentric Celestial
+**     Reference System (IAU, 2000) and the p-vector V(date) is with
+**     respect to the mean equatorial triad of the given date.
+**
+**  Called:
+**     iauBp00      frame bias and precession matrices, IAU 2000
+**
+**  Reference:
+**
+**     IAU: Trans. International Astronomical Union, Vol. XXIVB;  Proc.
+**     24th General Assembly, Manchester, UK.  Resolutions B1.3, B1.6.
+**     (2000)
+**
+**  This revision:  2009 December 21
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double rb[3][3], rp[3][3];
+
+
+/* Obtain the required matrix (discarding others). */
+   iauBp00(date1, date2, rb, rp, rbp);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauPmat06(double date1, double date2, double rbp[3][3])
+/*
+**  - - - - - - - - - -
+**   i a u P m a t 0 6
+**  - - - - - - - - - -
+**
+**  Precession matrix (including frame bias) from GCRS to a specified
+**  date, IAU 2006 model.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     date1,date2  double          TT as a 2-part Julian Date (Note 1)
+**
+**  Returned:
+**     rbp          double[3][3]    bias-precession matrix (Note 2)
+**
+**  Notes:
+**
+**  1) The TT date date1+date2 is a Julian Date, apportioned in any
+**     convenient way between the two arguments.  For example,
+**     JD(TT)=2450123.7 could be expressed in any of these ways,
+**     among others:
+**
+**            date1          date2
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in
+**     cases where the loss of several decimal digits of resolution
+**     is acceptable.  The J2000 method is best matched to the way
+**     the argument is handled internally and will deliver the
+**     optimum resolution.  The MJD method and the date & time methods
+**     are both good compromises between resolution and convenience.
+**
+**  2) The matrix operates in the sense V(date) = rbp * V(GCRS), where
+**     the p-vector V(GCRS) is with respect to the Geocentric Celestial
+**     Reference System (IAU, 2000) and the p-vector V(date) is with
+**     respect to the mean equatorial triad of the given date.
+**
+**  Called:
+**     iauPfw06     bias-precession F-W angles, IAU 2006
+**     iauFw2m      F-W angles to r-matrix
+**
+**  References:
+**
+**     Capitaine, N. & Wallace, P.T., 2006, Astron.Astrophys. 450, 855
+**
+**     Wallace, P.T. & Capitaine, N., 2006, Astron.Astrophys. 459, 981
+**
+**  This revision:  2009 December 21
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double gamb, phib, psib, epsa;
+
+
+/* Bias-precession Fukushima-Williams angles. */
+   iauPfw06(date1, date2, &gamb, &phib, &psib, &epsa);
+
+/* Form the matrix. */
+   iauFw2m(gamb, phib, psib, epsa, rbp);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauPmat76(double date1, double date2, double rmatp[3][3])
+/*
+**  - - - - - - - - - -
+**   i a u P m a t 7 6
+**  - - - - - - - - - -
+**
+**  Precession matrix from J2000.0 to a specified date, IAU 1976 model.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     date1,date2 double       ending date, TT (Note 1)
+**
+**  Returned:
+**     rmatp       double[3][3] precession matrix, J2000.0 -> date1+date2
+**
+**  Notes:
+**
+**  1) The TT date date1+date2 is a Julian Date, apportioned in any
+**     convenient way between the two arguments.  For example,
+**     JD(TT)=2450123.7 could be expressed in any of these ways,
+**     among others:
+**
+**            date1          date2
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in
+**     cases where the loss of several decimal digits of resolution
+**     is acceptable.  The J2000 method is best matched to the way
+**     the argument is handled internally and will deliver the
+**     optimum resolution.  The MJD method and the date & time methods
+**     are both good compromises between resolution and convenience.
+**
+**  2) The matrix operates in the sense V(date) = RMATP * V(J2000),
+**     where the p-vector V(J2000) is with respect to the mean
+**     equatorial triad of epoch J2000.0 and the p-vector V(date)
+**     is with respect to the mean equatorial triad of the given
+**     date.
+**
+**  3) Though the matrix method itself is rigorous, the precession
+**     angles are expressed through canonical polynomials which are
+**     valid only for a limited time span.  In addition, the IAU 1976
+**     precession rate is known to be imperfect.  The absolute accuracy
+**     of the present formulation is better than 0.1 arcsec from
+**     1960AD to 2040AD, better than 1 arcsec from 1640AD to 2360AD,
+**     and remains below 3 arcsec for the whole of the period
+**     500BC to 3000AD.  The errors exceed 10 arcsec outside the
+**     range 1200BC to 3900AD, exceed 100 arcsec outside 4200BC to
+**     5600AD and exceed 1000 arcsec outside 6800BC to 8200AD.
+**
+**  Called:
+**     iauPrec76    accumulated precession angles, IAU 1976
+**     iauIr        initialize r-matrix to identity
+**     iauRz        rotate around Z-axis
+**     iauRy        rotate around Y-axis
+**     iauCr        copy r-matrix
+**
+**  References:
+**
+**     Lieske, J.H., 1979, Astron.Astrophys. 73, 282.
+**      equations (6) & (7), p283.
+**
+**     Kaplan,G.H., 1981. USNO circular no. 163, pA2.
+**
+**  This revision:  2009 December 18
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double zeta, z, theta, wmat[3][3];
+
+
+/* Precession Euler angles, J2000.0 to specified date. */
+   iauPrec76(DJ00, 0.0, date1, date2, &zeta, &z, &theta);
+
+/* Form the rotation matrix. */
+   iauIr(  wmat);
+   iauRz( -zeta, wmat);
+   iauRy(  theta, wmat);
+   iauRz( -z, wmat);
+   iauCr( wmat, rmatp);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauPmp(double a[3], double b[3], double amb[3])
+/*
+**  - - - - - - -
+**   i a u P m p
+**  - - - - - - -
+**
+**  P-vector subtraction.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  vector/matrix support function.
+**
+**  Given:
+**     a        double[3]      first p-vector
+**     b        double[3]      second p-vector
+**
+**  Returned:
+**     amb      double[3]      a - b
+**
+**  Note:
+**     It is permissible to re-use the same array for any of the
+**     arguments.
+**
+**  This revision:  2008 November 18
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   amb[0] = a[0] - b[0];
+   amb[1] = a[1] - b[1];
+   amb[2] = a[2] - b[2];
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauPn(double p[3], double *r, double u[3])
+/*
+**  - - - - - -
+**   i a u P n
+**  - - - - - -
+**
+**  Convert a p-vector into modulus and unit vector.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  vector/matrix support function.
+**
+**  Given:
+**     p        double[3]      p-vector
+**
+**  Returned:
+**     r        double         modulus
+**     u        double[3]      unit vector
+**
+**  Notes:
+**
+**  1) If p is null, the result is null.  Otherwise the result is a unit
+**     vector.
+**
+**  2) It is permissible to re-use the same array for any of the
+**     arguments.
+**
+**  Called:
+**     iauPm        modulus of p-vector
+**     iauZp        zero p-vector
+**     iauSxp       multiply p-vector by scalar
+**
+**  This revision:  2008 November 18
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double w;
+
+
+/* Obtain the modulus and test for zero. */
+   w = iauPm(p);
+   if (w == 0.0) {
+
+   /* Null vector. */
+      iauZp(u);
+
+   } else {
+
+   /* Unit vector. */
+      iauSxp(1.0/w, p, u);
+   }
+
+/* Return the modulus. */
+   *r = w;
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauPn00(double date1, double date2, double dpsi, double deps,
+             double *epsa,
+             double rb[3][3], double rp[3][3], double rbp[3][3],
+             double rn[3][3], double rbpn[3][3])
+/*
+**  - - - - - - - -
+**   i a u P n 0 0
+**  - - - - - - - -
+**
+**  Precession-nutation, IAU 2000 model:  a multi-purpose function,
+**  supporting classical (equinox-based) use directly and CIO-based
+**  use indirectly.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     date1,date2  double          TT as a 2-part Julian Date (Note 1)
+**     dpsi,deps    double          nutation (Note 2)
+**
+**  Returned:
+**     epsa         double          mean obliquity (Note 3)
+**     rb           double[3][3]    frame bias matrix (Note 4)
+**     rp           double[3][3]    precession matrix (Note 5)
+**     rbp          double[3][3]    bias-precession matrix (Note 6)
+**     rn           double[3][3]    nutation matrix (Note 7)
+**     rbpn         double[3][3]    GCRS-to-true matrix (Note 8)
+**
+**  Notes:
+**
+**  1) The TT date date1+date2 is a Julian Date, apportioned in any
+**     convenient way between the two arguments.  For example,
+**     JD(TT)=2450123.7 could be expressed in any of these ways,
+**     among others:
+**
+**            date1          date2
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in
+**     cases where the loss of several decimal digits of resolution
+**     is acceptable.  The J2000 method is best matched to the way
+**     the argument is handled internally and will deliver the
+**     optimum resolution.  The MJD method and the date & time methods
+**     are both good compromises between resolution and convenience.
+**
+**  2) The caller is responsible for providing the nutation components;
+**     they are in longitude and obliquity, in radians and are with
+**     respect to the equinox and ecliptic of date.  For high-accuracy
+**     applications, free core nutation should be included as well as
+**     any other relevant corrections to the position of the CIP.
+**
+**  3) The returned mean obliquity is consistent with the IAU 2000
+**     precession-nutation models.
+**
+**  4) The matrix rb transforms vectors from GCRS to J2000.0 mean
+**     equator and equinox by applying frame bias.
+**
+**  5) The matrix rp transforms vectors from J2000.0 mean equator and
+**     equinox to mean equator and equinox of date by applying
+**     precession.
+**
+**  6) The matrix rbp transforms vectors from GCRS to mean equator and
+**     equinox of date by applying frame bias then precession.  It is
+**     the product rp x rb.
+**
+**  7) The matrix rn transforms vectors from mean equator and equinox of
+**     date to true equator and equinox of date by applying the nutation
+**     (luni-solar + planetary).
+**
+**  8) The matrix rbpn transforms vectors from GCRS to true equator and
+**     equinox of date.  It is the product rn x rbp, applying frame
+**     bias, precession and nutation in that order.
+**
+**  9) It is permissible to re-use the same array in the returned
+**     arguments.  The arrays are filled in the order given.
+**
+**  Called:
+**     iauPr00      IAU 2000 precession adjustments
+**     iauObl80     mean obliquity, IAU 1980
+**     iauBp00      frame bias and precession matrices, IAU 2000
+**     iauCr        copy r-matrix
+**     iauNumat     form nutation matrix
+**     iauRxr       product of two r-matrices
+**
+**  Reference:
+**
+**     Capitaine, N., Chapront, J., Lambert, S. and Wallace, P.,
+**     "Expressions for the Celestial Intermediate Pole and Celestial
+**     Ephemeris Origin consistent with the IAU 2000A precession-
+**     nutation model", Astron.Astrophys. 400, 1145-1154 (2003)
+**
+**     n.b. The celestial ephemeris origin (CEO) was renamed "celestial
+**          intermediate origin" (CIO) by IAU 2006 Resolution 2.
+**
+**  This revision:  2010 January 18
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double dpsipr, depspr, rbpw[3][3], rnw[3][3];
+
+
+/* IAU 2000 precession-rate adjustments. */
+   iauPr00(date1, date2, &dpsipr, &depspr);
+
+/* Mean obliquity, consistent with IAU 2000 precession-nutation. */
+   *epsa = iauObl80(date1, date2) + depspr;
+
+/* Frame bias and precession matrices and their product. */
+   iauBp00(date1, date2, rb, rp, rbpw);
+   iauCr(rbpw, rbp);
+
+/* Nutation matrix. */
+   iauNumat(*epsa, dpsi, deps, rnw);
+   iauCr(rnw, rn);
+
+/* Bias-precession-nutation matrix (classical). */
+   iauRxr(rnw, rbpw, rbpn);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauPn00a(double date1, double date2,
+              double *dpsi, double *deps, double *epsa,
+              double rb[3][3], double rp[3][3], double rbp[3][3],
+              double rn[3][3], double rbpn[3][3])
+/*
+**  - - - - - - - - -
+**   i a u P n 0 0 a
+**  - - - - - - - - -
+**
+**  Precession-nutation, IAU 2000A model:  a multi-purpose function,
+**  supporting classical (equinox-based) use directly and CIO-based
+**  use indirectly.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     date1,date2  double          TT as a 2-part Julian Date (Note 1)
+**
+**  Returned:
+**     dpsi,deps    double          nutation (Note 2)
+**     epsa         double          mean obliquity (Note 3)
+**     rb           double[3][3]    frame bias matrix (Note 4)
+**     rp           double[3][3]    precession matrix (Note 5)
+**     rbp          double[3][3]    bias-precession matrix (Note 6)
+**     rn           double[3][3]    nutation matrix (Note 7)
+**     rbpn         double[3][3]    GCRS-to-true matrix (Notes 8,9)
+**
+**  Notes:
+**
+**  1)  The TT date date1+date2 is a Julian Date, apportioned in any
+**      convenient way between the two arguments.  For example,
+**      JD(TT)=2450123.7 could be expressed in any of these ways,
+**      among others:
+**
+**             date1          date2
+**
+**          2450123.7           0.0       (JD method)
+**          2451545.0       -1421.3       (J2000 method)
+**          2400000.5       50123.2       (MJD method)
+**          2450123.5           0.2       (date & time method)
+**
+**      The JD method is the most natural and convenient to use in
+**      cases where the loss of several decimal digits of resolution
+**      is acceptable.  The J2000 method is best matched to the way
+**      the argument is handled internally and will deliver the
+**      optimum resolution.  The MJD method and the date & time methods
+**      are both good compromises between resolution and convenience.
+**
+**  2)  The nutation components (luni-solar + planetary, IAU 2000A) in
+**      longitude and obliquity are in radians and with respect to the
+**      equinox and ecliptic of date.  Free core nutation is omitted;
+**      for the utmost accuracy, use the iauPn00  function, where the
+**      nutation components are caller-specified.  For faster but
+**      slightly less accurate results, use the iauPn00b function.
+**
+**  3)  The mean obliquity is consistent with the IAU 2000 precession.
+**
+**  4)  The matrix rb transforms vectors from GCRS to J2000.0 mean
+**      equator and equinox by applying frame bias.
+**
+**  5)  The matrix rp transforms vectors from J2000.0 mean equator and
+**      equinox to mean equator and equinox of date by applying
+**      precession.
+**
+**  6)  The matrix rbp transforms vectors from GCRS to mean equator and
+**      equinox of date by applying frame bias then precession.  It is
+**      the product rp x rb.
+**
+**  7)  The matrix rn transforms vectors from mean equator and equinox
+**      of date to true equator and equinox of date by applying the
+**      nutation (luni-solar + planetary).
+**
+**  8)  The matrix rbpn transforms vectors from GCRS to true equator and
+**      equinox of date.  It is the product rn x rbp, applying frame
+**      bias, precession and nutation in that order.
+**
+**  9)  The X,Y,Z coordinates of the IAU 2000B Celestial Intermediate
+**      Pole are elements (3,1-3) of the matrix rbpn.
+**
+**  10) It is permissible to re-use the same array in the returned
+**      arguments.  The arrays are filled in the order given.
+**
+**  Called:
+**     iauNut00a    nutation, IAU 2000A
+**     iauPn00      bias/precession/nutation results, IAU 2000
+**
+**  Reference:
+**
+**     Capitaine, N., Chapront, J., Lambert, S. and Wallace, P.,
+**     "Expressions for the Celestial Intermediate Pole and Celestial
+**     Ephemeris Origin consistent with the IAU 2000A precession-
+**     nutation model", Astron.Astrophys. 400, 1145-1154 (2003)
+**
+**     n.b. The celestial ephemeris origin (CEO) was renamed "celestial
+**          intermediate origin" (CIO) by IAU 2006 Resolution 2.
+**
+**  This revision:  2010 January 18
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+/* Nutation. */
+   iauNut00a(date1, date2, dpsi, deps);
+
+/* Remaining results. */
+   iauPn00(date1, date2, *dpsi, *deps, epsa, rb, rp, rbp, rn, rbpn);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauPn00b(double date1, double date2,
+              double *dpsi, double *deps, double *epsa,
+              double rb[3][3], double rp[3][3], double rbp[3][3],
+              double rn[3][3], double rbpn[3][3])
+/*
+**  - - - - - - - - -
+**   i a u P n 0 0 b
+**  - - - - - - - - -
+**
+**  Precession-nutation, IAU 2000B model:  a multi-purpose function,
+**  supporting classical (equinox-based) use directly and CIO-based
+**  use indirectly.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     date1,date2  double          TT as a 2-part Julian Date (Note 1)
+**
+**  Returned:
+**     dpsi,deps    double          nutation (Note 2)
+**     epsa         double          mean obliquity (Note 3)
+**     rb           double[3][3]    frame bias matrix (Note 4)
+**     rp           double[3][3]    precession matrix (Note 5)
+**     rbp          double[3][3]    bias-precession matrix (Note 6)
+**     rn           double[3][3]    nutation matrix (Note 7)
+**     rbpn         double[3][3]    GCRS-to-true matrix (Notes 8,9)
+**
+**  Notes:
+**
+**  1)  The TT date date1+date2 is a Julian Date, apportioned in any
+**      convenient way between the two arguments.  For example,
+**      JD(TT)=2450123.7 could be expressed in any of these ways,
+**      among others:
+**
+**             date1          date2
+**
+**          2450123.7           0.0       (JD method)
+**          2451545.0       -1421.3       (J2000 method)
+**          2400000.5       50123.2       (MJD method)
+**          2450123.5           0.2       (date & time method)
+**
+**      The JD method is the most natural and convenient to use in
+**      cases where the loss of several decimal digits of resolution
+**      is acceptable.  The J2000 method is best matched to the way
+**      the argument is handled internally and will deliver the
+**      optimum resolution.  The MJD method and the date & time methods
+**      are both good compromises between resolution and convenience.
+**
+**  2)  The nutation components (luni-solar + planetary, IAU 2000B) in
+**      longitude and obliquity are in radians and with respect to the
+**      equinox and ecliptic of date.  For more accurate results, but
+**      at the cost of increased computation, use the iauPn00a function.
+**      For the utmost accuracy, use the iauPn00  function, where the
+**      nutation components are caller-specified.
+**
+**  3)  The mean obliquity is consistent with the IAU 2000 precession.
+**
+**  4)  The matrix rb transforms vectors from GCRS to J2000.0 mean
+**      equator and equinox by applying frame bias.
+**
+**  5)  The matrix rp transforms vectors from J2000.0 mean equator and
+**      equinox to mean equator and equinox of date by applying
+**      precession.
+**
+**  6)  The matrix rbp transforms vectors from GCRS to mean equator and
+**      equinox of date by applying frame bias then precession.  It is
+**      the product rp x rb.
+**
+**  7)  The matrix rn transforms vectors from mean equator and equinox
+**      of date to true equator and equinox of date by applying the
+**      nutation (luni-solar + planetary).
+**
+**  8)  The matrix rbpn transforms vectors from GCRS to true equator and
+**      equinox of date.  It is the product rn x rbp, applying frame
+**      bias, precession and nutation in that order.
+**
+**  9)  The X,Y,Z coordinates of the IAU 2000B Celestial Intermediate
+**      Pole are elements (3,1-3) of the matrix rbpn.
+**
+**  10) It is permissible to re-use the same array in the returned
+**      arguments.  The arrays are filled in the stated order.
+**
+**  Called:
+**     iauNut00b    nutation, IAU 2000B
+**     iauPn00      bias/precession/nutation results, IAU 2000
+**
+**  Reference:
+**
+**     Capitaine, N., Chapront, J., Lambert, S. and Wallace, P.,
+**     "Expressions for the Celestial Intermediate Pole and Celestial
+**     Ephemeris Origin consistent with the IAU 2000A precession-
+**     nutation model", Astron.Astrophys. 400, 1145-1154 (2003).
+**
+**     n.b. The celestial ephemeris origin (CEO) was renamed "celestial
+**          intermediate origin" (CIO) by IAU 2006 Resolution 2.
+**
+**  This revision:  2010 January 18
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+/* Nutation. */
+   iauNut00b(date1, date2, dpsi, deps);
+
+/* Remaining results. */
+   iauPn00(date1, date2, *dpsi, *deps, epsa, rb, rp, rbp, rn, rbpn);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauPn06(double date1, double date2, double dpsi, double deps,
+             double *epsa,
+             double rb[3][3], double rp[3][3], double rbp[3][3],
+             double rn[3][3], double rbpn[3][3])
+/*
+**  - - - - - - - -
+**   i a u P n 0 6
+**  - - - - - - - -
+**
+**  Precession-nutation, IAU 2006 model:  a multi-purpose function,
+**  supporting classical (equinox-based) use directly and CIO-based use
+**  indirectly.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     date1,date2  double          TT as a 2-part Julian Date (Note 1)
+**     dpsi,deps    double          nutation (Note 2)
+**
+**  Returned:
+**     epsa         double          mean obliquity (Note 3)
+**     rb           double[3][3]    frame bias matrix (Note 4)
+**     rp           double[3][3]    precession matrix (Note 5)
+**     rbp          double[3][3]    bias-precession matrix (Note 6)
+**     rn           double[3][3]    nutation matrix (Note 7)
+**     rbpn         double[3][3]    GCRS-to-true matrix (Note 8)
+**
+**  Notes:
+**
+**  1)  The TT date date1+date2 is a Julian Date, apportioned in any
+**      convenient way between the two arguments.  For example,
+**      JD(TT)=2450123.7 could be expressed in any of these ways,
+**      among others:
+**
+**             date1          date2
+**
+**          2450123.7           0.0       (JD method)
+**          2451545.0       -1421.3       (J2000 method)
+**          2400000.5       50123.2       (MJD method)
+**          2450123.5           0.2       (date & time method)
+**
+**      The JD method is the most natural and convenient to use in
+**      cases where the loss of several decimal digits of resolution
+**      is acceptable.  The J2000 method is best matched to the way
+**      the argument is handled internally and will deliver the
+**      optimum resolution.  The MJD method and the date & time methods
+**      are both good compromises between resolution and convenience.
+**
+**  2)  The caller is responsible for providing the nutation components;
+**      they are in longitude and obliquity, in radians and are with
+**      respect to the equinox and ecliptic of date.  For high-accuracy
+**      applications, free core nutation should be included as well as
+**      any other relevant corrections to the position of the CIP.
+**
+**  3)  The returned mean obliquity is consistent with the IAU 2006
+**      precession.
+**
+**  4)  The matrix rb transforms vectors from GCRS to J2000.0 mean
+**      equator and equinox by applying frame bias.
+**
+**  5)  The matrix rp transforms vectors from J2000.0 mean equator and
+**      equinox to mean equator and equinox of date by applying
+**      precession.
+**
+**  6)  The matrix rbp transforms vectors from GCRS to mean equator and
+**      equinox of date by applying frame bias then precession.  It is
+**      the product rp x rb.
+**
+**  7)  The matrix rn transforms vectors from mean equator and equinox
+**      of date to true equator and equinox of date by applying the
+**      nutation (luni-solar + planetary).
+**
+**  8)  The matrix rbpn transforms vectors from GCRS to true equator and
+**      equinox of date.  It is the product rn x rbp, applying frame
+**      bias, precession and nutation in that order.
+**
+**  9)  The X,Y,Z coordinates of the IAU 2000B Celestial Intermediate
+**      Pole are elements (3,1-3) of the matrix rbpn.
+**
+**  10) It is permissible to re-use the same array in the returned
+**      arguments.  The arrays are filled in the stated order.
+**
+**  Called:
+**     iauPfw06     bias-precession F-W angles, IAU 2006
+**     iauFw2m      F-W angles to r-matrix
+**     iauCr        copy r-matrix
+**     iauTr        transpose r-matrix
+**     iauRxr       product of two r-matrices
+**
+**  References:
+**
+**     Capitaine, N. & Wallace, P.T., 2006, Astron.Astrophys. 450, 855
+**
+**     Wallace, P.T. & Capitaine, N., 2006, Astron.Astrophys. 459, 981
+**
+**  This revision:  2009 December 17
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double gamb, phib, psib, eps, r1[3][3], r2[3][3], rt[3][3];
+
+
+/* Bias-precession Fukushima-Williams angles of J2000.0 = frame bias. */
+   iauPfw06(DJM0, DJM00, &gamb, &phib, &psib, &eps);
+
+/* B matrix. */
+   iauFw2m(gamb, phib, psib, eps, r1);
+   iauCr(r1, rb);
+
+/* Bias-precession Fukushima-Williams angles of date. */
+   iauPfw06(date1, date2, &gamb, &phib, &psib, &eps);
+
+/* Bias-precession matrix. */
+   iauFw2m(gamb, phib, psib, eps, r2);
+   iauCr(r2, rbp);
+
+/* Solve for precession matrix. */
+   iauTr(r1, rt);
+   iauRxr(r2, rt, rp);
+
+/* Equinox-based bias-precession-nutation matrix. */
+   iauFw2m(gamb, phib, psib + dpsi, eps + deps, r1);
+   iauCr(r1, rbpn);
+
+/* Solve for nutation matrix. */
+   iauTr(r2, rt);
+   iauRxr(r1, rt, rn);
+
+/* Obliquity, mean of date. */
+   *epsa = eps;
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauPn06a(double date1, double date2,
+              double *dpsi, double *deps, double *epsa,
+              double rb[3][3], double rp[3][3], double rbp[3][3],
+              double rn[3][3], double rbpn[3][3])
+/*
+**  - - - - - - - - -
+**   i a u P n 0 6 a
+**  - - - - - - - - -
+**
+**  Precession-nutation, IAU 2006/2000A models:  a multi-purpose function,
+**  supporting classical (equinox-based) use directly and CIO-based use
+**  indirectly.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     date1,date2  double          TT as a 2-part Julian Date (Note 1)
+**
+**  Returned:
+**     dpsi,deps    double          nutation (Note 2)
+**     epsa         double          mean obliquity (Note 3)
+**     rb           double[3][3]    frame bias matrix (Note 4)
+**     rp           double[3][3]    precession matrix (Note 5)
+**     rbp          double[3][3]    bias-precession matrix (Note 6)
+**     rn           double[3][3]    nutation matrix (Note 7)
+**     rbpn         double[3][3]    GCRS-to-true matrix (Notes 8,9)
+**
+**  Notes:
+**
+**  1)  The TT date date1+date2 is a Julian Date, apportioned in any
+**      convenient way between the two arguments.  For example,
+**      JD(TT)=2450123.7 could be expressed in any of these ways,
+**      among others:
+**
+**             date1          date2
+**
+**          2450123.7           0.0       (JD method)
+**          2451545.0       -1421.3       (J2000 method)
+**          2400000.5       50123.2       (MJD method)
+**          2450123.5           0.2       (date & time method)
+**
+**      The JD method is the most natural and convenient to use in
+**      cases where the loss of several decimal digits of resolution
+**      is acceptable.  The J2000 method is best matched to the way
+**      the argument is handled internally and will deliver the
+**      optimum resolution.  The MJD method and the date & time methods
+**      are both good compromises between resolution and convenience.
+**
+**  2)  The nutation components (luni-solar + planetary, IAU 2000A) in
+**      longitude and obliquity are in radians and with respect to the
+**      equinox and ecliptic of date.  Free core nutation is omitted;
+**      for the utmost accuracy, use the iauPn06 function, where the
+**      nutation components are caller-specified.
+**
+**  3)  The mean obliquity is consistent with the IAU 2006 precession.
+**
+**  4)  The matrix rb transforms vectors from GCRS to mean J2000.0 by
+**      applying frame bias.
+**
+**  5)  The matrix rp transforms vectors from mean J2000.0 to mean of
+**      date by applying precession.
+**
+**  6)  The matrix rbp transforms vectors from GCRS to mean of date by
+**      applying frame bias then precession.  It is the product rp x rb.
+**
+**  7)  The matrix rn transforms vectors from mean of date to true of
+**      date by applying the nutation (luni-solar + planetary).
+**
+**  8)  The matrix rbpn transforms vectors from GCRS to true of date
+**      (CIP/equinox).  It is the product rn x rbp, applying frame bias,
+**      precession and nutation in that order.
+**
+**  9)  The X,Y,Z coordinates of the IAU 2006/2000A Celestial
+**      Intermediate Pole are elements (1,1-3) of the matrix rbpn.
+**
+**  10) It is permissible to re-use the same array in the returned
+**      arguments.  The arrays are filled in the stated order.
+**
+**  Called:
+**     iauNut06a    nutation, IAU 2006/2000A
+**     iauPn06      bias/precession/nutation results, IAU 2006
+**
+**  Reference:
+**
+**     Capitaine, N. & Wallace, P.T., 2006, Astron.Astrophys. 450, 855
+**
+**  This revision:  2009 December 18
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+/* Nutation. */
+   iauNut06a(date1, date2, dpsi, deps);
+
+/* Remaining results. */
+   iauPn06(date1, date2, *dpsi, *deps, epsa, rb, rp, rbp, rn, rbpn);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauPnm00a(double date1, double date2, double rbpn[3][3])
+/*
+**  - - - - - - - - - -
+**   i a u P n m 0 0 a
+**  - - - - - - - - - -
+**
+**  Form the matrix of precession-nutation for a given date (including
+**  frame bias), equinox-based, IAU 2000A model.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     date1,date2  double     TT as a 2-part Julian Date (Note 1)
+**
+**  Returned:
+**     rbpn         double[3][3]    classical NPB matrix (Note 2)
+**
+**  Notes:
+**
+**  1) The TT date date1+date2 is a Julian Date, apportioned in any
+**     convenient way between the two arguments.  For example,
+**     JD(TT)=2450123.7 could be expressed in any of these ways,
+**     among others:
+**
+**            date1          date2
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in
+**     cases where the loss of several decimal digits of resolution
+**     is acceptable.  The J2000 method is best matched to the way
+**     the argument is handled internally and will deliver the
+**     optimum resolution.  The MJD method and the date & time methods
+**     are both good compromises between resolution and convenience.
+**
+**  2) The matrix operates in the sense V(date) = rbpn * V(GCRS), where
+**     the p-vector V(date) is with respect to the true equatorial triad
+**     of date date1+date2 and the p-vector V(GCRS) is with respect to
+**     the Geocentric Celestial Reference System (IAU, 2000).
+**
+**  3) A faster, but slightly less accurate result (about 1 mas), can be
+**     obtained by using instead the iauPnm00b function.
+**
+**  Called:
+**     iauPn00a     bias/precession/nutation, IAU 2000A
+**
+**  Reference:
+**
+**     IAU: Trans. International Astronomical Union, Vol. XXIVB;  Proc.
+**     24th General Assembly, Manchester, UK.  Resolutions B1.3, B1.6.
+**     (2000)
+**
+**  This revision:  2009 December 21
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double dpsi, deps, epsa, rb[3][3], rp[3][3], rbp[3][3], rn[3][3];
+
+
+/* Obtain the required matrix (discarding other results). */
+   iauPn00a(date1, date2, &dpsi, &deps, &epsa, rb, rp, rbp, rn, rbpn);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauPnm00b(double date1, double date2, double rbpn[3][3])
+/*
+**  - - - - - - - - - -
+**   i a u P n m 0 0 b
+**  - - - - - - - - - -
+**
+**  Form the matrix of precession-nutation for a given date (including
+**  frame bias), equinox-based, IAU 2000B model.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     date1,date2 double       TT as a 2-part Julian Date (Note 1)
+**
+**  Returned:
+**     rbpn        double[3][3] bias-precession-nutation matrix (Note 2)
+**
+**  Notes:
+**
+**  1) The TT date date1+date2 is a Julian Date, apportioned in any
+**     convenient way between the two arguments.  For example,
+**     JD(TT)=2450123.7 could be expressed in any of these ways,
+**     among others:
+**
+**            date1          date2
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in
+**     cases where the loss of several decimal digits of resolution
+**     is acceptable.  The J2000 method is best matched to the way
+**     the argument is handled internally and will deliver the
+**     optimum resolution.  The MJD method and the date & time methods
+**     are both good compromises between resolution and convenience.
+**
+**  2) The matrix operates in the sense V(date) = rbpn * V(GCRS), where
+**     the p-vector V(date) is with respect to the true equatorial triad
+**     of date date1+date2 and the p-vector V(GCRS) is with respect to
+**     the Geocentric Celestial Reference System (IAU, 2000).
+**
+**  3) The present function is faster, but slightly less accurate (about
+**     1 mas), than the iauPnm00a function.
+**
+**  Called:
+**     iauPn00b     bias/precession/nutation, IAU 2000B
+**
+**  Reference:
+**
+**     IAU: Trans. International Astronomical Union, Vol. XXIVB;  Proc.
+**     24th General Assembly, Manchester, UK.  Resolutions B1.3, B1.6.
+**     (2000)
+**
+**  This revision:  2009 December 21
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double dpsi, deps, epsa, rb[3][3], rp[3][3], rbp[3][3], rn[3][3];
+
+
+/* Obtain the required matrix (discarding other results). */
+   iauPn00b(date1, date2, &dpsi, &deps, &epsa, rb, rp, rbp, rn, rbpn);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauPnm06a(double date1, double date2, double rnpb[3][3])
+/*
+**  - - - - - - - - - -
+**   i a u P n m 0 6 a
+**  - - - - - - - - - -
+**
+**  Form the matrix of precession-nutation for a given date (including
+**  frame bias), IAU 2006 precession and IAU 2000A nutation models.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     date1,date2 double       TT as a 2-part Julian Date (Note 1)
+**
+**  Returned:
+**     rnpb        double[3][3] bias-precession-nutation matrix (Note 2)
+**
+**  Notes:
+**
+**  1) The TT date date1+date2 is a Julian Date, apportioned in any
+**     convenient way between the two arguments.  For example,
+**     JD(TT)=2450123.7 could be expressed in any of these ways,
+**     among others:
+**
+**            date1          date2
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in
+**     cases where the loss of several decimal digits of resolution
+**     is acceptable.  The J2000 method is best matched to the way
+**     the argument is handled internally and will deliver the
+**     optimum resolution.  The MJD method and the date & time methods
+**     are both good compromises between resolution and convenience.
+**
+**  2) The matrix operates in the sense V(date) = rnpb * V(GCRS), where
+**     the p-vector V(date) is with respect to the true equatorial triad
+**     of date date1+date2 and the p-vector V(GCRS) is with respect to
+**     the Geocentric Celestial Reference System (IAU, 2000).
+**
+**  Called:
+**     iauPfw06     bias-precession F-W angles, IAU 2006
+**     iauNut06a    nutation, IAU 2006/2000A
+**     iauFw2m      F-W angles to r-matrix
+**
+**  Reference:
+**
+**     Capitaine, N. & Wallace, P.T., 2006, Astron.Astrophys. 450, 855.
+**
+**  This revision:  2009 December 21
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double gamb, phib, psib, epsa, dp, de;
+
+
+/* Fukushima-Williams angles for frame bias and precession. */
+   iauPfw06(date1, date2, &gamb, &phib, &psib, &epsa);
+
+/* Nutation components. */
+   iauNut06a(date1, date2, &dp, &de);
+
+/* Equinox based nutation x precession x bias matrix. */
+   iauFw2m(gamb, phib, psib + dp, epsa + de, rnpb);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauPnm80(double date1, double date2, double rmatpn[3][3])
+/*
+**  - - - - - - - - -
+**   i a u P n m 8 0
+**  - - - - - - - - -
+**
+**  Form the matrix of precession/nutation for a given date, IAU 1976
+**  precession model, IAU 1980 nutation model.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     date1,date2    double         TDB date (Note 1)
+**
+**  Returned:
+**     rmatpn         double[3][3]   combined precession/nutation matrix
+**
+**  Notes:
+**
+**  1) The TDB date date1+date2 is a Julian Date, apportioned in any
+**     convenient way between the two arguments.  For example,
+**     JD(TDB)=2450123.7 could be expressed in any of these ways,
+**     among others:
+**
+**            date1          date2
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in
+**     cases where the loss of several decimal digits of resolution
+**     is acceptable.  The J2000 method is best matched to the way
+**     the argument is handled internally and will deliver the
+**     optimum resolution.  The MJD method and the date & time methods
+**     are both good compromises between resolution and convenience.
+**
+**  2) The matrix operates in the sense V(date) = rmatpn * V(J2000),
+**     where the p-vector V(date) is with respect to the true equatorial
+**     triad of date date1+date2 and the p-vector V(J2000) is with
+**     respect to the mean equatorial triad of epoch J2000.0.
+**
+**  Called:
+**     iauPmat76    precession matrix, IAU 1976
+**     iauNutm80    nutation matrix, IAU 1980
+**     iauRxr       product of two r-matrices
+**
+**  Reference:
+**
+**     Explanatory Supplement to the Astronomical Almanac,
+**     P. Kenneth Seidelmann (ed), University Science Books (1992),
+**     Section 3.3 (p145).
+**
+**  This revision:  2010 January 23
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double rmatp[3][3], rmatn[3][3];
+
+
+/* Precession matrix, J2000.0 to date. */
+   iauPmat76(date1, date2, rmatp);
+
+/* Nutation matrix. */
+   iauNutm80(date1, date2, rmatn);
+
+/* Combine the matrices:  PN = N x P. */
+   iauRxr(rmatn, rmatp, rmatpn);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauPom00(double xp, double yp, double sp, double rpom[3][3])
+/*
+**  - - - - - - - - - -
+**   i a u P o m 0 0
+**  - - - - - - - - - -
+**
+**  Form the matrix of polar motion for a given date, IAU 2000.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     xp,yp    double    coordinates of the pole (radians, Note 1)
+**     sp       double    the TIO locator s' (radians, Note 2)
+**
+**  Returned:
+**     rpom     double[3][3]   polar-motion matrix (Note 3)
+**
+**  Notes:
+**
+**  1) The arguments xp and yp are the coordinates (in radians) of the
+**     Celestial Intermediate Pole with respect to the International
+**     Terrestrial Reference System (see IERS Conventions 2003),
+**     measured along the meridians to 0 and 90 deg west respectively.
+**
+**  2) The argument sp is the TIO locator s', in radians, which
+**     positions the Terrestrial Intermediate Origin on the equator.  It
+**     is obtained from polar motion observations by numerical
+**     integration, and so is in essence unpredictable.  However, it is
+**     dominated by a secular drift of about 47 microarcseconds per
+**     century, and so can be taken into account by using s' = -47*t,
+**     where t is centuries since J2000.0.  The function iauSp00
+**     implements this approximation.
+**
+**  3) The matrix operates in the sense V(TRS) = rpom * V(CIP), meaning
+**     that it is the final rotation when computing the pointing
+**     direction to a celestial source.
+**
+**  Called:
+**     iauIr        initialize r-matrix to identity
+**     iauRz        rotate around Z-axis
+**     iauRy        rotate around Y-axis
+**     iauRx        rotate around X-axis
+**
+**  Reference:
+**
+**     McCarthy, D. D., Petit, G. (eds.), IERS Conventions (2003),
+**     IERS Technical Note No. 32, BKG (2004)
+**
+**  This revision:  2009 December 17
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+
+/* Construct the matrix. */
+   iauIr(rpom);
+   iauRz(sp, rpom);
+   iauRy(-xp, rpom);
+   iauRx(-yp, rpom);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauPpp(double a[3], double b[3], double apb[3])
+/*
+**  - - - - - - -
+**   i a u P p p
+**  - - - - - - -
+**
+**  P-vector addition.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  vector/matrix support function.
+**
+**  Given:
+**     a        double[3]      first p-vector
+**     b        double[3]      second p-vector
+**
+**  Returned:
+**     apb      double[3]      a + b
+**
+**  Note:
+**     It is permissible to re-use the same array for any of the
+**     arguments.
+**
+**  This revision:  2008 November 18
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   apb[0] = a[0] + b[0];
+   apb[1] = a[1] + b[1];
+   apb[2] = a[2] + b[2];
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauPpsp(double a[3], double s, double b[3], double apsb[3])
+/*
+**  - - - - - - - -
+**   i a u P p s p
+**  - - - - - - - -
+**
+**  P-vector plus scaled p-vector.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  vector/matrix support function.
+**
+**  Given:
+**     a      double[3]     first p-vector
+**     s      double        scalar (multiplier for b)
+**     b      double[3]     second p-vector
+**
+**  Returned:
+**     apsb   double[3]     a + s*b
+**
+**  Note:
+**     It is permissible for any of a, b and apsb to be the same array.
+**
+**  Called:
+**     iauSxp       multiply p-vector by scalar
+**     iauPpp       p-vector plus p-vector
+**
+**  This revision:  2008 November 18
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double sb[3];
+
+
+/* s*b. */
+   iauSxp(s, b, sb);
+
+/* a + s*b. */
+   iauPpp(a, sb, apsb);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauPr00(double date1, double date2, double *dpsipr, double *depspr)
+/*
+**  - - - - - - - -
+**   i a u P r 0 0
+**  - - - - - - - -
+**
+**  Precession-rate part of the IAU 2000 precession-nutation models
+**  (part of MHB2000).
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  canonical model.
+**
+**  Given:
+**     date1,date2    double  TT as a 2-part Julian Date (Note 1)
+**
+**  Returned:
+**     dpsipr,depspr  double  precession corrections (Notes 2,3)
+**
+**  Notes:
+**
+**  1) The TT date date1+date2 is a Julian Date, apportioned in any
+**     convenient way between the two arguments.  For example,
+**     JD(TT)=2450123.7 could be expressed in any of these ways,
+**     among others:
+**
+**            date1          date2
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in
+**     cases where the loss of several decimal digits of resolution
+**     is acceptable.  The J2000 method is best matched to the way
+**     the argument is handled internally and will deliver the
+**     optimum resolution.  The MJD method and the date & time methods
+**     are both good compromises between resolution and convenience.
+**
+**  2) The precession adjustments are expressed as "nutation
+**     components", corrections in longitude and obliquity with respect
+**     to the J2000.0 equinox and ecliptic.
+**
+**  3) Although the precession adjustments are stated to be with respect
+**     to Lieske et al. (1977), the MHB2000 model does not specify which
+**     set of Euler angles are to be used and how the adjustments are to
+**     be applied.  The most literal and straightforward procedure is to
+**     adopt the 4-rotation epsilon_0, psi_A, omega_A, xi_A option, and
+**     to add dpsipr to psi_A and depspr to both omega_A and eps_A.
+**
+**  4) This is an implementation of one aspect of the IAU 2000A nutation
+**     model, formally adopted by the IAU General Assembly in 2000,
+**     namely MHB2000 (Mathews et al. 2002).
+**
+**  References:
+**
+**     Lieske, J.H., Lederle, T., Fricke, W. & Morando, B., "Expressions
+**     for the precession quantities based upon the IAU (1976) System of
+**     Astronomical Constants", Astron.Astrophys., 58, 1-16 (1977)
+**
+**     Mathews, P.M., Herring, T.A., Buffet, B.A., "Modeling of nutation
+**     and precession   New nutation series for nonrigid Earth and
+**     insights into the Earth's interior", J.Geophys.Res., 107, B4,
+**     2002.  The MHB2000 code itself was obtained on 9th September 2002
+**     from ftp://maia.usno.navy.mil/conv2000/chapter5/IAU2000A.
+**
+**     Wallace, P.T., "Software for Implementing the IAU 2000
+**     Resolutions", in IERS Workshop 5.1 (2002).
+**
+**  This revision:  2009 December 17
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double t;
+
+/* Precession and obliquity corrections (radians per century) */
+   static const double PRECOR = -0.29965 * DAS2R,
+                       OBLCOR = -0.02524 * DAS2R;
+
+
+/* Interval between fundamental epoch J2000.0 and given date (JC). */
+   t = ((date1 - DJ00) + date2) / DJC;
+
+/* Precession rate contributions with respect to IAU 1976/80. */
+   *dpsipr = PRECOR * t;
+   *depspr = OBLCOR * t;
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauPrec76(double ep01, double ep02, double ep11, double ep12,
+               double *zeta, double *z, double *theta)
+/*
+**  - - - - - - - - - -
+**   i a u P r e c 7 6
+**  - - - - - - - - - -
+**
+**  IAU 1976 precession model.
+**
+**  This function forms the three Euler angles which implement general
+**  precession between two epochs, using the IAU 1976 model (as for
+**  the FK5 catalog).
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  canonical model.
+**
+**  Given:
+**     ep01,ep02   double    TDB starting epoch (Note 1)
+**     ep11,ep12   double    TDB ending epoch (Note 1)
+**
+**  Returned:
+**     zeta        double    1st rotation: radians cw around z
+**     z           double    3rd rotation: radians cw around z
+**     theta       double    2nd rotation: radians ccw around y
+**
+**  Notes:
+**
+**  1) The epochs ep01+ep02 and ep11+ep12 are Julian Dates, apportioned
+**     in any convenient way between the arguments epn1 and epn2.  For
+**     example, JD(TDB)=2450123.7 could be expressed in any of these
+**     ways, among others:
+**
+**             epn1          epn2
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in cases
+**     where the loss of several decimal digits of resolution is
+**     acceptable.  The J2000 method is best matched to the way the
+**     argument is handled internally and will deliver the optimum
+**     optimum resolution.  The MJD method and the date & time methods
+**     are both good compromises between resolution and convenience.
+**     The two epochs may be expressed using different methods, but at
+**     the risk of losing some resolution.
+**
+**  2) The accumulated precession angles zeta, z, theta are expressed
+**     through canonical polynomials which are valid only for a limited
+**     time span.  In addition, the IAU 1976 precession rate is known to
+**     be imperfect.  The absolute accuracy of the present formulation
+**     is better than 0.1 arcsec from 1960AD to 2040AD, better than
+**     1 arcsec from 1640AD to 2360AD, and remains below 3 arcsec for
+**     the whole of the period 500BC to 3000AD.  The errors exceed
+**     10 arcsec outside the range 1200BC to 3900AD, exceed 100 arcsec
+**     outside 4200BC to 5600AD and exceed 1000 arcsec outside 6800BC to
+**     8200AD.
+**
+**  3) The three angles are returned in the conventional order, which
+**     is not the same as the order of the corresponding Euler
+**     rotations.  The precession matrix is
+**     R_3(-z) x R_2(+theta) x R_3(-zeta).
+**
+**  Reference:
+**
+**     Lieske, J.H., 1979, Astron.Astrophys. 73, 282, equations
+**     (6) & (7), p283.
+**
+**  This revision:  2009 December 17
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double t0, t, tas2r, w;
+
+
+/* Interval between fundamental epoch J2000.0 and start epoch (JC). */
+   t0 = ((ep01 - DJ00) + ep02) / DJC;
+
+/* Interval over which precession required (JC). */
+   t = ((ep11 - ep01) + (ep12 - ep02)) / DJC;
+
+/* Euler angles. */
+   tas2r = t * DAS2R;
+   w = 2306.2181 + (1.39656 - 0.000139 * t0) * t0;
+
+   *zeta = (w + ((0.30188 - 0.000344 * t0) + 0.017998 * t) * t) * tas2r;
+
+   *z = (w + ((1.09468 + 0.000066 * t0) + 0.018203 * t) * t) * tas2r;
+
+   *theta = ((2004.3109 + (-0.85330 - 0.000217 * t0) * t0)
+          + ((-0.42665 - 0.000217 * t0) - 0.041833 * t) * t) * tas2r;
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauPv2p(double pv[2][3], double p[3])
+/*
+**  - - - - - - - -
+**   i a u P v 2 p
+**  - - - - - - - -
+**
+**  Discard velocity component of a pv-vector.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  vector/matrix support function.
+**
+**  Given:
+**     pv      double[2][3]     pv-vector
+**
+**  Returned:
+**     p       double[3]        p-vector
+**
+**  Called:
+**     iauCp        copy p-vector
+**
+**  This revision:  2008 May 11
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   iauCp(pv[0], p);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauPv2s(double pv[2][3],
+             double *theta, double *phi, double *r,
+             double *td, double *pd, double *rd)
+/*
+**  - - - - - - - -
+**   i a u P v 2 s
+**  - - - - - - - -
+**
+**  Convert position/velocity from Cartesian to spherical coordinates.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  vector/matrix support function.
+**
+**  Given:
+**     pv       double[2][3]  pv-vector
+**
+**  Returned:
+**     theta    double        longitude angle (radians)
+**     phi      double        latitude angle (radians)
+**     r        double        radial distance
+**     td       double        rate of change of theta
+**     pd       double        rate of change of phi
+**     rd       double        rate of change of r
+**
+**  Notes:
+**
+**  1) If the position part of pv is null, theta, phi, td and pd
+**     are indeterminate.  This is handled by extrapolating the
+**     position through unit time by using the velocity part of
+**     pv.  This moves the origin without changing the direction
+**     of the velocity component.  If the position and velocity
+**     components of pv are both null, zeroes are returned for all
+**     six results.
+**
+**  2) If the position is a pole, theta, td and pd are indeterminate.
+**     In such cases zeroes are returned for all three.
+**
+**  This revision:  2008 October 28
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double x, y, z, xd, yd, zd, rxy2, rxy, r2, rtrue, rw, xyp;
+
+
+/* Components of position/velocity vector. */
+   x  = pv[0][0];
+   y  = pv[0][1];
+   z  = pv[0][2];
+   xd = pv[1][0];
+   yd = pv[1][1];
+   zd = pv[1][2];
+
+/* Component of r in XY plane squared. */
+   rxy2 = x*x + y*y;
+
+/* Modulus squared. */
+   r2 = rxy2 + z*z;
+
+/* Modulus. */
+   rtrue = sqrt(r2);
+
+/* If null vector, move the origin along the direction of movement. */
+   rw = rtrue;
+   if (rtrue == 0.0) {
+       x = xd;
+       y = yd;
+       z = zd;
+       rxy2 = x*x + y*y;
+       r2 = rxy2 + z*z;
+       rw = sqrt(r2);
+   }
+
+/* Position and velocity in spherical coordinates. */
+   rxy = sqrt(rxy2);
+   xyp = x*xd + y*yd;
+   if (rxy2 != 0.0) {
+       *theta = atan2(y, x);
+       *phi = atan2(z, rxy);
+       *td = (x*yd - y*xd) / rxy2;
+       *pd = (zd*rxy2 - z*xyp) / (r2*rxy);
+   } else {
+       *theta = 0.0;
+       *phi = (z != 0.0) ? atan2(z, rxy) : 0.0;
+       *td = 0.0;
+       *pd = 0.0;
+   }
+   *r = rtrue;
+   *rd = (rw != 0.0) ? (xyp + z*zd) / rw : 0.0;
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauPvdpv(double a[2][3], double b[2][3], double adb[2])
+/*
+**  - - - - - - - - -
+**   i a u P v d p v
+**  - - - - - - - - -
+**
+**  Inner (=scalar=dot) product of two pv-vectors.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  vector/matrix support function.
+**
+**  Given:
+**     a        double[2][3]      first pv-vector
+**     b        double[2][3]      second pv-vector
+**
+**  Returned:
+**     adb      double[2]         a . b (see note)
+**
+**  Note:
+**
+**     If the position and velocity components of the two pv-vectors are
+**     ( ap, av ) and ( bp, bv ), the result, a . b, is the pair of
+**     numbers ( ap . bp , ap . bv + av . bp ).  The two numbers are the
+**     dot-product of the two p-vectors and its derivative.
+**
+**  Called:
+**     iauPdp       scalar product of two p-vectors
+**
+**  This revision:  2008 May 22
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double adbd, addb;
+
+
+/* a . b = constant part of result. */
+   adb[0] = iauPdp(a[0], b[0]);
+
+/* a . bdot */
+   adbd = iauPdp(a[0], b[1]);
+
+/* adot . b */
+   addb = iauPdp(a[1], b[0]);
+
+/* Velocity part of result. */
+   adb[1] = adbd + addb;
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauPvm(double pv[2][3], double *r, double *s)
+/*
+**  - - - - - - -
+**   i a u P v m
+**  - - - - - - -
+**
+**  Modulus of pv-vector.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  vector/matrix support function.
+**
+**  Given:
+**     pv     double[2][3]   pv-vector
+**
+**  Returned:
+**     r      double         modulus of position component
+**     s      double         modulus of velocity component
+**
+**  Called:
+**     iauPm        modulus of p-vector
+**
+**  This revision:  2008 May 22
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+/* Distance. */
+   *r = iauPm(pv[0]);
+
+/* Speed. */
+   *s = iauPm(pv[1]);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauPvmpv(double a[2][3], double b[2][3], double amb[2][3])
+/*
+**  - - - - - - - - -
+**   i a u P v m p v
+**  - - - - - - - - -
+**
+**  Subtract one pv-vector from another.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  vector/matrix support function.
+**
+**  Given:
+**     a       double[2][3]      first pv-vector
+**     b       double[2][3]      second pv-vector
+**
+**  Returned:
+**     amb     double[2][3]      a - b
+**
+**  Note:
+**     It is permissible to re-use the same array for any of the
+**     arguments.
+**
+**  Called:
+**     iauPmp       p-vector minus p-vector
+**
+**  This revision:  2008 November 18
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   iauPmp(a[0], b[0], amb[0]);
+   iauPmp(a[1], b[1], amb[1]);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauPvppv(double a[2][3], double b[2][3], double apb[2][3])
+/*
+**  - - - - - - - - -
+**   i a u P v p p v
+**  - - - - - - - - -
+**
+**  Add one pv-vector to another.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  vector/matrix support function.
+**
+**  Given:
+**     a        double[2][3]      first pv-vector
+**     b        double[2][3]      second pv-vector
+**
+**  Returned:
+**     apb      double[2][3]      a + b
+**
+**  Note:
+**     It is permissible to re-use the same array for any of the
+**     arguments.
+**
+**  Called:
+**     iauPpp       p-vector plus p-vector
+**
+**  This revision:  2008 November 18
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   iauPpp(a[0], b[0], apb[0]);
+   iauPpp(a[1], b[1], apb[1]);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+int iauPvstar(double pv[2][3], double *ra, double *dec,
+              double *pmr, double *pmd, double *px, double *rv)
+/*
+**  - - - - - - - - - -
+**   i a u P v s t a r
+**  - - - - - - - - - -
+**
+**  Convert star position+velocity vector to catalog coordinates.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given (Note 1):
+**     pv     double[2][3]   pv-vector (AU, AU/day)
+**
+**  Returned (Note 2):
+**     ra     double         right ascension (radians)
+**     dec    double         declination (radians)
+**     pmr    double         RA proper motion (radians/year)
+**     pmd    double         Dec proper motion (radians/year)
+**     px     double         parallax (arcsec)
+**     rv     double         radial velocity (km/s, positive = receding)
+**
+**  Returned (function value):
+**            int            status:
+**                              0 = OK
+**                             -1 = superluminal speed (Note 5)
+**                             -2 = null position vector
+**
+**  Notes:
+**
+**  1) The specified pv-vector is the coordinate direction (and its rate
+**     of change) for the date at which the light leaving the star
+**     reached the solar-system barycenter.
+**
+**  2) The star data returned by this function are "observables" for an
+**     imaginary observer at the solar-system barycenter.  Proper motion
+**     and radial velocity are, strictly, in terms of barycentric
+**     coordinate time, TCB.  For most practical applications, it is
+**     permissible to neglect the distinction between TCB and ordinary
+**     "proper" time on Earth (TT/TAI).  The result will, as a rule, be
+**     limited by the intrinsic accuracy of the proper-motion and
+**     radial-velocity data;  moreover, the supplied pv-vector is likely
+**     to be merely an intermediate result (for example generated by the
+**     function iauStarpv), so that a change of time unit will cancel
+**     out overall.
+**
+**     In accordance with normal star-catalog conventions, the object's
+**     right ascension and declination are freed from the effects of
+**     secular aberration.  The frame, which is aligned to the catalog
+**     equator and equinox, is Lorentzian and centered on the SSB.
+**
+**     Summarizing, the specified pv-vector is for most stars almost
+**     identical to the result of applying the standard geometrical
+**     "space motion" transformation to the catalog data.  The
+**     differences, which are the subject of the Stumpff paper cited
+**     below, are:
+**
+**     (i) In stars with significant radial velocity and proper motion,
+**     the constantly changing light-time distorts the apparent proper
+**     motion.  Note that this is a classical, not a relativistic,
+**     effect.
+**
+**     (ii) The transformation complies with special relativity.
+**
+**  3) Care is needed with units.  The star coordinates are in radians
+**     and the proper motions in radians per Julian year, but the
+**     parallax is in arcseconds; the radial velocity is in km/s, but
+**     the pv-vector result is in AU and AU/day.
+**
+**  4) The proper motions are the rate of change of the right ascension
+**     and declination at the catalog epoch and are in radians per Julian
+**     year.  The RA proper motion is in terms of coordinate angle, not
+**     true angle, and will thus be numerically larger at high
+**     declinations.
+**
+**  5) Straight-line motion at constant speed in the inertial frame is
+**     assumed.  If the speed is greater than or equal to the speed of
+**     light, the function aborts with an error status.
+**
+**  6) The inverse transformation is performed by the function iauStarpv.
+**
+**  Called:
+**     iauPn        decompose p-vector into modulus and direction
+**     iauPdp       scalar product of two p-vectors
+**     iauSxp       multiply p-vector by scalar
+**     iauPmp       p-vector minus p-vector
+**     iauPm        modulus of p-vector
+**     iauPpp       p-vector plus p-vector
+**     iauPv2s      pv-vector to spherical
+**     iauAnp       normalize angle into range 0 to 2pi
+**
+**  Reference:
+**
+**     Stumpff, P., 1985, Astron.Astrophys. 144, 232-240.
+**
+**  This revision:  2008 May 18
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double r, x[3], vr, ur[3], vt, ut[3], bett, betr, d, w, del,
+          usr[3], ust[3], a, rad, decd, rd;
+
+
+/* Isolate the radial component of the velocity (AU/day, inertial). */
+   iauPn(pv[0], &r, x);
+   vr = iauPdp(x, pv[1]);
+   iauSxp(vr, x, ur);
+
+/* Isolate the transverse component of the velocity (AU/day, inertial). */
+   iauPmp(pv[1], ur, ut);
+   vt = iauPm(ut);
+
+/* Special-relativity dimensionless parameters. */
+   bett = vt / DC;
+   betr = vr / DC;
+
+/* The inertial-to-observed correction terms. */
+   d = 1.0 + betr;
+   w = 1.0 - betr*betr - bett*bett;
+   if (d == 0.0 || w < 0) return -1;
+   del = sqrt(w) - 1.0;
+
+/* Apply relativistic correction factor to radial velocity component. */
+   w = (betr != 0) ? (betr - del) / (betr * d) : 1.0;
+   iauSxp(w, ur, usr);
+
+/* Apply relativistic correction factor to tangential velocity */
+/* component.                                                  */
+   iauSxp(1.0/d, ut, ust);
+
+/* Combine the two to obtain the observed velocity vector (AU/day). */
+   iauPpp(usr, ust, pv[1]);
+
+/* Cartesian to spherical. */
+   iauPv2s(pv, &a, dec, &r, &rad, &decd, &rd);
+   if (r == 0.0) return -2;
+
+/* Return RA in range 0 to 2pi. */
+   *ra = iauAnp(a);
+
+/* Return proper motions in radians per year. */
+   *pmr = rad * DJY;
+   *pmd = decd * DJY;
+
+/* Return parallax in arcsec. */
+   *px = DR2AS / r;
+
+/* Return radial velocity in km/s. */
+   *rv = 1e-3 * rd * DAU / DAYSEC;
+
+/* OK status. */
+   return 0;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauPvu(double dt, double pv[2][3], double upv[2][3])
+/*
+**  - - - - - - -
+**   i a u P v u
+**  - - - - - - -
+**
+**  Update a pv-vector.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  vector/matrix support function.
+**
+**  Given:
+**     dt       double           time interval
+**     pv       double[2][3]     pv-vector
+**
+**  Returned:
+**     upv      double[2][3]     p updated, v unchanged
+**
+**  Notes:
+**
+**  1) "Update" means "refer the position component of the vector
+**     to a new date dt time units from the existing date".
+**
+**  2) The time units of dt must match those of the velocity.
+**
+**  3) It is permissible for pv and upv to be the same array.
+**
+**  Called:
+**     iauPpsp      p-vector plus scaled p-vector
+**     iauCp        copy p-vector
+**
+**  This revision:  2008 November 17
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   iauPpsp(pv[0], dt, pv[1], upv[0]);
+   iauCp(pv[1], upv[1]);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauPvup(double dt, double pv[2][3], double p[3])
+/*
+**  - - - - - - - -
+**   i a u P v u p
+**  - - - - - - - -
+**
+**  Update a pv-vector, discarding the velocity component.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  vector/matrix support function.
+**
+**  Given:
+**     dt       double            time interval
+**     pv       double[2][3]      pv-vector
+**
+**  Returned:
+**     p        double[3]         p-vector
+**
+**  Notes:
+**
+**  1) "Update" means "refer the position component of the vector to a
+**     new date dt time units from the existing date".
+**
+**  2) The time units of dt must match those of the velocity.
+**
+**  This revision:  2008 May 11
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   p[0] = pv[0][0] + dt * pv[1][0];
+   p[1] = pv[0][1] + dt * pv[1][1];
+   p[2] = pv[0][2] + dt * pv[1][2];
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauPvxpv(double a[2][3], double b[2][3], double axb[2][3])
+/*
+**  - - - - - - - - -
+**   i a u P v x p v
+**  - - - - - - - - -
+**
+**  Outer (=vector=cross) product of two pv-vectors.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  vector/matrix support function.
+**
+**  Given:
+**     a        double[2][3]      first pv-vector
+**     b        double[2][3]      second pv-vector
+**
+**  Returned:
+**     axb      double[2][3]      a x b
+**
+**  Notes:
+**
+**  1) If the position and velocity components of the two pv-vectors are
+**     ( ap, av ) and ( bp, bv ), the result, a x b, is the pair of
+**     vectors ( ap x bp, ap x bv + av x bp ).  The two vectors are the
+**     cross-product of the two p-vectors and its derivative.
+**
+**  2) It is permissible to re-use the same array for any of the
+**     arguments.
+**
+**  Called:
+**     iauCpv       copy pv-vector
+**     iauPxp       vector product of two p-vectors
+**     iauPpp       p-vector plus p-vector
+**
+**  This revision:  2008 November 18
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double wa[2][3], wb[2][3], axbd[3], adxb[3];
+
+
+/* Make copies of the inputs. */
+   iauCpv(a, wa);
+   iauCpv(b, wb);
+
+/* a x b = position part of result. */
+   iauPxp(wa[0], wb[0], axb[0]);
+
+/* a x bdot + adot x b = velocity part of result. */
+   iauPxp(wa[0], wb[1], axbd);
+   iauPxp(wa[1], wb[0], adxb);
+   iauPpp(axbd, adxb, axb[1]);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauPxp(double a[3], double b[3], double axb[3])
+/*
+**  - - - - - - -
+**   i a u P x p
+**  - - - - - - -
+**
+**  p-vector outer (=vector=cross) product.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  vector/matrix support function.
+**
+**  Given:
+**     a        double[3]      first p-vector
+**     b        double[3]      second p-vector
+**
+**  Returned:
+**     axb      double[3]      a x b
+**
+**  Note:
+**     It is permissible to re-use the same array for any of the
+**     arguments.
+**
+**  This revision:  2008 November 18
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double xa, ya, za, xb, yb, zb;
+
+
+   xa = a[0];
+   ya = a[1];
+   za = a[2];
+   xb = b[0];
+   yb = b[1];
+   zb = b[2];
+   axb[0] = ya*zb - za*yb;
+   axb[1] = za*xb - xa*zb;
+   axb[2] = xa*yb - ya*xb;
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauRm2v(double r[3][3], double w[3])
+/*
+**  - - - - - - - -
+**   i a u R m 2 v
+**  - - - - - - - -
+**
+**  Express an r-matrix as an r-vector.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  vector/matrix support function.
+**
+**  Given:
+**     r        double[3][3]    rotation matrix
+**
+**  Returned:
+**     w        double[3]       rotation vector (Note 1)
+**
+**  Notes:
+**
+**  1) A rotation matrix describes a rotation through some angle about
+**     some arbitrary axis called the Euler axis.  The "rotation vector"
+**     returned by this function has the same direction as the Euler axis,
+**     and its magnitude is the angle in radians.  (The magnitude and
+**     direction can be separated by means of the function iauPn.)
+**
+**  2) If r is null, so is the result.  If r is not a rotation matrix
+**     the result is undefined;  r must be proper (i.e. have a positive
+**     determinant) and real orthogonal (inverse = transpose).
+**
+**  3) The reference frame rotates clockwise as seen looking along
+**     the rotation vector from the origin.
+**
+**  This revision:  2010 August 27
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double x, y, z, s2, c2, phi, f;
+
+
+   x = r[1][2] - r[2][1];
+   y = r[2][0] - r[0][2];
+   z = r[0][1] - r[1][0];
+   s2 = sqrt(x*x + y*y + z*z);
+   if (s2 != 0) {
+      c2 = r[0][0] + r[1][1] + r[2][2] - 1.0;
+      phi = atan2(s2, c2);
+      f =  phi / s2;
+      w[0] = x * f;
+      w[1] = y * f;
+      w[2] = z * f;
+   } else {
+      w[0] = 0.0;
+      w[1] = 0.0;
+      w[2] = 0.0;
+   }
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauRv2m(double w[3], double r[3][3])
+/*
+**  - - - - - - - -
+**   i a u R v 2 m
+**  - - - - - - - -
+**
+**  Form the r-matrix corresponding to a given r-vector.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  vector/matrix support function.
+**
+**  Given:
+**     w        double[3]      rotation vector (Note 1)
+**
+**  Returned:
+**     r        double[3][3]    rotation matrix
+**
+**  Notes:
+**
+**  1) A rotation matrix describes a rotation through some angle about
+**     some arbitrary axis called the Euler axis.  The "rotation vector"
+**     supplied to This function has the same direction as the Euler
+**     axis, and its magnitude is the angle in radians.
+**
+**  2) If w is null, the unit matrix is returned.
+**
+**  3) The reference frame rotates clockwise as seen looking along the
+**     rotation vector from the origin.
+**
+**  This revision:  2008 May 11
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double x, y, z, phi, s, c, f;
+
+
+/* Euler angle (magnitude of rotation vector) and functions. */
+   x = w[0];
+   y = w[1];
+   z = w[2];
+   phi = sqrt(x*x + y*y + z*z);
+   s = sin(phi);
+   c = cos(phi);
+   f = 1.0 - c;
+
+/* Euler axis (direction of rotation vector), perhaps null. */
+   if (phi != 0.0) {
+       x /= phi;
+       y /= phi;
+       z /= phi;
+   }
+
+/* Form the rotation matrix. */
+   r[0][0] = x*x*f + c;
+   r[0][1] = x*y*f + z*s;
+   r[0][2] = x*z*f - y*s;
+   r[1][0] = y*x*f - z*s;
+   r[1][1] = y*y*f + c;
+   r[1][2] = y*z*f + x*s;
+   r[2][0] = z*x*f + y*s;
+   r[2][1] = z*y*f - x*s;
+   r[2][2] = z*z*f + c;
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauRx(double phi, double r[3][3])
+/*
+**  - - - - - -
+**   i a u R x
+**  - - - - - -
+**
+**  Rotate an r-matrix about the x-axis.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  vector/matrix support function.
+**
+**  Given:
+**     phi    double          angle (radians)
+**
+**  Given and returned:
+**     r      double[3][3]    r-matrix
+**
+**  Sign convention:  The matrix can be used to rotate the reference
+**  frame of a vector.  Calling this function with positive phi
+**  incorporates in the matrix an additional rotation, about the x-axis,
+**  anticlockwise as seen looking towards the origin from positive x.
+**
+**  Called:
+**     iauIr        initialize r-matrix to identity
+**     iauRxr       product of two r-matrices
+**     iauCr        copy r-matrix
+**
+**  This revision:  2008 May 22
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double s, c, a[3][3], w[3][3];
+
+
+/* Matrix representing new rotation. */
+   s = sin(phi);
+   c = cos(phi);
+   iauIr(a);
+   a[1][1] =  c;
+   a[2][1] = -s;
+   a[1][2] =  s;
+   a[2][2] =  c;
+
+/* Rotate. */
+   iauRxr(a, r, w);
+
+/* Return result. */
+   iauCr(w, r);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauRxp(double r[3][3], double p[3], double rp[3])
+/*
+**  - - - - - - -
+**   i a u R x p
+**  - - - - - - -
+**
+**  Multiply a p-vector by an r-matrix.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  vector/matrix support function.
+**
+**  Given:
+**     r        double[3][3]    r-matrix
+**     p        double[3]       p-vector
+**
+**  Returned:
+**     rp       double[3]       r * p
+**
+**  Note:
+**     It is permissible for p and rp to be the same array.
+**
+**  Called:
+**     iauCp        copy p-vector
+**
+**  This revision:  2008 October 28
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double w, wrp[3];
+   int i, j;
+
+
+/* Matrix r * vector p. */
+   for (j = 0; j < 3; j++) {
+       w = 0.0;
+       for (i = 0; i < 3; i++) {
+           w += r[j][i] * p[i];
+       }
+       wrp[j] = w;
+   }
+
+/* Return the result. */
+   iauCp(wrp, rp);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauRxpv(double r[3][3], double pv[2][3], double rpv[2][3])
+/*
+**  - - - - - - - -
+**   i a u R x p v
+**  - - - - - - - -
+**
+**  Multiply a pv-vector by an r-matrix.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  vector/matrix support function.
+**
+**  Given:
+**     r        double[3][3]    r-matrix
+**     pv       double[2][3]    pv-vector
+**
+**  Returned:
+**     rpv      double[2][3]    r * pv
+**
+**  Note:
+**     It is permissible for pv and rpv to be the same array.
+**
+**  Called:
+**     iauRxp       product of r-matrix and p-vector
+**
+**  This revision:  2008 October 28
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   iauRxp(r, pv[0], rpv[0]);
+   iauRxp(r, pv[1], rpv[1]);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauRxr(double a[3][3], double b[3][3], double atb[3][3])
+/*
+**  - - - - - - -
+**   i a u R x r
+**  - - - - - - -
+**
+**  Multiply two r-matrices.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  vector/matrix support function.
+**
+**  Given:
+**     a        double[3][3]    first r-matrix
+**     b        double[3][3]    second r-matrix
+**
+**  Returned:
+**     atb      double[3][3]    a * b
+**
+**  Note:
+**     It is permissible to re-use the same array for any of the
+**     arguments.
+**
+**  Called:
+**     iauCr        copy r-matrix
+**
+**  This revision:  2008 November 18
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   int i, j, k;
+   double w, wm[3][3];
+
+
+   for (i = 0; i < 3; i++) {
+      for (j = 0; j < 3; j++) {
+         w = 0.0;
+         for (k = 0; k < 3; k++) {
+            w +=  a[i][k] * b[k][j];
+         }
+         wm[i][j] = w;
+      }
+   }
+   iauCr(wm, atb);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauRy(double theta, double r[3][3])
+/*
+**  - - - - - -
+**   i a u R y
+**  - - - - - -
+**
+**  Rotate an r-matrix about the y-axis.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  vector/matrix support function.
+**
+**  Given:
+**     theta  double          angle (radians)
+**
+**  Given and returned:
+**     r      double[3][3]    r-matrix
+**
+**  Sign convention:  The matrix can be used to rotate the reference
+**  frame of a vector.  Calling This function with positive theta
+**  incorporates in the matrix an additional rotation, about the y-axis,
+**  anticlockwise as seen looking towards the origin from positive y.
+**
+**  Called:
+**     iauIr        initialize r-matrix to identity
+**     iauRxr       product of two r-matrices
+**     iauCr        copy r-matrix
+**
+**  This revision:  2008 May 22
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double s, c, a[3][3], w[3][3];
+
+
+/* Matrix representing new rotation. */
+   s = sin(theta);
+   c = cos(theta);
+   iauIr(a);
+   a[0][0] =  c;
+   a[2][0] =  s;
+   a[0][2] = -s;
+   a[2][2] =  c;
+
+/* Rotate. */
+   iauRxr(a, r, w);
+
+/* Return result. */
+   iauCr(w, r);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauRz(double psi, double r[3][3])
+/*
+**  - - - - - -
+**   i a u R z
+**  - - - - - -
+**
+**  Rotate an r-matrix about the z-axis.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  vector/matrix support function.
+**
+**  Given:
+**     psi    double          angle (radians)
+**
+**  Given and returned:
+**     r      double[3][3]    r-matrix, rotated
+**
+**  Sign convention:  The matrix can be used to rotate the reference
+**  frame of a vector.  Calling This function with positive psi
+**  incorporates in the matrix an additional rotation, about the z-axis,
+**  anticlockwise as seen looking towards the origin from positive z.
+**
+**  Called:
+**     iauIr        initialize r-matrix to identity
+**     iauRxr       product of two r-matrices
+**     iauCr        copy r-matrix
+**
+**  This revision:  2008 May 22
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double s, c, a[3][3], w[3][3];
+
+
+/* Matrix representing new rotation. */
+   s = sin(psi);
+   c = cos(psi);
+   iauIr(a);
+   a[0][0] =  c;
+   a[1][0] = -s;
+   a[0][1] =  s;
+   a[1][1] =  c;
+
+/* Rotate. */
+   iauRxr(a, r, w);
+
+/* Return result. */
+   iauCr(w, r);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+double iauS00(double date1, double date2, double x, double y)
+/*
+**  - - - - - - -
+**   i a u S 0 0
+**  - - - - - - -
+**
+**  The CIO locator s, positioning the Celestial Intermediate Origin on
+**  the equator of the Celestial Intermediate Pole, given the CIP's X,Y
+**  coordinates.  Compatible with IAU 2000A precession-nutation.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  canonical model.
+**
+**  Given:
+**     date1,date2   double    TT as a 2-part Julian Date (Note 1)
+**     x,y           double    CIP coordinates (Note 3)
+**
+**  Returned (function value):
+**                   double    the CIO locator s in radians (Note 2)
+**
+**  Notes:
+**
+**  1) The TT date date1+date2 is a Julian Date, apportioned in any
+**     convenient way between the two arguments.  For example,
+**     JD(TT)=2450123.7 could be expressed in any of these ways,
+**     among others:
+**
+**            date1          date2
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in
+**     cases where the loss of several decimal digits of resolution
+**     is acceptable.  The J2000 method is best matched to the way
+**     the argument is handled internally and will deliver the
+**     optimum resolution.  The MJD method and the date & time methods
+**     are both good compromises between resolution and convenience.
+**
+**  2) The CIO locator s is the difference between the right ascensions
+**     of the same point in two systems:  the two systems are the GCRS
+**     and the CIP,CIO, and the point is the ascending node of the
+**     CIP equator.  The quantity s remains below 0.1 arcsecond
+**     throughout 1900-2100.
+**
+**  3) The series used to compute s is in fact for s+XY/2, where X and Y
+**     are the x and y components of the CIP unit vector;  this series
+**     is more compact than a direct series for s would be.  This
+**     function requires X,Y to be supplied by the caller, who is
+**     responsible for providing values that are consistent with the
+**     supplied date.
+**
+**  4) The model is consistent with the IAU 2000A precession-nutation.
+**
+**  Called:
+**     iauFal03     mean anomaly of the Moon
+**     iauFalp03    mean anomaly of the Sun
+**     iauFaf03     mean argument of the latitude of the Moon
+**     iauFad03     mean elongation of the Moon from the Sun
+**     iauFaom03    mean longitude of the Moon's ascending node
+**     iauFave03    mean longitude of Venus
+**     iauFae03     mean longitude of Earth
+**     iauFapa03    general accumulated precession in longitude
+**
+**  References:
+**
+**     Capitaine, N., Chapront, J., Lambert, S. and Wallace, P.,
+**     "Expressions for the Celestial Intermediate Pole and Celestial
+**     Ephemeris Origin consistent with the IAU 2000A precession-
+**     nutation model", Astron.Astrophys. 400, 1145-1154 (2003)
+**
+**     n.b. The celestial ephemeris origin (CEO) was renamed "celestial
+**          intermediate origin" (CIO) by IAU 2006 Resolution 2.
+**
+**     McCarthy, D. D., Petit, G. (eds.), IERS Conventions (2003),
+**     IERS Technical Note No. 32, BKG (2004)
+**
+**  This revision:  2010 January 18
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+/* Time since J2000.0, in Julian centuries */
+   double t;
+
+/* Miscellaneous */
+   int i, j;
+   double a, w0, w1, w2, w3, w4, w5;
+
+/* Fundamental arguments */
+   double fa[8];
+
+/* Returned value */
+   double s;
+
+/* --------------------- */
+/* The series for s+XY/2 */
+/* --------------------- */
+
+   typedef struct {
+      int nfa[8];      /* coefficients of l,l',F,D,Om,LVe,LE,pA */
+      double s, c;     /* sine and cosine coefficients */
+   } TERM;
+
+/* Polynomial coefficients */
+   static const double sp[] = {
+
+   /* 1-6 */
+          94.00e-6,
+        3808.35e-6,
+        -119.94e-6,
+      -72574.09e-6,
+          27.70e-6,
+          15.61e-6
+   };
+
+/* Terms of order t^0 */
+   static const TERM s0[] = {
+
+   /* 1-10 */
+      {{ 0,  0,  0,  0,  1,  0,  0,  0}, -2640.73e-6,   0.39e-6 },
+      {{ 0,  0,  0,  0,  2,  0,  0,  0},   -63.53e-6,   0.02e-6 },
+      {{ 0,  0,  2, -2,  3,  0,  0,  0},   -11.75e-6,  -0.01e-6 },
+      {{ 0,  0,  2, -2,  1,  0,  0,  0},   -11.21e-6,  -0.01e-6 },
+      {{ 0,  0,  2, -2,  2,  0,  0,  0},     4.57e-6,   0.00e-6 },
+      {{ 0,  0,  2,  0,  3,  0,  0,  0},    -2.02e-6,   0.00e-6 },
+      {{ 0,  0,  2,  0,  1,  0,  0,  0},    -1.98e-6,   0.00e-6 },
+      {{ 0,  0,  0,  0,  3,  0,  0,  0},     1.72e-6,   0.00e-6 },
+      {{ 0,  1,  0,  0,  1,  0,  0,  0},     1.41e-6,   0.01e-6 },
+      {{ 0,  1,  0,  0, -1,  0,  0,  0},     1.26e-6,   0.01e-6 },
+
+   /* 11-20 */
+      {{ 1,  0,  0,  0, -1,  0,  0,  0},     0.63e-6,   0.00e-6 },
+      {{ 1,  0,  0,  0,  1,  0,  0,  0},     0.63e-6,   0.00e-6 },
+      {{ 0,  1,  2, -2,  3,  0,  0,  0},    -0.46e-6,   0.00e-6 },
+      {{ 0,  1,  2, -2,  1,  0,  0,  0},    -0.45e-6,   0.00e-6 },
+      {{ 0,  0,  4, -4,  4,  0,  0,  0},    -0.36e-6,   0.00e-6 },
+      {{ 0,  0,  1, -1,  1, -8, 12,  0},     0.24e-6,   0.12e-6 },
+      {{ 0,  0,  2,  0,  0,  0,  0,  0},    -0.32e-6,   0.00e-6 },
+      {{ 0,  0,  2,  0,  2,  0,  0,  0},    -0.28e-6,   0.00e-6 },
+      {{ 1,  0,  2,  0,  3,  0,  0,  0},    -0.27e-6,   0.00e-6 },
+      {{ 1,  0,  2,  0,  1,  0,  0,  0},    -0.26e-6,   0.00e-6 },
+
+   /* 21-30 */
+      {{ 0,  0,  2, -2,  0,  0,  0,  0},     0.21e-6,   0.00e-6 },
+      {{ 0,  1, -2,  2, -3,  0,  0,  0},    -0.19e-6,   0.00e-6 },
+      {{ 0,  1, -2,  2, -1,  0,  0,  0},    -0.18e-6,   0.00e-6 },
+      {{ 0,  0,  0,  0,  0,  8,-13, -1},     0.10e-6,  -0.05e-6 },
+      {{ 0,  0,  0,  2,  0,  0,  0,  0},    -0.15e-6,   0.00e-6 },
+      {{ 2,  0, -2,  0, -1,  0,  0,  0},     0.14e-6,   0.00e-6 },
+      {{ 0,  1,  2, -2,  2,  0,  0,  0},     0.14e-6,   0.00e-6 },
+      {{ 1,  0,  0, -2,  1,  0,  0,  0},    -0.14e-6,   0.00e-6 },
+      {{ 1,  0,  0, -2, -1,  0,  0,  0},    -0.14e-6,   0.00e-6 },
+      {{ 0,  0,  4, -2,  4,  0,  0,  0},    -0.13e-6,   0.00e-6 },
+
+   /* 31-33 */
+      {{ 0,  0,  2, -2,  4,  0,  0,  0},     0.11e-6,   0.00e-6 },
+      {{ 1,  0, -2,  0, -3,  0,  0,  0},    -0.11e-6,   0.00e-6 },
+      {{ 1,  0, -2,  0, -1,  0,  0,  0},    -0.11e-6,   0.00e-6 }
+   };
+
+/* Terms of order t^1 */
+   static const TERM s1[] ={
+
+   /* 1-3 */
+      {{ 0,  0,  0,  0,  2,  0,  0,  0},    -0.07e-6,   3.57e-6 },
+      {{ 0,  0,  0,  0,  1,  0,  0,  0},     1.71e-6,  -0.03e-6 },
+      {{ 0,  0,  2, -2,  3,  0,  0,  0},     0.00e-6,   0.48e-6 }
+   };
+
+/* Terms of order t^2 */
+   static const TERM s2[] ={
+
+   /* 1-10 */
+      {{ 0,  0,  0,  0,  1,  0,  0,  0},   743.53e-6,  -0.17e-6 },
+      {{ 0,  0,  2, -2,  2,  0,  0,  0},    56.91e-6,   0.06e-6 },
+      {{ 0,  0,  2,  0,  2,  0,  0,  0},     9.84e-6,  -0.01e-6 },
+      {{ 0,  0,  0,  0,  2,  0,  0,  0},    -8.85e-6,   0.01e-6 },
+      {{ 0,  1,  0,  0,  0,  0,  0,  0},    -6.38e-6,  -0.05e-6 },
+      {{ 1,  0,  0,  0,  0,  0,  0,  0},    -3.07e-6,   0.00e-6 },
+      {{ 0,  1,  2, -2,  2,  0,  0,  0},     2.23e-6,   0.00e-6 },
+      {{ 0,  0,  2,  0,  1,  0,  0,  0},     1.67e-6,   0.00e-6 },
+      {{ 1,  0,  2,  0,  2,  0,  0,  0},     1.30e-6,   0.00e-6 },
+      {{ 0,  1, -2,  2, -2,  0,  0,  0},     0.93e-6,   0.00e-6 },
+
+   /* 11-20 */
+      {{ 1,  0,  0, -2,  0,  0,  0,  0},     0.68e-6,   0.00e-6 },
+      {{ 0,  0,  2, -2,  1,  0,  0,  0},    -0.55e-6,   0.00e-6 },
+      {{ 1,  0, -2,  0, -2,  0,  0,  0},     0.53e-6,   0.00e-6 },
+      {{ 0,  0,  0,  2,  0,  0,  0,  0},    -0.27e-6,   0.00e-6 },
+      {{ 1,  0,  0,  0,  1,  0,  0,  0},    -0.27e-6,   0.00e-6 },
+      {{ 1,  0, -2, -2, -2,  0,  0,  0},    -0.26e-6,   0.00e-6 },
+      {{ 1,  0,  0,  0, -1,  0,  0,  0},    -0.25e-6,   0.00e-6 },
+      {{ 1,  0,  2,  0,  1,  0,  0,  0},     0.22e-6,   0.00e-6 },
+      {{ 2,  0,  0, -2,  0,  0,  0,  0},    -0.21e-6,   0.00e-6 },
+      {{ 2,  0, -2,  0, -1,  0,  0,  0},     0.20e-6,   0.00e-6 },
+
+   /* 21-25 */
+      {{ 0,  0,  2,  2,  2,  0,  0,  0},     0.17e-6,   0.00e-6 },
+      {{ 2,  0,  2,  0,  2,  0,  0,  0},     0.13e-6,   0.00e-6 },
+      {{ 2,  0,  0,  0,  0,  0,  0,  0},    -0.13e-6,   0.00e-6 },
+      {{ 1,  0,  2, -2,  2,  0,  0,  0},    -0.12e-6,   0.00e-6 },
+      {{ 0,  0,  2,  0,  0,  0,  0,  0},    -0.11e-6,   0.00e-6 }
+   };
+
+/* Terms of order t^3 */
+   static const TERM s3[] ={
+
+   /* 1-4 */
+      {{ 0,  0,  0,  0,  1,  0,  0,  0},     0.30e-6, -23.51e-6 },
+      {{ 0,  0,  2, -2,  2,  0,  0,  0},    -0.03e-6,  -1.39e-6 },
+      {{ 0,  0,  2,  0,  2,  0,  0,  0},    -0.01e-6,  -0.24e-6 },
+      {{ 0,  0,  0,  0,  2,  0,  0,  0},     0.00e-6,   0.22e-6 }
+   };
+
+/* Terms of order t^4 */
+   static const TERM s4[] ={
+
+   /* 1-1 */
+      {{ 0,  0,  0,  0,  1,  0,  0,  0},    -0.26e-6,  -0.01e-6 }
+   };
+
+/* Number of terms in the series */
+   const int NS0 = (int) (sizeof s0 / sizeof (TERM));
+   const int NS1 = (int) (sizeof s1 / sizeof (TERM));
+   const int NS2 = (int) (sizeof s2 / sizeof (TERM));
+   const int NS3 = (int) (sizeof s3 / sizeof (TERM));
+   const int NS4 = (int) (sizeof s4 / sizeof (TERM));
+
+/*--------------------------------------------------------------------*/
+
+/* Interval between fundamental epoch J2000.0 and current date (JC). */
+   t = ((date1 - DJ00) + date2) / DJC;
+
+/* Fundamental Arguments (from IERS Conventions 2003) */
+
+/* Mean anomaly of the Moon. */
+   fa[0] = iauFal03(t);
+
+/* Mean anomaly of the Sun. */
+   fa[1] = iauFalp03(t);
+
+/* Mean longitude of the Moon minus that of the ascending node. */
+   fa[2] = iauFaf03(t);
+
+/* Mean elongation of the Moon from the Sun. */
+   fa[3] = iauFad03(t);
+
+/* Mean longitude of the ascending node of the Moon. */
+   fa[4] = iauFaom03(t);
+
+/* Mean longitude of Venus. */
+   fa[5] = iauFave03(t);
+
+/* Mean longitude of Earth. */
+   fa[6] = iauFae03(t);
+
+/* General precession in longitude. */
+   fa[7] = iauFapa03(t);
+
+/* Evaluate s. */
+   w0 = sp[0];
+   w1 = sp[1];
+   w2 = sp[2];
+   w3 = sp[3];
+   w4 = sp[4];
+   w5 = sp[5];
+
+   for (i = NS0-1; i >= 0; i--) {
+   a = 0.0;
+   for (j = 0; j < 8; j++) {
+       a += (double)s0[i].nfa[j] * fa[j];
+   }
+   w0 += s0[i].s * sin(a) + s0[i].c * cos(a);
+   }
+
+   for (i = NS1-1; i >= 0; i--) {
+   a = 0.0;
+   for (j = 0; j < 8; j++) {
+       a += (double)s1[i].nfa[j] * fa[j];
+   }
+   w1 += s1[i].s * sin(a) + s1[i].c * cos(a);
+   }
+
+   for (i = NS2-1; i >= 0; i--) {
+   a = 0.0;
+   for (j = 0; j < 8; j++) {
+       a += (double)s2[i].nfa[j] * fa[j];
+   }
+   w2 += s2[i].s * sin(a) + s2[i].c * cos(a);
+   }
+
+   for (i = NS3-1; i >= 0; i--) {
+   a = 0.0;
+   for (j = 0; j < 8; j++) {
+       a += (double)s3[i].nfa[j] * fa[j];
+   }
+   w3 += s3[i].s * sin(a) + s3[i].c * cos(a);
+   }
+
+   for (i = NS4-1; i >= 0; i--) {
+   a = 0.0;
+   for (j = 0; j < 8; j++) {
+       a += (double)s4[i].nfa[j] * fa[j];
+   }
+   w4 += s4[i].s * sin(a) + s4[i].c * cos(a);
+   }
+
+   s = (w0 +
+       (w1 +
+       (w2 +
+       (w3 +
+       (w4 +
+        w5 * t) * t) * t) * t) * t) * DAS2R - x*y/2.0;
+
+   return s;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+double iauS00a(double date1, double date2)
+/*
+**  - - - - - - - -
+**   i a u S 0 0 a
+**  - - - - - - - -
+**
+**  The CIO locator s, positioning the Celestial Intermediate Origin on
+**  the equator of the Celestial Intermediate Pole, using the IAU 2000A
+**  precession-nutation model.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     date1,date2  double    TT as a 2-part Julian Date (Note 1)
+**
+**  Returned (function value):
+**                  double    the CIO locator s in radians (Note 2)
+**
+**  Notes:
+**
+**  1) The TT date date1+date2 is a Julian Date, apportioned in any
+**     convenient way between the two arguments.  For example,
+**     JD(TT)=2450123.7 could be expressed in any of these ways,
+**     among others:
+**
+**            date1          date2
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in
+**     cases where the loss of several decimal digits of resolution
+**     is acceptable.  The J2000 method is best matched to the way
+**     the argument is handled internally and will deliver the
+**     optimum resolution.  The MJD method and the date & time methods
+**     are both good compromises between resolution and convenience.
+**
+**  2) The CIO locator s is the difference between the right ascensions
+**     of the same point in two systems.  The two systems are the GCRS
+**     and the CIP,CIO, and the point is the ascending node of the
+**     CIP equator.  The CIO locator s remains a small fraction of
+**     1 arcsecond throughout 1900-2100.
+**
+**  3) The series used to compute s is in fact for s+XY/2, where X and Y
+**     are the x and y components of the CIP unit vector;  this series
+**     is more compact than a direct series for s would be.  The present
+**     function uses the full IAU 2000A nutation model when predicting
+**     the CIP position.  Faster results, with no significant loss of
+**     accuracy, can be obtained via the function iauS00b, which uses
+**     instead the IAU 2000B truncated model.
+**
+**  Called:
+**     iauPnm00a     classical NPB matrix, IAU 2000A
+**     iauBnp2xy     extract CIP X,Y from the BPN matrix
+**     iauS00        the CIO locator s, given X,Y, IAU 2000A
+**
+**  References:
+**
+**     Capitaine, N., Chapront, J., Lambert, S. and Wallace, P.,
+**     "Expressions for the Celestial Intermediate Pole and Celestial
+**     Ephemeris Origin consistent with the IAU 2000A precession-
+**     nutation model", Astron.Astrophys. 400, 1145-1154 (2003)
+**
+**     n.b. The celestial ephemeris origin (CEO) was renamed "celestial
+**          intermediate origin" (CIO) by IAU 2006 Resolution 2.
+**
+**     McCarthy, D. D., Petit, G. (eds.), IERS Conventions (2003),
+**     IERS Technical Note No. 32, BKG (2004)
+**
+**  This revision:  2010 January 18
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double rbpn[3][3], x, y, s;
+
+
+/* Bias-precession-nutation-matrix, IAU 2000A. */
+   iauPnm00a(date1, date2, rbpn);
+
+/* Extract the CIP coordinates. */
+   iauBpn2xy(rbpn, &x, &y);
+
+/* Compute the CIO locator s, given the CIP coordinates. */
+   s = iauS00(date1, date2, x, y);
+
+   return s;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+double iauS00b(double date1, double date2)
+/*
+**  - - - - - - - -
+**   i a u S 0 0 b
+**  - - - - - - - -
+**
+**  The CIO locator s, positioning the Celestial Intermediate Origin on
+**  the equator of the Celestial Intermediate Pole, using the IAU 2000B
+**  precession-nutation model.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     date1,date2  double    TT as a 2-part Julian Date (Note 1)
+**
+**  Returned (function value):
+**                  double    the CIO locator s in radians (Note 2)
+**
+**  Notes:
+**
+**  1) The TT date date1+date2 is a Julian Date, apportioned in any
+**     convenient way between the two arguments.  For example,
+**     JD(TT)=2450123.7 could be expressed in any of these ways,
+**     among others:
+**
+**            date1          date2
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in
+**     cases where the loss of several decimal digits of resolution
+**     is acceptable.  The J2000 method is best matched to the way
+**     the argument is handled internally and will deliver the
+**     optimum resolution.  The MJD method and the date & time methods
+**     are both good compromises between resolution and convenience.
+**
+**  2) The CIO locator s is the difference between the right ascensions
+**     of the same point in two systems.  The two systems are the GCRS
+**     and the CIP,CIO, and the point is the ascending node of the
+**     CIP equator.  The CIO locator s remains a small fraction of
+**     1 arcsecond throughout 1900-2100.
+**
+**  3) The series used to compute s is in fact for s+XY/2, where X and Y
+**     are the x and y components of the CIP unit vector;  this series
+**     is more compact than a direct series for s would be.  The present
+**     function uses the IAU 2000B truncated nutation model when
+**     predicting the CIP position.  The function iauS00a uses instead
+**     the full IAU 2000A model, but with no significant increase in
+**     accuracy and at some cost in speed.
+**
+**  Called:
+**     iauPnm00b     classical NPB matrix, IAU 2000B
+**     iauBnp2xy     extract CIP X,Y from the BPN matrix
+**     iauS00        the CIO locator s, given X,Y, IAU 2000A
+**
+**  References:
+**
+**     Capitaine, N., Chapront, J., Lambert, S. and Wallace, P.,
+**     "Expressions for the Celestial Intermediate Pole and Celestial
+**     Ephemeris Origin consistent with the IAU 2000A precession-
+**     nutation model", Astron.Astrophys. 400, 1145-1154 (2003)
+**
+**     n.b. The celestial ephemeris origin (CEO) was renamed "celestial
+**          intermediate origin" (CIO) by IAU 2006 Resolution 2.
+**
+**     McCarthy, D. D., Petit, G. (eds.), IERS Conventions (2003),
+**     IERS Technical Note No. 32, BKG (2004)
+**
+**  This revision:  2010 January 18
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double rbpn[3][3], x, y, s;
+
+
+/* Bias-precession-nutation-matrix, IAU 2000B. */
+   iauPnm00b(date1, date2, rbpn);
+
+/* Extract the CIP coordinates. */
+   iauBpn2xy(rbpn, &x, &y);
+
+/* Compute the CIO locator s, given the CIP coordinates. */
+   s = iauS00(date1, date2, x, y);
+
+   return s;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+double iauS06(double date1, double date2, double x, double y)
+/*
+**  - - - - - - -
+**   i a u S 0 6
+**  - - - - - - -
+**
+**  The CIO locator s, positioning the Celestial Intermediate Origin on
+**  the equator of the Celestial Intermediate Pole, given the CIP's X,Y
+**  coordinates.  Compatible with IAU 2006/2000A precession-nutation.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  canonical model.
+**
+**  Given:
+**     date1,date2   double    TT as a 2-part Julian Date (Note 1)
+**     x,y           double    CIP coordinates (Note 3)
+**
+**  Returned (function value):
+**                   double    the CIO locator s in radians (Note 2)
+**
+**  Notes:
+**
+**  1) The TT date date1+date2 is a Julian Date, apportioned in any
+**     convenient way between the two arguments.  For example,
+**     JD(TT)=2450123.7 could be expressed in any of these ways,
+**     among others:
+**
+**            date1          date2
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in
+**     cases where the loss of several decimal digits of resolution
+**     is acceptable.  The J2000 method is best matched to the way
+**     the argument is handled internally and will deliver the
+**     optimum resolution.  The MJD method and the date & time methods
+**     are both good compromises between resolution and convenience.
+**
+**  2) The CIO locator s is the difference between the right ascensions
+**     of the same point in two systems:  the two systems are the GCRS
+**     and the CIP,CIO, and the point is the ascending node of the
+**     CIP equator.  The quantity s remains below 0.1 arcsecond
+**     throughout 1900-2100.
+**
+**  3) The series used to compute s is in fact for s+XY/2, where X and Y
+**     are the x and y components of the CIP unit vector;  this series
+**     is more compact than a direct series for s would be.  This
+**     function requires X,Y to be supplied by the caller, who is
+**     responsible for providing values that are consistent with the
+**     supplied date.
+**
+**  4) The model is consistent with the "P03" precession (Capitaine et
+**     al. 2003), adopted by IAU 2006 Resolution 1, 2006, and the
+**     IAU 2000A nutation (with P03 adjustments).
+**
+**  Called:
+**     iauFal03     mean anomaly of the Moon
+**     iauFalp03    mean anomaly of the Sun
+**     iauFaf03     mean argument of the latitude of the Moon
+**     iauFad03     mean elongation of the Moon from the Sun
+**     iauFaom03    mean longitude of the Moon's ascending node
+**     iauFave03    mean longitude of Venus
+**     iauFae03     mean longitude of Earth
+**     iauFapa03    general accumulated precession in longitude
+**
+**  References:
+**
+**     Capitaine, N., Wallace, P.T. & Chapront, J., 2003, Astron.
+**     Astrophys. 432, 355
+**
+**     McCarthy, D.D., Petit, G. (eds.) 2004, IERS Conventions (2003),
+**     IERS Technical Note No. 32, BKG
+**
+**  This revision:  2009 December 17
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+/* Time since J2000.0, in Julian centuries */
+   double t;
+
+/* Miscellaneous */
+   int i, j;
+   double a, w0, w1, w2, w3, w4, w5;
+
+/* Fundamental arguments */
+   double fa[8];
+
+/* Returned value */
+   double s;
+
+/* --------------------- */
+/* The series for s+XY/2 */
+/* --------------------- */
+
+   typedef struct {
+      int nfa[8];      /* coefficients of l,l',F,D,Om,LVe,LE,pA */
+      double s, c;     /* sine and cosine coefficients */
+   } TERM;
+
+/* Polynomial coefficients */
+   static const double sp[] = {
+
+   /* 1-6 */
+          94.00e-6,
+        3808.65e-6,
+        -122.68e-6,
+      -72574.11e-6,
+          27.98e-6,
+          15.62e-6
+   };
+
+/* Terms of order t^0 */
+   static const TERM s0[] = {
+
+   /* 1-10 */
+      {{ 0,  0,  0,  0,  1,  0,  0,  0}, -2640.73e-6,   0.39e-6 },
+      {{ 0,  0,  0,  0,  2,  0,  0,  0},   -63.53e-6,   0.02e-6 },
+      {{ 0,  0,  2, -2,  3,  0,  0,  0},   -11.75e-6,  -0.01e-6 },
+      {{ 0,  0,  2, -2,  1,  0,  0,  0},   -11.21e-6,  -0.01e-6 },
+      {{ 0,  0,  2, -2,  2,  0,  0,  0},     4.57e-6,   0.00e-6 },
+      {{ 0,  0,  2,  0,  3,  0,  0,  0},    -2.02e-6,   0.00e-6 },
+      {{ 0,  0,  2,  0,  1,  0,  0,  0},    -1.98e-6,   0.00e-6 },
+      {{ 0,  0,  0,  0,  3,  0,  0,  0},     1.72e-6,   0.00e-6 },
+      {{ 0,  1,  0,  0,  1,  0,  0,  0},     1.41e-6,   0.01e-6 },
+      {{ 0,  1,  0,  0, -1,  0,  0,  0},     1.26e-6,   0.01e-6 },
+
+   /* 11-20 */
+      {{ 1,  0,  0,  0, -1,  0,  0,  0},     0.63e-6,   0.00e-6 },
+      {{ 1,  0,  0,  0,  1,  0,  0,  0},     0.63e-6,   0.00e-6 },
+      {{ 0,  1,  2, -2,  3,  0,  0,  0},    -0.46e-6,   0.00e-6 },
+      {{ 0,  1,  2, -2,  1,  0,  0,  0},    -0.45e-6,   0.00e-6 },
+      {{ 0,  0,  4, -4,  4,  0,  0,  0},    -0.36e-6,   0.00e-6 },
+      {{ 0,  0,  1, -1,  1, -8, 12,  0},     0.24e-6,   0.12e-6 },
+      {{ 0,  0,  2,  0,  0,  0,  0,  0},    -0.32e-6,   0.00e-6 },
+      {{ 0,  0,  2,  0,  2,  0,  0,  0},    -0.28e-6,   0.00e-6 },
+      {{ 1,  0,  2,  0,  3,  0,  0,  0},    -0.27e-6,   0.00e-6 },
+      {{ 1,  0,  2,  0,  1,  0,  0,  0},    -0.26e-6,   0.00e-6 },
+
+   /* 21-30 */
+      {{ 0,  0,  2, -2,  0,  0,  0,  0},     0.21e-6,   0.00e-6 },
+      {{ 0,  1, -2,  2, -3,  0,  0,  0},    -0.19e-6,   0.00e-6 },
+      {{ 0,  1, -2,  2, -1,  0,  0,  0},    -0.18e-6,   0.00e-6 },
+      {{ 0,  0,  0,  0,  0,  8,-13, -1},     0.10e-6,  -0.05e-6 },
+      {{ 0,  0,  0,  2,  0,  0,  0,  0},    -0.15e-6,   0.00e-6 },
+      {{ 2,  0, -2,  0, -1,  0,  0,  0},     0.14e-6,   0.00e-6 },
+      {{ 0,  1,  2, -2,  2,  0,  0,  0},     0.14e-6,   0.00e-6 },
+      {{ 1,  0,  0, -2,  1,  0,  0,  0},    -0.14e-6,   0.00e-6 },
+      {{ 1,  0,  0, -2, -1,  0,  0,  0},    -0.14e-6,   0.00e-6 },
+      {{ 0,  0,  4, -2,  4,  0,  0,  0},    -0.13e-6,   0.00e-6 },
+
+   /* 31-33 */
+      {{ 0,  0,  2, -2,  4,  0,  0,  0},     0.11e-6,   0.00e-6 },
+      {{ 1,  0, -2,  0, -3,  0,  0,  0},    -0.11e-6,   0.00e-6 },
+      {{ 1,  0, -2,  0, -1,  0,  0,  0},    -0.11e-6,   0.00e-6 }
+   };
+
+/* Terms of order t^1 */
+   static const TERM s1[] = {
+
+   /* 1 - 3 */
+      {{ 0,  0,  0,  0,  2,  0,  0,  0},    -0.07e-6,   3.57e-6 },
+      {{ 0,  0,  0,  0,  1,  0,  0,  0},     1.73e-6,  -0.03e-6 },
+      {{ 0,  0,  2, -2,  3,  0,  0,  0},     0.00e-6,   0.48e-6 }
+   };
+
+/* Terms of order t^2 */
+   static const TERM s2[] = {
+
+   /* 1-10 */
+      {{ 0,  0,  0,  0,  1,  0,  0,  0},   743.52e-6,  -0.17e-6 },
+      {{ 0,  0,  2, -2,  2,  0,  0,  0},    56.91e-6,   0.06e-6 },
+      {{ 0,  0,  2,  0,  2,  0,  0,  0},     9.84e-6,  -0.01e-6 },
+      {{ 0,  0,  0,  0,  2,  0,  0,  0},    -8.85e-6,   0.01e-6 },
+      {{ 0,  1,  0,  0,  0,  0,  0,  0},    -6.38e-6,  -0.05e-6 },
+      {{ 1,  0,  0,  0,  0,  0,  0,  0},    -3.07e-6,   0.00e-6 },
+      {{ 0,  1,  2, -2,  2,  0,  0,  0},     2.23e-6,   0.00e-6 },
+      {{ 0,  0,  2,  0,  1,  0,  0,  0},     1.67e-6,   0.00e-6 },
+      {{ 1,  0,  2,  0,  2,  0,  0,  0},     1.30e-6,   0.00e-6 },
+      {{ 0,  1, -2,  2, -2,  0,  0,  0},     0.93e-6,   0.00e-6 },
+
+   /* 11-20 */
+      {{ 1,  0,  0, -2,  0,  0,  0,  0},     0.68e-6,   0.00e-6 },
+      {{ 0,  0,  2, -2,  1,  0,  0,  0},    -0.55e-6,   0.00e-6 },
+      {{ 1,  0, -2,  0, -2,  0,  0,  0},     0.53e-6,   0.00e-6 },
+      {{ 0,  0,  0,  2,  0,  0,  0,  0},    -0.27e-6,   0.00e-6 },
+      {{ 1,  0,  0,  0,  1,  0,  0,  0},    -0.27e-6,   0.00e-6 },
+      {{ 1,  0, -2, -2, -2,  0,  0,  0},    -0.26e-6,   0.00e-6 },
+      {{ 1,  0,  0,  0, -1,  0,  0,  0},    -0.25e-6,   0.00e-6 },
+      {{ 1,  0,  2,  0,  1,  0,  0,  0},     0.22e-6,   0.00e-6 },
+      {{ 2,  0,  0, -2,  0,  0,  0,  0},    -0.21e-6,   0.00e-6 },
+      {{ 2,  0, -2,  0, -1,  0,  0,  0},     0.20e-6,   0.00e-6 },
+
+   /* 21-25 */
+      {{ 0,  0,  2,  2,  2,  0,  0,  0},     0.17e-6,   0.00e-6 },
+      {{ 2,  0,  2,  0,  2,  0,  0,  0},     0.13e-6,   0.00e-6 },
+      {{ 2,  0,  0,  0,  0,  0,  0,  0},    -0.13e-6,   0.00e-6 },
+      {{ 1,  0,  2, -2,  2,  0,  0,  0},    -0.12e-6,   0.00e-6 },
+      {{ 0,  0,  2,  0,  0,  0,  0,  0},    -0.11e-6,   0.00e-6 }
+   };
+
+/* Terms of order t^3 */
+   static const TERM s3[] = {
+
+   /* 1-4 */
+      {{ 0,  0,  0,  0,  1,  0,  0,  0},     0.30e-6, -23.42e-6 },
+      {{ 0,  0,  2, -2,  2,  0,  0,  0},    -0.03e-6,  -1.46e-6 },
+      {{ 0,  0,  2,  0,  2,  0,  0,  0},    -0.01e-6,  -0.25e-6 },
+      {{ 0,  0,  0,  0,  2,  0,  0,  0},     0.00e-6,   0.23e-6 }
+   };
+
+/* Terms of order t^4 */
+   static const TERM s4[] = {
+
+   /* 1-1 */
+      {{ 0,  0,  0,  0,  1,  0,  0,  0},    -0.26e-6,  -0.01e-6 }
+   };
+
+/* Number of terms in the series */
+   static const int NS0 = (int) (sizeof s0 / sizeof (TERM));
+   static const int NS1 = (int) (sizeof s1 / sizeof (TERM));
+   static const int NS2 = (int) (sizeof s2 / sizeof (TERM));
+   static const int NS3 = (int) (sizeof s3 / sizeof (TERM));
+   static const int NS4 = (int) (sizeof s4 / sizeof (TERM));
+
+/*--------------------------------------------------------------------*/
+
+/* Interval between fundamental epoch J2000.0 and current date (JC). */
+   t = ((date1 - DJ00) + date2) / DJC;
+
+/* Fundamental Arguments (from IERS Conventions 2003) */
+
+/* Mean anomaly of the Moon. */
+   fa[0] = iauFal03(t);
+
+/* Mean anomaly of the Sun. */
+   fa[1] = iauFalp03(t);
+
+/* Mean longitude of the Moon minus that of the ascending node. */
+   fa[2] = iauFaf03(t);
+
+/* Mean elongation of the Moon from the Sun. */
+   fa[3] = iauFad03(t);
+
+/* Mean longitude of the ascending node of the Moon. */
+   fa[4] = iauFaom03(t);
+
+/* Mean longitude of Venus. */
+   fa[5] = iauFave03(t);
+
+/* Mean longitude of Earth. */
+   fa[6] = iauFae03(t);
+
+/* General precession in longitude. */
+   fa[7] = iauFapa03(t);
+
+/* Evaluate s. */
+   w0 = sp[0];
+   w1 = sp[1];
+   w2 = sp[2];
+   w3 = sp[3];
+   w4 = sp[4];
+   w5 = sp[5];
+
+   for (i = NS0-1; i >= 0; i--) {
+   a = 0.0;
+   for (j = 0; j < 8; j++) {
+      a += (double)s0[i].nfa[j] * fa[j];
+   }
+   w0 += s0[i].s * sin(a) + s0[i].c * cos(a);
+   }
+
+   for (i = NS1-1; i >= 0; i--) {
+      a = 0.0;
+      for (j = 0; j < 8; j++) {
+         a += (double)s1[i].nfa[j] * fa[j];
+      }
+      w1 += s1[i].s * sin(a) + s1[i].c * cos(a);
+   }
+
+   for (i = NS2-1; i >= 0; i--) {
+      a = 0.0;
+      for (j = 0; j < 8; j++) {
+         a += (double)s2[i].nfa[j] * fa[j];
+      }
+      w2 += s2[i].s * sin(a) + s2[i].c * cos(a);
+   }
+
+   for (i = NS3-1; i >= 0; i--) {
+      a = 0.0;
+      for (j = 0; j < 8; j++) {
+         a += (double)s3[i].nfa[j] * fa[j];
+      }
+      w3 += s3[i].s * sin(a) + s3[i].c * cos(a);
+   }
+
+   for (i = NS4-1; i >= 0; i--) {
+      a = 0.0;
+      for (j = 0; j < 8; j++) {
+         a += (double)s4[i].nfa[j] * fa[j];
+      }
+      w4 += s4[i].s * sin(a) + s4[i].c * cos(a);
+   }
+
+   s = (w0 +
+       (w1 +
+       (w2 +
+       (w3 +
+       (w4 +
+        w5 * t) * t) * t) * t) * t) * DAS2R - x*y/2.0;
+
+   return s;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+double iauS06a(double date1, double date2)
+/*
+**  - - - - - - - -
+**   i a u S 0 6 a
+**  - - - - - - - -
+**
+**  The CIO locator s, positioning the Celestial Intermediate Origin on
+**  the equator of the Celestial Intermediate Pole, using the IAU 2006
+**  precession and IAU 2000A nutation models.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     date1,date2  double    TT as a 2-part Julian Date (Note 1)
+**
+**  Returned (function value):
+**                  double    the CIO locator s in radians (Note 2)
+**
+**  Notes:
+**
+**  1) The TT date date1+date2 is a Julian Date, apportioned in any
+**     convenient way between the two arguments.  For example,
+**     JD(TT)=2450123.7 could be expressed in any of these ways,
+**     among others:
+**
+**            date1          date2
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in
+**     cases where the loss of several decimal digits of resolution
+**     is acceptable.  The J2000 method is best matched to the way
+**     the argument is handled internally and will deliver the
+**     optimum resolution.  The MJD method and the date & time methods
+**     are both good compromises between resolution and convenience.
+**
+**  2) The CIO locator s is the difference between the right ascensions
+**     of the same point in two systems.  The two systems are the GCRS
+**     and the CIP,CIO, and the point is the ascending node of the
+**     CIP equator.  The CIO locator s remains a small fraction of
+**     1 arcsecond throughout 1900-2100.
+**
+**  3) The series used to compute s is in fact for s+XY/2, where X and Y
+**     are the x and y components of the CIP unit vector;  this series is
+**     more compact than a direct series for s would be.  The present
+**     function uses the full IAU 2000A nutation model when predicting
+**     the CIP position.
+**
+**  Called:
+**     iauPnm06a    classical NPB matrix, IAU 2006/2000A
+**     iauBpn2xy    extract CIP X,Y coordinates from NPB matrix
+**     iauS06       the CIO locator s, given X,Y, IAU 2006
+**
+**  References:
+**
+**     Capitaine, N., Chapront, J., Lambert, S. and Wallace, P.,
+**     "Expressions for the Celestial Intermediate Pole and Celestial
+**     Ephemeris Origin consistent with the IAU 2000A precession-
+**     nutation model", Astron.Astrophys. 400, 1145-1154 (2003)
+**
+**     n.b. The celestial ephemeris origin (CEO) was renamed "celestial
+**          intermediate origin" (CIO) by IAU 2006 Resolution 2.
+**
+**     Capitaine, N. & Wallace, P.T., 2006, Astron.Astrophys. 450, 855
+**
+**     McCarthy, D. D., Petit, G. (eds.), 2004, IERS Conventions (2003),
+**     IERS Technical Note No. 32, BKG
+**
+**     Wallace, P.T. & Capitaine, N., 2006, Astron.Astrophys. 459, 981
+**
+**  This revision:  2010 January 18
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double rnpb[3][3], x, y, s;
+
+
+/* Bias-precession-nutation-matrix, IAU 20006/2000A. */
+   iauPnm06a(date1, date2, rnpb);
+
+/* Extract the CIP coordinates. */
+   iauBpn2xy(rnpb, &x, &y);
+
+/* Compute the CIO locator s, given the CIP coordinates. */
+   s = iauS06(date1, date2, x, y);
+
+   return s;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauS2c(double theta, double phi, double c[3])
+/*
+**  - - - - - - -
+**   i a u S 2 c
+**  - - - - - - -
+**
+**  Convert spherical coordinates to Cartesian.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  vector/matrix support function.
+**
+**  Given:
+**     theta    double       longitude angle (radians)
+**     phi      double       latitude angle (radians)
+**
+**  Returned:
+**     c        double[3]    direction cosines
+**
+**  This revision:  2008 October 28
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double cp;
+
+
+   cp = cos(phi);
+   c[0] = cos(theta) * cp;
+   c[1] = sin(theta) * cp;
+   c[2] = sin(phi);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauS2p(double theta, double phi, double r, double p[3])
+/*
+**  - - - - - - -
+**   i a u S 2 p
+**  - - - - - - -
+**
+**  Convert spherical polar coordinates to p-vector.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  vector/matrix support function.
+**
+**  Given:
+**     theta   double       longitude angle (radians)
+**     phi     double       latitude angle (radians)
+**     r       double       radial distance
+**
+**  Returned:
+**     p       double[3]    Cartesian coordinates
+**
+**  Called:
+**     iauS2c       spherical coordinates to unit vector
+**     iauSxp       multiply p-vector by scalar
+**
+**  This revision:  2008 May 11
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double u[3];
+
+
+   iauS2c(theta, phi, u);
+   iauSxp(r, u, p);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauS2pv(double theta, double phi, double r,
+             double td, double pd, double rd,
+             double pv[2][3])
+/*
+**  - - - - - - - -
+**   i a u S 2 p v
+**  - - - - - - - -
+**
+**  Convert position/velocity from spherical to Cartesian coordinates.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  vector/matrix support function.
+**
+**  Given:
+**     theta    double          longitude angle (radians)
+**     phi      double          latitude angle (radians)
+**     r        double          radial distance
+**     td       double          rate of change of theta
+**     pd       double          rate of change of phi
+**     rd       double          rate of change of r
+**
+**  Returned:
+**     pv       double[2][3]    pv-vector
+**
+**  This revision:  2008 May 25
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double st, ct, sp, cp, rcp, x, y, rpd, w;
+
+
+   st = sin(theta);
+   ct = cos(theta);
+   sp = sin(phi);
+   cp = cos(phi);
+   rcp = r * cp;
+   x = rcp * ct;
+   y = rcp * st;
+   rpd = r * pd;
+   w = rpd*sp - cp*rd;
+
+   pv[0][0] = x;
+   pv[0][1] = y;
+   pv[0][2] = r * sp;
+   pv[1][0] = -y*td - w*ct;
+   pv[1][1] =  x*td - w*st;
+   pv[1][2] = rpd*cp + sp*rd;
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauS2xpv(double s1, double s2, double pv[2][3], double spv[2][3])
+/*
+**  - - - - - - - - -
+**   i a u S 2 x p v
+**  - - - - - - - - -
+**
+**  Multiply a pv-vector by two scalars.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  vector/matrix support function.
+**
+**  Given:
+**     s1     double         scalar to multiply position component by
+**     s2     double         scalar to multiply velocity component by
+**     pv     double[2][3]   pv-vector
+**
+**  Returned:
+**     spv    double[2][3]   pv-vector: p scaled by s1, v scaled by s2
+**
+**  Note:
+**     It is permissible for pv and spv to be the same array.
+**
+**  Called:
+**     iauSxp       multiply p-vector by scalar
+**
+**  This revision:  2008 October 28
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   iauSxp(s1, pv[0], spv[0]);
+   iauSxp(s2, pv[1], spv[1]);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+double iauSepp(double a[3], double b[3])
+/*
+**  - - - - - - - -
+**   i a u S e p p
+**  - - - - - - - -
+**
+**  Angular separation between two p-vectors.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  vector/matrix support function.
+**
+**  Given:
+**     a      double[3]    first p-vector (not necessarily unit length)
+**     b      double[3]    second p-vector (not necessarily unit length)
+**
+**  Returned (function value):
+**            double       angular separation (radians, always positive)
+**
+**  Notes:
+**
+**  1) If either vector is null, a zero result is returned.
+**
+**  2) The angular separation is most simply formulated in terms of
+**     scalar product.  However, this gives poor accuracy for angles
+**     near zero and pi.  The present algorithm uses both cross product
+**     and dot product, to deliver full accuracy whatever the size of
+**     the angle.
+**
+**  Called:
+**     iauPxp       vector product of two p-vectors
+**     iauPm        modulus of p-vector
+**     iauPdp       scalar product of two p-vectors
+**
+**  This revision:  2008 May 22
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double axb[3], ss, cs, s;
+
+
+/* Sine of angle between the vectors, multiplied by the two moduli. */
+   iauPxp(a, b, axb);
+   ss = iauPm(axb);
+
+/* Cosine of the angle, multiplied by the two moduli. */
+   cs = iauPdp(a, b);
+
+/* The angle. */
+   s = ((ss != 0.0) || (cs != 0.0)) ? atan2(ss, cs) : 0.0;
+
+   return s;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+double iauSeps(double al, double ap, double bl, double bp)
+/*
+**  - - - - - - - -
+**   i a u S e p s
+**  - - - - - - - -
+**
+**  Angular separation between two sets of spherical coordinates.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  vector/matrix support function.
+**
+**  Given:
+**     al     double       first longitude (radians)
+**     ap     double       first latitude (radians)
+**     bl     double       second longitude (radians)
+**     bp     double       second latitude (radians)
+**
+**  Returned (function value):
+**            double       angular separation (radians)
+**
+**  Called:
+**     iauS2c       spherical coordinates to unit vector
+**     iauSepp      angular separation between two p-vectors
+**
+**  This revision:  2008 May 16
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double ac[3], bc[3], s;
+
+
+/* Spherical to Cartesian. */
+   iauS2c(al, ap, ac);
+   iauS2c(bl, bp, bc);
+
+/* Angle between the vectors. */
+   s = iauSepp(ac, bc);
+
+   return s;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+double iauSp00(double date1, double date2)
+/*
+**  - - - - - - - -
+**   i a u S p 0 0
+**  - - - - - - - -
+**
+**  The TIO locator s', positioning the Terrestrial Intermediate Origin
+**  on the equator of the Celestial Intermediate Pole.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  canonical model.
+**
+**  Given:
+**     date1,date2  double    TT as a 2-part Julian Date (Note 1)
+**
+**  Returned (function value):
+**                  double    the TIO locator s' in radians (Note 2)
+**
+**  Notes:
+**
+**  1) The TT date date1+date2 is a Julian Date, apportioned in any
+**     convenient way between the two arguments.  For example,
+**     JD(TT)=2450123.7 could be expressed in any of these ways,
+**     among others:
+**
+**            date1          date2
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in
+**     cases where the loss of several decimal digits of resolution
+**     is acceptable.  The J2000 method is best matched to the way
+**     the argument is handled internally and will deliver the
+**     optimum resolution.  The MJD method and the date & time methods
+**     are both good compromises between resolution and convenience.
+**
+**  2) The TIO locator s' is obtained from polar motion observations by
+**     numerical integration, and so is in essence unpredictable.
+**     However, it is dominated by a secular drift of about
+**     47 microarcseconds per century, which is the approximation
+**     evaluated by the present function.
+**
+**  Reference:
+**
+**     McCarthy, D. D., Petit, G. (eds.), IERS Conventions (2003),
+**     IERS Technical Note No. 32, BKG (2004)
+**
+**  This revision:  2008 May 24
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double t, sp;
+
+
+/* Interval between fundamental epoch J2000.0 and current date (JC). */
+   t = ((date1 - DJ00) + date2) / DJC;
+
+/* Approximate s'. */
+   sp = -47e-6 * t * DAS2R;
+
+   return sp;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+int iauStarpm(double ra1, double dec1,
+              double pmr1, double pmd1, double px1, double rv1,
+              double ep1a, double ep1b, double ep2a, double ep2b,
+              double *ra2, double *dec2,
+              double *pmr2, double *pmd2, double *px2, double *rv2)
+/*
+**  - - - - - - - - - -
+**   i a u S t a r p m
+**  - - - - - - - - - -
+**
+**  Star proper motion:  update star catalog data for space motion.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     ra1    double     right ascension (radians), before
+**     dec1   double     declination (radians), before
+**     pmr1   double     RA proper motion (radians/year), before
+**     pmd1   double     Dec proper motion (radians/year), before
+**     px1    double     parallax (arcseconds), before
+**     rv1    double     radial velocity (km/s, +ve = receding), before
+**     ep1a   double     "before" epoch, part A (Note 1)
+**     ep1b   double     "before" epoch, part B (Note 1)
+**     ep2a   double     "after" epoch, part A (Note 1)
+**     ep2b   double     "after" epoch, part B (Note 1)
+**
+**  Returned:
+**     ra2    double     right ascension (radians), after
+**     dec2   double     declination (radians), after
+**     pmr2   double     RA proper motion (radians/year), after
+**     pmd2   double     Dec proper motion (radians/year), after
+**     px2    double     parallax (arcseconds), after
+**     rv2    double     radial velocity (km/s, +ve = receding), after
+**
+**  Returned (function value):
+**            int        status:
+**                          -1 = system error (should not occur)
+**                           0 = no warnings or errors
+**                           1 = distance overridden (Note 6)
+**                           2 = excessive velocity (Note 7)
+**                           4 = solution didn't converge (Note 8)
+**                        else = binary logical OR of the above warnings
+**
+**  Notes:
+**
+**  1) The starting and ending TDB dates ep1a+ep1b and ep2a+ep2b are
+**     Julian Dates, apportioned in any convenient way between the two
+**     parts (A and B).  For example, JD(TDB)=2450123.7 could be
+**     expressed in any of these ways, among others:
+**
+**             epna          epnb
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in
+**     cases where the loss of several decimal digits of resolution
+**     is acceptable.  The J2000 method is best matched to the way
+**     the argument is handled internally and will deliver the
+**     optimum resolution.  The MJD method and the date & time methods
+**     are both good compromises between resolution and convenience.
+**
+**  2) In accordance with normal star-catalog conventions, the object's
+**     right ascension and declination are freed from the effects of
+**     secular aberration.  The frame, which is aligned to the catalog
+**     equator and equinox, is Lorentzian and centered on the SSB.
+**
+**     The proper motions are the rate of change of the right ascension
+**     and declination at the catalog epoch and are in radians per TDB
+**     Julian year.
+**
+**     The parallax and radial velocity are in the same frame.
+**
+**  3) Care is needed with units.  The star coordinates are in radians
+**     and the proper motions in radians per Julian year, but the
+**     parallax is in arcseconds.
+**
+**  4) The RA proper motion is in terms of coordinate angle, not true
+**     angle.  If the catalog uses arcseconds for both RA and Dec proper
+**     motions, the RA proper motion will need to be divided by cos(Dec)
+**     before use.
+**
+**  5) Straight-line motion at constant speed, in the inertial frame,
+**     is assumed.
+**
+**  6) An extremely small (or zero or negative) parallax is interpreted
+**     to mean that the object is on the "celestial sphere", the radius
+**     of which is an arbitrary (large) value (see the iauStarpv
+**     function for the value used).  When the distance is overridden in
+**     this way, the status, initially zero, has 1 added to it.
+**
+**  7) If the space velocity is a significant fraction of c (see the
+**     constant VMAX in the function iauStarpv),  it is arbitrarily set
+**     to zero.  When this action occurs, 2 is added to the status.
+**
+**  8) The relativistic adjustment carried out in the iauStarpv function
+**     involves an iterative calculation.  If the process fails to
+**     converge within a set number of iterations, 4 is added to the
+**     status.
+**
+**  Called:
+**     iauStarpv    star catalog data to space motion pv-vector
+**     iauPvu       update a pv-vector
+**     iauPdp       scalar product of two p-vectors
+**     iauPvstar    space motion pv-vector to star catalog data
+**
+**  This revision:  2008 May 16
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double pv1[2][3], tl1, dt, pv[2][3], r2, rdv, v2, c2mv2, tl2,
+          pv2[2][3];
+   int j1, j2, j;
+
+
+/* RA,Dec etc. at the "before" epoch to space motion pv-vector. */
+   j1 = iauStarpv(ra1, dec1, pmr1, pmd1, px1, rv1, pv1);
+
+/* Light time when observed (days). */
+   tl1 = iauPm(pv1[0]) / DC;
+
+/* Time interval, "before" to "after" (days). */
+   dt = (ep2a - ep1a) + (ep2b - ep1b);
+
+/* Move star along track from the "before" observed position to the */
+/* "after" geometric position. */
+   iauPvu(dt + tl1, pv1, pv);
+
+/* From this geometric position, deduce the observed light time (days) */
+/* at the "after" epoch (with theoretically unneccessary error check). */
+   r2 = iauPdp(pv[0], pv[0]);
+   rdv = iauPdp(pv[0], pv[1]);
+   v2 = iauPdp(pv[1], pv[1]);
+   c2mv2 = DC*DC - v2;
+   if (c2mv2 <=  0) return -1;
+   tl2 = (-rdv + sqrt(rdv*rdv + c2mv2*r2)) / c2mv2;
+
+/* Move the position along track from the observed place at the */
+/* "before" epoch to the observed place at the "after" epoch. */
+   iauPvu(dt + (tl1 - tl2), pv1, pv2);
+
+/* Space motion pv-vector to RA,Dec etc. at the "after" epoch. */
+   j2 = iauPvstar(pv2, ra2, dec2, pmr2, pmd2, px2, rv2);
+
+/* Final status. */
+   j = (j2 == 0) ? j1 : -1;
+
+   return j;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+int iauStarpv(double ra, double dec,
+              double pmr, double pmd, double px, double rv,
+              double pv[2][3])
+/*
+**  - - - - - - - - - -
+**   i a u S t a r p v
+**  - - - - - - - - - -
+**
+**  Convert star catalog coordinates to position+velocity vector.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given (Note 1):
+**     ra     double        right ascension (radians)
+**     dec    double        declination (radians)
+**     pmr    double        RA proper motion (radians/year)
+**     pmd    double        Dec proper motion (radians/year)
+**     px     double        parallax (arcseconds)
+**     rv     double        radial velocity (km/s, positive = receding)
+**
+**  Returned (Note 2):
+**     pv     double[2][3]  pv-vector (AU, AU/day)
+**
+**  Returned (function value):
+**            int           status:
+**                              0 = no warnings
+**                              1 = distance overridden (Note 6)
+**                              2 = excessive speed (Note 7)
+**                              4 = solution didn't converge (Note 8)
+**                           else = binary logical OR of the above
+**
+**  Notes:
+**
+**  1) The star data accepted by this function are "observables" for an
+**     imaginary observer at the solar-system barycenter.  Proper motion
+**     and radial velocity are, strictly, in terms of barycentric
+**     coordinate time, TCB.  For most practical applications, it is
+**     permissible to neglect the distinction between TCB and ordinary
+**     "proper" time on Earth (TT/TAI).  The result will, as a rule, be
+**     limited by the intrinsic accuracy of the proper-motion and
+**     radial-velocity data;  moreover, the pv-vector is likely to be
+**     merely an intermediate result, so that a change of time unit
+**     would cancel out overall.
+**
+**     In accordance with normal star-catalog conventions, the object's
+**     right ascension and declination are freed from the effects of
+**     secular aberration.  The frame, which is aligned to the catalog
+**     equator and equinox, is Lorentzian and centered on the SSB.
+**
+**  2) The resulting position and velocity pv-vector is with respect to
+**     the same frame and, like the catalog coordinates, is freed from
+**     the effects of secular aberration.  Should the "coordinate
+**     direction", where the object was located at the catalog epoch, be
+**     required, it may be obtained by calculating the magnitude of the
+**     position vector pv[0][0-2] dividing by the speed of light in
+**     AU/day to give the light-time, and then multiplying the space
+**     velocity pv[1][0-2] by this light-time and adding the result to
+**     pv[0][0-2].
+**
+**     Summarizing, the pv-vector returned is for most stars almost
+**     identical to the result of applying the standard geometrical
+**     "space motion" transformation.  The differences, which are the
+**     subject of the Stumpff paper referenced below, are:
+**
+**     (i) In stars with significant radial velocity and proper motion,
+**     the constantly changing light-time distorts the apparent proper
+**     motion.  Note that this is a classical, not a relativistic,
+**     effect.
+**
+**     (ii) The transformation complies with special relativity.
+**
+**  3) Care is needed with units.  The star coordinates are in radians
+**     and the proper motions in radians per Julian year, but the
+**     parallax is in arcseconds; the radial velocity is in km/s, but
+**     the pv-vector result is in AU and AU/day.
+**
+**  4) The RA proper motion is in terms of coordinate angle, not true
+**     angle.  If the catalog uses arcseconds for both RA and Dec proper
+**     motions, the RA proper motion will need to be divided by cos(Dec)
+**     before use.
+**
+**  5) Straight-line motion at constant speed, in the inertial frame,
+**     is assumed.
+**
+**  6) An extremely small (or zero or negative) parallax is interpreted
+**     to mean that the object is on the "celestial sphere", the radius
+**     of which is an arbitrary (large) value (see the constant PXMIN).
+**     When the distance is overridden in this way, the status,
+**     initially zero, has 1 added to it.
+**
+**  7) If the space velocity is a significant fraction of c (see the
+**     constant VMAX), it is arbitrarily set to zero.  When this action
+**     occurs, 2 is added to the status.
+**
+**  8) The relativistic adjustment involves an iterative calculation.
+**     If the process fails to converge within a set number (IMAX) of
+**     iterations, 4 is added to the status.
+**
+**  9) The inverse transformation is performed by the function
+**     iauPvstar.
+**
+**  Called:
+**     iauS2pv      spherical coordinates to pv-vector
+**     iauPm        modulus of p-vector
+**     iauZp        zero p-vector
+**     iauPn        decompose p-vector into modulus and direction
+**     iauPdp       scalar product of two p-vectors
+**     iauSxp       multiply p-vector by scalar
+**     iauPmp       p-vector minus p-vector
+**     iauPpp       p-vector plus p-vector
+**
+**  Reference:
+**
+**     Stumpff, P., 1985, Astron.Astrophys. 144, 232-240.
+**
+**  This revision:  2009 July 6
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+/* Smallest allowed parallax */
+   static const double PXMIN = 1e-7;
+
+/* Largest allowed speed (fraction of c) */
+   static const double VMAX = 0.5;
+
+/* Maximum number of iterations for relativistic solution */
+   static const int IMAX = 100;
+
+   int i, iwarn;
+   double w, r, rd, rad, decd, v, x[3], usr[3], ust[3],
+          vsr, vst, betst, betsr, bett, betr,
+          dd, ddel, ur[3], ut[3],
+          d = 0.0, del = 0.0,       /* to prevent */
+          odd = 0.0, oddel = 0.0,   /* compiler   */
+          od = 0.0, odel = 0.0;     /* warnings   */
+
+
+/* Distance (AU). */
+   if (px >= PXMIN) {
+      w = px;
+      iwarn = 0;
+   } else {
+      w = PXMIN;
+      iwarn = 1;
+   }
+   r = DR2AS / w;
+
+/* Radial velocity (AU/day). */
+   rd = DAYSEC * rv * 1e3 / DAU;
+
+/* Proper motion (radian/day). */
+   rad = pmr / DJY;
+   decd = pmd / DJY;
+
+/* To pv-vector (AU,AU/day). */
+   iauS2pv(ra, dec, r, rad, decd, rd, pv);
+
+/* If excessive velocity, arbitrarily set it to zero. */
+   v = iauPm(pv[1]);
+   if (v / DC > VMAX) {
+      iauZp(pv[1]);
+      iwarn += 2;
+   }
+
+/* Isolate the radial component of the velocity (AU/day). */
+   iauPn(pv[0], &w, x);
+   vsr = iauPdp(x, pv[1]);
+   iauSxp(vsr, x, usr);
+
+/* Isolate the transverse component of the velocity (AU/day). */
+   iauPmp(pv[1], usr, ust);
+   vst = iauPm(ust);
+
+/* Special-relativity dimensionless parameters. */
+   betsr = vsr / DC;
+   betst = vst / DC;
+
+/* Determine the inertial-to-observed relativistic correction terms. */
+   bett = betst;
+   betr = betsr;
+   for (i = 0; i < IMAX; i++) {
+      d = 1.0 + betr;
+      del = sqrt(1.0 - betr*betr - bett*bett) - 1.0;
+      betr = d * betsr + del;
+      bett = d * betst;
+      if (i > 0) {
+         dd = fabs(d - od);
+         ddel = fabs(del - odel);
+         if ((i > 1) && (dd >= odd) && (ddel >= oddel)) break;
+         odd = dd;
+         oddel = ddel;
+      }
+      od = d;
+      odel = del;
+   }
+   if (i >= IMAX) iwarn += 4;
+
+/* Replace observed radial velocity with inertial value. */
+   w = (betsr != 0.0) ? d + del / betsr : 1.0;
+   iauSxp(w, usr, ur);
+
+/* Replace observed tangential velocity with inertial value. */
+   iauSxp(d, ust, ut);
+
+/* Combine the two to obtain the inertial space velocity. */
+   iauPpp(ur, ut, pv[1]);
+
+/* Return the status. */
+   return iwarn;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauSxp(double s, double p[3], double sp[3])
+/*
+**  - - - - - - -
+**   i a u S x p
+**  - - - - - - -
+**
+**  Multiply a p-vector by a scalar.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  vector/matrix support function.
+**
+**  Given:
+**     s      double        scalar
+**     p      double[3]     p-vector
+**
+**  Returned:
+**     sp     double[3]     s * p
+**
+**  Note:
+**     It is permissible for p and sp to be the same array.
+**
+**  This revision:  2008 October 28
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   sp[0] = s * p[0];
+   sp[1] = s * p[1];
+   sp[2] = s * p[2];
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauSxpv(double s, double pv[2][3], double spv[2][3])
+/*
+**  - - - - - - - -
+**   i a u S x p v
+**  - - - - - - - -
+**
+**  Multiply a pv-vector by a scalar.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  vector/matrix support function.
+**
+**  Given:
+**     s       double          scalar
+**     pv      double[2][3]    pv-vector
+**
+**  Returned:
+**     spv     double[2][3]    s * pv
+**
+**  Note:
+**     It is permissible for pv and psv to be the same array
+**
+**  Called:
+**     iauS2xpv     multiply pv-vector by two scalars
+**
+**  This revision:  2008 October 28
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   iauS2xpv(s, s, pv, spv);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include <stdio.h>
+#include "sofa.h"
+#include "sofam.h"
+
+static int verbose = 0;
+
+/*
+**  - - - - - - - - -
+**   t _ s o f a _ c
+**  - - - - - - - - -
+**
+**  Validate the SOFA C functions.
+**
+**  Each SOFA function is at least called and a usually quite basic test
+**  is performed.  Successful completion is signalled by a confirming
+**  message.  Failure of a given function or group of functions results
+**  in error messages.
+**
+**  All messages go to stdout.
+**
+**  This revision:  2012 February 23
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+
+static void viv(int ival, int ivalok,
+                const char *func, const char *test, int *status)
+/*
+**  - - - -
+**   v i v
+**  - - - -
+**
+**  Validate an integer result.
+**
+**  Internal function used by t_sofa_c program.
+**
+**  Given:
+**     ival     int          value computed by function under test
+**     ivalok   int          correct value
+**     func     char[]       name of function under test
+**     test     char[]       name of individual test
+**
+**  Given and returned:
+**     status   int          set to FALSE if test fails
+**
+**  This revision:  2012 February 12
+*/
+{
+   if (ival != ivalok) {
+      *status = 1;
+      printf("%s failed: %s want %d got %d\n",
+             func, test, ivalok, ival);
+   } else if (verbose) {
+      printf("%s passed: %s want %d got %d\n",
+                    func, test, ivalok, ival);
+   }
+   return;
+}
+
+static void vvd(double val, double valok, double dval,
+                const char *func, const char *test, int *status)
+/*
+**  - - - -
+**   v v d
+**  - - - -
+**
+**  Validate a double result.
+**
+**  Internal function used by t_sofa_c program.
+**
+**  Given:
+**     val      double       value computed by function under test
+**     valok    double       expected value
+**     dval     double       maximum allowable error
+**     func     char[]       name of function under test
+**     test     char[]       name of individual test
+**
+**  Given and returned:
+**     status   int          set to FALSE if test fails
+**
+**  This revision:  2012 February 12
+*/
+{
+   double a, f;   /* absolute and fractional error */
+
+
+   a = val - valok;
+   if (fabs(a) > dval) {
+      f = fabs(valok / a);
+      *status = 1;
+      printf("%s failed: %s want %.20g got %.20g (1/%.3g)\n",
+             func, test, valok, val, f);
+   } else if (verbose) {
+      printf("%s passed: %s want %.20g got %.20g\n",
+             func, test, valok, val);
+   }
+   return;
+}
+
+static void t_a2af(int *status)
+/*
+**  - - - - - - -
+**   t _ a 2 a f
+**  - - - - - - -
+**
+**  Test iauA2af function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauA2af, viv
+**
+**  This revision:  2008 November 30
+*/
+{
+   int idmsf[4];
+   char s;
+
+
+   iauA2af(4, 2.345, &s, idmsf);
+
+   viv(s, '+', "iauA2af", "s", status);
+
+   viv(idmsf[0],  134, "iauA2af", "0", status);
+   viv(idmsf[1],   21, "iauA2af", "1", status);
+   viv(idmsf[2],   30, "iauA2af", "2", status);
+   viv(idmsf[3], 9706, "iauA2af", "3", status);
+
+}
+
+static void t_a2tf(int *status)
+/*
+**  - - - - - - -
+**   t _ a 2 t f
+**  - - - - - - -
+**
+**  Test iauA2tf function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauA2tf, viv
+**
+**  This revision:  2008 November 30
+*/
+{
+   int ihmsf[4];
+   char s;
+
+
+   iauA2tf(4, -3.01234, &s, ihmsf);
+
+   viv((int)s, '-', "iauA2tf", "s", status);
+
+   viv(ihmsf[0],   11, "iauA2tf", "0", status);
+   viv(ihmsf[1],   30, "iauA2tf", "1", status);
+   viv(ihmsf[2],   22, "iauA2tf", "2", status);
+   viv(ihmsf[3], 6484, "iauA2tf", "3", status);
+
+}
+
+static void t_af2a(int *status)
+/*
+**  - - - - - - -
+**   t _ a f 2 a
+**  - - - - - - -
+**
+**  Test iauAf2a function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauAf2a, viv
+**
+**  This revision:  2010 September 6
+*/
+{
+   double a;
+   int j;
+
+
+   j = iauAf2a('-', 45, 13, 27.2, &a);
+
+   vvd(a, -0.7893115794313644842, 1e-12, "iauAf2a", "a", status);
+   viv(j, 0, "iauAf2a", "j", status);
+
+}
+
+static void t_anp(int *status)
+/*
+**  - - - - - -
+**   t _ a n p
+**  - - - - - -
+**
+**  Test iauAnp function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauAnp, vvd
+**
+**  This revision:  2008 November 30
+*/
+{
+   vvd(iauAnp(-0.1), 6.183185307179586477, 1e-12, "iauAnp", "", status);
+}
+
+static void t_anpm(int *status)
+/*
+**  - - - - - - -
+**   t _ a n p m
+**  - - - - - - -
+**
+**  Test iauAnpm function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauAnpm, vvd
+**
+**  This revision:  2008 November 30
+*/
+{
+   vvd(iauAnpm(-4.0), 2.283185307179586477, 1e-12, "iauAnpm", "", status);
+}
+
+static void t_bi00(int *status)
+/*
+**  - - - - - - -
+**   t _ b i 0 0
+**  - - - - - - -
+**
+**  Test iauBi00 function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauBi00, vvd
+**
+**  This revision:  2009 November 4
+*/
+{
+   double dpsibi, depsbi, dra;
+
+   iauBi00(&dpsibi, &depsbi, &dra);
+
+   vvd(dpsibi, -0.2025309152835086613e-6, 1e-12,
+      "iauBi00", "dpsibi", status);
+   vvd(depsbi, -0.3306041454222147847e-7, 1e-12,
+      "iauBi00", "depsbi", status);
+   vvd(dra, -0.7078279744199225506e-7, 1e-12,
+      "iauBi00", "dra", status);
+}
+
+static void t_bp00(int *status)
+/*
+**  - - - - - - -
+**   t _ b p 0 0
+**  - - - - - - -
+**
+**  Test iauBp00 function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauBp00, vvd
+**
+**  This revision:  2008 November 28
+*/
+{
+   double rb[3][3], rp[3][3], rbp[3][3];
+
+
+   iauBp00(2400000.5, 50123.9999, rb, rp, rbp);
+
+   vvd(rb[0][0], 0.9999999999999942498, 1e-12,
+       "iauBp00", "rb11", status);
+   vvd(rb[0][1], -0.7078279744199196626e-7, 1e-16,
+       "iauBp00", "rb12", status);
+   vvd(rb[0][2], 0.8056217146976134152e-7, 1e-16,
+       "iauBp00", "rb13", status);
+   vvd(rb[1][0], 0.7078279477857337206e-7, 1e-16,
+       "iauBp00", "rb21", status);
+   vvd(rb[1][1], 0.9999999999999969484, 1e-12,
+       "iauBp00", "rb22", status);
+   vvd(rb[1][2], 0.3306041454222136517e-7, 1e-16,
+       "iauBp00", "rb23", status);
+   vvd(rb[2][0], -0.8056217380986972157e-7, 1e-16,
+       "iauBp00", "rb31", status);
+   vvd(rb[2][1], -0.3306040883980552500e-7, 1e-16,
+       "iauBp00", "rb32", status);
+   vvd(rb[2][2], 0.9999999999999962084, 1e-12,
+       "iauBp00", "rb33", status);
+
+   vvd(rp[0][0], 0.9999995504864048241, 1e-12,
+       "iauBp00", "rp11", status);
+   vvd(rp[0][1], 0.8696113836207084411e-3, 1e-14,
+       "iauBp00", "rp12", status);
+   vvd(rp[0][2], 0.3778928813389333402e-3, 1e-14,
+       "iauBp00", "rp13", status);
+   vvd(rp[1][0], -0.8696113818227265968e-3, 1e-14,
+       "iauBp00", "rp21", status);
+   vvd(rp[1][1], 0.9999996218879365258, 1e-12,
+       "iauBp00", "rp22", status);
+   vvd(rp[1][2], -0.1690679263009242066e-6, 1e-14,
+       "iauBp00", "rp23", status);
+   vvd(rp[2][0], -0.3778928854764695214e-3, 1e-14,
+       "iauBp00", "rp31", status);
+   vvd(rp[2][1], -0.1595521004195286491e-6, 1e-14,
+       "iauBp00", "rp32", status);
+   vvd(rp[2][2], 0.9999999285984682756, 1e-12,
+       "iauBp00", "rp33", status);
+
+   vvd(rbp[0][0], 0.9999995505175087260, 1e-12,
+       "iauBp00", "rbp11", status);
+   vvd(rbp[0][1], 0.8695405883617884705e-3, 1e-14,
+       "iauBp00", "rbp12", status);
+   vvd(rbp[0][2], 0.3779734722239007105e-3, 1e-14,
+       "iauBp00", "rbp13", status);
+   vvd(rbp[1][0], -0.8695405990410863719e-3, 1e-14,
+       "iauBp00", "rbp21", status);
+   vvd(rbp[1][1], 0.9999996219494925900, 1e-12,
+       "iauBp00", "rbp22", status);
+   vvd(rbp[1][2], -0.1360775820404982209e-6, 1e-14,
+       "iauBp00", "rbp23", status);
+   vvd(rbp[2][0], -0.3779734476558184991e-3, 1e-14,
+       "iauBp00", "rbp31", status);
+   vvd(rbp[2][1], -0.1925857585832024058e-6, 1e-14,
+       "iauBp00", "rbp32", status);
+   vvd(rbp[2][2], 0.9999999285680153377, 1e-12,
+       "iauBp00", "rbp33", status);
+}
+
+static void t_bp06(int *status)
+/*
+**  - - - - - - -
+**   t _ b p 0 6
+**  - - - - - - -
+**
+**  Test iauBp06 function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauBp06, vvd
+**
+**  This revision:  2008 November 28
+*/
+{
+   double rb[3][3], rp[3][3], rbp[3][3];
+
+
+   iauBp06(2400000.5, 50123.9999, rb, rp, rbp);
+
+   vvd(rb[0][0], 0.9999999999999942497, 1e-12,
+       "iauBp06", "rb11", status);
+   vvd(rb[0][1], -0.7078368960971557145e-7, 1e-14,
+       "iauBp06", "rb12", status);
+   vvd(rb[0][2], 0.8056213977613185606e-7, 1e-14,
+       "iauBp06", "rb13", status);
+   vvd(rb[1][0], 0.7078368694637674333e-7, 1e-14,
+       "iauBp06", "rb21", status);
+   vvd(rb[1][1], 0.9999999999999969484, 1e-12,
+       "iauBp06", "rb22", status);
+   vvd(rb[1][2], 0.3305943742989134124e-7, 1e-14,
+       "iauBp06", "rb23", status);
+   vvd(rb[2][0], -0.8056214211620056792e-7, 1e-14,
+       "iauBp06", "rb31", status);
+   vvd(rb[2][1], -0.3305943172740586950e-7, 1e-14,
+       "iauBp06", "rb32", status);
+   vvd(rb[2][2], 0.9999999999999962084, 1e-12,
+       "iauBp06", "rb33", status);
+
+   vvd(rp[0][0], 0.9999995504864960278, 1e-12,
+       "iauBp06", "rp11", status);
+   vvd(rp[0][1], 0.8696112578855404832e-3, 1e-14,
+       "iauBp06", "rp12", status);
+   vvd(rp[0][2], 0.3778929293341390127e-3, 1e-14,
+       "iauBp06", "rp13", status);
+   vvd(rp[1][0], -0.8696112560510186244e-3, 1e-14,
+       "iauBp06", "rp21", status);
+   vvd(rp[1][1], 0.9999996218880458820, 1e-12,
+       "iauBp06", "rp22", status);
+   vvd(rp[1][2], -0.1691646168941896285e-6, 1e-14,
+       "iauBp06", "rp23", status);
+   vvd(rp[2][0], -0.3778929335557603418e-3, 1e-14,
+       "iauBp06", "rp31", status);
+   vvd(rp[2][1], -0.1594554040786495076e-6, 1e-14,
+       "iauBp06", "rp32", status);
+   vvd(rp[2][2], 0.9999999285984501222, 1e-12,
+       "iauBp06", "rp33", status);
+
+   vvd(rbp[0][0], 0.9999995505176007047, 1e-12,
+       "iauBp06", "rbp11", status);
+   vvd(rbp[0][1], 0.8695404617348208406e-3, 1e-14,
+       "iauBp06", "rbp12", status);
+   vvd(rbp[0][2], 0.3779735201865589104e-3, 1e-14,
+       "iauBp06", "rbp13", status);
+   vvd(rbp[1][0], -0.8695404723772031414e-3, 1e-14,
+       "iauBp06", "rbp21", status);
+   vvd(rbp[1][1], 0.9999996219496027161, 1e-12,
+       "iauBp06", "rbp22", status);
+   vvd(rbp[1][2], -0.1361752497080270143e-6, 1e-14,
+       "iauBp06", "rbp23", status);
+   vvd(rbp[2][0], -0.3779734957034089490e-3, 1e-14,
+       "iauBp06", "rbp31", status);
+   vvd(rbp[2][1], -0.1924880847894457113e-6, 1e-14,
+       "iauBp06", "rbp32", status);
+   vvd(rbp[2][2], 0.9999999285679971958, 1e-12,
+       "iauBp06", "rbp33", status);
+}
+
+static void t_bpn2xy(int *status)
+/*
+**  - - - - - - - - -
+**   t _ b p n 2 x y
+**  - - - - - - - - -
+**
+**  Test iauBpn2xy function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauBpn2xy, vvd
+**
+**  This revision:  2008 May 26
+*/
+{
+   double rbpn[3][3], x, y;
+
+
+   rbpn[0][0] =  9.999962358680738e-1;
+   rbpn[0][1] = -2.516417057665452e-3;
+   rbpn[0][2] = -1.093569785342370e-3;
+
+   rbpn[1][0] =  2.516462370370876e-3;
+   rbpn[1][1] =  9.999968329010883e-1;
+   rbpn[1][2] =  4.006159587358310e-5;
+
+   rbpn[2][0] =  1.093465510215479e-3;
+   rbpn[2][1] = -4.281337229063151e-5;
+   rbpn[2][2] =  9.999994012499173e-1;
+
+   iauBpn2xy(rbpn, &x, &y);
+
+   vvd(x,  1.093465510215479e-3, 1e-12, "iauBpn2xy", "x", status);
+   vvd(y, -4.281337229063151e-5, 1e-12, "iauBpn2xy", "y", status);
+
+}
+
+static void t_c2i00a(int *status)
+/*
+**  - - - - - - - - -
+**   t _ c 2 i 0 0 a
+**  - - - - - - - - -
+**
+**  Test iauC2i00a function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauC2i00a, vvd
+**
+**  This revision:  2008 November 28
+*/
+{
+   double rc2i[3][3];
+
+
+   iauC2i00a(2400000.5, 53736.0, rc2i);
+
+   vvd(rc2i[0][0], 0.9999998323037165557, 1e-12,
+       "iauC2i00a", "11", status);
+   vvd(rc2i[0][1], 0.5581526348992140183e-9, 1e-12,
+       "iauC2i00a", "12", status);
+   vvd(rc2i[0][2], -0.5791308477073443415e-3, 1e-12,
+       "iauC2i00a", "13", status);
+
+   vvd(rc2i[1][0], -0.2384266227870752452e-7, 1e-12,
+       "iauC2i00a", "21", status);
+   vvd(rc2i[1][1], 0.9999999991917405258, 1e-12,
+       "iauC2i00a", "22", status);
+   vvd(rc2i[1][2], -0.4020594955028209745e-4, 1e-12,
+       "iauC2i00a", "23", status);
+
+   vvd(rc2i[2][0], 0.5791308472168152904e-3, 1e-12,
+       "iauC2i00a", "31", status);
+   vvd(rc2i[2][1], 0.4020595661591500259e-4, 1e-12,
+       "iauC2i00a", "32", status);
+   vvd(rc2i[2][2], 0.9999998314954572304, 1e-12,
+       "iauC2i00a", "33", status);
+
+}
+
+static void t_c2i00b(int *status)
+/*
+**  - - - - - - - - -
+**   t _ c 2 i 0 0 b
+**  - - - - - - - - -
+**
+**  Test iauC2i00b function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauC2i00b, vvd
+**
+**  This revision:  2008 November 28
+*/
+{
+   double rc2i[3][3];
+
+
+   iauC2i00b(2400000.5, 53736.0, rc2i);
+
+   vvd(rc2i[0][0], 0.9999998323040954356, 1e-12,
+       "iauC2i00b", "11", status);
+   vvd(rc2i[0][1], 0.5581526349131823372e-9, 1e-12,
+       "iauC2i00b", "12", status);
+   vvd(rc2i[0][2], -0.5791301934855394005e-3, 1e-12,
+       "iauC2i00b", "13", status);
+
+   vvd(rc2i[1][0], -0.2384239285499175543e-7, 1e-12,
+       "iauC2i00b", "21", status);
+   vvd(rc2i[1][1], 0.9999999991917574043, 1e-12,
+       "iauC2i00b", "22", status);
+   vvd(rc2i[1][2], -0.4020552974819030066e-4, 1e-12,
+       "iauC2i00b", "23", status);
+
+   vvd(rc2i[2][0], 0.5791301929950208873e-3, 1e-12,
+       "iauC2i00b", "31", status);
+   vvd(rc2i[2][1], 0.4020553681373720832e-4, 1e-12,
+       "iauC2i00b", "32", status);
+   vvd(rc2i[2][2], 0.9999998314958529887, 1e-12,
+       "iauC2i00b", "33", status);
+
+}
+
+static void t_c2i06a(int *status)
+/*
+**  - - - - - - - - -
+**   t _ c 2 i 0 6 a
+**  - - - - - - - - -
+**
+**  Test iauC2i06a function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauC2i06a, vvd
+**
+**  This revision:  2008 November 28
+*/
+{
+   double rc2i[3][3];
+
+
+   iauC2i06a(2400000.5, 53736.0, rc2i);
+
+   vvd(rc2i[0][0], 0.9999998323037159379, 1e-12,
+       "iauC2i06a", "11", status);
+   vvd(rc2i[0][1], 0.5581121329587613787e-9, 1e-12,
+       "iauC2i06a", "12", status);
+   vvd(rc2i[0][2], -0.5791308487740529749e-3, 1e-12,
+       "iauC2i06a", "13", status);
+
+   vvd(rc2i[1][0], -0.2384253169452306581e-7, 1e-12,
+       "iauC2i06a", "21", status);
+   vvd(rc2i[1][1], 0.9999999991917467827, 1e-12,
+       "iauC2i06a", "22", status);
+   vvd(rc2i[1][2], -0.4020579392895682558e-4, 1e-12,
+       "iauC2i06a", "23", status);
+
+   vvd(rc2i[2][0], 0.5791308482835292617e-3, 1e-12,
+       "iauC2i06a", "31", status);
+   vvd(rc2i[2][1], 0.4020580099454020310e-4, 1e-12,
+       "iauC2i06a", "32", status);
+   vvd(rc2i[2][2], 0.9999998314954628695, 1e-12,
+       "iauC2i06a", "33", status);
+
+}
+
+static void t_c2ibpn(int *status)
+/*
+**  - - - - - - - - -
+**   t _ c 2 i b p n
+**  - - - - - - - - -
+**
+**  Test iauC2ibpn function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauC2ibpn, vvd
+**
+**  This revision:  2008 November 28
+*/
+{
+   double rbpn[3][3], rc2i[3][3];
+
+
+   rbpn[0][0] =  9.999962358680738e-1;
+   rbpn[0][1] = -2.516417057665452e-3;
+   rbpn[0][2] = -1.093569785342370e-3;
+
+   rbpn[1][0] =  2.516462370370876e-3;
+   rbpn[1][1] =  9.999968329010883e-1;
+   rbpn[1][2] =  4.006159587358310e-5;
+
+   rbpn[2][0] =  1.093465510215479e-3;
+   rbpn[2][1] = -4.281337229063151e-5;
+   rbpn[2][2] =  9.999994012499173e-1;
+
+   iauC2ibpn(2400000.5, 50123.9999, rbpn, rc2i);
+
+   vvd(rc2i[0][0], 0.9999994021664089977, 1e-12,
+       "iauC2ibpn", "11", status);
+   vvd(rc2i[0][1], -0.3869195948017503664e-8, 1e-12,
+       "iauC2ibpn", "12", status);
+   vvd(rc2i[0][2], -0.1093465511383285076e-2, 1e-12,
+       "iauC2ibpn", "13", status);
+
+   vvd(rc2i[1][0], 0.5068413965715446111e-7, 1e-12,
+       "iauC2ibpn", "21", status);
+   vvd(rc2i[1][1], 0.9999999990835075686, 1e-12,
+       "iauC2ibpn", "22", status);
+   vvd(rc2i[1][2], 0.4281334246452708915e-4, 1e-12,
+       "iauC2ibpn", "23", status);
+
+   vvd(rc2i[2][0], 0.1093465510215479000e-2, 1e-12,
+       "iauC2ibpn", "31", status);
+   vvd(rc2i[2][1], -0.4281337229063151000e-4, 1e-12,
+       "iauC2ibpn", "32", status);
+   vvd(rc2i[2][2], 0.9999994012499173103, 1e-12,
+       "iauC2ibpn", "33", status);
+
+}
+
+static void t_c2ixy(int *status)
+/*
+**  - - - - - - - -
+**   t _ c 2 i x y
+**  - - - - - - - -
+**
+**  Test iauC2ixy function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauC2ixy, vvd
+**
+**  This revision:  2008 November 28
+*/
+{
+   double x, y, rc2i[3][3];
+
+
+   x = 0.5791308486706011000e-3;
+   y = 0.4020579816732961219e-4;
+
+   iauC2ixy(2400000.5, 53736, x, y, rc2i);
+
+   vvd(rc2i[0][0], 0.9999998323037157138, 1e-12,
+       "iauC2ixy", "11", status);
+   vvd(rc2i[0][1], 0.5581526349032241205e-9, 1e-12,
+       "iauC2ixy", "12", status);
+   vvd(rc2i[0][2], -0.5791308491611263745e-3, 1e-12,
+       "iauC2ixy", "13", status);
+
+   vvd(rc2i[1][0], -0.2384257057469842953e-7, 1e-12,
+       "iauC2ixy", "21", status);
+   vvd(rc2i[1][1], 0.9999999991917468964, 1e-12,
+       "iauC2ixy", "22", status);
+   vvd(rc2i[1][2], -0.4020579110172324363e-4, 1e-12,
+       "iauC2ixy", "23", status);
+
+   vvd(rc2i[2][0], 0.5791308486706011000e-3, 1e-12,
+       "iauC2ixy", "31", status);
+   vvd(rc2i[2][1], 0.4020579816732961219e-4, 1e-12,
+       "iauC2ixy", "32", status);
+   vvd(rc2i[2][2], 0.9999998314954627590, 1e-12,
+       "iauC2ixy", "33", status);
+
+}
+
+static void t_c2ixys(int *status)
+/*
+**  - - - - - - - - -
+**   t _ c 2 i x y s
+**  - - - - - - - - -
+**
+**  Test iauC2ixys function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauC2ixys, vvd
+**
+**  This revision:  2008 November 28
+*/
+{
+   double x, y, s, rc2i[3][3];
+
+
+   x =  0.5791308486706011000e-3;
+   y =  0.4020579816732961219e-4;
+   s = -0.1220040848472271978e-7;
+
+   iauC2ixys(x, y, s, rc2i);
+
+   vvd(rc2i[0][0], 0.9999998323037157138, 1e-12,
+       "iauC2ixys", "11", status);
+   vvd(rc2i[0][1], 0.5581984869168499149e-9, 1e-12,
+       "iauC2ixys", "12", status);
+   vvd(rc2i[0][2], -0.5791308491611282180e-3, 1e-12,
+       "iauC2ixys", "13", status);
+
+   vvd(rc2i[1][0], -0.2384261642670440317e-7, 1e-12,
+       "iauC2ixys", "21", status);
+   vvd(rc2i[1][1], 0.9999999991917468964, 1e-12,
+       "iauC2ixys", "22", status);
+   vvd(rc2i[1][2], -0.4020579110169668931e-4, 1e-12,
+       "iauC2ixys", "23", status);
+
+   vvd(rc2i[2][0], 0.5791308486706011000e-3, 1e-12,
+       "iauC2ixys", "31", status);
+   vvd(rc2i[2][1], 0.4020579816732961219e-4, 1e-12,
+       "iauC2ixys", "32", status);
+   vvd(rc2i[2][2], 0.9999998314954627590, 1e-12,
+       "iauC2ixys", "33", status);
+
+}
+
+static void t_c2s(int *status)
+/*
+**  - - - - - -
+**   t _ c 2 s
+**  - - - - - -
+**
+**  Test iauC2s function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauC2s, vvd
+**
+**  This revision:  2008 May 27
+*/
+{
+   double p[3], theta, phi;
+
+
+   p[0] = 100.0;
+   p[1] = -50.0;
+   p[2] =  25.0;
+
+   iauC2s(p, &theta, &phi);
+
+   vvd(theta, -0.4636476090008061162, 1e-14, "iauC2s", "theta", status);
+   vvd(phi, 0.2199879773954594463, 1e-14, "iauC2s", "phi", status);
+
+}
+
+static void t_c2t00a(int *status)
+/*
+**  - - - - - - - - -
+**   t _ c 2 t 0 0 a
+**  - - - - - - - - -
+**
+**  Test iauC2t00a function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauC2t00a, vvd
+**
+**  This revision:  2008 November 28
+*/
+{
+   double tta, ttb, uta, utb, xp, yp, rc2t[3][3];
+
+
+   tta = 2400000.5;
+   uta = 2400000.5;
+   ttb = 53736.0;
+   utb = 53736.0;
+   xp = 2.55060238e-7;
+   yp = 1.860359247e-6;
+
+   iauC2t00a(tta, ttb, uta, utb, xp, yp, rc2t);
+
+   vvd(rc2t[0][0], -0.1810332128307182668, 1e-12,
+       "iauC2t00a", "11", status);
+   vvd(rc2t[0][1], 0.9834769806938457836, 1e-12,
+       "iauC2t00a", "12", status);
+   vvd(rc2t[0][2], 0.6555535638688341725e-4, 1e-12,
+       "iauC2t00a", "13", status);
+
+   vvd(rc2t[1][0], -0.9834768134135984552, 1e-12,
+       "iauC2t00a", "21", status);
+   vvd(rc2t[1][1], -0.1810332203649520727, 1e-12,
+       "iauC2t00a", "22", status);
+   vvd(rc2t[1][2], 0.5749801116141056317e-3, 1e-12,
+       "iauC2t00a", "23", status);
+
+   vvd(rc2t[2][0], 0.5773474014081406921e-3, 1e-12,
+       "iauC2t00a", "31", status);
+   vvd(rc2t[2][1], 0.3961832391770163647e-4, 1e-12,
+       "iauC2t00a", "32", status);
+   vvd(rc2t[2][2], 0.9999998325501692289, 1e-12,
+       "iauC2t00a", "33", status);
+
+}
+
+static void t_c2t00b(int *status)
+/*
+**  - - - - - - - - -
+**   t _ c 2 t 0 0 b
+**  - - - - - - - - -
+**
+**  Test iauC2t00b function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauC2t00b, vvd
+**
+**  This revision:  2008 November 28
+*/
+{
+   double tta, ttb, uta, utb, xp, yp, rc2t[3][3];
+
+
+   tta = 2400000.5;
+   uta = 2400000.5;
+   ttb = 53736.0;
+   utb = 53736.0;
+   xp = 2.55060238e-7;
+   yp = 1.860359247e-6;
+
+   iauC2t00b(tta, ttb, uta, utb, xp, yp, rc2t);
+
+   vvd(rc2t[0][0], -0.1810332128439678965, 1e-12,
+       "iauC2t00b", "11", status);
+   vvd(rc2t[0][1], 0.9834769806913872359, 1e-12,
+       "iauC2t00b", "12", status);
+   vvd(rc2t[0][2], 0.6555565082458415611e-4, 1e-12,
+       "iauC2t00b", "13", status);
+
+   vvd(rc2t[1][0], -0.9834768134115435923, 1e-12,
+       "iauC2t00b", "21", status);
+   vvd(rc2t[1][1], -0.1810332203784001946, 1e-12,
+       "iauC2t00b", "22", status);
+   vvd(rc2t[1][2], 0.5749793922030017230e-3, 1e-12,
+       "iauC2t00b", "23", status);
+
+   vvd(rc2t[2][0], 0.5773467471863534901e-3, 1e-12,
+       "iauC2t00b", "31", status);
+   vvd(rc2t[2][1], 0.3961790411549945020e-4, 1e-12,
+       "iauC2t00b", "32", status);
+   vvd(rc2t[2][2], 0.9999998325505635738, 1e-12,
+       "iauC2t00b", "33", status);
+
+}
+
+static void t_c2t06a(int *status)
+/*
+**  - - - - - - - - -
+**   t _ c 2 t 0 6 a
+**  - - - - - - - - -
+**
+**  Test iauC2t06a function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauC2t06a, vvd
+**
+**  This revision:  2008 November 28
+*/
+{
+   double tta, ttb, uta, utb, xp, yp, rc2t[3][3];
+
+
+   tta = 2400000.5;
+   uta = 2400000.5;
+   ttb = 53736.0;
+   utb = 53736.0;
+   xp = 2.55060238e-7;
+   yp = 1.860359247e-6;
+
+   iauC2t06a(tta, ttb, uta, utb, xp, yp, rc2t);
+
+   vvd(rc2t[0][0], -0.1810332128305897282, 1e-12,
+       "iauC2t06a", "11", status);
+   vvd(rc2t[0][1], 0.9834769806938592296, 1e-12,
+       "iauC2t06a", "12", status);
+   vvd(rc2t[0][2], 0.6555550962998436505e-4, 1e-12,
+       "iauC2t06a", "13", status);
+
+   vvd(rc2t[1][0], -0.9834768134136214897, 1e-12,
+       "iauC2t06a", "21", status);
+   vvd(rc2t[1][1], -0.1810332203649130832, 1e-12,
+       "iauC2t06a", "22", status);
+   vvd(rc2t[1][2], 0.5749800844905594110e-3, 1e-12,
+       "iauC2t06a", "23", status);
+
+   vvd(rc2t[2][0], 0.5773474024748545878e-3, 1e-12,
+       "iauC2t06a", "31", status);
+   vvd(rc2t[2][1], 0.3961816829632690581e-4, 1e-12,
+       "iauC2t06a", "32", status);
+   vvd(rc2t[2][2], 0.9999998325501747785, 1e-12,
+       "iauC2t06a", "33", status);
+
+}
+
+static void t_c2tcio(int *status)
+/*
+**  - - - - - - - - -
+**   t _ c 2 t c i o
+**  - - - - - - - - -
+**
+**  Test iauC2tcio function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauC2tcio, vvd
+**
+**  This revision:  2008 November 28
+*/
+{
+   double rc2i[3][3], era, rpom[3][3], rc2t[3][3];
+
+
+   rc2i[0][0] =  0.9999998323037164738;
+   rc2i[0][1] =  0.5581526271714303683e-9;
+   rc2i[0][2] = -0.5791308477073443903e-3;
+
+   rc2i[1][0] = -0.2384266227524722273e-7;
+   rc2i[1][1] =  0.9999999991917404296;
+   rc2i[1][2] = -0.4020594955030704125e-4;
+
+   rc2i[2][0] =  0.5791308472168153320e-3;
+   rc2i[2][1] =  0.4020595661593994396e-4;
+   rc2i[2][2] =  0.9999998314954572365;
+
+   era = 1.75283325530307;
+
+   rpom[0][0] =  0.9999999999999674705;
+   rpom[0][1] = -0.1367174580728847031e-10;
+   rpom[0][2] =  0.2550602379999972723e-6;
+
+   rpom[1][0] =  0.1414624947957029721e-10;
+   rpom[1][1] =  0.9999999999982694954;
+   rpom[1][2] = -0.1860359246998866338e-5;
+
+   rpom[2][0] = -0.2550602379741215275e-6;
+   rpom[2][1] =  0.1860359247002413923e-5;
+   rpom[2][2] =  0.9999999999982369658;
+
+
+   iauC2tcio(rc2i, era, rpom, rc2t);
+
+   vvd(rc2t[0][0], -0.1810332128307110439, 1e-12,
+       "iauC2tcio", "11", status);
+   vvd(rc2t[0][1], 0.9834769806938470149, 1e-12,
+       "iauC2tcio", "12", status);
+   vvd(rc2t[0][2], 0.6555535638685466874e-4, 1e-12,
+       "iauC2tcio", "13", status);
+
+   vvd(rc2t[1][0], -0.9834768134135996657, 1e-12,
+       "iauC2tcio", "21", status);
+   vvd(rc2t[1][1], -0.1810332203649448367, 1e-12,
+       "iauC2tcio", "22", status);
+   vvd(rc2t[1][2], 0.5749801116141106528e-3, 1e-12,
+       "iauC2tcio", "23", status);
+
+   vvd(rc2t[2][0], 0.5773474014081407076e-3, 1e-12,
+       "iauC2tcio", "31", status);
+   vvd(rc2t[2][1], 0.3961832391772658944e-4, 1e-12,
+       "iauC2tcio", "32", status);
+   vvd(rc2t[2][2], 0.9999998325501691969, 1e-12,
+       "iauC2tcio", "33", status);
+
+}
+
+static void t_c2teqx(int *status)
+/*
+**  - - - - - - - - -
+**   t _ c 2 t e q x
+**  - - - - - - - - -
+**
+**  Test iauC2teqx function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauC2teqx, vvd
+**
+**  This revision:  2008 November 28
+*/
+{
+   double rbpn[3][3], gst, rpom[3][3], rc2t[3][3];
+
+
+   rbpn[0][0] =  0.9999989440476103608;
+   rbpn[0][1] = -0.1332881761240011518e-2;
+   rbpn[0][2] = -0.5790767434730085097e-3;
+
+   rbpn[1][0] =  0.1332858254308954453e-2;
+   rbpn[1][1] =  0.9999991109044505944;
+   rbpn[1][2] = -0.4097782710401555759e-4;
+
+   rbpn[2][0] =  0.5791308472168153320e-3;
+   rbpn[2][1] =  0.4020595661593994396e-4;
+   rbpn[2][2] =  0.9999998314954572365;
+
+   gst = 1.754166138040730516;
+
+   rpom[0][0] =  0.9999999999999674705;
+   rpom[0][1] = -0.1367174580728847031e-10;
+   rpom[0][2] =  0.2550602379999972723e-6;
+
+   rpom[1][0] =  0.1414624947957029721e-10;
+   rpom[1][1] =  0.9999999999982694954;
+   rpom[1][2] = -0.1860359246998866338e-5;
+
+   rpom[2][0] = -0.2550602379741215275e-6;
+   rpom[2][1] =  0.1860359247002413923e-5;
+   rpom[2][2] =  0.9999999999982369658;
+
+   iauC2teqx(rbpn, gst, rpom, rc2t);
+
+   vvd(rc2t[0][0], -0.1810332128528685730, 1e-12,
+       "iauC2teqx", "11", status);
+   vvd(rc2t[0][1], 0.9834769806897685071, 1e-12,
+       "iauC2teqx", "12", status);
+   vvd(rc2t[0][2], 0.6555535639982634449e-4, 1e-12,
+       "iauC2teqx", "13", status);
+
+   vvd(rc2t[1][0], -0.9834768134095211257, 1e-12,
+       "iauC2teqx", "21", status);
+   vvd(rc2t[1][1], -0.1810332203871023800, 1e-12,
+       "iauC2teqx", "22", status);
+   vvd(rc2t[1][2], 0.5749801116126438962e-3, 1e-12,
+       "iauC2teqx", "23", status);
+
+   vvd(rc2t[2][0], 0.5773474014081539467e-3, 1e-12,
+       "iauC2teqx", "31", status);
+   vvd(rc2t[2][1], 0.3961832391768640871e-4, 1e-12,
+       "iauC2teqx", "32", status);
+   vvd(rc2t[2][2], 0.9999998325501691969, 1e-12,
+       "iauC2teqx", "33", status);
+
+}
+
+static void t_c2tpe(int *status)
+/*
+**  - - - - - - - -
+**   t _ c 2 t p e
+**  - - - - - - - -
+**
+**  Test iauC2tpe function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauC2tpe, vvd
+**
+**  This revision:  2008 November 28
+*/
+{
+   double tta, ttb, uta, utb, dpsi, deps, xp, yp, rc2t[3][3];
+
+
+   tta = 2400000.5;
+   uta = 2400000.5;
+   ttb = 53736.0;
+   utb = 53736.0;
+   deps =  0.4090789763356509900;
+   dpsi = -0.9630909107115582393e-5;
+   xp = 2.55060238e-7;
+   yp = 1.860359247e-6;
+
+   iauC2tpe(tta, ttb, uta, utb, dpsi, deps, xp, yp, rc2t);
+
+   vvd(rc2t[0][0], -0.1813677995763029394, 1e-12,
+       "iauC2tpe", "11", status);
+   vvd(rc2t[0][1], 0.9023482206891683275, 1e-12,
+       "iauC2tpe", "12", status);
+   vvd(rc2t[0][2], -0.3909902938641085751, 1e-12,
+       "iauC2tpe", "13", status);
+
+   vvd(rc2t[1][0], -0.9834147641476804807, 1e-12,
+       "iauC2tpe", "21", status);
+   vvd(rc2t[1][1], -0.1659883635434995121, 1e-12,
+       "iauC2tpe", "22", status);
+   vvd(rc2t[1][2], 0.7309763898042819705e-1, 1e-12,
+       "iauC2tpe", "23", status);
+
+   vvd(rc2t[2][0], 0.1059685430673215247e-2, 1e-12,
+       "iauC2tpe", "31", status);
+   vvd(rc2t[2][1], 0.3977631855605078674, 1e-12,
+       "iauC2tpe", "32", status);
+   vvd(rc2t[2][2], 0.9174875068792735362, 1e-12,
+       "iauC2tpe", "33", status);
+
+}
+
+static void t_c2txy(int *status)
+/*
+**  - - - - - - - -
+**   t _ c 2 t x y
+**  - - - - - - - -
+**
+**  Test iauC2txy function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauC2txy, vvd
+**
+**  This revision:  2008 November 28
+*/
+{
+   double tta, ttb, uta, utb, x, y, xp, yp, rc2t[3][3];
+
+
+   tta = 2400000.5;
+   uta = 2400000.5;
+   ttb = 53736.0;
+   utb = 53736.0;
+   x = 0.5791308486706011000e-3;
+   y = 0.4020579816732961219e-4;
+   xp = 2.55060238e-7;
+   yp = 1.860359247e-6;
+
+   iauC2txy(tta, ttb, uta, utb, x, y, xp, yp, rc2t);
+
+   vvd(rc2t[0][0], -0.1810332128306279253, 1e-12,
+       "iauC2txy", "11", status);
+   vvd(rc2t[0][1], 0.9834769806938520084, 1e-12,
+       "iauC2txy", "12", status);
+   vvd(rc2t[0][2], 0.6555551248057665829e-4, 1e-12,
+       "iauC2txy", "13", status);
+
+   vvd(rc2t[1][0], -0.9834768134136142314, 1e-12,
+       "iauC2txy", "21", status);
+   vvd(rc2t[1][1], -0.1810332203649529312, 1e-12,
+       "iauC2txy", "22", status);
+   vvd(rc2t[1][2], 0.5749800843594139912e-3, 1e-12,
+       "iauC2txy", "23", status);
+
+   vvd(rc2t[2][0], 0.5773474028619264494e-3, 1e-12,
+       "iauC2txy", "31", status);
+   vvd(rc2t[2][1], 0.3961816546911624260e-4, 1e-12,
+       "iauC2txy", "32", status);
+   vvd(rc2t[2][2], 0.9999998325501746670, 1e-12,
+       "iauC2txy", "33", status);
+
+}
+
+static void t_cal2jd(int *status)
+/*
+**  - - - - - - - - -
+**   t _ c a l 2 j d
+**  - - - - - - - - -
+**
+**  Test iauCal2jd function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauCal2jd, vvd, viv
+**
+**  This revision:  2008 May 27
+*/
+{
+   int j;
+   double djm0, djm;
+
+
+   j = iauCal2jd(2003, 06, 01, &djm0, &djm);
+
+   vvd(djm0, 2400000.5, 0.0, "iauCal2jd", "djm0", status);
+   vvd(djm,    52791.0, 0.0, "iauCal2jd", "djm", status);
+
+   viv(j, 0, "iauCal2jd", "j", status);
+
+}
+
+static void t_cp(int *status)
+/*
+**  - - - - -
+**   t _ c p
+**  - - - - -
+**
+**  Test iauCp function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauCp, vvd
+**
+**  This revision:  2008 November 30
+*/
+{
+   double p[3], c[3];
+
+
+   p[0] =  0.3;
+   p[1] =  1.2;
+   p[2] = -2.5;
+
+   iauCp(p, c);
+
+   vvd(c[0],  0.3, 0.0, "iauCp", "1", status);
+   vvd(c[1],  1.2, 0.0, "iauCp", "2", status);
+   vvd(c[2], -2.5, 0.0, "iauCp", "3", status);
+}
+
+static void t_cpv(int *status)
+/*
+**  - - - - - -
+**   t _ c p v
+**  - - - - - -
+**
+**  Test iauCpv function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauCpv, vvd
+**
+**  This revision:  2008 May 25
+*/
+{
+   double pv[2][3], c[2][3];
+
+
+   pv[0][0] =  0.3;
+   pv[0][1] =  1.2;
+   pv[0][2] = -2.5;
+
+   pv[1][0] = -0.5;
+   pv[1][1] =  3.1;
+   pv[1][2] =  0.9;
+
+   iauCpv(pv, c);
+
+   vvd(c[0][0],  0.3, 0.0, "iauCpv", "p1", status);
+   vvd(c[0][1],  1.2, 0.0, "iauCpv", "p2", status);
+   vvd(c[0][2], -2.5, 0.0, "iauCpv", "p3", status);
+
+   vvd(c[1][0], -0.5, 0.0, "iauCpv", "v1", status);
+   vvd(c[1][1],  3.1, 0.0, "iauCpv", "v2", status);
+   vvd(c[1][2],  0.9, 0.0, "iauCpv", "v3", status);
+
+}
+
+static void t_cr(int *status)
+/*
+**  - - - - -
+**   t _ c r
+**  - - - - -
+**
+**  Test iauCr function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauCr, vvd
+**
+**  This revision:  2008 November 30
+*/
+{
+   double r[3][3], c[3][3];
+
+
+   r[0][0] = 2.0;
+   r[0][1] = 3.0;
+   r[0][2] = 2.0;
+
+   r[1][0] = 3.0;
+   r[1][1] = 2.0;
+   r[1][2] = 3.0;
+
+   r[2][0] = 3.0;
+   r[2][1] = 4.0;
+   r[2][2] = 5.0;
+
+   iauCr(r, c);
+
+   vvd(c[0][0], 2.0, 0.0, "iauCr", "11", status);
+   vvd(c[0][1], 3.0, 0.0, "iauCr", "12", status);
+   vvd(c[0][2], 2.0, 0.0, "iauCr", "13", status);
+
+   vvd(c[1][0], 3.0, 0.0, "iauCr", "21", status);
+   vvd(c[1][1], 2.0, 0.0, "iauCr", "22", status);
+   vvd(c[1][2], 3.0, 0.0, "iauCr", "23", status);
+
+   vvd(c[2][0], 3.0, 0.0, "iauCr", "31", status);
+   vvd(c[2][1], 4.0, 0.0, "iauCr", "32", status);
+   vvd(c[2][2], 5.0, 0.0, "iauCr", "33", status);
+}
+
+static void t_d2dtf(int *status )
+/*
+**  - - - - - - - -
+**   t _ d 2 d t f
+**  - - - - - - - -
+**
+**  Test iauD2dtf function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauD2dtf, viv
+**
+**  This revision:  2010 September 7
+*/
+{
+   int j, iy, im, id, ihmsf[4];
+
+
+   j = iauD2dtf("UTC", 5, 2400000.5, 49533.99999, &iy, &im, &id, ihmsf);
+
+   viv(iy, 1994, "iauD2dtf", "y", status);
+   viv(im, 6, "iauD2dtf", "mo", status);
+   viv(id, 30, "iauD2dtf", "d", status);
+   viv(ihmsf[0], 23, "iauD2dtf", "h", status);
+   viv(ihmsf[1], 59, "iauD2dtf", "m", status);
+   viv(ihmsf[2], 60, "iauD2dtf", "s", status);
+   viv(ihmsf[3], 13599, "iauD2dtf", "f", status);
+   viv(j, 0, "iauD2dtf", "j", status);
+
+}
+
+static void t_d2tf(int *status)
+/*
+**  - - - - - - -
+**   t _ d 2 t f
+**  - - - - - - -
+**
+**  Test iauD2tf function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauD2tf, viv, vvd
+**
+**  This revision:  2008 November 30
+*/
+{
+   int ihmsf[4];
+   char s;
+
+
+   iauD2tf(4, -0.987654321, &s, ihmsf);
+
+   viv((int)s, '-', "iauD2tf", "s", status);
+
+   viv(ihmsf[0], 23, "iauD2tf", "0", status);
+   viv(ihmsf[1], 42, "iauD2tf", "1", status);
+   viv(ihmsf[2], 13, "iauD2tf", "2", status);
+   viv(ihmsf[3], 3333, "iauD2tf", "3", status);
+
+}
+
+static void t_dat(int *status)
+/*
+**  - - - - - -
+**   t _ d a t
+**  - - - - - -
+**
+**  Test iauDat function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauDat, vvd, viv
+**
+**  This revision:  2008 November 29
+*/
+{
+   int j;
+   double deltat;
+
+
+   j = iauDat(2003, 6, 1, 0.0, &deltat);
+
+   vvd(deltat, 32.0, 0.0, "iauDat", "d1", status);
+   viv(j, 0, "iauDat", "j1", status);
+
+   j = iauDat(2008, 1, 17, 0.0, &deltat);
+
+   vvd(deltat, 33.0, 0.0, "iauDat", "d2", status);
+   viv(j, 0, "iauDat", "j2", status);
+
+}
+
+static void t_dtdb(int *status)
+/*
+**  - - - - - - -
+**   t _ d t d b
+**  - - - - - - -
+**
+**  Test iauDtdb function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauDtdb, vvd
+**
+**  This revision:  2008 November 28
+*/
+{
+   double dtdb;
+
+
+   dtdb = iauDtdb(2448939.5, 0.123, 0.76543, 5.0123, 5525.242, 3190.0);
+
+   vvd(dtdb, -0.1280368005936998991e-2, 1e-15, "iauDtdb", "", status);
+
+}
+
+static void t_dtf2d(int *status)
+/*
+**  - - - - - - - -
+**   t _ d t f 2 d
+**  - - - - - - - -
+**
+**  Test iauDtf2d function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauDtf2d, vvd, viv
+**
+**  This revision:  2010 September 7
+*/
+{
+   double u1, u2;
+   int j;
+
+
+   j = iauDtf2d("UTC", 1994, 6, 30, 23, 59, 60.13599, &u1, &u2);
+
+   vvd(u1+u2, 2449534.49999, 1e-6, "iauDtf2d", "u", status);
+   viv(j, 0, "iauDtf2d", "j", status);
+
+}
+
+static void t_ee00(int *status)
+/*
+**  - - - - - - -
+**   t _ e e 0 0
+**  - - - - - - -
+**
+**  Test iauEe00 function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauEe00, vvd
+**
+**  This revision:  2008 November 28
+*/
+{
+   double epsa, dpsi, ee;
+
+
+   epsa =  0.4090789763356509900;
+   dpsi = -0.9630909107115582393e-5;
+
+   ee = iauEe00(2400000.5, 53736.0, epsa, dpsi);
+
+   vvd(ee, -0.8834193235367965479e-5, 1e-18, "iauEe00", "", status);
+
+}
+
+static void t_ee00a(int *status)
+/*
+**  - - - - - - - -
+**   t _ e e 0 0 a
+**  - - - - - - - -
+**
+**  Test iauEe00a function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauEe00a, vvd
+**
+**  This revision:  2008 November 28
+*/
+{
+   double ee;
+
+
+   ee = iauEe00a(2400000.5, 53736.0);
+
+   vvd(ee, -0.8834192459222588227e-5, 1e-18, "iauEe00a", "", status);
+
+}
+
+static void t_ee00b(int *status)
+/*
+**  - - - - - - - -
+**   t _ e e 0 0 b
+**  - - - - - - - -
+**
+**  Test iauEe00b function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauEe00b, vvd
+**
+**  This revision:  2008 November 28
+*/
+{
+   double ee;
+
+
+   ee = iauEe00b(2400000.5, 53736.0);
+
+   vvd(ee, -0.8835700060003032831e-5, 1e-18, "iauEe00b", "", status);
+
+}
+
+static void t_ee06a(int *status)
+/*
+**  - - - - - - - -
+**   t _ e e 0 6 a
+**  - - - - - - - -
+**
+**  Test iauEe06a function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauEe06a, vvd
+**
+**  This revision:  2008 November 28
+*/
+{
+   double ee;
+
+
+   ee = iauEe06a(2400000.5, 53736.0);
+
+   vvd(ee, -0.8834195072043790156e-5, 1e-15, "iauEe06a", "", status);
+}
+
+static void t_eect00(int *status)
+/*
+**  - - - - - - - - -
+**   t _ e e c t 0 0
+**  - - - - - - - - -
+**
+**  Test iauEect00 function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauEect00, vvd
+**
+**  This revision:  2008 November 28
+*/
+{
+   double eect;
+
+
+   eect = iauEect00(2400000.5, 53736.0);
+
+   vvd(eect, 0.2046085004885125264e-8, 1e-20, "iauEect00", "", status);
+
+}
+
+static void t_eform(int *status)
+/*
+**  - - - - - - - -
+**   t _ e f o r m
+**  - - - - - - - -
+**
+**  Test iauEform function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauEform, viv, vvd
+**
+**  This revision:  2012 February 23
+*/
+{
+   int j;
+   double a, f;
+
+   j = iauEform(0, &a, &f);
+
+   viv(j, -1, "iauEform", "j0", status);
+
+   j = iauEform(WGS84, &a, &f);
+
+   viv(j, 0, "iauEform", "j1", status);
+   vvd(a, 6378137.0, 1e-10, "iauEform", "a1", status);
+   vvd(f, 0.0033528106647474807, 1e-18, "iauEform", "f1", status);
+
+   j = iauEform(GRS80, &a, &f);
+
+   viv(j, 0, "iauEform", "j2", status);
+   vvd(a, 6378137.0, 1e-10, "iauEform", "a2", status);
+   vvd(f, 0.0033528106811823189, 1e-18, "iauEform", "f2", status);
+
+   j = iauEform(WGS72, &a, &f);
+
+   viv(j, 0, "iauEform", "j2", status);
+   vvd(a, 6378135.0, 1e-10, "iauEform", "a3", status);
+   vvd(f, 0.0033527794541675049, 1e-18, "iauEform", "f3", status);
+
+   j = iauEform(4, &a, &f);
+   viv(j, -1, "iauEform", "j3", status);
+}
+
+static void t_eo06a(int *status)
+/*
+**  - - - - - - - -
+**   t _ e o 0 6 a
+**  - - - - - - - -
+**
+**  Test iauEo06a function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauEo06a, vvd
+**
+**  This revision:  2008 November 28
+*/
+{
+   double eo;
+
+
+   eo = iauEo06a(2400000.5, 53736.0);
+
+   vvd(eo, -0.1332882371941833644e-2, 1e-15, "iauEo06a", "", status);
+
+}
+
+static void t_eors(int *status)
+/*
+**  - - - - - - -
+**   t _ e o r s
+**  - - - - - - -
+**
+**  Test iauEors function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauEors, vvd
+**
+**  This revision:  2008 November 28
+*/
+{
+   double rnpb[3][3], s, eo;
+
+
+   rnpb[0][0] =  0.9999989440476103608;
+   rnpb[0][1] = -0.1332881761240011518e-2;
+   rnpb[0][2] = -0.5790767434730085097e-3;
+
+   rnpb[1][0] =  0.1332858254308954453e-2;
+   rnpb[1][1] =  0.9999991109044505944;
+   rnpb[1][2] = -0.4097782710401555759e-4;
+
+   rnpb[2][0] =  0.5791308472168153320e-3;
+   rnpb[2][1] =  0.4020595661593994396e-4;
+   rnpb[2][2] =  0.9999998314954572365;
+
+   s = -0.1220040848472271978e-7;
+
+   eo = iauEors(rnpb, s);
+
+   vvd(eo, -0.1332882715130744606e-2, 1e-14, "iauEors", "", status);
+
+}
+
+static void t_epb(int *status)
+/*
+**  - - - - - -
+**   t _ e p b
+**  - - - - - -
+**
+**  Test iauEpb function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauEpb, vvd
+**
+**  This revision:  2008 May 27
+*/
+{
+   double epb;
+
+
+   epb = iauEpb(2415019.8135, 30103.18648);
+
+   vvd(epb, 1982.418424159278580, 1e-12, "iauEpb", "", status);
+
+}
+
+static void t_epb2jd(int *status)
+/*
+**  - - - - - - - - -
+**   t _ e p b 2 j d
+**  - - - - - - - - -
+**
+**  Test iauEpb2jd function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauEpb2jd, vvd
+**
+**  This revision:  2008 November 29
+*/
+{
+   double epb, djm0, djm;
+
+
+   epb = 1957.3;
+
+   iauEpb2jd(epb, &djm0, &djm);
+
+   vvd(djm0, 2400000.5, 1e-9, "iauEpb2jd", "djm0", status);
+   vvd(djm, 35948.1915101513, 1e-9, "iauEpb2jd", "mjd", status);
+
+}
+
+static void t_epj(int *status)
+/*
+**  - - - - - -
+**   t _ e p j
+**  - - - - - -
+**
+**  Test iauEpj function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauEpj, vvd
+**
+**  This revision:  2008 May 27
+*/
+{
+   double epj;
+
+
+   epj = iauEpj(2451545, -7392.5);
+
+   vvd(epj, 1979.760438056125941, 1e-12, "iauEpj", "", status);
+
+}
+
+static void t_epj2jd(int *status)
+/*
+**  - - - - - - - - -
+**   t _ e p j 2 j d
+**  - - - - - - - - -
+**
+**  Test iauEpj2jd function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauEpj2jd, vvd
+**
+**  This revision:  2008 November 29
+*/
+{
+   double epj, djm0, djm;
+
+
+   epj = 1996.8;
+
+   iauEpj2jd(epj, &djm0, &djm);
+
+   vvd(djm0, 2400000.5, 1e-9, "iauEpj2jd", "djm0", status);
+   vvd(djm,    50375.7, 1e-9, "iauEpj2jd", "mjd",  status);
+
+}
+
+static void t_epv00(int *status)
+/*
+**  - - - - - - - -
+**   t _ e p v 0 0
+**  - - - - - - - -
+**
+**  Test iauEpv00 function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called: iauEpv00, vvd, viv
+**
+**  This revision:  2008 November 28
+*/
+{
+   double pvh[2][3], pvb[2][3];
+   int j;
+
+
+   j = iauEpv00(2400000.5, 53411.52501161, pvh, pvb);
+
+   vvd(pvh[0][0], -0.7757238809297706813, 1e-14,
+       "iauEpv00", "ph(x)", status);
+   vvd(pvh[0][1], 0.5598052241363340596, 1e-14,
+       "iauEpv00", "ph(y)", status);
+   vvd(pvh[0][2], 0.2426998466481686993, 1e-14,
+       "iauEpv00", "ph(z)", status);
+
+   vvd(pvh[1][0], -0.1091891824147313846e-1, 1e-15,
+       "iauEpv00", "vh(x)", status);
+   vvd(pvh[1][1], -0.1247187268440845008e-1, 1e-15,
+       "iauEpv00", "vh(y)", status);
+   vvd(pvh[1][2], -0.5407569418065039061e-2, 1e-15,
+       "iauEpv00", "vh(z)", status);
+
+   vvd(pvb[0][0], -0.7714104440491111971, 1e-14,
+       "iauEpv00", "pb(x)", status);
+   vvd(pvb[0][1], 0.5598412061824171323, 1e-14,
+       "iauEpv00", "pb(y)", status);
+   vvd(pvb[0][2], 0.2425996277722452400, 1e-14,
+       "iauEpv00", "pb(z)", status);
+
+   vvd(pvb[1][0], -0.1091874268116823295e-1, 1e-15,
+       "iauEpv00", "vb(x)", status);
+   vvd(pvb[1][1], -0.1246525461732861538e-1, 1e-15,
+       "iauEpv00", "vb(y)", status);
+   vvd(pvb[1][2], -0.5404773180966231279e-2, 1e-15,
+       "iauEpv00", "vb(z)", status);
+
+   viv(j, 0, "iauEpv00", "j", status);
+
+}
+
+static void t_eqeq94(int *status)
+/*
+**  - - - - - - - - -
+**   t _ e q e q 9 4
+**  - - - - - - - - -
+**
+**  Test iauEqeq94 function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauEqeq94, vvd
+**
+**  This revision:  2008 November 28
+*/
+{
+   double eqeq;
+
+
+   eqeq = iauEqeq94(2400000.5, 41234.0);
+
+   vvd(eqeq, 0.5357758254609256894e-4, 1e-17, "iauEqeq94", "", status);
+
+}
+
+static void t_era00(int *status)
+/*
+**  - - - - - - - -
+**   t _ e r a 0 0
+**  - - - - - - - -
+**
+**  Test iauEra00 function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauEra00, vvd
+**
+**  This revision:  2008 May 26
+*/
+{
+   double era00;
+
+
+   era00 = iauEra00(2400000.5, 54388.0);
+
+   vvd(era00, 0.4022837240028158102, 1e-12, "iauEra00", "", status);
+
+}
+
+static void t_fad03(int *status)
+/*
+**  - - - - - - - -
+**   t _ f a d 0 3
+**  - - - - - - - -
+**
+**  Test iauFad03 function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauFad03, vvd
+**
+**  This revision:  2008 May 22
+*/
+{
+   vvd(iauFad03(0.80), 1.946709205396925672, 1e-12,
+       "iauFad03", "", status);
+}
+
+static void t_fae03(int *status)
+/*
+**  - - - - - - - -
+**   t _ f a e 0 3
+**  - - - - - - - -
+**
+**  Test iauFae03 function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauFae03, vvd
+**
+**  This revision:  2008 May 22
+*/
+{
+   vvd(iauFae03(0.80), 1.744713738913081846, 1e-12,
+       "iauFae03", "", status);
+}
+
+static void t_faf03(int *status)
+/*
+**  - - - - - - - -
+**   t _ f a f 0 3
+**  - - - - - - - -
+**
+**  Test iauFaf03 function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauFaf03, vvd
+**
+**  This revision:  2008 May 22
+*/
+{
+   vvd(iauFaf03(0.80), 0.2597711366745499518, 1e-12,
+       "iauFaf03", "", status);
+}
+
+static void t_faju03(int *status)
+/*
+**  - - - - - - - - -
+**   t _ f a j u 0 3
+**  - - - - - - - - -
+**
+**  Test iauFaju03 function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauFaju03, vvd
+**
+**  This revision:  2008 May 22
+*/
+{
+   vvd(iauFaju03(0.80), 5.275711665202481138, 1e-12,
+       "iauFaju03", "", status);
+}
+
+static void t_fal03(int *status)
+/*
+**  - - - - - - - -
+**   t _ f a l 0 3
+**  - - - - - - - -
+**
+**  Test iauFal03 function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauFal03, vvd
+**
+**  This revision:  2008 May 22
+*/
+{
+   vvd(iauFal03(0.80), 5.132369751108684150, 1e-12,
+       "iauFal03", "", status);
+}
+
+static void t_falp03(int *status)
+/*
+**  - - - - - - - - -
+**   t _ f a l p 0 3
+**  - - - - - - - - -
+**
+**  Test iauFalp03 function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauFalp03, vvd
+**
+**  This revision:  2008 May 22
+*/
+{
+   vvd(iauFalp03(0.80), 6.226797973505507345, 1e-12,
+      "iauFalp03", "", status);
+}
+
+static void t_fama03(int *status)
+/*
+**  - - - - - - - - -
+**   t _ f a m a 0 3
+**  - - - - - - - - -
+**
+**  Test iauFama03 function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauFama03, vvd
+**
+**  This revision:  2008 May 22
+*/
+{
+   vvd(iauFama03(0.80), 3.275506840277781492, 1e-12,
+       "iauFama03", "", status);
+}
+
+static void t_fame03(int *status)
+/*
+**  - - - - - - - - -
+**   t _ f a m e 0 3
+**  - - - - - - - - -
+**
+**  Test iauFame03 function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauFame03, vvd
+**
+**  This revision:  2008 May 22
+*/
+{
+   vvd(iauFame03(0.80), 5.417338184297289661, 1e-12,
+       "iauFame03", "", status);
+}
+
+static void t_fane03(int *status)
+/*
+**  - - - - - - - - -
+**   t _ f a n e 0 3
+**  - - - - - - - - -
+**
+**  Test iauFane03 function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauFane03, vvd
+**
+**  This revision:  2008 May 22
+*/
+{
+   vvd(iauFane03(0.80), 2.079343830860413523, 1e-12,
+       "iauFane03", "", status);
+}
+
+static void t_faom03(int *status)
+/*
+**  - - - - - - - - -
+**   t _ f a o m 0 3
+**  - - - - - - - - -
+**
+**  Test iauFaom03 function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauFaom03, vvd
+**
+**  This revision:  2008 May 22
+*/
+{
+   vvd(iauFaom03(0.80), -5.973618440951302183, 1e-12,
+       "iauFaom03", "", status);
+}
+
+static void t_fapa03(int *status)
+/*
+**  - - - - - - - - -
+**   t _ f a p a 0 3
+**  - - - - - - - - -
+**
+**  Test iauFapa03 function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauFapa03, vvd
+**
+**  This revision:  2008 November 28
+*/
+{
+   vvd(iauFapa03(0.80), 0.1950884762240000000e-1, 1e-12,
+       "iauFapa03", "", status);
+}
+
+static void t_fasa03(int *status)
+/*
+**  - - - - - - - - -
+**   t _ f a s a 0 3
+**  - - - - - - - - -
+**
+**  Test iauFasa03 function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauFasa03, vvd
+**
+**  This revision:  2008 May 22
+*/
+{
+   vvd(iauFasa03(0.80), 5.371574539440827046, 1e-12,
+       "iauFasa03", "", status);
+}
+
+static void t_faur03(int *status)
+/*
+**  - - - - - - - - -
+**   t _ f a u r 0 3
+**  - - - - - - - - -
+**
+**  Test iauFaur03 function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauFaur03, vvd
+**
+**  This revision:  2008 May 22
+*/
+{
+   vvd(iauFaur03(0.80), 5.180636450180413523, 1e-12,
+       "iauFaur03", "", status);
+}
+
+static void t_fave03(int *status)
+/*
+**  - - - - - - - - -
+**   t _ f a v e 0 3
+**  - - - - - - - - -
+**
+**  Test iauFave03 function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauFave03, vvd
+**
+**  This revision:  2008 May 22
+*/
+{
+   vvd(iauFave03(0.80), 3.424900460533758000, 1e-12,
+       "iauFave03", "", status);
+}
+
+static void t_fk52h(int *status)
+/*
+**  - - - - - - - -
+**   t _ f k 5 2 h
+**  - - - - - - - -
+**
+**  Test iauFk52h function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauFk52h, vvd
+**
+**  This revision:  2009 November 6
+*/
+{
+   double r5, d5, dr5, dd5, px5, rv5, rh, dh, drh, ddh, pxh, rvh;
+
+
+   r5  =  1.76779433;
+   d5  = -0.2917517103;
+   dr5 = -1.91851572e-7;
+   dd5 = -5.8468475e-6;
+   px5 =  0.379210;
+   rv5 = -7.6;
+
+   iauFk52h(r5, d5, dr5, dd5, px5, rv5,
+            &rh, &dh, &drh, &ddh, &pxh, &rvh);
+
+   vvd(rh, 1.767794226299947632, 1e-14,
+       "iauFk52h", "ra", status);
+   vvd(dh,  -0.2917516070530391757, 1e-14,
+       "iauFk52h", "dec", status);
+   vvd(drh, -0.19618741256057224e-6,1e-19,
+       "iauFk52h", "dr5", status);
+   vvd(ddh, -0.58459905176693911e-5, 1e-19,
+       "iauFk52h", "dd5", status);
+   vvd(pxh,  0.37921, 1e-14,
+       "iauFk52h", "px", status);
+   vvd(rvh, -7.6000000940000254, 1e-11,
+       "iauFk52h", "rv", status);
+
+}
+
+static void t_fk5hip(int *status)
+/*
+**  - - - - - - - - -
+**   t _ f k 5 h i p
+**  - - - - - - - - -
+**
+**  Test iauFk5hip function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauFk5hip, vvd
+**
+**  This revision:  2008 November 30
+*/
+{
+   double r5h[3][3], s5h[3];
+
+
+   iauFk5hip(r5h, s5h);
+
+   vvd(r5h[0][0], 0.9999999999999928638, 1e-14,
+       "iauFk5hip", "11", status);
+   vvd(r5h[0][1], 0.1110223351022919694e-6, 1e-17,
+       "iauFk5hip", "12", status);
+   vvd(r5h[0][2], 0.4411803962536558154e-7, 1e-17,
+       "iauFk5hip", "13", status);
+   vvd(r5h[1][0], -0.1110223308458746430e-6, 1e-17,
+       "iauFk5hip", "21", status);
+   vvd(r5h[1][1], 0.9999999999999891830, 1e-14,
+       "iauFk5hip", "22", status);
+   vvd(r5h[1][2], -0.9647792498984142358e-7, 1e-17,
+       "iauFk5hip", "23", status);
+   vvd(r5h[2][0], -0.4411805033656962252e-7, 1e-17,
+       "iauFk5hip", "31", status);
+   vvd(r5h[2][1], 0.9647792009175314354e-7, 1e-17,
+       "iauFk5hip", "32", status);
+   vvd(r5h[2][2], 0.9999999999999943728, 1e-14,
+       "iauFk5hip", "33", status);
+   vvd(s5h[0], -0.1454441043328607981e-8, 1e-17,
+       "iauFk5hip", "s1", status);
+   vvd(s5h[1], 0.2908882086657215962e-8, 1e-17,
+       "iauFk5hip", "s2", status);
+   vvd(s5h[2], 0.3393695767766751955e-8, 1e-17,
+       "iauFk5hip", "s3", status);
+
+}
+
+static void t_fk5hz(int *status)
+/*
+**  - - - - - - - -
+**   t _ f k 5 h z
+**  - - - - - - - -
+**
+**  Test iauFk5hz function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauFk5hz, vvd
+**
+**  This revision:  2008 May 26
+*/
+{
+   double r5, d5, rh, dh;
+
+
+   r5 =  1.76779433;
+   d5 = -0.2917517103;
+
+   iauFk5hz(r5, d5, 2400000.5, 54479.0, &rh, &dh);
+
+   vvd(rh,  1.767794191464423978, 1e-12, "iauFk5hz", "ra", status);
+   vvd(dh, -0.2917516001679884419, 1e-12, "iauFk5hz", "dec", status);
+
+}
+
+static void t_fw2m(int *status)
+/*
+**  - - - - - - -
+**   t _ f w 2 m
+**  - - - - - - -
+**
+**  Test iauFw2m function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauFw2m, vvd
+**
+**  This revision:  2008 November 30
+*/
+{
+   double gamb, phib, psi, eps, r[3][3];
+
+
+   gamb = -0.2243387670997992368e-5;
+   phib =  0.4091014602391312982;
+   psi  = -0.9501954178013015092e-3;
+   eps  =  0.4091014316587367472;
+
+   iauFw2m(gamb, phib, psi, eps, r);
+
+   vvd(r[0][0], 0.9999995505176007047, 1e-12,
+       "iauFw2m", "11", status);
+   vvd(r[0][1], 0.8695404617348192957e-3, 1e-12,
+       "iauFw2m", "12", status);
+   vvd(r[0][2], 0.3779735201865582571e-3, 1e-12,
+       "iauFw2m", "13", status);
+
+   vvd(r[1][0], -0.8695404723772016038e-3, 1e-12,
+       "iauFw2m", "21", status);
+   vvd(r[1][1], 0.9999996219496027161, 1e-12,
+       "iauFw2m", "22", status);
+   vvd(r[1][2], -0.1361752496887100026e-6, 1e-12,
+       "iauFw2m", "23", status);
+
+   vvd(r[2][0], -0.3779734957034082790e-3, 1e-12,
+       "iauFw2m", "31", status);
+   vvd(r[2][1], -0.1924880848087615651e-6, 1e-12,
+       "iauFw2m", "32", status);
+   vvd(r[2][2], 0.9999999285679971958, 1e-12,
+       "iauFw2m", "33", status);
+
+}
+
+static void t_fw2xy(int *status)
+/*
+**  - - - - - - - -
+**   t _ f w 2 x y
+**  - - - - - - - -
+**
+**  Test iauFw2xy function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauFw2xy, vvd
+**
+**  This revision:  2008 November 28
+*/
+{
+   double gamb, phib, psi, eps, x, y;
+
+
+   gamb = -0.2243387670997992368e-5;
+   phib =  0.4091014602391312982;
+   psi  = -0.9501954178013015092e-3;
+   eps  =  0.4091014316587367472;
+
+   iauFw2xy(gamb, phib, psi, eps, &x, &y);
+
+   vvd(x, -0.3779734957034082790e-3, 1e-14, "iauFw2xy", "x", status);
+   vvd(y, -0.1924880848087615651e-6, 1e-14, "iauFw2xy", "y", status);
+
+}
+
+static void t_gc2gd(int *status)
+/*
+**  - - - - - - - -
+**   t _ g c 2 g d
+**  - - - - - - - -
+**
+**  Test iauGc2gd function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauGc2gd, viv, vvd
+**
+**  This revision:  2012 February 23
+*/
+{
+   int j;
+   double xyz[] = {2e6, 3e6, 5.244e6};
+   double e, p, h;
+
+   j = iauGc2gd(0, xyz, &e, &p, &h);
+
+   viv(j, -1, "iauGc2gd", "j0", status);
+
+   j = iauGc2gd(WGS84, xyz, &e, &p, &h);
+
+   viv(j, 0, "iauGc2gd", "j1", status);
+   vvd(e, 0.98279372324732907, 1e-14, "iauGc2gd", "e1", status);
+   vvd(p, 0.97160184819075459, 1e-14, "iauGc2gd", "p1", status);
+   vvd(h, 331.41724614260599, 1e-8, "iauGc2gd", "h1", status);
+
+   j = iauGc2gd(GRS80, xyz, &e, &p, &h);
+
+   viv(j, 0, "iauGc2gd", "j2", status);
+   vvd(e, 0.98279372324732907, 1e-14, "iauGc2gd", "e2", status);
+   vvd(p, 0.97160184820607853, 1e-14, "iauGc2gd", "p2", status);
+   vvd(h, 331.41731754844348, 1e-8, "iauGc2gd", "h2", status);
+
+   j = iauGc2gd(WGS72, xyz, &e, &p, &h);
+
+   viv(j, 0, "iauGc2gd", "j3", status);
+   vvd(e, 0.98279372324732907, 1e-14, "iauGc2gd", "e3", status);
+   vvd(p, 0.97160181811015119, 1e-14, "iauGc2gd", "p3", status);
+   vvd(h, 333.27707261303181, 1e-8, "iauGc2gd", "h3", status);
+
+   j = iauGc2gd(4, xyz, &e, &p, &h);
+
+   viv(j, -1, "iauGc2gd", "j4", status);
+}
+
+static void t_gc2gde(int *status)
+/*
+**  - - - - - - - - -
+**   t _ g c 2 g d e
+**  - - - - - - - - -
+**
+**  Test iauGc2gde function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauGc2gde, viv, vvd
+**
+**  This revision:  2010 September 7
+*/
+{
+   int j;
+   double a = 6378136.0, f = 0.0033528;
+   double xyz[] = {2e6, 3e6, 5.244e6};
+   double e, p, h;
+
+   j = iauGc2gde(a, f, xyz, &e, &p, &h);
+
+   viv(j, 0, "iauGc2gde", "j", status);
+   vvd(e, 0.98279372324732907, 1e-14, "iauGc2gde", "e", status);
+   vvd(p, 0.97160183775704115, 1e-14, "iauGc2gde", "p", status);
+   vvd(h, 332.36862495764397, 1e-8, "iauGc2gde", "h", status);
+}
+
+static void t_gd2gc(int *status)
+/*
+**  - - - - - - - -
+**   t _ g d 2 g c
+**  - - - - - - - -
+**
+**  Test iauGd2gc function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauGd2gc, viv, vvd
+**
+**  This revision:  2012 February 23
+*/
+{
+   int j;
+   double e = 3.1, p = -0.5, h = 2500.0;
+   double xyz[3];
+
+   j = iauGd2gc(0, e, p, h, xyz);
+
+   viv(j, -1, "iauGd2gc", "j0", status);
+
+   j = iauGd2gc(WGS84, e, p, h, xyz);
+
+   viv(j, 0, "iauGd2gc", "j1", status);
+   vvd(xyz[0], -5599000.5577049947, 1e-7, "iauGd2gc", "0/1", status);
+   vvd(xyz[1], 233011.67223479203, 1e-7, "iauGd2gc", "1/1", status);
+   vvd(xyz[2], -3040909.4706983363, 1e-7, "iauGd2gc", "2/1", status);
+
+   j = iauGd2gc(GRS80, e, p, h, xyz);
+
+   viv(j, 0, "iauGd2gc", "j2", status);
+   vvd(xyz[0], -5599000.5577260984, 1e-7, "iauGd2gc", "0/2", status);
+   vvd(xyz[1], 233011.6722356703, 1e-7, "iauGd2gc", "1/2", status);
+   vvd(xyz[2], -3040909.4706095476, 1e-7, "iauGd2gc", "2/2", status);
+
+   j = iauGd2gc(WGS72, e, p, h, xyz);
+
+   viv(j, 0, "iauGd2gc", "j3", status);
+   vvd(xyz[0], -5598998.7626301490, 1e-7, "iauGd2gc", "0/3", status);
+   vvd(xyz[1], 233011.5975297822, 1e-7, "iauGd2gc", "1/3", status);
+   vvd(xyz[2], -3040908.6861467111, 1e-7, "iauGd2gc", "2/3", status);
+
+   j = iauGd2gc(4, e, p, h, xyz);
+
+   viv(j, -1, "iauGd2gc", "j4", status);
+}
+
+static void t_gd2gce(int *status)
+/*
+**  - - - - - - - - -
+**   t _ g d 2 g c e
+**  - - - - - - - - -
+**
+**  Test iauGd2gce function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauGd2gce, viv, vvd
+**
+**  This revision:  2010 September 7
+*/
+{
+   int j;
+   double a = 6378136.0, f = 0.0033528;
+   double e = 3.1, p = -0.5, h = 2500.0;
+   double xyz[3];
+
+   j = iauGd2gce(a, f, e, p, h, xyz);
+
+   viv(j, 0, "iauGd2gce", "j", status);
+   vvd(xyz[0], -5598999.6665116328, 1e-7, "iauGd2gce", "0", status);
+   vvd(xyz[1], 233011.63514630572, 1e-7, "iauGd2gce", "1", status);
+   vvd(xyz[2], -3040909.0517314132, 1e-7, "iauGd2gce", "2", status);
+}
+
+static void t_gmst00(int *status)
+/*
+**  - - - - - - - - -
+**   t _ g m s t 0 0
+**  - - - - - - - - -
+**
+**  Test iauGmst00 function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauGmst00, vvd
+**
+**  This revision:  2008 May 26
+*/
+{
+   double theta;
+
+
+   theta = iauGmst00(2400000.5, 53736.0, 2400000.5, 53736.0);
+
+   vvd(theta, 1.754174972210740592, 1e-12, "iauGmst00", "", status);
+
+}
+
+static void t_gmst06(int *status)
+/*
+**  - - - - - - - - -
+**   t _ g m s t 0 6
+**  - - - - - - - - -
+**
+**  Test iauGmst06 function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauGmst06, vvd
+**
+**  This revision:  2008 May 26
+*/
+{
+   double theta;
+
+
+   theta = iauGmst06(2400000.5, 53736.0, 2400000.5, 53736.0);
+
+   vvd(theta, 1.754174971870091203, 1e-12, "iauGmst06", "", status);
+
+}
+
+static void t_gmst82(int *status)
+/*
+**  - - - - - - - - -
+**   t _ g m s t 8 2
+**  - - - - - - - - -
+**
+**  Test iauGmst82 function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauGmst82, vvd
+**
+**  This revision:  2008 May 26
+*/
+{
+   double theta;
+
+
+   theta = iauGmst82(2400000.5, 53736.0);
+
+   vvd(theta, 1.754174981860675096, 1e-12, "iauGmst82", "", status);
+
+}
+
+static void t_gst00a(int *status)
+/*
+**  - - - - - - - - -
+**   t _ g s t 0 0 a
+**  - - - - - - - - -
+**
+**  Test iauGst00a function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauGst00a, vvd
+**
+**  This revision:  2008 May 26
+*/
+{
+   double theta;
+
+
+   theta = iauGst00a(2400000.5, 53736.0, 2400000.5, 53736.0);
+
+   vvd(theta, 1.754166138018281369, 1e-12, "iauGst00a", "", status);
+
+}
+
+static void t_gst00b(int *status)
+/*
+**  - - - - - - - - -
+**   t _ g s t 0 0 b
+**  - - - - - - - - -
+**
+**  Test iauGst00b function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauGst00b, vvd
+**
+**  This revision:  2008 May 26
+*/
+{
+   double theta;
+
+
+   theta = iauGst00b(2400000.5, 53736.0);
+
+   vvd(theta, 1.754166136510680589, 1e-12, "iauGst00b", "", status);
+
+}
+
+static void t_gst06(int *status)
+/*
+**  - - - - - - - -
+**   t _ g s t 0 6
+**  - - - - - - - -
+**
+**  Test iauGst06 function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauGst06, vvd
+**
+**  This revision:  2008 November 28
+*/
+{
+   double rnpb[3][3], theta;
+
+
+   rnpb[0][0] =  0.9999989440476103608;
+   rnpb[0][1] = -0.1332881761240011518e-2;
+   rnpb[0][2] = -0.5790767434730085097e-3;
+
+   rnpb[1][0] =  0.1332858254308954453e-2;
+   rnpb[1][1] =  0.9999991109044505944;
+   rnpb[1][2] = -0.4097782710401555759e-4;
+
+   rnpb[2][0] =  0.5791308472168153320e-3;
+   rnpb[2][1] =  0.4020595661593994396e-4;
+   rnpb[2][2] =  0.9999998314954572365;
+
+   theta = iauGst06(2400000.5, 53736.0, 2400000.5, 53736.0, rnpb);
+
+   vvd(theta, 1.754166138018167568, 1e-12, "iauGst06", "", status);
+
+}
+
+static void t_gst06a(int *status)
+/*
+**  - - - - - - - - -
+**   t _ g s t 0 6 a
+**  - - - - - - - - -
+**
+**  Test iauGst06a function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauGst06a, vvd
+**
+**  This revision:  2008 May 26
+*/
+{
+   double theta;
+
+
+   theta = iauGst06a(2400000.5, 53736.0, 2400000.5, 53736.0);
+
+   vvd(theta, 1.754166137675019159, 1e-12, "iauGst06a", "", status);
+
+}
+
+static void t_gst94(int *status)
+/*
+**  - - - - - - - -
+**   t _ g s t 9 4
+**  - - - - - - - -
+**
+**  Test iauGst94 function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauGst94, vvd
+**
+**  This revision:  2008 May 26
+*/
+{
+   double theta;
+
+
+   theta = iauGst94(2400000.5, 53736.0);
+
+   vvd(theta, 1.754166136020645203, 1e-12, "iauGst94", "", status);
+
+}
+
+static void t_h2fk5(int *status)
+/*
+**  - - - - - - - -
+**   t _ h 2 f k 5
+**  - - - - - - - -
+**
+**  Test iauH2fk5 function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauH2fk5, vvd
+**
+**  This revision:  2009 November 6
+*/
+{
+   double rh, dh, drh, ddh, pxh, rvh, r5, d5, dr5, dd5, px5, rv5;
+
+
+   rh  =  1.767794352;
+   dh  = -0.2917512594;
+   drh = -2.76413026e-6;
+   ddh = -5.92994449e-6;
+   pxh =  0.379210;
+   rvh = -7.6;
+
+   iauH2fk5(rh, dh, drh, ddh, pxh, rvh,
+            &r5, &d5, &dr5, &dd5, &px5, &rv5);
+
+   vvd(r5, 1.767794455700065506, 1e-13,
+       "iauH2fk5", "ra", status);
+   vvd(d5, -0.2917513626469638890, 1e-13,
+       "iauH2fk5", "dec", status);
+   vvd(dr5, -0.27597945024511204e-5, 1e-18,
+       "iauH2fk5", "dr5", status);
+   vvd(dd5, -0.59308014093262838e-5, 1e-18,
+       "iauH2fk5", "dd5", status);
+   vvd(px5, 0.37921, 1e-13,
+       "iauH2fk5", "px", status);
+   vvd(rv5, -7.6000001309071126, 1e-10,
+       "iauH2fk5", "rv", status);
+
+}
+
+static void t_hfk5z(int *status)
+/*
+**  - - - - - - - -
+**   t _ h f k 5 z
+**  - - - - - - - -
+**
+**  Test iauHfk5z function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauHfk5z, vvd
+**
+**  This revision:  2008 November 29
+*/
+{
+   double rh, dh, r5, d5, dr5, dd5;
+
+
+
+   rh =  1.767794352;
+   dh = -0.2917512594;
+
+   iauHfk5z(rh, dh, 2400000.5, 54479.0, &r5, &d5, &dr5, &dd5);
+
+   vvd(r5, 1.767794490535581026, 1e-13,
+       "iauHfk5z", "ra", status);
+   vvd(d5, -0.2917513695320114258, 1e-14,
+       "iauHfk5z", "dec", status);
+   vvd(dr5, 0.4335890983539243029e-8, 1e-22,
+       "iauHfk5z", "dr5", status);
+   vvd(dd5, -0.8569648841237745902e-9, 1e-23,
+       "iauHfk5z", "dd5", status);
+
+}
+
+static void t_ir(int *status)
+/*
+**  - - - - -
+**   t _ i r
+**  - - - - -
+**
+**  Test iauIr function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauIr, vvd
+**
+**  This revision:  2008 November 30
+*/
+{
+   double r[3][3];
+
+
+   r[0][0] = 2.0;
+   r[0][1] = 3.0;
+   r[0][2] = 2.0;
+
+   r[1][0] = 3.0;
+   r[1][1] = 2.0;
+   r[1][2] = 3.0;
+
+   r[2][0] = 3.0;
+   r[2][1] = 4.0;
+   r[2][2] = 5.0;
+
+   iauIr(r);
+
+   vvd(r[0][0], 1.0, 0.0, "iauIr", "11", status);
+   vvd(r[0][1], 0.0, 0.0, "iauIr", "12", status);
+   vvd(r[0][2], 0.0, 0.0, "iauIr", "13", status);
+
+   vvd(r[1][0], 0.0, 0.0, "iauIr", "21", status);
+   vvd(r[1][1], 1.0, 0.0, "iauIr", "22", status);
+   vvd(r[1][2], 0.0, 0.0, "iauIr", "23", status);
+
+   vvd(r[2][0], 0.0, 0.0, "iauIr", "31", status);
+   vvd(r[2][1], 0.0, 0.0, "iauIr", "32", status);
+   vvd(r[2][2], 1.0, 0.0, "iauIr", "33", status);
+
+}
+
+static void t_jd2cal(int *status)
+/*
+**  - - - - - - - - -
+**   t _ j d 2 c a l
+**  - - - - - - - - -
+**
+**  Test iauJd2cal function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauJd2cal, viv, vvd
+**
+**  This revision:  2008 November 29
+*/
+{
+   double dj1, dj2, fd;
+   int iy, im, id, j;
+
+
+   dj1 = 2400000.5;
+   dj2 = 50123.9999;
+
+   j = iauJd2cal(dj1, dj2, &iy, &im, &id, &fd);
+
+   viv(iy, 1996, "iauJd2cal", "y", status);
+   viv(im, 2, "iauJd2cal", "m", status);
+   viv(id, 10, "iauJd2cal", "d", status);
+   vvd(fd, 0.9999, 1e-7, "iauJd2cal", "fd", status);
+   viv(j, 0, "iauJd2cal", "j", status);
+
+}
+
+static void t_jdcalf(int *status)
+/*
+**  - - - - - - - - -
+**   t _ j d c a l f
+**  - - - - - - - - -
+**
+**  Test iauJdcalf function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauJdcalf, viv
+**
+**  This revision:  2008 May 26
+*/
+{
+   double dj1, dj2;
+   int iydmf[4], j;
+
+
+   dj1 = 2400000.5;
+   dj2 = 50123.9999;
+
+   j = iauJdcalf(4, dj1, dj2, iydmf);
+
+   viv(iydmf[0], 1996, "iauJdcalf", "y", status);
+   viv(iydmf[1], 2, "iauJdcalf", "m", status);
+   viv(iydmf[2], 10, "iauJdcalf", "d", status);
+   viv(iydmf[3], 9999, "iauJdcalf", "f", status);
+
+   viv(j, 0, "iauJdcalf", "j", status);
+
+}
+
+static void t_num00a(int *status)
+/*
+**  - - - - - - - - -
+**   t _ n u m 0 0 a
+**  - - - - - - - - -
+**
+**  Test iauNum00a function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauNum00a, vvd
+**
+**  This revision:  2008 November 28
+*/
+{
+   double rmatn[3][3];
+
+
+   iauNum00a(2400000.5, 53736.0, rmatn);
+
+   vvd(rmatn[0][0], 0.9999999999536227949, 1e-12,
+       "iauNum00a", "11", status);
+   vvd(rmatn[0][1], 0.8836238544090873336e-5, 1e-12,
+       "iauNum00a", "12", status);
+   vvd(rmatn[0][2], 0.3830835237722400669e-5, 1e-12,
+       "iauNum00a", "13", status);
+
+   vvd(rmatn[1][0], -0.8836082880798569274e-5, 1e-12,
+       "iauNum00a", "21", status);
+   vvd(rmatn[1][1], 0.9999999991354655028, 1e-12,
+       "iauNum00a", "22", status);
+   vvd(rmatn[1][2], -0.4063240865362499850e-4, 1e-12,
+       "iauNum00a", "23", status);
+
+   vvd(rmatn[2][0], -0.3831194272065995866e-5, 1e-12,
+       "iauNum00a", "31", status);
+   vvd(rmatn[2][1], 0.4063237480216291775e-4, 1e-12,
+       "iauNum00a", "32", status);
+   vvd(rmatn[2][2], 0.9999999991671660338, 1e-12,
+       "iauNum00a", "33", status);
+
+}
+
+static void t_num00b(int *status)
+/*
+**  - - - - - - - - -
+**   t _ n u m 0 0 b
+**  - - - - - - - - -
+**
+**  Test iauNum00b function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauNum00b, vvd
+**
+**  This revision:  2008 November 28
+*/
+{
+    double rmatn[3][3];
+
+    iauNum00b(2400000.5, 53736, rmatn);
+
+   vvd(rmatn[0][0], 0.9999999999536069682, 1e-12,
+       "iauNum00b", "11", status);
+   vvd(rmatn[0][1], 0.8837746144871248011e-5, 1e-12,
+       "iauNum00b", "12", status);
+   vvd(rmatn[0][2], 0.3831488838252202945e-5, 1e-12,
+       "iauNum00b", "13", status);
+
+   vvd(rmatn[1][0], -0.8837590456632304720e-5, 1e-12,
+       "iauNum00b", "21", status);
+   vvd(rmatn[1][1], 0.9999999991354692733, 1e-12,
+       "iauNum00b", "22", status);
+   vvd(rmatn[1][2], -0.4063198798559591654e-4, 1e-12,
+       "iauNum00b", "23", status);
+
+   vvd(rmatn[2][0], -0.3831847930134941271e-5, 1e-12,
+       "iauNum00b", "31", status);
+   vvd(rmatn[2][1], 0.4063195412258168380e-4, 1e-12,
+       "iauNum00b", "32", status);
+   vvd(rmatn[2][2], 0.9999999991671806225, 1e-12,
+       "iauNum00b", "33", status);
+
+}
+
+static void t_num06a(int *status)
+/*
+**  - - - - - - - - -
+**   t _ n u m 0 6 a
+**  - - - - - - - - -
+**
+**  Test iauNum06a function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauNum06a, vvd
+**
+**  This revision:  2008 November 28
+*/
+{
+    double rmatn[3][3];
+
+    iauNum06a(2400000.5, 53736, rmatn);
+
+   vvd(rmatn[0][0], 0.9999999999536227668, 1e-12,
+       "iauNum06a", "11", status);
+   vvd(rmatn[0][1], 0.8836241998111535233e-5, 1e-12,
+       "iauNum06a", "12", status);
+   vvd(rmatn[0][2], 0.3830834608415287707e-5, 1e-12,
+       "iauNum06a", "13", status);
+
+   vvd(rmatn[1][0], -0.8836086334870740138e-5, 1e-12,
+       "iauNum06a", "21", status);
+   vvd(rmatn[1][1], 0.9999999991354657474, 1e-12,
+       "iauNum06a", "22", status);
+   vvd(rmatn[1][2], -0.4063240188248455065e-4, 1e-12,
+       "iauNum06a", "23", status);
+
+   vvd(rmatn[2][0], -0.3831193642839398128e-5, 1e-12,
+       "iauNum06a", "31", status);
+   vvd(rmatn[2][1], 0.4063236803101479770e-4, 1e-12,
+       "iauNum06a", "32", status);
+   vvd(rmatn[2][2], 0.9999999991671663114, 1e-12,
+       "iauNum06a", "33", status);
+
+}
+
+static void t_numat(int *status)
+/*
+**  - - - - - - - -
+**   t _ n u m a t
+**  - - - - - - - -
+**
+**  Test iauNumat function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauNumat, vvd
+**
+**  This revision:  2008 November 28
+*/
+{
+   double epsa, dpsi, deps, rmatn[3][3];
+
+
+   epsa =  0.4090789763356509900;
+   dpsi = -0.9630909107115582393e-5;
+   deps =  0.4063239174001678826e-4;
+
+   iauNumat(epsa, dpsi, deps, rmatn);
+
+   vvd(rmatn[0][0], 0.9999999999536227949, 1e-12,
+       "iauNumat", "11", status);
+   vvd(rmatn[0][1], 0.8836239320236250577e-5, 1e-12,
+       "iauNumat", "12", status);
+   vvd(rmatn[0][2], 0.3830833447458251908e-5, 1e-12,
+       "iauNumat", "13", status);
+
+   vvd(rmatn[1][0], -0.8836083657016688588e-5, 1e-12,
+       "iauNumat", "21", status);
+   vvd(rmatn[1][1], 0.9999999991354654959, 1e-12,
+       "iauNumat", "22", status);
+   vvd(rmatn[1][2], -0.4063240865361857698e-4, 1e-12,
+       "iauNumat", "23", status);
+
+   vvd(rmatn[2][0], -0.3831192481833385226e-5, 1e-12,
+       "iauNumat", "31", status);
+   vvd(rmatn[2][1], 0.4063237480216934159e-4, 1e-12,
+       "iauNumat", "32", status);
+   vvd(rmatn[2][2], 0.9999999991671660407, 1e-12,
+       "iauNumat", "33", status);
+
+}
+
+static void t_nut00a(int *status)
+/*
+**  - - - - - - - - -
+**   t _ n u t 0 0 a
+**  - - - - - - - - -
+**
+**  Test iauNut00a function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauNut00a, vvd
+**
+**  This revision:  2008 November 28
+*/
+{
+   double dpsi, deps;
+
+
+   iauNut00a(2400000.5, 53736.0, &dpsi, &deps);
+
+   vvd(dpsi, -0.9630909107115518431e-5, 1e-13,
+       "iauNut00a", "dpsi", status);
+   vvd(deps,  0.4063239174001678710e-4, 1e-13,
+       "iauNut00a", "deps", status);
+
+}
+
+static void t_nut00b(int *status)
+/*
+**  - - - - - - - - -
+**   t _ n u t 0 0 b
+**  - - - - - - - - -
+**
+**  Test iauNut00b function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauNut00b, vvd
+**
+**  This revision:  2008 November 28
+*/
+{
+   double dpsi, deps;
+
+
+   iauNut00b(2400000.5, 53736.0, &dpsi, &deps);
+
+   vvd(dpsi, -0.9632552291148362783e-5, 1e-13,
+       "iauNut00b", "dpsi", status);
+   vvd(deps,  0.4063197106621159367e-4, 1e-13,
+       "iauNut00b", "deps", status);
+
+}
+
+static void t_nut06a(int *status)
+/*
+**  - - - - - - - - -
+**   t _ n u t 0 6 a
+**  - - - - - - - - -
+**
+**  Test iauNut06a function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauNut06a, vvd
+**
+**  This revision:  2008 November 28
+*/
+{
+   double dpsi, deps;
+
+
+   iauNut06a(2400000.5, 53736.0, &dpsi, &deps);
+
+   vvd(dpsi, -0.9630912025820308797e-5, 1e-13,
+       "iauNut06a", "dpsi", status);
+   vvd(deps,  0.4063238496887249798e-4, 1e-13,
+       "iauNut06a", "deps", status);
+
+}
+
+static void t_nut80(int *status)
+/*
+**  - - - - - - - -
+**   t _ n u t 8 0
+**  - - - - - - - -
+**
+**  Test iauNut80 function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauNut80, vvd
+**
+**  This revision:  2008 November 28
+*/
+{
+   double dpsi, deps;
+
+
+   iauNut80(2400000.5, 53736.0, &dpsi, &deps);
+
+   vvd(dpsi, -0.9643658353226563966e-5, 1e-13,
+       "iauNut80", "dpsi", status);
+   vvd(deps,  0.4060051006879713322e-4, 1e-13,
+       "iauNut80", "deps", status);
+
+}
+
+static void t_nutm80(int *status)
+/*
+**  - - - - - - - - -
+**   t _ n u t m 8 0
+**  - - - - - - - - -
+**
+**  Test iauNutm80 function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauNutm80, vvd
+**
+**  This revision:  2008 November 30
+*/
+{
+   double rmatn[3][3];
+
+
+   iauNutm80(2400000.5, 53736.0, rmatn);
+
+   vvd(rmatn[0][0], 0.9999999999534999268, 1e-12,
+      "iauNutm80", "11", status);
+   vvd(rmatn[0][1], 0.8847935789636432161e-5, 1e-12,
+      "iauNutm80", "12", status);
+   vvd(rmatn[0][2], 0.3835906502164019142e-5, 1e-12,
+      "iauNutm80", "13", status);
+
+   vvd(rmatn[1][0], -0.8847780042583435924e-5, 1e-12,
+      "iauNutm80", "21", status);
+   vvd(rmatn[1][1], 0.9999999991366569963, 1e-12,
+      "iauNutm80", "22", status);
+   vvd(rmatn[1][2], -0.4060052702727130809e-4, 1e-12,
+      "iauNutm80", "23", status);
+
+   vvd(rmatn[2][0], -0.3836265729708478796e-5, 1e-12,
+      "iauNutm80", "31", status);
+   vvd(rmatn[2][1], 0.4060049308612638555e-4, 1e-12,
+      "iauNutm80", "32", status);
+   vvd(rmatn[2][2], 0.9999999991684415129, 1e-12,
+      "iauNutm80", "33", status);
+
+}
+
+static void t_obl06(int *status)
+/*
+**  - - - - - - - -
+**   t _ o b l 0 6
+**  - - - - - - - -
+**
+**  Test iauObl06 function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauObl06, vvd
+**
+**  This revision:  2008 November 29
+*/
+{
+   vvd(iauObl06(2400000.5, 54388.0), 0.4090749229387258204, 1e-14,
+       "iauObl06", "", status);
+}
+
+static void t_obl80(int *status)
+/*
+**  - - - - - - - -
+**   t _ o b l 8 0
+**  - - - - - - - -
+**
+**  Test iauObl80 function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauObl80, vvd
+**
+**  This revision:  2008 November 29
+*/
+{
+   double eps0;
+
+
+   eps0 = iauObl80(2400000.5, 54388.0);
+
+   vvd(eps0, 0.4090751347643816218, 1e-14, "iauObl80", "", status);
+
+}
+
+static void t_p06e(int *status)
+/*
+**  - - - - - - -
+**   t _ p 0 6 e
+**  - - - - - - -
+**
+**  Test iauP06e function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauP06e, vvd
+**
+**  This revision:  2008 November 28
+*/
+{
+    double eps0, psia, oma, bpa, bqa, pia, bpia,
+           epsa, chia, za, zetaa, thetaa, pa, gam, phi, psi;
+
+
+   iauP06e(2400000.5, 52541.0, &eps0, &psia, &oma, &bpa,
+           &bqa, &pia, &bpia, &epsa, &chia, &za,
+           &zetaa, &thetaa, &pa, &gam, &phi, &psi);
+
+   vvd(eps0, 0.4090926006005828715, 1e-14,
+       "iauP06e", "eps0", status);
+   vvd(psia, 0.6664369630191613431e-3, 1e-14,
+       "iauP06e", "psia", status);
+   vvd(oma , 0.4090925973783255982, 1e-14,
+       "iauP06e", "oma", status);
+   vvd(bpa, 0.5561149371265209445e-6, 1e-14,
+       "iauP06e", "bpa", status);
+   vvd(bqa, -0.6191517193290621270e-5, 1e-14,
+       "iauP06e", "bqa", status);
+   vvd(pia, 0.6216441751884382923e-5, 1e-14,
+       "iauP06e", "pia", status);
+   vvd(bpia, 3.052014180023779882, 1e-14,
+       "iauP06e", "bpia", status);
+   vvd(epsa, 0.4090864054922431688, 1e-14,
+       "iauP06e", "epsa", status);
+   vvd(chia, 0.1387703379530915364e-5, 1e-14,
+       "iauP06e", "chia", status);
+   vvd(za, 0.2921789846651790546e-3, 1e-14,
+       "iauP06e", "za", status);
+   vvd(zetaa, 0.3178773290332009310e-3, 1e-14,
+       "iauP06e", "zetaa", status);
+   vvd(thetaa, 0.2650932701657497181e-3, 1e-14,
+       "iauP06e", "thetaa", status);
+   vvd(pa, 0.6651637681381016344e-3, 1e-14,
+       "iauP06e", "pa", status);
+   vvd(gam, 0.1398077115963754987e-5, 1e-14,
+       "iauP06e", "gam", status);
+   vvd(phi, 0.4090864090837462602, 1e-14,
+       "iauP06e", "phi", status);
+   vvd(psi, 0.6664464807480920325e-3, 1e-14,
+       "iauP06e", "psi", status);
+
+}
+
+static void t_p2pv(int *status)
+/*
+**  - - - - - - -
+**   t _ p 2 p v
+**  - - - - - - -
+**
+**  Test iauP2pv function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauP2pv, vvd
+**
+**  This revision:  2008 May 26
+*/
+{
+   double p[3], pv[2][3];
+
+
+   p[0] = 0.25;
+   p[1] = 1.2;
+   p[2] = 3.0;
+
+   pv[0][0] =  0.3;
+   pv[0][1] =  1.2;
+   pv[0][2] = -2.5;
+
+   pv[1][0] = -0.5;
+   pv[1][1] =  3.1;
+   pv[1][2] =  0.9;
+
+   iauP2pv(p, pv);
+
+   vvd(pv[0][0], 0.25, 0.0, "iauP2pv", "p1", status);
+   vvd(pv[0][1], 1.2,  0.0, "iauP2pv", "p2", status);
+   vvd(pv[0][2], 3.0,  0.0, "iauP2pv", "p3", status);
+
+   vvd(pv[1][0], 0.0,  0.0, "iauP2pv", "v1", status);
+   vvd(pv[1][1], 0.0,  0.0, "iauP2pv", "v2", status);
+   vvd(pv[1][2], 0.0,  0.0, "iauP2pv", "v3", status);
+
+}
+
+static void t_p2s(int *status)
+/*
+**  - - - - - -
+**   t _ p 2 s
+**  - - - - - -
+**
+**  Test iauP2s function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauP2s, vvd
+**
+**  This revision:  2008 November 29
+*/
+{
+   double p[3], theta, phi, r;
+
+
+   p[0] = 100.0;
+   p[1] = -50.0;
+   p[2] =  25.0;
+
+   iauP2s(p, &theta, &phi, &r);
+
+   vvd(theta, -0.4636476090008061162, 1e-12, "iauP2s", "theta", status);
+   vvd(phi, 0.2199879773954594463, 1e-12, "iauP2s", "phi", status);
+   vvd(r, 114.5643923738960002, 1e-9, "iauP2s", "r", status);
+
+}
+
+static void t_pap(int *status)
+/*
+**  - - - - - -
+**   t _ p a p
+**  - - - - - -
+**
+**  Test iauPap function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauPap, vvd
+**
+**  This revision:  2008 May 25
+*/
+{
+   double a[3], b[3], theta;
+
+
+   a[0] =  1.0;
+   a[1] =  0.1;
+   a[2] =  0.2;
+
+   b[0] = -3.0;
+   b[1] = 1e-3;
+   b[2] =  0.2;
+
+   theta = iauPap(a, b);
+
+   vvd(theta, 0.3671514267841113674, 1e-12, "iauPap", "", status);
+
+}
+
+static void t_pas(int *status)
+/*
+**  - - - - - -
+**   t _ p a s
+**  - - - - - -
+**
+**  Test iauPas function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauPas, vvd
+**
+**  This revision:  2008 May 25
+*/
+{
+   double al, ap, bl, bp, theta;
+
+
+   al =  1.0;
+   ap =  0.1;
+   bl =  0.2;
+   bp = -1.0;
+
+   theta = iauPas(al, ap, bl, bp);
+
+   vvd(theta, -2.724544922932270424, 1e-12, "iauPas", "", status);
+
+}
+
+static void t_pb06(int *status)
+/*
+**  - - - - - - -
+**   t _ p b 0 6
+**  - - - - - - -
+**
+**  Test iauPb06 function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauPb06, vvd
+**
+**  This revision:  2008 November 28
+*/
+{
+   double bzeta, bz, btheta;
+
+
+   iauPb06(2400000.5, 50123.9999, &bzeta, &bz, &btheta);
+
+   vvd(bzeta, -0.5092634016326478238e-3, 1e-12,
+       "iauPb06", "bzeta", status);
+   vvd(bz, -0.3602772060566044413e-3, 1e-12,
+       "iauPb06", "bz", status);
+   vvd(btheta, -0.3779735537167811177e-3, 1e-12,
+       "iauPb06", "btheta", status);
+
+}
+
+static void t_pdp(int *status)
+/*
+**  - - - - - -
+**   t _ p d p
+**  - - - - - -
+**
+**  Test iauPdp function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauPdp, vvd
+**
+**  This revision:  2008 November 30
+*/
+{
+   double a[3], b[3], adb;
+
+
+   a[0] = 2.0;
+   a[1] = 2.0;
+   a[2] = 3.0;
+
+   b[0] = 1.0;
+   b[1] = 3.0;
+   b[2] = 4.0;
+
+   adb = iauPdp(a, b);
+
+   vvd(adb, 20, 1e-12, "iauPdp", "", status);
+
+}
+
+static void t_pfw06(int *status)
+/*
+**  - - - - - - - -
+**   t _ p f w 0 6
+**  - - - - - - - -
+**
+**  Test iauPfw06 function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauPfw06, vvd
+**
+**  This revision:  2008 November 30
+*/
+{
+   double gamb, phib, psib, epsa;
+
+
+   iauPfw06(2400000.5, 50123.9999, &gamb, &phib, &psib, &epsa);
+
+   vvd(gamb, -0.2243387670997995690e-5, 1e-16,
+       "iauPfw06", "gamb", status);
+   vvd(phib,  0.4091014602391312808, 1e-12,
+       "iauPfw06", "phib", status);
+   vvd(psib, -0.9501954178013031895e-3, 1e-14,
+       "iauPfw06", "psib", status);
+   vvd(epsa,  0.4091014316587367491, 1e-12,
+       "iauPfw06", "epsa", status);
+
+}
+
+static void t_plan94(int *status)
+/*
+**  - - - - - - - - -
+**   t _ p l a n 9 4
+**  - - - - - - - - -
+**
+**  Test iauPlan94 function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauPlan94, VVD, VIV
+**
+**  This revision:  2008 November 28
+*/
+{
+   double pv[2][3];
+   int j;
+
+
+   j = iauPlan94(2400000.5, 1e6, 0, pv);
+
+   vvd(pv[0][0], 0.0, 0.0, "iauPlan94", "x 1", status);
+   vvd(pv[0][1], 0.0, 0.0, "iauPlan94", "y 1", status);
+   vvd(pv[0][2], 0.0, 0.0, "iauPlan94", "z 1", status);
+
+   vvd(pv[1][0], 0.0, 0.0, "iauPlan94", "xd 1", status);
+   vvd(pv[1][1], 0.0, 0.0, "iauPlan94", "yd 1", status);
+   vvd(pv[1][2], 0.0, 0.0, "iauPlan94", "zd 1", status);
+
+   viv(j, -1, "iauPlan94", "j 1", status);
+
+   j = iauPlan94(2400000.5, 1e6, 10, pv);
+
+   viv(j, -1, "iauPlan94", "j 2", status);
+
+   j = iauPlan94(2400000.5, -320000, 3, pv);
+
+   vvd(pv[0][0], 0.9308038666832975759, 1e-11,
+       "iauPlan94", "x 3", status);
+   vvd(pv[0][1], 0.3258319040261346000, 1e-11,
+       "iauPlan94", "y 3", status);
+   vvd(pv[0][2], 0.1422794544481140560, 1e-11,
+       "iauPlan94", "z 3", status);
+
+   vvd(pv[1][0], -0.6429458958255170006e-2, 1e-11,
+       "iauPlan94", "xd 3", status);
+   vvd(pv[1][1], 0.1468570657704237764e-1, 1e-11,
+       "iauPlan94", "yd 3", status);
+   vvd(pv[1][2], 0.6406996426270981189e-2, 1e-11,
+       "iauPlan94", "zd 3", status);
+
+   viv(j, 1, "iauPlan94", "j 3", status);
+
+   j = iauPlan94(2400000.5, 43999.9, 1, pv);
+
+   vvd(pv[0][0], 0.2945293959257430832, 1e-11,
+       "iauPlan94", "x 4", status);
+   vvd(pv[0][1], -0.2452204176601049596, 1e-11,
+       "iauPlan94", "y 4", status);
+   vvd(pv[0][2], -0.1615427700571978153, 1e-11,
+       "iauPlan94", "z 4", status);
+
+   vvd(pv[1][0], 0.1413867871404614441e-1, 1e-11,
+       "iauPlan94", "xd 4", status);
+   vvd(pv[1][1], 0.1946548301104706582e-1, 1e-11,
+       "iauPlan94", "yd 4", status);
+   vvd(pv[1][2], 0.8929809783898904786e-2, 1e-11,
+       "iauPlan94", "zd 4", status);
+
+   viv(j, 0, "iauPlan94", "j 4", status);
+
+}
+
+static void t_pmat00(int *status)
+/*
+**  - - - - - - - - -
+**   t _ p m a t 0 0
+**  - - - - - - - - -
+**
+**  Test iauPmat00 function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauPmat00, vvd
+**
+**  This revision:  2008 November 29
+*/
+{
+   double rbp[3][3];
+
+
+   iauPmat00(2400000.5, 50123.9999, rbp);
+
+   vvd(rbp[0][0], 0.9999995505175087260, 1e-12,
+       "iauPmat00", "11", status);
+   vvd(rbp[0][1], 0.8695405883617884705e-3, 1e-14,
+       "iauPmat00", "12", status);
+   vvd(rbp[0][2], 0.3779734722239007105e-3, 1e-14,
+       "iauPmat00", "13", status);
+
+   vvd(rbp[1][0], -0.8695405990410863719e-3, 1e-14,
+       "iauPmat00", "21", status);
+   vvd(rbp[1][1], 0.9999996219494925900, 1e-12,
+       "iauPmat00", "22", status);
+   vvd(rbp[1][2], -0.1360775820404982209e-6, 1e-14,
+       "iauPmat00", "23", status);
+
+   vvd(rbp[2][0], -0.3779734476558184991e-3, 1e-14,
+       "iauPmat00", "31", status);
+   vvd(rbp[2][1], -0.1925857585832024058e-6, 1e-14,
+       "iauPmat00", "32", status);
+   vvd(rbp[2][2], 0.9999999285680153377, 1e-12,
+       "iauPmat00", "33", status);
+
+}
+
+static void t_pmat06(int *status)
+/*
+**  - - - - - - - - -
+**   t _ p m a t 0 6
+**  - - - - - - - - -
+**
+**  Test iauPmat06 function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauPmat06, vvd
+**
+**  This revision:  2008 November 30
+*/
+{
+   double rbp[3][3];
+
+
+   iauPmat06(2400000.5, 50123.9999, rbp);
+
+   vvd(rbp[0][0], 0.9999995505176007047, 1e-12,
+       "iauPmat06", "11", status);
+   vvd(rbp[0][1], 0.8695404617348208406e-3, 1e-14,
+       "iauPmat06", "12", status);
+   vvd(rbp[0][2], 0.3779735201865589104e-3, 1e-14,
+       "iauPmat06", "13", status);
+
+   vvd(rbp[1][0], -0.8695404723772031414e-3, 1e-14,
+       "iauPmat06", "21", status);
+   vvd(rbp[1][1], 0.9999996219496027161, 1e-12,
+       "iauPmat06", "22", status);
+   vvd(rbp[1][2], -0.1361752497080270143e-6, 1e-14,
+       "iauPmat06", "23", status);
+
+   vvd(rbp[2][0], -0.3779734957034089490e-3, 1e-14,
+       "iauPmat06", "31", status);
+   vvd(rbp[2][1], -0.1924880847894457113e-6, 1e-14,
+       "iauPmat06", "32", status);
+   vvd(rbp[2][2], 0.9999999285679971958, 1e-12,
+       "iauPmat06", "33", status);
+
+}
+
+static void t_pmat76(int *status)
+/*
+**  - - - - - - - - -
+**   t _ p m a t 7 6
+**  - - - - - - - - -
+**
+**  Test iauPmat76 function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauPmat76, vvd
+**
+**  This revision:  2008 November 28
+*/
+{
+   double rmatp[3][3];
+
+
+   iauPmat76(2400000.5, 50123.9999, rmatp);
+
+   vvd(rmatp[0][0], 0.9999995504328350733, 1e-12,
+       "iauPmat76", "11", status);
+   vvd(rmatp[0][1], 0.8696632209480960785e-3, 1e-14,
+       "iauPmat76", "12", status);
+   vvd(rmatp[0][2], 0.3779153474959888345e-3, 1e-14,
+       "iauPmat76", "13", status);
+
+   vvd(rmatp[1][0], -0.8696632209485112192e-3, 1e-14,
+       "iauPmat76", "21", status);
+   vvd(rmatp[1][1], 0.9999996218428560614, 1e-12,
+       "iauPmat76", "22", status);
+   vvd(rmatp[1][2], -0.1643284776111886407e-6, 1e-14,
+       "iauPmat76", "23", status);
+
+   vvd(rmatp[2][0], -0.3779153474950335077e-3, 1e-14,
+       "iauPmat76", "31", status);
+   vvd(rmatp[2][1], -0.1643306746147366896e-6, 1e-14,
+       "iauPmat76", "32", status);
+   vvd(rmatp[2][2], 0.9999999285899790119, 1e-12,
+       "iauPmat76", "33", status);
+
+}
+
+static void t_pm(int *status)
+/*
+**  - - - - -
+**   t _ p m
+**  - - - - -
+**
+**  Test iauPm function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauPm, vvd
+**
+**  This revision:  2008 November 30
+*/
+{
+   double p[3], r;
+
+
+   p[0] =  0.3;
+   p[1] =  1.2;
+   p[2] = -2.5;
+
+   r = iauPm(p);
+
+   vvd(r, 2.789265136196270604, 1e-12, "iauPm", "", status);
+
+}
+
+static void t_pmp(int *status)
+/*
+**  - - - - - -
+**   t _ p m p
+**  - - - - - -
+**
+**  Test iauPmp function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauPmp, vvd
+**
+**  This revision:  2008 November 30
+*/
+{
+   double a[3], b[3], amb[3];
+
+
+   a[0] = 2.0;
+   a[1] = 2.0;
+   a[2] = 3.0;
+
+   b[0] = 1.0;
+   b[1] = 3.0;
+   b[2] = 4.0;
+
+   iauPmp(a, b, amb);
+
+   vvd(amb[0],  1.0, 1e-12, "iauPmp", "0", status);
+   vvd(amb[1], -1.0, 1e-12, "iauPmp", "1", status);
+   vvd(amb[2], -1.0, 1e-12, "iauPmp", "2", status);
+
+}
+
+static void t_pn(int *status)
+/*
+**  - - - - -
+**   t _ p n
+**  - - - - -
+**
+**  Test iauPn function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauPn, vvd
+**
+**  This revision:  2008 November 30
+*/
+{
+   double p[3], r, u[3];
+
+
+   p[0] =  0.3;
+   p[1] =  1.2;
+   p[2] = -2.5;
+
+   iauPn(p, &r, u);
+
+   vvd(r, 2.789265136196270604, 1e-12, "iauPn", "r", status);
+
+   vvd(u[0], 0.1075552109073112058, 1e-12, "iauPn", "u1", status);
+   vvd(u[1], 0.4302208436292448232, 1e-12, "iauPn", "u2", status);
+   vvd(u[2], -0.8962934242275933816, 1e-12, "iauPn", "u3", status);
+
+}
+
+static void t_pn00(int *status)
+/*
+**  - - - - - - -
+**   t _ p n 0 0
+**  - - - - - - -
+**
+**  Test iauPn00 function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauPn00, vvd
+**
+**  This revision:  2008 November 28
+*/
+{
+   double dpsi, deps, epsa,
+          rb[3][3], rp[3][3], rbp[3][3], rn[3][3], rbpn[3][3];
+
+
+   dpsi = -0.9632552291149335877e-5;
+   deps =  0.4063197106621141414e-4;
+
+   iauPn00(2400000.5, 53736.0, dpsi, deps,
+           &epsa, rb, rp, rbp, rn, rbpn);
+
+   vvd(epsa, 0.4090791789404229916, 1e-12, "iauPn00", "epsa", status);
+
+   vvd(rb[0][0], 0.9999999999999942498, 1e-12,
+       "iauPn00", "rb11", status);
+   vvd(rb[0][1], -0.7078279744199196626e-7, 1e-18,
+       "iauPn00", "rb12", status);
+   vvd(rb[0][2], 0.8056217146976134152e-7, 1e-18,
+       "iauPn00", "rb13", status);
+
+   vvd(rb[1][0], 0.7078279477857337206e-7, 1e-18,
+       "iauPn00", "rb21", status);
+   vvd(rb[1][1], 0.9999999999999969484, 1e-12,
+       "iauPn00", "rb22", status);
+   vvd(rb[1][2], 0.3306041454222136517e-7, 1e-18,
+       "iauPn00", "rb23", status);
+
+   vvd(rb[2][0], -0.8056217380986972157e-7, 1e-18,
+       "iauPn00", "rb31", status);
+   vvd(rb[2][1], -0.3306040883980552500e-7, 1e-18,
+       "iauPn00", "rb32", status);
+   vvd(rb[2][2], 0.9999999999999962084, 1e-12,
+       "iauPn00", "rb33", status);
+
+   vvd(rp[0][0], 0.9999989300532289018, 1e-12,
+       "iauPn00", "rp11", status);
+   vvd(rp[0][1], -0.1341647226791824349e-2, 1e-14,
+       "iauPn00", "rp12", status);
+   vvd(rp[0][2], -0.5829880927190296547e-3, 1e-14,
+       "iauPn00", "rp13", status);
+
+   vvd(rp[1][0], 0.1341647231069759008e-2, 1e-14,
+       "iauPn00", "rp21", status);
+   vvd(rp[1][1], 0.9999990999908750433, 1e-12,
+       "iauPn00", "rp22", status);
+   vvd(rp[1][2], -0.3837444441583715468e-6, 1e-14,
+       "iauPn00", "rp23", status);
+
+   vvd(rp[2][0], 0.5829880828740957684e-3, 1e-14,
+       "iauPn00", "rp31", status);
+   vvd(rp[2][1], -0.3984203267708834759e-6, 1e-14,
+       "iauPn00", "rp32", status);
+   vvd(rp[2][2], 0.9999998300623538046, 1e-12,
+       "iauPn00", "rp33", status);
+
+   vvd(rbp[0][0], 0.9999989300052243993, 1e-12,
+       "iauPn00", "rbp11", status);
+   vvd(rbp[0][1], -0.1341717990239703727e-2, 1e-14,
+       "iauPn00", "rbp12", status);
+   vvd(rbp[0][2], -0.5829075749891684053e-3, 1e-14,
+       "iauPn00", "rbp13", status);
+
+   vvd(rbp[1][0], 0.1341718013831739992e-2, 1e-14,
+       "iauPn00", "rbp21", status);
+   vvd(rbp[1][1], 0.9999990998959191343, 1e-12,
+       "iauPn00", "rbp22", status);
+   vvd(rbp[1][2], -0.3505759733565421170e-6, 1e-14,
+       "iauPn00", "rbp23", status);
+
+   vvd(rbp[2][0], 0.5829075206857717883e-3, 1e-14,
+       "iauPn00", "rbp31", status);
+   vvd(rbp[2][1], -0.4315219955198608970e-6, 1e-14,
+       "iauPn00", "rbp32", status);
+   vvd(rbp[2][2], 0.9999998301093036269, 1e-12,
+       "iauPn00", "rbp33", status);
+
+   vvd(rn[0][0], 0.9999999999536069682, 1e-12,
+       "iauPn00", "rn11", status);
+   vvd(rn[0][1], 0.8837746144872140812e-5, 1e-16,
+       "iauPn00", "rn12", status);
+   vvd(rn[0][2], 0.3831488838252590008e-5, 1e-16,
+       "iauPn00", "rn13", status);
+
+   vvd(rn[1][0], -0.8837590456633197506e-5, 1e-16,
+       "iauPn00", "rn21", status);
+   vvd(rn[1][1], 0.9999999991354692733, 1e-12,
+       "iauPn00", "rn22", status);
+   vvd(rn[1][2], -0.4063198798559573702e-4, 1e-16,
+       "iauPn00", "rn23", status);
+
+   vvd(rn[2][0], -0.3831847930135328368e-5, 1e-16,
+       "iauPn00", "rn31", status);
+   vvd(rn[2][1], 0.4063195412258150427e-4, 1e-16,
+       "iauPn00", "rn32", status);
+   vvd(rn[2][2], 0.9999999991671806225, 1e-12,
+       "iauPn00", "rn33", status);
+
+   vvd(rbpn[0][0], 0.9999989440499982806, 1e-12,
+       "iauPn00", "rbpn11", status);
+   vvd(rbpn[0][1], -0.1332880253640848301e-2, 1e-14,
+       "iauPn00", "rbpn12", status);
+   vvd(rbpn[0][2], -0.5790760898731087295e-3, 1e-14,
+       "iauPn00", "rbpn13", status);
+
+   vvd(rbpn[1][0], 0.1332856746979948745e-2, 1e-14,
+       "iauPn00", "rbpn21", status);
+   vvd(rbpn[1][1], 0.9999991109064768883, 1e-12,
+       "iauPn00", "rbpn22", status);
+   vvd(rbpn[1][2], -0.4097740555723063806e-4, 1e-14,
+       "iauPn00", "rbpn23", status);
+
+   vvd(rbpn[2][0], 0.5791301929950205000e-3, 1e-14,
+       "iauPn00", "rbpn31", status);
+   vvd(rbpn[2][1], 0.4020553681373702931e-4, 1e-14,
+       "iauPn00", "rbpn32", status);
+   vvd(rbpn[2][2], 0.9999998314958529887, 1e-12,
+       "iauPn00", "rbpn33", status);
+
+}
+
+static void t_pn00a(int *status)
+/*
+**  - - - - - - - -
+**   t _ p n 0 0 a
+**  - - - - - - - -
+**
+**  Test iauPn00a function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauPn00a, vvd
+**
+**  This revision:  2008 November 28
+*/
+{
+   double dpsi, deps, epsa,
+          rb[3][3], rp[3][3], rbp[3][3], rn[3][3], rbpn[3][3];
+
+
+   iauPn00a(2400000.5, 53736.0,
+            &dpsi, &deps, &epsa, rb, rp, rbp, rn, rbpn);
+
+   vvd(dpsi, -0.9630909107115518431e-5, 1e-12,
+       "iauPn00a", "dpsi", status);
+   vvd(deps,  0.4063239174001678710e-4, 1e-12,
+       "iauPn00a", "deps", status);
+   vvd(epsa,  0.4090791789404229916, 1e-12, "iauPn00a", "epsa", status);
+
+   vvd(rb[0][0], 0.9999999999999942498, 1e-12,
+       "iauPn00a", "rb11", status);
+   vvd(rb[0][1], -0.7078279744199196626e-7, 1e-16,
+       "iauPn00a", "rb12", status);
+   vvd(rb[0][2], 0.8056217146976134152e-7, 1e-16,
+       "iauPn00a", "rb13", status);
+
+   vvd(rb[1][0], 0.7078279477857337206e-7, 1e-16,
+       "iauPn00a", "rb21", status);
+   vvd(rb[1][1], 0.9999999999999969484, 1e-12,
+       "iauPn00a", "rb22", status);
+   vvd(rb[1][2], 0.3306041454222136517e-7, 1e-16,
+       "iauPn00a", "rb23", status);
+
+   vvd(rb[2][0], -0.8056217380986972157e-7, 1e-16,
+       "iauPn00a", "rb31", status);
+   vvd(rb[2][1], -0.3306040883980552500e-7, 1e-16,
+       "iauPn00a", "rb32", status);
+   vvd(rb[2][2], 0.9999999999999962084, 1e-12,
+       "iauPn00a", "rb33", status);
+
+   vvd(rp[0][0], 0.9999989300532289018, 1e-12,
+       "iauPn00a", "rp11", status);
+   vvd(rp[0][1], -0.1341647226791824349e-2, 1e-14,
+       "iauPn00a", "rp12", status);
+   vvd(rp[0][2], -0.5829880927190296547e-3, 1e-14,
+       "iauPn00a", "rp13", status);
+
+   vvd(rp[1][0], 0.1341647231069759008e-2, 1e-14,
+       "iauPn00a", "rp21", status);
+   vvd(rp[1][1], 0.9999990999908750433, 1e-12,
+       "iauPn00a", "rp22", status);
+   vvd(rp[1][2], -0.3837444441583715468e-6, 1e-14,
+       "iauPn00a", "rp23", status);
+
+   vvd(rp[2][0], 0.5829880828740957684e-3, 1e-14,
+       "iauPn00a", "rp31", status);
+   vvd(rp[2][1], -0.3984203267708834759e-6, 1e-14,
+       "iauPn00a", "rp32", status);
+   vvd(rp[2][2], 0.9999998300623538046, 1e-12,
+       "iauPn00a", "rp33", status);
+
+   vvd(rbp[0][0], 0.9999989300052243993, 1e-12,
+       "iauPn00a", "rbp11", status);
+   vvd(rbp[0][1], -0.1341717990239703727e-2, 1e-14,
+       "iauPn00a", "rbp12", status);
+   vvd(rbp[0][2], -0.5829075749891684053e-3, 1e-14,
+       "iauPn00a", "rbp13", status);
+
+   vvd(rbp[1][0], 0.1341718013831739992e-2, 1e-14,
+       "iauPn00a", "rbp21", status);
+   vvd(rbp[1][1], 0.9999990998959191343, 1e-12,
+       "iauPn00a", "rbp22", status);
+   vvd(rbp[1][2], -0.3505759733565421170e-6, 1e-14,
+       "iauPn00a", "rbp23", status);
+
+   vvd(rbp[2][0], 0.5829075206857717883e-3, 1e-14,
+       "iauPn00a", "rbp31", status);
+   vvd(rbp[2][1], -0.4315219955198608970e-6, 1e-14,
+       "iauPn00a", "rbp32", status);
+   vvd(rbp[2][2], 0.9999998301093036269, 1e-12,
+       "iauPn00a", "rbp33", status);
+
+   vvd(rn[0][0], 0.9999999999536227949, 1e-12,
+       "iauPn00a", "rn11", status);
+   vvd(rn[0][1], 0.8836238544090873336e-5, 1e-14,
+       "iauPn00a", "rn12", status);
+   vvd(rn[0][2], 0.3830835237722400669e-5, 1e-14,
+       "iauPn00a", "rn13", status);
+
+   vvd(rn[1][0], -0.8836082880798569274e-5, 1e-14,
+       "iauPn00a", "rn21", status);
+   vvd(rn[1][1], 0.9999999991354655028, 1e-12,
+       "iauPn00a", "rn22", status);
+   vvd(rn[1][2], -0.4063240865362499850e-4, 1e-14,
+       "iauPn00a", "rn23", status);
+
+   vvd(rn[2][0], -0.3831194272065995866e-5, 1e-14,
+       "iauPn00a", "rn31", status);
+   vvd(rn[2][1], 0.4063237480216291775e-4, 1e-14,
+       "iauPn00a", "rn32", status);
+   vvd(rn[2][2], 0.9999999991671660338, 1e-12,
+       "iauPn00a", "rn33", status);
+
+   vvd(rbpn[0][0], 0.9999989440476103435, 1e-12,
+       "iauPn00a", "rbpn11", status);
+   vvd(rbpn[0][1], -0.1332881761240011763e-2, 1e-14,
+       "iauPn00a", "rbpn12", status);
+   vvd(rbpn[0][2], -0.5790767434730085751e-3, 1e-14,
+       "iauPn00a", "rbpn13", status);
+
+   vvd(rbpn[1][0], 0.1332858254308954658e-2, 1e-14,
+       "iauPn00a", "rbpn21", status);
+   vvd(rbpn[1][1], 0.9999991109044505577, 1e-12,
+       "iauPn00a", "rbpn22", status);
+   vvd(rbpn[1][2], -0.4097782710396580452e-4, 1e-14,
+       "iauPn00a", "rbpn23", status);
+
+   vvd(rbpn[2][0], 0.5791308472168152904e-3, 1e-14,
+       "iauPn00a", "rbpn31", status);
+   vvd(rbpn[2][1], 0.4020595661591500259e-4, 1e-14,
+       "iauPn00a", "rbpn32", status);
+   vvd(rbpn[2][2], 0.9999998314954572304, 1e-12,
+       "iauPn00a", "rbpn33", status);
+
+}
+
+static void t_pn00b(int *status)
+/*
+**  - - - - - - - -
+**   t _ p n 0 0 b
+**  - - - - - - - -
+**
+**  Test iauPn00b function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauPn00b, vvd
+**
+**  This revision:  2008 November 28
+*/
+{
+   double dpsi, deps, epsa,
+          rb[3][3], rp[3][3], rbp[3][3], rn[3][3], rbpn[3][3];
+
+
+   iauPn00b(2400000.5, 53736.0, &dpsi, &deps, &epsa,
+            rb, rp, rbp, rn, rbpn);
+
+   vvd(dpsi, -0.9632552291148362783e-5, 1e-12,
+       "iauPn00b", "dpsi", status);
+   vvd(deps,  0.4063197106621159367e-4, 1e-12,
+       "iauPn00b", "deps", status);
+   vvd(epsa,  0.4090791789404229916, 1e-12, "iauPn00b", "epsa", status);
+
+   vvd(rb[0][0], 0.9999999999999942498, 1e-12,
+      "iauPn00b", "rb11", status);
+   vvd(rb[0][1], -0.7078279744199196626e-7, 1e-16,
+      "iauPn00b", "rb12", status);
+   vvd(rb[0][2], 0.8056217146976134152e-7, 1e-16,
+      "iauPn00b", "rb13", status);
+
+   vvd(rb[1][0], 0.7078279477857337206e-7, 1e-16,
+      "iauPn00b", "rb21", status);
+   vvd(rb[1][1], 0.9999999999999969484, 1e-12,
+      "iauPn00b", "rb22", status);
+   vvd(rb[1][2], 0.3306041454222136517e-7, 1e-16,
+      "iauPn00b", "rb23", status);
+
+   vvd(rb[2][0], -0.8056217380986972157e-7, 1e-16,
+      "iauPn00b", "rb31", status);
+   vvd(rb[2][1], -0.3306040883980552500e-7, 1e-16,
+      "iauPn00b", "rb32", status);
+   vvd(rb[2][2], 0.9999999999999962084, 1e-12,
+      "iauPn00b", "rb33", status);
+
+   vvd(rp[0][0], 0.9999989300532289018, 1e-12,
+      "iauPn00b", "rp11", status);
+   vvd(rp[0][1], -0.1341647226791824349e-2, 1e-14,
+      "iauPn00b", "rp12", status);
+   vvd(rp[0][2], -0.5829880927190296547e-3, 1e-14,
+      "iauPn00b", "rp13", status);
+
+   vvd(rp[1][0], 0.1341647231069759008e-2, 1e-14,
+      "iauPn00b", "rp21", status);
+   vvd(rp[1][1], 0.9999990999908750433, 1e-12,
+      "iauPn00b", "rp22", status);
+   vvd(rp[1][2], -0.3837444441583715468e-6, 1e-14,
+      "iauPn00b", "rp23", status);
+
+   vvd(rp[2][0], 0.5829880828740957684e-3, 1e-14,
+      "iauPn00b", "rp31", status);
+   vvd(rp[2][1], -0.3984203267708834759e-6, 1e-14,
+      "iauPn00b", "rp32", status);
+   vvd(rp[2][2], 0.9999998300623538046, 1e-12,
+      "iauPn00b", "rp33", status);
+
+   vvd(rbp[0][0], 0.9999989300052243993, 1e-12,
+      "iauPn00b", "rbp11", status);
+   vvd(rbp[0][1], -0.1341717990239703727e-2, 1e-14,
+      "iauPn00b", "rbp12", status);
+   vvd(rbp[0][2], -0.5829075749891684053e-3, 1e-14,
+      "iauPn00b", "rbp13", status);
+
+   vvd(rbp[1][0], 0.1341718013831739992e-2, 1e-14,
+      "iauPn00b", "rbp21", status);
+   vvd(rbp[1][1], 0.9999990998959191343, 1e-12,
+      "iauPn00b", "rbp22", status);
+   vvd(rbp[1][2], -0.3505759733565421170e-6, 1e-14,
+      "iauPn00b", "rbp23", status);
+
+   vvd(rbp[2][0], 0.5829075206857717883e-3, 1e-14,
+      "iauPn00b", "rbp31", status);
+   vvd(rbp[2][1], -0.4315219955198608970e-6, 1e-14,
+      "iauPn00b", "rbp32", status);
+   vvd(rbp[2][2], 0.9999998301093036269, 1e-12,
+      "iauPn00b", "rbp33", status);
+
+   vvd(rn[0][0], 0.9999999999536069682, 1e-12,
+      "iauPn00b", "rn11", status);
+   vvd(rn[0][1], 0.8837746144871248011e-5, 1e-14,
+      "iauPn00b", "rn12", status);
+   vvd(rn[0][2], 0.3831488838252202945e-5, 1e-14,
+      "iauPn00b", "rn13", status);
+
+   vvd(rn[1][0], -0.8837590456632304720e-5, 1e-14,
+      "iauPn00b", "rn21", status);
+   vvd(rn[1][1], 0.9999999991354692733, 1e-12,
+      "iauPn00b", "rn22", status);
+   vvd(rn[1][2], -0.4063198798559591654e-4, 1e-14,
+      "iauPn00b", "rn23", status);
+
+   vvd(rn[2][0], -0.3831847930134941271e-5, 1e-14,
+      "iauPn00b", "rn31", status);
+   vvd(rn[2][1], 0.4063195412258168380e-4, 1e-14,
+      "iauPn00b", "rn32", status);
+   vvd(rn[2][2], 0.9999999991671806225, 1e-12,
+      "iauPn00b", "rn33", status);
+
+   vvd(rbpn[0][0], 0.9999989440499982806, 1e-12,
+      "iauPn00b", "rbpn11", status);
+   vvd(rbpn[0][1], -0.1332880253640849194e-2, 1e-14,
+      "iauPn00b", "rbpn12", status);
+   vvd(rbpn[0][2], -0.5790760898731091166e-3, 1e-14,
+      "iauPn00b", "rbpn13", status);
+
+   vvd(rbpn[1][0], 0.1332856746979949638e-2, 1e-14,
+      "iauPn00b", "rbpn21", status);
+   vvd(rbpn[1][1], 0.9999991109064768883, 1e-12,
+      "iauPn00b", "rbpn22", status);
+   vvd(rbpn[1][2], -0.4097740555723081811e-4, 1e-14,
+      "iauPn00b", "rbpn23", status);
+
+   vvd(rbpn[2][0], 0.5791301929950208873e-3, 1e-14,
+      "iauPn00b", "rbpn31", status);
+   vvd(rbpn[2][1], 0.4020553681373720832e-4, 1e-14,
+      "iauPn00b", "rbpn32", status);
+   vvd(rbpn[2][2], 0.9999998314958529887, 1e-12,
+      "iauPn00b", "rbpn33", status);
+
+}
+
+static void t_pn06a(int *status)
+/*
+**  - - - - - - - -
+**   t _ p n 0 6 a
+**  - - - - - - - -
+**
+**  Test iauPn06a function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauPn06a, vvd
+**
+**  This revision:  2008 November 28
+*/
+{
+   double dpsi, deps, epsa;
+   double rb[3][3], rp[3][3], rbp[3][3], rn[3][3], rbpn[3][3];
+
+
+   iauPn06a(2400000.5, 53736.0, &dpsi, &deps, &epsa,
+            rb, rp, rbp, rn, rbpn);
+
+   vvd(dpsi, -0.9630912025820308797e-5, 1e-12,
+       "iauPn06a", "dpsi", status);
+   vvd(deps,  0.4063238496887249798e-4, 1e-12,
+       "iauPn06a", "deps", status);
+   vvd(epsa,  0.4090789763356509926, 1e-12, "iauPn06a", "epsa", status);
+
+   vvd(rb[0][0], 0.9999999999999942497, 1e-12,
+       "iauPn06a", "rb11", status);
+   vvd(rb[0][1], -0.7078368960971557145e-7, 1e-14,
+       "iauPn06a", "rb12", status);
+   vvd(rb[0][2], 0.8056213977613185606e-7, 1e-14,
+       "iauPn06a", "rb13", status);
+
+   vvd(rb[1][0], 0.7078368694637674333e-7, 1e-14,
+       "iauPn06a", "rb21", status);
+   vvd(rb[1][1], 0.9999999999999969484, 1e-12,
+       "iauPn06a", "rb22", status);
+   vvd(rb[1][2], 0.3305943742989134124e-7, 1e-14,
+       "iauPn06a", "rb23", status);
+
+   vvd(rb[2][0], -0.8056214211620056792e-7, 1e-14,
+       "iauPn06a", "rb31", status);
+   vvd(rb[2][1], -0.3305943172740586950e-7, 1e-14,
+       "iauPn06a", "rb32", status);
+   vvd(rb[2][2], 0.9999999999999962084, 1e-12,
+       "iauPn06a", "rb33", status);
+
+   vvd(rp[0][0], 0.9999989300536854831, 1e-12,
+       "iauPn06a", "rp11", status);
+   vvd(rp[0][1], -0.1341646886204443795e-2, 1e-14,
+       "iauPn06a", "rp12", status);
+   vvd(rp[0][2], -0.5829880933488627759e-3, 1e-14,
+       "iauPn06a", "rp13", status);
+
+   vvd(rp[1][0], 0.1341646890569782183e-2, 1e-14,
+       "iauPn06a", "rp21", status);
+   vvd(rp[1][1], 0.9999990999913319321, 1e-12,
+       "iauPn06a", "rp22", status);
+   vvd(rp[1][2], -0.3835944216374477457e-6, 1e-14,
+       "iauPn06a", "rp23", status);
+
+   vvd(rp[2][0], 0.5829880833027867368e-3, 1e-14,
+       "iauPn06a", "rp31", status);
+   vvd(rp[2][1], -0.3985701514686976112e-6, 1e-14,
+       "iauPn06a", "rp32", status);
+   vvd(rp[2][2], 0.9999998300623534950, 1e-12,
+       "iauPn06a", "rp33", status);
+
+   vvd(rbp[0][0], 0.9999989300056797893, 1e-12,
+       "iauPn06a", "rbp11", status);
+   vvd(rbp[0][1], -0.1341717650545059598e-2, 1e-14,
+       "iauPn06a", "rbp12", status);
+   vvd(rbp[0][2], -0.5829075756493728856e-3, 1e-14,
+       "iauPn06a", "rbp13", status);
+
+   vvd(rbp[1][0], 0.1341717674223918101e-2, 1e-14,
+       "iauPn06a", "rbp21", status);
+   vvd(rbp[1][1], 0.9999990998963748448, 1e-12,
+       "iauPn06a", "rbp22", status);
+   vvd(rbp[1][2], -0.3504269280170069029e-6, 1e-14,
+       "iauPn06a", "rbp23", status);
+
+   vvd(rbp[2][0], 0.5829075211461454599e-3, 1e-14,
+       "iauPn06a", "rbp31", status);
+   vvd(rbp[2][1], -0.4316708436255949093e-6, 1e-14,
+       "iauPn06a", "rbp32", status);
+   vvd(rbp[2][2], 0.9999998301093032943, 1e-12,
+       "iauPn06a", "rbp33", status);
+
+   vvd(rn[0][0], 0.9999999999536227668, 1e-12,
+       "iauPn06a", "rn11", status);
+   vvd(rn[0][1], 0.8836241998111535233e-5, 1e-14,
+       "iauPn06a", "rn12", status);
+   vvd(rn[0][2], 0.3830834608415287707e-5, 1e-14,
+       "iauPn06a", "rn13", status);
+
+   vvd(rn[1][0], -0.8836086334870740138e-5, 1e-14,
+       "iauPn06a", "rn21", status);
+   vvd(rn[1][1], 0.9999999991354657474, 1e-12,
+       "iauPn06a", "rn22", status);
+   vvd(rn[1][2], -0.4063240188248455065e-4, 1e-14,
+       "iauPn06a", "rn23", status);
+
+   vvd(rn[2][0], -0.3831193642839398128e-5, 1e-14,
+       "iauPn06a", "rn31", status);
+   vvd(rn[2][1], 0.4063236803101479770e-4, 1e-14,
+       "iauPn06a", "rn32", status);
+   vvd(rn[2][2], 0.9999999991671663114, 1e-12,
+       "iauPn06a", "rn33", status);
+
+   vvd(rbpn[0][0], 0.9999989440480669738, 1e-12,
+       "iauPn06a", "rbpn11", status);
+   vvd(rbpn[0][1], -0.1332881418091915973e-2, 1e-14,
+       "iauPn06a", "rbpn12", status);
+   vvd(rbpn[0][2], -0.5790767447612042565e-3, 1e-14,
+       "iauPn06a", "rbpn13", status);
+
+   vvd(rbpn[1][0], 0.1332857911250989133e-2, 1e-14,
+       "iauPn06a", "rbpn21", status);
+   vvd(rbpn[1][1], 0.9999991109049141908, 1e-12,
+       "iauPn06a", "rbpn22", status);
+   vvd(rbpn[1][2], -0.4097767128546784878e-4, 1e-14,
+       "iauPn06a", "rbpn23", status);
+
+   vvd(rbpn[2][0], 0.5791308482835292617e-3, 1e-14,
+       "iauPn06a", "rbpn31", status);
+   vvd(rbpn[2][1], 0.4020580099454020310e-4, 1e-14,
+       "iauPn06a", "rbpn32", status);
+   vvd(rbpn[2][2], 0.9999998314954628695, 1e-12,
+       "iauPn06a", "rbpn33", status);
+
+}
+
+static void t_pn06(int *status)
+/*
+**  - - - - - - -
+**   t _ p n 0 6
+**  - - - - - - -
+**
+**  Test iauPn06 function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauPn06, vvd
+**
+**  This revision:  2008 November 28
+*/
+{
+   double dpsi, deps, epsa,
+          rb[3][3], rp[3][3], rbp[3][3], rn[3][3], rbpn[3][3];
+
+
+   dpsi = -0.9632552291149335877e-5;
+   deps =  0.4063197106621141414e-4;
+
+   iauPn06(2400000.5, 53736.0, dpsi, deps,
+           &epsa, rb, rp, rbp, rn, rbpn);
+
+   vvd(epsa, 0.4090789763356509926, 1e-12, "iauPn06", "epsa", status);
+
+   vvd(rb[0][0], 0.9999999999999942497, 1e-12,
+       "iauPn06", "rb11", status);
+   vvd(rb[0][1], -0.7078368960971557145e-7, 1e-14,
+       "iauPn06", "rb12", status);
+   vvd(rb[0][2], 0.8056213977613185606e-7, 1e-14,
+       "iauPn06", "rb13", status);
+
+   vvd(rb[1][0], 0.7078368694637674333e-7, 1e-14,
+       "iauPn06", "rb21", status);
+   vvd(rb[1][1], 0.9999999999999969484, 1e-12,
+       "iauPn06", "rb22", status);
+   vvd(rb[1][2], 0.3305943742989134124e-7, 1e-14,
+       "iauPn06", "rb23", status);
+
+   vvd(rb[2][0], -0.8056214211620056792e-7, 1e-14,
+       "iauPn06", "rb31", status);
+   vvd(rb[2][1], -0.3305943172740586950e-7, 1e-14,
+       "iauPn06", "rb32", status);
+   vvd(rb[2][2], 0.9999999999999962084, 1e-12,
+       "iauPn06", "rb33", status);
+
+   vvd(rp[0][0], 0.9999989300536854831, 1e-12,
+       "iauPn06", "rp11", status);
+   vvd(rp[0][1], -0.1341646886204443795e-2, 1e-14,
+       "iauPn06", "rp12", status);
+   vvd(rp[0][2], -0.5829880933488627759e-3, 1e-14,
+       "iauPn06", "rp13", status);
+
+   vvd(rp[1][0], 0.1341646890569782183e-2, 1e-14,
+       "iauPn06", "rp21", status);
+   vvd(rp[1][1], 0.9999990999913319321, 1e-12,
+       "iauPn06", "rp22", status);
+   vvd(rp[1][2], -0.3835944216374477457e-6, 1e-14,
+       "iauPn06", "rp23", status);
+
+   vvd(rp[2][0], 0.5829880833027867368e-3, 1e-14,
+       "iauPn06", "rp31", status);
+   vvd(rp[2][1], -0.3985701514686976112e-6, 1e-14,
+       "iauPn06", "rp32", status);
+   vvd(rp[2][2], 0.9999998300623534950, 1e-12,
+       "iauPn06", "rp33", status);
+
+   vvd(rbp[0][0], 0.9999989300056797893, 1e-12,
+       "iauPn06", "rbp11", status);
+   vvd(rbp[0][1], -0.1341717650545059598e-2, 1e-14,
+       "iauPn06", "rbp12", status);
+   vvd(rbp[0][2], -0.5829075756493728856e-3, 1e-14,
+       "iauPn06", "rbp13", status);
+
+   vvd(rbp[1][0], 0.1341717674223918101e-2, 1e-14,
+       "iauPn06", "rbp21", status);
+   vvd(rbp[1][1], 0.9999990998963748448, 1e-12,
+       "iauPn06", "rbp22", status);
+   vvd(rbp[1][2], -0.3504269280170069029e-6, 1e-14,
+       "iauPn06", "rbp23", status);
+
+   vvd(rbp[2][0], 0.5829075211461454599e-3, 1e-14,
+       "iauPn06", "rbp31", status);
+   vvd(rbp[2][1], -0.4316708436255949093e-6, 1e-14,
+       "iauPn06", "rbp32", status);
+   vvd(rbp[2][2], 0.9999998301093032943, 1e-12,
+       "iauPn06", "rbp33", status);
+
+   vvd(rn[0][0], 0.9999999999536069682, 1e-12,
+       "iauPn06", "rn11", status);
+   vvd(rn[0][1], 0.8837746921149881914e-5, 1e-14,
+       "iauPn06", "rn12", status);
+   vvd(rn[0][2], 0.3831487047682968703e-5, 1e-14,
+       "iauPn06", "rn13", status);
+
+   vvd(rn[1][0], -0.8837591232983692340e-5, 1e-14,
+       "iauPn06", "rn21", status);
+   vvd(rn[1][1], 0.9999999991354692664, 1e-12,
+       "iauPn06", "rn22", status);
+   vvd(rn[1][2], -0.4063198798558931215e-4, 1e-14,
+       "iauPn06", "rn23", status);
+
+   vvd(rn[2][0], -0.3831846139597250235e-5, 1e-14,
+       "iauPn06", "rn31", status);
+   vvd(rn[2][1], 0.4063195412258792914e-4, 1e-14,
+       "iauPn06", "rn32", status);
+   vvd(rn[2][2], 0.9999999991671806293, 1e-12,
+       "iauPn06", "rn33", status);
+
+   vvd(rbpn[0][0], 0.9999989440504506688, 1e-12,
+       "iauPn06", "rbpn11", status);
+   vvd(rbpn[0][1], -0.1332879913170492655e-2, 1e-14,
+       "iauPn06", "rbpn12", status);
+   vvd(rbpn[0][2], -0.5790760923225655753e-3, 1e-14,
+       "iauPn06", "rbpn13", status);
+
+   vvd(rbpn[1][0], 0.1332856406595754748e-2, 1e-14,
+       "iauPn06", "rbpn21", status);
+   vvd(rbpn[1][1], 0.9999991109069366795, 1e-12,
+       "iauPn06", "rbpn22", status);
+   vvd(rbpn[1][2], -0.4097725651142641812e-4, 1e-14,
+       "iauPn06", "rbpn23", status);
+
+   vvd(rbpn[2][0], 0.5791301952321296716e-3, 1e-14,
+       "iauPn06", "rbpn31", status);
+   vvd(rbpn[2][1], 0.4020538796195230577e-4, 1e-14,
+       "iauPn06", "rbpn32", status);
+   vvd(rbpn[2][2], 0.9999998314958576778, 1e-12,
+       "iauPn06", "rbpn33", status);
+
+}
+
+static void t_pnm00a(int *status)
+/*
+**  - - - - - - - - -
+**   t _ p n m 0 0 a
+**  - - - - - - - - -
+**
+**  Test iauPnm00a function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauPnm00a, vvd
+**
+**  This revision:  2008 November 28
+*/
+{
+   double rbpn[3][3];
+
+
+   iauPnm00a(2400000.5, 50123.9999, rbpn);
+
+   vvd(rbpn[0][0], 0.9999995832793134257, 1e-12,
+       "iauPnm00a", "11", status);
+   vvd(rbpn[0][1], 0.8372384254137809439e-3, 1e-14,
+       "iauPnm00a", "12", status);
+   vvd(rbpn[0][2], 0.3639684306407150645e-3, 1e-14,
+       "iauPnm00a", "13", status);
+
+   vvd(rbpn[1][0], -0.8372535226570394543e-3, 1e-14,
+       "iauPnm00a", "21", status);
+   vvd(rbpn[1][1], 0.9999996486491582471, 1e-12,
+       "iauPnm00a", "22", status);
+   vvd(rbpn[1][2], 0.4132915262664072381e-4, 1e-14,
+       "iauPnm00a", "23", status);
+
+   vvd(rbpn[2][0], -0.3639337004054317729e-3, 1e-14,
+       "iauPnm00a", "31", status);
+   vvd(rbpn[2][1], -0.4163386925461775873e-4, 1e-14,
+       "iauPnm00a", "32", status);
+   vvd(rbpn[2][2], 0.9999999329094390695, 1e-12,
+       "iauPnm00a", "33", status);
+
+}
+
+static void t_pnm00b(int *status)
+/*
+**  - - - - - - - - -
+**   t _ p n m 0 0 b
+**  - - - - - - - - -
+**
+**  Test iauPnm00b function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauPnm00b, vvd
+**
+**  This revision:  2008 November 28
+*/
+{
+   double rbpn[3][3];
+
+
+   iauPnm00b(2400000.5, 50123.9999, rbpn);
+
+   vvd(rbpn[0][0], 0.9999995832776208280, 1e-12,
+       "iauPnm00b", "11", status);
+   vvd(rbpn[0][1], 0.8372401264429654837e-3, 1e-14,
+       "iauPnm00b", "12", status);
+   vvd(rbpn[0][2], 0.3639691681450271771e-3, 1e-14,
+       "iauPnm00b", "13", status);
+
+   vvd(rbpn[1][0], -0.8372552234147137424e-3, 1e-14,
+       "iauPnm00b", "21", status);
+   vvd(rbpn[1][1], 0.9999996486477686123, 1e-12,
+       "iauPnm00b", "22", status);
+   vvd(rbpn[1][2], 0.4132832190946052890e-4, 1e-14,
+       "iauPnm00b", "23", status);
+
+   vvd(rbpn[2][0], -0.3639344385341866407e-3, 1e-14,
+       "iauPnm00b", "31", status);
+   vvd(rbpn[2][1], -0.4163303977421522785e-4, 1e-14,
+       "iauPnm00b", "32", status);
+   vvd(rbpn[2][2], 0.9999999329092049734, 1e-12,
+       "iauPnm00b", "33", status);
+
+}
+
+static void t_pnm06a(int *status)
+/*
+**  - - - - - - - - -
+**   t _ p n m 0 6 a
+**  - - - - - - - - -
+**
+**  Test iauPnm06a function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauPnm06a, vvd
+**
+**  This revision:  2008 November 28
+*/
+{
+   double rbpn[3][3];
+
+
+   iauPnm06a(2400000.5, 50123.9999, rbpn);
+
+   vvd(rbpn[0][0], 0.9999995832794205484, 1e-12,
+       "iauPnm06a", "11", status);
+   vvd(rbpn[0][1], 0.8372382772630962111e-3, 1e-14,
+       "iauPnm06a", "12", status);
+   vvd(rbpn[0][2], 0.3639684771140623099e-3, 1e-14,
+       "iauPnm06a", "13", status);
+
+   vvd(rbpn[1][0], -0.8372533744743683605e-3, 1e-14,
+       "iauPnm06a", "21", status);
+   vvd(rbpn[1][1], 0.9999996486492861646, 1e-12,
+       "iauPnm06a", "22", status);
+   vvd(rbpn[1][2], 0.4132905944611019498e-4, 1e-14,
+       "iauPnm06a", "23", status);
+
+   vvd(rbpn[2][0], -0.3639337469629464969e-3, 1e-14,
+       "iauPnm06a", "31", status);
+   vvd(rbpn[2][1], -0.4163377605910663999e-4, 1e-14,
+       "iauPnm06a", "32", status);
+   vvd(rbpn[2][2], 0.9999999329094260057, 1e-12,
+       "iauPnm06a", "33", status);
+
+}
+
+static void t_pnm80(int *status)
+/*
+**  - - - - - - - -
+**   t _ p n m 8 0
+**  - - - - - - - -
+**
+**  Test iauPnm80 function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauPnm80, vvd
+**
+**  This revision:  2008 November 28
+*/
+{
+   double rmatpn[3][3];
+
+
+   iauPnm80(2400000.5, 50123.9999, rmatpn);
+
+   vvd(rmatpn[0][0], 0.9999995831934611169, 1e-12,
+       "iauPnm80", "11", status);
+   vvd(rmatpn[0][1], 0.8373654045728124011e-3, 1e-14,
+       "iauPnm80", "12", status);
+   vvd(rmatpn[0][2], 0.3639121916933106191e-3, 1e-14,
+       "iauPnm80", "13", status);
+
+   vvd(rmatpn[1][0], -0.8373804896118301316e-3, 1e-14,
+       "iauPnm80", "21", status);
+   vvd(rmatpn[1][1], 0.9999996485439674092, 1e-12,
+       "iauPnm80", "22", status);
+   vvd(rmatpn[1][2], 0.4130202510421549752e-4, 1e-14,
+       "iauPnm80", "23", status);
+
+   vvd(rmatpn[2][0], -0.3638774789072144473e-3, 1e-14,
+       "iauPnm80", "31", status);
+   vvd(rmatpn[2][1], -0.4160674085851722359e-4, 1e-14,
+       "iauPnm80", "32", status);
+   vvd(rmatpn[2][2], 0.9999999329310274805, 1e-12,
+       "iauPnm80", "33", status);
+
+}
+
+static void t_pom00(int *status)
+/*
+**  - - - - - - - -
+**   t _ p o m 0 0
+**  - - - - - - - -
+**
+**  Test iauPom00 function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauPom00, vvd
+**
+**  This revision:  2008 November 28
+*/
+{
+   double xp, yp, sp, rpom[3][3];
+
+
+   xp =  2.55060238e-7;
+   yp =  1.860359247e-6;
+   sp = -0.1367174580728891460e-10;
+
+   iauPom00(xp, yp, sp, rpom);
+
+   vvd(rpom[0][0], 0.9999999999999674721, 1e-12,
+       "iauPom00", "11", status);
+   vvd(rpom[0][1], -0.1367174580728846989e-10, 1e-16,
+       "iauPom00", "12", status);
+   vvd(rpom[0][2], 0.2550602379999972345e-6, 1e-16,
+       "iauPom00", "13", status);
+
+   vvd(rpom[1][0], 0.1414624947957029801e-10, 1e-16,
+       "iauPom00", "21", status);
+   vvd(rpom[1][1], 0.9999999999982695317, 1e-12,
+       "iauPom00", "22", status);
+   vvd(rpom[1][2], -0.1860359246998866389e-5, 1e-16,
+       "iauPom00", "23", status);
+
+   vvd(rpom[2][0], -0.2550602379741215021e-6, 1e-16,
+       "iauPom00", "31", status);
+   vvd(rpom[2][1], 0.1860359247002414021e-5, 1e-16,
+       "iauPom00", "32", status);
+   vvd(rpom[2][2], 0.9999999999982370039, 1e-12,
+       "iauPom00", "33", status);
+
+}
+
+static void t_ppp(int *status)
+/*
+**  - - - - - -
+**   t _ p p p
+**  - - - - - -
+**
+**  Test iauPpp function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauPpp, vvd
+**
+**  This revision:  2008 November 30
+*/
+{
+   double a[3], b[3], apb[3];
+
+
+   a[0] = 2.0;
+   a[1] = 2.0;
+   a[2] = 3.0;
+
+   b[0] = 1.0;
+   b[1] = 3.0;
+   b[2] = 4.0;
+
+   iauPpp(a, b, apb);
+
+   vvd(apb[0], 3.0, 1e-12, "iauPpp", "0", status);
+   vvd(apb[1], 5.0, 1e-12, "iauPpp", "1", status);
+   vvd(apb[2], 7.0, 1e-12, "iauPpp", "2", status);
+
+}
+
+static void t_ppsp(int *status)
+/*
+**  - - - - - - -
+**   t _ p p s p
+**  - - - - - - -
+**
+**  Test iauPpsp function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauPpsp, vvd
+**
+**  This revision:  2008 November 30
+*/
+{
+   double a[3], s, b[3], apsb[3];
+
+
+   a[0] = 2.0;
+   a[1] = 2.0;
+   a[2] = 3.0;
+
+   s = 5.0;
+
+   b[0] = 1.0;
+   b[1] = 3.0;
+   b[2] = 4.0;
+
+   iauPpsp(a, s, b, apsb);
+
+   vvd(apsb[0], 7.0, 1e-12, "iauPpsp", "0", status);
+   vvd(apsb[1], 17.0, 1e-12, "iauPpsp", "1", status);
+   vvd(apsb[2], 23.0, 1e-12, "iauPpsp", "2", status);
+
+}
+
+static void t_pr00(int *status)
+/*
+**  - - - - - - -
+**   t _ p r 0 0
+**  - - - - - - -
+**
+**  Test iauPr00 function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauPr00, vvd
+**
+**  This revision:  2008 November 28
+*/
+{
+   double dpsipr, depspr;
+
+   iauPr00(2400000.5, 53736, &dpsipr, &depspr);
+
+   vvd(dpsipr, -0.8716465172668347629e-7, 1e-22,
+      "iauPr00", "dpsipr", status);
+   vvd(depspr, -0.7342018386722813087e-8, 1e-22,
+      "iauPr00", "depspr", status);
+
+}
+
+static void t_prec76(int *status)
+/*
+**  - - - - - - - - -
+**   t _ p r e c 7 6
+**  - - - - - - - - -
+**
+**  Test iauPrec76 function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauPrec76, vvd
+**
+**  This revision:  2008 November 28
+*/
+{
+   double ep01, ep02, ep11, ep12, zeta, z, theta;
+
+
+   ep01 = 2400000.5;
+   ep02 = 33282.0;
+   ep11 = 2400000.5;
+   ep12 = 51544.0;
+
+   iauPrec76(ep01, ep02, ep11, ep12, &zeta, &z, &theta);
+
+   vvd(zeta,  0.5588961642000161243e-2, 1e-12,
+       "iauPrec76", "zeta",  status);
+   vvd(z,     0.5589922365870680624e-2, 1e-12,
+       "iauPrec76", "z",     status);
+   vvd(theta, 0.4858945471687296760e-2, 1e-12,
+       "iauPrec76", "theta", status);
+
+}
+
+static void t_pv2p(int *status)
+/*
+**  - - - - - - -
+**   t _ p v 2 p
+**  - - - - - - -
+**
+**  Test iauPv2p function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauPv2p, vvd
+**
+**  This revision:  2008 November 30
+*/
+{
+   double pv[2][3], p[3];
+
+
+   pv[0][0] =  0.3;
+   pv[0][1] =  1.2;
+   pv[0][2] = -2.5;
+
+   pv[1][0] = -0.5;
+   pv[1][1] =  3.1;
+   pv[1][2] =  0.9;
+
+   iauPv2p(pv, p);
+
+   vvd(p[0],  0.3, 0.0, "iauPv2p", "1", status);
+   vvd(p[1],  1.2, 0.0, "iauPv2p", "2", status);
+   vvd(p[2], -2.5, 0.0, "iauPv2p", "3", status);
+
+}
+
+static void t_pv2s(int *status)
+/*
+**  - - - - - - -
+**   t _ p v 2 s
+**  - - - - - - -
+**
+**  Test iauPv2s function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauPv2s, vvd
+**
+**  This revision:  2008 November 28
+*/
+{
+   double pv[2][3], theta, phi, r, td, pd, rd;
+
+
+   pv[0][0] = -0.4514964673880165;
+   pv[0][1] =  0.03093394277342585;
+   pv[0][2] =  0.05594668105108779;
+
+   pv[1][0] =  1.292270850663260e-5;
+   pv[1][1] =  2.652814182060692e-6;
+   pv[1][2] =  2.568431853930293e-6;
+
+   iauPv2s(pv, &theta, &phi, &r, &td, &pd, &rd);
+
+   vvd(theta, 3.073185307179586515, 1e-12, "iauPv2s", "theta", status);
+   vvd(phi, 0.1229999999999999992, 1e-12, "iauPv2s", "phi", status);
+   vvd(r, 0.4559999999999999757, 1e-12, "iauPv2s", "r", status);
+   vvd(td, -0.7800000000000000364e-5, 1e-16, "iauPv2s", "td", status);
+   vvd(pd, 0.9010000000000001639e-5, 1e-16, "iauPv2s", "pd", status);
+   vvd(rd, -0.1229999999999999832e-4, 1e-16, "iauPv2s", "rd", status);
+
+}
+
+static void t_pvdpv(int *status)
+/*
+**  - - - - - - - -
+**   t _ p v d p v
+**  - - - - - - - -
+**
+**  Test iauPvdpv function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauPvdpv, vvd
+**
+**  This revision:  2008 November 30
+*/
+{
+   double a[2][3], b[2][3], adb[2];
+
+
+   a[0][0] = 2.0;
+   a[0][1] = 2.0;
+   a[0][2] = 3.0;
+
+   a[1][0] = 6.0;
+   a[1][1] = 0.0;
+   a[1][2] = 4.0;
+
+   b[0][0] = 1.0;
+   b[0][1] = 3.0;
+   b[0][2] = 4.0;
+
+   b[1][0] = 0.0;
+   b[1][1] = 2.0;
+   b[1][2] = 8.0;
+
+   iauPvdpv(a, b, adb);
+
+   vvd(adb[0], 20.0, 1e-12, "iauPvdpv", "1", status);
+   vvd(adb[1], 50.0, 1e-12, "iauPvdpv", "2", status);
+
+}
+
+static void t_pvm(int *status)
+/*
+**  - - - - - -
+**   t _ p v m
+**  - - - - - -
+**
+**  Test iauPvm function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauPvm, vvd
+**
+**  This revision:  2008 May 25
+*/
+{
+   double pv[2][3], r, s;
+
+
+   pv[0][0] =  0.3;
+   pv[0][1] =  1.2;
+   pv[0][2] = -2.5;
+
+   pv[1][0] =  0.45;
+   pv[1][1] = -0.25;
+   pv[1][2] =  1.1;
+
+   iauPvm(pv, &r, &s);
+
+   vvd(r, 2.789265136196270604, 1e-12, "iauPvm", "r", status);
+   vvd(s, 1.214495780149111922, 1e-12, "iauPvm", "s", status);
+
+}
+
+static void t_pvmpv(int *status)
+/*
+**  - - - - - - - -
+**   t _ p v m p v
+**  - - - - - - - -
+**
+**  Test iauPvmpv function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauPvmpv, vvd
+**
+**  This revision:  2008 November 30
+*/
+{
+   double a[2][3], b[2][3], amb[2][3];
+
+
+   a[0][0] = 2.0;
+   a[0][1] = 2.0;
+   a[0][2] = 3.0;
+
+   a[1][0] = 5.0;
+   a[1][1] = 6.0;
+   a[1][2] = 3.0;
+
+   b[0][0] = 1.0;
+   b[0][1] = 3.0;
+   b[0][2] = 4.0;
+
+   b[1][0] = 3.0;
+   b[1][1] = 2.0;
+   b[1][2] = 1.0;
+
+   iauPvmpv(a, b, amb);
+
+   vvd(amb[0][0],  1.0, 1e-12, "iauPvmpv", "11", status);
+   vvd(amb[0][1], -1.0, 1e-12, "iauPvmpv", "21", status);
+   vvd(amb[0][2], -1.0, 1e-12, "iauPvmpv", "31", status);
+
+   vvd(amb[1][0],  2.0, 1e-12, "iauPvmpv", "12", status);
+   vvd(amb[1][1],  4.0, 1e-12, "iauPvmpv", "22", status);
+   vvd(amb[1][2],  2.0, 1e-12, "iauPvmpv", "32", status);
+
+}
+
+static void t_pvppv(int *status)
+/*
+**  - - - - - - - -
+**   t _ p v p p v
+**  - - - - - - - -
+**
+**  Test iauPvppv function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauPvppv, vvd
+**
+**  This revision:  2008 November 30
+*/
+{
+   double a[2][3], b[2][3], apb[2][3];
+
+
+   a[0][0] = 2.0;
+   a[0][1] = 2.0;
+   a[0][2] = 3.0;
+
+   a[1][0] = 5.0;
+   a[1][1] = 6.0;
+   a[1][2] = 3.0;
+
+   b[0][0] = 1.0;
+   b[0][1] = 3.0;
+   b[0][2] = 4.0;
+
+   b[1][0] = 3.0;
+   b[1][1] = 2.0;
+   b[1][2] = 1.0;
+
+   iauPvppv(a, b, apb);
+
+   vvd(apb[0][0], 3.0, 1e-12, "iauPvppv", "p1", status);
+   vvd(apb[0][1], 5.0, 1e-12, "iauPvppv", "p2", status);
+   vvd(apb[0][2], 7.0, 1e-12, "iauPvppv", "p3", status);
+
+   vvd(apb[1][0], 8.0, 1e-12, "iauPvppv", "v1", status);
+   vvd(apb[1][1], 8.0, 1e-12, "iauPvppv", "v2", status);
+   vvd(apb[1][2], 4.0, 1e-12, "iauPvppv", "v3", status);
+
+}
+
+static void t_pvstar(int *status)
+/*
+**  - - - - - - - - -
+**   t _ p v s t a r
+**  - - - - - - - - -
+**
+**  Test iauPvstar function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauPvstar, vvd, viv
+**
+**  This revision:  2009 November 6
+*/
+{
+   double pv[2][3], ra, dec, pmr, pmd, px, rv;
+   int j;
+
+
+   pv[0][0] =  126668.5912743160601;
+   pv[0][1] =  2136.792716839935195;
+   pv[0][2] = -245251.2339876830091;
+
+   pv[1][0] = -0.4051854035740712739e-2;
+   pv[1][1] = -0.6253919754866173866e-2;
+   pv[1][2] =  0.1189353719774107189e-1;
+
+   j = iauPvstar(pv, &ra, &dec, &pmr, &pmd, &px, &rv);
+
+   vvd(ra, 0.1686756e-1, 1e-12, "iauPvstar", "ra", status);
+   vvd(dec, -1.093989828, 1e-12, "iauPvstar", "dec", status);
+   vvd(pmr, -0.178323516e-4, 1e-16, "iauPvstar", "pmr", status);
+   vvd(pmd, 0.2336024047e-5, 1e-16, "iauPvstar", "pmd", status);
+   vvd(px, 0.74723, 1e-12, "iauPvstar", "px", status);
+   vvd(rv, -21.6, 1e-11, "iauPvstar", "rv", status);
+
+   viv(j, 0, "iauPvstar", "j", status);
+
+}
+
+static void t_pvu(int *status)
+/*
+**  - - - - - -
+**   t _ p v u
+**  - - - - - -
+**
+**  Test iauPvu function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauPvu, vvd
+**
+**  This revision:  2008 November 30
+*/
+{
+   double pv[2][3], upv[2][3];
+
+
+   pv[0][0] =  126668.5912743160734;
+   pv[0][1] =  2136.792716839935565;
+   pv[0][2] = -245251.2339876830229;
+
+   pv[1][0] = -0.4051854035740713039e-2;
+   pv[1][1] = -0.6253919754866175788e-2;
+   pv[1][2] =  0.1189353719774107615e-1;
+
+   iauPvu(2920.0, pv, upv);
+
+   vvd(upv[0][0], 126656.7598605317105, 1e-12,
+       "iauPvu", "p1", status);
+   vvd(upv[0][1], 2118.531271155726332, 1e-12,
+       "iauPvu", "p2", status);
+   vvd(upv[0][2], -245216.5048590656190, 1e-12,
+       "iauPvu", "p3", status);
+
+   vvd(upv[1][0], -0.4051854035740713039e-2, 1e-12,
+       "iauPvu", "v1", status);
+   vvd(upv[1][1], -0.6253919754866175788e-2, 1e-12,
+       "iauPvu", "v2", status);
+   vvd(upv[1][2], 0.1189353719774107615e-1, 1e-12,
+       "iauPvu", "v3", status);
+
+}
+
+static void t_pvup(int *status)
+/*
+**  - - - - - - -
+**   t _ p v u p
+**  - - - - - - -
+**
+**  Test iauPvup function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauPvup, vvd
+**
+**  This revision:  2008 November 30
+*/
+{
+   double pv[2][3], p[3];
+
+
+   pv[0][0] =  126668.5912743160734;
+   pv[0][1] =  2136.792716839935565;
+   pv[0][2] = -245251.2339876830229;
+
+   pv[1][0] = -0.4051854035740713039e-2;
+   pv[1][1] = -0.6253919754866175788e-2;
+   pv[1][2] =  0.1189353719774107615e-1;
+
+   iauPvup(2920.0, pv, p);
+
+   vvd(p[0],  126656.7598605317105,   1e-12, "iauPvup", "1", status);
+   vvd(p[1],    2118.531271155726332, 1e-12, "iauPvup", "2", status);
+   vvd(p[2], -245216.5048590656190,   1e-12, "iauPvup", "3", status);
+
+}
+
+static void t_pvxpv(int *status)
+/*
+**  - - - - - - - -
+**   t _ p v x p v
+**  - - - - - - - -
+**
+**  Test iauPvxpv function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauPvxpv, vvd
+**
+**  This revision:  2008 November 30
+*/
+{
+   double a[2][3], b[2][3], axb[2][3];
+
+
+   a[0][0] = 2.0;
+   a[0][1] = 2.0;
+   a[0][2] = 3.0;
+
+   a[1][0] = 6.0;
+   a[1][1] = 0.0;
+   a[1][2] = 4.0;
+
+   b[0][0] = 1.0;
+   b[0][1] = 3.0;
+   b[0][2] = 4.0;
+
+   b[1][0] = 0.0;
+   b[1][1] = 2.0;
+   b[1][2] = 8.0;
+
+   iauPvxpv(a, b, axb);
+
+   vvd(axb[0][0],  -1.0, 1e-12, "iauPvxpv", "p1", status);
+   vvd(axb[0][1],  -5.0, 1e-12, "iauPvxpv", "p2", status);
+   vvd(axb[0][2],   4.0, 1e-12, "iauPvxpv", "p3", status);
+
+   vvd(axb[1][0],  -2.0, 1e-12, "iauPvxpv", "v1", status);
+   vvd(axb[1][1], -36.0, 1e-12, "iauPvxpv", "v2", status);
+   vvd(axb[1][2],  22.0, 1e-12, "iauPvxpv", "v3", status);
+
+}
+
+static void t_pxp(int *status)
+/*
+**  - - - - - -
+**   t _ p x p
+**  - - - - - -
+**
+**  Test iauPxp function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauPxp, vvd
+**
+**  This revision:  2008 November 30
+*/
+{
+   double a[3], b[3], axb[3];
+
+
+   a[0] = 2.0;
+   a[1] = 2.0;
+   a[2] = 3.0;
+
+   b[0] = 1.0;
+   b[1] = 3.0;
+   b[2] = 4.0;
+
+   iauPxp(a, b, axb);
+
+   vvd(axb[0], -1.0, 1e-12, "iauPxp", "1", status);
+   vvd(axb[1], -5.0, 1e-12, "iauPxp", "2", status);
+   vvd(axb[2],  4.0, 1e-12, "iauPxp", "3", status);
+
+}
+
+static void t_rm2v(int *status)
+/*
+**  - - - - - - -
+**   t _ r m 2 v
+**  - - - - - - -
+**
+**  Test iauRm2v function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauRm2v, vvd
+**
+**  This revision:  2008 November 30
+*/
+{
+   double r[3][3], w[3];
+
+
+   r[0][0] =  0.00;
+   r[0][1] = -0.80;
+   r[0][2] = -0.60;
+
+   r[1][0] =  0.80;
+   r[1][1] = -0.36;
+   r[1][2] =  0.48;
+
+   r[2][0] =  0.60;
+   r[2][1] =  0.48;
+   r[2][2] = -0.64;
+
+   iauRm2v(r, w);
+
+   vvd(w[0],  0.0,                  1e-12, "iauRm2v", "1", status);
+   vvd(w[1],  1.413716694115406957, 1e-12, "iauRm2v", "2", status);
+   vvd(w[2], -1.884955592153875943, 1e-12, "iauRm2v", "3", status);
+
+}
+
+static void t_rv2m(int *status)
+/*
+**  - - - - - - -
+**   t _ r v 2 m
+**  - - - - - - -
+**
+**  Test iauRv2m function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauRv2m, vvd
+**
+**  This revision:  2008 May 27
+*/
+{
+   double w[3], r[3][3];
+
+
+   w[0] =  0.0;
+   w[1] =  1.41371669;
+   w[2] = -1.88495559;
+
+   iauRv2m(w, r);
+
+   vvd(r[0][0], -0.7071067782221119905, 1e-14, "iauRv2m", "11", status);
+   vvd(r[0][1], -0.5656854276809129651, 1e-14, "iauRv2m", "12", status);
+   vvd(r[0][2], -0.4242640700104211225, 1e-14, "iauRv2m", "13", status);
+
+   vvd(r[1][0],  0.5656854276809129651, 1e-14, "iauRv2m", "21", status);
+   vvd(r[1][1], -0.0925483394532274246, 1e-14, "iauRv2m", "22", status);
+   vvd(r[1][2], -0.8194112531408833269, 1e-14, "iauRv2m", "23", status);
+
+   vvd(r[2][0],  0.4242640700104211225, 1e-14, "iauRv2m", "31", status);
+   vvd(r[2][1], -0.8194112531408833269, 1e-14, "iauRv2m", "32", status);
+   vvd(r[2][2],  0.3854415612311154341, 1e-14, "iauRv2m", "33", status);
+
+}
+
+static void t_rx(int *status)
+/*
+**  - - - - -
+**   t _ r x
+**  - - - - -
+**
+**  Test iauRx function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauRx, vvd
+**
+**  This revision:  2008 November 30
+*/
+{
+   double phi, r[3][3];
+
+
+   phi = 0.3456789;
+
+   r[0][0] = 2.0;
+   r[0][1] = 3.0;
+   r[0][2] = 2.0;
+
+   r[1][0] = 3.0;
+   r[1][1] = 2.0;
+   r[1][2] = 3.0;
+
+   r[2][0] = 3.0;
+   r[2][1] = 4.0;
+   r[2][2] = 5.0;
+
+   iauRx(phi, r);
+
+   vvd(r[0][0], 2.0, 0.0, "iauRx", "11", status);
+   vvd(r[0][1], 3.0, 0.0, "iauRx", "12", status);
+   vvd(r[0][2], 2.0, 0.0, "iauRx", "13", status);
+
+   vvd(r[1][0], 3.839043388235612460, 1e-12, "iauRx", "21", status);
+   vvd(r[1][1], 3.237033249594111899, 1e-12, "iauRx", "22", status);
+   vvd(r[1][2], 4.516714379005982719, 1e-12, "iauRx", "23", status);
+
+   vvd(r[2][0], 1.806030415924501684, 1e-12, "iauRx", "31", status);
+   vvd(r[2][1], 3.085711545336372503, 1e-12, "iauRx", "32", status);
+   vvd(r[2][2], 3.687721683977873065, 1e-12, "iauRx", "33", status);
+
+}
+
+static void t_rxp(int *status)
+/*
+**  - - - - - -
+**   t _ r x p
+**  - - - - - -
+**
+**  Test iauRxp function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauRxp, vvd
+**
+**  This revision:  2008 November 30
+*/
+{
+   double r[3][3], p[3], rp[3];
+
+
+   r[0][0] = 2.0;
+   r[0][1] = 3.0;
+   r[0][2] = 2.0;
+
+   r[1][0] = 3.0;
+   r[1][1] = 2.0;
+   r[1][2] = 3.0;
+
+   r[2][0] = 3.0;
+   r[2][1] = 4.0;
+   r[2][2] = 5.0;
+
+   p[0] = 0.2;
+   p[1] = 1.5;
+   p[2] = 0.1;
+
+   iauRxp(r, p, rp);
+
+   vvd(rp[0], 5.1, 1e-12, "iauRxp", "1", status);
+   vvd(rp[1], 3.9, 1e-12, "iauRxp", "2", status);
+   vvd(rp[2], 7.1, 1e-12, "iauRxp", "3", status);
+
+}
+
+static void t_rxpv(int *status)
+/*
+**  - - - - - - -
+**   t _ r x p v
+**  - - - - - - -
+**
+**  Test iauRxpv function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauRxpv, vvd
+**
+**  This revision:  2008 November 30
+*/
+{
+   double r[3][3], pv[2][3], rpv[2][3];
+
+
+   r[0][0] = 2.0;
+   r[0][1] = 3.0;
+   r[0][2] = 2.0;
+
+   r[1][0] = 3.0;
+   r[1][1] = 2.0;
+   r[1][2] = 3.0;
+
+   r[2][0] = 3.0;
+   r[2][1] = 4.0;
+   r[2][2] = 5.0;
+
+   pv[0][0] = 0.2;
+   pv[0][1] = 1.5;
+   pv[0][2] = 0.1;
+
+   pv[1][0] = 1.5;
+   pv[1][1] = 0.2;
+   pv[1][2] = 0.1;
+
+   iauRxpv(r, pv, rpv);
+
+   vvd(rpv[0][0], 5.1, 1e-12, "iauRxpv", "11", status);
+   vvd(rpv[1][0], 3.8, 1e-12, "iauRxpv", "12", status);
+
+   vvd(rpv[0][1], 3.9, 1e-12, "iauRxpv", "21", status);
+   vvd(rpv[1][1], 5.2, 1e-12, "iauRxpv", "22", status);
+
+   vvd(rpv[0][2], 7.1, 1e-12, "iauRxpv", "31", status);
+   vvd(rpv[1][2], 5.8, 1e-12, "iauRxpv", "32", status);
+
+}
+
+static void t_rxr(int *status)
+/*
+**  - - - - - -
+**   t _ r x r
+**  - - - - - -
+**
+**  Test iauRxr function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauRxr, vvd
+**
+**  This revision:  2008 November 30
+*/
+{
+   double a[3][3], b[3][3], atb[3][3];
+
+
+   a[0][0] = 2.0;
+   a[0][1] = 3.0;
+   a[0][2] = 2.0;
+
+   a[1][0] = 3.0;
+   a[1][1] = 2.0;
+   a[1][2] = 3.0;
+
+   a[2][0] = 3.0;
+   a[2][1] = 4.0;
+   a[2][2] = 5.0;
+
+   b[0][0] = 1.0;
+   b[0][1] = 2.0;
+   b[0][2] = 2.0;
+
+   b[1][0] = 4.0;
+   b[1][1] = 1.0;
+   b[1][2] = 1.0;
+
+   b[2][0] = 3.0;
+   b[2][1] = 0.0;
+   b[2][2] = 1.0;
+
+   iauRxr(a, b, atb);
+
+   vvd(atb[0][0], 20.0, 1e-12, "iauRxr", "11", status);
+   vvd(atb[0][1],  7.0, 1e-12, "iauRxr", "12", status);
+   vvd(atb[0][2],  9.0, 1e-12, "iauRxr", "13", status);
+
+   vvd(atb[1][0], 20.0, 1e-12, "iauRxr", "21", status);
+   vvd(atb[1][1],  8.0, 1e-12, "iauRxr", "22", status);
+   vvd(atb[1][2], 11.0, 1e-12, "iauRxr", "23", status);
+
+   vvd(atb[2][0], 34.0, 1e-12, "iauRxr", "31", status);
+   vvd(atb[2][1], 10.0, 1e-12, "iauRxr", "32", status);
+   vvd(atb[2][2], 15.0, 1e-12, "iauRxr", "33", status);
+
+}
+
+static void t_ry(int *status)
+/*
+**  - - - - -
+**   t _ r y
+**  - - - - -
+**
+**  Test iauRy function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauRy, vvd
+**
+**  This revision:  2008 November 30
+*/
+{
+   double theta, r[3][3];
+
+
+   theta = 0.3456789;
+
+   r[0][0] = 2.0;
+   r[0][1] = 3.0;
+   r[0][2] = 2.0;
+
+   r[1][0] = 3.0;
+   r[1][1] = 2.0;
+   r[1][2] = 3.0;
+
+   r[2][0] = 3.0;
+   r[2][1] = 4.0;
+   r[2][2] = 5.0;
+
+   iauRy(theta, r);
+
+   vvd(r[0][0], 0.8651847818978159930, 1e-12, "iauRy", "11", status);
+   vvd(r[0][1], 1.467194920539316554, 1e-12, "iauRy", "12", status);
+   vvd(r[0][2], 0.1875137911274457342, 1e-12, "iauRy", "13", status);
+
+   vvd(r[1][0], 3, 1e-12, "iauRy", "21", status);
+   vvd(r[1][1], 2, 1e-12, "iauRy", "22", status);
+   vvd(r[1][2], 3, 1e-12, "iauRy", "23", status);
+
+   vvd(r[2][0], 3.500207892850427330, 1e-12, "iauRy", "31", status);
+   vvd(r[2][1], 4.779889022262298150, 1e-12, "iauRy", "32", status);
+   vvd(r[2][2], 5.381899160903798712, 1e-12, "iauRy", "33", status);
+
+}
+
+static void t_rz(int *status)
+/*
+**  - - - - -
+**   t _ r z
+**  - - - - -
+**
+**  Test iauRz function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauRz, vvd
+**
+**  This revision:  2008 November 30
+*/
+{
+   double psi, r[3][3];
+
+
+   psi = 0.3456789;
+
+   r[0][0] = 2.0;
+   r[0][1] = 3.0;
+   r[0][2] = 2.0;
+
+   r[1][0] = 3.0;
+   r[1][1] = 2.0;
+   r[1][2] = 3.0;
+
+   r[2][0] = 3.0;
+   r[2][1] = 4.0;
+   r[2][2] = 5.0;
+
+   iauRz(psi, r);
+
+   vvd(r[0][0], 2.898197754208926769, 1e-12, "iauRz", "11", status);
+   vvd(r[0][1], 3.500207892850427330, 1e-12, "iauRz", "12", status);
+   vvd(r[0][2], 2.898197754208926769, 1e-12, "iauRz", "13", status);
+
+   vvd(r[1][0], 2.144865911309686813, 1e-12, "iauRz", "21", status);
+   vvd(r[1][1], 0.865184781897815993, 1e-12, "iauRz", "22", status);
+   vvd(r[1][2], 2.144865911309686813, 1e-12, "iauRz", "23", status);
+
+   vvd(r[2][0], 3.0, 1e-12, "iauRz", "31", status);
+   vvd(r[2][1], 4.0, 1e-12, "iauRz", "32", status);
+   vvd(r[2][2], 5.0, 1e-12, "iauRz", "33", status);
+
+}
+
+static void t_s00a(int *status)
+/*
+**  - - - - - - -
+**   t _ s 0 0 a
+**  - - - - - - -
+**
+**  Test iauS00a function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauS00a, vvd
+**
+**  This revision:  2008 November 28
+*/
+{
+   double s;
+
+
+   s = iauS00a(2400000.5, 52541.0);
+
+   vvd(s, -0.1340684448919163584e-7, 1e-18, "iauS00a", "", status);
+
+}
+
+static void t_s00b(int *status)
+/*
+**  - - - - - - -
+**   t _ s 0 0 b
+**  - - - - - - -
+**
+**  Test iauS00b function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauS00b, vvd
+**
+**  This revision:  2008 November 28
+*/
+{
+   double s;
+
+
+   s = iauS00b(2400000.5, 52541.0);
+
+   vvd(s, -0.1340695782951026584e-7, 1e-18, "iauS00b", "", status);
+
+}
+
+static void t_s00(int *status)
+/*
+**  - - - - - -
+**   t _ s 0 0
+**  - - - - - -
+**
+**  Test iauS00 function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauS00, vvd
+**
+**  This revision:  2008 November 28
+*/
+{
+   double x, y, s;
+
+
+   x = 0.5791308486706011000e-3;
+   y = 0.4020579816732961219e-4;
+
+   s = iauS00(2400000.5, 53736.0, x, y);
+
+   vvd(s, -0.1220036263270905693e-7, 1e-18, "iauS00", "", status);
+
+}
+
+static void t_s06a(int *status)
+/*
+**  - - - - - - -
+**   t _ s 0 6 a
+**  - - - - - - -
+**
+**  Test iauS06a function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauS06a, vvd
+**
+**  This revision:  2008 November 28
+*/
+{
+   double s;
+
+
+   s = iauS06a(2400000.5, 52541.0);
+
+   vvd(s, -0.1340680437291812383e-7, 1e-18, "iauS06a", "", status);
+
+}
+
+static void t_s06(int *status)
+/*
+**  - - - - - -
+**   t _ s 0 6
+**  - - - - - -
+**
+**  Test iauS06 function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauS06, vvd
+**
+**  This revision:  2008 November 28
+*/
+{
+   double x, y, s;
+
+
+   x = 0.5791308486706011000e-3;
+   y = 0.4020579816732961219e-4;
+
+   s = iauS06(2400000.5, 53736.0, x, y);
+
+   vvd(s, -0.1220032213076463117e-7, 1e-18, "iauS06", "", status);
+
+}
+
+static void t_s2c(int *status)
+/*
+**  - - - - - -
+**   t _ s 2 c
+**  - - - - - -
+**
+**  Test iauS2c function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauS2c, vvd
+**
+**  This revision:  2008 November 30
+*/
+{
+   double c[3];
+
+
+   iauS2c(3.0123, -0.999, c);
+
+   vvd(c[0], -0.5366267667260523906, 1e-12, "iauS2c", "1", status);
+   vvd(c[1],  0.0697711109765145365, 1e-12, "iauS2c", "2", status);
+   vvd(c[2], -0.8409302618566214041, 1e-12, "iauS2c", "3", status);
+
+}
+
+static void t_s2p(int *status)
+/*
+**  - - - - - -
+**   t _ s 2 p
+**  - - - - - -
+**
+**  Test iauS2p function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauS2p, vvd
+**
+**  This revision:  2008 May 25
+*/
+{
+   double p[3];
+
+
+   iauS2p(-3.21, 0.123, 0.456, p);
+
+   vvd(p[0], -0.4514964673880165228, 1e-12, "iauS2p", "x", status);
+   vvd(p[1],  0.0309339427734258688, 1e-12, "iauS2p", "y", status);
+   vvd(p[2],  0.0559466810510877933, 1e-12, "iauS2p", "z", status);
+
+}
+
+static void t_s2pv(int *status)
+/*
+**  - - - - - - -
+**   t _ s 2 p v
+**  - - - - - - -
+**
+**  Test iauS2pv function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauS2pv, vvd
+**
+**  This revision:  2008 November 28
+*/
+{
+   double pv[2][3];
+
+
+   iauS2pv(-3.21, 0.123, 0.456, -7.8e-6, 9.01e-6, -1.23e-5, pv);
+
+   vvd(pv[0][0], -0.4514964673880165228, 1e-12, "iauS2pv", "x", status);
+   vvd(pv[0][1],  0.0309339427734258688, 1e-12, "iauS2pv", "y", status);
+   vvd(pv[0][2],  0.0559466810510877933, 1e-12, "iauS2pv", "z", status);
+
+   vvd(pv[1][0],  0.1292270850663260170e-4, 1e-16,
+       "iauS2pv", "vx", status);
+   vvd(pv[1][1],  0.2652814182060691422e-5, 1e-16,
+       "iauS2pv", "vy", status);
+   vvd(pv[1][2],  0.2568431853930292259e-5, 1e-16,
+       "iauS2pv", "vz", status);
+
+}
+
+static void t_s2xpv(int *status)
+/*
+**  - - - - - - - -
+**   t _ s 2 x p v
+**  - - - - - - - -
+**
+**  Test iauS2xpv function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauS2xpv, vvd
+**
+**  This revision:  2008 November 30
+*/
+{
+   double s1, s2, pv[2][3], spv[2][3];
+
+
+   s1 = 2.0;
+   s2 = 3.0;
+
+   pv[0][0] =  0.3;
+   pv[0][1] =  1.2;
+   pv[0][2] = -2.5;
+
+   pv[1][0] =  0.5;
+   pv[1][1] =  2.3;
+   pv[1][2] = -0.4;
+
+   iauS2xpv(s1, s2, pv, spv);
+
+   vvd(spv[0][0],  0.6, 1e-12, "iauS2xpv", "p1", status);
+   vvd(spv[0][1],  2.4, 1e-12, "iauS2xpv", "p2", status);
+   vvd(spv[0][2], -5.0, 1e-12, "iauS2xpv", "p3", status);
+
+   vvd(spv[1][0],  1.5, 1e-12, "iauS2xpv", "v1", status);
+   vvd(spv[1][1],  6.9, 1e-12, "iauS2xpv", "v2", status);
+   vvd(spv[1][2], -1.2, 1e-12, "iauS2xpv", "v3", status);
+
+}
+
+static void t_sepp(int *status)
+/*
+**  - - - - - - -
+**   t _ s e p p
+**  - - - - - - -
+**
+**  Test iauSepp function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauSepp, vvd
+**
+**  This revision:  2008 November 29
+*/
+{
+   double a[3], b[3], s;
+
+
+   a[0] =  1.0;
+   a[1] =  0.1;
+   a[2] =  0.2;
+
+   b[0] = -3.0;
+   b[1] =  1e-3;
+   b[2] =  0.2;
+
+   s = iauSepp(a, b);
+
+   vvd(s, 2.860391919024660768, 1e-12, "iauSepp", "", status);
+
+}
+
+static void t_seps(int *status)
+/*
+**  - - - - - - -
+**   t _ s e p s
+**  - - - - - - -
+**
+**  Test iauSeps function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauSeps, vvd
+**
+**  This revision:  2008 May 22
+*/
+{
+   double al, ap, bl, bp, s;
+
+
+   al =  1.0;
+   ap =  0.1;
+
+   bl =  0.2;
+   bp = -3.0;
+
+   s = iauSeps(al, ap, bl, bp);
+
+   vvd(s, 2.346722016996998842, 1e-14, "iauSeps", "", status);
+
+}
+
+static void t_sp00(int *status)
+/*
+**  - - - - - - -
+**   t _ s p 0 0
+**  - - - - - - -
+**
+**  Test iauSp00 function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauSp00, vvd
+**
+**  This revision:  2008 May 25
+*/
+{
+   vvd(iauSp00(2400000.5, 52541.0),
+       -0.6216698469981019309e-11, 1e-12, "iauSp00", "", status);
+
+}
+
+static void t_starpm(int *status)
+/*
+**  - - - - - - - - -
+**   t _ s t a r p m
+**  - - - - - - - - -
+**
+**  Test iauStarpm function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauStarpm, vvd, viv
+**
+**  This revision:  2008 November 30
+*/
+{
+   double ra1, dec1, pmr1, pmd1, px1, rv1;
+   double ra2, dec2, pmr2, pmd2, px2, rv2;
+   int j;
+
+
+   ra1 =   0.01686756;
+   dec1 = -1.093989828;
+   pmr1 = -1.78323516e-5;
+   pmd1 =  2.336024047e-6;
+   px1 =   0.74723;
+   rv1 = -21.6;
+
+   j = iauStarpm(ra1, dec1, pmr1, pmd1, px1, rv1,
+                 2400000.5, 50083.0, 2400000.5, 53736.0,
+                 &ra2, &dec2, &pmr2, &pmd2, &px2, &rv2);
+
+   vvd(ra2, 0.01668919069414242368, 1e-13,
+       "iauStarpm", "ra", status);
+   vvd(dec2, -1.093966454217127879, 1e-13,
+       "iauStarpm", "dec", status);
+   vvd(pmr2, -0.1783662682155932702e-4, 1e-17,
+       "iauStarpm", "pmr", status);
+   vvd(pmd2, 0.2338092915987603664e-5, 1e-17,
+       "iauStarpm", "pmd", status);
+   vvd(px2, 0.7473533835323493644, 1e-13,
+       "iauStarpm", "px", status);
+   vvd(rv2, -21.59905170476860786, 1e-11,
+       "iauStarpm", "rv", status);
+
+   viv(j, 0, "iauStarpm", "j", status);
+
+}
+
+static void t_starpv(int *status)
+/*
+**  - - - - - - - - -
+**   t _ s t a r p v
+**  - - - - - - - - -
+**
+**  Test iauStarpv function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauStarpv, vvd, viv
+**
+**  This revision:  2008 November 30
+*/
+{
+   double ra, dec, pmr, pmd, px, rv, pv[2][3];
+   int j;
+
+
+   ra =   0.01686756;
+   dec = -1.093989828;
+   pmr = -1.78323516e-5;
+   pmd =  2.336024047e-6;
+   px =   0.74723;
+   rv = -21.6;
+
+   j = iauStarpv(ra, dec, pmr, pmd, px, rv, pv);
+
+   vvd(pv[0][0], 126668.5912743160601, 1e-10,
+       "iauStarpv", "11", status);
+   vvd(pv[0][1], 2136.792716839935195, 1e-12,
+       "iauStarpv", "12", status);
+   vvd(pv[0][2], -245251.2339876830091, 1e-10,
+       "iauStarpv", "13", status);
+
+   vvd(pv[1][0], -0.4051854035740712739e-2, 1e-13,
+       "iauStarpv", "21", status);
+   vvd(pv[1][1], -0.6253919754866173866e-2, 1e-15,
+       "iauStarpv", "22", status);
+   vvd(pv[1][2], 0.1189353719774107189e-1, 1e-13,
+       "iauStarpv", "23", status);
+
+   viv(j, 0, "iauStarpv", "j", status);
+
+}
+
+static void t_sxp(int *status)
+/*
+**  - - - - - -
+**   t _ s x p
+**  - - - - - -
+**
+**  Test iauSxp function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauSxp, vvd
+**
+**  This revision:  2008 November 30
+*/
+{
+   double s, p[3], sp[3];
+
+
+   s = 2.0;
+
+   p[0] =  0.3;
+   p[1] =  1.2;
+   p[2] = -2.5;
+
+   iauSxp(s, p, sp);
+
+   vvd(sp[0],  0.6, 0.0, "iauSxp", "1", status);
+   vvd(sp[1],  2.4, 0.0, "iauSxp", "2", status);
+   vvd(sp[2], -5.0, 0.0, "iauSxp", "3", status);
+
+}
+
+
+static void t_sxpv(int *status)
+/*
+**  - - - - - - -
+**   t _ s x p v
+**  - - - - - - -
+**
+**  Test iauSxpv function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauSxpv, vvd
+**
+**  This revision:  2008 November 30
+*/
+{
+   double s, pv[2][3], spv[2][3];
+
+
+   s = 2.0;
+
+   pv[0][0] =  0.3;
+   pv[0][1] =  1.2;
+   pv[0][2] = -2.5;
+
+   pv[1][0] =  0.5;
+   pv[1][1] =  3.2;
+   pv[1][2] = -0.7;
+
+   iauSxpv(s, pv, spv);
+
+   vvd(spv[0][0],  0.6, 0.0, "iauSxpv", "p1", status);
+   vvd(spv[0][1],  2.4, 0.0, "iauSxpv", "p2", status);
+   vvd(spv[0][2], -5.0, 0.0, "iauSxpv", "p3", status);
+
+   vvd(spv[1][0],  1.0, 0.0, "iauSxpv", "v1", status);
+   vvd(spv[1][1],  6.4, 0.0, "iauSxpv", "v2", status);
+   vvd(spv[1][2], -1.4, 0.0, "iauSxpv", "v3", status);
+
+}
+
+static void t_taitt(int *status)
+/*
+**  - - - - - - - -
+**   t _ t a i t t
+**  - - - - - - - -
+**
+**  Test iauTaitt function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauTaitt, vvd, viv
+**
+**  This revision:  2010 September 7
+*/
+{
+   double t1, t2;
+   int j;
+
+
+   j = iauTaitt(2453750.5, 0.892482639, &t1, &t2);
+
+   vvd(t1, 2453750.5, 1e-6, "iauTaitt", "t1", status);
+   vvd(t2, 0.892855139, 1e-12, "iauTaitt", "t2", status);
+   viv(j, 0, "iauTaitt", "j", status);
+
+}
+
+static void t_taiut1(int *status)
+/*
+**  - - - - - - - - -
+**   t _ t a i u t 1
+**  - - - - - - - - -
+**
+**  Test iauTaiut1 function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauTaiut1, vvd, viv
+**
+**  This revision:  2010 September 7
+*/
+{
+   double u1, u2;
+   int j;
+
+
+   j = iauTaiut1(2453750.5, 0.892482639, -32.6659, &u1, &u2);
+
+   vvd(u1, 2453750.5, 1e-6, "iauTaiut1", "u1", status);
+   vvd(u2, 0.8921045614537037037, 1e-12, "iauTaiut1", "u2", status);
+   viv(j, 0, "iauTaiut1", "j", status);
+
+}
+
+static void t_taiutc(int *status)
+/*
+**  - - - - - - - - -
+**   t _ t a i u t c
+**  - - - - - - - - - - - -
+**
+**  Test iauTaiutc function.
+**
+**  Returned:
+**     status    LOGICAL     TRUE = success, FALSE = fail
+**
+**  Called:  iauTaiutc, vvd, viv
+**
+**  This revision:  2010 September 7
+*/
+{
+   double u1, u2;
+   int j;
+
+
+   j = iauTaiutc(2453750.5, 0.892482639, &u1, &u2);
+
+   vvd(u1, 2453750.5, 1e-6, "iauTaiutc", "u1", status);
+   vvd(u2, 0.8921006945555555556, 1e-12, "iauTaiutc", "u2", status);
+   viv(j, 0, "iauTaiutc", "j", status);
+
+}
+
+static void t_tcbtdb(int *status)
+/*
+**  - - - - - - - - -
+**   t _ t c b t d b
+**  - - - - - - - - -
+**
+**  Test iauTcbtdb function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauTcbtdb, vvd, viv
+**
+**  This revision:  2010 September 6
+*/
+{
+   double b1, b2;
+   int j;
+
+
+   j = iauTcbtdb(2453750.5, 0.893019599, &b1, &b2);
+
+   vvd(b1, 2453750.5, 1e-6, "iauTcbtdb", "b1", status);
+   vvd(b2, 0.8928551362746343397, 1e-12, "iauTcbtdb", "b2", status);
+   viv(j, 0, "iauTcbtdb", "j", status);
+
+}
+
+static void t_tcgtt(int *status)
+/*
+**  - - - - - - - -
+**   t _ t c g t t
+**  - - - - - - - -
+**
+**  Test iauTcgtt function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauTcgtt, vvd, viv
+**
+**  This revision:  2010 September g
+*/
+{
+   double t1, t2;
+   int j;
+
+
+   j = iauTcgtt(2453750.5, 0.892862531, &t1, &t2);
+
+   vvd(t1, 2453750.5, 1e-6, "iauTcgtt", "t1", status);
+   vvd(t2, 0.8928551387488816828, 1e-12, "iauTcgtt", "t2", status);
+   viv(j, 0, "iauTcgtt", "j", status);
+
+}
+
+static void t_tdbtcb(int *status)
+/*
+**  - - - - - - - - -
+**   t _ t d b t c b
+**  - - - - - - - - -
+**
+**  Test iauTdbtcb function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauTdbtcb, vvd, viv
+**
+**  This revision:  2010 September 6
+*/
+{
+   double b1, b2;
+   int j;
+
+
+   j = iauTdbtcb(2453750.5, 0.892855137, &b1, &b2);
+
+   vvd( b1, 2453750.5, 1e-6, "iauTdbtcb", "b1", status);
+   vvd( b2, 0.8930195997253656716, 1e-12, "iauTdbtcb", "b2", status);
+   viv(j, 0, "iauTdbtcb", "j", status);
+
+}
+
+static void t_tdbtt(int *status)
+/*
+**  - - - - - - - -
+**   t _ t d b t t
+**  - - - - - - - -
+**
+**  Test iauTdbtt function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauTdbtt, vvd, viv
+**
+**  This revision:  2010 September 7
+*/
+{
+   double t1, t2;
+   int j;
+
+
+   j = iauTdbtt(2453750.5, 0.892855137, -0.000201, &t1, &t2);
+
+   vvd(t1, 2453750.5, 1e-6, "iauTdbtt", "t1", status);
+   vvd(t2, 0.8928551393263888889, 1e-12, "iauTdbtt", "t2", status);
+   viv(j, 0, "iauTdbtt", "j", status);
+
+}
+
+static void t_tf2a(int *status)
+/*
+**  - - - - - - -
+**   t _ t f 2 a
+**  - - - - - - -
+**
+**  Test iauTf2a function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauTf2a, vvd, viv
+**
+**  This revision:  2010 September 7
+*/
+{
+   double a;
+   int j;
+
+
+   j = iauTf2a('+', 4, 58, 20.2, &a);
+
+   vvd(a, 1.301739278189537429, 1e-12, "iauTf2a", "a", status);
+   viv(j, 0, "iauTf2a", "j", status);
+
+}
+
+static void t_tf2d(int *status)
+/*
+**  - - - - - - -
+**   t _ t f 2 d
+**  - - - - - - -
+**
+**  Test iauTf2d function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauTf2d, vvd, viv
+**
+**  This revision:  2010 September 7
+*/
+{
+   double d;
+   int j;
+
+
+   j = iauTf2d(' ', 23, 55, 10.9, &d);
+
+   vvd(d, 0.9966539351851851852, 1e-12, "iauTf2d", "d", status);
+   viv(j, 0, "iauTf2d", "j", status);
+
+}
+
+static void t_tr(int *status)
+/*
+**  - - - - -
+**   t _ t r
+**  - - - - -
+**
+**  Test iauTr function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauTr, vvd
+**
+**  This revision:  2008 November 30
+*/
+{
+   double r[3][3], rt[3][3];
+
+
+   r[0][0] = 2.0;
+   r[0][1] = 3.0;
+   r[0][2] = 2.0;
+
+   r[1][0] = 3.0;
+   r[1][1] = 2.0;
+   r[1][2] = 3.0;
+
+   r[2][0] = 3.0;
+   r[2][1] = 4.0;
+   r[2][2] = 5.0;
+
+   iauTr(r, rt);
+
+   vvd(rt[0][0], 2.0, 0.0, "iauTr", "11", status);
+   vvd(rt[0][1], 3.0, 0.0, "iauTr", "12", status);
+   vvd(rt[0][2], 3.0, 0.0, "iauTr", "13", status);
+
+   vvd(rt[1][0], 3.0, 0.0, "iauTr", "21", status);
+   vvd(rt[1][1], 2.0, 0.0, "iauTr", "22", status);
+   vvd(rt[1][2], 4.0, 0.0, "iauTr", "23", status);
+
+   vvd(rt[2][0], 2.0, 0.0, "iauTr", "31", status);
+   vvd(rt[2][1], 3.0, 0.0, "iauTr", "32", status);
+   vvd(rt[2][2], 5.0, 0.0, "iauTr", "33", status);
+
+}
+
+static void t_trxp(int *status)
+/*
+**  - - - - - - -
+**   t _ t r x p
+**  - - - - - - -
+**
+**  Test iauTrxp function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauTrxp, vvd
+**
+**  This revision:  2008 November 30
+*/
+{
+   double r[3][3], p[3], trp[3];
+
+
+   r[0][0] = 2.0;
+   r[0][1] = 3.0;
+   r[0][2] = 2.0;
+
+   r[1][0] = 3.0;
+   r[1][1] = 2.0;
+   r[1][2] = 3.0;
+
+   r[2][0] = 3.0;
+   r[2][1] = 4.0;
+   r[2][2] = 5.0;
+
+   p[0] = 0.2;
+   p[1] = 1.5;
+   p[2] = 0.1;
+
+   iauTrxp(r, p, trp);
+
+   vvd(trp[0], 5.2, 1e-12, "iauTrxp", "1", status);
+   vvd(trp[1], 4.0, 1e-12, "iauTrxp", "2", status);
+   vvd(trp[2], 5.4, 1e-12, "iauTrxp", "3", status);
+
+}
+
+static void t_trxpv(int *status)
+/*
+**  - - - - - - - -
+**   t _ t r x p v
+**  - - - - - - - -
+**
+**  Test iauTrxpv function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauTrxpv, vvd
+**
+**  This revision:  2008 November 30
+*/
+{
+   double r[3][3], pv[2][3], trpv[2][3];
+
+
+   r[0][0] = 2.0;
+   r[0][1] = 3.0;
+   r[0][2] = 2.0;
+
+   r[1][0] = 3.0;
+   r[1][1] = 2.0;
+   r[1][2] = 3.0;
+
+   r[2][0] = 3.0;
+   r[2][1] = 4.0;
+   r[2][2] = 5.0;
+
+   pv[0][0] = 0.2;
+   pv[0][1] = 1.5;
+   pv[0][2] = 0.1;
+
+   pv[1][0] = 1.5;
+   pv[1][1] = 0.2;
+   pv[1][2] = 0.1;
+
+   iauTrxpv(r, pv, trpv);
+
+   vvd(trpv[0][0], 5.2, 1e-12, "iauTrxpv", "p1", status);
+   vvd(trpv[0][1], 4.0, 1e-12, "iauTrxpv", "p1", status);
+   vvd(trpv[0][2], 5.4, 1e-12, "iauTrxpv", "p1", status);
+
+   vvd(trpv[1][0], 3.9, 1e-12, "iauTrxpv", "v1", status);
+   vvd(trpv[1][1], 5.3, 1e-12, "iauTrxpv", "v2", status);
+   vvd(trpv[1][2], 4.1, 1e-12, "iauTrxpv", "v3", status);
+
+}
+
+static void t_tttai(int *status)
+/*
+**  - - - - - - - -
+**   t _ t t t a i
+**  - - - - - - - -
+**
+**  Test iauTttai function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauTttai, vvd, viv
+**
+**  This revision:  2010 September 7
+*/
+{
+   double a1, a2;
+   int j;
+
+
+   j = iauTttai(2453750.5, 0.892482639, &a1, &a2);
+
+   vvd(a1, 2453750.5, 1e-6, "iauTttai", "a1", status);
+   vvd(a2, 0.892110139, 1e-12, "iauTttai", "a2", status);
+   viv(j, 0, "iauTttai", "j", status);
+
+}
+
+static void t_tttcg(int *status)
+/*
+**  - - - - - - - -
+**   t _ t t t c g
+**  - - - - - - - -
+**
+**  Test iauTttcg function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauTttcg, vvd, viv
+**
+**  This revision:  2010 September 7
+*/
+{
+   double g1, g2;
+   int j;
+
+
+   j = iauTttcg(2453750.5, 0.892482639, &g1, &g2);
+
+   vvd( g1, 2453750.5, 1e-6, "iauTttcg", "g1", status);
+   vvd( g2, 0.8924900312508587113, 1e-12, "iauTttcg", "g2", status);
+   viv(j, 0, "iauTttcg", "j", status);
+
+}
+
+static void t_tttdb(int *status)
+/*
+**  - - - - - - - -
+**   t _ t t t d b
+**  - - - - - - - -
+**
+**  Test iauTttdb function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauTttdb, vvd, viv
+**
+**  This revision:  2010 September 7
+*/
+{
+   double b1, b2;
+   int j;
+
+
+   j = iauTttdb(2453750.5, 0.892855139, -0.000201, &b1, &b2);
+
+   vvd(b1, 2453750.5, 1e-6, "iauTttdb", "b1", status);
+   vvd(b2, 0.8928551366736111111, 1e-12, "iauTttdb", "b2", status);
+   viv(j, 0, "iauTttdb", "j", status);
+
+}
+
+static void t_ttut1(int *status)
+/*
+**  - - - - - - - -
+**   t _ t t u t 1
+**  - - - - - - - -
+**
+**  Test iauTtut1 function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauTtut1, vvd, viv
+**
+**  This revision:  2010 September 7
+*/
+{
+   double u1, u2;
+   int j;
+
+
+   j = iauTtut1(2453750.5, 0.892855139, 64.8499, &u1, &u2);
+
+   vvd(u1, 2453750.5, 1e-6, "iauTtut1", "u1", status);
+   vvd(u2, 0.8921045614537037037, 1e-12, "iauTtut1", "u2", status);
+   viv(j, 0, "iauTtut1", "j", status);
+
+}
+
+static void t_ut1tai(int *status)
+/*
+**  - - - - - - - - -
+**   t _ u t 1 t a i
+**  - - - - - - - - -
+**
+**  Test iauUt1tai function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauUt1tai, vvd, viv
+**
+**  This revision:  2010 September 7
+*/
+{
+   double a1, a2;
+   int j;
+
+
+   j = iauUt1tai(2453750.5, 0.892104561, -32.6659, &a1, &a2);
+
+   vvd(a1, 2453750.5, 1e-6, "iauUt1tai", "a1", status);
+   vvd(a2, 0.8924826385462962963, 1e-12, "iauUt1tai", "a2", status);
+   viv(j, 0, "iauUt1tai", "j", status);
+
+}
+
+static void t_ut1tt(int *status)
+/*
+**  - - - - - - - - - - -
+**   t _ u t 1 t t
+**  - - - - - - - - - - -
+**
+**  Test iauUt1tt function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauUt1tt, vvd, viv
+**
+**  This revision:  2010 September 7
+*/
+{
+   double t1, t2;
+   int j;
+
+
+   j = iauUt1tt(2453750.5, 0.892104561, 64.8499, &t1, &t2);
+
+   vvd(t1, 2453750.5, 1e-6, "iauUt1tt", "t1", status);
+   vvd(t2, 0.8928551385462962963, 1e-12, "iauUt1tt", "t2", status);
+   viv(j, 0, "iauUt1tt", "j", status);
+
+}
+
+static void t_ut1utc(int *status)
+/*
+**  - - - - - - - - -
+**   t _ u t 1 u t c
+**  - - - - - - - - -
+**
+**  Test iauUt1utc function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauUt1utc, vvd, viv
+**
+**  This revision:  2010 September 7
+*/
+{
+   double u1, u2;
+   int j;
+
+
+   j = iauUt1utc(2453750.5, 0.892104561, 0.3341, &u1, &u2);
+
+   vvd(u1, 2453750.5, 1e-6, "iauUt1utc", "u1", status);
+   vvd(u2, 0.8921006941018518519, 1e-12, "iauUt1utc", "u2", status);
+   viv(j, 0, "iauUt1utc", "j", status);
+
+}
+
+static void t_utctai(int *status)
+/*
+**  - - - - - - - - -
+**   t _ u t c t a i
+**  - - - - - - - - -
+**
+**  Test iauUtctai function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauUtctai, vvd, viv
+**
+**  This revision:  2010 September 7
+*/
+{
+   double u1, u2;
+   int j;
+
+
+   j = iauUtctai(2453750.5, 0.892100694, &u1, &u2);
+
+   vvd(u1, 2453750.5, 1e-6, "iauUtctai", "u1", status);
+   vvd(u2, 0.8924826384444444444, 1e-12, "iauUtctai", "u2", status);
+   viv(j, 0, "iauUtctai", "j", status);
+
+}
+
+static void t_utcut1(int *status)
+/*
+**  - - - - - - - - -
+**   t _ u t c u t 1
+**  - - - - - - - - -
+**
+**  Test iauUtcut1 function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauUtcut1, vvd, viv
+**
+**  This revision:  2010 September 7
+*/
+{
+   double u1, u2;
+   int j;
+
+
+   j = iauUtcut1(2453750.5, 0.892100694, 0.3341, &u1, &u2);
+
+   vvd(u1, 2453750.5, 1e-6, "iauUtcut1", "u1", status);
+   vvd(u2, 0.8921045608981481481, 1e-12, "iauUtcut1", "u2", status);
+   viv(j, 0, "iauUtcut1", "j", status);
+
+}
+
+static void t_xy06(int *status)
+/*
+**  - - - - - - -
+**   t _ x y 0 6
+**  - - - - - - -
+**
+**  Test iauXy06 function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauXy06, vvd
+**
+**  This revision:  2008 November 28
+*/
+{
+   double x, y;
+
+
+   iauXy06(2400000.5, 53736.0, &x, &y);
+
+   vvd(x, 0.5791308486706010975e-3, 1e-15, "iauXy06", "x", status);
+   vvd(y, 0.4020579816732958141e-4, 1e-16, "iauXy06", "y", status);
+
+}
+
+static void t_xys00a(int *status)
+/*
+**  - - - - - - - - -
+**   t _ x y s 0 0 a
+**  - - - - - - - - -
+**
+**  Test iauXys00a function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauXys00a, vvd
+**
+**  This revision:  2008 November 28
+*/
+{
+   double x, y, s;
+
+
+   iauXys00a(2400000.5, 53736.0, &x, &y, &s);
+
+   vvd(x,  0.5791308472168152904e-3, 1e-14, "iauXys00a", "x", status);
+   vvd(y,  0.4020595661591500259e-4, 1e-15, "iauXys00a", "y", status);
+   vvd(s, -0.1220040848471549623e-7, 1e-18, "iauXys00a", "s", status);
+
+}
+
+static void t_xys00b(int *status)
+/*
+**  - - - - - - - - -
+**   t _ x y s 0 0 b
+**  - - - - - - - - -
+**
+**  Test iauXys00b function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauXys00b, vvd
+**
+**  This revision:  2008 November 28
+*/
+{
+   double x, y, s;
+
+
+   iauXys00b(2400000.5, 53736.0, &x, &y, &s);
+
+   vvd(x,  0.5791301929950208873e-3, 1e-14, "iauXys00b", "x", status);
+   vvd(y,  0.4020553681373720832e-4, 1e-15, "iauXys00b", "y", status);
+   vvd(s, -0.1220027377285083189e-7, 1e-18, "iauXys00b", "s", status);
+
+}
+
+static void t_xys06a(int *status)
+/*
+**  - - - - - - - - -
+**   t _ x y s 0 6 a
+**  - - - - - - - - -
+**
+**  Test iauXys06a function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauXys06a, vvd
+**
+**  This revision:  2008 November 28
+*/
+{
+   double x, y, s;
+
+
+   iauXys06a(2400000.5, 53736.0, &x, &y, &s);
+
+   vvd(x,  0.5791308482835292617e-3, 1e-14, "iauXys06a", "x", status);
+   vvd(y,  0.4020580099454020310e-4, 1e-15, "iauXys06a", "y", status);
+   vvd(s, -0.1220032294164579896e-7, 1e-18, "iauXys06a", "s", status);
+
+}
+
+static void t_zp(int *status)
+/*
+**  - - - - -
+**   t _ z p
+**  - - - - -
+**
+**  Test iauZp function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauZp, vvd
+**
+**  This revision:  2008 November 30
+*/
+{
+   double p[3];
+
+
+   p[0] =  0.3;
+   p[1] =  1.2;
+   p[2] = -2.5;
+
+   iauZp(p);
+
+   vvd(p[0], 0.0, 0.0, "iauZp", "1", status);
+   vvd(p[1], 0.0, 0.0, "iauZp", "2", status);
+   vvd(p[2], 0.0, 0.0, "iauZp", "3", status);
+
+}
+
+static void t_zpv(int *status)
+/*
+**  - - - - - -
+**   t _ z p v
+**  - - - - - -
+**
+**  Test iauZpv function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauZpv, vvd
+**
+**  This revision:  2008 May 25
+*/
+{
+   double pv[2][3];
+
+
+   pv[0][0] =  0.3;
+   pv[0][1] =  1.2;
+   pv[0][2] = -2.5;
+
+   pv[1][0] = -0.5;
+   pv[1][1] =  3.1;
+   pv[1][2] =  0.9;
+
+   iauZpv(pv);
+
+   vvd(pv[0][0], 0.0, 0.0, "iauZpv", "p1", status);
+   vvd(pv[0][1], 0.0, 0.0, "iauZpv", "p2", status);
+   vvd(pv[0][2], 0.0, 0.0, "iauZpv", "p3", status);
+
+   vvd(pv[1][0], 0.0, 0.0, "iauZpv", "v1", status);
+   vvd(pv[1][1], 0.0, 0.0, "iauZpv", "v2", status);
+   vvd(pv[1][2], 0.0, 0.0, "iauZpv", "v3", status);
+
+}
+
+static void t_zr(int *status)
+/*
+**  - - - - -
+**   t _ z r
+**  - - - - -
+**
+**  Test iauZr function.
+**
+**  Returned:
+**     status    int         TRUE = success, FALSE = fail
+**
+**  Called:  iauZr, vvd
+**
+**  This revision:  2008 November 30
+*/
+{
+   double r[3][3];
+
+
+   r[0][0] = 2.0;
+   r[1][0] = 3.0;
+   r[2][0] = 2.0;
+
+   r[0][1] = 3.0;
+   r[1][1] = 2.0;
+   r[2][1] = 3.0;
+
+   r[0][2] = 3.0;
+   r[1][2] = 4.0;
+   r[2][2] = 5.0;
+
+   iauZr(r);
+
+   vvd(r[0][0], 0.0, 0.0, "iauZr", "00", status);
+   vvd(r[1][0], 0.0, 0.0, "iauZr", "01", status);
+   vvd(r[2][0], 0.0, 0.0, "iauZr", "02", status);
+
+   vvd(r[0][1], 0.0, 0.0, "iauZr", "10", status);
+   vvd(r[1][1], 0.0, 0.0, "iauZr", "11", status);
+   vvd(r[2][1], 0.0, 0.0, "iauZr", "12", status);
+
+   vvd(r[0][2], 0.0, 0.0, "iauZr", "20", status);
+   vvd(r[1][2], 0.0, 0.0, "iauZr", "21", status);
+   vvd(r[2][2], 0.0, 0.0, "iauZr", "22", status);
+
+}
+
+int main(int argc, char *argv[])
+/*
+**  - - - - -
+**   m a i n
+**  - - - - -
+**
+**  This revision:  2010 September 7
+*/
+{
+   int status;
+
+
+/* If any command-line argument, switch to verbose reporting. */
+   if (argc > 1) {
+      verbose = 1;
+      argv[0][0] += 0;    /* to avoid compiler warnings */
+   }
+
+/* Preset the &status to FALSE = success. */
+   status = 0;
+
+/* Test all of the SOFA functions. */
+   t_a2af(&status);
+   t_a2tf(&status);
+   t_af2a(&status);
+   t_anp(&status);
+   t_anpm(&status);
+   t_bi00(&status);
+   t_bp00(&status);
+   t_bp06(&status);
+   t_bpn2xy(&status);
+   t_c2i00a(&status);
+   t_c2i00b(&status);
+   t_c2i06a(&status);
+   t_c2ibpn(&status);
+   t_c2ixy(&status);
+   t_c2ixys(&status);
+   t_c2s(&status);
+   t_c2t00a(&status);
+   t_c2t00b(&status);
+   t_c2t06a(&status);
+   t_c2tcio(&status);
+   t_c2teqx(&status);
+   t_c2tpe(&status);
+   t_c2txy(&status);
+   t_cal2jd(&status);
+   t_cp(&status);
+   t_cpv(&status);
+   t_cr(&status);
+   t_d2dtf(&status);
+   t_d2tf(&status);
+   t_dat(&status);
+   t_dtdb(&status);
+   t_dtf2d(&status);
+   t_ee00(&status);
+   t_ee00a(&status);
+   t_ee00b(&status);
+   t_ee06a(&status);
+   t_eect00(&status);
+   t_eform(&status);
+   t_eo06a(&status);
+   t_eors(&status);
+   t_epb(&status);
+   t_epb2jd(&status);
+   t_epj(&status);
+   t_epj2jd(&status);
+   t_epv00(&status);
+   t_eqeq94(&status);
+   t_era00(&status);
+   t_fad03(&status);
+   t_fae03(&status);
+   t_faf03(&status);
+   t_faju03(&status);
+   t_fal03(&status);
+   t_falp03(&status);
+   t_fama03(&status);
+   t_fame03(&status);
+   t_fane03(&status);
+   t_faom03(&status);
+   t_fapa03(&status);
+   t_fasa03(&status);
+   t_faur03(&status);
+   t_fave03(&status);
+   t_fk52h(&status);
+   t_fk5hip(&status);
+   t_fk5hz(&status);
+   t_fw2m(&status);
+   t_fw2xy(&status);
+   t_gc2gd(&status);
+   t_gc2gde(&status);
+   t_gd2gc(&status);
+   t_gd2gce(&status);
+   t_gmst00(&status);
+   t_gmst06(&status);
+   t_gmst82(&status);
+   t_gst00a(&status);
+   t_gst00b(&status);
+   t_gst06(&status);
+   t_gst06a(&status);
+   t_gst94(&status);
+   t_h2fk5(&status);
+   t_hfk5z(&status);
+   t_ir(&status);
+   t_jd2cal(&status);
+   t_jdcalf(&status);
+   t_num00a(&status);
+   t_num00b(&status);
+   t_num06a(&status);
+   t_numat(&status);
+   t_nut00a(&status);
+   t_nut00b(&status);
+   t_nut06a(&status);
+   t_nut80(&status);
+   t_nutm80(&status);
+   t_obl06(&status);
+   t_obl80(&status);
+   t_p06e(&status);
+   t_p2pv(&status);
+   t_p2s(&status);
+   t_pap(&status);
+   t_pas(&status);
+   t_pb06(&status);
+   t_pdp(&status);
+   t_pfw06(&status);
+   t_plan94(&status);
+   t_pmat00(&status);
+   t_pmat06(&status);
+   t_pmat76(&status);
+   t_pm(&status);
+   t_pmp(&status);
+   t_pn(&status);
+   t_pn00(&status);
+   t_pn00a(&status);
+   t_pn00b(&status);
+   t_pn06a(&status);
+   t_pn06(&status);
+   t_pnm00a(&status);
+   t_pnm00b(&status);
+   t_pnm06a(&status);
+   t_pnm80(&status);
+   t_pom00(&status);
+   t_ppp(&status);
+   t_ppsp(&status);
+   t_pr00(&status);
+   t_prec76(&status);
+   t_pv2p(&status);
+   t_pv2s(&status);
+   t_pvdpv(&status);
+   t_pvm(&status);
+   t_pvmpv(&status);
+   t_pvppv(&status);
+   t_pvstar(&status);
+   t_pvu(&status);
+   t_pvup(&status);
+   t_pvxpv(&status);
+   t_pxp(&status);
+   t_rm2v(&status);
+   t_rv2m(&status);
+   t_rx(&status);
+   t_rxp(&status);
+   t_rxpv(&status);
+   t_rxr(&status);
+   t_ry(&status);
+   t_rz(&status);
+   t_s00a(&status);
+   t_s00b(&status);
+   t_s00(&status);
+   t_s06a(&status);
+   t_s06(&status);
+   t_s2c(&status);
+   t_s2p(&status);
+   t_s2pv(&status);
+   t_s2xpv(&status);
+   t_sepp(&status);
+   t_seps(&status);
+   t_sp00(&status);
+   t_starpm(&status);
+   t_starpv(&status);
+   t_sxp(&status);
+   t_sxpv(&status);
+   t_taitt(&status);
+   t_taiut1(&status);
+   t_taiutc(&status);
+   t_tcbtdb(&status);
+   t_tcgtt(&status);
+   t_tdbtcb(&status);
+   t_tdbtt(&status);
+   t_tf2a(&status);
+   t_tf2d(&status);
+   t_tr(&status);
+   t_trxp(&status);
+   t_trxpv(&status);
+   t_tttai(&status);
+   t_tttcg(&status);
+   t_tttdb(&status);
+   t_ttut1(&status);
+   t_ut1tai(&status);
+   t_ut1tt(&status) ;
+   t_ut1utc(&status);
+   t_utctai(&status);
+   t_utcut1(&status);
+   t_xy06(&status);
+   t_xys00a(&status);
+   t_xys00b(&status);
+   t_xys06a(&status);
+   t_zp(&status);
+   t_zpv(&status);
+   t_zr(&status);
+
+/* Report, set up an appropriate exit status, and finish. */
+   if (status) {
+      printf("t_sofa_c validation failed!\n");
+   } else {
+      printf("t_sofa_c validation successful\n");
+   }
+   return status;
+}
+#include "sofam.h"
+
+int iauTaitt(double tai1, double tai2, double *tt1, double *tt2)
+/*
+**  - - - - - - - - -
+**   i a u T a i t t
+**  - - - - - - - - -
+**
+**  Time scale transformation:  International Atomic Time, TAI, to
+**  Terrestrial Time, TT.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards of Fundamental Astronomy) software collection.
+**
+**  Status:  canonical.
+**
+**  Given:
+**     tai1,tai2  double    TAI as a 2-part Julian Date
+**
+**  Returned:
+**     tt1,tt2    double    TT as a 2-part Julian Date
+**
+**  Returned (function value):
+**                int       status:  0 = OK
+**
+**  Note:
+**
+**     tai1+tai2 is Julian Date, apportioned in any convenient way
+**     between the two arguments, for example where tai1 is the Julian
+**     Day Number and tai2 is the fraction of a day.  The returned
+**     tt1,tt2 follow suit.
+**
+**  References:
+**
+**     McCarthy, D. D., Petit, G. (eds.), IERS Conventions (2003),
+**     IERS Technical Note No. 32, BKG (2004)
+**
+**     Explanatory Supplement to the Astronomical Almanac,
+**     P. Kenneth Seidelmann (ed), University Science Books (1992)
+**
+**  This revision:  2011 May 14
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+
+/* TT minus TAI (days). */
+   static const double dtat = TTMTAI/DAYSEC;
+
+
+/* Result, safeguarding precision. */
+   if ( tai1 > tai2 ) {
+      *tt1 = tai1;
+      *tt2 = tai2 + dtat;
+   } else {
+      *tt1 = tai1 + dtat;
+      *tt2 = tai2;
+   }
+
+/* Status (always OK). */
+   return 0;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+int iauTaiut1(double tai1, double tai2, double dta,
+              double *ut11, double *ut12)
+/*
+**  - - - - - - - - - -
+**   i a u T a i u t 1
+**  - - - - - - - - - -
+**
+**  Time scale transformation:  International Atomic Time, TAI, to
+**  Universal Time, UT1.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards of Fundamental Astronomy) software collection.
+**
+**  Status:  canonical.
+**
+**  Given:
+**     tai1,tai2  double    TAI as a 2-part Julian Date
+**     dta        double    UT1-TAI in seconds
+**
+**  Returned:
+**     ut11,ut12  double    UT1 as a 2-part Julian Date
+**
+**  Returned (function value):
+**                int       status:  0 = OK
+**
+**  Notes:
+**
+**  1) tai1+tai2 is Julian Date, apportioned in any convenient way
+**     between the two arguments, for example where tai1 is the Julian
+**     Day Number and tai2 is the fraction of a day.  The returned
+**     UT11,UT12 follow suit.
+**
+**  2) The argument dta, i.e. UT1-TAI, is an observed quantity, and is
+**     available from IERS tabulations.
+**
+**  Reference:
+**
+**     Explanatory Supplement to the Astronomical Almanac,
+**     P. Kenneth Seidelmann (ed), University Science Books (1992)
+**
+**  This revision:  2011 May 14
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+**
+*/
+{
+   double dtad;
+
+
+/* Result, safeguarding precision. */
+   dtad = dta / DAYSEC;
+   if ( tai1 > tai2 ) {
+      *ut11 = tai1;
+      *ut12 = tai2 + dtad;
+   } else {
+      *ut11 = tai1 + dtad;
+      *ut12 = tai2;
+   }
+
+/* Status (always OK). */
+   return 0;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+int iauTaiutc(double tai1, double tai2, double *utc1, double *utc2)
+/*
+**  - - - - - - - - - -
+**   i a u T a i u t c
+**  - - - - - - - - - -
+**
+**  Time scale transformation:  International Atomic Time, TAI, to
+**  Coordinated Universal Time, UTC.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards of Fundamental Astronomy) software collection.
+**
+**  Status:  canonical.
+**
+**  Given:
+**     tai1,tai2  double   TAI as a 2-part Julian Date (Note 1)
+**
+**  Returned:
+**     utc1,utc2  double   UTC as a 2-part quasi Julian Date (Notes 1-3)
+**
+**  Returned (function value):
+**                int      status: +1 = dubious year (Note 4)
+**                                  0 = OK
+**                                 -1 = unacceptable date
+**
+**  Notes:
+**
+**  1) tai1+tai2 is Julian Date, apportioned in any convenient way
+**     between the two arguments, for example where tai1 is the Julian
+**     Day Number and tai2 is the fraction of a day.  The returned utc1
+**     and utc2 form an analogous pair, except that a special convention
+**     is used, to deal with the problem of leap seconds - see the next
+**     note.
+**
+**  2) JD cannot unambiguously represent UTC during a leap second unless
+**     special measures are taken.  The convention in the present
+**     function is that the JD day represents UTC days whether the
+**     length is 86399, 86400 or 86401 SI seconds.
+**
+**  3) The function iauD2dtf can be used to transform the UTC quasi-JD
+**     into calendar date and clock time, including UTC leap second
+**     handling.
+**
+**  4) The warning status "dubious year" flags UTCs that predate the
+**     introduction of the time scale and that are too far in the future
+**     to be trusted.  See iauDat for further details.
+**
+**  Called:
+**     iauJd2cal    JD to Gregorian calendar
+**     iauDat       delta(AT) = TAI-UTC
+**     iauCal2jd    Gregorian calendar to JD
+**
+**  References:
+**
+**     McCarthy, D. D., Petit, G. (eds.), IERS Conventions (2003),
+**     IERS Technical Note No. 32, BKG (2004)
+**
+**     Explanatory Supplement to the Astronomical Almanac,
+**     P. Kenneth Seidelmann (ed), University Science Books (1992)
+**
+**  This revision:  2011 May 14
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   int big1;
+   int i, iy, im, id, js;
+   double a1, a2, d1, dats1, d2, fd, ddats, dats2, datd, as1, as2, da;
+
+
+/* Put the two parts of the TAI into big-first order. */
+   big1 = ( tai1 >= tai2 );
+   if ( big1 ) {
+      a1 = tai1;
+      a2 = tai2;
+   } else {
+      a1 = tai2;
+      a2 = tai1;
+   }
+
+/* See if the TAI can possibly be in a leap-second day. */
+   d1 = a1;
+   dats1 = 0.0;
+   for ( i = -1; i <= 3; i++ ) {
+      d2 = a2 + (double) i;
+      if ( iauJd2cal(d1, d2, &iy, &im, &id, &fd) ) return -1;
+      js = iauDat(iy, im, id, 0.0, &dats2);
+      if ( js < 0 ) return -1;
+      if ( i == -1 ) dats1 = dats2;
+      ddats = dats2 - dats1;
+      datd = dats1 / DAYSEC;
+      if ( fabs(ddats) >= 0.5 ) {
+
+      /* Yes.  Get TAI for the start of the UTC day that */
+      /* ends in a leap. */
+         if ( iauCal2jd(iy, im, id, &d1, &d2) ) return -1;
+         as1 = d1;
+         as2 = d2 - 1.0 + datd;
+
+      /* Is the TAI after this point? */
+         da = a1 - as1;
+         da = da + ( a2 - as2 );
+         if ( da > 0 ) {
+
+         /* Yes:  fraction of the current UTC day that has elapsed. */
+            fd = da * DAYSEC / ( DAYSEC + ddats );
+
+         /* Ramp TAI-UTC to bring about SOFA's JD(UTC) convention. */
+            datd += ddats * ( fd <= 1.0 ? fd : 1.0 ) / DAYSEC;
+         }
+
+      /* Done. */
+         break;
+      }
+      dats1 = dats2;
+   }
+
+/* Subtract the (possibly adjusted) TAI-UTC from TAI to give UTC. */
+   a2 -= datd;
+
+/* Return the UTC result, preserving the TAI order. */
+   if ( big1 ) {
+      *utc1 = a1;
+      *utc2 = a2;
+   } else {
+      *utc1 = a2;
+      *utc2 = a1;
+   }
+
+/* Status. */
+   return js;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+int iauTcbtdb(double tcb1, double tcb2, double *tdb1, double *tdb2)
+/*
+**  - - - - - - - - - -
+**   i a u T c b t d b
+**  - - - - - - - - - -
+**
+**  Time scale transformation:  Barycentric Coordinate Time, TCB, to
+**  Barycentric Dynamical Time, TDB.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards of Fundamental Astronomy) software collection.
+**
+**  Status:  canonical.
+**
+**  Given:
+**     tcb1,tcb2  double    TCB as a 2-part Julian Date
+**
+**  Returned:
+**     tdb1,tdb2  double    TDB as a 2-part Julian Date
+**
+**  Returned (function value):
+**                int       status:  0 = OK
+**
+**  Notes:
+**
+**  1) tcb1+tcb2 is Julian Date, apportioned in any convenient way
+**     between the two arguments, for example where tcb1 is the Julian
+**     Day Number and tcb2 is the fraction of a day.  The returned
+**     tdb1,tdb2 follow suit.
+**
+**  2) The 2006 IAU General Assembly introduced a conventional linear
+**     transformation between TDB and TCB.  This transformation
+**     compensates for the drift between TCB and terrestrial time TT,
+**     and keeps TDB approximately centered on TT.  Because the
+**     relationship between TT and TCB depends on the adopted solar
+**     system ephemeris, the degree of alignment between TDB and TT over
+**     long intervals will vary according to which ephemeris is used.
+**     Former definitions of TDB attempted to avoid this problem by
+**     stipulating that TDB and TT should differ only by periodic
+**     effects.  This is a good description of the nature of the
+**     relationship but eluded precise mathematical formulation.  The
+**     conventional linear relationship adopted in 2006 sidestepped
+**     these difficulties whilst delivering a TDB that in practice was
+**     consistent with values before that date.
+**
+**  3) TDB is essentially the same as Teph, the time argument for the
+**     JPL solar system ephemerides.
+**
+**  Reference:
+**
+**     IAU 2006 Resolution B3
+**
+**  This revision:  2011 May 14
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+
+/* 1977 Jan 1 00:00:32.184 TT, as two-part JD */
+   static const double t77td = DJM0 + DJM77;
+   static const double t77tf = TTMTAI/DAYSEC;
+
+/* TDB (days) at TAI 1977 Jan 1.0 */
+   static const double tdb0 = TDB0/DAYSEC;
+
+   double d;
+
+
+/* Result, safeguarding precision. */
+   if ( tcb1 > tcb2 ) {
+      d = tcb1 - t77td;
+      *tdb1 = tcb1;
+      *tdb2 = tcb2 + tdb0 - ( d + ( tcb2 - t77tf ) ) * ELB;
+   } else {
+      d = tcb2 - t77td;
+      *tdb1 = tcb1 + tdb0 - ( d + ( tcb1 - t77tf ) ) * ELB;
+      *tdb2 = tcb2;
+   }
+
+/* Status (always OK). */
+   return 0;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+int iauTcgtt(double tcg1, double tcg2, double *tt1, double *tt2)
+/*
+**  - - - - - - - - -
+**   i a u T c g t t
+**  - - - - - - - - -
+**
+**  Time scale transformation:  Geocentric Coordinate Time, TCG, to
+**  Terrestrial Time, TT.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards of Fundamental Astronomy) software collection.
+**
+**  Status:  canonical.
+**
+**  Given:
+**     tcg1,tcg2  double    TCG as a 2-part Julian Date
+**
+**  Returned:
+**     tt1,tt2    double    TT as a 2-part Julian Date
+**
+**  Returned (function value):
+**                int       status:  0 = OK
+**
+**  Note:
+**
+**     tcg1+tcg2 is Julian Date, apportioned in any convenient way
+**     between the two arguments, for example where tcg1 is the Julian
+**     Day Number and tcg22 is the fraction of a day.  The returned
+**     tt1,tt2 follow suit.
+**
+**  References:
+**
+**     McCarthy, D. D., Petit, G. (eds.), IERS Conventions (2003),.
+**     IERS Technical Note No. 32, BKG (2004)
+**
+**     IAU 2000 Resolution B1.9
+**
+**  This revision:  2010 May 14
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+
+/* 1977 Jan 1 00:00:32.184 TT, as MJD */
+   static const double t77t = DJM77 + TTMTAI/DAYSEC;
+
+
+/* Result, safeguarding precision. */
+   if ( tcg1 > tcg2 ) {
+      *tt1 = tcg1;
+      *tt2 = tcg2 - ( ( tcg1 - DJM0 ) + ( tcg2 - t77t ) ) * ELG;
+   } else {
+      *tt1 = tcg1 - ( ( tcg2 - DJM0 ) + ( tcg1 - t77t ) ) * ELG;
+      *tt2 = tcg2;
+   }
+
+/* OK status. */
+   return 0;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+int iauTdbtcb(double tdb1, double tdb2, double *tcb1, double *tcb2)
+/*
+**  - - - - - - - - - -
+**   i a u T d b t c b
+**  - - - - - - - - - -
+**
+**  Time scale transformation:  Barycentric Dynamical Time, TDB, to
+**  Barycentric Coordinate Time, TCB.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards of Fundamental Astronomy) software collection.
+**
+**  Status:  canonical.
+**
+**  Given:
+**     tdb1,tdb2  double    TDB as a 2-part Julian Date
+**
+**  Returned:
+**     tcb1,tcb2  double    TCB as a 2-part Julian Date
+**
+**  Returned (function value):
+**                int       status:  0 = OK
+**
+**  Notes:
+**
+**  1) tdb1+tdb2 is Julian Date, apportioned in any convenient way
+**     between the two arguments, for example where tdb1 is the Julian
+**     Day Number and tdb2 is the fraction of a day.  The returned
+**     tcb1,tcb2 follow suit.
+**
+**  2) The 2006 IAU General Assembly introduced a conventional linear
+**     transformation between TDB and TCB.  This transformation
+**     compensates for the drift between TCB and terrestrial time TT,
+**     and keeps TDB approximately centered on TT.  Because the
+**     relationship between TT and TCB depends on the adopted solar
+**     system ephemeris, the degree of alignment between TDB and TT over
+**     long intervals will vary according to which ephemeris is used.
+**     Former definitions of TDB attempted to avoid this problem by
+**     stipulating that TDB and TT should differ only by periodic
+**     effects.  This is a good description of the nature of the
+**     relationship but eluded precise mathematical formulation.  The
+**     conventional linear relationship adopted in 2006 sidestepped
+**     these difficulties whilst delivering a TDB that in practice was
+**     consistent with values before that date.
+**
+**  3) TDB is essentially the same as Teph, the time argument for the
+**     JPL solar system ephemerides.
+**
+**  Reference:
+**
+**     IAU 2006 Resolution B3
+**
+**  This revision:  2011 May 14
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+
+/* 1977 Jan 1 00:00:32.184 TT, as two-part JD */
+   static const double t77td = DJM0 + DJM77;
+   static const double t77tf = TTMTAI/DAYSEC;
+
+/* TDB (days) at TAI 1977 Jan 1.0 */
+   static const double tdb0 = TDB0/DAYSEC;
+
+/* TDB to TCB rate */
+   static const double elbb = ELB/(1.0-ELB);
+
+   double d, f;
+
+
+/* Result, preserving date format but safeguarding precision. */
+   if ( tdb1 > tdb2 ) {
+      d = t77td - tdb1;
+      f  = tdb2 - tdb0;
+      *tcb1 = tdb1;
+      *tcb2 = f - ( d - ( f - t77tf ) ) * elbb;
+   } else {
+      d = t77td - tdb2;
+      f  = tdb1 - tdb0;
+      *tcb1 = f + ( d - ( f - t77tf ) ) * elbb;
+      *tcb2 = tdb2;
+   }
+
+/* Status (always OK). */
+   return 0;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+int iauTdbtt(double tdb1, double tdb2, double dtr,
+             double *tt1, double *tt2 )
+/*
+**  - - - - - - - - -
+**   i a u T d b t t
+**  - - - - - - - - -
+**
+**  Time scale transformation:  Barycentric Dynamical Time, TDB, to
+**  Terrestrial Time, TT.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards of Fundamental Astronomy) software collection.
+**
+**  Status:  canonical.
+**
+**  Given:
+**     tdb1,tdb2  double    TDB as a 2-part Julian Date
+**     dtr        double    TDB-TT in seconds
+**
+**  Returned:
+**     tt1,tt2    double    TT as a 2-part Julian Date
+**
+**  Returned (function value):
+**                int       status:  0 = OK
+**
+**  Notes:
+**
+**  1) tdb1+tdb2 is Julian Date, apportioned in any convenient way
+**     between the two arguments, for example where tdb1 is the Julian
+**     Day Number and tdb2 is the fraction of a day.  The returned
+**     tt1,tt2 follow suit.
+**
+**  2) The argument dtr represents the quasi-periodic component of the
+**     GR transformation between TT and TCB.  It is dependent upon the
+**     adopted solar-system ephemeris, and can be obtained by numerical
+**     integration, by interrogating a precomputed time ephemeris or by
+**     evaluating a model such as that implemented in the SOFA function
+**     iauDtdb.   The quantity is dominated by an annual term of 1.7 ms
+**     amplitude.
+**
+**  3) TDB is essentially the same as Teph, the time argument for the
+**     JPL solar system ephemerides.
+**
+**  References:
+**
+**     McCarthy, D. D., Petit, G. (eds.), IERS Conventions (2003),
+**     IERS Technical Note No. 32, BKG (2004)
+**
+**     IAU 2006 Resolution 3
+**
+**  This revision:  2011 May 14
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+**
+*/
+{
+   double dtrd;
+
+
+/* Result, safeguarding precision. */
+   dtrd = dtr / DAYSEC;
+   if ( tdb1 > tdb2 ) {
+      *tt1 = tdb1;
+      *tt2 = tdb2 - dtrd;
+   } else {
+      *tt1 = tdb1 - dtrd;
+      *tt2 = tdb2;
+   }
+
+/* Status (always OK). */
+   return 0;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+#include <stdlib.h>
+
+int iauTf2a(char s, int ihour, int imin, double sec, double *rad)
+/*
+**  - - - - - - - -
+**   i a u T f 2 a
+**  - - - - - - - -
+**
+**  Convert hours, minutes, seconds to radians.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     s         char    sign:  '-' = negative, otherwise positive
+**     ihour     int     hours
+**     imin      int     minutes
+**     sec       double  seconds
+**
+**  Returned:
+**     rad       double  angle in radians
+**
+**  Returned (function value):
+**               int     status:  0 = OK
+**                                1 = ihour outside range 0-23
+**                                2 = imin outside range 0-59
+**                                3 = sec outside range 0-59.999...
+**
+**  Notes:
+**
+**  1)  The result is computed even if any of the range checks fail.
+**
+**  2)  Negative ihour, imin and/or sec produce a warning status, but
+**      the absolute value is used in the conversion.
+**
+**  3)  If there are multiple errors, the status value reflects only the
+**      first, the smallest taking precedence.
+**
+**  This revision:  2012 February 13
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+
+/* Compute the interval. */
+   *rad  = ( s == '-' ? -1.0 : 1.0 ) *
+           ( 60.0 * ( 60.0 * ( (double) abs(ihour) ) +
+                             ( (double) abs(imin) ) ) +
+                                        fabs(sec) ) * DS2R;
+
+/* Validate arguments and return status. */
+   if ( ihour < 0 || ihour > 23 ) return 1;
+   if ( imin < 0 || imin > 59 ) return 2;
+   if ( sec < 0.0 || sec >= 60.0 ) return 3;
+   return 0;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+#include <stdlib.h>
+
+int iauTf2d(char s, int ihour, int imin, double sec, double *days)
+/*
+**  - - - - - - - -
+**   i a u T f 2 d
+**  - - - - - - - -
+**
+**  Convert hours, minutes, seconds to days.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     s         char    sign:  '-' = negative, otherwise positive
+**     ihour     int     hours
+**     imin      int     minutes
+**     sec       double  seconds
+**
+**  Returned:
+**     days      double  interval in days
+**
+**  Returned (function value):
+**               int     status:  0 = OK
+**                                1 = ihour outside range 0-23
+**                                2 = imin outside range 0-59
+**                                3 = sec outside range 0-59.999...
+**
+**  Notes:
+**
+**  1)  The result is computed even if any of the range checks fail.
+**
+**  2)  Negative ihour, imin and/or sec produce a warning status, but
+**      the absolute value is used in the conversion.
+**
+**  3)  If there are multiple errors, the status value reflects only the
+**      first, the smallest taking precedence.
+**
+**  This revision:  2012 February 13
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+
+/* Compute the interval. */
+   *days  = ( s == '-' ? -1.0 : 1.0 ) *
+            ( 60.0 * ( 60.0 * ( (double) abs(ihour) ) +
+                              ( (double) abs(imin) ) ) +
+                                         fabs(sec) ) / DAYSEC;
+
+/* Validate arguments and return status. */
+   if ( ihour < 0 || ihour > 23 ) return 1;
+   if ( imin < 0 || imin > 59 ) return 2;
+   if ( sec < 0.0 || sec >= 60.0 ) return 3;
+   return 0;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauTr(double r[3][3], double rt[3][3])
+/*
+**  - - - - - -
+**   i a u T r
+**  - - - - - -
+**
+**  Transpose an r-matrix.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  vector/matrix support function.
+**
+**  Given:
+**     r        double[3][3]    r-matrix
+**
+**  Returned:
+**     rt       double[3][3]    transpose
+**
+**  Note:
+**     It is permissible for r and rt to be the same array.
+**
+**  Called:
+**     iauCr        copy r-matrix
+**
+**  This revision:  2008 May 22
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double wm[3][3];
+   int i, j;
+
+
+   for (i = 0; i < 3; i++) {
+      for (j = 0; j < 3; j++) {
+         wm[i][j] = r[j][i];
+      }
+   }
+   iauCr(wm, rt);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauTrxp(double r[3][3], double p[3], double trp[3])
+/*
+**  - - - - - - - -
+**   i a u T r x p
+**  - - - - - - - -
+**
+**  Multiply a p-vector by the transpose of an r-matrix.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  vector/matrix support function.
+**
+**  Given:
+**     r        double[3][3]   r-matrix
+**     p        double[3]      p-vector
+**
+**  Returned:
+**     trp      double[3]      r * p
+**
+**  Note:
+**     It is permissible for p and trp to be the same array.
+**
+**  Called:
+**     iauTr        transpose r-matrix
+**     iauRxp       product of r-matrix and p-vector
+**
+**  This revision:  2008 October 28
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double tr[3][3];
+
+
+/* Transpose of matrix r. */
+   iauTr(r, tr);
+
+/* Matrix tr * vector p -> vector trp. */
+   iauRxp(tr, p, trp);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauTrxpv(double r[3][3], double pv[2][3], double trpv[2][3])
+/*
+**  - - - - - - - - -
+**   i a u T r x p v
+**  - - - - - - - - -
+**
+**  Multiply a pv-vector by the transpose of an r-matrix.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  vector/matrix support function.
+**
+**  Given:
+**     r        double[3][3]    r-matrix
+**     pv       double[2][3]    pv-vector
+**
+**  Returned:
+**     trpv     double[2][3]    r * pv
+**
+**  Note:
+**     It is permissible for pv and trpv to be the same array.
+**
+**  Called:
+**     iauTr        transpose r-matrix
+**     iauRxpv      product of r-matrix and pv-vector
+**
+**  This revision:  2008 October 28
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double tr[3][3];
+
+
+/* Transpose of matrix r. */
+   iauTr(r, tr);
+
+/* Matrix tr * vector pv -> vector trpv. */
+   iauRxpv(tr, pv, trpv);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+int iauTttai(double tt1, double tt2, double *tai1, double *tai2)
+/*
+**  - - - - - - - - -
+**   i a u T t t a i
+**  - - - - - - - - -
+**
+**  Time scale transformation:  Terrestrial Time, TT, to International
+**  Atomic Time, TAI.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards of Fundamental Astronomy) software collection.
+**
+**  Status:  canonical.
+**
+**  Given:
+**     tt1,tt2    double    TT as a 2-part Julian Date
+**
+**  Returned:
+**     tai1,tai2  double    TAI as a 2-part Julian Date
+**
+**  Returned (function value):
+**                int       status:  0 = OK
+**
+**  Note:
+**
+**     tt1+tt2 is Julian Date, apportioned in any convenient way between
+**     the two arguments, for example where tt1 is the Julian Day Number
+**     and tt2 is the fraction of a day.  The returned tai1,tai2 follow
+**     suit.
+**
+**  References:
+**
+**     McCarthy, D. D., Petit, G. (eds.), IERS Conventions (2003),
+**     IERS Technical Note No. 32, BKG (2004)
+**
+**     Explanatory Supplement to the Astronomical Almanac,
+**     P. Kenneth Seidelmann (ed), University Science Books (1992)
+**
+**  This revision:  2011 May 14
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+
+/* TT minus TAI (days). */
+   static const double dtat = TTMTAI/DAYSEC;
+
+
+/* Result, safeguarding precision. */
+   if ( tt1 > tt2 ) {
+      *tai1 = tt1;
+      *tai2 = tt2 - dtat;
+   } else {
+      *tai1 = tt1 - dtat;
+      *tai2 = tt2;
+   }
+
+/* Status (always OK). */
+   return 0;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+int iauTttcg(double tt1, double tt2, double *tcg1, double *tcg2)
+/*
+**  - - - - - - - - -
+**   i a u T t t c g
+**  - - - - - - - - -
+**
+**  Time scale transformation:  Terrestrial Time, TT, to Geocentric
+**  Coordinate Time, TCG.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards of Fundamental Astronomy) software collection.
+**
+**  Status:  canonical.
+**
+**  Given:
+**     tt1,tt2    double    TT as a 2-part Julian Date
+**
+**  Returned:
+**     tcg1,tcg2  double    TCG as a 2-part Julian Date
+**
+**  Returned (function value):
+**                int       status:  0 = OK
+**
+**  Note:
+**
+**     tt1+tt2 is Julian Date, apportioned in any convenient way between
+**     the two arguments, for example where tt1 is the Julian Day Number
+**     and tt2 is the fraction of a day.  The returned tcg1,tcg2 follow
+**     suit.
+**
+**  References:
+**
+**     McCarthy, D. D., Petit, G. (eds.), IERS Conventions (2003),
+**     IERS Technical Note No. 32, BKG (2004)
+**
+**     IAU 2000 Resolution B1.9
+**
+**  This revision:  2010 May 13
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+
+/* 1977 Jan 1 00:00:32.184 TT, as MJD */
+   static const double t77t = DJM77 + TTMTAI/DAYSEC;
+
+/* TT to TCG rate */
+   static const double elgg = ELG/(1.0-ELG);
+
+
+/* Result, safeguarding precision. */
+   if ( tt1 > tt2 ) {
+      *tcg1 = tt1;
+      *tcg2 = tt2 + ( ( tt1 - DJM0 ) + ( tt2 - t77t ) ) * elgg;
+   } else {
+      *tcg1 = tt1 + ( ( tt2 - DJM0 ) + ( tt1 - t77t ) ) * elgg;
+      *tcg2 = tt2;
+   }
+
+/* Status (always OK). */
+   return 0;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+int iauTttdb(double tt1, double tt2, double dtr,
+             double *tdb1, double *tdb2)
+/*
+**  - - - - - - - - -
+**   i a u T t t d b
+**  - - - - - - - - -
+**
+**  Time scale transformation:  Terrestrial Time, TT, to Barycentric
+**  Dynamical Time, TDB.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards of Fundamental Astronomy) software collection.
+**
+**  Status:  canonical.
+**
+**  Given:
+**     tt1,tt2    double    TT as a 2-part Julian Date
+**     dtr        double    TDB-TT in seconds
+**
+**  Returned:
+**     tdb1,tdb2  double    TDB as a 2-part Julian Date
+**
+**  Returned (function value):
+**                int       status:  0 = OK
+**
+**  Notes:
+**
+**  1) tt1+tt2 is Julian Date, apportioned in any convenient way between
+**     the two arguments, for example where tt1 is the Julian Day Number
+**     and tt2 is the fraction of a day.  The returned tdb1,tdb2 follow
+**     suit.
+**
+**  2) The argument dtr represents the quasi-periodic component of the
+**     GR transformation between TT and TCB.  It is dependent upon the
+**     adopted solar-system ephemeris, and can be obtained by numerical
+**     integration, by interrogating a precomputed time ephemeris or by
+**     evaluating a model such as that implemented in the SOFA function
+**     iauDtdb.   The quantity is dominated by an annual term of 1.7 ms
+**     amplitude.
+**
+**  3) TDB is essentially the same as Teph, the time argument for the JPL
+**     solar system ephemerides.
+**
+**  References:
+**
+**     McCarthy, D. D., Petit, G. (eds.), IERS Conventions (2003),
+**     IERS Technical Note No. 32, BKG (2004)
+**
+**     IAU 2006 Resolution 3
+**
+**  This revision:  2011 May 14
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double dtrd;
+
+
+/* Result, safeguarding precision. */
+   dtrd = dtr / DAYSEC;
+   if ( tt1 > tt2 ) {
+      *tdb1 = tt1;
+      *tdb2 = tt2 + dtrd;
+   } else {
+      *tdb1 = tt1 + dtrd;
+      *tdb2 = tt2;
+   }
+
+/* Status (always OK). */
+   return 0;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+int iauTtut1(double tt1, double tt2, double dt,
+             double *ut11, double *ut12)
+/*
+**  - - - - - - - - -
+**   i a u T t u t 1
+**  - - - - - - - - -
+**
+**  Time scale transformation:  Terrestrial Time, TT, to Universal Time,
+**  UT1.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards of Fundamental Astronomy) software collection.
+**
+**  Status:  canonical.
+**
+**  Given:
+**     tt1,tt2    double    TT as a 2-part Julian Date
+**     dt         double    TT-UT1 in seconds
+**
+**  Returned:
+**     ut11,ut12  double    UT1 as a 2-part Julian Date
+**
+**  Returned (function value):
+**                int       status:  0 = OK
+**
+**  Notes:
+**
+**  1) tt1+tt2 is Julian Date, apportioned in any convenient way between
+**     the two arguments, for example where tt1 is the Julian Day Number
+**     and tt2 is the fraction of a day.  The returned ut11,ut12 follow
+**     suit.
+**
+**  2) The argument dt is classical Delta T.
+**
+**  Reference:
+**
+**     Explanatory Supplement to the Astronomical Almanac,
+**     P. Kenneth Seidelmann (ed), University Science Books (1992)
+**
+**  This revision:  2011 May 14
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double dtd;
+
+
+/* Result, safeguarding precision. */
+   dtd = dt / DAYSEC;
+   if ( tt1 > tt2 ) {
+      *ut11 = tt1;
+      *ut12 = tt2 - dtd;
+   } else {
+      *ut11 = tt1 - dtd;
+      *ut12 = tt2;
+   }
+
+/* Status (always OK). */
+   return 0;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+int iauUt1tai(double ut11, double ut12, double dta,
+              double *tai1, double *tai2)
+/*
+**  - - - - - - - - - -
+**   i a u U t 1 t a i
+**  - - - - - - - - - -
+**
+**  Time scale transformation:  Universal Time, UT1, to International
+**  Atomic Time, TAI.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards of Fundamental Astronomy) software collection.
+**
+**  Status:  canonical.
+**
+**  Given:
+**     ut11,ut12  double    UT1 as a 2-part Julian Date
+**     dta        double    UT1-TAI in seconds
+**
+**  Returned:
+**     tai1,tai2  double    TAI as a 2-part Julian Date
+**
+**  Returned (function value):
+**                int       status:  0 = OK
+**
+**  Notes:
+**
+**  1) ut11+ut12 is Julian Date, apportioned in any convenient way
+**     between the two arguments, for example where ut11 is the Julian
+**     Day Number and ut12 is the fraction of a day.  The returned
+**     tai1,tai2 follow suit.
+**
+**  2) The argument dta, i.e. UT1-TAI, is an observed quantity, and is
+**     available from IERS tabulations.
+**
+**  Reference:
+**
+**     Explanatory Supplement to the Astronomical Almanac,
+**     P. Kenneth Seidelmann (ed), University Science Books (1992)
+**
+**  This revision:  2011 May 14
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double dtad;
+
+
+/* Result, safeguarding precision. */
+   dtad = dta / DAYSEC;
+   if ( ut11 > ut12 ) {
+      *tai1 = ut11;
+      *tai2 = ut12 - dtad;
+   } else {
+      *tai1 = ut11 - dtad;
+      *tai2 = ut12;
+   }
+
+/* Status (always OK). */
+   return 0;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+int iauUt1tt(double ut11, double ut12, double dt,
+             double *tt1, double *tt2)
+/*
+**  - - - - - - - - -
+**   i a u U t 1 t t
+**  - - - - - - - - -
+**
+**  Time scale transformation:  Universal Time, UT1, to Terrestrial
+**  Time, TT.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards of Fundamental Astronomy) software collection.
+**
+**  Status:  canonical.
+**
+**  Given:
+**     ut11,ut12  double    UT1 as a 2-part Julian Date
+**     dt         double    TT-UT1 in seconds
+**
+**  Returned:
+**     tt1,tt2    double    TT as a 2-part Julian Date
+**
+**  Returned (function value):
+**                int       status:  0 = OK
+**
+**  Notes:
+**
+**  1) ut11+ut12 is Julian Date, apportioned in any convenient way
+**     between the two arguments, for example where ut11 is the Julian
+**     Day Number and ut12 is the fraction of a day.  The returned
+**     tt1,tt2 follow suit.
+**
+**  2) The argument dt is classical Delta T.
+**
+**  Reference:
+**
+**     Explanatory Supplement to the Astronomical Almanac,
+**     P. Kenneth Seidelmann (ed), University Science Books (1992)
+**
+**  This revision:  2011 May 14
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double dtd;
+
+
+/* Result, safeguarding precision. */
+   dtd = dt / DAYSEC;
+   if ( ut11 > ut12 ) {
+      *tt1 = ut11;
+      *tt2 = ut12 + dtd;
+   } else {
+      *tt1 = ut11 + dtd;
+      *tt2 = ut12;
+   }
+
+/* Status (always OK). */
+   return 0;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+int iauUt1utc(double ut11, double ut12, double dut1,
+              double *utc1, double *utc2)
+/*
+**  - - - - - - - - - -
+**   i a u U t 1 u t c
+**  - - - - - - - - - -
+**
+**  Time scale transformation:  Universal Time, UT1, to Coordinated
+**  Universal Time, UTC.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards of Fundamental Astronomy) software collection.
+**
+**  Status:  canonical.
+**
+**  Given:
+**     ut11,ut12  double   UT1 as a 2-part Julian Date (Note 1)
+**     dut1       double   Delta UT1: UT1-UTC in seconds (Note 2)
+**
+**  Returned:
+**     utc1,utc2  double   UTC as a 2-part quasi Julian Date (Notes 3,4)
+**
+**  Returned (function value):
+**                int      status: +1 = dubious year (Note 5)
+**                                  0 = OK
+**                                 -1 = unacceptable date
+**
+**  Notes:
+**
+**  1) ut11+ut12 is Julian Date, apportioned in any convenient way
+**     between the two arguments, for example where ut11 is the Julian
+**     Day Number and ut12 is the fraction of a day.  The returned utc1
+**     and utc2 form an analogous pair, except that a special convention
+**     is used, to deal with the problem of leap seconds - see Note 3.
+**
+**  2) Delta UT1 can be obtained from tabulations provided by the
+**     International Earth Rotation and Reference Systems Service.  The
+**     value changes abruptly by 1s at a leap second;  however, close to
+**     a leap second the algorithm used here is tolerant of the "wrong"
+**     choice of value being made.
+**
+**  3) JD cannot unambiguously represent UTC during a leap second unless
+**     special measures are taken.  The convention in the present
+**     function is that the returned quasi JD day UTC1+UTC2 represents
+**     UTC days whether the length is 86399, 86400 or 86401 SI seconds.
+**
+**  4) The function iauD2dtf can be used to transform the UTC quasi-JD
+**     into calendar date and clock time, including UTC leap second
+**     handling.
+**
+**  5) The warning status "dubious year" flags UTCs that predate the
+**     introduction of the time scale and that are too far in the future
+**     to be trusted.  See iauDat for further details.
+**
+**  Called:
+**     iauJd2cal    JD to Gregorian calendar
+**     iauDat       delta(AT) = TAI-UTC
+**     iauCal2jd    Gregorian calendar to JD
+**
+**  References:
+**
+**     McCarthy, D. D., Petit, G. (eds.), IERS Conventions (2003),
+**     IERS Technical Note No. 32, BKG (2004)
+**
+**     Explanatory Supplement to the Astronomical Almanac,
+**     P. Kenneth Seidelmann (ed), University Science Books (1992)
+**
+**  This revision:  2011 May 14
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   int big1;
+   int i, iy, im, id, js;
+   double duts, u1, u2, d1, dats1, d2, fd, dats2, ddats, us1, us2, du;
+
+
+/* UT1-UTC in seconds. */
+   duts = dut1;
+
+/* Put the two parts of the UT1 into big-first order. */
+   big1 = ( ut11 >= ut12 );
+   if ( big1 ) {
+      u1 = ut11;
+      u2 = ut12;
+   } else {
+      u1 = ut12;
+      u2 = ut11;
+   }
+
+/* See if the UT1 can possibly be in a leap-second day. */
+   d1 = u1;
+   dats1 = 0;
+   for ( i = -1; i <= 3; i++ ) {
+      d2 = u2 + (double) i;
+      if ( iauJd2cal(d1, d2, &iy, &im, &id, &fd) ) return -1;
+      js = iauDat(iy, im, id, 0.0, &dats2);
+      if ( js < 0 ) return -1;
+      if ( i == - 1 ) dats1 = dats2;
+      ddats = dats2 - dats1;
+      if ( fabs(ddats) >= 0.5 ) {
+
+      /* Yes, leap second nearby: ensure UT1-UTC is "before" value. */
+         if ( ddats * duts >= 0 ) duts -= ddats;
+
+      /* UT1 for the start of the UTC day that ends in a leap. */
+         if ( iauCal2jd(iy, im, id, &d1, &d2) ) return -1;
+         us1 = d1;
+         us2 = d2 - 1.0 + duts/DAYSEC;
+
+      /* Is the UT1 after this point? */
+         du = u1 - us1;
+         du += u2 - us2;
+         if ( du > 0 ) {
+
+         /* Yes:  fraction of the current UTC day that has elapsed. */
+            fd = du * DAYSEC / ( DAYSEC + ddats );
+
+         /* Ramp UT1-UTC to bring about SOFA's JD(UTC) convention. */
+            duts += ddats * ( fd <= 1.0 ? fd : 1.0 );
+         }
+
+      /* Done. */
+         break;
+      }
+      dats1 = dats2;
+   }
+
+/* Subtract the (possibly adjusted) UT1-UTC from UT1 to give UTC. */
+   u2 -= duts / DAYSEC;
+
+/* Result, safeguarding precision. */
+   if ( big1 ) {
+      *utc1 = u1;
+      *utc2 = u2;
+   } else {
+      *utc1 = u2;
+      *utc2 = u1;
+   }
+
+/* Status. */
+   return js;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+int iauUtctai(double utc1, double utc2, double *tai1, double *tai2)
+/*
+**  - - - - - - - - - -
+**   i a u U t c t a i
+**  - - - - - - - - - -
+**
+**  Time scale transformation:  Coordinated Universal Time, UTC, to
+**  International Atomic Time, TAI.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards of Fundamental Astronomy) software collection.
+**
+**  Status:  canonical.
+**
+**  Given:
+**     utc1,utc2  double   UTC as a 2-part quasi Julian Date (Notes 1-4)
+**
+**  Returned:
+**     tai1,tai2  double   TAI as a 2-part Julian Date (Note 5)
+**
+**  Returned (function value):
+**                int      status: +1 = dubious year (Note 3)
+**                                  0 = OK
+**                                 -1 = unacceptable date
+**
+**  Notes:
+**
+**  1) utc1+utc2 is quasi Julian Date (see Note 2), apportioned in any
+**     convenient way between the two arguments, for example where utc1
+**     is the Julian Day Number and utc2 is the fraction of a day.
+**
+**  2) JD cannot unambiguously represent UTC during a leap second unless
+**     special measures are taken.  The convention in the present
+**     function is that the JD day represents UTC days whether the
+**     length is 86399, 86400 or 86401 SI seconds.
+**
+**  3) The warning status "dubious year" flags UTCs that predate the
+**     introduction of the time scale and that are too far in the future
+**     to be trusted.  See iauDat  for further details.
+**
+**  4) The function iauDtf2d converts from calendar date and time of day
+**     into 2-part Julian Date, and in the case of UTC implements the
+**     leap-second-ambiguity convention described above.
+**
+**  5) The returned TAI1,TAI2 are such that their sum is the TAI Julian
+**     Date.
+**
+**  Called:
+**     iauJd2cal    JD to Gregorian calendar
+**     iauDat       delta(AT) = TAI-UTC
+**     iauCal2jd    Gregorian calendar to JD
+**
+**  References:
+**
+**     McCarthy, D. D., Petit, G. (eds.), IERS Conventions (2003),
+**     IERS Technical Note No. 32, BKG (2004)
+**
+**     Explanatory Supplement to the Astronomical Almanac,
+**     P. Kenneth Seidelmann (ed), University Science Books (1992)
+**
+**  This revision:  2010 September 10
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+**
+*/
+{
+   int big1;
+   int iy, im, id, js, iyt, imt, idt;
+   double u1, u2, fd, dats, fdt, datst, ddat, z1, z2, a2;
+
+
+/* Put the two parts of the UTC into big-first order. */
+   big1 = ( utc1 >= utc2 );
+   if ( big1 ) {
+      u1 = utc1;
+      u2 = utc2;
+   } else {
+      u1 = utc2;
+      u2 = utc1;
+   }
+
+/* Get TAI-UTC now. */
+   if ( iauJd2cal(u1, u2, &iy, &im, &id, &fd) ) return -1;
+   js = iauDat(iy, im, id, fd, &dats);
+   if ( js < 0 ) return -1;
+
+/* Get TAI-UTC tomorrow. */
+   if ( iauJd2cal(u1+1.5, u2-fd, &iyt, &imt, &idt, &fdt) ) return -1;
+   js = iauDat(iyt, imt, idt, fdt, &datst);
+   if ( js < 0 ) return -1;
+
+/* If today ends in a leap second, scale the fraction into SI days. */
+   ddat = datst - dats;
+   if ( fabs(ddat) > 0.5 ) fd += fd * ddat / DAYSEC;
+
+/* Today's calendar date to 2-part JD. */
+   if ( iauCal2jd(iy, im, id, &z1, &z2) ) return -1;
+
+/* Assemble the TAI result, preserving the UTC split and order. */
+   a2 = z1 - u1;
+   a2 += z2;
+   a2 += fd + dats / DAYSEC;
+   if ( big1 ) {
+      *tai1 = u1;
+      *tai2 = a2;
+   } else {
+      *tai1 = a2;
+      *tai2 = u1;
+   }
+
+/* Status. */
+   return js;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+int iauUtcut1(double utc1, double utc2, double dut1,
+              double *ut11, double *ut12)
+/*
+**  - - - - - - - - - -
+**   i a u U t c u t 1
+**  - - - - - - - - - -
+**
+**  Time scale transformation:  Coordinated Universal Time, UTC, to
+**  Universal Time, UT1.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards of Fundamental Astronomy) software collection.
+**
+**  Status:  canonical.
+**
+**  Given:
+**     utc1,utc2  double   UTC as a 2-part quasi Julian Date (Notes 1-4)
+**     dut1       double   Delta UT1 = UT1-UTC in seconds (Note 5)
+**
+**  Returned:
+**     ut11,ut12  double   UT1 as a 2-part Julian Date (Note 6)
+**
+**  Returned (function value):
+**                int      status: +1 = dubious year (Note 7)
+**                                  0 = OK
+**                                 -1 = unacceptable date
+**
+**  Notes:
+**
+**  1) utc1+utc2 is quasi Julian Date (see Note 2), apportioned in any
+**     convenient way between the two arguments, for example where utc1
+**     is the Julian Day Number and utc2 is the fraction of a day.
+**
+**  2) JD cannot unambiguously represent UTC during a leap second unless
+**     special measures are taken.  The convention in the present
+**     function is that the JD day represents UTC days whether the
+**     length is 86399, 86400 or 86401 SI seconds.
+**
+**  3) The warning status "dubious year" flags UTCs that predate the
+**     introduction of the time scale and that are too far in the future
+**     to be trusted.  See iauDat  for further details.
+**
+**  4) The function iauDtf2d  converts from calendar date and time of
+**     day into 2-part Julian Date, and in the case of UTC implements
+**     the leap-second-ambiguity convention described above.
+**
+**  5) Delta UT1 can be obtained from tabulations provided by the
+**     International Earth Rotation and Reference Systems Service.  It
+**     It is the caller's responsibility to supply a DUT argument
+**     containing the UT1-UTC value that matches the given UTC.
+**
+**  6) The returned ut11,ut12 are such that their sum is the UT1 Julian
+**     Date.
+**
+**  7) The warning status "dubious year" flags UTCs that predate the
+**     introduction of the time scale and that are too far in the future
+**     to be trusted.  See iauDat for further details.
+**
+**  References:
+**
+**     McCarthy, D. D., Petit, G. (eds.), IERS Conventions (2003),
+**     IERS Technical Note No. 32, BKG (2004)
+**
+**     Explanatory Supplement to the Astronomical Almanac,
+**     P. Kenneth Seidelmann (ed), University Science Books (1992)
+**
+**  Called:
+**     iauJd2cal    JD to Gregorian calendar
+**     iauDat       delta(AT) = TAI-UTC
+**     iauUtctai    UTC to TAI
+**     iauTaiut1    TAI to UT1
+**
+**  This revision:  2010 May 16
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   int iy, im, id, js, jw;
+   double w, dat, dta, tai1, tai2;
+
+
+/* Look up TAI-UTC. */
+   if ( iauJd2cal(utc1, utc2, &iy, &im, &id, &w) ) return -1;
+   js = iauDat ( iy, im, id, 0.0, &dat);
+   if ( js < 0 ) return -1;
+
+/* Form UT1-TAI. */
+   dta = dut1 - dat;
+
+/* UTC to TAI to UT1. */
+   jw = iauUtctai(utc1, utc2, &tai1, &tai2);
+   if ( jw < 0 ) {
+      return -1;
+   } else if ( jw > 0 ) {
+      js = jw;
+   }
+   if ( iauTaiut1(tai1, tai2, dta, ut11, ut12) ) return -1;
+
+/* Status. */
+   return js;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauXy06(double date1, double date2, double *x, double *y)
+/*
+**  - - - - - - - -
+**   i a u X y 0 6
+**  - - - - - - - -
+**
+**  X,Y coordinates of celestial intermediate pole from series based
+**  on IAU 2006 precession and IAU 2000A nutation.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  canonical model.
+**
+**  Given:
+**     date1,date2  double     TT as a 2-part Julian Date (Note 1)
+**
+**  Returned:
+**     x,y          double     CIP X,Y coordinates (Note 2)
+**
+**  Notes:
+**
+**  1) The TT date date1+date2 is a Julian Date, apportioned in any
+**     convenient way between the two arguments.  For example,
+**     JD(TT)=2450123.7 could be expressed in any of these ways,
+**     among others:
+**
+**            date1          date2
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in
+**     cases where the loss of several decimal digits of resolution
+**     is acceptable.  The J2000 method is best matched to the way
+**     the argument is handled internally and will deliver the
+**     optimum resolution.  The MJD method and the date & time methods
+**     are both good compromises between resolution and convenience.
+**
+**  2) The X,Y coordinates are those of the unit vector towards the
+**     celestial intermediate pole.  They represent the combined effects
+**     of frame bias, precession and nutation.
+**
+**  3) The fundamental arguments used are as adopted in IERS Conventions
+**     (2003) and are from Simon et al. (1994) and Souchay et al.
+**     (1999).
+**
+**  4) This is an alternative to the angles-based method, via the SOFA
+**     function iauFw2xy and as used in iauXys06a for example.  The two
+**     methods agree at the 1 microarcsecond level (at present), a
+**     negligible amount compared with the intrinsic accuracy of the
+**     models.  However, it would be unwise to mix the two methods
+**     (angles-based and series-based) in a single application.
+**
+**  Called:
+**     iauFal03     mean anomaly of the Moon
+**     iauFalp03    mean anomaly of the Sun
+**     iauFaf03     mean argument of the latitude of the Moon
+**     iauFad03     mean elongation of the Moon from the Sun
+**     iauFaom03    mean longitude of the Moon's ascending node
+**     iauFame03    mean longitude of Mercury
+**     iauFave03    mean longitude of Venus
+**     iauFae03     mean longitude of Earth
+**     iauFama03    mean longitude of Mars
+**     iauFaju03    mean longitude of Jupiter
+**     iauFasa03    mean longitude of Saturn
+**     iauFaur03    mean longitude of Uranus
+**     iauFane03    mean longitude of Neptune
+**     iauFapa03    general accumulated precession in longitude
+**
+**  References:
+**
+**     Capitaine, N., Wallace, P.T. & Chapront, J., 2003,
+**     Astron.Astrophys., 412, 567
+**
+**     Capitaine, N. & Wallace, P.T., 2006, Astron.Astrophys. 450, 855
+**
+**     McCarthy, D. D., Petit, G. (eds.), 2004, IERS Conventions (2003),
+**     IERS Technical Note No. 32, BKG
+**
+**     Simon, J.L., Bretagnon, P., Chapront, J., Chapront-Touze, M.,
+**     Francou, G. & Laskar, J., Astron.Astrophys., 1994, 282, 663
+**
+**     Souchay, J., Loysel, B., Kinoshita, H., Folgueira, M., 1999,
+**     Astron.Astrophys.Supp.Ser. 135, 111
+**
+**     Wallace, P.T. & Capitaine, N., 2006, Astron.Astrophys. 459, 981
+**
+**  This revision:  2009 October 16
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+
+/* Maximum power of T in the polynomials for X and Y */
+#define MAXPT (5)
+
+/* Polynomial coefficients (arcsec, X then Y). */
+   static const double xyp[2][MAXPT+1] = {
+
+      {    -0.016617,
+         2004.191898,
+           -0.4297829,
+           -0.19861834,
+            0.000007578,
+            0.0000059285
+      },
+      {    -0.006951,
+           -0.025896,
+          -22.4072747,
+            0.00190059,
+            0.001112526,
+            0.0000001358
+      }
+   };
+
+/* Fundamental-argument multipliers:  luni-solar terms */
+   static const int mfals[][5] = {
+
+   /* 1-10 */
+      {  0,   0,   0,   0,   1 },
+      {  0,   0,   2,  -2,   2 },
+      {  0,   0,   2,   0,   2 },
+      {  0,   0,   0,   0,   2 },
+      {  0,   1,   0,   0,   0 },
+      {  0,   1,   2,  -2,   2 },
+      {  1,   0,   0,   0,   0 },
+      {  0,   0,   2,   0,   1 },
+      {  1,   0,   2,   0,   2 },
+      {  0,   1,  -2,   2,  -2 },
+
+   /* 11-20 */
+      {  0,   0,   2,  -2,   1 },
+      {  1,   0,  -2,   0,  -2 },
+      {  1,   0,   0,  -2,   0 },
+      {  1,   0,   0,   0,   1 },
+      {  1,   0,   0,   0,  -1 },
+      {  1,   0,  -2,  -2,  -2 },
+      {  1,   0,   2,   0,   1 },
+      {  2,   0,  -2,   0,  -1 },
+      {  0,   0,   0,   2,   0 },
+      {  0,   0,   2,   2,   2 },
+
+   /* 21-30 */
+      {  2,   0,   0,  -2,   0 },
+      {  0,   2,  -2,   2,  -2 },
+      {  2,   0,   2,   0,   2 },
+      {  1,   0,   2,  -2,   2 },
+      {  1,   0,  -2,   0,  -1 },
+      {  2,   0,   0,   0,   0 },
+      {  0,   0,   2,   0,   0 },
+      {  0,   1,   0,   0,   1 },
+      {  1,   0,   0,  -2,  -1 },
+      {  0,   2,   2,  -2,   2 },
+
+   /* 31-40 */
+      {  0,   0,   2,  -2,   0 },
+      {  1,   0,   0,  -2,   1 },
+      {  0,   1,   0,   0,  -1 },
+      {  0,   2,   0,   0,   0 },
+      {  1,   0,  -2,  -2,  -1 },
+      {  1,   0,   2,   2,   2 },
+      {  0,   1,   2,   0,   2 },
+      {  2,   0,  -2,   0,   0 },
+      {  0,   0,   2,   2,   1 },
+      {  0,   1,  -2,   0,  -2 },
+
+   /* 41-50 */
+      {  0,   0,   0,   2,   1 },
+      {  1,   0,   2,  -2,   1 },
+      {  2,   0,   0,  -2,  -1 },
+      {  2,   0,   2,  -2,   2 },
+      {  2,   0,   2,   0,   1 },
+      {  0,   0,   0,   2,  -1 },
+      {  0,   1,  -2,   2,  -1 },
+      {  1,   1,   0,  -2,   0 },
+      {  2,   0,   0,  -2,   1 },
+      {  1,   0,   0,   2,   0 },
+
+   /* 51-60 */
+      {  0,   1,   2,  -2,   1 },
+      {  1,  -1,   0,   0,   0 },
+      {  0,   1,  -1,   1,  -1 },
+      {  2,   0,  -2,   0,  -2 },
+      {  0,   1,   0,  -2,   0 },
+      {  1,   0,   0,  -1,   0 },
+      {  3,   0,   2,   0,   2 },
+      {  0,   0,   0,   1,   0 },
+      {  1,  -1,   2,   0,   2 },
+      {  1,   1,  -2,  -2,  -2 },
+
+   /* 61-70 */
+      {  1,   0,  -2,   0,   0 },
+      {  2,   0,   0,   0,  -1 },
+      {  0,   1,  -2,  -2,  -2 },
+      {  1,   1,   2,   0,   2 },
+      {  2,   0,   0,   0,   1 },
+      {  1,   1,   0,   0,   0 },
+      {  1,   0,  -2,   2,  -1 },
+      {  1,   0,   2,   0,   0 },
+      {  1,  -1,   0,  -1,   0 },
+      {  1,   0,   0,   0,   2 },
+
+   /* 71-80 */
+      {  1,   0,  -1,   0,  -1 },
+      {  0,   0,   2,   1,   2 },
+      {  1,   0,  -2,  -4,  -2 },
+      {  1,  -1,   0,  -1,  -1 },
+      {  1,   0,   2,   2,   1 },
+      {  0,   2,  -2,   2,  -1 },
+      {  1,   0,   0,   0,  -2 },
+      {  2,   0,  -2,  -2,  -2 },
+      {  1,   1,   2,  -2,   2 },
+      {  2,   0,  -2,  -4,  -2 },
+
+   /* 81-90 */
+      {  1,   0,  -4,   0,  -2 },
+      {  2,   0,   2,  -2,   1 },
+      {  1,   0,   0,  -1,  -1 },
+      {  2,   0,   2,   2,   2 },
+      {  3,   0,   0,   0,   0 },
+      {  1,   0,   0,   2,   1 },
+      {  0,   0,   2,  -2,  -1 },
+      {  3,   0,   2,  -2,   2 },
+      {  0,   0,   4,  -2,   2 },
+      {  1,   0,   0,  -4,   0 },
+
+   /* 91-100 */
+      {  0,   1,   2,   0,   1 },
+      {  2,   0,   0,  -4,   0 },
+      {  1,   1,   0,  -2,  -1 },
+      {  2,   0,  -2,   0,   1 },
+      {  0,   0,   2,   0,  -1 },
+      {  0,   1,  -2,   0,  -1 },
+      {  0,   1,   0,   0,   2 },
+      {  0,   0,   2,  -1,   2 },
+      {  0,   0,   2,   4,   2 },
+      {  2,   1,   0,  -2,   0 },
+
+   /* 101-110 */
+      {  1,   1,   0,  -2,   1 },
+      {  1,  -1,   0,  -2,   0 },
+      {  1,  -1,   0,  -1,  -2 },
+      {  1,  -1,   0,   0,   1 },
+      {  0,   1,  -2,   2,   0 },
+      {  0,   1,   0,   0,  -2 },
+      {  1,  -1,   2,   2,   2 },
+      {  1,   0,   0,   2,  -1 },
+      {  1,  -1,  -2,  -2,  -2 },
+      {  3,   0,   2,   0,   1 },
+
+   /* 111-120 */
+      {  0,   1,   2,   2,   2 },
+      {  1,   0,   2,  -2,   0 },
+      {  1,   1,  -2,  -2,  -1 },
+      {  1,   0,   2,  -4,   1 },
+      {  0,   1,  -2,  -2,  -1 },
+      {  2,  -1,   2,   0,   2 },
+      {  0,   0,   0,   2,   2 },
+      {  1,  -1,   2,   0,   1 },
+      {  1,  -1,  -2,   0,  -2 },
+      {  0,   1,   0,   2,   0 },
+
+   /* 121-130 */
+      {  0,   1,   2,  -2,   0 },
+      {  0,   0,   0,   1,   1 },
+      {  1,   0,  -2,  -2,   0 },
+      {  0,   3,   2,  -2,   2 },
+      {  2,   1,   2,   0,   2 },
+      {  1,   1,   0,   0,   1 },
+      {  2,   0,   0,   2,   0 },
+      {  1,   1,   2,   0,   1 },
+      {  1,   0,   0,  -2,  -2 },
+      {  1,   0,  -2,   2,   0 },
+
+   /* 131-140 */
+      {  1,   0,  -1,   0,  -2 },
+      {  0,   1,   0,  -2,   1 },
+      {  0,   1,   0,   1,   0 },
+      {  0,   0,   0,   1,  -1 },
+      {  1,   0,  -2,   2,  -2 },
+      {  1,  -1,   0,   0,  -1 },
+      {  0,   0,   0,   4,   0 },
+      {  1,  -1,   0,   2,   0 },
+      {  1,   0,   2,   1,   2 },
+      {  1,   0,   2,  -1,   2 },
+
+   /* 141-150 */
+      {  0,   0,   2,   1,   1 },
+      {  1,   0,   0,  -2,   2 },
+      {  1,   0,  -2,   0,   1 },
+      {  1,   0,  -2,  -4,  -1 },
+      {  0,   0,   2,   2,   0 },
+      {  1,   1,   2,  -2,   1 },
+      {  1,   0,  -2,   1,  -1 },
+      {  0,   0,   1,   0,   1 },
+      {  2,   0,  -2,  -2,  -1 },
+      {  4,   0,   2,   0,   2 },
+
+   /* 151-160 */
+      {  2,  -1,   0,   0,   0 },
+      {  2,   1,   2,  -2,   2 },
+      {  0,   1,   2,   1,   2 },
+      {  1,   0,   4,  -2,   2 },
+      {  1,   1,   0,   0,  -1 },
+      {  2,   0,   2,   0,   0 },
+      {  2,   0,  -2,  -4,  -1 },
+      {  1,   0,  -1,   0,   0 },
+      {  1,   0,   0,   1,   0 },
+      {  0,   1,   0,   2,   1 },
+
+   /* 161-170 */
+      {  1,   0,  -4,   0,  -1 },
+      {  1,   0,   0,  -4,  -1 },
+      {  2,   0,   2,   2,   1 },
+      {  2,   1,   0,   0,   0 },
+      {  0,   0,   2,  -3,   2 },
+      {  1,   2,   0,  -2,   0 },
+      {  0,   3,   0,   0,   0 },
+      {  0,   0,   4,   0,   2 },
+      {  0,   0,   2,  -4,   1 },
+      {  2,   0,   0,  -2,  -2 },
+
+   /* 171-180 */
+      {  1,   1,  -2,  -4,  -2 },
+      {  0,   1,   0,  -2,  -1 },
+      {  0,   0,   0,   4,   1 },
+      {  3,   0,   2,  -2,   1 },
+      {  1,   0,   2,   4,   2 },
+      {  1,   1,  -2,   0,  -2 },
+      {  0,   0,   4,  -2,   1 },
+      {  2,  -2,   0,  -2,   0 },
+      {  2,   1,   0,  -2,  -1 },
+      {  0,   2,   0,  -2,   0 },
+
+   /* 181-190 */
+      {  1,   0,   0,  -1,   1 },
+      {  1,   1,   2,   2,   2 },
+      {  3,   0,   0,   0,  -1 },
+      {  2,   0,   0,  -4,  -1 },
+      {  3,   0,   2,   2,   2 },
+      {  0,   0,   2,   4,   1 },
+      {  0,   2,  -2,  -2,  -2 },
+      {  1,  -1,   0,  -2,  -1 },
+      {  0,   0,   2,  -1,   1 },
+      {  2,   0,   0,   2,   1 },
+
+   /* 191-200 */
+      {  1,  -1,  -2,   2,  -1 },
+      {  0,   0,   0,   2,  -2 },
+      {  2,   0,   0,  -4,   1 },
+      {  1,   0,   0,  -4,   1 },
+      {  2,   0,   2,  -4,   1 },
+      {  4,   0,   2,  -2,   2 },
+      {  2,   1,  -2,   0,  -1 },
+      {  2,   1,  -2,  -4,  -2 },
+      {  3,   0,   0,  -4,   0 },
+      {  1,  -1,   2,   2,   1 },
+
+   /* 201-210 */
+      {  1,  -1,  -2,   0,  -1 },
+      {  0,   2,   0,   0,   1 },
+      {  1,   2,  -2,  -2,  -2 },
+      {  1,   1,   0,  -4,   0 },
+      {  2,   0,   0,  -2,   2 },
+      {  0,   2,   2,  -2,   1 },
+      {  1,   0,   2,   0,  -1 },
+      {  2,   1,   0,  -2,   1 },
+      {  2,  -1,  -2,   0,  -1 },
+      {  1,  -1,  -2,  -2,  -1 },
+
+   /* 211-220 */
+      {  0,   1,  -2,   1,  -2 },
+      {  1,   0,  -4,   2,  -2 },
+      {  0,   1,   2,   2,   1 },
+      {  3,   0,   0,   0,   1 },
+      {  2,  -1,   2,   2,   2 },
+      {  0,   1,  -2,  -4,  -2 },
+      {  1,   0,  -2,  -3,  -2 },
+      {  2,   0,   0,   0,   2 },
+      {  1,  -1,   0,  -2,  -2 },
+      {  2,   0,  -2,   2,  -1 },
+
+   /* 221-230 */
+      {  0,   2,  -2,   0,  -2 },
+      {  3,   0,  -2,   0,  -1 },
+      {  2,  -1,   2,   0,   1 },
+      {  1,   0,  -2,  -1,  -2 },
+      {  0,   0,   2,   0,   3 },
+      {  2,   0,  -4,   0,  -2 },
+      {  2,   1,   0,  -4,   0 },
+      {  1,   1,  -2,   1,  -1 },
+      {  0,   2,   2,   0,   2 },
+      {  1,  -1,   2,  -2,   2 },
+
+   /* 231-240 */
+      {  1,  -1,   0,  -2,   1 },
+      {  2,   1,   2,   0,   1 },
+      {  1,   0,   2,  -4,   2 },
+      {  1,   1,  -2,   0,  -1 },
+      {  1,   1,   0,   2,   0 },
+      {  1,   0,   0,  -3,   0 },
+      {  2,   0,   2,  -1,   2 },
+      {  0,   2,   0,   0,  -1 },
+      {  2,  -1,   0,  -2,   0 },
+      {  4,   0,   0,   0,   0 },
+
+   /* 241-250 */
+      {  2,   1,  -2,  -2,  -2 },
+      {  0,   2,  -2,   2,   0 },
+      {  1,   0,   2,   1,   1 },
+      {  1,   0,  -1,   0,  -3 },
+      {  3,  -1,   2,   0,   2 },
+      {  2,   0,   2,  -2,   0 },
+      {  1,  -2,   0,   0,   0 },
+      {  2,   0,   0,   0,  -2 },
+      {  1,   0,   0,   4,   0 },
+      {  0,   1,   0,   1,   1 },
+
+   /* 251-260 */
+      {  1,   0,   2,   2,   0 },
+      {  0,   1,   0,   2,  -1 },
+      {  0,   1,   0,   1,  -1 },
+      {  0,   0,   2,  -2,   3 },
+      {  3,   1,   2,   0,   2 },
+      {  1,   1,   2,   1,   2 },
+      {  1,   1,  -2,   2,  -1 },
+      {  2,  -1,   2,  -2,   2 },
+      {  1,  -2,   2,   0,   2 },
+      {  1,   0,   2,  -4,   0 },
+
+   /* 261-270 */
+      {  0,   0,   1,   0,   0 },
+      {  1,   0,   2,  -3,   1 },
+      {  1,  -2,   0,  -2,   0 },
+      {  2,   0,   0,   2,  -1 },
+      {  1,   1,   2,  -4,   1 },
+      {  4,   0,   2,   0,   1 },
+      {  0,   1,   2,   1,   1 },
+      {  1,   2,   2,  -2,   2 },
+      {  2,   0,   2,   1,   2 },
+      {  2,   1,   2,  -2,   1 },
+
+   /* 271-280 */
+      {  1,   0,   2,  -1,   1 },
+      {  1,   0,   4,  -2,   1 },
+      {  1,  -1,   2,  -2,   1 },
+      {  0,   1,   0,  -4,   0 },
+      {  3,   0,  -2,  -2,  -2 },
+      {  0,   0,   4,  -4,   2 },
+      {  2,   0,  -4,  -2,  -2 },
+      {  2,  -2,   0,  -2,  -1 },
+      {  1,   0,   2,  -2,  -1 },
+      {  2,   0,  -2,  -6,  -2 },
+
+   /* 281-290 */
+      {  1,   0,  -2,   1,  -2 },
+      {  1,   0,  -2,   2,   1 },
+      {  1,  -1,   0,   2,  -1 },
+      {  1,   0,  -2,   1,   0 },
+      {  2,  -1,   0,  -2,   1 },
+      {  1,  -1,   0,   2,   1 },
+      {  2,   0,  -2,  -2,   0 },
+      {  1,   0,   2,  -3,   2 },
+      {  0,   0,   0,   4,  -1 },
+      {  2,  -1,   0,   0,   1 },
+
+   /* 291-300 */
+      {  2,   0,   4,  -2,   2 },
+      {  0,   0,   2,   3,   2 },
+      {  0,   1,   4,  -2,   2 },
+      {  0,   1,  -2,   2,   1 },
+      {  1,   1,   0,   2,   1 },
+      {  1,   0,   0,   4,   1 },
+      {  0,   0,   4,   0,   1 },
+      {  2,   0,   0,  -3,   0 },
+      {  1,   0,   0,  -1,  -2 },
+      {  1,  -2,  -2,  -2,  -2 },
+
+   /* 301-310 */
+      {  3,   0,   0,   2,   0 },
+      {  2,   0,   2,  -4,   2 },
+      {  1,   1,  -2,  -4,  -1 },
+      {  1,   0,  -2,  -6,  -2 },
+      {  2,  -1,   0,   0,  -1 },
+      {  2,  -1,   0,   2,   0 },
+      {  0,   1,   2,  -2,  -1 },
+      {  1,   1,   0,   1,   0 },
+      {  1,   2,   0,  -2,  -1 },
+      {  1,   0,   0,   1,  -1 },
+
+   /* 311-320 */
+      {  0,   0,   1,   0,   2 },
+      {  3,   1,   2,  -2,   2 },
+      {  1,   0,  -4,  -2,  -2 },
+      {  1,   0,   2,   4,   1 },
+      {  1,  -2,   2,   2,   2 },
+      {  1,  -1,  -2,  -4,  -2 },
+      {  0,   0,   2,  -4,   2 },
+      {  0,   0,   2,  -3,   1 },
+      {  2,   1,  -2,   0,   0 },
+      {  3,   0,  -2,  -2,  -1 },
+
+   /* 321-330 */
+      {  2,   0,   2,   4,   2 },
+      {  0,   0,   0,   0,   3 },
+      {  2,  -1,  -2,  -2,  -2 },
+      {  2,   0,   0,  -1,   0 },
+      {  3,   0,   2,  -4,   2 },
+      {  2,   1,   2,   2,   2 },
+      {  0,   0,   3,   0,   3 },
+      {  1,   1,   2,   2,   1 },
+      {  2,   1,   0,   0,  -1 },
+      {  1,   2,   0,  -2,   1 },
+
+   /* 331-340 */
+      {  3,   0,   2,   2,   1 },
+      {  1,  -1,  -2,   2,  -2 },
+      {  1,   1,   0,  -1,   0 },
+      {  1,   2,   0,   0,   0 },
+      {  1,   0,   4,   0,   2 },
+      {  1,  -1,   2,   4,   2 },
+      {  2,   1,   0,   0,   1 },
+      {  1,   0,   0,   2,   2 },
+      {  1,  -1,  -2,   2,   0 },
+      {  0,   2,  -2,  -2,  -1 },
+
+   /* 341-350 */
+      {  2,   0,  -2,   0,   2 },
+      {  5,   0,   2,   0,   2 },
+      {  3,   0,  -2,  -6,  -2 },
+      {  1,  -1,   2,  -1,   2 },
+      {  3,   0,   0,  -4,  -1 },
+      {  1,   0,   0,   1,   1 },
+      {  1,   0,  -4,   2,  -1 },
+      {  0,   1,   2,  -4,   1 },
+      {  1,   2,   2,   0,   2 },
+      {  0,   1,   0,  -2,  -2 },
+
+   /* 351-360 */
+      {  0,   0,   2,  -1,   0 },
+      {  1,   0,   1,   0,   1 },
+      {  0,   2,   0,  -2,   1 },
+      {  3,   0,   2,   0,   0 },
+      {  1,   1,  -2,   1,   0 },
+      {  2,   1,  -2,  -4,  -1 },
+      {  3,  -1,   0,   0,   0 },
+      {  2,  -1,  -2,   0,   0 },
+      {  4,   0,   2,  -2,   1 },
+      {  2,   0,  -2,   2,   0 },
+
+   /* 361-370 */
+      {  1,   1,   2,  -2,   0 },
+      {  1,   0,  -2,   4,  -1 },
+      {  1,   0,  -2,  -2,   1 },
+      {  2,   0,   2,  -4,   0 },
+      {  1,   1,   0,  -2,  -2 },
+      {  1,   1,  -2,  -2,   0 },
+      {  1,   0,   1,  -2,   1 },
+      {  2,  -1,  -2,  -4,  -2 },
+      {  3,   0,  -2,   0,  -2 },
+      {  0,   1,  -2,  -2,   0 },
+
+   /* 371-380 */
+      {  3,   0,   0,  -2,  -1 },
+      {  1,   0,  -2,  -3,  -1 },
+      {  0,   1,   0,  -4,  -1 },
+      {  1,  -2,   2,  -2,   1 },
+      {  0,   1,  -2,   1,  -1 },
+      {  1,  -1,   0,   0,   2 },
+      {  2,   0,   0,   1,   0 },
+      {  1,  -2,   0,   2,   0 },
+      {  1,   2,  -2,  -2,  -1 },
+      {  0,   0,   4,  -4,   1 },
+
+   /* 381-390 */
+      {  0,   1,   2,   4,   2 },
+      {  0,   1,  -4,   2,  -2 },
+      {  3,   0,  -2,   0,   0 },
+      {  2,  -1,   2,   2,   1 },
+      {  0,   1,  -2,  -4,  -1 },
+      {  4,   0,   2,   2,   2 },
+      {  2,   0,  -2,  -3,  -2 },
+      {  2,   0,   0,  -6,   0 },
+      {  1,   0,   2,   0,   3 },
+      {  3,   1,   0,   0,   0 },
+
+   /* 391-400 */
+      {  3,   0,   0,  -4,   1 },
+      {  1,  -1,   2,   0,   0 },
+      {  1,  -1,   0,  -4,   0 },
+      {  2,   0,  -2,   2,  -2 },
+      {  1,   1,   0,  -2,   2 },
+      {  4,   0,   0,  -2,   0 },
+      {  2,   2,   0,  -2,   0 },
+      {  0,   1,   2,   0,   0 },
+      {  1,   1,   0,  -4,   1 },
+      {  1,   0,   0,  -4,  -2 },
+
+   /* 401-410 */
+      {  0,   0,   0,   1,   2 },
+      {  3,   0,   0,   2,   1 },
+      {  1,   1,   0,  -4,  -1 },
+      {  0,   0,   2,   2,  -1 },
+      {  1,   1,   2,   0,   0 },
+      {  1,  -1,   2,  -4,   1 },
+      {  1,   1,   0,   0,   2 },
+      {  0,   0,   2,   6,   2 },
+      {  4,   0,  -2,  -2,  -1 },
+      {  2,   1,   0,  -4,  -1 },
+
+   /* 411-420 */
+      {  0,   0,   0,   3,   1 },
+      {  1,  -1,  -2,   0,   0 },
+      {  0,   0,   2,   1,   0 },
+      {  1,   0,   0,   2,  -2 },
+      {  3,  -1,   2,   2,   2 },
+      {  3,  -1,   2,  -2,   2 },
+      {  1,   0,   0,  -1,   2 },
+      {  1,  -2,   2,  -2,   2 },
+      {  0,   1,   0,   2,   2 },
+      {  0,   1,  -2,  -1,  -2 },
+
+   /* 421-430 */
+      {  1,   1,  -2,   0,   0 },
+      {  0,   2,   2,  -2,   0 },
+      {  3,  -1,  -2,  -1,  -2 },
+      {  1,   0,   0,  -6,   0 },
+      {  1,   0,  -2,  -4,   0 },
+      {  2,   1,   0,  -4,   1 },
+      {  2,   0,   2,   0,  -1 },
+      {  2,   0,  -4,   0,  -1 },
+      {  0,   0,   3,   0,   2 },
+      {  2,   1,  -2,  -2,  -1 },
+
+   /* 431-440 */
+      {  1,  -2,   0,   0,   1 },
+      {  2,  -1,   0,  -4,   0 },
+      {  0,   0,   0,   3,   0 },
+      {  5,   0,   2,  -2,   2 },
+      {  1,   2,  -2,  -4,  -2 },
+      {  1,   0,   4,  -4,   2 },
+      {  0,   0,   4,  -1,   2 },
+      {  3,   1,   0,  -4,   0 },
+      {  3,   0,   0,  -6,   0 },
+      {  2,   0,   0,   2,   2 },
+
+   /* 441-450 */
+      {  2,  -2,   2,   0,   2 },
+      {  1,   0,   0,  -3,   1 },
+      {  1,  -2,  -2,   0,  -2 },
+      {  1,  -1,  -2,  -3,  -2 },
+      {  0,   0,   2,  -2,  -2 },
+      {  2,   0,  -2,  -4,   0 },
+      {  1,   0,  -4,   0,   0 },
+      {  0,   1,   0,  -1,   0 },
+      {  4,   0,   0,   0,  -1 },
+      {  3,   0,   2,  -1,   2 },
+
+   /* 451-460 */
+      {  3,  -1,   2,   0,   1 },
+      {  2,   0,   2,  -1,   1 },
+      {  1,   2,   2,  -2,   1 },
+      {  1,   1,   0,   2,  -1 },
+      {  0,   2,   2,   0,   1 },
+      {  3,   1,   2,   0,   1 },
+      {  1,   1,   2,   1,   1 },
+      {  1,   1,   0,  -1,   1 },
+      {  1,  -2,   0,  -2,  -1 },
+      {  4,   0,   0,  -4,   0 },
+
+   /* 461-470 */
+      {  2,   1,   0,   2,   0 },
+      {  1,  -1,   0,   4,   0 },
+      {  0,   1,   0,  -2,   2 },
+      {  0,   0,   2,   0,  -2 },
+      {  1,   0,  -1,   0,   1 },
+      {  3,   0,   2,  -2,   0 },
+      {  2,   0,   2,   2,   0 },
+      {  1,   2,   0,  -4,   0 },
+      {  1,  -1,   0,  -3,   0 },
+      {  0,   1,   0,   4,   0 },
+
+   /* 471 - 480 */
+      {  0,   1,  -2,   0,   0 },
+      {  2,   2,   2,  -2,   2 },
+      {  0,   0,   0,   1,  -2 },
+      {  0,   2,  -2,   0,  -1 },
+      {  4,   0,   2,  -4,   2 },
+      {  2,   0,  -4,   2,  -2 },
+      {  2,  -1,  -2,   0,  -2 },
+      {  1,   1,   4,  -2,   2 },
+      {  1,   1,   2,  -4,   2 },
+      {  1,   0,   2,   3,   2 },
+
+   /* 481-490 */
+      {  1,   0,   0,   4,  -1 },
+      {  0,   0,   0,   4,   2 },
+      {  2,   0,   0,   4,   0 },
+      {  1,   1,  -2,   2,   0 },
+      {  2,   1,   2,   1,   2 },
+      {  2,   1,   2,  -4,   1 },
+      {  2,   0,   2,   1,   1 },
+      {  2,   0,  -4,  -2,  -1 },
+      {  2,   0,  -2,  -6,  -1 },
+      {  2,  -1,   2,  -1,   2 },
+
+   /* 491-500 */
+      {  1,  -2,   2,   0,   1 },
+      {  1,  -2,   0,  -2,   1 },
+      {  1,  -1,   0,  -4,  -1 },
+      {  0,   2,   2,   2,   2 },
+      {  0,   2,  -2,  -4,  -2 },
+      {  0,   1,   2,   3,   2 },
+      {  0,   1,   0,  -4,   1 },
+      {  3,   0,   0,  -2,   1 },
+      {  2,   1,  -2,   0,   1 },
+      {  2,   0,   4,  -2,   1 },
+
+   /* 501-510 */
+      {  2,   0,   0,  -3,  -1 },
+      {  2,  -2,   0,  -2,   1 },
+      {  2,  -1,   2,  -2,   1 },
+      {  1,   0,   0,  -6,  -1 },
+      {  1,  -2,   0,   0,  -1 },
+      {  1,  -2,  -2,  -2,  -1 },
+      {  0,   1,   4,  -2,   1 },
+      {  0,   0,   2,   3,   1 },
+      {  2,  -1,   0,  -1,   0 },
+      {  1,   3,   0,  -2,   0 },
+
+   /* 511-520 */
+      {  0,   3,   0,  -2,   0 },
+      {  2,  -2,   2,  -2,   2 },
+      {  0,   0,   4,  -2,   0 },
+      {  4,  -1,   2,   0,   2 },
+      {  2,   2,  -2,  -4,  -2 },
+      {  4,   1,   2,   0,   2 },
+      {  4,  -1,  -2,  -2,  -2 },
+      {  2,   1,   0,  -2,  -2 },
+      {  2,   1,  -2,  -6,  -2 },
+      {  2,   0,   0,  -1,   1 },
+
+   /* 521-530 */
+      {  2,  -1,  -2,   2,  -1 },
+      {  1,   1,  -2,   2,  -2 },
+      {  1,   1,  -2,  -3,  -2 },
+      {  1,   0,   3,   0,   3 },
+      {  1,   0,  -2,   1,   1 },
+      {  1,   0,  -2,   0,   2 },
+      {  1,  -1,   2,   1,   2 },
+      {  1,  -1,   0,   0,  -2 },
+      {  1,  -1,  -4,   2,  -2 },
+      {  0,   3,  -2,  -2,  -2 },
+
+   /* 531-540 */
+      {  0,   1,   0,   4,   1 },
+      {  0,   0,   4,   2,   2 },
+      {  3,   0,  -2,  -2,   0 },
+      {  2,  -2,   0,   0,   0 },
+      {  1,   1,   2,  -4,   0 },
+      {  1,   1,   0,  -3,   0 },
+      {  1,   0,   2,  -3,   0 },
+      {  1,  -1,   2,  -2,   0 },
+      {  0,   2,   0,   2,   0 },
+      {  0,   0,   2,   4,   0 },
+
+   /* 541-550 */
+      {  1,   0,   1,   0,   0 },
+      {  3,   1,   2,  -2,   1 },
+      {  3,   0,   4,  -2,   2 },
+      {  3,   0,   2,   1,   2 },
+      {  3,   0,   0,   2,  -1 },
+      {  3,   0,   0,   0,   2 },
+      {  3,   0,  -2,   2,  -1 },
+      {  2,   0,   4,  -4,   2 },
+      {  2,   0,   2,  -3,   2 },
+      {  2,   0,   0,   4,   1 },
+
+   /* 551-560 */
+      {  2,   0,   0,  -3,   1 },
+      {  2,   0,  -4,   2,  -1 },
+      {  2,   0,  -2,  -2,   1 },
+      {  2,  -2,   2,   2,   2 },
+      {  2,  -2,   0,  -2,  -2 },
+      {  2,  -1,   0,   2,   1 },
+      {  2,  -1,   0,   2,  -1 },
+      {  1,   1,   2,   4,   2 },
+      {  1,   1,   0,   1,   1 },
+      {  1,   1,   0,   1,  -1 },
+
+   /* 561-570 */
+      {  1,   1,  -2,  -6,  -2 },
+      {  1,   0,   0,  -3,  -1 },
+      {  1,   0,  -4,  -2,  -1 },
+      {  1,   0,  -2,  -6,  -1 },
+      {  1,  -2,   2,   2,   1 },
+      {  1,  -2,  -2,   2,  -1 },
+      {  1,  -1,  -2,  -4,  -1 },
+      {  0,   2,   0,   0,   2 },
+      {  0,   1,   2,  -4,   2 },
+      {  0,   1,  -2,   4,  -1 },
+
+   /* 571-580 */
+      {  5,   0,   0,   0,   0 },
+      {  3,   0,   0,  -3,   0 },
+      {  2,   2,   0,  -4,   0 },
+      {  1,  -1,   2,   2,   0 },
+      {  0,   1,   0,   3,   0 },
+      {  4,   0,  -2,   0,  -1 },
+      {  3,   0,  -2,  -6,  -1 },
+      {  3,   0,  -2,  -1,  -1 },
+      {  2,   1,   2,   2,   1 },
+      {  2,   1,   0,   2,   1 },
+
+   /* 581-590 */
+      {  2,   0,   2,   4,   1 },
+      {  2,   0,   2,  -6,   1 },
+      {  2,   0,   2,  -2,  -1 },
+      {  2,   0,   0,  -6,  -1 },
+      {  2,  -1,  -2,  -2,  -1 },
+      {  1,   2,   2,   0,   1 },
+      {  1,   2,   0,   0,   1 },
+      {  1,   0,   4,   0,   1 },
+      {  1,   0,   2,  -6,   1 },
+      {  1,   0,   2,  -4,  -1 },
+
+   /* 591-600 */
+      {  1,   0,  -1,  -2,  -1 },
+      {  1,  -1,   2,   4,   1 },
+      {  1,  -1,   2,  -3,   1 },
+      {  1,  -1,   0,   4,   1 },
+      {  1,  -1,  -2,   1,  -1 },
+      {  0,   1,   2,  -2,   3 },
+      {  3,   0,   0,  -2,   0 },
+      {  1,   0,   1,  -2,   0 },
+      {  0,   2,   0,  -4,   0 },
+      {  0,   0,   2,  -4,   0 },
+
+   /* 601-610 */
+      {  0,   0,   1,  -1,   0 },
+      {  0,   0,   0,   6,   0 },
+      {  0,   2,   0,   0,  -2 },
+      {  0,   1,  -2,   2,  -3 },
+      {  4,   0,   0,   2,   0 },
+      {  3,   0,   0,  -1,   0 },
+      {  3,  -1,   0,   2,   0 },
+      {  2,   1,   0,   1,   0 },
+      {  2,   1,   0,  -6,   0 },
+      {  2,  -1,   2,   0,   0 },
+
+   /* 611-620 */
+      {  1,   0,   2,  -1,   0 },
+      {  1,  -1,   0,   1,   0 },
+      {  1,  -1,  -2,  -2,   0 },
+      {  0,   1,   2,   2,   0 },
+      {  0,   0,   2,  -3,   0 },
+      {  2,   2,   0,  -2,  -1 },
+      {  2,  -1,  -2,   0,   1 },
+      {  1,   2,   2,  -4,   1 },
+      {  0,   1,   4,  -4,   2 },
+      {  0,   0,   0,   3,   2 },
+
+   /* 621-630 */
+      {  5,   0,   2,   0,   1 },
+      {  4,   1,   2,  -2,   2 },
+      {  4,   0,  -2,  -2,   0 },
+      {  3,   1,   2,   2,   2 },
+      {  3,   1,   0,  -2,   0 },
+      {  3,   1,  -2,  -6,  -2 },
+      {  3,   0,   0,   0,  -2 },
+      {  3,   0,  -2,  -4,  -2 },
+      {  3,  -1,   0,  -3,   0 },
+      {  3,  -1,   0,  -2,   0 },
+
+   /* 631-640 */
+      {  2,   1,   2,   0,   0 },
+      {  2,   1,   2,  -4,   2 },
+      {  2,   1,   2,  -2,   0 },
+      {  2,   1,   0,  -3,   0 },
+      {  2,   1,  -2,   0,  -2 },
+      {  2,   0,   0,  -4,   2 },
+      {  2,   0,   0,  -4,  -2 },
+      {  2,   0,  -2,  -5,  -2 },
+      {  2,  -1,   2,   4,   2 },
+      {  2,  -1,   0,  -2,   2 },
+
+   /* 641-650 */
+      {  1,   3,  -2,  -2,  -2 },
+      {  1,   1,   0,   0,  -2 },
+      {  1,   1,   0,  -6,   0 },
+      {  1,   1,  -2,   1,  -2 },
+      {  1,   1,  -2,  -1,  -2 },
+      {  1,   0,   2,   1,   0 },
+      {  1,   0,   0,   3,   0 },
+      {  1,   0,   0,  -4,   2 },
+      {  1,   0,  -2,   4,  -2 },
+      {  1,  -2,   0,  -1,   0 },
+
+   /* 651-NFLS */
+      {  0,   1,  -4,   2,  -1 },
+      {  1,   0,  -2,   0,  -3 },
+      {  0,   0,   4,  -4,   4 }
+   };
+
+/* Number of frequencies:  luni-solar */
+   static const int NFLS = (int) (sizeof mfals / sizeof (int) / 5);
+
+/* Fundamental-argument multipliers:  planetary terms */
+   static const int mfapl[][14] = {
+
+   /* 1-10 */
+      {  0,  0,  1, -1,  1,  0,  0, -1,  0, -2,  5,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  0,  0,  2, -5,  0,  0, -1 },
+      {  0,  0,  0,  0,  0,  0,  3, -5,  0,  0,  0,  0,  0, -2 },
+      {  0,  0,  1, -1,  1,  0, -8, 12,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  0,  0,  2,  0,  0,  0,  2 },
+      {  0,  0,  0,  0,  0,  0,  0,  4, -8,  3,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  1, -1,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  8,-16,  4,  5,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  1,  0, -1,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  1,  0,  0, -1,  2,  0,  0,  0,  0,  0 },
+
+   /* 11-20 */
+      {  0,  0,  0,  0,  0,  0,  8,-13,  0,  0,  0,  0,  0, -1 },
+      {  0,  0,  1, -1,  1,  0,  0, -1,  0,  2, -5,  0,  0,  0 },
+      {  0,  0,  2, -2,  1,  0, -5,  6,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  4, -6,  0,  0,  0,  0,  0, -2 },
+      {  0,  0,  0,  0,  0,  0,  0,  3,  0, -1,  0,  0,  0,  2 },
+      {  0,  0,  0,  0,  0,  0,  0,  2, -8,  3,  0,  0,  0, -2 },
+      {  0,  0,  0,  0,  0,  0,  2, -4,  0,  0,  0,  0,  0, -2 },
+      {  0,  0,  0,  0,  0,  0,  0,  6, -8,  3,  0,  0,  0,  2 },
+      {  0,  0,  0,  0,  0,  0,  0,  1, -2,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  2, -3,  0,  0,  0,  0,  0,  0 },
+
+   /* 21-30 */
+      {  0,  0,  0,  0,  0,  0,  2, -2,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  2,  0,  0,  0,  0,  0,  0,  2 },
+      {  0,  0,  0,  0,  1,  0,  0, -4,  8, -3,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  1,  0,  0,  4, -8,  3,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  0,  0,  2, -5,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  1,  1,  0,  0,  0,  0,  0,  2 },
+      {  0,  0,  1, -1,  1,  0,  0,  0, -2,  0,  0,  0,  0,  0 },
+      {  2,  0,  0, -2, -1,  0,  0, -2,  0,  2,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  0,  0,  2,  0,  0,  0,  1 },
+      {  2,  0,  0, -2,  0,  0,  0, -2,  0,  2,  0,  0,  0,  0 },
+
+   /* 31-40 */
+      {  0,  0,  0,  0,  0,  0,  0,  2,  0, -2,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  8,-13,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  0,  0,  2 },
+      {  0,  0,  0,  0,  0,  0,  5, -8,  0,  0,  0,  0,  0, -2 },
+      {  0,  0,  0,  0,  0,  0,  0,  2, -2,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  0,  0,  2, -5,  0,  0,  1 },
+      {  2,  0,  0, -2,  0,  0,  0, -2,  0,  3,  0,  0,  0,  0 },
+      {  0,  0,  1, -1,  1,  0,  0, -1,  0, -1,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  3, -4,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  1, -1,  1,  0,  0, -1,  0,  0, -1,  0,  0,  0 },
+
+   /* 41-50 */
+      {  0,  0,  0,  0,  0,  0,  0,  1,  0, -2,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  5, -7,  0,  0,  0,  0,  0, -2 },
+      {  0,  0,  1, -1,  0,  0,  0,  0, -2,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  4,  0, -2,  0,  0,  0,  2 },
+      {  0,  0,  0,  0,  0,  0,  8,-13,  0,  0,  0,  0,  0, -2 },
+      {  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  2, -1,  0,  0,  0,  0,  0,  2 },
+      {  1,  0,  0,  0,  0,  0,-18, 16,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  1, -1,  1,  0,  0, -1,  0,  2,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  2,  0,  1,  0,  0,  0,  2 },
+
+   /* 51-60 */
+      {  0,  0,  1, -1,  1,  0, -5,  7,  0,  0,  0,  0,  0,  0 },
+      {  1,  0,  0,  0,  0,  0,-10,  3,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  2, -2,  0,  0, -5,  6,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  2,  0, -1,  0,  0,  0,  2 },
+      {  1,  0,  2,  0,  2,  0,  0,  1,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  4, -2,  0,  0,  0,  0,  2 },
+      {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  2,  0,  0,  1 },
+      {  1,  0, -2,  0, -2,  0,  0,  4, -8,  3,  0,  0,  0,  0 },
+      {  0,  0,  1, -1,  1,  0,  0, -1,  0,  0,  2,  0,  0,  0 },
+      {  0,  0,  2, -2,  1,  0, -3,  3,  0,  0,  0,  0,  0,  0 },
+
+   /* 61-70 */
+      {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  2,  0,  0,  2 },
+      {  0,  0,  0,  0,  0,  0,  0,  8,-16,  4,  5,  0,  0, -2 },
+      {  0,  0,  1, -1,  1,  0,  0,  3, -8,  3,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  8,-11,  0,  0,  0,  0,  0, -2 },
+      {  0,  0,  0,  0,  0,  0,  0,  0,  0,  3,  0,  0,  0,  2 },
+      {  0,  0,  0,  0,  0,  0,  0,  8,-16,  4,  5,  0,  0,  2 },
+      {  0,  0,  0,  0,  0,  0,  1, -1,  0,  0,  0,  0,  0, -1 },
+      {  0,  0,  0,  0,  0,  0,  4, -6,  0,  0,  0,  0,  0, -1 },
+      {  0,  0,  0,  0,  0,  0,  0,  1,  0, -3,  0,  0,  0, -2 },
+      {  0,  0,  0,  0,  0,  0,  0,  2, -4,  0,  0,  0,  0,  0 },
+
+   /* 71-80 */
+      {  0,  0,  0,  0,  0,  0,  6, -8,  0,  0,  0,  0,  0, -2 },
+      {  0,  0,  0,  0,  0,  0,  3, -2,  0,  0,  0,  0,  0,  2 },
+      {  0,  0,  0,  0,  0,  0,  8,-15,  0,  0,  0,  0,  0, -2 },
+      {  0,  0,  0,  0,  0,  0,  2, -5,  0,  0,  0,  0,  0, -2 },
+      {  0,  0,  0,  0,  0,  0,  1, -3,  0,  0,  0,  0,  0, -2 },
+      {  0,  0,  0,  0,  0,  0,  0,  3,  0, -2,  0,  0,  0,  2 },
+      {  0,  0,  1, -1,  1,  0,  0, -5,  8, -3,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  1,  2,  0,  0,  0,  0,  2 },
+      {  0,  0,  0,  0,  0,  0,  0,  3, -2,  0,  0,  0,  0,  2 },
+      {  0,  0,  0,  0,  0,  0,  3, -5,  0,  0,  0,  0,  0,  0 },
+
+   /* 81-90 */
+      {  2,  0,  0, -2,  1,  0,  0, -2,  0,  3,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  5, -8,  0,  0,  0,  0,  0, -1 },
+      {  2,  0,  0, -2,  0,  0, -3,  3,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  1,  0,  8,-13,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  1,  0,  0,  0,  0, -2,  5,  0,  0,  0 },
+      {  1,  0,  0, -1,  0,  0, -3,  4,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  2,  0,  0,  0,  0,  0,  2 },
+      {  1,  0,  0,  0, -1,  0,-18, 16,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  1,  0,  0,  0,  0,  2, -5,  0,  0,  0 },
+      {  0,  0,  0,  0,  1,  0,  0,  0,  0,  1,  0,  0,  0,  0 },
+
+   /* 91-100 */
+      {  1,  0,  0, -2,  0,  0, 19,-21,  3,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  1,  0, -8, 13,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  1, -1,  1,  0,  0, -1,  0,  0,  1,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  7, -9,  0,  0,  0,  0,  0, -2 },
+      {  0,  0,  0,  0,  0,  0,  0,  0,  2,  0,  0,  0,  0,  2 },
+      {  1,  0,  0,  0,  1,  0,-18, 16,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  2, -4,  0,  0,  0,  0,  0, -1 },
+      {  0,  0,  0,  0,  0,  0,  0,  6,-16,  4,  5,  0,  0, -2 },
+      {  0,  0,  0,  0,  0,  0,  4, -7,  0,  0,  0,  0,  0, -2 },
+      {  0,  0,  0,  0,  0,  0,  3, -7,  0,  0,  0,  0,  0, -2 },
+
+   /* 101-110 */
+      {  0,  0,  0,  0,  0,  0,  2, -2,  0,  0,  0,  0,  0, -1 },
+      {  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  0,  0,  1 },
+      {  2,  0,  0, -2,  1,  0,  0, -2,  0,  2,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  0,  0, -1 },
+      {  0,  0,  0,  0,  0,  0,  0,  3, -4,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  1, -2,  0,  0,  0,  0,  0,  0 },
+      {  2,  0,  0, -2, -1,  0,  0, -2,  0,  3,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  3, -3,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  2,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  1,  0,  2,  0,  0,  0,  2 },
+
+   /* 111-120 */
+      {  0,  0,  0,  0,  1,  0,  0,  1, -2,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  0,  0,  2 },
+      {  0,  0,  2, -2,  1,  0,  0, -2,  0,  2,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  2,  0, -3,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  3, -5,  0,  0,  0,  0,  0, -1 },
+      {  0,  0,  0,  0,  0,  0,  3, -3,  0,  0,  0,  0,  0,  2 },
+      {  0,  0,  0,  0,  0,  0,  4, -4,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  1, -1,  0,  0,  0, -1,  0, -1,  0,  0,  0,  0 },
+      {  2,  0,  0, -2,  0,  0, -6,  8,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  1, -1,  1,  0,  0, -2,  2,  0,  0,  0,  0,  0 },
+
+   /* 121-130 */
+      {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  0,  1 },
+      {  0,  0,  1, -1,  1,  0,  0, -1,  0,  1,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  1, -2,  0,  0,  0,  0, -1 },
+      {  0,  0,  0,  0,  0,  0,  0,  2, -3,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  2, -4,  0,  0,  0,  0, -2 },
+      {  0,  0,  0,  0,  0,  0,  0,  1,  0,  0, -1,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  8,-10,  0,  0,  0,  0,  0, -2 },
+      {  0,  0,  1, -1,  1,  0, -3,  4,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  6, -9,  0,  0,  0,  0,  0, -2 },
+      {  1,  0,  0, -1,  1,  0,  0, -1,  0,  2,  0,  0,  0,  0 },
+
+   /* 131-140 */
+      {  0,  0,  0,  0,  0,  0,  5, -7,  0,  0,  0,  0,  0, -1 },
+      {  0,  0,  0,  0,  0,  0,  5, -5,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  0, -1 },
+      {  0,  0,  0,  0,  0,  0,  3, -3,  0,  0,  0,  0,  0, -1 },
+      {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  0,  4,  0,  0,  0,  0,  2 },
+      {  0,  0,  0,  0,  0,  0,  0,  4,  0, -3,  0,  0,  0,  2 },
+      {  0,  0,  0,  0,  0,  0,  1, -1,  0,  0,  0,  0,  0,  1 },
+      {  0,  0,  0,  0,  0,  0,  0,  2,  0,  0,  0,  0,  0,  1 },
+      {  0,  0,  0,  0,  1,  0,  2, -3,  0,  0,  0,  0,  0,  0 },
+
+   /* 141-150 */
+      {  1,  0,  0, -1,  0,  0,  0, -1,  0,  1,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  1, -3,  0,  0,  0,  0,  0, -1 },
+      {  0,  0,  0,  0,  0,  0,  0,  5, -4,  0,  0,  0,  0,  2 },
+      {  0,  0,  0,  0,  0,  0,  0,  4, -4,  0,  0,  0,  0,  2 },
+      {  0,  0,  0,  0,  0,  0,  9,-11,  0,  0,  0,  0,  0, -2 },
+      {  0,  0,  0,  0,  0,  0,  2, -3,  0,  0,  0,  0,  0, -1 },
+      {  0,  0,  0,  0,  0,  0,  0,  8,-15,  0,  0,  0,  0,  0 },
+      {  0,  0,  1, -1,  1,  0, -4,  5,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  4, -6,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  4,  0, -1,  0,  0,  0,  2 },
+
+   /* 151-160 */
+      {  1,  0,  0, -1,  1,  0, -3,  4,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  1,  1,  1,  0,  0,  1,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  1, -1,  1,  0,  0, -1,  0, -4, 10,  0,  0,  0 },
+      {  0,  0,  0,  0,  1,  0,  1, -1,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  1, -1,  0,  0,  0, -1,  0,  0, -1,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  1,  0, -3,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  3, -1,  0,  0,  0,  0,  0,  2 },
+      {  0,  0,  0,  0,  0,  0,  0,  1,  0, -4,  0,  0,  0, -2 },
+      {  0,  0,  0,  0,  0,  0,  0,  0,  0,  2, -5,  0,  0, -2 },
+      {  0,  0,  2, -2,  1,  0, -4,  4,  0,  0,  0,  0,  0,  0 },
+
+   /* 161-170 */
+      {  0,  0,  0,  0,  0,  0,  0,  3,  0,  0, -1,  0,  0,  2 },
+      {  0,  0,  0,  0,  0,  0,  0,  4, -3,  0,  0,  0,  0,  2 },
+      {  0,  0,  1, -1,  1,  0,  0, -1,  0,  0,  0,  0,  2,  0 },
+      {  0,  0,  0,  0,  0,  0,  4, -4,  0,  0,  0,  0,  0, -1 },
+      {  0,  0,  0,  0,  0,  0,  0,  2, -4,  0,  0,  0,  0, -1 },
+      {  0,  0,  0,  0,  0,  0,  5, -8,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  1, -2,  0,  0,  0,  0,  1 },
+      {  0,  0,  0,  0,  1,  0,  0,  0,  0,  0,  1,  0,  0,  0 },
+      {  0,  0,  2, -2,  1,  0,  0, -9, 13,  0,  0,  0,  0,  0 },
+      {  2,  0,  2,  0,  2,  0,  0,  2,  0, -3,  0,  0,  0,  0 },
+
+   /* 171-180 */
+      {  0,  0,  0,  0,  0,  0,  3, -6,  0,  0,  0,  0,  0, -2 },
+      {  0,  0,  1, -1,  2,  0,  0, -1,  0,  0,  2,  0,  0,  0 },
+      {  1,  0,  0, -1, -1,  0, -3,  4,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  3, -6,  0,  0,  0,  0, -2 },
+      {  0,  0,  0,  0,  0,  0,  6, -6,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  0,  0,  3,  0,  0,  0,  1 },
+      {  1,  0,  2,  0,  1,  0,  0, -2,  0,  3,  0,  0,  0,  0 },
+      {  1,  0, -2,  0, -1,  0,  0, -1,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  1,  0,  0, -2,  4,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  3, -5,  0,  0,  0,  0,  0 },
+
+   /* 181-190 */
+      {  0,  0,  0,  0,  0,  0,  2,  1,  0,  0,  0,  0,  0,  2 },
+      {  0,  0,  0,  0,  0,  0,  1,  1,  0,  0,  0,  0,  0,  1 },
+      {  0,  0,  2,  0,  2,  0,  0,  1,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  1, -8,  3,  0,  0,  0, -2 },
+      {  0,  0,  0,  0,  0,  0,  6,-10,  0,  0,  0,  0,  0, -2 },
+      {  0,  0,  0,  0,  0,  0,  0,  7, -8,  3,  0,  0,  0,  2 },
+      {  0,  0,  0,  0,  1,  0, -3,  5,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  1, -1,  1,  0, -1,  0,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  1, -1,  0,  0, -5,  7,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  2,  0, -2,  0,  0,  0,  1 },
+
+   /* 191-200 */
+      {  0,  0,  0,  0,  0,  0,  0,  2,  0, -1,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  7,-10,  0,  0,  0,  0,  0, -2 },
+      {  1,  0,  0, -2,  0,  0,  0, -2,  0,  2,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  0,  0,  2,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  1,  0,  2, -5,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  6, -8,  0,  0,  0,  0,  0, -1 },
+      {  0,  0,  1, -1,  1,  0,  0, -9, 15,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  1,  0, -2,  3,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  1,  0, -1,  1,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  3, -6,  0,  0,  0,  0,  0 },
+
+   /* 201-210 */
+      {  0,  0,  0,  0,  0,  0,  0,  1, -4,  0,  0,  0,  0, -2 },
+      {  0,  0,  0,  0,  0,  0,  0,  0,  3,  0,  0,  0,  0,  2 },
+      {  0,  0,  0,  0,  0,  0,  0,  2,  0,  0, -1,  0,  0,  2 },
+      {  2,  0,  0, -2,  1,  0, -6,  8,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  5, -5,  0,  0,  0,  0,  0, -1 },
+      {  0,  0,  1, -1,  1,  0,  3, -6,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  1, -1,  1,  0, -2,  2,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  1, -1,  1,  0,  8,-14,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  1,  0,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  1,  0,  0,  0,  0,  0,  0 },
+
+   /* 211-220 */
+      {  0,  0,  0,  0,  1,  0,  0,  8,-15,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  4, -6,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  7, -7,  0,  0,  0,  0,  0,  0 },
+      {  2,  0,  0, -2,  1,  0, -3,  3,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  3, -1,  0,  0,  0,  0,  2 },
+      {  0,  0,  0,  0,  0,  0,  0,  2,  0,  0,  1,  0,  0,  2 },
+      {  2,  0, -1, -1,  0,  0,  0,  3, -7,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  4, -7,  0,  0,  0,  0, -2 },
+      {  0,  0,  0,  0,  0,  0,  0,  3, -3,  0,  0,  0,  0,  0 },
+      {  0,  0,  1, -1,  1,  0,  0, -3,  4,  0,  0,  0,  0,  0 },
+
+   /* 221-230 */
+      {  2,  0,  0, -2,  0,  0,  0, -6,  8,  0,  0,  0,  0,  0 },
+      {  2,  0,  0, -2,  0,  0,  0, -5,  6,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  1,  0,  0,  0,  0, -1,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  2,  0,  0,  0,  0,  0,  0,  1 },
+      {  0,  0,  0,  0,  0,  0,  2,  1,  0,  0,  0,  0,  0,  1 },
+      {  0,  0,  0,  0,  0,  0,  1,  2,  0,  0,  0,  0,  0,  2 },
+      {  0,  0,  0,  0,  1,  0,  0,  1,  0, -1,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  1, -1,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  3, -9,  4,  0,  0,  0,  0, -2 },
+      {  0,  0,  0,  0,  0,  0,  0,  3, -5,  0,  0,  0,  0, -2 },
+
+   /* 231-240 */
+      {  0,  0,  0,  0,  0,  0,  0,  2,  0, -4,  0,  0,  0, -2 },
+      {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  2,  1 },
+      {  0,  0,  0,  0,  0,  0,  7,-11,  0,  0,  0,  0,  0, -2 },
+      {  0,  0,  0,  0,  0,  0,  3, -5,  4,  0,  0,  0,  0,  2 },
+      {  0,  0,  1, -1,  0,  0,  0, -1,  0, -1,  1,  0,  0,  0 },
+      {  2,  0,  0,  0,  0,  0,  0, -2,  0,  3,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  8,-15,  0,  0,  0,  0, -2 },
+      {  0,  0,  1, -1,  2,  0,  0, -2,  2,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  3,  0,  0,  2 },
+      {  0,  0,  0,  0,  0,  0,  6, -6,  0,  0,  0,  0,  0, -1 },
+
+   /* 241-250 */
+      {  0,  0,  1, -1,  1,  0,  0, -1,  0, -1,  1,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  2, -2,  0,  0,  0,  0,  0,  1 },
+      {  0,  0,  0,  0,  0,  0,  0,  4, -7,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  3, -8,  3,  0,  0,  0,  0 },
+      {  0,  0,  1, -1,  1,  0,  2, -4,  0, -3,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  1,  0,  3, -5,  0,  2,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  3,  0, -3,  0,  0,  0,  2 },
+      {  0,  0,  2, -2,  2,  0, -8, 11,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  5, -8,  3,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  1,  0,  0, -2,  0,  0,  0 },
+
+   /* 251-260 */
+      {  0,  0,  0,  0,  0,  0,  0,  1,  0,  0,  1,  0,  0,  2 },
+      {  0,  0,  0,  0,  0,  0,  0,  5, -9,  0,  0,  0,  0, -2 },
+      {  0,  0,  0,  0,  0,  0,  0,  5, -5,  0,  0,  0,  0,  2 },
+      {  0,  0,  0,  0,  0,  0,  7, -9,  0,  0,  0,  0,  0, -1 },
+      {  0,  0,  0,  0,  0,  0,  4, -7,  0,  0,  0,  0,  0, -1 },
+      {  0,  0,  0,  0,  0,  0,  2, -1,  0,  0,  0,  0,  0,  0 },
+      {  1,  0, -2, -2, -2,  0,  0, -2,  0,  2,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  1,  1,  0,  0,  0,  0,  2 },
+      {  0,  0,  0,  0,  0,  0,  0,  2,  0, -2,  5,  0,  0,  2 },
+      {  0,  0,  0,  0,  0,  0,  3, -3,  0,  0,  0,  0,  0,  1 },
+
+   /* 261-270 */
+      {  0,  0,  0,  0,  0,  0,  0,  6,  0,  0,  0,  0,  0,  2 },
+      {  0,  0,  0,  0,  0,  0,  0,  2,  0,  2, -5,  0,  0,  2 },
+      {  2,  0,  0, -2, -1,  0,  0, -2,  0,  0,  5,  0,  0,  0 },
+      {  2,  0,  0, -2, -1,  0, -6,  8,  0,  0,  0,  0,  0,  0 },
+      {  1,  0,  0, -2,  0,  0, -3,  3,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  8, -8,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  3,  0,  2, -5,  0,  0,  2 },
+      {  0,  0,  0,  0,  1,  0,  3, -7,  4,  0,  0,  0,  0,  0 },
+      {  0,  0,  2, -2,  1,  0, -2,  2,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  1,  0,  0, -1,  0,  1,  0,  0,  0,  0 },
+
+   /* 271-280 */
+      {  0,  0,  1, -1,  0,  0,  0, -1,  0, -2,  5,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  3,  0, -3,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  3, -1,  0,  0,  0,  0,  0,  1 },
+      {  0,  0,  0,  0,  0,  0,  2, -3,  0,  0,  0,  0,  0, -2 },
+      {  0,  0,  0,  0,  0,  0,  0, 11,  0,  0,  0,  0,  0,  2 },
+      {  0,  0,  0,  0,  0,  0,  0,  6,-15,  0,  0,  0,  0, -2 },
+      {  0,  0,  0,  0,  0,  0,  0,  3,  0,  1,  0,  0,  0,  2 },
+      {  1,  0,  0, -1,  0,  0,  0, -3,  4,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  1,  0, -3,  7, -4,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  5,  0, -2,  0,  0,  0,  2 },
+
+   /* 281-290 */
+      {  0,  0,  0,  0,  0,  0,  3, -5,  0,  0,  0,  0,  0,  1 },
+      {  0,  0,  2, -2,  2,  0, -5,  6,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  2, -2,  2,  0, -3,  3,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  3,  0,  0,  0,  0,  0,  0,  2 },
+      {  0,  0,  0,  0,  0,  0,  0,  6,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  4, -4,  0,  0,  0,  0,  0,  2 },
+      {  0,  0,  0,  0,  0,  0,  0,  4, -8,  0,  0,  0,  0, -2 },
+      {  0,  0,  0,  0,  0,  0,  0,  4, -5,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  5, -7,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  6,-11,  0,  0,  0,  0, -2 },
+
+   /* 291-300 */
+      {  0,  0,  0,  0,  0,  0,  0,  1, -3,  0,  0,  0,  0, -2 },
+      {  0,  0,  1, -1,  1,  0,  0, -1,  0,  3,  0,  0,  0,  0 },
+      {  0,  0,  1, -1,  0,  0,  0, -1,  0,  2,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  1, -2,  0,  0,  0,  0,  0,  1 },
+      {  0,  0,  0,  0,  0,  0,  9,-12,  0,  0,  0,  0,  0, -2 },
+      {  0,  0,  0,  0,  0,  0,  4, -4,  0,  0,  0,  0,  0,  1 },
+      {  0,  0,  1, -1,  0,  0, -8, 12,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  1, -1,  1,  0, -2,  3,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  7, -7,  0,  0,  0,  0,  0, -1 },
+      {  0,  0,  0,  0,  0,  0,  0,  3, -6,  0,  0,  0,  0, -1 },
+
+   /* 301-310 */
+      {  0,  0,  0,  0,  0,  0,  0,  6, -6,  0,  0,  0,  0,  2 },
+      {  0,  0,  0,  0,  0,  1,  0, -4,  0,  0,  0,  0,  0, -2 },
+      {  0,  0,  1, -1,  1,  0,  0,  1,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  6, -9,  0,  0,  0,  0,  0, -1 },
+      {  0,  0,  1, -1, -1,  0,  0,  0, -2,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  1, -5,  0,  0,  0,  0, -2 },
+      {  2,  0,  0, -2,  0,  0,  0, -2,  0,  3, -1,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  2,  0,  0, -2,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  5, -9,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  5, -6,  0,  0,  0,  0,  0,  2 },
+
+   /* 311-320 */
+      {  0,  0,  0,  0,  0,  0,  9, -9,  0,  0,  0,  0,  0, -1 },
+      {  0,  0,  1, -1,  1,  0,  0, -1,  0,  0,  3,  0,  0,  0 },
+      {  0,  0,  0,  0,  1,  0,  0,  2, -4,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  5, -3,  0,  0,  0,  0,  0,  2 },
+      {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  3,  0,  0,  1 },
+      {  0,  0,  1, -1,  2,  0,  0, -1,  0,  2,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  5, -9,  0,  0,  0,  0,  0, -2 },
+      {  0,  0,  0,  0,  0,  0,  0,  5, -3,  0,  0,  0,  0,  2 },
+      {  0,  0,  0,  0,  0,  0,  0,  0,  0,  4,  0,  0,  0,  2 },
+      {  0,  0,  2,  0,  2,  0,  0,  4, -8,  3,  0,  0,  0,  0 },
+
+   /* 321-330 */
+      {  0,  0,  2,  0,  2,  0,  0, -4,  8, -3,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  5,  0, -3,  0,  0,  0,  2 },
+      {  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  0,  0,  0 },
+      {  2,  0, -1, -1, -1,  0,  0, -1,  0,  3,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  4, -3,  0,  0,  0,  0,  0,  2 },
+      {  0,  0,  0,  0,  0,  0,  4, -2,  0,  0,  0,  0,  0,  2 },
+      {  0,  0,  0,  0,  0,  0,  5,-10,  0,  0,  0,  0,  0, -2 },
+      {  0,  0,  0,  0,  0,  0,  8,-13,  0,  0,  0,  0,  0,  1 },
+      {  0,  0,  2, -2,  1, -1,  0,  2,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  1, -1,  1,  0,  0, -1,  0,  0,  0,  2,  0,  0 },
+
+   /* 331-340 */
+      {  0,  0,  0,  0,  1,  0,  3, -5,  0,  0,  0,  0,  0,  0 },
+      {  1,  0,  0, -2,  0,  0,  0, -2,  0,  3,  0,  0,  0,  0 },
+      {  0,  0,  2, -2,  0,  0, -3,  3,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  9, -9,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  2,  0,  2,  0,  1, -1,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  2, -2,  1,  0,  0, -8, 11,  0,  0,  0,  0,  0 },
+      {  0,  0,  2, -2,  1,  0,  0, -2,  0,  0,  2,  0,  0,  0 },
+      {  0,  0,  1, -1,  1,  0,  0, -1,  0, -1,  2,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  5, -5,  0,  0,  0,  0,  0,  2 },
+      {  0,  0,  0,  0,  0,  0,  2, -6,  0,  0,  0,  0,  0, -2 },
+
+   /* 341-350 */
+      {  0,  0,  0,  0,  0,  0,  0,  8,-15,  0,  0,  0,  0, -1 },
+      {  0,  0,  0,  0,  0,  0,  0,  5, -2,  0,  0,  0,  0,  2 },
+      {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  0,  2 },
+      {  0,  0,  0,  0,  0,  0,  0,  7,-13,  0,  0,  0,  0, -2 },
+      {  0,  0,  0,  0,  0,  0,  0,  3,  0, -2,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  1,  0,  3,  0,  0,  0,  2 },
+      {  0,  0,  2, -2,  1,  0,  0, -2,  0,  3,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  8, -8,  0,  0,  0,  0,  0, -1 },
+      {  0,  0,  0,  0,  0,  0,  8,-10,  0,  0,  0,  0,  0, -1 },
+      {  0,  0,  0,  0,  0,  0,  4, -2,  0,  0,  0,  0,  0,  1 },
+
+   /* 351-360 */
+      {  0,  0,  0,  0,  0,  0,  3, -6,  0,  0,  0,  0,  0, -1 },
+      {  0,  0,  0,  0,  0,  0,  3, -4,  0,  0,  0,  0,  0, -1 },
+      {  0,  0,  0,  0,  0,  0,  0,  0,  0,  2, -5,  0,  0,  2 },
+      {  0,  0,  0,  0,  0,  0,  1,  0,  0,  0,  0,  0,  0,  2 },
+      {  0,  0,  0,  0,  0,  0,  0,  2,  0, -4,  0,  0,  0,  0 },
+      {  2,  0,  0, -2, -1,  0,  0, -5,  6,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  2, -5,  0,  0,  0,  0, -2 },
+      {  2,  0, -1, -1, -1,  0,  0,  3, -7,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  5, -8,  0,  0,  0,  0,  0 },
+      {  0,  0,  2,  0,  2,  0, -1,  1,  0,  0,  0,  0,  0,  0 },
+
+   /* 361-370 */
+      {  2,  0,  0, -2,  0,  0,  0, -2,  0,  4, -3,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  6,-11,  0,  0,  0,  0,  0 },
+      {  2,  0,  0, -2,  1,  0,  0, -6,  8,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  4, -8,  1,  5,  0,  0, -2 },
+      {  0,  0,  0,  0,  0,  0,  0,  6, -5,  0,  0,  0,  0,  2 },
+      {  1,  0, -2, -2, -2,  0, -3,  3,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  1, -1,  2,  0,  0,  0, -2,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  2,  0,  0,  4, -8,  3,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  2,  0,  0, -4,  8, -3,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  6,  0,  0,  0,  0,  0,  1 },
+
+   /* 371-380 */
+      {  0,  0,  0,  0,  0,  0,  0,  6, -7,  0,  0,  0,  0,  2 },
+      {  0,  0,  0,  0,  0,  0,  0,  4,  0,  0, -2,  0,  0,  2 },
+      {  0,  0,  0,  0,  0,  0,  0,  3,  0,  0, -2,  0,  0,  2 },
+      {  0,  0,  0,  0,  0,  0,  0,  1,  0, -1,  0,  0,  0,  1 },
+      {  0,  0,  0,  0,  0,  0,  0,  1, -6,  0,  0,  0,  0, -2 },
+      {  0,  0,  0,  0,  0,  0,  0,  0,  0,  4, -5,  0,  0,  2 },
+      {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  2,  0,  2 },
+      {  0,  0,  0,  0,  0,  0,  3, -5,  0,  2,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  7,-13,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  2,  0, -2,  0,  0,  0,  2 },
+
+   /* 381-390 */
+      {  0,  0,  1, -1,  0,  0,  0, -1,  0,  0,  2,  0,  0,  0 },
+      {  0,  0,  0,  0,  1,  0,  0, -8, 15,  0,  0,  0,  0,  0 },
+      {  2,  0,  0, -2, -2,  0, -3,  3,  0,  0,  0,  0,  0,  0 },
+      {  2,  0, -1, -1, -1,  0,  0, -1,  0,  2,  0,  0,  0,  0 },
+      {  1,  0,  2, -2,  2,  0,  0, -2,  0,  2,  0,  0,  0,  0 },
+      {  1,  0, -1,  1, -1,  0,-18, 17,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  2,  0,  2,  0,  0,  1,  0, -1,  0,  0,  0,  0 },
+      {  0,  0,  2,  0,  2,  0,  0, -1,  0,  1,  0,  0,  0,  0 },
+      {  0,  0,  2, -2, -1,  0, -5,  6,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  1, -1,  2,  0,  0, -1,  0,  1,  0,  0,  0,  0 },
+
+   /* 391-400 */
+      {  0,  0,  0,  0,  1,  0,  2, -2,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  8,-16,  0,  0,  0,  0,  0, -2 },
+      {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  5,  0,  0,  2 },
+      {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  2,  2 },
+      {  0,  0,  0,  0,  2,  0,  0, -1,  2,  0,  0,  0,  0,  0 },
+      {  2,  0, -1, -1, -2,  0,  0, -1,  0,  2,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  6,-10,  0,  0,  0,  0,  0, -1 },
+      {  0,  0,  1, -1,  1,  0,  0, -1,  0, -2,  4,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  2,  2,  0,  0,  0,  0,  2 },
+      {  2,  0,  0, -2, -1,  0,  0, -2,  0,  4, -5,  0,  0,  0 },
+
+   /* 401-410 */
+      {  2,  0,  0, -2, -1,  0, -3,  3,  0,  0,  0,  0,  0,  0 },
+      {  2,  0, -1, -1, -1,  0,  0, -1,  0,  0,  0,  0,  0,  0 },
+      {  1,  0,  1, -1,  1,  0,  0, -1,  0,  0,  0,  0,  0,  0 },
+      {  1,  0,  0, -1, -1,  0,  0, -2,  2,  0,  0,  0,  0,  0 },
+      {  1,  0, -1, -1, -1,  0, 20,-20,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  2, -2,  1,  0,  0, -1,  0,  1,  0,  0,  0,  0 },
+      {  0,  0,  1, -1,  1,  0,  1, -2,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  1, -1,  1,  0, -2,  1,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  1,  0,  5, -8,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  1,  0,  0,  0,  0,  0, -1,  0,  0,  0 },
+
+   /* 411-420 */
+      {  0,  0,  0,  0,  0,  0,  9,-11,  0,  0,  0,  0,  0, -1 },
+      {  0,  0,  0,  0,  0,  0,  5, -3,  0,  0,  0,  0,  0,  1 },
+      {  0,  0,  0,  0,  0,  0,  0,  1,  0, -3,  0,  0,  0, -1 },
+      {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  2,  0,  1 },
+      {  0,  0,  0,  0,  0,  0,  6, -7,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  3, -2,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  1, -2,  0,  0,  0,  0,  0, -2 },
+      {  0,  0,  1, -1,  1,  0,  0, -1,  0,  0, -2,  0,  0,  0 },
+      {  0,  0,  1, -1,  2,  0,  0, -1,  0, -2,  5,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  5, -7,  0,  0,  0,  0,  0 },
+
+   /* 421-430 */
+      {  0,  0,  0,  0,  0,  0,  1, -3,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  5, -8,  0,  0,  0,  0, -2 },
+      {  0,  0,  0,  0,  0,  0,  0,  2, -6,  0,  0,  0,  0, -2 },
+      {  1,  0,  0, -2,  0,  0, 20,-21,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  8,-12,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  5, -6,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  4, -4,  0,  0,  0,  0,  0 },
+      {  0,  0,  1, -1,  2,  0,  0, -1,  0, -1,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  8,-12,  0,  0,  0,  0,  0, -2 },
+      {  0,  0,  0,  0,  0,  0,  0,  9,-17,  0,  0,  0,  0,  0 },
+
+   /* 431-440 */
+      {  0,  0,  0,  0,  0,  0,  0,  5, -6,  0,  0,  0,  0,  2 },
+      {  0,  0,  0,  0,  0,  0,  0,  4, -8,  1,  5,  0,  0,  2 },
+      {  0,  0,  0,  0,  0,  0,  0,  4, -6,  0,  0,  0,  0, -2 },
+      {  0,  0,  0,  0,  0,  0,  0,  2, -7,  0,  0,  0,  0, -2 },
+      {  1,  0,  0, -1,  1,  0,  0, -3,  4,  0,  0,  0,  0,  0 },
+      {  1,  0, -2,  0, -2,  0,-10,  3,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  1,  0,  0, -9, 17,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  1, -4,  0,  0,  0,  0,  0, -2 },
+      {  1,  0, -2, -2, -2,  0,  0, -2,  0,  3,  0,  0,  0,  0 },
+      {  1,  0, -1,  1, -1,  0,  0,  1,  0,  0,  0,  0,  0,  0 },
+
+   /* 441-450 */
+      {  0,  0,  2, -2,  2,  0,  0, -2,  0,  2,  0,  0,  0,  0 },
+      {  0,  0,  1, -1,  2,  0,  0, -1,  0,  0,  1,  0,  0,  0 },
+      {  0,  0,  1, -1,  2,  0, -5,  7,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  1,  0,  0,  2, -2,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  4, -5,  0,  0,  0,  0,  0, -1 },
+      {  0,  0,  0,  0,  0,  0,  3, -4,  0,  0,  0,  0,  0, -2 },
+      {  0,  0,  0,  0,  0,  0,  2, -4,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  5,-10,  0,  0,  0,  0, -2 },
+      {  0,  0,  0,  0,  0,  0,  0,  4,  0, -4,  0,  0,  0,  2 },
+      {  0,  0,  0,  0,  0,  0,  0,  2,  0, -5,  0,  0,  0, -2 },
+
+   /* 451-460 */
+      {  0,  0,  0,  0,  0,  0,  0,  1,  0, -5,  0,  0,  0, -2 },
+      {  0,  0,  0,  0,  0,  0,  0,  1,  0, -2,  5,  0,  0,  2 },
+      {  0,  0,  0,  0,  0,  0,  0,  1,  0, -2,  0,  0,  0, -2 },
+      {  0,  0,  0,  0,  0,  0,  2, -3,  0,  0,  0,  0,  0,  1 },
+      {  1,  0,  0, -2,  0,  0,  0,  1,  0, -1,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  3, -7,  4,  0,  0,  0,  0,  0 },
+      {  2,  0,  2,  0,  1,  0,  0,  1,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  1, -1, -1,  0,  0, -1,  0, -1,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  1,  0,  0,  1,  0, -2,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  6,-10,  0,  0,  0,  0, -2 },
+
+   /* 461-470 */
+      {  1,  0,  0, -1,  1,  0,  0, -1,  0,  1,  0,  0,  0,  0 },
+      {  0,  0,  2, -2,  1,  0,  0,  4, -8,  3,  0,  0,  0,  0 },
+      {  0,  0,  2, -2,  1,  0,  0,  1,  0, -1,  0,  0,  0,  0 },
+      {  0,  0,  2, -2,  1,  0,  0, -4,  8, -3,  0,  0,  0,  0 },
+      {  0,  0,  2, -2,  1,  0,  0, -3,  0,  3,  0,  0,  0,  0 },
+      {  0,  0,  2, -2,  1,  0, -5,  5,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  1, -1,  1,  0,  1, -3,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  1, -1,  1,  0,  0, -4,  6,  0,  0,  0,  0,  0 },
+      {  0,  0,  1, -1,  1,  0,  0, -1,  0,  0,  0, -1,  0,  0 },
+      {  0,  0,  1, -1,  1,  0, -5,  6,  0,  0,  0,  0,  0,  0 },
+
+   /* 471-480 */
+      {  0,  0,  0,  0,  1,  0,  3, -4,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  1,  0, -2,  2,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  7,-10,  0,  0,  0,  0,  0, -1 },
+      {  0,  0,  0,  0,  0,  0,  5, -5,  0,  0,  0,  0,  0,  1 },
+      {  0,  0,  0,  0,  0,  0,  4, -5,  0,  0,  0,  0,  0, -2 },
+      {  0,  0,  0,  0,  0,  0,  3, -8,  0,  0,  0,  0,  0, -2 },
+      {  0,  0,  0,  0,  0,  0,  2, -5,  0,  0,  0,  0,  0, -1 },
+      {  0,  0,  0,  0,  0,  0,  1, -2,  0,  0,  0,  0,  0, -1 },
+      {  0,  0,  0,  0,  0,  0,  0,  7, -9,  0,  0,  0,  0,  2 },
+      {  0,  0,  0,  0,  0,  0,  0,  7, -8,  0,  0,  0,  0,  2 },
+
+   /* 481-490 */
+      {  0,  0,  0,  0,  0,  0,  0,  3,  0,  0,  0,  0,  0,  2 },
+      {  0,  0,  0,  0,  0,  0,  0,  3, -8,  3,  0,  0,  0, -2 },
+      {  0,  0,  0,  0,  0,  0,  0,  2,  0,  0, -2,  0,  0,  1 },
+      {  0,  0,  0,  0,  0,  0,  0,  2, -4,  0,  0,  0,  0,  1 },
+      {  0,  0,  0,  0,  0,  0,  0,  1,  0,  0,  0,  0,  0, -1 },
+      {  0,  0,  0,  0,  0,  0,  0,  1,  0, -1,  0,  0,  0, -1 },
+      {  2,  0,  0, -2, -1,  0,  0, -6,  8,  0,  0,  0,  0,  0 },
+      {  2,  0, -1, -1,  1,  0,  0,  3, -7,  0,  0,  0,  0,  0 },
+      {  0,  0,  2, -2,  1,  0,  0, -7,  9,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  3, -5,  0,  0,  0,  0, -1 },
+
+   /* 491-500 */
+      {  0,  0,  1, -1,  2,  0, -8, 12,  0,  0,  0,  0,  0,  0 },
+      {  1,  0,  0,  0,  0,  0,  0, -2,  0,  2,  0,  0,  0,  0 },
+      {  1,  0,  0, -2,  0,  0,  2, -2,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  7, -8,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  0,  2,  0,  0,  0,  0,  0 },
+      {  2,  0,  0, -2,  1,  0,  0, -5,  6,  0,  0,  0,  0,  0 },
+      {  2,  0,  0, -2, -1,  0,  0, -2,  0,  3, -1,  0,  0,  0 },
+      {  1,  0,  1,  1,  1,  0,  0,  1,  0,  0,  0,  0,  0,  0 },
+      {  1,  0,  0, -2,  1,  0,  0, -2,  0,  2,  0,  0,  0,  0 },
+      {  1,  0,  0, -2, -1,  0,  0, -2,  0,  2,  0,  0,  0,  0 },
+
+   /* 501-510 */
+      {  1,  0,  0, -1, -1,  0,  0, -3,  4,  0,  0,  0,  0,  0 },
+      {  1,  0, -1,  0, -1,  0, -3,  5,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  2, -2,  1,  0,  0, -4,  4,  0,  0,  0,  0,  0 },
+      {  0,  0,  2, -2,  1,  0,  0, -2,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  2, -2,  1,  0, -8, 11,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  2, -2,  0,  0,  0, -9, 13,  0,  0,  0,  0,  0 },
+      {  0,  0,  1,  1,  2,  0,  0,  1,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  1, -1,  1,  0,  0,  1, -4,  0,  0,  0,  0,  0 },
+      {  0,  0,  1, -1,  1,  0,  0, -1,  0,  1, -3,  0,  0,  0 },
+      {  0,  0,  0,  0,  1,  0,  0,  7,-13,  0,  0,  0,  0,  0 },
+
+   /* 511-520 */
+      {  0,  0,  0,  0,  1,  0,  0,  2,  0, -2,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  1,  0,  0, -2,  2,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  1,  0, -3,  4,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  1,  0, -4,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  7,-11,  0,  0,  0,  0,  0, -1 },
+      {  0,  0,  0,  0,  0,  0,  6, -6,  0,  0,  0,  0,  0,  1 },
+      {  0,  0,  0,  0,  0,  0,  6, -4,  0,  0,  0,  0,  0,  1 },
+      {  0,  0,  0,  0,  0,  0,  5, -6,  0,  0,  0,  0,  0, -1 },
+      {  0,  0,  0,  0,  0,  0,  4, -2,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  3, -4,  0,  0,  0,  0,  0,  1 },
+
+   /* 521-530 */
+      {  0,  0,  0,  0,  0,  0,  1, -4,  0,  0,  0,  0,  0, -1 },
+      {  0,  0,  0,  0,  0,  0,  0,  9,-17,  0,  0,  0,  0, -2 },
+      {  0,  0,  0,  0,  0,  0,  0,  7, -7,  0,  0,  0,  0,  2 },
+      {  0,  0,  0,  0,  0,  0,  0,  4, -8,  3,  0,  0,  0,  1 },
+      {  0,  0,  0,  0,  0,  0,  0,  4, -8,  3,  0,  0,  0, -1 },
+      {  0,  0,  0,  0,  0,  0,  0,  4, -8,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  4, -7,  0,  0,  0,  0, -1 },
+      {  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  0,  0,  1 },
+      {  0,  0,  0,  0,  0,  0,  0,  1,  0, -4,  0,  0,  0,  0 },
+      {  2,  0,  0, -2,  0,  0,  0, -4,  8, -3,  0,  0,  0,  0 },
+
+   /* 531-540 */
+      {  2,  0,  0, -2,  0,  0, -2,  2,  0,  0,  0,  0,  0,  0 },
+      {  1,  0,  0,  0,  0,  0,  0,  4, -8,  3,  0,  0,  0,  0 },
+      {  1,  0,  0,  0,  0,  0,  0, -4,  8, -3,  0,  0,  0,  0 },
+      {  1,  0,  0,  0,  0,  0, -1,  1,  0,  0,  0,  0,  0,  0 },
+      {  1,  0,  0, -2,  0,  0, 17,-16,  0, -2,  0,  0,  0,  0 },
+      {  1,  0,  0, -1,  0,  0,  0, -2,  2,  0,  0,  0,  0,  0 },
+      {  0,  0,  2, -2,  0,  0,  0, -2,  0,  2,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  6, -9,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  4,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  3,  0, -4,  0,  0,  0,  0 },
+
+   /* 541-550 */
+      {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1, -2, -2 },
+      {  0,  0,  0,  0,  0,  0,  0,  2,  1,  0,  0,  0,  0,  2 },
+      {  2,  0,  0, -2,  0,  0,  0, -4,  4,  0,  0,  0,  0,  0 },
+      {  2,  0,  0, -2,  0,  0,  0, -2,  0,  2,  2,  0,  0,  0 },
+      {  1,  0,  0,  0,  0,  0,  1, -1,  0,  0,  0,  0,  0,  0 },
+      {  1,  0,  0,  0,  0,  0,  0, -1,  0,  1,  0,  0,  0,  0 },
+      {  1,  0,  0,  0,  0,  0, -3,  3,  0,  0,  0,  0,  0,  0 },
+      {  1,  0,  0, -2,  0,  0,  1, -1,  0,  0,  0,  0,  0,  0 },
+      {  1,  0,  0, -2,  0,  0,  0,  4, -8,  3,  0,  0,  0,  0 },
+      {  1,  0,  0, -2,  0,  0,  0, -4,  8, -3,  0,  0,  0,  0 },
+
+   /* 551-560 */
+      {  1,  0,  0, -2,  0,  0, -2,  2,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  2, -2,  0,  0, -4,  4,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  1,  1,  0,  0,  0,  1,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  1, -1,  0,  0,  3, -6,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  1, -1,  0,  0,  0, -2,  2,  0,  0,  0,  0,  0 },
+      {  0,  0,  1, -1,  0,  0,  0, -1,  0,  1,  0,  0,  0,  0 },
+      {  0,  0,  1, -1,  0,  0,  0, -1,  0,  0,  1,  0,  0,  0 },
+      {  0,  0,  1, -1,  0,  0, -4,  5,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  1, -1,  0,  0, -3,  4,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  2,  0,  0,  0, -1,  0,  1,  0,  0,  0,  0 },
+
+   /* 561-570 */
+      {  0,  0,  0,  0,  0,  0,  8, -9,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  3, -6,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  1,  1,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  0,  0,  3, -5,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  0,  0,  2, -2,  0,  0,  0 },
+      {  2,  0, -2, -2, -2,  0,  0, -2,  0,  2,  0,  0,  0,  0 },
+      {  1,  0,  0,  0,  1,  0,-10,  3,  0,  0,  0,  0,  0,  0 },
+      {  1,  0,  0,  0, -1,  0,-10,  3,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  2,  0,  2,  0,  2, -3,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  2,  0,  2,  0,  2, -2,  0,  0,  0,  0,  0,  0 },
+
+   /* 571-580 */
+      {  0,  0,  2,  0,  2,  0, -2,  3,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  2,  0,  2,  0, -2,  2,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  2,  0,  0,  0,  0,  1,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  1,  0,  0, -1,  0,  2,  0,  0,  0,  0 },
+      {  2,  0,  2, -2,  2,  0,  0, -2,  0,  3,  0,  0,  0,  0 },
+      {  2,  0,  1, -3,  1,  0, -6,  7,  0,  0,  0,  0,  0,  0 },
+      {  2,  0,  0, -2,  0,  0,  2, -5,  0,  0,  0,  0,  0,  0 },
+      {  2,  0,  0, -2,  0,  0,  0, -2,  0,  5, -5,  0,  0,  0 },
+      {  2,  0,  0, -2,  0,  0,  0, -2,  0,  1,  5,  0,  0,  0 },
+      {  2,  0,  0, -2,  0,  0,  0, -2,  0,  0,  5,  0,  0,  0 },
+
+   /* 581-590 */
+      {  2,  0,  0, -2,  0,  0,  0, -2,  0,  0,  2,  0,  0,  0 },
+      {  2,  0,  0, -2,  0,  0, -4,  4,  0,  0,  0,  0,  0,  0 },
+      {  2,  0, -2,  0, -2,  0,  0,  5, -9,  0,  0,  0,  0,  0 },
+      {  2,  0, -1, -1,  0,  0,  0, -1,  0,  3,  0,  0,  0,  0 },
+      {  1,  0,  2,  0,  2,  0,  1, -1,  0,  0,  0,  0,  0,  0 },
+      {  1,  0,  2,  0,  2,  0,  0,  4, -8,  3,  0,  0,  0,  0 },
+      {  1,  0,  2,  0,  2,  0,  0, -4,  8, -3,  0,  0,  0,  0 },
+      {  1,  0,  2,  0,  2,  0, -1,  1,  0,  0,  0,  0,  0,  0 },
+      {  1,  0,  2, -2,  2,  0, -3,  3,  0,  0,  0,  0,  0,  0 },
+      {  1,  0,  0,  0,  0,  0,  0,  1,  0, -1,  0,  0,  0,  0 },
+
+   /* 591-600 */
+      {  1,  0,  0,  0,  0,  0,  0, -2,  0,  3,  0,  0,  0,  0 },
+      {  1,  0,  0, -2,  0,  0,  0,  2,  0, -2,  0,  0,  0,  0 },
+      {  1,  0, -2, -2, -2,  0,  0,  1,  0, -1,  0,  0,  0,  0 },
+      {  1,  0, -1,  1,  0,  0,  0,  1,  0,  0,  0,  0,  0,  0 },
+      {  1,  0, -1, -1,  0,  0,  0,  8,-15,  0,  0,  0,  0,  0 },
+      {  0,  0,  2,  2,  2,  0,  0,  2,  0, -2,  0,  0,  0,  0 },
+      {  0,  0,  2, -2,  1,  0,  1, -1,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  2, -2,  1,  0,  0, -2,  0,  1,  0,  0,  0,  0 },
+      {  0,  0,  2, -2,  1,  0,  0,-10, 15,  0,  0,  0,  0,  0 },
+      {  0,  0,  2, -2,  0, -1,  0,  2,  0,  0,  0,  0,  0,  0 },
+
+   /* 601-610 */
+      {  0,  0,  1, -1,  2,  0,  0, -1,  0,  0, -1,  0,  0,  0 },
+      {  0,  0,  1, -1,  2,  0, -3,  4,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  1, -1,  1,  0, -4,  6,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  1, -1,  1,  0, -1,  2,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  1, -1,  0,  0,  0,  1,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  1, -1,  0,  0,  0, -1,  0,  0, -2,  0,  0,  0 },
+      {  0,  0,  1, -1,  0,  0, -2,  2,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  1, -1,  0,  0, -1,  0,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  1, -1, -1,  0, -5,  7,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  2,  0,  0,  0,  2,  0, -2,  0,  0,  0,  0 },
+
+   /* 611-620 */
+      {  0,  0,  0,  2,  0,  0, -2,  2,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  2,  0, -3,  5,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  1,  0, -1,  2,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  9,-13,  0,  0,  0,  0,  0, -2 },
+      {  0,  0,  0,  0,  0,  0,  8,-14,  0,  0,  0,  0,  0, -2 },
+      {  0,  0,  0,  0,  0,  0,  8,-11,  0,  0,  0,  0,  0, -1 },
+      {  0,  0,  0,  0,  0,  0,  6, -9,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  6, -8,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  6, -7,  0,  0,  0,  0,  0, -1 },
+      {  0,  0,  0,  0,  0,  0,  5, -6,  0,  0,  0,  0,  0, -2 },
+
+   /* 621-630 */
+      {  0,  0,  0,  0,  0,  0,  5, -6, -4,  0,  0,  0,  0, -2 },
+      {  0,  0,  0,  0,  0,  0,  5, -4,  0,  0,  0,  0,  0,  2 },
+      {  0,  0,  0,  0,  0,  0,  4, -8,  0,  0,  0,  0,  0, -2 },
+      {  0,  0,  0,  0,  0,  0,  4, -5,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  3, -3,  0,  2,  0,  0,  0,  2 },
+      {  0,  0,  0,  0,  0,  0,  3, -1,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  2,  0,  0,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  1, -1,  0,  0,  0,  0,  0, -2 },
+      {  0,  0,  0,  0,  0,  0,  0,  7,-12,  0,  0,  0,  0, -2 },
+      {  0,  0,  0,  0,  0,  0,  0,  6, -9,  0,  0,  0,  0, -2 },
+
+   /* 631-640 */
+      {  0,  0,  0,  0,  0,  0,  0,  6, -8,  1,  5,  0,  0,  2 },
+      {  0,  0,  0,  0,  0,  0,  0,  6, -4,  0,  0,  0,  0,  2 },
+      {  0,  0,  0,  0,  0,  0,  0,  6,-10,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  5,  0, -4,  0,  0,  0,  2 },
+      {  0,  0,  0,  0,  0,  0,  0,  5, -9,  0,  0,  0,  0, -1 },
+      {  0,  0,  0,  0,  0,  0,  0,  5, -8,  3,  0,  0,  0,  2 },
+      {  0,  0,  0,  0,  0,  0,  0,  5, -7,  0,  0,  0,  0, -2 },
+      {  0,  0,  0,  0,  0,  0,  0,  5, -6,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  5,-16,  4,  5,  0,  0, -2 },
+      {  0,  0,  0,  0,  0,  0,  0,  5,-13,  0,  0,  0,  0, -2 },
+
+   /* 641-650 */
+      {  0,  0,  0,  0,  0,  0,  0,  3,  0, -5,  0,  0,  0, -2 },
+      {  0,  0,  0,  0,  0,  0,  0,  3, -9,  0,  0,  0,  0, -2 },
+      {  0,  0,  0,  0,  0,  0,  0,  3, -7,  0,  0,  0,  0, -2 },
+      {  0,  0,  0,  0,  0,  0,  0,  2,  0,  2,  0,  0,  0,  2 },
+      {  0,  0,  0,  0,  0,  0,  0,  2,  0,  0, -3,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  2, -8,  1,  5,  0,  0, -2 },
+      {  0,  0,  0,  0,  0,  0,  0,  1,  0,  1, -5,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  1,  0,  0,  2,  0,  0,  2 },
+      {  0,  0,  0,  0,  0,  0,  0,  1,  0,  0, -3,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  1,  0, -3,  5,  0,  0,  0 },
+
+   /* 651-NFPL */
+      {  0,  0,  0,  0,  0,  0,  0,  1, -3,  0,  0,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  0,  0,  2, -6,  3,  0, -2 },
+      {  0,  0,  0,  0,  0,  0,  0,  0,  0,  1, -2,  0,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  0 },
+      {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  2 },
+      {  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  0,  0,  0,  0 }
+   };
+
+/* Number of frequencies:  planetary */
+   static const int NFPL = (int) (sizeof mfapl / sizeof (int) / 14);
+
+/* Pointers into amplitudes array, one pointer per frequency */
+   static const int nc[] = {
+
+   /* 1-100 */
+       1,    21,    37,    51,    65,    79,    91,   103,   115,   127,
+     139,   151,   163,   172,   184,   196,   207,   219,   231,   240,
+     252,   261,   273,   285,   297,   309,   318,   327,   339,   351,
+     363,   372,   384,   396,   405,   415,   423,   435,   444,   452,
+     460,   467,   474,   482,   490,   498,   506,   513,   521,   528,
+     536,   543,   551,   559,   566,   574,   582,   590,   597,   605,
+     613,   620,   628,   636,   644,   651,   658,   666,   674,   680,
+     687,   695,   702,   710,   717,   725,   732,   739,   746,   753,
+     760,   767,   774,   782,   790,   798,   805,   812,   819,   826,
+     833,   840,   846,   853,   860,   867,   874,   881,   888,   895,
+
+   /* 101-200 */
+     901,   908,   914,   921,   928,   934,   941,   948,   955,   962,
+     969,   976,   982,   989,   996,  1003,  1010,  1017,  1024,  1031,
+    1037,  1043,  1050,  1057,  1064,  1071,  1078,  1084,  1091,  1098,
+    1104,  1112,  1118,  1124,  1131,  1138,  1145,  1151,  1157,  1164,
+    1171,  1178,  1185,  1192,  1199,  1205,  1212,  1218,  1226,  1232,
+    1239,  1245,  1252,  1259,  1266,  1272,  1278,  1284,  1292,  1298,
+    1304,  1310,  1316,  1323,  1329,  1335,  1341,  1347,  1353,  1359,
+    1365,  1371,  1377,  1383,  1389,  1396,  1402,  1408,  1414,  1420,
+    1426,  1434,  1440,  1446,  1452,  1459,  1465,  1471,  1477,  1482,
+    1488,  1493,  1499,  1504,  1509,  1514,  1520,  1527,  1532,  1538,
+
+   /* 201-300 */
+    1543,  1548,  1553,  1558,  1564,  1569,  1574,  1579,  1584,  1589,
+    1594,  1596,  1598,  1600,  1602,  1605,  1608,  1610,  1612,  1617,
+    1619,  1623,  1625,  1627,  1629,  1632,  1634,  1640,  1642,  1644,
+    1646,  1648,  1650,  1652,  1654,  1658,  1660,  1662,  1664,  1668,
+    1670,  1672,  1673,  1675,  1679,  1681,  1683,  1684,  1686,  1688,
+    1690,  1693,  1695,  1697,  1701,  1703,  1705,  1707,  1709,  1711,
+    1712,  1715,  1717,  1721,  1723,  1725,  1727,  1729,  1731,  1733,
+    1735,  1737,  1739,  1741,  1743,  1745,  1747,  1749,  1751,  1753,
+    1755,  1757,  1759,  1761,  1762,  1764,  1766,  1768,  1769,  1771,
+    1773,  1775,  1777,  1779,  1781,  1783,  1785,  1787,  1788,  1790,
+
+   /* 301-400 */
+    1792,  1794,  1796,  1798,  1800,  1802,  1804,  1806,  1807,  1809,
+    1811,  1815,  1817,  1819,  1821,  1823,  1825,  1827,  1829,  1831,
+    1833,  1835,  1837,  1839,  1840,  1842,  1844,  1848,  1850,  1852,
+    1854,  1856,  1858,  1859,  1860,  1862,  1864,  1866,  1868,  1869,
+    1871,  1873,  1875,  1877,  1879,  1881,  1883,  1885,  1887,  1889,
+    1891,  1892,  1896,  1898,  1900,  1901,  1903,  1905,  1907,  1909,
+    1910,  1911,  1913,  1915,  1919,  1921,  1923,  1927,  1929,  1931,
+    1933,  1935,  1937,  1939,  1943,  1945,  1947,  1948,  1949,  1951,
+    1953,  1955,  1957,  1958,  1960,  1962,  1964,  1966,  1968,  1970,
+    1971,  1973,  1974,  1975,  1977,  1979,  1980,  1981,  1982,  1984,
+
+   /* 401-500 */
+    1986,  1988,  1990,  1992,  1994,  1995,  1997,  1999,  2001,  2003,
+    2005,  2007,  2008,  2009,  2011,  2013,  2015,  2017,  2019,  2021,
+    2023,  2024,  2025,  2027,  2029,  2031,  2033,  2035,  2037,  2041,
+    2043,  2045,  2046,  2047,  2049,  2051,  2053,  2055,  2056,  2057,
+    2059,  2061,  2063,  2065,  2067,  2069,  2070,  2071,  2072,  2074,
+    2076,  2078,  2080,  2082,  2084,  2086,  2088,  2090,  2092,  2094,
+    2095,  2096,  2097,  2099,  2101,  2105,  2106,  2107,  2108,  2109,
+    2110,  2111,  2113,  2115,  2119,  2121,  2123,  2125,  2127,  2129,
+    2131,  2133,  2135,  2136,  2137,  2139,  2141,  2143,  2145,  2147,
+    2149,  2151,  2153,  2155,  2157,  2159,  2161,  2163,  2165,  2167,
+
+   /* 501-600 */
+    2169,  2171,  2173,  2175,  2177,  2179,  2181,  2183,  2185,  2186,
+    2187,  2188,  2192,  2193,  2195,  2197,  2199,  2201,  2203,  2205,
+    2207,  2209,  2211,  2213,  2217,  2219,  2221,  2223,  2225,  2227,
+    2229,  2231,  2233,  2234,  2235,  2236,  2237,  2238,  2239,  2240,
+    2241,  2244,  2246,  2248,  2250,  2252,  2254,  2256,  2258,  2260,
+    2262,  2264,  2266,  2268,  2270,  2272,  2274,  2276,  2278,  2280,
+    2282,  2284,  2286,  2288,  2290,  2292,  2294,  2296,  2298,  2300,
+    2302,  2303,  2304,  2305,  2306,  2307,  2309,  2311,  2313,  2315,
+    2317,  2319,  2321,  2323,  2325,  2327,  2329,  2331,  2333,  2335,
+    2337,  2341,  2343,  2345,  2347,  2349,  2351,  2352,  2355,  2356,
+
+   /* 601-700 */
+    2357,  2358,  2359,  2361,  2363,  2364,  2365,  2366,  2367,  2368,
+    2369,  2370,  2371,  2372,  2373,  2374,  2376,  2378,  2380,  2382,
+    2384,  2385,  2386,  2387,  2388,  2389,  2390,  2391,  2392,  2393,
+    2394,  2395,  2396,  2397,  2398,  2399,  2400,  2401,  2402,  2403,
+    2404,  2405,  2406,  2407,  2408,  2409,  2410,  2411,  2412,  2413,
+    2414,  2415,  2417,  2418,  2430,  2438,  2445,  2453,  2460,  2468,
+    2474,  2480,  2488,  2496,  2504,  2512,  2520,  2527,  2535,  2543,
+    2550,  2558,  2566,  2574,  2580,  2588,  2596,  2604,  2612,  2619,
+    2627,  2634,  2642,  2648,  2656,  2664,  2671,  2679,  2685,  2693,
+    2701,  2709,  2717,  2725,  2733,  2739,  2747,  2753,  2761,  2769,
+
+   /* 701-800 */
+    2777,  2785,  2793,  2801,  2809,  2817,  2825,  2833,  2841,  2848,
+    2856,  2864,  2872,  2878,  2884,  2892,  2898,  2906,  2914,  2922,
+    2930,  2938,  2944,  2952,  2958,  2966,  2974,  2982,  2988,  2996,
+    3001,  3009,  3017,  3025,  3032,  3039,  3045,  3052,  3059,  3067,
+    3069,  3076,  3083,  3090,  3098,  3105,  3109,  3111,  3113,  3120,
+    3124,  3128,  3132,  3136,  3140,  3144,  3146,  3150,  3158,  3161,
+    3165,  3166,  3168,  3172,  3176,  3180,  3182,  3185,  3189,  3193,
+    3194,  3197,  3200,  3204,  3208,  3212,  3216,  3219,  3221,  3222,
+    3226,  3230,  3234,  3238,  3242,  3243,  3247,  3251,  3254,  3258,
+    3262,  3266,  3270,  3274,  3275,  3279,  3283,  3287,  3289,  3293,
+
+   /* 801-900 */
+    3296,  3300,  3303,  3307,  3311,  3315,  3319,  3321,  3324,  3327,
+    3330,  3334,  3338,  3340,  3342,  3346,  3350,  3354,  3358,  3361,
+    3365,  3369,  3373,  3377,  3381,  3385,  3389,  3393,  3394,  3398,
+    3402,  3406,  3410,  3413,  3417,  3421,  3425,  3429,  3433,  3435,
+    3439,  3443,  3446,  3450,  3453,  3457,  3458,  3461,  3464,  3468,
+    3472,  3476,  3478,  3481,  3485,  3489,  3493,  3497,  3501,  3505,
+    3507,  3511,  3514,  3517,  3521,  3524,  3525,  3527,  3529,  3533,
+    3536,  3540,  3541,  3545,  3548,  3551,  3555,  3559,  3563,  3567,
+    3569,  3570,  3574,  3576,  3578,  3582,  3586,  3590,  3593,  3596,
+    3600,  3604,  3608,  3612,  3616,  3620,  3623,  3626,  3630,  3632,
+
+   /* 901-1000 */
+    3636,  3640,  3643,  3646,  3648,  3652,  3656,  3660,  3664,  3667,
+    3669,  3671,  3675,  3679,  3683,  3687,  3689,  3693,  3694,  3695,
+    3699,  3703,  3705,  3707,  3710,  3713,  3717,  3721,  3725,  3729,
+    3733,  3736,  3740,  3744,  3748,  3752,  3754,  3757,  3759,  3763,
+    3767,  3770,  3773,  3777,  3779,  3783,  3786,  3790,  3794,  3798,
+    3801,  3805,  3809,  3813,  3817,  3821,  3825,  3827,  3831,  3835,
+    3836,  3837,  3840,  3844,  3848,  3852,  3856,  3859,  3863,  3867,
+    3869,  3871,  3875,  3879,  3883,  3887,  3890,  3894,  3898,  3901,
+    3905,  3909,  3913,  3917,  3921,  3922,  3923,  3924,  3926,  3930,
+    3932,  3936,  3938,  3940,  3944,  3948,  3952,  3956,  3959,  3963,
+
+   /* 1001-1100 */
+    3965,  3969,  3973,  3977,  3979,  3981,  3982,  3986,  3989,  3993,
+    3997,  4001,  4004,  4006,  4009,  4012,  4016,  4020,  4024,  4026,
+    4028,  4032,  4036,  4040,  4044,  4046,  4050,  4054,  4058,  4060,
+    4062,  4063,  4064,  4068,  4071,  4075,  4077,  4081,  4083,  4087,
+    4089,  4091,  4095,  4099,  4101,  4103,  4105,  4107,  4111,  4115,
+    4119,  4123,  4127,  4129,  4131,  4135,  4139,  4141,  4143,  4145,
+    4149,  4153,  4157,  4161,  4165,  4169,  4173,  4177,  4180,  4183,
+    4187,  4191,  4195,  4198,  4201,  4205,  4209,  4212,  4213,  4216,
+    4217,  4221,  4223,  4226,  4230,  4234,  4236,  4240,  4244,  4248,
+    4252,  4256,  4258,  4262,  4264,  4266,  4268,  4270,  4272,  4276,
+
+   /* 1101-1200 */
+    4279,  4283,  4285,  4287,  4289,  4293,  4295,  4299,  4300,  4301,
+    4305,  4309,  4313,  4317,  4319,  4323,  4325,  4329,  4331,  4333,
+    4335,  4337,  4341,  4345,  4349,  4351,  4353,  4357,  4361,  4365,
+    4367,  4369,  4373,  4377,  4381,  4383,  4387,  4389,  4391,  4395,
+    4399,  4403,  4407,  4411,  4413,  4414,  4415,  4418,  4419,  4421,
+    4423,  4427,  4429,  4431,  4433,  4435,  4437,  4439,  4443,  4446,
+    4450,  4452,  4456,  4458,  4460,  4462,  4466,  4469,  4473,  4477,
+    4481,  4483,  4487,  4489,  4491,  4493,  4497,  4499,  4501,  4504,
+    4506,  4510,  4513,  4514,  4515,  4518,  4521,  4522,  4525,  4526,
+    4527,  4530,  4533,  4534,  4537,  4541,  4542,  4543,  4544,  4545,
+
+   /* 1201-1300 */
+    4546,  4547,  4550,  4553,  4554,  4555,  4558,  4561,  4564,  4567,
+    4568,  4571,  4574,  4575,  4578,  4581,  4582,  4585,  4586,  4588,
+    4590,  4592,  4596,  4598,  4602,  4604,  4608,  4612,  4613,  4616,
+    4619,  4622,  4623,  4624,  4625,  4626,  4629,  4632,  4633,  4636,
+    4639,  4640,  4641,  4642,  4643,  4644,  4645,  4648,  4649,  4650,
+    4651,  4652,  4653,  4656,  4657,  4660,  4661,  4664,  4667,  4670,
+    4671,  4674,  4675,  4676,  4677,  4678,  4681,  4682,  4683,  4684,
+    4687,  4688,  4689,  4692,  4693,  4696,  4697,  4700,  4701,  4702,
+    4703,  4704,  4707,  4708,  4711,  4712,  4715,  4716,  4717,  4718,
+    4719,  4720,  4721,  4722,  4723,  4726,  4729,  4730,  4733,  4736,
+
+   /* 1301-(NFLS+NFPL) */
+    4737,  4740,  4741,  4742,  4745,  4746,  4749,  4752,  4753
+   };
+
+/* Amplitude coefficients (microarcsec);  indexed using the nc array. */
+   static const double a[] = {
+
+   /* 1-105 */
+         -6844318.44,     9205236.26,1328.67,1538.18,      205833.11,
+           153041.79,       -3309.73, 853.32,2037.98,       -2301.27,
+       81.46, 120.56, -20.39, -15.22,   1.73,  -1.61,  -0.10,   0.11,
+       -0.02,  -0.02,     -523908.04,      573033.42,-544.75,-458.66,
+            12814.01,       11714.49, 198.97,-290.91, 155.74,-143.27,
+       -2.75,  -1.03,  -1.27,  -1.16,   0.00,  -0.01,      -90552.22,
+            97846.69, 111.23, 137.41,2187.91,2024.68,  41.44, -51.26,
+       26.92, -24.46,  -0.46,  -0.28,  -0.22,  -0.20,       82168.76,
+           -89618.24, -27.64, -29.05,       -2004.36,       -1837.32,
+      -36.07,  48.00, -24.43,  22.41,   0.47,   0.24,   0.20,   0.18,
+            58707.02,7387.02, 470.05,-192.40, 164.33,       -1312.21,
+     -179.73, -28.93, -17.36,  -1.83,  -0.50,   3.57,   0.00,   0.13,
+           -20557.78,       22438.42, -20.84, -17.40, 501.82, 459.68,
+       59.20, -67.30,   6.08,  -5.61,  -1.36,  -1.19,       28288.28,
+     -674.99, -34.69,  35.80, -15.07,-632.54, -11.19,   0.78,  -8.41,
+        0.17,   0.01,   0.07,      -15406.85,       20069.50,  15.12,
+
+   /* 106-219 */
+       31.80, 448.76, 344.50,  -5.77,   1.41,   4.59,  -5.02,   0.17,
+        0.24,      -11991.74,       12902.66,  32.46,  36.70, 288.49,
+      268.14,   5.70,  -7.06,   3.57,  -3.23,  -0.06,  -0.04,
+            -8584.95,       -9592.72,   4.42, -13.20,-214.50, 192.06,
+       23.87,  29.83,   2.54,   2.40,   0.60,  -0.48,5095.50,
+            -6918.22,   7.19,   3.92,-154.91,-113.94,   2.86,  -1.04,
+       -1.52,   1.73,  -0.07,  -0.10,       -4910.93,       -5331.13,
+        0.76,   0.40,-119.21, 109.81,   2.16,   3.20,   1.46,   1.33,
+        0.04,  -0.02,       -6245.02,-123.48,  -6.68,  -8.20,  -2.76,
+      139.64,   2.71,   0.15,   1.86,2511.85,       -3323.89,   1.07,
+       -0.90, -74.33, -56.17,   1.16,  -0.01,  -0.75,   0.83,  -0.02,
+       -0.04,2307.58,3143.98,  -7.52,   7.50,  70.31, -51.60,   1.46,
+        0.16,  -0.69,  -0.79,   0.02,  -0.05,2372.58,2554.51,   5.93,
+       -6.60,  57.12, -53.05,  -0.96,  -1.24,  -0.71,  -0.64,  -0.01,
+            -2053.16,2636.13,   5.13,   7.80,  58.94,  45.91,  -0.42,
+       -0.12,   0.61,  -0.66,   0.02,   0.03,       -1825.49,
+
+   /* 220-339 */
+            -2423.59,   1.23,  -2.00, -54.19,  40.82,  -1.07,  -1.02,
+        0.54,   0.61,  -0.04,   0.04,2521.07,-122.28,  -5.97,   2.90,
+       -2.73, -56.37,  -0.82,   0.13,  -0.75,       -1534.09,1645.01,
+        6.29,   6.80,  36.78,  34.30,   0.92,  -1.25,   0.46,  -0.41,
+       -0.02,  -0.01,1898.27,  47.70,  -0.72,   2.50,   1.07, -42.45,
+       -0.94,   0.02,  -0.56,       -1292.02,       -1387.00,   0.00,
+        0.00, -31.01,  28.89,   0.68,   0.00,   0.38,   0.35,  -0.01,
+       -0.01,       -1234.96,1323.81,   5.21,   5.90,  29.60,  27.61,
+        0.74,  -1.22,   0.37,  -0.33,  -0.02,  -0.01,1137.48,
+            -1233.89,  -0.04,  -0.30, -27.59, -25.43,  -0.61,   1.00,
+       -0.34,   0.31,   0.01,   0.01,-813.13,       -1075.60,   0.40,
+        0.30, -24.05,  18.18,  -0.40,  -0.01,   0.24,   0.27,  -0.01,
+        0.01,1163.22, -60.90,  -2.94,   1.30,  -1.36, -26.01,  -0.58,
+        0.07,  -0.35,1029.70, -55.55,  -2.63,   1.10,  -1.25, -23.02,
+       -0.52,   0.06,  -0.31,-556.26, 852.85,   3.16,  -4.48,  19.06,
+       12.44,  -0.81,  -0.27,   0.17,  -0.21,   0.00,   0.02,-603.52,
+
+   /* 340-467 */
+     -800.34,   0.44,   0.10, -17.90,  13.49,  -0.08,  -0.01,   0.18,
+        0.20,  -0.01,   0.01,-628.24, 684.99,  -0.64,  -0.50,  15.32,
+       14.05,   3.18,  -4.19,   0.19,  -0.17,  -0.09,  -0.07,-866.48,
+      -16.26,   0.52,  -1.30,  -0.36,  19.37,   0.43,  -0.01,   0.26,
+     -512.37, 695.54,  -1.47,  -1.40,  15.55,  11.46,  -0.16,   0.03,
+        0.15,  -0.17,   0.01,   0.01, 506.65, 643.75,   2.54,  -2.62,
+       14.40, -11.33,  -0.77,  -0.06,  -0.15,  -0.16,   0.00,   0.01,
+      664.57,  16.81,  -0.40,   1.00,   0.38, -14.86,  -3.71,  -0.09,
+       -0.20, 405.91, 522.11,   0.99,  -1.50,  11.67,  -9.08,  -0.25,
+       -0.02,  -0.12,  -0.13,-305.78, 326.60,   1.75,   1.90,   7.30,
+        6.84,   0.20,  -0.04, 300.99,-325.03,  -0.44,  -0.50,  -7.27,
+       -6.73,  -1.01,   0.01,   0.00,   0.08,   0.00,   0.02, 438.51,
+       10.47,  -0.56,  -0.20,   0.24,  -9.81,  -0.24,   0.01,  -0.13,
+     -264.02, 335.24,   0.99,   1.40,   7.49,   5.90,  -0.27,  -0.02,
+      284.09, 307.03,   0.32,  -0.40,   6.87,  -6.35,  -0.99,  -0.01,
+     -250.54, 327.11,   0.08,   0.40,   7.31,   5.60,  -0.30, 230.72,
+
+   /* 468-595 */
+     -304.46,   0.08,  -0.10,  -6.81,  -5.16,   0.27, 229.78, 304.17,
+       -0.60,   0.50,   6.80,  -5.14,   0.33,   0.01, 256.30,-276.81,
+       -0.28,  -0.40,  -6.19,  -5.73,  -0.14,   0.01,-212.82, 269.45,
+        0.84,   1.20,   6.02,   4.76,   0.14,  -0.02, 196.64, 272.05,
+       -0.84,   0.90,   6.08,  -4.40,   0.35,   0.02, 188.95, 272.22,
+       -0.12,   0.30,   6.09,  -4.22,   0.34,-292.37,  -5.10,  -0.32,
+       -0.40,  -0.11,   6.54,   0.14,   0.01, 161.79,-220.67,   0.24,
+        0.10,  -4.93,  -3.62,  -0.08, 261.54, -19.94,  -0.95,   0.20,
+       -0.45,  -5.85,  -0.13,   0.02, 142.16,-190.79,   0.20,   0.10,
+       -4.27,  -3.18,  -0.07, 187.95,  -4.11,  -0.24,   0.30,  -0.09,
+       -4.20,  -0.09,   0.01,   0.00,   0.00, -79.08, 167.90,   0.04,
+        0.00,   3.75,   1.77, 121.98, 131.04,  -0.08,   0.10,   2.93,
+       -2.73,  -0.06,-172.95,  -8.11,  -0.40,  -0.20,  -0.18,   3.87,
+        0.09,   0.01,-160.15, -55.30, -14.04,  13.90,  -1.23,   3.58,
+        0.40,   0.31,-115.40, 123.20,   0.60,   0.70,   2.75,   2.58,
+        0.08,  -0.01,-168.26,  -2.00,   0.20,  -0.20,  -0.04,   3.76,
+
+   /* 596-723 */
+        0.08,-114.49, 123.20,   0.32,   0.40,   2.75,   2.56,   0.07,
+       -0.01, 112.14, 120.70,   0.28,  -0.30,   2.70,  -2.51,  -0.07,
+       -0.01, 161.34,   4.03,   0.20,   0.20,   0.09,  -3.61,  -0.08,
+       91.31, 126.64,  -0.40,   0.40,   2.83,  -2.04,  -0.04,   0.01,
+      105.29, 112.90,   0.44,  -0.50,   2.52,  -2.35,  -0.07,  -0.01,
+       98.69,-106.20,  -0.28,  -0.30,  -2.37,  -2.21,  -0.06,   0.01,
+       86.74,-112.94,  -0.08,  -0.20,  -2.53,  -1.94,  -0.05,-134.81,
+        3.51,   0.20,  -0.20,   0.08,   3.01,   0.07,  79.03, 107.31,
+       -0.24,   0.20,   2.40,  -1.77,  -0.04,   0.01, 132.81, -10.77,
+       -0.52,   0.10,  -0.24,  -2.97,  -0.07,   0.01,-130.31,  -0.90,
+        0.04,   0.00,   0.00,   2.91, -78.56,  85.32,   0.00,   0.00,
+        1.91,   1.76,   0.04,   0.00,   0.00, -41.53,  89.10,   0.02,
+        0.00,   1.99,   0.93,  66.03, -71.00,  -0.20,  -0.20,  -1.59,
+       -1.48,  -0.04,  60.50,  64.70,   0.36,  -0.40,   1.45,  -1.35,
+       -0.04,  -0.01, -52.27, -70.01,   0.00,   0.00,  -1.57,   1.17,
+        0.03, -52.95,  66.29,   0.32,   0.40,   1.48,   1.18,   0.04,
+
+   /* 724-851 */
+       -0.01,  51.02,  67.25,   0.00,   0.00,   1.50,  -1.14,  -0.03,
+      -55.66, -60.92,   0.16,  -0.20,  -1.36,   1.24,   0.03, -54.81,
+      -59.20,  -0.08,   0.20,  -1.32,   1.23,   0.03,  51.32, -55.60,
+        0.00,   0.00,  -1.24,  -1.15,  -0.03,  48.29,  51.80,   0.20,
+       -0.20,   1.16,  -1.08,  -0.03, -45.59, -49.00,  -0.12,   0.10,
+       -1.10,   1.02,   0.03,  40.54, -52.69,  -0.04,  -0.10,  -1.18,
+       -0.91,  -0.02, -40.58, -49.51,  -1.00,   1.00,  -1.11,   0.91,
+        0.04,   0.02, -43.76,  46.50,   0.36,   0.40,   1.04,   0.98,
+        0.03,  -0.01,  62.65,  -5.00,  -0.24,   0.00,  -0.11,  -1.40,
+       -0.03,   0.01, -38.57,  49.59,   0.08,   0.10,   1.11,   0.86,
+        0.02, -33.22, -44.04,   0.08,  -0.10,  -0.98,   0.74,   0.02,
+       37.15, -39.90,  -0.12,  -0.10,  -0.89,  -0.83,  -0.02,  36.68,
+      -39.50,  -0.04,  -0.10,  -0.88,  -0.82,  -0.02, -53.22,  -3.91,
+       -0.20,   0.00,  -0.09,   1.19,   0.03,  32.43, -42.19,  -0.04,
+       -0.10,  -0.94,  -0.73,  -0.02, -51.00,  -2.30,  -0.12,  -0.10,
+        0.00,   1.14, -29.53, -39.11,   0.04,   0.00,  -0.87,   0.66,
+
+   /* 852-979 */
+        0.02,  28.50, -38.92,  -0.08,  -0.10,  -0.87,  -0.64,  -0.02,
+       26.54,  36.95,  -0.12,   0.10,   0.83,  -0.59,  -0.01,  26.54,
+       34.59,   0.04,  -0.10,   0.77,  -0.59,  -0.02,  28.35, -32.55,
+       -0.16,   0.20,  -0.73,  -0.63,  -0.01, -28.00,  30.40,   0.00,
+        0.00,   0.68,   0.63,   0.01, -27.61,  29.40,   0.20,   0.20,
+        0.66,   0.62,   0.02,  40.33,   0.40,  -0.04,   0.10,   0.00,
+       -0.90, -23.28,  31.61,  -0.08,  -0.10,   0.71,   0.52,   0.01,
+       37.75,   0.80,   0.04,   0.10,   0.00,  -0.84,  23.66,  25.80,
+        0.00,   0.00,   0.58,  -0.53,  -0.01,  21.01, -27.91,   0.00,
+        0.00,  -0.62,  -0.47,  -0.01, -34.81,   2.89,   0.04,   0.00,
+        0.00,   0.78, -23.49, -25.31,   0.00,   0.00,  -0.57,   0.53,
+        0.01, -23.47,  25.20,   0.16,   0.20,   0.56,   0.52,   0.02,
+       19.58,  27.50,  -0.12,   0.10,   0.62,  -0.44,  -0.01, -22.67,
+      -24.40,  -0.08,   0.10,  -0.55,   0.51,   0.01, -19.97,  25.00,
+        0.12,   0.20,   0.56,   0.45,   0.01,  21.28, -22.80,  -0.08,
+       -0.10,  -0.51,  -0.48,  -0.01, -30.47,   0.91,   0.04,   0.00,
+
+   /* 980-1107 */
+        0.00,   0.68,  18.58,  24.00,   0.04,  -0.10,   0.54,  -0.42,
+       -0.01, -18.02,  24.40,  -0.04,  -0.10,   0.55,   0.40,   0.01,
+       17.74,  22.50,   0.08,  -0.10,   0.50,  -0.40,  -0.01, -19.41,
+       20.70,   0.08,   0.10,   0.46,   0.43,   0.01, -18.64,  20.11,
+        0.00,   0.00,   0.45,   0.42,   0.01, -16.75,  21.60,   0.04,
+        0.10,   0.48,   0.37,   0.01, -18.42, -20.00,   0.00,   0.00,
+       -0.45,   0.41,   0.01, -26.77,   1.41,   0.08,   0.00,   0.00,
+        0.60, -26.17,  -0.19,   0.00,   0.00,   0.00,   0.59, -15.52,
+       20.51,   0.00,   0.00,   0.46,   0.35,   0.01, -25.42,  -1.91,
+       -0.08,   0.00,  -0.04,   0.57,   0.45, -17.42,  18.10,   0.00,
+        0.00,   0.40,   0.39,   0.01,  16.39, -17.60,  -0.08,  -0.10,
+       -0.39,  -0.37,  -0.01, -14.37,  18.91,   0.00,   0.00,   0.42,
+        0.32,   0.01,  23.39,  -2.40,  -0.12,   0.00,   0.00,  -0.52,
+       14.32, -18.50,  -0.04,  -0.10,  -0.41,  -0.32,  -0.01,  15.69,
+       17.08,   0.00,   0.00,   0.38,  -0.35,  -0.01, -22.99,   0.50,
+        0.04,   0.00,   0.00,   0.51,   0.00,   0.00,  14.47, -17.60,
+
+   /* 1108-1235 */
+       -0.01,   0.00,  -0.39,  -0.32, -13.33,  18.40,  -0.04,  -0.10,
+        0.41,   0.30,  22.47,  -0.60,  -0.04,   0.00,   0.00,  -0.50,
+      -12.78, -17.41,   0.04,   0.00,  -0.39,   0.29,   0.01, -14.10,
+      -15.31,   0.04,   0.00,  -0.34,   0.32,   0.01,  11.98,  16.21,
+       -0.04,   0.00,   0.36,  -0.27,  -0.01,  19.65,  -1.90,  -0.08,
+        0.00,   0.00,  -0.44,  19.61,  -1.50,  -0.08,   0.00,   0.00,
+       -0.44,  13.41, -14.30,  -0.04,  -0.10,  -0.32,  -0.30,  -0.01,
+      -13.29,  14.40,   0.00,   0.00,   0.32,   0.30,   0.01,  11.14,
+      -14.40,  -0.04,   0.00,  -0.32,  -0.25,  -0.01,  12.24, -13.38,
+        0.04,   0.00,  -0.30,  -0.27,  -0.01,  10.07, -13.81,   0.04,
+        0.00,  -0.31,  -0.23,  -0.01,  10.46,  13.10,   0.08,  -0.10,
+        0.29,  -0.23,  -0.01,  16.55,  -1.71,  -0.08,   0.00,   0.00,
+       -0.37,   9.75, -12.80,   0.00,   0.00,  -0.29,  -0.22,  -0.01,
+        9.11,  12.80,   0.00,   0.00,   0.29,  -0.20,   0.00,   0.00,
+       -6.44, -13.80,   0.00,   0.00,  -0.31,   0.14,  -9.19, -12.00,
+        0.00,   0.00,  -0.27,   0.21, -10.30,  10.90,   0.08,   0.10,
+
+   /* 1236-1363 */
+        0.24,   0.23,   0.01,  14.92,  -0.80,  -0.04,   0.00,   0.00,
+       -0.33,  10.02, -10.80,   0.00,   0.00,  -0.24,  -0.22,  -0.01,
+       -9.75,  10.40,   0.04,   0.00,   0.23,   0.22,   0.01,   9.67,
+      -10.40,  -0.04,   0.00,  -0.23,  -0.22,  -0.01,  -8.28, -11.20,
+        0.04,   0.00,  -0.25,   0.19,  13.32,  -1.41,  -0.08,   0.00,
+        0.00,  -0.30,   8.27,  10.50,   0.04,   0.00,   0.23,  -0.19,
+        0.00,   0.00,  13.13,   0.00,   0.00,   0.00,   0.00,  -0.29,
+      -12.93,   0.70,   0.04,   0.00,   0.00,   0.29,   7.91, -10.20,
+        0.00,   0.00,  -0.23,  -0.18,  -7.84, -10.00,  -0.04,   0.00,
+       -0.22,   0.18,   7.44,   9.60,   0.00,   0.00,   0.21,  -0.17,
+       -7.64,   9.40,   0.08,   0.10,   0.21,   0.17,   0.01, -11.38,
+        0.60,   0.04,   0.00,   0.00,   0.25,  -7.48,   8.30,   0.00,
+        0.00,   0.19,   0.17, -10.98,  -0.20,   0.00,   0.00,   0.00,
+        0.25,  10.98,   0.20,   0.00,   0.00,   0.00,  -0.25,   7.40,
+       -7.90,  -0.04,   0.00,  -0.18,  -0.17,  -6.09,   8.40,  -0.04,
+        0.00,   0.19,   0.14,  -6.94,  -7.49,   0.00,   0.00,  -0.17,
+
+   /* 1364-1491 */
+        0.16,   6.92,   7.50,   0.04,   0.00,   0.17,  -0.15,   6.20,
+        8.09,   0.00,   0.00,   0.18,  -0.14,  -6.12,   7.80,   0.04,
+        0.00,   0.17,   0.14,   5.85,  -7.50,   0.00,   0.00,  -0.17,
+       -0.13,  -6.48,   6.90,   0.08,   0.10,   0.15,   0.14,   0.01,
+        6.32,   6.90,   0.00,   0.00,   0.15,  -0.14,   5.61,  -7.20,
+        0.00,   0.00,  -0.16,  -0.13,   9.07,   0.00,   0.00,   0.00,
+        0.00,  -0.20,   5.25,   6.90,   0.00,   0.00,   0.15,  -0.12,
+       -8.47,  -0.40,   0.00,   0.00,   0.00,   0.19,   6.32,  -5.39,
+       -1.11,   1.10,  -0.12,  -0.14,   0.02,   0.02,   5.73,  -6.10,
+       -0.04,   0.00,  -0.14,  -0.13,   4.70,   6.60,  -0.04,   0.00,
+        0.15,  -0.11,  -4.90,  -6.40,   0.00,   0.00,  -0.14,   0.11,
+       -5.33,   5.60,   0.04,   0.10,   0.13,   0.12,   0.01,  -4.81,
+        6.00,   0.04,   0.00,   0.13,   0.11,   5.13,   5.50,   0.04,
+        0.00,   0.12,  -0.11,   4.50,   5.90,   0.00,   0.00,   0.13,
+       -0.10,  -4.22,   6.10,   0.00,   0.00,   0.14,  -4.53,   5.70,
+        0.00,   0.00,   0.13,   0.10,   4.18,   5.70,   0.00,   0.00,
+
+   /* 1492-1619 */
+        0.13,  -4.75,  -5.19,   0.00,   0.00,  -0.12,   0.11,  -4.06,
+        5.60,   0.00,   0.00,   0.13,  -3.98,   5.60,  -0.04,   0.00,
+        0.13,   4.02,  -5.40,   0.00,   0.00,  -0.12,   4.49,  -4.90,
+       -0.04,   0.00,  -0.11,  -0.10,  -3.62,  -5.40,  -0.16,   0.20,
+       -0.12,   0.00,   0.01,   4.38,   4.80,   0.00,   0.00,   0.11,
+       -6.40,  -0.10,   0.00,   0.00,   0.00,   0.14,  -3.98,   5.00,
+        0.04,   0.00,   0.11,  -3.82,  -5.00,   0.00,   0.00,  -0.11,
+       -3.71,   5.07,   0.00,   0.00,   0.11,   4.14,   4.40,   0.00,
+        0.00,   0.10,  -6.01,  -0.50,  -0.04,   0.00,   0.00,   0.13,
+       -4.04,   4.39,   0.00,   0.00,   0.10,   3.45,  -4.72,   0.00,
+        0.00,  -0.11,   3.31,   4.71,   0.00,   0.00,   0.11,   3.26,
+       -4.50,   0.00,   0.00,  -0.10,  -3.26,  -4.50,   0.00,   0.00,
+       -0.10,  -3.34,  -4.40,   0.00,   0.00,  -0.10,  -3.74,  -4.00,
+        3.70,   4.00,   3.34,  -4.30,   3.30,  -4.30,  -3.66,   3.90,
+        0.04,   3.66,   3.90,   0.04,  -3.62,  -3.90,  -3.61,   3.90,
+       -0.20,   5.30,   0.00,   0.00,   0.12,   3.06,   4.30,   3.30,
+
+   /* 1620-1747 */
+        4.00,   0.40,   0.20,   3.10,   4.10,  -3.06,   3.90,  -3.30,
+       -3.60,  -3.30,   3.36,   0.01,   3.14,   3.40,  -4.57,  -0.20,
+        0.00,   0.00,   0.00,   0.10,  -2.70,  -3.60,   2.94,  -3.20,
+       -2.90,   3.20,   2.47,  -3.40,   2.55,  -3.30,   2.80,  -3.08,
+        2.51,   3.30,  -4.10,   0.30,  -0.12,  -0.10,   4.10,   0.20,
+       -2.74,   3.00,   2.46,   3.23,  -3.66,   1.20,  -0.20,   0.20,
+        3.74,  -0.40,  -2.51,  -2.80,  -3.74,   2.27,  -2.90,   0.00,
+        0.00,  -2.50,   2.70,  -2.51,   2.60,  -3.50,   0.20,   3.38,
+       -2.22,  -2.50,   3.26,  -0.40,   1.95,  -2.60,   3.22,  -0.40,
+       -0.04,  -1.79,  -2.60,   1.91,   2.50,   0.74,   3.05,  -0.04,
+        0.08,   2.11,  -2.30,  -2.11,   2.20,  -1.87,  -2.40,   2.03,
+       -2.20,  -2.03,   2.20,   2.98,   0.00,   0.00,   2.98,  -1.71,
+        2.40,   2.94,  -0.10,  -0.12,   0.10,   1.67,   2.40,  -1.79,
+        2.30,  -1.79,   2.20,  -1.67,   2.20,   1.79,  -2.00,   1.87,
+       -1.90,   1.63,  -2.10,  -1.59,   2.10,   1.55,  -2.10,  -1.55,
+        2.10,  -2.59,  -0.20,  -1.75,  -1.90,  -1.75,   1.90,  -1.83,
+
+   /* 1748-1875 */
+       -1.80,   1.51,   2.00,  -1.51,  -2.00,   1.71,   1.80,   1.31,
+        2.10,  -1.43,   2.00,   1.43,   2.00,  -2.43,  -1.51,   1.90,
+       -1.47,   1.90,   2.39,   0.20,  -2.39,   1.39,   1.90,   1.39,
+       -1.80,   1.47,  -1.60,   1.47,  -1.60,   1.43,  -1.50,  -1.31,
+        1.60,   1.27,  -1.60,  -1.27,   1.60,   1.27,  -1.60,   2.03,
+        1.35,   1.50,  -1.39,  -1.40,   1.95,  -0.20,  -1.27,   1.49,
+        1.19,   1.50,   1.27,   1.40,   1.15,   1.50,   1.87,  -0.10,
+       -1.12,  -1.50,   1.87,  -1.11,  -1.50,  -1.11,  -1.50,   0.00,
+        0.00,   1.19,   1.40,   1.27,  -1.30,  -1.27,  -1.30,  -1.15,
+        1.40,  -1.23,   1.30,  -1.23,  -1.30,   1.22,  -1.29,   1.07,
+       -1.40,   1.75,  -0.20,  -1.03,  -1.40,  -1.07,   1.20,  -1.03,
+        1.15,   1.07,   1.10,   1.51,  -1.03,   1.10,   1.03,  -1.10,
+        0.00,   0.00,  -1.03,  -1.10,   0.91,  -1.20,  -0.88,  -1.20,
+       -0.88,   1.20,  -0.95,   1.10,  -0.95,  -1.10,   1.43,  -1.39,
+        0.95,  -1.00,  -0.95,   1.00,  -0.80,   1.10,   0.91,  -1.00,
+       -1.35,   0.88,   1.00,  -0.83,   1.00,  -0.91,   0.90,   0.91,
+
+   /* 1876-2003 */
+        0.90,   0.88,  -0.90,  -0.76,  -1.00,  -0.76,   1.00,   0.76,
+        1.00,  -0.72,   1.00,   0.84,  -0.90,   0.84,   0.90,   1.23,
+        0.00,   0.00,  -0.52,  -1.10,  -0.68,   1.00,   1.19,  -0.20,
+        1.19,   0.76,   0.90,   1.15,  -0.10,   1.15,  -0.10,   0.72,
+       -0.90,  -1.15,  -1.15,   0.68,   0.90,  -0.68,   0.90,  -1.11,
+        0.00,   0.00,   0.20,   0.79,   0.80,  -1.11,  -0.10,   0.00,
+        0.00,  -0.48,  -1.00,  -0.76,  -0.80,  -0.72,  -0.80,  -1.07,
+       -0.10,   0.64,   0.80,  -0.64,  -0.80,   0.64,   0.80,   0.40,
+        0.60,   0.52,  -0.50,  -0.60,  -0.80,  -0.71,   0.70,  -0.99,
+        0.99,   0.56,   0.80,  -0.56,   0.80,   0.68,  -0.70,   0.68,
+        0.70,  -0.95,  -0.64,   0.70,   0.64,   0.70,  -0.60,   0.70,
+       -0.60,  -0.70,  -0.91,  -0.10,  -0.51,   0.76,  -0.91,  -0.56,
+        0.70,   0.88,   0.88,  -0.63,  -0.60,   0.55,  -0.60,  -0.80,
+        0.80,  -0.80,  -0.52,   0.60,   0.52,   0.60,   0.52,  -0.60,
+       -0.48,   0.60,   0.48,   0.60,   0.48,   0.60,  -0.76,   0.44,
+       -0.60,   0.52,  -0.50,  -0.52,   0.50,   0.40,   0.60,  -0.40,
+
+   /* 2004-2131 */
+       -0.60,   0.40,  -0.60,   0.72,  -0.72,  -0.51,  -0.50,  -0.48,
+        0.50,   0.48,  -0.50,  -0.48,   0.50,  -0.48,   0.50,   0.48,
+       -0.50,  -0.48,  -0.50,  -0.68,  -0.68,   0.44,   0.50,  -0.64,
+       -0.10,  -0.64,  -0.10,  -0.40,   0.50,   0.40,   0.50,   0.40,
+        0.50,   0.00,   0.00,  -0.40,  -0.50,  -0.36,  -0.50,   0.36,
+       -0.50,   0.60,  -0.60,   0.40,  -0.40,   0.40,   0.40,  -0.40,
+        0.40,  -0.40,   0.40,  -0.56,  -0.56,   0.36,  -0.40,  -0.36,
+        0.40,   0.36,  -0.40,  -0.36,  -0.40,   0.36,   0.40,   0.36,
+        0.40,  -0.52,   0.52,   0.52,   0.32,   0.40,  -0.32,   0.40,
+       -0.32,   0.40,  -0.32,   0.40,   0.32,  -0.40,  -0.32,  -0.40,
+        0.32,  -0.40,   0.28,  -0.40,  -0.28,   0.40,   0.28,  -0.40,
+        0.28,   0.40,   0.48,  -0.48,   0.48,   0.36,  -0.30,  -0.36,
+       -0.30,   0.00,   0.00,   0.20,   0.40,  -0.44,   0.44,  -0.44,
+       -0.44,  -0.44,  -0.44,   0.32,  -0.30,   0.32,   0.30,   0.24,
+        0.30,  -0.12,  -0.10,  -0.28,   0.30,   0.28,   0.30,   0.28,
+        0.30,   0.28,  -0.30,   0.28,  -0.30,   0.28,  -0.30,   0.28,
+
+   /* 2132-2259 */
+        0.30,  -0.28,   0.30,   0.40,   0.40,  -0.24,   0.30,   0.24,
+       -0.30,   0.24,  -0.30,  -0.24,  -0.30,   0.24,   0.30,   0.24,
+       -0.30,  -0.24,   0.30,   0.24,  -0.30,  -0.24,  -0.30,   0.24,
+       -0.30,   0.24,   0.30,  -0.24,   0.30,  -0.24,   0.30,   0.20,
+       -0.30,   0.20,  -0.30,   0.20,  -0.30,   0.20,   0.30,   0.20,
+       -0.30,   0.20,  -0.30,   0.20,   0.30,   0.20,   0.30,  -0.20,
+       -0.30,   0.20,  -0.30,   0.20,  -0.30,  -0.36,  -0.36,  -0.36,
+       -0.04,   0.30,   0.12,  -0.10,  -0.32,  -0.24,   0.20,   0.24,
+        0.20,   0.20,  -0.20,  -0.20,  -0.20,  -0.20,  -0.20,   0.20,
+        0.20,   0.20,  -0.20,   0.20,   0.20,   0.20,   0.20,  -0.20,
+       -0.20,   0.00,   0.00,  -0.20,  -0.20,  -0.20,   0.20,  -0.20,
+        0.20,   0.20,  -0.20,  -0.20,  -0.20,   0.20,   0.20,   0.20,
+        0.20,   0.20,  -0.20,   0.20,  -0.20,   0.28,   0.28,   0.28,
+        0.28,   0.28,   0.28,  -0.28,   0.28,   0.12,   0.00,   0.24,
+        0.16,  -0.20,   0.16,  -0.20,   0.16,  -0.20,   0.16,   0.20,
+       -0.16,   0.20,   0.16,   0.20,  -0.16,   0.20,  -0.16,   0.20,
+
+   /* 2260-2387 */
+       -0.16,   0.20,   0.16,  -0.20,   0.16,   0.20,   0.16,  -0.20,
+       -0.16,   0.20,  -0.16,  -0.20,  -0.16,   0.20,   0.16,   0.20,
+        0.16,  -0.20,   0.16,  -0.20,   0.16,   0.20,   0.16,   0.20,
+        0.16,   0.20,  -0.16,  -0.20,   0.16,   0.20,  -0.16,   0.20,
+        0.16,   0.20,  -0.16,  -0.20,   0.16,  -0.20,   0.16,  -0.20,
+       -0.16,  -0.20,   0.24,  -0.24,  -0.24,   0.24,   0.24,   0.12,
+        0.20,   0.12,   0.20,  -0.12,  -0.20,   0.12,  -0.20,   0.12,
+       -0.20,  -0.12,   0.20,  -0.12,   0.20,  -0.12,  -0.20,   0.12,
+        0.20,   0.12,   0.20,   0.12,  -0.20,  -0.12,   0.20,   0.12,
+       -0.20,  -0.12,   0.20,   0.12,   0.20,   0.00,   0.00,  -0.12,
+        0.20,  -0.12,   0.20,   0.12,  -0.20,  -0.12,   0.20,   0.12,
+        0.20,   0.00,  -0.21,  -0.20,   0.00,   0.00,   0.20,  -0.20,
+       -0.20,  -0.20,   0.20,  -0.16,  -0.10,   0.00,   0.17,   0.16,
+        0.16,   0.16,   0.16,  -0.16,   0.16,   0.16,  -0.16,   0.16,
+       -0.16,   0.16,   0.12,   0.10,   0.12,  -0.10,  -0.12,   0.10,
+       -0.12,   0.10,   0.12,  -0.10,  -0.12,   0.12,  -0.12,   0.12,
+
+   /* 2388-2515 */
+       -0.12,   0.12,  -0.12,  -0.12,  -0.12,  -0.12,  -0.12,  -0.12,
+       -0.12,   0.12,   0.12,   0.12,   0.12,  -0.12,  -0.12,   0.12,
+        0.12,   0.12,  -0.12,   0.12,  -0.12,  -0.12,  -0.12,   0.12,
+       -0.12,  -0.12,   0.12,   0.00,   0.11,   0.11,-122.67, 164.70,
+      203.78, 273.50,   3.58,   2.74,   6.18,  -4.56,   0.00,  -0.04,
+        0.00,  -0.07,  57.44, -77.10,  95.82, 128.60,  -1.77,  -1.28,
+        2.85,  -2.14,  82.14,  89.50,   0.00,   0.00,   2.00,  -1.84,
+       -0.04,  47.73, -64.10,  23.79,  31.90,  -1.45,  -1.07,   0.69,
+       -0.53, -46.38,  50.50,   0.00,   0.00,   1.13,   1.04,   0.02,
+      -18.38,   0.00,  63.80,   0.00,   0.00,   0.41,   0.00,  -1.43,
+       59.07,   0.00,   0.00,   0.00,   0.00,  -1.32,  57.28,   0.00,
+        0.00,   0.00,   0.00,  -1.28, -48.65,   0.00,  -1.15,   0.00,
+        0.00,   1.09,   0.00,   0.03, -18.30,  24.60, -17.30, -23.20,
+        0.56,   0.41,  -0.51,   0.39, -16.91,  26.90,   8.43,  13.30,
+        0.60,   0.38,   0.31,  -0.19,   1.23,  -1.70, -19.13, -25.70,
+       -0.03,  -0.03,  -0.58,   0.43,  -0.72,   0.90, -17.34, -23.30,
+
+   /* 2516-2643 */
+        0.03,   0.02,  -0.52,   0.39, -19.49, -21.30,   0.00,   0.00,
+       -0.48,   0.44,   0.01,  20.57, -20.10,   0.64,   0.70,  -0.45,
+       -0.46,   0.00,  -0.01,   4.89,   5.90, -16.55,  19.90,   0.14,
+       -0.11,   0.44,   0.37,  18.22,  19.80,   0.00,   0.00,   0.44,
+       -0.41,  -0.01,   4.89,  -5.30, -16.51, -18.00,  -0.11,  -0.11,
+       -0.41,   0.37, -17.86,   0.00,  17.10,   0.00,   0.00,   0.40,
+        0.00,  -0.38,   0.32,   0.00,  24.42,   0.00,   0.00,  -0.01,
+        0.00,  -0.55, -23.79,   0.00,   0.00,   0.00,   0.00,   0.53,
+       14.72, -16.00,  -0.32,   0.00,  -0.36,  -0.33,  -0.01,   0.01,
+        3.34,  -4.50,  11.86,  15.90,  -0.11,  -0.07,   0.35,  -0.27,
+       -3.26,   4.40,  11.62,  15.60,   0.09,   0.07,   0.35,  -0.26,
+      -19.53,   0.00,   5.09,   0.00,   0.00,   0.44,   0.00,  -0.11,
+      -13.48,  14.70,   0.00,   0.00,   0.33,   0.30,   0.01,  10.86,
+      -14.60,   3.18,   4.30,  -0.33,  -0.24,   0.09,  -0.07, -11.30,
+      -15.10,   0.00,   0.00,  -0.34,   0.25,   0.01,   2.03,  -2.70,
+       10.82,  14.50,  -0.07,  -0.05,   0.32,  -0.24,  17.46,   0.00,
+
+   /* 2644-2771 */
+        0.00,   0.00,   0.00,  -0.39,  16.43,   0.00,   0.52,   0.00,
+        0.00,  -0.37,   0.00,  -0.01,   9.35,   0.00,  13.29,   0.00,
+        0.00,  -0.21,   0.00,  -0.30, -10.42,  11.40,   0.00,   0.00,
+        0.25,   0.23,   0.01,   0.44,   0.50, -10.38,  11.30,   0.02,
+       -0.01,   0.25,   0.23, -14.64,   0.00,   0.00,   0.00,   0.00,
+        0.33,   0.56,   0.80,  -8.67,  11.70,   0.02,  -0.01,   0.26,
+        0.19,  13.88,   0.00,  -2.47,   0.00,   0.00,  -0.31,   0.00,
+        0.06,  -1.99,   2.70,   7.72,  10.30,   0.06,   0.04,   0.23,
+       -0.17,  -0.20,   0.00,  13.05,   0.00,   0.00,   0.00,   0.00,
+       -0.29,   6.92,  -9.30,   3.34,   4.50,  -0.21,  -0.15,   0.10,
+       -0.07,  -6.60,   0.00,  10.70,   0.00,   0.00,   0.15,   0.00,
+       -0.24,  -8.04,  -8.70,   0.00,   0.00,  -0.19,   0.18, -10.58,
+        0.00,  -3.10,   0.00,   0.00,   0.24,   0.00,   0.07,  -7.32,
+        8.00,  -0.12,  -0.10,   0.18,   0.16,   1.63,   1.70,   6.96,
+       -7.60,   0.03,  -0.04,  -0.17,  -0.16,  -3.62,   0.00,   9.86,
+        0.00,   0.00,   0.08,   0.00,  -0.22,   0.20,  -0.20,  -6.88,
+
+   /* 2772-2899 */
+       -7.50,   0.00,   0.00,  -0.17,   0.15,  -8.99,   0.00,   4.02,
+        0.00,   0.00,   0.20,   0.00,  -0.09,  -1.07,   1.40,  -5.69,
+       -7.70,   0.03,   0.02,  -0.17,   0.13,   6.48,  -7.20,  -0.48,
+       -0.50,  -0.16,  -0.14,  -0.01,   0.01,   5.57,  -7.50,   1.07,
+        1.40,  -0.17,  -0.12,   0.03,  -0.02,   8.71,   0.00,   3.54,
+        0.00,   0.00,  -0.19,   0.00,  -0.08,   0.40,   0.00,   9.27,
+        0.00,   0.00,  -0.01,   0.00,  -0.21,  -6.13,   6.70,  -1.19,
+       -1.30,   0.15,   0.14,  -0.03,   0.03,   5.21,  -5.70,  -2.51,
+       -2.60,  -0.13,  -0.12,  -0.06,   0.06,   5.69,  -6.20,  -0.12,
+       -0.10,  -0.14,  -0.13,  -0.01,   2.03,  -2.70,   4.53,   6.10,
+       -0.06,  -0.05,   0.14,  -0.10,   5.01,   5.50,  -2.51,   2.70,
+        0.12,  -0.11,   0.06,   0.06,  -1.91,   2.60,  -4.38,  -5.90,
+        0.06,   0.04,  -0.13,   0.10,   4.65,  -6.30,   0.00,   0.00,
+       -0.14,  -0.10,  -5.29,   5.70,   0.00,   0.00,   0.13,   0.12,
+       -2.23,  -4.00,  -4.65,   4.20,  -0.09,   0.05,   0.10,   0.10,
+       -4.53,   6.10,   0.00,   0.00,   0.14,   0.10,   2.47,   2.70,
+
+   /* 2900-3027 */
+       -4.46,   4.90,   0.06,  -0.06,   0.11,   0.10,  -5.05,   5.50,
+        0.84,   0.90,   0.12,   0.11,   0.02,  -0.02,   4.97,  -5.40,
+       -1.71,   0.00,  -0.12,  -0.11,   0.00,   0.04,  -0.99,  -1.30,
+        4.22,  -5.70,  -0.03,   0.02,  -0.13,  -0.09,   0.99,   1.40,
+        4.22,  -5.60,   0.03,  -0.02,  -0.13,  -0.09,  -4.69,  -5.20,
+        0.00,   0.00,  -0.12,   0.10,  -3.42,   0.00,   6.09,   0.00,
+        0.00,   0.08,   0.00,  -0.14,  -4.65,  -5.10,   0.00,   0.00,
+       -0.11,   0.10,   0.00,   0.00,  -4.53,  -5.00,   0.00,   0.00,
+       -0.11,   0.10,  -2.43,  -2.70,  -3.82,   4.20,  -0.06,   0.05,
+        0.10,   0.09,   0.00,   0.00,  -4.53,   4.90,   0.00,   0.00,
+        0.11,   0.10,  -4.49,  -4.90,   0.00,   0.00,  -0.11,   0.10,
+        2.67,  -2.90,  -3.62,  -3.90,  -0.06,  -0.06,  -0.09,   0.08,
+        3.94,  -5.30,   0.00,   0.00,  -0.12,  -3.38,   3.70,  -2.78,
+       -3.10,   0.08,   0.08,  -0.07,   0.06,   3.18,  -3.50,  -2.82,
+       -3.10,  -0.08,  -0.07,  -0.07,   0.06,  -5.77,   0.00,   1.87,
+        0.00,   0.00,   0.13,   0.00,  -0.04,   3.54,  -4.80,  -0.64,
+
+   /* 3028-3155 */
+       -0.90,  -0.11,   0.00,  -0.02,  -3.50,  -4.70,   0.68,  -0.90,
+       -0.11,   0.00,  -0.02,   5.49,   0.00,   0.00,   0.00,   0.00,
+       -0.12,   1.83,  -2.50,   2.63,   3.50,  -0.06,   0.00,   0.08,
+        3.02,  -4.10,   0.68,   0.90,  -0.09,   0.00,   0.02,   0.00,
+        0.00,   5.21,   0.00,   0.00,   0.00,   0.00,  -0.12,  -3.54,
+        3.80,   2.70,   3.60,  -1.35,   1.80,   0.08,   0.00,   0.04,
+       -2.90,   3.90,   0.68,   0.90,   0.09,   0.00,   0.02,   0.80,
+       -1.10,  -2.78,  -3.70,  -0.02,   0.00,  -0.08,   4.10,   0.00,
+       -2.39,   0.00,   0.00,  -0.09,   0.00,   0.05,  -1.59,   2.10,
+        2.27,   3.00,   0.05,   0.00,   0.07,  -2.63,   3.50,  -0.48,
+       -0.60,  -2.94,  -3.20,  -2.94,   3.20,   2.27,  -3.00,  -1.11,
+       -1.50,  -0.07,   0.00,  -0.03,  -0.56,  -0.80,  -2.35,   3.10,
+        0.00,  -0.60,  -3.42,   1.90,  -0.12,  -0.10,   2.63,  -2.90,
+        2.51,   2.80,  -0.64,   0.70,  -0.48,  -0.60,   2.19,  -2.90,
+        0.24,  -0.30,   2.15,   2.90,   2.15,  -2.90,   0.52,   0.70,
+        2.07,  -2.80,  -3.10,   0.00,   1.79,   0.00,   0.00,   0.07,
+
+   /* 3156-3283 */
+        0.00,  -0.04,   0.88,   0.00,  -3.46,   2.11,   2.80,  -0.36,
+        0.50,   3.54,  -0.20,  -3.50,  -1.39,   1.50,  -1.91,  -2.10,
+       -1.47,   2.00,   1.39,   1.90,   2.07,  -2.30,   0.91,   1.00,
+        1.99,  -2.70,   3.30,   0.00,   0.60,  -0.44,  -0.70,  -1.95,
+        2.60,   2.15,  -2.40,  -0.60,  -0.70,   3.30,   0.84,   0.00,
+       -3.10,  -3.10,   0.00,  -0.72,  -0.32,   0.40,  -1.87,  -2.50,
+        1.87,  -2.50,   0.32,   0.40,  -0.24,   0.30,  -1.87,  -2.50,
+       -0.24,  -0.30,   1.87,  -2.50,  -2.70,   0.00,   1.55,   2.03,
+        2.20,  -2.98,  -1.99,  -2.20,   0.12,  -0.10,  -0.40,   0.50,
+        1.59,   2.10,   0.00,   0.00,  -1.79,   2.00,  -1.03,   1.40,
+       -1.15,  -1.60,   0.32,   0.50,   1.39,  -1.90,   2.35,  -1.27,
+        1.70,   0.60,   0.80,  -0.32,  -0.40,   1.35,  -1.80,   0.44,
+        0.00,   2.23,  -0.84,   0.90,  -1.27,  -1.40,  -1.47,   1.60,
+       -0.28,  -0.30,  -0.28,   0.40,  -1.27,  -1.70,   0.28,  -0.40,
+       -1.43,  -1.50,   0.00,   0.00,  -1.27,  -1.70,   2.11,  -0.32,
+       -0.40,  -1.23,   1.60,   1.19,  -1.30,  -0.72,  -0.80,   0.72,
+
+   /* 3284-3411 */
+       -0.80,  -1.15,  -1.30,  -1.35,  -1.50,  -1.19,  -1.60,  -0.12,
+        0.20,   1.79,   0.00,  -0.88,  -0.28,   0.40,   1.11,   1.50,
+       -1.83,   0.00,   0.56,  -0.12,   0.10,  -1.27,  -1.40,   0.00,
+        0.00,   1.15,   1.50,  -0.12,   0.20,   1.11,   1.50,   0.36,
+       -0.50,  -1.07,  -1.40,  -1.11,   1.50,   1.67,   0.00,   0.80,
+       -1.11,   0.00,   1.43,   1.23,  -1.30,  -0.24,  -1.19,  -1.30,
+       -0.24,   0.20,  -0.44,  -0.90,  -0.95,   1.10,   1.07,  -1.40,
+        1.15,  -1.30,   1.03,  -1.10,  -0.56,  -0.60,  -0.68,   0.90,
+       -0.76,  -1.00,  -0.24,  -0.30,   0.95,  -1.30,   0.56,   0.70,
+        0.84,  -1.10,  -0.56,   0.00,  -1.55,   0.91,  -1.30,   0.28,
+        0.30,   0.16,  -0.20,   0.95,   1.30,   0.40,  -0.50,  -0.88,
+       -1.20,   0.95,  -1.10,  -0.48,  -0.50,   0.00,   0.00,  -1.07,
+        1.20,   0.44,  -0.50,   0.95,   1.10,   0.00,   0.00,   0.92,
+       -1.30,   0.95,   1.00,  -0.52,   0.60,   1.59,   0.24,  -0.40,
+        0.91,   1.20,   0.84,  -1.10,  -0.44,  -0.60,   0.84,   1.10,
+       -0.44,   0.60,  -0.44,   0.60,  -0.84,  -1.10,  -0.80,   0.00,
+
+   /* 3412-3539 */
+        1.35,   0.76,   0.20,  -0.91,  -1.00,   0.20,  -0.30,  -0.91,
+       -1.20,  -0.95,   1.00,  -0.48,  -0.50,   0.88,   1.00,   0.48,
+       -0.50,  -0.95,  -1.10,   0.20,  -0.20,  -0.99,   1.10,  -0.84,
+        1.10,  -0.24,  -0.30,   0.20,  -0.30,   0.84,   1.10,  -1.39,
+        0.00,  -0.28,  -0.16,   0.20,   0.84,   1.10,   0.00,   0.00,
+        1.39,   0.00,   0.00,  -0.95,   1.00,   1.35,  -0.99,   0.00,
+        0.88,  -0.52,   0.00,  -1.19,   0.20,   0.20,   0.76,  -1.00,
+        0.00,   0.00,   0.76,   1.00,   0.00,   0.00,   0.76,   1.00,
+       -0.76,   1.00,   0.00,   0.00,   1.23,   0.76,   0.80,  -0.32,
+        0.40,  -0.72,   0.80,  -0.40,  -0.40,   0.00,   0.00,  -0.80,
+       -0.90,  -0.68,   0.90,  -0.16,  -0.20,  -0.16,  -0.20,   0.68,
+       -0.90,  -0.36,   0.50,  -0.56,  -0.80,   0.72,  -0.90,   0.44,
+       -0.60,  -0.48,  -0.70,  -0.16,   0.00,  -1.11,   0.32,   0.00,
+       -1.07,   0.60,  -0.80,  -0.28,  -0.40,  -0.64,   0.00,   0.91,
+        1.11,   0.64,  -0.90,   0.76,  -0.80,   0.00,   0.00,  -0.76,
+       -0.80,   1.03,   0.00,  -0.36,  -0.64,  -0.70,   0.36,  -0.40,
+
+   /* 3540-3667 */
+        1.07,   0.36,  -0.50,  -0.52,  -0.70,   0.60,   0.00,   0.88,
+        0.95,   0.00,   0.48,   0.16,  -0.20,   0.60,   0.80,   0.16,
+       -0.20,  -0.60,  -0.80,   0.00,  -1.00,   0.12,   0.20,   0.16,
+       -0.20,   0.68,   0.70,   0.59,  -0.80,  -0.99,  -0.56,  -0.60,
+        0.36,  -0.40,  -0.68,  -0.70,  -0.68,  -0.70,  -0.36,  -0.50,
+       -0.44,   0.60,   0.64,   0.70,  -0.12,   0.10,  -0.52,   0.60,
+        0.36,   0.40,   0.00,   0.00,   0.95,  -0.84,   0.00,   0.44,
+        0.56,   0.60,   0.32,  -0.30,   0.00,   0.00,   0.60,   0.70,
+        0.00,   0.00,   0.60,   0.70,  -0.12,  -0.20,   0.52,  -0.70,
+        0.00,   0.00,   0.56,   0.70,  -0.12,   0.10,  -0.52,  -0.70,
+        0.00,   0.00,   0.88,  -0.76,   0.00,  -0.44,   0.00,   0.00,
+       -0.52,  -0.70,   0.52,  -0.70,   0.36,  -0.40,  -0.44,  -0.50,
+        0.00,   0.00,   0.60,   0.60,   0.84,   0.00,   0.12,  -0.24,
+        0.00,   0.80,  -0.56,   0.60,  -0.32,  -0.30,   0.48,  -0.50,
+        0.28,  -0.30,  -0.48,  -0.50,   0.12,   0.20,   0.48,  -0.60,
+        0.48,   0.60,  -0.12,   0.20,   0.24,   0.00,   0.76,  -0.52,
+
+   /* 3668-3795 */
+       -0.60,  -0.52,   0.60,   0.48,  -0.50,  -0.24,  -0.30,   0.12,
+       -0.10,   0.48,   0.60,   0.52,  -0.20,   0.36,   0.40,  -0.44,
+        0.50,  -0.24,  -0.30,  -0.48,  -0.60,  -0.44,  -0.60,  -0.12,
+        0.10,   0.76,   0.76,   0.20,  -0.20,   0.48,   0.50,   0.40,
+       -0.50,  -0.24,  -0.30,   0.44,  -0.60,   0.44,  -0.60,   0.36,
+        0.00,  -0.64,   0.72,   0.00,  -0.12,   0.00,  -0.10,  -0.40,
+       -0.60,  -0.20,  -0.20,  -0.44,   0.50,  -0.44,   0.50,   0.20,
+        0.20,  -0.44,  -0.50,   0.20,  -0.20,  -0.20,   0.20,  -0.44,
+       -0.50,   0.64,   0.00,   0.32,  -0.36,   0.50,  -0.20,  -0.30,
+        0.12,  -0.10,   0.48,   0.50,  -0.12,   0.30,  -0.36,  -0.50,
+        0.00,   0.00,   0.48,   0.50,  -0.48,   0.50,   0.68,   0.00,
+       -0.12,   0.56,  -0.40,   0.44,  -0.50,  -0.12,  -0.10,   0.24,
+        0.30,  -0.40,   0.40,   0.64,   0.00,  -0.24,   0.64,   0.00,
+       -0.20,   0.00,   0.00,   0.44,  -0.50,   0.44,   0.50,  -0.12,
+        0.20,  -0.36,  -0.50,   0.12,   0.00,   0.64,  -0.40,   0.50,
+        0.00,   0.10,   0.00,   0.00,  -0.40,   0.50,   0.00,   0.00,
+
+   /* 3796-3923 */
+       -0.40,  -0.50,   0.56,   0.00,   0.28,   0.00,   0.10,   0.36,
+        0.50,   0.00,  -0.10,   0.36,  -0.50,   0.36,   0.50,   0.00,
+       -0.10,   0.24,  -0.20,  -0.36,  -0.40,   0.16,   0.20,   0.40,
+       -0.40,   0.00,   0.00,  -0.36,  -0.50,  -0.36,  -0.50,  -0.32,
+       -0.50,  -0.12,   0.10,   0.20,   0.20,  -0.36,   0.40,  -0.60,
+        0.60,   0.28,   0.00,   0.52,   0.12,  -0.10,   0.40,   0.40,
+        0.00,  -0.50,   0.20,  -0.20,  -0.32,   0.40,   0.16,   0.20,
+       -0.16,   0.20,   0.32,   0.40,   0.56,   0.00,  -0.12,   0.32,
+       -0.40,  -0.16,  -0.20,   0.00,   0.00,   0.40,   0.40,  -0.40,
+       -0.40,  -0.40,   0.40,  -0.36,   0.40,   0.12,   0.10,   0.00,
+        0.10,   0.36,   0.40,   0.00,  -0.10,   0.36,   0.40,  -0.36,
+        0.40,   0.00,   0.10,   0.32,   0.00,   0.44,   0.12,   0.20,
+        0.28,  -0.40,   0.00,   0.00,   0.36,   0.40,   0.32,  -0.40,
+       -0.16,   0.12,   0.10,   0.32,  -0.40,   0.20,   0.30,  -0.24,
+        0.30,   0.00,   0.10,   0.32,   0.40,   0.00,  -0.10,  -0.32,
+       -0.40,  -0.32,   0.40,   0.00,   0.10,  -0.52,  -0.52,   0.52,
+
+   /* 3924-4051 */
+        0.32,  -0.40,   0.00,   0.00,   0.32,   0.40,   0.32,  -0.40,
+        0.00,   0.00,  -0.32,  -0.40,  -0.32,   0.40,   0.32,   0.40,
+        0.00,   0.00,   0.32,   0.40,   0.00,   0.00,  -0.32,  -0.40,
+        0.00,   0.00,   0.32,   0.40,   0.16,   0.20,   0.32,  -0.30,
+       -0.16,   0.00,  -0.48,  -0.20,   0.20,  -0.28,  -0.30,   0.28,
+       -0.40,   0.00,   0.00,   0.28,  -0.40,   0.00,   0.00,   0.28,
+       -0.40,   0.00,   0.00,  -0.28,  -0.40,   0.28,   0.40,  -0.28,
+       -0.40,  -0.48,  -0.20,   0.20,   0.24,   0.30,   0.44,   0.00,
+        0.16,   0.24,   0.30,   0.16,  -0.20,   0.24,   0.30,  -0.12,
+        0.20,   0.20,   0.30,  -0.16,   0.20,   0.00,   0.00,   0.44,
+       -0.32,   0.30,   0.24,   0.00,  -0.36,   0.36,   0.00,   0.24,
+        0.12,  -0.20,   0.20,   0.30,  -0.12,   0.00,  -0.28,   0.30,
+       -0.24,   0.30,   0.12,   0.10,  -0.28,  -0.30,  -0.28,   0.30,
+        0.00,   0.00,  -0.28,  -0.30,   0.00,   0.00,  -0.28,  -0.30,
+        0.00,   0.00,   0.28,   0.30,   0.00,   0.00,  -0.28,  -0.30,
+       -0.28,   0.30,   0.00,   0.00,  -0.28,  -0.30,   0.00,   0.00,
+
+   /* 4052-4179 */
+        0.28,   0.30,   0.00,   0.00,  -0.28,   0.30,   0.28,  -0.30,
+       -0.28,   0.30,   0.40,   0.40,  -0.24,   0.30,   0.00,  -0.10,
+        0.16,   0.00,   0.36,  -0.20,   0.30,  -0.12,  -0.10,  -0.24,
+       -0.30,   0.00,   0.00,  -0.24,   0.30,  -0.24,   0.30,   0.00,
+        0.00,  -0.24,   0.30,  -0.24,   0.30,   0.24,  -0.30,   0.00,
+        0.00,   0.24,  -0.30,   0.00,   0.00,   0.24,   0.30,   0.24,
+       -0.30,   0.24,   0.30,  -0.24,   0.30,  -0.24,   0.30,  -0.20,
+        0.20,  -0.16,  -0.20,   0.00,   0.00,  -0.32,   0.20,   0.00,
+        0.10,   0.20,  -0.30,   0.20,  -0.20,   0.12,   0.20,  -0.16,
+        0.20,   0.16,   0.20,   0.20,   0.30,   0.20,   0.30,   0.00,
+        0.00,  -0.20,   0.30,   0.00,   0.00,   0.20,   0.30,  -0.20,
+       -0.30,  -0.20,  -0.30,   0.20,  -0.30,   0.00,   0.00,   0.20,
+        0.30,   0.00,   0.00,   0.20,   0.30,   0.00,   0.00,   0.20,
+        0.30,   0.00,   0.00,   0.20,   0.30,   0.00,   0.00,   0.20,
+       -0.30,   0.00,   0.00,  -0.20,  -0.30,   0.00,   0.00,  -0.20,
+        0.30,   0.00,   0.00,  -0.20,   0.30,   0.00,   0.00,   0.36,
+
+   /* 4180-4307 */
+        0.00,   0.00,   0.36,   0.12,   0.10,  -0.24,   0.20,   0.12,
+       -0.20,  -0.16,  -0.20,  -0.13,   0.10,   0.22,   0.21,   0.20,
+        0.00,  -0.28,   0.32,   0.00,  -0.12,  -0.20,  -0.20,   0.12,
+       -0.10,   0.12,   0.10,  -0.20,   0.20,   0.00,   0.00,  -0.32,
+        0.32,   0.00,   0.00,   0.32,   0.32,   0.00,   0.00,  -0.24,
+       -0.20,   0.24,   0.20,   0.20,   0.00,  -0.24,   0.00,   0.00,
+       -0.24,  -0.20,   0.00,   0.00,   0.24,   0.20,  -0.24,  -0.20,
+        0.00,   0.00,  -0.24,   0.20,   0.16,  -0.20,   0.12,   0.10,
+        0.20,   0.20,   0.00,  -0.10,  -0.12,   0.10,  -0.16,  -0.20,
+       -0.12,  -0.10,  -0.16,   0.20,   0.20,   0.20,   0.00,   0.00,
+       -0.20,   0.20,  -0.20,   0.20,  -0.20,   0.20,  -0.20,   0.20,
+        0.20,  -0.20,  -0.20,  -0.20,   0.00,   0.00,  -0.20,   0.20,
+        0.20,   0.00,  -0.20,   0.00,   0.00,  -0.20,   0.20,  -0.20,
+        0.20,  -0.20,  -0.20,  -0.20,  -0.20,   0.00,   0.00,   0.20,
+        0.20,   0.20,   0.20,   0.12,  -0.20,  -0.12,  -0.10,   0.28,
+       -0.28,   0.16,  -0.20,   0.00,  -0.10,   0.00,   0.10,  -0.16,
+
+   /* 4308-4435 */
+        0.20,   0.00,  -0.10,  -0.16,  -0.20,   0.00,  -0.10,   0.16,
+       -0.20,   0.16,  -0.20,   0.00,   0.00,   0.16,   0.20,  -0.16,
+        0.20,   0.00,   0.00,   0.16,   0.20,   0.16,  -0.20,   0.16,
+       -0.20,  -0.16,   0.20,   0.16,  -0.20,   0.00,   0.00,   0.16,
+        0.20,   0.00,   0.00,   0.16,   0.20,   0.00,   0.00,  -0.16,
+       -0.20,   0.16,  -0.20,  -0.16,  -0.20,   0.00,   0.00,  -0.16,
+       -0.20,   0.00,   0.00,  -0.16,   0.20,   0.00,   0.00,   0.16,
+       -0.20,   0.16,   0.20,   0.16,   0.20,   0.00,   0.00,  -0.16,
+       -0.20,   0.00,   0.00,  -0.16,  -0.20,   0.00,   0.00,   0.16,
+        0.20,   0.16,   0.20,   0.00,   0.00,   0.16,   0.20,   0.16,
+       -0.20,   0.16,   0.20,   0.00,   0.00,  -0.16,   0.20,   0.00,
+        0.10,   0.12,  -0.20,   0.12,  -0.20,   0.00,  -0.10,   0.00,
+       -0.10,   0.12,   0.20,   0.00,  -0.10,  -0.12,   0.20,  -0.15,
+        0.20,  -0.24,   0.24,   0.00,   0.00,   0.24,   0.24,   0.12,
+       -0.20,  -0.12,  -0.20,   0.00,   0.00,   0.12,   0.20,   0.12,
+       -0.20,   0.12,   0.20,   0.12,   0.20,   0.12,   0.20,   0.12,
+
+   /* 4436-4563 */
+       -0.20,  -0.12,   0.20,   0.00,   0.00,   0.12,   0.20,   0.12,
+        0.00,  -0.20,   0.00,   0.00,  -0.12,  -0.20,   0.12,  -0.20,
+        0.00,   0.00,   0.12,   0.20,  -0.12,   0.20,  -0.12,   0.20,
+        0.12,  -0.20,   0.00,   0.00,   0.12,   0.20,   0.20,   0.00,
+        0.12,   0.00,   0.00,  -0.12,   0.20,   0.00,   0.00,  -0.12,
+       -0.20,   0.00,   0.00,  -0.12,  -0.20,  -0.12,  -0.20,   0.00,
+        0.00,   0.12,  -0.20,   0.12,  -0.20,   0.12,   0.20,  -0.12,
+       -0.20,   0.00,   0.00,   0.12,  -0.20,   0.12,  -0.20,   0.12,
+        0.20,   0.12,   0.00,   0.20,  -0.12,  -0.20,   0.00,   0.00,
+        0.12,   0.20,  -0.16,   0.00,   0.16,  -0.20,   0.20,   0.00,
+        0.00,  -0.20,   0.00,   0.00,  -0.20,   0.20,   0.00,   0.00,
+        0.20,   0.20,  -0.20,   0.00,   0.00,  -0.20,   0.12,   0.00,
+       -0.16,   0.20,   0.00,   0.00,   0.20,   0.12,  -0.10,   0.00,
+        0.10,   0.16,  -0.16,  -0.16,  -0.16,  -0.16,  -0.16,   0.00,
+        0.00,  -0.16,   0.00,   0.00,  -0.16,  -0.16,  -0.16,   0.00,
+        0.00,  -0.16,   0.00,   0.00,   0.16,   0.00,   0.00,   0.16,
+
+   /* 4564-4691 */
+        0.00,   0.00,   0.16,   0.16,   0.00,   0.00,  -0.16,   0.00,
+        0.00,  -0.16,  -0.16,   0.00,   0.00,   0.16,   0.00,   0.00,
+       -0.16,  -0.16,   0.00,   0.00,  -0.16,  -0.16,   0.12,   0.10,
+        0.12,  -0.10,   0.12,   0.10,   0.00,   0.00,   0.12,   0.10,
+       -0.12,   0.10,   0.00,   0.00,   0.12,   0.10,   0.12,  -0.10,
+        0.00,   0.00,  -0.12,  -0.10,   0.00,   0.00,   0.12,   0.10,
+        0.12,   0.00,   0.00,   0.12,   0.00,   0.00,  -0.12,   0.00,
+        0.00,   0.12,   0.12,   0.12,   0.12,   0.12,   0.00,   0.00,
+        0.12,   0.00,   0.00,   0.12,   0.12,   0.00,   0.00,   0.12,
+        0.00,   0.00,   0.12,  -0.12,  -0.12,   0.12,   0.12,  -0.12,
+       -0.12,   0.00,   0.00,   0.12,  -0.12,   0.12,   0.12,  -0.12,
+       -0.12,   0.00,   0.00,  -0.12,  -0.12,   0.00,   0.00,  -0.12,
+        0.12,   0.00,   0.00,   0.12,   0.00,   0.00,   0.12,   0.00,
+        0.00,   0.12,  -0.12,   0.00,   0.00,  -0.12,   0.12,  -0.12,
+       -0.12,   0.12,   0.00,   0.00,   0.12,   0.12,   0.12,  -0.12,
+        0.00,   0.00,  -0.12,  -0.12,  -0.12,   0.00,   0.00,  -0.12,
+
+   /* 4692-NA */
+       -0.12,   0.00,   0.00,   0.12,   0.12,   0.00,   0.00,  -0.12,
+       -0.12,  -0.12,  -0.12,   0.12,   0.00,   0.00,   0.12,  -0.12,
+        0.00,   0.00,  -0.12,  -0.12,   0.00,   0.00,   0.12,  -0.12,
+       -0.12,  -0.12,  -0.12,   0.12,   0.12,  -0.12,  -0.12,   0.00,
+        0.00,  -0.12,   0.00,   0.00,  -0.12,   0.12,   0.00,   0.00,
+        0.12,   0.00,   0.00,  -0.12,  -0.12,   0.00,   0.00,  -0.12,
+       -0.12,   0.12,   0.00,   0.00,   0.12,   0.12,   0.00,   0.00,
+        0.12,   0.00,   0.00,   0.12,   0.12,   0.08,   0.00,   0.04
+   };
+
+/* Number of amplitude coefficients */
+   static const int NA = (int) (sizeof a / sizeof (double));
+
+/* Amplitude usage: X or Y, sin or cos, power of T. */
+   static const int jaxy[] = {0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1};
+   static const int jasc[] = {0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0};
+   static const int japt[] = {0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4};
+
+/* Miscellaneous */
+   double t, w, pt[MAXPT+1], fa[14], xypr[2], xypl[2], xyls[2], arg,
+          sc[2];
+   int jpt, i, j, jxy, ialast, ifreq, m, ia, jsc;
+
+/*--------------------------------------------------------------------*/
+
+/* Interval between fundamental date J2000.0 and given date (JC). */
+   t = ((date1 - DJ00) + date2) / DJC;
+
+/* Powers of T. */
+   w = 1.0;
+   for (jpt = 0; jpt <= MAXPT; jpt++) {
+      pt[jpt] = w;
+      w *= t;
+   }
+
+/* Initialize totals in X and Y:  polynomial, luni-solar, planetary. */
+   for (jxy = 0; jxy < 2; jxy++) {
+      xypr[jxy] = 0.0;
+      xyls[jxy] = 0.0;
+      xypl[jxy] = 0.0;
+   }
+
+/* --------------------------------- */
+/* Fundamental arguments (IERS 2003) */
+/* --------------------------------- */
+
+/* Mean anomaly of the Moon. */
+   fa[0] = iauFal03(t);
+
+/* Mean anomaly of the Sun. */
+   fa[1] = iauFalp03(t);
+
+/* Mean argument of the latitude of the Moon. */
+   fa[2] = iauFaf03(t);
+
+/* Mean elongation of the Moon from the Sun. */
+   fa[3] = iauFad03(t);
+
+/* Mean longitude of the ascending node of the Moon. */
+   fa[4] = iauFaom03(t);
+
+/* Planetary longitudes, Mercury through Neptune. */
+   fa[5] = iauFame03(t);
+   fa[6] = iauFave03(t);
+   fa[7] = iauFae03(t);
+   fa[8] = iauFama03(t);
+   fa[9] = iauFaju03(t);
+   fa[10] = iauFasa03(t);
+   fa[11] = iauFaur03(t);
+   fa[12] = iauFane03(t);
+
+/* General accumulated precession in longitude. */
+   fa[13] = iauFapa03(t);
+
+/* -------------------------------------- */
+/* Polynomial part of precession-nutation */
+/* -------------------------------------- */
+
+   for (jxy = 0; jxy < 2; jxy++) {
+      for (j = MAXPT; j >= 0; j--) {
+         xypr[jxy] += xyp[jxy][j] * pt[j];
+      }
+   }
+
+/* ---------------------------------- */
+/* Nutation periodic terms, planetary */
+/* ---------------------------------- */
+
+/* Work backwards through the coefficients per frequency list. */
+   ialast = NA;
+   for (ifreq = NFPL-1; ifreq >= 0; ifreq--) {
+
+   /* Obtain the argument functions. */
+      arg = 0.0;
+      for (i = 0; i < 14; i++) {
+         m = mfapl[ifreq][i];
+         if (m != 0) arg += (double)m * fa[i];
+      }
+      sc[0] = sin(arg);
+      sc[1] = cos(arg);
+
+   /* Work backwards through the amplitudes at this frequency. */
+      ia = nc[ifreq+NFLS];
+      for (i = ialast; i >= ia; i--) {
+
+      /* Coefficient number (0 = 1st). */
+         j = i-ia;
+
+      /* X or Y. */
+         jxy = jaxy[j];
+
+      /* Sin or cos. */
+         jsc = jasc[j];
+
+      /* Power of T. */
+         jpt = japt[j];
+
+      /* Accumulate the component. */
+         xypl[jxy] += a[i-1] * sc[jsc] * pt[jpt];
+      }
+      ialast = ia-1;
+   }
+
+/* ----------------------------------- */
+/* Nutation periodic terms, luni-solar */
+/* ----------------------------------- */
+
+/* Continue working backwards through the number of coefficients list. */
+   for (ifreq = NFLS-1; ifreq >= 0; ifreq--) {
+
+   /* Obtain the argument functions. */
+      arg = 0.0;
+      for (i = 0; i < 5; i++) {
+         m = mfals[ifreq][i];
+         if (m != 0) arg += (double)m * fa[i];
+      }
+      sc[0] = sin(arg);
+      sc[1] = cos(arg);
+
+   /* Work backwards through the amplitudes at this frequency. */
+      ia = nc[ifreq];
+      for (i = ialast; i >= ia; i--) {
+
+      /* Coefficient number (0 = 1st). */
+         j = i-ia;
+
+      /* X or Y. */
+         jxy = jaxy[j];
+
+      /* Sin or cos. */
+         jsc = jasc[j];
+
+      /* Power of T. */
+         jpt = japt[j];
+
+      /* Accumulate the component. */
+         xyls[jxy] += a[i-1] * sc[jsc] * pt[jpt];
+      }
+      ialast = ia-1;
+   }
+
+/* ------------------------------------ */
+/* Results:  CIP unit vector components */
+/* ------------------------------------ */
+
+   *x = DAS2R * (xypr[0] + (xyls[0] + xypl[0]) / 1e6);
+   *y = DAS2R * (xypr[1] + (xyls[1] + xypl[1]) / 1e6);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauXys00a(double date1, double date2,
+               double *x, double *y, double *s)
+/*
+**  - - - - - - - - - -
+**   i a u X y s 0 0 a
+**  - - - - - - - - - -
+**
+**  For a given TT date, compute the X,Y coordinates of the Celestial
+**  Intermediate Pole and the CIO locator s, using the IAU 2000A
+**  precession-nutation model.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     date1,date2  double   TT as a 2-part Julian Date (Note 1)
+**
+**  Returned:
+**     x,y          double   Celestial Intermediate Pole (Note 2)
+**     s            double   the CIO locator s (Note 2)
+**
+**  Notes:
+**
+**  1) The TT date date1+date2 is a Julian Date, apportioned in any
+**     convenient way between the two arguments.  For example,
+**     JD(TT)=2450123.7 could be expressed in any of these ways,
+**     among others:
+**
+**            date1          date2
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in
+**     cases where the loss of several decimal digits of resolution
+**     is acceptable.  The J2000 method is best matched to the way
+**     the argument is handled internally and will deliver the
+**     optimum resolution.  The MJD method and the date & time methods
+**     are both good compromises between resolution and convenience.
+**
+**  2) The Celestial Intermediate Pole coordinates are the x,y
+**     components of the unit vector in the Geocentric Celestial
+**     Reference System.
+**
+**  3) The CIO locator s (in radians) positions the Celestial
+**     Intermediate Origin on the equator of the CIP.
+**
+**  4) A faster, but slightly less accurate result (about 1 mas for
+**     X,Y), can be obtained by using instead the iauXys00b function.
+**
+**  Called:
+**     iauPnm00a    classical NPB matrix, IAU 2000A
+**     iauBpn2xy    extract CIP X,Y coordinates from NPB matrix
+**     iauS00       the CIO locator s, given X,Y, IAU 2000A
+**
+**  Reference:
+**
+**     McCarthy, D. D., Petit, G. (eds.), IERS Conventions (2003),
+**     IERS Technical Note No. 32, BKG (2004)
+**
+**  This revision:  2008 May 12
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double rbpn[3][3];
+
+
+/* Form the bias-precession-nutation matrix, IAU 2000A. */
+   iauPnm00a(date1, date2, rbpn);
+
+/* Extract X,Y. */
+   iauBpn2xy(rbpn, x, y);
+
+/* Obtain s. */
+   *s = iauS00(date1, date2, *x, *y);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauXys00b(double date1, double date2,
+               double *x, double *y, double *s)
+/*
+**  - - - - - - - - - -
+**   i a u X y s 0 0 b
+**  - - - - - - - - - -
+**
+**  For a given TT date, compute the X,Y coordinates of the Celestial
+**  Intermediate Pole and the CIO locator s, using the IAU 2000B
+**  precession-nutation model.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     date1,date2  double   TT as a 2-part Julian Date (Note 1)
+**
+**  Returned:
+**     x,y          double   Celestial Intermediate Pole (Note 2)
+**     s            double   the CIO locator s (Note 2)
+**
+**  Notes:
+**
+**  1) The TT date date1+date2 is a Julian Date, apportioned in any
+**     convenient way between the two arguments.  For example,
+**     JD(TT)=2450123.7 could be expressed in any of these ways,
+**     among others:
+**
+**            date1          date2
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in
+**     cases where the loss of several decimal digits of resolution
+**     is acceptable.  The J2000 method is best matched to the way
+**     the argument is handled internally and will deliver the
+**     optimum resolution.  The MJD method and the date & time methods
+**     are both good compromises between resolution and convenience.
+**
+**  2) The Celestial Intermediate Pole coordinates are the x,y
+**     components of the unit vector in the Geocentric Celestial
+**     Reference System.
+**
+**  3) The CIO locator s (in radians) positions the Celestial
+**     Intermediate Origin on the equator of the CIP.
+**
+**  4) The present function is faster, but slightly less accurate (about
+**     1 mas in X,Y), than the iauXys00a function.
+**
+**  Called:
+**     iauPnm00b    classical NPB matrix, IAU 2000B
+**     iauBpn2xy    extract CIP X,Y coordinates from NPB matrix
+**     iauS00       the CIO locator s, given X,Y, IAU 2000A
+**
+**  Reference:
+**
+**     McCarthy, D. D., Petit, G. (eds.), IERS Conventions (2003),
+**     IERS Technical Note No. 32, BKG (2004)
+**
+**  This revision:  2008 May 12
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double rbpn[3][3];
+
+
+/* Form the bias-precession-nutation matrix, IAU 2000A. */
+   iauPnm00b(date1, date2, rbpn);
+
+/* Extract X,Y. */
+   iauBpn2xy(rbpn, x, y);
+
+/* Obtain s. */
+   *s = iauS00(date1, date2, *x, *y);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauXys06a(double date1, double date2,
+               double *x, double *y, double *s)
+/*
+**  - - - - - - - - - -
+**   i a u X y s 0 6 a
+**  - - - - - - - - - -
+**
+**  For a given TT date, compute the X,Y coordinates of the Celestial
+**  Intermediate Pole and the CIO locator s, using the IAU 2006
+**  precession and IAU 2000A nutation models.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  support function.
+**
+**  Given:
+**     date1,date2  double  TT as a 2-part Julian Date (Note 1)
+**
+**  Returned:
+**     x,y          double  Celestial Intermediate Pole (Note 2)
+**     s            double  the CIO locator s (Note 2)
+**
+**  Notes:
+**
+**  1) The TT date date1+date2 is a Julian Date, apportioned in any
+**     convenient way between the two arguments.  For example,
+**     JD(TT)=2450123.7 could be expressed in any of these ways,
+**     among others:
+**
+**            date1          date2
+**
+**         2450123.7           0.0       (JD method)
+**         2451545.0       -1421.3       (J2000 method)
+**         2400000.5       50123.2       (MJD method)
+**         2450123.5           0.2       (date & time method)
+**
+**     The JD method is the most natural and convenient to use in
+**     cases where the loss of several decimal digits of resolution
+**     is acceptable.  The J2000 method is best matched to the way
+**     the argument is handled internally and will deliver the
+**     optimum resolution.  The MJD method and the date & time methods
+**     are both good compromises between resolution and convenience.
+**
+**  2) The Celestial Intermediate Pole coordinates are the x,y components
+**     of the unit vector in the Geocentric Celestial Reference System.
+**
+**  3) The CIO locator s (in radians) positions the Celestial
+**     Intermediate Origin on the equator of the CIP.
+**
+**  4) Series-based solutions for generating X and Y are also available:
+**     see Capitaine & Wallace (2006) and iauXy06.
+**
+**  Called:
+**     iauPnm06a    classical NPB matrix, IAU 2006/2000A
+**     iauBpn2xy    extract CIP X,Y coordinates from NPB matrix
+**     iauS06       the CIO locator s, given X,Y, IAU 2006
+**
+**  References:
+**
+**     Capitaine, N. & Wallace, P.T., 2006, Astron.Astrophys. 450, 855
+**
+**     Wallace, P.T. & Capitaine, N., 2006, Astron.Astrophys. 459, 981
+**
+**  This revision:  2008 May 11
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   double rbpn[3][3];
+
+
+/* Form the bias-precession-nutation matrix, IAU 2000A. */
+   iauPnm06a(date1, date2, rbpn);
+
+/* Extract X,Y. */
+   iauBpn2xy(rbpn, x, y);
+
+/* Obtain s. */
+   *s = iauS06(date1, date2, *x, *y);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauZp(double p[3])
+/*
+**  - - - - - -
+**   i a u Z p
+**  - - - - - -
+**
+**  Zero a p-vector.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  vector/matrix support function.
+**
+**  Returned:
+**     p        double[3]      p-vector
+**
+**  This revision:  2008 May 11
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   p[0] = 0.0;
+   p[1] = 0.0;
+   p[2] = 0.0;
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauZpv(double pv[2][3])
+/*
+**  - - - - - - -
+**   i a u Z p v
+**  - - - - - - -
+**
+**  Zero a pv-vector.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  vector/matrix support function.
+**
+**  Returned:
+**     pv       double[2][3]      pv-vector
+**
+**  Called:
+**     iauZp        zero p-vector
+**
+**  This revision:  2008 May 11
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   iauZp(pv[0]);
+   iauZp(pv[1]);
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
+#include "sofam.h"
+
+void iauZr(double r[3][3])
+/*
+**  - - - - - -
+**   i a u Z r
+**  - - - - - -
+**
+**  Initialize an r-matrix to the null matrix.
+**
+**  This function is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Status:  vector/matrix support function.
+**
+**  Returned:
+**     r        double[3][3]    r-matrix
+**
+**  This revision:  2008 May 11
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+{
+   int i, j;
+
+
+   for (i = 0; i < 3; i++) {
+      for (j = 0; j < 3; j++) {
+         r[i][j] = 0.0;
+      }
+   }
+
+   return;
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
+}
diff --git a/cextern/sofa/sofa.h b/cextern/sofa/sofa.h
new file mode 100644
index 0000000..43e08dc
--- /dev/null
+++ b/cextern/sofa/sofa.h
@@ -0,0 +1,429 @@
+#ifndef SOFAHDEF
+#define SOFAHDEF
+
+/*
+**  - - - - - - -
+**   s o f a . h
+**  - - - - - - -
+**
+**  Prototype function declarations for SOFA library.
+**
+**  This file is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  This revision:   2012 February 23
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+
+#include "math.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Astronomy/Calendars */
+int iauCal2jd(int iy, int im, int id, double *djm0, double *djm);
+double iauEpb(double dj1, double dj2);
+void iauEpb2jd(double epb, double *djm0, double *djm);
+double iauEpj(double dj1, double dj2);
+void iauEpj2jd(double epj, double *djm0, double *djm);
+int iauJd2cal(double dj1, double dj2,
+                     int *iy, int *im, int *id, double *fd);
+int iauJdcalf(int ndp, double dj1, double dj2, int iymdf[4]);
+
+/* Astronomy/Ephemerides */
+int iauEpv00(double date1, double date2,
+             double pvh[2][3], double pvb[2][3]);
+int iauPlan94(double date1, double date2, int np, double pv[2][3]);
+
+/* Astronomy/FundamentalArgs */
+double iauFad03(double t);
+double iauFae03(double t);
+double iauFaf03(double t);
+double iauFaju03(double t);
+double iauFal03(double t);
+double iauFalp03(double t);
+double iauFama03(double t);
+double iauFame03(double t);
+double iauFane03(double t);
+double iauFaom03(double t);
+double iauFapa03(double t);
+double iauFasa03(double t);
+double iauFaur03(double t);
+double iauFave03(double t);
+
+/* Astronomy/PrecNutPolar */
+void iauBi00(double *dpsibi, double *depsbi, double *dra);
+void iauBp00(double date1, double date2,
+             double rb[3][3], double rp[3][3], double rbp[3][3]);
+void iauBp06(double date1, double date2,
+             double rb[3][3], double rp[3][3], double rbp[3][3]);
+void iauBpn2xy(double rbpn[3][3], double *x, double *y);
+void iauC2i00a(double date1, double date2, double rc2i[3][3]);
+void iauC2i00b(double date1, double date2, double rc2i[3][3]);
+void iauC2i06a(double date1, double date2, double rc2i[3][3]);
+void iauC2ibpn(double date1, double date2, double rbpn[3][3],
+               double rc2i[3][3]);
+void iauC2ixy(double date1, double date2, double x, double y,
+              double rc2i[3][3]);
+void iauC2ixys(double x, double y, double s, double rc2i[3][3]);
+void iauC2t00a(double tta, double ttb, double uta, double utb,
+               double xp, double yp, double rc2t[3][3]);
+void iauC2t00b(double tta, double ttb, double uta, double utb,
+               double xp, double yp, double rc2t[3][3]);
+void iauC2t06a(double tta, double ttb, double uta, double utb,
+               double xp, double yp, double rc2t[3][3]);
+void iauC2tcio(double rc2i[3][3], double era, double rpom[3][3],
+               double rc2t[3][3]);
+void iauC2teqx(double rbpn[3][3], double gst, double rpom[3][3],
+               double rc2t[3][3]);
+void iauC2tpe(double tta, double ttb, double uta, double utb,
+              double dpsi, double deps, double xp, double yp,
+              double rc2t[3][3]);
+void iauC2txy(double tta, double ttb, double uta, double utb,
+              double x, double y, double xp, double yp,
+              double rc2t[3][3]);
+double iauEo06a(double date1, double date2);
+double iauEors(double rnpb[3][3], double s);
+void iauFw2m(double gamb, double phib, double psi, double eps,
+             double r[3][3]);
+void iauFw2xy(double gamb, double phib, double psi, double eps,
+              double *x, double *y);
+void iauNum00a(double date1, double date2, double rmatn[3][3]);
+void iauNum00b(double date1, double date2, double rmatn[3][3]);
+void iauNum06a(double date1, double date2, double rmatn[3][3]);
+void iauNumat(double epsa, double dpsi, double deps, double rmatn[3][3]);
+void iauNut00a(double date1, double date2, double *dpsi, double *deps);
+void iauNut00b(double date1, double date2, double *dpsi, double *deps);
+void iauNut06a(double date1, double date2, double *dpsi, double *deps);
+void iauNut80(double date1, double date2, double *dpsi, double *deps);
+void iauNutm80(double date1, double date2, double rmatn[3][3]);
+double iauObl06(double date1, double date2);
+double iauObl80(double date1, double date2);
+void iauP06e(double date1, double date2,
+             double *eps0, double *psia, double *oma, double *bpa,
+             double *bqa, double *pia, double *bpia,
+             double *epsa, double *chia, double *za, double *zetaa,
+             double *thetaa, double *pa,
+             double *gam, double *phi, double *psi);
+void iauPb06(double date1, double date2,
+             double *bzeta, double *bz, double *btheta);
+void iauPfw06(double date1, double date2,
+              double *gamb, double *phib, double *psib, double *epsa);
+void iauPmat00(double date1, double date2, double rbp[3][3]);
+void iauPmat06(double date1, double date2, double rbp[3][3]);
+void iauPmat76(double date1, double date2, double rmatp[3][3]);
+void iauPn00(double date1, double date2, double dpsi, double deps,
+             double *epsa,
+             double rb[3][3], double rp[3][3], double rbp[3][3],
+             double rn[3][3], double rbpn[3][3]);
+void iauPn00a(double date1, double date2,
+              double *dpsi, double *deps, double *epsa,
+              double rb[3][3], double rp[3][3], double rbp[3][3],
+              double rn[3][3], double rbpn[3][3]);
+void iauPn00b(double date1, double date2,
+              double *dpsi, double *deps, double *epsa,
+              double rb[3][3], double rp[3][3], double rbp[3][3],
+              double rn[3][3], double rbpn[3][3]);
+void iauPn06(double date1, double date2, double dpsi, double deps,
+             double *epsa,
+             double rb[3][3], double rp[3][3], double rbp[3][3],
+             double rn[3][3], double rbpn[3][3]);
+void iauPn06a(double date1, double date2,
+              double *dpsi, double *deps, double *epsa,
+              double rb[3][3], double rp[3][3], double rbp[3][3],
+              double rn[3][3], double rbpn[3][3]);
+void iauPnm00a(double date1, double date2, double rbpn[3][3]);
+void iauPnm00b(double date1, double date2, double rbpn[3][3]);
+void iauPnm06a(double date1, double date2, double rnpb[3][3]);
+void iauPnm80(double date1, double date2, double rmatpn[3][3]);
+void iauPom00(double xp, double yp, double sp, double rpom[3][3]);
+void iauPr00(double date1, double date2, double *dpsipr, double *depspr);
+void iauPrec76(double ep01, double ep02, double ep11, double ep12,
+               double *zeta, double *z, double *theta);
+double iauS00(double date1, double date2, double x, double y);
+double iauS00a(double date1, double date2);
+double iauS00b(double date1, double date2);
+double iauS06(double date1, double date2, double x, double y);
+double iauS06a(double date1, double date2);
+double iauSp00(double date1, double date2);
+void iauXy06(double date1, double date2, double *x, double *y);
+void iauXys00a(double date1, double date2,
+               double *x, double *y, double *s);
+void iauXys00b(double date1, double date2,
+               double *x, double *y, double *s);
+void iauXys06a(double date1, double date2,
+               double *x, double *y, double *s);
+
+/* Astronomy/RotationAndTime */
+double iauEe00(double date1, double date2, double epsa, double dpsi);
+double iauEe00a(double date1, double date2);
+double iauEe00b(double date1, double date2);
+double iauEe06a(double date1, double date2);
+double iauEect00(double date1, double date2);
+double iauEqeq94(double date1, double date2);
+double iauEra00(double dj1, double dj2);
+double iauGmst00(double uta, double utb, double tta, double ttb);
+double iauGmst06(double uta, double utb, double tta, double ttb);
+double iauGmst82(double dj1, double dj2);
+double iauGst00a(double uta, double utb, double tta, double ttb);
+double iauGst00b(double uta, double utb);
+double iauGst06(double uta, double utb, double tta, double ttb,
+                double rnpb[3][3]);
+double iauGst06a(double uta, double utb, double tta, double ttb);
+double iauGst94(double uta, double utb);
+
+/* Astronomy/SpaceMotion */
+int iauPvstar(double pv[2][3], double *ra, double *dec,
+              double *pmr, double *pmd, double *px, double *rv);
+int iauStarpv(double ra, double dec,
+              double pmr, double pmd, double px, double rv,
+              double pv[2][3]);
+
+/* Astronomy/StarCatalogs */
+void iauFk52h(double r5, double d5,
+              double dr5, double dd5, double px5, double rv5,
+              double *rh, double *dh,
+              double *drh, double *ddh, double *pxh, double *rvh);
+void iauFk5hip(double r5h[3][3], double s5h[3]);
+void iauFk5hz(double r5, double d5, double date1, double date2,
+              double *rh, double *dh);
+void iauH2fk5(double rh, double dh,
+              double drh, double ddh, double pxh, double rvh,
+              double *r5, double *d5,
+              double *dr5, double *dd5, double *px5, double *rv5);
+void iauHfk5z(double rh, double dh, double date1, double date2,
+              double *r5, double *d5, double *dr5, double *dd5);
+int iauStarpm(double ra1, double dec1,
+              double pmr1, double pmd1, double px1, double rv1,
+              double ep1a, double ep1b, double ep2a, double ep2b,
+              double *ra2, double *dec2,
+              double *pmr2, double *pmd2, double *px2, double *rv2);
+
+/* Astronomy/Geodetic/Geocentric */
+int iauEform(int n, double *a, double *f);
+int iauGc2gd(int n, double xyz[3],
+             double *elong, double *phi, double *height);
+int iauGc2gde(double a, double f, double xyz[3],
+              double *elong, double *phi, double *height);
+int iauGd2gc(int n, double elong, double phi, double height,
+             double xyz[3]);
+int iauGd2gce(double a, double f,
+              double elong, double phi, double height, double xyz[3]);
+
+/* Astronomy/Timescales */
+int iauD2dtf(const char *scale, int ndp, double d1, double d2,
+             int *iy, int *im, int *id, int ihmsf[4]);
+int iauDat(int iy, int im, int id, double fd, double *deltat);
+double iauDtdb(double date1, double date2,
+               double ut, double elong, double u, double v);
+int iauDtf2d(const char *scale, int iy, int im, int id,
+             int ihr, int imn, double sec, double *d1, double *d2);
+int iauTaitt(double tai1, double tai2, double *tt1, double *tt2);
+int iauTaiut1(double tai1, double tai2, double dta,
+              double *ut11, double *ut12);
+int iauTaiutc(double tai1, double tai2, double *utc1, double *utc2);
+int iauTcbtdb(double tcb1, double tcb2, double *tdb1, double *tdb2);
+int iauTcgtt(double tcg1, double tcg2, double *tt1, double *tt2);
+int iauTdbtcb(double tdb1, double tdb2, double *tcb1, double *tcb2);
+int iauTdbtt(double tdb1, double tdb2, double dtr,
+             double *tt1, double *tt2);
+int iauTttai(double tt1, double tt2, double *tai1, double *tai2);
+int iauTttcg(double tt1, double tt2, double *tcg1, double *tcg2);
+int iauTttdb(double tt1, double tt2, double dtr,
+             double *tdb1, double *tdb2);
+int iauTtut1(double tt1, double tt2, double dt,
+             double *ut11, double *ut12);
+int iauUt1tai(double ut11, double ut12, double dta,
+              double *tai1, double *tai2);
+int iauUt1tt(double ut11, double ut12, double dt,
+             double *tt1, double *tt2);
+int iauUt1utc(double ut11, double ut12, double dut1,
+              double *utc1, double *utc2);
+int iauUtctai(double utc1, double utc2, double *tai1, double *tai2);
+int iauUtcut1(double utc1, double utc2, double dut1,
+              double *ut11, double *ut12);
+
+/* VectorMatrix/AngleOps */
+void iauA2af(int ndp, double angle, char *sign, int idmsf[4]);
+void iauA2tf(int ndp, double angle, char *sign, int ihmsf[4]);
+int iauAf2a(char s, int ideg, int iamin, double asec, double *rad);
+double iauAnp(double a);
+double iauAnpm(double a);
+void iauD2tf(int ndp, double days, char *sign, int ihmsf[4]);
+int iauTf2a(char s, int ihour, int imin, double sec, double *rad);
+int iauTf2d(char s, int ihour, int imin, double sec, double *days);
+
+/* VectorMatrix/BuildRotations */
+void iauRx(double phi, double r[3][3]);
+void iauRy(double theta, double r[3][3]);
+void iauRz(double psi, double r[3][3]);
+
+/* VectorMatrix/CopyExtendExtract */
+void iauCp(double p[3], double c[3]);
+void iauCpv(double pv[2][3], double c[2][3]);
+void iauCr(double r[3][3], double c[3][3]);
+void iauP2pv(double p[3], double pv[2][3]);
+void iauPv2p(double pv[2][3], double p[3]);
+
+/* VectorMatrix/Initialization */
+void iauIr(double r[3][3]);
+void iauZp(double p[3]);
+void iauZpv(double pv[2][3]);
+void iauZr(double r[3][3]);
+
+/* VectorMatrix/MatrixOps */
+void iauRxr(double a[3][3], double b[3][3], double atb[3][3]);
+void iauTr(double r[3][3], double rt[3][3]);
+
+/* VectorMatrix/MatrixVectorProducts */
+void iauRxp(double r[3][3], double p[3], double rp[3]);
+void iauRxpv(double r[3][3], double pv[2][3], double rpv[2][3]);
+void iauTrxp(double r[3][3], double p[3], double trp[3]);
+void iauTrxpv(double r[3][3], double pv[2][3], double trpv[2][3]);
+
+/* VectorMatrix/RotationVectors */
+void iauRm2v(double r[3][3], double w[3]);
+void iauRv2m(double w[3], double r[3][3]);
+
+/* VectorMatrix/SeparationAndAngle */
+double iauPap(double a[3], double b[3]);
+double iauPas(double al, double ap, double bl, double bp);
+double iauSepp(double a[3], double b[3]);
+double iauSeps(double al, double ap, double bl, double bp);
+
+/* VectorMatrix/SphericalCartesian */
+void iauC2s(double p[3], double *theta, double *phi);
+void iauP2s(double p[3], double *theta, double *phi, double *r);
+void iauPv2s(double pv[2][3],
+             double *theta, double *phi, double *r,
+             double *td, double *pd, double *rd);
+void iauS2c(double theta, double phi, double c[3]);
+void iauS2p(double theta, double phi, double r, double p[3]);
+void iauS2pv(double theta, double phi, double r,
+             double td, double pd, double rd,
+             double pv[2][3]);
+
+/* VectorMatrix/VectorOps */
+double iauPdp(double a[3], double b[3]);
+double iauPm(double p[3]);
+void iauPmp(double a[3], double b[3], double amb[3]);
+void iauPn(double p[3], double *r, double u[3]);
+void iauPpp(double a[3], double b[3], double apb[3]);
+void iauPpsp(double a[3], double s, double b[3], double apsb[3]);
+void iauPvdpv(double a[2][3], double b[2][3], double adb[2]);
+void iauPvm(double pv[2][3], double *r, double *s);
+void iauPvmpv(double a[2][3], double b[2][3], double amb[2][3]);
+void iauPvppv(double a[2][3], double b[2][3], double apb[2][3]);
+void iauPvu(double dt, double pv[2][3], double upv[2][3]);
+void iauPvup(double dt, double pv[2][3], double p[3]);
+void iauPvxpv(double a[2][3], double b[2][3], double axb[2][3]);
+void iauPxp(double a[3], double b[3], double axb[3]);
+void iauS2xpv(double s1, double s2, double pv[2][3], double spv[2][3]);
+void iauSxp(double s, double p[3], double sp[3]);
+void iauSxpv(double s, double pv[2][3], double spv[2][3]);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
diff --git a/cextern/sofa/sofam.h b/cextern/sofa/sofam.h
new file mode 100644
index 0000000..a6fce72
--- /dev/null
+++ b/cextern/sofa/sofam.h
@@ -0,0 +1,205 @@
+#ifndef SOFAMHDEF
+#define SOFAMHDEF
+
+/*
+**  - - - - - - - -
+**   s o f a m . h
+**  - - - - - - - -
+**
+**  Macros used by SOFA library.
+**
+**  This file is part of the International Astronomical Union's
+**  SOFA (Standards Of Fundamental Astronomy) software collection.
+**
+**  Please note that the constants defined below are to be used only in
+**  the context of the SOFA software, and have no other official IAU
+**  status.
+**
+**  This revision:   2012 February 23
+**
+**  SOFA release 2012-03-01
+**
+**  Copyright (C) 2012 IAU SOFA Board.  See notes at end.
+*/
+
+#include "sofa.h"
+
+
+/* Pi */
+#define DPI (3.141592653589793238462643)
+
+/* 2Pi */
+#define D2PI (6.283185307179586476925287)
+
+/* Degrees to radians */
+#define DD2R (1.745329251994329576923691e-2)
+
+/* Radians to arcseconds */
+#define DR2AS (206264.8062470963551564734)
+
+/* Arcseconds to radians */
+#define DAS2R (4.848136811095359935899141e-6)
+
+/* Seconds of time to radians */
+#define DS2R (7.272205216643039903848712e-5)
+
+/* Arcseconds in a full circle */
+#define TURNAS (1296000.0)
+
+/* Milliarcseconds to radians */
+#define DMAS2R (DAS2R / 1e3)
+
+/* Length of tropical year B1900 (days) */
+#define DTY (365.242198781)
+
+/* Seconds per day. */
+#define DAYSEC (86400.0)
+
+/* Days per Julian year */
+#define DJY (365.25)
+
+/* Days per Julian century */
+#define DJC (36525.0)
+
+/* Days per Julian millennium */
+#define DJM (365250.0)
+
+/* Reference epoch (J2000.0), Julian Date */
+#define DJ00 (2451545.0)
+
+/* Julian Date of Modified Julian Date zero */
+#define DJM0 (2400000.5)
+
+/* Reference epoch (J2000.0), Modified Julian Date */
+#define DJM00 (51544.5)
+
+/* 1977 Jan 1.0 as MJD */
+#define DJM77 (43144.0)
+
+/* TT minus TAI (s) */
+#define TTMTAI (32.184)
+
+/* AU (m) */
+#define DAU (149597870e3)
+
+/* Speed of light (AU per day) */
+#define DC (DAYSEC / 499.004782)
+
+/* L_G = 1 - d(TT)/d(TCG) */
+#define ELG (6.969290134e-10)
+
+/* L_B = 1 - d(TDB)/d(TCB), and TDB (s) at TAI 1977/1/1.0 */
+#define ELB (1.550519768e-8)
+#define TDB0 (-6.55e-5)
+
+/* dint(A) - truncate to nearest whole number towards zero (double) */
+#define dint(A) ((A)<0.0?ceil(A):floor(A))
+
+/* dnint(A) - round to nearest whole number (double) */
+#define dnint(A) ((A)<0.0?ceil((A)-0.5):floor((A)+0.5))
+
+/* dsign(A,B) - magnitude of A with sign of B (double) */
+#define dsign(A,B) ((B)<0.0?-fabs(A):fabs(A))
+
+/* Reference ellipsoids */
+#define WGS84 1
+#define GRS80 2
+#define WGS72 3
+
+#endif
+
+/*----------------------------------------------------------------------
+**
+**  Copyright (C) 2012
+**  Standards Of Fundamental Astronomy Board
+**  of the International Astronomical Union.
+**
+**  =====================
+**  SOFA Software License
+**  =====================
+**
+**  NOTICE TO USER:
+**
+**  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+**  CONDITIONS WHICH APPLY TO ITS USE.
+**
+**  1. The Software is owned by the IAU SOFA Board ("SOFA").
+**
+**  2. Permission is granted to anyone to use the SOFA software for any
+**     purpose, including commercial applications, free of charge and
+**     without payment of royalties, subject to the conditions and
+**     restrictions listed below.
+**
+**  3. You (the user) may copy and distribute SOFA source code to others,
+**     and use and adapt its code and algorithms in your own software,
+**     on a world-wide, royalty-free basis.  That portion of your
+**     distribution that does not consist of intact and unchanged copies
+**     of SOFA source code files is a "derived work" that must comply
+**     with the following requirements:
+**
+**     a) Your work shall be marked or carry a statement that it
+**        (i) uses routines and computations derived by you from
+**        software provided by SOFA under license to you; and
+**        (ii) does not itself constitute software provided by and/or
+**        endorsed by SOFA.
+**
+**     b) The source code of your derived work must contain descriptions
+**        of how the derived work is based upon, contains and/or differs
+**        from the original SOFA software.
+**
+**     c) The names of all routines in your derived work shall not
+**        include the prefix "iau" or "sofa" or trivial modifications
+**        thereof such as changes of case.
+**
+**     d) The origin of the SOFA components of your derived work must
+**        not be misrepresented;  you must not claim that you wrote the
+**        original software, nor file a patent application for SOFA
+**        software or algorithms embedded in the SOFA software.
+**
+**     e) These requirements must be reproduced intact in any source
+**        distribution and shall apply to anyone to whom you have
+**        granted a further right to modify the source code of your
+**        derived work.
+**
+**     Note that, as originally distributed, the SOFA software is
+**     intended to be a definitive implementation of the IAU standards,
+**     and consequently third-party modifications are discouraged.  All
+**     variations, no matter how minor, must be explicitly marked as
+**     such, as explained above.
+**
+**  4. You shall not cause the SOFA software to be brought into
+**     disrepute, either by misuse, or use for inappropriate tasks, or
+**     by inappropriate modification.
+**
+**  5. The SOFA software is provided "as is" and SOFA makes no warranty
+**     as to its use or performance.   SOFA does not and cannot warrant
+**     the performance or results which the user may obtain by using the
+**     SOFA software.  SOFA makes no warranties, express or implied, as
+**     to non-infringement of third party rights, merchantability, or
+**     fitness for any particular purpose.  In no event will SOFA be
+**     liable to the user for any consequential, incidental, or special
+**     damages, including any lost profits or lost savings, even if a
+**     SOFA representative has been advised of such damages, or for any
+**     claim by any third party.
+**
+**  6. The provision of any version of the SOFA software under the terms
+**     and conditions specified herein does not imply that future
+**     versions will also be made available under the same terms and
+**     conditions.
+*
+**  In any published work or commercial product which uses the SOFA
+**  software directly, acknowledgement (see www.iausofa.org) is
+**  appreciated.
+**
+**  Correspondence concerning SOFA software should be addressed as
+**  follows:
+**
+**      By email:  sofa at ukho.gov.uk
+**      By post:   IAU SOFA Center
+**                 HM Nautical Almanac Office
+**                 UK Hydrographic Office
+**                 Admiralty Way, Taunton
+**                 Somerset, TA1 2DN
+**                 United Kingdom
+**
+**--------------------------------------------------------------------*/
diff --git a/cextern/trim_wcslib.sh b/cextern/trim_wcslib.sh
new file mode 100755
index 0000000..007e265
--- /dev/null
+++ b/cextern/trim_wcslib.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+# This script should be run every time wcslib is updated.
+
+# This removes extra large files from wcslib that aren't needed.
+
+rm -rf wcslib/C/test
+rm -rf wcslib/doxygen
+rm -rf wcslib/Fortran
+rm -rf wcslib/html
+rm -rf wcslib/pgsbox
+rm -rf wcslib/utils
+rm wcslib/*.pdf
diff --git a/cextern/wcslib/C/GNUmakefile b/cextern/wcslib/C/GNUmakefile
new file mode 100644
index 0000000..1500adc
--- /dev/null
+++ b/cextern/wcslib/C/GNUmakefile
@@ -0,0 +1,444 @@
+#-----------------------------------------------------------------------------
+# GNU makefile for building WCSLIB 4.16 and its test suite.
+#
+# Summary of the main targets
+# ---------------------------
+#   build:     Build the library.
+#
+#   clean:     Delete intermediate object files.
+#
+#   cleaner:   clean, and also delete the test executables.
+#
+#   cleanest (distclean or realclean): cleaner, and also delete the object
+#              library the C source files generated by 'flex'.
+#
+#   check (or test): Compile and run the test programs.  By default they are
+#              executed in batch mode, and non-graphical tests only report
+#              "PASS" on success.  Use
+#
+#                make MODE=interactive check
+#
+#              to run them interactively with full diagnostic output.  To skip
+#              graphical tests even if PGPLOT is available, use
+#
+#                make CHECK=nopgplot check
+#
+#   tests:     Compile the test programs (but don't run them).
+#
+# Notes:
+#   1) If you need to make changes then preferably modify ../makedefs.in
+#      instead and re-run configure.
+#
+# Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
+# http://www.atnf.csiro.au/people/Mark.Calabretta
+# $Id: GNUmakefile,v 4.16 2012/11/07 04:42:44 cal103 Exp $
+#-----------------------------------------------------------------------------
+# Get configure settings.
+include ../makedefs
+
+FLEXMODS := $(patsubst %.l,%.c,$(wildcard *.l))
+MODULES  := $(sort \
+              $(patsubst %.c,%.o, \
+                $(filter-out getwcstab.c,$(wildcard *.c)) $(FLEXMODS)))
+
+ifeq "$(WCSTRIG)" "MACRO"
+  CPPFLAGS += -DWCSTRIG_MACRO
+  MODULES  := $(filter-out wcstrig.o, $(MODULES))
+else
+  ifeq "$(WCSTRIG)" "NATIVE"
+    MODULES := $(filter-out wcstrig.o, $(MODULES))
+  endif
+endif
+
+# For building the sharable library.
+PICLIB := libwcs-PIC.a
+
+CPPFLAGS += -I. -I..
+
+vpath %.c  test
+vpath %.h  ..
+vpath %.in ..
+
+
+# For building and exercising the test suite
+# ------------------------------------------
+# Signals tfitshdr to use wcshdr().
+ifneq "$(DO_WCSHDR)" ""
+  CPPFLAGS += -DDO_WCSHDR
+endif
+
+# Test programs that don't require CFITSIO or PGPLOT...
+TEST_N := tlin tlog tprj1 tsph tsphdpa tspx ttab1 twcs twcssub tpih1 tbth1 \
+          tfitshdr tunits twcsfix
+
+# ...and unofficial test programs.
+TEST_n := tspcaips tspcspxe tspctrne twcs_locale
+
+# Test programs that require CFITSIO (they don't need PGPLOT).
+TEST_C := twcstab twcshdr
+
+# Test programs that require PGPLOT but not PGSBOX.
+TEST_P := tspc tprj2 tcel1 tcel2 ttab2 ttab3 twcsmix
+
+# Test programs that require PGPLOT and PGSBOX.
+TEST_B := tpih2
+
+# Test programs that aren't automatically exercised.
+TEST_X := tsphdpa twcshdr
+
+TESTS  := $(TEST_N)
+
+# Add test programs that require CFITSIO if we have it.
+ifneq "$(CFITSIOINC)" ""
+ifneq "$(CFITSIOLIB)" ""
+  TESTS += $(TEST_C)
+endif
+endif
+
+# Add test programs that require PGPLOT if we have it.
+ifneq "$(CHECK)" "nopgplot"
+ifneq "$(PGPLOTINC)" ""
+ifneq "$(PGPLOTLIB)" ""
+  TESTS += $(TEST_P) $(TEST_B)
+endif
+endif
+endif
+
+# Remove tests that aren't automatically exercised.
+TESTS := $(filter-out $(TEST_X), $(TESTS))
+
+PGSBOXLIB := ../pgsbox/libpgsbox-$(LIBVER).a
+
+# Pattern rules
+#--------------
+
+ifeq "$(FLEX)" "flex"
+  %.c : %.l
+	-@ echo ''
+	-@ $(RM) $@
+	   $(FLEX) $(FLFLAGS) -t $< | sed -e 's/^[	 ]*#/#/' > $@
+else
+  %.c : %.l
+	-@ echo ''
+	-@ $(RM) $@
+	   cp flexed/$@ .
+endif
+
+$(WCSLIB)(%.o) : %.c
+	-@ echo ''
+	   $(CC) $(CPPFLAGS) $(CFLAGS) -c $<
+	   $(AR) r $(WCSLIB) $%
+	-@ $(RM) $%
+
+$(PICLIB)(%.o) : %.c
+	-@ echo ''
+	   $(CC) $(CPPFLAGS) $(CFLAGS) $(SHRFLAGS) -c $<
+	   $(AR) r $(PICLIB) $%
+	-@ $(RM) $%
+
+%.i : %.c
+	-@ echo ''
+	-@ $(RM) $@
+	   $(CPP) $(CPPFLAGS) $(CFLAGS) $< > $@
+
+# Print out include file dependencies.
+%.d : %.c
+	-@ echo ''
+	-@ $(CPP) $(CPPFLAGS) $(CFLAGS) $< | \
+	   sed -n -e 's|^# 1 "\([^/].*\.h\)".*|\1|p' | \
+	   sort -u
+
+# Use 'make FLAVOUR=Linux run_%' to have VALGRIND defined (from flavours).
+run_% : %
+	-@ echo ''
+	-@ $(TIMER)
+	 @ if [ '$(MODE)' = interactive -o '$(VALGRIND)' ] ; then \
+	     printf 'Press <CR> to run $<: ' ; \
+	     read DUMMY ; \
+	   fi ; \
+	   if [ '$(VALGRIND)' ] ; then \
+	     if [ '$<' = tunits ] ; then \
+	       $(VALGRIND) ./$< < test/units_test ; \
+	     else \
+	       $(VALGRIND) ./$< ; \
+	     fi ; \
+	   else \
+	     if [ '$(filter $<, $(TEST_N) $(TEST_C))' ] ; then \
+	       if [ '$<' = tunits ] ; then \
+	         if [ '$(MODE)' = interactive ] ; then \
+	           ./$< < test/units_test 2>&1 | tee $<.out ; \
+	         else \
+	           ./$< < test/units_test > $<.out 2>&1 ; \
+	         fi ; \
+	       else \
+	         if [ '$(MODE)' = interactive ] ; then \
+	           ./$< < /dev/null 2>&1 | tee $<.out ; \
+	         else \
+	           ./$< < /dev/null > $<.out 2>&1 ; \
+	         fi ; \
+	       fi ; \
+	       if grep 'PASS:' $<.out > /dev/null ; then \
+	         if [ '$(MODE)' != interactive ] ; then \
+	           head -2 $<.out ; \
+	           grep 'PASS:' $<.out ; \
+	         fi ; \
+	         echo 'PASS: C/$<' >> test_results ; \
+	       elif [ -f 'test/$<.out' ] ; then \
+	         trap 'rm -f run_test.tmp' 0 1 2 3 15 ; \
+	         sed -e 's/0x[0-9a-f][0-9a-f][0-9a-f]*/0x<address>/g' $<.out > \
+	           run_test.tmp ; \
+	         mv -f run_test.tmp $<.out ; \
+	         if cmp -s $<.out test/$<.out ; then \
+	           if [ '$(MODE)' != interactive ] ; then \
+	             head -1 $<.out ; \
+	           fi ; \
+	           echo '' ; \
+	           echo 'PASS: Output agrees with C/test/$<.out' ; \
+	           echo 'PASS: C/$<' >> test_results ; \
+	         else \
+	           if [ '$(MODE)' != interactive ] ; then \
+	             cat $<.out ; \
+	           fi ; \
+	           echo '' ; \
+	           echo 'FAIL: Output disagrees with C/test/$<.out' ; \
+	           echo 'FAIL: C/$<' >> test_results ; \
+	         fi ; \
+	       elif [ '$(MODE)' != interactive ] ; then \
+	         cat $<.out ; \
+	         echo 'FAIL: C/$<' >> test_results ; \
+	       fi ; \
+	     elif [ '$(MODE)' = interactive ] ; then \
+	       ./$< ; \
+	     else \
+	       if [ '$<' = tcel2 ] ; then \
+	         echo N | ./$< ; \
+	       else \
+	         ./$< < /dev/null 2>&1 ; \
+	       fi ; \
+	     fi ; \
+	   fi
+	-@ echo ''
+
+# Static and static pattern rules
+#--------------------------------
+
+.PHONY : build check clean cleaner cleanest distclean install lib realclean \
+         run_% test tests
+
+build : lib
+
+lib : $(FLEXMODS) $(WCSLIB) $(SHRLIB)
+
+$(WCSLIB) : $(MODULES:%=$(WCSLIB)(%))
+	-@ echo ''
+	   $(RANLIB) $@
+
+$(SHRLIB) : $(PICLIB)
+	-@ echo ''
+	-@ $(RM) -r tmp
+	   mkdir tmp && \
+	     cd tmp && \
+	     trap 'cd .. ; $(RM) -r tmp' 0 1 2 3 15 ; \
+	     $(AR) x ../$(PICLIB) && \
+	     $(SHRLD) -o $@ *.o $(LDFLAGS) $(LIBS) && \
+	     mv $@ ..
+
+$(PICLIB) : $(MODULES:%.o=$(PICLIB)(%.o)) ;
+
+install : build
+	-  if [ ! -d "$(LIBDIR)" ] ; then \
+	     $(INSTALL) -d -m 2775 $(LIBDIR) ; \
+	   fi
+	   $(INSTALL) -m 644 $(WCSLIB) $(LIBDIR)
+	   $(RANLIB) $(LIBDIR)/$(WCSLIB)
+	-  if [ -h "$(LIBDIR)/libwcs.a" ] ; then \
+	     $(RM) $(LIBDIR)/libwcs.a ; \
+	   fi
+	-  $(LN_S) $(WCSLIB) $(LIBDIR)/libwcs.a
+	-  if [ "$(SHRLIB)" != "" ] ; then \
+	     $(INSTALL) -m 644 $(SHRLIB) $(LIBDIR) ; \
+	     if [ -h "$(LIBDIR)/$(SONAME)" ] ; then \
+	       $(RM) $(LIBDIR)/$(SONAME) ; \
+	     fi ; \
+	     $(LN_S) $(SHRLIB) $(LIBDIR)/$(SONAME) ; \
+	     if [ "$(SHRLN)" != "" ] ; then \
+	       if [ -h "$(LIBDIR)/$(SHRLN)" ] ; then \
+	         $(RM) $(LIBDIR)/$(SHRLN) ; \
+	       fi ; \
+	       $(LN_S) $(SONAME) $(LIBDIR)/$(SHRLN) ; \
+	     fi ; \
+	   fi
+	-  if [ ! -d "$(INCDIR)" ] ; then \
+	     $(INSTALL) -d -m 2775 $(INCDIR) ; \
+	   fi
+	   $(INSTALL) -m 444 *.h $(INCDIR)
+	   $(RM) $(INCLINK)
+	   $(LN_S) $(notdir $(INCDIR)) $(INCLINK)
+
+clean :
+	- $(RM) -r *.o *.i a.out t*.out core *.dSYM $(EXTRA_CLEAN)
+
+cleaner : clean
+	-  $(RM) .gdb_history
+	-  $(RM) $(TEST_N) $(TEST_n) $(TEST_X)
+	-  $(RM) $(TEST_P) tpih2 twcstab twcshdr
+	-  $(RM) tofits bth.fits pih.fits wcstab.fits
+	-  $(RM) t*_cfitsio test_results
+
+cleanest distclean realclean : cleaner
+	-  $(RM) ../wcsconfig.h ../wcsconfig_tests.h
+	-  $(RM) fitshdr.c wcsbth.c wcspih.c wcsulex.c wcsutrn.c
+	-  $(RM) $(PICLIB) libwcs-*.a libwcs.so.* libwcs.*.dylib
+
+check test : tests $(TESTS:%=run_%)
+
+tests : $(TESTS) $(TEST_X)
+
+$(TEST_N) $(TEST_n) : % : test/%.c $(WCSLIB)
+	-@ echo ''
+	   $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $< $(LDFLAGS) $(WCSLIB) $(LIBS)
+	-@ $(RM) $@.o
+
+$(TEST_P) : % : test/%.c $(WCSLIB)
+	-@ echo ''
+	   $(CC) $(CPPFLAGS) $(PGPLOTINC) $(CFLAGS) -c -o $@.o $<
+	   $(LD) -o $@ $@.o $(LDFLAGS) $(PGPLOTLIB) $(WCSLIB) $(FLIBS) $(LIBS)
+	-@ $(RM) $@.o
+
+tpih2 : test/tpih2.c $(PGSBOXLIB) $(WCSLIB)
+	-@ echo ''
+	   $(CC) $(CPPFLAGS) -I../pgsbox $(PGPLOTINC) $(CFLAGS) -c -o $@.o $<
+	   $(LD) -o $@ $@.o $(LDFLAGS) $(PGSBOXLIB) $(PGPLOTLIB) $(WCSLIB) \
+	     $(FLIBS) $(LIBS)
+	-@ $(RM) $@.o
+
+tfitshdr_cfitsio tpih1_cfitsio tbth1_cfitsio : %_cfitsio : test/%.c $(WCSLIB)
+	-@ echo ''
+	   $(CC) -DDO_CFITSIO $(CPPFLAGS) $(CFITSIOINC) $(CFLAGS) \
+	     -o $@ $< $(LDFLAGS) $(CFITSIOLIB) $(WCSLIB) $(LIBS)
+	-@ $(RM) $@.o
+
+tpih2_cfitsio : test/tpih2.c $(PGSBOXLIB) $(WCSLIB)
+	-@ echo ''
+	   $(CC) -DDO_CFITSIO $(CPPFLAGS) -I../pgsbox $(PGPLOTINC) \
+	     $(CFITSIOINC) $(CFLAGS) -c -o $@.o $<
+	   $(LD) -o $@ $@.o $(LDFLAGS) $(PGSBOXLIB) $(PGPLOTLIB) \
+	     $(CFITSIOLIB) $(WCSLIB) $(FLIBS) $(LIBS)
+	-@ $(RM) $@.o
+
+twcstab : test/twcstab.c $(GETWCSTAB) $(WCSLIB)
+	-@ echo ''
+	   $(CC) $(CPPFLAGS) $(CFITSIOINC) $(CFLAGS) -o $@ $< $(GETWCSTAB) \
+	     $(LDFLAGS) $(CFITSIOLIB) $(WCSLIB) $(LIBS)
+	-@ $(RM) $@.o
+
+twcshdr : test/twcshdr.c $(GETWCSTAB) $(WCSLIB)
+	-@ echo ''
+	   $(CC) $(CPPFLAGS) $(CFITSIOINC) $(CFLAGS) -o $@ $< $(GETWCSTAB) \
+	     $(LDFLAGS) $(CFITSIOLIB) $(WCSLIB) $(LIBS)
+	-@ $(RM) $@.o
+
+getwcstab.o : getwcstab.c getwcstab.h
+	-@ echo ''
+	   $(CC) $(CPPFLAGS) $(CFLAGS) $(CFITSIOINC) -c $<
+
+$(PGSBOXLIB) :
+	-@ echo ''
+	   $(MAKE) -C ../pgsbox lib
+
+tofits : test/tofits.c
+	   $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $<
+
+pih.fits : test/pih.keyrec tofits
+	   ./tofits < $< > $@
+
+bth.fits : test/bth.keyrec tofits
+	   ./tofits < $< > $@
+
+GNUmakefile : ../makedefs ;
+
+../makedefs ../wcsconfig.h ../wcsconfig_tests.h : makedefs.in wcsconfig.h.in \
+    wcsconfig_tests.h.in ../config.status
+	-@ $(RM) ../wcsconfig.h ../wcsconfig_tests.h
+	   cd .. && ./config.status
+
+show ::
+	-@ -@ echo '  FLEXMODS    := $(FLEXMODS)'
+	-@ -@ echo '  MODULES     := $(MODULES)'
+
+# Dependencies (use the %.d pattern rule to list them)
+#-----------------------------------------------------
+
+$(WCSLIB)(cel.o)      : cel.h prj.h sph.h wcsconfig.h wcserr.h wcsmath.h \
+                        wcsprintf.h wcstrig.h
+$(WCSLIB)(fitshdr.o)  : wcsconfig.h fitshdr.h wcsutil.h
+$(WCSLIB)(lin.o)      : lin.h wcserr.h wcsprintf.h
+$(WCSLIB)(log.o)      : log.h
+$(WCSLIB)(prj.o)      : prj.h wcsconfig.h wcserr.h wcsmath.h wcsprintf.h \
+                        wcstrig.h wcsutil.h
+$(WCSLIB)(spc.o)      : spc.h spx.h wcserr.h wcsmath.h wcsprintf.h wcstrig.h \
+                        wcsutil.h
+$(WCSLIB)(sph.o)      : sph.h wcsconfig.h wcstrig.h
+$(WCSLIB)(spx.o)      : spx.h wcserr.h wcsmath.h
+$(WCSLIB)(tab.o)      : tab.h wcserr.h wcsmath.h wcsprintf.h
+$(WCSLIB)(wcs.o)      : cel.h lin.h log.h prj.h spc.h sph.h spx.h tab.h \
+                        wcs.h wcsconfig.h wcserr.h wcsmath.h wcsprintf.h \
+                        wcstrig.h wcsunits.h wcsutil.h
+$(WCSLIB)(wcsbth.o)   : cel.h lin.h prj.h spc.h spx.h tab.h wcs.h wcserr.h \
+                        wcshdr.h wcsmath.h wcsutil.h
+$(WCSLIB)(wcserr.o)   : wcserr.h wcsprintf.h
+$(WCSLIB)(wcsfix.o)   : cel.h lin.h prj.h spc.h sph.h spx.h tab.h wcs.h \
+                        wcserr.h wcsfix.h wcsmath.h wcsunits.h wcsutil.h
+$(WCSLIB)(wcshdr.o)   : cel.h lin.h prj.h spc.h spx.h tab.h wcs.h wcserr.h \
+                        wcshdr.h wcsmath.h wcsutil.h
+$(WCSLIB)(wcspih.o)   : cel.h lin.h prj.h spc.h spx.h tab.h wcs.h wcserr.h \
+                        wcshdr.h wcsmath.h wcsutil.h
+$(WCSLIB)(wcsprintf.o): wcsprintf.h
+$(WCSLIB)(wcstrig.o)  : wcsconfig.h wcsmath.h wcstrig.h
+$(WCSLIB)(wcsulex.o)  : wcserr.h wcsmath.h wcsunits.h wcsutil.h
+$(WCSLIB)(wcsunits.o) : wcserr.h wcsunits.h
+$(WCSLIB)(wcsutil.o)  : wcsutil.h
+$(WCSLIB)(wcsutrn.o)  : wcserr.h wcsunits.h
+
+tbth1 tbth1_cfitsio : cel.h lin.h prj.h spc.h spx.h tab.h wcs.h wcsconfig.h \
+                      wcsconfig_tests.h wcserr.h wcsfix.h wcshdr.h
+tcel1   : cel.h prj.h wcserr.h
+tcel2   : cel.h prj.h wcserr.h
+tfitshdr tfitshdr_cfitsio : fitshdr.h wcsconfig.h wcsconfig_tests.h
+tlin    : lin.h wcserr.h
+tlog    : log.h
+tpih1 tpih1_cfitsio : cel.h lin.h prj.h spc.h spx.h tab.h wcs.h wcsconfig.h \
+                      wcsconfig_tests.h wcserr.h wcsfix.h wcshdr.h wcsprintf.h
+tpih2 tpih2_cfitsio : cel.h lin.h prj.h spc.h spx.h tab.h wcs.h wcsconfig.h \
+                      wcsconfig_tests.h wcserr.h wcshdr.h
+tprj1   : prj.h wcsconfig.h wcserr.h wcstrig.h
+tprj2   : prj.h wcserr.h
+tspc    : spc.h spx.h wcsconfig.h wcserr.h wcstrig.h
+tspcaips: spc.h
+tspctrne: spc.h wcserr.h
+tsph    : sph.h wcsconfig.h wcstrig.h
+tsphdpa : sph.h
+tspx    : spx.h wcserr.h
+ttab1   : tab.h wcserr.h
+ttab2   : tab.h wcserr.h
+ttab3   : prj.h tab.h wcserr.h
+tunits  : wcserr.h wcsunits.h
+twcs    : cel.h lin.h log.h prj.h spc.h sph.h spx.h tab.h wcs.h wcsconfig.h \
+          wcsconfig_tests.h wcserr.h wcsfix.h wcshdr.h wcslib.h wcsmath.h \
+          wcsprintf.h wcstrig.h wcsunits.h wcsutil.h
+twcs_locale : wcs.h wcserr.h wcshdr.h wcsprintf.h
+twcsfix : cel.h lin.h prj.h spc.h spx.h tab.h wcs.h wcserr.h wcsfix.h \
+          wcsunits.h
+twcshdr : cel.h fitshdr.h getwcstab.h lin.h log.h prj.h spc.h sph.h spx.h \
+          tab.h wcs.h wcsconfig.h wcserr.h wcsfix.h wcshdr.h wcslib.h \
+          wcsmath.h wcsprintf.h wcstrig.h wcsunits.h wcsutil.h
+twcsmix : cel.h lin.h prj.h spc.h sph.h spx.h tab.h wcs.h wcserr.h
+twcssub : cel.h lin.h prj.h spc.h spx.h tab.h wcs.h wcserr.h
+twcstab : cel.h fitshdr.h getwcstab.h lin.h log.h prj.h spc.h sph.h spx.h \
+          tab.h wcs.h wcsconfig.h wcserr.h wcsfix.h wcshdr.h wcslib.h \
+          wcsmath.h wcsprintf.h wcstrig.h wcsunits.h wcsutil.h
+
+run_tbth1 run_tbth1_cfitsio : bth.fits
+run_tfitshdr run_tfitshdr_cfitsio : pih.fits
+run_tpih1 run_tpih1_cfitsio : pih.fits
+run_tpih2 run_tpih2_cfitsio : pih.fits
diff --git a/cextern/wcslib/C/cel.c b/cextern/wcslib/C/cel.c
new file mode 100644
index 0000000..18618d7
--- /dev/null
+++ b/cextern/wcslib/C/cel.c
@@ -0,0 +1,504 @@
+/*============================================================================
+
+  WCSLIB 4.16 - an implementation of the FITS WCS standard.
+  Copyright (C) 1995-2012, Mark Calabretta
+
+  This file is part of WCSLIB.
+
+  WCSLIB is free software: you can redistribute it and/or modify it under the
+  terms of the GNU Lesser General Public License as published by the Free
+  Software Foundation, either version 3 of the License, or (at your option)
+  any later version.
+
+  WCSLIB 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 Lesser General Public License for
+  more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with WCSLIB.  If not, see http://www.gnu.org/licenses.
+
+  Direct correspondence concerning WCSLIB to mark at calabretta.id.au
+
+  Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
+  http://www.atnf.csiro.au/people/Mark.Calabretta
+  $Id: cel.c,v 4.16 2012/11/07 04:42:44 cal103 Exp $
+*===========================================================================*/
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "wcserr.h"
+#include "wcsmath.h"
+#include "wcsprintf.h"
+#include "wcstrig.h"
+#include "sph.h"
+#include "cel.h"
+
+const int CELSET = 137;
+
+/* Map status return value to message. */
+const char *cel_errmsg[] = {
+  "Success",
+  "Null celprm pointer passed",
+  "Invalid projection parameters",
+  "Invalid coordinate transformation parameters",
+  "Ill-conditioned coordinate transformation parameters",
+  "One or more of the (x,y) coordinates were invalid",
+  "One or more of the (lng,lat) coordinates were invalid"};
+
+/* Convenience macro for invoking wcserr_set(). */
+#define CEL_ERRMSG(status) WCSERR_SET(status), cel_errmsg[status]
+
+/*--------------------------------------------------------------------------*/
+
+int celini(cel)
+
+struct celprm *cel;
+
+{
+  register int k;
+
+  if (cel == 0x0) return CELERR_NULL_POINTER;
+
+  cel->flag = 0;
+
+  cel->offset = 0;
+  cel->phi0   = UNDEFINED;
+  cel->theta0 = UNDEFINED;
+  cel->ref[0] =   0.0;
+  cel->ref[1] =   0.0;
+  cel->ref[2] = UNDEFINED;
+  cel->ref[3] = +90.0;
+
+  for (k = 0; k < 5; cel->euler[k++] = 0.0);
+  cel->latpreq = -1;
+
+  cel->err = 0x0;
+
+  return prjini(&(cel->prj));
+}
+
+/*--------------------------------------------------------------------------*/
+
+int celfree(cel)
+
+struct celprm *cel;
+
+{
+  if (cel == 0x0) return CELERR_NULL_POINTER;
+
+  if (cel->err) {
+    free(cel->err);
+    cel->err = 0x0;
+  }
+
+  prjfree(&(cel->prj));
+
+  return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int celprt(cel)
+
+const struct celprm *cel;
+
+{
+  int i;
+
+  if (cel == 0x0) return CELERR_NULL_POINTER;
+
+  wcsprintf("      flag: %d\n",  cel->flag);
+  wcsprintf("     offset: %d\n",  cel->offset);
+  if (undefined(cel->phi0)) {
+    wcsprintf("       phi0: UNDEFINED\n");
+  } else {
+    wcsprintf("       phi0: %9f\n", cel->phi0);
+  }
+  if (undefined(cel->theta0)) {
+    wcsprintf("     theta0: UNDEFINED\n");
+  } else {
+    wcsprintf("     theta0: %9f\n", cel->theta0);
+  }
+  wcsprintf("       ref:");
+  for (i = 0; i < 4; i++) {
+    wcsprintf("  %- 11.5g", cel->ref[i]);
+  }
+  wcsprintf("\n");
+  wcsprintf("       prj: (see below)\n");
+
+  wcsprintf("     euler:");
+  for (i = 0; i < 5; i++) {
+    wcsprintf("  %- 11.5g", cel->euler[i]);
+  }
+  wcsprintf("\n");
+  wcsprintf("    latpreq: %d", cel->latpreq);
+  if (cel->latpreq == 0) {
+    wcsprintf(" (not required)\n");
+  } else if (cel->latpreq == 1) {
+    wcsprintf(" (disambiguation)\n");
+  } else if (cel->latpreq == 2) {
+    wcsprintf(" (specification)\n");
+  } else {
+    wcsprintf(" (UNDEFINED)\n");
+  }
+  wcsprintf("     isolat: %d\n", cel->isolat);
+
+  WCSPRINTF_PTR("        err: ", cel->err, "\n");
+  if (cel->err) {
+    wcserr_prt(cel->err, "             ");
+  }
+
+  wcsprintf("\n");
+  wcsprintf("   prj.*\n");
+  prjprt(&(cel->prj));
+
+  return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int celset(cel)
+
+struct celprm *cel;
+
+{
+  static const char *function = "celset";
+
+  const double tol = 1.0e-10;
+  double clat0, cphip, cthe0, lat0, lng0, phip, slat0, slz, sphip, sthe0;
+  double latp, latp1, latp2, lngp;
+  double u, v, x, y, z;
+  struct prjprm *celprj;
+  struct wcserr **err;
+
+  if (cel == 0x0) return CELERR_NULL_POINTER;
+  err = &(cel->err);
+
+  /* Initialize the projection driver routines. */
+  celprj = &(cel->prj);
+  if (cel->offset) {
+    celprj->phi0   = cel->phi0;
+    celprj->theta0 = cel->theta0;
+  } else {
+    /* Ensure that these are undefined - no fiducial offset. */
+    celprj->phi0   = UNDEFINED;
+    celprj->theta0 = UNDEFINED;
+  }
+
+  if (prjset(celprj)) {
+    return wcserr_set(CEL_ERRMSG(CELERR_BAD_PARAM));
+  }
+
+  /* Defaults set by the projection routines. */
+  if (undefined(cel->phi0)) {
+    cel->phi0 = celprj->phi0;
+  }
+
+  if (undefined(cel->theta0)) {
+    cel->theta0 = celprj->theta0;
+
+  } else if (fabs(cel->theta0) > 90.0) {
+    if (fabs(cel->theta0) > 90.0 + tol) {
+      return wcserr_set(WCSERR_SET(CELERR_BAD_COORD_TRANS),
+        "Invalid coordinate transformation parameters: theta0 > 90");
+    }
+
+    if (cel->theta0 > 90.0) {
+      cel->theta0 =  90.0;
+    } else {
+      cel->theta0 = -90.0;
+    }
+  }
+
+
+  lng0 = cel->ref[0];
+  lat0 = cel->ref[1];
+  phip = cel->ref[2];
+  latp = cel->ref[3];
+
+  /* Set default for native longitude of the celestial pole? */
+  if (undefined(phip) || phip == 999.0) {
+    phip = (lat0 < cel->theta0) ? 180.0 : 0.0;
+    phip += cel->phi0;
+
+    if (phip < -180.0) {
+      phip += 360.0;
+    } else if (phip > 180.0) {
+      phip -= 360.0;
+    }
+
+    cel->ref[2] = phip;
+  }
+
+
+  /* Compute celestial coordinates of the native pole. */
+  cel->latpreq = 0;
+  if (cel->theta0 == 90.0) {
+    /* Fiducial point at the native pole. */
+    lngp = lng0;
+    latp = lat0;
+
+  } else {
+    /* Fiducial point away from the native pole. */
+    sincosd(lat0, &slat0, &clat0);
+    sincosd(cel->theta0, &sthe0, &cthe0);
+
+    if (phip == cel->phi0) {
+      sphip = 0.0;
+      cphip = 1.0;
+
+      u = cel->theta0;
+      v = 90.0 - lat0;
+
+    } else {
+      sincosd(phip - cel->phi0, &sphip, &cphip);
+
+      x = cthe0*cphip;
+      y = sthe0;
+      z = sqrt(x*x + y*y);
+      if (z == 0.0) {
+        if (slat0 != 0.0) {
+          return wcserr_set(WCSERR_SET(CELERR_BAD_COORD_TRANS),
+            "Invalid coordinate description:\n"
+            "lat0 == 0 is required for |phip - phi0| = 90 and theta0 == 0");
+        }
+
+        /* latp determined solely by LATPOLEa in this case. */
+        cel->latpreq = 2;
+        if (latp > 90.0) {
+          latp = 90.0;
+        } else if (latp < -90.0) {
+          latp = -90.0;
+        }
+
+      } else {
+        slz = slat0/z;
+        if (fabs(slz) > 1.0) {
+          if ((fabs(slz) - 1.0) < tol) {
+            if (slz > 0.0) {
+              slz = 1.0;
+            } else {
+              slz = -1.0;
+            }
+          } else {
+            return wcserr_set(WCSERR_SET(CELERR_BAD_COORD_TRANS),
+              "Invalid coordinate description:\n|lat0| <= %.3f is required "
+              "for these values of phip, phi0, and theta0", asind(z));
+          }
+        }
+
+        u = atan2d(y,x);
+        v = acosd(slz);
+      }
+    }
+
+    if (cel->latpreq == 0) {
+      latp1 = u + v;
+      if (latp1 > 180.0) {
+        latp1 -= 360.0;
+      } else if (latp1 < -180.0) {
+        latp1 += 360.0;
+      }
+
+      latp2 = u - v;
+      if (latp2 > 180.0) {
+        latp2 -= 360.0;
+      } else if (latp2 < -180.0) {
+        latp2 += 360.0;
+      }
+
+      if (fabs(latp1) < 90.0+tol &&
+          fabs(latp2) < 90.0+tol) {
+        /* There are two valid solutions for latp. */
+        cel->latpreq = 1;
+      }
+
+      if (fabs(latp-latp1) < fabs(latp-latp2)) {
+        if (fabs(latp1) < 90.0+tol) {
+          latp = latp1;
+        } else {
+          latp = latp2;
+        }
+      } else {
+        if (fabs(latp2) < 90.0+tol) {
+          latp = latp2;
+        } else {
+          latp = latp1;
+        }
+      }
+
+      /* Account for rounding error. */
+      if (fabs(latp) < 90.0+tol) {
+        if (latp > 90.0) {
+          latp =  90.0;
+        } else if (latp < -90.0) {
+          latp = -90.0;
+        }
+      }
+    }
+
+    z = cosd(latp)*clat0;
+    if (fabs(z) < tol) {
+      if (fabs(clat0) < tol) {
+        /* Celestial pole at the fiducial point. */
+        lngp = lng0;
+
+      } else if (latp > 0.0) {
+        /* Celestial north pole at the native pole.*/
+        lngp = lng0 + phip - cel->phi0 - 180.0;
+
+      } else {
+        /* Celestial south pole at the native pole. */
+        lngp = lng0 - phip + cel->phi0;
+      }
+
+    } else {
+      x = (sthe0 - sind(latp)*slat0)/z;
+      y =  sphip*cthe0/clat0;
+      if (x == 0.0 && y == 0.0) {
+        /* Sanity check (shouldn't be possible). */
+        return wcserr_set(WCSERR_SET(CELERR_BAD_COORD_TRANS),
+          "Invalid coordinate transformation parameters, internal error");
+      }
+      lngp = lng0 - atan2d(y,x);
+    }
+
+    /* Make celestial longitude of the native pole the same sign as at the
+       fiducial point. */
+    if (lng0 >= 0.0) {
+      if (lngp < 0.0) {
+        lngp += 360.0;
+      } else if (lngp > 360.0) {
+        lngp -= 360.0;
+      }
+    } else {
+      if (lngp > 0.0) {
+        lngp -= 360.0;
+      } else if (lngp < -360.0) {
+        lngp += 360.0;
+      }
+    }
+  }
+
+  /* Reset LATPOLEa. */
+  cel->ref[3] = latp;
+
+  /* Set the Euler angles. */
+  cel->euler[0] = lngp;
+  cel->euler[1] = 90.0 - latp;
+  cel->euler[2] = phip;
+  sincosd(cel->euler[1], &cel->euler[4], &cel->euler[3]);
+  cel->isolat = (cel->euler[4] == 0.0);
+  cel->flag = CELSET;
+
+  /* Check for ill-conditioned parameters. */
+  if (fabs(latp) > 90.0+tol) {
+    return wcserr_set(WCSERR_SET(CELERR_ILL_COORD_TRANS),
+      "Ill-conditioned coordinate transformation parameters\nNo valid "
+      "solution for latp for these values of phip, phi0, and theta0");
+  }
+
+  return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int celx2s(cel, nx, ny, sxy, sll, x, y, phi, theta, lng, lat, stat)
+
+struct celprm *cel;
+int nx, ny, sxy, sll;
+const double x[], y[];
+double phi[], theta[];
+double lng[], lat[];
+int stat[];
+
+{
+  static const char *function = "celx2s";
+
+  int    nphi, status;
+  struct prjprm *celprj;
+  struct wcserr **err;
+
+  /* Initialize. */
+  if (cel == 0x0) return CELERR_NULL_POINTER;
+  err = &(cel->err);
+
+  if (cel->flag != CELSET) {
+    if ((status = celset(cel))) return status;
+  }
+
+  /* Apply spherical deprojection. */
+  celprj = &(cel->prj);
+  if ((status = celprj->prjx2s(celprj, nx, ny, sxy, 1, x, y, phi, theta,
+                               stat))) {
+    if (status == PRJERR_BAD_PIX) {
+      status = CELERR_BAD_PIX;
+    }
+
+    wcserr_set(CEL_ERRMSG(status));
+
+    if (status != CELERR_BAD_PIX) return status;
+  }
+
+  nphi = (ny > 0) ? (nx*ny) : nx;
+
+  /* Compute celestial coordinates. */
+  sphx2s(cel->euler, nphi, 0, 1, sll, phi, theta, lng, lat);
+
+  return status;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int cels2x(cel, nlng, nlat, sll, sxy, lng, lat, phi, theta, x, y, stat)
+
+struct celprm *cel;
+int nlng, nlat, sll, sxy;
+const double lng[], lat[];
+double phi[], theta[];
+double x[], y[];
+int stat[];
+
+{
+  static const char *function = "cels2x";
+
+  int    nphi, ntheta, status;
+  struct prjprm *celprj;
+  struct wcserr **err;
+
+  /* Initialize. */
+  if (cel == 0x0) return CELERR_NULL_POINTER;
+  err = &(cel->err);
+
+  if (cel->flag != CELSET) {
+    if ((status = celset(cel))) return status;
+  }
+
+  /* Compute native coordinates. */
+  sphs2x(cel->euler, nlng, nlat, sll, 1, lng, lat, phi, theta);
+
+  if (cel->isolat) {
+    /* Constant celestial latitude -> constant native latitude. */
+    nphi   = nlng;
+    ntheta = nlat;
+  } else {
+    nphi   = (nlat > 0) ? (nlng*nlat) : nlng;
+    ntheta = 0;
+  }
+
+  /* Apply the spherical projection. */
+  celprj = &(cel->prj);
+  if ((status = celprj->prjs2x(celprj, nphi, ntheta, 1, sxy, phi, theta, x, y,
+                               stat))) {
+    if (status != PRJERR_BAD_PARAM) {
+      status = CELERR_BAD_WORLD;
+    }
+
+    return wcserr_set(CEL_ERRMSG(status));
+  }
+
+  return 0;
+}
diff --git a/cextern/wcslib/C/cel.h b/cextern/wcslib/C/cel.h
new file mode 100644
index 0000000..7fd4210
--- /dev/null
+++ b/cextern/wcslib/C/cel.h
@@ -0,0 +1,435 @@
+/*============================================================================
+
+  WCSLIB 4.16 - an implementation of the FITS WCS standard.
+  Copyright (C) 1995-2012, Mark Calabretta
+
+  This file is part of WCSLIB.
+
+  WCSLIB is free software: you can redistribute it and/or modify it under the
+  terms of the GNU Lesser General Public License as published by the Free
+  Software Foundation, either version 3 of the License, or (at your option)
+  any later version.
+
+  WCSLIB 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 Lesser General Public License for
+  more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with WCSLIB.  If not, see http://www.gnu.org/licenses.
+
+  Direct correspondence concerning WCSLIB to mark at calabretta.id.au
+
+  Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
+  http://www.atnf.csiro.au/people/Mark.Calabretta
+  $Id: cel.h,v 4.16 2012/11/07 04:42:44 cal103 Exp $
+*=============================================================================
+*
+* WCSLIB 4.16 - C routines that implement the FITS World Coordinate System
+* (WCS) standard.  Refer to
+*
+*   "Representations of world coordinates in FITS",
+*   Greisen, E.W., & Calabretta, M.R. 2002, A&A, 395, 1061 (Paper I)
+*
+*   "Representations of celestial coordinates in FITS",
+*   Calabretta, M.R., & Greisen, E.W. 2002, A&A, 395, 1077 (Paper II)
+*
+* Refer to the README file provided with WCSLIB for an overview of the
+* library.
+*
+*
+* Summary of the cel routines
+* ---------------------------
+* These routines implement the part of the FITS World Coordinate System (WCS)
+* standard that deals with celestial coordinates.  They define methods to be
+* used for computing celestial world coordinates from intermediate world
+* coordinates (a linear transformation of image pixel coordinates), and vice
+* versa.  They are based on the celprm struct which contains all information
+* needed for the computations.  This struct contains some elements that must
+* be set by the user, and others that are maintained by these routines,
+* somewhat like a C++ class but with no encapsulation.
+*
+* Routine celini() is provided to initialize the celprm struct with default
+* values, celfree() reclaims any memory that may have been allocated to store
+* an error message, and celprt() prints its contents.
+*
+* A setup routine, celset(), computes intermediate values in the celprm struct
+* from parameters in it that were supplied by the user.  The struct always
+* needs to be set up by celset() but it need not be called explicitly - refer
+* to the explanation of celprm::flag.
+*
+* celx2s() and cels2x() implement the WCS celestial coordinate
+* transformations.  In fact, they are high level driver routines for the lower
+* level spherical coordinate rotation and projection routines described in
+* sph.h and prj.h.
+*
+*
+* celini() - Default constructor for the celprm struct
+* ----------------------------------------------------
+* celini() sets all members of a celprm struct to default values.  It should
+* be used to initialize every celprm struct.
+*
+* Returned:
+*   cel       struct celprm*
+*                       Celestial transformation parameters.
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         1: Null celprm pointer passed.
+*
+*
+* celfree() - Destructor for the celprm struct
+* --------------------------------------------
+* celfree() frees any memory that may have been allocated to store an error
+* message in the celprm struct.
+*
+* Given:
+*   cel       struct celprm*
+*                       Celestial transformation parameters.
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         1: Null celprm pointer passed.
+*
+*
+* celprt() - Print routine for the celprm struct
+* ----------------------------------------------
+* celprt() prints the contents of a celprm struct using wcsprintf().  Mainly
+* intended for diagnostic purposes.
+*
+* Given:
+*   cel       const struct celprm*
+*                       Celestial transformation parameters.
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         1: Null celprm pointer passed.
+*
+*
+* celset() - Setup routine for the celprm struct
+* ----------------------------------------------
+* celset() sets up a celprm struct according to information supplied within
+* it.
+*
+* Note that this routine need not be called directly; it will be invoked by
+* celx2s() and cels2x() if celprm::flag is anything other than a predefined
+* magic value.
+*
+* Given and returned:
+*   cel       struct celprm*
+*                       Celestial transformation parameters.
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         1: Null celprm pointer passed.
+*                         2: Invalid projection parameters.
+*                         3: Invalid coordinate transformation parameters.
+*                         4: Ill-conditioned coordinate transformation
+*                            parameters.
+*
+*                       For returns > 1, a detailed error message is set in
+*                       celprm::err if enabled, see wcserr_enable().
+*
+*
+* celx2s() - Pixel-to-world celestial transformation
+* --------------------------------------------------
+* celx2s() transforms (x,y) coordinates in the plane of projection to
+* celestial coordinates (lng,lat).
+*
+* Given and returned:
+*   cel       struct celprm*
+*                       Celestial transformation parameters.
+*
+* Given:
+*   nx,ny     int       Vector lengths.
+*
+*   sxy,sll   int       Vector strides.
+*
+*   x,y       const double[]
+*                       Projected coordinates in pseudo "degrees".
+*
+* Returned:
+*   phi,theta double[]  Longitude and latitude (phi,theta) in the native
+*                       coordinate system of the projection [deg].
+*
+*   lng,lat   double[]  Celestial longitude and latitude (lng,lat) of the
+*                       projected point [deg].
+*
+*   stat      int[]     Status return value for each vector element:
+*                         0: Success.
+*                         1: Invalid value of (x,y).
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         1: Null celprm pointer passed.
+*                         2: Invalid projection parameters.
+*                         3: Invalid coordinate transformation parameters.
+*                         4: Ill-conditioned coordinate transformation
+*                            parameters.
+*                         5: One or more of the (x,y) coordinates were
+*                            invalid, as indicated by the stat vector.
+*
+*                       For returns > 1, a detailed error message is set in
+*                       celprm::err if enabled, see wcserr_enable().
+*
+*
+* cels2x() - World-to-pixel celestial transformation
+* --------------------------------------------------
+* cels2x() transforms celestial coordinates (lng,lat) to (x,y) coordinates in
+* the plane of projection.
+*
+* Given and returned:
+*   cel       struct celprm*
+*                       Celestial transformation parameters.
+*
+* Given:
+*   nlng,nlat int       Vector lengths.
+*
+*   sll,sxy   int       Vector strides.
+*
+*   lng,lat   const double[]
+*                       Celestial longitude and latitude (lng,lat) of the
+*                       projected point [deg].
+*
+* Returned:
+*   phi,theta double[]  Longitude and latitude (phi,theta) in the native
+*                       coordinate system of the projection [deg].
+*
+*   x,y       double[]  Projected coordinates in pseudo "degrees".
+*
+*   stat      int[]     Status return value for each vector element:
+*                         0: Success.
+*                         1: Invalid value of (lng,lat).
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         1: Null celprm pointer passed.
+*                         2: Invalid projection parameters.
+*                         3: Invalid coordinate transformation parameters.
+*                         4: Ill-conditioned coordinate transformation
+*                            parameters.
+*                         6: One or more of the (lng,lat) coordinates were
+*                            invalid, as indicated by the stat vector.
+*
+*                       For returns > 1, a detailed error message is set in
+*                       celprm::err if enabled, see wcserr_enable().
+*
+*
+* celprm struct - Celestial transformation parameters
+* ---------------------------------------------------
+* The celprm struct contains information required to transform celestial
+* coordinates.  It consists of certain members that must be set by the user
+* ("given") and others that are set by the WCSLIB routines ("returned").  Some
+* of the latter are supplied for informational purposes and others are for
+* internal use only.
+*
+* Returned celprm struct members must not be modified by the user.
+*
+*   int flag
+*     (Given and returned) This flag must be set to zero whenever any of the
+*     following celprm struct members are set or changed:
+*
+*       - celprm::offset,
+*       - celprm::phi0,
+*       - celprm::theta0,
+*       - celprm::ref[4],
+*       - celprm::prj:
+*         - prjprm::code,
+*         - prjprm::r0,
+*         - prjprm::pv[],
+*         - prjprm::phi0,
+*         - prjprm::theta0.
+*
+*     This signals the initialization routine, celset(), to recompute the
+*     returned members of the celprm struct.  celset() will reset flag to
+*     indicate that this has been done.
+*
+*   int offset
+*     (Given) If true (non-zero), an offset will be applied to (x,y) to
+*     force (x,y) = (0,0) at the fiducial point, (phi_0,theta_0).
+*     Default is 0 (false).
+*
+*   double phi0
+*     (Given) The native longitude, phi_0 [deg], and ...
+*
+*   double theta0
+*     (Given) ... the native latitude, theta_0 [deg], of the fiducial point,
+*     i.e. the point whose celestial coordinates are given in
+*     celprm::ref[1:2].  If undefined (set to a magic value by prjini()) the
+*     initialization routine, celset(), will set this to a projection-specific
+*     default.
+*
+*   double ref[4]
+*     (Given) The first pair of values should be set to the celestial
+*     longitude and latitude of the fiducial point [deg] - typically right
+*     ascension and declination.  These are given by the CRVALia keywords in
+*     FITS.
+*
+*     (Given and returned) The second pair of values are the native longitude,
+*     phi_p [deg], and latitude, theta_p [deg], of the celestial pole (the
+*     latter is the same as the celestial latitude of the native pole,
+*     delta_p) and these are given by the FITS keywords LONPOLEa and LATPOLEa
+*     (or by PVi_2a and PVi_3a attached to the longitude axis which take
+*     precedence if defined).
+*
+*     LONPOLEa defaults to phi_0 (see above) if the celestial latitude of the
+*     fiducial point of the projection is greater than or equal to the native
+*     latitude, otherwise phi_0 + 180 [deg].  (This is the condition for the
+*     celestial latitude to increase in the same direction as the native
+*     latitude at the fiducial point.)  ref[2] may be set to UNDEFINED (from
+*     wcsmath.h) or 999.0 to indicate that the correct default should be
+*     substituted.
+*
+*     theta_p, the native latitude of the celestial pole (or equally the
+*     celestial latitude of the native pole, delta_p) is often determined
+*     uniquely by CRVALia and LONPOLEa in which case LATPOLEa is ignored.
+*     However, in some circumstances there are two valid solutions for theta_p
+*     and LATPOLEa is used to choose between them.  LATPOLEa is set in ref[3]
+*     and the solution closest to this value is used to reset ref[3].  It is
+*     therefore legitimate, for example, to set ref[3] to +90.0 to choose the
+*     more northerly solution - the default if the LATPOLEa keyword is omitted
+*     from the FITS header.  For the special case where the fiducial point of
+*     the projection is at native latitude zero, its celestial latitude is
+*     zero, and LONPOLEa = +/- 90.0 then the celestial latitude of the native
+*     pole is not determined by the first three reference values and LATPOLEa
+*     specifies it completely.
+*
+*     The returned value, celprm::latpreq, specifies how LATPOLEa was actually
+*     used.
+*
+*   struct prjprm prj
+*     (Given and returned) Projection parameters described in the prologue to
+*     prj.h.
+*
+*   double euler[5]
+*     (Returned) Euler angles and associated intermediaries derived from the
+*     coordinate reference values.  The first three values are the Z-, X-, and
+*     Z'-Euler angles [deg], and the remaining two are the cosine and sine of
+*     the X-Euler angle.
+*
+*   int latpreq
+*     (Returned) For informational purposes, this indicates how the LATPOLEa
+*     keyword was used
+*       - 0: Not required, theta_p (== delta_p) was determined uniquely by the
+*            CRVALia and LONPOLEa keywords.
+*       - 1: Required to select between two valid solutions of theta_p.
+*       - 2: theta_p was specified solely by LATPOLEa.
+*
+*   int isolat
+*     (Returned) True if the spherical rotation preserves the magnitude of the
+*     latitude, which occurs iff the axes of the native and celestial
+*     coordinates are coincident.  It signals an opportunity to cache
+*     intermediate calculations common to all elements in a vector
+*     computation.
+*
+*   struct wcserr *err
+*     (Returned) If enabled, when an error status is returned this struct
+*     contains detailed information about the error, see wcserr_enable().
+*
+*   void *padding
+*     (An unused variable inserted for alignment purposes only.)
+*
+* Global variable: const char *cel_errmsg[] - Status return messages
+* ------------------------------------------------------------------
+* Status messages to match the status value returned from each function.
+*
+*===========================================================================*/
+
+#ifndef WCSLIB_CEL
+#define WCSLIB_CEL
+
+#include "prj.h"
+#include "wcserr.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+extern const char *cel_errmsg[];
+
+enum cel_errmsg_enum {
+  CELERR_SUCCESS         = 0,	/* Success. */
+  CELERR_NULL_POINTER    = 1,	/* Null celprm pointer passed. */
+  CELERR_BAD_PARAM       = 2,	/* Invalid projection parameters. */
+  CELERR_BAD_COORD_TRANS = 3,	/* Invalid coordinate transformation
+				   parameters. */
+  CELERR_ILL_COORD_TRANS = 4,	/* Ill-conditioned coordinated transformation
+				   parameters. */
+  CELERR_BAD_PIX         = 5,	/* One or more of the (x,y) coordinates were
+				   invalid. */
+  CELERR_BAD_WORLD       = 6 	/* One or more of the (lng,lat) coordinates
+				   were invalid. */
+};
+
+struct celprm {
+  /* Initialization flag (see the prologue above).                          */
+  /*------------------------------------------------------------------------*/
+  int    flag;			/* Set to zero to force initialization.     */
+
+  /* Parameters to be provided (see the prologue above).                    */
+  /*------------------------------------------------------------------------*/
+  int    offset;		/* Force (x,y) = (0,0) at (phi_0,theta_0).  */
+  double phi0, theta0;		/* Native coordinates of fiducial point.    */
+  double ref[4];		/* Celestial coordinates of fiducial        */
+                                /* point and native coordinates of          */
+                                /* celestial pole.                          */
+
+  struct prjprm prj;		/* Projection parameters (see prj.h).       */
+
+  /* Information derived from the parameters supplied.                      */
+  /*------------------------------------------------------------------------*/
+  double euler[5];		/* Euler angles and functions thereof.      */
+  int    latpreq;		/* LATPOLEa requirement.                    */
+  int    isolat;		/* True if |latitude| is preserved.         */
+
+  /* Error handling                                                         */
+  /*------------------------------------------------------------------------*/
+  struct wcserr *err;
+
+  /* Private                                                                */
+  /*------------------------------------------------------------------------*/
+  void   *padding;		/* (Dummy inserted for alignment purposes.) */
+};
+
+/* Size of the celprm struct in int units, used by the Fortran wrappers. */
+#define CELLEN (sizeof(struct celprm)/sizeof(int))
+
+
+int celini(struct celprm *cel);
+
+int celfree(struct celprm *cel);
+
+int celprt(const struct celprm *cel);
+
+int celset(struct celprm *cel);
+
+int celx2s(struct celprm *cel, int nx, int ny, int sxy, int sll,
+           const double x[], const double y[],
+           double phi[], double theta[], double lng[], double lat[],
+           int stat[]);
+
+int cels2x(struct celprm *cel, int nlng, int nlat, int sll, int sxy,
+           const double lng[], const double lat[],
+           double phi[], double theta[], double x[], double y[],
+           int stat[]);
+
+
+/* Deprecated. */
+#define celini_errmsg cel_errmsg
+#define celprt_errmsg cel_errmsg
+#define celset_errmsg cel_errmsg
+#define celx2s_errmsg cel_errmsg
+#define cels2x_errmsg cel_errmsg
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* WCSLIB_CEL */
diff --git a/cextern/wcslib/C/fitshdr.h b/cextern/wcslib/C/fitshdr.h
new file mode 100644
index 0000000..555d987
--- /dev/null
+++ b/cextern/wcslib/C/fitshdr.h
@@ -0,0 +1,443 @@
+/*============================================================================
+
+  WCSLIB 4.16 - an implementation of the FITS WCS standard.
+  Copyright (C) 1995-2012, Mark Calabretta
+
+  This file is part of WCSLIB.
+
+  WCSLIB is free software: you can redistribute it and/or modify it under the
+  terms of the GNU Lesser General Public License as published by the Free
+  Software Foundation, either version 3 of the License, or (at your option)
+  any later version.
+
+  WCSLIB 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 Lesser General Public License for
+  more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with WCSLIB.  If not, see http://www.gnu.org/licenses.
+
+  Direct correspondence concerning WCSLIB to mark at calabretta.id.au
+
+  Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
+  http://www.atnf.csiro.au/people/Mark.Calabretta
+  $Id: fitshdr.h,v 4.16 2012/11/07 04:42:44 cal103 Exp $
+*=============================================================================
+*
+* The Flexible Image Transport System (FITS), a data format widely used in
+* astronomy for data interchange and archive, is described in
+*
+*   "Definition of The Flexible Image Transport System (FITS)",
+*   Hanisch, R.J., Farris, A., Greisen, E.W., et al. 2001, A&A, 376, 359
+*
+* which formalizes NOST 100-2.0, a document produced by the NASA/Science
+* Office of Standards and Technology, see http://fits.gsfc.nasa.gov.
+*
+* Refer to the README file provided with WCSLIB for an overview of the
+* library.
+*
+*
+* Summary of the fitshdr routines
+* -------------------------------
+* fitshdr() is a generic FITS header parser provided to handle keyrecords that
+* are ignored by the WCS header parsers, wcspih() and wcsbth().  Typically the
+* latter may be set to remove WCS keyrecords from a header leaving fitshdr()
+* to handle the remainder.
+*
+*
+* fitshdr() - FITS header parser routine
+* --------------------------------------
+* fitshdr() parses a character array containing a FITS header, extracting
+* all keywords and their values into an array of fitskey structs.
+*
+* Given:
+*   header    const char []
+*                       Character array containing the (entire) FITS header,
+*                       for example, as might be obtained conveniently via the
+*                       CFITSIO routine fits_hdr2str().
+*
+*                       Each header "keyrecord" (formerly "card image")
+*                       consists of exactly 80 7-bit ASCII printing characters
+*                       in the range 0x20 to 0x7e (which excludes NUL, BS,
+*                       TAB, LF, FF and CR) especially noting that the
+*                       keyrecords are NOT null-terminated.
+*
+*   nkeyrec   int       Number of keyrecords in header[].
+*
+*   nkeyids   int       Number of entries in keyids[].
+*
+* Given and returned:
+*   keyids    struct fitskeyid []
+*                       While all keywords are extracted from the header,
+*                       keyids[] provides a convienient way of indexing them.
+*                       The fitskeyid struct contains three members;
+*                       fitskeyid::name must be set by the user while
+*                       fitskeyid::count and fitskeyid::name are returned by
+*                       fitshdr().  All matched keywords will have their
+*                       fitskey::keyno member negated.
+*
+* Returned:
+*   nreject   int*      Number of header keyrecords rejected for syntax
+*                       errors.
+*
+*   keys      struct fitskey**
+*                       Pointer to an array of nkeyrec fitskey structs
+*                       containing all keywords and keyvalues extracted from
+*                       the header.
+*
+*                       Memory for the array is allocated by fitshdr() and
+*                       this must be freed by the user by invoking free() on
+*                       the array.
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         1: Null fitskey pointer passed.
+*                         2: Memory allocation failed.
+*                         3: Fatal error returned by Flex parser.
+*
+* Notes:
+*   1: Keyword parsing is done in accordance with the syntax defined by
+*      NOST 100-2.0, noting the following points in particular:
+*
+*      a: Sect. 5.1.2.1 specifies that keywords be left-justified in columns
+*         1-8, blank-filled with no embedded spaces, composed only of the
+*         ASCII characters ABCDEFGHJKLMNOPQRSTUVWXYZ0123456789-_
+*
+*         fitshdr() accepts any characters in columns 1-8 but flags keywords
+*         that do not conform to standard syntax.
+*
+*      b: Sect. 5.1.2.2 defines the "value indicator" as the characters "= "
+*         occurring in columns 9 and 10.  If these are absent then the
+*         keyword has no value and columns 9-80 may contain any ASCII text
+*         (but see note 2 for CONTINUE keyrecords).  This is copied to the
+*         comment member of the fitskey struct.
+*
+*      c: Sect. 5.1.2.3 states that a keyword may have a null (undefined)
+*         value if the value/comment field, columns 11-80, consists entirely
+*         of spaces, possibly followed by a comment.
+*
+*      d: Sect. 5.1.1 states that trailing blanks in a string keyvalue are
+*         not significant and the parser always removes them.  A string
+*         containing nothing but blanks will be replaced with a single
+*         blank.
+*
+*         Sect. 5.2.1 also states that a quote character (') in a string
+*         value is to be represented by two successive quote characters and
+*         the parser removes the repeated quote.
+*
+*      e: The parser recognizes free-format character (NOST 100-2.0,
+*         Sect. 5.2.1), integer (Sect. 5.2.3), and floating-point values
+*         (Sect. 5.2.4) for all keywords.
+*
+*      f: Sect. 5.2.3 offers no comment on the size of an integer keyvalue
+*         except indirectly in limiting it to 70 digits.  The parser will
+*         translates an integer keyvalue to a 32-bit signed integer if it
+*         lies in the range -2147483648 to +2147483647, otherwise it
+*         interprets it as a 64-bit signed integer if possible, or else a
+*         "very long" integer (see fitskey::type).
+*
+*      g: END not followed by 77 blanks is not considered to be a legitimate
+*         end keyrecord.
+*
+*   2: The parser supports a generalization of the OGIP Long String Keyvalue
+*      Convention (v1.0) whereby strings may be continued onto successive
+*      header keyrecords.  A keyrecord contains a segment of a continued
+*      string if and only if
+*
+*      a: it contains the pseudo-keyword CONTINUE,
+*
+*      b: columns 9 and 10 are both blank,
+*
+*      c: columns 11 to 80 contain what would be considered a valid string
+*         keyvalue, including optional keycomment, if column 9 had contained
+*         '=',
+*
+*      d: the previous keyrecord contained either a valid string keyvalue or
+*         a valid CONTINUE keyrecord.
+*
+*      If any of these conditions is violated, the keyrecord is considered in
+*      isolation.
+*
+*      Syntax errors in keycomments in a continued string are treated more
+*      permissively than usual; the '/' delimiter may be omitted provided that
+*      parsing of the string keyvalue is not compromised.  However, the
+*      FITSHDR_COMMENT status bit will be set for the keyrecord (see
+*      fitskey::status).
+*
+*      As for normal strings, trailing blanks in a continued string are not
+*      significant.
+*
+*      In the OGIP convention "the '&' character is used as the last non-blank
+*      character of the string to indicate that the string is (probably)
+*      continued on the following keyword".  This additional syntax is not
+*      required by fitshdr(), but if '&' does occur as the last non-blank
+*      character of a continued string keyvalue then it will be removed, along
+*      with any trailing blanks.  However, blanks that occur before the '&'
+*      will be preserved.
+*
+*
+* fitskeyid struct - Keyword indexing
+* -----------------------------------
+* fitshdr() uses the fitskeyid struct to return indexing information for
+* specified keywords.  The struct contains three members, the first of which,
+* fitskeyid::name, must be set by the user with the remainder returned by
+* fitshdr().
+*
+*   char name[12]:
+*     (Given) Name of the required keyword.  This is to be set by the user;
+*     the '.' character may be used for wildcarding.  Trailing blanks will be
+*     replaced with nulls.
+*
+*   int count:
+*     (Returned) The number of matches found for the keyword.
+*
+*   int idx[2]:
+*     (Returned) Indices into keys[], the array of fitskey structs returned by
+*     fitshdr().  Note that these are 0-relative array indices, not keyrecord
+*     numbers.
+*
+*     If the keyword is found in the header the first index will be set to the
+*     array index of its first occurrence, otherwise it will be set to -1.
+*
+*     If multiples of the keyword are found, the second index will be set to
+*     the array index of its last occurrence, otherwise it will be set to -1.
+*
+*
+* fitskey struct - Keyword/value information
+* ------------------------------------------
+* fitshdr() returns an array of fitskey structs, each of which contains the
+* result of parsing one FITS header keyrecord.  All members of the fitskey
+* struct are returned by fitshdr(), none are given by the user.
+*
+*   int keyno
+*     (Returned) Keyrecord number (1-relative) in the array passed as input to
+*     fitshdr().  This will be negated if the keyword matched any specified in
+*     the keyids[] index.
+*
+*   int keyid
+*     (Returned) Index into the first entry in keyids[] with which the
+*     keyrecord matches, else -1.
+*
+*   int status
+*     (Returned) Status flag bit-vector for the header keyrecord employing the
+*     following bit masks defined as preprocessor macros:
+*
+*       - FITSHDR_KEYWORD:    Illegal keyword syntax.
+*       - FITSHDR_KEYVALUE:   Illegal keyvalue syntax.
+*       - FITSHDR_COMMENT:    Illegal keycomment syntax.
+*       - FITSHDR_KEYREC:     Illegal keyrecord, e.g. an END keyrecord with
+*                             trailing text.
+*       - FITSHDR_TRAILER:    Keyrecord following a valid END keyrecord.
+*
+*     The header keyrecord is syntactically correct if no bits are set.
+*
+*   char keyword[12]
+*     (Returned) Keyword name, null-filled for keywords of less than eight
+*     characters (trailing blanks replaced by nulls).
+*
+*     Use
+*
+=       sprintf(dst, "%.8s", keyword)
+*
+*     to copy it to a character array with null-termination, or
+*
+=       sprintf(dst, "%8.8s", keyword)
+*
+*     to blank-fill to eight characters followed by null-termination.
+*
+*   int type
+*     (Returned) Keyvalue data type:
+*       - 0: No keyvalue.
+*       - 1: Logical, represented as int.
+*       - 2: 32-bit signed integer.
+*       - 3: 64-bit signed integer (see below).
+*       - 4: Very long integer (see below).
+*       - 5: Floating point (stored as double).
+*       - 6: Integer complex (stored as double[2]).
+*       - 7: Floating point complex (stored as double[2]).
+*       - 8: String.
+*       - 8+10*n: Continued string (described below and in fitshdr() note 2).
+*
+*     A negative type indicates that a syntax error was encountered when
+*     attempting to parse a keyvalue of the particular type.
+*
+*     Comments on particular data types:
+*       - 64-bit signed integers lie in the range
+*
+=           (-9223372036854775808 <= int64 <  -2147483648) ||
+=                    (+2147483647 <  int64 <= +9223372036854775807)
+*
+*         A native 64-bit data type may be defined via preprocessor macro
+*         WCSLIB_INT64 defined in wcsconfig.h, e.g. as 'long long int'; this
+*         will be typedef'd to 'int64' here.  If WCSLIB_INT64 is not set, then
+*         int64 is typedef'd to int[3] instead and fitskey::keyvalue is to be
+*         computed as
+*
+=           ((keyvalue.k[2]) * 1000000000 +
+=             keyvalue.k[1]) * 1000000000 +
+=             keyvalue.k[0]
+*
+*         and may reported via
+*
+=            if (keyvalue.k[2]) {
+=              printf("%d%09d%09d", keyvalue.k[2], abs(keyvalue.k[1]),
+=                                   abs(keyvalue.k[0]));
+=            } else {
+=              printf("%d%09d", keyvalue.k[1], abs(keyvalue.k[0]));
+=            }
+*
+*         where keyvalue.k[0] and keyvalue.k[1] range from -999999999 to
+*         +999999999.
+*
+*       - Very long integers, up to 70 decimal digits in length, are encoded
+*         in keyvalue.l as an array of int[8], each of which stores 9 decimal
+*         digits.  fitskey::keyvalue is to be computed as
+*
+=           (((((((keyvalue.l[7]) * 1000000000 +
+=                  keyvalue.l[6]) * 1000000000 +
+=                  keyvalue.l[5]) * 1000000000 +
+=                  keyvalue.l[4]) * 1000000000 +
+=                  keyvalue.l[3]) * 1000000000 +
+=                  keyvalue.l[2]) * 1000000000 +
+=                  keyvalue.l[1]) * 1000000000 +
+=                  keyvalue.l[0]
+*
+*       - Continued strings are not reconstructed, they remain split over
+*         successive fitskey structs in the keys[] array returned by
+*         fitshdr().  fitskey::keyvalue data type, 8 + 10n, indicates the
+*         segment number, n, in the continuation.
+*
+*   int padding
+*     (An unused variable inserted for alignment purposes only.)
+*
+*   union keyvalue
+*     (Returned) A union comprised of
+*
+*       - fitskey::i,
+*       - fitskey::k,
+*       - fitskey::l,
+*       - fitskey::f,
+*       - fitskey::c,
+*       - fitskey::s,
+*
+*     used by the fitskey struct to contain the value associated with a
+*     keyword.
+*
+*   int i
+*     (Returned) Logical (fitskey::type == 1) and 32-bit signed integer
+*     (fitskey::type == 2) data types in the fitskey::keyvalue union.
+*
+*   int64 k
+*     (Returned) 64-bit signed integer (fitskey::type == 3) data type in the
+*     fitskey::keyvalue union.
+*
+*   int l[8]
+*     (Returned) Very long integer (fitskey::type == 4) data type in the
+*     fitskey::keyvalue union.
+*
+*   double f
+*     (Returned) Floating point (fitskey::type == 5) data type in the
+*     fitskey::keyvalue union.
+*
+*   double c[2]
+*     (Returned) Integer and floating point complex (fitskey::type == 6 || 7)
+*     data types in the fitskey::keyvalue union.
+*
+*   char s[72]
+*     (Returned) Null-terminated string (fitskey::type == 8) data type in the
+*     fitskey::keyvalue union.
+*
+*   int ulen
+*     (Returned) Where a keycomment contains a units string in the standard
+*     form, e.g. [m/s], the ulen member indicates its length, inclusive of
+*     square brackets.  Otherwise ulen is zero.
+*
+*   char comment[84]
+*     (Returned) Keycomment, i.e. comment associated with the keyword or, for
+*     keyrecords rejected because of syntax errors, the compete keyrecord
+*     itself with null-termination.
+*
+*     Comments are null-terminated with trailing spaces removed.  Leading
+*     spaces are also removed from keycomments (i.e. those immediately
+*     following the '/' character), but not from COMMENT or HISTORY keyrecords
+*     or keyrecords without a value indicator ("= " in columns 9-80).
+*
+*
+* Global variable: const char *fitshdr_errmsg[] - Status return messages
+* ----------------------------------------------------------------------
+* Error messages to match the status value returned from each function.
+*
+*===========================================================================*/
+
+#ifndef WCSLIB_FITSHDR
+#define WCSLIB_FITSHDR
+
+#include "wcsconfig.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define FITSHDR_KEYWORD  0x01
+#define FITSHDR_KEYVALUE 0x02
+#define FITSHDR_COMMENT  0x04
+#define FITSHDR_KEYREC   0x08
+#define FITSHDR_CARD     0x08	/* Alias for backwards compatibility. */
+#define FITSHDR_TRAILER  0x10
+
+
+extern const char *fitshdr_errmsg[];
+
+#ifdef WCSLIB_INT64
+  typedef WCSLIB_INT64 int64;
+#else
+  typedef int int64[3];
+#endif
+
+
+/* Struct used for indexing the keywords. */
+struct fitskeyid {
+  char name[12];		/* Keyword name, null-terminated.           */
+  int  count;			/* Number of occurrences of keyword.        */
+  int  idx[2];			/* Indices into fitskey array.              */
+};
+
+/* Size of the fitskeyid struct in int units, used by the Fortran wrappers. */
+#define KEYIDLEN (sizeof(struct fitskeyid)/sizeof(int))
+
+
+/* Struct used for storing FITS keywords. */
+struct fitskey {
+  int  keyno;			/* Header keyrecord sequence number (1-rel).*/
+  int  keyid;			/* Index into fitskeyid[].                  */
+  int  status;			/* Header keyrecord status bit flags.       */
+  char keyword[12];		/* Keyword name, null-filled.               */
+  int  type;			/* Keyvalue type (see above).               */
+  int  padding;			/* (Dummy inserted for alignment purposes.) */
+  union {
+    int    i;			/* 32-bit integer and logical values.       */
+    int64  k;			/* 64-bit integer values.                   */
+    int    l[8];		/* Very long signed integer values.         */
+    double f;			/* Floating point values.                   */
+    double c[2];		/* Complex values.                          */
+    char   s[72];		/* String values, null-terminated.          */
+  } keyvalue;			/* Keyvalue.                                */
+  int  ulen;			/* Length of units string.                  */
+  char comment[84];		/* Comment (or keyrecord), null-terminated. */
+};
+
+/* Size of the fitskey struct in int units, used by the Fortran wrappers. */
+#define KEYLEN (sizeof(struct fitskey)/sizeof(int))
+
+
+int fitshdr(const char header[], int nkeyrec, int nkeyids,
+            struct fitskeyid keyids[], int *nreject, struct fitskey **keys);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* WCSLIB_FITSHDR */
diff --git a/cextern/wcslib/C/fitshdr.l b/cextern/wcslib/C/fitshdr.l
new file mode 100644
index 0000000..a763282
--- /dev/null
+++ b/cextern/wcslib/C/fitshdr.l
@@ -0,0 +1,570 @@
+/*============================================================================
+
+  WCSLIB 4.16 - an implementation of the FITS WCS standard.
+  Copyright (C) 1995-2012, Mark Calabretta
+
+  This file is part of WCSLIB.
+
+  WCSLIB is free software: you can redistribute it and/or modify it under the
+  terms of the GNU Lesser General Public License as published by the Free
+  Software Foundation, either version 3 of the License, or (at your option)
+  any later version.
+
+  WCSLIB 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 Lesser General Public License for
+  more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with WCSLIB.  If not, see http://www.gnu.org/licenses.
+
+  Direct correspondence concerning WCSLIB to mark at calabretta.id.au
+
+  Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
+  http://www.atnf.csiro.au/people/Mark.Calabretta
+  $Id: fitshdr.l,v 4.16 2012/11/07 04:42:44 cal103 Exp $
+*=============================================================================
+*
+* fitshdr.l is a Flex description file containing a lexical scanner
+* definition for extracting keywords and keyvalues from a FITS header.
+*
+* It requires Flex v2.5.4 or later.
+*
+* Refer to fitshdr.h for a description of the user interface and operating
+* notes.
+*
+*===========================================================================*/
+
+/* Options. */
+%option full
+%option never-interactive
+%option nounput
+%option noyywrap
+%option outfile="fitshdr.c"
+%option prefix="fitshdr"
+
+/* Keywords. */
+KEYCHR	[-_A-Z0-9]
+KW1	{KEYCHR}{1}" "{7}
+KW2	{KEYCHR}{2}" "{6}
+KW3	{KEYCHR}{3}" "{5}
+KW4	{KEYCHR}{4}" "{4}
+KW5	{KEYCHR}{5}" "{3}
+KW6	{KEYCHR}{6}" "{2}
+KW7	{KEYCHR}{7}" "{1}
+KW8	{KEYCHR}{8}
+KEYWORD	({KW1}|{KW2}|{KW3}|{KW4}|{KW5}|{KW6}|{KW7}|{KW8})
+
+/* Keyvalue data types. */
+LOGICAL	[TF]
+INT32	[+-]?0*[0-9]{1,9}
+INT64	[+-]?0*[0-9]{10,18}
+INTVL	[+-]?0*[0-9]{19,}
+INTEGER	[+-]?[0-9]+
+FLOAT	[+-]?([0-9]+\.?[0-9]*|\.[0-9]+)([eE][+-]?[0-9]+)?
+ICOMPLX	\(" "*{INTEGER}" "*," "*{INTEGER}" "*\)
+FCOMPLX	\(" "*{FLOAT}" "*," "*{FLOAT}" "*\)
+STRING	'([^']|'')*'
+
+/* Characters forming standard unit strings (jwBIQX are not used). */
+UNITSTR \[[-+*/^(). 0-9a-zA-Z]+\]
+
+/* Exclusive start states. */
+%x VALUE INLINE UNITS COMMENT ERROR FLUSH
+
+%{
+#include <math.h>
+#include <limits.h>
+#include <setjmp.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "fitshdr.h"
+#include "wcsutil.h"
+
+#define YY_DECL int fitshdr(const char header[], int nkeyrec, int nkeyids, \
+                            struct fitskeyid keyids[], int *nreject, \
+                            struct fitskey **keys)
+
+#define YY_INPUT(inbuff, count, bufsize) \
+	{ \
+	  if (fitshdr_nkeyrec) { \
+	    strncpy(inbuff, fitshdr_hdr, 80); \
+	    inbuff[80] = '\n'; \
+	    fitshdr_hdr += 80; \
+	    fitshdr_nkeyrec--; \
+	    count = 81; \
+	  } else { \
+	    count = YY_NULL; \
+	  } \
+	}
+
+/* These global variables are required by YY_INPUT. */
+const char *fitshdr_hdr;
+int  fitshdr_nkeyrec;
+
+/* Used in preempting the call to exit() by yy_fatal_error(). */
+jmp_buf fitshdr_abort_jmp_env;
+#define exit(status) longjmp(fitshdr_abort_jmp_env, status)
+
+/* Map status return value to message. */
+const char *fitshdr_errmsg[] = {
+   "Success",
+   "Null fitskey pointer-pointer passed",
+   "Memory allocation failed",
+   "Fatal error returned by Flex parser"};
+
+%}
+
+%%
+	char *cptr, ctmp[72];
+	int  blank, continuation, end, j, k, keyno;
+	double dtmp;
+	struct fitskey *kptr;
+	struct fitskeyid *iptr;
+	void nullfill(char cptr[], int len);
+	int  yylex_destroy(void);
+	
+	fitshdr_hdr = header;
+	fitshdr_nkeyrec = nkeyrec;
+	
+	*nreject = 0;
+	keyno = 0;
+	
+	if (keys == 0x0) {
+	  return 1;
+	}
+	
+	/* Allocate memory for the required number of fitskey structs. */
+	/* Recall that calloc() initializes allocated memory to zero.  */
+	if (!(kptr = *keys = calloc(nkeyrec, sizeof(struct fitskey)))) {
+	  return 2;
+	}
+	
+	/* Initialize keyids[]. */
+	iptr = keyids;
+	for (j = 0; j < nkeyids; j++, iptr++) {
+	  iptr->count  = 0;
+	  iptr->idx[0] = -1;
+	  iptr->idx[1] = -1;
+	}
+	
+	blank = 0;
+	continuation = 0;
+	end = 0;
+	
+	/* Return here via longjmp() invoked by yy_fatal_error(). */
+	if (setjmp(fitshdr_abort_jmp_env)) {
+	  return 3;
+	}
+	
+	BEGIN(INITIAL);
+
+^" "{80} {
+	  /* A completely blank keyrecord. */
+	  strncpy(kptr->keyword, yytext, 8);
+	  yyless(0);
+	  blank = 1;
+	  BEGIN(COMMENT);
+	}
+
+^(COMMENT|HISTORY|" "{8}) {
+	  strncpy(kptr->keyword, yytext, 8);
+	  BEGIN(COMMENT);
+	}
+
+^END" "{77} {
+	  strncpy(kptr->keyword, yytext, 8);
+	  end = 1;
+	  BEGIN(FLUSH);
+	}
+
+^END" "{5}=" "+ {
+	  /* Illegal END keyrecord. */
+	  strncpy(kptr->keyword, yytext, 8);
+	  kptr->status |= FITSHDR_KEYREC;
+	  BEGIN(VALUE);
+	}
+
+^END" "{5} {
+	  /* Illegal END keyrecord. */
+	  strncpy(kptr->keyword, yytext, 8);
+	  kptr->status |= FITSHDR_KEYREC;
+	  BEGIN(COMMENT);
+	}
+
+^{KEYWORD}=" "+ {
+	  strncpy(kptr->keyword, yytext, 8);
+	  BEGIN(VALUE);
+	}
+
+^CONTINUE"  "+{STRING} {
+	  /* Continued string keyvalue. */
+	  strncpy(kptr->keyword, yytext, 8);
+	
+	  if (keyno > 0 && (kptr-1)->type%10 == 8) {
+	    /* Put back the string keyvalue. */
+	    for (k = 10; yytext[k] != '\''; k++);
+	    yyless(k);
+	    continuation = 1;
+	    BEGIN(VALUE);
+	
+	  } else {
+	    /* Not a valid continuation. */
+	    yyless(8);
+	    BEGIN(COMMENT);
+	  }
+	}
+
+^{KEYWORD} {
+	  /* Keyword without value. */
+	  strncpy(kptr->keyword, yytext, 8);
+	  BEGIN(COMMENT);
+	}
+
+^.{8}=" "+ {
+	  /* Illegal keyword, carry on regardless. */
+	  strncpy(kptr->keyword, yytext, 8);
+	  kptr->status |= FITSHDR_KEYWORD;
+	  BEGIN(VALUE);
+	}
+
+^.{8}	{
+	  /* Illegal keyword, carry on regardless. */
+	  strncpy(kptr->keyword, yytext, 8);
+	  kptr->status |= FITSHDR_KEYWORD;
+	  BEGIN(COMMENT);
+	}
+
+<VALUE>" "*/\/ {
+	  /* Null keyvalue. */
+	  BEGIN(INLINE);
+	}
+
+<VALUE>{LOGICAL} {
+	  /* Logical keyvalue. */
+	  kptr->type = 1;
+	  kptr->keyvalue.i = (*yytext == 'T');
+	  BEGIN(INLINE);
+	}
+
+<VALUE>{INT32} {
+	  /* 32-bit signed integer keyvalue. */
+	  kptr->type = 2;
+	  if (sscanf(yytext, "%d", &(kptr->keyvalue.i)) < 1) {
+	    kptr->status |= FITSHDR_KEYVALUE;
+	    BEGIN(ERROR);
+	  }
+	
+	  BEGIN(INLINE);
+	}
+
+<VALUE>{INT64} {
+	  /* 64-bit signed integer keyvalue (up to 18 digits). */
+	  if (wcsutil_str2double(yytext, "%lf", &dtmp)) {
+	    kptr->status |= FITSHDR_KEYVALUE;
+	    BEGIN(ERROR);
+	
+	  } else if (INT_MIN <= dtmp && dtmp <= INT_MAX) {
+	    /* Can be accomodated as a 32-bit signed integer. */
+	    kptr->type = 2;
+	    if (sscanf(yytext, "%d", &(kptr->keyvalue.i)) < 1) {
+	      kptr->status |= FITSHDR_KEYVALUE;
+	      BEGIN(ERROR);
+	    }
+	
+	  } else {
+	    /* 64-bit signed integer. */
+	    kptr->type = 3;
+	    #ifdef WCSLIB_INT64
+	      /* Native 64-bit integer is available. */
+	      if (sscanf(yytext, "%lld", &(kptr->keyvalue.k)) < 1) {
+	        kptr->status |= FITSHDR_KEYVALUE;
+	        BEGIN(ERROR);
+	      }
+	    #else
+	      /* 64-bit integer (up to 18 digits) implemented as int[3]. */
+	      kptr->keyvalue.k[2] = 0;
+	
+	      sprintf(ctmp, "%%%dd%%9d", yyleng-9);
+	      if (sscanf(yytext, ctmp, kptr->keyvalue.k+1,
+	                 kptr->keyvalue.k) < 1) {
+	        kptr->status |= FITSHDR_KEYVALUE;
+	        BEGIN(ERROR);
+	      } else if (*yytext == '-') {
+	        kptr->keyvalue.k[0] *= -1;
+	      }
+	    #endif
+	  }
+	
+	  BEGIN(INLINE);
+	}
+
+<VALUE>{INTVL} {
+	  /* Very long integer keyvalue (and 19-digit int64). */
+	  kptr->type = 4;
+	  strcpy(ctmp, yytext);
+	  k = yyleng;
+	  for (j = 0; j < 8; j++) {
+	    /* Read it backwards. */
+	    k -= 9;
+	    if (k < 0) k = 0;
+	    if (sscanf(ctmp+k, "%d", kptr->keyvalue.l+j) < 1) {
+	      kptr->status |= FITSHDR_KEYVALUE;
+	      BEGIN(ERROR);
+	    }
+	    if (*yytext == '-') {
+	      kptr->keyvalue.l[j] = -abs(kptr->keyvalue.l[j]);
+	    }
+	
+	    if (k == 0) break;
+	    ctmp[k] = '\0';
+	  }
+	
+	  /* Can it be accomodated as a 64-bit signed integer? */
+	  if (j == 2 && abs(kptr->keyvalue.l[2]) <=  9 &&
+	                abs(kptr->keyvalue.l[1]) <=  223372036 &&
+	                    kptr->keyvalue.l[0]  <=  854775807 &&
+	                    kptr->keyvalue.l[0]  >= -854775808) {
+	    kptr->type = 3;
+	
+	    #ifdef WCSLIB_INT64
+	      /* Native 64-bit integer is available. */
+	      kptr->keyvalue.l[2] = 0;
+	      if (sscanf(yytext, "%lld", &(kptr->keyvalue.k)) < 1) {
+	        kptr->status |= FITSHDR_KEYVALUE;
+	        BEGIN(ERROR);
+	      }
+	    #endif
+	  }
+	
+	  BEGIN(INLINE);
+	}
+
+<VALUE>{FLOAT} {
+	  /* Float keyvalue. */
+	  kptr->type = 5;
+	  if (wcsutil_str2double(yytext, "%lf", &(kptr->keyvalue.f))) {
+	    kptr->status |= FITSHDR_KEYVALUE;
+	    BEGIN(ERROR);
+	  }
+	
+	  BEGIN(INLINE);
+	}
+
+<VALUE>{ICOMPLX} {
+	  /* Integer complex keyvalue. */
+	  kptr->type = 6;
+	  if (sscanf(yytext, "(%lf,%lf)", kptr->keyvalue.c,
+	      kptr->keyvalue.c+1) < 2) {
+	    kptr->status |= FITSHDR_KEYVALUE;
+	    BEGIN(ERROR);
+	  }
+	
+	  BEGIN(INLINE);
+	}
+
+<VALUE>{FCOMPLX} {
+	  /* Floating point complex keyvalue. */
+	  kptr->type = 7;
+	
+	  for (cptr = ctmp, k = 1; yytext[k] != ','; cptr++, k++) {
+	    *cptr = yytext[k];
+	  }
+	  *cptr = '\0';
+	
+	  if (wcsutil_str2double(ctmp, "%lf", kptr->keyvalue.c)) {
+	    kptr->status |= FITSHDR_KEYVALUE;
+	    BEGIN(ERROR);
+	  }
+	
+	  for (cptr = ctmp, k++; yytext[k] != ')'; cptr++, k++) {
+	    *cptr = yytext[k];
+	  }
+	  *cptr = '\0';
+	
+	  if (wcsutil_str2double(ctmp, "%lf", kptr->keyvalue.c+1)) {
+	    kptr->status |= FITSHDR_KEYVALUE;
+	    BEGIN(ERROR);
+	  }
+	
+	  BEGIN(INLINE);
+	}
+
+<VALUE>{STRING} {
+	  /* String keyvalue. */
+	  kptr->type = 8;
+	  cptr = kptr->keyvalue.s;
+	  strcpy(cptr, yytext+1);
+	
+	  /* Squeeze out repeated quotes. */
+	  k = 0;
+	  for (j = 0; j < 72; j++) {
+	    if (k < j) {
+	      cptr[k] = cptr[j];
+	    }
+	
+	    if (cptr[j] == '\0') {
+	      if (k) cptr[k-1] = '\0';
+	      break;
+	    } else if (cptr[j] == '\'' && cptr[j+1] == '\'') {
+	      j++;
+	    }
+	
+	    k++;
+	  }
+	
+	  if (*cptr) {
+	    /* Retain the initial blank in all-blank strings. */
+	    nullfill(cptr+1, 71);
+	  } else {
+	    nullfill(cptr, 72);
+	  }
+	
+	  BEGIN(INLINE);
+	}
+
+<VALUE>. {
+	  kptr->status |= FITSHDR_KEYVALUE;
+	  BEGIN(ERROR);
+	}
+
+<INLINE>" "*$ {
+	  BEGIN(FLUSH);
+	}
+
+<INLINE>" "*\/" "*$ {
+	  BEGIN(FLUSH);
+	}
+
+<INLINE>" "*\/" "* {
+	  BEGIN(UNITS);
+	}
+
+<INLINE>" " {
+	  kptr->status |= FITSHDR_COMMENT;
+	  BEGIN(ERROR);
+	}
+
+<INLINE>. {
+	  /* Keyvalue parsing must now also be suspect. */
+	  kptr->status |= FITSHDR_COMMENT;
+	  kptr->type = 0;
+	  BEGIN(ERROR);
+	}
+
+<UNITS>{UNITSTR} {
+	  kptr->ulen = yyleng;
+	  yymore();
+	  BEGIN(COMMENT);
+	}
+
+<UNITS>. {
+	  yymore();
+	  BEGIN(COMMENT);
+	}
+
+<COMMENT>.* {
+	  strcpy(kptr->comment, yytext);
+	  nullfill(kptr->comment, 84);
+	  BEGIN(FLUSH);
+	}
+
+<ERROR>.* {
+	  if (!continuation) kptr->type = -abs(kptr->type);
+	
+	  sprintf(kptr->comment, "%.80s", fitshdr_hdr-80);
+	  kptr->comment[80] = '\0';
+	  nullfill(kptr->comment+80, 4);
+	
+	  BEGIN(FLUSH);
+	}
+
+<FLUSH>.*\n {
+	  /* Discard the rest of the input line. */
+	  kptr->keyno = ++keyno;
+	
+	  /* Null-fill the keyword. */
+	  kptr->keyword[8] = '\0';
+	  nullfill(kptr->keyword, 12);
+	
+	  /* Do indexing. */
+	  iptr = keyids;
+	  kptr->keyid = -1;
+	  for (j = 0; j < nkeyids; j++, iptr++) {
+	    cptr = iptr->name;
+	    cptr[8] = '\0';
+	    nullfill(cptr, 12);
+	    for (k = 0; k < 8; k++, cptr++) {
+	      if (*cptr != '.' && *cptr != kptr->keyword[k]) break;
+	    }
+	
+	    if (k == 8) {
+	      /* Found a match. */
+	      iptr->count++;
+	      if (iptr->idx[0] == -1) {
+	        iptr->idx[0] = keyno-1;
+	      } else {
+	        iptr->idx[1] = keyno-1;
+	      }
+	
+	      kptr->keyno = -abs(kptr->keyno);
+	      if (kptr->keyid < 0) kptr->keyid = j;
+	    }
+	  }
+	
+	  /* Deal with continued strings. */
+	  if (continuation) {
+	    /* Tidy up the previous string keyvalue. */
+	    if ((kptr-1)->type == 8) (kptr-1)->type += 10;
+	    cptr = (kptr-1)->keyvalue.s;
+	    if (cptr[strlen(cptr)-1] == '&') cptr[strlen(cptr)-1] = '\0';
+	
+	    kptr->type = (kptr-1)->type + 10;
+	  }
+	
+	  /* Check for keyrecords following the END keyrecord. */
+	  if (end && (end++ > 1) && !blank) {
+	    kptr->status |= FITSHDR_TRAILER;
+	  }
+	  if (kptr->status) (*nreject)++;
+	
+	  kptr++;
+	  blank = 0;
+	  continuation = 0;
+	
+	  BEGIN(INITIAL);
+	}
+
+<<EOF>>	{
+	  /* End-of-input. */
+	  yylex_destroy();
+	  return 0;
+	}
+
+%%
+
+/*--------------------------------------------------------------------------*/
+
+void nullfill(char cptr[], int len)
+
+{
+  int j, k;
+
+  /* Null-fill the string. */
+  for (j = 0; j < len; j++) {
+    if (cptr[j] == '\0') {
+      for (k = j+1; k < len; k++) {
+        cptr[k] = '\0';
+      }
+      break;
+    }
+  }
+
+  for (k = j-1; k >= 0; k--) {
+    if (cptr[k] != ' ') break;
+    cptr[k] = '\0';
+  }
+
+  return;
+}
diff --git a/astropy/wcs/src/wcslib/C/flexed/README b/cextern/wcslib/C/flexed/README
similarity index 100%
rename from astropy/wcs/src/wcslib/C/flexed/README
rename to cextern/wcslib/C/flexed/README
diff --git a/cextern/wcslib/C/flexed/fitshdr.c b/cextern/wcslib/C/flexed/fitshdr.c
new file mode 100644
index 0000000..f60f93c
--- /dev/null
+++ b/cextern/wcslib/C/flexed/fitshdr.c
@@ -0,0 +1,11947 @@
+#line 2 "fitshdr.c"
+
+#line 4 "fitshdr.c"
+
+#define  YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define yy_create_buffer fitshdr_create_buffer
+#define yy_delete_buffer fitshdr_delete_buffer
+#define yy_flex_debug fitshdr_flex_debug
+#define yy_init_buffer fitshdr_init_buffer
+#define yy_flush_buffer fitshdr_flush_buffer
+#define yy_load_buffer_state fitshdr_load_buffer_state
+#define yy_switch_to_buffer fitshdr_switch_to_buffer
+#define yyin fitshdrin
+#define yyleng fitshdrleng
+#define yylex fitshdrlex
+#define yylineno fitshdrlineno
+#define yyout fitshdrout
+#define yyrestart fitshdrrestart
+#define yytext fitshdrtext
+#define yywrap fitshdrwrap
+#define yyalloc fitshdralloc
+#define yyrealloc fitshdrrealloc
+#define yyfree fitshdrfree
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+#define YY_FLEX_SUBMINOR_VERSION 35
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+/* First, we deal with  platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. 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 <inttypes.h>
+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;
+
+/* 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 /* ! C99 */
+
+#endif /* ! FLEXINT_H */
+
+#ifdef __cplusplus
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else	/* ! __cplusplus */
+
+/* C99 requires __STDC__ to be defined as 1. */
+#if defined (__STDC__)
+
+#define YY_USE_CONST
+
+#endif	/* defined (__STDC__) */
+#endif	/* ! __cplusplus */
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_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 YY_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 (yy_start) = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state.  The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START (((yy_start) - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE fitshdrrestart(fitshdrin  )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k.
+ * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
+ * Ditto for the __ia64__ case accordingly.
+ */
+#define YY_BUF_SIZE 32768
+#else
+#define YY_BUF_SIZE 16384
+#endif /* __ia64__ */
+#endif
+
+/* The state buf must be large enough to hold one state per character in the main buffer.
+ */
+#define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+extern int fitshdrleng;
+
+extern FILE *fitshdrin, *fitshdrout;
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+#define YY_LESS_LINENO(n)
+    
+/* Return all but the first "n" matched characters back to the input stream. */
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up fitshdrtext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+		*yy_cp = (yy_hold_char); \
+		YY_RESTORE_YY_MORE_OFFSET \
+		(yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+		YY_DO_BEFORE_ACTION; /* set up fitshdrtext again */ \
+		} \
+	while ( 0 )
+
+#define unput(c) yyunput( c, (yytext_ptr)  )
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef size_t yy_size_t;
+#endif
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+	{
+	FILE *yy_input_file;
+
+	char *yy_ch_buf;		/* input buffer */
+	char *yy_buf_pos;		/* current position in input buffer */
+
+	/* Size of input buffer in bytes, not including room for EOB
+	 * characters.
+	 */
+	yy_size_t yy_buf_size;
+
+	/* Number of characters read into yy_ch_buf, not including EOB
+	 * characters.
+	 */
+	int yy_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 yy_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 yy_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 yy_at_bol;
+
+    int yy_bs_lineno; /**< The line count. */
+    int yy_bs_column; /**< The column count. */
+    
+	/* Whether to try to fill the input buffer when we reach the
+	 * end of it.
+	 */
+	int yy_fill_buffer;
+
+	int yy_buffer_status;
+
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+	/* When an EOF's been seen but there's still some text to process
+	 * then we mark the buffer as YY_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 fitshdrrestart()), so that the user can continue scanning by
+	 * just pointing fitshdrin at a new input file.
+	 */
+#define YY_BUFFER_EOF_PENDING 2
+
+	};
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+/* Stack of input buffers. */
+static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
+static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
+static YY_BUFFER_STATE * yy_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 YY_CURRENT_BUFFER ( (yy_buffer_stack) \
+                          ? (yy_buffer_stack)[(yy_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 YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
+
+/* yy_hold_char holds the character lost when fitshdrtext is formed. */
+static char yy_hold_char;
+static int yy_n_chars;		/* number of characters read into yy_ch_buf */
+int fitshdrleng;
+
+/* Points to current character in buffer. */
+static char *yy_c_buf_p = (char *) 0;
+static int yy_init = 0;		/* whether we need to initialize */
+static int yy_start = 0;	/* start state number */
+
+/* Flag which is used to allow fitshdrwrap()'s to do buffer switches
+ * instead of setting up a fresh fitshdrin.  A bit of a hack ...
+ */
+static int yy_did_buffer_switch_on_eof;
+
+void fitshdrrestart (FILE *input_file  );
+void fitshdr_switch_to_buffer (YY_BUFFER_STATE new_buffer  );
+YY_BUFFER_STATE fitshdr_create_buffer (FILE *file,int size  );
+void fitshdr_delete_buffer (YY_BUFFER_STATE b  );
+void fitshdr_flush_buffer (YY_BUFFER_STATE b  );
+void fitshdrpush_buffer_state (YY_BUFFER_STATE new_buffer  );
+void fitshdrpop_buffer_state (void );
+
+static void fitshdrensure_buffer_stack (void );
+static void fitshdr_load_buffer_state (void );
+static void fitshdr_init_buffer (YY_BUFFER_STATE b,FILE *file  );
+
+#define YY_FLUSH_BUFFER fitshdr_flush_buffer(YY_CURRENT_BUFFER )
+
+YY_BUFFER_STATE fitshdr_scan_buffer (char *base,yy_size_t size  );
+YY_BUFFER_STATE fitshdr_scan_string (yyconst char *yy_str  );
+YY_BUFFER_STATE fitshdr_scan_bytes (yyconst char *bytes,int len  );
+
+void *fitshdralloc (yy_size_t  );
+void *fitshdrrealloc (void *,yy_size_t  );
+void fitshdrfree (void *  );
+
+#define yy_new_buffer fitshdr_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+	{ \
+	if ( ! YY_CURRENT_BUFFER ){ \
+        fitshdrensure_buffer_stack (); \
+		YY_CURRENT_BUFFER_LVALUE =    \
+            fitshdr_create_buffer(fitshdrin,YY_BUF_SIZE ); \
+	} \
+	YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+	}
+
+#define yy_set_bol(at_bol) \
+	{ \
+	if ( ! YY_CURRENT_BUFFER ){\
+        fitshdrensure_buffer_stack (); \
+		YY_CURRENT_BUFFER_LVALUE =    \
+            fitshdr_create_buffer(fitshdrin,YY_BUF_SIZE ); \
+	} \
+	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+	}
+
+#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+
+/* Begin user sect3 */
+
+#define fitshdrwrap(n) 1
+#define YY_SKIP_YYWRAP
+
+typedef char YY_CHAR;
+
+FILE *fitshdrin = (FILE *) 0, *fitshdrout = (FILE *) 0;
+
+typedef int yy_state_type;
+
+extern int fitshdrlineno;
+
+int fitshdrlineno = 1;
+
+extern char *fitshdrtext;
+#define yytext_ptr fitshdrtext
+static yyconst flex_int16_t yy_nxt[][128] =
+    {
+    {
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0
+    },
+
+    {
+       15,   16,   16,   16,   16,   16,   16,   16,   16,   16,
+       16,   16,   16,   16,   16,   16,   16,   16,   16,   16,
+       16,   16,   16,   16,   16,   16,   16,   16,   16,   16,
+       16,   16,   16,   16,   16,   16,   16,   16,   16,   16,
+       16,   16,   16,   16,   16,   16,   16,   16,   16,   16,
+       16,   16,   16,   16,   16,   16,   16,   16,   16,   16,
+       16,   16,   16,   16,   16,   16,   16,   16,   16,   16,
+
+       16,   16,   16,   16,   16,   16,   16,   16,   16,   16,
+       16,   16,   16,   16,   16,   16,   16,   16,   16,   16,
+       16,   16,   16,   16,   16,   16,   16,   16,   16,   16,
+       16,   16,   16,   16,   16,   16,   16,   16,   16,   16,
+       16,   16,   16,   16,   16,   16,   16,   16,   16,   16,
+       16,   16,   16,   16,   16,   16,   16,   16
+    },
+
+    {
+       15,   17,   17,   17,   17,   17,   17,   17,   17,   17,
+       16,   17,   17,   17,   17,   17,   17,   17,   17,   17,
+       17,   17,   17,   17,   17,   17,   17,   17,   17,   17,
+       17,   17,   18,   17,   17,   17,   17,   17,   17,   17,
+
+       17,   17,   17,   17,   17,   19,   17,   17,   19,   19,
+       19,   19,   19,   19,   19,   19,   19,   19,   17,   17,
+       17,   17,   17,   17,   17,   19,   19,   20,   19,   21,
+       19,   19,   22,   19,   19,   19,   19,   19,   19,   19,
+       19,   19,   19,   19,   19,   19,   19,   19,   19,   19,
+       19,   17,   17,   17,   17,   19,   17,   17,   17,   17,
+       17,   17,   17,   17,   17,   17,   17,   17,   17,   17,
+       17,   17,   17,   17,   17,   17,   17,   17,   17,   17,
+       17,   17,   17,   17,   17,   17,   17,   17
+    },
+
+    {
+       15,   23,   23,   23,   23,   23,   23,   23,   23,   23,
+
+       16,   23,   23,   23,   23,   23,   23,   23,   23,   23,
+       23,   23,   23,   23,   23,   23,   23,   23,   23,   23,
+       23,   23,   24,   23,   23,   23,   23,   23,   23,   25,
+       26,   23,   23,   27,   23,   27,   28,   29,   30,   31,
+       31,   31,   31,   31,   31,   31,   31,   31,   23,   23,
+       23,   23,   23,   23,   23,   23,   23,   23,   23,   23,
+       32,   23,   23,   23,   23,   23,   23,   23,   23,   23,
+       23,   23,   23,   23,   32,   23,   23,   23,   23,   23,
+       23,   23,   23,   23,   23,   23,   23,   23,   23,   23,
+       23,   23,   23,   23,   23,   23,   23,   23,   23,   23,
+
+       23,   23,   23,   23,   23,   23,   23,   23,   23,   23,
+       23,   23,   23,   23,   23,   23,   23,   23
+    },
+
+    {
+       15,   23,   23,   23,   23,   23,   23,   23,   23,   23,
+       16,   23,   23,   23,   23,   23,   23,   23,   23,   23,
+       23,   23,   23,   23,   23,   23,   23,   23,   23,   23,
+       23,   23,   24,   23,   23,   23,   23,   23,   23,   25,
+       26,   23,   23,   27,   23,   27,   28,   29,   30,   31,
+       31,   31,   31,   31,   31,   31,   31,   31,   23,   23,
+       23,   23,   23,   23,   23,   23,   23,   23,   23,   23,
+       32,   23,   23,   23,   23,   23,   23,   23,   23,   23,
+
+       23,   23,   23,   23,   32,   23,   23,   23,   23,   23,
+       23,   23,   23,   23,   23,   23,   23,   23,   23,   23,
+       23,   23,   23,   23,   23,   23,   23,   23,   23,   23,
+       23,   23,   23,   23,   23,   23,   23,   23,   23,   23,
+       23,   23,   23,   23,   23,   23,   23,   23
+    },
+
+    {
+       15,   33,   33,   33,   33,   33,   33,   33,   33,   33,
+       34,   33,   33,   33,   33,   33,   33,   33,   33,   33,
+       33,   33,   33,   33,   33,   33,   33,   33,   33,   33,
+       33,   33,   35,   33,   33,   33,   33,   33,   33,   33,
+       33,   33,   33,   33,   33,   33,   33,   36,   33,   33,
+
+       33,   33,   33,   33,   33,   33,   33,   33,   33,   33,
+       33,   33,   33,   33,   33,   33,   33,   33,   33,   33,
+       33,   33,   33,   33,   33,   33,   33,   33,   33,   33,
+       33,   33,   33,   33,   33,   33,   33,   33,   33,   33,
+       33,   33,   33,   33,   33,   33,   33,   33,   33,   33,
+       33,   33,   33,   33,   33,   33,   33,   33,   33,   33,
+       33,   33,   33,   33,   33,   33,   33,   33,   33,   33,
+       33,   33,   33,   33,   33,   33,   33,   33
+    },
+
+    {
+       15,   33,   33,   33,   33,   33,   33,   33,   33,   33,
+       34,   33,   33,   33,   33,   33,   33,   33,   33,   33,
+
+       33,   33,   33,   33,   33,   33,   33,   33,   33,   33,
+       33,   33,   35,   33,   33,   33,   33,   33,   33,   33,
+       33,   33,   33,   33,   33,   33,   33,   36,   33,   33,
+       33,   33,   33,   33,   33,   33,   33,   33,   33,   33,
+       33,   33,   33,   33,   33,   33,   33,   33,   33,   33,
+       33,   33,   33,   33,   33,   33,   33,   33,   33,   33,
+       33,   33,   33,   33,   33,   33,   33,   33,   33,   33,
+       33,   33,   33,   33,   33,   33,   33,   33,   33,   33,
+       33,   33,   33,   33,   33,   33,   33,   33,   33,   33,
+       33,   33,   33,   33,   33,   33,   33,   33,   33,   33,
+
+       33,   33,   33,   33,   33,   33,   33,   33
+    },
+
+    {
+       15,   37,   37,   37,   37,   37,   37,   37,   37,   37,
+       16,   37,   37,   37,   37,   37,   37,   37,   37,   37,
+       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
+       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
+       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
+       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
+       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
+       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
+       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
+
+       37,   38,   37,   37,   37,   37,   37,   37,   37,   37,
+       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
+       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
+       37,   37,   37,   37,   37,   37,   37,   37
+    },
+
+    {
+       15,   37,   37,   37,   37,   37,   37,   37,   37,   37,
+       16,   37,   37,   37,   37,   37,   37,   37,   37,   37,
+       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
+       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
+       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
+       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
+
+       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
+       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
+       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
+       37,   38,   37,   37,   37,   37,   37,   37,   37,   37,
+       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
+       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
+       37,   37,   37,   37,   37,   37,   37,   37
+    },
+
+    {
+       15,   39,   39,   39,   39,   39,   39,   39,   39,   39,
+       16,   39,   39,   39,   39,   39,   39,   39,   39,   39,
+       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
+
+       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
+       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
+       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
+       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
+       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
+       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
+       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
+       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
+       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
+       39,   39,   39,   39,   39,   39,   39,   39
+
+    },
+
+    {
+       15,   39,   39,   39,   39,   39,   39,   39,   39,   39,
+       16,   39,   39,   39,   39,   39,   39,   39,   39,   39,
+       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
+       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
+       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
+       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
+       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
+       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
+       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
+       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
+
+       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
+       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
+       39,   39,   39,   39,   39,   39,   39,   39
+    },
+
+    {
+       15,   40,   40,   40,   40,   40,   40,   40,   40,   40,
+       16,   40,   40,   40,   40,   40,   40,   40,   40,   40,
+       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
+       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
+       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
+       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
+       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
+
+       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
+       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
+       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
+       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
+       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
+       40,   40,   40,   40,   40,   40,   40,   40
+    },
+
+    {
+       15,   40,   40,   40,   40,   40,   40,   40,   40,   40,
+       16,   40,   40,   40,   40,   40,   40,   40,   40,   40,
+       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
+       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
+
+       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
+       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
+       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
+       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
+       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
+       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
+       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
+       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
+       40,   40,   40,   40,   40,   40,   40,   40
+    },
+
+    {
+       15,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+
+       42,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+
+       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+       41,   41,   41,   41,   41,   41,   41,   41
+    },
+
+    {
+       15,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+       42,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+
+       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+       41,   41,   41,   41,   41,   41,   41,   41
+    },
+
+    {
+      -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,  -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
+    },
+
+    {
+       15,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
+      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
+
+      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
+      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
+      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
+      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
+      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
+      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
+      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
+      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
+      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
+      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
+
+      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16
+    },
+
+    {
+       15,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+      -17,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43
+    },
+
+    {
+       15,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+      -18,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   44,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43
+    },
+
+    {
+       15,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+      -19,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43,   43,   45,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   46,   43,   43,   46,   46,
+       46,   46,   46,   46,   46,   46,   46,   46,   43,   43,
+       43,   43,   43,   43,   43,   46,   46,   46,   46,   46,
+       46,   46,   46,   46,   46,   46,   46,   46,   46,   46,
+       46,   46,   46,   46,   46,   46,   46,   46,   46,   46,
+       46,   43,   43,   43,   43,   46,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43
+
+    },
+
+    {
+       15,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+      -20,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   45,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   46,   43,   43,   46,   46,
+       46,   46,   46,   46,   46,   46,   46,   46,   43,   43,
+       43,   43,   43,   43,   43,   46,   46,   46,   46,   46,
+       46,   46,   46,   46,   46,   46,   46,   46,   46,   47,
+       46,   46,   46,   46,   46,   46,   46,   46,   46,   46,
+       46,   43,   43,   43,   43,   46,   43,   43,   43,   43,
+
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43
+    },
+
+    {
+       15,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+      -21,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   45,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   46,   43,   43,   46,   46,
+       46,   46,   46,   46,   46,   46,   46,   46,   43,   43,
+       43,   43,   43,   43,   43,   46,   46,   46,   46,   46,
+
+       46,   46,   46,   46,   46,   46,   46,   46,   48,   46,
+       46,   46,   46,   46,   46,   46,   46,   46,   46,   46,
+       46,   43,   43,   43,   43,   46,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43
+    },
+
+    {
+       15,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+      -22,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   45,   43,   43,   43,   43,   43,   43,   43,
+
+       43,   43,   43,   43,   43,   46,   43,   43,   46,   46,
+       46,   46,   46,   46,   46,   46,   46,   46,   43,   43,
+       43,   43,   43,   43,   43,   46,   46,   46,   46,   46,
+       46,   46,   46,   49,   46,   46,   46,   46,   46,   46,
+       46,   46,   46,   46,   46,   46,   46,   46,   46,   46,
+       46,   43,   43,   43,   43,   46,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43
+    },
+
+    {
+       15,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
+
+      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
+      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
+      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
+      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
+      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
+      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
+      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
+      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
+      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
+      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
+
+      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
+      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23
+    },
+
+    {
+       15,  -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,   50,  -24,  -24,  -24,  -24,  -24,  -24,  -24,
+      -24,  -24,  -24,  -24,  -24,  -24,  -24,   51,  -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,
+
+      -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,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,
+      -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24
+    },
+
+    {
+       15,   52,   52,   52,   52,   52,   52,   52,   52,   52,
+       52,   52,   52,   52,   52,   52,   52,   52,   52,   52,
+       52,   52,   52,   52,   52,   52,   52,   52,   52,   52,
+       52,   52,   52,   52,   52,   52,   52,   52,   52,   53,
+       52,   52,   52,   52,   52,   52,   52,   52,   52,   52,
+
+       52,   52,   52,   52,   52,   52,   52,   52,   52,   52,
+       52,   52,   52,   52,   52,   52,   52,   52,   52,   52,
+       52,   52,   52,   52,   52,   52,   52,   52,   52,   52,
+       52,   52,   52,   52,   52,   52,   52,   52,   52,   52,
+       52,   52,   52,   52,   52,   52,   52,   52,   52,   52,
+       52,   52,   52,   52,   52,   52,   52,   52,   52,   52,
+       52,   52,   52,   52,   52,   52,   52,   52,   52,   52,
+       52,   52,   52,   52,   52,   52,   52,   52
+    },
+
+    {
+       15,  -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,   54,  -26,  -26,  -26,  -26,  -26,  -26,  -26,
+      -26,  -26,  -26,   55,  -26,   55,   56,  -26,   57,   57,
+       57,   57,   57,   57,   57,   57,   57,   57,  -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,
+      -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,  -26,  -26,  -26,  -26,  -26,  -26
+    },
+
+    {
+       15,  -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,  -27,  -27,  -27,  -27,  -27,  -27,  -27,
+      -27,  -27,  -27,  -27,  -27,  -27,   58,  -27,   59,   60,
+       60,   60,   60,   60,   60,   60,   60,   60,  -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,
+
+      -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,  -27,  -27,  -27,  -27,  -27,  -27
+    },
+
+    {
+       15,  -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,   61,   61,
+       61,   61,   61,   61,   61,   61,   61,   61,  -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,  -28,  -28,  -28,  -28,  -28,  -28
+    },
+
+    {
+       15,  -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,  -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
+
+    },
+
+    {
+       15,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
+      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
+      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
+      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
+      -30,  -30,  -30,  -30,  -30,  -30,   62,  -30,   63,   64,
+       64,   64,   64,   64,   64,   64,   64,   64,  -30,  -30,
+      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,   65,
+      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
+      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
+      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
+
+      -30,   65,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
+      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
+      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30
+    },
+
+    {
+       15,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
+      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
+      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
+      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
+      -31,  -31,  -31,  -31,  -31,  -31,   62,  -31,   66,   66,
+       66,   66,   66,   66,   66,   66,   66,   66,  -31,  -31,
+      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,   65,
+
+      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
+      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
+      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
+      -31,   65,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
+      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
+      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31
+    },
+
+    {
+       15,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
+      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
+      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
+      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
+
+      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
+      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
+      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
+      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
+      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
+      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
+      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
+      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
+      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32
+    },
+
+    {
+       15,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
+
+      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
+      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
+      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
+      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
+      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
+      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
+      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
+      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
+      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
+      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
+
+      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
+      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33
+    },
+
+    {
+       15,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
+      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
+      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
+      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
+      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
+      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
+      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
+      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
+
+      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
+      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
+      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
+      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
+      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34
+    },
+
+    {
+       15,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
+       67,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
+      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
+      -35,  -35,   68,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
+      -35,  -35,  -35,  -35,  -35,  -35,  -35,   69,  -35,  -35,
+
+      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
+      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
+      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
+      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
+      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
+      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
+      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
+      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35
+    },
+
+    {
+       15,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
+       70,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
+
+      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
+      -36,  -36,   71,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
+      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
+      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
+      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
+      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
+      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
+      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
+      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
+      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
+
+      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36
+    },
+
+    {
+       15,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37
+    },
+
+    {
+       15,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
+      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
+      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
+      -38,  -38,   72,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
+       72,   72,   72,   72,  -38,   72,   72,   72,   72,   72,
+       72,   72,   72,   72,   72,   72,   72,   72,  -38,  -38,
+
+      -38,  -38,  -38,  -38,  -38,   72,   72,   72,   72,   72,
+       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
+       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
+       72,  -38,  -38,  -38,   72,  -38,  -38,   72,   72,   72,
+       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
+       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
+       72,   72,   72,  -38,  -38,  -38,  -38,  -38
+    },
+
+    {
+       15,   73,   73,   73,   73,   73,   73,   73,   73,   73,
+      -39,   73,   73,   73,   73,   73,   73,   73,   73,   73,
+       73,   73,   73,   73,   73,   73,   73,   73,   73,   73,
+
+       73,   73,   73,   73,   73,   73,   73,   73,   73,   73,
+       73,   73,   73,   73,   73,   73,   73,   73,   73,   73,
+       73,   73,   73,   73,   73,   73,   73,   73,   73,   73,
+       73,   73,   73,   73,   73,   73,   73,   73,   73,   73,
+       73,   73,   73,   73,   73,   73,   73,   73,   73,   73,
+       73,   73,   73,   73,   73,   73,   73,   73,   73,   73,
+       73,   73,   73,   73,   73,   73,   73,   73,   73,   73,
+       73,   73,   73,   73,   73,   73,   73,   73,   73,   73,
+       73,   73,   73,   73,   73,   73,   73,   73,   73,   73,
+       73,   73,   73,   73,   73,   73,   73,   73
+
+    },
+
+    {
+       15,   74,   74,   74,   74,   74,   74,   74,   74,   74,
+      -40,   74,   74,   74,   74,   74,   74,   74,   74,   74,
+       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
+       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
+       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
+       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
+       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
+       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
+       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
+       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
+
+       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
+       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
+       74,   74,   74,   74,   74,   74,   74,   74
+    },
+
+    {
+       15,   75,   75,   75,   75,   75,   75,   75,   75,   75,
+       76,   75,   75,   75,   75,   75,   75,   75,   75,   75,
+       75,   75,   75,   75,   75,   75,   75,   75,   75,   75,
+       75,   75,   75,   75,   75,   75,   75,   75,   75,   75,
+       75,   75,   75,   75,   75,   75,   75,   75,   75,   75,
+       75,   75,   75,   75,   75,   75,   75,   75,   75,   75,
+       75,   75,   75,   75,   75,   75,   75,   75,   75,   75,
+
+       75,   75,   75,   75,   75,   75,   75,   75,   75,   75,
+       75,   75,   75,   75,   75,   75,   75,   75,   75,   75,
+       75,   75,   75,   75,   75,   75,   75,   75,   75,   75,
+       75,   75,   75,   75,   75,   75,   75,   75,   75,   75,
+       75,   75,   75,   75,   75,   75,   75,   75,   75,   75,
+       75,   75,   75,   75,   75,   75,   75,   75
+    },
+
+    {
+       15,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
+      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
+      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
+      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
+
+      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
+      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
+      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
+      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
+      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
+      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
+      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
+      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
+      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42
+    },
+
+    {
+       15,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+
+      -43,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77
+    },
+
+    {
+       15,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+      -44,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   78,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77
+    },
+
+    {
+       15,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+      -45,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   79,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77
+    },
+
+    {
+       15,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+      -46,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   80,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   81,   77,   77,   81,   81,
+       81,   81,   81,   81,   81,   81,   81,   81,   77,   77,
+       77,   77,   77,   77,   77,   81,   81,   81,   81,   81,
+       81,   81,   81,   81,   81,   81,   81,   81,   81,   81,
+       81,   81,   81,   81,   81,   81,   81,   81,   81,   81,
+       81,   77,   77,   77,   77,   81,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+
+       77,   77,   77,   77,   77,   77,   77,   77
+    },
+
+    {
+       15,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+      -47,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   80,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   81,   77,   77,   81,   81,
+       81,   81,   81,   81,   81,   81,   81,   81,   77,   77,
+       77,   77,   77,   77,   77,   81,   81,   81,   81,   81,
+       81,   81,   81,   81,   81,   81,   81,   82,   83,   81,
+       81,   81,   81,   81,   81,   81,   81,   81,   81,   81,
+
+       81,   77,   77,   77,   77,   81,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77
+    },
+
+    {
+       15,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+      -48,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   80,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   81,   77,   77,   81,   81,
+       81,   81,   81,   81,   81,   81,   81,   81,   77,   77,
+
+       77,   77,   77,   77,   77,   81,   81,   81,   84,   81,
+       81,   81,   81,   81,   81,   81,   81,   81,   81,   81,
+       81,   81,   81,   81,   81,   81,   81,   81,   81,   81,
+       81,   77,   77,   77,   77,   81,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77
+    },
+
+    {
+       15,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+      -49,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+
+       77,   77,   80,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   81,   77,   77,   81,   81,
+       81,   81,   81,   81,   81,   81,   81,   81,   77,   77,
+       77,   77,   77,   77,   77,   81,   81,   81,   81,   81,
+       81,   81,   81,   81,   81,   81,   81,   81,   81,   81,
+       81,   81,   81,   85,   81,   81,   81,   81,   81,   81,
+       81,   77,   77,   77,   77,   81,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77
+
+    },
+
+    {
+       15,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
+      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
+      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
+      -50,  -50,   50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
+      -50,  -50,  -50,  -50,  -50,  -50,  -50,   51,  -50,  -50,
+      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
+      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
+      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
+      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
+      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
+
+      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
+      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
+      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50
+    },
+
+    {
+       15,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
+      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
+      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
+      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
+      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
+      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
+      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
+
+      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
+      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
+      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
+      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
+      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
+      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51
+    },
+
+    {
+       15,   52,   52,   52,   52,   52,   52,   52,   52,   52,
+       52,   52,   52,   52,   52,   52,   52,   52,   52,   52,
+       52,   52,   52,   52,   52,   52,   52,   52,   52,   52,
+       52,   52,   52,   52,   52,   52,   52,   52,   52,   53,
+
+       52,   52,   52,   52,   52,   52,   52,   52,   52,   52,
+       52,   52,   52,   52,   52,   52,   52,   52,   52,   52,
+       52,   52,   52,   52,   52,   52,   52,   52,   52,   52,
+       52,   52,   52,   52,   52,   52,   52,   52,   52,   52,
+       52,   52,   52,   52,   52,   52,   52,   52,   52,   52,
+       52,   52,   52,   52,   52,   52,   52,   52,   52,   52,
+       52,   52,   52,   52,   52,   52,   52,   52,   52,   52,
+       52,   52,   52,   52,   52,   52,   52,   52,   52,   52,
+       52,   52,   52,   52,   52,   52,   52,   52
+    },
+
+    {
+       15,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,   52,
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53
+    },
+
+    {
+       15,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
+      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
+      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
+      -54,  -54,   54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
+      -54,  -54,  -54,   55,  -54,   55,   56,  -54,   57,   57,
+       57,   57,   57,   57,   57,   57,   57,   57,  -54,  -54,
+      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
+      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
+
+      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
+      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
+      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
+      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
+      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54
+    },
+
+    {
+       15,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
+      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
+      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
+      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
+      -55,  -55,  -55,  -55,  -55,  -55,   56,  -55,   57,   57,
+
+       57,   57,   57,   57,   57,   57,   57,   57,  -55,  -55,
+      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
+      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
+      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
+      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
+      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
+      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
+      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55
+    },
+
+    {
+       15,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
+      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
+
+      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
+      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
+      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,   86,   86,
+       86,   86,   86,   86,   86,   86,   86,   86,  -56,  -56,
+      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
+      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
+      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
+      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
+      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
+      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
+
+      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56
+    },
+
+    {
+       15,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
+      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
+      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
+      -57,  -57,   87,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
+      -57,  -57,  -57,  -57,   88,  -57,   89,  -57,   90,   90,
+       90,   90,   90,   90,   90,   90,   90,   90,  -57,  -57,
+      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,   91,
+      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
+      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
+
+      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
+      -57,   91,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
+      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
+      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57
+    },
+
+    {
+       15,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
+      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
+      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
+      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
+      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,   61,   61,
+       61,   61,   61,   61,   61,   61,   61,   61,  -58,  -58,
+
+      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
+      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
+      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
+      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
+      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
+      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
+      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58
+    },
+
+    {
+       15,  -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,  -59,  -59,
+      -59,  -59,  -59,  -59,  -59,  -59,   62,  -59,   63,   64,
+       64,   64,   64,   64,   64,   64,   64,   64,  -59,  -59,
+      -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,   65,
+      -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,   65,  -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
+
+    },
+
+    {
+       15,  -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,  -60,   66,   66,
+       66,   66,   66,   66,   66,   66,   66,   66,  -60,  -60,
+      -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,   65,
+      -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,   65,  -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
+    },
+
+    {
+       15,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
+      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
+      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
+      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
+      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,   61,   61,
+       61,   61,   61,   61,   61,   61,   61,   61,  -61,  -61,
+      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,   65,
+
+      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
+      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
+      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
+      -61,   65,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
+      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
+      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61
+    },
+
+    {
+       15,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
+      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
+      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
+      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
+
+      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,   92,   92,
+       92,   92,   92,   92,   92,   92,   92,   92,  -62,  -62,
+      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,   65,
+      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
+      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
+      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
+      -62,   65,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
+      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
+      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62
+    },
+
+    {
+       15,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
+
+      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
+      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
+      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
+      -63,  -63,  -63,  -63,  -63,  -63,   62,  -63,   93,   94,
+       94,   94,   94,   94,   94,   94,   94,   94,  -63,  -63,
+      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,   65,
+      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
+      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
+      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
+      -63,   65,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
+
+      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
+      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63
+    },
+
+    {
+       15,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
+      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
+      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
+      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
+      -64,  -64,  -64,  -64,  -64,  -64,   62,  -64,   95,   95,
+       95,   95,   95,   95,   95,   95,   95,   95,  -64,  -64,
+      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,   65,
+      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
+
+      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
+      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
+      -64,   65,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
+      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
+      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64
+    },
+
+    {
+       15,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
+      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
+      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
+      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
+      -65,  -65,  -65,   96,  -65,   96,  -65,  -65,   97,   97,
+
+       97,   97,   97,   97,   97,   97,   97,   97,  -65,  -65,
+      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
+      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
+      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
+      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
+      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
+      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
+      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65
+    },
+
+    {
+       15,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
+      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
+
+      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
+      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
+      -66,  -66,  -66,  -66,  -66,  -66,   62,  -66,   98,   98,
+       98,   98,   98,   98,   98,   98,   98,   98,  -66,  -66,
+      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,   65,
+      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
+      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
+      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
+      -66,   65,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
+      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
+
+      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66
+    },
+
+    {
+       15,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67
+    },
+
+    {
+       15,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+       67,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+      -68,  -68,   68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+      -68,  -68,  -68,  -68,  -68,  -68,  -68,   69,  -68,  -68,
+      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+
+      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68
+    },
+
+    {
+       15,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
+       70,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
+      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
+
+      -69,  -69,   71,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
+      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
+      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
+      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
+      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
+      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
+      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
+      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
+      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
+      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69
+
+    },
+
+    {
+       15,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
+      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
+      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
+      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
+      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
+      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
+      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
+      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
+      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
+      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
+
+      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
+      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
+      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70
+    },
+
+    {
+       15,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
+       70,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
+      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
+      -71,  -71,   71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
+      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
+      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
+      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
+
+      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
+      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
+      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
+      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
+      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
+      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71
+    },
+
+    {
+       15,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
+      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
+      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
+      -72,  -72,   72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
+
+       72,   72,   72,   72,  -72,   72,   72,   72,   72,   72,
+       72,   72,   72,   72,   72,   72,   72,   72,  -72,  -72,
+      -72,  -72,  -72,  -72,  -72,   72,   72,   72,   72,   72,
+       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
+       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
+       72,  -72,  -72,   99,   72,  -72,  -72,   72,   72,   72,
+       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
+       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
+       72,   72,   72,  -72,  -72,  -72,  -72,  -72
+    },
+
+    {
+       15,   73,   73,   73,   73,   73,   73,   73,   73,   73,
+
+      -73,   73,   73,   73,   73,   73,   73,   73,   73,   73,
+       73,   73,   73,   73,   73,   73,   73,   73,   73,   73,
+       73,   73,   73,   73,   73,   73,   73,   73,   73,   73,
+       73,   73,   73,   73,   73,   73,   73,   73,   73,   73,
+       73,   73,   73,   73,   73,   73,   73,   73,   73,   73,
+       73,   73,   73,   73,   73,   73,   73,   73,   73,   73,
+       73,   73,   73,   73,   73,   73,   73,   73,   73,   73,
+       73,   73,   73,   73,   73,   73,   73,   73,   73,   73,
+       73,   73,   73,   73,   73,   73,   73,   73,   73,   73,
+       73,   73,   73,   73,   73,   73,   73,   73,   73,   73,
+
+       73,   73,   73,   73,   73,   73,   73,   73,   73,   73,
+       73,   73,   73,   73,   73,   73,   73,   73
+    },
+
+    {
+       15,   74,   74,   74,   74,   74,   74,   74,   74,   74,
+      -74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
+       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
+       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
+       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
+       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
+       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
+       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
+
+       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
+       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
+       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
+       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
+       74,   74,   74,   74,   74,   74,   74,   74
+    },
+
+    {
+       15,   75,   75,   75,   75,   75,   75,   75,   75,   75,
+       76,   75,   75,   75,   75,   75,   75,   75,   75,   75,
+       75,   75,   75,   75,   75,   75,   75,   75,   75,   75,
+       75,   75,   75,   75,   75,   75,   75,   75,   75,   75,
+       75,   75,   75,   75,   75,   75,   75,   75,   75,   75,
+
+       75,   75,   75,   75,   75,   75,   75,   75,   75,   75,
+       75,   75,   75,   75,   75,   75,   75,   75,   75,   75,
+       75,   75,   75,   75,   75,   75,   75,   75,   75,   75,
+       75,   75,   75,   75,   75,   75,   75,   75,   75,   75,
+       75,   75,   75,   75,   75,   75,   75,   75,   75,   75,
+       75,   75,   75,   75,   75,   75,   75,   75,   75,   75,
+       75,   75,   75,   75,   75,   75,   75,   75,   75,   75,
+       75,   75,   75,   75,   75,   75,   75,   75
+    },
+
+    {
+       15,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
+      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
+
+      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
+      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
+      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
+      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
+      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
+      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
+      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
+      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
+      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
+      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
+
+      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76
+    },
+
+    {
+       15,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      -77,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+
+      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      100,  100,  100,  100,  100,  100,  100,  100
+    },
+
+    {
+       15,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      -78,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      100,  100,  101,  100,  100,  100,  100,  100,  100,  100,
+      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+
+      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      100,  100,  100,  100,  100,  100,  100,  100
+    },
+
+    {
+       15,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      -79,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+
+      100,  100,  102,  100,  100,  100,  100,  100,  100,  100,
+      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      100,  100,  100,  100,  100,  100,  100,  100
+
+    },
+
+    {
+       15,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      -80,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      100,  100,  103,  100,  100,  100,  100,  100,  100,  100,
+      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+
+      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      100,  100,  100,  100,  100,  100,  100,  100
+    },
+
+    {
+       15,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      -81,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      100,  100,  104,  100,  100,  100,  100,  100,  100,  100,
+      100,  100,  100,  100,  100,  105,  100,  100,  105,  105,
+      105,  105,  105,  105,  105,  105,  105,  105,  100,  100,
+      100,  100,  100,  100,  100,  105,  105,  105,  105,  105,
+
+      105,  105,  105,  105,  105,  105,  105,  105,  105,  105,
+      105,  105,  105,  105,  105,  105,  105,  105,  105,  105,
+      105,  100,  100,  100,  100,  105,  100,  100,  100,  100,
+      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      100,  100,  100,  100,  100,  100,  100,  100
+    },
+
+    {
+       15,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      -82,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      100,  100,  104,  100,  100,  100,  100,  100,  100,  100,
+
+      100,  100,  100,  100,  100,  105,  100,  100,  105,  105,
+      105,  105,  105,  105,  105,  105,  105,  105,  100,  100,
+      100,  100,  100,  100,  100,  105,  105,  105,  105,  105,
+      105,  105,  105,  105,  105,  105,  105,  106,  105,  105,
+      105,  105,  105,  105,  105,  105,  105,  105,  105,  105,
+      105,  100,  100,  100,  100,  105,  100,  100,  100,  100,
+      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      100,  100,  100,  100,  100,  100,  100,  100
+    },
+
+    {
+       15,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+
+      -83,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      100,  100,  104,  100,  100,  100,  100,  100,  100,  100,
+      100,  100,  100,  100,  100,  105,  100,  100,  105,  105,
+      105,  105,  105,  105,  105,  105,  105,  105,  100,  100,
+      100,  100,  100,  100,  100,  105,  105,  105,  105,  105,
+      105,  105,  105,  105,  105,  105,  105,  105,  105,  105,
+      105,  105,  105,  105,  107,  105,  105,  105,  105,  105,
+      105,  100,  100,  100,  100,  105,  100,  100,  100,  100,
+      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+
+      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      100,  100,  100,  100,  100,  100,  100,  100
+    },
+
+    {
+       15,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      -84,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      100,  100,  108,  100,  100,  100,  100,  100,  100,  100,
+      100,  100,  100,  100,  100,  105,  100,  100,  105,  105,
+      105,  105,  105,  105,  105,  105,  105,  105,  100,  100,
+      100,  100,  100,  100,  100,  105,  105,  105,  105,  105,
+      105,  105,  105,  105,  105,  105,  105,  105,  105,  105,
+
+      105,  105,  105,  105,  105,  105,  105,  105,  105,  105,
+      105,  100,  100,  100,  100,  105,  100,  100,  100,  100,
+      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      100,  100,  100,  100,  100,  100,  100,  100
+    },
+
+    {
+       15,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      -85,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      100,  100,  104,  100,  100,  100,  100,  100,  100,  100,
+      100,  100,  100,  100,  100,  105,  100,  100,  105,  105,
+
+      105,  105,  105,  105,  105,  105,  105,  105,  100,  100,
+      100,  100,  100,  100,  100,  105,  105,  105,  105,  105,
+      105,  105,  105,  105,  105,  105,  105,  105,  105,  105,
+      105,  105,  105,  105,  109,  105,  105,  105,  105,  105,
+      105,  100,  100,  100,  100,  105,  100,  100,  100,  100,
+      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      100,  100,  100,  100,  100,  100,  100,  100,  100,  100,
+      100,  100,  100,  100,  100,  100,  100,  100
+    },
+
+    {
+       15,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
+      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
+
+      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
+      -86,  -86,  110,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
+      -86,  -86,  -86,  -86,  111,  -86,  -86,  -86,   86,   86,
+       86,   86,   86,   86,   86,   86,   86,   86,  -86,  -86,
+      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,   91,
+      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
+      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
+      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
+      -86,   91,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
+      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
+
+      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86
+    },
+
+    {
+       15,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+      -87,  -87,   87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+      -87,  -87,  -87,  -87,   88,  -87,  -87,  -87,  -87,  -87,
+      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+
+      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87
+    },
+
+    {
+       15,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
+      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
+      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
+      -88,  -88,  112,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
+      -88,  -88,  -88,  113,  -88,  113,  114,  -88,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,  -88,  -88,
+
+      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
+      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
+      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
+      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
+      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
+      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
+      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88
+    },
+
+    {
+       15,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
+      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
+      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
+
+      -89,  -89,  110,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
+      -89,  -89,  -89,  -89,  111,  -89,  -89,  -89,  116,  116,
+      116,  116,  116,  116,  116,  116,  116,  116,  -89,  -89,
+      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,   91,
+      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
+      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
+      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
+      -89,   91,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
+      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
+      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89
+
+    },
+
+    {
+       15,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
+      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
+      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
+      -90,  -90,   87,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
+      -90,  -90,  -90,  -90,   88,  -90,   89,  -90,   90,   90,
+       90,   90,   90,   90,   90,   90,   90,   90,  -90,  -90,
+      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,   91,
+      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
+      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
+      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
+
+      -90,   91,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
+      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
+      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90
+    },
+
+    {
+       15,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+      -91,  -91,  -91,  117,  -91,  117,  -91,  -91,  118,  118,
+      118,  118,  118,  118,  118,  118,  118,  118,  -91,  -91,
+      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+
+      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91
+    },
+
+    {
+       15,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
+      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
+      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
+      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
+
+      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,   92,   92,
+       92,   92,   92,   92,   92,   92,   92,   92,  -92,  -92,
+      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,   65,
+      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
+      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
+      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
+      -92,   65,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
+      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
+      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92
+    },
+
+    {
+       15,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+
+      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+      -93,  -93,  -93,  -93,  -93,  -93,   62,  -93,  119,  120,
+      120,  120,  120,  120,  120,  120,  120,  120,  -93,  -93,
+      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,   65,
+      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+      -93,   65,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+
+      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93
+    },
+
+    {
+       15,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
+      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
+      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
+      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
+      -94,  -94,  -94,  -94,  -94,  -94,   62,  -94,  121,  121,
+      121,  121,  121,  121,  121,  121,  121,  121,  -94,  -94,
+      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,   65,
+      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
+
+      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
+      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
+      -94,   65,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
+      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
+      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94
+    },
+
+    {
+       15,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
+      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
+      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
+      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
+      -95,  -95,  -95,  -95,  -95,  -95,   62,  -95,  122,  122,
+
+      122,  122,  122,  122,  122,  122,  122,  122,  -95,  -95,
+      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,   65,
+      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
+      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
+      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
+      -95,   65,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
+      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
+      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95
+    },
+
+    {
+       15,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
+      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
+
+      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
+      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
+      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,   97,   97,
+       97,   97,   97,   97,   97,   97,   97,   97,  -96,  -96,
+      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
+      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
+      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
+      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
+      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
+      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
+
+      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96
+    },
+
+    {
+       15,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
+      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
+      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
+      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
+      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,   97,   97,
+       97,   97,   97,   97,   97,   97,   97,   97,  -97,  -97,
+      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
+      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
+      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
+
+      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
+      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
+      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
+      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97
+    },
+
+    {
+       15,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
+      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
+      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
+      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
+      -98,  -98,  -98,  -98,  -98,  -98,   62,  -98,  123,  123,
+      123,  123,  123,  123,  123,  123,  123,  123,  -98,  -98,
+
+      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,   65,
+      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
+      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
+      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
+      -98,   65,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
+      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
+      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98
+    },
+
+    {
+       15,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
+      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
+      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
+
+      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
+      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
+      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
+      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
+      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
+      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
+      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
+      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
+      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
+      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99
+
+    },
+
+    {
+       15,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+     -100,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124
+    },
+
+    {
+       15,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+     -101,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  125,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124
+    },
+
+    {
+       15,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+     -102,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  126,  124,  124,  124,  124,  124,  124,  124,
+
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124
+    },
+
+    {
+       15,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+
+     -103,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  127,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124
+    },
+
+    {
+       15,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+     -104,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  128,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124
+    },
+
+    {
+       15,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+     -105,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  129,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  130,  124,  124,  130,  130,
+
+      130,  130,  130,  130,  130,  130,  130,  130,  124,  124,
+      124,  124,  124,  124,  124,  130,  130,  130,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+      130,  124,  124,  124,  124,  130,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124
+    },
+
+    {
+       15,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+     -106,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  129,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  130,  124,  124,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130,  124,  124,
+      124,  124,  124,  124,  124,  130,  130,  130,  130,  131,
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+      130,  124,  124,  124,  124,  130,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+
+      124,  124,  124,  124,  124,  124,  124,  124
+    },
+
+    {
+       15,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+     -107,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  129,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  130,  124,  124,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130,  124,  124,
+      124,  124,  124,  124,  124,  130,  130,  130,  130,  130,
+      130,  130,  130,  132,  130,  130,  130,  130,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+
+      130,  124,  124,  124,  124,  130,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124
+    },
+
+    {
+       15,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+     -108,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  133,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124
+    },
+
+    {
+       15,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+     -109,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+
+      124,  124,  129,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  130,  124,  124,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130,  124,  124,
+      124,  124,  124,  124,  124,  130,  130,  130,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  134,
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+      130,  124,  124,  124,  124,  130,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124
+
+    },
+
+    {
+       15, -110, -110, -110, -110, -110, -110, -110, -110, -110,
+     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
+     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
+     -110, -110,  110, -110, -110, -110, -110, -110, -110, -110,
+     -110, -110, -110, -110,  111, -110, -110, -110, -110, -110,
+     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
+     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
+     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
+     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
+     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
+
+     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
+     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
+     -110, -110, -110, -110, -110, -110, -110, -110
+    },
+
+    {
+       15, -111, -111, -111, -111, -111, -111, -111, -111, -111,
+     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
+     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
+     -111, -111,  135, -111, -111, -111, -111, -111, -111, -111,
+     -111, -111, -111,  136, -111,  136,  114, -111,  137,  137,
+      137,  137,  137,  137,  137,  137,  137,  137, -111, -111,
+     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
+
+     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
+     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
+     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
+     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
+     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
+     -111, -111, -111, -111, -111, -111, -111, -111
+    },
+
+    {
+       15, -112, -112, -112, -112, -112, -112, -112, -112, -112,
+     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
+     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
+     -112, -112,  112, -112, -112, -112, -112, -112, -112, -112,
+
+     -112, -112, -112,  113, -112,  113,  114, -112,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115, -112, -112,
+     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
+     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
+     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
+     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
+     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
+     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
+     -112, -112, -112, -112, -112, -112, -112, -112
+    },
+
+    {
+       15, -113, -113, -113, -113, -113, -113, -113, -113, -113,
+
+     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
+     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
+     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
+     -113, -113, -113, -113, -113, -113,  114, -113,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115, -113, -113,
+     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
+     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
+     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
+     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
+     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
+
+     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
+     -113, -113, -113, -113, -113, -113, -113, -113
+    },
+
+    {
+       15, -114, -114, -114, -114, -114, -114, -114, -114, -114,
+     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
+     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
+     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
+     -114, -114, -114, -114, -114, -114, -114, -114,  138,  138,
+      138,  138,  138,  138,  138,  138,  138,  138, -114, -114,
+     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
+     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
+
+     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
+     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
+     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
+     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
+     -114, -114, -114, -114, -114, -114, -114, -114
+    },
+
+    {
+       15, -115, -115, -115, -115, -115, -115, -115, -115, -115,
+     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
+     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
+     -115, -115,  139, -115, -115, -115, -115, -115, -115, -115,
+     -115,  140, -115, -115, -115, -115,  141, -115,  142,  142,
+
+      142,  142,  142,  142,  142,  142,  142,  142, -115, -115,
+     -115, -115, -115, -115, -115, -115, -115, -115, -115,  143,
+     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
+     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
+     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
+     -115,  143, -115, -115, -115, -115, -115, -115, -115, -115,
+     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
+     -115, -115, -115, -115, -115, -115, -115, -115
+    },
+
+    {
+       15, -116, -116, -116, -116, -116, -116, -116, -116, -116,
+     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
+
+     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
+     -116, -116,  110, -116, -116, -116, -116, -116, -116, -116,
+     -116, -116, -116, -116,  111, -116, -116, -116,  116,  116,
+      116,  116,  116,  116,  116,  116,  116,  116, -116, -116,
+     -116, -116, -116, -116, -116, -116, -116, -116, -116,   91,
+     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
+     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
+     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
+     -116,   91, -116, -116, -116, -116, -116, -116, -116, -116,
+     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
+
+     -116, -116, -116, -116, -116, -116, -116, -116
+    },
+
+    {
+       15, -117, -117, -117, -117, -117, -117, -117, -117, -117,
+     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
+     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
+     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
+     -117, -117, -117, -117, -117, -117, -117, -117,  118,  118,
+      118,  118,  118,  118,  118,  118,  118,  118, -117, -117,
+     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
+     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
+     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
+
+     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
+     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
+     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
+     -117, -117, -117, -117, -117, -117, -117, -117
+    },
+
+    {
+       15, -118, -118, -118, -118, -118, -118, -118, -118, -118,
+     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
+     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
+     -118, -118,  110, -118, -118, -118, -118, -118, -118, -118,
+     -118, -118, -118, -118,  111, -118, -118, -118,  118,  118,
+      118,  118,  118,  118,  118,  118,  118,  118, -118, -118,
+
+     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
+     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
+     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
+     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
+     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
+     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
+     -118, -118, -118, -118, -118, -118, -118, -118
+    },
+
+    {
+       15, -119, -119, -119, -119, -119, -119, -119, -119, -119,
+     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
+     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
+
+     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
+     -119, -119, -119, -119, -119, -119,   62, -119,  144,  145,
+      145,  145,  145,  145,  145,  145,  145,  145, -119, -119,
+     -119, -119, -119, -119, -119, -119, -119, -119, -119,   65,
+     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
+     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
+     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
+     -119,   65, -119, -119, -119, -119, -119, -119, -119, -119,
+     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
+     -119, -119, -119, -119, -119, -119, -119, -119
+
+    },
+
+    {
+       15, -120, -120, -120, -120, -120, -120, -120, -120, -120,
+     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
+     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
+     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
+     -120, -120, -120, -120, -120, -120,   62, -120,  146,  146,
+      146,  146,  146,  146,  146,  146,  146,  146, -120, -120,
+     -120, -120, -120, -120, -120, -120, -120, -120, -120,   65,
+     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
+     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
+     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
+
+     -120,   65, -120, -120, -120, -120, -120, -120, -120, -120,
+     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
+     -120, -120, -120, -120, -120, -120, -120, -120
+    },
+
+    {
+       15, -121, -121, -121, -121, -121, -121, -121, -121, -121,
+     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
+     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
+     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
+     -121, -121, -121, -121, -121, -121,   62, -121,  147,  147,
+      147,  147,  147,  147,  147,  147,  147,  147, -121, -121,
+     -121, -121, -121, -121, -121, -121, -121, -121, -121,   65,
+
+     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
+     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
+     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
+     -121,   65, -121, -121, -121, -121, -121, -121, -121, -121,
+     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
+     -121, -121, -121, -121, -121, -121, -121, -121
+    },
+
+    {
+       15, -122, -122, -122, -122, -122, -122, -122, -122, -122,
+     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
+     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
+     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
+
+     -122, -122, -122, -122, -122, -122,   62, -122,  148,  148,
+      148,  148,  148,  148,  148,  148,  148,  148, -122, -122,
+     -122, -122, -122, -122, -122, -122, -122, -122, -122,   65,
+     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
+     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
+     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
+     -122,   65, -122, -122, -122, -122, -122, -122, -122, -122,
+     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
+     -122, -122, -122, -122, -122, -122, -122, -122
+    },
+
+    {
+       15, -123, -123, -123, -123, -123, -123, -123, -123, -123,
+
+     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
+     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
+     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
+     -123, -123, -123, -123, -123, -123,   62, -123,  149,  149,
+      149,  149,  149,  149,  149,  149,  149,  149, -123, -123,
+     -123, -123, -123, -123, -123, -123, -123, -123, -123,   65,
+     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
+     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
+     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
+     -123,   65, -123, -123, -123, -123, -123, -123, -123, -123,
+
+     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
+     -123, -123, -123, -123, -123, -123, -123, -123
+    },
+
+    {
+       15,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+     -124,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150
+    },
+
+    {
+       15,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+     -125,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  151,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150
+    },
+
+    {
+       15,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+     -126,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  152,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+
+      150,  150,  150,  150,  150,  150,  150,  150
+    },
+
+    {
+       15,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+     -127,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  153,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150
+    },
+
+    {
+       15,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+     -128,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  154,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150
+    },
+
+    {
+       15,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+     -129,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+
+      150,  150,  155,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150
+
+    },
+
+    {
+       15,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+     -130,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  156,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  157,  150,  150,  157,  157,
+      157,  157,  157,  157,  157,  157,  157,  157,  150,  150,
+      150,  150,  150,  150,  150,  157,  157,  157,  157,  157,
+      157,  157,  157,  157,  157,  157,  157,  157,  157,  157,
+      157,  157,  157,  157,  157,  157,  157,  157,  157,  157,
+      157,  150,  150,  150,  150,  157,  150,  150,  150,  150,
+
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150
+    },
+
+    {
+       15,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+     -131,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  156,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  157,  150,  150,  157,  157,
+      157,  157,  157,  157,  157,  157,  157,  157,  150,  150,
+      150,  150,  150,  150,  150,  157,  157,  157,  157,  157,
+
+      157,  157,  157,  157,  157,  157,  157,  157,  158,  157,
+      157,  157,  157,  157,  157,  157,  157,  157,  157,  157,
+      157,  150,  150,  150,  150,  157,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150
+    },
+
+    {
+       15,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+     -132,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  156,  150,  150,  150,  150,  150,  150,  150,
+
+      150,  150,  150,  150,  150,  157,  150,  150,  157,  157,
+      157,  157,  157,  157,  157,  157,  157,  157,  150,  150,
+      150,  150,  150,  150,  150,  157,  157,  157,  157,  157,
+      157,  157,  157,  157,  157,  157,  157,  157,  159,  157,
+      157,  157,  157,  157,  157,  157,  157,  157,  157,  157,
+      157,  150,  150,  150,  150,  157,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150
+    },
+
+    {
+       15,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+
+     -133,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  160,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150
+    },
+
+    {
+       15,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+     -134,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  156,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  157,  150,  150,  157,  157,
+      157,  157,  157,  157,  157,  157,  157,  157,  150,  150,
+      150,  150,  150,  150,  150,  157,  157,  157,  157,  157,
+      157,  157,  157,  157,  157,  157,  157,  157,  157,  157,
+
+      157,  157,  161,  157,  157,  157,  157,  157,  157,  157,
+      157,  150,  150,  150,  150,  157,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,  150,  150,  150,  150
+    },
+
+    {
+       15, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+     -135, -135,  135, -135, -135, -135, -135, -135, -135, -135,
+     -135, -135, -135,  136, -135,  136,  114, -135,  137,  137,
+
+      137,  137,  137,  137,  137,  137,  137,  137, -135, -135,
+     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+     -135, -135, -135, -135, -135, -135, -135, -135
+    },
+
+    {
+       15, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+
+     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+     -136, -136, -136, -136, -136, -136,  114, -136,  137,  137,
+      137,  137,  137,  137,  137,  137,  137,  137, -136, -136,
+     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+
+     -136, -136, -136, -136, -136, -136, -136, -136
+    },
+
+    {
+       15, -137, -137, -137, -137, -137, -137, -137, -137, -137,
+     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
+     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
+     -137, -137,  162, -137, -137, -137, -137, -137, -137, -137,
+     -137,  163, -137, -137, -137, -137,  141, -137,  164,  164,
+      164,  164,  164,  164,  164,  164,  164,  164, -137, -137,
+     -137, -137, -137, -137, -137, -137, -137, -137, -137,  143,
+     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
+     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
+
+     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
+     -137,  143, -137, -137, -137, -137, -137, -137, -137, -137,
+     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
+     -137, -137, -137, -137, -137, -137, -137, -137
+    },
+
+    {
+       15, -138, -138, -138, -138, -138, -138, -138, -138, -138,
+     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
+     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
+     -138, -138,  162, -138, -138, -138, -138, -138, -138, -138,
+     -138,  163, -138, -138, -138, -138, -138, -138,  138,  138,
+      138,  138,  138,  138,  138,  138,  138,  138, -138, -138,
+
+     -138, -138, -138, -138, -138, -138, -138, -138, -138,  143,
+     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
+     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
+     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
+     -138,  143, -138, -138, -138, -138, -138, -138, -138, -138,
+     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
+     -138, -138, -138, -138, -138, -138, -138, -138
+    },
+
+    {
+       15, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+
+     -139, -139,  139, -139, -139, -139, -139, -139, -139, -139,
+     -139,  140, -139, -139, -139, -139, -139, -139, -139, -139,
+     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+     -139, -139, -139, -139, -139, -139, -139, -139
+
+    },
+
+    {
+       15, -140, -140, -140, -140, -140, -140, -140, -140, -140,
+     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
+     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
+     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
+     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
+     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
+     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
+     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
+     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
+     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
+
+     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
+     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
+     -140, -140, -140, -140, -140, -140, -140, -140
+    },
+
+    {
+       15, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+     -141, -141,  162, -141, -141, -141, -141, -141, -141, -141,
+     -141,  163, -141, -141, -141, -141, -141, -141,  165,  165,
+      165,  165,  165,  165,  165,  165,  165,  165, -141, -141,
+     -141, -141, -141, -141, -141, -141, -141, -141, -141,  143,
+
+     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+     -141,  143, -141, -141, -141, -141, -141, -141, -141, -141,
+     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+     -141, -141, -141, -141, -141, -141, -141, -141
+    },
+
+    {
+       15, -142, -142, -142, -142, -142, -142, -142, -142, -142,
+     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
+     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
+     -142, -142,  139, -142, -142, -142, -142, -142, -142, -142,
+
+     -142,  140, -142, -142, -142, -142,  141, -142,  142,  142,
+      142,  142,  142,  142,  142,  142,  142,  142, -142, -142,
+     -142, -142, -142, -142, -142, -142, -142, -142, -142,  143,
+     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
+     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
+     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
+     -142,  143, -142, -142, -142, -142, -142, -142, -142, -142,
+     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
+     -142, -142, -142, -142, -142, -142, -142, -142
+    },
+
+    {
+       15, -143, -143, -143, -143, -143, -143, -143, -143, -143,
+
+     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
+     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
+     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
+     -143, -143, -143,  166, -143,  166, -143, -143,  167,  167,
+      167,  167,  167,  167,  167,  167,  167,  167, -143, -143,
+     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
+     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
+     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
+     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
+     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
+
+     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
+     -143, -143, -143, -143, -143, -143, -143, -143
+    },
+
+    {
+       15, -144, -144, -144, -144, -144, -144, -144, -144, -144,
+     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
+     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
+     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
+     -144, -144, -144, -144, -144, -144,   62, -144,  168,  169,
+      169,  169,  169,  169,  169,  169,  169,  169, -144, -144,
+     -144, -144, -144, -144, -144, -144, -144, -144, -144,   65,
+     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
+
+     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
+     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
+     -144,   65, -144, -144, -144, -144, -144, -144, -144, -144,
+     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
+     -144, -144, -144, -144, -144, -144, -144, -144
+    },
+
+    {
+       15, -145, -145, -145, -145, -145, -145, -145, -145, -145,
+     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
+     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
+     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
+     -145, -145, -145, -145, -145, -145,   62, -145,  170,  170,
+
+      170,  170,  170,  170,  170,  170,  170,  170, -145, -145,
+     -145, -145, -145, -145, -145, -145, -145, -145, -145,   65,
+     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
+     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
+     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
+     -145,   65, -145, -145, -145, -145, -145, -145, -145, -145,
+     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
+     -145, -145, -145, -145, -145, -145, -145, -145
+    },
+
+    {
+       15, -146, -146, -146, -146, -146, -146, -146, -146, -146,
+     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
+
+     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
+     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
+     -146, -146, -146, -146, -146, -146,   62, -146,  171,  171,
+      171,  171,  171,  171,  171,  171,  171,  171, -146, -146,
+     -146, -146, -146, -146, -146, -146, -146, -146, -146,   65,
+     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
+     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
+     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
+     -146,   65, -146, -146, -146, -146, -146, -146, -146, -146,
+     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
+
+     -146, -146, -146, -146, -146, -146, -146, -146
+    },
+
+    {
+       15, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+     -147, -147, -147, -147, -147, -147,   62, -147,  172,  172,
+      172,  172,  172,  172,  172,  172,  172,  172, -147, -147,
+     -147, -147, -147, -147, -147, -147, -147, -147, -147,   65,
+     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+
+     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+     -147,   65, -147, -147, -147, -147, -147, -147, -147, -147,
+     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+     -147, -147, -147, -147, -147, -147, -147, -147
+    },
+
+    {
+       15, -148, -148, -148, -148, -148, -148, -148, -148, -148,
+     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
+     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
+     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
+     -148, -148, -148, -148, -148, -148,   62, -148,  173,  173,
+      173,  173,  173,  173,  173,  173,  173,  173, -148, -148,
+
+     -148, -148, -148, -148, -148, -148, -148, -148, -148,   65,
+     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
+     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
+     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
+     -148,   65, -148, -148, -148, -148, -148, -148, -148, -148,
+     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
+     -148, -148, -148, -148, -148, -148, -148, -148
+    },
+
+    {
+       15, -149, -149, -149, -149, -149, -149, -149, -149, -149,
+     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
+     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
+
+     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
+     -149, -149, -149, -149, -149, -149,   62, -149,  174,  174,
+      174,  174,  174,  174,  174,  174,  174,  174, -149, -149,
+     -149, -149, -149, -149, -149, -149, -149, -149, -149,   65,
+     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
+     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
+     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
+     -149,   65, -149, -149, -149, -149, -149, -149, -149, -149,
+     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
+     -149, -149, -149, -149, -149, -149, -149, -149
+
+    },
+
+    {
+       15,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+     -150,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175
+    },
+
+    {
+       15,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+     -151,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  176,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175
+    },
+
+    {
+       15,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+     -152,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  177,  175,  175,  175,  175,  175,  175,  175,
+
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175
+    },
+
+    {
+       15,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+
+     -153,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  178,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175
+    },
+
+    {
+       15,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+     -154,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  179,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175
+    },
+
+    {
+       15,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+     -155,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  180,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175
+    },
+
+    {
+       15,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+     -156,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  181,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+
+      175,  175,  175,  175,  175,  175,  175,  175
+    },
+
+    {
+       15,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+     -157,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  182,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  183,  175,  175,  183,  183,
+      183,  183,  183,  183,  183,  183,  183,  183,  175,  175,
+      175,  175,  175,  175,  175,  183,  183,  183,  183,  183,
+      183,  183,  183,  183,  183,  183,  183,  183,  183,  183,
+      183,  183,  183,  183,  183,  183,  183,  183,  183,  183,
+
+      183,  175,  175,  175,  175,  183,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175
+    },
+
+    {
+       15,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+     -158,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  182,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  183,  175,  175,  183,  183,
+      183,  183,  183,  183,  183,  183,  183,  183,  175,  175,
+
+      175,  175,  175,  175,  175,  183,  183,  183,  183,  183,
+      183,  183,  183,  183,  183,  183,  183,  183,  183,  183,
+      183,  183,  183,  183,  184,  183,  183,  183,  183,  183,
+      183,  175,  175,  175,  175,  183,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175
+    },
+
+    {
+       15,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+     -159,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+
+      175,  175,  182,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  183,  175,  175,  183,  183,
+      183,  183,  183,  183,  183,  183,  183,  183,  175,  175,
+      175,  175,  175,  175,  175,  183,  183,  183,  183,  183,
+      183,  183,  183,  183,  183,  183,  183,  183,  183,  183,
+      183,  183,  183,  183,  183,  185,  183,  183,  183,  183,
+      183,  175,  175,  175,  175,  183,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175
+
+    },
+
+    {
+       15,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+     -160,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  186,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175
+    },
+
+    {
+       15,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+     -161,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  182,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  183,  175,  175,  183,  183,
+      183,  183,  183,  183,  183,  183,  183,  183,  175,  175,
+      175,  175,  175,  175,  175,  183,  183,  183,  183,  183,
+
+      183,  183,  183,  183,  183,  183,  183,  183,  183,  183,
+      183,  183,  183,  183,  183,  183,  183,  183,  183,  184,
+      183,  175,  175,  175,  175,  183,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,  175,  175,  175,  175,  175,  175,  175
+    },
+
+    {
+       15, -162, -162, -162, -162, -162, -162, -162, -162, -162,
+     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
+     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
+     -162, -162,  162, -162, -162, -162, -162, -162, -162, -162,
+
+     -162,  163, -162, -162, -162, -162, -162, -162, -162, -162,
+     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
+     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
+     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
+     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
+     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
+     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
+     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
+     -162, -162, -162, -162, -162, -162, -162, -162
+    },
+
+    {
+       15, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+
+     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+
+     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+     -163, -163, -163, -163, -163, -163, -163, -163
+    },
+
+    {
+       15, -164, -164, -164, -164, -164, -164, -164, -164, -164,
+     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
+     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
+     -164, -164,  162, -164, -164, -164, -164, -164, -164, -164,
+     -164,  163, -164, -164, -164, -164,  141, -164,  164,  164,
+      164,  164,  164,  164,  164,  164,  164,  164, -164, -164,
+     -164, -164, -164, -164, -164, -164, -164, -164, -164,  143,
+     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
+
+     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
+     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
+     -164,  143, -164, -164, -164, -164, -164, -164, -164, -164,
+     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
+     -164, -164, -164, -164, -164, -164, -164, -164
+    },
+
+    {
+       15, -165, -165, -165, -165, -165, -165, -165, -165, -165,
+     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
+     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
+     -165, -165,  162, -165, -165, -165, -165, -165, -165, -165,
+     -165,  163, -165, -165, -165, -165, -165, -165,  165,  165,
+
+      165,  165,  165,  165,  165,  165,  165,  165, -165, -165,
+     -165, -165, -165, -165, -165, -165, -165, -165, -165,  143,
+     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
+     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
+     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
+     -165,  143, -165, -165, -165, -165, -165, -165, -165, -165,
+     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
+     -165, -165, -165, -165, -165, -165, -165, -165
+    },
+
+    {
+       15, -166, -166, -166, -166, -166, -166, -166, -166, -166,
+     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
+
+     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
+     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
+     -166, -166, -166, -166, -166, -166, -166, -166,  167,  167,
+      167,  167,  167,  167,  167,  167,  167,  167, -166, -166,
+     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
+     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
+     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
+     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
+     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
+     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
+
+     -166, -166, -166, -166, -166, -166, -166, -166
+    },
+
+    {
+       15, -167, -167, -167, -167, -167, -167, -167, -167, -167,
+     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
+     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
+     -167, -167,  162, -167, -167, -167, -167, -167, -167, -167,
+     -167,  163, -167, -167, -167, -167, -167, -167,  167,  167,
+      167,  167,  167,  167,  167,  167,  167,  167, -167, -167,
+     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
+     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
+     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
+
+     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
+     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
+     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
+     -167, -167, -167, -167, -167, -167, -167, -167
+    },
+
+    {
+       15, -168, -168, -168, -168, -168, -168, -168, -168, -168,
+     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
+     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
+     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
+     -168, -168, -168, -168, -168, -168,   62, -168,  187,  188,
+      188,  188,  188,  188,  188,  188,  188,  188, -168, -168,
+
+     -168, -168, -168, -168, -168, -168, -168, -168, -168,   65,
+     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
+     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
+     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
+     -168,   65, -168, -168, -168, -168, -168, -168, -168, -168,
+     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
+     -168, -168, -168, -168, -168, -168, -168, -168
+    },
+
+    {
+       15, -169, -169, -169, -169, -169, -169, -169, -169, -169,
+     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
+     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
+
+     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
+     -169, -169, -169, -169, -169, -169,   62, -169,  189,  189,
+      189,  189,  189,  189,  189,  189,  189,  189, -169, -169,
+     -169, -169, -169, -169, -169, -169, -169, -169, -169,   65,
+     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
+     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
+     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
+     -169,   65, -169, -169, -169, -169, -169, -169, -169, -169,
+     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
+     -169, -169, -169, -169, -169, -169, -169, -169
+
+    },
+
+    {
+       15, -170, -170, -170, -170, -170, -170, -170, -170, -170,
+     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
+     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
+     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
+     -170, -170, -170, -170, -170, -170,   62, -170,  190,  190,
+      190,  190,  190,  190,  190,  190,  190,  190, -170, -170,
+     -170, -170, -170, -170, -170, -170, -170, -170, -170,   65,
+     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
+     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
+     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
+
+     -170,   65, -170, -170, -170, -170, -170, -170, -170, -170,
+     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
+     -170, -170, -170, -170, -170, -170, -170, -170
+    },
+
+    {
+       15, -171, -171, -171, -171, -171, -171, -171, -171, -171,
+     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
+     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
+     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
+     -171, -171, -171, -171, -171, -171,   62, -171,  191,  191,
+      191,  191,  191,  191,  191,  191,  191,  191, -171, -171,
+     -171, -171, -171, -171, -171, -171, -171, -171, -171,   65,
+
+     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
+     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
+     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
+     -171,   65, -171, -171, -171, -171, -171, -171, -171, -171,
+     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
+     -171, -171, -171, -171, -171, -171, -171, -171
+    },
+
+    {
+       15, -172, -172, -172, -172, -172, -172, -172, -172, -172,
+     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
+     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
+     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
+
+     -172, -172, -172, -172, -172, -172,   62, -172,  192,  192,
+      192,  192,  192,  192,  192,  192,  192,  192, -172, -172,
+     -172, -172, -172, -172, -172, -172, -172, -172, -172,   65,
+     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
+     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
+     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
+     -172,   65, -172, -172, -172, -172, -172, -172, -172, -172,
+     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
+     -172, -172, -172, -172, -172, -172, -172, -172
+    },
+
+    {
+       15, -173, -173, -173, -173, -173, -173, -173, -173, -173,
+
+     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
+     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
+     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
+     -173, -173, -173, -173, -173, -173,   62, -173,  193,  193,
+      193,  193,  193,  193,  193,  193,  193,  193, -173, -173,
+     -173, -173, -173, -173, -173, -173, -173, -173, -173,   65,
+     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
+     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
+     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
+     -173,   65, -173, -173, -173, -173, -173, -173, -173, -173,
+
+     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
+     -173, -173, -173, -173, -173, -173, -173, -173
+    },
+
+    {
+       15, -174, -174, -174, -174, -174, -174, -174, -174, -174,
+     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
+     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
+     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
+     -174, -174, -174, -174, -174, -174,   62, -174,  194,  194,
+      194,  194,  194,  194,  194,  194,  194,  194, -174, -174,
+     -174, -174, -174, -174, -174, -174, -174, -174, -174,   65,
+     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
+
+     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
+     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
+     -174,   65, -174, -174, -174, -174, -174, -174, -174, -174,
+     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
+     -174, -174, -174, -174, -174, -174, -174, -174
+    },
+
+    {
+       15,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+     -175,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195
+    },
+
+    {
+       15,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+     -176,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  196,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+
+      195,  195,  195,  195,  195,  195,  195,  195
+    },
+
+    {
+       15,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+     -177,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  197,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195
+    },
+
+    {
+       15,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+     -178,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  197,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195
+    },
+
+    {
+       15,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+     -179,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+
+      195,  195,  197,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195
+
+    },
+
+    {
+       15,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+     -180,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  197,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195
+    },
+
+    {
+       15,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+     -181,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  197,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195
+    },
+
+    {
+       15,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+     -182,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  197,  195,  195,  195,  195,  195,  195,  195,
+
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195
+    },
+
+    {
+       15,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+
+     -183,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  198,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  197,  195,  195,  197,  197,
+      197,  197,  197,  197,  197,  197,  197,  197,  195,  195,
+      195,  195,  195,  195,  195,  197,  197,  197,  197,  197,
+      197,  197,  197,  197,  197,  197,  197,  197,  197,  197,
+      197,  197,  197,  197,  197,  197,  197,  197,  197,  197,
+      197,  195,  195,  195,  195,  197,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195
+    },
+
+    {
+       15,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+     -184,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  198,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  197,  195,  195,  197,  197,
+      197,  197,  197,  197,  197,  197,  197,  197,  195,  195,
+      195,  195,  195,  195,  195,  197,  197,  197,  197,  197,
+      197,  197,  197,  197,  197,  197,  197,  197,  197,  197,
+
+      197,  197,  197,  197,  197,  197,  197,  197,  197,  197,
+      197,  195,  195,  195,  195,  197,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195
+    },
+
+    {
+       15,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+     -185,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  198,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  197,  195,  195,  197,  197,
+
+      197,  197,  197,  197,  197,  197,  197,  197,  195,  195,
+      195,  195,  195,  195,  195,  197,  197,  197,  197,  199,
+      197,  197,  197,  197,  197,  197,  197,  197,  197,  197,
+      197,  197,  197,  197,  197,  197,  197,  197,  197,  197,
+      197,  195,  195,  195,  195,  197,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195
+    },
+
+    {
+       15,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+     -186,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  200,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+
+      195,  195,  195,  195,  195,  195,  195,  195
+    },
+
+    {
+       15, -187, -187, -187, -187, -187, -187, -187, -187, -187,
+     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
+     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
+     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
+     -187, -187, -187, -187, -187, -187,   62, -187,  201,  202,
+      202,  202,  202,  202,  202,  202,  202,  202, -187, -187,
+     -187, -187, -187, -187, -187, -187, -187, -187, -187,   65,
+     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
+     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
+
+     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
+     -187,   65, -187, -187, -187, -187, -187, -187, -187, -187,
+     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
+     -187, -187, -187, -187, -187, -187, -187, -187
+    },
+
+    {
+       15, -188, -188, -188, -188, -188, -188, -188, -188, -188,
+     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
+     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
+     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
+     -188, -188, -188, -188, -188, -188,   62, -188,  203,  203,
+      203,  203,  203,  203,  203,  203,  203,  203, -188, -188,
+
+     -188, -188, -188, -188, -188, -188, -188, -188, -188,   65,
+     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
+     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
+     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
+     -188,   65, -188, -188, -188, -188, -188, -188, -188, -188,
+     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
+     -188, -188, -188, -188, -188, -188, -188, -188
+    },
+
+    {
+       15, -189, -189, -189, -189, -189, -189, -189, -189, -189,
+     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
+     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
+
+     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
+     -189, -189, -189, -189, -189, -189,   62, -189,  204,  204,
+      204,  204,  204,  204,  204,  204,  204,  204, -189, -189,
+     -189, -189, -189, -189, -189, -189, -189, -189, -189,   65,
+     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
+     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
+     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
+     -189,   65, -189, -189, -189, -189, -189, -189, -189, -189,
+     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
+     -189, -189, -189, -189, -189, -189, -189, -189
+
+    },
+
+    {
+       15, -190, -190, -190, -190, -190, -190, -190, -190, -190,
+     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
+     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
+     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
+     -190, -190, -190, -190, -190, -190,   62, -190,  205,  205,
+      205,  205,  205,  205,  205,  205,  205,  205, -190, -190,
+     -190, -190, -190, -190, -190, -190, -190, -190, -190,   65,
+     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
+     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
+     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
+
+     -190,   65, -190, -190, -190, -190, -190, -190, -190, -190,
+     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
+     -190, -190, -190, -190, -190, -190, -190, -190
+    },
+
+    {
+       15, -191, -191, -191, -191, -191, -191, -191, -191, -191,
+     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
+     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
+     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
+     -191, -191, -191, -191, -191, -191,   62, -191,  206,  206,
+      206,  206,  206,  206,  206,  206,  206,  206, -191, -191,
+     -191, -191, -191, -191, -191, -191, -191, -191, -191,   65,
+
+     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
+     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
+     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
+     -191,   65, -191, -191, -191, -191, -191, -191, -191, -191,
+     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
+     -191, -191, -191, -191, -191, -191, -191, -191
+    },
+
+    {
+       15, -192, -192, -192, -192, -192, -192, -192, -192, -192,
+     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
+     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
+     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
+
+     -192, -192, -192, -192, -192, -192,   62, -192,  207,  207,
+      207,  207,  207,  207,  207,  207,  207,  207, -192, -192,
+     -192, -192, -192, -192, -192, -192, -192, -192, -192,   65,
+     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
+     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
+     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
+     -192,   65, -192, -192, -192, -192, -192, -192, -192, -192,
+     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
+     -192, -192, -192, -192, -192, -192, -192, -192
+    },
+
+    {
+       15, -193, -193, -193, -193, -193, -193, -193, -193, -193,
+
+     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
+     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
+     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
+     -193, -193, -193, -193, -193, -193,   62, -193,  208,  208,
+      208,  208,  208,  208,  208,  208,  208,  208, -193, -193,
+     -193, -193, -193, -193, -193, -193, -193, -193, -193,   65,
+     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
+     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
+     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
+     -193,   65, -193, -193, -193, -193, -193, -193, -193, -193,
+
+     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
+     -193, -193, -193, -193, -193, -193, -193, -193
+    },
+
+    {
+       15, -194, -194, -194, -194, -194, -194, -194, -194, -194,
+     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
+     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
+     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
+     -194, -194, -194, -194, -194, -194,   62, -194,  209,  209,
+      209,  209,  209,  209,  209,  209,  209,  209, -194, -194,
+     -194, -194, -194, -194, -194, -194, -194, -194, -194,   65,
+     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
+
+     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
+     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
+     -194,   65, -194, -194, -194, -194, -194, -194, -194, -194,
+     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
+     -194, -194, -194, -194, -194, -194, -194, -194
+    },
+
+    {
+       15, -195, -195, -195, -195, -195, -195, -195, -195, -195,
+     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
+     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
+     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
+     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
+
+     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
+     -195,  210, -195, -195, -195, -195, -195, -195, -195, -195,
+     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
+     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
+     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
+     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
+     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
+     -195, -195, -195, -195, -195, -195, -195, -195
+    },
+
+    {
+       15, -196, -196, -196, -196, -196, -196, -196, -196, -196,
+     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
+
+     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
+     -196, -196,  211, -196, -196, -196, -196, -196, -196, -196,
+     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
+     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
+     -196,  210, -196, -196, -196, -196, -196, -196, -196, -196,
+     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
+     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
+     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
+     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
+     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
+
+     -196, -196, -196, -196, -196, -196, -196, -196
+    },
+
+    {
+       15, -197, -197, -197, -197, -197, -197, -197, -197, -197,
+     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
+     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
+     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
+     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
+     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
+     -197,  212, -197, -197, -197, -197, -197, -197, -197, -197,
+     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
+     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
+
+     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
+     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
+     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
+     -197, -197, -197, -197, -197, -197, -197, -197
+    },
+
+    {
+       15, -198, -198, -198, -198, -198, -198, -198, -198, -198,
+     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
+     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
+     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
+     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
+     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
+
+     -198,  212, -198, -198, -198, -198, -198, -198, -198, -198,
+     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
+     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
+     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
+     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
+     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
+     -198, -198, -198, -198, -198, -198, -198, -198
+    },
+
+    {
+       15, -199, -199, -199, -199, -199, -199, -199, -199, -199,
+     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
+     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
+
+     -199, -199,  213, -199, -199, -199, -199, -199, -199, -199,
+     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
+     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
+     -199,  212, -199, -199, -199, -199, -199, -199, -199, -199,
+     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
+     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
+     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
+     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
+     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
+     -199, -199, -199, -199, -199, -199, -199, -199
+
+    },
+
+    {
+       15, -200, -200, -200, -200, -200, -200, -200, -200, -200,
+     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
+     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
+     -200, -200,  214, -200, -200, -200, -200, -200, -200, -200,
+     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
+     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
+     -200,  215, -200, -200, -200, -200, -200, -200, -200, -200,
+     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
+     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
+     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
+
+     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
+     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
+     -200, -200, -200, -200, -200, -200, -200, -200
+    },
+
+    {
+       15, -201, -201, -201, -201, -201, -201, -201, -201, -201,
+     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
+     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
+     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
+     -201, -201, -201, -201, -201, -201,   62, -201,  216,  217,
+      217,  217,  217,  217,  217,  217,  217,  217, -201, -201,
+     -201, -201, -201, -201, -201, -201, -201, -201, -201,   65,
+
+     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
+     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
+     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
+     -201,   65, -201, -201, -201, -201, -201, -201, -201, -201,
+     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
+     -201, -201, -201, -201, -201, -201, -201, -201
+    },
+
+    {
+       15, -202, -202, -202, -202, -202, -202, -202, -202, -202,
+     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
+     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
+     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
+
+     -202, -202, -202, -202, -202, -202,   62, -202,  218,  218,
+      218,  218,  218,  218,  218,  218,  218,  218, -202, -202,
+     -202, -202, -202, -202, -202, -202, -202, -202, -202,   65,
+     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
+     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
+     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
+     -202,   65, -202, -202, -202, -202, -202, -202, -202, -202,
+     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
+     -202, -202, -202, -202, -202, -202, -202, -202
+    },
+
+    {
+       15, -203, -203, -203, -203, -203, -203, -203, -203, -203,
+
+     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
+     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
+     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
+     -203, -203, -203, -203, -203, -203,   62, -203,  219,  219,
+      219,  219,  219,  219,  219,  219,  219,  219, -203, -203,
+     -203, -203, -203, -203, -203, -203, -203, -203, -203,   65,
+     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
+     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
+     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
+     -203,   65, -203, -203, -203, -203, -203, -203, -203, -203,
+
+     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
+     -203, -203, -203, -203, -203, -203, -203, -203
+    },
+
+    {
+       15, -204, -204, -204, -204, -204, -204, -204, -204, -204,
+     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
+     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
+     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
+     -204, -204, -204, -204, -204, -204,   62, -204,  220,  220,
+      220,  220,  220,  220,  220,  220,  220,  220, -204, -204,
+     -204, -204, -204, -204, -204, -204, -204, -204, -204,   65,
+     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
+
+     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
+     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
+     -204,   65, -204, -204, -204, -204, -204, -204, -204, -204,
+     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
+     -204, -204, -204, -204, -204, -204, -204, -204
+    },
+
+    {
+       15, -205, -205, -205, -205, -205, -205, -205, -205, -205,
+     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
+     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
+     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
+     -205, -205, -205, -205, -205, -205,   62, -205,  221,  221,
+
+      221,  221,  221,  221,  221,  221,  221,  221, -205, -205,
+     -205, -205, -205, -205, -205, -205, -205, -205, -205,   65,
+     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
+     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
+     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
+     -205,   65, -205, -205, -205, -205, -205, -205, -205, -205,
+     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
+     -205, -205, -205, -205, -205, -205, -205, -205
+    },
+
+    {
+       15, -206, -206, -206, -206, -206, -206, -206, -206, -206,
+     -206, -206, -206, -206, -206, -206, -206, -206, -206, -206,
+
+     -206, -206, -206, -206, -206, -206, -206, -206, -206, -206,
+     -206, -206, -206, -206, -206, -206, -206, -206, -206, -206,
+     -206, -206, -206, -206, -206, -206,   62, -206,  222,  222,
+      222,  222,  222,  222,  222,  222,  222,  222, -206, -206,
+     -206, -206, -206, -206, -206, -206, -206, -206, -206,   65,
+     -206, -206, -206, -206, -206, -206, -206, -206, -206, -206,
+     -206, -206, -206, -206, -206, -206, -206, -206, -206, -206,
+     -206, -206, -206, -206, -206, -206, -206, -206, -206, -206,
+     -206,   65, -206, -206, -206, -206, -206, -206, -206, -206,
+     -206, -206, -206, -206, -206, -206, -206, -206, -206, -206,
+
+     -206, -206, -206, -206, -206, -206, -206, -206
+    },
+
+    {
+       15, -207, -207, -207, -207, -207, -207, -207, -207, -207,
+     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
+     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
+     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
+     -207, -207, -207, -207, -207, -207,   62, -207,  223,  223,
+      223,  223,  223,  223,  223,  223,  223,  223, -207, -207,
+     -207, -207, -207, -207, -207, -207, -207, -207, -207,   65,
+     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
+     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
+
+     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
+     -207,   65, -207, -207, -207, -207, -207, -207, -207, -207,
+     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
+     -207, -207, -207, -207, -207, -207, -207, -207
+    },
+
+    {
+       15, -208, -208, -208, -208, -208, -208, -208, -208, -208,
+     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
+     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
+     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
+     -208, -208, -208, -208, -208, -208,   62, -208,  224,  224,
+      224,  224,  224,  224,  224,  224,  224,  224, -208, -208,
+
+     -208, -208, -208, -208, -208, -208, -208, -208, -208,   65,
+     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
+     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
+     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
+     -208,   65, -208, -208, -208, -208, -208, -208, -208, -208,
+     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
+     -208, -208, -208, -208, -208, -208, -208, -208
+    },
+
+    {
+       15, -209, -209, -209, -209, -209, -209, -209, -209, -209,
+     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
+     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
+
+     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
+     -209, -209, -209, -209, -209, -209,   62, -209,  225,  225,
+      225,  225,  225,  225,  225,  225,  225,  225, -209, -209,
+     -209, -209, -209, -209, -209, -209, -209, -209, -209,   65,
+     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
+     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
+     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
+     -209,   65, -209, -209, -209, -209, -209, -209, -209, -209,
+     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
+     -209, -209, -209, -209, -209, -209, -209, -209
+
+    },
+
+    {
+       15, -210, -210, -210, -210, -210, -210, -210, -210, -210,
+     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
+     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
+     -210, -210,  226, -210, -210, -210, -210, -210, -210, -210,
+     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
+     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
+     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
+     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
+     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
+     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
+
+     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
+     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
+     -210, -210, -210, -210, -210, -210, -210, -210
+    },
+
+    {
+       15, -211, -211, -211, -211, -211, -211, -211, -211, -211,
+     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
+     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
+     -211, -211,  227, -211, -211, -211, -211, -211, -211, -211,
+     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
+     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
+     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
+
+     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
+     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
+     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
+     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
+     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
+     -211, -211, -211, -211, -211, -211, -211, -211
+    },
+
+    {
+       15, -212, -212, -212, -212, -212, -212, -212, -212, -212,
+     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
+     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
+     -212, -212,  228, -212, -212, -212, -212, -212, -212, -212,
+
+     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
+     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
+     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
+     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
+     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
+     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
+     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
+     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
+     -212, -212, -212, -212, -212, -212, -212, -212
+    },
+
+    {
+       15, -213, -213, -213, -213, -213, -213, -213, -213, -213,
+
+     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
+     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
+     -213, -213,  229, -213, -213, -213, -213, -213, -213, -213,
+     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
+     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
+     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
+     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
+     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
+     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
+     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
+
+     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
+     -213, -213, -213, -213, -213, -213, -213, -213
+    },
+
+    {
+       15, -214, -214, -214, -214, -214, -214, -214, -214, -214,
+     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
+     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
+     -214, -214,  230, -214, -214, -214, -214, -214, -214, -214,
+     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
+     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
+     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
+     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
+
+     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
+     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
+     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
+     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
+     -214, -214, -214, -214, -214, -214, -214, -214
+    },
+
+    {
+       15, -215, -215, -215, -215, -215, -215, -215, -215, -215,
+     -215, -215, -215, -215, -215, -215, -215, -215, -215, -215,
+     -215, -215, -215, -215, -215, -215, -215, -215, -215, -215,
+     -215, -215,  231, -215, -215, -215, -215, -215, -215, -215,
+     -215, -215, -215, -215, -215, -215, -215, -215, -215, -215,
+
+     -215, -215, -215, -215, -215, -215, -215, -215, -215, -215,
+     -215, -215, -215, -215, -215, -215, -215, -215, -215, -215,
+     -215, -215, -215, -215, -215, -215, -215, -215, -215, -215,
+     -215, -215, -215, -215, -215, -215, -215, -215, -215, -215,
+     -215, -215, -215, -215, -215, -215, -215, -215, -215, -215,
+     -215, -215, -215, -215, -215, -215, -215, -215, -215, -215,
+     -215, -215, -215, -215, -215, -215, -215, -215, -215, -215,
+     -215, -215, -215, -215, -215, -215, -215, -215
+    },
+
+    {
+       15, -216, -216, -216, -216, -216, -216, -216, -216, -216,
+     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
+
+     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
+     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
+     -216, -216, -216, -216, -216, -216,   62, -216,  232,  233,
+      233,  233,  233,  233,  233,  233,  233,  233, -216, -216,
+     -216, -216, -216, -216, -216, -216, -216, -216, -216,   65,
+     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
+     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
+     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
+     -216,   65, -216, -216, -216, -216, -216, -216, -216, -216,
+     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
+
+     -216, -216, -216, -216, -216, -216, -216, -216
+    },
+
+    {
+       15, -217, -217, -217, -217, -217, -217, -217, -217, -217,
+     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
+     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
+     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
+     -217, -217, -217, -217, -217, -217,   62, -217,  234,  234,
+      234,  234,  234,  234,  234,  234,  234,  234, -217, -217,
+     -217, -217, -217, -217, -217, -217, -217, -217, -217,   65,
+     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
+     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
+
+     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
+     -217,   65, -217, -217, -217, -217, -217, -217, -217, -217,
+     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
+     -217, -217, -217, -217, -217, -217, -217, -217
+    },
+
+    {
+       15, -218, -218, -218, -218, -218, -218, -218, -218, -218,
+     -218, -218, -218, -218, -218, -218, -218, -218, -218, -218,
+     -218, -218, -218, -218, -218, -218, -218, -218, -218, -218,
+     -218, -218, -218, -218, -218, -218, -218, -218, -218, -218,
+     -218, -218, -218, -218, -218, -218,   62, -218,  235,  235,
+      235,  235,  235,  235,  235,  235,  235,  235, -218, -218,
+
+     -218, -218, -218, -218, -218, -218, -218, -218, -218,   65,
+     -218, -218, -218, -218, -218, -218, -218, -218, -218, -218,
+     -218, -218, -218, -218, -218, -218, -218, -218, -218, -218,
+     -218, -218, -218, -218, -218, -218, -218, -218, -218, -218,
+     -218,   65, -218, -218, -218, -218, -218, -218, -218, -218,
+     -218, -218, -218, -218, -218, -218, -218, -218, -218, -218,
+     -218, -218, -218, -218, -218, -218, -218, -218
+    },
+
+    {
+       15, -219, -219, -219, -219, -219, -219, -219, -219, -219,
+     -219, -219, -219, -219, -219, -219, -219, -219, -219, -219,
+     -219, -219, -219, -219, -219, -219, -219, -219, -219, -219,
+
+     -219, -219, -219, -219, -219, -219, -219, -219, -219, -219,
+     -219, -219, -219, -219, -219, -219,   62, -219,  236,  236,
+      236,  236,  236,  236,  236,  236,  236,  236, -219, -219,
+     -219, -219, -219, -219, -219, -219, -219, -219, -219,   65,
+     -219, -219, -219, -219, -219, -219, -219, -219, -219, -219,
+     -219, -219, -219, -219, -219, -219, -219, -219, -219, -219,
+     -219, -219, -219, -219, -219, -219, -219, -219, -219, -219,
+     -219,   65, -219, -219, -219, -219, -219, -219, -219, -219,
+     -219, -219, -219, -219, -219, -219, -219, -219, -219, -219,
+     -219, -219, -219, -219, -219, -219, -219, -219
+
+    },
+
+    {
+       15, -220, -220, -220, -220, -220, -220, -220, -220, -220,
+     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
+     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
+     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
+     -220, -220, -220, -220, -220, -220,   62, -220,  237,  237,
+      237,  237,  237,  237,  237,  237,  237,  237, -220, -220,
+     -220, -220, -220, -220, -220, -220, -220, -220, -220,   65,
+     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
+     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
+     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
+
+     -220,   65, -220, -220, -220, -220, -220, -220, -220, -220,
+     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
+     -220, -220, -220, -220, -220, -220, -220, -220
+    },
+
+    {
+       15, -221, -221, -221, -221, -221, -221, -221, -221, -221,
+     -221, -221, -221, -221, -221, -221, -221, -221, -221, -221,
+     -221, -221, -221, -221, -221, -221, -221, -221, -221, -221,
+     -221, -221, -221, -221, -221, -221, -221, -221, -221, -221,
+     -221, -221, -221, -221, -221, -221,   62, -221,  238,  238,
+      238,  238,  238,  238,  238,  238,  238,  238, -221, -221,
+     -221, -221, -221, -221, -221, -221, -221, -221, -221,   65,
+
+     -221, -221, -221, -221, -221, -221, -221, -221, -221, -221,
+     -221, -221, -221, -221, -221, -221, -221, -221, -221, -221,
+     -221, -221, -221, -221, -221, -221, -221, -221, -221, -221,
+     -221,   65, -221, -221, -221, -221, -221, -221, -221, -221,
+     -221, -221, -221, -221, -221, -221, -221, -221, -221, -221,
+     -221, -221, -221, -221, -221, -221, -221, -221
+    },
+
+    {
+       15, -222, -222, -222, -222, -222, -222, -222, -222, -222,
+     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
+     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
+     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
+
+     -222, -222, -222, -222, -222, -222,   62, -222,  239,  239,
+      239,  239,  239,  239,  239,  239,  239,  239, -222, -222,
+     -222, -222, -222, -222, -222, -222, -222, -222, -222,   65,
+     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
+     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
+     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
+     -222,   65, -222, -222, -222, -222, -222, -222, -222, -222,
+     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
+     -222, -222, -222, -222, -222, -222, -222, -222
+    },
+
+    {
+       15, -223, -223, -223, -223, -223, -223, -223, -223, -223,
+
+     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
+     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
+     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
+     -223, -223, -223, -223, -223, -223,   62, -223,  240,  240,
+      240,  240,  240,  240,  240,  240,  240,  240, -223, -223,
+     -223, -223, -223, -223, -223, -223, -223, -223, -223,   65,
+     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
+     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
+     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
+     -223,   65, -223, -223, -223, -223, -223, -223, -223, -223,
+
+     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
+     -223, -223, -223, -223, -223, -223, -223, -223
+    },
+
+    {
+       15, -224, -224, -224, -224, -224, -224, -224, -224, -224,
+     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
+     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
+     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
+     -224, -224, -224, -224, -224, -224,   62, -224,  241,  241,
+      241,  241,  241,  241,  241,  241,  241,  241, -224, -224,
+     -224, -224, -224, -224, -224, -224, -224, -224, -224,   65,
+     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
+
+     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
+     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
+     -224,   65, -224, -224, -224, -224, -224, -224, -224, -224,
+     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
+     -224, -224, -224, -224, -224, -224, -224, -224
+    },
+
+    {
+       15, -225, -225, -225, -225, -225, -225, -225, -225, -225,
+     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
+     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
+     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
+     -225, -225, -225, -225, -225, -225,   62, -225,  242,  242,
+
+      242,  242,  242,  242,  242,  242,  242,  242, -225, -225,
+     -225, -225, -225, -225, -225, -225, -225, -225, -225,   65,
+     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
+     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
+     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
+     -225,   65, -225, -225, -225, -225, -225, -225, -225, -225,
+     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
+     -225, -225, -225, -225, -225, -225, -225, -225
+    },
+
+    {
+       15, -226, -226, -226, -226, -226, -226, -226, -226, -226,
+     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
+
+     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
+     -226, -226,  226, -226, -226, -226, -226, -226, -226, -226,
+     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
+     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
+     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
+     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
+     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
+     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
+     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
+     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
+
+     -226, -226, -226, -226, -226, -226, -226, -226
+    },
+
+    {
+       15, -227, -227, -227, -227, -227, -227, -227, -227, -227,
+     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
+     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
+     -227, -227,  243, -227, -227, -227, -227, -227, -227, -227,
+     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
+     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
+     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
+     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
+     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
+
+     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
+     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
+     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
+     -227, -227, -227, -227, -227, -227, -227, -227
+    },
+
+    {
+       15, -228, -228, -228, -228, -228, -228, -228, -228, -228,
+     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
+     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
+     -228, -228,  228, -228, -228, -228, -228, -228, -228, -228,
+     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
+     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
+
+     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
+     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
+     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
+     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
+     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
+     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
+     -228, -228, -228, -228, -228, -228, -228, -228
+    },
+
+    {
+       15, -229, -229, -229, -229, -229, -229, -229, -229, -229,
+     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
+     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
+
+     -229, -229,  213, -229, -229, -229, -229, -229, -229,  244,
+     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
+     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
+     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
+     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
+     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
+     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
+     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
+     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
+     -229, -229, -229, -229, -229, -229, -229, -229
+
+    },
+
+    {
+       15, -230, -230, -230, -230, -230, -230, -230, -230, -230,
+     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
+     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
+     -230, -230,  245, -230, -230, -230, -230, -230, -230, -230,
+     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
+     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
+     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
+     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
+     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
+     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
+
+     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
+     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
+     -230, -230, -230, -230, -230, -230, -230, -230
+    },
+
+    {
+       15, -231, -231, -231, -231, -231, -231, -231, -231, -231,
+     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
+     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
+     -231, -231,  231, -231, -231, -231, -231, -231, -231, -231,
+     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
+     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
+     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
+
+     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
+     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
+     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
+     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
+     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
+     -231, -231, -231, -231, -231, -231, -231, -231
+    },
+
+    {
+       15, -232, -232, -232, -232, -232, -232, -232, -232, -232,
+     -232, -232, -232, -232, -232, -232, -232, -232, -232, -232,
+     -232, -232, -232, -232, -232, -232, -232, -232, -232, -232,
+     -232, -232, -232, -232, -232, -232, -232, -232, -232, -232,
+
+     -232, -232, -232, -232, -232, -232,   62, -232,  246,  247,
+      247,  247,  247,  247,  247,  247,  247,  247, -232, -232,
+     -232, -232, -232, -232, -232, -232, -232, -232, -232,   65,
+     -232, -232, -232, -232, -232, -232, -232, -232, -232, -232,
+     -232, -232, -232, -232, -232, -232, -232, -232, -232, -232,
+     -232, -232, -232, -232, -232, -232, -232, -232, -232, -232,
+     -232,   65, -232, -232, -232, -232, -232, -232, -232, -232,
+     -232, -232, -232, -232, -232, -232, -232, -232, -232, -232,
+     -232, -232, -232, -232, -232, -232, -232, -232
+    },
+
+    {
+       15, -233, -233, -233, -233, -233, -233, -233, -233, -233,
+
+     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
+     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
+     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
+     -233, -233, -233, -233, -233, -233,   62, -233,  248,  248,
+      248,  248,  248,  248,  248,  248,  248,  248, -233, -233,
+     -233, -233, -233, -233, -233, -233, -233, -233, -233,   65,
+     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
+     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
+     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
+     -233,   65, -233, -233, -233, -233, -233, -233, -233, -233,
+
+     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
+     -233, -233, -233, -233, -233, -233, -233, -233
+    },
+
+    {
+       15, -234, -234, -234, -234, -234, -234, -234, -234, -234,
+     -234, -234, -234, -234, -234, -234, -234, -234, -234, -234,
+     -234, -234, -234, -234, -234, -234, -234, -234, -234, -234,
+     -234, -234, -234, -234, -234, -234, -234, -234, -234, -234,
+     -234, -234, -234, -234, -234, -234,   62, -234,  249,  249,
+      249,  249,  249,  249,  249,  249,  249,  249, -234, -234,
+     -234, -234, -234, -234, -234, -234, -234, -234, -234,   65,
+     -234, -234, -234, -234, -234, -234, -234, -234, -234, -234,
+
+     -234, -234, -234, -234, -234, -234, -234, -234, -234, -234,
+     -234, -234, -234, -234, -234, -234, -234, -234, -234, -234,
+     -234,   65, -234, -234, -234, -234, -234, -234, -234, -234,
+     -234, -234, -234, -234, -234, -234, -234, -234, -234, -234,
+     -234, -234, -234, -234, -234, -234, -234, -234
+    },
+
+    {
+       15, -235, -235, -235, -235, -235, -235, -235, -235, -235,
+     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
+     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
+     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
+     -235, -235, -235, -235, -235, -235,   62, -235,  250,  250,
+
+      250,  250,  250,  250,  250,  250,  250,  250, -235, -235,
+     -235, -235, -235, -235, -235, -235, -235, -235, -235,   65,
+     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
+     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
+     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
+     -235,   65, -235, -235, -235, -235, -235, -235, -235, -235,
+     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
+     -235, -235, -235, -235, -235, -235, -235, -235
+    },
+
+    {
+       15, -236, -236, -236, -236, -236, -236, -236, -236, -236,
+     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
+
+     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
+     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
+     -236, -236, -236, -236, -236, -236,   62, -236,  251,  251,
+      251,  251,  251,  251,  251,  251,  251,  251, -236, -236,
+     -236, -236, -236, -236, -236, -236, -236, -236, -236,   65,
+     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
+     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
+     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
+     -236,   65, -236, -236, -236, -236, -236, -236, -236, -236,
+     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
+
+     -236, -236, -236, -236, -236, -236, -236, -236
+    },
+
+    {
+       15, -237, -237, -237, -237, -237, -237, -237, -237, -237,
+     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
+     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
+     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
+     -237, -237, -237, -237, -237, -237,   62, -237,  252,  252,
+      252,  252,  252,  252,  252,  252,  252,  252, -237, -237,
+     -237, -237, -237, -237, -237, -237, -237, -237, -237,   65,
+     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
+     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
+
+     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
+     -237,   65, -237, -237, -237, -237, -237, -237, -237, -237,
+     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
+     -237, -237, -237, -237, -237, -237, -237, -237
+    },
+
+    {
+       15, -238, -238, -238, -238, -238, -238, -238, -238, -238,
+     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
+     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
+     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
+     -238, -238, -238, -238, -238, -238,   62, -238,  253,  253,
+      253,  253,  253,  253,  253,  253,  253,  253, -238, -238,
+
+     -238, -238, -238, -238, -238, -238, -238, -238, -238,   65,
+     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
+     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
+     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
+     -238,   65, -238, -238, -238, -238, -238, -238, -238, -238,
+     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
+     -238, -238, -238, -238, -238, -238, -238, -238
+    },
+
+    {
+       15, -239, -239, -239, -239, -239, -239, -239, -239, -239,
+     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
+     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
+
+     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
+     -239, -239, -239, -239, -239, -239,   62, -239,  254,  254,
+      254,  254,  254,  254,  254,  254,  254,  254, -239, -239,
+     -239, -239, -239, -239, -239, -239, -239, -239, -239,   65,
+     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
+     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
+     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
+     -239,   65, -239, -239, -239, -239, -239, -239, -239, -239,
+     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
+     -239, -239, -239, -239, -239, -239, -239, -239
+
+    },
+
+    {
+       15, -240, -240, -240, -240, -240, -240, -240, -240, -240,
+     -240, -240, -240, -240, -240, -240, -240, -240, -240, -240,
+     -240, -240, -240, -240, -240, -240, -240, -240, -240, -240,
+     -240, -240, -240, -240, -240, -240, -240, -240, -240, -240,
+     -240, -240, -240, -240, -240, -240,   62, -240,  255,  255,
+      255,  255,  255,  255,  255,  255,  255,  255, -240, -240,
+     -240, -240, -240, -240, -240, -240, -240, -240, -240,   65,
+     -240, -240, -240, -240, -240, -240, -240, -240, -240, -240,
+     -240, -240, -240, -240, -240, -240, -240, -240, -240, -240,
+     -240, -240, -240, -240, -240, -240, -240, -240, -240, -240,
+
+     -240,   65, -240, -240, -240, -240, -240, -240, -240, -240,
+     -240, -240, -240, -240, -240, -240, -240, -240, -240, -240,
+     -240, -240, -240, -240, -240, -240, -240, -240
+    },
+
+    {
+       15, -241, -241, -241, -241, -241, -241, -241, -241, -241,
+     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
+     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
+     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
+     -241, -241, -241, -241, -241, -241,   62, -241,  256,  256,
+      256,  256,  256,  256,  256,  256,  256,  256, -241, -241,
+     -241, -241, -241, -241, -241, -241, -241, -241, -241,   65,
+
+     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
+     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
+     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
+     -241,   65, -241, -241, -241, -241, -241, -241, -241, -241,
+     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
+     -241, -241, -241, -241, -241, -241, -241, -241
+    },
+
+    {
+       15, -242, -242, -242, -242, -242, -242, -242, -242, -242,
+     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
+     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
+     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
+
+     -242, -242, -242, -242, -242, -242,   62, -242,  257,  257,
+      257,  257,  257,  257,  257,  257,  257,  257, -242, -242,
+     -242, -242, -242, -242, -242, -242, -242, -242, -242,   65,
+     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
+     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
+     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
+     -242,   65, -242, -242, -242, -242, -242, -242, -242, -242,
+     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
+     -242, -242, -242, -242, -242, -242, -242, -242
+    },
+
+    {
+       15, -243, -243, -243, -243, -243, -243, -243, -243, -243,
+
+     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
+     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
+     -243, -243,  258, -243, -243, -243, -243, -243, -243, -243,
+     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
+     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
+     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
+     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
+     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
+     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
+     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
+
+     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
+     -243, -243, -243, -243, -243, -243, -243, -243
+    },
+
+    {
+       15,  259,  259,  259,  259,  259,  259,  259,  259,  259,
+      259,  259,  259,  259,  259,  259,  259,  259,  259,  259,
+      259,  259,  259,  259,  259,  259,  259,  259,  259,  259,
+      259,  259,  259,  259,  259,  259,  259,  259,  259,  260,
+      259,  259,  259,  259,  259,  259,  259,  259,  259,  259,
+      259,  259,  259,  259,  259,  259,  259,  259,  259,  259,
+      259,  259,  259,  259,  259,  259,  259,  259,  259,  259,
+      259,  259,  259,  259,  259,  259,  259,  259,  259,  259,
+
+      259,  259,  259,  259,  259,  259,  259,  259,  259,  259,
+      259,  259,  259,  259,  259,  259,  259,  259,  259,  259,
+      259,  259,  259,  259,  259,  259,  259,  259,  259,  259,
+      259,  259,  259,  259,  259,  259,  259,  259,  259,  259,
+      259,  259,  259,  259,  259,  259,  259,  259
+    },
+
+    {
+       15, -245, -245, -245, -245, -245, -245, -245, -245, -245,
+     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
+     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
+     -245, -245,  261, -245, -245, -245, -245, -245, -245, -245,
+     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
+
+     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
+     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
+     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
+     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
+     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
+     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
+     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
+     -245, -245, -245, -245, -245, -245, -245, -245
+    },
+
+    {
+       15, -246, -246, -246, -246, -246, -246, -246, -246, -246,
+     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
+
+     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
+     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
+     -246, -246, -246, -246, -246, -246,   62, -246,  262,  263,
+      263,  263,  263,  263,  263,  263,  263,  263, -246, -246,
+     -246, -246, -246, -246, -246, -246, -246, -246, -246,   65,
+     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
+     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
+     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
+     -246,   65, -246, -246, -246, -246, -246, -246, -246, -246,
+     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
+
+     -246, -246, -246, -246, -246, -246, -246, -246
+    },
+
+    {
+       15, -247, -247, -247, -247, -247, -247, -247, -247, -247,
+     -247, -247, -247, -247, -247, -247, -247, -247, -247, -247,
+     -247, -247, -247, -247, -247, -247, -247, -247, -247, -247,
+     -247, -247, -247, -247, -247, -247, -247, -247, -247, -247,
+     -247, -247, -247, -247, -247, -247,   62, -247,  264,  264,
+      264,  264,  264,  264,  264,  264,  264,  264, -247, -247,
+     -247, -247, -247, -247, -247, -247, -247, -247, -247,   65,
+     -247, -247, -247, -247, -247, -247, -247, -247, -247, -247,
+     -247, -247, -247, -247, -247, -247, -247, -247, -247, -247,
+
+     -247, -247, -247, -247, -247, -247, -247, -247, -247, -247,
+     -247,   65, -247, -247, -247, -247, -247, -247, -247, -247,
+     -247, -247, -247, -247, -247, -247, -247, -247, -247, -247,
+     -247, -247, -247, -247, -247, -247, -247, -247
+    },
+
+    {
+       15, -248, -248, -248, -248, -248, -248, -248, -248, -248,
+     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
+     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
+     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
+     -248, -248, -248, -248, -248, -248,   62, -248,  265,  265,
+      265,  265,  265,  265,  265,  265,  265,  265, -248, -248,
+
+     -248, -248, -248, -248, -248, -248, -248, -248, -248,   65,
+     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
+     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
+     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
+     -248,   65, -248, -248, -248, -248, -248, -248, -248, -248,
+     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
+     -248, -248, -248, -248, -248, -248, -248, -248
+    },
+
+    {
+       15, -249, -249, -249, -249, -249, -249, -249, -249, -249,
+     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
+     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
+
+     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
+     -249, -249, -249, -249, -249, -249,   62, -249,  266,  266,
+      266,  266,  266,  266,  266,  266,  266,  266, -249, -249,
+     -249, -249, -249, -249, -249, -249, -249, -249, -249,   65,
+     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
+     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
+     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
+     -249,   65, -249, -249, -249, -249, -249, -249, -249, -249,
+     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
+     -249, -249, -249, -249, -249, -249, -249, -249
+
+    },
+
+    {
+       15, -250, -250, -250, -250, -250, -250, -250, -250, -250,
+     -250, -250, -250, -250, -250, -250, -250, -250, -250, -250,
+     -250, -250, -250, -250, -250, -250, -250, -250, -250, -250,
+     -250, -250, -250, -250, -250, -250, -250, -250, -250, -250,
+     -250, -250, -250, -250, -250, -250,   62, -250,  267,  267,
+      267,  267,  267,  267,  267,  267,  267,  267, -250, -250,
+     -250, -250, -250, -250, -250, -250, -250, -250, -250,   65,
+     -250, -250, -250, -250, -250, -250, -250, -250, -250, -250,
+     -250, -250, -250, -250, -250, -250, -250, -250, -250, -250,
+     -250, -250, -250, -250, -250, -250, -250, -250, -250, -250,
+
+     -250,   65, -250, -250, -250, -250, -250, -250, -250, -250,
+     -250, -250, -250, -250, -250, -250, -250, -250, -250, -250,
+     -250, -250, -250, -250, -250, -250, -250, -250
+    },
+
+    {
+       15, -251, -251, -251, -251, -251, -251, -251, -251, -251,
+     -251, -251, -251, -251, -251, -251, -251, -251, -251, -251,
+     -251, -251, -251, -251, -251, -251, -251, -251, -251, -251,
+     -251, -251, -251, -251, -251, -251, -251, -251, -251, -251,
+     -251, -251, -251, -251, -251, -251,   62, -251,  268,  268,
+      268,  268,  268,  268,  268,  268,  268,  268, -251, -251,
+     -251, -251, -251, -251, -251, -251, -251, -251, -251,   65,
+
+     -251, -251, -251, -251, -251, -251, -251, -251, -251, -251,
+     -251, -251, -251, -251, -251, -251, -251, -251, -251, -251,
+     -251, -251, -251, -251, -251, -251, -251, -251, -251, -251,
+     -251,   65, -251, -251, -251, -251, -251, -251, -251, -251,
+     -251, -251, -251, -251, -251, -251, -251, -251, -251, -251,
+     -251, -251, -251, -251, -251, -251, -251, -251
+    },
+
+    {
+       15, -252, -252, -252, -252, -252, -252, -252, -252, -252,
+     -252, -252, -252, -252, -252, -252, -252, -252, -252, -252,
+     -252, -252, -252, -252, -252, -252, -252, -252, -252, -252,
+     -252, -252, -252, -252, -252, -252, -252, -252, -252, -252,
+
+     -252, -252, -252, -252, -252, -252,   62, -252,  269,  269,
+      269,  269,  269,  269,  269,  269,  269,  269, -252, -252,
+     -252, -252, -252, -252, -252, -252, -252, -252, -252,   65,
+     -252, -252, -252, -252, -252, -252, -252, -252, -252, -252,
+     -252, -252, -252, -252, -252, -252, -252, -252, -252, -252,
+     -252, -252, -252, -252, -252, -252, -252, -252, -252, -252,
+     -252,   65, -252, -252, -252, -252, -252, -252, -252, -252,
+     -252, -252, -252, -252, -252, -252, -252, -252, -252, -252,
+     -252, -252, -252, -252, -252, -252, -252, -252
+    },
+
+    {
+       15, -253, -253, -253, -253, -253, -253, -253, -253, -253,
+
+     -253, -253, -253, -253, -253, -253, -253, -253, -253, -253,
+     -253, -253, -253, -253, -253, -253, -253, -253, -253, -253,
+     -253, -253, -253, -253, -253, -253, -253, -253, -253, -253,
+     -253, -253, -253, -253, -253, -253,   62, -253,  270,  270,
+      270,  270,  270,  270,  270,  270,  270,  270, -253, -253,
+     -253, -253, -253, -253, -253, -253, -253, -253, -253,   65,
+     -253, -253, -253, -253, -253, -253, -253, -253, -253, -253,
+     -253, -253, -253, -253, -253, -253, -253, -253, -253, -253,
+     -253, -253, -253, -253, -253, -253, -253, -253, -253, -253,
+     -253,   65, -253, -253, -253, -253, -253, -253, -253, -253,
+
+     -253, -253, -253, -253, -253, -253, -253, -253, -253, -253,
+     -253, -253, -253, -253, -253, -253, -253, -253
+    },
+
+    {
+       15, -254, -254, -254, -254, -254, -254, -254, -254, -254,
+     -254, -254, -254, -254, -254, -254, -254, -254, -254, -254,
+     -254, -254, -254, -254, -254, -254, -254, -254, -254, -254,
+     -254, -254, -254, -254, -254, -254, -254, -254, -254, -254,
+     -254, -254, -254, -254, -254, -254,   62, -254,  271,  271,
+      271,  271,  271,  271,  271,  271,  271,  271, -254, -254,
+     -254, -254, -254, -254, -254, -254, -254, -254, -254,   65,
+     -254, -254, -254, -254, -254, -254, -254, -254, -254, -254,
+
+     -254, -254, -254, -254, -254, -254, -254, -254, -254, -254,
+     -254, -254, -254, -254, -254, -254, -254, -254, -254, -254,
+     -254,   65, -254, -254, -254, -254, -254, -254, -254, -254,
+     -254, -254, -254, -254, -254, -254, -254, -254, -254, -254,
+     -254, -254, -254, -254, -254, -254, -254, -254
+    },
+
+    {
+       15, -255, -255, -255, -255, -255, -255, -255, -255, -255,
+     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
+     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
+     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
+     -255, -255, -255, -255, -255, -255,   62, -255,  272,  272,
+
+      272,  272,  272,  272,  272,  272,  272,  272, -255, -255,
+     -255, -255, -255, -255, -255, -255, -255, -255, -255,   65,
+     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
+     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
+     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
+     -255,   65, -255, -255, -255, -255, -255, -255, -255, -255,
+     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
+     -255, -255, -255, -255, -255, -255, -255, -255
+    },
+
+    {
+       15, -256, -256, -256, -256, -256, -256, -256, -256, -256,
+     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
+
+     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
+     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
+     -256, -256, -256, -256, -256, -256,   62, -256,  273,  273,
+      273,  273,  273,  273,  273,  273,  273,  273, -256, -256,
+     -256, -256, -256, -256, -256, -256, -256, -256, -256,   65,
+     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
+     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
+     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
+     -256,   65, -256, -256, -256, -256, -256, -256, -256, -256,
+     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
+
+     -256, -256, -256, -256, -256, -256, -256, -256
+    },
+
+    {
+       15, -257, -257, -257, -257, -257, -257, -257, -257, -257,
+     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
+     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
+     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
+     -257, -257, -257, -257, -257, -257,   62, -257,  274,  274,
+      274,  274,  274,  274,  274,  274,  274,  274, -257, -257,
+     -257, -257, -257, -257, -257, -257, -257, -257, -257,   65,
+     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
+     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
+
+     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
+     -257,   65, -257, -257, -257, -257, -257, -257, -257, -257,
+     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
+     -257, -257, -257, -257, -257, -257, -257, -257
+    },
+
+    {
+       15, -258, -258, -258, -258, -258, -258, -258, -258, -258,
+     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
+     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
+     -258, -258,  275, -258, -258, -258, -258, -258, -258, -258,
+     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
+     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
+
+     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
+     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
+     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
+     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
+     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
+     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
+     -258, -258, -258, -258, -258, -258, -258, -258
+    },
+
+    {
+       15,  259,  259,  259,  259,  259,  259,  259,  259,  259,
+      259,  259,  259,  259,  259,  259,  259,  259,  259,  259,
+      259,  259,  259,  259,  259,  259,  259,  259,  259,  259,
+
+      259,  259,  259,  259,  259,  259,  259,  259,  259,  260,
+      259,  259,  259,  259,  259,  259,  259,  259,  259,  259,
+      259,  259,  259,  259,  259,  259,  259,  259,  259,  259,
+      259,  259,  259,  259,  259,  259,  259,  259,  259,  259,
+      259,  259,  259,  259,  259,  259,  259,  259,  259,  259,
+      259,  259,  259,  259,  259,  259,  259,  259,  259,  259,
+      259,  259,  259,  259,  259,  259,  259,  259,  259,  259,
+      259,  259,  259,  259,  259,  259,  259,  259,  259,  259,
+      259,  259,  259,  259,  259,  259,  259,  259,  259,  259,
+      259,  259,  259,  259,  259,  259,  259,  259
+
+    },
+
+    {
+       15, -260, -260, -260, -260, -260, -260, -260, -260, -260,
+     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
+     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
+     -260, -260, -260, -260, -260, -260, -260, -260, -260,  259,
+     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
+     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
+     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
+     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
+     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
+     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
+
+     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
+     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
+     -260, -260, -260, -260, -260, -260, -260, -260
+    },
+
+    {
+       15, -261, -261, -261, -261, -261, -261, -261, -261, -261,
+     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
+     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
+     -261, -261,  276, -261, -261, -261, -261, -261, -261, -261,
+     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
+     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
+     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
+
+     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
+     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
+     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
+     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
+     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
+     -261, -261, -261, -261, -261, -261, -261, -261
+    },
+
+    {
+       15, -262, -262, -262, -262, -262, -262, -262, -262, -262,
+     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
+     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
+     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
+
+     -262, -262, -262, -262, -262, -262,   62, -262,  277,  278,
+      278,  278,  278,  278,  278,  278,  278,  278, -262, -262,
+     -262, -262, -262, -262, -262, -262, -262, -262, -262,   65,
+     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
+     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
+     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
+     -262,   65, -262, -262, -262, -262, -262, -262, -262, -262,
+     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
+     -262, -262, -262, -262, -262, -262, -262, -262
+    },
+
+    {
+       15, -263, -263, -263, -263, -263, -263, -263, -263, -263,
+
+     -263, -263, -263, -263, -263, -263, -263, -263, -263, -263,
+     -263, -263, -263, -263, -263, -263, -263, -263, -263, -263,
+     -263, -263, -263, -263, -263, -263, -263, -263, -263, -263,
+     -263, -263, -263, -263, -263, -263,   62, -263,  279,  279,
+      279,  279,  279,  279,  279,  279,  279,  279, -263, -263,
+     -263, -263, -263, -263, -263, -263, -263, -263, -263,   65,
+     -263, -263, -263, -263, -263, -263, -263, -263, -263, -263,
+     -263, -263, -263, -263, -263, -263, -263, -263, -263, -263,
+     -263, -263, -263, -263, -263, -263, -263, -263, -263, -263,
+     -263,   65, -263, -263, -263, -263, -263, -263, -263, -263,
+
+     -263, -263, -263, -263, -263, -263, -263, -263, -263, -263,
+     -263, -263, -263, -263, -263, -263, -263, -263
+    },
+
+    {
+       15, -264, -264, -264, -264, -264, -264, -264, -264, -264,
+     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
+     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
+     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
+     -264, -264, -264, -264, -264, -264,   62, -264,  280,  280,
+      280,  280,  280,  280,  280,  280,  280,  280, -264, -264,
+     -264, -264, -264, -264, -264, -264, -264, -264, -264,   65,
+     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
+
+     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
+     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
+     -264,   65, -264, -264, -264, -264, -264, -264, -264, -264,
+     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
+     -264, -264, -264, -264, -264, -264, -264, -264
+    },
+
+    {
+       15, -265, -265, -265, -265, -265, -265, -265, -265, -265,
+     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
+     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
+     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
+     -265, -265, -265, -265, -265, -265,   62, -265,  281,  281,
+
+      281,  281,  281,  281,  281,  281,  281,  281, -265, -265,
+     -265, -265, -265, -265, -265, -265, -265, -265, -265,   65,
+     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
+     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
+     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
+     -265,   65, -265, -265, -265, -265, -265, -265, -265, -265,
+     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
+     -265, -265, -265, -265, -265, -265, -265, -265
+    },
+
+    {
+       15, -266, -266, -266, -266, -266, -266, -266, -266, -266,
+     -266, -266, -266, -266, -266, -266, -266, -266, -266, -266,
+
+     -266, -266, -266, -266, -266, -266, -266, -266, -266, -266,
+     -266, -266, -266, -266, -266, -266, -266, -266, -266, -266,
+     -266, -266, -266, -266, -266, -266,   62, -266,  282,  282,
+      282,  282,  282,  282,  282,  282,  282,  282, -266, -266,
+     -266, -266, -266, -266, -266, -266, -266, -266, -266,   65,
+     -266, -266, -266, -266, -266, -266, -266, -266, -266, -266,
+     -266, -266, -266, -266, -266, -266, -266, -266, -266, -266,
+     -266, -266, -266, -266, -266, -266, -266, -266, -266, -266,
+     -266,   65, -266, -266, -266, -266, -266, -266, -266, -266,
+     -266, -266, -266, -266, -266, -266, -266, -266, -266, -266,
+
+     -266, -266, -266, -266, -266, -266, -266, -266
+    },
+
+    {
+       15, -267, -267, -267, -267, -267, -267, -267, -267, -267,
+     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
+     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
+     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
+     -267, -267, -267, -267, -267, -267,   62, -267,  283,  283,
+      283,  283,  283,  283,  283,  283,  283,  283, -267, -267,
+     -267, -267, -267, -267, -267, -267, -267, -267, -267,   65,
+     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
+     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
+
+     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
+     -267,   65, -267, -267, -267, -267, -267, -267, -267, -267,
+     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
+     -267, -267, -267, -267, -267, -267, -267, -267
+    },
+
+    {
+       15, -268, -268, -268, -268, -268, -268, -268, -268, -268,
+     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
+     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
+     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
+     -268, -268, -268, -268, -268, -268,   62, -268,  284,  284,
+      284,  284,  284,  284,  284,  284,  284,  284, -268, -268,
+
+     -268, -268, -268, -268, -268, -268, -268, -268, -268,   65,
+     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
+     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
+     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
+     -268,   65, -268, -268, -268, -268, -268, -268, -268, -268,
+     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
+     -268, -268, -268, -268, -268, -268, -268, -268
+    },
+
+    {
+       15, -269, -269, -269, -269, -269, -269, -269, -269, -269,
+     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
+     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
+
+     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
+     -269, -269, -269, -269, -269, -269,   62, -269,  285,  285,
+      285,  285,  285,  285,  285,  285,  285,  285, -269, -269,
+     -269, -269, -269, -269, -269, -269, -269, -269, -269,   65,
+     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
+     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
+     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
+     -269,   65, -269, -269, -269, -269, -269, -269, -269, -269,
+     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
+     -269, -269, -269, -269, -269, -269, -269, -269
+
+    },
+
+    {
+       15, -270, -270, -270, -270, -270, -270, -270, -270, -270,
+     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
+     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
+     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
+     -270, -270, -270, -270, -270, -270,   62, -270,  286,  286,
+      286,  286,  286,  286,  286,  286,  286,  286, -270, -270,
+     -270, -270, -270, -270, -270, -270, -270, -270, -270,   65,
+     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
+     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
+     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
+
+     -270,   65, -270, -270, -270, -270, -270, -270, -270, -270,
+     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
+     -270, -270, -270, -270, -270, -270, -270, -270
+    },
+
+    {
+       15, -271, -271, -271, -271, -271, -271, -271, -271, -271,
+     -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
+     -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
+     -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
+     -271, -271, -271, -271, -271, -271,   62, -271,  287,  287,
+      287,  287,  287,  287,  287,  287,  287,  287, -271, -271,
+     -271, -271, -271, -271, -271, -271, -271, -271, -271,   65,
+
+     -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
+     -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
+     -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
+     -271,   65, -271, -271, -271, -271, -271, -271, -271, -271,
+     -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
+     -271, -271, -271, -271, -271, -271, -271, -271
+    },
+
+    {
+       15, -272, -272, -272, -272, -272, -272, -272, -272, -272,
+     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
+     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
+     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
+
+     -272, -272, -272, -272, -272, -272,   62, -272,  288,  288,
+      288,  288,  288,  288,  288,  288,  288,  288, -272, -272,
+     -272, -272, -272, -272, -272, -272, -272, -272, -272,   65,
+     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
+     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
+     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
+     -272,   65, -272, -272, -272, -272, -272, -272, -272, -272,
+     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
+     -272, -272, -272, -272, -272, -272, -272, -272
+    },
+
+    {
+       15, -273, -273, -273, -273, -273, -273, -273, -273, -273,
+
+     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
+     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
+     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
+     -273, -273, -273, -273, -273, -273,   62, -273,  289,  289,
+      289,  289,  289,  289,  289,  289,  289,  289, -273, -273,
+     -273, -273, -273, -273, -273, -273, -273, -273, -273,   65,
+     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
+     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
+     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
+     -273,   65, -273, -273, -273, -273, -273, -273, -273, -273,
+
+     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
+     -273, -273, -273, -273, -273, -273, -273, -273
+    },
+
+    {
+       15, -274, -274, -274, -274, -274, -274, -274, -274, -274,
+     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
+     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
+     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
+     -274, -274, -274, -274, -274, -274,   62, -274,  290,  290,
+      290,  290,  290,  290,  290,  290,  290,  290, -274, -274,
+     -274, -274, -274, -274, -274, -274, -274, -274, -274,   65,
+     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
+
+     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
+     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
+     -274,   65, -274, -274, -274, -274, -274, -274, -274, -274,
+     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
+     -274, -274, -274, -274, -274, -274, -274, -274
+    },
+
+    {
+       15, -275, -275, -275, -275, -275, -275, -275, -275, -275,
+     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
+     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
+     -275, -275,  291, -275, -275, -275, -275, -275, -275, -275,
+     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
+
+     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
+     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
+     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
+     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
+     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
+     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
+     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
+     -275, -275, -275, -275, -275, -275, -275, -275
+    },
+
+    {
+       15, -276, -276, -276, -276, -276, -276, -276, -276, -276,
+     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
+
+     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
+     -276, -276,  292, -276, -276, -276, -276, -276, -276, -276,
+     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
+     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
+     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
+     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
+     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
+     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
+     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
+     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
+
+     -276, -276, -276, -276, -276, -276, -276, -276
+    },
+
+    {
+       15, -277, -277, -277, -277, -277, -277, -277, -277, -277,
+     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
+     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
+     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
+     -277, -277, -277, -277, -277, -277,   62, -277,  293,  294,
+      294,  294,  294,  294,  294,  294,  294,  294, -277, -277,
+     -277, -277, -277, -277, -277, -277, -277, -277, -277,   65,
+     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
+     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
+
+     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
+     -277,   65, -277, -277, -277, -277, -277, -277, -277, -277,
+     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
+     -277, -277, -277, -277, -277, -277, -277, -277
+    },
+
+    {
+       15, -278, -278, -278, -278, -278, -278, -278, -278, -278,
+     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
+     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
+     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
+     -278, -278, -278, -278, -278, -278,   62, -278,  295,  295,
+      295,  295,  295,  295,  295,  295,  295,  295, -278, -278,
+
+     -278, -278, -278, -278, -278, -278, -278, -278, -278,   65,
+     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
+     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
+     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
+     -278,   65, -278, -278, -278, -278, -278, -278, -278, -278,
+     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
+     -278, -278, -278, -278, -278, -278, -278, -278
+    },
+
+    {
+       15, -279, -279, -279, -279, -279, -279, -279, -279, -279,
+     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
+     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
+
+     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
+     -279, -279, -279, -279, -279, -279,   62, -279,  296,  296,
+      296,  296,  296,  296,  296,  296,  296,  296, -279, -279,
+     -279, -279, -279, -279, -279, -279, -279, -279, -279,   65,
+     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
+     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
+     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
+     -279,   65, -279, -279, -279, -279, -279, -279, -279, -279,
+     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
+     -279, -279, -279, -279, -279, -279, -279, -279
+
+    },
+
+    {
+       15, -280, -280, -280, -280, -280, -280, -280, -280, -280,
+     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
+     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
+     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
+     -280, -280, -280, -280, -280, -280,   62, -280,  297,  297,
+      297,  297,  297,  297,  297,  297,  297,  297, -280, -280,
+     -280, -280, -280, -280, -280, -280, -280, -280, -280,   65,
+     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
+     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
+     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
+
+     -280,   65, -280, -280, -280, -280, -280, -280, -280, -280,
+     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
+     -280, -280, -280, -280, -280, -280, -280, -280
+    },
+
+    {
+       15, -281, -281, -281, -281, -281, -281, -281, -281, -281,
+     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
+     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
+     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
+     -281, -281, -281, -281, -281, -281,   62, -281,  298,  298,
+      298,  298,  298,  298,  298,  298,  298,  298, -281, -281,
+     -281, -281, -281, -281, -281, -281, -281, -281, -281,   65,
+
+     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
+     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
+     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
+     -281,   65, -281, -281, -281, -281, -281, -281, -281, -281,
+     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
+     -281, -281, -281, -281, -281, -281, -281, -281
+    },
+
+    {
+       15, -282, -282, -282, -282, -282, -282, -282, -282, -282,
+     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
+     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
+     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
+
+     -282, -282, -282, -282, -282, -282,   62, -282,  299,  299,
+      299,  299,  299,  299,  299,  299,  299,  299, -282, -282,
+     -282, -282, -282, -282, -282, -282, -282, -282, -282,   65,
+     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
+     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
+     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
+     -282,   65, -282, -282, -282, -282, -282, -282, -282, -282,
+     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
+     -282, -282, -282, -282, -282, -282, -282, -282
+    },
+
+    {
+       15, -283, -283, -283, -283, -283, -283, -283, -283, -283,
+
+     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
+     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
+     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
+     -283, -283, -283, -283, -283, -283,   62, -283,  300,  300,
+      300,  300,  300,  300,  300,  300,  300,  300, -283, -283,
+     -283, -283, -283, -283, -283, -283, -283, -283, -283,   65,
+     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
+     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
+     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
+     -283,   65, -283, -283, -283, -283, -283, -283, -283, -283,
+
+     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
+     -283, -283, -283, -283, -283, -283, -283, -283
+    },
+
+    {
+       15, -284, -284, -284, -284, -284, -284, -284, -284, -284,
+     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
+     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
+     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
+     -284, -284, -284, -284, -284, -284,   62, -284,  301,  301,
+      301,  301,  301,  301,  301,  301,  301,  301, -284, -284,
+     -284, -284, -284, -284, -284, -284, -284, -284, -284,   65,
+     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
+
+     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
+     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
+     -284,   65, -284, -284, -284, -284, -284, -284, -284, -284,
+     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
+     -284, -284, -284, -284, -284, -284, -284, -284
+    },
+
+    {
+       15, -285, -285, -285, -285, -285, -285, -285, -285, -285,
+     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
+     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
+     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
+     -285, -285, -285, -285, -285, -285,   62, -285,  302,  302,
+
+      302,  302,  302,  302,  302,  302,  302,  302, -285, -285,
+     -285, -285, -285, -285, -285, -285, -285, -285, -285,   65,
+     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
+     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
+     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
+     -285,   65, -285, -285, -285, -285, -285, -285, -285, -285,
+     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
+     -285, -285, -285, -285, -285, -285, -285, -285
+    },
+
+    {
+       15, -286, -286, -286, -286, -286, -286, -286, -286, -286,
+     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
+
+     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
+     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
+     -286, -286, -286, -286, -286, -286,   62, -286,  303,  303,
+      303,  303,  303,  303,  303,  303,  303,  303, -286, -286,
+     -286, -286, -286, -286, -286, -286, -286, -286, -286,   65,
+     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
+     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
+     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
+     -286,   65, -286, -286, -286, -286, -286, -286, -286, -286,
+     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
+
+     -286, -286, -286, -286, -286, -286, -286, -286
+    },
+
+    {
+       15, -287, -287, -287, -287, -287, -287, -287, -287, -287,
+     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
+     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
+     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
+     -287, -287, -287, -287, -287, -287,   62, -287,  304,  304,
+      304,  304,  304,  304,  304,  304,  304,  304, -287, -287,
+     -287, -287, -287, -287, -287, -287, -287, -287, -287,   65,
+     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
+     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
+
+     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
+     -287,   65, -287, -287, -287, -287, -287, -287, -287, -287,
+     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
+     -287, -287, -287, -287, -287, -287, -287, -287
+    },
+
+    {
+       15, -288, -288, -288, -288, -288, -288, -288, -288, -288,
+     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
+     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
+     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
+     -288, -288, -288, -288, -288, -288,   62, -288,  305,  305,
+      305,  305,  305,  305,  305,  305,  305,  305, -288, -288,
+
+     -288, -288, -288, -288, -288, -288, -288, -288, -288,   65,
+     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
+     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
+     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
+     -288,   65, -288, -288, -288, -288, -288, -288, -288, -288,
+     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
+     -288, -288, -288, -288, -288, -288, -288, -288
+    },
+
+    {
+       15, -289, -289, -289, -289, -289, -289, -289, -289, -289,
+     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
+     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
+
+     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
+     -289, -289, -289, -289, -289, -289,   62, -289,  306,  306,
+      306,  306,  306,  306,  306,  306,  306,  306, -289, -289,
+     -289, -289, -289, -289, -289, -289, -289, -289, -289,   65,
+     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
+     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
+     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
+     -289,   65, -289, -289, -289, -289, -289, -289, -289, -289,
+     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
+     -289, -289, -289, -289, -289, -289, -289, -289
+
+    },
+
+    {
+       15, -290, -290, -290, -290, -290, -290, -290, -290, -290,
+     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
+     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
+     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
+     -290, -290, -290, -290, -290, -290,   62, -290,  307,  307,
+      307,  307,  307,  307,  307,  307,  307,  307, -290, -290,
+     -290, -290, -290, -290, -290, -290, -290, -290, -290,   65,
+     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
+     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
+     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
+
+     -290,   65, -290, -290, -290, -290, -290, -290, -290, -290,
+     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
+     -290, -290, -290, -290, -290, -290, -290, -290
+    },
+
+    {
+       15, -291, -291, -291, -291, -291, -291, -291, -291, -291,
+     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
+     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
+     -291, -291,  308, -291, -291, -291, -291, -291, -291, -291,
+     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
+     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
+     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
+
+     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
+     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
+     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
+     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
+     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
+     -291, -291, -291, -291, -291, -291, -291, -291
+    },
+
+    {
+       15, -292, -292, -292, -292, -292, -292, -292, -292, -292,
+     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
+     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
+     -292, -292,  309, -292, -292, -292, -292, -292, -292, -292,
+
+     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
+     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
+     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
+     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
+     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
+     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
+     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
+     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
+     -292, -292, -292, -292, -292, -292, -292, -292
+    },
+
+    {
+       15, -293, -293, -293, -293, -293, -293, -293, -293, -293,
+
+     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
+     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
+     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
+     -293, -293, -293, -293, -293, -293,   62, -293,  310,  311,
+      311,  311,  311,  311,  311,  311,  311,  311, -293, -293,
+     -293, -293, -293, -293, -293, -293, -293, -293, -293,   65,
+     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
+     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
+     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
+     -293,   65, -293, -293, -293, -293, -293, -293, -293, -293,
+
+     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
+     -293, -293, -293, -293, -293, -293, -293, -293
+    },
+
+    {
+       15, -294, -294, -294, -294, -294, -294, -294, -294, -294,
+     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
+     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
+     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
+     -294, -294, -294, -294, -294, -294,   62, -294,  312,  312,
+      312,  312,  312,  312,  312,  312,  312,  312, -294, -294,
+     -294, -294, -294, -294, -294, -294, -294, -294, -294,   65,
+     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
+
+     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
+     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
+     -294,   65, -294, -294, -294, -294, -294, -294, -294, -294,
+     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
+     -294, -294, -294, -294, -294, -294, -294, -294
+    },
+
+    {
+       15, -295, -295, -295, -295, -295, -295, -295, -295, -295,
+     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
+     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
+     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
+     -295, -295, -295, -295, -295, -295,   62, -295,  313,  313,
+
+      313,  313,  313,  313,  313,  313,  313,  313, -295, -295,
+     -295, -295, -295, -295, -295, -295, -295, -295, -295,   65,
+     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
+     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
+     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
+     -295,   65, -295, -295, -295, -295, -295, -295, -295, -295,
+     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
+     -295, -295, -295, -295, -295, -295, -295, -295
+    },
+
+    {
+       15, -296, -296, -296, -296, -296, -296, -296, -296, -296,
+     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
+
+     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
+     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
+     -296, -296, -296, -296, -296, -296,   62, -296,  314,  314,
+      314,  314,  314,  314,  314,  314,  314,  314, -296, -296,
+     -296, -296, -296, -296, -296, -296, -296, -296, -296,   65,
+     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
+     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
+     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
+     -296,   65, -296, -296, -296, -296, -296, -296, -296, -296,
+     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
+
+     -296, -296, -296, -296, -296, -296, -296, -296
+    },
+
+    {
+       15, -297, -297, -297, -297, -297, -297, -297, -297, -297,
+     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
+     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
+     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
+     -297, -297, -297, -297, -297, -297,   62, -297,  315,  315,
+      315,  315,  315,  315,  315,  315,  315,  315, -297, -297,
+     -297, -297, -297, -297, -297, -297, -297, -297, -297,   65,
+     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
+     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
+
+     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
+     -297,   65, -297, -297, -297, -297, -297, -297, -297, -297,
+     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
+     -297, -297, -297, -297, -297, -297, -297, -297
+    },
+
+    {
+       15, -298, -298, -298, -298, -298, -298, -298, -298, -298,
+     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
+     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
+     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
+     -298, -298, -298, -298, -298, -298,   62, -298,  316,  316,
+      316,  316,  316,  316,  316,  316,  316,  316, -298, -298,
+
+     -298, -298, -298, -298, -298, -298, -298, -298, -298,   65,
+     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
+     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
+     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
+     -298,   65, -298, -298, -298, -298, -298, -298, -298, -298,
+     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
+     -298, -298, -298, -298, -298, -298, -298, -298
+    },
+
+    {
+       15, -299, -299, -299, -299, -299, -299, -299, -299, -299,
+     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
+     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
+
+     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
+     -299, -299, -299, -299, -299, -299,   62, -299,  317,  317,
+      317,  317,  317,  317,  317,  317,  317,  317, -299, -299,
+     -299, -299, -299, -299, -299, -299, -299, -299, -299,   65,
+     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
+     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
+     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
+     -299,   65, -299, -299, -299, -299, -299, -299, -299, -299,
+     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
+     -299, -299, -299, -299, -299, -299, -299, -299
+
+    },
+
+    {
+       15, -300, -300, -300, -300, -300, -300, -300, -300, -300,
+     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
+     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
+     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
+     -300, -300, -300, -300, -300, -300,   62, -300,  318,  318,
+      318,  318,  318,  318,  318,  318,  318,  318, -300, -300,
+     -300, -300, -300, -300, -300, -300, -300, -300, -300,   65,
+     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
+     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
+     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
+
+     -300,   65, -300, -300, -300, -300, -300, -300, -300, -300,
+     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
+     -300, -300, -300, -300, -300, -300, -300, -300
+    },
+
+    {
+       15, -301, -301, -301, -301, -301, -301, -301, -301, -301,
+     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
+     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
+     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
+     -301, -301, -301, -301, -301, -301,   62, -301,  319,  319,
+      319,  319,  319,  319,  319,  319,  319,  319, -301, -301,
+     -301, -301, -301, -301, -301, -301, -301, -301, -301,   65,
+
+     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
+     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
+     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
+     -301,   65, -301, -301, -301, -301, -301, -301, -301, -301,
+     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
+     -301, -301, -301, -301, -301, -301, -301, -301
+    },
+
+    {
+       15, -302, -302, -302, -302, -302, -302, -302, -302, -302,
+     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
+     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
+     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
+
+     -302, -302, -302, -302, -302, -302,   62, -302,  320,  320,
+      320,  320,  320,  320,  320,  320,  320,  320, -302, -302,
+     -302, -302, -302, -302, -302, -302, -302, -302, -302,   65,
+     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
+     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
+     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
+     -302,   65, -302, -302, -302, -302, -302, -302, -302, -302,
+     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
+     -302, -302, -302, -302, -302, -302, -302, -302
+    },
+
+    {
+       15, -303, -303, -303, -303, -303, -303, -303, -303, -303,
+
+     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
+     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
+     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
+     -303, -303, -303, -303, -303, -303,   62, -303,  321,  321,
+      321,  321,  321,  321,  321,  321,  321,  321, -303, -303,
+     -303, -303, -303, -303, -303, -303, -303, -303, -303,   65,
+     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
+     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
+     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
+     -303,   65, -303, -303, -303, -303, -303, -303, -303, -303,
+
+     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
+     -303, -303, -303, -303, -303, -303, -303, -303
+    },
+
+    {
+       15, -304, -304, -304, -304, -304, -304, -304, -304, -304,
+     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
+     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
+     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
+     -304, -304, -304, -304, -304, -304,   62, -304,  322,  322,
+      322,  322,  322,  322,  322,  322,  322,  322, -304, -304,
+     -304, -304, -304, -304, -304, -304, -304, -304, -304,   65,
+     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
+
+     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
+     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
+     -304,   65, -304, -304, -304, -304, -304, -304, -304, -304,
+     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
+     -304, -304, -304, -304, -304, -304, -304, -304
+    },
+
+    {
+       15, -305, -305, -305, -305, -305, -305, -305, -305, -305,
+     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
+     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
+     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
+     -305, -305, -305, -305, -305, -305,   62, -305,  323,  323,
+
+      323,  323,  323,  323,  323,  323,  323,  323, -305, -305,
+     -305, -305, -305, -305, -305, -305, -305, -305, -305,   65,
+     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
+     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
+     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
+     -305,   65, -305, -305, -305, -305, -305, -305, -305, -305,
+     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
+     -305, -305, -305, -305, -305, -305, -305, -305
+    },
+
+    {
+       15, -306, -306, -306, -306, -306, -306, -306, -306, -306,
+     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
+
+     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
+     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
+     -306, -306, -306, -306, -306, -306,   62, -306,  324,  324,
+      324,  324,  324,  324,  324,  324,  324,  324, -306, -306,
+     -306, -306, -306, -306, -306, -306, -306, -306, -306,   65,
+     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
+     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
+     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
+     -306,   65, -306, -306, -306, -306, -306, -306, -306, -306,
+     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
+
+     -306, -306, -306, -306, -306, -306, -306, -306
+    },
+
+    {
+       15, -307, -307, -307, -307, -307, -307, -307, -307, -307,
+     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
+     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
+     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
+     -307, -307, -307, -307, -307, -307,   62, -307,  325,  325,
+      325,  325,  325,  325,  325,  325,  325,  325, -307, -307,
+     -307, -307, -307, -307, -307, -307, -307, -307, -307,   65,
+     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
+     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
+
+     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
+     -307,   65, -307, -307, -307, -307, -307, -307, -307, -307,
+     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
+     -307, -307, -307, -307, -307, -307, -307, -307
+    },
+
+    {
+       15, -308, -308, -308, -308, -308, -308, -308, -308, -308,
+     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
+     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
+     -308, -308,  326, -308, -308, -308, -308, -308, -308, -308,
+     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
+     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
+
+     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
+     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
+     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
+     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
+     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
+     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
+     -308, -308, -308, -308, -308, -308, -308, -308
+    },
+
+    {
+       15, -309, -309, -309, -309, -309, -309, -309, -309, -309,
+     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
+     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
+
+     -309, -309,  327, -309, -309, -309, -309, -309, -309, -309,
+     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
+     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
+     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
+     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
+     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
+     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
+     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
+     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
+     -309, -309, -309, -309, -309, -309, -309, -309
+
+    },
+
+    {
+       15, -310, -310, -310, -310, -310, -310, -310, -310, -310,
+     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
+     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
+     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
+     -310, -310, -310, -310, -310, -310,   62, -310,  328,  329,
+      329,  329,  329,  329,  329,  329,  329,  329, -310, -310,
+     -310, -310, -310, -310, -310, -310, -310, -310, -310,   65,
+     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
+     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
+     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
+
+     -310,   65, -310, -310, -310, -310, -310, -310, -310, -310,
+     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
+     -310, -310, -310, -310, -310, -310, -310, -310
+    },
+
+    {
+       15, -311, -311, -311, -311, -311, -311, -311, -311, -311,
+     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
+     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
+     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
+     -311, -311, -311, -311, -311, -311,   62, -311,  330,  330,
+      330,  330,  330,  330,  330,  330,  330,  330, -311, -311,
+     -311, -311, -311, -311, -311, -311, -311, -311, -311,   65,
+
+     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
+     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
+     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
+     -311,   65, -311, -311, -311, -311, -311, -311, -311, -311,
+     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
+     -311, -311, -311, -311, -311, -311, -311, -311
+    },
+
+    {
+       15, -312, -312, -312, -312, -312, -312, -312, -312, -312,
+     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
+     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
+     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
+
+     -312, -312, -312, -312, -312, -312,   62, -312,  331,  331,
+      331,  331,  331,  331,  331,  331,  331,  331, -312, -312,
+     -312, -312, -312, -312, -312, -312, -312, -312, -312,   65,
+     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
+     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
+     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
+     -312,   65, -312, -312, -312, -312, -312, -312, -312, -312,
+     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
+     -312, -312, -312, -312, -312, -312, -312, -312
+    },
+
+    {
+       15, -313, -313, -313, -313, -313, -313, -313, -313, -313,
+
+     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
+     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
+     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
+     -313, -313, -313, -313, -313, -313,   62, -313,  332,  332,
+      332,  332,  332,  332,  332,  332,  332,  332, -313, -313,
+     -313, -313, -313, -313, -313, -313, -313, -313, -313,   65,
+     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
+     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
+     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
+     -313,   65, -313, -313, -313, -313, -313, -313, -313, -313,
+
+     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
+     -313, -313, -313, -313, -313, -313, -313, -313
+    },
+
+    {
+       15, -314, -314, -314, -314, -314, -314, -314, -314, -314,
+     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
+     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
+     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
+     -314, -314, -314, -314, -314, -314,   62, -314,  333,  333,
+      333,  333,  333,  333,  333,  333,  333,  333, -314, -314,
+     -314, -314, -314, -314, -314, -314, -314, -314, -314,   65,
+     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
+
+     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
+     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
+     -314,   65, -314, -314, -314, -314, -314, -314, -314, -314,
+     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
+     -314, -314, -314, -314, -314, -314, -314, -314
+    },
+
+    {
+       15, -315, -315, -315, -315, -315, -315, -315, -315, -315,
+     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
+     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
+     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
+     -315, -315, -315, -315, -315, -315,   62, -315,  334,  334,
+
+      334,  334,  334,  334,  334,  334,  334,  334, -315, -315,
+     -315, -315, -315, -315, -315, -315, -315, -315, -315,   65,
+     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
+     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
+     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
+     -315,   65, -315, -315, -315, -315, -315, -315, -315, -315,
+     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
+     -315, -315, -315, -315, -315, -315, -315, -315
+    },
+
+    {
+       15, -316, -316, -316, -316, -316, -316, -316, -316, -316,
+     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
+
+     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
+     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
+     -316, -316, -316, -316, -316, -316,   62, -316,  335,  335,
+      335,  335,  335,  335,  335,  335,  335,  335, -316, -316,
+     -316, -316, -316, -316, -316, -316, -316, -316, -316,   65,
+     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
+     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
+     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
+     -316,   65, -316, -316, -316, -316, -316, -316, -316, -316,
+     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
+
+     -316, -316, -316, -316, -316, -316, -316, -316
+    },
+
+    {
+       15, -317, -317, -317, -317, -317, -317, -317, -317, -317,
+     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
+     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
+     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
+     -317, -317, -317, -317, -317, -317,   62, -317,  336,  336,
+      336,  336,  336,  336,  336,  336,  336,  336, -317, -317,
+     -317, -317, -317, -317, -317, -317, -317, -317, -317,   65,
+     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
+     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
+
+     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
+     -317,   65, -317, -317, -317, -317, -317, -317, -317, -317,
+     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
+     -317, -317, -317, -317, -317, -317, -317, -317
+    },
+
+    {
+       15, -318, -318, -318, -318, -318, -318, -318, -318, -318,
+     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
+     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
+     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
+     -318, -318, -318, -318, -318, -318,   62, -318,  337,  337,
+      337,  337,  337,  337,  337,  337,  337,  337, -318, -318,
+
+     -318, -318, -318, -318, -318, -318, -318, -318, -318,   65,
+     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
+     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
+     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
+     -318,   65, -318, -318, -318, -318, -318, -318, -318, -318,
+     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
+     -318, -318, -318, -318, -318, -318, -318, -318
+    },
+
+    {
+       15, -319, -319, -319, -319, -319, -319, -319, -319, -319,
+     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
+     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
+
+     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
+     -319, -319, -319, -319, -319, -319,   62, -319,  338,  338,
+      338,  338,  338,  338,  338,  338,  338,  338, -319, -319,
+     -319, -319, -319, -319, -319, -319, -319, -319, -319,   65,
+     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
+     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
+     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
+     -319,   65, -319, -319, -319, -319, -319, -319, -319, -319,
+     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
+     -319, -319, -319, -319, -319, -319, -319, -319
+
+    },
+
+    {
+       15, -320, -320, -320, -320, -320, -320, -320, -320, -320,
+     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
+     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
+     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
+     -320, -320, -320, -320, -320, -320,   62, -320,  339,  339,
+      339,  339,  339,  339,  339,  339,  339,  339, -320, -320,
+     -320, -320, -320, -320, -320, -320, -320, -320, -320,   65,
+     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
+     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
+     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
+
+     -320,   65, -320, -320, -320, -320, -320, -320, -320, -320,
+     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
+     -320, -320, -320, -320, -320, -320, -320, -320
+    },
+
+    {
+       15, -321, -321, -321, -321, -321, -321, -321, -321, -321,
+     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
+     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
+     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
+     -321, -321, -321, -321, -321, -321,   62, -321,  340,  340,
+      340,  340,  340,  340,  340,  340,  340,  340, -321, -321,
+     -321, -321, -321, -321, -321, -321, -321, -321, -321,   65,
+
+     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
+     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
+     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
+     -321,   65, -321, -321, -321, -321, -321, -321, -321, -321,
+     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
+     -321, -321, -321, -321, -321, -321, -321, -321
+    },
+
+    {
+       15, -322, -322, -322, -322, -322, -322, -322, -322, -322,
+     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
+     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
+     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
+
+     -322, -322, -322, -322, -322, -322,   62, -322,  341,  341,
+      341,  341,  341,  341,  341,  341,  341,  341, -322, -322,
+     -322, -322, -322, -322, -322, -322, -322, -322, -322,   65,
+     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
+     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
+     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
+     -322,   65, -322, -322, -322, -322, -322, -322, -322, -322,
+     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
+     -322, -322, -322, -322, -322, -322, -322, -322
+    },
+
+    {
+       15, -323, -323, -323, -323, -323, -323, -323, -323, -323,
+
+     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
+     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
+     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
+     -323, -323, -323, -323, -323, -323,   62, -323,  342,  342,
+      342,  342,  342,  342,  342,  342,  342,  342, -323, -323,
+     -323, -323, -323, -323, -323, -323, -323, -323, -323,   65,
+     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
+     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
+     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
+     -323,   65, -323, -323, -323, -323, -323, -323, -323, -323,
+
+     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
+     -323, -323, -323, -323, -323, -323, -323, -323
+    },
+
+    {
+       15, -324, -324, -324, -324, -324, -324, -324, -324, -324,
+     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
+     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
+     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
+     -324, -324, -324, -324, -324, -324,   62, -324,  343,  343,
+      343,  343,  343,  343,  343,  343,  343,  343, -324, -324,
+     -324, -324, -324, -324, -324, -324, -324, -324, -324,   65,
+     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
+
+     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
+     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
+     -324,   65, -324, -324, -324, -324, -324, -324, -324, -324,
+     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
+     -324, -324, -324, -324, -324, -324, -324, -324
+    },
+
+    {
+       15, -325, -325, -325, -325, -325, -325, -325, -325, -325,
+     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
+     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
+     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
+     -325, -325, -325, -325, -325, -325,   62, -325,  344,  344,
+
+      344,  344,  344,  344,  344,  344,  344,  344, -325, -325,
+     -325, -325, -325, -325, -325, -325, -325, -325, -325,   65,
+     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
+     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
+     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
+     -325,   65, -325, -325, -325, -325, -325, -325, -325, -325,
+     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
+     -325, -325, -325, -325, -325, -325, -325, -325
+    },
+
+    {
+       15, -326, -326, -326, -326, -326, -326, -326, -326, -326,
+     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
+
+     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
+     -326, -326,  345, -326, -326, -326, -326, -326, -326, -326,
+     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
+     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
+     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
+     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
+     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
+     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
+     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
+     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
+
+     -326, -326, -326, -326, -326, -326, -326, -326
+    },
+
+    {
+       15, -327, -327, -327, -327, -327, -327, -327, -327, -327,
+     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
+     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
+     -327, -327,  346, -327, -327, -327, -327, -327, -327, -327,
+     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
+     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
+     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
+     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
+     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
+
+     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
+     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
+     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
+     -327, -327, -327, -327, -327, -327, -327, -327
+    },
+
+    {
+       15, -328, -328, -328, -328, -328, -328, -328, -328, -328,
+     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
+     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
+     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
+     -328, -328, -328, -328, -328, -328,   62, -328,  347,  348,
+      348,  348,  348,  348,  348,  348,  348,  348, -328, -328,
+
+     -328, -328, -328, -328, -328, -328, -328, -328, -328,   65,
+     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
+     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
+     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
+     -328,   65, -328, -328, -328, -328, -328, -328, -328, -328,
+     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
+     -328, -328, -328, -328, -328, -328, -328, -328
+    },
+
+    {
+       15, -329, -329, -329, -329, -329, -329, -329, -329, -329,
+     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
+     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
+
+     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
+     -329, -329, -329, -329, -329, -329,   62, -329,  349,  349,
+      349,  349,  349,  349,  349,  349,  349,  349, -329, -329,
+     -329, -329, -329, -329, -329, -329, -329, -329, -329,   65,
+     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
+     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
+     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
+     -329,   65, -329, -329, -329, -329, -329, -329, -329, -329,
+     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
+     -329, -329, -329, -329, -329, -329, -329, -329
+
+    },
+
+    {
+       15, -330, -330, -330, -330, -330, -330, -330, -330, -330,
+     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
+     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
+     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
+     -330, -330, -330, -330, -330, -330,   62, -330,  350,  350,
+      350,  350,  350,  350,  350,  350,  350,  350, -330, -330,
+     -330, -330, -330, -330, -330, -330, -330, -330, -330,   65,
+     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
+     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
+     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
+
+     -330,   65, -330, -330, -330, -330, -330, -330, -330, -330,
+     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
+     -330, -330, -330, -330, -330, -330, -330, -330
+    },
+
+    {
+       15, -331, -331, -331, -331, -331, -331, -331, -331, -331,
+     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
+     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
+     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
+     -331, -331, -331, -331, -331, -331,   62, -331,  351,  351,
+      351,  351,  351,  351,  351,  351,  351,  351, -331, -331,
+     -331, -331, -331, -331, -331, -331, -331, -331, -331,   65,
+
+     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
+     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
+     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
+     -331,   65, -331, -331, -331, -331, -331, -331, -331, -331,
+     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
+     -331, -331, -331, -331, -331, -331, -331, -331
+    },
+
+    {
+       15, -332, -332, -332, -332, -332, -332, -332, -332, -332,
+     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
+     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
+     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
+
+     -332, -332, -332, -332, -332, -332,   62, -332,  352,  352,
+      352,  352,  352,  352,  352,  352,  352,  352, -332, -332,
+     -332, -332, -332, -332, -332, -332, -332, -332, -332,   65,
+     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
+     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
+     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
+     -332,   65, -332, -332, -332, -332, -332, -332, -332, -332,
+     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
+     -332, -332, -332, -332, -332, -332, -332, -332
+    },
+
+    {
+       15, -333, -333, -333, -333, -333, -333, -333, -333, -333,
+
+     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
+     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
+     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
+     -333, -333, -333, -333, -333, -333,   62, -333,  353,  353,
+      353,  353,  353,  353,  353,  353,  353,  353, -333, -333,
+     -333, -333, -333, -333, -333, -333, -333, -333, -333,   65,
+     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
+     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
+     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
+     -333,   65, -333, -333, -333, -333, -333, -333, -333, -333,
+
+     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
+     -333, -333, -333, -333, -333, -333, -333, -333
+    },
+
+    {
+       15, -334, -334, -334, -334, -334, -334, -334, -334, -334,
+     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
+     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
+     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
+     -334, -334, -334, -334, -334, -334,   62, -334,  354,  354,
+      354,  354,  354,  354,  354,  354,  354,  354, -334, -334,
+     -334, -334, -334, -334, -334, -334, -334, -334, -334,   65,
+     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
+
+     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
+     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
+     -334,   65, -334, -334, -334, -334, -334, -334, -334, -334,
+     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
+     -334, -334, -334, -334, -334, -334, -334, -334
+    },
+
+    {
+       15, -335, -335, -335, -335, -335, -335, -335, -335, -335,
+     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
+     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
+     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
+     -335, -335, -335, -335, -335, -335,   62, -335,  355,  355,
+
+      355,  355,  355,  355,  355,  355,  355,  355, -335, -335,
+     -335, -335, -335, -335, -335, -335, -335, -335, -335,   65,
+     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
+     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
+     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
+     -335,   65, -335, -335, -335, -335, -335, -335, -335, -335,
+     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
+     -335, -335, -335, -335, -335, -335, -335, -335
+    },
+
+    {
+       15, -336, -336, -336, -336, -336, -336, -336, -336, -336,
+     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
+
+     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
+     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
+     -336, -336, -336, -336, -336, -336,   62, -336,  356,  356,
+      356,  356,  356,  356,  356,  356,  356,  356, -336, -336,
+     -336, -336, -336, -336, -336, -336, -336, -336, -336,   65,
+     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
+     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
+     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
+     -336,   65, -336, -336, -336, -336, -336, -336, -336, -336,
+     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
+
+     -336, -336, -336, -336, -336, -336, -336, -336
+    },
+
+    {
+       15, -337, -337, -337, -337, -337, -337, -337, -337, -337,
+     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
+     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
+     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
+     -337, -337, -337, -337, -337, -337,   62, -337,  357,  357,
+      357,  357,  357,  357,  357,  357,  357,  357, -337, -337,
+     -337, -337, -337, -337, -337, -337, -337, -337, -337,   65,
+     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
+     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
+
+     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
+     -337,   65, -337, -337, -337, -337, -337, -337, -337, -337,
+     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
+     -337, -337, -337, -337, -337, -337, -337, -337
+    },
+
+    {
+       15, -338, -338, -338, -338, -338, -338, -338, -338, -338,
+     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
+     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
+     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
+     -338, -338, -338, -338, -338, -338,   62, -338,  358,  358,
+      358,  358,  358,  358,  358,  358,  358,  358, -338, -338,
+
+     -338, -338, -338, -338, -338, -338, -338, -338, -338,   65,
+     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
+     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
+     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
+     -338,   65, -338, -338, -338, -338, -338, -338, -338, -338,
+     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
+     -338, -338, -338, -338, -338, -338, -338, -338
+    },
+
+    {
+       15, -339, -339, -339, -339, -339, -339, -339, -339, -339,
+     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
+     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
+
+     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
+     -339, -339, -339, -339, -339, -339,   62, -339,  359,  359,
+      359,  359,  359,  359,  359,  359,  359,  359, -339, -339,
+     -339, -339, -339, -339, -339, -339, -339, -339, -339,   65,
+     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
+     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
+     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
+     -339,   65, -339, -339, -339, -339, -339, -339, -339, -339,
+     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
+     -339, -339, -339, -339, -339, -339, -339, -339
+
+    },
+
+    {
+       15, -340, -340, -340, -340, -340, -340, -340, -340, -340,
+     -340, -340, -340, -340, -340, -340, -340, -340, -340, -340,
+     -340, -340, -340, -340, -340, -340, -340, -340, -340, -340,
+     -340, -340, -340, -340, -340, -340, -340, -340, -340, -340,
+     -340, -340, -340, -340, -340, -340,   62, -340,  360,  360,
+      360,  360,  360,  360,  360,  360,  360,  360, -340, -340,
+     -340, -340, -340, -340, -340, -340, -340, -340, -340,   65,
+     -340, -340, -340, -340, -340, -340, -340, -340, -340, -340,
+     -340, -340, -340, -340, -340, -340, -340, -340, -340, -340,
+     -340, -340, -340, -340, -340, -340, -340, -340, -340, -340,
+
+     -340,   65, -340, -340, -340, -340, -340, -340, -340, -340,
+     -340, -340, -340, -340, -340, -340, -340, -340, -340, -340,
+     -340, -340, -340, -340, -340, -340, -340, -340
+    },
+
+    {
+       15, -341, -341, -341, -341, -341, -341, -341, -341, -341,
+     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
+     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
+     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
+     -341, -341, -341, -341, -341, -341,   62, -341,  361,  361,
+      361,  361,  361,  361,  361,  361,  361,  361, -341, -341,
+     -341, -341, -341, -341, -341, -341, -341, -341, -341,   65,
+
+     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
+     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
+     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
+     -341,   65, -341, -341, -341, -341, -341, -341, -341, -341,
+     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
+     -341, -341, -341, -341, -341, -341, -341, -341
+    },
+
+    {
+       15, -342, -342, -342, -342, -342, -342, -342, -342, -342,
+     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
+     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
+     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
+
+     -342, -342, -342, -342, -342, -342,   62, -342,  362,  362,
+      362,  362,  362,  362,  362,  362,  362,  362, -342, -342,
+     -342, -342, -342, -342, -342, -342, -342, -342, -342,   65,
+     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
+     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
+     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
+     -342,   65, -342, -342, -342, -342, -342, -342, -342, -342,
+     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
+     -342, -342, -342, -342, -342, -342, -342, -342
+    },
+
+    {
+       15, -343, -343, -343, -343, -343, -343, -343, -343, -343,
+
+     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
+     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
+     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
+     -343, -343, -343, -343, -343, -343,   62, -343,  363,  363,
+      363,  363,  363,  363,  363,  363,  363,  363, -343, -343,
+     -343, -343, -343, -343, -343, -343, -343, -343, -343,   65,
+     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
+     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
+     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
+     -343,   65, -343, -343, -343, -343, -343, -343, -343, -343,
+
+     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
+     -343, -343, -343, -343, -343, -343, -343, -343
+    },
+
+    {
+       15, -344, -344, -344, -344, -344, -344, -344, -344, -344,
+     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
+     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
+     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
+     -344, -344, -344, -344, -344, -344,   62, -344,  364,  364,
+      364,  364,  364,  364,  364,  364,  364,  364, -344, -344,
+     -344, -344, -344, -344, -344, -344, -344, -344, -344,   65,
+     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
+
+     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
+     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
+     -344,   65, -344, -344, -344, -344, -344, -344, -344, -344,
+     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
+     -344, -344, -344, -344, -344, -344, -344, -344
+    },
+
+    {
+       15, -345, -345, -345, -345, -345, -345, -345, -345, -345,
+     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
+     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
+     -345, -345,  365, -345, -345, -345, -345, -345, -345, -345,
+     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
+
+     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
+     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
+     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
+     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
+     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
+     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
+     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
+     -345, -345, -345, -345, -345, -345, -345, -345
+    },
+
+    {
+       15, -346, -346, -346, -346, -346, -346, -346, -346, -346,
+     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
+
+     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
+     -346, -346,  366, -346, -346, -346, -346, -346, -346, -346,
+     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
+     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
+     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
+     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
+     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
+     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
+     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
+     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
+
+     -346, -346, -346, -346, -346, -346, -346, -346
+    },
+
+    {
+       15, -347, -347, -347, -347, -347, -347, -347, -347, -347,
+     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
+     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
+     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
+     -347, -347, -347, -347, -347, -347,   62, -347,  367,  368,
+      368,  368,  368,  368,  368,  368,  368,  368, -347, -347,
+     -347, -347, -347, -347, -347, -347, -347, -347, -347,   65,
+     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
+     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
+
+     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
+     -347,   65, -347, -347, -347, -347, -347, -347, -347, -347,
+     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
+     -347, -347, -347, -347, -347, -347, -347, -347
+    },
+
+    {
+       15, -348, -348, -348, -348, -348, -348, -348, -348, -348,
+     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
+     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
+     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
+     -348, -348, -348, -348, -348, -348,   62, -348,  369,  369,
+      369,  369,  369,  369,  369,  369,  369,  369, -348, -348,
+
+     -348, -348, -348, -348, -348, -348, -348, -348, -348,   65,
+     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
+     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
+     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
+     -348,   65, -348, -348, -348, -348, -348, -348, -348, -348,
+     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
+     -348, -348, -348, -348, -348, -348, -348, -348
+    },
+
+    {
+       15, -349, -349, -349, -349, -349, -349, -349, -349, -349,
+     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
+     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
+
+     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
+     -349, -349, -349, -349, -349, -349,   62, -349,  370,  370,
+      370,  370,  370,  370,  370,  370,  370,  370, -349, -349,
+     -349, -349, -349, -349, -349, -349, -349, -349, -349,   65,
+     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
+     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
+     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
+     -349,   65, -349, -349, -349, -349, -349, -349, -349, -349,
+     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
+     -349, -349, -349, -349, -349, -349, -349, -349
+
+    },
+
+    {
+       15, -350, -350, -350, -350, -350, -350, -350, -350, -350,
+     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
+     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
+     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
+     -350, -350, -350, -350, -350, -350,   62, -350,  371,  371,
+      371,  371,  371,  371,  371,  371,  371,  371, -350, -350,
+     -350, -350, -350, -350, -350, -350, -350, -350, -350,   65,
+     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
+     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
+     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
+
+     -350,   65, -350, -350, -350, -350, -350, -350, -350, -350,
+     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
+     -350, -350, -350, -350, -350, -350, -350, -350
+    },
+
+    {
+       15, -351, -351, -351, -351, -351, -351, -351, -351, -351,
+     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
+     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
+     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
+     -351, -351, -351, -351, -351, -351,   62, -351,  372,  372,
+      372,  372,  372,  372,  372,  372,  372,  372, -351, -351,
+     -351, -351, -351, -351, -351, -351, -351, -351, -351,   65,
+
+     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
+     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
+     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
+     -351,   65, -351, -351, -351, -351, -351, -351, -351, -351,
+     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
+     -351, -351, -351, -351, -351, -351, -351, -351
+    },
+
+    {
+       15, -352, -352, -352, -352, -352, -352, -352, -352, -352,
+     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
+     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
+     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
+
+     -352, -352, -352, -352, -352, -352,   62, -352,  373,  373,
+      373,  373,  373,  373,  373,  373,  373,  373, -352, -352,
+     -352, -352, -352, -352, -352, -352, -352, -352, -352,   65,
+     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
+     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
+     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
+     -352,   65, -352, -352, -352, -352, -352, -352, -352, -352,
+     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
+     -352, -352, -352, -352, -352, -352, -352, -352
+    },
+
+    {
+       15, -353, -353, -353, -353, -353, -353, -353, -353, -353,
+
+     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
+     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
+     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
+     -353, -353, -353, -353, -353, -353,   62, -353,  374,  374,
+      374,  374,  374,  374,  374,  374,  374,  374, -353, -353,
+     -353, -353, -353, -353, -353, -353, -353, -353, -353,   65,
+     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
+     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
+     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
+     -353,   65, -353, -353, -353, -353, -353, -353, -353, -353,
+
+     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
+     -353, -353, -353, -353, -353, -353, -353, -353
+    },
+
+    {
+       15, -354, -354, -354, -354, -354, -354, -354, -354, -354,
+     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
+     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
+     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
+     -354, -354, -354, -354, -354, -354,   62, -354,  375,  375,
+      375,  375,  375,  375,  375,  375,  375,  375, -354, -354,
+     -354, -354, -354, -354, -354, -354, -354, -354, -354,   65,
+     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
+
+     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
+     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
+     -354,   65, -354, -354, -354, -354, -354, -354, -354, -354,
+     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
+     -354, -354, -354, -354, -354, -354, -354, -354
+    },
+
+    {
+       15, -355, -355, -355, -355, -355, -355, -355, -355, -355,
+     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
+     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
+     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
+     -355, -355, -355, -355, -355, -355,   62, -355,  376,  376,
+
+      376,  376,  376,  376,  376,  376,  376,  376, -355, -355,
+     -355, -355, -355, -355, -355, -355, -355, -355, -355,   65,
+     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
+     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
+     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
+     -355,   65, -355, -355, -355, -355, -355, -355, -355, -355,
+     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
+     -355, -355, -355, -355, -355, -355, -355, -355
+    },
+
+    {
+       15, -356, -356, -356, -356, -356, -356, -356, -356, -356,
+     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
+
+     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
+     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
+     -356, -356, -356, -356, -356, -356,   62, -356,  377,  377,
+      377,  377,  377,  377,  377,  377,  377,  377, -356, -356,
+     -356, -356, -356, -356, -356, -356, -356, -356, -356,   65,
+     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
+     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
+     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
+     -356,   65, -356, -356, -356, -356, -356, -356, -356, -356,
+     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
+
+     -356, -356, -356, -356, -356, -356, -356, -356
+    },
+
+    {
+       15, -357, -357, -357, -357, -357, -357, -357, -357, -357,
+     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
+     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
+     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
+     -357, -357, -357, -357, -357, -357,   62, -357,  378,  378,
+      378,  378,  378,  378,  378,  378,  378,  378, -357, -357,
+     -357, -357, -357, -357, -357, -357, -357, -357, -357,   65,
+     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
+     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
+
+     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
+     -357,   65, -357, -357, -357, -357, -357, -357, -357, -357,
+     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
+     -357, -357, -357, -357, -357, -357, -357, -357
+    },
+
+    {
+       15, -358, -358, -358, -358, -358, -358, -358, -358, -358,
+     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
+     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
+     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
+     -358, -358, -358, -358, -358, -358,   62, -358,  379,  379,
+      379,  379,  379,  379,  379,  379,  379,  379, -358, -358,
+
+     -358, -358, -358, -358, -358, -358, -358, -358, -358,   65,
+     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
+     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
+     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
+     -358,   65, -358, -358, -358, -358, -358, -358, -358, -358,
+     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
+     -358, -358, -358, -358, -358, -358, -358, -358
+    },
+
+    {
+       15, -359, -359, -359, -359, -359, -359, -359, -359, -359,
+     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
+     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
+
+     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
+     -359, -359, -359, -359, -359, -359,   62, -359,  380,  380,
+      380,  380,  380,  380,  380,  380,  380,  380, -359, -359,
+     -359, -359, -359, -359, -359, -359, -359, -359, -359,   65,
+     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
+     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
+     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
+     -359,   65, -359, -359, -359, -359, -359, -359, -359, -359,
+     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
+     -359, -359, -359, -359, -359, -359, -359, -359
+
+    },
+
+    {
+       15, -360, -360, -360, -360, -360, -360, -360, -360, -360,
+     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
+     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
+     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
+     -360, -360, -360, -360, -360, -360,   62, -360,  381,  381,
+      381,  381,  381,  381,  381,  381,  381,  381, -360, -360,
+     -360, -360, -360, -360, -360, -360, -360, -360, -360,   65,
+     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
+     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
+     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
+
+     -360,   65, -360, -360, -360, -360, -360, -360, -360, -360,
+     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
+     -360, -360, -360, -360, -360, -360, -360, -360
+    },
+
+    {
+       15, -361, -361, -361, -361, -361, -361, -361, -361, -361,
+     -361, -361, -361, -361, -361, -361, -361, -361, -361, -361,
+     -361, -361, -361, -361, -361, -361, -361, -361, -361, -361,
+     -361, -361, -361, -361, -361, -361, -361, -361, -361, -361,
+     -361, -361, -361, -361, -361, -361,   62, -361,  382,  382,
+      382,  382,  382,  382,  382,  382,  382,  382, -361, -361,
+     -361, -361, -361, -361, -361, -361, -361, -361, -361,   65,
+
+     -361, -361, -361, -361, -361, -361, -361, -361, -361, -361,
+     -361, -361, -361, -361, -361, -361, -361, -361, -361, -361,
+     -361, -361, -361, -361, -361, -361, -361, -361, -361, -361,
+     -361,   65, -361, -361, -361, -361, -361, -361, -361, -361,
+     -361, -361, -361, -361, -361, -361, -361, -361, -361, -361,
+     -361, -361, -361, -361, -361, -361, -361, -361
+    },
+
+    {
+       15, -362, -362, -362, -362, -362, -362, -362, -362, -362,
+     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
+     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
+     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
+
+     -362, -362, -362, -362, -362, -362,   62, -362,  383,  383,
+      383,  383,  383,  383,  383,  383,  383,  383, -362, -362,
+     -362, -362, -362, -362, -362, -362, -362, -362, -362,   65,
+     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
+     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
+     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
+     -362,   65, -362, -362, -362, -362, -362, -362, -362, -362,
+     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
+     -362, -362, -362, -362, -362, -362, -362, -362
+    },
+
+    {
+       15, -363, -363, -363, -363, -363, -363, -363, -363, -363,
+
+     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
+     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
+     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
+     -363, -363, -363, -363, -363, -363,   62, -363,  384,  384,
+      384,  384,  384,  384,  384,  384,  384,  384, -363, -363,
+     -363, -363, -363, -363, -363, -363, -363, -363, -363,   65,
+     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
+     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
+     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
+     -363,   65, -363, -363, -363, -363, -363, -363, -363, -363,
+
+     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
+     -363, -363, -363, -363, -363, -363, -363, -363
+    },
+
+    {
+       15, -364, -364, -364, -364, -364, -364, -364, -364, -364,
+     -364, -364, -364, -364, -364, -364, -364, -364, -364, -364,
+     -364, -364, -364, -364, -364, -364, -364, -364, -364, -364,
+     -364, -364, -364, -364, -364, -364, -364, -364, -364, -364,
+     -364, -364, -364, -364, -364, -364,   62, -364,  385,  385,
+      385,  385,  385,  385,  385,  385,  385,  385, -364, -364,
+     -364, -364, -364, -364, -364, -364, -364, -364, -364,   65,
+     -364, -364, -364, -364, -364, -364, -364, -364, -364, -364,
+
+     -364, -364, -364, -364, -364, -364, -364, -364, -364, -364,
+     -364, -364, -364, -364, -364, -364, -364, -364, -364, -364,
+     -364,   65, -364, -364, -364, -364, -364, -364, -364, -364,
+     -364, -364, -364, -364, -364, -364, -364, -364, -364, -364,
+     -364, -364, -364, -364, -364, -364, -364, -364
+    },
+
+    {
+       15, -365, -365, -365, -365, -365, -365, -365, -365, -365,
+     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
+     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
+     -365, -365,  386, -365, -365, -365, -365, -365, -365, -365,
+     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
+
+     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
+     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
+     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
+     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
+     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
+     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
+     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
+     -365, -365, -365, -365, -365, -365, -365, -365
+    },
+
+    {
+       15, -366, -366, -366, -366, -366, -366, -366, -366, -366,
+     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
+
+     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
+     -366, -366,  387, -366, -366, -366, -366, -366, -366, -366,
+     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
+     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
+     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
+     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
+     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
+     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
+     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
+     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
+
+     -366, -366, -366, -366, -366, -366, -366, -366
+    },
+
+    {
+       15, -367, -367, -367, -367, -367, -367, -367, -367, -367,
+     -367, -367, -367, -367, -367, -367, -367, -367, -367, -367,
+     -367, -367, -367, -367, -367, -367, -367, -367, -367, -367,
+     -367, -367, -367, -367, -367, -367, -367, -367, -367, -367,
+     -367, -367, -367, -367, -367, -367,   62, -367,  388,  389,
+      389,  389,  389,  389,  389,  389,  389,  389, -367, -367,
+     -367, -367, -367, -367, -367, -367, -367, -367, -367,   65,
+     -367, -367, -367, -367, -367, -367, -367, -367, -367, -367,
+     -367, -367, -367, -367, -367, -367, -367, -367, -367, -367,
+
+     -367, -367, -367, -367, -367, -367, -367, -367, -367, -367,
+     -367,   65, -367, -367, -367, -367, -367, -367, -367, -367,
+     -367, -367, -367, -367, -367, -367, -367, -367, -367, -367,
+     -367, -367, -367, -367, -367, -367, -367, -367
+    },
+
+    {
+       15, -368, -368, -368, -368, -368, -368, -368, -368, -368,
+     -368, -368, -368, -368, -368, -368, -368, -368, -368, -368,
+     -368, -368, -368, -368, -368, -368, -368, -368, -368, -368,
+     -368, -368, -368, -368, -368, -368, -368, -368, -368, -368,
+     -368, -368, -368, -368, -368, -368,   62, -368,  390,  390,
+      390,  390,  390,  390,  390,  390,  390,  390, -368, -368,
+
+     -368, -368, -368, -368, -368, -368, -368, -368, -368,   65,
+     -368, -368, -368, -368, -368, -368, -368, -368, -368, -368,
+     -368, -368, -368, -368, -368, -368, -368, -368, -368, -368,
+     -368, -368, -368, -368, -368, -368, -368, -368, -368, -368,
+     -368,   65, -368, -368, -368, -368, -368, -368, -368, -368,
+     -368, -368, -368, -368, -368, -368, -368, -368, -368, -368,
+     -368, -368, -368, -368, -368, -368, -368, -368
+    },
+
+    {
+       15, -369, -369, -369, -369, -369, -369, -369, -369, -369,
+     -369, -369, -369, -369, -369, -369, -369, -369, -369, -369,
+     -369, -369, -369, -369, -369, -369, -369, -369, -369, -369,
+
+     -369, -369, -369, -369, -369, -369, -369, -369, -369, -369,
+     -369, -369, -369, -369, -369, -369,   62, -369,  391,  391,
+      391,  391,  391,  391,  391,  391,  391,  391, -369, -369,
+     -369, -369, -369, -369, -369, -369, -369, -369, -369,   65,
+     -369, -369, -369, -369, -369, -369, -369, -369, -369, -369,
+     -369, -369, -369, -369, -369, -369, -369, -369, -369, -369,
+     -369, -369, -369, -369, -369, -369, -369, -369, -369, -369,
+     -369,   65, -369, -369, -369, -369, -369, -369, -369, -369,
+     -369, -369, -369, -369, -369, -369, -369, -369, -369, -369,
+     -369, -369, -369, -369, -369, -369, -369, -369
+
+    },
+
+    {
+       15, -370, -370, -370, -370, -370, -370, -370, -370, -370,
+     -370, -370, -370, -370, -370, -370, -370, -370, -370, -370,
+     -370, -370, -370, -370, -370, -370, -370, -370, -370, -370,
+     -370, -370, -370, -370, -370, -370, -370, -370, -370, -370,
+     -370, -370, -370, -370, -370, -370,   62, -370,  392,  392,
+      392,  392,  392,  392,  392,  392,  392,  392, -370, -370,
+     -370, -370, -370, -370, -370, -370, -370, -370, -370,   65,
+     -370, -370, -370, -370, -370, -370, -370, -370, -370, -370,
+     -370, -370, -370, -370, -370, -370, -370, -370, -370, -370,
+     -370, -370, -370, -370, -370, -370, -370, -370, -370, -370,
+
+     -370,   65, -370, -370, -370, -370, -370, -370, -370, -370,
+     -370, -370, -370, -370, -370, -370, -370, -370, -370, -370,
+     -370, -370, -370, -370, -370, -370, -370, -370
+    },
+
+    {
+       15, -371, -371, -371, -371, -371, -371, -371, -371, -371,
+     -371, -371, -371, -371, -371, -371, -371, -371, -371, -371,
+     -371, -371, -371, -371, -371, -371, -371, -371, -371, -371,
+     -371, -371, -371, -371, -371, -371, -371, -371, -371, -371,
+     -371, -371, -371, -371, -371, -371,   62, -371,  393,  393,
+      393,  393,  393,  393,  393,  393,  393,  393, -371, -371,
+     -371, -371, -371, -371, -371, -371, -371, -371, -371,   65,
+
+     -371, -371, -371, -371, -371, -371, -371, -371, -371, -371,
+     -371, -371, -371, -371, -371, -371, -371, -371, -371, -371,
+     -371, -371, -371, -371, -371, -371, -371, -371, -371, -371,
+     -371,   65, -371, -371, -371, -371, -371, -371, -371, -371,
+     -371, -371, -371, -371, -371, -371, -371, -371, -371, -371,
+     -371, -371, -371, -371, -371, -371, -371, -371
+    },
+
+    {
+       15, -372, -372, -372, -372, -372, -372, -372, -372, -372,
+     -372, -372, -372, -372, -372, -372, -372, -372, -372, -372,
+     -372, -372, -372, -372, -372, -372, -372, -372, -372, -372,
+     -372, -372, -372, -372, -372, -372, -372, -372, -372, -372,
+
+     -372, -372, -372, -372, -372, -372,   62, -372,  394,  394,
+      394,  394,  394,  394,  394,  394,  394,  394, -372, -372,
+     -372, -372, -372, -372, -372, -372, -372, -372, -372,   65,
+     -372, -372, -372, -372, -372, -372, -372, -372, -372, -372,
+     -372, -372, -372, -372, -372, -372, -372, -372, -372, -372,
+     -372, -372, -372, -372, -372, -372, -372, -372, -372, -372,
+     -372,   65, -372, -372, -372, -372, -372, -372, -372, -372,
+     -372, -372, -372, -372, -372, -372, -372, -372, -372, -372,
+     -372, -372, -372, -372, -372, -372, -372, -372
+    },
+
+    {
+       15, -373, -373, -373, -373, -373, -373, -373, -373, -373,
+
+     -373, -373, -373, -373, -373, -373, -373, -373, -373, -373,
+     -373, -373, -373, -373, -373, -373, -373, -373, -373, -373,
+     -373, -373, -373, -373, -373, -373, -373, -373, -373, -373,
+     -373, -373, -373, -373, -373, -373,   62, -373,  395,  395,
+      395,  395,  395,  395,  395,  395,  395,  395, -373, -373,
+     -373, -373, -373, -373, -373, -373, -373, -373, -373,   65,
+     -373, -373, -373, -373, -373, -373, -373, -373, -373, -373,
+     -373, -373, -373, -373, -373, -373, -373, -373, -373, -373,
+     -373, -373, -373, -373, -373, -373, -373, -373, -373, -373,
+     -373,   65, -373, -373, -373, -373, -373, -373, -373, -373,
+
+     -373, -373, -373, -373, -373, -373, -373, -373, -373, -373,
+     -373, -373, -373, -373, -373, -373, -373, -373
+    },
+
+    {
+       15, -374, -374, -374, -374, -374, -374, -374, -374, -374,
+     -374, -374, -374, -374, -374, -374, -374, -374, -374, -374,
+     -374, -374, -374, -374, -374, -374, -374, -374, -374, -374,
+     -374, -374, -374, -374, -374, -374, -374, -374, -374, -374,
+     -374, -374, -374, -374, -374, -374,   62, -374,  396,  396,
+      396,  396,  396,  396,  396,  396,  396,  396, -374, -374,
+     -374, -374, -374, -374, -374, -374, -374, -374, -374,   65,
+     -374, -374, -374, -374, -374, -374, -374, -374, -374, -374,
+
+     -374, -374, -374, -374, -374, -374, -374, -374, -374, -374,
+     -374, -374, -374, -374, -374, -374, -374, -374, -374, -374,
+     -374,   65, -374, -374, -374, -374, -374, -374, -374, -374,
+     -374, -374, -374, -374, -374, -374, -374, -374, -374, -374,
+     -374, -374, -374, -374, -374, -374, -374, -374
+    },
+
+    {
+       15, -375, -375, -375, -375, -375, -375, -375, -375, -375,
+     -375, -375, -375, -375, -375, -375, -375, -375, -375, -375,
+     -375, -375, -375, -375, -375, -375, -375, -375, -375, -375,
+     -375, -375, -375, -375, -375, -375, -375, -375, -375, -375,
+     -375, -375, -375, -375, -375, -375,   62, -375,  397,  397,
+
+      397,  397,  397,  397,  397,  397,  397,  397, -375, -375,
+     -375, -375, -375, -375, -375, -375, -375, -375, -375,   65,
+     -375, -375, -375, -375, -375, -375, -375, -375, -375, -375,
+     -375, -375, -375, -375, -375, -375, -375, -375, -375, -375,
+     -375, -375, -375, -375, -375, -375, -375, -375, -375, -375,
+     -375,   65, -375, -375, -375, -375, -375, -375, -375, -375,
+     -375, -375, -375, -375, -375, -375, -375, -375, -375, -375,
+     -375, -375, -375, -375, -375, -375, -375, -375
+    },
+
+    {
+       15, -376, -376, -376, -376, -376, -376, -376, -376, -376,
+     -376, -376, -376, -376, -376, -376, -376, -376, -376, -376,
+
+     -376, -376, -376, -376, -376, -376, -376, -376, -376, -376,
+     -376, -376, -376, -376, -376, -376, -376, -376, -376, -376,
+     -376, -376, -376, -376, -376, -376,   62, -376,  398,  398,
+      398,  398,  398,  398,  398,  398,  398,  398, -376, -376,
+     -376, -376, -376, -376, -376, -376, -376, -376, -376,   65,
+     -376, -376, -376, -376, -376, -376, -376, -376, -376, -376,
+     -376, -376, -376, -376, -376, -376, -376, -376, -376, -376,
+     -376, -376, -376, -376, -376, -376, -376, -376, -376, -376,
+     -376,   65, -376, -376, -376, -376, -376, -376, -376, -376,
+     -376, -376, -376, -376, -376, -376, -376, -376, -376, -376,
+
+     -376, -376, -376, -376, -376, -376, -376, -376
+    },
+
+    {
+       15, -377, -377, -377, -377, -377, -377, -377, -377, -377,
+     -377, -377, -377, -377, -377, -377, -377, -377, -377, -377,
+     -377, -377, -377, -377, -377, -377, -377, -377, -377, -377,
+     -377, -377, -377, -377, -377, -377, -377, -377, -377, -377,
+     -377, -377, -377, -377, -377, -377,   62, -377,  399,  399,
+      399,  399,  399,  399,  399,  399,  399,  399, -377, -377,
+     -377, -377, -377, -377, -377, -377, -377, -377, -377,   65,
+     -377, -377, -377, -377, -377, -377, -377, -377, -377, -377,
+     -377, -377, -377, -377, -377, -377, -377, -377, -377, -377,
+
+     -377, -377, -377, -377, -377, -377, -377, -377, -377, -377,
+     -377,   65, -377, -377, -377, -377, -377, -377, -377, -377,
+     -377, -377, -377, -377, -377, -377, -377, -377, -377, -377,
+     -377, -377, -377, -377, -377, -377, -377, -377
+    },
+
+    {
+       15, -378, -378, -378, -378, -378, -378, -378, -378, -378,
+     -378, -378, -378, -378, -378, -378, -378, -378, -378, -378,
+     -378, -378, -378, -378, -378, -378, -378, -378, -378, -378,
+     -378, -378, -378, -378, -378, -378, -378, -378, -378, -378,
+     -378, -378, -378, -378, -378, -378,   62, -378,  400,  400,
+      400,  400,  400,  400,  400,  400,  400,  400, -378, -378,
+
+     -378, -378, -378, -378, -378, -378, -378, -378, -378,   65,
+     -378, -378, -378, -378, -378, -378, -378, -378, -378, -378,
+     -378, -378, -378, -378, -378, -378, -378, -378, -378, -378,
+     -378, -378, -378, -378, -378, -378, -378, -378, -378, -378,
+     -378,   65, -378, -378, -378, -378, -378, -378, -378, -378,
+     -378, -378, -378, -378, -378, -378, -378, -378, -378, -378,
+     -378, -378, -378, -378, -378, -378, -378, -378
+    },
+
+    {
+       15, -379, -379, -379, -379, -379, -379, -379, -379, -379,
+     -379, -379, -379, -379, -379, -379, -379, -379, -379, -379,
+     -379, -379, -379, -379, -379, -379, -379, -379, -379, -379,
+
+     -379, -379, -379, -379, -379, -379, -379, -379, -379, -379,
+     -379, -379, -379, -379, -379, -379,   62, -379,  401,  401,
+      401,  401,  401,  401,  401,  401,  401,  401, -379, -379,
+     -379, -379, -379, -379, -379, -379, -379, -379, -379,   65,
+     -379, -379, -379, -379, -379, -379, -379, -379, -379, -379,
+     -379, -379, -379, -379, -379, -379, -379, -379, -379, -379,
+     -379, -379, -379, -379, -379, -379, -379, -379, -379, -379,
+     -379,   65, -379, -379, -379, -379, -379, -379, -379, -379,
+     -379, -379, -379, -379, -379, -379, -379, -379, -379, -379,
+     -379, -379, -379, -379, -379, -379, -379, -379
+
+    },
+
+    {
+       15, -380, -380, -380, -380, -380, -380, -380, -380, -380,
+     -380, -380, -380, -380, -380, -380, -380, -380, -380, -380,
+     -380, -380, -380, -380, -380, -380, -380, -380, -380, -380,
+     -380, -380, -380, -380, -380, -380, -380, -380, -380, -380,
+     -380, -380, -380, -380, -380, -380,   62, -380,  402,  402,
+      402,  402,  402,  402,  402,  402,  402,  402, -380, -380,
+     -380, -380, -380, -380, -380, -380, -380, -380, -380,   65,
+     -380, -380, -380, -380, -380, -380, -380, -380, -380, -380,
+     -380, -380, -380, -380, -380, -380, -380, -380, -380, -380,
+     -380, -380, -380, -380, -380, -380, -380, -380, -380, -380,
+
+     -380,   65, -380, -380, -380, -380, -380, -380, -380, -380,
+     -380, -380, -380, -380, -380, -380, -380, -380, -380, -380,
+     -380, -380, -380, -380, -380, -380, -380, -380
+    },
+
+    {
+       15, -381, -381, -381, -381, -381, -381, -381, -381, -381,
+     -381, -381, -381, -381, -381, -381, -381, -381, -381, -381,
+     -381, -381, -381, -381, -381, -381, -381, -381, -381, -381,
+     -381, -381, -381, -381, -381, -381, -381, -381, -381, -381,
+     -381, -381, -381, -381, -381, -381,   62, -381,  403,  403,
+      403,  403,  403,  403,  403,  403,  403,  403, -381, -381,
+     -381, -381, -381, -381, -381, -381, -381, -381, -381,   65,
+
+     -381, -381, -381, -381, -381, -381, -381, -381, -381, -381,
+     -381, -381, -381, -381, -381, -381, -381, -381, -381, -381,
+     -381, -381, -381, -381, -381, -381, -381, -381, -381, -381,
+     -381,   65, -381, -381, -381, -381, -381, -381, -381, -381,
+     -381, -381, -381, -381, -381, -381, -381, -381, -381, -381,
+     -381, -381, -381, -381, -381, -381, -381, -381
+    },
+
+    {
+       15, -382, -382, -382, -382, -382, -382, -382, -382, -382,
+     -382, -382, -382, -382, -382, -382, -382, -382, -382, -382,
+     -382, -382, -382, -382, -382, -382, -382, -382, -382, -382,
+     -382, -382, -382, -382, -382, -382, -382, -382, -382, -382,
+
+     -382, -382, -382, -382, -382, -382,   62, -382,  404,  404,
+      404,  404,  404,  404,  404,  404,  404,  404, -382, -382,
+     -382, -382, -382, -382, -382, -382, -382, -382, -382,   65,
+     -382, -382, -382, -382, -382, -382, -382, -382, -382, -382,
+     -382, -382, -382, -382, -382, -382, -382, -382, -382, -382,
+     -382, -382, -382, -382, -382, -382, -382, -382, -382, -382,
+     -382,   65, -382, -382, -382, -382, -382, -382, -382, -382,
+     -382, -382, -382, -382, -382, -382, -382, -382, -382, -382,
+     -382, -382, -382, -382, -382, -382, -382, -382
+    },
+
+    {
+       15, -383, -383, -383, -383, -383, -383, -383, -383, -383,
+
+     -383, -383, -383, -383, -383, -383, -383, -383, -383, -383,
+     -383, -383, -383, -383, -383, -383, -383, -383, -383, -383,
+     -383, -383, -383, -383, -383, -383, -383, -383, -383, -383,
+     -383, -383, -383, -383, -383, -383,   62, -383,  405,  405,
+      405,  405,  405,  405,  405,  405,  405,  405, -383, -383,
+     -383, -383, -383, -383, -383, -383, -383, -383, -383,   65,
+     -383, -383, -383, -383, -383, -383, -383, -383, -383, -383,
+     -383, -383, -383, -383, -383, -383, -383, -383, -383, -383,
+     -383, -383, -383, -383, -383, -383, -383, -383, -383, -383,
+     -383,   65, -383, -383, -383, -383, -383, -383, -383, -383,
+
+     -383, -383, -383, -383, -383, -383, -383, -383, -383, -383,
+     -383, -383, -383, -383, -383, -383, -383, -383
+    },
+
+    {
+       15, -384, -384, -384, -384, -384, -384, -384, -384, -384,
+     -384, -384, -384, -384, -384, -384, -384, -384, -384, -384,
+     -384, -384, -384, -384, -384, -384, -384, -384, -384, -384,
+     -384, -384, -384, -384, -384, -384, -384, -384, -384, -384,
+     -384, -384, -384, -384, -384, -384,   62, -384,  406,  406,
+      406,  406,  406,  406,  406,  406,  406,  406, -384, -384,
+     -384, -384, -384, -384, -384, -384, -384, -384, -384,   65,
+     -384, -384, -384, -384, -384, -384, -384, -384, -384, -384,
+
+     -384, -384, -384, -384, -384, -384, -384, -384, -384, -384,
+     -384, -384, -384, -384, -384, -384, -384, -384, -384, -384,
+     -384,   65, -384, -384, -384, -384, -384, -384, -384, -384,
+     -384, -384, -384, -384, -384, -384, -384, -384, -384, -384,
+     -384, -384, -384, -384, -384, -384, -384, -384
+    },
+
+    {
+       15, -385, -385, -385, -385, -385, -385, -385, -385, -385,
+     -385, -385, -385, -385, -385, -385, -385, -385, -385, -385,
+     -385, -385, -385, -385, -385, -385, -385, -385, -385, -385,
+     -385, -385, -385, -385, -385, -385, -385, -385, -385, -385,
+     -385, -385, -385, -385, -385, -385,   62, -385,  407,  407,
+
+      407,  407,  407,  407,  407,  407,  407,  407, -385, -385,
+     -385, -385, -385, -385, -385, -385, -385, -385, -385,   65,
+     -385, -385, -385, -385, -385, -385, -385, -385, -385, -385,
+     -385, -385, -385, -385, -385, -385, -385, -385, -385, -385,
+     -385, -385, -385, -385, -385, -385, -385, -385, -385, -385,
+     -385,   65, -385, -385, -385, -385, -385, -385, -385, -385,
+     -385, -385, -385, -385, -385, -385, -385, -385, -385, -385,
+     -385, -385, -385, -385, -385, -385, -385, -385
+    },
+
+    {
+       15, -386, -386, -386, -386, -386, -386, -386, -386, -386,
+     -386, -386, -386, -386, -386, -386, -386, -386, -386, -386,
+
+     -386, -386, -386, -386, -386, -386, -386, -386, -386, -386,
+     -386, -386,  408, -386, -386, -386, -386, -386, -386, -386,
+     -386, -386, -386, -386, -386, -386, -386, -386, -386, -386,
+     -386, -386, -386, -386, -386, -386, -386, -386, -386, -386,
+     -386, -386, -386, -386, -386, -386, -386, -386, -386, -386,
+     -386, -386, -386, -386, -386, -386, -386, -386, -386, -386,
+     -386, -386, -386, -386, -386, -386, -386, -386, -386, -386,
+     -386, -386, -386, -386, -386, -386, -386, -386, -386, -386,
+     -386, -386, -386, -386, -386, -386, -386, -386, -386, -386,
+     -386, -386, -386, -386, -386, -386, -386, -386, -386, -386,
+
+     -386, -386, -386, -386, -386, -386, -386, -386
+    },
+
+    {
+       15, -387, -387, -387, -387, -387, -387, -387, -387, -387,
+     -387, -387, -387, -387, -387, -387, -387, -387, -387, -387,
+     -387, -387, -387, -387, -387, -387, -387, -387, -387, -387,
+     -387, -387,  409, -387, -387, -387, -387, -387, -387, -387,
+     -387, -387, -387, -387, -387, -387, -387, -387, -387, -387,
+     -387, -387, -387, -387, -387, -387, -387, -387, -387, -387,
+     -387, -387, -387, -387, -387, -387, -387, -387, -387, -387,
+     -387, -387, -387, -387, -387, -387, -387, -387, -387, -387,
+     -387, -387, -387, -387, -387, -387, -387, -387, -387, -387,
+
+     -387, -387, -387, -387, -387, -387, -387, -387, -387, -387,
+     -387, -387, -387, -387, -387, -387, -387, -387, -387, -387,
+     -387, -387, -387, -387, -387, -387, -387, -387, -387, -387,
+     -387, -387, -387, -387, -387, -387, -387, -387
+    },
+
+    {
+       15, -388, -388, -388, -388, -388, -388, -388, -388, -388,
+     -388, -388, -388, -388, -388, -388, -388, -388, -388, -388,
+     -388, -388, -388, -388, -388, -388, -388, -388, -388, -388,
+     -388, -388, -388, -388, -388, -388, -388, -388, -388, -388,
+     -388, -388, -388, -388, -388, -388,   62, -388,  410,  411,
+      411,  411,  411,  411,  411,  411,  411,  411, -388, -388,
+
+     -388, -388, -388, -388, -388, -388, -388, -388, -388,   65,
+     -388, -388, -388, -388, -388, -388, -388, -388, -388, -388,
+     -388, -388, -388, -388, -388, -388, -388, -388, -388, -388,
+     -388, -388, -388, -388, -388, -388, -388, -388, -388, -388,
+     -388,   65, -388, -388, -388, -388, -388, -388, -388, -388,
+     -388, -388, -388, -388, -388, -388, -388, -388, -388, -388,
+     -388, -388, -388, -388, -388, -388, -388, -388
+    },
+
+    {
+       15, -389, -389, -389, -389, -389, -389, -389, -389, -389,
+     -389, -389, -389, -389, -389, -389, -389, -389, -389, -389,
+     -389, -389, -389, -389, -389, -389, -389, -389, -389, -389,
+
+     -389, -389, -389, -389, -389, -389, -389, -389, -389, -389,
+     -389, -389, -389, -389, -389, -389,   62, -389,  412,  412,
+      412,  412,  412,  412,  412,  412,  412,  412, -389, -389,
+     -389, -389, -389, -389, -389, -389, -389, -389, -389,   65,
+     -389, -389, -389, -389, -389, -389, -389, -389, -389, -389,
+     -389, -389, -389, -389, -389, -389, -389, -389, -389, -389,
+     -389, -389, -389, -389, -389, -389, -389, -389, -389, -389,
+     -389,   65, -389, -389, -389, -389, -389, -389, -389, -389,
+     -389, -389, -389, -389, -389, -389, -389, -389, -389, -389,
+     -389, -389, -389, -389, -389, -389, -389, -389
+
+    },
+
+    {
+       15, -390, -390, -390, -390, -390, -390, -390, -390, -390,
+     -390, -390, -390, -390, -390, -390, -390, -390, -390, -390,
+     -390, -390, -390, -390, -390, -390, -390, -390, -390, -390,
+     -390, -390, -390, -390, -390, -390, -390, -390, -390, -390,
+     -390, -390, -390, -390, -390, -390,   62, -390,  413,  413,
+      413,  413,  413,  413,  413,  413,  413,  413, -390, -390,
+     -390, -390, -390, -390, -390, -390, -390, -390, -390,   65,
+     -390, -390, -390, -390, -390, -390, -390, -390, -390, -390,
+     -390, -390, -390, -390, -390, -390, -390, -390, -390, -390,
+     -390, -390, -390, -390, -390, -390, -390, -390, -390, -390,
+
+     -390,   65, -390, -390, -390, -390, -390, -390, -390, -390,
+     -390, -390, -390, -390, -390, -390, -390, -390, -390, -390,
+     -390, -390, -390, -390, -390, -390, -390, -390
+    },
+
+    {
+       15, -391, -391, -391, -391, -391, -391, -391, -391, -391,
+     -391, -391, -391, -391, -391, -391, -391, -391, -391, -391,
+     -391, -391, -391, -391, -391, -391, -391, -391, -391, -391,
+     -391, -391, -391, -391, -391, -391, -391, -391, -391, -391,
+     -391, -391, -391, -391, -391, -391,   62, -391,  414,  414,
+      414,  414,  414,  414,  414,  414,  414,  414, -391, -391,
+     -391, -391, -391, -391, -391, -391, -391, -391, -391,   65,
+
+     -391, -391, -391, -391, -391, -391, -391, -391, -391, -391,
+     -391, -391, -391, -391, -391, -391, -391, -391, -391, -391,
+     -391, -391, -391, -391, -391, -391, -391, -391, -391, -391,
+     -391,   65, -391, -391, -391, -391, -391, -391, -391, -391,
+     -391, -391, -391, -391, -391, -391, -391, -391, -391, -391,
+     -391, -391, -391, -391, -391, -391, -391, -391
+    },
+
+    {
+       15, -392, -392, -392, -392, -392, -392, -392, -392, -392,
+     -392, -392, -392, -392, -392, -392, -392, -392, -392, -392,
+     -392, -392, -392, -392, -392, -392, -392, -392, -392, -392,
+     -392, -392, -392, -392, -392, -392, -392, -392, -392, -392,
+
+     -392, -392, -392, -392, -392, -392,   62, -392,  415,  415,
+      415,  415,  415,  415,  415,  415,  415,  415, -392, -392,
+     -392, -392, -392, -392, -392, -392, -392, -392, -392,   65,
+     -392, -392, -392, -392, -392, -392, -392, -392, -392, -392,
+     -392, -392, -392, -392, -392, -392, -392, -392, -392, -392,
+     -392, -392, -392, -392, -392, -392, -392, -392, -392, -392,
+     -392,   65, -392, -392, -392, -392, -392, -392, -392, -392,
+     -392, -392, -392, -392, -392, -392, -392, -392, -392, -392,
+     -392, -392, -392, -392, -392, -392, -392, -392
+    },
+
+    {
+       15, -393, -393, -393, -393, -393, -393, -393, -393, -393,
+
+     -393, -393, -393, -393, -393, -393, -393, -393, -393, -393,
+     -393, -393, -393, -393, -393, -393, -393, -393, -393, -393,
+     -393, -393, -393, -393, -393, -393, -393, -393, -393, -393,
+     -393, -393, -393, -393, -393, -393,   62, -393,  416,  416,
+      416,  416,  416,  416,  416,  416,  416,  416, -393, -393,
+     -393, -393, -393, -393, -393, -393, -393, -393, -393,   65,
+     -393, -393, -393, -393, -393, -393, -393, -393, -393, -393,
+     -393, -393, -393, -393, -393, -393, -393, -393, -393, -393,
+     -393, -393, -393, -393, -393, -393, -393, -393, -393, -393,
+     -393,   65, -393, -393, -393, -393, -393, -393, -393, -393,
+
+     -393, -393, -393, -393, -393, -393, -393, -393, -393, -393,
+     -393, -393, -393, -393, -393, -393, -393, -393
+    },
+
+    {
+       15, -394, -394, -394, -394, -394, -394, -394, -394, -394,
+     -394, -394, -394, -394, -394, -394, -394, -394, -394, -394,
+     -394, -394, -394, -394, -394, -394, -394, -394, -394, -394,
+     -394, -394, -394, -394, -394, -394, -394, -394, -394, -394,
+     -394, -394, -394, -394, -394, -394,   62, -394,  417,  417,
+      417,  417,  417,  417,  417,  417,  417,  417, -394, -394,
+     -394, -394, -394, -394, -394, -394, -394, -394, -394,   65,
+     -394, -394, -394, -394, -394, -394, -394, -394, -394, -394,
+
+     -394, -394, -394, -394, -394, -394, -394, -394, -394, -394,
+     -394, -394, -394, -394, -394, -394, -394, -394, -394, -394,
+     -394,   65, -394, -394, -394, -394, -394, -394, -394, -394,
+     -394, -394, -394, -394, -394, -394, -394, -394, -394, -394,
+     -394, -394, -394, -394, -394, -394, -394, -394
+    },
+
+    {
+       15, -395, -395, -395, -395, -395, -395, -395, -395, -395,
+     -395, -395, -395, -395, -395, -395, -395, -395, -395, -395,
+     -395, -395, -395, -395, -395, -395, -395, -395, -395, -395,
+     -395, -395, -395, -395, -395, -395, -395, -395, -395, -395,
+     -395, -395, -395, -395, -395, -395,   62, -395,  418,  418,
+
+      418,  418,  418,  418,  418,  418,  418,  418, -395, -395,
+     -395, -395, -395, -395, -395, -395, -395, -395, -395,   65,
+     -395, -395, -395, -395, -395, -395, -395, -395, -395, -395,
+     -395, -395, -395, -395, -395, -395, -395, -395, -395, -395,
+     -395, -395, -395, -395, -395, -395, -395, -395, -395, -395,
+     -395,   65, -395, -395, -395, -395, -395, -395, -395, -395,
+     -395, -395, -395, -395, -395, -395, -395, -395, -395, -395,
+     -395, -395, -395, -395, -395, -395, -395, -395
+    },
+
+    {
+       15, -396, -396, -396, -396, -396, -396, -396, -396, -396,
+     -396, -396, -396, -396, -396, -396, -396, -396, -396, -396,
+
+     -396, -396, -396, -396, -396, -396, -396, -396, -396, -396,
+     -396, -396, -396, -396, -396, -396, -396, -396, -396, -396,
+     -396, -396, -396, -396, -396, -396,   62, -396,  419,  419,
+      419,  419,  419,  419,  419,  419,  419,  419, -396, -396,
+     -396, -396, -396, -396, -396, -396, -396, -396, -396,   65,
+     -396, -396, -396, -396, -396, -396, -396, -396, -396, -396,
+     -396, -396, -396, -396, -396, -396, -396, -396, -396, -396,
+     -396, -396, -396, -396, -396, -396, -396, -396, -396, -396,
+     -396,   65, -396, -396, -396, -396, -396, -396, -396, -396,
+     -396, -396, -396, -396, -396, -396, -396, -396, -396, -396,
+
+     -396, -396, -396, -396, -396, -396, -396, -396
+    },
+
+    {
+       15, -397, -397, -397, -397, -397, -397, -397, -397, -397,
+     -397, -397, -397, -397, -397, -397, -397, -397, -397, -397,
+     -397, -397, -397, -397, -397, -397, -397, -397, -397, -397,
+     -397, -397, -397, -397, -397, -397, -397, -397, -397, -397,
+     -397, -397, -397, -397, -397, -397,   62, -397,  420,  420,
+      420,  420,  420,  420,  420,  420,  420,  420, -397, -397,
+     -397, -397, -397, -397, -397, -397, -397, -397, -397,   65,
+     -397, -397, -397, -397, -397, -397, -397, -397, -397, -397,
+     -397, -397, -397, -397, -397, -397, -397, -397, -397, -397,
+
+     -397, -397, -397, -397, -397, -397, -397, -397, -397, -397,
+     -397,   65, -397, -397, -397, -397, -397, -397, -397, -397,
+     -397, -397, -397, -397, -397, -397, -397, -397, -397, -397,
+     -397, -397, -397, -397, -397, -397, -397, -397
+    },
+
+    {
+       15, -398, -398, -398, -398, -398, -398, -398, -398, -398,
+     -398, -398, -398, -398, -398, -398, -398, -398, -398, -398,
+     -398, -398, -398, -398, -398, -398, -398, -398, -398, -398,
+     -398, -398, -398, -398, -398, -398, -398, -398, -398, -398,
+     -398, -398, -398, -398, -398, -398,   62, -398,  421,  421,
+      421,  421,  421,  421,  421,  421,  421,  421, -398, -398,
+
+     -398, -398, -398, -398, -398, -398, -398, -398, -398,   65,
+     -398, -398, -398, -398, -398, -398, -398, -398, -398, -398,
+     -398, -398, -398, -398, -398, -398, -398, -398, -398, -398,
+     -398, -398, -398, -398, -398, -398, -398, -398, -398, -398,
+     -398,   65, -398, -398, -398, -398, -398, -398, -398, -398,
+     -398, -398, -398, -398, -398, -398, -398, -398, -398, -398,
+     -398, -398, -398, -398, -398, -398, -398, -398
+    },
+
+    {
+       15, -399, -399, -399, -399, -399, -399, -399, -399, -399,
+     -399, -399, -399, -399, -399, -399, -399, -399, -399, -399,
+     -399, -399, -399, -399, -399, -399, -399, -399, -399, -399,
+
+     -399, -399, -399, -399, -399, -399, -399, -399, -399, -399,
+     -399, -399, -399, -399, -399, -399,   62, -399,  422,  422,
+      422,  422,  422,  422,  422,  422,  422,  422, -399, -399,
+     -399, -399, -399, -399, -399, -399, -399, -399, -399,   65,
+     -399, -399, -399, -399, -399, -399, -399, -399, -399, -399,
+     -399, -399, -399, -399, -399, -399, -399, -399, -399, -399,
+     -399, -399, -399, -399, -399, -399, -399, -399, -399, -399,
+     -399,   65, -399, -399, -399, -399, -399, -399, -399, -399,
+     -399, -399, -399, -399, -399, -399, -399, -399, -399, -399,
+     -399, -399, -399, -399, -399, -399, -399, -399
+
+    },
+
+    {
+       15, -400, -400, -400, -400, -400, -400, -400, -400, -400,
+     -400, -400, -400, -400, -400, -400, -400, -400, -400, -400,
+     -400, -400, -400, -400, -400, -400, -400, -400, -400, -400,
+     -400, -400, -400, -400, -400, -400, -400, -400, -400, -400,
+     -400, -400, -400, -400, -400, -400,   62, -400,  423,  423,
+      423,  423,  423,  423,  423,  423,  423,  423, -400, -400,
+     -400, -400, -400, -400, -400, -400, -400, -400, -400,   65,
+     -400, -400, -400, -400, -400, -400, -400, -400, -400, -400,
+     -400, -400, -400, -400, -400, -400, -400, -400, -400, -400,
+     -400, -400, -400, -400, -400, -400, -400, -400, -400, -400,
+
+     -400,   65, -400, -400, -400, -400, -400, -400, -400, -400,
+     -400, -400, -400, -400, -400, -400, -400, -400, -400, -400,
+     -400, -400, -400, -400, -400, -400, -400, -400
+    },
+
+    {
+       15, -401, -401, -401, -401, -401, -401, -401, -401, -401,
+     -401, -401, -401, -401, -401, -401, -401, -401, -401, -401,
+     -401, -401, -401, -401, -401, -401, -401, -401, -401, -401,
+     -401, -401, -401, -401, -401, -401, -401, -401, -401, -401,
+     -401, -401, -401, -401, -401, -401,   62, -401,  424,  424,
+      424,  424,  424,  424,  424,  424,  424,  424, -401, -401,
+     -401, -401, -401, -401, -401, -401, -401, -401, -401,   65,
+
+     -401, -401, -401, -401, -401, -401, -401, -401, -401, -401,
+     -401, -401, -401, -401, -401, -401, -401, -401, -401, -401,
+     -401, -401, -401, -401, -401, -401, -401, -401, -401, -401,
+     -401,   65, -401, -401, -401, -401, -401, -401, -401, -401,
+     -401, -401, -401, -401, -401, -401, -401, -401, -401, -401,
+     -401, -401, -401, -401, -401, -401, -401, -401
+    },
+
+    {
+       15, -402, -402, -402, -402, -402, -402, -402, -402, -402,
+     -402, -402, -402, -402, -402, -402, -402, -402, -402, -402,
+     -402, -402, -402, -402, -402, -402, -402, -402, -402, -402,
+     -402, -402, -402, -402, -402, -402, -402, -402, -402, -402,
+
+     -402, -402, -402, -402, -402, -402,   62, -402,  425,  425,
+      425,  425,  425,  425,  425,  425,  425,  425, -402, -402,
+     -402, -402, -402, -402, -402, -402, -402, -402, -402,   65,
+     -402, -402, -402, -402, -402, -402, -402, -402, -402, -402,
+     -402, -402, -402, -402, -402, -402, -402, -402, -402, -402,
+     -402, -402, -402, -402, -402, -402, -402, -402, -402, -402,
+     -402,   65, -402, -402, -402, -402, -402, -402, -402, -402,
+     -402, -402, -402, -402, -402, -402, -402, -402, -402, -402,
+     -402, -402, -402, -402, -402, -402, -402, -402
+    },
+
+    {
+       15, -403, -403, -403, -403, -403, -403, -403, -403, -403,
+
+     -403, -403, -403, -403, -403, -403, -403, -403, -403, -403,
+     -403, -403, -403, -403, -403, -403, -403, -403, -403, -403,
+     -403, -403, -403, -403, -403, -403, -403, -403, -403, -403,
+     -403, -403, -403, -403, -403, -403,   62, -403,  426,  426,
+      426,  426,  426,  426,  426,  426,  426,  426, -403, -403,
+     -403, -403, -403, -403, -403, -403, -403, -403, -403,   65,
+     -403, -403, -403, -403, -403, -403, -403, -403, -403, -403,
+     -403, -403, -403, -403, -403, -403, -403, -403, -403, -403,
+     -403, -403, -403, -403, -403, -403, -403, -403, -403, -403,
+     -403,   65, -403, -403, -403, -403, -403, -403, -403, -403,
+
+     -403, -403, -403, -403, -403, -403, -403, -403, -403, -403,
+     -403, -403, -403, -403, -403, -403, -403, -403
+    },
+
+    {
+       15, -404, -404, -404, -404, -404, -404, -404, -404, -404,
+     -404, -404, -404, -404, -404, -404, -404, -404, -404, -404,
+     -404, -404, -404, -404, -404, -404, -404, -404, -404, -404,
+     -404, -404, -404, -404, -404, -404, -404, -404, -404, -404,
+     -404, -404, -404, -404, -404, -404,   62, -404,  427,  427,
+      427,  427,  427,  427,  427,  427,  427,  427, -404, -404,
+     -404, -404, -404, -404, -404, -404, -404, -404, -404,   65,
+     -404, -404, -404, -404, -404, -404, -404, -404, -404, -404,
+
+     -404, -404, -404, -404, -404, -404, -404, -404, -404, -404,
+     -404, -404, -404, -404, -404, -404, -404, -404, -404, -404,
+     -404,   65, -404, -404, -404, -404, -404, -404, -404, -404,
+     -404, -404, -404, -404, -404, -404, -404, -404, -404, -404,
+     -404, -404, -404, -404, -404, -404, -404, -404
+    },
+
+    {
+       15, -405, -405, -405, -405, -405, -405, -405, -405, -405,
+     -405, -405, -405, -405, -405, -405, -405, -405, -405, -405,
+     -405, -405, -405, -405, -405, -405, -405, -405, -405, -405,
+     -405, -405, -405, -405, -405, -405, -405, -405, -405, -405,
+     -405, -405, -405, -405, -405, -405,   62, -405,  428,  428,
+
+      428,  428,  428,  428,  428,  428,  428,  428, -405, -405,
+     -405, -405, -405, -405, -405, -405, -405, -405, -405,   65,
+     -405, -405, -405, -405, -405, -405, -405, -405, -405, -405,
+     -405, -405, -405, -405, -405, -405, -405, -405, -405, -405,
+     -405, -405, -405, -405, -405, -405, -405, -405, -405, -405,
+     -405,   65, -405, -405, -405, -405, -405, -405, -405, -405,
+     -405, -405, -405, -405, -405, -405, -405, -405, -405, -405,
+     -405, -405, -405, -405, -405, -405, -405, -405
+    },
+
+    {
+       15, -406, -406, -406, -406, -406, -406, -406, -406, -406,
+     -406, -406, -406, -406, -406, -406, -406, -406, -406, -406,
+
+     -406, -406, -406, -406, -406, -406, -406, -406, -406, -406,
+     -406, -406, -406, -406, -406, -406, -406, -406, -406, -406,
+     -406, -406, -406, -406, -406, -406,   62, -406,  429,  429,
+      429,  429,  429,  429,  429,  429,  429,  429, -406, -406,
+     -406, -406, -406, -406, -406, -406, -406, -406, -406,   65,
+     -406, -406, -406, -406, -406, -406, -406, -406, -406, -406,
+     -406, -406, -406, -406, -406, -406, -406, -406, -406, -406,
+     -406, -406, -406, -406, -406, -406, -406, -406, -406, -406,
+     -406,   65, -406, -406, -406, -406, -406, -406, -406, -406,
+     -406, -406, -406, -406, -406, -406, -406, -406, -406, -406,
+
+     -406, -406, -406, -406, -406, -406, -406, -406
+    },
+
+    {
+       15, -407, -407, -407, -407, -407, -407, -407, -407, -407,
+     -407, -407, -407, -407, -407, -407, -407, -407, -407, -407,
+     -407, -407, -407, -407, -407, -407, -407, -407, -407, -407,
+     -407, -407, -407, -407, -407, -407, -407, -407, -407, -407,
+     -407, -407, -407, -407, -407, -407,   62, -407,  430,  430,
+      430,  430,  430,  430,  430,  430,  430,  430, -407, -407,
+     -407, -407, -407, -407, -407, -407, -407, -407, -407,   65,
+     -407, -407, -407, -407, -407, -407, -407, -407, -407, -407,
+     -407, -407, -407, -407, -407, -407, -407, -407, -407, -407,
+
+     -407, -407, -407, -407, -407, -407, -407, -407, -407, -407,
+     -407,   65, -407, -407, -407, -407, -407, -407, -407, -407,
+     -407, -407, -407, -407, -407, -407, -407, -407, -407, -407,
+     -407, -407, -407, -407, -407, -407, -407, -407
+    },
+
+    {
+       15, -408, -408, -408, -408, -408, -408, -408, -408, -408,
+     -408, -408, -408, -408, -408, -408, -408, -408, -408, -408,
+     -408, -408, -408, -408, -408, -408, -408, -408, -408, -408,
+     -408, -408,  431, -408, -408, -408, -408, -408, -408, -408,
+     -408, -408, -408, -408, -408, -408, -408, -408, -408, -408,
+     -408, -408, -408, -408, -408, -408, -408, -408, -408, -408,
+
+     -408, -408, -408, -408, -408, -408, -408, -408, -408, -408,
+     -408, -408, -408, -408, -408, -408, -408, -408, -408, -408,
+     -408, -408, -408, -408, -408, -408, -408, -408, -408, -408,
+     -408, -408, -408, -408, -408, -408, -408, -408, -408, -408,
+     -408, -408, -408, -408, -408, -408, -408, -408, -408, -408,
+     -408, -408, -408, -408, -408, -408, -408, -408, -408, -408,
+     -408, -408, -408, -408, -408, -408, -408, -408
+    },
+
+    {
+       15, -409, -409, -409, -409, -409, -409, -409, -409, -409,
+     -409, -409, -409, -409, -409, -409, -409, -409, -409, -409,
+     -409, -409, -409, -409, -409, -409, -409, -409, -409, -409,
+
+     -409, -409,  432, -409, -409, -409, -409, -409, -409, -409,
+     -409, -409, -409, -409, -409, -409, -409, -409, -409, -409,
+     -409, -409, -409, -409, -409, -409, -409, -409, -409, -409,
+     -409, -409, -409, -409, -409, -409, -409, -409, -409, -409,
+     -409, -409, -409, -409, -409, -409, -409, -409, -409, -409,
+     -409, -409, -409, -409, -409, -409, -409, -409, -409, -409,
+     -409, -409, -409, -409, -409, -409, -409, -409, -409, -409,
+     -409, -409, -409, -409, -409, -409, -409, -409, -409, -409,
+     -409, -409, -409, -409, -409, -409, -409, -409, -409, -409,
+     -409, -409, -409, -409, -409, -409, -409, -409
+
+    },
+
+    {
+       15, -410, -410, -410, -410, -410, -410, -410, -410, -410,
+     -410, -410, -410, -410, -410, -410, -410, -410, -410, -410,
+     -410, -410, -410, -410, -410, -410, -410, -410, -410, -410,
+     -410, -410, -410, -410, -410, -410, -410, -410, -410, -410,
+     -410, -410, -410, -410, -410, -410,   62, -410,  410,  411,
+      411,  411,  411,  411,  411,  411,  411,  411, -410, -410,
+     -410, -410, -410, -410, -410, -410, -410, -410, -410,   65,
+     -410, -410, -410, -410, -410, -410, -410, -410, -410, -410,
+     -410, -410, -410, -410, -410, -410, -410, -410, -410, -410,
+     -410, -410, -410, -410, -410, -410, -410, -410, -410, -410,
+
+     -410,   65, -410, -410, -410, -410, -410, -410, -410, -410,
+     -410, -410, -410, -410, -410, -410, -410, -410, -410, -410,
+     -410, -410, -410, -410, -410, -410, -410, -410
+    },
+
+    {
+       15, -411, -411, -411, -411, -411, -411, -411, -411, -411,
+     -411, -411, -411, -411, -411, -411, -411, -411, -411, -411,
+     -411, -411, -411, -411, -411, -411, -411, -411, -411, -411,
+     -411, -411, -411, -411, -411, -411, -411, -411, -411, -411,
+     -411, -411, -411, -411, -411, -411,   62, -411,  412,  412,
+      412,  412,  412,  412,  412,  412,  412,  412, -411, -411,
+     -411, -411, -411, -411, -411, -411, -411, -411, -411,   65,
+
+     -411, -411, -411, -411, -411, -411, -411, -411, -411, -411,
+     -411, -411, -411, -411, -411, -411, -411, -411, -411, -411,
+     -411, -411, -411, -411, -411, -411, -411, -411, -411, -411,
+     -411,   65, -411, -411, -411, -411, -411, -411, -411, -411,
+     -411, -411, -411, -411, -411, -411, -411, -411, -411, -411,
+     -411, -411, -411, -411, -411, -411, -411, -411
+    },
+
+    {
+       15, -412, -412, -412, -412, -412, -412, -412, -412, -412,
+     -412, -412, -412, -412, -412, -412, -412, -412, -412, -412,
+     -412, -412, -412, -412, -412, -412, -412, -412, -412, -412,
+     -412, -412, -412, -412, -412, -412, -412, -412, -412, -412,
+
+     -412, -412, -412, -412, -412, -412,   62, -412,  413,  413,
+      413,  413,  413,  413,  413,  413,  413,  413, -412, -412,
+     -412, -412, -412, -412, -412, -412, -412, -412, -412,   65,
+     -412, -412, -412, -412, -412, -412, -412, -412, -412, -412,
+     -412, -412, -412, -412, -412, -412, -412, -412, -412, -412,
+     -412, -412, -412, -412, -412, -412, -412, -412, -412, -412,
+     -412,   65, -412, -412, -412, -412, -412, -412, -412, -412,
+     -412, -412, -412, -412, -412, -412, -412, -412, -412, -412,
+     -412, -412, -412, -412, -412, -412, -412, -412
+    },
+
+    {
+       15, -413, -413, -413, -413, -413, -413, -413, -413, -413,
+
+     -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
+     -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
+     -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
+     -413, -413, -413, -413, -413, -413,   62, -413,  414,  414,
+      414,  414,  414,  414,  414,  414,  414,  414, -413, -413,
+     -413, -413, -413, -413, -413, -413, -413, -413, -413,   65,
+     -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
+     -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
+     -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
+     -413,   65, -413, -413, -413, -413, -413, -413, -413, -413,
+
+     -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
+     -413, -413, -413, -413, -413, -413, -413, -413
+    },
+
+    {
+       15, -414, -414, -414, -414, -414, -414, -414, -414, -414,
+     -414, -414, -414, -414, -414, -414, -414, -414, -414, -414,
+     -414, -414, -414, -414, -414, -414, -414, -414, -414, -414,
+     -414, -414, -414, -414, -414, -414, -414, -414, -414, -414,
+     -414, -414, -414, -414, -414, -414,   62, -414,  415,  415,
+      415,  415,  415,  415,  415,  415,  415,  415, -414, -414,
+     -414, -414, -414, -414, -414, -414, -414, -414, -414,   65,
+     -414, -414, -414, -414, -414, -414, -414, -414, -414, -414,
+
+     -414, -414, -414, -414, -414, -414, -414, -414, -414, -414,
+     -414, -414, -414, -414, -414, -414, -414, -414, -414, -414,
+     -414,   65, -414, -414, -414, -414, -414, -414, -414, -414,
+     -414, -414, -414, -414, -414, -414, -414, -414, -414, -414,
+     -414, -414, -414, -414, -414, -414, -414, -414
+    },
+
+    {
+       15, -415, -415, -415, -415, -415, -415, -415, -415, -415,
+     -415, -415, -415, -415, -415, -415, -415, -415, -415, -415,
+     -415, -415, -415, -415, -415, -415, -415, -415, -415, -415,
+     -415, -415, -415, -415, -415, -415, -415, -415, -415, -415,
+     -415, -415, -415, -415, -415, -415,   62, -415,  416,  416,
+
+      416,  416,  416,  416,  416,  416,  416,  416, -415, -415,
+     -415, -415, -415, -415, -415, -415, -415, -415, -415,   65,
+     -415, -415, -415, -415, -415, -415, -415, -415, -415, -415,
+     -415, -415, -415, -415, -415, -415, -415, -415, -415, -415,
+     -415, -415, -415, -415, -415, -415, -415, -415, -415, -415,
+     -415,   65, -415, -415, -415, -415, -415, -415, -415, -415,
+     -415, -415, -415, -415, -415, -415, -415, -415, -415, -415,
+     -415, -415, -415, -415, -415, -415, -415, -415
+    },
+
+    {
+       15, -416, -416, -416, -416, -416, -416, -416, -416, -416,
+     -416, -416, -416, -416, -416, -416, -416, -416, -416, -416,
+
+     -416, -416, -416, -416, -416, -416, -416, -416, -416, -416,
+     -416, -416, -416, -416, -416, -416, -416, -416, -416, -416,
+     -416, -416, -416, -416, -416, -416,   62, -416,  417,  417,
+      417,  417,  417,  417,  417,  417,  417,  417, -416, -416,
+     -416, -416, -416, -416, -416, -416, -416, -416, -416,   65,
+     -416, -416, -416, -416, -416, -416, -416, -416, -416, -416,
+     -416, -416, -416, -416, -416, -416, -416, -416, -416, -416,
+     -416, -416, -416, -416, -416, -416, -416, -416, -416, -416,
+     -416,   65, -416, -416, -416, -416, -416, -416, -416, -416,
+     -416, -416, -416, -416, -416, -416, -416, -416, -416, -416,
+
+     -416, -416, -416, -416, -416, -416, -416, -416
+    },
+
+    {
+       15, -417, -417, -417, -417, -417, -417, -417, -417, -417,
+     -417, -417, -417, -417, -417, -417, -417, -417, -417, -417,
+     -417, -417, -417, -417, -417, -417, -417, -417, -417, -417,
+     -417, -417, -417, -417, -417, -417, -417, -417, -417, -417,
+     -417, -417, -417, -417, -417, -417,   62, -417,  418,  418,
+      418,  418,  418,  418,  418,  418,  418,  418, -417, -417,
+     -417, -417, -417, -417, -417, -417, -417, -417, -417,   65,
+     -417, -417, -417, -417, -417, -417, -417, -417, -417, -417,
+     -417, -417, -417, -417, -417, -417, -417, -417, -417, -417,
+
+     -417, -417, -417, -417, -417, -417, -417, -417, -417, -417,
+     -417,   65, -417, -417, -417, -417, -417, -417, -417, -417,
+     -417, -417, -417, -417, -417, -417, -417, -417, -417, -417,
+     -417, -417, -417, -417, -417, -417, -417, -417
+    },
+
+    {
+       15, -418, -418, -418, -418, -418, -418, -418, -418, -418,
+     -418, -418, -418, -418, -418, -418, -418, -418, -418, -418,
+     -418, -418, -418, -418, -418, -418, -418, -418, -418, -418,
+     -418, -418, -418, -418, -418, -418, -418, -418, -418, -418,
+     -418, -418, -418, -418, -418, -418,   62, -418,  419,  419,
+      419,  419,  419,  419,  419,  419,  419,  419, -418, -418,
+
+     -418, -418, -418, -418, -418, -418, -418, -418, -418,   65,
+     -418, -418, -418, -418, -418, -418, -418, -418, -418, -418,
+     -418, -418, -418, -418, -418, -418, -418, -418, -418, -418,
+     -418, -418, -418, -418, -418, -418, -418, -418, -418, -418,
+     -418,   65, -418, -418, -418, -418, -418, -418, -418, -418,
+     -418, -418, -418, -418, -418, -418, -418, -418, -418, -418,
+     -418, -418, -418, -418, -418, -418, -418, -418
+    },
+
+    {
+       15, -419, -419, -419, -419, -419, -419, -419, -419, -419,
+     -419, -419, -419, -419, -419, -419, -419, -419, -419, -419,
+     -419, -419, -419, -419, -419, -419, -419, -419, -419, -419,
+
+     -419, -419, -419, -419, -419, -419, -419, -419, -419, -419,
+     -419, -419, -419, -419, -419, -419,   62, -419,  420,  420,
+      420,  420,  420,  420,  420,  420,  420,  420, -419, -419,
+     -419, -419, -419, -419, -419, -419, -419, -419, -419,   65,
+     -419, -419, -419, -419, -419, -419, -419, -419, -419, -419,
+     -419, -419, -419, -419, -419, -419, -419, -419, -419, -419,
+     -419, -419, -419, -419, -419, -419, -419, -419, -419, -419,
+     -419,   65, -419, -419, -419, -419, -419, -419, -419, -419,
+     -419, -419, -419, -419, -419, -419, -419, -419, -419, -419,
+     -419, -419, -419, -419, -419, -419, -419, -419
+
+    },
+
+    {
+       15, -420, -420, -420, -420, -420, -420, -420, -420, -420,
+     -420, -420, -420, -420, -420, -420, -420, -420, -420, -420,
+     -420, -420, -420, -420, -420, -420, -420, -420, -420, -420,
+     -420, -420, -420, -420, -420, -420, -420, -420, -420, -420,
+     -420, -420, -420, -420, -420, -420,   62, -420,  421,  421,
+      421,  421,  421,  421,  421,  421,  421,  421, -420, -420,
+     -420, -420, -420, -420, -420, -420, -420, -420, -420,   65,
+     -420, -420, -420, -420, -420, -420, -420, -420, -420, -420,
+     -420, -420, -420, -420, -420, -420, -420, -420, -420, -420,
+     -420, -420, -420, -420, -420, -420, -420, -420, -420, -420,
+
+     -420,   65, -420, -420, -420, -420, -420, -420, -420, -420,
+     -420, -420, -420, -420, -420, -420, -420, -420, -420, -420,
+     -420, -420, -420, -420, -420, -420, -420, -420
+    },
+
+    {
+       15, -421, -421, -421, -421, -421, -421, -421, -421, -421,
+     -421, -421, -421, -421, -421, -421, -421, -421, -421, -421,
+     -421, -421, -421, -421, -421, -421, -421, -421, -421, -421,
+     -421, -421, -421, -421, -421, -421, -421, -421, -421, -421,
+     -421, -421, -421, -421, -421, -421,   62, -421,  422,  422,
+      422,  422,  422,  422,  422,  422,  422,  422, -421, -421,
+     -421, -421, -421, -421, -421, -421, -421, -421, -421,   65,
+
+     -421, -421, -421, -421, -421, -421, -421, -421, -421, -421,
+     -421, -421, -421, -421, -421, -421, -421, -421, -421, -421,
+     -421, -421, -421, -421, -421, -421, -421, -421, -421, -421,
+     -421,   65, -421, -421, -421, -421, -421, -421, -421, -421,
+     -421, -421, -421, -421, -421, -421, -421, -421, -421, -421,
+     -421, -421, -421, -421, -421, -421, -421, -421
+    },
+
+    {
+       15, -422, -422, -422, -422, -422, -422, -422, -422, -422,
+     -422, -422, -422, -422, -422, -422, -422, -422, -422, -422,
+     -422, -422, -422, -422, -422, -422, -422, -422, -422, -422,
+     -422, -422, -422, -422, -422, -422, -422, -422, -422, -422,
+
+     -422, -422, -422, -422, -422, -422,   62, -422,  423,  423,
+      423,  423,  423,  423,  423,  423,  423,  423, -422, -422,
+     -422, -422, -422, -422, -422, -422, -422, -422, -422,   65,
+     -422, -422, -422, -422, -422, -422, -422, -422, -422, -422,
+     -422, -422, -422, -422, -422, -422, -422, -422, -422, -422,
+     -422, -422, -422, -422, -422, -422, -422, -422, -422, -422,
+     -422,   65, -422, -422, -422, -422, -422, -422, -422, -422,
+     -422, -422, -422, -422, -422, -422, -422, -422, -422, -422,
+     -422, -422, -422, -422, -422, -422, -422, -422
+    },
+
+    {
+       15, -423, -423, -423, -423, -423, -423, -423, -423, -423,
+
+     -423, -423, -423, -423, -423, -423, -423, -423, -423, -423,
+     -423, -423, -423, -423, -423, -423, -423, -423, -423, -423,
+     -423, -423, -423, -423, -423, -423, -423, -423, -423, -423,
+     -423, -423, -423, -423, -423, -423,   62, -423,  424,  424,
+      424,  424,  424,  424,  424,  424,  424,  424, -423, -423,
+     -423, -423, -423, -423, -423, -423, -423, -423, -423,   65,
+     -423, -423, -423, -423, -423, -423, -423, -423, -423, -423,
+     -423, -423, -423, -423, -423, -423, -423, -423, -423, -423,
+     -423, -423, -423, -423, -423, -423, -423, -423, -423, -423,
+     -423,   65, -423, -423, -423, -423, -423, -423, -423, -423,
+
+     -423, -423, -423, -423, -423, -423, -423, -423, -423, -423,
+     -423, -423, -423, -423, -423, -423, -423, -423
+    },
+
+    {
+       15, -424, -424, -424, -424, -424, -424, -424, -424, -424,
+     -424, -424, -424, -424, -424, -424, -424, -424, -424, -424,
+     -424, -424, -424, -424, -424, -424, -424, -424, -424, -424,
+     -424, -424, -424, -424, -424, -424, -424, -424, -424, -424,
+     -424, -424, -424, -424, -424, -424,   62, -424,  425,  425,
+      425,  425,  425,  425,  425,  425,  425,  425, -424, -424,
+     -424, -424, -424, -424, -424, -424, -424, -424, -424,   65,
+     -424, -424, -424, -424, -424, -424, -424, -424, -424, -424,
+
+     -424, -424, -424, -424, -424, -424, -424, -424, -424, -424,
+     -424, -424, -424, -424, -424, -424, -424, -424, -424, -424,
+     -424,   65, -424, -424, -424, -424, -424, -424, -424, -424,
+     -424, -424, -424, -424, -424, -424, -424, -424, -424, -424,
+     -424, -424, -424, -424, -424, -424, -424, -424
+    },
+
+    {
+       15, -425, -425, -425, -425, -425, -425, -425, -425, -425,
+     -425, -425, -425, -425, -425, -425, -425, -425, -425, -425,
+     -425, -425, -425, -425, -425, -425, -425, -425, -425, -425,
+     -425, -425, -425, -425, -425, -425, -425, -425, -425, -425,
+     -425, -425, -425, -425, -425, -425,   62, -425,  426,  426,
+
+      426,  426,  426,  426,  426,  426,  426,  426, -425, -425,
+     -425, -425, -425, -425, -425, -425, -425, -425, -425,   65,
+     -425, -425, -425, -425, -425, -425, -425, -425, -425, -425,
+     -425, -425, -425, -425, -425, -425, -425, -425, -425, -425,
+     -425, -425, -425, -425, -425, -425, -425, -425, -425, -425,
+     -425,   65, -425, -425, -425, -425, -425, -425, -425, -425,
+     -425, -425, -425, -425, -425, -425, -425, -425, -425, -425,
+     -425, -425, -425, -425, -425, -425, -425, -425
+    },
+
+    {
+       15, -426, -426, -426, -426, -426, -426, -426, -426, -426,
+     -426, -426, -426, -426, -426, -426, -426, -426, -426, -426,
+
+     -426, -426, -426, -426, -426, -426, -426, -426, -426, -426,
+     -426, -426, -426, -426, -426, -426, -426, -426, -426, -426,
+     -426, -426, -426, -426, -426, -426,   62, -426,  427,  427,
+      427,  427,  427,  427,  427,  427,  427,  427, -426, -426,
+     -426, -426, -426, -426, -426, -426, -426, -426, -426,   65,
+     -426, -426, -426, -426, -426, -426, -426, -426, -426, -426,
+     -426, -426, -426, -426, -426, -426, -426, -426, -426, -426,
+     -426, -426, -426, -426, -426, -426, -426, -426, -426, -426,
+     -426,   65, -426, -426, -426, -426, -426, -426, -426, -426,
+     -426, -426, -426, -426, -426, -426, -426, -426, -426, -426,
+
+     -426, -426, -426, -426, -426, -426, -426, -426
+    },
+
+    {
+       15, -427, -427, -427, -427, -427, -427, -427, -427, -427,
+     -427, -427, -427, -427, -427, -427, -427, -427, -427, -427,
+     -427, -427, -427, -427, -427, -427, -427, -427, -427, -427,
+     -427, -427, -427, -427, -427, -427, -427, -427, -427, -427,
+     -427, -427, -427, -427, -427, -427,   62, -427,  428,  428,
+      428,  428,  428,  428,  428,  428,  428,  428, -427, -427,
+     -427, -427, -427, -427, -427, -427, -427, -427, -427,   65,
+     -427, -427, -427, -427, -427, -427, -427, -427, -427, -427,
+     -427, -427, -427, -427, -427, -427, -427, -427, -427, -427,
+
+     -427, -427, -427, -427, -427, -427, -427, -427, -427, -427,
+     -427,   65, -427, -427, -427, -427, -427, -427, -427, -427,
+     -427, -427, -427, -427, -427, -427, -427, -427, -427, -427,
+     -427, -427, -427, -427, -427, -427, -427, -427
+    },
+
+    {
+       15, -428, -428, -428, -428, -428, -428, -428, -428, -428,
+     -428, -428, -428, -428, -428, -428, -428, -428, -428, -428,
+     -428, -428, -428, -428, -428, -428, -428, -428, -428, -428,
+     -428, -428, -428, -428, -428, -428, -428, -428, -428, -428,
+     -428, -428, -428, -428, -428, -428,   62, -428,  429,  429,
+      429,  429,  429,  429,  429,  429,  429,  429, -428, -428,
+
+     -428, -428, -428, -428, -428, -428, -428, -428, -428,   65,
+     -428, -428, -428, -428, -428, -428, -428, -428, -428, -428,
+     -428, -428, -428, -428, -428, -428, -428, -428, -428, -428,
+     -428, -428, -428, -428, -428, -428, -428, -428, -428, -428,
+     -428,   65, -428, -428, -428, -428, -428, -428, -428, -428,
+     -428, -428, -428, -428, -428, -428, -428, -428, -428, -428,
+     -428, -428, -428, -428, -428, -428, -428, -428
+    },
+
+    {
+       15, -429, -429, -429, -429, -429, -429, -429, -429, -429,
+     -429, -429, -429, -429, -429, -429, -429, -429, -429, -429,
+     -429, -429, -429, -429, -429, -429, -429, -429, -429, -429,
+
+     -429, -429, -429, -429, -429, -429, -429, -429, -429, -429,
+     -429, -429, -429, -429, -429, -429,   62, -429,  430,  430,
+      430,  430,  430,  430,  430,  430,  430,  430, -429, -429,
+     -429, -429, -429, -429, -429, -429, -429, -429, -429,   65,
+     -429, -429, -429, -429, -429, -429, -429, -429, -429, -429,
+     -429, -429, -429, -429, -429, -429, -429, -429, -429, -429,
+     -429, -429, -429, -429, -429, -429, -429, -429, -429, -429,
+     -429,   65, -429, -429, -429, -429, -429, -429, -429, -429,
+     -429, -429, -429, -429, -429, -429, -429, -429, -429, -429,
+     -429, -429, -429, -429, -429, -429, -429, -429
+
+    },
+
+    {
+       15, -430, -430, -430, -430, -430, -430, -430, -430, -430,
+     -430, -430, -430, -430, -430, -430, -430, -430, -430, -430,
+     -430, -430, -430, -430, -430, -430, -430, -430, -430, -430,
+     -430, -430, -430, -430, -430, -430, -430, -430, -430, -430,
+     -430, -430, -430, -430, -430, -430,   62, -430,  430,  430,
+      430,  430,  430,  430,  430,  430,  430,  430, -430, -430,
+     -430, -430, -430, -430, -430, -430, -430, -430, -430,   65,
+     -430, -430, -430, -430, -430, -430, -430, -430, -430, -430,
+     -430, -430, -430, -430, -430, -430, -430, -430, -430, -430,
+     -430, -430, -430, -430, -430, -430, -430, -430, -430, -430,
+
+     -430,   65, -430, -430, -430, -430, -430, -430, -430, -430,
+     -430, -430, -430, -430, -430, -430, -430, -430, -430, -430,
+     -430, -430, -430, -430, -430, -430, -430, -430
+    },
+
+    {
+       15, -431, -431, -431, -431, -431, -431, -431, -431, -431,
+     -431, -431, -431, -431, -431, -431, -431, -431, -431, -431,
+     -431, -431, -431, -431, -431, -431, -431, -431, -431, -431,
+     -431, -431,  433, -431, -431, -431, -431, -431, -431, -431,
+     -431, -431, -431, -431, -431, -431, -431, -431, -431, -431,
+     -431, -431, -431, -431, -431, -431, -431, -431, -431, -431,
+     -431, -431, -431, -431, -431, -431, -431, -431, -431, -431,
+
+     -431, -431, -431, -431, -431, -431, -431, -431, -431, -431,
+     -431, -431, -431, -431, -431, -431, -431, -431, -431, -431,
+     -431, -431, -431, -431, -431, -431, -431, -431, -431, -431,
+     -431, -431, -431, -431, -431, -431, -431, -431, -431, -431,
+     -431, -431, -431, -431, -431, -431, -431, -431, -431, -431,
+     -431, -431, -431, -431, -431, -431, -431, -431
+    },
+
+    {
+       15, -432, -432, -432, -432, -432, -432, -432, -432, -432,
+     -432, -432, -432, -432, -432, -432, -432, -432, -432, -432,
+     -432, -432, -432, -432, -432, -432, -432, -432, -432, -432,
+     -432, -432,  434, -432, -432, -432, -432, -432, -432, -432,
+
+     -432, -432, -432, -432, -432, -432, -432, -432, -432, -432,
+     -432, -432, -432, -432, -432, -432, -432, -432, -432, -432,
+     -432, -432, -432, -432, -432, -432, -432, -432, -432, -432,
+     -432, -432, -432, -432, -432, -432, -432, -432, -432, -432,
+     -432, -432, -432, -432, -432, -432, -432, -432, -432, -432,
+     -432, -432, -432, -432, -432, -432, -432, -432, -432, -432,
+     -432, -432, -432, -432, -432, -432, -432, -432, -432, -432,
+     -432, -432, -432, -432, -432, -432, -432, -432, -432, -432,
+     -432, -432, -432, -432, -432, -432, -432, -432
+    },
+
+    {
+       15, -433, -433, -433, -433, -433, -433, -433, -433, -433,
+
+     -433, -433, -433, -433, -433, -433, -433, -433, -433, -433,
+     -433, -433, -433, -433, -433, -433, -433, -433, -433, -433,
+     -433, -433,  435, -433, -433, -433, -433, -433, -433, -433,
+     -433, -433, -433, -433, -433, -433, -433, -433, -433, -433,
+     -433, -433, -433, -433, -433, -433, -433, -433, -433, -433,
+     -433, -433, -433, -433, -433, -433, -433, -433, -433, -433,
+     -433, -433, -433, -433, -433, -433, -433, -433, -433, -433,
+     -433, -433, -433, -433, -433, -433, -433, -433, -433, -433,
+     -433, -433, -433, -433, -433, -433, -433, -433, -433, -433,
+     -433, -433, -433, -433, -433, -433, -433, -433, -433, -433,
+
+     -433, -433, -433, -433, -433, -433, -433, -433, -433, -433,
+     -433, -433, -433, -433, -433, -433, -433, -433
+    },
+
+    {
+       15, -434, -434, -434, -434, -434, -434, -434, -434, -434,
+     -434, -434, -434, -434, -434, -434, -434, -434, -434, -434,
+     -434, -434, -434, -434, -434, -434, -434, -434, -434, -434,
+     -434, -434,  436, -434, -434, -434, -434, -434, -434, -434,
+     -434, -434, -434, -434, -434, -434, -434, -434, -434, -434,
+     -434, -434, -434, -434, -434, -434, -434, -434, -434, -434,
+     -434, -434, -434, -434, -434, -434, -434, -434, -434, -434,
+     -434, -434, -434, -434, -434, -434, -434, -434, -434, -434,
+
+     -434, -434, -434, -434, -434, -434, -434, -434, -434, -434,
+     -434, -434, -434, -434, -434, -434, -434, -434, -434, -434,
+     -434, -434, -434, -434, -434, -434, -434, -434, -434, -434,
+     -434, -434, -434, -434, -434, -434, -434, -434, -434, -434,
+     -434, -434, -434, -434, -434, -434, -434, -434
+    },
+
+    {
+       15, -435, -435, -435, -435, -435, -435, -435, -435, -435,
+     -435, -435, -435, -435, -435, -435, -435, -435, -435, -435,
+     -435, -435, -435, -435, -435, -435, -435, -435, -435, -435,
+     -435, -435,  437, -435, -435, -435, -435, -435, -435, -435,
+     -435, -435, -435, -435, -435, -435, -435, -435, -435, -435,
+
+     -435, -435, -435, -435, -435, -435, -435, -435, -435, -435,
+     -435, -435, -435, -435, -435, -435, -435, -435, -435, -435,
+     -435, -435, -435, -435, -435, -435, -435, -435, -435, -435,
+     -435, -435, -435, -435, -435, -435, -435, -435, -435, -435,
+     -435, -435, -435, -435, -435, -435, -435, -435, -435, -435,
+     -435, -435, -435, -435, -435, -435, -435, -435, -435, -435,
+     -435, -435, -435, -435, -435, -435, -435, -435, -435, -435,
+     -435, -435, -435, -435, -435, -435, -435, -435
+    },
+
+    {
+       15, -436, -436, -436, -436, -436, -436, -436, -436, -436,
+     -436, -436, -436, -436, -436, -436, -436, -436, -436, -436,
+
+     -436, -436, -436, -436, -436, -436, -436, -436, -436, -436,
+     -436, -436,  438, -436, -436, -436, -436, -436, -436, -436,
+     -436, -436, -436, -436, -436, -436, -436, -436, -436, -436,
+     -436, -436, -436, -436, -436, -436, -436, -436, -436, -436,
+     -436, -436, -436, -436, -436, -436, -436, -436, -436, -436,
+     -436, -436, -436, -436, -436, -436, -436, -436, -436, -436,
+     -436, -436, -436, -436, -436, -436, -436, -436, -436, -436,
+     -436, -436, -436, -436, -436, -436, -436, -436, -436, -436,
+     -436, -436, -436, -436, -436, -436, -436, -436, -436, -436,
+     -436, -436, -436, -436, -436, -436, -436, -436, -436, -436,
+
+     -436, -436, -436, -436, -436, -436, -436, -436
+    },
+
+    {
+       15, -437, -437, -437, -437, -437, -437, -437, -437, -437,
+     -437, -437, -437, -437, -437, -437, -437, -437, -437, -437,
+     -437, -437, -437, -437, -437, -437, -437, -437, -437, -437,
+     -437, -437,  439, -437, -437, -437, -437, -437, -437, -437,
+     -437, -437, -437, -437, -437, -437, -437, -437, -437, -437,
+     -437, -437, -437, -437, -437, -437, -437, -437, -437, -437,
+     -437, -437, -437, -437, -437, -437, -437, -437, -437, -437,
+     -437, -437, -437, -437, -437, -437, -437, -437, -437, -437,
+     -437, -437, -437, -437, -437, -437, -437, -437, -437, -437,
+
+     -437, -437, -437, -437, -437, -437, -437, -437, -437, -437,
+     -437, -437, -437, -437, -437, -437, -437, -437, -437, -437,
+     -437, -437, -437, -437, -437, -437, -437, -437, -437, -437,
+     -437, -437, -437, -437, -437, -437, -437, -437
+    },
+
+    {
+       15, -438, -438, -438, -438, -438, -438, -438, -438, -438,
+     -438, -438, -438, -438, -438, -438, -438, -438, -438, -438,
+     -438, -438, -438, -438, -438, -438, -438, -438, -438, -438,
+     -438, -438,  440, -438, -438, -438, -438, -438, -438, -438,
+     -438, -438, -438, -438, -438, -438, -438, -438, -438, -438,
+     -438, -438, -438, -438, -438, -438, -438, -438, -438, -438,
+
+     -438, -438, -438, -438, -438, -438, -438, -438, -438, -438,
+     -438, -438, -438, -438, -438, -438, -438, -438, -438, -438,
+     -438, -438, -438, -438, -438, -438, -438, -438, -438, -438,
+     -438, -438, -438, -438, -438, -438, -438, -438, -438, -438,
+     -438, -438, -438, -438, -438, -438, -438, -438, -438, -438,
+     -438, -438, -438, -438, -438, -438, -438, -438, -438, -438,
+     -438, -438, -438, -438, -438, -438, -438, -438
+    },
+
+    {
+       15, -439, -439, -439, -439, -439, -439, -439, -439, -439,
+     -439, -439, -439, -439, -439, -439, -439, -439, -439, -439,
+     -439, -439, -439, -439, -439, -439, -439, -439, -439, -439,
+
+     -439, -439,  441, -439, -439, -439, -439, -439, -439, -439,
+     -439, -439, -439, -439, -439, -439, -439, -439, -439, -439,
+     -439, -439, -439, -439, -439, -439, -439, -439, -439, -439,
+     -439, -439, -439, -439, -439, -439, -439, -439, -439, -439,
+     -439, -439, -439, -439, -439, -439, -439, -439, -439, -439,
+     -439, -439, -439, -439, -439, -439, -439, -439, -439, -439,
+     -439, -439, -439, -439, -439, -439, -439, -439, -439, -439,
+     -439, -439, -439, -439, -439, -439, -439, -439, -439, -439,
+     -439, -439, -439, -439, -439, -439, -439, -439, -439, -439,
+     -439, -439, -439, -439, -439, -439, -439, -439
+
+    },
+
+    {
+       15, -440, -440, -440, -440, -440, -440, -440, -440, -440,
+     -440, -440, -440, -440, -440, -440, -440, -440, -440, -440,
+     -440, -440, -440, -440, -440, -440, -440, -440, -440, -440,
+     -440, -440,  442, -440, -440, -440, -440, -440, -440, -440,
+     -440, -440, -440, -440, -440, -440, -440, -440, -440, -440,
+     -440, -440, -440, -440, -440, -440, -440, -440, -440, -440,
+     -440, -440, -440, -440, -440, -440, -440, -440, -440, -440,
+     -440, -440, -440, -440, -440, -440, -440, -440, -440, -440,
+     -440, -440, -440, -440, -440, -440, -440, -440, -440, -440,
+     -440, -440, -440, -440, -440, -440, -440, -440, -440, -440,
+
+     -440, -440, -440, -440, -440, -440, -440, -440, -440, -440,
+     -440, -440, -440, -440, -440, -440, -440, -440, -440, -440,
+     -440, -440, -440, -440, -440, -440, -440, -440
+    },
+
+    {
+       15, -441, -441, -441, -441, -441, -441, -441, -441, -441,
+     -441, -441, -441, -441, -441, -441, -441, -441, -441, -441,
+     -441, -441, -441, -441, -441, -441, -441, -441, -441, -441,
+     -441, -441,  443, -441, -441, -441, -441, -441, -441, -441,
+     -441, -441, -441, -441, -441, -441, -441, -441, -441, -441,
+     -441, -441, -441, -441, -441, -441, -441, -441, -441, -441,
+     -441, -441, -441, -441, -441, -441, -441, -441, -441, -441,
+
+     -441, -441, -441, -441, -441, -441, -441, -441, -441, -441,
+     -441, -441, -441, -441, -441, -441, -441, -441, -441, -441,
+     -441, -441, -441, -441, -441, -441, -441, -441, -441, -441,
+     -441, -441, -441, -441, -441, -441, -441, -441, -441, -441,
+     -441, -441, -441, -441, -441, -441, -441, -441, -441, -441,
+     -441, -441, -441, -441, -441, -441, -441, -441
+    },
+
+    {
+       15, -442, -442, -442, -442, -442, -442, -442, -442, -442,
+     -442, -442, -442, -442, -442, -442, -442, -442, -442, -442,
+     -442, -442, -442, -442, -442, -442, -442, -442, -442, -442,
+     -442, -442,  444, -442, -442, -442, -442, -442, -442, -442,
+
+     -442, -442, -442, -442, -442, -442, -442, -442, -442, -442,
+     -442, -442, -442, -442, -442, -442, -442, -442, -442, -442,
+     -442, -442, -442, -442, -442, -442, -442, -442, -442, -442,
+     -442, -442, -442, -442, -442, -442, -442, -442, -442, -442,
+     -442, -442, -442, -442, -442, -442, -442, -442, -442, -442,
+     -442, -442, -442, -442, -442, -442, -442, -442, -442, -442,
+     -442, -442, -442, -442, -442, -442, -442, -442, -442, -442,
+     -442, -442, -442, -442, -442, -442, -442, -442, -442, -442,
+     -442, -442, -442, -442, -442, -442, -442, -442
+    },
+
+    {
+       15, -443, -443, -443, -443, -443, -443, -443, -443, -443,
+
+     -443, -443, -443, -443, -443, -443, -443, -443, -443, -443,
+     -443, -443, -443, -443, -443, -443, -443, -443, -443, -443,
+     -443, -443,  445, -443, -443, -443, -443, -443, -443, -443,
+     -443, -443, -443, -443, -443, -443, -443, -443, -443, -443,
+     -443, -443, -443, -443, -443, -443, -443, -443, -443, -443,
+     -443, -443, -443, -443, -443, -443, -443, -443, -443, -443,
+     -443, -443, -443, -443, -443, -443, -443, -443, -443, -443,
+     -443, -443, -443, -443, -443, -443, -443, -443, -443, -443,
+     -443, -443, -443, -443, -443, -443, -443, -443, -443, -443,
+     -443, -443, -443, -443, -443, -443, -443, -443, -443, -443,
+
+     -443, -443, -443, -443, -443, -443, -443, -443, -443, -443,
+     -443, -443, -443, -443, -443, -443, -443, -443
+    },
+
+    {
+       15, -444, -444, -444, -444, -444, -444, -444, -444, -444,
+     -444, -444, -444, -444, -444, -444, -444, -444, -444, -444,
+     -444, -444, -444, -444, -444, -444, -444, -444, -444, -444,
+     -444, -444,  446, -444, -444, -444, -444, -444, -444, -444,
+     -444, -444, -444, -444, -444, -444, -444, -444, -444, -444,
+     -444, -444, -444, -444, -444, -444, -444, -444, -444, -444,
+     -444, -444, -444, -444, -444, -444, -444, -444, -444, -444,
+     -444, -444, -444, -444, -444, -444, -444, -444, -444, -444,
+
+     -444, -444, -444, -444, -444, -444, -444, -444, -444, -444,
+     -444, -444, -444, -444, -444, -444, -444, -444, -444, -444,
+     -444, -444, -444, -444, -444, -444, -444, -444, -444, -444,
+     -444, -444, -444, -444, -444, -444, -444, -444, -444, -444,
+     -444, -444, -444, -444, -444, -444, -444, -444
+    },
+
+    {
+       15, -445, -445, -445, -445, -445, -445, -445, -445, -445,
+     -445, -445, -445, -445, -445, -445, -445, -445, -445, -445,
+     -445, -445, -445, -445, -445, -445, -445, -445, -445, -445,
+     -445, -445,  447, -445, -445, -445, -445, -445, -445, -445,
+     -445, -445, -445, -445, -445, -445, -445, -445, -445, -445,
+
+     -445, -445, -445, -445, -445, -445, -445, -445, -445, -445,
+     -445, -445, -445, -445, -445, -445, -445, -445, -445, -445,
+     -445, -445, -445, -445, -445, -445, -445, -445, -445, -445,
+     -445, -445, -445, -445, -445, -445, -445, -445, -445, -445,
+     -445, -445, -445, -445, -445, -445, -445, -445, -445, -445,
+     -445, -445, -445, -445, -445, -445, -445, -445, -445, -445,
+     -445, -445, -445, -445, -445, -445, -445, -445, -445, -445,
+     -445, -445, -445, -445, -445, -445, -445, -445
+    },
+
+    {
+       15, -446, -446, -446, -446, -446, -446, -446, -446, -446,
+     -446, -446, -446, -446, -446, -446, -446, -446, -446, -446,
+
+     -446, -446, -446, -446, -446, -446, -446, -446, -446, -446,
+     -446, -446,  448, -446, -446, -446, -446, -446, -446, -446,
+     -446, -446, -446, -446, -446, -446, -446, -446, -446, -446,
+     -446, -446, -446, -446, -446, -446, -446, -446, -446, -446,
+     -446, -446, -446, -446, -446, -446, -446, -446, -446, -446,
+     -446, -446, -446, -446, -446, -446, -446, -446, -446, -446,
+     -446, -446, -446, -446, -446, -446, -446, -446, -446, -446,
+     -446, -446, -446, -446, -446, -446, -446, -446, -446, -446,
+     -446, -446, -446, -446, -446, -446, -446, -446, -446, -446,
+     -446, -446, -446, -446, -446, -446, -446, -446, -446, -446,
+
+     -446, -446, -446, -446, -446, -446, -446, -446
+    },
+
+    {
+       15, -447, -447, -447, -447, -447, -447, -447, -447, -447,
+     -447, -447, -447, -447, -447, -447, -447, -447, -447, -447,
+     -447, -447, -447, -447, -447, -447, -447, -447, -447, -447,
+     -447, -447,  449, -447, -447, -447, -447, -447, -447, -447,
+     -447, -447, -447, -447, -447, -447, -447, -447, -447, -447,
+     -447, -447, -447, -447, -447, -447, -447, -447, -447, -447,
+     -447, -447, -447, -447, -447, -447, -447, -447, -447, -447,
+     -447, -447, -447, -447, -447, -447, -447, -447, -447, -447,
+     -447, -447, -447, -447, -447, -447, -447, -447, -447, -447,
+
+     -447, -447, -447, -447, -447, -447, -447, -447, -447, -447,
+     -447, -447, -447, -447, -447, -447, -447, -447, -447, -447,
+     -447, -447, -447, -447, -447, -447, -447, -447, -447, -447,
+     -447, -447, -447, -447, -447, -447, -447, -447
+    },
+
+    {
+       15, -448, -448, -448, -448, -448, -448, -448, -448, -448,
+     -448, -448, -448, -448, -448, -448, -448, -448, -448, -448,
+     -448, -448, -448, -448, -448, -448, -448, -448, -448, -448,
+     -448, -448,  450, -448, -448, -448, -448, -448, -448, -448,
+     -448, -448, -448, -448, -448, -448, -448, -448, -448, -448,
+     -448, -448, -448, -448, -448, -448, -448, -448, -448, -448,
+
+     -448, -448, -448, -448, -448, -448, -448, -448, -448, -448,
+     -448, -448, -448, -448, -448, -448, -448, -448, -448, -448,
+     -448, -448, -448, -448, -448, -448, -448, -448, -448, -448,
+     -448, -448, -448, -448, -448, -448, -448, -448, -448, -448,
+     -448, -448, -448, -448, -448, -448, -448, -448, -448, -448,
+     -448, -448, -448, -448, -448, -448, -448, -448, -448, -448,
+     -448, -448, -448, -448, -448, -448, -448, -448
+    },
+
+    {
+       15, -449, -449, -449, -449, -449, -449, -449, -449, -449,
+     -449, -449, -449, -449, -449, -449, -449, -449, -449, -449,
+     -449, -449, -449, -449, -449, -449, -449, -449, -449, -449,
+
+     -449, -449,  451, -449, -449, -449, -449, -449, -449, -449,
+     -449, -449, -449, -449, -449, -449, -449, -449, -449, -449,
+     -449, -449, -449, -449, -449, -449, -449, -449, -449, -449,
+     -449, -449, -449, -449, -449, -449, -449, -449, -449, -449,
+     -449, -449, -449, -449, -449, -449, -449, -449, -449, -449,
+     -449, -449, -449, -449, -449, -449, -449, -449, -449, -449,
+     -449, -449, -449, -449, -449, -449, -449, -449, -449, -449,
+     -449, -449, -449, -449, -449, -449, -449, -449, -449, -449,
+     -449, -449, -449, -449, -449, -449, -449, -449, -449, -449,
+     -449, -449, -449, -449, -449, -449, -449, -449
+
+    },
+
+    {
+       15, -450, -450, -450, -450, -450, -450, -450, -450, -450,
+     -450, -450, -450, -450, -450, -450, -450, -450, -450, -450,
+     -450, -450, -450, -450, -450, -450, -450, -450, -450, -450,
+     -450, -450,  452, -450, -450, -450, -450, -450, -450, -450,
+     -450, -450, -450, -450, -450, -450, -450, -450, -450, -450,
+     -450, -450, -450, -450, -450, -450, -450, -450, -450, -450,
+     -450, -450, -450, -450, -450, -450, -450, -450, -450, -450,
+     -450, -450, -450, -450, -450, -450, -450, -450, -450, -450,
+     -450, -450, -450, -450, -450, -450, -450, -450, -450, -450,
+     -450, -450, -450, -450, -450, -450, -450, -450, -450, -450,
+
+     -450, -450, -450, -450, -450, -450, -450, -450, -450, -450,
+     -450, -450, -450, -450, -450, -450, -450, -450, -450, -450,
+     -450, -450, -450, -450, -450, -450, -450, -450
+    },
+
+    {
+       15, -451, -451, -451, -451, -451, -451, -451, -451, -451,
+     -451, -451, -451, -451, -451, -451, -451, -451, -451, -451,
+     -451, -451, -451, -451, -451, -451, -451, -451, -451, -451,
+     -451, -451,  453, -451, -451, -451, -451, -451, -451, -451,
+     -451, -451, -451, -451, -451, -451, -451, -451, -451, -451,
+     -451, -451, -451, -451, -451, -451, -451, -451, -451, -451,
+     -451, -451, -451, -451, -451, -451, -451, -451, -451, -451,
+
+     -451, -451, -451, -451, -451, -451, -451, -451, -451, -451,
+     -451, -451, -451, -451, -451, -451, -451, -451, -451, -451,
+     -451, -451, -451, -451, -451, -451, -451, -451, -451, -451,
+     -451, -451, -451, -451, -451, -451, -451, -451, -451, -451,
+     -451, -451, -451, -451, -451, -451, -451, -451, -451, -451,
+     -451, -451, -451, -451, -451, -451, -451, -451
+    },
+
+    {
+       15, -452, -452, -452, -452, -452, -452, -452, -452, -452,
+     -452, -452, -452, -452, -452, -452, -452, -452, -452, -452,
+     -452, -452, -452, -452, -452, -452, -452, -452, -452, -452,
+     -452, -452,  454, -452, -452, -452, -452, -452, -452, -452,
+
+     -452, -452, -452, -452, -452, -452, -452, -452, -452, -452,
+     -452, -452, -452, -452, -452, -452, -452, -452, -452, -452,
+     -452, -452, -452, -452, -452, -452, -452, -452, -452, -452,
+     -452, -452, -452, -452, -452, -452, -452, -452, -452, -452,
+     -452, -452, -452, -452, -452, -452, -452, -452, -452, -452,
+     -452, -452, -452, -452, -452, -452, -452, -452, -452, -452,
+     -452, -452, -452, -452, -452, -452, -452, -452, -452, -452,
+     -452, -452, -452, -452, -452, -452, -452, -452, -452, -452,
+     -452, -452, -452, -452, -452, -452, -452, -452
+    },
+
+    {
+       15, -453, -453, -453, -453, -453, -453, -453, -453, -453,
+
+     -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
+     -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
+     -453, -453,  455, -453, -453, -453, -453, -453, -453, -453,
+     -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
+     -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
+     -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
+     -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
+     -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
+     -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
+     -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
+
+     -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
+     -453, -453, -453, -453, -453, -453, -453, -453
+    },
+
+    {
+       15, -454, -454, -454, -454, -454, -454, -454, -454, -454,
+     -454, -454, -454, -454, -454, -454, -454, -454, -454, -454,
+     -454, -454, -454, -454, -454, -454, -454, -454, -454, -454,
+     -454, -454,  456, -454, -454, -454, -454, -454, -454, -454,
+     -454, -454, -454, -454, -454, -454, -454, -454, -454, -454,
+     -454, -454, -454, -454, -454, -454, -454, -454, -454, -454,
+     -454, -454, -454, -454, -454, -454, -454, -454, -454, -454,
+     -454, -454, -454, -454, -454, -454, -454, -454, -454, -454,
+
+     -454, -454, -454, -454, -454, -454, -454, -454, -454, -454,
+     -454, -454, -454, -454, -454, -454, -454, -454, -454, -454,
+     -454, -454, -454, -454, -454, -454, -454, -454, -454, -454,
+     -454, -454, -454, -454, -454, -454, -454, -454, -454, -454,
+     -454, -454, -454, -454, -454, -454, -454, -454
+    },
+
+    {
+       15, -455, -455, -455, -455, -455, -455, -455, -455, -455,
+     -455, -455, -455, -455, -455, -455, -455, -455, -455, -455,
+     -455, -455, -455, -455, -455, -455, -455, -455, -455, -455,
+     -455, -455,  457, -455, -455, -455, -455, -455, -455, -455,
+     -455, -455, -455, -455, -455, -455, -455, -455, -455, -455,
+
+     -455, -455, -455, -455, -455, -455, -455, -455, -455, -455,
+     -455, -455, -455, -455, -455, -455, -455, -455, -455, -455,
+     -455, -455, -455, -455, -455, -455, -455, -455, -455, -455,
+     -455, -455, -455, -455, -455, -455, -455, -455, -455, -455,
+     -455, -455, -455, -455, -455, -455, -455, -455, -455, -455,
+     -455, -455, -455, -455, -455, -455, -455, -455, -455, -455,
+     -455, -455, -455, -455, -455, -455, -455, -455, -455, -455,
+     -455, -455, -455, -455, -455, -455, -455, -455
+    },
+
+    {
+       15, -456, -456, -456, -456, -456, -456, -456, -456, -456,
+     -456, -456, -456, -456, -456, -456, -456, -456, -456, -456,
+
+     -456, -456, -456, -456, -456, -456, -456, -456, -456, -456,
+     -456, -456,  458, -456, -456, -456, -456, -456, -456, -456,
+     -456, -456, -456, -456, -456, -456, -456, -456, -456, -456,
+     -456, -456, -456, -456, -456, -456, -456, -456, -456, -456,
+     -456, -456, -456, -456, -456, -456, -456, -456, -456, -456,
+     -456, -456, -456, -456, -456, -456, -456, -456, -456, -456,
+     -456, -456, -456, -456, -456, -456, -456, -456, -456, -456,
+     -456, -456, -456, -456, -456, -456, -456, -456, -456, -456,
+     -456, -456, -456, -456, -456, -456, -456, -456, -456, -456,
+     -456, -456, -456, -456, -456, -456, -456, -456, -456, -456,
+
+     -456, -456, -456, -456, -456, -456, -456, -456
+    },
+
+    {
+       15, -457, -457, -457, -457, -457, -457, -457, -457, -457,
+     -457, -457, -457, -457, -457, -457, -457, -457, -457, -457,
+     -457, -457, -457, -457, -457, -457, -457, -457, -457, -457,
+     -457, -457,  459, -457, -457, -457, -457, -457, -457, -457,
+     -457, -457, -457, -457, -457, -457, -457, -457, -457, -457,
+     -457, -457, -457, -457, -457, -457, -457, -457, -457, -457,
+     -457, -457, -457, -457, -457, -457, -457, -457, -457, -457,
+     -457, -457, -457, -457, -457, -457, -457, -457, -457, -457,
+     -457, -457, -457, -457, -457, -457, -457, -457, -457, -457,
+
+     -457, -457, -457, -457, -457, -457, -457, -457, -457, -457,
+     -457, -457, -457, -457, -457, -457, -457, -457, -457, -457,
+     -457, -457, -457, -457, -457, -457, -457, -457, -457, -457,
+     -457, -457, -457, -457, -457, -457, -457, -457
+    },
+
+    {
+       15, -458, -458, -458, -458, -458, -458, -458, -458, -458,
+     -458, -458, -458, -458, -458, -458, -458, -458, -458, -458,
+     -458, -458, -458, -458, -458, -458, -458, -458, -458, -458,
+     -458, -458,  460, -458, -458, -458, -458, -458, -458, -458,
+     -458, -458, -458, -458, -458, -458, -458, -458, -458, -458,
+     -458, -458, -458, -458, -458, -458, -458, -458, -458, -458,
+
+     -458, -458, -458, -458, -458, -458, -458, -458, -458, -458,
+     -458, -458, -458, -458, -458, -458, -458, -458, -458, -458,
+     -458, -458, -458, -458, -458, -458, -458, -458, -458, -458,
+     -458, -458, -458, -458, -458, -458, -458, -458, -458, -458,
+     -458, -458, -458, -458, -458, -458, -458, -458, -458, -458,
+     -458, -458, -458, -458, -458, -458, -458, -458, -458, -458,
+     -458, -458, -458, -458, -458, -458, -458, -458
+    },
+
+    {
+       15, -459, -459, -459, -459, -459, -459, -459, -459, -459,
+     -459, -459, -459, -459, -459, -459, -459, -459, -459, -459,
+     -459, -459, -459, -459, -459, -459, -459, -459, -459, -459,
+
+     -459, -459,  461, -459, -459, -459, -459, -459, -459, -459,
+     -459, -459, -459, -459, -459, -459, -459, -459, -459, -459,
+     -459, -459, -459, -459, -459, -459, -459, -459, -459, -459,
+     -459, -459, -459, -459, -459, -459, -459, -459, -459, -459,
+     -459, -459, -459, -459, -459, -459, -459, -459, -459, -459,
+     -459, -459, -459, -459, -459, -459, -459, -459, -459, -459,
+     -459, -459, -459, -459, -459, -459, -459, -459, -459, -459,
+     -459, -459, -459, -459, -459, -459, -459, -459, -459, -459,
+     -459, -459, -459, -459, -459, -459, -459, -459, -459, -459,
+     -459, -459, -459, -459, -459, -459, -459, -459
+
+    },
+
+    {
+       15, -460, -460, -460, -460, -460, -460, -460, -460, -460,
+     -460, -460, -460, -460, -460, -460, -460, -460, -460, -460,
+     -460, -460, -460, -460, -460, -460, -460, -460, -460, -460,
+     -460, -460,  462, -460, -460, -460, -460, -460, -460, -460,
+     -460, -460, -460, -460, -460, -460, -460, -460, -460, -460,
+     -460, -460, -460, -460, -460, -460, -460, -460, -460, -460,
+     -460, -460, -460, -460, -460, -460, -460, -460, -460, -460,
+     -460, -460, -460, -460, -460, -460, -460, -460, -460, -460,
+     -460, -460, -460, -460, -460, -460, -460, -460, -460, -460,
+     -460, -460, -460, -460, -460, -460, -460, -460, -460, -460,
+
+     -460, -460, -460, -460, -460, -460, -460, -460, -460, -460,
+     -460, -460, -460, -460, -460, -460, -460, -460, -460, -460,
+     -460, -460, -460, -460, -460, -460, -460, -460
+    },
+
+    {
+       15, -461, -461, -461, -461, -461, -461, -461, -461, -461,
+     -461, -461, -461, -461, -461, -461, -461, -461, -461, -461,
+     -461, -461, -461, -461, -461, -461, -461, -461, -461, -461,
+     -461, -461,  463, -461, -461, -461, -461, -461, -461, -461,
+     -461, -461, -461, -461, -461, -461, -461, -461, -461, -461,
+     -461, -461, -461, -461, -461, -461, -461, -461, -461, -461,
+     -461, -461, -461, -461, -461, -461, -461, -461, -461, -461,
+
+     -461, -461, -461, -461, -461, -461, -461, -461, -461, -461,
+     -461, -461, -461, -461, -461, -461, -461, -461, -461, -461,
+     -461, -461, -461, -461, -461, -461, -461, -461, -461, -461,
+     -461, -461, -461, -461, -461, -461, -461, -461, -461, -461,
+     -461, -461, -461, -461, -461, -461, -461, -461, -461, -461,
+     -461, -461, -461, -461, -461, -461, -461, -461
+    },
+
+    {
+       15, -462, -462, -462, -462, -462, -462, -462, -462, -462,
+     -462, -462, -462, -462, -462, -462, -462, -462, -462, -462,
+     -462, -462, -462, -462, -462, -462, -462, -462, -462, -462,
+     -462, -462,  464, -462, -462, -462, -462, -462, -462, -462,
+
+     -462, -462, -462, -462, -462, -462, -462, -462, -462, -462,
+     -462, -462, -462, -462, -462, -462, -462, -462, -462, -462,
+     -462, -462, -462, -462, -462, -462, -462, -462, -462, -462,
+     -462, -462, -462, -462, -462, -462, -462, -462, -462, -462,
+     -462, -462, -462, -462, -462, -462, -462, -462, -462, -462,
+     -462, -462, -462, -462, -462, -462, -462, -462, -462, -462,
+     -462, -462, -462, -462, -462, -462, -462, -462, -462, -462,
+     -462, -462, -462, -462, -462, -462, -462, -462, -462, -462,
+     -462, -462, -462, -462, -462, -462, -462, -462
+    },
+
+    {
+       15, -463, -463, -463, -463, -463, -463, -463, -463, -463,
+
+     -463, -463, -463, -463, -463, -463, -463, -463, -463, -463,
+     -463, -463, -463, -463, -463, -463, -463, -463, -463, -463,
+     -463, -463,  465, -463, -463, -463, -463, -463, -463, -463,
+     -463, -463, -463, -463, -463, -463, -463, -463, -463, -463,
+     -463, -463, -463, -463, -463, -463, -463, -463, -463, -463,
+     -463, -463, -463, -463, -463, -463, -463, -463, -463, -463,
+     -463, -463, -463, -463, -463, -463, -463, -463, -463, -463,
+     -463, -463, -463, -463, -463, -463, -463, -463, -463, -463,
+     -463, -463, -463, -463, -463, -463, -463, -463, -463, -463,
+     -463, -463, -463, -463, -463, -463, -463, -463, -463, -463,
+
+     -463, -463, -463, -463, -463, -463, -463, -463, -463, -463,
+     -463, -463, -463, -463, -463, -463, -463, -463
+    },
+
+    {
+       15, -464, -464, -464, -464, -464, -464, -464, -464, -464,
+     -464, -464, -464, -464, -464, -464, -464, -464, -464, -464,
+     -464, -464, -464, -464, -464, -464, -464, -464, -464, -464,
+     -464, -464,  466, -464, -464, -464, -464, -464, -464, -464,
+     -464, -464, -464, -464, -464, -464, -464, -464, -464, -464,
+     -464, -464, -464, -464, -464, -464, -464, -464, -464, -464,
+     -464, -464, -464, -464, -464, -464, -464, -464, -464, -464,
+     -464, -464, -464, -464, -464, -464, -464, -464, -464, -464,
+
+     -464, -464, -464, -464, -464, -464, -464, -464, -464, -464,
+     -464, -464, -464, -464, -464, -464, -464, -464, -464, -464,
+     -464, -464, -464, -464, -464, -464, -464, -464, -464, -464,
+     -464, -464, -464, -464, -464, -464, -464, -464, -464, -464,
+     -464, -464, -464, -464, -464, -464, -464, -464
+    },
+
+    {
+       15, -465, -465, -465, -465, -465, -465, -465, -465, -465,
+     -465, -465, -465, -465, -465, -465, -465, -465, -465, -465,
+     -465, -465, -465, -465, -465, -465, -465, -465, -465, -465,
+     -465, -465,  467, -465, -465, -465, -465, -465, -465, -465,
+     -465, -465, -465, -465, -465, -465, -465, -465, -465, -465,
+
+     -465, -465, -465, -465, -465, -465, -465, -465, -465, -465,
+     -465, -465, -465, -465, -465, -465, -465, -465, -465, -465,
+     -465, -465, -465, -465, -465, -465, -465, -465, -465, -465,
+     -465, -465, -465, -465, -465, -465, -465, -465, -465, -465,
+     -465, -465, -465, -465, -465, -465, -465, -465, -465, -465,
+     -465, -465, -465, -465, -465, -465, -465, -465, -465, -465,
+     -465, -465, -465, -465, -465, -465, -465, -465, -465, -465,
+     -465, -465, -465, -465, -465, -465, -465, -465
+    },
+
+    {
+       15, -466, -466, -466, -466, -466, -466, -466, -466, -466,
+     -466, -466, -466, -466, -466, -466, -466, -466, -466, -466,
+
+     -466, -466, -466, -466, -466, -466, -466, -466, -466, -466,
+     -466, -466,  468, -466, -466, -466, -466, -466, -466, -466,
+     -466, -466, -466, -466, -466, -466, -466, -466, -466, -466,
+     -466, -466, -466, -466, -466, -466, -466, -466, -466, -466,
+     -466, -466, -466, -466, -466, -466, -466, -466, -466, -466,
+     -466, -466, -466, -466, -466, -466, -466, -466, -466, -466,
+     -466, -466, -466, -466, -466, -466, -466, -466, -466, -466,
+     -466, -466, -466, -466, -466, -466, -466, -466, -466, -466,
+     -466, -466, -466, -466, -466, -466, -466, -466, -466, -466,
+     -466, -466, -466, -466, -466, -466, -466, -466, -466, -466,
+
+     -466, -466, -466, -466, -466, -466, -466, -466
+    },
+
+    {
+       15, -467, -467, -467, -467, -467, -467, -467, -467, -467,
+     -467, -467, -467, -467, -467, -467, -467, -467, -467, -467,
+     -467, -467, -467, -467, -467, -467, -467, -467, -467, -467,
+     -467, -467,  469, -467, -467, -467, -467, -467, -467, -467,
+     -467, -467, -467, -467, -467, -467, -467, -467, -467, -467,
+     -467, -467, -467, -467, -467, -467, -467, -467, -467, -467,
+     -467, -467, -467, -467, -467, -467, -467, -467, -467, -467,
+     -467, -467, -467, -467, -467, -467, -467, -467, -467, -467,
+     -467, -467, -467, -467, -467, -467, -467, -467, -467, -467,
+
+     -467, -467, -467, -467, -467, -467, -467, -467, -467, -467,
+     -467, -467, -467, -467, -467, -467, -467, -467, -467, -467,
+     -467, -467, -467, -467, -467, -467, -467, -467, -467, -467,
+     -467, -467, -467, -467, -467, -467, -467, -467
+    },
+
+    {
+       15, -468, -468, -468, -468, -468, -468, -468, -468, -468,
+     -468, -468, -468, -468, -468, -468, -468, -468, -468, -468,
+     -468, -468, -468, -468, -468, -468, -468, -468, -468, -468,
+     -468, -468,  470, -468, -468, -468, -468, -468, -468, -468,
+     -468, -468, -468, -468, -468, -468, -468, -468, -468, -468,
+     -468, -468, -468, -468, -468, -468, -468, -468, -468, -468,
+
+     -468, -468, -468, -468, -468, -468, -468, -468, -468, -468,
+     -468, -468, -468, -468, -468, -468, -468, -468, -468, -468,
+     -468, -468, -468, -468, -468, -468, -468, -468, -468, -468,
+     -468, -468, -468, -468, -468, -468, -468, -468, -468, -468,
+     -468, -468, -468, -468, -468, -468, -468, -468, -468, -468,
+     -468, -468, -468, -468, -468, -468, -468, -468, -468, -468,
+     -468, -468, -468, -468, -468, -468, -468, -468
+    },
+
+    {
+       15, -469, -469, -469, -469, -469, -469, -469, -469, -469,
+     -469, -469, -469, -469, -469, -469, -469, -469, -469, -469,
+     -469, -469, -469, -469, -469, -469, -469, -469, -469, -469,
+
+     -469, -469,  471, -469, -469, -469, -469, -469, -469, -469,
+     -469, -469, -469, -469, -469, -469, -469, -469, -469, -469,
+     -469, -469, -469, -469, -469, -469, -469, -469, -469, -469,
+     -469, -469, -469, -469, -469, -469, -469, -469, -469, -469,
+     -469, -469, -469, -469, -469, -469, -469, -469, -469, -469,
+     -469, -469, -469, -469, -469, -469, -469, -469, -469, -469,
+     -469, -469, -469, -469, -469, -469, -469, -469, -469, -469,
+     -469, -469, -469, -469, -469, -469, -469, -469, -469, -469,
+     -469, -469, -469, -469, -469, -469, -469, -469, -469, -469,
+     -469, -469, -469, -469, -469, -469, -469, -469
+
+    },
+
+    {
+       15, -470, -470, -470, -470, -470, -470, -470, -470, -470,
+     -470, -470, -470, -470, -470, -470, -470, -470, -470, -470,
+     -470, -470, -470, -470, -470, -470, -470, -470, -470, -470,
+     -470, -470,  472, -470, -470, -470, -470, -470, -470, -470,
+     -470, -470, -470, -470, -470, -470, -470, -470, -470, -470,
+     -470, -470, -470, -470, -470, -470, -470, -470, -470, -470,
+     -470, -470, -470, -470, -470, -470, -470, -470, -470, -470,
+     -470, -470, -470, -470, -470, -470, -470, -470, -470, -470,
+     -470, -470, -470, -470, -470, -470, -470, -470, -470, -470,
+     -470, -470, -470, -470, -470, -470, -470, -470, -470, -470,
+
+     -470, -470, -470, -470, -470, -470, -470, -470, -470, -470,
+     -470, -470, -470, -470, -470, -470, -470, -470, -470, -470,
+     -470, -470, -470, -470, -470, -470, -470, -470
+    },
+
+    {
+       15, -471, -471, -471, -471, -471, -471, -471, -471, -471,
+     -471, -471, -471, -471, -471, -471, -471, -471, -471, -471,
+     -471, -471, -471, -471, -471, -471, -471, -471, -471, -471,
+     -471, -471,  473, -471, -471, -471, -471, -471, -471, -471,
+     -471, -471, -471, -471, -471, -471, -471, -471, -471, -471,
+     -471, -471, -471, -471, -471, -471, -471, -471, -471, -471,
+     -471, -471, -471, -471, -471, -471, -471, -471, -471, -471,
+
+     -471, -471, -471, -471, -471, -471, -471, -471, -471, -471,
+     -471, -471, -471, -471, -471, -471, -471, -471, -471, -471,
+     -471, -471, -471, -471, -471, -471, -471, -471, -471, -471,
+     -471, -471, -471, -471, -471, -471, -471, -471, -471, -471,
+     -471, -471, -471, -471, -471, -471, -471, -471, -471, -471,
+     -471, -471, -471, -471, -471, -471, -471, -471
+    },
+
+    {
+       15, -472, -472, -472, -472, -472, -472, -472, -472, -472,
+     -472, -472, -472, -472, -472, -472, -472, -472, -472, -472,
+     -472, -472, -472, -472, -472, -472, -472, -472, -472, -472,
+     -472, -472,  474, -472, -472, -472, -472, -472, -472, -472,
+
+     -472, -472, -472, -472, -472, -472, -472, -472, -472, -472,
+     -472, -472, -472, -472, -472, -472, -472, -472, -472, -472,
+     -472, -472, -472, -472, -472, -472, -472, -472, -472, -472,
+     -472, -472, -472, -472, -472, -472, -472, -472, -472, -472,
+     -472, -472, -472, -472, -472, -472, -472, -472, -472, -472,
+     -472, -472, -472, -472, -472, -472, -472, -472, -472, -472,
+     -472, -472, -472, -472, -472, -472, -472, -472, -472, -472,
+     -472, -472, -472, -472, -472, -472, -472, -472, -472, -472,
+     -472, -472, -472, -472, -472, -472, -472, -472
+    },
+
+    {
+       15, -473, -473, -473, -473, -473, -473, -473, -473, -473,
+
+     -473, -473, -473, -473, -473, -473, -473, -473, -473, -473,
+     -473, -473, -473, -473, -473, -473, -473, -473, -473, -473,
+     -473, -473,  475, -473, -473, -473, -473, -473, -473, -473,
+     -473, -473, -473, -473, -473, -473, -473, -473, -473, -473,
+     -473, -473, -473, -473, -473, -473, -473, -473, -473, -473,
+     -473, -473, -473, -473, -473, -473, -473, -473, -473, -473,
+     -473, -473, -473, -473, -473, -473, -473, -473, -473, -473,
+     -473, -473, -473, -473, -473, -473, -473, -473, -473, -473,
+     -473, -473, -473, -473, -473, -473, -473, -473, -473, -473,
+     -473, -473, -473, -473, -473, -473, -473, -473, -473, -473,
+
+     -473, -473, -473, -473, -473, -473, -473, -473, -473, -473,
+     -473, -473, -473, -473, -473, -473, -473, -473
+    },
+
+    {
+       15, -474, -474, -474, -474, -474, -474, -474, -474, -474,
+     -474, -474, -474, -474, -474, -474, -474, -474, -474, -474,
+     -474, -474, -474, -474, -474, -474, -474, -474, -474, -474,
+     -474, -474,  476, -474, -474, -474, -474, -474, -474, -474,
+     -474, -474, -474, -474, -474, -474, -474, -474, -474, -474,
+     -474, -474, -474, -474, -474, -474, -474, -474, -474, -474,
+     -474, -474, -474, -474, -474, -474, -474, -474, -474, -474,
+     -474, -474, -474, -474, -474, -474, -474, -474, -474, -474,
+
+     -474, -474, -474, -474, -474, -474, -474, -474, -474, -474,
+     -474, -474, -474, -474, -474, -474, -474, -474, -474, -474,
+     -474, -474, -474, -474, -474, -474, -474, -474, -474, -474,
+     -474, -474, -474, -474, -474, -474, -474, -474, -474, -474,
+     -474, -474, -474, -474, -474, -474, -474, -474
+    },
+
+    {
+       15, -475, -475, -475, -475, -475, -475, -475, -475, -475,
+     -475, -475, -475, -475, -475, -475, -475, -475, -475, -475,
+     -475, -475, -475, -475, -475, -475, -475, -475, -475, -475,
+     -475, -475,  477, -475, -475, -475, -475, -475, -475, -475,
+     -475, -475, -475, -475, -475, -475, -475, -475, -475, -475,
+
+     -475, -475, -475, -475, -475, -475, -475, -475, -475, -475,
+     -475, -475, -475, -475, -475, -475, -475, -475, -475, -475,
+     -475, -475, -475, -475, -475, -475, -475, -475, -475, -475,
+     -475, -475, -475, -475, -475, -475, -475, -475, -475, -475,
+     -475, -475, -475, -475, -475, -475, -475, -475, -475, -475,
+     -475, -475, -475, -475, -475, -475, -475, -475, -475, -475,
+     -475, -475, -475, -475, -475, -475, -475, -475, -475, -475,
+     -475, -475, -475, -475, -475, -475, -475, -475
+    },
+
+    {
+       15, -476, -476, -476, -476, -476, -476, -476, -476, -476,
+     -476, -476, -476, -476, -476, -476, -476, -476, -476, -476,
+
+     -476, -476, -476, -476, -476, -476, -476, -476, -476, -476,
+     -476, -476,  478, -476, -476, -476, -476, -476, -476, -476,
+     -476, -476, -476, -476, -476, -476, -476, -476, -476, -476,
+     -476, -476, -476, -476, -476, -476, -476, -476, -476, -476,
+     -476, -476, -476, -476, -476, -476, -476, -476, -476, -476,
+     -476, -476, -476, -476, -476, -476, -476, -476, -476, -476,
+     -476, -476, -476, -476, -476, -476, -476, -476, -476, -476,
+     -476, -476, -476, -476, -476, -476, -476, -476, -476, -476,
+     -476, -476, -476, -476, -476, -476, -476, -476, -476, -476,
+     -476, -476, -476, -476, -476, -476, -476, -476, -476, -476,
+
+     -476, -476, -476, -476, -476, -476, -476, -476
+    },
+
+    {
+       15, -477, -477, -477, -477, -477, -477, -477, -477, -477,
+     -477, -477, -477, -477, -477, -477, -477, -477, -477, -477,
+     -477, -477, -477, -477, -477, -477, -477, -477, -477, -477,
+     -477, -477,  479, -477, -477, -477, -477, -477, -477, -477,
+     -477, -477, -477, -477, -477, -477, -477, -477, -477, -477,
+     -477, -477, -477, -477, -477, -477, -477, -477, -477, -477,
+     -477, -477, -477, -477, -477, -477, -477, -477, -477, -477,
+     -477, -477, -477, -477, -477, -477, -477, -477, -477, -477,
+     -477, -477, -477, -477, -477, -477, -477, -477, -477, -477,
+
+     -477, -477, -477, -477, -477, -477, -477, -477, -477, -477,
+     -477, -477, -477, -477, -477, -477, -477, -477, -477, -477,
+     -477, -477, -477, -477, -477, -477, -477, -477, -477, -477,
+     -477, -477, -477, -477, -477, -477, -477, -477
+    },
+
+    {
+       15, -478, -478, -478, -478, -478, -478, -478, -478, -478,
+     -478, -478, -478, -478, -478, -478, -478, -478, -478, -478,
+     -478, -478, -478, -478, -478, -478, -478, -478, -478, -478,
+     -478, -478,  480, -478, -478, -478, -478, -478, -478, -478,
+     -478, -478, -478, -478, -478, -478, -478, -478, -478, -478,
+     -478, -478, -478, -478, -478, -478, -478, -478, -478, -478,
+
+     -478, -478, -478, -478, -478, -478, -478, -478, -478, -478,
+     -478, -478, -478, -478, -478, -478, -478, -478, -478, -478,
+     -478, -478, -478, -478, -478, -478, -478, -478, -478, -478,
+     -478, -478, -478, -478, -478, -478, -478, -478, -478, -478,
+     -478, -478, -478, -478, -478, -478, -478, -478, -478, -478,
+     -478, -478, -478, -478, -478, -478, -478, -478, -478, -478,
+     -478, -478, -478, -478, -478, -478, -478, -478
+    },
+
+    {
+       15, -479, -479, -479, -479, -479, -479, -479, -479, -479,
+     -479, -479, -479, -479, -479, -479, -479, -479, -479, -479,
+     -479, -479, -479, -479, -479, -479, -479, -479, -479, -479,
+
+     -479, -479,  481, -479, -479, -479, -479, -479, -479, -479,
+     -479, -479, -479, -479, -479, -479, -479, -479, -479, -479,
+     -479, -479, -479, -479, -479, -479, -479, -479, -479, -479,
+     -479, -479, -479, -479, -479, -479, -479, -479, -479, -479,
+     -479, -479, -479, -479, -479, -479, -479, -479, -479, -479,
+     -479, -479, -479, -479, -479, -479, -479, -479, -479, -479,
+     -479, -479, -479, -479, -479, -479, -479, -479, -479, -479,
+     -479, -479, -479, -479, -479, -479, -479, -479, -479, -479,
+     -479, -479, -479, -479, -479, -479, -479, -479, -479, -479,
+     -479, -479, -479, -479, -479, -479, -479, -479
+
+    },
+
+    {
+       15, -480, -480, -480, -480, -480, -480, -480, -480, -480,
+     -480, -480, -480, -480, -480, -480, -480, -480, -480, -480,
+     -480, -480, -480, -480, -480, -480, -480, -480, -480, -480,
+     -480, -480,  482, -480, -480, -480, -480, -480, -480, -480,
+     -480, -480, -480, -480, -480, -480, -480, -480, -480, -480,
+     -480, -480, -480, -480, -480, -480, -480, -480, -480, -480,
+     -480, -480, -480, -480, -480, -480, -480, -480, -480, -480,
+     -480, -480, -480, -480, -480, -480, -480, -480, -480, -480,
+     -480, -480, -480, -480, -480, -480, -480, -480, -480, -480,
+     -480, -480, -480, -480, -480, -480, -480, -480, -480, -480,
+
+     -480, -480, -480, -480, -480, -480, -480, -480, -480, -480,
+     -480, -480, -480, -480, -480, -480, -480, -480, -480, -480,
+     -480, -480, -480, -480, -480, -480, -480, -480
+    },
+
+    {
+       15, -481, -481, -481, -481, -481, -481, -481, -481, -481,
+     -481, -481, -481, -481, -481, -481, -481, -481, -481, -481,
+     -481, -481, -481, -481, -481, -481, -481, -481, -481, -481,
+     -481, -481,  483, -481, -481, -481, -481, -481, -481, -481,
+     -481, -481, -481, -481, -481, -481, -481, -481, -481, -481,
+     -481, -481, -481, -481, -481, -481, -481, -481, -481, -481,
+     -481, -481, -481, -481, -481, -481, -481, -481, -481, -481,
+
+     -481, -481, -481, -481, -481, -481, -481, -481, -481, -481,
+     -481, -481, -481, -481, -481, -481, -481, -481, -481, -481,
+     -481, -481, -481, -481, -481, -481, -481, -481, -481, -481,
+     -481, -481, -481, -481, -481, -481, -481, -481, -481, -481,
+     -481, -481, -481, -481, -481, -481, -481, -481, -481, -481,
+     -481, -481, -481, -481, -481, -481, -481, -481
+    },
+
+    {
+       15, -482, -482, -482, -482, -482, -482, -482, -482, -482,
+     -482, -482, -482, -482, -482, -482, -482, -482, -482, -482,
+     -482, -482, -482, -482, -482, -482, -482, -482, -482, -482,
+     -482, -482,  484, -482, -482, -482, -482, -482, -482, -482,
+
+     -482, -482, -482, -482, -482, -482, -482, -482, -482, -482,
+     -482, -482, -482, -482, -482, -482, -482, -482, -482, -482,
+     -482, -482, -482, -482, -482, -482, -482, -482, -482, -482,
+     -482, -482, -482, -482, -482, -482, -482, -482, -482, -482,
+     -482, -482, -482, -482, -482, -482, -482, -482, -482, -482,
+     -482, -482, -482, -482, -482, -482, -482, -482, -482, -482,
+     -482, -482, -482, -482, -482, -482, -482, -482, -482, -482,
+     -482, -482, -482, -482, -482, -482, -482, -482, -482, -482,
+     -482, -482, -482, -482, -482, -482, -482, -482
+    },
+
+    {
+       15, -483, -483, -483, -483, -483, -483, -483, -483, -483,
+
+     -483, -483, -483, -483, -483, -483, -483, -483, -483, -483,
+     -483, -483, -483, -483, -483, -483, -483, -483, -483, -483,
+     -483, -483,  485, -483, -483, -483, -483, -483, -483, -483,
+     -483, -483, -483, -483, -483, -483, -483, -483, -483, -483,
+     -483, -483, -483, -483, -483, -483, -483, -483, -483, -483,
+     -483, -483, -483, -483, -483, -483, -483, -483, -483, -483,
+     -483, -483, -483, -483, -483, -483, -483, -483, -483, -483,
+     -483, -483, -483, -483, -483, -483, -483, -483, -483, -483,
+     -483, -483, -483, -483, -483, -483, -483, -483, -483, -483,
+     -483, -483, -483, -483, -483, -483, -483, -483, -483, -483,
+
+     -483, -483, -483, -483, -483, -483, -483, -483, -483, -483,
+     -483, -483, -483, -483, -483, -483, -483, -483
+    },
+
+    {
+       15, -484, -484, -484, -484, -484, -484, -484, -484, -484,
+     -484, -484, -484, -484, -484, -484, -484, -484, -484, -484,
+     -484, -484, -484, -484, -484, -484, -484, -484, -484, -484,
+     -484, -484,  486, -484, -484, -484, -484, -484, -484, -484,
+     -484, -484, -484, -484, -484, -484, -484, -484, -484, -484,
+     -484, -484, -484, -484, -484, -484, -484, -484, -484, -484,
+     -484, -484, -484, -484, -484, -484, -484, -484, -484, -484,
+     -484, -484, -484, -484, -484, -484, -484, -484, -484, -484,
+
+     -484, -484, -484, -484, -484, -484, -484, -484, -484, -484,
+     -484, -484, -484, -484, -484, -484, -484, -484, -484, -484,
+     -484, -484, -484, -484, -484, -484, -484, -484, -484, -484,
+     -484, -484, -484, -484, -484, -484, -484, -484, -484, -484,
+     -484, -484, -484, -484, -484, -484, -484, -484
+    },
+
+    {
+       15, -485, -485, -485, -485, -485, -485, -485, -485, -485,
+     -485, -485, -485, -485, -485, -485, -485, -485, -485, -485,
+     -485, -485, -485, -485, -485, -485, -485, -485, -485, -485,
+     -485, -485,  487, -485, -485, -485, -485, -485, -485, -485,
+     -485, -485, -485, -485, -485, -485, -485, -485, -485, -485,
+
+     -485, -485, -485, -485, -485, -485, -485, -485, -485, -485,
+     -485, -485, -485, -485, -485, -485, -485, -485, -485, -485,
+     -485, -485, -485, -485, -485, -485, -485, -485, -485, -485,
+     -485, -485, -485, -485, -485, -485, -485, -485, -485, -485,
+     -485, -485, -485, -485, -485, -485, -485, -485, -485, -485,
+     -485, -485, -485, -485, -485, -485, -485, -485, -485, -485,
+     -485, -485, -485, -485, -485, -485, -485, -485, -485, -485,
+     -485, -485, -485, -485, -485, -485, -485, -485
+    },
+
+    {
+       15, -486, -486, -486, -486, -486, -486, -486, -486, -486,
+     -486, -486, -486, -486, -486, -486, -486, -486, -486, -486,
+
+     -486, -486, -486, -486, -486, -486, -486, -486, -486, -486,
+     -486, -486,  488, -486, -486, -486, -486, -486, -486, -486,
+     -486, -486, -486, -486, -486, -486, -486, -486, -486, -486,
+     -486, -486, -486, -486, -486, -486, -486, -486, -486, -486,
+     -486, -486, -486, -486, -486, -486, -486, -486, -486, -486,
+     -486, -486, -486, -486, -486, -486, -486, -486, -486, -486,
+     -486, -486, -486, -486, -486, -486, -486, -486, -486, -486,
+     -486, -486, -486, -486, -486, -486, -486, -486, -486, -486,
+     -486, -486, -486, -486, -486, -486, -486, -486, -486, -486,
+     -486, -486, -486, -486, -486, -486, -486, -486, -486, -486,
+
+     -486, -486, -486, -486, -486, -486, -486, -486
+    },
+
+    {
+       15, -487, -487, -487, -487, -487, -487, -487, -487, -487,
+     -487, -487, -487, -487, -487, -487, -487, -487, -487, -487,
+     -487, -487, -487, -487, -487, -487, -487, -487, -487, -487,
+     -487, -487,  489, -487, -487, -487, -487, -487, -487, -487,
+     -487, -487, -487, -487, -487, -487, -487, -487, -487, -487,
+     -487, -487, -487, -487, -487, -487, -487, -487, -487, -487,
+     -487, -487, -487, -487, -487, -487, -487, -487, -487, -487,
+     -487, -487, -487, -487, -487, -487, -487, -487, -487, -487,
+     -487, -487, -487, -487, -487, -487, -487, -487, -487, -487,
+
+     -487, -487, -487, -487, -487, -487, -487, -487, -487, -487,
+     -487, -487, -487, -487, -487, -487, -487, -487, -487, -487,
+     -487, -487, -487, -487, -487, -487, -487, -487, -487, -487,
+     -487, -487, -487, -487, -487, -487, -487, -487
+    },
+
+    {
+       15, -488, -488, -488, -488, -488, -488, -488, -488, -488,
+     -488, -488, -488, -488, -488, -488, -488, -488, -488, -488,
+     -488, -488, -488, -488, -488, -488, -488, -488, -488, -488,
+     -488, -488,  490, -488, -488, -488, -488, -488, -488, -488,
+     -488, -488, -488, -488, -488, -488, -488, -488, -488, -488,
+     -488, -488, -488, -488, -488, -488, -488, -488, -488, -488,
+
+     -488, -488, -488, -488, -488, -488, -488, -488, -488, -488,
+     -488, -488, -488, -488, -488, -488, -488, -488, -488, -488,
+     -488, -488, -488, -488, -488, -488, -488, -488, -488, -488,
+     -488, -488, -488, -488, -488, -488, -488, -488, -488, -488,
+     -488, -488, -488, -488, -488, -488, -488, -488, -488, -488,
+     -488, -488, -488, -488, -488, -488, -488, -488, -488, -488,
+     -488, -488, -488, -488, -488, -488, -488, -488
+    },
+
+    {
+       15, -489, -489, -489, -489, -489, -489, -489, -489, -489,
+     -489, -489, -489, -489, -489, -489, -489, -489, -489, -489,
+     -489, -489, -489, -489, -489, -489, -489, -489, -489, -489,
+
+     -489, -489,  491, -489, -489, -489, -489, -489, -489, -489,
+     -489, -489, -489, -489, -489, -489, -489, -489, -489, -489,
+     -489, -489, -489, -489, -489, -489, -489, -489, -489, -489,
+     -489, -489, -489, -489, -489, -489, -489, -489, -489, -489,
+     -489, -489, -489, -489, -489, -489, -489, -489, -489, -489,
+     -489, -489, -489, -489, -489, -489, -489, -489, -489, -489,
+     -489, -489, -489, -489, -489, -489, -489, -489, -489, -489,
+     -489, -489, -489, -489, -489, -489, -489, -489, -489, -489,
+     -489, -489, -489, -489, -489, -489, -489, -489, -489, -489,
+     -489, -489, -489, -489, -489, -489, -489, -489
+
+    },
+
+    {
+       15, -490, -490, -490, -490, -490, -490, -490, -490, -490,
+     -490, -490, -490, -490, -490, -490, -490, -490, -490, -490,
+     -490, -490, -490, -490, -490, -490, -490, -490, -490, -490,
+     -490, -490,  492, -490, -490, -490, -490, -490, -490, -490,
+     -490, -490, -490, -490, -490, -490, -490, -490, -490, -490,
+     -490, -490, -490, -490, -490, -490, -490, -490, -490, -490,
+     -490, -490, -490, -490, -490, -490, -490, -490, -490, -490,
+     -490, -490, -490, -490, -490, -490, -490, -490, -490, -490,
+     -490, -490, -490, -490, -490, -490, -490, -490, -490, -490,
+     -490, -490, -490, -490, -490, -490, -490, -490, -490, -490,
+
+     -490, -490, -490, -490, -490, -490, -490, -490, -490, -490,
+     -490, -490, -490, -490, -490, -490, -490, -490, -490, -490,
+     -490, -490, -490, -490, -490, -490, -490, -490
+    },
+
+    {
+       15, -491, -491, -491, -491, -491, -491, -491, -491, -491,
+     -491, -491, -491, -491, -491, -491, -491, -491, -491, -491,
+     -491, -491, -491, -491, -491, -491, -491, -491, -491, -491,
+     -491, -491,  493, -491, -491, -491, -491, -491, -491, -491,
+     -491, -491, -491, -491, -491, -491, -491, -491, -491, -491,
+     -491, -491, -491, -491, -491, -491, -491, -491, -491, -491,
+     -491, -491, -491, -491, -491, -491, -491, -491, -491, -491,
+
+     -491, -491, -491, -491, -491, -491, -491, -491, -491, -491,
+     -491, -491, -491, -491, -491, -491, -491, -491, -491, -491,
+     -491, -491, -491, -491, -491, -491, -491, -491, -491, -491,
+     -491, -491, -491, -491, -491, -491, -491, -491, -491, -491,
+     -491, -491, -491, -491, -491, -491, -491, -491, -491, -491,
+     -491, -491, -491, -491, -491, -491, -491, -491
+    },
+
+    {
+       15, -492, -492, -492, -492, -492, -492, -492, -492, -492,
+     -492, -492, -492, -492, -492, -492, -492, -492, -492, -492,
+     -492, -492, -492, -492, -492, -492, -492, -492, -492, -492,
+     -492, -492,  494, -492, -492, -492, -492, -492, -492, -492,
+
+     -492, -492, -492, -492, -492, -492, -492, -492, -492, -492,
+     -492, -492, -492, -492, -492, -492, -492, -492, -492, -492,
+     -492, -492, -492, -492, -492, -492, -492, -492, -492, -492,
+     -492, -492, -492, -492, -492, -492, -492, -492, -492, -492,
+     -492, -492, -492, -492, -492, -492, -492, -492, -492, -492,
+     -492, -492, -492, -492, -492, -492, -492, -492, -492, -492,
+     -492, -492, -492, -492, -492, -492, -492, -492, -492, -492,
+     -492, -492, -492, -492, -492, -492, -492, -492, -492, -492,
+     -492, -492, -492, -492, -492, -492, -492, -492
+    },
+
+    {
+       15, -493, -493, -493, -493, -493, -493, -493, -493, -493,
+
+     -493, -493, -493, -493, -493, -493, -493, -493, -493, -493,
+     -493, -493, -493, -493, -493, -493, -493, -493, -493, -493,
+     -493, -493,  495, -493, -493, -493, -493, -493, -493, -493,
+     -493, -493, -493, -493, -493, -493, -493, -493, -493, -493,
+     -493, -493, -493, -493, -493, -493, -493, -493, -493, -493,
+     -493, -493, -493, -493, -493, -493, -493, -493, -493, -493,
+     -493, -493, -493, -493, -493, -493, -493, -493, -493, -493,
+     -493, -493, -493, -493, -493, -493, -493, -493, -493, -493,
+     -493, -493, -493, -493, -493, -493, -493, -493, -493, -493,
+     -493, -493, -493, -493, -493, -493, -493, -493, -493, -493,
+
+     -493, -493, -493, -493, -493, -493, -493, -493, -493, -493,
+     -493, -493, -493, -493, -493, -493, -493, -493
+    },
+
+    {
+       15, -494, -494, -494, -494, -494, -494, -494, -494, -494,
+     -494, -494, -494, -494, -494, -494, -494, -494, -494, -494,
+     -494, -494, -494, -494, -494, -494, -494, -494, -494, -494,
+     -494, -494,  496, -494, -494, -494, -494, -494, -494, -494,
+     -494, -494, -494, -494, -494, -494, -494, -494, -494, -494,
+     -494, -494, -494, -494, -494, -494, -494, -494, -494, -494,
+     -494, -494, -494, -494, -494, -494, -494, -494, -494, -494,
+     -494, -494, -494, -494, -494, -494, -494, -494, -494, -494,
+
+     -494, -494, -494, -494, -494, -494, -494, -494, -494, -494,
+     -494, -494, -494, -494, -494, -494, -494, -494, -494, -494,
+     -494, -494, -494, -494, -494, -494, -494, -494, -494, -494,
+     -494, -494, -494, -494, -494, -494, -494, -494, -494, -494,
+     -494, -494, -494, -494, -494, -494, -494, -494
+    },
+
+    {
+       15, -495, -495, -495, -495, -495, -495, -495, -495, -495,
+     -495, -495, -495, -495, -495, -495, -495, -495, -495, -495,
+     -495, -495, -495, -495, -495, -495, -495, -495, -495, -495,
+     -495, -495,  497, -495, -495, -495, -495, -495, -495, -495,
+     -495, -495, -495, -495, -495, -495, -495, -495, -495, -495,
+
+     -495, -495, -495, -495, -495, -495, -495, -495, -495, -495,
+     -495, -495, -495, -495, -495, -495, -495, -495, -495, -495,
+     -495, -495, -495, -495, -495, -495, -495, -495, -495, -495,
+     -495, -495, -495, -495, -495, -495, -495, -495, -495, -495,
+     -495, -495, -495, -495, -495, -495, -495, -495, -495, -495,
+     -495, -495, -495, -495, -495, -495, -495, -495, -495, -495,
+     -495, -495, -495, -495, -495, -495, -495, -495, -495, -495,
+     -495, -495, -495, -495, -495, -495, -495, -495
+    },
+
+    {
+       15, -496, -496, -496, -496, -496, -496, -496, -496, -496,
+     -496, -496, -496, -496, -496, -496, -496, -496, -496, -496,
+
+     -496, -496, -496, -496, -496, -496, -496, -496, -496, -496,
+     -496, -496,  498, -496, -496, -496, -496, -496, -496, -496,
+     -496, -496, -496, -496, -496, -496, -496, -496, -496, -496,
+     -496, -496, -496, -496, -496, -496, -496, -496, -496, -496,
+     -496, -496, -496, -496, -496, -496, -496, -496, -496, -496,
+     -496, -496, -496, -496, -496, -496, -496, -496, -496, -496,
+     -496, -496, -496, -496, -496, -496, -496, -496, -496, -496,
+     -496, -496, -496, -496, -496, -496, -496, -496, -496, -496,
+     -496, -496, -496, -496, -496, -496, -496, -496, -496, -496,
+     -496, -496, -496, -496, -496, -496, -496, -496, -496, -496,
+
+     -496, -496, -496, -496, -496, -496, -496, -496
+    },
+
+    {
+       15, -497, -497, -497, -497, -497, -497, -497, -497, -497,
+     -497, -497, -497, -497, -497, -497, -497, -497, -497, -497,
+     -497, -497, -497, -497, -497, -497, -497, -497, -497, -497,
+     -497, -497,  499, -497, -497, -497, -497, -497, -497, -497,
+     -497, -497, -497, -497, -497, -497, -497, -497, -497, -497,
+     -497, -497, -497, -497, -497, -497, -497, -497, -497, -497,
+     -497, -497, -497, -497, -497, -497, -497, -497, -497, -497,
+     -497, -497, -497, -497, -497, -497, -497, -497, -497, -497,
+     -497, -497, -497, -497, -497, -497, -497, -497, -497, -497,
+
+     -497, -497, -497, -497, -497, -497, -497, -497, -497, -497,
+     -497, -497, -497, -497, -497, -497, -497, -497, -497, -497,
+     -497, -497, -497, -497, -497, -497, -497, -497, -497, -497,
+     -497, -497, -497, -497, -497, -497, -497, -497
+    },
+
+    {
+       15, -498, -498, -498, -498, -498, -498, -498, -498, -498,
+     -498, -498, -498, -498, -498, -498, -498, -498, -498, -498,
+     -498, -498, -498, -498, -498, -498, -498, -498, -498, -498,
+     -498, -498,  500, -498, -498, -498, -498, -498, -498, -498,
+     -498, -498, -498, -498, -498, -498, -498, -498, -498, -498,
+     -498, -498, -498, -498, -498, -498, -498, -498, -498, -498,
+
+     -498, -498, -498, -498, -498, -498, -498, -498, -498, -498,
+     -498, -498, -498, -498, -498, -498, -498, -498, -498, -498,
+     -498, -498, -498, -498, -498, -498, -498, -498, -498, -498,
+     -498, -498, -498, -498, -498, -498, -498, -498, -498, -498,
+     -498, -498, -498, -498, -498, -498, -498, -498, -498, -498,
+     -498, -498, -498, -498, -498, -498, -498, -498, -498, -498,
+     -498, -498, -498, -498, -498, -498, -498, -498
+    },
+
+    {
+       15, -499, -499, -499, -499, -499, -499, -499, -499, -499,
+     -499, -499, -499, -499, -499, -499, -499, -499, -499, -499,
+     -499, -499, -499, -499, -499, -499, -499, -499, -499, -499,
+
+     -499, -499,  501, -499, -499, -499, -499, -499, -499, -499,
+     -499, -499, -499, -499, -499, -499, -499, -499, -499, -499,
+     -499, -499, -499, -499, -499, -499, -499, -499, -499, -499,
+     -499, -499, -499, -499, -499, -499, -499, -499, -499, -499,
+     -499, -499, -499, -499, -499, -499, -499, -499, -499, -499,
+     -499, -499, -499, -499, -499, -499, -499, -499, -499, -499,
+     -499, -499, -499, -499, -499, -499, -499, -499, -499, -499,
+     -499, -499, -499, -499, -499, -499, -499, -499, -499, -499,
+     -499, -499, -499, -499, -499, -499, -499, -499, -499, -499,
+     -499, -499, -499, -499, -499, -499, -499, -499
+
+    },
+
+    {
+       15, -500, -500, -500, -500, -500, -500, -500, -500, -500,
+     -500, -500, -500, -500, -500, -500, -500, -500, -500, -500,
+     -500, -500, -500, -500, -500, -500, -500, -500, -500, -500,
+     -500, -500,  502, -500, -500, -500, -500, -500, -500, -500,
+     -500, -500, -500, -500, -500, -500, -500, -500, -500, -500,
+     -500, -500, -500, -500, -500, -500, -500, -500, -500, -500,
+     -500, -500, -500, -500, -500, -500, -500, -500, -500, -500,
+     -500, -500, -500, -500, -500, -500, -500, -500, -500, -500,
+     -500, -500, -500, -500, -500, -500, -500, -500, -500, -500,
+     -500, -500, -500, -500, -500, -500, -500, -500, -500, -500,
+
+     -500, -500, -500, -500, -500, -500, -500, -500, -500, -500,
+     -500, -500, -500, -500, -500, -500, -500, -500, -500, -500,
+     -500, -500, -500, -500, -500, -500, -500, -500
+    },
+
+    {
+       15, -501, -501, -501, -501, -501, -501, -501, -501, -501,
+     -501, -501, -501, -501, -501, -501, -501, -501, -501, -501,
+     -501, -501, -501, -501, -501, -501, -501, -501, -501, -501,
+     -501, -501,  503, -501, -501, -501, -501, -501, -501, -501,
+     -501, -501, -501, -501, -501, -501, -501, -501, -501, -501,
+     -501, -501, -501, -501, -501, -501, -501, -501, -501, -501,
+     -501, -501, -501, -501, -501, -501, -501, -501, -501, -501,
+
+     -501, -501, -501, -501, -501, -501, -501, -501, -501, -501,
+     -501, -501, -501, -501, -501, -501, -501, -501, -501, -501,
+     -501, -501, -501, -501, -501, -501, -501, -501, -501, -501,
+     -501, -501, -501, -501, -501, -501, -501, -501, -501, -501,
+     -501, -501, -501, -501, -501, -501, -501, -501, -501, -501,
+     -501, -501, -501, -501, -501, -501, -501, -501
+    },
+
+    {
+       15, -502, -502, -502, -502, -502, -502, -502, -502, -502,
+     -502, -502, -502, -502, -502, -502, -502, -502, -502, -502,
+     -502, -502, -502, -502, -502, -502, -502, -502, -502, -502,
+     -502, -502,  504, -502, -502, -502, -502, -502, -502, -502,
+
+     -502, -502, -502, -502, -502, -502, -502, -502, -502, -502,
+     -502, -502, -502, -502, -502, -502, -502, -502, -502, -502,
+     -502, -502, -502, -502, -502, -502, -502, -502, -502, -502,
+     -502, -502, -502, -502, -502, -502, -502, -502, -502, -502,
+     -502, -502, -502, -502, -502, -502, -502, -502, -502, -502,
+     -502, -502, -502, -502, -502, -502, -502, -502, -502, -502,
+     -502, -502, -502, -502, -502, -502, -502, -502, -502, -502,
+     -502, -502, -502, -502, -502, -502, -502, -502, -502, -502,
+     -502, -502, -502, -502, -502, -502, -502, -502
+    },
+
+    {
+       15, -503, -503, -503, -503, -503, -503, -503, -503, -503,
+
+     -503, -503, -503, -503, -503, -503, -503, -503, -503, -503,
+     -503, -503, -503, -503, -503, -503, -503, -503, -503, -503,
+     -503, -503,  505, -503, -503, -503, -503, -503, -503, -503,
+     -503, -503, -503, -503, -503, -503, -503, -503, -503, -503,
+     -503, -503, -503, -503, -503, -503, -503, -503, -503, -503,
+     -503, -503, -503, -503, -503, -503, -503, -503, -503, -503,
+     -503, -503, -503, -503, -503, -503, -503, -503, -503, -503,
+     -503, -503, -503, -503, -503, -503, -503, -503, -503, -503,
+     -503, -503, -503, -503, -503, -503, -503, -503, -503, -503,
+     -503, -503, -503, -503, -503, -503, -503, -503, -503, -503,
+
+     -503, -503, -503, -503, -503, -503, -503, -503, -503, -503,
+     -503, -503, -503, -503, -503, -503, -503, -503
+    },
+
+    {
+       15, -504, -504, -504, -504, -504, -504, -504, -504, -504,
+     -504, -504, -504, -504, -504, -504, -504, -504, -504, -504,
+     -504, -504, -504, -504, -504, -504, -504, -504, -504, -504,
+     -504, -504,  506, -504, -504, -504, -504, -504, -504, -504,
+     -504, -504, -504, -504, -504, -504, -504, -504, -504, -504,
+     -504, -504, -504, -504, -504, -504, -504, -504, -504, -504,
+     -504, -504, -504, -504, -504, -504, -504, -504, -504, -504,
+     -504, -504, -504, -504, -504, -504, -504, -504, -504, -504,
+
+     -504, -504, -504, -504, -504, -504, -504, -504, -504, -504,
+     -504, -504, -504, -504, -504, -504, -504, -504, -504, -504,
+     -504, -504, -504, -504, -504, -504, -504, -504, -504, -504,
+     -504, -504, -504, -504, -504, -504, -504, -504, -504, -504,
+     -504, -504, -504, -504, -504, -504, -504, -504
+    },
+
+    {
+       15, -505, -505, -505, -505, -505, -505, -505, -505, -505,
+     -505, -505, -505, -505, -505, -505, -505, -505, -505, -505,
+     -505, -505, -505, -505, -505, -505, -505, -505, -505, -505,
+     -505, -505,  507, -505, -505, -505, -505, -505, -505, -505,
+     -505, -505, -505, -505, -505, -505, -505, -505, -505, -505,
+
+     -505, -505, -505, -505, -505, -505, -505, -505, -505, -505,
+     -505, -505, -505, -505, -505, -505, -505, -505, -505, -505,
+     -505, -505, -505, -505, -505, -505, -505, -505, -505, -505,
+     -505, -505, -505, -505, -505, -505, -505, -505, -505, -505,
+     -505, -505, -505, -505, -505, -505, -505, -505, -505, -505,
+     -505, -505, -505, -505, -505, -505, -505, -505, -505, -505,
+     -505, -505, -505, -505, -505, -505, -505, -505, -505, -505,
+     -505, -505, -505, -505, -505, -505, -505, -505
+    },
+
+    {
+       15, -506, -506, -506, -506, -506, -506, -506, -506, -506,
+     -506, -506, -506, -506, -506, -506, -506, -506, -506, -506,
+
+     -506, -506, -506, -506, -506, -506, -506, -506, -506, -506,
+     -506, -506,  508, -506, -506, -506, -506, -506, -506, -506,
+     -506, -506, -506, -506, -506, -506, -506, -506, -506, -506,
+     -506, -506, -506, -506, -506, -506, -506, -506, -506, -506,
+     -506, -506, -506, -506, -506, -506, -506, -506, -506, -506,
+     -506, -506, -506, -506, -506, -506, -506, -506, -506, -506,
+     -506, -506, -506, -506, -506, -506, -506, -506, -506, -506,
+     -506, -506, -506, -506, -506, -506, -506, -506, -506, -506,
+     -506, -506, -506, -506, -506, -506, -506, -506, -506, -506,
+     -506, -506, -506, -506, -506, -506, -506, -506, -506, -506,
+
+     -506, -506, -506, -506, -506, -506, -506, -506
+    },
+
+    {
+       15, -507, -507, -507, -507, -507, -507, -507, -507, -507,
+     -507, -507, -507, -507, -507, -507, -507, -507, -507, -507,
+     -507, -507, -507, -507, -507, -507, -507, -507, -507, -507,
+     -507, -507,  509, -507, -507, -507, -507, -507, -507, -507,
+     -507, -507, -507, -507, -507, -507, -507, -507, -507, -507,
+     -507, -507, -507, -507, -507, -507, -507, -507, -507, -507,
+     -507, -507, -507, -507, -507, -507, -507, -507, -507, -507,
+     -507, -507, -507, -507, -507, -507, -507, -507, -507, -507,
+     -507, -507, -507, -507, -507, -507, -507, -507, -507, -507,
+
+     -507, -507, -507, -507, -507, -507, -507, -507, -507, -507,
+     -507, -507, -507, -507, -507, -507, -507, -507, -507, -507,
+     -507, -507, -507, -507, -507, -507, -507, -507, -507, -507,
+     -507, -507, -507, -507, -507, -507, -507, -507
+    },
+
+    {
+       15, -508, -508, -508, -508, -508, -508, -508, -508, -508,
+     -508, -508, -508, -508, -508, -508, -508, -508, -508, -508,
+     -508, -508, -508, -508, -508, -508, -508, -508, -508, -508,
+     -508, -508,  510, -508, -508, -508, -508, -508, -508, -508,
+     -508, -508, -508, -508, -508, -508, -508, -508, -508, -508,
+     -508, -508, -508, -508, -508, -508, -508, -508, -508, -508,
+
+     -508, -508, -508, -508, -508, -508, -508, -508, -508, -508,
+     -508, -508, -508, -508, -508, -508, -508, -508, -508, -508,
+     -508, -508, -508, -508, -508, -508, -508, -508, -508, -508,
+     -508, -508, -508, -508, -508, -508, -508, -508, -508, -508,
+     -508, -508, -508, -508, -508, -508, -508, -508, -508, -508,
+     -508, -508, -508, -508, -508, -508, -508, -508, -508, -508,
+     -508, -508, -508, -508, -508, -508, -508, -508
+    },
+
+    {
+       15, -509, -509, -509, -509, -509, -509, -509, -509, -509,
+     -509, -509, -509, -509, -509, -509, -509, -509, -509, -509,
+     -509, -509, -509, -509, -509, -509, -509, -509, -509, -509,
+
+     -509, -509,  511, -509, -509, -509, -509, -509, -509, -509,
+     -509, -509, -509, -509, -509, -509, -509, -509, -509, -509,
+     -509, -509, -509, -509, -509, -509, -509, -509, -509, -509,
+     -509, -509, -509, -509, -509, -509, -509, -509, -509, -509,
+     -509, -509, -509, -509, -509, -509, -509, -509, -509, -509,
+     -509, -509, -509, -509, -509, -509, -509, -509, -509, -509,
+     -509, -509, -509, -509, -509, -509, -509, -509, -509, -509,
+     -509, -509, -509, -509, -509, -509, -509, -509, -509, -509,
+     -509, -509, -509, -509, -509, -509, -509, -509, -509, -509,
+     -509, -509, -509, -509, -509, -509, -509, -509
+
+    },
+
+    {
+       15, -510, -510, -510, -510, -510, -510, -510, -510, -510,
+     -510, -510, -510, -510, -510, -510, -510, -510, -510, -510,
+     -510, -510, -510, -510, -510, -510, -510, -510, -510, -510,
+     -510, -510,  512, -510, -510, -510, -510, -510, -510, -510,
+     -510, -510, -510, -510, -510, -510, -510, -510, -510, -510,
+     -510, -510, -510, -510, -510, -510, -510, -510, -510, -510,
+     -510, -510, -510, -510, -510, -510, -510, -510, -510, -510,
+     -510, -510, -510, -510, -510, -510, -510, -510, -510, -510,
+     -510, -510, -510, -510, -510, -510, -510, -510, -510, -510,
+     -510, -510, -510, -510, -510, -510, -510, -510, -510, -510,
+
+     -510, -510, -510, -510, -510, -510, -510, -510, -510, -510,
+     -510, -510, -510, -510, -510, -510, -510, -510, -510, -510,
+     -510, -510, -510, -510, -510, -510, -510, -510
+    },
+
+    {
+       15, -511, -511, -511, -511, -511, -511, -511, -511, -511,
+     -511, -511, -511, -511, -511, -511, -511, -511, -511, -511,
+     -511, -511, -511, -511, -511, -511, -511, -511, -511, -511,
+     -511, -511,  513, -511, -511, -511, -511, -511, -511, -511,
+     -511, -511, -511, -511, -511, -511, -511, -511, -511, -511,
+     -511, -511, -511, -511, -511, -511, -511, -511, -511, -511,
+     -511, -511, -511, -511, -511, -511, -511, -511, -511, -511,
+
+     -511, -511, -511, -511, -511, -511, -511, -511, -511, -511,
+     -511, -511, -511, -511, -511, -511, -511, -511, -511, -511,
+     -511, -511, -511, -511, -511, -511, -511, -511, -511, -511,
+     -511, -511, -511, -511, -511, -511, -511, -511, -511, -511,
+     -511, -511, -511, -511, -511, -511, -511, -511, -511, -511,
+     -511, -511, -511, -511, -511, -511, -511, -511
+    },
+
+    {
+       15, -512, -512, -512, -512, -512, -512, -512, -512, -512,
+     -512, -512, -512, -512, -512, -512, -512, -512, -512, -512,
+     -512, -512, -512, -512, -512, -512, -512, -512, -512, -512,
+     -512, -512,  514, -512, -512, -512, -512, -512, -512, -512,
+
+     -512, -512, -512, -512, -512, -512, -512, -512, -512, -512,
+     -512, -512, -512, -512, -512, -512, -512, -512, -512, -512,
+     -512, -512, -512, -512, -512, -512, -512, -512, -512, -512,
+     -512, -512, -512, -512, -512, -512, -512, -512, -512, -512,
+     -512, -512, -512, -512, -512, -512, -512, -512, -512, -512,
+     -512, -512, -512, -512, -512, -512, -512, -512, -512, -512,
+     -512, -512, -512, -512, -512, -512, -512, -512, -512, -512,
+     -512, -512, -512, -512, -512, -512, -512, -512, -512, -512,
+     -512, -512, -512, -512, -512, -512, -512, -512
+    },
+
+    {
+       15, -513, -513, -513, -513, -513, -513, -513, -513, -513,
+
+     -513, -513, -513, -513, -513, -513, -513, -513, -513, -513,
+     -513, -513, -513, -513, -513, -513, -513, -513, -513, -513,
+     -513, -513,  515, -513, -513, -513, -513, -513, -513, -513,
+     -513, -513, -513, -513, -513, -513, -513, -513, -513, -513,
+     -513, -513, -513, -513, -513, -513, -513, -513, -513, -513,
+     -513, -513, -513, -513, -513, -513, -513, -513, -513, -513,
+     -513, -513, -513, -513, -513, -513, -513, -513, -513, -513,
+     -513, -513, -513, -513, -513, -513, -513, -513, -513, -513,
+     -513, -513, -513, -513, -513, -513, -513, -513, -513, -513,
+     -513, -513, -513, -513, -513, -513, -513, -513, -513, -513,
+
+     -513, -513, -513, -513, -513, -513, -513, -513, -513, -513,
+     -513, -513, -513, -513, -513, -513, -513, -513
+    },
+
+    {
+       15, -514, -514, -514, -514, -514, -514, -514, -514, -514,
+     -514, -514, -514, -514, -514, -514, -514, -514, -514, -514,
+     -514, -514, -514, -514, -514, -514, -514, -514, -514, -514,
+     -514, -514,  516, -514, -514, -514, -514, -514, -514, -514,
+     -514, -514, -514, -514, -514, -514, -514, -514, -514, -514,
+     -514, -514, -514, -514, -514, -514, -514, -514, -514, -514,
+     -514, -514, -514, -514, -514, -514, -514, -514, -514, -514,
+     -514, -514, -514, -514, -514, -514, -514, -514, -514, -514,
+
+     -514, -514, -514, -514, -514, -514, -514, -514, -514, -514,
+     -514, -514, -514, -514, -514, -514, -514, -514, -514, -514,
+     -514, -514, -514, -514, -514, -514, -514, -514, -514, -514,
+     -514, -514, -514, -514, -514, -514, -514, -514, -514, -514,
+     -514, -514, -514, -514, -514, -514, -514, -514
+    },
+
+    {
+       15, -515, -515, -515, -515, -515, -515, -515, -515, -515,
+     -515, -515, -515, -515, -515, -515, -515, -515, -515, -515,
+     -515, -515, -515, -515, -515, -515, -515, -515, -515, -515,
+     -515, -515,  517, -515, -515, -515, -515, -515, -515, -515,
+     -515, -515, -515, -515, -515, -515, -515, -515, -515, -515,
+
+     -515, -515, -515, -515, -515, -515, -515, -515, -515, -515,
+     -515, -515, -515, -515, -515, -515, -515, -515, -515, -515,
+     -515, -515, -515, -515, -515, -515, -515, -515, -515, -515,
+     -515, -515, -515, -515, -515, -515, -515, -515, -515, -515,
+     -515, -515, -515, -515, -515, -515, -515, -515, -515, -515,
+     -515, -515, -515, -515, -515, -515, -515, -515, -515, -515,
+     -515, -515, -515, -515, -515, -515, -515, -515, -515, -515,
+     -515, -515, -515, -515, -515, -515, -515, -515
+    },
+
+    {
+       15, -516, -516, -516, -516, -516, -516, -516, -516, -516,
+     -516, -516, -516, -516, -516, -516, -516, -516, -516, -516,
+
+     -516, -516, -516, -516, -516, -516, -516, -516, -516, -516,
+     -516, -516,  518, -516, -516, -516, -516, -516, -516, -516,
+     -516, -516, -516, -516, -516, -516, -516, -516, -516, -516,
+     -516, -516, -516, -516, -516, -516, -516, -516, -516, -516,
+     -516, -516, -516, -516, -516, -516, -516, -516, -516, -516,
+     -516, -516, -516, -516, -516, -516, -516, -516, -516, -516,
+     -516, -516, -516, -516, -516, -516, -516, -516, -516, -516,
+     -516, -516, -516, -516, -516, -516, -516, -516, -516, -516,
+     -516, -516, -516, -516, -516, -516, -516, -516, -516, -516,
+     -516, -516, -516, -516, -516, -516, -516, -516, -516, -516,
+
+     -516, -516, -516, -516, -516, -516, -516, -516
+    },
+
+    {
+       15, -517, -517, -517, -517, -517, -517, -517, -517, -517,
+     -517, -517, -517, -517, -517, -517, -517, -517, -517, -517,
+     -517, -517, -517, -517, -517, -517, -517, -517, -517, -517,
+     -517, -517,  519, -517, -517, -517, -517, -517, -517, -517,
+     -517, -517, -517, -517, -517, -517, -517, -517, -517, -517,
+     -517, -517, -517, -517, -517, -517, -517, -517, -517, -517,
+     -517, -517, -517, -517, -517, -517, -517, -517, -517, -517,
+     -517, -517, -517, -517, -517, -517, -517, -517, -517, -517,
+     -517, -517, -517, -517, -517, -517, -517, -517, -517, -517,
+
+     -517, -517, -517, -517, -517, -517, -517, -517, -517, -517,
+     -517, -517, -517, -517, -517, -517, -517, -517, -517, -517,
+     -517, -517, -517, -517, -517, -517, -517, -517, -517, -517,
+     -517, -517, -517, -517, -517, -517, -517, -517
+    },
+
+    {
+       15, -518, -518, -518, -518, -518, -518, -518, -518, -518,
+     -518, -518, -518, -518, -518, -518, -518, -518, -518, -518,
+     -518, -518, -518, -518, -518, -518, -518, -518, -518, -518,
+     -518, -518,  520, -518, -518, -518, -518, -518, -518, -518,
+     -518, -518, -518, -518, -518, -518, -518, -518, -518, -518,
+     -518, -518, -518, -518, -518, -518, -518, -518, -518, -518,
+
+     -518, -518, -518, -518, -518, -518, -518, -518, -518, -518,
+     -518, -518, -518, -518, -518, -518, -518, -518, -518, -518,
+     -518, -518, -518, -518, -518, -518, -518, -518, -518, -518,
+     -518, -518, -518, -518, -518, -518, -518, -518, -518, -518,
+     -518, -518, -518, -518, -518, -518, -518, -518, -518, -518,
+     -518, -518, -518, -518, -518, -518, -518, -518, -518, -518,
+     -518, -518, -518, -518, -518, -518, -518, -518
+    },
+
+    {
+       15, -519, -519, -519, -519, -519, -519, -519, -519, -519,
+     -519, -519, -519, -519, -519, -519, -519, -519, -519, -519,
+     -519, -519, -519, -519, -519, -519, -519, -519, -519, -519,
+
+     -519, -519,  521, -519, -519, -519, -519, -519, -519, -519,
+     -519, -519, -519, -519, -519, -519, -519, -519, -519, -519,
+     -519, -519, -519, -519, -519, -519, -519, -519, -519, -519,
+     -519, -519, -519, -519, -519, -519, -519, -519, -519, -519,
+     -519, -519, -519, -519, -519, -519, -519, -519, -519, -519,
+     -519, -519, -519, -519, -519, -519, -519, -519, -519, -519,
+     -519, -519, -519, -519, -519, -519, -519, -519, -519, -519,
+     -519, -519, -519, -519, -519, -519, -519, -519, -519, -519,
+     -519, -519, -519, -519, -519, -519, -519, -519, -519, -519,
+     -519, -519, -519, -519, -519, -519, -519, -519
+
+    },
+
+    {
+       15, -520, -520, -520, -520, -520, -520, -520, -520, -520,
+     -520, -520, -520, -520, -520, -520, -520, -520, -520, -520,
+     -520, -520, -520, -520, -520, -520, -520, -520, -520, -520,
+     -520, -520,  522, -520, -520, -520, -520, -520, -520, -520,
+     -520, -520, -520, -520, -520, -520, -520, -520, -520, -520,
+     -520, -520, -520, -520, -520, -520, -520, -520, -520, -520,
+     -520, -520, -520, -520, -520, -520, -520, -520, -520, -520,
+     -520, -520, -520, -520, -520, -520, -520, -520, -520, -520,
+     -520, -520, -520, -520, -520, -520, -520, -520, -520, -520,
+     -520, -520, -520, -520, -520, -520, -520, -520, -520, -520,
+
+     -520, -520, -520, -520, -520, -520, -520, -520, -520, -520,
+     -520, -520, -520, -520, -520, -520, -520, -520, -520, -520,
+     -520, -520, -520, -520, -520, -520, -520, -520
+    },
+
+    {
+       15, -521, -521, -521, -521, -521, -521, -521, -521, -521,
+     -521, -521, -521, -521, -521, -521, -521, -521, -521, -521,
+     -521, -521, -521, -521, -521, -521, -521, -521, -521, -521,
+     -521, -521,  523, -521, -521, -521, -521, -521, -521, -521,
+     -521, -521, -521, -521, -521, -521, -521, -521, -521, -521,
+     -521, -521, -521, -521, -521, -521, -521, -521, -521, -521,
+     -521, -521, -521, -521, -521, -521, -521, -521, -521, -521,
+
+     -521, -521, -521, -521, -521, -521, -521, -521, -521, -521,
+     -521, -521, -521, -521, -521, -521, -521, -521, -521, -521,
+     -521, -521, -521, -521, -521, -521, -521, -521, -521, -521,
+     -521, -521, -521, -521, -521, -521, -521, -521, -521, -521,
+     -521, -521, -521, -521, -521, -521, -521, -521, -521, -521,
+     -521, -521, -521, -521, -521, -521, -521, -521
+    },
+
+    {
+       15, -522, -522, -522, -522, -522, -522, -522, -522, -522,
+     -522, -522, -522, -522, -522, -522, -522, -522, -522, -522,
+     -522, -522, -522, -522, -522, -522, -522, -522, -522, -522,
+     -522, -522,  524, -522, -522, -522, -522, -522, -522, -522,
+
+     -522, -522, -522, -522, -522, -522, -522, -522, -522, -522,
+     -522, -522, -522, -522, -522, -522, -522, -522, -522, -522,
+     -522, -522, -522, -522, -522, -522, -522, -522, -522, -522,
+     -522, -522, -522, -522, -522, -522, -522, -522, -522, -522,
+     -522, -522, -522, -522, -522, -522, -522, -522, -522, -522,
+     -522, -522, -522, -522, -522, -522, -522, -522, -522, -522,
+     -522, -522, -522, -522, -522, -522, -522, -522, -522, -522,
+     -522, -522, -522, -522, -522, -522, -522, -522, -522, -522,
+     -522, -522, -522, -522, -522, -522, -522, -522
+    },
+
+    {
+       15, -523, -523, -523, -523, -523, -523, -523, -523, -523,
+
+     -523, -523, -523, -523, -523, -523, -523, -523, -523, -523,
+     -523, -523, -523, -523, -523, -523, -523, -523, -523, -523,
+     -523, -523,  525, -523, -523, -523, -523, -523, -523, -523,
+     -523, -523, -523, -523, -523, -523, -523, -523, -523, -523,
+     -523, -523, -523, -523, -523, -523, -523, -523, -523, -523,
+     -523, -523, -523, -523, -523, -523, -523, -523, -523, -523,
+     -523, -523, -523, -523, -523, -523, -523, -523, -523, -523,
+     -523, -523, -523, -523, -523, -523, -523, -523, -523, -523,
+     -523, -523, -523, -523, -523, -523, -523, -523, -523, -523,
+     -523, -523, -523, -523, -523, -523, -523, -523, -523, -523,
+
+     -523, -523, -523, -523, -523, -523, -523, -523, -523, -523,
+     -523, -523, -523, -523, -523, -523, -523, -523
+    },
+
+    {
+       15, -524, -524, -524, -524, -524, -524, -524, -524, -524,
+     -524, -524, -524, -524, -524, -524, -524, -524, -524, -524,
+     -524, -524, -524, -524, -524, -524, -524, -524, -524, -524,
+     -524, -524,  526, -524, -524, -524, -524, -524, -524, -524,
+     -524, -524, -524, -524, -524, -524, -524, -524, -524, -524,
+     -524, -524, -524, -524, -524, -524, -524, -524, -524, -524,
+     -524, -524, -524, -524, -524, -524, -524, -524, -524, -524,
+     -524, -524, -524, -524, -524, -524, -524, -524, -524, -524,
+
+     -524, -524, -524, -524, -524, -524, -524, -524, -524, -524,
+     -524, -524, -524, -524, -524, -524, -524, -524, -524, -524,
+     -524, -524, -524, -524, -524, -524, -524, -524, -524, -524,
+     -524, -524, -524, -524, -524, -524, -524, -524, -524, -524,
+     -524, -524, -524, -524, -524, -524, -524, -524
+    },
+
+    {
+       15, -525, -525, -525, -525, -525, -525, -525, -525, -525,
+     -525, -525, -525, -525, -525, -525, -525, -525, -525, -525,
+     -525, -525, -525, -525, -525, -525, -525, -525, -525, -525,
+     -525, -525,  527, -525, -525, -525, -525, -525, -525, -525,
+     -525, -525, -525, -525, -525, -525, -525, -525, -525, -525,
+
+     -525, -525, -525, -525, -525, -525, -525, -525, -525, -525,
+     -525, -525, -525, -525, -525, -525, -525, -525, -525, -525,
+     -525, -525, -525, -525, -525, -525, -525, -525, -525, -525,
+     -525, -525, -525, -525, -525, -525, -525, -525, -525, -525,
+     -525, -525, -525, -525, -525, -525, -525, -525, -525, -525,
+     -525, -525, -525, -525, -525, -525, -525, -525, -525, -525,
+     -525, -525, -525, -525, -525, -525, -525, -525, -525, -525,
+     -525, -525, -525, -525, -525, -525, -525, -525
+    },
+
+    {
+       15, -526, -526, -526, -526, -526, -526, -526, -526, -526,
+     -526, -526, -526, -526, -526, -526, -526, -526, -526, -526,
+
+     -526, -526, -526, -526, -526, -526, -526, -526, -526, -526,
+     -526, -526,  528, -526, -526, -526, -526, -526, -526, -526,
+     -526, -526, -526, -526, -526, -526, -526, -526, -526, -526,
+     -526, -526, -526, -526, -526, -526, -526, -526, -526, -526,
+     -526, -526, -526, -526, -526, -526, -526, -526, -526, -526,
+     -526, -526, -526, -526, -526, -526, -526, -526, -526, -526,
+     -526, -526, -526, -526, -526, -526, -526, -526, -526, -526,
+     -526, -526, -526, -526, -526, -526, -526, -526, -526, -526,
+     -526, -526, -526, -526, -526, -526, -526, -526, -526, -526,
+     -526, -526, -526, -526, -526, -526, -526, -526, -526, -526,
+
+     -526, -526, -526, -526, -526, -526, -526, -526
+    },
+
+    {
+       15, -527, -527, -527, -527, -527, -527, -527, -527, -527,
+     -527, -527, -527, -527, -527, -527, -527, -527, -527, -527,
+     -527, -527, -527, -527, -527, -527, -527, -527, -527, -527,
+     -527, -527,  529, -527, -527, -527, -527, -527, -527, -527,
+     -527, -527, -527, -527, -527, -527, -527, -527, -527, -527,
+     -527, -527, -527, -527, -527, -527, -527, -527, -527, -527,
+     -527, -527, -527, -527, -527, -527, -527, -527, -527, -527,
+     -527, -527, -527, -527, -527, -527, -527, -527, -527, -527,
+     -527, -527, -527, -527, -527, -527, -527, -527, -527, -527,
+
+     -527, -527, -527, -527, -527, -527, -527, -527, -527, -527,
+     -527, -527, -527, -527, -527, -527, -527, -527, -527, -527,
+     -527, -527, -527, -527, -527, -527, -527, -527, -527, -527,
+     -527, -527, -527, -527, -527, -527, -527, -527
+    },
+
+    {
+       15, -528, -528, -528, -528, -528, -528, -528, -528, -528,
+     -528, -528, -528, -528, -528, -528, -528, -528, -528, -528,
+     -528, -528, -528, -528, -528, -528, -528, -528, -528, -528,
+     -528, -528,  530, -528, -528, -528, -528, -528, -528, -528,
+     -528, -528, -528, -528, -528, -528, -528, -528, -528, -528,
+     -528, -528, -528, -528, -528, -528, -528, -528, -528, -528,
+
+     -528, -528, -528, -528, -528, -528, -528, -528, -528, -528,
+     -528, -528, -528, -528, -528, -528, -528, -528, -528, -528,
+     -528, -528, -528, -528, -528, -528, -528, -528, -528, -528,
+     -528, -528, -528, -528, -528, -528, -528, -528, -528, -528,
+     -528, -528, -528, -528, -528, -528, -528, -528, -528, -528,
+     -528, -528, -528, -528, -528, -528, -528, -528, -528, -528,
+     -528, -528, -528, -528, -528, -528, -528, -528
+    },
+
+    {
+       15, -529, -529, -529, -529, -529, -529, -529, -529, -529,
+     -529, -529, -529, -529, -529, -529, -529, -529, -529, -529,
+     -529, -529, -529, -529, -529, -529, -529, -529, -529, -529,
+
+     -529, -529,  531, -529, -529, -529, -529, -529, -529, -529,
+     -529, -529, -529, -529, -529, -529, -529, -529, -529, -529,
+     -529, -529, -529, -529, -529, -529, -529, -529, -529, -529,
+     -529, -529, -529, -529, -529, -529, -529, -529, -529, -529,
+     -529, -529, -529, -529, -529, -529, -529, -529, -529, -529,
+     -529, -529, -529, -529, -529, -529, -529, -529, -529, -529,
+     -529, -529, -529, -529, -529, -529, -529, -529, -529, -529,
+     -529, -529, -529, -529, -529, -529, -529, -529, -529, -529,
+     -529, -529, -529, -529, -529, -529, -529, -529, -529, -529,
+     -529, -529, -529, -529, -529, -529, -529, -529
+
+    },
+
+    {
+       15, -530, -530, -530, -530, -530, -530, -530, -530, -530,
+     -530, -530, -530, -530, -530, -530, -530, -530, -530, -530,
+     -530, -530, -530, -530, -530, -530, -530, -530, -530, -530,
+     -530, -530,  532, -530, -530, -530, -530, -530, -530, -530,
+     -530, -530, -530, -530, -530, -530, -530, -530, -530, -530,
+     -530, -530, -530, -530, -530, -530, -530, -530, -530, -530,
+     -530, -530, -530, -530, -530, -530, -530, -530, -530, -530,
+     -530, -530, -530, -530, -530, -530, -530, -530, -530, -530,
+     -530, -530, -530, -530, -530, -530, -530, -530, -530, -530,
+     -530, -530, -530, -530, -530, -530, -530, -530, -530, -530,
+
+     -530, -530, -530, -530, -530, -530, -530, -530, -530, -530,
+     -530, -530, -530, -530, -530, -530, -530, -530, -530, -530,
+     -530, -530, -530, -530, -530, -530, -530, -530
+    },
+
+    {
+       15, -531, -531, -531, -531, -531, -531, -531, -531, -531,
+     -531, -531, -531, -531, -531, -531, -531, -531, -531, -531,
+     -531, -531, -531, -531, -531, -531, -531, -531, -531, -531,
+     -531, -531,  533, -531, -531, -531, -531, -531, -531, -531,
+     -531, -531, -531, -531, -531, -531, -531, -531, -531, -531,
+     -531, -531, -531, -531, -531, -531, -531, -531, -531, -531,
+     -531, -531, -531, -531, -531, -531, -531, -531, -531, -531,
+
+     -531, -531, -531, -531, -531, -531, -531, -531, -531, -531,
+     -531, -531, -531, -531, -531, -531, -531, -531, -531, -531,
+     -531, -531, -531, -531, -531, -531, -531, -531, -531, -531,
+     -531, -531, -531, -531, -531, -531, -531, -531, -531, -531,
+     -531, -531, -531, -531, -531, -531, -531, -531, -531, -531,
+     -531, -531, -531, -531, -531, -531, -531, -531
+    },
+
+    {
+       15, -532, -532, -532, -532, -532, -532, -532, -532, -532,
+     -532, -532, -532, -532, -532, -532, -532, -532, -532, -532,
+     -532, -532, -532, -532, -532, -532, -532, -532, -532, -532,
+     -532, -532,  534, -532, -532, -532, -532, -532, -532, -532,
+
+     -532, -532, -532, -532, -532, -532, -532, -532, -532, -532,
+     -532, -532, -532, -532, -532, -532, -532, -532, -532, -532,
+     -532, -532, -532, -532, -532, -532, -532, -532, -532, -532,
+     -532, -532, -532, -532, -532, -532, -532, -532, -532, -532,
+     -532, -532, -532, -532, -532, -532, -532, -532, -532, -532,
+     -532, -532, -532, -532, -532, -532, -532, -532, -532, -532,
+     -532, -532, -532, -532, -532, -532, -532, -532, -532, -532,
+     -532, -532, -532, -532, -532, -532, -532, -532, -532, -532,
+     -532, -532, -532, -532, -532, -532, -532, -532
+    },
+
+    {
+       15, -533, -533, -533, -533, -533, -533, -533, -533, -533,
+
+     -533, -533, -533, -533, -533, -533, -533, -533, -533, -533,
+     -533, -533, -533, -533, -533, -533, -533, -533, -533, -533,
+     -533, -533,  535, -533, -533, -533, -533, -533, -533, -533,
+     -533, -533, -533, -533, -533, -533, -533, -533, -533, -533,
+     -533, -533, -533, -533, -533, -533, -533, -533, -533, -533,
+     -533, -533, -533, -533, -533, -533, -533, -533, -533, -533,
+     -533, -533, -533, -533, -533, -533, -533, -533, -533, -533,
+     -533, -533, -533, -533, -533, -533, -533, -533, -533, -533,
+     -533, -533, -533, -533, -533, -533, -533, -533, -533, -533,
+     -533, -533, -533, -533, -533, -533, -533, -533, -533, -533,
+
+     -533, -533, -533, -533, -533, -533, -533, -533, -533, -533,
+     -533, -533, -533, -533, -533, -533, -533, -533
+    },
+
+    {
+       15, -534, -534, -534, -534, -534, -534, -534, -534, -534,
+     -534, -534, -534, -534, -534, -534, -534, -534, -534, -534,
+     -534, -534, -534, -534, -534, -534, -534, -534, -534, -534,
+     -534, -534,  536, -534, -534, -534, -534, -534, -534, -534,
+     -534, -534, -534, -534, -534, -534, -534, -534, -534, -534,
+     -534, -534, -534, -534, -534, -534, -534, -534, -534, -534,
+     -534, -534, -534, -534, -534, -534, -534, -534, -534, -534,
+     -534, -534, -534, -534, -534, -534, -534, -534, -534, -534,
+
+     -534, -534, -534, -534, -534, -534, -534, -534, -534, -534,
+     -534, -534, -534, -534, -534, -534, -534, -534, -534, -534,
+     -534, -534, -534, -534, -534, -534, -534, -534, -534, -534,
+     -534, -534, -534, -534, -534, -534, -534, -534, -534, -534,
+     -534, -534, -534, -534, -534, -534, -534, -534
+    },
+
+    {
+       15, -535, -535, -535, -535, -535, -535, -535, -535, -535,
+     -535, -535, -535, -535, -535, -535, -535, -535, -535, -535,
+     -535, -535, -535, -535, -535, -535, -535, -535, -535, -535,
+     -535, -535,  537, -535, -535, -535, -535, -535, -535, -535,
+     -535, -535, -535, -535, -535, -535, -535, -535, -535, -535,
+
+     -535, -535, -535, -535, -535, -535, -535, -535, -535, -535,
+     -535, -535, -535, -535, -535, -535, -535, -535, -535, -535,
+     -535, -535, -535, -535, -535, -535, -535, -535, -535, -535,
+     -535, -535, -535, -535, -535, -535, -535, -535, -535, -535,
+     -535, -535, -535, -535, -535, -535, -535, -535, -535, -535,
+     -535, -535, -535, -535, -535, -535, -535, -535, -535, -535,
+     -535, -535, -535, -535, -535, -535, -535, -535, -535, -535,
+     -535, -535, -535, -535, -535, -535, -535, -535
+    },
+
+    {
+       15, -536, -536, -536, -536, -536, -536, -536, -536, -536,
+     -536, -536, -536, -536, -536, -536, -536, -536, -536, -536,
+
+     -536, -536, -536, -536, -536, -536, -536, -536, -536, -536,
+     -536, -536,  538, -536, -536, -536, -536, -536, -536, -536,
+     -536, -536, -536, -536, -536, -536, -536, -536, -536, -536,
+     -536, -536, -536, -536, -536, -536, -536, -536, -536, -536,
+     -536, -536, -536, -536, -536, -536, -536, -536, -536, -536,
+     -536, -536, -536, -536, -536, -536, -536, -536, -536, -536,
+     -536, -536, -536, -536, -536, -536, -536, -536, -536, -536,
+     -536, -536, -536, -536, -536, -536, -536, -536, -536, -536,
+     -536, -536, -536, -536, -536, -536, -536, -536, -536, -536,
+     -536, -536, -536, -536, -536, -536, -536, -536, -536, -536,
+
+     -536, -536, -536, -536, -536, -536, -536, -536
+    },
+
+    {
+       15, -537, -537, -537, -537, -537, -537, -537, -537, -537,
+     -537, -537, -537, -537, -537, -537, -537, -537, -537, -537,
+     -537, -537, -537, -537, -537, -537, -537, -537, -537, -537,
+     -537, -537,  539, -537, -537, -537, -537, -537, -537, -537,
+     -537, -537, -537, -537, -537, -537, -537, -537, -537, -537,
+     -537, -537, -537, -537, -537, -537, -537, -537, -537, -537,
+     -537, -537, -537, -537, -537, -537, -537, -537, -537, -537,
+     -537, -537, -537, -537, -537, -537, -537, -537, -537, -537,
+     -537, -537, -537, -537, -537, -537, -537, -537, -537, -537,
+
+     -537, -537, -537, -537, -537, -537, -537, -537, -537, -537,
+     -537, -537, -537, -537, -537, -537, -537, -537, -537, -537,
+     -537, -537, -537, -537, -537, -537, -537, -537, -537, -537,
+     -537, -537, -537, -537, -537, -537, -537, -537
+    },
+
+    {
+       15, -538, -538, -538, -538, -538, -538, -538, -538, -538,
+     -538, -538, -538, -538, -538, -538, -538, -538, -538, -538,
+     -538, -538, -538, -538, -538, -538, -538, -538, -538, -538,
+     -538, -538,  540, -538, -538, -538, -538, -538, -538, -538,
+     -538, -538, -538, -538, -538, -538, -538, -538, -538, -538,
+     -538, -538, -538, -538, -538, -538, -538, -538, -538, -538,
+
+     -538, -538, -538, -538, -538, -538, -538, -538, -538, -538,
+     -538, -538, -538, -538, -538, -538, -538, -538, -538, -538,
+     -538, -538, -538, -538, -538, -538, -538, -538, -538, -538,
+     -538, -538, -538, -538, -538, -538, -538, -538, -538, -538,
+     -538, -538, -538, -538, -538, -538, -538, -538, -538, -538,
+     -538, -538, -538, -538, -538, -538, -538, -538, -538, -538,
+     -538, -538, -538, -538, -538, -538, -538, -538
+    },
+
+    {
+       15, -539, -539, -539, -539, -539, -539, -539, -539, -539,
+     -539, -539, -539, -539, -539, -539, -539, -539, -539, -539,
+     -539, -539, -539, -539, -539, -539, -539, -539, -539, -539,
+
+     -539, -539,  541, -539, -539, -539, -539, -539, -539, -539,
+     -539, -539, -539, -539, -539, -539, -539, -539, -539, -539,
+     -539, -539, -539, -539, -539, -539, -539, -539, -539, -539,
+     -539, -539, -539, -539, -539, -539, -539, -539, -539, -539,
+     -539, -539, -539, -539, -539, -539, -539, -539, -539, -539,
+     -539, -539, -539, -539, -539, -539, -539, -539, -539, -539,
+     -539, -539, -539, -539, -539, -539, -539, -539, -539, -539,
+     -539, -539, -539, -539, -539, -539, -539, -539, -539, -539,
+     -539, -539, -539, -539, -539, -539, -539, -539, -539, -539,
+     -539, -539, -539, -539, -539, -539, -539, -539
+
+    },
+
+    {
+       15, -540, -540, -540, -540, -540, -540, -540, -540, -540,
+     -540, -540, -540, -540, -540, -540, -540, -540, -540, -540,
+     -540, -540, -540, -540, -540, -540, -540, -540, -540, -540,
+     -540, -540,  542, -540, -540, -540, -540, -540, -540, -540,
+     -540, -540, -540, -540, -540, -540, -540, -540, -540, -540,
+     -540, -540, -540, -540, -540, -540, -540, -540, -540, -540,
+     -540, -540, -540, -540, -540, -540, -540, -540, -540, -540,
+     -540, -540, -540, -540, -540, -540, -540, -540, -540, -540,
+     -540, -540, -540, -540, -540, -540, -540, -540, -540, -540,
+     -540, -540, -540, -540, -540, -540, -540, -540, -540, -540,
+
+     -540, -540, -540, -540, -540, -540, -540, -540, -540, -540,
+     -540, -540, -540, -540, -540, -540, -540, -540, -540, -540,
+     -540, -540, -540, -540, -540, -540, -540, -540
+    },
+
+    {
+       15, -541, -541, -541, -541, -541, -541, -541, -541, -541,
+     -541, -541, -541, -541, -541, -541, -541, -541, -541, -541,
+     -541, -541, -541, -541, -541, -541, -541, -541, -541, -541,
+     -541, -541,  543, -541, -541, -541, -541, -541, -541, -541,
+     -541, -541, -541, -541, -541, -541, -541, -541, -541, -541,
+     -541, -541, -541, -541, -541, -541, -541, -541, -541, -541,
+     -541, -541, -541, -541, -541, -541, -541, -541, -541, -541,
+
+     -541, -541, -541, -541, -541, -541, -541, -541, -541, -541,
+     -541, -541, -541, -541, -541, -541, -541, -541, -541, -541,
+     -541, -541, -541, -541, -541, -541, -541, -541, -541, -541,
+     -541, -541, -541, -541, -541, -541, -541, -541, -541, -541,
+     -541, -541, -541, -541, -541, -541, -541, -541, -541, -541,
+     -541, -541, -541, -541, -541, -541, -541, -541
+    },
+
+    {
+       15, -542, -542, -542, -542, -542, -542, -542, -542, -542,
+     -542, -542, -542, -542, -542, -542, -542, -542, -542, -542,
+     -542, -542, -542, -542, -542, -542, -542, -542, -542, -542,
+     -542, -542,  544, -542, -542, -542, -542, -542, -542, -542,
+
+     -542, -542, -542, -542, -542, -542, -542, -542, -542, -542,
+     -542, -542, -542, -542, -542, -542, -542, -542, -542, -542,
+     -542, -542, -542, -542, -542, -542, -542, -542, -542, -542,
+     -542, -542, -542, -542, -542, -542, -542, -542, -542, -542,
+     -542, -542, -542, -542, -542, -542, -542, -542, -542, -542,
+     -542, -542, -542, -542, -542, -542, -542, -542, -542, -542,
+     -542, -542, -542, -542, -542, -542, -542, -542, -542, -542,
+     -542, -542, -542, -542, -542, -542, -542, -542, -542, -542,
+     -542, -542, -542, -542, -542, -542, -542, -542
+    },
+
+    {
+       15, -543, -543, -543, -543, -543, -543, -543, -543, -543,
+
+     -543, -543, -543, -543, -543, -543, -543, -543, -543, -543,
+     -543, -543, -543, -543, -543, -543, -543, -543, -543, -543,
+     -543, -543,  545, -543, -543, -543, -543, -543, -543, -543,
+     -543, -543, -543, -543, -543, -543, -543, -543, -543, -543,
+     -543, -543, -543, -543, -543, -543, -543, -543, -543, -543,
+     -543, -543, -543, -543, -543, -543, -543, -543, -543, -543,
+     -543, -543, -543, -543, -543, -543, -543, -543, -543, -543,
+     -543, -543, -543, -543, -543, -543, -543, -543, -543, -543,
+     -543, -543, -543, -543, -543, -543, -543, -543, -543, -543,
+     -543, -543, -543, -543, -543, -543, -543, -543, -543, -543,
+
+     -543, -543, -543, -543, -543, -543, -543, -543, -543, -543,
+     -543, -543, -543, -543, -543, -543, -543, -543
+    },
+
+    {
+       15, -544, -544, -544, -544, -544, -544, -544, -544, -544,
+     -544, -544, -544, -544, -544, -544, -544, -544, -544, -544,
+     -544, -544, -544, -544, -544, -544, -544, -544, -544, -544,
+     -544, -544,  546, -544, -544, -544, -544, -544, -544, -544,
+     -544, -544, -544, -544, -544, -544, -544, -544, -544, -544,
+     -544, -544, -544, -544, -544, -544, -544, -544, -544, -544,
+     -544, -544, -544, -544, -544, -544, -544, -544, -544, -544,
+     -544, -544, -544, -544, -544, -544, -544, -544, -544, -544,
+
+     -544, -544, -544, -544, -544, -544, -544, -544, -544, -544,
+     -544, -544, -544, -544, -544, -544, -544, -544, -544, -544,
+     -544, -544, -544, -544, -544, -544, -544, -544, -544, -544,
+     -544, -544, -544, -544, -544, -544, -544, -544, -544, -544,
+     -544, -544, -544, -544, -544, -544, -544, -544
+    },
+
+    {
+       15, -545, -545, -545, -545, -545, -545, -545, -545, -545,
+     -545, -545, -545, -545, -545, -545, -545, -545, -545, -545,
+     -545, -545, -545, -545, -545, -545, -545, -545, -545, -545,
+     -545, -545,  547, -545, -545, -545, -545, -545, -545, -545,
+     -545, -545, -545, -545, -545, -545, -545, -545, -545, -545,
+
+     -545, -545, -545, -545, -545, -545, -545, -545, -545, -545,
+     -545, -545, -545, -545, -545, -545, -545, -545, -545, -545,
+     -545, -545, -545, -545, -545, -545, -545, -545, -545, -545,
+     -545, -545, -545, -545, -545, -545, -545, -545, -545, -545,
+     -545, -545, -545, -545, -545, -545, -545, -545, -545, -545,
+     -545, -545, -545, -545, -545, -545, -545, -545, -545, -545,
+     -545, -545, -545, -545, -545, -545, -545, -545, -545, -545,
+     -545, -545, -545, -545, -545, -545, -545, -545
+    },
+
+    {
+       15, -546, -546, -546, -546, -546, -546, -546, -546, -546,
+     -546, -546, -546, -546, -546, -546, -546, -546, -546, -546,
+
+     -546, -546, -546, -546, -546, -546, -546, -546, -546, -546,
+     -546, -546,  548, -546, -546, -546, -546, -546, -546, -546,
+     -546, -546, -546, -546, -546, -546, -546, -546, -546, -546,
+     -546, -546, -546, -546, -546, -546, -546, -546, -546, -546,
+     -546, -546, -546, -546, -546, -546, -546, -546, -546, -546,
+     -546, -546, -546, -546, -546, -546, -546, -546, -546, -546,
+     -546, -546, -546, -546, -546, -546, -546, -546, -546, -546,
+     -546, -546, -546, -546, -546, -546, -546, -546, -546, -546,
+     -546, -546, -546, -546, -546, -546, -546, -546, -546, -546,
+     -546, -546, -546, -546, -546, -546, -546, -546, -546, -546,
+
+     -546, -546, -546, -546, -546, -546, -546, -546
+    },
+
+    {
+       15, -547, -547, -547, -547, -547, -547, -547, -547, -547,
+     -547, -547, -547, -547, -547, -547, -547, -547, -547, -547,
+     -547, -547, -547, -547, -547, -547, -547, -547, -547, -547,
+     -547, -547,  549, -547, -547, -547, -547, -547, -547, -547,
+     -547, -547, -547, -547, -547, -547, -547, -547, -547, -547,
+     -547, -547, -547, -547, -547, -547, -547, -547, -547, -547,
+     -547, -547, -547, -547, -547, -547, -547, -547, -547, -547,
+     -547, -547, -547, -547, -547, -547, -547, -547, -547, -547,
+     -547, -547, -547, -547, -547, -547, -547, -547, -547, -547,
+
+     -547, -547, -547, -547, -547, -547, -547, -547, -547, -547,
+     -547, -547, -547, -547, -547, -547, -547, -547, -547, -547,
+     -547, -547, -547, -547, -547, -547, -547, -547, -547, -547,
+     -547, -547, -547, -547, -547, -547, -547, -547
+    },
+
+    {
+       15, -548, -548, -548, -548, -548, -548, -548, -548, -548,
+     -548, -548, -548, -548, -548, -548, -548, -548, -548, -548,
+     -548, -548, -548, -548, -548, -548, -548, -548, -548, -548,
+     -548, -548,  550, -548, -548, -548, -548, -548, -548, -548,
+     -548, -548, -548, -548, -548, -548, -548, -548, -548, -548,
+     -548, -548, -548, -548, -548, -548, -548, -548, -548, -548,
+
+     -548, -548, -548, -548, -548, -548, -548, -548, -548, -548,
+     -548, -548, -548, -548, -548, -548, -548, -548, -548, -548,
+     -548, -548, -548, -548, -548, -548, -548, -548, -548, -548,
+     -548, -548, -548, -548, -548, -548, -548, -548, -548, -548,
+     -548, -548, -548, -548, -548, -548, -548, -548, -548, -548,
+     -548, -548, -548, -548, -548, -548, -548, -548, -548, -548,
+     -548, -548, -548, -548, -548, -548, -548, -548
+    },
+
+    {
+       15, -549, -549, -549, -549, -549, -549, -549, -549, -549,
+     -549, -549, -549, -549, -549, -549, -549, -549, -549, -549,
+     -549, -549, -549, -549, -549, -549, -549, -549, -549, -549,
+
+     -549, -549, -549, -549, -549, -549, -549, -549, -549, -549,
+     -549, -549, -549, -549, -549, -549, -549, -549, -549, -549,
+     -549, -549, -549, -549, -549, -549, -549, -549, -549, -549,
+     -549, -549, -549, -549, -549, -549, -549, -549, -549, -549,
+     -549, -549, -549, -549, -549, -549, -549, -549, -549, -549,
+     -549, -549, -549, -549, -549, -549, -549, -549, -549, -549,
+     -549, -549, -549, -549, -549, -549, -549, -549, -549, -549,
+     -549, -549, -549, -549, -549, -549, -549, -549, -549, -549,
+     -549, -549, -549, -549, -549, -549, -549, -549, -549, -549,
+     -549, -549, -549, -549, -549, -549, -549, -549
+
+    },
+
+    {
+       15, -550, -550, -550, -550, -550, -550, -550, -550, -550,
+     -550, -550, -550, -550, -550, -550, -550, -550, -550, -550,
+     -550, -550, -550, -550, -550, -550, -550, -550, -550, -550,
+     -550, -550, -550, -550, -550, -550, -550, -550, -550, -550,
+     -550, -550, -550, -550, -550, -550, -550, -550, -550, -550,
+     -550, -550, -550, -550, -550, -550, -550, -550, -550, -550,
+     -550, -550, -550, -550, -550, -550, -550, -550, -550, -550,
+     -550, -550, -550, -550, -550, -550, -550, -550, -550, -550,
+     -550, -550, -550, -550, -550, -550, -550, -550, -550, -550,
+     -550, -550, -550, -550, -550, -550, -550, -550, -550, -550,
+
+     -550, -550, -550, -550, -550, -550, -550, -550, -550, -550,
+     -550, -550, -550, -550, -550, -550, -550, -550, -550, -550,
+     -550, -550, -550, -550, -550, -550, -550, -550
+    },
+
+    } ;
+
+static yy_state_type yy_get_previous_state (void );
+static yy_state_type yy_try_NUL_trans (yy_state_type current_state  );
+static int yy_get_next_buffer (void );
+static void yy_fatal_error (yyconst char msg[]  );
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up fitshdrtext.
+ */
+#define YY_DO_BEFORE_ACTION \
+	(yytext_ptr) = yy_bp; \
+	(yytext_ptr) -= (yy_more_len); \
+	fitshdrleng = (size_t) (yy_cp - (yytext_ptr)); \
+	(yy_hold_char) = *yy_cp; \
+	*yy_cp = '\0'; \
+	(yy_c_buf_p) = yy_cp;
+
+#define YY_NUM_RULES 31
+#define YY_END_OF_BUFFER 32
+/* This struct is not used in this scanner,
+   but its presence is necessary. */
+struct yy_trans_info
+	{
+	flex_int32_t yy_verify;
+	flex_int32_t yy_nxt;
+	};
+static yyconst flex_int16_t yy_accept[551] =
+    {   0,
+        0,    0,    0,    0,    0,    0,    0,    0,   28,   28,
+       29,   29,    0,    0,   32,   31,   31,   31,   31,   31,
+       31,   31,   20,   20,   20,   20,   20,   20,   11,   13,
+       13,   12,   25,   21,   24,   23,   27,   27,   28,   29,
+       31,   30,    0,    0,    0,    0,    0,    0,    0,    0,
+       11,    0,   19,    0,    0,    0,    0,    0,   13,   13,
+       16,   16,   13,   13,    0,   13,   21,    0,   23,   22,
+       23,    0,   28,   29,    0,   30,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,   16,   13,   13,   13,    0,   16,   13,   26,    0,
+
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,   13,   13,
+       13,   13,   13,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,   17,
+        0,    0,    0,   13,   13,   13,   13,   13,   13,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,   18,    0,    0,    0,    0,   13,   13,   13,
+       13,   13,   13,   13,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    2,    0,    0,   13,   13,   13,   13,
+       13,   13,   13,   13,   10,    2,    8,    8,    8,    5,
+
+       13,   13,   13,   13,   13,   13,   13,   13,   13,    0,
+        0,    0,    0,    0,    0,   13,   13,   13,   13,   13,
+       13,   13,   13,   13,   13,    9,    0,    6,    0,    0,
+        4,   13,   13,   13,   13,   13,   13,   13,   13,   13,
+       13,   14,    0,    0,    0,   13,   13,   13,   13,   13,
+       13,   13,   13,   13,   13,   14,   14,    0,    0,    7,
+        0,   13,   13,   13,   13,   13,   13,   13,   13,   13,
+       13,   14,   14,   14,    0,    0,   13,   13,   13,   13,
+       13,   13,   13,   13,   13,   13,   14,   14,   14,   14,
+        0,    0,   13,   13,   13,   13,   13,   13,   13,   13,
+
+       13,   13,   14,   14,   14,   14,   14,    0,    0,   13,
+       13,   13,   13,   13,   13,   13,   13,   13,   13,   14,
+       14,   14,   14,   14,   14,    0,    0,   13,   13,   13,
+       13,   13,   13,   13,   13,   13,   13,   14,   14,   14,
+       14,   14,   14,   14,    0,    0,   13,   13,   13,   13,
+       13,   13,   13,   13,   13,   13,   14,   14,   14,   14,
+       14,   14,   14,   14,    0,    0,   13,   13,   13,   13,
+       13,   13,   13,   13,   13,   13,   14,   14,   14,   14,
+       14,   14,   14,   14,   14,    0,    0,   13,   13,   13,
+       13,   13,   13,   13,   13,   13,   13,   14,   14,   14,
+
+       14,   14,   14,   14,   14,   14,   15,    0,    0,   13,
+       13,   13,   13,   13,   13,   13,   13,   13,   13,   14,
+       14,   14,   14,   14,   14,   14,   14,   14,   15,   15,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    1,    3
+    } ;
+
+static yy_state_type yy_last_accepting_state;
+static char *yy_last_accepting_cpos;
+
+static yyconst yy_state_type yy_NUL_trans[551] =
+    {   0,
+       16,   17,   23,   23,   33,   33,   37,   37,   39,   39,
+       40,   40,   41,   41,    0,    0,   43,   43,   43,   43,
+       43,   43,    0,    0,   52,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,   73,   74,
+       75,    0,   77,   77,   77,   77,   77,   77,   77,    0,
+        0,   52,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,   73,   74,   75,    0,  100,  100,  100,  100,
+      100,  100,  100,  100,  100,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,  124,
+
+      124,  124,  124,  124,  124,  124,  124,  124,  124,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,  150,  150,  150,  150,  150,  150,  150,
+      150,  150,  150,  150,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,  175,
+      175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
+      175,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,  259,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,  259,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0
+    } ;
+
+extern int fitshdr_flex_debug;
+int fitshdr_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
+static int yy_more_flag = 0;
+static int yy_more_len = 0;
+#define yymore() ((yy_more_flag) = 1)
+#define YY_MORE_ADJ (yy_more_len)
+#define YY_RESTORE_YY_MORE_OFFSET
+char *fitshdrtext;
+#line 1 "fitshdr.l"
+/*============================================================================
+
+  WCSLIB 4.16 - an implementation of the FITS WCS standard.
+  Copyright (C) 1995-2012, Mark Calabretta
+
+  This file is part of WCSLIB.
+
+  WCSLIB is free software: you can redistribute it and/or modify it under the
+  terms of the GNU Lesser General Public License as published by the Free
+  Software Foundation, either version 3 of the License, or (at your option)
+  any later version.
+
+  WCSLIB 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 Lesser General Public License for
+  more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with WCSLIB.  If not, see http://www.gnu.org/licenses.
+
+  Direct correspondence concerning WCSLIB to mark at calabretta.id.au
+
+  Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
+  http://www.atnf.csiro.au/people/Mark.Calabretta
+  $Id: fitshdr.c,v 4.16 2012/11/07 04:42:44 cal103 Exp $
+*=============================================================================
+*
+* fitshdr.l is a Flex description file containing a lexical scanner
+* definition for extracting keywords and keyvalues from a FITS header.
+*
+* It requires Flex v2.5.4 or later.
+*
+* Refer to fitshdr.h for a description of the user interface and operating
+* notes.
+*
+*===========================================================================*/
+/* Options. */
+/* Keywords. */
+/* Keyvalue data types. */
+/* Characters forming standard unit strings (jwBIQX are not used). */
+/* Exclusive start states. */
+
+#line 76 "fitshdr.l"
+#include <math.h>
+#include <limits.h>
+#include <setjmp.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "fitshdr.h"
+#include "wcsutil.h"
+
+#define YY_DECL int fitshdr(const char header[], int nkeyrec, int nkeyids, \
+                            struct fitskeyid keyids[], int *nreject, \
+                            struct fitskey **keys)
+
+#define YY_INPUT(inbuff, count, bufsize) \
+	{ \
+	  if (fitshdr_nkeyrec) { \
+	    strncpy(inbuff, fitshdr_hdr, 80); \
+	    inbuff[80] = '\n'; \
+	    fitshdr_hdr += 80; \
+	    fitshdr_nkeyrec--; \
+	    count = 81; \
+	  } else { \
+	    count = YY_NULL; \
+	  } \
+	}
+
+/* These global variables are required by YY_INPUT. */
+const char *fitshdr_hdr;
+int  fitshdr_nkeyrec;
+
+/* Used in preempting the call to exit() by yy_fatal_error(). */
+jmp_buf fitshdr_abort_jmp_env;
+#define exit(status) longjmp(fitshdr_abort_jmp_env, status)
+
+/* Map status return value to message. */
+const char *fitshdr_errmsg[] = {
+   "Success",
+   "Null fitskey pointer-pointer passed",
+   "Memory allocation failed",
+   "Fatal error returned by Flex parser"};
+
+#line 10169 "fitshdr.c"
+
+#define INITIAL 0
+#define VALUE 1
+#define INLINE 2
+#define UNITS 3
+#define COMMENT 4
+#define ERROR 5
+#define FLUSH 6
+
+#ifndef YY_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 <unistd.h>
+#endif
+
+#ifndef YY_EXTRA_TYPE
+#define YY_EXTRA_TYPE void *
+#endif
+
+static int yy_init_globals (void );
+
+/* Accessor methods to globals.
+   These are made visible to non-reentrant scanners for convenience. */
+
+int fitshdrlex_destroy (void );
+
+int fitshdrget_debug (void );
+
+void fitshdrset_debug (int debug_flag  );
+
+YY_EXTRA_TYPE fitshdrget_extra (void );
+
+void fitshdrset_extra (YY_EXTRA_TYPE user_defined  );
+
+FILE *fitshdrget_in (void );
+
+void fitshdrset_in  (FILE * in_str  );
+
+FILE *fitshdrget_out (void );
+
+void fitshdrset_out  (FILE * out_str  );
+
+int fitshdrget_leng (void );
+
+char *fitshdrget_text (void );
+
+int fitshdrget_lineno (void );
+
+void fitshdrset_lineno (int line_number  );
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int fitshdrwrap (void );
+#else
+extern int fitshdrwrap (void );
+#endif
+#endif
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char *,yyconst char *,int );
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * );
+#endif
+
+#ifndef YY_NO_INPUT
+
+#ifdef __cplusplus
+static int yyinput (void );
+#else
+static int input (void );
+#endif
+
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k */
+#define YY_READ_BUF_SIZE 16384
+#else
+#define YY_READ_BUF_SIZE 8192
+#endif /* __ia64__ */
+#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( fitshdrtext, fitshdrleng, 1, fitshdrout )) {} } while (0)
+#endif
+
+/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+	errno=0; \
+	while ( (result = read( fileno(fitshdrin), (char *) buf, max_size )) < 0 ) \
+	{ \
+		if( errno != EINTR) \
+		{ \
+			YY_FATAL_ERROR( "input in flex scanner failed" ); \
+			break; \
+		} \
+		errno=0; \
+		clearerr(fitshdrin); \
+	}\
+\
+
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_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 YY_DECL
+#define YY_DECL_IS_OURS 1
+
+extern int fitshdrlex (void);
+
+#define YY_DECL int fitshdrlex (void)
+#endif /* !YY_DECL */
+
+/* Code executed at the beginning of each rule, after fitshdrtext and fitshdrleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+	if ( fitshdrleng > 0 ) \
+		YY_CURRENT_BUFFER_LVALUE->yy_at_bol = \
+				(fitshdrtext[fitshdrleng - 1] == '\n'); \
+	YY_USER_ACTION
+
+/** The main scanner function which does all the work.
+ */
+YY_DECL
+{
+	register yy_state_type yy_current_state;
+	register char *yy_cp, *yy_bp;
+	register int yy_act;
+    
+#line 119 "fitshdr.l"
+
+	char *cptr, ctmp[72];
+	int  blank, continuation, end, j, k, keyno;
+	double dtmp;
+	struct fitskey *kptr;
+	struct fitskeyid *iptr;
+	void nullfill(char cptr[], int len);
+	int  fitshdrlex_destroy(void);
+	
+	fitshdr_hdr = header;
+	fitshdr_nkeyrec = nkeyrec;
+	
+	*nreject = 0;
+	keyno = 0;
+	
+	if (keys == 0x0) {
+	  return 1;
+	}
+	
+	/* Allocate memory for the required number of fitskey structs. */
+	/* Recall that calloc() initializes allocated memory to zero.  */
+	if (!(kptr = *keys = calloc(nkeyrec, sizeof(struct fitskey)))) {
+	  return 2;
+	}
+	
+	/* Initialize keyids[]. */
+	iptr = keyids;
+	for (j = 0; j < nkeyids; j++, iptr++) {
+	  iptr->count  = 0;
+	  iptr->idx[0] = -1;
+	  iptr->idx[1] = -1;
+	}
+	
+	blank = 0;
+	continuation = 0;
+	end = 0;
+	
+	/* Return here via longjmp() invoked by yy_fatal_error(). */
+	if (setjmp(fitshdr_abort_jmp_env)) {
+	  return 3;
+	}
+	
+	BEGIN(INITIAL);
+
+#line 10392 "fitshdr.c"
+
+	if ( !(yy_init) )
+		{
+		(yy_init) = 1;
+
+#ifdef YY_USER_INIT
+		YY_USER_INIT;
+#endif
+
+		if ( ! (yy_start) )
+			(yy_start) = 1;	/* first start state */
+
+		if ( ! fitshdrin )
+			fitshdrin = stdin;
+
+		if ( ! fitshdrout )
+			fitshdrout = stdout;
+
+		if ( ! YY_CURRENT_BUFFER ) {
+			fitshdrensure_buffer_stack ();
+			YY_CURRENT_BUFFER_LVALUE =
+				fitshdr_create_buffer(fitshdrin,YY_BUF_SIZE );
+		}
+
+		fitshdr_load_buffer_state( );
+		}
+
+	while ( 1 )		/* loops until end-of-file is reached */
+		{
+		(yy_more_len) = 0;
+		if ( (yy_more_flag) )
+			{
+			(yy_more_len) = (yy_c_buf_p) - (yytext_ptr);
+			(yy_more_flag) = 0;
+			}
+		yy_cp = (yy_c_buf_p);
+
+		/* Support of fitshdrtext. */
+		*yy_cp = (yy_hold_char);
+
+		/* yy_bp points to the position in yy_ch_buf of the start of
+		 * the current run.
+		 */
+		yy_bp = yy_cp;
+
+		yy_current_state = (yy_start);
+		yy_current_state += YY_AT_BOL();
+yy_match:
+		while ( (yy_current_state = yy_nxt[yy_current_state][ YY_SC_TO_UI(*yy_cp) ]) > 0 )
+			{
+			if ( yy_accept[yy_current_state] )
+				{
+				(yy_last_accepting_state) = yy_current_state;
+				(yy_last_accepting_cpos) = yy_cp;
+				}
+
+			++yy_cp;
+			}
+
+		yy_current_state = -yy_current_state;
+
+yy_find_action:
+		yy_act = yy_accept[yy_current_state];
+
+		YY_DO_BEFORE_ACTION;
+
+do_action:	/* This label is used only to access EOF actions. */
+
+		switch ( yy_act )
+	{ /* beginning of action switch */
+			case 0: /* must back up */
+			/* undo the effects of YY_DO_BEFORE_ACTION */
+			*yy_cp = (yy_hold_char);
+			yy_cp = (yy_last_accepting_cpos) + 1;
+			yy_current_state = (yy_last_accepting_state);
+			goto yy_find_action;
+
+case 1:
+YY_RULE_SETUP
+#line 163 "fitshdr.l"
+{
+	  /* A completely blank keyrecord. */
+	  strncpy(kptr->keyword, fitshdrtext, 8);
+	  yyless(0);
+	  blank = 1;
+	  BEGIN(COMMENT);
+	}
+	YY_BREAK
+case 2:
+YY_RULE_SETUP
+#line 171 "fitshdr.l"
+{
+	  strncpy(kptr->keyword, fitshdrtext, 8);
+	  BEGIN(COMMENT);
+	}
+	YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 176 "fitshdr.l"
+{
+	  strncpy(kptr->keyword, fitshdrtext, 8);
+	  end = 1;
+	  BEGIN(FLUSH);
+	}
+	YY_BREAK
+case 4:
+YY_RULE_SETUP
+#line 182 "fitshdr.l"
+{
+	  /* Illegal END keyrecord. */
+	  strncpy(kptr->keyword, fitshdrtext, 8);
+	  kptr->status |= FITSHDR_KEYREC;
+	  BEGIN(VALUE);
+	}
+	YY_BREAK
+case 5:
+YY_RULE_SETUP
+#line 189 "fitshdr.l"
+{
+	  /* Illegal END keyrecord. */
+	  strncpy(kptr->keyword, fitshdrtext, 8);
+	  kptr->status |= FITSHDR_KEYREC;
+	  BEGIN(COMMENT);
+	}
+	YY_BREAK
+case 6:
+YY_RULE_SETUP
+#line 196 "fitshdr.l"
+{
+	  strncpy(kptr->keyword, fitshdrtext, 8);
+	  BEGIN(VALUE);
+	}
+	YY_BREAK
+case 7:
+/* rule 7 can match eol */
+YY_RULE_SETUP
+#line 201 "fitshdr.l"
+{
+	  /* Continued string keyvalue. */
+	  strncpy(kptr->keyword, fitshdrtext, 8);
+	
+	  if (keyno > 0 && (kptr-1)->type%10 == 8) {
+	    /* Put back the string keyvalue. */
+	    for (k = 10; fitshdrtext[k] != '\''; k++);
+	    yyless(k);
+	    continuation = 1;
+	    BEGIN(VALUE);
+	
+	  } else {
+	    /* Not a valid continuation. */
+	    yyless(8);
+	    BEGIN(COMMENT);
+	  }
+	}
+	YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 219 "fitshdr.l"
+{
+	  /* Keyword without value. */
+	  strncpy(kptr->keyword, fitshdrtext, 8);
+	  BEGIN(COMMENT);
+	}
+	YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 225 "fitshdr.l"
+{
+	  /* Illegal keyword, carry on regardless. */
+	  strncpy(kptr->keyword, fitshdrtext, 8);
+	  kptr->status |= FITSHDR_KEYWORD;
+	  BEGIN(VALUE);
+	}
+	YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 232 "fitshdr.l"
+{
+	  /* Illegal keyword, carry on regardless. */
+	  strncpy(kptr->keyword, fitshdrtext, 8);
+	  kptr->status |= FITSHDR_KEYWORD;
+	  BEGIN(COMMENT);
+	}
+	YY_BREAK
+case 11:
+*yy_cp = (yy_hold_char); /* undo effects of setting up fitshdrtext */
+(yy_c_buf_p) = yy_cp -= 1;
+YY_DO_BEFORE_ACTION; /* set up fitshdrtext again */
+YY_RULE_SETUP
+#line 239 "fitshdr.l"
+{
+	  /* Null keyvalue. */
+	  BEGIN(INLINE);
+	}
+	YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 244 "fitshdr.l"
+{
+	  /* Logical keyvalue. */
+	  kptr->type = 1;
+	  kptr->keyvalue.i = (*fitshdrtext == 'T');
+	  BEGIN(INLINE);
+	}
+	YY_BREAK
+case 13:
+YY_RULE_SETUP
+#line 251 "fitshdr.l"
+{
+	  /* 32-bit signed integer keyvalue. */
+	  kptr->type = 2;
+	  if (sscanf(fitshdrtext, "%d", &(kptr->keyvalue.i)) < 1) {
+	    kptr->status |= FITSHDR_KEYVALUE;
+	    BEGIN(ERROR);
+	  }
+	
+	  BEGIN(INLINE);
+	}
+	YY_BREAK
+case 14:
+YY_RULE_SETUP
+#line 262 "fitshdr.l"
+{
+	  /* 64-bit signed integer keyvalue (up to 18 digits). */
+	  if (wcsutil_str2double(fitshdrtext, "%lf", &dtmp)) {
+	    kptr->status |= FITSHDR_KEYVALUE;
+	    BEGIN(ERROR);
+	
+	  } else if (INT_MIN <= dtmp && dtmp <= INT_MAX) {
+	    /* Can be accomodated as a 32-bit signed integer. */
+	    kptr->type = 2;
+	    if (sscanf(fitshdrtext, "%d", &(kptr->keyvalue.i)) < 1) {
+	      kptr->status |= FITSHDR_KEYVALUE;
+	      BEGIN(ERROR);
+	    }
+	
+	  } else {
+	    /* 64-bit signed integer. */
+	    kptr->type = 3;
+#ifdef WCSLIB_INT64
+	      /* Native 64-bit integer is available. */
+	      if (sscanf(fitshdrtext, "%lld", &(kptr->keyvalue.k)) < 1) {
+	        kptr->status |= FITSHDR_KEYVALUE;
+	        BEGIN(ERROR);
+	      }
+#else
+	      /* 64-bit integer (up to 18 digits) implemented as int[3]. */
+	      kptr->keyvalue.k[2] = 0;
+	
+	      sprintf(ctmp, "%%%dd%%9d", fitshdrleng-9);
+	      if (sscanf(fitshdrtext, ctmp, kptr->keyvalue.k+1,
+	                 kptr->keyvalue.k) < 1) {
+	        kptr->status |= FITSHDR_KEYVALUE;
+	        BEGIN(ERROR);
+	      } else if (*fitshdrtext == '-') {
+	        kptr->keyvalue.k[0] *= -1;
+	      }
+#endif
+	  }
+	
+	  BEGIN(INLINE);
+	}
+	YY_BREAK
+case 15:
+YY_RULE_SETUP
+#line 303 "fitshdr.l"
+{
+	  /* Very long integer keyvalue (and 19-digit int64). */
+	  kptr->type = 4;
+	  strcpy(ctmp, fitshdrtext);
+	  k = fitshdrleng;
+	  for (j = 0; j < 8; j++) {
+	    /* Read it backwards. */
+	    k -= 9;
+	    if (k < 0) k = 0;
+	    if (sscanf(ctmp+k, "%d", kptr->keyvalue.l+j) < 1) {
+	      kptr->status |= FITSHDR_KEYVALUE;
+	      BEGIN(ERROR);
+	    }
+	    if (*fitshdrtext == '-') {
+	      kptr->keyvalue.l[j] = -abs(kptr->keyvalue.l[j]);
+	    }
+	
+	    if (k == 0) break;
+	    ctmp[k] = '\0';
+	  }
+	
+	  /* Can it be accomodated as a 64-bit signed integer? */
+	  if (j == 2 && abs(kptr->keyvalue.l[2]) <=  9 &&
+	                abs(kptr->keyvalue.l[1]) <=  223372036 &&
+	                    kptr->keyvalue.l[0]  <=  854775807 &&
+	                    kptr->keyvalue.l[0]  >= -854775808) {
+	    kptr->type = 3;
+	
+#ifdef WCSLIB_INT64
+	      /* Native 64-bit integer is available. */
+	      kptr->keyvalue.l[2] = 0;
+	      if (sscanf(fitshdrtext, "%lld", &(kptr->keyvalue.k)) < 1) {
+	        kptr->status |= FITSHDR_KEYVALUE;
+	        BEGIN(ERROR);
+	      }
+#endif
+	  }
+	
+	  BEGIN(INLINE);
+	}
+	YY_BREAK
+case 16:
+YY_RULE_SETUP
+#line 344 "fitshdr.l"
+{
+	  /* Float keyvalue. */
+	  kptr->type = 5;
+	  if (wcsutil_str2double(fitshdrtext, "%lf", &(kptr->keyvalue.f))) {
+	    kptr->status |= FITSHDR_KEYVALUE;
+	    BEGIN(ERROR);
+	  }
+	
+	  BEGIN(INLINE);
+	}
+	YY_BREAK
+case 17:
+YY_RULE_SETUP
+#line 355 "fitshdr.l"
+{
+	  /* Integer complex keyvalue. */
+	  kptr->type = 6;
+	  if (sscanf(fitshdrtext, "(%lf,%lf)", kptr->keyvalue.c,
+	      kptr->keyvalue.c+1) < 2) {
+	    kptr->status |= FITSHDR_KEYVALUE;
+	    BEGIN(ERROR);
+	  }
+	
+	  BEGIN(INLINE);
+	}
+	YY_BREAK
+case 18:
+YY_RULE_SETUP
+#line 367 "fitshdr.l"
+{
+	  /* Floating point complex keyvalue. */
+	  kptr->type = 7;
+	
+	  for (cptr = ctmp, k = 1; fitshdrtext[k] != ','; cptr++, k++) {
+	    *cptr = fitshdrtext[k];
+	  }
+	  *cptr = '\0';
+	
+	  if (wcsutil_str2double(ctmp, "%lf", kptr->keyvalue.c)) {
+	    kptr->status |= FITSHDR_KEYVALUE;
+	    BEGIN(ERROR);
+	  }
+	
+	  for (cptr = ctmp, k++; fitshdrtext[k] != ')'; cptr++, k++) {
+	    *cptr = fitshdrtext[k];
+	  }
+	  *cptr = '\0';
+	
+	  if (wcsutil_str2double(ctmp, "%lf", kptr->keyvalue.c+1)) {
+	    kptr->status |= FITSHDR_KEYVALUE;
+	    BEGIN(ERROR);
+	  }
+	
+	  BEGIN(INLINE);
+	}
+	YY_BREAK
+case 19:
+/* rule 19 can match eol */
+YY_RULE_SETUP
+#line 394 "fitshdr.l"
+{
+	  /* String keyvalue. */
+	  kptr->type = 8;
+	  cptr = kptr->keyvalue.s;
+	  strcpy(cptr, fitshdrtext+1);
+	
+	  /* Squeeze out repeated quotes. */
+	  k = 0;
+	  for (j = 0; j < 72; j++) {
+	    if (k < j) {
+	      cptr[k] = cptr[j];
+	    }
+	
+	    if (cptr[j] == '\0') {
+	      if (k) cptr[k-1] = '\0';
+	      break;
+	    } else if (cptr[j] == '\'' && cptr[j+1] == '\'') {
+	      j++;
+	    }
+	
+	    k++;
+	  }
+	
+	  if (*cptr) {
+	    /* Retain the initial blank in all-blank strings. */
+	    nullfill(cptr+1, 71);
+	  } else {
+	    nullfill(cptr, 72);
+	  }
+	
+	  BEGIN(INLINE);
+	}
+	YY_BREAK
+case 20:
+YY_RULE_SETUP
+#line 427 "fitshdr.l"
+{
+	  kptr->status |= FITSHDR_KEYVALUE;
+	  BEGIN(ERROR);
+	}
+	YY_BREAK
+case 21:
+*yy_cp = (yy_hold_char); /* undo effects of setting up fitshdrtext */
+(yy_c_buf_p) = yy_cp -= 1;
+YY_DO_BEFORE_ACTION; /* set up fitshdrtext again */
+YY_RULE_SETUP
+#line 432 "fitshdr.l"
+{
+	  BEGIN(FLUSH);
+	}
+	YY_BREAK
+case 22:
+*yy_cp = (yy_hold_char); /* undo effects of setting up fitshdrtext */
+(yy_c_buf_p) = yy_cp -= 1;
+YY_DO_BEFORE_ACTION; /* set up fitshdrtext again */
+YY_RULE_SETUP
+#line 436 "fitshdr.l"
+{
+	  BEGIN(FLUSH);
+	}
+	YY_BREAK
+case 23:
+YY_RULE_SETUP
+#line 440 "fitshdr.l"
+{
+	  BEGIN(UNITS);
+	}
+	YY_BREAK
+case 24:
+YY_RULE_SETUP
+#line 444 "fitshdr.l"
+{
+	  kptr->status |= FITSHDR_COMMENT;
+	  BEGIN(ERROR);
+	}
+	YY_BREAK
+case 25:
+YY_RULE_SETUP
+#line 449 "fitshdr.l"
+{
+	  /* Keyvalue parsing must now also be suspect. */
+	  kptr->status |= FITSHDR_COMMENT;
+	  kptr->type = 0;
+	  BEGIN(ERROR);
+	}
+	YY_BREAK
+case 26:
+YY_RULE_SETUP
+#line 456 "fitshdr.l"
+{
+	  kptr->ulen = fitshdrleng;
+	  yymore();
+	  BEGIN(COMMENT);
+	}
+	YY_BREAK
+case 27:
+YY_RULE_SETUP
+#line 462 "fitshdr.l"
+{
+	  yymore();
+	  BEGIN(COMMENT);
+	}
+	YY_BREAK
+case 28:
+YY_RULE_SETUP
+#line 467 "fitshdr.l"
+{
+	  strcpy(kptr->comment, fitshdrtext);
+	  nullfill(kptr->comment, 84);
+	  BEGIN(FLUSH);
+	}
+	YY_BREAK
+case 29:
+YY_RULE_SETUP
+#line 473 "fitshdr.l"
+{
+	  if (!continuation) kptr->type = -abs(kptr->type);
+	
+	  sprintf(kptr->comment, "%.80s", fitshdr_hdr-80);
+	  kptr->comment[80] = '\0';
+	  nullfill(kptr->comment+80, 4);
+	
+	  BEGIN(FLUSH);
+	}
+	YY_BREAK
+case 30:
+/* rule 30 can match eol */
+YY_RULE_SETUP
+#line 483 "fitshdr.l"
+{
+	  /* Discard the rest of the input line. */
+	  kptr->keyno = ++keyno;
+	
+	  /* Null-fill the keyword. */
+	  kptr->keyword[8] = '\0';
+	  nullfill(kptr->keyword, 12);
+	
+	  /* Do indexing. */
+	  iptr = keyids;
+	  kptr->keyid = -1;
+	  for (j = 0; j < nkeyids; j++, iptr++) {
+	    cptr = iptr->name;
+	    cptr[8] = '\0';
+	    nullfill(cptr, 12);
+	    for (k = 0; k < 8; k++, cptr++) {
+	      if (*cptr != '.' && *cptr != kptr->keyword[k]) break;
+	    }
+	
+	    if (k == 8) {
+	      /* Found a match. */
+	      iptr->count++;
+	      if (iptr->idx[0] == -1) {
+	        iptr->idx[0] = keyno-1;
+	      } else {
+	        iptr->idx[1] = keyno-1;
+	      }
+	
+	      kptr->keyno = -abs(kptr->keyno);
+	      if (kptr->keyid < 0) kptr->keyid = j;
+	    }
+	  }
+	
+	  /* Deal with continued strings. */
+	  if (continuation) {
+	    /* Tidy up the previous string keyvalue. */
+	    if ((kptr-1)->type == 8) (kptr-1)->type += 10;
+	    cptr = (kptr-1)->keyvalue.s;
+	    if (cptr[strlen(cptr)-1] == '&') cptr[strlen(cptr)-1] = '\0';
+	
+	    kptr->type = (kptr-1)->type + 10;
+	  }
+	
+	  /* Check for keyrecords following the END keyrecord. */
+	  if (end && (end++ > 1) && !blank) {
+	    kptr->status |= FITSHDR_TRAILER;
+	  }
+	  if (kptr->status) (*nreject)++;
+	
+	  kptr++;
+	  blank = 0;
+	  continuation = 0;
+	
+	  BEGIN(INITIAL);
+	}
+	YY_BREAK
+case YY_STATE_EOF(INITIAL):
+case YY_STATE_EOF(VALUE):
+case YY_STATE_EOF(INLINE):
+case YY_STATE_EOF(UNITS):
+case YY_STATE_EOF(COMMENT):
+case YY_STATE_EOF(ERROR):
+case YY_STATE_EOF(FLUSH):
+#line 539 "fitshdr.l"
+{
+	  /* End-of-input. */
+	  fitshdrlex_destroy();
+	  return 0;
+	}
+	YY_BREAK
+case 31:
+YY_RULE_SETUP
+#line 545 "fitshdr.l"
+ECHO;
+	YY_BREAK
+#line 10967 "fitshdr.c"
+
+	case YY_END_OF_BUFFER:
+		{
+		/* Amount of text matched not including the EOB char. */
+		int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;
+
+		/* Undo the effects of YY_DO_BEFORE_ACTION. */
+		*yy_cp = (yy_hold_char);
+		YY_RESTORE_YY_MORE_OFFSET
+
+		if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
+			{
+			/* We're scanning a new file or input source.  It's
+			 * possible that this happened because the user
+			 * just pointed fitshdrin at a new source and called
+			 * fitshdrlex().  If so, then we have to assure
+			 * consistency between YY_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.
+			 */
+			(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+			YY_CURRENT_BUFFER_LVALUE->yy_input_file = fitshdrin;
+			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
+			}
+
+		/* Note that here we test for yy_c_buf_p "<=" to the position
+		 * of the first EOB in the buffer, since yy_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 ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+			{ /* This was really a NUL. */
+			yy_state_type yy_next_state;
+
+			(yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;
+
+			yy_current_state = yy_get_previous_state(  );
+
+			/* Okay, we're now positioned to make the NUL
+			 * transition.  We couldn't have
+			 * yy_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).
+			 */
+
+			yy_next_state = yy_try_NUL_trans( yy_current_state );
+
+			yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+
+			if ( yy_next_state )
+				{
+				/* Consume the NUL. */
+				yy_cp = ++(yy_c_buf_p);
+				yy_current_state = yy_next_state;
+				goto yy_match;
+				}
+
+			else
+				{
+				yy_cp = (yy_c_buf_p);
+				goto yy_find_action;
+				}
+			}
+
+		else switch ( yy_get_next_buffer(  ) )
+			{
+			case EOB_ACT_END_OF_FILE:
+				{
+				(yy_did_buffer_switch_on_eof) = 0;
+
+				if ( fitshdrwrap( ) )
+					{
+					/* Note: because we've taken care in
+					 * yy_get_next_buffer() to have set up
+					 * fitshdrtext, we can now set up
+					 * yy_c_buf_p so that if some total
+					 * hoser (like flex itself) wants to
+					 * call the scanner after we return the
+					 * YY_NULL, it'll still work - another
+					 * YY_NULL will get returned.
+					 */
+					(yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;
+
+					yy_act = YY_STATE_EOF(YY_START);
+					goto do_action;
+					}
+
+				else
+					{
+					if ( ! (yy_did_buffer_switch_on_eof) )
+						YY_NEW_FILE;
+					}
+				break;
+				}
+
+			case EOB_ACT_CONTINUE_SCAN:
+				(yy_c_buf_p) =
+					(yytext_ptr) + yy_amount_of_matched_text;
+
+				yy_current_state = yy_get_previous_state(  );
+
+				yy_cp = (yy_c_buf_p);
+				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+				goto yy_match;
+
+			case EOB_ACT_LAST_MATCH:
+				(yy_c_buf_p) =
+				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];
+
+				yy_current_state = yy_get_previous_state(  );
+
+				yy_cp = (yy_c_buf_p);
+				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+				goto yy_find_action;
+			}
+		break;
+		}
+
+	default:
+		YY_FATAL_ERROR(
+			"fatal flex scanner internal error--no action found" );
+	} /* end of action switch */
+		} /* end of scanning one token */
+} /* end of fitshdrlex */
+
+/* yy_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 yy_get_next_buffer (void)
+{
+    	register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+	register char *source = (yytext_ptr);
+	register int number_to_move, i;
+	int ret_val;
+
+	if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
+		YY_FATAL_ERROR(
+		"fatal flex scanner internal error--end of buffer missed" );
+
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
+		{ /* Don't try to fill the buffer, so this is an EOF. */
+		if ( (yy_c_buf_p) - (yytext_ptr) - YY_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) ((yy_c_buf_p) - (yytext_ptr)) - 1;
+
+	for ( i = 0; i < number_to_move; ++i )
+		*(dest++) = *(source++);
+
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+		/* don't do the read, it's not guaranteed to return an EOF,
+		 * just force an EOF
+		 */
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
+
+	else
+		{
+			int num_to_read =
+			YY_CURRENT_BUFFER_LVALUE->yy_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 */
+			YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
+
+			int yy_c_buf_p_offset =
+				(int) ((yy_c_buf_p) - b->yy_ch_buf);
+
+			if ( b->yy_is_our_buffer )
+				{
+				int new_size = b->yy_buf_size * 2;
+
+				if ( new_size <= 0 )
+					b->yy_buf_size += b->yy_buf_size / 8;
+				else
+					b->yy_buf_size *= 2;
+
+				b->yy_ch_buf = (char *)
+					/* Include room in for 2 EOB chars. */
+					fitshdrrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2  );
+				}
+			else
+				/* Can't grow it, we don't own it. */
+				b->yy_ch_buf = 0;
+
+			if ( ! b->yy_ch_buf )
+				YY_FATAL_ERROR(
+				"fatal error - scanner input buffer overflow" );
+
+			(yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+			num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
+						number_to_move - 1;
+
+			}
+
+		if ( num_to_read > YY_READ_BUF_SIZE )
+			num_to_read = YY_READ_BUF_SIZE;
+
+		/* Read in more data. */
+		YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+			(yy_n_chars), (size_t) num_to_read );
+
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+		}
+
+	if ( (yy_n_chars) == 0 )
+		{
+		if ( number_to_move == YY_MORE_ADJ )
+			{
+			ret_val = EOB_ACT_END_OF_FILE;
+			fitshdrrestart(fitshdrin  );
+			}
+
+		else
+			{
+			ret_val = EOB_ACT_LAST_MATCH;
+			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
+				YY_BUFFER_EOF_PENDING;
+			}
+		}
+
+	else
+		ret_val = EOB_ACT_CONTINUE_SCAN;
+
+	if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+		/* Extend the array by 50%, plus the number we really need. */
+		yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1);
+		YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) fitshdrrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size  );
+		if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+			YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+	}
+
+	(yy_n_chars) += number_to_move;
+	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
+	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
+
+	(yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+
+	return ret_val;
+}
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+    static yy_state_type yy_get_previous_state (void)
+{
+	register yy_state_type yy_current_state;
+	register char *yy_cp;
+    
+	yy_current_state = (yy_start);
+	yy_current_state += YY_AT_BOL();
+
+	for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
+		{
+		if ( *yy_cp )
+			{
+			yy_current_state = yy_nxt[yy_current_state][YY_SC_TO_UI(*yy_cp)];
+			}
+		else
+			yy_current_state = yy_NUL_trans[yy_current_state];
+		if ( yy_accept[yy_current_state] )
+			{
+			(yy_last_accepting_state) = yy_current_state;
+			(yy_last_accepting_cpos) = yy_cp;
+			}
+		}
+
+	return yy_current_state;
+}
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ *	next_state = yy_try_NUL_trans( current_state );
+ */
+    static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state )
+{
+	register int yy_is_jam;
+    	register char *yy_cp = (yy_c_buf_p);
+
+	yy_current_state = yy_NUL_trans[yy_current_state];
+	yy_is_jam = (yy_current_state == 0);
+
+	if ( ! yy_is_jam )
+		{
+		if ( yy_accept[yy_current_state] )
+			{
+			(yy_last_accepting_state) = yy_current_state;
+			(yy_last_accepting_cpos) = yy_cp;
+			}
+		}
+
+	return yy_is_jam ? 0 : yy_current_state;
+}
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+    static int yyinput (void)
+#else
+    static int input  (void)
+#endif
+
+{
+	int c;
+    
+	*(yy_c_buf_p) = (yy_hold_char);
+
+	if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
+		{
+		/* yy_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 ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+			/* This was really a NUL. */
+			*(yy_c_buf_p) = '\0';
+
+		else
+			{ /* need more input */
+			int offset = (yy_c_buf_p) - (yytext_ptr);
+			++(yy_c_buf_p);
+
+			switch ( yy_get_next_buffer(  ) )
+				{
+				case EOB_ACT_LAST_MATCH:
+					/* This happens because yy_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. */
+					fitshdrrestart(fitshdrin );
+
+					/*FALLTHROUGH*/
+
+				case EOB_ACT_END_OF_FILE:
+					{
+					if ( fitshdrwrap( ) )
+						return EOF;
+
+					if ( ! (yy_did_buffer_switch_on_eof) )
+						YY_NEW_FILE;
+#ifdef __cplusplus
+					return yyinput();
+#else
+					return input();
+#endif
+					}
+
+				case EOB_ACT_CONTINUE_SCAN:
+					(yy_c_buf_p) = (yytext_ptr) + offset;
+					break;
+				}
+			}
+		}
+
+	c = *(unsigned char *) (yy_c_buf_p);	/* cast for 8-bit char's */
+	*(yy_c_buf_p) = '\0';	/* preserve fitshdrtext */
+	(yy_hold_char) = *++(yy_c_buf_p);
+
+	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = (c == '\n');
+
+	return c;
+}
+#endif	/* ifndef YY_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 fitshdrrestart  (FILE * input_file )
+{
+    
+	if ( ! YY_CURRENT_BUFFER ){
+        fitshdrensure_buffer_stack ();
+		YY_CURRENT_BUFFER_LVALUE =
+            fitshdr_create_buffer(fitshdrin,YY_BUF_SIZE );
+	}
+
+	fitshdr_init_buffer(YY_CURRENT_BUFFER,input_file );
+	fitshdr_load_buffer_state( );
+}
+
+/** Switch to a different input buffer.
+ * @param new_buffer The new input buffer.
+ * 
+ */
+    void fitshdr_switch_to_buffer  (YY_BUFFER_STATE  new_buffer )
+{
+    
+	/* TODO. We should be able to replace this entire function body
+	 * with
+	 *		fitshdrpop_buffer_state();
+	 *		fitshdrpush_buffer_state(new_buffer);
+     */
+	fitshdrensure_buffer_stack ();
+	if ( YY_CURRENT_BUFFER == new_buffer )
+		return;
+
+	if ( YY_CURRENT_BUFFER )
+		{
+		/* Flush out information for old buffer. */
+		*(yy_c_buf_p) = (yy_hold_char);
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+		}
+
+	YY_CURRENT_BUFFER_LVALUE = new_buffer;
+	fitshdr_load_buffer_state( );
+
+	/* We don't actually know whether we did this switch during
+	 * EOF (fitshdrwrap()) processing, but the only time this flag
+	 * is looked at is after fitshdrwrap() is called, so it's safe
+	 * to go ahead and always set it.
+	 */
+	(yy_did_buffer_switch_on_eof) = 1;
+}
+
+static void fitshdr_load_buffer_state  (void)
+{
+    	(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+	(yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+	fitshdrin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+	(yy_hold_char) = *(yy_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 YY_BUF_SIZE.
+ * 
+ * @return the allocated buffer state.
+ */
+    YY_BUFFER_STATE fitshdr_create_buffer  (FILE * file, int  size )
+{
+	YY_BUFFER_STATE b;
+    
+	b = (YY_BUFFER_STATE) fitshdralloc(sizeof( struct yy_buffer_state )  );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in fitshdr_create_buffer()" );
+
+	b->yy_buf_size = size;
+
+	/* yy_ch_buf has to be 2 characters longer than the size given because
+	 * we need to put in 2 end-of-buffer characters.
+	 */
+	b->yy_ch_buf = (char *) fitshdralloc(b->yy_buf_size + 2  );
+	if ( ! b->yy_ch_buf )
+		YY_FATAL_ERROR( "out of dynamic memory in fitshdr_create_buffer()" );
+
+	b->yy_is_our_buffer = 1;
+
+	fitshdr_init_buffer(b,file );
+
+	return b;
+}
+
+/** Destroy the buffer.
+ * @param b a buffer created with fitshdr_create_buffer()
+ * 
+ */
+    void fitshdr_delete_buffer (YY_BUFFER_STATE  b )
+{
+    
+	if ( ! b )
+		return;
+
+	if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+		YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
+
+	if ( b->yy_is_our_buffer )
+		fitshdrfree((void *) b->yy_ch_buf  );
+
+	fitshdrfree((void *) b  );
+}
+
+/* Initializes or reinitializes a buffer.
+ * This function is sometimes called more than once on the same buffer,
+ * such as during a fitshdrrestart() or at EOF.
+ */
+    static void fitshdr_init_buffer  (YY_BUFFER_STATE  b, FILE * file )
+
+{
+	int oerrno = errno;
+    
+	fitshdr_flush_buffer(b );
+
+	b->yy_input_file = file;
+	b->yy_fill_buffer = 1;
+
+    /* If b is the current buffer, then fitshdr_init_buffer was _probably_
+     * called from fitshdrrestart() or through yy_get_next_buffer.
+     * In that case, we don't want to reset the lineno or column.
+     */
+    if (b != YY_CURRENT_BUFFER){
+        b->yy_bs_lineno = 1;
+        b->yy_bs_column = 0;
+    }
+
+        b->yy_is_interactive = 0;
+    
+	errno = oerrno;
+}
+
+/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
+ * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
+ * 
+ */
+    void fitshdr_flush_buffer (YY_BUFFER_STATE  b )
+{
+    	if ( ! b )
+		return;
+
+	b->yy_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->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+	b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+	b->yy_buf_pos = &b->yy_ch_buf[0];
+
+	b->yy_at_bol = 1;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	if ( b == YY_CURRENT_BUFFER )
+		fitshdr_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 fitshdrpush_buffer_state (YY_BUFFER_STATE new_buffer )
+{
+    	if (new_buffer == NULL)
+		return;
+
+	fitshdrensure_buffer_stack();
+
+	/* This block is copied from fitshdr_switch_to_buffer. */
+	if ( YY_CURRENT_BUFFER )
+		{
+		/* Flush out information for old buffer. */
+		*(yy_c_buf_p) = (yy_hold_char);
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+		}
+
+	/* Only push if top exists. Otherwise, replace top. */
+	if (YY_CURRENT_BUFFER)
+		(yy_buffer_stack_top)++;
+	YY_CURRENT_BUFFER_LVALUE = new_buffer;
+
+	/* copied from fitshdr_switch_to_buffer. */
+	fitshdr_load_buffer_state( );
+	(yy_did_buffer_switch_on_eof) = 1;
+}
+
+/** Removes and deletes the top of the stack, if present.
+ *  The next element becomes the new top.
+ *  
+ */
+void fitshdrpop_buffer_state (void)
+{
+    	if (!YY_CURRENT_BUFFER)
+		return;
+
+	fitshdr_delete_buffer(YY_CURRENT_BUFFER );
+	YY_CURRENT_BUFFER_LVALUE = NULL;
+	if ((yy_buffer_stack_top) > 0)
+		--(yy_buffer_stack_top);
+
+	if (YY_CURRENT_BUFFER) {
+		fitshdr_load_buffer_state( );
+		(yy_did_buffer_switch_on_eof) = 1;
+	}
+}
+
+/* Allocates the stack if it does not exist.
+ *  Guarantees space for at least one push.
+ */
+static void fitshdrensure_buffer_stack (void)
+{
+	int num_to_alloc;
+    
+	if (!(yy_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;
+		(yy_buffer_stack) = (struct yy_buffer_state**)fitshdralloc
+								(num_to_alloc * sizeof(struct yy_buffer_state*)
+								);
+		if ( ! (yy_buffer_stack) )
+			YY_FATAL_ERROR( "out of dynamic memory in fitshdrensure_buffer_stack()" );
+								  
+		memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+				
+		(yy_buffer_stack_max) = num_to_alloc;
+		(yy_buffer_stack_top) = 0;
+		return;
+	}
+
+	if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
+
+		/* Increase the buffer to prepare for a possible push. */
+		int grow_size = 8 /* arbitrary grow size */;
+
+		num_to_alloc = (yy_buffer_stack_max) + grow_size;
+		(yy_buffer_stack) = (struct yy_buffer_state**)fitshdrrealloc
+								((yy_buffer_stack),
+								num_to_alloc * sizeof(struct yy_buffer_state*)
+								);
+		if ( ! (yy_buffer_stack) )
+			YY_FATAL_ERROR( "out of dynamic memory in fitshdrensure_buffer_stack()" );
+
+		/* zero only the new slots.*/
+		memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
+		(yy_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. 
+ */
+YY_BUFFER_STATE fitshdr_scan_buffer  (char * base, yy_size_t  size )
+{
+	YY_BUFFER_STATE b;
+    
+	if ( size < 2 ||
+	     base[size-2] != YY_END_OF_BUFFER_CHAR ||
+	     base[size-1] != YY_END_OF_BUFFER_CHAR )
+		/* They forgot to leave room for the EOB's. */
+		return 0;
+
+	b = (YY_BUFFER_STATE) fitshdralloc(sizeof( struct yy_buffer_state )  );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in fitshdr_scan_buffer()" );
+
+	b->yy_buf_size = size - 2;	/* "- 2" to take care of EOB's */
+	b->yy_buf_pos = b->yy_ch_buf = base;
+	b->yy_is_our_buffer = 0;
+	b->yy_input_file = 0;
+	b->yy_n_chars = b->yy_buf_size;
+	b->yy_is_interactive = 0;
+	b->yy_at_bol = 1;
+	b->yy_fill_buffer = 0;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	fitshdr_switch_to_buffer(b  );
+
+	return b;
+}
+
+/** Setup the input buffer state to scan a string. The next call to fitshdrlex() will
+ * scan from a @e copy of @a str.
+ * @param yystr 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
+ *       fitshdr_scan_bytes() instead.
+ */
+YY_BUFFER_STATE fitshdr_scan_string (yyconst char * yystr )
+{
+    
+	return fitshdr_scan_bytes(yystr,strlen(yystr) );
+}
+
+/** Setup the input buffer state to scan the given bytes. The next call to fitshdrlex() will
+ * scan from a @e copy of @a bytes.
+ * @param yybytes the byte buffer to scan
+ * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
+ * 
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE fitshdr_scan_bytes  (yyconst char * yybytes, int  _yybytes_len )
+{
+	YY_BUFFER_STATE b;
+	char *buf;
+	yy_size_t n;
+	int i;
+    
+	/* Get memory for full buffer, including space for trailing EOB's. */
+	n = _yybytes_len + 2;
+	buf = (char *) fitshdralloc(n  );
+	if ( ! buf )
+		YY_FATAL_ERROR( "out of dynamic memory in fitshdr_scan_bytes()" );
+
+	for ( i = 0; i < _yybytes_len; ++i )
+		buf[i] = yybytes[i];
+
+	buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
+
+	b = fitshdr_scan_buffer(buf,n );
+	if ( ! b )
+		YY_FATAL_ERROR( "bad buffer in fitshdr_scan_bytes()" );
+
+	/* It's okay to grow etc. this buffer, and we should throw it
+	 * away when we're done.
+	 */
+	b->yy_is_our_buffer = 1;
+
+	return b;
+}
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+static void yy_fatal_error (yyconst char* msg )
+{
+    	(void) fprintf( stderr, "%s\n", msg );
+	exit( YY_EXIT_FAILURE );
+}
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up fitshdrtext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+		fitshdrtext[fitshdrleng] = (yy_hold_char); \
+		(yy_c_buf_p) = fitshdrtext + yyless_macro_arg; \
+		(yy_hold_char) = *(yy_c_buf_p); \
+		*(yy_c_buf_p) = '\0'; \
+		fitshdrleng = yyless_macro_arg; \
+		} \
+	while ( 0 )
+
+/* Accessor  methods (get/set functions) to struct members. */
+
+/** Get the current line number.
+ * 
+ */
+int fitshdrget_lineno  (void)
+{
+        
+    return fitshdrlineno;
+}
+
+/** Get the input stream.
+ * 
+ */
+FILE *fitshdrget_in  (void)
+{
+        return fitshdrin;
+}
+
+/** Get the output stream.
+ * 
+ */
+FILE *fitshdrget_out  (void)
+{
+        return fitshdrout;
+}
+
+/** Get the length of the current token.
+ * 
+ */
+int fitshdrget_leng  (void)
+{
+        return fitshdrleng;
+}
+
+/** Get the current token.
+ * 
+ */
+
+char *fitshdrget_text  (void)
+{
+        return fitshdrtext;
+}
+
+/** Set the current line number.
+ * @param line_number
+ * 
+ */
+void fitshdrset_lineno (int  line_number )
+{
+    
+    fitshdrlineno = line_number;
+}
+
+/** Set the input stream. This does not discard the current
+ * input buffer.
+ * @param in_str A readable stream.
+ * 
+ * @see fitshdr_switch_to_buffer
+ */
+void fitshdrset_in (FILE *  in_str )
+{
+        fitshdrin = in_str ;
+}
+
+void fitshdrset_out (FILE *  out_str )
+{
+        fitshdrout = out_str ;
+}
+
+int fitshdrget_debug  (void)
+{
+        return fitshdr_flex_debug;
+}
+
+void fitshdrset_debug (int  bdebug )
+{
+        fitshdr_flex_debug = bdebug ;
+}
+
+static int yy_init_globals (void)
+{
+        /* Initialization is the same as for the non-reentrant scanner.
+     * This function is called from fitshdrlex_destroy(), so don't allocate here.
+     */
+
+    (yy_buffer_stack) = 0;
+    (yy_buffer_stack_top) = 0;
+    (yy_buffer_stack_max) = 0;
+    (yy_c_buf_p) = (char *) 0;
+    (yy_init) = 0;
+    (yy_start) = 0;
+
+/* Defined in main.c */
+#ifdef YY_STDINIT
+    fitshdrin = stdin;
+    fitshdrout = stdout;
+#else
+    fitshdrin = (FILE *) 0;
+    fitshdrout = (FILE *) 0;
+#endif
+
+    /* For future reference: Set errno on error, since we are called by
+     * fitshdrlex_init()
+     */
+    return 0;
+}
+
+/* fitshdrlex_destroy is for both reentrant and non-reentrant scanners. */
+int fitshdrlex_destroy  (void)
+{
+    
+    /* Pop the buffer stack, destroying each element. */
+	while(YY_CURRENT_BUFFER){
+		fitshdr_delete_buffer(YY_CURRENT_BUFFER  );
+		YY_CURRENT_BUFFER_LVALUE = NULL;
+		fitshdrpop_buffer_state();
+	}
+
+	/* Destroy the stack itself. */
+	fitshdrfree((yy_buffer_stack) );
+	(yy_buffer_stack) = NULL;
+
+    /* Reset the globals. This is important in a non-reentrant scanner so the next time
+     * fitshdrlex() is called, initialization will occur. */
+    yy_init_globals( );
+
+    return 0;
+}
+
+/*
+ * Internal utility routines.
+ */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
+{
+	register int i;
+	for ( i = 0; i < n; ++i )
+		s1[i] = s2[i];
+}
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * s )
+{
+	register int n;
+	for ( n = 0; s[n]; ++n )
+		;
+
+	return n;
+}
+#endif
+
+void *fitshdralloc (yy_size_t  size )
+{
+	return (void *) malloc( size );
+}
+
+void *fitshdrrealloc  (void * ptr, yy_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 fitshdrfree (void * ptr )
+{
+	free( (char *) ptr );	/* see fitshdrrealloc() for (char *) cast */
+}
+
+#define YYTABLES_NAME "yytables"
+
+#line 545 "fitshdr.l"
+
+
+
+/*--------------------------------------------------------------------------*/
+
+void nullfill(char cptr[], int len)
+
+{
+  int j, k;
+
+  /* Null-fill the string. */
+  for (j = 0; j < len; j++) {
+    if (cptr[j] == '\0') {
+      for (k = j+1; k < len; k++) {
+        cptr[k] = '\0';
+      }
+      break;
+    }
+  }
+
+  for (k = j-1; k >= 0; k--) {
+    if (cptr[k] != ' ') break;
+    cptr[k] = '\0';
+  }
+
+  return;
+}
+
diff --git a/cextern/wcslib/C/flexed/wcsbth.c b/cextern/wcslib/C/flexed/wcsbth.c
new file mode 100644
index 0000000..52ef518
--- /dev/null
+++ b/cextern/wcslib/C/flexed/wcsbth.c
@@ -0,0 +1,21063 @@
+#line 2 "wcsbth.c"
+
+#line 4 "wcsbth.c"
+
+#define  YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define yy_create_buffer wcsbth_create_buffer
+#define yy_delete_buffer wcsbth_delete_buffer
+#define yy_flex_debug wcsbth_flex_debug
+#define yy_init_buffer wcsbth_init_buffer
+#define yy_flush_buffer wcsbth_flush_buffer
+#define yy_load_buffer_state wcsbth_load_buffer_state
+#define yy_switch_to_buffer wcsbth_switch_to_buffer
+#define yyin wcsbthin
+#define yyleng wcsbthleng
+#define yylex wcsbthlex
+#define yylineno wcsbthlineno
+#define yyout wcsbthout
+#define yyrestart wcsbthrestart
+#define yytext wcsbthtext
+#define yywrap wcsbthwrap
+#define yyalloc wcsbthalloc
+#define yyrealloc wcsbthrealloc
+#define yyfree wcsbthfree
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+#define YY_FLEX_SUBMINOR_VERSION 35
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+/* First, we deal with  platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. 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 <inttypes.h>
+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;
+
+/* 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 /* ! C99 */
+
+#endif /* ! FLEXINT_H */
+
+#ifdef __cplusplus
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else	/* ! __cplusplus */
+
+/* C99 requires __STDC__ to be defined as 1. */
+#if defined (__STDC__)
+
+#define YY_USE_CONST
+
+#endif	/* defined (__STDC__) */
+#endif	/* ! __cplusplus */
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_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 YY_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 (yy_start) = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state.  The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START (((yy_start) - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE wcsbthrestart(wcsbthin  )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k.
+ * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
+ * Ditto for the __ia64__ case accordingly.
+ */
+#define YY_BUF_SIZE 32768
+#else
+#define YY_BUF_SIZE 16384
+#endif /* __ia64__ */
+#endif
+
+/* The state buf must be large enough to hold one state per character in the main buffer.
+ */
+#define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+extern int wcsbthleng;
+
+extern FILE *wcsbthin, *wcsbthout;
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+#define YY_LESS_LINENO(n)
+    
+/* Return all but the first "n" matched characters back to the input stream. */
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up wcsbthtext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+		*yy_cp = (yy_hold_char); \
+		YY_RESTORE_YY_MORE_OFFSET \
+		(yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+		YY_DO_BEFORE_ACTION; /* set up wcsbthtext again */ \
+		} \
+	while ( 0 )
+
+#define unput(c) yyunput( c, (yytext_ptr)  )
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef size_t yy_size_t;
+#endif
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+	{
+	FILE *yy_input_file;
+
+	char *yy_ch_buf;		/* input buffer */
+	char *yy_buf_pos;		/* current position in input buffer */
+
+	/* Size of input buffer in bytes, not including room for EOB
+	 * characters.
+	 */
+	yy_size_t yy_buf_size;
+
+	/* Number of characters read into yy_ch_buf, not including EOB
+	 * characters.
+	 */
+	int yy_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 yy_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 yy_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 yy_at_bol;
+
+    int yy_bs_lineno; /**< The line count. */
+    int yy_bs_column; /**< The column count. */
+    
+	/* Whether to try to fill the input buffer when we reach the
+	 * end of it.
+	 */
+	int yy_fill_buffer;
+
+	int yy_buffer_status;
+
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+	/* When an EOF's been seen but there's still some text to process
+	 * then we mark the buffer as YY_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 wcsbthrestart()), so that the user can continue scanning by
+	 * just pointing wcsbthin at a new input file.
+	 */
+#define YY_BUFFER_EOF_PENDING 2
+
+	};
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+/* Stack of input buffers. */
+static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
+static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
+static YY_BUFFER_STATE * yy_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 YY_CURRENT_BUFFER ( (yy_buffer_stack) \
+                          ? (yy_buffer_stack)[(yy_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 YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
+
+/* yy_hold_char holds the character lost when wcsbthtext is formed. */
+static char yy_hold_char;
+static int yy_n_chars;		/* number of characters read into yy_ch_buf */
+int wcsbthleng;
+
+/* Points to current character in buffer. */
+static char *yy_c_buf_p = (char *) 0;
+static int yy_init = 0;		/* whether we need to initialize */
+static int yy_start = 0;	/* start state number */
+
+/* Flag which is used to allow wcsbthwrap()'s to do buffer switches
+ * instead of setting up a fresh wcsbthin.  A bit of a hack ...
+ */
+static int yy_did_buffer_switch_on_eof;
+
+void wcsbthrestart (FILE *input_file  );
+void wcsbth_switch_to_buffer (YY_BUFFER_STATE new_buffer  );
+YY_BUFFER_STATE wcsbth_create_buffer (FILE *file,int size  );
+void wcsbth_delete_buffer (YY_BUFFER_STATE b  );
+void wcsbth_flush_buffer (YY_BUFFER_STATE b  );
+void wcsbthpush_buffer_state (YY_BUFFER_STATE new_buffer  );
+void wcsbthpop_buffer_state (void );
+
+static void wcsbthensure_buffer_stack (void );
+static void wcsbth_load_buffer_state (void );
+static void wcsbth_init_buffer (YY_BUFFER_STATE b,FILE *file  );
+
+#define YY_FLUSH_BUFFER wcsbth_flush_buffer(YY_CURRENT_BUFFER )
+
+YY_BUFFER_STATE wcsbth_scan_buffer (char *base,yy_size_t size  );
+YY_BUFFER_STATE wcsbth_scan_string (yyconst char *yy_str  );
+YY_BUFFER_STATE wcsbth_scan_bytes (yyconst char *bytes,int len  );
+
+void *wcsbthalloc (yy_size_t  );
+void *wcsbthrealloc (void *,yy_size_t  );
+void wcsbthfree (void *  );
+
+#define yy_new_buffer wcsbth_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+	{ \
+	if ( ! YY_CURRENT_BUFFER ){ \
+        wcsbthensure_buffer_stack (); \
+		YY_CURRENT_BUFFER_LVALUE =    \
+            wcsbth_create_buffer(wcsbthin,YY_BUF_SIZE ); \
+	} \
+	YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+	}
+
+#define yy_set_bol(at_bol) \
+	{ \
+	if ( ! YY_CURRENT_BUFFER ){\
+        wcsbthensure_buffer_stack (); \
+		YY_CURRENT_BUFFER_LVALUE =    \
+            wcsbth_create_buffer(wcsbthin,YY_BUF_SIZE ); \
+	} \
+	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+	}
+
+#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+
+/* Begin user sect3 */
+
+#define wcsbthwrap(n) 1
+#define YY_SKIP_YYWRAP
+
+typedef char YY_CHAR;
+
+FILE *wcsbthin = (FILE *) 0, *wcsbthout = (FILE *) 0;
+
+typedef int yy_state_type;
+
+extern int wcsbthlineno;
+
+int wcsbthlineno = 1;
+
+extern char *wcsbthtext;
+#define yytext_ptr wcsbthtext
+static yyconst flex_int16_t yy_nxt[][128] =
+    {
+    {
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0
+    },
+
+    {
+       67,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68
+    },
+
+    {
+       67,   69,   69,   69,   69,   69,   69,   69,   69,   69,
+       68,   69,   69,   69,   69,   69,   69,   69,   69,   69,
+       69,   69,   69,   69,   69,   69,   69,   69,   69,   69,
+       69,   69,   69,   69,   69,   69,   69,   69,   69,   69,
+
+       69,   69,   69,   69,   69,   69,   69,   69,   69,   70,
+       70,   70,   70,   70,   70,   70,   70,   70,   69,   69,
+       69,   69,   69,   69,   69,   69,   69,   71,   72,   73,
+       69,   69,   69,   69,   69,   69,   74,   75,   69,   76,
+       77,   69,   78,   79,   80,   69,   81,   82,   69,   69,
+       83,   69,   69,   69,   69,   69,   69,   69,   69,   69,
+       69,   69,   69,   69,   69,   69,   69,   69,   69,   69,
+       69,   69,   69,   69,   69,   69,   69,   69,   69,   69,
+       69,   69,   69,   69,   69,   69,   69,   69
+    },
+
+    {
+       67,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   84,
+       84,   84,   84,   84,   84,   84,   84,   84,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68
+    },
+
+    {
+       67,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   84,
+       84,   84,   84,   84,   84,   84,   84,   84,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68
+    },
+
+    {
+       67,   85,   85,   85,   85,   85,   85,   85,   85,   85,
+       68,   85,   85,   85,   85,   85,   85,   85,   85,   85,
+       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
+       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
+       85,   85,   85,   85,   85,   85,   85,   85,   85,   86,
+
+       86,   86,   86,   86,   86,   86,   86,   86,   85,   85,
+       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
+       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
+       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
+       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
+       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
+       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
+       85,   85,   85,   85,   85,   85,   85,   85
+    },
+
+    {
+       67,   85,   85,   85,   85,   85,   85,   85,   85,   85,
+       68,   85,   85,   85,   85,   85,   85,   85,   85,   85,
+
+       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
+       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
+       85,   85,   85,   85,   85,   85,   85,   85,   85,   86,
+       86,   86,   86,   86,   86,   86,   86,   86,   85,   85,
+       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
+       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
+       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
+       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
+       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
+       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
+
+       85,   85,   85,   85,   85,   85,   85,   85
+    },
+
+    {
+       67,   87,   87,   87,   87,   87,   87,   87,   87,   87,
+       68,   87,   87,   87,   87,   87,   87,   87,   87,   87,
+       87,   87,   87,   87,   87,   87,   87,   87,   87,   87,
+       87,   87,   87,   87,   87,   87,   87,   87,   87,   87,
+       87,   87,   87,   87,   87,   87,   87,   87,   87,   88,
+       88,   88,   88,   88,   88,   88,   88,   88,   87,   87,
+       87,   87,   87,   87,   87,   87,   87,   87,   87,   87,
+       87,   87,   87,   87,   87,   87,   87,   87,   87,   87,
+       87,   87,   87,   87,   87,   87,   87,   87,   87,   87,
+
+       87,   87,   87,   87,   87,   87,   87,   87,   87,   87,
+       87,   87,   87,   87,   87,   87,   87,   87,   87,   87,
+       87,   87,   87,   87,   87,   87,   87,   87,   87,   87,
+       87,   87,   87,   87,   87,   87,   87,   87
+    },
+
+    {
+       67,   87,   87,   87,   87,   87,   87,   87,   87,   87,
+       68,   87,   87,   87,   87,   87,   87,   87,   87,   87,
+       87,   87,   87,   87,   87,   87,   87,   87,   87,   87,
+       87,   87,   87,   87,   87,   87,   87,   87,   87,   87,
+       87,   87,   87,   87,   87,   87,   87,   87,   87,   88,
+       88,   88,   88,   88,   88,   88,   88,   88,   87,   87,
+
+       87,   87,   87,   87,   87,   87,   87,   87,   87,   87,
+       87,   87,   87,   87,   87,   87,   87,   87,   87,   87,
+       87,   87,   87,   87,   87,   87,   87,   87,   87,   87,
+       87,   87,   87,   87,   87,   87,   87,   87,   87,   87,
+       87,   87,   87,   87,   87,   87,   87,   87,   87,   87,
+       87,   87,   87,   87,   87,   87,   87,   87,   87,   87,
+       87,   87,   87,   87,   87,   87,   87,   87
+    },
+
+    {
+       67,   89,   89,   89,   89,   89,   89,   89,   89,   89,
+       68,   89,   89,   89,   89,   89,   89,   89,   89,   89,
+       89,   89,   89,   89,   89,   89,   89,   89,   89,   89,
+
+       89,   89,   89,   89,   89,   89,   89,   89,   89,   89,
+       89,   89,   89,   89,   89,   89,   89,   89,   89,   90,
+       90,   90,   90,   90,   90,   90,   90,   90,   89,   89,
+       89,   89,   89,   89,   89,   89,   89,   89,   89,   89,
+       89,   89,   89,   89,   89,   89,   89,   89,   89,   89,
+       89,   89,   89,   89,   89,   89,   89,   89,   89,   89,
+       89,   89,   89,   89,   89,   89,   89,   89,   89,   89,
+       89,   89,   89,   89,   89,   89,   89,   89,   89,   89,
+       89,   89,   89,   89,   89,   89,   89,   89,   89,   89,
+       89,   89,   89,   89,   89,   89,   89,   89
+
+    },
+
+    {
+       67,   89,   89,   89,   89,   89,   89,   89,   89,   89,
+       68,   89,   89,   89,   89,   89,   89,   89,   89,   89,
+       89,   89,   89,   89,   89,   89,   89,   89,   89,   89,
+       89,   89,   89,   89,   89,   89,   89,   89,   89,   89,
+       89,   89,   89,   89,   89,   89,   89,   89,   89,   90,
+       90,   90,   90,   90,   90,   90,   90,   90,   89,   89,
+       89,   89,   89,   89,   89,   89,   89,   89,   89,   89,
+       89,   89,   89,   89,   89,   89,   89,   89,   89,   89,
+       89,   89,   89,   89,   89,   89,   89,   89,   89,   89,
+       89,   89,   89,   89,   89,   89,   89,   89,   89,   89,
+
+       89,   89,   89,   89,   89,   89,   89,   89,   89,   89,
+       89,   89,   89,   89,   89,   89,   89,   89,   89,   89,
+       89,   89,   89,   89,   89,   89,   89,   89
+    },
+
+    {
+       67,   91,   91,   91,   91,   91,   91,   91,   91,   91,
+       68,   91,   91,   91,   91,   91,   91,   91,   91,   91,
+       91,   91,   91,   91,   91,   91,   91,   91,   91,   91,
+       91,   91,   91,   91,   91,   91,   91,   91,   91,   91,
+       91,   91,   91,   91,   91,   91,   91,   91,   91,   92,
+       92,   92,   92,   92,   92,   92,   92,   92,   91,   91,
+       91,   91,   91,   91,   91,   91,   91,   91,   91,   91,
+
+       91,   91,   91,   91,   91,   91,   91,   91,   91,   91,
+       91,   91,   91,   91,   91,   91,   91,   91,   91,   91,
+       91,   91,   91,   91,   91,   91,   91,   91,   91,   91,
+       91,   91,   91,   91,   91,   91,   91,   91,   91,   91,
+       91,   91,   91,   91,   91,   91,   91,   91,   91,   91,
+       91,   91,   91,   91,   91,   91,   91,   91
+    },
+
+    {
+       67,   91,   91,   91,   91,   91,   91,   91,   91,   91,
+       68,   91,   91,   91,   91,   91,   91,   91,   91,   91,
+       91,   91,   91,   91,   91,   91,   91,   91,   91,   91,
+       91,   91,   91,   91,   91,   91,   91,   91,   91,   91,
+
+       91,   91,   91,   91,   91,   91,   91,   91,   91,   92,
+       92,   92,   92,   92,   92,   92,   92,   92,   91,   91,
+       91,   91,   91,   91,   91,   91,   91,   91,   91,   91,
+       91,   91,   91,   91,   91,   91,   91,   91,   91,   91,
+       91,   91,   91,   91,   91,   91,   91,   91,   91,   91,
+       91,   91,   91,   91,   91,   91,   91,   91,   91,   91,
+       91,   91,   91,   91,   91,   91,   91,   91,   91,   91,
+       91,   91,   91,   91,   91,   91,   91,   91,   91,   91,
+       91,   91,   91,   91,   91,   91,   91,   91
+    },
+
+    {
+       67,   93,   93,   93,   93,   93,   93,   93,   93,   93,
+
+       68,   93,   93,   93,   93,   93,   93,   93,   93,   93,
+       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
+       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
+       93,   93,   93,   93,   93,   93,   93,   93,   94,   95,
+       95,   95,   95,   95,   95,   95,   95,   95,   93,   93,
+       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
+       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
+       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
+       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
+       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
+
+       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
+       93,   93,   93,   93,   93,   93,   93,   93
+    },
+
+    {
+       67,   93,   93,   93,   93,   93,   93,   93,   93,   93,
+       68,   93,   93,   93,   93,   93,   93,   93,   93,   93,
+       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
+       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
+       93,   93,   93,   93,   93,   93,   93,   93,   94,   95,
+       95,   95,   95,   95,   95,   95,   95,   95,   93,   93,
+       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
+       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
+
+       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
+       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
+       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
+       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
+       93,   93,   93,   93,   93,   93,   93,   93
+    },
+
+    {
+       67,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   96,
+
+       96,   96,   96,   96,   96,   96,   96,   96,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68
+    },
+
+    {
+       67,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   96,
+       96,   96,   96,   96,   96,   96,   96,   96,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+
+       68,   68,   68,   68,   68,   68,   68,   68
+    },
+
+    {
+       67,   97,   97,   97,   97,   97,   97,   97,   97,   97,
+       68,   97,   97,   97,   97,   97,   97,   97,   97,   97,
+       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
+       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
+       97,   97,   97,   97,   97,   97,   97,   97,   97,   98,
+       98,   98,   98,   98,   98,   98,   98,   98,   97,   97,
+       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
+       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
+       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
+
+       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
+       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
+       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
+       97,   97,   97,   97,   97,   97,   97,   97
+    },
+
+    {
+       67,   97,   97,   97,   97,   97,   97,   97,   97,   97,
+       68,   97,   97,   97,   97,   97,   97,   97,   97,   97,
+       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
+       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
+       97,   97,   97,   97,   97,   97,   97,   97,   97,   98,
+       98,   98,   98,   98,   98,   98,   98,   98,   97,   97,
+
+       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
+       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
+       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
+       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
+       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
+       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
+       97,   97,   97,   97,   97,   97,   97,   97
+    },
+
+    {
+       67,   99,   99,   99,   99,   99,   99,   99,   99,   99,
+       68,   99,   99,   99,   99,   99,   99,   99,   99,   99,
+       99,   99,   99,   99,   99,   99,   99,   99,   99,   99,
+
+       99,   99,   99,   99,   99,   99,   99,   99,   99,   99,
+       99,   99,   99,   99,   99,   99,   99,   99,   99,  100,
+      100,  100,  100,  100,  100,  100,  100,  100,   99,   99,
+       99,   99,   99,   99,   99,   99,   99,   99,   99,   99,
+       99,   99,   99,   99,   99,   99,   99,   99,   99,   99,
+       99,   99,   99,   99,   99,   99,   99,   99,   99,   99,
+       99,   99,   99,   99,   99,   99,   99,   99,   99,   99,
+       99,   99,   99,   99,   99,   99,   99,   99,   99,   99,
+       99,   99,   99,   99,   99,   99,   99,   99,   99,   99,
+       99,   99,   99,   99,   99,   99,   99,   99
+
+    },
+
+    {
+       67,   99,   99,   99,   99,   99,   99,   99,   99,   99,
+       68,   99,   99,   99,   99,   99,   99,   99,   99,   99,
+       99,   99,   99,   99,   99,   99,   99,   99,   99,   99,
+       99,   99,   99,   99,   99,   99,   99,   99,   99,   99,
+       99,   99,   99,   99,   99,   99,   99,   99,   99,  100,
+      100,  100,  100,  100,  100,  100,  100,  100,   99,   99,
+       99,   99,   99,   99,   99,   99,   99,   99,   99,   99,
+       99,   99,   99,   99,   99,   99,   99,   99,   99,   99,
+       99,   99,   99,   99,   99,   99,   99,   99,   99,   99,
+       99,   99,   99,   99,   99,   99,   99,   99,   99,   99,
+
+       99,   99,   99,   99,   99,   99,   99,   99,   99,   99,
+       99,   99,   99,   99,   99,   99,   99,   99,   99,   99,
+       99,   99,   99,   99,   99,   99,   99,   99
+    },
+
+    {
+       67,  101,  101,  101,  101,  101,  101,  101,  101,  101,
+       68,  101,  101,  101,  101,  101,  101,  101,  101,  101,
+      101,  101,  101,  101,  101,  101,  101,  101,  101,  101,
+      101,  101,  101,  101,  101,  101,  101,  101,  101,  101,
+      101,  101,  101,  101,  101,  101,  101,  101,  101,  102,
+      102,  102,  102,  102,  102,  102,  102,  102,  101,  101,
+      101,  101,  101,  101,  101,  101,  101,  101,  101,  101,
+
+      101,  101,  101,  101,  101,  101,  101,  101,  101,  101,
+      101,  101,  101,  101,  101,  101,  101,  101,  101,  101,
+      101,  101,  101,  101,  101,  101,  101,  101,  101,  101,
+      101,  101,  101,  101,  101,  101,  101,  101,  101,  101,
+      101,  101,  101,  101,  101,  101,  101,  101,  101,  101,
+      101,  101,  101,  101,  101,  101,  101,  101
+    },
+
+    {
+       67,  101,  101,  101,  101,  101,  101,  101,  101,  101,
+       68,  101,  101,  101,  101,  101,  101,  101,  101,  101,
+      101,  101,  101,  101,  101,  101,  101,  101,  101,  101,
+      101,  101,  101,  101,  101,  101,  101,  101,  101,  101,
+
+      101,  101,  101,  101,  101,  101,  101,  101,  101,  102,
+      102,  102,  102,  102,  102,  102,  102,  102,  101,  101,
+      101,  101,  101,  101,  101,  101,  101,  101,  101,  101,
+      101,  101,  101,  101,  101,  101,  101,  101,  101,  101,
+      101,  101,  101,  101,  101,  101,  101,  101,  101,  101,
+      101,  101,  101,  101,  101,  101,  101,  101,  101,  101,
+      101,  101,  101,  101,  101,  101,  101,  101,  101,  101,
+      101,  101,  101,  101,  101,  101,  101,  101,  101,  101,
+      101,  101,  101,  101,  101,  101,  101,  101
+    },
+
+    {
+       67,  103,  103,  103,  103,  103,  103,  103,  103,  103,
+
+       68,  103,  103,  103,  103,  103,  103,  103,  103,  103,
+      103,  103,  103,  103,  103,  103,  103,  103,  103,  103,
+      103,  103,  103,  103,  103,  103,  103,  103,  103,  103,
+      103,  103,  103,  103,  103,  103,  103,  103,  103,  104,
+      104,  104,  104,  104,  104,  104,  104,  104,  103,  103,
+      103,  103,  103,  103,  103,  103,  103,  103,  103,  103,
+      103,  103,  103,  103,  103,  103,  103,  103,  103,  103,
+      103,  103,  103,  103,  103,  103,  103,  103,  103,  103,
+      103,  103,  103,  103,  103,  103,  103,  103,  103,  103,
+      103,  103,  103,  103,  103,  103,  103,  103,  103,  103,
+
+      103,  103,  103,  103,  103,  103,  103,  103,  103,  103,
+      103,  103,  103,  103,  103,  103,  103,  103
+    },
+
+    {
+       67,  103,  103,  103,  103,  103,  103,  103,  103,  103,
+       68,  103,  103,  103,  103,  103,  103,  103,  103,  103,
+      103,  103,  103,  103,  103,  103,  103,  103,  103,  103,
+      103,  103,  103,  103,  103,  103,  103,  103,  103,  103,
+      103,  103,  103,  103,  103,  103,  103,  103,  103,  104,
+      104,  104,  104,  104,  104,  104,  104,  104,  103,  103,
+      103,  103,  103,  103,  103,  103,  103,  103,  103,  103,
+      103,  103,  103,  103,  103,  103,  103,  103,  103,  103,
+
+      103,  103,  103,  103,  103,  103,  103,  103,  103,  103,
+      103,  103,  103,  103,  103,  103,  103,  103,  103,  103,
+      103,  103,  103,  103,  103,  103,  103,  103,  103,  103,
+      103,  103,  103,  103,  103,  103,  103,  103,  103,  103,
+      103,  103,  103,  103,  103,  103,  103,  103
+    },
+
+    {
+       67,  105,  105,  105,  105,  105,  105,  105,  105,  105,
+       68,  105,  105,  105,  105,  105,  105,  105,  105,  105,
+      105,  105,  105,  105,  105,  105,  105,  105,  105,  105,
+      105,  105,  105,  105,  105,  105,  105,  105,  105,  105,
+      105,  105,  105,  105,  105,  105,  105,  105,  105,  106,
+
+      106,  106,  106,  106,  106,  106,  106,  106,  105,  105,
+      105,  105,  105,  105,  105,  105,  105,  105,  105,  105,
+      105,  105,  105,  105,  105,  105,  105,  105,  105,  105,
+      105,  105,  105,  105,  105,  105,  105,  105,  105,  105,
+      105,  105,  105,  105,  105,  105,  105,  105,  105,  105,
+      105,  105,  105,  105,  105,  105,  105,  105,  105,  105,
+      105,  105,  105,  105,  105,  105,  105,  105,  105,  105,
+      105,  105,  105,  105,  105,  105,  105,  105
+    },
+
+    {
+       67,  105,  105,  105,  105,  105,  105,  105,  105,  105,
+       68,  105,  105,  105,  105,  105,  105,  105,  105,  105,
+
+      105,  105,  105,  105,  105,  105,  105,  105,  105,  105,
+      105,  105,  105,  105,  105,  105,  105,  105,  105,  105,
+      105,  105,  105,  105,  105,  105,  105,  105,  105,  106,
+      106,  106,  106,  106,  106,  106,  106,  106,  105,  105,
+      105,  105,  105,  105,  105,  105,  105,  105,  105,  105,
+      105,  105,  105,  105,  105,  105,  105,  105,  105,  105,
+      105,  105,  105,  105,  105,  105,  105,  105,  105,  105,
+      105,  105,  105,  105,  105,  105,  105,  105,  105,  105,
+      105,  105,  105,  105,  105,  105,  105,  105,  105,  105,
+      105,  105,  105,  105,  105,  105,  105,  105,  105,  105,
+
+      105,  105,  105,  105,  105,  105,  105,  105
+    },
+
+    {
+       67,  107,  107,  107,  107,  107,  107,  107,  107,  107,
+       68,  107,  107,  107,  107,  107,  107,  107,  107,  107,
+      107,  107,  107,  107,  107,  107,  107,  107,  107,  107,
+      107,  107,  107,  107,  107,  107,  107,  107,  107,  107,
+      107,  107,  107,  107,  107,  107,  107,  107,  107,  108,
+      108,  108,  108,  108,  108,  108,  108,  108,  107,  107,
+      107,  107,  107,  107,  107,  107,  107,  107,  107,  107,
+      107,  107,  107,  107,  107,  107,  107,  107,  107,  107,
+      107,  107,  107,  107,  107,  107,  107,  107,  107,  107,
+
+      107,  107,  107,  107,  107,  107,  107,  107,  107,  107,
+      107,  107,  107,  107,  107,  107,  107,  107,  107,  107,
+      107,  107,  107,  107,  107,  107,  107,  107,  107,  107,
+      107,  107,  107,  107,  107,  107,  107,  107
+    },
+
+    {
+       67,  107,  107,  107,  107,  107,  107,  107,  107,  107,
+       68,  107,  107,  107,  107,  107,  107,  107,  107,  107,
+      107,  107,  107,  107,  107,  107,  107,  107,  107,  107,
+      107,  107,  107,  107,  107,  107,  107,  107,  107,  107,
+      107,  107,  107,  107,  107,  107,  107,  107,  107,  108,
+      108,  108,  108,  108,  108,  108,  108,  108,  107,  107,
+
+      107,  107,  107,  107,  107,  107,  107,  107,  107,  107,
+      107,  107,  107,  107,  107,  107,  107,  107,  107,  107,
+      107,  107,  107,  107,  107,  107,  107,  107,  107,  107,
+      107,  107,  107,  107,  107,  107,  107,  107,  107,  107,
+      107,  107,  107,  107,  107,  107,  107,  107,  107,  107,
+      107,  107,  107,  107,  107,  107,  107,  107,  107,  107,
+      107,  107,  107,  107,  107,  107,  107,  107
+    },
+
+    {
+       67,  109,  109,  109,  109,  109,  109,  109,  109,  109,
+       68,  109,  109,  109,  109,  109,  109,  109,  109,  109,
+      109,  109,  109,  109,  109,  109,  109,  109,  109,  109,
+
+      109,  109,  109,  109,  109,  109,  109,  109,  109,  109,
+      109,  109,  109,  109,  109,  109,  109,  109,  109,  110,
+      110,  110,  110,  110,  110,  110,  110,  110,  109,  109,
+      109,  109,  109,  109,  109,  109,  109,  109,  109,  109,
+      109,  109,  109,  109,  109,  109,  109,  109,  109,  109,
+      109,  109,  109,  109,  109,  109,  109,  109,  109,  109,
+      109,  109,  109,  109,  109,  109,  109,  109,  109,  109,
+      109,  109,  109,  109,  109,  109,  109,  109,  109,  109,
+      109,  109,  109,  109,  109,  109,  109,  109,  109,  109,
+      109,  109,  109,  109,  109,  109,  109,  109
+
+    },
+
+    {
+       67,  109,  109,  109,  109,  109,  109,  109,  109,  109,
+       68,  109,  109,  109,  109,  109,  109,  109,  109,  109,
+      109,  109,  109,  109,  109,  109,  109,  109,  109,  109,
+      109,  109,  109,  109,  109,  109,  109,  109,  109,  109,
+      109,  109,  109,  109,  109,  109,  109,  109,  109,  110,
+      110,  110,  110,  110,  110,  110,  110,  110,  109,  109,
+      109,  109,  109,  109,  109,  109,  109,  109,  109,  109,
+      109,  109,  109,  109,  109,  109,  109,  109,  109,  109,
+      109,  109,  109,  109,  109,  109,  109,  109,  109,  109,
+      109,  109,  109,  109,  109,  109,  109,  109,  109,  109,
+
+      109,  109,  109,  109,  109,  109,  109,  109,  109,  109,
+      109,  109,  109,  109,  109,  109,  109,  109,  109,  109,
+      109,  109,  109,  109,  109,  109,  109,  109
+    },
+
+    {
+       67,  111,  111,  111,  111,  111,  111,  111,  111,  111,
+       68,  111,  111,  111,  111,  111,  111,  111,  111,  111,
+      111,  111,  111,  111,  111,  111,  111,  111,  111,  111,
+      111,  111,  111,  111,  111,  111,  111,  111,  111,  111,
+      111,  111,  111,  111,  111,  111,  111,  111,  111,  112,
+      112,  112,  112,  112,  112,  112,  112,  112,  111,  111,
+      111,  111,  111,  111,  111,  111,  111,  111,  111,  111,
+
+      111,  111,  111,  111,  111,  111,  111,  111,  111,  111,
+      111,  111,  111,  111,  111,  111,  111,  111,  111,  111,
+      111,  111,  111,  111,  111,  111,  111,  111,  111,  111,
+      111,  111,  111,  111,  111,  111,  111,  111,  111,  111,
+      111,  111,  111,  111,  111,  111,  111,  111,  111,  111,
+      111,  111,  111,  111,  111,  111,  111,  111
+    },
+
+    {
+       67,  111,  111,  111,  111,  111,  111,  111,  111,  111,
+       68,  111,  111,  111,  111,  111,  111,  111,  111,  111,
+      111,  111,  111,  111,  111,  111,  111,  111,  111,  111,
+      111,  111,  111,  111,  111,  111,  111,  111,  111,  111,
+
+      111,  111,  111,  111,  111,  111,  111,  111,  111,  112,
+      112,  112,  112,  112,  112,  112,  112,  112,  111,  111,
+      111,  111,  111,  111,  111,  111,  111,  111,  111,  111,
+      111,  111,  111,  111,  111,  111,  111,  111,  111,  111,
+      111,  111,  111,  111,  111,  111,  111,  111,  111,  111,
+      111,  111,  111,  111,  111,  111,  111,  111,  111,  111,
+      111,  111,  111,  111,  111,  111,  111,  111,  111,  111,
+      111,  111,  111,  111,  111,  111,  111,  111,  111,  111,
+      111,  111,  111,  111,  111,  111,  111,  111
+    },
+
+    {
+       67,  113,  113,  113,  113,  113,  113,  113,  113,  113,
+
+       68,  113,  113,  113,  113,  113,  113,  113,  113,  113,
+      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
+      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
+      113,  113,  113,  113,  113,  113,  113,  113,  113,  114,
+      114,  114,  114,  114,  114,  114,  114,  114,  113,  113,
+      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
+      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
+      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
+      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
+      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
+
+      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
+      113,  113,  113,  113,  113,  113,  113,  113
+    },
+
+    {
+       67,  113,  113,  113,  113,  113,  113,  113,  113,  113,
+       68,  113,  113,  113,  113,  113,  113,  113,  113,  113,
+      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
+      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
+      113,  113,  113,  113,  113,  113,  113,  113,  113,  114,
+      114,  114,  114,  114,  114,  114,  114,  114,  113,  113,
+      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
+      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
+
+      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
+      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
+      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
+      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
+      113,  113,  113,  113,  113,  113,  113,  113
+    },
+
+    {
+       67,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+       68,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  116,
+
+      116,  116,  116,  116,  116,  116,  116,  116,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115
+    },
+
+    {
+       67,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+       68,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  116,
+      116,  116,  116,  116,  116,  116,  116,  116,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+
+      115,  115,  115,  115,  115,  115,  115,  115
+    },
+
+    {
+       67,  117,  117,  117,  117,  117,  117,  117,  117,  117,
+       68,  117,  117,  117,  117,  117,  117,  117,  117,  117,
+      117,  117,  117,  117,  117,  117,  117,  117,  117,  117,
+      117,  117,  117,  117,  117,  117,  117,  117,  117,  117,
+      117,  117,  117,  117,  117,  117,  117,  117,  118,  118,
+      118,  118,  118,  118,  118,  118,  118,  118,  117,  117,
+      117,  117,  117,  117,  117,  117,  117,  117,  117,  117,
+      117,  117,  117,  117,  117,  117,  117,  117,  117,  117,
+      117,  117,  117,  117,  117,  117,  117,  117,  117,  117,
+
+      117,  117,  117,  117,  117,  117,  117,  117,  117,  117,
+      117,  117,  117,  117,  117,  117,  117,  117,  117,  117,
+      117,  117,  117,  117,  117,  117,  117,  117,  117,  117,
+      117,  117,  117,  117,  117,  117,  117,  117
+    },
+
+    {
+       67,  117,  117,  117,  117,  117,  117,  117,  117,  117,
+       68,  117,  117,  117,  117,  117,  117,  117,  117,  117,
+      117,  117,  117,  117,  117,  117,  117,  117,  117,  117,
+      117,  117,  117,  117,  117,  117,  117,  117,  117,  117,
+      117,  117,  117,  117,  117,  117,  117,  117,  118,  118,
+      118,  118,  118,  118,  118,  118,  118,  118,  117,  117,
+
+      117,  117,  117,  117,  117,  117,  117,  117,  117,  117,
+      117,  117,  117,  117,  117,  117,  117,  117,  117,  117,
+      117,  117,  117,  117,  117,  117,  117,  117,  117,  117,
+      117,  117,  117,  117,  117,  117,  117,  117,  117,  117,
+      117,  117,  117,  117,  117,  117,  117,  117,  117,  117,
+      117,  117,  117,  117,  117,  117,  117,  117,  117,  117,
+      117,  117,  117,  117,  117,  117,  117,  117
+    },
+
+    {
+       67,  119,  119,  119,  119,  119,  119,  119,  119,  119,
+       68,  119,  119,  119,  119,  119,  119,  119,  119,  119,
+      119,  119,  119,  119,  119,  119,  119,  119,  119,  119,
+
+      119,  119,  119,  119,  119,  119,  119,  119,  119,  119,
+      119,  119,  119,  119,  119,  119,  119,  119,  119,  119,
+      119,  119,  119,  119,  119,  119,  119,  119,  119,  119,
+      119,  119,  119,  119,  119,  119,  119,  119,  119,  119,
+      119,  119,  119,  119,  119,  119,  119,  119,  119,  119,
+      119,  119,  119,  119,  119,  119,  119,  119,  119,  119,
+      119,  119,  119,  119,  119,  119,  119,  119,  119,  119,
+      119,  119,  119,  119,  119,  119,  119,  119,  119,  119,
+      119,  119,  119,  119,  119,  119,  119,  119,  119,  119,
+      119,  119,  119,  119,  119,  119,  119,  119
+
+    },
+
+    {
+       67,  119,  119,  119,  119,  119,  119,  119,  119,  119,
+       68,  119,  119,  119,  119,  119,  119,  119,  119,  119,
+      119,  119,  119,  119,  119,  119,  119,  119,  119,  119,
+      119,  119,  119,  119,  119,  119,  119,  119,  119,  119,
+      119,  119,  119,  119,  119,  119,  119,  119,  119,  119,
+      119,  119,  119,  119,  119,  119,  119,  119,  119,  119,
+      119,  119,  119,  119,  119,  119,  119,  119,  119,  119,
+      119,  119,  119,  119,  119,  119,  119,  119,  119,  119,
+      119,  119,  119,  119,  119,  119,  119,  119,  119,  119,
+      119,  119,  119,  119,  119,  119,  119,  119,  119,  119,
+
+      119,  119,  119,  119,  119,  119,  119,  119,  119,  119,
+      119,  119,  119,  119,  119,  119,  119,  119,  119,  119,
+      119,  119,  119,  119,  119,  119,  119,  119
+    },
+
+    {
+       67,  120,  120,  120,  120,  120,  120,  120,  120,  120,
+       68,  120,  120,  120,  120,  120,  120,  120,  120,  120,
+      120,  120,  120,  120,  120,  120,  120,  120,  120,  120,
+      120,  120,  121,  120,  120,  120,  120,  120,  120,  120,
+      120,  120,  120,  120,  120,  120,  120,  120,  120,  120,
+      120,  120,  120,  120,  120,  120,  120,  120,  120,  120,
+      120,  120,  120,  120,  120,  121,  121,  121,  121,  121,
+
+      121,  121,  121,  121,  121,  121,  121,  121,  121,  121,
+      121,  121,  121,  121,  121,  121,  121,  121,  121,  121,
+      121,  120,  120,  120,  120,  120,  120,  120,  120,  120,
+      120,  120,  120,  120,  120,  120,  120,  120,  120,  120,
+      120,  120,  120,  120,  120,  120,  120,  120,  120,  120,
+      120,  120,  120,  120,  120,  120,  120,  120
+    },
+
+    {
+       67,  120,  120,  120,  120,  120,  120,  120,  120,  120,
+       68,  120,  120,  120,  120,  120,  120,  120,  120,  120,
+      120,  120,  120,  120,  120,  120,  120,  120,  120,  120,
+      120,  120,  121,  120,  120,  120,  120,  120,  120,  120,
+
+      120,  120,  120,  120,  120,  120,  120,  120,  120,  120,
+      120,  120,  120,  120,  120,  120,  120,  120,  120,  120,
+      120,  120,  120,  120,  120,  121,  121,  121,  121,  121,
+      121,  121,  121,  121,  121,  121,  121,  121,  121,  121,
+      121,  121,  121,  121,  121,  121,  121,  121,  121,  121,
+      121,  120,  120,  120,  120,  120,  120,  120,  120,  120,
+      120,  120,  120,  120,  120,  120,  120,  120,  120,  120,
+      120,  120,  120,  120,  120,  120,  120,  120,  120,  120,
+      120,  120,  120,  120,  120,  120,  120,  120
+    },
+
+    {
+       67,  122,  122,  122,  122,  122,  122,  122,  122,  122,
+
+       68,  122,  122,  122,  122,  122,  122,  122,  122,  122,
+      122,  122,  122,  122,  122,  122,  122,  122,  122,  122,
+      122,  122,  122,  122,  122,  122,  122,  122,  122,  122,
+      122,  122,  122,  122,  122,  122,  122,  122,  122,  123,
+      123,  123,  123,  123,  123,  123,  123,  123,  122,  122,
+      122,  122,  122,  122,  122,  122,  122,  122,  122,  122,
+      122,  122,  122,  122,  122,  122,  122,  122,  122,  122,
+      122,  122,  122,  122,  122,  122,  122,  122,  122,  122,
+      122,  122,  122,  122,  122,  122,  122,  122,  122,  122,
+      122,  122,  122,  122,  122,  122,  122,  122,  122,  122,
+
+      122,  122,  122,  122,  122,  122,  122,  122,  122,  122,
+      122,  122,  122,  122,  122,  122,  122,  122
+    },
+
+    {
+       67,  122,  122,  122,  122,  122,  122,  122,  122,  122,
+       68,  122,  122,  122,  122,  122,  122,  122,  122,  122,
+      122,  122,  122,  122,  122,  122,  122,  122,  122,  122,
+      122,  122,  122,  122,  122,  122,  122,  122,  122,  122,
+      122,  122,  122,  122,  122,  122,  122,  122,  122,  123,
+      123,  123,  123,  123,  123,  123,  123,  123,  122,  122,
+      122,  122,  122,  122,  122,  122,  122,  122,  122,  122,
+      122,  122,  122,  122,  122,  122,  122,  122,  122,  122,
+
+      122,  122,  122,  122,  122,  122,  122,  122,  122,  122,
+      122,  122,  122,  122,  122,  122,  122,  122,  122,  122,
+      122,  122,  122,  122,  122,  122,  122,  122,  122,  122,
+      122,  122,  122,  122,  122,  122,  122,  122,  122,  122,
+      122,  122,  122,  122,  122,  122,  122,  122
+    },
+
+    {
+       67,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+       68,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  125,
+
+      125,  125,  125,  125,  125,  125,  125,  125,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124
+    },
+
+    {
+       67,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+       68,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  125,
+      125,  125,  125,  125,  125,  125,  125,  125,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+
+      124,  124,  124,  124,  124,  124,  124,  124
+    },
+
+    {
+       67,  126,  126,  126,  126,  126,  126,  126,  126,  126,
+       68,  126,  126,  126,  126,  126,  126,  126,  126,  126,
+      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
+      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
+      126,  126,  126,  126,  126,  126,  126,  126,  126,  127,
+      127,  127,  127,  127,  127,  127,  127,  127,  126,  126,
+      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
+      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
+      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
+
+      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
+      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
+      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
+      126,  126,  126,  126,  126,  126,  126,  126
+    },
+
+    {
+       67,  126,  126,  126,  126,  126,  126,  126,  126,  126,
+       68,  126,  126,  126,  126,  126,  126,  126,  126,  126,
+      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
+      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
+      126,  126,  126,  126,  126,  126,  126,  126,  126,  127,
+      127,  127,  127,  127,  127,  127,  127,  127,  126,  126,
+
+      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
+      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
+      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
+      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
+      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
+      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
+      126,  126,  126,  126,  126,  126,  126,  126
+    },
+
+    {
+       67,  128,  128,  128,  128,  128,  128,  128,  128,  128,
+       68,  128,  128,  128,  128,  128,  128,  128,  128,  128,
+      128,  128,  128,  128,  128,  128,  128,  128,  128,  128,
+
+      128,  128,  128,  128,  128,  128,  128,  128,  128,  128,
+      128,  128,  128,  128,  128,  128,  128,  128,  128,  129,
+      129,  129,  129,  129,  129,  129,  129,  129,  128,  128,
+      128,  128,  128,  128,  128,  128,  128,  128,  128,  128,
+      128,  128,  128,  128,  128,  128,  128,  128,  128,  128,
+      128,  128,  128,  128,  128,  128,  128,  128,  128,  128,
+      128,  128,  128,  128,  128,  128,  128,  128,  128,  128,
+      128,  128,  128,  128,  128,  128,  128,  128,  128,  128,
+      128,  128,  128,  128,  128,  128,  128,  128,  128,  128,
+      128,  128,  128,  128,  128,  128,  128,  128
+
+    },
+
+    {
+       67,  128,  128,  128,  128,  128,  128,  128,  128,  128,
+       68,  128,  128,  128,  128,  128,  128,  128,  128,  128,
+      128,  128,  128,  128,  128,  128,  128,  128,  128,  128,
+      128,  128,  128,  128,  128,  128,  128,  128,  128,  128,
+      128,  128,  128,  128,  128,  128,  128,  128,  128,  129,
+      129,  129,  129,  129,  129,  129,  129,  129,  128,  128,
+      128,  128,  128,  128,  128,  128,  128,  128,  128,  128,
+      128,  128,  128,  128,  128,  128,  128,  128,  128,  128,
+      128,  128,  128,  128,  128,  128,  128,  128,  128,  128,
+      128,  128,  128,  128,  128,  128,  128,  128,  128,  128,
+
+      128,  128,  128,  128,  128,  128,  128,  128,  128,  128,
+      128,  128,  128,  128,  128,  128,  128,  128,  128,  128,
+      128,  128,  128,  128,  128,  128,  128,  128
+    },
+
+    {
+       67,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+       68,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+      130,  131,  130,  130,  130,  130,  130,  130,  130,  130,
+
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130
+    },
+
+    {
+       67,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+       68,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+      130,  131,  130,  130,  130,  130,  130,  130,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130
+    },
+
+    {
+       67,  132,  132,  132,  132,  132,  132,  132,  132,  132,
+
+       68,  132,  132,  132,  132,  132,  132,  132,  132,  132,
+      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
+      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
+      132,  132,  132,  133,  132,  133,  132,  132,  134,  134,
+      134,  134,  134,  134,  134,  134,  134,  134,  132,  132,
+      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
+      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
+      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
+      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
+      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
+
+      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
+      132,  132,  132,  132,  132,  132,  132,  132
+    },
+
+    {
+       67,  132,  132,  132,  132,  132,  132,  132,  132,  132,
+       68,  132,  132,  132,  132,  132,  132,  132,  132,  132,
+      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
+      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
+      132,  132,  132,  133,  132,  133,  132,  132,  134,  134,
+      134,  134,  134,  134,  134,  134,  134,  134,  132,  132,
+      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
+      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
+
+      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
+      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
+      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
+      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
+      132,  132,  132,  132,  132,  132,  132,  132
+    },
+
+    {
+       67,  135,  135,  135,  135,  135,  135,  135,  135,  135,
+       68,  135,  135,  135,  135,  135,  135,  135,  135,  135,
+      135,  135,  135,  135,  135,  135,  135,  135,  135,  135,
+      135,  135,  135,  135,  135,  135,  135,  135,  135,  135,
+      135,  135,  135,  136,  135,  136,  137,  135,  138,  138,
+
+      138,  138,  138,  138,  138,  138,  138,  138,  135,  135,
+      135,  135,  135,  135,  135,  135,  135,  135,  135,  135,
+      135,  135,  135,  135,  135,  135,  135,  135,  135,  135,
+      135,  135,  135,  135,  135,  135,  135,  135,  135,  135,
+      135,  135,  135,  135,  135,  135,  135,  135,  135,  135,
+      135,  135,  135,  135,  135,  135,  135,  135,  135,  135,
+      135,  135,  135,  135,  135,  135,  135,  135,  135,  135,
+      135,  135,  135,  135,  135,  135,  135,  135
+    },
+
+    {
+       67,  135,  135,  135,  135,  135,  135,  135,  135,  135,
+       68,  135,  135,  135,  135,  135,  135,  135,  135,  135,
+
+      135,  135,  135,  135,  135,  135,  135,  135,  135,  135,
+      135,  135,  135,  135,  135,  135,  135,  135,  135,  135,
+      135,  135,  135,  136,  135,  136,  137,  135,  138,  138,
+      138,  138,  138,  138,  138,  138,  138,  138,  135,  135,
+      135,  135,  135,  135,  135,  135,  135,  135,  135,  135,
+      135,  135,  135,  135,  135,  135,  135,  135,  135,  135,
+      135,  135,  135,  135,  135,  135,  135,  135,  135,  135,
+      135,  135,  135,  135,  135,  135,  135,  135,  135,  135,
+      135,  135,  135,  135,  135,  135,  135,  135,  135,  135,
+      135,  135,  135,  135,  135,  135,  135,  135,  135,  135,
+
+      135,  135,  135,  135,  135,  135,  135,  135
+    },
+
+    {
+       67,  139,  139,  139,  139,  139,  139,  139,  139,  139,
+       68,  139,  139,  139,  139,  139,  139,  139,  139,  139,
+      139,  139,  139,  139,  139,  139,  139,  139,  139,  139,
+      139,  139,  139,  139,  139,  139,  139,  139,  139,  140,
+      139,  139,  139,  139,  139,  139,  139,  139,  139,  139,
+      139,  139,  139,  139,  139,  139,  139,  139,  139,  139,
+      139,  139,  139,  139,  139,  139,  139,  139,  139,  139,
+      139,  139,  139,  139,  139,  139,  139,  139,  139,  139,
+      139,  139,  139,  139,  139,  139,  139,  139,  139,  139,
+
+      139,  139,  139,  139,  139,  139,  139,  139,  139,  139,
+      139,  139,  139,  139,  139,  139,  139,  139,  139,  139,
+      139,  139,  139,  139,  139,  139,  139,  139,  139,  139,
+      139,  139,  139,  139,  139,  139,  139,  139
+    },
+
+    {
+       67,  139,  139,  139,  139,  139,  139,  139,  139,  139,
+       68,  139,  139,  139,  139,  139,  139,  139,  139,  139,
+      139,  139,  139,  139,  139,  139,  139,  139,  139,  139,
+      139,  139,  139,  139,  139,  139,  139,  139,  139,  140,
+      139,  139,  139,  139,  139,  139,  139,  139,  139,  139,
+      139,  139,  139,  139,  139,  139,  139,  139,  139,  139,
+
+      139,  139,  139,  139,  139,  139,  139,  139,  139,  139,
+      139,  139,  139,  139,  139,  139,  139,  139,  139,  139,
+      139,  139,  139,  139,  139,  139,  139,  139,  139,  139,
+      139,  139,  139,  139,  139,  139,  139,  139,  139,  139,
+      139,  139,  139,  139,  139,  139,  139,  139,  139,  139,
+      139,  139,  139,  139,  139,  139,  139,  139,  139,  139,
+      139,  139,  139,  139,  139,  139,  139,  139
+    },
+
+    {
+       67,  141,  141,  141,  141,  141,  141,  141,  141,  141,
+       68,  141,  141,  141,  141,  141,  141,  141,  141,  141,
+      141,  141,  141,  141,  141,  141,  141,  141,  141,  141,
+
+      141,  141,  142,  141,  141,  141,  141,  141,  141,  141,
+      141,  141,  141,  141,  141,  141,  141,  143,  141,  141,
+      141,  141,  141,  141,  141,  141,  141,  141,  141,  141,
+      141,  141,  141,  141,  141,  141,  141,  141,  141,  141,
+      141,  141,  141,  141,  141,  141,  141,  141,  141,  141,
+      141,  141,  141,  141,  141,  141,  141,  141,  141,  141,
+      141,  141,  141,  141,  141,  141,  141,  141,  141,  141,
+      141,  141,  141,  141,  141,  141,  141,  141,  141,  141,
+      141,  141,  141,  141,  141,  141,  141,  141,  141,  141,
+      141,  141,  141,  141,  141,  141,  141,  141
+
+    },
+
+    {
+       67,  141,  141,  141,  141,  141,  141,  141,  141,  141,
+       68,  141,  141,  141,  141,  141,  141,  141,  141,  141,
+      141,  141,  141,  141,  141,  141,  141,  141,  141,  141,
+      141,  141,  142,  141,  141,  141,  141,  141,  141,  141,
+      141,  141,  141,  141,  141,  141,  141,  143,  141,  141,
+      141,  141,  141,  141,  141,  141,  141,  141,  141,  141,
+      141,  141,  141,  141,  141,  141,  141,  141,  141,  141,
+      141,  141,  141,  141,  141,  141,  141,  141,  141,  141,
+      141,  141,  141,  141,  141,  141,  141,  141,  141,  141,
+      141,  141,  141,  141,  141,  141,  141,  141,  141,  141,
+
+      141,  141,  141,  141,  141,  141,  141,  141,  141,  141,
+      141,  141,  141,  141,  141,  141,  141,  141,  141,  141,
+      141,  141,  141,  141,  141,  141,  141,  141
+    },
+
+    {
+       67,  144,  144,  144,  144,  144,  144,  144,  144,  144,
+       68,  144,  144,  144,  144,  144,  144,  144,  144,  144,
+      144,  144,  144,  144,  144,  144,  144,  144,  144,  144,
+      144,  144,  144,  144,  144,  144,  144,  144,  144,  144,
+      144,  144,  144,  144,  144,  144,  144,  144,  144,  144,
+      144,  144,  144,  144,  144,  144,  144,  144,  144,  144,
+      144,  144,  144,  144,  144,  144,  144,  144,  144,  144,
+
+      144,  144,  144,  144,  144,  144,  144,  144,  144,  144,
+      144,  144,  144,  144,  144,  144,  144,  144,  144,  144,
+      144,  144,  144,  144,  144,  144,  144,  144,  144,  144,
+      144,  144,  144,  144,  144,  144,  144,  144,  144,  144,
+      144,  144,  144,  144,  144,  144,  144,  144,  144,  144,
+      144,  144,  144,  144,  144,  144,  144,  144
+    },
+
+    {
+       67,  144,  144,  144,  144,  144,  144,  144,  144,  144,
+       68,  144,  144,  144,  144,  144,  144,  144,  144,  144,
+      144,  144,  144,  144,  144,  144,  144,  144,  144,  144,
+      144,  144,  144,  144,  144,  144,  144,  144,  144,  144,
+
+      144,  144,  144,  144,  144,  144,  144,  144,  144,  144,
+      144,  144,  144,  144,  144,  144,  144,  144,  144,  144,
+      144,  144,  144,  144,  144,  144,  144,  144,  144,  144,
+      144,  144,  144,  144,  144,  144,  144,  144,  144,  144,
+      144,  144,  144,  144,  144,  144,  144,  144,  144,  144,
+      144,  144,  144,  144,  144,  144,  144,  144,  144,  144,
+      144,  144,  144,  144,  144,  144,  144,  144,  144,  144,
+      144,  144,  144,  144,  144,  144,  144,  144,  144,  144,
+      144,  144,  144,  144,  144,  144,  144,  144
+    },
+
+    {
+       67,  145,  145,  145,  145,  145,  145,  145,  145,  145,
+
+       68,  145,  145,  145,  145,  145,  145,  145,  145,  145,
+      145,  145,  145,  145,  145,  145,  145,  145,  145,  145,
+      145,  145,  145,  145,  145,  145,  145,  145,  145,  145,
+      145,  145,  145,  145,  145,  145,  145,  145,  145,  145,
+      145,  145,  145,  145,  145,  145,  145,  145,  145,  145,
+      145,  145,  145,  145,  145,  145,  145,  145,  145,  145,
+      145,  145,  145,  145,  145,  145,  145,  145,  145,  145,
+      145,  145,  145,  145,  145,  145,  145,  145,  145,  145,
+      145,  145,  145,  145,  145,  145,  145,  145,  145,  145,
+      145,  145,  145,  145,  145,  145,  145,  145,  145,  145,
+
+      145,  145,  145,  145,  145,  145,  145,  145,  145,  145,
+      145,  145,  145,  145,  145,  145,  145,  145
+    },
+
+    {
+       67,  145,  145,  145,  145,  145,  145,  145,  145,  145,
+       68,  145,  145,  145,  145,  145,  145,  145,  145,  145,
+      145,  145,  145,  145,  145,  145,  145,  145,  145,  145,
+      145,  145,  145,  145,  145,  145,  145,  145,  145,  145,
+      145,  145,  145,  145,  145,  145,  145,  145,  145,  145,
+      145,  145,  145,  145,  145,  145,  145,  145,  145,  145,
+      145,  145,  145,  145,  145,  145,  145,  145,  145,  145,
+      145,  145,  145,  145,  145,  145,  145,  145,  145,  145,
+
+      145,  145,  145,  145,  145,  145,  145,  145,  145,  145,
+      145,  145,  145,  145,  145,  145,  145,  145,  145,  145,
+      145,  145,  145,  145,  145,  145,  145,  145,  145,  145,
+      145,  145,  145,  145,  145,  145,  145,  145,  145,  145,
+      145,  145,  145,  145,  145,  145,  145,  145
+    },
+
+    {
+       67,  146,  146,  146,  146,  146,  146,  146,  146,  146,
+      147,  146,  146,  146,  146,  146,  146,  146,  146,  146,
+      146,  146,  146,  146,  146,  146,  146,  146,  146,  146,
+      146,  146,  146,  146,  146,  146,  146,  146,  146,  146,
+      146,  146,  146,  146,  146,  146,  146,  146,  146,  146,
+
+      146,  146,  146,  146,  146,  146,  146,  146,  146,  146,
+      146,  146,  146,  146,  146,  146,  146,  146,  146,  146,
+      146,  146,  146,  146,  146,  146,  146,  146,  146,  146,
+      146,  146,  146,  146,  146,  146,  146,  146,  146,  146,
+      146,  146,  146,  146,  146,  146,  146,  146,  146,  146,
+      146,  146,  146,  146,  146,  146,  146,  146,  146,  146,
+      146,  146,  146,  146,  146,  146,  146,  146,  146,  146,
+      146,  146,  146,  146,  146,  146,  146,  146
+    },
+
+    {
+       67,  146,  146,  146,  146,  146,  146,  146,  146,  146,
+      147,  146,  146,  146,  146,  146,  146,  146,  146,  146,
+
+      146,  146,  146,  146,  146,  146,  146,  146,  146,  146,
+      146,  146,  146,  146,  146,  146,  146,  146,  146,  146,
+      146,  146,  146,  146,  146,  146,  146,  146,  146,  146,
+      146,  146,  146,  146,  146,  146,  146,  146,  146,  146,
+      146,  146,  146,  146,  146,  146,  146,  146,  146,  146,
+      146,  146,  146,  146,  146,  146,  146,  146,  146,  146,
+      146,  146,  146,  146,  146,  146,  146,  146,  146,  146,
+      146,  146,  146,  146,  146,  146,  146,  146,  146,  146,
+      146,  146,  146,  146,  146,  146,  146,  146,  146,  146,
+      146,  146,  146,  146,  146,  146,  146,  146,  146,  146,
+
+      146,  146,  146,  146,  146,  146,  146,  146
+    },
+
+    {
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67
+    },
+
+    {
+       67,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+
+      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68
+    },
+
+    {
+       67,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
+      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
+      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
+
+      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
+      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
+      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
+      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
+      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
+      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
+      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
+      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
+      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
+      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69
+
+    },
+
+    {
+       67,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
+      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
+      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
+      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
+      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  148,  148,
+      148,  148,  148,  148,  148,  148,  148,  148,  -70,  -70,
+      -70,  -70,  -70,  -70,  -70,  -70,  -70,  149,  -70,  -70,
+      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
+      150,  -70,  -70,  151,  -70,  -70,  152,  -70,  -70,  -70,
+      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
+
+      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
+      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
+      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70
+    },
+
+    {
+       67,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
+      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
+      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
+      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
+      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
+      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
+      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  153,  -71,
+
+      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  154,  -71,
+      -71,  -71,  155,  156,  157,  158,  -71,  -71,  -71,  -71,
+      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
+      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
+      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
+      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71
+    },
+
+    {
+       67,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
+      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
+      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
+      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
+
+      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
+      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
+      -72,  -72,  -72,  -72,  -72,  159,  -72,  -72,  -72,  -72,
+      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  160,
+      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
+      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
+      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
+      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
+      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72
+    },
+
+    {
+       67,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
+
+      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
+      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
+      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
+      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
+      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
+      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
+      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  161,  -73,
+      162,  163,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
+      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
+      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
+
+      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
+      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73
+    },
+
+    {
+       67,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
+      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
+      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
+      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
+      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
+      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
+      -74,  -74,  -74,  -74,  -74,  164,  -74,  -74,  -74,  -74,
+      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  165,
+
+      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
+      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
+      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
+      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
+      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74
+    },
+
+    {
+       67,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
+      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
+      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
+      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
+      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
+
+      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
+      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
+      -75,  -75,  -75,  -75,  166,  -75,  -75,  -75,  -75,  -75,
+      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
+      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
+      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
+      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
+      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75
+    },
+
+    {
+       67,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
+      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
+
+      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
+      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
+      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
+      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
+      -76,  -76,  -76,  -76,  -76,  -76,  167,  -76,  -76,  -76,
+      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
+      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
+      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
+      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
+      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
+
+      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76
+    },
+
+    {
+       67,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
+      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
+      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
+      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
+      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
+      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
+      -77,  -77,  -77,  -77,  -77,  -77,  -77,  168,  -77,  -77,
+      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
+      -77,  -77,  169,  170,  -77,  -77,  171,  -77,  -77,  -77,
+
+      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
+      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
+      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
+      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77
+    },
+
+    {
+       67,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
+      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
+      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
+      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
+      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
+      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
+
+      -78,  -78,  -78,  -78,  -78,  172,  -78,  -78,  -78,  173,
+      174,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
+      -78,  -78,  -78,  -78,  -78,  -78,  -78,  175,  -78,  -78,
+      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
+      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
+      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
+      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78
+    },
+
+    {
+       67,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
+      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
+      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
+
+      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
+      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
+      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
+      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
+      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  176,
+      177,  -79,  -79,  178,  -79,  -79,  -79,  -79,  -79,  -79,
+      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
+      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
+      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
+      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79
+
+    },
+
+    {
+       67,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
+      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
+      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
+      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
+      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
+      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
+      -80,  -80,  -80,  -80,  -80,  -80,  -80,  179,  -80,  -80,
+      180,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
+      181,  -80,  -80,  182,  -80,  -80,  183,  184,  -80,  -80,
+      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
+
+      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
+      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
+      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80
+    },
+
+    {
+       67,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
+      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
+      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
+      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
+      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
+      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
+      -81,  -81,  -81,  -81,  -81,  185,  -81,  -81,  -81,  186,
+
+      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
+      -81,  -81,  -81,  187,  -81,  -81,  -81,  -81,  -81,  -81,
+      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
+      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
+      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
+      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81
+    },
+
+    {
+       67,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
+      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
+      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
+      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
+
+      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
+      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
+      -82,  -82,  -82,  -82,  -82,  -82,  -82,  188,  -82,  -82,
+      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
+      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
+      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
+      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
+      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
+      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82
+    },
+
+    {
+       67,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
+
+      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
+      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
+      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
+      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
+      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
+      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
+      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
+      -83,  -83,  -83,  189,  -83,  -83,  -83,  -83,  -83,  -83,
+      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
+      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
+
+      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
+      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83
+    },
+
+    {
+       67,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
+      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
+      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
+      -84,  -84,  190,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
+      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  191,  191,
+      191,  191,  191,  191,  191,  191,  191,  191,  -84,  -84,
+      -84,  -84,  -84,  -84,  -84,  190,  190,  190,  190,  190,
+      190,  190,  190,  190,  190,  190,  190,  190,  190,  190,
+
+      190,  190,  190,  190,  190,  190,  190,  190,  190,  190,
+      190,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
+      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
+      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
+      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84
+    },
+
+    {
+       67,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
+      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
+      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
+      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
+      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
+
+      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
+      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
+      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
+      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
+      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
+      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
+      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
+      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85
+    },
+
+    {
+       67,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
+      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
+
+      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
+      -86,  -86,  192,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
+      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  193,  193,
+      193,  193,  193,  193,  193,  193,  193,  193,  -86,  -86,
+      -86,  -86,  -86,  -86,  -86,  192,  192,  192,  192,  192,
+      192,  192,  192,  192,  192,  192,  192,  192,  192,  192,
+      192,  192,  192,  192,  192,  192,  192,  192,  192,  192,
+      192,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
+      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
+      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
+
+      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86
+    },
+
+    {
+       67,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+
+      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87
+    },
+
+    {
+       67,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
+      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
+      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
+      -88,  -88,  194,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
+      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  -88,  -88,
+
+      -88,  -88,  -88,  -88,  -88,  196,  196,  196,  196,  196,
+      196,  196,  196,  196,  196,  196,  196,  196,  196,  196,
+      196,  196,  196,  196,  196,  196,  196,  196,  196,  196,
+      196,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
+      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
+      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
+      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88
+    },
+
+    {
+       67,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
+      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
+      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
+
+      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
+      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
+      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
+      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
+      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
+      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
+      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
+      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
+      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
+      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89
+
+    },
+
+    {
+       67,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
+      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
+      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
+      -90,  -90,  197,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
+      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  198,  198,
+      198,  198,  198,  198,  198,  198,  198,  198,  -90,  -90,
+      -90,  -90,  -90,  -90,  -90,  197,  197,  197,  197,  197,
+      197,  197,  197,  197,  197,  197,  197,  197,  197,  197,
+      197,  197,  197,  197,  197,  197,  197,  197,  197,  197,
+      197,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
+
+      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
+      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
+      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90
+    },
+
+    {
+       67,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+
+      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91
+    },
+
+    {
+       67,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
+      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
+      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
+      -92,  -92,  199,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
+
+      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  200,  200,
+      200,  200,  200,  200,  200,  200,  200,  200,  -92,  -92,
+      -92,  -92,  -92,  -92,  -92,  201,  201,  201,  201,  201,
+      201,  201,  201,  201,  201,  201,  201,  201,  201,  201,
+      201,  201,  201,  201,  201,  201,  201,  201,  201,  201,
+      201,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
+      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
+      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
+      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92
+    },
+
+    {
+       67,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+
+      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+
+      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93
+    },
+
+    {
+       67,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
+      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
+      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
+      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
+      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  202,  202,
+      202,  202,  202,  202,  202,  202,  202,  202,  -94,  -94,
+      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
+      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
+
+      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
+      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
+      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
+      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
+      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94
+    },
+
+    {
+       67,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
+      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
+      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
+      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
+      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  203,  203,
+
+      203,  203,  203,  203,  203,  203,  203,  203,  -95,  -95,
+      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
+      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
+      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
+      -95,  -95,  -95,  -95,  -95,  204,  -95,  -95,  -95,  -95,
+      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
+      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
+      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95
+    },
+
+    {
+       67,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
+      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
+
+      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
+      -96,  -96,  205,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
+      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  206,  206,
+      206,  206,  206,  206,  206,  206,  206,  206,  -96,  -96,
+      -96,  -96,  -96,  -96,  -96,  205,  205,  205,  205,  205,
+      205,  205,  205,  205,  205,  205,  205,  205,  205,  205,
+      205,  205,  205,  205,  205,  205,  205,  205,  205,  205,
+      205,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
+      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
+      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
+
+      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96
+    },
+
+    {
+       67,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
+      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
+      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
+      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
+      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
+      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
+      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
+      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
+      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
+
+      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
+      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
+      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
+      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97
+    },
+
+    {
+       67,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
+      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
+      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
+      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
+      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  207,  207,
+      207,  207,  207,  207,  207,  207,  207,  207,  -98,  -98,
+
+      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
+      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
+      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
+      -98,  -98,  -98,  -98,  -98,  208,  -98,  -98,  -98,  -98,
+      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
+      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
+      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98
+    },
+
+    {
+       67,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
+      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
+      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
+
+      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
+      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
+      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
+      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
+      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
+      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
+      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
+      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
+      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
+      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99
+
+    },
+
+    {
+       67, -100, -100, -100, -100, -100, -100, -100, -100, -100,
+     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
+     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
+     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
+     -100, -100, -100, -100, -100, -100, -100, -100,  209,  209,
+      209,  209,  209,  209,  209,  209,  209,  209, -100, -100,
+     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
+     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
+     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
+     -100, -100, -100, -100, -100,  210, -100, -100, -100, -100,
+
+     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
+     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
+     -100, -100, -100, -100, -100, -100, -100, -100
+    },
+
+    {
+       67, -101, -101, -101, -101, -101, -101, -101, -101, -101,
+     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
+     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
+     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
+     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
+     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
+     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
+
+     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
+     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
+     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
+     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
+     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
+     -101, -101, -101, -101, -101, -101, -101, -101
+    },
+
+    {
+       67, -102, -102, -102, -102, -102, -102, -102, -102, -102,
+     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
+     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
+     -102, -102,  211, -102, -102, -102, -102, -102, -102, -102,
+
+     -102, -102, -102, -102, -102, -102, -102, -102,  212,  212,
+      212,  212,  212,  212,  212,  212,  212,  212, -102, -102,
+     -102, -102, -102, -102, -102,  213,  213,  213,  213,  213,
+      213,  213,  213,  213,  213,  213,  213,  213,  213,  213,
+      213,  213,  213,  213,  213,  213,  213,  213,  213,  213,
+      213, -102, -102, -102, -102, -102, -102, -102, -102, -102,
+     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
+     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
+     -102, -102, -102, -102, -102, -102, -102, -102
+    },
+
+    {
+       67, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+
+     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+
+     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+     -103, -103, -103, -103, -103, -103, -103, -103
+    },
+
+    {
+       67, -104, -104, -104, -104, -104, -104, -104, -104, -104,
+     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
+     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
+     -104, -104,  214, -104, -104, -104, -104, -104, -104, -104,
+     -104, -104, -104, -104, -104, -104, -104, -104,  215,  215,
+      215,  215,  215,  215,  215,  215,  215,  215, -104, -104,
+     -104, -104, -104, -104, -104,  216,  216,  216,  216,  216,
+      216,  216,  216,  216,  216,  216,  216,  216,  216,  216,
+
+      216,  216,  216,  216,  216,  216,  216,  216,  216,  216,
+      216, -104, -104, -104, -104, -104, -104, -104, -104, -104,
+     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
+     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
+     -104, -104, -104, -104, -104, -104, -104, -104
+    },
+
+    {
+       67, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+
+     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+     -105, -105, -105, -105, -105, -105, -105, -105
+    },
+
+    {
+       67, -106, -106, -106, -106, -106, -106, -106, -106, -106,
+     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
+
+     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
+     -106, -106,  217, -106, -106, -106, -106, -106, -106, -106,
+     -106, -106, -106, -106, -106, -106, -106, -106,  218,  218,
+      218,  218,  218,  218,  218,  218,  218,  218, -106, -106,
+     -106, -106, -106, -106, -106,  219,  219,  219,  219,  219,
+      219,  219,  219,  219,  219,  219,  219,  219,  219,  219,
+      219,  219,  219,  219,  219,  219,  219,  219,  219,  219,
+      219, -106, -106, -106, -106, -106, -106, -106, -106, -106,
+     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
+     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
+
+     -106, -106, -106, -106, -106, -106, -106, -106
+    },
+
+    {
+       67, -107, -107, -107, -107, -107, -107, -107, -107, -107,
+     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
+     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
+     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
+     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
+     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
+     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
+     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
+     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
+
+     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
+     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
+     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
+     -107, -107, -107, -107, -107, -107, -107, -107
+    },
+
+    {
+       67, -108, -108, -108, -108, -108, -108, -108, -108, -108,
+     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
+     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
+     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
+     -108, -108, -108, -108, -108, -108, -108, -108,  220,  220,
+      220,  220,  220,  220,  220,  220,  220,  220, -108, -108,
+
+     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
+     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
+     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
+     -108, -108, -108, -108, -108,  221, -108, -108, -108, -108,
+     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
+     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
+     -108, -108, -108, -108, -108, -108, -108, -108
+    },
+
+    {
+       67, -109, -109, -109, -109, -109, -109, -109, -109, -109,
+     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
+     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
+
+     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
+     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
+     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
+     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
+     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
+     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
+     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
+     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
+     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
+     -109, -109, -109, -109, -109, -109, -109, -109
+
+    },
+
+    {
+       67, -110, -110, -110, -110, -110, -110, -110, -110, -110,
+     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
+     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
+     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
+     -110, -110, -110, -110, -110, -110, -110, -110,  222,  222,
+      222,  222,  222,  222,  222,  222,  222,  222, -110, -110,
+     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
+     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
+     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
+     -110, -110, -110, -110, -110,  223, -110, -110, -110, -110,
+
+     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
+     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
+     -110, -110, -110, -110, -110, -110, -110, -110
+    },
+
+    {
+       67, -111, -111, -111, -111, -111, -111, -111, -111, -111,
+     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
+     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
+     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
+     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
+     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
+     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
+
+     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
+     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
+     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
+     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
+     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
+     -111, -111, -111, -111, -111, -111, -111, -111
+    },
+
+    {
+       67, -112, -112, -112, -112, -112, -112, -112, -112, -112,
+     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
+     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
+     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
+
+     -112, -112, -112, -112, -112, -112, -112, -112,  224,  224,
+      224,  224,  224,  224,  224,  224,  224,  224, -112, -112,
+     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
+     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
+     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
+     -112, -112, -112, -112, -112,  225, -112, -112, -112, -112,
+     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
+     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
+     -112, -112, -112, -112, -112, -112, -112, -112
+    },
+
+    {
+       67, -113, -113, -113, -113, -113, -113, -113, -113, -113,
+
+     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
+     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
+     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
+     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
+     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
+     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
+     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
+     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
+     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
+     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
+
+     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
+     -113, -113, -113, -113, -113, -113, -113, -113
+    },
+
+    {
+       67, -114, -114, -114, -114, -114, -114, -114, -114, -114,
+     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
+     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
+     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
+     -114, -114, -114, -114, -114, -114, -114, -114,  226,  226,
+      226,  226,  226,  226,  226,  226,  226,  226, -114, -114,
+     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
+     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
+
+     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
+     -114, -114, -114, -114, -114,  227, -114, -114, -114, -114,
+     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
+     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
+     -114, -114, -114, -114, -114, -114, -114, -114
+    },
+
+    {
+       67, -115, -115, -115, -115, -115, -115, -115, -115, -115,
+     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
+     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
+     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
+     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
+
+     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
+     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
+     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
+     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
+     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
+     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
+     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
+     -115, -115, -115, -115, -115, -115, -115, -115
+    },
+
+    {
+       67, -116, -116, -116, -116, -116, -116, -116, -116, -116,
+     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
+
+     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
+     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
+     -116, -116, -116, -116, -116, -116, -116, -116,  228,  228,
+      228,  228,  228,  228,  228,  228,  228,  228, -116, -116,
+     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
+     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
+     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
+     -116, -116, -116, -116, -116,  229, -116, -116, -116, -116,
+     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
+     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
+
+     -116, -116, -116, -116, -116, -116, -116, -116
+    },
+
+    {
+       67, -117, -117, -117, -117, -117, -117, -117, -117, -117,
+     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
+     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
+     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
+     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
+     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
+     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
+     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
+     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
+
+     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
+     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
+     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
+     -117, -117, -117, -117, -117, -117, -117, -117
+    },
+
+    {
+       67, -118, -118, -118, -118, -118, -118, -118, -118, -118,
+     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
+     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
+     -118, -118,  230, -118, -118, -118, -118, -118, -118, -118,
+     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
+     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
+
+     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
+     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
+     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
+     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
+     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
+     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
+     -118, -118, -118, -118, -118, -118, -118, -118
+    },
+
+    {
+       67, -119, -119, -119, -119, -119, -119, -119, -119, -119,
+     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
+     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
+
+     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
+     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
+     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
+     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
+     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
+     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
+     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
+     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
+     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
+     -119, -119, -119, -119, -119, -119, -119, -119
+
+    },
+
+    {
+       67, -120, -120, -120, -120, -120, -120, -120, -120, -120,
+     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
+     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
+     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
+     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
+     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
+     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
+     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
+     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
+     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
+
+     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
+     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
+     -120, -120, -120, -120, -120, -120, -120, -120
+    },
+
+    {
+       67, -121, -121, -121, -121, -121, -121, -121, -121, -121,
+     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
+     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
+     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
+     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
+     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
+     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
+
+     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
+     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
+     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
+     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
+     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
+     -121, -121, -121, -121, -121, -121, -121, -121
+    },
+
+    {
+       67, -122, -122, -122, -122, -122, -122, -122, -122, -122,
+     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
+     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
+     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
+
+     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
+     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
+     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
+     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
+     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
+     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
+     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
+     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
+     -122, -122, -122, -122, -122, -122, -122, -122
+    },
+
+    {
+       67, -123, -123, -123, -123, -123, -123, -123, -123, -123,
+
+     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
+     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
+     -123, -123,  231, -123, -123, -123, -123, -123, -123, -123,
+     -123, -123, -123, -123, -123, -123, -123, -123,  232,  232,
+      232,  232,  232,  232,  232,  232,  232,  232, -123, -123,
+     -123, -123, -123, -123, -123,  231,  231,  231,  231,  231,
+      231,  231,  231,  231,  231,  231,  231,  231,  231,  231,
+      231,  231,  231,  231,  231,  231,  231,  231,  231,  231,
+      231, -123, -123, -123, -123, -123, -123, -123, -123, -123,
+     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
+
+     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
+     -123, -123, -123, -123, -123, -123, -123, -123
+    },
+
+    {
+       67, -124, -124, -124, -124, -124, -124, -124, -124, -124,
+     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
+     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
+     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
+     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
+     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
+     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
+     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
+
+     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
+     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
+     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
+     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
+     -124, -124, -124, -124, -124, -124, -124, -124
+    },
+
+    {
+       67, -125, -125, -125, -125, -125, -125, -125, -125, -125,
+     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
+     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
+     -125, -125,  233, -125, -125, -125, -125, -125, -125, -125,
+     -125, -125, -125, -125, -125, -125, -125, -125,  234,  234,
+
+      234,  234,  234,  234,  234,  234,  234,  234, -125, -125,
+     -125, -125, -125, -125, -125,  233,  233,  233,  233,  233,
+      233,  233,  233,  233,  233,  233,  233,  233,  233,  233,
+      233,  233,  233,  233,  233,  233,  233,  233,  233,  233,
+      233, -125, -125, -125, -125, -125, -125, -125, -125, -125,
+     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
+     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
+     -125, -125, -125, -125, -125, -125, -125, -125
+    },
+
+    {
+       67, -126, -126, -126, -126, -126, -126, -126, -126, -126,
+     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
+
+     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
+     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
+     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
+     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
+     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
+     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
+     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
+     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
+     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
+     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
+
+     -126, -126, -126, -126, -126, -126, -126, -126
+    },
+
+    {
+       67, -127, -127, -127, -127, -127, -127, -127, -127, -127,
+     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
+     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
+     -127, -127,  235, -127, -127, -127, -127, -127, -127, -127,
+     -127, -127, -127, -127, -127, -127, -127, -127,  236,  236,
+      236,  236,  236,  236,  236,  236,  236,  236, -127, -127,
+     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
+     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
+     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
+
+     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
+     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
+     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
+     -127, -127, -127, -127, -127, -127, -127, -127
+    },
+
+    {
+       67, -128, -128, -128, -128, -128, -128, -128, -128, -128,
+     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
+     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
+     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
+     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
+     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
+
+     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
+     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
+     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
+     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
+     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
+     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
+     -128, -128, -128, -128, -128, -128, -128, -128
+    },
+
+    {
+       67, -129, -129, -129, -129, -129, -129, -129, -129, -129,
+     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
+     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
+
+     -129, -129,  237, -129, -129, -129, -129, -129, -129, -129,
+     -129, -129, -129, -129, -129, -129, -129, -129,  238,  238,
+      238,  238,  238,  238,  238,  238,  238,  238, -129, -129,
+     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
+     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
+     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
+     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
+     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
+     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
+     -129, -129, -129, -129, -129, -129, -129, -129
+
+    },
+
+    {
+       67, -130, -130, -130, -130, -130, -130, -130, -130, -130,
+     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
+     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
+     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
+     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
+     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
+     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
+     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
+     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
+     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
+
+     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
+     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
+     -130, -130, -130, -130, -130, -130, -130, -130
+    },
+
+    {
+       67, -131, -131, -131, -131, -131, -131, -131, -131, -131,
+     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
+     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
+     -131, -131,  239, -131, -131, -131, -131, -131, -131, -131,
+     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
+     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
+     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
+
+     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
+     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
+     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
+     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
+     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
+     -131, -131, -131, -131, -131, -131, -131, -131
+    },
+
+    {
+       67, -132, -132, -132, -132, -132, -132, -132, -132, -132,
+     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
+     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
+     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
+
+     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
+     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
+     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
+     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
+     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
+     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
+     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
+     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
+     -132, -132, -132, -132, -132, -132, -132, -132
+    },
+
+    {
+       67, -133, -133, -133, -133, -133, -133, -133, -133, -133,
+
+     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
+     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
+     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
+     -133, -133, -133, -133, -133, -133, -133, -133,  240,  240,
+      240,  240,  240,  240,  240,  240,  240,  240, -133, -133,
+     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
+     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
+     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
+     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
+     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
+
+     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
+     -133, -133, -133, -133, -133, -133, -133, -133
+    },
+
+    {
+       67, -134, -134, -134, -134, -134, -134, -134, -134, -134,
+     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
+     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
+     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
+     -134, -134, -134, -134, -134, -134, -134, -134,  240,  240,
+      240,  240,  240,  240,  240,  240,  240,  240, -134, -134,
+     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
+     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
+
+     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
+     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
+     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
+     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
+     -134, -134, -134, -134, -134, -134, -134, -134
+    },
+
+    {
+       67, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+
+     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+     -135, -135, -135, -135, -135, -135, -135, -135
+    },
+
+    {
+       67, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+
+     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+     -136, -136, -136, -136, -136, -136,  241, -136,  242,  242,
+      242,  242,  242,  242,  242,  242,  242,  242, -136, -136,
+     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+
+     -136, -136, -136, -136, -136, -136, -136, -136
+    },
+
+    {
+       67, -137, -137, -137, -137, -137, -137, -137, -137, -137,
+     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
+     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
+     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
+     -137, -137, -137, -137, -137, -137, -137, -137,  243,  243,
+      243,  243,  243,  243,  243,  243,  243,  243, -137, -137,
+     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
+     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
+     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
+
+     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
+     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
+     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
+     -137, -137, -137, -137, -137, -137, -137, -137
+    },
+
+    {
+       67, -138, -138, -138, -138, -138, -138, -138, -138, -138,
+     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
+     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
+     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
+     -138, -138, -138, -138, -138, -138,  244, -138,  245,  245,
+      245,  245,  245,  245,  245,  245,  245,  245, -138, -138,
+
+     -138, -138, -138, -138, -138, -138, -138, -138, -138,  246,
+     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
+     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
+     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
+     -138,  246, -138, -138, -138, -138, -138, -138, -138, -138,
+     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
+     -138, -138, -138, -138, -138, -138, -138, -138
+    },
+
+    {
+       67, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+
+     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+     -139, -139, -139, -139, -139, -139, -139, -139
+
+    },
+
+    {
+       67,  247,  247,  247,  247,  247,  247,  247,  247,  247,
+      247,  247,  247,  247,  247,  247,  247,  247,  247,  247,
+      247,  247,  247,  247,  247,  247,  247,  247,  247,  247,
+      247,  247,  247,  247,  247,  247,  247,  247,  247,  248,
+      247,  247,  247,  247,  247,  247,  247,  247,  247,  247,
+      247,  247,  247,  247,  247,  247,  247,  247,  247,  247,
+      247,  247,  247,  247,  247,  247,  247,  247,  247,  247,
+      247,  247,  247,  247,  247,  247,  247,  247,  247,  247,
+      247,  247,  247,  247,  247,  247,  247,  247,  247,  247,
+      247,  247,  247,  247,  247,  247,  247,  247,  247,  247,
+
+      247,  247,  247,  247,  247,  247,  247,  247,  247,  247,
+      247,  247,  247,  247,  247,  247,  247,  247,  247,  247,
+      247,  247,  247,  247,  247,  247,  247,  247
+    },
+
+    {
+       67, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+
+     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+     -141, -141, -141, -141, -141, -141, -141, -141
+    },
+
+    {
+       67, -142, -142, -142, -142, -142, -142, -142, -142, -142,
+     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
+     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
+     -142, -142,  249, -142, -142, -142, -142, -142, -142, -142,
+
+     -142, -142, -142, -142, -142, -142, -142,  250, -142, -142,
+     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
+     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
+     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
+     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
+     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
+     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
+     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
+     -142, -142, -142, -142, -142, -142, -142, -142
+    },
+
+    {
+       67,  251,  251,  251,  251,  251,  251,  251,  251,  251,
+
+     -143,  251,  251,  251,  251,  251,  251,  251,  251,  251,
+      251,  251,  251,  251,  251,  251,  251,  251,  251,  251,
+      251,  251,  251,  251,  251,  251,  251,  251,  251,  251,
+      251,  251,  251,  251,  251,  251,  251,  251,  251,  251,
+      251,  251,  251,  251,  251,  251,  251,  251,  251,  251,
+      251,  251,  251,  251,  251,  251,  251,  251,  251,  251,
+      251,  251,  251,  251,  251,  251,  251,  251,  251,  251,
+      251,  251,  251,  251,  251,  251,  251,  251,  251,  251,
+      251,  251,  251,  251,  251,  251,  251,  251,  251,  251,
+      251,  251,  251,  251,  251,  251,  251,  251,  251,  251,
+
+      251,  251,  251,  251,  251,  251,  251,  251,  251,  251,
+      251,  251,  251,  251,  251,  251,  251,  251
+    },
+
+    {
+       67,  252,  252,  252,  252,  252,  252,  252,  252,  252,
+     -144,  252,  252,  252,  252,  252,  252,  252,  252,  252,
+      252,  252,  252,  252,  252,  252,  252,  252,  252,  252,
+      252,  252,  252,  252,  252,  252,  252,  252,  252,  252,
+      252,  252,  252,  252,  252,  252,  252,  252,  252,  252,
+      252,  252,  252,  252,  252,  252,  252,  252,  252,  252,
+      252,  252,  252,  252,  252,  252,  252,  252,  252,  252,
+      252,  252,  252,  252,  252,  252,  252,  252,  252,  252,
+
+      252,  252,  252,  252,  252,  252,  252,  252,  252,  252,
+      252,  252,  252,  252,  252,  252,  252,  252,  252,  252,
+      252,  252,  252,  252,  252,  252,  252,  252,  252,  252,
+      252,  252,  252,  252,  252,  252,  252,  252,  252,  252,
+      252,  252,  252,  252,  252,  252,  252,  252
+    },
+
+    {
+       67,  253,  253,  253,  253,  253,  253,  253,  253,  253,
+     -145,  253,  253,  253,  253,  253,  253,  253,  253,  253,
+      253,  253,  253,  253,  253,  253,  253,  253,  253,  253,
+      253,  253,  253,  253,  253,  253,  253,  253,  253,  253,
+      253,  253,  253,  253,  253,  253,  253,  253,  253,  253,
+
+      253,  253,  253,  253,  253,  253,  253,  253,  253,  253,
+      253,  253,  253,  253,  253,  253,  253,  253,  253,  253,
+      253,  253,  253,  253,  253,  253,  253,  253,  253,  253,
+      253,  253,  253,  253,  253,  253,  253,  253,  253,  253,
+      253,  253,  253,  253,  253,  253,  253,  253,  253,  253,
+      253,  253,  253,  253,  253,  253,  253,  253,  253,  253,
+      253,  253,  253,  253,  253,  253,  253,  253,  253,  253,
+      253,  253,  253,  253,  253,  253,  253,  253
+    },
+
+    {
+       67,  254,  254,  254,  254,  254,  254,  254,  254,  254,
+      255,  254,  254,  254,  254,  254,  254,  254,  254,  254,
+
+      254,  254,  254,  254,  254,  254,  254,  254,  254,  254,
+      254,  254,  254,  254,  254,  254,  254,  254,  254,  254,
+      254,  254,  254,  254,  254,  254,  254,  254,  254,  254,
+      254,  254,  254,  254,  254,  254,  254,  254,  254,  254,
+      254,  254,  254,  254,  254,  254,  254,  254,  254,  254,
+      254,  254,  254,  254,  254,  254,  254,  254,  254,  254,
+      254,  254,  254,  254,  254,  254,  254,  254,  254,  254,
+      254,  254,  254,  254,  254,  254,  254,  254,  254,  254,
+      254,  254,  254,  254,  254,  254,  254,  254,  254,  254,
+      254,  254,  254,  254,  254,  254,  254,  254,  254,  254,
+
+      254,  254,  254,  254,  254,  254,  254,  254
+    },
+
+    {
+       67, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+
+     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+     -147, -147, -147, -147, -147, -147, -147, -147
+    },
+
+    {
+       67, -148, -148, -148, -148, -148, -148, -148, -148, -148,
+     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
+     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
+     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
+     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
+     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
+
+     -148, -148, -148, -148, -148, -148, -148,  256, -148, -148,
+     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
+      257, -148, -148, -148, -148, -148, -148, -148, -148, -148,
+     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
+     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
+     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
+     -148, -148, -148, -148, -148, -148, -148, -148
+    },
+
+    {
+       67, -149, -149, -149, -149, -149, -149, -149, -149, -149,
+     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
+     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
+
+     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
+     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
+     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
+     -149, -149, -149, -149, -149, -149, -149, -149,  258, -149,
+     -149, -149, -149, -149, -149, -149, -149, -149,  259, -149,
+     -149, -149,  260,  261,  262,  263, -149, -149, -149, -149,
+     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
+     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
+     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
+     -149, -149, -149, -149, -149, -149, -149, -149
+
+    },
+
+    {
+       67, -150, -150, -150, -150, -150, -150, -150, -150, -150,
+     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
+     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
+     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
+     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
+     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
+     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
+     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
+     -150, -150, -150,  264, -150, -150,  265, -150, -150, -150,
+     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
+
+     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
+     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
+     -150, -150, -150, -150, -150, -150, -150, -150
+    },
+
+    {
+       67, -151, -151, -151, -151, -151, -151, -151, -151, -151,
+     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
+     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
+     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
+     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
+     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
+     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
+
+     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
+     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
+     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
+     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
+     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
+     -151, -151, -151, -151, -151, -151, -151, -151
+    },
+
+    {
+       67, -152, -152, -152, -152, -152, -152, -152, -152, -152,
+     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
+     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
+     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
+
+     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
+     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
+     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
+     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
+     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
+     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
+     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
+     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
+     -152, -152, -152, -152, -152, -152, -152, -152
+    },
+
+    {
+       67, -153, -153, -153, -153, -153, -153, -153, -153, -153,
+
+     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
+     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
+     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
+     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
+     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
+     -153, -153, -153, -153, -153, -153, -153, -153, -153,  266,
+     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
+     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
+     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
+     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
+
+     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
+     -153, -153, -153, -153, -153, -153, -153, -153
+    },
+
+    {
+       67, -154, -154, -154, -154, -154, -154, -154, -154, -154,
+     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
+     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
+     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
+     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
+     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
+     -154, -154, -154, -154, -154,  267, -154, -154, -154, -154,
+     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
+
+     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
+     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
+     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
+     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
+     -154, -154, -154, -154, -154, -154, -154, -154
+    },
+
+    {
+       67, -155, -155, -155, -155, -155, -155, -155, -155, -155,
+     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
+     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
+     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
+     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
+
+     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
+     -155, -155, -155, -155, -155, -155, -155, -155,  268, -155,
+     -155, -155, -155, -155, -155, -155, -155, -155, -155,  269,
+      270, -155, -155, -155, -155, -155,  271, -155, -155, -155,
+     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
+     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
+     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
+     -155, -155, -155, -155, -155, -155, -155, -155
+    },
+
+    {
+       67, -156, -156, -156, -156, -156, -156, -156, -156, -156,
+     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
+
+     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
+     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
+     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
+     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
+     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
+     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
+     -156, -156, -156, -156, -156, -156, -156, -156, -156,  272,
+     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
+     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
+     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
+
+     -156, -156, -156, -156, -156, -156, -156, -156
+    },
+
+    {
+       67, -157, -157, -157, -157, -157, -157, -157, -157, -157,
+     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
+     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
+     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
+     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
+     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
+     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
+     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
+     -157, -157, -157, -157, -157, -157, -157, -157, -157,  273,
+
+     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
+     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
+     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
+     -157, -157, -157, -157, -157, -157, -157, -157
+    },
+
+    {
+       67, -158, -158, -158, -158, -158, -158, -158, -158, -158,
+     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
+     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
+     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
+     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
+     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
+
+     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
+     -158, -158, -158, -158, -158, -158, -158, -158,  274, -158,
+     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
+     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
+     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
+     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
+     -158, -158, -158, -158, -158, -158, -158, -158
+    },
+
+    {
+       67, -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, -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,  275, -159,  276, -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
+
+    },
+
+    {
+       67, -160, -160, -160, -160, -160, -160, -160, -160, -160,
+     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
+     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
+     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
+     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
+     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
+     -160, -160, -160, -160, -160, -160,  277, -160, -160, -160,
+     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
+     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
+     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
+
+     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
+     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
+     -160, -160, -160, -160, -160, -160, -160, -160
+    },
+
+    {
+       67, -161, -161, -161, -161, -161, -161, -161, -161, -161,
+     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
+     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
+     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
+     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
+     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
+     -161, -161, -161, -161, -161, -161, -161, -161,  278, -161,
+
+     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
+     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
+     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
+     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
+     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
+     -161, -161, -161, -161, -161, -161, -161, -161
+    },
+
+    {
+       67, -162, -162, -162, -162, -162, -162, -162, -162, -162,
+     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
+     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
+     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
+
+     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
+     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
+     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
+     -162, -162, -162, -162, -162, -162, -162, -162, -162,  279,
+     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
+     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
+     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
+     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
+     -162, -162, -162, -162, -162, -162, -162, -162
+    },
+
+    {
+       67, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+
+     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+     -163, -163, -163, -163, -163,  280, -163, -163, -163, -163,
+     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+
+     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+     -163, -163, -163, -163, -163, -163, -163, -163
+    },
+
+    {
+       67, -164, -164, -164, -164, -164, -164, -164, -164, -164,
+     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
+     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
+     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
+     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
+     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
+     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
+     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
+
+     -164, -164, -164, -164,  281, -164, -164, -164, -164, -164,
+     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
+     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
+     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
+     -164, -164, -164, -164, -164, -164, -164, -164
+    },
+
+    {
+       67, -165, -165, -165, -165, -165, -165, -165, -165, -165,
+     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
+     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
+     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
+     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
+
+     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
+     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
+     -165, -165, -165, -165, -165, -165, -165, -165,  282, -165,
+     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
+     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
+     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
+     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
+     -165, -165, -165, -165, -165, -165, -165, -165
+    },
+
+    {
+       67, -166, -166, -166, -166, -166, -166, -166, -166, -166,
+     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
+
+     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
+     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
+     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
+     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
+     -166, -166, -166, -166, -166, -166, -166, -166,  283, -166,
+     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
+     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
+     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
+     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
+     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
+
+     -166, -166, -166, -166, -166, -166, -166, -166
+    },
+
+    {
+       67, -167, -167, -167, -167, -167, -167, -167, -167, -167,
+     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
+     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
+     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
+     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
+     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
+     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
+     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
+     -167, -167, -167,  284, -167, -167, -167, -167, -167, -167,
+
+     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
+     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
+     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
+     -167, -167, -167, -167, -167, -167, -167, -167
+    },
+
+    {
+       67, -168, -168, -168, -168, -168, -168, -168, -168, -168,
+     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
+     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
+     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
+     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
+     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
+
+     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
+     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
+     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
+     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
+     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
+     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
+     -168, -168, -168, -168, -168, -168, -168, -168
+    },
+
+    {
+       67, -169, -169, -169, -169, -169, -169, -169, -169, -169,
+     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
+     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
+
+     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
+     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
+     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
+     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
+     -169, -169, -169, -169, -169, -169, -169, -169, -169,  285,
+     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
+     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
+     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
+     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
+     -169, -169, -169, -169, -169, -169, -169, -169
+
+    },
+
+    {
+       67, -170, -170, -170, -170, -170, -170, -170, -170, -170,
+     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
+     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
+     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
+     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
+     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
+     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
+     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
+     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
+     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
+
+     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
+     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
+     -170, -170, -170, -170, -170, -170, -170, -170
+    },
+
+    {
+       67, -171, -171, -171, -171, -171, -171, -171, -171, -171,
+     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
+     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
+     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
+     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
+     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
+     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
+
+     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
+     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
+     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
+     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
+     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
+     -171, -171, -171, -171, -171, -171, -171, -171
+    },
+
+    {
+       67, -172, -172, -172, -172, -172, -172, -172, -172, -172,
+     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
+     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
+     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
+
+     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
+     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
+     -172, -172, -172, -172, -172, -172, -172, -172,  286, -172,
+     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
+     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
+     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
+     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
+     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
+     -172, -172, -172, -172, -172, -172, -172, -172
+    },
+
+    {
+       67, -173, -173, -173, -173, -173, -173, -173, -173, -173,
+
+     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
+     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
+     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
+     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
+     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
+     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
+     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
+     -173, -173, -173,  287, -173, -173, -173, -173, -173, -173,
+     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
+     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
+
+     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
+     -173, -173, -173, -173, -173, -173, -173, -173
+    },
+
+    {
+       67, -174, -174, -174, -174, -174, -174, -174, -174, -174,
+     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
+     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
+     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
+     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
+     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
+     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
+     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
+
+     -174, -174,  288, -174, -174, -174, -174, -174, -174, -174,
+     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
+     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
+     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
+     -174, -174, -174, -174, -174, -174, -174, -174
+    },
+
+    {
+       67, -175, -175, -175, -175, -175, -175, -175, -175, -175,
+     -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
+     -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
+     -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
+     -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
+
+     -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
+     -175, -175, -175, -175, -175,  289, -175, -175, -175, -175,
+     -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
+     -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
+     -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
+     -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
+     -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
+     -175, -175, -175, -175, -175, -175, -175, -175
+    },
+
+    {
+       67, -176, -176, -176, -176, -176, -176, -176, -176, -176,
+     -176, -176, -176, -176, -176, -176, -176, -176, -176, -176,
+
+     -176, -176, -176, -176, -176, -176, -176, -176, -176, -176,
+     -176, -176, -176, -176, -176, -176, -176, -176, -176, -176,
+     -176, -176, -176, -176, -176, -176, -176, -176, -176, -176,
+     -176, -176, -176, -176, -176, -176, -176, -176, -176, -176,
+     -176, -176, -176, -176, -176, -176,  290, -176, -176, -176,
+     -176, -176, -176, -176, -176, -176, -176, -176, -176, -176,
+     -176, -176, -176, -176, -176, -176, -176, -176, -176, -176,
+     -176, -176, -176, -176, -176, -176, -176, -176, -176, -176,
+     -176, -176, -176, -176, -176, -176, -176, -176, -176, -176,
+     -176, -176, -176, -176, -176, -176, -176, -176, -176, -176,
+
+     -176, -176, -176, -176, -176, -176, -176, -176
+    },
+
+    {
+       67, -177, -177, -177, -177, -177, -177, -177, -177, -177,
+     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
+     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
+     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
+     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
+     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
+     -177, -177, -177, -177, -177, -177, -177, -177, -177,  291,
+     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
+     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
+
+     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
+     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
+     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
+     -177, -177, -177, -177, -177, -177, -177, -177
+    },
+
+    {
+       67, -178, -178, -178, -178, -178, -178, -178, -178, -178,
+     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
+     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
+     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
+     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
+     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
+
+     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
+     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
+     -178, -178,  292, -178, -178, -178, -178, -178, -178,  293,
+     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
+     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
+     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
+     -178, -178, -178, -178, -178, -178, -178, -178
+    },
+
+    {
+       67, -179, -179, -179, -179, -179, -179, -179, -179, -179,
+     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
+     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
+
+     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
+     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
+     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
+     -179, -179, -179, -179, -179, -179, -179, -179,  294, -179,
+     -179, -179, -179, -179, -179, -179, -179, -179,  295, -179,
+     -179, -179,  296,  297,  298,  299, -179, -179, -179, -179,
+     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
+     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
+     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
+     -179, -179, -179, -179, -179, -179, -179, -179
+
+    },
+
+    {
+       67, -180, -180, -180, -180, -180, -180, -180, -180, -180,
+     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
+     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
+     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
+     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
+     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
+     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
+     -180, -180, -180,  300, -180, -180, -180, -180, -180, -180,
+     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
+     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
+
+     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
+     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
+     -180, -180, -180, -180, -180, -180, -180, -180
+    },
+
+    {
+       67, -181, -181, -181, -181, -181, -181, -181, -181, -181,
+     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
+     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
+     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
+     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
+     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
+     -181, -181, -181, -181, -181, -181, -181,  301, -181, -181,
+
+     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
+     -181, -181, -181,  302, -181, -181,  303, -181, -181, -181,
+     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
+     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
+     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
+     -181, -181, -181, -181, -181, -181, -181, -181
+    },
+
+    {
+       67, -182, -182, -182, -182, -182, -182, -182, -182, -182,
+     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
+     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
+     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
+
+     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
+     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
+     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
+     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
+     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
+     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
+     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
+     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
+     -182, -182, -182, -182, -182, -182, -182, -182
+    },
+
+    {
+       67, -183, -183, -183, -183, -183, -183, -183, -183, -183,
+
+     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
+     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
+     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
+     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
+     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
+     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
+     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
+     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
+     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
+     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
+
+     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
+     -183, -183, -183, -183, -183, -183, -183, -183
+    },
+
+    {
+       67, -184, -184, -184, -184, -184, -184, -184, -184, -184,
+     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
+     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
+     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
+     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
+     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
+     -184, -184, -184, -184, -184, -184, -184,  304, -184, -184,
+     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
+
+     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
+     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
+     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
+     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
+     -184, -184, -184, -184, -184, -184, -184, -184
+    },
+
+    {
+       67, -185, -185, -185, -185, -185, -185, -185, -185, -185,
+     -185, -185, -185, -185, -185, -185, -185, -185, -185, -185,
+     -185, -185, -185, -185, -185, -185, -185, -185, -185, -185,
+     -185, -185, -185, -185, -185, -185, -185, -185, -185, -185,
+     -185, -185, -185, -185, -185, -185, -185, -185, -185, -185,
+
+     -185, -185, -185, -185, -185, -185, -185, -185, -185, -185,
+     -185, -185, -185, -185, -185, -185, -185, -185, -185, -185,
+     -185, -185, -185, -185, -185, -185, -185, -185,  305, -185,
+     -185, -185, -185, -185, -185, -185, -185, -185, -185, -185,
+     -185, -185, -185, -185, -185, -185, -185, -185, -185, -185,
+     -185, -185, -185, -185, -185, -185, -185, -185, -185, -185,
+     -185, -185, -185, -185, -185, -185, -185, -185, -185, -185,
+     -185, -185, -185, -185, -185, -185, -185, -185
+    },
+
+    {
+       67, -186, -186, -186, -186, -186, -186, -186, -186, -186,
+     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
+
+     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
+     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
+     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
+     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
+     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
+     -186, -186, -186, -186, -186, -186,  306, -186, -186, -186,
+     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
+     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
+     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
+     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
+
+     -186, -186, -186, -186, -186, -186, -186, -186
+    },
+
+    {
+       67, -187, -187, -187, -187, -187, -187, -187, -187, -187,
+     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
+     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
+     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
+     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
+     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
+     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
+     -187, -187, -187, -187, -187, -187, -187, -187, -187,  307,
+     -187, -187, -187, -187, -187, -187, -187, -187, -187,  308,
+
+     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
+     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
+     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
+     -187, -187, -187, -187, -187, -187, -187, -187
+    },
+
+    {
+       67, -188, -188, -188, -188, -188, -188, -188, -188, -188,
+     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
+     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
+     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
+     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
+     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
+
+     -188, -188, -188, -188, -188,  309, -188, -188, -188, -188,
+     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
+     -188, -188, -188,  310, -188, -188, -188, -188, -188, -188,
+     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
+     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
+     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
+     -188, -188, -188, -188, -188, -188, -188, -188
+    },
+
+    {
+       67, -189, -189, -189, -189, -189, -189, -189, -189, -189,
+     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
+     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
+
+     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
+     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
+     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
+     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
+     -189, -189, -189, -189, -189, -189, -189, -189, -189,  311,
+     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
+     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
+     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
+     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
+     -189, -189, -189, -189, -189, -189, -189, -189
+
+    },
+
+    {
+       67, -190, -190, -190, -190, -190, -190, -190, -190, -190,
+     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
+     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
+     -190, -190,  312, -190, -190, -190, -190, -190, -190, -190,
+     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
+     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
+     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
+     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
+     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
+     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
+
+     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
+     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
+     -190, -190, -190, -190, -190, -190, -190, -190
+    },
+
+    {
+       67, -191, -191, -191, -191, -191, -191, -191, -191, -191,
+     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
+     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
+     -191, -191,  313, -191, -191, -191, -191, -191, -191, -191,
+     -191, -191, -191, -191, -191, -191, -191, -191,  314,  314,
+      314,  314,  314,  314,  314,  314,  314,  314, -191, -191,
+     -191, -191, -191, -191, -191,  313,  313,  313,  313,  313,
+
+      313,  313,  313,  313,  313,  313,  313,  313,  313,  313,
+      313,  313,  313,  313,  313,  313,  313,  313,  313,  313,
+      313, -191, -191, -191, -191, -191, -191, -191, -191, -191,
+     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
+     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
+     -191, -191, -191, -191, -191, -191, -191, -191
+    },
+
+    {
+       67, -192, -192, -192, -192, -192, -192, -192, -192, -192,
+     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
+     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
+     -192, -192,  315, -192, -192, -192, -192, -192, -192, -192,
+
+     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
+     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
+     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
+     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
+     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
+     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
+     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
+     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
+     -192, -192, -192, -192, -192, -192, -192, -192
+    },
+
+    {
+       67, -193, -193, -193, -193, -193, -193, -193, -193, -193,
+
+     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
+     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
+     -193, -193,  316, -193, -193, -193, -193, -193, -193, -193,
+     -193, -193, -193, -193, -193, -193, -193, -193,  317,  317,
+      317,  317,  317,  317,  317,  317,  317,  317, -193, -193,
+     -193, -193, -193, -193, -193,  316,  316,  316,  316,  316,
+      316,  316,  316,  316,  316,  316,  316,  316,  316,  316,
+      316,  316,  316,  316,  316,  316,  316,  316,  316,  316,
+      316, -193, -193, -193, -193, -193, -193, -193, -193, -193,
+     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
+
+     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
+     -193, -193, -193, -193, -193, -193, -193, -193
+    },
+
+    {
+       67, -194, -194, -194, -194, -194, -194, -194, -194, -194,
+     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
+     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
+     -194, -194,  318, -194, -194, -194, -194, -194, -194, -194,
+     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
+     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
+     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
+     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
+
+     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
+     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
+     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
+     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
+     -194, -194, -194, -194, -194, -194, -194, -194
+    },
+
+    {
+       67, -195, -195, -195, -195, -195, -195, -195, -195, -195,
+     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
+     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
+     -195, -195,  319, -195, -195, -195, -195, -195, -195, -195,
+     -195, -195, -195, -195, -195, -195, -195, -195,  320,  320,
+
+      320,  320,  320,  320,  320,  320,  320,  320, -195, -195,
+     -195, -195, -195, -195, -195,  321,  321,  321,  321,  321,
+      321,  321,  321,  321,  321,  321,  321,  321,  321,  321,
+      321,  321,  321,  321,  321,  321,  321,  321,  321,  321,
+      321, -195, -195, -195, -195, -195, -195, -195, -195, -195,
+     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
+     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
+     -195, -195, -195, -195, -195, -195, -195, -195
+    },
+
+    {
+       67, -196, -196, -196, -196, -196, -196, -196, -196, -196,
+     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
+
+     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
+     -196, -196,  322, -196, -196, -196, -196, -196, -196, -196,
+     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
+     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
+     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
+     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
+     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
+     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
+     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
+     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
+
+     -196, -196, -196, -196, -196, -196, -196, -196
+    },
+
+    {
+       67, -197, -197, -197, -197, -197, -197, -197, -197, -197,
+     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
+     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
+     -197, -197,  323, -197, -197, -197, -197, -197, -197, -197,
+     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
+     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
+     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
+     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
+     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
+
+     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
+     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
+     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
+     -197, -197, -197, -197, -197, -197, -197, -197
+    },
+
+    {
+       67, -198, -198, -198, -198, -198, -198, -198, -198, -198,
+     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
+     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
+     -198, -198,  324, -198, -198, -198, -198, -198, -198, -198,
+     -198, -198, -198, -198, -198, -198, -198, -198,  325,  325,
+      325,  325,  325,  325,  325,  325,  325,  325, -198, -198,
+
+     -198, -198, -198, -198, -198,  324,  324,  324,  324,  324,
+      324,  324,  324,  324,  324,  324,  324,  324,  324,  324,
+      324,  324,  324,  324,  324,  324,  324,  324,  324,  324,
+      324, -198, -198, -198, -198, -198, -198, -198, -198, -198,
+     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
+     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
+     -198, -198, -198, -198, -198, -198, -198, -198
+    },
+
+    {
+       67, -199, -199, -199, -199, -199, -199, -199, -199, -199,
+     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
+     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
+
+     -199, -199,  326, -199, -199, -199, -199, -199, -199, -199,
+     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
+     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
+     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
+     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
+     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
+     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
+     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
+     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
+     -199, -199, -199, -199, -199, -199, -199, -199
+
+    },
+
+    {
+       67, -200, -200, -200, -200, -200, -200, -200, -200, -200,
+     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
+     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
+     -200, -200,  327, -200, -200, -200, -200, -200, -200, -200,
+     -200, -200, -200, -200, -200, -200, -200, -200,  328,  328,
+      328,  328,  328,  328,  328,  328,  328,  328, -200, -200,
+     -200, -200, -200, -200, -200,  329,  329,  329,  329,  329,
+      329,  329,  329,  329,  329,  329,  329,  329,  329,  329,
+      329,  329,  329,  329,  329,  329,  329,  329,  329,  329,
+      329, -200, -200, -200, -200, -200, -200, -200, -200, -200,
+
+     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
+     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
+     -200, -200, -200, -200, -200, -200, -200, -200
+    },
+
+    {
+       67, -201, -201, -201, -201, -201, -201, -201, -201, -201,
+     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
+     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
+     -201, -201,  330, -201, -201, -201, -201, -201, -201, -201,
+     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
+     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
+     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
+
+     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
+     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
+     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
+     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
+     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
+     -201, -201, -201, -201, -201, -201, -201, -201
+    },
+
+    {
+       67, -202, -202, -202, -202, -202, -202, -202, -202, -202,
+     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
+     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
+     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
+
+     -202, -202, -202, -202, -202, -202, -202, -202,  331,  331,
+      331,  331,  331,  331,  331,  331,  331,  331, -202, -202,
+     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
+     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
+     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
+     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
+     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
+     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
+     -202, -202, -202, -202, -202, -202, -202, -202
+    },
+
+    {
+       67, -203, -203, -203, -203, -203, -203, -203, -203, -203,
+
+     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
+     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
+     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
+     -203, -203, -203, -203, -203, -203, -203, -203,  332,  332,
+      332,  332,  332,  332,  332,  332,  332,  332, -203, -203,
+     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
+     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
+     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
+     -203, -203, -203, -203, -203,  333, -203, -203, -203, -203,
+     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
+
+     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
+     -203, -203, -203, -203, -203, -203, -203, -203
+    },
+
+    {
+       67, -204, -204, -204, -204, -204, -204, -204, -204, -204,
+     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
+     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
+     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
+     -204, -204, -204, -204, -204, -204, -204, -204, -204,  334,
+      334,  334,  334,  334,  334,  334,  334,  334, -204, -204,
+     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
+     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
+
+     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
+     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
+     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
+     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
+     -204, -204, -204, -204, -204, -204, -204, -204
+    },
+
+    {
+       67, -205, -205, -205, -205, -205, -205, -205, -205, -205,
+     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
+     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
+     -205, -205,  335, -205, -205, -205, -205, -205, -205, -205,
+     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
+
+     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
+     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
+     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
+     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
+     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
+     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
+     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
+     -205, -205, -205, -205, -205, -205, -205, -205
+    },
+
+    {
+       67, -206, -206, -206, -206, -206, -206, -206, -206, -206,
+     -206, -206, -206, -206, -206, -206, -206, -206, -206, -206,
+
+     -206, -206, -206, -206, -206, -206, -206, -206, -206, -206,
+     -206, -206,  336, -206, -206, -206, -206, -206, -206, -206,
+     -206, -206, -206, -206, -206, -206, -206, -206,  337,  337,
+      337,  337,  337,  337,  337,  337,  337,  337, -206, -206,
+     -206, -206, -206, -206, -206,  336,  336,  336,  336,  336,
+      336,  336,  336,  336,  336,  336,  336,  336,  336,  336,
+      336,  336,  336,  336,  336,  336,  336,  336,  336,  336,
+      336, -206, -206, -206, -206, -206, -206, -206, -206, -206,
+     -206, -206, -206, -206, -206, -206, -206, -206, -206, -206,
+     -206, -206, -206, -206, -206, -206, -206, -206, -206, -206,
+
+     -206, -206, -206, -206, -206, -206, -206, -206
+    },
+
+    {
+       67, -207, -207, -207, -207, -207, -207, -207, -207, -207,
+     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
+     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
+     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
+     -207, -207, -207, -207, -207, -207, -207, -207,  338,  338,
+      338,  338,  338,  338,  338,  338,  338,  338, -207, -207,
+     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
+     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
+     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
+
+     -207, -207, -207, -207, -207,  339, -207, -207, -207, -207,
+     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
+     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
+     -207, -207, -207, -207, -207, -207, -207, -207
+    },
+
+    {
+       67, -208, -208, -208, -208, -208, -208, -208, -208, -208,
+     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
+     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
+     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
+     -208, -208, -208, -208, -208, -208, -208, -208, -208,  340,
+      340,  340,  340,  340,  340,  340,  340,  340, -208, -208,
+
+     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
+     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
+     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
+     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
+     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
+     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
+     -208, -208, -208, -208, -208, -208, -208, -208
+    },
+
+    {
+       67, -209, -209, -209, -209, -209, -209, -209, -209, -209,
+     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
+     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
+
+     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
+     -209, -209, -209, -209, -209, -209, -209, -209,  341,  341,
+      341,  341,  341,  341,  341,  341,  341,  341, -209, -209,
+     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
+     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
+     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
+     -209, -209, -209, -209, -209,  342, -209, -209, -209, -209,
+     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
+     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
+     -209, -209, -209, -209, -209, -209, -209, -209
+
+    },
+
+    {
+       67, -210, -210, -210, -210, -210, -210, -210, -210, -210,
+     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
+     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
+     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
+     -210, -210, -210, -210, -210, -210, -210, -210, -210,  343,
+      343,  343,  343,  343,  343,  343,  343,  343, -210, -210,
+     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
+     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
+     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
+     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
+
+     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
+     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
+     -210, -210, -210, -210, -210, -210, -210, -210
+    },
+
+    {
+       67, -211, -211, -211, -211, -211, -211, -211, -211, -211,
+     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
+     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
+     -211, -211,  344, -211, -211, -211, -211, -211, -211, -211,
+     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
+     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
+     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
+
+     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
+     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
+     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
+     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
+     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
+     -211, -211, -211, -211, -211, -211, -211, -211
+    },
+
+    {
+       67, -212, -212, -212, -212, -212, -212, -212, -212, -212,
+     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
+     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
+     -212, -212,  345, -212, -212, -212, -212, -212, -212, -212,
+
+     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
+     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
+     -212, -212, -212, -212, -212,  346,  346,  346,  346,  346,
+      346,  346,  346,  346,  346,  346,  346,  346,  346,  346,
+      346,  346,  346,  346,  346,  346,  346,  346,  346,  346,
+      346, -212, -212, -212, -212, -212, -212, -212, -212, -212,
+     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
+     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
+     -212, -212, -212, -212, -212, -212, -212, -212
+    },
+
+    {
+       67, -213, -213, -213, -213, -213, -213, -213, -213, -213,
+
+     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
+     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
+     -213, -213,  347, -213, -213, -213, -213, -213, -213, -213,
+     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
+     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
+     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
+     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
+     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
+     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
+     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
+
+     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
+     -213, -213, -213, -213, -213, -213, -213, -213
+    },
+
+    {
+       67, -214, -214, -214, -214, -214, -214, -214, -214, -214,
+     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
+     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
+     -214, -214,  348, -214, -214, -214, -214, -214, -214, -214,
+     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
+     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
+     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
+     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
+
+     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
+     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
+     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
+     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
+     -214, -214, -214, -214, -214, -214, -214, -214
+    },
+
+    {
+       67, -215, -215, -215, -215, -215, -215, -215, -215, -215,
+     -215, -215, -215, -215, -215, -215, -215, -215, -215, -215,
+     -215, -215, -215, -215, -215, -215, -215, -215, -215, -215,
+     -215, -215,  349, -215, -215, -215, -215, -215, -215, -215,
+     -215, -215, -215, -215, -215, -215, -215, -215,  350,  350,
+
+      350,  350,  350,  350,  350,  350,  350,  350, -215, -215,
+     -215, -215, -215, -215, -215,  351,  351,  351,  351,  351,
+      351,  351,  351,  351,  351,  351,  351,  351,  351,  351,
+      351,  351,  351,  351,  351,  351,  351,  351,  351,  351,
+      351, -215, -215, -215, -215, -215, -215, -215, -215, -215,
+     -215, -215, -215, -215, -215, -215, -215, -215, -215, -215,
+     -215, -215, -215, -215, -215, -215, -215, -215, -215, -215,
+     -215, -215, -215, -215, -215, -215, -215, -215
+    },
+
+    {
+       67, -216, -216, -216, -216, -216, -216, -216, -216, -216,
+     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
+
+     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
+     -216, -216,  352, -216, -216, -216, -216, -216, -216, -216,
+     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
+     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
+     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
+     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
+     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
+     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
+     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
+     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
+
+     -216, -216, -216, -216, -216, -216, -216, -216
+    },
+
+    {
+       67, -217, -217, -217, -217, -217, -217, -217, -217, -217,
+     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
+     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
+     -217, -217,  353, -217, -217, -217, -217, -217, -217, -217,
+     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
+     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
+     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
+     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
+     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
+
+     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
+     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
+     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
+     -217, -217, -217, -217, -217, -217, -217, -217
+    },
+
+    {
+       67, -218, -218, -218, -218, -218, -218, -218, -218, -218,
+     -218, -218, -218, -218, -218, -218, -218, -218, -218, -218,
+     -218, -218, -218, -218, -218, -218, -218, -218, -218, -218,
+     -218, -218,  354, -218, -218, -218, -218, -218, -218, -218,
+     -218, -218, -218, -218, -218, -218, -218, -218,  355,  355,
+      355,  355,  355,  355,  355,  355,  355,  355, -218, -218,
+
+     -218, -218, -218, -218, -218,  356,  356,  356,  356,  356,
+      356,  356,  356,  356,  356,  356,  356,  356,  356,  356,
+      356,  356,  356,  356,  356,  356,  356,  356,  356,  356,
+      356, -218, -218, -218, -218, -218, -218, -218, -218, -218,
+     -218, -218, -218, -218, -218, -218, -218, -218, -218, -218,
+     -218, -218, -218, -218, -218, -218, -218, -218, -218, -218,
+     -218, -218, -218, -218, -218, -218, -218, -218
+    },
+
+    {
+       67, -219, -219, -219, -219, -219, -219, -219, -219, -219,
+     -219, -219, -219, -219, -219, -219, -219, -219, -219, -219,
+     -219, -219, -219, -219, -219, -219, -219, -219, -219, -219,
+
+     -219, -219,  357, -219, -219, -219, -219, -219, -219, -219,
+     -219, -219, -219, -219, -219, -219, -219, -219, -219, -219,
+     -219, -219, -219, -219, -219, -219, -219, -219, -219, -219,
+     -219, -219, -219, -219, -219, -219, -219, -219, -219, -219,
+     -219, -219, -219, -219, -219, -219, -219, -219, -219, -219,
+     -219, -219, -219, -219, -219, -219, -219, -219, -219, -219,
+     -219, -219, -219, -219, -219, -219, -219, -219, -219, -219,
+     -219, -219, -219, -219, -219, -219, -219, -219, -219, -219,
+     -219, -219, -219, -219, -219, -219, -219, -219, -219, -219,
+     -219, -219, -219, -219, -219, -219, -219, -219
+
+    },
+
+    {
+       67, -220, -220, -220, -220, -220, -220, -220, -220, -220,
+     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
+     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
+     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
+     -220, -220, -220, -220, -220, -220, -220, -220,  358,  358,
+      358,  358,  358,  358,  358,  358,  358,  358, -220, -220,
+     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
+     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
+     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
+     -220, -220, -220, -220, -220,  359, -220, -220, -220, -220,
+
+     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
+     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
+     -220, -220, -220, -220, -220, -220, -220, -220
+    },
+
+    {
+       67, -221, -221, -221, -221, -221, -221, -221, -221, -221,
+     -221, -221, -221, -221, -221, -221, -221, -221, -221, -221,
+     -221, -221, -221, -221, -221, -221, -221, -221, -221, -221,
+     -221, -221, -221, -221, -221, -221, -221, -221, -221, -221,
+     -221, -221, -221, -221, -221, -221, -221, -221,  360,  361,
+      361,  361,  361,  361,  361,  361,  361,  361, -221, -221,
+     -221, -221, -221, -221, -221, -221, -221, -221, -221, -221,
+
+     -221, -221, -221, -221, -221, -221, -221, -221, -221, -221,
+     -221, -221, -221, -221, -221, -221, -221, -221, -221, -221,
+     -221, -221, -221, -221, -221, -221, -221, -221, -221, -221,
+     -221, -221, -221, -221, -221, -221, -221, -221, -221, -221,
+     -221, -221, -221, -221, -221, -221, -221, -221, -221, -221,
+     -221, -221, -221, -221, -221, -221, -221, -221
+    },
+
+    {
+       67, -222, -222, -222, -222, -222, -222, -222, -222, -222,
+     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
+     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
+     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
+
+     -222, -222, -222, -222, -222, -222, -222, -222,  362,  362,
+      362,  362,  362,  362,  362,  362,  362,  362, -222, -222,
+     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
+     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
+     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
+     -222, -222, -222, -222, -222,  363, -222, -222, -222, -222,
+     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
+     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
+     -222, -222, -222, -222, -222, -222, -222, -222
+    },
+
+    {
+       67, -223, -223, -223, -223, -223, -223, -223, -223, -223,
+
+     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
+     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
+     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
+     -223, -223, -223, -223, -223, -223, -223, -223,  364,  365,
+      365,  365,  365,  365,  365,  365,  365,  365, -223, -223,
+     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
+     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
+     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
+     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
+     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
+
+     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
+     -223, -223, -223, -223, -223, -223, -223, -223
+    },
+
+    {
+       67, -224, -224, -224, -224, -224, -224, -224, -224, -224,
+     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
+     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
+     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
+     -224, -224, -224, -224, -224, -224, -224, -224,  366,  366,
+      366,  366,  366,  366,  366,  366,  366,  366, -224, -224,
+     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
+     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
+
+     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
+     -224, -224, -224, -224, -224,  367, -224, -224, -224, -224,
+     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
+     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
+     -224, -224, -224, -224, -224, -224, -224, -224
+    },
+
+    {
+       67, -225, -225, -225, -225, -225, -225, -225, -225, -225,
+     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
+     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
+     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
+     -225, -225, -225, -225, -225, -225, -225, -225,  368,  369,
+
+      369,  369,  369,  369,  369,  369,  369,  369, -225, -225,
+     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
+     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
+     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
+     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
+     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
+     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
+     -225, -225, -225, -225, -225, -225, -225, -225
+    },
+
+    {
+       67, -226, -226, -226, -226, -226, -226, -226, -226, -226,
+     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
+
+     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
+     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
+     -226, -226, -226, -226, -226, -226, -226, -226,  370,  370,
+      370,  370,  370,  370,  370,  370,  370,  370, -226, -226,
+     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
+     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
+     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
+     -226, -226, -226, -226, -226,  371, -226, -226, -226, -226,
+     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
+     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
+
+     -226, -226, -226, -226, -226, -226, -226, -226
+    },
+
+    {
+       67, -227, -227, -227, -227, -227, -227, -227, -227, -227,
+     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
+     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
+     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
+     -227, -227, -227, -227, -227, -227, -227, -227,  372,  373,
+      373,  373,  373,  373,  373,  373,  373,  373, -227, -227,
+     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
+     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
+     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
+
+     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
+     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
+     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
+     -227, -227, -227, -227, -227, -227, -227, -227
+    },
+
+    {
+       67, -228, -228, -228, -228, -228, -228, -228, -228, -228,
+     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
+     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
+     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
+     -228, -228, -228, -228, -228, -228, -228, -228,  374,  374,
+      374,  374,  374,  374,  374,  374,  374,  374, -228, -228,
+
+     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
+     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
+     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
+     -228, -228, -228, -228, -228,  375, -228, -228, -228, -228,
+     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
+     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
+     -228, -228, -228, -228, -228, -228, -228, -228
+    },
+
+    {
+       67, -229, -229, -229, -229, -229, -229, -229, -229, -229,
+     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
+     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
+
+     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
+     -229, -229, -229, -229, -229, -229, -229, -229,  376,  377,
+      377,  377,  377,  377,  377,  377,  377,  377, -229, -229,
+     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
+     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
+     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
+     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
+     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
+     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
+     -229, -229, -229, -229, -229, -229, -229, -229
+
+    },
+
+    {
+       67, -230, -230, -230, -230, -230, -230, -230, -230, -230,
+     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
+     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
+     -230, -230,  378, -230, -230, -230, -230, -230, -230, -230,
+     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
+     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
+     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
+     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
+     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
+     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
+
+     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
+     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
+     -230, -230, -230, -230, -230, -230, -230, -230
+    },
+
+    {
+       67, -231, -231, -231, -231, -231, -231, -231, -231, -231,
+     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
+     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
+     -231, -231,  379, -231, -231, -231, -231, -231, -231, -231,
+     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
+     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
+     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
+
+     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
+     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
+     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
+     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
+     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
+     -231, -231, -231, -231, -231, -231, -231, -231
+    },
+
+    {
+       67, -232, -232, -232, -232, -232, -232, -232, -232, -232,
+     -232, -232, -232, -232, -232, -232, -232, -232, -232, -232,
+     -232, -232, -232, -232, -232, -232, -232, -232, -232, -232,
+     -232, -232,  380, -232, -232, -232, -232, -232, -232, -232,
+
+     -232, -232, -232, -232, -232, -232, -232, -232,  381,  381,
+      381,  381,  381,  381,  381,  381,  381,  381, -232, -232,
+     -232, -232, -232, -232, -232,  380,  380,  380,  380,  380,
+      380,  380,  380,  380,  380,  380,  380,  380,  380,  380,
+      380,  380,  380,  380,  380,  380,  380,  380,  380,  380,
+      380, -232, -232, -232, -232, -232, -232, -232, -232, -232,
+     -232, -232, -232, -232, -232, -232, -232, -232, -232, -232,
+     -232, -232, -232, -232, -232, -232, -232, -232, -232, -232,
+     -232, -232, -232, -232, -232, -232, -232, -232
+    },
+
+    {
+       67, -233, -233, -233, -233, -233, -233, -233, -233, -233,
+
+     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
+     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
+     -233, -233,  382, -233, -233, -233, -233, -233, -233, -233,
+     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
+     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
+     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
+     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
+     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
+     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
+     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
+
+     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
+     -233, -233, -233, -233, -233, -233, -233, -233
+    },
+
+    {
+       67, -234, -234, -234, -234, -234, -234, -234, -234, -234,
+     -234, -234, -234, -234, -234, -234, -234, -234, -234, -234,
+     -234, -234, -234, -234, -234, -234, -234, -234, -234, -234,
+     -234, -234,  383, -234, -234, -234, -234, -234, -234, -234,
+     -234, -234, -234, -234, -234, -234, -234, -234,  384,  384,
+      384,  384,  384,  384,  384,  384,  384,  384, -234, -234,
+     -234, -234, -234, -234, -234,  383,  383,  383,  383,  383,
+      383,  383,  383,  383,  383,  383,  383,  383,  383,  383,
+
+      383,  383,  383,  383,  383,  383,  383,  383,  383,  383,
+      383, -234, -234, -234, -234, -234, -234, -234, -234, -234,
+     -234, -234, -234, -234, -234, -234, -234, -234, -234, -234,
+     -234, -234, -234, -234, -234, -234, -234, -234, -234, -234,
+     -234, -234, -234, -234, -234, -234, -234, -234
+    },
+
+    {
+       67, -235, -235, -235, -235, -235, -235, -235, -235, -235,
+     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
+     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
+     -235, -235,  385, -235, -235, -235, -235, -235, -235, -235,
+     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
+
+     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
+     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
+     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
+     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
+     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
+     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
+     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
+     -235, -235, -235, -235, -235, -235, -235, -235
+    },
+
+    {
+       67, -236, -236, -236, -236, -236, -236, -236, -236, -236,
+     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
+
+     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
+     -236, -236,  386, -236, -236, -236, -236, -236, -236, -236,
+     -236, -236, -236, -236, -236, -236, -236, -236,  387,  387,
+      387,  387,  387,  387,  387,  387,  387,  387, -236, -236,
+     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
+     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
+     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
+     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
+     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
+     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
+
+     -236, -236, -236, -236, -236, -236, -236, -236
+    },
+
+    {
+       67, -237, -237, -237, -237, -237, -237, -237, -237, -237,
+     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
+     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
+     -237, -237,  388, -237, -237, -237, -237, -237, -237, -237,
+     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
+     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
+     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
+     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
+     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
+
+     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
+     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
+     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
+     -237, -237, -237, -237, -237, -237, -237, -237
+    },
+
+    {
+       67, -238, -238, -238, -238, -238, -238, -238, -238, -238,
+     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
+     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
+     -238, -238,  389, -238, -238, -238, -238, -238, -238, -238,
+     -238, -238, -238, -238, -238, -238, -238, -238,  390,  390,
+      390,  390,  390,  390,  390,  390,  390,  390, -238, -238,
+
+     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
+     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
+     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
+     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
+     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
+     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
+     -238, -238, -238, -238, -238, -238, -238, -238
+    },
+
+    {
+       67, -239, -239, -239, -239, -239, -239, -239, -239, -239,
+     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
+     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
+
+     -239, -239,  239, -239, -239, -239, -239, -239, -239, -239,
+     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
+     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
+     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
+     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
+     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
+     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
+     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
+     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
+     -239, -239, -239, -239, -239, -239, -239, -239
+
+    },
+
+    {
+       67, -240, -240, -240, -240, -240, -240, -240, -240, -240,
+     -240, -240, -240, -240, -240, -240, -240, -240, -240, -240,
+     -240, -240, -240, -240, -240, -240, -240, -240, -240, -240,
+     -240, -240, -240, -240, -240, -240, -240, -240, -240, -240,
+     -240, -240, -240, -240, -240, -240, -240, -240,  240,  240,
+      240,  240,  240,  240,  240,  240,  240,  240, -240, -240,
+     -240, -240, -240, -240, -240, -240, -240, -240, -240, -240,
+     -240, -240, -240, -240, -240, -240, -240, -240, -240, -240,
+     -240, -240, -240, -240, -240, -240, -240, -240, -240, -240,
+     -240, -240, -240, -240, -240, -240, -240, -240, -240, -240,
+
+     -240, -240, -240, -240, -240, -240, -240, -240, -240, -240,
+     -240, -240, -240, -240, -240, -240, -240, -240, -240, -240,
+     -240, -240, -240, -240, -240, -240, -240, -240
+    },
+
+    {
+       67, -241, -241, -241, -241, -241, -241, -241, -241, -241,
+     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
+     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
+     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
+     -241, -241, -241, -241, -241, -241, -241, -241,  243,  243,
+      243,  243,  243,  243,  243,  243,  243,  243, -241, -241,
+     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
+
+     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
+     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
+     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
+     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
+     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
+     -241, -241, -241, -241, -241, -241, -241, -241
+    },
+
+    {
+       67, -242, -242, -242, -242, -242, -242, -242, -242, -242,
+     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
+     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
+     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
+
+     -242, -242, -242, -242, -242, -242,  244, -242,  245,  245,
+      245,  245,  245,  245,  245,  245,  245,  245, -242, -242,
+     -242, -242, -242, -242, -242, -242, -242, -242, -242,  246,
+     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
+     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
+     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
+     -242,  246, -242, -242, -242, -242, -242, -242, -242, -242,
+     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
+     -242, -242, -242, -242, -242, -242, -242, -242
+    },
+
+    {
+       67, -243, -243, -243, -243, -243, -243, -243, -243, -243,
+
+     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
+     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
+     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
+     -243, -243, -243, -243, -243, -243, -243, -243,  243,  243,
+      243,  243,  243,  243,  243,  243,  243,  243, -243, -243,
+     -243, -243, -243, -243, -243, -243, -243, -243, -243,  246,
+     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
+     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
+     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
+     -243,  246, -243, -243, -243, -243, -243, -243, -243, -243,
+
+     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
+     -243, -243, -243, -243, -243, -243, -243, -243
+    },
+
+    {
+       67, -244, -244, -244, -244, -244, -244, -244, -244, -244,
+     -244, -244, -244, -244, -244, -244, -244, -244, -244, -244,
+     -244, -244, -244, -244, -244, -244, -244, -244, -244, -244,
+     -244, -244, -244, -244, -244, -244, -244, -244, -244, -244,
+     -244, -244, -244, -244, -244, -244, -244, -244,  391,  391,
+      391,  391,  391,  391,  391,  391,  391,  391, -244, -244,
+     -244, -244, -244, -244, -244, -244, -244, -244, -244,  246,
+     -244, -244, -244, -244, -244, -244, -244, -244, -244, -244,
+
+     -244, -244, -244, -244, -244, -244, -244, -244, -244, -244,
+     -244, -244, -244, -244, -244, -244, -244, -244, -244, -244,
+     -244,  246, -244, -244, -244, -244, -244, -244, -244, -244,
+     -244, -244, -244, -244, -244, -244, -244, -244, -244, -244,
+     -244, -244, -244, -244, -244, -244, -244, -244
+    },
+
+    {
+       67, -245, -245, -245, -245, -245, -245, -245, -245, -245,
+     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
+     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
+     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
+     -245, -245, -245, -245, -245, -245,  244, -245,  245,  245,
+
+      245,  245,  245,  245,  245,  245,  245,  245, -245, -245,
+     -245, -245, -245, -245, -245, -245, -245, -245, -245,  246,
+     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
+     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
+     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
+     -245,  246, -245, -245, -245, -245, -245, -245, -245, -245,
+     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
+     -245, -245, -245, -245, -245, -245, -245, -245
+    },
+
+    {
+       67, -246, -246, -246, -246, -246, -246, -246, -246, -246,
+     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
+
+     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
+     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
+     -246, -246, -246,  392, -246,  392, -246, -246,  393,  393,
+      393,  393,  393,  393,  393,  393,  393,  393, -246, -246,
+     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
+     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
+     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
+     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
+     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
+     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
+
+     -246, -246, -246, -246, -246, -246, -246, -246
+    },
+
+    {
+       67,  247,  247,  247,  247,  247,  247,  247,  247,  247,
+      247,  247,  247,  247,  247,  247,  247,  247,  247,  247,
+      247,  247,  247,  247,  247,  247,  247,  247,  247,  247,
+      247,  247,  247,  247,  247,  247,  247,  247,  247,  248,
+      247,  247,  247,  247,  247,  247,  247,  247,  247,  247,
+      247,  247,  247,  247,  247,  247,  247,  247,  247,  247,
+      247,  247,  247,  247,  247,  247,  247,  247,  247,  247,
+      247,  247,  247,  247,  247,  247,  247,  247,  247,  247,
+      247,  247,  247,  247,  247,  247,  247,  247,  247,  247,
+
+      247,  247,  247,  247,  247,  247,  247,  247,  247,  247,
+      247,  247,  247,  247,  247,  247,  247,  247,  247,  247,
+      247,  247,  247,  247,  247,  247,  247,  247,  247,  247,
+      247,  247,  247,  247,  247,  247,  247,  247
+    },
+
+    {
+       67, -248, -248, -248, -248, -248, -248, -248, -248, -248,
+     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
+     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
+     -248, -248, -248, -248, -248, -248, -248, -248, -248,  247,
+     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
+     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
+
+     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
+     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
+     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
+     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
+     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
+     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
+     -248, -248, -248, -248, -248, -248, -248, -248
+    },
+
+    {
+       67, -249, -249, -249, -249, -249, -249, -249, -249, -249,
+     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
+     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
+
+     -249, -249,  249, -249, -249, -249, -249, -249, -249, -249,
+     -249, -249, -249, -249, -249, -249, -249,  250, -249, -249,
+     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
+     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
+     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
+     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
+     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
+     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
+     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
+     -249, -249, -249, -249, -249, -249, -249, -249
+
+    },
+
+    {
+       67,  251,  251,  251,  251,  251,  251,  251,  251,  251,
+     -250,  251,  251,  251,  251,  251,  251,  251,  251,  251,
+      251,  251,  251,  251,  251,  251,  251,  251,  251,  251,
+      251,  251,  251,  251,  251,  251,  251,  251,  251,  251,
+      251,  251,  251,  251,  251,  251,  251,  251,  251,  251,
+      251,  251,  251,  251,  251,  251,  251,  251,  251,  251,
+      251,  251,  251,  251,  251,  251,  251,  251,  251,  251,
+      251,  251,  251,  251,  251,  251,  251,  251,  251,  251,
+      251,  251,  251,  251,  251,  251,  251,  251,  251,  251,
+      251,  251,  251,  251,  251,  251,  251,  251,  251,  251,
+
+      251,  251,  251,  251,  251,  251,  251,  251,  251,  251,
+      251,  251,  251,  251,  251,  251,  251,  251,  251,  251,
+      251,  251,  251,  251,  251,  251,  251,  251
+    },
+
+    {
+       67,  251,  251,  251,  251,  251,  251,  251,  251,  251,
+     -251,  251,  251,  251,  251,  251,  251,  251,  251,  251,
+      251,  251,  251,  251,  251,  251,  251,  251,  251,  251,
+      251,  251,  251,  251,  251,  251,  251,  251,  251,  251,
+      251,  251,  251,  251,  251,  251,  251,  251,  251,  251,
+      251,  251,  251,  251,  251,  251,  251,  251,  251,  251,
+      251,  251,  251,  251,  251,  251,  251,  251,  251,  251,
+
+      251,  251,  251,  251,  251,  251,  251,  251,  251,  251,
+      251,  251,  251,  251,  251,  251,  251,  251,  251,  251,
+      251,  251,  251,  251,  251,  251,  251,  251,  251,  251,
+      251,  251,  251,  251,  251,  251,  251,  251,  251,  251,
+      251,  251,  251,  251,  251,  251,  251,  251,  251,  251,
+      251,  251,  251,  251,  251,  251,  251,  251
+    },
+
+    {
+       67,  252,  252,  252,  252,  252,  252,  252,  252,  252,
+     -252,  252,  252,  252,  252,  252,  252,  252,  252,  252,
+      252,  252,  252,  252,  252,  252,  252,  252,  252,  252,
+      252,  252,  252,  252,  252,  252,  252,  252,  252,  252,
+
+      252,  252,  252,  252,  252,  252,  252,  252,  252,  252,
+      252,  252,  252,  252,  252,  252,  252,  252,  252,  252,
+      252,  252,  252,  252,  252,  252,  252,  252,  252,  252,
+      252,  252,  252,  252,  252,  252,  252,  252,  252,  252,
+      252,  252,  252,  252,  252,  252,  252,  252,  252,  252,
+      252,  252,  252,  252,  252,  252,  252,  252,  252,  252,
+      252,  252,  252,  252,  252,  252,  252,  252,  252,  252,
+      252,  252,  252,  252,  252,  252,  252,  252,  252,  252,
+      252,  252,  252,  252,  252,  252,  252,  252
+    },
+
+    {
+       67,  253,  253,  253,  253,  253,  253,  253,  253,  253,
+
+     -253,  253,  253,  253,  253,  253,  253,  253,  253,  253,
+      253,  253,  253,  253,  253,  253,  253,  253,  253,  253,
+      253,  253,  253,  253,  253,  253,  253,  253,  253,  253,
+      253,  253,  253,  253,  253,  253,  253,  253,  253,  253,
+      253,  253,  253,  253,  253,  253,  253,  253,  253,  253,
+      253,  253,  253,  253,  253,  253,  253,  253,  253,  253,
+      253,  253,  253,  253,  253,  253,  253,  253,  253,  253,
+      253,  253,  253,  253,  253,  253,  253,  253,  253,  253,
+      253,  253,  253,  253,  253,  253,  253,  253,  253,  253,
+      253,  253,  253,  253,  253,  253,  253,  253,  253,  253,
+
+      253,  253,  253,  253,  253,  253,  253,  253,  253,  253,
+      253,  253,  253,  253,  253,  253,  253,  253
+    },
+
+    {
+       67,  254,  254,  254,  254,  254,  254,  254,  254,  254,
+      255,  254,  254,  254,  254,  254,  254,  254,  254,  254,
+      254,  254,  254,  254,  254,  254,  254,  254,  254,  254,
+      254,  254,  254,  254,  254,  254,  254,  254,  254,  254,
+      254,  254,  254,  254,  254,  254,  254,  254,  254,  254,
+      254,  254,  254,  254,  254,  254,  254,  254,  254,  254,
+      254,  254,  254,  254,  254,  254,  254,  254,  254,  254,
+      254,  254,  254,  254,  254,  254,  254,  254,  254,  254,
+
+      254,  254,  254,  254,  254,  254,  254,  254,  254,  254,
+      254,  254,  254,  254,  254,  254,  254,  254,  254,  254,
+      254,  254,  254,  254,  254,  254,  254,  254,  254,  254,
+      254,  254,  254,  254,  254,  254,  254,  254,  254,  254,
+      254,  254,  254,  254,  254,  254,  254,  254
+    },
+
+    {
+       67, -255, -255, -255, -255, -255, -255, -255, -255, -255,
+     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
+     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
+     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
+     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
+
+     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
+     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
+     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
+     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
+     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
+     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
+     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
+     -255, -255, -255, -255, -255, -255, -255, -255
+    },
+
+    {
+       67, -256, -256, -256, -256, -256, -256, -256, -256, -256,
+     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
+
+     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
+     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
+     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
+     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
+     -256, -256, -256, -256, -256, -256, -256, -256,  394, -256,
+     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
+     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
+     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
+     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
+     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
+
+     -256, -256, -256, -256, -256, -256, -256, -256
+    },
+
+    {
+       67, -257, -257, -257, -257, -257, -257, -257, -257, -257,
+     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
+     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
+     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
+     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
+     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
+     -257, -257, -257, -257, -257, -257, -257,  395, -257, -257,
+     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
+     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
+
+     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
+     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
+     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
+     -257, -257, -257, -257, -257, -257, -257, -257
+    },
+
+    {
+       67, -258, -258, -258, -258, -258, -258, -258, -258, -258,
+     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
+     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
+     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
+     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
+     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
+
+     -258, -258, -258, -258, -258, -258, -258, -258, -258,  396,
+     -258, -258, -258, -258, -258, -258,  397, -258, -258, -258,
+     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
+     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
+     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
+     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
+     -258, -258, -258, -258, -258, -258, -258, -258
+    },
+
+    {
+       67, -259, -259, -259, -259, -259, -259, -259, -259, -259,
+     -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
+     -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
+
+     -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
+     -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
+     -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
+     -259, -259, -259, -259, -259,  398, -259, -259, -259, -259,
+     -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
+     -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
+     -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
+     -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
+     -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
+     -259, -259, -259, -259, -259, -259, -259, -259
+
+    },
+
+    {
+       67, -260, -260, -260, -260, -260, -260, -260, -260, -260,
+     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
+     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
+     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
+     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
+     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
+     -260, -260, -260, -260, -260, -260, -260, -260,  399, -260,
+     -260, -260, -260, -260, -260, -260, -260, -260, -260,  400,
+      401, -260, -260, -260, -260, -260,  402, -260, -260, -260,
+     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
+
+     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
+     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
+     -260, -260, -260, -260, -260, -260, -260, -260
+    },
+
+    {
+       67, -261, -261, -261, -261, -261, -261, -261, -261, -261,
+     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
+     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
+     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
+     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
+     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
+     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
+
+     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
+     -261, -261, -261, -261, -261, -261, -261, -261, -261,  403,
+     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
+     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
+     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
+     -261, -261, -261, -261, -261, -261, -261, -261
+    },
+
+    {
+       67, -262, -262, -262, -262, -262, -262, -262, -262, -262,
+     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
+     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
+     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
+
+     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
+     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
+     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
+     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
+     -262, -262, -262, -262, -262, -262, -262, -262, -262,  404,
+     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
+     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
+     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
+     -262, -262, -262, -262, -262, -262, -262, -262
+    },
+
+    {
+       67, -263, -263, -263, -263, -263, -263, -263, -263, -263,
+
+     -263, -263, -263, -263, -263, -263, -263, -263, -263, -263,
+     -263, -263, -263, -263, -263, -263, -263, -263, -263, -263,
+     -263, -263, -263, -263, -263, -263, -263, -263, -263, -263,
+     -263, -263, -263, -263, -263, -263, -263, -263, -263, -263,
+     -263, -263, -263, -263, -263, -263, -263, -263, -263, -263,
+     -263, -263, -263, -263, -263, -263, -263, -263, -263, -263,
+     -263, -263, -263, -263, -263, -263, -263, -263,  405, -263,
+     -263, -263, -263, -263, -263, -263, -263, -263, -263, -263,
+     -263, -263, -263, -263, -263, -263, -263, -263, -263, -263,
+     -263, -263, -263, -263, -263, -263, -263, -263, -263, -263,
+
+     -263, -263, -263, -263, -263, -263, -263, -263, -263, -263,
+     -263, -263, -263, -263, -263, -263, -263, -263
+    },
+
+    {
+       67, -264, -264, -264, -264, -264, -264, -264, -264, -264,
+     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
+     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
+     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
+     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
+     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
+     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
+     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
+
+     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
+     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
+     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
+     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
+     -264, -264, -264, -264, -264, -264, -264, -264
+    },
+
+    {
+       67, -265, -265, -265, -265, -265, -265, -265, -265, -265,
+     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
+     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
+     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
+     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
+
+     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
+     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
+     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
+     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
+     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
+     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
+     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
+     -265, -265, -265, -265, -265, -265, -265, -265
+    },
+
+    {
+       67, -266, -266, -266, -266, -266, -266, -266, -266, -266,
+     -266, -266, -266, -266, -266, -266, -266, -266, -266, -266,
+
+     -266, -266, -266, -266, -266, -266, -266, -266, -266, -266,
+     -266, -266, -266, -266, -266, -266, -266, -266, -266, -266,
+     -266, -266, -266, -266, -266, -266, -266, -266, -266, -266,
+     -266, -266, -266, -266, -266, -266, -266, -266, -266, -266,
+     -266, -266, -266, -266, -266, -266, -266, -266, -266, -266,
+     -266, -266, -266, -266, -266, -266,  406, -266, -266, -266,
+     -266, -266, -266, -266, -266, -266, -266, -266, -266, -266,
+     -266, -266, -266, -266, -266, -266, -266, -266, -266, -266,
+     -266, -266, -266, -266, -266, -266, -266, -266, -266, -266,
+     -266, -266, -266, -266, -266, -266, -266, -266, -266, -266,
+
+     -266, -266, -266, -266, -266, -266, -266, -266
+    },
+
+    {
+       67, -267, -267, -267, -267, -267, -267, -267, -267, -267,
+     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
+     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
+     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
+     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
+     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
+     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
+     -267, -267, -267, -267, -267, -267, -267,  407, -267, -267,
+     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
+
+     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
+     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
+     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
+     -267, -267, -267, -267, -267, -267, -267, -267
+    },
+
+    {
+       67, -268, -268, -268, -268, -268, -268, -268, -268, -268,
+     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
+     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
+     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
+     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
+     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
+
+     -268, -268, -268, -268, -268, -268, -268, -268, -268,  408,
+     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
+     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
+     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
+     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
+     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
+     -268, -268, -268, -268, -268, -268, -268, -268
+    },
+
+    {
+       67, -269, -269, -269, -269, -269, -269, -269, -269, -269,
+     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
+     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
+
+     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
+     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
+     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
+     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
+     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
+     -269, -269, -269, -269,  409, -269, -269, -269, -269, -269,
+     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
+     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
+     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
+     -269, -269, -269, -269, -269, -269, -269, -269
+
+    },
+
+    {
+       67, -270, -270, -270, -270, -270, -270, -270, -270, -270,
+     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
+     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
+     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
+     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
+     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
+     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
+     -270, -270, -270,  410, -270, -270, -270, -270, -270, -270,
+     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
+     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
+
+     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
+     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
+     -270, -270, -270, -270, -270, -270, -270, -270
+    },
+
+    {
+       67, -271, -271, -271, -271, -271, -271, -271, -271, -271,
+     -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
+     -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
+     -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
+     -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
+     -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
+     -271, -271, -271, -271, -271,  411, -271, -271, -271, -271,
+
+     -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
+     -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
+     -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
+     -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
+     -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
+     -271, -271, -271, -271, -271, -271, -271, -271
+    },
+
+    {
+       67, -272, -272, -272, -272, -272, -272, -272, -272, -272,
+     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
+     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
+     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
+
+     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
+     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
+     -272, -272, -272, -272, -272, -272, -272, -272, -272,  412,
+     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
+     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
+     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
+     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
+     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
+     -272, -272, -272, -272, -272, -272, -272, -272
+    },
+
+    {
+       67, -273, -273, -273, -273, -273, -273, -273, -273, -273,
+
+     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
+     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
+     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
+     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
+     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
+     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
+     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
+      413, -273, -273, -273, -273, -273, -273, -273, -273, -273,
+     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
+     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
+
+     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
+     -273, -273, -273, -273, -273, -273, -273, -273
+    },
+
+    {
+       67, -274, -274, -274, -274, -274, -274, -274, -274, -274,
+     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
+     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
+     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
+     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
+     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
+     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
+     -274, -274, -274,  414, -274, -274, -274, -274, -274, -274,
+
+     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
+     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
+     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
+     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
+     -274, -274, -274, -274, -274, -274, -274, -274
+    },
+
+    {
+       67, -275, -275, -275, -275, -275, -275, -275, -275, -275,
+     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
+     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
+     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
+     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
+
+     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
+     -275, -275, -275, -275, -275, -275, -275, -275, -275,  415,
+     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
+     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
+     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
+     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
+     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
+     -275, -275, -275, -275, -275, -275, -275, -275
+    },
+
+    {
+       67, -276, -276, -276, -276, -276, -276, -276, -276, -276,
+     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
+
+     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
+     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
+     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
+     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
+     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
+     -276,  416, -276, -276, -276, -276, -276, -276, -276, -276,
+     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
+     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
+     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
+     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
+
+     -276, -276, -276, -276, -276, -276, -276, -276
+    },
+
+    {
+       67, -277, -277, -277, -277, -277, -277, -277, -277, -277,
+     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
+     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
+     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
+     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
+     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
+     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
+     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
+     -277, -277, -277,  417, -277, -277, -277, -277, -277, -277,
+
+     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
+     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
+     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
+     -277, -277, -277, -277, -277, -277, -277, -277
+    },
+
+    {
+       67, -278, -278, -278, -278, -278, -278, -278, -278, -278,
+     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
+     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
+     -278, -278,  418, -278, -278, -278, -278, -278, -278, -278,
+     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
+     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
+
+     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
+     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
+     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
+     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
+     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
+     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
+     -278, -278, -278, -278, -278, -278, -278, -278
+    },
+
+    {
+       67, -279, -279, -279, -279, -279, -279, -279, -279, -279,
+     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
+     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
+
+     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
+     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
+     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
+     -279, -279, -279, -279, -279, -279, -279,  419, -279, -279,
+     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
+     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
+     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
+     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
+     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
+     -279, -279, -279, -279, -279, -279, -279, -279
+
+    },
+
+    {
+       67, -280, -280, -280, -280, -280, -280, -280, -280, -280,
+     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
+     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
+     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
+     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
+     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
+     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
+     -280, -280, -280,  420, -280, -280, -280, -280, -280, -280,
+     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
+     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
+
+     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
+     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
+     -280, -280, -280, -280, -280, -280, -280, -280
+    },
+
+    {
+       67, -281, -281, -281, -281, -281, -281, -281, -281, -281,
+     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
+     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
+     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
+     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
+     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
+     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
+
+     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
+      421, -281, -281, -281, -281, -281, -281, -281, -281, -281,
+     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
+     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
+     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
+     -281, -281, -281, -281, -281, -281, -281, -281
+    },
+
+    {
+       67, -282, -282, -282, -282, -282, -282, -282, -282, -282,
+     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
+     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
+     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
+
+     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
+     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
+     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
+     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
+      422, -282, -282, -282, -282, -282, -282, -282, -282, -282,
+     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
+     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
+     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
+     -282, -282, -282, -282, -282, -282, -282, -282
+    },
+
+    {
+       67, -283, -283, -283, -283, -283, -283, -283, -283, -283,
+
+     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
+     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
+     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
+     -283, -283, -283, -283, -283,  423, -283, -283, -283, -283,
+     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
+     -283, -283, -283, -283, -283,  424, -283, -283, -283, -283,
+     -283, -283, -283, -283, -283, -283, -283, -283, -283,  425,
+     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
+     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
+     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
+
+     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
+     -283, -283, -283, -283, -283, -283, -283, -283
+    },
+
+    {
+       67, -284, -284, -284, -284, -284, -284, -284, -284, -284,
+     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
+     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
+     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
+     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
+     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
+     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
+     -284,  426, -284, -284, -284, -284, -284, -284, -284, -284,
+
+     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
+     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
+     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
+     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
+     -284, -284, -284, -284, -284, -284, -284, -284
+    },
+
+    {
+       67, -285, -285, -285, -285, -285, -285, -285, -285, -285,
+     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
+     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
+     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
+     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
+
+     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
+     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
+     -285, -285, -285, -285,  427, -285, -285, -285, -285, -285,
+     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
+     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
+     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
+     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
+     -285, -285, -285, -285, -285, -285, -285, -285
+    },
+
+    {
+       67, -286, -286, -286, -286, -286, -286, -286, -286, -286,
+     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
+
+     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
+     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
+     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
+     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
+     -286, -286, -286, -286, -286, -286, -286, -286, -286,  428,
+     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
+     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
+     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
+     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
+     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
+
+     -286, -286, -286, -286, -286, -286, -286, -286
+    },
+
+    {
+       67, -287, -287, -287, -287, -287, -287, -287, -287, -287,
+     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
+     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
+     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
+     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
+     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
+     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
+     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
+     -287, -287, -287, -287,  429, -287, -287, -287, -287, -287,
+
+     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
+     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
+     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
+     -287, -287, -287, -287, -287, -287, -287, -287
+    },
+
+    {
+       67, -288, -288, -288, -288, -288, -288, -288, -288, -288,
+     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
+     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
+     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
+     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
+     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
+
+     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
+     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
+     -288,  430, -288, -288, -288, -288, -288, -288, -288, -288,
+     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
+     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
+     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
+     -288, -288, -288, -288, -288, -288, -288, -288
+    },
+
+    {
+       67, -289, -289, -289, -289, -289, -289, -289, -289, -289,
+     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
+     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
+
+     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
+     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
+     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
+     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
+     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
+     -289, -289, -289, -289, -289, -289,  431, -289, -289, -289,
+     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
+     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
+     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
+     -289, -289, -289, -289, -289, -289, -289, -289
+
+    },
+
+    {
+       67, -290, -290, -290, -290, -290, -290, -290, -290, -290,
+     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
+     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
+     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
+     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
+     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
+     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
+     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
+     -290, -290, -290,  432, -290, -290, -290, -290, -290, -290,
+     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
+
+     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
+     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
+     -290, -290, -290, -290, -290, -290, -290, -290
+    },
+
+    {
+       67, -291, -291, -291, -291, -291, -291, -291, -291, -291,
+     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
+     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
+     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
+     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
+     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
+     -291, -291, -291, -291, -291, -291, -291,  433, -291, -291,
+
+     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
+     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
+     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
+     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
+     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
+     -291, -291, -291, -291, -291, -291, -291, -291
+    },
+
+    {
+       67, -292, -292, -292, -292, -292, -292, -292, -292, -292,
+     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
+     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
+     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
+
+     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
+     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
+     -292, -292, -292, -292, -292, -292, -292,  434, -292, -292,
+     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
+     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
+     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
+     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
+     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
+     -292, -292, -292, -292, -292, -292, -292, -292
+    },
+
+    {
+       67, -293, -293, -293, -293, -293, -293, -293, -293, -293,
+
+     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
+     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
+     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
+     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
+     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
+     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
+     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
+     -293, -293, -293,  435, -293, -293, -293, -293, -293, -293,
+     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
+     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
+
+     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
+     -293, -293, -293, -293, -293, -293, -293, -293
+    },
+
+    {
+       67, -294, -294, -294, -294, -294, -294, -294, -294, -294,
+     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
+     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
+     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
+     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
+     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
+     -294, -294, -294, -294, -294, -294, -294, -294, -294,  436,
+     -294, -294, -294, -294, -294, -294,  437, -294, -294, -294,
+
+     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
+     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
+     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
+     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
+     -294, -294, -294, -294, -294, -294, -294, -294
+    },
+
+    {
+       67, -295, -295, -295, -295, -295, -295, -295, -295, -295,
+     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
+     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
+     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
+     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
+
+     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
+     -295, -295, -295, -295, -295,  438, -295, -295, -295, -295,
+     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
+     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
+     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
+     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
+     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
+     -295, -295, -295, -295, -295, -295, -295, -295
+    },
+
+    {
+       67, -296, -296, -296, -296, -296, -296, -296, -296, -296,
+     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
+
+     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
+     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
+     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
+     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
+     -296, -296, -296, -296, -296, -296, -296, -296,  439, -296,
+     -296, -296, -296, -296, -296, -296, -296, -296, -296,  440,
+      441, -296, -296, -296, -296, -296,  442, -296, -296, -296,
+     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
+     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
+     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
+
+     -296, -296, -296, -296, -296, -296, -296, -296
+    },
+
+    {
+       67, -297, -297, -297, -297, -297, -297, -297, -297, -297,
+     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
+     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
+     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
+     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
+     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
+     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
+     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
+     -297, -297, -297, -297, -297, -297, -297, -297, -297,  443,
+
+     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
+     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
+     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
+     -297, -297, -297, -297, -297, -297, -297, -297
+    },
+
+    {
+       67, -298, -298, -298, -298, -298, -298, -298, -298, -298,
+     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
+     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
+     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
+     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
+     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
+
+     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
+     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
+     -298, -298, -298, -298, -298, -298, -298, -298, -298,  444,
+     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
+     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
+     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
+     -298, -298, -298, -298, -298, -298, -298, -298
+    },
+
+    {
+       67, -299, -299, -299, -299, -299, -299, -299, -299, -299,
+     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
+     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
+
+     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
+     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
+     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
+     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
+     -299, -299, -299, -299, -299, -299, -299, -299,  445, -299,
+     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
+     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
+     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
+     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
+     -299, -299, -299, -299, -299, -299, -299, -299
+
+    },
+
+    {
+       67, -300, -300, -300, -300, -300, -300, -300, -300, -300,
+     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
+     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
+     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
+     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
+     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
+     -300, -300, -300, -300, -300, -300, -300, -300, -300,  446,
+     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
+     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
+     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
+
+     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
+     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
+     -300, -300, -300, -300, -300, -300, -300, -300
+    },
+
+    {
+       67, -301, -301, -301, -301, -301, -301, -301, -301, -301,
+     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
+     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
+     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
+     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
+     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
+     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
+
+     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
+     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
+     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
+     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
+     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
+     -301, -301, -301, -301, -301, -301, -301, -301
+    },
+
+    {
+       67, -302, -302, -302, -302, -302, -302, -302, -302, -302,
+     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
+     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
+     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
+
+     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
+     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
+     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
+     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
+     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
+     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
+     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
+     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
+     -302, -302, -302, -302, -302, -302, -302, -302
+    },
+
+    {
+       67, -303, -303, -303, -303, -303, -303, -303, -303, -303,
+
+     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
+     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
+     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
+     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
+     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
+     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
+     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
+     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
+     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
+     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
+
+     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
+     -303, -303, -303, -303, -303, -303, -303, -303
+    },
+
+    {
+       67, -304, -304, -304, -304, -304, -304, -304, -304, -304,
+     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
+     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
+     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
+     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
+     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
+     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
+     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
+
+     -304, -304, -304,  447, -304, -304, -304, -304, -304, -304,
+     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
+     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
+     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
+     -304, -304, -304, -304, -304, -304, -304, -304
+    },
+
+    {
+       67, -305, -305, -305, -305, -305, -305, -305, -305, -305,
+     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
+     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
+     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
+     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
+
+     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
+     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
+     -305,  448, -305, -305, -305, -305, -305, -305, -305, -305,
+     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
+     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
+     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
+     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
+     -305, -305, -305, -305, -305, -305, -305, -305
+    },
+
+    {
+       67, -306, -306, -306, -306, -306, -306, -306, -306, -306,
+     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
+
+     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
+     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
+     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
+     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
+     -306, -306, -306, -306, -306,  449, -306, -306, -306, -306,
+     -306, -306, -306, -306, -306, -306, -306, -306, -306,  450,
+     -306, -306,  451, -306, -306, -306, -306, -306, -306, -306,
+     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
+     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
+     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
+
+     -306, -306, -306, -306, -306, -306, -306, -306
+    },
+
+    {
+       67, -307, -307, -307, -307, -307, -307, -307, -307, -307,
+     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
+     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
+     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
+     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
+     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
+     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
+     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
+     -307, -307, -307, -307, -307,  452, -307, -307, -307, -307,
+
+     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
+     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
+     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
+     -307, -307, -307, -307, -307, -307, -307, -307
+    },
+
+    {
+       67, -308, -308, -308, -308, -308, -308, -308, -308, -308,
+     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
+     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
+     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
+     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
+     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
+
+     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
+     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
+     -308, -308, -308,  453, -308, -308, -308, -308, -308, -308,
+     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
+     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
+     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
+     -308, -308, -308, -308, -308, -308, -308, -308
+    },
+
+    {
+       67, -309, -309, -309, -309, -309, -309, -309, -309, -309,
+     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
+     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
+
+     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
+     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
+     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
+     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
+     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
+     -309, -309, -309, -309, -309, -309, -309, -309,  454, -309,
+     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
+     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
+     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
+     -309, -309, -309, -309, -309, -309, -309, -309
+
+    },
+
+    {
+       67, -310, -310, -310, -310, -310, -310, -310, -310, -310,
+     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
+     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
+     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
+     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
+     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
+     -310, -310, -310, -310, -310,  455, -310, -310, -310, -310,
+     -310, -310, -310, -310, -310, -310, -310, -310,  456, -310,
+     -310, -310, -310, -310,  457, -310, -310, -310,  458, -310,
+     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
+
+     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
+     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
+     -310, -310, -310, -310, -310, -310, -310, -310
+    },
+
+    {
+       67, -311, -311, -311, -311, -311, -311, -311, -311, -311,
+     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
+     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
+     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
+     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
+     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
+     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
+
+     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
+     -311, -311, -311, -311, -311,  459, -311, -311, -311, -311,
+     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
+     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
+     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
+     -311, -311, -311, -311, -311, -311, -311, -311
+    },
+
+    {
+       67, -312, -312, -312, -312, -312, -312, -312, -312, -312,
+     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
+     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
+     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
+
+     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
+     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
+     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
+     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
+     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
+     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
+     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
+     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
+     -312, -312, -312, -312, -312, -312, -312, -312
+    },
+
+    {
+       67, -313, -313, -313, -313, -313, -313, -313, -313, -313,
+
+     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
+     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
+     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
+     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
+     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
+     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
+     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
+     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
+     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
+     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
+
+     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
+     -313, -313, -313, -313, -313, -313, -313, -313
+    },
+
+    {
+       67, -314, -314, -314, -314, -314, -314, -314, -314, -314,
+     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
+     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
+     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
+     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
+     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
+     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
+     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
+
+     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
+     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
+     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
+     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
+     -314, -314, -314, -314, -314, -314, -314, -314
+    },
+
+    {
+       67, -315, -315, -315, -315, -315, -315, -315, -315, -315,
+     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
+     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
+     -315, -315,  460, -315, -315, -315, -315, -315, -315, -315,
+     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
+
+     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
+     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
+     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
+     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
+     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
+     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
+     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
+     -315, -315, -315, -315, -315, -315, -315, -315
+    },
+
+    {
+       67, -316, -316, -316, -316, -316, -316, -316, -316, -316,
+     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
+
+     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
+     -316, -316,  461, -316, -316, -316, -316, -316, -316, -316,
+     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
+     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
+     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
+     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
+     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
+     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
+     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
+     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
+
+     -316, -316, -316, -316, -316, -316, -316, -316
+    },
+
+    {
+       67, -317, -317, -317, -317, -317, -317, -317, -317, -317,
+     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
+     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
+     -317, -317,  462, -317, -317, -317, -317, -317, -317, -317,
+     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
+     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
+     -317, -317, -317, -317, -317,  462,  462,  462,  462,  462,
+      462,  462,  462,  462,  462,  462,  462,  462,  462,  462,
+      462,  462,  462,  462,  462,  462,  462,  462,  462,  462,
+
+      462, -317, -317, -317, -317, -317, -317, -317, -317, -317,
+     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
+     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
+     -317, -317, -317, -317, -317, -317, -317, -317
+    },
+
+    {
+       67, -318, -318, -318, -318, -318, -318, -318, -318, -318,
+     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
+     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
+     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
+     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
+     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
+
+     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
+     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
+     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
+     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
+     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
+     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
+     -318, -318, -318, -318, -318, -318, -318, -318
+    },
+
+    {
+       67, -319, -319, -319, -319, -319, -319, -319, -319, -319,
+     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
+     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
+
+     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
+     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
+     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
+     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
+     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
+     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
+     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
+     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
+     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
+     -319, -319, -319, -319, -319, -319, -319, -319
+
+    },
+
+    {
+       67, -320, -320, -320, -320, -320, -320, -320, -320, -320,
+     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
+     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
+     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
+     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
+     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
+     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
+     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
+     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
+     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
+
+     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
+     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
+     -320, -320, -320, -320, -320, -320, -320, -320
+    },
+
+    {
+       67, -321, -321, -321, -321, -321, -321, -321, -321, -321,
+     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
+     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
+     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
+     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
+     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
+     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
+
+     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
+     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
+     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
+     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
+     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
+     -321, -321, -321, -321, -321, -321, -321, -321
+    },
+
+    {
+       67, -322, -322, -322, -322, -322, -322, -322, -322, -322,
+     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
+     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
+     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
+
+     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
+     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
+     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
+     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
+     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
+     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
+     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
+     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
+     -322, -322, -322, -322, -322, -322, -322, -322
+    },
+
+    {
+       67, -323, -323, -323, -323, -323, -323, -323, -323, -323,
+
+     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
+     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
+     -323, -323,  463, -323, -323, -323, -323, -323, -323, -323,
+     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
+     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
+     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
+     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
+     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
+     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
+     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
+
+     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
+     -323, -323, -323, -323, -323, -323, -323, -323
+    },
+
+    {
+       67, -324, -324, -324, -324, -324, -324, -324, -324, -324,
+     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
+     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
+     -324, -324,  464, -324, -324, -324, -324, -324, -324, -324,
+     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
+     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
+     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
+     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
+
+     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
+     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
+     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
+     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
+     -324, -324, -324, -324, -324, -324, -324, -324
+    },
+
+    {
+       67, -325, -325, -325, -325, -325, -325, -325, -325, -325,
+     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
+     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
+     -325, -325,  465, -325, -325, -325, -325, -325, -325, -325,
+     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
+
+     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
+     -325, -325, -325, -325, -325,  465,  465,  465,  465,  465,
+      465,  465,  465,  465,  465,  465,  465,  465,  465,  465,
+      465,  465,  465,  465,  465,  465,  465,  465,  465,  465,
+      465, -325, -325, -325, -325, -325, -325, -325, -325, -325,
+     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
+     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
+     -325, -325, -325, -325, -325, -325, -325, -325
+    },
+
+    {
+       67, -326, -326, -326, -326, -326, -326, -326, -326, -326,
+     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
+
+     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
+     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
+     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
+     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
+     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
+     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
+     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
+     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
+     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
+     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
+
+     -326, -326, -326, -326, -326, -326, -326, -326
+    },
+
+    {
+       67, -327, -327, -327, -327, -327, -327, -327, -327, -327,
+     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
+     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
+     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
+     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
+     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
+     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
+     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
+     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
+
+     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
+     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
+     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
+     -327, -327, -327, -327, -327, -327, -327, -327
+    },
+
+    {
+       67, -328, -328, -328, -328, -328, -328, -328, -328, -328,
+     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
+     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
+     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
+     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
+     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
+
+     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
+     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
+     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
+     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
+     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
+     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
+     -328, -328, -328, -328, -328, -328, -328, -328
+    },
+
+    {
+       67, -329, -329, -329, -329, -329, -329, -329, -329, -329,
+     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
+     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
+
+     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
+     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
+     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
+     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
+     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
+     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
+     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
+     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
+     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
+     -329, -329, -329, -329, -329, -329, -329, -329
+
+    },
+
+    {
+       67, -330, -330, -330, -330, -330, -330, -330, -330, -330,
+     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
+     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
+     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
+     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
+     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
+     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
+     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
+     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
+     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
+
+     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
+     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
+     -330, -330, -330, -330, -330, -330, -330, -330
+    },
+
+    {
+       67, -331, -331, -331, -331, -331, -331, -331, -331, -331,
+     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
+     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
+     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
+     -331, -331, -331, -331, -331, -331, -331, -331,  466,  466,
+      466,  466,  466,  466,  466,  466,  466,  466, -331, -331,
+     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
+
+     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
+     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
+     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
+     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
+     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
+     -331, -331, -331, -331, -331, -331, -331, -331
+    },
+
+    {
+       67, -332, -332, -332, -332, -332, -332, -332, -332, -332,
+     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
+     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
+     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
+
+     -332, -332, -332, -332, -332, -332, -332, -332,  467,  467,
+      467,  467,  467,  467,  467,  467,  467,  467, -332, -332,
+     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
+     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
+     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
+     -332, -332, -332, -332, -332,  468, -332, -332, -332, -332,
+     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
+     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
+     -332, -332, -332, -332, -332, -332, -332, -332
+    },
+
+    {
+       67, -333, -333, -333, -333, -333, -333, -333, -333, -333,
+
+     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
+     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
+     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
+     -333, -333, -333, -333, -333, -333, -333, -333, -333,  469,
+      469,  469,  469,  469,  469,  469,  469,  469, -333, -333,
+     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
+     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
+     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
+     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
+     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
+
+     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
+     -333, -333, -333, -333, -333, -333, -333, -333
+    },
+
+    {
+       67, -334, -334, -334, -334, -334, -334, -334, -334, -334,
+     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
+     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
+     -334, -334,  470, -334, -334, -334, -334, -334, -334, -334,
+     -334, -334, -334, -334, -334, -334, -334, -334,  471,  471,
+      471,  471,  471,  471,  471,  471,  471,  471, -334, -334,
+     -334, -334, -334, -334, -334,  470,  470,  470,  470,  470,
+      470,  470,  470,  470,  470,  470,  470,  470,  470,  470,
+
+      470,  470,  470,  470,  470,  470,  470,  470,  470,  470,
+      470, -334, -334, -334, -334, -334, -334, -334, -334, -334,
+     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
+     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
+     -334, -334, -334, -334, -334, -334, -334, -334
+    },
+
+    {
+       67, -335, -335, -335, -335, -335, -335, -335, -335, -335,
+     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
+     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
+     -335, -335,  472, -335, -335, -335, -335, -335, -335, -335,
+     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
+
+     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
+     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
+     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
+     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
+     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
+     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
+     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
+     -335, -335, -335, -335, -335, -335, -335, -335
+    },
+
+    {
+       67, -336, -336, -336, -336, -336, -336, -336, -336, -336,
+     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
+
+     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
+     -336, -336,  473, -336, -336, -336, -336, -336, -336, -336,
+     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
+     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
+     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
+     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
+     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
+     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
+     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
+     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
+
+     -336, -336, -336, -336, -336, -336, -336, -336
+    },
+
+    {
+       67, -337, -337, -337, -337, -337, -337, -337, -337, -337,
+     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
+     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
+     -337, -337,  474, -337, -337, -337, -337, -337, -337, -337,
+     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
+     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
+     -337, -337, -337, -337, -337,  474,  474,  474,  474,  474,
+      474,  474,  474,  474,  474,  474,  474,  474,  474,  474,
+      474,  474,  474,  474,  474,  474,  474,  474,  474,  474,
+
+      474, -337, -337, -337, -337, -337, -337, -337, -337, -337,
+     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
+     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
+     -337, -337, -337, -337, -337, -337, -337, -337
+    },
+
+    {
+       67, -338, -338, -338, -338, -338, -338, -338, -338, -338,
+     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
+     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
+     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
+     -338, -338, -338, -338, -338, -338, -338, -338,  475,  475,
+      475,  475,  475,  475,  475,  475,  475,  475, -338, -338,
+
+     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
+     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
+     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
+     -338, -338, -338, -338, -338,  476, -338, -338, -338, -338,
+     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
+     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
+     -338, -338, -338, -338, -338, -338, -338, -338
+    },
+
+    {
+       67, -339, -339, -339, -339, -339, -339, -339, -339, -339,
+     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
+     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
+
+     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
+     -339, -339, -339, -339, -339, -339, -339, -339, -339,  477,
+      477,  477,  477,  477,  477,  477,  477,  477, -339, -339,
+     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
+     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
+     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
+     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
+     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
+     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
+     -339, -339, -339, -339, -339, -339, -339, -339
+
+    },
+
+    {
+       67, -340, -340, -340, -340, -340, -340, -340, -340, -340,
+     -340, -340, -340, -340, -340, -340, -340, -340, -340, -340,
+     -340, -340, -340, -340, -340, -340, -340, -340, -340, -340,
+     -340, -340,  478, -340, -340, -340, -340, -340, -340, -340,
+     -340, -340, -340, -340, -340, -340, -340, -340,  479,  479,
+      479,  479,  479,  479,  479,  479,  479,  479, -340, -340,
+     -340, -340, -340, -340, -340,  478,  478,  478,  478,  478,
+      478,  478,  478,  478,  478,  478,  478,  478,  478,  478,
+      478,  478,  478,  478,  478,  478,  478,  478,  478,  478,
+      478, -340, -340, -340, -340, -340, -340, -340, -340, -340,
+
+     -340, -340, -340, -340, -340, -340, -340, -340, -340, -340,
+     -340, -340, -340, -340, -340, -340, -340, -340, -340, -340,
+     -340, -340, -340, -340, -340, -340, -340, -340
+    },
+
+    {
+       67, -341, -341, -341, -341, -341, -341, -341, -341, -341,
+     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
+     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
+     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
+     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
+     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
+     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
+
+     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
+     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
+     -341, -341, -341, -341, -341,  480, -341, -341, -341, -341,
+     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
+     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
+     -341, -341, -341, -341, -341, -341, -341, -341
+    },
+
+    {
+       67, -342, -342, -342, -342, -342, -342, -342, -342, -342,
+     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
+     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
+     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
+
+     -342, -342, -342, -342, -342, -342, -342, -342, -342,  481,
+      481,  481,  481,  481,  481,  481,  481,  481, -342, -342,
+     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
+     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
+     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
+     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
+     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
+     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
+     -342, -342, -342, -342, -342, -342, -342, -342
+    },
+
+    {
+       67, -343, -343, -343, -343, -343, -343, -343, -343, -343,
+
+     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
+     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
+     -343, -343,  482, -343, -343, -343, -343, -343, -343, -343,
+     -343, -343, -343, -343, -343, -343, -343, -343,  483,  483,
+      483,  483,  483,  483,  483,  483,  483,  483, -343, -343,
+     -343, -343, -343, -343, -343,  482,  482,  482,  482,  482,
+      482,  482,  482,  482,  482,  482,  482,  482,  482,  482,
+      482,  482,  482,  482,  482,  482,  482,  482,  482,  482,
+      482, -343, -343, -343, -343, -343, -343, -343, -343, -343,
+     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
+
+     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
+     -343, -343, -343, -343, -343, -343, -343, -343
+    },
+
+    {
+       67, -344, -344, -344, -344, -344, -344, -344, -344, -344,
+     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
+     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
+     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
+     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
+     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
+     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
+     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
+
+     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
+     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
+     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
+     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
+     -344, -344, -344, -344, -344, -344, -344, -344
+    },
+
+    {
+       67, -345, -345, -345, -345, -345, -345, -345, -345, -345,
+     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
+     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
+     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
+     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
+
+     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
+     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
+     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
+     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
+     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
+     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
+     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
+     -345, -345, -345, -345, -345, -345, -345, -345
+    },
+
+    {
+       67, -346, -346, -346, -346, -346, -346, -346, -346, -346,
+     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
+
+     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
+     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
+     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
+     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
+     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
+     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
+     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
+     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
+     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
+     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
+
+     -346, -346, -346, -346, -346, -346, -346, -346
+    },
+
+    {
+       67, -347, -347, -347, -347, -347, -347, -347, -347, -347,
+     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
+     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
+     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
+     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
+     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
+     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
+     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
+     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
+
+     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
+     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
+     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
+     -347, -347, -347, -347, -347, -347, -347, -347
+    },
+
+    {
+       67, -348, -348, -348, -348, -348, -348, -348, -348, -348,
+     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
+     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
+     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
+     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
+     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
+
+     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
+     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
+     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
+     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
+     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
+     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
+     -348, -348, -348, -348, -348, -348, -348, -348
+    },
+
+    {
+       67, -349, -349, -349, -349, -349, -349, -349, -349, -349,
+     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
+     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
+
+     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
+     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
+     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
+     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
+     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
+     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
+     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
+     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
+     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
+     -349, -349, -349, -349, -349, -349, -349, -349
+
+    },
+
+    {
+       67, -350, -350, -350, -350, -350, -350, -350, -350, -350,
+     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
+     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
+     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
+     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
+     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
+     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
+     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
+     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
+     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
+
+     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
+     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
+     -350, -350, -350, -350, -350, -350, -350, -350
+    },
+
+    {
+       67, -351, -351, -351, -351, -351, -351, -351, -351, -351,
+     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
+     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
+     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
+     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
+     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
+     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
+
+     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
+     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
+     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
+     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
+     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
+     -351, -351, -351, -351, -351, -351, -351, -351
+    },
+
+    {
+       67, -352, -352, -352, -352, -352, -352, -352, -352, -352,
+     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
+     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
+     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
+
+     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
+     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
+     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
+     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
+     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
+     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
+     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
+     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
+     -352, -352, -352, -352, -352, -352, -352, -352
+    },
+
+    {
+       67, -353, -353, -353, -353, -353, -353, -353, -353, -353,
+
+     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
+     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
+     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
+     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
+     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
+     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
+     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
+     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
+     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
+     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
+
+     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
+     -353, -353, -353, -353, -353, -353, -353, -353
+    },
+
+    {
+       67, -354, -354, -354, -354, -354, -354, -354, -354, -354,
+     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
+     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
+     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
+     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
+     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
+     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
+     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
+
+     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
+     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
+     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
+     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
+     -354, -354, -354, -354, -354, -354, -354, -354
+    },
+
+    {
+       67, -355, -355, -355, -355, -355, -355, -355, -355, -355,
+     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
+     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
+     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
+     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
+
+     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
+     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
+     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
+     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
+     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
+     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
+     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
+     -355, -355, -355, -355, -355, -355, -355, -355
+    },
+
+    {
+       67, -356, -356, -356, -356, -356, -356, -356, -356, -356,
+     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
+
+     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
+     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
+     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
+     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
+     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
+     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
+     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
+     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
+     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
+     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
+
+     -356, -356, -356, -356, -356, -356, -356, -356
+    },
+
+    {
+       67, -357, -357, -357, -357, -357, -357, -357, -357, -357,
+     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
+     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
+     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
+     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
+     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
+     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
+     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
+     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
+
+     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
+     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
+     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
+     -357, -357, -357, -357, -357, -357, -357, -357
+    },
+
+    {
+       67, -358, -358, -358, -358, -358, -358, -358, -358, -358,
+     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
+     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
+     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
+     -358, -358, -358, -358, -358, -358, -358, -358,  484,  484,
+      484,  484,  484,  484,  484,  484,  484,  484, -358, -358,
+
+     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
+     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
+     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
+     -358, -358, -358, -358, -358,  485, -358, -358, -358, -358,
+     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
+     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
+     -358, -358, -358, -358, -358, -358, -358, -358
+    },
+
+    {
+       67, -359, -359, -359, -359, -359, -359, -359, -359, -359,
+     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
+     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
+
+     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
+     -359, -359, -359, -359, -359, -359, -359, -359,  486,  487,
+      487,  487,  487,  487,  487,  487,  487,  487, -359, -359,
+     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
+     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
+     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
+     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
+     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
+     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
+     -359, -359, -359, -359, -359, -359, -359, -359
+
+    },
+
+    {
+       67, -360, -360, -360, -360, -360, -360, -360, -360, -360,
+     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
+     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
+     -360, -360,  488, -360, -360, -360, -360, -360, -360, -360,
+     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
+     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
+     -360, -360, -360, -360, -360,  488,  488,  488,  488,  488,
+      488,  488,  488,  488,  488,  488,  488,  488,  488,  488,
+      488,  488,  488,  488,  488,  488,  488,  488,  488,  488,
+      488, -360, -360, -360, -360, -360, -360, -360, -360, -360,
+
+     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
+     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
+     -360, -360, -360, -360, -360, -360, -360, -360
+    },
+
+    {
+       67, -361, -361, -361, -361, -361, -361, -361, -361, -361,
+     -361, -361, -361, -361, -361, -361, -361, -361, -361, -361,
+     -361, -361, -361, -361, -361, -361, -361, -361, -361, -361,
+     -361, -361,  488, -361, -361, -361, -361, -361, -361, -361,
+     -361, -361, -361, -361, -361, -361, -361, -361,  489,  489,
+      489,  489,  489,  489,  489,  489,  489,  489, -361, -361,
+     -361, -361, -361, -361, -361,  488,  488,  488,  488,  488,
+
+      488,  488,  488,  488,  488,  488,  488,  488,  488,  488,
+      488,  488,  488,  488,  488,  488,  488,  488,  488,  488,
+      488, -361, -361, -361, -361, -361, -361, -361, -361, -361,
+     -361, -361, -361, -361, -361, -361, -361, -361, -361, -361,
+     -361, -361, -361, -361, -361, -361, -361, -361, -361, -361,
+     -361, -361, -361, -361, -361, -361, -361, -361
+    },
+
+    {
+       67, -362, -362, -362, -362, -362, -362, -362, -362, -362,
+     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
+     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
+     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
+
+     -362, -362, -362, -362, -362, -362, -362, -362,  490,  490,
+      490,  490,  490,  490,  490,  490,  490,  490, -362, -362,
+     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
+     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
+     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
+     -362, -362, -362, -362, -362,  491, -362, -362, -362, -362,
+     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
+     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
+     -362, -362, -362, -362, -362, -362, -362, -362
+    },
+
+    {
+       67, -363, -363, -363, -363, -363, -363, -363, -363, -363,
+
+     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
+     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
+     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
+     -363, -363, -363, -363, -363, -363, -363, -363,  492,  493,
+      493,  493,  493,  493,  493,  493,  493,  493, -363, -363,
+     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
+     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
+     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
+     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
+     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
+
+     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
+     -363, -363, -363, -363, -363, -363, -363, -363
+    },
+
+    {
+       67, -364, -364, -364, -364, -364, -364, -364, -364, -364,
+     -364, -364, -364, -364, -364, -364, -364, -364, -364, -364,
+     -364, -364, -364, -364, -364, -364, -364, -364, -364, -364,
+     -364, -364,  494, -364, -364, -364, -364, -364, -364, -364,
+     -364, -364, -364, -364, -364, -364, -364, -364, -364, -364,
+     -364, -364, -364, -364, -364, -364, -364, -364, -364, -364,
+     -364, -364, -364, -364, -364,  494,  494,  494,  494,  494,
+      494,  494,  494,  494,  494,  494,  494,  494,  494,  494,
+
+      494,  494,  494,  494,  494,  494,  494,  494,  494,  494,
+      494, -364, -364, -364, -364, -364, -364, -364, -364, -364,
+     -364, -364, -364, -364, -364, -364, -364, -364, -364, -364,
+     -364, -364, -364, -364, -364, -364, -364, -364, -364, -364,
+     -364, -364, -364, -364, -364, -364, -364, -364
+    },
+
+    {
+       67, -365, -365, -365, -365, -365, -365, -365, -365, -365,
+     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
+     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
+     -365, -365,  494, -365, -365, -365, -365, -365, -365, -365,
+     -365, -365, -365, -365, -365, -365, -365, -365,  495,  495,
+
+      495,  495,  495,  495,  495,  495,  495,  495, -365, -365,
+     -365, -365, -365, -365, -365,  494,  494,  494,  494,  494,
+      494,  494,  494,  494,  494,  494,  494,  494,  494,  494,
+      494,  494,  494,  494,  494,  494,  494,  494,  494,  494,
+      494, -365, -365, -365, -365, -365, -365, -365, -365, -365,
+     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
+     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
+     -365, -365, -365, -365, -365, -365, -365, -365
+    },
+
+    {
+       67, -366, -366, -366, -366, -366, -366, -366, -366, -366,
+     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
+
+     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
+     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
+     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
+     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
+     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
+     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
+     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
+     -366, -366, -366, -366, -366,  496, -366, -366, -366, -366,
+     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
+     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
+
+     -366, -366, -366, -366, -366, -366, -366, -366
+    },
+
+    {
+       67, -367, -367, -367, -367, -367, -367, -367, -367, -367,
+     -367, -367, -367, -367, -367, -367, -367, -367, -367, -367,
+     -367, -367, -367, -367, -367, -367, -367, -367, -367, -367,
+     -367, -367, -367, -367, -367, -367, -367, -367, -367, -367,
+     -367, -367, -367, -367, -367, -367, -367, -367,  497,  498,
+      498,  498,  498,  498,  498,  498,  498,  498, -367, -367,
+     -367, -367, -367, -367, -367, -367, -367, -367, -367, -367,
+     -367, -367, -367, -367, -367, -367, -367, -367, -367, -367,
+     -367, -367, -367, -367, -367, -367, -367, -367, -367, -367,
+
+     -367, -367, -367, -367, -367, -367, -367, -367, -367, -367,
+     -367, -367, -367, -367, -367, -367, -367, -367, -367, -367,
+     -367, -367, -367, -367, -367, -367, -367, -367, -367, -367,
+     -367, -367, -367, -367, -367, -367, -367, -367
+    },
+
+    {
+       67, -368, -368, -368, -368, -368, -368, -368, -368, -368,
+     -368, -368, -368, -368, -368, -368, -368, -368, -368, -368,
+     -368, -368, -368, -368, -368, -368, -368, -368, -368, -368,
+     -368, -368,  499, -368, -368, -368, -368, -368, -368, -368,
+     -368, -368, -368, -368, -368, -368, -368, -368, -368, -368,
+     -368, -368, -368, -368, -368, -368, -368, -368, -368, -368,
+
+     -368, -368, -368, -368, -368,  499,  499,  499,  499,  499,
+      499,  499,  499,  499,  499,  499,  499,  499,  499,  499,
+      499,  499,  499,  499,  499,  499,  499,  499,  499,  499,
+      499, -368, -368, -368, -368, -368, -368, -368, -368, -368,
+     -368, -368, -368, -368, -368, -368, -368, -368, -368, -368,
+     -368, -368, -368, -368, -368, -368, -368, -368, -368, -368,
+     -368, -368, -368, -368, -368, -368, -368, -368
+    },
+
+    {
+       67, -369, -369, -369, -369, -369, -369, -369, -369, -369,
+     -369, -369, -369, -369, -369, -369, -369, -369, -369, -369,
+     -369, -369, -369, -369, -369, -369, -369, -369, -369, -369,
+
+     -369, -369,  499, -369, -369, -369, -369, -369, -369, -369,
+     -369, -369, -369, -369, -369, -369, -369, -369,  500,  500,
+      500,  500,  500,  500,  500,  500,  500,  500, -369, -369,
+     -369, -369, -369, -369, -369,  499,  499,  499,  499,  499,
+      499,  499,  499,  499,  499,  499,  499,  499,  499,  499,
+      499,  499,  499,  499,  499,  499,  499,  499,  499,  499,
+      499, -369, -369, -369, -369, -369, -369, -369, -369, -369,
+     -369, -369, -369, -369, -369, -369, -369, -369, -369, -369,
+     -369, -369, -369, -369, -369, -369, -369, -369, -369, -369,
+     -369, -369, -369, -369, -369, -369, -369, -369
+
+    },
+
+    {
+       67, -370, -370, -370, -370, -370, -370, -370, -370, -370,
+     -370, -370, -370, -370, -370, -370, -370, -370, -370, -370,
+     -370, -370, -370, -370, -370, -370, -370, -370, -370, -370,
+     -370, -370, -370, -370, -370, -370, -370, -370, -370, -370,
+     -370, -370, -370, -370, -370, -370, -370, -370,  501,  501,
+      501,  501,  501,  501,  501,  501,  501,  501, -370, -370,
+     -370, -370, -370, -370, -370, -370, -370, -370, -370, -370,
+     -370, -370, -370, -370, -370, -370, -370, -370, -370, -370,
+     -370, -370, -370, -370, -370, -370, -370, -370, -370, -370,
+     -370, -370, -370, -370, -370,  502, -370, -370, -370, -370,
+
+     -370, -370, -370, -370, -370, -370, -370, -370, -370, -370,
+     -370, -370, -370, -370, -370, -370, -370, -370, -370, -370,
+     -370, -370, -370, -370, -370, -370, -370, -370
+    },
+
+    {
+       67, -371, -371, -371, -371, -371, -371, -371, -371, -371,
+     -371, -371, -371, -371, -371, -371, -371, -371, -371, -371,
+     -371, -371, -371, -371, -371, -371, -371, -371, -371, -371,
+     -371, -371, -371, -371, -371, -371, -371, -371, -371, -371,
+     -371, -371, -371, -371, -371, -371, -371, -371,  503,  504,
+      504,  504,  504,  504,  504,  504,  504,  504, -371, -371,
+     -371, -371, -371, -371, -371, -371, -371, -371, -371, -371,
+
+     -371, -371, -371, -371, -371, -371, -371, -371, -371, -371,
+     -371, -371, -371, -371, -371, -371, -371, -371, -371, -371,
+     -371, -371, -371, -371, -371, -371, -371, -371, -371, -371,
+     -371, -371, -371, -371, -371, -371, -371, -371, -371, -371,
+     -371, -371, -371, -371, -371, -371, -371, -371, -371, -371,
+     -371, -371, -371, -371, -371, -371, -371, -371
+    },
+
+    {
+       67, -372, -372, -372, -372, -372, -372, -372, -372, -372,
+     -372, -372, -372, -372, -372, -372, -372, -372, -372, -372,
+     -372, -372, -372, -372, -372, -372, -372, -372, -372, -372,
+     -372, -372,  505, -372, -372, -372, -372, -372, -372, -372,
+
+     -372, -372, -372, -372, -372, -372, -372, -372, -372, -372,
+     -372, -372, -372, -372, -372, -372, -372, -372, -372, -372,
+     -372, -372, -372, -372, -372,  505,  505,  505,  505,  505,
+      505,  505,  505,  505,  505,  505,  505,  505,  505,  505,
+      505,  505,  505,  505,  505,  505,  505,  505,  505,  505,
+      505, -372, -372, -372, -372, -372, -372, -372, -372, -372,
+     -372, -372, -372, -372, -372, -372, -372, -372, -372, -372,
+     -372, -372, -372, -372, -372, -372, -372, -372, -372, -372,
+     -372, -372, -372, -372, -372, -372, -372, -372
+    },
+
+    {
+       67, -373, -373, -373, -373, -373, -373, -373, -373, -373,
+
+     -373, -373, -373, -373, -373, -373, -373, -373, -373, -373,
+     -373, -373, -373, -373, -373, -373, -373, -373, -373, -373,
+     -373, -373,  505, -373, -373, -373, -373, -373, -373, -373,
+     -373, -373, -373, -373, -373, -373, -373, -373,  506,  506,
+      506,  506,  506,  506,  506,  506,  506,  506, -373, -373,
+     -373, -373, -373, -373, -373,  505,  505,  505,  505,  505,
+      505,  505,  505,  505,  505,  505,  505,  505,  505,  505,
+      505,  505,  505,  505,  505,  505,  505,  505,  505,  505,
+      505, -373, -373, -373, -373, -373, -373, -373, -373, -373,
+     -373, -373, -373, -373, -373, -373, -373, -373, -373, -373,
+
+     -373, -373, -373, -373, -373, -373, -373, -373, -373, -373,
+     -373, -373, -373, -373, -373, -373, -373, -373
+    },
+
+    {
+       67, -374, -374, -374, -374, -374, -374, -374, -374, -374,
+     -374, -374, -374, -374, -374, -374, -374, -374, -374, -374,
+     -374, -374, -374, -374, -374, -374, -374, -374, -374, -374,
+     -374, -374, -374, -374, -374, -374, -374, -374, -374, -374,
+     -374, -374, -374, -374, -374, -374, -374, -374, -374, -374,
+     -374, -374, -374, -374, -374, -374, -374, -374, -374, -374,
+     -374, -374, -374, -374, -374, -374, -374, -374, -374, -374,
+     -374, -374, -374, -374, -374, -374, -374, -374, -374, -374,
+
+     -374, -374, -374, -374, -374, -374, -374, -374, -374, -374,
+     -374, -374, -374, -374, -374,  507, -374, -374, -374, -374,
+     -374, -374, -374, -374, -374, -374, -374, -374, -374, -374,
+     -374, -374, -374, -374, -374, -374, -374, -374, -374, -374,
+     -374, -374, -374, -374, -374, -374, -374, -374
+    },
+
+    {
+       67, -375, -375, -375, -375, -375, -375, -375, -375, -375,
+     -375, -375, -375, -375, -375, -375, -375, -375, -375, -375,
+     -375, -375, -375, -375, -375, -375, -375, -375, -375, -375,
+     -375, -375, -375, -375, -375, -375, -375, -375, -375, -375,
+     -375, -375, -375, -375, -375, -375, -375, -375,  508,  509,
+
+      509,  509,  509,  509,  509,  509,  509,  509, -375, -375,
+     -375, -375, -375, -375, -375, -375, -375, -375, -375, -375,
+     -375, -375, -375, -375, -375, -375, -375, -375, -375, -375,
+     -375, -375, -375, -375, -375, -375, -375, -375, -375, -375,
+     -375, -375, -375, -375, -375, -375, -375, -375, -375, -375,
+     -375, -375, -375, -375, -375, -375, -375, -375, -375, -375,
+     -375, -375, -375, -375, -375, -375, -375, -375, -375, -375,
+     -375, -375, -375, -375, -375, -375, -375, -375
+    },
+
+    {
+       67, -376, -376, -376, -376, -376, -376, -376, -376, -376,
+     -376, -376, -376, -376, -376, -376, -376, -376, -376, -376,
+
+     -376, -376, -376, -376, -376, -376, -376, -376, -376, -376,
+     -376, -376,  510, -376, -376, -376, -376, -376, -376, -376,
+     -376, -376, -376, -376, -376, -376, -376, -376, -376, -376,
+     -376, -376, -376, -376, -376, -376, -376, -376, -376, -376,
+     -376, -376, -376, -376, -376,  510,  510,  510,  510,  510,
+      510,  510,  510,  510,  510,  510,  510,  510,  510,  510,
+      510,  510,  510,  510,  510,  510,  510,  510,  510,  510,
+      510, -376, -376, -376, -376, -376, -376, -376, -376, -376,
+     -376, -376, -376, -376, -376, -376, -376, -376, -376, -376,
+     -376, -376, -376, -376, -376, -376, -376, -376, -376, -376,
+
+     -376, -376, -376, -376, -376, -376, -376, -376
+    },
+
+    {
+       67, -377, -377, -377, -377, -377, -377, -377, -377, -377,
+     -377, -377, -377, -377, -377, -377, -377, -377, -377, -377,
+     -377, -377, -377, -377, -377, -377, -377, -377, -377, -377,
+     -377, -377,  510, -377, -377, -377, -377, -377, -377, -377,
+     -377, -377, -377, -377, -377, -377, -377, -377,  511,  511,
+      511,  511,  511,  511,  511,  511,  511,  511, -377, -377,
+     -377, -377, -377, -377, -377,  510,  510,  510,  510,  510,
+      510,  510,  510,  510,  510,  510,  510,  510,  510,  510,
+      510,  510,  510,  510,  510,  510,  510,  510,  510,  510,
+
+      510, -377, -377, -377, -377, -377, -377, -377, -377, -377,
+     -377, -377, -377, -377, -377, -377, -377, -377, -377, -377,
+     -377, -377, -377, -377, -377, -377, -377, -377, -377, -377,
+     -377, -377, -377, -377, -377, -377, -377, -377
+    },
+
+    {
+       67, -378, -378, -378, -378, -378, -378, -378, -378, -378,
+     -378, -378, -378, -378, -378, -378, -378, -378, -378, -378,
+     -378, -378, -378, -378, -378, -378, -378, -378, -378, -378,
+     -378, -378, -378, -378, -378, -378, -378, -378, -378, -378,
+     -378, -378, -378, -378, -378, -378, -378, -378, -378, -378,
+     -378, -378, -378, -378, -378, -378, -378, -378, -378, -378,
+
+     -378, -378, -378, -378, -378, -378, -378, -378, -378, -378,
+     -378, -378, -378, -378, -378, -378, -378, -378, -378, -378,
+     -378, -378, -378, -378, -378, -378, -378, -378, -378, -378,
+     -378, -378, -378, -378, -378, -378, -378, -378, -378, -378,
+     -378, -378, -378, -378, -378, -378, -378, -378, -378, -378,
+     -378, -378, -378, -378, -378, -378, -378, -378, -378, -378,
+     -378, -378, -378, -378, -378, -378, -378, -378
+    },
+
+    {
+       67, -379, -379, -379, -379, -379, -379, -379, -379, -379,
+     -379, -379, -379, -379, -379, -379, -379, -379, -379, -379,
+     -379, -379, -379, -379, -379, -379, -379, -379, -379, -379,
+
+     -379, -379,  512, -379, -379, -379, -379, -379, -379, -379,
+     -379, -379, -379, -379, -379, -379, -379, -379, -379, -379,
+     -379, -379, -379, -379, -379, -379, -379, -379, -379, -379,
+     -379, -379, -379, -379, -379, -379, -379, -379, -379, -379,
+     -379, -379, -379, -379, -379, -379, -379, -379, -379, -379,
+     -379, -379, -379, -379, -379, -379, -379, -379, -379, -379,
+     -379, -379, -379, -379, -379, -379, -379, -379, -379, -379,
+     -379, -379, -379, -379, -379, -379, -379, -379, -379, -379,
+     -379, -379, -379, -379, -379, -379, -379, -379, -379, -379,
+     -379, -379, -379, -379, -379, -379, -379, -379
+
+    },
+
+    {
+       67, -380, -380, -380, -380, -380, -380, -380, -380, -380,
+     -380, -380, -380, -380, -380, -380, -380, -380, -380, -380,
+     -380, -380, -380, -380, -380, -380, -380, -380, -380, -380,
+     -380, -380,  513, -380, -380, -380, -380, -380, -380, -380,
+     -380, -380, -380, -380, -380, -380, -380, -380, -380, -380,
+     -380, -380, -380, -380, -380, -380, -380, -380, -380, -380,
+     -380, -380, -380, -380, -380, -380, -380, -380, -380, -380,
+     -380, -380, -380, -380, -380, -380, -380, -380, -380, -380,
+     -380, -380, -380, -380, -380, -380, -380, -380, -380, -380,
+     -380, -380, -380, -380, -380, -380, -380, -380, -380, -380,
+
+     -380, -380, -380, -380, -380, -380, -380, -380, -380, -380,
+     -380, -380, -380, -380, -380, -380, -380, -380, -380, -380,
+     -380, -380, -380, -380, -380, -380, -380, -380
+    },
+
+    {
+       67, -381, -381, -381, -381, -381, -381, -381, -381, -381,
+     -381, -381, -381, -381, -381, -381, -381, -381, -381, -381,
+     -381, -381, -381, -381, -381, -381, -381, -381, -381, -381,
+     -381, -381,  514, -381, -381, -381, -381, -381, -381, -381,
+     -381, -381, -381, -381, -381, -381, -381, -381, -381, -381,
+     -381, -381, -381, -381, -381, -381, -381, -381, -381, -381,
+     -381, -381, -381, -381, -381,  514,  514,  514,  514,  514,
+
+      514,  514,  514,  514,  514,  514,  514,  514,  514,  514,
+      514,  514,  514,  514,  514,  514,  514,  514,  514,  514,
+      514, -381, -381, -381, -381, -381, -381, -381, -381, -381,
+     -381, -381, -381, -381, -381, -381, -381, -381, -381, -381,
+     -381, -381, -381, -381, -381, -381, -381, -381, -381, -381,
+     -381, -381, -381, -381, -381, -381, -381, -381
+    },
+
+    {
+       67, -382, -382, -382, -382, -382, -382, -382, -382, -382,
+     -382, -382, -382, -382, -382, -382, -382, -382, -382, -382,
+     -382, -382, -382, -382, -382, -382, -382, -382, -382, -382,
+     -382, -382, -382, -382, -382, -382, -382, -382, -382, -382,
+
+     -382, -382, -382, -382, -382, -382, -382, -382, -382, -382,
+     -382, -382, -382, -382, -382, -382, -382, -382, -382, -382,
+     -382, -382, -382, -382, -382, -382, -382, -382, -382, -382,
+     -382, -382, -382, -382, -382, -382, -382, -382, -382, -382,
+     -382, -382, -382, -382, -382, -382, -382, -382, -382, -382,
+     -382, -382, -382, -382, -382, -382, -382, -382, -382, -382,
+     -382, -382, -382, -382, -382, -382, -382, -382, -382, -382,
+     -382, -382, -382, -382, -382, -382, -382, -382, -382, -382,
+     -382, -382, -382, -382, -382, -382, -382, -382
+    },
+
+    {
+       67, -383, -383, -383, -383, -383, -383, -383, -383, -383,
+
+     -383, -383, -383, -383, -383, -383, -383, -383, -383, -383,
+     -383, -383, -383, -383, -383, -383, -383, -383, -383, -383,
+     -383, -383, -383, -383, -383, -383, -383, -383, -383, -383,
+     -383, -383, -383, -383, -383, -383, -383, -383, -383, -383,
+     -383, -383, -383, -383, -383, -383, -383, -383, -383, -383,
+     -383, -383, -383, -383, -383, -383, -383, -383, -383, -383,
+     -383, -383, -383, -383, -383, -383, -383, -383, -383, -383,
+     -383, -383, -383, -383, -383, -383, -383, -383, -383, -383,
+     -383, -383, -383, -383, -383, -383, -383, -383, -383, -383,
+     -383, -383, -383, -383, -383, -383, -383, -383, -383, -383,
+
+     -383, -383, -383, -383, -383, -383, -383, -383, -383, -383,
+     -383, -383, -383, -383, -383, -383, -383, -383
+    },
+
+    {
+       67, -384, -384, -384, -384, -384, -384, -384, -384, -384,
+     -384, -384, -384, -384, -384, -384, -384, -384, -384, -384,
+     -384, -384, -384, -384, -384, -384, -384, -384, -384, -384,
+     -384, -384, -384, -384, -384, -384, -384, -384, -384, -384,
+     -384, -384, -384, -384, -384, -384, -384, -384, -384, -384,
+     -384, -384, -384, -384, -384, -384, -384, -384, -384, -384,
+     -384, -384, -384, -384, -384, -384, -384, -384, -384, -384,
+     -384, -384, -384, -384, -384, -384, -384, -384, -384, -384,
+
+     -384, -384, -384, -384, -384, -384, -384, -384, -384, -384,
+     -384, -384, -384, -384, -384, -384, -384, -384, -384, -384,
+     -384, -384, -384, -384, -384, -384, -384, -384, -384, -384,
+     -384, -384, -384, -384, -384, -384, -384, -384, -384, -384,
+     -384, -384, -384, -384, -384, -384, -384, -384
+    },
+
+    {
+       67, -385, -385, -385, -385, -385, -385, -385, -385, -385,
+     -385, -385, -385, -385, -385, -385, -385, -385, -385, -385,
+     -385, -385, -385, -385, -385, -385, -385, -385, -385, -385,
+     -385, -385,  515, -385, -385, -385, -385, -385, -385, -385,
+     -385, -385, -385, -385, -385, -385, -385, -385, -385, -385,
+
+     -385, -385, -385, -385, -385, -385, -385, -385, -385, -385,
+     -385, -385, -385, -385, -385, -385, -385, -385, -385, -385,
+     -385, -385, -385, -385, -385, -385, -385, -385, -385, -385,
+     -385, -385, -385, -385, -385, -385, -385, -385, -385, -385,
+     -385, -385, -385, -385, -385, -385, -385, -385, -385, -385,
+     -385, -385, -385, -385, -385, -385, -385, -385, -385, -385,
+     -385, -385, -385, -385, -385, -385, -385, -385, -385, -385,
+     -385, -385, -385, -385, -385, -385, -385, -385
+    },
+
+    {
+       67, -386, -386, -386, -386, -386, -386, -386, -386, -386,
+     -386, -386, -386, -386, -386, -386, -386, -386, -386, -386,
+
+     -386, -386, -386, -386, -386, -386, -386, -386, -386, -386,
+     -386, -386,  516, -386, -386, -386, -386, -386, -386, -386,
+     -386, -386, -386, -386, -386, -386, -386, -386, -386, -386,
+     -386, -386, -386, -386, -386, -386, -386, -386, -386, -386,
+     -386, -386, -386, -386, -386, -386, -386, -386, -386, -386,
+     -386, -386, -386, -386, -386, -386, -386, -386, -386, -386,
+     -386, -386, -386, -386, -386, -386, -386, -386, -386, -386,
+     -386, -386, -386, -386, -386, -386, -386, -386, -386, -386,
+     -386, -386, -386, -386, -386, -386, -386, -386, -386, -386,
+     -386, -386, -386, -386, -386, -386, -386, -386, -386, -386,
+
+     -386, -386, -386, -386, -386, -386, -386, -386
+    },
+
+    {
+       67, -387, -387, -387, -387, -387, -387, -387, -387, -387,
+     -387, -387, -387, -387, -387, -387, -387, -387, -387, -387,
+     -387, -387, -387, -387, -387, -387, -387, -387, -387, -387,
+     -387, -387,  517, -387, -387, -387, -387, -387, -387, -387,
+     -387, -387, -387, -387, -387, -387, -387, -387,  518,  518,
+      518,  518,  518,  518,  518,  518,  518,  518, -387, -387,
+     -387, -387, -387, -387, -387, -387, -387, -387, -387, -387,
+     -387, -387, -387, -387, -387, -387, -387, -387, -387, -387,
+     -387, -387, -387, -387, -387, -387, -387, -387, -387, -387,
+
+     -387, -387, -387, -387, -387, -387, -387, -387, -387, -387,
+     -387, -387, -387, -387, -387, -387, -387, -387, -387, -387,
+     -387, -387, -387, -387, -387, -387, -387, -387, -387, -387,
+     -387, -387, -387, -387, -387, -387, -387, -387
+    },
+
+    {
+       67, -388, -388, -388, -388, -388, -388, -388, -388, -388,
+     -388, -388, -388, -388, -388, -388, -388, -388, -388, -388,
+     -388, -388, -388, -388, -388, -388, -388, -388, -388, -388,
+     -388, -388, -388, -388, -388, -388, -388, -388, -388, -388,
+     -388, -388, -388, -388, -388, -388, -388, -388, -388, -388,
+     -388, -388, -388, -388, -388, -388, -388, -388, -388, -388,
+
+     -388, -388, -388, -388, -388, -388, -388, -388, -388, -388,
+     -388, -388, -388, -388, -388, -388, -388, -388, -388, -388,
+     -388, -388, -388, -388, -388, -388, -388, -388, -388, -388,
+     -388, -388, -388, -388, -388, -388, -388, -388, -388, -388,
+     -388, -388, -388, -388, -388, -388, -388, -388, -388, -388,
+     -388, -388, -388, -388, -388, -388, -388, -388, -388, -388,
+     -388, -388, -388, -388, -388, -388, -388, -388
+    },
+
+    {
+       67, -389, -389, -389, -389, -389, -389, -389, -389, -389,
+     -389, -389, -389, -389, -389, -389, -389, -389, -389, -389,
+     -389, -389, -389, -389, -389, -389, -389, -389, -389, -389,
+
+     -389, -389, -389, -389, -389, -389, -389, -389, -389, -389,
+     -389, -389, -389, -389, -389, -389, -389, -389, -389, -389,
+     -389, -389, -389, -389, -389, -389, -389, -389, -389, -389,
+     -389, -389, -389, -389, -389, -389, -389, -389, -389, -389,
+     -389, -389, -389, -389, -389, -389, -389, -389, -389, -389,
+     -389, -389, -389, -389, -389, -389, -389, -389, -389, -389,
+     -389, -389, -389, -389, -389, -389, -389, -389, -389, -389,
+     -389, -389, -389, -389, -389, -389, -389, -389, -389, -389,
+     -389, -389, -389, -389, -389, -389, -389, -389, -389, -389,
+     -389, -389, -389, -389, -389, -389, -389, -389
+
+    },
+
+    {
+       67, -390, -390, -390, -390, -390, -390, -390, -390, -390,
+     -390, -390, -390, -390, -390, -390, -390, -390, -390, -390,
+     -390, -390, -390, -390, -390, -390, -390, -390, -390, -390,
+     -390, -390, -390, -390, -390, -390, -390, -390, -390, -390,
+     -390, -390, -390, -390, -390, -390, -390, -390, -390, -390,
+     -390, -390, -390, -390, -390, -390, -390, -390, -390, -390,
+     -390, -390, -390, -390, -390, -390, -390, -390, -390, -390,
+     -390, -390, -390, -390, -390, -390, -390, -390, -390, -390,
+     -390, -390, -390, -390, -390, -390, -390, -390, -390, -390,
+     -390, -390, -390, -390, -390, -390, -390, -390, -390, -390,
+
+     -390, -390, -390, -390, -390, -390, -390, -390, -390, -390,
+     -390, -390, -390, -390, -390, -390, -390, -390, -390, -390,
+     -390, -390, -390, -390, -390, -390, -390, -390
+    },
+
+    {
+       67, -391, -391, -391, -391, -391, -391, -391, -391, -391,
+     -391, -391, -391, -391, -391, -391, -391, -391, -391, -391,
+     -391, -391, -391, -391, -391, -391, -391, -391, -391, -391,
+     -391, -391, -391, -391, -391, -391, -391, -391, -391, -391,
+     -391, -391, -391, -391, -391, -391, -391, -391,  391,  391,
+      391,  391,  391,  391,  391,  391,  391,  391, -391, -391,
+     -391, -391, -391, -391, -391, -391, -391, -391, -391,  246,
+
+     -391, -391, -391, -391, -391, -391, -391, -391, -391, -391,
+     -391, -391, -391, -391, -391, -391, -391, -391, -391, -391,
+     -391, -391, -391, -391, -391, -391, -391, -391, -391, -391,
+     -391,  246, -391, -391, -391, -391, -391, -391, -391, -391,
+     -391, -391, -391, -391, -391, -391, -391, -391, -391, -391,
+     -391, -391, -391, -391, -391, -391, -391, -391
+    },
+
+    {
+       67, -392, -392, -392, -392, -392, -392, -392, -392, -392,
+     -392, -392, -392, -392, -392, -392, -392, -392, -392, -392,
+     -392, -392, -392, -392, -392, -392, -392, -392, -392, -392,
+     -392, -392, -392, -392, -392, -392, -392, -392, -392, -392,
+
+     -392, -392, -392, -392, -392, -392, -392, -392,  393,  393,
+      393,  393,  393,  393,  393,  393,  393,  393, -392, -392,
+     -392, -392, -392, -392, -392, -392, -392, -392, -392, -392,
+     -392, -392, -392, -392, -392, -392, -392, -392, -392, -392,
+     -392, -392, -392, -392, -392, -392, -392, -392, -392, -392,
+     -392, -392, -392, -392, -392, -392, -392, -392, -392, -392,
+     -392, -392, -392, -392, -392, -392, -392, -392, -392, -392,
+     -392, -392, -392, -392, -392, -392, -392, -392, -392, -392,
+     -392, -392, -392, -392, -392, -392, -392, -392
+    },
+
+    {
+       67, -393, -393, -393, -393, -393, -393, -393, -393, -393,
+
+     -393, -393, -393, -393, -393, -393, -393, -393, -393, -393,
+     -393, -393, -393, -393, -393, -393, -393, -393, -393, -393,
+     -393, -393, -393, -393, -393, -393, -393, -393, -393, -393,
+     -393, -393, -393, -393, -393, -393, -393, -393,  393,  393,
+      393,  393,  393,  393,  393,  393,  393,  393, -393, -393,
+     -393, -393, -393, -393, -393, -393, -393, -393, -393, -393,
+     -393, -393, -393, -393, -393, -393, -393, -393, -393, -393,
+     -393, -393, -393, -393, -393, -393, -393, -393, -393, -393,
+     -393, -393, -393, -393, -393, -393, -393, -393, -393, -393,
+     -393, -393, -393, -393, -393, -393, -393, -393, -393, -393,
+
+     -393, -393, -393, -393, -393, -393, -393, -393, -393, -393,
+     -393, -393, -393, -393, -393, -393, -393, -393
+    },
+
+    {
+       67, -394, -394, -394, -394, -394, -394, -394, -394, -394,
+     -394, -394, -394, -394, -394, -394, -394, -394, -394, -394,
+     -394, -394, -394, -394, -394, -394, -394, -394, -394, -394,
+     -394, -394, -394, -394, -394, -394, -394, -394, -394, -394,
+     -394, -394, -394, -394, -394, -394, -394, -394, -394, -394,
+     -394, -394, -394, -394, -394, -394, -394, -394, -394, -394,
+     -394, -394, -394, -394, -394, -394, -394, -394, -394, -394,
+     -394, -394, -394, -394, -394, -394, -394, -394, -394, -394,
+
+     -394, -394, -394, -394, -394, -394, -394, -394, -394, -394,
+     -394, -394, -394, -394, -394, -394, -394, -394, -394, -394,
+     -394, -394, -394, -394, -394, -394, -394, -394, -394, -394,
+     -394, -394, -394, -394, -394, -394, -394, -394, -394, -394,
+     -394, -394, -394, -394, -394, -394, -394, -394
+    },
+
+    {
+       67, -395, -395, -395, -395, -395, -395, -395, -395, -395,
+     -395, -395, -395, -395, -395, -395, -395, -395, -395, -395,
+     -395, -395, -395, -395, -395, -395, -395, -395, -395, -395,
+     -395, -395, -395, -395, -395, -395, -395, -395, -395, -395,
+     -395, -395, -395, -395, -395, -395, -395, -395, -395, -395,
+
+     -395, -395, -395, -395, -395, -395, -395, -395, -395, -395,
+     -395, -395, -395, -395, -395, -395, -395, -395, -395, -395,
+     -395, -395, -395, -395, -395, -395, -395, -395, -395, -395,
+     -395, -395, -395, -395, -395, -395, -395, -395, -395, -395,
+     -395, -395, -395, -395, -395, -395, -395, -395, -395, -395,
+     -395, -395, -395, -395, -395, -395, -395, -395, -395, -395,
+     -395, -395, -395, -395, -395, -395, -395, -395, -395, -395,
+     -395, -395, -395, -395, -395, -395, -395, -395
+    },
+
+    {
+       67, -396, -396, -396, -396, -396, -396, -396, -396, -396,
+     -396, -396, -396, -396, -396, -396, -396, -396, -396, -396,
+
+     -396, -396, -396, -396, -396, -396, -396, -396, -396, -396,
+     -396, -396, -396, -396, -396, -396, -396, -396, -396, -396,
+     -396, -396, -396, -396, -396, -396, -396, -396, -396, -396,
+     -396, -396, -396, -396, -396, -396, -396, -396, -396, -396,
+     -396, -396, -396, -396, -396, -396, -396, -396, -396, -396,
+     -396, -396, -396, -396, -396, -396, -396, -396, -396, -396,
+     -396, -396, -396, -396, -396, -396, -396, -396, -396, -396,
+     -396, -396, -396, -396, -396, -396, -396, -396, -396, -396,
+     -396, -396, -396, -396, -396, -396, -396, -396, -396, -396,
+     -396, -396, -396, -396, -396, -396, -396, -396, -396, -396,
+
+     -396, -396, -396, -396, -396, -396, -396, -396
+    },
+
+    {
+       67, -397, -397, -397, -397, -397, -397, -397, -397, -397,
+     -397, -397, -397, -397, -397, -397, -397, -397, -397, -397,
+     -397, -397, -397, -397, -397, -397, -397, -397, -397, -397,
+     -397, -397, -397, -397, -397, -397, -397, -397, -397, -397,
+     -397, -397, -397, -397, -397, -397, -397, -397, -397, -397,
+     -397, -397, -397, -397, -397, -397, -397, -397, -397, -397,
+     -397, -397, -397, -397, -397, -397, -397, -397, -397, -397,
+     -397, -397, -397, -397, -397, -397, -397, -397, -397, -397,
+     -397, -397, -397, -397,  519, -397, -397, -397, -397, -397,
+
+     -397, -397, -397, -397, -397, -397, -397, -397, -397, -397,
+     -397, -397, -397, -397, -397, -397, -397, -397, -397, -397,
+     -397, -397, -397, -397, -397, -397, -397, -397, -397, -397,
+     -397, -397, -397, -397, -397, -397, -397, -397
+    },
+
+    {
+       67, -398, -398, -398, -398, -398, -398, -398, -398, -398,
+     -398, -398, -398, -398, -398, -398, -398, -398, -398, -398,
+     -398, -398, -398, -398, -398, -398, -398, -398, -398, -398,
+     -398, -398, -398, -398, -398, -398, -398, -398, -398, -398,
+     -398, -398, -398, -398, -398, -398, -398, -398, -398, -398,
+     -398, -398, -398, -398, -398, -398, -398, -398, -398, -398,
+
+     -398, -398, -398, -398, -398, -398, -398, -398, -398, -398,
+     -398, -398, -398, -398, -398, -398, -398,  520, -398, -398,
+     -398, -398, -398, -398, -398, -398, -398, -398, -398, -398,
+     -398, -398, -398, -398, -398, -398, -398, -398, -398, -398,
+     -398, -398, -398, -398, -398, -398, -398, -398, -398, -398,
+     -398, -398, -398, -398, -398, -398, -398, -398, -398, -398,
+     -398, -398, -398, -398, -398, -398, -398, -398
+    },
+
+    {
+       67, -399, -399, -399, -399, -399, -399, -399, -399, -399,
+     -399, -399, -399, -399, -399, -399, -399, -399, -399, -399,
+     -399, -399, -399, -399, -399, -399, -399, -399, -399, -399,
+
+     -399, -399, -399, -399, -399, -399, -399, -399, -399, -399,
+     -399, -399, -399, -399, -399, -399, -399, -399, -399, -399,
+     -399, -399, -399, -399, -399, -399, -399, -399, -399, -399,
+     -399, -399, -399, -399, -399, -399, -399, -399, -399,  521,
+     -399, -399, -399, -399, -399, -399, -399, -399, -399, -399,
+     -399, -399, -399, -399, -399, -399, -399, -399, -399, -399,
+     -399, -399, -399, -399, -399, -399, -399, -399, -399, -399,
+     -399, -399, -399, -399, -399, -399, -399, -399, -399, -399,
+     -399, -399, -399, -399, -399, -399, -399, -399, -399, -399,
+     -399, -399, -399, -399, -399, -399, -399, -399
+
+    },
+
+    {
+       67, -400, -400, -400, -400, -400, -400, -400, -400, -400,
+     -400, -400, -400, -400, -400, -400, -400, -400, -400, -400,
+     -400, -400, -400, -400, -400, -400, -400, -400, -400, -400,
+     -400, -400, -400, -400, -400, -400, -400, -400, -400, -400,
+     -400, -400, -400, -400, -400, -400, -400, -400, -400, -400,
+     -400, -400, -400, -400, -400, -400, -400, -400, -400, -400,
+     -400, -400, -400, -400, -400, -400, -400, -400, -400, -400,
+     -400, -400, -400, -400, -400, -400, -400, -400, -400, -400,
+     -400, -400, -400, -400,  522, -400, -400, -400, -400, -400,
+     -400, -400, -400, -400, -400, -400, -400, -400, -400, -400,
+
+     -400, -400, -400, -400, -400, -400, -400, -400, -400, -400,
+     -400, -400, -400, -400, -400, -400, -400, -400, -400, -400,
+     -400, -400, -400, -400, -400, -400, -400, -400
+    },
+
+    {
+       67, -401, -401, -401, -401, -401, -401, -401, -401, -401,
+     -401, -401, -401, -401, -401, -401, -401, -401, -401, -401,
+     -401, -401, -401, -401, -401, -401, -401, -401, -401, -401,
+     -401, -401, -401, -401, -401, -401, -401, -401, -401, -401,
+     -401, -401, -401, -401, -401, -401, -401, -401, -401, -401,
+     -401, -401, -401, -401, -401, -401, -401, -401, -401, -401,
+     -401, -401, -401, -401, -401, -401, -401, -401, -401, -401,
+
+     -401, -401, -401, -401, -401, -401, -401, -401, -401, -401,
+     -401, -401, -401, -401, -401, -401, -401, -401,  523, -401,
+     -401, -401, -401, -401, -401, -401, -401, -401, -401, -401,
+     -401, -401, -401, -401, -401, -401, -401, -401, -401, -401,
+     -401, -401, -401, -401, -401, -401, -401, -401, -401, -401,
+     -401, -401, -401, -401, -401, -401, -401, -401
+    },
+
+    {
+       67, -402, -402, -402, -402, -402, -402, -402, -402, -402,
+     -402, -402, -402, -402, -402, -402, -402, -402, -402, -402,
+     -402, -402, -402, -402, -402, -402, -402, -402, -402, -402,
+     -402, -402, -402, -402, -402, -402, -402, -402, -402, -402,
+
+     -402, -402, -402, -402, -402, -402, -402, -402, -402, -402,
+     -402, -402, -402, -402, -402, -402, -402, -402, -402, -402,
+     -402, -402, -402, -402, -402, -402, -402, -402, -402, -402,
+     -402, -402, -402, -402, -402, -402,  524, -402, -402, -402,
+     -402, -402, -402, -402, -402, -402, -402, -402, -402, -402,
+     -402, -402, -402, -402, -402, -402, -402, -402, -402, -402,
+     -402, -402, -402, -402, -402, -402, -402, -402, -402, -402,
+     -402, -402, -402, -402, -402, -402, -402, -402, -402, -402,
+     -402, -402, -402, -402, -402, -402, -402, -402
+    },
+
+    {
+       67, -403, -403, -403, -403, -403, -403, -403, -403, -403,
+
+     -403, -403, -403, -403, -403, -403, -403, -403, -403, -403,
+     -403, -403, -403, -403, -403, -403, -403, -403, -403, -403,
+     -403, -403, -403, -403, -403, -403, -403, -403, -403, -403,
+     -403, -403, -403, -403, -403, -403, -403, -403, -403, -403,
+     -403, -403, -403, -403, -403, -403, -403, -403, -403, -403,
+     -403, -403, -403, -403, -403, -403, -403, -403, -403,  525,
+     -403, -403, -403, -403, -403, -403, -403, -403, -403, -403,
+     -403, -403, -403, -403, -403, -403, -403, -403, -403, -403,
+     -403, -403, -403, -403, -403, -403, -403, -403, -403, -403,
+     -403, -403, -403, -403, -403, -403, -403, -403, -403, -403,
+
+     -403, -403, -403, -403, -403, -403, -403, -403, -403, -403,
+     -403, -403, -403, -403, -403, -403, -403, -403
+    },
+
+    {
+       67, -404, -404, -404, -404, -404, -404, -404, -404, -404,
+     -404, -404, -404, -404, -404, -404, -404, -404, -404, -404,
+     -404, -404, -404, -404, -404, -404, -404, -404, -404, -404,
+     -404, -404, -404, -404, -404, -404, -404, -404, -404, -404,
+     -404, -404, -404, -404, -404, -404, -404, -404, -404, -404,
+     -404, -404, -404, -404, -404, -404, -404, -404, -404, -404,
+     -404, -404, -404, -404, -404, -404, -404, -404, -404, -404,
+     -404, -404, -404, -404, -404, -404, -404, -404, -404, -404,
+
+      526, -404, -404, -404, -404, -404, -404, -404, -404, -404,
+     -404, -404, -404, -404, -404, -404, -404, -404, -404, -404,
+     -404, -404, -404, -404, -404, -404, -404, -404, -404, -404,
+     -404, -404, -404, -404, -404, -404, -404, -404, -404, -404,
+     -404, -404, -404, -404, -404, -404, -404, -404
+    },
+
+    {
+       67, -405, -405, -405, -405, -405, -405, -405, -405, -405,
+     -405, -405, -405, -405, -405, -405, -405, -405, -405, -405,
+     -405, -405, -405, -405, -405, -405, -405, -405, -405, -405,
+     -405, -405, -405, -405, -405, -405, -405, -405, -405, -405,
+     -405, -405, -405, -405, -405, -405, -405, -405, -405, -405,
+
+     -405, -405, -405, -405, -405, -405, -405, -405, -405, -405,
+     -405, -405, -405, -405, -405, -405, -405, -405, -405, -405,
+     -405, -405, -405,  527, -405, -405, -405, -405, -405, -405,
+     -405, -405, -405, -405, -405, -405, -405, -405, -405, -405,
+     -405, -405, -405, -405, -405, -405, -405, -405, -405, -405,
+     -405, -405, -405, -405, -405, -405, -405, -405, -405, -405,
+     -405, -405, -405, -405, -405, -405, -405, -405, -405, -405,
+     -405, -405, -405, -405, -405, -405, -405, -405
+    },
+
+    {
+       67, -406, -406, -406, -406, -406, -406, -406, -406, -406,
+     -406, -406, -406, -406, -406, -406, -406, -406, -406, -406,
+
+     -406, -406, -406, -406, -406, -406, -406, -406, -406, -406,
+     -406, -406, -406, -406, -406, -406, -406, -406, -406, -406,
+     -406, -406, -406, -406, -406, -406, -406, -406, -406, -406,
+     -406, -406, -406, -406, -406, -406, -406, -406, -406, -406,
+     -406, -406, -406, -406, -406, -406, -406, -406, -406, -406,
+     -406, -406, -406, -406, -406, -406, -406, -406, -406, -406,
+     -406, -406, -406, -406,  528, -406, -406, -406, -406, -406,
+     -406, -406, -406, -406, -406, -406, -406, -406, -406, -406,
+     -406, -406, -406, -406, -406, -406, -406, -406, -406, -406,
+     -406, -406, -406, -406, -406, -406, -406, -406, -406, -406,
+
+     -406, -406, -406, -406, -406, -406, -406, -406
+    },
+
+    {
+       67, -407, -407, -407, -407, -407, -407, -407, -407, -407,
+     -407, -407, -407, -407, -407, -407, -407, -407, -407, -407,
+     -407, -407, -407, -407, -407, -407, -407, -407, -407, -407,
+     -407, -407, -407, -407, -407, -407, -407, -407, -407, -407,
+     -407, -407, -407, -407, -407, -407, -407, -407, -407, -407,
+     -407, -407, -407, -407, -407, -407, -407, -407, -407, -407,
+     -407, -407, -407, -407, -407, -407, -407, -407, -407,  529,
+     -407, -407, -407, -407, -407, -407, -407, -407, -407, -407,
+     -407, -407, -407, -407, -407, -407, -407, -407, -407, -407,
+
+     -407, -407, -407, -407, -407, -407, -407, -407, -407, -407,
+     -407, -407, -407, -407, -407, -407, -407, -407, -407, -407,
+     -407, -407, -407, -407, -407, -407, -407, -407, -407, -407,
+     -407, -407, -407, -407, -407, -407, -407, -407
+    },
+
+    {
+       67, -408, -408, -408, -408, -408, -408, -408, -408, -408,
+     -408, -408, -408, -408, -408, -408, -408, -408, -408, -408,
+     -408, -408, -408, -408, -408, -408, -408, -408, -408, -408,
+     -408, -408, -408, -408, -408, -408, -408, -408, -408, -408,
+     -408, -408, -408, -408, -408, -408, -408, -408, -408, -408,
+     -408, -408, -408, -408, -408, -408, -408, -408, -408, -408,
+
+     -408, -408, -408, -408, -408, -408, -408, -408, -408, -408,
+     -408, -408, -408, -408, -408, -408, -408, -408, -408, -408,
+     -408, -408,  530, -408, -408, -408, -408, -408, -408, -408,
+     -408, -408, -408, -408, -408, -408, -408, -408, -408, -408,
+     -408, -408, -408, -408, -408, -408, -408, -408, -408, -408,
+     -408, -408, -408, -408, -408, -408, -408, -408, -408, -408,
+     -408, -408, -408, -408, -408, -408, -408, -408
+    },
+
+    {
+       67, -409, -409, -409, -409, -409, -409, -409, -409, -409,
+     -409, -409, -409, -409, -409, -409, -409, -409, -409, -409,
+     -409, -409, -409, -409, -409, -409, -409, -409, -409, -409,
+
+     -409, -409, -409, -409, -409, -409, -409, -409, -409, -409,
+     -409, -409, -409, -409, -409, -409, -409, -409, -409, -409,
+     -409, -409, -409, -409, -409, -409, -409, -409, -409, -409,
+     -409, -409, -409, -409, -409,  531, -409, -409, -409, -409,
+     -409, -409, -409, -409, -409, -409, -409, -409, -409, -409,
+     -409, -409, -409, -409, -409, -409, -409, -409, -409, -409,
+     -409, -409, -409, -409, -409, -409, -409, -409, -409, -409,
+     -409, -409, -409, -409, -409, -409, -409, -409, -409, -409,
+     -409, -409, -409, -409, -409, -409, -409, -409, -409, -409,
+     -409, -409, -409, -409, -409, -409, -409, -409
+
+    },
+
+    {
+       67, -410, -410, -410, -410, -410, -410, -410, -410, -410,
+     -410, -410, -410, -410, -410, -410, -410, -410, -410, -410,
+     -410, -410, -410, -410, -410, -410, -410, -410, -410, -410,
+     -410, -410, -410, -410, -410, -410, -410, -410, -410, -410,
+     -410, -410, -410, -410, -410, -410, -410, -410, -410, -410,
+     -410, -410, -410, -410, -410, -410, -410, -410, -410, -410,
+     -410, -410, -410, -410, -410, -410, -410, -410, -410, -410,
+     -410, -410, -410, -410, -410, -410, -410, -410, -410, -410,
+     -410, -410, -410, -410, -410, -410, -410, -410,  532, -410,
+     -410, -410, -410, -410, -410, -410, -410, -410, -410, -410,
+
+     -410, -410, -410, -410, -410, -410, -410, -410, -410, -410,
+     -410, -410, -410, -410, -410, -410, -410, -410, -410, -410,
+     -410, -410, -410, -410, -410, -410, -410, -410
+    },
+
+    {
+       67, -411, -411, -411, -411, -411, -411, -411, -411, -411,
+     -411, -411, -411, -411, -411, -411, -411, -411, -411, -411,
+     -411, -411, -411, -411, -411, -411, -411, -411, -411, -411,
+     -411, -411, -411, -411, -411, -411, -411, -411, -411, -411,
+     -411, -411, -411, -411, -411, -411, -411, -411, -411, -411,
+     -411, -411, -411, -411, -411, -411, -411, -411, -411, -411,
+     -411, -411, -411, -411, -411, -411, -411, -411, -411, -411,
+
+     -411, -411, -411, -411, -411, -411,  533, -411, -411, -411,
+     -411, -411, -411, -411, -411, -411, -411, -411, -411, -411,
+     -411, -411, -411, -411, -411, -411, -411, -411, -411, -411,
+     -411, -411, -411, -411, -411, -411, -411, -411, -411, -411,
+     -411, -411, -411, -411, -411, -411, -411, -411, -411, -411,
+     -411, -411, -411, -411, -411, -411, -411, -411
+    },
+
+    {
+       67, -412, -412, -412, -412, -412, -412, -412, -412, -412,
+     -412, -412, -412, -412, -412, -412, -412, -412, -412, -412,
+     -412, -412, -412, -412, -412, -412, -412, -412, -412, -412,
+     -412, -412, -412, -412, -412, -412, -412, -412, -412, -412,
+
+     -412, -412, -412, -412, -412, -412, -412, -412, -412, -412,
+     -412, -412, -412, -412, -412, -412, -412, -412, -412, -412,
+     -412, -412, -412, -412, -412, -412, -412, -412, -412, -412,
+     -412, -412, -412, -412, -412, -412, -412, -412, -412, -412,
+     -412, -412,  534, -412, -412, -412, -412, -412, -412, -412,
+     -412, -412, -412, -412, -412, -412, -412, -412, -412, -412,
+     -412, -412, -412, -412, -412, -412, -412, -412, -412, -412,
+     -412, -412, -412, -412, -412, -412, -412, -412, -412, -412,
+     -412, -412, -412, -412, -412, -412, -412, -412
+    },
+
+    {
+       67, -413, -413, -413, -413, -413, -413, -413, -413, -413,
+
+     -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
+     -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
+     -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
+     -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
+     -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
+     -413, -413, -413, -413, -413, -413, -413, -413, -413,  535,
+     -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
+     -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
+     -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
+     -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
+
+     -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
+     -413, -413, -413, -413, -413, -413, -413, -413
+    },
+
+    {
+       67, -414, -414, -414, -414, -414, -414, -414, -414, -414,
+     -414, -414, -414, -414, -414, -414, -414, -414, -414, -414,
+     -414, -414, -414, -414, -414, -414, -414, -414, -414, -414,
+     -414, -414, -414, -414, -414, -414, -414, -414, -414, -414,
+     -414, -414, -414, -414, -414, -414, -414, -414, -414, -414,
+     -414, -414, -414, -414, -414, -414, -414, -414, -414, -414,
+     -414, -414, -414, -414, -414, -414, -414, -414, -414, -414,
+     -414, -414, -414, -414, -414, -414, -414, -414, -414, -414,
+
+     -414, -414, -414, -414,  536, -414, -414, -414, -414, -414,
+     -414, -414, -414, -414, -414, -414, -414, -414, -414, -414,
+     -414, -414, -414, -414, -414, -414, -414, -414, -414, -414,
+     -414, -414, -414, -414, -414, -414, -414, -414, -414, -414,
+     -414, -414, -414, -414, -414, -414, -414, -414
+    },
+
+    {
+       67, -415, -415, -415, -415, -415, -415, -415, -415, -415,
+     -415, -415, -415, -415, -415, -415, -415, -415, -415, -415,
+     -415, -415, -415, -415, -415, -415, -415, -415, -415, -415,
+     -415, -415, -415, -415, -415, -415, -415, -415, -415, -415,
+     -415, -415, -415, -415, -415,  537, -415, -415, -415, -415,
+
+     -415, -415, -415, -415, -415, -415, -415, -415, -415, -415,
+     -415, -415, -415, -415, -415, -415, -415, -415, -415, -415,
+     -415, -415, -415, -415, -415, -415, -415, -415, -415, -415,
+     -415, -415, -415, -415, -415, -415, -415, -415, -415, -415,
+     -415, -415, -415, -415, -415, -415, -415, -415, -415, -415,
+     -415, -415, -415, -415, -415, -415, -415, -415, -415, -415,
+     -415, -415, -415, -415, -415, -415, -415, -415, -415, -415,
+     -415, -415, -415, -415, -415, -415, -415, -415
+    },
+
+    {
+       67, -416, -416, -416, -416, -416, -416, -416, -416, -416,
+     -416, -416, -416, -416, -416, -416, -416, -416, -416, -416,
+
+     -416, -416, -416, -416, -416, -416, -416, -416, -416, -416,
+     -416, -416, -416, -416, -416, -416, -416, -416, -416, -416,
+     -416, -416, -416, -416, -416, -416, -416, -416, -416, -416,
+     -416, -416, -416, -416, -416, -416, -416, -416, -416, -416,
+     -416, -416, -416, -416, -416, -416, -416, -416, -416, -416,
+     -416, -416, -416, -416, -416, -416, -416, -416, -416, -416,
+     -416, -416, -416, -416, -416, -416, -416, -416, -416, -416,
+     -416, -416, -416, -416, -416, -416, -416, -416, -416, -416,
+     -416, -416, -416, -416, -416, -416, -416, -416, -416, -416,
+     -416, -416, -416, -416, -416, -416, -416, -416, -416, -416,
+
+     -416, -416, -416, -416, -416, -416, -416, -416
+    },
+
+    {
+       67, -417, -417, -417, -417, -417, -417, -417, -417, -417,
+     -417, -417, -417, -417, -417, -417, -417, -417, -417, -417,
+     -417, -417, -417, -417, -417, -417, -417, -417, -417, -417,
+     -417, -417, -417, -417, -417, -417, -417, -417, -417, -417,
+     -417, -417, -417, -417, -417, -417, -417, -417, -417,  538,
+      538,  538,  538,  538,  538,  538,  538,  538, -417, -417,
+     -417, -417, -417, -417, -417, -417, -417, -417, -417, -417,
+     -417, -417, -417, -417, -417, -417, -417, -417, -417, -417,
+     -417, -417, -417, -417, -417, -417, -417, -417, -417, -417,
+
+     -417, -417, -417, -417, -417, -417, -417, -417, -417, -417,
+     -417, -417, -417, -417, -417, -417, -417, -417, -417, -417,
+     -417, -417, -417, -417, -417, -417, -417, -417, -417, -417,
+     -417, -417, -417, -417, -417, -417, -417, -417
+    },
+
+    {
+       67, -418, -418, -418, -418, -418, -418, -418, -418, -418,
+     -418, -418, -418, -418, -418, -418, -418, -418, -418, -418,
+     -418, -418, -418, -418, -418, -418, -418, -418, -418, -418,
+     -418, -418,  539, -418, -418, -418, -418, -418, -418, -418,
+     -418, -418, -418, -418, -418, -418, -418, -418, -418, -418,
+     -418, -418, -418, -418, -418, -418, -418, -418, -418, -418,
+
+     -418, -418, -418, -418, -418, -418, -418, -418, -418, -418,
+     -418, -418, -418, -418, -418, -418, -418, -418, -418, -418,
+     -418, -418, -418, -418, -418, -418, -418, -418, -418, -418,
+     -418, -418, -418, -418, -418, -418, -418, -418, -418, -418,
+     -418, -418, -418, -418, -418, -418, -418, -418, -418, -418,
+     -418, -418, -418, -418, -418, -418, -418, -418, -418, -418,
+     -418, -418, -418, -418, -418, -418, -418, -418
+    },
+
+    {
+       67, -419, -419, -419, -419, -419, -419, -419, -419, -419,
+     -419, -419, -419, -419, -419, -419, -419, -419, -419, -419,
+     -419, -419, -419, -419, -419, -419, -419, -419, -419, -419,
+
+     -419, -419, -419, -419, -419, -419, -419, -419, -419, -419,
+     -419, -419, -419, -419, -419, -419, -419, -419, -419, -419,
+     -419, -419, -419, -419, -419, -419, -419, -419, -419, -419,
+     -419, -419, -419, -419, -419, -419, -419, -419, -419, -419,
+     -419, -419,  540, -419, -419, -419, -419, -419, -419, -419,
+     -419, -419, -419, -419, -419, -419, -419, -419, -419, -419,
+     -419, -419, -419, -419, -419, -419, -419, -419, -419, -419,
+     -419, -419, -419, -419, -419, -419, -419, -419, -419, -419,
+     -419, -419, -419, -419, -419, -419, -419, -419, -419, -419,
+     -419, -419, -419, -419, -419, -419, -419, -419
+
+    },
+
+    {
+       67, -420, -420, -420, -420, -420, -420, -420, -420, -420,
+     -420, -420, -420, -420, -420, -420, -420, -420, -420, -420,
+     -420, -420, -420, -420, -420, -420, -420, -420, -420, -420,
+     -420, -420, -420, -420, -420, -420, -420, -420, -420, -420,
+     -420, -420, -420, -420, -420, -420, -420, -420, -420, -420,
+     -420, -420, -420, -420, -420, -420, -420, -420, -420, -420,
+     -420, -420, -420, -420, -420, -420, -420, -420, -420, -420,
+     -420, -420, -420, -420, -420, -420, -420, -420,  541, -420,
+     -420, -420, -420, -420, -420, -420, -420, -420, -420, -420,
+     -420, -420, -420, -420, -420, -420, -420, -420, -420, -420,
+
+     -420, -420, -420, -420, -420, -420, -420, -420, -420, -420,
+     -420, -420, -420, -420, -420, -420, -420, -420, -420, -420,
+     -420, -420, -420, -420, -420, -420, -420, -420
+    },
+
+    {
+       67, -421, -421, -421, -421, -421, -421, -421, -421, -421,
+     -421, -421, -421, -421, -421, -421, -421, -421, -421, -421,
+     -421, -421, -421, -421, -421, -421, -421, -421, -421, -421,
+     -421, -421, -421, -421, -421, -421, -421, -421, -421, -421,
+     -421, -421, -421, -421, -421, -421, -421, -421, -421, -421,
+     -421, -421, -421, -421, -421, -421, -421, -421, -421, -421,
+     -421, -421, -421, -421, -421, -421, -421, -421, -421, -421,
+
+     -421, -421, -421, -421, -421, -421, -421, -421, -421,  542,
+     -421, -421, -421, -421, -421, -421, -421, -421, -421, -421,
+     -421, -421, -421, -421, -421, -421, -421, -421, -421, -421,
+     -421, -421, -421, -421, -421, -421, -421, -421, -421, -421,
+     -421, -421, -421, -421, -421, -421, -421, -421, -421, -421,
+     -421, -421, -421, -421, -421, -421, -421, -421
+    },
+
+    {
+       67, -422, -422, -422, -422, -422, -422, -422, -422, -422,
+     -422, -422, -422, -422, -422, -422, -422, -422, -422, -422,
+     -422, -422, -422, -422, -422, -422, -422, -422, -422, -422,
+     -422, -422, -422, -422, -422, -422, -422, -422, -422, -422,
+
+     -422, -422, -422, -422, -422, -422, -422, -422, -422, -422,
+     -422, -422, -422, -422, -422, -422, -422, -422, -422, -422,
+     -422, -422, -422, -422, -422, -422, -422, -422, -422, -422,
+     -422, -422, -422, -422, -422, -422, -422, -422, -422,  543,
+     -422, -422, -422, -422, -422, -422, -422, -422, -422, -422,
+     -422, -422, -422, -422, -422, -422, -422, -422, -422, -422,
+     -422, -422, -422, -422, -422, -422, -422, -422, -422, -422,
+     -422, -422, -422, -422, -422, -422, -422, -422, -422, -422,
+     -422, -422, -422, -422, -422, -422, -422, -422
+    },
+
+    {
+       67, -423, -423, -423, -423, -423, -423, -423, -423, -423,
+
+     -423, -423, -423, -423, -423, -423, -423, -423, -423, -423,
+     -423, -423, -423, -423, -423, -423, -423, -423, -423, -423,
+     -423, -423, -423, -423, -423, -423, -423, -423, -423, -423,
+     -423, -423, -423, -423, -423, -423, -423, -423, -423, -423,
+     -423, -423, -423, -423, -423, -423, -423, -423, -423, -423,
+     -423, -423, -423, -423, -423,  544, -423, -423, -423, -423,
+     -423, -423, -423, -423, -423, -423, -423, -423, -423,  545,
+     -423, -423, -423, -423, -423, -423, -423, -423, -423, -423,
+     -423, -423, -423, -423, -423, -423, -423, -423, -423, -423,
+     -423, -423, -423, -423, -423, -423, -423, -423, -423, -423,
+
+     -423, -423, -423, -423, -423, -423, -423, -423, -423, -423,
+     -423, -423, -423, -423, -423, -423, -423, -423
+    },
+
+    {
+       67, -424, -424, -424, -424, -424, -424, -424, -424, -424,
+     -424, -424, -424, -424, -424, -424, -424, -424, -424, -424,
+     -424, -424, -424, -424, -424, -424, -424, -424, -424, -424,
+     -424, -424, -424, -424, -424, -424, -424, -424, -424, -424,
+     -424, -424, -424, -424, -424, -424, -424, -424, -424, -424,
+     -424, -424, -424, -424, -424, -424, -424, -424, -424, -424,
+     -424, -424, -424, -424, -424, -424, -424, -424, -424, -424,
+     -424, -424, -424, -424, -424, -424, -424, -424, -424, -424,
+
+     -424, -424, -424, -424, -424, -424, -424, -424, -424, -424,
+     -424, -424, -424, -424, -424, -424, -424, -424, -424, -424,
+     -424, -424, -424, -424, -424, -424, -424, -424, -424, -424,
+     -424, -424, -424, -424, -424, -424, -424, -424, -424, -424,
+     -424, -424, -424, -424, -424, -424, -424, -424
+    },
+
+    {
+       67, -425, -425, -425, -425, -425, -425, -425, -425, -425,
+     -425, -425, -425, -425, -425, -425, -425, -425, -425, -425,
+     -425, -425, -425, -425, -425, -425, -425, -425, -425, -425,
+     -425, -425, -425, -425, -425, -425, -425, -425, -425, -425,
+     -425, -425, -425, -425, -425, -425, -425, -425, -425, -425,
+
+     -425, -425, -425, -425, -425, -425, -425, -425, -425, -425,
+     -425, -425, -425, -425, -425, -425,  546, -425, -425, -425,
+     -425, -425, -425, -425, -425, -425, -425, -425, -425, -425,
+     -425, -425, -425, -425, -425, -425, -425, -425, -425, -425,
+     -425, -425, -425, -425, -425, -425, -425, -425, -425, -425,
+     -425, -425, -425, -425, -425, -425, -425, -425, -425, -425,
+     -425, -425, -425, -425, -425, -425, -425, -425, -425, -425,
+     -425, -425, -425, -425, -425, -425, -425, -425
+    },
+
+    {
+       67, -426, -426, -426, -426, -426, -426, -426, -426, -426,
+     -426, -426, -426, -426, -426, -426, -426, -426, -426, -426,
+
+     -426, -426, -426, -426, -426, -426, -426, -426, -426, -426,
+     -426, -426, -426, -426, -426, -426, -426, -426, -426, -426,
+     -426, -426, -426, -426, -426, -426, -426, -426, -426, -426,
+     -426, -426, -426, -426, -426, -426, -426, -426, -426, -426,
+     -426, -426, -426, -426, -426, -426, -426, -426, -426,  547,
+     -426, -426, -426, -426, -426, -426, -426, -426, -426, -426,
+     -426, -426, -426, -426, -426, -426, -426, -426,  548,  549,
+      550, -426, -426, -426, -426, -426, -426, -426, -426, -426,
+     -426, -426, -426, -426, -426, -426, -426, -426, -426, -426,
+     -426, -426, -426, -426, -426, -426, -426, -426, -426, -426,
+
+     -426, -426, -426, -426, -426, -426, -426, -426
+    },
+
+    {
+       67, -427, -427, -427, -427, -427, -427, -427, -427, -427,
+     -427, -427, -427, -427, -427, -427, -427, -427, -427, -427,
+     -427, -427, -427, -427, -427, -427, -427, -427, -427, -427,
+     -427, -427, -427, -427, -427, -427, -427, -427, -427, -427,
+     -427, -427, -427, -427, -427, -427, -427, -427, -427, -427,
+     -427, -427, -427, -427, -427, -427, -427, -427, -427, -427,
+     -427, -427, -427, -427, -427, -427, -427, -427, -427, -427,
+     -427, -427, -427, -427, -427, -427, -427, -427, -427, -427,
+      551, -427, -427, -427, -427, -427, -427, -427, -427, -427,
+
+     -427, -427, -427, -427, -427, -427, -427, -427, -427, -427,
+     -427, -427, -427, -427, -427, -427, -427, -427, -427, -427,
+     -427, -427, -427, -427, -427, -427, -427, -427, -427, -427,
+     -427, -427, -427, -427, -427, -427, -427, -427
+    },
+
+    {
+       67, -428, -428, -428, -428, -428, -428, -428, -428, -428,
+     -428, -428, -428, -428, -428, -428, -428, -428, -428, -428,
+     -428, -428, -428, -428, -428, -428, -428, -428, -428, -428,
+     -428, -428, -428, -428, -428, -428, -428, -428, -428, -428,
+     -428, -428, -428, -428, -428, -428, -428, -428, -428, -428,
+     -428, -428, -428, -428, -428, -428, -428, -428, -428, -428,
+
+     -428, -428, -428, -428, -428, -428, -428,  552, -428, -428,
+     -428, -428, -428, -428, -428, -428, -428, -428, -428, -428,
+     -428, -428, -428,  553, -428, -428, -428, -428, -428, -428,
+     -428, -428, -428, -428, -428, -428, -428, -428, -428, -428,
+     -428, -428, -428, -428, -428, -428, -428, -428, -428, -428,
+     -428, -428, -428, -428, -428, -428, -428, -428, -428, -428,
+     -428, -428, -428, -428, -428, -428, -428, -428
+    },
+
+    {
+       67, -429, -429, -429, -429, -429, -429, -429, -429, -429,
+     -429, -429, -429, -429, -429, -429, -429, -429, -429, -429,
+     -429, -429, -429, -429, -429, -429, -429, -429, -429, -429,
+
+     -429, -429, -429, -429, -429, -429, -429, -429, -429, -429,
+     -429, -429, -429, -429, -429, -429, -429, -429, -429, -429,
+     -429, -429, -429, -429, -429, -429, -429, -429, -429, -429,
+     -429, -429, -429, -429, -429, -429, -429, -429, -429, -429,
+      554, -429, -429, -429, -429, -429, -429, -429, -429, -429,
+     -429, -429, -429, -429, -429, -429, -429,  555, -429, -429,
+     -429, -429, -429, -429, -429, -429, -429, -429, -429, -429,
+     -429, -429, -429, -429, -429, -429, -429, -429, -429, -429,
+     -429, -429, -429, -429, -429, -429, -429, -429, -429, -429,
+     -429, -429, -429, -429, -429, -429, -429, -429
+
+    },
+
+    {
+       67, -430, -430, -430, -430, -430, -430, -430, -430, -430,
+     -430, -430, -430, -430, -430, -430, -430, -430, -430, -430,
+     -430, -430, -430, -430, -430, -430, -430, -430, -430, -430,
+     -430, -430, -430, -430, -430, -430, -430, -430, -430, -430,
+     -430, -430, -430, -430, -430, -430, -430, -430, -430, -430,
+     -430, -430, -430, -430, -430, -430, -430, -430, -430, -430,
+     -430, -430, -430, -430, -430, -430, -430, -430, -430, -430,
+     -430, -430, -430, -430, -430, -430, -430, -430, -430, -430,
+     -430, -430, -430, -430, -430, -430, -430, -430, -430, -430,
+     -430, -430, -430, -430, -430, -430, -430, -430, -430, -430,
+
+     -430, -430, -430, -430, -430, -430, -430, -430, -430, -430,
+     -430, -430, -430, -430, -430, -430, -430, -430, -430, -430,
+     -430, -430, -430, -430, -430, -430, -430, -430
+    },
+
+    {
+       67, -431, -431, -431, -431, -431, -431, -431, -431, -431,
+     -431, -431, -431, -431, -431, -431, -431, -431, -431, -431,
+     -431, -431, -431, -431, -431, -431, -431, -431, -431, -431,
+     -431, -431, -431, -431, -431, -431, -431, -431, -431, -431,
+     -431, -431, -431, -431, -431, -431, -431, -431, -431, -431,
+     -431, -431, -431, -431, -431, -431, -431, -431, -431, -431,
+     -431, -431, -431, -431, -431, -431, -431, -431, -431, -431,
+
+     -431, -431, -431, -431, -431, -431, -431, -431, -431, -431,
+     -431, -431, -431, -431, -431, -431, -431, -431, -431, -431,
+     -431, -431, -431, -431, -431, -431, -431, -431, -431, -431,
+     -431, -431, -431, -431, -431, -431, -431, -431, -431, -431,
+     -431, -431, -431, -431, -431, -431, -431, -431, -431, -431,
+     -431, -431, -431, -431, -431, -431, -431, -431
+    },
+
+    {
+       67, -432, -432, -432, -432, -432, -432, -432, -432, -432,
+     -432, -432, -432, -432, -432, -432, -432, -432, -432, -432,
+     -432, -432, -432, -432, -432, -432, -432, -432, -432, -432,
+     -432, -432, -432, -432, -432, -432, -432, -432, -432, -432,
+
+     -432, -432, -432, -432, -432, -432, -432, -432, -432, -432,
+     -432, -432, -432, -432, -432, -432, -432, -432, -432, -432,
+     -432, -432, -432, -432, -432, -432, -432, -432, -432, -432,
+     -432, -432, -432, -432, -432, -432, -432, -432, -432, -432,
+     -432, -432, -432, -432, -432, -432, -432, -432, -432, -432,
+     -432, -432, -432, -432, -432, -432, -432, -432, -432, -432,
+     -432, -432, -432, -432, -432, -432, -432, -432, -432, -432,
+     -432, -432, -432, -432, -432, -432, -432, -432, -432, -432,
+     -432, -432, -432, -432, -432, -432, -432, -432
+    },
+
+    {
+       67, -433, -433, -433, -433, -433, -433, -433, -433, -433,
+
+     -433, -433, -433, -433, -433, -433, -433, -433, -433, -433,
+     -433, -433, -433, -433, -433, -433, -433, -433, -433, -433,
+     -433, -433, -433, -433, -433, -433, -433, -433, -433, -433,
+     -433, -433, -433, -433, -433, -433, -433, -433, -433, -433,
+     -433, -433, -433, -433, -433, -433, -433, -433, -433, -433,
+     -433, -433, -433, -433, -433, -433, -433, -433, -433, -433,
+     -433, -433, -433, -433, -433, -433, -433, -433, -433, -433,
+     -433, -433, -433,  556, -433, -433, -433, -433, -433, -433,
+     -433, -433, -433, -433, -433, -433, -433, -433, -433, -433,
+     -433, -433, -433, -433, -433, -433, -433, -433, -433, -433,
+
+     -433, -433, -433, -433, -433, -433, -433, -433, -433, -433,
+     -433, -433, -433, -433, -433, -433, -433, -433
+    },
+
+    {
+       67, -434, -434, -434, -434, -434, -434, -434, -434, -434,
+     -434, -434, -434, -434, -434, -434, -434, -434, -434, -434,
+     -434, -434, -434, -434, -434, -434, -434, -434, -434, -434,
+     -434, -434, -434, -434, -434, -434, -434, -434, -434, -434,
+     -434, -434, -434, -434, -434, -434, -434, -434, -434, -434,
+     -434, -434, -434, -434, -434, -434, -434, -434, -434, -434,
+     -434, -434, -434, -434, -434, -434, -434, -434, -434, -434,
+     -434, -434, -434, -434, -434, -434, -434, -434, -434, -434,
+
+     -434, -434, -434, -434, -434, -434, -434, -434, -434, -434,
+     -434, -434, -434, -434, -434, -434, -434, -434, -434, -434,
+     -434, -434, -434, -434, -434, -434, -434, -434, -434, -434,
+     -434, -434, -434, -434, -434, -434, -434, -434, -434, -434,
+     -434, -434, -434, -434, -434, -434, -434, -434
+    },
+
+    {
+       67, -435, -435, -435, -435, -435, -435, -435, -435, -435,
+     -435, -435, -435, -435, -435, -435, -435, -435, -435, -435,
+     -435, -435, -435, -435, -435, -435, -435, -435, -435, -435,
+     -435, -435, -435, -435, -435, -435, -435, -435, -435, -435,
+     -435, -435, -435, -435, -435, -435, -435, -435, -435, -435,
+
+     -435, -435, -435, -435, -435, -435, -435, -435, -435, -435,
+     -435, -435, -435, -435, -435, -435, -435, -435, -435, -435,
+     -435, -435, -435, -435, -435, -435, -435, -435, -435,  557,
+     -435, -435, -435,  558, -435, -435, -435, -435, -435, -435,
+     -435, -435, -435, -435, -435, -435, -435, -435, -435, -435,
+     -435, -435, -435, -435, -435, -435, -435, -435, -435, -435,
+     -435, -435, -435, -435, -435, -435, -435, -435, -435, -435,
+     -435, -435, -435, -435, -435, -435, -435, -435
+    },
+
+    {
+       67, -436, -436, -436, -436, -436, -436, -436, -436, -436,
+     -436, -436, -436, -436, -436, -436, -436, -436, -436, -436,
+
+     -436, -436, -436, -436, -436, -436, -436, -436, -436, -436,
+     -436, -436, -436, -436, -436, -436, -436, -436, -436, -436,
+     -436, -436, -436, -436, -436, -436, -436, -436, -436, -436,
+     -436, -436, -436, -436, -436, -436, -436, -436, -436, -436,
+     -436, -436, -436, -436, -436, -436, -436, -436, -436, -436,
+     -436, -436, -436, -436, -436, -436, -436, -436, -436, -436,
+     -436, -436, -436, -436, -436, -436, -436, -436, -436, -436,
+     -436, -436, -436, -436, -436, -436, -436, -436, -436, -436,
+     -436, -436, -436, -436, -436, -436, -436, -436, -436, -436,
+     -436, -436, -436, -436, -436, -436, -436, -436, -436, -436,
+
+     -436, -436, -436, -436, -436, -436, -436, -436
+    },
+
+    {
+       67, -437, -437, -437, -437, -437, -437, -437, -437, -437,
+     -437, -437, -437, -437, -437, -437, -437, -437, -437, -437,
+     -437, -437, -437, -437, -437, -437, -437, -437, -437, -437,
+     -437, -437, -437, -437, -437, -437, -437, -437, -437, -437,
+     -437, -437, -437, -437, -437, -437, -437, -437, -437, -437,
+     -437, -437, -437, -437, -437, -437, -437, -437, -437, -437,
+     -437, -437, -437, -437, -437, -437, -437, -437, -437, -437,
+     -437, -437, -437, -437, -437, -437, -437, -437, -437, -437,
+     -437, -437, -437, -437,  559, -437, -437, -437, -437, -437,
+
+     -437, -437, -437, -437, -437, -437, -437, -437, -437, -437,
+     -437, -437, -437, -437, -437, -437, -437, -437, -437, -437,
+     -437, -437, -437, -437, -437, -437, -437, -437, -437, -437,
+     -437, -437, -437, -437, -437, -437, -437, -437
+    },
+
+    {
+       67, -438, -438, -438, -438, -438, -438, -438, -438, -438,
+     -438, -438, -438, -438, -438, -438, -438, -438, -438, -438,
+     -438, -438, -438, -438, -438, -438, -438, -438, -438, -438,
+     -438, -438, -438, -438, -438, -438, -438, -438, -438, -438,
+     -438, -438, -438, -438, -438, -438, -438, -438, -438, -438,
+     -438, -438, -438, -438, -438, -438, -438, -438, -438, -438,
+
+     -438, -438, -438, -438, -438, -438, -438, -438, -438, -438,
+     -438, -438, -438, -438, -438, -438, -438,  560, -438, -438,
+     -438, -438, -438, -438, -438, -438, -438, -438, -438, -438,
+     -438, -438, -438, -438, -438, -438, -438, -438, -438, -438,
+     -438, -438, -438, -438, -438, -438, -438, -438, -438, -438,
+     -438, -438, -438, -438, -438, -438, -438, -438, -438, -438,
+     -438, -438, -438, -438, -438, -438, -438, -438
+    },
+
+    {
+       67, -439, -439, -439, -439, -439, -439, -439, -439, -439,
+     -439, -439, -439, -439, -439, -439, -439, -439, -439, -439,
+     -439, -439, -439, -439, -439, -439, -439, -439, -439, -439,
+
+     -439, -439, -439, -439, -439, -439, -439, -439, -439, -439,
+     -439, -439, -439, -439, -439, -439, -439, -439, -439, -439,
+     -439, -439, -439, -439, -439, -439, -439, -439, -439, -439,
+     -439, -439, -439, -439, -439, -439, -439, -439, -439,  561,
+     -439, -439, -439, -439, -439, -439, -439, -439, -439, -439,
+     -439, -439, -439, -439, -439, -439, -439, -439, -439, -439,
+     -439, -439, -439, -439, -439, -439, -439, -439, -439, -439,
+     -439, -439, -439, -439, -439, -439, -439, -439, -439, -439,
+     -439, -439, -439, -439, -439, -439, -439, -439, -439, -439,
+     -439, -439, -439, -439, -439, -439, -439, -439
+
+    },
+
+    {
+       67, -440, -440, -440, -440, -440, -440, -440, -440, -440,
+     -440, -440, -440, -440, -440, -440, -440, -440, -440, -440,
+     -440, -440, -440, -440, -440, -440, -440, -440, -440, -440,
+     -440, -440, -440, -440, -440, -440, -440, -440, -440, -440,
+     -440, -440, -440, -440, -440, -440, -440, -440, -440, -440,
+     -440, -440, -440, -440, -440, -440, -440, -440, -440, -440,
+     -440, -440, -440, -440, -440, -440, -440, -440, -440, -440,
+     -440, -440, -440, -440, -440, -440, -440, -440, -440, -440,
+     -440, -440, -440, -440,  562, -440, -440, -440, -440, -440,
+     -440, -440, -440, -440, -440, -440, -440, -440, -440, -440,
+
+     -440, -440, -440, -440, -440, -440, -440, -440, -440, -440,
+     -440, -440, -440, -440, -440, -440, -440, -440, -440, -440,
+     -440, -440, -440, -440, -440, -440, -440, -440
+    },
+
+    {
+       67, -441, -441, -441, -441, -441, -441, -441, -441, -441,
+     -441, -441, -441, -441, -441, -441, -441, -441, -441, -441,
+     -441, -441, -441, -441, -441, -441, -441, -441, -441, -441,
+     -441, -441, -441, -441, -441, -441, -441, -441, -441, -441,
+     -441, -441, -441, -441, -441, -441, -441, -441, -441, -441,
+     -441, -441, -441, -441, -441, -441, -441, -441, -441, -441,
+     -441, -441, -441, -441, -441, -441, -441, -441, -441, -441,
+
+     -441, -441, -441, -441, -441, -441, -441, -441, -441, -441,
+     -441, -441, -441, -441, -441, -441, -441, -441,  563, -441,
+     -441, -441, -441, -441, -441, -441, -441, -441, -441, -441,
+     -441, -441, -441, -441, -441, -441, -441, -441, -441, -441,
+     -441, -441, -441, -441, -441, -441, -441, -441, -441, -441,
+     -441, -441, -441, -441, -441, -441, -441, -441
+    },
+
+    {
+       67, -442, -442, -442, -442, -442, -442, -442, -442, -442,
+     -442, -442, -442, -442, -442, -442, -442, -442, -442, -442,
+     -442, -442, -442, -442, -442, -442, -442, -442, -442, -442,
+     -442, -442, -442, -442, -442, -442, -442, -442, -442, -442,
+
+     -442, -442, -442, -442, -442, -442, -442, -442, -442, -442,
+     -442, -442, -442, -442, -442, -442, -442, -442, -442, -442,
+     -442, -442, -442, -442, -442, -442, -442, -442, -442, -442,
+     -442, -442, -442, -442, -442, -442,  564, -442, -442, -442,
+     -442, -442, -442, -442, -442, -442, -442, -442, -442, -442,
+     -442, -442, -442, -442, -442, -442, -442, -442, -442, -442,
+     -442, -442, -442, -442, -442, -442, -442, -442, -442, -442,
+     -442, -442, -442, -442, -442, -442, -442, -442, -442, -442,
+     -442, -442, -442, -442, -442, -442, -442, -442
+    },
+
+    {
+       67, -443, -443, -443, -443, -443, -443, -443, -443, -443,
+
+     -443, -443, -443, -443, -443, -443, -443, -443, -443, -443,
+     -443, -443, -443, -443, -443, -443, -443, -443, -443, -443,
+     -443, -443, -443, -443, -443, -443, -443, -443, -443, -443,
+     -443, -443, -443, -443, -443, -443, -443, -443, -443, -443,
+     -443, -443, -443, -443, -443, -443, -443, -443, -443, -443,
+     -443, -443, -443, -443, -443, -443, -443, -443, -443,  565,
+     -443, -443, -443, -443, -443, -443, -443, -443, -443, -443,
+     -443, -443, -443, -443, -443, -443, -443, -443, -443, -443,
+     -443, -443, -443, -443, -443, -443, -443, -443, -443, -443,
+     -443, -443, -443, -443, -443, -443, -443, -443, -443, -443,
+
+     -443, -443, -443, -443, -443, -443, -443, -443, -443, -443,
+     -443, -443, -443, -443, -443, -443, -443, -443
+    },
+
+    {
+       67, -444, -444, -444, -444, -444, -444, -444, -444, -444,
+     -444, -444, -444, -444, -444, -444, -444, -444, -444, -444,
+     -444, -444, -444, -444, -444, -444, -444, -444, -444, -444,
+     -444, -444, -444, -444, -444, -444, -444, -444, -444, -444,
+     -444, -444, -444, -444, -444, -444, -444, -444, -444, -444,
+     -444, -444, -444, -444, -444, -444, -444, -444, -444, -444,
+     -444, -444, -444, -444, -444, -444, -444, -444, -444, -444,
+     -444, -444, -444, -444, -444, -444, -444, -444, -444, -444,
+
+      566, -444, -444, -444, -444, -444, -444, -444, -444, -444,
+     -444, -444, -444, -444, -444, -444, -444, -444, -444, -444,
+     -444, -444, -444, -444, -444, -444, -444, -444, -444, -444,
+     -444, -444, -444, -444, -444, -444, -444, -444, -444, -444,
+     -444, -444, -444, -444, -444, -444, -444, -444
+    },
+
+    {
+       67, -445, -445, -445, -445, -445, -445, -445, -445, -445,
+     -445, -445, -445, -445, -445, -445, -445, -445, -445, -445,
+     -445, -445, -445, -445, -445, -445, -445, -445, -445, -445,
+     -445, -445, -445, -445, -445, -445, -445, -445, -445, -445,
+     -445, -445, -445, -445, -445, -445, -445, -445, -445, -445,
+
+     -445, -445, -445, -445, -445, -445, -445, -445, -445, -445,
+     -445, -445, -445, -445, -445, -445, -445, -445, -445, -445,
+     -445, -445, -445,  567, -445, -445, -445, -445, -445, -445,
+     -445, -445, -445, -445, -445, -445, -445, -445, -445, -445,
+     -445, -445, -445, -445, -445, -445, -445, -445, -445, -445,
+     -445, -445, -445, -445, -445, -445, -445, -445, -445, -445,
+     -445, -445, -445, -445, -445, -445, -445, -445, -445, -445,
+     -445, -445, -445, -445, -445, -445, -445, -445
+    },
+
+    {
+       67, -446, -446, -446, -446, -446, -446, -446, -446, -446,
+     -446, -446, -446, -446, -446, -446, -446, -446, -446, -446,
+
+     -446, -446, -446, -446, -446, -446, -446, -446, -446, -446,
+     -446, -446, -446, -446, -446, -446, -446, -446, -446, -446,
+     -446, -446, -446, -446, -446, -446, -446, -446, -446, -446,
+     -446, -446, -446, -446, -446, -446, -446, -446, -446, -446,
+     -446, -446, -446, -446, -446, -446, -446, -446, -446, -446,
+     -446, -446, -446, -446, -446, -446,  568, -446, -446, -446,
+     -446, -446, -446, -446, -446, -446, -446, -446, -446, -446,
+     -446, -446, -446, -446, -446, -446, -446, -446, -446, -446,
+     -446, -446, -446, -446, -446, -446, -446, -446, -446, -446,
+     -446, -446, -446, -446, -446, -446, -446, -446, -446, -446,
+
+     -446, -446, -446, -446, -446, -446, -446, -446
+    },
+
+    {
+       67, -447, -447, -447, -447, -447, -447, -447, -447, -447,
+     -447, -447, -447, -447, -447, -447, -447, -447, -447, -447,
+     -447, -447, -447, -447, -447, -447, -447, -447, -447, -447,
+     -447, -447, -447, -447, -447, -447, -447, -447, -447, -447,
+     -447, -447, -447, -447, -447, -447, -447, -447, -447, -447,
+     -447, -447, -447, -447, -447, -447, -447, -447, -447, -447,
+     -447, -447, -447, -447, -447, -447, -447, -447, -447, -447,
+     -447, -447, -447, -447, -447, -447, -447, -447, -447, -447,
+     -447, -447, -447, -447, -447, -447, -447, -447, -447, -447,
+
+     -447, -447, -447, -447, -447, -447, -447, -447, -447, -447,
+     -447, -447, -447, -447, -447, -447, -447, -447, -447, -447,
+     -447, -447, -447, -447, -447, -447, -447, -447, -447, -447,
+     -447, -447, -447, -447, -447, -447, -447, -447
+    },
+
+    {
+       67, -448, -448, -448, -448, -448, -448, -448, -448, -448,
+     -448, -448, -448, -448, -448, -448, -448, -448, -448, -448,
+     -448, -448, -448, -448, -448, -448, -448, -448, -448, -448,
+     -448, -448, -448, -448, -448, -448, -448, -448, -448, -448,
+     -448, -448, -448, -448, -448, -448, -448, -448, -448, -448,
+     -448, -448, -448, -448, -448, -448, -448, -448, -448, -448,
+
+     -448, -448, -448, -448, -448, -448, -448, -448, -448, -448,
+     -448, -448, -448, -448, -448, -448, -448, -448, -448, -448,
+     -448, -448, -448, -448, -448, -448, -448, -448, -448, -448,
+     -448, -448, -448, -448, -448, -448, -448, -448, -448, -448,
+     -448, -448, -448, -448, -448, -448, -448, -448, -448, -448,
+     -448, -448, -448, -448, -448, -448, -448, -448, -448, -448,
+     -448, -448, -448, -448, -448, -448, -448, -448
+    },
+
+    {
+       67, -449, -449, -449, -449, -449, -449, -449, -449, -449,
+     -449, -449, -449, -449, -449, -449, -449, -449, -449, -449,
+     -449, -449, -449, -449, -449, -449, -449, -449, -449, -449,
+
+     -449, -449, -449, -449, -449, -449, -449, -449, -449, -449,
+     -449, -449, -449, -449, -449, -449, -449, -449, -449, -449,
+     -449, -449, -449, -449, -449, -449, -449, -449, -449, -449,
+     -449, -449, -449, -449, -449, -449, -449, -449, -449, -449,
+     -449, -449, -449, -449, -449, -449, -449, -449,  569, -449,
+     -449, -449, -449, -449, -449, -449, -449, -449, -449, -449,
+     -449, -449, -449, -449, -449, -449, -449, -449, -449, -449,
+     -449, -449, -449, -449, -449, -449, -449, -449, -449, -449,
+     -449, -449, -449, -449, -449, -449, -449, -449, -449, -449,
+     -449, -449, -449, -449, -449, -449, -449, -449
+
+    },
+
+    {
+       67, -450, -450, -450, -450, -450, -450, -450, -450, -450,
+     -450, -450, -450, -450, -450, -450, -450, -450, -450, -450,
+     -450, -450, -450, -450, -450, -450, -450, -450, -450, -450,
+     -450, -450, -450, -450, -450, -450, -450, -450, -450, -450,
+     -450, -450, -450, -450, -450, -450, -450, -450, -450, -450,
+     -450, -450, -450, -450, -450, -450, -450, -450, -450, -450,
+     -450, -450, -450, -450, -450, -450, -450, -450, -450, -450,
+     -450, -450, -450, -450, -450, -450, -450, -450, -450, -450,
+     -450, -450, -450,  570, -450, -450, -450, -450, -450, -450,
+     -450, -450, -450, -450, -450, -450, -450, -450, -450, -450,
+
+     -450, -450, -450, -450, -450, -450, -450, -450, -450, -450,
+     -450, -450, -450, -450, -450, -450, -450, -450, -450, -450,
+     -450, -450, -450, -450, -450, -450, -450, -450
+    },
+
+    {
+       67, -451, -451, -451, -451, -451, -451, -451, -451, -451,
+     -451, -451, -451, -451, -451, -451, -451, -451, -451, -451,
+     -451, -451, -451, -451, -451, -451, -451, -451, -451, -451,
+     -451, -451, -451, -451, -451, -451, -451, -451, -451, -451,
+     -451, -451, -451, -451, -451, -451, -451, -451, -451, -451,
+     -451, -451, -451, -451, -451, -451, -451, -451, -451, -451,
+     -451, -451, -451, -451, -451, -451, -451, -451, -451,  571,
+
+     -451, -451, -451, -451, -451, -451, -451, -451, -451, -451,
+     -451, -451, -451, -451, -451, -451, -451, -451, -451, -451,
+     -451, -451, -451, -451, -451, -451, -451, -451, -451, -451,
+     -451, -451, -451, -451, -451, -451, -451, -451, -451, -451,
+     -451, -451, -451, -451, -451, -451, -451, -451, -451, -451,
+     -451, -451, -451, -451, -451, -451, -451, -451
+    },
+
+    {
+       67, -452, -452, -452, -452, -452, -452, -452, -452, -452,
+     -452, -452, -452, -452, -452, -452, -452, -452, -452, -452,
+     -452, -452, -452, -452, -452, -452, -452, -452, -452, -452,
+     -452, -452, -452, -452, -452, -452, -452, -452, -452, -452,
+
+     -452, -452, -452, -452, -452, -452, -452, -452, -452,  572,
+      572,  572,  572,  572,  572,  572,  572,  572, -452, -452,
+     -452, -452, -452, -452, -452, -452, -452, -452, -452, -452,
+     -452, -452, -452, -452, -452, -452, -452, -452, -452, -452,
+     -452, -452,  573, -452, -452, -452, -452, -452, -452, -452,
+     -452, -452, -452, -452, -452, -452, -452, -452, -452, -452,
+     -452, -452, -452, -452, -452, -452, -452, -452, -452, -452,
+     -452, -452, -452, -452, -452, -452, -452, -452, -452, -452,
+     -452, -452, -452, -452, -452, -452, -452, -452
+    },
+
+    {
+       67, -453, -453, -453, -453, -453, -453, -453, -453, -453,
+
+     -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
+     -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
+     -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
+     -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
+     -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
+     -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
+     -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
+     -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
+     -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
+     -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
+
+     -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
+     -453, -453, -453, -453, -453, -453, -453, -453
+    },
+
+    {
+       67, -454, -454, -454, -454, -454, -454, -454, -454, -454,
+     -454, -454, -454, -454, -454, -454, -454, -454, -454, -454,
+     -454, -454, -454, -454, -454, -454, -454, -454, -454, -454,
+     -454, -454, -454, -454, -454, -454, -454, -454, -454, -454,
+     -454, -454, -454, -454, -454, -454, -454, -454, -454,  574,
+      574,  574,  574,  574,  574,  574,  574,  574, -454, -454,
+     -454, -454, -454, -454, -454, -454, -454, -454, -454, -454,
+     -454, -454, -454, -454, -454, -454, -454, -454, -454, -454,
+
+     -454, -454, -454, -454, -454, -454, -454, -454, -454, -454,
+     -454, -454, -454, -454, -454, -454, -454, -454, -454, -454,
+     -454, -454, -454, -454, -454, -454, -454, -454, -454, -454,
+     -454, -454, -454, -454, -454, -454, -454, -454, -454, -454,
+     -454, -454, -454, -454, -454, -454, -454, -454
+    },
+
+    {
+       67, -455, -455, -455, -455, -455, -455, -455, -455, -455,
+     -455, -455, -455, -455, -455, -455, -455, -455, -455, -455,
+     -455, -455, -455, -455, -455, -455, -455, -455, -455, -455,
+     -455, -455, -455, -455, -455, -455, -455, -455, -455, -455,
+     -455, -455, -455, -455, -455, -455, -455, -455, -455, -455,
+
+     -455, -455, -455, -455, -455, -455, -455, -455, -455, -455,
+     -455, -455, -455, -455, -455, -455, -455, -455, -455, -455,
+     -455, -455, -455, -455, -455, -455, -455, -455, -455, -455,
+     -455, -455, -455, -455, -455, -455, -455, -455,  575, -455,
+     -455, -455, -455, -455, -455, -455, -455, -455, -455, -455,
+     -455, -455, -455, -455, -455, -455, -455, -455, -455, -455,
+     -455, -455, -455, -455, -455, -455, -455, -455, -455, -455,
+     -455, -455, -455, -455, -455, -455, -455, -455
+    },
+
+    {
+       67, -456, -456, -456, -456, -456, -456, -456, -456, -456,
+     -456, -456, -456, -456, -456, -456, -456, -456, -456, -456,
+
+     -456, -456, -456, -456, -456, -456, -456, -456, -456, -456,
+     -456, -456, -456, -456, -456, -456, -456, -456, -456, -456,
+     -456, -456, -456, -456, -456, -456, -456, -456, -456, -456,
+     -456, -456, -456, -456, -456, -456, -456, -456, -456, -456,
+     -456, -456, -456, -456, -456,  576, -456, -456, -456, -456,
+     -456, -456, -456, -456, -456, -456, -456, -456, -456, -456,
+     -456, -456, -456, -456, -456, -456, -456, -456, -456, -456,
+     -456, -456, -456, -456, -456, -456, -456, -456, -456, -456,
+     -456, -456, -456, -456, -456, -456, -456, -456, -456, -456,
+     -456, -456, -456, -456, -456, -456, -456, -456, -456, -456,
+
+     -456, -456, -456, -456, -456, -456, -456, -456
+    },
+
+    {
+       67, -457, -457, -457, -457, -457, -457, -457, -457, -457,
+     -457, -457, -457, -457, -457, -457, -457, -457, -457, -457,
+     -457, -457, -457, -457, -457, -457, -457, -457, -457, -457,
+     -457, -457, -457, -457, -457, -457, -457, -457, -457, -457,
+     -457, -457, -457, -457, -457, -457, -457, -457, -457,  577,
+      577,  577,  577,  577,  577,  577,  577,  577, -457, -457,
+     -457, -457, -457, -457, -457, -457, -457, -457, -457, -457,
+     -457, -457, -457, -457, -457, -457, -457, -457, -457, -457,
+     -457, -457, -457, -457, -457, -457, -457, -457, -457, -457,
+
+     -457, -457, -457, -457, -457, -457, -457, -457, -457, -457,
+     -457, -457, -457, -457, -457, -457, -457, -457, -457, -457,
+     -457, -457, -457, -457, -457, -457, -457, -457, -457, -457,
+     -457, -457, -457, -457, -457, -457, -457, -457
+    },
+
+    {
+       67, -458, -458, -458, -458, -458, -458, -458, -458, -458,
+     -458, -458, -458, -458, -458, -458, -458, -458, -458, -458,
+     -458, -458, -458, -458, -458, -458, -458, -458, -458, -458,
+     -458, -458, -458, -458, -458, -458, -458, -458, -458, -458,
+     -458, -458, -458, -458, -458, -458, -458, -458, -458,  578,
+      578,  578,  578,  578,  578,  578,  578,  578, -458, -458,
+
+     -458, -458, -458, -458, -458, -458, -458, -458, -458, -458,
+     -458, -458, -458, -458, -458, -458, -458, -458, -458, -458,
+     -458, -458, -458, -458, -458, -458, -458, -458, -458, -458,
+     -458, -458, -458, -458, -458, -458, -458, -458, -458, -458,
+     -458, -458, -458, -458, -458, -458, -458, -458, -458, -458,
+     -458, -458, -458, -458, -458, -458, -458, -458, -458, -458,
+     -458, -458, -458, -458, -458, -458, -458, -458
+    },
+
+    {
+       67, -459, -459, -459, -459, -459, -459, -459, -459, -459,
+     -459, -459, -459, -459, -459, -459, -459, -459, -459, -459,
+     -459, -459, -459, -459, -459, -459, -459, -459, -459, -459,
+
+     -459, -459, -459, -459, -459, -459, -459, -459, -459, -459,
+     -459, -459, -459, -459, -459, -459, -459, -459, -459, -459,
+     -459, -459, -459, -459, -459, -459, -459, -459, -459, -459,
+     -459, -459, -459, -459, -459, -459, -459, -459, -459, -459,
+     -459, -459, -459, -459, -459, -459, -459, -459, -459, -459,
+     -459, -459,  579, -459, -459, -459, -459, -459, -459, -459,
+     -459, -459, -459, -459, -459, -459, -459, -459, -459, -459,
+     -459, -459, -459, -459, -459, -459, -459, -459, -459, -459,
+     -459, -459, -459, -459, -459, -459, -459, -459, -459, -459,
+     -459, -459, -459, -459, -459, -459, -459, -459
+
+    },
+
+    {
+       67, -460, -460, -460, -460, -460, -460, -460, -460, -460,
+     -460, -460, -460, -460, -460, -460, -460, -460, -460, -460,
+     -460, -460, -460, -460, -460, -460, -460, -460, -460, -460,
+     -460, -460, -460, -460, -460, -460, -460, -460, -460, -460,
+     -460, -460, -460, -460, -460, -460, -460, -460, -460, -460,
+     -460, -460, -460, -460, -460, -460, -460, -460, -460, -460,
+     -460, -460, -460, -460, -460, -460, -460, -460, -460, -460,
+     -460, -460, -460, -460, -460, -460, -460, -460, -460, -460,
+     -460, -460, -460, -460, -460, -460, -460, -460, -460, -460,
+     -460, -460, -460, -460, -460, -460, -460, -460, -460, -460,
+
+     -460, -460, -460, -460, -460, -460, -460, -460, -460, -460,
+     -460, -460, -460, -460, -460, -460, -460, -460, -460, -460,
+     -460, -460, -460, -460, -460, -460, -460, -460
+    },
+
+    {
+       67, -461, -461, -461, -461, -461, -461, -461, -461, -461,
+     -461, -461, -461, -461, -461, -461, -461, -461, -461, -461,
+     -461, -461, -461, -461, -461, -461, -461, -461, -461, -461,
+     -461, -461, -461, -461, -461, -461, -461, -461, -461, -461,
+     -461, -461, -461, -461, -461, -461, -461, -461, -461, -461,
+     -461, -461, -461, -461, -461, -461, -461, -461, -461, -461,
+     -461, -461, -461, -461, -461, -461, -461, -461, -461, -461,
+
+     -461, -461, -461, -461, -461, -461, -461, -461, -461, -461,
+     -461, -461, -461, -461, -461, -461, -461, -461, -461, -461,
+     -461, -461, -461, -461, -461, -461, -461, -461, -461, -461,
+     -461, -461, -461, -461, -461, -461, -461, -461, -461, -461,
+     -461, -461, -461, -461, -461, -461, -461, -461, -461, -461,
+     -461, -461, -461, -461, -461, -461, -461, -461
+    },
+
+    {
+       67, -462, -462, -462, -462, -462, -462, -462, -462, -462,
+     -462, -462, -462, -462, -462, -462, -462, -462, -462, -462,
+     -462, -462, -462, -462, -462, -462, -462, -462, -462, -462,
+     -462, -462, -462, -462, -462, -462, -462, -462, -462, -462,
+
+     -462, -462, -462, -462, -462, -462, -462, -462, -462, -462,
+     -462, -462, -462, -462, -462, -462, -462, -462, -462, -462,
+     -462, -462, -462, -462, -462, -462, -462, -462, -462, -462,
+     -462, -462, -462, -462, -462, -462, -462, -462, -462, -462,
+     -462, -462, -462, -462, -462, -462, -462, -462, -462, -462,
+     -462, -462, -462, -462, -462, -462, -462, -462, -462, -462,
+     -462, -462, -462, -462, -462, -462, -462, -462, -462, -462,
+     -462, -462, -462, -462, -462, -462, -462, -462, -462, -462,
+     -462, -462, -462, -462, -462, -462, -462, -462
+    },
+
+    {
+       67, -463, -463, -463, -463, -463, -463, -463, -463, -463,
+
+     -463, -463, -463, -463, -463, -463, -463, -463, -463, -463,
+     -463, -463, -463, -463, -463, -463, -463, -463, -463, -463,
+     -463, -463, -463, -463, -463, -463, -463, -463, -463, -463,
+     -463, -463, -463, -463, -463, -463, -463, -463, -463, -463,
+     -463, -463, -463, -463, -463, -463, -463, -463, -463, -463,
+     -463, -463, -463, -463, -463, -463, -463, -463, -463, -463,
+     -463, -463, -463, -463, -463, -463, -463, -463, -463, -463,
+     -463, -463, -463, -463, -463, -463, -463, -463, -463, -463,
+     -463, -463, -463, -463, -463, -463, -463, -463, -463, -463,
+     -463, -463, -463, -463, -463, -463, -463, -463, -463, -463,
+
+     -463, -463, -463, -463, -463, -463, -463, -463, -463, -463,
+     -463, -463, -463, -463, -463, -463, -463, -463
+    },
+
+    {
+       67, -464, -464, -464, -464, -464, -464, -464, -464, -464,
+     -464, -464, -464, -464, -464, -464, -464, -464, -464, -464,
+     -464, -464, -464, -464, -464, -464, -464, -464, -464, -464,
+     -464, -464, -464, -464, -464, -464, -464, -464, -464, -464,
+     -464, -464, -464, -464, -464, -464, -464, -464, -464, -464,
+     -464, -464, -464, -464, -464, -464, -464, -464, -464, -464,
+     -464, -464, -464, -464, -464, -464, -464, -464, -464, -464,
+     -464, -464, -464, -464, -464, -464, -464, -464, -464, -464,
+
+     -464, -464, -464, -464, -464, -464, -464, -464, -464, -464,
+     -464, -464, -464, -464, -464, -464, -464, -464, -464, -464,
+     -464, -464, -464, -464, -464, -464, -464, -464, -464, -464,
+     -464, -464, -464, -464, -464, -464, -464, -464, -464, -464,
+     -464, -464, -464, -464, -464, -464, -464, -464
+    },
+
+    {
+       67, -465, -465, -465, -465, -465, -465, -465, -465, -465,
+     -465, -465, -465, -465, -465, -465, -465, -465, -465, -465,
+     -465, -465, -465, -465, -465, -465, -465, -465, -465, -465,
+     -465, -465, -465, -465, -465, -465, -465, -465, -465, -465,
+     -465, -465, -465, -465, -465, -465, -465, -465, -465, -465,
+
+     -465, -465, -465, -465, -465, -465, -465, -465, -465, -465,
+     -465, -465, -465, -465, -465, -465, -465, -465, -465, -465,
+     -465, -465, -465, -465, -465, -465, -465, -465, -465, -465,
+     -465, -465, -465, -465, -465, -465, -465, -465, -465, -465,
+     -465, -465, -465, -465, -465, -465, -465, -465, -465, -465,
+     -465, -465, -465, -465, -465, -465, -465, -465, -465, -465,
+     -465, -465, -465, -465, -465, -465, -465, -465, -465, -465,
+     -465, -465, -465, -465, -465, -465, -465, -465
+    },
+
+    {
+       67, -466, -466, -466, -466, -466, -466, -466, -466, -466,
+     -466, -466, -466, -466, -466, -466, -466, -466, -466, -466,
+
+     -466, -466, -466, -466, -466, -466, -466, -466, -466, -466,
+     -466, -466, -466, -466, -466, -466, -466, -466, -466, -466,
+     -466, -466, -466, -466, -466, -466, -466, -466,  580,  580,
+      580,  580,  580,  580,  580,  580,  580,  580, -466, -466,
+     -466, -466, -466, -466, -466, -466, -466, -466, -466, -466,
+     -466, -466, -466, -466, -466, -466, -466, -466, -466, -466,
+     -466, -466, -466, -466, -466, -466, -466, -466, -466, -466,
+     -466, -466, -466, -466, -466, -466, -466, -466, -466, -466,
+     -466, -466, -466, -466, -466, -466, -466, -466, -466, -466,
+     -466, -466, -466, -466, -466, -466, -466, -466, -466, -466,
+
+     -466, -466, -466, -466, -466, -466, -466, -466
+    },
+
+    {
+       67, -467, -467, -467, -467, -467, -467, -467, -467, -467,
+     -467, -467, -467, -467, -467, -467, -467, -467, -467, -467,
+     -467, -467, -467, -467, -467, -467, -467, -467, -467, -467,
+     -467, -467, -467, -467, -467, -467, -467, -467, -467, -467,
+     -467, -467, -467, -467, -467, -467, -467, -467,  580,  580,
+      580,  580,  580,  580,  580,  580,  580,  580, -467, -467,
+     -467, -467, -467, -467, -467, -467, -467, -467, -467, -467,
+     -467, -467, -467, -467, -467, -467, -467, -467, -467, -467,
+     -467, -467, -467, -467, -467, -467, -467, -467, -467, -467,
+
+     -467, -467, -467, -467, -467,  581, -467, -467, -467, -467,
+     -467, -467, -467, -467, -467, -467, -467, -467, -467, -467,
+     -467, -467, -467, -467, -467, -467, -467, -467, -467, -467,
+     -467, -467, -467, -467, -467, -467, -467, -467
+    },
+
+    {
+       67, -468, -468, -468, -468, -468, -468, -468, -468, -468,
+     -468, -468, -468, -468, -468, -468, -468, -468, -468, -468,
+     -468, -468, -468, -468, -468, -468, -468, -468, -468, -468,
+     -468, -468, -468, -468, -468, -468, -468, -468, -468, -468,
+     -468, -468, -468, -468, -468, -468, -468, -468, -468,  582,
+      582,  582,  582,  582,  582,  582,  582,  582, -468, -468,
+
+     -468, -468, -468, -468, -468, -468, -468, -468, -468, -468,
+     -468, -468, -468, -468, -468, -468, -468, -468, -468, -468,
+     -468, -468, -468, -468, -468, -468, -468, -468, -468, -468,
+     -468, -468, -468, -468, -468, -468, -468, -468, -468, -468,
+     -468, -468, -468, -468, -468, -468, -468, -468, -468, -468,
+     -468, -468, -468, -468, -468, -468, -468, -468, -468, -468,
+     -468, -468, -468, -468, -468, -468, -468, -468
+    },
+
+    {
+       67, -469, -469, -469, -469, -469, -469, -469, -469, -469,
+     -469, -469, -469, -469, -469, -469, -469, -469, -469, -469,
+     -469, -469, -469, -469, -469, -469, -469, -469, -469, -469,
+
+     -469, -469,  583, -469, -469, -469, -469, -469, -469, -469,
+     -469, -469, -469, -469, -469, -469, -469, -469,  584,  584,
+      584,  584,  584,  584,  584,  584,  584,  584, -469, -469,
+     -469, -469, -469, -469, -469,  583,  583,  583,  583,  583,
+      583,  583,  583,  583,  583,  583,  583,  583,  583,  583,
+      583,  583,  583,  583,  583,  583,  583,  583,  583,  583,
+      583, -469, -469, -469, -469, -469, -469, -469, -469, -469,
+     -469, -469, -469, -469, -469, -469, -469, -469, -469, -469,
+     -469, -469, -469, -469, -469, -469, -469, -469, -469, -469,
+     -469, -469, -469, -469, -469, -469, -469, -469
+
+    },
+
+    {
+       67, -470, -470, -470, -470, -470, -470, -470, -470, -470,
+     -470, -470, -470, -470, -470, -470, -470, -470, -470, -470,
+     -470, -470, -470, -470, -470, -470, -470, -470, -470, -470,
+     -470, -470,  585, -470, -470, -470, -470, -470, -470, -470,
+     -470, -470, -470, -470, -470, -470, -470, -470, -470, -470,
+     -470, -470, -470, -470, -470, -470, -470, -470, -470, -470,
+     -470, -470, -470, -470, -470, -470, -470, -470, -470, -470,
+     -470, -470, -470, -470, -470, -470, -470, -470, -470, -470,
+     -470, -470, -470, -470, -470, -470, -470, -470, -470, -470,
+     -470, -470, -470, -470, -470, -470, -470, -470, -470, -470,
+
+     -470, -470, -470, -470, -470, -470, -470, -470, -470, -470,
+     -470, -470, -470, -470, -470, -470, -470, -470, -470, -470,
+     -470, -470, -470, -470, -470, -470, -470, -470
+    },
+
+    {
+       67, -471, -471, -471, -471, -471, -471, -471, -471, -471,
+     -471, -471, -471, -471, -471, -471, -471, -471, -471, -471,
+     -471, -471, -471, -471, -471, -471, -471, -471, -471, -471,
+     -471, -471,  586, -471, -471, -471, -471, -471, -471, -471,
+     -471, -471, -471, -471, -471, -471, -471, -471,  587,  587,
+      587,  587,  587,  587,  587,  587,  587,  587, -471, -471,
+     -471, -471, -471, -471, -471,  586,  586,  586,  586,  586,
+
+      586,  586,  586,  586,  586,  586,  586,  586,  586,  586,
+      586,  586,  586,  586,  586,  586,  586,  586,  586,  586,
+      586, -471, -471, -471, -471, -471, -471, -471, -471, -471,
+     -471, -471, -471, -471, -471, -471, -471, -471, -471, -471,
+     -471, -471, -471, -471, -471, -471, -471, -471, -471, -471,
+     -471, -471, -471, -471, -471, -471, -471, -471
+    },
+
+    {
+       67, -472, -472, -472, -472, -472, -472, -472, -472, -472,
+     -472, -472, -472, -472, -472, -472, -472, -472, -472, -472,
+     -472, -472, -472, -472, -472, -472, -472, -472, -472, -472,
+     -472, -472, -472, -472, -472, -472, -472, -472, -472, -472,
+
+     -472, -472, -472, -472, -472, -472, -472, -472, -472, -472,
+     -472, -472, -472, -472, -472, -472, -472, -472, -472, -472,
+     -472, -472, -472, -472, -472, -472, -472, -472, -472, -472,
+     -472, -472, -472, -472, -472, -472, -472, -472, -472, -472,
+     -472, -472, -472, -472, -472, -472, -472, -472, -472, -472,
+     -472, -472, -472, -472, -472, -472, -472, -472, -472, -472,
+     -472, -472, -472, -472, -472, -472, -472, -472, -472, -472,
+     -472, -472, -472, -472, -472, -472, -472, -472, -472, -472,
+     -472, -472, -472, -472, -472, -472, -472, -472
+    },
+
+    {
+       67, -473, -473, -473, -473, -473, -473, -473, -473, -473,
+
+     -473, -473, -473, -473, -473, -473, -473, -473, -473, -473,
+     -473, -473, -473, -473, -473, -473, -473, -473, -473, -473,
+     -473, -473, -473, -473, -473, -473, -473, -473, -473, -473,
+     -473, -473, -473, -473, -473, -473, -473, -473, -473, -473,
+     -473, -473, -473, -473, -473, -473, -473, -473, -473, -473,
+     -473, -473, -473, -473, -473, -473, -473, -473, -473, -473,
+     -473, -473, -473, -473, -473, -473, -473, -473, -473, -473,
+     -473, -473, -473, -473, -473, -473, -473, -473, -473, -473,
+     -473, -473, -473, -473, -473, -473, -473, -473, -473, -473,
+     -473, -473, -473, -473, -473, -473, -473, -473, -473, -473,
+
+     -473, -473, -473, -473, -473, -473, -473, -473, -473, -473,
+     -473, -473, -473, -473, -473, -473, -473, -473
+    },
+
+    {
+       67, -474, -474, -474, -474, -474, -474, -474, -474, -474,
+     -474, -474, -474, -474, -474, -474, -474, -474, -474, -474,
+     -474, -474, -474, -474, -474, -474, -474, -474, -474, -474,
+     -474, -474, -474, -474, -474, -474, -474, -474, -474, -474,
+     -474, -474, -474, -474, -474, -474, -474, -474, -474, -474,
+     -474, -474, -474, -474, -474, -474, -474, -474, -474, -474,
+     -474, -474, -474, -474, -474, -474, -474, -474, -474, -474,
+     -474, -474, -474, -474, -474, -474, -474, -474, -474, -474,
+
+     -474, -474, -474, -474, -474, -474, -474, -474, -474, -474,
+     -474, -474, -474, -474, -474, -474, -474, -474, -474, -474,
+     -474, -474, -474, -474, -474, -474, -474, -474, -474, -474,
+     -474, -474, -474, -474, -474, -474, -474, -474, -474, -474,
+     -474, -474, -474, -474, -474, -474, -474, -474
+    },
+
+    {
+       67, -475, -475, -475, -475, -475, -475, -475, -475, -475,
+     -475, -475, -475, -475, -475, -475, -475, -475, -475, -475,
+     -475, -475, -475, -475, -475, -475, -475, -475, -475, -475,
+     -475, -475, -475, -475, -475, -475, -475, -475, -475, -475,
+     -475, -475, -475, -475, -475, -475, -475, -475, -475, -475,
+
+     -475, -475, -475, -475, -475, -475, -475, -475, -475, -475,
+     -475, -475, -475, -475, -475, -475, -475, -475, -475, -475,
+     -475, -475, -475, -475, -475, -475, -475, -475, -475, -475,
+     -475, -475, -475, -475, -475, -475, -475, -475, -475, -475,
+     -475, -475, -475, -475, -475,  588, -475, -475, -475, -475,
+     -475, -475, -475, -475, -475, -475, -475, -475, -475, -475,
+     -475, -475, -475, -475, -475, -475, -475, -475, -475, -475,
+     -475, -475, -475, -475, -475, -475, -475, -475
+    },
+
+    {
+       67, -476, -476, -476, -476, -476, -476, -476, -476, -476,
+     -476, -476, -476, -476, -476, -476, -476, -476, -476, -476,
+
+     -476, -476, -476, -476, -476, -476, -476, -476, -476, -476,
+     -476, -476, -476, -476, -476, -476, -476, -476, -476, -476,
+     -476, -476, -476, -476, -476, -476, -476, -476, -476,  589,
+      589,  589,  589,  589,  589,  589,  589,  589, -476, -476,
+     -476, -476, -476, -476, -476, -476, -476, -476, -476, -476,
+     -476, -476, -476, -476, -476, -476, -476, -476, -476, -476,
+     -476, -476, -476, -476, -476, -476, -476, -476, -476, -476,
+     -476, -476, -476, -476, -476, -476, -476, -476, -476, -476,
+     -476, -476, -476, -476, -476, -476, -476, -476, -476, -476,
+     -476, -476, -476, -476, -476, -476, -476, -476, -476, -476,
+
+     -476, -476, -476, -476, -476, -476, -476, -476
+    },
+
+    {
+       67, -477, -477, -477, -477, -477, -477, -477, -477, -477,
+     -477, -477, -477, -477, -477, -477, -477, -477, -477, -477,
+     -477, -477, -477, -477, -477, -477, -477, -477, -477, -477,
+     -477, -477,  590, -477, -477, -477, -477, -477, -477, -477,
+     -477, -477, -477, -477, -477, -477, -477, -477,  591,  591,
+      591,  591,  591,  591,  591,  591,  591,  591, -477, -477,
+     -477, -477, -477, -477, -477,  590,  590,  590,  590,  590,
+      590,  590,  590,  590,  590,  590,  590,  590,  590,  590,
+      590,  590,  590,  590,  590,  590,  590,  590,  590,  590,
+
+      590, -477, -477, -477, -477, -477, -477, -477, -477, -477,
+     -477, -477, -477, -477, -477, -477, -477, -477, -477, -477,
+     -477, -477, -477, -477, -477, -477, -477, -477, -477, -477,
+     -477, -477, -477, -477, -477, -477, -477, -477
+    },
+
+    {
+       67, -478, -478, -478, -478, -478, -478, -478, -478, -478,
+     -478, -478, -478, -478, -478, -478, -478, -478, -478, -478,
+     -478, -478, -478, -478, -478, -478, -478, -478, -478, -478,
+     -478, -478,  592, -478, -478, -478, -478, -478, -478, -478,
+     -478, -478, -478, -478, -478, -478, -478, -478, -478, -478,
+     -478, -478, -478, -478, -478, -478, -478, -478, -478, -478,
+
+     -478, -478, -478, -478, -478, -478, -478, -478, -478, -478,
+     -478, -478, -478, -478, -478, -478, -478, -478, -478, -478,
+     -478, -478, -478, -478, -478, -478, -478, -478, -478, -478,
+     -478, -478, -478, -478, -478, -478, -478, -478, -478, -478,
+     -478, -478, -478, -478, -478, -478, -478, -478, -478, -478,
+     -478, -478, -478, -478, -478, -478, -478, -478, -478, -478,
+     -478, -478, -478, -478, -478, -478, -478, -478
+    },
+
+    {
+       67, -479, -479, -479, -479, -479, -479, -479, -479, -479,
+     -479, -479, -479, -479, -479, -479, -479, -479, -479, -479,
+     -479, -479, -479, -479, -479, -479, -479, -479, -479, -479,
+
+     -479, -479,  593, -479, -479, -479, -479, -479, -479, -479,
+     -479, -479, -479, -479, -479, -479, -479, -479,  594,  594,
+      594,  594,  594,  594,  594,  594,  594,  594, -479, -479,
+     -479, -479, -479, -479, -479,  593,  593,  593,  593,  593,
+      593,  593,  593,  593,  593,  593,  593,  593,  593,  593,
+      593,  593,  593,  593,  593,  593,  593,  593,  593,  593,
+      593, -479, -479, -479, -479, -479, -479, -479, -479, -479,
+     -479, -479, -479, -479, -479, -479, -479, -479, -479, -479,
+     -479, -479, -479, -479, -479, -479, -479, -479, -479, -479,
+     -479, -479, -479, -479, -479, -479, -479, -479
+
+    },
+
+    {
+       67, -480, -480, -480, -480, -480, -480, -480, -480, -480,
+     -480, -480, -480, -480, -480, -480, -480, -480, -480, -480,
+     -480, -480, -480, -480, -480, -480, -480, -480, -480, -480,
+     -480, -480, -480, -480, -480, -480, -480, -480, -480, -480,
+     -480, -480, -480, -480, -480, -480, -480, -480, -480,  595,
+      595,  595,  595,  595,  595,  595,  595,  595, -480, -480,
+     -480, -480, -480, -480, -480, -480, -480, -480, -480, -480,
+     -480, -480, -480, -480, -480, -480, -480, -480, -480, -480,
+     -480, -480, -480, -480, -480, -480, -480, -480, -480, -480,
+     -480, -480, -480, -480, -480, -480, -480, -480, -480, -480,
+
+     -480, -480, -480, -480, -480, -480, -480, -480, -480, -480,
+     -480, -480, -480, -480, -480, -480, -480, -480, -480, -480,
+     -480, -480, -480, -480, -480, -480, -480, -480
+    },
+
+    {
+       67, -481, -481, -481, -481, -481, -481, -481, -481, -481,
+     -481, -481, -481, -481, -481, -481, -481, -481, -481, -481,
+     -481, -481, -481, -481, -481, -481, -481, -481, -481, -481,
+     -481, -481,  596, -481, -481, -481, -481, -481, -481, -481,
+     -481, -481, -481, -481, -481, -481, -481, -481,  597,  597,
+      597,  597,  597,  597,  597,  597,  597,  597, -481, -481,
+     -481, -481, -481, -481, -481,  596,  596,  596,  596,  596,
+
+      596,  596,  596,  596,  596,  596,  596,  596,  596,  596,
+      596,  596,  596,  596,  596,  596,  596,  596,  596,  596,
+      596, -481, -481, -481, -481, -481, -481, -481, -481, -481,
+     -481, -481, -481, -481, -481, -481, -481, -481, -481, -481,
+     -481, -481, -481, -481, -481, -481, -481, -481, -481, -481,
+     -481, -481, -481, -481, -481, -481, -481, -481
+    },
+
+    {
+       67, -482, -482, -482, -482, -482, -482, -482, -482, -482,
+     -482, -482, -482, -482, -482, -482, -482, -482, -482, -482,
+     -482, -482, -482, -482, -482, -482, -482, -482, -482, -482,
+     -482, -482,  598, -482, -482, -482, -482, -482, -482, -482,
+
+     -482, -482, -482, -482, -482, -482, -482, -482, -482, -482,
+     -482, -482, -482, -482, -482, -482, -482, -482, -482, -482,
+     -482, -482, -482, -482, -482, -482, -482, -482, -482, -482,
+     -482, -482, -482, -482, -482, -482, -482, -482, -482, -482,
+     -482, -482, -482, -482, -482, -482, -482, -482, -482, -482,
+     -482, -482, -482, -482, -482, -482, -482, -482, -482, -482,
+     -482, -482, -482, -482, -482, -482, -482, -482, -482, -482,
+     -482, -482, -482, -482, -482, -482, -482, -482, -482, -482,
+     -482, -482, -482, -482, -482, -482, -482, -482
+    },
+
+    {
+       67, -483, -483, -483, -483, -483, -483, -483, -483, -483,
+
+     -483, -483, -483, -483, -483, -483, -483, -483, -483, -483,
+     -483, -483, -483, -483, -483, -483, -483, -483, -483, -483,
+     -483, -483,  599, -483, -483, -483, -483, -483, -483, -483,
+     -483, -483, -483, -483, -483, -483, -483, -483,  600,  600,
+      600,  600,  600,  600,  600,  600,  600,  600, -483, -483,
+     -483, -483, -483, -483, -483,  599,  599,  599,  599,  599,
+      599,  599,  599,  599,  599,  599,  599,  599,  599,  599,
+      599,  599,  599,  599,  599,  599,  599,  599,  599,  599,
+      599, -483, -483, -483, -483, -483, -483, -483, -483, -483,
+     -483, -483, -483, -483, -483, -483, -483, -483, -483, -483,
+
+     -483, -483, -483, -483, -483, -483, -483, -483, -483, -483,
+     -483, -483, -483, -483, -483, -483, -483, -483
+    },
+
+    {
+       67, -484, -484, -484, -484, -484, -484, -484, -484, -484,
+     -484, -484, -484, -484, -484, -484, -484, -484, -484, -484,
+     -484, -484, -484, -484, -484, -484, -484, -484, -484, -484,
+     -484, -484, -484, -484, -484, -484, -484, -484, -484, -484,
+     -484, -484, -484, -484, -484, -484, -484, -484, -484, -484,
+     -484, -484, -484, -484, -484, -484, -484, -484, -484, -484,
+     -484, -484, -484, -484, -484, -484, -484, -484, -484, -484,
+     -484, -484, -484, -484, -484, -484, -484, -484, -484, -484,
+
+     -484, -484, -484, -484, -484, -484, -484, -484, -484, -484,
+     -484, -484, -484, -484, -484,  601, -484, -484, -484, -484,
+     -484, -484, -484, -484, -484, -484, -484, -484, -484, -484,
+     -484, -484, -484, -484, -484, -484, -484, -484, -484, -484,
+     -484, -484, -484, -484, -484, -484, -484, -484
+    },
+
+    {
+       67, -485, -485, -485, -485, -485, -485, -485, -485, -485,
+     -485, -485, -485, -485, -485, -485, -485, -485, -485, -485,
+     -485, -485, -485, -485, -485, -485, -485, -485, -485, -485,
+     -485, -485, -485, -485, -485, -485, -485, -485, -485, -485,
+     -485, -485, -485, -485, -485, -485, -485, -485,  602,  603,
+
+      603,  603,  603,  603,  603,  603,  603,  603, -485, -485,
+     -485, -485, -485, -485, -485, -485, -485, -485, -485, -485,
+     -485, -485, -485, -485, -485, -485, -485, -485, -485, -485,
+     -485, -485, -485, -485, -485, -485, -485, -485, -485, -485,
+     -485, -485, -485, -485, -485, -485, -485, -485, -485, -485,
+     -485, -485, -485, -485, -485, -485, -485, -485, -485, -485,
+     -485, -485, -485, -485, -485, -485, -485, -485, -485, -485,
+     -485, -485, -485, -485, -485, -485, -485, -485
+    },
+
+    {
+       67, -486, -486, -486, -486, -486, -486, -486, -486, -486,
+     -486, -486, -486, -486, -486, -486, -486, -486, -486, -486,
+
+     -486, -486, -486, -486, -486, -486, -486, -486, -486, -486,
+     -486, -486,  604, -486, -486, -486, -486, -486, -486, -486,
+     -486, -486, -486, -486, -486, -486, -486, -486, -486, -486,
+     -486, -486, -486, -486, -486, -486, -486, -486, -486, -486,
+     -486, -486, -486, -486, -486,  604,  604,  604,  604,  604,
+      604,  604,  604,  604,  604,  604,  604,  604,  604,  604,
+      604,  604,  604,  604,  604,  604,  604,  604,  604,  604,
+      604, -486, -486, -486, -486, -486, -486, -486, -486, -486,
+     -486, -486, -486, -486, -486, -486, -486, -486, -486, -486,
+     -486, -486, -486, -486, -486, -486, -486, -486, -486, -486,
+
+     -486, -486, -486, -486, -486, -486, -486, -486
+    },
+
+    {
+       67, -487, -487, -487, -487, -487, -487, -487, -487, -487,
+     -487, -487, -487, -487, -487, -487, -487, -487, -487, -487,
+     -487, -487, -487, -487, -487, -487, -487, -487, -487, -487,
+     -487, -487,  604, -487, -487, -487, -487, -487, -487, -487,
+     -487, -487, -487, -487, -487, -487, -487, -487,  605,  605,
+      605,  605,  605,  605,  605,  605,  605,  605, -487, -487,
+     -487, -487, -487, -487, -487,  604,  604,  604,  604,  604,
+      604,  604,  604,  604,  604,  604,  604,  604,  604,  604,
+      604,  604,  604,  604,  604,  604,  604,  604,  604,  604,
+
+      604, -487, -487, -487, -487, -487, -487, -487, -487, -487,
+     -487, -487, -487, -487, -487, -487, -487, -487, -487, -487,
+     -487, -487, -487, -487, -487, -487, -487, -487, -487, -487,
+     -487, -487, -487, -487, -487, -487, -487, -487
+    },
+
+    {
+       67, -488, -488, -488, -488, -488, -488, -488, -488, -488,
+     -488, -488, -488, -488, -488, -488, -488, -488, -488, -488,
+     -488, -488, -488, -488, -488, -488, -488, -488, -488, -488,
+     -488, -488,  606, -488, -488, -488, -488, -488, -488, -488,
+     -488, -488, -488, -488, -488, -488, -488, -488, -488, -488,
+     -488, -488, -488, -488, -488, -488, -488, -488, -488, -488,
+
+     -488, -488, -488, -488, -488, -488, -488, -488, -488, -488,
+     -488, -488, -488, -488, -488, -488, -488, -488, -488, -488,
+     -488, -488, -488, -488, -488, -488, -488, -488, -488, -488,
+     -488, -488, -488, -488, -488, -488, -488, -488, -488, -488,
+     -488, -488, -488, -488, -488, -488, -488, -488, -488, -488,
+     -488, -488, -488, -488, -488, -488, -488, -488, -488, -488,
+     -488, -488, -488, -488, -488, -488, -488, -488
+    },
+
+    {
+       67, -489, -489, -489, -489, -489, -489, -489, -489, -489,
+     -489, -489, -489, -489, -489, -489, -489, -489, -489, -489,
+     -489, -489, -489, -489, -489, -489, -489, -489, -489, -489,
+
+     -489, -489,  607, -489, -489, -489, -489, -489, -489, -489,
+     -489, -489, -489, -489, -489, -489, -489, -489,  608,  608,
+      608,  608,  608,  608,  608,  608,  608,  608, -489, -489,
+     -489, -489, -489, -489, -489,  607,  607,  607,  607,  607,
+      607,  607,  607,  607,  607,  607,  607,  607,  607,  607,
+      607,  607,  607,  607,  607,  607,  607,  607,  607,  607,
+      607, -489, -489, -489, -489, -489, -489, -489, -489, -489,
+     -489, -489, -489, -489, -489, -489, -489, -489, -489, -489,
+     -489, -489, -489, -489, -489, -489, -489, -489, -489, -489,
+     -489, -489, -489, -489, -489, -489, -489, -489
+
+    },
+
+    {
+       67, -490, -490, -490, -490, -490, -490, -490, -490, -490,
+     -490, -490, -490, -490, -490, -490, -490, -490, -490, -490,
+     -490, -490, -490, -490, -490, -490, -490, -490, -490, -490,
+     -490, -490, -490, -490, -490, -490, -490, -490, -490, -490,
+     -490, -490, -490, -490, -490, -490, -490, -490, -490, -490,
+     -490, -490, -490, -490, -490, -490, -490, -490, -490, -490,
+     -490, -490, -490, -490, -490, -490, -490, -490, -490, -490,
+     -490, -490, -490, -490, -490, -490, -490, -490, -490, -490,
+     -490, -490, -490, -490, -490, -490, -490, -490, -490, -490,
+     -490, -490, -490, -490, -490,  609, -490, -490, -490, -490,
+
+     -490, -490, -490, -490, -490, -490, -490, -490, -490, -490,
+     -490, -490, -490, -490, -490, -490, -490, -490, -490, -490,
+     -490, -490, -490, -490, -490, -490, -490, -490
+    },
+
+    {
+       67, -491, -491, -491, -491, -491, -491, -491, -491, -491,
+     -491, -491, -491, -491, -491, -491, -491, -491, -491, -491,
+     -491, -491, -491, -491, -491, -491, -491, -491, -491, -491,
+     -491, -491, -491, -491, -491, -491, -491, -491, -491, -491,
+     -491, -491, -491, -491, -491, -491, -491, -491,  610,  611,
+      611,  611,  611,  611,  611,  611,  611,  611, -491, -491,
+     -491, -491, -491, -491, -491, -491, -491, -491, -491, -491,
+
+     -491, -491, -491, -491, -491, -491, -491, -491, -491, -491,
+     -491, -491, -491, -491, -491, -491, -491, -491, -491, -491,
+     -491, -491, -491, -491, -491, -491, -491, -491, -491, -491,
+     -491, -491, -491, -491, -491, -491, -491, -491, -491, -491,
+     -491, -491, -491, -491, -491, -491, -491, -491, -491, -491,
+     -491, -491, -491, -491, -491, -491, -491, -491
+    },
+
+    {
+       67, -492, -492, -492, -492, -492, -492, -492, -492, -492,
+     -492, -492, -492, -492, -492, -492, -492, -492, -492, -492,
+     -492, -492, -492, -492, -492, -492, -492, -492, -492, -492,
+     -492, -492,  612, -492, -492, -492, -492, -492, -492, -492,
+
+     -492, -492, -492, -492, -492, -492, -492, -492, -492, -492,
+     -492, -492, -492, -492, -492, -492, -492, -492, -492, -492,
+     -492, -492, -492, -492, -492,  612,  612,  612,  612,  612,
+      612,  612,  612,  612,  612,  612,  612,  612,  612,  612,
+      612,  612,  612,  612,  612,  612,  612,  612,  612,  612,
+      612, -492, -492, -492, -492, -492, -492, -492, -492, -492,
+     -492, -492, -492, -492, -492, -492, -492, -492, -492, -492,
+     -492, -492, -492, -492, -492, -492, -492, -492, -492, -492,
+     -492, -492, -492, -492, -492, -492, -492, -492
+    },
+
+    {
+       67, -493, -493, -493, -493, -493, -493, -493, -493, -493,
+
+     -493, -493, -493, -493, -493, -493, -493, -493, -493, -493,
+     -493, -493, -493, -493, -493, -493, -493, -493, -493, -493,
+     -493, -493,  612, -493, -493, -493, -493, -493, -493, -493,
+     -493, -493, -493, -493, -493, -493, -493, -493,  613,  613,
+      613,  613,  613,  613,  613,  613,  613,  613, -493, -493,
+     -493, -493, -493, -493, -493,  612,  612,  612,  612,  612,
+      612,  612,  612,  612,  612,  612,  612,  612,  612,  612,
+      612,  612,  612,  612,  612,  612,  612,  612,  612,  612,
+      612, -493, -493, -493, -493, -493, -493, -493, -493, -493,
+     -493, -493, -493, -493, -493, -493, -493, -493, -493, -493,
+
+     -493, -493, -493, -493, -493, -493, -493, -493, -493, -493,
+     -493, -493, -493, -493, -493, -493, -493, -493
+    },
+
+    {
+       67, -494, -494, -494, -494, -494, -494, -494, -494, -494,
+     -494, -494, -494, -494, -494, -494, -494, -494, -494, -494,
+     -494, -494, -494, -494, -494, -494, -494, -494, -494, -494,
+     -494, -494,  614, -494, -494, -494, -494, -494, -494, -494,
+     -494, -494, -494, -494, -494, -494, -494, -494, -494, -494,
+     -494, -494, -494, -494, -494, -494, -494, -494, -494, -494,
+     -494, -494, -494, -494, -494, -494, -494, -494, -494, -494,
+     -494, -494, -494, -494, -494, -494, -494, -494, -494, -494,
+
+     -494, -494, -494, -494, -494, -494, -494, -494, -494, -494,
+     -494, -494, -494, -494, -494, -494, -494, -494, -494, -494,
+     -494, -494, -494, -494, -494, -494, -494, -494, -494, -494,
+     -494, -494, -494, -494, -494, -494, -494, -494, -494, -494,
+     -494, -494, -494, -494, -494, -494, -494, -494
+    },
+
+    {
+       67, -495, -495, -495, -495, -495, -495, -495, -495, -495,
+     -495, -495, -495, -495, -495, -495, -495, -495, -495, -495,
+     -495, -495, -495, -495, -495, -495, -495, -495, -495, -495,
+     -495, -495,  615, -495, -495, -495, -495, -495, -495, -495,
+     -495, -495, -495, -495, -495, -495, -495, -495,  616,  616,
+
+      616,  616,  616,  616,  616,  616,  616,  616, -495, -495,
+     -495, -495, -495, -495, -495,  615,  615,  615,  615,  615,
+      615,  615,  615,  615,  615,  615,  615,  615,  615,  615,
+      615,  615,  615,  615,  615,  615,  615,  615,  615,  615,
+      615, -495, -495, -495, -495, -495, -495, -495, -495, -495,
+     -495, -495, -495, -495, -495, -495, -495, -495, -495, -495,
+     -495, -495, -495, -495, -495, -495, -495, -495, -495, -495,
+     -495, -495, -495, -495, -495, -495, -495, -495
+    },
+
+    {
+       67, -496, -496, -496, -496, -496, -496, -496, -496, -496,
+     -496, -496, -496, -496, -496, -496, -496, -496, -496, -496,
+
+     -496, -496, -496, -496, -496, -496, -496, -496, -496, -496,
+     -496, -496, -496, -496, -496, -496, -496, -496, -496, -496,
+     -496, -496, -496, -496, -496, -496, -496, -496,  617,  617,
+      617,  617,  617,  617,  617,  617,  617,  617, -496, -496,
+     -496, -496, -496, -496, -496, -496, -496, -496, -496, -496,
+     -496, -496, -496, -496, -496, -496, -496, -496, -496, -496,
+     -496, -496, -496, -496, -496, -496, -496, -496, -496, -496,
+     -496, -496, -496, -496, -496, -496, -496, -496, -496, -496,
+     -496, -496, -496, -496, -496, -496, -496, -496, -496, -496,
+     -496, -496, -496, -496, -496, -496, -496, -496, -496, -496,
+
+     -496, -496, -496, -496, -496, -496, -496, -496
+    },
+
+    {
+       67, -497, -497, -497, -497, -497, -497, -497, -497, -497,
+     -497, -497, -497, -497, -497, -497, -497, -497, -497, -497,
+     -497, -497, -497, -497, -497, -497, -497, -497, -497, -497,
+     -497, -497,  618, -497, -497, -497, -497, -497, -497, -497,
+     -497, -497, -497, -497, -497, -497, -497, -497, -497, -497,
+     -497, -497, -497, -497, -497, -497, -497, -497, -497, -497,
+     -497, -497, -497, -497, -497,  618,  618,  618,  618,  618,
+      618,  618,  618,  618,  618,  618,  618,  618,  618,  618,
+      618,  618,  618,  618,  618,  618,  618,  618,  618,  618,
+
+      618, -497, -497, -497, -497, -497, -497, -497, -497, -497,
+     -497, -497, -497, -497, -497, -497, -497, -497, -497, -497,
+     -497, -497, -497, -497, -497, -497, -497, -497, -497, -497,
+     -497, -497, -497, -497, -497, -497, -497, -497
+    },
+
+    {
+       67, -498, -498, -498, -498, -498, -498, -498, -498, -498,
+     -498, -498, -498, -498, -498, -498, -498, -498, -498, -498,
+     -498, -498, -498, -498, -498, -498, -498, -498, -498, -498,
+     -498, -498,  618, -498, -498, -498, -498, -498, -498, -498,
+     -498, -498, -498, -498, -498, -498, -498, -498,  619,  619,
+      619,  619,  619,  619,  619,  619,  619,  619, -498, -498,
+
+     -498, -498, -498, -498, -498,  618,  618,  618,  618,  618,
+      618,  618,  618,  618,  618,  618,  618,  618,  618,  618,
+      618,  618,  618,  618,  618,  618,  618,  618,  618,  618,
+      618, -498, -498, -498, -498, -498, -498, -498, -498, -498,
+     -498, -498, -498, -498, -498, -498, -498, -498, -498, -498,
+     -498, -498, -498, -498, -498, -498, -498, -498, -498, -498,
+     -498, -498, -498, -498, -498, -498, -498, -498
+    },
+
+    {
+       67, -499, -499, -499, -499, -499, -499, -499, -499, -499,
+     -499, -499, -499, -499, -499, -499, -499, -499, -499, -499,
+     -499, -499, -499, -499, -499, -499, -499, -499, -499, -499,
+
+     -499, -499,  620, -499, -499, -499, -499, -499, -499, -499,
+     -499, -499, -499, -499, -499, -499, -499, -499, -499, -499,
+     -499, -499, -499, -499, -499, -499, -499, -499, -499, -499,
+     -499, -499, -499, -499, -499, -499, -499, -499, -499, -499,
+     -499, -499, -499, -499, -499, -499, -499, -499, -499, -499,
+     -499, -499, -499, -499, -499, -499, -499, -499, -499, -499,
+     -499, -499, -499, -499, -499, -499, -499, -499, -499, -499,
+     -499, -499, -499, -499, -499, -499, -499, -499, -499, -499,
+     -499, -499, -499, -499, -499, -499, -499, -499, -499, -499,
+     -499, -499, -499, -499, -499, -499, -499, -499
+
+    },
+
+    {
+       67, -500, -500, -500, -500, -500, -500, -500, -500, -500,
+     -500, -500, -500, -500, -500, -500, -500, -500, -500, -500,
+     -500, -500, -500, -500, -500, -500, -500, -500, -500, -500,
+     -500, -500,  621, -500, -500, -500, -500, -500, -500, -500,
+     -500, -500, -500, -500, -500, -500, -500, -500,  622,  622,
+      622,  622,  622,  622,  622,  622,  622,  622, -500, -500,
+     -500, -500, -500, -500, -500,  621,  621,  621,  621,  621,
+      621,  621,  621,  621,  621,  621,  621,  621,  621,  621,
+      621,  621,  621,  621,  621,  621,  621,  621,  621,  621,
+      621, -500, -500, -500, -500, -500, -500, -500, -500, -500,
+
+     -500, -500, -500, -500, -500, -500, -500, -500, -500, -500,
+     -500, -500, -500, -500, -500, -500, -500, -500, -500, -500,
+     -500, -500, -500, -500, -500, -500, -500, -500
+    },
+
+    {
+       67, -501, -501, -501, -501, -501, -501, -501, -501, -501,
+     -501, -501, -501, -501, -501, -501, -501, -501, -501, -501,
+     -501, -501, -501, -501, -501, -501, -501, -501, -501, -501,
+     -501, -501, -501, -501, -501, -501, -501, -501, -501, -501,
+     -501, -501, -501, -501, -501, -501, -501, -501, -501, -501,
+     -501, -501, -501, -501, -501, -501, -501, -501, -501, -501,
+     -501, -501, -501, -501, -501, -501, -501, -501, -501, -501,
+
+     -501, -501, -501, -501, -501, -501, -501, -501, -501, -501,
+     -501, -501, -501, -501, -501, -501, -501, -501, -501, -501,
+     -501, -501, -501, -501, -501,  623, -501, -501, -501, -501,
+     -501, -501, -501, -501, -501, -501, -501, -501, -501, -501,
+     -501, -501, -501, -501, -501, -501, -501, -501, -501, -501,
+     -501, -501, -501, -501, -501, -501, -501, -501
+    },
+
+    {
+       67, -502, -502, -502, -502, -502, -502, -502, -502, -502,
+     -502, -502, -502, -502, -502, -502, -502, -502, -502, -502,
+     -502, -502, -502, -502, -502, -502, -502, -502, -502, -502,
+     -502, -502, -502, -502, -502, -502, -502, -502, -502, -502,
+
+     -502, -502, -502, -502, -502, -502, -502, -502,  624,  625,
+      625,  625,  625,  625,  625,  625,  625,  625, -502, -502,
+     -502, -502, -502, -502, -502, -502, -502, -502, -502, -502,
+     -502, -502, -502, -502, -502, -502, -502, -502, -502, -502,
+     -502, -502, -502, -502, -502, -502, -502, -502, -502, -502,
+     -502, -502, -502, -502, -502, -502, -502, -502, -502, -502,
+     -502, -502, -502, -502, -502, -502, -502, -502, -502, -502,
+     -502, -502, -502, -502, -502, -502, -502, -502, -502, -502,
+     -502, -502, -502, -502, -502, -502, -502, -502
+    },
+
+    {
+       67, -503, -503, -503, -503, -503, -503, -503, -503, -503,
+
+     -503, -503, -503, -503, -503, -503, -503, -503, -503, -503,
+     -503, -503, -503, -503, -503, -503, -503, -503, -503, -503,
+     -503, -503,  626, -503, -503, -503, -503, -503, -503, -503,
+     -503, -503, -503, -503, -503, -503, -503, -503, -503, -503,
+     -503, -503, -503, -503, -503, -503, -503, -503, -503, -503,
+     -503, -503, -503, -503, -503,  626,  626,  626,  626,  626,
+      626,  626,  626,  626,  626,  626,  626,  626,  626,  626,
+      626,  626,  626,  626,  626,  626,  626,  626,  626,  626,
+      626, -503, -503, -503, -503, -503, -503, -503, -503, -503,
+     -503, -503, -503, -503, -503, -503, -503, -503, -503, -503,
+
+     -503, -503, -503, -503, -503, -503, -503, -503, -503, -503,
+     -503, -503, -503, -503, -503, -503, -503, -503
+    },
+
+    {
+       67, -504, -504, -504, -504, -504, -504, -504, -504, -504,
+     -504, -504, -504, -504, -504, -504, -504, -504, -504, -504,
+     -504, -504, -504, -504, -504, -504, -504, -504, -504, -504,
+     -504, -504,  626, -504, -504, -504, -504, -504, -504, -504,
+     -504, -504, -504, -504, -504, -504, -504, -504,  627,  627,
+      627,  627,  627,  627,  627,  627,  627,  627, -504, -504,
+     -504, -504, -504, -504, -504,  626,  626,  626,  626,  626,
+      626,  626,  626,  626,  626,  626,  626,  626,  626,  626,
+
+      626,  626,  626,  626,  626,  626,  626,  626,  626,  626,
+      626, -504, -504, -504, -504, -504, -504, -504, -504, -504,
+     -504, -504, -504, -504, -504, -504, -504, -504, -504, -504,
+     -504, -504, -504, -504, -504, -504, -504, -504, -504, -504,
+     -504, -504, -504, -504, -504, -504, -504, -504
+    },
+
+    {
+       67, -505, -505, -505, -505, -505, -505, -505, -505, -505,
+     -505, -505, -505, -505, -505, -505, -505, -505, -505, -505,
+     -505, -505, -505, -505, -505, -505, -505, -505, -505, -505,
+     -505, -505,  628, -505, -505, -505, -505, -505, -505, -505,
+     -505, -505, -505, -505, -505, -505, -505, -505, -505, -505,
+
+     -505, -505, -505, -505, -505, -505, -505, -505, -505, -505,
+     -505, -505, -505, -505, -505, -505, -505, -505, -505, -505,
+     -505, -505, -505, -505, -505, -505, -505, -505, -505, -505,
+     -505, -505, -505, -505, -505, -505, -505, -505, -505, -505,
+     -505, -505, -505, -505, -505, -505, -505, -505, -505, -505,
+     -505, -505, -505, -505, -505, -505, -505, -505, -505, -505,
+     -505, -505, -505, -505, -505, -505, -505, -505, -505, -505,
+     -505, -505, -505, -505, -505, -505, -505, -505
+    },
+
+    {
+       67, -506, -506, -506, -506, -506, -506, -506, -506, -506,
+     -506, -506, -506, -506, -506, -506, -506, -506, -506, -506,
+
+     -506, -506, -506, -506, -506, -506, -506, -506, -506, -506,
+     -506, -506,  629, -506, -506, -506, -506, -506, -506, -506,
+     -506, -506, -506, -506, -506, -506, -506, -506,  630,  630,
+      630,  630,  630,  630,  630,  630,  630,  630, -506, -506,
+     -506, -506, -506, -506, -506,  629,  629,  629,  629,  629,
+      629,  629,  629,  629,  629,  629,  629,  629,  629,  629,
+      629,  629,  629,  629,  629,  629,  629,  629,  629,  629,
+      629, -506, -506, -506, -506, -506, -506, -506, -506, -506,
+     -506, -506, -506, -506, -506, -506, -506, -506, -506, -506,
+     -506, -506, -506, -506, -506, -506, -506, -506, -506, -506,
+
+     -506, -506, -506, -506, -506, -506, -506, -506
+    },
+
+    {
+       67, -507, -507, -507, -507, -507, -507, -507, -507, -507,
+     -507, -507, -507, -507, -507, -507, -507, -507, -507, -507,
+     -507, -507, -507, -507, -507, -507, -507, -507, -507, -507,
+     -507, -507, -507, -507, -507, -507, -507, -507, -507, -507,
+     -507, -507, -507, -507, -507, -507, -507, -507,  631,  631,
+      631,  631,  631,  631,  631,  631,  631,  631, -507, -507,
+     -507, -507, -507, -507, -507, -507, -507, -507, -507, -507,
+     -507, -507, -507, -507, -507, -507, -507, -507, -507, -507,
+     -507, -507, -507, -507, -507, -507, -507, -507, -507, -507,
+
+     -507, -507, -507, -507, -507, -507, -507, -507, -507, -507,
+     -507, -507, -507, -507, -507, -507, -507, -507, -507, -507,
+     -507, -507, -507, -507, -507, -507, -507, -507, -507, -507,
+     -507, -507, -507, -507, -507, -507, -507, -507
+    },
+
+    {
+       67, -508, -508, -508, -508, -508, -508, -508, -508, -508,
+     -508, -508, -508, -508, -508, -508, -508, -508, -508, -508,
+     -508, -508, -508, -508, -508, -508, -508, -508, -508, -508,
+     -508, -508,  632, -508, -508, -508, -508, -508, -508, -508,
+     -508, -508, -508, -508, -508, -508, -508, -508, -508, -508,
+     -508, -508, -508, -508, -508, -508, -508, -508, -508, -508,
+
+     -508, -508, -508, -508, -508,  632,  632,  632,  632,  632,
+      632,  632,  632,  632,  632,  632,  632,  632,  632,  632,
+      632,  632,  632,  632,  632,  632,  632,  632,  632,  632,
+      632, -508, -508, -508, -508, -508, -508, -508, -508, -508,
+     -508, -508, -508, -508, -508, -508, -508, -508, -508, -508,
+     -508, -508, -508, -508, -508, -508, -508, -508, -508, -508,
+     -508, -508, -508, -508, -508, -508, -508, -508
+    },
+
+    {
+       67, -509, -509, -509, -509, -509, -509, -509, -509, -509,
+     -509, -509, -509, -509, -509, -509, -509, -509, -509, -509,
+     -509, -509, -509, -509, -509, -509, -509, -509, -509, -509,
+
+     -509, -509,  632, -509, -509, -509, -509, -509, -509, -509,
+     -509, -509, -509, -509, -509, -509, -509, -509,  633,  633,
+      633,  633,  633,  633,  633,  633,  633,  633, -509, -509,
+     -509, -509, -509, -509, -509,  632,  632,  632,  632,  632,
+      632,  632,  632,  632,  632,  632,  632,  632,  632,  632,
+      632,  632,  632,  632,  632,  632,  632,  632,  632,  632,
+      632, -509, -509, -509, -509, -509, -509, -509, -509, -509,
+     -509, -509, -509, -509, -509, -509, -509, -509, -509, -509,
+     -509, -509, -509, -509, -509, -509, -509, -509, -509, -509,
+     -509, -509, -509, -509, -509, -509, -509, -509
+
+    },
+
+    {
+       67, -510, -510, -510, -510, -510, -510, -510, -510, -510,
+     -510, -510, -510, -510, -510, -510, -510, -510, -510, -510,
+     -510, -510, -510, -510, -510, -510, -510, -510, -510, -510,
+     -510, -510,  634, -510, -510, -510, -510, -510, -510, -510,
+     -510, -510, -510, -510, -510, -510, -510, -510, -510, -510,
+     -510, -510, -510, -510, -510, -510, -510, -510, -510, -510,
+     -510, -510, -510, -510, -510, -510, -510, -510, -510, -510,
+     -510, -510, -510, -510, -510, -510, -510, -510, -510, -510,
+     -510, -510, -510, -510, -510, -510, -510, -510, -510, -510,
+     -510, -510, -510, -510, -510, -510, -510, -510, -510, -510,
+
+     -510, -510, -510, -510, -510, -510, -510, -510, -510, -510,
+     -510, -510, -510, -510, -510, -510, -510, -510, -510, -510,
+     -510, -510, -510, -510, -510, -510, -510, -510
+    },
+
+    {
+       67, -511, -511, -511, -511, -511, -511, -511, -511, -511,
+     -511, -511, -511, -511, -511, -511, -511, -511, -511, -511,
+     -511, -511, -511, -511, -511, -511, -511, -511, -511, -511,
+     -511, -511,  635, -511, -511, -511, -511, -511, -511, -511,
+     -511, -511, -511, -511, -511, -511, -511, -511,  636,  636,
+      636,  636,  636,  636,  636,  636,  636,  636, -511, -511,
+     -511, -511, -511, -511, -511,  635,  635,  635,  635,  635,
+
+      635,  635,  635,  635,  635,  635,  635,  635,  635,  635,
+      635,  635,  635,  635,  635,  635,  635,  635,  635,  635,
+      635, -511, -511, -511, -511, -511, -511, -511, -511, -511,
+     -511, -511, -511, -511, -511, -511, -511, -511, -511, -511,
+     -511, -511, -511, -511, -511, -511, -511, -511, -511, -511,
+     -511, -511, -511, -511, -511, -511, -511, -511
+    },
+
+    {
+       67, -512, -512, -512, -512, -512, -512, -512, -512, -512,
+     -512, -512, -512, -512, -512, -512, -512, -512, -512, -512,
+     -512, -512, -512, -512, -512, -512, -512, -512, -512, -512,
+     -512, -512, -512, -512, -512, -512, -512, -512, -512, -512,
+
+     -512, -512, -512, -512, -512, -512, -512, -512, -512, -512,
+     -512, -512, -512, -512, -512, -512, -512, -512, -512, -512,
+     -512, -512, -512, -512, -512, -512, -512, -512, -512, -512,
+     -512, -512, -512, -512, -512, -512, -512, -512, -512, -512,
+     -512, -512, -512, -512, -512, -512, -512, -512, -512, -512,
+     -512, -512, -512, -512, -512, -512, -512, -512, -512, -512,
+     -512, -512, -512, -512, -512, -512, -512, -512, -512, -512,
+     -512, -512, -512, -512, -512, -512, -512, -512, -512, -512,
+     -512, -512, -512, -512, -512, -512, -512, -512
+    },
+
+    {
+       67, -513, -513, -513, -513, -513, -513, -513, -513, -513,
+
+     -513, -513, -513, -513, -513, -513, -513, -513, -513, -513,
+     -513, -513, -513, -513, -513, -513, -513, -513, -513, -513,
+     -513, -513, -513, -513, -513, -513, -513, -513, -513, -513,
+     -513, -513, -513, -513, -513, -513, -513, -513, -513, -513,
+     -513, -513, -513, -513, -513, -513, -513, -513, -513, -513,
+     -513, -513, -513, -513, -513, -513, -513, -513, -513, -513,
+     -513, -513, -513, -513, -513, -513, -513, -513, -513, -513,
+     -513, -513, -513, -513, -513, -513, -513, -513, -513, -513,
+     -513, -513, -513, -513, -513, -513, -513, -513, -513, -513,
+     -513, -513, -513, -513, -513, -513, -513, -513, -513, -513,
+
+     -513, -513, -513, -513, -513, -513, -513, -513, -513, -513,
+     -513, -513, -513, -513, -513, -513, -513, -513
+    },
+
+    {
+       67, -514, -514, -514, -514, -514, -514, -514, -514, -514,
+     -514, -514, -514, -514, -514, -514, -514, -514, -514, -514,
+     -514, -514, -514, -514, -514, -514, -514, -514, -514, -514,
+     -514, -514, -514, -514, -514, -514, -514, -514, -514, -514,
+     -514, -514, -514, -514, -514, -514, -514, -514, -514, -514,
+     -514, -514, -514, -514, -514, -514, -514, -514, -514, -514,
+     -514, -514, -514, -514, -514, -514, -514, -514, -514, -514,
+     -514, -514, -514, -514, -514, -514, -514, -514, -514, -514,
+
+     -514, -514, -514, -514, -514, -514, -514, -514, -514, -514,
+     -514, -514, -514, -514, -514, -514, -514, -514, -514, -514,
+     -514, -514, -514, -514, -514, -514, -514, -514, -514, -514,
+     -514, -514, -514, -514, -514, -514, -514, -514, -514, -514,
+     -514, -514, -514, -514, -514, -514, -514, -514
+    },
+
+    {
+       67, -515, -515, -515, -515, -515, -515, -515, -515, -515,
+     -515, -515, -515, -515, -515, -515, -515, -515, -515, -515,
+     -515, -515, -515, -515, -515, -515, -515, -515, -515, -515,
+     -515, -515, -515, -515, -515, -515, -515, -515, -515, -515,
+     -515, -515, -515, -515, -515, -515, -515, -515, -515, -515,
+
+     -515, -515, -515, -515, -515, -515, -515, -515, -515, -515,
+     -515, -515, -515, -515, -515, -515, -515, -515, -515, -515,
+     -515, -515, -515, -515, -515, -515, -515, -515, -515, -515,
+     -515, -515, -515, -515, -515, -515, -515, -515, -515, -515,
+     -515, -515, -515, -515, -515, -515, -515, -515, -515, -515,
+     -515, -515, -515, -515, -515, -515, -515, -515, -515, -515,
+     -515, -515, -515, -515, -515, -515, -515, -515, -515, -515,
+     -515, -515, -515, -515, -515, -515, -515, -515
+    },
+
+    {
+       67, -516, -516, -516, -516, -516, -516, -516, -516, -516,
+     -516, -516, -516, -516, -516, -516, -516, -516, -516, -516,
+
+     -516, -516, -516, -516, -516, -516, -516, -516, -516, -516,
+     -516, -516, -516, -516, -516, -516, -516, -516, -516, -516,
+     -516, -516, -516, -516, -516, -516, -516, -516, -516, -516,
+     -516, -516, -516, -516, -516, -516, -516, -516, -516, -516,
+     -516, -516, -516, -516, -516, -516, -516, -516, -516, -516,
+     -516, -516, -516, -516, -516, -516, -516, -516, -516, -516,
+     -516, -516, -516, -516, -516, -516, -516, -516, -516, -516,
+     -516, -516, -516, -516, -516, -516, -516, -516, -516, -516,
+     -516, -516, -516, -516, -516, -516, -516, -516, -516, -516,
+     -516, -516, -516, -516, -516, -516, -516, -516, -516, -516,
+
+     -516, -516, -516, -516, -516, -516, -516, -516
+    },
+
+    {
+       67, -517, -517, -517, -517, -517, -517, -517, -517, -517,
+     -517, -517, -517, -517, -517, -517, -517, -517, -517, -517,
+     -517, -517, -517, -517, -517, -517, -517, -517, -517, -517,
+     -517, -517, -517, -517, -517, -517, -517, -517, -517, -517,
+     -517, -517, -517, -517, -517, -517, -517, -517, -517, -517,
+     -517, -517, -517, -517, -517, -517, -517, -517, -517, -517,
+     -517, -517, -517, -517, -517, -517, -517, -517, -517, -517,
+     -517, -517, -517, -517, -517, -517, -517, -517, -517, -517,
+     -517, -517, -517, -517, -517, -517, -517, -517, -517, -517,
+
+     -517, -517, -517, -517, -517, -517, -517, -517, -517, -517,
+     -517, -517, -517, -517, -517, -517, -517, -517, -517, -517,
+     -517, -517, -517, -517, -517, -517, -517, -517, -517, -517,
+     -517, -517, -517, -517, -517, -517, -517, -517
+    },
+
+    {
+       67, -518, -518, -518, -518, -518, -518, -518, -518, -518,
+     -518, -518, -518, -518, -518, -518, -518, -518, -518, -518,
+     -518, -518, -518, -518, -518, -518, -518, -518, -518, -518,
+     -518, -518, -518, -518, -518, -518, -518, -518, -518, -518,
+     -518, -518, -518, -518, -518, -518, -518, -518, -518, -518,
+     -518, -518, -518, -518, -518, -518, -518, -518, -518, -518,
+
+     -518, -518, -518, -518, -518, -518, -518, -518, -518, -518,
+     -518, -518, -518, -518, -518, -518, -518, -518, -518, -518,
+     -518, -518, -518, -518, -518, -518, -518, -518, -518, -518,
+     -518, -518, -518, -518, -518, -518, -518, -518, -518, -518,
+     -518, -518, -518, -518, -518, -518, -518, -518, -518, -518,
+     -518, -518, -518, -518, -518, -518, -518, -518, -518, -518,
+     -518, -518, -518, -518, -518, -518, -518, -518
+    },
+
+    {
+       67, -519, -519, -519, -519, -519, -519, -519, -519, -519,
+     -519, -519, -519, -519, -519, -519, -519, -519, -519, -519,
+     -519, -519, -519, -519, -519, -519, -519, -519, -519, -519,
+
+     -519, -519, -519, -519, -519, -519, -519, -519, -519, -519,
+     -519, -519, -519, -519, -519, -519, -519, -519, -519, -519,
+     -519, -519, -519, -519, -519, -519, -519, -519, -519, -519,
+     -519, -519, -519, -519, -519, -519, -519, -519, -519, -519,
+     -519, -519, -519, -519, -519, -519, -519, -519, -519, -519,
+     -519, -519, -519, -519, -519, -519, -519, -519, -519, -519,
+     -519, -519, -519, -519, -519, -519, -519, -519, -519, -519,
+     -519, -519, -519, -519, -519, -519, -519, -519, -519, -519,
+     -519, -519, -519, -519, -519, -519, -519, -519, -519, -519,
+     -519, -519, -519, -519, -519, -519, -519, -519
+
+    },
+
+    {
+       67, -520, -520, -520, -520, -520, -520, -520, -520, -520,
+     -520, -520, -520, -520, -520, -520, -520, -520, -520, -520,
+     -520, -520, -520, -520, -520, -520, -520, -520, -520, -520,
+     -520, -520, -520, -520, -520, -520, -520, -520, -520, -520,
+     -520, -520, -520, -520, -520, -520, -520, -520, -520, -520,
+     -520, -520, -520, -520, -520, -520, -520, -520, -520, -520,
+     -520, -520, -520, -520, -520, -520, -520, -520, -520, -520,
+     -520, -520, -520, -520, -520, -520, -520, -520, -520, -520,
+     -520, -520, -520, -520, -520, -520, -520, -520, -520, -520,
+     -520, -520, -520, -520, -520, -520, -520, -520, -520, -520,
+
+     -520, -520, -520, -520, -520, -520, -520, -520, -520, -520,
+     -520, -520, -520, -520, -520, -520, -520, -520, -520, -520,
+     -520, -520, -520, -520, -520, -520, -520, -520
+    },
+
+    {
+       67, -521, -521, -521, -521, -521, -521, -521, -521, -521,
+     -521, -521, -521, -521, -521, -521, -521, -521, -521, -521,
+     -521, -521, -521, -521, -521, -521, -521, -521, -521, -521,
+     -521, -521, -521, -521, -521, -521, -521, -521, -521, -521,
+     -521, -521, -521, -521, -521, -521, -521, -521, -521, -521,
+     -521, -521, -521, -521, -521, -521, -521, -521, -521, -521,
+     -521, -521, -521, -521, -521, -521, -521, -521, -521, -521,
+
+     -521, -521, -521, -521, -521, -521, -521, -521, -521, -521,
+     -521, -521, -521, -521, -521, -521, -521, -521, -521, -521,
+     -521, -521, -521, -521, -521, -521, -521, -521, -521, -521,
+     -521, -521, -521, -521, -521, -521, -521, -521, -521, -521,
+     -521, -521, -521, -521, -521, -521, -521, -521, -521, -521,
+     -521, -521, -521, -521, -521, -521, -521, -521
+    },
+
+    {
+       67, -522, -522, -522, -522, -522, -522, -522, -522, -522,
+     -522, -522, -522, -522, -522, -522, -522, -522, -522, -522,
+     -522, -522, -522, -522, -522, -522, -522, -522, -522, -522,
+     -522, -522, -522, -522, -522, -522, -522, -522, -522, -522,
+
+     -522, -522, -522, -522, -522, -522, -522, -522, -522, -522,
+     -522, -522, -522, -522, -522, -522, -522, -522, -522, -522,
+     -522, -522, -522, -522, -522, -522, -522, -522, -522, -522,
+     -522, -522, -522, -522, -522, -522, -522, -522, -522, -522,
+     -522, -522, -522, -522, -522, -522, -522, -522, -522, -522,
+     -522, -522, -522, -522, -522, -522, -522, -522, -522, -522,
+     -522, -522, -522, -522, -522, -522, -522, -522, -522, -522,
+     -522, -522, -522, -522, -522, -522, -522, -522, -522, -522,
+     -522, -522, -522, -522, -522, -522, -522, -522
+    },
+
+    {
+       67, -523, -523, -523, -523, -523, -523, -523, -523, -523,
+
+     -523, -523, -523, -523, -523, -523, -523, -523, -523, -523,
+     -523, -523, -523, -523, -523, -523, -523, -523, -523, -523,
+     -523, -523, -523, -523, -523, -523, -523, -523, -523, -523,
+     -523, -523, -523, -523, -523, -523, -523, -523, -523, -523,
+     -523, -523, -523, -523, -523, -523, -523, -523, -523, -523,
+     -523, -523, -523, -523, -523, -523, -523, -523, -523, -523,
+     -523, -523, -523, -523, -523, -523, -523, -523, -523, -523,
+     -523, -523, -523, -523, -523, -523, -523, -523, -523, -523,
+     -523, -523, -523, -523, -523, -523, -523, -523, -523, -523,
+     -523, -523, -523, -523, -523, -523, -523, -523, -523, -523,
+
+     -523, -523, -523, -523, -523, -523, -523, -523, -523, -523,
+     -523, -523, -523, -523, -523, -523, -523, -523
+    },
+
+    {
+       67, -524, -524, -524, -524, -524, -524, -524, -524, -524,
+     -524, -524, -524, -524, -524, -524, -524, -524, -524, -524,
+     -524, -524, -524, -524, -524, -524, -524, -524, -524, -524,
+     -524, -524, -524, -524, -524, -524, -524, -524, -524, -524,
+     -524, -524, -524, -524, -524, -524, -524, -524, -524, -524,
+     -524, -524, -524, -524, -524, -524, -524, -524, -524, -524,
+     -524, -524, -524, -524, -524, -524, -524, -524, -524, -524,
+     -524, -524, -524, -524, -524, -524, -524, -524, -524, -524,
+
+     -524, -524, -524, -524, -524, -524, -524, -524, -524, -524,
+     -524, -524, -524, -524, -524, -524, -524, -524, -524, -524,
+     -524, -524, -524, -524, -524, -524, -524, -524, -524, -524,
+     -524, -524, -524, -524, -524, -524, -524, -524, -524, -524,
+     -524, -524, -524, -524, -524, -524, -524, -524
+    },
+
+    {
+       67, -525, -525, -525, -525, -525, -525, -525, -525, -525,
+     -525, -525, -525, -525, -525, -525, -525, -525, -525, -525,
+     -525, -525, -525, -525, -525, -525, -525, -525, -525, -525,
+     -525, -525, -525, -525, -525, -525, -525, -525, -525, -525,
+     -525, -525, -525, -525, -525, -525, -525, -525, -525, -525,
+
+     -525, -525, -525, -525, -525, -525, -525, -525, -525, -525,
+     -525, -525, -525, -525, -525, -525, -525, -525, -525, -525,
+     -525, -525, -525, -525, -525, -525, -525, -525, -525, -525,
+     -525, -525, -525, -525, -525, -525, -525, -525, -525, -525,
+     -525, -525, -525, -525, -525, -525, -525, -525, -525, -525,
+     -525, -525, -525, -525, -525, -525, -525, -525, -525, -525,
+     -525, -525, -525, -525, -525, -525, -525, -525, -525, -525,
+     -525, -525, -525, -525, -525, -525, -525, -525
+    },
+
+    {
+       67, -526, -526, -526, -526, -526, -526, -526, -526, -526,
+     -526, -526, -526, -526, -526, -526, -526, -526, -526, -526,
+
+     -526, -526, -526, -526, -526, -526, -526, -526, -526, -526,
+     -526, -526, -526, -526, -526, -526, -526, -526, -526, -526,
+     -526, -526, -526, -526, -526, -526, -526, -526, -526, -526,
+     -526, -526, -526, -526, -526, -526, -526, -526, -526, -526,
+     -526, -526, -526, -526, -526, -526, -526, -526, -526, -526,
+     -526, -526, -526, -526, -526, -526, -526, -526, -526, -526,
+     -526, -526, -526, -526, -526, -526, -526, -526, -526, -526,
+     -526, -526, -526, -526, -526, -526, -526, -526, -526, -526,
+     -526, -526, -526, -526, -526, -526, -526, -526, -526, -526,
+     -526, -526, -526, -526, -526, -526, -526, -526, -526, -526,
+
+     -526, -526, -526, -526, -526, -526, -526, -526
+    },
+
+    {
+       67, -527, -527, -527, -527, -527, -527, -527, -527, -527,
+     -527, -527, -527, -527, -527, -527, -527, -527, -527, -527,
+     -527, -527, -527, -527, -527, -527, -527, -527, -527, -527,
+     -527, -527, -527, -527, -527, -527, -527, -527, -527, -527,
+     -527, -527, -527, -527, -527, -527, -527, -527, -527, -527,
+     -527, -527, -527, -527, -527, -527, -527, -527, -527, -527,
+     -527, -527, -527, -527, -527, -527, -527, -527, -527, -527,
+     -527, -527, -527, -527, -527, -527, -527, -527, -527, -527,
+     -527, -527, -527, -527, -527, -527, -527, -527, -527, -527,
+
+     -527, -527, -527, -527, -527, -527, -527, -527, -527, -527,
+     -527, -527, -527, -527, -527, -527, -527, -527, -527, -527,
+     -527, -527, -527, -527, -527, -527, -527, -527, -527, -527,
+     -527, -527, -527, -527, -527, -527, -527, -527
+    },
+
+    {
+       67, -528, -528, -528, -528, -528, -528, -528, -528, -528,
+     -528, -528, -528, -528, -528, -528, -528, -528, -528, -528,
+     -528, -528, -528, -528, -528, -528, -528, -528, -528, -528,
+     -528, -528, -528, -528, -528, -528, -528, -528, -528, -528,
+     -528, -528, -528, -528, -528, -528, -528, -528, -528, -528,
+     -528, -528, -528, -528, -528, -528, -528, -528, -528, -528,
+
+     -528, -528, -528, -528, -528, -528, -528, -528, -528, -528,
+     -528, -528, -528, -528, -528, -528, -528, -528, -528, -528,
+     -528, -528, -528, -528, -528, -528, -528, -528, -528, -528,
+     -528, -528, -528, -528, -528, -528, -528, -528, -528, -528,
+     -528, -528, -528, -528, -528, -528, -528, -528, -528, -528,
+     -528, -528, -528, -528, -528, -528, -528, -528, -528, -528,
+     -528, -528, -528, -528, -528, -528, -528, -528
+    },
+
+    {
+       67, -529, -529, -529, -529, -529, -529, -529, -529, -529,
+     -529, -529, -529, -529, -529, -529, -529, -529, -529, -529,
+     -529, -529, -529, -529, -529, -529, -529, -529, -529, -529,
+
+     -529, -529, -529, -529, -529, -529, -529, -529, -529, -529,
+     -529, -529, -529, -529, -529, -529, -529, -529, -529, -529,
+     -529, -529, -529, -529, -529, -529, -529, -529, -529, -529,
+     -529, -529, -529, -529, -529, -529, -529, -529, -529, -529,
+     -529, -529, -529, -529, -529, -529, -529, -529, -529, -529,
+     -529, -529, -529, -529, -529, -529, -529, -529, -529, -529,
+     -529, -529, -529, -529, -529, -529, -529, -529, -529, -529,
+     -529, -529, -529, -529, -529, -529, -529, -529, -529, -529,
+     -529, -529, -529, -529, -529, -529, -529, -529, -529, -529,
+     -529, -529, -529, -529, -529, -529, -529, -529
+
+    },
+
+    {
+       67, -530, -530, -530, -530, -530, -530, -530, -530, -530,
+     -530, -530, -530, -530, -530, -530, -530, -530, -530, -530,
+     -530, -530, -530, -530, -530, -530, -530, -530, -530, -530,
+     -530, -530, -530, -530, -530, -530, -530, -530, -530, -530,
+     -530, -530, -530, -530, -530, -530, -530, -530, -530, -530,
+     -530, -530, -530, -530, -530, -530, -530, -530, -530, -530,
+     -530, -530, -530, -530, -530, -530, -530, -530, -530, -530,
+     -530, -530, -530, -530, -530, -530, -530, -530, -530, -530,
+     -530, -530, -530, -530, -530, -530, -530, -530, -530, -530,
+     -530, -530, -530, -530, -530, -530, -530, -530, -530, -530,
+
+     -530, -530, -530, -530, -530, -530, -530, -530, -530, -530,
+     -530, -530, -530, -530, -530, -530, -530, -530, -530, -530,
+     -530, -530, -530, -530, -530, -530, -530, -530
+    },
+
+    {
+       67, -531, -531, -531, -531, -531, -531, -531, -531, -531,
+     -531, -531, -531, -531, -531, -531, -531, -531, -531, -531,
+     -531, -531, -531, -531, -531, -531, -531, -531, -531, -531,
+     -531, -531, -531, -531, -531, -531, -531, -531, -531, -531,
+     -531, -531, -531, -531, -531, -531, -531, -531, -531, -531,
+     -531, -531, -531, -531, -531, -531, -531, -531, -531, -531,
+     -531, -531, -531, -531, -531, -531, -531, -531, -531, -531,
+
+     -531, -531, -531, -531, -531, -531, -531, -531, -531, -531,
+     -531, -531, -531, -531, -531, -531, -531, -531, -531, -531,
+     -531, -531, -531, -531, -531, -531, -531, -531, -531, -531,
+     -531, -531, -531, -531, -531, -531, -531, -531, -531, -531,
+     -531, -531, -531, -531, -531, -531, -531, -531, -531, -531,
+     -531, -531, -531, -531, -531, -531, -531, -531
+    },
+
+    {
+       67, -532, -532, -532, -532, -532, -532, -532, -532, -532,
+     -532, -532, -532, -532, -532, -532, -532, -532, -532, -532,
+     -532, -532, -532, -532, -532, -532, -532, -532, -532, -532,
+     -532, -532, -532, -532, -532, -532, -532, -532, -532, -532,
+
+     -532, -532, -532, -532, -532, -532, -532, -532, -532, -532,
+     -532, -532, -532, -532, -532, -532, -532, -532, -532, -532,
+     -532, -532, -532, -532, -532, -532, -532, -532, -532, -532,
+     -532, -532, -532, -532, -532, -532, -532, -532, -532, -532,
+     -532, -532, -532, -532, -532, -532, -532, -532, -532, -532,
+     -532, -532, -532, -532, -532, -532, -532, -532, -532, -532,
+     -532, -532, -532, -532, -532, -532, -532, -532, -532, -532,
+     -532, -532, -532, -532, -532, -532, -532, -532, -532, -532,
+     -532, -532, -532, -532, -532, -532, -532, -532
+    },
+
+    {
+       67, -533, -533, -533, -533, -533, -533, -533, -533, -533,
+
+     -533, -533, -533, -533, -533, -533, -533, -533, -533, -533,
+     -533, -533, -533, -533, -533, -533, -533, -533, -533, -533,
+     -533, -533, -533, -533, -533, -533, -533, -533, -533, -533,
+     -533, -533, -533, -533, -533, -533, -533, -533, -533, -533,
+     -533, -533, -533, -533, -533, -533, -533, -533, -533, -533,
+     -533, -533, -533, -533, -533, -533, -533, -533, -533, -533,
+     -533, -533, -533, -533, -533, -533, -533, -533, -533, -533,
+     -533, -533, -533, -533, -533, -533, -533, -533, -533, -533,
+     -533, -533, -533, -533, -533, -533, -533, -533, -533, -533,
+     -533, -533, -533, -533, -533, -533, -533, -533, -533, -533,
+
+     -533, -533, -533, -533, -533, -533, -533, -533, -533, -533,
+     -533, -533, -533, -533, -533, -533, -533, -533
+    },
+
+    {
+       67, -534, -534, -534, -534, -534, -534, -534, -534, -534,
+     -534, -534, -534, -534, -534, -534, -534, -534, -534, -534,
+     -534, -534, -534, -534, -534, -534, -534, -534, -534, -534,
+     -534, -534, -534, -534, -534, -534, -534, -534, -534, -534,
+     -534, -534, -534, -534, -534, -534, -534, -534, -534, -534,
+     -534, -534, -534, -534, -534, -534, -534, -534, -534, -534,
+     -534, -534, -534, -534, -534, -534, -534, -534, -534, -534,
+     -534, -534, -534, -534, -534, -534, -534, -534, -534, -534,
+
+     -534, -534, -534, -534, -534, -534, -534, -534, -534, -534,
+     -534, -534, -534, -534, -534, -534, -534, -534, -534, -534,
+     -534, -534, -534, -534, -534, -534, -534, -534, -534, -534,
+     -534, -534, -534, -534, -534, -534, -534, -534, -534, -534,
+     -534, -534, -534, -534, -534, -534, -534, -534
+    },
+
+    {
+       67, -535, -535, -535, -535, -535, -535, -535, -535, -535,
+     -535, -535, -535, -535, -535, -535, -535, -535, -535, -535,
+     -535, -535, -535, -535, -535, -535, -535, -535, -535, -535,
+     -535, -535, -535, -535, -535, -535, -535, -535, -535, -535,
+     -535, -535, -535, -535, -535, -535, -535, -535, -535, -535,
+
+     -535, -535, -535, -535, -535, -535, -535, -535, -535, -535,
+     -535, -535, -535, -535, -535, -535, -535, -535, -535, -535,
+     -535, -535, -535, -535, -535, -535, -535, -535, -535, -535,
+     -535, -535, -535, -535, -535, -535, -535, -535, -535, -535,
+     -535, -535, -535, -535, -535, -535, -535, -535, -535, -535,
+     -535, -535, -535, -535, -535, -535, -535, -535, -535, -535,
+     -535, -535, -535, -535, -535, -535, -535, -535, -535, -535,
+     -535, -535, -535, -535, -535, -535, -535, -535
+    },
+
+    {
+       67, -536, -536, -536, -536, -536, -536, -536, -536, -536,
+     -536, -536, -536, -536, -536, -536, -536, -536, -536, -536,
+
+     -536, -536, -536, -536, -536, -536, -536, -536, -536, -536,
+     -536, -536, -536, -536, -536, -536, -536, -536, -536, -536,
+     -536, -536, -536, -536, -536, -536, -536, -536, -536, -536,
+     -536, -536, -536, -536, -536, -536, -536, -536, -536, -536,
+     -536, -536, -536, -536, -536, -536, -536, -536, -536, -536,
+     -536, -536, -536, -536, -536, -536, -536, -536, -536, -536,
+     -536, -536, -536, -536, -536, -536, -536, -536, -536, -536,
+     -536, -536, -536, -536, -536, -536, -536, -536, -536, -536,
+     -536, -536, -536, -536, -536, -536, -536, -536, -536, -536,
+     -536, -536, -536, -536, -536, -536, -536, -536, -536, -536,
+
+     -536, -536, -536, -536, -536, -536, -536, -536
+    },
+
+    {
+       67, -537, -537, -537, -537, -537, -537, -537, -537, -537,
+     -537, -537, -537, -537, -537, -537, -537, -537, -537, -537,
+     -537, -537, -537, -537, -537, -537, -537, -537, -537, -537,
+     -537, -537, -537, -537, -537, -537, -537, -537, -537, -537,
+     -537, -537, -537, -537, -537, -537, -537, -537, -537, -537,
+     -537, -537, -537, -537, -537, -537, -537, -537, -537, -537,
+     -537, -537, -537, -537, -537,  637, -537, -537, -537, -537,
+     -537, -537, -537, -537, -537, -537, -537, -537, -537,  638,
+     -537, -537, -537, -537, -537, -537, -537, -537, -537, -537,
+
+     -537, -537, -537, -537, -537, -537, -537, -537, -537, -537,
+     -537, -537, -537, -537, -537, -537, -537, -537, -537, -537,
+     -537, -537, -537, -537, -537, -537, -537, -537, -537, -537,
+     -537, -537, -537, -537, -537, -537, -537, -537
+    },
+
+    {
+       67, -538, -538, -538, -538, -538, -538, -538, -538, -538,
+     -538, -538, -538, -538, -538, -538, -538, -538, -538, -538,
+     -538, -538, -538, -538, -538, -538, -538, -538, -538, -538,
+     -538, -538,  639, -538, -538, -538, -538, -538, -538, -538,
+     -538, -538, -538, -538, -538, -538, -538, -538,  640,  640,
+      640,  640,  640,  640,  640,  640,  640,  640, -538, -538,
+
+     -538, -538, -538, -538, -538, -538, -538, -538, -538, -538,
+     -538, -538, -538, -538, -538, -538, -538, -538, -538, -538,
+     -538, -538, -538, -538, -538, -538, -538, -538, -538, -538,
+     -538, -538, -538, -538, -538, -538, -538, -538, -538, -538,
+     -538, -538, -538, -538, -538, -538, -538, -538, -538, -538,
+     -538, -538, -538, -538, -538, -538, -538, -538, -538, -538,
+     -538, -538, -538, -538, -538, -538, -538, -538
+    },
+
+    {
+       67, -539, -539, -539, -539, -539, -539, -539, -539, -539,
+     -539, -539, -539, -539, -539, -539, -539, -539, -539, -539,
+     -539, -539, -539, -539, -539, -539, -539, -539, -539, -539,
+
+     -539, -539,  641, -539, -539, -539, -539, -539, -539, -539,
+     -539, -539, -539, -539, -539, -539, -539, -539, -539, -539,
+     -539, -539, -539, -539, -539, -539, -539, -539, -539, -539,
+     -539, -539, -539, -539, -539, -539, -539, -539, -539, -539,
+     -539, -539, -539, -539, -539, -539, -539, -539, -539, -539,
+     -539, -539, -539, -539, -539, -539, -539, -539, -539, -539,
+     -539, -539, -539, -539, -539, -539, -539, -539, -539, -539,
+     -539, -539, -539, -539, -539, -539, -539, -539, -539, -539,
+     -539, -539, -539, -539, -539, -539, -539, -539, -539, -539,
+     -539, -539, -539, -539, -539, -539, -539, -539
+
+    },
+
+    {
+       67, -540, -540, -540, -540, -540, -540, -540, -540, -540,
+     -540, -540, -540, -540, -540, -540, -540, -540, -540, -540,
+     -540, -540, -540, -540, -540, -540, -540, -540, -540, -540,
+     -540, -540,  642, -540, -540, -540, -540, -540, -540, -540,
+     -540, -540, -540, -540, -540, -540, -540, -540, -540, -540,
+     -540, -540, -540, -540, -540, -540, -540, -540, -540, -540,
+     -540, -540, -540, -540, -540,  642,  642,  642,  642,  642,
+      642,  642,  642,  642,  642,  642,  642,  642,  642,  642,
+      642,  642,  642,  642,  642,  642,  642,  642,  642,  642,
+      642, -540, -540, -540, -540, -540, -540, -540, -540, -540,
+
+     -540, -540, -540, -540, -540, -540, -540, -540, -540, -540,
+     -540, -540, -540, -540, -540, -540, -540, -540, -540, -540,
+     -540, -540, -540, -540, -540, -540, -540, -540
+    },
+
+    {
+       67, -541, -541, -541, -541, -541, -541, -541, -541, -541,
+     -541, -541, -541, -541, -541, -541, -541, -541, -541, -541,
+     -541, -541, -541, -541, -541, -541, -541, -541, -541, -541,
+     -541, -541, -541, -541, -541, -541, -541, -541, -541, -541,
+     -541, -541, -541, -541, -541, -541, -541, -541, -541, -541,
+     -541, -541, -541, -541, -541, -541, -541, -541, -541, -541,
+     -541, -541, -541, -541, -541, -541, -541, -541, -541, -541,
+
+     -541, -541, -541, -541, -541, -541, -541, -541, -541,  643,
+     -541, -541, -541, -541, -541, -541, -541, -541, -541, -541,
+     -541, -541, -541, -541, -541, -541, -541, -541, -541, -541,
+     -541, -541, -541, -541, -541, -541, -541, -541, -541, -541,
+     -541, -541, -541, -541, -541, -541, -541, -541, -541, -541,
+     -541, -541, -541, -541, -541, -541, -541, -541
+    },
+
+    {
+       67, -542, -542, -542, -542, -542, -542, -542, -542, -542,
+     -542, -542, -542, -542, -542, -542, -542, -542, -542, -542,
+     -542, -542, -542, -542, -542, -542, -542, -542, -542, -542,
+     -542, -542, -542, -542, -542, -542, -542, -542, -542, -542,
+
+     -542, -542, -542, -542, -542, -542, -542, -542, -542, -542,
+     -542, -542, -542, -542, -542, -542, -542, -542, -542, -542,
+     -542, -542, -542, -542, -542, -542, -542, -542, -542, -542,
+     -542, -542, -542, -542, -542, -542,  644, -542, -542, -542,
+     -542, -542, -542, -542, -542, -542, -542, -542, -542, -542,
+     -542, -542, -542, -542, -542, -542, -542, -542, -542, -542,
+     -542, -542, -542, -542, -542, -542, -542, -542, -542, -542,
+     -542, -542, -542, -542, -542, -542, -542, -542, -542, -542,
+     -542, -542, -542, -542, -542, -542, -542, -542
+    },
+
+    {
+       67, -543, -543, -543, -543, -543, -543, -543, -543, -543,
+
+     -543, -543, -543, -543, -543, -543, -543, -543, -543, -543,
+     -543, -543, -543, -543, -543, -543, -543, -543, -543, -543,
+     -543, -543, -543, -543, -543, -543, -543, -543, -543, -543,
+     -543, -543, -543, -543, -543, -543, -543, -543, -543, -543,
+     -543, -543, -543, -543, -543, -543, -543, -543, -543, -543,
+     -543, -543, -543, -543, -543, -543, -543, -543, -543, -543,
+     -543, -543, -543, -543, -543, -543,  645, -543, -543, -543,
+     -543, -543, -543, -543, -543, -543, -543, -543, -543, -543,
+     -543, -543, -543, -543, -543, -543, -543, -543, -543, -543,
+     -543, -543, -543, -543, -543, -543, -543, -543, -543, -543,
+
+     -543, -543, -543, -543, -543, -543, -543, -543, -543, -543,
+     -543, -543, -543, -543, -543, -543, -543, -543
+    },
+
+    {
+       67, -544, -544, -544, -544, -544, -544, -544, -544, -544,
+     -544, -544, -544, -544, -544, -544, -544, -544, -544, -544,
+     -544, -544, -544, -544, -544, -544, -544, -544, -544, -544,
+     -544, -544, -544, -544, -544, -544, -544, -544, -544, -544,
+     -544, -544, -544, -544, -544, -544, -544, -544, -544, -544,
+     -544, -544, -544, -544, -544, -544, -544, -544, -544, -544,
+     -544, -544, -544, -544, -544, -544, -544, -544, -544, -544,
+     -544, -544, -544, -544, -544, -544, -544, -544, -544, -544,
+
+     -544, -544, -544, -544, -544, -544,  646, -544, -544, -544,
+     -544, -544, -544, -544, -544, -544, -544, -544, -544, -544,
+     -544, -544, -544, -544, -544, -544, -544, -544, -544, -544,
+     -544, -544, -544, -544, -544, -544, -544, -544, -544, -544,
+     -544, -544, -544, -544, -544, -544, -544, -544
+    },
+
+    {
+       67, -545, -545, -545, -545, -545, -545, -545, -545, -545,
+     -545, -545, -545, -545, -545, -545, -545, -545, -545, -545,
+     -545, -545, -545, -545, -545, -545, -545, -545, -545, -545,
+     -545, -545, -545, -545, -545, -545, -545, -545, -545, -545,
+     -545, -545, -545, -545, -545, -545, -545, -545, -545, -545,
+
+     -545, -545, -545, -545, -545, -545, -545, -545, -545, -545,
+     -545, -545, -545, -545, -545, -545,  647, -545, -545, -545,
+     -545, -545, -545, -545, -545, -545, -545, -545, -545, -545,
+     -545, -545, -545, -545, -545, -545, -545, -545, -545, -545,
+     -545, -545, -545, -545, -545, -545, -545, -545, -545, -545,
+     -545, -545, -545, -545, -545, -545, -545, -545, -545, -545,
+     -545, -545, -545, -545, -545, -545, -545, -545, -545, -545,
+     -545, -545, -545, -545, -545, -545, -545, -545
+    },
+
+    {
+       67, -546, -546, -546, -546, -546, -546, -546, -546, -546,
+     -546, -546, -546, -546, -546, -546, -546, -546, -546, -546,
+
+     -546, -546, -546, -546, -546, -546, -546, -546, -546, -546,
+     -546, -546, -546, -546, -546, -546, -546, -546, -546, -546,
+     -546, -546, -546, -546, -546, -546, -546, -546, -546, -546,
+     -546, -546, -546, -546, -546, -546, -546, -546, -546, -546,
+     -546, -546, -546, -546, -546, -546, -546, -546, -546, -546,
+     -546, -546, -546, -546, -546, -546, -546, -546, -546, -546,
+     -546, -546, -546, -546, -546, -546, -546, -546, -546, -546,
+     -546, -546, -546, -546, -546, -546, -546, -546, -546, -546,
+     -546, -546, -546, -546, -546, -546, -546, -546, -546, -546,
+     -546, -546, -546, -546, -546, -546, -546, -546, -546, -546,
+
+     -546, -546, -546, -546, -546, -546, -546, -546
+    },
+
+    {
+       67, -547, -547, -547, -547, -547, -547, -547, -547, -547,
+     -547, -547, -547, -547, -547, -547, -547, -547, -547, -547,
+     -547, -547, -547, -547, -547, -547, -547, -547, -547, -547,
+     -547, -547, -547, -547, -547, -547, -547, -547, -547, -547,
+     -547, -547, -547, -547, -547, -547, -547, -547, -547, -547,
+     -547, -547, -547, -547, -547, -547, -547, -547, -547, -547,
+     -547, -547, -547, -547, -547, -547, -547, -547, -547, -547,
+     -547, -547, -547, -547, -547, -547, -547, -547, -547,  648,
+     -547, -547, -547, -547, -547, -547, -547, -547, -547, -547,
+
+     -547, -547, -547, -547, -547, -547, -547, -547, -547, -547,
+     -547, -547, -547, -547, -547, -547, -547, -547, -547, -547,
+     -547, -547, -547, -547, -547, -547, -547, -547, -547, -547,
+     -547, -547, -547, -547, -547, -547, -547, -547
+    },
+
+    {
+       67, -548, -548, -548, -548, -548, -548, -548, -548, -548,
+     -548, -548, -548, -548, -548, -548, -548, -548, -548, -548,
+     -548, -548, -548, -548, -548, -548, -548, -548, -548, -548,
+     -548, -548, -548, -548, -548, -548, -548, -548, -548, -548,
+     -548, -548, -548, -548, -548, -548, -548, -548, -548, -548,
+     -548, -548, -548, -548, -548, -548, -548, -548, -548, -548,
+
+     -548, -548, -548, -548, -548, -548, -548, -548, -548, -548,
+     -548, -548, -548, -548, -548, -548, -548, -548, -548, -548,
+     -548, -548, -548, -548, -548, -548, -548, -548, -548, -548,
+     -548, -548, -548, -548, -548, -548, -548, -548, -548, -548,
+     -548, -548, -548, -548, -548, -548, -548, -548, -548, -548,
+     -548, -548, -548, -548, -548, -548, -548, -548, -548, -548,
+     -548, -548, -548, -548, -548, -548, -548, -548
+    },
+
+    {
+       67, -549, -549, -549, -549, -549, -549, -549, -549, -549,
+     -549, -549, -549, -549, -549, -549, -549, -549, -549, -549,
+     -549, -549, -549, -549, -549, -549, -549, -549, -549, -549,
+
+     -549, -549, -549, -549, -549, -549, -549, -549, -549, -549,
+     -549, -549, -549, -549, -549, -549, -549, -549, -549, -549,
+     -549, -549, -549, -549, -549, -549, -549, -549, -549, -549,
+     -549, -549, -549, -549, -549, -549, -549, -549, -549, -549,
+     -549, -549, -549, -549, -549, -549, -549, -549, -549, -549,
+     -549, -549, -549, -549, -549, -549, -549, -549, -549, -549,
+     -549, -549, -549, -549, -549, -549, -549, -549, -549, -549,
+     -549, -549, -549, -549, -549, -549, -549, -549, -549, -549,
+     -549, -549, -549, -549, -549, -549, -549, -549, -549, -549,
+     -549, -549, -549, -549, -549, -549, -549, -549
+
+    },
+
+    {
+       67, -550, -550, -550, -550, -550, -550, -550, -550, -550,
+     -550, -550, -550, -550, -550, -550, -550, -550, -550, -550,
+     -550, -550, -550, -550, -550, -550, -550, -550, -550, -550,
+     -550, -550, -550, -550, -550, -550, -550, -550, -550, -550,
+     -550, -550, -550, -550, -550, -550, -550, -550, -550, -550,
+     -550, -550, -550, -550, -550, -550, -550, -550, -550, -550,
+     -550, -550, -550, -550, -550, -550, -550, -550, -550, -550,
+     -550, -550, -550, -550, -550, -550, -550, -550, -550, -550,
+     -550, -550, -550, -550, -550, -550, -550, -550, -550, -550,
+     -550, -550, -550, -550, -550, -550, -550, -550, -550, -550,
+
+     -550, -550, -550, -550, -550, -550, -550, -550, -550, -550,
+     -550, -550, -550, -550, -550, -550, -550, -550, -550, -550,
+     -550, -550, -550, -550, -550, -550, -550, -550
+    },
+
+    {
+       67, -551, -551, -551, -551, -551, -551, -551, -551, -551,
+     -551, -551, -551, -551, -551, -551, -551, -551, -551, -551,
+     -551, -551, -551, -551, -551, -551, -551, -551, -551, -551,
+     -551, -551, -551, -551, -551, -551, -551, -551, -551, -551,
+     -551, -551, -551, -551, -551, -551, -551, -551, -551, -551,
+     -551, -551, -551, -551, -551, -551, -551, -551, -551, -551,
+     -551, -551, -551, -551, -551, -551, -551, -551, -551, -551,
+
+     -551, -551, -551, -551, -551, -551, -551, -551, -551, -551,
+     -551, -551, -551, -551, -551, -551, -551, -551, -551, -551,
+     -551, -551, -551, -551, -551, -551, -551, -551, -551, -551,
+     -551, -551, -551, -551, -551, -551, -551, -551, -551, -551,
+     -551, -551, -551, -551, -551, -551, -551, -551, -551, -551,
+     -551, -551, -551, -551, -551, -551, -551, -551
+    },
+
+    {
+       67, -552, -552, -552, -552, -552, -552, -552, -552, -552,
+     -552, -552, -552, -552, -552, -552, -552, -552, -552, -552,
+     -552, -552, -552, -552, -552, -552, -552, -552, -552, -552,
+     -552, -552, -552, -552, -552, -552, -552, -552, -552, -552,
+
+     -552, -552, -552, -552, -552, -552, -552, -552, -552, -552,
+     -552, -552, -552, -552, -552, -552, -552, -552, -552, -552,
+     -552, -552, -552, -552, -552, -552, -552, -552, -552, -552,
+     -552, -552, -552, -552, -552, -552, -552, -552, -552, -552,
+     -552, -552, -552,  649, -552, -552, -552, -552, -552, -552,
+     -552, -552, -552, -552, -552, -552, -552, -552, -552, -552,
+     -552, -552, -552, -552, -552, -552, -552, -552, -552, -552,
+     -552, -552, -552, -552, -552, -552, -552, -552, -552, -552,
+     -552, -552, -552, -552, -552, -552, -552, -552
+    },
+
+    {
+       67, -553, -553, -553, -553, -553, -553, -553, -553, -553,
+
+     -553, -553, -553, -553, -553, -553, -553, -553, -553, -553,
+     -553, -553, -553, -553, -553, -553, -553, -553, -553, -553,
+     -553, -553, -553, -553, -553, -553, -553, -553, -553, -553,
+     -553, -553, -553, -553, -553, -553, -553, -553, -553, -553,
+     -553, -553, -553, -553, -553, -553, -553, -553, -553, -553,
+     -553, -553, -553, -553, -553, -553, -553, -553, -553, -553,
+     -553, -553, -553, -553, -553, -553, -553, -553, -553, -553,
+     -553, -553, -553, -553, -553, -553, -553, -553, -553,  650,
+     -553, -553, -553, -553, -553, -553, -553, -553, -553, -553,
+     -553, -553, -553, -553, -553, -553, -553, -553, -553, -553,
+
+     -553, -553, -553, -553, -553, -553, -553, -553, -553, -553,
+     -553, -553, -553, -553, -553, -553, -553, -553
+    },
+
+    {
+       67, -554, -554, -554, -554, -554, -554, -554, -554, -554,
+     -554, -554, -554, -554, -554, -554, -554, -554, -554, -554,
+     -554, -554, -554, -554, -554, -554, -554, -554, -554, -554,
+     -554, -554, -554, -554, -554, -554, -554, -554, -554, -554,
+     -554, -554, -554, -554, -554, -554, -554, -554, -554, -554,
+     -554, -554, -554, -554, -554, -554, -554, -554, -554, -554,
+     -554, -554, -554, -554, -554, -554, -554, -554, -554, -554,
+     -554, -554, -554, -554, -554, -554, -554, -554, -554, -554,
+
+     -554, -554,  651, -554, -554, -554, -554, -554, -554, -554,
+     -554, -554, -554, -554, -554, -554, -554, -554, -554, -554,
+     -554, -554, -554, -554, -554, -554, -554, -554, -554, -554,
+     -554, -554, -554, -554, -554, -554, -554, -554, -554, -554,
+     -554, -554, -554, -554, -554, -554, -554, -554
+    },
+
+    {
+       67, -555, -555, -555, -555, -555, -555, -555, -555, -555,
+     -555, -555, -555, -555, -555, -555, -555, -555, -555, -555,
+     -555, -555, -555, -555, -555, -555, -555, -555, -555, -555,
+     -555, -555, -555, -555, -555, -555, -555, -555, -555, -555,
+     -555, -555, -555, -555, -555, -555, -555, -555, -555, -555,
+
+     -555, -555, -555, -555, -555, -555, -555, -555, -555, -555,
+     -555, -555, -555, -555, -555,  652, -555, -555, -555, -555,
+     -555, -555, -555, -555, -555, -555, -555, -555, -555, -555,
+     -555, -555, -555, -555, -555, -555, -555, -555, -555, -555,
+     -555, -555, -555, -555, -555, -555, -555, -555, -555, -555,
+     -555, -555, -555, -555, -555, -555, -555, -555, -555, -555,
+     -555, -555, -555, -555, -555, -555, -555, -555, -555, -555,
+     -555, -555, -555, -555, -555, -555, -555, -555
+    },
+
+    {
+       67, -556, -556, -556, -556, -556, -556, -556, -556, -556,
+     -556, -556, -556, -556, -556, -556, -556, -556, -556, -556,
+
+     -556, -556, -556, -556, -556, -556, -556, -556, -556, -556,
+     -556, -556, -556, -556, -556, -556, -556, -556, -556, -556,
+     -556, -556, -556, -556, -556, -556, -556, -556, -556, -556,
+     -556, -556, -556, -556, -556, -556, -556, -556, -556, -556,
+     -556, -556, -556, -556, -556, -556, -556, -556, -556, -556,
+     -556, -556, -556, -556, -556, -556, -556, -556, -556, -556,
+     -556, -556, -556, -556, -556, -556, -556, -556, -556,  653,
+     -556, -556, -556, -556, -556, -556, -556, -556, -556, -556,
+     -556, -556, -556, -556, -556, -556, -556, -556, -556, -556,
+     -556, -556, -556, -556, -556, -556, -556, -556, -556, -556,
+
+     -556, -556, -556, -556, -556, -556, -556, -556
+    },
+
+    {
+       67, -557, -557, -557, -557, -557, -557, -557, -557, -557,
+     -557, -557, -557, -557, -557, -557, -557, -557, -557, -557,
+     -557, -557, -557, -557, -557, -557, -557, -557, -557, -557,
+     -557, -557, -557, -557, -557, -557, -557, -557, -557, -557,
+     -557, -557, -557, -557, -557, -557, -557, -557, -557, -557,
+     -557, -557, -557, -557, -557, -557, -557, -557, -557, -557,
+     -557, -557, -557, -557, -557, -557,  654, -557, -557, -557,
+     -557, -557, -557, -557, -557, -557, -557, -557, -557, -557,
+     -557, -557, -557, -557, -557, -557, -557, -557, -557, -557,
+
+     -557, -557, -557, -557, -557, -557, -557, -557, -557, -557,
+     -557, -557, -557, -557, -557, -557, -557, -557, -557, -557,
+     -557, -557, -557, -557, -557, -557, -557, -557, -557, -557,
+     -557, -557, -557, -557, -557, -557, -557, -557
+    },
+
+    {
+       67, -558, -558, -558, -558, -558, -558, -558, -558, -558,
+     -558, -558, -558, -558, -558, -558, -558, -558, -558, -558,
+     -558, -558, -558, -558, -558, -558, -558, -558, -558, -558,
+     -558, -558, -558, -558, -558, -558, -558, -558, -558, -558,
+     -558, -558, -558, -558, -558, -558, -558, -558, -558, -558,
+     -558, -558, -558, -558, -558, -558, -558, -558, -558, -558,
+
+     -558, -558, -558, -558, -558, -558, -558, -558, -558, -558,
+     -558, -558, -558, -558, -558, -558, -558, -558, -558, -558,
+     -558, -558,  655, -558, -558, -558, -558, -558, -558, -558,
+     -558, -558, -558, -558, -558, -558, -558, -558, -558, -558,
+     -558, -558, -558, -558, -558, -558, -558, -558, -558, -558,
+     -558, -558, -558, -558, -558, -558, -558, -558, -558, -558,
+     -558, -558, -558, -558, -558, -558, -558, -558
+    },
+
+    {
+       67, -559, -559, -559, -559, -559, -559, -559, -559, -559,
+     -559, -559, -559, -559, -559, -559, -559, -559, -559, -559,
+     -559, -559, -559, -559, -559, -559, -559, -559, -559, -559,
+
+     -559, -559, -559, -559, -559, -559, -559, -559, -559, -559,
+     -559, -559, -559, -559, -559, -559, -559, -559, -559, -559,
+     -559, -559, -559, -559, -559, -559, -559, -559, -559, -559,
+     -559, -559, -559, -559, -559, -559, -559, -559, -559, -559,
+     -559, -559, -559, -559, -559, -559, -559, -559, -559, -559,
+     -559, -559, -559, -559, -559, -559, -559, -559, -559, -559,
+     -559, -559, -559, -559, -559, -559, -559, -559, -559, -559,
+     -559, -559, -559, -559, -559, -559, -559, -559, -559, -559,
+     -559, -559, -559, -559, -559, -559, -559, -559, -559, -559,
+     -559, -559, -559, -559, -559, -559, -559, -559
+
+    },
+
+    {
+       67, -560, -560, -560, -560, -560, -560, -560, -560, -560,
+     -560, -560, -560, -560, -560, -560, -560, -560, -560, -560,
+     -560, -560, -560, -560, -560, -560, -560, -560, -560, -560,
+     -560, -560, -560, -560, -560, -560, -560, -560, -560, -560,
+     -560, -560, -560, -560, -560, -560, -560, -560, -560, -560,
+     -560, -560, -560, -560, -560, -560, -560, -560, -560, -560,
+     -560, -560, -560, -560, -560, -560, -560, -560, -560, -560,
+     -560, -560, -560, -560, -560, -560, -560, -560, -560, -560,
+     -560, -560, -560, -560, -560, -560, -560, -560, -560, -560,
+     -560, -560, -560, -560, -560, -560, -560, -560, -560, -560,
+
+     -560, -560, -560, -560, -560, -560, -560, -560, -560, -560,
+     -560, -560, -560, -560, -560, -560, -560, -560, -560, -560,
+     -560, -560, -560, -560, -560, -560, -560, -560
+    },
+
+    {
+       67, -561, -561, -561, -561, -561, -561, -561, -561, -561,
+     -561, -561, -561, -561, -561, -561, -561, -561, -561, -561,
+     -561, -561, -561, -561, -561, -561, -561, -561, -561, -561,
+     -561, -561, -561, -561, -561, -561, -561, -561, -561, -561,
+     -561, -561, -561, -561, -561, -561, -561, -561, -561, -561,
+     -561, -561, -561, -561, -561, -561, -561, -561, -561, -561,
+     -561, -561, -561, -561, -561, -561, -561, -561, -561, -561,
+
+     -561, -561, -561, -561, -561, -561, -561, -561, -561, -561,
+     -561, -561, -561, -561, -561, -561, -561, -561, -561, -561,
+     -561, -561, -561, -561, -561, -561, -561, -561, -561, -561,
+     -561, -561, -561, -561, -561, -561, -561, -561, -561, -561,
+     -561, -561, -561, -561, -561, -561, -561, -561, -561, -561,
+     -561, -561, -561, -561, -561, -561, -561, -561
+    },
+
+    {
+       67, -562, -562, -562, -562, -562, -562, -562, -562, -562,
+     -562, -562, -562, -562, -562, -562, -562, -562, -562, -562,
+     -562, -562, -562, -562, -562, -562, -562, -562, -562, -562,
+     -562, -562, -562, -562, -562, -562, -562, -562, -562, -562,
+
+     -562, -562, -562, -562, -562, -562, -562, -562, -562, -562,
+     -562, -562, -562, -562, -562, -562, -562, -562, -562, -562,
+     -562, -562, -562, -562, -562, -562, -562, -562, -562, -562,
+     -562, -562, -562, -562, -562, -562, -562, -562, -562, -562,
+     -562, -562, -562, -562, -562, -562, -562, -562, -562, -562,
+     -562, -562, -562, -562, -562, -562, -562, -562, -562, -562,
+     -562, -562, -562, -562, -562, -562, -562, -562, -562, -562,
+     -562, -562, -562, -562, -562, -562, -562, -562, -562, -562,
+     -562, -562, -562, -562, -562, -562, -562, -562
+    },
+
+    {
+       67, -563, -563, -563, -563, -563, -563, -563, -563, -563,
+
+     -563, -563, -563, -563, -563, -563, -563, -563, -563, -563,
+     -563, -563, -563, -563, -563, -563, -563, -563, -563, -563,
+     -563, -563, -563, -563, -563, -563, -563, -563, -563, -563,
+     -563, -563, -563, -563, -563, -563, -563, -563, -563, -563,
+     -563, -563, -563, -563, -563, -563, -563, -563, -563, -563,
+     -563, -563, -563, -563, -563, -563, -563, -563, -563, -563,
+     -563, -563, -563, -563, -563, -563, -563, -563, -563, -563,
+     -563, -563, -563, -563, -563, -563, -563, -563, -563, -563,
+     -563, -563, -563, -563, -563, -563, -563, -563, -563, -563,
+     -563, -563, -563, -563, -563, -563, -563, -563, -563, -563,
+
+     -563, -563, -563, -563, -563, -563, -563, -563, -563, -563,
+     -563, -563, -563, -563, -563, -563, -563, -563
+    },
+
+    {
+       67, -564, -564, -564, -564, -564, -564, -564, -564, -564,
+     -564, -564, -564, -564, -564, -564, -564, -564, -564, -564,
+     -564, -564, -564, -564, -564, -564, -564, -564, -564, -564,
+     -564, -564, -564, -564, -564, -564, -564, -564, -564, -564,
+     -564, -564, -564, -564, -564, -564, -564, -564, -564, -564,
+     -564, -564, -564, -564, -564, -564, -564, -564, -564, -564,
+     -564, -564, -564, -564, -564, -564, -564, -564, -564, -564,
+     -564, -564, -564, -564, -564, -564, -564, -564, -564, -564,
+
+     -564, -564, -564, -564, -564, -564, -564, -564, -564, -564,
+     -564, -564, -564, -564, -564, -564, -564, -564, -564, -564,
+     -564, -564, -564, -564, -564, -564, -564, -564, -564, -564,
+     -564, -564, -564, -564, -564, -564, -564, -564, -564, -564,
+     -564, -564, -564, -564, -564, -564, -564, -564
+    },
+
+    {
+       67, -565, -565, -565, -565, -565, -565, -565, -565, -565,
+     -565, -565, -565, -565, -565, -565, -565, -565, -565, -565,
+     -565, -565, -565, -565, -565, -565, -565, -565, -565, -565,
+     -565, -565, -565, -565, -565, -565, -565, -565, -565, -565,
+     -565, -565, -565, -565, -565, -565, -565, -565, -565, -565,
+
+     -565, -565, -565, -565, -565, -565, -565, -565, -565, -565,
+     -565, -565, -565, -565, -565, -565, -565, -565, -565, -565,
+     -565, -565, -565, -565, -565, -565, -565, -565, -565, -565,
+     -565, -565, -565, -565, -565, -565, -565, -565, -565, -565,
+     -565, -565, -565, -565, -565, -565, -565, -565, -565, -565,
+     -565, -565, -565, -565, -565, -565, -565, -565, -565, -565,
+     -565, -565, -565, -565, -565, -565, -565, -565, -565, -565,
+     -565, -565, -565, -565, -565, -565, -565, -565
+    },
+
+    {
+       67, -566, -566, -566, -566, -566, -566, -566, -566, -566,
+     -566, -566, -566, -566, -566, -566, -566, -566, -566, -566,
+
+     -566, -566, -566, -566, -566, -566, -566, -566, -566, -566,
+     -566, -566, -566, -566, -566, -566, -566, -566, -566, -566,
+     -566, -566, -566, -566, -566, -566, -566, -566, -566, -566,
+     -566, -566, -566, -566, -566, -566, -566, -566, -566, -566,
+     -566, -566, -566, -566, -566, -566, -566, -566, -566, -566,
+     -566, -566, -566, -566, -566, -566, -566, -566, -566, -566,
+     -566, -566, -566, -566, -566, -566, -566, -566, -566, -566,
+     -566, -566, -566, -566, -566, -566, -566, -566, -566, -566,
+     -566, -566, -566, -566, -566, -566, -566, -566, -566, -566,
+     -566, -566, -566, -566, -566, -566, -566, -566, -566, -566,
+
+     -566, -566, -566, -566, -566, -566, -566, -566
+    },
+
+    {
+       67, -567, -567, -567, -567, -567, -567, -567, -567, -567,
+     -567, -567, -567, -567, -567, -567, -567, -567, -567, -567,
+     -567, -567, -567, -567, -567, -567, -567, -567, -567, -567,
+     -567, -567, -567, -567, -567, -567, -567, -567, -567, -567,
+     -567, -567, -567, -567, -567, -567, -567, -567, -567, -567,
+     -567, -567, -567, -567, -567, -567, -567, -567, -567, -567,
+     -567, -567, -567, -567, -567, -567, -567, -567, -567, -567,
+     -567, -567, -567, -567, -567, -567, -567, -567, -567, -567,
+     -567, -567, -567, -567, -567, -567, -567, -567, -567, -567,
+
+     -567, -567, -567, -567, -567, -567, -567, -567, -567, -567,
+     -567, -567, -567, -567, -567, -567, -567, -567, -567, -567,
+     -567, -567, -567, -567, -567, -567, -567, -567, -567, -567,
+     -567, -567, -567, -567, -567, -567, -567, -567
+    },
+
+    {
+       67, -568, -568, -568, -568, -568, -568, -568, -568, -568,
+     -568, -568, -568, -568, -568, -568, -568, -568, -568, -568,
+     -568, -568, -568, -568, -568, -568, -568, -568, -568, -568,
+     -568, -568, -568, -568, -568, -568, -568, -568, -568, -568,
+     -568, -568, -568, -568, -568, -568, -568, -568, -568, -568,
+     -568, -568, -568, -568, -568, -568, -568, -568, -568, -568,
+
+     -568, -568, -568, -568, -568, -568, -568, -568,  656, -568,
+     -568, -568, -568, -568, -568, -568, -568, -568, -568, -568,
+     -568, -568, -568, -568, -568, -568, -568, -568, -568, -568,
+     -568, -568, -568, -568, -568, -568, -568, -568, -568, -568,
+     -568, -568, -568, -568, -568, -568, -568, -568, -568, -568,
+     -568, -568, -568, -568, -568, -568, -568, -568, -568, -568,
+     -568, -568, -568, -568, -568, -568, -568, -568
+    },
+
+    {
+       67, -569, -569, -569, -569, -569, -569, -569, -569, -569,
+     -569, -569, -569, -569, -569, -569, -569, -569, -569, -569,
+     -569, -569, -569, -569, -569, -569, -569, -569, -569, -569,
+
+     -569, -569, -569, -569, -569, -569, -569, -569, -569, -569,
+     -569, -569, -569, -569, -569, -569, -569, -569, -569, -569,
+     -569, -569, -569, -569, -569, -569, -569, -569, -569, -569,
+     -569, -569, -569, -569, -569, -569, -569, -569, -569, -569,
+     -569,  657, -569, -569, -569, -569, -569, -569, -569, -569,
+     -569, -569, -569, -569, -569, -569, -569, -569, -569, -569,
+     -569, -569, -569, -569, -569, -569, -569, -569, -569, -569,
+     -569, -569, -569, -569, -569, -569, -569, -569, -569, -569,
+     -569, -569, -569, -569, -569, -569, -569, -569, -569, -569,
+     -569, -569, -569, -569, -569, -569, -569, -569
+
+    },
+
+    {
+       67, -570, -570, -570, -570, -570, -570, -570, -570, -570,
+     -570, -570, -570, -570, -570, -570, -570, -570, -570, -570,
+     -570, -570, -570, -570, -570, -570, -570, -570, -570, -570,
+     -570, -570, -570, -570, -570, -570, -570, -570, -570, -570,
+     -570, -570, -570, -570, -570, -570, -570, -570, -570, -570,
+     -570, -570, -570, -570, -570, -570, -570, -570, -570, -570,
+     -570, -570, -570, -570, -570, -570, -570, -570, -570, -570,
+     -570, -570, -570, -570, -570, -570, -570, -570, -570, -570,
+     -570, -570, -570, -570, -570, -570, -570, -570, -570,  658,
+     -570, -570, -570, -570, -570, -570, -570, -570, -570, -570,
+
+     -570, -570, -570, -570, -570, -570, -570, -570, -570, -570,
+     -570, -570, -570, -570, -570, -570, -570, -570, -570, -570,
+     -570, -570, -570, -570, -570, -570, -570, -570
+    },
+
+    {
+       67, -571, -571, -571, -571, -571, -571, -571, -571, -571,
+     -571, -571, -571, -571, -571, -571, -571, -571, -571, -571,
+     -571, -571, -571, -571, -571, -571, -571, -571, -571, -571,
+     -571, -571, -571, -571, -571, -571, -571, -571, -571, -571,
+     -571, -571, -571, -571, -571, -571, -571, -571, -571, -571,
+     -571, -571, -571, -571, -571, -571, -571, -571, -571, -571,
+     -571, -571, -571, -571, -571, -571, -571, -571, -571, -571,
+
+      659, -571, -571, -571, -571, -571, -571, -571, -571, -571,
+     -571, -571, -571, -571, -571, -571, -571, -571, -571, -571,
+     -571, -571, -571, -571, -571, -571, -571, -571, -571, -571,
+     -571, -571, -571, -571, -571, -571, -571, -571, -571, -571,
+     -571, -571, -571, -571, -571, -571, -571, -571, -571, -571,
+     -571, -571, -571, -571, -571, -571, -571, -571
+    },
+
+    {
+       67, -572, -572, -572, -572, -572, -572, -572, -572, -572,
+     -572, -572, -572, -572, -572, -572, -572, -572, -572, -572,
+     -572, -572, -572, -572, -572, -572, -572, -572, -572, -572,
+     -572, -572,  660, -572, -572, -572, -572, -572, -572, -572,
+
+     -572, -572, -572, -572, -572, -572, -572, -572,  661,  661,
+      661,  661,  661,  661,  661,  661,  661,  661, -572, -572,
+     -572, -572, -572, -572, -572,  660,  660,  660,  660,  660,
+      660,  660,  660,  660,  660,  660,  660,  660,  660,  660,
+      660,  660,  660,  660,  660,  660,  660,  660,  660,  660,
+      660, -572, -572, -572, -572, -572, -572, -572, -572, -572,
+     -572, -572, -572, -572, -572, -572, -572, -572, -572, -572,
+     -572, -572, -572, -572, -572, -572, -572, -572, -572, -572,
+     -572, -572, -572, -572, -572, -572, -572, -572
+    },
+
+    {
+       67, -573, -573, -573, -573, -573, -573, -573, -573, -573,
+
+     -573, -573, -573, -573, -573, -573, -573, -573, -573, -573,
+     -573, -573, -573, -573, -573, -573, -573, -573, -573, -573,
+     -573, -573, -573, -573, -573, -573, -573, -573, -573, -573,
+     -573, -573, -573, -573, -573, -573, -573, -573, -573, -573,
+     -573, -573, -573, -573, -573, -573, -573, -573, -573, -573,
+     -573, -573, -573, -573, -573, -573, -573,  662, -573, -573,
+     -573, -573, -573, -573, -573, -573, -573, -573, -573, -573,
+     -573, -573, -573, -573, -573, -573, -573, -573, -573, -573,
+     -573, -573, -573, -573, -573, -573, -573, -573, -573, -573,
+     -573, -573, -573, -573, -573, -573, -573, -573, -573, -573,
+
+     -573, -573, -573, -573, -573, -573, -573, -573, -573, -573,
+     -573, -573, -573, -573, -573, -573, -573, -573
+    },
+
+    {
+       67, -574, -574, -574, -574, -574, -574, -574, -574, -574,
+     -574, -574, -574, -574, -574, -574, -574, -574, -574, -574,
+     -574, -574, -574, -574, -574, -574, -574, -574, -574, -574,
+     -574, -574,  663, -574, -574, -574, -574, -574, -574, -574,
+     -574, -574, -574, -574, -574, -574, -574, -574,  664,  664,
+      664,  664,  664,  664,  664,  664,  664,  664, -574, -574,
+     -574, -574, -574, -574, -574,  663,  663,  663,  663,  663,
+      663,  663,  663,  663,  663,  663,  663,  663,  663,  663,
+
+      663,  663,  663,  663,  663,  663,  663,  663,  663,  663,
+      663, -574, -574, -574, -574, -574, -574, -574, -574, -574,
+     -574, -574, -574, -574, -574, -574, -574, -574, -574, -574,
+     -574, -574, -574, -574, -574, -574, -574, -574, -574, -574,
+     -574, -574, -574, -574, -574, -574, -574, -574
+    },
+
+    {
+       67, -575, -575, -575, -575, -575, -575, -575, -575, -575,
+     -575, -575, -575, -575, -575, -575, -575, -575, -575, -575,
+     -575, -575, -575, -575, -575, -575, -575, -575, -575, -575,
+     -575, -575, -575, -575, -575, -575, -575, -575, -575, -575,
+     -575, -575, -575, -575, -575, -575, -575, -575, -575, -575,
+
+     -575, -575, -575, -575, -575, -575, -575, -575, -575, -575,
+     -575, -575, -575, -575, -575, -575, -575, -575, -575,  665,
+     -575, -575, -575, -575, -575, -575, -575, -575, -575, -575,
+     -575, -575, -575, -575, -575, -575, -575, -575, -575, -575,
+     -575, -575, -575, -575, -575, -575, -575, -575, -575, -575,
+     -575, -575, -575, -575, -575, -575, -575, -575, -575, -575,
+     -575, -575, -575, -575, -575, -575, -575, -575, -575, -575,
+     -575, -575, -575, -575, -575, -575, -575, -575
+    },
+
+    {
+       67, -576, -576, -576, -576, -576, -576, -576, -576, -576,
+     -576, -576, -576, -576, -576, -576, -576, -576, -576, -576,
+
+     -576, -576, -576, -576, -576, -576, -576, -576, -576, -576,
+     -576, -576, -576, -576, -576, -576, -576, -576, -576, -576,
+     -576, -576, -576, -576, -576, -576, -576, -576, -576, -576,
+     -576, -576, -576, -576, -576, -576, -576, -576, -576, -576,
+     -576, -576, -576, -576, -576, -576, -576, -576, -576, -576,
+     -576, -576, -576, -576, -576, -576, -576,  666, -576, -576,
+     -576, -576, -576, -576, -576, -576, -576, -576, -576, -576,
+     -576, -576, -576, -576, -576, -576, -576, -576, -576, -576,
+     -576, -576, -576, -576, -576, -576, -576, -576, -576, -576,
+     -576, -576, -576, -576, -576, -576, -576, -576, -576, -576,
+
+     -576, -576, -576, -576, -576, -576, -576, -576
+    },
+
+    {
+       67, -577, -577, -577, -577, -577, -577, -577, -577, -577,
+     -577, -577, -577, -577, -577, -577, -577, -577, -577, -577,
+     -577, -577, -577, -577, -577, -577, -577, -577, -577, -577,
+     -577, -577,  667, -577, -577, -577, -577, -577, -577, -577,
+     -577, -577, -577, -577, -577, -577, -577, -577,  668,  668,
+      668,  668,  668,  668,  668,  668,  668,  668, -577, -577,
+     -577, -577, -577, -577, -577,  667,  667,  667,  667,  667,
+      667,  667,  667,  667,  667,  667,  667,  667,  667,  667,
+      667,  667,  667,  667,  667,  667,  667,  667,  667,  667,
+
+      667, -577, -577, -577, -577, -577, -577, -577, -577, -577,
+     -577, -577, -577, -577, -577, -577, -577, -577, -577, -577,
+     -577, -577, -577, -577, -577, -577, -577, -577, -577, -577,
+     -577, -577, -577, -577, -577, -577, -577, -577
+    },
+
+    {
+       67, -578, -578, -578, -578, -578, -578, -578, -578, -578,
+     -578, -578, -578, -578, -578, -578, -578, -578, -578, -578,
+     -578, -578, -578, -578, -578, -578, -578, -578, -578, -578,
+     -578, -578,  669, -578, -578, -578, -578, -578, -578, -578,
+     -578, -578, -578, -578, -578, -578, -578, -578,  670,  670,
+      670,  670,  670,  670,  670,  670,  670,  670, -578, -578,
+
+     -578, -578, -578, -578, -578,  669,  669,  669,  669,  669,
+      669,  669,  669,  669,  669,  669,  669,  669,  669,  669,
+      669,  669,  669,  669,  669,  669,  669,  669,  669,  669,
+      669, -578, -578, -578, -578, -578, -578, -578, -578, -578,
+     -578, -578, -578, -578, -578, -578, -578, -578, -578, -578,
+     -578, -578, -578, -578, -578, -578, -578, -578, -578, -578,
+     -578, -578, -578, -578, -578, -578, -578, -578
+    },
+
+    {
+       67, -579, -579, -579, -579, -579, -579, -579, -579, -579,
+     -579, -579, -579, -579, -579, -579, -579, -579, -579, -579,
+     -579, -579, -579, -579, -579, -579, -579, -579, -579, -579,
+
+     -579, -579, -579, -579, -579, -579, -579, -579, -579, -579,
+     -579, -579, -579, -579, -579, -579, -579, -579, -579, -579,
+     -579, -579, -579, -579, -579, -579, -579, -579, -579, -579,
+     -579, -579, -579, -579, -579, -579, -579,  671, -579, -579,
+     -579, -579, -579, -579, -579, -579, -579, -579, -579, -579,
+     -579, -579, -579, -579, -579, -579, -579, -579, -579, -579,
+     -579, -579, -579, -579, -579, -579, -579, -579, -579, -579,
+     -579, -579, -579, -579, -579, -579, -579, -579, -579, -579,
+     -579, -579, -579, -579, -579, -579, -579, -579, -579, -579,
+     -579, -579, -579, -579, -579, -579, -579, -579
+
+    },
+
+    {
+       67, -580, -580, -580, -580, -580, -580, -580, -580, -580,
+     -580, -580, -580, -580, -580, -580, -580, -580, -580, -580,
+     -580, -580, -580, -580, -580, -580, -580, -580, -580, -580,
+     -580, -580, -580, -580, -580, -580, -580, -580, -580, -580,
+     -580, -580, -580, -580, -580, -580, -580, -580,  672,  672,
+      672,  672,  672,  672,  672,  672,  672,  672, -580, -580,
+     -580, -580, -580, -580, -580, -580, -580, -580, -580, -580,
+     -580, -580, -580, -580, -580, -580, -580, -580, -580, -580,
+     -580, -580, -580, -580, -580, -580, -580, -580, -580, -580,
+     -580, -580, -580, -580, -580, -580, -580, -580, -580, -580,
+
+     -580, -580, -580, -580, -580, -580, -580, -580, -580, -580,
+     -580, -580, -580, -580, -580, -580, -580, -580, -580, -580,
+     -580, -580, -580, -580, -580, -580, -580, -580
+    },
+
+    {
+       67, -581, -581, -581, -581, -581, -581, -581, -581, -581,
+     -581, -581, -581, -581, -581, -581, -581, -581, -581, -581,
+     -581, -581, -581, -581, -581, -581, -581, -581, -581, -581,
+     -581, -581, -581, -581, -581, -581, -581, -581, -581, -581,
+     -581, -581, -581, -581, -581, -581, -581, -581, -581,  673,
+      673,  673,  673,  673,  673,  673,  673,  673, -581, -581,
+     -581, -581, -581, -581, -581, -581, -581, -581, -581, -581,
+
+     -581, -581, -581, -581, -581, -581, -581, -581, -581, -581,
+     -581, -581, -581, -581, -581, -581, -581, -581, -581, -581,
+     -581, -581, -581, -581, -581, -581, -581, -581, -581, -581,
+     -581, -581, -581, -581, -581, -581, -581, -581, -581, -581,
+     -581, -581, -581, -581, -581, -581, -581, -581, -581, -581,
+     -581, -581, -581, -581, -581, -581, -581, -581
+    },
+
+    {
+       67, -582, -582, -582, -582, -582, -582, -582, -582, -582,
+     -582, -582, -582, -582, -582, -582, -582, -582, -582, -582,
+     -582, -582, -582, -582, -582, -582, -582, -582, -582, -582,
+     -582, -582,  674, -582, -582, -582, -582, -582, -582, -582,
+
+     -582, -582, -582, -582, -582, -582, -582, -582,  675,  675,
+      675,  675,  675,  675,  675,  675,  675,  675, -582, -582,
+     -582, -582, -582, -582, -582,  674,  674,  674,  674,  674,
+      674,  674,  674,  674,  674,  674,  674,  674,  674,  674,
+      674,  674,  674,  674,  674,  674,  674,  674,  674,  674,
+      674, -582, -582, -582, -582, -582, -582, -582, -582, -582,
+     -582, -582, -582, -582, -582, -582, -582, -582, -582, -582,
+     -582, -582, -582, -582, -582, -582, -582, -582, -582, -582,
+     -582, -582, -582, -582, -582, -582, -582, -582
+    },
+
+    {
+       67, -583, -583, -583, -583, -583, -583, -583, -583, -583,
+
+     -583, -583, -583, -583, -583, -583, -583, -583, -583, -583,
+     -583, -583, -583, -583, -583, -583, -583, -583, -583, -583,
+     -583, -583,  676, -583, -583, -583, -583, -583, -583, -583,
+     -583, -583, -583, -583, -583, -583, -583, -583, -583, -583,
+     -583, -583, -583, -583, -583, -583, -583, -583, -583, -583,
+     -583, -583, -583, -583, -583, -583, -583, -583, -583, -583,
+     -583, -583, -583, -583, -583, -583, -583, -583, -583, -583,
+     -583, -583, -583, -583, -583, -583, -583, -583, -583, -583,
+     -583, -583, -583, -583, -583, -583, -583, -583, -583, -583,
+     -583, -583, -583, -583, -583, -583, -583, -583, -583, -583,
+
+     -583, -583, -583, -583, -583, -583, -583, -583, -583, -583,
+     -583, -583, -583, -583, -583, -583, -583, -583
+    },
+
+    {
+       67, -584, -584, -584, -584, -584, -584, -584, -584, -584,
+     -584, -584, -584, -584, -584, -584, -584, -584, -584, -584,
+     -584, -584, -584, -584, -584, -584, -584, -584, -584, -584,
+     -584, -584,  677, -584, -584, -584, -584, -584, -584, -584,
+     -584, -584, -584, -584, -584, -584, -584, -584,  678,  678,
+      678,  678,  678,  678,  678,  678,  678,  678, -584, -584,
+     -584, -584, -584, -584, -584,  677,  677,  677,  677,  677,
+      677,  677,  677,  677,  677,  677,  677,  677,  677,  677,
+
+      677,  677,  677,  677,  677,  677,  677,  677,  677,  677,
+      677, -584, -584, -584, -584, -584, -584, -584, -584, -584,
+     -584, -584, -584, -584, -584, -584, -584, -584, -584, -584,
+     -584, -584, -584, -584, -584, -584, -584, -584, -584, -584,
+     -584, -584, -584, -584, -584, -584, -584, -584
+    },
+
+    {
+       67, -585, -585, -585, -585, -585, -585, -585, -585, -585,
+     -585, -585, -585, -585, -585, -585, -585, -585, -585, -585,
+     -585, -585, -585, -585, -585, -585, -585, -585, -585, -585,
+     -585, -585,  679, -585, -585, -585, -585, -585, -585, -585,
+     -585, -585, -585, -585, -585, -585, -585, -585, -585, -585,
+
+     -585, -585, -585, -585, -585, -585, -585, -585, -585, -585,
+     -585, -585, -585, -585, -585, -585, -585, -585, -585, -585,
+     -585, -585, -585, -585, -585, -585, -585, -585, -585, -585,
+     -585, -585, -585, -585, -585, -585, -585, -585, -585, -585,
+     -585, -585, -585, -585, -585, -585, -585, -585, -585, -585,
+     -585, -585, -585, -585, -585, -585, -585, -585, -585, -585,
+     -585, -585, -585, -585, -585, -585, -585, -585, -585, -585,
+     -585, -585, -585, -585, -585, -585, -585, -585
+    },
+
+    {
+       67, -586, -586, -586, -586, -586, -586, -586, -586, -586,
+     -586, -586, -586, -586, -586, -586, -586, -586, -586, -586,
+
+     -586, -586, -586, -586, -586, -586, -586, -586, -586, -586,
+     -586, -586,  680, -586, -586, -586, -586, -586, -586, -586,
+     -586, -586, -586, -586, -586, -586, -586, -586, -586, -586,
+     -586, -586, -586, -586, -586, -586, -586, -586, -586, -586,
+     -586, -586, -586, -586, -586, -586, -586, -586, -586, -586,
+     -586, -586, -586, -586, -586, -586, -586, -586, -586, -586,
+     -586, -586, -586, -586, -586, -586, -586, -586, -586, -586,
+     -586, -586, -586, -586, -586, -586, -586, -586, -586, -586,
+     -586, -586, -586, -586, -586, -586, -586, -586, -586, -586,
+     -586, -586, -586, -586, -586, -586, -586, -586, -586, -586,
+
+     -586, -586, -586, -586, -586, -586, -586, -586
+    },
+
+    {
+       67, -587, -587, -587, -587, -587, -587, -587, -587, -587,
+     -587, -587, -587, -587, -587, -587, -587, -587, -587, -587,
+     -587, -587, -587, -587, -587, -587, -587, -587, -587, -587,
+     -587, -587,  681, -587, -587, -587, -587, -587, -587, -587,
+     -587, -587, -587, -587, -587, -587, -587, -587,  682,  682,
+      682,  682,  682,  682,  682,  682,  682,  682, -587, -587,
+     -587, -587, -587, -587, -587,  681,  681,  681,  681,  681,
+      681,  681,  681,  681,  681,  681,  681,  681,  681,  681,
+      681,  681,  681,  681,  681,  681,  681,  681,  681,  681,
+
+      681, -587, -587, -587, -587, -587, -587, -587, -587, -587,
+     -587, -587, -587, -587, -587, -587, -587, -587, -587, -587,
+     -587, -587, -587, -587, -587, -587, -587, -587, -587, -587,
+     -587, -587, -587, -587, -587, -587, -587, -587
+    },
+
+    {
+       67, -588, -588, -588, -588, -588, -588, -588, -588, -588,
+     -588, -588, -588, -588, -588, -588, -588, -588, -588, -588,
+     -588, -588, -588, -588, -588, -588, -588, -588, -588, -588,
+     -588, -588, -588, -588, -588, -588, -588, -588, -588, -588,
+     -588, -588, -588, -588, -588, -588, -588, -588, -588,  683,
+      683,  683,  683,  683,  683,  683,  683,  683, -588, -588,
+
+     -588, -588, -588, -588, -588, -588, -588, -588, -588, -588,
+     -588, -588, -588, -588, -588, -588, -588, -588, -588, -588,
+     -588, -588, -588, -588, -588, -588, -588, -588, -588, -588,
+     -588, -588, -588, -588, -588, -588, -588, -588, -588, -588,
+     -588, -588, -588, -588, -588, -588, -588, -588, -588, -588,
+     -588, -588, -588, -588, -588, -588, -588, -588, -588, -588,
+     -588, -588, -588, -588, -588, -588, -588, -588
+    },
+
+    {
+       67, -589, -589, -589, -589, -589, -589, -589, -589, -589,
+     -589, -589, -589, -589, -589, -589, -589, -589, -589, -589,
+     -589, -589, -589, -589, -589, -589, -589, -589, -589, -589,
+
+     -589, -589,  684, -589, -589, -589, -589, -589, -589, -589,
+     -589, -589, -589, -589, -589, -589, -589, -589,  685,  685,
+      685,  685,  685,  685,  685,  685,  685,  685, -589, -589,
+     -589, -589, -589, -589, -589,  684,  684,  684,  684,  684,
+      684,  684,  684,  684,  684,  684,  684,  684,  684,  684,
+      684,  684,  684,  684,  684,  684,  684,  684,  684,  684,
+      684, -589, -589, -589, -589, -589, -589, -589, -589, -589,
+     -589, -589, -589, -589, -589, -589, -589, -589, -589, -589,
+     -589, -589, -589, -589, -589, -589, -589, -589, -589, -589,
+     -589, -589, -589, -589, -589, -589, -589, -589
+
+    },
+
+    {
+       67, -590, -590, -590, -590, -590, -590, -590, -590, -590,
+     -590, -590, -590, -590, -590, -590, -590, -590, -590, -590,
+     -590, -590, -590, -590, -590, -590, -590, -590, -590, -590,
+     -590, -590,  686, -590, -590, -590, -590, -590, -590, -590,
+     -590, -590, -590, -590, -590, -590, -590, -590, -590, -590,
+     -590, -590, -590, -590, -590, -590, -590, -590, -590, -590,
+     -590, -590, -590, -590, -590, -590, -590, -590, -590, -590,
+     -590, -590, -590, -590, -590, -590, -590, -590, -590, -590,
+     -590, -590, -590, -590, -590, -590, -590, -590, -590, -590,
+     -590, -590, -590, -590, -590, -590, -590, -590, -590, -590,
+
+     -590, -590, -590, -590, -590, -590, -590, -590, -590, -590,
+     -590, -590, -590, -590, -590, -590, -590, -590, -590, -590,
+     -590, -590, -590, -590, -590, -590, -590, -590
+    },
+
+    {
+       67, -591, -591, -591, -591, -591, -591, -591, -591, -591,
+     -591, -591, -591, -591, -591, -591, -591, -591, -591, -591,
+     -591, -591, -591, -591, -591, -591, -591, -591, -591, -591,
+     -591, -591,  687, -591, -591, -591, -591, -591, -591, -591,
+     -591, -591, -591, -591, -591, -591, -591, -591,  688,  688,
+      688,  688,  688,  688,  688,  688,  688,  688, -591, -591,
+     -591, -591, -591, -591, -591,  687,  687,  687,  687,  687,
+
+      687,  687,  687,  687,  687,  687,  687,  687,  687,  687,
+      687,  687,  687,  687,  687,  687,  687,  687,  687,  687,
+      687, -591, -591, -591, -591, -591, -591, -591, -591, -591,
+     -591, -591, -591, -591, -591, -591, -591, -591, -591, -591,
+     -591, -591, -591, -591, -591, -591, -591, -591, -591, -591,
+     -591, -591, -591, -591, -591, -591, -591, -591
+    },
+
+    {
+       67, -592, -592, -592, -592, -592, -592, -592, -592, -592,
+     -592, -592, -592, -592, -592, -592, -592, -592, -592, -592,
+     -592, -592, -592, -592, -592, -592, -592, -592, -592, -592,
+     -592, -592,  689, -592, -592, -592, -592, -592, -592, -592,
+
+     -592, -592, -592, -592, -592, -592, -592, -592, -592, -592,
+     -592, -592, -592, -592, -592, -592, -592, -592, -592, -592,
+     -592, -592, -592, -592, -592, -592, -592, -592, -592, -592,
+     -592, -592, -592, -592, -592, -592, -592, -592, -592, -592,
+     -592, -592, -592, -592, -592, -592, -592, -592, -592, -592,
+     -592, -592, -592, -592, -592, -592, -592, -592, -592, -592,
+     -592, -592, -592, -592, -592, -592, -592, -592, -592, -592,
+     -592, -592, -592, -592, -592, -592, -592, -592, -592, -592,
+     -592, -592, -592, -592, -592, -592, -592, -592
+    },
+
+    {
+       67, -593, -593, -593, -593, -593, -593, -593, -593, -593,
+
+     -593, -593, -593, -593, -593, -593, -593, -593, -593, -593,
+     -593, -593, -593, -593, -593, -593, -593, -593, -593, -593,
+     -593, -593,  690, -593, -593, -593, -593, -593, -593, -593,
+     -593, -593, -593, -593, -593, -593, -593, -593, -593, -593,
+     -593, -593, -593, -593, -593, -593, -593, -593, -593, -593,
+     -593, -593, -593, -593, -593, -593, -593, -593, -593, -593,
+     -593, -593, -593, -593, -593, -593, -593, -593, -593, -593,
+     -593, -593, -593, -593, -593, -593, -593, -593, -593, -593,
+     -593, -593, -593, -593, -593, -593, -593, -593, -593, -593,
+     -593, -593, -593, -593, -593, -593, -593, -593, -593, -593,
+
+     -593, -593, -593, -593, -593, -593, -593, -593, -593, -593,
+     -593, -593, -593, -593, -593, -593, -593, -593
+    },
+
+    {
+       67, -594, -594, -594, -594, -594, -594, -594, -594, -594,
+     -594, -594, -594, -594, -594, -594, -594, -594, -594, -594,
+     -594, -594, -594, -594, -594, -594, -594, -594, -594, -594,
+     -594, -594,  691, -594, -594, -594, -594, -594, -594, -594,
+     -594, -594, -594, -594, -594, -594, -594, -594,  692,  692,
+      692,  692,  692,  692,  692,  692,  692,  692, -594, -594,
+     -594, -594, -594, -594, -594,  691,  691,  691,  691,  691,
+      691,  691,  691,  691,  691,  691,  691,  691,  691,  691,
+
+      691,  691,  691,  691,  691,  691,  691,  691,  691,  691,
+      691, -594, -594, -594, -594, -594, -594, -594, -594, -594,
+     -594, -594, -594, -594, -594, -594, -594, -594, -594, -594,
+     -594, -594, -594, -594, -594, -594, -594, -594, -594, -594,
+     -594, -594, -594, -594, -594, -594, -594, -594
+    },
+
+    {
+       67, -595, -595, -595, -595, -595, -595, -595, -595, -595,
+     -595, -595, -595, -595, -595, -595, -595, -595, -595, -595,
+     -595, -595, -595, -595, -595, -595, -595, -595, -595, -595,
+     -595, -595, -595, -595, -595, -595, -595, -595, -595, -595,
+     -595, -595, -595, -595, -595, -595, -595, -595, -595, -595,
+
+     -595, -595, -595, -595, -595, -595, -595, -595, -595, -595,
+     -595, -595, -595, -595, -595, -595, -595, -595, -595, -595,
+     -595, -595, -595, -595, -595, -595, -595, -595, -595, -595,
+     -595, -595, -595, -595, -595, -595, -595, -595, -595, -595,
+     -595, -595, -595, -595, -595, -595, -595, -595, -595, -595,
+     -595, -595, -595, -595, -595, -595, -595, -595, -595, -595,
+     -595, -595, -595, -595, -595, -595, -595, -595, -595, -595,
+     -595, -595, -595, -595, -595, -595, -595, -595
+    },
+
+    {
+       67, -596, -596, -596, -596, -596, -596, -596, -596, -596,
+     -596, -596, -596, -596, -596, -596, -596, -596, -596, -596,
+
+     -596, -596, -596, -596, -596, -596, -596, -596, -596, -596,
+     -596, -596, -596, -596, -596, -596, -596, -596, -596, -596,
+     -596, -596, -596, -596, -596, -596, -596, -596, -596, -596,
+     -596, -596, -596, -596, -596, -596, -596, -596, -596, -596,
+     -596, -596, -596, -596, -596, -596, -596, -596, -596, -596,
+     -596, -596, -596, -596, -596, -596, -596, -596, -596, -596,
+     -596, -596, -596, -596, -596, -596, -596, -596, -596, -596,
+     -596, -596, -596, -596, -596, -596, -596, -596, -596, -596,
+     -596, -596, -596, -596, -596, -596, -596, -596, -596, -596,
+     -596, -596, -596, -596, -596, -596, -596, -596, -596, -596,
+
+     -596, -596, -596, -596, -596, -596, -596, -596
+    },
+
+    {
+       67, -597, -597, -597, -597, -597, -597, -597, -597, -597,
+     -597, -597, -597, -597, -597, -597, -597, -597, -597, -597,
+     -597, -597, -597, -597, -597, -597, -597, -597, -597, -597,
+     -597, -597, -597, -597, -597, -597, -597, -597, -597, -597,
+     -597, -597, -597, -597, -597, -597, -597, -597, -597, -597,
+     -597, -597, -597, -597, -597, -597, -597, -597, -597, -597,
+     -597, -597, -597, -597, -597, -597, -597, -597, -597, -597,
+     -597, -597, -597, -597, -597, -597, -597, -597, -597, -597,
+     -597, -597, -597, -597, -597, -597, -597, -597, -597, -597,
+
+     -597, -597, -597, -597, -597, -597, -597, -597, -597, -597,
+     -597, -597, -597, -597, -597, -597, -597, -597, -597, -597,
+     -597, -597, -597, -597, -597, -597, -597, -597, -597, -597,
+     -597, -597, -597, -597, -597, -597, -597, -597
+    },
+
+    {
+       67, -598, -598, -598, -598, -598, -598, -598, -598, -598,
+     -598, -598, -598, -598, -598, -598, -598, -598, -598, -598,
+     -598, -598, -598, -598, -598, -598, -598, -598, -598, -598,
+     -598, -598, -598, -598, -598, -598, -598, -598, -598, -598,
+     -598, -598, -598, -598, -598, -598, -598, -598, -598, -598,
+     -598, -598, -598, -598, -598, -598, -598, -598, -598, -598,
+
+     -598, -598, -598, -598, -598, -598, -598, -598, -598, -598,
+     -598, -598, -598, -598, -598, -598, -598, -598, -598, -598,
+     -598, -598, -598, -598, -598, -598, -598, -598, -598, -598,
+     -598, -598, -598, -598, -598, -598, -598, -598, -598, -598,
+     -598, -598, -598, -598, -598, -598, -598, -598, -598, -598,
+     -598, -598, -598, -598, -598, -598, -598, -598, -598, -598,
+     -598, -598, -598, -598, -598, -598, -598, -598
+    },
+
+    {
+       67, -599, -599, -599, -599, -599, -599, -599, -599, -599,
+     -599, -599, -599, -599, -599, -599, -599, -599, -599, -599,
+     -599, -599, -599, -599, -599, -599, -599, -599, -599, -599,
+
+     -599, -599, -599, -599, -599, -599, -599, -599, -599, -599,
+     -599, -599, -599, -599, -599, -599, -599, -599, -599, -599,
+     -599, -599, -599, -599, -599, -599, -599, -599, -599, -599,
+     -599, -599, -599, -599, -599, -599, -599, -599, -599, -599,
+     -599, -599, -599, -599, -599, -599, -599, -599, -599, -599,
+     -599, -599, -599, -599, -599, -599, -599, -599, -599, -599,
+     -599, -599, -599, -599, -599, -599, -599, -599, -599, -599,
+     -599, -599, -599, -599, -599, -599, -599, -599, -599, -599,
+     -599, -599, -599, -599, -599, -599, -599, -599, -599, -599,
+     -599, -599, -599, -599, -599, -599, -599, -599
+
+    },
+
+    {
+       67, -600, -600, -600, -600, -600, -600, -600, -600, -600,
+     -600, -600, -600, -600, -600, -600, -600, -600, -600, -600,
+     -600, -600, -600, -600, -600, -600, -600, -600, -600, -600,
+     -600, -600, -600, -600, -600, -600, -600, -600, -600, -600,
+     -600, -600, -600, -600, -600, -600, -600, -600, -600, -600,
+     -600, -600, -600, -600, -600, -600, -600, -600, -600, -600,
+     -600, -600, -600, -600, -600, -600, -600, -600, -600, -600,
+     -600, -600, -600, -600, -600, -600, -600, -600, -600, -600,
+     -600, -600, -600, -600, -600, -600, -600, -600, -600, -600,
+     -600, -600, -600, -600, -600, -600, -600, -600, -600, -600,
+
+     -600, -600, -600, -600, -600, -600, -600, -600, -600, -600,
+     -600, -600, -600, -600, -600, -600, -600, -600, -600, -600,
+     -600, -600, -600, -600, -600, -600, -600, -600
+    },
+
+    {
+       67, -601, -601, -601, -601, -601, -601, -601, -601, -601,
+     -601, -601, -601, -601, -601, -601, -601, -601, -601, -601,
+     -601, -601, -601, -601, -601, -601, -601, -601, -601, -601,
+     -601, -601, -601, -601, -601, -601, -601, -601, -601, -601,
+     -601, -601, -601, -601, -601, -601, -601, -601,  693,  693,
+      693,  693,  693,  693,  693,  693,  693,  693, -601, -601,
+     -601, -601, -601, -601, -601, -601, -601, -601, -601, -601,
+
+     -601, -601, -601, -601, -601, -601, -601, -601, -601, -601,
+     -601, -601, -601, -601, -601, -601, -601, -601, -601, -601,
+     -601, -601, -601, -601, -601, -601, -601, -601, -601, -601,
+     -601, -601, -601, -601, -601, -601, -601, -601, -601, -601,
+     -601, -601, -601, -601, -601, -601, -601, -601, -601, -601,
+     -601, -601, -601, -601, -601, -601, -601, -601
+    },
+
+    {
+       67, -602, -602, -602, -602, -602, -602, -602, -602, -602,
+     -602, -602, -602, -602, -602, -602, -602, -602, -602, -602,
+     -602, -602, -602, -602, -602, -602, -602, -602, -602, -602,
+     -602, -602,  694, -602, -602, -602, -602, -602, -602, -602,
+
+     -602, -602, -602, -602, -602, -602, -602, -602, -602, -602,
+     -602, -602, -602, -602, -602, -602, -602, -602, -602, -602,
+     -602, -602, -602, -602, -602,  694,  694,  694,  694,  694,
+      694,  694,  694,  694,  694,  694,  694,  694,  694,  694,
+      694,  694,  694,  694,  694,  694,  694,  694,  694,  694,
+      694, -602, -602, -602, -602, -602, -602, -602, -602, -602,
+     -602, -602, -602, -602, -602, -602, -602, -602, -602, -602,
+     -602, -602, -602, -602, -602, -602, -602, -602, -602, -602,
+     -602, -602, -602, -602, -602, -602, -602, -602
+    },
+
+    {
+       67, -603, -603, -603, -603, -603, -603, -603, -603, -603,
+
+     -603, -603, -603, -603, -603, -603, -603, -603, -603, -603,
+     -603, -603, -603, -603, -603, -603, -603, -603, -603, -603,
+     -603, -603,  694, -603, -603, -603, -603, -603, -603, -603,
+     -603, -603, -603, -603, -603, -603, -603, -603,  695,  695,
+      695,  695,  695,  695,  695,  695,  695,  695, -603, -603,
+     -603, -603, -603, -603, -603,  694,  694,  694,  694,  694,
+      694,  694,  694,  694,  694,  694,  694,  694,  694,  694,
+      694,  694,  694,  694,  694,  694,  694,  694,  694,  694,
+      694, -603, -603, -603, -603, -603, -603, -603, -603, -603,
+     -603, -603, -603, -603, -603, -603, -603, -603, -603, -603,
+
+     -603, -603, -603, -603, -603, -603, -603, -603, -603, -603,
+     -603, -603, -603, -603, -603, -603, -603, -603
+    },
+
+    {
+       67, -604, -604, -604, -604, -604, -604, -604, -604, -604,
+     -604, -604, -604, -604, -604, -604, -604, -604, -604, -604,
+     -604, -604, -604, -604, -604, -604, -604, -604, -604, -604,
+     -604, -604,  696, -604, -604, -604, -604, -604, -604, -604,
+     -604, -604, -604, -604, -604, -604, -604, -604, -604, -604,
+     -604, -604, -604, -604, -604, -604, -604, -604, -604, -604,
+     -604, -604, -604, -604, -604, -604, -604, -604, -604, -604,
+     -604, -604, -604, -604, -604, -604, -604, -604, -604, -604,
+
+     -604, -604, -604, -604, -604, -604, -604, -604, -604, -604,
+     -604, -604, -604, -604, -604, -604, -604, -604, -604, -604,
+     -604, -604, -604, -604, -604, -604, -604, -604, -604, -604,
+     -604, -604, -604, -604, -604, -604, -604, -604, -604, -604,
+     -604, -604, -604, -604, -604, -604, -604, -604
+    },
+
+    {
+       67, -605, -605, -605, -605, -605, -605, -605, -605, -605,
+     -605, -605, -605, -605, -605, -605, -605, -605, -605, -605,
+     -605, -605, -605, -605, -605, -605, -605, -605, -605, -605,
+     -605, -605,  697, -605, -605, -605, -605, -605, -605, -605,
+     -605, -605, -605, -605, -605, -605, -605, -605,  698,  698,
+
+      698,  698,  698,  698,  698,  698,  698,  698, -605, -605,
+     -605, -605, -605, -605, -605,  697,  697,  697,  697,  697,
+      697,  697,  697,  697,  697,  697,  697,  697,  697,  697,
+      697,  697,  697,  697,  697,  697,  697,  697,  697,  697,
+      697, -605, -605, -605, -605, -605, -605, -605, -605, -605,
+     -605, -605, -605, -605, -605, -605, -605, -605, -605, -605,
+     -605, -605, -605, -605, -605, -605, -605, -605, -605, -605,
+     -605, -605, -605, -605, -605, -605, -605, -605
+    },
+
+    {
+       67, -606, -606, -606, -606, -606, -606, -606, -606, -606,
+     -606, -606, -606, -606, -606, -606, -606, -606, -606, -606,
+
+     -606, -606, -606, -606, -606, -606, -606, -606, -606, -606,
+     -606, -606,  699, -606, -606, -606, -606, -606, -606, -606,
+     -606, -606, -606, -606, -606, -606, -606, -606, -606, -606,
+     -606, -606, -606, -606, -606, -606, -606, -606, -606, -606,
+     -606, -606, -606, -606, -606, -606, -606, -606, -606, -606,
+     -606, -606, -606, -606, -606, -606, -606, -606, -606, -606,
+     -606, -606, -606, -606, -606, -606, -606, -606, -606, -606,
+     -606, -606, -606, -606, -606, -606, -606, -606, -606, -606,
+     -606, -606, -606, -606, -606, -606, -606, -606, -606, -606,
+     -606, -606, -606, -606, -606, -606, -606, -606, -606, -606,
+
+     -606, -606, -606, -606, -606, -606, -606, -606
+    },
+
+    {
+       67, -607, -607, -607, -607, -607, -607, -607, -607, -607,
+     -607, -607, -607, -607, -607, -607, -607, -607, -607, -607,
+     -607, -607, -607, -607, -607, -607, -607, -607, -607, -607,
+     -607, -607,  700, -607, -607, -607, -607, -607, -607, -607,
+     -607, -607, -607, -607, -607, -607, -607, -607, -607, -607,
+     -607, -607, -607, -607, -607, -607, -607, -607, -607, -607,
+     -607, -607, -607, -607, -607, -607, -607, -607, -607, -607,
+     -607, -607, -607, -607, -607, -607, -607, -607, -607, -607,
+     -607, -607, -607, -607, -607, -607, -607, -607, -607, -607,
+
+     -607, -607, -607, -607, -607, -607, -607, -607, -607, -607,
+     -607, -607, -607, -607, -607, -607, -607, -607, -607, -607,
+     -607, -607, -607, -607, -607, -607, -607, -607, -607, -607,
+     -607, -607, -607, -607, -607, -607, -607, -607
+    },
+
+    {
+       67, -608, -608, -608, -608, -608, -608, -608, -608, -608,
+     -608, -608, -608, -608, -608, -608, -608, -608, -608, -608,
+     -608, -608, -608, -608, -608, -608, -608, -608, -608, -608,
+     -608, -608,  701, -608, -608, -608, -608, -608, -608, -608,
+     -608, -608, -608, -608, -608, -608, -608, -608,  702,  702,
+      702,  702,  702,  702,  702,  702,  702,  702, -608, -608,
+
+     -608, -608, -608, -608, -608,  701,  701,  701,  701,  701,
+      701,  701,  701,  701,  701,  701,  701,  701,  701,  701,
+      701,  701,  701,  701,  701,  701,  701,  701,  701,  701,
+      701, -608, -608, -608, -608, -608, -608, -608, -608, -608,
+     -608, -608, -608, -608, -608, -608, -608, -608, -608, -608,
+     -608, -608, -608, -608, -608, -608, -608, -608, -608, -608,
+     -608, -608, -608, -608, -608, -608, -608, -608
+    },
+
+    {
+       67, -609, -609, -609, -609, -609, -609, -609, -609, -609,
+     -609, -609, -609, -609, -609, -609, -609, -609, -609, -609,
+     -609, -609, -609, -609, -609, -609, -609, -609, -609, -609,
+
+     -609, -609, -609, -609, -609, -609, -609, -609, -609, -609,
+     -609, -609, -609, -609, -609, -609, -609, -609,  703,  703,
+      703,  703,  703,  703,  703,  703,  703,  703, -609, -609,
+     -609, -609, -609, -609, -609, -609, -609, -609, -609, -609,
+     -609, -609, -609, -609, -609, -609, -609, -609, -609, -609,
+     -609, -609, -609, -609, -609, -609, -609, -609, -609, -609,
+     -609, -609, -609, -609, -609, -609, -609, -609, -609, -609,
+     -609, -609, -609, -609, -609, -609, -609, -609, -609, -609,
+     -609, -609, -609, -609, -609, -609, -609, -609, -609, -609,
+     -609, -609, -609, -609, -609, -609, -609, -609
+
+    },
+
+    {
+       67, -610, -610, -610, -610, -610, -610, -610, -610, -610,
+     -610, -610, -610, -610, -610, -610, -610, -610, -610, -610,
+     -610, -610, -610, -610, -610, -610, -610, -610, -610, -610,
+     -610, -610,  704, -610, -610, -610, -610, -610, -610, -610,
+     -610, -610, -610, -610, -610, -610, -610, -610, -610, -610,
+     -610, -610, -610, -610, -610, -610, -610, -610, -610, -610,
+     -610, -610, -610, -610, -610,  704,  704,  704,  704,  704,
+      704,  704,  704,  704,  704,  704,  704,  704,  704,  704,
+      704,  704,  704,  704,  704,  704,  704,  704,  704,  704,
+      704, -610, -610, -610, -610, -610, -610, -610, -610, -610,
+
+     -610, -610, -610, -610, -610, -610, -610, -610, -610, -610,
+     -610, -610, -610, -610, -610, -610, -610, -610, -610, -610,
+     -610, -610, -610, -610, -610, -610, -610, -610
+    },
+
+    {
+       67, -611, -611, -611, -611, -611, -611, -611, -611, -611,
+     -611, -611, -611, -611, -611, -611, -611, -611, -611, -611,
+     -611, -611, -611, -611, -611, -611, -611, -611, -611, -611,
+     -611, -611,  704, -611, -611, -611, -611, -611, -611, -611,
+     -611, -611, -611, -611, -611, -611, -611, -611,  705,  705,
+      705,  705,  705,  705,  705,  705,  705,  705, -611, -611,
+     -611, -611, -611, -611, -611,  704,  704,  704,  704,  704,
+
+      704,  704,  704,  704,  704,  704,  704,  704,  704,  704,
+      704,  704,  704,  704,  704,  704,  704,  704,  704,  704,
+      704, -611, -611, -611, -611, -611, -611, -611, -611, -611,
+     -611, -611, -611, -611, -611, -611, -611, -611, -611, -611,
+     -611, -611, -611, -611, -611, -611, -611, -611, -611, -611,
+     -611, -611, -611, -611, -611, -611, -611, -611
+    },
+
+    {
+       67, -612, -612, -612, -612, -612, -612, -612, -612, -612,
+     -612, -612, -612, -612, -612, -612, -612, -612, -612, -612,
+     -612, -612, -612, -612, -612, -612, -612, -612, -612, -612,
+     -612, -612,  706, -612, -612, -612, -612, -612, -612, -612,
+
+     -612, -612, -612, -612, -612, -612, -612, -612, -612, -612,
+     -612, -612, -612, -612, -612, -612, -612, -612, -612, -612,
+     -612, -612, -612, -612, -612, -612, -612, -612, -612, -612,
+     -612, -612, -612, -612, -612, -612, -612, -612, -612, -612,
+     -612, -612, -612, -612, -612, -612, -612, -612, -612, -612,
+     -612, -612, -612, -612, -612, -612, -612, -612, -612, -612,
+     -612, -612, -612, -612, -612, -612, -612, -612, -612, -612,
+     -612, -612, -612, -612, -612, -612, -612, -612, -612, -612,
+     -612, -612, -612, -612, -612, -612, -612, -612
+    },
+
+    {
+       67, -613, -613, -613, -613, -613, -613, -613, -613, -613,
+
+     -613, -613, -613, -613, -613, -613, -613, -613, -613, -613,
+     -613, -613, -613, -613, -613, -613, -613, -613, -613, -613,
+     -613, -613,  707, -613, -613, -613, -613, -613, -613, -613,
+     -613, -613, -613, -613, -613, -613, -613, -613,  708,  708,
+      708,  708,  708,  708,  708,  708,  708,  708, -613, -613,
+     -613, -613, -613, -613, -613,  707,  707,  707,  707,  707,
+      707,  707,  707,  707,  707,  707,  707,  707,  707,  707,
+      707,  707,  707,  707,  707,  707,  707,  707,  707,  707,
+      707, -613, -613, -613, -613, -613, -613, -613, -613, -613,
+     -613, -613, -613, -613, -613, -613, -613, -613, -613, -613,
+
+     -613, -613, -613, -613, -613, -613, -613, -613, -613, -613,
+     -613, -613, -613, -613, -613, -613, -613, -613
+    },
+
+    {
+       67, -614, -614, -614, -614, -614, -614, -614, -614, -614,
+     -614, -614, -614, -614, -614, -614, -614, -614, -614, -614,
+     -614, -614, -614, -614, -614, -614, -614, -614, -614, -614,
+     -614, -614,  709, -614, -614, -614, -614, -614, -614, -614,
+     -614, -614, -614, -614, -614, -614, -614, -614, -614, -614,
+     -614, -614, -614, -614, -614, -614, -614, -614, -614, -614,
+     -614, -614, -614, -614, -614, -614, -614, -614, -614, -614,
+     -614, -614, -614, -614, -614, -614, -614, -614, -614, -614,
+
+     -614, -614, -614, -614, -614, -614, -614, -614, -614, -614,
+     -614, -614, -614, -614, -614, -614, -614, -614, -614, -614,
+     -614, -614, -614, -614, -614, -614, -614, -614, -614, -614,
+     -614, -614, -614, -614, -614, -614, -614, -614, -614, -614,
+     -614, -614, -614, -614, -614, -614, -614, -614
+    },
+
+    {
+       67, -615, -615, -615, -615, -615, -615, -615, -615, -615,
+     -615, -615, -615, -615, -615, -615, -615, -615, -615, -615,
+     -615, -615, -615, -615, -615, -615, -615, -615, -615, -615,
+     -615, -615,  710, -615, -615, -615, -615, -615, -615, -615,
+     -615, -615, -615, -615, -615, -615, -615, -615, -615, -615,
+
+     -615, -615, -615, -615, -615, -615, -615, -615, -615, -615,
+     -615, -615, -615, -615, -615, -615, -615, -615, -615, -615,
+     -615, -615, -615, -615, -615, -615, -615, -615, -615, -615,
+     -615, -615, -615, -615, -615, -615, -615, -615, -615, -615,
+     -615, -615, -615, -615, -615, -615, -615, -615, -615, -615,
+     -615, -615, -615, -615, -615, -615, -615, -615, -615, -615,
+     -615, -615, -615, -615, -615, -615, -615, -615, -615, -615,
+     -615, -615, -615, -615, -615, -615, -615, -615
+    },
+
+    {
+       67, -616, -616, -616, -616, -616, -616, -616, -616, -616,
+     -616, -616, -616, -616, -616, -616, -616, -616, -616, -616,
+
+     -616, -616, -616, -616, -616, -616, -616, -616, -616, -616,
+     -616, -616,  711, -616, -616, -616, -616, -616, -616, -616,
+     -616, -616, -616, -616, -616, -616, -616, -616,  712,  712,
+      712,  712,  712,  712,  712,  712,  712,  712, -616, -616,
+     -616, -616, -616, -616, -616,  711,  711,  711,  711,  711,
+      711,  711,  711,  711,  711,  711,  711,  711,  711,  711,
+      711,  711,  711,  711,  711,  711,  711,  711,  711,  711,
+      711, -616, -616, -616, -616, -616, -616, -616, -616, -616,
+     -616, -616, -616, -616, -616, -616, -616, -616, -616, -616,
+     -616, -616, -616, -616, -616, -616, -616, -616, -616, -616,
+
+     -616, -616, -616, -616, -616, -616, -616, -616
+    },
+
+    {
+       67, -617, -617, -617, -617, -617, -617, -617, -617, -617,
+     -617, -617, -617, -617, -617, -617, -617, -617, -617, -617,
+     -617, -617, -617, -617, -617, -617, -617, -617, -617, -617,
+     -617, -617, -617, -617, -617, -617, -617, -617, -617, -617,
+     -617, -617, -617, -617, -617, -617, -617, -617, -617, -617,
+     -617, -617, -617, -617, -617, -617, -617, -617, -617, -617,
+     -617, -617, -617, -617, -617, -617, -617, -617, -617, -617,
+     -617, -617, -617, -617, -617, -617, -617, -617, -617, -617,
+     -617, -617, -617, -617, -617, -617, -617, -617, -617, -617,
+
+     -617, -617, -617, -617, -617, -617, -617, -617, -617, -617,
+     -617, -617, -617, -617, -617, -617, -617, -617, -617, -617,
+     -617, -617, -617, -617, -617, -617, -617, -617, -617, -617,
+     -617, -617, -617, -617, -617, -617, -617, -617
+    },
+
+    {
+       67, -618, -618, -618, -618, -618, -618, -618, -618, -618,
+     -618, -618, -618, -618, -618, -618, -618, -618, -618, -618,
+     -618, -618, -618, -618, -618, -618, -618, -618, -618, -618,
+     -618, -618, -618, -618, -618, -618, -618, -618, -618, -618,
+     -618, -618, -618, -618, -618, -618, -618, -618, -618, -618,
+     -618, -618, -618, -618, -618, -618, -618, -618, -618, -618,
+
+     -618, -618, -618, -618, -618, -618, -618, -618, -618, -618,
+     -618, -618, -618, -618, -618, -618, -618, -618, -618, -618,
+     -618, -618, -618, -618, -618, -618, -618, -618, -618, -618,
+     -618, -618, -618, -618, -618, -618, -618, -618, -618, -618,
+     -618, -618, -618, -618, -618, -618, -618, -618, -618, -618,
+     -618, -618, -618, -618, -618, -618, -618, -618, -618, -618,
+     -618, -618, -618, -618, -618, -618, -618, -618
+    },
+
+    {
+       67, -619, -619, -619, -619, -619, -619, -619, -619, -619,
+     -619, -619, -619, -619, -619, -619, -619, -619, -619, -619,
+     -619, -619, -619, -619, -619, -619, -619, -619, -619, -619,
+
+     -619, -619, -619, -619, -619, -619, -619, -619, -619, -619,
+     -619, -619, -619, -619, -619, -619, -619, -619, -619, -619,
+     -619, -619, -619, -619, -619, -619, -619, -619, -619, -619,
+     -619, -619, -619, -619, -619, -619, -619, -619, -619, -619,
+     -619, -619, -619, -619, -619, -619, -619, -619, -619, -619,
+     -619, -619, -619, -619, -619, -619, -619, -619, -619, -619,
+     -619, -619, -619, -619, -619, -619, -619, -619, -619, -619,
+     -619, -619, -619, -619, -619, -619, -619, -619, -619, -619,
+     -619, -619, -619, -619, -619, -619, -619, -619, -619, -619,
+     -619, -619, -619, -619, -619, -619, -619, -619
+
+    },
+
+    {
+       67, -620, -620, -620, -620, -620, -620, -620, -620, -620,
+     -620, -620, -620, -620, -620, -620, -620, -620, -620, -620,
+     -620, -620, -620, -620, -620, -620, -620, -620, -620, -620,
+     -620, -620, -620, -620, -620, -620, -620, -620, -620, -620,
+     -620, -620, -620, -620, -620, -620, -620, -620, -620, -620,
+     -620, -620, -620, -620, -620, -620, -620, -620, -620, -620,
+     -620, -620, -620, -620, -620, -620, -620, -620, -620, -620,
+     -620, -620, -620, -620, -620, -620, -620, -620, -620, -620,
+     -620, -620, -620, -620, -620, -620, -620, -620, -620, -620,
+     -620, -620, -620, -620, -620, -620, -620, -620, -620, -620,
+
+     -620, -620, -620, -620, -620, -620, -620, -620, -620, -620,
+     -620, -620, -620, -620, -620, -620, -620, -620, -620, -620,
+     -620, -620, -620, -620, -620, -620, -620, -620
+    },
+
+    {
+       67, -621, -621, -621, -621, -621, -621, -621, -621, -621,
+     -621, -621, -621, -621, -621, -621, -621, -621, -621, -621,
+     -621, -621, -621, -621, -621, -621, -621, -621, -621, -621,
+     -621, -621, -621, -621, -621, -621, -621, -621, -621, -621,
+     -621, -621, -621, -621, -621, -621, -621, -621, -621, -621,
+     -621, -621, -621, -621, -621, -621, -621, -621, -621, -621,
+     -621, -621, -621, -621, -621, -621, -621, -621, -621, -621,
+
+     -621, -621, -621, -621, -621, -621, -621, -621, -621, -621,
+     -621, -621, -621, -621, -621, -621, -621, -621, -621, -621,
+     -621, -621, -621, -621, -621, -621, -621, -621, -621, -621,
+     -621, -621, -621, -621, -621, -621, -621, -621, -621, -621,
+     -621, -621, -621, -621, -621, -621, -621, -621, -621, -621,
+     -621, -621, -621, -621, -621, -621, -621, -621
+    },
+
+    {
+       67, -622, -622, -622, -622, -622, -622, -622, -622, -622,
+     -622, -622, -622, -622, -622, -622, -622, -622, -622, -622,
+     -622, -622, -622, -622, -622, -622, -622, -622, -622, -622,
+     -622, -622, -622, -622, -622, -622, -622, -622, -622, -622,
+
+     -622, -622, -622, -622, -622, -622, -622, -622, -622, -622,
+     -622, -622, -622, -622, -622, -622, -622, -622, -622, -622,
+     -622, -622, -622, -622, -622, -622, -622, -622, -622, -622,
+     -622, -622, -622, -622, -622, -622, -622, -622, -622, -622,
+     -622, -622, -622, -622, -622, -622, -622, -622, -622, -622,
+     -622, -622, -622, -622, -622, -622, -622, -622, -622, -622,
+     -622, -622, -622, -622, -622, -622, -622, -622, -622, -622,
+     -622, -622, -622, -622, -622, -622, -622, -622, -622, -622,
+     -622, -622, -622, -622, -622, -622, -622, -622
+    },
+
+    {
+       67, -623, -623, -623, -623, -623, -623, -623, -623, -623,
+
+     -623, -623, -623, -623, -623, -623, -623, -623, -623, -623,
+     -623, -623, -623, -623, -623, -623, -623, -623, -623, -623,
+     -623, -623, -623, -623, -623, -623, -623, -623, -623, -623,
+     -623, -623, -623, -623, -623, -623, -623, -623,  713,  713,
+      713,  713,  713,  713,  713,  713,  713,  713, -623, -623,
+     -623, -623, -623, -623, -623, -623, -623, -623, -623, -623,
+     -623, -623, -623, -623, -623, -623, -623, -623, -623, -623,
+     -623, -623, -623, -623, -623, -623, -623, -623, -623, -623,
+     -623, -623, -623, -623, -623, -623, -623, -623, -623, -623,
+     -623, -623, -623, -623, -623, -623, -623, -623, -623, -623,
+
+     -623, -623, -623, -623, -623, -623, -623, -623, -623, -623,
+     -623, -623, -623, -623, -623, -623, -623, -623
+    },
+
+    {
+       67, -624, -624, -624, -624, -624, -624, -624, -624, -624,
+     -624, -624, -624, -624, -624, -624, -624, -624, -624, -624,
+     -624, -624, -624, -624, -624, -624, -624, -624, -624, -624,
+     -624, -624,  714, -624, -624, -624, -624, -624, -624, -624,
+     -624, -624, -624, -624, -624, -624, -624, -624, -624, -624,
+     -624, -624, -624, -624, -624, -624, -624, -624, -624, -624,
+     -624, -624, -624, -624, -624,  714,  714,  714,  714,  714,
+      714,  714,  714,  714,  714,  714,  714,  714,  714,  714,
+
+      714,  714,  714,  714,  714,  714,  714,  714,  714,  714,
+      714, -624, -624, -624, -624, -624, -624, -624, -624, -624,
+     -624, -624, -624, -624, -624, -624, -624, -624, -624, -624,
+     -624, -624, -624, -624, -624, -624, -624, -624, -624, -624,
+     -624, -624, -624, -624, -624, -624, -624, -624
+    },
+
+    {
+       67, -625, -625, -625, -625, -625, -625, -625, -625, -625,
+     -625, -625, -625, -625, -625, -625, -625, -625, -625, -625,
+     -625, -625, -625, -625, -625, -625, -625, -625, -625, -625,
+     -625, -625,  714, -625, -625, -625, -625, -625, -625, -625,
+     -625, -625, -625, -625, -625, -625, -625, -625,  715,  715,
+
+      715,  715,  715,  715,  715,  715,  715,  715, -625, -625,
+     -625, -625, -625, -625, -625,  714,  714,  714,  714,  714,
+      714,  714,  714,  714,  714,  714,  714,  714,  714,  714,
+      714,  714,  714,  714,  714,  714,  714,  714,  714,  714,
+      714, -625, -625, -625, -625, -625, -625, -625, -625, -625,
+     -625, -625, -625, -625, -625, -625, -625, -625, -625, -625,
+     -625, -625, -625, -625, -625, -625, -625, -625, -625, -625,
+     -625, -625, -625, -625, -625, -625, -625, -625
+    },
+
+    {
+       67, -626, -626, -626, -626, -626, -626, -626, -626, -626,
+     -626, -626, -626, -626, -626, -626, -626, -626, -626, -626,
+
+     -626, -626, -626, -626, -626, -626, -626, -626, -626, -626,
+     -626, -626,  716, -626, -626, -626, -626, -626, -626, -626,
+     -626, -626, -626, -626, -626, -626, -626, -626, -626, -626,
+     -626, -626, -626, -626, -626, -626, -626, -626, -626, -626,
+     -626, -626, -626, -626, -626, -626, -626, -626, -626, -626,
+     -626, -626, -626, -626, -626, -626, -626, -626, -626, -626,
+     -626, -626, -626, -626, -626, -626, -626, -626, -626, -626,
+     -626, -626, -626, -626, -626, -626, -626, -626, -626, -626,
+     -626, -626, -626, -626, -626, -626, -626, -626, -626, -626,
+     -626, -626, -626, -626, -626, -626, -626, -626, -626, -626,
+
+     -626, -626, -626, -626, -626, -626, -626, -626
+    },
+
+    {
+       67, -627, -627, -627, -627, -627, -627, -627, -627, -627,
+     -627, -627, -627, -627, -627, -627, -627, -627, -627, -627,
+     -627, -627, -627, -627, -627, -627, -627, -627, -627, -627,
+     -627, -627,  717, -627, -627, -627, -627, -627, -627, -627,
+     -627, -627, -627, -627, -627, -627, -627, -627,  718,  718,
+      718,  718,  718,  718,  718,  718,  718,  718, -627, -627,
+     -627, -627, -627, -627, -627,  717,  717,  717,  717,  717,
+      717,  717,  717,  717,  717,  717,  717,  717,  717,  717,
+      717,  717,  717,  717,  717,  717,  717,  717,  717,  717,
+
+      717, -627, -627, -627, -627, -627, -627, -627, -627, -627,
+     -627, -627, -627, -627, -627, -627, -627, -627, -627, -627,
+     -627, -627, -627, -627, -627, -627, -627, -627, -627, -627,
+     -627, -627, -627, -627, -627, -627, -627, -627
+    },
+
+    {
+       67, -628, -628, -628, -628, -628, -628, -628, -628, -628,
+     -628, -628, -628, -628, -628, -628, -628, -628, -628, -628,
+     -628, -628, -628, -628, -628, -628, -628, -628, -628, -628,
+     -628, -628,  719, -628, -628, -628, -628, -628, -628, -628,
+     -628, -628, -628, -628, -628, -628, -628, -628, -628, -628,
+     -628, -628, -628, -628, -628, -628, -628, -628, -628, -628,
+
+     -628, -628, -628, -628, -628, -628, -628, -628, -628, -628,
+     -628, -628, -628, -628, -628, -628, -628, -628, -628, -628,
+     -628, -628, -628, -628, -628, -628, -628, -628, -628, -628,
+     -628, -628, -628, -628, -628, -628, -628, -628, -628, -628,
+     -628, -628, -628, -628, -628, -628, -628, -628, -628, -628,
+     -628, -628, -628, -628, -628, -628, -628, -628, -628, -628,
+     -628, -628, -628, -628, -628, -628, -628, -628
+    },
+
+    {
+       67, -629, -629, -629, -629, -629, -629, -629, -629, -629,
+     -629, -629, -629, -629, -629, -629, -629, -629, -629, -629,
+     -629, -629, -629, -629, -629, -629, -629, -629, -629, -629,
+
+     -629, -629,  720, -629, -629, -629, -629, -629, -629, -629,
+     -629, -629, -629, -629, -629, -629, -629, -629, -629, -629,
+     -629, -629, -629, -629, -629, -629, -629, -629, -629, -629,
+     -629, -629, -629, -629, -629, -629, -629, -629, -629, -629,
+     -629, -629, -629, -629, -629, -629, -629, -629, -629, -629,
+     -629, -629, -629, -629, -629, -629, -629, -629, -629, -629,
+     -629, -629, -629, -629, -629, -629, -629, -629, -629, -629,
+     -629, -629, -629, -629, -629, -629, -629, -629, -629, -629,
+     -629, -629, -629, -629, -629, -629, -629, -629, -629, -629,
+     -629, -629, -629, -629, -629, -629, -629, -629
+
+    },
+
+    {
+       67, -630, -630, -630, -630, -630, -630, -630, -630, -630,
+     -630, -630, -630, -630, -630, -630, -630, -630, -630, -630,
+     -630, -630, -630, -630, -630, -630, -630, -630, -630, -630,
+     -630, -630,  721, -630, -630, -630, -630, -630, -630, -630,
+     -630, -630, -630, -630, -630, -630, -630, -630,  722,  722,
+      722,  722,  722,  722,  722,  722,  722,  722, -630, -630,
+     -630, -630, -630, -630, -630,  721,  721,  721,  721,  721,
+      721,  721,  721,  721,  721,  721,  721,  721,  721,  721,
+      721,  721,  721,  721,  721,  721,  721,  721,  721,  721,
+      721, -630, -630, -630, -630, -630, -630, -630, -630, -630,
+
+     -630, -630, -630, -630, -630, -630, -630, -630, -630, -630,
+     -630, -630, -630, -630, -630, -630, -630, -630, -630, -630,
+     -630, -630, -630, -630, -630, -630, -630, -630
+    },
+
+    {
+       67, -631, -631, -631, -631, -631, -631, -631, -631, -631,
+     -631, -631, -631, -631, -631, -631, -631, -631, -631, -631,
+     -631, -631, -631, -631, -631, -631, -631, -631, -631, -631,
+     -631, -631, -631, -631, -631, -631, -631, -631, -631, -631,
+     -631, -631, -631, -631, -631, -631, -631, -631, -631, -631,
+     -631, -631, -631, -631, -631, -631, -631, -631, -631, -631,
+     -631, -631, -631, -631, -631, -631, -631, -631, -631, -631,
+
+     -631, -631, -631, -631, -631, -631, -631, -631, -631, -631,
+     -631, -631, -631, -631, -631, -631, -631, -631, -631, -631,
+     -631, -631, -631, -631, -631, -631, -631, -631, -631, -631,
+     -631, -631, -631, -631, -631, -631, -631, -631, -631, -631,
+     -631, -631, -631, -631, -631, -631, -631, -631, -631, -631,
+     -631, -631, -631, -631, -631, -631, -631, -631
+    },
+
+    {
+       67, -632, -632, -632, -632, -632, -632, -632, -632, -632,
+     -632, -632, -632, -632, -632, -632, -632, -632, -632, -632,
+     -632, -632, -632, -632, -632, -632, -632, -632, -632, -632,
+     -632, -632, -632, -632, -632, -632, -632, -632, -632, -632,
+
+     -632, -632, -632, -632, -632, -632, -632, -632, -632, -632,
+     -632, -632, -632, -632, -632, -632, -632, -632, -632, -632,
+     -632, -632, -632, -632, -632, -632, -632, -632, -632, -632,
+     -632, -632, -632, -632, -632, -632, -632, -632, -632, -632,
+     -632, -632, -632, -632, -632, -632, -632, -632, -632, -632,
+     -632, -632, -632, -632, -632, -632, -632, -632, -632, -632,
+     -632, -632, -632, -632, -632, -632, -632, -632, -632, -632,
+     -632, -632, -632, -632, -632, -632, -632, -632, -632, -632,
+     -632, -632, -632, -632, -632, -632, -632, -632
+    },
+
+    {
+       67, -633, -633, -633, -633, -633, -633, -633, -633, -633,
+
+     -633, -633, -633, -633, -633, -633, -633, -633, -633, -633,
+     -633, -633, -633, -633, -633, -633, -633, -633, -633, -633,
+     -633, -633, -633, -633, -633, -633, -633, -633, -633, -633,
+     -633, -633, -633, -633, -633, -633, -633, -633, -633, -633,
+     -633, -633, -633, -633, -633, -633, -633, -633, -633, -633,
+     -633, -633, -633, -633, -633, -633, -633, -633, -633, -633,
+     -633, -633, -633, -633, -633, -633, -633, -633, -633, -633,
+     -633, -633, -633, -633, -633, -633, -633, -633, -633, -633,
+     -633, -633, -633, -633, -633, -633, -633, -633, -633, -633,
+     -633, -633, -633, -633, -633, -633, -633, -633, -633, -633,
+
+     -633, -633, -633, -633, -633, -633, -633, -633, -633, -633,
+     -633, -633, -633, -633, -633, -633, -633, -633
+    },
+
+    {
+       67, -634, -634, -634, -634, -634, -634, -634, -634, -634,
+     -634, -634, -634, -634, -634, -634, -634, -634, -634, -634,
+     -634, -634, -634, -634, -634, -634, -634, -634, -634, -634,
+     -634, -634, -634, -634, -634, -634, -634, -634, -634, -634,
+     -634, -634, -634, -634, -634, -634, -634, -634, -634, -634,
+     -634, -634, -634, -634, -634, -634, -634, -634, -634, -634,
+     -634, -634, -634, -634, -634, -634, -634, -634, -634, -634,
+     -634, -634, -634, -634, -634, -634, -634, -634, -634, -634,
+
+     -634, -634, -634, -634, -634, -634, -634, -634, -634, -634,
+     -634, -634, -634, -634, -634, -634, -634, -634, -634, -634,
+     -634, -634, -634, -634, -634, -634, -634, -634, -634, -634,
+     -634, -634, -634, -634, -634, -634, -634, -634, -634, -634,
+     -634, -634, -634, -634, -634, -634, -634, -634
+    },
+
+    {
+       67, -635, -635, -635, -635, -635, -635, -635, -635, -635,
+     -635, -635, -635, -635, -635, -635, -635, -635, -635, -635,
+     -635, -635, -635, -635, -635, -635, -635, -635, -635, -635,
+     -635, -635, -635, -635, -635, -635, -635, -635, -635, -635,
+     -635, -635, -635, -635, -635, -635, -635, -635, -635, -635,
+
+     -635, -635, -635, -635, -635, -635, -635, -635, -635, -635,
+     -635, -635, -635, -635, -635, -635, -635, -635, -635, -635,
+     -635, -635, -635, -635, -635, -635, -635, -635, -635, -635,
+     -635, -635, -635, -635, -635, -635, -635, -635, -635, -635,
+     -635, -635, -635, -635, -635, -635, -635, -635, -635, -635,
+     -635, -635, -635, -635, -635, -635, -635, -635, -635, -635,
+     -635, -635, -635, -635, -635, -635, -635, -635, -635, -635,
+     -635, -635, -635, -635, -635, -635, -635, -635
+    },
+
+    {
+       67, -636, -636, -636, -636, -636, -636, -636, -636, -636,
+     -636, -636, -636, -636, -636, -636, -636, -636, -636, -636,
+
+     -636, -636, -636, -636, -636, -636, -636, -636, -636, -636,
+     -636, -636, -636, -636, -636, -636, -636, -636, -636, -636,
+     -636, -636, -636, -636, -636, -636, -636, -636, -636, -636,
+     -636, -636, -636, -636, -636, -636, -636, -636, -636, -636,
+     -636, -636, -636, -636, -636, -636, -636, -636, -636, -636,
+     -636, -636, -636, -636, -636, -636, -636, -636, -636, -636,
+     -636, -636, -636, -636, -636, -636, -636, -636, -636, -636,
+     -636, -636, -636, -636, -636, -636, -636, -636, -636, -636,
+     -636, -636, -636, -636, -636, -636, -636, -636, -636, -636,
+     -636, -636, -636, -636, -636, -636, -636, -636, -636, -636,
+
+     -636, -636, -636, -636, -636, -636, -636, -636
+    },
+
+    {
+       67, -637, -637, -637, -637, -637, -637, -637, -637, -637,
+     -637, -637, -637, -637, -637, -637, -637, -637, -637, -637,
+     -637, -637, -637, -637, -637, -637, -637, -637, -637, -637,
+     -637, -637, -637, -637, -637, -637, -637, -637, -637, -637,
+     -637, -637, -637, -637, -637, -637, -637, -637, -637, -637,
+     -637, -637, -637, -637, -637, -637, -637, -637, -637, -637,
+     -637, -637, -637, -637, -637, -637, -637, -637, -637, -637,
+     -637, -637, -637, -637, -637, -637, -637, -637, -637, -637,
+     -637, -637, -637, -637, -637, -637,  723, -637, -637, -637,
+
+     -637, -637, -637, -637, -637, -637, -637, -637, -637, -637,
+     -637, -637, -637, -637, -637, -637, -637, -637, -637, -637,
+     -637, -637, -637, -637, -637, -637, -637, -637, -637, -637,
+     -637, -637, -637, -637, -637, -637, -637, -637
+    },
+
+    {
+       67, -638, -638, -638, -638, -638, -638, -638, -638, -638,
+     -638, -638, -638, -638, -638, -638, -638, -638, -638, -638,
+     -638, -638, -638, -638, -638, -638, -638, -638, -638, -638,
+     -638, -638, -638, -638, -638, -638, -638, -638, -638, -638,
+     -638, -638, -638, -638, -638, -638, -638, -638, -638, -638,
+     -638, -638, -638, -638, -638, -638, -638, -638, -638, -638,
+
+     -638, -638, -638, -638, -638, -638,  724, -638, -638, -638,
+     -638, -638, -638, -638, -638, -638, -638, -638, -638, -638,
+     -638, -638, -638, -638, -638, -638, -638, -638, -638, -638,
+     -638, -638, -638, -638, -638, -638, -638, -638, -638, -638,
+     -638, -638, -638, -638, -638, -638, -638, -638, -638, -638,
+     -638, -638, -638, -638, -638, -638, -638, -638, -638, -638,
+     -638, -638, -638, -638, -638, -638, -638, -638
+    },
+
+    {
+       67, -639, -639, -639, -639, -639, -639, -639, -639, -639,
+     -639, -639, -639, -639, -639, -639, -639, -639, -639, -639,
+     -639, -639, -639, -639, -639, -639, -639, -639, -639, -639,
+
+     -639, -639,  725, -639, -639, -639, -639, -639, -639, -639,
+     -639, -639, -639, -639, -639, -639, -639, -639, -639, -639,
+     -639, -639, -639, -639, -639, -639, -639, -639, -639, -639,
+     -639, -639, -639, -639, -639, -639, -639, -639, -639, -639,
+     -639, -639, -639, -639, -639, -639, -639, -639, -639, -639,
+     -639, -639, -639, -639, -639, -639, -639, -639, -639, -639,
+     -639, -639, -639, -639, -639, -639, -639, -639, -639, -639,
+     -639, -639, -639, -639, -639, -639, -639, -639, -639, -639,
+     -639, -639, -639, -639, -639, -639, -639, -639, -639, -639,
+     -639, -639, -639, -639, -639, -639, -639, -639
+
+    },
+
+    {
+       67, -640, -640, -640, -640, -640, -640, -640, -640, -640,
+     -640, -640, -640, -640, -640, -640, -640, -640, -640, -640,
+     -640, -640, -640, -640, -640, -640, -640, -640, -640, -640,
+     -640, -640,  726, -640, -640, -640, -640, -640, -640, -640,
+     -640, -640, -640, -640, -640, -640, -640, -640,  727,  727,
+      727,  727,  727,  727,  727,  727,  727,  727, -640, -640,
+     -640, -640, -640, -640, -640, -640, -640, -640, -640, -640,
+     -640, -640, -640, -640, -640, -640, -640, -640, -640, -640,
+     -640, -640, -640, -640, -640, -640, -640, -640, -640, -640,
+     -640, -640, -640, -640, -640, -640, -640, -640, -640, -640,
+
+     -640, -640, -640, -640, -640, -640, -640, -640, -640, -640,
+     -640, -640, -640, -640, -640, -640, -640, -640, -640, -640,
+     -640, -640, -640, -640, -640, -640, -640, -640
+    },
+
+    {
+       67, -641, -641, -641, -641, -641, -641, -641, -641, -641,
+     -641, -641, -641, -641, -641, -641, -641, -641, -641, -641,
+     -641, -641, -641, -641, -641, -641, -641, -641, -641, -641,
+     -641, -641,  728, -641, -641, -641, -641, -641, -641, -641,
+     -641, -641, -641, -641, -641, -641, -641, -641, -641, -641,
+     -641, -641, -641, -641, -641, -641, -641, -641, -641, -641,
+     -641, -641, -641, -641, -641, -641, -641, -641, -641, -641,
+
+     -641, -641, -641, -641, -641, -641, -641, -641, -641, -641,
+     -641, -641, -641, -641, -641, -641, -641, -641, -641, -641,
+     -641, -641, -641, -641, -641, -641, -641, -641, -641, -641,
+     -641, -641, -641, -641, -641, -641, -641, -641, -641, -641,
+     -641, -641, -641, -641, -641, -641, -641, -641, -641, -641,
+     -641, -641, -641, -641, -641, -641, -641, -641
+    },
+
+    {
+       67, -642, -642, -642, -642, -642, -642, -642, -642, -642,
+     -642, -642, -642, -642, -642, -642, -642, -642, -642, -642,
+     -642, -642, -642, -642, -642, -642, -642, -642, -642, -642,
+     -642, -642,  729, -642, -642, -642, -642, -642, -642, -642,
+
+     -642, -642, -642, -642, -642, -642, -642, -642, -642, -642,
+     -642, -642, -642, -642, -642, -642, -642, -642, -642, -642,
+     -642, -642, -642, -642, -642, -642, -642, -642, -642, -642,
+     -642, -642, -642, -642, -642, -642, -642, -642, -642, -642,
+     -642, -642, -642, -642, -642, -642, -642, -642, -642, -642,
+     -642, -642, -642, -642, -642, -642, -642, -642, -642, -642,
+     -642, -642, -642, -642, -642, -642, -642, -642, -642, -642,
+     -642, -642, -642, -642, -642, -642, -642, -642, -642, -642,
+     -642, -642, -642, -642, -642, -642, -642, -642
+    },
+
+    {
+       67, -643, -643, -643, -643, -643, -643, -643, -643, -643,
+
+     -643, -643, -643, -643, -643, -643, -643, -643, -643, -643,
+     -643, -643, -643, -643, -643, -643, -643, -643, -643, -643,
+     -643, -643, -643, -643, -643, -643, -643, -643, -643, -643,
+     -643, -643, -643, -643, -643, -643, -643, -643, -643, -643,
+     -643, -643, -643, -643, -643, -643, -643, -643, -643, -643,
+     -643, -643, -643, -643, -643, -643, -643, -643, -643, -643,
+     -643, -643, -643, -643, -643, -643, -643, -643, -643, -643,
+     -643, -643, -643, -643, -643, -643, -643, -643,  730, -643,
+     -643, -643, -643, -643, -643, -643, -643, -643, -643, -643,
+     -643, -643, -643, -643, -643, -643, -643, -643, -643, -643,
+
+     -643, -643, -643, -643, -643, -643, -643, -643, -643, -643,
+     -643, -643, -643, -643, -643, -643, -643, -643
+    },
+
+    {
+       67, -644, -644, -644, -644, -644, -644, -644, -644, -644,
+     -644, -644, -644, -644, -644, -644, -644, -644, -644, -644,
+     -644, -644, -644, -644, -644, -644, -644, -644, -644, -644,
+     -644, -644, -644, -644, -644, -644, -644, -644, -644, -644,
+     -644, -644, -644, -644, -644, -644, -644, -644, -644, -644,
+     -644, -644, -644, -644, -644, -644, -644, -644, -644, -644,
+     -644, -644, -644, -644, -644, -644, -644, -644, -644,  731,
+     -644, -644, -644, -644, -644, -644, -644, -644, -644, -644,
+
+     -644, -644, -644, -644, -644, -644, -644, -644, -644, -644,
+     -644, -644, -644, -644, -644, -644, -644, -644, -644, -644,
+     -644, -644, -644, -644, -644, -644, -644, -644, -644, -644,
+     -644, -644, -644, -644, -644, -644, -644, -644, -644, -644,
+     -644, -644, -644, -644, -644, -644, -644, -644
+    },
+
+    {
+       67, -645, -645, -645, -645, -645, -645, -645, -645, -645,
+     -645, -645, -645, -645, -645, -645, -645, -645, -645, -645,
+     -645, -645, -645, -645, -645, -645, -645, -645, -645, -645,
+     -645, -645, -645, -645, -645, -645, -645, -645, -645, -645,
+     -645, -645, -645, -645, -645, -645, -645, -645, -645, -645,
+
+     -645, -645, -645, -645, -645, -645, -645, -645, -645, -645,
+     -645, -645, -645, -645, -645, -645, -645, -645, -645,  732,
+     -645, -645, -645, -645, -645, -645, -645, -645, -645, -645,
+     -645, -645, -645, -645, -645, -645, -645, -645, -645, -645,
+     -645, -645, -645, -645, -645, -645, -645, -645, -645, -645,
+     -645, -645, -645, -645, -645, -645, -645, -645, -645, -645,
+     -645, -645, -645, -645, -645, -645, -645, -645, -645, -645,
+     -645, -645, -645, -645, -645, -645, -645, -645
+    },
+
+    {
+       67, -646, -646, -646, -646, -646, -646, -646, -646, -646,
+     -646, -646, -646, -646, -646, -646, -646, -646, -646, -646,
+
+     -646, -646, -646, -646, -646, -646, -646, -646, -646, -646,
+     -646, -646, -646, -646, -646, -646, -646, -646, -646, -646,
+     -646, -646, -646, -646, -646, -646, -646, -646, -646, -646,
+     -646, -646, -646, -646, -646, -646, -646, -646, -646, -646,
+     -646, -646, -646, -646, -646, -646, -646, -646, -646, -646,
+     -646,  733, -646, -646, -646, -646, -646, -646, -646, -646,
+     -646, -646, -646, -646, -646, -646, -646, -646, -646, -646,
+     -646, -646, -646, -646, -646, -646, -646, -646, -646, -646,
+     -646, -646, -646, -646, -646, -646, -646, -646, -646, -646,
+     -646, -646, -646, -646, -646, -646, -646, -646, -646, -646,
+
+     -646, -646, -646, -646, -646, -646, -646, -646
+    },
+
+    {
+       67, -647, -647, -647, -647, -647, -647, -647, -647, -647,
+     -647, -647, -647, -647, -647, -647, -647, -647, -647, -647,
+     -647, -647, -647, -647, -647, -647, -647, -647, -647, -647,
+     -647, -647, -647, -647, -647, -647, -647, -647, -647, -647,
+     -647, -647, -647, -647, -647, -647, -647, -647, -647, -647,
+     -647, -647, -647, -647, -647, -647, -647, -647, -647, -647,
+     -647, -647, -647, -647, -647, -647, -647, -647, -647, -647,
+     -647, -647, -647, -647, -647, -647, -647, -647, -647, -647,
+     -647, -647, -647,  734, -647, -647, -647, -647, -647, -647,
+
+     -647, -647, -647, -647, -647, -647, -647, -647, -647, -647,
+     -647, -647, -647, -647, -647, -647, -647, -647, -647, -647,
+     -647, -647, -647, -647, -647, -647, -647, -647, -647, -647,
+     -647, -647, -647, -647, -647, -647, -647, -647
+    },
+
+    {
+       67, -648, -648, -648, -648, -648, -648, -648, -648, -648,
+     -648, -648, -648, -648, -648, -648, -648, -648, -648, -648,
+     -648, -648, -648, -648, -648, -648, -648, -648, -648, -648,
+     -648, -648, -648, -648, -648, -648, -648, -648, -648, -648,
+     -648, -648, -648, -648, -648,  735, -648, -648, -648, -648,
+     -648, -648, -648, -648, -648, -648, -648, -648, -648, -648,
+
+     -648, -648, -648, -648, -648, -648, -648, -648, -648, -648,
+     -648, -648, -648, -648, -648, -648, -648, -648, -648, -648,
+     -648, -648, -648, -648, -648, -648, -648, -648, -648, -648,
+     -648, -648, -648, -648, -648, -648, -648, -648, -648, -648,
+     -648, -648, -648, -648, -648, -648, -648, -648, -648, -648,
+     -648, -648, -648, -648, -648, -648, -648, -648, -648, -648,
+     -648, -648, -648, -648, -648, -648, -648, -648
+    },
+
+    {
+       67, -649, -649, -649, -649, -649, -649, -649, -649, -649,
+     -649, -649, -649, -649, -649, -649, -649, -649, -649, -649,
+     -649, -649, -649, -649, -649, -649, -649, -649, -649, -649,
+
+     -649, -649, -649, -649, -649, -649, -649, -649, -649, -649,
+     -649, -649, -649, -649, -649, -649, -649, -649, -649, -649,
+     -649, -649, -649, -649, -649, -649, -649, -649, -649, -649,
+     -649, -649, -649, -649, -649, -649, -649, -649, -649, -649,
+     -649, -649, -649, -649, -649, -649, -649, -649, -649, -649,
+     -649, -649, -649, -649, -649, -649, -649, -649, -649,  736,
+     -649, -649, -649, -649, -649, -649, -649, -649, -649, -649,
+     -649, -649, -649, -649, -649, -649, -649, -649, -649, -649,
+     -649, -649, -649, -649, -649, -649, -649, -649, -649, -649,
+     -649, -649, -649, -649, -649, -649, -649, -649
+
+    },
+
+    {
+       67, -650, -650, -650, -650, -650, -650, -650, -650, -650,
+     -650, -650, -650, -650, -650, -650, -650, -650, -650, -650,
+     -650, -650, -650, -650, -650, -650, -650, -650, -650, -650,
+     -650, -650, -650, -650, -650, -650, -650, -650, -650, -650,
+     -650, -650, -650, -650, -650, -650, -650, -650, -650, -650,
+     -650, -650, -650, -650, -650, -650, -650, -650, -650, -650,
+     -650, -650, -650, -650, -650, -650, -650, -650, -650, -650,
+     -650, -650, -650, -650, -650, -650, -650, -650, -650, -650,
+     -650, -650, -650,  737, -650, -650, -650, -650, -650, -650,
+     -650, -650, -650, -650, -650, -650, -650, -650, -650, -650,
+
+     -650, -650, -650, -650, -650, -650, -650, -650, -650, -650,
+     -650, -650, -650, -650, -650, -650, -650, -650, -650, -650,
+     -650, -650, -650, -650, -650, -650, -650, -650
+    },
+
+    {
+       67, -651, -651, -651, -651, -651, -651, -651, -651, -651,
+     -651, -651, -651, -651, -651, -651, -651, -651, -651, -651,
+     -651, -651, -651, -651, -651, -651, -651, -651, -651, -651,
+     -651, -651, -651, -651, -651, -651, -651, -651, -651, -651,
+     -651, -651, -651, -651, -651, -651, -651, -651, -651, -651,
+     -651, -651, -651, -651, -651, -651, -651, -651, -651, -651,
+     -651, -651, -651, -651, -651, -651, -651, -651, -651,  738,
+
+     -651, -651, -651, -651, -651, -651, -651, -651, -651, -651,
+     -651,  739, -651, -651, -651, -651, -651, -651, -651, -651,
+     -651, -651, -651, -651, -651, -651, -651, -651, -651, -651,
+     -651, -651, -651, -651, -651, -651, -651, -651, -651, -651,
+     -651, -651, -651, -651, -651, -651, -651, -651, -651, -651,
+     -651, -651, -651, -651, -651, -651, -651, -651
+    },
+
+    {
+       67, -652, -652, -652, -652, -652, -652, -652, -652, -652,
+     -652, -652, -652, -652, -652, -652, -652, -652, -652, -652,
+     -652, -652, -652, -652, -652, -652, -652, -652, -652, -652,
+     -652, -652, -652, -652, -652, -652, -652, -652, -652, -652,
+
+     -652, -652, -652, -652, -652, -652, -652, -652, -652, -652,
+     -652, -652, -652, -652, -652, -652, -652, -652, -652, -652,
+     -652, -652, -652, -652, -652, -652, -652, -652, -652, -652,
+     -652, -652, -652, -652, -652, -652, -652, -652, -652, -652,
+     -652, -652, -652, -652, -652, -652,  740, -652, -652, -652,
+     -652, -652, -652, -652, -652, -652, -652, -652, -652, -652,
+     -652, -652, -652, -652, -652, -652, -652, -652, -652, -652,
+     -652, -652, -652, -652, -652, -652, -652, -652, -652, -652,
+     -652, -652, -652, -652, -652, -652, -652, -652
+    },
+
+    {
+       67, -653, -653, -653, -653, -653, -653, -653, -653, -653,
+
+     -653, -653, -653, -653, -653, -653, -653, -653, -653, -653,
+     -653, -653, -653, -653, -653, -653, -653, -653, -653, -653,
+     -653, -653, -653, -653, -653, -653, -653, -653, -653, -653,
+     -653, -653, -653, -653, -653, -653, -653, -653, -653, -653,
+     -653, -653, -653, -653, -653, -653, -653, -653, -653, -653,
+     -653, -653, -653, -653, -653, -653, -653, -653, -653, -653,
+     -653, -653, -653, -653, -653, -653, -653, -653, -653, -653,
+     -653, -653, -653,  741, -653, -653, -653, -653, -653, -653,
+     -653, -653, -653, -653, -653, -653, -653, -653, -653, -653,
+     -653, -653, -653, -653, -653, -653, -653, -653, -653, -653,
+
+     -653, -653, -653, -653, -653, -653, -653, -653, -653, -653,
+     -653, -653, -653, -653, -653, -653, -653, -653
+    },
+
+    {
+       67, -654, -654, -654, -654, -654, -654, -654, -654, -654,
+     -654, -654, -654, -654, -654, -654, -654, -654, -654, -654,
+     -654, -654, -654, -654, -654, -654, -654, -654, -654, -654,
+     -654, -654, -654, -654, -654, -654, -654, -654, -654, -654,
+     -654, -654, -654, -654, -654, -654, -654, -654, -654, -654,
+     -654, -654, -654, -654, -654, -654, -654, -654, -654, -654,
+     -654, -654, -654, -654, -654, -654, -654, -654, -654, -654,
+     -654, -654, -654, -654, -654, -654, -654, -654, -654, -654,
+
+     -654, -654, -654,  742, -654, -654, -654, -654, -654, -654,
+     -654, -654, -654, -654, -654, -654, -654, -654, -654, -654,
+     -654, -654, -654, -654, -654, -654, -654, -654, -654, -654,
+     -654, -654, -654, -654, -654, -654, -654, -654, -654, -654,
+     -654, -654, -654, -654, -654, -654, -654, -654
+    },
+
+    {
+       67, -655, -655, -655, -655, -655, -655, -655, -655, -655,
+     -655, -655, -655, -655, -655, -655, -655, -655, -655, -655,
+     -655, -655, -655, -655, -655, -655, -655, -655, -655, -655,
+     -655, -655, -655, -655, -655, -655, -655, -655, -655, -655,
+     -655, -655, -655, -655, -655, -655, -655, -655, -655, -655,
+
+     -655, -655, -655, -655, -655, -655, -655, -655, -655, -655,
+     -655, -655, -655, -655, -655, -655, -655,  743, -655, -655,
+     -655, -655, -655, -655, -655, -655, -655, -655, -655, -655,
+     -655, -655, -655, -655, -655, -655, -655, -655, -655, -655,
+     -655, -655, -655, -655, -655, -655, -655, -655, -655, -655,
+     -655, -655, -655, -655, -655, -655, -655, -655, -655, -655,
+     -655, -655, -655, -655, -655, -655, -655, -655, -655, -655,
+     -655, -655, -655, -655, -655, -655, -655, -655
+    },
+
+    {
+       67, -656, -656, -656, -656, -656, -656, -656, -656, -656,
+     -656, -656, -656, -656, -656, -656, -656, -656, -656, -656,
+
+     -656, -656, -656, -656, -656, -656, -656, -656, -656, -656,
+     -656, -656, -656, -656, -656, -656, -656, -656, -656, -656,
+     -656, -656, -656, -656, -656, -656, -656, -656, -656, -656,
+     -656, -656, -656, -656, -656, -656, -656, -656, -656, -656,
+     -656, -656, -656, -656, -656, -656, -656, -656, -656, -656,
+     -656, -656, -656, -656, -656, -656, -656, -656, -656, -656,
+     -656, -656, -656,  744, -656, -656, -656, -656, -656, -656,
+     -656, -656, -656, -656, -656, -656, -656, -656, -656, -656,
+     -656, -656, -656, -656, -656, -656, -656, -656, -656, -656,
+     -656, -656, -656, -656, -656, -656, -656, -656, -656, -656,
+
+     -656, -656, -656, -656, -656, -656, -656, -656
+    },
+
+    {
+       67, -657, -657, -657, -657, -657, -657, -657, -657, -657,
+     -657, -657, -657, -657, -657, -657, -657, -657, -657, -657,
+     -657, -657, -657, -657, -657, -657, -657, -657, -657, -657,
+     -657, -657, -657, -657, -657, -657, -657, -657, -657, -657,
+     -657, -657, -657, -657, -657, -657, -657, -657, -657, -657,
+     -657, -657, -657, -657, -657, -657, -657, -657, -657, -657,
+     -657, -657, -657, -657, -657, -657, -657, -657, -657, -657,
+     -657, -657, -657, -657, -657, -657,  745, -657, -657, -657,
+     -657, -657, -657, -657, -657, -657, -657, -657, -657, -657,
+
+     -657, -657, -657, -657, -657, -657, -657, -657, -657, -657,
+     -657, -657, -657, -657, -657, -657, -657, -657, -657, -657,
+     -657, -657, -657, -657, -657, -657, -657, -657, -657, -657,
+     -657, -657, -657, -657, -657, -657, -657, -657
+    },
+
+    {
+       67, -658, -658, -658, -658, -658, -658, -658, -658, -658,
+     -658, -658, -658, -658, -658, -658, -658, -658, -658, -658,
+     -658, -658, -658, -658, -658, -658, -658, -658, -658, -658,
+     -658, -658, -658, -658, -658, -658, -658, -658, -658, -658,
+     -658, -658, -658, -658, -658, -658, -658, -658, -658, -658,
+     -658, -658, -658, -658, -658, -658, -658, -658, -658, -658,
+
+     -658, -658, -658, -658, -658, -658, -658, -658, -658, -658,
+     -658, -658, -658, -658, -658, -658, -658, -658, -658, -658,
+     -658, -658, -658,  746, -658, -658, -658, -658, -658, -658,
+     -658, -658, -658, -658, -658, -658, -658, -658, -658, -658,
+     -658, -658, -658, -658, -658, -658, -658, -658, -658, -658,
+     -658, -658, -658, -658, -658, -658, -658, -658, -658, -658,
+     -658, -658, -658, -658, -658, -658, -658, -658
+    },
+
+    {
+       67, -659, -659, -659, -659, -659, -659, -659, -659, -659,
+     -659, -659, -659, -659, -659, -659, -659, -659, -659, -659,
+     -659, -659, -659, -659, -659, -659, -659, -659, -659, -659,
+
+     -659, -659,  747, -659, -659, -659, -659, -659, -659, -659,
+     -659, -659, -659, -659, -659, -659, -659, -659, -659, -659,
+     -659, -659, -659, -659, -659, -659, -659, -659, -659, -659,
+     -659, -659, -659, -659, -659,  747,  747,  747,  747,  747,
+      747,  747,  747,  747,  747,  747,  747,  747,  747,  747,
+      747,  747,  747,  747,  747,  747,  747,  747,  747,  747,
+      747, -659, -659, -659, -659, -659, -659, -659, -659, -659,
+     -659, -659, -659, -659, -659, -659, -659, -659, -659, -659,
+     -659, -659, -659, -659, -659, -659, -659, -659, -659, -659,
+     -659, -659, -659, -659, -659, -659, -659, -659
+
+    },
+
+    {
+       67, -660, -660, -660, -660, -660, -660, -660, -660, -660,
+     -660, -660, -660, -660, -660, -660, -660, -660, -660, -660,
+     -660, -660, -660, -660, -660, -660, -660, -660, -660, -660,
+     -660, -660,  748, -660, -660, -660, -660, -660, -660, -660,
+     -660, -660, -660, -660, -660, -660, -660, -660, -660, -660,
+     -660, -660, -660, -660, -660, -660, -660, -660, -660, -660,
+     -660, -660, -660, -660, -660, -660, -660, -660, -660, -660,
+     -660, -660, -660, -660, -660, -660, -660, -660, -660, -660,
+     -660, -660, -660, -660, -660, -660, -660, -660, -660, -660,
+     -660, -660, -660, -660, -660, -660, -660, -660, -660, -660,
+
+     -660, -660, -660, -660, -660, -660, -660, -660, -660, -660,
+     -660, -660, -660, -660, -660, -660, -660, -660, -660, -660,
+     -660, -660, -660, -660, -660, -660, -660, -660
+    },
+
+    {
+       67, -661, -661, -661, -661, -661, -661, -661, -661, -661,
+     -661, -661, -661, -661, -661, -661, -661, -661, -661, -661,
+     -661, -661, -661, -661, -661, -661, -661, -661, -661, -661,
+     -661, -661,  749, -661, -661, -661, -661, -661, -661, -661,
+     -661, -661, -661, -661, -661, -661, -661, -661,  750,  750,
+      750,  750,  750,  750,  750,  750,  750,  750, -661, -661,
+     -661, -661, -661, -661, -661,  749,  749,  749,  749,  749,
+
+      749,  749,  749,  749,  749,  749,  749,  749,  749,  749,
+      749,  749,  749,  749,  749,  749,  749,  749,  749,  749,
+      749, -661, -661, -661, -661, -661, -661, -661, -661, -661,
+     -661, -661, -661, -661, -661, -661, -661, -661, -661, -661,
+     -661, -661, -661, -661, -661, -661, -661, -661, -661, -661,
+     -661, -661, -661, -661, -661, -661, -661, -661
+    },
+
+    {
+       67, -662, -662, -662, -662, -662, -662, -662, -662, -662,
+     -662, -662, -662, -662, -662, -662, -662, -662, -662, -662,
+     -662, -662, -662, -662, -662, -662, -662, -662, -662, -662,
+     -662, -662, -662, -662, -662, -662, -662, -662, -662, -662,
+
+     -662, -662, -662, -662, -662, -662, -662, -662, -662, -662,
+     -662, -662, -662, -662, -662, -662, -662, -662, -662, -662,
+     -662, -662, -662, -662, -662, -662, -662, -662, -662,  751,
+     -662, -662, -662, -662, -662, -662, -662, -662, -662, -662,
+     -662, -662, -662, -662, -662, -662, -662, -662, -662, -662,
+     -662, -662, -662, -662, -662, -662, -662, -662, -662, -662,
+     -662, -662, -662, -662, -662, -662, -662, -662, -662, -662,
+     -662, -662, -662, -662, -662, -662, -662, -662, -662, -662,
+     -662, -662, -662, -662, -662, -662, -662, -662
+    },
+
+    {
+       67, -663, -663, -663, -663, -663, -663, -663, -663, -663,
+
+     -663, -663, -663, -663, -663, -663, -663, -663, -663, -663,
+     -663, -663, -663, -663, -663, -663, -663, -663, -663, -663,
+     -663, -663,  752, -663, -663, -663, -663, -663, -663, -663,
+     -663, -663, -663, -663, -663, -663, -663, -663, -663, -663,
+     -663, -663, -663, -663, -663, -663, -663, -663, -663, -663,
+     -663, -663, -663, -663, -663, -663, -663, -663, -663, -663,
+     -663, -663, -663, -663, -663, -663, -663, -663, -663, -663,
+     -663, -663, -663, -663, -663, -663, -663, -663, -663, -663,
+     -663, -663, -663, -663, -663, -663, -663, -663, -663, -663,
+     -663, -663, -663, -663, -663, -663, -663, -663, -663, -663,
+
+     -663, -663, -663, -663, -663, -663, -663, -663, -663, -663,
+     -663, -663, -663, -663, -663, -663, -663, -663
+    },
+
+    {
+       67, -664, -664, -664, -664, -664, -664, -664, -664, -664,
+     -664, -664, -664, -664, -664, -664, -664, -664, -664, -664,
+     -664, -664, -664, -664, -664, -664, -664, -664, -664, -664,
+     -664, -664,  753, -664, -664, -664, -664, -664, -664, -664,
+     -664, -664, -664, -664, -664, -664, -664, -664,  754,  754,
+      754,  754,  754,  754,  754,  754,  754,  754, -664, -664,
+     -664, -664, -664, -664, -664,  753,  753,  753,  753,  753,
+      753,  753,  753,  753,  753,  753,  753,  753,  753,  753,
+
+      753,  753,  753,  753,  753,  753,  753,  753,  753,  753,
+      753, -664, -664, -664, -664, -664, -664, -664, -664, -664,
+     -664, -664, -664, -664, -664, -664, -664, -664, -664, -664,
+     -664, -664, -664, -664, -664, -664, -664, -664, -664, -664,
+     -664, -664, -664, -664, -664, -664, -664, -664
+    },
+
+    {
+       67, -665, -665, -665, -665, -665, -665, -665, -665, -665,
+     -665, -665, -665, -665, -665, -665, -665, -665, -665, -665,
+     -665, -665, -665, -665, -665, -665, -665, -665, -665, -665,
+     -665, -665, -665, -665, -665, -665, -665, -665, -665, -665,
+     -665, -665, -665, -665, -665, -665, -665, -665, -665, -665,
+
+     -665, -665, -665, -665, -665, -665, -665, -665, -665, -665,
+     -665, -665, -665, -665, -665, -665, -665, -665, -665, -665,
+     -665, -665, -665, -665, -665, -665, -665, -665, -665, -665,
+     -665, -665, -665,  755, -665, -665, -665, -665, -665, -665,
+     -665, -665, -665, -665, -665, -665, -665, -665, -665, -665,
+     -665, -665, -665, -665, -665, -665, -665, -665, -665, -665,
+     -665, -665, -665, -665, -665, -665, -665, -665, -665, -665,
+     -665, -665, -665, -665, -665, -665, -665, -665
+    },
+
+    {
+       67, -666, -666, -666, -666, -666, -666, -666, -666, -666,
+     -666, -666, -666, -666, -666, -666, -666, -666, -666, -666,
+
+     -666, -666, -666, -666, -666, -666, -666, -666, -666, -666,
+     -666, -666, -666, -666, -666, -666, -666, -666, -666, -666,
+     -666, -666, -666, -666, -666, -666, -666, -666, -666, -666,
+     -666, -666, -666, -666, -666, -666, -666, -666, -666, -666,
+     -666, -666, -666, -666, -666, -666, -666, -666, -666,  756,
+     -666, -666, -666, -666, -666, -666, -666, -666, -666, -666,
+     -666, -666, -666, -666, -666, -666, -666, -666, -666, -666,
+     -666, -666, -666, -666, -666, -666, -666, -666, -666, -666,
+     -666, -666, -666, -666, -666, -666, -666, -666, -666, -666,
+     -666, -666, -666, -666, -666, -666, -666, -666, -666, -666,
+
+     -666, -666, -666, -666, -666, -666, -666, -666
+    },
+
+    {
+       67, -667, -667, -667, -667, -667, -667, -667, -667, -667,
+     -667, -667, -667, -667, -667, -667, -667, -667, -667, -667,
+     -667, -667, -667, -667, -667, -667, -667, -667, -667, -667,
+     -667, -667,  757, -667, -667, -667, -667, -667, -667, -667,
+     -667, -667, -667, -667, -667, -667, -667, -667, -667, -667,
+     -667, -667, -667, -667, -667, -667, -667, -667, -667, -667,
+     -667, -667, -667, -667, -667, -667, -667, -667, -667, -667,
+     -667, -667, -667, -667, -667, -667, -667, -667, -667, -667,
+     -667, -667, -667, -667, -667, -667, -667, -667, -667, -667,
+
+     -667, -667, -667, -667, -667, -667, -667, -667, -667, -667,
+     -667, -667, -667, -667, -667, -667, -667, -667, -667, -667,
+     -667, -667, -667, -667, -667, -667, -667, -667, -667, -667,
+     -667, -667, -667, -667, -667, -667, -667, -667
+    },
+
+    {
+       67, -668, -668, -668, -668, -668, -668, -668, -668, -668,
+     -668, -668, -668, -668, -668, -668, -668, -668, -668, -668,
+     -668, -668, -668, -668, -668, -668, -668, -668, -668, -668,
+     -668, -668,  758, -668, -668, -668, -668, -668, -668, -668,
+     -668, -668, -668, -668, -668, -668, -668, -668,  759,  759,
+      759,  759,  759,  759,  759,  759,  759,  759, -668, -668,
+
+     -668, -668, -668, -668, -668,  758,  758,  758,  758,  758,
+      758,  758,  758,  758,  758,  758,  758,  758,  758,  758,
+      758,  758,  758,  758,  758,  758,  758,  758,  758,  758,
+      758, -668, -668, -668, -668, -668, -668, -668, -668, -668,
+     -668, -668, -668, -668, -668, -668, -668, -668, -668, -668,
+     -668, -668, -668, -668, -668, -668, -668, -668, -668, -668,
+     -668, -668, -668, -668, -668, -668, -668, -668
+    },
+
+    {
+       67, -669, -669, -669, -669, -669, -669, -669, -669, -669,
+     -669, -669, -669, -669, -669, -669, -669, -669, -669, -669,
+     -669, -669, -669, -669, -669, -669, -669, -669, -669, -669,
+
+     -669, -669,  760, -669, -669, -669, -669, -669, -669, -669,
+     -669, -669, -669, -669, -669, -669, -669, -669, -669, -669,
+     -669, -669, -669, -669, -669, -669, -669, -669, -669, -669,
+     -669, -669, -669, -669, -669, -669, -669, -669, -669, -669,
+     -669, -669, -669, -669, -669, -669, -669, -669, -669, -669,
+     -669, -669, -669, -669, -669, -669, -669, -669, -669, -669,
+     -669, -669, -669, -669, -669, -669, -669, -669, -669, -669,
+     -669, -669, -669, -669, -669, -669, -669, -669, -669, -669,
+     -669, -669, -669, -669, -669, -669, -669, -669, -669, -669,
+     -669, -669, -669, -669, -669, -669, -669, -669
+
+    },
+
+    {
+       67, -670, -670, -670, -670, -670, -670, -670, -670, -670,
+     -670, -670, -670, -670, -670, -670, -670, -670, -670, -670,
+     -670, -670, -670, -670, -670, -670, -670, -670, -670, -670,
+     -670, -670,  761, -670, -670, -670, -670, -670, -670, -670,
+     -670, -670, -670, -670, -670, -670, -670, -670,  762,  762,
+      762,  762,  762,  762,  762,  762,  762,  762, -670, -670,
+     -670, -670, -670, -670, -670,  761,  761,  761,  761,  761,
+      761,  761,  761,  761,  761,  761,  761,  761,  761,  761,
+      761,  761,  761,  761,  761,  761,  761,  761,  761,  761,
+      761, -670, -670, -670, -670, -670, -670, -670, -670, -670,
+
+     -670, -670, -670, -670, -670, -670, -670, -670, -670, -670,
+     -670, -670, -670, -670, -670, -670, -670, -670, -670, -670,
+     -670, -670, -670, -670, -670, -670, -670, -670
+    },
+
+    {
+       67, -671, -671, -671, -671, -671, -671, -671, -671, -671,
+     -671, -671, -671, -671, -671, -671, -671, -671, -671, -671,
+     -671, -671, -671, -671, -671, -671, -671, -671, -671, -671,
+     -671, -671, -671, -671, -671, -671, -671, -671, -671, -671,
+     -671, -671, -671, -671, -671, -671, -671, -671, -671, -671,
+     -671, -671, -671, -671, -671, -671, -671, -671, -671, -671,
+     -671, -671, -671, -671, -671, -671, -671, -671, -671,  763,
+
+     -671, -671, -671, -671, -671, -671, -671, -671, -671, -671,
+     -671, -671, -671, -671, -671, -671, -671, -671, -671, -671,
+     -671, -671, -671, -671, -671, -671, -671, -671, -671, -671,
+     -671, -671, -671, -671, -671, -671, -671, -671, -671, -671,
+     -671, -671, -671, -671, -671, -671, -671, -671, -671, -671,
+     -671, -671, -671, -671, -671, -671, -671, -671
+    },
+
+    {
+       67, -672, -672, -672, -672, -672, -672, -672, -672, -672,
+     -672, -672, -672, -672, -672, -672, -672, -672, -672, -672,
+     -672, -672, -672, -672, -672, -672, -672, -672, -672, -672,
+     -672, -672, -672, -672, -672, -672, -672, -672, -672, -672,
+
+     -672, -672, -672, -672, -672, -672, -672, -672, -672, -672,
+     -672, -672, -672, -672, -672, -672, -672, -672, -672, -672,
+     -672, -672, -672, -672, -672, -672, -672, -672, -672, -672,
+     -672, -672, -672, -672, -672, -672, -672, -672, -672, -672,
+     -672, -672, -672, -672, -672, -672, -672, -672, -672, -672,
+     -672, -672, -672, -672, -672, -672, -672, -672, -672, -672,
+     -672, -672, -672, -672, -672, -672, -672, -672, -672, -672,
+     -672, -672, -672, -672, -672, -672, -672, -672, -672, -672,
+     -672, -672, -672, -672, -672, -672, -672, -672
+    },
+
+    {
+       67, -673, -673, -673, -673, -673, -673, -673, -673, -673,
+
+     -673, -673, -673, -673, -673, -673, -673, -673, -673, -673,
+     -673, -673, -673, -673, -673, -673, -673, -673, -673, -673,
+     -673, -673, -673, -673, -673, -673, -673, -673, -673, -673,
+     -673, -673, -673, -673, -673, -673, -673, -673, -673, -673,
+     -673, -673, -673, -673, -673, -673, -673, -673, -673, -673,
+     -673, -673, -673, -673, -673, -673, -673, -673, -673, -673,
+     -673, -673, -673, -673, -673, -673, -673, -673, -673, -673,
+     -673, -673, -673, -673, -673, -673, -673, -673, -673, -673,
+     -673, -673, -673, -673, -673, -673, -673, -673, -673, -673,
+     -673, -673, -673, -673, -673, -673, -673, -673, -673, -673,
+
+     -673, -673, -673, -673, -673, -673, -673, -673, -673, -673,
+     -673, -673, -673, -673, -673, -673, -673, -673
+    },
+
+    {
+       67, -674, -674, -674, -674, -674, -674, -674, -674, -674,
+     -674, -674, -674, -674, -674, -674, -674, -674, -674, -674,
+     -674, -674, -674, -674, -674, -674, -674, -674, -674, -674,
+     -674, -674, -674, -674, -674, -674, -674, -674, -674, -674,
+     -674, -674, -674, -674, -674, -674, -674, -674, -674, -674,
+     -674, -674, -674, -674, -674, -674, -674, -674, -674, -674,
+     -674, -674, -674, -674, -674, -674, -674, -674, -674, -674,
+     -674, -674, -674, -674, -674, -674, -674, -674, -674, -674,
+
+     -674, -674, -674, -674, -674, -674, -674, -674, -674, -674,
+     -674, -674, -674, -674, -674, -674, -674, -674, -674, -674,
+     -674, -674, -674, -674, -674, -674, -674, -674, -674, -674,
+     -674, -674, -674, -674, -674, -674, -674, -674, -674, -674,
+     -674, -674, -674, -674, -674, -674, -674, -674
+    },
+
+    {
+       67, -675, -675, -675, -675, -675, -675, -675, -675, -675,
+     -675, -675, -675, -675, -675, -675, -675, -675, -675, -675,
+     -675, -675, -675, -675, -675, -675, -675, -675, -675, -675,
+     -675, -675, -675, -675, -675, -675, -675, -675, -675, -675,
+     -675, -675, -675, -675, -675, -675, -675, -675, -675, -675,
+
+     -675, -675, -675, -675, -675, -675, -675, -675, -675, -675,
+     -675, -675, -675, -675, -675, -675, -675, -675, -675, -675,
+     -675, -675, -675, -675, -675, -675, -675, -675, -675, -675,
+     -675, -675, -675, -675, -675, -675, -675, -675, -675, -675,
+     -675, -675, -675, -675, -675, -675, -675, -675, -675, -675,
+     -675, -675, -675, -675, -675, -675, -675, -675, -675, -675,
+     -675, -675, -675, -675, -675, -675, -675, -675, -675, -675,
+     -675, -675, -675, -675, -675, -675, -675, -675
+    },
+
+    {
+       67, -676, -676, -676, -676, -676, -676, -676, -676, -676,
+     -676, -676, -676, -676, -676, -676, -676, -676, -676, -676,
+
+     -676, -676, -676, -676, -676, -676, -676, -676, -676, -676,
+     -676, -676, -676, -676, -676, -676, -676, -676, -676, -676,
+     -676, -676, -676, -676, -676, -676, -676, -676, -676, -676,
+     -676, -676, -676, -676, -676, -676, -676, -676, -676, -676,
+     -676, -676, -676, -676, -676, -676, -676, -676, -676, -676,
+     -676, -676, -676, -676, -676, -676, -676, -676, -676, -676,
+     -676, -676, -676, -676, -676, -676, -676, -676, -676, -676,
+     -676, -676, -676, -676, -676, -676, -676, -676, -676, -676,
+     -676, -676, -676, -676, -676, -676, -676, -676, -676, -676,
+     -676, -676, -676, -676, -676, -676, -676, -676, -676, -676,
+
+     -676, -676, -676, -676, -676, -676, -676, -676
+    },
+
+    {
+       67, -677, -677, -677, -677, -677, -677, -677, -677, -677,
+     -677, -677, -677, -677, -677, -677, -677, -677, -677, -677,
+     -677, -677, -677, -677, -677, -677, -677, -677, -677, -677,
+     -677, -677, -677, -677, -677, -677, -677, -677, -677, -677,
+     -677, -677, -677, -677, -677, -677, -677, -677, -677, -677,
+     -677, -677, -677, -677, -677, -677, -677, -677, -677, -677,
+     -677, -677, -677, -677, -677, -677, -677, -677, -677, -677,
+     -677, -677, -677, -677, -677, -677, -677, -677, -677, -677,
+     -677, -677, -677, -677, -677, -677, -677, -677, -677, -677,
+
+     -677, -677, -677, -677, -677, -677, -677, -677, -677, -677,
+     -677, -677, -677, -677, -677, -677, -677, -677, -677, -677,
+     -677, -677, -677, -677, -677, -677, -677, -677, -677, -677,
+     -677, -677, -677, -677, -677, -677, -677, -677
+    },
+
+    {
+       67, -678, -678, -678, -678, -678, -678, -678, -678, -678,
+     -678, -678, -678, -678, -678, -678, -678, -678, -678, -678,
+     -678, -678, -678, -678, -678, -678, -678, -678, -678, -678,
+     -678, -678, -678, -678, -678, -678, -678, -678, -678, -678,
+     -678, -678, -678, -678, -678, -678, -678, -678, -678, -678,
+     -678, -678, -678, -678, -678, -678, -678, -678, -678, -678,
+
+     -678, -678, -678, -678, -678, -678, -678, -678, -678, -678,
+     -678, -678, -678, -678, -678, -678, -678, -678, -678, -678,
+     -678, -678, -678, -678, -678, -678, -678, -678, -678, -678,
+     -678, -678, -678, -678, -678, -678, -678, -678, -678, -678,
+     -678, -678, -678, -678, -678, -678, -678, -678, -678, -678,
+     -678, -678, -678, -678, -678, -678, -678, -678, -678, -678,
+     -678, -678, -678, -678, -678, -678, -678, -678
+    },
+
+    {
+       67, -679, -679, -679, -679, -679, -679, -679, -679, -679,
+     -679, -679, -679, -679, -679, -679, -679, -679, -679, -679,
+     -679, -679, -679, -679, -679, -679, -679, -679, -679, -679,
+
+     -679, -679, -679, -679, -679, -679, -679, -679, -679, -679,
+     -679, -679, -679, -679, -679, -679, -679, -679, -679, -679,
+     -679, -679, -679, -679, -679, -679, -679, -679, -679, -679,
+     -679, -679, -679, -679, -679, -679, -679, -679, -679, -679,
+     -679, -679, -679, -679, -679, -679, -679, -679, -679, -679,
+     -679, -679, -679, -679, -679, -679, -679, -679, -679, -679,
+     -679, -679, -679, -679, -679, -679, -679, -679, -679, -679,
+     -679, -679, -679, -679, -679, -679, -679, -679, -679, -679,
+     -679, -679, -679, -679, -679, -679, -679, -679, -679, -679,
+     -679, -679, -679, -679, -679, -679, -679, -679
+
+    },
+
+    {
+       67, -680, -680, -680, -680, -680, -680, -680, -680, -680,
+     -680, -680, -680, -680, -680, -680, -680, -680, -680, -680,
+     -680, -680, -680, -680, -680, -680, -680, -680, -680, -680,
+     -680, -680, -680, -680, -680, -680, -680, -680, -680, -680,
+     -680, -680, -680, -680, -680, -680, -680, -680, -680, -680,
+     -680, -680, -680, -680, -680, -680, -680, -680, -680, -680,
+     -680, -680, -680, -680, -680, -680, -680, -680, -680, -680,
+     -680, -680, -680, -680, -680, -680, -680, -680, -680, -680,
+     -680, -680, -680, -680, -680, -680, -680, -680, -680, -680,
+     -680, -680, -680, -680, -680, -680, -680, -680, -680, -680,
+
+     -680, -680, -680, -680, -680, -680, -680, -680, -680, -680,
+     -680, -680, -680, -680, -680, -680, -680, -680, -680, -680,
+     -680, -680, -680, -680, -680, -680, -680, -680
+    },
+
+    {
+       67, -681, -681, -681, -681, -681, -681, -681, -681, -681,
+     -681, -681, -681, -681, -681, -681, -681, -681, -681, -681,
+     -681, -681, -681, -681, -681, -681, -681, -681, -681, -681,
+     -681, -681, -681, -681, -681, -681, -681, -681, -681, -681,
+     -681, -681, -681, -681, -681, -681, -681, -681, -681, -681,
+     -681, -681, -681, -681, -681, -681, -681, -681, -681, -681,
+     -681, -681, -681, -681, -681, -681, -681, -681, -681, -681,
+
+     -681, -681, -681, -681, -681, -681, -681, -681, -681, -681,
+     -681, -681, -681, -681, -681, -681, -681, -681, -681, -681,
+     -681, -681, -681, -681, -681, -681, -681, -681, -681, -681,
+     -681, -681, -681, -681, -681, -681, -681, -681, -681, -681,
+     -681, -681, -681, -681, -681, -681, -681, -681, -681, -681,
+     -681, -681, -681, -681, -681, -681, -681, -681
+    },
+
+    {
+       67, -682, -682, -682, -682, -682, -682, -682, -682, -682,
+     -682, -682, -682, -682, -682, -682, -682, -682, -682, -682,
+     -682, -682, -682, -682, -682, -682, -682, -682, -682, -682,
+     -682, -682, -682, -682, -682, -682, -682, -682, -682, -682,
+
+     -682, -682, -682, -682, -682, -682, -682, -682, -682, -682,
+     -682, -682, -682, -682, -682, -682, -682, -682, -682, -682,
+     -682, -682, -682, -682, -682, -682, -682, -682, -682, -682,
+     -682, -682, -682, -682, -682, -682, -682, -682, -682, -682,
+     -682, -682, -682, -682, -682, -682, -682, -682, -682, -682,
+     -682, -682, -682, -682, -682, -682, -682, -682, -682, -682,
+     -682, -682, -682, -682, -682, -682, -682, -682, -682, -682,
+     -682, -682, -682, -682, -682, -682, -682, -682, -682, -682,
+     -682, -682, -682, -682, -682, -682, -682, -682
+    },
+
+    {
+       67, -683, -683, -683, -683, -683, -683, -683, -683, -683,
+
+     -683, -683, -683, -683, -683, -683, -683, -683, -683, -683,
+     -683, -683, -683, -683, -683, -683, -683, -683, -683, -683,
+     -683, -683, -683, -683, -683, -683, -683, -683, -683, -683,
+     -683, -683, -683, -683, -683, -683, -683, -683, -683, -683,
+     -683, -683, -683, -683, -683, -683, -683, -683, -683, -683,
+     -683, -683, -683, -683, -683, -683, -683, -683, -683, -683,
+     -683, -683, -683, -683, -683, -683, -683, -683, -683, -683,
+     -683, -683, -683, -683, -683, -683, -683, -683, -683, -683,
+     -683, -683, -683, -683, -683, -683, -683, -683, -683, -683,
+     -683, -683, -683, -683, -683, -683, -683, -683, -683, -683,
+
+     -683, -683, -683, -683, -683, -683, -683, -683, -683, -683,
+     -683, -683, -683, -683, -683, -683, -683, -683
+    },
+
+    {
+       67, -684, -684, -684, -684, -684, -684, -684, -684, -684,
+     -684, -684, -684, -684, -684, -684, -684, -684, -684, -684,
+     -684, -684, -684, -684, -684, -684, -684, -684, -684, -684,
+     -684, -684, -684, -684, -684, -684, -684, -684, -684, -684,
+     -684, -684, -684, -684, -684, -684, -684, -684, -684, -684,
+     -684, -684, -684, -684, -684, -684, -684, -684, -684, -684,
+     -684, -684, -684, -684, -684, -684, -684, -684, -684, -684,
+     -684, -684, -684, -684, -684, -684, -684, -684, -684, -684,
+
+     -684, -684, -684, -684, -684, -684, -684, -684, -684, -684,
+     -684, -684, -684, -684, -684, -684, -684, -684, -684, -684,
+     -684, -684, -684, -684, -684, -684, -684, -684, -684, -684,
+     -684, -684, -684, -684, -684, -684, -684, -684, -684, -684,
+     -684, -684, -684, -684, -684, -684, -684, -684
+    },
+
+    {
+       67, -685, -685, -685, -685, -685, -685, -685, -685, -685,
+     -685, -685, -685, -685, -685, -685, -685, -685, -685, -685,
+     -685, -685, -685, -685, -685, -685, -685, -685, -685, -685,
+     -685, -685, -685, -685, -685, -685, -685, -685, -685, -685,
+     -685, -685, -685, -685, -685, -685, -685, -685, -685, -685,
+
+     -685, -685, -685, -685, -685, -685, -685, -685, -685, -685,
+     -685, -685, -685, -685, -685, -685, -685, -685, -685, -685,
+     -685, -685, -685, -685, -685, -685, -685, -685, -685, -685,
+     -685, -685, -685, -685, -685, -685, -685, -685, -685, -685,
+     -685, -685, -685, -685, -685, -685, -685, -685, -685, -685,
+     -685, -685, -685, -685, -685, -685, -685, -685, -685, -685,
+     -685, -685, -685, -685, -685, -685, -685, -685, -685, -685,
+     -685, -685, -685, -685, -685, -685, -685, -685
+    },
+
+    {
+       67, -686, -686, -686, -686, -686, -686, -686, -686, -686,
+     -686, -686, -686, -686, -686, -686, -686, -686, -686, -686,
+
+     -686, -686, -686, -686, -686, -686, -686, -686, -686, -686,
+     -686, -686, -686, -686, -686, -686, -686, -686, -686, -686,
+     -686, -686, -686, -686, -686, -686, -686, -686, -686, -686,
+     -686, -686, -686, -686, -686, -686, -686, -686, -686, -686,
+     -686, -686, -686, -686, -686, -686, -686, -686, -686, -686,
+     -686, -686, -686, -686, -686, -686, -686, -686, -686, -686,
+     -686, -686, -686, -686, -686, -686, -686, -686, -686, -686,
+     -686, -686, -686, -686, -686, -686, -686, -686, -686, -686,
+     -686, -686, -686, -686, -686, -686, -686, -686, -686, -686,
+     -686, -686, -686, -686, -686, -686, -686, -686, -686, -686,
+
+     -686, -686, -686, -686, -686, -686, -686, -686
+    },
+
+    {
+       67, -687, -687, -687, -687, -687, -687, -687, -687, -687,
+     -687, -687, -687, -687, -687, -687, -687, -687, -687, -687,
+     -687, -687, -687, -687, -687, -687, -687, -687, -687, -687,
+     -687, -687, -687, -687, -687, -687, -687, -687, -687, -687,
+     -687, -687, -687, -687, -687, -687, -687, -687, -687, -687,
+     -687, -687, -687, -687, -687, -687, -687, -687, -687, -687,
+     -687, -687, -687, -687, -687, -687, -687, -687, -687, -687,
+     -687, -687, -687, -687, -687, -687, -687, -687, -687, -687,
+     -687, -687, -687, -687, -687, -687, -687, -687, -687, -687,
+
+     -687, -687, -687, -687, -687, -687, -687, -687, -687, -687,
+     -687, -687, -687, -687, -687, -687, -687, -687, -687, -687,
+     -687, -687, -687, -687, -687, -687, -687, -687, -687, -687,
+     -687, -687, -687, -687, -687, -687, -687, -687
+    },
+
+    {
+       67, -688, -688, -688, -688, -688, -688, -688, -688, -688,
+     -688, -688, -688, -688, -688, -688, -688, -688, -688, -688,
+     -688, -688, -688, -688, -688, -688, -688, -688, -688, -688,
+     -688, -688, -688, -688, -688, -688, -688, -688, -688, -688,
+     -688, -688, -688, -688, -688, -688, -688, -688, -688, -688,
+     -688, -688, -688, -688, -688, -688, -688, -688, -688, -688,
+
+     -688, -688, -688, -688, -688, -688, -688, -688, -688, -688,
+     -688, -688, -688, -688, -688, -688, -688, -688, -688, -688,
+     -688, -688, -688, -688, -688, -688, -688, -688, -688, -688,
+     -688, -688, -688, -688, -688, -688, -688, -688, -688, -688,
+     -688, -688, -688, -688, -688, -688, -688, -688, -688, -688,
+     -688, -688, -688, -688, -688, -688, -688, -688, -688, -688,
+     -688, -688, -688, -688, -688, -688, -688, -688
+    },
+
+    {
+       67, -689, -689, -689, -689, -689, -689, -689, -689, -689,
+     -689, -689, -689, -689, -689, -689, -689, -689, -689, -689,
+     -689, -689, -689, -689, -689, -689, -689, -689, -689, -689,
+
+     -689, -689, -689, -689, -689, -689, -689, -689, -689, -689,
+     -689, -689, -689, -689, -689, -689, -689, -689, -689, -689,
+     -689, -689, -689, -689, -689, -689, -689, -689, -689, -689,
+     -689, -689, -689, -689, -689, -689, -689, -689, -689, -689,
+     -689, -689, -689, -689, -689, -689, -689, -689, -689, -689,
+     -689, -689, -689, -689, -689, -689, -689, -689, -689, -689,
+     -689, -689, -689, -689, -689, -689, -689, -689, -689, -689,
+     -689, -689, -689, -689, -689, -689, -689, -689, -689, -689,
+     -689, -689, -689, -689, -689, -689, -689, -689, -689, -689,
+     -689, -689, -689, -689, -689, -689, -689, -689
+
+    },
+
+    {
+       67, -690, -690, -690, -690, -690, -690, -690, -690, -690,
+     -690, -690, -690, -690, -690, -690, -690, -690, -690, -690,
+     -690, -690, -690, -690, -690, -690, -690, -690, -690, -690,
+     -690, -690, -690, -690, -690, -690, -690, -690, -690, -690,
+     -690, -690, -690, -690, -690, -690, -690, -690, -690, -690,
+     -690, -690, -690, -690, -690, -690, -690, -690, -690, -690,
+     -690, -690, -690, -690, -690, -690, -690, -690, -690, -690,
+     -690, -690, -690, -690, -690, -690, -690, -690, -690, -690,
+     -690, -690, -690, -690, -690, -690, -690, -690, -690, -690,
+     -690, -690, -690, -690, -690, -690, -690, -690, -690, -690,
+
+     -690, -690, -690, -690, -690, -690, -690, -690, -690, -690,
+     -690, -690, -690, -690, -690, -690, -690, -690, -690, -690,
+     -690, -690, -690, -690, -690, -690, -690, -690
+    },
+
+    {
+       67, -691, -691, -691, -691, -691, -691, -691, -691, -691,
+     -691, -691, -691, -691, -691, -691, -691, -691, -691, -691,
+     -691, -691, -691, -691, -691, -691, -691, -691, -691, -691,
+     -691, -691, -691, -691, -691, -691, -691, -691, -691, -691,
+     -691, -691, -691, -691, -691, -691, -691, -691, -691, -691,
+     -691, -691, -691, -691, -691, -691, -691, -691, -691, -691,
+     -691, -691, -691, -691, -691, -691, -691, -691, -691, -691,
+
+     -691, -691, -691, -691, -691, -691, -691, -691, -691, -691,
+     -691, -691, -691, -691, -691, -691, -691, -691, -691, -691,
+     -691, -691, -691, -691, -691, -691, -691, -691, -691, -691,
+     -691, -691, -691, -691, -691, -691, -691, -691, -691, -691,
+     -691, -691, -691, -691, -691, -691, -691, -691, -691, -691,
+     -691, -691, -691, -691, -691, -691, -691, -691
+    },
+
+    {
+       67, -692, -692, -692, -692, -692, -692, -692, -692, -692,
+     -692, -692, -692, -692, -692, -692, -692, -692, -692, -692,
+     -692, -692, -692, -692, -692, -692, -692, -692, -692, -692,
+     -692, -692, -692, -692, -692, -692, -692, -692, -692, -692,
+
+     -692, -692, -692, -692, -692, -692, -692, -692, -692, -692,
+     -692, -692, -692, -692, -692, -692, -692, -692, -692, -692,
+     -692, -692, -692, -692, -692, -692, -692, -692, -692, -692,
+     -692, -692, -692, -692, -692, -692, -692, -692, -692, -692,
+     -692, -692, -692, -692, -692, -692, -692, -692, -692, -692,
+     -692, -692, -692, -692, -692, -692, -692, -692, -692, -692,
+     -692, -692, -692, -692, -692, -692, -692, -692, -692, -692,
+     -692, -692, -692, -692, -692, -692, -692, -692, -692, -692,
+     -692, -692, -692, -692, -692, -692, -692, -692
+    },
+
+    {
+       67, -693, -693, -693, -693, -693, -693, -693, -693, -693,
+
+     -693, -693, -693, -693, -693, -693, -693, -693, -693, -693,
+     -693, -693, -693, -693, -693, -693, -693, -693, -693, -693,
+     -693, -693, -693, -693, -693, -693, -693, -693, -693, -693,
+     -693, -693, -693, -693, -693, -693, -693, -693, -693, -693,
+     -693, -693, -693, -693, -693, -693, -693, -693, -693, -693,
+     -693, -693, -693, -693, -693, -693, -693, -693, -693, -693,
+     -693, -693, -693, -693, -693, -693, -693, -693, -693, -693,
+     -693, -693, -693, -693, -693, -693, -693, -693, -693, -693,
+     -693, -693, -693, -693, -693, -693, -693, -693, -693, -693,
+     -693, -693, -693, -693, -693, -693, -693, -693, -693, -693,
+
+     -693, -693, -693, -693, -693, -693, -693, -693, -693, -693,
+     -693, -693, -693, -693, -693, -693, -693, -693
+    },
+
+    {
+       67, -694, -694, -694, -694, -694, -694, -694, -694, -694,
+     -694, -694, -694, -694, -694, -694, -694, -694, -694, -694,
+     -694, -694, -694, -694, -694, -694, -694, -694, -694, -694,
+     -694, -694, -694, -694, -694, -694, -694, -694, -694, -694,
+     -694, -694, -694, -694, -694, -694, -694, -694, -694, -694,
+     -694, -694, -694, -694, -694, -694, -694, -694, -694, -694,
+     -694, -694, -694, -694, -694, -694, -694, -694, -694, -694,
+     -694, -694, -694, -694, -694, -694, -694, -694, -694, -694,
+
+     -694, -694, -694, -694, -694, -694, -694, -694, -694, -694,
+     -694, -694, -694, -694, -694, -694, -694, -694, -694, -694,
+     -694, -694, -694, -694, -694, -694, -694, -694, -694, -694,
+     -694, -694, -694, -694, -694, -694, -694, -694, -694, -694,
+     -694, -694, -694, -694, -694, -694, -694, -694
+    },
+
+    {
+       67, -695, -695, -695, -695, -695, -695, -695, -695, -695,
+     -695, -695, -695, -695, -695, -695, -695, -695, -695, -695,
+     -695, -695, -695, -695, -695, -695, -695, -695, -695, -695,
+     -695, -695, -695, -695, -695, -695, -695, -695, -695, -695,
+     -695, -695, -695, -695, -695, -695, -695, -695, -695, -695,
+
+     -695, -695, -695, -695, -695, -695, -695, -695, -695, -695,
+     -695, -695, -695, -695, -695, -695, -695, -695, -695, -695,
+     -695, -695, -695, -695, -695, -695, -695, -695, -695, -695,
+     -695, -695, -695, -695, -695, -695, -695, -695, -695, -695,
+     -695, -695, -695, -695, -695, -695, -695, -695, -695, -695,
+     -695, -695, -695, -695, -695, -695, -695, -695, -695, -695,
+     -695, -695, -695, -695, -695, -695, -695, -695, -695, -695,
+     -695, -695, -695, -695, -695, -695, -695, -695
+    },
+
+    {
+       67, -696, -696, -696, -696, -696, -696, -696, -696, -696,
+     -696, -696, -696, -696, -696, -696, -696, -696, -696, -696,
+
+     -696, -696, -696, -696, -696, -696, -696, -696, -696, -696,
+     -696, -696, -696, -696, -696, -696, -696, -696, -696, -696,
+     -696, -696, -696, -696, -696, -696, -696, -696, -696, -696,
+     -696, -696, -696, -696, -696, -696, -696, -696, -696, -696,
+     -696, -696, -696, -696, -696, -696, -696, -696, -696, -696,
+     -696, -696, -696, -696, -696, -696, -696, -696, -696, -696,
+     -696, -696, -696, -696, -696, -696, -696, -696, -696, -696,
+     -696, -696, -696, -696, -696, -696, -696, -696, -696, -696,
+     -696, -696, -696, -696, -696, -696, -696, -696, -696, -696,
+     -696, -696, -696, -696, -696, -696, -696, -696, -696, -696,
+
+     -696, -696, -696, -696, -696, -696, -696, -696
+    },
+
+    {
+       67, -697, -697, -697, -697, -697, -697, -697, -697, -697,
+     -697, -697, -697, -697, -697, -697, -697, -697, -697, -697,
+     -697, -697, -697, -697, -697, -697, -697, -697, -697, -697,
+     -697, -697, -697, -697, -697, -697, -697, -697, -697, -697,
+     -697, -697, -697, -697, -697, -697, -697, -697, -697, -697,
+     -697, -697, -697, -697, -697, -697, -697, -697, -697, -697,
+     -697, -697, -697, -697, -697, -697, -697, -697, -697, -697,
+     -697, -697, -697, -697, -697, -697, -697, -697, -697, -697,
+     -697, -697, -697, -697, -697, -697, -697, -697, -697, -697,
+
+     -697, -697, -697, -697, -697, -697, -697, -697, -697, -697,
+     -697, -697, -697, -697, -697, -697, -697, -697, -697, -697,
+     -697, -697, -697, -697, -697, -697, -697, -697, -697, -697,
+     -697, -697, -697, -697, -697, -697, -697, -697
+    },
+
+    {
+       67, -698, -698, -698, -698, -698, -698, -698, -698, -698,
+     -698, -698, -698, -698, -698, -698, -698, -698, -698, -698,
+     -698, -698, -698, -698, -698, -698, -698, -698, -698, -698,
+     -698, -698, -698, -698, -698, -698, -698, -698, -698, -698,
+     -698, -698, -698, -698, -698, -698, -698, -698, -698, -698,
+     -698, -698, -698, -698, -698, -698, -698, -698, -698, -698,
+
+     -698, -698, -698, -698, -698, -698, -698, -698, -698, -698,
+     -698, -698, -698, -698, -698, -698, -698, -698, -698, -698,
+     -698, -698, -698, -698, -698, -698, -698, -698, -698, -698,
+     -698, -698, -698, -698, -698, -698, -698, -698, -698, -698,
+     -698, -698, -698, -698, -698, -698, -698, -698, -698, -698,
+     -698, -698, -698, -698, -698, -698, -698, -698, -698, -698,
+     -698, -698, -698, -698, -698, -698, -698, -698
+    },
+
+    {
+       67, -699, -699, -699, -699, -699, -699, -699, -699, -699,
+     -699, -699, -699, -699, -699, -699, -699, -699, -699, -699,
+     -699, -699, -699, -699, -699, -699, -699, -699, -699, -699,
+
+     -699, -699, -699, -699, -699, -699, -699, -699, -699, -699,
+     -699, -699, -699, -699, -699, -699, -699, -699, -699, -699,
+     -699, -699, -699, -699, -699, -699, -699, -699, -699, -699,
+     -699, -699, -699, -699, -699, -699, -699, -699, -699, -699,
+     -699, -699, -699, -699, -699, -699, -699, -699, -699, -699,
+     -699, -699, -699, -699, -699, -699, -699, -699, -699, -699,
+     -699, -699, -699, -699, -699, -699, -699, -699, -699, -699,
+     -699, -699, -699, -699, -699, -699, -699, -699, -699, -699,
+     -699, -699, -699, -699, -699, -699, -699, -699, -699, -699,
+     -699, -699, -699, -699, -699, -699, -699, -699
+
+    },
+
+    {
+       67, -700, -700, -700, -700, -700, -700, -700, -700, -700,
+     -700, -700, -700, -700, -700, -700, -700, -700, -700, -700,
+     -700, -700, -700, -700, -700, -700, -700, -700, -700, -700,
+     -700, -700, -700, -700, -700, -700, -700, -700, -700, -700,
+     -700, -700, -700, -700, -700, -700, -700, -700, -700, -700,
+     -700, -700, -700, -700, -700, -700, -700, -700, -700, -700,
+     -700, -700, -700, -700, -700, -700, -700, -700, -700, -700,
+     -700, -700, -700, -700, -700, -700, -700, -700, -700, -700,
+     -700, -700, -700, -700, -700, -700, -700, -700, -700, -700,
+     -700, -700, -700, -700, -700, -700, -700, -700, -700, -700,
+
+     -700, -700, -700, -700, -700, -700, -700, -700, -700, -700,
+     -700, -700, -700, -700, -700, -700, -700, -700, -700, -700,
+     -700, -700, -700, -700, -700, -700, -700, -700
+    },
+
+    {
+       67, -701, -701, -701, -701, -701, -701, -701, -701, -701,
+     -701, -701, -701, -701, -701, -701, -701, -701, -701, -701,
+     -701, -701, -701, -701, -701, -701, -701, -701, -701, -701,
+     -701, -701, -701, -701, -701, -701, -701, -701, -701, -701,
+     -701, -701, -701, -701, -701, -701, -701, -701, -701, -701,
+     -701, -701, -701, -701, -701, -701, -701, -701, -701, -701,
+     -701, -701, -701, -701, -701, -701, -701, -701, -701, -701,
+
+     -701, -701, -701, -701, -701, -701, -701, -701, -701, -701,
+     -701, -701, -701, -701, -701, -701, -701, -701, -701, -701,
+     -701, -701, -701, -701, -701, -701, -701, -701, -701, -701,
+     -701, -701, -701, -701, -701, -701, -701, -701, -701, -701,
+     -701, -701, -701, -701, -701, -701, -701, -701, -701, -701,
+     -701, -701, -701, -701, -701, -701, -701, -701
+    },
+
+    {
+       67, -702, -702, -702, -702, -702, -702, -702, -702, -702,
+     -702, -702, -702, -702, -702, -702, -702, -702, -702, -702,
+     -702, -702, -702, -702, -702, -702, -702, -702, -702, -702,
+     -702, -702, -702, -702, -702, -702, -702, -702, -702, -702,
+
+     -702, -702, -702, -702, -702, -702, -702, -702, -702, -702,
+     -702, -702, -702, -702, -702, -702, -702, -702, -702, -702,
+     -702, -702, -702, -702, -702, -702, -702, -702, -702, -702,
+     -702, -702, -702, -702, -702, -702, -702, -702, -702, -702,
+     -702, -702, -702, -702, -702, -702, -702, -702, -702, -702,
+     -702, -702, -702, -702, -702, -702, -702, -702, -702, -702,
+     -702, -702, -702, -702, -702, -702, -702, -702, -702, -702,
+     -702, -702, -702, -702, -702, -702, -702, -702, -702, -702,
+     -702, -702, -702, -702, -702, -702, -702, -702
+    },
+
+    {
+       67, -703, -703, -703, -703, -703, -703, -703, -703, -703,
+
+     -703, -703, -703, -703, -703, -703, -703, -703, -703, -703,
+     -703, -703, -703, -703, -703, -703, -703, -703, -703, -703,
+     -703, -703, -703, -703, -703, -703, -703, -703, -703, -703,
+     -703, -703, -703, -703, -703, -703, -703, -703, -703, -703,
+     -703, -703, -703, -703, -703, -703, -703, -703, -703, -703,
+     -703, -703, -703, -703, -703, -703, -703, -703, -703, -703,
+     -703, -703, -703, -703, -703, -703, -703, -703, -703, -703,
+     -703, -703, -703, -703, -703, -703, -703, -703, -703, -703,
+     -703, -703, -703, -703, -703, -703, -703, -703, -703, -703,
+     -703, -703, -703, -703, -703, -703, -703, -703, -703, -703,
+
+     -703, -703, -703, -703, -703, -703, -703, -703, -703, -703,
+     -703, -703, -703, -703, -703, -703, -703, -703
+    },
+
+    {
+       67, -704, -704, -704, -704, -704, -704, -704, -704, -704,
+     -704, -704, -704, -704, -704, -704, -704, -704, -704, -704,
+     -704, -704, -704, -704, -704, -704, -704, -704, -704, -704,
+     -704, -704, -704, -704, -704, -704, -704, -704, -704, -704,
+     -704, -704, -704, -704, -704, -704, -704, -704, -704, -704,
+     -704, -704, -704, -704, -704, -704, -704, -704, -704, -704,
+     -704, -704, -704, -704, -704, -704, -704, -704, -704, -704,
+     -704, -704, -704, -704, -704, -704, -704, -704, -704, -704,
+
+     -704, -704, -704, -704, -704, -704, -704, -704, -704, -704,
+     -704, -704, -704, -704, -704, -704, -704, -704, -704, -704,
+     -704, -704, -704, -704, -704, -704, -704, -704, -704, -704,
+     -704, -704, -704, -704, -704, -704, -704, -704, -704, -704,
+     -704, -704, -704, -704, -704, -704, -704, -704
+    },
+
+    {
+       67, -705, -705, -705, -705, -705, -705, -705, -705, -705,
+     -705, -705, -705, -705, -705, -705, -705, -705, -705, -705,
+     -705, -705, -705, -705, -705, -705, -705, -705, -705, -705,
+     -705, -705, -705, -705, -705, -705, -705, -705, -705, -705,
+     -705, -705, -705, -705, -705, -705, -705, -705, -705, -705,
+
+     -705, -705, -705, -705, -705, -705, -705, -705, -705, -705,
+     -705, -705, -705, -705, -705, -705, -705, -705, -705, -705,
+     -705, -705, -705, -705, -705, -705, -705, -705, -705, -705,
+     -705, -705, -705, -705, -705, -705, -705, -705, -705, -705,
+     -705, -705, -705, -705, -705, -705, -705, -705, -705, -705,
+     -705, -705, -705, -705, -705, -705, -705, -705, -705, -705,
+     -705, -705, -705, -705, -705, -705, -705, -705, -705, -705,
+     -705, -705, -705, -705, -705, -705, -705, -705
+    },
+
+    {
+       67, -706, -706, -706, -706, -706, -706, -706, -706, -706,
+     -706, -706, -706, -706, -706, -706, -706, -706, -706, -706,
+
+     -706, -706, -706, -706, -706, -706, -706, -706, -706, -706,
+     -706, -706, -706, -706, -706, -706, -706, -706, -706, -706,
+     -706, -706, -706, -706, -706, -706, -706, -706, -706, -706,
+     -706, -706, -706, -706, -706, -706, -706, -706, -706, -706,
+     -706, -706, -706, -706, -706, -706, -706, -706, -706, -706,
+     -706, -706, -706, -706, -706, -706, -706, -706, -706, -706,
+     -706, -706, -706, -706, -706, -706, -706, -706, -706, -706,
+     -706, -706, -706, -706, -706, -706, -706, -706, -706, -706,
+     -706, -706, -706, -706, -706, -706, -706, -706, -706, -706,
+     -706, -706, -706, -706, -706, -706, -706, -706, -706, -706,
+
+     -706, -706, -706, -706, -706, -706, -706, -706
+    },
+
+    {
+       67, -707, -707, -707, -707, -707, -707, -707, -707, -707,
+     -707, -707, -707, -707, -707, -707, -707, -707, -707, -707,
+     -707, -707, -707, -707, -707, -707, -707, -707, -707, -707,
+     -707, -707, -707, -707, -707, -707, -707, -707, -707, -707,
+     -707, -707, -707, -707, -707, -707, -707, -707, -707, -707,
+     -707, -707, -707, -707, -707, -707, -707, -707, -707, -707,
+     -707, -707, -707, -707, -707, -707, -707, -707, -707, -707,
+     -707, -707, -707, -707, -707, -707, -707, -707, -707, -707,
+     -707, -707, -707, -707, -707, -707, -707, -707, -707, -707,
+
+     -707, -707, -707, -707, -707, -707, -707, -707, -707, -707,
+     -707, -707, -707, -707, -707, -707, -707, -707, -707, -707,
+     -707, -707, -707, -707, -707, -707, -707, -707, -707, -707,
+     -707, -707, -707, -707, -707, -707, -707, -707
+    },
+
+    {
+       67, -708, -708, -708, -708, -708, -708, -708, -708, -708,
+     -708, -708, -708, -708, -708, -708, -708, -708, -708, -708,
+     -708, -708, -708, -708, -708, -708, -708, -708, -708, -708,
+     -708, -708, -708, -708, -708, -708, -708, -708, -708, -708,
+     -708, -708, -708, -708, -708, -708, -708, -708, -708, -708,
+     -708, -708, -708, -708, -708, -708, -708, -708, -708, -708,
+
+     -708, -708, -708, -708, -708, -708, -708, -708, -708, -708,
+     -708, -708, -708, -708, -708, -708, -708, -708, -708, -708,
+     -708, -708, -708, -708, -708, -708, -708, -708, -708, -708,
+     -708, -708, -708, -708, -708, -708, -708, -708, -708, -708,
+     -708, -708, -708, -708, -708, -708, -708, -708, -708, -708,
+     -708, -708, -708, -708, -708, -708, -708, -708, -708, -708,
+     -708, -708, -708, -708, -708, -708, -708, -708
+    },
+
+    {
+       67, -709, -709, -709, -709, -709, -709, -709, -709, -709,
+     -709, -709, -709, -709, -709, -709, -709, -709, -709, -709,
+     -709, -709, -709, -709, -709, -709, -709, -709, -709, -709,
+
+     -709, -709, -709, -709, -709, -709, -709, -709, -709, -709,
+     -709, -709, -709, -709, -709, -709, -709, -709, -709, -709,
+     -709, -709, -709, -709, -709, -709, -709, -709, -709, -709,
+     -709, -709, -709, -709, -709, -709, -709, -709, -709, -709,
+     -709, -709, -709, -709, -709, -709, -709, -709, -709, -709,
+     -709, -709, -709, -709, -709, -709, -709, -709, -709, -709,
+     -709, -709, -709, -709, -709, -709, -709, -709, -709, -709,
+     -709, -709, -709, -709, -709, -709, -709, -709, -709, -709,
+     -709, -709, -709, -709, -709, -709, -709, -709, -709, -709,
+     -709, -709, -709, -709, -709, -709, -709, -709
+
+    },
+
+    {
+       67, -710, -710, -710, -710, -710, -710, -710, -710, -710,
+     -710, -710, -710, -710, -710, -710, -710, -710, -710, -710,
+     -710, -710, -710, -710, -710, -710, -710, -710, -710, -710,
+     -710, -710, -710, -710, -710, -710, -710, -710, -710, -710,
+     -710, -710, -710, -710, -710, -710, -710, -710, -710, -710,
+     -710, -710, -710, -710, -710, -710, -710, -710, -710, -710,
+     -710, -710, -710, -710, -710, -710, -710, -710, -710, -710,
+     -710, -710, -710, -710, -710, -710, -710, -710, -710, -710,
+     -710, -710, -710, -710, -710, -710, -710, -710, -710, -710,
+     -710, -710, -710, -710, -710, -710, -710, -710, -710, -710,
+
+     -710, -710, -710, -710, -710, -710, -710, -710, -710, -710,
+     -710, -710, -710, -710, -710, -710, -710, -710, -710, -710,
+     -710, -710, -710, -710, -710, -710, -710, -710
+    },
+
+    {
+       67, -711, -711, -711, -711, -711, -711, -711, -711, -711,
+     -711, -711, -711, -711, -711, -711, -711, -711, -711, -711,
+     -711, -711, -711, -711, -711, -711, -711, -711, -711, -711,
+     -711, -711, -711, -711, -711, -711, -711, -711, -711, -711,
+     -711, -711, -711, -711, -711, -711, -711, -711, -711, -711,
+     -711, -711, -711, -711, -711, -711, -711, -711, -711, -711,
+     -711, -711, -711, -711, -711, -711, -711, -711, -711, -711,
+
+     -711, -711, -711, -711, -711, -711, -711, -711, -711, -711,
+     -711, -711, -711, -711, -711, -711, -711, -711, -711, -711,
+     -711, -711, -711, -711, -711, -711, -711, -711, -711, -711,
+     -711, -711, -711, -711, -711, -711, -711, -711, -711, -711,
+     -711, -711, -711, -711, -711, -711, -711, -711, -711, -711,
+     -711, -711, -711, -711, -711, -711, -711, -711
+    },
+
+    {
+       67, -712, -712, -712, -712, -712, -712, -712, -712, -712,
+     -712, -712, -712, -712, -712, -712, -712, -712, -712, -712,
+     -712, -712, -712, -712, -712, -712, -712, -712, -712, -712,
+     -712, -712, -712, -712, -712, -712, -712, -712, -712, -712,
+
+     -712, -712, -712, -712, -712, -712, -712, -712, -712, -712,
+     -712, -712, -712, -712, -712, -712, -712, -712, -712, -712,
+     -712, -712, -712, -712, -712, -712, -712, -712, -712, -712,
+     -712, -712, -712, -712, -712, -712, -712, -712, -712, -712,
+     -712, -712, -712, -712, -712, -712, -712, -712, -712, -712,
+     -712, -712, -712, -712, -712, -712, -712, -712, -712, -712,
+     -712, -712, -712, -712, -712, -712, -712, -712, -712, -712,
+     -712, -712, -712, -712, -712, -712, -712, -712, -712, -712,
+     -712, -712, -712, -712, -712, -712, -712, -712
+    },
+
+    {
+       67, -713, -713, -713, -713, -713, -713, -713, -713, -713,
+
+     -713, -713, -713, -713, -713, -713, -713, -713, -713, -713,
+     -713, -713, -713, -713, -713, -713, -713, -713, -713, -713,
+     -713, -713, -713, -713, -713, -713, -713, -713, -713, -713,
+     -713, -713, -713, -713, -713, -713, -713, -713, -713, -713,
+     -713, -713, -713, -713, -713, -713, -713, -713, -713, -713,
+     -713, -713, -713, -713, -713, -713, -713, -713, -713, -713,
+     -713, -713, -713, -713, -713, -713, -713, -713, -713, -713,
+     -713, -713, -713, -713, -713, -713, -713, -713, -713, -713,
+     -713, -713, -713, -713, -713, -713, -713, -713, -713, -713,
+     -713, -713, -713, -713, -713, -713, -713, -713, -713, -713,
+
+     -713, -713, -713, -713, -713, -713, -713, -713, -713, -713,
+     -713, -713, -713, -713, -713, -713, -713, -713
+    },
+
+    {
+       67, -714, -714, -714, -714, -714, -714, -714, -714, -714,
+     -714, -714, -714, -714, -714, -714, -714, -714, -714, -714,
+     -714, -714, -714, -714, -714, -714, -714, -714, -714, -714,
+     -714, -714, -714, -714, -714, -714, -714, -714, -714, -714,
+     -714, -714, -714, -714, -714, -714, -714, -714, -714, -714,
+     -714, -714, -714, -714, -714, -714, -714, -714, -714, -714,
+     -714, -714, -714, -714, -714, -714, -714, -714, -714, -714,
+     -714, -714, -714, -714, -714, -714, -714, -714, -714, -714,
+
+     -714, -714, -714, -714, -714, -714, -714, -714, -714, -714,
+     -714, -714, -714, -714, -714, -714, -714, -714, -714, -714,
+     -714, -714, -714, -714, -714, -714, -714, -714, -714, -714,
+     -714, -714, -714, -714, -714, -714, -714, -714, -714, -714,
+     -714, -714, -714, -714, -714, -714, -714, -714
+    },
+
+    {
+       67, -715, -715, -715, -715, -715, -715, -715, -715, -715,
+     -715, -715, -715, -715, -715, -715, -715, -715, -715, -715,
+     -715, -715, -715, -715, -715, -715, -715, -715, -715, -715,
+     -715, -715, -715, -715, -715, -715, -715, -715, -715, -715,
+     -715, -715, -715, -715, -715, -715, -715, -715, -715, -715,
+
+     -715, -715, -715, -715, -715, -715, -715, -715, -715, -715,
+     -715, -715, -715, -715, -715, -715, -715, -715, -715, -715,
+     -715, -715, -715, -715, -715, -715, -715, -715, -715, -715,
+     -715, -715, -715, -715, -715, -715, -715, -715, -715, -715,
+     -715, -715, -715, -715, -715, -715, -715, -715, -715, -715,
+     -715, -715, -715, -715, -715, -715, -715, -715, -715, -715,
+     -715, -715, -715, -715, -715, -715, -715, -715, -715, -715,
+     -715, -715, -715, -715, -715, -715, -715, -715
+    },
+
+    {
+       67, -716, -716, -716, -716, -716, -716, -716, -716, -716,
+     -716, -716, -716, -716, -716, -716, -716, -716, -716, -716,
+
+     -716, -716, -716, -716, -716, -716, -716, -716, -716, -716,
+     -716, -716, -716, -716, -716, -716, -716, -716, -716, -716,
+     -716, -716, -716, -716, -716, -716, -716, -716, -716, -716,
+     -716, -716, -716, -716, -716, -716, -716, -716, -716, -716,
+     -716, -716, -716, -716, -716, -716, -716, -716, -716, -716,
+     -716, -716, -716, -716, -716, -716, -716, -716, -716, -716,
+     -716, -716, -716, -716, -716, -716, -716, -716, -716, -716,
+     -716, -716, -716, -716, -716, -716, -716, -716, -716, -716,
+     -716, -716, -716, -716, -716, -716, -716, -716, -716, -716,
+     -716, -716, -716, -716, -716, -716, -716, -716, -716, -716,
+
+     -716, -716, -716, -716, -716, -716, -716, -716
+    },
+
+    {
+       67, -717, -717, -717, -717, -717, -717, -717, -717, -717,
+     -717, -717, -717, -717, -717, -717, -717, -717, -717, -717,
+     -717, -717, -717, -717, -717, -717, -717, -717, -717, -717,
+     -717, -717, -717, -717, -717, -717, -717, -717, -717, -717,
+     -717, -717, -717, -717, -717, -717, -717, -717, -717, -717,
+     -717, -717, -717, -717, -717, -717, -717, -717, -717, -717,
+     -717, -717, -717, -717, -717, -717, -717, -717, -717, -717,
+     -717, -717, -717, -717, -717, -717, -717, -717, -717, -717,
+     -717, -717, -717, -717, -717, -717, -717, -717, -717, -717,
+
+     -717, -717, -717, -717, -717, -717, -717, -717, -717, -717,
+     -717, -717, -717, -717, -717, -717, -717, -717, -717, -717,
+     -717, -717, -717, -717, -717, -717, -717, -717, -717, -717,
+     -717, -717, -717, -717, -717, -717, -717, -717
+    },
+
+    {
+       67, -718, -718, -718, -718, -718, -718, -718, -718, -718,
+     -718, -718, -718, -718, -718, -718, -718, -718, -718, -718,
+     -718, -718, -718, -718, -718, -718, -718, -718, -718, -718,
+     -718, -718, -718, -718, -718, -718, -718, -718, -718, -718,
+     -718, -718, -718, -718, -718, -718, -718, -718, -718, -718,
+     -718, -718, -718, -718, -718, -718, -718, -718, -718, -718,
+
+     -718, -718, -718, -718, -718, -718, -718, -718, -718, -718,
+     -718, -718, -718, -718, -718, -718, -718, -718, -718, -718,
+     -718, -718, -718, -718, -718, -718, -718, -718, -718, -718,
+     -718, -718, -718, -718, -718, -718, -718, -718, -718, -718,
+     -718, -718, -718, -718, -718, -718, -718, -718, -718, -718,
+     -718, -718, -718, -718, -718, -718, -718, -718, -718, -718,
+     -718, -718, -718, -718, -718, -718, -718, -718
+    },
+
+    {
+       67, -719, -719, -719, -719, -719, -719, -719, -719, -719,
+     -719, -719, -719, -719, -719, -719, -719, -719, -719, -719,
+     -719, -719, -719, -719, -719, -719, -719, -719, -719, -719,
+
+     -719, -719, -719, -719, -719, -719, -719, -719, -719, -719,
+     -719, -719, -719, -719, -719, -719, -719, -719, -719, -719,
+     -719, -719, -719, -719, -719, -719, -719, -719, -719, -719,
+     -719, -719, -719, -719, -719, -719, -719, -719, -719, -719,
+     -719, -719, -719, -719, -719, -719, -719, -719, -719, -719,
+     -719, -719, -719, -719, -719, -719, -719, -719, -719, -719,
+     -719, -719, -719, -719, -719, -719, -719, -719, -719, -719,
+     -719, -719, -719, -719, -719, -719, -719, -719, -719, -719,
+     -719, -719, -719, -719, -719, -719, -719, -719, -719, -719,
+     -719, -719, -719, -719, -719, -719, -719, -719
+
+    },
+
+    {
+       67, -720, -720, -720, -720, -720, -720, -720, -720, -720,
+     -720, -720, -720, -720, -720, -720, -720, -720, -720, -720,
+     -720, -720, -720, -720, -720, -720, -720, -720, -720, -720,
+     -720, -720, -720, -720, -720, -720, -720, -720, -720, -720,
+     -720, -720, -720, -720, -720, -720, -720, -720, -720, -720,
+     -720, -720, -720, -720, -720, -720, -720, -720, -720, -720,
+     -720, -720, -720, -720, -720, -720, -720, -720, -720, -720,
+     -720, -720, -720, -720, -720, -720, -720, -720, -720, -720,
+     -720, -720, -720, -720, -720, -720, -720, -720, -720, -720,
+     -720, -720, -720, -720, -720, -720, -720, -720, -720, -720,
+
+     -720, -720, -720, -720, -720, -720, -720, -720, -720, -720,
+     -720, -720, -720, -720, -720, -720, -720, -720, -720, -720,
+     -720, -720, -720, -720, -720, -720, -720, -720
+    },
+
+    {
+       67, -721, -721, -721, -721, -721, -721, -721, -721, -721,
+     -721, -721, -721, -721, -721, -721, -721, -721, -721, -721,
+     -721, -721, -721, -721, -721, -721, -721, -721, -721, -721,
+     -721, -721, -721, -721, -721, -721, -721, -721, -721, -721,
+     -721, -721, -721, -721, -721, -721, -721, -721, -721, -721,
+     -721, -721, -721, -721, -721, -721, -721, -721, -721, -721,
+     -721, -721, -721, -721, -721, -721, -721, -721, -721, -721,
+
+     -721, -721, -721, -721, -721, -721, -721, -721, -721, -721,
+     -721, -721, -721, -721, -721, -721, -721, -721, -721, -721,
+     -721, -721, -721, -721, -721, -721, -721, -721, -721, -721,
+     -721, -721, -721, -721, -721, -721, -721, -721, -721, -721,
+     -721, -721, -721, -721, -721, -721, -721, -721, -721, -721,
+     -721, -721, -721, -721, -721, -721, -721, -721
+    },
+
+    {
+       67, -722, -722, -722, -722, -722, -722, -722, -722, -722,
+     -722, -722, -722, -722, -722, -722, -722, -722, -722, -722,
+     -722, -722, -722, -722, -722, -722, -722, -722, -722, -722,
+     -722, -722, -722, -722, -722, -722, -722, -722, -722, -722,
+
+     -722, -722, -722, -722, -722, -722, -722, -722, -722, -722,
+     -722, -722, -722, -722, -722, -722, -722, -722, -722, -722,
+     -722, -722, -722, -722, -722, -722, -722, -722, -722, -722,
+     -722, -722, -722, -722, -722, -722, -722, -722, -722, -722,
+     -722, -722, -722, -722, -722, -722, -722, -722, -722, -722,
+     -722, -722, -722, -722, -722, -722, -722, -722, -722, -722,
+     -722, -722, -722, -722, -722, -722, -722, -722, -722, -722,
+     -722, -722, -722, -722, -722, -722, -722, -722, -722, -722,
+     -722, -722, -722, -722, -722, -722, -722, -722
+    },
+
+    {
+       67, -723, -723, -723, -723, -723, -723, -723, -723, -723,
+
+     -723, -723, -723, -723, -723, -723, -723, -723, -723, -723,
+     -723, -723, -723, -723, -723, -723, -723, -723, -723, -723,
+     -723, -723, -723, -723, -723, -723, -723, -723, -723, -723,
+     -723, -723, -723, -723, -723, -723, -723, -723, -723, -723,
+     -723, -723, -723, -723, -723, -723, -723, -723, -723, -723,
+     -723, -723, -723, -723, -723, -723, -723, -723, -723, -723,
+     -723,  764, -723, -723, -723, -723, -723, -723, -723, -723,
+     -723, -723, -723, -723, -723, -723, -723, -723, -723, -723,
+     -723, -723, -723, -723, -723, -723, -723, -723, -723, -723,
+     -723, -723, -723, -723, -723, -723, -723, -723, -723, -723,
+
+     -723, -723, -723, -723, -723, -723, -723, -723, -723, -723,
+     -723, -723, -723, -723, -723, -723, -723, -723
+    },
+
+    {
+       67, -724, -724, -724, -724, -724, -724, -724, -724, -724,
+     -724, -724, -724, -724, -724, -724, -724, -724, -724, -724,
+     -724, -724, -724, -724, -724, -724, -724, -724, -724, -724,
+     -724, -724, -724, -724, -724, -724, -724, -724, -724, -724,
+     -724, -724, -724, -724, -724, -724, -724, -724, -724, -724,
+     -724, -724, -724, -724, -724, -724, -724, -724, -724, -724,
+     -724, -724, -724, -724, -724, -724, -724, -724, -724, -724,
+     -724, -724, -724, -724, -724, -724, -724, -724, -724, -724,
+
+     -724, -724, -724,  765, -724, -724, -724, -724, -724, -724,
+     -724, -724, -724, -724, -724, -724, -724, -724, -724, -724,
+     -724, -724, -724, -724, -724, -724, -724, -724, -724, -724,
+     -724, -724, -724, -724, -724, -724, -724, -724, -724, -724,
+     -724, -724, -724, -724, -724, -724, -724, -724
+    },
+
+    {
+       67, -725, -725, -725, -725, -725, -725, -725, -725, -725,
+     -725, -725, -725, -725, -725, -725, -725, -725, -725, -725,
+     -725, -725, -725, -725, -725, -725, -725, -725, -725, -725,
+     -725, -725,  766, -725, -725, -725, -725, -725, -725, -725,
+     -725, -725, -725, -725, -725, -725, -725, -725, -725, -725,
+
+     -725, -725, -725, -725, -725, -725, -725, -725, -725, -725,
+     -725, -725, -725, -725, -725, -725, -725, -725, -725, -725,
+     -725, -725, -725, -725, -725, -725, -725, -725, -725, -725,
+     -725, -725, -725, -725, -725, -725, -725, -725, -725, -725,
+     -725, -725, -725, -725, -725, -725, -725, -725, -725, -725,
+     -725, -725, -725, -725, -725, -725, -725, -725, -725, -725,
+     -725, -725, -725, -725, -725, -725, -725, -725, -725, -725,
+     -725, -725, -725, -725, -725, -725, -725, -725
+    },
+
+    {
+       67, -726, -726, -726, -726, -726, -726, -726, -726, -726,
+     -726, -726, -726, -726, -726, -726, -726, -726, -726, -726,
+
+     -726, -726, -726, -726, -726, -726, -726, -726, -726, -726,
+     -726, -726,  767, -726, -726, -726, -726, -726, -726, -726,
+     -726, -726, -726, -726, -726, -726, -726, -726, -726, -726,
+     -726, -726, -726, -726, -726, -726, -726, -726, -726, -726,
+     -726, -726, -726, -726, -726, -726, -726, -726, -726, -726,
+     -726, -726, -726, -726, -726, -726, -726, -726, -726, -726,
+     -726, -726, -726, -726, -726, -726, -726, -726, -726, -726,
+     -726, -726, -726, -726, -726, -726, -726, -726, -726, -726,
+     -726, -726, -726, -726, -726, -726, -726, -726, -726, -726,
+     -726, -726, -726, -726, -726, -726, -726, -726, -726, -726,
+
+     -726, -726, -726, -726, -726, -726, -726, -726
+    },
+
+    {
+       67, -727, -727, -727, -727, -727, -727, -727, -727, -727,
+     -727, -727, -727, -727, -727, -727, -727, -727, -727, -727,
+     -727, -727, -727, -727, -727, -727, -727, -727, -727, -727,
+     -727, -727,  768, -727, -727, -727, -727, -727, -727, -727,
+     -727, -727, -727, -727, -727, -727, -727, -727, -727, -727,
+     -727, -727, -727, -727, -727, -727, -727, -727, -727, -727,
+     -727, -727, -727, -727, -727, -727, -727, -727, -727, -727,
+     -727, -727, -727, -727, -727, -727, -727, -727, -727, -727,
+     -727, -727, -727, -727, -727, -727, -727, -727, -727, -727,
+
+     -727, -727, -727, -727, -727, -727, -727, -727, -727, -727,
+     -727, -727, -727, -727, -727, -727, -727, -727, -727, -727,
+     -727, -727, -727, -727, -727, -727, -727, -727, -727, -727,
+     -727, -727, -727, -727, -727, -727, -727, -727
+    },
+
+    {
+       67, -728, -728, -728, -728, -728, -728, -728, -728, -728,
+     -728, -728, -728, -728, -728, -728, -728, -728, -728, -728,
+     -728, -728, -728, -728, -728, -728, -728, -728, -728, -728,
+     -728, -728,  769, -728, -728, -728, -728, -728, -728, -728,
+     -728, -728, -728, -728, -728, -728, -728, -728, -728, -728,
+     -728, -728, -728, -728, -728, -728, -728, -728, -728, -728,
+
+     -728, -728, -728, -728, -728, -728, -728, -728, -728, -728,
+     -728, -728, -728, -728, -728, -728, -728, -728, -728, -728,
+     -728, -728, -728, -728, -728, -728, -728, -728, -728, -728,
+     -728, -728, -728, -728, -728, -728, -728, -728, -728, -728,
+     -728, -728, -728, -728, -728, -728, -728, -728, -728, -728,
+     -728, -728, -728, -728, -728, -728, -728, -728, -728, -728,
+     -728, -728, -728, -728, -728, -728, -728, -728
+    },
+
+    {
+       67, -729, -729, -729, -729, -729, -729, -729, -729, -729,
+     -729, -729, -729, -729, -729, -729, -729, -729, -729, -729,
+     -729, -729, -729, -729, -729, -729, -729, -729, -729, -729,
+
+     -729, -729,  770, -729, -729, -729, -729, -729, -729, -729,
+     -729, -729, -729, -729, -729, -729, -729, -729, -729, -729,
+     -729, -729, -729, -729, -729, -729, -729, -729, -729, -729,
+     -729, -729, -729, -729, -729, -729, -729, -729, -729, -729,
+     -729, -729, -729, -729, -729, -729, -729, -729, -729, -729,
+     -729, -729, -729, -729, -729, -729, -729, -729, -729, -729,
+     -729, -729, -729, -729, -729, -729, -729, -729, -729, -729,
+     -729, -729, -729, -729, -729, -729, -729, -729, -729, -729,
+     -729, -729, -729, -729, -729, -729, -729, -729, -729, -729,
+     -729, -729, -729, -729, -729, -729, -729, -729
+
+    },
+
+    {
+       67, -730, -730, -730, -730, -730, -730, -730, -730, -730,
+     -730, -730, -730, -730, -730, -730, -730, -730, -730, -730,
+     -730, -730, -730, -730, -730, -730, -730, -730, -730, -730,
+     -730, -730, -730, -730, -730, -730, -730, -730, -730, -730,
+     -730, -730, -730, -730, -730, -730, -730, -730, -730, -730,
+     -730, -730, -730, -730, -730, -730, -730, -730, -730, -730,
+     -730, -730, -730, -730, -730, -730, -730, -730, -730, -730,
+     -730, -730, -730, -730, -730, -730, -730, -730, -730, -730,
+     -730, -730, -730, -730, -730, -730, -730, -730, -730, -730,
+     -730, -730, -730, -730, -730, -730, -730, -730, -730, -730,
+
+     -730, -730, -730, -730, -730, -730, -730, -730, -730, -730,
+     -730, -730, -730, -730, -730, -730, -730, -730, -730, -730,
+     -730, -730, -730, -730, -730, -730, -730, -730
+    },
+
+    {
+       67, -731, -731, -731, -731, -731, -731, -731, -731, -731,
+     -731, -731, -731, -731, -731, -731, -731, -731, -731, -731,
+     -731, -731, -731, -731, -731, -731, -731, -731, -731, -731,
+     -731, -731, -731, -731, -731, -731, -731, -731, -731, -731,
+     -731, -731, -731, -731, -731, -731, -731, -731, -731, -731,
+     -731, -731, -731, -731, -731, -731, -731, -731, -731, -731,
+     -731, -731, -731, -731, -731, -731, -731, -731, -731, -731,
+
+     -731, -731, -731, -731, -731, -731, -731, -731, -731, -731,
+     -731, -731, -731, -731, -731, -731, -731, -731, -731, -731,
+     -731, -731, -731, -731, -731, -731, -731, -731, -731, -731,
+     -731, -731, -731, -731, -731, -731, -731, -731, -731, -731,
+     -731, -731, -731, -731, -731, -731, -731, -731, -731, -731,
+     -731, -731, -731, -731, -731, -731, -731, -731
+    },
+
+    {
+       67, -732, -732, -732, -732, -732, -732, -732, -732, -732,
+     -732, -732, -732, -732, -732, -732, -732, -732, -732, -732,
+     -732, -732, -732, -732, -732, -732, -732, -732, -732, -732,
+     -732, -732, -732, -732, -732, -732, -732, -732, -732, -732,
+
+     -732, -732, -732, -732, -732, -732, -732, -732, -732, -732,
+     -732, -732, -732, -732, -732, -732, -732, -732, -732, -732,
+     -732, -732, -732, -732, -732, -732, -732, -732, -732, -732,
+     -732, -732, -732, -732, -732, -732, -732, -732, -732, -732,
+     -732, -732, -732, -732, -732, -732, -732, -732, -732, -732,
+     -732, -732, -732, -732, -732, -732, -732, -732, -732, -732,
+     -732, -732, -732, -732, -732, -732, -732, -732, -732, -732,
+     -732, -732, -732, -732, -732, -732, -732, -732, -732, -732,
+     -732, -732, -732, -732, -732, -732, -732, -732
+    },
+
+    {
+       67, -733, -733, -733, -733, -733, -733, -733, -733, -733,
+
+     -733, -733, -733, -733, -733, -733, -733, -733, -733, -733,
+     -733, -733, -733, -733, -733, -733, -733, -733, -733, -733,
+     -733, -733,  771, -733, -733, -733, -733, -733, -733, -733,
+     -733, -733, -733, -733, -733, -733, -733, -733, -733, -733,
+     -733, -733, -733, -733, -733, -733, -733, -733, -733, -733,
+     -733, -733, -733, -733, -733, -733, -733, -733, -733, -733,
+     -733, -733, -733, -733, -733, -733, -733, -733, -733, -733,
+     -733, -733, -733, -733, -733, -733, -733, -733, -733, -733,
+     -733, -733, -733, -733, -733, -733, -733, -733, -733, -733,
+     -733, -733, -733, -733, -733, -733, -733, -733, -733, -733,
+
+     -733, -733, -733, -733, -733, -733, -733, -733, -733, -733,
+     -733, -733, -733, -733, -733, -733, -733, -733
+    },
+
+    {
+       67, -734, -734, -734, -734, -734, -734, -734, -734, -734,
+     -734, -734, -734, -734, -734, -734, -734, -734, -734, -734,
+     -734, -734, -734, -734, -734, -734, -734, -734, -734, -734,
+     -734, -734,  772, -734, -734, -734, -734, -734, -734, -734,
+     -734, -734, -734, -734, -734, -734, -734, -734, -734, -734,
+     -734, -734, -734, -734, -734, -734, -734, -734, -734, -734,
+     -734, -734, -734, -734, -734, -734, -734, -734, -734, -734,
+     -734, -734, -734, -734, -734, -734, -734, -734, -734, -734,
+
+     -734, -734, -734, -734, -734, -734, -734, -734, -734, -734,
+     -734, -734, -734, -734, -734, -734, -734, -734, -734, -734,
+     -734, -734, -734, -734, -734, -734, -734, -734, -734, -734,
+     -734, -734, -734, -734, -734, -734, -734, -734, -734, -734,
+     -734, -734, -734, -734, -734, -734, -734, -734
+    },
+
+    {
+       67, -735, -735, -735, -735, -735, -735, -735, -735, -735,
+     -735, -735, -735, -735, -735, -735, -735, -735, -735, -735,
+     -735, -735, -735, -735, -735, -735, -735, -735, -735, -735,
+     -735, -735, -735, -735, -735, -735, -735, -735, -735, -735,
+     -735, -735, -735, -735, -735, -735, -735, -735, -735, -735,
+
+     -735, -735, -735, -735, -735, -735, -735, -735, -735, -735,
+     -735, -735, -735, -735, -735, -735, -735, -735, -735, -735,
+     -735, -735, -735, -735, -735, -735, -735, -735, -735, -735,
+     -735, -735, -735, -735, -735, -735, -735, -735,  773,  774,
+      775, -735, -735, -735, -735, -735, -735, -735, -735, -735,
+     -735, -735, -735, -735, -735, -735, -735, -735, -735, -735,
+     -735, -735, -735, -735, -735, -735, -735, -735, -735, -735,
+     -735, -735, -735, -735, -735, -735, -735, -735
+    },
+
+    {
+       67, -736, -736, -736, -736, -736, -736, -736, -736, -736,
+     -736, -736, -736, -736, -736, -736, -736, -736, -736, -736,
+
+     -736, -736, -736, -736, -736, -736, -736, -736, -736, -736,
+     -736, -736, -736, -736, -736, -736, -736, -736, -736, -736,
+     -736, -736, -736, -736, -736, -736, -736, -736, -736, -736,
+     -736, -736, -736, -736, -736, -736, -736, -736, -736, -736,
+     -736, -736, -736, -736, -736, -736, -736, -736, -736, -736,
+     -736, -736, -736, -736, -736, -736, -736, -736, -736, -736,
+     -736, -736, -736,  776, -736, -736, -736, -736, -736, -736,
+     -736, -736, -736, -736, -736, -736, -736, -736, -736, -736,
+     -736, -736, -736, -736, -736, -736, -736, -736, -736, -736,
+     -736, -736, -736, -736, -736, -736, -736, -736, -736, -736,
+
+     -736, -736, -736, -736, -736, -736, -736, -736
+    },
+
+    {
+       67, -737, -737, -737, -737, -737, -737, -737, -737, -737,
+     -737, -737, -737, -737, -737, -737, -737, -737, -737, -737,
+     -737, -737, -737, -737, -737, -737, -737, -737, -737, -737,
+     -737, -737, -737, -737, -737, -737, -737, -737, -737, -737,
+     -737, -737, -737, -737, -737, -737, -737, -737, -737, -737,
+     -737, -737, -737, -737, -737, -737, -737, -737, -737, -737,
+     -737, -737, -737, -737, -737, -737, -737, -737, -737, -737,
+     -737, -737, -737, -737, -737, -737, -737, -737, -737, -737,
+     -737, -737, -737, -737, -737, -737, -737, -737, -737, -737,
+
+     -737, -737, -737, -737, -737, -737, -737, -737, -737, -737,
+     -737, -737, -737, -737, -737, -737, -737, -737, -737, -737,
+     -737, -737, -737, -737, -737, -737, -737, -737, -737, -737,
+     -737, -737, -737, -737, -737, -737, -737, -737
+    },
+
+    {
+       67, -738, -738, -738, -738, -738, -738, -738, -738, -738,
+     -738, -738, -738, -738, -738, -738, -738, -738, -738, -738,
+     -738, -738, -738, -738, -738, -738, -738, -738, -738, -738,
+     -738, -738, -738, -738, -738, -738, -738, -738, -738, -738,
+     -738, -738, -738, -738, -738, -738, -738, -738, -738, -738,
+     -738, -738, -738, -738, -738, -738, -738, -738, -738, -738,
+
+     -738, -738, -738, -738, -738, -738, -738, -738, -738, -738,
+     -738, -738, -738, -738, -738, -738, -738, -738, -738, -738,
+     -738,  777, -738, -738, -738, -738, -738, -738, -738, -738,
+     -738, -738, -738, -738, -738, -738, -738, -738, -738, -738,
+     -738, -738, -738, -738, -738, -738, -738, -738, -738, -738,
+     -738, -738, -738, -738, -738, -738, -738, -738, -738, -738,
+     -738, -738, -738, -738, -738, -738, -738, -738
+    },
+
+    {
+       67, -739, -739, -739, -739, -739, -739, -739, -739, -739,
+     -739, -739, -739, -739, -739, -739, -739, -739, -739, -739,
+     -739, -739, -739, -739, -739, -739, -739, -739, -739, -739,
+
+     -739, -739, -739, -739, -739, -739, -739, -739, -739, -739,
+     -739, -739, -739, -739, -739, -739, -739, -739, -739, -739,
+     -739, -739, -739, -739, -739, -739, -739, -739, -739, -739,
+     -739, -739, -739, -739, -739, -739, -739, -739, -739, -739,
+     -739, -739, -739, -739, -739, -739, -739, -739, -739, -739,
+     -739, -739, -739, -739, -739, -739, -739, -739, -739, -739,
+     -739, -739, -739, -739, -739, -739, -739, -739, -739, -739,
+     -739, -739, -739, -739, -739, -739, -739, -739, -739, -739,
+     -739, -739, -739, -739, -739, -739, -739, -739, -739, -739,
+     -739, -739, -739, -739, -739, -739, -739, -739
+
+    },
+
+    {
+       67, -740, -740, -740, -740, -740, -740, -740, -740, -740,
+     -740, -740, -740, -740, -740, -740, -740, -740, -740, -740,
+     -740, -740, -740, -740, -740, -740, -740, -740, -740, -740,
+     -740, -740, -740, -740, -740, -740, -740, -740, -740, -740,
+     -740, -740, -740, -740, -740, -740, -740, -740, -740, -740,
+     -740, -740, -740, -740, -740, -740, -740, -740, -740, -740,
+     -740, -740, -740, -740, -740, -740, -740, -740, -740, -740,
+     -740, -740, -740, -740, -740, -740, -740, -740, -740, -740,
+     -740, -740, -740, -740, -740, -740, -740, -740, -740, -740,
+     -740, -740, -740, -740, -740, -740, -740, -740, -740, -740,
+
+     -740, -740, -740, -740, -740, -740, -740, -740, -740, -740,
+     -740, -740, -740, -740, -740, -740, -740, -740, -740, -740,
+     -740, -740, -740, -740, -740, -740, -740, -740
+    },
+
+    {
+       67, -741, -741, -741, -741, -741, -741, -741, -741, -741,
+     -741, -741, -741, -741, -741, -741, -741, -741, -741, -741,
+     -741, -741, -741, -741, -741, -741, -741, -741, -741, -741,
+     -741, -741, -741, -741, -741, -741, -741, -741, -741, -741,
+     -741, -741, -741, -741, -741, -741, -741, -741, -741, -741,
+     -741, -741, -741, -741, -741, -741, -741, -741, -741, -741,
+     -741, -741, -741, -741, -741, -741, -741, -741, -741, -741,
+
+     -741, -741, -741, -741, -741, -741, -741, -741, -741, -741,
+     -741, -741, -741, -741, -741, -741, -741, -741, -741, -741,
+     -741, -741, -741, -741, -741, -741, -741, -741, -741, -741,
+     -741, -741, -741, -741, -741, -741, -741, -741, -741, -741,
+     -741, -741, -741, -741, -741, -741, -741, -741, -741, -741,
+     -741, -741, -741, -741, -741, -741, -741, -741
+    },
+
+    {
+       67, -742, -742, -742, -742, -742, -742, -742, -742, -742,
+     -742, -742, -742, -742, -742, -742, -742, -742, -742, -742,
+     -742, -742, -742, -742, -742, -742, -742, -742, -742, -742,
+     -742, -742, -742, -742, -742, -742, -742, -742, -742, -742,
+
+     -742, -742, -742, -742, -742, -742, -742, -742, -742, -742,
+     -742, -742, -742, -742, -742, -742, -742, -742, -742, -742,
+     -742, -742, -742, -742, -742, -742, -742, -742, -742, -742,
+     -742, -742, -742, -742, -742, -742, -742, -742, -742, -742,
+     -742, -742, -742, -742, -742, -742, -742, -742, -742, -742,
+     -742, -742, -742, -742, -742, -742, -742, -742, -742, -742,
+     -742, -742, -742, -742, -742, -742, -742, -742, -742, -742,
+     -742, -742, -742, -742, -742, -742, -742, -742, -742, -742,
+     -742, -742, -742, -742, -742, -742, -742, -742
+    },
+
+    {
+       67, -743, -743, -743, -743, -743, -743, -743, -743, -743,
+
+     -743, -743, -743, -743, -743, -743, -743, -743, -743, -743,
+     -743, -743, -743, -743, -743, -743, -743, -743, -743, -743,
+     -743, -743, -743, -743, -743, -743, -743, -743, -743, -743,
+     -743, -743, -743, -743, -743, -743, -743, -743, -743, -743,
+     -743, -743, -743, -743, -743, -743, -743, -743, -743, -743,
+     -743, -743, -743, -743, -743, -743, -743, -743, -743, -743,
+     -743, -743, -743, -743, -743, -743, -743, -743, -743, -743,
+     -743, -743, -743, -743, -743, -743, -743, -743, -743, -743,
+     -743, -743, -743, -743, -743, -743, -743, -743, -743, -743,
+     -743, -743, -743, -743, -743, -743, -743, -743, -743, -743,
+
+     -743, -743, -743, -743, -743, -743, -743, -743, -743, -743,
+     -743, -743, -743, -743, -743, -743, -743, -743
+    },
+
+    {
+       67, -744, -744, -744, -744, -744, -744, -744, -744, -744,
+     -744, -744, -744, -744, -744, -744, -744, -744, -744, -744,
+     -744, -744, -744, -744, -744, -744, -744, -744, -744, -744,
+     -744, -744,  778, -744, -744, -744, -744, -744, -744, -744,
+     -744, -744, -744, -744, -744, -744, -744, -744, -744, -744,
+     -744, -744, -744, -744, -744, -744, -744, -744, -744, -744,
+     -744, -744, -744, -744, -744, -744, -744, -744, -744, -744,
+     -744, -744, -744, -744, -744, -744, -744, -744, -744, -744,
+
+     -744, -744, -744, -744, -744, -744, -744, -744, -744, -744,
+     -744, -744, -744, -744, -744, -744, -744, -744, -744, -744,
+     -744, -744, -744, -744, -744, -744, -744, -744, -744, -744,
+     -744, -744, -744, -744, -744, -744, -744, -744, -744, -744,
+     -744, -744, -744, -744, -744, -744, -744, -744
+    },
+
+    {
+       67, -745, -745, -745, -745, -745, -745, -745, -745, -745,
+     -745, -745, -745, -745, -745, -745, -745, -745, -745, -745,
+     -745, -745, -745, -745, -745, -745, -745, -745, -745, -745,
+     -745, -745, -745, -745, -745, -745, -745, -745, -745, -745,
+     -745, -745, -745, -745, -745, -745, -745, -745, -745, -745,
+
+     -745, -745, -745, -745, -745, -745, -745, -745, -745, -745,
+     -745, -745, -745, -745, -745, -745, -745, -745, -745, -745,
+     -745, -745, -745, -745, -745, -745, -745, -745, -745, -745,
+     -745, -745, -745, -745, -745, -745, -745, -745, -745, -745,
+     -745, -745, -745, -745, -745, -745, -745, -745, -745, -745,
+     -745, -745, -745, -745, -745, -745, -745, -745, -745, -745,
+     -745, -745, -745, -745, -745, -745, -745, -745, -745, -745,
+     -745, -745, -745, -745, -745, -745, -745, -745
+    },
+
+    {
+       67, -746, -746, -746, -746, -746, -746, -746, -746, -746,
+     -746, -746, -746, -746, -746, -746, -746, -746, -746, -746,
+
+     -746, -746, -746, -746, -746, -746, -746, -746, -746, -746,
+     -746, -746, -746, -746, -746, -746, -746, -746, -746, -746,
+     -746, -746, -746, -746, -746, -746, -746, -746, -746, -746,
+     -746, -746, -746, -746, -746, -746, -746, -746, -746, -746,
+     -746, -746, -746, -746, -746, -746, -746, -746, -746, -746,
+     -746, -746, -746, -746, -746, -746, -746, -746, -746, -746,
+     -746, -746, -746, -746, -746, -746, -746, -746, -746, -746,
+     -746, -746, -746, -746, -746, -746, -746, -746, -746, -746,
+     -746, -746, -746, -746, -746, -746, -746, -746, -746, -746,
+     -746, -746, -746, -746, -746, -746, -746, -746, -746, -746,
+
+     -746, -746, -746, -746, -746, -746, -746, -746
+    },
+
+    {
+       67, -747, -747, -747, -747, -747, -747, -747, -747, -747,
+     -747, -747, -747, -747, -747, -747, -747, -747, -747, -747,
+     -747, -747, -747, -747, -747, -747, -747, -747, -747, -747,
+     -747, -747,  779, -747, -747, -747, -747, -747, -747, -747,
+     -747, -747, -747, -747, -747, -747, -747, -747, -747, -747,
+     -747, -747, -747, -747, -747, -747, -747, -747, -747, -747,
+     -747, -747, -747, -747, -747, -747, -747, -747, -747, -747,
+     -747, -747, -747, -747, -747, -747, -747, -747, -747, -747,
+     -747, -747, -747, -747, -747, -747, -747, -747, -747, -747,
+
+     -747, -747, -747, -747, -747, -747, -747, -747, -747, -747,
+     -747, -747, -747, -747, -747, -747, -747, -747, -747, -747,
+     -747, -747, -747, -747, -747, -747, -747, -747, -747, -747,
+     -747, -747, -747, -747, -747, -747, -747, -747
+    },
+
+    {
+       67, -748, -748, -748, -748, -748, -748, -748, -748, -748,
+     -748, -748, -748, -748, -748, -748, -748, -748, -748, -748,
+     -748, -748, -748, -748, -748, -748, -748, -748, -748, -748,
+     -748, -748,  780, -748, -748, -748, -748, -748, -748, -748,
+     -748, -748, -748, -748, -748, -748, -748, -748, -748, -748,
+     -748, -748, -748, -748, -748, -748, -748, -748, -748, -748,
+
+     -748, -748, -748, -748, -748, -748, -748, -748, -748, -748,
+     -748, -748, -748, -748, -748, -748, -748, -748, -748, -748,
+     -748, -748, -748, -748, -748, -748, -748, -748, -748, -748,
+     -748, -748, -748, -748, -748, -748, -748, -748, -748, -748,
+     -748, -748, -748, -748, -748, -748, -748, -748, -748, -748,
+     -748, -748, -748, -748, -748, -748, -748, -748, -748, -748,
+     -748, -748, -748, -748, -748, -748, -748, -748
+    },
+
+    {
+       67, -749, -749, -749, -749, -749, -749, -749, -749, -749,
+     -749, -749, -749, -749, -749, -749, -749, -749, -749, -749,
+     -749, -749, -749, -749, -749, -749, -749, -749, -749, -749,
+
+     -749, -749,  781, -749, -749, -749, -749, -749, -749, -749,
+     -749, -749, -749, -749, -749, -749, -749, -749, -749, -749,
+     -749, -749, -749, -749, -749, -749, -749, -749, -749, -749,
+     -749, -749, -749, -749, -749, -749, -749, -749, -749, -749,
+     -749, -749, -749, -749, -749, -749, -749, -749, -749, -749,
+     -749, -749, -749, -749, -749, -749, -749, -749, -749, -749,
+     -749, -749, -749, -749, -749, -749, -749, -749, -749, -749,
+     -749, -749, -749, -749, -749, -749, -749, -749, -749, -749,
+     -749, -749, -749, -749, -749, -749, -749, -749, -749, -749,
+     -749, -749, -749, -749, -749, -749, -749, -749
+
+    },
+
+    {
+       67, -750, -750, -750, -750, -750, -750, -750, -750, -750,
+     -750, -750, -750, -750, -750, -750, -750, -750, -750, -750,
+     -750, -750, -750, -750, -750, -750, -750, -750, -750, -750,
+     -750, -750,  782, -750, -750, -750, -750, -750, -750, -750,
+     -750, -750, -750, -750, -750, -750, -750, -750, -750, -750,
+     -750, -750, -750, -750, -750, -750, -750, -750, -750, -750,
+     -750, -750, -750, -750, -750,  782,  782,  782,  782,  782,
+      782,  782,  782,  782,  782,  782,  782,  782,  782,  782,
+      782,  782,  782,  782,  782,  782,  782,  782,  782,  782,
+      782, -750, -750, -750, -750, -750, -750, -750, -750, -750,
+
+     -750, -750, -750, -750, -750, -750, -750, -750, -750, -750,
+     -750, -750, -750, -750, -750, -750, -750, -750, -750, -750,
+     -750, -750, -750, -750, -750, -750, -750, -750
+    },
+
+    {
+       67, -751, -751, -751, -751, -751, -751, -751, -751, -751,
+     -751, -751, -751, -751, -751, -751, -751, -751, -751, -751,
+     -751, -751, -751, -751, -751, -751, -751, -751, -751, -751,
+     -751, -751,  783, -751, -751, -751, -751, -751, -751, -751,
+     -751, -751, -751, -751, -751, -751, -751, -751, -751, -751,
+     -751, -751, -751, -751, -751, -751, -751, -751, -751, -751,
+     -751, -751, -751, -751, -751,  783,  783,  783,  783,  783,
+
+      783,  783,  783,  783,  783,  783,  783,  783,  783,  783,
+      783,  783,  783,  783,  783,  783,  783,  783,  783,  783,
+      783, -751, -751, -751, -751, -751, -751, -751, -751, -751,
+     -751, -751, -751, -751, -751, -751, -751, -751, -751, -751,
+     -751, -751, -751, -751, -751, -751, -751, -751, -751, -751,
+     -751, -751, -751, -751, -751, -751, -751, -751
+    },
+
+    {
+       67, -752, -752, -752, -752, -752, -752, -752, -752, -752,
+     -752, -752, -752, -752, -752, -752, -752, -752, -752, -752,
+     -752, -752, -752, -752, -752, -752, -752, -752, -752, -752,
+     -752, -752,  784, -752, -752, -752, -752, -752, -752, -752,
+
+     -752, -752, -752, -752, -752, -752, -752, -752, -752, -752,
+     -752, -752, -752, -752, -752, -752, -752, -752, -752, -752,
+     -752, -752, -752, -752, -752, -752, -752, -752, -752, -752,
+     -752, -752, -752, -752, -752, -752, -752, -752, -752, -752,
+     -752, -752, -752, -752, -752, -752, -752, -752, -752, -752,
+     -752, -752, -752, -752, -752, -752, -752, -752, -752, -752,
+     -752, -752, -752, -752, -752, -752, -752, -752, -752, -752,
+     -752, -752, -752, -752, -752, -752, -752, -752, -752, -752,
+     -752, -752, -752, -752, -752, -752, -752, -752
+    },
+
+    {
+       67, -753, -753, -753, -753, -753, -753, -753, -753, -753,
+
+     -753, -753, -753, -753, -753, -753, -753, -753, -753, -753,
+     -753, -753, -753, -753, -753, -753, -753, -753, -753, -753,
+     -753, -753,  785, -753, -753, -753, -753, -753, -753, -753,
+     -753, -753, -753, -753, -753, -753, -753, -753, -753, -753,
+     -753, -753, -753, -753, -753, -753, -753, -753, -753, -753,
+     -753, -753, -753, -753, -753, -753, -753, -753, -753, -753,
+     -753, -753, -753, -753, -753, -753, -753, -753, -753, -753,
+     -753, -753, -753, -753, -753, -753, -753, -753, -753, -753,
+     -753, -753, -753, -753, -753, -753, -753, -753, -753, -753,
+     -753, -753, -753, -753, -753, -753, -753, -753, -753, -753,
+
+     -753, -753, -753, -753, -753, -753, -753, -753, -753, -753,
+     -753, -753, -753, -753, -753, -753, -753, -753
+    },
+
+    {
+       67, -754, -754, -754, -754, -754, -754, -754, -754, -754,
+     -754, -754, -754, -754, -754, -754, -754, -754, -754, -754,
+     -754, -754, -754, -754, -754, -754, -754, -754, -754, -754,
+     -754, -754,  786, -754, -754, -754, -754, -754, -754, -754,
+     -754, -754, -754, -754, -754, -754, -754, -754, -754, -754,
+     -754, -754, -754, -754, -754, -754, -754, -754, -754, -754,
+     -754, -754, -754, -754, -754,  786,  786,  786,  786,  786,
+      786,  786,  786,  786,  786,  786,  786,  786,  786,  786,
+
+      786,  786,  786,  786,  786,  786,  786,  786,  786,  786,
+      786, -754, -754, -754, -754, -754, -754, -754, -754, -754,
+     -754, -754, -754, -754, -754, -754, -754, -754, -754, -754,
+     -754, -754, -754, -754, -754, -754, -754, -754, -754, -754,
+     -754, -754, -754, -754, -754, -754, -754, -754
+    },
+
+    {
+       67, -755, -755, -755, -755, -755, -755, -755, -755, -755,
+     -755, -755, -755, -755, -755, -755, -755, -755, -755, -755,
+     -755, -755, -755, -755, -755, -755, -755, -755, -755, -755,
+     -755, -755,  787, -755, -755, -755, -755, -755, -755, -755,
+     -755, -755, -755, -755, -755, -755, -755, -755, -755, -755,
+
+     -755, -755, -755, -755, -755, -755, -755, -755, -755, -755,
+     -755, -755, -755, -755, -755,  787,  787,  787,  787,  787,
+      787,  787,  787,  787,  787,  787,  787,  787,  787,  787,
+      787,  787,  787,  787,  787,  787,  787,  787,  787,  787,
+      787, -755, -755, -755, -755, -755, -755, -755, -755, -755,
+     -755, -755, -755, -755, -755, -755, -755, -755, -755, -755,
+     -755, -755, -755, -755, -755, -755, -755, -755, -755, -755,
+     -755, -755, -755, -755, -755, -755, -755, -755
+    },
+
+    {
+       67, -756, -756, -756, -756, -756, -756, -756, -756, -756,
+     -756, -756, -756, -756, -756, -756, -756, -756, -756, -756,
+
+     -756, -756, -756, -756, -756, -756, -756, -756, -756, -756,
+     -756, -756, -756, -756, -756, -756, -756, -756, -756, -756,
+     -756, -756, -756, -756, -756, -756, -756, -756, -756, -756,
+     -756, -756, -756, -756, -756, -756, -756, -756, -756, -756,
+     -756, -756, -756, -756, -756, -756, -756, -756, -756, -756,
+     -756, -756, -756, -756, -756, -756, -756, -756, -756, -756,
+     -756, -756, -756, -756, -756, -756, -756, -756, -756, -756,
+     -756, -756, -756, -756, -756, -756, -756, -756, -756, -756,
+     -756, -756, -756, -756, -756, -756, -756, -756, -756, -756,
+     -756, -756, -756, -756, -756, -756, -756, -756, -756, -756,
+
+     -756, -756, -756, -756, -756, -756, -756, -756
+    },
+
+    {
+       67, -757, -757, -757, -757, -757, -757, -757, -757, -757,
+     -757, -757, -757, -757, -757, -757, -757, -757, -757, -757,
+     -757, -757, -757, -757, -757, -757, -757, -757, -757, -757,
+     -757, -757,  788, -757, -757, -757, -757, -757, -757, -757,
+     -757, -757, -757, -757, -757, -757, -757, -757, -757, -757,
+     -757, -757, -757, -757, -757, -757, -757, -757, -757, -757,
+     -757, -757, -757, -757, -757, -757, -757, -757, -757, -757,
+     -757, -757, -757, -757, -757, -757, -757, -757, -757, -757,
+     -757, -757, -757, -757, -757, -757, -757, -757, -757, -757,
+
+     -757, -757, -757, -757, -757, -757, -757, -757, -757, -757,
+     -757, -757, -757, -757, -757, -757, -757, -757, -757, -757,
+     -757, -757, -757, -757, -757, -757, -757, -757, -757, -757,
+     -757, -757, -757, -757, -757, -757, -757, -757
+    },
+
+    {
+       67, -758, -758, -758, -758, -758, -758, -758, -758, -758,
+     -758, -758, -758, -758, -758, -758, -758, -758, -758, -758,
+     -758, -758, -758, -758, -758, -758, -758, -758, -758, -758,
+     -758, -758,  789, -758, -758, -758, -758, -758, -758, -758,
+     -758, -758, -758, -758, -758, -758, -758, -758, -758, -758,
+     -758, -758, -758, -758, -758, -758, -758, -758, -758, -758,
+
+     -758, -758, -758, -758, -758, -758, -758, -758, -758, -758,
+     -758, -758, -758, -758, -758, -758, -758, -758, -758, -758,
+     -758, -758, -758, -758, -758, -758, -758, -758, -758, -758,
+     -758, -758, -758, -758, -758, -758, -758, -758, -758, -758,
+     -758, -758, -758, -758, -758, -758, -758, -758, -758, -758,
+     -758, -758, -758, -758, -758, -758, -758, -758, -758, -758,
+     -758, -758, -758, -758, -758, -758, -758, -758
+    },
+
+    {
+       67, -759, -759, -759, -759, -759, -759, -759, -759, -759,
+     -759, -759, -759, -759, -759, -759, -759, -759, -759, -759,
+     -759, -759, -759, -759, -759, -759, -759, -759, -759, -759,
+
+     -759, -759,  790, -759, -759, -759, -759, -759, -759, -759,
+     -759, -759, -759, -759, -759, -759, -759, -759, -759, -759,
+     -759, -759, -759, -759, -759, -759, -759, -759, -759, -759,
+     -759, -759, -759, -759, -759,  790,  790,  790,  790,  790,
+      790,  790,  790,  790,  790,  790,  790,  790,  790,  790,
+      790,  790,  790,  790,  790,  790,  790,  790,  790,  790,
+      790, -759, -759, -759, -759, -759, -759, -759, -759, -759,
+     -759, -759, -759, -759, -759, -759, -759, -759, -759, -759,
+     -759, -759, -759, -759, -759, -759, -759, -759, -759, -759,
+     -759, -759, -759, -759, -759, -759, -759, -759
+
+    },
+
+    {
+       67, -760, -760, -760, -760, -760, -760, -760, -760, -760,
+     -760, -760, -760, -760, -760, -760, -760, -760, -760, -760,
+     -760, -760, -760, -760, -760, -760, -760, -760, -760, -760,
+     -760, -760,  791, -760, -760, -760, -760, -760, -760, -760,
+     -760, -760, -760, -760, -760, -760, -760, -760, -760, -760,
+     -760, -760, -760, -760, -760, -760, -760, -760, -760, -760,
+     -760, -760, -760, -760, -760, -760, -760, -760, -760, -760,
+     -760, -760, -760, -760, -760, -760, -760, -760, -760, -760,
+     -760, -760, -760, -760, -760, -760, -760, -760, -760, -760,
+     -760, -760, -760, -760, -760, -760, -760, -760, -760, -760,
+
+     -760, -760, -760, -760, -760, -760, -760, -760, -760, -760,
+     -760, -760, -760, -760, -760, -760, -760, -760, -760, -760,
+     -760, -760, -760, -760, -760, -760, -760, -760
+    },
+
+    {
+       67, -761, -761, -761, -761, -761, -761, -761, -761, -761,
+     -761, -761, -761, -761, -761, -761, -761, -761, -761, -761,
+     -761, -761, -761, -761, -761, -761, -761, -761, -761, -761,
+     -761, -761,  792, -761, -761, -761, -761, -761, -761, -761,
+     -761, -761, -761, -761, -761, -761, -761, -761, -761, -761,
+     -761, -761, -761, -761, -761, -761, -761, -761, -761, -761,
+     -761, -761, -761, -761, -761, -761, -761, -761, -761, -761,
+
+     -761, -761, -761, -761, -761, -761, -761, -761, -761, -761,
+     -761, -761, -761, -761, -761, -761, -761, -761, -761, -761,
+     -761, -761, -761, -761, -761, -761, -761, -761, -761, -761,
+     -761, -761, -761, -761, -761, -761, -761, -761, -761, -761,
+     -761, -761, -761, -761, -761, -761, -761, -761, -761, -761,
+     -761, -761, -761, -761, -761, -761, -761, -761
+    },
+
+    {
+       67, -762, -762, -762, -762, -762, -762, -762, -762, -762,
+     -762, -762, -762, -762, -762, -762, -762, -762, -762, -762,
+     -762, -762, -762, -762, -762, -762, -762, -762, -762, -762,
+     -762, -762,  793, -762, -762, -762, -762, -762, -762, -762,
+
+     -762, -762, -762, -762, -762, -762, -762, -762, -762, -762,
+     -762, -762, -762, -762, -762, -762, -762, -762, -762, -762,
+     -762, -762, -762, -762, -762,  793,  793,  793,  793,  793,
+      793,  793,  793,  793,  793,  793,  793,  793,  793,  793,
+      793,  793,  793,  793,  793,  793,  793,  793,  793,  793,
+      793, -762, -762, -762, -762, -762, -762, -762, -762, -762,
+     -762, -762, -762, -762, -762, -762, -762, -762, -762, -762,
+     -762, -762, -762, -762, -762, -762, -762, -762, -762, -762,
+     -762, -762, -762, -762, -762, -762, -762, -762
+    },
+
+    {
+       67, -763, -763, -763, -763, -763, -763, -763, -763, -763,
+
+     -763, -763, -763, -763, -763, -763, -763, -763, -763, -763,
+     -763, -763, -763, -763, -763, -763, -763, -763, -763, -763,
+     -763, -763, -763, -763, -763, -763, -763, -763, -763, -763,
+     -763, -763, -763, -763, -763, -763, -763, -763, -763, -763,
+     -763, -763, -763, -763, -763, -763, -763, -763, -763, -763,
+     -763, -763, -763, -763, -763, -763, -763, -763, -763, -763,
+     -763, -763, -763, -763, -763, -763, -763, -763, -763, -763,
+     -763, -763, -763, -763, -763, -763, -763, -763, -763, -763,
+     -763, -763, -763, -763, -763, -763, -763, -763, -763, -763,
+     -763, -763, -763, -763, -763, -763, -763, -763, -763, -763,
+
+     -763, -763, -763, -763, -763, -763, -763, -763, -763, -763,
+     -763, -763, -763, -763, -763, -763, -763, -763
+    },
+
+    {
+       67, -764, -764, -764, -764, -764, -764, -764, -764, -764,
+     -764, -764, -764, -764, -764, -764, -764, -764, -764, -764,
+     -764, -764, -764, -764, -764, -764, -764, -764, -764, -764,
+     -764, -764, -764, -764, -764, -764, -764, -764, -764, -764,
+     -764, -764, -764, -764, -764, -764, -764, -764, -764, -764,
+     -764, -764, -764, -764, -764, -764, -764, -764, -764, -764,
+     -764, -764, -764, -764, -764, -764, -764, -764, -764, -764,
+     -764, -764, -764, -764, -764, -764, -764, -764, -764, -764,
+
+     -764, -764, -764, -764, -764, -764, -764, -764, -764, -764,
+     -764, -764, -764, -764, -764, -764, -764, -764, -764, -764,
+     -764, -764, -764, -764, -764, -764, -764, -764, -764, -764,
+     -764, -764, -764, -764, -764, -764, -764, -764, -764, -764,
+     -764, -764, -764, -764, -764, -764, -764, -764
+    },
+
+    {
+       67, -765, -765, -765, -765, -765, -765, -765, -765, -765,
+     -765, -765, -765, -765, -765, -765, -765, -765, -765, -765,
+     -765, -765, -765, -765, -765, -765, -765, -765, -765, -765,
+     -765, -765, -765, -765, -765, -765, -765, -765, -765, -765,
+     -765, -765, -765, -765, -765, -765, -765, -765, -765, -765,
+
+     -765, -765, -765, -765, -765, -765, -765, -765, -765, -765,
+     -765, -765, -765, -765, -765, -765, -765, -765, -765, -765,
+     -765, -765, -765, -765, -765, -765, -765, -765, -765, -765,
+     -765, -765, -765, -765, -765, -765, -765, -765, -765, -765,
+     -765, -765, -765, -765, -765, -765, -765, -765, -765, -765,
+     -765, -765, -765, -765, -765, -765, -765, -765, -765, -765,
+     -765, -765, -765, -765, -765, -765, -765, -765, -765, -765,
+     -765, -765, -765, -765, -765, -765, -765, -765
+    },
+
+    {
+       67, -766, -766, -766, -766, -766, -766, -766, -766, -766,
+     -766, -766, -766, -766, -766, -766, -766, -766, -766, -766,
+
+     -766, -766, -766, -766, -766, -766, -766, -766, -766, -766,
+     -766, -766, -766, -766, -766, -766, -766, -766, -766, -766,
+     -766, -766, -766, -766, -766, -766, -766, -766, -766, -766,
+     -766, -766, -766, -766, -766, -766, -766, -766, -766, -766,
+     -766, -766, -766, -766, -766, -766, -766, -766, -766, -766,
+     -766, -766, -766, -766, -766, -766, -766, -766, -766, -766,
+     -766, -766, -766, -766, -766, -766, -766, -766, -766, -766,
+     -766, -766, -766, -766, -766, -766, -766, -766, -766, -766,
+     -766, -766, -766, -766, -766, -766, -766, -766, -766, -766,
+     -766, -766, -766, -766, -766, -766, -766, -766, -766, -766,
+
+     -766, -766, -766, -766, -766, -766, -766, -766
+    },
+
+    {
+       67, -767, -767, -767, -767, -767, -767, -767, -767, -767,
+     -767, -767, -767, -767, -767, -767, -767, -767, -767, -767,
+     -767, -767, -767, -767, -767, -767, -767, -767, -767, -767,
+     -767, -767, -767, -767, -767, -767, -767, -767, -767, -767,
+     -767, -767, -767, -767, -767, -767, -767, -767, -767, -767,
+     -767, -767, -767, -767, -767, -767, -767, -767, -767, -767,
+     -767, -767, -767, -767, -767, -767, -767, -767, -767, -767,
+     -767, -767, -767, -767, -767, -767, -767, -767, -767, -767,
+     -767, -767, -767, -767, -767, -767, -767, -767, -767, -767,
+
+     -767, -767, -767, -767, -767, -767, -767, -767, -767, -767,
+     -767, -767, -767, -767, -767, -767, -767, -767, -767, -767,
+     -767, -767, -767, -767, -767, -767, -767, -767, -767, -767,
+     -767, -767, -767, -767, -767, -767, -767, -767
+    },
+
+    {
+       67, -768, -768, -768, -768, -768, -768, -768, -768, -768,
+     -768, -768, -768, -768, -768, -768, -768, -768, -768, -768,
+     -768, -768, -768, -768, -768, -768, -768, -768, -768, -768,
+     -768, -768, -768, -768, -768, -768, -768, -768, -768, -768,
+     -768, -768, -768, -768, -768, -768, -768, -768, -768, -768,
+     -768, -768, -768, -768, -768, -768, -768, -768, -768, -768,
+
+     -768, -768, -768, -768, -768, -768, -768, -768, -768, -768,
+     -768, -768, -768, -768, -768, -768, -768, -768, -768, -768,
+     -768, -768, -768, -768, -768, -768, -768, -768, -768, -768,
+     -768, -768, -768, -768, -768, -768, -768, -768, -768, -768,
+     -768, -768, -768, -768, -768, -768, -768, -768, -768, -768,
+     -768, -768, -768, -768, -768, -768, -768, -768, -768, -768,
+     -768, -768, -768, -768, -768, -768, -768, -768
+    },
+
+    {
+       67, -769, -769, -769, -769, -769, -769, -769, -769, -769,
+     -769, -769, -769, -769, -769, -769, -769, -769, -769, -769,
+     -769, -769, -769, -769, -769, -769, -769, -769, -769, -769,
+
+     -769, -769,  794, -769, -769, -769, -769, -769, -769, -769,
+     -769, -769, -769, -769, -769, -769, -769, -769, -769, -769,
+     -769, -769, -769, -769, -769, -769, -769, -769, -769, -769,
+     -769, -769, -769, -769, -769, -769, -769, -769, -769, -769,
+     -769, -769, -769, -769, -769, -769, -769, -769, -769, -769,
+     -769, -769, -769, -769, -769, -769, -769, -769, -769, -769,
+     -769, -769, -769, -769, -769, -769, -769, -769, -769, -769,
+     -769, -769, -769, -769, -769, -769, -769, -769, -769, -769,
+     -769, -769, -769, -769, -769, -769, -769, -769, -769, -769,
+     -769, -769, -769, -769, -769, -769, -769, -769
+
+    },
+
+    {
+       67, -770, -770, -770, -770, -770, -770, -770, -770, -770,
+     -770, -770, -770, -770, -770, -770, -770, -770, -770, -770,
+     -770, -770, -770, -770, -770, -770, -770, -770, -770, -770,
+     -770, -770, -770, -770, -770, -770, -770, -770, -770, -770,
+     -770, -770, -770, -770, -770, -770, -770, -770, -770, -770,
+     -770, -770, -770, -770, -770, -770, -770, -770, -770, -770,
+     -770, -770, -770, -770, -770, -770, -770, -770, -770, -770,
+     -770, -770, -770, -770, -770, -770, -770, -770, -770, -770,
+     -770, -770, -770, -770, -770, -770, -770, -770, -770, -770,
+     -770, -770, -770, -770, -770, -770, -770, -770, -770, -770,
+
+     -770, -770, -770, -770, -770, -770, -770, -770, -770, -770,
+     -770, -770, -770, -770, -770, -770, -770, -770, -770, -770,
+     -770, -770, -770, -770, -770, -770, -770, -770
+    },
+
+    {
+       67, -771, -771, -771, -771, -771, -771, -771, -771, -771,
+     -771, -771, -771, -771, -771, -771, -771, -771, -771, -771,
+     -771, -771, -771, -771, -771, -771, -771, -771, -771, -771,
+     -771, -771, -771, -771, -771, -771, -771, -771, -771, -771,
+     -771, -771, -771, -771, -771, -771, -771, -771, -771, -771,
+     -771, -771, -771, -771, -771, -771, -771, -771, -771, -771,
+     -771, -771, -771, -771, -771, -771, -771, -771, -771, -771,
+
+     -771, -771, -771, -771, -771, -771, -771, -771, -771, -771,
+     -771, -771, -771, -771, -771, -771, -771, -771, -771, -771,
+     -771, -771, -771, -771, -771, -771, -771, -771, -771, -771,
+     -771, -771, -771, -771, -771, -771, -771, -771, -771, -771,
+     -771, -771, -771, -771, -771, -771, -771, -771, -771, -771,
+     -771, -771, -771, -771, -771, -771, -771, -771
+    },
+
+    {
+       67, -772, -772, -772, -772, -772, -772, -772, -772, -772,
+     -772, -772, -772, -772, -772, -772, -772, -772, -772, -772,
+     -772, -772, -772, -772, -772, -772, -772, -772, -772, -772,
+     -772, -772, -772, -772, -772, -772, -772, -772, -772, -772,
+
+     -772, -772, -772, -772, -772, -772, -772, -772, -772, -772,
+     -772, -772, -772, -772, -772, -772, -772, -772, -772, -772,
+     -772, -772, -772, -772, -772, -772, -772, -772, -772, -772,
+     -772, -772, -772, -772, -772, -772, -772, -772, -772, -772,
+     -772, -772, -772, -772, -772, -772, -772, -772, -772, -772,
+     -772, -772, -772, -772, -772, -772, -772, -772, -772, -772,
+     -772, -772, -772, -772, -772, -772, -772, -772, -772, -772,
+     -772, -772, -772, -772, -772, -772, -772, -772, -772, -772,
+     -772, -772, -772, -772, -772, -772, -772, -772
+    },
+
+    {
+       67, -773, -773, -773, -773, -773, -773, -773, -773, -773,
+
+     -773, -773, -773, -773, -773, -773, -773, -773, -773, -773,
+     -773, -773, -773, -773, -773, -773, -773, -773, -773, -773,
+     -773, -773, -773, -773, -773, -773, -773, -773, -773, -773,
+     -773, -773, -773, -773, -773, -773, -773, -773, -773, -773,
+     -773, -773, -773, -773, -773, -773, -773, -773, -773, -773,
+     -773, -773, -773, -773, -773, -773, -773, -773, -773, -773,
+     -773, -773, -773, -773, -773, -773, -773, -773, -773, -773,
+     -773, -773, -773, -773, -773, -773, -773, -773, -773, -773,
+     -773, -773, -773, -773, -773, -773, -773, -773, -773, -773,
+     -773, -773, -773, -773, -773, -773, -773, -773, -773, -773,
+
+     -773, -773, -773, -773, -773, -773, -773, -773, -773, -773,
+     -773, -773, -773, -773, -773, -773, -773, -773
+    },
+
+    {
+       67, -774, -774, -774, -774, -774, -774, -774, -774, -774,
+     -774, -774, -774, -774, -774, -774, -774, -774, -774, -774,
+     -774, -774, -774, -774, -774, -774, -774, -774, -774, -774,
+     -774, -774, -774, -774, -774, -774, -774, -774, -774, -774,
+     -774, -774, -774, -774, -774, -774, -774, -774, -774, -774,
+     -774, -774, -774, -774, -774, -774, -774, -774, -774, -774,
+     -774, -774, -774, -774, -774, -774, -774, -774, -774, -774,
+     -774, -774, -774, -774, -774, -774, -774, -774, -774, -774,
+
+     -774, -774, -774, -774, -774, -774, -774, -774, -774, -774,
+     -774, -774, -774, -774, -774, -774, -774, -774, -774, -774,
+     -774, -774, -774, -774, -774, -774, -774, -774, -774, -774,
+     -774, -774, -774, -774, -774, -774, -774, -774, -774, -774,
+     -774, -774, -774, -774, -774, -774, -774, -774
+    },
+
+    {
+       67, -775, -775, -775, -775, -775, -775, -775, -775, -775,
+     -775, -775, -775, -775, -775, -775, -775, -775, -775, -775,
+     -775, -775, -775, -775, -775, -775, -775, -775, -775, -775,
+     -775, -775, -775, -775, -775, -775, -775, -775, -775, -775,
+     -775, -775, -775, -775, -775, -775, -775, -775, -775, -775,
+
+     -775, -775, -775, -775, -775, -775, -775, -775, -775, -775,
+     -775, -775, -775, -775, -775, -775, -775, -775, -775, -775,
+     -775, -775, -775, -775, -775, -775, -775, -775, -775, -775,
+     -775, -775, -775, -775, -775, -775, -775, -775, -775, -775,
+     -775, -775, -775, -775, -775, -775, -775, -775, -775, -775,
+     -775, -775, -775, -775, -775, -775, -775, -775, -775, -775,
+     -775, -775, -775, -775, -775, -775, -775, -775, -775, -775,
+     -775, -775, -775, -775, -775, -775, -775, -775
+    },
+
+    {
+       67, -776, -776, -776, -776, -776, -776, -776, -776, -776,
+     -776, -776, -776, -776, -776, -776, -776, -776, -776, -776,
+
+     -776, -776, -776, -776, -776, -776, -776, -776, -776, -776,
+     -776, -776, -776, -776, -776, -776, -776, -776, -776, -776,
+     -776, -776, -776, -776, -776, -776, -776, -776, -776, -776,
+     -776, -776, -776, -776, -776, -776, -776, -776, -776, -776,
+     -776, -776, -776, -776, -776, -776, -776, -776, -776, -776,
+     -776, -776, -776, -776, -776, -776, -776, -776, -776, -776,
+     -776, -776, -776, -776, -776, -776, -776, -776, -776, -776,
+     -776, -776, -776, -776, -776, -776, -776, -776, -776, -776,
+     -776, -776, -776, -776, -776, -776, -776, -776, -776, -776,
+     -776, -776, -776, -776, -776, -776, -776, -776, -776, -776,
+
+     -776, -776, -776, -776, -776, -776, -776, -776
+    },
+
+    {
+       67, -777, -777, -777, -777, -777, -777, -777, -777, -777,
+     -777, -777, -777, -777, -777, -777, -777, -777, -777, -777,
+     -777, -777, -777, -777, -777, -777, -777, -777, -777, -777,
+     -777, -777, -777, -777, -777, -777, -777, -777, -777, -777,
+     -777, -777, -777, -777, -777, -777, -777, -777, -777, -777,
+     -777, -777, -777, -777, -777, -777, -777, -777, -777, -777,
+     -777, -777, -777, -777, -777, -777, -777, -777, -777, -777,
+     -777, -777, -777, -777, -777, -777, -777, -777, -777, -777,
+     -777, -777, -777, -777, -777, -777, -777, -777, -777, -777,
+
+     -777, -777, -777, -777, -777, -777, -777, -777, -777, -777,
+     -777, -777, -777, -777, -777, -777, -777, -777, -777, -777,
+     -777, -777, -777, -777, -777, -777, -777, -777, -777, -777,
+     -777, -777, -777, -777, -777, -777, -777, -777
+    },
+
+    {
+       67, -778, -778, -778, -778, -778, -778, -778, -778, -778,
+     -778, -778, -778, -778, -778, -778, -778, -778, -778, -778,
+     -778, -778, -778, -778, -778, -778, -778, -778, -778, -778,
+     -778, -778, -778, -778, -778, -778, -778, -778, -778, -778,
+     -778, -778, -778, -778, -778, -778, -778, -778, -778, -778,
+     -778, -778, -778, -778, -778, -778, -778, -778, -778, -778,
+
+     -778,  795, -778, -778, -778, -778, -778, -778, -778, -778,
+     -778, -778, -778, -778, -778, -778, -778, -778, -778, -778,
+     -778, -778, -778, -778, -778, -778, -778, -778, -778, -778,
+     -778, -778, -778, -778, -778, -778, -778, -778, -778, -778,
+     -778, -778, -778, -778, -778, -778, -778, -778, -778, -778,
+     -778, -778, -778, -778, -778, -778, -778, -778, -778, -778,
+     -778, -778, -778, -778, -778, -778, -778, -778
+    },
+
+    {
+       67, -779, -779, -779, -779, -779, -779, -779, -779, -779,
+     -779, -779, -779, -779, -779, -779, -779, -779, -779, -779,
+     -779, -779, -779, -779, -779, -779, -779, -779, -779, -779,
+
+     -779, -779, -779, -779, -779, -779, -779, -779, -779, -779,
+     -779, -779, -779, -779, -779, -779, -779, -779, -779, -779,
+     -779, -779, -779, -779, -779, -779, -779, -779, -779, -779,
+     -779, -779, -779, -779, -779, -779, -779, -779, -779, -779,
+     -779, -779, -779, -779, -779, -779, -779, -779, -779, -779,
+     -779, -779, -779, -779, -779, -779, -779, -779, -779, -779,
+     -779, -779, -779, -779, -779, -779, -779, -779, -779, -779,
+     -779, -779, -779, -779, -779, -779, -779, -779, -779, -779,
+     -779, -779, -779, -779, -779, -779, -779, -779, -779, -779,
+     -779, -779, -779, -779, -779, -779, -779, -779
+
+    },
+
+    {
+       67, -780, -780, -780, -780, -780, -780, -780, -780, -780,
+     -780, -780, -780, -780, -780, -780, -780, -780, -780, -780,
+     -780, -780, -780, -780, -780, -780, -780, -780, -780, -780,
+     -780, -780, -780, -780, -780, -780, -780, -780, -780, -780,
+     -780, -780, -780, -780, -780, -780, -780, -780, -780, -780,
+     -780, -780, -780, -780, -780, -780, -780, -780, -780, -780,
+     -780, -780, -780, -780, -780, -780, -780, -780, -780, -780,
+     -780, -780, -780, -780, -780, -780, -780, -780, -780, -780,
+     -780, -780, -780, -780, -780, -780, -780, -780, -780, -780,
+     -780, -780, -780, -780, -780, -780, -780, -780, -780, -780,
+
+     -780, -780, -780, -780, -780, -780, -780, -780, -780, -780,
+     -780, -780, -780, -780, -780, -780, -780, -780, -780, -780,
+     -780, -780, -780, -780, -780, -780, -780, -780
+    },
+
+    {
+       67, -781, -781, -781, -781, -781, -781, -781, -781, -781,
+     -781, -781, -781, -781, -781, -781, -781, -781, -781, -781,
+     -781, -781, -781, -781, -781, -781, -781, -781, -781, -781,
+     -781, -781, -781, -781, -781, -781, -781, -781, -781, -781,
+     -781, -781, -781, -781, -781, -781, -781, -781, -781, -781,
+     -781, -781, -781, -781, -781, -781, -781, -781, -781, -781,
+     -781, -781, -781, -781, -781, -781, -781, -781, -781, -781,
+
+     -781, -781, -781, -781, -781, -781, -781, -781, -781, -781,
+     -781, -781, -781, -781, -781, -781, -781, -781, -781, -781,
+     -781, -781, -781, -781, -781, -781, -781, -781, -781, -781,
+     -781, -781, -781, -781, -781, -781, -781, -781, -781, -781,
+     -781, -781, -781, -781, -781, -781, -781, -781, -781, -781,
+     -781, -781, -781, -781, -781, -781, -781, -781
+    },
+
+    {
+       67, -782, -782, -782, -782, -782, -782, -782, -782, -782,
+     -782, -782, -782, -782, -782, -782, -782, -782, -782, -782,
+     -782, -782, -782, -782, -782, -782, -782, -782, -782, -782,
+     -782, -782, -782, -782, -782, -782, -782, -782, -782, -782,
+
+     -782, -782, -782, -782, -782, -782, -782, -782, -782, -782,
+     -782, -782, -782, -782, -782, -782, -782, -782, -782, -782,
+     -782, -782, -782, -782, -782, -782, -782, -782, -782, -782,
+     -782, -782, -782, -782, -782, -782, -782, -782, -782, -782,
+     -782, -782, -782, -782, -782, -782, -782, -782, -782, -782,
+     -782, -782, -782, -782, -782, -782, -782, -782, -782, -782,
+     -782, -782, -782, -782, -782, -782, -782, -782, -782, -782,
+     -782, -782, -782, -782, -782, -782, -782, -782, -782, -782,
+     -782, -782, -782, -782, -782, -782, -782, -782
+    },
+
+    {
+       67, -783, -783, -783, -783, -783, -783, -783, -783, -783,
+
+     -783, -783, -783, -783, -783, -783, -783, -783, -783, -783,
+     -783, -783, -783, -783, -783, -783, -783, -783, -783, -783,
+     -783, -783, -783, -783, -783, -783, -783, -783, -783, -783,
+     -783, -783, -783, -783, -783, -783, -783, -783, -783, -783,
+     -783, -783, -783, -783, -783, -783, -783, -783, -783, -783,
+     -783, -783, -783, -783, -783, -783, -783, -783, -783, -783,
+     -783, -783, -783, -783, -783, -783, -783, -783, -783, -783,
+     -783, -783, -783, -783, -783, -783, -783, -783, -783, -783,
+     -783, -783, -783, -783, -783, -783, -783, -783, -783, -783,
+     -783, -783, -783, -783, -783, -783, -783, -783, -783, -783,
+
+     -783, -783, -783, -783, -783, -783, -783, -783, -783, -783,
+     -783, -783, -783, -783, -783, -783, -783, -783
+    },
+
+    {
+       67, -784, -784, -784, -784, -784, -784, -784, -784, -784,
+     -784, -784, -784, -784, -784, -784, -784, -784, -784, -784,
+     -784, -784, -784, -784, -784, -784, -784, -784, -784, -784,
+     -784, -784, -784, -784, -784, -784, -784, -784, -784, -784,
+     -784, -784, -784, -784, -784, -784, -784, -784, -784, -784,
+     -784, -784, -784, -784, -784, -784, -784, -784, -784, -784,
+     -784,  796, -784, -784, -784, -784, -784, -784, -784, -784,
+     -784, -784, -784, -784, -784, -784, -784, -784, -784, -784,
+
+     -784, -784, -784, -784, -784, -784, -784, -784, -784, -784,
+     -784, -784, -784, -784, -784, -784, -784, -784, -784, -784,
+     -784, -784, -784, -784, -784, -784, -784, -784, -784, -784,
+     -784, -784, -784, -784, -784, -784, -784, -784, -784, -784,
+     -784, -784, -784, -784, -784, -784, -784, -784
+    },
+
+    {
+       67, -785, -785, -785, -785, -785, -785, -785, -785, -785,
+     -785, -785, -785, -785, -785, -785, -785, -785, -785, -785,
+     -785, -785, -785, -785, -785, -785, -785, -785, -785, -785,
+     -785, -785, -785, -785, -785, -785, -785, -785, -785, -785,
+     -785, -785, -785, -785, -785, -785, -785, -785, -785, -785,
+
+     -785, -785, -785, -785, -785, -785, -785, -785, -785, -785,
+     -785,  797, -785, -785, -785, -785, -785, -785, -785, -785,
+     -785, -785, -785, -785, -785, -785, -785, -785, -785, -785,
+     -785, -785, -785, -785, -785, -785, -785, -785, -785, -785,
+     -785, -785, -785, -785, -785, -785, -785, -785, -785, -785,
+     -785, -785, -785, -785, -785, -785, -785, -785, -785, -785,
+     -785, -785, -785, -785, -785, -785, -785, -785, -785, -785,
+     -785, -785, -785, -785, -785, -785, -785, -785
+    },
+
+    {
+       67, -786, -786, -786, -786, -786, -786, -786, -786, -786,
+     -786, -786, -786, -786, -786, -786, -786, -786, -786, -786,
+
+     -786, -786, -786, -786, -786, -786, -786, -786, -786, -786,
+     -786, -786, -786, -786, -786, -786, -786, -786, -786, -786,
+     -786, -786, -786, -786, -786, -786, -786, -786, -786, -786,
+     -786, -786, -786, -786, -786, -786, -786, -786, -786, -786,
+     -786,  798, -786, -786, -786, -786, -786, -786, -786, -786,
+     -786, -786, -786, -786, -786, -786, -786, -786, -786, -786,
+     -786, -786, -786, -786, -786, -786, -786, -786, -786, -786,
+     -786, -786, -786, -786, -786, -786, -786, -786, -786, -786,
+     -786, -786, -786, -786, -786, -786, -786, -786, -786, -786,
+     -786, -786, -786, -786, -786, -786, -786, -786, -786, -786,
+
+     -786, -786, -786, -786, -786, -786, -786, -786
+    },
+
+    {
+       67, -787, -787, -787, -787, -787, -787, -787, -787, -787,
+     -787, -787, -787, -787, -787, -787, -787, -787, -787, -787,
+     -787, -787, -787, -787, -787, -787, -787, -787, -787, -787,
+     -787, -787, -787, -787, -787, -787, -787, -787, -787, -787,
+     -787, -787, -787, -787, -787, -787, -787, -787, -787, -787,
+     -787, -787, -787, -787, -787, -787, -787, -787, -787, -787,
+     -787,  799, -787, -787, -787, -787, -787, -787, -787, -787,
+     -787, -787, -787, -787, -787, -787, -787, -787, -787, -787,
+     -787, -787, -787, -787, -787, -787, -787, -787, -787, -787,
+
+     -787, -787, -787, -787, -787, -787, -787, -787, -787, -787,
+     -787, -787, -787, -787, -787, -787, -787, -787, -787, -787,
+     -787, -787, -787, -787, -787, -787, -787, -787, -787, -787,
+     -787, -787, -787, -787, -787, -787, -787, -787
+    },
+
+    {
+       67, -788, -788, -788, -788, -788, -788, -788, -788, -788,
+     -788, -788, -788, -788, -788, -788, -788, -788, -788, -788,
+     -788, -788, -788, -788, -788, -788, -788, -788, -788, -788,
+     -788, -788, -788, -788, -788, -788, -788, -788, -788, -788,
+     -788, -788, -788, -788, -788, -788, -788, -788, -788, -788,
+     -788, -788, -788, -788, -788, -788, -788, -788, -788, -788,
+
+     -788,  800, -788, -788, -788, -788, -788, -788, -788, -788,
+     -788, -788, -788, -788, -788, -788, -788, -788, -788, -788,
+     -788, -788, -788, -788, -788, -788, -788, -788, -788, -788,
+     -788, -788, -788, -788, -788, -788, -788, -788, -788, -788,
+     -788, -788, -788, -788, -788, -788, -788, -788, -788, -788,
+     -788, -788, -788, -788, -788, -788, -788, -788, -788, -788,
+     -788, -788, -788, -788, -788, -788, -788, -788
+    },
+
+    {
+       67, -789, -789, -789, -789, -789, -789, -789, -789, -789,
+     -789, -789, -789, -789, -789, -789, -789, -789, -789, -789,
+     -789, -789, -789, -789, -789, -789, -789, -789, -789, -789,
+
+     -789, -789, -789, -789, -789, -789, -789, -789, -789, -789,
+     -789, -789, -789, -789, -789, -789, -789, -789, -789, -789,
+     -789, -789, -789, -789, -789, -789, -789, -789, -789, -789,
+     -789,  801, -789, -789, -789, -789, -789, -789, -789, -789,
+     -789, -789, -789, -789, -789, -789, -789, -789, -789, -789,
+     -789, -789, -789, -789, -789, -789, -789, -789, -789, -789,
+     -789, -789, -789, -789, -789, -789, -789, -789, -789, -789,
+     -789, -789, -789, -789, -789, -789, -789, -789, -789, -789,
+     -789, -789, -789, -789, -789, -789, -789, -789, -789, -789,
+     -789, -789, -789, -789, -789, -789, -789, -789
+
+    },
+
+    {
+       67, -790, -790, -790, -790, -790, -790, -790, -790, -790,
+     -790, -790, -790, -790, -790, -790, -790, -790, -790, -790,
+     -790, -790, -790, -790, -790, -790, -790, -790, -790, -790,
+     -790, -790, -790, -790, -790, -790, -790, -790, -790, -790,
+     -790, -790, -790, -790, -790, -790, -790, -790, -790, -790,
+     -790, -790, -790, -790, -790, -790, -790, -790, -790, -790,
+     -790,  802, -790, -790, -790, -790, -790, -790, -790, -790,
+     -790, -790, -790, -790, -790, -790, -790, -790, -790, -790,
+     -790, -790, -790, -790, -790, -790, -790, -790, -790, -790,
+     -790, -790, -790, -790, -790, -790, -790, -790, -790, -790,
+
+     -790, -790, -790, -790, -790, -790, -790, -790, -790, -790,
+     -790, -790, -790, -790, -790, -790, -790, -790, -790, -790,
+     -790, -790, -790, -790, -790, -790, -790, -790
+    },
+
+    {
+       67, -791, -791, -791, -791, -791, -791, -791, -791, -791,
+     -791, -791, -791, -791, -791, -791, -791, -791, -791, -791,
+     -791, -791, -791, -791, -791, -791, -791, -791, -791, -791,
+     -791, -791, -791, -791, -791, -791, -791, -791, -791, -791,
+     -791, -791, -791, -791, -791, -791, -791, -791, -791, -791,
+     -791, -791, -791, -791, -791, -791, -791, -791, -791, -791,
+     -791,  803, -791, -791, -791, -791, -791, -791, -791, -791,
+
+     -791, -791, -791, -791, -791, -791, -791, -791, -791, -791,
+     -791, -791, -791, -791, -791, -791, -791, -791, -791, -791,
+     -791, -791, -791, -791, -791, -791, -791, -791, -791, -791,
+     -791, -791, -791, -791, -791, -791, -791, -791, -791, -791,
+     -791, -791, -791, -791, -791, -791, -791, -791, -791, -791,
+     -791, -791, -791, -791, -791, -791, -791, -791
+    },
+
+    {
+       67, -792, -792, -792, -792, -792, -792, -792, -792, -792,
+     -792, -792, -792, -792, -792, -792, -792, -792, -792, -792,
+     -792, -792, -792, -792, -792, -792, -792, -792, -792, -792,
+     -792, -792, -792, -792, -792, -792, -792, -792, -792, -792,
+
+     -792, -792, -792, -792, -792, -792, -792, -792, -792, -792,
+     -792, -792, -792, -792, -792, -792, -792, -792, -792, -792,
+     -792,  804, -792, -792, -792, -792, -792, -792, -792, -792,
+     -792, -792, -792, -792, -792, -792, -792, -792, -792, -792,
+     -792, -792, -792, -792, -792, -792, -792, -792, -792, -792,
+     -792, -792, -792, -792, -792, -792, -792, -792, -792, -792,
+     -792, -792, -792, -792, -792, -792, -792, -792, -792, -792,
+     -792, -792, -792, -792, -792, -792, -792, -792, -792, -792,
+     -792, -792, -792, -792, -792, -792, -792, -792
+    },
+
+    {
+       67, -793, -793, -793, -793, -793, -793, -793, -793, -793,
+
+     -793, -793, -793, -793, -793, -793, -793, -793, -793, -793,
+     -793, -793, -793, -793, -793, -793, -793, -793, -793, -793,
+     -793, -793, -793, -793, -793, -793, -793, -793, -793, -793,
+     -793, -793, -793, -793, -793, -793, -793, -793, -793, -793,
+     -793, -793, -793, -793, -793, -793, -793, -793, -793, -793,
+     -793,  805, -793, -793, -793, -793, -793, -793, -793, -793,
+     -793, -793, -793, -793, -793, -793, -793, -793, -793, -793,
+     -793, -793, -793, -793, -793, -793, -793, -793, -793, -793,
+     -793, -793, -793, -793, -793, -793, -793, -793, -793, -793,
+     -793, -793, -793, -793, -793, -793, -793, -793, -793, -793,
+
+     -793, -793, -793, -793, -793, -793, -793, -793, -793, -793,
+     -793, -793, -793, -793, -793, -793, -793, -793
+    },
+
+    {
+       67, -794, -794, -794, -794, -794, -794, -794, -794, -794,
+     -794, -794, -794, -794, -794, -794, -794, -794, -794, -794,
+     -794, -794, -794, -794, -794, -794, -794, -794, -794, -794,
+     -794, -794,  806, -794, -794, -794, -794, -794, -794, -794,
+     -794, -794, -794, -794, -794, -794, -794, -794, -794, -794,
+     -794, -794, -794, -794, -794, -794, -794, -794, -794, -794,
+     -794, -794, -794, -794, -794, -794, -794, -794, -794, -794,
+     -794, -794, -794, -794, -794, -794, -794, -794, -794, -794,
+
+     -794, -794, -794, -794, -794, -794, -794, -794, -794, -794,
+     -794, -794, -794, -794, -794, -794, -794, -794, -794, -794,
+     -794, -794, -794, -794, -794, -794, -794, -794, -794, -794,
+     -794, -794, -794, -794, -794, -794, -794, -794, -794, -794,
+     -794, -794, -794, -794, -794, -794, -794, -794
+    },
+
+    {
+       67, -795, -795, -795, -795, -795, -795, -795, -795, -795,
+     -795, -795, -795, -795, -795, -795, -795, -795, -795, -795,
+     -795, -795, -795, -795, -795, -795, -795, -795, -795, -795,
+     -795, -795,  807, -795, -795, -795, -795, -795, -795, -795,
+     -795, -795, -795, -795, -795, -795, -795, -795, -795, -795,
+
+     -795, -795, -795, -795, -795, -795, -795, -795, -795, -795,
+     -795, -795, -795, -795, -795, -795, -795, -795, -795, -795,
+     -795, -795, -795, -795, -795, -795, -795, -795, -795, -795,
+     -795, -795, -795, -795, -795, -795, -795, -795, -795, -795,
+     -795, -795, -795, -795, -795, -795, -795, -795, -795, -795,
+     -795, -795, -795, -795, -795, -795, -795, -795, -795, -795,
+     -795, -795, -795, -795, -795, -795, -795, -795, -795, -795,
+     -795, -795, -795, -795, -795, -795, -795, -795
+    },
+
+    {
+       67, -796, -796, -796, -796, -796, -796, -796, -796, -796,
+     -796, -796, -796, -796, -796, -796, -796, -796, -796, -796,
+
+     -796, -796, -796, -796, -796, -796, -796, -796, -796, -796,
+     -796, -796,  808, -796, -796, -796, -796, -796, -796, -796,
+     -796, -796, -796, -796, -796, -796, -796, -796, -796, -796,
+     -796, -796, -796, -796, -796, -796, -796, -796, -796, -796,
+     -796, -796, -796, -796, -796, -796, -796, -796, -796, -796,
+     -796, -796, -796, -796, -796, -796, -796, -796, -796, -796,
+     -796, -796, -796, -796, -796, -796, -796, -796, -796, -796,
+     -796, -796, -796, -796, -796, -796, -796, -796, -796, -796,
+     -796, -796, -796, -796, -796, -796, -796, -796, -796, -796,
+     -796, -796, -796, -796, -796, -796, -796, -796, -796, -796,
+
+     -796, -796, -796, -796, -796, -796, -796, -796
+    },
+
+    {
+       67, -797, -797, -797, -797, -797, -797, -797, -797, -797,
+     -797, -797, -797, -797, -797, -797, -797, -797, -797, -797,
+     -797, -797, -797, -797, -797, -797, -797, -797, -797, -797,
+     -797, -797,  809, -797, -797, -797, -797, -797, -797, -797,
+     -797, -797, -797, -797, -797, -797, -797, -797, -797, -797,
+     -797, -797, -797, -797, -797, -797, -797, -797, -797, -797,
+     -797, -797, -797, -797, -797, -797, -797, -797, -797, -797,
+     -797, -797, -797, -797, -797, -797, -797, -797, -797, -797,
+     -797, -797, -797, -797, -797, -797, -797, -797, -797, -797,
+
+     -797, -797, -797, -797, -797, -797, -797, -797, -797, -797,
+     -797, -797, -797, -797, -797, -797, -797, -797, -797, -797,
+     -797, -797, -797, -797, -797, -797, -797, -797, -797, -797,
+     -797, -797, -797, -797, -797, -797, -797, -797
+    },
+
+    {
+       67, -798, -798, -798, -798, -798, -798, -798, -798, -798,
+     -798, -798, -798, -798, -798, -798, -798, -798, -798, -798,
+     -798, -798, -798, -798, -798, -798, -798, -798, -798, -798,
+     -798, -798,  810, -798, -798, -798, -798, -798, -798, -798,
+     -798, -798, -798, -798, -798, -798, -798, -798, -798, -798,
+     -798, -798, -798, -798, -798, -798, -798, -798, -798, -798,
+
+     -798, -798, -798, -798, -798, -798, -798, -798, -798, -798,
+     -798, -798, -798, -798, -798, -798, -798, -798, -798, -798,
+     -798, -798, -798, -798, -798, -798, -798, -798, -798, -798,
+     -798, -798, -798, -798, -798, -798, -798, -798, -798, -798,
+     -798, -798, -798, -798, -798, -798, -798, -798, -798, -798,
+     -798, -798, -798, -798, -798, -798, -798, -798, -798, -798,
+     -798, -798, -798, -798, -798, -798, -798, -798
+    },
+
+    {
+       67, -799, -799, -799, -799, -799, -799, -799, -799, -799,
+     -799, -799, -799, -799, -799, -799, -799, -799, -799, -799,
+     -799, -799, -799, -799, -799, -799, -799, -799, -799, -799,
+
+     -799, -799,  811, -799, -799, -799, -799, -799, -799, -799,
+     -799, -799, -799, -799, -799, -799, -799, -799, -799, -799,
+     -799, -799, -799, -799, -799, -799, -799, -799, -799, -799,
+     -799, -799, -799, -799, -799, -799, -799, -799, -799, -799,
+     -799, -799, -799, -799, -799, -799, -799, -799, -799, -799,
+     -799, -799, -799, -799, -799, -799, -799, -799, -799, -799,
+     -799, -799, -799, -799, -799, -799, -799, -799, -799, -799,
+     -799, -799, -799, -799, -799, -799, -799, -799, -799, -799,
+     -799, -799, -799, -799, -799, -799, -799, -799, -799, -799,
+     -799, -799, -799, -799, -799, -799, -799, -799
+
+    },
+
+    {
+       67, -800, -800, -800, -800, -800, -800, -800, -800, -800,
+     -800, -800, -800, -800, -800, -800, -800, -800, -800, -800,
+     -800, -800, -800, -800, -800, -800, -800, -800, -800, -800,
+     -800, -800,  812, -800, -800, -800, -800, -800, -800, -800,
+     -800, -800, -800, -800, -800, -800, -800, -800, -800, -800,
+     -800, -800, -800, -800, -800, -800, -800, -800, -800, -800,
+     -800, -800, -800, -800, -800, -800, -800, -800, -800, -800,
+     -800, -800, -800, -800, -800, -800, -800, -800, -800, -800,
+     -800, -800, -800, -800, -800, -800, -800, -800, -800, -800,
+     -800, -800, -800, -800, -800, -800, -800, -800, -800, -800,
+
+     -800, -800, -800, -800, -800, -800, -800, -800, -800, -800,
+     -800, -800, -800, -800, -800, -800, -800, -800, -800, -800,
+     -800, -800, -800, -800, -800, -800, -800, -800
+    },
+
+    {
+       67, -801, -801, -801, -801, -801, -801, -801, -801, -801,
+     -801, -801, -801, -801, -801, -801, -801, -801, -801, -801,
+     -801, -801, -801, -801, -801, -801, -801, -801, -801, -801,
+     -801, -801,  813, -801, -801, -801, -801, -801, -801, -801,
+     -801, -801, -801, -801, -801, -801, -801, -801, -801, -801,
+     -801, -801, -801, -801, -801, -801, -801, -801, -801, -801,
+     -801, -801, -801, -801, -801, -801, -801, -801, -801, -801,
+
+     -801, -801, -801, -801, -801, -801, -801, -801, -801, -801,
+     -801, -801, -801, -801, -801, -801, -801, -801, -801, -801,
+     -801, -801, -801, -801, -801, -801, -801, -801, -801, -801,
+     -801, -801, -801, -801, -801, -801, -801, -801, -801, -801,
+     -801, -801, -801, -801, -801, -801, -801, -801, -801, -801,
+     -801, -801, -801, -801, -801, -801, -801, -801
+    },
+
+    {
+       67, -802, -802, -802, -802, -802, -802, -802, -802, -802,
+     -802, -802, -802, -802, -802, -802, -802, -802, -802, -802,
+     -802, -802, -802, -802, -802, -802, -802, -802, -802, -802,
+     -802, -802,  814, -802, -802, -802, -802, -802, -802, -802,
+
+     -802, -802, -802, -802, -802, -802, -802, -802, -802, -802,
+     -802, -802, -802, -802, -802, -802, -802, -802, -802, -802,
+     -802, -802, -802, -802, -802, -802, -802, -802, -802, -802,
+     -802, -802, -802, -802, -802, -802, -802, -802, -802, -802,
+     -802, -802, -802, -802, -802, -802, -802, -802, -802, -802,
+     -802, -802, -802, -802, -802, -802, -802, -802, -802, -802,
+     -802, -802, -802, -802, -802, -802, -802, -802, -802, -802,
+     -802, -802, -802, -802, -802, -802, -802, -802, -802, -802,
+     -802, -802, -802, -802, -802, -802, -802, -802
+    },
+
+    {
+       67, -803, -803, -803, -803, -803, -803, -803, -803, -803,
+
+     -803, -803, -803, -803, -803, -803, -803, -803, -803, -803,
+     -803, -803, -803, -803, -803, -803, -803, -803, -803, -803,
+     -803, -803,  815, -803, -803, -803, -803, -803, -803, -803,
+     -803, -803, -803, -803, -803, -803, -803, -803, -803, -803,
+     -803, -803, -803, -803, -803, -803, -803, -803, -803, -803,
+     -803, -803, -803, -803, -803, -803, -803, -803, -803, -803,
+     -803, -803, -803, -803, -803, -803, -803, -803, -803, -803,
+     -803, -803, -803, -803, -803, -803, -803, -803, -803, -803,
+     -803, -803, -803, -803, -803, -803, -803, -803, -803, -803,
+     -803, -803, -803, -803, -803, -803, -803, -803, -803, -803,
+
+     -803, -803, -803, -803, -803, -803, -803, -803, -803, -803,
+     -803, -803, -803, -803, -803, -803, -803, -803
+    },
+
+    {
+       67, -804, -804, -804, -804, -804, -804, -804, -804, -804,
+     -804, -804, -804, -804, -804, -804, -804, -804, -804, -804,
+     -804, -804, -804, -804, -804, -804, -804, -804, -804, -804,
+     -804, -804,  816, -804, -804, -804, -804, -804, -804, -804,
+     -804, -804, -804, -804, -804, -804, -804, -804, -804, -804,
+     -804, -804, -804, -804, -804, -804, -804, -804, -804, -804,
+     -804, -804, -804, -804, -804, -804, -804, -804, -804, -804,
+     -804, -804, -804, -804, -804, -804, -804, -804, -804, -804,
+
+     -804, -804, -804, -804, -804, -804, -804, -804, -804, -804,
+     -804, -804, -804, -804, -804, -804, -804, -804, -804, -804,
+     -804, -804, -804, -804, -804, -804, -804, -804, -804, -804,
+     -804, -804, -804, -804, -804, -804, -804, -804, -804, -804,
+     -804, -804, -804, -804, -804, -804, -804, -804
+    },
+
+    {
+       67, -805, -805, -805, -805, -805, -805, -805, -805, -805,
+     -805, -805, -805, -805, -805, -805, -805, -805, -805, -805,
+     -805, -805, -805, -805, -805, -805, -805, -805, -805, -805,
+     -805, -805,  817, -805, -805, -805, -805, -805, -805, -805,
+     -805, -805, -805, -805, -805, -805, -805, -805, -805, -805,
+
+     -805, -805, -805, -805, -805, -805, -805, -805, -805, -805,
+     -805, -805, -805, -805, -805, -805, -805, -805, -805, -805,
+     -805, -805, -805, -805, -805, -805, -805, -805, -805, -805,
+     -805, -805, -805, -805, -805, -805, -805, -805, -805, -805,
+     -805, -805, -805, -805, -805, -805, -805, -805, -805, -805,
+     -805, -805, -805, -805, -805, -805, -805, -805, -805, -805,
+     -805, -805, -805, -805, -805, -805, -805, -805, -805, -805,
+     -805, -805, -805, -805, -805, -805, -805, -805
+    },
+
+    {
+       67, -806, -806, -806, -806, -806, -806, -806, -806, -806,
+     -806, -806, -806, -806, -806, -806, -806, -806, -806, -806,
+
+     -806, -806, -806, -806, -806, -806, -806, -806, -806, -806,
+     -806, -806,  818, -806, -806, -806, -806, -806, -806, -806,
+     -806, -806, -806, -806, -806, -806, -806, -806, -806, -806,
+     -806, -806, -806, -806, -806, -806, -806, -806, -806, -806,
+     -806, -806, -806, -806, -806, -806, -806, -806, -806, -806,
+     -806, -806, -806, -806, -806, -806, -806, -806, -806, -806,
+     -806, -806, -806, -806, -806, -806, -806, -806, -806, -806,
+     -806, -806, -806, -806, -806, -806, -806, -806, -806, -806,
+     -806, -806, -806, -806, -806, -806, -806, -806, -806, -806,
+     -806, -806, -806, -806, -806, -806, -806, -806, -806, -806,
+
+     -806, -806, -806, -806, -806, -806, -806, -806
+    },
+
+    {
+       67, -807, -807, -807, -807, -807, -807, -807, -807, -807,
+     -807, -807, -807, -807, -807, -807, -807, -807, -807, -807,
+     -807, -807, -807, -807, -807, -807, -807, -807, -807, -807,
+     -807, -807,  819, -807, -807, -807, -807, -807, -807, -807,
+     -807, -807, -807,  820, -807,  820, -807, -807,  821,  821,
+      821,  821,  821,  821,  821,  821,  821,  821, -807, -807,
+     -807, -807, -807, -807, -807, -807, -807, -807, -807, -807,
+     -807, -807, -807, -807, -807, -807, -807, -807, -807, -807,
+     -807, -807, -807, -807, -807, -807, -807, -807, -807, -807,
+
+     -807, -807, -807, -807, -807, -807, -807, -807, -807, -807,
+     -807, -807, -807, -807, -807, -807, -807, -807, -807, -807,
+     -807, -807, -807, -807, -807, -807, -807, -807, -807, -807,
+     -807, -807, -807, -807, -807, -807, -807, -807
+    },
+
+    {
+       67, -808, -808, -808, -808, -808, -808, -808, -808, -808,
+     -808, -808, -808, -808, -808, -808, -808, -808, -808, -808,
+     -808, -808, -808, -808, -808, -808, -808, -808, -808, -808,
+     -808, -808,  822, -808, -808, -808, -808, -808, -808, -808,
+     -808, -808, -808,  823, -808,  823, -808, -808,  824,  824,
+      824,  824,  824,  824,  824,  824,  824,  824, -808, -808,
+
+     -808, -808, -808, -808, -808, -808, -808, -808, -808, -808,
+     -808, -808, -808, -808, -808, -808, -808, -808, -808, -808,
+     -808, -808, -808, -808, -808, -808, -808, -808, -808, -808,
+     -808, -808, -808, -808, -808, -808, -808, -808, -808, -808,
+     -808, -808, -808, -808, -808, -808, -808, -808, -808, -808,
+     -808, -808, -808, -808, -808, -808, -808, -808, -808, -808,
+     -808, -808, -808, -808, -808, -808, -808, -808
+    },
+
+    {
+       67, -809, -809, -809, -809, -809, -809, -809, -809, -809,
+     -809, -809, -809, -809, -809, -809, -809, -809, -809, -809,
+     -809, -809, -809, -809, -809, -809, -809, -809, -809, -809,
+
+     -809, -809,  825, -809, -809, -809, -809, -809, -809, -809,
+     -809, -809, -809,  826, -809,  826, -809, -809,  827,  827,
+      827,  827,  827,  827,  827,  827,  827,  827, -809, -809,
+     -809, -809, -809, -809, -809, -809, -809, -809, -809, -809,
+     -809, -809, -809, -809, -809, -809, -809, -809, -809, -809,
+     -809, -809, -809, -809, -809, -809, -809, -809, -809, -809,
+     -809, -809, -809, -809, -809, -809, -809, -809, -809, -809,
+     -809, -809, -809, -809, -809, -809, -809, -809, -809, -809,
+     -809, -809, -809, -809, -809, -809, -809, -809, -809, -809,
+     -809, -809, -809, -809, -809, -809, -809, -809
+
+    },
+
+    {
+       67, -810, -810, -810, -810, -810, -810, -810, -810, -810,
+     -810, -810, -810, -810, -810, -810, -810, -810, -810, -810,
+     -810, -810, -810, -810, -810, -810, -810, -810, -810, -810,
+     -810, -810,  828, -810, -810, -810, -810, -810, -810, -810,
+     -810, -810, -810,  829, -810,  829, -810, -810,  830,  830,
+      830,  830,  830,  830,  830,  830,  830,  830, -810, -810,
+     -810, -810, -810, -810, -810, -810, -810, -810, -810, -810,
+     -810, -810, -810, -810, -810, -810, -810, -810, -810, -810,
+     -810, -810, -810, -810, -810, -810, -810, -810, -810, -810,
+     -810, -810, -810, -810, -810, -810, -810, -810, -810, -810,
+
+     -810, -810, -810, -810, -810, -810, -810, -810, -810, -810,
+     -810, -810, -810, -810, -810, -810, -810, -810, -810, -810,
+     -810, -810, -810, -810, -810, -810, -810, -810
+    },
+
+    {
+       67, -811, -811, -811, -811, -811, -811, -811, -811, -811,
+     -811, -811, -811, -811, -811, -811, -811, -811, -811, -811,
+     -811, -811, -811, -811, -811, -811, -811, -811, -811, -811,
+     -811, -811,  831, -811, -811, -811, -811, -811, -811, -811,
+     -811, -811, -811,  832, -811,  832, -811, -811,  833,  833,
+      833,  833,  833,  833,  833,  833,  833,  833, -811, -811,
+     -811, -811, -811, -811, -811, -811, -811, -811, -811, -811,
+
+     -811, -811, -811, -811, -811, -811, -811, -811, -811, -811,
+     -811, -811, -811, -811, -811, -811, -811, -811, -811, -811,
+     -811, -811, -811, -811, -811, -811, -811, -811, -811, -811,
+     -811, -811, -811, -811, -811, -811, -811, -811, -811, -811,
+     -811, -811, -811, -811, -811, -811, -811, -811, -811, -811,
+     -811, -811, -811, -811, -811, -811, -811, -811
+    },
+
+    {
+       67, -812, -812, -812, -812, -812, -812, -812, -812, -812,
+     -812, -812, -812, -812, -812, -812, -812, -812, -812, -812,
+     -812, -812, -812, -812, -812, -812, -812, -812, -812, -812,
+     -812, -812,  834, -812, -812, -812, -812, -812, -812,  835,
+
+     -812, -812, -812, -812, -812, -812, -812, -812, -812, -812,
+     -812, -812, -812, -812, -812, -812, -812, -812, -812, -812,
+     -812, -812, -812, -812, -812, -812, -812, -812, -812, -812,
+     -812, -812, -812, -812, -812, -812, -812, -812, -812, -812,
+     -812, -812, -812, -812, -812, -812, -812, -812, -812, -812,
+     -812, -812, -812, -812, -812, -812, -812, -812, -812, -812,
+     -812, -812, -812, -812, -812, -812, -812, -812, -812, -812,
+     -812, -812, -812, -812, -812, -812, -812, -812, -812, -812,
+     -812, -812, -812, -812, -812, -812, -812, -812
+    },
+
+    {
+       67, -813, -813, -813, -813, -813, -813, -813, -813, -813,
+
+     -813, -813, -813, -813, -813, -813, -813, -813, -813, -813,
+     -813, -813, -813, -813, -813, -813, -813, -813, -813, -813,
+     -813, -813,  836, -813, -813, -813, -813, -813, -813,  837,
+     -813, -813, -813, -813, -813, -813, -813, -813, -813, -813,
+     -813, -813, -813, -813, -813, -813, -813, -813, -813, -813,
+     -813, -813, -813, -813, -813, -813, -813, -813, -813, -813,
+     -813, -813, -813, -813, -813, -813, -813, -813, -813, -813,
+     -813, -813, -813, -813, -813, -813, -813, -813, -813, -813,
+     -813, -813, -813, -813, -813, -813, -813, -813, -813, -813,
+     -813, -813, -813, -813, -813, -813, -813, -813, -813, -813,
+
+     -813, -813, -813, -813, -813, -813, -813, -813, -813, -813,
+     -813, -813, -813, -813, -813, -813, -813, -813
+    },
+
+    {
+       67, -814, -814, -814, -814, -814, -814, -814, -814, -814,
+     -814, -814, -814, -814, -814, -814, -814, -814, -814, -814,
+     -814, -814, -814, -814, -814, -814, -814, -814, -814, -814,
+     -814, -814,  838, -814, -814, -814, -814, -814, -814,  839,
+     -814, -814, -814, -814, -814, -814, -814, -814, -814, -814,
+     -814, -814, -814, -814, -814, -814, -814, -814, -814, -814,
+     -814, -814, -814, -814, -814, -814, -814, -814, -814, -814,
+     -814, -814, -814, -814, -814, -814, -814, -814, -814, -814,
+
+     -814, -814, -814, -814, -814, -814, -814, -814, -814, -814,
+     -814, -814, -814, -814, -814, -814, -814, -814, -814, -814,
+     -814, -814, -814, -814, -814, -814, -814, -814, -814, -814,
+     -814, -814, -814, -814, -814, -814, -814, -814, -814, -814,
+     -814, -814, -814, -814, -814, -814, -814, -814
+    },
+
+    {
+       67, -815, -815, -815, -815, -815, -815, -815, -815, -815,
+     -815, -815, -815, -815, -815, -815, -815, -815, -815, -815,
+     -815, -815, -815, -815, -815, -815, -815, -815, -815, -815,
+     -815, -815,  840, -815, -815, -815, -815, -815, -815,  841,
+     -815, -815, -815, -815, -815, -815, -815, -815, -815, -815,
+
+     -815, -815, -815, -815, -815, -815, -815, -815, -815, -815,
+     -815, -815, -815, -815, -815, -815, -815, -815, -815, -815,
+     -815, -815, -815, -815, -815, -815, -815, -815, -815, -815,
+     -815, -815, -815, -815, -815, -815, -815, -815, -815, -815,
+     -815, -815, -815, -815, -815, -815, -815, -815, -815, -815,
+     -815, -815, -815, -815, -815, -815, -815, -815, -815, -815,
+     -815, -815, -815, -815, -815, -815, -815, -815, -815, -815,
+     -815, -815, -815, -815, -815, -815, -815, -815
+    },
+
+    {
+       67, -816, -816, -816, -816, -816, -816, -816, -816, -816,
+     -816, -816, -816, -816, -816, -816, -816, -816, -816, -816,
+
+     -816, -816, -816, -816, -816, -816, -816, -816, -816, -816,
+     -816, -816,  842, -816, -816, -816, -816, -816, -816,  843,
+     -816, -816, -816, -816, -816, -816, -816, -816, -816, -816,
+     -816, -816, -816, -816, -816, -816, -816, -816, -816, -816,
+     -816, -816, -816, -816, -816, -816, -816, -816, -816, -816,
+     -816, -816, -816, -816, -816, -816, -816, -816, -816, -816,
+     -816, -816, -816, -816, -816, -816, -816, -816, -816, -816,
+     -816, -816, -816, -816, -816, -816, -816, -816, -816, -816,
+     -816, -816, -816, -816, -816, -816, -816, -816, -816, -816,
+     -816, -816, -816, -816, -816, -816, -816, -816, -816, -816,
+
+     -816, -816, -816, -816, -816, -816, -816, -816
+    },
+
+    {
+       67, -817, -817, -817, -817, -817, -817, -817, -817, -817,
+     -817, -817, -817, -817, -817, -817, -817, -817, -817, -817,
+     -817, -817, -817, -817, -817, -817, -817, -817, -817, -817,
+     -817, -817,  844, -817, -817, -817, -817, -817, -817,  845,
+     -817, -817, -817, -817, -817, -817, -817, -817, -817, -817,
+     -817, -817, -817, -817, -817, -817, -817, -817, -817, -817,
+     -817, -817, -817, -817, -817, -817, -817, -817, -817, -817,
+     -817, -817, -817, -817, -817, -817, -817, -817, -817, -817,
+     -817, -817, -817, -817, -817, -817, -817, -817, -817, -817,
+
+     -817, -817, -817, -817, -817, -817, -817, -817, -817, -817,
+     -817, -817, -817, -817, -817, -817, -817, -817, -817, -817,
+     -817, -817, -817, -817, -817, -817, -817, -817, -817, -817,
+     -817, -817, -817, -817, -817, -817, -817, -817
+    },
+
+    {
+       67, -818, -818, -818, -818, -818, -818, -818, -818, -818,
+     -818, -818, -818, -818, -818, -818, -818, -818, -818, -818,
+     -818, -818, -818, -818, -818, -818, -818, -818, -818, -818,
+     -818, -818,  846, -818, -818, -818, -818, -818, -818, -818,
+     -818, -818, -818, -818, -818, -818, -818, -818, -818, -818,
+     -818, -818, -818, -818, -818, -818, -818, -818, -818, -818,
+
+     -818, -818, -818, -818, -818, -818, -818, -818, -818, -818,
+     -818, -818, -818, -818, -818, -818, -818, -818, -818, -818,
+     -818, -818, -818, -818, -818, -818, -818, -818, -818, -818,
+     -818, -818, -818, -818, -818, -818, -818, -818, -818, -818,
+     -818, -818, -818, -818, -818, -818, -818, -818, -818, -818,
+     -818, -818, -818, -818, -818, -818, -818, -818, -818, -818,
+     -818, -818, -818, -818, -818, -818, -818, -818
+    },
+
+    {
+       67, -819, -819, -819, -819, -819, -819, -819, -819, -819,
+     -819, -819, -819, -819, -819, -819, -819, -819, -819, -819,
+     -819, -819, -819, -819, -819, -819, -819, -819, -819, -819,
+
+     -819, -819,  819, -819, -819, -819, -819, -819, -819, -819,
+     -819, -819, -819,  820, -819,  820, -819, -819,  821,  821,
+      821,  821,  821,  821,  821,  821,  821,  821, -819, -819,
+     -819, -819, -819, -819, -819, -819, -819, -819, -819, -819,
+     -819, -819, -819, -819, -819, -819, -819, -819, -819, -819,
+     -819, -819, -819, -819, -819, -819, -819, -819, -819, -819,
+     -819, -819, -819, -819, -819, -819, -819, -819, -819, -819,
+     -819, -819, -819, -819, -819, -819, -819, -819, -819, -819,
+     -819, -819, -819, -819, -819, -819, -819, -819, -819, -819,
+     -819, -819, -819, -819, -819, -819, -819, -819
+
+    },
+
+    {
+       67, -820, -820, -820, -820, -820, -820, -820, -820, -820,
+     -820, -820, -820, -820, -820, -820, -820, -820, -820, -820,
+     -820, -820, -820, -820, -820, -820, -820, -820, -820, -820,
+     -820, -820, -820, -820, -820, -820, -820, -820, -820, -820,
+     -820, -820, -820, -820, -820, -820, -820, -820,  821,  821,
+      821,  821,  821,  821,  821,  821,  821,  821, -820, -820,
+     -820, -820, -820, -820, -820, -820, -820, -820, -820, -820,
+     -820, -820, -820, -820, -820, -820, -820, -820, -820, -820,
+     -820, -820, -820, -820, -820, -820, -820, -820, -820, -820,
+     -820, -820, -820, -820, -820, -820, -820, -820, -820, -820,
+
+     -820, -820, -820, -820, -820, -820, -820, -820, -820, -820,
+     -820, -820, -820, -820, -820, -820, -820, -820, -820, -820,
+     -820, -820, -820, -820, -820, -820, -820, -820
+    },
+
+    {
+       67, -821, -821, -821, -821, -821, -821, -821, -821, -821,
+     -821, -821, -821, -821, -821, -821, -821, -821, -821, -821,
+     -821, -821, -821, -821, -821, -821, -821, -821, -821, -821,
+     -821, -821, -821, -821, -821, -821, -821, -821, -821, -821,
+     -821, -821, -821, -821, -821, -821, -821, -821,  821,  821,
+      821,  821,  821,  821,  821,  821,  821,  821, -821, -821,
+     -821, -821, -821, -821, -821, -821, -821, -821, -821, -821,
+
+     -821, -821, -821, -821, -821, -821, -821, -821, -821, -821,
+     -821, -821, -821, -821, -821, -821, -821, -821, -821, -821,
+     -821, -821, -821, -821, -821, -821, -821, -821, -821, -821,
+     -821, -821, -821, -821, -821, -821, -821, -821, -821, -821,
+     -821, -821, -821, -821, -821, -821, -821, -821, -821, -821,
+     -821, -821, -821, -821, -821, -821, -821, -821
+    },
+
+    {
+       67, -822, -822, -822, -822, -822, -822, -822, -822, -822,
+     -822, -822, -822, -822, -822, -822, -822, -822, -822, -822,
+     -822, -822, -822, -822, -822, -822, -822, -822, -822, -822,
+     -822, -822,  822, -822, -822, -822, -822, -822, -822, -822,
+
+     -822, -822, -822,  823, -822,  823, -822, -822,  824,  824,
+      824,  824,  824,  824,  824,  824,  824,  824, -822, -822,
+     -822, -822, -822, -822, -822, -822, -822, -822, -822, -822,
+     -822, -822, -822, -822, -822, -822, -822, -822, -822, -822,
+     -822, -822, -822, -822, -822, -822, -822, -822, -822, -822,
+     -822, -822, -822, -822, -822, -822, -822, -822, -822, -822,
+     -822, -822, -822, -822, -822, -822, -822, -822, -822, -822,
+     -822, -822, -822, -822, -822, -822, -822, -822, -822, -822,
+     -822, -822, -822, -822, -822, -822, -822, -822
+    },
+
+    {
+       67, -823, -823, -823, -823, -823, -823, -823, -823, -823,
+
+     -823, -823, -823, -823, -823, -823, -823, -823, -823, -823,
+     -823, -823, -823, -823, -823, -823, -823, -823, -823, -823,
+     -823, -823, -823, -823, -823, -823, -823, -823, -823, -823,
+     -823, -823, -823, -823, -823, -823, -823, -823,  824,  824,
+      824,  824,  824,  824,  824,  824,  824,  824, -823, -823,
+     -823, -823, -823, -823, -823, -823, -823, -823, -823, -823,
+     -823, -823, -823, -823, -823, -823, -823, -823, -823, -823,
+     -823, -823, -823, -823, -823, -823, -823, -823, -823, -823,
+     -823, -823, -823, -823, -823, -823, -823, -823, -823, -823,
+     -823, -823, -823, -823, -823, -823, -823, -823, -823, -823,
+
+     -823, -823, -823, -823, -823, -823, -823, -823, -823, -823,
+     -823, -823, -823, -823, -823, -823, -823, -823
+    },
+
+    {
+       67, -824, -824, -824, -824, -824, -824, -824, -824, -824,
+     -824, -824, -824, -824, -824, -824, -824, -824, -824, -824,
+     -824, -824, -824, -824, -824, -824, -824, -824, -824, -824,
+     -824, -824, -824, -824, -824, -824, -824, -824, -824, -824,
+     -824, -824, -824, -824, -824, -824, -824, -824,  824,  824,
+      824,  824,  824,  824,  824,  824,  824,  824, -824, -824,
+     -824, -824, -824, -824, -824, -824, -824, -824, -824, -824,
+     -824, -824, -824, -824, -824, -824, -824, -824, -824, -824,
+
+     -824, -824, -824, -824, -824, -824, -824, -824, -824, -824,
+     -824, -824, -824, -824, -824, -824, -824, -824, -824, -824,
+     -824, -824, -824, -824, -824, -824, -824, -824, -824, -824,
+     -824, -824, -824, -824, -824, -824, -824, -824, -824, -824,
+     -824, -824, -824, -824, -824, -824, -824, -824
+    },
+
+    {
+       67, -825, -825, -825, -825, -825, -825, -825, -825, -825,
+     -825, -825, -825, -825, -825, -825, -825, -825, -825, -825,
+     -825, -825, -825, -825, -825, -825, -825, -825, -825, -825,
+     -825, -825,  825, -825, -825, -825, -825, -825, -825, -825,
+     -825, -825, -825,  826, -825,  826, -825, -825,  827,  827,
+
+      827,  827,  827,  827,  827,  827,  827,  827, -825, -825,
+     -825, -825, -825, -825, -825, -825, -825, -825, -825, -825,
+     -825, -825, -825, -825, -825, -825, -825, -825, -825, -825,
+     -825, -825, -825, -825, -825, -825, -825, -825, -825, -825,
+     -825, -825, -825, -825, -825, -825, -825, -825, -825, -825,
+     -825, -825, -825, -825, -825, -825, -825, -825, -825, -825,
+     -825, -825, -825, -825, -825, -825, -825, -825, -825, -825,
+     -825, -825, -825, -825, -825, -825, -825, -825
+    },
+
+    {
+       67, -826, -826, -826, -826, -826, -826, -826, -826, -826,
+     -826, -826, -826, -826, -826, -826, -826, -826, -826, -826,
+
+     -826, -826, -826, -826, -826, -826, -826, -826, -826, -826,
+     -826, -826, -826, -826, -826, -826, -826, -826, -826, -826,
+     -826, -826, -826, -826, -826, -826, -826, -826,  827,  827,
+      827,  827,  827,  827,  827,  827,  827,  827, -826, -826,
+     -826, -826, -826, -826, -826, -826, -826, -826, -826, -826,
+     -826, -826, -826, -826, -826, -826, -826, -826, -826, -826,
+     -826, -826, -826, -826, -826, -826, -826, -826, -826, -826,
+     -826, -826, -826, -826, -826, -826, -826, -826, -826, -826,
+     -826, -826, -826, -826, -826, -826, -826, -826, -826, -826,
+     -826, -826, -826, -826, -826, -826, -826, -826, -826, -826,
+
+     -826, -826, -826, -826, -826, -826, -826, -826
+    },
+
+    {
+       67, -827, -827, -827, -827, -827, -827, -827, -827, -827,
+     -827, -827, -827, -827, -827, -827, -827, -827, -827, -827,
+     -827, -827, -827, -827, -827, -827, -827, -827, -827, -827,
+     -827, -827, -827, -827, -827, -827, -827, -827, -827, -827,
+     -827, -827, -827, -827, -827, -827, -827, -827,  827,  827,
+      827,  827,  827,  827,  827,  827,  827,  827, -827, -827,
+     -827, -827, -827, -827, -827, -827, -827, -827, -827, -827,
+     -827, -827, -827, -827, -827, -827, -827, -827, -827, -827,
+     -827, -827, -827, -827, -827, -827, -827, -827, -827, -827,
+
+     -827, -827, -827, -827, -827, -827, -827, -827, -827, -827,
+     -827, -827, -827, -827, -827, -827, -827, -827, -827, -827,
+     -827, -827, -827, -827, -827, -827, -827, -827, -827, -827,
+     -827, -827, -827, -827, -827, -827, -827, -827
+    },
+
+    {
+       67, -828, -828, -828, -828, -828, -828, -828, -828, -828,
+     -828, -828, -828, -828, -828, -828, -828, -828, -828, -828,
+     -828, -828, -828, -828, -828, -828, -828, -828, -828, -828,
+     -828, -828,  828, -828, -828, -828, -828, -828, -828, -828,
+     -828, -828, -828,  829, -828,  829, -828, -828,  830,  830,
+      830,  830,  830,  830,  830,  830,  830,  830, -828, -828,
+
+     -828, -828, -828, -828, -828, -828, -828, -828, -828, -828,
+     -828, -828, -828, -828, -828, -828, -828, -828, -828, -828,
+     -828, -828, -828, -828, -828, -828, -828, -828, -828, -828,
+     -828, -828, -828, -828, -828, -828, -828, -828, -828, -828,
+     -828, -828, -828, -828, -828, -828, -828, -828, -828, -828,
+     -828, -828, -828, -828, -828, -828, -828, -828, -828, -828,
+     -828, -828, -828, -828, -828, -828, -828, -828
+    },
+
+    {
+       67, -829, -829, -829, -829, -829, -829, -829, -829, -829,
+     -829, -829, -829, -829, -829, -829, -829, -829, -829, -829,
+     -829, -829, -829, -829, -829, -829, -829, -829, -829, -829,
+
+     -829, -829, -829, -829, -829, -829, -829, -829, -829, -829,
+     -829, -829, -829, -829, -829, -829, -829, -829,  830,  830,
+      830,  830,  830,  830,  830,  830,  830,  830, -829, -829,
+     -829, -829, -829, -829, -829, -829, -829, -829, -829, -829,
+     -829, -829, -829, -829, -829, -829, -829, -829, -829, -829,
+     -829, -829, -829, -829, -829, -829, -829, -829, -829, -829,
+     -829, -829, -829, -829, -829, -829, -829, -829, -829, -829,
+     -829, -829, -829, -829, -829, -829, -829, -829, -829, -829,
+     -829, -829, -829, -829, -829, -829, -829, -829, -829, -829,
+     -829, -829, -829, -829, -829, -829, -829, -829
+
+    },
+
+    {
+       67, -830, -830, -830, -830, -830, -830, -830, -830, -830,
+     -830, -830, -830, -830, -830, -830, -830, -830, -830, -830,
+     -830, -830, -830, -830, -830, -830, -830, -830, -830, -830,
+     -830, -830, -830, -830, -830, -830, -830, -830, -830, -830,
+     -830, -830, -830, -830, -830, -830, -830, -830,  830,  830,
+      830,  830,  830,  830,  830,  830,  830,  830, -830, -830,
+     -830, -830, -830, -830, -830, -830, -830, -830, -830, -830,
+     -830, -830, -830, -830, -830, -830, -830, -830, -830, -830,
+     -830, -830, -830, -830, -830, -830, -830, -830, -830, -830,
+     -830, -830, -830, -830, -830, -830, -830, -830, -830, -830,
+
+     -830, -830, -830, -830, -830, -830, -830, -830, -830, -830,
+     -830, -830, -830, -830, -830, -830, -830, -830, -830, -830,
+     -830, -830, -830, -830, -830, -830, -830, -830
+    },
+
+    {
+       67, -831, -831, -831, -831, -831, -831, -831, -831, -831,
+     -831, -831, -831, -831, -831, -831, -831, -831, -831, -831,
+     -831, -831, -831, -831, -831, -831, -831, -831, -831, -831,
+     -831, -831,  831, -831, -831, -831, -831, -831, -831, -831,
+     -831, -831, -831,  832, -831,  832, -831, -831,  833,  833,
+      833,  833,  833,  833,  833,  833,  833,  833, -831, -831,
+     -831, -831, -831, -831, -831, -831, -831, -831, -831, -831,
+
+     -831, -831, -831, -831, -831, -831, -831, -831, -831, -831,
+     -831, -831, -831, -831, -831, -831, -831, -831, -831, -831,
+     -831, -831, -831, -831, -831, -831, -831, -831, -831, -831,
+     -831, -831, -831, -831, -831, -831, -831, -831, -831, -831,
+     -831, -831, -831, -831, -831, -831, -831, -831, -831, -831,
+     -831, -831, -831, -831, -831, -831, -831, -831
+    },
+
+    {
+       67, -832, -832, -832, -832, -832, -832, -832, -832, -832,
+     -832, -832, -832, -832, -832, -832, -832, -832, -832, -832,
+     -832, -832, -832, -832, -832, -832, -832, -832, -832, -832,
+     -832, -832, -832, -832, -832, -832, -832, -832, -832, -832,
+
+     -832, -832, -832, -832, -832, -832, -832, -832,  833,  833,
+      833,  833,  833,  833,  833,  833,  833,  833, -832, -832,
+     -832, -832, -832, -832, -832, -832, -832, -832, -832, -832,
+     -832, -832, -832, -832, -832, -832, -832, -832, -832, -832,
+     -832, -832, -832, -832, -832, -832, -832, -832, -832, -832,
+     -832, -832, -832, -832, -832, -832, -832, -832, -832, -832,
+     -832, -832, -832, -832, -832, -832, -832, -832, -832, -832,
+     -832, -832, -832, -832, -832, -832, -832, -832, -832, -832,
+     -832, -832, -832, -832, -832, -832, -832, -832
+    },
+
+    {
+       67, -833, -833, -833, -833, -833, -833, -833, -833, -833,
+
+     -833, -833, -833, -833, -833, -833, -833, -833, -833, -833,
+     -833, -833, -833, -833, -833, -833, -833, -833, -833, -833,
+     -833, -833, -833, -833, -833, -833, -833, -833, -833, -833,
+     -833, -833, -833, -833, -833, -833, -833, -833,  833,  833,
+      833,  833,  833,  833,  833,  833,  833,  833, -833, -833,
+     -833, -833, -833, -833, -833, -833, -833, -833, -833, -833,
+     -833, -833, -833, -833, -833, -833, -833, -833, -833, -833,
+     -833, -833, -833, -833, -833, -833, -833, -833, -833, -833,
+     -833, -833, -833, -833, -833, -833, -833, -833, -833, -833,
+     -833, -833, -833, -833, -833, -833, -833, -833, -833, -833,
+
+     -833, -833, -833, -833, -833, -833, -833, -833, -833, -833,
+     -833, -833, -833, -833, -833, -833, -833, -833
+    },
+
+    {
+       67, -834, -834, -834, -834, -834, -834, -834, -834, -834,
+     -834, -834, -834, -834, -834, -834, -834, -834, -834, -834,
+     -834, -834, -834, -834, -834, -834, -834, -834, -834, -834,
+     -834, -834,  834, -834, -834, -834, -834, -834, -834,  835,
+     -834, -834, -834, -834, -834, -834, -834, -834, -834, -834,
+     -834, -834, -834, -834, -834, -834, -834, -834, -834, -834,
+     -834, -834, -834, -834, -834, -834, -834, -834, -834, -834,
+     -834, -834, -834, -834, -834, -834, -834, -834, -834, -834,
+
+     -834, -834, -834, -834, -834, -834, -834, -834, -834, -834,
+     -834, -834, -834, -834, -834, -834, -834, -834, -834, -834,
+     -834, -834, -834, -834, -834, -834, -834, -834, -834, -834,
+     -834, -834, -834, -834, -834, -834, -834, -834, -834, -834,
+     -834, -834, -834, -834, -834, -834, -834, -834
+    },
+
+    {
+       67,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  848,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847
+    },
+
+    {
+       67, -836, -836, -836, -836, -836, -836, -836, -836, -836,
+     -836, -836, -836, -836, -836, -836, -836, -836, -836, -836,
+
+     -836, -836, -836, -836, -836, -836, -836, -836, -836, -836,
+     -836, -836,  836, -836, -836, -836, -836, -836, -836,  837,
+     -836, -836, -836, -836, -836, -836, -836, -836, -836, -836,
+     -836, -836, -836, -836, -836, -836, -836, -836, -836, -836,
+     -836, -836, -836, -836, -836, -836, -836, -836, -836, -836,
+     -836, -836, -836, -836, -836, -836, -836, -836, -836, -836,
+     -836, -836, -836, -836, -836, -836, -836, -836, -836, -836,
+     -836, -836, -836, -836, -836, -836, -836, -836, -836, -836,
+     -836, -836, -836, -836, -836, -836, -836, -836, -836, -836,
+     -836, -836, -836, -836, -836, -836, -836, -836, -836, -836,
+
+     -836, -836, -836, -836, -836, -836, -836, -836
+    },
+
+    {
+       67,  849,  849,  849,  849,  849,  849,  849,  849,  849,
+      849,  849,  849,  849,  849,  849,  849,  849,  849,  849,
+      849,  849,  849,  849,  849,  849,  849,  849,  849,  849,
+      849,  849,  849,  849,  849,  849,  849,  849,  849,  850,
+      849,  849,  849,  849,  849,  849,  849,  849,  849,  849,
+      849,  849,  849,  849,  849,  849,  849,  849,  849,  849,
+      849,  849,  849,  849,  849,  849,  849,  849,  849,  849,
+      849,  849,  849,  849,  849,  849,  849,  849,  849,  849,
+      849,  849,  849,  849,  849,  849,  849,  849,  849,  849,
+
+      849,  849,  849,  849,  849,  849,  849,  849,  849,  849,
+      849,  849,  849,  849,  849,  849,  849,  849,  849,  849,
+      849,  849,  849,  849,  849,  849,  849,  849,  849,  849,
+      849,  849,  849,  849,  849,  849,  849,  849
+    },
+
+    {
+       67, -838, -838, -838, -838, -838, -838, -838, -838, -838,
+     -838, -838, -838, -838, -838, -838, -838, -838, -838, -838,
+     -838, -838, -838, -838, -838, -838, -838, -838, -838, -838,
+     -838, -838,  838, -838, -838, -838, -838, -838, -838,  839,
+     -838, -838, -838, -838, -838, -838, -838, -838, -838, -838,
+     -838, -838, -838, -838, -838, -838, -838, -838, -838, -838,
+
+     -838, -838, -838, -838, -838, -838, -838, -838, -838, -838,
+     -838, -838, -838, -838, -838, -838, -838, -838, -838, -838,
+     -838, -838, -838, -838, -838, -838, -838, -838, -838, -838,
+     -838, -838, -838, -838, -838, -838, -838, -838, -838, -838,
+     -838, -838, -838, -838, -838, -838, -838, -838, -838, -838,
+     -838, -838, -838, -838, -838, -838, -838, -838, -838, -838,
+     -838, -838, -838, -838, -838, -838, -838, -838
+    },
+
+    {
+       67,  851,  851,  851,  851,  851,  851,  851,  851,  851,
+      851,  851,  851,  851,  851,  851,  851,  851,  851,  851,
+      851,  851,  851,  851,  851,  851,  851,  851,  851,  851,
+
+      851,  851,  851,  851,  851,  851,  851,  851,  851,  852,
+      851,  851,  851,  851,  851,  851,  851,  851,  851,  851,
+      851,  851,  851,  851,  851,  851,  851,  851,  851,  851,
+      851,  851,  851,  851,  851,  851,  851,  851,  851,  851,
+      851,  851,  851,  851,  851,  851,  851,  851,  851,  851,
+      851,  851,  851,  851,  851,  851,  851,  851,  851,  851,
+      851,  851,  851,  851,  851,  851,  851,  851,  851,  851,
+      851,  851,  851,  851,  851,  851,  851,  851,  851,  851,
+      851,  851,  851,  851,  851,  851,  851,  851,  851,  851,
+      851,  851,  851,  851,  851,  851,  851,  851
+
+    },
+
+    {
+       67, -840, -840, -840, -840, -840, -840, -840, -840, -840,
+     -840, -840, -840, -840, -840, -840, -840, -840, -840, -840,
+     -840, -840, -840, -840, -840, -840, -840, -840, -840, -840,
+     -840, -840,  840, -840, -840, -840, -840, -840, -840,  841,
+     -840, -840, -840, -840, -840, -840, -840, -840, -840, -840,
+     -840, -840, -840, -840, -840, -840, -840, -840, -840, -840,
+     -840, -840, -840, -840, -840, -840, -840, -840, -840, -840,
+     -840, -840, -840, -840, -840, -840, -840, -840, -840, -840,
+     -840, -840, -840, -840, -840, -840, -840, -840, -840, -840,
+     -840, -840, -840, -840, -840, -840, -840, -840, -840, -840,
+
+     -840, -840, -840, -840, -840, -840, -840, -840, -840, -840,
+     -840, -840, -840, -840, -840, -840, -840, -840, -840, -840,
+     -840, -840, -840, -840, -840, -840, -840, -840
+    },
+
+    {
+       67,  853,  853,  853,  853,  853,  853,  853,  853,  853,
+      853,  853,  853,  853,  853,  853,  853,  853,  853,  853,
+      853,  853,  853,  853,  853,  853,  853,  853,  853,  853,
+      853,  853,  853,  853,  853,  853,  853,  853,  853,  854,
+      853,  853,  853,  853,  853,  853,  853,  853,  853,  853,
+      853,  853,  853,  853,  853,  853,  853,  853,  853,  853,
+      853,  853,  853,  853,  853,  853,  853,  853,  853,  853,
+
+      853,  853,  853,  853,  853,  853,  853,  853,  853,  853,
+      853,  853,  853,  853,  853,  853,  853,  853,  853,  853,
+      853,  853,  853,  853,  853,  853,  853,  853,  853,  853,
+      853,  853,  853,  853,  853,  853,  853,  853,  853,  853,
+      853,  853,  853,  853,  853,  853,  853,  853,  853,  853,
+      853,  853,  853,  853,  853,  853,  853,  853
+    },
+
+    {
+       67, -842, -842, -842, -842, -842, -842, -842, -842, -842,
+     -842, -842, -842, -842, -842, -842, -842, -842, -842, -842,
+     -842, -842, -842, -842, -842, -842, -842, -842, -842, -842,
+     -842, -842,  842, -842, -842, -842, -842, -842, -842,  843,
+
+     -842, -842, -842, -842, -842, -842, -842, -842, -842, -842,
+     -842, -842, -842, -842, -842, -842, -842, -842, -842, -842,
+     -842, -842, -842, -842, -842, -842, -842, -842, -842, -842,
+     -842, -842, -842, -842, -842, -842, -842, -842, -842, -842,
+     -842, -842, -842, -842, -842, -842, -842, -842, -842, -842,
+     -842, -842, -842, -842, -842, -842, -842, -842, -842, -842,
+     -842, -842, -842, -842, -842, -842, -842, -842, -842, -842,
+     -842, -842, -842, -842, -842, -842, -842, -842, -842, -842,
+     -842, -842, -842, -842, -842, -842, -842, -842
+    },
+
+    {
+       67,  855,  855,  855,  855,  855,  855,  855,  855,  855,
+
+      855,  855,  855,  855,  855,  855,  855,  855,  855,  855,
+      855,  855,  855,  855,  855,  855,  855,  855,  855,  855,
+      855,  855,  855,  855,  855,  855,  855,  855,  855,  856,
+      855,  855,  855,  855,  855,  855,  855,  855,  855,  855,
+      855,  855,  855,  855,  855,  855,  855,  855,  855,  855,
+      855,  855,  855,  855,  855,  855,  855,  855,  855,  855,
+      855,  855,  855,  855,  855,  855,  855,  855,  855,  855,
+      855,  855,  855,  855,  855,  855,  855,  855,  855,  855,
+      855,  855,  855,  855,  855,  855,  855,  855,  855,  855,
+      855,  855,  855,  855,  855,  855,  855,  855,  855,  855,
+
+      855,  855,  855,  855,  855,  855,  855,  855,  855,  855,
+      855,  855,  855,  855,  855,  855,  855,  855
+    },
+
+    {
+       67, -844, -844, -844, -844, -844, -844, -844, -844, -844,
+     -844, -844, -844, -844, -844, -844, -844, -844, -844, -844,
+     -844, -844, -844, -844, -844, -844, -844, -844, -844, -844,
+     -844, -844,  844, -844, -844, -844, -844, -844, -844,  845,
+     -844, -844, -844, -844, -844, -844, -844, -844, -844, -844,
+     -844, -844, -844, -844, -844, -844, -844, -844, -844, -844,
+     -844, -844, -844, -844, -844, -844, -844, -844, -844, -844,
+     -844, -844, -844, -844, -844, -844, -844, -844, -844, -844,
+
+     -844, -844, -844, -844, -844, -844, -844, -844, -844, -844,
+     -844, -844, -844, -844, -844, -844, -844, -844, -844, -844,
+     -844, -844, -844, -844, -844, -844, -844, -844, -844, -844,
+     -844, -844, -844, -844, -844, -844, -844, -844, -844, -844,
+     -844, -844, -844, -844, -844, -844, -844, -844
+    },
+
+    {
+       67,  857,  857,  857,  857,  857,  857,  857,  857,  857,
+      857,  857,  857,  857,  857,  857,  857,  857,  857,  857,
+      857,  857,  857,  857,  857,  857,  857,  857,  857,  857,
+      857,  857,  857,  857,  857,  857,  857,  857,  857,  858,
+      857,  857,  857,  857,  857,  857,  857,  857,  857,  857,
+
+      857,  857,  857,  857,  857,  857,  857,  857,  857,  857,
+      857,  857,  857,  857,  857,  857,  857,  857,  857,  857,
+      857,  857,  857,  857,  857,  857,  857,  857,  857,  857,
+      857,  857,  857,  857,  857,  857,  857,  857,  857,  857,
+      857,  857,  857,  857,  857,  857,  857,  857,  857,  857,
+      857,  857,  857,  857,  857,  857,  857,  857,  857,  857,
+      857,  857,  857,  857,  857,  857,  857,  857,  857,  857,
+      857,  857,  857,  857,  857,  857,  857,  857
+    },
+
+    {
+       67, -846, -846, -846, -846, -846, -846, -846, -846, -846,
+     -846, -846, -846, -846, -846, -846, -846, -846, -846, -846,
+
+     -846, -846, -846, -846, -846, -846, -846, -846, -846, -846,
+     -846, -846,  859, -846, -846, -846, -846, -846, -846, -846,
+     -846, -846, -846, -846, -846, -846, -846, -846, -846, -846,
+     -846, -846, -846, -846, -846, -846, -846, -846, -846, -846,
+     -846, -846, -846, -846, -846, -846, -846, -846, -846, -846,
+     -846, -846, -846, -846, -846, -846, -846, -846, -846, -846,
+     -846, -846, -846, -846, -846, -846, -846, -846, -846, -846,
+     -846, -846, -846, -846, -846, -846, -846, -846, -846, -846,
+     -846, -846, -846, -846, -846, -846, -846, -846, -846, -846,
+     -846, -846, -846, -846, -846, -846, -846, -846, -846, -846,
+
+     -846, -846, -846, -846, -846, -846, -846, -846
+    },
+
+    {
+       67,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  848,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  847,  847,  847
+    },
+
+    {
+       67, -848, -848, -848, -848, -848, -848, -848, -848, -848,
+     -848, -848, -848, -848, -848, -848, -848, -848, -848, -848,
+     -848, -848, -848, -848, -848, -848, -848, -848, -848, -848,
+     -848, -848, -848, -848, -848, -848, -848, -848, -848,  847,
+     -848, -848, -848, -848, -848, -848, -848, -848, -848, -848,
+     -848, -848, -848, -848, -848, -848, -848, -848, -848, -848,
+
+     -848, -848, -848, -848, -848, -848, -848, -848, -848, -848,
+     -848, -848, -848, -848, -848, -848, -848, -848, -848, -848,
+     -848, -848, -848, -848, -848, -848, -848, -848, -848, -848,
+     -848, -848, -848, -848, -848, -848, -848, -848, -848, -848,
+     -848, -848, -848, -848, -848, -848, -848, -848, -848, -848,
+     -848, -848, -848, -848, -848, -848, -848, -848, -848, -848,
+     -848, -848, -848, -848, -848, -848, -848, -848
+    },
+
+    {
+       67,  849,  849,  849,  849,  849,  849,  849,  849,  849,
+      849,  849,  849,  849,  849,  849,  849,  849,  849,  849,
+      849,  849,  849,  849,  849,  849,  849,  849,  849,  849,
+
+      849,  849,  849,  849,  849,  849,  849,  849,  849,  850,
+      849,  849,  849,  849,  849,  849,  849,  849,  849,  849,
+      849,  849,  849,  849,  849,  849,  849,  849,  849,  849,
+      849,  849,  849,  849,  849,  849,  849,  849,  849,  849,
+      849,  849,  849,  849,  849,  849,  849,  849,  849,  849,
+      849,  849,  849,  849,  849,  849,  849,  849,  849,  849,
+      849,  849,  849,  849,  849,  849,  849,  849,  849,  849,
+      849,  849,  849,  849,  849,  849,  849,  849,  849,  849,
+      849,  849,  849,  849,  849,  849,  849,  849,  849,  849,
+      849,  849,  849,  849,  849,  849,  849,  849
+
+    },
+
+    {
+       67, -850, -850, -850, -850, -850, -850, -850, -850, -850,
+     -850, -850, -850, -850, -850, -850, -850, -850, -850, -850,
+     -850, -850, -850, -850, -850, -850, -850, -850, -850, -850,
+     -850, -850, -850, -850, -850, -850, -850, -850, -850,  849,
+     -850, -850, -850, -850, -850, -850, -850, -850, -850, -850,
+     -850, -850, -850, -850, -850, -850, -850, -850, -850, -850,
+     -850, -850, -850, -850, -850, -850, -850, -850, -850, -850,
+     -850, -850, -850, -850, -850, -850, -850, -850, -850, -850,
+     -850, -850, -850, -850, -850, -850, -850, -850, -850, -850,
+     -850, -850, -850, -850, -850, -850, -850, -850, -850, -850,
+
+     -850, -850, -850, -850, -850, -850, -850, -850, -850, -850,
+     -850, -850, -850, -850, -850, -850, -850, -850, -850, -850,
+     -850, -850, -850, -850, -850, -850, -850, -850
+    },
+
+    {
+       67,  851,  851,  851,  851,  851,  851,  851,  851,  851,
+      851,  851,  851,  851,  851,  851,  851,  851,  851,  851,
+      851,  851,  851,  851,  851,  851,  851,  851,  851,  851,
+      851,  851,  851,  851,  851,  851,  851,  851,  851,  852,
+      851,  851,  851,  851,  851,  851,  851,  851,  851,  851,
+      851,  851,  851,  851,  851,  851,  851,  851,  851,  851,
+      851,  851,  851,  851,  851,  851,  851,  851,  851,  851,
+
+      851,  851,  851,  851,  851,  851,  851,  851,  851,  851,
+      851,  851,  851,  851,  851,  851,  851,  851,  851,  851,
+      851,  851,  851,  851,  851,  851,  851,  851,  851,  851,
+      851,  851,  851,  851,  851,  851,  851,  851,  851,  851,
+      851,  851,  851,  851,  851,  851,  851,  851,  851,  851,
+      851,  851,  851,  851,  851,  851,  851,  851
+    },
+
+    {
+       67, -852, -852, -852, -852, -852, -852, -852, -852, -852,
+     -852, -852, -852, -852, -852, -852, -852, -852, -852, -852,
+     -852, -852, -852, -852, -852, -852, -852, -852, -852, -852,
+     -852, -852, -852, -852, -852, -852, -852, -852, -852,  851,
+
+     -852, -852, -852, -852, -852, -852, -852, -852, -852, -852,
+     -852, -852, -852, -852, -852, -852, -852, -852, -852, -852,
+     -852, -852, -852, -852, -852, -852, -852, -852, -852, -852,
+     -852, -852, -852, -852, -852, -852, -852, -852, -852, -852,
+     -852, -852, -852, -852, -852, -852, -852, -852, -852, -852,
+     -852, -852, -852, -852, -852, -852, -852, -852, -852, -852,
+     -852, -852, -852, -852, -852, -852, -852, -852, -852, -852,
+     -852, -852, -852, -852, -852, -852, -852, -852, -852, -852,
+     -852, -852, -852, -852, -852, -852, -852, -852
+    },
+
+    {
+       67,  853,  853,  853,  853,  853,  853,  853,  853,  853,
+
+      853,  853,  853,  853,  853,  853,  853,  853,  853,  853,
+      853,  853,  853,  853,  853,  853,  853,  853,  853,  853,
+      853,  853,  853,  853,  853,  853,  853,  853,  853,  854,
+      853,  853,  853,  853,  853,  853,  853,  853,  853,  853,
+      853,  853,  853,  853,  853,  853,  853,  853,  853,  853,
+      853,  853,  853,  853,  853,  853,  853,  853,  853,  853,
+      853,  853,  853,  853,  853,  853,  853,  853,  853,  853,
+      853,  853,  853,  853,  853,  853,  853,  853,  853,  853,
+      853,  853,  853,  853,  853,  853,  853,  853,  853,  853,
+      853,  853,  853,  853,  853,  853,  853,  853,  853,  853,
+
+      853,  853,  853,  853,  853,  853,  853,  853,  853,  853,
+      853,  853,  853,  853,  853,  853,  853,  853
+    },
+
+    {
+       67, -854, -854, -854, -854, -854, -854, -854, -854, -854,
+     -854, -854, -854, -854, -854, -854, -854, -854, -854, -854,
+     -854, -854, -854, -854, -854, -854, -854, -854, -854, -854,
+     -854, -854, -854, -854, -854, -854, -854, -854, -854,  853,
+     -854, -854, -854, -854, -854, -854, -854, -854, -854, -854,
+     -854, -854, -854, -854, -854, -854, -854, -854, -854, -854,
+     -854, -854, -854, -854, -854, -854, -854, -854, -854, -854,
+     -854, -854, -854, -854, -854, -854, -854, -854, -854, -854,
+
+     -854, -854, -854, -854, -854, -854, -854, -854, -854, -854,
+     -854, -854, -854, -854, -854, -854, -854, -854, -854, -854,
+     -854, -854, -854, -854, -854, -854, -854, -854, -854, -854,
+     -854, -854, -854, -854, -854, -854, -854, -854, -854, -854,
+     -854, -854, -854, -854, -854, -854, -854, -854
+    },
+
+    {
+       67,  855,  855,  855,  855,  855,  855,  855,  855,  855,
+      855,  855,  855,  855,  855,  855,  855,  855,  855,  855,
+      855,  855,  855,  855,  855,  855,  855,  855,  855,  855,
+      855,  855,  855,  855,  855,  855,  855,  855,  855,  856,
+      855,  855,  855,  855,  855,  855,  855,  855,  855,  855,
+
+      855,  855,  855,  855,  855,  855,  855,  855,  855,  855,
+      855,  855,  855,  855,  855,  855,  855,  855,  855,  855,
+      855,  855,  855,  855,  855,  855,  855,  855,  855,  855,
+      855,  855,  855,  855,  855,  855,  855,  855,  855,  855,
+      855,  855,  855,  855,  855,  855,  855,  855,  855,  855,
+      855,  855,  855,  855,  855,  855,  855,  855,  855,  855,
+      855,  855,  855,  855,  855,  855,  855,  855,  855,  855,
+      855,  855,  855,  855,  855,  855,  855,  855
+    },
+
+    {
+       67, -856, -856, -856, -856, -856, -856, -856, -856, -856,
+     -856, -856, -856, -856, -856, -856, -856, -856, -856, -856,
+
+     -856, -856, -856, -856, -856, -856, -856, -856, -856, -856,
+     -856, -856, -856, -856, -856, -856, -856, -856, -856,  855,
+     -856, -856, -856, -856, -856, -856, -856, -856, -856, -856,
+     -856, -856, -856, -856, -856, -856, -856, -856, -856, -856,
+     -856, -856, -856, -856, -856, -856, -856, -856, -856, -856,
+     -856, -856, -856, -856, -856, -856, -856, -856, -856, -856,
+     -856, -856, -856, -856, -856, -856, -856, -856, -856, -856,
+     -856, -856, -856, -856, -856, -856, -856, -856, -856, -856,
+     -856, -856, -856, -856, -856, -856, -856, -856, -856, -856,
+     -856, -856, -856, -856, -856, -856, -856, -856, -856, -856,
+
+     -856, -856, -856, -856, -856, -856, -856, -856
+    },
+
+    {
+       67,  857,  857,  857,  857,  857,  857,  857,  857,  857,
+      857,  857,  857,  857,  857,  857,  857,  857,  857,  857,
+      857,  857,  857,  857,  857,  857,  857,  857,  857,  857,
+      857,  857,  857,  857,  857,  857,  857,  857,  857,  858,
+      857,  857,  857,  857,  857,  857,  857,  857,  857,  857,
+      857,  857,  857,  857,  857,  857,  857,  857,  857,  857,
+      857,  857,  857,  857,  857,  857,  857,  857,  857,  857,
+      857,  857,  857,  857,  857,  857,  857,  857,  857,  857,
+      857,  857,  857,  857,  857,  857,  857,  857,  857,  857,
+
+      857,  857,  857,  857,  857,  857,  857,  857,  857,  857,
+      857,  857,  857,  857,  857,  857,  857,  857,  857,  857,
+      857,  857,  857,  857,  857,  857,  857,  857,  857,  857,
+      857,  857,  857,  857,  857,  857,  857,  857
+    },
+
+    {
+       67, -858, -858, -858, -858, -858, -858, -858, -858, -858,
+     -858, -858, -858, -858, -858, -858, -858, -858, -858, -858,
+     -858, -858, -858, -858, -858, -858, -858, -858, -858, -858,
+     -858, -858, -858, -858, -858, -858, -858, -858, -858,  857,
+     -858, -858, -858, -858, -858, -858, -858, -858, -858, -858,
+     -858, -858, -858, -858, -858, -858, -858, -858, -858, -858,
+
+     -858, -858, -858, -858, -858, -858, -858, -858, -858, -858,
+     -858, -858, -858, -858, -858, -858, -858, -858, -858, -858,
+     -858, -858, -858, -858, -858, -858, -858, -858, -858, -858,
+     -858, -858, -858, -858, -858, -858, -858, -858, -858, -858,
+     -858, -858, -858, -858, -858, -858, -858, -858, -858, -858,
+     -858, -858, -858, -858, -858, -858, -858, -858, -858, -858,
+     -858, -858, -858, -858, -858, -858, -858, -858
+    },
+
+    {
+       67, -859, -859, -859, -859, -859, -859, -859, -859, -859,
+     -859, -859, -859, -859, -859, -859, -859, -859, -859, -859,
+     -859, -859, -859, -859, -859, -859, -859, -859, -859, -859,
+
+     -859, -859,  860, -859, -859, -859, -859, -859, -859, -859,
+     -859, -859, -859, -859, -859, -859, -859, -859, -859, -859,
+     -859, -859, -859, -859, -859, -859, -859, -859, -859, -859,
+     -859, -859, -859, -859, -859, -859, -859, -859, -859, -859,
+     -859, -859, -859, -859, -859, -859, -859, -859, -859, -859,
+     -859, -859, -859, -859, -859, -859, -859, -859, -859, -859,
+     -859, -859, -859, -859, -859, -859, -859, -859, -859, -859,
+     -859, -859, -859, -859, -859, -859, -859, -859, -859, -859,
+     -859, -859, -859, -859, -859, -859, -859, -859, -859, -859,
+     -859, -859, -859, -859, -859, -859, -859, -859
+
+    },
+
+    {
+       67, -860, -860, -860, -860, -860, -860, -860, -860, -860,
+     -860, -860, -860, -860, -860, -860, -860, -860, -860, -860,
+     -860, -860, -860, -860, -860, -860, -860, -860, -860, -860,
+     -860, -860,  861, -860, -860, -860, -860, -860, -860, -860,
+     -860, -860, -860, -860, -860, -860, -860, -860, -860, -860,
+     -860, -860, -860, -860, -860, -860, -860, -860, -860, -860,
+     -860, -860, -860, -860, -860, -860, -860, -860, -860, -860,
+     -860, -860, -860, -860, -860, -860, -860, -860, -860, -860,
+     -860, -860, -860, -860, -860, -860, -860, -860, -860, -860,
+     -860, -860, -860, -860, -860, -860, -860, -860, -860, -860,
+
+     -860, -860, -860, -860, -860, -860, -860, -860, -860, -860,
+     -860, -860, -860, -860, -860, -860, -860, -860, -860, -860,
+     -860, -860, -860, -860, -860, -860, -860, -860
+    },
+
+    {
+       67, -861, -861, -861, -861, -861, -861, -861, -861, -861,
+     -861, -861, -861, -861, -861, -861, -861, -861, -861, -861,
+     -861, -861, -861, -861, -861, -861, -861, -861, -861, -861,
+     -861, -861,  862, -861, -861, -861, -861, -861, -861, -861,
+     -861, -861, -861, -861, -861, -861, -861, -861, -861, -861,
+     -861, -861, -861, -861, -861, -861, -861, -861, -861, -861,
+     -861, -861, -861, -861, -861, -861, -861, -861, -861, -861,
+
+     -861, -861, -861, -861, -861, -861, -861, -861, -861, -861,
+     -861, -861, -861, -861, -861, -861, -861, -861, -861, -861,
+     -861, -861, -861, -861, -861, -861, -861, -861, -861, -861,
+     -861, -861, -861, -861, -861, -861, -861, -861, -861, -861,
+     -861, -861, -861, -861, -861, -861, -861, -861, -861, -861,
+     -861, -861, -861, -861, -861, -861, -861, -861
+    },
+
+    {
+       67, -862, -862, -862, -862, -862, -862, -862, -862, -862,
+     -862, -862, -862, -862, -862, -862, -862, -862, -862, -862,
+     -862, -862, -862, -862, -862, -862, -862, -862, -862, -862,
+     -862, -862,  863, -862, -862, -862, -862, -862, -862, -862,
+
+     -862, -862, -862, -862, -862, -862, -862, -862, -862, -862,
+     -862, -862, -862, -862, -862, -862, -862, -862, -862, -862,
+     -862, -862, -862, -862, -862, -862, -862, -862, -862, -862,
+     -862, -862, -862, -862, -862, -862, -862, -862, -862, -862,
+     -862, -862, -862, -862, -862, -862, -862, -862, -862, -862,
+     -862, -862, -862, -862, -862, -862, -862, -862, -862, -862,
+     -862, -862, -862, -862, -862, -862, -862, -862, -862, -862,
+     -862, -862, -862, -862, -862, -862, -862, -862, -862, -862,
+     -862, -862, -862, -862, -862, -862, -862, -862
+    },
+
+    {
+       67, -863, -863, -863, -863, -863, -863, -863, -863, -863,
+
+     -863, -863, -863, -863, -863, -863, -863, -863, -863, -863,
+     -863, -863, -863, -863, -863, -863, -863, -863, -863, -863,
+     -863, -863,  864, -863, -863, -863, -863, -863, -863, -863,
+     -863, -863, -863, -863, -863, -863, -863, -863, -863, -863,
+     -863, -863, -863, -863, -863, -863, -863, -863, -863, -863,
+     -863, -863, -863, -863, -863, -863, -863, -863, -863, -863,
+     -863, -863, -863, -863, -863, -863, -863, -863, -863, -863,
+     -863, -863, -863, -863, -863, -863, -863, -863, -863, -863,
+     -863, -863, -863, -863, -863, -863, -863, -863, -863, -863,
+     -863, -863, -863, -863, -863, -863, -863, -863, -863, -863,
+
+     -863, -863, -863, -863, -863, -863, -863, -863, -863, -863,
+     -863, -863, -863, -863, -863, -863, -863, -863
+    },
+
+    {
+       67, -864, -864, -864, -864, -864, -864, -864, -864, -864,
+     -864, -864, -864, -864, -864, -864, -864, -864, -864, -864,
+     -864, -864, -864, -864, -864, -864, -864, -864, -864, -864,
+     -864, -864,  865, -864, -864, -864, -864, -864, -864, -864,
+     -864, -864, -864, -864, -864, -864, -864, -864, -864, -864,
+     -864, -864, -864, -864, -864, -864, -864, -864, -864, -864,
+     -864, -864, -864, -864, -864, -864, -864, -864, -864, -864,
+     -864, -864, -864, -864, -864, -864, -864, -864, -864, -864,
+
+     -864, -864, -864, -864, -864, -864, -864, -864, -864, -864,
+     -864, -864, -864, -864, -864, -864, -864, -864, -864, -864,
+     -864, -864, -864, -864, -864, -864, -864, -864, -864, -864,
+     -864, -864, -864, -864, -864, -864, -864, -864, -864, -864,
+     -864, -864, -864, -864, -864, -864, -864, -864
+    },
+
+    {
+       67, -865, -865, -865, -865, -865, -865, -865, -865, -865,
+     -865, -865, -865, -865, -865, -865, -865, -865, -865, -865,
+     -865, -865, -865, -865, -865, -865, -865, -865, -865, -865,
+     -865, -865,  866, -865, -865, -865, -865, -865, -865, -865,
+     -865, -865, -865, -865, -865, -865, -865, -865, -865, -865,
+
+     -865, -865, -865, -865, -865, -865, -865, -865, -865, -865,
+     -865, -865, -865, -865, -865, -865, -865, -865, -865, -865,
+     -865, -865, -865, -865, -865, -865, -865, -865, -865, -865,
+     -865, -865, -865, -865, -865, -865, -865, -865, -865, -865,
+     -865, -865, -865, -865, -865, -865, -865, -865, -865, -865,
+     -865, -865, -865, -865, -865, -865, -865, -865, -865, -865,
+     -865, -865, -865, -865, -865, -865, -865, -865, -865, -865,
+     -865, -865, -865, -865, -865, -865, -865, -865
+    },
+
+    {
+       67, -866, -866, -866, -866, -866, -866, -866, -866, -866,
+     -866, -866, -866, -866, -866, -866, -866, -866, -866, -866,
+
+     -866, -866, -866, -866, -866, -866, -866, -866, -866, -866,
+     -866, -866,  867, -866, -866, -866, -866, -866, -866, -866,
+     -866, -866, -866, -866, -866, -866, -866, -866, -866, -866,
+     -866, -866, -866, -866, -866, -866, -866, -866, -866, -866,
+     -866, -866, -866, -866, -866, -866, -866, -866, -866, -866,
+     -866, -866, -866, -866, -866, -866, -866, -866, -866, -866,
+     -866, -866, -866, -866, -866, -866, -866, -866, -866, -866,
+     -866, -866, -866, -866, -866, -866, -866, -866, -866, -866,
+     -866, -866, -866, -866, -866, -866, -866, -866, -866, -866,
+     -866, -866, -866, -866, -866, -866, -866, -866, -866, -866,
+
+     -866, -866, -866, -866, -866, -866, -866, -866
+    },
+
+    {
+       67, -867, -867, -867, -867, -867, -867, -867, -867, -867,
+     -867, -867, -867, -867, -867, -867, -867, -867, -867, -867,
+     -867, -867, -867, -867, -867, -867, -867, -867, -867, -867,
+     -867, -867,  868, -867, -867, -867, -867, -867, -867, -867,
+     -867, -867, -867, -867, -867, -867, -867, -867, -867, -867,
+     -867, -867, -867, -867, -867, -867, -867, -867, -867, -867,
+     -867, -867, -867, -867, -867, -867, -867, -867, -867, -867,
+     -867, -867, -867, -867, -867, -867, -867, -867, -867, -867,
+     -867, -867, -867, -867, -867, -867, -867, -867, -867, -867,
+
+     -867, -867, -867, -867, -867, -867, -867, -867, -867, -867,
+     -867, -867, -867, -867, -867, -867, -867, -867, -867, -867,
+     -867, -867, -867, -867, -867, -867, -867, -867, -867, -867,
+     -867, -867, -867, -867, -867, -867, -867, -867
+    },
+
+    {
+       67, -868, -868, -868, -868, -868, -868, -868, -868, -868,
+     -868, -868, -868, -868, -868, -868, -868, -868, -868, -868,
+     -868, -868, -868, -868, -868, -868, -868, -868, -868, -868,
+     -868, -868,  869, -868, -868, -868, -868, -868, -868, -868,
+     -868, -868, -868, -868, -868, -868, -868, -868, -868, -868,
+     -868, -868, -868, -868, -868, -868, -868, -868, -868, -868,
+
+     -868, -868, -868, -868, -868, -868, -868, -868, -868, -868,
+     -868, -868, -868, -868, -868, -868, -868, -868, -868, -868,
+     -868, -868, -868, -868, -868, -868, -868, -868, -868, -868,
+     -868, -868, -868, -868, -868, -868, -868, -868, -868, -868,
+     -868, -868, -868, -868, -868, -868, -868, -868, -868, -868,
+     -868, -868, -868, -868, -868, -868, -868, -868, -868, -868,
+     -868, -868, -868, -868, -868, -868, -868, -868
+    },
+
+    {
+       67, -869, -869, -869, -869, -869, -869, -869, -869, -869,
+     -869, -869, -869, -869, -869, -869, -869, -869, -869, -869,
+     -869, -869, -869, -869, -869, -869, -869, -869, -869, -869,
+
+     -869, -869,  870, -869, -869, -869, -869, -869, -869, -869,
+     -869, -869, -869, -869, -869, -869, -869, -869, -869, -869,
+     -869, -869, -869, -869, -869, -869, -869, -869, -869, -869,
+     -869, -869, -869, -869, -869, -869, -869, -869, -869, -869,
+     -869, -869, -869, -869, -869, -869, -869, -869, -869, -869,
+     -869, -869, -869, -869, -869, -869, -869, -869, -869, -869,
+     -869, -869, -869, -869, -869, -869, -869, -869, -869, -869,
+     -869, -869, -869, -869, -869, -869, -869, -869, -869, -869,
+     -869, -869, -869, -869, -869, -869, -869, -869, -869, -869,
+     -869, -869, -869, -869, -869, -869, -869, -869
+
+    },
+
+    {
+       67, -870, -870, -870, -870, -870, -870, -870, -870, -870,
+     -870, -870, -870, -870, -870, -870, -870, -870, -870, -870,
+     -870, -870, -870, -870, -870, -870, -870, -870, -870, -870,
+     -870, -870,  871, -870, -870, -870, -870, -870, -870, -870,
+     -870, -870, -870, -870, -870, -870, -870, -870, -870, -870,
+     -870, -870, -870, -870, -870, -870, -870, -870, -870, -870,
+     -870, -870, -870, -870, -870, -870, -870, -870, -870, -870,
+     -870, -870, -870, -870, -870, -870, -870, -870, -870, -870,
+     -870, -870, -870, -870, -870, -870, -870, -870, -870, -870,
+     -870, -870, -870, -870, -870, -870, -870, -870, -870, -870,
+
+     -870, -870, -870, -870, -870, -870, -870, -870, -870, -870,
+     -870, -870, -870, -870, -870, -870, -870, -870, -870, -870,
+     -870, -870, -870, -870, -870, -870, -870, -870
+    },
+
+    {
+       67, -871, -871, -871, -871, -871, -871, -871, -871, -871,
+     -871, -871, -871, -871, -871, -871, -871, -871, -871, -871,
+     -871, -871, -871, -871, -871, -871, -871, -871, -871, -871,
+     -871, -871,  872, -871, -871, -871, -871, -871, -871, -871,
+     -871, -871, -871, -871, -871, -871, -871, -871, -871, -871,
+     -871, -871, -871, -871, -871, -871, -871, -871, -871, -871,
+     -871, -871, -871, -871, -871, -871, -871, -871, -871, -871,
+
+     -871, -871, -871, -871, -871, -871, -871, -871, -871, -871,
+     -871, -871, -871, -871, -871, -871, -871, -871, -871, -871,
+     -871, -871, -871, -871, -871, -871, -871, -871, -871, -871,
+     -871, -871, -871, -871, -871, -871, -871, -871, -871, -871,
+     -871, -871, -871, -871, -871, -871, -871, -871, -871, -871,
+     -871, -871, -871, -871, -871, -871, -871, -871
+    },
+
+    {
+       67, -872, -872, -872, -872, -872, -872, -872, -872, -872,
+     -872, -872, -872, -872, -872, -872, -872, -872, -872, -872,
+     -872, -872, -872, -872, -872, -872, -872, -872, -872, -872,
+     -872, -872,  873, -872, -872, -872, -872, -872, -872, -872,
+
+     -872, -872, -872, -872, -872, -872, -872, -872, -872, -872,
+     -872, -872, -872, -872, -872, -872, -872, -872, -872, -872,
+     -872, -872, -872, -872, -872, -872, -872, -872, -872, -872,
+     -872, -872, -872, -872, -872, -872, -872, -872, -872, -872,
+     -872, -872, -872, -872, -872, -872, -872, -872, -872, -872,
+     -872, -872, -872, -872, -872, -872, -872, -872, -872, -872,
+     -872, -872, -872, -872, -872, -872, -872, -872, -872, -872,
+     -872, -872, -872, -872, -872, -872, -872, -872, -872, -872,
+     -872, -872, -872, -872, -872, -872, -872, -872
+    },
+
+    {
+       67, -873, -873, -873, -873, -873, -873, -873, -873, -873,
+
+     -873, -873, -873, -873, -873, -873, -873, -873, -873, -873,
+     -873, -873, -873, -873, -873, -873, -873, -873, -873, -873,
+     -873, -873,  874, -873, -873, -873, -873, -873, -873, -873,
+     -873, -873, -873, -873, -873, -873, -873, -873, -873, -873,
+     -873, -873, -873, -873, -873, -873, -873, -873, -873, -873,
+     -873, -873, -873, -873, -873, -873, -873, -873, -873, -873,
+     -873, -873, -873, -873, -873, -873, -873, -873, -873, -873,
+     -873, -873, -873, -873, -873, -873, -873, -873, -873, -873,
+     -873, -873, -873, -873, -873, -873, -873, -873, -873, -873,
+     -873, -873, -873, -873, -873, -873, -873, -873, -873, -873,
+
+     -873, -873, -873, -873, -873, -873, -873, -873, -873, -873,
+     -873, -873, -873, -873, -873, -873, -873, -873
+    },
+
+    {
+       67, -874, -874, -874, -874, -874, -874, -874, -874, -874,
+     -874, -874, -874, -874, -874, -874, -874, -874, -874, -874,
+     -874, -874, -874, -874, -874, -874, -874, -874, -874, -874,
+     -874, -874,  875, -874, -874, -874, -874, -874, -874, -874,
+     -874, -874, -874, -874, -874, -874, -874, -874, -874, -874,
+     -874, -874, -874, -874, -874, -874, -874, -874, -874, -874,
+     -874, -874, -874, -874, -874, -874, -874, -874, -874, -874,
+     -874, -874, -874, -874, -874, -874, -874, -874, -874, -874,
+
+     -874, -874, -874, -874, -874, -874, -874, -874, -874, -874,
+     -874, -874, -874, -874, -874, -874, -874, -874, -874, -874,
+     -874, -874, -874, -874, -874, -874, -874, -874, -874, -874,
+     -874, -874, -874, -874, -874, -874, -874, -874, -874, -874,
+     -874, -874, -874, -874, -874, -874, -874, -874
+    },
+
+    {
+       67, -875, -875, -875, -875, -875, -875, -875, -875, -875,
+     -875, -875, -875, -875, -875, -875, -875, -875, -875, -875,
+     -875, -875, -875, -875, -875, -875, -875, -875, -875, -875,
+     -875, -875,  876, -875, -875, -875, -875, -875, -875, -875,
+     -875, -875, -875, -875, -875, -875, -875, -875, -875, -875,
+
+     -875, -875, -875, -875, -875, -875, -875, -875, -875, -875,
+     -875, -875, -875, -875, -875, -875, -875, -875, -875, -875,
+     -875, -875, -875, -875, -875, -875, -875, -875, -875, -875,
+     -875, -875, -875, -875, -875, -875, -875, -875, -875, -875,
+     -875, -875, -875, -875, -875, -875, -875, -875, -875, -875,
+     -875, -875, -875, -875, -875, -875, -875, -875, -875, -875,
+     -875, -875, -875, -875, -875, -875, -875, -875, -875, -875,
+     -875, -875, -875, -875, -875, -875, -875, -875
+    },
+
+    {
+       67, -876, -876, -876, -876, -876, -876, -876, -876, -876,
+     -876, -876, -876, -876, -876, -876, -876, -876, -876, -876,
+
+     -876, -876, -876, -876, -876, -876, -876, -876, -876, -876,
+     -876, -876,  877, -876, -876, -876, -876, -876, -876, -876,
+     -876, -876, -876, -876, -876, -876, -876, -876, -876, -876,
+     -876, -876, -876, -876, -876, -876, -876, -876, -876, -876,
+     -876, -876, -876, -876, -876, -876, -876, -876, -876, -876,
+     -876, -876, -876, -876, -876, -876, -876, -876, -876, -876,
+     -876, -876, -876, -876, -876, -876, -876, -876, -876, -876,
+     -876, -876, -876, -876, -876, -876, -876, -876, -876, -876,
+     -876, -876, -876, -876, -876, -876, -876, -876, -876, -876,
+     -876, -876, -876, -876, -876, -876, -876, -876, -876, -876,
+
+     -876, -876, -876, -876, -876, -876, -876, -876
+    },
+
+    {
+       67, -877, -877, -877, -877, -877, -877, -877, -877, -877,
+     -877, -877, -877, -877, -877, -877, -877, -877, -877, -877,
+     -877, -877, -877, -877, -877, -877, -877, -877, -877, -877,
+     -877, -877,  878, -877, -877, -877, -877, -877, -877, -877,
+     -877, -877, -877, -877, -877, -877, -877, -877, -877, -877,
+     -877, -877, -877, -877, -877, -877, -877, -877, -877, -877,
+     -877, -877, -877, -877, -877, -877, -877, -877, -877, -877,
+     -877, -877, -877, -877, -877, -877, -877, -877, -877, -877,
+     -877, -877, -877, -877, -877, -877, -877, -877, -877, -877,
+
+     -877, -877, -877, -877, -877, -877, -877, -877, -877, -877,
+     -877, -877, -877, -877, -877, -877, -877, -877, -877, -877,
+     -877, -877, -877, -877, -877, -877, -877, -877, -877, -877,
+     -877, -877, -877, -877, -877, -877, -877, -877
+    },
+
+    {
+       67, -878, -878, -878, -878, -878, -878, -878, -878, -878,
+     -878, -878, -878, -878, -878, -878, -878, -878, -878, -878,
+     -878, -878, -878, -878, -878, -878, -878, -878, -878, -878,
+     -878, -878,  879, -878, -878, -878, -878, -878, -878, -878,
+     -878, -878, -878, -878, -878, -878, -878, -878, -878, -878,
+     -878, -878, -878, -878, -878, -878, -878, -878, -878, -878,
+
+     -878, -878, -878, -878, -878, -878, -878, -878, -878, -878,
+     -878, -878, -878, -878, -878, -878, -878, -878, -878, -878,
+     -878, -878, -878, -878, -878, -878, -878, -878, -878, -878,
+     -878, -878, -878, -878, -878, -878, -878, -878, -878, -878,
+     -878, -878, -878, -878, -878, -878, -878, -878, -878, -878,
+     -878, -878, -878, -878, -878, -878, -878, -878, -878, -878,
+     -878, -878, -878, -878, -878, -878, -878, -878
+    },
+
+    {
+       67, -879, -879, -879, -879, -879, -879, -879, -879, -879,
+     -879, -879, -879, -879, -879, -879, -879, -879, -879, -879,
+     -879, -879, -879, -879, -879, -879, -879, -879, -879, -879,
+
+     -879, -879,  880, -879, -879, -879, -879, -879, -879, -879,
+     -879, -879, -879, -879, -879, -879, -879, -879, -879, -879,
+     -879, -879, -879, -879, -879, -879, -879, -879, -879, -879,
+     -879, -879, -879, -879, -879, -879, -879, -879, -879, -879,
+     -879, -879, -879, -879, -879, -879, -879, -879, -879, -879,
+     -879, -879, -879, -879, -879, -879, -879, -879, -879, -879,
+     -879, -879, -879, -879, -879, -879, -879, -879, -879, -879,
+     -879, -879, -879, -879, -879, -879, -879, -879, -879, -879,
+     -879, -879, -879, -879, -879, -879, -879, -879, -879, -879,
+     -879, -879, -879, -879, -879, -879, -879, -879
+
+    },
+
+    {
+       67, -880, -880, -880, -880, -880, -880, -880, -880, -880,
+     -880, -880, -880, -880, -880, -880, -880, -880, -880, -880,
+     -880, -880, -880, -880, -880, -880, -880, -880, -880, -880,
+     -880, -880,  881, -880, -880, -880, -880, -880, -880, -880,
+     -880, -880, -880, -880, -880, -880, -880, -880, -880, -880,
+     -880, -880, -880, -880, -880, -880, -880, -880, -880, -880,
+     -880, -880, -880, -880, -880, -880, -880, -880, -880, -880,
+     -880, -880, -880, -880, -880, -880, -880, -880, -880, -880,
+     -880, -880, -880, -880, -880, -880, -880, -880, -880, -880,
+     -880, -880, -880, -880, -880, -880, -880, -880, -880, -880,
+
+     -880, -880, -880, -880, -880, -880, -880, -880, -880, -880,
+     -880, -880, -880, -880, -880, -880, -880, -880, -880, -880,
+     -880, -880, -880, -880, -880, -880, -880, -880
+    },
+
+    {
+       67, -881, -881, -881, -881, -881, -881, -881, -881, -881,
+     -881, -881, -881, -881, -881, -881, -881, -881, -881, -881,
+     -881, -881, -881, -881, -881, -881, -881, -881, -881, -881,
+     -881, -881,  882, -881, -881, -881, -881, -881, -881, -881,
+     -881, -881, -881, -881, -881, -881, -881, -881, -881, -881,
+     -881, -881, -881, -881, -881, -881, -881, -881, -881, -881,
+     -881, -881, -881, -881, -881, -881, -881, -881, -881, -881,
+
+     -881, -881, -881, -881, -881, -881, -881, -881, -881, -881,
+     -881, -881, -881, -881, -881, -881, -881, -881, -881, -881,
+     -881, -881, -881, -881, -881, -881, -881, -881, -881, -881,
+     -881, -881, -881, -881, -881, -881, -881, -881, -881, -881,
+     -881, -881, -881, -881, -881, -881, -881, -881, -881, -881,
+     -881, -881, -881, -881, -881, -881, -881, -881
+    },
+
+    {
+       67, -882, -882, -882, -882, -882, -882, -882, -882, -882,
+     -882, -882, -882, -882, -882, -882, -882, -882, -882, -882,
+     -882, -882, -882, -882, -882, -882, -882, -882, -882, -882,
+     -882, -882,  883, -882, -882, -882, -882, -882, -882, -882,
+
+     -882, -882, -882, -882, -882, -882, -882, -882, -882, -882,
+     -882, -882, -882, -882, -882, -882, -882, -882, -882, -882,
+     -882, -882, -882, -882, -882, -882, -882, -882, -882, -882,
+     -882, -882, -882, -882, -882, -882, -882, -882, -882, -882,
+     -882, -882, -882, -882, -882, -882, -882, -882, -882, -882,
+     -882, -882, -882, -882, -882, -882, -882, -882, -882, -882,
+     -882, -882, -882, -882, -882, -882, -882, -882, -882, -882,
+     -882, -882, -882, -882, -882, -882, -882, -882, -882, -882,
+     -882, -882, -882, -882, -882, -882, -882, -882
+    },
+
+    {
+       67, -883, -883, -883, -883, -883, -883, -883, -883, -883,
+
+     -883, -883, -883, -883, -883, -883, -883, -883, -883, -883,
+     -883, -883, -883, -883, -883, -883, -883, -883, -883, -883,
+     -883, -883,  884, -883, -883, -883, -883, -883, -883, -883,
+     -883, -883, -883, -883, -883, -883, -883, -883, -883, -883,
+     -883, -883, -883, -883, -883, -883, -883, -883, -883, -883,
+     -883, -883, -883, -883, -883, -883, -883, -883, -883, -883,
+     -883, -883, -883, -883, -883, -883, -883, -883, -883, -883,
+     -883, -883, -883, -883, -883, -883, -883, -883, -883, -883,
+     -883, -883, -883, -883, -883, -883, -883, -883, -883, -883,
+     -883, -883, -883, -883, -883, -883, -883, -883, -883, -883,
+
+     -883, -883, -883, -883, -883, -883, -883, -883, -883, -883,
+     -883, -883, -883, -883, -883, -883, -883, -883
+    },
+
+    {
+       67, -884, -884, -884, -884, -884, -884, -884, -884, -884,
+     -884, -884, -884, -884, -884, -884, -884, -884, -884, -884,
+     -884, -884, -884, -884, -884, -884, -884, -884, -884, -884,
+     -884, -884,  885, -884, -884, -884, -884, -884, -884, -884,
+     -884, -884, -884, -884, -884, -884, -884, -884, -884, -884,
+     -884, -884, -884, -884, -884, -884, -884, -884, -884, -884,
+     -884, -884, -884, -884, -884, -884, -884, -884, -884, -884,
+     -884, -884, -884, -884, -884, -884, -884, -884, -884, -884,
+
+     -884, -884, -884, -884, -884, -884, -884, -884, -884, -884,
+     -884, -884, -884, -884, -884, -884, -884, -884, -884, -884,
+     -884, -884, -884, -884, -884, -884, -884, -884, -884, -884,
+     -884, -884, -884, -884, -884, -884, -884, -884, -884, -884,
+     -884, -884, -884, -884, -884, -884, -884, -884
+    },
+
+    {
+       67, -885, -885, -885, -885, -885, -885, -885, -885, -885,
+     -885, -885, -885, -885, -885, -885, -885, -885, -885, -885,
+     -885, -885, -885, -885, -885, -885, -885, -885, -885, -885,
+     -885, -885,  886, -885, -885, -885, -885, -885, -885, -885,
+     -885, -885, -885, -885, -885, -885, -885, -885, -885, -885,
+
+     -885, -885, -885, -885, -885, -885, -885, -885, -885, -885,
+     -885, -885, -885, -885, -885, -885, -885, -885, -885, -885,
+     -885, -885, -885, -885, -885, -885, -885, -885, -885, -885,
+     -885, -885, -885, -885, -885, -885, -885, -885, -885, -885,
+     -885, -885, -885, -885, -885, -885, -885, -885, -885, -885,
+     -885, -885, -885, -885, -885, -885, -885, -885, -885, -885,
+     -885, -885, -885, -885, -885, -885, -885, -885, -885, -885,
+     -885, -885, -885, -885, -885, -885, -885, -885
+    },
+
+    {
+       67, -886, -886, -886, -886, -886, -886, -886, -886, -886,
+     -886, -886, -886, -886, -886, -886, -886, -886, -886, -886,
+
+     -886, -886, -886, -886, -886, -886, -886, -886, -886, -886,
+     -886, -886,  887, -886, -886, -886, -886, -886, -886, -886,
+     -886, -886, -886, -886, -886, -886, -886, -886, -886, -886,
+     -886, -886, -886, -886, -886, -886, -886, -886, -886, -886,
+     -886, -886, -886, -886, -886, -886, -886, -886, -886, -886,
+     -886, -886, -886, -886, -886, -886, -886, -886, -886, -886,
+     -886, -886, -886, -886, -886, -886, -886, -886, -886, -886,
+     -886, -886, -886, -886, -886, -886, -886, -886, -886, -886,
+     -886, -886, -886, -886, -886, -886, -886, -886, -886, -886,
+     -886, -886, -886, -886, -886, -886, -886, -886, -886, -886,
+
+     -886, -886, -886, -886, -886, -886, -886, -886
+    },
+
+    {
+       67, -887, -887, -887, -887, -887, -887, -887, -887, -887,
+     -887, -887, -887, -887, -887, -887, -887, -887, -887, -887,
+     -887, -887, -887, -887, -887, -887, -887, -887, -887, -887,
+     -887, -887,  888, -887, -887, -887, -887, -887, -887, -887,
+     -887, -887, -887, -887, -887, -887, -887, -887, -887, -887,
+     -887, -887, -887, -887, -887, -887, -887, -887, -887, -887,
+     -887, -887, -887, -887, -887, -887, -887, -887, -887, -887,
+     -887, -887, -887, -887, -887, -887, -887, -887, -887, -887,
+     -887, -887, -887, -887, -887, -887, -887, -887, -887, -887,
+
+     -887, -887, -887, -887, -887, -887, -887, -887, -887, -887,
+     -887, -887, -887, -887, -887, -887, -887, -887, -887, -887,
+     -887, -887, -887, -887, -887, -887, -887, -887, -887, -887,
+     -887, -887, -887, -887, -887, -887, -887, -887
+    },
+
+    {
+       67, -888, -888, -888, -888, -888, -888, -888, -888, -888,
+     -888, -888, -888, -888, -888, -888, -888, -888, -888, -888,
+     -888, -888, -888, -888, -888, -888, -888, -888, -888, -888,
+     -888, -888,  889, -888, -888, -888, -888, -888, -888, -888,
+     -888, -888, -888, -888, -888, -888, -888, -888, -888, -888,
+     -888, -888, -888, -888, -888, -888, -888, -888, -888, -888,
+
+     -888, -888, -888, -888, -888, -888, -888, -888, -888, -888,
+     -888, -888, -888, -888, -888, -888, -888, -888, -888, -888,
+     -888, -888, -888, -888, -888, -888, -888, -888, -888, -888,
+     -888, -888, -888, -888, -888, -888, -888, -888, -888, -888,
+     -888, -888, -888, -888, -888, -888, -888, -888, -888, -888,
+     -888, -888, -888, -888, -888, -888, -888, -888, -888, -888,
+     -888, -888, -888, -888, -888, -888, -888, -888
+    },
+
+    {
+       67, -889, -889, -889, -889, -889, -889, -889, -889, -889,
+     -889, -889, -889, -889, -889, -889, -889, -889, -889, -889,
+     -889, -889, -889, -889, -889, -889, -889, -889, -889, -889,
+
+     -889, -889,  890, -889, -889, -889, -889, -889, -889, -889,
+     -889, -889, -889, -889, -889, -889, -889, -889, -889, -889,
+     -889, -889, -889, -889, -889, -889, -889, -889, -889, -889,
+     -889, -889, -889, -889, -889, -889, -889, -889, -889, -889,
+     -889, -889, -889, -889, -889, -889, -889, -889, -889, -889,
+     -889, -889, -889, -889, -889, -889, -889, -889, -889, -889,
+     -889, -889, -889, -889, -889, -889, -889, -889, -889, -889,
+     -889, -889, -889, -889, -889, -889, -889, -889, -889, -889,
+     -889, -889, -889, -889, -889, -889, -889, -889, -889, -889,
+     -889, -889, -889, -889, -889, -889, -889, -889
+
+    },
+
+    {
+       67, -890, -890, -890, -890, -890, -890, -890, -890, -890,
+     -890, -890, -890, -890, -890, -890, -890, -890, -890, -890,
+     -890, -890, -890, -890, -890, -890, -890, -890, -890, -890,
+     -890, -890,  891, -890, -890, -890, -890, -890, -890, -890,
+     -890, -890, -890, -890, -890, -890, -890, -890, -890, -890,
+     -890, -890, -890, -890, -890, -890, -890, -890, -890, -890,
+     -890, -890, -890, -890, -890, -890, -890, -890, -890, -890,
+     -890, -890, -890, -890, -890, -890, -890, -890, -890, -890,
+     -890, -890, -890, -890, -890, -890, -890, -890, -890, -890,
+     -890, -890, -890, -890, -890, -890, -890, -890, -890, -890,
+
+     -890, -890, -890, -890, -890, -890, -890, -890, -890, -890,
+     -890, -890, -890, -890, -890, -890, -890, -890, -890, -890,
+     -890, -890, -890, -890, -890, -890, -890, -890
+    },
+
+    {
+       67, -891, -891, -891, -891, -891, -891, -891, -891, -891,
+     -891, -891, -891, -891, -891, -891, -891, -891, -891, -891,
+     -891, -891, -891, -891, -891, -891, -891, -891, -891, -891,
+     -891, -891,  892, -891, -891, -891, -891, -891, -891, -891,
+     -891, -891, -891, -891, -891, -891, -891, -891, -891, -891,
+     -891, -891, -891, -891, -891, -891, -891, -891, -891, -891,
+     -891, -891, -891, -891, -891, -891, -891, -891, -891, -891,
+
+     -891, -891, -891, -891, -891, -891, -891, -891, -891, -891,
+     -891, -891, -891, -891, -891, -891, -891, -891, -891, -891,
+     -891, -891, -891, -891, -891, -891, -891, -891, -891, -891,
+     -891, -891, -891, -891, -891, -891, -891, -891, -891, -891,
+     -891, -891, -891, -891, -891, -891, -891, -891, -891, -891,
+     -891, -891, -891, -891, -891, -891, -891, -891
+    },
+
+    {
+       67, -892, -892, -892, -892, -892, -892, -892, -892, -892,
+     -892, -892, -892, -892, -892, -892, -892, -892, -892, -892,
+     -892, -892, -892, -892, -892, -892, -892, -892, -892, -892,
+     -892, -892,  893, -892, -892, -892, -892, -892, -892, -892,
+
+     -892, -892, -892, -892, -892, -892, -892, -892, -892, -892,
+     -892, -892, -892, -892, -892, -892, -892, -892, -892, -892,
+     -892, -892, -892, -892, -892, -892, -892, -892, -892, -892,
+     -892, -892, -892, -892, -892, -892, -892, -892, -892, -892,
+     -892, -892, -892, -892, -892, -892, -892, -892, -892, -892,
+     -892, -892, -892, -892, -892, -892, -892, -892, -892, -892,
+     -892, -892, -892, -892, -892, -892, -892, -892, -892, -892,
+     -892, -892, -892, -892, -892, -892, -892, -892, -892, -892,
+     -892, -892, -892, -892, -892, -892, -892, -892
+    },
+
+    {
+       67, -893, -893, -893, -893, -893, -893, -893, -893, -893,
+
+     -893, -893, -893, -893, -893, -893, -893, -893, -893, -893,
+     -893, -893, -893, -893, -893, -893, -893, -893, -893, -893,
+     -893, -893,  894, -893, -893, -893, -893, -893, -893, -893,
+     -893, -893, -893, -893, -893, -893, -893, -893, -893, -893,
+     -893, -893, -893, -893, -893, -893, -893, -893, -893, -893,
+     -893, -893, -893, -893, -893, -893, -893, -893, -893, -893,
+     -893, -893, -893, -893, -893, -893, -893, -893, -893, -893,
+     -893, -893, -893, -893, -893, -893, -893, -893, -893, -893,
+     -893, -893, -893, -893, -893, -893, -893, -893, -893, -893,
+     -893, -893, -893, -893, -893, -893, -893, -893, -893, -893,
+
+     -893, -893, -893, -893, -893, -893, -893, -893, -893, -893,
+     -893, -893, -893, -893, -893, -893, -893, -893
+    },
+
+    {
+       67, -894, -894, -894, -894, -894, -894, -894, -894, -894,
+     -894, -894, -894, -894, -894, -894, -894, -894, -894, -894,
+     -894, -894, -894, -894, -894, -894, -894, -894, -894, -894,
+     -894, -894,  895, -894, -894, -894, -894, -894, -894, -894,
+     -894, -894, -894, -894, -894, -894, -894, -894, -894, -894,
+     -894, -894, -894, -894, -894, -894, -894, -894, -894, -894,
+     -894, -894, -894, -894, -894, -894, -894, -894, -894, -894,
+     -894, -894, -894, -894, -894, -894, -894, -894, -894, -894,
+
+     -894, -894, -894, -894, -894, -894, -894, -894, -894, -894,
+     -894, -894, -894, -894, -894, -894, -894, -894, -894, -894,
+     -894, -894, -894, -894, -894, -894, -894, -894, -894, -894,
+     -894, -894, -894, -894, -894, -894, -894, -894, -894, -894,
+     -894, -894, -894, -894, -894, -894, -894, -894
+    },
+
+    {
+       67, -895, -895, -895, -895, -895, -895, -895, -895, -895,
+     -895, -895, -895, -895, -895, -895, -895, -895, -895, -895,
+     -895, -895, -895, -895, -895, -895, -895, -895, -895, -895,
+     -895, -895,  896, -895, -895, -895, -895, -895, -895, -895,
+     -895, -895, -895, -895, -895, -895, -895, -895, -895, -895,
+
+     -895, -895, -895, -895, -895, -895, -895, -895, -895, -895,
+     -895, -895, -895, -895, -895, -895, -895, -895, -895, -895,
+     -895, -895, -895, -895, -895, -895, -895, -895, -895, -895,
+     -895, -895, -895, -895, -895, -895, -895, -895, -895, -895,
+     -895, -895, -895, -895, -895, -895, -895, -895, -895, -895,
+     -895, -895, -895, -895, -895, -895, -895, -895, -895, -895,
+     -895, -895, -895, -895, -895, -895, -895, -895, -895, -895,
+     -895, -895, -895, -895, -895, -895, -895, -895
+    },
+
+    {
+       67, -896, -896, -896, -896, -896, -896, -896, -896, -896,
+     -896, -896, -896, -896, -896, -896, -896, -896, -896, -896,
+
+     -896, -896, -896, -896, -896, -896, -896, -896, -896, -896,
+     -896, -896,  897, -896, -896, -896, -896, -896, -896, -896,
+     -896, -896, -896, -896, -896, -896, -896, -896, -896, -896,
+     -896, -896, -896, -896, -896, -896, -896, -896, -896, -896,
+     -896, -896, -896, -896, -896, -896, -896, -896, -896, -896,
+     -896, -896, -896, -896, -896, -896, -896, -896, -896, -896,
+     -896, -896, -896, -896, -896, -896, -896, -896, -896, -896,
+     -896, -896, -896, -896, -896, -896, -896, -896, -896, -896,
+     -896, -896, -896, -896, -896, -896, -896, -896, -896, -896,
+     -896, -896, -896, -896, -896, -896, -896, -896, -896, -896,
+
+     -896, -896, -896, -896, -896, -896, -896, -896
+    },
+
+    {
+       67, -897, -897, -897, -897, -897, -897, -897, -897, -897,
+     -897, -897, -897, -897, -897, -897, -897, -897, -897, -897,
+     -897, -897, -897, -897, -897, -897, -897, -897, -897, -897,
+     -897, -897,  898, -897, -897, -897, -897, -897, -897, -897,
+     -897, -897, -897, -897, -897, -897, -897, -897, -897, -897,
+     -897, -897, -897, -897, -897, -897, -897, -897, -897, -897,
+     -897, -897, -897, -897, -897, -897, -897, -897, -897, -897,
+     -897, -897, -897, -897, -897, -897, -897, -897, -897, -897,
+     -897, -897, -897, -897, -897, -897, -897, -897, -897, -897,
+
+     -897, -897, -897, -897, -897, -897, -897, -897, -897, -897,
+     -897, -897, -897, -897, -897, -897, -897, -897, -897, -897,
+     -897, -897, -897, -897, -897, -897, -897, -897, -897, -897,
+     -897, -897, -897, -897, -897, -897, -897, -897
+    },
+
+    {
+       67, -898, -898, -898, -898, -898, -898, -898, -898, -898,
+     -898, -898, -898, -898, -898, -898, -898, -898, -898, -898,
+     -898, -898, -898, -898, -898, -898, -898, -898, -898, -898,
+     -898, -898,  899, -898, -898, -898, -898, -898, -898, -898,
+     -898, -898, -898, -898, -898, -898, -898, -898, -898, -898,
+     -898, -898, -898, -898, -898, -898, -898, -898, -898, -898,
+
+     -898, -898, -898, -898, -898, -898, -898, -898, -898, -898,
+     -898, -898, -898, -898, -898, -898, -898, -898, -898, -898,
+     -898, -898, -898, -898, -898, -898, -898, -898, -898, -898,
+     -898, -898, -898, -898, -898, -898, -898, -898, -898, -898,
+     -898, -898, -898, -898, -898, -898, -898, -898, -898, -898,
+     -898, -898, -898, -898, -898, -898, -898, -898, -898, -898,
+     -898, -898, -898, -898, -898, -898, -898, -898
+    },
+
+    {
+       67, -899, -899, -899, -899, -899, -899, -899, -899, -899,
+     -899, -899, -899, -899, -899, -899, -899, -899, -899, -899,
+     -899, -899, -899, -899, -899, -899, -899, -899, -899, -899,
+
+     -899, -899,  900, -899, -899, -899, -899, -899, -899, -899,
+     -899, -899, -899, -899, -899, -899, -899, -899, -899, -899,
+     -899, -899, -899, -899, -899, -899, -899, -899, -899, -899,
+     -899, -899, -899, -899, -899, -899, -899, -899, -899, -899,
+     -899, -899, -899, -899, -899, -899, -899, -899, -899, -899,
+     -899, -899, -899, -899, -899, -899, -899, -899, -899, -899,
+     -899, -899, -899, -899, -899, -899, -899, -899, -899, -899,
+     -899, -899, -899, -899, -899, -899, -899, -899, -899, -899,
+     -899, -899, -899, -899, -899, -899, -899, -899, -899, -899,
+     -899, -899, -899, -899, -899, -899, -899, -899
+
+    },
+
+    {
+       67, -900, -900, -900, -900, -900, -900, -900, -900, -900,
+     -900, -900, -900, -900, -900, -900, -900, -900, -900, -900,
+     -900, -900, -900, -900, -900, -900, -900, -900, -900, -900,
+     -900, -900,  901, -900, -900, -900, -900, -900, -900, -900,
+     -900, -900, -900, -900, -900, -900, -900, -900, -900, -900,
+     -900, -900, -900, -900, -900, -900, -900, -900, -900, -900,
+     -900, -900, -900, -900, -900, -900, -900, -900, -900, -900,
+     -900, -900, -900, -900, -900, -900, -900, -900, -900, -900,
+     -900, -900, -900, -900, -900, -900, -900, -900, -900, -900,
+     -900, -900, -900, -900, -900, -900, -900, -900, -900, -900,
+
+     -900, -900, -900, -900, -900, -900, -900, -900, -900, -900,
+     -900, -900, -900, -900, -900, -900, -900, -900, -900, -900,
+     -900, -900, -900, -900, -900, -900, -900, -900
+    },
+
+    {
+       67, -901, -901, -901, -901, -901, -901, -901, -901, -901,
+     -901, -901, -901, -901, -901, -901, -901, -901, -901, -901,
+     -901, -901, -901, -901, -901, -901, -901, -901, -901, -901,
+     -901, -901,  902, -901, -901, -901, -901, -901, -901, -901,
+     -901, -901, -901, -901, -901, -901, -901, -901, -901, -901,
+     -901, -901, -901, -901, -901, -901, -901, -901, -901, -901,
+     -901, -901, -901, -901, -901, -901, -901, -901, -901, -901,
+
+     -901, -901, -901, -901, -901, -901, -901, -901, -901, -901,
+     -901, -901, -901, -901, -901, -901, -901, -901, -901, -901,
+     -901, -901, -901, -901, -901, -901, -901, -901, -901, -901,
+     -901, -901, -901, -901, -901, -901, -901, -901, -901, -901,
+     -901, -901, -901, -901, -901, -901, -901, -901, -901, -901,
+     -901, -901, -901, -901, -901, -901, -901, -901
+    },
+
+    {
+       67, -902, -902, -902, -902, -902, -902, -902, -902, -902,
+     -902, -902, -902, -902, -902, -902, -902, -902, -902, -902,
+     -902, -902, -902, -902, -902, -902, -902, -902, -902, -902,
+     -902, -902,  903, -902, -902, -902, -902, -902, -902, -902,
+
+     -902, -902, -902, -902, -902, -902, -902, -902, -902, -902,
+     -902, -902, -902, -902, -902, -902, -902, -902, -902, -902,
+     -902, -902, -902, -902, -902, -902, -902, -902, -902, -902,
+     -902, -902, -902, -902, -902, -902, -902, -902, -902, -902,
+     -902, -902, -902, -902, -902, -902, -902, -902, -902, -902,
+     -902, -902, -902, -902, -902, -902, -902, -902, -902, -902,
+     -902, -902, -902, -902, -902, -902, -902, -902, -902, -902,
+     -902, -902, -902, -902, -902, -902, -902, -902, -902, -902,
+     -902, -902, -902, -902, -902, -902, -902, -902
+    },
+
+    {
+       67, -903, -903, -903, -903, -903, -903, -903, -903, -903,
+
+     -903, -903, -903, -903, -903, -903, -903, -903, -903, -903,
+     -903, -903, -903, -903, -903, -903, -903, -903, -903, -903,
+     -903, -903,  904, -903, -903, -903, -903, -903, -903, -903,
+     -903, -903, -903, -903, -903, -903, -903, -903, -903, -903,
+     -903, -903, -903, -903, -903, -903, -903, -903, -903, -903,
+     -903, -903, -903, -903, -903, -903, -903, -903, -903, -903,
+     -903, -903, -903, -903, -903, -903, -903, -903, -903, -903,
+     -903, -903, -903, -903, -903, -903, -903, -903, -903, -903,
+     -903, -903, -903, -903, -903, -903, -903, -903, -903, -903,
+     -903, -903, -903, -903, -903, -903, -903, -903, -903, -903,
+
+     -903, -903, -903, -903, -903, -903, -903, -903, -903, -903,
+     -903, -903, -903, -903, -903, -903, -903, -903
+    },
+
+    {
+       67, -904, -904, -904, -904, -904, -904, -904, -904, -904,
+     -904, -904, -904, -904, -904, -904, -904, -904, -904, -904,
+     -904, -904, -904, -904, -904, -904, -904, -904, -904, -904,
+     -904, -904,  905, -904, -904, -904, -904, -904, -904, -904,
+     -904, -904, -904, -904, -904, -904, -904, -904, -904, -904,
+     -904, -904, -904, -904, -904, -904, -904, -904, -904, -904,
+     -904, -904, -904, -904, -904, -904, -904, -904, -904, -904,
+     -904, -904, -904, -904, -904, -904, -904, -904, -904, -904,
+
+     -904, -904, -904, -904, -904, -904, -904, -904, -904, -904,
+     -904, -904, -904, -904, -904, -904, -904, -904, -904, -904,
+     -904, -904, -904, -904, -904, -904, -904, -904, -904, -904,
+     -904, -904, -904, -904, -904, -904, -904, -904, -904, -904,
+     -904, -904, -904, -904, -904, -904, -904, -904
+    },
+
+    {
+       67, -905, -905, -905, -905, -905, -905, -905, -905, -905,
+     -905, -905, -905, -905, -905, -905, -905, -905, -905, -905,
+     -905, -905, -905, -905, -905, -905, -905, -905, -905, -905,
+     -905, -905,  906, -905, -905, -905, -905, -905, -905, -905,
+     -905, -905, -905, -905, -905, -905, -905, -905, -905, -905,
+
+     -905, -905, -905, -905, -905, -905, -905, -905, -905, -905,
+     -905, -905, -905, -905, -905, -905, -905, -905, -905, -905,
+     -905, -905, -905, -905, -905, -905, -905, -905, -905, -905,
+     -905, -905, -905, -905, -905, -905, -905, -905, -905, -905,
+     -905, -905, -905, -905, -905, -905, -905, -905, -905, -905,
+     -905, -905, -905, -905, -905, -905, -905, -905, -905, -905,
+     -905, -905, -905, -905, -905, -905, -905, -905, -905, -905,
+     -905, -905, -905, -905, -905, -905, -905, -905
+    },
+
+    {
+       67, -906, -906, -906, -906, -906, -906, -906, -906, -906,
+     -906, -906, -906, -906, -906, -906, -906, -906, -906, -906,
+
+     -906, -906, -906, -906, -906, -906, -906, -906, -906, -906,
+     -906, -906,  907, -906, -906, -906, -906, -906, -906, -906,
+     -906, -906, -906, -906, -906, -906, -906, -906, -906, -906,
+     -906, -906, -906, -906, -906, -906, -906, -906, -906, -906,
+     -906, -906, -906, -906, -906, -906, -906, -906, -906, -906,
+     -906, -906, -906, -906, -906, -906, -906, -906, -906, -906,
+     -906, -906, -906, -906, -906, -906, -906, -906, -906, -906,
+     -906, -906, -906, -906, -906, -906, -906, -906, -906, -906,
+     -906, -906, -906, -906, -906, -906, -906, -906, -906, -906,
+     -906, -906, -906, -906, -906, -906, -906, -906, -906, -906,
+
+     -906, -906, -906, -906, -906, -906, -906, -906
+    },
+
+    {
+       67, -907, -907, -907, -907, -907, -907, -907, -907, -907,
+     -907, -907, -907, -907, -907, -907, -907, -907, -907, -907,
+     -907, -907, -907, -907, -907, -907, -907, -907, -907, -907,
+     -907, -907,  908, -907, -907, -907, -907, -907, -907, -907,
+     -907, -907, -907, -907, -907, -907, -907, -907, -907, -907,
+     -907, -907, -907, -907, -907, -907, -907, -907, -907, -907,
+     -907, -907, -907, -907, -907, -907, -907, -907, -907, -907,
+     -907, -907, -907, -907, -907, -907, -907, -907, -907, -907,
+     -907, -907, -907, -907, -907, -907, -907, -907, -907, -907,
+
+     -907, -907, -907, -907, -907, -907, -907, -907, -907, -907,
+     -907, -907, -907, -907, -907, -907, -907, -907, -907, -907,
+     -907, -907, -907, -907, -907, -907, -907, -907, -907, -907,
+     -907, -907, -907, -907, -907, -907, -907, -907
+    },
+
+    {
+       67, -908, -908, -908, -908, -908, -908, -908, -908, -908,
+     -908, -908, -908, -908, -908, -908, -908, -908, -908, -908,
+     -908, -908, -908, -908, -908, -908, -908, -908, -908, -908,
+     -908, -908,  909, -908, -908, -908, -908, -908, -908, -908,
+     -908, -908, -908, -908, -908, -908, -908, -908, -908, -908,
+     -908, -908, -908, -908, -908, -908, -908, -908, -908, -908,
+
+     -908, -908, -908, -908, -908, -908, -908, -908, -908, -908,
+     -908, -908, -908, -908, -908, -908, -908, -908, -908, -908,
+     -908, -908, -908, -908, -908, -908, -908, -908, -908, -908,
+     -908, -908, -908, -908, -908, -908, -908, -908, -908, -908,
+     -908, -908, -908, -908, -908, -908, -908, -908, -908, -908,
+     -908, -908, -908, -908, -908, -908, -908, -908, -908, -908,
+     -908, -908, -908, -908, -908, -908, -908, -908
+    },
+
+    {
+       67, -909, -909, -909, -909, -909, -909, -909, -909, -909,
+     -909, -909, -909, -909, -909, -909, -909, -909, -909, -909,
+     -909, -909, -909, -909, -909, -909, -909, -909, -909, -909,
+
+     -909, -909,  910, -909, -909, -909, -909, -909, -909, -909,
+     -909, -909, -909, -909, -909, -909, -909, -909, -909, -909,
+     -909, -909, -909, -909, -909, -909, -909, -909, -909, -909,
+     -909, -909, -909, -909, -909, -909, -909, -909, -909, -909,
+     -909, -909, -909, -909, -909, -909, -909, -909, -909, -909,
+     -909, -909, -909, -909, -909, -909, -909, -909, -909, -909,
+     -909, -909, -909, -909, -909, -909, -909, -909, -909, -909,
+     -909, -909, -909, -909, -909, -909, -909, -909, -909, -909,
+     -909, -909, -909, -909, -909, -909, -909, -909, -909, -909,
+     -909, -909, -909, -909, -909, -909, -909, -909
+
+    },
+
+    {
+       67, -910, -910, -910, -910, -910, -910, -910, -910, -910,
+     -910, -910, -910, -910, -910, -910, -910, -910, -910, -910,
+     -910, -910, -910, -910, -910, -910, -910, -910, -910, -910,
+     -910, -910,  911, -910, -910, -910, -910, -910, -910, -910,
+     -910, -910, -910, -910, -910, -910, -910, -910, -910, -910,
+     -910, -910, -910, -910, -910, -910, -910, -910, -910, -910,
+     -910, -910, -910, -910, -910, -910, -910, -910, -910, -910,
+     -910, -910, -910, -910, -910, -910, -910, -910, -910, -910,
+     -910, -910, -910, -910, -910, -910, -910, -910, -910, -910,
+     -910, -910, -910, -910, -910, -910, -910, -910, -910, -910,
+
+     -910, -910, -910, -910, -910, -910, -910, -910, -910, -910,
+     -910, -910, -910, -910, -910, -910, -910, -910, -910, -910,
+     -910, -910, -910, -910, -910, -910, -910, -910
+    },
+
+    {
+       67, -911, -911, -911, -911, -911, -911, -911, -911, -911,
+     -911, -911, -911, -911, -911, -911, -911, -911, -911, -911,
+     -911, -911, -911, -911, -911, -911, -911, -911, -911, -911,
+     -911, -911,  912, -911, -911, -911, -911, -911, -911, -911,
+     -911, -911, -911, -911, -911, -911, -911, -911, -911, -911,
+     -911, -911, -911, -911, -911, -911, -911, -911, -911, -911,
+     -911, -911, -911, -911, -911, -911, -911, -911, -911, -911,
+
+     -911, -911, -911, -911, -911, -911, -911, -911, -911, -911,
+     -911, -911, -911, -911, -911, -911, -911, -911, -911, -911,
+     -911, -911, -911, -911, -911, -911, -911, -911, -911, -911,
+     -911, -911, -911, -911, -911, -911, -911, -911, -911, -911,
+     -911, -911, -911, -911, -911, -911, -911, -911, -911, -911,
+     -911, -911, -911, -911, -911, -911, -911, -911
+    },
+
+    {
+       67, -912, -912, -912, -912, -912, -912, -912, -912, -912,
+     -912, -912, -912, -912, -912, -912, -912, -912, -912, -912,
+     -912, -912, -912, -912, -912, -912, -912, -912, -912, -912,
+     -912, -912,  913, -912, -912, -912, -912, -912, -912, -912,
+
+     -912, -912, -912, -912, -912, -912, -912, -912, -912, -912,
+     -912, -912, -912, -912, -912, -912, -912, -912, -912, -912,
+     -912, -912, -912, -912, -912, -912, -912, -912, -912, -912,
+     -912, -912, -912, -912, -912, -912, -912, -912, -912, -912,
+     -912, -912, -912, -912, -912, -912, -912, -912, -912, -912,
+     -912, -912, -912, -912, -912, -912, -912, -912, -912, -912,
+     -912, -912, -912, -912, -912, -912, -912, -912, -912, -912,
+     -912, -912, -912, -912, -912, -912, -912, -912, -912, -912,
+     -912, -912, -912, -912, -912, -912, -912, -912
+    },
+
+    {
+       67, -913, -913, -913, -913, -913, -913, -913, -913, -913,
+
+     -913, -913, -913, -913, -913, -913, -913, -913, -913, -913,
+     -913, -913, -913, -913, -913, -913, -913, -913, -913, -913,
+     -913, -913,  914, -913, -913, -913, -913, -913, -913, -913,
+     -913, -913, -913, -913, -913, -913, -913, -913, -913, -913,
+     -913, -913, -913, -913, -913, -913, -913, -913, -913, -913,
+     -913, -913, -913, -913, -913, -913, -913, -913, -913, -913,
+     -913, -913, -913, -913, -913, -913, -913, -913, -913, -913,
+     -913, -913, -913, -913, -913, -913, -913, -913, -913, -913,
+     -913, -913, -913, -913, -913, -913, -913, -913, -913, -913,
+     -913, -913, -913, -913, -913, -913, -913, -913, -913, -913,
+
+     -913, -913, -913, -913, -913, -913, -913, -913, -913, -913,
+     -913, -913, -913, -913, -913, -913, -913, -913
+    },
+
+    {
+       67, -914, -914, -914, -914, -914, -914, -914, -914, -914,
+     -914, -914, -914, -914, -914, -914, -914, -914, -914, -914,
+     -914, -914, -914, -914, -914, -914, -914, -914, -914, -914,
+     -914, -914,  915, -914, -914, -914, -914, -914, -914, -914,
+     -914, -914, -914, -914, -914, -914, -914, -914, -914, -914,
+     -914, -914, -914, -914, -914, -914, -914, -914, -914, -914,
+     -914, -914, -914, -914, -914, -914, -914, -914, -914, -914,
+     -914, -914, -914, -914, -914, -914, -914, -914, -914, -914,
+
+     -914, -914, -914, -914, -914, -914, -914, -914, -914, -914,
+     -914, -914, -914, -914, -914, -914, -914, -914, -914, -914,
+     -914, -914, -914, -914, -914, -914, -914, -914, -914, -914,
+     -914, -914, -914, -914, -914, -914, -914, -914, -914, -914,
+     -914, -914, -914, -914, -914, -914, -914, -914
+    },
+
+    {
+       67, -915, -915, -915, -915, -915, -915, -915, -915, -915,
+     -915, -915, -915, -915, -915, -915, -915, -915, -915, -915,
+     -915, -915, -915, -915, -915, -915, -915, -915, -915, -915,
+     -915, -915,  916, -915, -915, -915, -915, -915, -915, -915,
+     -915, -915, -915, -915, -915, -915, -915, -915, -915, -915,
+
+     -915, -915, -915, -915, -915, -915, -915, -915, -915, -915,
+     -915, -915, -915, -915, -915, -915, -915, -915, -915, -915,
+     -915, -915, -915, -915, -915, -915, -915, -915, -915, -915,
+     -915, -915, -915, -915, -915, -915, -915, -915, -915, -915,
+     -915, -915, -915, -915, -915, -915, -915, -915, -915, -915,
+     -915, -915, -915, -915, -915, -915, -915, -915, -915, -915,
+     -915, -915, -915, -915, -915, -915, -915, -915, -915, -915,
+     -915, -915, -915, -915, -915, -915, -915, -915
+    },
+
+    {
+       67, -916, -916, -916, -916, -916, -916, -916, -916, -916,
+     -916, -916, -916, -916, -916, -916, -916, -916, -916, -916,
+
+     -916, -916, -916, -916, -916, -916, -916, -916, -916, -916,
+     -916, -916,  917, -916, -916, -916, -916, -916, -916, -916,
+     -916, -916, -916, -916, -916, -916, -916, -916, -916, -916,
+     -916, -916, -916, -916, -916, -916, -916, -916, -916, -916,
+     -916, -916, -916, -916, -916, -916, -916, -916, -916, -916,
+     -916, -916, -916, -916, -916, -916, -916, -916, -916, -916,
+     -916, -916, -916, -916, -916, -916, -916, -916, -916, -916,
+     -916, -916, -916, -916, -916, -916, -916, -916, -916, -916,
+     -916, -916, -916, -916, -916, -916, -916, -916, -916, -916,
+     -916, -916, -916, -916, -916, -916, -916, -916, -916, -916,
+
+     -916, -916, -916, -916, -916, -916, -916, -916
+    },
+
+    {
+       67, -917, -917, -917, -917, -917, -917, -917, -917, -917,
+     -917, -917, -917, -917, -917, -917, -917, -917, -917, -917,
+     -917, -917, -917, -917, -917, -917, -917, -917, -917, -917,
+     -917, -917,  918, -917, -917, -917, -917, -917, -917, -917,
+     -917, -917, -917, -917, -917, -917, -917, -917, -917, -917,
+     -917, -917, -917, -917, -917, -917, -917, -917, -917, -917,
+     -917, -917, -917, -917, -917, -917, -917, -917, -917, -917,
+     -917, -917, -917, -917, -917, -917, -917, -917, -917, -917,
+     -917, -917, -917, -917, -917, -917, -917, -917, -917, -917,
+
+     -917, -917, -917, -917, -917, -917, -917, -917, -917, -917,
+     -917, -917, -917, -917, -917, -917, -917, -917, -917, -917,
+     -917, -917, -917, -917, -917, -917, -917, -917, -917, -917,
+     -917, -917, -917, -917, -917, -917, -917, -917
+    },
+
+    {
+       67, -918, -918, -918, -918, -918, -918, -918, -918, -918,
+     -918, -918, -918, -918, -918, -918, -918, -918, -918, -918,
+     -918, -918, -918, -918, -918, -918, -918, -918, -918, -918,
+     -918, -918,  919, -918, -918, -918, -918, -918, -918, -918,
+     -918, -918, -918, -918, -918, -918, -918, -918, -918, -918,
+     -918, -918, -918, -918, -918, -918, -918, -918, -918, -918,
+
+     -918, -918, -918, -918, -918, -918, -918, -918, -918, -918,
+     -918, -918, -918, -918, -918, -918, -918, -918, -918, -918,
+     -918, -918, -918, -918, -918, -918, -918, -918, -918, -918,
+     -918, -918, -918, -918, -918, -918, -918, -918, -918, -918,
+     -918, -918, -918, -918, -918, -918, -918, -918, -918, -918,
+     -918, -918, -918, -918, -918, -918, -918, -918, -918, -918,
+     -918, -918, -918, -918, -918, -918, -918, -918
+    },
+
+    {
+       67, -919, -919, -919, -919, -919, -919, -919, -919, -919,
+     -919, -919, -919, -919, -919, -919, -919, -919, -919, -919,
+     -919, -919, -919, -919, -919, -919, -919, -919, -919, -919,
+
+     -919, -919,  920, -919, -919, -919, -919, -919, -919, -919,
+     -919, -919, -919, -919, -919, -919, -919, -919, -919, -919,
+     -919, -919, -919, -919, -919, -919, -919, -919, -919, -919,
+     -919, -919, -919, -919, -919, -919, -919, -919, -919, -919,
+     -919, -919, -919, -919, -919, -919, -919, -919, -919, -919,
+     -919, -919, -919, -919, -919, -919, -919, -919, -919, -919,
+     -919, -919, -919, -919, -919, -919, -919, -919, -919, -919,
+     -919, -919, -919, -919, -919, -919, -919, -919, -919, -919,
+     -919, -919, -919, -919, -919, -919, -919, -919, -919, -919,
+     -919, -919, -919, -919, -919, -919, -919, -919
+
+    },
+
+    {
+       67, -920, -920, -920, -920, -920, -920, -920, -920, -920,
+     -920, -920, -920, -920, -920, -920, -920, -920, -920, -920,
+     -920, -920, -920, -920, -920, -920, -920, -920, -920, -920,
+     -920, -920,  921, -920, -920, -920, -920, -920, -920, -920,
+     -920, -920, -920, -920, -920, -920, -920, -920, -920, -920,
+     -920, -920, -920, -920, -920, -920, -920, -920, -920, -920,
+     -920, -920, -920, -920, -920, -920, -920, -920, -920, -920,
+     -920, -920, -920, -920, -920, -920, -920, -920, -920, -920,
+     -920, -920, -920, -920, -920, -920, -920, -920, -920, -920,
+     -920, -920, -920, -920, -920, -920, -920, -920, -920, -920,
+
+     -920, -920, -920, -920, -920, -920, -920, -920, -920, -920,
+     -920, -920, -920, -920, -920, -920, -920, -920, -920, -920,
+     -920, -920, -920, -920, -920, -920, -920, -920
+    },
+
+    {
+       67, -921, -921, -921, -921, -921, -921, -921, -921, -921,
+     -921, -921, -921, -921, -921, -921, -921, -921, -921, -921,
+     -921, -921, -921, -921, -921, -921, -921, -921, -921, -921,
+     -921, -921,  922, -921, -921, -921, -921, -921, -921, -921,
+     -921, -921, -921, -921, -921, -921, -921, -921, -921, -921,
+     -921, -921, -921, -921, -921, -921, -921, -921, -921, -921,
+     -921, -921, -921, -921, -921, -921, -921, -921, -921, -921,
+
+     -921, -921, -921, -921, -921, -921, -921, -921, -921, -921,
+     -921, -921, -921, -921, -921, -921, -921, -921, -921, -921,
+     -921, -921, -921, -921, -921, -921, -921, -921, -921, -921,
+     -921, -921, -921, -921, -921, -921, -921, -921, -921, -921,
+     -921, -921, -921, -921, -921, -921, -921, -921, -921, -921,
+     -921, -921, -921, -921, -921, -921, -921, -921
+    },
+
+    {
+       67, -922, -922, -922, -922, -922, -922, -922, -922, -922,
+     -922, -922, -922, -922, -922, -922, -922, -922, -922, -922,
+     -922, -922, -922, -922, -922, -922, -922, -922, -922, -922,
+     -922, -922,  923, -922, -922, -922, -922, -922, -922, -922,
+
+     -922, -922, -922, -922, -922, -922, -922, -922, -922, -922,
+     -922, -922, -922, -922, -922, -922, -922, -922, -922, -922,
+     -922, -922, -922, -922, -922, -922, -922, -922, -922, -922,
+     -922, -922, -922, -922, -922, -922, -922, -922, -922, -922,
+     -922, -922, -922, -922, -922, -922, -922, -922, -922, -922,
+     -922, -922, -922, -922, -922, -922, -922, -922, -922, -922,
+     -922, -922, -922, -922, -922, -922, -922, -922, -922, -922,
+     -922, -922, -922, -922, -922, -922, -922, -922, -922, -922,
+     -922, -922, -922, -922, -922, -922, -922, -922
+    },
+
+    {
+       67, -923, -923, -923, -923, -923, -923, -923, -923, -923,
+
+     -923, -923, -923, -923, -923, -923, -923, -923, -923, -923,
+     -923, -923, -923, -923, -923, -923, -923, -923, -923, -923,
+     -923, -923,  924, -923, -923, -923, -923, -923, -923, -923,
+     -923, -923, -923, -923, -923, -923, -923, -923, -923, -923,
+     -923, -923, -923, -923, -923, -923, -923, -923, -923, -923,
+     -923, -923, -923, -923, -923, -923, -923, -923, -923, -923,
+     -923, -923, -923, -923, -923, -923, -923, -923, -923, -923,
+     -923, -923, -923, -923, -923, -923, -923, -923, -923, -923,
+     -923, -923, -923, -923, -923, -923, -923, -923, -923, -923,
+     -923, -923, -923, -923, -923, -923, -923, -923, -923, -923,
+
+     -923, -923, -923, -923, -923, -923, -923, -923, -923, -923,
+     -923, -923, -923, -923, -923, -923, -923, -923
+    },
+
+    {
+       67, -924, -924, -924, -924, -924, -924, -924, -924, -924,
+     -924, -924, -924, -924, -924, -924, -924, -924, -924, -924,
+     -924, -924, -924, -924, -924, -924, -924, -924, -924, -924,
+     -924, -924,  925, -924, -924, -924, -924, -924, -924, -924,
+     -924, -924, -924, -924, -924, -924, -924, -924, -924, -924,
+     -924, -924, -924, -924, -924, -924, -924, -924, -924, -924,
+     -924, -924, -924, -924, -924, -924, -924, -924, -924, -924,
+     -924, -924, -924, -924, -924, -924, -924, -924, -924, -924,
+
+     -924, -924, -924, -924, -924, -924, -924, -924, -924, -924,
+     -924, -924, -924, -924, -924, -924, -924, -924, -924, -924,
+     -924, -924, -924, -924, -924, -924, -924, -924, -924, -924,
+     -924, -924, -924, -924, -924, -924, -924, -924, -924, -924,
+     -924, -924, -924, -924, -924, -924, -924, -924
+    },
+
+    {
+       67, -925, -925, -925, -925, -925, -925, -925, -925, -925,
+     -925, -925, -925, -925, -925, -925, -925, -925, -925, -925,
+     -925, -925, -925, -925, -925, -925, -925, -925, -925, -925,
+     -925, -925,  926, -925, -925, -925, -925, -925, -925, -925,
+     -925, -925, -925, -925, -925, -925, -925, -925, -925, -925,
+
+     -925, -925, -925, -925, -925, -925, -925, -925, -925, -925,
+     -925, -925, -925, -925, -925, -925, -925, -925, -925, -925,
+     -925, -925, -925, -925, -925, -925, -925, -925, -925, -925,
+     -925, -925, -925, -925, -925, -925, -925, -925, -925, -925,
+     -925, -925, -925, -925, -925, -925, -925, -925, -925, -925,
+     -925, -925, -925, -925, -925, -925, -925, -925, -925, -925,
+     -925, -925, -925, -925, -925, -925, -925, -925, -925, -925,
+     -925, -925, -925, -925, -925, -925, -925, -925
+    },
+
+    {
+       67, -926, -926, -926, -926, -926, -926, -926, -926, -926,
+     -926, -926, -926, -926, -926, -926, -926, -926, -926, -926,
+
+     -926, -926, -926, -926, -926, -926, -926, -926, -926, -926,
+     -926, -926, -926, -926, -926, -926, -926, -926, -926, -926,
+     -926, -926, -926, -926, -926, -926, -926, -926, -926, -926,
+     -926, -926, -926, -926, -926, -926, -926, -926, -926, -926,
+     -926, -926, -926, -926, -926, -926, -926, -926, -926, -926,
+     -926, -926, -926, -926, -926, -926, -926, -926, -926, -926,
+     -926, -926, -926, -926, -926, -926, -926, -926, -926, -926,
+     -926, -926, -926, -926, -926, -926, -926, -926, -926, -926,
+     -926, -926, -926, -926, -926, -926, -926, -926, -926, -926,
+     -926, -926, -926, -926, -926, -926, -926, -926, -926, -926,
+
+     -926, -926, -926, -926, -926, -926, -926, -926
+    },
+
+    } ;
+
+static yy_state_type yy_get_previous_state (void );
+static yy_state_type yy_try_NUL_trans (yy_state_type current_state  );
+static int yy_get_next_buffer (void );
+static void yy_fatal_error (yyconst char msg[]  );
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up wcsbthtext.
+ */
+#define YY_DO_BEFORE_ACTION \
+	(yytext_ptr) = yy_bp; \
+	wcsbthleng = (size_t) (yy_cp - yy_bp); \
+	(yy_hold_char) = *yy_cp; \
+	*yy_cp = '\0'; \
+	(yy_c_buf_p) = yy_cp;
+
+#define YY_NUM_RULES 283
+#define YY_END_OF_BUFFER 284
+/* This struct is not used in this scanner,
+   but its presence is necessary. */
+struct yy_trans_info
+	{
+	flex_int32_t yy_verify;
+	flex_int32_t yy_nxt;
+	};
+static yyconst flex_int16_t yy_accept[927] =
+    {   0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,  278,  278,
+      280,  280,  281,  281,    0,    0,  284,  283,  126,  126,
+      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
+      126,  126,  126,  283,  148,  148,  140,  140,  149,  149,
+      141,  141,  161,  161,  161,  283,  182,  182,  171,  171,
+
+      187,  187,  198,  198,  199,  199,  230,  230,  265,  265,
+      243,  243,  266,  266,  244,  244,  268,  268,  201,  202,
+      200,  209,  209,  210,  210,  218,  218,  219,  219,  270,
+      270,  272,  272,  271,  274,  274,  274,  273,  276,  276,
+      279,  278,  277,  280,  281,  283,  282,    0,    0,    0,
+       64,   58,   21,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,   17,    0,   63,
+       57,    0,    0,    0,    0,    0,    0,    0,   23,    0,
+       19,   66,   60,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,  269,  271,
+        0,  273,  273,  273,  273,    0,    0,  275,  278,  277,
+      277,  280,  281,    0,  282,    0,    0,    0,    0,    0,
+        0,    0,    0,   65,   59,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,   24,    0,    0,    0,    0,    0,    0,
+
+       20,   67,   61,    0,    0,    0,    0,    0,    0,    0,
+        0,  127,  128,  129,    0,    0,    0,  130,  131,  132,
+      137,  136,    0,    0,    0,  133,  134,  135,  139,  138,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,  183,  184,  186,  185,  188,  189,  190,
+      195,  194,  191,  192,  193,  197,  196,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,  267,    0,    0,
+        0,  206,  207,  208,    0,    0,    0,  215,  216,  217,
+      273,    0,  273,   22,   18,   26,    0,   69,   74,    0,
+
+       13,   44,   79,   39,   34,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,   84,    0,    0,    0,   91,
+       51,   49,    0,   93,    0,    0,    0,  103,    0,   54,
+       56,  108,  106,  110,    0,   28,    0,   71,   76,    0,
+       15,   46,   81,   41,   36,    0,  122,  114,    0,    0,
+        0,    0,  112,    0,    0,  121,    0,    0,  124,  142,
+      143,  144,  145,  146,  147,    0,    0,    0,    0,    0,
+        0,  162,  163,  164,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,  203,  204,  205,  211,  212,  213,  214,   27,   70,
+       75,   31,   14,   45,   80,   40,   35,   25,   68,   73,
+       30,   12,   43,   78,   38,   33,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,   95,    0,   97,   99,  101,
+       62,    0,    0,    0,    0,    0,    0,    0,   29,   72,
+       77,   32,   16,   47,   82,   42,   37,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,  170,  167,  169,  165,  166,  168,
+
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,  236,  234,  235,  231,
+      232,  233,    0,    0,    0,    0,    0,    0,    0,    0,
+      242,  240,  241,  237,  238,  239,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,  160,  159,  155,  158,  152,  153,  157,  150,  151,
+      154,  156,  181,  177,  180,  174,  176,  179,  172,  173,
+      175,  178,  229,  225,  228,  222,  223,  227,  220,  221,
+
+      224,  226,  260,  250,  259,  248,  249,  258,  245,  246,
+      247,  257,  264,  256,  263,  254,  255,  262,  251,  252,
+      253,  261,    0,    0,    0,    0,    0,    0,    0,   90,
+       50,   48,    0,    0,    0,    0,  102,    0,   52,   55,
+      105,  107,  109,    0,  113,  111,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,  120,    0,    0,    0,    0,
+        0,    0,  123,   83,   85,   86,   87,   88,    0,   89,
+       92,   94,   96,   98,  100,  104,   53,    0,  115,  117,
+      118,  119,  116,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        1,    0,    0,    3,    0,    0,    4,    0,    0,    5,
+        0,    0,    2,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    6,    0,    7,
+        0,    8,    0,    9,    0,   10,    0,   11,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,  125
+    } ;
+
+static yy_state_type yy_last_accepting_state;
+static char *yy_last_accepting_cpos;
+
+static yyconst yy_state_type yy_NUL_trans[927] =
+    {   0,
+       68,   69,   68,   68,   85,   85,   87,   87,   89,   89,
+       91,   91,   93,   93,   68,   68,   97,   97,   99,   99,
+      101,  101,  103,  103,  105,  105,  107,  107,  109,  109,
+      111,  111,  113,  113,  115,  115,  117,  117,  119,  119,
+      120,  120,  122,  122,  124,  124,  126,  126,  128,  128,
+      130,  130,  132,  132,  135,  135,  139,  139,  141,  141,
+      144,  144,  145,  145,  146,  146,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,  247,
+        0,    0,  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,    0,  247,    0,    0,  251,
+      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,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,  847,    0,  849,    0,  851,    0,
+      853,    0,  855,    0,  857,    0,  847,    0,  849,    0,
+      851,    0,  853,    0,  855,    0,  857,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0
+    } ;
+
+extern int wcsbth_flex_debug;
+int wcsbth_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 yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+char *wcsbthtext;
+#line 1 "wcsbth.l"
+/*============================================================================
+
+  WCSLIB 4.16 - an implementation of the FITS WCS standard.
+  Copyright (C) 1995-2012, Mark Calabretta
+
+  This file is part of WCSLIB.
+
+  WCSLIB is free software: you can redistribute it and/or modify it under the
+  terms of the GNU Lesser General Public License as published by the Free
+  Software Foundation, either version 3 of the License, or (at your option)
+  any later version.
+
+  WCSLIB 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 Lesser General Public License for
+  more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with WCSLIB.  If not, see http://www.gnu.org/licenses.
+
+  Direct correspondence concerning WCSLIB to mark at calabretta.id.au
+
+  Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
+  http://www.atnf.csiro.au/people/Mark.Calabretta
+  $Id: wcsbth.c,v 4.16 2012/11/07 04:42:44 cal103 Exp $
+*=============================================================================
+*
+* wcsbth.l is a Flex description file containing the definition of a lexical
+* scanner for parsing the WCS keyrecords for one or more image arrays and/or
+* pixel lists in a FITS binary table header.  It can also handle primary image
+* and image extension headers.
+*
+* wcsbth.l requires Flex v2.5.4 or later.  Refer to wcshdr.h for a description
+* of the user interface and operating notes.
+*
+* Implementation notes
+* --------------------
+* wcsbth() may be invoked with an option that causes it to recognise the
+* image-header form of WCS keywords as defaults for each alternate coordinate
+* representation (up to 27).  By design, with this option enabled wcsbth() can
+* also handle primary image and image extension headers, effectively treating
+* them as a single-column binary table though with WCS keywords of a different
+* form.
+*
+* NAXIS is always 2 for binary tables, it refers to the two-dimensional nature
+* of the table.  Thus NAXIS does not count the number of image axes in either
+* image arrays or pixels lists and for the latter there is not even a formal
+* equivalent of WCSAXESa.  Hence NAXIS is always ignored and a first pass
+* through the header is required to determine the number of images, the number
+* of alternate coordinate representations for each image (up to 27), and the
+* number of coordinate axes in each representation; this pass also counts the
+* number of iPVn_ma and iPSn_ma or TVk_ma and TSk_ma keywords in each
+* representation.
+*
+* On completion of the first pass, the association between column number and
+* axis number is defined for each representation of a pixel list.  Memory is
+* allocated for an array of the required number of wcsprm structs and each of
+* these is initialized appropriately.  These structs are filled in the second
+* pass.
+*
+* It is permissible for a scalar table column to contain degenerate (single-
+* point) image arrays and simultaneously form one axis of a pixel list.
+*
+* The parser does not check for duplicated keywords, for most keywords it
+* accepts the last encountered.
+*
+* wcsbth() does not currently handle the Green Bank convention.
+*
+*===========================================================================*/
+/* Options. */
+/* Indices for parameterized keywords. */
+/* Alternate coordinate system identifier. */
+/* Keyvalue data types. */
+/* Exclusive start states. */
+
+
+
+
+
+
+
+
+
+
+#line 106 "wcsbth.l"
+#include <math.h>
+#include <setjmp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "wcs.h"
+#include "wcshdr.h"
+#include "wcsmath.h"
+#include "wcsutil.h"
+
+			/* Codes used for keyvalue data types. */
+#define INTEGER 0
+#define FLOAT   1
+#define STRING  2
+
+			/* Bit masks used for keyword types:        */
+#define IMGAUX  0x1	/* Auxiliary image header, e.g. LONPOLEa or */
+			/* DATE-OBS.                                */
+#define IMGAXIS 0x2	/* Image header with axis number, e.g.      */
+			/* CTYPEia.                                 */
+#define IMGHEAD 0x3	/* Image header of either type.             */
+#define BIMGARR 0x4	/* Binary table image array with axis       */
+			/* number, e.g. iCTYna.                     */
+#define PIXLIST 0x8	/* Pixel list, e.g. TCTYna.                 */
+#define BINTAB  0xC	/* Shared binary table image array (without */
+			/* axis number) or pixel list, e.g. LONPna  */
+			/* or OBSGXn.                               */
+
+#define YY_DECL int wcsbth(char *header, int nkeyrec, int relax, int ctrl, \
+                           int keysel, int *colsel, int *nreject, int *nwcs, \
+			   struct wcsprm **wcs)
+
+#define YY_INPUT(inbuff, count, bufsize) \
+	{ \
+	  if (wcsbth_nkeyrec) { \
+	    strncpy(inbuff, wcsbth_hdr, 80); \
+	    inbuff[80] = '\n'; \
+	    wcsbth_hdr += 80; \
+	    wcsbth_nkeyrec--; \
+	    count = 81; \
+	  } else { \
+	    count = YY_NULL; \
+	  } \
+	}
+
+/* A convenience macro to get around incompatibilities between unput() and
+   yyless(): put wcsbthtext followed by a blank back onto the input stream. */
+#define WCSBTH_PUTBACK \
+  sprintf(stmp, "%s ", wcsbthtext); \
+  itmp = strlen(stmp); \
+  while (itmp) unput(stmp[--itmp]);
+
+/* These global variables are required by YY_INPUT. */
+char *wcsbth_hdr;
+int  wcsbth_nkeyrec;
+
+/* Used in preempting the call to exit() by yy_fatal_error(). */
+jmp_buf wcsbth_abort_jmp_env;
+#define exit(status) longjmp(wcsbth_abort_jmp_env, status)
+
+/* Struct used internally for header bookkeeping. */
+struct wcsbth_alts {
+  int ncol, ialt, icol, imgherit;
+  short int (*arridx)[27];
+  short int pixidx[27];
+  short int pad1;
+  unsigned int *pixlist;
+
+  unsigned char (*npv)[27];
+  unsigned char (*nps)[27];
+  unsigned char pixnpv[27];
+  unsigned char pixnps[27];
+  unsigned char pad2[2];
+};
+
+int wcsbth_pass1(int keytype, int i, int j, int n, int k, char a, char ptype,
+        struct wcsbth_alts *alts);
+int wcsbth_init1(struct wcsbth_alts *alts, int *nwcs, struct wcsprm **wcs);
+
+struct wcsprm *wcsbth_idx(struct wcsprm *wcs, struct wcsbth_alts *alts,
+        int keytype, int n, char a);
+int wcsbth_colax(struct wcsprm *wcs, struct wcsbth_alts *alts, int k, char a);
+
+int wcsbth_epoch(void *wptr);
+int wcsbth_vsource(void *wptr);
+
+int wcsbth_final(struct wcsbth_alts *alts, int *nwcs, struct wcsprm **wcs);
+
+#line 16845 "wcsbth.c"
+
+#define INITIAL 0
+#define CCCCCia 1
+#define iCCCna 2
+#define iCCCCn 3
+#define TCCCna 4
+#define TCCCCn 5
+#define CCi_ja 6
+#define ijCCna 7
+#define TCn_ka 8
+#define TCCn_ka 9
+#define CROTAi 10
+#define iCROTn 11
+#define TCROTn 12
+#define CCi_ma 13
+#define iCn_ma 14
+#define iCCn_ma 15
+#define TCn_ma 16
+#define TCCn_ma 17
+#define PROJPm 18
+#define CCCCCCCC 19
+#define CCCCCCCa 20
+#define CCCCna 21
+#define CCCCCna 22
+#define CCCCn 23
+#define CCCCCn 24
+#define VALUE 25
+#define INTEGER_VAL 26
+#define FLOAT_VAL 27
+#define STRING_VAL 28
+#define COMMENT 29
+#define DISCARD 30
+#define ERROR 31
+#define FLUSH 32
+
+#ifndef YY_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 <unistd.h>
+#endif
+
+#ifndef YY_EXTRA_TYPE
+#define YY_EXTRA_TYPE void *
+#endif
+
+static int yy_init_globals (void );
+
+/* Accessor methods to globals.
+   These are made visible to non-reentrant scanners for convenience. */
+
+int wcsbthlex_destroy (void );
+
+int wcsbthget_debug (void );
+
+void wcsbthset_debug (int debug_flag  );
+
+YY_EXTRA_TYPE wcsbthget_extra (void );
+
+void wcsbthset_extra (YY_EXTRA_TYPE user_defined  );
+
+FILE *wcsbthget_in (void );
+
+void wcsbthset_in  (FILE * in_str  );
+
+FILE *wcsbthget_out (void );
+
+void wcsbthset_out  (FILE * out_str  );
+
+int wcsbthget_leng (void );
+
+char *wcsbthget_text (void );
+
+int wcsbthget_lineno (void );
+
+void wcsbthset_lineno (int line_number  );
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int wcsbthwrap (void );
+#else
+extern int wcsbthwrap (void );
+#endif
+#endif
+
+    static void yyunput (int c,char *buf_ptr  );
+    
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char *,yyconst char *,int );
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * );
+#endif
+
+#ifndef YY_NO_INPUT
+
+#ifdef __cplusplus
+static int yyinput (void );
+#else
+static int input (void );
+#endif
+
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k */
+#define YY_READ_BUF_SIZE 16384
+#else
+#define YY_READ_BUF_SIZE 8192
+#endif /* __ia64__ */
+#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( wcsbthtext, wcsbthleng, 1, wcsbthout )) {} } while (0)
+#endif
+
+/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+	errno=0; \
+	while ( (result = read( fileno(wcsbthin), (char *) buf, max_size )) < 0 ) \
+	{ \
+		if( errno != EINTR) \
+		{ \
+			YY_FATAL_ERROR( "input in flex scanner failed" ); \
+			break; \
+		} \
+		errno=0; \
+		clearerr(wcsbthin); \
+	}\
+\
+
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_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 YY_DECL
+#define YY_DECL_IS_OURS 1
+
+extern int wcsbthlex (void);
+
+#define YY_DECL int wcsbthlex (void)
+#endif /* !YY_DECL */
+
+/* Code executed at the beginning of each rule, after wcsbthtext and wcsbthleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+	if ( wcsbthleng > 0 ) \
+		YY_CURRENT_BUFFER_LVALUE->yy_at_bol = \
+				(wcsbthtext[wcsbthleng - 1] == '\n'); \
+	YY_USER_ACTION
+
+/** The main scanner function which does all the work.
+ */
+YY_DECL
+{
+	register yy_state_type yy_current_state;
+	register char *yy_cp, *yy_bp;
+	register int yy_act;
+    
+#line 197 "wcsbth.l"
+
+	/* Keyword indices, as used in the WCS papers, e.g. iVn_ma, TPn_ka. */
+	char a;
+	int  i, j, k, m, n;
+	
+	char *cptr, *errmsg, errtxt[80], exclude[1000], *extkey, *hptr, ptype,
+	     stmp[16];
+	int  altlin, ialt, icol, incl, ipass, ipx, itmp, ix, jx, keytype,
+	     nsel, npass, status, valtype, voff;
+	void   *vptr, *wptr;
+	struct wcsbth_alts alts;
+	struct wcsprm *wcsp, wcstem;
+	int (*special)(void *);
+	int wcsbthlex_destroy(void);
+	
+	/* The data structures produced. */
+	*nwcs = 0;
+	*wcs  = 0x0;
+	
+	/* Parameters used to implement YY_INPUT. */
+	wcsbth_hdr = header;
+	wcsbth_nkeyrec = nkeyrec;
+	
+	/* Our handle on the input stream. */
+	hptr = header;
+	*nreject = 0;
+	
+	/* Keyword parameters. */
+	i = j = 0;
+	n = k = 0;
+	m = 0;
+	a = ' ';
+	
+	/* Header bookkeeping. */
+	alts.ncol = 0;
+	alts.arridx  = 0x0;
+	alts.pixlist = 0x0;
+	alts.npv = 0x0;
+	alts.nps = 0x0;
+	
+	for (ialt = 0; ialt < 27; ialt++) {
+	  alts.pixidx[ialt] = 0;
+	  alts.pixnpv[ialt] = 0;
+	  alts.pixnps[ialt] = 0;
+	}
+	
+	/* For decoding the keyvalue. */
+	keytype =  0;
+	valtype = -1;
+	vptr    = 0x0;
+	
+	/* For keywords that require special handling. */
+	altlin = 0;
+	ptype  = ' ';
+	special = 0x0;
+	
+	/* Selection by column number. */
+	nsel = colsel ? colsel[0] : 0;
+	incl = (nsel > 0);
+	for (icol = 0; icol < 1000; icol++) {
+	  exclude[icol] = incl;
+	}
+	for (icol = 1; icol <= abs(nsel); icol++) {
+	  itmp = colsel[icol];
+	  if (0 < itmp && itmp < 1000) {
+	    exclude[itmp] = !incl;
+	  }
+	}
+	exclude[0] = 0;
+	
+	/* Selection by keyword type. */
+	itmp = keysel;
+	keysel = 0;
+	if (itmp) {
+	  if (itmp & WCSHDR_IMGHEAD) keysel |= IMGHEAD;
+	  if (itmp & WCSHDR_BIMGARR) keysel |= BIMGARR;
+	  if (itmp & WCSHDR_PIXLIST) keysel |= PIXLIST;
+	}
+	if (keysel == 0) {
+	  keysel = IMGHEAD | BINTAB;
+	}
+	
+	/* Control variables. */
+	ipass = 1;
+	npass = 2;
+	
+	/* Return here via longjmp() invoked by yy_fatal_error(). */
+	if (setjmp(wcsbth_abort_jmp_env)) {
+	  return 4;
+	}
+	
+	BEGIN(INITIAL);
+
+
+#line 17146 "wcsbth.c"
+
+	if ( !(yy_init) )
+		{
+		(yy_init) = 1;
+
+#ifdef YY_USER_INIT
+		YY_USER_INIT;
+#endif
+
+		if ( ! (yy_start) )
+			(yy_start) = 1;	/* first start state */
+
+		if ( ! wcsbthin )
+			wcsbthin = stdin;
+
+		if ( ! wcsbthout )
+			wcsbthout = stdout;
+
+		if ( ! YY_CURRENT_BUFFER ) {
+			wcsbthensure_buffer_stack ();
+			YY_CURRENT_BUFFER_LVALUE =
+				wcsbth_create_buffer(wcsbthin,YY_BUF_SIZE );
+		}
+
+		wcsbth_load_buffer_state( );
+		}
+
+	while ( 1 )		/* loops until end-of-file is reached */
+		{
+		yy_cp = (yy_c_buf_p);
+
+		/* Support of wcsbthtext. */
+		*yy_cp = (yy_hold_char);
+
+		/* yy_bp points to the position in yy_ch_buf of the start of
+		 * the current run.
+		 */
+		yy_bp = yy_cp;
+
+		yy_current_state = (yy_start);
+		yy_current_state += YY_AT_BOL();
+yy_match:
+		while ( (yy_current_state = yy_nxt[yy_current_state][ YY_SC_TO_UI(*yy_cp) ]) > 0 )
+			{
+			if ( yy_accept[yy_current_state] )
+				{
+				(yy_last_accepting_state) = yy_current_state;
+				(yy_last_accepting_cpos) = yy_cp;
+				}
+
+			++yy_cp;
+			}
+
+		yy_current_state = -yy_current_state;
+
+yy_find_action:
+		yy_act = yy_accept[yy_current_state];
+
+		YY_DO_BEFORE_ACTION;
+
+do_action:	/* This label is used only to access EOF actions. */
+
+		switch ( yy_act )
+	{ /* beginning of action switch */
+			case 0: /* must back up */
+			/* undo the effects of YY_DO_BEFORE_ACTION */
+			*yy_cp = (yy_hold_char);
+			yy_cp = (yy_last_accepting_cpos) + 1;
+			yy_current_state = (yy_last_accepting_state);
+			goto yy_find_action;
+
+case 1:
+YY_RULE_SETUP
+#line 291 "wcsbth.l"
+{
+	  if (ipass == 1) {
+	    if (alts.ncol == 0) {
+	      sscanf(wcsbthtext, "TFIELDS = %d", &(alts.ncol));
+	      BEGIN(FLUSH);
+	    } else {
+	      errmsg = "Duplicate or out-of-sequence TFIELDS keyword";
+	      BEGIN(ERROR);
+	    }
+	
+	  } else {
+	    BEGIN(FLUSH);
+	  }
+	}
+	YY_BREAK
+case 2:
+YY_RULE_SETUP
+#line 306 "wcsbth.l"
+{
+	  keytype = IMGAXIS;
+	
+	  if (!(keytype & keysel)) {
+	    /* Ignore this key type. */
+	    BEGIN(DISCARD);
+	
+	  } else {
+	    if (relax & WCSHDR_ALLIMG) {
+	      if (ipass == 1) {
+	        sscanf(wcsbthtext, "WCSAXES%c= %d", &a, &i);
+	        wcsbth_pass1(IMGAXIS, i, 0, 0, 0, a, ' ', &alts);
+	      }
+	
+	      BEGIN(FLUSH);
+	
+	    } else if (relax & WCSHDR_reject) {
+	      errmsg = "Image-header keyword WCSAXESa in binary table";
+	      BEGIN(ERROR);
+	
+	    } else {
+	      /* Pretend we don't recognize it. */
+	      BEGIN(DISCARD);
+	    }
+	  }
+	}
+	YY_BREAK
+case 3:
+#line 334 "wcsbth.l"
+case 4:
+#line 335 "wcsbth.l"
+case 5:
+YY_RULE_SETUP
+#line 335 "wcsbth.l"
+{
+	  keytype = BIMGARR;
+	
+	  /* Note that a blank in the sscanf() format string matches zero or
+	     more of them in the input. */
+	  sscanf(wcsbthtext, "WCAX%d%c = %d", &n, &a, &i);
+	
+	  if (!(keytype & keysel) || exclude[n]) {
+	    /* Ignore this key type or column. */
+	    BEGIN(DISCARD);
+	  } else {
+	    if (ipass == 1) {
+	      wcsbth_pass1(BIMGARR, i, 0, n, 0, a, ' ', &alts);
+	    }
+	    BEGIN(FLUSH);
+	  }
+	}
+	YY_BREAK
+case 6:
+/* rule 6 can match eol */
+#line 354 "wcsbth.l"
+case 7:
+/* rule 7 can match eol */
+#line 355 "wcsbth.l"
+case 8:
+/* rule 8 can match eol */
+YY_RULE_SETUP
+#line 355 "wcsbth.l"
+{
+	  /* Cross-reference supplier. */
+	  keytype = BIMGARR;
+	  errmsg = "Cross-references are not currently implemented";
+	  BEGIN(ERROR);
+	}
+	YY_BREAK
+case 9:
+/* rule 9 can match eol */
+#line 363 "wcsbth.l"
+case 10:
+/* rule 10 can match eol */
+#line 364 "wcsbth.l"
+case 11:
+/* rule 11 can match eol */
+YY_RULE_SETUP
+#line 364 "wcsbth.l"
+{
+	  /* Cross-reference consumer. */
+	  keytype = BIMGARR;
+	  errmsg = "Cross-references are not currently implemented";
+	  BEGIN(ERROR);
+	}
+	YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 371 "wcsbth.l"
+{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.crpix);
+	
+	  extkey = "CRPIXja";
+	  BEGIN(CCCCCia);
+	}
+	YY_BREAK
+case 13:
+#line 380 "wcsbth.l"
+case 14:
+YY_RULE_SETUP
+#line 380 "wcsbth.l"
+{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.crpix);
+	
+	  sscanf(wcsbthtext, "%d", &i);
+	
+	  if (wcsbthleng == 4) {
+	    BEGIN(iCCCna);
+	  } else {
+	    extkey = "jCRPXn";
+	    BEGIN(iCCCCn);
+	  }
+	}
+	YY_BREAK
+case 15:
+#line 395 "wcsbth.l"
+case 16:
+YY_RULE_SETUP
+#line 395 "wcsbth.l"
+{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.crpix);
+	
+	  if (wcsbthleng == 4) {
+	    BEGIN(TCCCna);
+	  } else {
+	    extkey = "TCRPXn";
+	    BEGIN(TCCCCn);
+	  }
+	}
+	YY_BREAK
+case 17:
+YY_RULE_SETUP
+#line 407 "wcsbth.l"
+{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.pc);
+	  altlin = 1;
+	
+	  extkey = "PCi_ja";
+	  BEGIN(CCi_ja);
+	}
+	YY_BREAK
+case 18:
+YY_RULE_SETUP
+#line 416 "wcsbth.l"
+{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.pc);
+	  altlin = 1;
+	
+	  sscanf(wcsbthtext, "%1d%1d", &i, &j);
+	
+	  BEGIN(ijCCna);
+	}
+	YY_BREAK
+case 19:
+#line 427 "wcsbth.l"
+case 20:
+YY_RULE_SETUP
+#line 427 "wcsbth.l"
+{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.pc);
+	  altlin = 1;
+	
+	  if (wcsbthleng == 2) {
+	    BEGIN(TCn_ka);
+	  } else {
+	    extkey = "TPCn_ka";
+	    BEGIN(TCCn_ka);
+	  }
+	}
+	YY_BREAK
+case 21:
+YY_RULE_SETUP
+#line 440 "wcsbth.l"
+{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.cd);
+	  altlin = 2;
+	
+	  extkey = "CDi_ja";
+	  BEGIN(CCi_ja);
+	}
+	YY_BREAK
+case 22:
+YY_RULE_SETUP
+#line 449 "wcsbth.l"
+{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.cd);
+	  altlin = 2;
+	
+	  sscanf(wcsbthtext, "%1d%1d", &i, &j);
+	
+	  BEGIN(ijCCna);
+	}
+	YY_BREAK
+case 23:
+#line 460 "wcsbth.l"
+case 24:
+YY_RULE_SETUP
+#line 460 "wcsbth.l"
+{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.cd);
+	  altlin = 2;
+	
+	  if (wcsbthleng == 2) {
+	    BEGIN(TCn_ka);
+	  } else {
+	    extkey = "TCDn_ka";
+	    BEGIN(TCCn_ka);
+	  }
+	}
+	YY_BREAK
+case 25:
+YY_RULE_SETUP
+#line 473 "wcsbth.l"
+{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.cdelt);
+	
+	  extkey = "CDELTia";
+	  BEGIN(CCCCCia);
+	}
+	YY_BREAK
+case 26:
+#line 482 "wcsbth.l"
+case 27:
+YY_RULE_SETUP
+#line 482 "wcsbth.l"
+{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.cdelt);
+	
+	  sscanf(wcsbthtext, "%d", &i);
+	
+	  if (wcsbthleng == 4) {
+	    BEGIN(iCCCna);
+	  } else {
+	    extkey = "iCDLTn";
+	    BEGIN(iCCCCn);
+	  }
+	}
+	YY_BREAK
+case 28:
+#line 497 "wcsbth.l"
+case 29:
+YY_RULE_SETUP
+#line 497 "wcsbth.l"
+{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.cdelt);
+	
+	  if (wcsbthleng == 4) {
+	    BEGIN(TCCCna);
+	  } else {
+	    extkey = "TCDLTn";
+	    BEGIN(TCCCCn);
+	  }
+	}
+	YY_BREAK
+case 30:
+YY_RULE_SETUP
+#line 509 "wcsbth.l"
+{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.crota);
+	  altlin = 4;
+	
+	  extkey = "CROTAi";
+	  BEGIN(CROTAi);
+	}
+	YY_BREAK
+case 31:
+YY_RULE_SETUP
+#line 518 "wcsbth.l"
+{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.crota);
+	  altlin = 4;
+	
+	  sscanf(wcsbthtext, "%d", &i);
+	
+	  extkey = "iCROTn";
+	  BEGIN(iCROTn);
+	}
+	YY_BREAK
+case 32:
+YY_RULE_SETUP
+#line 529 "wcsbth.l"
+{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.crota);
+	  altlin = 4;
+	
+	  extkey = "TCROTn";
+	  BEGIN(TCROTn);
+	}
+	YY_BREAK
+case 33:
+YY_RULE_SETUP
+#line 538 "wcsbth.l"
+{
+	  valtype = STRING;
+	  vptr = &(wcstem.cunit);
+	
+	  extkey = "CUNITia";
+	  BEGIN(CCCCCia);
+	}
+	YY_BREAK
+case 34:
+#line 547 "wcsbth.l"
+case 35:
+YY_RULE_SETUP
+#line 547 "wcsbth.l"
+{
+	  valtype = STRING;
+	  vptr = &(wcstem.cunit);
+	
+	  sscanf(wcsbthtext, "%d", &i);
+	
+	  if (wcsbthleng == 4) {
+	    BEGIN(iCCCna);
+	  } else {
+	    extkey = "iCUNIn";
+	    BEGIN(iCCCCn);
+	  }
+	}
+	YY_BREAK
+case 36:
+#line 562 "wcsbth.l"
+case 37:
+YY_RULE_SETUP
+#line 562 "wcsbth.l"
+{
+	  valtype = STRING;
+	  vptr = &(wcstem.cunit);
+	
+	  if (wcsbthleng == 4) {
+	    BEGIN(TCCCna);
+	  } else {
+	    extkey = "TCUNIn";
+	    BEGIN(TCCCCn);
+	  }
+	}
+	YY_BREAK
+case 38:
+YY_RULE_SETUP
+#line 574 "wcsbth.l"
+{
+	  valtype = STRING;
+	  vptr = &(wcstem.ctype);
+	
+	  extkey = "CTYPEia";
+	  BEGIN(CCCCCia);
+	}
+	YY_BREAK
+case 39:
+#line 583 "wcsbth.l"
+case 40:
+YY_RULE_SETUP
+#line 583 "wcsbth.l"
+{
+	  valtype = STRING;
+	  vptr = &(wcstem.ctype);
+	
+	  sscanf(wcsbthtext, "%d", &i);
+	
+	  if (wcsbthleng == 4) {
+	    BEGIN(iCCCna);
+	  } else {
+	    extkey = "iCTYPn";
+	    BEGIN(iCCCCn);
+	  }
+	}
+	YY_BREAK
+case 41:
+#line 598 "wcsbth.l"
+case 42:
+YY_RULE_SETUP
+#line 598 "wcsbth.l"
+{
+	  valtype = STRING;
+	  vptr = &(wcstem.ctype);
+	
+	  if (wcsbthleng == 4) {
+	    BEGIN(TCCCna);
+	  } else {
+	    extkey = "TCTYPn";
+	    BEGIN(TCCCCn);
+	  }
+	}
+	YY_BREAK
+case 43:
+YY_RULE_SETUP
+#line 610 "wcsbth.l"
+{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.crval);
+	
+	  extkey = "CRVALia";
+	  BEGIN(CCCCCia);
+	}
+	YY_BREAK
+case 44:
+#line 619 "wcsbth.l"
+case 45:
+YY_RULE_SETUP
+#line 619 "wcsbth.l"
+{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.crval);
+	
+	  sscanf(wcsbthtext, "%d", &i);
+	
+	  if (wcsbthleng == 4) {
+	    BEGIN(iCCCna);
+	  } else {
+	    extkey = "iCRVLn";
+	    BEGIN(iCCCCn);
+	  }
+	}
+	YY_BREAK
+case 46:
+#line 634 "wcsbth.l"
+case 47:
+YY_RULE_SETUP
+#line 634 "wcsbth.l"
+{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.crval);
+	
+	  if (wcsbthleng == 4) {
+	    BEGIN(TCCCna);
+	  } else {
+	    extkey = "TCRVLn";
+	    BEGIN(TCCCCn);
+	  }
+	}
+	YY_BREAK
+case 48:
+#line 647 "wcsbth.l"
+case 49:
+YY_RULE_SETUP
+#line 647 "wcsbth.l"
+{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.lonpole);
+	
+	  if (wcsbthleng == 7) {
+	    extkey = "LONPOLEa";
+	    BEGIN(CCCCCCCa);
+	  } else {
+	    BEGIN(CCCCna);
+	  }
+	}
+	YY_BREAK
+case 50:
+#line 660 "wcsbth.l"
+case 51:
+YY_RULE_SETUP
+#line 660 "wcsbth.l"
+{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.latpole);
+	
+	  if (wcsbthleng == 7) {
+	    extkey = "LATPOLEa";
+	    BEGIN(CCCCCCCa);
+	  } else {
+	    BEGIN(CCCCna);
+	  }
+	}
+	YY_BREAK
+case 52:
+#line 673 "wcsbth.l"
+case 53:
+#line 674 "wcsbth.l"
+case 54:
+YY_RULE_SETUP
+#line 674 "wcsbth.l"
+{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.restfrq);
+	
+	  if (wcsbthleng == 8) {
+	    unput(' ');
+	    extkey = "RESTFREQ";
+	    BEGIN(CCCCCCCa);
+	  } else if (wcsbthleng == 7) {
+	    extkey = "RESTFRQa";
+	    BEGIN(CCCCCCCa);
+	  } else {
+	    BEGIN(CCCCna);
+	  }
+	}
+	YY_BREAK
+case 55:
+#line 691 "wcsbth.l"
+case 56:
+YY_RULE_SETUP
+#line 691 "wcsbth.l"
+{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.restwav);
+	
+	  if (wcsbthleng == 7) {
+	    extkey = "RESTWAVa";
+	    BEGIN(CCCCCCCa);
+	  } else {
+	    BEGIN(CCCCna);
+	  }
+	}
+	YY_BREAK
+case 57:
+YY_RULE_SETUP
+#line 703 "wcsbth.l"
+{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.pv);
+	  ptype = 'v';
+	
+	  extkey = "PVi_ma";
+	  BEGIN(CCi_ma);
+	}
+	YY_BREAK
+case 58:
+#line 713 "wcsbth.l"
+case 59:
+YY_RULE_SETUP
+#line 713 "wcsbth.l"
+{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.pv);
+	  ptype = 'v';
+	
+	  sscanf(wcsbthtext, "%d", &i);
+	
+	  if (wcsbthleng == 2) {
+	    BEGIN(iCn_ma);
+	  } else {
+	    extkey = "iPVn_ma";
+	    BEGIN(iCCn_ma);
+	  }
+	}
+	YY_BREAK
+case 60:
+#line 729 "wcsbth.l"
+case 61:
+YY_RULE_SETUP
+#line 729 "wcsbth.l"
+{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.pv);
+	  ptype = 'v';
+	
+	  if (wcsbthleng == 2) {
+	    BEGIN(TCn_ma);
+	  } else {
+	    extkey = "TPVn_ma";
+	    BEGIN(TCCn_ma);
+	  }
+	}
+	YY_BREAK
+case 62:
+YY_RULE_SETUP
+#line 742 "wcsbth.l"
+{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.pv);
+	  ptype = 'v';
+	
+	  BEGIN(PROJPm);
+	}
+	YY_BREAK
+case 63:
+YY_RULE_SETUP
+#line 750 "wcsbth.l"
+{
+	  valtype = STRING;
+	  vptr = &(wcstem.ps);
+	  ptype = 's';
+	
+	  extkey = "PSi_ma";
+	  BEGIN(CCi_ma);
+	}
+	YY_BREAK
+case 64:
+#line 760 "wcsbth.l"
+case 65:
+YY_RULE_SETUP
+#line 760 "wcsbth.l"
+{
+	  valtype = STRING;
+	  vptr = &(wcstem.ps);
+	  ptype = 's';
+	
+	  sscanf(wcsbthtext, "%d", &i);
+	
+	  if (wcsbthleng == 2) {
+	    BEGIN(iCn_ma);
+	  } else {
+	    extkey = "iPSn_ma";
+	    BEGIN(iCCn_ma);
+	  }
+	}
+	YY_BREAK
+case 66:
+#line 776 "wcsbth.l"
+case 67:
+YY_RULE_SETUP
+#line 776 "wcsbth.l"
+{
+	  valtype = STRING;
+	  vptr = &(wcstem.ps);
+	  ptype = 's';
+	
+	  if (wcsbthleng == 2) {
+	    BEGIN(TCn_ma);
+	  } else {
+	    extkey = "TPSn_ma";
+	    BEGIN(TCCn_ma);
+	  }
+	}
+	YY_BREAK
+case 68:
+YY_RULE_SETUP
+#line 789 "wcsbth.l"
+{
+	  valtype = STRING;
+	  vptr = &(wcstem.cname);
+	
+	  extkey = "CNAMEia";
+	  BEGIN(CCCCCia);
+	}
+	YY_BREAK
+case 69:
+#line 798 "wcsbth.l"
+case 70:
+YY_RULE_SETUP
+#line 798 "wcsbth.l"
+{
+	  valtype = STRING;
+	  vptr = &(wcstem.cname);
+	
+	  sscanf(wcsbthtext, "%d", &i);
+	
+	  if (wcsbthleng == 4) {
+	    BEGIN(iCCCna);
+	  } else {
+	    if (!(relax & WCSHDR_CNAMn)) vptr = 0x0;
+	    extkey = "iCNAMn";
+	    BEGIN(iCCCCn);
+	  }
+	}
+	YY_BREAK
+case 71:
+#line 814 "wcsbth.l"
+case 72:
+YY_RULE_SETUP
+#line 814 "wcsbth.l"
+{
+	  valtype = STRING;
+	  vptr = &(wcstem.cname);
+	
+	  if (wcsbthleng == 4) {
+	    BEGIN(TCCCna);
+	  } else {
+	    if (!(relax & WCSHDR_CNAMn)) vptr = 0x0;
+	    extkey = "TCNAMn";
+	    BEGIN(TCCCCn);
+	  }
+	}
+	YY_BREAK
+case 73:
+YY_RULE_SETUP
+#line 827 "wcsbth.l"
+{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.crder);
+	
+	  extkey = "CRDERia";
+	  BEGIN(CCCCCia);
+	}
+	YY_BREAK
+case 74:
+#line 836 "wcsbth.l"
+case 75:
+YY_RULE_SETUP
+#line 836 "wcsbth.l"
+{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.crder);
+	
+	  sscanf(wcsbthtext, "%d", &i);
+	
+	  if (wcsbthleng == 4) {
+	    BEGIN(iCCCna);
+	  } else {
+	    if (!(relax & WCSHDR_CNAMn)) vptr = 0x0;
+	    extkey = "iCRDEn";
+	    BEGIN(iCCCCn);
+	  }
+	}
+	YY_BREAK
+case 76:
+#line 852 "wcsbth.l"
+case 77:
+YY_RULE_SETUP
+#line 852 "wcsbth.l"
+{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.crder);
+	
+	  if (wcsbthleng == 4) {
+	    BEGIN(TCCCna);
+	  } else {
+	    if (!(relax & WCSHDR_CNAMn)) vptr = 0x0;
+	    extkey = "TCRDEn";
+	    BEGIN(TCCCCn);
+	  }
+	}
+	YY_BREAK
+case 78:
+YY_RULE_SETUP
+#line 865 "wcsbth.l"
+{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.csyer);
+	
+	  extkey = "CSYERia";
+	  BEGIN(CCCCCia);
+	}
+	YY_BREAK
+case 79:
+#line 874 "wcsbth.l"
+case 80:
+YY_RULE_SETUP
+#line 874 "wcsbth.l"
+{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.csyer);
+	
+	  sscanf(wcsbthtext, "%d", &i);
+	
+	  if (wcsbthleng == 4) {
+	    BEGIN(iCCCna);
+	  } else {
+	    if (!(relax & WCSHDR_CNAMn)) vptr = 0x0;
+	    extkey = "iCSYEn";
+	    BEGIN(iCCCCn);
+	  }
+	}
+	YY_BREAK
+case 81:
+#line 890 "wcsbth.l"
+case 82:
+YY_RULE_SETUP
+#line 890 "wcsbth.l"
+{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.csyer);
+	
+	  if (wcsbthleng == 4) {
+	    BEGIN(TCCCna);
+	  } else {
+	    if (!(relax & WCSHDR_CNAMn)) vptr = 0x0;
+	    extkey = "TCSYEn";
+	    BEGIN(TCCCCn);
+	  }
+	}
+	YY_BREAK
+case 83:
+#line 904 "wcsbth.l"
+case 84:
+YY_RULE_SETUP
+#line 904 "wcsbth.l"
+{
+	  valtype = STRING;
+	  vptr = wcstem.dateavg;
+	
+	  if (wcsbthleng == 8) {
+	    extkey = "DATE-AVG";
+	    BEGIN(CCCCCCCC);
+	  } else {
+	    BEGIN(CCCCn);
+	  }
+	}
+	YY_BREAK
+case 85:
+YY_RULE_SETUP
+#line 916 "wcsbth.l"
+{
+	  valtype = STRING;
+	  vptr = wcstem.dateobs;
+	
+	  extkey = "DATE-OBS";
+	  BEGIN(CCCCCCCC);
+	}
+	YY_BREAK
+case 86:
+#line 925 "wcsbth.l"
+case 87:
+#line 926 "wcsbth.l"
+case 88:
+YY_RULE_SETUP
+#line 926 "wcsbth.l"
+{
+	  if (relax & WCSHDR_DOBSn) {
+	    valtype = STRING;
+	    vptr = wcstem.dateobs;
+	
+	    yyless(4);
+	    BEGIN(CCCCn);
+	
+	  } else {
+	    keytype = BINTAB;
+	    if (relax & WCSHDR_reject) {
+	      errmsg = "DOBSna keyword is non-standard";
+	      BEGIN(ERROR);
+	    } else {
+	      BEGIN(DISCARD);
+	    }
+	  }
+	}
+	YY_BREAK
+case 89:
+YY_RULE_SETUP
+#line 945 "wcsbth.l"
+{
+	  sscanf(wcsbthtext, "EPOCH%c", &a);
+	
+	  if (a == ' ' || (relax & WCSHDR_EPOCHa)) {
+	    valtype = FLOAT;
+	    vptr = &(wcstem.equinox);
+	    special = wcsbth_epoch;
+	
+	    unput(a);
+	    extkey = "EPOCH";
+	    BEGIN(CCCCCCCa);
+	
+	  } else {
+	    keytype = IMGAUX;
+	    if (relax & WCSHDR_reject) {
+	      errmsg = "EPOCH keyword may not have an alternate version code";
+	      BEGIN(ERROR);
+	    } else {
+	      BEGIN(DISCARD);
+	    }
+	  }
+	}
+	YY_BREAK
+case 90:
+#line 969 "wcsbth.l"
+case 91:
+YY_RULE_SETUP
+#line 969 "wcsbth.l"
+{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.equinox);
+	
+	  if (wcsbthleng == 7) {
+	    extkey = "EQUINOXa";
+	    BEGIN(CCCCCCCa);
+	  } else {
+	    BEGIN(CCCCna);
+	  }
+	}
+	YY_BREAK
+case 92:
+#line 982 "wcsbth.l"
+case 93:
+YY_RULE_SETUP
+#line 982 "wcsbth.l"
+{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.mjdavg);
+	
+	  if (wcsbthleng == 8) {
+	    extkey = "MJD-AVG";
+	    BEGIN(CCCCCCCC);
+	  } else {
+	    BEGIN(CCCCn);
+	  }
+	}
+	YY_BREAK
+case 94:
+#line 995 "wcsbth.l"
+case 95:
+YY_RULE_SETUP
+#line 995 "wcsbth.l"
+{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.mjdobs);
+	
+	  if (wcsbthleng == 8) {
+	    extkey = "MJD-OBS";
+	    BEGIN(CCCCCCCC);
+	  } else {
+	    BEGIN(CCCCCn);
+	  }
+	}
+	YY_BREAK
+case 96:
+#line 1008 "wcsbth.l"
+case 97:
+YY_RULE_SETUP
+#line 1008 "wcsbth.l"
+{
+	  valtype = FLOAT;
+	  vptr = wcstem.obsgeo;
+	
+	  if (wcsbthleng == 8) {
+	    extkey = "OBSGEO-X";
+	    BEGIN(CCCCCCCC);
+	  } else {
+	    BEGIN(CCCCCn);
+	  }
+	}
+	YY_BREAK
+case 98:
+#line 1021 "wcsbth.l"
+case 99:
+YY_RULE_SETUP
+#line 1021 "wcsbth.l"
+{
+	  valtype = FLOAT;
+	  vptr = wcstem.obsgeo + 1;
+	
+	  if (wcsbthleng == 8) {
+	    extkey = "OBSGEO-Y";
+	    BEGIN(CCCCCCCC);
+	  } else {
+	    BEGIN(CCCCCn);
+	  }
+	}
+	YY_BREAK
+case 100:
+#line 1034 "wcsbth.l"
+case 101:
+YY_RULE_SETUP
+#line 1034 "wcsbth.l"
+{
+	  valtype = FLOAT;
+	  vptr = wcstem.obsgeo + 2;
+	
+	  if (wcsbthleng == 8) {
+	    extkey = "OBSGEO-Z";
+	    BEGIN(CCCCCCCC);
+	  } else {
+	    BEGIN(CCCCCn);
+	  }
+	}
+	YY_BREAK
+case 102:
+#line 1047 "wcsbth.l"
+case 103:
+YY_RULE_SETUP
+#line 1047 "wcsbth.l"
+{
+	  valtype = STRING;
+	  vptr = wcstem.radesys;
+	
+	  if (wcsbthleng == 7) {
+	    extkey = "RADESYSa";
+	    BEGIN(CCCCCCCa);
+	  } else {
+	    BEGIN(CCCCna);
+	  }
+	}
+	YY_BREAK
+case 104:
+YY_RULE_SETUP
+#line 1059 "wcsbth.l"
+{
+	  if (relax & WCSHDR_RADECSYS) {
+	    valtype = STRING;
+	    vptr = wcstem.radesys;
+	
+	    unput(' ');
+	    extkey = "RADECSYS";
+	    BEGIN(CCCCCCCa);
+	
+	  } else {
+	    keytype = IMGAUX;
+	    if (relax & WCSHDR_reject) {
+	      errmsg = "RADECSYS keyword is non-standard";
+	      BEGIN(ERROR);
+	    } else {
+	      BEGIN(DISCARD);
+	    }
+	  }
+	}
+	YY_BREAK
+case 105:
+#line 1080 "wcsbth.l"
+case 106:
+YY_RULE_SETUP
+#line 1080 "wcsbth.l"
+{
+	  valtype = STRING;
+	  vptr = wcstem.specsys;
+	
+	  if (wcsbthleng == 7) {
+	    extkey = "SPECSYSa";
+	    BEGIN(CCCCCCCa);
+	  } else {
+	    BEGIN(CCCCna);
+	  }
+	}
+	YY_BREAK
+case 107:
+#line 1093 "wcsbth.l"
+case 108:
+YY_RULE_SETUP
+#line 1093 "wcsbth.l"
+{
+	  valtype = STRING;
+	  vptr = wcstem.ssysobs;
+	
+	  if (wcsbthleng == 7) {
+	    extkey = "SSYSOBSa";
+	    BEGIN(CCCCCCCa);
+	  } else {
+	    BEGIN(CCCCna);
+	  }
+	}
+	YY_BREAK
+case 109:
+#line 1106 "wcsbth.l"
+case 110:
+YY_RULE_SETUP
+#line 1106 "wcsbth.l"
+{
+	  valtype = STRING;
+	  vptr = wcstem.ssyssrc;
+	
+	  if (wcsbthleng == 7) {
+	    extkey = "SSYSSRCa";
+	    BEGIN(CCCCCCCa);
+	  } else {
+	    BEGIN(CCCCna);
+	  }
+	}
+	YY_BREAK
+case 111:
+#line 1119 "wcsbth.l"
+case 112:
+YY_RULE_SETUP
+#line 1119 "wcsbth.l"
+{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.velosys);
+	
+	  if (wcsbthleng == 7) {
+	    extkey = "VELOSYSa";
+	    BEGIN(CCCCCCCa);
+	  } else {
+	    BEGIN(CCCCna);
+	  }
+	}
+	YY_BREAK
+case 113:
+#line 1132 "wcsbth.l"
+case 114:
+YY_RULE_SETUP
+#line 1132 "wcsbth.l"
+{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.velangl);
+	
+	  if (wcsbthleng == 7) {
+	    extkey = "VELANGLa";
+	    BEGIN(CCCCCCCa);
+	  } else {
+	    BEGIN(CCCCna);
+	  }
+	}
+	YY_BREAK
+case 115:
+YY_RULE_SETUP
+#line 1144 "wcsbth.l"
+{
+	  sscanf(wcsbthtext, "VELREF%c", &a);
+	
+	  if (a == ' ' || (relax & WCSHDR_VELREFa)) {
+	    valtype = INTEGER;
+	    vptr = &(wcstem.velref);
+	
+	    unput(a);
+	    extkey = "VELREF";
+	    BEGIN(CCCCCCCa);
+	
+	  } else {
+	    keytype = IMGAUX;
+	    if (relax & WCSHDR_reject) {
+	      errmsg = "VELREF keyword may not have an alternate version code";
+	      BEGIN(ERROR);
+	    } else {
+	      BEGIN(DISCARD);
+	    }
+	  }
+	}
+	YY_BREAK
+case 116:
+YY_RULE_SETUP
+#line 1166 "wcsbth.l"
+{
+	  if (relax & WCSHDR_VSOURCE) {
+	    valtype = FLOAT;
+	    vptr = &(wcstem.zsource);
+	    special = wcsbth_vsource;
+	
+	    yyless(7);
+	    extkey = "VSOURCEa";
+	    BEGIN(CCCCCCCa);
+	
+	  } else {
+	    keytype = IMGAUX;
+	    if (relax & WCSHDR_reject) {
+	      errmsg = "VSOURCEa keyword is deprecated";
+	      BEGIN(ERROR);
+	    } else {
+	      BEGIN(DISCARD);
+	    }
+	  }
+	}
+	YY_BREAK
+case 117:
+#line 1188 "wcsbth.l"
+case 118:
+#line 1189 "wcsbth.l"
+case 119:
+YY_RULE_SETUP
+#line 1189 "wcsbth.l"
+{
+	  if (relax & WCSHDR_VSOURCE) {
+	    valtype = FLOAT;
+	    vptr = &(wcstem.zsource);
+	    special = wcsbth_vsource;
+	
+	    yyless(4);
+	    BEGIN(CCCCna);
+	
+	  } else {
+	    keytype = BINTAB;
+	    if (relax & WCSHDR_reject) {
+	      errmsg = "VSOUna keyword is deprecated";
+	      BEGIN(ERROR);
+	    } else {
+	      /* Pretend we don't recognize it. */
+	      BEGIN(DISCARD);
+	    }
+	  }
+	}
+	YY_BREAK
+case 120:
+#line 1211 "wcsbth.l"
+case 121:
+#line 1212 "wcsbth.l"
+case 122:
+YY_RULE_SETUP
+#line 1212 "wcsbth.l"
+{
+	  valtype = STRING;
+	  vptr = wcstem.wcsname;
+	
+	  if (wcsbthleng == 7) {
+	    extkey = "WCSNAMEa";
+	    BEGIN(CCCCCCCa);
+	  } else {
+	    BEGIN(CCCCna);
+	  }
+	}
+	YY_BREAK
+case 123:
+#line 1225 "wcsbth.l"
+case 124:
+YY_RULE_SETUP
+#line 1225 "wcsbth.l"
+{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.zsource);
+	
+	  if (wcsbthleng == 7) {
+	    extkey = "ZSOURCEa";
+	    BEGIN(CCCCCCCa);
+	  } else {
+	    BEGIN(CCCCna);
+	  }
+	}
+	YY_BREAK
+case 125:
+YY_RULE_SETUP
+#line 1237 "wcsbth.l"
+{
+	  yyless(0);
+	  if (wcsbth_nkeyrec) {
+	    wcsbth_nkeyrec = 0;
+	    errmsg = "Keyrecords following the END keyrecord were ignored";
+	    BEGIN(ERROR);
+	  } else {
+	    BEGIN(DISCARD);
+	  }
+	}
+	YY_BREAK
+case 126:
+YY_RULE_SETUP
+#line 1248 "wcsbth.l"
+{
+	  yyless(0);
+	  BEGIN(DISCARD);
+	}
+	YY_BREAK
+case 127:
+#line 1254 "wcsbth.l"
+case 128:
+YY_RULE_SETUP
+#line 1254 "wcsbth.l"
+{
+	  /* Image-header keyword. */
+	  keytype = IMGAXIS;
+	  if (relax & WCSHDR_ALLIMG) {
+	    sscanf(wcsbthtext, "%d%c", &i, &a);
+	    BEGIN(VALUE);
+	
+	  } else if (relax & WCSHDR_reject) {
+	    errmsg = errtxt;
+	    sprintf(errmsg,
+	      "Image-header keyword %s in binary table", extkey);
+	    BEGIN(ERROR);
+	
+	  } else {
+	    /* Pretend we don't recognize it. */
+	    BEGIN(DISCARD);
+	  }
+	}
+	YY_BREAK
+case 129:
+YY_RULE_SETUP
+#line 1273 "wcsbth.l"
+{
+	  /* Invalid axis number in image-header keyword. */
+	  keytype = IMGAXIS;
+	  if (relax & WCSHDR_ALLIMG) {
+	    /* Will also be flagged by <VALUE> as invalid. */
+	    sscanf(wcsbthtext, "%3d", &i);
+	    BEGIN(VALUE);
+	
+	  } else {
+	    /* Pretend we don't recognize it. */
+	    BEGIN(DISCARD);
+	  }
+	}
+	YY_BREAK
+case 130:
+#line 1288 "wcsbth.l"
+case 131:
+#line 1289 "wcsbth.l"
+case 132:
+#line 1290 "wcsbth.l"
+case 133:
+#line 1291 "wcsbth.l"
+case 134:
+#line 1292 "wcsbth.l"
+case 135:
+YY_RULE_SETUP
+#line 1292 "wcsbth.l"
+{
+	  if (vptr) {
+	    WCSBTH_PUTBACK;
+	    BEGIN((YY_START == iCCCCn) ? iCCCna : TCCCna);
+	  } else {
+	    keytype = (YY_START == iCCCCn) ? BIMGARR : PIXLIST;
+	    if (relax & WCSHDR_reject) {
+	      errmsg = errtxt;
+	      sprintf(errmsg, "%s keyword is non-standard", extkey);
+	      BEGIN(ERROR);
+	    } else {
+	      BEGIN(DISCARD);
+	    }
+	  }
+	}
+	YY_BREAK
+case 136:
+#line 1309 "wcsbth.l"
+case 137:
+#line 1310 "wcsbth.l"
+case 138:
+#line 1311 "wcsbth.l"
+case 139:
+YY_RULE_SETUP
+#line 1311 "wcsbth.l"
+{
+	  if (vptr && (relax & WCSHDR_LONGKEY)) {
+	    WCSBTH_PUTBACK;
+	    BEGIN((YY_START == iCCCCn) ? iCCCna : TCCCna);
+	
+	  } else {
+	    keytype = (YY_START == iCCCna) ? BIMGARR : PIXLIST;
+	    if (relax & WCSHDR_reject) {
+	      errmsg = errtxt;
+	      if (!vptr) {
+	        sprintf(errmsg, "%s keyword is non-standard", extkey);
+	      } else {
+	        sprintf(errmsg,
+	          "%s keyword may not have an alternate version code", extkey);
+	      }
+	      BEGIN(ERROR);
+	
+	    } else {
+	      /* Pretend we don't recognize it. */
+	      BEGIN(DISCARD);
+	    }
+	  }
+	}
+	YY_BREAK
+case 140:
+#line 1336 "wcsbth.l"
+case 141:
+YY_RULE_SETUP
+#line 1336 "wcsbth.l"
+{
+	  BEGIN(DISCARD);
+	}
+	YY_BREAK
+case 142:
+#line 1341 "wcsbth.l"
+case 143:
+#line 1342 "wcsbth.l"
+case 144:
+#line 1343 "wcsbth.l"
+case 145:
+#line 1344 "wcsbth.l"
+case 146:
+#line 1345 "wcsbth.l"
+case 147:
+YY_RULE_SETUP
+#line 1345 "wcsbth.l"
+{
+	  sscanf(wcsbthtext, "%d%c", &n, &a);
+	  if (YY_START == TCCCna) i = wcsbth_colax(*wcs, &alts, n, a);
+	  keytype = (YY_START == iCCCna) ? BIMGARR : PIXLIST;
+	  BEGIN(VALUE);
+	}
+	YY_BREAK
+case 148:
+#line 1353 "wcsbth.l"
+case 149:
+YY_RULE_SETUP
+#line 1353 "wcsbth.l"
+{
+	  BEGIN(DISCARD);
+	}
+	YY_BREAK
+case 150:
+#line 1358 "wcsbth.l"
+case 151:
+#line 1359 "wcsbth.l"
+case 152:
+#line 1360 "wcsbth.l"
+case 153:
+YY_RULE_SETUP
+#line 1360 "wcsbth.l"
+{
+	  /* Image-header keyword. */
+	  if (relax & WCSHDR_ALLIMG) {
+	    sscanf(wcsbthtext, "%d_%d%c", &i, &j, &a);
+	    keytype = IMGAXIS;
+	    BEGIN(VALUE);
+	
+	  } else if (relax & WCSHDR_reject) {
+	    errmsg = errtxt;
+	    sprintf(errmsg,
+	      "Image-header keyword %s in binary table", extkey);
+	    BEGIN(ERROR);
+	
+	  } else {
+	    /* Pretend we don't recognize it. */
+	    BEGIN(DISCARD);
+	  }
+	}
+	YY_BREAK
+case 154:
+#line 1380 "wcsbth.l"
+case 155:
+#line 1381 "wcsbth.l"
+case 156:
+#line 1382 "wcsbth.l"
+case 157:
+#line 1383 "wcsbth.l"
+case 158:
+#line 1384 "wcsbth.l"
+case 159:
+YY_RULE_SETUP
+#line 1384 "wcsbth.l"
+{
+	  /* Invalid axis number in image-header keyword. */
+	  if (relax & WCSHDR_ALLIMG) {
+	    /* Will be flagged by <VALUE> as invalid. */
+	    sscanf(wcsbthtext, "%d_%d", &i, &j);
+	    keytype = IMGAXIS;
+	    BEGIN(VALUE);
+	
+	  } else {
+	    /* Pretend we don't recognize it. */
+	    BEGIN(DISCARD);
+	  }
+	}
+	YY_BREAK
+case 160:
+YY_RULE_SETUP
+#line 1398 "wcsbth.l"
+{
+	  /* This covers the defunct forms CD00i00j and PC00i00j. */
+	  if (((relax & WCSHDR_PC00i00j) && (altlin == 1)) ||
+	      ((relax & WCSHDR_CD00i00j) && (altlin == 2))) {
+	    sscanf(wcsbthtext, "%3d%3d", &i, &j);
+	    a = ' ';
+	    keytype = IMGAXIS;
+	    BEGIN(VALUE);
+	
+	  } else if (relax & WCSHDR_reject) {
+	    errmsg = errtxt;
+	    sprintf(errmsg, "Defunct form of %si_ja keyword",
+	                     (altlin==1) ? "PC" : "CD");
+	    BEGIN(ERROR);
+	
+	  } else {
+	    /* Pretend we don't recognize it. */
+	    BEGIN(DISCARD);
+	  }
+	}
+	YY_BREAK
+case 161:
+YY_RULE_SETUP
+#line 1419 "wcsbth.l"
+{
+	  BEGIN(DISCARD);
+	}
+	YY_BREAK
+case 162:
+#line 1424 "wcsbth.l"
+case 163:
+#line 1425 "wcsbth.l"
+case 164:
+YY_RULE_SETUP
+#line 1425 "wcsbth.l"
+{
+	  sscanf(wcsbthtext, "%d%c", &n, &a);
+	  keytype = BIMGARR;
+	  BEGIN(VALUE);
+	}
+	YY_BREAK
+case 165:
+#line 1432 "wcsbth.l"
+case 166:
+#line 1433 "wcsbth.l"
+case 167:
+#line 1434 "wcsbth.l"
+case 168:
+#line 1435 "wcsbth.l"
+case 169:
+#line 1436 "wcsbth.l"
+case 170:
+YY_RULE_SETUP
+#line 1436 "wcsbth.l"
+{
+	  if (relax & WCSHDR_LONGKEY) {
+	    WCSBTH_PUTBACK;
+	    BEGIN(TCn_ka);
+	
+	  } else if (relax & WCSHDR_reject) {
+	    errmsg = errtxt;
+	    sprintf(errmsg, "%s keyword is non-standard", extkey);
+	    BEGIN(ERROR);
+	
+	  } else {
+	    /* Pretend we don't recognize it. */
+	    BEGIN(DISCARD);
+	  }
+	}
+	YY_BREAK
+case 171:
+YY_RULE_SETUP
+#line 1452 "wcsbth.l"
+{
+	  BEGIN(DISCARD);
+	}
+	YY_BREAK
+case 172:
+#line 1457 "wcsbth.l"
+case 173:
+#line 1458 "wcsbth.l"
+case 174:
+#line 1459 "wcsbth.l"
+case 175:
+#line 1460 "wcsbth.l"
+case 176:
+#line 1461 "wcsbth.l"
+case 177:
+YY_RULE_SETUP
+#line 1461 "wcsbth.l"
+{
+	  sscanf(wcsbthtext, "%d_%d%c", &n, &k, &a);
+	  i = wcsbth_colax(*wcs, &alts, n, a);
+	  j = wcsbth_colax(*wcs, &alts, k, a);
+	  keytype = PIXLIST;
+	  BEGIN(VALUE);
+	}
+	YY_BREAK
+case 178:
+#line 1470 "wcsbth.l"
+case 179:
+#line 1471 "wcsbth.l"
+case 180:
+#line 1472 "wcsbth.l"
+case 181:
+YY_RULE_SETUP
+#line 1472 "wcsbth.l"
+{
+	  sscanf(wcsbthtext, "%d_%d", &n, &k);
+	  a = ' ';
+	  i = wcsbth_colax(*wcs, &alts, n, a);
+	  j = wcsbth_colax(*wcs, &alts, k, a);
+	  keytype = PIXLIST;
+	  BEGIN(VALUE);
+	}
+	YY_BREAK
+case 182:
+YY_RULE_SETUP
+#line 1481 "wcsbth.l"
+{
+	  BEGIN(DISCARD);
+	}
+	YY_BREAK
+case 183:
+#line 1486 "wcsbth.l"
+case 184:
+YY_RULE_SETUP
+#line 1486 "wcsbth.l"
+{
+	  yyless(0);
+	  BEGIN(CCCCCia);
+	}
+	YY_BREAK
+case 185:
+#line 1492 "wcsbth.l"
+case 186:
+YY_RULE_SETUP
+#line 1492 "wcsbth.l"
+{
+	  if (relax & WCSHDR_CROTAia) {
+	    yyless(0);
+	    BEGIN(CCCCCia);
+	
+	  } else if (relax & WCSHDR_reject) {
+	    errmsg = "CROTAn keyword may not have an alternate version code";
+	    BEGIN(ERROR);
+	
+	  } else {
+	    /* Pretend we don't recognize it. */
+	    BEGIN(DISCARD);
+	  }
+	}
+	YY_BREAK
+case 187:
+YY_RULE_SETUP
+#line 1507 "wcsbth.l"
+{
+	  BEGIN(DISCARD);
+	}
+	YY_BREAK
+case 188:
+#line 1512 "wcsbth.l"
+case 189:
+#line 1513 "wcsbth.l"
+case 190:
+#line 1514 "wcsbth.l"
+case 191:
+#line 1515 "wcsbth.l"
+case 192:
+#line 1516 "wcsbth.l"
+case 193:
+YY_RULE_SETUP
+#line 1516 "wcsbth.l"
+{
+	  WCSBTH_PUTBACK;
+	  BEGIN((YY_START == iCROTn) ? iCCCna : TCCCna);
+	}
+	YY_BREAK
+case 194:
+#line 1522 "wcsbth.l"
+case 195:
+#line 1523 "wcsbth.l"
+case 196:
+#line 1524 "wcsbth.l"
+case 197:
+YY_RULE_SETUP
+#line 1524 "wcsbth.l"
+{
+	  if (relax & WCSHDR_CROTAia) {
+	    WCSBTH_PUTBACK;
+	    BEGIN((YY_START == iCROTn) ? iCCCna : TCCCna);
+	
+	  } else if (relax & WCSHDR_reject) {
+	    errmsg = errtxt;
+	    sprintf(errmsg,
+	      "%s keyword may not have an alternate version code", extkey);
+	    BEGIN(ERROR);
+	
+	  } else {
+	    /* Pretend we don't recognize it. */
+	    BEGIN(DISCARD);
+	  }
+	}
+	YY_BREAK
+case 198:
+#line 1542 "wcsbth.l"
+case 199:
+YY_RULE_SETUP
+#line 1542 "wcsbth.l"
+{
+	  BEGIN(DISCARD);
+	}
+	YY_BREAK
+case 200:
+#line 1547 "wcsbth.l"
+case 201:
+YY_RULE_SETUP
+#line 1547 "wcsbth.l"
+{
+	  /* Image-header keyword. */
+	  if (relax & (WCSHDR_AUXIMG | WCSHDR_ALLIMG)) {
+	    if (YY_START == CCCCCCCa) {
+	      sscanf(wcsbthtext, "%c", &a);
+	    } else {
+	      a = 0;
+	      unput(wcsbthtext[0]);
+	    }
+	    keytype = IMGAUX;
+	    BEGIN(VALUE);
+	
+	  } else if (relax & WCSHDR_reject) {
+	    errmsg = errtxt;
+	    sprintf(errmsg,
+	      "Image-header keyword %s in binary table", extkey);
+	    BEGIN(ERROR);
+	
+	  } else {
+	    /* Pretend we don't recognize it. */
+	    BEGIN(DISCARD);
+	  }
+	}
+	YY_BREAK
+case 202:
+YY_RULE_SETUP
+#line 1571 "wcsbth.l"
+{
+	  BEGIN(DISCARD);
+	}
+	YY_BREAK
+case 203:
+#line 1576 "wcsbth.l"
+case 204:
+#line 1577 "wcsbth.l"
+case 205:
+#line 1578 "wcsbth.l"
+case 206:
+#line 1579 "wcsbth.l"
+case 207:
+YY_RULE_SETUP
+#line 1579 "wcsbth.l"
+{
+	  sscanf(wcsbthtext, "%d%c", &n, &a);
+	  keytype = BINTAB;
+	  BEGIN(VALUE);
+	}
+	YY_BREAK
+case 208:
+YY_RULE_SETUP
+#line 1585 "wcsbth.l"
+{
+	  sscanf(wcsbthtext, "%d", &n);
+	  a = ' ';
+	  keytype = BINTAB;
+	  BEGIN(VALUE);
+	}
+	YY_BREAK
+case 209:
+#line 1593 "wcsbth.l"
+case 210:
+YY_RULE_SETUP
+#line 1593 "wcsbth.l"
+{
+	  BEGIN(DISCARD);
+	}
+	YY_BREAK
+case 211:
+#line 1598 "wcsbth.l"
+case 212:
+#line 1599 "wcsbth.l"
+case 213:
+#line 1600 "wcsbth.l"
+case 214:
+#line 1601 "wcsbth.l"
+case 215:
+#line 1602 "wcsbth.l"
+case 216:
+#line 1603 "wcsbth.l"
+case 217:
+YY_RULE_SETUP
+#line 1603 "wcsbth.l"
+{
+	  sscanf(wcsbthtext, "%d", &n);
+	  a = 0;
+	  keytype = BINTAB;
+	  BEGIN(VALUE);
+	}
+	YY_BREAK
+case 218:
+#line 1611 "wcsbth.l"
+case 219:
+YY_RULE_SETUP
+#line 1611 "wcsbth.l"
+{
+	  BEGIN(DISCARD);
+	}
+	YY_BREAK
+case 220:
+#line 1616 "wcsbth.l"
+case 221:
+#line 1617 "wcsbth.l"
+case 222:
+#line 1618 "wcsbth.l"
+case 223:
+YY_RULE_SETUP
+#line 1618 "wcsbth.l"
+{
+	  /* Image-header keyword. */
+	  if (relax & WCSHDR_ALLIMG) {
+	    sscanf(wcsbthtext, "%d_%d%c", &i, &m, &a);
+	    keytype = IMGAXIS;
+	    BEGIN(VALUE);
+	
+	  } else if (relax & WCSHDR_reject) {
+	    errmsg = errtxt;
+	    sprintf(errmsg,
+	      "Image-header keyword %s in binary table", extkey);
+	    BEGIN(ERROR);
+	
+	  } else {
+	    /* Pretend we don't recognize it. */
+	    BEGIN(DISCARD);
+	  }
+	}
+	YY_BREAK
+case 224:
+#line 1638 "wcsbth.l"
+case 225:
+#line 1639 "wcsbth.l"
+case 226:
+#line 1640 "wcsbth.l"
+case 227:
+#line 1641 "wcsbth.l"
+case 228:
+#line 1642 "wcsbth.l"
+case 229:
+YY_RULE_SETUP
+#line 1642 "wcsbth.l"
+{
+	  /* Invalid parameter in image-header keyword. */
+	  if (relax & WCSHDR_ALLIMG) {
+	    /* Will be flagged by <VALUE> as invalid. */
+	    sscanf(wcsbthtext, "%d_%d", &i, &m);
+	    keytype = IMGAXIS;
+	    BEGIN(VALUE);
+	
+	  } else {
+	    /* Pretend we don't recognize it. */
+	    BEGIN(DISCARD);
+	  }
+	}
+	YY_BREAK
+case 230:
+YY_RULE_SETUP
+#line 1656 "wcsbth.l"
+{
+	  BEGIN(DISCARD);
+	}
+	YY_BREAK
+case 231:
+#line 1661 "wcsbth.l"
+case 232:
+#line 1662 "wcsbth.l"
+case 233:
+#line 1663 "wcsbth.l"
+case 234:
+#line 1664 "wcsbth.l"
+case 235:
+#line 1665 "wcsbth.l"
+case 236:
+#line 1666 "wcsbth.l"
+case 237:
+#line 1667 "wcsbth.l"
+case 238:
+#line 1668 "wcsbth.l"
+case 239:
+#line 1669 "wcsbth.l"
+case 240:
+#line 1670 "wcsbth.l"
+case 241:
+#line 1671 "wcsbth.l"
+case 242:
+YY_RULE_SETUP
+#line 1671 "wcsbth.l"
+{
+	  if (relax & WCSHDR_LONGKEY) {
+	    WCSBTH_PUTBACK;
+	    BEGIN((YY_START == iCCn_ma) ? iCn_ma : TCn_ma);
+	
+	  } else if (relax & WCSHDR_reject) {
+	    errmsg = errtxt;
+	    sprintf(errmsg, "%s keyword is non-standard", extkey);
+	    BEGIN(ERROR);
+	
+	  } else {
+	    /* Pretend we don't recognize it. */
+	    BEGIN(DISCARD);
+	  }
+	}
+	YY_BREAK
+case 243:
+#line 1688 "wcsbth.l"
+case 244:
+YY_RULE_SETUP
+#line 1688 "wcsbth.l"
+{
+	  BEGIN(DISCARD);
+	}
+	YY_BREAK
+case 245:
+#line 1693 "wcsbth.l"
+case 246:
+#line 1694 "wcsbth.l"
+case 247:
+#line 1695 "wcsbth.l"
+case 248:
+#line 1696 "wcsbth.l"
+case 249:
+#line 1697 "wcsbth.l"
+case 250:
+#line 1698 "wcsbth.l"
+case 251:
+#line 1699 "wcsbth.l"
+case 252:
+#line 1700 "wcsbth.l"
+case 253:
+#line 1701 "wcsbth.l"
+case 254:
+#line 1702 "wcsbth.l"
+case 255:
+#line 1703 "wcsbth.l"
+case 256:
+YY_RULE_SETUP
+#line 1703 "wcsbth.l"
+{
+	  sscanf(wcsbthtext, "%d_%d%c", &n, &m, &a);
+	  if (YY_START == TCn_ma) i = wcsbth_colax(*wcs, &alts, n, a);
+	  keytype = (YY_START == iCn_ma) ? BIMGARR : PIXLIST;
+	  BEGIN(VALUE);
+	}
+	YY_BREAK
+case 257:
+#line 1711 "wcsbth.l"
+case 258:
+#line 1712 "wcsbth.l"
+case 259:
+#line 1713 "wcsbth.l"
+case 260:
+#line 1714 "wcsbth.l"
+case 261:
+#line 1715 "wcsbth.l"
+case 262:
+#line 1716 "wcsbth.l"
+case 263:
+#line 1717 "wcsbth.l"
+case 264:
+YY_RULE_SETUP
+#line 1717 "wcsbth.l"
+{
+	  /* Invalid combinations will be flagged by <VALUE>. */
+	  sscanf(wcsbthtext, "%d_%d", &n, &m);
+	  a = ' ';
+	  if (YY_START == TCn_ma) i = wcsbth_colax(*wcs, &alts, n, a);
+	  keytype = (YY_START == iCn_ma) ? BIMGARR : PIXLIST;
+	  BEGIN(VALUE);
+	}
+	YY_BREAK
+case 265:
+#line 1727 "wcsbth.l"
+case 266:
+YY_RULE_SETUP
+#line 1727 "wcsbth.l"
+{
+	  BEGIN(DISCARD);
+	}
+	YY_BREAK
+case 267:
+YY_RULE_SETUP
+#line 1731 "wcsbth.l"
+{
+	  if (relax & WCSHDR_PROJPn) {
+	    sscanf(wcsbthtext, "%d", &m);
+	    i = 0;
+	    a = ' ';
+	    keytype = IMGAXIS;
+	    BEGIN(VALUE);
+	
+	  } else if (relax & WCSHDR_reject) {
+	    errmsg = "PROJPn keyword is defunct";
+	    BEGIN(ERROR);
+	
+	  } else {
+	    /* Pretend we don't recognize it. */
+	    BEGIN(DISCARD);
+	  }
+	}
+	YY_BREAK
+case 268:
+YY_RULE_SETUP
+#line 1749 "wcsbth.l"
+{
+	  BEGIN(DISCARD);
+	}
+	YY_BREAK
+case 269:
+YY_RULE_SETUP
+#line 1753 "wcsbth.l"
+{
+	  /* Do checks on i, j, m, n, k. */
+	  if (!(keytype & keysel)) {
+	    /* Selection by keyword type. */
+	    BEGIN(DISCARD);
+	
+	  } else if (exclude[n] || exclude[k]) {
+	    /* One or other column is not selected. */
+	    if (k && (exclude[n] != exclude[k])) {
+	      /* For keywords such as TCn_ka, both columns must be excluded.
+	         User error, so return immediately. */
+	      wcsbthlex_destroy();
+	      return 3;
+	
+	    } else {
+	      BEGIN(DISCARD);
+	    }
+	
+	  } else if (i > 99 || j > 99 || m > 99 || n > 999 || k > 999) {
+	    if (relax & WCSHDR_reject) {
+	      errmsg = errtxt;
+	      if (i > 99 || j > 99) {
+	        sprintf(errmsg, "Axis number exceeds 99");
+	      } else if (m > 99) {
+	        sprintf(errmsg, "Parameter number exceeds 99");
+	      } else if (n > 999 || k > 999) {
+	        sprintf(errmsg, "Column number exceeds 999");
+	      }
+	      BEGIN(ERROR);
+	
+	    } else {
+	      /* Pretend we don't recognize it. */
+	      BEGIN(DISCARD);
+	    }
+	
+	  } else if (ipass == 2 && npass == 3 && (keytype & BINTAB)) {
+	    /* Skip keyvalues that won't be inherited. */
+	    BEGIN(FLUSH);
+	
+	  } else if (ipass == 3 && (keytype & IMGHEAD)) {
+	    /* IMGHEAD keytypes are always dealt with on the second pass. */
+	    BEGIN(FLUSH);
+	
+	  } else if (vptr) {
+	    alts.icol = 0;
+	    alts.ialt = 0;
+	    voff = (char *)vptr - (char *)(&wcstem);
+	
+	    if (valtype == INTEGER) {
+	      BEGIN(INTEGER_VAL);
+	    } else if (valtype == FLOAT) {
+	      BEGIN(FLOAT_VAL);
+	    } else if (valtype == STRING) {
+	      BEGIN(STRING_VAL);
+	    } else {
+	      errmsg = errtxt;
+	      sprintf(errmsg, "Internal parser ERROR, bad data type: %d",
+	        valtype);
+	      BEGIN(ERROR);
+	    }
+	
+	  } else {
+	    errmsg = "Internal parser ERROR, null pointer";
+	    BEGIN(ERROR);
+	  }
+	}
+	YY_BREAK
+case 270:
+YY_RULE_SETUP
+#line 1820 "wcsbth.l"
+{
+	  errmsg = "Invalid KEYWORD = VALUE syntax";
+	  BEGIN(ERROR);
+	}
+	YY_BREAK
+case 271:
+YY_RULE_SETUP
+#line 1825 "wcsbth.l"
+{
+	  if (ipass == 1) {
+	    /* Do first-pass bookkeeping. */
+	    wcsbth_pass1(keytype, i, j, n, k, a, ptype, &alts);
+	    BEGIN(FLUSH);
+	
+	  } else {
+	    /* Update each coordinate representation. */
+	    while ((wcsp = wcsbth_idx(*wcs, &alts, keytype, n, a))) {
+	      wptr = (void *)((char *)wcsp + voff);
+	
+	      /* Read the keyvalue. */
+	      if (special) {
+	        special(wptr);
+	      } else {
+	        sscanf(wcsbthtext, "%d", (int *)wptr);
+	      }
+	    }
+	
+	    BEGIN(COMMENT);
+	  }
+	}
+	YY_BREAK
+case 272:
+YY_RULE_SETUP
+#line 1848 "wcsbth.l"
+{
+	  errmsg = "An integer value was expected";
+	  BEGIN(ERROR);
+	}
+	YY_BREAK
+case 273:
+YY_RULE_SETUP
+#line 1853 "wcsbth.l"
+{
+	  if (ipass == 1) {
+	    /* Do first-pass bookkeeping. */
+	    wcsbth_pass1(keytype, i, j, n, k, a, ptype, &alts);
+	    BEGIN(FLUSH);
+	
+	  } else {
+	    /* Update each coordinate representation. */
+	    while ((wcsp = wcsbth_idx(*wcs, &alts, keytype, n, a))) {
+	      wptr = (void *)((char *)wcsp + voff);
+	
+	      /* Apply keyword parameterization. */
+	      if (ptype == 'v') {
+	        ipx = wcsp->npv++;
+	        wcsp->pv[ipx].i = i;
+	        wcsp->pv[ipx].m = m;
+	        wptr = &(wcsp->pv[ipx].value);
+	
+	      } else if (j) {
+	        /* Is the de-reference necessary? */
+	        wptr = *((double **)wptr) + (i - 1)*(wcsp->naxis) + (j - 1);
+	
+	      } else if (i) {
+	        wptr = *((double **)wptr) + (i - 1);
+	      }
+	
+	      /* Read the keyvalue. */
+	      if (special) {
+	        special(wptr);
+	      } else {
+	        wcsutil_str2double(wcsbthtext, "%lf", (double *)wptr);
+	      }
+	
+	      /* Flag the presence of PC, or CD and/or CROTA. */
+	      if (altlin) {
+	        wcsp->altlin |= altlin;
+	        altlin = 0;
+	      }
+	    }
+	
+	    BEGIN(COMMENT);
+	  }
+	}
+	YY_BREAK
+case 274:
+YY_RULE_SETUP
+#line 1897 "wcsbth.l"
+{
+	  errmsg = "A floating-point value was expected";
+	  BEGIN(ERROR);
+	}
+	YY_BREAK
+case 275:
+/* rule 275 can match eol */
+YY_RULE_SETUP
+#line 1902 "wcsbth.l"
+{
+	  if (ipass == 1) {
+	    /* Do first-pass bookkeeping. */
+	    wcsbth_pass1(keytype, i, j, n, k, a, ptype, &alts);
+	    BEGIN(FLUSH);
+	
+	  } else {
+	    /* Update each coordinate representation. */
+	    while ((wcsp = wcsbth_idx(*wcs, &alts, keytype, n, a))) {
+	      wptr = (void *)((char *)wcsp + voff);
+	
+	      /* Apply keyword parameterization. */
+	      if (ptype == 's') {
+	        ipx = wcsp->nps++;
+	        wcsp->ps[ipx].i = i;
+	        wcsp->ps[ipx].m = m;
+	        wptr = wcsp->ps[ipx].value;
+	
+	      } else if (j) {
+	        wptr = *((char (**)[72])wptr) +
+	                (i - 1)*(wcsp->naxis) + (j - 1);
+	
+	      } else if (i) {
+	        wptr = *((char (**)[72])wptr) + (i - 1);
+	      }
+	
+	      /* Read the keyvalue. */
+	      cptr = (char *)wptr;
+	      strcpy(cptr, wcsbthtext+1);
+	
+	      /* Squeeze out repeated quotes. */
+	      ix = 0;
+	      for (jx = 0; jx < 72; jx++) {
+	        if (ix < jx) {
+	          cptr[ix] = cptr[jx];
+	        }
+	
+	        if (cptr[jx] == '\0') {
+	          if (ix) cptr[ix-1] = '\0';
+	          break;
+	        } else if (cptr[jx] == '\'' && cptr[jx+1] == '\'') {
+	          jx++;
+	        }
+	
+	        ix++;
+	      }
+	    }
+	
+	    BEGIN(COMMENT);
+	  }
+	}
+	YY_BREAK
+case 276:
+YY_RULE_SETUP
+#line 1954 "wcsbth.l"
+{
+	  errmsg = "A string value was expected";
+	  BEGIN(ERROR);
+	}
+	YY_BREAK
+case 277:
+#line 1960 "wcsbth.l"
+case 278:
+YY_RULE_SETUP
+#line 1960 "wcsbth.l"
+{
+	  BEGIN(FLUSH);
+	}
+	YY_BREAK
+case 279:
+YY_RULE_SETUP
+#line 1964 "wcsbth.l"
+{
+	  errmsg = "Malformed keycomment";
+	  BEGIN(ERROR);
+	}
+	YY_BREAK
+case 280:
+YY_RULE_SETUP
+#line 1969 "wcsbth.l"
+{
+	  if (ipass == npass) {
+	    if (ctrl < 0) {
+	      /* Preserve discards. */
+	      if (hptr < wcsbth_hdr-80) {
+	        strncpy(hptr, wcsbth_hdr-80, 80);
+	      }
+	      hptr += 80;
+	
+	    } else if (ctrl > 2) {
+	      fprintf(stderr, "%.80s\n  Discarded.\n", wcsbth_hdr-80);
+	    }
+	  }
+	
+	  BEGIN(FLUSH);
+	}
+	YY_BREAK
+case 281:
+YY_RULE_SETUP
+#line 1986 "wcsbth.l"
+{
+	  (*nreject)++;
+	  if (ipass == npass) {
+	    if (ctrl == -1) {
+	      if (hptr < wcsbth_hdr-80) {
+	        /* Preserve rejects. */
+	        strncpy(hptr, wcsbth_hdr-80, 80);
+	      }
+	      hptr += 80;
+	    }
+	
+	    if (abs(ctrl) > 1) {
+	      fprintf(stderr, "%.80s\n%4d: %s.\n", wcsbth_hdr-80, *nreject,
+	        errmsg);
+	    }
+	  }
+	
+	  BEGIN(FLUSH);
+	}
+	YY_BREAK
+case 282:
+/* rule 282 can match eol */
+YY_RULE_SETUP
+#line 2006 "wcsbth.l"
+{
+	  /* Throw away the rest of the line and reset for the next one. */
+	  i = j = 0;
+	  n = k = 0;
+	  m = 0;
+	  a = ' ';
+	
+	  keytype =  0;
+	  valtype = -1;
+	  vptr    = 0x0;
+	
+	  altlin = 0;
+	  ptype  = ' ';
+	  special = 0x0;
+	  BEGIN(INITIAL);
+	}
+	YY_BREAK
+case YY_STATE_EOF(INITIAL):
+case YY_STATE_EOF(CCCCCia):
+case YY_STATE_EOF(iCCCna):
+case YY_STATE_EOF(iCCCCn):
+case YY_STATE_EOF(TCCCna):
+case YY_STATE_EOF(TCCCCn):
+case YY_STATE_EOF(CCi_ja):
+case YY_STATE_EOF(ijCCna):
+case YY_STATE_EOF(TCn_ka):
+case YY_STATE_EOF(TCCn_ka):
+case YY_STATE_EOF(CROTAi):
+case YY_STATE_EOF(iCROTn):
+case YY_STATE_EOF(TCROTn):
+case YY_STATE_EOF(CCi_ma):
+case YY_STATE_EOF(iCn_ma):
+case YY_STATE_EOF(iCCn_ma):
+case YY_STATE_EOF(TCn_ma):
+case YY_STATE_EOF(TCCn_ma):
+case YY_STATE_EOF(PROJPm):
+case YY_STATE_EOF(CCCCCCCC):
+case YY_STATE_EOF(CCCCCCCa):
+case YY_STATE_EOF(CCCCna):
+case YY_STATE_EOF(CCCCCna):
+case YY_STATE_EOF(CCCCn):
+case YY_STATE_EOF(CCCCCn):
+case YY_STATE_EOF(VALUE):
+case YY_STATE_EOF(INTEGER_VAL):
+case YY_STATE_EOF(FLOAT_VAL):
+case YY_STATE_EOF(STRING_VAL):
+case YY_STATE_EOF(COMMENT):
+case YY_STATE_EOF(DISCARD):
+case YY_STATE_EOF(ERROR):
+case YY_STATE_EOF(FLUSH):
+#line 2023 "wcsbth.l"
+{
+	  /* End-of-input. */
+	  if (ipass == 1) {
+	    if ((status = wcsbth_init1(&alts, nwcs, wcs)) || *nwcs == 0) {
+	      wcsbthlex_destroy();
+	      return status;
+	    }
+
+	    if (alts.imgherit) npass = 3;
+	
+	    if (abs(ctrl) > 2) {
+	      if (*nwcs == 1) {
+	        fprintf(stderr, "Found one coordinate representation.\n");
+	      } else {
+	        fprintf(stderr, "Found %d coordinate representations.\n",
+	          *nwcs);
+	      }
+	    }
+	  }
+	
+	  if (ipass++ < npass) {
+	    wcsbth_hdr = header;
+	    wcsbth_nkeyrec = nkeyrec;
+	    *nreject = 0;
+	
+	    i = j = 0;
+	    k = n = 0;
+	    m = 0;
+	    a = ' ';
+	
+	    keytype =  0;
+	    valtype = -1;
+	    vptr    = 0x0;
+	
+	    altlin = 0;
+	    ptype  = ' ';
+	    special = 0x0;
+	
+	    wcsbthrestart(wcsbthin);
+	
+	  } else {
+	    wcsbthlex_destroy();
+	
+	    if (ctrl < 0) {
+	      *hptr = '\0';
+	    } else if (ctrl == 1) {
+	      fprintf(stderr, "%d WCS keyrecords were rejected.\n", *nreject);
+	    }
+	
+	    return wcsbth_final(&alts, nwcs, wcs);
+	  }
+	}
+	YY_BREAK
+case 283:
+YY_RULE_SETUP
+#line 2076 "wcsbth.l"
+ECHO;
+	YY_BREAK
+#line 19584 "wcsbth.c"
+
+	case YY_END_OF_BUFFER:
+		{
+		/* Amount of text matched not including the EOB char. */
+		int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;
+
+		/* Undo the effects of YY_DO_BEFORE_ACTION. */
+		*yy_cp = (yy_hold_char);
+		YY_RESTORE_YY_MORE_OFFSET
+
+		if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
+			{
+			/* We're scanning a new file or input source.  It's
+			 * possible that this happened because the user
+			 * just pointed wcsbthin at a new source and called
+			 * wcsbthlex().  If so, then we have to assure
+			 * consistency between YY_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.
+			 */
+			(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+			YY_CURRENT_BUFFER_LVALUE->yy_input_file = wcsbthin;
+			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
+			}
+
+		/* Note that here we test for yy_c_buf_p "<=" to the position
+		 * of the first EOB in the buffer, since yy_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 ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+			{ /* This was really a NUL. */
+			yy_state_type yy_next_state;
+
+			(yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;
+
+			yy_current_state = yy_get_previous_state(  );
+
+			/* Okay, we're now positioned to make the NUL
+			 * transition.  We couldn't have
+			 * yy_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).
+			 */
+
+			yy_next_state = yy_try_NUL_trans( yy_current_state );
+
+			yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+
+			if ( yy_next_state )
+				{
+				/* Consume the NUL. */
+				yy_cp = ++(yy_c_buf_p);
+				yy_current_state = yy_next_state;
+				goto yy_match;
+				}
+
+			else
+				{
+				yy_cp = (yy_c_buf_p);
+				goto yy_find_action;
+				}
+			}
+
+		else switch ( yy_get_next_buffer(  ) )
+			{
+			case EOB_ACT_END_OF_FILE:
+				{
+				(yy_did_buffer_switch_on_eof) = 0;
+
+				if ( wcsbthwrap( ) )
+					{
+					/* Note: because we've taken care in
+					 * yy_get_next_buffer() to have set up
+					 * wcsbthtext, we can now set up
+					 * yy_c_buf_p so that if some total
+					 * hoser (like flex itself) wants to
+					 * call the scanner after we return the
+					 * YY_NULL, it'll still work - another
+					 * YY_NULL will get returned.
+					 */
+					(yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;
+
+					yy_act = YY_STATE_EOF(YY_START);
+					goto do_action;
+					}
+
+				else
+					{
+					if ( ! (yy_did_buffer_switch_on_eof) )
+						YY_NEW_FILE;
+					}
+				break;
+				}
+
+			case EOB_ACT_CONTINUE_SCAN:
+				(yy_c_buf_p) =
+					(yytext_ptr) + yy_amount_of_matched_text;
+
+				yy_current_state = yy_get_previous_state(  );
+
+				yy_cp = (yy_c_buf_p);
+				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+				goto yy_match;
+
+			case EOB_ACT_LAST_MATCH:
+				(yy_c_buf_p) =
+				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];
+
+				yy_current_state = yy_get_previous_state(  );
+
+				yy_cp = (yy_c_buf_p);
+				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+				goto yy_find_action;
+			}
+		break;
+		}
+
+	default:
+		YY_FATAL_ERROR(
+			"fatal flex scanner internal error--no action found" );
+	} /* end of action switch */
+		} /* end of scanning one token */
+} /* end of wcsbthlex */
+
+/* yy_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 yy_get_next_buffer (void)
+{
+    	register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+	register char *source = (yytext_ptr);
+	register int number_to_move, i;
+	int ret_val;
+
+	if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
+		YY_FATAL_ERROR(
+		"fatal flex scanner internal error--end of buffer missed" );
+
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
+		{ /* Don't try to fill the buffer, so this is an EOF. */
+		if ( (yy_c_buf_p) - (yytext_ptr) - YY_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) ((yy_c_buf_p) - (yytext_ptr)) - 1;
+
+	for ( i = 0; i < number_to_move; ++i )
+		*(dest++) = *(source++);
+
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+		/* don't do the read, it's not guaranteed to return an EOF,
+		 * just force an EOF
+		 */
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
+
+	else
+		{
+			int num_to_read =
+			YY_CURRENT_BUFFER_LVALUE->yy_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 */
+			YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
+
+			int yy_c_buf_p_offset =
+				(int) ((yy_c_buf_p) - b->yy_ch_buf);
+
+			if ( b->yy_is_our_buffer )
+				{
+				int new_size = b->yy_buf_size * 2;
+
+				if ( new_size <= 0 )
+					b->yy_buf_size += b->yy_buf_size / 8;
+				else
+					b->yy_buf_size *= 2;
+
+				b->yy_ch_buf = (char *)
+					/* Include room in for 2 EOB chars. */
+					wcsbthrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2  );
+				}
+			else
+				/* Can't grow it, we don't own it. */
+				b->yy_ch_buf = 0;
+
+			if ( ! b->yy_ch_buf )
+				YY_FATAL_ERROR(
+				"fatal error - scanner input buffer overflow" );
+
+			(yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+			num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
+						number_to_move - 1;
+
+			}
+
+		if ( num_to_read > YY_READ_BUF_SIZE )
+			num_to_read = YY_READ_BUF_SIZE;
+
+		/* Read in more data. */
+		YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+			(yy_n_chars), (size_t) num_to_read );
+
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+		}
+
+	if ( (yy_n_chars) == 0 )
+		{
+		if ( number_to_move == YY_MORE_ADJ )
+			{
+			ret_val = EOB_ACT_END_OF_FILE;
+			wcsbthrestart(wcsbthin  );
+			}
+
+		else
+			{
+			ret_val = EOB_ACT_LAST_MATCH;
+			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
+				YY_BUFFER_EOF_PENDING;
+			}
+		}
+
+	else
+		ret_val = EOB_ACT_CONTINUE_SCAN;
+
+	if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+		/* Extend the array by 50%, plus the number we really need. */
+		yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1);
+		YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) wcsbthrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size  );
+		if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+			YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+	}
+
+	(yy_n_chars) += number_to_move;
+	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
+	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
+
+	(yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+
+	return ret_val;
+}
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+    static yy_state_type yy_get_previous_state (void)
+{
+	register yy_state_type yy_current_state;
+	register char *yy_cp;
+    
+	yy_current_state = (yy_start);
+	yy_current_state += YY_AT_BOL();
+
+	for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
+		{
+		if ( *yy_cp )
+			{
+			yy_current_state = yy_nxt[yy_current_state][YY_SC_TO_UI(*yy_cp)];
+			}
+		else
+			yy_current_state = yy_NUL_trans[yy_current_state];
+		if ( yy_accept[yy_current_state] )
+			{
+			(yy_last_accepting_state) = yy_current_state;
+			(yy_last_accepting_cpos) = yy_cp;
+			}
+		}
+
+	return yy_current_state;
+}
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ *	next_state = yy_try_NUL_trans( current_state );
+ */
+    static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state )
+{
+	register int yy_is_jam;
+    	register char *yy_cp = (yy_c_buf_p);
+
+	yy_current_state = yy_NUL_trans[yy_current_state];
+	yy_is_jam = (yy_current_state == 0);
+
+	if ( ! yy_is_jam )
+		{
+		if ( yy_accept[yy_current_state] )
+			{
+			(yy_last_accepting_state) = yy_current_state;
+			(yy_last_accepting_cpos) = yy_cp;
+			}
+		}
+
+	return yy_is_jam ? 0 : yy_current_state;
+}
+
+    static void yyunput (int c, register char * yy_bp )
+{
+	register char *yy_cp;
+    
+    yy_cp = (yy_c_buf_p);
+
+	/* undo effects of setting up wcsbthtext */
+	*yy_cp = (yy_hold_char);
+
+	if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+		{ /* need to shift things up to make room */
+		/* +2 for EOB chars. */
+		register int number_to_move = (yy_n_chars) + 2;
+		register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
+					YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
+		register char *source =
+				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
+
+		while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+			*--dest = *--source;
+
+		yy_cp += (int) (dest - source);
+		yy_bp += (int) (dest - source);
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars =
+			(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size;
+
+		if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+			YY_FATAL_ERROR( "flex scanner push-back overflow" );
+		}
+
+	*--yy_cp = (char) c;
+
+	(yytext_ptr) = yy_bp;
+	(yy_hold_char) = *yy_cp;
+	(yy_c_buf_p) = yy_cp;
+}
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+    static int yyinput (void)
+#else
+    static int input  (void)
+#endif
+
+{
+	int c;
+    
+	*(yy_c_buf_p) = (yy_hold_char);
+
+	if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
+		{
+		/* yy_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 ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+			/* This was really a NUL. */
+			*(yy_c_buf_p) = '\0';
+
+		else
+			{ /* need more input */
+			int offset = (yy_c_buf_p) - (yytext_ptr);
+			++(yy_c_buf_p);
+
+			switch ( yy_get_next_buffer(  ) )
+				{
+				case EOB_ACT_LAST_MATCH:
+					/* This happens because yy_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. */
+					wcsbthrestart(wcsbthin );
+
+					/*FALLTHROUGH*/
+
+				case EOB_ACT_END_OF_FILE:
+					{
+					if ( wcsbthwrap( ) )
+						return EOF;
+
+					if ( ! (yy_did_buffer_switch_on_eof) )
+						YY_NEW_FILE;
+#ifdef __cplusplus
+					return yyinput();
+#else
+					return input();
+#endif
+					}
+
+				case EOB_ACT_CONTINUE_SCAN:
+					(yy_c_buf_p) = (yytext_ptr) + offset;
+					break;
+				}
+			}
+		}
+
+	c = *(unsigned char *) (yy_c_buf_p);	/* cast for 8-bit char's */
+	*(yy_c_buf_p) = '\0';	/* preserve wcsbthtext */
+	(yy_hold_char) = *++(yy_c_buf_p);
+
+	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = (c == '\n');
+
+	return c;
+}
+#endif	/* ifndef YY_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 wcsbthrestart  (FILE * input_file )
+{
+    
+	if ( ! YY_CURRENT_BUFFER ){
+        wcsbthensure_buffer_stack ();
+		YY_CURRENT_BUFFER_LVALUE =
+            wcsbth_create_buffer(wcsbthin,YY_BUF_SIZE );
+	}
+
+	wcsbth_init_buffer(YY_CURRENT_BUFFER,input_file );
+	wcsbth_load_buffer_state( );
+}
+
+/** Switch to a different input buffer.
+ * @param new_buffer The new input buffer.
+ * 
+ */
+    void wcsbth_switch_to_buffer  (YY_BUFFER_STATE  new_buffer )
+{
+    
+	/* TODO. We should be able to replace this entire function body
+	 * with
+	 *		wcsbthpop_buffer_state();
+	 *		wcsbthpush_buffer_state(new_buffer);
+     */
+	wcsbthensure_buffer_stack ();
+	if ( YY_CURRENT_BUFFER == new_buffer )
+		return;
+
+	if ( YY_CURRENT_BUFFER )
+		{
+		/* Flush out information for old buffer. */
+		*(yy_c_buf_p) = (yy_hold_char);
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+		}
+
+	YY_CURRENT_BUFFER_LVALUE = new_buffer;
+	wcsbth_load_buffer_state( );
+
+	/* We don't actually know whether we did this switch during
+	 * EOF (wcsbthwrap()) processing, but the only time this flag
+	 * is looked at is after wcsbthwrap() is called, so it's safe
+	 * to go ahead and always set it.
+	 */
+	(yy_did_buffer_switch_on_eof) = 1;
+}
+
+static void wcsbth_load_buffer_state  (void)
+{
+    	(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+	(yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+	wcsbthin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+	(yy_hold_char) = *(yy_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 YY_BUF_SIZE.
+ * 
+ * @return the allocated buffer state.
+ */
+    YY_BUFFER_STATE wcsbth_create_buffer  (FILE * file, int  size )
+{
+	YY_BUFFER_STATE b;
+    
+	b = (YY_BUFFER_STATE) wcsbthalloc(sizeof( struct yy_buffer_state )  );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in wcsbth_create_buffer()" );
+
+	b->yy_buf_size = size;
+
+	/* yy_ch_buf has to be 2 characters longer than the size given because
+	 * we need to put in 2 end-of-buffer characters.
+	 */
+	b->yy_ch_buf = (char *) wcsbthalloc(b->yy_buf_size + 2  );
+	if ( ! b->yy_ch_buf )
+		YY_FATAL_ERROR( "out of dynamic memory in wcsbth_create_buffer()" );
+
+	b->yy_is_our_buffer = 1;
+
+	wcsbth_init_buffer(b,file );
+
+	return b;
+}
+
+/** Destroy the buffer.
+ * @param b a buffer created with wcsbth_create_buffer()
+ * 
+ */
+    void wcsbth_delete_buffer (YY_BUFFER_STATE  b )
+{
+    
+	if ( ! b )
+		return;
+
+	if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+		YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
+
+	if ( b->yy_is_our_buffer )
+		wcsbthfree((void *) b->yy_ch_buf  );
+
+	wcsbthfree((void *) b  );
+}
+
+/* Initializes or reinitializes a buffer.
+ * This function is sometimes called more than once on the same buffer,
+ * such as during a wcsbthrestart() or at EOF.
+ */
+    static void wcsbth_init_buffer  (YY_BUFFER_STATE  b, FILE * file )
+
+{
+	int oerrno = errno;
+    
+	wcsbth_flush_buffer(b );
+
+	b->yy_input_file = file;
+	b->yy_fill_buffer = 1;
+
+    /* If b is the current buffer, then wcsbth_init_buffer was _probably_
+     * called from wcsbthrestart() or through yy_get_next_buffer.
+     * In that case, we don't want to reset the lineno or column.
+     */
+    if (b != YY_CURRENT_BUFFER){
+        b->yy_bs_lineno = 1;
+        b->yy_bs_column = 0;
+    }
+
+        b->yy_is_interactive = 0;
+    
+	errno = oerrno;
+}
+
+/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
+ * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
+ * 
+ */
+    void wcsbth_flush_buffer (YY_BUFFER_STATE  b )
+{
+    	if ( ! b )
+		return;
+
+	b->yy_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->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+	b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+	b->yy_buf_pos = &b->yy_ch_buf[0];
+
+	b->yy_at_bol = 1;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	if ( b == YY_CURRENT_BUFFER )
+		wcsbth_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 wcsbthpush_buffer_state (YY_BUFFER_STATE new_buffer )
+{
+    	if (new_buffer == NULL)
+		return;
+
+	wcsbthensure_buffer_stack();
+
+	/* This block is copied from wcsbth_switch_to_buffer. */
+	if ( YY_CURRENT_BUFFER )
+		{
+		/* Flush out information for old buffer. */
+		*(yy_c_buf_p) = (yy_hold_char);
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+		}
+
+	/* Only push if top exists. Otherwise, replace top. */
+	if (YY_CURRENT_BUFFER)
+		(yy_buffer_stack_top)++;
+	YY_CURRENT_BUFFER_LVALUE = new_buffer;
+
+	/* copied from wcsbth_switch_to_buffer. */
+	wcsbth_load_buffer_state( );
+	(yy_did_buffer_switch_on_eof) = 1;
+}
+
+/** Removes and deletes the top of the stack, if present.
+ *  The next element becomes the new top.
+ *  
+ */
+void wcsbthpop_buffer_state (void)
+{
+    	if (!YY_CURRENT_BUFFER)
+		return;
+
+	wcsbth_delete_buffer(YY_CURRENT_BUFFER );
+	YY_CURRENT_BUFFER_LVALUE = NULL;
+	if ((yy_buffer_stack_top) > 0)
+		--(yy_buffer_stack_top);
+
+	if (YY_CURRENT_BUFFER) {
+		wcsbth_load_buffer_state( );
+		(yy_did_buffer_switch_on_eof) = 1;
+	}
+}
+
+/* Allocates the stack if it does not exist.
+ *  Guarantees space for at least one push.
+ */
+static void wcsbthensure_buffer_stack (void)
+{
+	int num_to_alloc;
+    
+	if (!(yy_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;
+		(yy_buffer_stack) = (struct yy_buffer_state**)wcsbthalloc
+								(num_to_alloc * sizeof(struct yy_buffer_state*)
+								);
+		if ( ! (yy_buffer_stack) )
+			YY_FATAL_ERROR( "out of dynamic memory in wcsbthensure_buffer_stack()" );
+								  
+		memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+				
+		(yy_buffer_stack_max) = num_to_alloc;
+		(yy_buffer_stack_top) = 0;
+		return;
+	}
+
+	if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
+
+		/* Increase the buffer to prepare for a possible push. */
+		int grow_size = 8 /* arbitrary grow size */;
+
+		num_to_alloc = (yy_buffer_stack_max) + grow_size;
+		(yy_buffer_stack) = (struct yy_buffer_state**)wcsbthrealloc
+								((yy_buffer_stack),
+								num_to_alloc * sizeof(struct yy_buffer_state*)
+								);
+		if ( ! (yy_buffer_stack) )
+			YY_FATAL_ERROR( "out of dynamic memory in wcsbthensure_buffer_stack()" );
+
+		/* zero only the new slots.*/
+		memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
+		(yy_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. 
+ */
+YY_BUFFER_STATE wcsbth_scan_buffer  (char * base, yy_size_t  size )
+{
+	YY_BUFFER_STATE b;
+    
+	if ( size < 2 ||
+	     base[size-2] != YY_END_OF_BUFFER_CHAR ||
+	     base[size-1] != YY_END_OF_BUFFER_CHAR )
+		/* They forgot to leave room for the EOB's. */
+		return 0;
+
+	b = (YY_BUFFER_STATE) wcsbthalloc(sizeof( struct yy_buffer_state )  );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in wcsbth_scan_buffer()" );
+
+	b->yy_buf_size = size - 2;	/* "- 2" to take care of EOB's */
+	b->yy_buf_pos = b->yy_ch_buf = base;
+	b->yy_is_our_buffer = 0;
+	b->yy_input_file = 0;
+	b->yy_n_chars = b->yy_buf_size;
+	b->yy_is_interactive = 0;
+	b->yy_at_bol = 1;
+	b->yy_fill_buffer = 0;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	wcsbth_switch_to_buffer(b  );
+
+	return b;
+}
+
+/** Setup the input buffer state to scan a string. The next call to wcsbthlex() will
+ * scan from a @e copy of @a str.
+ * @param yystr 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
+ *       wcsbth_scan_bytes() instead.
+ */
+YY_BUFFER_STATE wcsbth_scan_string (yyconst char * yystr )
+{
+    
+	return wcsbth_scan_bytes(yystr,strlen(yystr) );
+}
+
+/** Setup the input buffer state to scan the given bytes. The next call to wcsbthlex() will
+ * scan from a @e copy of @a bytes.
+ * @param yybytes the byte buffer to scan
+ * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
+ * 
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE wcsbth_scan_bytes  (yyconst char * yybytes, int  _yybytes_len )
+{
+	YY_BUFFER_STATE b;
+	char *buf;
+	yy_size_t n;
+	int i;
+    
+	/* Get memory for full buffer, including space for trailing EOB's. */
+	n = _yybytes_len + 2;
+	buf = (char *) wcsbthalloc(n  );
+	if ( ! buf )
+		YY_FATAL_ERROR( "out of dynamic memory in wcsbth_scan_bytes()" );
+
+	for ( i = 0; i < _yybytes_len; ++i )
+		buf[i] = yybytes[i];
+
+	buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
+
+	b = wcsbth_scan_buffer(buf,n );
+	if ( ! b )
+		YY_FATAL_ERROR( "bad buffer in wcsbth_scan_bytes()" );
+
+	/* It's okay to grow etc. this buffer, and we should throw it
+	 * away when we're done.
+	 */
+	b->yy_is_our_buffer = 1;
+
+	return b;
+}
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+static void yy_fatal_error (yyconst char* msg )
+{
+    	(void) fprintf( stderr, "%s\n", msg );
+	exit( YY_EXIT_FAILURE );
+}
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up wcsbthtext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+		wcsbthtext[wcsbthleng] = (yy_hold_char); \
+		(yy_c_buf_p) = wcsbthtext + yyless_macro_arg; \
+		(yy_hold_char) = *(yy_c_buf_p); \
+		*(yy_c_buf_p) = '\0'; \
+		wcsbthleng = yyless_macro_arg; \
+		} \
+	while ( 0 )
+
+/* Accessor  methods (get/set functions) to struct members. */
+
+/** Get the current line number.
+ * 
+ */
+int wcsbthget_lineno  (void)
+{
+        
+    return wcsbthlineno;
+}
+
+/** Get the input stream.
+ * 
+ */
+FILE *wcsbthget_in  (void)
+{
+        return wcsbthin;
+}
+
+/** Get the output stream.
+ * 
+ */
+FILE *wcsbthget_out  (void)
+{
+        return wcsbthout;
+}
+
+/** Get the length of the current token.
+ * 
+ */
+int wcsbthget_leng  (void)
+{
+        return wcsbthleng;
+}
+
+/** Get the current token.
+ * 
+ */
+
+char *wcsbthget_text  (void)
+{
+        return wcsbthtext;
+}
+
+/** Set the current line number.
+ * @param line_number
+ * 
+ */
+void wcsbthset_lineno (int  line_number )
+{
+    
+    wcsbthlineno = line_number;
+}
+
+/** Set the input stream. This does not discard the current
+ * input buffer.
+ * @param in_str A readable stream.
+ * 
+ * @see wcsbth_switch_to_buffer
+ */
+void wcsbthset_in (FILE *  in_str )
+{
+        wcsbthin = in_str ;
+}
+
+void wcsbthset_out (FILE *  out_str )
+{
+        wcsbthout = out_str ;
+}
+
+int wcsbthget_debug  (void)
+{
+        return wcsbth_flex_debug;
+}
+
+void wcsbthset_debug (int  bdebug )
+{
+        wcsbth_flex_debug = bdebug ;
+}
+
+static int yy_init_globals (void)
+{
+        /* Initialization is the same as for the non-reentrant scanner.
+     * This function is called from wcsbthlex_destroy(), so don't allocate here.
+     */
+
+    (yy_buffer_stack) = 0;
+    (yy_buffer_stack_top) = 0;
+    (yy_buffer_stack_max) = 0;
+    (yy_c_buf_p) = (char *) 0;
+    (yy_init) = 0;
+    (yy_start) = 0;
+
+/* Defined in main.c */
+#ifdef YY_STDINIT
+    wcsbthin = stdin;
+    wcsbthout = stdout;
+#else
+    wcsbthin = (FILE *) 0;
+    wcsbthout = (FILE *) 0;
+#endif
+
+    /* For future reference: Set errno on error, since we are called by
+     * wcsbthlex_init()
+     */
+    return 0;
+}
+
+/* wcsbthlex_destroy is for both reentrant and non-reentrant scanners. */
+int wcsbthlex_destroy  (void)
+{
+    
+    /* Pop the buffer stack, destroying each element. */
+	while(YY_CURRENT_BUFFER){
+		wcsbth_delete_buffer(YY_CURRENT_BUFFER  );
+		YY_CURRENT_BUFFER_LVALUE = NULL;
+		wcsbthpop_buffer_state();
+	}
+
+	/* Destroy the stack itself. */
+	wcsbthfree((yy_buffer_stack) );
+	(yy_buffer_stack) = NULL;
+
+    /* Reset the globals. This is important in a non-reentrant scanner so the next time
+     * wcsbthlex() is called, initialization will occur. */
+    yy_init_globals( );
+
+    return 0;
+}
+
+/*
+ * Internal utility routines.
+ */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
+{
+	register int i;
+	for ( i = 0; i < n; ++i )
+		s1[i] = s2[i];
+}
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * s )
+{
+	register int n;
+	for ( n = 0; s[n]; ++n )
+		;
+
+	return n;
+}
+#endif
+
+void *wcsbthalloc (yy_size_t  size )
+{
+	return (void *) malloc( size );
+}
+
+void *wcsbthrealloc  (void * ptr, yy_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 wcsbthfree (void * ptr )
+{
+	free( (char *) ptr );	/* see wcsbthrealloc() for (char *) cast */
+}
+
+#define YYTABLES_NAME "yytables"
+
+#line 2076 "wcsbth.l"
+
+
+
+/*----------------------------------------------------------------------------
+* Perform first-pass tasks:
+*
+* 1) Count the number of coordinate axes in each of the 27 possible alternate
+*    image-header coordinate representations.  Also count the number of PVi_ma
+*    and PSi_ma keywords in each representation.
+*
+* 2) Determine the number of binary table columns that have an image array
+*    with a coordinate representation (up to 999), and count the number of
+*    coordinate axes in each of the 27 possible alternates.  Also count the
+*    number of iVn_ma and iSn_ma keywords in each representation.
+*
+* 3) Determine the number of alternate pixel list coordinate representations
+*    (up to 27) and the table columns associated with each.  Also count the
+*    number of TVn_ma and TSn_ma keywords in each representation.
+*
+* In the first pass alts->arridx[icol][27] is used to determine the number of
+* axes in each of 27 possible image-header coordinate descriptions (icol == 0)
+* and each of the 27 possible coordinate representations for an image array in
+* each column.
+*
+* The elements of alts->pixlist[icol] are used as bit arrays to flag which of
+* the 27 possible pixel list coordinate representations are associated with
+* each table column.
+*---------------------------------------------------------------------------*/
+
+int wcsbth_pass1(
+  int keytype,
+  int i,
+  int j,
+  int n,
+  int k,
+  char a,
+  char ptype,
+  struct wcsbth_alts *alts)
+
+{
+  int ialt, icol, mask, ncol;
+
+  if (a == 0) {
+    /* Keywords such as DATE-OBS go along for the ride. */
+    return 0;
+  }
+
+  ncol = alts->ncol;
+
+  /* Do we need to allocate memory for alts? */
+  if (alts->arridx == 0x0) {
+    if (ncol == 0) {
+      /* Can only happen if TFIELDS is missing or out-of-sequence.  If n and
+         k are both zero then we may be processing an image header so leave
+         ncol alone - the array will be realloc'd later if required. */
+      if (n || k) {
+        /* The header is mangled, assume the worst. */
+        ncol = 999;
+      }
+    }
+
+    if (!(alts->arridx  =  calloc((1 + ncol)*27, sizeof(short int))) ||
+        !(alts->npv     =  calloc((1 + ncol)*27, sizeof(unsigned char)))  ||
+        !(alts->nps     =  calloc((1 + ncol)*27, sizeof(unsigned char)))  ||
+        !(alts->pixlist =  calloc((1 + ncol),    sizeof(unsigned int)))) {
+      if (alts->arridx)  free(alts->arridx);
+      if (alts->npv)     free(alts->npv);
+      if (alts->nps)     free(alts->nps);
+      if (alts->pixlist) free(alts->pixlist);
+      return 2;
+    }
+
+    alts->ncol = ncol;
+
+  } else if (n > ncol || k > ncol) {
+    /* Can only happen if TFIELDS or the WCS keyword is wrong; carry on. */
+    ncol = 999;
+    if (!(alts->arridx  = realloc(alts->arridx,
+                                    27*(1 + ncol)*sizeof(short int))) ||
+        !(alts->npv     = realloc(alts->npv,
+                                    27*(1 + ncol)*sizeof(unsigned char)))  ||
+        !(alts->nps     = realloc(alts->nps,
+                                    27*(1 + ncol)*sizeof(unsigned char)))  ||
+        !(alts->pixlist = realloc(alts->pixlist,
+                                       (1 + ncol)*sizeof(unsigned int)))) {
+      if (alts->arridx)  free(alts->arridx);
+      if (alts->npv)     free(alts->npv);
+      if (alts->nps)     free(alts->nps);
+      if (alts->pixlist) free(alts->pixlist);
+      return 2;
+    }
+
+    /* Since realloc() doesn't initialize the extra memory. */
+    for (icol = (1 + alts->ncol); icol < (1 + ncol); icol++) {
+      for (ialt = 0; ialt < 27; ialt++) {
+        alts->arridx[icol][ialt] = 0;
+        alts->npv[icol][ialt] = 0;
+        alts->nps[icol][ialt] = 0;
+        alts->pixlist[icol]   = 0;
+      }
+    }
+
+    alts->ncol = ncol;
+  }
+
+  ialt = 0;
+  if (a != ' ') {
+    ialt = a - 'A' + 1;
+  }
+
+  /* A BINTAB keytype such as LONPna, in conjunction with an IMGAXIS keytype
+     causes a table column to be recognized as an image array. */
+  if (keytype & IMGHEAD || keytype & BIMGARR) {
+    /* n == 0 is expected for IMGHEAD keywords. */
+    if (i == 0 && j == 0) {
+      if (alts->arridx[n][ialt] == 0) {
+        /* Flag that an auxiliary keyword was seen. */
+        alts->arridx[n][ialt] = -1;
+      }
+
+    } else {
+      /* Record the maximum axis number found. */
+      if (alts->arridx[n][ialt] < i) {
+        alts->arridx[n][ialt] = i;
+      }
+
+      if (alts->arridx[n][ialt] < j) {
+        alts->arridx[n][ialt] = j;
+      }
+    }
+
+    if (ptype == 'v') {
+      alts->npv[n][ialt]++;
+    } else if (ptype == 's') {
+      alts->nps[n][ialt]++;
+    }
+  }
+
+  /* BINTAB keytypes, which apply both to pixel lists as well as binary table
+     image arrays, never contribute to recognizing a table column as a pixel
+     list axis.  A PIXLIST keytype is required for that. */
+  if (keytype == PIXLIST) {
+    mask = 1 << ialt;
+
+    /* n > 0 for PIXLIST keytypes. */
+    alts->pixlist[n] |= mask;
+    if (k) alts->pixlist[k] |= mask;
+
+    /* Used as a flag over all columns. */
+    alts->pixlist[0] |= mask;
+
+    if (ptype == 'v') {
+      alts->pixnpv[ialt]++;
+    } else if (ptype == 's') {
+      alts->pixnps[ialt]++;
+    }
+  }
+
+  return 0;
+}
+
+
+/*----------------------------------------------------------------------------
+* Perform initializations at the end of the first pass:
+*
+* 1) Determine the required number of wcsprm structs, allocate memory for
+*    an array of them and initialize each one.
+*---------------------------------------------------------------------------*/
+
+int wcsbth_init1(
+  struct wcsbth_alts *alts,
+  int *nwcs,
+  struct wcsprm **wcs)
+
+{
+  int ialt, icol, inherit[27], ix, mask, ncol, npsmax, npvmax, status = 0;
+  struct wcsprm *wcsp;
+
+
+  if (alts->arridx == 0x0) {
+    *nwcs = 0;
+    return 0;
+  }
+
+  /* Determine the number of axes in each pixel list representation. */
+  ncol = alts->ncol;
+  for (ialt = 0, mask = 1; ialt < 27; ialt++, mask <<= 1) {
+    alts->pixidx[ialt] = 0;
+
+    if (alts->pixlist[0] | mask) {
+      for (icol = 1; icol <= ncol; icol++) {
+        if (alts->pixlist[icol] & mask) {
+          alts->pixidx[ialt]++;
+        }
+      }
+    }
+  }
+
+  /* Find the total number of coordinate representations. */
+  *nwcs = 0;
+  alts->imgherit = 0;
+  for (ialt = 0; ialt < 27; ialt++) {
+    inherit[ialt] = 0;
+
+    for (icol = 1; icol <= ncol; icol++) {
+      if (alts->arridx[icol][ialt] < 0) {
+        /* No BIMGARR keytype but there's at least one BINTAB. */
+        if (alts->arridx[0][ialt] > 0) {
+          /* There is an IMGAXIS keytype that we will inherit, so count this
+             representation. */
+          alts->arridx[icol][ialt] = alts->arridx[0][ialt];
+        } else {
+          alts->arridx[icol][ialt] = 0;
+        }
+      }
+
+      if (alts->arridx[icol][ialt]) {
+        if (alts->arridx[0][ialt]) {
+          /* All IMGHEAD keywords are inherited for this ialt. */
+          inherit[ialt] = 1;
+
+          if (alts->arridx[icol][ialt] < alts->arridx[0][ialt]) {
+            /* The extra axes are also inherited. */
+            alts->arridx[icol][ialt] = alts->arridx[0][ialt];
+          }
+        }
+
+        (*nwcs)++;
+      }
+    }
+
+    /* Count every "a" found in any IMGHEAD keyword... */
+    if (alts->arridx[0][ialt]) {
+      if (inherit[ialt]) {
+        /* ...but not if the IMGHEAD keywords will be inherited. */
+        alts->arridx[0][ialt] = 0;
+        alts->imgherit = 1;
+      } else {
+        (*nwcs)++;
+      }
+    }
+
+    /* We need a struct for every "a" found in a PIXLIST keyword. */
+    if (alts->pixidx[ialt]) {
+      (*nwcs)++;
+    }
+  }
+
+
+  if (*nwcs) {
+    /* Allocate memory for the required number of wcsprm structs. */
+    if (!(*wcs = calloc(*nwcs, sizeof(struct wcsprm)))) {
+      return 2;
+    }
+
+    /* Record the current values of NPVMAX and NPSMAX. */
+    npvmax = wcsnpv(-1);
+    npsmax = wcsnps(-1);
+
+    /* Initialize each wcsprm struct. */
+    wcsp = *wcs;
+    *nwcs = 0;
+    for (icol = 0; icol <= ncol; icol++) {
+      for (ialt = 0; ialt < 27; ialt++) {
+        if (alts->arridx[icol][ialt]) {
+          /* Image-header representations that are not for inheritance
+             (icol == 0) or binary table image array representations. */
+          wcsp->flag = -1;
+          wcsnpv(alts->npv[icol][ialt]);
+          wcsnps(alts->nps[icol][ialt]);
+          if ((status = wcsini(1, (int)(alts->arridx[icol][ialt]), wcsp))) {
+            wcsvfree(nwcs, wcs);
+            break;
+          }
+
+          /* Record the alternate version code. */
+          if (ialt) {
+            wcsp->alt[0] = 'A' + ialt - 1;
+          }
+
+          /* Record the table column number. */
+          wcsp->colnum = icol;
+
+          /* On the second pass alts->arridx[icol][27] indexes the array of
+             wcsprm structs. */
+          alts->arridx[icol][ialt] = (*nwcs)++;
+
+          wcsp++;
+
+        } else {
+          /* Signal that this column has no WCS for this "a". */
+          alts->arridx[icol][ialt] = -1;
+        }
+      }
+    }
+
+    for (ialt = 0; ialt < 27; ialt++) {
+      if (alts->pixidx[ialt]) {
+        /* Pixel lists representations. */
+        wcsp->flag = -1;
+        wcsnpv(alts->pixnpv[ialt]);
+        wcsnps(alts->pixnps[ialt]);
+        if ((status = wcsini(1, (int)(alts->pixidx[ialt]), wcsp))) {
+          wcsvfree(nwcs, wcs);
+          break;
+        }
+
+        /* Record the alternate version code. */
+        if (ialt) {
+          wcsp->alt[0] = 'A' + ialt - 1;
+        }
+
+        /* Record the pixel list column numbers. */
+        mask = (1 << ialt);
+        for (icol = 1, ix = 0; icol <= ncol; icol++) {
+          if (alts->pixlist[icol] & mask) {
+            wcsp->colax[ix++] = icol;
+          }
+        }
+
+        /* alts->pixidx[] indexes the array of wcsprm structs. */
+        alts->pixidx[ialt] = (*nwcs)++;
+
+        wcsp++;
+
+      } else {
+        /* Signal that this column is not a pixel list axis for this "a". */
+        alts->pixidx[ialt] = -1;
+      }
+    }
+
+    /* Restore the original values of NPVMAX and NPSMAX. */
+    wcsnpv(npvmax);
+    wcsnps(npsmax);
+  }
+
+  return status;
+}
+
+
+/*----------------------------------------------------------------------------
+* Return a pointer to the next wcsprm struct for a particular column number
+* and alternate.
+*---------------------------------------------------------------------------*/
+
+struct wcsprm *wcsbth_idx(
+  struct wcsprm *wcs,
+  struct wcsbth_alts *alts,
+  int  keytype,
+  int  n,
+  char a)
+
+{
+  const char as[] = " ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+  int iwcs;
+
+  if (!wcs) return 0x0;
+
+  iwcs = -1;
+  for (; iwcs < 0 && alts->ialt < 27; alts->ialt++) {
+    /* Note that a == 0 applies to every alternate, otherwise this
+       loop simply determines the appropriate value of alts->ialt. */
+    if (a && a != as[alts->ialt]) continue;
+
+    if (keytype & (IMGHEAD | BIMGARR)) {
+      for (; iwcs < 0 && alts->icol <= alts->ncol; alts->icol++) {
+        /* Image header keywords, n == 0, apply to all columns, otherwise this
+           loop simply determines the appropriate value of alts->icol. */
+        if (n && n != alts->icol) continue;
+        iwcs = alts->arridx[alts->icol][alts->ialt];
+      }
+
+      /* Break out of the loop to stop alts->ialt from being incremented. */
+      if (iwcs >= 0) break;
+
+      /* Start from scratch for the next alts->ialt. */
+      alts->icol = 0;
+    }
+
+    if (keytype & (IMGAUX | PIXLIST)) {
+      iwcs = alts->pixidx[alts->ialt];
+    }
+  }
+
+  return (iwcs >= 0) ? (wcs + iwcs) : 0x0;
+}
+
+
+/*----------------------------------------------------------------------------
+* Return the axis number associated with the specified column number in a
+* particular pixel list coordinate representation.
+*---------------------------------------------------------------------------*/
+
+int wcsbth_colax(
+  struct wcsprm *wcs,
+  struct wcsbth_alts *alts,
+  int n,
+  char a)
+
+{
+  int ix;
+  struct wcsprm *wcsp;
+
+  if (!wcs) return 0;
+
+  wcsp = wcs;
+  if (a != ' ') {
+    wcsp += alts->pixidx[a-'A'+1];
+  }
+
+  for (ix = 0; ix < wcsp->naxis; ix++) {
+    if (wcsp->colax[ix] == n) {
+      return ++ix;
+    }
+  }
+
+  return 0;
+}
+
+
+/*----------------------------------------------------------------------------
+* Interpret EPOCH keywords.
+*---------------------------------------------------------------------------*/
+
+int wcsbth_epoch(void *wptr)
+
+{
+  double *equinox;
+
+  /* If EQUINOXa is currently undefined then set it from EPOCHa. */
+  equinox = (double *)wptr;
+  if (undefined(*equinox)) {
+    wcsutil_str2double(wcsbthtext, "%lf", equinox);
+  }
+
+  return 0;
+}
+
+
+/*----------------------------------------------------------------------------
+* Interpret VSOURCE keywords.
+*---------------------------------------------------------------------------*/
+
+int wcsbth_vsource(void *wptr)
+
+{
+  double beta, c = 299792458.0, vsource, *zsource;
+
+  /* If ZSOURCEa is currently undefined then set it from VSOURCEa. */
+  zsource = (double *)wptr;
+  if (undefined(*zsource)) {
+    wcsutil_str2double(wcsbthtext, "%lf", &vsource);
+
+    /* Convert relativistic Doppler velocity to redshift. */
+    beta = vsource/c;
+    *zsource = (1.0 + beta)/sqrt(1.0 - beta*beta) - 1.0;
+  }
+
+  return 0;
+}
+
+
+/*----------------------------------------------------------------------------
+* Tie up loose ends.
+*---------------------------------------------------------------------------*/
+
+int wcsbth_final(
+  struct wcsbth_alts *alts,
+  int *nwcs,
+  struct wcsprm **wcs)
+
+{
+  int ialt, status;
+
+  if (alts->arridx)  free(alts->arridx);
+  if (alts->npv)     free(alts->npv);
+  if (alts->nps)     free(alts->nps);
+  if (alts->pixlist) free(alts->pixlist);
+
+  for (ialt = 0; ialt < *nwcs; ialt++) {
+    /* Interpret -TAB header keywords. */
+    if ((status = wcstab(*wcs+ialt))) {
+       wcsvfree(nwcs, wcs);
+       return status;
+    }
+  }
+
+  return 0;
+}
+
diff --git a/cextern/wcslib/C/flexed/wcspih.c b/cextern/wcslib/C/flexed/wcspih.c
new file mode 100644
index 0000000..8244346
--- /dev/null
+++ b/cextern/wcslib/C/flexed/wcspih.c
@@ -0,0 +1,10831 @@
+#line 2 "wcspih.c"
+
+#line 4 "wcspih.c"
+
+#define  YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define yy_create_buffer wcspih_create_buffer
+#define yy_delete_buffer wcspih_delete_buffer
+#define yy_flex_debug wcspih_flex_debug
+#define yy_init_buffer wcspih_init_buffer
+#define yy_flush_buffer wcspih_flush_buffer
+#define yy_load_buffer_state wcspih_load_buffer_state
+#define yy_switch_to_buffer wcspih_switch_to_buffer
+#define yyin wcspihin
+#define yyleng wcspihleng
+#define yylex wcspihlex
+#define yylineno wcspihlineno
+#define yyout wcspihout
+#define yyrestart wcspihrestart
+#define yytext wcspihtext
+#define yywrap wcspihwrap
+#define yyalloc wcspihalloc
+#define yyrealloc wcspihrealloc
+#define yyfree wcspihfree
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+#define YY_FLEX_SUBMINOR_VERSION 35
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+/* First, we deal with  platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. 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 <inttypes.h>
+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;
+
+/* 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 /* ! C99 */
+
+#endif /* ! FLEXINT_H */
+
+#ifdef __cplusplus
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else	/* ! __cplusplus */
+
+/* C99 requires __STDC__ to be defined as 1. */
+#if defined (__STDC__)
+
+#define YY_USE_CONST
+
+#endif	/* defined (__STDC__) */
+#endif	/* ! __cplusplus */
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_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 YY_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 (yy_start) = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state.  The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START (((yy_start) - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE wcspihrestart(wcspihin  )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k.
+ * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
+ * Ditto for the __ia64__ case accordingly.
+ */
+#define YY_BUF_SIZE 32768
+#else
+#define YY_BUF_SIZE 16384
+#endif /* __ia64__ */
+#endif
+
+/* The state buf must be large enough to hold one state per character in the main buffer.
+ */
+#define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+extern int wcspihleng;
+
+extern FILE *wcspihin, *wcspihout;
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+#define YY_LESS_LINENO(n)
+    
+/* Return all but the first "n" matched characters back to the input stream. */
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up wcspihtext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+		*yy_cp = (yy_hold_char); \
+		YY_RESTORE_YY_MORE_OFFSET \
+		(yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+		YY_DO_BEFORE_ACTION; /* set up wcspihtext again */ \
+		} \
+	while ( 0 )
+
+#define unput(c) yyunput( c, (yytext_ptr)  )
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef size_t yy_size_t;
+#endif
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+	{
+	FILE *yy_input_file;
+
+	char *yy_ch_buf;		/* input buffer */
+	char *yy_buf_pos;		/* current position in input buffer */
+
+	/* Size of input buffer in bytes, not including room for EOB
+	 * characters.
+	 */
+	yy_size_t yy_buf_size;
+
+	/* Number of characters read into yy_ch_buf, not including EOB
+	 * characters.
+	 */
+	int yy_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 yy_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 yy_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 yy_at_bol;
+
+    int yy_bs_lineno; /**< The line count. */
+    int yy_bs_column; /**< The column count. */
+    
+	/* Whether to try to fill the input buffer when we reach the
+	 * end of it.
+	 */
+	int yy_fill_buffer;
+
+	int yy_buffer_status;
+
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+	/* When an EOF's been seen but there's still some text to process
+	 * then we mark the buffer as YY_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 wcspihrestart()), so that the user can continue scanning by
+	 * just pointing wcspihin at a new input file.
+	 */
+#define YY_BUFFER_EOF_PENDING 2
+
+	};
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+/* Stack of input buffers. */
+static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
+static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
+static YY_BUFFER_STATE * yy_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 YY_CURRENT_BUFFER ( (yy_buffer_stack) \
+                          ? (yy_buffer_stack)[(yy_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 YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
+
+/* yy_hold_char holds the character lost when wcspihtext is formed. */
+static char yy_hold_char;
+static int yy_n_chars;		/* number of characters read into yy_ch_buf */
+int wcspihleng;
+
+/* Points to current character in buffer. */
+static char *yy_c_buf_p = (char *) 0;
+static int yy_init = 0;		/* whether we need to initialize */
+static int yy_start = 0;	/* start state number */
+
+/* Flag which is used to allow wcspihwrap()'s to do buffer switches
+ * instead of setting up a fresh wcspihin.  A bit of a hack ...
+ */
+static int yy_did_buffer_switch_on_eof;
+
+void wcspihrestart (FILE *input_file  );
+void wcspih_switch_to_buffer (YY_BUFFER_STATE new_buffer  );
+YY_BUFFER_STATE wcspih_create_buffer (FILE *file,int size  );
+void wcspih_delete_buffer (YY_BUFFER_STATE b  );
+void wcspih_flush_buffer (YY_BUFFER_STATE b  );
+void wcspihpush_buffer_state (YY_BUFFER_STATE new_buffer  );
+void wcspihpop_buffer_state (void );
+
+static void wcspihensure_buffer_stack (void );
+static void wcspih_load_buffer_state (void );
+static void wcspih_init_buffer (YY_BUFFER_STATE b,FILE *file  );
+
+#define YY_FLUSH_BUFFER wcspih_flush_buffer(YY_CURRENT_BUFFER )
+
+YY_BUFFER_STATE wcspih_scan_buffer (char *base,yy_size_t size  );
+YY_BUFFER_STATE wcspih_scan_string (yyconst char *yy_str  );
+YY_BUFFER_STATE wcspih_scan_bytes (yyconst char *bytes,int len  );
+
+void *wcspihalloc (yy_size_t  );
+void *wcspihrealloc (void *,yy_size_t  );
+void wcspihfree (void *  );
+
+#define yy_new_buffer wcspih_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+	{ \
+	if ( ! YY_CURRENT_BUFFER ){ \
+        wcspihensure_buffer_stack (); \
+		YY_CURRENT_BUFFER_LVALUE =    \
+            wcspih_create_buffer(wcspihin,YY_BUF_SIZE ); \
+	} \
+	YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+	}
+
+#define yy_set_bol(at_bol) \
+	{ \
+	if ( ! YY_CURRENT_BUFFER ){\
+        wcspihensure_buffer_stack (); \
+		YY_CURRENT_BUFFER_LVALUE =    \
+            wcspih_create_buffer(wcspihin,YY_BUF_SIZE ); \
+	} \
+	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+	}
+
+#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+
+/* Begin user sect3 */
+
+#define wcspihwrap(n) 1
+#define YY_SKIP_YYWRAP
+
+typedef char YY_CHAR;
+
+FILE *wcspihin = (FILE *) 0, *wcspihout = (FILE *) 0;
+
+typedef int yy_state_type;
+
+extern int wcspihlineno;
+
+int wcspihlineno = 1;
+
+extern char *wcspihtext;
+#define yytext_ptr wcspihtext
+static yyconst flex_int16_t yy_nxt[][128] =
+    {
+    {
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0
+    },
+
+    {
+       33,   34,   34,   34,   34,   34,   34,   34,   34,   34,
+       34,   34,   34,   34,   34,   34,   34,   34,   34,   34,
+       34,   34,   34,   34,   34,   34,   34,   34,   34,   34,
+       34,   34,   34,   34,   34,   34,   34,   34,   34,   34,
+       34,   34,   34,   34,   34,   34,   34,   34,   34,   34,
+       34,   34,   34,   34,   34,   34,   34,   34,   34,   34,
+       34,   34,   34,   34,   34,   34,   34,   34,   34,   34,
+
+       34,   34,   34,   34,   34,   34,   34,   34,   34,   34,
+       34,   34,   34,   34,   34,   34,   34,   34,   34,   34,
+       34,   34,   34,   34,   34,   34,   34,   34,   34,   34,
+       34,   34,   34,   34,   34,   34,   34,   34,   34,   34,
+       34,   34,   34,   34,   34,   34,   34,   34,   34,   34,
+       34,   34,   34,   34,   34,   34,   34,   34
+    },
+
+    {
+       33,   35,   35,   35,   35,   35,   35,   35,   35,   35,
+       34,   35,   35,   35,   35,   35,   35,   35,   35,   35,
+       35,   35,   35,   35,   35,   35,   35,   35,   35,   35,
+       35,   35,   35,   35,   35,   35,   35,   35,   35,   35,
+
+       35,   35,   35,   35,   35,   35,   35,   35,   35,   35,
+       35,   35,   35,   35,   35,   35,   35,   35,   35,   35,
+       35,   35,   35,   35,   35,   35,   35,   36,   37,   38,
+       35,   35,   35,   35,   35,   35,   39,   40,   41,   42,
+       43,   35,   44,   45,   35,   35,   46,   47,   35,   35,
+       48,   35,   35,   35,   35,   35,   35,   35,   35,   35,
+       35,   35,   35,   35,   35,   35,   35,   35,   35,   35,
+       35,   35,   35,   35,   35,   35,   35,   35,   35,   35,
+       35,   35,   35,   35,   35,   35,   35,   35
+    },
+
+    {
+       33,   49,   49,   49,   49,   49,   49,   49,   49,   49,
+
+       34,   49,   49,   49,   49,   49,   49,   49,   49,   49,
+       49,   49,   49,   49,   49,   49,   49,   49,   49,   49,
+       49,   49,   49,   49,   49,   49,   49,   49,   49,   49,
+       49,   49,   49,   49,   49,   49,   49,   49,   49,   50,
+       50,   50,   50,   50,   50,   50,   50,   50,   49,   49,
+       49,   49,   49,   49,   49,   49,   49,   49,   49,   49,
+       49,   49,   49,   49,   49,   49,   49,   49,   49,   49,
+       49,   49,   49,   49,   49,   49,   49,   49,   49,   49,
+       49,   49,   49,   49,   49,   49,   49,   49,   49,   49,
+       49,   49,   49,   49,   49,   49,   49,   49,   49,   49,
+
+       49,   49,   49,   49,   49,   49,   49,   49,   49,   49,
+       49,   49,   49,   49,   49,   49,   49,   49
+    },
+
+    {
+       33,   49,   49,   49,   49,   49,   49,   49,   49,   49,
+       34,   49,   49,   49,   49,   49,   49,   49,   49,   49,
+       49,   49,   49,   49,   49,   49,   49,   49,   49,   49,
+       49,   49,   49,   49,   49,   49,   49,   49,   49,   49,
+       49,   49,   49,   49,   49,   49,   49,   49,   49,   50,
+       50,   50,   50,   50,   50,   50,   50,   50,   49,   49,
+       49,   49,   49,   49,   49,   49,   49,   49,   49,   49,
+       49,   49,   49,   49,   49,   49,   49,   49,   49,   49,
+
+       49,   49,   49,   49,   49,   49,   49,   49,   49,   49,
+       49,   49,   49,   49,   49,   49,   49,   49,   49,   49,
+       49,   49,   49,   49,   49,   49,   49,   49,   49,   49,
+       49,   49,   49,   49,   49,   49,   49,   49,   49,   49,
+       49,   49,   49,   49,   49,   49,   49,   49
+    },
+
+    {
+       33,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+       34,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+       51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+       51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+       51,   51,   51,   51,   51,   51,   51,   51,   52,   52,
+
+       52,   52,   52,   52,   52,   52,   52,   52,   51,   51,
+       51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+       51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+       51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+       51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+       51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+       51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+       51,   51,   51,   51,   51,   51,   51,   51
+    },
+
+    {
+       33,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+       34,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+
+       51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+       51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+       51,   51,   51,   51,   51,   51,   51,   51,   52,   52,
+       52,   52,   52,   52,   52,   52,   52,   52,   51,   51,
+       51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+       51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+       51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+       51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+       51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+       51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+
+       51,   51,   51,   51,   51,   51,   51,   51
+    },
+
+    {
+       33,   53,   53,   53,   53,   53,   53,   53,   53,   53,
+       34,   53,   53,   53,   53,   53,   53,   53,   53,   53,
+       53,   53,   53,   53,   53,   53,   53,   53,   53,   53,
+       53,   53,   53,   53,   53,   53,   53,   53,   53,   53,
+       53,   53,   53,   53,   53,   53,   53,   53,   53,   54,
+       54,   54,   54,   54,   54,   54,   54,   54,   53,   53,
+       53,   53,   53,   53,   53,   53,   53,   53,   53,   53,
+       53,   53,   53,   53,   53,   53,   53,   53,   53,   53,
+       53,   53,   53,   53,   53,   53,   53,   53,   53,   53,
+
+       53,   53,   53,   53,   53,   53,   53,   53,   53,   53,
+       53,   53,   53,   53,   53,   53,   53,   53,   53,   53,
+       53,   53,   53,   53,   53,   53,   53,   53,   53,   53,
+       53,   53,   53,   53,   53,   53,   53,   53
+    },
+
+    {
+       33,   53,   53,   53,   53,   53,   53,   53,   53,   53,
+       34,   53,   53,   53,   53,   53,   53,   53,   53,   53,
+       53,   53,   53,   53,   53,   53,   53,   53,   53,   53,
+       53,   53,   53,   53,   53,   53,   53,   53,   53,   53,
+       53,   53,   53,   53,   53,   53,   53,   53,   53,   54,
+       54,   54,   54,   54,   54,   54,   54,   54,   53,   53,
+
+       53,   53,   53,   53,   53,   53,   53,   53,   53,   53,
+       53,   53,   53,   53,   53,   53,   53,   53,   53,   53,
+       53,   53,   53,   53,   53,   53,   53,   53,   53,   53,
+       53,   53,   53,   53,   53,   53,   53,   53,   53,   53,
+       53,   53,   53,   53,   53,   53,   53,   53,   53,   53,
+       53,   53,   53,   53,   53,   53,   53,   53,   53,   53,
+       53,   53,   53,   53,   53,   53,   53,   53
+    },
+
+    {
+       33,   55,   55,   55,   55,   55,   55,   55,   55,   55,
+       34,   55,   55,   55,   55,   55,   55,   55,   55,   55,
+       55,   55,   55,   55,   55,   55,   55,   55,   55,   55,
+
+       55,   55,   55,   55,   55,   55,   55,   55,   55,   55,
+       55,   55,   55,   55,   55,   55,   55,   55,   56,   57,
+       57,   57,   57,   57,   57,   57,   57,   57,   55,   55,
+       55,   55,   55,   55,   55,   55,   55,   55,   55,   55,
+       55,   55,   55,   55,   55,   55,   55,   55,   55,   55,
+       55,   55,   55,   55,   55,   55,   55,   55,   55,   55,
+       55,   55,   55,   55,   55,   55,   55,   55,   55,   55,
+       55,   55,   55,   55,   55,   55,   55,   55,   55,   55,
+       55,   55,   55,   55,   55,   55,   55,   55,   55,   55,
+       55,   55,   55,   55,   55,   55,   55,   55
+
+    },
+
+    {
+       33,   55,   55,   55,   55,   55,   55,   55,   55,   55,
+       34,   55,   55,   55,   55,   55,   55,   55,   55,   55,
+       55,   55,   55,   55,   55,   55,   55,   55,   55,   55,
+       55,   55,   55,   55,   55,   55,   55,   55,   55,   55,
+       55,   55,   55,   55,   55,   55,   55,   55,   56,   57,
+       57,   57,   57,   57,   57,   57,   57,   57,   55,   55,
+       55,   55,   55,   55,   55,   55,   55,   55,   55,   55,
+       55,   55,   55,   55,   55,   55,   55,   55,   55,   55,
+       55,   55,   55,   55,   55,   55,   55,   55,   55,   55,
+       55,   55,   55,   55,   55,   55,   55,   55,   55,   55,
+
+       55,   55,   55,   55,   55,   55,   55,   55,   55,   55,
+       55,   55,   55,   55,   55,   55,   55,   55,   55,   55,
+       55,   55,   55,   55,   55,   55,   55,   55
+    },
+
+    {
+       33,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       34,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   59,
+       59,   59,   59,   59,   59,   59,   59,   59,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58
+    },
+
+    {
+       33,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       34,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   59,
+       59,   59,   59,   59,   59,   59,   59,   59,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58
+    },
+
+    {
+       33,   60,   60,   60,   60,   60,   60,   60,   60,   60,
+
+       34,   60,   60,   60,   60,   60,   60,   60,   60,   60,
+       60,   60,   60,   60,   60,   60,   60,   60,   60,   60,
+       60,   60,   61,   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,   61,   61,   61,   61,   61,
+       61,   61,   61,   61,   61,   61,   61,   61,   61,   61,
+       61,   61,   61,   61,   61,   61,   61,   61,   61,   61,
+       61,   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
+    },
+
+    {
+       33,   60,   60,   60,   60,   60,   60,   60,   60,   60,
+       34,   60,   60,   60,   60,   60,   60,   60,   60,   60,
+       60,   60,   60,   60,   60,   60,   60,   60,   60,   60,
+       60,   60,   61,   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,   61,   61,   61,   61,   61,
+       61,   61,   61,   61,   61,   61,   61,   61,   61,   61,
+
+       61,   61,   61,   61,   61,   61,   61,   61,   61,   61,
+       61,   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
+    },
+
+    {
+       33,   62,   62,   62,   62,   62,   62,   62,   62,   62,
+       34,   62,   62,   62,   62,   62,   62,   62,   62,   62,
+       62,   62,   62,   62,   62,   62,   62,   62,   62,   62,
+       62,   62,   62,   62,   62,   62,   62,   62,   62,   62,
+       62,   62,   62,   62,   62,   62,   62,   62,   62,   62,
+
+       62,   62,   62,   62,   62,   62,   62,   62,   62,   62,
+       62,   62,   62,   62,   62,   62,   62,   62,   62,   62,
+       62,   62,   62,   62,   62,   62,   62,   62,   62,   62,
+       62,   62,   62,   62,   62,   62,   62,   62,   62,   62,
+       62,   62,   62,   62,   62,   62,   62,   62,   62,   62,
+       62,   62,   62,   62,   62,   62,   62,   62,   62,   62,
+       62,   62,   62,   62,   62,   62,   62,   62,   62,   62,
+       62,   62,   62,   62,   62,   62,   62,   62
+    },
+
+    {
+       33,   62,   62,   62,   62,   62,   62,   62,   62,   62,
+       34,   62,   62,   62,   62,   62,   62,   62,   62,   62,
+
+       62,   62,   62,   62,   62,   62,   62,   62,   62,   62,
+       62,   62,   62,   62,   62,   62,   62,   62,   62,   62,
+       62,   62,   62,   62,   62,   62,   62,   62,   62,   62,
+       62,   62,   62,   62,   62,   62,   62,   62,   62,   62,
+       62,   62,   62,   62,   62,   62,   62,   62,   62,   62,
+       62,   62,   62,   62,   62,   62,   62,   62,   62,   62,
+       62,   62,   62,   62,   62,   62,   62,   62,   62,   62,
+       62,   62,   62,   62,   62,   62,   62,   62,   62,   62,
+       62,   62,   62,   62,   62,   62,   62,   62,   62,   62,
+       62,   62,   62,   62,   62,   62,   62,   62,   62,   62,
+
+       62,   62,   62,   62,   62,   62,   62,   62
+    },
+
+    {
+       33,   63,   63,   63,   63,   63,   63,   63,   63,   63,
+       34,   63,   63,   63,   63,   63,   63,   63,   63,   63,
+       63,   63,   63,   63,   63,   63,   63,   63,   63,   63,
+       63,   63,   63,   63,   63,   63,   63,   63,   63,   63,
+       63,   63,   63,   63,   63,   63,   63,   63,   63,   63,
+       63,   63,   63,   63,   63,   63,   63,   63,   63,   63,
+       63,   64,   63,   63,   63,   63,   63,   63,   63,   63,
+       63,   63,   63,   63,   63,   63,   63,   63,   63,   63,
+       63,   63,   63,   63,   63,   63,   63,   63,   63,   63,
+
+       63,   63,   63,   63,   63,   63,   63,   63,   63,   63,
+       63,   63,   63,   63,   63,   63,   63,   63,   63,   63,
+       63,   63,   63,   63,   63,   63,   63,   63,   63,   63,
+       63,   63,   63,   63,   63,   63,   63,   63
+    },
+
+    {
+       33,   63,   63,   63,   63,   63,   63,   63,   63,   63,
+       34,   63,   63,   63,   63,   63,   63,   63,   63,   63,
+       63,   63,   63,   63,   63,   63,   63,   63,   63,   63,
+       63,   63,   63,   63,   63,   63,   63,   63,   63,   63,
+       63,   63,   63,   63,   63,   63,   63,   63,   63,   63,
+       63,   63,   63,   63,   63,   63,   63,   63,   63,   63,
+
+       63,   64,   63,   63,   63,   63,   63,   63,   63,   63,
+       63,   63,   63,   63,   63,   63,   63,   63,   63,   63,
+       63,   63,   63,   63,   63,   63,   63,   63,   63,   63,
+       63,   63,   63,   63,   63,   63,   63,   63,   63,   63,
+       63,   63,   63,   63,   63,   63,   63,   63,   63,   63,
+       63,   63,   63,   63,   63,   63,   63,   63,   63,   63,
+       63,   63,   63,   63,   63,   63,   63,   63
+    },
+
+    {
+       33,   65,   65,   65,   65,   65,   65,   65,   65,   65,
+       34,   65,   65,   65,   65,   65,   65,   65,   65,   65,
+       65,   65,   65,   65,   65,   65,   65,   65,   65,   65,
+
+       65,   65,   65,   65,   65,   65,   65,   65,   65,   65,
+       65,   65,   65,   66,   65,   66,   65,   65,   67,   67,
+       67,   67,   67,   67,   67,   67,   67,   67,   65,   65,
+       65,   65,   65,   65,   65,   65,   65,   65,   65,   65,
+       65,   65,   65,   65,   65,   65,   65,   65,   65,   65,
+       65,   65,   65,   65,   65,   65,   65,   65,   65,   65,
+       65,   65,   65,   65,   65,   65,   65,   65,   65,   65,
+       65,   65,   65,   65,   65,   65,   65,   65,   65,   65,
+       65,   65,   65,   65,   65,   65,   65,   65,   65,   65,
+       65,   65,   65,   65,   65,   65,   65,   65
+
+    },
+
+    {
+       33,   65,   65,   65,   65,   65,   65,   65,   65,   65,
+       34,   65,   65,   65,   65,   65,   65,   65,   65,   65,
+       65,   65,   65,   65,   65,   65,   65,   65,   65,   65,
+       65,   65,   65,   65,   65,   65,   65,   65,   65,   65,
+       65,   65,   65,   66,   65,   66,   65,   65,   67,   67,
+       67,   67,   67,   67,   67,   67,   67,   67,   65,   65,
+       65,   65,   65,   65,   65,   65,   65,   65,   65,   65,
+       65,   65,   65,   65,   65,   65,   65,   65,   65,   65,
+       65,   65,   65,   65,   65,   65,   65,   65,   65,   65,
+       65,   65,   65,   65,   65,   65,   65,   65,   65,   65,
+
+       65,   65,   65,   65,   65,   65,   65,   65,   65,   65,
+       65,   65,   65,   65,   65,   65,   65,   65,   65,   65,
+       65,   65,   65,   65,   65,   65,   65,   65
+    },
+
+    {
+       33,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       34,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   69,   68,   69,   70,   68,   71,   71,
+       71,   71,   71,   71,   71,   71,   71,   71,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68
+    },
+
+    {
+       33,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       34,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+
+       68,   68,   68,   69,   68,   69,   70,   68,   71,   71,
+       71,   71,   71,   71,   71,   71,   71,   71,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68
+    },
+
+    {
+       33,   72,   72,   72,   72,   72,   72,   72,   72,   72,
+
+       34,   72,   72,   72,   72,   72,   72,   72,   72,   72,
+       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
+       72,   72,   72,   72,   72,   72,   72,   72,   72,   73,
+       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
+       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
+       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
+       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
+       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
+       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
+       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
+
+       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
+       72,   72,   72,   72,   72,   72,   72,   72
+    },
+
+    {
+       33,   72,   72,   72,   72,   72,   72,   72,   72,   72,
+       34,   72,   72,   72,   72,   72,   72,   72,   72,   72,
+       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
+       72,   72,   72,   72,   72,   72,   72,   72,   72,   73,
+       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
+       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
+       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
+       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
+
+       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
+       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
+       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
+       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
+       72,   72,   72,   72,   72,   72,   72,   72
+    },
+
+    {
+       33,   74,   74,   74,   74,   74,   74,   74,   74,   74,
+       34,   74,   74,   74,   74,   74,   74,   74,   74,   74,
+       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
+       74,   74,   75,   74,   74,   74,   74,   74,   74,   74,
+       74,   74,   74,   74,   74,   74,   74,   76,   74,   74,
+
+       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
+       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
+       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
+       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
+       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
+       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
+       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
+       74,   74,   74,   74,   74,   74,   74,   74
+    },
+
+    {
+       33,   74,   74,   74,   74,   74,   74,   74,   74,   74,
+       34,   74,   74,   74,   74,   74,   74,   74,   74,   74,
+
+       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
+       74,   74,   75,   74,   74,   74,   74,   74,   74,   74,
+       74,   74,   74,   74,   74,   74,   74,   76,   74,   74,
+       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
+       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
+       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
+       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
+       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
+       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
+       74,   74,   74,   74,   74,   74,   74,   74,   74,   74,
+
+       74,   74,   74,   74,   74,   74,   74,   74
+    },
+
+    {
+       33,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       34,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77
+    },
+
+    {
+       33,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       34,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77
+    },
+
+    {
+       33,   78,   78,   78,   78,   78,   78,   78,   78,   78,
+       34,   78,   78,   78,   78,   78,   78,   78,   78,   78,
+       78,   78,   78,   78,   78,   78,   78,   78,   78,   78,
+
+       78,   78,   78,   78,   78,   78,   78,   78,   78,   78,
+       78,   78,   78,   78,   78,   78,   78,   78,   78,   78,
+       78,   78,   78,   78,   78,   78,   78,   78,   78,   78,
+       78,   78,   78,   78,   78,   78,   78,   78,   78,   78,
+       78,   78,   78,   78,   78,   78,   78,   78,   78,   78,
+       78,   78,   78,   78,   78,   78,   78,   78,   78,   78,
+       78,   78,   78,   78,   78,   78,   78,   78,   78,   78,
+       78,   78,   78,   78,   78,   78,   78,   78,   78,   78,
+       78,   78,   78,   78,   78,   78,   78,   78,   78,   78,
+       78,   78,   78,   78,   78,   78,   78,   78
+
+    },
+
+    {
+       33,   78,   78,   78,   78,   78,   78,   78,   78,   78,
+       34,   78,   78,   78,   78,   78,   78,   78,   78,   78,
+       78,   78,   78,   78,   78,   78,   78,   78,   78,   78,
+       78,   78,   78,   78,   78,   78,   78,   78,   78,   78,
+       78,   78,   78,   78,   78,   78,   78,   78,   78,   78,
+       78,   78,   78,   78,   78,   78,   78,   78,   78,   78,
+       78,   78,   78,   78,   78,   78,   78,   78,   78,   78,
+       78,   78,   78,   78,   78,   78,   78,   78,   78,   78,
+       78,   78,   78,   78,   78,   78,   78,   78,   78,   78,
+       78,   78,   78,   78,   78,   78,   78,   78,   78,   78,
+
+       78,   78,   78,   78,   78,   78,   78,   78,   78,   78,
+       78,   78,   78,   78,   78,   78,   78,   78,   78,   78,
+       78,   78,   78,   78,   78,   78,   78,   78
+    },
+
+    {
+       33,   79,   79,   79,   79,   79,   79,   79,   79,   79,
+       80,   79,   79,   79,   79,   79,   79,   79,   79,   79,
+       79,   79,   79,   79,   79,   79,   79,   79,   79,   79,
+       79,   79,   79,   79,   79,   79,   79,   79,   79,   79,
+       79,   79,   79,   79,   79,   79,   79,   79,   79,   79,
+       79,   79,   79,   79,   79,   79,   79,   79,   79,   79,
+       79,   79,   79,   79,   79,   79,   79,   79,   79,   79,
+
+       79,   79,   79,   79,   79,   79,   79,   79,   79,   79,
+       79,   79,   79,   79,   79,   79,   79,   79,   79,   79,
+       79,   79,   79,   79,   79,   79,   79,   79,   79,   79,
+       79,   79,   79,   79,   79,   79,   79,   79,   79,   79,
+       79,   79,   79,   79,   79,   79,   79,   79,   79,   79,
+       79,   79,   79,   79,   79,   79,   79,   79
+    },
+
+    {
+       33,   79,   79,   79,   79,   79,   79,   79,   79,   79,
+       80,   79,   79,   79,   79,   79,   79,   79,   79,   79,
+       79,   79,   79,   79,   79,   79,   79,   79,   79,   79,
+       79,   79,   79,   79,   79,   79,   79,   79,   79,   79,
+
+       79,   79,   79,   79,   79,   79,   79,   79,   79,   79,
+       79,   79,   79,   79,   79,   79,   79,   79,   79,   79,
+       79,   79,   79,   79,   79,   79,   79,   79,   79,   79,
+       79,   79,   79,   79,   79,   79,   79,   79,   79,   79,
+       79,   79,   79,   79,   79,   79,   79,   79,   79,   79,
+       79,   79,   79,   79,   79,   79,   79,   79,   79,   79,
+       79,   79,   79,   79,   79,   79,   79,   79,   79,   79,
+       79,   79,   79,   79,   79,   79,   79,   79,   79,   79,
+       79,   79,   79,   79,   79,   79,   79,   79
+    },
+
+    {
+      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
+
+      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
+      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
+      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
+      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
+      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
+      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
+      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
+      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
+      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
+      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
+
+      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
+      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33
+    },
+
+    {
+       33,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
+      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
+      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
+      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
+      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
+      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
+      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
+      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
+
+      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
+      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
+      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
+      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
+      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34
+    },
+
+    {
+       33,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
+      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
+      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
+      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
+      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
+
+      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
+      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
+      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
+      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
+      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
+      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
+      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
+      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35
+    },
+
+    {
+       33,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
+      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
+
+      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
+      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
+      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
+      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
+      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,   81,  -36,
+      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,   82,  -36,
+      -36,  -36,   83,   84,   85,   86,  -36,  -36,  -36,  -36,
+      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
+      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
+      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
+
+      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36
+    },
+
+    {
+       33,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,   87,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37
+    },
+
+    {
+       33,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
+      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
+      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
+      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
+      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
+      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
+
+      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
+      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,   88,  -38,
+       89,   90,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
+      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
+      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
+      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
+      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38
+    },
+
+    {
+       33,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
+      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
+      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
+
+      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
+      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
+      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
+      -39,  -39,  -39,  -39,  -39,   91,  -39,  -39,  -39,  -39,
+      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,   92,
+      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
+      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
+      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
+      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
+      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39
+
+    },
+
+    {
+       33,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
+      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
+      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
+      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
+      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
+      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
+      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
+      -40,  -40,  -40,  -40,   93,  -40,  -40,  -40,  -40,  -40,
+      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
+      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
+
+      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
+      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
+      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40
+    },
+
+    {
+       33,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,
+      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,
+      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,
+      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,
+      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,
+      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,
+      -41,  -41,  -41,  -41,  -41,   94,  -41,  -41,  -41,  -41,
+
+      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,
+      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,
+      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,
+      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,
+      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,
+      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41
+    },
+
+    {
+       33,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
+      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
+      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
+      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
+
+      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
+      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
+      -42,  -42,  -42,  -42,  -42,  -42,   95,  -42,  -42,  -42,
+      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
+      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
+      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
+      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
+      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
+      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42
+    },
+
+    {
+       33,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
+
+      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
+      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
+      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
+      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
+      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
+      -43,  -43,  -43,  -43,  -43,  -43,  -43,   96,  -43,  -43,
+      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
+      -43,  -43,   97,   98,  -43,  -43,   99,  -43,  -43,  -43,
+      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
+      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
+
+      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
+      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43
+    },
+
+    {
+       33,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
+      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
+      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
+      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
+      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
+      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
+      -44,  -44,  -44,  -44,  -44,  100,  -44,  -44,  -44,  101,
+      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
+
+      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
+      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
+      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
+      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
+      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44
+    },
+
+    {
+       33,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
+      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
+      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
+      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
+      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
+
+      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
+      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
+      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
+      102,  -45,  -45,  103,  -45,  -45,  -45,  -45,  -45,  -45,
+      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
+      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
+      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
+      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45
+    },
+
+    {
+       33,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
+      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
+
+      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
+      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
+      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
+      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
+      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  104,
+      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
+      -46,  -46,  -46,  105,  -46,  -46,  -46,  -46,  -46,  -46,
+      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
+      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
+      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
+
+      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46
+    },
+
+    {
+       33,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
+      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
+      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
+      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
+      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
+      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
+      -47,  -47,  -47,  -47,  -47,  -47,  -47,  106,  -47,  -47,
+      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
+      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
+
+      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
+      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
+      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
+      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47
+    },
+
+    {
+       33,  -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,  107,  -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,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
+      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
+      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
+
+      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
+      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
+      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
+      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
+      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
+      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
+      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
+      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
+      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
+      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49
+
+    },
+
+    {
+       33,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
+      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
+      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
+      -50,  -50,  108,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
+      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  109,  109,
+      109,  109,  109,  109,  109,  109,  109,  109,  -50,  -50,
+      -50,  -50,  -50,  -50,  -50,  108,  108,  108,  108,  108,
+      108,  108,  108,  108,  108,  108,  108,  108,  108,  108,
+      108,  108,  108,  108,  108,  108,  108,  108,  108,  108,
+      108,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
+
+      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
+      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
+      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50
+    },
+
+    {
+       33,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
+      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
+      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
+      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
+      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
+      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
+      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
+
+      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
+      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
+      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
+      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
+      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
+      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51
+    },
+
+    {
+       33,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
+      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
+      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
+      -52,  -52,  110,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
+
+      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
+      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
+      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
+      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
+      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
+      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
+      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
+      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
+      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52
+    },
+
+    {
+       33,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53
+    },
+
+    {
+       33,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
+      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
+      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
+      -54,  -54,  111,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
+      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  112,  112,
+      112,  112,  112,  112,  112,  112,  112,  112,  -54,  -54,
+      -54,  -54,  -54,  -54,  -54,  111,  111,  111,  111,  111,
+      111,  111,  111,  111,  111,  111,  111,  111,  111,  111,
+
+      111,  111,  111,  111,  111,  111,  111,  111,  111,  111,
+      111,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
+      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
+      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
+      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54
+    },
+
+    {
+       33,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
+      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
+      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
+      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
+      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
+
+      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
+      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
+      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
+      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
+      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
+      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
+      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
+      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55
+    },
+
+    {
+       33,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
+      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
+
+      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
+      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
+      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  113,  113,
+      113,  113,  113,  113,  113,  113,  113,  113,  -56,  -56,
+      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
+      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
+      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
+      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
+      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
+      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
+
+      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56
+    },
+
+    {
+       33,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
+      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
+      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
+      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
+      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  114,  114,
+      114,  114,  114,  114,  114,  114,  114,  114,  -57,  -57,
+      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
+      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
+      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
+
+      -57,  -57,  -57,  -57,  -57,  115,  -57,  -57,  -57,  -57,
+      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
+      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
+      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57
+    },
+
+    {
+       33,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
+      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
+      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
+      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
+      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
+      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
+
+      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
+      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
+      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
+      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
+      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
+      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
+      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58
+    },
+
+    {
+       33,  -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,  -59,  -59,
+      -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  116,  116,
+      116,  116,  116,  116,  116,  116,  116,  116,  -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,  117,  -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
+
+    },
+
+    {
+       33,  -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,
+      -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,  -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
+    },
+
+    {
+       33,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
+      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
+      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
+      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
+      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
+      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
+      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
+
+      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
+      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
+      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
+      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
+      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
+      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61
+    },
+
+    {
+       33,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
+      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
+      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
+      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
+
+      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
+      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
+      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
+      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
+      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
+      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
+      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
+      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
+      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62
+    },
+
+    {
+       33,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
+
+      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
+      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
+      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
+      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
+      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
+      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
+      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
+      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
+      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
+      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
+
+      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
+      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63
+    },
+
+    {
+       33,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
+      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
+      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
+      -64,  -64,  118,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
+      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
+      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
+      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
+      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
+
+      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
+      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
+      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
+      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
+      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64
+    },
+
+    {
+       33,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
+      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
+      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
+      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
+      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
+
+      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
+      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
+      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
+      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
+      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
+      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
+      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
+      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65
+    },
+
+    {
+       33,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
+      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
+
+      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
+      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
+      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  119,  119,
+      119,  119,  119,  119,  119,  119,  119,  119,  -66,  -66,
+      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
+      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
+      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
+      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
+      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
+      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
+
+      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66
+    },
+
+    {
+       33,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  119,  119,
+      119,  119,  119,  119,  119,  119,  119,  119,  -67,  -67,
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67
+    },
+
+    {
+       33,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+
+      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68
+    },
+
+    {
+       33,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
+      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
+      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
+
+      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
+      -69,  -69,  -69,  -69,  -69,  -69,  120,  -69,  121,  121,
+      121,  121,  121,  121,  121,  121,  121,  121,  -69,  -69,
+      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
+      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
+      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
+      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
+      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
+      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
+      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69
+
+    },
+
+    {
+       33,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
+      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
+      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
+      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
+      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  122,  122,
+      122,  122,  122,  122,  122,  122,  122,  122,  -70,  -70,
+      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
+      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
+      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
+      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
+
+      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
+      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
+      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70
+    },
+
+    {
+       33,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
+      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
+      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
+      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
+      -71,  -71,  -71,  -71,  -71,  -71,  123,  -71,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124,  -71,  -71,
+      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  125,
+
+      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
+      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
+      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
+      -71,  125,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
+      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
+      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71
+    },
+
+    {
+       33,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
+      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
+      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
+      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
+
+      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
+      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
+      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
+      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
+      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
+      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
+      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
+      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
+      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72
+    },
+
+    {
+       33,  126,  126,  126,  126,  126,  126,  126,  126,  126,
+
+      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
+      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
+      126,  126,  126,  126,  126,  126,  126,  126,  126,  127,
+      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
+      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
+      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
+      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
+      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
+      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
+      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
+
+      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
+      126,  126,  126,  126,  126,  126,  126,  126
+    },
+
+    {
+       33,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
+      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
+      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
+      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
+      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
+      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
+      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
+      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
+
+      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
+      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
+      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
+      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
+      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74
+    },
+
+    {
+       33,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
+      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
+      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
+      -75,  -75,  128,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
+      -75,  -75,  -75,  -75,  -75,  -75,  -75,  129,  -75,  -75,
+
+      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
+      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
+      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
+      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
+      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
+      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
+      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
+      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75
+    },
+
+    {
+       33,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+      -76,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+
+      130,  130,  130,  130,  130,  130,  130,  130
+    },
+
+    {
+       33,  131,  131,  131,  131,  131,  131,  131,  131,  131,
+      -77,  131,  131,  131,  131,  131,  131,  131,  131,  131,
+      131,  131,  131,  131,  131,  131,  131,  131,  131,  131,
+      131,  131,  131,  131,  131,  131,  131,  131,  131,  131,
+      131,  131,  131,  131,  131,  131,  131,  131,  131,  131,
+      131,  131,  131,  131,  131,  131,  131,  131,  131,  131,
+      131,  131,  131,  131,  131,  131,  131,  131,  131,  131,
+      131,  131,  131,  131,  131,  131,  131,  131,  131,  131,
+      131,  131,  131,  131,  131,  131,  131,  131,  131,  131,
+
+      131,  131,  131,  131,  131,  131,  131,  131,  131,  131,
+      131,  131,  131,  131,  131,  131,  131,  131,  131,  131,
+      131,  131,  131,  131,  131,  131,  131,  131,  131,  131,
+      131,  131,  131,  131,  131,  131,  131,  131
+    },
+
+    {
+       33,  132,  132,  132,  132,  132,  132,  132,  132,  132,
+      -78,  132,  132,  132,  132,  132,  132,  132,  132,  132,
+      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
+      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
+      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
+      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
+
+      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
+      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
+      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
+      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
+      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
+      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
+      132,  132,  132,  132,  132,  132,  132,  132
+    },
+
+    {
+       33,  133,  133,  133,  133,  133,  133,  133,  133,  133,
+      134,  133,  133,  133,  133,  133,  133,  133,  133,  133,
+      133,  133,  133,  133,  133,  133,  133,  133,  133,  133,
+
+      133,  133,  133,  133,  133,  133,  133,  133,  133,  133,
+      133,  133,  133,  133,  133,  133,  133,  133,  133,  133,
+      133,  133,  133,  133,  133,  133,  133,  133,  133,  133,
+      133,  133,  133,  133,  133,  133,  133,  133,  133,  133,
+      133,  133,  133,  133,  133,  133,  133,  133,  133,  133,
+      133,  133,  133,  133,  133,  133,  133,  133,  133,  133,
+      133,  133,  133,  133,  133,  133,  133,  133,  133,  133,
+      133,  133,  133,  133,  133,  133,  133,  133,  133,  133,
+      133,  133,  133,  133,  133,  133,  133,  133,  133,  133,
+      133,  133,  133,  133,  133,  133,  133,  133
+
+    },
+
+    {
+       33,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
+      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
+      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
+      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
+      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
+      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
+      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
+      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
+      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
+      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
+
+      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
+      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
+      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80
+    },
+
+    {
+       33,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
+      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
+      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
+      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
+      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
+      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
+      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  135,
+
+      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
+      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
+      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
+      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
+      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
+      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81
+    },
+
+    {
+       33,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
+      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
+      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
+      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
+
+      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
+      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
+      -82,  -82,  -82,  -82,  -82,  136,  -82,  -82,  -82,  -82,
+      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
+      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
+      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
+      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
+      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
+      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82
+    },
+
+    {
+       33,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
+
+      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
+      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
+      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
+      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
+      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
+      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  137,  -83,
+      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  138,
+      139,  -83,  -83,  -83,  -83,  -83,  140,  -83,  -83,  -83,
+      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
+      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
+
+      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
+      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83
+    },
+
+    {
+       33,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
+      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
+      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
+      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
+      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
+      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
+      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
+      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
+
+      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  141,
+      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
+      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
+      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
+      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84
+    },
+
+    {
+       33,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
+      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
+      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
+      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
+      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
+
+      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
+      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
+      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
+      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  142,
+      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
+      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
+      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
+      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85
+    },
+
+    {
+       33,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
+      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
+
+      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
+      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
+      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
+      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
+      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
+      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  143,  -86,
+      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
+      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
+      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
+      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
+
+      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86
+    },
+
+    {
+       33,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+      -87,  -87,  -87,  -87,  144,  -87,  -87,  -87,  -87,  -87,
+
+      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87
+    },
+
+    {
+       33,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
+      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
+      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
+      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
+      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
+      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
+
+      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  145,  -88,
+      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
+      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
+      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
+      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
+      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
+      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88
+    },
+
+    {
+       33,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
+      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
+      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
+
+      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
+      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
+      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
+      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
+      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  146,
+      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
+      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
+      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
+      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
+      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89
+
+    },
+
+    {
+       33,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
+      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
+      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
+      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
+      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
+      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
+      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
+      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
+      -90,  -90,  -90,  -90,  -90,  147,  -90,  -90,  -90,  -90,
+      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
+
+      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
+      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
+      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90
+    },
+
+    {
+       33,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+
+      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+      -91,  -91,  -91,  -91,  148,  -91,  -91,  -91,  -91,  -91,
+      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91
+    },
+
+    {
+       33,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
+      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
+      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
+      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
+
+      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
+      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
+      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
+      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  149,  -92,
+      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
+      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
+      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
+      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
+      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92
+    },
+
+    {
+       33,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+
+      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  150,  -93,
+      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+
+      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93
+    },
+
+    {
+       33,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
+      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
+      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
+      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
+      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
+      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
+      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
+      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
+
+      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  151,  -94,
+      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
+      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
+      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
+      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94
+    },
+
+    {
+       33,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
+      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
+      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
+      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
+      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
+
+      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
+      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
+      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
+      -95,  -95,  -95,  152,  -95,  -95,  -95,  -95,  -95,  -95,
+      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
+      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
+      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
+      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95
+    },
+
+    {
+       33,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
+      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
+
+      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
+      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
+      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
+      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
+      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
+      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
+      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
+      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
+      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
+      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
+
+      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96
+    },
+
+    {
+       33,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
+      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
+      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
+      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
+      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
+      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
+      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
+      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  153,
+      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
+
+      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
+      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
+      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
+      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97
+    },
+
+    {
+       33,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
+      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
+      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
+      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
+      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
+      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
+
+      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
+      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
+      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
+      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
+      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
+      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
+      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98
+    },
+
+    {
+       33,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
+      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
+      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
+
+      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
+      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
+      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
+      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
+      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
+      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
+      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
+      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
+      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
+      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99
+
+    },
+
+    {
+       33, -100, -100, -100, -100, -100, -100, -100, -100, -100,
+     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
+     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
+     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
+     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
+     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
+     -100, -100, -100, -100, -100, -100, -100, -100,  154, -100,
+     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
+     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
+     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
+
+     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
+     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
+     -100, -100, -100, -100, -100, -100, -100, -100
+    },
+
+    {
+       33, -101, -101, -101, -101, -101, -101, -101, -101, -101,
+     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
+     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
+     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
+     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
+     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
+     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
+
+     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
+     -101, -101, -101,  155, -101, -101, -101, -101, -101, -101,
+     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
+     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
+     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
+     -101, -101, -101, -101, -101, -101, -101, -101
+    },
+
+    {
+       33, -102, -102, -102, -102, -102, -102, -102, -102, -102,
+     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
+     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
+     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
+
+     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
+     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
+     -102, -102, -102, -102, -102, -102, -102, -102, -102,  156,
+     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
+     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
+     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
+     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
+     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
+     -102, -102, -102, -102, -102, -102, -102, -102
+    },
+
+    {
+       33, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+
+     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+     -103, -103, -103, -103, -103, -103, -103, -103, -103,  157,
+     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+
+     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+     -103, -103, -103, -103, -103, -103, -103, -103
+    },
+
+    {
+       33, -104, -104, -104, -104, -104, -104, -104, -104, -104,
+     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
+     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
+     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
+     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
+     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
+     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
+     -104, -104, -104, -104, -104, -104,  158, -104, -104, -104,
+
+     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
+     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
+     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
+     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
+     -104, -104, -104, -104, -104, -104, -104, -104
+    },
+
+    {
+       33, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+
+     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+     -105, -105, -105, -105, -105, -105, -105, -105, -105,  159,
+     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+     -105, -105, -105, -105, -105, -105, -105, -105
+    },
+
+    {
+       33, -106, -106, -106, -106, -106, -106, -106, -106, -106,
+     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
+
+     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
+     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
+     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
+     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
+     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
+     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
+     -106, -106, -106,  160, -106, -106, -106, -106, -106, -106,
+     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
+     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
+     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
+
+     -106, -106, -106, -106, -106, -106, -106, -106
+    },
+
+    {
+       33, -107, -107, -107, -107, -107, -107, -107, -107, -107,
+     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
+     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
+     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
+     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
+     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
+     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
+     -107, -107, -107, -107, -107, -107, -107, -107, -107,  161,
+     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
+
+     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
+     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
+     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
+     -107, -107, -107, -107, -107, -107, -107, -107
+    },
+
+    {
+       33, -108, -108, -108, -108, -108, -108, -108, -108, -108,
+     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
+     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
+     -108, -108,  162, -108, -108, -108, -108, -108, -108, -108,
+     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
+     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
+
+     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
+     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
+     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
+     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
+     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
+     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
+     -108, -108, -108, -108, -108, -108, -108, -108
+    },
+
+    {
+       33, -109, -109, -109, -109, -109, -109, -109, -109, -109,
+     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
+     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
+
+     -109, -109,  163, -109, -109, -109, -109, -109, -109, -109,
+     -109, -109, -109, -109, -109, -109, -109, -109,  164,  164,
+      164,  164,  164,  164,  164,  164,  164,  164, -109, -109,
+     -109, -109, -109, -109, -109,  163,  163,  163,  163,  163,
+      163,  163,  163,  163,  163,  163,  163,  163,  163,  163,
+      163,  163,  163,  163,  163,  163,  163,  163,  163,  163,
+      163, -109, -109, -109, -109, -109, -109, -109, -109, -109,
+     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
+     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
+     -109, -109, -109, -109, -109, -109, -109, -109
+
+    },
+
+    {
+       33, -110, -110, -110, -110, -110, -110, -110, -110, -110,
+     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
+     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
+     -110, -110,  165, -110, -110, -110, -110, -110, -110, -110,
+     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
+     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
+     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
+     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
+     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
+     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
+
+     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
+     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
+     -110, -110, -110, -110, -110, -110, -110, -110
+    },
+
+    {
+       33, -111, -111, -111, -111, -111, -111, -111, -111, -111,
+     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
+     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
+     -111, -111,  166, -111, -111, -111, -111, -111, -111, -111,
+     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
+     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
+     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
+
+     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
+     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
+     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
+     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
+     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
+     -111, -111, -111, -111, -111, -111, -111, -111
+    },
+
+    {
+       33, -112, -112, -112, -112, -112, -112, -112, -112, -112,
+     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
+     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
+     -112, -112,  167, -112, -112, -112, -112, -112, -112, -112,
+
+     -112, -112, -112, -112, -112, -112, -112, -112,  168,  168,
+      168,  168,  168,  168,  168,  168,  168,  168, -112, -112,
+     -112, -112, -112, -112, -112,  167,  167,  167,  167,  167,
+      167,  167,  167,  167,  167,  167,  167,  167,  167,  167,
+      167,  167,  167,  167,  167,  167,  167,  167,  167,  167,
+      167, -112, -112, -112, -112, -112, -112, -112, -112, -112,
+     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
+     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
+     -112, -112, -112, -112, -112, -112, -112, -112
+    },
+
+    {
+       33, -113, -113, -113, -113, -113, -113, -113, -113, -113,
+
+     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
+     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
+     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
+     -113, -113, -113, -113, -113, -113, -113, -113,  169,  169,
+      169,  169,  169,  169,  169,  169,  169,  169, -113, -113,
+     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
+     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
+     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
+     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
+     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
+
+     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
+     -113, -113, -113, -113, -113, -113, -113, -113
+    },
+
+    {
+       33, -114, -114, -114, -114, -114, -114, -114, -114, -114,
+     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
+     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
+     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
+     -114, -114, -114, -114, -114, -114, -114, -114,  170,  170,
+      170,  170,  170,  170,  170,  170,  170,  170, -114, -114,
+     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
+     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
+
+     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
+     -114, -114, -114, -114, -114,  171, -114, -114, -114, -114,
+     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
+     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
+     -114, -114, -114, -114, -114, -114, -114, -114
+    },
+
+    {
+       33, -115, -115, -115, -115, -115, -115, -115, -115, -115,
+     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
+     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
+     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
+     -115, -115, -115, -115, -115, -115, -115, -115, -115,  172,
+
+      172,  172,  172,  172,  172,  172,  172,  172, -115, -115,
+     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
+     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
+     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
+     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
+     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
+     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
+     -115, -115, -115, -115, -115, -115, -115, -115
+    },
+
+    {
+       33, -116, -116, -116, -116, -116, -116, -116, -116, -116,
+     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
+
+     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
+     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
+     -116, -116, -116, -116, -116, -116, -116, -116,  173,  173,
+      173,  173,  173,  173,  173,  173,  173,  173, -116, -116,
+     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
+     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
+     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
+     -116, -116, -116, -116, -116,  174, -116, -116, -116, -116,
+     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
+     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
+
+     -116, -116, -116, -116, -116, -116, -116, -116
+    },
+
+    {
+       33, -117, -117, -117, -117, -117, -117, -117, -117, -117,
+     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
+     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
+     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
+     -117, -117, -117, -117, -117, -117, -117, -117,  175,  176,
+      176,  176,  176,  176,  176,  176,  176,  176, -117, -117,
+     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
+     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
+     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
+
+     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
+     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
+     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
+     -117, -117, -117, -117, -117, -117, -117, -117
+    },
+
+    {
+       33, -118, -118, -118, -118, -118, -118, -118, -118, -118,
+     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
+     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
+     -118, -118,  118, -118, -118, -118, -118, -118, -118, -118,
+     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
+     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
+
+     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
+     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
+     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
+     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
+     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
+     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
+     -118, -118, -118, -118, -118, -118, -118, -118
+    },
+
+    {
+       33, -119, -119, -119, -119, -119, -119, -119, -119, -119,
+     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
+     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
+
+     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
+     -119, -119, -119, -119, -119, -119, -119, -119,  119,  119,
+      119,  119,  119,  119,  119,  119,  119,  119, -119, -119,
+     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
+     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
+     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
+     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
+     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
+     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
+     -119, -119, -119, -119, -119, -119, -119, -119
+
+    },
+
+    {
+       33, -120, -120, -120, -120, -120, -120, -120, -120, -120,
+     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
+     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
+     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
+     -120, -120, -120, -120, -120, -120, -120, -120,  122,  122,
+      122,  122,  122,  122,  122,  122,  122,  122, -120, -120,
+     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
+     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
+     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
+     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
+
+     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
+     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
+     -120, -120, -120, -120, -120, -120, -120, -120
+    },
+
+    {
+       33, -121, -121, -121, -121, -121, -121, -121, -121, -121,
+     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
+     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
+     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
+     -121, -121, -121, -121, -121, -121,  123, -121,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124, -121, -121,
+     -121, -121, -121, -121, -121, -121, -121, -121, -121,  125,
+
+     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
+     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
+     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
+     -121,  125, -121, -121, -121, -121, -121, -121, -121, -121,
+     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
+     -121, -121, -121, -121, -121, -121, -121, -121
+    },
+
+    {
+       33, -122, -122, -122, -122, -122, -122, -122, -122, -122,
+     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
+     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
+     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
+
+     -122, -122, -122, -122, -122, -122, -122, -122,  122,  122,
+      122,  122,  122,  122,  122,  122,  122,  122, -122, -122,
+     -122, -122, -122, -122, -122, -122, -122, -122, -122,  125,
+     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
+     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
+     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
+     -122,  125, -122, -122, -122, -122, -122, -122, -122, -122,
+     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
+     -122, -122, -122, -122, -122, -122, -122, -122
+    },
+
+    {
+       33, -123, -123, -123, -123, -123, -123, -123, -123, -123,
+
+     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
+     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
+     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
+     -123, -123, -123, -123, -123, -123, -123, -123,  177,  177,
+      177,  177,  177,  177,  177,  177,  177,  177, -123, -123,
+     -123, -123, -123, -123, -123, -123, -123, -123, -123,  125,
+     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
+     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
+     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
+     -123,  125, -123, -123, -123, -123, -123, -123, -123, -123,
+
+     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
+     -123, -123, -123, -123, -123, -123, -123, -123
+    },
+
+    {
+       33, -124, -124, -124, -124, -124, -124, -124, -124, -124,
+     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
+     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
+     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
+     -124, -124, -124, -124, -124, -124,  123, -124,  124,  124,
+      124,  124,  124,  124,  124,  124,  124,  124, -124, -124,
+     -124, -124, -124, -124, -124, -124, -124, -124, -124,  125,
+     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
+
+     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
+     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
+     -124,  125, -124, -124, -124, -124, -124, -124, -124, -124,
+     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
+     -124, -124, -124, -124, -124, -124, -124, -124
+    },
+
+    {
+       33, -125, -125, -125, -125, -125, -125, -125, -125, -125,
+     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
+     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
+     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
+     -125, -125, -125,  178, -125,  178, -125, -125,  179,  179,
+
+      179,  179,  179,  179,  179,  179,  179,  179, -125, -125,
+     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
+     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
+     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
+     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
+     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
+     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
+     -125, -125, -125, -125, -125, -125, -125, -125
+    },
+
+    {
+       33,  126,  126,  126,  126,  126,  126,  126,  126,  126,
+      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
+
+      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
+      126,  126,  126,  126,  126,  126,  126,  126,  126,  127,
+      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
+      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
+      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
+      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
+      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
+      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
+      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
+      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
+
+      126,  126,  126,  126,  126,  126,  126,  126
+    },
+
+    {
+       33, -127, -127, -127, -127, -127, -127, -127, -127, -127,
+     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
+     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
+     -127, -127, -127, -127, -127, -127, -127, -127, -127,  126,
+     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
+     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
+     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
+     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
+     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
+
+     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
+     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
+     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
+     -127, -127, -127, -127, -127, -127, -127, -127
+    },
+
+    {
+       33, -128, -128, -128, -128, -128, -128, -128, -128, -128,
+     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
+     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
+     -128, -128,  128, -128, -128, -128, -128, -128, -128, -128,
+     -128, -128, -128, -128, -128, -128, -128,  129, -128, -128,
+     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
+
+     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
+     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
+     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
+     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
+     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
+     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
+     -128, -128, -128, -128, -128, -128, -128, -128
+    },
+
+    {
+       33,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+     -129,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130
+
+    },
+
+    {
+       33,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+     -130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130
+    },
+
+    {
+       33,  131,  131,  131,  131,  131,  131,  131,  131,  131,
+     -131,  131,  131,  131,  131,  131,  131,  131,  131,  131,
+      131,  131,  131,  131,  131,  131,  131,  131,  131,  131,
+      131,  131,  131,  131,  131,  131,  131,  131,  131,  131,
+      131,  131,  131,  131,  131,  131,  131,  131,  131,  131,
+      131,  131,  131,  131,  131,  131,  131,  131,  131,  131,
+      131,  131,  131,  131,  131,  131,  131,  131,  131,  131,
+
+      131,  131,  131,  131,  131,  131,  131,  131,  131,  131,
+      131,  131,  131,  131,  131,  131,  131,  131,  131,  131,
+      131,  131,  131,  131,  131,  131,  131,  131,  131,  131,
+      131,  131,  131,  131,  131,  131,  131,  131,  131,  131,
+      131,  131,  131,  131,  131,  131,  131,  131,  131,  131,
+      131,  131,  131,  131,  131,  131,  131,  131
+    },
+
+    {
+       33,  132,  132,  132,  132,  132,  132,  132,  132,  132,
+     -132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
+      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
+      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
+
+      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
+      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
+      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
+      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
+      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
+      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
+      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
+      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
+      132,  132,  132,  132,  132,  132,  132,  132
+    },
+
+    {
+       33,  133,  133,  133,  133,  133,  133,  133,  133,  133,
+
+      134,  133,  133,  133,  133,  133,  133,  133,  133,  133,
+      133,  133,  133,  133,  133,  133,  133,  133,  133,  133,
+      133,  133,  133,  133,  133,  133,  133,  133,  133,  133,
+      133,  133,  133,  133,  133,  133,  133,  133,  133,  133,
+      133,  133,  133,  133,  133,  133,  133,  133,  133,  133,
+      133,  133,  133,  133,  133,  133,  133,  133,  133,  133,
+      133,  133,  133,  133,  133,  133,  133,  133,  133,  133,
+      133,  133,  133,  133,  133,  133,  133,  133,  133,  133,
+      133,  133,  133,  133,  133,  133,  133,  133,  133,  133,
+      133,  133,  133,  133,  133,  133,  133,  133,  133,  133,
+
+      133,  133,  133,  133,  133,  133,  133,  133,  133,  133,
+      133,  133,  133,  133,  133,  133,  133,  133
+    },
+
+    {
+       33, -134, -134, -134, -134, -134, -134, -134, -134, -134,
+     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
+     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
+     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
+     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
+     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
+     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
+     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
+
+     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
+     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
+     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
+     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
+     -134, -134, -134, -134, -134, -134, -134, -134
+    },
+
+    {
+       33, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+
+     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+     -135, -135, -135, -135, -135, -135,  180, -135, -135, -135,
+     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+     -135, -135, -135, -135, -135, -135, -135, -135
+    },
+
+    {
+       33, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+
+     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+     -136, -136, -136, -136, -136, -136, -136,  181, -136, -136,
+     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+
+     -136, -136, -136, -136, -136, -136, -136, -136
+    },
+
+    {
+       33, -137, -137, -137, -137, -137, -137, -137, -137, -137,
+     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
+     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
+     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
+     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
+     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
+     -137, -137, -137, -137, -137, -137, -137, -137, -137,  182,
+     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
+     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
+
+     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
+     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
+     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
+     -137, -137, -137, -137, -137, -137, -137, -137
+    },
+
+    {
+       33, -138, -138, -138, -138, -138, -138, -138, -138, -138,
+     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
+     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
+     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
+     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
+     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
+
+     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
+     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
+     -138, -138, -138, -138,  183, -138, -138, -138, -138, -138,
+     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
+     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
+     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
+     -138, -138, -138, -138, -138, -138, -138, -138
+    },
+
+    {
+       33, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+
+     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+     -139, -139, -139,  184, -139, -139, -139, -139, -139, -139,
+     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+     -139, -139, -139, -139, -139, -139, -139, -139
+
+    },
+
+    {
+       33, -140, -140, -140, -140, -140, -140, -140, -140, -140,
+     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
+     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
+     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
+     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
+     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
+     -140, -140, -140, -140, -140,  185, -140, -140, -140, -140,
+     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
+     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
+     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
+
+     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
+     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
+     -140, -140, -140, -140, -140, -140, -140, -140
+    },
+
+    {
+       33, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+     -141, -141, -141, -141, -141, -141, -141, -141, -141,  186,
+
+     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+     -141, -141, -141, -141, -141, -141, -141, -141
+    },
+
+    {
+       33, -142, -142, -142, -142, -142, -142, -142, -142, -142,
+     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
+     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
+     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
+
+     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
+     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
+     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
+     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
+      187, -142, -142, -142, -142, -142, -142, -142, -142, -142,
+     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
+     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
+     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
+     -142, -142, -142, -142, -142, -142, -142, -142
+    },
+
+    {
+       33, -143, -143, -143, -143, -143, -143, -143, -143, -143,
+
+     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
+     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
+     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
+     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
+     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
+     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
+     -143, -143, -143,  188, -143, -143, -143, -143, -143, -143,
+     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
+     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
+     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
+
+     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
+     -143, -143, -143, -143, -143, -143, -143, -143
+    },
+
+    {
+       33, -144, -144, -144, -144, -144, -144, -144, -144, -144,
+     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
+     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
+     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
+     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
+     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
+     -144, -144, -144, -144, -144, -144, -144, -144, -144,  189,
+     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
+
+     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
+     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
+     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
+     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
+     -144, -144, -144, -144, -144, -144, -144, -144
+    },
+
+    {
+       33, -145, -145, -145, -145, -145, -145, -145, -145, -145,
+     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
+     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
+     -145, -145,  190, -145, -145, -145, -145, -145, -145, -145,
+     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
+
+     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
+     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
+     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
+     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
+     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
+     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
+     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
+     -145, -145, -145, -145, -145, -145, -145, -145
+    },
+
+    {
+       33, -146, -146, -146, -146, -146, -146, -146, -146, -146,
+     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
+
+     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
+     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
+     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
+     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
+     -146, -146, -146, -146, -146, -146, -146,  191, -146, -146,
+     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
+     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
+     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
+     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
+     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
+
+     -146, -146, -146, -146, -146, -146, -146, -146
+    },
+
+    {
+       33, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+     -147, -147, -147,  192, -147, -147, -147, -147, -147, -147,
+     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+
+     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+     -147, -147, -147, -147, -147, -147, -147, -147
+    },
+
+    {
+       33, -148, -148, -148, -148, -148, -148, -148, -148, -148,
+     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
+     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
+     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
+     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
+     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
+
+     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
+     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
+      193, -148, -148, -148, -148, -148, -148, -148, -148, -148,
+     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
+     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
+     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
+     -148, -148, -148, -148, -148, -148, -148, -148
+    },
+
+    {
+       33, -149, -149, -149, -149, -149, -149, -149, -149, -149,
+     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
+     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
+
+     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
+     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
+     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
+     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
+     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
+      194, -149, -149, -149, -149, -149, -149, -149, -149, -149,
+     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
+     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
+     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
+     -149, -149, -149, -149, -149, -149, -149, -149
+
+    },
+
+    {
+       33, -150, -150, -150, -150, -150, -150, -150, -150, -150,
+     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
+     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
+     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
+     -150, -150, -150, -150, -150,  195, -150, -150, -150, -150,
+     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
+     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
+     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
+     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
+     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
+
+     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
+     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
+     -150, -150, -150, -150, -150, -150, -150, -150
+    },
+
+    {
+       33, -151, -151, -151, -151, -151, -151, -151, -151, -151,
+     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
+     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
+     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
+     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
+     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
+     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
+
+     -151, -151, -151,  196, -151, -151, -151, -151, -151, -151,
+     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
+     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
+     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
+     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
+     -151, -151, -151, -151, -151, -151, -151, -151
+    },
+
+    {
+       33, -152, -152, -152, -152, -152, -152, -152, -152, -152,
+     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
+     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
+     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
+
+     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
+     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
+     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
+     -152,  197, -152, -152, -152, -152, -152, -152, -152, -152,
+     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
+     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
+     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
+     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
+     -152, -152, -152, -152, -152, -152, -152, -152
+    },
+
+    {
+       33, -153, -153, -153, -153, -153, -153, -153, -153, -153,
+
+     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
+     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
+     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
+     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
+     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
+     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
+     -153, -153, -153, -153,  198, -153, -153, -153, -153, -153,
+     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
+     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
+     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
+
+     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
+     -153, -153, -153, -153, -153, -153, -153, -153
+    },
+
+    {
+       33, -154, -154, -154, -154, -154, -154, -154, -154, -154,
+     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
+     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
+     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
+     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
+     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
+     -154, -154, -154, -154, -154, -154, -154, -154, -154,  199,
+     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
+
+     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
+     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
+     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
+     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
+     -154, -154, -154, -154, -154, -154, -154, -154
+    },
+
+    {
+       33, -155, -155, -155, -155, -155, -155, -155, -155, -155,
+     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
+     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
+     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
+     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
+
+     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
+     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
+     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
+     -155, -155, -155, -155,  200, -155, -155, -155, -155, -155,
+     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
+     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
+     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
+     -155, -155, -155, -155, -155, -155, -155, -155
+    },
+
+    {
+       33, -156, -156, -156, -156, -156, -156, -156, -156, -156,
+     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
+
+     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
+     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
+     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
+     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
+     -156, -156, -156, -156, -156, -156, -156,  201, -156, -156,
+     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
+     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
+     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
+     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
+     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
+
+     -156, -156, -156, -156, -156, -156, -156, -156
+    },
+
+    {
+       33, -157, -157, -157, -157, -157, -157, -157, -157, -157,
+     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
+     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
+     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
+     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
+     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
+     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
+     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
+     -157, -157, -157,  202, -157, -157, -157, -157, -157, -157,
+
+     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
+     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
+     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
+     -157, -157, -157, -157, -157, -157, -157, -157
+    },
+
+    {
+       33, -158, -158, -158, -158, -158, -158, -158, -158, -158,
+     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
+     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
+     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
+     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
+     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
+
+     -158, -158, -158, -158, -158,  203, -158, -158, -158, -158,
+     -158, -158, -158, -158, -158, -158, -158, -158, -158,  204,
+     -158, -158,  205, -158, -158, -158, -158, -158, -158, -158,
+     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
+     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
+     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
+     -158, -158, -158, -158, -158, -158, -158, -158
+    },
+
+    {
+       33, -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, -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,  206, -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
+
+    },
+
+    {
+       33, -160, -160, -160, -160, -160, -160, -160, -160, -160,
+     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
+     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
+     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
+     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
+     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
+     -160, -160, -160, -160, -160,  207, -160, -160, -160, -160,
+     -160, -160, -160, -160, -160, -160, -160, -160,  208, -160,
+     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
+     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
+
+     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
+     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
+     -160, -160, -160, -160, -160, -160, -160, -160
+    },
+
+    {
+       33, -161, -161, -161, -161, -161, -161, -161, -161, -161,
+     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
+     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
+     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
+     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
+     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
+     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
+
+     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
+     -161, -161, -161, -161, -161,  209, -161, -161, -161, -161,
+     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
+     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
+     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
+     -161, -161, -161, -161, -161, -161, -161, -161
+    },
+
+    {
+       33, -162, -162, -162, -162, -162, -162, -162, -162, -162,
+     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
+     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
+     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
+
+     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
+     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
+     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
+     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
+     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
+     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
+     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
+     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
+     -162, -162, -162, -162, -162, -162, -162, -162
+    },
+
+    {
+       33, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+
+     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+
+     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+     -163, -163, -163, -163, -163, -163, -163, -163
+    },
+
+    {
+       33, -164, -164, -164, -164, -164, -164, -164, -164, -164,
+     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
+     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
+     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
+     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
+     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
+     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
+     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
+
+     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
+     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
+     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
+     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
+     -164, -164, -164, -164, -164, -164, -164, -164
+    },
+
+    {
+       33, -165, -165, -165, -165, -165, -165, -165, -165, -165,
+     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
+     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
+     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
+     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
+
+     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
+     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
+     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
+     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
+     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
+     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
+     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
+     -165, -165, -165, -165, -165, -165, -165, -165
+    },
+
+    {
+       33, -166, -166, -166, -166, -166, -166, -166, -166, -166,
+     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
+
+     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
+     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
+     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
+     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
+     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
+     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
+     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
+     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
+     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
+     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
+
+     -166, -166, -166, -166, -166, -166, -166, -166
+    },
+
+    {
+       33, -167, -167, -167, -167, -167, -167, -167, -167, -167,
+     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
+     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
+     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
+     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
+     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
+     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
+     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
+     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
+
+     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
+     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
+     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
+     -167, -167, -167, -167, -167, -167, -167, -167
+    },
+
+    {
+       33, -168, -168, -168, -168, -168, -168, -168, -168, -168,
+     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
+     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
+     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
+     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
+     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
+
+     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
+     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
+     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
+     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
+     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
+     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
+     -168, -168, -168, -168, -168, -168, -168, -168
+    },
+
+    {
+       33, -169, -169, -169, -169, -169, -169, -169, -169, -169,
+     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
+     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
+
+     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
+     -169, -169, -169, -169, -169, -169, -169, -169,  210,  210,
+      210,  210,  210,  210,  210,  210,  210,  210, -169, -169,
+     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
+     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
+     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
+     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
+     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
+     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
+     -169, -169, -169, -169, -169, -169, -169, -169
+
+    },
+
+    {
+       33, -170, -170, -170, -170, -170, -170, -170, -170, -170,
+     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
+     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
+     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
+     -170, -170, -170, -170, -170, -170, -170, -170,  211,  211,
+      211,  211,  211,  211,  211,  211,  211,  211, -170, -170,
+     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
+     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
+     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
+     -170, -170, -170, -170, -170,  212, -170, -170, -170, -170,
+
+     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
+     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
+     -170, -170, -170, -170, -170, -170, -170, -170
+    },
+
+    {
+       33, -171, -171, -171, -171, -171, -171, -171, -171, -171,
+     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
+     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
+     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
+     -171, -171, -171, -171, -171, -171, -171, -171, -171,  213,
+      213,  213,  213,  213,  213,  213,  213,  213, -171, -171,
+     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
+
+     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
+     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
+     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
+     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
+     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
+     -171, -171, -171, -171, -171, -171, -171, -171
+    },
+
+    {
+       33, -172, -172, -172, -172, -172, -172, -172, -172, -172,
+     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
+     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
+     -172, -172,  214, -172, -172, -172, -172, -172, -172, -172,
+
+     -172, -172, -172, -172, -172, -172, -172, -172,  215,  215,
+      215,  215,  215,  215,  215,  215,  215,  215, -172, -172,
+     -172, -172, -172, -172, -172,  214,  214,  214,  214,  214,
+      214,  214,  214,  214,  214,  214,  214,  214,  214,  214,
+      214,  214,  214,  214,  214,  214,  214,  214,  214,  214,
+      214, -172, -172, -172, -172, -172, -172, -172, -172, -172,
+     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
+     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
+     -172, -172, -172, -172, -172, -172, -172, -172
+    },
+
+    {
+       33, -173, -173, -173, -173, -173, -173, -173, -173, -173,
+
+     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
+     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
+     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
+     -173, -173, -173, -173, -173, -173, -173, -173,  216,  216,
+      216,  216,  216,  216,  216,  216,  216,  216, -173, -173,
+     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
+     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
+     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
+     -173, -173, -173, -173, -173,  217, -173, -173, -173, -173,
+     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
+
+     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
+     -173, -173, -173, -173, -173, -173, -173, -173
+    },
+
+    {
+       33, -174, -174, -174, -174, -174, -174, -174, -174, -174,
+     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
+     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
+     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
+     -174, -174, -174, -174, -174, -174, -174, -174,  218,  219,
+      219,  219,  219,  219,  219,  219,  219,  219, -174, -174,
+     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
+     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
+
+     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
+     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
+     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
+     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
+     -174, -174, -174, -174, -174, -174, -174, -174
+    },
+
+    {
+       33, -175, -175, -175, -175, -175, -175, -175, -175, -175,
+     -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
+     -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
+     -175, -175,  220, -175, -175, -175, -175, -175, -175, -175,
+     -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
+
+     -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
+     -175, -175, -175, -175, -175,  220,  220,  220,  220,  220,
+      220,  220,  220,  220,  220,  220,  220,  220,  220,  220,
+      220,  220,  220,  220,  220,  220,  220,  220,  220,  220,
+      220, -175, -175, -175, -175, -175, -175, -175, -175, -175,
+     -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
+     -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
+     -175, -175, -175, -175, -175, -175, -175, -175
+    },
+
+    {
+       33, -176, -176, -176, -176, -176, -176, -176, -176, -176,
+     -176, -176, -176, -176, -176, -176, -176, -176, -176, -176,
+
+     -176, -176, -176, -176, -176, -176, -176, -176, -176, -176,
+     -176, -176,  220, -176, -176, -176, -176, -176, -176, -176,
+     -176, -176, -176, -176, -176, -176, -176, -176,  221,  221,
+      221,  221,  221,  221,  221,  221,  221,  221, -176, -176,
+     -176, -176, -176, -176, -176,  220,  220,  220,  220,  220,
+      220,  220,  220,  220,  220,  220,  220,  220,  220,  220,
+      220,  220,  220,  220,  220,  220,  220,  220,  220,  220,
+      220, -176, -176, -176, -176, -176, -176, -176, -176, -176,
+     -176, -176, -176, -176, -176, -176, -176, -176, -176, -176,
+     -176, -176, -176, -176, -176, -176, -176, -176, -176, -176,
+
+     -176, -176, -176, -176, -176, -176, -176, -176
+    },
+
+    {
+       33, -177, -177, -177, -177, -177, -177, -177, -177, -177,
+     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
+     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
+     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
+     -177, -177, -177, -177, -177, -177, -177, -177,  177,  177,
+      177,  177,  177,  177,  177,  177,  177,  177, -177, -177,
+     -177, -177, -177, -177, -177, -177, -177, -177, -177,  125,
+     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
+     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
+
+     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
+     -177,  125, -177, -177, -177, -177, -177, -177, -177, -177,
+     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
+     -177, -177, -177, -177, -177, -177, -177, -177
+    },
+
+    {
+       33, -178, -178, -178, -178, -178, -178, -178, -178, -178,
+     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
+     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
+     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
+     -178, -178, -178, -178, -178, -178, -178, -178,  179,  179,
+      179,  179,  179,  179,  179,  179,  179,  179, -178, -178,
+
+     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
+     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
+     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
+     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
+     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
+     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
+     -178, -178, -178, -178, -178, -178, -178, -178
+    },
+
+    {
+       33, -179, -179, -179, -179, -179, -179, -179, -179, -179,
+     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
+     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
+
+     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
+     -179, -179, -179, -179, -179, -179, -179, -179,  179,  179,
+      179,  179,  179,  179,  179,  179,  179,  179, -179, -179,
+     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
+     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
+     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
+     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
+     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
+     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
+     -179, -179, -179, -179, -179, -179, -179, -179
+
+    },
+
+    {
+       33, -180, -180, -180, -180, -180, -180, -180, -180, -180,
+     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
+     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
+     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
+     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
+     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
+     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
+     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
+     -180, -180, -180, -180,  222, -180, -180, -180, -180, -180,
+     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
+
+     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
+     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
+     -180, -180, -180, -180, -180, -180, -180, -180
+    },
+
+    {
+       33, -181, -181, -181, -181, -181, -181, -181, -181, -181,
+     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
+     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
+     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
+     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
+     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
+     -181, -181, -181, -181, -181, -181, -181, -181, -181,  223,
+
+     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
+     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
+     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
+     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
+     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
+     -181, -181, -181, -181, -181, -181, -181, -181
+    },
+
+    {
+       33, -182, -182, -182, -182, -182, -182, -182, -182, -182,
+     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
+     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
+     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
+
+     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
+     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
+     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
+     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
+     -182, -182,  224, -182, -182, -182, -182, -182, -182, -182,
+     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
+     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
+     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
+     -182, -182, -182, -182, -182, -182, -182, -182
+    },
+
+    {
+       33, -183, -183, -183, -183, -183, -183, -183, -183, -183,
+
+     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
+     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
+     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
+     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
+     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
+     -183, -183, -183, -183, -183,  225, -183, -183, -183, -183,
+     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
+     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
+     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
+     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
+
+     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
+     -183, -183, -183, -183, -183, -183, -183, -183
+    },
+
+    {
+       33, -184, -184, -184, -184, -184, -184, -184, -184, -184,
+     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
+     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
+     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
+     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
+     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
+     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
+     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
+
+     -184, -184, -184, -184, -184, -184, -184, -184,  226, -184,
+     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
+     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
+     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
+     -184, -184, -184, -184, -184, -184, -184, -184
+    },
+
+    {
+       33, -185, -185, -185, -185, -185, -185, -185, -185, -185,
+     -185, -185, -185, -185, -185, -185, -185, -185, -185, -185,
+     -185, -185, -185, -185, -185, -185, -185, -185, -185, -185,
+     -185, -185, -185, -185, -185, -185, -185, -185, -185, -185,
+     -185, -185, -185, -185, -185, -185, -185, -185, -185, -185,
+
+     -185, -185, -185, -185, -185, -185, -185, -185, -185, -185,
+     -185, -185, -185, -185, -185, -185, -185, -185, -185, -185,
+     -185, -185, -185, -185, -185, -185,  227, -185, -185, -185,
+     -185, -185, -185, -185, -185, -185, -185, -185, -185, -185,
+     -185, -185, -185, -185, -185, -185, -185, -185, -185, -185,
+     -185, -185, -185, -185, -185, -185, -185, -185, -185, -185,
+     -185, -185, -185, -185, -185, -185, -185, -185, -185, -185,
+     -185, -185, -185, -185, -185, -185, -185, -185
+    },
+
+    {
+       33, -186, -186, -186, -186, -186, -186, -186, -186, -186,
+     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
+
+     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
+     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
+     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
+     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
+     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
+     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
+     -186, -186,  228, -186, -186, -186, -186, -186, -186, -186,
+     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
+     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
+     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
+
+     -186, -186, -186, -186, -186, -186, -186, -186
+    },
+
+    {
+       33, -187, -187, -187, -187, -187, -187, -187, -187, -187,
+     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
+     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
+     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
+     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
+     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
+     -187, -187, -187, -187, -187, -187, -187, -187, -187,  229,
+     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
+     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
+
+     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
+     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
+     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
+     -187, -187, -187, -187, -187, -187, -187, -187
+    },
+
+    {
+       33, -188, -188, -188, -188, -188, -188, -188, -188, -188,
+     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
+     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
+     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
+     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
+     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
+
+     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
+     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
+     -188, -188, -188, -188,  230, -188, -188, -188, -188, -188,
+     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
+     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
+     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
+     -188, -188, -188, -188, -188, -188, -188, -188
+    },
+
+    {
+       33, -189, -189, -189, -189, -189, -189, -189, -189, -189,
+     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
+     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
+
+     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
+     -189, -189, -189, -189, -189,  231, -189, -189, -189, -189,
+     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
+     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
+     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
+     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
+     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
+     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
+     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
+     -189, -189, -189, -189, -189, -189, -189, -189
+
+    },
+
+    {
+       33, -190, -190, -190, -190, -190, -190, -190, -190, -190,
+     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
+     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
+     -190, -190,  232, -190, -190, -190, -190, -190, -190, -190,
+     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
+     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
+     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
+     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
+     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
+     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
+
+     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
+     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
+     -190, -190, -190, -190, -190, -190, -190, -190
+    },
+
+    {
+       33, -191, -191, -191, -191, -191, -191, -191, -191, -191,
+     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
+     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
+     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
+     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
+     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
+     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
+
+     -191, -191,  233, -191, -191, -191, -191, -191, -191, -191,
+     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
+     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
+     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
+     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
+     -191, -191, -191, -191, -191, -191, -191, -191
+    },
+
+    {
+       33, -192, -192, -192, -192, -192, -192, -192, -192, -192,
+     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
+     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
+     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
+
+     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
+     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
+     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
+     -192, -192, -192, -192, -192, -192, -192, -192,  234, -192,
+     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
+     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
+     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
+     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
+     -192, -192, -192, -192, -192, -192, -192, -192
+    },
+
+    {
+       33, -193, -193, -193, -193, -193, -193, -193, -193, -193,
+
+     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
+     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
+     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
+     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
+     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
+     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
+     -193, -193, -193, -193, -193, -193, -193, -193, -193,  235,
+     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
+     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
+     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
+
+     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
+     -193, -193, -193, -193, -193, -193, -193, -193
+    },
+
+    {
+       33, -194, -194, -194, -194, -194, -194, -194, -194, -194,
+     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
+     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
+     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
+     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
+     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
+     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
+     -194, -194, -194, -194, -194, -194, -194, -194, -194,  236,
+
+     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
+     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
+     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
+     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
+     -194, -194, -194, -194, -194, -194, -194, -194
+    },
+
+    {
+       33, -195, -195, -195, -195, -195, -195, -195, -195, -195,
+     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
+     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
+     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
+     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
+
+     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
+     -195, -195, -195, -195, -195,  237, -195, -195, -195, -195,
+     -195, -195, -195, -195, -195, -195, -195, -195, -195,  238,
+     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
+     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
+     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
+     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
+     -195, -195, -195, -195, -195, -195, -195, -195
+    },
+
+    {
+       33, -196, -196, -196, -196, -196, -196, -196, -196, -196,
+     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
+
+     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
+     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
+     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
+     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
+     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
+     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
+     -196, -196, -196,  239, -196, -196, -196, -196, -196, -196,
+     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
+     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
+     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
+
+     -196, -196, -196, -196, -196, -196, -196, -196
+    },
+
+    {
+       33, -197, -197, -197, -197, -197, -197, -197, -197, -197,
+     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
+     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
+     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
+     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
+     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
+     -197, -197, -197, -197, -197, -197, -197, -197, -197,  240,
+     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
+     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
+
+     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
+     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
+     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
+     -197, -197, -197, -197, -197, -197, -197, -197
+    },
+
+    {
+       33, -198, -198, -198, -198, -198, -198, -198, -198, -198,
+     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
+     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
+     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
+     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
+     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
+
+     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
+     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
+      241, -198, -198, -198, -198, -198, -198, -198, -198, -198,
+     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
+     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
+     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
+     -198, -198, -198, -198, -198, -198, -198, -198
+    },
+
+    {
+       33, -199, -199, -199, -199, -199, -199, -199, -199, -199,
+     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
+     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
+
+     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
+     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
+     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
+     -199, -199, -199, -199, -199, -199, -199,  242, -199, -199,
+     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
+     -199, -199, -199,  243, -199, -199, -199, -199, -199, -199,
+     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
+     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
+     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
+     -199, -199, -199, -199, -199, -199, -199, -199
+
+    },
+
+    {
+       33, -200, -200, -200, -200, -200, -200, -200, -200, -200,
+     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
+     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
+     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
+     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
+     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
+     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
+      244, -200, -200, -200, -200, -200, -200, -200, -200, -200,
+     -200, -200, -200, -200, -200, -200, -200,  245, -200, -200,
+     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
+
+     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
+     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
+     -200, -200, -200, -200, -200, -200, -200, -200
+    },
+
+    {
+       33, -201, -201, -201, -201, -201, -201, -201, -201, -201,
+     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
+     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
+     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
+     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
+     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
+     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
+
+     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
+     -201, -201, -201,  246, -201, -201, -201, -201, -201, -201,
+     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
+     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
+     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
+     -201, -201, -201, -201, -201, -201, -201, -201
+    },
+
+    {
+       33, -202, -202, -202, -202, -202, -202, -202, -202, -202,
+     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
+     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
+     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
+
+     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
+     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
+     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
+     -202, -202, -202, -202, -202, -202, -202, -202, -202,  247,
+     -202, -202, -202,  248, -202, -202, -202, -202, -202, -202,
+     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
+     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
+     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
+     -202, -202, -202, -202, -202, -202, -202, -202
+    },
+
+    {
+       33, -203, -203, -203, -203, -203, -203, -203, -203, -203,
+
+     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
+     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
+     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
+     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
+     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
+     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
+     -203, -203, -203, -203, -203, -203, -203, -203,  249, -203,
+     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
+     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
+     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
+
+     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
+     -203, -203, -203, -203, -203, -203, -203, -203
+    },
+
+    {
+       33, -204, -204, -204, -204, -204, -204, -204, -204, -204,
+     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
+     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
+     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
+     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
+     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
+     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
+     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
+
+     -204, -204, -204,  250, -204, -204, -204, -204, -204, -204,
+     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
+     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
+     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
+     -204, -204, -204, -204, -204, -204, -204, -204
+    },
+
+    {
+       33, -205, -205, -205, -205, -205, -205, -205, -205, -205,
+     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
+     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
+     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
+     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
+
+     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
+     -205, -205, -205, -205, -205, -205, -205, -205, -205,  251,
+     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
+     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
+     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
+     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
+     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
+     -205, -205, -205, -205, -205, -205, -205, -205
+    },
+
+    {
+       33, -206, -206, -206, -206, -206, -206, -206, -206, -206,
+     -206, -206, -206, -206, -206, -206, -206, -206, -206, -206,
+
+     -206, -206, -206, -206, -206, -206, -206, -206, -206, -206,
+     -206, -206, -206, -206, -206, -206, -206, -206, -206, -206,
+     -206, -206, -206, -206, -206, -206, -206, -206, -206, -206,
+     -206, -206, -206, -206, -206, -206, -206, -206, -206, -206,
+     -206, -206, -206, -206, -206, -206, -206, -206, -206, -206,
+     -206, -206, -206, -206, -206, -206, -206, -206, -206, -206,
+     -206, -206,  252, -206, -206, -206, -206, -206, -206, -206,
+     -206, -206, -206, -206, -206, -206, -206, -206, -206, -206,
+     -206, -206, -206, -206, -206, -206, -206, -206, -206, -206,
+     -206, -206, -206, -206, -206, -206, -206, -206, -206, -206,
+
+     -206, -206, -206, -206, -206, -206, -206, -206
+    },
+
+    {
+       33, -207, -207, -207, -207, -207, -207, -207, -207, -207,
+     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
+     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
+     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
+     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
+     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
+     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
+     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
+     -207, -207, -207, -207, -207, -207, -207, -207,  253, -207,
+
+     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
+     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
+     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
+     -207, -207, -207, -207, -207, -207, -207, -207
+    },
+
+    {
+       33, -208, -208, -208, -208, -208, -208, -208, -208, -208,
+     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
+     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
+     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
+     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
+     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
+
+     -208, -208, -208, -208, -208,  254, -208, -208, -208, -208,
+     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
+     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
+     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
+     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
+     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
+     -208, -208, -208, -208, -208, -208, -208, -208
+    },
+
+    {
+       33, -209, -209, -209, -209, -209, -209, -209, -209, -209,
+     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
+     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
+
+     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
+     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
+     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
+     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
+     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
+     -209, -209,  255, -209, -209, -209, -209, -209, -209, -209,
+     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
+     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
+     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
+     -209, -209, -209, -209, -209, -209, -209, -209
+
+    },
+
+    {
+       33, -210, -210, -210, -210, -210, -210, -210, -210, -210,
+     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
+     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
+     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
+     -210, -210, -210, -210, -210, -210, -210, -210,  256,  256,
+      256,  256,  256,  256,  256,  256,  256,  256, -210, -210,
+     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
+     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
+     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
+     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
+
+     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
+     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
+     -210, -210, -210, -210, -210, -210, -210, -210
+    },
+
+    {
+       33, -211, -211, -211, -211, -211, -211, -211, -211, -211,
+     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
+     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
+     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
+     -211, -211, -211, -211, -211, -211, -211, -211,  256,  256,
+      256,  256,  256,  256,  256,  256,  256,  256, -211, -211,
+     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
+
+     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
+     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
+     -211, -211, -211, -211, -211,  257, -211, -211, -211, -211,
+     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
+     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
+     -211, -211, -211, -211, -211, -211, -211, -211
+    },
+
+    {
+       33, -212, -212, -212, -212, -212, -212, -212, -212, -212,
+     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
+     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
+     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
+
+     -212, -212, -212, -212, -212, -212, -212, -212, -212,  258,
+      258,  258,  258,  258,  258,  258,  258,  258, -212, -212,
+     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
+     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
+     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
+     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
+     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
+     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
+     -212, -212, -212, -212, -212, -212, -212, -212
+    },
+
+    {
+       33, -213, -213, -213, -213, -213, -213, -213, -213, -213,
+
+     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
+     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
+     -213, -213,  259, -213, -213, -213, -213, -213, -213, -213,
+     -213, -213, -213, -213, -213, -213, -213, -213,  260,  260,
+      260,  260,  260,  260,  260,  260,  260,  260, -213, -213,
+     -213, -213, -213, -213, -213,  259,  259,  259,  259,  259,
+      259,  259,  259,  259,  259,  259,  259,  259,  259,  259,
+      259,  259,  259,  259,  259,  259,  259,  259,  259,  259,
+      259, -213, -213, -213, -213, -213, -213, -213, -213, -213,
+     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
+
+     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
+     -213, -213, -213, -213, -213, -213, -213, -213
+    },
+
+    {
+       33, -214, -214, -214, -214, -214, -214, -214, -214, -214,
+     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
+     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
+     -214, -214,  261, -214, -214, -214, -214, -214, -214, -214,
+     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
+     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
+     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
+     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
+
+     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
+     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
+     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
+     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
+     -214, -214, -214, -214, -214, -214, -214, -214
+    },
+
+    {
+       33, -215, -215, -215, -215, -215, -215, -215, -215, -215,
+     -215, -215, -215, -215, -215, -215, -215, -215, -215, -215,
+     -215, -215, -215, -215, -215, -215, -215, -215, -215, -215,
+     -215, -215,  262, -215, -215, -215, -215, -215, -215, -215,
+     -215, -215, -215, -215, -215, -215, -215, -215,  263,  263,
+
+      263,  263,  263,  263,  263,  263,  263,  263, -215, -215,
+     -215, -215, -215, -215, -215,  262,  262,  262,  262,  262,
+      262,  262,  262,  262,  262,  262,  262,  262,  262,  262,
+      262,  262,  262,  262,  262,  262,  262,  262,  262,  262,
+      262, -215, -215, -215, -215, -215, -215, -215, -215, -215,
+     -215, -215, -215, -215, -215, -215, -215, -215, -215, -215,
+     -215, -215, -215, -215, -215, -215, -215, -215, -215, -215,
+     -215, -215, -215, -215, -215, -215, -215, -215
+    },
+
+    {
+       33, -216, -216, -216, -216, -216, -216, -216, -216, -216,
+     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
+
+     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
+     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
+     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
+     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
+     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
+     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
+     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
+     -216, -216, -216, -216, -216,  264, -216, -216, -216, -216,
+     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
+     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
+
+     -216, -216, -216, -216, -216, -216, -216, -216
+    },
+
+    {
+       33, -217, -217, -217, -217, -217, -217, -217, -217, -217,
+     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
+     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
+     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
+     -217, -217, -217, -217, -217, -217, -217, -217,  265,  266,
+      266,  266,  266,  266,  266,  266,  266,  266, -217, -217,
+     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
+     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
+     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
+
+     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
+     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
+     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
+     -217, -217, -217, -217, -217, -217, -217, -217
+    },
+
+    {
+       33, -218, -218, -218, -218, -218, -218, -218, -218, -218,
+     -218, -218, -218, -218, -218, -218, -218, -218, -218, -218,
+     -218, -218, -218, -218, -218, -218, -218, -218, -218, -218,
+     -218, -218,  267, -218, -218, -218, -218, -218, -218, -218,
+     -218, -218, -218, -218, -218, -218, -218, -218, -218, -218,
+     -218, -218, -218, -218, -218, -218, -218, -218, -218, -218,
+
+     -218, -218, -218, -218, -218,  267,  267,  267,  267,  267,
+      267,  267,  267,  267,  267,  267,  267,  267,  267,  267,
+      267,  267,  267,  267,  267,  267,  267,  267,  267,  267,
+      267, -218, -218, -218, -218, -218, -218, -218, -218, -218,
+     -218, -218, -218, -218, -218, -218, -218, -218, -218, -218,
+     -218, -218, -218, -218, -218, -218, -218, -218, -218, -218,
+     -218, -218, -218, -218, -218, -218, -218, -218
+    },
+
+    {
+       33, -219, -219, -219, -219, -219, -219, -219, -219, -219,
+     -219, -219, -219, -219, -219, -219, -219, -219, -219, -219,
+     -219, -219, -219, -219, -219, -219, -219, -219, -219, -219,
+
+     -219, -219,  267, -219, -219, -219, -219, -219, -219, -219,
+     -219, -219, -219, -219, -219, -219, -219, -219,  268,  268,
+      268,  268,  268,  268,  268,  268,  268,  268, -219, -219,
+     -219, -219, -219, -219, -219,  267,  267,  267,  267,  267,
+      267,  267,  267,  267,  267,  267,  267,  267,  267,  267,
+      267,  267,  267,  267,  267,  267,  267,  267,  267,  267,
+      267, -219, -219, -219, -219, -219, -219, -219, -219, -219,
+     -219, -219, -219, -219, -219, -219, -219, -219, -219, -219,
+     -219, -219, -219, -219, -219, -219, -219, -219, -219, -219,
+     -219, -219, -219, -219, -219, -219, -219, -219
+
+    },
+
+    {
+       33, -220, -220, -220, -220, -220, -220, -220, -220, -220,
+     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
+     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
+     -220, -220,  269, -220, -220, -220, -220, -220, -220, -220,
+     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
+     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
+     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
+     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
+     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
+     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
+
+     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
+     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
+     -220, -220, -220, -220, -220, -220, -220, -220
+    },
+
+    {
+       33, -221, -221, -221, -221, -221, -221, -221, -221, -221,
+     -221, -221, -221, -221, -221, -221, -221, -221, -221, -221,
+     -221, -221, -221, -221, -221, -221, -221, -221, -221, -221,
+     -221, -221,  270, -221, -221, -221, -221, -221, -221, -221,
+     -221, -221, -221, -221, -221, -221, -221, -221,  271,  271,
+      271,  271,  271,  271,  271,  271,  271,  271, -221, -221,
+     -221, -221, -221, -221, -221,  270,  270,  270,  270,  270,
+
+      270,  270,  270,  270,  270,  270,  270,  270,  270,  270,
+      270,  270,  270,  270,  270,  270,  270,  270,  270,  270,
+      270, -221, -221, -221, -221, -221, -221, -221, -221, -221,
+     -221, -221, -221, -221, -221, -221, -221, -221, -221, -221,
+     -221, -221, -221, -221, -221, -221, -221, -221, -221, -221,
+     -221, -221, -221, -221, -221, -221, -221, -221
+    },
+
+    {
+       33, -222, -222, -222, -222, -222, -222, -222, -222, -222,
+     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
+     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
+     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
+
+     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
+     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
+     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
+     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
+     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
+     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
+     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
+     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
+     -222, -222, -222, -222, -222, -222, -222, -222
+    },
+
+    {
+       33, -223, -223, -223, -223, -223, -223, -223, -223, -223,
+
+     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
+     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
+     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
+     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
+     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
+     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
+     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
+     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
+     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
+     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
+
+     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
+     -223, -223, -223, -223, -223, -223, -223, -223
+    },
+
+    {
+       33, -224, -224, -224, -224, -224, -224, -224, -224, -224,
+     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
+     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
+     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
+     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
+     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
+     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
+     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
+
+     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
+     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
+     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
+     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
+     -224, -224, -224, -224, -224, -224, -224, -224
+    },
+
+    {
+       33, -225, -225, -225, -225, -225, -225, -225, -225, -225,
+     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
+     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
+     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
+     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
+
+     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
+     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
+     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
+     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
+     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
+     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
+     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
+     -225, -225, -225, -225, -225, -225, -225, -225
+    },
+
+    {
+       33, -226, -226, -226, -226, -226, -226, -226, -226, -226,
+     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
+
+     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
+     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
+     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
+     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
+     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
+     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
+     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
+     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
+     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
+     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
+
+     -226, -226, -226, -226, -226, -226, -226, -226
+    },
+
+    {
+       33, -227, -227, -227, -227, -227, -227, -227, -227, -227,
+     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
+     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
+     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
+     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
+     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
+     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
+     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
+     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
+
+     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
+     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
+     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
+     -227, -227, -227, -227, -227, -227, -227, -227
+    },
+
+    {
+       33, -228, -228, -228, -228, -228, -228, -228, -228, -228,
+     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
+     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
+     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
+     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
+     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
+
+     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
+     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
+     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
+     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
+     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
+     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
+     -228, -228, -228, -228, -228, -228, -228, -228
+    },
+
+    {
+       33, -229, -229, -229, -229, -229, -229, -229, -229, -229,
+     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
+     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
+
+     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
+     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
+     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
+     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
+     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
+     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
+     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
+     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
+     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
+     -229, -229, -229, -229, -229, -229, -229, -229
+
+    },
+
+    {
+       33, -230, -230, -230, -230, -230, -230, -230, -230, -230,
+     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
+     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
+     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
+     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
+     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
+     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
+     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
+     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
+     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
+
+     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
+     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
+     -230, -230, -230, -230, -230, -230, -230, -230
+    },
+
+    {
+       33, -231, -231, -231, -231, -231, -231, -231, -231, -231,
+     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
+     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
+     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
+     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
+     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
+     -231, -231, -231, -231, -231,  272, -231, -231, -231, -231,
+
+     -231, -231, -231, -231, -231, -231, -231, -231, -231,  273,
+     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
+     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
+     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
+     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
+     -231, -231, -231, -231, -231, -231, -231, -231
+    },
+
+    {
+       33, -232, -232, -232, -232, -232, -232, -232, -232, -232,
+     -232, -232, -232, -232, -232, -232, -232, -232, -232, -232,
+     -232, -232, -232, -232, -232, -232, -232, -232, -232, -232,
+     -232, -232,  274, -232, -232, -232, -232, -232, -232, -232,
+
+     -232, -232, -232, -232, -232, -232, -232, -232, -232, -232,
+     -232, -232, -232, -232, -232, -232, -232, -232, -232, -232,
+     -232, -232, -232, -232, -232, -232, -232, -232, -232, -232,
+     -232, -232, -232, -232, -232, -232, -232, -232, -232, -232,
+     -232, -232, -232, -232, -232, -232, -232, -232, -232, -232,
+     -232, -232, -232, -232, -232, -232, -232, -232, -232, -232,
+     -232, -232, -232, -232, -232, -232, -232, -232, -232, -232,
+     -232, -232, -232, -232, -232, -232, -232, -232, -232, -232,
+     -232, -232, -232, -232, -232, -232, -232, -232
+    },
+
+    {
+       33, -233, -233, -233, -233, -233, -233, -233, -233, -233,
+
+     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
+     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
+     -233, -233,  275, -233, -233, -233, -233, -233, -233, -233,
+     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
+     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
+     -233, -233, -233, -233, -233,  275,  275,  275,  275,  275,
+      275,  275,  275,  275,  275,  275,  275,  275,  275,  275,
+      275,  275,  275,  275,  275,  275,  275,  275,  275,  275,
+      275, -233, -233, -233, -233, -233, -233, -233, -233, -233,
+     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
+
+     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
+     -233, -233, -233, -233, -233, -233, -233, -233
+    },
+
+    {
+       33, -234, -234, -234, -234, -234, -234, -234, -234, -234,
+     -234, -234, -234, -234, -234, -234, -234, -234, -234, -234,
+     -234, -234, -234, -234, -234, -234, -234, -234, -234, -234,
+     -234, -234, -234, -234, -234, -234, -234, -234, -234, -234,
+     -234, -234, -234, -234, -234, -234, -234, -234, -234, -234,
+     -234, -234, -234, -234, -234, -234, -234, -234, -234, -234,
+     -234, -234, -234, -234, -234, -234, -234, -234, -234, -234,
+     -234, -234, -234, -234, -234, -234, -234, -234, -234,  276,
+
+     -234, -234, -234, -234, -234, -234, -234, -234, -234, -234,
+     -234, -234, -234, -234, -234, -234, -234, -234, -234, -234,
+     -234, -234, -234, -234, -234, -234, -234, -234, -234, -234,
+     -234, -234, -234, -234, -234, -234, -234, -234, -234, -234,
+     -234, -234, -234, -234, -234, -234, -234, -234
+    },
+
+    {
+       33, -235, -235, -235, -235, -235, -235, -235, -235, -235,
+     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
+     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
+     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
+     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
+
+     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
+     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
+     -235, -235, -235, -235, -235, -235,  277, -235, -235, -235,
+     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
+     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
+     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
+     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
+     -235, -235, -235, -235, -235, -235, -235, -235
+    },
+
+    {
+       33, -236, -236, -236, -236, -236, -236, -236, -236, -236,
+     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
+
+     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
+     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
+     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
+     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
+     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
+     -236, -236, -236, -236, -236, -236,  278, -236, -236, -236,
+     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
+     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
+     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
+     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
+
+     -236, -236, -236, -236, -236, -236, -236, -236
+    },
+
+    {
+       33, -237, -237, -237, -237, -237, -237, -237, -237, -237,
+     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
+     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
+     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
+     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
+     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
+     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
+     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
+     -237, -237, -237, -237, -237, -237,  279, -237, -237, -237,
+
+     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
+     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
+     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
+     -237, -237, -237, -237, -237, -237, -237, -237
+    },
+
+    {
+       33, -238, -238, -238, -238, -238, -238, -238, -238, -238,
+     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
+     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
+     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
+     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
+     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
+
+     -238, -238, -238, -238, -238, -238,  280, -238, -238, -238,
+     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
+     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
+     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
+     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
+     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
+     -238, -238, -238, -238, -238, -238, -238, -238
+    },
+
+    {
+       33, -239, -239, -239, -239, -239, -239, -239, -239, -239,
+     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
+     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
+
+     -239, -239,  281, -239, -239, -239, -239, -239, -239, -239,
+     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
+     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
+     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
+     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
+     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
+     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
+     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
+     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
+     -239, -239, -239, -239, -239, -239, -239, -239
+
+    },
+
+    {
+       33, -240, -240, -240, -240, -240, -240, -240, -240, -240,
+     -240, -240, -240, -240, -240, -240, -240, -240, -240, -240,
+     -240, -240, -240, -240, -240, -240, -240, -240, -240, -240,
+     -240, -240, -240, -240, -240, -240, -240, -240, -240, -240,
+     -240, -240, -240, -240, -240, -240, -240, -240, -240, -240,
+     -240, -240, -240, -240, -240, -240, -240, -240, -240, -240,
+     -240, -240, -240, -240, -240, -240, -240, -240, -240, -240,
+     -240, -240, -240, -240, -240, -240, -240, -240, -240,  282,
+     -240, -240, -240, -240, -240, -240, -240, -240, -240, -240,
+     -240, -240, -240, -240, -240, -240, -240, -240, -240, -240,
+
+     -240, -240, -240, -240, -240, -240, -240, -240, -240, -240,
+     -240, -240, -240, -240, -240, -240, -240, -240, -240, -240,
+     -240, -240, -240, -240, -240, -240, -240, -240
+    },
+
+    {
+       33, -241, -241, -241, -241, -241, -241, -241, -241, -241,
+     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
+     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
+     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
+     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
+     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
+     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
+
+     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
+     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
+     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
+     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
+     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
+     -241, -241, -241, -241, -241, -241, -241, -241
+    },
+
+    {
+       33, -242, -242, -242, -242, -242, -242, -242, -242, -242,
+     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
+     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
+     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
+
+     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
+     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
+     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
+     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
+     -242, -242, -242,  283, -242, -242, -242, -242, -242, -242,
+     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
+     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
+     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
+     -242, -242, -242, -242, -242, -242, -242, -242
+    },
+
+    {
+       33, -243, -243, -243, -243, -243, -243, -243, -243, -243,
+
+     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
+     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
+     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
+     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
+     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
+     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
+     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
+     -243, -243, -243, -243, -243, -243, -243, -243, -243,  284,
+     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
+     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
+
+     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
+     -243, -243, -243, -243, -243, -243, -243, -243
+    },
+
+    {
+       33, -244, -244, -244, -244, -244, -244, -244, -244, -244,
+     -244, -244, -244, -244, -244, -244, -244, -244, -244, -244,
+     -244, -244, -244, -244, -244, -244, -244, -244, -244, -244,
+     -244, -244, -244, -244, -244, -244, -244, -244, -244, -244,
+     -244, -244, -244, -244, -244, -244, -244, -244, -244, -244,
+     -244, -244, -244, -244, -244, -244, -244, -244, -244, -244,
+     -244, -244, -244, -244, -244, -244, -244, -244, -244, -244,
+     -244, -244, -244, -244, -244, -244, -244, -244, -244, -244,
+
+     -244, -244,  285, -244, -244, -244, -244, -244, -244, -244,
+     -244, -244, -244, -244, -244, -244, -244, -244, -244, -244,
+     -244, -244, -244, -244, -244, -244, -244, -244, -244, -244,
+     -244, -244, -244, -244, -244, -244, -244, -244, -244, -244,
+     -244, -244, -244, -244, -244, -244, -244, -244
+    },
+
+    {
+       33, -245, -245, -245, -245, -245, -245, -245, -245, -245,
+     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
+     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
+     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
+     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
+
+     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
+     -245, -245, -245, -245, -245,  286, -245, -245, -245, -245,
+     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
+     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
+     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
+     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
+     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
+     -245, -245, -245, -245, -245, -245, -245, -245
+    },
+
+    {
+       33, -246, -246, -246, -246, -246, -246, -246, -246, -246,
+     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
+
+     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
+     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
+     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
+     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
+     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
+     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
+     -246, -246, -246, -246, -246, -246, -246, -246, -246,  287,
+     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
+     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
+     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
+
+     -246, -246, -246, -246, -246, -246, -246, -246
+    },
+
+    {
+       33, -247, -247, -247, -247, -247, -247, -247, -247, -247,
+     -247, -247, -247, -247, -247, -247, -247, -247, -247, -247,
+     -247, -247, -247, -247, -247, -247, -247, -247, -247, -247,
+     -247, -247, -247, -247, -247, -247, -247, -247, -247, -247,
+     -247, -247, -247, -247, -247, -247, -247, -247, -247, -247,
+     -247, -247, -247, -247, -247, -247, -247, -247, -247, -247,
+     -247, -247, -247, -247, -247, -247,  288, -247, -247, -247,
+     -247, -247, -247, -247, -247, -247, -247, -247, -247, -247,
+     -247, -247, -247, -247, -247, -247, -247, -247, -247, -247,
+
+     -247, -247, -247, -247, -247, -247, -247, -247, -247, -247,
+     -247, -247, -247, -247, -247, -247, -247, -247, -247, -247,
+     -247, -247, -247, -247, -247, -247, -247, -247, -247, -247,
+     -247, -247, -247, -247, -247, -247, -247, -247
+    },
+
+    {
+       33, -248, -248, -248, -248, -248, -248, -248, -248, -248,
+     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
+     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
+     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
+     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
+     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
+
+     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
+     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
+     -248, -248,  289, -248, -248, -248, -248, -248, -248, -248,
+     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
+     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
+     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
+     -248, -248, -248, -248, -248, -248, -248, -248
+    },
+
+    {
+       33, -249, -249, -249, -249, -249, -249, -249, -249, -249,
+     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
+     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
+
+     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
+     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
+     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
+     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
+     -249,  290, -249, -249, -249, -249, -249, -249, -249, -249,
+     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
+     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
+     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
+     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
+     -249, -249, -249, -249, -249, -249, -249, -249
+
+    },
+
+    {
+       33, -250, -250, -250, -250, -250, -250, -250, -250, -250,
+     -250, -250, -250, -250, -250, -250, -250, -250, -250, -250,
+     -250, -250, -250, -250, -250, -250, -250, -250, -250, -250,
+     -250, -250, -250, -250, -250, -250, -250, -250, -250, -250,
+     -250, -250, -250, -250, -250, -250, -250, -250, -250, -250,
+     -250, -250, -250, -250, -250, -250, -250, -250, -250, -250,
+     -250, -250, -250, -250, -250, -250, -250, -250, -250, -250,
+     -250, -250, -250, -250, -250, -250, -250, -250, -250, -250,
+     -250, -250, -250, -250, -250, -250, -250, -250, -250,  291,
+     -250, -250, -250, -250, -250, -250, -250, -250, -250, -250,
+
+     -250, -250, -250, -250, -250, -250, -250, -250, -250, -250,
+     -250, -250, -250, -250, -250, -250, -250, -250, -250, -250,
+     -250, -250, -250, -250, -250, -250, -250, -250
+    },
+
+    {
+       33, -251, -251, -251, -251, -251, -251, -251, -251, -251,
+     -251, -251, -251, -251, -251, -251, -251, -251, -251, -251,
+     -251, -251, -251, -251, -251, -251, -251, -251, -251, -251,
+     -251, -251, -251, -251, -251, -251, -251, -251, -251, -251,
+     -251, -251, -251, -251, -251, -251, -251, -251, -251, -251,
+     -251, -251, -251, -251, -251, -251, -251, -251, -251, -251,
+     -251, -251, -251, -251, -251, -251, -251, -251, -251, -251,
+
+      292, -251, -251, -251, -251, -251, -251, -251, -251, -251,
+     -251, -251, -251, -251, -251, -251, -251, -251, -251, -251,
+     -251, -251, -251, -251, -251, -251, -251, -251, -251, -251,
+     -251, -251, -251, -251, -251, -251, -251, -251, -251, -251,
+     -251, -251, -251, -251, -251, -251, -251, -251, -251, -251,
+     -251, -251, -251, -251, -251, -251, -251, -251
+    },
+
+    {
+       33, -252, -252, -252, -252, -252, -252, -252, -252, -252,
+     -252, -252, -252, -252, -252, -252, -252, -252, -252, -252,
+     -252, -252, -252, -252, -252, -252, -252, -252, -252, -252,
+     -252, -252, -252, -252, -252, -252, -252, -252, -252, -252,
+
+     -252, -252, -252, -252, -252, -252, -252, -252, -252, -252,
+     -252, -252, -252, -252, -252, -252, -252, -252, -252, -252,
+     -252, -252, -252, -252, -252, -252, -252,  293, -252, -252,
+     -252, -252, -252, -252, -252, -252, -252, -252, -252, -252,
+     -252, -252, -252, -252, -252, -252, -252, -252, -252, -252,
+     -252, -252, -252, -252, -252, -252, -252, -252, -252, -252,
+     -252, -252, -252, -252, -252, -252, -252, -252, -252, -252,
+     -252, -252, -252, -252, -252, -252, -252, -252, -252, -252,
+     -252, -252, -252, -252, -252, -252, -252, -252
+    },
+
+    {
+       33, -253, -253, -253, -253, -253, -253, -253, -253, -253,
+
+     -253, -253, -253, -253, -253, -253, -253, -253, -253, -253,
+     -253, -253, -253, -253, -253, -253, -253, -253, -253, -253,
+     -253, -253, -253, -253, -253, -253, -253, -253, -253, -253,
+     -253, -253, -253, -253, -253, -253, -253, -253, -253, -253,
+     -253, -253, -253, -253, -253, -253, -253, -253, -253, -253,
+     -253, -253, -253, -253, -253, -253, -253, -253, -253,  294,
+     -253, -253, -253, -253, -253, -253, -253, -253, -253, -253,
+     -253, -253, -253, -253, -253, -253, -253, -253, -253, -253,
+     -253, -253, -253, -253, -253, -253, -253, -253, -253, -253,
+     -253, -253, -253, -253, -253, -253, -253, -253, -253, -253,
+
+     -253, -253, -253, -253, -253, -253, -253, -253, -253, -253,
+     -253, -253, -253, -253, -253, -253, -253, -253
+    },
+
+    {
+       33, -254, -254, -254, -254, -254, -254, -254, -254, -254,
+     -254, -254, -254, -254, -254, -254, -254, -254, -254, -254,
+     -254, -254, -254, -254, -254, -254, -254, -254, -254, -254,
+     -254, -254, -254, -254, -254, -254, -254, -254, -254, -254,
+     -254, -254, -254, -254, -254, -254, -254, -254, -254, -254,
+     -254, -254, -254, -254, -254, -254, -254, -254, -254, -254,
+     -254, -254, -254, -254, -254, -254, -254, -254, -254, -254,
+     -254, -254, -254, -254, -254, -254, -254,  295, -254, -254,
+
+     -254, -254, -254, -254, -254, -254, -254, -254, -254, -254,
+     -254, -254, -254, -254, -254, -254, -254, -254, -254, -254,
+     -254, -254, -254, -254, -254, -254, -254, -254, -254, -254,
+     -254, -254, -254, -254, -254, -254, -254, -254, -254, -254,
+     -254, -254, -254, -254, -254, -254, -254, -254
+    },
+
+    {
+       33, -255, -255, -255, -255, -255, -255, -255, -255, -255,
+     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
+     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
+     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
+     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
+
+     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
+     -255, -255, -255, -255, -255, -255, -255,  296, -255, -255,
+     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
+     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
+     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
+     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
+     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
+     -255, -255, -255, -255, -255, -255, -255, -255
+    },
+
+    {
+       33, -256, -256, -256, -256, -256, -256, -256, -256, -256,
+     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
+
+     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
+     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
+     -256, -256, -256, -256, -256, -256, -256, -256,  297,  297,
+      297,  297,  297,  297,  297,  297,  297,  297, -256, -256,
+     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
+     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
+     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
+     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
+     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
+     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
+
+     -256, -256, -256, -256, -256, -256, -256, -256
+    },
+
+    {
+       33, -257, -257, -257, -257, -257, -257, -257, -257, -257,
+     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
+     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
+     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
+     -257, -257, -257, -257, -257, -257, -257, -257, -257,  298,
+      298,  298,  298,  298,  298,  298,  298,  298, -257, -257,
+     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
+     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
+     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
+
+     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
+     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
+     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
+     -257, -257, -257, -257, -257, -257, -257, -257
+    },
+
+    {
+       33, -258, -258, -258, -258, -258, -258, -258, -258, -258,
+     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
+     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
+     -258, -258,  299, -258, -258, -258, -258, -258, -258, -258,
+     -258, -258, -258, -258, -258, -258, -258, -258,  300,  300,
+      300,  300,  300,  300,  300,  300,  300,  300, -258, -258,
+
+     -258, -258, -258, -258, -258,  299,  299,  299,  299,  299,
+      299,  299,  299,  299,  299,  299,  299,  299,  299,  299,
+      299,  299,  299,  299,  299,  299,  299,  299,  299,  299,
+      299, -258, -258, -258, -258, -258, -258, -258, -258, -258,
+     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
+     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
+     -258, -258, -258, -258, -258, -258, -258, -258
+    },
+
+    {
+       33, -259, -259, -259, -259, -259, -259, -259, -259, -259,
+     -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
+     -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
+
+     -259, -259,  301, -259, -259, -259, -259, -259, -259, -259,
+     -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
+     -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
+     -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
+     -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
+     -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
+     -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
+     -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
+     -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
+     -259, -259, -259, -259, -259, -259, -259, -259
+
+    },
+
+    {
+       33, -260, -260, -260, -260, -260, -260, -260, -260, -260,
+     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
+     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
+     -260, -260,  302, -260, -260, -260, -260, -260, -260, -260,
+     -260, -260, -260, -260, -260, -260, -260, -260,  303,  303,
+      303,  303,  303,  303,  303,  303,  303,  303, -260, -260,
+     -260, -260, -260, -260, -260,  302,  302,  302,  302,  302,
+      302,  302,  302,  302,  302,  302,  302,  302,  302,  302,
+      302,  302,  302,  302,  302,  302,  302,  302,  302,  302,
+      302, -260, -260, -260, -260, -260, -260, -260, -260, -260,
+
+     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
+     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
+     -260, -260, -260, -260, -260, -260, -260, -260
+    },
+
+    {
+       33, -261, -261, -261, -261, -261, -261, -261, -261, -261,
+     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
+     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
+     -261, -261,  304, -261, -261, -261, -261, -261, -261, -261,
+     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
+     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
+     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
+
+     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
+     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
+     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
+     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
+     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
+     -261, -261, -261, -261, -261, -261, -261, -261
+    },
+
+    {
+       33, -262, -262, -262, -262, -262, -262, -262, -262, -262,
+     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
+     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
+     -262, -262,  305, -262, -262, -262, -262, -262, -262, -262,
+
+     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
+     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
+     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
+     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
+     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
+     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
+     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
+     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
+     -262, -262, -262, -262, -262, -262, -262, -262
+    },
+
+    {
+       33, -263, -263, -263, -263, -263, -263, -263, -263, -263,
+
+     -263, -263, -263, -263, -263, -263, -263, -263, -263, -263,
+     -263, -263, -263, -263, -263, -263, -263, -263, -263, -263,
+     -263, -263,  306, -263, -263, -263, -263, -263, -263, -263,
+     -263, -263, -263, -263, -263, -263, -263, -263,  307,  307,
+      307,  307,  307,  307,  307,  307,  307,  307, -263, -263,
+     -263, -263, -263, -263, -263,  306,  306,  306,  306,  306,
+      306,  306,  306,  306,  306,  306,  306,  306,  306,  306,
+      306,  306,  306,  306,  306,  306,  306,  306,  306,  306,
+      306, -263, -263, -263, -263, -263, -263, -263, -263, -263,
+     -263, -263, -263, -263, -263, -263, -263, -263, -263, -263,
+
+     -263, -263, -263, -263, -263, -263, -263, -263, -263, -263,
+     -263, -263, -263, -263, -263, -263, -263, -263
+    },
+
+    {
+       33, -264, -264, -264, -264, -264, -264, -264, -264, -264,
+     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
+     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
+     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
+     -264, -264, -264, -264, -264, -264, -264, -264,  308,  308,
+      308,  308,  308,  308,  308,  308,  308,  308, -264, -264,
+     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
+     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
+
+     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
+     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
+     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
+     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
+     -264, -264, -264, -264, -264, -264, -264, -264
+    },
+
+    {
+       33, -265, -265, -265, -265, -265, -265, -265, -265, -265,
+     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
+     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
+     -265, -265,  309, -265, -265, -265, -265, -265, -265, -265,
+     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
+
+     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
+     -265, -265, -265, -265, -265,  309,  309,  309,  309,  309,
+      309,  309,  309,  309,  309,  309,  309,  309,  309,  309,
+      309,  309,  309,  309,  309,  309,  309,  309,  309,  309,
+      309, -265, -265, -265, -265, -265, -265, -265, -265, -265,
+     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
+     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
+     -265, -265, -265, -265, -265, -265, -265, -265
+    },
+
+    {
+       33, -266, -266, -266, -266, -266, -266, -266, -266, -266,
+     -266, -266, -266, -266, -266, -266, -266, -266, -266, -266,
+
+     -266, -266, -266, -266, -266, -266, -266, -266, -266, -266,
+     -266, -266,  309, -266, -266, -266, -266, -266, -266, -266,
+     -266, -266, -266, -266, -266, -266, -266, -266,  310,  310,
+      310,  310,  310,  310,  310,  310,  310,  310, -266, -266,
+     -266, -266, -266, -266, -266,  309,  309,  309,  309,  309,
+      309,  309,  309,  309,  309,  309,  309,  309,  309,  309,
+      309,  309,  309,  309,  309,  309,  309,  309,  309,  309,
+      309, -266, -266, -266, -266, -266, -266, -266, -266, -266,
+     -266, -266, -266, -266, -266, -266, -266, -266, -266, -266,
+     -266, -266, -266, -266, -266, -266, -266, -266, -266, -266,
+
+     -266, -266, -266, -266, -266, -266, -266, -266
+    },
+
+    {
+       33, -267, -267, -267, -267, -267, -267, -267, -267, -267,
+     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
+     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
+     -267, -267,  311, -267, -267, -267, -267, -267, -267, -267,
+     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
+     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
+     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
+     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
+     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
+
+     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
+     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
+     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
+     -267, -267, -267, -267, -267, -267, -267, -267
+    },
+
+    {
+       33, -268, -268, -268, -268, -268, -268, -268, -268, -268,
+     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
+     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
+     -268, -268,  312, -268, -268, -268, -268, -268, -268, -268,
+     -268, -268, -268, -268, -268, -268, -268, -268,  313,  313,
+      313,  313,  313,  313,  313,  313,  313,  313, -268, -268,
+
+     -268, -268, -268, -268, -268,  312,  312,  312,  312,  312,
+      312,  312,  312,  312,  312,  312,  312,  312,  312,  312,
+      312,  312,  312,  312,  312,  312,  312,  312,  312,  312,
+      312, -268, -268, -268, -268, -268, -268, -268, -268, -268,
+     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
+     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
+     -268, -268, -268, -268, -268, -268, -268, -268
+    },
+
+    {
+       33, -269, -269, -269, -269, -269, -269, -269, -269, -269,
+     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
+     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
+
+     -269, -269,  314, -269, -269, -269, -269, -269, -269, -269,
+     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
+     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
+     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
+     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
+     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
+     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
+     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
+     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
+     -269, -269, -269, -269, -269, -269, -269, -269
+
+    },
+
+    {
+       33, -270, -270, -270, -270, -270, -270, -270, -270, -270,
+     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
+     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
+     -270, -270,  315, -270, -270, -270, -270, -270, -270, -270,
+     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
+     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
+     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
+     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
+     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
+     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
+
+     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
+     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
+     -270, -270, -270, -270, -270, -270, -270, -270
+    },
+
+    {
+       33, -271, -271, -271, -271, -271, -271, -271, -271, -271,
+     -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
+     -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
+     -271, -271,  316, -271, -271, -271, -271, -271, -271, -271,
+     -271, -271, -271, -271, -271, -271, -271, -271,  317,  317,
+      317,  317,  317,  317,  317,  317,  317,  317, -271, -271,
+     -271, -271, -271, -271, -271,  316,  316,  316,  316,  316,
+
+      316,  316,  316,  316,  316,  316,  316,  316,  316,  316,
+      316,  316,  316,  316,  316,  316,  316,  316,  316,  316,
+      316, -271, -271, -271, -271, -271, -271, -271, -271, -271,
+     -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
+     -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
+     -271, -271, -271, -271, -271, -271, -271, -271
+    },
+
+    {
+       33, -272, -272, -272, -272, -272, -272, -272, -272, -272,
+     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
+     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
+     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
+
+     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
+     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
+     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
+     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
+     -272, -272, -272, -272, -272, -272,  318, -272, -272, -272,
+     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
+     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
+     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
+     -272, -272, -272, -272, -272, -272, -272, -272
+    },
+
+    {
+       33, -273, -273, -273, -273, -273, -273, -273, -273, -273,
+
+     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
+     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
+     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
+     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
+     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
+     -273, -273, -273, -273, -273, -273,  319, -273, -273, -273,
+     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
+     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
+     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
+     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
+
+     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
+     -273, -273, -273, -273, -273, -273, -273, -273
+    },
+
+    {
+       33, -274, -274, -274, -274, -274, -274, -274, -274, -274,
+     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
+     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
+     -274, -274,  320, -274, -274, -274, -274, -274, -274, -274,
+     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
+     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
+     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
+     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
+
+     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
+     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
+     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
+     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
+     -274, -274, -274, -274, -274, -274, -274, -274
+    },
+
+    {
+       33, -275, -275, -275, -275, -275, -275, -275, -275, -275,
+     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
+     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
+     -275, -275,  321, -275, -275, -275, -275, -275, -275, -275,
+     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
+
+     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
+     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
+     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
+     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
+     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
+     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
+     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
+     -275, -275, -275, -275, -275, -275, -275, -275
+    },
+
+    {
+       33, -276, -276, -276, -276, -276, -276, -276, -276, -276,
+     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
+
+     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
+     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
+     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
+     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
+     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
+     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
+     -276, -276, -276, -276, -276, -276, -276, -276,  322, -276,
+     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
+     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
+     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
+
+     -276, -276, -276, -276, -276, -276, -276, -276
+    },
+
+    {
+       33, -277, -277, -277, -277, -277, -277, -277, -277, -277,
+     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
+     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
+     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
+     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
+     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
+     -277, -277, -277, -277, -277, -277, -277, -277, -277,  323,
+     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
+     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
+
+     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
+     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
+     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
+     -277, -277, -277, -277, -277, -277, -277, -277
+    },
+
+    {
+       33, -278, -278, -278, -278, -278, -278, -278, -278, -278,
+     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
+     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
+     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
+     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
+     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
+
+     -278, -278, -278, -278, -278, -278, -278, -278, -278,  324,
+     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
+     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
+     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
+     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
+     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
+     -278, -278, -278, -278, -278, -278, -278, -278
+    },
+
+    {
+       33, -279, -279, -279, -279, -279, -279, -279, -279, -279,
+     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
+     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
+
+     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
+     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
+     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
+     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
+     -279,  325, -279, -279, -279, -279, -279, -279, -279, -279,
+     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
+     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
+     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
+     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
+     -279, -279, -279, -279, -279, -279, -279, -279
+
+    },
+
+    {
+       33, -280, -280, -280, -280, -280, -280, -280, -280, -280,
+     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
+     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
+     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
+     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
+     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
+     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
+     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
+     -280, -280, -280,  326, -280, -280, -280, -280, -280, -280,
+     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
+
+     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
+     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
+     -280, -280, -280, -280, -280, -280, -280, -280
+    },
+
+    {
+       33, -281, -281, -281, -281, -281, -281, -281, -281, -281,
+     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
+     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
+     -281, -281,  327, -281, -281, -281, -281, -281, -281, -281,
+     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
+     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
+     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
+
+     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
+     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
+     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
+     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
+     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
+     -281, -281, -281, -281, -281, -281, -281, -281
+    },
+
+    {
+       33, -282, -282, -282, -282, -282, -282, -282, -282, -282,
+     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
+     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
+     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
+
+     -282, -282, -282, -282, -282,  328, -282, -282, -282, -282,
+     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
+     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
+     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
+     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
+     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
+     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
+     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
+     -282, -282, -282, -282, -282, -282, -282, -282
+    },
+
+    {
+       33, -283, -283, -283, -283, -283, -283, -283, -283, -283,
+
+     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
+     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
+     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
+     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
+     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
+     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
+     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
+     -283, -283, -283, -283, -283, -283, -283, -283, -283,  329,
+     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
+     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
+
+     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
+     -283, -283, -283, -283, -283, -283, -283, -283
+    },
+
+    {
+       33, -284, -284, -284, -284, -284, -284, -284, -284, -284,
+     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
+     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
+     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
+     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
+     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
+     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
+     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
+
+     -284, -284, -284,  330, -284, -284, -284, -284, -284, -284,
+     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
+     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
+     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
+     -284, -284, -284, -284, -284, -284, -284, -284
+    },
+
+    {
+       33, -285, -285, -285, -285, -285, -285, -285, -285, -285,
+     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
+     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
+     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
+     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
+
+     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
+     -285, -285, -285, -285, -285, -285, -285, -285, -285,  331,
+     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
+     -285,  332, -285, -285, -285, -285, -285, -285, -285, -285,
+     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
+     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
+     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
+     -285, -285, -285, -285, -285, -285, -285, -285
+    },
+
+    {
+       33, -286, -286, -286, -286, -286, -286, -286, -286, -286,
+     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
+
+     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
+     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
+     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
+     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
+     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
+     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
+     -286, -286, -286, -286, -286, -286,  333, -286, -286, -286,
+     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
+     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
+     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
+
+     -286, -286, -286, -286, -286, -286, -286, -286
+    },
+
+    {
+       33, -287, -287, -287, -287, -287, -287, -287, -287, -287,
+     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
+     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
+     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
+     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
+     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
+     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
+     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
+     -287, -287, -287,  334, -287, -287, -287, -287, -287, -287,
+
+     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
+     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
+     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
+     -287, -287, -287, -287, -287, -287, -287, -287
+    },
+
+    {
+       33, -288, -288, -288, -288, -288, -288, -288, -288, -288,
+     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
+     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
+     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
+     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
+     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
+
+     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
+     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
+     -288, -288, -288,  335, -288, -288, -288, -288, -288, -288,
+     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
+     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
+     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
+     -288, -288, -288, -288, -288, -288, -288, -288
+    },
+
+    {
+       33, -289, -289, -289, -289, -289, -289, -289, -289, -289,
+     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
+     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
+
+     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
+     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
+     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
+     -289, -289, -289, -289, -289, -289, -289,  336, -289, -289,
+     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
+     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
+     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
+     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
+     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
+     -289, -289, -289, -289, -289, -289, -289, -289
+
+    },
+
+    {
+       33, -290, -290, -290, -290, -290, -290, -290, -290, -290,
+     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
+     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
+     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
+     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
+     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
+     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
+     -290, -290, -290, -290, -290, -290,  337, -290, -290, -290,
+     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
+     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
+
+     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
+     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
+     -290, -290, -290, -290, -290, -290, -290, -290
+    },
+
+    {
+       33, -291, -291, -291, -291, -291, -291, -291, -291, -291,
+     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
+     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
+     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
+     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
+     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
+     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
+
+     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
+     -291, -291, -291,  338, -291, -291, -291, -291, -291, -291,
+     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
+     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
+     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
+     -291, -291, -291, -291, -291, -291, -291, -291
+    },
+
+    {
+       33, -292, -292, -292, -292, -292, -292, -292, -292, -292,
+     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
+     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
+     -292, -292,  339, -292, -292, -292, -292, -292, -292, -292,
+
+     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
+     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
+     -292, -292, -292, -292, -292,  339,  339,  339,  339,  339,
+      339,  339,  339,  339,  339,  339,  339,  339,  339,  339,
+      339,  339,  339,  339,  339,  339,  339,  339,  339,  339,
+      339, -292, -292, -292, -292, -292, -292, -292, -292, -292,
+     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
+     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
+     -292, -292, -292, -292, -292, -292, -292, -292
+    },
+
+    {
+       33, -293, -293, -293, -293, -293, -293, -293, -293, -293,
+
+     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
+     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
+     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
+     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
+     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
+     -293, -293, -293, -293, -293, -293, -293, -293, -293,  340,
+     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
+     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
+     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
+     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
+
+     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
+     -293, -293, -293, -293, -293, -293, -293, -293
+    },
+
+    {
+       33, -294, -294, -294, -294, -294, -294, -294, -294, -294,
+     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
+     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
+     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
+     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
+     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
+     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
+     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
+
+     -294, -294, -294,  341, -294, -294, -294, -294, -294, -294,
+     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
+     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
+     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
+     -294, -294, -294, -294, -294, -294, -294, -294
+    },
+
+    {
+       33, -295, -295, -295, -295, -295, -295, -295, -295, -295,
+     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
+     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
+     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
+     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
+
+     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
+     -295, -295, -295, -295, -295, -295, -295, -295, -295,  342,
+     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
+     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
+     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
+     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
+     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
+     -295, -295, -295, -295, -295, -295, -295, -295
+    },
+
+    {
+       33, -296, -296, -296, -296, -296, -296, -296, -296, -296,
+     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
+
+     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
+     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
+     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
+     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
+     -296, -296, -296, -296, -296, -296, -296, -296, -296,  343,
+     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
+     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
+     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
+     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
+     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
+
+     -296, -296, -296, -296, -296, -296, -296, -296
+    },
+
+    {
+       33, -297, -297, -297, -297, -297, -297, -297, -297, -297,
+     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
+     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
+     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
+     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
+     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
+     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
+     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
+     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
+
+     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
+     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
+     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
+     -297, -297, -297, -297, -297, -297, -297, -297
+    },
+
+    {
+       33, -298, -298, -298, -298, -298, -298, -298, -298, -298,
+     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
+     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
+     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
+     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
+     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
+
+     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
+     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
+     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
+     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
+     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
+     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
+     -298, -298, -298, -298, -298, -298, -298, -298
+    },
+
+    {
+       33, -299, -299, -299, -299, -299, -299, -299, -299, -299,
+     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
+     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
+
+     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
+     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
+     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
+     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
+     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
+     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
+     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
+     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
+     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
+     -299, -299, -299, -299, -299, -299, -299, -299
+
+    },
+
+    {
+       33, -300, -300, -300, -300, -300, -300, -300, -300, -300,
+     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
+     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
+     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
+     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
+     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
+     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
+     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
+     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
+     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
+
+     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
+     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
+     -300, -300, -300, -300, -300, -300, -300, -300
+    },
+
+    {
+       33, -301, -301, -301, -301, -301, -301, -301, -301, -301,
+     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
+     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
+     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
+     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
+     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
+     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
+
+     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
+     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
+     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
+     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
+     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
+     -301, -301, -301, -301, -301, -301, -301, -301
+    },
+
+    {
+       33, -302, -302, -302, -302, -302, -302, -302, -302, -302,
+     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
+     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
+     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
+
+     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
+     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
+     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
+     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
+     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
+     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
+     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
+     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
+     -302, -302, -302, -302, -302, -302, -302, -302
+    },
+
+    {
+       33, -303, -303, -303, -303, -303, -303, -303, -303, -303,
+
+     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
+     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
+     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
+     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
+     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
+     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
+     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
+     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
+     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
+     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
+
+     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
+     -303, -303, -303, -303, -303, -303, -303, -303
+    },
+
+    {
+       33, -304, -304, -304, -304, -304, -304, -304, -304, -304,
+     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
+     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
+     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
+     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
+     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
+     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
+     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
+
+     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
+     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
+     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
+     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
+     -304, -304, -304, -304, -304, -304, -304, -304
+    },
+
+    {
+       33, -305, -305, -305, -305, -305, -305, -305, -305, -305,
+     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
+     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
+     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
+     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
+
+     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
+     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
+     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
+     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
+     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
+     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
+     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
+     -305, -305, -305, -305, -305, -305, -305, -305
+    },
+
+    {
+       33, -306, -306, -306, -306, -306, -306, -306, -306, -306,
+     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
+
+     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
+     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
+     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
+     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
+     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
+     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
+     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
+     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
+     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
+     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
+
+     -306, -306, -306, -306, -306, -306, -306, -306
+    },
+
+    {
+       33, -307, -307, -307, -307, -307, -307, -307, -307, -307,
+     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
+     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
+     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
+     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
+     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
+     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
+     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
+     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
+
+     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
+     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
+     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
+     -307, -307, -307, -307, -307, -307, -307, -307
+    },
+
+    {
+       33, -308, -308, -308, -308, -308, -308, -308, -308, -308,
+     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
+     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
+     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
+     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
+     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
+
+     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
+     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
+     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
+     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
+     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
+     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
+     -308, -308, -308, -308, -308, -308, -308, -308
+    },
+
+    {
+       33, -309, -309, -309, -309, -309, -309, -309, -309, -309,
+     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
+     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
+
+     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
+     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
+     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
+     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
+     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
+     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
+     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
+     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
+     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
+     -309, -309, -309, -309, -309, -309, -309, -309
+
+    },
+
+    {
+       33, -310, -310, -310, -310, -310, -310, -310, -310, -310,
+     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
+     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
+     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
+     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
+     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
+     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
+     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
+     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
+     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
+
+     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
+     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
+     -310, -310, -310, -310, -310, -310, -310, -310
+    },
+
+    {
+       33, -311, -311, -311, -311, -311, -311, -311, -311, -311,
+     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
+     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
+     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
+     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
+     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
+     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
+
+     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
+     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
+     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
+     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
+     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
+     -311, -311, -311, -311, -311, -311, -311, -311
+    },
+
+    {
+       33, -312, -312, -312, -312, -312, -312, -312, -312, -312,
+     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
+     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
+     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
+
+     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
+     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
+     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
+     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
+     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
+     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
+     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
+     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
+     -312, -312, -312, -312, -312, -312, -312, -312
+    },
+
+    {
+       33, -313, -313, -313, -313, -313, -313, -313, -313, -313,
+
+     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
+     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
+     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
+     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
+     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
+     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
+     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
+     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
+     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
+     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
+
+     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
+     -313, -313, -313, -313, -313, -313, -313, -313
+    },
+
+    {
+       33, -314, -314, -314, -314, -314, -314, -314, -314, -314,
+     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
+     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
+     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
+     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
+     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
+     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
+     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
+
+     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
+     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
+     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
+     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
+     -314, -314, -314, -314, -314, -314, -314, -314
+    },
+
+    {
+       33, -315, -315, -315, -315, -315, -315, -315, -315, -315,
+     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
+     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
+     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
+     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
+
+     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
+     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
+     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
+     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
+     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
+     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
+     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
+     -315, -315, -315, -315, -315, -315, -315, -315
+    },
+
+    {
+       33, -316, -316, -316, -316, -316, -316, -316, -316, -316,
+     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
+
+     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
+     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
+     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
+     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
+     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
+     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
+     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
+     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
+     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
+     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
+
+     -316, -316, -316, -316, -316, -316, -316, -316
+    },
+
+    {
+       33, -317, -317, -317, -317, -317, -317, -317, -317, -317,
+     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
+     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
+     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
+     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
+     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
+     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
+     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
+     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
+
+     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
+     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
+     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
+     -317, -317, -317, -317, -317, -317, -317, -317
+    },
+
+    {
+       33, -318, -318, -318, -318, -318, -318, -318, -318, -318,
+     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
+     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
+     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
+     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
+     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
+
+     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
+     -318,  344, -318, -318, -318, -318, -318, -318, -318, -318,
+     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
+     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
+     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
+     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
+     -318, -318, -318, -318, -318, -318, -318, -318
+    },
+
+    {
+       33, -319, -319, -319, -319, -319, -319, -319, -319, -319,
+     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
+     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
+
+     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
+     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
+     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
+     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
+     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
+     -319, -319, -319,  345, -319, -319, -319, -319, -319, -319,
+     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
+     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
+     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
+     -319, -319, -319, -319, -319, -319, -319, -319
+
+    },
+
+    {
+       33, -320, -320, -320, -320, -320, -320, -320, -320, -320,
+     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
+     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
+     -320, -320,  346, -320, -320, -320, -320, -320, -320, -320,
+     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
+     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
+     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
+     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
+     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
+     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
+
+     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
+     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
+     -320, -320, -320, -320, -320, -320, -320, -320
+    },
+
+    {
+       33, -321, -321, -321, -321, -321, -321, -321, -321, -321,
+     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
+     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
+     -321, -321,  347, -321, -321, -321, -321, -321, -321, -321,
+     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
+     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
+     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
+
+     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
+     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
+     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
+     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
+     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
+     -321, -321, -321, -321, -321, -321, -321, -321
+    },
+
+    {
+       33, -322, -322, -322, -322, -322, -322, -322, -322, -322,
+     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
+     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
+     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
+
+     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
+     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
+     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
+     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
+     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
+     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
+     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
+     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
+     -322, -322, -322, -322, -322, -322, -322, -322
+    },
+
+    {
+       33, -323, -323, -323, -323, -323, -323, -323, -323, -323,
+
+     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
+     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
+     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
+     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
+     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
+     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
+     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
+     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
+     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
+     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
+
+     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
+     -323, -323, -323, -323, -323, -323, -323, -323
+    },
+
+    {
+       33, -324, -324, -324, -324, -324, -324, -324, -324, -324,
+     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
+     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
+     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
+     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
+     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
+     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
+     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
+
+     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
+     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
+     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
+     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
+     -324, -324, -324, -324, -324, -324, -324, -324
+    },
+
+    {
+       33, -325, -325, -325, -325, -325, -325, -325, -325, -325,
+     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
+     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
+     -325, -325,  348, -325, -325, -325, -325, -325, -325, -325,
+     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
+
+     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
+     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
+     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
+     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
+     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
+     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
+     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
+     -325, -325, -325, -325, -325, -325, -325, -325
+    },
+
+    {
+       33, -326, -326, -326, -326, -326, -326, -326, -326, -326,
+     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
+
+     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
+     -326, -326,  349, -326, -326, -326, -326, -326, -326, -326,
+     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
+     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
+     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
+     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
+     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
+     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
+     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
+     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
+
+     -326, -326, -326, -326, -326, -326, -326, -326
+    },
+
+    {
+       33, -327, -327, -327, -327, -327, -327, -327, -327, -327,
+     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
+     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
+     -327, -327,  350, -327, -327, -327, -327, -327, -327, -327,
+     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
+     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
+     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
+     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
+     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
+
+     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
+     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
+     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
+     -327, -327, -327, -327, -327, -327, -327, -327
+    },
+
+    {
+       33, -328, -328, -328, -328, -328, -328, -328, -328, -328,
+     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
+     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
+     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
+     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
+     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
+
+     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
+     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
+     -328, -328, -328, -328, -328, -328, -328, -328,  351,  352,
+      353, -328, -328, -328, -328, -328, -328, -328, -328, -328,
+     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
+     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
+     -328, -328, -328, -328, -328, -328, -328, -328
+    },
+
+    {
+       33, -329, -329, -329, -329, -329, -329, -329, -329, -329,
+     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
+     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
+
+     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
+     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
+     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
+     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
+     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
+     -329, -329, -329,  354, -329, -329, -329, -329, -329, -329,
+     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
+     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
+     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
+     -329, -329, -329, -329, -329, -329, -329, -329
+
+    },
+
+    {
+       33, -330, -330, -330, -330, -330, -330, -330, -330, -330,
+     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
+     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
+     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
+     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
+     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
+     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
+     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
+     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
+     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
+
+     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
+     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
+     -330, -330, -330, -330, -330, -330, -330, -330
+    },
+
+    {
+       33, -331, -331, -331, -331, -331, -331, -331, -331, -331,
+     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
+     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
+     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
+     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
+     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
+     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
+
+     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
+     -331,  355, -331, -331, -331, -331, -331, -331, -331, -331,
+     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
+     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
+     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
+     -331, -331, -331, -331, -331, -331, -331, -331
+    },
+
+    {
+       33, -332, -332, -332, -332, -332, -332, -332, -332, -332,
+     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
+     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
+     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
+
+     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
+     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
+     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
+     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
+     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
+     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
+     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
+     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
+     -332, -332, -332, -332, -332, -332, -332, -332
+    },
+
+    {
+       33, -333, -333, -333, -333, -333, -333, -333, -333, -333,
+
+     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
+     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
+     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
+     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
+     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
+     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
+     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
+     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
+     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
+     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
+
+     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
+     -333, -333, -333, -333, -333, -333, -333, -333
+    },
+
+    {
+       33, -334, -334, -334, -334, -334, -334, -334, -334, -334,
+     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
+     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
+     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
+     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
+     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
+     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
+     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
+
+     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
+     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
+     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
+     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
+     -334, -334, -334, -334, -334, -334, -334, -334
+    },
+
+    {
+       33, -335, -335, -335, -335, -335, -335, -335, -335, -335,
+     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
+     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
+     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
+     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
+
+     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
+     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
+     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
+     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
+     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
+     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
+     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
+     -335, -335, -335, -335, -335, -335, -335, -335
+    },
+
+    {
+       33, -336, -336, -336, -336, -336, -336, -336, -336, -336,
+     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
+
+     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
+     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
+     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
+     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
+     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
+     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
+     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
+     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
+     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
+     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
+
+     -336, -336, -336, -336, -336, -336, -336, -336
+    },
+
+    {
+       33, -337, -337, -337, -337, -337, -337, -337, -337, -337,
+     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
+     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
+     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
+     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
+     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
+     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
+     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
+     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
+
+     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
+     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
+     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
+     -337, -337, -337, -337, -337, -337, -337, -337
+    },
+
+    {
+       33, -338, -338, -338, -338, -338, -338, -338, -338, -338,
+     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
+     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
+     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
+     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
+     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
+
+     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
+     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
+     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
+     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
+     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
+     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
+     -338, -338, -338, -338, -338, -338, -338, -338
+    },
+
+    {
+       33, -339, -339, -339, -339, -339, -339, -339, -339, -339,
+     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
+     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
+
+     -339, -339,  356, -339, -339, -339, -339, -339, -339, -339,
+     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
+     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
+     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
+     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
+     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
+     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
+     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
+     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
+     -339, -339, -339, -339, -339, -339, -339, -339
+
+    },
+
+    {
+       33, -340, -340, -340, -340, -340, -340, -340, -340, -340,
+     -340, -340, -340, -340, -340, -340, -340, -340, -340, -340,
+     -340, -340, -340, -340, -340, -340, -340, -340, -340, -340,
+     -340, -340,  357, -340, -340, -340, -340, -340, -340, -340,
+     -340, -340, -340, -340, -340, -340, -340, -340, -340, -340,
+     -340, -340, -340, -340, -340, -340, -340, -340, -340, -340,
+     -340, -340, -340, -340, -340,  357,  357,  357,  357,  357,
+      357,  357,  357,  357,  357,  357,  357,  357,  357,  357,
+      357,  357,  357,  357,  357,  357,  357,  357,  357,  357,
+      357, -340, -340, -340, -340, -340, -340, -340, -340, -340,
+
+     -340, -340, -340, -340, -340, -340, -340, -340, -340, -340,
+     -340, -340, -340, -340, -340, -340, -340, -340, -340, -340,
+     -340, -340, -340, -340, -340, -340, -340, -340
+    },
+
+    {
+       33, -341, -341, -341, -341, -341, -341, -341, -341, -341,
+     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
+     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
+     -341, -341,  358, -341, -341, -341, -341, -341, -341, -341,
+     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
+     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
+     -341, -341, -341, -341, -341,  358,  358,  358,  358,  358,
+
+      358,  358,  358,  358,  358,  358,  358,  358,  358,  358,
+      358,  358,  358,  358,  358,  358,  358,  358,  358,  358,
+      358, -341, -341, -341, -341, -341, -341, -341, -341, -341,
+     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
+     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
+     -341, -341, -341, -341, -341, -341, -341, -341
+    },
+
+    {
+       33, -342, -342, -342, -342, -342, -342, -342, -342, -342,
+     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
+     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
+     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
+
+     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
+     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
+     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
+     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
+     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
+     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
+     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
+     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
+     -342, -342, -342, -342, -342, -342, -342, -342
+    },
+
+    {
+       33, -343, -343, -343, -343, -343, -343, -343, -343, -343,
+
+     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
+     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
+     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
+     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
+     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
+     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
+     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
+     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
+     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
+     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
+
+     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
+     -343, -343, -343, -343, -343, -343, -343, -343
+    },
+
+    {
+       33, -344, -344, -344, -344, -344, -344, -344, -344, -344,
+     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
+     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
+     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
+     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
+     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
+     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
+     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
+
+     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
+     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
+     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
+     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
+     -344, -344, -344, -344, -344, -344, -344, -344
+    },
+
+    {
+       33, -345, -345, -345, -345, -345, -345, -345, -345, -345,
+     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
+     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
+     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
+     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
+
+     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
+     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
+     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
+     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
+     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
+     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
+     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
+     -345, -345, -345, -345, -345, -345, -345, -345
+    },
+
+    {
+       33, -346, -346, -346, -346, -346, -346, -346, -346, -346,
+     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
+
+     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
+     -346, -346,  359, -346, -346, -346, -346, -346, -346, -346,
+     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
+     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
+     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
+     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
+     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
+     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
+     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
+     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
+
+     -346, -346, -346, -346, -346, -346, -346, -346
+    },
+
+    {
+       33, -347, -347, -347, -347, -347, -347, -347, -347, -347,
+     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
+     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
+     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
+     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
+     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
+     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
+     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
+     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
+
+     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
+     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
+     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
+     -347, -347, -347, -347, -347, -347, -347, -347
+    },
+
+    {
+       33, -348, -348, -348, -348, -348, -348, -348, -348, -348,
+     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
+     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
+     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
+     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
+     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
+
+     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
+     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
+     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
+     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
+     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
+     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
+     -348, -348, -348, -348, -348, -348, -348, -348
+    },
+
+    {
+       33, -349, -349, -349, -349, -349, -349, -349, -349, -349,
+     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
+     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
+
+     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
+     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
+     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
+     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
+     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
+     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
+     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
+     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
+     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
+     -349, -349, -349, -349, -349, -349, -349, -349
+
+    },
+
+    {
+       33, -350, -350, -350, -350, -350, -350, -350, -350, -350,
+     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
+     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
+     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
+     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
+     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
+     -350,  360, -350, -350, -350, -350, -350, -350, -350, -350,
+     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
+     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
+     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
+
+     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
+     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
+     -350, -350, -350, -350, -350, -350, -350, -350
+    },
+
+    {
+       33, -351, -351, -351, -351, -351, -351, -351, -351, -351,
+     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
+     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
+     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
+     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
+     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
+     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
+
+     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
+     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
+     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
+     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
+     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
+     -351, -351, -351, -351, -351, -351, -351, -351
+    },
+
+    {
+       33, -352, -352, -352, -352, -352, -352, -352, -352, -352,
+     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
+     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
+     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
+
+     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
+     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
+     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
+     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
+     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
+     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
+     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
+     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
+     -352, -352, -352, -352, -352, -352, -352, -352
+    },
+
+    {
+       33, -353, -353, -353, -353, -353, -353, -353, -353, -353,
+
+     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
+     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
+     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
+     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
+     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
+     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
+     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
+     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
+     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
+     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
+
+     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
+     -353, -353, -353, -353, -353, -353, -353, -353
+    },
+
+    {
+       33, -354, -354, -354, -354, -354, -354, -354, -354, -354,
+     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
+     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
+     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
+     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
+     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
+     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
+     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
+
+     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
+     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
+     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
+     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
+     -354, -354, -354, -354, -354, -354, -354, -354
+    },
+
+    {
+       33, -355, -355, -355, -355, -355, -355, -355, -355, -355,
+     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
+     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
+     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
+     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
+
+     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
+     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
+     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
+     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
+     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
+     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
+     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
+     -355, -355, -355, -355, -355, -355, -355, -355
+    },
+
+    {
+       33, -356, -356, -356, -356, -356, -356, -356, -356, -356,
+     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
+
+     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
+     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
+     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
+     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
+     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
+     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
+     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
+     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
+     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
+     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
+
+     -356, -356, -356, -356, -356, -356, -356, -356
+    },
+
+    {
+       33, -357, -357, -357, -357, -357, -357, -357, -357, -357,
+     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
+     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
+     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
+     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
+     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
+     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
+     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
+     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
+
+     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
+     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
+     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
+     -357, -357, -357, -357, -357, -357, -357, -357
+    },
+
+    {
+       33, -358, -358, -358, -358, -358, -358, -358, -358, -358,
+     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
+     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
+     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
+     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
+     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
+
+     -358,  361, -358, -358, -358, -358, -358, -358, -358, -358,
+     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
+     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
+     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
+     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
+     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
+     -358, -358, -358, -358, -358, -358, -358, -358
+    },
+
+    {
+       33, -359, -359, -359, -359, -359, -359, -359, -359, -359,
+     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
+     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
+
+     -359, -359,  362, -359, -359, -359, -359, -359, -359, -359,
+     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
+     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
+     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
+     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
+     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
+     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
+     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
+     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
+     -359, -359, -359, -359, -359, -359, -359, -359
+
+    },
+
+    {
+       33, -360, -360, -360, -360, -360, -360, -360, -360, -360,
+     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
+     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
+     -360, -360,  363, -360, -360, -360, -360, -360, -360, -360,
+     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
+     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
+     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
+     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
+     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
+     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
+
+     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
+     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
+     -360, -360, -360, -360, -360, -360, -360, -360
+    },
+
+    {
+       33, -361, -361, -361, -361, -361, -361, -361, -361, -361,
+     -361, -361, -361, -361, -361, -361, -361, -361, -361, -361,
+     -361, -361, -361, -361, -361, -361, -361, -361, -361, -361,
+     -361, -361,  364, -361, -361, -361, -361, -361, -361, -361,
+     -361, -361, -361, -361, -361, -361, -361, -361, -361, -361,
+     -361, -361, -361, -361, -361, -361, -361, -361, -361, -361,
+     -361, -361, -361, -361, -361, -361, -361, -361, -361, -361,
+
+     -361, -361, -361, -361, -361, -361, -361, -361, -361, -361,
+     -361, -361, -361, -361, -361, -361, -361, -361, -361, -361,
+     -361, -361, -361, -361, -361, -361, -361, -361, -361, -361,
+     -361, -361, -361, -361, -361, -361, -361, -361, -361, -361,
+     -361, -361, -361, -361, -361, -361, -361, -361, -361, -361,
+     -361, -361, -361, -361, -361, -361, -361, -361
+    },
+
+    {
+       33, -362, -362, -362, -362, -362, -362, -362, -362, -362,
+     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
+     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
+     -362, -362,  365, -362, -362, -362, -362, -362, -362, -362,
+
+     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
+     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
+     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
+     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
+     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
+     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
+     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
+     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
+     -362, -362, -362, -362, -362, -362, -362, -362
+    },
+
+    {
+       33, -363, -363, -363, -363, -363, -363, -363, -363, -363,
+
+     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
+     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
+     -363, -363,  366, -363, -363, -363, -363, -363, -363, -363,
+     -363, -363, -363,  367, -363,  367, -363, -363,  368,  368,
+      368,  368,  368,  368,  368,  368,  368,  368, -363, -363,
+     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
+     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
+     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
+     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
+     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
+
+     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
+     -363, -363, -363, -363, -363, -363, -363, -363
+    },
+
+    {
+       33, -364, -364, -364, -364, -364, -364, -364, -364, -364,
+     -364, -364, -364, -364, -364, -364, -364, -364, -364, -364,
+     -364, -364, -364, -364, -364, -364, -364, -364, -364, -364,
+     -364, -364,  369, -364, -364, -364, -364, -364, -364, -364,
+     -364, -364, -364,  370, -364,  370, -364, -364,  371,  371,
+      371,  371,  371,  371,  371,  371,  371,  371, -364, -364,
+     -364, -364, -364, -364, -364, -364, -364, -364, -364, -364,
+     -364, -364, -364, -364, -364, -364, -364, -364, -364, -364,
+
+     -364, -364, -364, -364, -364, -364, -364, -364, -364, -364,
+     -364, -364, -364, -364, -364, -364, -364, -364, -364, -364,
+     -364, -364, -364, -364, -364, -364, -364, -364, -364, -364,
+     -364, -364, -364, -364, -364, -364, -364, -364, -364, -364,
+     -364, -364, -364, -364, -364, -364, -364, -364
+    },
+
+    {
+       33, -365, -365, -365, -365, -365, -365, -365, -365, -365,
+     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
+     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
+     -365, -365,  372, -365, -365, -365, -365, -365, -365, -365,
+     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
+
+     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
+     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
+     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
+     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
+     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
+     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
+     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
+     -365, -365, -365, -365, -365, -365, -365, -365
+    },
+
+    {
+       33, -366, -366, -366, -366, -366, -366, -366, -366, -366,
+     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
+
+     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
+     -366, -366,  366, -366, -366, -366, -366, -366, -366, -366,
+     -366, -366, -366,  367, -366,  367, -366, -366,  368,  368,
+      368,  368,  368,  368,  368,  368,  368,  368, -366, -366,
+     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
+     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
+     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
+     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
+     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
+     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
+
+     -366, -366, -366, -366, -366, -366, -366, -366
+    },
+
+    {
+       33, -367, -367, -367, -367, -367, -367, -367, -367, -367,
+     -367, -367, -367, -367, -367, -367, -367, -367, -367, -367,
+     -367, -367, -367, -367, -367, -367, -367, -367, -367, -367,
+     -367, -367, -367, -367, -367, -367, -367, -367, -367, -367,
+     -367, -367, -367, -367, -367, -367, -367, -367,  368,  368,
+      368,  368,  368,  368,  368,  368,  368,  368, -367, -367,
+     -367, -367, -367, -367, -367, -367, -367, -367, -367, -367,
+     -367, -367, -367, -367, -367, -367, -367, -367, -367, -367,
+     -367, -367, -367, -367, -367, -367, -367, -367, -367, -367,
+
+     -367, -367, -367, -367, -367, -367, -367, -367, -367, -367,
+     -367, -367, -367, -367, -367, -367, -367, -367, -367, -367,
+     -367, -367, -367, -367, -367, -367, -367, -367, -367, -367,
+     -367, -367, -367, -367, -367, -367, -367, -367
+    },
+
+    {
+       33, -368, -368, -368, -368, -368, -368, -368, -368, -368,
+     -368, -368, -368, -368, -368, -368, -368, -368, -368, -368,
+     -368, -368, -368, -368, -368, -368, -368, -368, -368, -368,
+     -368, -368, -368, -368, -368, -368, -368, -368, -368, -368,
+     -368, -368, -368, -368, -368, -368, -368, -368,  368,  368,
+      368,  368,  368,  368,  368,  368,  368,  368, -368, -368,
+
+     -368, -368, -368, -368, -368, -368, -368, -368, -368, -368,
+     -368, -368, -368, -368, -368, -368, -368, -368, -368, -368,
+     -368, -368, -368, -368, -368, -368, -368, -368, -368, -368,
+     -368, -368, -368, -368, -368, -368, -368, -368, -368, -368,
+     -368, -368, -368, -368, -368, -368, -368, -368, -368, -368,
+     -368, -368, -368, -368, -368, -368, -368, -368, -368, -368,
+     -368, -368, -368, -368, -368, -368, -368, -368
+    },
+
+    {
+       33, -369, -369, -369, -369, -369, -369, -369, -369, -369,
+     -369, -369, -369, -369, -369, -369, -369, -369, -369, -369,
+     -369, -369, -369, -369, -369, -369, -369, -369, -369, -369,
+
+     -369, -369,  369, -369, -369, -369, -369, -369, -369, -369,
+     -369, -369, -369,  370, -369,  370, -369, -369,  371,  371,
+      371,  371,  371,  371,  371,  371,  371,  371, -369, -369,
+     -369, -369, -369, -369, -369, -369, -369, -369, -369, -369,
+     -369, -369, -369, -369, -369, -369, -369, -369, -369, -369,
+     -369, -369, -369, -369, -369, -369, -369, -369, -369, -369,
+     -369, -369, -369, -369, -369, -369, -369, -369, -369, -369,
+     -369, -369, -369, -369, -369, -369, -369, -369, -369, -369,
+     -369, -369, -369, -369, -369, -369, -369, -369, -369, -369,
+     -369, -369, -369, -369, -369, -369, -369, -369
+
+    },
+
+    {
+       33, -370, -370, -370, -370, -370, -370, -370, -370, -370,
+     -370, -370, -370, -370, -370, -370, -370, -370, -370, -370,
+     -370, -370, -370, -370, -370, -370, -370, -370, -370, -370,
+     -370, -370, -370, -370, -370, -370, -370, -370, -370, -370,
+     -370, -370, -370, -370, -370, -370, -370, -370,  371,  371,
+      371,  371,  371,  371,  371,  371,  371,  371, -370, -370,
+     -370, -370, -370, -370, -370, -370, -370, -370, -370, -370,
+     -370, -370, -370, -370, -370, -370, -370, -370, -370, -370,
+     -370, -370, -370, -370, -370, -370, -370, -370, -370, -370,
+     -370, -370, -370, -370, -370, -370, -370, -370, -370, -370,
+
+     -370, -370, -370, -370, -370, -370, -370, -370, -370, -370,
+     -370, -370, -370, -370, -370, -370, -370, -370, -370, -370,
+     -370, -370, -370, -370, -370, -370, -370, -370
+    },
+
+    {
+       33, -371, -371, -371, -371, -371, -371, -371, -371, -371,
+     -371, -371, -371, -371, -371, -371, -371, -371, -371, -371,
+     -371, -371, -371, -371, -371, -371, -371, -371, -371, -371,
+     -371, -371, -371, -371, -371, -371, -371, -371, -371, -371,
+     -371, -371, -371, -371, -371, -371, -371, -371,  371,  371,
+      371,  371,  371,  371,  371,  371,  371,  371, -371, -371,
+     -371, -371, -371, -371, -371, -371, -371, -371, -371, -371,
+
+     -371, -371, -371, -371, -371, -371, -371, -371, -371, -371,
+     -371, -371, -371, -371, -371, -371, -371, -371, -371, -371,
+     -371, -371, -371, -371, -371, -371, -371, -371, -371, -371,
+     -371, -371, -371, -371, -371, -371, -371, -371, -371, -371,
+     -371, -371, -371, -371, -371, -371, -371, -371, -371, -371,
+     -371, -371, -371, -371, -371, -371, -371, -371
+    },
+
+    {
+       33, -372, -372, -372, -372, -372, -372, -372, -372, -372,
+     -372, -372, -372, -372, -372, -372, -372, -372, -372, -372,
+     -372, -372, -372, -372, -372, -372, -372, -372, -372, -372,
+     -372, -372,  373, -372, -372, -372, -372, -372, -372, -372,
+
+     -372, -372, -372, -372, -372, -372, -372, -372, -372, -372,
+     -372, -372, -372, -372, -372, -372, -372, -372, -372, -372,
+     -372, -372, -372, -372, -372, -372, -372, -372, -372, -372,
+     -372, -372, -372, -372, -372, -372, -372, -372, -372, -372,
+     -372, -372, -372, -372, -372, -372, -372, -372, -372, -372,
+     -372, -372, -372, -372, -372, -372, -372, -372, -372, -372,
+     -372, -372, -372, -372, -372, -372, -372, -372, -372, -372,
+     -372, -372, -372, -372, -372, -372, -372, -372, -372, -372,
+     -372, -372, -372, -372, -372, -372, -372, -372
+    },
+
+    {
+       33, -373, -373, -373, -373, -373, -373, -373, -373, -373,
+
+     -373, -373, -373, -373, -373, -373, -373, -373, -373, -373,
+     -373, -373, -373, -373, -373, -373, -373, -373, -373, -373,
+     -373, -373,  374, -373, -373, -373, -373, -373, -373, -373,
+     -373, -373, -373, -373, -373, -373, -373, -373, -373, -373,
+     -373, -373, -373, -373, -373, -373, -373, -373, -373, -373,
+     -373, -373, -373, -373, -373, -373, -373, -373, -373, -373,
+     -373, -373, -373, -373, -373, -373, -373, -373, -373, -373,
+     -373, -373, -373, -373, -373, -373, -373, -373, -373, -373,
+     -373, -373, -373, -373, -373, -373, -373, -373, -373, -373,
+     -373, -373, -373, -373, -373, -373, -373, -373, -373, -373,
+
+     -373, -373, -373, -373, -373, -373, -373, -373, -373, -373,
+     -373, -373, -373, -373, -373, -373, -373, -373
+    },
+
+    {
+       33, -374, -374, -374, -374, -374, -374, -374, -374, -374,
+     -374, -374, -374, -374, -374, -374, -374, -374, -374, -374,
+     -374, -374, -374, -374, -374, -374, -374, -374, -374, -374,
+     -374, -374,  375, -374, -374, -374, -374, -374, -374, -374,
+     -374, -374, -374, -374, -374, -374, -374, -374, -374, -374,
+     -374, -374, -374, -374, -374, -374, -374, -374, -374, -374,
+     -374, -374, -374, -374, -374, -374, -374, -374, -374, -374,
+     -374, -374, -374, -374, -374, -374, -374, -374, -374, -374,
+
+     -374, -374, -374, -374, -374, -374, -374, -374, -374, -374,
+     -374, -374, -374, -374, -374, -374, -374, -374, -374, -374,
+     -374, -374, -374, -374, -374, -374, -374, -374, -374, -374,
+     -374, -374, -374, -374, -374, -374, -374, -374, -374, -374,
+     -374, -374, -374, -374, -374, -374, -374, -374
+    },
+
+    {
+       33, -375, -375, -375, -375, -375, -375, -375, -375, -375,
+     -375, -375, -375, -375, -375, -375, -375, -375, -375, -375,
+     -375, -375, -375, -375, -375, -375, -375, -375, -375, -375,
+     -375, -375,  376, -375, -375, -375, -375, -375, -375, -375,
+     -375, -375, -375, -375, -375, -375, -375, -375, -375, -375,
+
+     -375, -375, -375, -375, -375, -375, -375, -375, -375, -375,
+     -375, -375, -375, -375, -375, -375, -375, -375, -375, -375,
+     -375, -375, -375, -375, -375, -375, -375, -375, -375, -375,
+     -375, -375, -375, -375, -375, -375, -375, -375, -375, -375,
+     -375, -375, -375, -375, -375, -375, -375, -375, -375, -375,
+     -375, -375, -375, -375, -375, -375, -375, -375, -375, -375,
+     -375, -375, -375, -375, -375, -375, -375, -375, -375, -375,
+     -375, -375, -375, -375, -375, -375, -375, -375
+    },
+
+    {
+       33, -376, -376, -376, -376, -376, -376, -376, -376, -376,
+     -376, -376, -376, -376, -376, -376, -376, -376, -376, -376,
+
+     -376, -376, -376, -376, -376, -376, -376, -376, -376, -376,
+     -376, -376,  377, -376, -376, -376, -376, -376, -376, -376,
+     -376, -376, -376, -376, -376, -376, -376, -376, -376, -376,
+     -376, -376, -376, -376, -376, -376, -376, -376, -376, -376,
+     -376, -376, -376, -376, -376, -376, -376, -376, -376, -376,
+     -376, -376, -376, -376, -376, -376, -376, -376, -376, -376,
+     -376, -376, -376, -376, -376, -376, -376, -376, -376, -376,
+     -376, -376, -376, -376, -376, -376, -376, -376, -376, -376,
+     -376, -376, -376, -376, -376, -376, -376, -376, -376, -376,
+     -376, -376, -376, -376, -376, -376, -376, -376, -376, -376,
+
+     -376, -376, -376, -376, -376, -376, -376, -376
+    },
+
+    {
+       33, -377, -377, -377, -377, -377, -377, -377, -377, -377,
+     -377, -377, -377, -377, -377, -377, -377, -377, -377, -377,
+     -377, -377, -377, -377, -377, -377, -377, -377, -377, -377,
+     -377, -377,  378, -377, -377, -377, -377, -377, -377, -377,
+     -377, -377, -377, -377, -377, -377, -377, -377, -377, -377,
+     -377, -377, -377, -377, -377, -377, -377, -377, -377, -377,
+     -377, -377, -377, -377, -377, -377, -377, -377, -377, -377,
+     -377, -377, -377, -377, -377, -377, -377, -377, -377, -377,
+     -377, -377, -377, -377, -377, -377, -377, -377, -377, -377,
+
+     -377, -377, -377, -377, -377, -377, -377, -377, -377, -377,
+     -377, -377, -377, -377, -377, -377, -377, -377, -377, -377,
+     -377, -377, -377, -377, -377, -377, -377, -377, -377, -377,
+     -377, -377, -377, -377, -377, -377, -377, -377
+    },
+
+    {
+       33, -378, -378, -378, -378, -378, -378, -378, -378, -378,
+     -378, -378, -378, -378, -378, -378, -378, -378, -378, -378,
+     -378, -378, -378, -378, -378, -378, -378, -378, -378, -378,
+     -378, -378,  379, -378, -378, -378, -378, -378, -378, -378,
+     -378, -378, -378, -378, -378, -378, -378, -378, -378, -378,
+     -378, -378, -378, -378, -378, -378, -378, -378, -378, -378,
+
+     -378, -378, -378, -378, -378, -378, -378, -378, -378, -378,
+     -378, -378, -378, -378, -378, -378, -378, -378, -378, -378,
+     -378, -378, -378, -378, -378, -378, -378, -378, -378, -378,
+     -378, -378, -378, -378, -378, -378, -378, -378, -378, -378,
+     -378, -378, -378, -378, -378, -378, -378, -378, -378, -378,
+     -378, -378, -378, -378, -378, -378, -378, -378, -378, -378,
+     -378, -378, -378, -378, -378, -378, -378, -378
+    },
+
+    {
+       33, -379, -379, -379, -379, -379, -379, -379, -379, -379,
+     -379, -379, -379, -379, -379, -379, -379, -379, -379, -379,
+     -379, -379, -379, -379, -379, -379, -379, -379, -379, -379,
+
+     -379, -379,  380, -379, -379, -379, -379, -379, -379, -379,
+     -379, -379, -379, -379, -379, -379, -379, -379, -379, -379,
+     -379, -379, -379, -379, -379, -379, -379, -379, -379, -379,
+     -379, -379, -379, -379, -379, -379, -379, -379, -379, -379,
+     -379, -379, -379, -379, -379, -379, -379, -379, -379, -379,
+     -379, -379, -379, -379, -379, -379, -379, -379, -379, -379,
+     -379, -379, -379, -379, -379, -379, -379, -379, -379, -379,
+     -379, -379, -379, -379, -379, -379, -379, -379, -379, -379,
+     -379, -379, -379, -379, -379, -379, -379, -379, -379, -379,
+     -379, -379, -379, -379, -379, -379, -379, -379
+
+    },
+
+    {
+       33, -380, -380, -380, -380, -380, -380, -380, -380, -380,
+     -380, -380, -380, -380, -380, -380, -380, -380, -380, -380,
+     -380, -380, -380, -380, -380, -380, -380, -380, -380, -380,
+     -380, -380,  381, -380, -380, -380, -380, -380, -380, -380,
+     -380, -380, -380, -380, -380, -380, -380, -380, -380, -380,
+     -380, -380, -380, -380, -380, -380, -380, -380, -380, -380,
+     -380, -380, -380, -380, -380, -380, -380, -380, -380, -380,
+     -380, -380, -380, -380, -380, -380, -380, -380, -380, -380,
+     -380, -380, -380, -380, -380, -380, -380, -380, -380, -380,
+     -380, -380, -380, -380, -380, -380, -380, -380, -380, -380,
+
+     -380, -380, -380, -380, -380, -380, -380, -380, -380, -380,
+     -380, -380, -380, -380, -380, -380, -380, -380, -380, -380,
+     -380, -380, -380, -380, -380, -380, -380, -380
+    },
+
+    {
+       33, -381, -381, -381, -381, -381, -381, -381, -381, -381,
+     -381, -381, -381, -381, -381, -381, -381, -381, -381, -381,
+     -381, -381, -381, -381, -381, -381, -381, -381, -381, -381,
+     -381, -381,  382, -381, -381, -381, -381, -381, -381, -381,
+     -381, -381, -381, -381, -381, -381, -381, -381, -381, -381,
+     -381, -381, -381, -381, -381, -381, -381, -381, -381, -381,
+     -381, -381, -381, -381, -381, -381, -381, -381, -381, -381,
+
+     -381, -381, -381, -381, -381, -381, -381, -381, -381, -381,
+     -381, -381, -381, -381, -381, -381, -381, -381, -381, -381,
+     -381, -381, -381, -381, -381, -381, -381, -381, -381, -381,
+     -381, -381, -381, -381, -381, -381, -381, -381, -381, -381,
+     -381, -381, -381, -381, -381, -381, -381, -381, -381, -381,
+     -381, -381, -381, -381, -381, -381, -381, -381
+    },
+
+    {
+       33, -382, -382, -382, -382, -382, -382, -382, -382, -382,
+     -382, -382, -382, -382, -382, -382, -382, -382, -382, -382,
+     -382, -382, -382, -382, -382, -382, -382, -382, -382, -382,
+     -382, -382,  383, -382, -382, -382, -382, -382, -382, -382,
+
+     -382, -382, -382, -382, -382, -382, -382, -382, -382, -382,
+     -382, -382, -382, -382, -382, -382, -382, -382, -382, -382,
+     -382, -382, -382, -382, -382, -382, -382, -382, -382, -382,
+     -382, -382, -382, -382, -382, -382, -382, -382, -382, -382,
+     -382, -382, -382, -382, -382, -382, -382, -382, -382, -382,
+     -382, -382, -382, -382, -382, -382, -382, -382, -382, -382,
+     -382, -382, -382, -382, -382, -382, -382, -382, -382, -382,
+     -382, -382, -382, -382, -382, -382, -382, -382, -382, -382,
+     -382, -382, -382, -382, -382, -382, -382, -382
+    },
+
+    {
+       33, -383, -383, -383, -383, -383, -383, -383, -383, -383,
+
+     -383, -383, -383, -383, -383, -383, -383, -383, -383, -383,
+     -383, -383, -383, -383, -383, -383, -383, -383, -383, -383,
+     -383, -383,  384, -383, -383, -383, -383, -383, -383, -383,
+     -383, -383, -383, -383, -383, -383, -383, -383, -383, -383,
+     -383, -383, -383, -383, -383, -383, -383, -383, -383, -383,
+     -383, -383, -383, -383, -383, -383, -383, -383, -383, -383,
+     -383, -383, -383, -383, -383, -383, -383, -383, -383, -383,
+     -383, -383, -383, -383, -383, -383, -383, -383, -383, -383,
+     -383, -383, -383, -383, -383, -383, -383, -383, -383, -383,
+     -383, -383, -383, -383, -383, -383, -383, -383, -383, -383,
+
+     -383, -383, -383, -383, -383, -383, -383, -383, -383, -383,
+     -383, -383, -383, -383, -383, -383, -383, -383
+    },
+
+    {
+       33, -384, -384, -384, -384, -384, -384, -384, -384, -384,
+     -384, -384, -384, -384, -384, -384, -384, -384, -384, -384,
+     -384, -384, -384, -384, -384, -384, -384, -384, -384, -384,
+     -384, -384,  385, -384, -384, -384, -384, -384, -384, -384,
+     -384, -384, -384, -384, -384, -384, -384, -384, -384, -384,
+     -384, -384, -384, -384, -384, -384, -384, -384, -384, -384,
+     -384, -384, -384, -384, -384, -384, -384, -384, -384, -384,
+     -384, -384, -384, -384, -384, -384, -384, -384, -384, -384,
+
+     -384, -384, -384, -384, -384, -384, -384, -384, -384, -384,
+     -384, -384, -384, -384, -384, -384, -384, -384, -384, -384,
+     -384, -384, -384, -384, -384, -384, -384, -384, -384, -384,
+     -384, -384, -384, -384, -384, -384, -384, -384, -384, -384,
+     -384, -384, -384, -384, -384, -384, -384, -384
+    },
+
+    {
+       33, -385, -385, -385, -385, -385, -385, -385, -385, -385,
+     -385, -385, -385, -385, -385, -385, -385, -385, -385, -385,
+     -385, -385, -385, -385, -385, -385, -385, -385, -385, -385,
+     -385, -385,  386, -385, -385, -385, -385, -385, -385, -385,
+     -385, -385, -385, -385, -385, -385, -385, -385, -385, -385,
+
+     -385, -385, -385, -385, -385, -385, -385, -385, -385, -385,
+     -385, -385, -385, -385, -385, -385, -385, -385, -385, -385,
+     -385, -385, -385, -385, -385, -385, -385, -385, -385, -385,
+     -385, -385, -385, -385, -385, -385, -385, -385, -385, -385,
+     -385, -385, -385, -385, -385, -385, -385, -385, -385, -385,
+     -385, -385, -385, -385, -385, -385, -385, -385, -385, -385,
+     -385, -385, -385, -385, -385, -385, -385, -385, -385, -385,
+     -385, -385, -385, -385, -385, -385, -385, -385
+    },
+
+    {
+       33, -386, -386, -386, -386, -386, -386, -386, -386, -386,
+     -386, -386, -386, -386, -386, -386, -386, -386, -386, -386,
+
+     -386, -386, -386, -386, -386, -386, -386, -386, -386, -386,
+     -386, -386,  387, -386, -386, -386, -386, -386, -386, -386,
+     -386, -386, -386, -386, -386, -386, -386, -386, -386, -386,
+     -386, -386, -386, -386, -386, -386, -386, -386, -386, -386,
+     -386, -386, -386, -386, -386, -386, -386, -386, -386, -386,
+     -386, -386, -386, -386, -386, -386, -386, -386, -386, -386,
+     -386, -386, -386, -386, -386, -386, -386, -386, -386, -386,
+     -386, -386, -386, -386, -386, -386, -386, -386, -386, -386,
+     -386, -386, -386, -386, -386, -386, -386, -386, -386, -386,
+     -386, -386, -386, -386, -386, -386, -386, -386, -386, -386,
+
+     -386, -386, -386, -386, -386, -386, -386, -386
+    },
+
+    {
+       33, -387, -387, -387, -387, -387, -387, -387, -387, -387,
+     -387, -387, -387, -387, -387, -387, -387, -387, -387, -387,
+     -387, -387, -387, -387, -387, -387, -387, -387, -387, -387,
+     -387, -387,  388, -387, -387, -387, -387, -387, -387, -387,
+     -387, -387, -387, -387, -387, -387, -387, -387, -387, -387,
+     -387, -387, -387, -387, -387, -387, -387, -387, -387, -387,
+     -387, -387, -387, -387, -387, -387, -387, -387, -387, -387,
+     -387, -387, -387, -387, -387, -387, -387, -387, -387, -387,
+     -387, -387, -387, -387, -387, -387, -387, -387, -387, -387,
+
+     -387, -387, -387, -387, -387, -387, -387, -387, -387, -387,
+     -387, -387, -387, -387, -387, -387, -387, -387, -387, -387,
+     -387, -387, -387, -387, -387, -387, -387, -387, -387, -387,
+     -387, -387, -387, -387, -387, -387, -387, -387
+    },
+
+    {
+       33, -388, -388, -388, -388, -388, -388, -388, -388, -388,
+     -388, -388, -388, -388, -388, -388, -388, -388, -388, -388,
+     -388, -388, -388, -388, -388, -388, -388, -388, -388, -388,
+     -388, -388,  389, -388, -388, -388, -388, -388, -388, -388,
+     -388, -388, -388, -388, -388, -388, -388, -388, -388, -388,
+     -388, -388, -388, -388, -388, -388, -388, -388, -388, -388,
+
+     -388, -388, -388, -388, -388, -388, -388, -388, -388, -388,
+     -388, -388, -388, -388, -388, -388, -388, -388, -388, -388,
+     -388, -388, -388, -388, -388, -388, -388, -388, -388, -388,
+     -388, -388, -388, -388, -388, -388, -388, -388, -388, -388,
+     -388, -388, -388, -388, -388, -388, -388, -388, -388, -388,
+     -388, -388, -388, -388, -388, -388, -388, -388, -388, -388,
+     -388, -388, -388, -388, -388, -388, -388, -388
+    },
+
+    {
+       33, -389, -389, -389, -389, -389, -389, -389, -389, -389,
+     -389, -389, -389, -389, -389, -389, -389, -389, -389, -389,
+     -389, -389, -389, -389, -389, -389, -389, -389, -389, -389,
+
+     -389, -389,  390, -389, -389, -389, -389, -389, -389, -389,
+     -389, -389, -389, -389, -389, -389, -389, -389, -389, -389,
+     -389, -389, -389, -389, -389, -389, -389, -389, -389, -389,
+     -389, -389, -389, -389, -389, -389, -389, -389, -389, -389,
+     -389, -389, -389, -389, -389, -389, -389, -389, -389, -389,
+     -389, -389, -389, -389, -389, -389, -389, -389, -389, -389,
+     -389, -389, -389, -389, -389, -389, -389, -389, -389, -389,
+     -389, -389, -389, -389, -389, -389, -389, -389, -389, -389,
+     -389, -389, -389, -389, -389, -389, -389, -389, -389, -389,
+     -389, -389, -389, -389, -389, -389, -389, -389
+
+    },
+
+    {
+       33, -390, -390, -390, -390, -390, -390, -390, -390, -390,
+     -390, -390, -390, -390, -390, -390, -390, -390, -390, -390,
+     -390, -390, -390, -390, -390, -390, -390, -390, -390, -390,
+     -390, -390,  391, -390, -390, -390, -390, -390, -390, -390,
+     -390, -390, -390, -390, -390, -390, -390, -390, -390, -390,
+     -390, -390, -390, -390, -390, -390, -390, -390, -390, -390,
+     -390, -390, -390, -390, -390, -390, -390, -390, -390, -390,
+     -390, -390, -390, -390, -390, -390, -390, -390, -390, -390,
+     -390, -390, -390, -390, -390, -390, -390, -390, -390, -390,
+     -390, -390, -390, -390, -390, -390, -390, -390, -390, -390,
+
+     -390, -390, -390, -390, -390, -390, -390, -390, -390, -390,
+     -390, -390, -390, -390, -390, -390, -390, -390, -390, -390,
+     -390, -390, -390, -390, -390, -390, -390, -390
+    },
+
+    {
+       33, -391, -391, -391, -391, -391, -391, -391, -391, -391,
+     -391, -391, -391, -391, -391, -391, -391, -391, -391, -391,
+     -391, -391, -391, -391, -391, -391, -391, -391, -391, -391,
+     -391, -391,  392, -391, -391, -391, -391, -391, -391, -391,
+     -391, -391, -391, -391, -391, -391, -391, -391, -391, -391,
+     -391, -391, -391, -391, -391, -391, -391, -391, -391, -391,
+     -391, -391, -391, -391, -391, -391, -391, -391, -391, -391,
+
+     -391, -391, -391, -391, -391, -391, -391, -391, -391, -391,
+     -391, -391, -391, -391, -391, -391, -391, -391, -391, -391,
+     -391, -391, -391, -391, -391, -391, -391, -391, -391, -391,
+     -391, -391, -391, -391, -391, -391, -391, -391, -391, -391,
+     -391, -391, -391, -391, -391, -391, -391, -391, -391, -391,
+     -391, -391, -391, -391, -391, -391, -391, -391
+    },
+
+    {
+       33, -392, -392, -392, -392, -392, -392, -392, -392, -392,
+     -392, -392, -392, -392, -392, -392, -392, -392, -392, -392,
+     -392, -392, -392, -392, -392, -392, -392, -392, -392, -392,
+     -392, -392,  393, -392, -392, -392, -392, -392, -392, -392,
+
+     -392, -392, -392, -392, -392, -392, -392, -392, -392, -392,
+     -392, -392, -392, -392, -392, -392, -392, -392, -392, -392,
+     -392, -392, -392, -392, -392, -392, -392, -392, -392, -392,
+     -392, -392, -392, -392, -392, -392, -392, -392, -392, -392,
+     -392, -392, -392, -392, -392, -392, -392, -392, -392, -392,
+     -392, -392, -392, -392, -392, -392, -392, -392, -392, -392,
+     -392, -392, -392, -392, -392, -392, -392, -392, -392, -392,
+     -392, -392, -392, -392, -392, -392, -392, -392, -392, -392,
+     -392, -392, -392, -392, -392, -392, -392, -392
+    },
+
+    {
+       33, -393, -393, -393, -393, -393, -393, -393, -393, -393,
+
+     -393, -393, -393, -393, -393, -393, -393, -393, -393, -393,
+     -393, -393, -393, -393, -393, -393, -393, -393, -393, -393,
+     -393, -393,  394, -393, -393, -393, -393, -393, -393, -393,
+     -393, -393, -393, -393, -393, -393, -393, -393, -393, -393,
+     -393, -393, -393, -393, -393, -393, -393, -393, -393, -393,
+     -393, -393, -393, -393, -393, -393, -393, -393, -393, -393,
+     -393, -393, -393, -393, -393, -393, -393, -393, -393, -393,
+     -393, -393, -393, -393, -393, -393, -393, -393, -393, -393,
+     -393, -393, -393, -393, -393, -393, -393, -393, -393, -393,
+     -393, -393, -393, -393, -393, -393, -393, -393, -393, -393,
+
+     -393, -393, -393, -393, -393, -393, -393, -393, -393, -393,
+     -393, -393, -393, -393, -393, -393, -393, -393
+    },
+
+    {
+       33, -394, -394, -394, -394, -394, -394, -394, -394, -394,
+     -394, -394, -394, -394, -394, -394, -394, -394, -394, -394,
+     -394, -394, -394, -394, -394, -394, -394, -394, -394, -394,
+     -394, -394,  395, -394, -394, -394, -394, -394, -394, -394,
+     -394, -394, -394, -394, -394, -394, -394, -394, -394, -394,
+     -394, -394, -394, -394, -394, -394, -394, -394, -394, -394,
+     -394, -394, -394, -394, -394, -394, -394, -394, -394, -394,
+     -394, -394, -394, -394, -394, -394, -394, -394, -394, -394,
+
+     -394, -394, -394, -394, -394, -394, -394, -394, -394, -394,
+     -394, -394, -394, -394, -394, -394, -394, -394, -394, -394,
+     -394, -394, -394, -394, -394, -394, -394, -394, -394, -394,
+     -394, -394, -394, -394, -394, -394, -394, -394, -394, -394,
+     -394, -394, -394, -394, -394, -394, -394, -394
+    },
+
+    {
+       33, -395, -395, -395, -395, -395, -395, -395, -395, -395,
+     -395, -395, -395, -395, -395, -395, -395, -395, -395, -395,
+     -395, -395, -395, -395, -395, -395, -395, -395, -395, -395,
+     -395, -395,  396, -395, -395, -395, -395, -395, -395, -395,
+     -395, -395, -395, -395, -395, -395, -395, -395, -395, -395,
+
+     -395, -395, -395, -395, -395, -395, -395, -395, -395, -395,
+     -395, -395, -395, -395, -395, -395, -395, -395, -395, -395,
+     -395, -395, -395, -395, -395, -395, -395, -395, -395, -395,
+     -395, -395, -395, -395, -395, -395, -395, -395, -395, -395,
+     -395, -395, -395, -395, -395, -395, -395, -395, -395, -395,
+     -395, -395, -395, -395, -395, -395, -395, -395, -395, -395,
+     -395, -395, -395, -395, -395, -395, -395, -395, -395, -395,
+     -395, -395, -395, -395, -395, -395, -395, -395
+    },
+
+    {
+       33, -396, -396, -396, -396, -396, -396, -396, -396, -396,
+     -396, -396, -396, -396, -396, -396, -396, -396, -396, -396,
+
+     -396, -396, -396, -396, -396, -396, -396, -396, -396, -396,
+     -396, -396,  397, -396, -396, -396, -396, -396, -396, -396,
+     -396, -396, -396, -396, -396, -396, -396, -396, -396, -396,
+     -396, -396, -396, -396, -396, -396, -396, -396, -396, -396,
+     -396, -396, -396, -396, -396, -396, -396, -396, -396, -396,
+     -396, -396, -396, -396, -396, -396, -396, -396, -396, -396,
+     -396, -396, -396, -396, -396, -396, -396, -396, -396, -396,
+     -396, -396, -396, -396, -396, -396, -396, -396, -396, -396,
+     -396, -396, -396, -396, -396, -396, -396, -396, -396, -396,
+     -396, -396, -396, -396, -396, -396, -396, -396, -396, -396,
+
+     -396, -396, -396, -396, -396, -396, -396, -396
+    },
+
+    {
+       33, -397, -397, -397, -397, -397, -397, -397, -397, -397,
+     -397, -397, -397, -397, -397, -397, -397, -397, -397, -397,
+     -397, -397, -397, -397, -397, -397, -397, -397, -397, -397,
+     -397, -397,  398, -397, -397, -397, -397, -397, -397, -397,
+     -397, -397, -397, -397, -397, -397, -397, -397, -397, -397,
+     -397, -397, -397, -397, -397, -397, -397, -397, -397, -397,
+     -397, -397, -397, -397, -397, -397, -397, -397, -397, -397,
+     -397, -397, -397, -397, -397, -397, -397, -397, -397, -397,
+     -397, -397, -397, -397, -397, -397, -397, -397, -397, -397,
+
+     -397, -397, -397, -397, -397, -397, -397, -397, -397, -397,
+     -397, -397, -397, -397, -397, -397, -397, -397, -397, -397,
+     -397, -397, -397, -397, -397, -397, -397, -397, -397, -397,
+     -397, -397, -397, -397, -397, -397, -397, -397
+    },
+
+    {
+       33, -398, -398, -398, -398, -398, -398, -398, -398, -398,
+     -398, -398, -398, -398, -398, -398, -398, -398, -398, -398,
+     -398, -398, -398, -398, -398, -398, -398, -398, -398, -398,
+     -398, -398,  399, -398, -398, -398, -398, -398, -398, -398,
+     -398, -398, -398, -398, -398, -398, -398, -398, -398, -398,
+     -398, -398, -398, -398, -398, -398, -398, -398, -398, -398,
+
+     -398, -398, -398, -398, -398, -398, -398, -398, -398, -398,
+     -398, -398, -398, -398, -398, -398, -398, -398, -398, -398,
+     -398, -398, -398, -398, -398, -398, -398, -398, -398, -398,
+     -398, -398, -398, -398, -398, -398, -398, -398, -398, -398,
+     -398, -398, -398, -398, -398, -398, -398, -398, -398, -398,
+     -398, -398, -398, -398, -398, -398, -398, -398, -398, -398,
+     -398, -398, -398, -398, -398, -398, -398, -398
+    },
+
+    {
+       33, -399, -399, -399, -399, -399, -399, -399, -399, -399,
+     -399, -399, -399, -399, -399, -399, -399, -399, -399, -399,
+     -399, -399, -399, -399, -399, -399, -399, -399, -399, -399,
+
+     -399, -399,  400, -399, -399, -399, -399, -399, -399, -399,
+     -399, -399, -399, -399, -399, -399, -399, -399, -399, -399,
+     -399, -399, -399, -399, -399, -399, -399, -399, -399, -399,
+     -399, -399, -399, -399, -399, -399, -399, -399, -399, -399,
+     -399, -399, -399, -399, -399, -399, -399, -399, -399, -399,
+     -399, -399, -399, -399, -399, -399, -399, -399, -399, -399,
+     -399, -399, -399, -399, -399, -399, -399, -399, -399, -399,
+     -399, -399, -399, -399, -399, -399, -399, -399, -399, -399,
+     -399, -399, -399, -399, -399, -399, -399, -399, -399, -399,
+     -399, -399, -399, -399, -399, -399, -399, -399
+
+    },
+
+    {
+       33, -400, -400, -400, -400, -400, -400, -400, -400, -400,
+     -400, -400, -400, -400, -400, -400, -400, -400, -400, -400,
+     -400, -400, -400, -400, -400, -400, -400, -400, -400, -400,
+     -400, -400,  401, -400, -400, -400, -400, -400, -400, -400,
+     -400, -400, -400, -400, -400, -400, -400, -400, -400, -400,
+     -400, -400, -400, -400, -400, -400, -400, -400, -400, -400,
+     -400, -400, -400, -400, -400, -400, -400, -400, -400, -400,
+     -400, -400, -400, -400, -400, -400, -400, -400, -400, -400,
+     -400, -400, -400, -400, -400, -400, -400, -400, -400, -400,
+     -400, -400, -400, -400, -400, -400, -400, -400, -400, -400,
+
+     -400, -400, -400, -400, -400, -400, -400, -400, -400, -400,
+     -400, -400, -400, -400, -400, -400, -400, -400, -400, -400,
+     -400, -400, -400, -400, -400, -400, -400, -400
+    },
+
+    {
+       33, -401, -401, -401, -401, -401, -401, -401, -401, -401,
+     -401, -401, -401, -401, -401, -401, -401, -401, -401, -401,
+     -401, -401, -401, -401, -401, -401, -401, -401, -401, -401,
+     -401, -401,  402, -401, -401, -401, -401, -401, -401, -401,
+     -401, -401, -401, -401, -401, -401, -401, -401, -401, -401,
+     -401, -401, -401, -401, -401, -401, -401, -401, -401, -401,
+     -401, -401, -401, -401, -401, -401, -401, -401, -401, -401,
+
+     -401, -401, -401, -401, -401, -401, -401, -401, -401, -401,
+     -401, -401, -401, -401, -401, -401, -401, -401, -401, -401,
+     -401, -401, -401, -401, -401, -401, -401, -401, -401, -401,
+     -401, -401, -401, -401, -401, -401, -401, -401, -401, -401,
+     -401, -401, -401, -401, -401, -401, -401, -401, -401, -401,
+     -401, -401, -401, -401, -401, -401, -401, -401
+    },
+
+    {
+       33, -402, -402, -402, -402, -402, -402, -402, -402, -402,
+     -402, -402, -402, -402, -402, -402, -402, -402, -402, -402,
+     -402, -402, -402, -402, -402, -402, -402, -402, -402, -402,
+     -402, -402,  403, -402, -402, -402, -402, -402, -402, -402,
+
+     -402, -402, -402, -402, -402, -402, -402, -402, -402, -402,
+     -402, -402, -402, -402, -402, -402, -402, -402, -402, -402,
+     -402, -402, -402, -402, -402, -402, -402, -402, -402, -402,
+     -402, -402, -402, -402, -402, -402, -402, -402, -402, -402,
+     -402, -402, -402, -402, -402, -402, -402, -402, -402, -402,
+     -402, -402, -402, -402, -402, -402, -402, -402, -402, -402,
+     -402, -402, -402, -402, -402, -402, -402, -402, -402, -402,
+     -402, -402, -402, -402, -402, -402, -402, -402, -402, -402,
+     -402, -402, -402, -402, -402, -402, -402, -402
+    },
+
+    {
+       33, -403, -403, -403, -403, -403, -403, -403, -403, -403,
+
+     -403, -403, -403, -403, -403, -403, -403, -403, -403, -403,
+     -403, -403, -403, -403, -403, -403, -403, -403, -403, -403,
+     -403, -403,  404, -403, -403, -403, -403, -403, -403, -403,
+     -403, -403, -403, -403, -403, -403, -403, -403, -403, -403,
+     -403, -403, -403, -403, -403, -403, -403, -403, -403, -403,
+     -403, -403, -403, -403, -403, -403, -403, -403, -403, -403,
+     -403, -403, -403, -403, -403, -403, -403, -403, -403, -403,
+     -403, -403, -403, -403, -403, -403, -403, -403, -403, -403,
+     -403, -403, -403, -403, -403, -403, -403, -403, -403, -403,
+     -403, -403, -403, -403, -403, -403, -403, -403, -403, -403,
+
+     -403, -403, -403, -403, -403, -403, -403, -403, -403, -403,
+     -403, -403, -403, -403, -403, -403, -403, -403
+    },
+
+    {
+       33, -404, -404, -404, -404, -404, -404, -404, -404, -404,
+     -404, -404, -404, -404, -404, -404, -404, -404, -404, -404,
+     -404, -404, -404, -404, -404, -404, -404, -404, -404, -404,
+     -404, -404,  405, -404, -404, -404, -404, -404, -404, -404,
+     -404, -404, -404, -404, -404, -404, -404, -404, -404, -404,
+     -404, -404, -404, -404, -404, -404, -404, -404, -404, -404,
+     -404, -404, -404, -404, -404, -404, -404, -404, -404, -404,
+     -404, -404, -404, -404, -404, -404, -404, -404, -404, -404,
+
+     -404, -404, -404, -404, -404, -404, -404, -404, -404, -404,
+     -404, -404, -404, -404, -404, -404, -404, -404, -404, -404,
+     -404, -404, -404, -404, -404, -404, -404, -404, -404, -404,
+     -404, -404, -404, -404, -404, -404, -404, -404, -404, -404,
+     -404, -404, -404, -404, -404, -404, -404, -404
+    },
+
+    {
+       33, -405, -405, -405, -405, -405, -405, -405, -405, -405,
+     -405, -405, -405, -405, -405, -405, -405, -405, -405, -405,
+     -405, -405, -405, -405, -405, -405, -405, -405, -405, -405,
+     -405, -405,  406, -405, -405, -405, -405, -405, -405, -405,
+     -405, -405, -405, -405, -405, -405, -405, -405, -405, -405,
+
+     -405, -405, -405, -405, -405, -405, -405, -405, -405, -405,
+     -405, -405, -405, -405, -405, -405, -405, -405, -405, -405,
+     -405, -405, -405, -405, -405, -405, -405, -405, -405, -405,
+     -405, -405, -405, -405, -405, -405, -405, -405, -405, -405,
+     -405, -405, -405, -405, -405, -405, -405, -405, -405, -405,
+     -405, -405, -405, -405, -405, -405, -405, -405, -405, -405,
+     -405, -405, -405, -405, -405, -405, -405, -405, -405, -405,
+     -405, -405, -405, -405, -405, -405, -405, -405
+    },
+
+    {
+       33, -406, -406, -406, -406, -406, -406, -406, -406, -406,
+     -406, -406, -406, -406, -406, -406, -406, -406, -406, -406,
+
+     -406, -406, -406, -406, -406, -406, -406, -406, -406, -406,
+     -406, -406,  407, -406, -406, -406, -406, -406, -406, -406,
+     -406, -406, -406, -406, -406, -406, -406, -406, -406, -406,
+     -406, -406, -406, -406, -406, -406, -406, -406, -406, -406,
+     -406, -406, -406, -406, -406, -406, -406, -406, -406, -406,
+     -406, -406, -406, -406, -406, -406, -406, -406, -406, -406,
+     -406, -406, -406, -406, -406, -406, -406, -406, -406, -406,
+     -406, -406, -406, -406, -406, -406, -406, -406, -406, -406,
+     -406, -406, -406, -406, -406, -406, -406, -406, -406, -406,
+     -406, -406, -406, -406, -406, -406, -406, -406, -406, -406,
+
+     -406, -406, -406, -406, -406, -406, -406, -406
+    },
+
+    {
+       33, -407, -407, -407, -407, -407, -407, -407, -407, -407,
+     -407, -407, -407, -407, -407, -407, -407, -407, -407, -407,
+     -407, -407, -407, -407, -407, -407, -407, -407, -407, -407,
+     -407, -407,  408, -407, -407, -407, -407, -407, -407, -407,
+     -407, -407, -407, -407, -407, -407, -407, -407, -407, -407,
+     -407, -407, -407, -407, -407, -407, -407, -407, -407, -407,
+     -407, -407, -407, -407, -407, -407, -407, -407, -407, -407,
+     -407, -407, -407, -407, -407, -407, -407, -407, -407, -407,
+     -407, -407, -407, -407, -407, -407, -407, -407, -407, -407,
+
+     -407, -407, -407, -407, -407, -407, -407, -407, -407, -407,
+     -407, -407, -407, -407, -407, -407, -407, -407, -407, -407,
+     -407, -407, -407, -407, -407, -407, -407, -407, -407, -407,
+     -407, -407, -407, -407, -407, -407, -407, -407
+    },
+
+    {
+       33, -408, -408, -408, -408, -408, -408, -408, -408, -408,
+     -408, -408, -408, -408, -408, -408, -408, -408, -408, -408,
+     -408, -408, -408, -408, -408, -408, -408, -408, -408, -408,
+     -408, -408,  409, -408, -408, -408, -408, -408, -408, -408,
+     -408, -408, -408, -408, -408, -408, -408, -408, -408, -408,
+     -408, -408, -408, -408, -408, -408, -408, -408, -408, -408,
+
+     -408, -408, -408, -408, -408, -408, -408, -408, -408, -408,
+     -408, -408, -408, -408, -408, -408, -408, -408, -408, -408,
+     -408, -408, -408, -408, -408, -408, -408, -408, -408, -408,
+     -408, -408, -408, -408, -408, -408, -408, -408, -408, -408,
+     -408, -408, -408, -408, -408, -408, -408, -408, -408, -408,
+     -408, -408, -408, -408, -408, -408, -408, -408, -408, -408,
+     -408, -408, -408, -408, -408, -408, -408, -408
+    },
+
+    {
+       33, -409, -409, -409, -409, -409, -409, -409, -409, -409,
+     -409, -409, -409, -409, -409, -409, -409, -409, -409, -409,
+     -409, -409, -409, -409, -409, -409, -409, -409, -409, -409,
+
+     -409, -409,  410, -409, -409, -409, -409, -409, -409, -409,
+     -409, -409, -409, -409, -409, -409, -409, -409, -409, -409,
+     -409, -409, -409, -409, -409, -409, -409, -409, -409, -409,
+     -409, -409, -409, -409, -409, -409, -409, -409, -409, -409,
+     -409, -409, -409, -409, -409, -409, -409, -409, -409, -409,
+     -409, -409, -409, -409, -409, -409, -409, -409, -409, -409,
+     -409, -409, -409, -409, -409, -409, -409, -409, -409, -409,
+     -409, -409, -409, -409, -409, -409, -409, -409, -409, -409,
+     -409, -409, -409, -409, -409, -409, -409, -409, -409, -409,
+     -409, -409, -409, -409, -409, -409, -409, -409
+
+    },
+
+    {
+       33, -410, -410, -410, -410, -410, -410, -410, -410, -410,
+     -410, -410, -410, -410, -410, -410, -410, -410, -410, -410,
+     -410, -410, -410, -410, -410, -410, -410, -410, -410, -410,
+     -410, -410,  411, -410, -410, -410, -410, -410, -410, -410,
+     -410, -410, -410, -410, -410, -410, -410, -410, -410, -410,
+     -410, -410, -410, -410, -410, -410, -410, -410, -410, -410,
+     -410, -410, -410, -410, -410, -410, -410, -410, -410, -410,
+     -410, -410, -410, -410, -410, -410, -410, -410, -410, -410,
+     -410, -410, -410, -410, -410, -410, -410, -410, -410, -410,
+     -410, -410, -410, -410, -410, -410, -410, -410, -410, -410,
+
+     -410, -410, -410, -410, -410, -410, -410, -410, -410, -410,
+     -410, -410, -410, -410, -410, -410, -410, -410, -410, -410,
+     -410, -410, -410, -410, -410, -410, -410, -410
+    },
+
+    {
+       33, -411, -411, -411, -411, -411, -411, -411, -411, -411,
+     -411, -411, -411, -411, -411, -411, -411, -411, -411, -411,
+     -411, -411, -411, -411, -411, -411, -411, -411, -411, -411,
+     -411, -411,  412, -411, -411, -411, -411, -411, -411, -411,
+     -411, -411, -411, -411, -411, -411, -411, -411, -411, -411,
+     -411, -411, -411, -411, -411, -411, -411, -411, -411, -411,
+     -411, -411, -411, -411, -411, -411, -411, -411, -411, -411,
+
+     -411, -411, -411, -411, -411, -411, -411, -411, -411, -411,
+     -411, -411, -411, -411, -411, -411, -411, -411, -411, -411,
+     -411, -411, -411, -411, -411, -411, -411, -411, -411, -411,
+     -411, -411, -411, -411, -411, -411, -411, -411, -411, -411,
+     -411, -411, -411, -411, -411, -411, -411, -411, -411, -411,
+     -411, -411, -411, -411, -411, -411, -411, -411
+    },
+
+    {
+       33, -412, -412, -412, -412, -412, -412, -412, -412, -412,
+     -412, -412, -412, -412, -412, -412, -412, -412, -412, -412,
+     -412, -412, -412, -412, -412, -412, -412, -412, -412, -412,
+     -412, -412,  413, -412, -412, -412, -412, -412, -412, -412,
+
+     -412, -412, -412, -412, -412, -412, -412, -412, -412, -412,
+     -412, -412, -412, -412, -412, -412, -412, -412, -412, -412,
+     -412, -412, -412, -412, -412, -412, -412, -412, -412, -412,
+     -412, -412, -412, -412, -412, -412, -412, -412, -412, -412,
+     -412, -412, -412, -412, -412, -412, -412, -412, -412, -412,
+     -412, -412, -412, -412, -412, -412, -412, -412, -412, -412,
+     -412, -412, -412, -412, -412, -412, -412, -412, -412, -412,
+     -412, -412, -412, -412, -412, -412, -412, -412, -412, -412,
+     -412, -412, -412, -412, -412, -412, -412, -412
+    },
+
+    {
+       33, -413, -413, -413, -413, -413, -413, -413, -413, -413,
+
+     -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
+     -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
+     -413, -413,  414, -413, -413, -413, -413, -413, -413, -413,
+     -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
+     -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
+     -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
+     -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
+     -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
+     -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
+     -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
+
+     -413, -413, -413, -413, -413, -413, -413, -413, -413, -413,
+     -413, -413, -413, -413, -413, -413, -413, -413
+    },
+
+    {
+       33, -414, -414, -414, -414, -414, -414, -414, -414, -414,
+     -414, -414, -414, -414, -414, -414, -414, -414, -414, -414,
+     -414, -414, -414, -414, -414, -414, -414, -414, -414, -414,
+     -414, -414,  415, -414, -414, -414, -414, -414, -414, -414,
+     -414, -414, -414, -414, -414, -414, -414, -414, -414, -414,
+     -414, -414, -414, -414, -414, -414, -414, -414, -414, -414,
+     -414, -414, -414, -414, -414, -414, -414, -414, -414, -414,
+     -414, -414, -414, -414, -414, -414, -414, -414, -414, -414,
+
+     -414, -414, -414, -414, -414, -414, -414, -414, -414, -414,
+     -414, -414, -414, -414, -414, -414, -414, -414, -414, -414,
+     -414, -414, -414, -414, -414, -414, -414, -414, -414, -414,
+     -414, -414, -414, -414, -414, -414, -414, -414, -414, -414,
+     -414, -414, -414, -414, -414, -414, -414, -414
+    },
+
+    {
+       33, -415, -415, -415, -415, -415, -415, -415, -415, -415,
+     -415, -415, -415, -415, -415, -415, -415, -415, -415, -415,
+     -415, -415, -415, -415, -415, -415, -415, -415, -415, -415,
+     -415, -415,  416, -415, -415, -415, -415, -415, -415, -415,
+     -415, -415, -415, -415, -415, -415, -415, -415, -415, -415,
+
+     -415, -415, -415, -415, -415, -415, -415, -415, -415, -415,
+     -415, -415, -415, -415, -415, -415, -415, -415, -415, -415,
+     -415, -415, -415, -415, -415, -415, -415, -415, -415, -415,
+     -415, -415, -415, -415, -415, -415, -415, -415, -415, -415,
+     -415, -415, -415, -415, -415, -415, -415, -415, -415, -415,
+     -415, -415, -415, -415, -415, -415, -415, -415, -415, -415,
+     -415, -415, -415, -415, -415, -415, -415, -415, -415, -415,
+     -415, -415, -415, -415, -415, -415, -415, -415
+    },
+
+    {
+       33, -416, -416, -416, -416, -416, -416, -416, -416, -416,
+     -416, -416, -416, -416, -416, -416, -416, -416, -416, -416,
+
+     -416, -416, -416, -416, -416, -416, -416, -416, -416, -416,
+     -416, -416,  417, -416, -416, -416, -416, -416, -416, -416,
+     -416, -416, -416, -416, -416, -416, -416, -416, -416, -416,
+     -416, -416, -416, -416, -416, -416, -416, -416, -416, -416,
+     -416, -416, -416, -416, -416, -416, -416, -416, -416, -416,
+     -416, -416, -416, -416, -416, -416, -416, -416, -416, -416,
+     -416, -416, -416, -416, -416, -416, -416, -416, -416, -416,
+     -416, -416, -416, -416, -416, -416, -416, -416, -416, -416,
+     -416, -416, -416, -416, -416, -416, -416, -416, -416, -416,
+     -416, -416, -416, -416, -416, -416, -416, -416, -416, -416,
+
+     -416, -416, -416, -416, -416, -416, -416, -416
+    },
+
+    {
+       33, -417, -417, -417, -417, -417, -417, -417, -417, -417,
+     -417, -417, -417, -417, -417, -417, -417, -417, -417, -417,
+     -417, -417, -417, -417, -417, -417, -417, -417, -417, -417,
+     -417, -417,  418, -417, -417, -417, -417, -417, -417, -417,
+     -417, -417, -417, -417, -417, -417, -417, -417, -417, -417,
+     -417, -417, -417, -417, -417, -417, -417, -417, -417, -417,
+     -417, -417, -417, -417, -417, -417, -417, -417, -417, -417,
+     -417, -417, -417, -417, -417, -417, -417, -417, -417, -417,
+     -417, -417, -417, -417, -417, -417, -417, -417, -417, -417,
+
+     -417, -417, -417, -417, -417, -417, -417, -417, -417, -417,
+     -417, -417, -417, -417, -417, -417, -417, -417, -417, -417,
+     -417, -417, -417, -417, -417, -417, -417, -417, -417, -417,
+     -417, -417, -417, -417, -417, -417, -417, -417
+    },
+
+    {
+       33, -418, -418, -418, -418, -418, -418, -418, -418, -418,
+     -418, -418, -418, -418, -418, -418, -418, -418, -418, -418,
+     -418, -418, -418, -418, -418, -418, -418, -418, -418, -418,
+     -418, -418,  419, -418, -418, -418, -418, -418, -418, -418,
+     -418, -418, -418, -418, -418, -418, -418, -418, -418, -418,
+     -418, -418, -418, -418, -418, -418, -418, -418, -418, -418,
+
+     -418, -418, -418, -418, -418, -418, -418, -418, -418, -418,
+     -418, -418, -418, -418, -418, -418, -418, -418, -418, -418,
+     -418, -418, -418, -418, -418, -418, -418, -418, -418, -418,
+     -418, -418, -418, -418, -418, -418, -418, -418, -418, -418,
+     -418, -418, -418, -418, -418, -418, -418, -418, -418, -418,
+     -418, -418, -418, -418, -418, -418, -418, -418, -418, -418,
+     -418, -418, -418, -418, -418, -418, -418, -418
+    },
+
+    {
+       33, -419, -419, -419, -419, -419, -419, -419, -419, -419,
+     -419, -419, -419, -419, -419, -419, -419, -419, -419, -419,
+     -419, -419, -419, -419, -419, -419, -419, -419, -419, -419,
+
+     -419, -419,  420, -419, -419, -419, -419, -419, -419, -419,
+     -419, -419, -419, -419, -419, -419, -419, -419, -419, -419,
+     -419, -419, -419, -419, -419, -419, -419, -419, -419, -419,
+     -419, -419, -419, -419, -419, -419, -419, -419, -419, -419,
+     -419, -419, -419, -419, -419, -419, -419, -419, -419, -419,
+     -419, -419, -419, -419, -419, -419, -419, -419, -419, -419,
+     -419, -419, -419, -419, -419, -419, -419, -419, -419, -419,
+     -419, -419, -419, -419, -419, -419, -419, -419, -419, -419,
+     -419, -419, -419, -419, -419, -419, -419, -419, -419, -419,
+     -419, -419, -419, -419, -419, -419, -419, -419
+
+    },
+
+    {
+       33, -420, -420, -420, -420, -420, -420, -420, -420, -420,
+     -420, -420, -420, -420, -420, -420, -420, -420, -420, -420,
+     -420, -420, -420, -420, -420, -420, -420, -420, -420, -420,
+     -420, -420,  421, -420, -420, -420, -420, -420, -420, -420,
+     -420, -420, -420, -420, -420, -420, -420, -420, -420, -420,
+     -420, -420, -420, -420, -420, -420, -420, -420, -420, -420,
+     -420, -420, -420, -420, -420, -420, -420, -420, -420, -420,
+     -420, -420, -420, -420, -420, -420, -420, -420, -420, -420,
+     -420, -420, -420, -420, -420, -420, -420, -420, -420, -420,
+     -420, -420, -420, -420, -420, -420, -420, -420, -420, -420,
+
+     -420, -420, -420, -420, -420, -420, -420, -420, -420, -420,
+     -420, -420, -420, -420, -420, -420, -420, -420, -420, -420,
+     -420, -420, -420, -420, -420, -420, -420, -420
+    },
+
+    {
+       33, -421, -421, -421, -421, -421, -421, -421, -421, -421,
+     -421, -421, -421, -421, -421, -421, -421, -421, -421, -421,
+     -421, -421, -421, -421, -421, -421, -421, -421, -421, -421,
+     -421, -421,  422, -421, -421, -421, -421, -421, -421, -421,
+     -421, -421, -421, -421, -421, -421, -421, -421, -421, -421,
+     -421, -421, -421, -421, -421, -421, -421, -421, -421, -421,
+     -421, -421, -421, -421, -421, -421, -421, -421, -421, -421,
+
+     -421, -421, -421, -421, -421, -421, -421, -421, -421, -421,
+     -421, -421, -421, -421, -421, -421, -421, -421, -421, -421,
+     -421, -421, -421, -421, -421, -421, -421, -421, -421, -421,
+     -421, -421, -421, -421, -421, -421, -421, -421, -421, -421,
+     -421, -421, -421, -421, -421, -421, -421, -421, -421, -421,
+     -421, -421, -421, -421, -421, -421, -421, -421
+    },
+
+    {
+       33, -422, -422, -422, -422, -422, -422, -422, -422, -422,
+     -422, -422, -422, -422, -422, -422, -422, -422, -422, -422,
+     -422, -422, -422, -422, -422, -422, -422, -422, -422, -422,
+     -422, -422,  423, -422, -422, -422, -422, -422, -422, -422,
+
+     -422, -422, -422, -422, -422, -422, -422, -422, -422, -422,
+     -422, -422, -422, -422, -422, -422, -422, -422, -422, -422,
+     -422, -422, -422, -422, -422, -422, -422, -422, -422, -422,
+     -422, -422, -422, -422, -422, -422, -422, -422, -422, -422,
+     -422, -422, -422, -422, -422, -422, -422, -422, -422, -422,
+     -422, -422, -422, -422, -422, -422, -422, -422, -422, -422,
+     -422, -422, -422, -422, -422, -422, -422, -422, -422, -422,
+     -422, -422, -422, -422, -422, -422, -422, -422, -422, -422,
+     -422, -422, -422, -422, -422, -422, -422, -422
+    },
+
+    {
+       33, -423, -423, -423, -423, -423, -423, -423, -423, -423,
+
+     -423, -423, -423, -423, -423, -423, -423, -423, -423, -423,
+     -423, -423, -423, -423, -423, -423, -423, -423, -423, -423,
+     -423, -423,  424, -423, -423, -423, -423, -423, -423, -423,
+     -423, -423, -423, -423, -423, -423, -423, -423, -423, -423,
+     -423, -423, -423, -423, -423, -423, -423, -423, -423, -423,
+     -423, -423, -423, -423, -423, -423, -423, -423, -423, -423,
+     -423, -423, -423, -423, -423, -423, -423, -423, -423, -423,
+     -423, -423, -423, -423, -423, -423, -423, -423, -423, -423,
+     -423, -423, -423, -423, -423, -423, -423, -423, -423, -423,
+     -423, -423, -423, -423, -423, -423, -423, -423, -423, -423,
+
+     -423, -423, -423, -423, -423, -423, -423, -423, -423, -423,
+     -423, -423, -423, -423, -423, -423, -423, -423
+    },
+
+    {
+       33, -424, -424, -424, -424, -424, -424, -424, -424, -424,
+     -424, -424, -424, -424, -424, -424, -424, -424, -424, -424,
+     -424, -424, -424, -424, -424, -424, -424, -424, -424, -424,
+     -424, -424,  425, -424, -424, -424, -424, -424, -424, -424,
+     -424, -424, -424, -424, -424, -424, -424, -424, -424, -424,
+     -424, -424, -424, -424, -424, -424, -424, -424, -424, -424,
+     -424, -424, -424, -424, -424, -424, -424, -424, -424, -424,
+     -424, -424, -424, -424, -424, -424, -424, -424, -424, -424,
+
+     -424, -424, -424, -424, -424, -424, -424, -424, -424, -424,
+     -424, -424, -424, -424, -424, -424, -424, -424, -424, -424,
+     -424, -424, -424, -424, -424, -424, -424, -424, -424, -424,
+     -424, -424, -424, -424, -424, -424, -424, -424, -424, -424,
+     -424, -424, -424, -424, -424, -424, -424, -424
+    },
+
+    {
+       33, -425, -425, -425, -425, -425, -425, -425, -425, -425,
+     -425, -425, -425, -425, -425, -425, -425, -425, -425, -425,
+     -425, -425, -425, -425, -425, -425, -425, -425, -425, -425,
+     -425, -425,  426, -425, -425, -425, -425, -425, -425, -425,
+     -425, -425, -425, -425, -425, -425, -425, -425, -425, -425,
+
+     -425, -425, -425, -425, -425, -425, -425, -425, -425, -425,
+     -425, -425, -425, -425, -425, -425, -425, -425, -425, -425,
+     -425, -425, -425, -425, -425, -425, -425, -425, -425, -425,
+     -425, -425, -425, -425, -425, -425, -425, -425, -425, -425,
+     -425, -425, -425, -425, -425, -425, -425, -425, -425, -425,
+     -425, -425, -425, -425, -425, -425, -425, -425, -425, -425,
+     -425, -425, -425, -425, -425, -425, -425, -425, -425, -425,
+     -425, -425, -425, -425, -425, -425, -425, -425
+    },
+
+    {
+       33, -426, -426, -426, -426, -426, -426, -426, -426, -426,
+     -426, -426, -426, -426, -426, -426, -426, -426, -426, -426,
+
+     -426, -426, -426, -426, -426, -426, -426, -426, -426, -426,
+     -426, -426,  427, -426, -426, -426, -426, -426, -426, -426,
+     -426, -426, -426, -426, -426, -426, -426, -426, -426, -426,
+     -426, -426, -426, -426, -426, -426, -426, -426, -426, -426,
+     -426, -426, -426, -426, -426, -426, -426, -426, -426, -426,
+     -426, -426, -426, -426, -426, -426, -426, -426, -426, -426,
+     -426, -426, -426, -426, -426, -426, -426, -426, -426, -426,
+     -426, -426, -426, -426, -426, -426, -426, -426, -426, -426,
+     -426, -426, -426, -426, -426, -426, -426, -426, -426, -426,
+     -426, -426, -426, -426, -426, -426, -426, -426, -426, -426,
+
+     -426, -426, -426, -426, -426, -426, -426, -426
+    },
+
+    {
+       33, -427, -427, -427, -427, -427, -427, -427, -427, -427,
+     -427, -427, -427, -427, -427, -427, -427, -427, -427, -427,
+     -427, -427, -427, -427, -427, -427, -427, -427, -427, -427,
+     -427, -427,  428, -427, -427, -427, -427, -427, -427, -427,
+     -427, -427, -427, -427, -427, -427, -427, -427, -427, -427,
+     -427, -427, -427, -427, -427, -427, -427, -427, -427, -427,
+     -427, -427, -427, -427, -427, -427, -427, -427, -427, -427,
+     -427, -427, -427, -427, -427, -427, -427, -427, -427, -427,
+     -427, -427, -427, -427, -427, -427, -427, -427, -427, -427,
+
+     -427, -427, -427, -427, -427, -427, -427, -427, -427, -427,
+     -427, -427, -427, -427, -427, -427, -427, -427, -427, -427,
+     -427, -427, -427, -427, -427, -427, -427, -427, -427, -427,
+     -427, -427, -427, -427, -427, -427, -427, -427
+    },
+
+    {
+       33, -428, -428, -428, -428, -428, -428, -428, -428, -428,
+     -428, -428, -428, -428, -428, -428, -428, -428, -428, -428,
+     -428, -428, -428, -428, -428, -428, -428, -428, -428, -428,
+     -428, -428,  429, -428, -428, -428, -428, -428, -428, -428,
+     -428, -428, -428, -428, -428, -428, -428, -428, -428, -428,
+     -428, -428, -428, -428, -428, -428, -428, -428, -428, -428,
+
+     -428, -428, -428, -428, -428, -428, -428, -428, -428, -428,
+     -428, -428, -428, -428, -428, -428, -428, -428, -428, -428,
+     -428, -428, -428, -428, -428, -428, -428, -428, -428, -428,
+     -428, -428, -428, -428, -428, -428, -428, -428, -428, -428,
+     -428, -428, -428, -428, -428, -428, -428, -428, -428, -428,
+     -428, -428, -428, -428, -428, -428, -428, -428, -428, -428,
+     -428, -428, -428, -428, -428, -428, -428, -428
+    },
+
+    {
+       33, -429, -429, -429, -429, -429, -429, -429, -429, -429,
+     -429, -429, -429, -429, -429, -429, -429, -429, -429, -429,
+     -429, -429, -429, -429, -429, -429, -429, -429, -429, -429,
+
+     -429, -429,  430, -429, -429, -429, -429, -429, -429, -429,
+     -429, -429, -429, -429, -429, -429, -429, -429, -429, -429,
+     -429, -429, -429, -429, -429, -429, -429, -429, -429, -429,
+     -429, -429, -429, -429, -429, -429, -429, -429, -429, -429,
+     -429, -429, -429, -429, -429, -429, -429, -429, -429, -429,
+     -429, -429, -429, -429, -429, -429, -429, -429, -429, -429,
+     -429, -429, -429, -429, -429, -429, -429, -429, -429, -429,
+     -429, -429, -429, -429, -429, -429, -429, -429, -429, -429,
+     -429, -429, -429, -429, -429, -429, -429, -429, -429, -429,
+     -429, -429, -429, -429, -429, -429, -429, -429
+
+    },
+
+    {
+       33, -430, -430, -430, -430, -430, -430, -430, -430, -430,
+     -430, -430, -430, -430, -430, -430, -430, -430, -430, -430,
+     -430, -430, -430, -430, -430, -430, -430, -430, -430, -430,
+     -430, -430,  431, -430, -430, -430, -430, -430, -430, -430,
+     -430, -430, -430, -430, -430, -430, -430, -430, -430, -430,
+     -430, -430, -430, -430, -430, -430, -430, -430, -430, -430,
+     -430, -430, -430, -430, -430, -430, -430, -430, -430, -430,
+     -430, -430, -430, -430, -430, -430, -430, -430, -430, -430,
+     -430, -430, -430, -430, -430, -430, -430, -430, -430, -430,
+     -430, -430, -430, -430, -430, -430, -430, -430, -430, -430,
+
+     -430, -430, -430, -430, -430, -430, -430, -430, -430, -430,
+     -430, -430, -430, -430, -430, -430, -430, -430, -430, -430,
+     -430, -430, -430, -430, -430, -430, -430, -430
+    },
+
+    {
+       33, -431, -431, -431, -431, -431, -431, -431, -431, -431,
+     -431, -431, -431, -431, -431, -431, -431, -431, -431, -431,
+     -431, -431, -431, -431, -431, -431, -431, -431, -431, -431,
+     -431, -431,  432, -431, -431, -431, -431, -431, -431, -431,
+     -431, -431, -431, -431, -431, -431, -431, -431, -431, -431,
+     -431, -431, -431, -431, -431, -431, -431, -431, -431, -431,
+     -431, -431, -431, -431, -431, -431, -431, -431, -431, -431,
+
+     -431, -431, -431, -431, -431, -431, -431, -431, -431, -431,
+     -431, -431, -431, -431, -431, -431, -431, -431, -431, -431,
+     -431, -431, -431, -431, -431, -431, -431, -431, -431, -431,
+     -431, -431, -431, -431, -431, -431, -431, -431, -431, -431,
+     -431, -431, -431, -431, -431, -431, -431, -431, -431, -431,
+     -431, -431, -431, -431, -431, -431, -431, -431
+    },
+
+    {
+       33, -432, -432, -432, -432, -432, -432, -432, -432, -432,
+     -432, -432, -432, -432, -432, -432, -432, -432, -432, -432,
+     -432, -432, -432, -432, -432, -432, -432, -432, -432, -432,
+     -432, -432,  433, -432, -432, -432, -432, -432, -432, -432,
+
+     -432, -432, -432, -432, -432, -432, -432, -432, -432, -432,
+     -432, -432, -432, -432, -432, -432, -432, -432, -432, -432,
+     -432, -432, -432, -432, -432, -432, -432, -432, -432, -432,
+     -432, -432, -432, -432, -432, -432, -432, -432, -432, -432,
+     -432, -432, -432, -432, -432, -432, -432, -432, -432, -432,
+     -432, -432, -432, -432, -432, -432, -432, -432, -432, -432,
+     -432, -432, -432, -432, -432, -432, -432, -432, -432, -432,
+     -432, -432, -432, -432, -432, -432, -432, -432, -432, -432,
+     -432, -432, -432, -432, -432, -432, -432, -432
+    },
+
+    {
+       33, -433, -433, -433, -433, -433, -433, -433, -433, -433,
+
+     -433, -433, -433, -433, -433, -433, -433, -433, -433, -433,
+     -433, -433, -433, -433, -433, -433, -433, -433, -433, -433,
+     -433, -433,  434, -433, -433, -433, -433, -433, -433, -433,
+     -433, -433, -433, -433, -433, -433, -433, -433, -433, -433,
+     -433, -433, -433, -433, -433, -433, -433, -433, -433, -433,
+     -433, -433, -433, -433, -433, -433, -433, -433, -433, -433,
+     -433, -433, -433, -433, -433, -433, -433, -433, -433, -433,
+     -433, -433, -433, -433, -433, -433, -433, -433, -433, -433,
+     -433, -433, -433, -433, -433, -433, -433, -433, -433, -433,
+     -433, -433, -433, -433, -433, -433, -433, -433, -433, -433,
+
+     -433, -433, -433, -433, -433, -433, -433, -433, -433, -433,
+     -433, -433, -433, -433, -433, -433, -433, -433
+    },
+
+    {
+       33, -434, -434, -434, -434, -434, -434, -434, -434, -434,
+     -434, -434, -434, -434, -434, -434, -434, -434, -434, -434,
+     -434, -434, -434, -434, -434, -434, -434, -434, -434, -434,
+     -434, -434,  435, -434, -434, -434, -434, -434, -434, -434,
+     -434, -434, -434, -434, -434, -434, -434, -434, -434, -434,
+     -434, -434, -434, -434, -434, -434, -434, -434, -434, -434,
+     -434, -434, -434, -434, -434, -434, -434, -434, -434, -434,
+     -434, -434, -434, -434, -434, -434, -434, -434, -434, -434,
+
+     -434, -434, -434, -434, -434, -434, -434, -434, -434, -434,
+     -434, -434, -434, -434, -434, -434, -434, -434, -434, -434,
+     -434, -434, -434, -434, -434, -434, -434, -434, -434, -434,
+     -434, -434, -434, -434, -434, -434, -434, -434, -434, -434,
+     -434, -434, -434, -434, -434, -434, -434, -434
+    },
+
+    {
+       33, -435, -435, -435, -435, -435, -435, -435, -435, -435,
+     -435, -435, -435, -435, -435, -435, -435, -435, -435, -435,
+     -435, -435, -435, -435, -435, -435, -435, -435, -435, -435,
+     -435, -435,  436, -435, -435, -435, -435, -435, -435, -435,
+     -435, -435, -435, -435, -435, -435, -435, -435, -435, -435,
+
+     -435, -435, -435, -435, -435, -435, -435, -435, -435, -435,
+     -435, -435, -435, -435, -435, -435, -435, -435, -435, -435,
+     -435, -435, -435, -435, -435, -435, -435, -435, -435, -435,
+     -435, -435, -435, -435, -435, -435, -435, -435, -435, -435,
+     -435, -435, -435, -435, -435, -435, -435, -435, -435, -435,
+     -435, -435, -435, -435, -435, -435, -435, -435, -435, -435,
+     -435, -435, -435, -435, -435, -435, -435, -435, -435, -435,
+     -435, -435, -435, -435, -435, -435, -435, -435
+    },
+
+    {
+       33, -436, -436, -436, -436, -436, -436, -436, -436, -436,
+     -436, -436, -436, -436, -436, -436, -436, -436, -436, -436,
+
+     -436, -436, -436, -436, -436, -436, -436, -436, -436, -436,
+     -436, -436,  437, -436, -436, -436, -436, -436, -436, -436,
+     -436, -436, -436, -436, -436, -436, -436, -436, -436, -436,
+     -436, -436, -436, -436, -436, -436, -436, -436, -436, -436,
+     -436, -436, -436, -436, -436, -436, -436, -436, -436, -436,
+     -436, -436, -436, -436, -436, -436, -436, -436, -436, -436,
+     -436, -436, -436, -436, -436, -436, -436, -436, -436, -436,
+     -436, -436, -436, -436, -436, -436, -436, -436, -436, -436,
+     -436, -436, -436, -436, -436, -436, -436, -436, -436, -436,
+     -436, -436, -436, -436, -436, -436, -436, -436, -436, -436,
+
+     -436, -436, -436, -436, -436, -436, -436, -436
+    },
+
+    {
+       33, -437, -437, -437, -437, -437, -437, -437, -437, -437,
+     -437, -437, -437, -437, -437, -437, -437, -437, -437, -437,
+     -437, -437, -437, -437, -437, -437, -437, -437, -437, -437,
+     -437, -437,  438, -437, -437, -437, -437, -437, -437, -437,
+     -437, -437, -437, -437, -437, -437, -437, -437, -437, -437,
+     -437, -437, -437, -437, -437, -437, -437, -437, -437, -437,
+     -437, -437, -437, -437, -437, -437, -437, -437, -437, -437,
+     -437, -437, -437, -437, -437, -437, -437, -437, -437, -437,
+     -437, -437, -437, -437, -437, -437, -437, -437, -437, -437,
+
+     -437, -437, -437, -437, -437, -437, -437, -437, -437, -437,
+     -437, -437, -437, -437, -437, -437, -437, -437, -437, -437,
+     -437, -437, -437, -437, -437, -437, -437, -437, -437, -437,
+     -437, -437, -437, -437, -437, -437, -437, -437
+    },
+
+    {
+       33, -438, -438, -438, -438, -438, -438, -438, -438, -438,
+     -438, -438, -438, -438, -438, -438, -438, -438, -438, -438,
+     -438, -438, -438, -438, -438, -438, -438, -438, -438, -438,
+     -438, -438,  439, -438, -438, -438, -438, -438, -438, -438,
+     -438, -438, -438, -438, -438, -438, -438, -438, -438, -438,
+     -438, -438, -438, -438, -438, -438, -438, -438, -438, -438,
+
+     -438, -438, -438, -438, -438, -438, -438, -438, -438, -438,
+     -438, -438, -438, -438, -438, -438, -438, -438, -438, -438,
+     -438, -438, -438, -438, -438, -438, -438, -438, -438, -438,
+     -438, -438, -438, -438, -438, -438, -438, -438, -438, -438,
+     -438, -438, -438, -438, -438, -438, -438, -438, -438, -438,
+     -438, -438, -438, -438, -438, -438, -438, -438, -438, -438,
+     -438, -438, -438, -438, -438, -438, -438, -438
+    },
+
+    {
+       33, -439, -439, -439, -439, -439, -439, -439, -439, -439,
+     -439, -439, -439, -439, -439, -439, -439, -439, -439, -439,
+     -439, -439, -439, -439, -439, -439, -439, -439, -439, -439,
+
+     -439, -439,  440, -439, -439, -439, -439, -439, -439, -439,
+     -439, -439, -439, -439, -439, -439, -439, -439, -439, -439,
+     -439, -439, -439, -439, -439, -439, -439, -439, -439, -439,
+     -439, -439, -439, -439, -439, -439, -439, -439, -439, -439,
+     -439, -439, -439, -439, -439, -439, -439, -439, -439, -439,
+     -439, -439, -439, -439, -439, -439, -439, -439, -439, -439,
+     -439, -439, -439, -439, -439, -439, -439, -439, -439, -439,
+     -439, -439, -439, -439, -439, -439, -439, -439, -439, -439,
+     -439, -439, -439, -439, -439, -439, -439, -439, -439, -439,
+     -439, -439, -439, -439, -439, -439, -439, -439
+
+    },
+
+    {
+       33, -440, -440, -440, -440, -440, -440, -440, -440, -440,
+     -440, -440, -440, -440, -440, -440, -440, -440, -440, -440,
+     -440, -440, -440, -440, -440, -440, -440, -440, -440, -440,
+     -440, -440, -440, -440, -440, -440, -440, -440, -440, -440,
+     -440, -440, -440, -440, -440, -440, -440, -440, -440, -440,
+     -440, -440, -440, -440, -440, -440, -440, -440, -440, -440,
+     -440, -440, -440, -440, -440, -440, -440, -440, -440, -440,
+     -440, -440, -440, -440, -440, -440, -440, -440, -440, -440,
+     -440, -440, -440, -440, -440, -440, -440, -440, -440, -440,
+     -440, -440, -440, -440, -440, -440, -440, -440, -440, -440,
+
+     -440, -440, -440, -440, -440, -440, -440, -440, -440, -440,
+     -440, -440, -440, -440, -440, -440, -440, -440, -440, -440,
+     -440, -440, -440, -440, -440, -440, -440, -440
+    },
+
+    } ;
+
+static yy_state_type yy_get_previous_state (void );
+static yy_state_type yy_try_NUL_trans (yy_state_type current_state  );
+static int yy_get_next_buffer (void );
+static void yy_fatal_error (yyconst char msg[]  );
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up wcspihtext.
+ */
+#define YY_DO_BEFORE_ACTION \
+	(yytext_ptr) = yy_bp; \
+	wcspihleng = (size_t) (yy_cp - yy_bp); \
+	(yy_hold_char) = *yy_cp; \
+	*yy_cp = '\0'; \
+	(yy_c_buf_p) = yy_cp;
+
+#define YY_NUM_RULES 94
+#define YY_END_OF_BUFFER 95
+/* This struct is not used in this scanner,
+   but its presence is necessary. */
+struct yy_trans_info
+	{
+	flex_int32_t yy_verify;
+	flex_int32_t yy_nxt;
+	};
+static yyconst flex_int16_t yy_accept[441] =
+    {   0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,   89,   89,   91,   91,   92,   92,
+        0,    0,   95,   94,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   63,   63,
+       79,   79,   47,   47,   59,   59,   59,   77,   77,   66,
+       64,   65,   81,   81,   83,   83,   82,   85,   85,   85,
+       84,   87,   87,   90,   89,   88,   91,   92,   94,   93,
+        5,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    4,    0,   18,   16,    0,
+
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,   80,   82,    0,
+       84,   84,   84,   84,    0,    0,   86,   89,   88,   88,
+       91,   92,    0,   93,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,   60,   61,   62,   78,   44,   45,   46,    0,    0,
+        0,    0,    0,    0,    0,    0,   84,    0,   84,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    6,   19,   20,    7,    3,   10,   21,    9,    8,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+       17,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,   58,   57,   53,   56,
+
+       50,   51,   55,   48,   49,   52,   54,   76,   72,   75,
+       69,   70,   74,   67,   68,   71,   73,    0,    0,    0,
+        0,   25,   12,   11,    0,    0,    0,    0,    0,   31,
+        0,   13,   15,   33,   34,   35,   36,   37,    0,    0,
+        0,   40,   41,   22,   23,    0,   24,   26,   27,    0,
+       28,   29,   30,   32,   14,   38,   39,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    1,    0,    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,    0,    0,    0,    0,    0,    0,
+
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,   42
+    } ;
+
+static yy_state_type yy_last_accepting_state;
+static char *yy_last_accepting_cpos;
+
+static yyconst yy_state_type yy_NUL_trans[441] =
+    {   0,
+       34,   35,   49,   49,   51,   51,   53,   53,   55,   55,
+       58,   58,   60,   60,   62,   62,   63,   63,   65,   65,
+       68,   68,   72,   72,   74,   74,   77,   77,   78,   78,
+       79,   79,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,  126,    0,    0,  130,  131,  132,  133,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,  126,    0,    0,  130,  130,
+      131,  132,  133,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0
+    } ;
+
+extern int wcspih_flex_debug;
+int wcspih_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 yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+char *wcspihtext;
+#line 1 "wcspih.l"
+/*============================================================================
+
+  WCSLIB 4.16 - an implementation of the FITS WCS standard.
+  Copyright (C) 1995-2012, Mark Calabretta
+
+  This file is part of WCSLIB.
+
+  WCSLIB is free software: you can redistribute it and/or modify it under the
+  terms of the GNU Lesser General Public License as published by the Free
+  Software Foundation, either version 3 of the License, or (at your option)
+  any later version.
+
+  WCSLIB 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 Lesser General Public License for
+  more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with WCSLIB.  If not, see http://www.gnu.org/licenses.
+
+  Direct correspondence concerning WCSLIB to mark at calabretta.id.au
+
+  Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
+  http://www.atnf.csiro.au/people/Mark.Calabretta
+  $Id: wcspih.c,v 4.16 2012/11/07 04:42:44 cal103 Exp $
+*=============================================================================
+*
+* wcspih.l is a Flex description file containing the definition of a lexical
+* scanner for parsing the WCS keyrecords from a FITS primary image or image
+* extension header.
+*
+* wcspih.l requires Flex v2.5.4 or later.  Refer to wcshdr.h for a description
+* of the user interface and operating notes.
+*
+* Implementation notes
+* --------------------
+* Use of the WCSAXESa keyword is not mandatory.  Its default value is "the
+* larger of NAXIS and the largest index of these keywords [i.e. CRPIXj, PCi_j
+* or CDi_j, CDELTi, CTYPEi, CRVALi, and CUNITi] found in the FITS header".
+* Consequently the definition of WCSAXESa effectively invalidates the use of
+* NAXIS for determining the number of coordinate axes and forces a preliminary
+* pass through the header to determine the "largest index" in headers where
+* WCSAXESa was omitted.
+*
+* Furthermore, since the use of WCSAXESa is optional, there is no way to
+* determine the number of coordinate representations (the "a" value) other
+* than by parsing all of the WCS keywords in the header; even if WCSAXESa was
+* specified for some representations it cannot be known in advance whether it
+* was specified for all of those present in the header.
+*
+* Hence the definition of WCSAXESa forces the scanner to be implemented in two
+* passes.  The first pass is used to determine the number of coordinate
+* representations (up to 27) and the number of coordinate axes in each.
+* Effectively WCSAXESa is ignored unless it exceeds the "largest index" in
+* which case the keywords for the extra axes assume their default values.  The
+* number of PVi_ma and PSi_ma keywords in each representation is also counted
+* in the first pass.
+*
+* On completion of the first pass, memory is allocated for an array of the
+* required number of wcsprm structs and each of these is initialized
+* appropriately.  These structs are filled in the second pass.
+*
+* The parser does not check for duplicated keywords, it accepts the last
+* encountered.
+*
+*===========================================================================*/
+/* Options. */
+/* Indices for parameterized keywords. */
+/* Alternate coordinate system identifier. */
+/* Keyvalue data types. */
+/* Exclusive start states. */
+
+
+
+
+
+
+#line 99 "wcspih.l"
+#include <math.h>
+#include <setjmp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "wcs.h"
+#include "wcshdr.h"
+#include "wcsmath.h"
+#include "wcsutil.h"
+
+#define INTEGER 0
+#define FLOAT   1
+#define STRING  2
+
+#define YY_DECL int wcspih(char *header, int nkeyrec, int relax, int ctrl, \
+                           int *nreject, int *nwcs, struct wcsprm **wcs)
+
+#define YY_INPUT(inbuff, count, bufsize) \
+	{ \
+	  if (wcspih_nkeyrec) { \
+	    strncpy(inbuff, wcspih_hdr, 80); \
+	    inbuff[80] = '\n'; \
+	    wcspih_hdr += 80; \
+	    wcspih_nkeyrec--; \
+	    count = 81; \
+	  } else { \
+	    count = YY_NULL; \
+	  } \
+	}
+
+/* These global variables are required by YY_INPUT. */
+char *wcspih_hdr;
+int  wcspih_nkeyrec;
+
+int wcspih_final(int alts[], double epoch[], double vsource[], int *nwcs,
+        struct wcsprm **wcs);
+int wcspih_inits(int naxis, int alts[], int npv[], int nps[], int *nwcs,
+        struct wcsprm **wcs);
+void wcspih_naxes(int naxis, int i, int j, char a, int alts[], int *npptr);
+
+/* Used in preempting the call to exit() by yy_fatal_error(). */
+jmp_buf wcspih_abort_jmp_env;
+#define exit(status) longjmp(wcspih_abort_jmp_env, status)
+
+#line 8278 "wcspih.c"
+
+#define INITIAL 0
+#define CROTAi 1
+#define PROJPn 2
+#define CCCCCia 3
+#define CCi_ja 4
+#define CCi_ma 5
+#define CCCCCCCa 6
+#define CCCCCCCC 7
+#define VALUE 8
+#define INTEGER_VAL 9
+#define FLOAT_VAL 10
+#define STRING_VAL 11
+#define COMMENT 12
+#define DISCARD 13
+#define ERROR 14
+#define FLUSH 15
+
+#ifndef YY_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 <unistd.h>
+#endif
+
+#ifndef YY_EXTRA_TYPE
+#define YY_EXTRA_TYPE void *
+#endif
+
+static int yy_init_globals (void );
+
+/* Accessor methods to globals.
+   These are made visible to non-reentrant scanners for convenience. */
+
+int wcspihlex_destroy (void );
+
+int wcspihget_debug (void );
+
+void wcspihset_debug (int debug_flag  );
+
+YY_EXTRA_TYPE wcspihget_extra (void );
+
+void wcspihset_extra (YY_EXTRA_TYPE user_defined  );
+
+FILE *wcspihget_in (void );
+
+void wcspihset_in  (FILE * in_str  );
+
+FILE *wcspihget_out (void );
+
+void wcspihset_out  (FILE * out_str  );
+
+int wcspihget_leng (void );
+
+char *wcspihget_text (void );
+
+int wcspihget_lineno (void );
+
+void wcspihset_lineno (int line_number  );
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int wcspihwrap (void );
+#else
+extern int wcspihwrap (void );
+#endif
+#endif
+
+    static void yyunput (int c,char *buf_ptr  );
+    
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char *,yyconst char *,int );
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * );
+#endif
+
+#ifndef YY_NO_INPUT
+
+#ifdef __cplusplus
+static int yyinput (void );
+#else
+static int input (void );
+#endif
+
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k */
+#define YY_READ_BUF_SIZE 16384
+#else
+#define YY_READ_BUF_SIZE 8192
+#endif /* __ia64__ */
+#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( wcspihtext, wcspihleng, 1, wcspihout )) {} } while (0)
+#endif
+
+/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+	errno=0; \
+	while ( (result = read( fileno(wcspihin), (char *) buf, max_size )) < 0 ) \
+	{ \
+		if( errno != EINTR) \
+		{ \
+			YY_FATAL_ERROR( "input in flex scanner failed" ); \
+			break; \
+		} \
+		errno=0; \
+		clearerr(wcspihin); \
+	}\
+\
+
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_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 YY_DECL
+#define YY_DECL_IS_OURS 1
+
+extern int wcspihlex (void);
+
+#define YY_DECL int wcspihlex (void)
+#endif /* !YY_DECL */
+
+/* Code executed at the beginning of each rule, after wcspihtext and wcspihleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+	if ( wcspihleng > 0 ) \
+		YY_CURRENT_BUFFER_LVALUE->yy_at_bol = \
+				(wcspihtext[wcspihleng - 1] == '\n'); \
+	YY_USER_ACTION
+
+/** The main scanner function which does all the work.
+ */
+YY_DECL
+{
+	register yy_state_type yy_current_state;
+	register char *yy_cp, *yy_bp;
+	register int yy_act;
+    
+#line 146 "wcspih.l"
+
+	/* Keyword indices, as used in the WCS papers, e.g. PCi_ja, PVi_ma. */
+	char a;
+	int  i, j, m;
+	
+	char *cptr, *errmsg, errtxt[80], *hptr, *keep;
+	int  altlin, alts[27], ialt, idx, ipx, ix, jx, naxis, *npptr,
+	     nps[27], npv[27], pass, status, valtype, voff;
+	double epoch[27], vsource[27];
+	void *vptr, *wptr;
+	struct wcsprm *wcsp;
+	int wcspihlex_destroy(void);
+	
+	naxis = 0;
+	for (ialt = 0; ialt < 27; ialt++) {
+	  alts[ialt] = 0;
+	  npv[ialt] = 0;
+	  nps[ialt] = 0;
+	  epoch[ialt]   = UNDEFINED;
+	  vsource[ialt] = UNDEFINED;
+	}
+	
+	/* Parameters used to implement YY_INPUT. */
+	wcspih_hdr = header;
+	wcspih_nkeyrec = nkeyrec;
+	
+	/* Our handle on the input stream. */
+	hptr = header;
+	keep = 0x0;
+	*nreject = 0;
+	
+	/* Keyword parameters. */
+	i = j = m = 0;
+	a = ' ';
+	
+	/* For decoding the keyvalue. */
+	valtype = -1;
+	idx     = -1;
+	vptr    = 0x0;
+	
+	/* For keywords that require special handling. */
+	altlin = 0;
+	npptr  = 0x0;
+	
+	/* The data structures produced. */
+	*nwcs = 0;
+	*wcs  = 0x0;
+	
+	pass = 1;
+	
+	/* Return here via longjmp() invoked by yy_fatal_error(). */
+	if (setjmp(wcspih_abort_jmp_env)) {
+	  return 3;
+	}
+	
+	BEGIN(INITIAL);
+
+
+#line 8526 "wcspih.c"
+
+	if ( !(yy_init) )
+		{
+		(yy_init) = 1;
+
+#ifdef YY_USER_INIT
+		YY_USER_INIT;
+#endif
+
+		if ( ! (yy_start) )
+			(yy_start) = 1;	/* first start state */
+
+		if ( ! wcspihin )
+			wcspihin = stdin;
+
+		if ( ! wcspihout )
+			wcspihout = stdout;
+
+		if ( ! YY_CURRENT_BUFFER ) {
+			wcspihensure_buffer_stack ();
+			YY_CURRENT_BUFFER_LVALUE =
+				wcspih_create_buffer(wcspihin,YY_BUF_SIZE );
+		}
+
+		wcspih_load_buffer_state( );
+		}
+
+	while ( 1 )		/* loops until end-of-file is reached */
+		{
+		yy_cp = (yy_c_buf_p);
+
+		/* Support of wcspihtext. */
+		*yy_cp = (yy_hold_char);
+
+		/* yy_bp points to the position in yy_ch_buf of the start of
+		 * the current run.
+		 */
+		yy_bp = yy_cp;
+
+		yy_current_state = (yy_start);
+		yy_current_state += YY_AT_BOL();
+yy_match:
+		while ( (yy_current_state = yy_nxt[yy_current_state][ YY_SC_TO_UI(*yy_cp) ]) > 0 )
+			{
+			if ( yy_accept[yy_current_state] )
+				{
+				(yy_last_accepting_state) = yy_current_state;
+				(yy_last_accepting_cpos) = yy_cp;
+				}
+
+			++yy_cp;
+			}
+
+		yy_current_state = -yy_current_state;
+
+yy_find_action:
+		yy_act = yy_accept[yy_current_state];
+
+		YY_DO_BEFORE_ACTION;
+
+do_action:	/* This label is used only to access EOF actions. */
+
+		switch ( yy_act )
+	{ /* beginning of action switch */
+			case 0: /* must back up */
+			/* undo the effects of YY_DO_BEFORE_ACTION */
+			*yy_cp = (yy_hold_char);
+			yy_cp = (yy_last_accepting_cpos) + 1;
+			yy_current_state = (yy_last_accepting_state);
+			goto yy_find_action;
+
+case 1:
+YY_RULE_SETUP
+#line 204 "wcspih.l"
+{
+	  if (pass == 1) {
+	    sscanf(wcspihtext, "NAXIS   = %d", &naxis);
+	  }
+	
+	  if (naxis < 0) {
+	    errmsg = errtxt;
+	    sprintf(errmsg, "Negative value of NAXIS ignored: %d", naxis);
+	    naxis = 0;
+	    BEGIN(ERROR);
+	  } else {
+	    BEGIN(DISCARD);
+	  }
+	}
+	YY_BREAK
+case 2:
+YY_RULE_SETUP
+#line 219 "wcspih.l"
+{
+	  if (pass == 1) {
+	    sscanf(wcspihtext, "WCSAXES%c= %d", &a, &i);
+	    wcspih_naxes(naxis, i, 0, a, alts, 0);
+	  }
+	  BEGIN(FLUSH);
+	}
+	YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 227 "wcspih.l"
+{
+	  valtype = FLOAT;
+	  if (pass == 2) vptr = &((*wcs)->crpix);
+	  BEGIN(CCCCCia);
+	}
+	YY_BREAK
+case 4:
+YY_RULE_SETUP
+#line 233 "wcspih.l"
+{
+	  valtype = FLOAT;
+	  if (pass == 2) vptr = &((*wcs)->pc);
+	  altlin = 1;
+	  BEGIN(CCi_ja);
+	}
+	YY_BREAK
+case 5:
+YY_RULE_SETUP
+#line 240 "wcspih.l"
+{
+	  valtype = FLOAT;
+	  if (pass == 2) vptr = &((*wcs)->cd);
+	  altlin = 2;
+	  BEGIN(CCi_ja);
+	}
+	YY_BREAK
+case 6:
+YY_RULE_SETUP
+#line 247 "wcspih.l"
+{
+	  valtype = FLOAT;
+	  if (pass == 2) vptr = &((*wcs)->cdelt);
+	  BEGIN(CCCCCia);
+	}
+	YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 253 "wcspih.l"
+{
+	  valtype = FLOAT;
+	  if (pass == 2) vptr = &((*wcs)->crota);
+	  altlin = 4;
+	  BEGIN(CROTAi);
+	}
+	YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 260 "wcspih.l"
+{
+	  valtype = STRING;
+	  if (pass == 2) vptr = &((*wcs)->cunit);
+	  BEGIN(CCCCCia);
+	}
+	YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 266 "wcspih.l"
+{
+	  valtype = STRING;
+	  if (pass == 2) vptr = &((*wcs)->ctype);
+	  BEGIN(CCCCCia);
+	}
+	YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 272 "wcspih.l"
+{
+	  valtype = FLOAT;
+	  if (pass == 2) vptr = &((*wcs)->crval);
+	  BEGIN(CCCCCia);
+	}
+	YY_BREAK
+case 11:
+YY_RULE_SETUP
+#line 278 "wcspih.l"
+{
+	  valtype = FLOAT;
+	  if (pass == 2) vptr = &((*wcs)->lonpole);
+	  BEGIN(CCCCCCCa);
+	}
+	YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 284 "wcspih.l"
+{
+	  valtype = FLOAT;
+	  if (pass == 2) vptr = &((*wcs)->latpole);
+	  BEGIN(CCCCCCCa);
+	}
+	YY_BREAK
+case 13:
+YY_RULE_SETUP
+#line 290 "wcspih.l"
+{
+	  valtype = FLOAT;
+	  if (pass == 2) vptr = &((*wcs)->restfrq);
+	  BEGIN(CCCCCCCa);
+	}
+	YY_BREAK
+case 14:
+YY_RULE_SETUP
+#line 296 "wcspih.l"
+{
+	  valtype = FLOAT;
+	  if (pass == 2) vptr = &((*wcs)->restfrq);
+	  unput(' ');
+	  BEGIN(CCCCCCCa);
+	}
+	YY_BREAK
+case 15:
+YY_RULE_SETUP
+#line 303 "wcspih.l"
+{
+	  valtype = FLOAT;
+	  if (pass == 2) vptr = &((*wcs)->restwav);
+	  BEGIN(CCCCCCCa);
+	}
+	YY_BREAK
+case 16:
+YY_RULE_SETUP
+#line 309 "wcspih.l"
+{
+	  valtype = FLOAT;
+	  if (pass == 2) vptr = &((*wcs)->pv);
+	  npptr = npv;
+	  BEGIN(CCi_ma);
+	}
+	YY_BREAK
+case 17:
+YY_RULE_SETUP
+#line 316 "wcspih.l"
+{
+	  valtype = FLOAT;
+	  if (pass == 2) vptr = &((*wcs)->pv);
+	  npptr = npv;
+	  BEGIN(PROJPn);
+	}
+	YY_BREAK
+case 18:
+YY_RULE_SETUP
+#line 323 "wcspih.l"
+{
+	  valtype = STRING;
+	  if (pass == 2) vptr = &((*wcs)->ps);
+	  npptr = nps;
+	  BEGIN(CCi_ma);
+	}
+	YY_BREAK
+case 19:
+YY_RULE_SETUP
+#line 330 "wcspih.l"
+{
+	  valtype = STRING;
+	  if (pass == 2) vptr = &((*wcs)->cname);
+	  BEGIN(CCCCCia);
+	}
+	YY_BREAK
+case 20:
+YY_RULE_SETUP
+#line 336 "wcspih.l"
+{
+	  valtype = FLOAT;
+	  if (pass == 2) vptr = &((*wcs)->crder);
+	  BEGIN(CCCCCia);
+	}
+	YY_BREAK
+case 21:
+YY_RULE_SETUP
+#line 342 "wcspih.l"
+{
+	  valtype = FLOAT;
+	  if (pass == 2) vptr = &((*wcs)->csyer);
+	  BEGIN(CCCCCia);
+	}
+	YY_BREAK
+case 22:
+YY_RULE_SETUP
+#line 348 "wcspih.l"
+{
+	  valtype = STRING;
+	  if (pass == 2) vptr = (*wcs)->dateavg;
+	  if (ctrl < -10) keep = wcspih_hdr - 80;
+	  BEGIN(CCCCCCCC);
+	}
+	YY_BREAK
+case 23:
+YY_RULE_SETUP
+#line 355 "wcspih.l"
+{
+	  valtype = STRING;
+	  if (pass == 2) vptr = (*wcs)->dateobs;
+	  if (ctrl < -10) keep = wcspih_hdr - 80;
+	  BEGIN(CCCCCCCC);
+	}
+	YY_BREAK
+case 24:
+YY_RULE_SETUP
+#line 362 "wcspih.l"
+{
+	  sscanf(wcspihtext, "EPOCH%c", &a);
+	
+	  if (a == ' ' || relax & WCSHDR_EPOCHa) {
+	    valtype = FLOAT;
+	    if (pass == 2) {
+	      vptr = epoch;
+	      if (a >= 'A') {
+	        vptr = (void *)((double *)vptr + alts[a-'A'+1]);
+	      }
+	    }
+	
+	    unput(' ');
+	    BEGIN(CCCCCCCa);
+	
+	  } else if (relax & WCSHDR_reject) {
+	    errmsg = "EPOCH keyword may not have an alternate version code";
+	    BEGIN(ERROR);
+	
+	  } else {
+	    BEGIN(DISCARD);
+	  }
+	}
+	YY_BREAK
+case 25:
+YY_RULE_SETUP
+#line 386 "wcspih.l"
+{
+	  valtype = FLOAT;
+	  if (pass == 2) vptr = &((*wcs)->equinox);
+	  BEGIN(CCCCCCCa);
+	}
+	YY_BREAK
+case 26:
+YY_RULE_SETUP
+#line 392 "wcspih.l"
+{
+	  valtype = FLOAT;
+	  if (pass == 2) vptr = &((*wcs)->mjdavg);
+	  if (ctrl < -10) keep = wcspih_hdr - 80;
+	  BEGIN(CCCCCCCC);
+	}
+	YY_BREAK
+case 27:
+YY_RULE_SETUP
+#line 399 "wcspih.l"
+{
+	  valtype = FLOAT;
+	  if (pass == 2) vptr = &((*wcs)->mjdobs);
+	  if (ctrl < -10) keep = wcspih_hdr - 80;
+	  BEGIN(CCCCCCCC);
+	}
+	YY_BREAK
+case 28:
+YY_RULE_SETUP
+#line 406 "wcspih.l"
+{
+	  valtype = FLOAT;
+	  if (pass == 2) vptr = (*wcs)->obsgeo;
+	  if (ctrl < -10) keep = wcspih_hdr - 80;
+	  BEGIN(CCCCCCCC);
+	}
+	YY_BREAK
+case 29:
+YY_RULE_SETUP
+#line 413 "wcspih.l"
+{
+	  valtype = FLOAT;
+	  if (pass == 2) vptr = (*wcs)->obsgeo + 1;
+	  if (ctrl < -10) keep = wcspih_hdr - 80;
+	  BEGIN(CCCCCCCC);
+	}
+	YY_BREAK
+case 30:
+YY_RULE_SETUP
+#line 420 "wcspih.l"
+{
+	  valtype = FLOAT;
+	  if (pass == 2) vptr = (*wcs)->obsgeo + 2;
+	  if (ctrl < -10) keep = wcspih_hdr - 80;
+	  BEGIN(CCCCCCCC);
+	}
+	YY_BREAK
+case 31:
+YY_RULE_SETUP
+#line 427 "wcspih.l"
+{
+	  valtype = STRING;
+	  if (pass == 2) vptr = (*wcs)->radesys;
+	  BEGIN(CCCCCCCa);
+	}
+	YY_BREAK
+case 32:
+YY_RULE_SETUP
+#line 433 "wcspih.l"
+{
+	  if (relax & WCSHDR_RADECSYS) {
+	    valtype = STRING;
+	    if (pass == 2) vptr = (*wcs)->radesys;
+	    unput(' ');
+	    BEGIN(CCCCCCCa);
+	
+	  } else if (relax & WCSHDR_reject) {
+	    errmsg = "RADECSYS is non-standard, use RADESYSa";
+	    BEGIN(ERROR);
+	
+	  } else {
+	    BEGIN(DISCARD);
+	  }
+	}
+	YY_BREAK
+case 33:
+YY_RULE_SETUP
+#line 449 "wcspih.l"
+{
+	  valtype = STRING;
+	  if (pass == 2) vptr = (*wcs)->specsys;
+	  BEGIN(CCCCCCCa);
+	}
+	YY_BREAK
+case 34:
+YY_RULE_SETUP
+#line 455 "wcspih.l"
+{
+	  valtype = STRING;
+	  if (pass == 2) vptr = (*wcs)->ssysobs;
+	  BEGIN(CCCCCCCa);
+	}
+	YY_BREAK
+case 35:
+YY_RULE_SETUP
+#line 461 "wcspih.l"
+{
+	  valtype = STRING;
+	  if (pass == 2) vptr = (*wcs)->ssyssrc;
+	  BEGIN(CCCCCCCa);
+	}
+	YY_BREAK
+case 36:
+YY_RULE_SETUP
+#line 467 "wcspih.l"
+{
+	  valtype = FLOAT;
+	  if (pass == 2) vptr = &((*wcs)->velangl);
+	  BEGIN(CCCCCCCa);
+	}
+	YY_BREAK
+case 37:
+YY_RULE_SETUP
+#line 473 "wcspih.l"
+{
+	  valtype = FLOAT;
+	  if (pass == 2) vptr = &((*wcs)->velosys);
+	  BEGIN(CCCCCCCa);
+	}
+	YY_BREAK
+case 38:
+YY_RULE_SETUP
+#line 479 "wcspih.l"
+{
+	  sscanf(wcspihtext, "VELREF%c", &a);
+	
+	  if (a == ' ' || relax & WCSHDR_VELREFa) {
+	    valtype = INTEGER;
+	    if (pass == 2) vptr = &((*wcs)->velref);
+	
+	    unput(a);
+	    BEGIN(CCCCCCCa);
+	
+	  } else if (relax & WCSHDR_reject) {
+	    errmsg = "VELREF keyword may not have an alternate version code";
+	    BEGIN(ERROR);
+	
+	  } else {
+	    BEGIN(DISCARD);
+	  }
+	}
+	YY_BREAK
+case 39:
+YY_RULE_SETUP
+#line 498 "wcspih.l"
+{
+	  sscanf(wcspihtext, "VSOURCE%c", &a);
+	
+	  if (relax & WCSHDR_VSOURCE) {
+	    valtype = FLOAT;
+	    if (pass == 2) {
+	      vptr = vsource;
+	      if (a >= 'A') {
+	        vptr = (void *)((double *)vptr + alts[a-'A'+1]);
+	      }
+	    }
+	
+	    unput(' ');
+	    BEGIN(CCCCCCCa);
+	
+	  } else if (relax & WCSHDR_reject) {
+	    errmsg = "Deprecated VSOURCEa keyword rejected";
+	    BEGIN(ERROR);
+	
+	  } else {
+	    BEGIN(DISCARD);
+	  }
+	}
+	YY_BREAK
+case 40:
+YY_RULE_SETUP
+#line 522 "wcspih.l"
+{
+	  valtype = STRING;
+	  if (pass == 2) vptr = (*wcs)->wcsname;
+	  BEGIN(CCCCCCCa);
+	}
+	YY_BREAK
+case 41:
+YY_RULE_SETUP
+#line 528 "wcspih.l"
+{
+	  valtype = FLOAT;
+	  if (pass == 2) vptr = &((*wcs)->zsource);
+	  BEGIN(CCCCCCCa);
+	}
+	YY_BREAK
+case 42:
+YY_RULE_SETUP
+#line 534 "wcspih.l"
+{
+	  yyless(0);
+	  if (wcspih_nkeyrec) {
+	    wcspih_nkeyrec = 0;
+	    errmsg = "Keyrecords following the END keyrecord were ignored";
+	    BEGIN(ERROR);
+	  } else {
+	    BEGIN(DISCARD);
+	  }
+	}
+	YY_BREAK
+case 43:
+YY_RULE_SETUP
+#line 545 "wcspih.l"
+{
+	  BEGIN(DISCARD);
+	}
+	YY_BREAK
+case 44:
+#line 550 "wcspih.l"
+case 45:
+YY_RULE_SETUP
+#line 550 "wcspih.l"
+{
+	  sscanf(wcspihtext, "%d%c", &i, &a);
+	  idx = i - 1;
+	  BEGIN(VALUE);
+	}
+	YY_BREAK
+case 46:
+YY_RULE_SETUP
+#line 556 "wcspih.l"
+{
+	  /* Invalid axis number will be caught by <VALUE>. */
+	  sscanf(wcspihtext, "%3d", &i);
+	  BEGIN(VALUE);
+	}
+	YY_BREAK
+case 47:
+YY_RULE_SETUP
+#line 562 "wcspih.l"
+{
+	  BEGIN(DISCARD);
+	}
+	YY_BREAK
+case 48:
+#line 567 "wcspih.l"
+case 49:
+#line 568 "wcspih.l"
+case 50:
+#line 569 "wcspih.l"
+case 51:
+YY_RULE_SETUP
+#line 569 "wcspih.l"
+{
+	  sscanf(wcspihtext, "%d_%d%c", &i, &j, &a);
+	  if (pass == 2) {
+	    wcsp = *wcs;
+	    if (a != ' ') {
+	      wcsp += alts[a-'A'+1];
+	    }
+	
+	    idx = (i-1)*(wcsp->naxis) + j - 1;
+	  }
+	  BEGIN(VALUE);
+	}
+	YY_BREAK
+case 52:
+#line 583 "wcspih.l"
+case 53:
+#line 584 "wcspih.l"
+case 54:
+#line 585 "wcspih.l"
+case 55:
+#line 586 "wcspih.l"
+case 56:
+#line 587 "wcspih.l"
+case 57:
+YY_RULE_SETUP
+#line 587 "wcspih.l"
+{
+	  /* Invalid axis numbers will be caught by <VALUE>. */
+	  sscanf(wcspihtext, "%d_%d", &i, &j);
+	  BEGIN(VALUE);
+	}
+	YY_BREAK
+case 58:
+YY_RULE_SETUP
+#line 593 "wcspih.l"
+{
+	  /* This covers the defunct forms CD00i00j and PC00i00j. */
+	  if (((relax & WCSHDR_PC00i00j) && (altlin == 1)) ||
+	      ((relax & WCSHDR_CD00i00j) && (altlin == 2))) {
+	    sscanf(wcspihtext, "%3d%3d", &i, &j);
+	    a = ' ';
+	    if (pass == 2) {
+	      idx = (i-1)*((*wcs)->naxis) + j - 1;
+	    }
+	    BEGIN(VALUE);
+	
+	  } else if (relax & WCSHDR_reject) {
+	    errmsg = errtxt;
+	    sprintf(errmsg, "Defunct form of %si_ja keyword",
+	                     (altlin==1) ? "PC" : "CD");
+	    BEGIN(ERROR);
+	
+	  } else {
+	    BEGIN(DISCARD);
+	  }
+	}
+	YY_BREAK
+case 59:
+YY_RULE_SETUP
+#line 615 "wcspih.l"
+{
+	  BEGIN(DISCARD);
+	}
+	YY_BREAK
+case 60:
+#line 620 "wcspih.l"
+case 61:
+YY_RULE_SETUP
+#line 620 "wcspih.l"
+{
+	  sscanf(wcspihtext, "%d%c", &i, &a);
+	  if (a == ' ' || relax & WCSHDR_CROTAia) {
+	    idx = i - 1;
+	    BEGIN(VALUE);
+	
+	  } else if (relax & WCSHDR_reject) {
+	    errmsg = "CROTAn keyword may not have an alternate version code";
+	    BEGIN(ERROR);
+	
+	  } else {
+	    BEGIN(DISCARD);
+	  }
+	}
+	YY_BREAK
+case 62:
+YY_RULE_SETUP
+#line 635 "wcspih.l"
+{
+	  sscanf(wcspihtext, "%d", &i);
+	  a = ' ';
+	  idx = i - 1;
+	  BEGIN(VALUE);
+	}
+	YY_BREAK
+case 63:
+YY_RULE_SETUP
+#line 642 "wcspih.l"
+{
+	  BEGIN(DISCARD);
+	}
+	YY_BREAK
+case 64:
+#line 647 "wcspih.l"
+case 65:
+YY_RULE_SETUP
+#line 647 "wcspih.l"
+{
+	  idx = -1;
+	
+	  if (YY_START == CCCCCCCa) {
+	    sscanf(wcspihtext, "%c", &a);
+	  } else {
+	    unput(wcspihtext[0]);
+	    a = 0;
+	  }
+	  BEGIN(VALUE);
+	}
+	YY_BREAK
+case 66:
+YY_RULE_SETUP
+#line 659 "wcspih.l"
+{
+	  BEGIN(DISCARD);
+	}
+	YY_BREAK
+case 67:
+#line 664 "wcspih.l"
+case 68:
+#line 665 "wcspih.l"
+case 69:
+#line 666 "wcspih.l"
+case 70:
+YY_RULE_SETUP
+#line 666 "wcspih.l"
+{
+	  sscanf(wcspihtext, "%d_%d%c", &i, &m, &a);
+	  idx = -1;
+	  BEGIN(VALUE);
+	}
+	YY_BREAK
+case 71:
+#line 673 "wcspih.l"
+case 72:
+#line 674 "wcspih.l"
+case 73:
+#line 675 "wcspih.l"
+case 74:
+#line 676 "wcspih.l"
+case 75:
+#line 677 "wcspih.l"
+case 76:
+YY_RULE_SETUP
+#line 677 "wcspih.l"
+{
+	  /* Invalid parameters will be caught by <VALUE>. */
+	  sscanf(wcspihtext, "%d_%d", &i, &m);
+	  BEGIN(VALUE);
+	}
+	YY_BREAK
+case 77:
+YY_RULE_SETUP
+#line 683 "wcspih.l"
+{
+	  BEGIN(DISCARD);
+	}
+	YY_BREAK
+case 78:
+YY_RULE_SETUP
+#line 687 "wcspih.l"
+{
+	  if (relax & WCSHDR_PROJPn) {
+	    sscanf(wcspihtext, "%d", &m);
+	    i = 0;
+	    a = ' ';
+	    idx = -1;
+	    BEGIN(VALUE);
+	
+	  } else if (relax & WCSHDR_reject) {
+	    errmsg = "Defunct PROJPn keyword rejected";
+	    BEGIN(ERROR);
+	
+	  } else {
+	    BEGIN(DISCARD);
+	  }
+	}
+	YY_BREAK
+case 79:
+YY_RULE_SETUP
+#line 704 "wcspih.l"
+{
+	  BEGIN(DISCARD);
+	}
+	YY_BREAK
+case 80:
+YY_RULE_SETUP
+#line 708 "wcspih.l"
+{
+	  /* Do checks on i, j & m. */
+	  if (i > 99 || j > 99 || m > 99) {
+	    if (relax & WCSHDR_reject) {
+	      errmsg = errtxt;
+	      if (i > 99 || j > 99) {
+	        sprintf(errmsg, "Axis number exceeds 99");
+	      } else if (m > 99) {
+	        sprintf(errmsg, "Parameter number exceeds 99");
+	      }
+	      BEGIN(ERROR);
+	
+	    } else {
+	      /* Pretend we don't recognize it. */
+	      BEGIN(DISCARD);
+	    }
+	
+	  } else {
+	    if (valtype == INTEGER) {
+	      BEGIN(INTEGER_VAL);
+	    } else if (valtype == FLOAT) {
+	      BEGIN(FLOAT_VAL);
+	    } else if (valtype == STRING) {
+	      BEGIN(STRING_VAL);
+	    } else {
+	      errmsg = errtxt;
+	      sprintf(errmsg, "Internal parser ERROR, bad data type: %d",
+	        valtype);
+	      BEGIN(ERROR);
+	    }
+	  }
+	}
+	YY_BREAK
+case 81:
+YY_RULE_SETUP
+#line 741 "wcspih.l"
+{
+	  errmsg = "Invalid KEYWORD = VALUE syntax";
+	  BEGIN(ERROR);
+	}
+	YY_BREAK
+case 82:
+YY_RULE_SETUP
+#line 746 "wcspih.l"
+{
+	  if (pass == 1) {
+	    wcspih_naxes(naxis, i, j, a, alts, npptr);
+	    BEGIN(FLUSH);
+	
+	  } else {
+	    if (vptr) {
+	      /* Determine the coordinate representation. */
+	      for (ialt = 0; ialt < *nwcs; ialt++) {
+	        /* The loop here is for keywords that apply */
+	        /* to every alternate; these have a == 0. */
+	        if (a >= 'A') {
+	          ialt = alts[a-'A'+1];
+	        }
+	
+	        wptr = vptr;
+	        if (ialt) {
+	          voff = (char *)(*wcs+ialt) - (char *)(*wcs);
+	          wptr = (void *)((char *)vptr + voff);
+	        }
+	
+	        /* Apply keyword parameterization. */
+	        if (idx >= 0) {
+	          wptr = *((int **)wptr) + idx;
+	        }
+	
+	        /* Read the keyvalue. */
+	        sscanf(wcspihtext, "%d", (int *)wptr);
+	
+	        if (a) break;
+	      }
+	
+	      BEGIN(COMMENT);
+	
+	    } else {
+	      errmsg = "Internal parser ERROR, null int pointer";
+	      BEGIN(ERROR);
+	    }
+	  }
+	}
+	YY_BREAK
+case 83:
+YY_RULE_SETUP
+#line 787 "wcspih.l"
+{
+	  errmsg = "An integer value was expected";
+	  BEGIN(ERROR);
+	}
+	YY_BREAK
+case 84:
+YY_RULE_SETUP
+#line 792 "wcspih.l"
+{
+	  if (pass == 1) {
+	    wcspih_naxes(naxis, i, j, a, alts, npptr);
+	    BEGIN(FLUSH);
+	
+	  } else {
+	    if (vptr) {
+	      /* Determine the coordinate representation. */
+	      for (ialt = 0; ialt < *nwcs; ialt++) {
+	        /* The loop here is for keywords like MJD-OBS that */
+	        /* apply to every alternate; these have a == 0.  */
+	        if (a >= 'A') {
+	          ialt = alts[a-'A'+1];
+	        }
+	
+	        wptr = vptr;
+	        if (ialt) {
+	          voff = (char *)(*wcs+ialt) - (char *)(*wcs);
+	          wptr = (void *)((char *)vptr + voff);
+	        }
+	
+	        /* Apply keyword parameterization. */
+	        if (idx >= 0) {
+	          wptr = *((double **)wptr) + idx;
+	
+	        } else if (npptr == npv) {
+	          ipx = (*wcs+ialt)->npv++;
+	          (*wcs+ialt)->pv[ipx].i = i;
+	          (*wcs+ialt)->pv[ipx].m = m;
+	          wptr = &((*wcs+ialt)->pv[ipx].value);
+	        }
+	
+	        /* Read the keyvalue. */
+	        wcsutil_str2double(wcspihtext, "%lf", (double *)wptr);
+	
+	        /* Flag the presence of PCi_ja, or CDi_ja and/or CROTAia. */
+	        if (altlin) {
+	          (*wcs+ialt)->altlin |= altlin;
+	          altlin = 0;
+	        }
+	
+	        if (a) break;
+	      }
+	
+	      BEGIN(COMMENT);
+	
+	    } else {
+	      errmsg = "Internal parser ERROR, null float pointer";
+	      BEGIN(ERROR);
+	    }
+	  }
+	}
+	YY_BREAK
+case 85:
+YY_RULE_SETUP
+#line 845 "wcspih.l"
+{
+	  errmsg = "A floating-point value was expected";
+	  BEGIN(ERROR);
+	}
+	YY_BREAK
+case 86:
+/* rule 86 can match eol */
+YY_RULE_SETUP
+#line 850 "wcspih.l"
+{
+	  if (pass == 1) {
+	    wcspih_naxes(naxis, i, j, a, alts, npptr);
+	    BEGIN(FLUSH);
+	
+	  } else {
+	    if (vptr) {
+	      /* Determine the coordinate representation. */
+	      for (ialt = 0; ialt < *nwcs; ialt++) {
+	        /* The loop here is for keywords like DATE-OBS that */
+	        /* apply to every alternate; these have a == 0.   */
+	        if (a >= 'A') {
+	          ialt = alts[a-'A'+1];
+	        }
+	
+	        wptr = vptr;
+	        if (ialt) {
+	          voff = (char *)(*wcs+ialt) - (char *)(*wcs);
+	          wptr = (void *)((char *)vptr + voff);
+	        }
+	
+	        /* Apply keyword parameterization. */
+	        if (idx >= 0) {
+	          wptr = *((char (**)[72])wptr) + idx;
+	
+	        } else if (npptr == nps) {
+	          ipx = (*wcs+ialt)->nps++;
+	          (*wcs+ialt)->ps[ipx].i = i;
+	          (*wcs+ialt)->ps[ipx].m = m;
+	          wptr = (*wcs+ialt)->ps[ipx].value;
+	        }
+	
+	        /* Read the keyvalue. */
+	        cptr = (char *)wptr;
+	        strcpy(cptr, wcspihtext+1);
+	
+	        /* Squeeze out repeated quotes. */
+	        ix = 0;
+	        for (jx = 0; jx < 72; jx++) {
+	          if (ix < jx) {
+	            cptr[ix] = cptr[jx];
+	          }
+	
+	          if (cptr[jx] == '\0') {
+	            if (ix) cptr[ix-1] = '\0';
+	            break;
+	          } else if (cptr[jx] == '\'' && cptr[jx+1] == '\'') {
+	            jx++;
+	          }
+	
+	          ix++;
+	        }
+	
+	        if (a) break;
+	      }
+	
+	      BEGIN(COMMENT);
+	
+	    } else {
+	      errmsg = "Internal parser ERROR, null string pointer";
+	      BEGIN(ERROR);
+	    }
+	  }
+	}
+	YY_BREAK
+case 87:
+YY_RULE_SETUP
+#line 915 "wcspih.l"
+{
+	  errmsg = "A string value was expected";
+	  BEGIN(ERROR);
+	}
+	YY_BREAK
+case 88:
+#line 921 "wcspih.l"
+case 89:
+YY_RULE_SETUP
+#line 921 "wcspih.l"
+{
+	  BEGIN(FLUSH);
+	}
+	YY_BREAK
+case 90:
+YY_RULE_SETUP
+#line 925 "wcspih.l"
+{
+	  errmsg = "Malformed keycomment";
+	  BEGIN(ERROR);
+	}
+	YY_BREAK
+case 91:
+YY_RULE_SETUP
+#line 930 "wcspih.l"
+{
+	  if (pass == 2) {
+	    if (ctrl < 0) {
+	      /* Preserve discards. */
+	      keep = wcspih_hdr - 80;
+	
+	    } else if (ctrl > 2) {
+	      fprintf(stderr, "%.80s\n  Discarded.\n", wcspih_hdr-80);
+	    }
+	  }
+	  BEGIN(FLUSH);
+	}
+	YY_BREAK
+case 92:
+YY_RULE_SETUP
+#line 943 "wcspih.l"
+{
+	  (*nreject)++;
+	  if (pass == 2) {
+	    if (ctrl%10 == -1) {
+	      /* Preserve rejects. */
+	      keep = wcspih_hdr - 80;
+	    }
+	
+	    if (abs(ctrl%10) > 1) {
+	      fprintf(stderr, "%.80s\n%4d: %s.\n", wcspih_hdr-80, *nreject,
+	        errmsg);
+	    }
+	  }
+	  BEGIN(FLUSH);
+	}
+	YY_BREAK
+case 93:
+/* rule 93 can match eol */
+YY_RULE_SETUP
+#line 959 "wcspih.l"
+{
+	  if (pass == 2 && keep) {
+	    if (hptr < keep) {
+	      strncpy(hptr, keep, 80);
+	    }
+	    hptr += 80;
+	  }
+	
+	  i = j = m = 0;
+	  a = ' ';
+	  valtype = -1;
+	  keep = 0x0;
+	  altlin = 0;
+	  npptr = 0x0;
+	  BEGIN(INITIAL);
+	}
+	YY_BREAK
+case YY_STATE_EOF(INITIAL):
+case YY_STATE_EOF(CROTAi):
+case YY_STATE_EOF(PROJPn):
+case YY_STATE_EOF(CCCCCia):
+case YY_STATE_EOF(CCi_ja):
+case YY_STATE_EOF(CCi_ma):
+case YY_STATE_EOF(CCCCCCCa):
+case YY_STATE_EOF(CCCCCCCC):
+case YY_STATE_EOF(VALUE):
+case YY_STATE_EOF(INTEGER_VAL):
+case YY_STATE_EOF(FLOAT_VAL):
+case YY_STATE_EOF(STRING_VAL):
+case YY_STATE_EOF(COMMENT):
+case YY_STATE_EOF(DISCARD):
+case YY_STATE_EOF(ERROR):
+case YY_STATE_EOF(FLUSH):
+#line 976 "wcspih.l"
+{
+	  /* End-of-input. */
+	  if (pass == 1) {
+	    if ((status = wcspih_inits(naxis, alts, npv, nps, nwcs, wcs)) ||
+	         *nwcs == 0) {
+	      wcspihlex_destroy();
+	      return status;
+	    }
+	
+	    if (abs(ctrl%10) > 2) {
+	      if (*nwcs == 1) {
+	        if (strcmp(wcs[0]->wcsname, "DEFAULTS") != 0) {
+	          fprintf(stderr, "Found one coordinate representation.\n");
+	        }
+	      } else {
+	        fprintf(stderr, "Found %d coordinate representations.\n",
+	          *nwcs);
+	      }
+	    }
+	
+	    wcspih_hdr = header;
+	    wcspih_nkeyrec = nkeyrec;
+	    *nreject = 0;
+	
+	    pass = 2;
+	    i = j = m = 0;
+	    a = ' ';
+	    valtype = -1;
+	
+	    wcspihrestart(wcspihin);
+	
+	  } else {
+	    wcspihlex_destroy();
+	
+	    if (ctrl < 0) {
+	      *hptr = '\0';
+	    } else if (ctrl == 1) {
+	      fprintf(stderr, "%d WCS keyrecords were rejected.\n",
+	        *nreject);
+	    }
+	
+	    return wcspih_final(alts, epoch, vsource, nwcs, wcs);
+	  }
+	}
+	YY_BREAK
+case 94:
+YY_RULE_SETUP
+#line 1021 "wcspih.l"
+ECHO;
+	YY_BREAK
+#line 9678 "wcspih.c"
+
+	case YY_END_OF_BUFFER:
+		{
+		/* Amount of text matched not including the EOB char. */
+		int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;
+
+		/* Undo the effects of YY_DO_BEFORE_ACTION. */
+		*yy_cp = (yy_hold_char);
+		YY_RESTORE_YY_MORE_OFFSET
+
+		if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
+			{
+			/* We're scanning a new file or input source.  It's
+			 * possible that this happened because the user
+			 * just pointed wcspihin at a new source and called
+			 * wcspihlex().  If so, then we have to assure
+			 * consistency between YY_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.
+			 */
+			(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+			YY_CURRENT_BUFFER_LVALUE->yy_input_file = wcspihin;
+			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
+			}
+
+		/* Note that here we test for yy_c_buf_p "<=" to the position
+		 * of the first EOB in the buffer, since yy_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 ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+			{ /* This was really a NUL. */
+			yy_state_type yy_next_state;
+
+			(yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;
+
+			yy_current_state = yy_get_previous_state(  );
+
+			/* Okay, we're now positioned to make the NUL
+			 * transition.  We couldn't have
+			 * yy_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).
+			 */
+
+			yy_next_state = yy_try_NUL_trans( yy_current_state );
+
+			yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+
+			if ( yy_next_state )
+				{
+				/* Consume the NUL. */
+				yy_cp = ++(yy_c_buf_p);
+				yy_current_state = yy_next_state;
+				goto yy_match;
+				}
+
+			else
+				{
+				yy_cp = (yy_c_buf_p);
+				goto yy_find_action;
+				}
+			}
+
+		else switch ( yy_get_next_buffer(  ) )
+			{
+			case EOB_ACT_END_OF_FILE:
+				{
+				(yy_did_buffer_switch_on_eof) = 0;
+
+				if ( wcspihwrap( ) )
+					{
+					/* Note: because we've taken care in
+					 * yy_get_next_buffer() to have set up
+					 * wcspihtext, we can now set up
+					 * yy_c_buf_p so that if some total
+					 * hoser (like flex itself) wants to
+					 * call the scanner after we return the
+					 * YY_NULL, it'll still work - another
+					 * YY_NULL will get returned.
+					 */
+					(yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;
+
+					yy_act = YY_STATE_EOF(YY_START);
+					goto do_action;
+					}
+
+				else
+					{
+					if ( ! (yy_did_buffer_switch_on_eof) )
+						YY_NEW_FILE;
+					}
+				break;
+				}
+
+			case EOB_ACT_CONTINUE_SCAN:
+				(yy_c_buf_p) =
+					(yytext_ptr) + yy_amount_of_matched_text;
+
+				yy_current_state = yy_get_previous_state(  );
+
+				yy_cp = (yy_c_buf_p);
+				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+				goto yy_match;
+
+			case EOB_ACT_LAST_MATCH:
+				(yy_c_buf_p) =
+				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];
+
+				yy_current_state = yy_get_previous_state(  );
+
+				yy_cp = (yy_c_buf_p);
+				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+				goto yy_find_action;
+			}
+		break;
+		}
+
+	default:
+		YY_FATAL_ERROR(
+			"fatal flex scanner internal error--no action found" );
+	} /* end of action switch */
+		} /* end of scanning one token */
+} /* end of wcspihlex */
+
+/* yy_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 yy_get_next_buffer (void)
+{
+    	register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+	register char *source = (yytext_ptr);
+	register int number_to_move, i;
+	int ret_val;
+
+	if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
+		YY_FATAL_ERROR(
+		"fatal flex scanner internal error--end of buffer missed" );
+
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
+		{ /* Don't try to fill the buffer, so this is an EOF. */
+		if ( (yy_c_buf_p) - (yytext_ptr) - YY_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) ((yy_c_buf_p) - (yytext_ptr)) - 1;
+
+	for ( i = 0; i < number_to_move; ++i )
+		*(dest++) = *(source++);
+
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+		/* don't do the read, it's not guaranteed to return an EOF,
+		 * just force an EOF
+		 */
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
+
+	else
+		{
+			int num_to_read =
+			YY_CURRENT_BUFFER_LVALUE->yy_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 */
+			YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
+
+			int yy_c_buf_p_offset =
+				(int) ((yy_c_buf_p) - b->yy_ch_buf);
+
+			if ( b->yy_is_our_buffer )
+				{
+				int new_size = b->yy_buf_size * 2;
+
+				if ( new_size <= 0 )
+					b->yy_buf_size += b->yy_buf_size / 8;
+				else
+					b->yy_buf_size *= 2;
+
+				b->yy_ch_buf = (char *)
+					/* Include room in for 2 EOB chars. */
+					wcspihrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2  );
+				}
+			else
+				/* Can't grow it, we don't own it. */
+				b->yy_ch_buf = 0;
+
+			if ( ! b->yy_ch_buf )
+				YY_FATAL_ERROR(
+				"fatal error - scanner input buffer overflow" );
+
+			(yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+			num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
+						number_to_move - 1;
+
+			}
+
+		if ( num_to_read > YY_READ_BUF_SIZE )
+			num_to_read = YY_READ_BUF_SIZE;
+
+		/* Read in more data. */
+		YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+			(yy_n_chars), (size_t) num_to_read );
+
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+		}
+
+	if ( (yy_n_chars) == 0 )
+		{
+		if ( number_to_move == YY_MORE_ADJ )
+			{
+			ret_val = EOB_ACT_END_OF_FILE;
+			wcspihrestart(wcspihin  );
+			}
+
+		else
+			{
+			ret_val = EOB_ACT_LAST_MATCH;
+			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
+				YY_BUFFER_EOF_PENDING;
+			}
+		}
+
+	else
+		ret_val = EOB_ACT_CONTINUE_SCAN;
+
+	if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+		/* Extend the array by 50%, plus the number we really need. */
+		yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1);
+		YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) wcspihrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size  );
+		if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+			YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+	}
+
+	(yy_n_chars) += number_to_move;
+	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
+	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
+
+	(yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+
+	return ret_val;
+}
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+    static yy_state_type yy_get_previous_state (void)
+{
+	register yy_state_type yy_current_state;
+	register char *yy_cp;
+    
+	yy_current_state = (yy_start);
+	yy_current_state += YY_AT_BOL();
+
+	for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
+		{
+		if ( *yy_cp )
+			{
+			yy_current_state = yy_nxt[yy_current_state][YY_SC_TO_UI(*yy_cp)];
+			}
+		else
+			yy_current_state = yy_NUL_trans[yy_current_state];
+		if ( yy_accept[yy_current_state] )
+			{
+			(yy_last_accepting_state) = yy_current_state;
+			(yy_last_accepting_cpos) = yy_cp;
+			}
+		}
+
+	return yy_current_state;
+}
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ *	next_state = yy_try_NUL_trans( current_state );
+ */
+    static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state )
+{
+	register int yy_is_jam;
+    	register char *yy_cp = (yy_c_buf_p);
+
+	yy_current_state = yy_NUL_trans[yy_current_state];
+	yy_is_jam = (yy_current_state == 0);
+
+	if ( ! yy_is_jam )
+		{
+		if ( yy_accept[yy_current_state] )
+			{
+			(yy_last_accepting_state) = yy_current_state;
+			(yy_last_accepting_cpos) = yy_cp;
+			}
+		}
+
+	return yy_is_jam ? 0 : yy_current_state;
+}
+
+    static void yyunput (int c, register char * yy_bp )
+{
+	register char *yy_cp;
+    
+    yy_cp = (yy_c_buf_p);
+
+	/* undo effects of setting up wcspihtext */
+	*yy_cp = (yy_hold_char);
+
+	if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+		{ /* need to shift things up to make room */
+		/* +2 for EOB chars. */
+		register int number_to_move = (yy_n_chars) + 2;
+		register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
+					YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
+		register char *source =
+				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
+
+		while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+			*--dest = *--source;
+
+		yy_cp += (int) (dest - source);
+		yy_bp += (int) (dest - source);
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars =
+			(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size;
+
+		if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+			YY_FATAL_ERROR( "flex scanner push-back overflow" );
+		}
+
+	*--yy_cp = (char) c;
+
+	(yytext_ptr) = yy_bp;
+	(yy_hold_char) = *yy_cp;
+	(yy_c_buf_p) = yy_cp;
+}
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+    static int yyinput (void)
+#else
+    static int input  (void)
+#endif
+
+{
+	int c;
+    
+	*(yy_c_buf_p) = (yy_hold_char);
+
+	if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
+		{
+		/* yy_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 ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+			/* This was really a NUL. */
+			*(yy_c_buf_p) = '\0';
+
+		else
+			{ /* need more input */
+			int offset = (yy_c_buf_p) - (yytext_ptr);
+			++(yy_c_buf_p);
+
+			switch ( yy_get_next_buffer(  ) )
+				{
+				case EOB_ACT_LAST_MATCH:
+					/* This happens because yy_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. */
+					wcspihrestart(wcspihin );
+
+					/*FALLTHROUGH*/
+
+				case EOB_ACT_END_OF_FILE:
+					{
+					if ( wcspihwrap( ) )
+						return EOF;
+
+					if ( ! (yy_did_buffer_switch_on_eof) )
+						YY_NEW_FILE;
+#ifdef __cplusplus
+					return yyinput();
+#else
+					return input();
+#endif
+					}
+
+				case EOB_ACT_CONTINUE_SCAN:
+					(yy_c_buf_p) = (yytext_ptr) + offset;
+					break;
+				}
+			}
+		}
+
+	c = *(unsigned char *) (yy_c_buf_p);	/* cast for 8-bit char's */
+	*(yy_c_buf_p) = '\0';	/* preserve wcspihtext */
+	(yy_hold_char) = *++(yy_c_buf_p);
+
+	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = (c == '\n');
+
+	return c;
+}
+#endif	/* ifndef YY_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 wcspihrestart  (FILE * input_file )
+{
+    
+	if ( ! YY_CURRENT_BUFFER ){
+        wcspihensure_buffer_stack ();
+		YY_CURRENT_BUFFER_LVALUE =
+            wcspih_create_buffer(wcspihin,YY_BUF_SIZE );
+	}
+
+	wcspih_init_buffer(YY_CURRENT_BUFFER,input_file );
+	wcspih_load_buffer_state( );
+}
+
+/** Switch to a different input buffer.
+ * @param new_buffer The new input buffer.
+ * 
+ */
+    void wcspih_switch_to_buffer  (YY_BUFFER_STATE  new_buffer )
+{
+    
+	/* TODO. We should be able to replace this entire function body
+	 * with
+	 *		wcspihpop_buffer_state();
+	 *		wcspihpush_buffer_state(new_buffer);
+     */
+	wcspihensure_buffer_stack ();
+	if ( YY_CURRENT_BUFFER == new_buffer )
+		return;
+
+	if ( YY_CURRENT_BUFFER )
+		{
+		/* Flush out information for old buffer. */
+		*(yy_c_buf_p) = (yy_hold_char);
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+		}
+
+	YY_CURRENT_BUFFER_LVALUE = new_buffer;
+	wcspih_load_buffer_state( );
+
+	/* We don't actually know whether we did this switch during
+	 * EOF (wcspihwrap()) processing, but the only time this flag
+	 * is looked at is after wcspihwrap() is called, so it's safe
+	 * to go ahead and always set it.
+	 */
+	(yy_did_buffer_switch_on_eof) = 1;
+}
+
+static void wcspih_load_buffer_state  (void)
+{
+    	(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+	(yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+	wcspihin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+	(yy_hold_char) = *(yy_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 YY_BUF_SIZE.
+ * 
+ * @return the allocated buffer state.
+ */
+    YY_BUFFER_STATE wcspih_create_buffer  (FILE * file, int  size )
+{
+	YY_BUFFER_STATE b;
+    
+	b = (YY_BUFFER_STATE) wcspihalloc(sizeof( struct yy_buffer_state )  );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in wcspih_create_buffer()" );
+
+	b->yy_buf_size = size;
+
+	/* yy_ch_buf has to be 2 characters longer than the size given because
+	 * we need to put in 2 end-of-buffer characters.
+	 */
+	b->yy_ch_buf = (char *) wcspihalloc(b->yy_buf_size + 2  );
+	if ( ! b->yy_ch_buf )
+		YY_FATAL_ERROR( "out of dynamic memory in wcspih_create_buffer()" );
+
+	b->yy_is_our_buffer = 1;
+
+	wcspih_init_buffer(b,file );
+
+	return b;
+}
+
+/** Destroy the buffer.
+ * @param b a buffer created with wcspih_create_buffer()
+ * 
+ */
+    void wcspih_delete_buffer (YY_BUFFER_STATE  b )
+{
+    
+	if ( ! b )
+		return;
+
+	if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+		YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
+
+	if ( b->yy_is_our_buffer )
+		wcspihfree((void *) b->yy_ch_buf  );
+
+	wcspihfree((void *) b  );
+}
+
+/* Initializes or reinitializes a buffer.
+ * This function is sometimes called more than once on the same buffer,
+ * such as during a wcspihrestart() or at EOF.
+ */
+    static void wcspih_init_buffer  (YY_BUFFER_STATE  b, FILE * file )
+
+{
+	int oerrno = errno;
+    
+	wcspih_flush_buffer(b );
+
+	b->yy_input_file = file;
+	b->yy_fill_buffer = 1;
+
+    /* If b is the current buffer, then wcspih_init_buffer was _probably_
+     * called from wcspihrestart() or through yy_get_next_buffer.
+     * In that case, we don't want to reset the lineno or column.
+     */
+    if (b != YY_CURRENT_BUFFER){
+        b->yy_bs_lineno = 1;
+        b->yy_bs_column = 0;
+    }
+
+        b->yy_is_interactive = 0;
+    
+	errno = oerrno;
+}
+
+/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
+ * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
+ * 
+ */
+    void wcspih_flush_buffer (YY_BUFFER_STATE  b )
+{
+    	if ( ! b )
+		return;
+
+	b->yy_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->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+	b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+	b->yy_buf_pos = &b->yy_ch_buf[0];
+
+	b->yy_at_bol = 1;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	if ( b == YY_CURRENT_BUFFER )
+		wcspih_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 wcspihpush_buffer_state (YY_BUFFER_STATE new_buffer )
+{
+    	if (new_buffer == NULL)
+		return;
+
+	wcspihensure_buffer_stack();
+
+	/* This block is copied from wcspih_switch_to_buffer. */
+	if ( YY_CURRENT_BUFFER )
+		{
+		/* Flush out information for old buffer. */
+		*(yy_c_buf_p) = (yy_hold_char);
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+		}
+
+	/* Only push if top exists. Otherwise, replace top. */
+	if (YY_CURRENT_BUFFER)
+		(yy_buffer_stack_top)++;
+	YY_CURRENT_BUFFER_LVALUE = new_buffer;
+
+	/* copied from wcspih_switch_to_buffer. */
+	wcspih_load_buffer_state( );
+	(yy_did_buffer_switch_on_eof) = 1;
+}
+
+/** Removes and deletes the top of the stack, if present.
+ *  The next element becomes the new top.
+ *  
+ */
+void wcspihpop_buffer_state (void)
+{
+    	if (!YY_CURRENT_BUFFER)
+		return;
+
+	wcspih_delete_buffer(YY_CURRENT_BUFFER );
+	YY_CURRENT_BUFFER_LVALUE = NULL;
+	if ((yy_buffer_stack_top) > 0)
+		--(yy_buffer_stack_top);
+
+	if (YY_CURRENT_BUFFER) {
+		wcspih_load_buffer_state( );
+		(yy_did_buffer_switch_on_eof) = 1;
+	}
+}
+
+/* Allocates the stack if it does not exist.
+ *  Guarantees space for at least one push.
+ */
+static void wcspihensure_buffer_stack (void)
+{
+	int num_to_alloc;
+    
+	if (!(yy_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;
+		(yy_buffer_stack) = (struct yy_buffer_state**)wcspihalloc
+								(num_to_alloc * sizeof(struct yy_buffer_state*)
+								);
+		if ( ! (yy_buffer_stack) )
+			YY_FATAL_ERROR( "out of dynamic memory in wcspihensure_buffer_stack()" );
+								  
+		memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+				
+		(yy_buffer_stack_max) = num_to_alloc;
+		(yy_buffer_stack_top) = 0;
+		return;
+	}
+
+	if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
+
+		/* Increase the buffer to prepare for a possible push. */
+		int grow_size = 8 /* arbitrary grow size */;
+
+		num_to_alloc = (yy_buffer_stack_max) + grow_size;
+		(yy_buffer_stack) = (struct yy_buffer_state**)wcspihrealloc
+								((yy_buffer_stack),
+								num_to_alloc * sizeof(struct yy_buffer_state*)
+								);
+		if ( ! (yy_buffer_stack) )
+			YY_FATAL_ERROR( "out of dynamic memory in wcspihensure_buffer_stack()" );
+
+		/* zero only the new slots.*/
+		memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
+		(yy_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. 
+ */
+YY_BUFFER_STATE wcspih_scan_buffer  (char * base, yy_size_t  size )
+{
+	YY_BUFFER_STATE b;
+    
+	if ( size < 2 ||
+	     base[size-2] != YY_END_OF_BUFFER_CHAR ||
+	     base[size-1] != YY_END_OF_BUFFER_CHAR )
+		/* They forgot to leave room for the EOB's. */
+		return 0;
+
+	b = (YY_BUFFER_STATE) wcspihalloc(sizeof( struct yy_buffer_state )  );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in wcspih_scan_buffer()" );
+
+	b->yy_buf_size = size - 2;	/* "- 2" to take care of EOB's */
+	b->yy_buf_pos = b->yy_ch_buf = base;
+	b->yy_is_our_buffer = 0;
+	b->yy_input_file = 0;
+	b->yy_n_chars = b->yy_buf_size;
+	b->yy_is_interactive = 0;
+	b->yy_at_bol = 1;
+	b->yy_fill_buffer = 0;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	wcspih_switch_to_buffer(b  );
+
+	return b;
+}
+
+/** Setup the input buffer state to scan a string. The next call to wcspihlex() will
+ * scan from a @e copy of @a str.
+ * @param yystr 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
+ *       wcspih_scan_bytes() instead.
+ */
+YY_BUFFER_STATE wcspih_scan_string (yyconst char * yystr )
+{
+    
+	return wcspih_scan_bytes(yystr,strlen(yystr) );
+}
+
+/** Setup the input buffer state to scan the given bytes. The next call to wcspihlex() will
+ * scan from a @e copy of @a bytes.
+ * @param yybytes the byte buffer to scan
+ * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
+ * 
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE wcspih_scan_bytes  (yyconst char * yybytes, int  _yybytes_len )
+{
+	YY_BUFFER_STATE b;
+	char *buf;
+	yy_size_t n;
+	int i;
+    
+	/* Get memory for full buffer, including space for trailing EOB's. */
+	n = _yybytes_len + 2;
+	buf = (char *) wcspihalloc(n  );
+	if ( ! buf )
+		YY_FATAL_ERROR( "out of dynamic memory in wcspih_scan_bytes()" );
+
+	for ( i = 0; i < _yybytes_len; ++i )
+		buf[i] = yybytes[i];
+
+	buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
+
+	b = wcspih_scan_buffer(buf,n );
+	if ( ! b )
+		YY_FATAL_ERROR( "bad buffer in wcspih_scan_bytes()" );
+
+	/* It's okay to grow etc. this buffer, and we should throw it
+	 * away when we're done.
+	 */
+	b->yy_is_our_buffer = 1;
+
+	return b;
+}
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+static void yy_fatal_error (yyconst char* msg )
+{
+    	(void) fprintf( stderr, "%s\n", msg );
+	exit( YY_EXIT_FAILURE );
+}
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up wcspihtext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+		wcspihtext[wcspihleng] = (yy_hold_char); \
+		(yy_c_buf_p) = wcspihtext + yyless_macro_arg; \
+		(yy_hold_char) = *(yy_c_buf_p); \
+		*(yy_c_buf_p) = '\0'; \
+		wcspihleng = yyless_macro_arg; \
+		} \
+	while ( 0 )
+
+/* Accessor  methods (get/set functions) to struct members. */
+
+/** Get the current line number.
+ * 
+ */
+int wcspihget_lineno  (void)
+{
+        
+    return wcspihlineno;
+}
+
+/** Get the input stream.
+ * 
+ */
+FILE *wcspihget_in  (void)
+{
+        return wcspihin;
+}
+
+/** Get the output stream.
+ * 
+ */
+FILE *wcspihget_out  (void)
+{
+        return wcspihout;
+}
+
+/** Get the length of the current token.
+ * 
+ */
+int wcspihget_leng  (void)
+{
+        return wcspihleng;
+}
+
+/** Get the current token.
+ * 
+ */
+
+char *wcspihget_text  (void)
+{
+        return wcspihtext;
+}
+
+/** Set the current line number.
+ * @param line_number
+ * 
+ */
+void wcspihset_lineno (int  line_number )
+{
+    
+    wcspihlineno = line_number;
+}
+
+/** Set the input stream. This does not discard the current
+ * input buffer.
+ * @param in_str A readable stream.
+ * 
+ * @see wcspih_switch_to_buffer
+ */
+void wcspihset_in (FILE *  in_str )
+{
+        wcspihin = in_str ;
+}
+
+void wcspihset_out (FILE *  out_str )
+{
+        wcspihout = out_str ;
+}
+
+int wcspihget_debug  (void)
+{
+        return wcspih_flex_debug;
+}
+
+void wcspihset_debug (int  bdebug )
+{
+        wcspih_flex_debug = bdebug ;
+}
+
+static int yy_init_globals (void)
+{
+        /* Initialization is the same as for the non-reentrant scanner.
+     * This function is called from wcspihlex_destroy(), so don't allocate here.
+     */
+
+    (yy_buffer_stack) = 0;
+    (yy_buffer_stack_top) = 0;
+    (yy_buffer_stack_max) = 0;
+    (yy_c_buf_p) = (char *) 0;
+    (yy_init) = 0;
+    (yy_start) = 0;
+
+/* Defined in main.c */
+#ifdef YY_STDINIT
+    wcspihin = stdin;
+    wcspihout = stdout;
+#else
+    wcspihin = (FILE *) 0;
+    wcspihout = (FILE *) 0;
+#endif
+
+    /* For future reference: Set errno on error, since we are called by
+     * wcspihlex_init()
+     */
+    return 0;
+}
+
+/* wcspihlex_destroy is for both reentrant and non-reentrant scanners. */
+int wcspihlex_destroy  (void)
+{
+    
+    /* Pop the buffer stack, destroying each element. */
+	while(YY_CURRENT_BUFFER){
+		wcspih_delete_buffer(YY_CURRENT_BUFFER  );
+		YY_CURRENT_BUFFER_LVALUE = NULL;
+		wcspihpop_buffer_state();
+	}
+
+	/* Destroy the stack itself. */
+	wcspihfree((yy_buffer_stack) );
+	(yy_buffer_stack) = NULL;
+
+    /* Reset the globals. This is important in a non-reentrant scanner so the next time
+     * wcspihlex() is called, initialization will occur. */
+    yy_init_globals( );
+
+    return 0;
+}
+
+/*
+ * Internal utility routines.
+ */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
+{
+	register int i;
+	for ( i = 0; i < n; ++i )
+		s1[i] = s2[i];
+}
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * s )
+{
+	register int n;
+	for ( n = 0; s[n]; ++n )
+		;
+
+	return n;
+}
+#endif
+
+void *wcspihalloc (yy_size_t  size )
+{
+	return (void *) malloc( size );
+}
+
+void *wcspihrealloc  (void * ptr, yy_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 wcspihfree (void * ptr )
+{
+	free( (char *) ptr );	/* see wcspihrealloc() for (char *) cast */
+}
+
+#define YYTABLES_NAME "yytables"
+
+#line 1021 "wcspih.l"
+
+
+
+/*----------------------------------------------------------------------------
+* Determine the number of coordinate representations (up to 27) and the
+* number of coordinate axes in each, and count the number of PVi_ma and
+* PSi_ma keywords in each representation.
+*---------------------------------------------------------------------------*/
+
+void wcspih_naxes(int naxis, int i, int j, char a, int alts[], int *npptr)
+
+{
+  /* On the first pass alts[] is used to determine the number of axes */
+  /* for each of the 27 possible alternate coordinate descriptions.   */
+  int ialt, *ip;
+
+  if (a == 0) {
+    return;
+  }
+
+  ialt = 0;
+  if (a != ' ') {
+    ialt = a - 'A' + 1;
+  }
+
+  ip = alts + ialt;
+
+  if (*ip < naxis) {
+    *ip = naxis;
+  }
+
+  /* i or j can be greater than naxis. */
+  if (*ip < i) {
+    *ip = i;
+  }
+
+  if (*ip < j) {
+    *ip = j;
+  }
+
+  if (npptr) {
+    npptr[ialt]++;
+  }
+}
+
+
+/*----------------------------------------------------------------------------
+* Allocate memory for an array of the required number of wcsprm structs and
+* initialize each of them.
+*---------------------------------------------------------------------------*/
+
+int wcspih_inits(
+  int naxis,
+  int alts[],
+  int npv[],
+  int nps[],
+  int *nwcs,
+  struct wcsprm **wcs)
+
+{
+  int ialt, defaults, npsmax, npvmax, status = 0;
+  struct wcsprm *wcsp;
+
+  /* Find the number of coordinate descriptions. */
+  *nwcs = 0;
+  for (ialt = 0; ialt < 27; ialt++) {
+    if (alts[ialt]) (*nwcs)++;
+  }
+
+  if ((defaults = !(*nwcs) && naxis)) {
+    /* NAXIS is non-zero but there were no WCS keywords with an alternate
+       version code; create a default WCS with blank alternate version. */
+    wcspih_naxes(naxis, 0, 0, ' ', alts, 0x0);
+    *nwcs = 1;
+  }
+
+  if (*nwcs) {
+    /* Allocate memory for the required number of wcsprm structs. */
+    if (!(*wcs = calloc(*nwcs, sizeof(struct wcsprm)))) {
+      return 2;
+    }
+
+    /* Record the current values of NPVMAX and NPSMAX. */
+    npvmax = wcsnpv(-1);
+    npsmax = wcsnps(-1);
+
+    /* Initialize each wcsprm struct. */
+    wcsp = *wcs;
+    *nwcs = 0;
+    for (ialt = 0; ialt < 27; ialt++) {
+      if (alts[ialt]) {
+        wcsp->flag = -1;
+        wcsnpv(npv[ialt]);
+        wcsnps(nps[ialt]);
+        if ((status = wcsini(1, alts[ialt], wcsp))) {
+          wcsvfree(nwcs, wcs);
+          break;
+        }
+
+        /* Record the alternate version code. */
+        if (ialt) {
+          wcsp->alt[0] = 'A' + ialt - 1;
+        }
+
+        /* Record in wcsname whether this is a default description. */
+        if (defaults) {
+          strcpy(wcsp->wcsname, "DEFAULTS");
+        }
+
+        /* On the second pass alts[] indexes the array of wcsprm structs. */
+        alts[ialt] = (*nwcs)++;
+
+        wcsp++;
+      }
+    }
+
+    /* Restore the original values of NPVMAX and NPSMAX. */
+    wcsnpv(npvmax);
+    wcsnps(npsmax);
+  }
+
+  return status;
+}
+
+
+/*----------------------------------------------------------------------------
+* Interpret special keywords encountered for each coordinate representation.
+*---------------------------------------------------------------------------*/
+
+int wcspih_final(
+  int alts[],
+  double epoch[],
+  double vsource[],
+  int *nwcs,
+  struct wcsprm **wcs)
+
+{
+  int ialt, status;
+  double beta, c = 299792458.0;
+
+  for (ialt = 0; ialt < *nwcs; ialt++) {
+    /* Check for EPOCH overriding EQUINOXa. */
+    if (undefined((*wcs+ialt)->equinox) && !undefined(epoch[ialt])) {
+      /* Set EQUINOXa. */
+      (*wcs+ialt)->equinox = epoch[ialt];
+    }
+
+    /* Check for VSOURCEa overriding ZSOURCEa. */
+    if (undefined((*wcs+ialt)->zsource) && !undefined(vsource[ialt])) {
+      /* Convert relativistic Doppler velocity to redshift. */
+      beta = vsource[ialt]/c;
+      (*wcs+ialt)->zsource = (1.0+beta)/sqrt(1.0 - beta*beta) - 1.0;
+    }
+
+    /* Interpret -TAB header keywords. */
+    if ((status = wcstab(*wcs+ialt))) {
+       wcsvfree(nwcs, wcs);
+       return status;
+    }
+  }
+
+  return 0;
+}
+
diff --git a/cextern/wcslib/C/flexed/wcsulex.c b/cextern/wcslib/C/flexed/wcsulex.c
new file mode 100644
index 0000000..db7c603
--- /dev/null
+++ b/cextern/wcslib/C/flexed/wcsulex.c
@@ -0,0 +1,9428 @@
+#line 2 "wcsulex.c"
+
+#line 4 "wcsulex.c"
+
+#define  YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define yy_create_buffer wcsulex_create_buffer
+#define yy_delete_buffer wcsulex_delete_buffer
+#define yy_flex_debug wcsulex_flex_debug
+#define yy_init_buffer wcsulex_init_buffer
+#define yy_flush_buffer wcsulex_flush_buffer
+#define yy_load_buffer_state wcsulex_load_buffer_state
+#define yy_switch_to_buffer wcsulex_switch_to_buffer
+#define yyin wcsulexin
+#define yyleng wcsulexleng
+#define yylex wcsulexlex
+#define yylineno wcsulexlineno
+#define yyout wcsulexout
+#define yyrestart wcsulexrestart
+#define yytext wcsulextext
+#define yywrap wcsulexwrap
+#define yyalloc wcsulexalloc
+#define yyrealloc wcsulexrealloc
+#define yyfree wcsulexfree
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+#define YY_FLEX_SUBMINOR_VERSION 35
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+/* First, we deal with  platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. 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 <inttypes.h>
+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;
+
+/* 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 /* ! C99 */
+
+#endif /* ! FLEXINT_H */
+
+#ifdef __cplusplus
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else	/* ! __cplusplus */
+
+/* C99 requires __STDC__ to be defined as 1. */
+#if defined (__STDC__)
+
+#define YY_USE_CONST
+
+#endif	/* defined (__STDC__) */
+#endif	/* ! __cplusplus */
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_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 YY_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 (yy_start) = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state.  The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START (((yy_start) - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE wcsulexrestart(wcsulexin  )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k.
+ * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
+ * Ditto for the __ia64__ case accordingly.
+ */
+#define YY_BUF_SIZE 32768
+#else
+#define YY_BUF_SIZE 16384
+#endif /* __ia64__ */
+#endif
+
+/* The state buf must be large enough to hold one state per character in the main buffer.
+ */
+#define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+extern int wcsulexleng;
+
+extern FILE *wcsulexin, *wcsulexout;
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+#define YY_LESS_LINENO(n)
+    
+/* Return all but the first "n" matched characters back to the input stream. */
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up wcsulextext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+		*yy_cp = (yy_hold_char); \
+		YY_RESTORE_YY_MORE_OFFSET \
+		(yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+		YY_DO_BEFORE_ACTION; /* set up wcsulextext again */ \
+		} \
+	while ( 0 )
+
+#define unput(c) yyunput( c, (yytext_ptr)  )
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef size_t yy_size_t;
+#endif
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+	{
+	FILE *yy_input_file;
+
+	char *yy_ch_buf;		/* input buffer */
+	char *yy_buf_pos;		/* current position in input buffer */
+
+	/* Size of input buffer in bytes, not including room for EOB
+	 * characters.
+	 */
+	yy_size_t yy_buf_size;
+
+	/* Number of characters read into yy_ch_buf, not including EOB
+	 * characters.
+	 */
+	int yy_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 yy_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 yy_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 yy_at_bol;
+
+    int yy_bs_lineno; /**< The line count. */
+    int yy_bs_column; /**< The column count. */
+    
+	/* Whether to try to fill the input buffer when we reach the
+	 * end of it.
+	 */
+	int yy_fill_buffer;
+
+	int yy_buffer_status;
+
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+	/* When an EOF's been seen but there's still some text to process
+	 * then we mark the buffer as YY_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 wcsulexrestart()), so that the user can continue scanning by
+	 * just pointing wcsulexin at a new input file.
+	 */
+#define YY_BUFFER_EOF_PENDING 2
+
+	};
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+/* Stack of input buffers. */
+static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
+static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
+static YY_BUFFER_STATE * yy_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 YY_CURRENT_BUFFER ( (yy_buffer_stack) \
+                          ? (yy_buffer_stack)[(yy_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 YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
+
+/* yy_hold_char holds the character lost when wcsulextext is formed. */
+static char yy_hold_char;
+static int yy_n_chars;		/* number of characters read into yy_ch_buf */
+int wcsulexleng;
+
+/* Points to current character in buffer. */
+static char *yy_c_buf_p = (char *) 0;
+static int yy_init = 0;		/* whether we need to initialize */
+static int yy_start = 0;	/* start state number */
+
+/* Flag which is used to allow wcsulexwrap()'s to do buffer switches
+ * instead of setting up a fresh wcsulexin.  A bit of a hack ...
+ */
+static int yy_did_buffer_switch_on_eof;
+
+void wcsulexrestart (FILE *input_file  );
+void wcsulex_switch_to_buffer (YY_BUFFER_STATE new_buffer  );
+YY_BUFFER_STATE wcsulex_create_buffer (FILE *file,int size  );
+void wcsulex_delete_buffer (YY_BUFFER_STATE b  );
+void wcsulex_flush_buffer (YY_BUFFER_STATE b  );
+void wcsulexpush_buffer_state (YY_BUFFER_STATE new_buffer  );
+void wcsulexpop_buffer_state (void );
+
+static void wcsulexensure_buffer_stack (void );
+static void wcsulex_load_buffer_state (void );
+static void wcsulex_init_buffer (YY_BUFFER_STATE b,FILE *file  );
+
+#define YY_FLUSH_BUFFER wcsulex_flush_buffer(YY_CURRENT_BUFFER )
+
+YY_BUFFER_STATE wcsulex_scan_buffer (char *base,yy_size_t size  );
+YY_BUFFER_STATE wcsulex_scan_string (yyconst char *yy_str  );
+YY_BUFFER_STATE wcsulex_scan_bytes (yyconst char *bytes,int len  );
+
+void *wcsulexalloc (yy_size_t  );
+void *wcsulexrealloc (void *,yy_size_t  );
+void wcsulexfree (void *  );
+
+#define yy_new_buffer wcsulex_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+	{ \
+	if ( ! YY_CURRENT_BUFFER ){ \
+        wcsulexensure_buffer_stack (); \
+		YY_CURRENT_BUFFER_LVALUE =    \
+            wcsulex_create_buffer(wcsulexin,YY_BUF_SIZE ); \
+	} \
+	YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+	}
+
+#define yy_set_bol(at_bol) \
+	{ \
+	if ( ! YY_CURRENT_BUFFER ){\
+        wcsulexensure_buffer_stack (); \
+		YY_CURRENT_BUFFER_LVALUE =    \
+            wcsulex_create_buffer(wcsulexin,YY_BUF_SIZE ); \
+	} \
+	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+	}
+
+#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+
+/* Begin user sect3 */
+
+#define wcsulexwrap(n) 1
+#define YY_SKIP_YYWRAP
+
+typedef char YY_CHAR;
+
+FILE *wcsulexin = (FILE *) 0, *wcsulexout = (FILE *) 0;
+
+typedef int yy_state_type;
+
+extern int wcsulexlineno;
+
+int wcsulexlineno = 1;
+
+extern char *wcsulextext;
+#define yytext_ptr wcsulextext
+static yyconst flex_int16_t yy_nxt[][128] =
+    {
+    {
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0
+    },
+
+    {
+       13,   14,   14,   14,   14,   14,   14,   14,   14,   14,
+       15,   14,   14,   14,   14,   14,   14,   14,   14,   14,
+       14,   14,   14,   14,   14,   14,   14,   14,   14,   14,
+       14,   14,   16,   14,   14,   14,   14,   14,   14,   14,
+       17,   14,   18,   14,   14,   14,   18,   19,   14,   14,
+       14,   14,   14,   14,   14,   14,   14,   14,   14,   14,
+       14,   14,   14,   14,   14,   20,   21,   22,   23,   24,
+
+       22,   25,   26,   14,   27,   28,   14,   24,   22,   29,
+       30,   14,   31,   32,   33,   14,   22,   34,   14,   24,
+       24,   14,   14,   35,   14,   14,   14,   36,   37,   38,
+       39,   40,   41,   28,   42,   14,   14,   24,   43,   44,
+       41,   29,   45,   14,   46,   47,   14,   48,   49,   14,
+       14,   50,   41,   14,   14,   14,   14,   14
+    },
+
+    {
+       13,   14,   14,   14,   14,   14,   14,   14,   14,   14,
+       15,   14,   14,   14,   14,   14,   14,   14,   14,   14,
+       14,   14,   14,   14,   14,   14,   14,   14,   14,   14,
+       14,   14,   51,   14,   14,   14,   14,   14,   14,   14,
+
+       17,   14,   52,   14,   14,   14,   52,   19,   14,   53,
+       14,   14,   14,   14,   14,   14,   14,   14,   14,   14,
+       14,   14,   14,   14,   14,   20,   21,   22,   23,   24,
+       22,   25,   26,   14,   27,   28,   14,   24,   22,   29,
+       30,   14,   31,   32,   33,   14,   22,   34,   14,   24,
+       24,   54,   14,   35,   14,   14,   14,   36,   37,   38,
+       39,   55,   41,   28,   42,   14,   14,   24,   56,   44,
+       41,   29,   45,   14,   46,   47,   14,   48,   49,   14,
+       14,   50,   41,   14,   14,   14,   14,   14
+    },
+
+    {
+       13,   57,   57,   57,   57,   57,   57,   57,   57,   57,
+
+       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
+       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
+       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
+       58,   59,   57,   57,   57,   57,   57,   57,   57,   57,
+       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
+       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
+       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
+       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
+       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
+       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
+
+       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
+       57,   57,   57,   57,   57,   57,   57,   57
+    },
+
+    {
+       13,   57,   57,   57,   57,   57,   57,   57,   57,   57,
+       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
+       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
+       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
+       58,   59,   57,   57,   57,   57,   57,   57,   57,   57,
+       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
+       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
+       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
+
+       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
+       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
+       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
+       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
+       57,   57,   57,   57,   57,   57,   57,   57
+    },
+
+    {
+       13,   60,   60,   60,   60,   60,   60,   60,   60,   60,
+       15,   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,
+       60,   60,   60,   60,   60,   60,   60,   60,   60,   61,
+       60,   62,   60,   60,   60,   60,   60,   63,   60,   60,
+       64,   60,   60,   60,   65,   60,   60,   60,   60,   66,
+       67,   60,   60,   60,   60,   60,   60,   68,   60,   69,
+       70,   60,   71,   60,   72,   60,   60,   73,   60,   74,
+       75,   60,   76,   60,   60,   60,   60,   77,   60,   60,
+       60,   78,   79,   60,   60,   60,   60,   60
+    },
+
+    {
+       13,   60,   60,   60,   60,   60,   60,   60,   60,   60,
+       15,   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,
+       60,   60,   60,   60,   60,   60,   60,   60,   60,   61,
+       60,   62,   60,   60,   60,   60,   60,   63,   60,   60,
+       64,   60,   60,   60,   65,   60,   60,   60,   60,   66,
+       67,   60,   60,   60,   60,   60,   60,   68,   60,   69,
+       70,   60,   71,   60,   72,   60,   60,   73,   60,   74,
+       75,   60,   76,   60,   60,   60,   60,   77,   60,   60,
+
+       60,   78,   79,   60,   60,   60,   60,   60
+    },
+
+    {
+       13,   80,   80,   80,   80,   80,   80,   80,   80,   80,
+       15,   80,   80,   80,   80,   80,   80,   80,   80,   80,
+       80,   80,   80,   80,   80,   80,   80,   80,   80,   80,
+       80,   80,   80,   80,   80,   80,   80,   80,   80,   80,
+       80,   80,   80,   80,   80,   80,   80,   80,   80,   80,
+       80,   80,   80,   80,   80,   80,   80,   80,   80,   80,
+       80,   80,   80,   80,   80,   81,   82,   83,   84,   80,
+       85,   86,   87,   80,   88,   89,   80,   80,   90,   91,
+       92,   80,   93,   94,   95,   80,   96,   97,   80,   80,
+
+       80,   80,   80,   80,   80,   80,   80,   98,   99,  100,
+      101,  102,   80,  103,  104,   80,   80,   80,  105,  106,
+       80,   91,  107,   80,  108,  109,   80,  110,  111,   80,
+       80,  112,   80,   80,   80,   80,   80,   80
+    },
+
+    {
+       13,   80,   80,   80,   80,   80,   80,   80,   80,   80,
+       15,   80,   80,   80,   80,   80,   80,   80,   80,   80,
+       80,   80,   80,   80,   80,   80,   80,   80,   80,   80,
+       80,   80,   80,   80,   80,   80,   80,   80,   80,   80,
+       80,   80,   80,   80,   80,   80,   80,   80,   80,   80,
+       80,   80,   80,   80,   80,   80,   80,   80,   80,   80,
+
+       80,   80,   80,   80,   80,   81,   82,   83,   84,   80,
+       85,   86,   87,   80,   88,   89,   80,   80,   90,   91,
+       92,   80,   93,   94,   95,   80,   96,   97,   80,   80,
+       80,   80,   80,   80,   80,   80,   80,   98,   99,  100,
+      101,  102,   80,  103,  104,   80,   80,   80,  105,  106,
+       80,   91,  107,   80,  108,  109,   80,  110,  111,   80,
+       80,  112,   80,   80,   80,   80,   80,   80
+    },
+
+    {
+       13,  113,  113,  113,  113,  113,  113,  113,  113,  113,
+       15,  113,  113,  113,  113,  113,  113,  113,  113,  113,
+      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
+
+      113,  113,  114,  113,  113,  113,  113,  113,  113,  113,
+      115,  113,  116,  117,  113,  117,  118,  119,  113,  120,
+      120,  120,  120,  120,  120,  120,  120,  120,  113,  113,
+      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
+      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
+      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
+      113,  113,  113,  121,  122,  113,  113,  113,  113,  113,
+      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
+      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
+      113,  113,  113,  113,  113,  113,  113,  113
+
+    },
+
+    {
+       13,  113,  113,  113,  113,  113,  113,  113,  113,  113,
+       15,  113,  113,  113,  113,  113,  113,  113,  113,  113,
+      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
+      113,  113,  114,  113,  113,  113,  113,  113,  113,  113,
+      115,  113,  116,  117,  113,  117,  118,  119,  113,  120,
+      120,  120,  120,  120,  120,  120,  120,  120,  113,  113,
+      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
+      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
+      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
+      113,  113,  113,  121,  122,  113,  113,  113,  113,  113,
+
+      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
+      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
+      113,  113,  113,  113,  113,  113,  113,  113
+    },
+
+    {
+       13,  123,  123,  123,  123,  123,  123,  123,  123,  123,
+       15,  123,  123,  123,  123,  123,  123,  123,  123,  123,
+      123,  123,  123,  123,  123,  123,  123,  123,  123,  123,
+      123,  123,  123,  123,  123,  123,  123,  123,  123,  123,
+      123,  123,  123,  123,  123,  123,  123,  123,  123,  123,
+      123,  123,  123,  123,  123,  123,  123,  123,  123,  123,
+      123,  123,  123,  123,  123,  123,  123,  123,  123,  123,
+
+      123,  123,  123,  123,  123,  123,  123,  123,  123,  123,
+      123,  123,  123,  123,  123,  123,  123,  123,  123,  123,
+      123,  123,  123,  123,  123,  123,  123,  123,  123,  123,
+      123,  123,  123,  123,  123,  123,  123,  123,  123,  123,
+      123,  123,  123,  123,  123,  123,  123,  123,  123,  123,
+      123,  123,  123,  123,  123,  123,  123,  123
+    },
+
+    {
+       13,  123,  123,  123,  123,  123,  123,  123,  123,  123,
+       15,  123,  123,  123,  123,  123,  123,  123,  123,  123,
+      123,  123,  123,  123,  123,  123,  123,  123,  123,  123,
+      123,  123,  123,  123,  123,  123,  123,  123,  123,  123,
+
+      123,  123,  123,  123,  123,  123,  123,  123,  123,  123,
+      123,  123,  123,  123,  123,  123,  123,  123,  123,  123,
+      123,  123,  123,  123,  123,  123,  123,  123,  123,  123,
+      123,  123,  123,  123,  123,  123,  123,  123,  123,  123,
+      123,  123,  123,  123,  123,  123,  123,  123,  123,  123,
+      123,  123,  123,  123,  123,  123,  123,  123,  123,  123,
+      123,  123,  123,  123,  123,  123,  123,  123,  123,  123,
+      123,  123,  123,  123,  123,  123,  123,  123,  123,  123,
+      123,  123,  123,  123,  123,  123,  123,  123
+    },
+
+    {
+      -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,  -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,  -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,  -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
+    },
+
+    {
+       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,  -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
+    },
+
+    {
+       13,  -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,  -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
+    },
+
+    {
+       13,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
+      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
+
+      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
+      -16,  -16,  124,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
+      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
+      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
+      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
+      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
+      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
+      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
+      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
+      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
+
+      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16
+    },
+
+    {
+       13,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
+      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
+      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
+      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
+      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
+      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
+      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
+      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
+      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
+
+      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
+      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
+      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
+      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17
+    },
+
+    {
+       13,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,
+      -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,
+      -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,
+      -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,
+      -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,
+      -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,
+
+      -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,
+      -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,
+      -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,
+      -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,
+      -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,
+      -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,
+      -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18
+    },
+
+    {
+       13,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,
+      -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,
+      -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,
+
+      -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,
+      -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,
+      -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,
+      -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,
+      -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,
+      -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,
+      -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,
+      -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,
+      -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,
+      -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19
+
+    },
+
+    {
+       13,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,
+      -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,
+      -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,
+      -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,
+      -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,
+      -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,
+      -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,
+      -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,
+      -20,  -20,  -20,  -20,  -20,  125,  -20,  -20,  -20,  -20,
+      -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,
+
+      -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,
+      126,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,
+      -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20
+    },
+
+    {
+       13,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,
+      -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,
+      -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,
+      -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,
+      -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,
+      -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,
+      -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,
+
+      -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,
+      -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,
+      -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,
+      -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,
+      -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,
+      -21,  127,  -21,  -21,  -21,  -21,  -21,  -21
+    },
+
+    {
+       13,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,
+      -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,
+      -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,
+      -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,
+
+      -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,
+      -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,
+      -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,
+      -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,
+      -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,
+      -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,
+      -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,
+      -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,
+      -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22
+    },
+
+    {
+       13,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
+
+      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
+      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
+      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
+      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
+      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
+      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
+      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
+      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
+      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
+      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
+
+      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
+      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23
+    },
+
+    {
+       13,  -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,  -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,  128,  129,  130,  -24,  -24,
+      130,  131,  132,  -24,  133,  128,  -24,  -24,  130,  134,
+
+      135,  -24,  131,  130,  130,  -24,  130,  136,  -24,  -24,
+      -24,  -24,  -24,  -24,  -24,  -24,  -24,  137,  138,  139,
+      -24,  140,  -24,  128,  -24,  -24,  -24,  -24,  141,  142,
+      -24,  134,  143,  -24,  144,  145,  -24,  -24,  -24,  -24,
+      -24,  146,  -24,  -24,  -24,  -24,  -24,  -24
+    },
+
+    {
+       13,  -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,  -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,  128,  129,  130,  -25,  -25,
+      130,  131,  132,  -25,  133,  128,  -25,  -25,  130,  134,
+      135,  -25,  131,  130,  130,  -25,  130,  136,  -25,  -25,
+      -25,  -25,  -25,  -25,  -25,  -25,  -25,  137,  138,  139,
+      -25,  140,  -25,  128,  -25,  -25,  -25,  -25,  141,  142,
+      -25,  134,  143,  -25,  144,  145,  -25,  -25,  -25,  -25,
+      -25,  146,  -25,  -25,  -25,  -25,  -25,  -25
+    },
+
+    {
+       13,  -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,  -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,  -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,  -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,  147,  -26,  -26,  -26,  -26,  -26
+    },
+
+    {
+       13,  -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,  -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,  -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,  -27,  -27,  -27,
+      -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,
+      -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,
+      -27,  148,  -27,  -27,  -27,  -27,  -27,  -27
+    },
+
+    {
+       13,  -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,  -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
+    },
+
+    {
+       13,  -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,  -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,  149,  -29,  -29,  -29,  -29,  -29,
+      -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,
+      -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29
+
+    },
+
+    {
+       13,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
+      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
+      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
+      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
+      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
+      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
+      -30,  -30,  -30,  -30,  -30,  128,  129,  130,  -30,  -30,
+      130,  131,  132,  -30,  133,  128,  -30,  -30,  130,  134,
+      135,  -30,  131,  130,  130,  -30,  130,  136,  -30,  -30,
+      -30,  -30,  -30,  -30,  -30,  -30,  -30,  150,  138,  139,
+
+      -30,  140,  -30,  128,  -30,  -30,  -30,  -30,  141,  142,
+      -30,  134,  143,  -30,  144,  145,  -30,  -30,  -30,  -30,
+      -30,  146,  -30,  -30,  -30,  -30,  -30,  -30
+    },
+
+    {
+       13,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
+      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
+      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
+      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
+      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
+      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
+      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
+
+      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
+      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
+      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
+      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
+      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
+      -31,  151,  -31,  -31,  -31,  -31,  -31,  -31
+    },
+
+    {
+       13,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
+      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
+      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
+      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
+
+      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
+      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
+      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
+      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
+      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
+      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
+      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
+      -32,  -32,  -32,  -32,  -32,  -32,  -32,  152,  -32,  -32,
+      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32
+    },
+
+    {
+       13,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
+
+      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
+      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
+      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
+      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
+      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
+      -33,  -33,  -33,  -33,  -33,  128,  129,  130,  -33,  -33,
+      130,  131,  132,  -33,  133,  128,  -33,  -33,  130,  134,
+      135,  -33,  131,  130,  130,  -33,  130,  136,  -33,  -33,
+      -33,  -33,  -33,  -33,  -33,  -33,  -33,  137,  138,  139,
+      -33,  140,  -33,  128,  -33,  -33,  -33,  -33,  141,  142,
+
+      -33,  134,  143,  -33,  144,  145,  -33,  -33,  -33,  -33,
+      -33,  146,  -33,  -33,  -33,  -33,  -33,  -33
+    },
+
+    {
+       13,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
+      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
+      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
+      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
+      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
+      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
+      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
+      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
+
+      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
+      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  147,  -34,
+      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
+      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
+      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34
+    },
+
+    {
+       13,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
+      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
+      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
+      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
+      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
+
+      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
+      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
+      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
+      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
+      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
+      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
+      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
+      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35
+    },
+
+    {
+       13,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
+      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
+
+      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
+      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
+      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
+      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
+      -36,  -36,  -36,  -36,  -36,  128,  -36,  130,  -36,  -36,
+      130,  131,  132,  -36,  133,  128,  -36,  -36,  130,  134,
+      135,  -36,  131,  130,  130,  -36,  130,  136,  -36,  -36,
+      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  153,  139,
+      154,  140,  -36,  128,  -36,  -36,  -36,  -36,  141,  155,
+      126,  134,  -36,  -36,  156,  145,  -36,  -36,  -36,  -36,
+
+      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36
+    },
+
+    {
+       13,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  157,  -37,  -37,
+      -37,  158,  -37,  -37,  -37,  159,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+      -37,  127,  -37,  -37,  -37,  -37,  -37,  -37
+    },
+
+    {
+       13,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
+      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
+      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
+      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
+      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
+      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
+
+      -38,  -38,  -38,  -38,  -38,  128,  -38,  130,  -38,  -38,
+      130,  131,  132,  -38,  133,  128,  -38,  -38,  130,  134,
+      135,  -38,  131,  130,  130,  -38,  130,  136,  -38,  -38,
+      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  153,  139,
+      160,  140,  -38,  128,  161,  -38,  -38,  -38,  141,  155,
+      -38,  162,  -38,  -38,  144,  145,  163,  -38,  -38,  -38,
+      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38
+    },
+
+    {
+       13,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
+      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
+      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
+
+      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
+      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
+      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
+      -39,  -39,  -39,  -39,  -39,  128,  -39,  130,  -39,  -39,
+      130,  131,  132,  -39,  133,  128,  -39,  -39,  130,  134,
+      135,  -39,  131,  130,  130,  -39,  130,  136,  -39,  -39,
+      -39,  -39,  -39,  -39,  -39,  -39,  -39,  164,  153,  139,
+      -39,  165,  -39,  128,  -39,  -39,  -39,  -39,  141,  155,
+      -39,  134,  -39,  -39,  144,  145,  -39,  -39,  -39,  -39,
+      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39
+
+    },
+
+    {
+       13,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
+      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
+      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
+      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
+      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
+      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
+      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
+      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
+      -40,  -40,  -40,  -40,  -40,  -40,  148,  -40,  -40,  -40,
+      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
+
+      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
+      -40,  -40,  -40,  -40,  166,  -40,  -40,  -40,  -40,  -40,
+      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40
+    },
+
+    {
+       13,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,
+      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,
+      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,
+      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,
+      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,
+      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,
+      -41,  -41,  -41,  -41,  -41,  128,  -41,  130,  -41,  -41,
+
+      130,  131,  132,  -41,  133,  128,  -41,  -41,  130,  134,
+      135,  -41,  131,  130,  130,  -41,  130,  136,  -41,  -41,
+      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  153,  139,
+      -41,  140,  -41,  128,  -41,  -41,  -41,  -41,  141,  155,
+      -41,  134,  -41,  -41,  144,  145,  -41,  -41,  -41,  -41,
+      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41
+    },
+
+    {
+       13,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
+      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
+      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
+      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
+
+      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
+      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
+      -42,  -42,  -42,  -42,  -42,  128,  129,  130,  -42,  -42,
+      130,  131,  132,  -42,  133,  128,  -42,  -42,  130,  134,
+      135,  -42,  131,  130,  130,  -42,  130,  136,  -42,  -42,
+      -42,  -42,  -42,  -42,  -42,  -42,  -42,  137,  138,  139,
+      -42,  140,  -42,  128,  -42,  -42,  -42,  -42,  141,  142,
+      -42,  134,  143,  -42,  144,  145,  -42,  -42,  -42,  -42,
+      -42,  146,  -42,  -42,  -42,  -42,  -42,  -42
+    },
+
+    {
+       13,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
+
+      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
+      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
+      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
+      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
+      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
+      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
+      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
+      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
+      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
+      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  147,
+
+      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
+      147,  167,  -43,  -43,  -43,  -43,  -43,  -43
+    },
+
+    {
+       13,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
+      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
+      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
+      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
+      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
+      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
+      -44,  -44,  -44,  -44,  -44,  128,  -44,  130,  -44,  -44,
+      130,  131,  132,  -44,  133,  128,  -44,  -44,  130,  134,
+
+      135,  -44,  131,  130,  130,  -44,  130,  136,  -44,  -44,
+      -44,  -44,  -44,  -44,  -44,  -44,  -44,  168,  153,  139,
+      -44,  140,  -44,  128,  -44,  169,  -44,  -44,  141,  155,
+      -44,  170,  -44,  -44,  144,  145,  -44,  -44,  -44,  -44,
+      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44
+    },
+
+    {
+       13,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
+      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
+      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
+      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
+      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
+
+      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
+      -45,  -45,  -45,  -45,  -45,  128,  -45,  130,  -45,  -45,
+      130,  131,  132,  -45,  133,  128,  -45,  -45,  130,  134,
+      135,  -45,  131,  130,  130,  -45,  130,  136,  -45,  -45,
+      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  153,  171,
+      -45,  140,  -45,  128,  172,  173,  -45,  -45,  141,  155,
+      -45,  134,  -45,  -45,  144,  145,  -45,  -45,  -45,  -45,
+      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45
+    },
+
+    {
+       13,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
+      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
+
+      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
+      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
+      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
+      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
+      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
+      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
+      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
+      -46,  -46,  -46,  -46,  -46,  -46,  -46,  174,  -46,  -46,
+      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
+      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
+
+      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46
+    },
+
+    {
+       13,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
+      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
+      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
+      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
+      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
+      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
+      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
+      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
+      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
+
+      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
+      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
+      -47,  175,  -47,  176,  160,  -47,  -47,  -47,  -47,  -47,
+      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47
+    },
+
+    {
+       13,  -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,  128,  -48,  130,  -48,  -48,
+      130,  131,  132,  -48,  133,  128,  -48,  -48,  130,  134,
+      135,  -48,  131,  130,  130,  -48,  130,  136,  -48,  -48,
+      -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  153,  139,
+      -48,  140,  -48,  128,  -48,  -48,  -48,  -48,  141,  155,
+      -48,  134,  -48,  -48,  144,  145,  -48,  -48,  -48,  -48,
+      -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48
+    },
+
+    {
+       13,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
+      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
+      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
+
+      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
+      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
+      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
+      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
+      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
+      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
+      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
+      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
+      -49,  177,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
+      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49
+
+    },
+
+    {
+       13,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
+      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
+      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
+      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
+      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
+      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
+      -50,  -50,  -50,  -50,  -50,  128,  -50,  130,  -50,  -50,
+      130,  131,  132,  -50,  133,  128,  -50,  -50,  130,  134,
+      135,  -50,  131,  130,  130,  -50,  130,  136,  -50,  -50,
+      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  153,  139,
+
+      -50,  140,  -50,  128,  -50,  -50,  -50,  -50,  141,  155,
+      -50,  134,  -50,  -50,  178,  145,  -50,  -50,  -50,  -50,
+      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50
+    },
+
+    {
+       13,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
+      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
+      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
+      -51,  -51,  179,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
+      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
+      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
+      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
+
+      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
+      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
+      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
+      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
+      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
+      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51
+    },
+
+    {
+       13,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
+      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
+      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
+      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
+
+      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
+      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
+      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
+      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
+      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
+      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
+      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
+      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
+      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52
+    },
+
+    {
+       13,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  180,  181,  -53,
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53
+    },
+
+    {
+       13,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
+      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
+      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
+      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
+      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
+      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
+      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
+      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
+
+      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
+      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
+      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
+      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
+      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54
+    },
+
+    {
+       13,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
+      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
+      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
+      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
+      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
+
+      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
+      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
+      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
+      -55,  -55,  -55,  -55,  -55,  -55,  148,  -55,  -55,  -55,
+      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
+      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
+      -55,  -55,  -55,  -55,  166,  -55,  -55,  -55,  -55,  -55,
+      182,  -55,  -55,  -55,  -55,  -55,  -55,  -55
+    },
+
+    {
+       13,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
+      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
+
+      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
+      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
+      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
+      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
+      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
+      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
+      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
+      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
+      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  147,
+      183,  184,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
+
+      147,  167,  -56,  -56,  -56,  -56,  -56,  -56
+    },
+
+    {
+       13,  185,  185,  185,  185,  185,  185,  185,  185,  185,
+      185,  185,  185,  185,  185,  185,  185,  185,  185,  185,
+      185,  185,  185,  185,  185,  185,  185,  185,  185,  185,
+      185,  185,  185,  185,  185,  185,  185,  185,  185,  185,
+      -57,  -57,  185,  185,  185,  185,  185,  185,  185,  185,
+      185,  185,  185,  185,  185,  185,  185,  185,  185,  185,
+      185,  185,  185,  185,  185,  185,  185,  185,  185,  185,
+      185,  185,  185,  185,  185,  185,  185,  185,  185,  185,
+      185,  185,  185,  185,  185,  185,  185,  185,  185,  185,
+
+      185,  185,  185,  185,  185,  185,  185,  185,  185,  185,
+      185,  185,  185,  185,  185,  185,  185,  185,  185,  185,
+      185,  185,  185,  185,  185,  185,  185,  185,  185,  185,
+      185,  185,  185,  185,  185,  185,  185,  185
+    },
+
+    {
+       13,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
+      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
+      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
+      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
+      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
+      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
+
+      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
+      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
+      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
+      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
+      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
+      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
+      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58
+    },
+
+    {
+       13,  -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,  -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,  -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,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,
+      -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59
+
+    },
+
+    {
+       13,  -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,
+      -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,  -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
+    },
+
+    {
+       13,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
+      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
+      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
+      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
+      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
+      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
+      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
+
+      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
+      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
+      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
+      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
+      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
+      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61
+    },
+
+    {
+       13,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
+      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
+      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
+      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
+
+      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
+      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
+      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
+      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
+      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
+      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
+      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
+      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
+      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62
+    },
+
+    {
+       13,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
+
+      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
+      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
+      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
+      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
+      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
+      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
+      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
+      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
+      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
+      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
+
+      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
+      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63
+    },
+
+    {
+       13,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
+      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
+      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
+      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
+      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
+      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
+      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
+      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
+
+      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
+      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
+      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
+      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
+      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64
+    },
+
+    {
+       13,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
+      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
+      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
+      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
+      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
+
+      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
+      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
+      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
+      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
+      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
+      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
+      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
+      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65
+    },
+
+    {
+       13,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
+      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
+
+      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
+      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
+      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
+      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
+      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
+      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
+      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
+      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
+      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
+      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
+
+      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66
+    },
+
+    {
+       13,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67
+    },
+
+    {
+       13,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+
+      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68
+    },
+
+    {
+       13,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
+      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
+      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
+
+      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
+      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
+      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
+      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
+      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
+      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
+      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
+      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
+      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
+      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69
+
+    },
+
+    {
+       13,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
+      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
+      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
+      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
+      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
+      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
+      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
+      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
+      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
+      -70,  -70,  -70,  -70,  -70,  -70,  -70,  186,  -70,  -70,
+
+      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
+      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
+      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70
+    },
+
+    {
+       13,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
+      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
+      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
+      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
+      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
+      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
+      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
+
+      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
+      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
+      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
+      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
+      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
+      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71
+    },
+
+    {
+       13,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
+      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
+      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
+      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
+
+      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
+      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
+      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
+      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
+      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
+      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
+      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
+      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
+      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72
+    },
+
+    {
+       13,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
+
+      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
+      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
+      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
+      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
+      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
+      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
+      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
+      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
+      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
+      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
+
+      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
+      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73
+    },
+
+    {
+       13,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
+      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
+      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
+      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
+      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
+      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
+      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
+      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
+
+      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
+      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
+      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
+      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
+      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74
+    },
+
+    {
+       13,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
+      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
+      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
+      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
+      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
+
+      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
+      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
+      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
+      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
+      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
+      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
+      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
+      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75
+    },
+
+    {
+       13,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
+      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
+
+      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
+      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
+      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
+      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
+      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
+      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
+      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
+      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
+      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
+      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
+
+      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76
+    },
+
+    {
+       13,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
+      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
+      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
+      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
+      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
+      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
+      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
+      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
+      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
+
+      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
+      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
+      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
+      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77
+    },
+
+    {
+       13,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
+      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
+      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
+      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
+      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
+      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
+
+      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
+      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
+      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
+      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
+      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
+      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
+      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78
+    },
+
+    {
+       13,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
+      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
+      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
+
+      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
+      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
+      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
+      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
+      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
+      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
+      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
+      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
+      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
+      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79
+
+    },
+
+    {
+       13,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
+      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
+      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
+      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
+      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
+      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
+      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
+      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
+      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
+      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
+
+      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
+      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
+      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80
+    },
+
+    {
+       13,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
+      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
+      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
+      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
+      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
+      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
+      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
+
+      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
+      -81,  -81,  -81,  -81,  -81,  187,  -81,  -81,  -81,  -81,
+      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
+      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
+      188,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
+      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81
+    },
+
+    {
+       13,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
+      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
+      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
+      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
+
+      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
+      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
+      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
+      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
+      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
+      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
+      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
+      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
+      -82,  189,  -82,  -82,  -82,  -82,  -82,  -82
+    },
+
+    {
+       13,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
+
+      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
+      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
+      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
+      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
+      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
+      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
+      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
+      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
+      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
+      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
+
+      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
+      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83
+    },
+
+    {
+       13,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
+      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
+      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
+      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
+      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
+      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
+      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
+      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
+
+      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
+      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
+      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
+      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
+      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84
+    },
+
+    {
+       13,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
+      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
+      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
+      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
+      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
+
+      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
+      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
+      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
+      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
+      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
+      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
+      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
+      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85
+    },
+
+    {
+       13,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
+      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
+
+      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
+      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
+      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
+      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
+      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
+      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
+      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
+      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
+      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
+      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
+
+      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86
+    },
+
+    {
+       13,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+
+      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+      -87,  -87,  190,  -87,  -87,  -87,  -87,  -87
+    },
+
+    {
+       13,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
+      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
+      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
+      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
+      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
+      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
+
+      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
+      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
+      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
+      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
+      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
+      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
+      -88,  191,  -88,  -88,  -88,  -88,  -88,  -88
+    },
+
+    {
+       13,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
+      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
+      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
+
+      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
+      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
+      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
+      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
+      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
+      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
+      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
+      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
+      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
+      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89
+
+    },
+
+    {
+       13,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
+      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
+      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
+      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
+      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
+      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
+      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
+      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
+      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
+      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
+
+      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
+      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
+      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90
+    },
+
+    {
+       13,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+
+      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+      -91,  -91,  -91,  -91,  192,  -91,  -91,  -91,  -91,  -91,
+      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91
+    },
+
+    {
+       13,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
+      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
+      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
+      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
+
+      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
+      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
+      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
+      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
+      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
+      -92,  -92,  -92,  -92,  -92,  -92,  -92,  193,  -92,  -92,
+      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
+      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
+      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92
+    },
+
+    {
+       13,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+
+      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+
+      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+      -93,  194,  -93,  -93,  -93,  -93,  -93,  -93
+    },
+
+    {
+       13,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
+      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
+      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
+      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
+      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
+      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
+      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
+      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
+
+      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
+      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
+      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
+      -94,  -94,  -94,  -94,  -94,  -94,  -94,  195,  -94,  -94,
+      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94
+    },
+
+    {
+       13,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
+      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
+      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
+      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
+      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
+
+      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
+      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
+      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
+      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
+      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
+      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
+      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
+      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95
+    },
+
+    {
+       13,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
+      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
+
+      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
+      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
+      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
+      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
+      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
+      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
+      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
+      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
+      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
+      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
+
+      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96
+    },
+
+    {
+       13,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
+      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
+      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
+      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
+      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
+      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
+      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
+      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
+      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
+
+      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  196,  -97,
+      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
+      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
+      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97
+    },
+
+    {
+       13,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
+      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
+      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
+      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
+      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
+      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
+
+      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
+      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
+      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
+      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
+      197,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
+      188,  -98,  -98,  -98,  198,  -98,  -98,  -98,  -98,  -98,
+      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98
+    },
+
+    {
+       13,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
+      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
+      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
+
+      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
+      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
+      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
+      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
+      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
+      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
+      -99,  -99,  -99,  -99,  -99,  -99,  -99,  199,  -99,  -99,
+      -99,  200,  -99,  -99,  -99,  201,  -99,  -99,  -99,  -99,
+      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
+      -99,  189,  -99,  -99,  -99,  -99,  -99,  -99
+
+    },
+
+    {
+       13, -100, -100, -100, -100, -100, -100, -100, -100, -100,
+     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
+     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
+     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
+     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
+     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
+     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
+     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
+     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
+     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
+
+      202, -100, -100, -100,  203, -100, -100, -100, -100, -100,
+     -100,  204, -100, -100, -100, -100,  205, -100, -100, -100,
+     -100, -100, -100, -100, -100, -100, -100, -100
+    },
+
+    {
+       13, -101, -101, -101, -101, -101, -101, -101, -101, -101,
+     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
+     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
+     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
+     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
+     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
+     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
+
+     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
+     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
+     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
+     -101,  206, -101, -101, -101, -101, -101, -101, -101, -101,
+     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
+     -101, -101, -101, -101, -101, -101, -101, -101
+    },
+
+    {
+       13, -102, -102, -102, -102, -102, -102, -102, -102, -102,
+     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
+     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
+     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
+
+     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
+     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
+     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
+     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
+     -102, -102, -102, -102, -102, -102,  207, -102, -102, -102,
+     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
+     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
+     -102, -102, -102, -102,  208, -102, -102, -102, -102, -102,
+     -102, -102, -102, -102, -102, -102, -102, -102
+    },
+
+    {
+       13, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+
+     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+
+     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+     -103, -103, -103, -103, -103, -103, -103, -103
+    },
+
+    {
+       13, -104, -104, -104, -104, -104, -104, -104, -104, -104,
+     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
+     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
+     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
+     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
+     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
+     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
+     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
+
+     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
+     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
+     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
+     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
+     -104, -104, -104, -104, -104, -104, -104, -104
+    },
+
+    {
+       13, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+
+     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+     -105, -105, -105, -105, -105, -105, -105, -105, -105,  209,
+     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+      210,  211, -105, -105, -105, -105, -105, -105
+    },
+
+    {
+       13, -106, -106, -106, -106, -106, -106, -106, -106, -106,
+     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
+
+     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
+     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
+     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
+     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
+     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
+     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
+     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
+     -106, -106, -106, -106, -106, -106, -106,  212, -106, -106,
+     -106, -106, -106, -106, -106,  213, -106, -106, -106, -106,
+     -106,  214, -106, -106, -106, -106, -106, -106, -106, -106,
+
+     -106, -106, -106, -106, -106, -106, -106, -106
+    },
+
+    {
+       13, -107, -107, -107, -107, -107, -107, -107, -107, -107,
+     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
+     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
+     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
+     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
+     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
+     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
+     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
+     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
+
+     -107, -107, -107, -107, -107, -107, -107, -107, -107,  215,
+     -107, -107, -107, -107,  216,  217, -107, -107, -107, -107,
+     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
+     -107, -107, -107, -107, -107, -107, -107, -107
+    },
+
+    {
+       13, -108, -108, -108, -108, -108, -108, -108, -108, -108,
+     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
+     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
+     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
+     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
+     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
+
+     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
+     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
+     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
+     -108, -108, -108, -108, -108, -108, -108,  218, -108, -108,
+     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
+     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
+     -108, -108, -108, -108, -108, -108, -108, -108
+    },
+
+    {
+       13, -109, -109, -109, -109, -109, -109, -109, -109, -109,
+     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
+     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
+
+     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
+     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
+     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
+     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
+     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
+     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
+     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
+     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
+     -109,  219, -109, -109,  220, -109, -109, -109, -109, -109,
+     -109, -109, -109, -109, -109, -109, -109, -109
+
+    },
+
+    {
+       13, -110, -110, -110, -110, -110, -110, -110, -110, -110,
+     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
+     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
+     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
+     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
+     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
+     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
+     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
+     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
+     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
+
+     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
+     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
+     -110, -110, -110, -110, -110, -110, -110, -110
+    },
+
+    {
+       13, -111, -111, -111, -111, -111, -111, -111, -111, -111,
+     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
+     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
+     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
+     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
+     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
+     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
+
+     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
+     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
+     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
+     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
+     -111,  221, -111, -111, -111, -111, -111, -111, -111, -111,
+     -111, -111, -111, -111, -111, -111, -111, -111
+    },
+
+    {
+       13, -112, -112, -112, -112, -112, -112, -112, -112, -112,
+     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
+     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
+     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
+
+     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
+     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
+     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
+     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
+     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
+     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
+     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
+     -112, -112, -112, -112,  222, -112, -112, -112, -112, -112,
+     -112, -112, -112, -112, -112, -112, -112, -112
+    },
+
+    {
+       13, -113, -113, -113, -113, -113, -113, -113, -113, -113,
+
+     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
+     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
+     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
+     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
+     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
+     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
+     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
+     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
+     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
+     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
+
+     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
+     -113, -113, -113, -113, -113, -113, -113, -113
+    },
+
+    {
+       13, -114, -114, -114, -114, -114, -114, -114, -114, -114,
+     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
+     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
+     -114, -114,  223, -114, -114, -114, -114, -114, -114, -114,
+      224, -114,  225,  226, -114,  226,  227,  228, -114,  229,
+      229,  229,  229,  229,  229,  229,  229,  229, -114, -114,
+     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
+     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
+
+     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
+     -114, -114, -114,  230,  231, -114, -114, -114, -114, -114,
+     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
+     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
+     -114, -114, -114, -114, -114, -114, -114, -114
+    },
+
+    {
+       13, -115, -115, -115, -115, -115, -115, -115, -115, -115,
+     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
+     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
+     -115, -115,  232, -115, -115, -115, -115, -115, -115, -115,
+     -115, -115, -115,  233, -115,  233,  234, -115,  235,  236,
+
+      236,  236,  236,  236,  236,  236,  236,  236, -115, -115,
+     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
+     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
+     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
+     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
+     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
+     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
+     -115, -115, -115, -115, -115, -115, -115, -115
+    },
+
+    {
+       13, -116, -116, -116, -116, -116, -116, -116, -116, -116,
+     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
+
+     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
+     -116, -116,  237, -116, -116, -116, -116, -116, -116, -116,
+     -116, -116,  231, -116, -116, -116, -116, -116, -116, -116,
+     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
+     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
+     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
+     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
+     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
+     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
+     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
+
+     -116, -116, -116, -116, -116, -116, -116, -116
+    },
+
+    {
+       13, -117, -117, -117, -117, -117, -117, -117, -117, -117,
+     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
+     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
+     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
+     -117, -117, -117, -117, -117, -117, -117, -117, -117,  229,
+      229,  229,  229,  229,  229,  229,  229,  229, -117, -117,
+     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
+     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
+     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
+
+     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
+     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
+     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
+     -117, -117, -117, -117, -117, -117, -117, -117
+    },
+
+    {
+       13, -118, -118, -118, -118, -118, -118, -118, -118, -118,
+     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
+     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
+     -118, -118,  237, -118, -118, -118, -118, -118, -118, -118,
+     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
+     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
+
+     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
+     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
+     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
+     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
+     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
+     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
+     -118, -118, -118, -118, -118, -118, -118, -118
+    },
+
+    {
+       13, -119, -119, -119, -119, -119, -119, -119, -119, -119,
+     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
+     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
+
+     -119, -119,  238, -119, -119, -119, -119, -119, -119, -119,
+     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
+     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
+     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
+     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
+     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
+     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
+     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
+     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
+     -119, -119, -119, -119, -119, -119, -119, -119
+
+    },
+
+    {
+       13, -120, -120, -120, -120, -120, -120, -120, -120, -120,
+     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
+     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
+     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
+     -120, -120, -120, -120, -120, -120, -120, -120,  239,  239,
+      239,  239,  239,  239,  239,  239,  239,  239, -120, -120,
+     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
+     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
+     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
+     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
+
+     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
+     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
+     -120, -120, -120, -120, -120, -120, -120, -120
+    },
+
+    {
+       13, -121, -121, -121, -121, -121, -121, -121, -121, -121,
+     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
+     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
+     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
+     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
+     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
+     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
+
+     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
+     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
+     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
+     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
+     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
+     -121, -121, -121, -121, -121, -121, -121, -121
+    },
+
+    {
+       13, -122, -122, -122, -122, -122, -122, -122, -122, -122,
+     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
+     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
+     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
+
+     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
+     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
+     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
+     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
+     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
+     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
+     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
+     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
+     -122, -122, -122, -122, -122, -122, -122, -122
+    },
+
+    {
+       13,  240,  240,  240,  240,  240,  240,  240,  240,  240,
+
+     -123,  240,  240,  240,  240,  240,  240,  240,  240,  240,
+      240,  240,  240,  240,  240,  240,  240,  240,  240,  240,
+      240,  240,  240,  240,  240,  240,  240,  240,  240,  240,
+      240,  240,  240,  240,  240,  240,  240,  240,  240,  240,
+      240,  240,  240,  240,  240,  240,  240,  240,  240,  240,
+      240,  240,  240,  240,  240,  240,  240,  240,  240,  240,
+      240,  240,  240,  240,  240,  240,  240,  240,  240,  240,
+      240,  240,  240,  240,  240,  240,  240,  240,  240,  240,
+      240,  240,  240,  240,  240,  240,  240,  240,  240,  240,
+      240,  240,  240,  240,  240,  240,  240,  240,  240,  240,
+
+      240,  240,  240,  240,  240,  240,  240,  240,  240,  240,
+      240,  240,  240,  240,  240,  240,  240,  240
+    },
+
+    {
+       13, -124, -124, -124, -124, -124, -124, -124, -124, -124,
+     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
+     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
+     -124, -124,  124, -124, -124, -124, -124, -124, -124, -124,
+     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
+     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
+     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
+     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
+
+     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
+     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
+     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
+     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
+     -124, -124, -124, -124, -124, -124, -124, -124
+    },
+
+    {
+       13, -125, -125, -125, -125, -125, -125, -125, -125, -125,
+     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
+     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
+     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
+     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
+
+     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
+     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
+     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
+     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
+     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
+     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
+     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
+     -125, -125, -125, -125, -125, -125, -125, -125
+    },
+
+    {
+       13, -126, -126, -126, -126, -126, -126, -126, -126, -126,
+     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
+
+     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
+     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
+     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
+     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
+     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
+     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
+     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
+     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
+     -126, -126, -126,  241, -126, -126, -126, -126, -126, -126,
+     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
+
+     -126, -126, -126, -126, -126, -126, -126, -126
+    },
+
+    {
+       13, -127, -127, -127, -127, -127, -127, -127, -127, -127,
+     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
+     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
+     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
+     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
+     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
+     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
+     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
+     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
+
+     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
+     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
+     -127, -127, -127, -127, -127, -127,  242, -127, -127, -127,
+     -127, -127, -127, -127, -127, -127, -127, -127
+    },
+
+    {
+       13, -128, -128, -128, -128, -128, -128, -128, -128, -128,
+     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
+     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
+     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
+     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
+     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
+
+     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
+     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
+     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
+     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
+     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
+     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
+     -128, -128, -128, -128, -128, -128, -128, -128
+    },
+
+    {
+       13, -129, -129, -129, -129, -129, -129, -129, -129, -129,
+     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
+     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
+
+     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
+     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
+     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
+     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
+     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
+     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
+     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
+     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
+     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
+     -129,  243, -129, -129, -129, -129, -129, -129
+
+    },
+
+    {
+       13, -130, -130, -130, -130, -130, -130, -130, -130, -130,
+     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
+     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
+     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
+     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
+     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
+     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
+     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
+     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
+     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
+
+     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
+     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
+     -130, -130, -130, -130, -130, -130, -130, -130
+    },
+
+    {
+       13, -131, -131, -131, -131, -131, -131, -131, -131, -131,
+     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
+     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
+     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
+     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
+     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
+     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
+
+     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
+     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
+     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
+     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
+     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
+     -131, -131, -131, -131, -131, -131, -131, -131
+    },
+
+    {
+       13, -132, -132, -132, -132, -132, -132, -132, -132, -132,
+     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
+     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
+     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
+
+     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
+     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
+     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
+     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
+     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
+     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
+     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
+     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
+     -132, -132,  130, -132, -132, -132, -132, -132
+    },
+
+    {
+       13, -133, -133, -133, -133, -133, -133, -133, -133, -133,
+
+     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
+     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
+     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
+     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
+     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
+     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
+     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
+     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
+     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
+     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
+
+     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
+     -133,  131, -133, -133, -133, -133, -133, -133
+    },
+
+    {
+       13, -134, -134, -134, -134, -134, -134, -134, -134, -134,
+     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
+     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
+     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
+     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
+     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
+     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
+     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
+
+     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
+     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
+     -134, -134, -134, -134,  244, -134, -134, -134, -134, -134,
+     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
+     -134, -134, -134, -134, -134, -134, -134, -134
+    },
+
+    {
+       13, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+
+     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+     -135, -135, -135, -135, -135, -135, -135,  130, -135, -135,
+     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+     -135, -135, -135, -135, -135, -135, -135, -135
+    },
+
+    {
+       13, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+
+     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+     -136, -136, -136, -136, -136, -136, -136, -136,  130, -136,
+     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+
+     -136, -136, -136, -136, -136, -136, -136, -136
+    },
+
+    {
+       13, -137, -137, -137, -137, -137, -137, -137, -137, -137,
+     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
+     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
+     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
+     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
+     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
+     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
+     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
+     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
+
+     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
+     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
+     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
+     -137, -137, -137, -137, -137, -137, -137, -137
+    },
+
+    {
+       13, -138, -138, -138, -138, -138, -138, -138, -138, -138,
+     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
+     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
+     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
+     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
+     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
+
+     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
+     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
+     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
+     -138, -138, -138, -138, -138, -138, -138,  245, -138, -138,
+     -138, -138, -138, -138, -138,  246, -138, -138, -138, -138,
+     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
+     -138,  243, -138, -138, -138, -138, -138, -138
+    },
+
+    {
+       13, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+
+     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+      128, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+     -139, -139, -139, -139, -139, -139, -139, -139
+
+    },
+
+    {
+       13, -140, -140, -140, -140, -140, -140, -140, -140, -140,
+     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
+     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
+     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
+     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
+     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
+     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
+     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
+     -140, -140, -140, -140, -140, -140,  131, -140, -140, -140,
+     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
+
+     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
+     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
+     -140, -140, -140, -140, -140, -140, -140, -140
+    },
+
+    {
+       13, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+
+     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+     -141, -141, -141, -141, -141, -141, -141, -141, -141,  130,
+     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+      130, -141, -141, -141, -141, -141, -141, -141
+    },
+
+    {
+       13, -142, -142, -142, -142, -142, -142, -142, -142, -142,
+     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
+     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
+     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
+
+     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
+     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
+     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
+     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
+     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
+     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
+     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
+     -142,  247, -142, -142, -142, -142, -142, -142, -142, -142,
+     -142, -142, -142, -142, -142, -142, -142, -142
+    },
+
+    {
+       13, -143, -143, -143, -143, -143, -143, -143, -143, -143,
+
+     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
+     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
+     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
+     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
+     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
+     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
+     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
+     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
+     -143, -143, -143, -143, -143, -143, -143, -143, -143,  137,
+     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
+
+     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
+     -143, -143, -143, -143, -143, -143, -143, -143
+    },
+
+    {
+       13, -144, -144, -144, -144, -144, -144, -144, -144, -144,
+     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
+     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
+     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
+     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
+     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
+     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
+     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
+
+     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
+     -144, -144, -144, -144, -144, -144, -144,  248, -144, -144,
+     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
+     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
+     -144, -144, -144, -144, -144, -144, -144, -144
+    },
+
+    {
+       13, -145, -145, -145, -145, -145, -145, -145, -145, -145,
+     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
+     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
+     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
+     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
+
+     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
+     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
+     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
+     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
+     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
+     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
+     -145, -145, -145, -145,  128, -145, -145, -145, -145, -145,
+     -145, -145, -145, -145, -145, -145, -145, -145
+    },
+
+    {
+       13, -146, -146, -146, -146, -146, -146, -146, -146, -146,
+     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
+
+     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
+     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
+     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
+     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
+     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
+     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
+     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
+     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
+     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
+     -146, -146, -146, -146,  137, -146, -146, -146, -146, -146,
+
+     -146, -146, -146, -146, -146, -146, -146, -146
+    },
+
+    {
+       13, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+
+     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+     -147, -147, -147, -147, -147, -147, -147, -147
+    },
+
+    {
+       13, -148, -148, -148, -148, -148, -148, -148, -148, -148,
+     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
+     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
+     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
+     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
+     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
+
+     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
+     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
+     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
+     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
+     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
+     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
+     -148, -148, -148, -148, -148, -148, -148, -148
+    },
+
+    {
+       13, -149, -149, -149, -149, -149, -149, -149, -149, -149,
+     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
+     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
+
+     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
+     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
+     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
+     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
+     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
+     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
+     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
+     -149, -149, -149, -149, -149, -149, -149, -149, -149,  147,
+     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
+     -149, -149, -149, -149, -149, -149, -149, -149
+
+    },
+
+    {
+       13, -150, -150, -150, -150, -150, -150, -150, -150, -150,
+     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
+     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
+     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
+     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
+     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
+     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
+     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
+     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
+     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
+
+     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
+     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
+     -150, -150, -150, -150, -150, -150, -150, -150
+    },
+
+    {
+       13, -151, -151, -151, -151, -151, -151, -151, -151, -151,
+     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
+     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
+     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
+     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
+     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
+     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
+
+     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
+     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
+     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
+     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
+     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
+     -151, -151, -151, -151, -151, -151, -151, -151
+    },
+
+    {
+       13, -152, -152, -152, -152, -152, -152, -152, -152, -152,
+     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
+     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
+     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
+
+     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
+     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
+     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
+     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
+     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
+     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
+     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
+      125, -152, -152, -152, -152, -152, -152, -152, -152, -152,
+     -152, -152, -152, -152, -152, -152, -152, -152
+    },
+
+    {
+       13, -153, -153, -153, -153, -153, -153, -153, -153, -153,
+
+     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
+     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
+     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
+     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
+     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
+     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
+     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
+     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
+     -153, -153, -153, -153, -153, -153, -153,  245, -153, -153,
+     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
+
+     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
+     -153, -153, -153, -153, -153, -153, -153, -153
+    },
+
+    {
+       13, -154, -154, -154, -154, -154, -154, -154, -154, -154,
+     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
+     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
+     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
+     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
+     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
+     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
+     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
+
+     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
+     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
+     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
+     -154, -154, -154, -154, -154, -154, -154,  163, -154, -154,
+     -154, -154, -154, -154, -154, -154, -154, -154
+    },
+
+    {
+       13, -155, -155, -155, -155, -155, -155, -155, -155, -155,
+     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
+     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
+     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
+     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
+
+     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
+     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
+     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
+     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
+     -155, -155, -155, -155, -155, -155, -155,  249, -155, -155,
+     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
+     -155,  247, -155, -155, -155, -155, -155, -155, -155, -155,
+     -155, -155, -155, -155, -155, -155, -155, -155
+    },
+
+    {
+       13, -156, -156, -156, -156, -156, -156, -156, -156, -156,
+     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
+
+     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
+     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
+     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
+     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
+     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
+     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
+     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
+     -156, -156, -156, -156, -156, -156, -156,  248, -156,  250,
+     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
+     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
+
+     -156, -156, -156, -156, -156, -156, -156, -156
+    },
+
+    {
+       13, -157, -157, -157, -157, -157, -157, -157, -157, -157,
+     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
+     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
+     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
+     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
+     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
+     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
+     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
+     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
+
+     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
+     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
+     -157, -157, -157, -157,  251, -157, -157, -157, -157, -157,
+     -157, -157, -157, -157, -157, -157, -157, -157
+    },
+
+    {
+       13, -158, -158, -158, -158, -158, -158, -158, -158, -158,
+     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
+     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
+     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
+     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
+     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
+
+     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
+     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
+     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
+     -158, -158, -158, -158, -158, -158, -158,  252, -158, -158,
+     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
+     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
+     -158, -158, -158, -158, -158, -158, -158, -158
+    },
+
+    {
+       13, -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, -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,
+      163, -159, -159, -159, -159, -159,  253, -159, -159, -159,
+     -159, -159, -159, -159, -159, -159, -159, -159
+
+    },
+
+    {
+       13, -160, -160, -160, -160, -160, -160, -160, -160, -160,
+     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
+     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
+     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
+     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
+     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
+     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
+     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
+     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
+     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
+
+     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
+     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
+     -160, -160, -160, -160, -160, -160, -160, -160
+    },
+
+    {
+       13, -161, -161, -161, -161, -161, -161, -161, -161, -161,
+     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
+     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
+     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
+     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
+     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
+     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
+
+     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
+     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
+     -161, -161, -161, -161, -161, -161, -161,  254, -161, -161,
+     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
+     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
+     -161, -161, -161, -161, -161, -161, -161, -161
+    },
+
+    {
+       13, -162, -162, -162, -162, -162, -162, -162, -162, -162,
+     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
+     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
+     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
+
+     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
+     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
+     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
+     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
+     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
+     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
+     -162, -162, -162, -162,  244, -162, -162, -162, -162, -162,
+     -162, -162, -162, -162, -162, -162, -162,  255, -162, -162,
+     -162, -162, -162, -162, -162, -162, -162, -162
+    },
+
+    {
+       13, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+
+     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+
+     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+     -163, -163, -163, -163, -163, -163, -163, -163
+    },
+
+    {
+       13, -164, -164, -164, -164, -164, -164, -164, -164, -164,
+     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
+     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
+     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
+     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
+     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
+     -164, -164, -164, -164, -164,  128,  129,  130, -164, -164,
+      130,  131,  132, -164,  133,  128, -164, -164,  130,  134,
+
+      135, -164,  131,  130,  130, -164,  130,  136, -164, -164,
+     -164, -164, -164, -164, -164, -164, -164,  137,  138,  139,
+     -164,  140, -164,  128, -164, -164, -164, -164,  141,  142,
+     -164,  134,  143, -164,  144,  145, -164, -164, -164, -164,
+     -164,  146, -164, -164, -164, -164, -164, -164
+    },
+
+    {
+       13, -165, -165, -165, -165, -165, -165, -165, -165, -165,
+     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
+     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
+     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
+     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
+
+     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
+     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
+     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
+     -165, -165, -165, -165, -165, -165,  131, -165, -165, -165,
+     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
+     -165, -165, -165,  151, -165, -165, -165, -165, -165, -165,
+     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
+     -165, -165, -165, -165, -165, -165, -165, -165
+    },
+
+    {
+       13, -166, -166, -166, -166, -166, -166, -166, -166, -166,
+     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
+
+     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
+     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
+     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
+     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
+     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
+     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
+     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
+     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
+     -166, -166, -166,  151, -166, -166, -166, -166, -166, -166,
+     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
+
+     -166, -166, -166, -166, -166, -166, -166, -166
+    },
+
+    {
+       13, -167, -167, -167, -167, -167, -167, -167, -167, -167,
+     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
+     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
+     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
+     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
+     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
+     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
+     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
+     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
+
+     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
+     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
+     -167, -167, -167, -167,  125, -167, -167, -167, -167, -167,
+     -167, -167, -167, -167, -167, -167, -167, -167
+    },
+
+    {
+       13, -168, -168, -168, -168, -168, -168, -168, -168, -168,
+     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
+     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
+     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
+     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
+     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
+
+     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
+     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
+     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
+     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
+     -168, -168, -168,  148, -168, -168, -168, -168, -168, -168,
+     -168, -168, -168, -168, -168,  151, -168, -168, -168, -168,
+     -168, -168, -168, -168, -168, -168, -168, -168
+    },
+
+    {
+       13, -169, -169, -169, -169, -169, -169, -169, -169, -169,
+     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
+     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
+
+     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
+     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
+     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
+     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
+     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
+     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
+     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
+     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
+      151, -169, -169, -169, -169, -169, -169, -169, -169, -169,
+     -169, -169, -169, -169, -169, -169, -169, -169
+
+    },
+
+    {
+       13, -170, -170, -170, -170, -170, -170, -170, -170, -170,
+     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
+     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
+     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
+     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
+     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
+     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
+     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
+     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
+     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
+
+     -170, -170, -170, -170,  244, -170, -170, -170,  160, -170,
+     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
+     -170, -170, -170, -170, -170, -170, -170, -170
+    },
+
+    {
+       13, -171, -171, -171, -171, -171, -171, -171, -171, -171,
+     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
+     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
+     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
+     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
+     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
+     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
+
+     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
+     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
+     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
+      128, -171, -171, -171, -171, -171, -171, -171, -171, -171,
+     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
+     -171, -171, -171, -171, -171, -171, -171, -171
+    },
+
+    {
+       13, -172, -172, -172, -172, -172, -172, -172, -172, -172,
+     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
+     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
+     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
+
+     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
+     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
+     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
+     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
+     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
+     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
+     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
+     -172,  256, -172, -172, -172, -172, -172, -172, -172, -172,
+     -172, -172, -172, -172, -172, -172, -172, -172
+    },
+
+    {
+       13, -173, -173, -173, -173, -173, -173, -173, -173, -173,
+
+     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
+     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
+     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
+     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
+     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
+     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
+     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
+     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
+     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
+     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
+
+     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
+      257, -173, -173, -173, -173, -173, -173, -173
+    },
+
+    {
+       13, -174, -174, -174, -174, -174, -174, -174, -174, -174,
+     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
+     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
+     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
+     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
+     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
+     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
+     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
+
+     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
+     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
+      160, -174, -174, -174, -174, -174, -174, -174, -174, -174,
+     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
+     -174, -174, -174, -174, -174, -174, -174, -174
+    },
+
+    {
+       13, -175, -175, -175, -175, -175, -175, -175, -175, -175,
+     -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
+     -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
+     -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
+     -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
+
+     -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
+     -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
+     -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
+     -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
+     -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
+     -175, -175, -175, -175, -175, -175, -175, -175,  258, -175,
+     -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
+     -175, -175, -175, -175, -175, -175, -175, -175
+    },
+
+    {
+       13, -176, -176, -176, -176, -176, -176, -176, -176, -176,
+     -176, -176, -176, -176, -176, -176, -176, -176, -176, -176,
+
+     -176, -176, -176, -176, -176, -176, -176, -176, -176, -176,
+     -176, -176, -176, -176, -176, -176, -176, -176, -176, -176,
+     -176, -176, -176, -176, -176, -176, -176, -176, -176, -176,
+     -176, -176, -176, -176, -176, -176, -176, -176, -176, -176,
+     -176, -176, -176, -176, -176, -176, -176, -176, -176, -176,
+     -176, -176, -176, -176, -176, -176, -176, -176, -176, -176,
+     -176, -176, -176, -176, -176, -176, -176, -176, -176, -176,
+     -176, -176, -176, -176, -176, -176, -176, -176, -176, -176,
+     -176, -176, -176, -176, -176, -176, -176, -176, -176, -176,
+     -176, -176, -176, -176,  259, -176, -176, -176, -176, -176,
+
+     -176, -176, -176, -176, -176, -176, -176, -176
+    },
+
+    {
+       13, -177, -177, -177, -177, -177, -177, -177, -177, -177,
+     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
+     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
+     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
+     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
+     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
+     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
+     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
+     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
+
+     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
+     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
+     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
+      260, -177, -177, -177, -177, -177, -177, -177
+    },
+
+    {
+       13, -178, -178, -178, -178, -178, -178, -178, -178, -178,
+     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
+     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
+     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
+     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
+     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
+
+     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
+     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
+     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
+     -178, -178, -178, -178, -178, -178, -178,  248, -178, -178,
+     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
+     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
+     -178, -178, -178, -178, -178, -178, -178, -178
+    },
+
+    {
+       13, -179, -179, -179, -179, -179, -179, -179, -179, -179,
+     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
+     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
+
+     -179, -179,  179, -179, -179, -179, -179, -179, -179, -179,
+     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
+     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
+     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
+     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
+     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
+     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
+     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
+     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
+     -179, -179, -179, -179, -179, -179, -179, -179
+
+    },
+
+    {
+       13, -180, -180, -180, -180, -180, -180, -180, -180, -180,
+     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
+     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
+     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
+     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
+     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
+     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
+     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
+     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
+     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
+
+     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
+     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
+     -180, -180, -180, -180, -180, -180, -180, -180
+    },
+
+    {
+       13, -181, -181, -181, -181, -181, -181, -181, -181, -181,
+     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
+     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
+     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
+     -181, -181, -181, -181, -181, -181, -181, -181,  261,  261,
+      261,  261,  261,  261,  261,  261,  261,  261, -181, -181,
+     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
+
+     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
+     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
+     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
+     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
+     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
+     -181, -181, -181, -181, -181, -181, -181, -181
+    },
+
+    {
+       13, -182, -182, -182, -182, -182, -182, -182, -182, -182,
+     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
+     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
+     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
+
+     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
+     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
+     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
+     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
+     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
+     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
+     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
+     -182, -182,  262, -182, -182, -182, -182, -182, -182, -182,
+     -182, -182, -182, -182, -182, -182, -182, -182
+    },
+
+    {
+       13, -183, -183, -183, -183, -183, -183, -183, -183, -183,
+
+     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
+     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
+     -183, -183,  263, -183, -183, -183, -183, -183, -183, -183,
+      264, -183, -183, -183, -183, -183, -183, -183, -183, -183,
+     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
+     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
+     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
+     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
+     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
+     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
+
+     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
+     -183, -183, -183, -183, -183, -183, -183, -183
+    },
+
+    {
+       13, -184, -184, -184, -184, -184, -184, -184, -184, -184,
+     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
+     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
+     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
+     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
+     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
+     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
+     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
+
+     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
+     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
+     -184, -184, -184,  265, -184, -184, -184, -184, -184, -184,
+     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
+     -184, -184, -184, -184, -184, -184, -184, -184
+    },
+
+    {
+       13,  185,  185,  185,  185,  185,  185,  185,  185,  185,
+      185,  185,  185,  185,  185,  185,  185,  185,  185,  185,
+      185,  185,  185,  185,  185,  185,  185,  185,  185,  185,
+      185,  185,  185,  185,  185,  185,  185,  185,  185,  185,
+     -185, -185,  185,  185,  185,  185,  185,  185,  185,  185,
+
+      185,  185,  185,  185,  185,  185,  185,  185,  185,  185,
+      185,  185,  185,  185,  185,  185,  185,  185,  185,  185,
+      185,  185,  185,  185,  185,  185,  185,  185,  185,  185,
+      185,  185,  185,  185,  185,  185,  185,  185,  185,  185,
+      185,  185,  185,  185,  185,  185,  185,  185,  185,  185,
+      185,  185,  185,  185,  185,  185,  185,  185,  185,  185,
+      185,  185,  185,  185,  185,  185,  185,  185,  185,  185,
+      185,  185,  185,  185,  185,  185,  185,  185
+    },
+
+    {
+       13, -186, -186, -186, -186, -186, -186, -186, -186, -186,
+     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
+
+     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
+     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
+     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
+     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
+     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
+     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
+     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
+     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
+     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
+     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
+
+     -186, -186, -186, -186, -186, -186, -186, -186
+    },
+
+    {
+       13, -187, -187, -187, -187, -187, -187, -187, -187, -187,
+     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
+     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
+     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
+     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
+     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
+     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
+     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
+     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
+
+     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
+     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
+     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
+     -187, -187, -187, -187, -187, -187, -187, -187
+    },
+
+    {
+       13, -188, -188, -188, -188, -188, -188, -188, -188, -188,
+     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
+     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
+     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
+     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
+     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
+
+     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
+     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
+     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
+     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
+     -188, -188, -188,  266, -188, -188, -188, -188, -188, -188,
+     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
+     -188, -188, -188, -188, -188, -188, -188, -188
+    },
+
+    {
+       13, -189, -189, -189, -189, -189, -189, -189, -189, -189,
+     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
+     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
+
+     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
+     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
+     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
+     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
+     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
+     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
+     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
+     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
+     -189, -189, -189, -189, -189, -189,  267, -189, -189, -189,
+     -189, -189, -189, -189, -189, -189, -189, -189
+
+    },
+
+    {
+       13, -190, -190, -190, -190, -190, -190, -190, -190, -190,
+     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
+     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
+     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
+     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
+     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
+     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
+     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
+     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
+     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
+
+     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
+     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
+     -190, -190, -190, -190, -190, -190, -190, -190
+    },
+
+    {
+       13, -191, -191, -191, -191, -191, -191, -191, -191, -191,
+     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
+     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
+     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
+     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
+     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
+     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
+
+     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
+     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
+     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
+     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
+     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
+     -191, -191, -191, -191, -191, -191, -191, -191
+    },
+
+    {
+       13, -192, -192, -192, -192, -192, -192, -192, -192, -192,
+     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
+     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
+     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
+
+     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
+     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
+     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
+     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
+     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
+     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
+     -192, -192, -192, -192, -192, -192, -192, -192, -192,  268,
+     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
+     -192, -192, -192, -192, -192, -192, -192, -192
+    },
+
+    {
+       13, -193, -193, -193, -193, -193, -193, -193, -193, -193,
+
+     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
+     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
+     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
+     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
+     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
+     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
+     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
+     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
+     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
+     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
+
+     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
+     -193, -193, -193, -193, -193, -193, -193, -193
+    },
+
+    {
+       13, -194, -194, -194, -194, -194, -194, -194, -194, -194,
+     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
+     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
+     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
+     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
+     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
+     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
+     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
+
+     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
+     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
+     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
+     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
+     -194, -194, -194, -194, -194, -194, -194, -194
+    },
+
+    {
+       13, -195, -195, -195, -195, -195, -195, -195, -195, -195,
+     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
+     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
+     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
+     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
+
+     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
+     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
+     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
+     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
+     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
+     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
+      269, -195, -195, -195, -195, -195, -195, -195, -195, -195,
+     -195, -195, -195, -195, -195, -195, -195, -195
+    },
+
+    {
+       13, -196, -196, -196, -196, -196, -196, -196, -196, -196,
+     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
+
+     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
+     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
+     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
+     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
+     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
+     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
+     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
+     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
+     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
+     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
+
+     -196, -196, -196, -196, -196, -196, -196, -196
+    },
+
+    {
+       13, -197, -197, -197, -197, -197, -197, -197, -197, -197,
+     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
+     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
+     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
+     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
+     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
+     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
+     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
+     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
+
+     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
+     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
+     -197, -197, -197, -197, -197, -197, -197,  270, -197, -197,
+     -197, -197, -197, -197, -197, -197, -197, -197
+    },
+
+    {
+       13, -198, -198, -198, -198, -198, -198, -198, -198, -198,
+     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
+     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
+     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
+     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
+     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
+
+     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
+     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
+     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
+     -198, -198, -198, -198, -198, -198, -198, -198, -198,  271,
+     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
+     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
+     -198, -198, -198, -198, -198, -198, -198, -198
+    },
+
+    {
+       13, -199, -199, -199, -199, -199, -199, -199, -199, -199,
+     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
+     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
+
+     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
+     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
+     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
+     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
+     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
+     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
+     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
+     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
+     -199, -199, -199, -199,  272, -199, -199, -199, -199, -199,
+     -199, -199, -199, -199, -199, -199, -199, -199
+
+    },
+
+    {
+       13, -200, -200, -200, -200, -200, -200, -200, -200, -200,
+     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
+     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
+     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
+     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
+     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
+     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
+     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
+     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
+     -200, -200, -200, -200, -200, -200, -200,  273, -200, -200,
+
+     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
+     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
+     -200, -200, -200, -200, -200, -200, -200, -200
+    },
+
+    {
+       13, -201, -201, -201, -201, -201, -201, -201, -201, -201,
+     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
+     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
+     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
+     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
+     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
+     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
+
+     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
+     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
+     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
+     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
+      274, -201, -201, -201, -201, -201,  275, -201, -201, -201,
+     -201, -201, -201, -201, -201, -201, -201, -201
+    },
+
+    {
+       13, -202, -202, -202, -202, -202, -202, -202, -202, -202,
+     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
+     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
+     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
+
+     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
+     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
+     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
+     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
+     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
+     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
+     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
+     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
+     -202, -202, -202, -202, -202, -202, -202, -202
+    },
+
+    {
+       13, -203, -203, -203, -203, -203, -203, -203, -203, -203,
+
+     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
+     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
+     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
+     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
+     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
+     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
+     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
+     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
+     -203, -203, -203, -203, -203, -203, -203,  276, -203, -203,
+     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
+
+     -203, -203, -203, -203, -203, -203, -203, -203, -203, -203,
+     -203, -203, -203, -203, -203, -203, -203, -203
+    },
+
+    {
+       13, -204, -204, -204, -204, -204, -204, -204, -204, -204,
+     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
+     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
+     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
+     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
+     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
+     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
+     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
+
+     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
+     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
+     -204, -204, -204, -204, -204, -204, -204, -204, -204, -204,
+     -204, -204, -204, -204, -204, -204, -204,  277, -204, -204,
+     -204, -204, -204, -204, -204, -204, -204, -204
+    },
+
+    {
+       13, -205, -205, -205, -205, -205, -205, -205, -205, -205,
+     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
+     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
+     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
+     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
+
+     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
+     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
+     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
+     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
+     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
+     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
+     -205, -205, -205, -205, -205, -205, -205, -205, -205, -205,
+     -205, -205, -205, -205, -205, -205, -205, -205
+    },
+
+    {
+       13, -206, -206, -206, -206, -206, -206, -206, -206, -206,
+     -206, -206, -206, -206, -206, -206, -206, -206, -206, -206,
+
+     -206, -206, -206, -206, -206, -206, -206, -206, -206, -206,
+     -206, -206, -206, -206, -206, -206, -206, -206, -206, -206,
+     -206, -206, -206, -206, -206, -206, -206, -206, -206, -206,
+     -206, -206, -206, -206, -206, -206, -206, -206, -206, -206,
+     -206, -206, -206, -206, -206, -206, -206, -206, -206, -206,
+     -206, -206, -206, -206, -206, -206, -206, -206, -206, -206,
+     -206, -206, -206, -206, -206, -206, -206, -206, -206, -206,
+     -206, -206, -206, -206, -206, -206, -206, -206, -206, -206,
+     -206, -206, -206,  278, -206, -206, -206, -206, -206, -206,
+     -206, -206, -206, -206, -206, -206, -206, -206, -206, -206,
+
+     -206, -206, -206, -206, -206, -206, -206, -206
+    },
+
+    {
+       13, -207, -207, -207, -207, -207, -207, -207, -207, -207,
+     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
+     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
+     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
+     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
+     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
+     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
+     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
+     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
+
+     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
+     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
+     -207, -207, -207, -207, -207, -207, -207, -207, -207, -207,
+     -207, -207, -207, -207, -207, -207, -207, -207
+    },
+
+    {
+       13, -208, -208, -208, -208, -208, -208, -208, -208, -208,
+     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
+     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
+     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
+     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
+     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
+
+     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
+     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
+     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
+     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
+     -208, -208, -208,  279, -208, -208, -208, -208, -208, -208,
+     -208, -208, -208, -208, -208, -208, -208, -208, -208, -208,
+     -208, -208, -208, -208, -208, -208, -208, -208
+    },
+
+    {
+       13, -209, -209, -209, -209, -209, -209, -209, -209, -209,
+     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
+     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
+
+     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
+     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
+     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
+     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
+     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
+     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
+     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
+     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
+     -209, -209, -209, -209, -209, -209, -209, -209, -209, -209,
+     -209, -209, -209, -209, -209, -209, -209, -209
+
+    },
+
+    {
+       13, -210, -210, -210, -210, -210, -210, -210, -210, -210,
+     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
+     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
+     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
+     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
+     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
+     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
+     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
+     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
+     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
+
+     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
+     -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
+     -210, -210, -210, -210, -210, -210, -210, -210
+    },
+
+    {
+       13, -211, -211, -211, -211, -211, -211, -211, -211, -211,
+     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
+     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
+     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
+     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
+     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
+     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
+
+     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
+     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
+     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
+     -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
+     -211, -211, -211, -211,  280, -211, -211, -211, -211, -211,
+     -211, -211, -211, -211, -211, -211, -211, -211
+    },
+
+    {
+       13, -212, -212, -212, -212, -212, -212, -212, -212, -212,
+     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
+     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
+     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
+
+     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
+     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
+     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
+     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
+     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
+     -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
+     -212, -212, -212,  281, -212, -212, -212, -212, -212, -212,
+     -212, -212, -212, -212, -212,  282, -212, -212, -212, -212,
+     -212, -212, -212, -212, -212, -212, -212, -212
+    },
+
+    {
+       13, -213, -213, -213, -213, -213, -213, -213, -213, -213,
+
+     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
+     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
+     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
+     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
+     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
+     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
+     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
+     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
+     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
+     -213, -213, -213, -213, -213, -213, -213, -213, -213, -213,
+
+      283, -213, -213, -213, -213, -213, -213, -213, -213, -213,
+     -213, -213, -213, -213, -213, -213, -213, -213
+    },
+
+    {
+       13, -214, -214, -214, -214, -214, -214, -214, -214, -214,
+     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
+     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
+     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
+     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
+     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
+     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
+     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
+
+     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
+     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
+     -214, -214, -214, -214, -214, -214, -214, -214,  284, -214,
+     -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
+     -214, -214, -214, -214, -214, -214, -214, -214
+    },
+
+    {
+       13, -215, -215, -215, -215, -215, -215, -215, -215, -215,
+     -215, -215, -215, -215, -215, -215, -215, -215, -215, -215,
+     -215, -215, -215, -215, -215, -215, -215, -215, -215, -215,
+     -215, -215, -215, -215, -215, -215, -215, -215, -215, -215,
+     -215, -215, -215, -215, -215, -215, -215, -215, -215, -215,
+
+     -215, -215, -215, -215, -215, -215, -215, -215, -215, -215,
+     -215, -215, -215, -215, -215, -215, -215, -215, -215, -215,
+     -215, -215, -215, -215, -215, -215, -215, -215, -215, -215,
+     -215, -215, -215, -215, -215, -215, -215, -215, -215, -215,
+     -215, -215, -215, -215, -215, -215, -215, -215, -215, -215,
+     -215, -215, -215, -215, -215, -215, -215, -215, -215, -215,
+     -215, -215, -215, -215, -215, -215, -215, -215, -215, -215,
+     -215, -215, -215, -215, -215, -215, -215, -215
+    },
+
+    {
+       13, -216, -216, -216, -216, -216, -216, -216, -216, -216,
+     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
+
+     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
+     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
+     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
+     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
+     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
+     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
+     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
+     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
+     -216, -216, -216, -216, -216, -216, -216, -216, -216, -216,
+     -216,  285, -216, -216, -216, -216, -216, -216, -216, -216,
+
+     -216, -216, -216, -216, -216, -216, -216, -216
+    },
+
+    {
+       13, -217, -217, -217, -217, -217, -217, -217, -217, -217,
+     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
+     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
+     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
+     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
+     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
+     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
+     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
+     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
+
+     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
+     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
+     -217, -217, -217, -217, -217, -217, -217, -217, -217, -217,
+      286, -217, -217, -217, -217, -217, -217, -217
+    },
+
+    {
+       13, -218, -218, -218, -218, -218, -218, -218, -218, -218,
+     -218, -218, -218, -218, -218, -218, -218, -218, -218, -218,
+     -218, -218, -218, -218, -218, -218, -218, -218, -218, -218,
+     -218, -218, -218, -218, -218, -218, -218, -218, -218, -218,
+     -218, -218, -218, -218, -218, -218, -218, -218, -218, -218,
+     -218, -218, -218, -218, -218, -218, -218, -218, -218, -218,
+
+     -218, -218, -218, -218, -218, -218, -218, -218, -218, -218,
+     -218, -218, -218, -218, -218, -218, -218, -218, -218, -218,
+     -218, -218, -218, -218, -218, -218, -218, -218, -218, -218,
+     -218, -218, -218, -218, -218, -218, -218, -218, -218, -218,
+      287, -218, -218, -218, -218, -218, -218, -218, -218, -218,
+     -218, -218, -218, -218, -218, -218, -218, -218, -218, -218,
+     -218, -218, -218, -218, -218, -218, -218, -218
+    },
+
+    {
+       13, -219, -219, -219, -219, -219, -219, -219, -219, -219,
+     -219, -219, -219, -219, -219, -219, -219, -219, -219, -219,
+     -219, -219, -219, -219, -219, -219, -219, -219, -219, -219,
+
+     -219, -219, -219, -219, -219, -219, -219, -219, -219, -219,
+     -219, -219, -219, -219, -219, -219, -219, -219, -219, -219,
+     -219, -219, -219, -219, -219, -219, -219, -219, -219, -219,
+     -219, -219, -219, -219, -219, -219, -219, -219, -219, -219,
+     -219, -219, -219, -219, -219, -219, -219, -219, -219, -219,
+     -219, -219, -219, -219, -219, -219, -219, -219, -219, -219,
+     -219, -219, -219, -219, -219, -219, -219, -219, -219, -219,
+     -219, -219, -219, -219, -219, -219, -219, -219,  288, -219,
+     -219, -219, -219, -219, -219, -219, -219, -219, -219, -219,
+     -219, -219, -219, -219, -219, -219, -219, -219
+
+    },
+
+    {
+       13, -220, -220, -220, -220, -220, -220, -220, -220, -220,
+     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
+     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
+     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
+     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
+     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
+     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
+     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
+     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
+     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
+
+     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
+     -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
+     -220, -220, -220, -220, -220, -220, -220, -220
+    },
+
+    {
+       13, -221, -221, -221, -221, -221, -221, -221, -221, -221,
+     -221, -221, -221, -221, -221, -221, -221, -221, -221, -221,
+     -221, -221, -221, -221, -221, -221, -221, -221, -221, -221,
+     -221, -221, -221, -221, -221, -221, -221, -221, -221, -221,
+     -221, -221, -221, -221, -221, -221, -221, -221, -221, -221,
+     -221, -221, -221, -221, -221, -221, -221, -221, -221, -221,
+     -221, -221, -221, -221, -221, -221, -221, -221, -221, -221,
+
+     -221, -221, -221, -221, -221, -221, -221, -221, -221, -221,
+     -221, -221, -221, -221, -221, -221, -221, -221, -221, -221,
+     -221, -221, -221, -221, -221, -221, -221, -221, -221, -221,
+     -221, -221, -221, -221, -221, -221, -221, -221, -221, -221,
+     -221, -221, -221, -221, -221, -221, -221, -221, -221, -221,
+      289, -221, -221, -221, -221, -221, -221, -221
+    },
+
+    {
+       13, -222, -222, -222, -222, -222, -222, -222, -222, -222,
+     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
+     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
+     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
+
+     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
+     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
+     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
+     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
+     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
+     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
+     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
+     -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
+     -222, -222, -222, -222, -222, -222, -222, -222
+    },
+
+    {
+       13, -223, -223, -223, -223, -223, -223, -223, -223, -223,
+
+     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
+     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
+     -223, -223,  223, -223, -223, -223, -223, -223, -223, -223,
+      224, -223,  225,  226, -223,  226,  227,  228, -223,  229,
+      229,  229,  229,  229,  229,  229,  229,  229, -223, -223,
+     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
+     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
+     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
+     -223, -223, -223,  230,  231, -223, -223, -223, -223, -223,
+     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
+
+     -223, -223, -223, -223, -223, -223, -223, -223, -223, -223,
+     -223, -223, -223, -223, -223, -223, -223, -223
+    },
+
+    {
+       13, -224, -224, -224, -224, -224, -224, -224, -224, -224,
+     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
+     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
+     -224, -224,  232, -224, -224, -224, -224, -224, -224, -224,
+     -224, -224, -224,  233, -224,  233,  234, -224,  235,  236,
+      236,  236,  236,  236,  236,  236,  236,  236, -224, -224,
+     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
+     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
+
+     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
+     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
+     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
+     -224, -224, -224, -224, -224, -224, -224, -224, -224, -224,
+     -224, -224, -224, -224, -224, -224, -224, -224
+    },
+
+    {
+       13, -225, -225, -225, -225, -225, -225, -225, -225, -225,
+     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
+     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
+     -225, -225,  237, -225, -225, -225, -225, -225, -225, -225,
+     -225, -225,  231, -225, -225, -225, -225, -225, -225, -225,
+
+     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
+     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
+     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
+     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
+     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
+     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
+     -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
+     -225, -225, -225, -225, -225, -225, -225, -225
+    },
+
+    {
+       13, -226, -226, -226, -226, -226, -226, -226, -226, -226,
+     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
+
+     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
+     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
+     -226, -226, -226, -226, -226, -226, -226, -226, -226,  229,
+      229,  229,  229,  229,  229,  229,  229,  229, -226, -226,
+     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
+     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
+     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
+     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
+     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
+     -226, -226, -226, -226, -226, -226, -226, -226, -226, -226,
+
+     -226, -226, -226, -226, -226, -226, -226, -226
+    },
+
+    {
+       13, -227, -227, -227, -227, -227, -227, -227, -227, -227,
+     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
+     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
+     -227, -227,  237, -227, -227, -227, -227, -227, -227, -227,
+     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
+     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
+     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
+     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
+     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
+
+     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
+     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
+     -227, -227, -227, -227, -227, -227, -227, -227, -227, -227,
+     -227, -227, -227, -227, -227, -227, -227, -227
+    },
+
+    {
+       13, -228, -228, -228, -228, -228, -228, -228, -228, -228,
+     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
+     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
+     -228, -228,  238, -228, -228, -228, -228, -228, -228, -228,
+     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
+     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
+
+     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
+     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
+     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
+     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
+     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
+     -228, -228, -228, -228, -228, -228, -228, -228, -228, -228,
+     -228, -228, -228, -228, -228, -228, -228, -228
+    },
+
+    {
+       13, -229, -229, -229, -229, -229, -229, -229, -229, -229,
+     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
+     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
+
+     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
+     -229, -229, -229, -229, -229, -229, -229, -229,  239,  239,
+      239,  239,  239,  239,  239,  239,  239,  239, -229, -229,
+     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
+     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
+     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
+     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
+     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
+     -229, -229, -229, -229, -229, -229, -229, -229, -229, -229,
+     -229, -229, -229, -229, -229, -229, -229, -229
+
+    },
+
+    {
+       13, -230, -230, -230, -230, -230, -230, -230, -230, -230,
+     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
+     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
+     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
+     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
+     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
+     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
+     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
+     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
+     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
+
+     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
+     -230, -230, -230, -230, -230, -230, -230, -230, -230, -230,
+     -230, -230, -230, -230, -230, -230, -230, -230
+    },
+
+    {
+       13, -231, -231, -231, -231, -231, -231, -231, -231, -231,
+     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
+     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
+     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
+     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
+     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
+     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
+
+     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
+     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
+     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
+     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
+     -231, -231, -231, -231, -231, -231, -231, -231, -231, -231,
+     -231, -231, -231, -231, -231, -231, -231, -231
+    },
+
+    {
+       13, -232, -232, -232, -232, -232, -232, -232, -232, -232,
+     -232, -232, -232, -232, -232, -232, -232, -232, -232, -232,
+     -232, -232, -232, -232, -232, -232, -232, -232, -232, -232,
+     -232, -232,  232, -232, -232, -232, -232, -232, -232, -232,
+
+     -232, -232, -232,  233, -232,  233,  234, -232,  235,  236,
+      236,  236,  236,  236,  236,  236,  236,  236, -232, -232,
+     -232, -232, -232, -232, -232, -232, -232, -232, -232, -232,
+     -232, -232, -232, -232, -232, -232, -232, -232, -232, -232,
+     -232, -232, -232, -232, -232, -232, -232, -232, -232, -232,
+     -232, -232, -232, -232, -232, -232, -232, -232, -232, -232,
+     -232, -232, -232, -232, -232, -232, -232, -232, -232, -232,
+     -232, -232, -232, -232, -232, -232, -232, -232, -232, -232,
+     -232, -232, -232, -232, -232, -232, -232, -232
+    },
+
+    {
+       13, -233, -233, -233, -233, -233, -233, -233, -233, -233,
+
+     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
+     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
+     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
+     -233, -233, -233, -233, -233, -233,  234, -233,  235,  236,
+      236,  236,  236,  236,  236,  236,  236,  236, -233, -233,
+     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
+     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
+     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
+     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
+     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
+
+     -233, -233, -233, -233, -233, -233, -233, -233, -233, -233,
+     -233, -233, -233, -233, -233, -233, -233, -233
+    },
+
+    {
+       13, -234, -234, -234, -234, -234, -234, -234, -234, -234,
+     -234, -234, -234, -234, -234, -234, -234, -234, -234, -234,
+     -234, -234, -234, -234, -234, -234, -234, -234, -234, -234,
+     -234, -234, -234, -234, -234, -234, -234, -234, -234, -234,
+     -234, -234, -234, -234, -234, -234, -234, -234,  290,  290,
+      290,  290,  290,  290,  290,  290,  290,  290, -234, -234,
+     -234, -234, -234, -234, -234, -234, -234, -234, -234, -234,
+     -234, -234, -234, -234, -234, -234, -234, -234, -234, -234,
+
+     -234, -234, -234, -234, -234, -234, -234, -234, -234, -234,
+     -234, -234, -234, -234, -234, -234, -234, -234, -234, -234,
+     -234, -234, -234, -234, -234, -234, -234, -234, -234, -234,
+     -234, -234, -234, -234, -234, -234, -234, -234, -234, -234,
+     -234, -234, -234, -234, -234, -234, -234, -234
+    },
+
+    {
+       13, -235, -235, -235, -235, -235, -235, -235, -235, -235,
+     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
+     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
+     -235, -235,  291, -235, -235, -235, -235, -235, -235, -235,
+     -235,  292, -235, -235, -235, -235,  293, -235,  294,  294,
+
+      294,  294,  294,  294,  294,  294,  294,  294, -235, -235,
+     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
+     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
+     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
+     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
+     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
+     -235, -235, -235, -235, -235, -235, -235, -235, -235, -235,
+     -235, -235, -235, -235, -235, -235, -235, -235
+    },
+
+    {
+       13, -236, -236, -236, -236, -236, -236, -236, -236, -236,
+     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
+
+     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
+     -236, -236,  295, -236, -236, -236, -236, -236, -236, -236,
+     -236,  296, -236, -236, -236, -236,  293,  297,  298,  298,
+      298,  298,  298,  298,  298,  298,  298,  298, -236, -236,
+     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
+     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
+     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
+     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
+     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
+     -236, -236, -236, -236, -236, -236, -236, -236, -236, -236,
+
+     -236, -236, -236, -236, -236, -236, -236, -236
+    },
+
+    {
+       13, -237, -237, -237, -237, -237, -237, -237, -237, -237,
+     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
+     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
+     -237, -237,  237, -237, -237, -237, -237, -237, -237, -237,
+     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
+     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
+     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
+     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
+     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
+
+     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
+     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
+     -237, -237, -237, -237, -237, -237, -237, -237, -237, -237,
+     -237, -237, -237, -237, -237, -237, -237, -237
+    },
+
+    {
+       13, -238, -238, -238, -238, -238, -238, -238, -238, -238,
+     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
+     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
+     -238, -238,  238, -238, -238, -238, -238, -238, -238, -238,
+     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
+     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
+
+     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
+     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
+     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
+     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
+     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
+     -238, -238, -238, -238, -238, -238, -238, -238, -238, -238,
+     -238, -238, -238, -238, -238, -238, -238, -238
+    },
+
+    {
+       13, -239, -239, -239, -239, -239, -239, -239, -239, -239,
+     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
+     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
+
+     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
+     -239, -239, -239, -239, -239, -239, -239, -239,  239,  239,
+      239,  239,  239,  239,  239,  239,  239,  239, -239, -239,
+     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
+     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
+     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
+     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
+     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
+     -239, -239, -239, -239, -239, -239, -239, -239, -239, -239,
+     -239, -239, -239, -239, -239, -239, -239, -239
+
+    },
+
+    {
+       13,  240,  240,  240,  240,  240,  240,  240,  240,  240,
+     -240,  240,  240,  240,  240,  240,  240,  240,  240,  240,
+      240,  240,  240,  240,  240,  240,  240,  240,  240,  240,
+      240,  240,  240,  240,  240,  240,  240,  240,  240,  240,
+      240,  240,  240,  240,  240,  240,  240,  240,  240,  240,
+      240,  240,  240,  240,  240,  240,  240,  240,  240,  240,
+      240,  240,  240,  240,  240,  240,  240,  240,  240,  240,
+      240,  240,  240,  240,  240,  240,  240,  240,  240,  240,
+      240,  240,  240,  240,  240,  240,  240,  240,  240,  240,
+      240,  240,  240,  240,  240,  240,  240,  240,  240,  240,
+
+      240,  240,  240,  240,  240,  240,  240,  240,  240,  240,
+      240,  240,  240,  240,  240,  240,  240,  240,  240,  240,
+      240,  240,  240,  240,  240,  240,  240,  240
+    },
+
+    {
+       13, -241, -241, -241, -241, -241, -241, -241, -241, -241,
+     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
+     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
+     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
+     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
+     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
+     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
+
+     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
+     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
+     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
+     -241, -241, -241, -241, -241, -241, -241, -241, -241, -241,
+     -241, -241, -241, -241, -241,  299, -241, -241, -241, -241,
+     -241, -241, -241, -241, -241, -241, -241, -241
+    },
+
+    {
+       13, -242, -242, -242, -242, -242, -242, -242, -242, -242,
+     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
+     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
+     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
+
+     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
+     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
+     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
+     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
+     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
+     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
+     -242,  253, -242, -242, -242, -242, -242, -242, -242, -242,
+     -242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
+     -242, -242, -242, -242, -242, -242, -242, -242
+    },
+
+    {
+       13, -243, -243, -243, -243, -243, -243, -243, -243, -243,
+
+     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
+     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
+     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
+     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
+     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
+     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
+     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
+     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
+     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
+     -243, -243, -243, -243, -243, -243, -243, -243, -243, -243,
+
+     -243, -243, -243, -243, -243, -243,  300, -243, -243, -243,
+     -243, -243, -243, -243, -243, -243, -243, -243
+    },
+
+    {
+       13, -244, -244, -244, -244, -244, -244, -244, -244, -244,
+     -244, -244, -244, -244, -244, -244, -244, -244, -244, -244,
+     -244, -244, -244, -244, -244, -244, -244, -244, -244, -244,
+     -244, -244, -244, -244, -244, -244, -244, -244, -244, -244,
+     -244, -244, -244, -244, -244, -244, -244, -244, -244, -244,
+     -244, -244, -244, -244, -244, -244, -244, -244, -244, -244,
+     -244, -244, -244, -244, -244, -244, -244, -244, -244, -244,
+     -244, -244, -244, -244, -244, -244, -244, -244, -244, -244,
+
+     -244, -244, -244, -244, -244, -244, -244, -244, -244, -244,
+     -244, -244, -244, -244, -244, -244, -244, -244, -244, -244,
+     -244, -244, -244, -244, -244, -244, -244, -244, -244,  130,
+     -244, -244, -244, -244, -244, -244, -244, -244, -244, -244,
+     -244, -244, -244, -244, -244, -244, -244, -244
+    },
+
+    {
+       13, -245, -245, -245, -245, -245, -245, -245, -245, -245,
+     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
+     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
+     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
+     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
+
+     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
+     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
+     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
+     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
+     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
+     -245, -245, -245, -245, -245, -245, -245, -245, -245, -245,
+     -245, -245, -245, -245,  301, -245, -245, -245, -245, -245,
+     -245, -245, -245, -245, -245, -245, -245, -245
+    },
+
+    {
+       13, -246, -246, -246, -246, -246, -246, -246, -246, -246,
+     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
+
+     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
+     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
+     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
+     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
+     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
+     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
+     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
+     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
+     -246, -246, -246, -246, -246, -246, -246, -246, -246, -246,
+     -246, -246, -246, -246, -246, -246,  137, -246, -246, -246,
+
+     -246, -246, -246, -246, -246, -246, -246, -246
+    },
+
+    {
+       13, -247, -247, -247, -247, -247, -247, -247, -247, -247,
+     -247, -247, -247, -247, -247, -247, -247, -247, -247, -247,
+     -247, -247, -247, -247, -247, -247, -247, -247, -247, -247,
+     -247, -247, -247, -247, -247, -247, -247, -247, -247, -247,
+     -247, -247, -247, -247, -247, -247, -247, -247, -247, -247,
+     -247, -247, -247, -247, -247, -247, -247, -247, -247, -247,
+     -247, -247, -247, -247, -247, -247, -247, -247, -247, -247,
+     -247, -247, -247, -247, -247, -247, -247, -247, -247, -247,
+     -247, -247, -247, -247, -247, -247, -247, -247, -247, -247,
+
+     -247, -247, -247, -247, -247, -247, -247, -247, -247, -247,
+     -247, -247, -247, -247, -247, -247, -247, -247,  128, -247,
+     -247, -247, -247, -247, -247, -247, -247, -247, -247, -247,
+     -247, -247, -247, -247, -247, -247, -247, -247
+    },
+
+    {
+       13, -248, -248, -248, -248, -248, -248, -248, -248, -248,
+     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
+     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
+     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
+     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
+     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
+
+     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
+     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
+     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
+     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
+      128, -248, -248, -248, -248, -248, -248, -248, -248, -248,
+     -248, -248, -248, -248, -248, -248, -248, -248, -248, -248,
+     -248, -248, -248, -248, -248, -248, -248, -248
+    },
+
+    {
+       13, -249, -249, -249, -249, -249, -249, -249, -249, -249,
+     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
+     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
+
+     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
+     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
+     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
+     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
+     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
+     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
+     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
+     -249, -249, -249,  302, -249, -249, -249, -249, -249, -249,
+     -249, -249, -249, -249, -249, -249, -249, -249, -249, -249,
+     -249, -249, -249, -249, -249, -249, -249, -249
+
+    },
+
+    {
+       13, -250, -250, -250, -250, -250, -250, -250, -250, -250,
+     -250, -250, -250, -250, -250, -250, -250, -250, -250, -250,
+     -250, -250, -250, -250, -250, -250, -250, -250, -250, -250,
+     -250, -250, -250, -250, -250, -250, -250, -250, -250, -250,
+     -250, -250, -250, -250, -250, -250, -250, -250, -250, -250,
+     -250, -250, -250, -250, -250, -250, -250, -250, -250, -250,
+     -250, -250, -250, -250, -250, -250, -250, -250, -250, -250,
+     -250, -250, -250, -250, -250, -250, -250, -250, -250, -250,
+     -250, -250, -250, -250, -250, -250, -250, -250, -250, -250,
+     -250, -250, -250, -250, -250, -250, -250, -250, -250, -250,
+
+     -250, -250, -250, -250, -250, -250, -250, -250, -250,  303,
+     -250, -250, -250, -250, -250,  304, -250, -250, -250, -250,
+     -250, -250, -250, -250, -250, -250, -250, -250
+    },
+
+    {
+       13, -251, -251, -251, -251, -251, -251, -251, -251, -251,
+     -251, -251, -251, -251, -251, -251, -251, -251, -251, -251,
+     -251, -251, -251, -251, -251, -251, -251, -251, -251, -251,
+     -251, -251, -251, -251, -251, -251, -251, -251, -251, -251,
+     -251, -251, -251, -251, -251, -251, -251, -251, -251, -251,
+     -251, -251, -251, -251, -251, -251, -251, -251, -251, -251,
+     -251, -251, -251, -251, -251, -251, -251, -251, -251, -251,
+
+     -251, -251, -251, -251, -251, -251, -251, -251, -251, -251,
+     -251, -251, -251, -251, -251, -251, -251, -251, -251, -251,
+     -251, -251, -251, -251, -251, -251, -251, -251, -251, -251,
+     -251, -251, -251, -251, -251, -251, -251, -251, -251, -251,
+      148, -251, -251, -251, -251, -251, -251, -251, -251, -251,
+     -251, -251, -251, -251, -251, -251, -251, -251
+    },
+
+    {
+       13, -252, -252, -252, -252, -252, -252, -252, -252, -252,
+     -252, -252, -252, -252, -252, -252, -252, -252, -252, -252,
+     -252, -252, -252, -252, -252, -252, -252, -252, -252, -252,
+     -252, -252, -252, -252, -252, -252, -252, -252, -252, -252,
+
+     -252, -252, -252, -252, -252, -252, -252, -252, -252, -252,
+     -252, -252, -252, -252, -252, -252, -252, -252, -252, -252,
+     -252, -252, -252, -252, -252, -252, -252, -252, -252, -252,
+     -252, -252, -252, -252, -252, -252, -252, -252, -252, -252,
+     -252, -252, -252, -252, -252, -252, -252, -252, -252, -252,
+     -252, -252, -252, -252, -252, -252, -252, -252, -252, -252,
+     -252, -252, -252, -252, -252, -252, -252, -252, -252,  125,
+     -252, -252, -252, -252, -252, -252, -252, -252, -252, -252,
+     -252, -252, -252, -252, -252, -252, -252, -252
+    },
+
+    {
+       13, -253, -253, -253, -253, -253, -253, -253, -253, -253,
+
+     -253, -253, -253, -253, -253, -253, -253, -253, -253, -253,
+     -253, -253, -253, -253, -253, -253, -253, -253, -253, -253,
+     -253, -253, -253, -253, -253, -253, -253, -253, -253, -253,
+     -253, -253, -253, -253, -253, -253, -253, -253, -253, -253,
+     -253, -253, -253, -253, -253, -253, -253, -253, -253, -253,
+     -253, -253, -253, -253, -253, -253, -253, -253, -253, -253,
+     -253, -253, -253, -253, -253, -253, -253, -253, -253, -253,
+     -253, -253, -253, -253, -253, -253, -253, -253, -253, -253,
+     -253, -253, -253, -253, -253, -253, -253, -253, -253, -253,
+     -253, -253, -253, -253, -253, -253, -253, -253, -253, -253,
+
+     -253, -253, -253, -253, -253, -253, -253, -253, -253, -253,
+     -253, -253, -253, -253, -253, -253, -253, -253
+    },
+
+    {
+       13, -254, -254, -254, -254, -254, -254, -254, -254, -254,
+     -254, -254, -254, -254, -254, -254, -254, -254, -254, -254,
+     -254, -254, -254, -254, -254, -254, -254, -254, -254, -254,
+     -254, -254, -254, -254, -254, -254, -254, -254, -254, -254,
+     -254, -254, -254, -254, -254, -254, -254, -254, -254, -254,
+     -254, -254, -254, -254, -254, -254, -254, -254, -254, -254,
+     -254, -254, -254, -254, -254, -254, -254, -254, -254, -254,
+     -254, -254, -254, -254, -254, -254, -254, -254, -254, -254,
+
+     -254, -254, -254, -254, -254, -254, -254, -254, -254, -254,
+     -254, -254, -254, -254, -254, -254, -254, -254, -254, -254,
+     -254, -254, -254, -254, -254, -254, -254, -254, -254, -254,
+      163, -254, -254, -254, -254, -254, -254, -254, -254, -254,
+     -254, -254, -254, -254, -254, -254, -254, -254
+    },
+
+    {
+       13, -255, -255, -255, -255, -255, -255, -255, -255, -255,
+     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
+     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
+     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
+     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
+
+     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
+     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
+     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
+     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
+     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
+     -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
+      305, -255, -255, -255, -255, -255, -255, -255, -255, -255,
+     -255, -255, -255, -255, -255, -255, -255, -255
+    },
+
+    {
+       13, -256, -256, -256, -256, -256, -256, -256, -256, -256,
+     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
+
+     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
+     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
+     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
+     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
+     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
+     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
+     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
+     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
+     -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
+     -256, -256, -256, -256, -256, -256,  306, -256, -256, -256,
+
+     -256, -256, -256, -256, -256, -256, -256, -256
+    },
+
+    {
+       13, -257, -257, -257, -257, -257, -257, -257, -257, -257,
+     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
+     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
+     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
+     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
+     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
+     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
+     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
+     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
+
+     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
+     -257,  307, -257, -257, -257, -257, -257, -257, -257, -257,
+     -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
+     -257, -257, -257, -257, -257, -257, -257, -257
+    },
+
+    {
+       13, -258, -258, -258, -258, -258, -258, -258, -258, -258,
+     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
+     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
+     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
+     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
+     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
+
+     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
+     -258, -258, -258, -258, -258, -258,  308,  309, -258, -258,
+     -258, -258,  310, -258, -258, -258, -258, -258, -258, -258,
+     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
+     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
+     -258, -258, -258, -258, -258, -258, -258, -258, -258, -258,
+     -258, -258, -258, -258, -258, -258, -258, -258
+    },
+
+    {
+       13, -259, -259, -259, -259, -259, -259, -259, -259, -259,
+     -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
+     -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
+
+     -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
+     -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
+     -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
+     -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
+     -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
+     -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
+     -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
+     -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
+     -259, -259, -259, -259, -259, -259,  311, -259, -259, -259,
+     -259, -259, -259, -259, -259, -259, -259, -259
+
+    },
+
+    {
+       13, -260, -260, -260, -260, -260, -260, -260, -260, -260,
+     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
+     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
+     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
+     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
+     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
+     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
+     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
+     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
+     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
+
+     -260,  312, -260, -260, -260, -260, -260, -260, -260, -260,
+     -260, -260, -260, -260, -260, -260, -260, -260, -260, -260,
+     -260, -260, -260, -260, -260, -260, -260, -260
+    },
+
+    {
+       13, -261, -261, -261, -261, -261, -261, -261, -261, -261,
+     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
+     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
+     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
+     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
+     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
+     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
+
+     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
+     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
+     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
+     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
+     -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
+     -261, -261, -261, -261, -261, -261, -261, -261
+    },
+
+    {
+       13, -262, -262, -262, -262, -262, -262, -262, -262, -262,
+     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
+     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
+     -262, -262,  313, -262, -262, -262, -262, -262, -262, -262,
+
+      314, -262, -262, -262, -262, -262, -262, -262, -262, -262,
+     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
+     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
+     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
+     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
+     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
+     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
+     -262, -262, -262, -262, -262, -262, -262, -262, -262, -262,
+     -262, -262, -262, -262, -262, -262, -262, -262
+    },
+
+    {
+       13, -263, -263, -263, -263, -263, -263, -263, -263, -263,
+
+     -263, -263, -263, -263, -263, -263, -263, -263, -263, -263,
+     -263, -263, -263, -263, -263, -263, -263, -263, -263, -263,
+     -263, -263,  263, -263, -263, -263, -263, -263, -263, -263,
+      264, -263, -263, -263, -263, -263, -263, -263, -263, -263,
+     -263, -263, -263, -263, -263, -263, -263, -263, -263, -263,
+     -263, -263, -263, -263, -263, -263, -263, -263, -263, -263,
+     -263, -263, -263, -263, -263, -263, -263, -263, -263, -263,
+     -263, -263, -263, -263, -263, -263, -263, -263, -263, -263,
+     -263, -263, -263, -263, -263, -263, -263, -263, -263, -263,
+     -263, -263, -263, -263, -263, -263, -263, -263, -263, -263,
+
+     -263, -263, -263, -263, -263, -263, -263, -263, -263, -263,
+     -263, -263, -263, -263, -263, -263, -263, -263
+    },
+
+    {
+       13, -264, -264, -264, -264, -264, -264, -264, -264, -264,
+     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
+     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
+     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
+     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
+     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
+     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
+     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
+
+     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
+     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
+     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
+     -264, -264, -264, -264, -264, -264, -264, -264, -264, -264,
+     -264, -264, -264, -264, -264, -264, -264, -264
+    },
+
+    {
+       13, -265, -265, -265, -265, -265, -265, -265, -265, -265,
+     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
+     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
+     -265, -265,  315, -265, -265, -265, -265, -265, -265, -265,
+      316, -265, -265, -265, -265, -265, -265, -265, -265, -265,
+
+     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
+     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
+     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
+     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
+     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
+     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
+     -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
+     -265, -265, -265, -265, -265, -265, -265, -265
+    },
+
+    {
+       13, -266, -266, -266, -266, -266, -266, -266, -266, -266,
+     -266, -266, -266, -266, -266, -266, -266, -266, -266, -266,
+
+     -266, -266, -266, -266, -266, -266, -266, -266, -266, -266,
+     -266, -266, -266, -266, -266, -266, -266, -266, -266, -266,
+     -266, -266, -266, -266, -266, -266, -266, -266, -266, -266,
+     -266, -266, -266, -266, -266, -266, -266, -266, -266, -266,
+     -266, -266, -266, -266, -266, -266, -266, -266, -266, -266,
+     -266, -266, -266, -266, -266, -266, -266, -266, -266, -266,
+     -266, -266, -266, -266, -266, -266, -266, -266, -266, -266,
+     -266, -266, -266, -266, -266, -266, -266, -266, -266, -266,
+     -266, -266, -266, -266, -266, -266, -266, -266, -266, -266,
+     -266, -266, -266, -266, -266,  317, -266, -266, -266, -266,
+
+     -266, -266, -266, -266, -266, -266, -266, -266
+    },
+
+    {
+       13, -267, -267, -267, -267, -267, -267, -267, -267, -267,
+     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
+     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
+     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
+     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
+     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
+     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
+     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
+     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
+
+     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
+     -267,  318, -267, -267, -267, -267, -267, -267, -267, -267,
+     -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
+     -267, -267, -267, -267, -267, -267, -267, -267
+    },
+
+    {
+       13, -268, -268, -268, -268, -268, -268, -268, -268, -268,
+     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
+     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
+     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
+     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
+     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
+
+     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
+     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
+     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
+     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
+     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
+     -268, -268, -268, -268, -268, -268, -268, -268, -268, -268,
+     -268, -268, -268, -268, -268, -268, -268, -268
+    },
+
+    {
+       13, -269, -269, -269, -269, -269, -269, -269, -269, -269,
+     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
+     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
+
+     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
+     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
+     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
+     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
+     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
+     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
+     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
+     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
+     -269, -269, -269, -269, -269, -269, -269, -269, -269, -269,
+     -269, -269, -269, -269, -269, -269, -269, -269
+
+    },
+
+    {
+       13, -270, -270, -270, -270, -270, -270, -270, -270, -270,
+     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
+     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
+     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
+     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
+     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
+     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
+     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
+     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
+     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
+
+     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
+     -270, -270, -270, -270, -270, -270, -270, -270, -270, -270,
+     -270, -270, -270, -270, -270, -270, -270, -270
+    },
+
+    {
+       13, -271, -271, -271, -271, -271, -271, -271, -271, -271,
+     -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
+     -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
+     -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
+     -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
+     -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
+     -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
+
+     -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
+     -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
+     -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
+     -271, -271, -271, -271, -271, -271, -271, -271, -271,  319,
+     -271, -271, -271, -271, -271,  320, -271, -271, -271, -271,
+     -271, -271, -271, -271, -271, -271, -271, -271
+    },
+
+    {
+       13, -272, -272, -272, -272, -272, -272, -272, -272, -272,
+     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
+     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
+     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
+
+     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
+     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
+     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
+     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
+     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
+     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
+     -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
+      321, -272, -272, -272, -272, -272, -272, -272, -272, -272,
+     -272, -272, -272, -272, -272, -272, -272, -272
+    },
+
+    {
+       13, -273, -273, -273, -273, -273, -273, -273, -273, -273,
+
+     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
+     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
+     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
+     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
+     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
+     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
+     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
+     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
+     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
+     -273, -273, -273, -273, -273, -273, -273, -273, -273,  322,
+
+     -273, -273, -273, -273, -273, -273, -273, -273, -273, -273,
+     -273, -273, -273, -273, -273, -273, -273, -273
+    },
+
+    {
+       13, -274, -274, -274, -274, -274, -274, -274, -274, -274,
+     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
+     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
+     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
+     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
+     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
+     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
+     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
+
+     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
+     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
+     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
+     -274, -274, -274, -274, -274, -274, -274, -274, -274, -274,
+     -274, -274, -274, -274, -274, -274, -274, -274
+    },
+
+    {
+       13, -275, -275, -275, -275, -275, -275, -275, -275, -275,
+     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
+     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
+     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
+     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
+
+     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
+     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
+     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
+     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
+     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
+     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
+     -275, -275, -275, -275, -275, -275, -275, -275, -275, -275,
+     -275, -275, -275, -275, -275, -275, -275, -275
+    },
+
+    {
+       13, -276, -276, -276, -276, -276, -276, -276, -276, -276,
+     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
+
+     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
+     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
+     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
+     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
+     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
+     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
+     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
+     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
+     -276, -276, -276, -276, -276, -276, -276, -276, -276, -276,
+      323, -276, -276, -276, -276, -276, -276, -276, -276, -276,
+
+     -276, -276, -276, -276, -276, -276, -276, -276
+    },
+
+    {
+       13, -277, -277, -277, -277, -277, -277, -277, -277, -277,
+     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
+     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
+     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
+     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
+     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
+     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
+     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
+     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
+
+     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
+     -277, -277, -277, -277, -277, -277, -277, -277, -277, -277,
+      324, -277, -277, -277, -277, -277, -277, -277, -277, -277,
+     -277, -277, -277, -277, -277, -277, -277, -277
+    },
+
+    {
+       13, -278, -278, -278, -278, -278, -278, -278, -278, -278,
+     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
+     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
+     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
+     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
+     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
+
+     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
+     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
+     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
+     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
+     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
+     -278, -278, -278, -278, -278, -278, -278, -278, -278, -278,
+     -278, -278, -278, -278, -278, -278, -278, -278
+    },
+
+    {
+       13, -279, -279, -279, -279, -279, -279, -279, -279, -279,
+     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
+     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
+
+     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
+     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
+     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
+     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
+     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
+     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
+     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
+     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
+     -279, -279, -279, -279, -279, -279, -279, -279, -279, -279,
+     -279, -279, -279, -279, -279, -279, -279, -279
+
+    },
+
+    {
+       13, -280, -280, -280, -280, -280, -280, -280, -280, -280,
+     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
+     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
+     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
+     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
+     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
+     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
+     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
+     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
+     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
+
+     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
+     -280, -280, -280, -280, -280, -280, -280, -280, -280, -280,
+     -280, -280, -280, -280, -280, -280, -280, -280
+    },
+
+    {
+       13, -281, -281, -281, -281, -281, -281, -281, -281, -281,
+     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
+     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
+     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
+     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
+     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
+     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
+
+     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
+     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
+     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
+     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
+     -281, -281, -281, -281, -281, -281, -281, -281, -281, -281,
+     -281, -281, -281, -281, -281, -281, -281, -281
+    },
+
+    {
+       13, -282, -282, -282, -282, -282, -282, -282, -282, -282,
+     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
+     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
+     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
+
+     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
+     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
+     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
+     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
+     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
+     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
+     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
+     -282, -282, -282, -282, -282, -282, -282, -282, -282, -282,
+     -282, -282, -282, -282, -282, -282, -282, -282
+    },
+
+    {
+       13, -283, -283, -283, -283, -283, -283, -283, -283, -283,
+
+     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
+     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
+     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
+     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
+     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
+     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
+     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
+     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
+     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
+     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
+
+     -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
+     -283, -283, -283, -283, -283, -283, -283, -283
+    },
+
+    {
+       13, -284, -284, -284, -284, -284, -284, -284, -284, -284,
+     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
+     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
+     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
+     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
+     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
+     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
+     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
+
+     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
+     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
+     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
+     -284, -284, -284, -284, -284, -284, -284, -284, -284, -284,
+     -284, -284, -284, -284, -284, -284, -284, -284
+    },
+
+    {
+       13, -285, -285, -285, -285, -285, -285, -285, -285, -285,
+     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
+     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
+     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
+     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
+
+     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
+     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
+     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
+     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
+     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
+     -285, -285, -285, -285, -285, -285, -285, -285, -285, -285,
+     -285, -285, -285, -285, -285, -285,  325, -285, -285, -285,
+     -285, -285, -285, -285, -285, -285, -285, -285
+    },
+
+    {
+       13, -286, -286, -286, -286, -286, -286, -286, -286, -286,
+     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
+
+     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
+     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
+     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
+     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
+     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
+     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
+     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
+     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
+     -286,  326, -286, -286, -286, -286, -286, -286, -286, -286,
+     -286, -286, -286, -286, -286, -286, -286, -286, -286, -286,
+
+     -286, -286, -286, -286, -286, -286, -286, -286
+    },
+
+    {
+       13, -287, -287, -287, -287, -287, -287, -287, -287, -287,
+     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
+     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
+     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
+     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
+     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
+     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
+     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
+     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
+
+     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
+     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
+     -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
+     -287, -287, -287, -287, -287, -287, -287, -287
+    },
+
+    {
+       13, -288, -288, -288, -288, -288, -288, -288, -288, -288,
+     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
+     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
+     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
+     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
+     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
+
+     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
+     -288, -288, -288, -288, -288, -288,  327,  328, -288, -288,
+     -288, -288,  329, -288, -288, -288, -288, -288, -288, -288,
+     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
+     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
+     -288, -288, -288, -288, -288, -288, -288, -288, -288, -288,
+     -288, -288, -288, -288, -288, -288, -288, -288
+    },
+
+    {
+       13, -289, -289, -289, -289, -289, -289, -289, -289, -289,
+     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
+     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
+
+     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
+     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
+     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
+     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
+     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
+     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
+     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
+     -289,  330, -289, -289, -289, -289, -289, -289, -289, -289,
+     -289, -289, -289, -289, -289, -289, -289, -289, -289, -289,
+     -289, -289, -289, -289, -289, -289, -289, -289
+
+    },
+
+    {
+       13, -290, -290, -290, -290, -290, -290, -290, -290, -290,
+     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
+     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
+     -290, -290,  291, -290, -290, -290, -290, -290, -290, -290,
+     -290,  292, -290, -290, -290, -290, -290, -290,  290,  290,
+      290,  290,  290,  290,  290,  290,  290,  290, -290, -290,
+     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
+     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
+     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
+     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
+
+     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
+     -290, -290, -290, -290, -290, -290, -290, -290, -290, -290,
+     -290, -290, -290, -290, -290, -290, -290, -290
+    },
+
+    {
+       13, -291, -291, -291, -291, -291, -291, -291, -291, -291,
+     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
+     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
+     -291, -291,  291, -291, -291, -291, -291, -291, -291, -291,
+     -291,  292, -291, -291, -291, -291, -291, -291, -291, -291,
+     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
+     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
+
+     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
+     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
+     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
+     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
+     -291, -291, -291, -291, -291, -291, -291, -291, -291, -291,
+     -291, -291, -291, -291, -291, -291, -291, -291
+    },
+
+    {
+       13, -292, -292, -292, -292, -292, -292, -292, -292, -292,
+     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
+     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
+     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
+
+     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
+     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
+     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
+     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
+     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
+     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
+     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
+     -292, -292, -292, -292, -292, -292, -292, -292, -292, -292,
+     -292, -292, -292, -292, -292, -292, -292, -292
+    },
+
+    {
+       13, -293, -293, -293, -293, -293, -293, -293, -293, -293,
+
+     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
+     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
+     -293, -293,  291, -293, -293, -293, -293, -293, -293, -293,
+     -293,  292, -293, -293, -293, -293, -293, -293,  331,  331,
+      331,  331,  331,  331,  331,  331,  331,  331, -293, -293,
+     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
+     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
+     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
+     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
+     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
+
+     -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
+     -293, -293, -293, -293, -293, -293, -293, -293
+    },
+
+    {
+       13, -294, -294, -294, -294, -294, -294, -294, -294, -294,
+     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
+     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
+     -294, -294,  291, -294, -294, -294, -294, -294, -294, -294,
+     -294,  292, -294, -294, -294, -294,  293, -294,  294,  294,
+      294,  294,  294,  294,  294,  294,  294,  294, -294, -294,
+     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
+     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
+
+     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
+     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
+     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
+     -294, -294, -294, -294, -294, -294, -294, -294, -294, -294,
+     -294, -294, -294, -294, -294, -294, -294, -294
+    },
+
+    {
+       13, -295, -295, -295, -295, -295, -295, -295, -295, -295,
+     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
+     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
+     -295, -295,  295, -295, -295, -295, -295, -295, -295, -295,
+     -295,  296, -295, -295, -295, -295, -295, -295, -295, -295,
+
+     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
+     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
+     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
+     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
+     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
+     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
+     -295, -295, -295, -295, -295, -295, -295, -295, -295, -295,
+     -295, -295, -295, -295, -295, -295, -295, -295
+    },
+
+    {
+       13, -296, -296, -296, -296, -296, -296, -296, -296, -296,
+     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
+
+     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
+     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
+     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
+     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
+     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
+     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
+     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
+     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
+     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
+     -296, -296, -296, -296, -296, -296, -296, -296, -296, -296,
+
+     -296, -296, -296, -296, -296, -296, -296, -296
+    },
+
+    {
+       13, -297, -297, -297, -297, -297, -297, -297, -297, -297,
+     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
+     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
+     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
+     -297, -297, -297, -297, -297, -297, -297, -297, -297,  332,
+      332,  332,  332,  332,  332,  332,  332,  332, -297, -297,
+     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
+     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
+     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
+
+     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
+     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
+     -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
+     -297, -297, -297, -297, -297, -297, -297, -297
+    },
+
+    {
+       13, -298, -298, -298, -298, -298, -298, -298, -298, -298,
+     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
+     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
+     -298, -298,  295, -298, -298, -298, -298, -298, -298, -298,
+     -298,  296, -298, -298, -298, -298,  293,  297,  298,  298,
+      298,  298,  298,  298,  298,  298,  298,  298, -298, -298,
+
+     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
+     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
+     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
+     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
+     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
+     -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
+     -298, -298, -298, -298, -298, -298, -298, -298
+    },
+
+    {
+       13, -299, -299, -299, -299, -299, -299, -299, -299, -299,
+     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
+     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
+
+     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
+     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
+     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
+     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
+     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
+     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
+     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
+     -299, -299, -299, -299, -299, -299, -299, -299, -299, -299,
+     -299, -299, -299, -299, -299, -299,  333, -299, -299, -299,
+     -299, -299, -299, -299, -299, -299, -299, -299
+
+    },
+
+    {
+       13, -300, -300, -300, -300, -300, -300, -300, -300, -300,
+     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
+     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
+     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
+     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
+     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
+     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
+     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
+     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
+     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
+
+     -300,  137, -300, -300, -300, -300, -300, -300, -300, -300,
+     -300, -300, -300, -300, -300, -300, -300, -300, -300, -300,
+     -300, -300, -300, -300, -300, -300, -300, -300
+    },
+
+    {
+       13, -301, -301, -301, -301, -301, -301, -301, -301, -301,
+     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
+     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
+     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
+     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
+     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
+     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
+
+     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
+     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
+     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
+     -301, -301, -301, -301, -301, -301, -301, -301, -301, -301,
+      131, -301, -301, -301, -301, -301, -301, -301, -301, -301,
+     -301, -301, -301, -301, -301, -301, -301, -301
+    },
+
+    {
+       13, -302, -302, -302, -302, -302, -302, -302, -302, -302,
+     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
+     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
+     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
+
+     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
+     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
+     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
+     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
+     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
+     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
+     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
+     -302, -302, -302, -302, -302, -302, -302, -302, -302, -302,
+     -302, -302, -302, -302, -302, -302, -302, -302
+    },
+
+    {
+       13, -303, -303, -303, -303, -303, -303, -303, -303, -303,
+
+     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
+     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
+     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
+     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
+     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
+     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
+     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
+     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
+     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
+     -303, -303, -303, -303, -303,  334, -303, -303, -303, -303,
+
+     -303, -303, -303, -303, -303, -303, -303, -303, -303, -303,
+     -303, -303, -303, -303, -303, -303, -303, -303
+    },
+
+    {
+       13, -304, -304, -304, -304, -304, -304, -304, -304, -304,
+     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
+     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
+     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
+     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
+     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
+     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
+     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
+
+     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
+     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
+     -304,  335, -304, -304, -304, -304, -304, -304, -304, -304,
+     -304, -304, -304, -304, -304, -304, -304, -304, -304, -304,
+     -304, -304, -304, -304, -304, -304, -304, -304
+    },
+
+    {
+       13, -305, -305, -305, -305, -305, -305, -305, -305, -305,
+     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
+     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
+     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
+     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
+
+     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
+     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
+     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
+     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
+     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
+     -305, -305, -305, -305, -305, -305, -305, -305, -305, -305,
+     -305, -305, -305, -305, -305, -305,  163, -305, -305, -305,
+     -305, -305, -305, -305, -305, -305, -305, -305
+    },
+
+    {
+       13, -306, -306, -306, -306, -306, -306, -306, -306, -306,
+     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
+
+     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
+     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
+     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
+     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
+     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
+     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
+     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
+     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
+     -306, -306, -306, -306, -306, -306, -306, -306, -306, -306,
+     -306,  336, -306, -306, -306, -306, -306, -306, -306, -306,
+
+     -306, -306, -306, -306, -306, -306, -306, -306
+    },
+
+    {
+       13, -307, -307, -307, -307, -307, -307, -307, -307, -307,
+     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
+     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
+     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
+     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
+     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
+     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
+     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
+     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
+
+     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
+     -307, -307, -307, -307, -307, -307, -307, -307,  163, -307,
+     -307, -307, -307, -307, -307, -307, -307, -307, -307, -307,
+     -307, -307, -307, -307, -307, -307, -307, -307
+    },
+
+    {
+       13, -308, -308, -308, -308, -308, -308, -308, -308, -308,
+     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
+     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
+     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
+     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
+     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
+
+     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
+     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
+     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
+     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
+     -308, -308, -308, -308, -308, -308, -308, -308, -308, -308,
+     -308, -308, -308, -308, -308, -308, -308,  337, -308, -308,
+     -308, -308, -308, -308, -308, -308, -308, -308
+    },
+
+    {
+       13, -309, -309, -309, -309, -309, -309, -309, -309, -309,
+     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
+     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
+
+     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
+     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
+     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
+     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
+     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
+     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
+     -309, -309, -309, -309, -309, -309, -309,  338, -309, -309,
+     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
+     -309, -309, -309, -309, -309, -309, -309, -309, -309, -309,
+     -309, -309, -309, -309, -309, -309, -309, -309
+
+    },
+
+    {
+       13, -310, -310, -310, -310, -310, -310, -310, -310, -310,
+     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
+     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
+     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
+     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
+     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
+     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
+     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
+     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
+     -310, -310, -310, -310, -310, -310, -310,  339, -310, -310,
+
+     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
+     -310, -310, -310, -310, -310, -310, -310, -310, -310, -310,
+     -310, -310, -310, -310, -310, -310, -310, -310
+    },
+
+    {
+       13, -311, -311, -311, -311, -311, -311, -311, -311, -311,
+     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
+     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
+     -311, -311,  340, -311, -311, -311, -311, -311, -311, -311,
+      341, -311, -311, -311, -311, -311, -311, -311, -311, -311,
+     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
+     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
+
+     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
+     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
+     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
+     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
+     -311, -311, -311, -311, -311, -311, -311, -311, -311, -311,
+     -311, -311, -311, -311, -311, -311, -311, -311
+    },
+
+    {
+       13, -312, -312, -312, -312, -312, -312, -312, -312, -312,
+     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
+     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
+     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
+
+     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
+     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
+     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
+     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
+     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
+     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
+     -312, -312, -312, -312, -312, -312, -312, -312,  163, -312,
+     -312, -312, -312, -312, -312, -312, -312, -312, -312, -312,
+     -312, -312, -312, -312, -312, -312, -312, -312
+    },
+
+    {
+       13, -313, -313, -313, -313, -313, -313, -313, -313, -313,
+
+     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
+     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
+     -313, -313,  313, -313, -313, -313, -313, -313, -313, -313,
+      314, -313, -313, -313, -313, -313, -313, -313, -313, -313,
+     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
+     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
+     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
+     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
+     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
+     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
+
+     -313, -313, -313, -313, -313, -313, -313, -313, -313, -313,
+     -313, -313, -313, -313, -313, -313, -313, -313
+    },
+
+    {
+       13, -314, -314, -314, -314, -314, -314, -314, -314, -314,
+     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
+     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
+     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
+     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
+     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
+     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
+     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
+
+     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
+     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
+     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
+     -314, -314, -314, -314, -314, -314, -314, -314, -314, -314,
+     -314, -314, -314, -314, -314, -314, -314, -314
+    },
+
+    {
+       13, -315, -315, -315, -315, -315, -315, -315, -315, -315,
+     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
+     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
+     -315, -315,  315, -315, -315, -315, -315, -315, -315, -315,
+      316, -315, -315, -315, -315, -315, -315, -315, -315, -315,
+
+     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
+     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
+     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
+     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
+     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
+     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
+     -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
+     -315, -315, -315, -315, -315, -315, -315, -315
+    },
+
+    {
+       13, -316, -316, -316, -316, -316, -316, -316, -316, -316,
+     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
+
+     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
+     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
+     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
+     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
+     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
+     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
+     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
+     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
+     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
+     -316, -316, -316, -316, -316, -316, -316, -316, -316, -316,
+
+     -316, -316, -316, -316, -316, -316, -316, -316
+    },
+
+    {
+       13, -317, -317, -317, -317, -317, -317, -317, -317, -317,
+     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
+     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
+     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
+     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
+     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
+     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
+     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
+     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
+
+     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
+     -317, -317, -317, -317, -317, -317, -317, -317, -317, -317,
+     -317, -317, -317, -317, -317, -317,  342, -317, -317, -317,
+     -317, -317, -317, -317, -317, -317, -317, -317
+    },
+
+    {
+       13, -318, -318, -318, -318, -318, -318, -318, -318, -318,
+     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
+     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
+     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
+     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
+     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
+
+     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
+     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
+     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
+     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
+     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
+     -318, -318, -318, -318, -318, -318, -318, -318, -318, -318,
+     -318, -318, -318, -318, -318, -318, -318, -318
+    },
+
+    {
+       13, -319, -319, -319, -319, -319, -319, -319, -319, -319,
+     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
+     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
+
+     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
+     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
+     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
+     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
+     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
+     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
+     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
+     -319, -319, -319, -319, -319,  343, -319, -319, -319, -319,
+     -319, -319, -319, -319, -319, -319, -319, -319, -319, -319,
+     -319, -319, -319, -319, -319, -319, -319, -319
+
+    },
+
+    {
+       13, -320, -320, -320, -320, -320, -320, -320, -320, -320,
+     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
+     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
+     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
+     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
+     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
+     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
+     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
+     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
+     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
+
+     -320,  344, -320, -320, -320, -320, -320, -320, -320, -320,
+     -320, -320, -320, -320, -320, -320, -320, -320, -320, -320,
+     -320, -320, -320, -320, -320, -320, -320, -320
+    },
+
+    {
+       13, -321, -321, -321, -321, -321, -321, -321, -321, -321,
+     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
+     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
+     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
+     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
+     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
+     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
+
+     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
+     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
+     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
+     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
+     -321, -321, -321, -321, -321, -321, -321, -321, -321, -321,
+     -321, -321, -321, -321, -321, -321, -321, -321
+    },
+
+    {
+       13, -322, -322, -322, -322, -322, -322, -322, -322, -322,
+     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
+     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
+     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
+
+     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
+     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
+     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
+     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
+     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
+     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
+     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
+     -322, -322, -322, -322, -322, -322, -322, -322, -322, -322,
+     -322, -322, -322, -322, -322, -322, -322, -322
+    },
+
+    {
+       13, -323, -323, -323, -323, -323, -323, -323, -323, -323,
+
+     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
+     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
+     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
+     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
+     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
+     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
+     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
+     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
+     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
+     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
+
+     -323, -323, -323, -323, -323, -323, -323, -323, -323, -323,
+     -323, -323, -323, -323, -323, -323, -323, -323
+    },
+
+    {
+       13, -324, -324, -324, -324, -324, -324, -324, -324, -324,
+     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
+     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
+     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
+     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
+     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
+     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
+     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
+
+     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
+     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
+     -324, -324, -324, -324, -324, -324, -324, -324, -324, -324,
+     -324, -324, -324, -324, -324, -324,  205, -324, -324, -324,
+     -324, -324, -324, -324, -324, -324, -324, -324
+    },
+
+    {
+       13, -325, -325, -325, -325, -325, -325, -325, -325, -325,
+     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
+     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
+     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
+     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
+
+     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
+     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
+     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
+     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
+     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
+     -325, -325, -325, -325, -325, -325, -325, -325, -325, -325,
+     -325,  345, -325, -325, -325, -325, -325, -325, -325, -325,
+     -325, -325, -325, -325, -325, -325, -325, -325
+    },
+
+    {
+       13, -326, -326, -326, -326, -326, -326, -326, -326, -326,
+     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
+
+     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
+     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
+     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
+     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
+     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
+     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
+     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
+     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
+     -326, -326, -326, -326, -326, -326, -326, -326,  346, -326,
+     -326, -326, -326, -326, -326, -326, -326, -326, -326, -326,
+
+     -326, -326, -326, -326, -326, -326, -326, -326
+    },
+
+    {
+       13, -327, -327, -327, -327, -327, -327, -327, -327, -327,
+     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
+     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
+     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
+     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
+     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
+     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
+     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
+     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
+
+     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
+     -327, -327, -327, -327, -327, -327, -327, -327, -327, -327,
+     -327, -327, -327, -327, -327, -327, -327,  347, -327, -327,
+     -327, -327, -327, -327, -327, -327, -327, -327
+    },
+
+    {
+       13, -328, -328, -328, -328, -328, -328, -328, -328, -328,
+     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
+     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
+     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
+     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
+     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
+
+     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
+     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
+     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
+     -328, -328, -328, -328, -328, -328, -328,  348, -328, -328,
+     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
+     -328, -328, -328, -328, -328, -328, -328, -328, -328, -328,
+     -328, -328, -328, -328, -328, -328, -328, -328
+    },
+
+    {
+       13, -329, -329, -329, -329, -329, -329, -329, -329, -329,
+     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
+     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
+
+     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
+     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
+     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
+     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
+     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
+     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
+     -329, -329, -329, -329, -329, -329, -329,  349, -329, -329,
+     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
+     -329, -329, -329, -329, -329, -329, -329, -329, -329, -329,
+     -329, -329, -329, -329, -329, -329, -329, -329
+
+    },
+
+    {
+       13, -330, -330, -330, -330, -330, -330, -330, -330, -330,
+     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
+     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
+     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
+     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
+     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
+     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
+     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
+     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
+     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
+
+     -330, -330, -330, -330, -330, -330, -330, -330,  350, -330,
+     -330, -330, -330, -330, -330, -330, -330, -330, -330, -330,
+     -330, -330, -330, -330, -330, -330, -330, -330
+    },
+
+    {
+       13, -331, -331, -331, -331, -331, -331, -331, -331, -331,
+     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
+     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
+     -331, -331,  291, -331, -331, -331, -331, -331, -331, -331,
+     -331,  292, -331, -331, -331, -331, -331, -331,  331,  331,
+      331,  331,  331,  331,  331,  331,  331,  331, -331, -331,
+     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
+
+     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
+     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
+     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
+     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
+     -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
+     -331, -331, -331, -331, -331, -331, -331, -331
+    },
+
+    {
+       13, -332, -332, -332, -332, -332, -332, -332, -332, -332,
+     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
+     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
+     -332, -332,  351, -332, -332, -332, -332, -332, -332, -332,
+
+     -332,  352, -332, -332, -332, -332, -332, -332,  353,  353,
+      353,  353,  353,  353,  353,  353,  353,  353, -332, -332,
+     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
+     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
+     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
+     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
+     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
+     -332, -332, -332, -332, -332, -332, -332, -332, -332, -332,
+     -332, -332, -332, -332, -332, -332, -332, -332
+    },
+
+    {
+       13, -333, -333, -333, -333, -333, -333, -333, -333, -333,
+
+     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
+     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
+     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
+     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
+     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
+     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
+     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
+     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
+     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
+     -333, -333, -333, -333, -333, -333, -333, -333, -333, -333,
+
+     -333, -333, -333, -333,  354, -333, -333, -333, -333, -333,
+     -333, -333, -333, -333, -333, -333, -333, -333
+    },
+
+    {
+       13, -334, -334, -334, -334, -334, -334, -334, -334, -334,
+     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
+     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
+     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
+     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
+     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
+     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
+     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
+
+     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
+     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
+     -334, -334, -334, -334, -334, -334, -334, -334, -334, -334,
+      151, -334, -334, -334, -334, -334, -334, -334, -334, -334,
+     -334, -334, -334, -334, -334, -334, -334, -334
+    },
+
+    {
+       13, -335, -335, -335, -335, -335, -335, -335, -335, -335,
+     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
+     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
+     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
+     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
+
+     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
+     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
+     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
+     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
+     -335, -335, -335, -335, -335, -335, -335, -335, -335,  151,
+     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
+     -335, -335, -335, -335, -335, -335, -335, -335, -335, -335,
+     -335, -335, -335, -335, -335, -335, -335, -335
+    },
+
+    {
+       13, -336, -336, -336, -336, -336, -336, -336, -336, -336,
+     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
+
+     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
+     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
+     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
+     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
+     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
+     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
+     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
+     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
+     -336, -336, -336, -336, -336, -336, -336, -336, -336, -336,
+      163, -336, -336, -336, -336, -336, -336, -336, -336, -336,
+
+     -336, -336, -336, -336, -336, -336, -336, -336
+    },
+
+    {
+       13, -337, -337, -337, -337, -337, -337, -337, -337, -337,
+     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
+     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
+     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
+     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
+     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
+     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
+     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
+     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
+
+     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
+     -337, -337, -337, -337, -337, -337, -337, -337, -337,  125,
+     -337, -337, -337, -337, -337, -337, -337, -337, -337, -337,
+     -337, -337, -337, -337, -337, -337, -337, -337
+    },
+
+    {
+       13, -338, -338, -338, -338, -338, -338, -338, -338, -338,
+     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
+     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
+     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
+     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
+     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
+
+     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
+     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
+     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
+     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
+     -338, -338, -338, -338, -338, -338, -338, -338, -338, -338,
+     -338, -338, -338, -338, -338,  355, -338, -338, -338, -338,
+     -338, -338, -338, -338, -338, -338, -338, -338
+    },
+
+    {
+       13, -339, -339, -339, -339, -339, -339, -339, -339, -339,
+     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
+     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
+
+     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
+     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
+     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
+     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
+     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
+     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
+     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
+      125, -339, -339, -339, -339, -339, -339, -339, -339, -339,
+     -339, -339, -339, -339, -339, -339, -339, -339, -339, -339,
+     -339, -339, -339, -339, -339, -339, -339, -339
+
+    },
+
+    {
+       13, -340, -340, -340, -340, -340, -340, -340, -340, -340,
+     -340, -340, -340, -340, -340, -340, -340, -340, -340, -340,
+     -340, -340, -340, -340, -340, -340, -340, -340, -340, -340,
+     -340, -340,  340, -340, -340, -340, -340, -340, -340, -340,
+      341, -340, -340, -340, -340, -340, -340, -340, -340, -340,
+     -340, -340, -340, -340, -340, -340, -340, -340, -340, -340,
+     -340, -340, -340, -340, -340, -340, -340, -340, -340, -340,
+     -340, -340, -340, -340, -340, -340, -340, -340, -340, -340,
+     -340, -340, -340, -340, -340, -340, -340, -340, -340, -340,
+     -340, -340, -340, -340, -340, -340, -340, -340, -340, -340,
+
+     -340, -340, -340, -340, -340, -340, -340, -340, -340, -340,
+     -340, -340, -340, -340, -340, -340, -340, -340, -340, -340,
+     -340, -340, -340, -340, -340, -340, -340, -340
+    },
+
+    {
+       13, -341, -341, -341, -341, -341, -341, -341, -341, -341,
+     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
+     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
+     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
+     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
+     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
+     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
+
+     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
+     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
+     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
+     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
+     -341, -341, -341, -341, -341, -341, -341, -341, -341, -341,
+     -341, -341, -341, -341, -341, -341, -341, -341
+    },
+
+    {
+       13, -342, -342, -342, -342, -342, -342, -342, -342, -342,
+     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
+     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
+     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
+
+     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
+     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
+     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
+     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
+     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
+     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
+     -342, -342, -342, -342, -342, -342, -342, -342, -342, -342,
+     -342, -342, -342, -342,  356, -342, -342, -342, -342, -342,
+     -342, -342, -342, -342, -342, -342, -342, -342
+    },
+
+    {
+       13, -343, -343, -343, -343, -343, -343, -343, -343, -343,
+
+     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
+     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
+     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
+     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
+     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
+     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
+     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
+     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
+     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
+     -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
+
+      357, -343, -343, -343, -343, -343, -343, -343, -343, -343,
+     -343, -343, -343, -343, -343, -343, -343, -343
+    },
+
+    {
+       13, -344, -344, -344, -344, -344, -344, -344, -344, -344,
+     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
+     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
+     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
+     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
+     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
+     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
+     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
+
+     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
+     -344, -344, -344, -344, -344, -344, -344, -344, -344,  358,
+     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
+     -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
+     -344, -344, -344, -344, -344, -344, -344, -344
+    },
+
+    {
+       13, -345, -345, -345, -345, -345, -345, -345, -345, -345,
+     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
+     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
+     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
+     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
+
+     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
+     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
+     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
+     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
+     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
+     -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
+      359, -345, -345, -345, -345, -345, -345, -345, -345, -345,
+     -345, -345, -345, -345, -345, -345, -345, -345
+    },
+
+    {
+       13, -346, -346, -346, -346, -346, -346, -346, -346, -346,
+     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
+
+     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
+     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
+     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
+     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
+     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
+     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
+     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
+     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
+     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
+     -346, -346, -346, -346, -346, -346, -346, -346, -346, -346,
+
+     -346, -346, -346, -346, -346, -346, -346, -346
+    },
+
+    {
+       13, -347, -347, -347, -347, -347, -347, -347, -347, -347,
+     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
+     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
+     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
+     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
+     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
+     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
+     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
+     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
+
+     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
+     -347, -347, -347, -347, -347, -347, -347, -347, -347,  360,
+     -347, -347, -347, -347, -347, -347, -347, -347, -347, -347,
+     -347, -347, -347, -347, -347, -347, -347, -347
+    },
+
+    {
+       13, -348, -348, -348, -348, -348, -348, -348, -348, -348,
+     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
+     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
+     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
+     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
+     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
+
+     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
+     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
+     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
+     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
+     -348, -348, -348, -348, -348, -348, -348, -348, -348, -348,
+     -348, -348, -348, -348, -348,  361, -348, -348, -348, -348,
+     -348, -348, -348, -348, -348, -348, -348, -348
+    },
+
+    {
+       13, -349, -349, -349, -349, -349, -349, -349, -349, -349,
+     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
+     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
+
+     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
+     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
+     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
+     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
+     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
+     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
+     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
+      362, -349, -349, -349, -349, -349, -349, -349, -349, -349,
+     -349, -349, -349, -349, -349, -349, -349, -349, -349, -349,
+     -349, -349, -349, -349, -349, -349, -349, -349
+
+    },
+
+    {
+       13, -350, -350, -350, -350, -350, -350, -350, -350, -350,
+     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
+     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
+     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
+     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
+     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
+     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
+     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
+     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
+     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
+
+     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
+     -350, -350, -350, -350, -350, -350, -350, -350, -350, -350,
+     -350, -350, -350, -350, -350, -350, -350, -350
+    },
+
+    {
+       13, -351, -351, -351, -351, -351, -351, -351, -351, -351,
+     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
+     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
+     -351, -351,  351, -351, -351, -351, -351, -351, -351, -351,
+     -351,  352, -351, -351, -351, -351, -351, -351, -351, -351,
+     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
+     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
+
+     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
+     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
+     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
+     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
+     -351, -351, -351, -351, -351, -351, -351, -351, -351, -351,
+     -351, -351, -351, -351, -351, -351, -351, -351
+    },
+
+    {
+       13, -352, -352, -352, -352, -352, -352, -352, -352, -352,
+     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
+     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
+     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
+
+     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
+     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
+     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
+     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
+     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
+     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
+     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
+     -352, -352, -352, -352, -352, -352, -352, -352, -352, -352,
+     -352, -352, -352, -352, -352, -352, -352, -352
+    },
+
+    {
+       13, -353, -353, -353, -353, -353, -353, -353, -353, -353,
+
+     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
+     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
+     -353, -353,  351, -353, -353, -353, -353, -353, -353, -353,
+     -353,  352, -353, -353, -353, -353, -353, -353,  353,  353,
+      353,  353,  353,  353,  353,  353,  353,  353, -353, -353,
+     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
+     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
+     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
+     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
+     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
+
+     -353, -353, -353, -353, -353, -353, -353, -353, -353, -353,
+     -353, -353, -353, -353, -353, -353, -353, -353
+    },
+
+    {
+       13, -354, -354, -354, -354, -354, -354, -354, -354, -354,
+     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
+     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
+     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
+     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
+     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
+     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
+     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
+
+     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
+     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
+     -354, -354, -354, -354, -354, -354, -354, -354, -354, -354,
+     -354,  363, -354, -354, -354, -354, -354, -354, -354, -354,
+     -354, -354, -354, -354, -354, -354, -354, -354
+    },
+
+    {
+       13, -355, -355, -355, -355, -355, -355, -355, -355, -355,
+     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
+     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
+     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
+     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
+
+     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
+     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
+     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
+     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
+     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
+     -355, -355, -355, -355, -355, -355, -355, -355, -355, -355,
+     -355, -355, -355, -355, -355,  125, -355, -355, -355, -355,
+     -355, -355, -355, -355, -355, -355, -355, -355
+    },
+
+    {
+       13, -356, -356, -356, -356, -356, -356, -356, -356, -356,
+     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
+
+     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
+     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
+     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
+     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
+     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
+     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
+     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
+     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
+     -356, -356, -356, -356, -356, -356, -356, -356, -356, -356,
+     -356,  364, -356, -356, -356, -356, -356, -356, -356, -356,
+
+     -356, -356, -356, -356, -356, -356, -356, -356
+    },
+
+    {
+       13, -357, -357, -357, -357, -357, -357, -357, -357, -357,
+     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
+     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
+     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
+     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
+     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
+     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
+     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
+     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
+
+     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
+     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
+     -357, -357, -357, -357, -357, -357, -357, -357, -357, -357,
+     -357, -357, -357, -357, -357, -357, -357, -357
+    },
+
+    {
+       13, -358, -358, -358, -358, -358, -358, -358, -358, -358,
+     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
+     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
+     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
+     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
+     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
+
+     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
+     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
+     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
+     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
+     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
+     -358, -358, -358, -358, -358, -358, -358, -358, -358, -358,
+     -358, -358, -358, -358, -358, -358, -358, -358
+    },
+
+    {
+       13, -359, -359, -359, -359, -359, -359, -359, -359, -359,
+     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
+     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
+
+     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
+     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
+     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
+     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
+     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
+     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
+     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
+     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
+     -359, -359, -359, -359, -359, -359, -359, -359, -359, -359,
+     -359, -359, -359, -359, -359, -359, -359, -359
+
+    },
+
+    {
+       13, -360, -360, -360, -360, -360, -360, -360, -360, -360,
+     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
+     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
+     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
+     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
+     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
+     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
+     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
+     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
+     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
+
+     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
+     -360, -360, -360, -360, -360, -360, -360, -360, -360, -360,
+     -360, -360, -360, -360, -360, -360, -360, -360
+    },
+
+    {
+       13, -361, -361, -361, -361, -361, -361, -361, -361, -361,
+     -361, -361, -361, -361, -361, -361, -361, -361, -361, -361,
+     -361, -361, -361, -361, -361, -361, -361, -361, -361, -361,
+     -361, -361, -361, -361, -361, -361, -361, -361, -361, -361,
+     -361, -361, -361, -361, -361, -361, -361, -361, -361, -361,
+     -361, -361, -361, -361, -361, -361, -361, -361, -361, -361,
+     -361, -361, -361, -361, -361, -361, -361, -361, -361, -361,
+
+     -361, -361, -361, -361, -361, -361, -361, -361, -361, -361,
+     -361, -361, -361, -361, -361, -361, -361, -361, -361, -361,
+     -361, -361, -361, -361, -361, -361, -361, -361, -361, -361,
+     -361, -361, -361, -361, -361, -361, -361, -361, -361, -361,
+     -361, -361, -361, -361, -361,  365, -361, -361, -361, -361,
+     -361, -361, -361, -361, -361, -361, -361, -361
+    },
+
+    {
+       13, -362, -362, -362, -362, -362, -362, -362, -362, -362,
+     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
+     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
+     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
+
+     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
+     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
+     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
+     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
+     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
+     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
+     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
+     -362, -362, -362, -362, -362, -362, -362, -362, -362, -362,
+     -362, -362, -362, -362, -362, -362, -362, -362
+    },
+
+    {
+       13, -363, -363, -363, -363, -363, -363, -363, -363, -363,
+
+     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
+     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
+     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
+     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
+     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
+     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
+     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
+     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
+     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
+     -363, -363, -363, -363, -363, -363, -363, -363, -363,  125,
+
+     -363, -363, -363, -363, -363, -363, -363, -363, -363, -363,
+     -363, -363, -363, -363, -363, -363, -363, -363
+    },
+
+    {
+       13, -364, -364, -364, -364, -364, -364, -364, -364, -364,
+     -364, -364, -364, -364, -364, -364, -364, -364, -364, -364,
+     -364, -364, -364, -364, -364, -364, -364, -364, -364, -364,
+     -364, -364, -364, -364, -364, -364, -364, -364, -364, -364,
+     -364, -364, -364, -364, -364, -364, -364, -364, -364, -364,
+     -364, -364, -364, -364, -364, -364, -364, -364, -364, -364,
+     -364, -364, -364, -364, -364, -364, -364, -364, -364, -364,
+     -364, -364, -364, -364, -364, -364, -364, -364, -364, -364,
+
+     -364, -364, -364, -364, -364, -364, -364, -364, -364, -364,
+     -364, -364, -364, -364, -364, -364, -364, -364, -364, -364,
+     -364, -364, -364, -364, -364, -364, -364, -364, -364,  366,
+     -364, -364, -364, -364, -364, -364, -364, -364, -364, -364,
+     -364, -364, -364, -364, -364, -364, -364, -364
+    },
+
+    {
+       13, -365, -365, -365, -365, -365, -365, -365, -365, -365,
+     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
+     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
+     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
+     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
+
+     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
+     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
+     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
+     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
+     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
+     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
+     -365, -365, -365, -365, -365, -365, -365, -365, -365, -365,
+     -365, -365, -365, -365, -365, -365, -365, -365
+    },
+
+    {
+       13, -366, -366, -366, -366, -366, -366, -366, -366, -366,
+     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
+
+     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
+     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
+     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
+     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
+     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
+     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
+     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
+     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
+     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
+     -366, -366, -366, -366, -366, -366, -366, -366, -366, -366,
+
+     -366, -366, -366, -366, -366, -366, -366, -366
+    },
+
+    } ;
+
+static yy_state_type yy_get_previous_state (void );
+static yy_state_type yy_try_NUL_trans (yy_state_type current_state  );
+static int yy_get_next_buffer (void );
+static void yy_fatal_error (yyconst char msg[]  );
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up wcsulextext.
+ */
+#define YY_DO_BEFORE_ACTION \
+	(yytext_ptr) = yy_bp; \
+	(yytext_ptr) -= (yy_more_len); \
+	wcsulexleng = (size_t) (yy_cp - (yytext_ptr)); \
+	(yy_hold_char) = *yy_cp; \
+	*yy_cp = '\0'; \
+	(yy_c_buf_p) = yy_cp;
+
+#define YY_NUM_RULES 118
+#define YY_END_OF_BUFFER 119
+/* This struct is not used in this scanner,
+   but its presence is necessary. */
+struct yy_trans_info
+	{
+	flex_int32_t yy_verify;
+	flex_int32_t yy_nxt;
+	};
+static yyconst flex_int16_t yy_accept[367] =
+    {   0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+      117,  117,  119,   20,  118,    9,   11,   12,   14,   15,
+       20,   15,   15,   20,   15,   15,   15,   15,   20,   20,
+       15,   15,   15,   15,   19,   15,   20,   20,   15,   20,
+       20,   15,   20,   15,   20,   20,   15,   15,   20,   20,
+        1,    8,   20,    2,   20,   20,   23,   21,   22,   44,
+       41,   38,   37,   40,   39,   43,   42,   31,   25,   24,
+       30,   35,   36,   26,   28,   29,   27,   33,   32,  105,
+       45,  105,   57,   61,   66,   67,   69,   72,   74,   83,
+      105,  105,   89,   92,   99,  101,  103,   46,  105,  105,
+
+       62,  105,   68,   70,  105,   78,  105,  105,   93,  100,
+      105,  105,  116,  113,  112,  111,  116,  111,  114,  107,
+      115,  106,  117,    9,   15,    0,    0,   16,    0,   16,
+       16,   16,   16,    0,    0,   16,   17,    0,    0,    0,
+        0,   16,    0,    0,   16,    0,   15,   15,    0,   15,
+       15,    0,    0,    0,   16,    0,    0,    0,    0,   15,
+        0,    0,   15,    0,    0,    0,    0,    0,    0,    0,
+       15,   15,    0,    0,    0,    0,    0,   15,    1,   13,
+        4,    0,    0,    0,   23,   34,   51,    0,    0,   71,
+       73,    0,   85,   91,    0,  104,    0,    0,    0,    0,
+
+        0,   58,    0,    0,   60,    0,   65,    0,   75,   76,
+        0,    0,    0,    0,   86,   87,    0,    0,    0,   97,
+        0,   46,  113,  112,  111,    0,  111,  114,  107,  115,
+      106,    0,    0,    0,    0,    0,  111,  114,  107,  117,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,   15,    0,    0,    0,   15,    0,    0,    0,
+        3,    0,    0,    6,    0,    0,    0,   84,   98,   47,
+        0,    0,    0,   54,   55,    0,    0,   63,   64,   77,
+       79,   80,   81,   82,    0,   88,   90,    0,    0,    0,
+        0,  110,    0,    0,    0,  108,    0,    0,    0,    0,
+
+        0,   18,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    7,    0,    5,    0,   56,    0,    0,
+       52,   53,   59,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+       10,    0,    0,    0,    0,   88,    0,    0,    0,  102,
+        0,  109,    0,    0,    0,    0,   49,   50,   87,   94,
+        0,   96,    0,    0,   95,   48
+    } ;
+
+static yy_state_type yy_last_accepting_state;
+static char *yy_last_accepting_cpos;
+
+static yyconst yy_state_type yy_NUL_trans[367] =
+    {   0,
+       14,   14,   57,   57,   60,   60,   80,   80,  113,  113,
+      123,  123,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,  185,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,  240,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,  185,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,  240,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0
+    } ;
+
+extern int wcsulex_flex_debug;
+int wcsulex_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
+static int yy_more_flag = 0;
+static int yy_more_len = 0;
+#define yymore() ((yy_more_flag) = 1)
+#define YY_MORE_ADJ (yy_more_len)
+#define YY_RESTORE_YY_MORE_OFFSET
+char *wcsulextext;
+#line 1 "wcsulex.l"
+/*============================================================================
+
+  WCSLIB 4.16 - an implementation of the FITS WCS standard.
+  Copyright (C) 1995-2012, Mark Calabretta
+
+  This file is part of WCSLIB.
+
+  WCSLIB is free software: you can redistribute it and/or modify it under the
+  terms of the GNU Lesser General Public License as published by the Free
+  Software Foundation, either version 3 of the License, or (at your option)
+  any later version.
+
+  WCSLIB 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 Lesser General Public License for
+  more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with WCSLIB.  If not, see http://www.gnu.org/licenses.
+
+  Direct correspondence concerning WCSLIB to mark at calabretta.id.au
+
+  Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
+  http://www.atnf.csiro.au/people/Mark.Calabretta
+  $Id: wcsulex.c,v 4.16 2012/11/07 04:42:44 cal103 Exp $
+*=============================================================================
+*
+* wcsulex.l is a Flex description file containing the definition of a
+* recursive, multi-buffered lexical scanner that parses FITS units
+* specifications.
+*
+* It requires Flex v2.5.4 or later.
+*
+* Refer to wcsunits.h for a description of the user interface and operating
+* notes.
+*
+*===========================================================================*/
+/* Options. */
+/* Exponents. */
+/* Metric prefixes. */
+/* Basic and derived SI units. */
+/* Additional recognized units: all metric prefixes allowed. */
+/* Additional recognized units: only super-metric prefixes allowed. */
+/* Additional recognized units: only sub-metric prefixes allowed. */
+/* Additional recognized units for which NO metric prefixes are allowed. */
+/* All additional recognized units. */
+/* Exclusive start states. */
+
+#line 85 "wcsulex.l"
+/* To get the prototype for fileno() from stdio.h when gcc is invoked with
+ * -std=c89 (same as -ansi) or -std=c99 since we do not define YY_INPUT. */
+#define _POSIX_SOURCE 1
+
+#include <math.h>
+#include <setjmp.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "wcserr.h"
+#include "wcsmath.h"
+#include "wcsunits.h"
+#include "wcsutil.h"
+
+#define YY_DECL int wcsulexe(const char unitstr[], int *func, double *scale, \
+                             double units[], struct wcserr **err)
+
+/* Used in preempting the call to exit() by yy_fatal_error(). */
+jmp_buf wcsulex_abort_jmp_env;
+#define exit(status) longjmp(wcsulex_abort_jmp_env, status)
+
+#line 6932 "wcsulex.c"
+
+#define INITIAL 0
+#define PAREN 1
+#define PREFIX 2
+#define UNITS 3
+#define EXPON 4
+#define FLUSH 5
+
+#ifndef YY_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 <unistd.h>
+#endif
+
+#ifndef YY_EXTRA_TYPE
+#define YY_EXTRA_TYPE void *
+#endif
+
+static int yy_init_globals (void );
+
+/* Accessor methods to globals.
+   These are made visible to non-reentrant scanners for convenience. */
+
+int wcsulexlex_destroy (void );
+
+int wcsulexget_debug (void );
+
+void wcsulexset_debug (int debug_flag  );
+
+YY_EXTRA_TYPE wcsulexget_extra (void );
+
+void wcsulexset_extra (YY_EXTRA_TYPE user_defined  );
+
+FILE *wcsulexget_in (void );
+
+void wcsulexset_in  (FILE * in_str  );
+
+FILE *wcsulexget_out (void );
+
+void wcsulexset_out  (FILE * out_str  );
+
+int wcsulexget_leng (void );
+
+char *wcsulexget_text (void );
+
+int wcsulexget_lineno (void );
+
+void wcsulexset_lineno (int line_number  );
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int wcsulexwrap (void );
+#else
+extern int wcsulexwrap (void );
+#endif
+#endif
+
+    static void yyunput (int c,char *buf_ptr  );
+    
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char *,yyconst char *,int );
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * );
+#endif
+
+#ifndef YY_NO_INPUT
+
+#ifdef __cplusplus
+static int yyinput (void );
+#else
+static int input (void );
+#endif
+
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k */
+#define YY_READ_BUF_SIZE 16384
+#else
+#define YY_READ_BUF_SIZE 8192
+#endif /* __ia64__ */
+#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( wcsulextext, wcsulexleng, 1, wcsulexout )) {} } while (0)
+#endif
+
+/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+	errno=0; \
+	while ( (result = read( fileno(wcsulexin), (char *) buf, max_size )) < 0 ) \
+	{ \
+		if( errno != EINTR) \
+		{ \
+			YY_FATAL_ERROR( "input in flex scanner failed" ); \
+			break; \
+		} \
+		errno=0; \
+		clearerr(wcsulexin); \
+	}\
+\
+
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_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 YY_DECL
+#define YY_DECL_IS_OURS 1
+
+extern int wcsulexlex (void);
+
+#define YY_DECL int wcsulexlex (void)
+#endif /* !YY_DECL */
+
+/* Code executed at the beginning of each rule, after wcsulextext and wcsulexleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+	if ( wcsulexleng > 0 ) \
+		YY_CURRENT_BUFFER_LVALUE->yy_at_bol = \
+				(wcsulextext[wcsulexleng - 1] == '\n'); \
+	YY_USER_ACTION
+
+/** The main scanner function which does all the work.
+ */
+YY_DECL
+{
+	register yy_state_type yy_current_state;
+	register char *yy_cp, *yy_bp;
+	register int yy_act;
+    
+#line 108 "wcsulex.l"
+
+	static const char *function = "wcsulexe";
+	
+	char ctmp[72];
+	int bracket  = 0;
+	int operator = 0;
+	int paren    = 0;
+	int status   = 0;
+	int func_r, i, j;
+	double dexp, expon, factor, factor_r, types[WCSUNITS_NTYPE];
+	YY_BUFFER_STATE buf;
+	void add(double *factor, double types[], double *expon, double *scale,
+	    double units[]);
+	int wcsulexlex_destroy(void);
+	
+	if (err) *err = 0x0;
+	
+	*func = 0;
+	for (i = 0; i < WCSUNITS_NTYPE; i++) {
+	  units[i] = 0.0;
+	  types[i] = 0.0;
+	}
+	expon  = 1.0;
+	factor = 1.0;
+	*scale = 1.0;
+	
+	wcsulex_scan_string(unitstr);
+	
+	/* Return here via longjmp() invoked by yy_fatal_error(). */
+	if (setjmp(wcsulex_abort_jmp_env)) {
+	  return wcserr_set(WCSERR_SET(UNITSERR_PARSER_ERROR),
+	    "Internal units parser error parsing '%s'", unitstr);
+	}
+	
+	BEGIN(INITIAL);
+	
+#ifdef DEBUG
+	fprintf(stderr, "\n%s ->\n", unitstr);
+#endif
+
+#line 7152 "wcsulex.c"
+
+	if ( !(yy_init) )
+		{
+		(yy_init) = 1;
+
+#ifdef YY_USER_INIT
+		YY_USER_INIT;
+#endif
+
+		if ( ! (yy_start) )
+			(yy_start) = 1;	/* first start state */
+
+		if ( ! wcsulexin )
+			wcsulexin = stdin;
+
+		if ( ! wcsulexout )
+			wcsulexout = stdout;
+
+		if ( ! YY_CURRENT_BUFFER ) {
+			wcsulexensure_buffer_stack ();
+			YY_CURRENT_BUFFER_LVALUE =
+				wcsulex_create_buffer(wcsulexin,YY_BUF_SIZE );
+		}
+
+		wcsulex_load_buffer_state( );
+		}
+
+	while ( 1 )		/* loops until end-of-file is reached */
+		{
+		(yy_more_len) = 0;
+		if ( (yy_more_flag) )
+			{
+			(yy_more_len) = (yy_c_buf_p) - (yytext_ptr);
+			(yy_more_flag) = 0;
+			}
+		yy_cp = (yy_c_buf_p);
+
+		/* Support of wcsulextext. */
+		*yy_cp = (yy_hold_char);
+
+		/* yy_bp points to the position in yy_ch_buf of the start of
+		 * the current run.
+		 */
+		yy_bp = yy_cp;
+
+		yy_current_state = (yy_start);
+		yy_current_state += YY_AT_BOL();
+yy_match:
+		while ( (yy_current_state = yy_nxt[yy_current_state][ YY_SC_TO_UI(*yy_cp) ]) > 0 )
+			{
+			if ( yy_accept[yy_current_state] )
+				{
+				(yy_last_accepting_state) = yy_current_state;
+				(yy_last_accepting_cpos) = yy_cp;
+				}
+
+			++yy_cp;
+			}
+
+		yy_current_state = -yy_current_state;
+
+yy_find_action:
+		yy_act = yy_accept[yy_current_state];
+
+		YY_DO_BEFORE_ACTION;
+
+do_action:	/* This label is used only to access EOF actions. */
+
+		switch ( yy_act )
+	{ /* beginning of action switch */
+			case 0: /* must back up */
+			/* undo the effects of YY_DO_BEFORE_ACTION */
+			*yy_cp = (yy_hold_char);
+			yy_cp = (yy_last_accepting_cpos) + 1;
+			yy_current_state = (yy_last_accepting_state);
+			goto yy_find_action;
+
+case 1:
+YY_RULE_SETUP
+#line 148 "wcsulex.l"
+{
+	  /* Pretend initial whitespace doesn't exist. */
+	  yy_set_bol(1);
+	}
+	YY_BREAK
+case 2:
+YY_RULE_SETUP
+#line 153 "wcsulex.l"
+{
+	  if (bracket++) {
+	    BEGIN(FLUSH);
+	  } else {
+	    yy_set_bol(1);
+	  }
+	}
+	YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 161 "wcsulex.l"
+{
+	  status = wcserr_set(WCSERR_SET(UNITSERR_BAD_NUM_MULTIPLIER),
+	    "Invalid exponent in '%s'", unitstr);
+	  BEGIN(FLUSH);
+	}
+	YY_BREAK
+case 4:
+YY_RULE_SETUP
+#line 167 "wcsulex.l"
+{
+	  factor = 10.0;
+	  BEGIN(EXPON);
+	}
+	YY_BREAK
+case 5:
+YY_RULE_SETUP
+#line 172 "wcsulex.l"
+{
+	  *func = 1;
+	  unput('(');
+	  BEGIN(PAREN);
+	}
+	YY_BREAK
+case 6:
+YY_RULE_SETUP
+#line 178 "wcsulex.l"
+{
+	  *func = 2;
+	  unput('(');
+	  BEGIN(PAREN);
+	}
+	YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 184 "wcsulex.l"
+{
+	  *func = 3;
+	  unput('(');
+	  BEGIN(PAREN);
+	}
+	YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 190 "wcsulex.l"
+{
+	  /* Leading binary multiply. */
+	  status = wcserr_set(WCSERR_SET(UNITSERR_DANGLING_BINOP),
+	    "Dangling binary operator in '%s'", unitstr);
+	  BEGIN(FLUSH);
+	}
+	YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 197 "wcsulex.l"
+/* Discard whitespace in INITIAL context. */
+	YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 199 "wcsulex.l"
+{
+	  expon /= 2.0;
+	  unput('(');
+	  BEGIN(PAREN);
+	}
+	YY_BREAK
+case 11:
+YY_RULE_SETUP
+#line 205 "wcsulex.l"
+{
+	  /* Gather terms in parentheses. */
+	  yyless(0);
+	  BEGIN(PAREN);
+	}
+	YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 211 "wcsulex.l"
+{
+	  if (operator++) {
+	    BEGIN(FLUSH);
+	  }
+	}
+	YY_BREAK
+case 13:
+#line 218 "wcsulex.l"
+case 14:
+YY_RULE_SETUP
+#line 218 "wcsulex.l"
+{
+	  if (operator++) {
+	    BEGIN(FLUSH);
+	  } else {
+	    expon *= -1.0;
+	  }
+	}
+	YY_BREAK
+case 15:
+YY_RULE_SETUP
+#line 226 "wcsulex.l"
+{
+	  operator = 0;
+	  yyless(0);
+	  BEGIN(UNITS);
+	}
+	YY_BREAK
+case 16:
+#line 233 "wcsulex.l"
+case 17:
+#line 234 "wcsulex.l"
+case 18:
+YY_RULE_SETUP
+#line 234 "wcsulex.l"
+{
+	  operator = 0;
+	  yyless(0);
+	  BEGIN(PREFIX);
+	}
+	YY_BREAK
+case 19:
+YY_RULE_SETUP
+#line 240 "wcsulex.l"
+{
+	  bracket = !bracket;
+	  BEGIN(FLUSH);
+	}
+	YY_BREAK
+case 20:
+YY_RULE_SETUP
+#line 245 "wcsulex.l"
+{
+	  status = wcserr_set(WCSERR_SET(UNITSERR_BAD_INITIAL_SYMBOL),
+	    "Invalid symbol in INITIAL context in '%s'", unitstr);
+	  BEGIN(FLUSH);
+	}
+	YY_BREAK
+case 21:
+YY_RULE_SETUP
+#line 251 "wcsulex.l"
+{
+	  paren++;
+	  operator = 0;
+	  yymore();
+	}
+	YY_BREAK
+case 22:
+YY_RULE_SETUP
+#line 257 "wcsulex.l"
+{
+	  paren--;
+	  if (paren) {
+	    /* Not balanced yet. */
+	    yymore();
+	
+	  } else {
+	    /* Balanced; strip off the outer parentheses and recurse. */
+	    wcsulextext[wcsulexleng-1] = '\0';
+	
+	    buf = YY_CURRENT_BUFFER;
+	    status = wcsulexe(wcsulextext+1, &func_r, &factor_r, types, err);
+	    wcsulex_switch_to_buffer(buf);
+	
+	    if (func_r) {
+	      status = wcserr_set(WCSERR_SET(UNITSERR_FUNCTION_CONTEXT),
+	        "Function in invalid context in '%s'", unitstr);
+	    }
+	
+	    if (status) {
+	      BEGIN(FLUSH);
+	    } else {
+	      factor *= factor_r;
+	      BEGIN(EXPON);
+	    }
+	  }
+	}
+	YY_BREAK
+case 23:
+/* rule 23 can match eol */
+YY_RULE_SETUP
+#line 285 "wcsulex.l"
+{
+	  yymore();
+	}
+	YY_BREAK
+case 24:
+YY_RULE_SETUP
+#line 289 "wcsulex.l"
+{
+	  factor = 1e-1;
+	  BEGIN(UNITS);
+	}
+	YY_BREAK
+case 25:
+YY_RULE_SETUP
+#line 294 "wcsulex.l"
+{
+	  factor = 1e-2;
+	  BEGIN(UNITS);
+	}
+	YY_BREAK
+case 26:
+YY_RULE_SETUP
+#line 299 "wcsulex.l"
+{
+	  factor = 1e-3;
+	  BEGIN(UNITS);
+	}
+	YY_BREAK
+case 27:
+YY_RULE_SETUP
+#line 304 "wcsulex.l"
+{
+	  factor = 1e-6;
+	  BEGIN(UNITS);
+	}
+	YY_BREAK
+case 28:
+YY_RULE_SETUP
+#line 309 "wcsulex.l"
+{
+	  factor = 1e-9;
+	  BEGIN(UNITS);
+	}
+	YY_BREAK
+case 29:
+YY_RULE_SETUP
+#line 314 "wcsulex.l"
+{
+	  factor = 1e-12;
+	  BEGIN(UNITS);
+	}
+	YY_BREAK
+case 30:
+YY_RULE_SETUP
+#line 319 "wcsulex.l"
+{
+	  factor = 1e-15;
+	  BEGIN(UNITS);
+	}
+	YY_BREAK
+case 31:
+YY_RULE_SETUP
+#line 324 "wcsulex.l"
+{
+	  factor = 1e-18;
+	  BEGIN(UNITS);
+	}
+	YY_BREAK
+case 32:
+YY_RULE_SETUP
+#line 329 "wcsulex.l"
+{
+	  factor = 1e-21;
+	  BEGIN(UNITS);
+	}
+	YY_BREAK
+case 33:
+YY_RULE_SETUP
+#line 334 "wcsulex.l"
+{
+	  factor = 1e-24;
+	  BEGIN(UNITS);
+	}
+	YY_BREAK
+case 34:
+YY_RULE_SETUP
+#line 339 "wcsulex.l"
+{
+	  factor = 1e+1;
+	  BEGIN(UNITS);
+	}
+	YY_BREAK
+case 35:
+YY_RULE_SETUP
+#line 344 "wcsulex.l"
+{
+	  factor = 1e+2;
+	  BEGIN(UNITS);
+	}
+	YY_BREAK
+case 36:
+YY_RULE_SETUP
+#line 349 "wcsulex.l"
+{
+	  factor = 1e+3;
+	  BEGIN(UNITS);
+	}
+	YY_BREAK
+case 37:
+YY_RULE_SETUP
+#line 354 "wcsulex.l"
+{
+	  factor = 1e+6;
+	  BEGIN(UNITS);
+	}
+	YY_BREAK
+case 38:
+YY_RULE_SETUP
+#line 359 "wcsulex.l"
+{
+	  factor = 1e+9;
+	  BEGIN(UNITS);
+	}
+	YY_BREAK
+case 39:
+YY_RULE_SETUP
+#line 364 "wcsulex.l"
+{
+	  factor = 1e+12;
+	  BEGIN(UNITS);
+	}
+	YY_BREAK
+case 40:
+YY_RULE_SETUP
+#line 369 "wcsulex.l"
+{
+	  factor = 1e+15;
+	  BEGIN(UNITS);
+	}
+	YY_BREAK
+case 41:
+YY_RULE_SETUP
+#line 374 "wcsulex.l"
+{
+	  factor = 1e+18;
+	  BEGIN(UNITS);
+	}
+	YY_BREAK
+case 42:
+YY_RULE_SETUP
+#line 379 "wcsulex.l"
+{
+	  factor = 1e+21;
+	  BEGIN(UNITS);
+	}
+	YY_BREAK
+case 43:
+YY_RULE_SETUP
+#line 384 "wcsulex.l"
+{
+	  factor = 1e+24;
+	  BEGIN(UNITS);
+	}
+	YY_BREAK
+case 44:
+YY_RULE_SETUP
+#line 389 "wcsulex.l"
+{
+	  /* Internal parser error. */
+	  status = wcserr_set(WCSERR_SET(UNITSERR_PARSER_ERROR),
+	    "Internal units parser error parsing '%s'", unitstr);
+	  BEGIN(FLUSH);
+	}
+	YY_BREAK
+case 45:
+YY_RULE_SETUP
+#line 396 "wcsulex.l"
+{
+	  /* Ampere. */
+	  types[WCSUNITS_CHARGE] += 1.0;
+	  types[WCSUNITS_TIME]   -= 1.0;
+	  BEGIN(EXPON);
+	}
+	YY_BREAK
+case 46:
+YY_RULE_SETUP
+#line 403 "wcsulex.l"
+{
+	  /* Year (annum). */
+	  factor *= 31557600.0;
+	  types[WCSUNITS_TIME] += 1.0;
+	  BEGIN(EXPON);
+	}
+	YY_BREAK
+case 47:
+YY_RULE_SETUP
+#line 410 "wcsulex.l"
+{
+	  /* Analogue-to-digital converter units. */
+	  types[WCSUNITS_COUNT] += 1.0;
+	  BEGIN(EXPON);
+	}
+	YY_BREAK
+case 48:
+YY_RULE_SETUP
+#line 416 "wcsulex.l"
+{
+	  /* Angstrom. */
+	  factor *= 1e-10;
+	  types[WCSUNITS_LENGTH] += 1.0;
+	  BEGIN(EXPON);
+	}
+	YY_BREAK
+case 49:
+YY_RULE_SETUP
+#line 423 "wcsulex.l"
+{
+	  /* Minute of arc. */
+	  factor /= 60.0;
+	  types[WCSUNITS_PLANE_ANGLE] += 1.0;
+	  BEGIN(EXPON);
+	}
+	YY_BREAK
+case 50:
+YY_RULE_SETUP
+#line 430 "wcsulex.l"
+{
+	  /* Second of arc. */
+	  factor /= 3600.0;
+	  types[WCSUNITS_PLANE_ANGLE] += 1.0;
+	  BEGIN(EXPON);
+	}
+	YY_BREAK
+case 51:
+YY_RULE_SETUP
+#line 437 "wcsulex.l"
+{
+	  /* Astronomical unit. */
+	  factor *= 1.49598e+11;
+	  types[WCSUNITS_LENGTH] += 1.0;
+	  BEGIN(EXPON);
+	}
+	YY_BREAK
+case 52:
+YY_RULE_SETUP
+#line 444 "wcsulex.l"
+{
+	  /* Barn. */
+	  factor *= 1e-28;
+	  types[WCSUNITS_LENGTH] += 2.0;
+	  BEGIN(EXPON);
+	}
+	YY_BREAK
+case 53:
+YY_RULE_SETUP
+#line 451 "wcsulex.l"
+{
+	  /* Beam, as in Jy/beam. */
+	  types[WCSUNITS_BEAM] += 1.0;
+	  BEGIN(EXPON);
+	}
+	YY_BREAK
+case 54:
+YY_RULE_SETUP
+#line 457 "wcsulex.l"
+{
+	  /* Bin (e.g. histogram). */
+	  types[WCSUNITS_BIN] += 1.0;
+	  BEGIN(EXPON);
+	}
+	YY_BREAK
+case 55:
+YY_RULE_SETUP
+#line 463 "wcsulex.l"
+{
+	  /* Bit. */
+	  types[WCSUNITS_BIT] += 1.0;
+	  BEGIN(EXPON);
+	}
+	YY_BREAK
+case 56:
+YY_RULE_SETUP
+#line 469 "wcsulex.l"
+{
+	  /* Byte. */
+	  factor *= 8.0;
+	  types[WCSUNITS_BIT] += 1.0;
+	  BEGIN(EXPON);
+	}
+	YY_BREAK
+case 57:
+YY_RULE_SETUP
+#line 476 "wcsulex.l"
+{
+	  /* Coulomb. */
+	  types[WCSUNITS_CHARGE] += 1.0;
+	  BEGIN(EXPON);
+	}
+	YY_BREAK
+case 58:
+YY_RULE_SETUP
+#line 482 "wcsulex.l"
+{
+	  /* Candela. */
+	  types[WCSUNITS_LUMINTEN] += 1.0;
+	  BEGIN(EXPON);
+	}
+	YY_BREAK
+case 59:
+YY_RULE_SETUP
+#line 488 "wcsulex.l"
+{
+	  /* Channel. */
+	  types[WCSUNITS_BIN] += 1.0;
+	  BEGIN(EXPON);
+	}
+	YY_BREAK
+case 60:
+YY_RULE_SETUP
+#line 494 "wcsulex.l"
+{
+	  /* Count. */
+	  types[WCSUNITS_COUNT] += 1.0;
+	  BEGIN(EXPON);
+	}
+	YY_BREAK
+case 61:
+YY_RULE_SETUP
+#line 500 "wcsulex.l"
+{
+	  /* Debye. */
+	  factor *= 1e-29 / 3.0;
+	  types[WCSUNITS_CHARGE] += 1.0;
+	  types[WCSUNITS_LENGTH] += 1.0;
+	  BEGIN(EXPON);
+	}
+	YY_BREAK
+case 62:
+YY_RULE_SETUP
+#line 508 "wcsulex.l"
+{
+	  /* Day. */
+	  factor *= 86400.0;
+	  types[WCSUNITS_TIME] += 1.0;
+	  BEGIN(EXPON);
+	}
+	YY_BREAK
+case 63:
+YY_RULE_SETUP
+#line 515 "wcsulex.l"
+{
+	  /* Degree. */
+	  types[WCSUNITS_PLANE_ANGLE] += 1.0;
+	  BEGIN(EXPON);
+	}
+	YY_BREAK
+case 64:
+YY_RULE_SETUP
+#line 521 "wcsulex.l"
+{
+	  /* Erg. */
+	  factor *= 1e-7;
+	  types[WCSUNITS_MASS]   += 1.0;
+	  types[WCSUNITS_LENGTH] += 2.0;
+	  types[WCSUNITS_TIME]   -= 2.0;
+	  BEGIN(EXPON);
+	}
+	YY_BREAK
+case 65:
+YY_RULE_SETUP
+#line 530 "wcsulex.l"
+{
+	  /* Electron volt. */
+	  factor *= 1.6021765e-19;
+	  types[WCSUNITS_MASS]   += 1.0;
+	  types[WCSUNITS_LENGTH] += 2.0;
+	  types[WCSUNITS_TIME]   -= 2.0;
+	  BEGIN(EXPON);
+	}
+	YY_BREAK
+case 66:
+YY_RULE_SETUP
+#line 539 "wcsulex.l"
+{
+	  /* Farad. */
+	  types[WCSUNITS_MASS]   -= 1.0;
+	  types[WCSUNITS_LENGTH] -= 2.0;
+	  types[WCSUNITS_TIME]   += 3.0;
+	  types[WCSUNITS_CHARGE] += 2.0;
+	  BEGIN(EXPON);
+	}
+	YY_BREAK
+case 67:
+YY_RULE_SETUP
+#line 548 "wcsulex.l"
+{
+	  /* Gauss. */
+	  factor *= 1e-4;
+	  types[WCSUNITS_MASS]   += 1.0;
+	  types[WCSUNITS_TIME]   += 1.0;
+	  types[WCSUNITS_CHARGE] -= 1.0;
+	  BEGIN(EXPON);
+	}
+	YY_BREAK
+case 68:
+YY_RULE_SETUP
+#line 557 "wcsulex.l"
+{
+	  /* Gram. */
+	  factor *= 1e-3;
+	  types[WCSUNITS_MASS] += 1.0;
+	  BEGIN(EXPON);
+	}
+	YY_BREAK
+case 69:
+YY_RULE_SETUP
+#line 564 "wcsulex.l"
+{
+	  /* Henry. */
+	  types[WCSUNITS_MASS]   += 1.0;
+	  types[WCSUNITS_LENGTH] += 2.0;
+	  types[WCSUNITS_TIME]   += 2.0;
+	  types[WCSUNITS_CHARGE] -= 2.0;
+	  BEGIN(EXPON);
+	}
+	YY_BREAK
+case 70:
+YY_RULE_SETUP
+#line 573 "wcsulex.l"
+{
+	  /* Hour. */
+	  factor *= 3600.0;
+	  types[WCSUNITS_TIME] += 1.0;
+	  BEGIN(EXPON);
+	}
+	YY_BREAK
+case 71:
+YY_RULE_SETUP
+#line 580 "wcsulex.l"
+{
+	  /* Hertz. */
+	  types[WCSUNITS_TIME] -= 1.0;
+	  BEGIN(EXPON);
+	}
+	YY_BREAK
+case 72:
+YY_RULE_SETUP
+#line 586 "wcsulex.l"
+{
+	  /* Joule. */
+	  types[WCSUNITS_MASS]   += 1.0;
+	  types[WCSUNITS_LENGTH] += 2.0;
+	  types[WCSUNITS_TIME]   -= 2.0;
+	  BEGIN(EXPON);
+	}
+	YY_BREAK
+case 73:
+YY_RULE_SETUP
+#line 594 "wcsulex.l"
+{
+	  /* Jansky. */
+	  factor *= 1e-26;
+	  types[WCSUNITS_MASS] += 1.0;
+	  types[WCSUNITS_TIME] -= 2.0;
+	  BEGIN(EXPON);
+	}
+	YY_BREAK
+case 74:
+YY_RULE_SETUP
+#line 602 "wcsulex.l"
+{
+	  /* Kelvin. */
+	  types[WCSUNITS_TEMPERATURE] += 1.0;
+	  BEGIN(EXPON);
+	}
+	YY_BREAK
+case 75:
+YY_RULE_SETUP
+#line 608 "wcsulex.l"
+{
+	  /* Lumen. */
+	  types[WCSUNITS_LUMINTEN]    += 1.0;
+	  types[WCSUNITS_SOLID_ANGLE] += 1.0;
+	  BEGIN(EXPON);
+	}
+	YY_BREAK
+case 76:
+YY_RULE_SETUP
+#line 615 "wcsulex.l"
+{
+	  /* Lux. */
+	  types[WCSUNITS_LUMINTEN]    += 1.0;
+	  types[WCSUNITS_SOLID_ANGLE] += 1.0;
+	  types[WCSUNITS_LENGTH]      -= 2.0;
+	  BEGIN(EXPON);
+	}
+	YY_BREAK
+case 77:
+YY_RULE_SETUP
+#line 623 "wcsulex.l"
+{
+	  /* Light year. */
+	  factor *= 2.99792458e8 * 31557600.0;
+	  types[WCSUNITS_LENGTH] += 1.0;
+	  BEGIN(EXPON);
+	}
+	YY_BREAK
+case 78:
+YY_RULE_SETUP
+#line 630 "wcsulex.l"
+{
+	  /* Metre. */
+	  types[WCSUNITS_LENGTH] += 1.0;
+	  BEGIN(EXPON);
+	}
+	YY_BREAK
+case 79:
+YY_RULE_SETUP
+#line 636 "wcsulex.l"
+{
+	  /* Stellar magnitude. */
+	  types[WCSUNITS_MAGNITUDE] += 1.0;
+	  BEGIN(EXPON);
+	}
+	YY_BREAK
+case 80:
+YY_RULE_SETUP
+#line 642 "wcsulex.l"
+{
+	  /* Milli-arcsec. */
+	  factor /= 3600e+3;
+	  types[WCSUNITS_PLANE_ANGLE] += 1.0;
+	  BEGIN(EXPON);
+	}
+	YY_BREAK
+case 81:
+YY_RULE_SETUP
+#line 649 "wcsulex.l"
+{
+	  /* Minute. */
+	  factor *= 60.0;
+	  types[WCSUNITS_TIME] += 1.0;
+	  BEGIN(EXPON);
+	}
+	YY_BREAK
+case 82:
+YY_RULE_SETUP
+#line 656 "wcsulex.l"
+{
+	  /* Mole. */
+	  types[WCSUNITS_MOLE] += 1.0;
+	  BEGIN(EXPON);
+	}
+	YY_BREAK
+case 83:
+YY_RULE_SETUP
+#line 662 "wcsulex.l"
+{
+	  /* Newton. */
+	  types[WCSUNITS_MASS]   += 1.0;
+	  types[WCSUNITS_LENGTH] += 1.0;
+	  types[WCSUNITS_TIME]   -= 2.0;
+	  BEGIN(EXPON);
+	}
+	YY_BREAK
+case 84:
+YY_RULE_SETUP
+#line 670 "wcsulex.l"
+{
+	  /* Ohm. */
+	  types[WCSUNITS_MASS]   += 1.0;
+	  types[WCSUNITS_LENGTH] += 2.0;
+	  types[WCSUNITS_TIME]   -= 1.0;
+	  types[WCSUNITS_CHARGE] -= 2.0;
+	  BEGIN(EXPON);
+	}
+	YY_BREAK
+case 85:
+YY_RULE_SETUP
+#line 679 "wcsulex.l"
+{
+	  /* Pascal. */
+	  types[WCSUNITS_MASS]   += 1.0;
+	  types[WCSUNITS_LENGTH] -= 1.0;
+	  types[WCSUNITS_TIME]   -= 2.0;
+	  BEGIN(EXPON);
+	}
+	YY_BREAK
+case 86:
+YY_RULE_SETUP
+#line 687 "wcsulex.l"
+{
+	  /* Parsec. */
+	  factor *= 3.0857e16;
+	  types[WCSUNITS_LENGTH] += 1.0;
+	  BEGIN(EXPON);
+	}
+	YY_BREAK
+case 87:
+YY_RULE_SETUP
+#line 694 "wcsulex.l"
+{
+	  /* Photon. */
+	  types[WCSUNITS_COUNT] += 1.0;
+	  BEGIN(EXPON);
+	}
+	YY_BREAK
+case 88:
+YY_RULE_SETUP
+#line 700 "wcsulex.l"
+{
+	  /* Pixel. */
+	  types[WCSUNITS_PIXEL] += 1.0;
+	  BEGIN(EXPON);
+	}
+	YY_BREAK
+case 89:
+YY_RULE_SETUP
+#line 706 "wcsulex.l"
+{
+	  /* Rayleigh. */
+	  factor *= 1e10 / (4.0 * PI);
+	  types[WCSUNITS_LENGTH]      -= 2.0;
+	  types[WCSUNITS_TIME]        -= 1.0;
+	  types[WCSUNITS_SOLID_ANGLE] -= 1.0;
+	  BEGIN(EXPON);
+	}
+	YY_BREAK
+case 90:
+YY_RULE_SETUP
+#line 715 "wcsulex.l"
+{
+	  /* Radian. */
+	  factor *= 180.0 / PI;
+	  types[WCSUNITS_PLANE_ANGLE] += 1.0;
+	  BEGIN(EXPON);
+	}
+	YY_BREAK
+case 91:
+YY_RULE_SETUP
+#line 722 "wcsulex.l"
+{
+	  /* Rydberg. */
+	  factor *= 13.605692 * 1.6021765e-19;
+	  types[WCSUNITS_MASS]   += 1.0;
+	  types[WCSUNITS_LENGTH] += 2.0;
+	  types[WCSUNITS_TIME]   -= 2.0;
+	  BEGIN(EXPON);
+	}
+	YY_BREAK
+case 92:
+YY_RULE_SETUP
+#line 731 "wcsulex.l"
+{
+	  /* Siemen. */
+	  types[WCSUNITS_MASS]   -= 1.0;
+	  types[WCSUNITS_LENGTH] -= 2.0;
+	  types[WCSUNITS_TIME]   += 1.0;
+	  types[WCSUNITS_CHARGE] += 2.0;
+	  BEGIN(EXPON);
+	}
+	YY_BREAK
+case 93:
+YY_RULE_SETUP
+#line 740 "wcsulex.l"
+{
+	  /* Second. */
+	  types[WCSUNITS_TIME] += 1.0;
+	  BEGIN(EXPON);
+	}
+	YY_BREAK
+case 94:
+YY_RULE_SETUP
+#line 746 "wcsulex.l"
+{
+	  /* Solar luminosity. */
+	  factor *= 3.8268e26;
+	  types[WCSUNITS_MASS]   += 1.0;
+	  types[WCSUNITS_LENGTH] += 2.0;
+	  types[WCSUNITS_TIME]   -= 3.0;
+	  BEGIN(EXPON);
+	}
+	YY_BREAK
+case 95:
+YY_RULE_SETUP
+#line 755 "wcsulex.l"
+{
+	  /* Solar mass. */
+	  factor *= 1.9891e30;
+	  types[WCSUNITS_MASS] += 1.0;
+	  BEGIN(EXPON);
+	}
+	YY_BREAK
+case 96:
+YY_RULE_SETUP
+#line 762 "wcsulex.l"
+{
+	  /* Solar radius. */
+	  factor *= 6.9599e8;
+	  types[WCSUNITS_LENGTH] += 1.0;
+	  BEGIN(EXPON);
+	}
+	YY_BREAK
+case 97:
+YY_RULE_SETUP
+#line 769 "wcsulex.l"
+{
+	  /* Steradian. */
+	  types[WCSUNITS_SOLID_ANGLE] += 1.0;
+	  BEGIN(EXPON);
+	}
+	YY_BREAK
+case 98:
+YY_RULE_SETUP
+#line 775 "wcsulex.l"
+{
+	  /* Sun (with respect to). */
+	  types[WCSUNITS_SOLRATIO] += 1.0;
+	  BEGIN(EXPON);
+	}
+	YY_BREAK
+case 99:
+YY_RULE_SETUP
+#line 781 "wcsulex.l"
+{
+	  /* Tesla. */
+	  types[WCSUNITS_MASS]   += 1.0;
+	  types[WCSUNITS_TIME]   += 1.0;
+	  types[WCSUNITS_CHARGE] -= 1.0;
+	  BEGIN(EXPON);
+	}
+	YY_BREAK
+case 100:
+YY_RULE_SETUP
+#line 789 "wcsulex.l"
+{
+	  /* Unified atomic mass unit. */
+	  factor *= 1.6605387e-27;
+	  types[WCSUNITS_MASS] += 1.0;
+	  BEGIN(EXPON);
+	}
+	YY_BREAK
+case 101:
+YY_RULE_SETUP
+#line 796 "wcsulex.l"
+{
+	  /* Volt. */
+	  types[WCSUNITS_MASS]   += 1.0;
+	  types[WCSUNITS_LENGTH] += 1.0;
+	  types[WCSUNITS_TIME]   -= 2.0;
+	  types[WCSUNITS_CHARGE] -= 1.0;
+	  BEGIN(EXPON);
+	}
+	YY_BREAK
+case 102:
+YY_RULE_SETUP
+#line 805 "wcsulex.l"
+{
+	  /* Voxel. */
+	  types[WCSUNITS_VOXEL] += 1.0;
+	  BEGIN(EXPON);
+	}
+	YY_BREAK
+case 103:
+YY_RULE_SETUP
+#line 811 "wcsulex.l"
+{
+	  /* Watt. */
+	  types[WCSUNITS_MASS]   += 1.0;
+	  types[WCSUNITS_LENGTH] += 2.0;
+	  types[WCSUNITS_TIME]   -= 3.0;
+	  BEGIN(EXPON);
+	}
+	YY_BREAK
+case 104:
+YY_RULE_SETUP
+#line 819 "wcsulex.l"
+{
+	  /* Weber. */
+	  types[WCSUNITS_MASS]   += 1.0;
+	  types[WCSUNITS_LENGTH] += 2.0;
+	  types[WCSUNITS_TIME]   += 1.0;
+	  types[WCSUNITS_CHARGE] -= 1.0;
+	  BEGIN(EXPON);
+	}
+	YY_BREAK
+case 105:
+YY_RULE_SETUP
+#line 828 "wcsulex.l"
+{
+	  /* Internal parser error. */
+	  status = wcserr_set(WCSERR_SET(UNITSERR_PARSER_ERROR),
+	    "Internal units parser error parsing '%s'", unitstr);
+	  BEGIN(FLUSH);
+	}
+	YY_BREAK
+case 106:
+YY_RULE_SETUP
+#line 835 "wcsulex.l"
+{
+	  /* Exponentiation. */
+	  if (operator++) {
+	    BEGIN(FLUSH);
+	  }
+	}
+	YY_BREAK
+case 107:
+YY_RULE_SETUP
+#line 842 "wcsulex.l"
+{
+	  sscanf(wcsulextext, " %d", &i);
+	  expon *= (double)i;
+	  add(&factor, types, &expon, scale, units);
+	  operator = 0;
+	  BEGIN(INITIAL);
+	}
+	YY_BREAK
+case 108:
+YY_RULE_SETUP
+#line 850 "wcsulex.l"
+{
+	  sscanf(wcsulextext, " (%d)", &i);
+	  expon *= (double)i;
+	  add(&factor, types, &expon, scale, units);
+	  operator = 0;
+	  BEGIN(INITIAL);
+	}
+	YY_BREAK
+case 109:
+YY_RULE_SETUP
+#line 858 "wcsulex.l"
+{
+	  sscanf(wcsulextext, " (%d/%d)", &i, &j);
+	  expon *= (double)i / (double)j;
+	  add(&factor, types, &expon, scale, units);
+	  operator = 0;
+	  BEGIN(INITIAL);
+	}
+	YY_BREAK
+case 110:
+YY_RULE_SETUP
+#line 866 "wcsulex.l"
+{
+	  sscanf(wcsulextext, " (%s)", ctmp);
+	  wcsutil_str2double(ctmp, "%lf", &dexp);
+	  expon *= dexp;
+	  add(&factor, types, &expon, scale, units);
+	  operator = 0;
+	  BEGIN(INITIAL);
+	}
+	YY_BREAK
+case 111:
+YY_RULE_SETUP
+#line 875 "wcsulex.l"
+{
+	  /* Multiply. */
+	  if (operator++) {
+	    BEGIN(FLUSH);
+	  } else {
+	    add(&factor, types, &expon, scale, units);
+	    BEGIN(INITIAL);
+	  }
+	}
+	YY_BREAK
+case 112:
+YY_RULE_SETUP
+#line 885 "wcsulex.l"
+{
+	  /* Multiply. */
+	  if (operator) {
+	    BEGIN(FLUSH);
+	  } else {
+	    add(&factor, types, &expon, scale, units);
+	    unput('(');
+	    BEGIN(INITIAL);
+	  }
+	}
+	YY_BREAK
+case 113:
+YY_RULE_SETUP
+#line 896 "wcsulex.l"
+{
+	  /* Multiply. */
+	  if (operator) {
+	    BEGIN(FLUSH);
+	  } else {
+	    add(&factor, types, &expon, scale, units);
+	    BEGIN(INITIAL);
+	  }
+	}
+	YY_BREAK
+case 114:
+YY_RULE_SETUP
+#line 906 "wcsulex.l"
+{
+	  /* Divide. */
+	  if (operator++) {
+	    BEGIN(FLUSH);
+	  } else {
+	    add(&factor, types, &expon, scale, units);
+	    expon = -1.0;
+	    BEGIN(INITIAL);
+	  }
+	}
+	YY_BREAK
+case 115:
+YY_RULE_SETUP
+#line 917 "wcsulex.l"
+{
+	  add(&factor, types, &expon, scale, units);
+	  bracket = !bracket;
+	  BEGIN(FLUSH);
+	}
+	YY_BREAK
+case 116:
+YY_RULE_SETUP
+#line 923 "wcsulex.l"
+{
+	  status = wcserr_set(WCSERR_SET(UNITSERR_BAD_EXPON_SYMBOL),
+	    "Invalid symbol in EXPON context in '%s'", unitstr);
+	  BEGIN(FLUSH);
+	}
+	YY_BREAK
+case 117:
+YY_RULE_SETUP
+#line 929 "wcsulex.l"
+{
+	  /* Discard any remaining input. */
+	}
+	YY_BREAK
+case YY_STATE_EOF(INITIAL):
+case YY_STATE_EOF(PAREN):
+case YY_STATE_EOF(PREFIX):
+case YY_STATE_EOF(UNITS):
+case YY_STATE_EOF(EXPON):
+case YY_STATE_EOF(FLUSH):
+#line 933 "wcsulex.l"
+{
+	  /* End-of-string. */
+	  if (YY_START == EXPON) {
+	    add(&factor, types, &expon, scale, units);
+	  }
+	
+	  wcsulexlex_destroy();
+	
+	  if (bracket) {
+	    status = wcserr_set(WCSERR_SET(UNITSERR_UNBAL_BRACKET),
+	      "Unbalanced bracket in '%s'", unitstr);
+	  } else if (paren) {
+	    status = wcserr_set(WCSERR_SET(UNITSERR_UNBAL_PAREN),
+	      "Unbalanced parenthesis in '%s'", unitstr);
+	  } else if (operator == 1) {
+	    status = wcserr_set(WCSERR_SET(UNITSERR_DANGLING_BINOP),
+	      "Dangling binary operator in '%s'", unitstr);
+	  } else if (operator) {
+	    status = wcserr_set(WCSERR_SET(UNITSERR_CONSEC_BINOPS),
+	      "Consecutive binary operators in '%s'", unitstr);
+#ifdef DEBUG
+	  } else {
+	    fprintf(stderr, "EOS\n");
+#endif
+	  }
+	
+	  if (status) {
+	    for (i = 0; i < WCSUNITS_NTYPE; i++) {
+	      units[i] = 0.0;
+	      *scale = 0.0;
+	    }
+	  }
+	
+	  return status;
+	}
+	YY_BREAK
+case 118:
+YY_RULE_SETUP
+#line 969 "wcsulex.l"
+ECHO;
+	YY_BREAK
+#line 8409 "wcsulex.c"
+
+	case YY_END_OF_BUFFER:
+		{
+		/* Amount of text matched not including the EOB char. */
+		int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;
+
+		/* Undo the effects of YY_DO_BEFORE_ACTION. */
+		*yy_cp = (yy_hold_char);
+		YY_RESTORE_YY_MORE_OFFSET
+
+		if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
+			{
+			/* We're scanning a new file or input source.  It's
+			 * possible that this happened because the user
+			 * just pointed wcsulexin at a new source and called
+			 * wcsulexlex().  If so, then we have to assure
+			 * consistency between YY_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.
+			 */
+			(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+			YY_CURRENT_BUFFER_LVALUE->yy_input_file = wcsulexin;
+			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
+			}
+
+		/* Note that here we test for yy_c_buf_p "<=" to the position
+		 * of the first EOB in the buffer, since yy_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 ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+			{ /* This was really a NUL. */
+			yy_state_type yy_next_state;
+
+			(yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;
+
+			yy_current_state = yy_get_previous_state(  );
+
+			/* Okay, we're now positioned to make the NUL
+			 * transition.  We couldn't have
+			 * yy_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).
+			 */
+
+			yy_next_state = yy_try_NUL_trans( yy_current_state );
+
+			yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+
+			if ( yy_next_state )
+				{
+				/* Consume the NUL. */
+				yy_cp = ++(yy_c_buf_p);
+				yy_current_state = yy_next_state;
+				goto yy_match;
+				}
+
+			else
+				{
+				yy_cp = (yy_c_buf_p);
+				goto yy_find_action;
+				}
+			}
+
+		else switch ( yy_get_next_buffer(  ) )
+			{
+			case EOB_ACT_END_OF_FILE:
+				{
+				(yy_did_buffer_switch_on_eof) = 0;
+
+				if ( wcsulexwrap( ) )
+					{
+					/* Note: because we've taken care in
+					 * yy_get_next_buffer() to have set up
+					 * wcsulextext, we can now set up
+					 * yy_c_buf_p so that if some total
+					 * hoser (like flex itself) wants to
+					 * call the scanner after we return the
+					 * YY_NULL, it'll still work - another
+					 * YY_NULL will get returned.
+					 */
+					(yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;
+
+					yy_act = YY_STATE_EOF(YY_START);
+					goto do_action;
+					}
+
+				else
+					{
+					if ( ! (yy_did_buffer_switch_on_eof) )
+						YY_NEW_FILE;
+					}
+				break;
+				}
+
+			case EOB_ACT_CONTINUE_SCAN:
+				(yy_c_buf_p) =
+					(yytext_ptr) + yy_amount_of_matched_text;
+
+				yy_current_state = yy_get_previous_state(  );
+
+				yy_cp = (yy_c_buf_p);
+				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+				goto yy_match;
+
+			case EOB_ACT_LAST_MATCH:
+				(yy_c_buf_p) =
+				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];
+
+				yy_current_state = yy_get_previous_state(  );
+
+				yy_cp = (yy_c_buf_p);
+				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+				goto yy_find_action;
+			}
+		break;
+		}
+
+	default:
+		YY_FATAL_ERROR(
+			"fatal flex scanner internal error--no action found" );
+	} /* end of action switch */
+		} /* end of scanning one token */
+} /* end of wcsulexlex */
+
+/* yy_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 yy_get_next_buffer (void)
+{
+    	register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+	register char *source = (yytext_ptr);
+	register int number_to_move, i;
+	int ret_val;
+
+	if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
+		YY_FATAL_ERROR(
+		"fatal flex scanner internal error--end of buffer missed" );
+
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
+		{ /* Don't try to fill the buffer, so this is an EOF. */
+		if ( (yy_c_buf_p) - (yytext_ptr) - YY_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) ((yy_c_buf_p) - (yytext_ptr)) - 1;
+
+	for ( i = 0; i < number_to_move; ++i )
+		*(dest++) = *(source++);
+
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+		/* don't do the read, it's not guaranteed to return an EOF,
+		 * just force an EOF
+		 */
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
+
+	else
+		{
+			int num_to_read =
+			YY_CURRENT_BUFFER_LVALUE->yy_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 */
+			YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
+
+			int yy_c_buf_p_offset =
+				(int) ((yy_c_buf_p) - b->yy_ch_buf);
+
+			if ( b->yy_is_our_buffer )
+				{
+				int new_size = b->yy_buf_size * 2;
+
+				if ( new_size <= 0 )
+					b->yy_buf_size += b->yy_buf_size / 8;
+				else
+					b->yy_buf_size *= 2;
+
+				b->yy_ch_buf = (char *)
+					/* Include room in for 2 EOB chars. */
+					wcsulexrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2  );
+				}
+			else
+				/* Can't grow it, we don't own it. */
+				b->yy_ch_buf = 0;
+
+			if ( ! b->yy_ch_buf )
+				YY_FATAL_ERROR(
+				"fatal error - scanner input buffer overflow" );
+
+			(yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+			num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
+						number_to_move - 1;
+
+			}
+
+		if ( num_to_read > YY_READ_BUF_SIZE )
+			num_to_read = YY_READ_BUF_SIZE;
+
+		/* Read in more data. */
+		YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+			(yy_n_chars), (size_t) num_to_read );
+
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+		}
+
+	if ( (yy_n_chars) == 0 )
+		{
+		if ( number_to_move == YY_MORE_ADJ )
+			{
+			ret_val = EOB_ACT_END_OF_FILE;
+			wcsulexrestart(wcsulexin  );
+			}
+
+		else
+			{
+			ret_val = EOB_ACT_LAST_MATCH;
+			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
+				YY_BUFFER_EOF_PENDING;
+			}
+		}
+
+	else
+		ret_val = EOB_ACT_CONTINUE_SCAN;
+
+	if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+		/* Extend the array by 50%, plus the number we really need. */
+		yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1);
+		YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) wcsulexrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size  );
+		if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+			YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+	}
+
+	(yy_n_chars) += number_to_move;
+	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
+	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
+
+	(yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+
+	return ret_val;
+}
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+    static yy_state_type yy_get_previous_state (void)
+{
+	register yy_state_type yy_current_state;
+	register char *yy_cp;
+    
+	yy_current_state = (yy_start);
+	yy_current_state += YY_AT_BOL();
+
+	for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
+		{
+		if ( *yy_cp )
+			{
+			yy_current_state = yy_nxt[yy_current_state][YY_SC_TO_UI(*yy_cp)];
+			}
+		else
+			yy_current_state = yy_NUL_trans[yy_current_state];
+		if ( yy_accept[yy_current_state] )
+			{
+			(yy_last_accepting_state) = yy_current_state;
+			(yy_last_accepting_cpos) = yy_cp;
+			}
+		}
+
+	return yy_current_state;
+}
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ *	next_state = yy_try_NUL_trans( current_state );
+ */
+    static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state )
+{
+	register int yy_is_jam;
+    	register char *yy_cp = (yy_c_buf_p);
+
+	yy_current_state = yy_NUL_trans[yy_current_state];
+	yy_is_jam = (yy_current_state == 0);
+
+	if ( ! yy_is_jam )
+		{
+		if ( yy_accept[yy_current_state] )
+			{
+			(yy_last_accepting_state) = yy_current_state;
+			(yy_last_accepting_cpos) = yy_cp;
+			}
+		}
+
+	return yy_is_jam ? 0 : yy_current_state;
+}
+
+    static void yyunput (int c, register char * yy_bp )
+{
+	register char *yy_cp;
+    
+    yy_cp = (yy_c_buf_p);
+
+	/* undo effects of setting up wcsulextext */
+	*yy_cp = (yy_hold_char);
+
+	if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+		{ /* need to shift things up to make room */
+		/* +2 for EOB chars. */
+		register int number_to_move = (yy_n_chars) + 2;
+		register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
+					YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
+		register char *source =
+				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
+
+		while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+			*--dest = *--source;
+
+		yy_cp += (int) (dest - source);
+		yy_bp += (int) (dest - source);
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars =
+			(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size;
+
+		if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+			YY_FATAL_ERROR( "flex scanner push-back overflow" );
+		}
+
+	*--yy_cp = (char) c;
+
+	(yytext_ptr) = yy_bp;
+	(yy_hold_char) = *yy_cp;
+	(yy_c_buf_p) = yy_cp;
+}
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+    static int yyinput (void)
+#else
+    static int input  (void)
+#endif
+
+{
+	int c;
+    
+	*(yy_c_buf_p) = (yy_hold_char);
+
+	if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
+		{
+		/* yy_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 ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+			/* This was really a NUL. */
+			*(yy_c_buf_p) = '\0';
+
+		else
+			{ /* need more input */
+			int offset = (yy_c_buf_p) - (yytext_ptr);
+			++(yy_c_buf_p);
+
+			switch ( yy_get_next_buffer(  ) )
+				{
+				case EOB_ACT_LAST_MATCH:
+					/* This happens because yy_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. */
+					wcsulexrestart(wcsulexin );
+
+					/*FALLTHROUGH*/
+
+				case EOB_ACT_END_OF_FILE:
+					{
+					if ( wcsulexwrap( ) )
+						return EOF;
+
+					if ( ! (yy_did_buffer_switch_on_eof) )
+						YY_NEW_FILE;
+#ifdef __cplusplus
+					return yyinput();
+#else
+					return input();
+#endif
+					}
+
+				case EOB_ACT_CONTINUE_SCAN:
+					(yy_c_buf_p) = (yytext_ptr) + offset;
+					break;
+				}
+			}
+		}
+
+	c = *(unsigned char *) (yy_c_buf_p);	/* cast for 8-bit char's */
+	*(yy_c_buf_p) = '\0';	/* preserve wcsulextext */
+	(yy_hold_char) = *++(yy_c_buf_p);
+
+	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = (c == '\n');
+
+	return c;
+}
+#endif	/* ifndef YY_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 wcsulexrestart  (FILE * input_file )
+{
+    
+	if ( ! YY_CURRENT_BUFFER ){
+        wcsulexensure_buffer_stack ();
+		YY_CURRENT_BUFFER_LVALUE =
+            wcsulex_create_buffer(wcsulexin,YY_BUF_SIZE );
+	}
+
+	wcsulex_init_buffer(YY_CURRENT_BUFFER,input_file );
+	wcsulex_load_buffer_state( );
+}
+
+/** Switch to a different input buffer.
+ * @param new_buffer The new input buffer.
+ * 
+ */
+    void wcsulex_switch_to_buffer  (YY_BUFFER_STATE  new_buffer )
+{
+    
+	/* TODO. We should be able to replace this entire function body
+	 * with
+	 *		wcsulexpop_buffer_state();
+	 *		wcsulexpush_buffer_state(new_buffer);
+     */
+	wcsulexensure_buffer_stack ();
+	if ( YY_CURRENT_BUFFER == new_buffer )
+		return;
+
+	if ( YY_CURRENT_BUFFER )
+		{
+		/* Flush out information for old buffer. */
+		*(yy_c_buf_p) = (yy_hold_char);
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+		}
+
+	YY_CURRENT_BUFFER_LVALUE = new_buffer;
+	wcsulex_load_buffer_state( );
+
+	/* We don't actually know whether we did this switch during
+	 * EOF (wcsulexwrap()) processing, but the only time this flag
+	 * is looked at is after wcsulexwrap() is called, so it's safe
+	 * to go ahead and always set it.
+	 */
+	(yy_did_buffer_switch_on_eof) = 1;
+}
+
+static void wcsulex_load_buffer_state  (void)
+{
+    	(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+	(yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+	wcsulexin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+	(yy_hold_char) = *(yy_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 YY_BUF_SIZE.
+ * 
+ * @return the allocated buffer state.
+ */
+    YY_BUFFER_STATE wcsulex_create_buffer  (FILE * file, int  size )
+{
+	YY_BUFFER_STATE b;
+    
+	b = (YY_BUFFER_STATE) wcsulexalloc(sizeof( struct yy_buffer_state )  );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in wcsulex_create_buffer()" );
+
+	b->yy_buf_size = size;
+
+	/* yy_ch_buf has to be 2 characters longer than the size given because
+	 * we need to put in 2 end-of-buffer characters.
+	 */
+	b->yy_ch_buf = (char *) wcsulexalloc(b->yy_buf_size + 2  );
+	if ( ! b->yy_ch_buf )
+		YY_FATAL_ERROR( "out of dynamic memory in wcsulex_create_buffer()" );
+
+	b->yy_is_our_buffer = 1;
+
+	wcsulex_init_buffer(b,file );
+
+	return b;
+}
+
+/** Destroy the buffer.
+ * @param b a buffer created with wcsulex_create_buffer()
+ * 
+ */
+    void wcsulex_delete_buffer (YY_BUFFER_STATE  b )
+{
+    
+	if ( ! b )
+		return;
+
+	if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+		YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
+
+	if ( b->yy_is_our_buffer )
+		wcsulexfree((void *) b->yy_ch_buf  );
+
+	wcsulexfree((void *) b  );
+}
+
+/* Initializes or reinitializes a buffer.
+ * This function is sometimes called more than once on the same buffer,
+ * such as during a wcsulexrestart() or at EOF.
+ */
+    static void wcsulex_init_buffer  (YY_BUFFER_STATE  b, FILE * file )
+
+{
+	int oerrno = errno;
+    
+	wcsulex_flush_buffer(b );
+
+	b->yy_input_file = file;
+	b->yy_fill_buffer = 1;
+
+    /* If b is the current buffer, then wcsulex_init_buffer was _probably_
+     * called from wcsulexrestart() or through yy_get_next_buffer.
+     * In that case, we don't want to reset the lineno or column.
+     */
+    if (b != YY_CURRENT_BUFFER){
+        b->yy_bs_lineno = 1;
+        b->yy_bs_column = 0;
+    }
+
+        b->yy_is_interactive = 0;
+    
+	errno = oerrno;
+}
+
+/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
+ * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
+ * 
+ */
+    void wcsulex_flush_buffer (YY_BUFFER_STATE  b )
+{
+    	if ( ! b )
+		return;
+
+	b->yy_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->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+	b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+	b->yy_buf_pos = &b->yy_ch_buf[0];
+
+	b->yy_at_bol = 1;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	if ( b == YY_CURRENT_BUFFER )
+		wcsulex_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 wcsulexpush_buffer_state (YY_BUFFER_STATE new_buffer )
+{
+    	if (new_buffer == NULL)
+		return;
+
+	wcsulexensure_buffer_stack();
+
+	/* This block is copied from wcsulex_switch_to_buffer. */
+	if ( YY_CURRENT_BUFFER )
+		{
+		/* Flush out information for old buffer. */
+		*(yy_c_buf_p) = (yy_hold_char);
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+		}
+
+	/* Only push if top exists. Otherwise, replace top. */
+	if (YY_CURRENT_BUFFER)
+		(yy_buffer_stack_top)++;
+	YY_CURRENT_BUFFER_LVALUE = new_buffer;
+
+	/* copied from wcsulex_switch_to_buffer. */
+	wcsulex_load_buffer_state( );
+	(yy_did_buffer_switch_on_eof) = 1;
+}
+
+/** Removes and deletes the top of the stack, if present.
+ *  The next element becomes the new top.
+ *  
+ */
+void wcsulexpop_buffer_state (void)
+{
+    	if (!YY_CURRENT_BUFFER)
+		return;
+
+	wcsulex_delete_buffer(YY_CURRENT_BUFFER );
+	YY_CURRENT_BUFFER_LVALUE = NULL;
+	if ((yy_buffer_stack_top) > 0)
+		--(yy_buffer_stack_top);
+
+	if (YY_CURRENT_BUFFER) {
+		wcsulex_load_buffer_state( );
+		(yy_did_buffer_switch_on_eof) = 1;
+	}
+}
+
+/* Allocates the stack if it does not exist.
+ *  Guarantees space for at least one push.
+ */
+static void wcsulexensure_buffer_stack (void)
+{
+	int num_to_alloc;
+    
+	if (!(yy_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;
+		(yy_buffer_stack) = (struct yy_buffer_state**)wcsulexalloc
+								(num_to_alloc * sizeof(struct yy_buffer_state*)
+								);
+		if ( ! (yy_buffer_stack) )
+			YY_FATAL_ERROR( "out of dynamic memory in wcsulexensure_buffer_stack()" );
+								  
+		memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+				
+		(yy_buffer_stack_max) = num_to_alloc;
+		(yy_buffer_stack_top) = 0;
+		return;
+	}
+
+	if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
+
+		/* Increase the buffer to prepare for a possible push. */
+		int grow_size = 8 /* arbitrary grow size */;
+
+		num_to_alloc = (yy_buffer_stack_max) + grow_size;
+		(yy_buffer_stack) = (struct yy_buffer_state**)wcsulexrealloc
+								((yy_buffer_stack),
+								num_to_alloc * sizeof(struct yy_buffer_state*)
+								);
+		if ( ! (yy_buffer_stack) )
+			YY_FATAL_ERROR( "out of dynamic memory in wcsulexensure_buffer_stack()" );
+
+		/* zero only the new slots.*/
+		memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
+		(yy_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. 
+ */
+YY_BUFFER_STATE wcsulex_scan_buffer  (char * base, yy_size_t  size )
+{
+	YY_BUFFER_STATE b;
+    
+	if ( size < 2 ||
+	     base[size-2] != YY_END_OF_BUFFER_CHAR ||
+	     base[size-1] != YY_END_OF_BUFFER_CHAR )
+		/* They forgot to leave room for the EOB's. */
+		return 0;
+
+	b = (YY_BUFFER_STATE) wcsulexalloc(sizeof( struct yy_buffer_state )  );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in wcsulex_scan_buffer()" );
+
+	b->yy_buf_size = size - 2;	/* "- 2" to take care of EOB's */
+	b->yy_buf_pos = b->yy_ch_buf = base;
+	b->yy_is_our_buffer = 0;
+	b->yy_input_file = 0;
+	b->yy_n_chars = b->yy_buf_size;
+	b->yy_is_interactive = 0;
+	b->yy_at_bol = 1;
+	b->yy_fill_buffer = 0;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	wcsulex_switch_to_buffer(b  );
+
+	return b;
+}
+
+/** Setup the input buffer state to scan a string. The next call to wcsulexlex() will
+ * scan from a @e copy of @a str.
+ * @param yystr 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
+ *       wcsulex_scan_bytes() instead.
+ */
+YY_BUFFER_STATE wcsulex_scan_string (yyconst char * yystr )
+{
+    
+	return wcsulex_scan_bytes(yystr,strlen(yystr) );
+}
+
+/** Setup the input buffer state to scan the given bytes. The next call to wcsulexlex() will
+ * scan from a @e copy of @a bytes.
+ * @param yybytes the byte buffer to scan
+ * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
+ * 
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE wcsulex_scan_bytes  (yyconst char * yybytes, int  _yybytes_len )
+{
+	YY_BUFFER_STATE b;
+	char *buf;
+	yy_size_t n;
+	int i;
+    
+	/* Get memory for full buffer, including space for trailing EOB's. */
+	n = _yybytes_len + 2;
+	buf = (char *) wcsulexalloc(n  );
+	if ( ! buf )
+		YY_FATAL_ERROR( "out of dynamic memory in wcsulex_scan_bytes()" );
+
+	for ( i = 0; i < _yybytes_len; ++i )
+		buf[i] = yybytes[i];
+
+	buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
+
+	b = wcsulex_scan_buffer(buf,n );
+	if ( ! b )
+		YY_FATAL_ERROR( "bad buffer in wcsulex_scan_bytes()" );
+
+	/* It's okay to grow etc. this buffer, and we should throw it
+	 * away when we're done.
+	 */
+	b->yy_is_our_buffer = 1;
+
+	return b;
+}
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+static void yy_fatal_error (yyconst char* msg )
+{
+    	(void) fprintf( stderr, "%s\n", msg );
+	exit( YY_EXIT_FAILURE );
+}
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up wcsulextext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+		wcsulextext[wcsulexleng] = (yy_hold_char); \
+		(yy_c_buf_p) = wcsulextext + yyless_macro_arg; \
+		(yy_hold_char) = *(yy_c_buf_p); \
+		*(yy_c_buf_p) = '\0'; \
+		wcsulexleng = yyless_macro_arg; \
+		} \
+	while ( 0 )
+
+/* Accessor  methods (get/set functions) to struct members. */
+
+/** Get the current line number.
+ * 
+ */
+int wcsulexget_lineno  (void)
+{
+        
+    return wcsulexlineno;
+}
+
+/** Get the input stream.
+ * 
+ */
+FILE *wcsulexget_in  (void)
+{
+        return wcsulexin;
+}
+
+/** Get the output stream.
+ * 
+ */
+FILE *wcsulexget_out  (void)
+{
+        return wcsulexout;
+}
+
+/** Get the length of the current token.
+ * 
+ */
+int wcsulexget_leng  (void)
+{
+        return wcsulexleng;
+}
+
+/** Get the current token.
+ * 
+ */
+
+char *wcsulexget_text  (void)
+{
+        return wcsulextext;
+}
+
+/** Set the current line number.
+ * @param line_number
+ * 
+ */
+void wcsulexset_lineno (int  line_number )
+{
+    
+    wcsulexlineno = line_number;
+}
+
+/** Set the input stream. This does not discard the current
+ * input buffer.
+ * @param in_str A readable stream.
+ * 
+ * @see wcsulex_switch_to_buffer
+ */
+void wcsulexset_in (FILE *  in_str )
+{
+        wcsulexin = in_str ;
+}
+
+void wcsulexset_out (FILE *  out_str )
+{
+        wcsulexout = out_str ;
+}
+
+int wcsulexget_debug  (void)
+{
+        return wcsulex_flex_debug;
+}
+
+void wcsulexset_debug (int  bdebug )
+{
+        wcsulex_flex_debug = bdebug ;
+}
+
+static int yy_init_globals (void)
+{
+        /* Initialization is the same as for the non-reentrant scanner.
+     * This function is called from wcsulexlex_destroy(), so don't allocate here.
+     */
+
+    (yy_buffer_stack) = 0;
+    (yy_buffer_stack_top) = 0;
+    (yy_buffer_stack_max) = 0;
+    (yy_c_buf_p) = (char *) 0;
+    (yy_init) = 0;
+    (yy_start) = 0;
+
+/* Defined in main.c */
+#ifdef YY_STDINIT
+    wcsulexin = stdin;
+    wcsulexout = stdout;
+#else
+    wcsulexin = (FILE *) 0;
+    wcsulexout = (FILE *) 0;
+#endif
+
+    /* For future reference: Set errno on error, since we are called by
+     * wcsulexlex_init()
+     */
+    return 0;
+}
+
+/* wcsulexlex_destroy is for both reentrant and non-reentrant scanners. */
+int wcsulexlex_destroy  (void)
+{
+    
+    /* Pop the buffer stack, destroying each element. */
+	while(YY_CURRENT_BUFFER){
+		wcsulex_delete_buffer(YY_CURRENT_BUFFER  );
+		YY_CURRENT_BUFFER_LVALUE = NULL;
+		wcsulexpop_buffer_state();
+	}
+
+	/* Destroy the stack itself. */
+	wcsulexfree((yy_buffer_stack) );
+	(yy_buffer_stack) = NULL;
+
+    /* Reset the globals. This is important in a non-reentrant scanner so the next time
+     * wcsulexlex() is called, initialization will occur. */
+    yy_init_globals( );
+
+    return 0;
+}
+
+/*
+ * Internal utility routines.
+ */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
+{
+	register int i;
+	for ( i = 0; i < n; ++i )
+		s1[i] = s2[i];
+}
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * s )
+{
+	register int n;
+	for ( n = 0; s[n]; ++n )
+		;
+
+	return n;
+}
+#endif
+
+void *wcsulexalloc (yy_size_t  size )
+{
+	return (void *) malloc( size );
+}
+
+void *wcsulexrealloc  (void * ptr, yy_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 wcsulexfree (void * ptr )
+{
+	free( (char *) ptr );	/* see wcsulexrealloc() for (char *) cast */
+}
+
+#define YYTABLES_NAME "yytables"
+
+#line 969 "wcsulex.l"
+
+
+
+/*----------------------------------------------------------------------------
+* Accumulate a term in a units specification and reset work variables.
+*---------------------------------------------------------------------------*/
+
+void add(
+  double *factor,
+  double types[],
+  double *expon,
+  double *scale,
+  double units[])
+
+{
+  int i;
+
+  *scale *= pow(*factor, *expon);
+
+  for (i = 0; i < WCSUNITS_NTYPE; i++) {
+    units[i] += *expon * types[i];
+    types[i] = 0.0;
+  }
+
+  *expon  = 1.0;
+  *factor = 1.0;
+
+  return;
+}
+
diff --git a/cextern/wcslib/C/flexed/wcsutrn.c b/cextern/wcslib/C/flexed/wcsutrn.c
new file mode 100644
index 0000000..c006451
--- /dev/null
+++ b/cextern/wcslib/C/flexed/wcsutrn.c
@@ -0,0 +1,5640 @@
+#line 2 "wcsutrn.c"
+
+#line 4 "wcsutrn.c"
+
+#define  YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define yy_create_buffer wcsutrn_create_buffer
+#define yy_delete_buffer wcsutrn_delete_buffer
+#define yy_flex_debug wcsutrn_flex_debug
+#define yy_init_buffer wcsutrn_init_buffer
+#define yy_flush_buffer wcsutrn_flush_buffer
+#define yy_load_buffer_state wcsutrn_load_buffer_state
+#define yy_switch_to_buffer wcsutrn_switch_to_buffer
+#define yyin wcsutrnin
+#define yyleng wcsutrnleng
+#define yylex wcsutrnlex
+#define yylineno wcsutrnlineno
+#define yyout wcsutrnout
+#define yyrestart wcsutrnrestart
+#define yytext wcsutrntext
+#define yywrap wcsutrnwrap
+#define yyalloc wcsutrnalloc
+#define yyrealloc wcsutrnrealloc
+#define yyfree wcsutrnfree
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+#define YY_FLEX_SUBMINOR_VERSION 35
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+/* First, we deal with  platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. 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 <inttypes.h>
+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;
+
+/* 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 /* ! C99 */
+
+#endif /* ! FLEXINT_H */
+
+#ifdef __cplusplus
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else	/* ! __cplusplus */
+
+/* C99 requires __STDC__ to be defined as 1. */
+#if defined (__STDC__)
+
+#define YY_USE_CONST
+
+#endif	/* defined (__STDC__) */
+#endif	/* ! __cplusplus */
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_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 YY_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 (yy_start) = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state.  The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START (((yy_start) - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE wcsutrnrestart(wcsutrnin  )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k.
+ * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
+ * Ditto for the __ia64__ case accordingly.
+ */
+#define YY_BUF_SIZE 32768
+#else
+#define YY_BUF_SIZE 16384
+#endif /* __ia64__ */
+#endif
+
+/* The state buf must be large enough to hold one state per character in the main buffer.
+ */
+#define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+extern int wcsutrnleng;
+
+extern FILE *wcsutrnin, *wcsutrnout;
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+#define YY_LESS_LINENO(n)
+    
+/* Return all but the first "n" matched characters back to the input stream. */
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up wcsutrntext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+		*yy_cp = (yy_hold_char); \
+		YY_RESTORE_YY_MORE_OFFSET \
+		(yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+		YY_DO_BEFORE_ACTION; /* set up wcsutrntext again */ \
+		} \
+	while ( 0 )
+
+#define unput(c) yyunput( c, (yytext_ptr)  )
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef size_t yy_size_t;
+#endif
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+	{
+	FILE *yy_input_file;
+
+	char *yy_ch_buf;		/* input buffer */
+	char *yy_buf_pos;		/* current position in input buffer */
+
+	/* Size of input buffer in bytes, not including room for EOB
+	 * characters.
+	 */
+	yy_size_t yy_buf_size;
+
+	/* Number of characters read into yy_ch_buf, not including EOB
+	 * characters.
+	 */
+	int yy_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 yy_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 yy_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 yy_at_bol;
+
+    int yy_bs_lineno; /**< The line count. */
+    int yy_bs_column; /**< The column count. */
+    
+	/* Whether to try to fill the input buffer when we reach the
+	 * end of it.
+	 */
+	int yy_fill_buffer;
+
+	int yy_buffer_status;
+
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+	/* When an EOF's been seen but there's still some text to process
+	 * then we mark the buffer as YY_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 wcsutrnrestart()), so that the user can continue scanning by
+	 * just pointing wcsutrnin at a new input file.
+	 */
+#define YY_BUFFER_EOF_PENDING 2
+
+	};
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+/* Stack of input buffers. */
+static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
+static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
+static YY_BUFFER_STATE * yy_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 YY_CURRENT_BUFFER ( (yy_buffer_stack) \
+                          ? (yy_buffer_stack)[(yy_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 YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
+
+/* yy_hold_char holds the character lost when wcsutrntext is formed. */
+static char yy_hold_char;
+static int yy_n_chars;		/* number of characters read into yy_ch_buf */
+int wcsutrnleng;
+
+/* Points to current character in buffer. */
+static char *yy_c_buf_p = (char *) 0;
+static int yy_init = 0;		/* whether we need to initialize */
+static int yy_start = 0;	/* start state number */
+
+/* Flag which is used to allow wcsutrnwrap()'s to do buffer switches
+ * instead of setting up a fresh wcsutrnin.  A bit of a hack ...
+ */
+static int yy_did_buffer_switch_on_eof;
+
+void wcsutrnrestart (FILE *input_file  );
+void wcsutrn_switch_to_buffer (YY_BUFFER_STATE new_buffer  );
+YY_BUFFER_STATE wcsutrn_create_buffer (FILE *file,int size  );
+void wcsutrn_delete_buffer (YY_BUFFER_STATE b  );
+void wcsutrn_flush_buffer (YY_BUFFER_STATE b  );
+void wcsutrnpush_buffer_state (YY_BUFFER_STATE new_buffer  );
+void wcsutrnpop_buffer_state (void );
+
+static void wcsutrnensure_buffer_stack (void );
+static void wcsutrn_load_buffer_state (void );
+static void wcsutrn_init_buffer (YY_BUFFER_STATE b,FILE *file  );
+
+#define YY_FLUSH_BUFFER wcsutrn_flush_buffer(YY_CURRENT_BUFFER )
+
+YY_BUFFER_STATE wcsutrn_scan_buffer (char *base,yy_size_t size  );
+YY_BUFFER_STATE wcsutrn_scan_string (yyconst char *yy_str  );
+YY_BUFFER_STATE wcsutrn_scan_bytes (yyconst char *bytes,int len  );
+
+void *wcsutrnalloc (yy_size_t  );
+void *wcsutrnrealloc (void *,yy_size_t  );
+void wcsutrnfree (void *  );
+
+#define yy_new_buffer wcsutrn_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+	{ \
+	if ( ! YY_CURRENT_BUFFER ){ \
+        wcsutrnensure_buffer_stack (); \
+		YY_CURRENT_BUFFER_LVALUE =    \
+            wcsutrn_create_buffer(wcsutrnin,YY_BUF_SIZE ); \
+	} \
+	YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+	}
+
+#define yy_set_bol(at_bol) \
+	{ \
+	if ( ! YY_CURRENT_BUFFER ){\
+        wcsutrnensure_buffer_stack (); \
+		YY_CURRENT_BUFFER_LVALUE =    \
+            wcsutrn_create_buffer(wcsutrnin,YY_BUF_SIZE ); \
+	} \
+	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+	}
+
+#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+
+/* Begin user sect3 */
+
+#define wcsutrnwrap(n) 1
+#define YY_SKIP_YYWRAP
+
+typedef char YY_CHAR;
+
+FILE *wcsutrnin = (FILE *) 0, *wcsutrnout = (FILE *) 0;
+
+typedef int yy_state_type;
+
+extern int wcsutrnlineno;
+
+int wcsutrnlineno = 1;
+
+extern char *wcsutrntext;
+#define yytext_ptr wcsutrntext
+static yyconst flex_int16_t yy_nxt[][128] =
+    {
+    {
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+
+        0,    0,    0,    0,    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,    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,    9,    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,   10,   11,   12,   13,   12,
+
+       12,   14,   15,   12,   16,   17,   12,   18,   12,   19,
+       20,   12,   21,   22,   12,   12,   23,   12,   12,   24,
+       12,    8,    8,    8,    8,    8,    8,   25,   12,   12,
+       26,   12,   12,   12,   27,   12,   12,   28,   12,   29,
+       12,   12,   30,   12,   31,   32,   12,   12,   33,   12,
+       12,   34,   12,    8,    8,    8,    8,    8
+    },
+
+    {
+        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,   35,    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,   10,   11,   12,   13,   12,
+       12,   14,   15,   12,   16,   17,   12,   18,   12,   19,
+       20,   12,   21,   22,   12,   12,   23,   12,   12,   24,
+       12,   36,    8,    8,    8,    8,    8,   25,   12,   12,
+       26,   12,   12,   12,   27,   12,   12,   28,   12,   29,
+       12,   12,   30,   12,   31,   32,   12,   12,   33,   12,
+       12,   34,   12,    8,    8,    8,    8,    8
+    },
+
+    {
+        7,   37,   37,   37,   37,   37,   37,   37,   37,   37,
+
+       38,   37,   37,   37,   37,   37,   37,   37,   37,   37,
+       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
+       37,   37,   39,   37,   37,   37,   37,   37,   37,   37,
+       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
+       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
+       37,   37,   37,   37,   37,   40,   40,   40,   40,   40,
+       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
+       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
+       40,   37,   37,   37,   37,   37,   37,   40,   40,   40,
+       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
+
+       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
+       40,   40,   40,   37,   37,   37,   37,   37
+    },
+
+    {
+        7,   37,   37,   37,   37,   37,   37,   37,   37,   37,
+       38,   37,   37,   37,   37,   37,   37,   37,   37,   37,
+       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
+       37,   37,   39,   37,   37,   37,   37,   37,   37,   37,
+       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
+       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
+       37,   37,   37,   37,   37,   40,   40,   40,   40,   40,
+       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
+
+       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
+       40,   37,   37,   37,   37,   37,   37,   40,   40,   40,
+       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
+       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
+       40,   40,   40,   37,   37,   37,   37,   37
+    },
+
+    {
+        7,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+       38,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+
+       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+       41,   41,   41,   41,   41,   41,   41,   41
+    },
+
+    {
+        7,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+       38,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+
+       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+       41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+
+       41,   41,   41,   41,   41,   41,   41,   41
+    },
+
+    {
+       -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,   -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
+    },
+
+    {
+        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
+    },
+
+    {
+        7,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,
+       -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,
+       -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,
+
+       -9,   -9,   42,   -9,   -9,   -9,   -9,   -9,   -9,   -9,
+       -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,
+       -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,
+       -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,
+       -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,
+       -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,
+       -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,
+       -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,
+       -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9,
+       -9,   -9,   -9,   -9,   -9,   -9,   -9,   -9
+
+    },
+
+    {
+        7,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,
+      -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,
+      -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,
+      -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,
+      -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,
+      -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,  -10,
+      -10,  -10,  -10,  -10,  -10,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   44,   43,   43,   43,   43,   43,   43,   43,
+       43,  -10,  -10,  -10,  -10,  -10,  -10,   43,   43,   43,
+
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  -10,  -10,  -10,  -10,  -10
+    },
+
+    {
+        7,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,
+      -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,
+      -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,
+      -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,
+      -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,
+      -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,
+      -11,  -11,  -11,  -11,  -11,   43,   43,   43,   43,   45,
+
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,  -11,  -11,  -11,  -11,  -11,  -11,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   46,   43,  -11,  -11,  -11,  -11,  -11
+    },
+
+    {
+        7,  -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,  -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,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,  -12,  -12,  -12,  -12,  -12,  -12,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  -12,  -12,  -12,  -12,  -12
+    },
+
+    {
+        7,  -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,  -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,   47,   43,   43,   43,   48,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,  -13,  -13,  -13,  -13,  -13,  -13,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  -13,  -13,  -13,  -13,  -13
+    },
+
+    {
+        7,  -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,   43,   43,   43,   43,   43,
+       43,   43,   49,   43,   43,   43,   43,   43,   43,   43,
+
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,  -14,  -14,  -14,  -14,  -14,  -14,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  -14,  -14,  -14,  -14,  -14
+    },
+
+    {
+        7,  -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,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   50,   43,   43,   43,   43,   43,   43,   43,
+       51,  -15,  -15,  -15,  -15,  -15,  -15,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  -15,  -15,  -15,  -15,  -15
+    },
+
+    {
+        7,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
+      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
+
+      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
+      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
+      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
+      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
+      -16,  -16,  -16,  -16,  -16,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   52,
+       43,  -16,  -16,  -16,  -16,  -16,  -16,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43,   43,   43,  -16,  -16,  -16,  -16,  -16
+    },
+
+    {
+        7,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
+      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
+      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
+      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
+      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
+      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
+      -17,  -17,  -17,  -17,  -17,   43,   43,   43,   43,   53,
+       43,   43,   54,   43,   43,   43,   43,   55,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43,  -17,  -17,  -17,  -17,  -17,  -17,   43,   43,   43,
+       43,   56,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  -17,  -17,  -17,  -17,  -17
+    },
+
+    {
+        7,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,
+      -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,
+      -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,
+      -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,
+      -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,
+      -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,
+
+      -18,  -18,  -18,  -18,  -18,   43,   43,   43,   43,   57,
+       43,   43,   58,   59,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,  -18,  -18,  -18,  -18,  -18,  -18,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  -18,  -18,  -18,  -18,  -18
+    },
+
+    {
+        7,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,
+      -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,
+      -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,
+
+      -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,
+      -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,
+      -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,
+      -19,  -19,  -19,  -19,  -19,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,  -19,  -19,  -19,  -19,  -19,  -19,   43,   43,   43,
+       43,   43,   43,   43,   60,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  -19,  -19,  -19,  -19,  -19
+
+    },
+
+    {
+        7,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,
+      -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,
+      -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,
+      -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,
+      -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,
+      -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,
+      -20,  -20,  -20,  -20,  -20,   61,   43,   43,   43,   43,
+       43,   43,   43,   62,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,  -20,  -20,  -20,  -20,  -20,  -20,   63,   43,   43,
+
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  -20,  -20,  -20,  -20,  -20
+    },
+
+    {
+        7,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,
+      -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,
+      -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,
+      -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,
+      -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,
+      -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,
+      -21,  -21,  -21,  -21,  -21,   64,   43,   43,   43,   43,
+
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,  -21,  -21,  -21,  -21,  -21,  -21,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  -21,  -21,  -21,  -21,  -21
+    },
+
+    {
+        7,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,
+      -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,
+      -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,
+      -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,
+
+      -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,
+      -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,
+      -22,  -22,  -22,  -22,  -22,   43,   43,   43,   43,   65,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,  -22,  -22,  -22,  -22,  -22,  -22,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  -22,  -22,  -22,  -22,  -22
+    },
+
+    {
+        7,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
+
+      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
+      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
+      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
+      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
+      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
+      -23,  -23,  -23,  -23,  -23,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   66,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,  -23,  -23,  -23,  -23,  -23,  -23,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43,   67,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  -23,  -23,  -23,  -23,  -23
+    },
+
+    {
+        7,  -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,  -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,   43,   43,   43,   43,   68,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43,   43,   69,   43,   43,   43,   43,   43,   43,   43,
+       43,  -24,  -24,  -24,  -24,  -24,  -24,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  -24,  -24,  -24,  -24,  -24
+    },
+
+    {
+        7,  -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,  -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,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,  -25,  -25,  -25,  -25,  -25,  -25,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       70,   43,   43,   43,   71,   43,   43,   43,   43,   43,
+       43,   43,   43,  -25,  -25,  -25,  -25,  -25
+    },
+
+    {
+        7,  -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,  -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,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,  -26,  -26,  -26,  -26,  -26,  -26,   72,   43,   43,
+       43,   73,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43,   43,   43,  -26,  -26,  -26,  -26,  -26
+    },
+
+    {
+        7,  -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,  -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,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43,  -27,  -27,  -27,  -27,  -27,  -27,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   50,   43,   43,   43,   43,   43,
+       43,   43,   51,  -27,  -27,  -27,  -27,  -27
+    },
+
+    {
+        7,  -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,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,  -28,  -28,  -28,  -28,  -28,  -28,   43,   43,   43,
+       43,   56,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  -28,  -28,  -28,  -28,  -28
+    },
+
+    {
+        7,  -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,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,  -29,  -29,  -29,  -29,  -29,  -29,   43,   43,   43,
+       43,   74,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  -29,  -29,  -29,  -29,  -29
+
+    },
+
+    {
+        7,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
+      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
+      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
+      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
+      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
+      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
+      -30,  -30,  -30,  -30,  -30,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,  -30,  -30,  -30,  -30,  -30,  -30,   63,   43,   43,
+
+       43,   43,   43,   43,   43,   75,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  -30,  -30,  -30,  -30,  -30
+    },
+
+    {
+        7,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
+      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
+      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
+      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
+      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
+      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
+      -31,  -31,  -31,  -31,  -31,   43,   43,   43,   43,   43,
+
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,  -31,  -31,  -31,  -31,  -31,  -31,   76,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  -31,  -31,  -31,  -31,  -31
+    },
+
+    {
+        7,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
+      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
+      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
+      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
+
+      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
+      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
+      -32,  -32,  -32,  -32,  -32,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,  -32,  -32,  -32,  -32,  -32,  -32,   43,   43,   43,
+       43,   77,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  -32,  -32,  -32,  -32,  -32
+    },
+
+    {
+        7,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
+
+      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
+      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
+      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
+      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
+      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
+      -33,  -33,  -33,  -33,  -33,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,  -33,  -33,  -33,  -33,  -33,  -33,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43,   67,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  -33,  -33,  -33,  -33,  -33
+    },
+
+    {
+        7,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
+      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
+      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
+      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
+      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
+      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
+      -34,  -34,  -34,  -34,  -34,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,  -34,  -34,  -34,  -34,  -34,  -34,   43,   43,   43,
+       43,   78,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  -34,  -34,  -34,  -34,  -34
+    },
+
+    {
+        7,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
+      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
+      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
+      -35,  -35,   79,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
+      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
+
+      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
+      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
+      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
+      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
+      -35,   80,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
+      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
+      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
+      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35
+    },
+
+    {
+        7,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
+      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
+
+      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
+      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
+      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
+      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
+      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
+      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
+      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
+      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
+      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
+      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
+
+      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36
+    },
+
+    {
+        7,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37
+    },
+
+    {
+        7,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
+      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
+      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
+      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
+      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
+      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
+
+      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
+      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
+      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
+      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
+      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
+      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
+      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38
+    },
+
+    {
+        7,   81,   81,   81,   81,   81,   81,   81,   81,   81,
+       81,   81,   81,   81,   81,   81,   81,   81,   81,   81,
+       81,   81,   81,   81,   81,   81,   81,   81,   81,   81,
+
+       81,   81,   82,   81,   81,   81,   81,   81,   81,   81,
+       81,   81,   81,   81,   81,   81,   81,   81,   81,   81,
+       81,   81,   81,   81,   81,   81,   81,   81,   81,   81,
+       81,   81,   81,   81,   81,   83,   83,   83,   83,   83,
+       83,   83,   83,   83,   83,   83,   83,   83,   83,   83,
+       83,   83,   83,   83,   83,   83,   83,   83,   83,   83,
+       83,   81,   81,   81,   81,   81,   81,   83,   83,   83,
+       83,   83,   83,   83,   83,   83,   83,   83,   83,   83,
+       83,   83,   83,   83,   83,   83,   83,   83,   83,   83,
+       83,   83,   83,   81,   81,   81,   81,   81
+
+    },
+
+    {
+        7,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
+      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
+      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
+      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
+      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
+      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
+      -40,  -40,  -40,  -40,  -40,   84,   84,   84,   84,   84,
+       84,   84,   84,   84,   84,   84,   84,   84,   84,   84,
+       84,   84,   84,   84,   84,   84,   84,   84,   84,   84,
+       84,  -40,  -40,  -40,  -40,  -40,  -40,   84,   84,   84,
+
+       84,   84,   84,   84,   84,   84,   84,   84,   84,   84,
+       84,   84,   84,   84,   84,   84,   84,   84,   84,   84,
+       84,   84,   84,  -40,  -40,  -40,  -40,  -40
+    },
+
+    {
+        7,   85,   85,   85,   85,   85,   85,   85,   85,   85,
+      -41,   85,   85,   85,   85,   85,   85,   85,   85,   85,
+       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
+       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
+       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
+       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
+       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
+
+       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
+       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
+       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
+       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
+       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
+       85,   85,   85,   85,   85,   85,   85,   85
+    },
+
+    {
+        7,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
+      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
+      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
+      -42,  -42,   42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
+
+      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
+      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
+      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
+      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
+      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
+      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
+      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
+      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
+      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42
+    },
+
+    {
+        7,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
+
+      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
+      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
+      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
+      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
+      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
+      -43,  -43,  -43,  -43,  -43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,  -43,  -43,  -43,  -43,  -43,  -43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  -43,  -43,  -43,  -43,  -43
+    },
+
+    {
+        7,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
+      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
+      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
+      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
+      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
+      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
+      -44,  -44,  -44,  -44,  -44,   43,   43,   86,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,  -44,  -44,  -44,  -44,  -44,  -44,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  -44,  -44,  -44,  -44,  -44
+    },
+
+    {
+        7,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
+      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
+      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
+      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
+      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
+
+      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
+      -45,  -45,  -45,  -45,  -45,   87,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,  -45,  -45,  -45,  -45,  -45,  -45,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  -45,  -45,  -45,  -45,  -45
+    },
+
+    {
+        7,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
+      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
+
+      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
+      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
+      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
+      -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
+      -46,  -46,  -46,  -46,  -46,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,  -46,  -46,  -46,  -46,  -46,  -46,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   88,   43,   43,   43,
+
+       43,   43,   43,  -46,  -46,  -46,  -46,  -46
+    },
+
+    {
+        7,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
+      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
+      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
+      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
+      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
+      -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
+      -47,  -47,  -47,  -47,  -47,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   89,
+
+       43,  -47,  -47,  -47,  -47,  -47,  -47,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  -47,  -47,  -47,  -47,  -47
+    },
+
+    {
+        7,  -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,   43,   43,   43,   43,   43,
+       43,   90,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,  -48,  -48,  -48,  -48,  -48,  -48,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  -48,  -48,  -48,  -48,  -48
+    },
+
+    {
+        7,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
+      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
+      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
+
+      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
+      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
+      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
+      -49,  -49,  -49,  -49,  -49,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       91,  -49,  -49,  -49,  -49,  -49,  -49,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  -49,  -49,  -49,  -49,  -49
+
+    },
+
+    {
+        7,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
+      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
+      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
+      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
+      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
+      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
+      -50,  -50,  -50,  -50,  -50,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,  -50,  -50,  -50,  -50,  -50,  -50,   43,   43,   43,
+
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  -50,  -50,  -50,  -50,  -50
+    },
+
+    {
+        7,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
+      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
+      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
+      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
+      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
+      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
+      -51,  -51,  -51,  -51,  -51,   43,   43,   43,   43,   43,
+
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,  -51,  -51,  -51,  -51,  -51,  -51,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  -51,  -51,  -51,  -51,  -51
+    },
+
+    {
+        7,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
+      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
+      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
+      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
+
+      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
+      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
+      -52,  -52,  -52,  -52,  -52,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,  -52,  -52,  -52,  -52,  -52,  -52,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  -52,  -52,  -52,  -52,  -52
+    },
+
+    {
+        7,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+      -53,  -53,  -53,  -53,  -53,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   92,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,  -53,  -53,  -53,  -53,  -53,  -53,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  -53,  -53,  -53,  -53,  -53
+    },
+
+    {
+        7,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
+      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
+      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
+      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
+      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
+      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
+      -54,  -54,  -54,  -54,  -54,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       93,  -54,  -54,  -54,  -54,  -54,  -54,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  -54,  -54,  -54,  -54,  -54
+    },
+
+    {
+        7,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
+      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
+      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
+      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
+      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
+
+      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
+      -55,  -55,  -55,  -55,  -55,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,  -55,  -55,  -55,  -55,  -55,  -55,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  -55,  -55,  -55,  -55,  -55
+    },
+
+    {
+        7,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
+      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
+
+      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
+      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
+      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
+      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
+      -56,  -56,  -56,  -56,  -56,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,  -56,  -56,  -56,  -56,  -56,  -56,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   94,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43,   43,   43,  -56,  -56,  -56,  -56,  -56
+    },
+
+    {
+        7,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
+      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
+      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
+      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
+      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
+      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
+      -57,  -57,  -57,  -57,  -57,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   95,   43,   43,   43,   43,   43,
+
+       43,  -57,  -57,  -57,  -57,  -57,  -57,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  -57,  -57,  -57,  -57,  -57
+    },
+
+    {
+        7,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
+      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
+      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
+      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
+      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
+      -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
+
+      -58,  -58,  -58,  -58,  -58,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       96,  -58,  -58,  -58,  -58,  -58,  -58,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  -58,  -58,  -58,  -58,  -58
+    },
+
+    {
+        7,  -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,  -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,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   97,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,  -59,  -59,  -59,  -59,  -59,  -59,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  -59,  -59,  -59,  -59,  -59
+
+    },
+
+    {
+        7,  -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,
+      -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,
+      -60,  -60,  -60,  -60,  -60,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,  -60,  -60,  -60,  -60,  -60,  -60,   43,   43,   43,
+
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   98,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  -60,  -60,  -60,  -60,  -60
+    },
+
+    {
+        7,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
+      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
+      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
+      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
+      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
+      -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
+      -61,  -61,  -61,  -61,  -61,   43,   43,   43,   43,   43,
+
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   99,   43,   43,   43,   43,   43,   43,
+       43,  -61,  -61,  -61,  -61,  -61,  -61,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  -61,  -61,  -61,  -61,  -61
+    },
+
+    {
+        7,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
+      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
+      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
+      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
+
+      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
+      -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
+      -62,  -62,  -62,  -62,  -62,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,  100,   43,
+       43,  -62,  -62,  -62,  -62,  -62,  -62,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  -62,  -62,  -62,  -62,  -62
+    },
+
+    {
+        7,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
+
+      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
+      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
+      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
+      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
+      -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
+      -63,  -63,  -63,  -63,  -63,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,  -63,  -63,  -63,  -63,  -63,  -63,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43,   43,   43,   43,   43,  101,   43,   43,   43,   43,
+       43,   43,   43,  -63,  -63,  -63,  -63,  -63
+    },
+
+    {
+        7,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
+      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
+      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
+      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
+      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
+      -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
+      -64,  -64,  -64,  -64,  -64,   43,   43,   43,  102,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,  -64,  -64,  -64,  -64,  -64,  -64,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  -64,  -64,  -64,  -64,  -64
+    },
+
+    {
+        7,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
+      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
+      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
+      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
+      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
+
+      -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
+      -65,  -65,  -65,  -65,  -65,   43,   43,  103,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,  -65,  -65,  -65,  -65,  -65,  -65,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  -65,  -65,  -65,  -65,  -65
+    },
+
+    {
+        7,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
+      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
+
+      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
+      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
+      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
+      -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
+      -66,  -66,  -66,  -66,  -66,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,  104,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,  -66,  -66,  -66,  -66,  -66,  -66,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43,   43,   43,  -66,  -66,  -66,  -66,  -66
+    },
+
+    {
+        7,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+      -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+      -67,  -67,  -67,  -67,  -67,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43,  -67,  -67,  -67,  -67,  -67,  -67,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,  105,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  -67,  -67,  -67,  -67,  -67
+    },
+
+    {
+        7,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+      -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+
+      -68,  -68,  -68,  -68,  -68,  106,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,  -68,  -68,  -68,  -68,  -68,  -68,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  -68,  -68,  -68,  -68,  -68
+    },
+
+    {
+        7,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
+      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
+      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
+
+      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
+      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
+      -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
+      -69,  -69,  -69,  -69,  -69,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,  -69,  -69,  -69,  -69,  -69,  -69,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  -69,  -69,  -69,  -69,  -69
+
+    },
+
+    {
+        7,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
+      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
+      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
+      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
+      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
+      -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
+      -70,  -70,  -70,  -70,  -70,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,  -70,  -70,  -70,  -70,  -70,  -70,   43,   43,   43,
+
+       43,   43,   43,  107,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  -70,  -70,  -70,  -70,  -70
+    },
+
+    {
+        7,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
+      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
+      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
+      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
+      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
+      -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
+      -71,  -71,  -71,  -71,  -71,   43,   43,   43,   43,   43,
+
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,  -71,  -71,  -71,  -71,  -71,  -71,   43,   43,  108,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  -71,  -71,  -71,  -71,  -71
+    },
+
+    {
+        7,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
+      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
+      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
+      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
+
+      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
+      -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
+      -72,  -72,  -72,  -72,  -72,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,  -72,  -72,  -72,  -72,  -72,  -72,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,  109,   43,  -72,  -72,  -72,  -72,  -72
+    },
+
+    {
+        7,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
+
+      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
+      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
+      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
+      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
+      -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
+      -73,  -73,  -73,  -73,  -73,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,  -73,  -73,  -73,  -73,  -73,  -73,   43,   43,   43,
+       43,   43,   43,  110,   43,   43,   43,   43,   43,   43,
+
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  -73,  -73,  -73,  -73,  -73
+    },
+
+    {
+        7,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
+      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
+      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
+      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
+      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
+      -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
+      -74,  -74,  -74,  -74,  -74,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,  -74,  -74,  -74,  -74,  -74,  -74,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,  111,   43,   43,   43,
+       43,   43,   43,  -74,  -74,  -74,  -74,  -74
+    },
+
+    {
+        7,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
+      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
+      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
+      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
+      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
+
+      -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
+      -75,  -75,  -75,  -75,  -75,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,  -75,  -75,  -75,  -75,  -75,  -75,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+      112,   43,   43,  -75,  -75,  -75,  -75,  -75
+    },
+
+    {
+        7,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
+      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
+
+      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
+      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
+      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
+      -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
+      -76,  -76,  -76,  -76,  -76,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,  -76,  -76,  -76,  -76,  -76,  -76,   43,   43,   43,
+      113,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43,   43,   43,  -76,  -76,  -76,  -76,  -76
+    },
+
+    {
+        7,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
+      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
+      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
+      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
+      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
+      -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,  -77,
+      -77,  -77,  -77,  -77,  -77,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43,  -77,  -77,  -77,  -77,  -77,  -77,   43,   43,  114,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  -77,  -77,  -77,  -77,  -77
+    },
+
+    {
+        7,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
+      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
+      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
+      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
+      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
+      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
+
+      -78,  -78,  -78,  -78,  -78,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,  -78,  -78,  -78,  -78,  -78,  -78,  115,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  -78,  -78,  -78,  -78,  -78
+    },
+
+    {
+        7,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
+      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
+      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
+
+      -79,  -79,   79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
+      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
+      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
+      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
+      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
+      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
+      -79,   80,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
+      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
+      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79,
+      -79,  -79,  -79,  -79,  -79,  -79,  -79,  -79
+
+    },
+
+    {
+        7,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
+      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
+      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
+      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
+      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
+      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
+      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
+      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
+      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
+      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
+
+      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
+      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
+      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80
+    },
+
+    {
+        7,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
+      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
+      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
+      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
+      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
+      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
+      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
+
+      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
+      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
+      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
+      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
+      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81,
+      -81,  -81,  -81,  -81,  -81,  -81,  -81,  -81
+    },
+
+    {
+        7,   81,   81,   81,   81,   81,   81,   81,   81,   81,
+       81,   81,   81,   81,   81,   81,   81,   81,   81,   81,
+       81,   81,   81,   81,   81,   81,   81,   81,   81,   81,
+       81,   81,   82,   81,   81,   81,   81,   81,   81,   81,
+
+       81,   81,   81,   81,   81,   81,   81,   81,   81,   81,
+       81,   81,   81,   81,   81,   81,   81,   81,   81,   81,
+       81,   81,   81,   81,   81,   83,   83,   83,   83,   83,
+       83,   83,   83,   83,   83,   83,   83,   83,   83,   83,
+       83,   83,   83,   83,   83,   83,   83,   83,   83,   83,
+       83,   81,   81,   81,   81,   81,   81,   83,   83,   83,
+       83,   83,   83,   83,   83,   83,   83,   83,   83,   83,
+       83,   83,   83,   83,   83,   83,   83,   83,   83,   83,
+       83,   83,   83,   81,   81,   81,   81,   81
+    },
+
+    {
+        7,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
+
+      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
+      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
+      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
+      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
+      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
+      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
+      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
+      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
+      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
+      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
+
+      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
+      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83
+    },
+
+    {
+        7,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
+      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
+      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
+      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
+      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
+      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
+      -84,  -84,  -84,  -84,  -84,   84,   84,   84,   84,   84,
+       84,   84,   84,   84,   84,   84,   84,   84,   84,   84,
+
+       84,   84,   84,   84,   84,   84,   84,   84,   84,   84,
+       84,  -84,  -84,  -84,  -84,  -84,  -84,   84,   84,   84,
+       84,   84,   84,   84,   84,   84,   84,   84,   84,   84,
+       84,   84,   84,   84,   84,   84,   84,   84,   84,   84,
+       84,   84,   84,  -84,  -84,  -84,  -84,  -84
+    },
+
+    {
+        7,   85,   85,   85,   85,   85,   85,   85,   85,   85,
+      -85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
+       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
+       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
+       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
+
+       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
+       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
+       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
+       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
+       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
+       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
+       85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
+       85,   85,   85,   85,   85,   85,   85,   85
+    },
+
+    {
+        7,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
+      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
+
+      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
+      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
+      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
+      -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,  -86,
+      -86,  -86,  -86,  -86,  -86,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,  116,   43,   43,
+       43,   43,   43,  117,   43,   43,   43,   43,   43,   43,
+       43,  -86,  -86,  -86,  -86,  -86,  -86,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43,   43,   43,  -86,  -86,  -86,  -86,  -86
+    },
+
+    {
+        7,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+      -87,  -87,  -87,  -87,  -87,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,  118,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43,  -87,  -87,  -87,  -87,  -87,  -87,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  -87,  -87,  -87,  -87,  -87
+    },
+
+    {
+        7,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
+      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
+      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
+      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
+      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
+      -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
+
+      -88,  -88,  -88,  -88,  -88,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,  -88,  -88,  -88,  -88,  -88,  -88,   43,   43,   43,
+       43,  119,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  -88,  -88,  -88,  -88,  -88
+    },
+
+    {
+        7,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
+      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
+      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
+
+      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
+      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
+      -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
+      -89,  -89,  -89,  -89,  -89,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  120,   43,   43,   43,   43,   43,   43,
+       43,  -89,  -89,  -89,  -89,  -89,  -89,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  -89,  -89,  -89,  -89,  -89
+
+    },
+
+    {
+        7,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
+      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
+      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
+      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
+      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
+      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
+      -90,  -90,  -90,  -90,  -90,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,  121,   43,   43,   43,   43,   43,   43,   43,
+       43,  -90,  -90,  -90,  -90,  -90,  -90,   43,   43,   43,
+
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  -90,  -90,  -90,  -90,  -90
+    },
+
+    {
+        7,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+      -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+      -91,  -91,  -91,  -91,  -91,   43,   43,   43,   43,   43,
+
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,  -91,  -91,  -91,  -91,  -91,  -91,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  -91,  -91,  -91,  -91,  -91
+    },
+
+    {
+        7,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
+      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
+      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
+      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
+
+      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
+      -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
+      -92,  -92,  -92,  -92,  -92,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,  122,   43,   43,   43,
+       43,  -92,  -92,  -92,  -92,  -92,  -92,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  -92,  -92,  -92,  -92,  -92
+    },
+
+    {
+        7,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+
+      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+      -93,  -93,  -93,  -93,  -93,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,  -93,  -93,  -93,  -93,  -93,  -93,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  -93,  -93,  -93,  -93,  -93
+    },
+
+    {
+        7,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
+      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
+      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
+      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
+      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
+      -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
+      -94,  -94,  -94,  -94,  -94,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,  -94,  -94,  -94,  -94,  -94,  -94,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,  123,   43,
+       43,   43,   43,  -94,  -94,  -94,  -94,  -94
+    },
+
+    {
+        7,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
+      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
+      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
+      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
+      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
+
+      -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
+      -95,  -95,  -95,  -95,  -95,   43,   43,   43,   43,  124,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,  125,   43,   43,   43,   43,   43,   43,   43,
+       43,  -95,  -95,  -95,  -95,  -95,  -95,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  -95,  -95,  -95,  -95,  -95
+    },
+
+    {
+        7,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
+      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
+
+      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
+      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
+      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
+      -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
+      -96,  -96,  -96,  -96,  -96,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,  -96,  -96,  -96,  -96,  -96,  -96,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43,   43,   43,  -96,  -96,  -96,  -96,  -96
+    },
+
+    {
+        7,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
+      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
+      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
+      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
+      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
+      -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
+      -97,  -97,  -97,  -97,  -97,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43,  -97,  -97,  -97,  -97,  -97,  -97,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  -97,  -97,  -97,  -97,  -97
+    },
+
+    {
+        7,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
+      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
+      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
+      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
+      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
+      -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
+
+      -98,  -98,  -98,  -98,  -98,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,  -98,  -98,  -98,  -98,  -98,  -98,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  -98,  -98,  -98,  -98,  -98
+    },
+
+    {
+        7,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
+      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
+      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
+
+      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
+      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
+      -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
+      -99,  -99,  -99,  -99,  -99,   43,   43,  126,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,  -99,  -99,  -99,  -99,  -99,  -99,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  -99,  -99,  -99,  -99,  -99
+
+    },
+
+    {
+        7, -100, -100, -100, -100, -100, -100, -100, -100, -100,
+     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
+     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
+     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
+     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
+     -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
+     -100, -100, -100, -100, -100,   43,   43,   43,   43,  127,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -100, -100, -100, -100, -100, -100,   43,   43,   43,
+
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -100, -100, -100, -100, -100
+    },
+
+    {
+        7, -101, -101, -101, -101, -101, -101, -101, -101, -101,
+     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
+     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
+     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
+     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
+     -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
+     -101, -101, -101, -101, -101,   43,   43,   43,   43,   43,
+
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -101, -101, -101, -101, -101, -101,   43,   43,  128,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -101, -101, -101, -101, -101
+    },
+
+    {
+        7, -102, -102, -102, -102, -102, -102, -102, -102, -102,
+     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
+     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
+     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
+
+     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
+     -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
+     -102, -102, -102, -102, -102,   43,   43,   43,   43,   43,
+       43,   43,   43,  129,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -102, -102, -102, -102, -102, -102,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -102, -102, -102, -102, -102
+    },
+
+    {
+        7, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+
+     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+     -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+     -103, -103, -103, -103, -103,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,  130,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -103, -103, -103, -103, -103, -103,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -103, -103, -103, -103, -103
+    },
+
+    {
+        7, -104, -104, -104, -104, -104, -104, -104, -104, -104,
+     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
+     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
+     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
+     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
+     -104, -104, -104, -104, -104, -104, -104, -104, -104, -104,
+     -104, -104, -104, -104, -104,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43,   43,   43,   43,  131,   43,   43,   43,   43,   43,
+       43, -104, -104, -104, -104, -104, -104,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -104, -104, -104, -104, -104
+    },
+
+    {
+        7, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+
+     -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+     -105, -105, -105, -105, -105,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -105, -105, -105, -105, -105, -105,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,  132,   43,   43,   43,
+       43,   43,   43, -105, -105, -105, -105, -105
+    },
+
+    {
+        7, -106, -106, -106, -106, -106, -106, -106, -106, -106,
+     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
+
+     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
+     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
+     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
+     -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
+     -106, -106, -106, -106, -106,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,  133,   43,   43,   43,   43,   43,   43,   43,
+       43, -106, -106, -106, -106, -106, -106,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43,   43,   43, -106, -106, -106, -106, -106
+    },
+
+    {
+        7, -107, -107, -107, -107, -107, -107, -107, -107, -107,
+     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
+     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
+     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
+     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
+     -107, -107, -107, -107, -107, -107, -107, -107, -107, -107,
+     -107, -107, -107, -107, -107,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43, -107, -107, -107, -107, -107, -107,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,  134,   43,   43,   43,   43,
+       43,   43,   43, -107, -107, -107, -107, -107
+    },
+
+    {
+        7, -108, -108, -108, -108, -108, -108, -108, -108, -108,
+     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
+     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
+     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
+     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
+     -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
+
+     -108, -108, -108, -108, -108,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -108, -108, -108, -108, -108, -108,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,  135,
+       43,   43,   43,   43,   43,  136,   43,   43,   43,   43,
+       43,   43,   43, -108, -108, -108, -108, -108
+    },
+
+    {
+        7, -109, -109, -109, -109, -109, -109, -109, -109, -109,
+     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
+     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
+
+     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
+     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
+     -109, -109, -109, -109, -109, -109, -109, -109, -109, -109,
+     -109, -109, -109, -109, -109,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -109, -109, -109, -109, -109, -109,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,  137,   43,   43,   43,   43,
+       43,   43,   43, -109, -109, -109, -109, -109
+
+    },
+
+    {
+        7, -110, -110, -110, -110, -110, -110, -110, -110, -110,
+     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
+     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
+     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
+     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
+     -110, -110, -110, -110, -110, -110, -110, -110, -110, -110,
+     -110, -110, -110, -110, -110,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -110, -110, -110, -110, -110, -110,   43,   43,   43,
+
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,  138,   43,   43,   43,   43,   43,
+       43,   43,   43, -110, -110, -110, -110, -110
+    },
+
+    {
+        7, -111, -111, -111, -111, -111, -111, -111, -111, -111,
+     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
+     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
+     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
+     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
+     -111, -111, -111, -111, -111, -111, -111, -111, -111, -111,
+     -111, -111, -111, -111, -111,   43,   43,   43,   43,   43,
+
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -111, -111, -111, -111, -111, -111,   43,   43,   43,
+       43,  139,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,  140,   43,   43,   43,   43,   43,
+       43,   43,   43, -111, -111, -111, -111, -111
+    },
+
+    {
+        7, -112, -112, -112, -112, -112, -112, -112, -112, -112,
+     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
+     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
+     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
+
+     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
+     -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
+     -112, -112, -112, -112, -112,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -112, -112, -112, -112, -112, -112,   43,   43,   43,
+       43,  141,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -112, -112, -112, -112, -112
+    },
+
+    {
+        7, -113, -113, -113, -113, -113, -113, -113, -113, -113,
+
+     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
+     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
+     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
+     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
+     -113, -113, -113, -113, -113, -113, -113, -113, -113, -113,
+     -113, -113, -113, -113, -113,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -113, -113, -113, -113, -113, -113,   43,   43,   43,
+       43,   43,   43,   43,   43,  142,   43,   43,   43,   43,
+
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -113, -113, -113, -113, -113
+    },
+
+    {
+        7, -114, -114, -114, -114, -114, -114, -114, -114, -114,
+     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
+     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
+     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
+     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
+     -114, -114, -114, -114, -114, -114, -114, -114, -114, -114,
+     -114, -114, -114, -114, -114,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -114, -114, -114, -114, -114, -114,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,  143,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -114, -114, -114, -114, -114
+    },
+
+    {
+        7, -115, -115, -115, -115, -115, -115, -115, -115, -115,
+     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
+     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
+     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
+     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
+
+     -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
+     -115, -115, -115, -115, -115,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -115, -115, -115, -115, -115, -115,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,  144,   43,   43,   43,   43,   43,
+       43,   43,   43, -115, -115, -115, -115, -115
+    },
+
+    {
+        7, -116, -116, -116, -116, -116, -116, -116, -116, -116,
+     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
+
+     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
+     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
+     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
+     -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
+     -116, -116, -116, -116, -116,   43,   43,   43,   43,   43,
+       43,   43,   43,  145,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -116, -116, -116, -116, -116, -116,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43,   43,   43, -116, -116, -116, -116, -116
+    },
+
+    {
+        7, -117, -117, -117, -117, -117, -117, -117, -117, -117,
+     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
+     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
+     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
+     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
+     -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
+     -117, -117, -117, -117, -117,   43,   43,   43,   43,  146,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43, -117, -117, -117, -117, -117, -117,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -117, -117, -117, -117, -117
+    },
+
+    {
+        7, -118, -118, -118, -118, -118, -118, -118, -118, -118,
+     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
+     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
+     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
+     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
+     -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
+
+     -118, -118, -118, -118, -118,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -118, -118, -118, -118, -118, -118,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -118, -118, -118, -118, -118
+    },
+
+    {
+        7, -119, -119, -119, -119, -119, -119, -119, -119, -119,
+     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
+     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
+
+     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
+     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
+     -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
+     -119, -119, -119, -119, -119,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -119, -119, -119, -119, -119, -119,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -119, -119, -119, -119, -119
+
+    },
+
+    {
+        7, -120, -120, -120, -120, -120, -120, -120, -120, -120,
+     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
+     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
+     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
+     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
+     -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
+     -120, -120, -120, -120, -120,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -120, -120, -120, -120, -120, -120,   43,   43,   43,
+
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -120, -120, -120, -120, -120
+    },
+
+    {
+        7, -121, -121, -121, -121, -121, -121, -121, -121, -121,
+     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
+     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
+     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
+     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
+     -121, -121, -121, -121, -121, -121, -121, -121, -121, -121,
+     -121, -121, -121, -121, -121,   43,   43,   43,   43,  147,
+
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -121, -121, -121, -121, -121, -121,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -121, -121, -121, -121, -121
+    },
+
+    {
+        7, -122, -122, -122, -122, -122, -122, -122, -122, -122,
+     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
+     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
+     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
+
+     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
+     -122, -122, -122, -122, -122, -122, -122, -122, -122, -122,
+     -122, -122, -122, -122, -122,   43,   43,   43,   43,   43,
+       43,   43,   43,  148,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -122, -122, -122, -122, -122, -122,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -122, -122, -122, -122, -122
+    },
+
+    {
+        7, -123, -123, -123, -123, -123, -123, -123, -123, -123,
+
+     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
+     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
+     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
+     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
+     -123, -123, -123, -123, -123, -123, -123, -123, -123, -123,
+     -123, -123, -123, -123, -123,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -123, -123, -123, -123, -123, -123,   43,   43,   43,
+       43,   43,   43,   43,   43,  149,   43,   43,   43,   43,
+
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -123, -123, -123, -123, -123
+    },
+
+    {
+        7, -124, -124, -124, -124, -124, -124, -124, -124, -124,
+     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
+     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
+     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
+     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
+     -124, -124, -124, -124, -124, -124, -124, -124, -124, -124,
+     -124, -124, -124, -124, -124,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43,   43,  150,   43,   43,   43,   43,   43,   43,   43,
+       43, -124, -124, -124, -124, -124, -124,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -124, -124, -124, -124, -124
+    },
+
+    {
+        7, -125, -125, -125, -125, -125, -125, -125, -125, -125,
+     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
+     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
+     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
+     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
+
+     -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
+     -125, -125, -125, -125, -125,   43,   43,   43,   43,  151,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -125, -125, -125, -125, -125, -125,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -125, -125, -125, -125, -125
+    },
+
+    {
+        7, -126, -126, -126, -126, -126, -126, -126, -126, -126,
+     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
+
+     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
+     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
+     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
+     -126, -126, -126, -126, -126, -126, -126, -126, -126, -126,
+     -126, -126, -126, -126, -126,  152,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -126, -126, -126, -126, -126, -126,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43,   43,   43, -126, -126, -126, -126, -126
+    },
+
+    {
+        7, -127, -127, -127, -127, -127, -127, -127, -127, -127,
+     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
+     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
+     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
+     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
+     -127, -127, -127, -127, -127, -127, -127, -127, -127, -127,
+     -127, -127, -127, -127, -127,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,  153,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43, -127, -127, -127, -127, -127, -127,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -127, -127, -127, -127, -127
+    },
+
+    {
+        7, -128, -128, -128, -128, -128, -128, -128, -128, -128,
+     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
+     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
+     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
+     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
+     -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
+
+     -128, -128, -128, -128, -128,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -128, -128, -128, -128, -128, -128,  154,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -128, -128, -128, -128, -128
+    },
+
+    {
+        7, -129, -129, -129, -129, -129, -129, -129, -129, -129,
+     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
+     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
+
+     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
+     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
+     -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
+     -129, -129, -129, -129, -129,  155,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -129, -129, -129, -129, -129, -129,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -129, -129, -129, -129, -129
+
+    },
+
+    {
+        7, -130, -130, -130, -130, -130, -130, -130, -130, -130,
+     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
+     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
+     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
+     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
+     -130, -130, -130, -130, -130, -130, -130, -130, -130, -130,
+     -130, -130, -130, -130, -130,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,  156,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -130, -130, -130, -130, -130, -130,   43,   43,   43,
+
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -130, -130, -130, -130, -130
+    },
+
+    {
+        7, -131, -131, -131, -131, -131, -131, -131, -131, -131,
+     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
+     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
+     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
+     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
+     -131, -131, -131, -131, -131, -131, -131, -131, -131, -131,
+     -131, -131, -131, -131, -131,   43,   43,   43,   43,   43,
+
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  157,   43,   43,   43,   43,   43,   43,
+       43, -131, -131, -131, -131, -131, -131,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -131, -131, -131, -131, -131
+    },
+
+    {
+        7, -132, -132, -132, -132, -132, -132, -132, -132, -132,
+     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
+     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
+     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
+
+     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
+     -132, -132, -132, -132, -132, -132, -132, -132, -132, -132,
+     -132, -132, -132, -132, -132,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -132, -132, -132, -132, -132, -132,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,  158,   43,   43,   43,   43,
+       43,   43,   43, -132, -132, -132, -132, -132
+    },
+
+    {
+        7, -133, -133, -133, -133, -133, -133, -133, -133, -133,
+
+     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
+     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
+     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
+     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
+     -133, -133, -133, -133, -133, -133, -133, -133, -133, -133,
+     -133, -133, -133, -133, -133,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  159,   43,   43,   43,   43,   43,   43,
+       43, -133, -133, -133, -133, -133, -133,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -133, -133, -133, -133, -133
+    },
+
+    {
+        7, -134, -134, -134, -134, -134, -134, -134, -134, -134,
+     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
+     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
+     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
+     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
+     -134, -134, -134, -134, -134, -134, -134, -134, -134, -134,
+     -134, -134, -134, -134, -134,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -134, -134, -134, -134, -134, -134,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,  160,   43,   43,   43,
+       43,   43,   43, -134, -134, -134, -134, -134
+    },
+
+    {
+        7, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+
+     -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+     -135, -135, -135, -135, -135,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -135, -135, -135, -135, -135, -135,   43,   43,   43,
+       43,   43,   43,   43,   43,  161,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -135, -135, -135, -135, -135
+    },
+
+    {
+        7, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+
+     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+     -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+     -136, -136, -136, -136, -136,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -136, -136, -136, -136, -136, -136,   43,   43,   43,
+       43,  162,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43,   43,   43, -136, -136, -136, -136, -136
+    },
+
+    {
+        7, -137, -137, -137, -137, -137, -137, -137, -137, -137,
+     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
+     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
+     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
+     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
+     -137, -137, -137, -137, -137, -137, -137, -137, -137, -137,
+     -137, -137, -137, -137, -137,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43, -137, -137, -137, -137, -137, -137,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -137, -137, -137, -137, -137
+    },
+
+    {
+        7, -138, -138, -138, -138, -138, -138, -138, -138, -138,
+     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
+     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
+     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
+     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
+     -138, -138, -138, -138, -138, -138, -138, -138, -138, -138,
+
+     -138, -138, -138, -138, -138,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -138, -138, -138, -138, -138, -138,   43,   43,   43,
+       43,  163,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -138, -138, -138, -138, -138
+    },
+
+    {
+        7, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+
+     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+     -139, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+     -139, -139, -139, -139, -139,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -139, -139, -139, -139, -139, -139,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,  164,   43,   43,   43,   43,   43,
+       43,   43,   43, -139, -139, -139, -139, -139
+
+    },
+
+    {
+        7, -140, -140, -140, -140, -140, -140, -140, -140, -140,
+     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
+     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
+     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
+     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
+     -140, -140, -140, -140, -140, -140, -140, -140, -140, -140,
+     -140, -140, -140, -140, -140,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -140, -140, -140, -140, -140, -140,   43,   43,   43,
+
+       43,  165,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -140, -140, -140, -140, -140
+    },
+
+    {
+        7, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+     -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+     -141, -141, -141, -141, -141,   43,   43,   43,   43,   43,
+
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -141, -141, -141, -141, -141, -141,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,  166,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -141, -141, -141, -141, -141
+    },
+
+    {
+        7, -142, -142, -142, -142, -142, -142, -142, -142, -142,
+     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
+     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
+     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
+
+     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
+     -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
+     -142, -142, -142, -142, -142,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -142, -142, -142, -142, -142, -142,  167,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -142, -142, -142, -142, -142
+    },
+
+    {
+        7, -143, -143, -143, -143, -143, -143, -143, -143, -143,
+
+     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
+     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
+     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
+     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
+     -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
+     -143, -143, -143, -143, -143,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -143, -143, -143, -143, -143, -143,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+      168,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -143, -143, -143, -143, -143
+    },
+
+    {
+        7, -144, -144, -144, -144, -144, -144, -144, -144, -144,
+     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
+     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
+     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
+     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
+     -144, -144, -144, -144, -144, -144, -144, -144, -144, -144,
+     -144, -144, -144, -144, -144,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -144, -144, -144, -144, -144, -144,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   69,   43,   43,   43,   43,
+       43,   43,   43, -144, -144, -144, -144, -144
+    },
+
+    {
+        7, -145, -145, -145, -145, -145, -145, -145, -145, -145,
+     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
+     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
+     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
+     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
+
+     -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
+     -145, -145, -145, -145, -145,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,  169,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -145, -145, -145, -145, -145, -145,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -145, -145, -145, -145, -145
+    },
+
+    {
+        7, -146, -146, -146, -146, -146, -146, -146, -146, -146,
+     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
+
+     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
+     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
+     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
+     -146, -146, -146, -146, -146, -146, -146, -146, -146, -146,
+     -146, -146, -146, -146, -146,   43,   43,  170,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -146, -146, -146, -146, -146, -146,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43,   43,   43, -146, -146, -146, -146, -146
+    },
+
+    {
+        7, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+     -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+     -147, -147, -147, -147, -147,   43,   43,   43,   43,  171,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43, -147, -147, -147, -147, -147, -147,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -147, -147, -147, -147, -147
+    },
+
+    {
+        7, -148, -148, -148, -148, -148, -148, -148, -148, -148,
+     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
+     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
+     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
+     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
+     -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
+
+     -148, -148, -148, -148, -148,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,  172,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -148, -148, -148, -148, -148, -148,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -148, -148, -148, -148, -148
+    },
+
+    {
+        7, -149, -149, -149, -149, -149, -149, -149, -149, -149,
+     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
+     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
+
+     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
+     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
+     -149, -149, -149, -149, -149, -149, -149, -149, -149, -149,
+     -149, -149, -149, -149, -149,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -149, -149, -149, -149, -149, -149,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+      173,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -149, -149, -149, -149, -149
+
+    },
+
+    {
+        7, -150, -150, -150, -150, -150, -150, -150, -150, -150,
+     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
+     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
+     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
+     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
+     -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
+     -150, -150, -150, -150, -150,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  174,   43,   43,   43,   43,   43,   43,
+       43, -150, -150, -150, -150, -150, -150,   43,   43,   43,
+
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -150, -150, -150, -150, -150
+    },
+
+    {
+        7, -151, -151, -151, -151, -151, -151, -151, -151, -151,
+     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
+     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
+     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
+     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
+     -151, -151, -151, -151, -151, -151, -151, -151, -151, -151,
+     -151, -151, -151, -151, -151,   43,   43,   43,   43,   43,
+
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  175,   43,   43,   43,   43,   43,   43,
+       43, -151, -151, -151, -151, -151, -151,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -151, -151, -151, -151, -151
+    },
+
+    {
+        7, -152, -152, -152, -152, -152, -152, -152, -152, -152,
+     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
+     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
+     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
+
+     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
+     -152, -152, -152, -152, -152, -152, -152, -152, -152, -152,
+     -152, -152, -152, -152, -152,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,  176,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -152, -152, -152, -152, -152, -152,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -152, -152, -152, -152, -152
+    },
+
+    {
+        7, -153, -153, -153, -153, -153, -153, -153, -153, -153,
+
+     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
+     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
+     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
+     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
+     -153, -153, -153, -153, -153, -153, -153, -153, -153, -153,
+     -153, -153, -153, -153, -153,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  177,   43,   43,   43,   43,   43,   43,
+       43, -153, -153, -153, -153, -153, -153,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -153, -153, -153, -153, -153
+    },
+
+    {
+        7, -154, -154, -154, -154, -154, -154, -154, -154, -154,
+     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
+     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
+     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
+     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
+     -154, -154, -154, -154, -154, -154, -154, -154, -154, -154,
+     -154, -154, -154, -154, -154,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -154, -154, -154, -154, -154, -154,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,  178,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -154, -154, -154, -154, -154
+    },
+
+    {
+        7, -155, -155, -155, -155, -155, -155, -155, -155, -155,
+     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
+     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
+     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
+     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
+
+     -155, -155, -155, -155, -155, -155, -155, -155, -155, -155,
+     -155, -155, -155, -155, -155,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,  179,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -155, -155, -155, -155, -155, -155,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -155, -155, -155, -155, -155
+    },
+
+    {
+        7, -156, -156, -156, -156, -156, -156, -156, -156, -156,
+     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
+
+     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
+     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
+     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
+     -156, -156, -156, -156, -156, -156, -156, -156, -156, -156,
+     -156, -156, -156, -156, -156,   43,   43,   43,  180,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -156, -156, -156, -156, -156, -156,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43,   43,   43, -156, -156, -156, -156, -156
+    },
+
+    {
+        7, -157, -157, -157, -157, -157, -157, -157, -157, -157,
+     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
+     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
+     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
+     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
+     -157, -157, -157, -157, -157, -157, -157, -157, -157, -157,
+     -157, -157, -157, -157, -157,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43, -157, -157, -157, -157, -157, -157,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -157, -157, -157, -157, -157
+    },
+
+    {
+        7, -158, -158, -158, -158, -158, -158, -158, -158, -158,
+     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
+     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
+     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
+     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
+     -158, -158, -158, -158, -158, -158, -158, -158, -158, -158,
+
+     -158, -158, -158, -158, -158,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -158, -158, -158, -158, -158, -158,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -158, -158, -158, -158, -158
+    },
+
+    {
+        7, -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, -159, -159, -159,
+     -159, -159, -159, -159, -159,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -159, -159, -159, -159, -159, -159,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -159, -159, -159, -159, -159
+
+    },
+
+    {
+        7, -160, -160, -160, -160, -160, -160, -160, -160, -160,
+     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
+     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
+     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
+     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
+     -160, -160, -160, -160, -160, -160, -160, -160, -160, -160,
+     -160, -160, -160, -160, -160,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -160, -160, -160, -160, -160, -160,   43,   43,   43,
+
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,  181,   43,   43,   43,   43,   43,
+       43,   43,   43, -160, -160, -160, -160, -160
+    },
+
+    {
+        7, -161, -161, -161, -161, -161, -161, -161, -161, -161,
+     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
+     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
+     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
+     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
+     -161, -161, -161, -161, -161, -161, -161, -161, -161, -161,
+     -161, -161, -161, -161, -161,   43,   43,   43,   43,   43,
+
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -161, -161, -161, -161, -161, -161,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+      182,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -161, -161, -161, -161, -161
+    },
+
+    {
+        7, -162, -162, -162, -162, -162, -162, -162, -162, -162,
+     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
+     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
+     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
+
+     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
+     -162, -162, -162, -162, -162, -162, -162, -162, -162, -162,
+     -162, -162, -162, -162, -162,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -162, -162, -162, -162, -162, -162,   43,   43,  183,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -162, -162, -162, -162, -162
+    },
+
+    {
+        7, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+
+     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+     -163, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+     -163, -163, -163, -163, -163,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -163, -163, -163, -163, -163, -163,   43,   43,   43,
+       43,  184,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -163, -163, -163, -163, -163
+    },
+
+    {
+        7, -164, -164, -164, -164, -164, -164, -164, -164, -164,
+     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
+     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
+     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
+     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
+     -164, -164, -164, -164, -164, -164, -164, -164, -164, -164,
+     -164, -164, -164, -164, -164,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -164, -164, -164, -164, -164, -164,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,  185,   43,   43,   43,   43,
+       43,   43,   43, -164, -164, -164, -164, -164
+    },
+
+    {
+        7, -165, -165, -165, -165, -165, -165, -165, -165, -165,
+     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
+     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
+     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
+     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
+
+     -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
+     -165, -165, -165, -165, -165,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -165, -165, -165, -165, -165, -165,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,  186,   43,   43,   43,   43,
+       43,   43,   43, -165, -165, -165, -165, -165
+    },
+
+    {
+        7, -166, -166, -166, -166, -166, -166, -166, -166, -166,
+     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
+
+     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
+     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
+     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
+     -166, -166, -166, -166, -166, -166, -166, -166, -166, -166,
+     -166, -166, -166, -166, -166,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -166, -166, -166, -166, -166, -166,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,  177,   43,   43,   43,   43,
+
+       43,   43,   43, -166, -166, -166, -166, -166
+    },
+
+    {
+        7, -167, -167, -167, -167, -167, -167, -167, -167, -167,
+     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
+     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
+     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
+     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
+     -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
+     -167, -167, -167, -167, -167,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43, -167, -167, -167, -167, -167, -167,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+      187,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -167, -167, -167, -167, -167
+    },
+
+    {
+        7, -168, -168, -168, -168, -168, -168, -168, -168, -168,
+     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
+     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
+     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
+     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
+     -168, -168, -168, -168, -168, -168, -168, -168, -168, -168,
+
+     -168, -168, -168, -168, -168,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -168, -168, -168, -168, -168, -168,   43,   43,   43,
+      188,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -168, -168, -168, -168, -168
+    },
+
+    {
+        7, -169, -169, -169, -169, -169, -169, -169, -169, -169,
+     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
+     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
+
+     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
+     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
+     -169, -169, -169, -169, -169, -169, -169, -169, -169, -169,
+     -169, -169, -169, -169, -169,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  189,   43,   43,   43,   43,   43,   43,
+       43, -169, -169, -169, -169, -169, -169,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -169, -169, -169, -169, -169
+
+    },
+
+    {
+        7, -170, -170, -170, -170, -170, -170, -170, -170, -170,
+     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
+     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
+     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
+     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
+     -170, -170, -170, -170, -170, -170, -170, -170, -170, -170,
+     -170, -170, -170, -170, -170,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  190,   43,   43,   43,   43,   43,   43,
+       43, -170, -170, -170, -170, -170, -170,   43,   43,   43,
+
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -170, -170, -170, -170, -170
+    },
+
+    {
+        7, -171, -171, -171, -171, -171, -171, -171, -171, -171,
+     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
+     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
+     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
+     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
+     -171, -171, -171, -171, -171, -171, -171, -171, -171, -171,
+     -171, -171, -171, -171, -171,   43,   43,   43,   43,   43,
+
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  191,   43,   43,   43,   43,   43,   43,
+       43, -171, -171, -171, -171, -171, -171,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -171, -171, -171, -171, -171
+    },
+
+    {
+        7, -172, -172, -172, -172, -172, -172, -172, -172, -172,
+     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
+     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
+     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
+
+     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
+     -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
+     -172, -172, -172, -172, -172,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  192,   43,   43,   43,   43,   43,   43,
+       43, -172, -172, -172, -172, -172, -172,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -172, -172, -172, -172, -172
+    },
+
+    {
+        7, -173, -173, -173, -173, -173, -173, -173, -173, -173,
+
+     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
+     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
+     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
+     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
+     -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
+     -173, -173, -173, -173, -173,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -173, -173, -173, -173, -173, -173,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43,   43,   43,   43,   43,  193,   43,   43,   43,   43,
+       43,   43,   43, -173, -173, -173, -173, -173
+    },
+
+    {
+        7, -174, -174, -174, -174, -174, -174, -174, -174, -174,
+     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
+     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
+     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
+     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
+     -174, -174, -174, -174, -174, -174, -174, -174, -174, -174,
+     -174, -174, -174, -174, -174,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -174, -174, -174, -174, -174, -174,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -174, -174, -174, -174, -174
+    },
+
+    {
+        7, -175, -175, -175, -175, -175, -175, -175, -175, -175,
+     -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
+     -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
+     -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
+     -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
+
+     -175, -175, -175, -175, -175, -175, -175, -175, -175, -175,
+     -175, -175, -175, -175, -175,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -175, -175, -175, -175, -175, -175,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -175, -175, -175, -175, -175
+    },
+
+    {
+        7, -176, -176, -176, -176, -176, -176, -176, -176, -176,
+     -176, -176, -176, -176, -176, -176, -176, -176, -176, -176,
+
+     -176, -176, -176, -176, -176, -176, -176, -176, -176, -176,
+     -176, -176, -176, -176, -176, -176, -176, -176, -176, -176,
+     -176, -176, -176, -176, -176, -176, -176, -176, -176, -176,
+     -176, -176, -176, -176, -176, -176, -176, -176, -176, -176,
+     -176, -176, -176, -176, -176,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  194,   43,   43,   43,   43,   43,   43,
+       43, -176, -176, -176, -176, -176, -176,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43,   43,   43, -176, -176, -176, -176, -176
+    },
+
+    {
+        7, -177, -177, -177, -177, -177, -177, -177, -177, -177,
+     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
+     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
+     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
+     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
+     -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
+     -177, -177, -177, -177, -177,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43, -177, -177, -177, -177, -177, -177,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -177, -177, -177, -177, -177
+    },
+
+    {
+        7, -178, -178, -178, -178, -178, -178, -178, -178, -178,
+     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
+     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
+     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
+     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
+     -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
+
+     -178, -178, -178, -178, -178,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -178, -178, -178, -178, -178, -178,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,  195,   43,   43,   43,   43,
+       43,   43,   43, -178, -178, -178, -178, -178
+    },
+
+    {
+        7, -179, -179, -179, -179, -179, -179, -179, -179, -179,
+     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
+     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
+
+     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
+     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
+     -179, -179, -179, -179, -179, -179, -179, -179, -179, -179,
+     -179, -179, -179, -179, -179,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  196,   43,   43,   43,   43,   43,   43,
+       43, -179, -179, -179, -179, -179, -179,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -179, -179, -179, -179, -179
+
+    },
+
+    {
+        7, -180, -180, -180, -180, -180, -180, -180, -180, -180,
+     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
+     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
+     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
+     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
+     -180, -180, -180, -180, -180, -180, -180, -180, -180, -180,
+     -180, -180, -180, -180, -180,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,  197,   43,   43,   43,   43,   43,   43,
+       43, -180, -180, -180, -180, -180, -180,   43,   43,   43,
+
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -180, -180, -180, -180, -180
+    },
+
+    {
+        7, -181, -181, -181, -181, -181, -181, -181, -181, -181,
+     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
+     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
+     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
+     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
+     -181, -181, -181, -181, -181, -181, -181, -181, -181, -181,
+     -181, -181, -181, -181, -181,   43,   43,   43,   43,   43,
+
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -181, -181, -181, -181, -181, -181,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,  198,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -181, -181, -181, -181, -181
+    },
+
+    {
+        7, -182, -182, -182, -182, -182, -182, -182, -182, -182,
+     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
+     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
+     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
+
+     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
+     -182, -182, -182, -182, -182, -182, -182, -182, -182, -182,
+     -182, -182, -182, -182, -182,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -182, -182, -182, -182, -182, -182,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,  189,   43,   43,   43,   43,
+       43,   43,   43, -182, -182, -182, -182, -182
+    },
+
+    {
+        7, -183, -183, -183, -183, -183, -183, -183, -183, -183,
+
+     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
+     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
+     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
+     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
+     -183, -183, -183, -183, -183, -183, -183, -183, -183, -183,
+     -183, -183, -183, -183, -183,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -183, -183, -183, -183, -183, -183,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43,   43,   43,   43,   43,  190,   43,   43,   43,   43,
+       43,   43,   43, -183, -183, -183, -183, -183
+    },
+
+    {
+        7, -184, -184, -184, -184, -184, -184, -184, -184, -184,
+     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
+     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
+     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
+     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
+     -184, -184, -184, -184, -184, -184, -184, -184, -184, -184,
+     -184, -184, -184, -184, -184,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -184, -184, -184, -184, -184, -184,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,  199,   43,   43,   43,   43,
+       43,   43,   43, -184, -184, -184, -184, -184
+    },
+
+    {
+        7, -185, -185, -185, -185, -185, -185, -185, -185, -185,
+     -185, -185, -185, -185, -185, -185, -185, -185, -185, -185,
+     -185, -185, -185, -185, -185, -185, -185, -185, -185, -185,
+     -185, -185, -185, -185, -185, -185, -185, -185, -185, -185,
+     -185, -185, -185, -185, -185, -185, -185, -185, -185, -185,
+
+     -185, -185, -185, -185, -185, -185, -185, -185, -185, -185,
+     -185, -185, -185, -185, -185,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -185, -185, -185, -185, -185, -185,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -185, -185, -185, -185, -185
+    },
+
+    {
+        7, -186, -186, -186, -186, -186, -186, -186, -186, -186,
+     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
+
+     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
+     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
+     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
+     -186, -186, -186, -186, -186, -186, -186, -186, -186, -186,
+     -186, -186, -186, -186, -186,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -186, -186, -186, -186, -186, -186,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43,   43,   43, -186, -186, -186, -186, -186
+    },
+
+    {
+        7, -187, -187, -187, -187, -187, -187, -187, -187, -187,
+     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
+     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
+     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
+     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
+     -187, -187, -187, -187, -187, -187, -187, -187, -187, -187,
+     -187, -187, -187, -187, -187,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43, -187, -187, -187, -187, -187, -187,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,  200,   43,   43,   43,   43,
+       43,   43,   43, -187, -187, -187, -187, -187
+    },
+
+    {
+        7, -188, -188, -188, -188, -188, -188, -188, -188, -188,
+     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
+     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
+     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
+     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
+     -188, -188, -188, -188, -188, -188, -188, -188, -188, -188,
+
+     -188, -188, -188, -188, -188,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -188, -188, -188, -188, -188, -188,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,  201,   43,   43,   43,   43,
+       43,   43,   43, -188, -188, -188, -188, -188
+    },
+
+    {
+        7, -189, -189, -189, -189, -189, -189, -189, -189, -189,
+     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
+     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
+
+     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
+     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
+     -189, -189, -189, -189, -189, -189, -189, -189, -189, -189,
+     -189, -189, -189, -189, -189,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -189, -189, -189, -189, -189, -189,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -189, -189, -189, -189, -189
+
+    },
+
+    {
+        7, -190, -190, -190, -190, -190, -190, -190, -190, -190,
+     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
+     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
+     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
+     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
+     -190, -190, -190, -190, -190, -190, -190, -190, -190, -190,
+     -190, -190, -190, -190, -190,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -190, -190, -190, -190, -190, -190,   43,   43,   43,
+
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -190, -190, -190, -190, -190
+    },
+
+    {
+        7, -191, -191, -191, -191, -191, -191, -191, -191, -191,
+     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
+     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
+     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
+     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
+     -191, -191, -191, -191, -191, -191, -191, -191, -191, -191,
+     -191, -191, -191, -191, -191,   43,   43,   43,   43,   43,
+
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -191, -191, -191, -191, -191, -191,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -191, -191, -191, -191, -191
+    },
+
+    {
+        7, -192, -192, -192, -192, -192, -192, -192, -192, -192,
+     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
+     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
+     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
+
+     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
+     -192, -192, -192, -192, -192, -192, -192, -192, -192, -192,
+     -192, -192, -192, -192, -192,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -192, -192, -192, -192, -192, -192,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -192, -192, -192, -192, -192
+    },
+
+    {
+        7, -193, -193, -193, -193, -193, -193, -193, -193, -193,
+
+     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
+     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
+     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
+     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
+     -193, -193, -193, -193, -193, -193, -193, -193, -193, -193,
+     -193, -193, -193, -193, -193,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -193, -193, -193, -193, -193, -193,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -193, -193, -193, -193, -193
+    },
+
+    {
+        7, -194, -194, -194, -194, -194, -194, -194, -194, -194,
+     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
+     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
+     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
+     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
+     -194, -194, -194, -194, -194, -194, -194, -194, -194, -194,
+     -194, -194, -194, -194, -194,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -194, -194, -194, -194, -194, -194,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -194, -194, -194, -194, -194
+    },
+
+    {
+        7, -195, -195, -195, -195, -195, -195, -195, -195, -195,
+     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
+     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
+     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
+     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
+
+     -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
+     -195, -195, -195, -195, -195,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -195, -195, -195, -195, -195, -195,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -195, -195, -195, -195, -195
+    },
+
+    {
+        7, -196, -196, -196, -196, -196, -196, -196, -196, -196,
+     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
+
+     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
+     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
+     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
+     -196, -196, -196, -196, -196, -196, -196, -196, -196, -196,
+     -196, -196, -196, -196, -196,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -196, -196, -196, -196, -196, -196,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43,   43,   43, -196, -196, -196, -196, -196
+    },
+
+    {
+        7, -197, -197, -197, -197, -197, -197, -197, -197, -197,
+     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
+     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
+     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
+     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
+     -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
+     -197, -197, -197, -197, -197,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+
+       43, -197, -197, -197, -197, -197, -197,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -197, -197, -197, -197, -197
+    },
+
+    {
+        7, -198, -198, -198, -198, -198, -198, -198, -198, -198,
+     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
+     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
+     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
+     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
+     -198, -198, -198, -198, -198, -198, -198, -198, -198, -198,
+
+     -198, -198, -198, -198, -198,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -198, -198, -198, -198, -198, -198,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,  202,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -198, -198, -198, -198, -198
+    },
+
+    {
+        7, -199, -199, -199, -199, -199, -199, -199, -199, -199,
+     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
+     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
+
+     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
+     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
+     -199, -199, -199, -199, -199, -199, -199, -199, -199, -199,
+     -199, -199, -199, -199, -199,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -199, -199, -199, -199, -199, -199,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -199, -199, -199, -199, -199
+
+    },
+
+    {
+        7, -200, -200, -200, -200, -200, -200, -200, -200, -200,
+     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
+     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
+     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
+     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
+     -200, -200, -200, -200, -200, -200, -200, -200, -200, -200,
+     -200, -200, -200, -200, -200,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -200, -200, -200, -200, -200, -200,   43,   43,   43,
+
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -200, -200, -200, -200, -200
+    },
+
+    {
+        7, -201, -201, -201, -201, -201, -201, -201, -201, -201,
+     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
+     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
+     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
+     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
+     -201, -201, -201, -201, -201, -201, -201, -201, -201, -201,
+     -201, -201, -201, -201, -201,   43,   43,   43,   43,   43,
+
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -201, -201, -201, -201, -201, -201,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -201, -201, -201, -201, -201
+    },
+
+    {
+        7, -202, -202, -202, -202, -202, -202, -202, -202, -202,
+     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
+     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
+     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
+
+     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
+     -202, -202, -202, -202, -202, -202, -202, -202, -202, -202,
+     -202, -202, -202, -202, -202,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43, -202, -202, -202, -202, -202, -202,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43, -202, -202, -202, -202, -202
+    },
+
+    } ;
+
+static yy_state_type yy_get_previous_state (void );
+static yy_state_type yy_try_NUL_trans (yy_state_type current_state  );
+static int yy_get_next_buffer (void );
+static void yy_fatal_error (yyconst char msg[]  );
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up wcsutrntext.
+ */
+#define YY_DO_BEFORE_ACTION \
+	(yytext_ptr) = yy_bp; \
+	wcsutrnleng = (size_t) (yy_cp - yy_bp); \
+	(yy_hold_char) = *yy_cp; \
+	*yy_cp = '\0'; \
+	(yy_c_buf_p) = yy_cp;
+
+#define YY_NUM_RULES 37
+#define YY_END_OF_BUFFER 38
+/* This struct is not used in this scanner,
+   but its presence is necessary. */
+struct yy_trans_info
+	{
+	flex_int32_t yy_verify;
+	flex_int32_t yy_nxt;
+	};
+static yyconst flex_int16_t yy_accept[203] =
+    {   0,
+        0,    0,    0,    0,   36,   36,   38,    3,    2,   31,
+       31,   31,   10,   31,   14,   31,   31,   20,   31,   31,
+       31,   28,   31,   31,   31,   31,   31,   31,   31,   31,
+       31,   31,   31,   31,    2,    1,   35,   37,   35,   32,
+       36,    2,   31,   31,   31,   31,   31,   31,   31,   13,
+       15,   17,   31,   31,   19,   31,   31,   31,   31,   31,
+       31,   31,   31,   31,   31,   31,   31,   31,   30,   31,
+       31,   31,   31,   31,   31,   31,   31,   31,    2,    1,
+       33,   33,   34,   32,   36,   31,   31,   31,    9,   11,
+       12,   31,   16,   31,   31,   22,   21,   23,   31,   31,
+
+       31,   26,   27,   31,   31,   31,   31,   31,    9,   31,
+       31,   31,   31,   27,   31,   31,   31,    7,    8,    9,
+       31,   31,   31,   31,   31,   31,   31,   31,   31,   31,
+       29,   29,   30,   31,   31,   31,    9,   31,   31,   31,
+       31,   31,   31,   30,   31,   31,   31,   31,   31,   20,
+       20,   31,   25,   31,   31,   31,   29,   29,   30,   31,
+       31,   31,   31,   20,   20,   31,   31,   31,    5,    6,
+       11,   18,   18,   20,   20,   24,   25,   24,   26,   27,
+       31,   31,   31,   11,   20,   20,   26,   27,    5,    6,
+       11,   18,   18,   24,   24,   26,   27,   31,   11,   26,
+
+       27,    4
+    } ;
+
+static yyconst yy_state_type yy_NUL_trans[203] =
+    {   0,
+        8,    8,   37,   37,   41,   41,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,   81,    0,
+       85,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,   81,    0,    0,   85,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+
+        0,    0
+    } ;
+
+extern int wcsutrn_flex_debug;
+int wcsutrn_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 yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+char *wcsutrntext;
+#line 1 "wcsutrn.l"
+/*============================================================================
+
+  WCSLIB 4.16 - an implementation of the FITS WCS standard.
+  Copyright (C) 1995-2012, Mark Calabretta
+
+  This file is part of WCSLIB.
+
+  WCSLIB is free software: you can redistribute it and/or modify it under the
+  terms of the GNU Lesser General Public License as published by the Free
+  Software Foundation, either version 3 of the License, or (at your option)
+  any later version.
+
+  WCSLIB 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 Lesser General Public License for
+  more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with WCSLIB.  If not, see http://www.gnu.org/licenses.
+
+  Direct correspondence concerning WCSLIB to mark at calabretta.id.au
+
+  Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
+  http://www.atnf.csiro.au/people/Mark.Calabretta
+  $Id: wcsutrn.c,v 4.16 2012/11/07 04:42:44 cal103 Exp $
+*=============================================================================
+*
+* wcsutrn.l is a Flex description file containing the definition of a lexical
+* scanner that translates non-standard FITS units specifications.
+*
+* It requires Flex v2.5.4 or later.
+*
+* Refer to wcsunits.h for a description of the user interface and operating
+* notes.
+*
+*===========================================================================*/
+/* Options. */
+/* Exclusive start states. */
+
+#line 49 "wcsutrn.l"
+/* To get the prototype for fileno() from stdio.h when gcc is invoked with
+ * -std=c89 (same as -ansi) or -std=c99 since we do not define YY_INPUT. */
+#define _POSIX_SOURCE 1
+
+#include <setjmp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "wcserr.h"
+#include "wcsunits.h"
+
+#define YY_DECL int wcsutrne(int ctrl, char unitstr[], struct wcserr **err)
+
+/* Used in preempting the call to exit() by yy_fatal_error(). */
+jmp_buf wcsutrn_abort_jmp_env;
+#define exit(status) longjmp(wcsutrn_abort_jmp_env, status)
+
+#line 4042 "wcsutrn.c"
+
+#define INITIAL 0
+#define NEXT 1
+#define FLUSH 2
+
+#ifndef YY_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 <unistd.h>
+#endif
+
+#ifndef YY_EXTRA_TYPE
+#define YY_EXTRA_TYPE void *
+#endif
+
+static int yy_init_globals (void );
+
+/* Accessor methods to globals.
+   These are made visible to non-reentrant scanners for convenience. */
+
+int wcsutrnlex_destroy (void );
+
+int wcsutrnget_debug (void );
+
+void wcsutrnset_debug (int debug_flag  );
+
+YY_EXTRA_TYPE wcsutrnget_extra (void );
+
+void wcsutrnset_extra (YY_EXTRA_TYPE user_defined  );
+
+FILE *wcsutrnget_in (void );
+
+void wcsutrnset_in  (FILE * in_str  );
+
+FILE *wcsutrnget_out (void );
+
+void wcsutrnset_out  (FILE * out_str  );
+
+int wcsutrnget_leng (void );
+
+char *wcsutrnget_text (void );
+
+int wcsutrnget_lineno (void );
+
+void wcsutrnset_lineno (int line_number  );
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int wcsutrnwrap (void );
+#else
+extern int wcsutrnwrap (void );
+#endif
+#endif
+
+    static void yyunput (int c,char *buf_ptr  );
+    
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char *,yyconst char *,int );
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * );
+#endif
+
+#ifndef YY_NO_INPUT
+
+#ifdef __cplusplus
+static int yyinput (void );
+#else
+static int input (void );
+#endif
+
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k */
+#define YY_READ_BUF_SIZE 16384
+#else
+#define YY_READ_BUF_SIZE 8192
+#endif /* __ia64__ */
+#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( wcsutrntext, wcsutrnleng, 1, wcsutrnout )) {} } while (0)
+#endif
+
+/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+	errno=0; \
+	while ( (result = read( fileno(wcsutrnin), (char *) buf, max_size )) < 0 ) \
+	{ \
+		if( errno != EINTR) \
+		{ \
+			YY_FATAL_ERROR( "input in flex scanner failed" ); \
+			break; \
+		} \
+		errno=0; \
+		clearerr(wcsutrnin); \
+	}\
+\
+
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_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 YY_DECL
+#define YY_DECL_IS_OURS 1
+
+extern int wcsutrnlex (void);
+
+#define YY_DECL int wcsutrnlex (void)
+#endif /* !YY_DECL */
+
+/* Code executed at the beginning of each rule, after wcsutrntext and wcsutrnleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+	if ( wcsutrnleng > 0 ) \
+		YY_CURRENT_BUFFER_LVALUE->yy_at_bol = \
+				(wcsutrntext[wcsutrnleng - 1] == '\n'); \
+	YY_USER_ACTION
+
+/** The main scanner function which does all the work.
+ */
+YY_DECL
+{
+	register yy_state_type yy_current_state;
+	register char *yy_cp, *yy_bp;
+	register int yy_act;
+    
+#line 69 "wcsutrn.l"
+
+	static const char *function = "wcsutrne";
+	
+	char orig[80], subs[80];
+	int bracket = 0;
+	int unsafe  = 0;
+	int status  = -1;
+	YY_BUFFER_STATE inbuff;
+	int wcsutrnlex_destroy(void);
+	
+	if (err) *err = 0x0;
+	
+	*orig = '\0';
+	*subs = '\0';
+	
+	inbuff = wcsutrn_scan_string(unitstr);
+	*unitstr = '\0';
+	
+	/* Return here via longjmp() invoked by yy_fatal_error(). */
+	if (setjmp(wcsutrn_abort_jmp_env)) {
+	  return wcserr_set(WCSERR_SET(UNITSERR_PARSER_ERROR),
+	    "Internal units translator error parsing '%s'", unitstr);
+	}
+	
+	BEGIN(INITIAL);
+	
+#ifdef DEBUG
+	fprintf(stderr, "\n%s ->\n", unitstr);
+#endif
+
+#line 4249 "wcsutrn.c"
+
+	if ( !(yy_init) )
+		{
+		(yy_init) = 1;
+
+#ifdef YY_USER_INIT
+		YY_USER_INIT;
+#endif
+
+		if ( ! (yy_start) )
+			(yy_start) = 1;	/* first start state */
+
+		if ( ! wcsutrnin )
+			wcsutrnin = stdin;
+
+		if ( ! wcsutrnout )
+			wcsutrnout = stdout;
+
+		if ( ! YY_CURRENT_BUFFER ) {
+			wcsutrnensure_buffer_stack ();
+			YY_CURRENT_BUFFER_LVALUE =
+				wcsutrn_create_buffer(wcsutrnin,YY_BUF_SIZE );
+		}
+
+		wcsutrn_load_buffer_state( );
+		}
+
+	while ( 1 )		/* loops until end-of-file is reached */
+		{
+		yy_cp = (yy_c_buf_p);
+
+		/* Support of wcsutrntext. */
+		*yy_cp = (yy_hold_char);
+
+		/* yy_bp points to the position in yy_ch_buf of the start of
+		 * the current run.
+		 */
+		yy_bp = yy_cp;
+
+		yy_current_state = (yy_start);
+		yy_current_state += YY_AT_BOL();
+yy_match:
+		while ( (yy_current_state = yy_nxt[yy_current_state][ YY_SC_TO_UI(*yy_cp) ]) > 0 )
+			++yy_cp;
+
+		yy_current_state = -yy_current_state;
+
+yy_find_action:
+		yy_act = yy_accept[yy_current_state];
+
+		YY_DO_BEFORE_ACTION;
+
+do_action:	/* This label is used only to access EOF actions. */
+
+		switch ( yy_act )
+	{ /* beginning of action switch */
+case 1:
+YY_RULE_SETUP
+#line 99 "wcsutrn.l"
+{
+	  /* Looks like a keycomment. */
+	  strcat(unitstr, "[");
+	  bracket = 1;
+	}
+	YY_BREAK
+case 2:
+YY_RULE_SETUP
+#line 105 "wcsutrn.l"
+/* Discard leading whitespace. */
+	YY_BREAK
+case 3:
+/* rule 3 can match eol */
+YY_RULE_SETUP
+#line 107 "wcsutrn.l"
+{
+	  /* Non-alphabetic character. */
+	  strcat(unitstr, wcsutrntext);
+	  if (bracket && *wcsutrntext == ']') {
+	    BEGIN(FLUSH);
+	  }
+	}
+	YY_BREAK
+case 4:
+YY_RULE_SETUP
+#line 115 "wcsutrn.l"
+{
+	  strcpy(orig, wcsutrntext);
+	  strcpy(subs, "Angstrom");
+	  BEGIN(NEXT);
+	}
+	YY_BREAK
+case 5:
+YY_RULE_SETUP
+#line 121 "wcsutrn.l"
+{
+	  strcpy(orig, wcsutrntext);
+	  strcpy(subs, "arcmin");
+	  BEGIN(NEXT);
+	}
+	YY_BREAK
+case 6:
+YY_RULE_SETUP
+#line 127 "wcsutrn.l"
+{
+	  strcpy(orig, wcsutrntext);
+	  strcpy(subs, "arcsec");
+	  BEGIN(NEXT);
+	}
+	YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 133 "wcsutrn.l"
+{
+	  strcpy(orig, wcsutrntext);
+	  strcpy(subs, "beam");
+	  BEGIN(NEXT);
+	}
+	YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 139 "wcsutrn.l"
+{
+	  strcpy(orig, wcsutrntext);
+	  strcpy(subs, "byte");
+	  BEGIN(NEXT);
+	}
+	YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 145 "wcsutrn.l"
+{
+	  strcpy(orig, wcsutrntext);
+	  strcpy(subs, "d");
+	  BEGIN(NEXT);
+	}
+	YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 151 "wcsutrn.l"
+{
+	  unsafe = 1;
+	  strcpy(orig, wcsutrntext);
+	  strcpy(subs, (ctrl & 4) ? "d" : "D");
+	  BEGIN(NEXT);
+	}
+	YY_BREAK
+case 11:
+YY_RULE_SETUP
+#line 158 "wcsutrn.l"
+{
+	  strcpy(orig, wcsutrntext);
+	  strcpy(subs, "deg");
+	  BEGIN(NEXT);
+	}
+	YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 164 "wcsutrn.l"
+{
+	  strcpy(orig, wcsutrntext);
+	  strcpy(subs, "GHz");
+	  BEGIN(NEXT);
+	}
+	YY_BREAK
+case 13:
+YY_RULE_SETUP
+#line 170 "wcsutrn.l"
+{
+	  strcpy(orig, wcsutrntext);
+	  strcpy(subs, "h");
+	  BEGIN(NEXT);
+	}
+	YY_BREAK
+case 14:
+YY_RULE_SETUP
+#line 176 "wcsutrn.l"
+{
+	  unsafe = 1;
+	  strcpy(orig, wcsutrntext);
+	  strcpy(subs, (ctrl & 2) ? "h" : "H");
+	  BEGIN(NEXT);
+	}
+	YY_BREAK
+case 15:
+YY_RULE_SETUP
+#line 183 "wcsutrn.l"
+{
+	  strcpy(orig, wcsutrntext);
+	  strcpy(subs, "Hz");
+	  BEGIN(NEXT);
+	}
+	YY_BREAK
+case 16:
+YY_RULE_SETUP
+#line 189 "wcsutrn.l"
+{
+	  strcpy(orig, wcsutrntext);
+	  strcpy(subs, "kHz");
+	  BEGIN(NEXT);
+	}
+	YY_BREAK
+case 17:
+YY_RULE_SETUP
+#line 195 "wcsutrn.l"
+{
+	  strcpy(orig, wcsutrntext);
+	  strcpy(subs, "Jy");
+	  BEGIN(NEXT);
+	}
+	YY_BREAK
+case 18:
+YY_RULE_SETUP
+#line 201 "wcsutrn.l"
+{
+	  strcpy(orig, wcsutrntext);
+	  strcpy(subs, "K");
+	  BEGIN(NEXT);
+	}
+	YY_BREAK
+case 19:
+YY_RULE_SETUP
+#line 207 "wcsutrn.l"
+{
+	  strcpy(orig, wcsutrntext);
+	  strcpy(subs, "km");
+	  BEGIN(NEXT);
+	}
+	YY_BREAK
+case 20:
+YY_RULE_SETUP
+#line 213 "wcsutrn.l"
+{
+	  strcpy(orig, wcsutrntext);
+	  strcpy(subs, "m");
+	  BEGIN(NEXT);
+	}
+	YY_BREAK
+case 21:
+YY_RULE_SETUP
+#line 219 "wcsutrn.l"
+{
+	  strcpy(orig, wcsutrntext);
+	  strcpy(subs, "min");
+	  BEGIN(NEXT);
+	}
+	YY_BREAK
+case 22:
+YY_RULE_SETUP
+#line 225 "wcsutrn.l"
+{
+	  strcpy(orig, wcsutrntext);
+	  strcpy(subs, "MHz");
+	  BEGIN(NEXT);
+	}
+	YY_BREAK
+case 23:
+YY_RULE_SETUP
+#line 231 "wcsutrn.l"
+{
+	  strcpy(orig, wcsutrntext);
+	  strcpy(subs, "ohm");
+	  BEGIN(NEXT);
+	}
+	YY_BREAK
+case 24:
+YY_RULE_SETUP
+#line 237 "wcsutrn.l"
+{
+	  strcpy(orig, wcsutrntext);
+	  strcpy(subs, "Pa");
+	  BEGIN(NEXT);
+	}
+	YY_BREAK
+case 25:
+YY_RULE_SETUP
+#line 243 "wcsutrn.l"
+{
+	  strcpy(orig, wcsutrntext);
+	  strcpy(subs, "pixel");
+	  BEGIN(NEXT);
+	}
+	YY_BREAK
+case 26:
+YY_RULE_SETUP
+#line 249 "wcsutrn.l"
+{
+	  strcpy(orig, wcsutrntext);
+	  strcpy(subs, "rad");
+	  BEGIN(NEXT);
+	}
+	YY_BREAK
+case 27:
+YY_RULE_SETUP
+#line 255 "wcsutrn.l"
+{
+	  strcpy(orig, wcsutrntext);
+	  strcpy(subs, "s");
+	  BEGIN(NEXT);
+	}
+	YY_BREAK
+case 28:
+YY_RULE_SETUP
+#line 261 "wcsutrn.l"
+{
+	  unsafe = 1;
+	  strcpy(orig, wcsutrntext);
+	  strcpy(subs, (ctrl & 1) ? "s" : "S");
+	  BEGIN(NEXT);
+	}
+	YY_BREAK
+case 29:
+YY_RULE_SETUP
+#line 268 "wcsutrn.l"
+{
+	  strcpy(orig, wcsutrntext);
+	  strcpy(subs, "V");
+	  BEGIN(NEXT);
+	}
+	YY_BREAK
+case 30:
+YY_RULE_SETUP
+#line 274 "wcsutrn.l"
+{
+	  strcpy(orig, wcsutrntext);
+	  strcpy(subs, "yr");
+	  BEGIN(NEXT);
+	}
+	YY_BREAK
+case 31:
+YY_RULE_SETUP
+#line 280 "wcsutrn.l"
+{
+	  /* Not a recognized alias. */
+	  strcpy(orig, wcsutrntext);
+	  strcpy(subs, orig);
+	  BEGIN(NEXT);
+	}
+	YY_BREAK
+case 32:
+YY_RULE_SETUP
+#line 287 "wcsutrn.l"
+{
+	  /* Reject the alias match. */
+	  strcat(orig, wcsutrntext);
+	  strcpy(subs, orig);
+	}
+	YY_BREAK
+case 33:
+/* rule 33 can match eol */
+YY_RULE_SETUP
+#line 293 "wcsutrn.l"
+{
+	  /* Discard separating whitespace. */
+	  unput(wcsutrntext[wcsutrnleng-1]);
+	}
+	YY_BREAK
+case 34:
+YY_RULE_SETUP
+#line 298 "wcsutrn.l"
+{
+	  /* Compress separating whitespace. */
+	  strcat(unitstr, subs);
+	  strcat(unitstr, " ");
+	  if (strcmp(orig, subs)) status = 0;
+	  unput(wcsutrntext[wcsutrnleng-1]);
+	  *subs = '\0';
+	  BEGIN(INITIAL);
+	}
+	YY_BREAK
+case 35:
+YY_RULE_SETUP
+#line 308 "wcsutrn.l"
+{
+	  /* Copy anything else unchanged. */
+	  strcat(unitstr, subs);
+	  if (strcmp(orig, subs)) status = 0;
+	  unput(*wcsutrntext);
+	  *subs = '\0';
+	  BEGIN(INITIAL);
+	}
+	YY_BREAK
+case 36:
+YY_RULE_SETUP
+#line 317 "wcsutrn.l"
+{
+	  /* Copy out remaining input. */
+	  strcat(unitstr, wcsutrntext);
+	}
+	YY_BREAK
+case YY_STATE_EOF(INITIAL):
+case YY_STATE_EOF(NEXT):
+case YY_STATE_EOF(FLUSH):
+#line 322 "wcsutrn.l"
+{
+	  /* End-of-string. */
+	  if (*subs) {
+	    strcat(unitstr, subs);
+	    if (strcmp(orig, subs)) status = 0;
+	  }
+	
+	  wcsutrnlex_destroy();
+	  if (unsafe) {
+	    return wcserr_set(WCSERR_SET(UNITSERR_UNSAFE_TRANS),
+	      "Unsafe unit translation in '%s'", unitstr);
+	  }
+	  return status;
+	}
+	YY_BREAK
+case 37:
+YY_RULE_SETUP
+#line 337 "wcsutrn.l"
+ECHO;
+	YY_BREAK
+#line 4663 "wcsutrn.c"
+
+	case YY_END_OF_BUFFER:
+		{
+		/* Amount of text matched not including the EOB char. */
+		int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;
+
+		/* Undo the effects of YY_DO_BEFORE_ACTION. */
+		*yy_cp = (yy_hold_char);
+		YY_RESTORE_YY_MORE_OFFSET
+
+		if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
+			{
+			/* We're scanning a new file or input source.  It's
+			 * possible that this happened because the user
+			 * just pointed wcsutrnin at a new source and called
+			 * wcsutrnlex().  If so, then we have to assure
+			 * consistency between YY_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.
+			 */
+			(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+			YY_CURRENT_BUFFER_LVALUE->yy_input_file = wcsutrnin;
+			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
+			}
+
+		/* Note that here we test for yy_c_buf_p "<=" to the position
+		 * of the first EOB in the buffer, since yy_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 ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+			{ /* This was really a NUL. */
+			yy_state_type yy_next_state;
+
+			(yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;
+
+			yy_current_state = yy_get_previous_state(  );
+
+			/* Okay, we're now positioned to make the NUL
+			 * transition.  We couldn't have
+			 * yy_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).
+			 */
+
+			yy_next_state = yy_try_NUL_trans( yy_current_state );
+
+			yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+
+			if ( yy_next_state )
+				{
+				/* Consume the NUL. */
+				yy_cp = ++(yy_c_buf_p);
+				yy_current_state = yy_next_state;
+				goto yy_match;
+				}
+
+			else
+				{
+				yy_cp = (yy_c_buf_p);
+				goto yy_find_action;
+				}
+			}
+
+		else switch ( yy_get_next_buffer(  ) )
+			{
+			case EOB_ACT_END_OF_FILE:
+				{
+				(yy_did_buffer_switch_on_eof) = 0;
+
+				if ( wcsutrnwrap( ) )
+					{
+					/* Note: because we've taken care in
+					 * yy_get_next_buffer() to have set up
+					 * wcsutrntext, we can now set up
+					 * yy_c_buf_p so that if some total
+					 * hoser (like flex itself) wants to
+					 * call the scanner after we return the
+					 * YY_NULL, it'll still work - another
+					 * YY_NULL will get returned.
+					 */
+					(yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;
+
+					yy_act = YY_STATE_EOF(YY_START);
+					goto do_action;
+					}
+
+				else
+					{
+					if ( ! (yy_did_buffer_switch_on_eof) )
+						YY_NEW_FILE;
+					}
+				break;
+				}
+
+			case EOB_ACT_CONTINUE_SCAN:
+				(yy_c_buf_p) =
+					(yytext_ptr) + yy_amount_of_matched_text;
+
+				yy_current_state = yy_get_previous_state(  );
+
+				yy_cp = (yy_c_buf_p);
+				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+				goto yy_match;
+
+			case EOB_ACT_LAST_MATCH:
+				(yy_c_buf_p) =
+				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];
+
+				yy_current_state = yy_get_previous_state(  );
+
+				yy_cp = (yy_c_buf_p);
+				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+				goto yy_find_action;
+			}
+		break;
+		}
+
+	default:
+		YY_FATAL_ERROR(
+			"fatal flex scanner internal error--no action found" );
+	} /* end of action switch */
+		} /* end of scanning one token */
+} /* end of wcsutrnlex */
+
+/* yy_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 yy_get_next_buffer (void)
+{
+    	register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+	register char *source = (yytext_ptr);
+	register int number_to_move, i;
+	int ret_val;
+
+	if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
+		YY_FATAL_ERROR(
+		"fatal flex scanner internal error--end of buffer missed" );
+
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
+		{ /* Don't try to fill the buffer, so this is an EOF. */
+		if ( (yy_c_buf_p) - (yytext_ptr) - YY_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) ((yy_c_buf_p) - (yytext_ptr)) - 1;
+
+	for ( i = 0; i < number_to_move; ++i )
+		*(dest++) = *(source++);
+
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+		/* don't do the read, it's not guaranteed to return an EOF,
+		 * just force an EOF
+		 */
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
+
+	else
+		{
+			int num_to_read =
+			YY_CURRENT_BUFFER_LVALUE->yy_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 */
+			YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
+
+			int yy_c_buf_p_offset =
+				(int) ((yy_c_buf_p) - b->yy_ch_buf);
+
+			if ( b->yy_is_our_buffer )
+				{
+				int new_size = b->yy_buf_size * 2;
+
+				if ( new_size <= 0 )
+					b->yy_buf_size += b->yy_buf_size / 8;
+				else
+					b->yy_buf_size *= 2;
+
+				b->yy_ch_buf = (char *)
+					/* Include room in for 2 EOB chars. */
+					wcsutrnrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2  );
+				}
+			else
+				/* Can't grow it, we don't own it. */
+				b->yy_ch_buf = 0;
+
+			if ( ! b->yy_ch_buf )
+				YY_FATAL_ERROR(
+				"fatal error - scanner input buffer overflow" );
+
+			(yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+			num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
+						number_to_move - 1;
+
+			}
+
+		if ( num_to_read > YY_READ_BUF_SIZE )
+			num_to_read = YY_READ_BUF_SIZE;
+
+		/* Read in more data. */
+		YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+			(yy_n_chars), (size_t) num_to_read );
+
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+		}
+
+	if ( (yy_n_chars) == 0 )
+		{
+		if ( number_to_move == YY_MORE_ADJ )
+			{
+			ret_val = EOB_ACT_END_OF_FILE;
+			wcsutrnrestart(wcsutrnin  );
+			}
+
+		else
+			{
+			ret_val = EOB_ACT_LAST_MATCH;
+			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
+				YY_BUFFER_EOF_PENDING;
+			}
+		}
+
+	else
+		ret_val = EOB_ACT_CONTINUE_SCAN;
+
+	if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+		/* Extend the array by 50%, plus the number we really need. */
+		yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1);
+		YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) wcsutrnrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size  );
+		if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+			YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+	}
+
+	(yy_n_chars) += number_to_move;
+	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
+	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
+
+	(yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+
+	return ret_val;
+}
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+    static yy_state_type yy_get_previous_state (void)
+{
+	register yy_state_type yy_current_state;
+	register char *yy_cp;
+    
+	yy_current_state = (yy_start);
+	yy_current_state += YY_AT_BOL();
+
+	for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
+		{
+		if ( *yy_cp )
+			{
+			yy_current_state = yy_nxt[yy_current_state][YY_SC_TO_UI(*yy_cp)];
+			}
+		else
+			yy_current_state = yy_NUL_trans[yy_current_state];
+		}
+
+	return yy_current_state;
+}
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ *	next_state = yy_try_NUL_trans( current_state );
+ */
+    static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state )
+{
+	register int yy_is_jam;
+    
+	yy_current_state = yy_NUL_trans[yy_current_state];
+	yy_is_jam = (yy_current_state == 0);
+
+	return yy_is_jam ? 0 : yy_current_state;
+}
+
+    static void yyunput (int c, register char * yy_bp )
+{
+	register char *yy_cp;
+    
+    yy_cp = (yy_c_buf_p);
+
+	/* undo effects of setting up wcsutrntext */
+	*yy_cp = (yy_hold_char);
+
+	if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+		{ /* need to shift things up to make room */
+		/* +2 for EOB chars. */
+		register int number_to_move = (yy_n_chars) + 2;
+		register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
+					YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
+		register char *source =
+				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
+
+		while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+			*--dest = *--source;
+
+		yy_cp += (int) (dest - source);
+		yy_bp += (int) (dest - source);
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars =
+			(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size;
+
+		if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+			YY_FATAL_ERROR( "flex scanner push-back overflow" );
+		}
+
+	*--yy_cp = (char) c;
+
+	(yytext_ptr) = yy_bp;
+	(yy_hold_char) = *yy_cp;
+	(yy_c_buf_p) = yy_cp;
+}
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+    static int yyinput (void)
+#else
+    static int input  (void)
+#endif
+
+{
+	int c;
+    
+	*(yy_c_buf_p) = (yy_hold_char);
+
+	if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
+		{
+		/* yy_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 ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+			/* This was really a NUL. */
+			*(yy_c_buf_p) = '\0';
+
+		else
+			{ /* need more input */
+			int offset = (yy_c_buf_p) - (yytext_ptr);
+			++(yy_c_buf_p);
+
+			switch ( yy_get_next_buffer(  ) )
+				{
+				case EOB_ACT_LAST_MATCH:
+					/* This happens because yy_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. */
+					wcsutrnrestart(wcsutrnin );
+
+					/*FALLTHROUGH*/
+
+				case EOB_ACT_END_OF_FILE:
+					{
+					if ( wcsutrnwrap( ) )
+						return EOF;
+
+					if ( ! (yy_did_buffer_switch_on_eof) )
+						YY_NEW_FILE;
+#ifdef __cplusplus
+					return yyinput();
+#else
+					return input();
+#endif
+					}
+
+				case EOB_ACT_CONTINUE_SCAN:
+					(yy_c_buf_p) = (yytext_ptr) + offset;
+					break;
+				}
+			}
+		}
+
+	c = *(unsigned char *) (yy_c_buf_p);	/* cast for 8-bit char's */
+	*(yy_c_buf_p) = '\0';	/* preserve wcsutrntext */
+	(yy_hold_char) = *++(yy_c_buf_p);
+
+	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = (c == '\n');
+
+	return c;
+}
+#endif	/* ifndef YY_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 wcsutrnrestart  (FILE * input_file )
+{
+    
+	if ( ! YY_CURRENT_BUFFER ){
+        wcsutrnensure_buffer_stack ();
+		YY_CURRENT_BUFFER_LVALUE =
+            wcsutrn_create_buffer(wcsutrnin,YY_BUF_SIZE );
+	}
+
+	wcsutrn_init_buffer(YY_CURRENT_BUFFER,input_file );
+	wcsutrn_load_buffer_state( );
+}
+
+/** Switch to a different input buffer.
+ * @param new_buffer The new input buffer.
+ * 
+ */
+    void wcsutrn_switch_to_buffer  (YY_BUFFER_STATE  new_buffer )
+{
+    
+	/* TODO. We should be able to replace this entire function body
+	 * with
+	 *		wcsutrnpop_buffer_state();
+	 *		wcsutrnpush_buffer_state(new_buffer);
+     */
+	wcsutrnensure_buffer_stack ();
+	if ( YY_CURRENT_BUFFER == new_buffer )
+		return;
+
+	if ( YY_CURRENT_BUFFER )
+		{
+		/* Flush out information for old buffer. */
+		*(yy_c_buf_p) = (yy_hold_char);
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+		}
+
+	YY_CURRENT_BUFFER_LVALUE = new_buffer;
+	wcsutrn_load_buffer_state( );
+
+	/* We don't actually know whether we did this switch during
+	 * EOF (wcsutrnwrap()) processing, but the only time this flag
+	 * is looked at is after wcsutrnwrap() is called, so it's safe
+	 * to go ahead and always set it.
+	 */
+	(yy_did_buffer_switch_on_eof) = 1;
+}
+
+static void wcsutrn_load_buffer_state  (void)
+{
+    	(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+	(yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+	wcsutrnin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+	(yy_hold_char) = *(yy_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 YY_BUF_SIZE.
+ * 
+ * @return the allocated buffer state.
+ */
+    YY_BUFFER_STATE wcsutrn_create_buffer  (FILE * file, int  size )
+{
+	YY_BUFFER_STATE b;
+    
+	b = (YY_BUFFER_STATE) wcsutrnalloc(sizeof( struct yy_buffer_state )  );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in wcsutrn_create_buffer()" );
+
+	b->yy_buf_size = size;
+
+	/* yy_ch_buf has to be 2 characters longer than the size given because
+	 * we need to put in 2 end-of-buffer characters.
+	 */
+	b->yy_ch_buf = (char *) wcsutrnalloc(b->yy_buf_size + 2  );
+	if ( ! b->yy_ch_buf )
+		YY_FATAL_ERROR( "out of dynamic memory in wcsutrn_create_buffer()" );
+
+	b->yy_is_our_buffer = 1;
+
+	wcsutrn_init_buffer(b,file );
+
+	return b;
+}
+
+/** Destroy the buffer.
+ * @param b a buffer created with wcsutrn_create_buffer()
+ * 
+ */
+    void wcsutrn_delete_buffer (YY_BUFFER_STATE  b )
+{
+    
+	if ( ! b )
+		return;
+
+	if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+		YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
+
+	if ( b->yy_is_our_buffer )
+		wcsutrnfree((void *) b->yy_ch_buf  );
+
+	wcsutrnfree((void *) b  );
+}
+
+/* Initializes or reinitializes a buffer.
+ * This function is sometimes called more than once on the same buffer,
+ * such as during a wcsutrnrestart() or at EOF.
+ */
+    static void wcsutrn_init_buffer  (YY_BUFFER_STATE  b, FILE * file )
+
+{
+	int oerrno = errno;
+    
+	wcsutrn_flush_buffer(b );
+
+	b->yy_input_file = file;
+	b->yy_fill_buffer = 1;
+
+    /* If b is the current buffer, then wcsutrn_init_buffer was _probably_
+     * called from wcsutrnrestart() or through yy_get_next_buffer.
+     * In that case, we don't want to reset the lineno or column.
+     */
+    if (b != YY_CURRENT_BUFFER){
+        b->yy_bs_lineno = 1;
+        b->yy_bs_column = 0;
+    }
+
+        b->yy_is_interactive = 0;
+    
+	errno = oerrno;
+}
+
+/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
+ * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
+ * 
+ */
+    void wcsutrn_flush_buffer (YY_BUFFER_STATE  b )
+{
+    	if ( ! b )
+		return;
+
+	b->yy_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->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+	b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+	b->yy_buf_pos = &b->yy_ch_buf[0];
+
+	b->yy_at_bol = 1;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	if ( b == YY_CURRENT_BUFFER )
+		wcsutrn_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 wcsutrnpush_buffer_state (YY_BUFFER_STATE new_buffer )
+{
+    	if (new_buffer == NULL)
+		return;
+
+	wcsutrnensure_buffer_stack();
+
+	/* This block is copied from wcsutrn_switch_to_buffer. */
+	if ( YY_CURRENT_BUFFER )
+		{
+		/* Flush out information for old buffer. */
+		*(yy_c_buf_p) = (yy_hold_char);
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+		}
+
+	/* Only push if top exists. Otherwise, replace top. */
+	if (YY_CURRENT_BUFFER)
+		(yy_buffer_stack_top)++;
+	YY_CURRENT_BUFFER_LVALUE = new_buffer;
+
+	/* copied from wcsutrn_switch_to_buffer. */
+	wcsutrn_load_buffer_state( );
+	(yy_did_buffer_switch_on_eof) = 1;
+}
+
+/** Removes and deletes the top of the stack, if present.
+ *  The next element becomes the new top.
+ *  
+ */
+void wcsutrnpop_buffer_state (void)
+{
+    	if (!YY_CURRENT_BUFFER)
+		return;
+
+	wcsutrn_delete_buffer(YY_CURRENT_BUFFER );
+	YY_CURRENT_BUFFER_LVALUE = NULL;
+	if ((yy_buffer_stack_top) > 0)
+		--(yy_buffer_stack_top);
+
+	if (YY_CURRENT_BUFFER) {
+		wcsutrn_load_buffer_state( );
+		(yy_did_buffer_switch_on_eof) = 1;
+	}
+}
+
+/* Allocates the stack if it does not exist.
+ *  Guarantees space for at least one push.
+ */
+static void wcsutrnensure_buffer_stack (void)
+{
+	int num_to_alloc;
+    
+	if (!(yy_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;
+		(yy_buffer_stack) = (struct yy_buffer_state**)wcsutrnalloc
+								(num_to_alloc * sizeof(struct yy_buffer_state*)
+								);
+		if ( ! (yy_buffer_stack) )
+			YY_FATAL_ERROR( "out of dynamic memory in wcsutrnensure_buffer_stack()" );
+								  
+		memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+				
+		(yy_buffer_stack_max) = num_to_alloc;
+		(yy_buffer_stack_top) = 0;
+		return;
+	}
+
+	if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
+
+		/* Increase the buffer to prepare for a possible push. */
+		int grow_size = 8 /* arbitrary grow size */;
+
+		num_to_alloc = (yy_buffer_stack_max) + grow_size;
+		(yy_buffer_stack) = (struct yy_buffer_state**)wcsutrnrealloc
+								((yy_buffer_stack),
+								num_to_alloc * sizeof(struct yy_buffer_state*)
+								);
+		if ( ! (yy_buffer_stack) )
+			YY_FATAL_ERROR( "out of dynamic memory in wcsutrnensure_buffer_stack()" );
+
+		/* zero only the new slots.*/
+		memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
+		(yy_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. 
+ */
+YY_BUFFER_STATE wcsutrn_scan_buffer  (char * base, yy_size_t  size )
+{
+	YY_BUFFER_STATE b;
+    
+	if ( size < 2 ||
+	     base[size-2] != YY_END_OF_BUFFER_CHAR ||
+	     base[size-1] != YY_END_OF_BUFFER_CHAR )
+		/* They forgot to leave room for the EOB's. */
+		return 0;
+
+	b = (YY_BUFFER_STATE) wcsutrnalloc(sizeof( struct yy_buffer_state )  );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in wcsutrn_scan_buffer()" );
+
+	b->yy_buf_size = size - 2;	/* "- 2" to take care of EOB's */
+	b->yy_buf_pos = b->yy_ch_buf = base;
+	b->yy_is_our_buffer = 0;
+	b->yy_input_file = 0;
+	b->yy_n_chars = b->yy_buf_size;
+	b->yy_is_interactive = 0;
+	b->yy_at_bol = 1;
+	b->yy_fill_buffer = 0;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	wcsutrn_switch_to_buffer(b  );
+
+	return b;
+}
+
+/** Setup the input buffer state to scan a string. The next call to wcsutrnlex() will
+ * scan from a @e copy of @a str.
+ * @param yystr 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
+ *       wcsutrn_scan_bytes() instead.
+ */
+YY_BUFFER_STATE wcsutrn_scan_string (yyconst char * yystr )
+{
+    
+	return wcsutrn_scan_bytes(yystr,strlen(yystr) );
+}
+
+/** Setup the input buffer state to scan the given bytes. The next call to wcsutrnlex() will
+ * scan from a @e copy of @a bytes.
+ * @param yybytes the byte buffer to scan
+ * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
+ * 
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE wcsutrn_scan_bytes  (yyconst char * yybytes, int  _yybytes_len )
+{
+	YY_BUFFER_STATE b;
+	char *buf;
+	yy_size_t n;
+	int i;
+    
+	/* Get memory for full buffer, including space for trailing EOB's. */
+	n = _yybytes_len + 2;
+	buf = (char *) wcsutrnalloc(n  );
+	if ( ! buf )
+		YY_FATAL_ERROR( "out of dynamic memory in wcsutrn_scan_bytes()" );
+
+	for ( i = 0; i < _yybytes_len; ++i )
+		buf[i] = yybytes[i];
+
+	buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
+
+	b = wcsutrn_scan_buffer(buf,n );
+	if ( ! b )
+		YY_FATAL_ERROR( "bad buffer in wcsutrn_scan_bytes()" );
+
+	/* It's okay to grow etc. this buffer, and we should throw it
+	 * away when we're done.
+	 */
+	b->yy_is_our_buffer = 1;
+
+	return b;
+}
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+static void yy_fatal_error (yyconst char* msg )
+{
+    	(void) fprintf( stderr, "%s\n", msg );
+	exit( YY_EXIT_FAILURE );
+}
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up wcsutrntext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+		wcsutrntext[wcsutrnleng] = (yy_hold_char); \
+		(yy_c_buf_p) = wcsutrntext + yyless_macro_arg; \
+		(yy_hold_char) = *(yy_c_buf_p); \
+		*(yy_c_buf_p) = '\0'; \
+		wcsutrnleng = yyless_macro_arg; \
+		} \
+	while ( 0 )
+
+/* Accessor  methods (get/set functions) to struct members. */
+
+/** Get the current line number.
+ * 
+ */
+int wcsutrnget_lineno  (void)
+{
+        
+    return wcsutrnlineno;
+}
+
+/** Get the input stream.
+ * 
+ */
+FILE *wcsutrnget_in  (void)
+{
+        return wcsutrnin;
+}
+
+/** Get the output stream.
+ * 
+ */
+FILE *wcsutrnget_out  (void)
+{
+        return wcsutrnout;
+}
+
+/** Get the length of the current token.
+ * 
+ */
+int wcsutrnget_leng  (void)
+{
+        return wcsutrnleng;
+}
+
+/** Get the current token.
+ * 
+ */
+
+char *wcsutrnget_text  (void)
+{
+        return wcsutrntext;
+}
+
+/** Set the current line number.
+ * @param line_number
+ * 
+ */
+void wcsutrnset_lineno (int  line_number )
+{
+    
+    wcsutrnlineno = line_number;
+}
+
+/** Set the input stream. This does not discard the current
+ * input buffer.
+ * @param in_str A readable stream.
+ * 
+ * @see wcsutrn_switch_to_buffer
+ */
+void wcsutrnset_in (FILE *  in_str )
+{
+        wcsutrnin = in_str ;
+}
+
+void wcsutrnset_out (FILE *  out_str )
+{
+        wcsutrnout = out_str ;
+}
+
+int wcsutrnget_debug  (void)
+{
+        return wcsutrn_flex_debug;
+}
+
+void wcsutrnset_debug (int  bdebug )
+{
+        wcsutrn_flex_debug = bdebug ;
+}
+
+static int yy_init_globals (void)
+{
+        /* Initialization is the same as for the non-reentrant scanner.
+     * This function is called from wcsutrnlex_destroy(), so don't allocate here.
+     */
+
+    (yy_buffer_stack) = 0;
+    (yy_buffer_stack_top) = 0;
+    (yy_buffer_stack_max) = 0;
+    (yy_c_buf_p) = (char *) 0;
+    (yy_init) = 0;
+    (yy_start) = 0;
+
+/* Defined in main.c */
+#ifdef YY_STDINIT
+    wcsutrnin = stdin;
+    wcsutrnout = stdout;
+#else
+    wcsutrnin = (FILE *) 0;
+    wcsutrnout = (FILE *) 0;
+#endif
+
+    /* For future reference: Set errno on error, since we are called by
+     * wcsutrnlex_init()
+     */
+    return 0;
+}
+
+/* wcsutrnlex_destroy is for both reentrant and non-reentrant scanners. */
+int wcsutrnlex_destroy  (void)
+{
+    
+    /* Pop the buffer stack, destroying each element. */
+	while(YY_CURRENT_BUFFER){
+		wcsutrn_delete_buffer(YY_CURRENT_BUFFER  );
+		YY_CURRENT_BUFFER_LVALUE = NULL;
+		wcsutrnpop_buffer_state();
+	}
+
+	/* Destroy the stack itself. */
+	wcsutrnfree((yy_buffer_stack) );
+	(yy_buffer_stack) = NULL;
+
+    /* Reset the globals. This is important in a non-reentrant scanner so the next time
+     * wcsutrnlex() is called, initialization will occur. */
+    yy_init_globals( );
+
+    return 0;
+}
+
+/*
+ * Internal utility routines.
+ */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
+{
+	register int i;
+	for ( i = 0; i < n; ++i )
+		s1[i] = s2[i];
+}
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * s )
+{
+	register int n;
+	for ( n = 0; s[n]; ++n )
+		;
+
+	return n;
+}
+#endif
+
+void *wcsutrnalloc (yy_size_t  size )
+{
+	return (void *) malloc( size );
+}
+
+void *wcsutrnrealloc  (void * ptr, yy_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 wcsutrnfree (void * ptr )
+{
+	free( (char *) ptr );	/* see wcsutrnrealloc() for (char *) cast */
+}
+
+#define YYTABLES_NAME "yytables"
+
+#line 337 "wcsutrn.l"
+
+
+
diff --git a/cextern/wcslib/C/getwcstab.c b/cextern/wcslib/C/getwcstab.c
new file mode 100644
index 0000000..db9ffc0
--- /dev/null
+++ b/cextern/wcslib/C/getwcstab.c
@@ -0,0 +1,154 @@
+/*============================================================================
+
+  WCSLIB 4.16 - an implementation of the FITS WCS standard.
+  Copyright (C) 1995-2012, Mark Calabretta
+
+  This file is part of WCSLIB.
+
+  WCSLIB is free software: you can redistribute it and/or modify it under the
+  terms of the GNU Lesser General Public License as published by the Free
+  Software Foundation, either version 3 of the License, or (at your option)
+  any later version.
+
+  WCSLIB 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 Lesser General Public License for
+  more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with WCSLIB.  If not, see http://www.gnu.org/licenses.
+
+  Direct correspondence concerning WCSLIB to mark at calabretta.id.au
+
+  Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
+  http://www.atnf.csiro.au/people/Mark.Calabretta
+  $Id: getwcstab.c,v 4.16 2012/11/07 04:42:44 cal103 Exp $
+*===========================================================================*/
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <fitsio.h>
+
+#include "getwcstab.h"
+
+/*--------------------------------------------------------------------------*/
+
+int fits_read_wcstab(
+  fitsfile   *fptr,
+  int  nwtb,
+  wtbarr *wtb,
+  int  *status)
+
+{
+  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;
+}
diff --git a/cextern/wcslib/C/getwcstab.h b/cextern/wcslib/C/getwcstab.h
new file mode 100644
index 0000000..c8e2111
--- /dev/null
+++ b/cextern/wcslib/C/getwcstab.h
@@ -0,0 +1,189 @@
+/*============================================================================
+
+  WCSLIB 4.16 - an implementation of the FITS WCS standard.
+  Copyright (C) 1995-2012, Mark Calabretta
+
+  This file is part of WCSLIB.
+
+  WCSLIB is free software: you can redistribute it and/or modify it under the
+  terms of the GNU Lesser General Public License as published by the Free
+  Software Foundation, either version 3 of the License, or (at your option)
+  any later version.
+
+  WCSLIB 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 Lesser General Public License for
+  more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with WCSLIB.  If not, see http://www.gnu.org/licenses.
+
+  Direct correspondence concerning WCSLIB to mark at calabretta.id.au
+
+  Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
+  http://www.atnf.csiro.au/people/Mark.Calabretta
+  $Id: getwcstab.h,v 4.16 2012/11/07 04:42:44 cal103 Exp $
+*=============================================================================
+*
+* Summary of the getwcstab routines
+* ---------------------------------
+* fits_read_wcstab(), an implementation of a FITS table reading routine for
+* 'TAB' coordinates, is provided for CFITSIO programmers.  It has been
+* incorporated into CFITSIO as of v3.006 with the definitions in this file,
+* getwcstab.h, moved into fitsio.h.
+*
+* fits_read_wcstab() is not included in the WCSLIB object library but the
+* source code is presented here as it may be useful for programmers using an
+* older version of CFITSIO than 3.006, or as a programming template for
+* non-CFITSIO programmers.
+*
+*
+* fits_read_wcstab() - FITS 'TAB' table reading routine
+* ----------------------------------------------------
+* fits_read_wcstab() extracts arrays from a binary table required in
+* constructing 'TAB' coordinates.
+*
+* Given:
+*   fptr      fitsfile *
+*                       Pointer to the file handle returned, for example, by
+*                       the fits_open_file() routine in CFITSIO.
+*
+*   nwtb      int       Number of arrays to be read from the binary table(s).
+*
+* Given and returned:
+*   wtb       wtbarr *  Address of the first element of an array of wtbarr
+*                       typedefs.  This wtbarr typedef is defined to match the
+*                       wtbarr struct defined in WCSLIB.  An array of such
+*                       structs returned by the WCSLIB function wcstab() as
+*                       discussed in the notes below.
+*
+* Returned:
+*   status    int *     CFITSIO status value.
+*
+* Function return value:
+*             int       CFITSIO status value.
+*
+* Notes:
+*   In order to maintain WCSLIB and CFITSIO as independent libraries it is 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 wtbarr structs defined in wcs.h within WCSLIB.
+*
+*   The problem therefore is to define the wtbarr 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().
+*
+*   The solution adopted is for WCSLIB to define "struct wtbarr" while
+*   fitsio.h defines "typedef wtbarr" as an 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 name spaces in C; Appendix A, Sect. A11.1 (p227) of
+*   the K&R ANSI edition states that:
+*
+*     Identifiers fall into several name spaces that do not interfere with one
+*     another; the same identifier may be used for different purposes, even in
+*     the same scope, if the uses are in different name spaces.  These classes
+*     are: objects, functions, typedef names, and enum constants; labels; tags
+*     of structures, unions, and enumerations; and members of each structure
+*     or union individually.
+*
+*   Therefore, declarations within WCSLIB look like
+*
+=     struct wtbarr *w;
+*
+*   while within CFITSIO they are simply
+*
+=     wtbarr *w;
+*
+*   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.
+*
+*   When using WCSLIB and CFITSIO together in C++ the situation is complicated
+*   by the fact that typedefs and structs share the same namespace; C++
+*   Annotated Reference Manual, Sect. 7.1.3 (p105).  In that case the wtbarr
+*   struct in wcs.h is renamed by preprocessor macro substitution to wtbarr_s
+*   to distinguish it from the typedef defined in fitsio.h.  However, the
+*   scope of this macro substitution is limited to wcs.h itself and CFITSIO
+*   programmer code, whether in C++ or C, should always use the wtbarr
+*   typedef.
+*
+*
+* wtbarr typedef
+* --------------
+* The wtbarr typedef is defined as a struct containing the following members:
+*
+*   int i
+*     Image axis number.
+*
+*   int m
+*     Array axis number for index vectors.
+*
+*   int kind
+*     Character identifying the array type:
+*       - c: coordinate array,
+*       - i: index vector.
+*
+*   char extnam[72]
+*     EXTNAME identifying the binary table extension.
+*
+*   int extver
+*     EXTVER identifying the binary table extension.
+*
+*   int extlev
+*     EXTLEV identifying the binary table extension.
+*
+*   char ttype[72]
+*     TTYPEn identifying the column of the binary table that contains the
+*     array.
+*
+*   long row
+*     Table row number.
+*
+*   int ndim
+*     Expected dimensionality of the array.
+*
+*   int *dimlen
+*     Address of the first element of an array of int of length ndim into
+*     which the array axis lengths are to be written.
+*
+*   double **arrayp
+*     Pointer to an array of double which is to be allocated by the user
+*     and into which the array is to be written.
+*
+*===========================================================================*/
+
+#ifndef WCSLIB_GETWCSTAB
+#define WCSLIB_GETWCSTAB
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <fitsio.h>
+
+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;
+
+
+int fits_read_wcstab(fitsfile *fptr, int nwtb, wtbarr *wtb, int *status);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* WCSLIB_GETWCSTAB */
diff --git a/cextern/wcslib/C/lin.c b/cextern/wcslib/C/lin.c
new file mode 100644
index 0000000..a647dff
--- /dev/null
+++ b/cextern/wcslib/C/lin.c
@@ -0,0 +1,749 @@
+/*============================================================================
+
+  WCSLIB 4.16 - an implementation of the FITS WCS standard.
+  Copyright (C) 1995-2012, Mark Calabretta
+
+  This file is part of WCSLIB.
+
+  WCSLIB is free software: you can redistribute it and/or modify it under the
+  terms of the GNU Lesser General Public License as published by the Free
+  Software Foundation, either version 3 of the License, or (at your option)
+  any later version.
+
+  WCSLIB 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 Lesser General Public License for
+  more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with WCSLIB.  If not, see http://www.gnu.org/licenses.
+
+  Direct correspondence concerning WCSLIB to mark at calabretta.id.au
+
+  Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
+  http://www.atnf.csiro.au/people/Mark.Calabretta
+  $Id: lin.c,v 4.16 2012/11/07 04:42:44 cal103 Exp $
+*===========================================================================*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include "wcserr.h"
+#include "wcsprintf.h"
+#include "lin.h"
+
+const int LINSET = 137;
+
+/* Map status return value to message. */
+const char *lin_errmsg[] = {
+  "Success",
+  "Null linprm pointer passed",
+  "Memory allocation failed",
+  "PCi_ja matrix is singular"};
+
+/* Convenience macro for invoking wcserr_set(). */
+#define LIN_ERRMSG(status) WCSERR_SET(status), lin_errmsg[status]
+
+/*--------------------------------------------------------------------------*/
+
+int linini(alloc, naxis, lin)
+
+int alloc, naxis;
+struct linprm *lin;
+
+{
+  static const char *function = "linini";
+
+  int i, j;
+  double *pc;
+  struct wcserr **err;
+
+  if (lin == 0x0) return LINERR_NULL_POINTER;
+
+  /* Initialize error message handling. */
+  err = &(lin->err);
+  if (lin->flag != -1) {
+    if (lin->err) free(lin->err);
+  }
+  lin->err = 0x0;
+
+
+  /* Initialize memory management. */
+  if (lin->flag == -1 || lin->m_flag != LINSET) {
+    lin->m_flag  = 0;
+    lin->m_naxis = 0x0;
+    lin->m_crpix = 0x0;
+    lin->m_pc    = 0x0;
+    lin->m_cdelt = 0x0;
+  }
+
+
+  if (naxis < 0) {
+    return wcserr_set(WCSERR_SET(LINERR_MEMORY),
+      "naxis must not be negative (got %d)", naxis);
+  }
+
+
+  /* Allocate memory for arrays if required. */
+  if (alloc ||
+     lin->crpix == 0x0 ||
+     lin->pc    == 0x0 ||
+     lin->cdelt == 0x0) {
+
+    /* Was sufficient allocated previously? */
+    if (lin->m_flag == LINSET && lin->m_naxis < naxis) {
+      /* No, free it. */
+      linfree(lin);
+    }
+
+    if (alloc || lin->crpix == 0x0) {
+      if (lin->m_crpix) {
+        /* In case the caller fiddled with it. */
+        lin->crpix = lin->m_crpix;
+
+      } else {
+        if (!(lin->crpix = calloc(naxis, sizeof(double)))) {
+          return wcserr_set(LIN_ERRMSG(LINERR_MEMORY));
+        }
+
+        lin->m_flag  = LINSET;
+        lin->m_naxis = naxis;
+        lin->m_crpix = lin->crpix;
+      }
+    }
+
+    if (alloc || lin->pc == 0x0) {
+      if (lin->m_pc) {
+        /* In case the caller fiddled with it. */
+        lin->pc = lin->m_pc;
+
+      } else {
+        if (!(lin->pc = calloc(naxis*naxis, sizeof(double)))) {
+          linfree(lin);
+          return wcserr_set(LIN_ERRMSG(LINERR_MEMORY));
+        }
+
+        lin->m_flag  = LINSET;
+        lin->m_naxis = naxis;
+        lin->m_pc    = lin->pc;
+      }
+    }
+
+    if (alloc || lin->cdelt == 0x0) {
+      if (lin->m_cdelt) {
+        /* In case the caller fiddled with it. */
+        lin->cdelt = lin->m_cdelt;
+
+      } else {
+        if (!(lin->cdelt = calloc(naxis, sizeof(double)))) {
+          linfree(lin);
+          return wcserr_set(LIN_ERRMSG(LINERR_MEMORY));
+        }
+
+        lin->m_flag  = LINSET;
+        lin->m_naxis = naxis;
+        lin->m_cdelt = lin->cdelt;
+      }
+    }
+  }
+
+  /* Free memory allocated by linset(). */
+  if (lin->flag == LINSET) {
+    if (lin->piximg) free(lin->piximg);
+    if (lin->imgpix) free(lin->imgpix);
+  }
+
+  lin->piximg = 0x0;
+  lin->imgpix = 0x0;
+  lin->i_naxis = 0x0;
+
+  lin->flag  = 0;
+  lin->naxis = naxis;
+
+
+  /* CRPIXja defaults to 0.0. */
+  for (j = 0; j < naxis; j++) {
+    lin->crpix[j] = 0.0;
+  }
+
+
+  /* PCi_ja defaults to the unit matrix. */
+  pc = lin->pc;
+  for (i = 0; i < naxis; i++) {
+    for (j = 0; j < naxis; j++) {
+      if (j == i) {
+        *pc = 1.0;
+      } else {
+        *pc = 0.0;
+      }
+      pc++;
+    }
+  }
+
+
+  /* CDELTia defaults to 1.0. */
+  for (i = 0; i < naxis; i++) {
+    lin->cdelt[i] = 1.0;
+  }
+
+
+  return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int lincpy(alloc, linsrc, lindst)
+
+int alloc;
+const struct linprm *linsrc;
+struct linprm *lindst;
+
+{
+  static const char *function = "lincpy";
+
+  int i, j, naxis, status;
+  const double *srcp;
+  double *dstp;
+  struct wcserr **err;
+
+  if (linsrc == 0x0) return LINERR_NULL_POINTER;
+  if (lindst == 0x0) return LINERR_NULL_POINTER;
+  err = &(lindst->err);
+
+  naxis = linsrc->naxis;
+  if (naxis < 1) {
+    return wcserr_set(WCSERR_SET(LINERR_MEMORY),
+      "naxis must be positive (got %d)", naxis);
+  }
+
+  if ((status = linini(alloc, naxis, lindst))) {
+    return status;
+  }
+
+  srcp = linsrc->crpix;
+  dstp = lindst->crpix;
+  for (j = 0; j < naxis; j++) {
+    *(dstp++) = *(srcp++);
+  }
+
+  srcp = linsrc->pc;
+  dstp = lindst->pc;
+  for (i = 0; i < naxis; i++) {
+    for (j = 0; j < naxis; j++) {
+      *(dstp++) = *(srcp++);
+    }
+  }
+
+  srcp = linsrc->cdelt;
+  dstp = lindst->cdelt;
+  for (i = 0; i < naxis; i++) {
+    *(dstp++) = *(srcp++);
+  }
+
+  return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int linfree(lin)
+
+struct linprm *lin;
+
+{
+  if (lin == 0x0) return LINERR_NULL_POINTER;
+
+  if (lin->flag != -1) {
+    /* Free memory allocated by linini(). */
+    if (lin->m_flag == LINSET) {
+      if (lin->crpix == lin->m_crpix) lin->crpix = 0x0;
+      if (lin->pc    == lin->m_pc)    lin->pc    = 0x0;
+      if (lin->cdelt == lin->m_cdelt) lin->cdelt = 0x0;
+
+      if (lin->m_crpix) free(lin->m_crpix);
+      if (lin->m_pc)    free(lin->m_pc);
+      if (lin->m_cdelt) free(lin->m_cdelt);
+    }
+  }
+
+  lin->m_flag  = 0;
+  lin->m_naxis = 0;
+  lin->m_crpix = 0x0;
+  lin->m_pc    = 0x0;
+  lin->m_cdelt = 0x0;
+
+
+  /* Free memory allocated by linset(). */
+  if (lin->flag == LINSET) {
+    if (lin->piximg) free(lin->piximg);
+    if (lin->imgpix) free(lin->imgpix);
+  }
+
+  lin->piximg = 0x0;
+  lin->imgpix = 0x0;
+  lin->i_naxis = 0;
+
+  if (lin->err) {
+    free(lin->err);
+    lin->err = 0x0;
+  }
+
+  lin->flag = 0;
+
+  return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int linprt(lin)
+
+const struct linprm *lin;
+
+{
+  int i, j, k;
+
+  if (lin == 0x0) return LINERR_NULL_POINTER;
+
+  if (lin->flag != LINSET) {
+    wcsprintf("The linprm struct is UNINITIALIZED.\n");
+    return 0;
+  }
+
+  wcsprintf("       flag: %d\n", lin->flag);
+  wcsprintf("      naxis: %d\n", lin->naxis);
+  WCSPRINTF_PTR("      crpix: ", lin->crpix, "\n");
+  wcsprintf("            ");
+  for (i = 0; i < lin->naxis; i++) {
+    wcsprintf("  %- 11.5g", lin->crpix[i]);
+  }
+  wcsprintf("\n");
+
+  k = 0;
+  WCSPRINTF_PTR("         pc: ", lin->pc, "\n");
+  for (i = 0; i < lin->naxis; i++) {
+    wcsprintf("    pc[%d][]:", i);
+    for (j = 0; j < lin->naxis; j++) {
+      wcsprintf("  %- 11.5g", lin->pc[k++]);
+    }
+    wcsprintf("\n");
+  }
+
+  WCSPRINTF_PTR("      cdelt: ", lin->cdelt, "\n");
+  wcsprintf("            ");
+  for (i = 0; i < lin->naxis; i++) {
+    wcsprintf("  %- 11.5g", lin->cdelt[i]);
+  }
+  wcsprintf("\n");
+
+  wcsprintf("      unity: %d\n", lin->unity);
+
+  WCSPRINTF_PTR("        err: ", lin->err, "\n");
+  if (lin->err) {
+    wcserr_prt(lin->err, "             ");
+  }
+
+  if (lin->piximg == 0x0) {
+    wcsprintf("     piximg: (nil)\n");
+  } else {
+    k = 0;
+    for (i = 0; i < lin->naxis; i++) {
+      wcsprintf("piximg[%d][]:", i);
+      for (j = 0; j < lin->naxis; j++) {
+        wcsprintf("  %- 11.5g", lin->piximg[k++]);
+      }
+      wcsprintf("\n");
+    }
+  }
+
+  if (lin->imgpix == 0x0) {
+    wcsprintf("     imgpix: (nil)\n");
+  } else {
+    k = 0;
+    for (i = 0; i < lin->naxis; i++) {
+      wcsprintf("imgpix[%d][]:", i);
+      for (j = 0; j < lin->naxis; j++) {
+        wcsprintf("  %- 11.5g", lin->imgpix[k++]);
+      }
+      wcsprintf("\n");
+    }
+  }
+
+  wcsprintf("     m_flag: %d\n", lin->m_flag);
+  wcsprintf("    m_naxis: %d\n", lin->m_naxis);
+  WCSPRINTF_PTR("    m_crpix: ", lin->m_crpix, "");
+  if (lin->m_crpix == lin->crpix) wcsprintf("  (= crpix)");
+  wcsprintf("\n");
+  WCSPRINTF_PTR("       m_pc: ", lin->m_pc, "");
+  if (lin->m_pc == lin->pc) wcsprintf("  (= pc)");
+  wcsprintf("\n");
+  WCSPRINTF_PTR("    m_cdelt: ", lin->m_cdelt, "");
+  if (lin->m_cdelt == lin->cdelt) wcsprintf("  (= cdelt)");
+  wcsprintf("\n");
+
+  return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int linset(lin)
+
+struct linprm *lin;
+
+{
+  static const char *function = "linset";
+
+  int i, j, n, status;
+  double *pc, *piximg;
+  struct wcserr **err;
+
+  if (lin == 0x0) return LINERR_NULL_POINTER;
+  err = &(lin->err);
+
+  n = lin->naxis;
+
+  /* Check for a unit matrix. */
+  lin->unity = 1;
+  pc = lin->pc;
+  for (i = 0; i < n; i++) {
+    for (j = 0; j < n; j++) {
+      if (j == i) {
+        if (*(pc++) != 1.0) {
+          lin->unity = 0;
+          break;
+        }
+      } else {
+        if (*(pc++) != 0.0) {
+          lin->unity = 0;
+          break;
+        }
+      }
+    }
+  }
+
+
+  if (lin->unity) {
+    if (lin->flag == LINSET) {
+      /* Free memory that may have been allocated previously. */
+      if (lin->piximg) free(lin->piximg);
+      if (lin->imgpix) free(lin->imgpix);
+    }
+
+    lin->piximg = 0x0;
+    lin->imgpix = 0x0;
+    lin->i_naxis = 0;
+
+  } else {
+    if (lin->flag != LINSET || lin->i_naxis < n) {
+      if (lin->flag == LINSET) {
+        /* Free memory that may have been allocated previously. */
+        if (lin->piximg) free(lin->piximg);
+        if (lin->imgpix) free(lin->imgpix);
+      }
+
+      /* Allocate memory for internal arrays. */
+      if (!(lin->piximg = calloc(n*n, sizeof(double)))) {
+        return wcserr_set(LIN_ERRMSG(LINERR_MEMORY));
+      }
+
+      if (!(lin->imgpix = calloc(n*n, sizeof(double)))) {
+        free(lin->piximg);
+        return wcserr_set(LIN_ERRMSG(LINERR_MEMORY));
+      }
+
+      lin->i_naxis = n;
+    }
+
+    /* Compute the pixel-to-image transformation matrix. */
+    pc     = lin->pc;
+    piximg = lin->piximg;
+    for (i = 0; i < n; i++) {
+      for (j = 0; j < n; j++) {
+        *(piximg++) = lin->cdelt[i] * (*(pc++));
+      }
+    }
+
+    /* Compute the image-to-pixel transformation matrix. */
+    if ((status = matinv(n, lin->piximg, lin->imgpix))) {
+      return wcserr_set(LIN_ERRMSG(status));
+    }
+  }
+
+
+  lin->flag = LINSET;
+
+  return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int linp2x(lin, ncoord, nelem, pixcrd, imgcrd)
+
+struct linprm *lin;
+int ncoord, nelem;
+const double pixcrd[];
+double imgcrd[];
+
+{
+  int i, j, k, n, status;
+  double temp;
+  register const double *pix;
+  register double *img, *piximg;
+
+
+  /* Initialize. */
+  if (lin == 0x0) return LINERR_NULL_POINTER;
+  if (lin->flag != LINSET) {
+    if ((status = linset(lin))) return status;
+  }
+
+  n = lin->naxis;
+
+
+  /* Convert pixel coordinates to intermediate world coordinates. */
+  pix = pixcrd;
+  img = imgcrd;
+
+  if (lin->unity) {
+    for (k = 0; k < ncoord; k++) {
+      for (i = 0; i < n; i++) {
+        *(img++) = lin->cdelt[i] * (*(pix++) - lin->crpix[i]);
+      }
+
+      pix += (nelem - n);
+      img += (nelem - n);
+    }
+
+  } else {
+    for (k = 0; k < ncoord; k++) {
+      for (i = 0; i < n; i++) {
+        img[i] = 0.0;
+      }
+
+      for (j = 0; j < n; j++) {
+        /* Column-wise multiplication allows this to be cached. */
+        temp = *(pix++) - lin->crpix[j];
+
+        piximg = lin->piximg + j;
+        for (i = 0; i < n; i++, piximg += n) {
+          img[i] += *piximg * temp;
+        }
+      }
+
+      pix += (nelem - n);
+      img += nelem;
+    }
+  }
+
+  return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int linx2p(lin, ncoord, nelem, imgcrd, pixcrd)
+
+struct linprm *lin;
+int ncoord, nelem;
+const double imgcrd[];
+double pixcrd[];
+
+{
+  int i, j, k, n, status;
+  register const double *img;
+  register double *imgpix, *pix;
+
+
+  /* Initialize. */
+  if (lin == 0x0) return LINERR_NULL_POINTER;
+  if (lin->flag != LINSET) {
+    if ((status = linset(lin))) return status;
+  }
+
+  n = lin->naxis;
+
+
+  /* Convert intermediate world coordinates to pixel coordinates. */
+  img = imgcrd;
+  pix = pixcrd;
+
+  if (lin->unity) {
+    for (k = 0; k < ncoord; k++) {
+      for (j = 0; j < n; j++) {
+        *(pix++) = (*(img++) / lin->cdelt[j]) + lin->crpix[j];
+      }
+
+      pix += (nelem - n);
+      img += (nelem - n);
+    }
+
+  } else {
+    for (k = 0; k < ncoord; k++) {
+      imgpix = lin->imgpix;
+
+      for (j = 0; j < n; j++) {
+        *pix = 0.0;
+        for (i = 0; i < n; i++) {
+          *pix += *imgpix * img[i];
+          imgpix++;
+        }
+
+        *(pix++) += lin->crpix[j];
+      }
+
+      pix += (nelem - n);
+      img += nelem;
+    }
+  }
+
+  return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int matinv(int n, const double mat[], double inv[])
+
+{
+  register int i, ij, ik, j, k, kj, pj;
+  int    itemp, *mxl, *lxm, pivot;
+  double colmax, *lu, *rowmax, dtemp;
+
+
+  /* Allocate memory for internal arrays. */
+  if (!(mxl = calloc(n, sizeof(int)))) {
+    return LINERR_MEMORY;
+  }
+  if (!(lxm = calloc(n, sizeof(int)))) {
+    free(mxl);
+    return LINERR_MEMORY;
+  }
+
+  if (!(rowmax = calloc(n, sizeof(double)))) {
+    free(mxl);
+    free(lxm);
+    return LINERR_MEMORY;
+  }
+
+  if (!(lu = calloc(n*n, sizeof(double)))) {
+    free(mxl);
+    free(lxm);
+    free(rowmax);
+    return LINERR_MEMORY;
+  }
+
+
+  /* Initialize arrays. */
+  for (i = 0, ij = 0; i < n; i++) {
+    /* Vector that records row interchanges. */
+    mxl[i] = i;
+
+    rowmax[i] = 0.0;
+
+    for (j = 0; j < n; j++, ij++) {
+      dtemp = fabs(mat[ij]);
+      if (dtemp > rowmax[i]) rowmax[i] = dtemp;
+
+      lu[ij] = mat[ij];
+    }
+
+    /* A row of zeroes indicates a singular matrix. */
+    if (rowmax[i] == 0.0) {
+      free(mxl);
+      free(lxm);
+      free(rowmax);
+      free(lu);
+      return LINERR_SINGULAR_MTX;
+    }
+  }
+
+
+  /* Form the LU triangular factorization using scaled partial pivoting. */
+  for (k = 0; k < n; k++) {
+    /* Decide whether to pivot. */
+    colmax = fabs(lu[k*n+k]) / rowmax[k];
+    pivot = k;
+
+    for (i = k+1; i < n; i++) {
+      ik = i*n + k;
+      dtemp = fabs(lu[ik]) / rowmax[i];
+      if (dtemp > colmax) {
+        colmax = dtemp;
+        pivot = i;
+      }
+    }
+
+    if (pivot > k) {
+      /* We must pivot, interchange the rows of the design matrix. */
+      for (j = 0, pj = pivot*n, kj = k*n; j < n; j++, pj++, kj++) {
+        dtemp = lu[pj];
+        lu[pj] = lu[kj];
+        lu[kj] = dtemp;
+      }
+
+      /* Amend the vector of row maxima. */
+      dtemp = rowmax[pivot];
+      rowmax[pivot] = rowmax[k];
+      rowmax[k] = dtemp;
+
+      /* Record the interchange for later use. */
+      itemp = mxl[pivot];
+      mxl[pivot] = mxl[k];
+      mxl[k] = itemp;
+    }
+
+    /* Gaussian elimination. */
+    for (i = k+1; i < n; i++) {
+      ik = i*n + k;
+
+      /* Nothing to do if lu[ik] is zero. */
+      if (lu[ik] != 0.0) {
+        /* Save the scaling factor. */
+        lu[ik] /= lu[k*n+k];
+
+        /* Subtract rows. */
+        for (j = k+1; j < n; j++) {
+          lu[i*n+j] -= lu[ik]*lu[k*n+j];
+        }
+      }
+    }
+  }
+
+
+  /* mxl[i] records which row of mat corresponds to row i of lu.  */
+  /* lxm[i] records which row of lu  corresponds to row i of mat. */
+  for (i = 0; i < n; i++) {
+    lxm[mxl[i]] = i;
+  }
+
+
+  /* Determine the inverse matrix. */
+  for (i = 0, ij = 0; i < n; i++) {
+    for (j = 0; j < n; j++, ij++) {
+      inv[ij] = 0.0;
+    }
+  }
+
+  for (k = 0; k < n; k++) {
+    inv[lxm[k]*n+k] = 1.0;
+
+    /* Forward substitution. */
+    for (i = lxm[k]+1; i < n; i++) {
+      for (j = lxm[k]; j < i; j++) {
+        inv[i*n+k] -= lu[i*n+j]*inv[j*n+k];
+      }
+    }
+
+    /* Backward substitution. */
+    for (i = n-1; i >= 0; i--) {
+      for (j = i+1; j < n; j++) {
+        inv[i*n+k] -= lu[i*n+j]*inv[j*n+k];
+      }
+      inv[i*n+k] /= lu[i*n+i];
+    }
+   }
+
+   free(mxl);
+   free(lxm);
+   free(rowmax);
+   free(lu);
+
+   return 0;
+}
diff --git a/cextern/wcslib/C/lin.h b/cextern/wcslib/C/lin.h
new file mode 100644
index 0000000..9504776
--- /dev/null
+++ b/cextern/wcslib/C/lin.h
@@ -0,0 +1,448 @@
+/*============================================================================
+
+  WCSLIB 4.16 - an implementation of the FITS WCS standard.
+  Copyright (C) 1995-2012, Mark Calabretta
+
+  This file is part of WCSLIB.
+
+  WCSLIB is free software: you can redistribute it and/or modify it under the
+  terms of the GNU Lesser General Public License as published by the Free
+  Software Foundation, either version 3 of the License, or (at your option)
+  any later version.
+
+  WCSLIB 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 Lesser General Public License for
+  more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with WCSLIB.  If not, see http://www.gnu.org/licenses.
+
+  Direct correspondence concerning WCSLIB to mark at calabretta.id.au
+
+  Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
+  http://www.atnf.csiro.au/people/Mark.Calabretta
+  $Id: lin.h,v 4.16 2012/11/07 04:42:44 cal103 Exp $
+*=============================================================================
+*
+* WCSLIB 4.16 - C routines that implement the FITS World Coordinate System
+* (WCS) standard.  Refer to
+*
+*   "Representations of world coordinates in FITS",
+*   Greisen, E.W., & Calabretta, M.R. 2002, A&A, 395, 1061 (Paper I)
+*
+* Refer to the README file provided with WCSLIB for an overview of the
+* library.
+*
+*
+* Summary of the lin routines
+* ---------------------------
+* These routines apply the linear transformation defined by the FITS WCS
+* standard.  They are based on the linprm struct which contains all
+* information needed for the computations.  The struct contains some members
+* that must be set by the user, and others that are maintained by these
+* routines, somewhat like a C++ class but with no encapsulation.
+*
+* Three routines, linini(), lincpy(), and linfree() are provided to manage the
+* linprm struct, and another, linprt(), prints its contents.
+*
+* A setup routine, linset(), computes intermediate values in the linprm struct
+* from parameters in it that were supplied by the user.  The struct always
+* needs to be set up by linset() but need not be called explicitly - refer to
+* the explanation of linprm::flag.
+*
+* linp2x() and linx2p() implement the WCS linear transformations.
+*
+* An auxiliary matrix inversion routine, matinv(), is included.  It uses
+* LU-triangular factorization with scaled partial pivoting.
+*
+*
+* linini() - Default constructor for the linprm struct
+* ----------------------------------------------------
+* linini() allocates memory for arrays in a linprm struct and sets all members
+* of the struct to default values.
+*
+* PLEASE NOTE: every linprm struct should be initialized by linini(), possibly
+* repeatedly.  On the first invokation, and only the first invokation,
+* linprm::flag must be set to -1 to initialize memory management, regardless
+* of whether linini() will actually be used to allocate memory.
+*
+* Given:
+*   alloc     int       If true, allocate memory unconditionally for arrays in
+*                       the linprm struct.
+*
+*                       If false, it is assumed that pointers to these arrays
+*                       have been set by the user except if they are null
+*                       pointers in which case memory will be allocated for
+*                       them regardless.  (In other words, setting alloc true
+*                       saves having to initalize these pointers to zero.)
+*
+*   naxis     int       The number of world coordinate axes, used to determine
+*                       array sizes.
+*
+* Given and returned:
+*   lin       struct linprm*
+*                       Linear transformation parameters.  Note that, in order
+*                       to initialize memory management linprm::flag should be
+*                       set to -1 when lin is initialized for the first time
+*                       (memory leaks may result if it had already been
+*                       initialized).
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         1: Null linprm pointer passed.
+*                         2: Memory allocation failed.
+*
+*                       For returns > 1, a detailed error message is set in
+*                       linprm::err if enabled, see wcserr_enable().
+*
+*
+* lincpy() - Copy routine for the linprm struct
+* ---------------------------------------------
+* lincpy() does a deep copy of one linprm struct to another, using linini() to
+* allocate memory for its arrays if required.  Only the "information to be
+* provided" part of the struct is copied; a call to linset() is required to
+* initialize the remainder.
+*
+* Given:
+*   alloc     int       If true, allocate memory for the crpix, pc, and cdelt
+*                       arrays in the destination.  Otherwise, it is assumed
+*                       that pointers to these arrays have been set by the
+*                       user except if they are null pointers in which case
+*                       memory will be allocated for them regardless.
+*
+*   linsrc    const struct linprm*
+*                       Struct to copy from.
+*
+* Given and returned:
+*   lindst    struct linprm*
+*                       Struct to copy to.  linprm::flag should be set to -1
+*                       if lindst was not previously initialized (memory leaks
+*                       may result if it was previously initialized).
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         1: Null linprm pointer passed.
+*                         2: Memory allocation failed.
+*
+*                       For returns > 1, a detailed error message is set in
+*                       linprm::err if enabled, see wcserr_enable().
+*
+*
+* linfree() - Destructor for the linprm struct
+* --------------------------------------------
+* linfree() frees memory allocated for the linprm arrays by linini() and/or
+* linset().  linini() keeps a record of the memory it allocates and linfree()
+* will only attempt to free this.
+*
+* PLEASE NOTE: linfree() must not be invoked on a linprm struct that was not
+* initialized by linini().
+*
+* Given:
+*   lin       struct linprm*
+*                       Linear transformation parameters.
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         1: Null linprm pointer passed.
+*
+*
+* linprt() - Print routine for the linprm struct
+* ----------------------------------------------
+* linprt() prints the contents of a linprm struct using wcsprintf().  Mainly
+* intended for diagnostic purposes.
+*
+* Given:
+*   lin       const struct linprm*
+*                       Linear transformation parameters.
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         1: Null linprm pointer passed.
+*
+*
+* linset() - Setup routine for the linprm struct
+* ----------------------------------------------
+* linset(), if necessary, allocates memory for the linprm::piximg and
+* linprm::imgpix arrays and sets up the linprm struct according to information
+* supplied within it - refer to the explanation of linprm::flag.
+*
+* Note that this routine need not be called directly; it will be invoked by
+* linp2x() and linx2p() if the linprm::flag is anything other than a
+* predefined magic value.
+*
+* Given and returned:
+*   lin       struct linprm*
+*                       Linear transformation parameters.
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         1: Null linprm pointer passed.
+*                         2: Memory allocation failed.
+*                         3: PCi_ja matrix is singular.
+*
+*                       For returns > 1, a detailed error message is set in
+*                       linprm::err if enabled, see wcserr_enable().
+*
+*
+* linp2x() - Pixel-to-world linear transformation
+* -----------------------------------------------
+* linp2x() transforms pixel coordinates to intermediate world coordinates.
+*
+* Given and returned:
+*   lin       struct linprm*
+*                       Linear transformation parameters.
+*
+* Given:
+*   ncoord,
+*   nelem     int       The number of coordinates, each of vector length nelem
+*                       but containing lin.naxis coordinate elements.
+*
+*   pixcrd    const double[ncoord][nelem]
+*                       Array of pixel coordinates.
+*
+* Returned:
+*   imgcrd    double[ncoord][nelem]
+*                       Array of intermediate world coordinates.
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         1: Null linprm pointer passed.
+*                         2: Memory allocation failed.
+*                         3: PCi_ja matrix is singular.
+*
+*                       For returns > 1, a detailed error message is set in
+*                       linprm::err if enabled, see wcserr_enable().
+*
+*
+* linx2p() - World-to-pixel linear transformation
+* -----------------------------------------------
+* linx2p() transforms intermediate world coordinates to pixel coordinates.
+*
+* Given and returned:
+*   lin       struct linprm*
+*                       Linear transformation parameters.
+*
+* Given:
+*   ncoord,
+*   nelem     int       The number of coordinates, each of vector length nelem
+*                       but containing lin.naxis coordinate elements.
+*
+*   imgcrd   const double[ncoord][nelem]
+*                       Array of intermediate world coordinates.
+*
+* Returned:
+*   pixcrd    double[ncoord][nelem]
+*                       Array of pixel coordinates.
+*
+*             int       Status return value:
+*                         0: Success.
+*                         1: Null linprm pointer passed.
+*                         2: Memory allocation failed.
+*                         3: PCi_ja matrix is singular.
+*
+*                       For returns > 1, a detailed error message is set in
+*                       linprm::err if enabled, see wcserr_enable().
+*
+*
+* linprm struct - Linear transformation parameters
+* ------------------------------------------------
+* The linprm struct contains all of the information required to perform a
+* linear transformation.  It consists of certain members that must be set by
+* the user ("given") and others that are set by the WCSLIB routines
+* ("returned").
+*
+*   int flag
+*     (Given and returned) This flag must be set to zero whenever any of the
+*     following members of the linprm struct are set or modified:
+*
+*       - linprm::naxis (q.v., not normally set by the user),
+*       - linprm::pc,
+*       - linprm::cdelt.
+*
+*     This signals the initialization routine, linset(), to recompute the
+*     returned members of the linprm struct.  linset() will reset flag to
+*     indicate that this has been done.
+*
+*     PLEASE NOTE: flag should be set to -1 when linini() is called for the
+*     first time for a particular linprm struct in order to initialize memory
+*     management.  It must ONLY be used on the first initialization otherwise
+*     memory leaks may result.
+*
+*   int naxis
+*     (Given or returned) Number of pixel and world coordinate elements.
+*
+*     If linini() is used to initialize the linprm struct (as would normally
+*     be the case) then it will set naxis from the value passed to it as a
+*     function argument.  The user should not subsequently modify it.
+*
+*   double *crpix
+*     (Given) Pointer to the first element of an array of double containing
+*     the coordinate reference pixel, CRPIXja.
+*
+*   double *pc
+*     (Given) Pointer to the first element of the PCi_ja (pixel coordinate)
+*     transformation matrix.  The expected order is
+*
+=       struct linprm lin;
+=       lin.pc = {PC1_1, PC1_2, PC2_1, PC2_2};
+*
+*     This may be constructed conveniently from a 2-D array via
+*
+=       double m[2][2] = {{PC1_1, PC1_2},
+=                         {PC2_1, PC2_2}};
+*
+*     which is equivalent to
+*
+=       double m[2][2];
+=       m[0][0] = PC1_1;
+=       m[0][1] = PC1_2;
+=       m[1][0] = PC2_1;
+=       m[1][1] = PC2_2;
+*
+*     The storage order for this 2-D array is the same as for the 1-D array,
+*     whence
+*
+=       lin.pc = *m;
+*
+*     would be legitimate.
+*
+*   double *cdelt
+*     (Given) Pointer to the first element of an array of double containing
+*     the coordinate increments, CDELTia.
+*
+*   int unity
+*     (Returned) True if the linear transformation matrix is unity.
+*
+*   int padding
+*     (An unused variable inserted for alignment purposes only.)
+*
+*   double *piximg
+*     (Returned) Pointer to the first element of the matrix containing the
+*     product of the CDELTia diagonal matrix and the PCi_ja matrix.
+*
+*   double *imgpix
+*     (Returned) Pointer to the first element of the inverse of the
+*     linprm::piximg matrix.
+*
+*   struct wcserr *err
+*     (Returned) If enabled, when an error status is returned this struct
+*     contains detailed information about the error, see wcserr_enable().
+*
+*   int i_naxis
+*     (For internal use only.)
+*   int m_flag
+*     (For internal use only.)
+*   int m_naxis
+*     (For internal use only.)
+*   int m_padding
+*     (For internal use only.)
+*   double *m_crpix
+*     (For internal use only.)
+*   double *m_pc
+*     (For internal use only.)
+*   double *m_cdelt
+*     (For internal use only.)
+*   void *padding2
+*     (For internal use only.)
+*
+*
+* Global variable: const char *lin_errmsg[] - Status return messages
+* ------------------------------------------------------------------
+* Error messages to match the status value returned from each function.
+*
+*===========================================================================*/
+
+#ifndef WCSLIB_LIN
+#define WCSLIB_LIN
+
+#include "wcserr.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+extern const char *lin_errmsg[];
+
+enum lin_errmsg_enum {
+  LINERR_SUCCESS      = 0,	/* Success. */
+  LINERR_NULL_POINTER = 1,	/* Null linprm pointer passed. */
+  LINERR_MEMORY       = 2,	/* Memory allocation failed. */
+  LINERR_SINGULAR_MTX = 3 	/* PCi_ja matrix is singular. */
+};
+
+struct linprm {
+  /* Initialization flag (see the prologue above).                          */
+  /*------------------------------------------------------------------------*/
+  int flag;			/* Set to zero to force initialization.     */
+
+  /* Parameters to be provided (see the prologue above).                    */
+  /*------------------------------------------------------------------------*/
+  int naxis;			/* The number of axes, given by NAXIS.      */
+  double *crpix;		/* CRPIXja keywords for each pixel axis.    */
+  double *pc;			/* PCi_ja  linear transformation matrix.    */
+  double *cdelt;		/* CDELTia keywords for each coord axis.    */
+
+  /* Information derived from the parameters supplied.                      */
+  /*------------------------------------------------------------------------*/
+  double *piximg;		/* Product of CDELTia and PCi_ja matrices.  */
+  double *imgpix;		/* Inverse of the piximg matrix.            */
+  int    unity;			/* True if the PCi_ja matrix is unity.      */
+
+  /* Error handling                                                         */
+  /*------------------------------------------------------------------------*/
+  int    padding;		/* (Dummy inserted for alignment purposes.) */
+  struct wcserr *err;
+
+  /* Private - the remainder are for memory management.                     */
+  /*------------------------------------------------------------------------*/
+  int    i_naxis;
+  int    m_flag, m_naxis, m_padding;
+  double *m_crpix, *m_pc, *m_cdelt;
+  void   *padding2;
+};
+
+/* Size of the linprm struct in int units, used by the Fortran wrappers. */
+#define LINLEN (sizeof(struct linprm)/sizeof(int))
+
+
+int linini(int alloc, int naxis, struct linprm *lin);
+
+int lincpy(int alloc, const struct linprm *linsrc, struct linprm *lindst);
+
+int linfree(struct linprm *lin);
+
+int linprt(const struct linprm *lin);
+
+int linset(struct linprm *lin);
+
+int linp2x(struct linprm *lin, int ncoord, int nelem, const double pixcrd[],
+           double imgcrd[]);
+
+int linx2p(struct linprm *lin, int ncoord, int nelem, const double imgcrd[],
+           double pixcrd[]);
+
+int matinv(int n, const double mat[], double inv[]);
+
+
+/* Deprecated. */
+#define linini_errmsg lin_errmsg
+#define lincpy_errmsg lin_errmsg
+#define linfree_errmsg lin_errmsg
+#define linprt_errmsg lin_errmsg
+#define linset_errmsg lin_errmsg
+#define linp2x_errmsg lin_errmsg
+#define linx2p_errmsg lin_errmsg
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* WCSLIB_LIN */
diff --git a/cextern/wcslib/C/log.c b/cextern/wcslib/C/log.c
new file mode 100644
index 0000000..69d8578
--- /dev/null
+++ b/cextern/wcslib/C/log.c
@@ -0,0 +1,112 @@
+/*============================================================================
+
+  WCSLIB 4.16 - an implementation of the FITS WCS standard.
+  Copyright (C) 1995-2012, Mark Calabretta
+
+  This file is part of WCSLIB.
+
+  WCSLIB is free software: you can redistribute it and/or modify it under the
+  terms of the GNU Lesser General Public License as published by the Free
+  Software Foundation, either version 3 of the License, or (at your option)
+  any later version.
+
+  WCSLIB 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 Lesser General Public License for
+  more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with WCSLIB.  If not, see http://www.gnu.org/licenses.
+
+  Direct correspondence concerning WCSLIB to mark at calabretta.id.au
+
+  Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
+  http://www.atnf.csiro.au/people/Mark.Calabretta
+  $Id: log.c,v 4.16 2012/11/07 04:42:44 cal103 Exp $
+*===========================================================================*/
+
+#include <math.h>
+
+#include "log.h"
+
+/* Map status return value to message. */
+const char *log_errmsg[] = {
+  "Success",
+  "",
+  "Invalid log-coordinate reference value",
+  "One or more of the x coordinates were invalid",
+  "One or more of the world coordinates were invalid"};
+
+
+/*--------------------------------------------------------------------------*/
+
+int logx2s(
+  double crval,
+  int nx,
+  int sx,
+  int slogc,
+  const double x[],
+  double logc[],
+  int stat[])
+
+{
+  register int ix;
+  register int *statp;
+  register const double *xp;
+  register double *logcp;
+
+
+  if (crval <= 0.0) {
+    return LOGERR_BAD_LOG_REF_VAL;
+  }
+
+  xp = x;
+  logcp = logc;
+  statp = stat;
+  for (ix = 0; ix < nx; ix++, xp += sx, logcp += slogc) {
+    *logcp = crval * exp((*xp) / crval);
+    *(statp++) = 0;
+  }
+
+  return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int logs2x(
+  double crval,
+  int nlogc,
+  int slogc,
+  int sx,
+  const double logc[],
+  double x[],
+  int stat[])
+
+{
+  int status;
+  register int ilogc;
+  register int *statp;
+  register const double *logcp;
+  register double *xp;
+
+
+  if (crval <= 0.0) {
+    return LOGERR_BAD_LOG_REF_VAL;
+  }
+
+  xp = x;
+  logcp = logc;
+  statp = stat;
+  status = 0;
+  for (ilogc = 0; ilogc < nlogc; ilogc++, logcp += slogc, xp += sx) {
+    if (*logcp > 0.0) {
+      *xp = crval * log(*logcp / crval);
+      *(statp++) = 0;
+    } else {
+      *(statp++) = 1;
+      status = LOGERR_BAD_WORLD;
+    }
+  }
+
+  return status;
+}
diff --git a/cextern/wcslib/C/log.h b/cextern/wcslib/C/log.h
new file mode 100644
index 0000000..e134bf7
--- /dev/null
+++ b/cextern/wcslib/C/log.h
@@ -0,0 +1,166 @@
+/*============================================================================
+
+  WCSLIB 4.16 - an implementation of the FITS WCS standard.
+  Copyright (C) 1995-2012, Mark Calabretta
+
+  This file is part of WCSLIB.
+
+  WCSLIB is free software: you can redistribute it and/or modify it under the
+  terms of the GNU Lesser General Public License as published by the Free
+  Software Foundation, either version 3 of the License, or (at your option)
+  any later version.
+
+  WCSLIB 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 Lesser General Public License for
+  more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with WCSLIB.  If not, see http://www.gnu.org/licenses.
+
+  Direct correspondence concerning WCSLIB to mark at calabretta.id.au
+
+  Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
+  http://www.atnf.csiro.au/people/Mark.Calabretta
+  $Id: log.h,v 4.16 2012/11/07 04:42:44 cal103 Exp $
+*=============================================================================
+*
+* WCSLIB 4.16 - C routines that implement logarithmic coordinate systems as
+* defined by the FITS World Coordinate System (WCS) standard.  Refer to
+*
+*   "Representations of world coordinates in FITS",
+*   Greisen, E.W., & Calabretta, M.R. 2002, A&A, 395, 1061 (Paper I)
+*
+*   "Representations of spectral coordinates in FITS",
+*   Greisen, E.W., Calabretta, M.R., Valdes, F.G., & Allen, S.L.
+*   2006, A&A, 446, 747 (Paper III)
+*
+* Refer to the README file provided with WCSLIB for an overview of the
+* library.
+*
+*
+* Summary of the log routines
+* ---------------------------
+* These routines implement the part of the FITS WCS standard that deals with
+* logarithmic coordinates.  They define methods to be used for computing
+* logarithmic world coordinates from intermediate world coordinates (a linear
+* transformation of image pixel coordinates), and vice versa.
+*
+* logx2s() and logs2x() implement the WCS logarithmic coordinate
+* transformations.
+*
+* Argument checking:
+* ------------------
+* The input log-coordinate values are only checked for values that would
+* result in floating point exceptions and the same is true for the
+* log-coordinate reference value.
+*
+* Accuracy:
+* ---------
+* No warranty is given for the accuracy of these routines (refer to the
+* copyright notice); intending users must satisfy for themselves their
+* adequacy for the intended purpose.  However, closure effectively to within
+* double precision rounding error was demonstrated by test routine tlog.c
+* which accompanies this software.
+*
+*
+* logx2s() - Transform to logarithmic coordinates
+* -----------------------------------------------
+* logx2s() transforms intermediate world coordinates to logarithmic
+* coordinates.
+*
+* Given and returned:
+*   crval     double    Log-coordinate reference value (CRVALia).
+*
+* Given:
+*   nx        int       Vector length.
+*
+*   sx        int       Vector stride.
+*
+*   slogc     int       Vector stride.
+*
+*   x         const double[]
+*                       Intermediate world coordinates, in SI units.
+*
+* Returned:
+*   logc      double[]  Logarithmic coordinates, in SI units.
+*
+*   stat      int[]     Status return value status for each vector element:
+*                         0: Success.
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         2: Invalid log-coordinate reference value.
+*
+*
+* logs2x() - Transform logarithmic coordinates
+* --------------------------------------------
+* logs2x() transforms logarithmic world coordinates to intermediate world
+* coordinates.
+*
+* Given and returned:
+*   crval     double    Log-coordinate reference value (CRVALia).
+*
+* Given:
+*   nlogc     int       Vector length.
+*
+*   slogc     int       Vector stride.
+*
+*   sx        int       Vector stride.
+*
+*   logc      const double[]
+*                       Logarithmic coordinates, in SI units.
+*
+* Returned:
+*   x         double[]  Intermediate world coordinates, in SI units.
+*
+*   stat      int[]     Status return value status for each vector element:
+*                         0: Success.
+*                         1: Invalid value of logc.
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         2: Invalid log-coordinate reference value.
+*                         4: One or more of the world-coordinate values
+*                            are incorrect, as indicated by the stat vector.
+*
+*
+* Global variable: const char *log_errmsg[] - Status return messages
+* ------------------------------------------------------------------
+* Error messages to match the status value returned from each function.
+*
+*===========================================================================*/
+
+#ifndef WCSLIB_LOG
+#define WCSLIB_LOG
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern const char *log_errmsg[];
+
+enum log_errmsg_enum {
+  LOGERR_SUCCESS         = 0,	/* Success. */
+  LOGERR_NULL_POINTER    = 1,	/* Null pointer passed. */
+  LOGERR_BAD_LOG_REF_VAL = 2,	/* Invalid log-coordinate reference value. */
+  LOGERR_BAD_X           = 3,	/* One or more of the x coordinates were
+				   invalid. */
+  LOGERR_BAD_WORLD       = 4 	/* One or more of the world coordinates were
+				   invalid. */
+};
+
+int logx2s(double crval, int nx, int sx, int slogc, const double x[],
+           double logc[], int stat[]);
+
+int logs2x(double crval, int nlogc, int slogc, int sx, const double logc[],
+           double x[], int stat[]);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* WCSLIB_LOG */
diff --git a/cextern/wcslib/C/prj.c b/cextern/wcslib/C/prj.c
new file mode 100644
index 0000000..7ad3b17
--- /dev/null
+++ b/cextern/wcslib/C/prj.c
@@ -0,0 +1,7848 @@
+/*============================================================================
+
+  WCSLIB 4.16 - an implementation of the FITS WCS standard.
+  Copyright (C) 1995-2012, Mark Calabretta
+
+  This file is part of WCSLIB.
+
+  WCSLIB is free software: you can redistribute it and/or modify it under the
+  terms of the GNU Lesser General Public License as published by the Free
+  Software Foundation, either version 3 of the License, or (at your option)
+  any later version.
+
+  WCSLIB 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 Lesser General Public License for
+  more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with WCSLIB.  If not, see http://www.gnu.org/licenses.
+
+  Direct correspondence concerning WCSLIB to mark at calabretta.id.au
+
+  Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
+  http://www.atnf.csiro.au/people/Mark.Calabretta
+  $Id: prj.c,v 4.16 2012/11/07 04:42:44 cal103 Exp $
+*===========================================================================*/
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "wcserr.h"
+#include "wcsmath.h"
+#include "wcsprintf.h"
+#include "wcstrig.h"
+#include "wcsutil.h"
+#include "prj.h"
+
+
+/* Projection categories. */
+const int ZENITHAL          = 1;
+const int CYLINDRICAL       = 2;
+const int PSEUDOCYLINDRICAL = 3;
+const int CONVENTIONAL      = 4;
+const int CONIC             = 5;
+const int POLYCONIC         = 6;
+const int QUADCUBE          = 7;
+const int HEALPIX           = 8;
+
+const char prj_categories[9][32] =
+  {"undefined", "zenithal", "cylindrical", "pseudocylindrical",
+  "conventional", "conic", "polyconic", "quadcube", "HEALPix"};
+
+
+/* Projection codes. */
+const int  prj_ncode = 27;
+const char prj_codes[27][4] =
+  {"AZP", "SZP", "TAN", "STG", "SIN", "ARC", "ZPN", "ZEA", "AIR", "CYP",
+   "CEA", "CAR", "MER", "COP", "COE", "COD", "COO", "SFL", "PAR", "MOL",
+   "AIT", "BON", "PCO", "TSC", "CSC", "QSC", "HPX"};
+
+const int AZP = 101;
+const int SZP = 102;
+const int TAN = 103;
+const int STG = 104;
+const int SIN = 105;
+const int ARC = 106;
+const int ZPN = 107;
+const int ZEA = 108;
+const int AIR = 109;
+const int CYP = 201;
+const int CEA = 202;
+const int CAR = 203;
+const int MER = 204;
+const int SFL = 301;
+const int PAR = 302;
+const int MOL = 303;
+const int AIT = 401;
+const int COP = 501;
+const int COE = 502;
+const int COD = 503;
+const int COO = 504;
+const int BON = 601;
+const int PCO = 602;
+const int TSC = 701;
+const int CSC = 702;
+const int QSC = 703;
+const int HPX = 801;
+
+
+/* Map status return value to message. */
+const char *prj_errmsg[] = {
+  "Success",
+  "Null prjprm pointer passed",
+  "Invalid projection parameters",
+  "One or more of the (x,y) coordinates were invalid",
+  "One or more of the (phi,theta) coordinates were invalid"};
+
+/* Convenience macros for generating common error messages. */
+#define PRJERR_BAD_PARAM_SET(function) \
+  wcserr_set(&(prj->err), PRJERR_BAD_PARAM, function, __FILE__, __LINE__, \
+    "Invalid parameters for %s projection", prj->name);
+
+#define PRJERR_BAD_PIX_SET(function) \
+  wcserr_set(&(prj->err), PRJERR_BAD_PIX, function, __FILE__, __LINE__, \
+    "One or more of the (x, y) coordinates were invalid for %s projection", \
+    prj->name);
+
+#define PRJERR_BAD_WORLD_SET(function) \
+  wcserr_set(&(prj->err), PRJERR_BAD_WORLD, function, __FILE__, __LINE__, \
+    "One or more of the (lat, lng) coordinates were invalid for " \
+    "%s projection", prj->name);
+
+#define copysign(X, Y) ((Y) < 0.0 ? -fabs(X) : fabs(X))
+
+
+/*============================================================================
+* Generic routines.
+*
+* prjini initializes a prjprm struct to default values.
+*
+* prjprt prints the contents of a prjprm struct.
+*
+* prjset invokes the specific initialization routine based on the projection
+*        code in the prjprm struct.
+*
+* prjx2s invokes the specific deprojection routine based on the pointer-to-
+*        function stored in the prjprm struct.
+*
+* prjs2x invokes the specific projection routine based on the pointer-to-
+*        function stored in the prjprm struct.
+*
+*---------------------------------------------------------------------------*/
+
+int prjini(prj)
+
+struct prjprm *prj;
+
+{
+  register int k;
+
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+
+  prj->flag = 0;
+
+  strcpy(prj->code, "   ");
+  prj->pv[0]  = 0.0;
+  prj->pv[1]  = UNDEFINED;
+  prj->pv[2]  = UNDEFINED;
+  prj->pv[3]  = UNDEFINED;
+  for (k = 4; k < PVN; prj->pv[k++] = 0.0);
+  prj->r0     = 0.0;
+  prj->phi0   = UNDEFINED;
+  prj->theta0 = UNDEFINED;
+  prj->bounds = 1;
+
+  strcpy(prj->name, "undefined");
+  for (k = 9; k < 40; prj->name[k++] = '\0');
+  prj->category  = 0;
+  prj->pvrange   = 0;
+  prj->simplezen = 0;
+  prj->equiareal = 0;
+  prj->conformal = 0;
+  prj->global    = 0;
+  prj->divergent = 0;
+  prj->x0 = 0.0;
+  prj->y0 = 0.0;
+
+  prj->err = 0x0;
+
+  prj->padding = 0x0;
+  for (k = 0; k < 10; prj->w[k++] = 0.0);
+  prj->m = 0;
+  prj->n = 0;
+  prj->prjx2s = 0x0;
+  prj->prjs2x = 0x0;
+
+  return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int prjfree(prj)
+
+struct prjprm *prj;
+
+{
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+
+  if (prj->err) {
+    free(prj->err);
+    prj->err = 0x0;
+  }
+
+  return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int prjprt(prj)
+
+const struct prjprm *prj;
+
+{
+  char hext[32];
+  int  i, n;
+
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+
+  wcsprintf("       flag: %d\n",  prj->flag);
+  wcsprintf("       code: \"%s\"\n",  prj->code);
+  wcsprintf("         r0: %9f\n", prj->r0);
+  wcsprintf("         pv:");
+  if (prj->pvrange) {
+    n = (prj->pvrange)%100;
+
+    if (prj->pvrange/100) {
+      wcsprintf(" (0)");
+    } else {
+      wcsprintf(" %- 11.5g", prj->pv[0]);
+      n--;
+    }
+
+    for (i = 1; i <= n; i++) {
+      if (i%5 == 1) {
+        wcsprintf("\n           ");
+      }
+
+      if (undefined(prj->pv[i])) {
+        wcsprintf("  UNDEFINED   ");
+      } else {
+        wcsprintf("  %- 11.5g", prj->pv[i]);
+      }
+    }
+    wcsprintf("\n");
+  } else {
+    wcsprintf(" (not used)\n");
+  }
+  if (undefined(prj->phi0)) {
+    wcsprintf("       phi0: UNDEFINED\n");
+  } else {
+    wcsprintf("       phi0: %9f\n", prj->phi0);
+  }
+  if (undefined(prj->theta0)) {
+    wcsprintf("     theta0: UNDEFINED\n");
+  } else {
+    wcsprintf("     theta0: %9f\n", prj->theta0);
+  }
+  wcsprintf("     bounds: %d\n",  prj->bounds);
+
+  wcsprintf("\n");
+  wcsprintf("       name: \"%s\"\n", prj->name);
+  wcsprintf("   category: %d (%s)\n", prj->category,
+                                      prj_categories[prj->category]);
+  wcsprintf("    pvrange: %d\n", prj->pvrange);
+  wcsprintf("  simplezen: %d\n", prj->simplezen);
+  wcsprintf("  equiareal: %d\n", prj->equiareal);
+  wcsprintf("  conformal: %d\n", prj->conformal);
+  wcsprintf("     global: %d\n", prj->global);
+  wcsprintf("  divergent: %d\n", prj->divergent);
+  wcsprintf("         x0: %f\n", prj->x0);
+  wcsprintf("         y0: %f\n", prj->y0);
+
+  WCSPRINTF_PTR("        err: ", prj->err, "\n");
+  if (prj->err) {
+    wcserr_prt(prj->err, "             ");
+  }
+
+  wcsprintf("        w[]:");
+  for (i = 0; i < 5; i++) {
+    wcsprintf("  %- 11.5g", prj->w[i]);
+  }
+  wcsprintf("\n            ");
+  for (i = 5; i < 10; i++) {
+    wcsprintf("  %- 11.5g", prj->w[i]);
+  }
+  wcsprintf("\n");
+  wcsprintf("          m: %d\n", prj->m);
+  wcsprintf("          n: %d\n", prj->n);
+  wcsprintf("     prjx2s: %s\n",
+    wcsutil_fptr2str((int (*)(void))prj->prjx2s, hext));
+  wcsprintf("     prjs2x: %s\n",
+    wcsutil_fptr2str((int (*)(void))prj->prjs2x, hext));
+
+  return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int prjset(prj)
+
+struct prjprm *prj;
+
+{
+  static const char *function = "prjset";
+
+  int status;
+  struct wcserr **err;
+
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+  err = &(prj->err);
+
+  /* Invoke the relevant initialization routine. */
+  prj->code[3] = '\0';
+  if (strcmp(prj->code, "AZP") == 0) {
+    status = azpset(prj);
+  } else if (strcmp(prj->code, "SZP") == 0) {
+    status = szpset(prj);
+  } else if (strcmp(prj->code, "TAN") == 0) {
+    status = tanset(prj);
+  } else if (strcmp(prj->code, "STG") == 0) {
+    status = stgset(prj);
+  } else if (strcmp(prj->code, "SIN") == 0) {
+    status = sinset(prj);
+  } else if (strcmp(prj->code, "ARC") == 0) {
+    status = arcset(prj);
+  } else if (strcmp(prj->code, "ZPN") == 0) {
+    status = zpnset(prj);
+  } else if (strcmp(prj->code, "ZEA") == 0) {
+    status = zeaset(prj);
+  } else if (strcmp(prj->code, "AIR") == 0) {
+    status = airset(prj);
+  } else if (strcmp(prj->code, "CYP") == 0) {
+    status = cypset(prj);
+  } else if (strcmp(prj->code, "CEA") == 0) {
+    status = ceaset(prj);
+  } else if (strcmp(prj->code, "CAR") == 0) {
+    status = carset(prj);
+  } else if (strcmp(prj->code, "MER") == 0) {
+    status = merset(prj);
+  } else if (strcmp(prj->code, "SFL") == 0) {
+    status = sflset(prj);
+  } else if (strcmp(prj->code, "PAR") == 0) {
+    status = parset(prj);
+  } else if (strcmp(prj->code, "MOL") == 0) {
+    status = molset(prj);
+  } else if (strcmp(prj->code, "AIT") == 0) {
+    status = aitset(prj);
+  } else if (strcmp(prj->code, "COP") == 0) {
+    status = copset(prj);
+  } else if (strcmp(prj->code, "COE") == 0) {
+    status = coeset(prj);
+  } else if (strcmp(prj->code, "COD") == 0) {
+    status = codset(prj);
+  } else if (strcmp(prj->code, "COO") == 0) {
+    status = cooset(prj);
+  } else if (strcmp(prj->code, "BON") == 0) {
+    status = bonset(prj);
+  } else if (strcmp(prj->code, "PCO") == 0) {
+    status = pcoset(prj);
+  } else if (strcmp(prj->code, "TSC") == 0) {
+    status = tscset(prj);
+  } else if (strcmp(prj->code, "CSC") == 0) {
+    status = cscset(prj);
+  } else if (strcmp(prj->code, "QSC") == 0) {
+    status = qscset(prj);
+  } else if (strcmp(prj->code, "HPX") == 0) {
+    status = hpxset(prj);
+  } else {
+    /* Unrecognized projection code. */
+    status = wcserr_set(WCSERR_SET(PRJERR_BAD_PARAM),
+               "Unrecognized projection code '%s'", prj->code);
+  }
+
+  return status;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int prjx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)
+
+struct prjprm *prj;
+int nx, ny, sxy, spt;
+const double x[], y[];
+double phi[], theta[];
+int stat[];
+
+{
+  int status;
+
+  /* Initialize. */
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+  if (prj->flag == 0) {
+    if ((status = prjset(prj))) return status;
+  }
+
+  return prj->prjx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat);
+}
+
+/*--------------------------------------------------------------------------*/
+
+int prjs2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)
+
+struct prjprm *prj;
+int nphi, ntheta, spt, sxy;
+const double phi[], theta[];
+double x[], y[];
+int stat[];
+
+{
+  int status;
+
+  /* Initialize. */
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+  if (prj->flag == 0) {
+    if ((status = prjset(prj))) return status;
+  }
+
+  return prj->prjs2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat);
+}
+
+/*============================================================================
+* Internal helper routine used by the *set() routines that forces
+* (x,y) = (0,0) at (phi0,theta0).
+*---------------------------------------------------------------------------*/
+
+int prjoff(prj, phi0, theta0)
+
+struct prjprm *prj;
+const double phi0, theta0;
+
+{
+  int    stat;
+  double x0, y0;
+
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+
+  prj->x0 = 0.0;
+  prj->y0 = 0.0;
+
+  if (undefined(prj->phi0) || undefined(prj->theta0)) {
+    /* Set both to the projection-specific default if either undefined. */
+    prj->phi0   = phi0;
+    prj->theta0 = theta0;
+
+  } else {
+    if (prj->prjs2x(prj, 1, 1, 1, 1, &(prj->phi0), &(prj->theta0), &x0, &y0,
+                    &stat)) {
+      return PRJERR_BAD_PARAM_SET("prjoff");
+    }
+
+    prj->x0 = x0;
+    prj->y0 = y0;
+  }
+
+  return 0;
+}
+
+/*============================================================================
+*   AZP: zenithal/azimuthal perspective projection.
+*
+*   Given:
+*      prj->pv[1]   Distance parameter, mu in units of r0.
+*      prj->pv[2]   Tilt angle, gamma in degrees.
+*
+*   Given and/or returned:
+*      prj->r0      Reset to 180/pi if 0.
+*      prj->phi0    Reset to  0.0 if undefined.
+*      prj->theta0  Reset to 90.0 if undefined.
+*
+*   Returned:
+*      prj->flag     AZP
+*      prj->code    "AZP"
+*      prj->x0      Offset in x.
+*      prj->y0      Offset in y.
+*      prj->w[0]    r0*(mu+1)
+*      prj->w[1]    tan(gamma)
+*      prj->w[2]    sec(gamma)
+*      prj->w[3]    cos(gamma)
+*      prj->w[4]    sin(gamma)
+*      prj->w[5]    asin(-1/mu) for |mu| >= 1, -90 otherwise
+*      prj->w[6]    mu*cos(gamma)
+*      prj->w[7]    1 if |mu*cos(gamma)| < 1, 0 otherwise
+*      prj->prjx2s  Pointer to azpx2s().
+*      prj->prjs2x  Pointer to azps2x().
+*===========================================================================*/
+
+int azpset(prj)
+
+struct prjprm *prj;
+
+{
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+
+  prj->flag = AZP;
+  strcpy(prj->code, "AZP");
+
+  if (undefined(prj->pv[1])) prj->pv[1] = 0.0;
+  if (undefined(prj->pv[2])) prj->pv[2] = 0.0;
+  if (prj->r0 == 0.0) prj->r0 = R2D;
+
+  strcpy(prj->name, "zenithal/azimuthal perspective");
+  prj->category  = ZENITHAL;
+  prj->pvrange   = 102;
+  prj->simplezen = prj->pv[2] == 0.0;
+  prj->equiareal = 0;
+  prj->conformal = 0;
+  prj->global    = 0;
+  prj->divergent = prj->pv[1] <= 1.0;
+
+  prj->w[0] = prj->r0*(prj->pv[1] + 1.0);
+  if (prj->w[0] == 0.0) {
+    return PRJERR_BAD_PARAM_SET("azpset");
+  }
+
+  prj->w[3] = cosd(prj->pv[2]);
+  if (prj->w[3] == 0.0) {
+    return PRJERR_BAD_PARAM_SET("azpset");
+  }
+
+  prj->w[2] = 1.0/prj->w[3];
+  prj->w[4] = sind(prj->pv[2]);
+  prj->w[1] = prj->w[4] / prj->w[3];
+
+  if (fabs(prj->pv[1]) > 1.0) {
+    prj->w[5] = asind(-1.0/prj->pv[1]);
+  } else {
+    prj->w[5] = -90.0;
+  }
+
+  prj->w[6] = prj->pv[1] * prj->w[3];
+  prj->w[7] = (fabs(prj->w[6]) < 1.0) ? 1.0 : 0.0;
+
+  prj->prjx2s = azpx2s;
+  prj->prjs2x = azps2x;
+
+  return prjoff(prj, 0.0, 90.0);
+}
+
+/*--------------------------------------------------------------------------*/
+
+int azpx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)
+
+struct prjprm *prj;
+int nx, ny, sxy, spt;
+const double x[], y[];
+double phi[], theta[];
+int stat[];
+
+{
+  int mx, my, rowlen, rowoff, status;
+  double a, b, q, r, s, t, xj, yj, yc, yc2;
+  const double tol = 1.0e-13;
+  register int ix, iy, *statp;
+  register const double *xp, *yp;
+  register double *phip, *thetap;
+
+
+  /* Initialize. */
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+  if (prj->flag != AZP) {
+    if ((status = azpset(prj))) return status;
+  }
+
+  if (ny > 0) {
+    mx = nx;
+    my = ny;
+  } else {
+    mx = 1;
+    my = 1;
+    ny = nx;
+  }
+
+  status = 0;
+
+
+  /* Do x dependence. */
+  xp = x;
+  rowoff = 0;
+  rowlen = nx*spt;
+  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
+    xj = *xp + prj->x0;
+
+    phip = phi + rowoff;
+    for (iy = 0; iy < my; iy++) {
+      *phip = xj;
+      phip += rowlen;
+    }
+  }
+
+
+  /* Do y dependence. */
+  yp = y;
+  phip   = phi;
+  thetap = theta;
+  statp  = stat;
+  for (iy = 0; iy < ny; iy++, yp += sxy) {
+    yj = *yp + prj->y0;
+
+    yc  = yj*prj->w[3];
+    yc2 = yc*yc;
+
+    q = prj->w[0] + yj*prj->w[4];
+
+    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
+      xj = *phip;
+
+      r = sqrt(xj*xj + yc2);
+      if (r == 0.0) {
+        *phip = 0.0;
+        *thetap = 90.0;
+        *(statp++) = 0;
+
+      } else {
+        *phip = atan2d(xj, -yc);
+
+        s = r / q;
+        t = s*prj->pv[1]/sqrt(s*s + 1.0);
+
+        s = atan2d(1.0, s);
+
+        if (fabs(t) > 1.0) {
+          if (fabs(t) > 1.0+tol) {
+            *thetap = 0.0;
+            *(statp++) = 1;
+            if (!status) status = PRJERR_BAD_PIX_SET("azpx2s");
+            continue;
+          }
+          t = copysign(90.0, t);
+        } else {
+          t = asind(t);
+        }
+
+        a = s - t;
+        b = s + t + 180.0;
+
+        if (a > 90.0) a -= 360.0;
+        if (b > 90.0) b -= 360.0;
+
+        *thetap = (a > b) ? a : b;
+        *(statp++) = 0;
+      }
+    }
+  }
+
+  return status;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int azps2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)
+
+struct prjprm *prj;
+int nphi, ntheta, spt, sxy;
+const double phi[], theta[];
+double x[], y[];
+int stat[];
+
+{
+  int mphi, mtheta, rowlen, rowoff, status;
+  double a, b, cosphi, costhe, r, s, sinphi, sinthe, t;
+  register int iphi, itheta, istat, *statp;
+  register const double *phip, *thetap;
+  register double *xp, *yp;
+
+
+  /* Initialize. */
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+  if (prj->flag != AZP) {
+    if ((status = azpset(prj))) return status;
+  }
+
+  if (ntheta > 0) {
+    mphi   = nphi;
+    mtheta = ntheta;
+  } else {
+    mphi   = 1;
+    mtheta = 1;
+    ntheta = nphi;
+  }
+
+  status = 0;
+
+
+  /* Do phi dependence. */
+  phip = phi;
+  rowoff = 0;
+  rowlen = nphi*sxy;
+  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
+    sincosd(*phip, &sinphi, &cosphi);
+
+    xp = x + rowoff;
+    yp = y + rowoff;
+    for (itheta = 0; itheta < mtheta; itheta++) {
+      *xp = sinphi;
+      *yp = cosphi;
+      xp += rowlen;
+      yp += rowlen;
+    }
+  }
+
+
+  /* Do theta dependence. */
+  thetap = theta;
+  xp = x;
+  yp = y;
+  statp = stat;
+  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
+    sincosd(*thetap, &sinthe, &costhe);
+
+    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
+      s = prj->w[1]*(*yp);
+      t = (prj->pv[1] + sinthe) + costhe*s;
+
+      if (t == 0.0) {
+        *xp = 0.0;
+        *yp = 0.0;
+        *(statp++) = 1;
+        if (!status) status = PRJERR_BAD_WORLD_SET("azps2x");
+
+      } else {
+        r = prj->w[0]*costhe/t;
+
+        /* Bounds checking. */
+        istat = 0;
+        if (prj->bounds) {
+          if (*thetap < prj->w[5]) {
+            /* Overlap. */
+            istat = 1;
+            if (!status) status = PRJERR_BAD_WORLD_SET("azps2x");
+
+          } else if (prj->w[7] > 0.0) {
+            /* Divergence. */
+            t = prj->pv[1] / sqrt(1.0 + s*s);
+
+            if (fabs(t) <= 1.0) {
+              s = atand(-s);
+              t = asind(t);
+              a = s - t;
+              b = s + t + 180.0;
+
+              if (a > 90.0) a -= 360.0;
+              if (b > 90.0) b -= 360.0;
+
+              if (*thetap < ((a > b) ? a : b)) {
+                istat = 1;
+                if (!status) status = PRJERR_BAD_WORLD_SET("azps2x");
+              }
+            }
+          }
+        }
+
+        *xp =  r*(*xp) - prj->x0;
+        *yp = -r*(*yp)*prj->w[2] - prj->y0;
+        *(statp++) = istat;
+      }
+    }
+  }
+
+  return status;
+}
+
+/*============================================================================
+*   SZP: slant zenithal perspective projection.
+*
+*   Given:
+*      prj->pv[1]   Distance of the point of projection from the centre of the
+*                   generating sphere, mu in units of r0.
+*      prj->pv[2]   Native longitude, phi_c, and ...
+*      prj->pv[3]   Native latitude, theta_c, on the planewards side of the
+*                   intersection of the line through the point of projection
+*                   and the centre of the generating sphere, phi_c in degrees.
+*
+*   Given and/or returned:
+*      prj->r0      Reset to 180/pi if 0.
+*      prj->phi0    Reset to  0.0 if undefined.
+*      prj->theta0  Reset to 90.0 if undefined.
+*
+*   Returned:
+*      prj->flag     SZP
+*      prj->code    "SZP"
+*      prj->x0      Fiducial offset in x.
+*      prj->y0      Fiducial offset in y.
+*      prj->w[0]    1/r0
+*      prj->w[1]    xp = -mu*cos(theta_c)*sin(phi_c)
+*      prj->w[2]    yp =  mu*cos(theta_c)*cos(phi_c)
+*      prj->w[3]    zp =  mu*sin(theta_c) + 1
+*      prj->w[4]    r0*xp
+*      prj->w[5]    r0*yp
+*      prj->w[6]    r0*zp
+*      prj->w[7]    (zp - 1)^2
+*      prj->w[8]    asin(1-zp) if |1 - zp| < 1, -90 otherwise
+*      prj->prjx2s  Pointer to szpx2s().
+*      prj->prjs2x  Pointer to szps2x().
+*===========================================================================*/
+
+int szpset(prj)
+
+struct prjprm *prj;
+
+{
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+
+  prj->flag = SZP;
+  strcpy(prj->code, "SZP");
+
+  if (undefined(prj->pv[1])) prj->pv[1] =  0.0;
+  if (undefined(prj->pv[2])) prj->pv[2] =  0.0;
+  if (undefined(prj->pv[3])) prj->pv[3] = 90.0;
+  if (prj->r0 == 0.0) prj->r0 = R2D;
+
+  strcpy(prj->name, "slant zenithal perspective");
+  prj->category  = ZENITHAL;
+  prj->pvrange   = 103;
+  prj->simplezen = prj->pv[3] == 90.0;
+  prj->equiareal = 0;
+  prj->conformal = 0;
+  prj->global    = 0;
+  prj->divergent = prj->pv[1] <= 1.0;
+
+  prj->w[0] = 1.0/prj->r0;
+
+  prj->w[3] = prj->pv[1] * sind(prj->pv[3]) + 1.0;
+  if (prj->w[3] == 0.0) {
+    return PRJERR_BAD_PARAM_SET("szpset");
+  }
+
+  prj->w[1] = -prj->pv[1] * cosd(prj->pv[3]) * sind(prj->pv[2]);
+  prj->w[2] =  prj->pv[1] * cosd(prj->pv[3]) * cosd(prj->pv[2]);
+  prj->w[4] =  prj->r0 * prj->w[1];
+  prj->w[5] =  prj->r0 * prj->w[2];
+  prj->w[6] =  prj->r0 * prj->w[3];
+  prj->w[7] =  (prj->w[3] - 1.0) * prj->w[3] - 1.0;
+
+  if (fabs(prj->w[3] - 1.0) < 1.0) {
+    prj->w[8] = asind(1.0 - prj->w[3]);
+  } else {
+    prj->w[8] = -90.0;
+  }
+
+  prj->prjx2s = szpx2s;
+  prj->prjs2x = szps2x;
+
+  return prjoff(prj, 0.0, 90.0);
+}
+
+/*--------------------------------------------------------------------------*/
+
+int szpx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)
+
+struct prjprm *prj;
+int nx, ny, sxy, spt;
+const double x[], y[];
+double phi[], theta[];
+int stat[];
+
+{
+  int mx, my, rowlen, rowoff, status;
+  double a, b, c, d, r2, sinth1, sinth2, sinthe, t, x1, xr, xy, y1, yr, z;
+  const double tol = 1.0e-13;
+  register int ix, iy, *statp;
+  register const double *xp, *yp;
+  register double *phip, *thetap;
+
+
+  /* Initialize. */
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+  if (prj->flag != SZP) {
+    if ((status = szpset(prj))) return status;
+  }
+
+  if (ny > 0) {
+    mx = nx;
+    my = ny;
+  } else {
+    mx = 1;
+    my = 1;
+    ny = nx;
+  }
+
+  status = 0;
+
+
+  /* Do x dependence. */
+  xp = x;
+  rowoff = 0;
+  rowlen = nx*spt;
+  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
+    xr = (*xp + prj->x0)*prj->w[0];
+
+    phip = phi + rowoff;
+    for (iy = 0; iy < my; iy++) {
+      *phip = xr;
+      phip += rowlen;
+    }
+  }
+
+
+  /* Do y dependence. */
+  yp = y;
+  phip   = phi;
+  thetap = theta;
+  statp  = stat;
+  for (iy = 0; iy < ny; iy++, yp += sxy) {
+    yr = (*yp + prj->y0)*prj->w[0];
+
+    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
+      xr = *phip;
+      r2 = xr*xr + yr*yr;
+
+      x1 = (xr - prj->w[1])/prj->w[3];
+      y1 = (yr - prj->w[2])/prj->w[3];
+      xy = xr*x1 + yr*y1;
+
+      if (r2 < 1.0e-10) {
+        /* Use small angle formula. */
+        z = r2/2.0;
+        *thetap = 90.0 - R2D*sqrt(r2/(1.0 + xy));
+
+      } else {
+        t = x1*x1 + y1*y1;
+        a = t + 1.0;
+        b = xy - t;
+        c = r2 - xy - xy + t - 1.0;
+        d = b*b - a*c;
+
+        /* Check for a solution. */
+        if (d < 0.0) {
+          *phip = 0.0;
+          *thetap = 0.0;
+          *(statp++) = 1;
+          if (!status) status = PRJERR_BAD_PIX_SET("szpx2s");
+          continue;
+        }
+        d = sqrt(d);
+
+        /* Choose solution closest to pole. */
+        sinth1 = (-b + d)/a;
+        sinth2 = (-b - d)/a;
+        sinthe = (sinth1 > sinth2) ? sinth1 : sinth2;
+        if (sinthe > 1.0) {
+          if (sinthe-1.0 < tol) {
+            sinthe = 1.0;
+          } else {
+            sinthe = (sinth1 < sinth2) ? sinth1 : sinth2;
+          }
+        }
+
+        if (sinthe < -1.0) {
+          if (sinthe+1.0 > -tol) {
+            sinthe = -1.0;
+          }
+        }
+
+        if (sinthe > 1.0 || sinthe < -1.0) {
+          *phip   = 0.0;
+          *thetap = 0.0;
+          *(statp++) = 1;
+          if (!status) status = PRJERR_BAD_PIX_SET("szpx2s");
+          continue;
+        }
+
+        *thetap = asind(sinthe);
+
+        z = 1.0 - sinthe;
+      }
+
+      *phip = atan2d(xr - x1*z, -(yr - y1*z));
+      *(statp++) = 0;
+    }
+  }
+
+  return status;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int szps2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)
+
+struct prjprm *prj;
+int nphi, ntheta, spt, sxy;
+const double phi[], theta[];
+double x[], y[];
+int stat[];
+
+{
+  int mphi, mtheta, rowlen, rowoff, status;
+  double a, b, cosphi, r, s, sinphi, t, u, v;
+  register int iphi, itheta, istat, *statp;
+  register const double *phip, *thetap;
+  register double *xp, *yp;
+
+
+  /* Initialize. */
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+  if (prj->flag != SZP) {
+    if ((status = szpset(prj))) return status;
+  }
+
+  if (ntheta > 0) {
+    mphi   = nphi;
+    mtheta = ntheta;
+  } else {
+    mphi   = 1;
+    mtheta = 1;
+    ntheta = nphi;
+  }
+
+  status = 0;
+
+
+  /* Do phi dependence. */
+  phip = phi;
+  rowoff = 0;
+  rowlen = nphi*sxy;
+  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
+    sincosd(*phip, &sinphi, &cosphi);
+
+    xp = x + rowoff;
+    yp = y + rowoff;
+    for (itheta = 0; itheta < mtheta; itheta++) {
+      *xp = sinphi;
+      *yp = cosphi;
+      xp += rowlen;
+      yp += rowlen;
+    }
+  }
+
+
+  /* Do theta dependence. */
+  thetap = theta;
+  xp = x;
+  yp = y;
+  statp = stat;
+  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
+    s = 1.0 - sind(*thetap);
+    t = prj->w[3] - s;
+
+    if (t == 0.0) {
+      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
+        *xp = 0.0;
+        *yp = 0.0;
+        *(statp++) = 1;
+      }
+
+      if (!status) status = PRJERR_BAD_WORLD_SET("szps2x");
+
+    } else {
+      r = prj->w[6]*cosd(*thetap)/t;
+      u = prj->w[4]*s/t + prj->x0;
+      v = prj->w[5]*s/t + prj->y0;
+
+      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
+        /* Bounds checking. */
+        istat = 0;
+        if (prj->bounds) {
+          if (*thetap < prj->w[8]) {
+            /* Divergence. */
+            istat = 1;
+            if (!status) status = PRJERR_BAD_WORLD_SET("szps2x");
+
+          } else if (fabs(prj->pv[1]) > 1.0) {
+            /* Overlap. */
+            s = prj->w[1]*(*xp) - prj->w[2]*(*yp);
+            t = 1.0/sqrt(prj->w[7] + s*s);
+
+            if (fabs(t) <= 1.0) {
+              s = atan2d(s, prj->w[3] - 1.0);
+              t = asind(t);
+              a = s - t;
+              b = s + t + 180.0;
+
+              if (a > 90.0) a -= 360.0;
+              if (b > 90.0) b -= 360.0;
+
+              if (*thetap < ((a > b) ? a : b)) {
+                istat = 1;
+                if (!status) status = PRJERR_BAD_WORLD_SET("szps2x");
+              }
+            }
+          }
+        }
+
+        *xp =  r*(*xp) - u;
+        *yp = -r*(*yp) - v;
+        *(statp++) = istat;
+      }
+    }
+  }
+
+  return status;
+}
+
+
+/*============================================================================
+*   TAN: gnomonic projection.
+*
+*   Given and/or returned:
+*      prj->r0      Reset to 180/pi if 0.
+*      prj->phi0    Reset to  0.0 if undefined.
+*      prj->theta0  Reset to 90.0 if undefined.
+*
+*   Returned:
+*      prj->flag     TAN
+*      prj->code    "TAN"
+*      prj->x0      Fiducial offset in x.
+*      prj->y0      Fiducial offset in y.
+*      prj->prjx2s  Pointer to tanx2s().
+*      prj->prjs2x  Pointer to tans2x().
+*===========================================================================*/
+
+int tanset(prj)
+
+struct prjprm *prj;
+
+{
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+
+  prj->flag = TAN;
+  strcpy(prj->code, "TAN");
+
+  if (prj->r0 == 0.0) prj->r0 = R2D;
+
+  strcpy(prj->name, "gnomonic");
+  prj->category  = ZENITHAL;
+  prj->pvrange   = 0;
+  prj->simplezen = 1;
+  prj->equiareal = 0;
+  prj->conformal = 0;
+  prj->global    = 0;
+  prj->divergent = 1;
+
+  prj->prjx2s = tanx2s;
+  prj->prjs2x = tans2x;
+
+  return prjoff(prj, 0.0, 90.0);
+}
+
+/*--------------------------------------------------------------------------*/
+
+int tanx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)
+
+struct prjprm *prj;
+int nx, ny, sxy, spt;
+const double x[], y[];
+double phi[], theta[];
+int stat[];
+
+{
+  int mx, my, rowlen, rowoff, status;
+  double r, xj, yj, yj2;
+  register int ix, iy, *statp;
+  register const double *xp, *yp;
+  register double *phip, *thetap;
+
+
+  /* Initialize. */
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+  if (prj->flag != TAN) {
+    if ((status = tanset(prj))) return status;
+  }
+
+  if (ny > 0) {
+    mx = nx;
+    my = ny;
+  } else {
+    mx = 1;
+    my = 1;
+    ny = nx;
+  }
+
+
+  /* Do x dependence. */
+  xp = x;
+  rowoff = 0;
+  rowlen = nx*spt;
+  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
+    xj = *xp + prj->x0;
+
+    phip = phi + rowoff;
+    for (iy = 0; iy < my; iy++) {
+      *phip = xj;
+      phip += rowlen;
+    }
+  }
+
+
+  /* Do y dependence. */
+  yp = y;
+  phip   = phi;
+  thetap = theta;
+  statp  = stat;
+  for (iy = 0; iy < ny; iy++, yp += sxy) {
+    yj  = *yp + prj->y0;
+    yj2 = yj*yj;
+
+    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
+      xj = *phip;
+
+      r = sqrt(xj*xj + yj2);
+      if (r == 0.0) {
+        *phip = 0.0;
+      } else {
+        *phip = atan2d(xj, -yj);
+      }
+
+      *thetap = atan2d(prj->r0, r);
+      *(statp++) = 0;
+    }
+  }
+
+  return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int tans2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)
+
+struct prjprm *prj;
+int nphi, ntheta, spt, sxy;
+const double phi[], theta[];
+double x[], y[];
+int stat[];
+
+{
+  int mphi, mtheta, rowlen, rowoff, status;
+  double cosphi, r, s, sinphi;
+  register int iphi, itheta, istat, *statp;
+  register const double *phip, *thetap;
+  register double *xp, *yp;
+
+
+  /* Initialize. */
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+  if (prj->flag != TAN) {
+    if ((status = tanset(prj))) return status;
+  }
+
+  if (ntheta > 0) {
+    mphi   = nphi;
+    mtheta = ntheta;
+  } else {
+    mphi   = 1;
+    mtheta = 1;
+    ntheta = nphi;
+  }
+
+  status = 0;
+
+
+  /* Do phi dependence. */
+  phip = phi;
+  rowoff = 0;
+  rowlen = nphi*sxy;
+  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
+    sincosd(*phip, &sinphi, &cosphi);
+
+    xp = x + rowoff;
+    yp = y + rowoff;
+    for (itheta = 0; itheta < mtheta; itheta++) {
+      *xp = sinphi;
+      *yp = cosphi;
+      xp += rowlen;
+      yp += rowlen;
+    }
+  }
+
+
+  /* Do theta dependence. */
+  thetap = theta;
+  xp = x;
+  yp = y;
+  statp = stat;
+  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
+    s = sind(*thetap);
+    if (s == 0.0) {
+      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
+        *xp = 0.0;
+        *yp = 0.0;
+        *(statp++) = 1;
+      }
+      if (!status) status = PRJERR_BAD_WORLD_SET("tans2x");
+
+    } else {
+      r =  prj->r0*cosd(*thetap)/s;
+
+      istat = 0;
+      if (prj->bounds && s < 0.0) {
+        istat = 1;
+        if (!status) status = PRJERR_BAD_WORLD_SET("tans2x");
+      }
+
+      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
+        *xp =  r*(*xp) - prj->x0;
+        *yp = -r*(*yp) - prj->y0;
+        *(statp++) = istat;
+      }
+    }
+  }
+
+  return status;
+}
+
+/*============================================================================
+*   STG: stereographic projection.
+*
+*   Given and/or returned:
+*      prj->r0      Reset to 180/pi if 0.
+*      prj->phi0    Reset to  0.0 if undefined.
+*      prj->theta0  Reset to 90.0 if undefined.
+*
+*   Returned:
+*      prj->flag     STG
+*      prj->code    "STG"
+*      prj->x0      Fiducial offset in x.
+*      prj->y0      Fiducial offset in y.
+*      prj->w[0]    2*r0
+*      prj->w[1]    1/(2*r0)
+*      prj->prjx2s  Pointer to stgx2s().
+*      prj->prjs2x  Pointer to stgs2x().
+*===========================================================================*/
+
+int stgset(prj)
+
+struct prjprm *prj;
+
+{
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+
+  prj->flag = STG;
+  strcpy(prj->code, "STG");
+
+  strcpy(prj->name, "stereographic");
+  prj->category  = ZENITHAL;
+  prj->pvrange   = 0;
+  prj->simplezen = 1;
+  prj->equiareal = 0;
+  prj->conformal = 1;
+  prj->global    = 0;
+  prj->divergent = 1;
+
+  if (prj->r0 == 0.0) {
+    prj->r0 = R2D;
+    prj->w[0] = 360.0/PI;
+    prj->w[1] = PI/360.0;
+  } else {
+    prj->w[0] = 2.0*prj->r0;
+    prj->w[1] = 1.0/prj->w[0];
+  }
+
+  prj->prjx2s = stgx2s;
+  prj->prjs2x = stgs2x;
+
+  return prjoff(prj, 0.0, 90.0);
+}
+
+/*--------------------------------------------------------------------------*/
+
+int stgx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)
+
+struct prjprm *prj;
+int nx, ny, sxy, spt;
+const double x[], y[];
+double phi[], theta[];
+int stat[];
+
+{
+  int mx, my, rowlen, rowoff, status;
+  double r, xj, yj, yj2;
+  register int ix, iy, *statp;
+  register const double *xp, *yp;
+  register double *phip, *thetap;
+
+
+  /* Initialize. */
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+  if (prj->flag != STG) {
+    if ((status = stgset(prj))) return status;
+  }
+
+  if (ny > 0) {
+    mx = nx;
+    my = ny;
+  } else {
+    mx = 1;
+    my = 1;
+    ny = nx;
+  }
+
+
+  /* Do x dependence. */
+  xp = x;
+  rowoff = 0;
+  rowlen = nx*spt;
+  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
+    xj = *xp + prj->x0;
+
+    phip = phi + rowoff;
+    for (iy = 0; iy < my; iy++) {
+      *phip = xj;
+      phip += rowlen;
+    }
+  }
+
+
+  /* Do y dependence. */
+  yp = y;
+  phip   = phi;
+  thetap = theta;
+  statp  = stat;
+  for (iy = 0; iy < ny; iy++, yp += sxy) {
+    yj  = *yp + prj->y0;
+    yj2 = yj*yj;
+
+    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
+      xj  = *phip;
+
+      r = sqrt(xj*xj + yj2);
+      if (r == 0.0) {
+        *phip = 0.0;
+      } else {
+        *phip = atan2d(xj, -yj);
+      }
+
+      *thetap = 90.0 - 2.0*atand(r*prj->w[1]);
+      *(statp++) = 0;
+    }
+  }
+
+  return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int stgs2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)
+
+struct prjprm *prj;
+int nphi, ntheta, spt, sxy;
+const double phi[], theta[];
+double x[], y[];
+int stat[];
+
+{
+  int mphi, mtheta, rowlen, rowoff, status;
+  double cosphi, r, s, sinphi;
+  register int iphi, itheta, *statp;
+  register const double *phip, *thetap;
+  register double *xp, *yp;
+
+
+  /* Initialize. */
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+  if (prj->flag != STG) {
+    if ((status = stgset(prj))) return status;
+  }
+
+  if (ntheta > 0) {
+    mphi   = nphi;
+    mtheta = ntheta;
+  } else {
+    mphi   = 1;
+    mtheta = 1;
+    ntheta = nphi;
+  }
+
+  status = 0;
+
+
+  /* Do phi dependence. */
+  phip = phi;
+  rowoff = 0;
+  rowlen = nphi*sxy;
+  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
+    sincosd(*phip, &sinphi, &cosphi);
+
+    xp = x + rowoff;
+    yp = y + rowoff;
+    for (itheta = 0; itheta < mtheta; itheta++) {
+      *xp = sinphi;
+      *yp = cosphi;
+      xp += rowlen;
+      yp += rowlen;
+    }
+  }
+
+
+  /* Do theta dependence. */
+  thetap = theta;
+  xp = x;
+  yp = y;
+  statp = stat;
+  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
+    s = 1.0 + sind(*thetap);
+    if (s == 0.0) {
+      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
+        *xp = 0.0;
+        *yp = 0.0;
+        *(statp++) = 1;
+      }
+      if (!status) status = PRJERR_BAD_WORLD_SET("stgs2x");
+
+    } else {
+      r = prj->w[0]*cosd(*thetap)/s;
+
+      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
+        *xp =  r*(*xp) - prj->x0;
+        *yp = -r*(*yp) - prj->y0;
+        *(statp++) = 0;
+      }
+    }
+  }
+
+  return status;
+}
+
+/*============================================================================
+*   SIN: orthographic/synthesis projection.
+*
+*   Given:
+*      prj->pv[1:2] Obliqueness parameters, xi and eta.
+*
+*   Given and/or returned:
+*      prj->r0      Reset to 180/pi if 0.
+*      prj->phi0    Reset to  0.0 if undefined.
+*      prj->theta0  Reset to 90.0 if undefined.
+*
+*   Returned:
+*      prj->flag     SIN
+*      prj->code    "SIN"
+*      prj->x0      Fiducial offset in x.
+*      prj->y0      Fiducial offset in y.
+*      prj->w[0]    1/r0
+*      prj->w[1]    xi**2 + eta**2
+*      prj->w[2]    xi**2 + eta**2 + 1
+*      prj->w[3]    xi**2 + eta**2 - 1
+*      prj->prjx2s  Pointer to sinx2s().
+*      prj->prjs2x  Pointer to sins2x().
+*===========================================================================*/
+
+int sinset(prj)
+
+struct prjprm *prj;
+
+{
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+
+  prj->flag = SIN;
+  strcpy(prj->code, "SIN");
+
+  if (undefined(prj->pv[1])) prj->pv[1] = 0.0;
+  if (undefined(prj->pv[2])) prj->pv[2] = 0.0;
+  if (prj->r0 == 0.0) prj->r0 = R2D;
+
+  strcpy(prj->name, "orthographic/synthesis");
+  prj->category  = ZENITHAL;
+  prj->pvrange   = 102;
+  prj->simplezen = (prj->pv[1] == 0.0 && prj->pv[2] == 0.0);
+  prj->equiareal = 0;
+  prj->conformal = 0;
+  prj->global    = 0;
+  prj->divergent = 0;
+
+  prj->w[0] = 1.0/prj->r0;
+  prj->w[1] = prj->pv[1]*prj->pv[1] + prj->pv[2]*prj->pv[2];
+  prj->w[2] = prj->w[1] + 1.0;
+  prj->w[3] = prj->w[1] - 1.0;
+
+  prj->prjx2s = sinx2s;
+  prj->prjs2x = sins2x;
+
+  return prjoff(prj, 0.0, 90.0);
+}
+
+/*--------------------------------------------------------------------------*/
+
+int sinx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)
+
+struct prjprm *prj;
+int nx, ny, sxy, spt;
+const double x[], y[];
+double phi[], theta[];
+int stat[];
+
+{
+  int mx, my, rowlen, rowoff, status;
+  const double tol = 1.0e-13;
+  double a, b, c, d, eta, r2, sinth1, sinth2, sinthe, x0, xi, x1, xy, y0, y02,
+         y1, z;
+  register int ix, iy, *statp;
+  register const double *xp, *yp;
+  register double *phip, *thetap;
+
+
+  /* Initialize. */
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+  if (prj->flag != SIN) {
+    if ((status = sinset(prj))) return status;
+  }
+
+  xi  = prj->pv[1];
+  eta = prj->pv[2];
+
+  if (ny > 0) {
+    mx = nx;
+    my = ny;
+  } else {
+    mx = 1;
+    my = 1;
+    ny = nx;
+  }
+
+  status = 0;
+
+
+  /* Do x dependence. */
+  xp = x;
+  rowoff = 0;
+  rowlen = nx*spt;
+  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
+    x0 = (*xp + prj->x0)*prj->w[0];
+
+    phip = phi + rowoff;
+    for (iy = 0; iy < my; iy++) {
+      *phip = x0;
+      phip += rowlen;
+    }
+  }
+
+
+  /* Do y dependence. */
+  yp = y;
+  phip   = phi;
+  thetap = theta;
+  statp  = stat;
+  for (iy = 0; iy < ny; iy++, yp += sxy) {
+    y0 = (*yp + prj->y0)*prj->w[0];
+    y02 = y0*y0;
+
+    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
+      /* Compute intermediaries. */
+      x0 = *phip;
+      r2 = x0*x0 + y02;
+
+      if (prj->w[1] == 0.0) {
+        /* Orthographic projection. */
+        if (r2 != 0.0) {
+          *phip = atan2d(x0, -y0);
+        } else {
+          *phip = 0.0;
+        }
+
+        if (r2 < 0.5) {
+          *thetap = acosd(sqrt(r2));
+        } else if (r2 <= 1.0) {
+          *thetap = asind(sqrt(1.0 - r2));
+        } else {
+          *(statp++) = 1;
+          if (!status) status = PRJERR_BAD_PIX_SET("sinx2s")
+          continue;
+        }
+
+      } else {
+        /* "Synthesis" projection. */
+        xy = x0*xi + y0*eta;
+
+        if (r2 < 1.0e-10) {
+          /* Use small angle formula. */
+          z = r2/2.0;
+          *thetap = 90.0 - R2D*sqrt(r2/(1.0 + xy));
+
+        } else {
+          a = prj->w[2];
+          b = xy - prj->w[1];
+          c = r2 - xy - xy + prj->w[3];
+          d = b*b - a*c;
+
+          /* Check for a solution. */
+          if (d < 0.0) {
+            *phip = 0.0;
+            *thetap = 0.0;
+            *(statp++) = 1;
+            if (!status) status = PRJERR_BAD_PIX_SET("sinx2s")
+            continue;
+          }
+          d = sqrt(d);
+
+          /* Choose solution closest to pole. */
+          sinth1 = (-b + d)/a;
+          sinth2 = (-b - d)/a;
+          sinthe = (sinth1 > sinth2) ? sinth1 : sinth2;
+          if (sinthe > 1.0) {
+            if (sinthe-1.0 < tol) {
+              sinthe = 1.0;
+            } else {
+              sinthe = (sinth1 < sinth2) ? sinth1 : sinth2;
+            }
+          }
+
+          if (sinthe < -1.0) {
+            if (sinthe+1.0 > -tol) {
+              sinthe = -1.0;
+            }
+          }
+
+          if (sinthe > 1.0 || sinthe < -1.0) {
+            *phip = 0.0;
+            *thetap = 0.0;
+            *(statp++) = 1;
+            if (!status) status = PRJERR_BAD_PIX_SET("sinx2s")
+            continue;
+          }
+
+          *thetap = asind(sinthe);
+          z = 1.0 - sinthe;
+        }
+
+        x1 = -y0 + eta*z;
+        y1 =  x0 -  xi*z;
+        if (x1 == 0.0 && y1 == 0.0) {
+          *phip = 0.0;
+        } else {
+          *phip = atan2d(y1,x1);
+        }
+      }
+
+      *(statp++) = 0;
+    }
+  }
+
+  return status;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int sins2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)
+
+struct prjprm *prj;
+int nphi, ntheta, spt, sxy;
+const double phi[], theta[];
+double x[], y[];
+int stat[];
+
+{
+  int mphi, mtheta, rowlen, rowoff, status;
+  double cosphi, costhe, sinphi, r, t, z, z1, z2;
+  register int iphi, itheta, istat, *statp;
+  register const double *phip, *thetap;
+  register double *xp, *yp;
+
+
+  /* Initialize. */
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+  if (prj->flag != SIN) {
+    if ((status = sinset(prj))) return status;
+  }
+
+  if (ntheta > 0) {
+    mphi   = nphi;
+    mtheta = ntheta;
+  } else {
+    mphi   = 1;
+    mtheta = 1;
+    ntheta = nphi;
+  }
+
+  status = 0;
+
+
+  /* Do phi dependence. */
+  phip = phi;
+  rowoff = 0;
+  rowlen = nphi*sxy;
+  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
+    sincosd(*phip, &sinphi, &cosphi);
+
+    xp = x + rowoff;
+    yp = y + rowoff;
+    for (itheta = 0; itheta < mtheta; itheta++) {
+      *xp = sinphi;
+      *yp = cosphi;
+      xp += rowlen;
+      yp += rowlen;
+    }
+  }
+
+
+  /* Do theta dependence. */
+  thetap = theta;
+  xp = x;
+  yp = y;
+  statp = stat;
+  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
+    t = (90.0 - fabs(*thetap))*D2R;
+    if (t < 1.0e-5) {
+      if (*thetap > 0.0) {
+         z = t*t/2.0;
+      } else {
+         z = 2.0 - t*t/2.0;
+      }
+      costhe = t;
+    } else {
+      z = 1.0 - sind(*thetap);
+      costhe = cosd(*thetap);
+    }
+    r = prj->r0*costhe;
+
+    if (prj->w[1] == 0.0) {
+      /* Orthographic projection. */
+      istat = 0;
+      if (prj->bounds && *thetap < 0.0) {
+        istat = 1;
+        if (!status) status = PRJERR_BAD_WORLD_SET("sins2x");
+      }
+
+      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
+        *xp =  r*(*xp) - prj->x0;
+        *yp = -r*(*yp) - prj->y0;
+        *(statp++) = istat;
+      }
+
+    } else {
+      /* "Synthesis" projection. */
+      z *= prj->r0;
+      z1 = prj->pv[1]*z - prj->x0;
+      z2 = prj->pv[2]*z - prj->y0;
+
+      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
+        istat = 0;
+        if (prj->bounds) {
+          t = -atand(prj->pv[1]*(*xp) - prj->pv[2]*(*yp));
+          if (*thetap < t) {
+            istat = 1;
+            if (!status) status = PRJERR_BAD_WORLD_SET("sins2x");
+          }
+        }
+
+        *xp =  r*(*xp) + z1;
+        *yp = -r*(*yp) + z2;
+        *(statp++) = istat;
+      }
+    }
+  }
+
+  return status;
+}
+
+/*============================================================================
+*   ARC: zenithal/azimuthal equidistant projection.
+*
+*   Given and/or returned:
+*      prj->r0      Reset to 180/pi if 0.
+*      prj->phi0    Reset to  0.0 if undefined.
+*      prj->theta0  Reset to 90.0 if undefined.
+*
+*   Returned:
+*      prj->flag     ARC
+*      prj->code    "ARC"
+*      prj->x0      Fiducial offset in x.
+*      prj->y0      Fiducial offset in y.
+*      prj->w[0]    r0*(pi/180)
+*      prj->w[1]    (180/pi)/r0
+*      prj->prjx2s  Pointer to arcx2s().
+*      prj->prjs2x  Pointer to arcs2x().
+*===========================================================================*/
+
+int arcset(prj)
+
+struct prjprm *prj;
+
+{
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+
+  prj->flag = ARC;
+  strcpy(prj->code, "ARC");
+
+  strcpy(prj->name, "zenithal/azimuthal equidistant");
+  prj->category  = ZENITHAL;
+  prj->pvrange   = 0;
+  prj->simplezen = 1;
+  prj->equiareal = 0;
+  prj->conformal = 0;
+  prj->global    = 1;
+  prj->divergent = 0;
+
+  if (prj->r0 == 0.0) {
+    prj->r0 = R2D;
+    prj->w[0] = 1.0;
+    prj->w[1] = 1.0;
+  } else {
+    prj->w[0] = prj->r0*D2R;
+    prj->w[1] = 1.0/prj->w[0];
+  }
+
+  prj->prjx2s = arcx2s;
+  prj->prjs2x = arcs2x;
+
+  return prjoff(prj, 0.0, 90.0);
+}
+
+/*--------------------------------------------------------------------------*/
+
+int arcx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)
+
+struct prjprm *prj;
+int nx, ny, sxy, spt;
+const double x[], y[];
+double phi[], theta[];
+int stat[];
+
+{
+  int mx, my, rowlen, rowoff, status;
+  double r, xj, yj, yj2;
+  register int ix, iy, *statp;
+  register const double *xp, *yp;
+  register double *phip, *thetap;
+
+
+  /* Initialize. */
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+  if (prj->flag != ARC) {
+    if ((status = arcset(prj))) return status;
+  }
+
+  if (ny > 0) {
+    mx = nx;
+    my = ny;
+  } else {
+    mx = 1;
+    my = 1;
+    ny = nx;
+  }
+
+
+  /* Do x dependence. */
+  xp = x;
+  rowoff = 0;
+  rowlen = nx*spt;
+  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
+    xj = *xp + prj->x0;
+
+    phip = phi + rowoff;
+    for (iy = 0; iy < my; iy++) {
+      *phip = xj;
+      phip += rowlen;
+    }
+  }
+
+
+  /* Do y dependence. */
+  yp = y;
+  phip   = phi;
+  thetap = theta;
+  statp  = stat;
+  for (iy = 0; iy < ny; iy++, yp += sxy) {
+    yj  = *yp + prj->y0;
+    yj2 = yj*yj;
+
+    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
+      xj = *phip;
+
+      r = sqrt(xj*xj + yj2);
+      if (r == 0.0) {
+        *phip = 0.0;
+        *thetap = 90.0;
+      } else {
+        *phip = atan2d(xj, -yj);
+        *thetap = 90.0 - r*prj->w[1];
+      }
+
+      *(statp++) = 0;
+    }
+  }
+
+  return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int arcs2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)
+
+struct prjprm *prj;
+int nphi, ntheta, spt, sxy;
+const double phi[], theta[];
+double x[], y[];
+int stat[];
+
+{
+  int mphi, mtheta, rowlen, rowoff, status;
+  double cosphi, r, sinphi;
+  register int iphi, itheta, *statp;
+  register const double *phip, *thetap;
+  register double *xp, *yp;
+
+
+  /* Initialize. */
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+  if (prj->flag != ARC) {
+    if ((status = arcset(prj))) return status;
+  }
+
+  if (ntheta > 0) {
+    mphi   = nphi;
+    mtheta = ntheta;
+  } else {
+    mphi   = 1;
+    mtheta = 1;
+    ntheta = nphi;
+  }
+
+
+  /* Do phi dependence. */
+  phip = phi;
+  rowoff = 0;
+  rowlen = nphi*sxy;
+  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
+    sincosd(*phip, &sinphi, &cosphi);
+
+    xp = x + rowoff;
+    yp = y + rowoff;
+    for (itheta = 0; itheta < mtheta; itheta++) {
+      *xp = sinphi;
+      *yp = cosphi;
+      xp += rowlen;
+      yp += rowlen;
+    }
+  }
+
+
+  /* Do theta dependence. */
+  thetap = theta;
+  xp = x;
+  yp = y;
+  statp = stat;
+  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
+    r =  prj->w[0]*(90.0 - *thetap);
+
+    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
+      *xp =  r*(*xp) - prj->x0;
+      *yp = -r*(*yp) - prj->y0;
+      *(statp++) = 0;
+    }
+  }
+
+  return 0;
+}
+
+/*============================================================================
+*   ZPN: zenithal/azimuthal polynomial projection.
+*
+*   Given:
+*      prj->pv[]    Polynomial coefficients.
+*
+*   Given and/or returned:
+*      prj->r0      Reset to 180/pi if 0.
+*      prj->phi0    Reset to  0.0 if undefined.
+*      prj->theta0  Reset to 90.0 if undefined.
+*
+*   Returned:
+*      prj->flag     ZPN
+*      prj->code    "ZPN"
+*      prj->x0      Fiducial offset in x.
+*      prj->y0      Fiducial offset in y.
+*      prj->n       Degree of the polynomial, N.
+*      prj->w[0]    Co-latitude of the first point of inflection, radian.
+*      prj->w[1]    Radius of the first point of inflection (N > 1), radian.
+*      prj->prjx2s  Pointer to zpnx2s().
+*      prj->prjs2x  Pointer to zpns2x().
+*===========================================================================*/
+
+int zpnset(prj)
+
+struct prjprm *prj;
+
+{
+  int j, k, m;
+  double d, d1, d2, r, zd, zd1, zd2;
+  const double tol = 1.0e-13;
+
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+
+  strcpy(prj->code, "ZPN");
+  prj->flag = ZPN;
+
+  if (undefined(prj->pv[1])) prj->pv[1] = 0.0;
+  if (undefined(prj->pv[2])) prj->pv[2] = 0.0;
+  if (undefined(prj->pv[3])) prj->pv[3] = 0.0;
+  if (prj->r0 == 0.0) prj->r0 = R2D;
+
+  strcpy(prj->name, "zenithal/azimuthal polynomial");
+  prj->category  = ZENITHAL;
+  prj->pvrange   = 30;
+  prj->simplezen = 1;
+  prj->equiareal = 0;
+  prj->conformal = 0;
+  prj->global    = 0;
+  prj->divergent = 0;
+
+  /* Find the highest non-zero coefficient. */
+  for (k = PVN-1; k >= 0 && prj->pv[k] == 0.0; k--);
+  if (k < 0) {
+    return PRJERR_BAD_PARAM_SET("zpnset");
+  }
+
+  prj->n = k;
+
+  if (k < 2) {
+    /* No point of inflection. */
+    prj->w[0] = PI;
+
+  } else {
+    /* Find the point of inflection closest to the pole. */
+    zd1 = 0.0;
+    d1  = prj->pv[1];
+    if (d1 <= 0.0) {
+      return PRJERR_BAD_PARAM_SET("zpnset");
+    }
+
+    /* Find the point where the derivative first goes negative. */
+    for (j = 0; j < 180; j++) {
+      zd2 = j*D2R;
+      d2  = 0.0;
+      for (m = k; m > 0; m--) {
+        d2 = d2*zd2 + m*prj->pv[m];
+      }
+
+      if (d2 <= 0.0) break;
+      zd1 = zd2;
+      d1  = d2;
+    }
+
+    if (j == 180) {
+      /* No negative derivative -> no point of inflection. */
+      zd = PI;
+      prj->global = 1;
+    } else {
+      /* Find where the derivative is zero. */
+      for (j = 1; j <= 10; j++) {
+        zd = zd1 - d1*(zd2-zd1)/(d2-d1);
+
+        d = 0.0;
+        for (m = k; m > 0; m--) {
+          d = d*zd + m*prj->pv[m];
+        }
+
+        if (fabs(d) < tol) break;
+
+        if (d < 0.0) {
+          zd2 = zd;
+          d2  = d;
+        } else {
+          zd1 = zd;
+          d1  = d;
+        }
+      }
+    }
+
+    r = 0.0;
+    for (m = k; m >= 0; m--) {
+      r = r*zd + prj->pv[m];
+    }
+    prj->w[0] = zd;
+    prj->w[1] = r;
+  }
+
+  prj->prjx2s = zpnx2s;
+  prj->prjs2x = zpns2x;
+
+  return prjoff(prj, 0.0, 90.0);
+}
+
+/*--------------------------------------------------------------------------*/
+
+int zpnx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)
+
+struct prjprm *prj;
+int nx, ny, sxy, spt;
+const double x[], y[];
+double phi[], theta[];
+int stat[];
+
+{
+  int j, k, m, mx, my, rowlen, rowoff, status;
+  double a, b, c, d, lambda, r, r1, r2, rt, xj, yj, yj2, zd, zd1, zd2;
+  const double tol = 1.0e-13;
+  register int ix, iy, *statp;
+  register const double *xp, *yp;
+  register double *phip, *thetap;
+
+
+  /* Initialize. */
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+  if (prj->flag != ZPN) {
+    if ((status = zpnset(prj))) return status;
+  }
+
+  k = prj->n;
+
+  if (ny > 0) {
+    mx = nx;
+    my = ny;
+  } else {
+    mx = 1;
+    my = 1;
+    ny = nx;
+  }
+
+  status = 0;
+
+
+  /* Do x dependence. */
+  xp = x;
+  rowoff = 0;
+  rowlen = nx*spt;
+  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
+    xj = *xp + prj->x0;
+
+    phip = phi + rowoff;
+    for (iy = 0; iy < my; iy++) {
+      *phip = xj;
+      phip += rowlen;
+    }
+  }
+
+
+  /* Do y dependence. */
+  yp = y;
+  phip   = phi;
+  thetap = theta;
+  statp  = stat;
+  for (iy = 0; iy < ny; iy++, yp += sxy) {
+    yj  = *yp + prj->y0;
+    yj2 = yj*yj;
+
+    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
+      xj = *phip;
+
+      r = sqrt(xj*xj + yj2)/prj->r0;
+      if (r == 0.0) {
+        *phip = 0.0;
+      } else {
+        *phip = atan2d(xj, -yj);
+      }
+
+      if (k < 1) {
+        /* Constant - no solution. */
+        return PRJERR_BAD_PARAM_SET("zpnx2s");
+      } else if (k == 1) {
+        /* Linear. */
+        zd = (r - prj->pv[0])/prj->pv[1];
+      } else if (k == 2) {
+        /* Quadratic. */
+        a = prj->pv[2];
+        b = prj->pv[1];
+        c = prj->pv[0] - r;
+
+        d = b*b - 4.0*a*c;
+        if (d < 0.0) {
+          *thetap = 0.0;
+          *(statp++) = 1;
+          if (!status) status = PRJERR_BAD_PIX_SET("zpnx2s");
+          continue;
+        }
+        d = sqrt(d);
+
+        /* Choose solution closest to pole. */
+        zd1 = (-b + d)/(2.0*a);
+        zd2 = (-b - d)/(2.0*a);
+        zd  = (zd1<zd2) ? zd1 : zd2;
+        if (zd < -tol) zd = (zd1>zd2) ? zd1 : zd2;
+        if (zd < 0.0) {
+          if (zd < -tol) {
+            *thetap = 0.0;
+            *(statp++) = 1;
+            if (!status) status = PRJERR_BAD_PIX_SET("zpnx2s");
+            continue;
+          }
+          zd = 0.0;
+        } else if (zd > PI) {
+          if (zd > PI+tol) {
+            *thetap = 0.0;
+            *(statp++) = 1;
+            if (!status) status = PRJERR_BAD_PIX_SET("zpnx2s");
+            continue;
+          }
+          zd = PI;
+        }
+      } else {
+        /* Higher order - solve iteratively. */
+        zd1 = 0.0;
+        r1  = prj->pv[0];
+        zd2 = prj->w[0];
+        r2  = prj->w[1];
+
+        if (r < r1) {
+          if (r < r1-tol) {
+            *thetap = 0.0;
+            *(statp++) = 1;
+            if (!status) status = PRJERR_BAD_PIX_SET("zpnx2s");
+            continue;
+          }
+          zd = zd1;
+        } else if (r > r2) {
+          if (r > r2+tol) {
+            *thetap = 0.0;
+            *(statp++) = 1;
+            if (!status) status = PRJERR_BAD_PIX_SET("zpnx2s");
+            continue;
+          }
+          zd = zd2;
+        } else {
+          /* Disect the interval. */
+          for (j = 0; j < 100; j++) {
+            lambda = (r2 - r)/(r2 - r1);
+            if (lambda < 0.1) {
+              lambda = 0.1;
+            } else if (lambda > 0.9) {
+              lambda = 0.9;
+            }
+
+            zd = zd2 - lambda*(zd2 - zd1);
+
+            rt = 0.0;
+            for (m = k; m >= 0; m--) {
+              rt = (rt * zd) + prj->pv[m];
+            }
+
+            if (rt < r) {
+              if (r-rt < tol) break;
+              r1 = rt;
+              zd1 = zd;
+            } else {
+              if (rt-r < tol) break;
+              r2 = rt;
+              zd2 = zd;
+            }
+
+            if (fabs(zd2-zd1) < tol) break;
+          }
+        }
+      }
+
+      *thetap = 90.0 - zd*R2D;
+      *(statp++) = 0;
+    }
+  }
+
+  return status;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int zpns2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)
+
+struct prjprm *prj;
+int nphi, ntheta, spt, sxy;
+const double phi[], theta[];
+double x[], y[];
+int stat[];
+
+{
+  int m, mphi, mtheta, rowlen, rowoff, status;
+  double cosphi, r, s, sinphi;
+  register int iphi, itheta, istat, *statp;
+  register const double *phip, *thetap;
+  register double *xp, *yp;
+
+
+  /* Initialize. */
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+  if (prj->flag != ZPN) {
+    if ((status = zpnset(prj))) return status;
+  }
+
+  if (ntheta > 0) {
+    mphi   = nphi;
+    mtheta = ntheta;
+  } else {
+    mphi   = 1;
+    mtheta = 1;
+    ntheta = nphi;
+  }
+
+  status = 0;
+
+
+  /* Do phi dependence. */
+  phip = phi;
+  rowoff = 0;
+  rowlen = nphi*sxy;
+  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
+    sincosd(*phip, &sinphi, &cosphi);
+
+    xp = x + rowoff;
+    yp = y + rowoff;
+    for (itheta = 0; itheta < mtheta; itheta++) {
+      *xp = sinphi;
+      *yp = cosphi;
+      xp += rowlen;
+      yp += rowlen;
+    }
+  }
+
+
+  /* Do theta dependence. */
+  thetap = theta;
+  xp = x;
+  yp = y;
+  statp = stat;
+  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
+    s = (90.0 - *thetap)*D2R;
+
+    r = 0.0;
+    for (m = prj->n; m >= 0; m--) {
+      r = r*s + prj->pv[m];
+    }
+    r *= prj->r0;
+
+    istat = 0;
+    if (prj->bounds && s > prj->w[0]) {
+      istat = 1;
+      if (!status) status = PRJERR_BAD_WORLD_SET("zpns2x");
+    }
+
+    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
+      *xp =  r*(*xp) - prj->x0;
+      *yp = -r*(*yp) - prj->y0;
+      *(statp++) = istat;
+    }
+  }
+
+  return status;
+}
+
+/*============================================================================
+*   ZEA: zenithal/azimuthal equal area projection.
+*
+*   Given and/or returned:
+*      prj->r0      Reset to 180/pi if 0.
+*      prj->phi0    Reset to  0.0 if undefined.
+*      prj->theta0  Reset to 90.0 if undefined.
+*
+*   Returned:
+*      prj->flag     ZEA
+*      prj->code    "ZEA"
+*      prj->x0      Fiducial offset in x.
+*      prj->y0      Fiducial offset in y.
+*      prj->w[0]    2*r0
+*      prj->w[1]    1/(2*r0)
+*      prj->prjx2s  Pointer to zeax2s().
+*      prj->prjs2x  Pointer to zeas2x().
+*===========================================================================*/
+
+int zeaset(prj)
+
+struct prjprm *prj;
+
+{
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+
+  prj->flag = ZEA;
+  strcpy(prj->code, "ZEA");
+
+  strcpy(prj->name, "zenithal/azimuthal equal area");
+  prj->category  = ZENITHAL;
+  prj->pvrange   = 0;
+  prj->simplezen = 1;
+  prj->equiareal = 1;
+  prj->conformal = 0;
+  prj->global    = 1;
+  prj->divergent = 0;
+
+  if (prj->r0 == 0.0) {
+    prj->r0 = R2D;
+    prj->w[0] = 360.0/PI;
+    prj->w[1] = PI/360.0;
+  } else {
+    prj->w[0] = 2.0*prj->r0;
+    prj->w[1] = 1.0/prj->w[0];
+  }
+
+  prj->prjx2s = zeax2s;
+  prj->prjs2x = zeas2x;
+
+  return prjoff(prj, 0.0, 90.0);
+}
+
+/*--------------------------------------------------------------------------*/
+
+int zeax2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)
+
+struct prjprm *prj;
+int nx, ny, sxy, spt;
+const double x[], y[];
+double phi[], theta[];
+int stat[];
+
+{
+  int mx, my, rowlen, rowoff, status;
+  double r, s, xj, yj, yj2;
+  const double tol = 1.0e-12;
+  register int ix, iy, *statp;
+  register const double *xp, *yp;
+  register double *phip, *thetap;
+
+
+  /* Initialize. */
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+  if (prj->flag != ZEA) {
+    if ((status = zeaset(prj))) return status;
+  }
+
+  if (ny > 0) {
+    mx = nx;
+    my = ny;
+  } else {
+    mx = 1;
+    my = 1;
+    ny = nx;
+  }
+
+  status = 0;
+
+
+  /* Do x dependence. */
+  xp = x;
+  rowoff = 0;
+  rowlen = nx*spt;
+  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
+    xj = *xp + prj->x0;
+
+    phip = phi + rowoff;
+    for (iy = 0; iy < my; iy++) {
+      *phip = xj;
+      phip += rowlen;
+    }
+  }
+
+
+  /* Do y dependence. */
+  yp = y;
+  phip   = phi;
+  thetap = theta;
+  statp  = stat;
+  for (iy = 0; iy < ny; iy++, yp += sxy) {
+    yj  = *yp + prj->y0;
+    yj2 = yj*yj;
+
+    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
+      xj  = *phip;
+
+      r = sqrt(xj*xj + yj2);
+      if (r == 0.0) {
+        *phip = 0.0;
+      } else {
+        *phip = atan2d(xj, -yj);
+      }
+
+      s = r*prj->w[1];
+      if (fabs(s) > 1.0) {
+        if (fabs(r - prj->w[0]) < tol) {
+          *thetap = -90.0;
+        } else {
+          *thetap = 0.0;
+          *(statp++) = 1;
+          if (!status) status = PRJERR_BAD_PIX_SET("zeax2s");
+          continue;
+        }
+      } else {
+        *thetap = 90.0 - 2.0*asind(s);
+      }
+
+      *(statp++) = 0;
+    }
+  }
+
+  return status;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int zeas2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)
+
+struct prjprm *prj;
+int nphi, ntheta, spt, sxy;
+const double phi[], theta[];
+double x[], y[];
+int stat[];
+
+{
+  int mphi, mtheta, rowlen, rowoff, status;
+  double cosphi, r, sinphi;
+  register int iphi, itheta, *statp;
+  register const double *phip, *thetap;
+  register double *xp, *yp;
+
+
+  /* Initialize. */
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+  if (prj->flag != ZEA) {
+    if ((status = zeaset(prj))) return status;
+  }
+
+  if (ntheta > 0) {
+    mphi   = nphi;
+    mtheta = ntheta;
+  } else {
+    mphi   = 1;
+    mtheta = 1;
+    ntheta = nphi;
+  }
+
+
+  /* Do phi dependence. */
+  phip = phi;
+  rowoff = 0;
+  rowlen = nphi*sxy;
+  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
+    sincosd(*phip, &sinphi, &cosphi);
+
+    xp = x + rowoff;
+    yp = y + rowoff;
+    for (itheta = 0; itheta < mtheta; itheta++) {
+      *xp = sinphi;
+      *yp = cosphi;
+      xp += rowlen;
+      yp += rowlen;
+    }
+  }
+
+
+  /* Do theta dependence. */
+  thetap = theta;
+  xp = x;
+  yp = y;
+  statp = stat;
+  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
+    r =  prj->w[0]*sind((90.0 - *thetap)/2.0);
+
+    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
+      *xp =  r*(*xp) - prj->x0;
+      *yp = -r*(*yp) - prj->y0;
+      *(statp++) = 0;
+    }
+  }
+
+  return 0;
+}
+
+/*============================================================================
+*   AIR: Airy's projection.
+*
+*   Given:
+*      prj->pv[1]   Latitude theta_b within which the error is minimized, in
+*                   degrees.
+*
+*   Given and/or returned:
+*      prj->r0      Reset to 180/pi if 0.
+*      prj->phi0    Reset to  0.0 if undefined.
+*      prj->theta0  Reset to 90.0 if undefined.
+*
+*   Returned:
+*      prj->flag     AIR
+*      prj->code    "AIR"
+*      prj->x0      Fiducial offset in x.
+*      prj->y0      Fiducial offset in y.
+*      prj->w[0]    2*r0
+*      prj->w[1]    ln(cos(xi_b))/tan(xi_b)**2, where xi_b = (90-theta_b)/2
+*      prj->w[2]    1/2 - prj->w[1]
+*      prj->w[3]    2*r0*prj->w[2]
+*      prj->w[4]    tol, cutoff for using small angle approximation, in
+*                   radians.
+*      prj->w[5]    prj->w[2]*tol
+*      prj->w[6]    (180/pi)/prj->w[2]
+*      prj->prjx2s  Pointer to airx2s().
+*      prj->prjs2x  Pointer to airs2x().
+*===========================================================================*/
+
+int airset(prj)
+
+struct prjprm *prj;
+
+{
+  const double tol = 1.0e-4;
+  double cosxi;
+
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+
+  prj->flag = AIR;
+  strcpy(prj->code, "AIR");
+
+  if (undefined(prj->pv[1])) prj->pv[1] = 90.0;
+  if (prj->r0 == 0.0) prj->r0 = R2D;
+
+  strcpy(prj->name, "Airy's zenithal");
+  prj->category  = ZENITHAL;
+  prj->pvrange   = 101;
+  prj->simplezen = 1;
+  prj->equiareal = 0;
+  prj->conformal = 0;
+  prj->global    = 0;
+  prj->divergent = 1;
+
+  prj->w[0] = 2.0*prj->r0;
+  if (prj->pv[1] == 90.0) {
+    prj->w[1] = -0.5;
+    prj->w[2] =  1.0;
+  } else if (prj->pv[1] > -90.0) {
+    cosxi = cosd((90.0 - prj->pv[1])/2.0);
+    prj->w[1] = log(cosxi)*(cosxi*cosxi)/(1.0-cosxi*cosxi);
+    prj->w[2] = 0.5 - prj->w[1];
+  } else {
+    return PRJERR_BAD_PARAM_SET("airset");
+  }
+
+  prj->w[3] = prj->w[0] * prj->w[2];
+  prj->w[4] = tol;
+  prj->w[5] = prj->w[2]*tol;
+  prj->w[6] = R2D/prj->w[2];
+
+  prj->prjx2s = airx2s;
+  prj->prjs2x = airs2x;
+
+  return prjoff(prj, 0.0, 90.0);
+}
+
+/*--------------------------------------------------------------------------*/
+
+int airx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)
+
+struct prjprm *prj;
+int nx, ny, sxy, spt;
+const double x[], y[];
+double phi[], theta[];
+int stat[];
+
+{
+  int k, mx, my, rowlen, rowoff, status;
+  double cosxi, lambda, r, r1, r2, rt, tanxi, x1, x2, xi, xj, yj, yj2;
+  const double tol = 1.0e-12;
+  register int ix, iy, *statp;
+  register const double *xp, *yp;
+  register double *phip, *thetap;
+
+
+  /* Initialize. */
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+  if (prj->flag != AIR) {
+    if ((status = airset(prj))) return status;
+  }
+
+  if (ny > 0) {
+    mx = nx;
+    my = ny;
+  } else {
+    mx = 1;
+    my = 1;
+    ny = nx;
+  }
+
+  status = 0;
+
+
+  /* Do x dependence. */
+  xp = x;
+  rowoff = 0;
+  rowlen = nx*spt;
+  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
+    xj = *xp + prj->x0;
+
+    phip = phi + rowoff;
+    for (iy = 0; iy < my; iy++) {
+      *phip = xj;
+      phip += rowlen;
+    }
+  }
+
+
+  /* Do y dependence. */
+  yp = y;
+  phip   = phi;
+  thetap = theta;
+  statp  = stat;
+  for (iy = 0; iy < ny; iy++, yp += sxy) {
+    yj  = *yp + prj->y0;
+    yj2 = yj*yj;
+
+    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
+      xj = *phip;
+
+      r = sqrt(xj*xj + yj2)/prj->w[0];
+      if (r == 0.0) {
+        *phip = 0.0;
+      } else {
+        *phip = atan2d(xj, -yj);
+      }
+
+
+      if (r == 0.0) {
+        xi = 0.0;
+      } else if (r < prj->w[5]) {
+        xi = r*prj->w[6];
+      } else {
+        /* Find a solution interval. */
+        x1 = x2 = 1.0;
+        r1 = r2 = 0.0;
+        for (k = 0; k < 30; k++) {
+          x2 = x1/2.0;
+          tanxi = sqrt(1.0-x2*x2)/x2;
+          r2 = -(log(x2)/tanxi + prj->w[1]*tanxi);
+
+          if (r2 >= r) break;
+          x1 = x2;
+          r1 = r2;
+        }
+        if (k == 30) {
+          *thetap = 0.0;
+          *(statp++) = 1;
+          if (!status) status = PRJERR_BAD_PIX_SET("airx2s");
+          continue;
+        }
+
+        for (k = 0; k < 100; k++) {
+          /* Weighted division of the interval. */
+          lambda = (r2-r)/(r2-r1);
+          if (lambda < 0.1) {
+            lambda = 0.1;
+          } else if (lambda > 0.9) {
+            lambda = 0.9;
+          }
+          cosxi = x2 - lambda*(x2-x1);
+
+          tanxi = sqrt(1.0-cosxi*cosxi)/cosxi;
+          rt = -(log(cosxi)/tanxi + prj->w[1]*tanxi);
+
+          if (rt < r) {
+            if (r-rt < tol) break;
+            r1 = rt;
+            x1 = cosxi;
+          } else {
+            if (rt-r < tol) break;
+            r2 = rt;
+            x2 = cosxi;
+          }
+        }
+        if (k == 100) {
+          *thetap = 0.0;
+          *(statp++) = 1;
+          if (!status) status = PRJERR_BAD_PIX_SET("airx2s");
+          continue;
+        }
+
+        xi = acosd(cosxi);
+      }
+
+      *thetap = 90.0 - 2.0*xi;
+      *(statp++) = 0;
+    }
+  }
+
+  return status;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int airs2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)
+
+struct prjprm *prj;
+int nphi, ntheta, spt, sxy;
+const double phi[], theta[];
+double x[], y[];
+int stat[];
+
+{
+  int mphi, mtheta, rowlen, rowoff, status;
+  double cosphi, cosxi, r, tanxi, xi, sinphi;
+  register int iphi, itheta, istat, *statp;
+  register const double *phip, *thetap;
+  register double *xp, *yp;
+
+
+  /* Initialize. */
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+  if (prj->flag != AIR) {
+    if ((status = airset(prj))) return status;
+  }
+
+  if (ntheta > 0) {
+    mphi   = nphi;
+    mtheta = ntheta;
+  } else {
+    mphi   = 1;
+    mtheta = 1;
+    ntheta = nphi;
+  }
+
+  status = 0;
+
+
+  /* Do phi dependence. */
+  phip = phi;
+  rowoff = 0;
+  rowlen = nphi*sxy;
+  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
+    sincosd(*phip, &sinphi, &cosphi);
+
+    xp = x + rowoff;
+    yp = y + rowoff;
+    for (itheta = 0; itheta < mtheta; itheta++) {
+      *xp = sinphi;
+      *yp = cosphi;
+      xp += rowlen;
+      yp += rowlen;
+    }
+  }
+
+
+  /* Do theta dependence. */
+  thetap = theta;
+  xp = x;
+  yp = y;
+  statp = stat;
+  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
+    istat = 0;
+
+    if (*thetap == 90.0) {
+      r = 0.0;
+    } else if (*thetap > -90.0) {
+      xi = D2R*(90.0 - *thetap)/2.0;
+      if (xi < prj->w[4]) {
+        r = xi*prj->w[3];
+      } else {
+        cosxi = cosd((90.0 - *thetap)/2.0);
+        tanxi = sqrt(1.0-cosxi*cosxi)/cosxi;
+        r = -prj->w[0]*(log(cosxi)/tanxi + prj->w[1]*tanxi);
+      }
+    } else {
+      r = 0.0;
+      istat = 1;
+      if (!status) status = PRJERR_BAD_WORLD_SET("airs2x");
+    }
+
+    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
+      *xp =  r*(*xp) - prj->x0;
+      *yp = -r*(*yp) - prj->y0;
+      *(statp++) = istat;
+    }
+  }
+
+  return status;
+}
+
+/*============================================================================
+*   CYP: cylindrical perspective projection.
+*
+*   Given:
+*      prj->pv[1]   Distance of point of projection from the centre of the
+*                   generating sphere, mu, in units of r0.
+*      prj->pv[2]   Radius of the cylinder of projection, lambda, in units of
+*                   r0.
+*
+*   Given and/or returned:
+*      prj->r0      Reset to 180/pi if 0.
+*      prj->phi0    Reset to 0.0 if undefined.
+*      prj->theta0  Reset to 0.0 if undefined.
+*
+*   Returned:
+*      prj->flag     CYP
+*      prj->code    "CYP"
+*      prj->x0      Fiducial offset in x.
+*      prj->y0      Fiducial offset in y.
+*      prj->w[0]    r0*lambda*(pi/180)
+*      prj->w[1]    (180/pi)/(r0*lambda)
+*      prj->w[2]    r0*(mu + lambda)
+*      prj->w[3]    1/(r0*(mu + lambda))
+*      prj->prjx2s  Pointer to cypx2s().
+*      prj->prjs2x  Pointer to cyps2x().
+*===========================================================================*/
+
+int cypset(prj)
+
+struct prjprm *prj;
+
+{
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+
+  prj->flag = CYP;
+  strcpy(prj->code, "CYP");
+
+  if (undefined(prj->pv[1])) prj->pv[1] = 1.0;
+  if (undefined(prj->pv[2])) prj->pv[2] = 1.0;
+
+  strcpy(prj->name, "cylindrical perspective");
+  prj->category  = CYLINDRICAL;
+  prj->pvrange   = 102;
+  prj->simplezen = 0;
+  prj->equiareal = 0;
+  prj->conformal = 0;
+  prj->global    = prj->pv[1] < -1.0 || 0.0 < prj->pv[1];
+  prj->divergent = !prj->global;
+
+  if (prj->r0 == 0.0) {
+    prj->r0 = R2D;
+
+    prj->w[0] = prj->pv[2];
+    if (prj->w[0] == 0.0) {
+      return PRJERR_BAD_PARAM_SET("cypset");
+    }
+
+    prj->w[1] = 1.0/prj->w[0];
+
+    prj->w[2] = R2D*(prj->pv[1] + prj->pv[2]);
+    if (prj->w[2] == 0.0) {
+      return PRJERR_BAD_PARAM_SET("cypset");
+    }
+
+    prj->w[3] = 1.0/prj->w[2];
+  } else {
+    prj->w[0] = prj->r0*prj->pv[2]*D2R;
+    if (prj->w[0] == 0.0) {
+      return PRJERR_BAD_PARAM_SET("cypset");
+    }
+
+    prj->w[1] = 1.0/prj->w[0];
+
+    prj->w[2] = prj->r0*(prj->pv[1] + prj->pv[2]);
+    if (prj->w[2] == 0.0) {
+      return PRJERR_BAD_PARAM_SET("cypset");
+    }
+
+    prj->w[3] = 1.0/prj->w[2];
+  }
+
+  prj->prjx2s = cypx2s;
+  prj->prjs2x = cyps2x;
+
+  return prjoff(prj, 0.0, 0.0);
+}
+
+/*--------------------------------------------------------------------------*/
+
+int cypx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)
+
+struct prjprm *prj;
+int nx, ny, sxy, spt;
+const double x[], y[];
+double phi[], theta[];
+int stat[];
+
+{
+  int mx, my, rowlen, rowoff, status;
+  double eta, s, t;
+  register int ix, iy, *statp;
+  register const double *xp, *yp;
+  register double *phip, *thetap;
+
+
+  /* Initialize. */
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+  if (prj->flag != CYP) {
+    if ((status = cypset(prj))) return status;
+  }
+
+  if (ny > 0) {
+    mx = nx;
+    my = ny;
+  } else {
+    mx = 1;
+    my = 1;
+    ny = nx;
+  }
+
+
+  /* Do x dependence. */
+  xp = x;
+  rowoff = 0;
+  rowlen = nx*spt;
+  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
+    s = prj->w[1]*(*xp + prj->x0);
+
+    phip = phi + rowoff;
+    for (iy = 0; iy < my; iy++) {
+      *phip = s;
+      phip += rowlen;
+    }
+  }
+
+
+  /* Do y dependence. */
+  yp = y;
+  thetap = theta;
+  statp = stat;
+  for (iy = 0; iy < ny; iy++, yp += sxy) {
+    eta = prj->w[3]*(*yp + prj->y0);
+    t = atan2d(eta,1.0) + asind(eta*prj->pv[1]/sqrt(eta*eta+1.0));
+
+    for (ix = 0; ix < mx; ix++, thetap += spt) {
+      *thetap = t;
+      *(statp++) = 0;
+    }
+  }
+
+  return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int cyps2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)
+
+struct prjprm *prj;
+int nphi, ntheta, spt, sxy;
+const double phi[], theta[];
+double x[], y[];
+int stat[];
+
+{
+  int mphi, mtheta, rowlen, rowoff, status;
+  double eta, xi;
+  register int iphi, itheta, istat, *statp;
+  register const double *phip, *thetap;
+  register double *xp, *yp;
+
+
+  /* Initialize. */
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+  if (prj->flag != CYP) {
+    if ((status = cypset(prj))) return status;
+  }
+
+  if (ntheta > 0) {
+    mphi   = nphi;
+    mtheta = ntheta;
+  } else {
+    mphi   = 1;
+    mtheta = 1;
+    ntheta = nphi;
+  }
+
+  status = 0;
+
+
+  /* Do phi dependence. */
+  phip = phi;
+  rowoff = 0;
+  rowlen = nphi*sxy;
+  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
+    xi = prj->w[0]*(*phip) - prj->x0;
+
+    xp = x + rowoff;
+    for (itheta = 0; itheta < mtheta; itheta++) {
+      *xp = xi;
+      xp += rowlen;
+    }
+  }
+
+
+  /* Do theta dependence. */
+  thetap = theta;
+  yp = y;
+  statp = stat;
+  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
+    eta = prj->pv[1] + cosd(*thetap);
+
+    istat = 0;
+    if (eta == 0.0) {
+      istat = 1;
+      if (!status) status = PRJERR_BAD_WORLD_SET("cyps2x");
+
+    } else {
+      eta = prj->w[2]*sind(*thetap)/eta;
+    }
+
+    eta -= prj->y0;
+    for (iphi = 0; iphi < mphi; iphi++, yp += sxy) {
+      *yp = eta;
+      *(statp++) = istat;
+    }
+  }
+
+  return status;
+}
+
+/*============================================================================
+*   CEA: cylindrical equal area projection.
+*
+*   Given:
+*      prj->pv[1]   Square of the cosine of the latitude at which the
+*                   projection is conformal, lambda.
+*
+*   Given and/or returned:
+*      prj->r0      Reset to 180/pi if 0.
+*      prj->phi0    Reset to 0.0 if undefined.
+*      prj->theta0  Reset to 0.0 if undefined.
+*
+*   Returned:
+*      prj->flag     CEA
+*      prj->code    "CEA"
+*      prj->x0      Fiducial offset in x.
+*      prj->y0      Fiducial offset in y.
+*      prj->w[0]    r0*(pi/180)
+*      prj->w[1]    (180/pi)/r0
+*      prj->w[2]    r0/lambda
+*      prj->w[3]    lambda/r0
+*      prj->prjx2s  Pointer to ceax2s().
+*      prj->prjs2x  Pointer to ceas2x().
+*===========================================================================*/
+
+int ceaset(prj)
+
+struct prjprm *prj;
+
+{
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+
+  prj->flag = CEA;
+  strcpy(prj->code, "CEA");
+
+  if (undefined(prj->pv[1])) prj->pv[1] = 1.0;
+
+  strcpy(prj->name, "cylindrical equal area");
+  prj->category  = CYLINDRICAL;
+  prj->pvrange   = 101;
+  prj->simplezen = 0;
+  prj->equiareal = 1;
+  prj->conformal = 0;
+  prj->global    = 1;
+  prj->divergent = 0;
+
+  if (prj->r0 == 0.0) {
+    prj->r0 = R2D;
+    prj->w[0] = 1.0;
+    prj->w[1] = 1.0;
+    if (prj->pv[1] <= 0.0 || prj->pv[1] > 1.0) {
+      return PRJERR_BAD_PARAM_SET("ceaset");
+    }
+    prj->w[2] = prj->r0/prj->pv[1];
+    prj->w[3] = prj->pv[1]/prj->r0;
+  } else {
+    prj->w[0] = prj->r0*D2R;
+    prj->w[1] = R2D/prj->r0;
+    if (prj->pv[1] <= 0.0 || prj->pv[1] > 1.0) {
+      return PRJERR_BAD_PARAM_SET("ceaset");
+    }
+    prj->w[2] = prj->r0/prj->pv[1];
+    prj->w[3] = prj->pv[1]/prj->r0;
+  }
+
+  prj->prjx2s = ceax2s;
+  prj->prjs2x = ceas2x;
+
+  return prjoff(prj, 0.0, 0.0);
+}
+
+/*--------------------------------------------------------------------------*/
+
+int ceax2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)
+
+struct prjprm *prj;
+int nx, ny, sxy, spt;
+const double x[], y[];
+double phi[], theta[];
+int stat[];
+
+{
+  int mx, my, rowlen, rowoff, status;
+  double s;
+  const double tol = 1.0e-13;
+  register int istat, ix, iy, *statp;
+  register const double *xp, *yp;
+  register double *phip, *thetap;
+
+
+  /* Initialize. */
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+  if (prj->flag != CEA) {
+    if ((status = ceaset(prj))) return status;
+  }
+
+  if (ny > 0) {
+    mx = nx;
+    my = ny;
+  } else {
+    mx = 1;
+    my = 1;
+    ny = nx;
+  }
+
+  status = 0;
+
+
+  /* Do x dependence. */
+  xp = x;
+  rowoff = 0;
+  rowlen = nx*spt;
+  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
+    s = prj->w[1]*(*xp + prj->x0);
+
+    phip = phi + rowoff;
+    for (iy = 0; iy < my; iy++) {
+      *phip = s;
+      phip += rowlen;
+    }
+  }
+
+
+  /* Do y dependence. */
+  yp = y;
+  thetap = theta;
+  statp = stat;
+  for (iy = 0; iy < ny; iy++, yp += sxy) {
+    s = prj->w[3]*(*yp + prj->y0);
+
+    istat = 0;
+    if (fabs(s) > 1.0) {
+      if (fabs(s) > 1.0+tol) {
+        s = 0.0;
+        istat = 1;
+        if (!status) status = PRJERR_BAD_PIX_SET("ceax2s");
+      } else {
+        s = copysign(90.0, s);
+      }
+    } else {
+      s = asind(s);
+    }
+
+    for (ix = 0; ix < mx; ix++, thetap += spt) {
+      *thetap = s;
+      *(statp++) = istat;
+    }
+  }
+
+  return status;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int ceas2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)
+
+struct prjprm *prj;
+int nphi, ntheta, spt, sxy;
+const double phi[], theta[];
+double x[], y[];
+int stat[];
+
+{
+  int mphi, mtheta, rowlen, rowoff, status;
+  double eta, xi;
+  register int iphi, itheta, *statp;
+  register const double *phip, *thetap;
+  register double *xp, *yp;
+
+
+  /* Initialize. */
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+  if (prj->flag != CEA) {
+    if ((status = ceaset(prj))) return status;
+  }
+
+  if (ntheta > 0) {
+    mphi   = nphi;
+    mtheta = ntheta;
+  } else {
+    mphi   = 1;
+    mtheta = 1;
+    ntheta = nphi;
+  }
+
+
+  /* Do phi dependence. */
+  phip = phi;
+  rowoff = 0;
+  rowlen = nphi*sxy;
+  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
+    xi = prj->w[0]*(*phip) - prj->x0;
+
+    xp = x + rowoff;
+    for (itheta = 0; itheta < mtheta; itheta++) {
+      *xp = xi;
+      xp += rowlen;
+    }
+  }
+
+
+  /* Do theta dependence. */
+  thetap = theta;
+  yp = y;
+  statp = stat;
+  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
+    eta = prj->w[2]*sind(*thetap) - prj->y0;
+
+    for (iphi = 0; iphi < mphi; iphi++, yp += sxy) {
+      *yp = eta;
+      *(statp++) = 0;
+    }
+  }
+
+  return 0;
+}
+
+/*============================================================================
+*   CAR: Plate carree projection.
+*
+*   Given and/or returned:
+*      prj->r0      Reset to 180/pi if 0.
+*      prj->phi0    Reset to 0.0 if undefined.
+*      prj->theta0  Reset to 0.0 if undefined.
+*
+*   Returned:
+*      prj->flag     CAR
+*      prj->code    "CAR"
+*      prj->x0      Fiducial offset in x.
+*      prj->y0      Fiducial offset in y.
+*      prj->w[0]    r0*(pi/180)
+*      prj->w[1]    (180/pi)/r0
+*      prj->prjx2s  Pointer to carx2s().
+*      prj->prjs2x  Pointer to cars2x().
+*===========================================================================*/
+
+int carset(prj)
+
+struct prjprm *prj;
+
+{
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+
+  prj->flag = CAR;
+  strcpy(prj->code, "CAR");
+
+  strcpy(prj->name, "plate caree");
+  prj->category  = CYLINDRICAL;
+  prj->pvrange   = 0;
+  prj->simplezen = 0;
+  prj->equiareal = 0;
+  prj->conformal = 0;
+  prj->global    = 1;
+  prj->divergent = 0;
+
+  if (prj->r0 == 0.0) {
+    prj->r0 = R2D;
+    prj->w[0] = 1.0;
+    prj->w[1] = 1.0;
+  } else {
+    prj->w[0] = prj->r0*D2R;
+    prj->w[1] = 1.0/prj->w[0];
+  }
+
+  prj->prjx2s = carx2s;
+  prj->prjs2x = cars2x;
+
+  return prjoff(prj, 0.0, 0.0);
+}
+
+/*--------------------------------------------------------------------------*/
+
+int carx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)
+
+struct prjprm *prj;
+int nx, ny, sxy, spt;
+const double x[], y[];
+double phi[], theta[];
+int stat[];
+
+{
+  int mx, my, rowlen, rowoff, status;
+  double s, t;
+  register int ix, iy, *statp;
+  register const double *xp, *yp;
+  register double *phip, *thetap;
+
+
+  /* Initialize. */
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+  if (prj->flag != CAR) {
+    if ((status = carset(prj))) return status;
+  }
+
+  if (ny > 0) {
+    mx = nx;
+    my = ny;
+  } else {
+    mx = 1;
+    my = 1;
+    ny = nx;
+  }
+
+
+  /* Do x dependence. */
+  xp = x;
+  rowoff = 0;
+  rowlen = nx*spt;
+  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
+    s = prj->w[1]*(*xp + prj->x0);
+
+    phip = phi + rowoff;
+    for (iy = 0; iy < my; iy++) {
+      *phip = s;
+      phip += rowlen;
+    }
+  }
+
+
+  /* Do y dependence. */
+  yp = y;
+  thetap = theta;
+  statp = stat;
+  for (iy = 0; iy < ny; iy++, yp += sxy) {
+    t = prj->w[1]*(*yp + prj->y0);
+
+    for (ix = 0; ix < mx; ix++, thetap += spt) {
+      *thetap = t;
+      *(statp++) = 0;
+    }
+  }
+
+  return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int cars2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)
+
+struct prjprm *prj;
+int nphi, ntheta, spt, sxy;
+const double phi[], theta[];
+double x[], y[];
+int stat[];
+
+{
+  int mphi, mtheta, rowlen, rowoff, status;
+  double eta, xi;
+  register int iphi, itheta, *statp;
+  register const double *phip, *thetap;
+  register double *xp, *yp;
+
+
+  /* Initialize. */
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+  if (prj->flag != CAR) {
+    if ((status = carset(prj))) return status;
+  }
+
+  if (ntheta > 0) {
+    mphi   = nphi;
+    mtheta = ntheta;
+  } else {
+    mphi   = 1;
+    mtheta = 1;
+    ntheta = nphi;
+  }
+
+
+  /* Do phi dependence. */
+  phip = phi;
+  rowoff = 0;
+  rowlen = nphi*sxy;
+  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
+    xi = prj->w[0]*(*phip) - prj->x0;
+
+    xp = x + rowoff;
+    for (itheta = 0; itheta < mtheta; itheta++) {
+      *xp = xi;
+      xp += rowlen;
+    }
+  }
+
+
+  /* Do theta dependence. */
+  thetap = theta;
+  yp = y;
+  statp = stat;
+  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
+    eta = prj->w[0]*(*thetap) - prj->y0;
+
+    for (iphi = 0; iphi < mphi; iphi++, yp += sxy) {
+      *yp = eta;
+      *(statp++) = 0;
+    }
+  }
+
+  return 0;
+}
+
+/*============================================================================
+*   MER: Mercator's projection.
+*
+*   Given and/or returned:
+*      prj->r0      Reset to 180/pi if 0.
+*      prj->phi0    Reset to 0.0 if undefined.
+*      prj->theta0  Reset to 0.0 if undefined.
+*
+*   Returned:
+*      prj->flag     MER
+*      prj->code    "MER"
+*      prj->x0      Fiducial offset in x.
+*      prj->y0      Fiducial offset in y.
+*      prj->w[0]    r0*(pi/180)
+*      prj->w[1]    (180/pi)/r0
+*      prj->prjx2s  Pointer to merx2s().
+*      prj->prjs2x  Pointer to mers2x().
+*===========================================================================*/
+
+int merset(prj)
+
+struct prjprm *prj;
+
+{
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+
+  prj->flag = MER;
+  strcpy(prj->code, "MER");
+
+  strcpy(prj->name, "Mercator's");
+  prj->category  = CYLINDRICAL;
+  prj->pvrange   = 0;
+  prj->simplezen = 0;
+  prj->equiareal = 0;
+  prj->conformal = 1;
+  prj->global    = 0;
+  prj->divergent = 1;
+
+  if (prj->r0 == 0.0) {
+    prj->r0 = R2D;
+    prj->w[0] = 1.0;
+    prj->w[1] = 1.0;
+  } else {
+    prj->w[0] = prj->r0*D2R;
+    prj->w[1] = 1.0/prj->w[0];
+  }
+
+  prj->prjx2s = merx2s;
+  prj->prjs2x = mers2x;
+
+  return prjoff(prj, 0.0, 0.0);
+}
+
+/*--------------------------------------------------------------------------*/
+
+int merx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)
+
+struct prjprm *prj;
+int nx, ny, sxy, spt;
+const double x[], y[];
+double phi[], theta[];
+int stat[];
+
+{
+  int mx, my, rowlen, rowoff, status;
+  double s, t;
+  register int ix, iy, *statp;
+  register const double *xp, *yp;
+  register double *phip, *thetap;
+
+
+  /* Initialize. */
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+  if (prj->flag != MER) {
+    if ((status = merset(prj))) return status;
+  }
+
+  if (ny > 0) {
+    mx = nx;
+    my = ny;
+  } else {
+    mx = 1;
+    my = 1;
+    ny = nx;
+  }
+
+
+  /* Do x dependence. */
+  xp = x;
+  rowoff = 0;
+  rowlen = nx*spt;
+  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
+    s = prj->w[1]*(*xp + prj->x0);
+
+    phip = phi + rowoff;
+    for (iy = 0; iy < my; iy++) {
+      *phip = s;
+      phip += rowlen;
+    }
+  }
+
+
+  /* Do y dependence. */
+  yp = y;
+  thetap = theta;
+  statp  = stat;
+  for (iy = 0; iy < ny; iy++, yp += sxy) {
+    t = 2.0*atand(exp((*yp + prj->y0)/prj->r0)) - 90.0;
+
+    for (ix = 0; ix < mx; ix++, thetap += spt) {
+      *thetap = t;
+      *(statp++) = 0;
+    }
+  }
+
+  return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int mers2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)
+
+struct prjprm *prj;
+int nphi, ntheta, spt, sxy;
+const double phi[], theta[];
+double x[], y[];
+int stat[];
+
+{
+  int mphi, mtheta, rowlen, rowoff, status;
+  double eta, xi;
+  register int iphi, itheta, istat, *statp;
+  register const double *phip, *thetap;
+  register double *xp, *yp;
+
+
+  /* Initialize. */
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+  if (prj->flag != MER) {
+    if ((status = merset(prj))) return status;
+  }
+
+  if (ntheta > 0) {
+    mphi   = nphi;
+    mtheta = ntheta;
+  } else {
+    mphi   = 1;
+    mtheta = 1;
+    ntheta = nphi;
+  }
+
+  status = 0;
+
+
+  /* Do phi dependence. */
+  phip = phi;
+  rowoff = 0;
+  rowlen = nphi*sxy;
+  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
+    xi  = prj->w[0]*(*phip) - prj->x0;
+
+    xp = x + rowoff;
+    for (itheta = 0; itheta < mtheta; itheta++) {
+      *xp = xi;
+      xp += rowlen;
+    }
+  }
+
+
+  /* Do theta dependence. */
+  thetap = theta;
+  yp = y;
+  statp = stat;
+  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
+    istat = 0;
+
+    if (*thetap <= -90.0 || *thetap >= 90.0) {
+      eta = 0.0;
+      istat = 1;
+      if (!status) status = PRJERR_BAD_WORLD_SET("mers2x");
+    } else {
+      eta = prj->r0*log(tand((*thetap+90.0)/2.0)) - prj->y0;
+    }
+
+    for (iphi = 0; iphi < mphi; iphi++, yp += sxy) {
+      *yp = eta;
+      *(statp++) = istat;
+    }
+  }
+
+  return status;
+}
+
+/*============================================================================
+*   SFL: Sanson-Flamsteed ("global sinusoid") projection.
+*
+*   Given and/or returned:
+*      prj->r0      Reset to 180/pi if 0.
+*      prj->phi0    Reset to 0.0 if undefined.
+*      prj->theta0  Reset to 0.0 if undefined.
+*
+*   Returned:
+*      prj->flag     SFL
+*      prj->code    "SFL"
+*      prj->x0      Fiducial offset in x.
+*      prj->y0      Fiducial offset in y.
+*      prj->w[0]    r0*(pi/180)
+*      prj->w[1]    (180/pi)/r0
+*      prj->prjx2s  Pointer to sflx2s().
+*      prj->prjs2x  Pointer to sfls2x().
+*===========================================================================*/
+
+int sflset(prj)
+
+struct prjprm *prj;
+
+{
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+
+  prj->flag = SFL;
+  strcpy(prj->code, "SFL");
+
+  strcpy(prj->name, "Sanson-Flamsteed");
+  prj->category  = PSEUDOCYLINDRICAL;
+  prj->pvrange   = 0;
+  prj->simplezen = 0;
+  prj->equiareal = 1;
+  prj->conformal = 0;
+  prj->global    = 1;
+  prj->divergent = 0;
+
+  if (prj->r0 == 0.0) {
+    prj->r0 = R2D;
+    prj->w[0] = 1.0;
+    prj->w[1] = 1.0;
+  } else {
+    prj->w[0] = prj->r0*D2R;
+    prj->w[1] = 1.0/prj->w[0];
+  }
+
+  prj->prjx2s = sflx2s;
+  prj->prjs2x = sfls2x;
+
+  return prjoff(prj, 0.0, 0.0);
+}
+
+/*--------------------------------------------------------------------------*/
+
+int sflx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)
+
+struct prjprm *prj;
+int nx, ny, sxy, spt;
+const double x[], y[];
+double phi[], theta[];
+int stat[];
+
+{
+  int mx, my, rowlen, rowoff, status;
+  double s, t, yj;
+  register int istat, ix, iy, *statp;
+  register const double *xp, *yp;
+  register double *phip, *thetap;
+
+
+  /* Initialize. */
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+  if (prj->flag != SFL) {
+    if ((status = sflset(prj))) return status;
+  }
+
+  if (ny > 0) {
+    mx = nx;
+    my = ny;
+  } else {
+    mx = 1;
+    my = 1;
+    ny = nx;
+  }
+
+  status = 0;
+
+
+  /* Do x dependence. */
+  xp = x;
+  rowoff = 0;
+  rowlen = nx*spt;
+  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
+    s = prj->w[1]*(*xp + prj->x0);
+
+    phip = phi + rowoff;
+    for (iy = 0; iy < my; iy++) {
+      *phip = s;
+      phip += rowlen;
+    }
+  }
+
+
+  /* Do y dependence. */
+  yp = y;
+  phip   = phi;
+  thetap = theta;
+  statp  = stat;
+  for (iy = 0; iy < ny; iy++, yp += sxy) {
+    yj = *yp + prj->y0;
+    s = cos(yj/prj->r0);
+
+    istat = 0;
+    if (s == 0.0) {
+      istat = 1;
+      if (!status) status = PRJERR_BAD_PIX_SET("sflx2s");
+    } else {
+      s = 1.0/s;
+    }
+
+    t = prj->w[1]*yj;
+
+    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
+      *phip  *= s;
+      *thetap = t;
+      *(statp++) = istat;
+    }
+  }
+
+  return status;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int sfls2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)
+
+struct prjprm *prj;
+int nphi, ntheta, spt, sxy;
+const double phi[], theta[];
+double x[], y[];
+int stat[];
+
+{
+  int mphi, mtheta, rowlen, rowoff, status;
+  double eta, xi;
+  register int iphi, itheta, *statp;
+  register const double *phip, *thetap;
+  register double *xp, *yp;
+
+
+  /* Initialize. */
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+  if (prj->flag != SFL) {
+    if ((status = sflset(prj))) return status;
+  }
+
+  if (ntheta > 0) {
+    mphi   = nphi;
+    mtheta = ntheta;
+  } else {
+    mphi   = 1;
+    mtheta = 1;
+    ntheta = nphi;
+  }
+
+
+  /* Do phi dependence. */
+  phip = phi;
+  rowoff = 0;
+  rowlen = nphi*sxy;
+  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
+    xi = prj->w[0]*(*phip);
+
+    xp = x + rowoff;
+    for (itheta = 0; itheta < mtheta; itheta++) {
+      *xp = xi;
+      xp += rowlen;
+    }
+  }
+
+
+  /* Do theta dependence. */
+  thetap = theta;
+  xp = x;
+  yp = y;
+  statp = stat;
+  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
+    xi  = cosd(*thetap);
+    eta = prj->w[0]*(*thetap) - prj->y0;
+
+    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
+      *xp = xi*(*xp) - prj->x0;
+      *yp = eta;
+      *(statp++) = 0;
+    }
+  }
+
+  return 0;
+}
+
+/*============================================================================
+*   PAR: parabolic projection.
+*
+*   Given and/or returned:
+*      prj->r0      Reset to 180/pi if 0.
+*      prj->phi0    Reset to 0.0 if undefined.
+*      prj->theta0  Reset to 0.0 if undefined.
+*
+*   Returned:
+*      prj->flag     PAR
+*      prj->code    "PAR"
+*      prj->x0      Fiducial offset in x.
+*      prj->y0      Fiducial offset in y.
+*      prj->w[0]    r0*(pi/180)
+*      prj->w[1]    (180/pi)/r0
+*      prj->w[2]    pi*r0
+*      prj->w[3]    1/(pi*r0)
+*      prj->prjx2s  Pointer to parx2s().
+*      prj->prjs2x  Pointer to pars2x().
+*===========================================================================*/
+
+int parset(prj)
+
+struct prjprm *prj;
+
+{
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+
+  prj->flag = PAR;
+  strcpy(prj->code, "PAR");
+
+  strcpy(prj->name, "parabolic");
+  prj->category  = PSEUDOCYLINDRICAL;
+  prj->pvrange   = 0;
+  prj->simplezen = 0;
+  prj->equiareal = 1;
+  prj->conformal = 0;
+  prj->global    = 1;
+  prj->divergent = 0;
+
+  if (prj->r0 == 0.0) {
+    prj->r0 = R2D;
+    prj->w[0] = 1.0;
+    prj->w[1] = 1.0;
+    prj->w[2] = 180.0;
+    prj->w[3] = 1.0/prj->w[2];
+  } else {
+    prj->w[0] = prj->r0*D2R;
+    prj->w[1] = 1.0/prj->w[0];
+    prj->w[2] = PI*prj->r0;
+    prj->w[3] = 1.0/prj->w[2];
+  }
+
+  prj->prjx2s = parx2s;
+  prj->prjs2x = pars2x;
+
+  return prjoff(prj, 0.0, 0.0);
+}
+
+/*--------------------------------------------------------------------------*/
+
+int parx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)
+
+struct prjprm *prj;
+int nx, ny, sxy, spt;
+const double x[], y[];
+double phi[], theta[];
+int stat[];
+
+{
+  int mx, my, rowlen, rowoff, status;
+  double r, s, t, xj;
+  const double tol = 1.0e-13;
+  register int istat, ix, iy, *statp;
+  register const double *xp, *yp;
+  register double *phip, *thetap;
+
+
+  /* Initialize. */
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+  if (prj->flag != PAR) {
+    if ((status = parset(prj))) return status;
+  }
+
+  if (ny > 0) {
+    mx = nx;
+    my = ny;
+  } else {
+    mx = 1;
+    my = 1;
+    ny = nx;
+  }
+
+  status = 0;
+
+
+  /* Do x dependence. */
+  xp = x;
+  rowoff = 0;
+  rowlen = nx*spt;
+  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
+    xj = *xp + prj->x0;
+    s = prj->w[1]*xj;
+    t = fabs(xj) - tol;
+
+    phip   = phi   + rowoff;
+    thetap = theta + rowoff;
+    for (iy = 0; iy < my; iy++) {
+      *phip   = s;
+      *thetap = t;
+      phip   += rowlen;
+      thetap += rowlen;
+    }
+  }
+
+
+  /* Do y dependence. */
+  yp = y;
+  phip   = phi;
+  thetap = theta;
+  statp  = stat;
+  for (iy = 0; iy < ny; iy++, yp += sxy) {
+    r = prj->w[3]*(*yp + prj->y0);
+
+    istat = 0;
+    if (r > 1.0 || r < -1.0) {
+      s = 0.0;
+      t = 0.0;
+      istat = 1;
+      if (!status) status = PRJERR_BAD_PIX_SET("parx2s");
+
+    } else {
+      s = 1.0 - 4.0*r*r;
+      if (s == 0.0) {
+        /* Deferred test. */
+        istat = -1;
+      } else {
+        s = 1.0/s;
+      }
+
+      t = 3.0*asind(r);
+    }
+
+    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
+      if (istat < 0) {
+        if (*thetap < 0.0) {
+          *(statp++) = 0;
+        } else {
+          *(statp++) = 1;
+          if (!status) status = PRJERR_BAD_PIX_SET("parx2s");
+        }
+      }
+
+      *phip  *= s;
+      *thetap = t;
+    }
+  }
+
+  return status;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int pars2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)
+
+struct prjprm *prj;
+int nphi, ntheta, spt, sxy;
+const double phi[], theta[];
+double x[], y[];
+int stat[];
+
+{
+  int mphi, mtheta, rowlen, rowoff, status;
+  double eta, s, xi;
+  register int iphi, itheta, *statp;
+  register const double *phip, *thetap;
+  register double *xp, *yp;
+
+
+  /* Initialize. */
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+  if (prj->flag != PAR) {
+    if ((status = parset(prj))) return status;
+  }
+
+  if (ntheta > 0) {
+    mphi   = nphi;
+    mtheta = ntheta;
+  } else {
+    mphi   = 1;
+    mtheta = 1;
+    ntheta = nphi;
+  }
+
+
+  /* Do phi dependence. */
+  phip = phi;
+  rowoff = 0;
+  rowlen = nphi*sxy;
+  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
+    xi = prj->w[0]*(*phip);
+
+    xp = x + rowoff;
+    for (itheta = 0; itheta < mtheta; itheta++) {
+      *xp = xi;
+      xp += rowlen;
+    }
+  }
+
+
+  /* Do theta dependence. */
+  thetap = theta;
+  xp = x;
+  yp = y;
+  statp = stat;
+  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
+    s = sind((*thetap)/3.0);
+    xi = (1.0 - 4.0*s*s);
+    eta = prj->w[2]*s - prj->y0;
+
+    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
+      *xp = xi*(*xp) - prj->x0;
+      *yp = eta;
+      *(statp++) = 0;
+    }
+  }
+
+  return 0;
+}
+
+/*============================================================================
+*   MOL: Mollweide's projection.
+*
+*   Given and/or returned:
+*      prj->r0      Reset to 180/pi if 0.
+*      prj->phi0    Reset to 0.0 if undefined.
+*      prj->theta0  Reset to 0.0 if undefined.
+*
+*   Returned:
+*      prj->flag     MOL
+*      prj->code    "MOL"
+*      prj->x0      Fiducial offset in x.
+*      prj->y0      Fiducial offset in y.
+*      prj->w[0]    sqrt(2)*r0
+*      prj->w[1]    sqrt(2)*r0/90
+*      prj->w[2]    1/(sqrt(2)*r0)
+*      prj->w[3]    90/r0
+*      prj->prjx2s  Pointer to molx2s().
+*      prj->prjs2x  Pointer to mols2x().
+*===========================================================================*/
+
+int molset(prj)
+
+struct prjprm *prj;
+
+{
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+
+  prj->flag = MOL;
+  strcpy(prj->code, "MOL");
+
+  if (prj->r0 == 0.0) prj->r0 = R2D;
+
+  strcpy(prj->name, "Mollweide's");
+  prj->category  = PSEUDOCYLINDRICAL;
+  prj->pvrange   = 0;
+  prj->simplezen = 0;
+  prj->equiareal = 1;
+  prj->conformal = 0;
+  prj->global    = 1;
+  prj->divergent = 0;
+
+  prj->w[0] = SQRT2*prj->r0;
+  prj->w[1] = prj->w[0]/90.0;
+  prj->w[2] = 1.0/prj->w[0];
+  prj->w[3] = 90.0/prj->r0;
+  prj->w[4] = 2.0/PI;
+
+  prj->prjx2s = molx2s;
+  prj->prjs2x = mols2x;
+
+  return prjoff(prj, 0.0, 0.0);
+}
+
+/*--------------------------------------------------------------------------*/
+
+int molx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)
+
+struct prjprm *prj;
+int nx, ny, sxy, spt;
+const double x[], y[];
+double phi[], theta[];
+int stat[];
+
+{
+  int mx, my, rowlen, rowoff, status;
+  double r, s, t, xj, y0, yj, z;
+  const double tol = 1.0e-12;
+  register int istat, ix, iy, *statp;
+  register const double *xp, *yp;
+  register double *phip, *thetap;
+
+
+  /* Initialize. */
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+  if (prj->flag != MOL) {
+    if ((status = molset(prj))) return status;
+  }
+
+  if (ny > 0) {
+    mx = nx;
+    my = ny;
+  } else {
+    mx = 1;
+    my = 1;
+    ny = nx;
+  }
+
+  status = 0;
+
+
+  /* Do x dependence. */
+  xp = x;
+  rowoff = 0;
+  rowlen = nx*spt;
+  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
+    xj = *xp + prj->x0;
+    s = prj->w[3]*xj;
+    t = fabs(xj) - tol;
+
+    phip   = phi   + rowoff;
+    thetap = theta + rowoff;
+    for (iy = 0; iy < my; iy++) {
+      *phip   = s;
+      *thetap = t;
+      phip   += rowlen;
+      thetap += rowlen;
+    }
+  }
+
+
+  /* Do y dependence. */
+  yp = y;
+  phip   = phi;
+  thetap = theta;
+  statp  = stat;
+  for (iy = 0; iy < ny; iy++, yp += sxy) {
+    yj = *yp + prj->y0;
+    y0 = yj/prj->r0;
+    r  = 2.0 - y0*y0;
+
+    istat = 0;
+    if (r <= tol) {
+      if (r < -tol) {
+        istat = 1;
+        if (!status) status = PRJERR_BAD_PIX_SET("molx2s");
+      } else {
+        /* OK if fabs(x) < tol whence phi = 0.0. */
+        istat = -1;
+      }
+
+      r = 0.0;
+      s = 0.0;
+
+    } else {
+      r = sqrt(r);
+      s = 1.0/r;
+    }
+
+    z = yj*prj->w[2];
+    if (fabs(z) > 1.0) {
+      if (fabs(z) > 1.0+tol) {
+        z = 0.0;
+        istat = 1;
+        if (!status) status = PRJERR_BAD_PIX_SET("molx2s");
+      } else {
+        z = copysign(1.0, z) + y0*r/PI;
+      }
+    } else {
+      z = asin(z)*prj->w[4] + y0*r/PI;
+    }
+
+    if (fabs(z) > 1.0) {
+      if (fabs(z) > 1.0+tol) {
+        z = 0.0;
+        istat = 1;
+        if (!status) status = PRJERR_BAD_PIX_SET("molx2s");
+      } else {
+        z = copysign(1.0, z);
+      }
+    }
+
+    t = asind(z);
+
+    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
+      if (istat < 0) {
+        if (*thetap < 0.0) {
+          *(statp++) = 0;
+        } else {
+          *(statp++) = 1;
+          if (!status) status = PRJERR_BAD_PIX_SET("molx2s");
+        }
+      }
+
+      *phip  *= s;
+      *thetap = t;
+    }
+  }
+
+  return status;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int mols2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)
+
+struct prjprm *prj;
+int nphi, ntheta, spt, sxy;
+const double phi[], theta[];
+double x[], y[];
+int stat[];
+
+{
+  int k, mphi, mtheta, rowlen, rowoff, status;
+  double eta, gamma, resid, u, v, v0, v1, xi;
+  const double tol = 1.0e-13;
+  register int iphi, itheta, *statp;
+  register const double *phip, *thetap;
+  register double *xp, *yp;
+
+
+  /* Initialize. */
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+  if (prj->flag != MOL) {
+    if ((status = molset(prj))) return status;
+  }
+
+  if (ntheta > 0) {
+    mphi   = nphi;
+    mtheta = ntheta;
+  } else {
+    mphi   = 1;
+    mtheta = 1;
+    ntheta = nphi;
+  }
+
+
+  /* Do phi dependence. */
+  phip = phi;
+  rowoff = 0;
+  rowlen = nphi*sxy;
+  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
+    xi = prj->w[1]*(*phip);
+
+    xp = x + rowoff;
+    for (itheta = 0; itheta < mtheta; itheta++) {
+      *xp = xi;
+      xp += rowlen;
+    }
+  }
+
+
+  /* Do theta dependence. */
+  thetap = theta;
+  xp = x;
+  yp = y;
+  statp = stat;
+  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
+    if (fabs(*thetap) == 90.0) {
+      xi  = 0.0;
+      eta = copysign(prj->w[0], *thetap);
+    } else if (*thetap == 0.0) {
+      xi  = 1.0;
+      eta = 0.0;
+    } else {
+      u  = PI*sind(*thetap);
+      v0 = -PI;
+      v1 =  PI;
+      v  = u;
+      for (k = 0; k < 100; k++) {
+        resid = (v - u) + sin(v);
+        if (resid < 0.0) {
+          if (resid > -tol) break;
+          v0 = v;
+        } else {
+          if (resid < tol) break;
+          v1 = v;
+        }
+        v = (v0 + v1)/2.0;
+      }
+
+      gamma = v/2.0;
+      xi  = cos(gamma);
+      eta = prj->w[0]*sin(gamma);
+    }
+
+    eta -= prj->y0;
+    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
+      *xp = xi*(*xp) - prj->x0;
+      *yp = eta;
+      *(statp++) = 0;
+    }
+  }
+
+  return 0;
+}
+
+/*============================================================================
+*   AIT: Hammer-Aitoff projection.
+*
+*   Given and/or returned:
+*      prj->r0      Reset to 180/pi if 0.
+*      prj->phi0    Reset to 0.0 if undefined.
+*      prj->theta0  Reset to 0.0 if undefined.
+*
+*   Returned:
+*      prj->flag     AIT
+*      prj->code    "AIT"
+*      prj->x0      Fiducial offset in x.
+*      prj->y0      Fiducial offset in y.
+*      prj->w[0]    2*r0**2
+*      prj->w[1]    1/(2*r0)**2
+*      prj->w[2]    1/(4*r0)**2
+*      prj->w[3]    1/(2*r0)
+*      prj->prjx2s  Pointer to aitx2s().
+*      prj->prjs2x  Pointer to aits2x().
+*===========================================================================*/
+
+int aitset(prj)
+
+struct prjprm *prj;
+
+{
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+
+  prj->flag = AIT;
+  strcpy(prj->code, "AIT");
+
+  if (prj->r0 == 0.0) prj->r0 = R2D;
+
+  strcpy(prj->name, "Hammer-Aitoff");
+  prj->category  = CONVENTIONAL;
+  prj->pvrange   = 0;
+  prj->simplezen = 0;
+  prj->equiareal = 1;
+  prj->conformal = 0;
+  prj->global    = 1;
+  prj->divergent = 0;
+
+  prj->w[0] = 2.0*prj->r0*prj->r0;
+  prj->w[1] = 1.0/(2.0*prj->w[0]);
+  prj->w[2] = prj->w[1]/4.0;
+  prj->w[3] = 1.0/(2.0*prj->r0);
+
+  prj->prjx2s = aitx2s;
+  prj->prjs2x = aits2x;
+
+  return prjoff(prj, 0.0, 0.0);
+}
+
+/*--------------------------------------------------------------------------*/
+
+int aitx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)
+
+struct prjprm *prj;
+int nx, ny, sxy, spt;
+const double x[], y[];
+double phi[], theta[];
+int stat[];
+
+{
+  int mx, my, rowlen, rowoff, status;
+  double s, t, x0, xj, y0, yj, yj2, z;
+  const double tol = 1.0e-13;
+  register int ix, iy, istat, *statp;
+  register const double *xp, *yp;
+  register double *phip, *thetap;
+
+
+  /* Initialize. */
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+  if (prj->flag != AIT) {
+    if ((status = aitset(prj))) return status;
+  }
+
+  if (ny > 0) {
+    mx = nx;
+    my = ny;
+  } else {
+    mx = 1;
+    my = 1;
+    ny = nx;
+  }
+
+  status = 0;
+
+
+  /* Do x dependence. */
+  xp = x;
+  rowoff = 0;
+  rowlen = nx*spt;
+  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
+    xj = *xp + prj->x0;
+    s  = 1.0 - xj*xj*prj->w[2];
+    t  = xj*prj->w[3];
+
+    phip   = phi   + rowoff;
+    thetap = theta + rowoff;
+    for (iy = 0; iy < my; iy++) {
+      *phip   = s;
+      *thetap = t;
+      phip   += rowlen;
+      thetap += rowlen;
+    }
+  }
+
+
+  /* Do y dependence. */
+  yp = y;
+  phip   = phi;
+  thetap = theta;
+  statp  = stat;
+  for (iy = 0; iy < ny; iy++, yp += sxy) {
+    yj  = *yp + prj->y0;
+    yj2 = yj*yj*prj->w[1];
+
+    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
+      s = *phip - yj2;
+
+      istat = 0;
+      if (s < 0.5) {
+        if (s < 0.5-tol) {
+          istat = 1;
+          if (!status) status = PRJERR_BAD_PIX_SET("aitx2s");
+        }
+
+        s = 0.5;
+      }
+
+      z = sqrt(s);
+      x0 = 2.0*z*z - 1.0;
+      y0 = z*(*thetap);
+      if (x0 == 0.0 && y0 == 0.0) {
+        *phip = 0.0;
+      } else {
+        *phip = 2.0*atan2d(y0, x0);
+      }
+
+      t = z*yj/prj->r0;
+      if (fabs(t) > 1.0) {
+        if (fabs(t) > 1.0+tol) {
+          istat = 1;
+          if (!status) status = PRJERR_BAD_PIX_SET("aitx2s");
+        }
+        t = copysign(90.0, t);
+
+      } else {
+        t = asind(t);
+      }
+
+      *thetap = t;
+      *(statp++) = istat;
+    }
+  }
+
+  return status;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int aits2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)
+
+struct prjprm *prj;
+int nphi, ntheta, spt, sxy;
+const double phi[], theta[];
+double x[], y[];
+int stat[];
+
+{
+  int mphi, mtheta, rowlen, rowoff, status;
+  double cosphi, costhe, sinphi, sinthe, w;
+  register int iphi, itheta, *statp;
+  register const double *phip, *thetap;
+  register double *xp, *yp;
+
+
+  /* Initialize. */
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+  if (prj->flag != AIT) {
+    if ((status = aitset(prj))) return status;
+  }
+
+  if (ntheta > 0) {
+    mphi   = nphi;
+    mtheta = ntheta;
+  } else {
+    mphi   = 1;
+    mtheta = 1;
+    ntheta = nphi;
+  }
+
+
+  /* Do phi dependence. */
+  phip = phi;
+  rowoff = 0;
+  rowlen = nphi*sxy;
+  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
+    w = (*phip)/2.0;
+    sincosd(w, &sinphi, &cosphi);
+
+    xp = x + rowoff;
+    yp = y + rowoff;
+    for (itheta = 0; itheta < mtheta; itheta++) {
+      *xp = sinphi;
+      *yp = cosphi;
+      xp += rowlen;
+      yp += rowlen;
+    }
+  }
+
+
+  /* Do theta dependence. */
+  thetap = theta;
+  xp = x;
+  yp = y;
+  statp = stat;
+  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
+    sincosd(*thetap, &sinthe, &costhe);
+
+    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
+      w = sqrt(prj->w[0]/(1.0 + costhe*(*yp)));
+      *xp = 2.0*w*costhe*(*xp) - prj->x0;
+      *yp = w*sinthe - prj->y0;
+      *(statp++) = 0;
+    }
+  }
+
+  return 0;
+}
+
+/*============================================================================
+*   COP: conic perspective projection.
+*
+*   Given:
+*      prj->pv[1]   sigma = (theta2+theta1)/2
+*      prj->pv[2]   delta = (theta2-theta1)/2, where theta1 and theta2 are the
+*                   latitudes of the standard parallels, in degrees.
+*
+*   Given and/or returned:
+*      prj->r0      Reset to 180/pi if 0.
+*      prj->phi0    Reset to sigma if undefined.
+*      prj->theta0  Reset to sigma if undefined.
+*
+*   Returned:
+*      prj->flag     COP
+*      prj->code    "COP"
+*      prj->x0      Fiducial offset in x.
+*      prj->y0      Fiducial offset in y.
+*      prj->w[0]    C  = sin(sigma)
+*      prj->w[1]    1/C
+*      prj->w[2]    Y0 = r0*cos(delta)*cot(sigma)
+*      prj->w[3]    r0*cos(delta)
+*      prj->w[4]    1/(r0*cos(delta)
+*      prj->w[5]    cot(sigma)
+*      prj->prjx2s  Pointer to copx2s().
+*      prj->prjs2x  Pointer to cops2x().
+*===========================================================================*/
+
+int copset(prj)
+
+struct prjprm *prj;
+
+{
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+
+  prj->flag = COP;
+  strcpy(prj->code, "COP");
+  strcpy(prj->name, "conic perspective");
+
+  if (undefined(prj->pv[1])) {
+    return PRJERR_BAD_PARAM_SET("copset");
+  }
+  if (undefined(prj->pv[2])) prj->pv[2] = 0.0;
+  if (prj->r0 == 0.0) prj->r0 = R2D;
+
+  prj->category  = CONIC;
+  prj->pvrange   = 102;
+  prj->simplezen = 0;
+  prj->equiareal = 0;
+  prj->conformal = 0;
+  prj->global    = 0;
+  prj->divergent = 1;
+
+  prj->w[0] = sind(prj->pv[1]);
+  if (prj->w[0] == 0.0) {
+    return PRJERR_BAD_PARAM_SET("copset");
+  }
+
+  prj->w[1] = 1.0/prj->w[0];
+
+  prj->w[3] = prj->r0*cosd(prj->pv[2]);
+  if (prj->w[3] == 0.0) {
+    return PRJERR_BAD_PARAM_SET("copset");
+  }
+
+  prj->w[4] = 1.0/prj->w[3];
+  prj->w[5] = 1.0/tand(prj->pv[1]);
+
+  prj->w[2] = prj->w[3]*prj->w[5];
+
+  prj->prjx2s = copx2s;
+  prj->prjs2x = cops2x;
+
+  return prjoff(prj, 0.0, prj->pv[1]);
+}
+
+/*--------------------------------------------------------------------------*/
+
+int copx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)
+
+struct prjprm *prj;
+int nx, ny, sxy, spt;
+const double x[], y[];
+double phi[], theta[];
+int stat[];
+
+{
+  int mx, my, rowlen, rowoff, status;
+  double alpha, dy, dy2, r, xj;
+  register int ix, iy, *statp;
+  register const double *xp, *yp;
+  register double *phip, *thetap;
+
+  /* Initialize. */
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+  if (prj->flag != COP) {
+    if ((status = copset(prj))) return status;
+  }
+
+  if (ny > 0) {
+    mx = nx;
+    my = ny;
+  } else {
+    mx = 1;
+    my = 1;
+    ny = nx;
+  }
+
+
+  /* Do x dependence. */
+  xp = x;
+  rowoff = 0;
+  rowlen = nx*spt;
+  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
+    xj = *xp + prj->x0;
+
+    phip = phi + rowoff;
+    for (iy = 0; iy < my; iy++) {
+      *phip = xj;
+      phip += rowlen;
+    }
+  }
+
+
+  /* Do y dependence. */
+  yp = y;
+  phip   = phi;
+  thetap = theta;
+  statp  = stat;
+  for (iy = 0; iy < ny; iy++, yp += sxy) {
+    dy  = prj->w[2] - (*yp + prj->y0);
+    dy2 = dy*dy;
+
+    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
+      xj = *phip;
+
+      r = sqrt(xj*xj + dy2);
+      if (prj->pv[1] < 0.0) r = -r;
+
+      if (r == 0.0) {
+        alpha = 0.0;
+      } else {
+        alpha = atan2d(xj/r, dy/r);
+      }
+
+      *phip = alpha*prj->w[1];
+      *thetap = prj->pv[1] + atand(prj->w[5] - r*prj->w[4]);
+      *(statp++) = 0;
+    }
+  }
+
+  return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int cops2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)
+
+struct prjprm *prj;
+int nphi, ntheta, spt, sxy;
+const double phi[], theta[];
+double x[], y[];
+int stat[];
+
+{
+  int mphi, mtheta, rowlen, rowoff, status;
+  double alpha, cosalpha, r, s, t, sinalpha, y0;
+  register int iphi, itheta, istat, *statp;
+  register const double *phip, *thetap;
+  register double *xp, *yp;
+
+  /* Initialize. */
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+  if (prj->flag != COP) {
+    if ((status = copset(prj))) return status;
+  }
+
+  if (ntheta > 0) {
+    mphi   = nphi;
+    mtheta = ntheta;
+  } else {
+    mphi   = 1;
+    mtheta = 1;
+    ntheta = nphi;
+  }
+
+  status = 0;
+
+
+  /* Do phi dependence. */
+  phip = phi;
+  rowoff = 0;
+  rowlen = nphi*sxy;
+  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
+    alpha = prj->w[0]*(*phip);
+    sincosd(alpha, &sinalpha, &cosalpha);
+
+    xp = x + rowoff;
+    yp = y + rowoff;
+    for (itheta = 0; itheta < mtheta; itheta++) {
+      *xp = sinalpha;
+      *yp = cosalpha;
+      xp += rowlen;
+      yp += rowlen;
+    }
+  }
+
+
+  /* Do theta dependence. */
+  thetap = theta;
+  xp = x;
+  yp = y;
+  statp = stat;
+  y0 = prj->y0 - prj->w[2];
+  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
+    t = *thetap - prj->pv[1];
+    s = cosd(t);
+
+    istat = 0;
+    if (s == 0.0) {
+      r = 0.0;
+      istat = 1;
+      if (!status) status = PRJERR_BAD_WORLD_SET("cops2x");
+
+    } else {
+      r = prj->w[2] - prj->w[3]*sind(t)/s;
+
+      if (prj->bounds && r*prj->w[0] < 0.0) {
+        istat = 1;
+        if (!status) status = PRJERR_BAD_WORLD_SET("cops2x");
+      }
+    }
+
+    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
+      *xp =  r*(*xp) - prj->x0;
+      *yp = -r*(*yp) - y0;
+      *(statp++) = istat;
+    }
+  }
+
+  return status;
+}
+
+/*============================================================================
+*   COE: conic equal area projection.
+*
+*   Given:
+*      prj->pv[1]   sigma = (theta2+theta1)/2
+*      prj->pv[2]   delta = (theta2-theta1)/2, where theta1 and theta2 are the
+*                   latitudes of the standard parallels, in degrees.
+*
+*   Given and/or returned:
+*      prj->r0      Reset to 180/pi if 0.
+*      prj->phi0    Reset to sigma if undefined.
+*      prj->theta0  Reset to sigma if undefined.
+*
+*   Returned:
+*      prj->flag     COE
+*      prj->code    "COE"
+*      prj->x0      Fiducial offset in x.
+*      prj->y0      Fiducial offset in y.
+*      prj->w[0]    C = (sin(theta1) + sin(theta2))/2
+*      prj->w[1]    1/C
+*      prj->w[2]    Y0 = chi*sqrt(psi - 2C*sind(sigma))
+*      prj->w[3]    chi = r0/C
+*      prj->w[4]    psi = 1 + sin(theta1)*sin(theta2)
+*      prj->w[5]    2C
+*      prj->w[6]    (1 + sin(theta1)*sin(theta2))*(r0/C)**2
+*      prj->w[7]    C/(2*r0**2)
+*      prj->w[8]    chi*sqrt(psi + 2C)
+*      prj->prjx2s  Pointer to coex2s().
+*      prj->prjs2x  Pointer to coes2x().
+*===========================================================================*/
+
+int coeset(prj)
+
+struct prjprm *prj;
+
+{
+  double theta1, theta2;
+
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+
+  prj->flag = COE;
+  strcpy(prj->code, "COE");
+  strcpy(prj->name, "conic equal area");
+
+  if (undefined(prj->pv[1])) {
+    return PRJERR_BAD_PARAM_SET("coeset");
+  }
+  if (undefined(prj->pv[2])) prj->pv[2] = 0.0;
+  if (prj->r0 == 0.0) prj->r0 = R2D;
+
+  prj->category  = CONIC;
+  prj->pvrange   = 102;
+  prj->simplezen = 0;
+  prj->equiareal = 1;
+  prj->conformal = 0;
+  prj->global    = 1;
+  prj->divergent = 0;
+
+  theta1 = prj->pv[1] - prj->pv[2];
+  theta2 = prj->pv[1] + prj->pv[2];
+
+  prj->w[0] = (sind(theta1) + sind(theta2))/2.0;
+  if (prj->w[0] == 0.0) {
+    return PRJERR_BAD_PARAM_SET("coeset");
+  }
+
+  prj->w[1] = 1.0/prj->w[0];
+
+  prj->w[3] = prj->r0/prj->w[0];
+  prj->w[4] = 1.0 + sind(theta1)*sind(theta2);
+  prj->w[5] = 2.0*prj->w[0];
+  prj->w[6] = prj->w[3]*prj->w[3]*prj->w[4];
+  prj->w[7] = 1.0/(2.0*prj->r0*prj->w[3]);
+  prj->w[8] = prj->w[3]*sqrt(prj->w[4] + prj->w[5]);
+
+  prj->w[2] = prj->w[3]*sqrt(prj->w[4] - prj->w[5]*sind(prj->pv[1]));
+
+  prj->prjx2s = coex2s;
+  prj->prjs2x = coes2x;
+
+  return prjoff(prj, 0.0, prj->pv[1]);
+}
+
+/*--------------------------------------------------------------------------*/
+
+int coex2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)
+
+struct prjprm *prj;
+int nx, ny, sxy, spt;
+const double x[], y[];
+double phi[], theta[];
+int stat[];
+
+{
+  int mx, my, rowlen, rowoff, status;
+  double alpha, dy, dy2, r, t, w, xj;
+  const double tol = 1.0e-12;
+  register int ix, iy, istat, *statp;
+  register const double *xp, *yp;
+  register double *phip, *thetap;
+
+  /* Initialize. */
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+  if (prj->flag != COE) {
+    if ((status = coeset(prj))) return status;
+  }
+
+  if (ny > 0) {
+    mx = nx;
+    my = ny;
+  } else {
+    mx = 1;
+    my = 1;
+    ny = nx;
+  }
+
+  status = 0;
+
+
+  /* Do x dependence. */
+  xp = x;
+  rowoff = 0;
+  rowlen = nx*spt;
+  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
+    xj = *xp + prj->x0;
+
+    phip = phi + rowoff;
+    for (iy = 0; iy < my; iy++) {
+      *phip = xj;
+      phip += rowlen;
+    }
+  }
+
+
+  /* Do y dependence. */
+  yp = y;
+  phip   = phi;
+  thetap = theta;
+  statp  = stat;
+  for (iy = 0; iy < ny; iy++, yp += sxy) {
+    dy  = prj->w[2] - (*yp + prj->y0);
+    dy2 = dy*dy;
+
+    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
+      xj = *phip;
+
+      r = sqrt(xj*xj + dy2);
+      if (prj->pv[1] < 0.0) r = -r;
+
+      if (r == 0.0) {
+        alpha = 0.0;
+      } else {
+        alpha = atan2d(xj/r, dy/r);
+      }
+
+      istat = 0;
+      if (fabs(r - prj->w[8]) < tol) {
+        t = -90.0;
+      } else {
+        w = (prj->w[6] - r*r)*prj->w[7];
+        if (fabs(w) > 1.0) {
+          if (fabs(w-1.0) < tol) {
+            t = 90.0;
+          } else if (fabs(w+1.0) < tol) {
+            t = -90.0;
+          } else {
+            t = 0.0;
+            istat = 1;
+            if (!status) status = PRJERR_BAD_PIX_SET("coex2s");
+          }
+        } else {
+          t = asind(w);
+        }
+      }
+
+      *phip = alpha*prj->w[1];
+      *thetap = t;
+      *(statp++) = istat;
+    }
+  }
+
+  return status;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int coes2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)
+
+struct prjprm *prj;
+int nphi, ntheta, spt, sxy;
+const double phi[], theta[];
+double x[], y[];
+int stat[];
+
+{
+  int mphi, mtheta, rowlen, rowoff, status;
+  double alpha, cosalpha, r, sinalpha, y0;
+  register int iphi, itheta, *statp;
+  register const double *phip, *thetap;
+  register double *xp, *yp;
+
+  /* Initialize. */
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+  if (prj->flag != COE) {
+    if ((status = coeset(prj))) return status;
+  }
+
+  if (ntheta > 0) {
+    mphi   = nphi;
+    mtheta = ntheta;
+  } else {
+    mphi   = 1;
+    mtheta = 1;
+    ntheta = nphi;
+  }
+
+
+  /* Do phi dependence. */
+  phip = phi;
+  rowoff = 0;
+  rowlen = nphi*sxy;
+  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
+    alpha = prj->w[0]*(*phip);
+    sincosd(alpha, &sinalpha, &cosalpha);
+
+    xp = x + rowoff;
+    yp = y + rowoff;
+    for (itheta = 0; itheta < mtheta; itheta++) {
+      *xp = sinalpha;
+      *yp = cosalpha;
+      xp += rowlen;
+      yp += rowlen;
+    }
+  }
+
+
+  /* Do theta dependence. */
+  thetap = theta;
+  xp = x;
+  yp = y;
+  statp = stat;
+  y0 = prj->y0 - prj->w[2];
+  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
+    if (*thetap == -90.0) {
+      r = prj->w[8];
+    } else {
+      r = prj->w[3]*sqrt(prj->w[4] - prj->w[5]*sind(*thetap));
+    }
+
+    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
+      *xp =  r*(*xp) - prj->x0;
+      *yp = -r*(*yp) - y0;
+      *(statp++) = 0;
+    }
+  }
+
+  return 0;
+}
+
+/*============================================================================
+*   COD: conic equidistant projection.
+*
+*   Given:
+*      prj->pv[1]   sigma = (theta2+theta1)/2
+*      prj->pv[2]   delta = (theta2-theta1)/2, where theta1 and theta2 are the
+*                   latitudes of the standard parallels, in degrees.
+*
+*   Given and/or returned:
+*      prj->r0      Reset to 180/pi if 0.
+*      prj->phi0    Reset to sigma if undefined.
+*      prj->theta0  Reset to sigma if undefined.
+*
+*   Returned:
+*      prj->flag     COD
+*      prj->code    "COD"
+*      prj->x0      Fiducial offset in x.
+*      prj->y0      Fiducial offset in y.
+*      prj->w[0]    C = r0*sin(sigma)*sin(delta)/delta
+*      prj->w[1]    1/C
+*      prj->w[2]    Y0 = delta*cot(delta)*cot(sigma)
+*      prj->w[3]    Y0 + sigma
+*      prj->prjx2s  Pointer to codx2s().
+*      prj->prjs2x  Pointer to cods2x().
+*===========================================================================*/
+
+int codset(prj)
+
+struct prjprm *prj;
+
+{
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+
+  prj->flag = COD;
+  strcpy(prj->code, "COD");
+  strcpy(prj->name, "conic equidistant");
+
+  if (undefined(prj->pv[1])) {
+    return PRJERR_BAD_PARAM_SET("codset");
+  }
+  if (undefined(prj->pv[2])) prj->pv[2] = 0.0;
+  if (prj->r0 == 0.0) prj->r0 = R2D;
+
+  prj->category  = CONIC;
+  prj->pvrange   = 102;
+  prj->simplezen = 0;
+  prj->equiareal = 0;
+  prj->conformal = 0;
+  prj->global    = 1;
+  prj->divergent = 0;
+
+  if (prj->pv[2] == 0.0) {
+    prj->w[0] = prj->r0*sind(prj->pv[1])*D2R;
+  } else {
+    prj->w[0] = prj->r0*sind(prj->pv[1])*sind(prj->pv[2])/prj->pv[2];
+  }
+
+  if (prj->w[0] == 0.0) {
+    return PRJERR_BAD_PARAM_SET("codset");
+  }
+
+  prj->w[1] = 1.0/prj->w[0];
+  prj->w[2] = prj->r0*cosd(prj->pv[2])*cosd(prj->pv[1])/prj->w[0];
+  prj->w[3] = prj->w[2] + prj->pv[1];
+
+  prj->prjx2s = codx2s;
+  prj->prjs2x = cods2x;
+
+  return prjoff(prj, 0.0, prj->pv[1]);
+}
+
+/*--------------------------------------------------------------------------*/
+
+int codx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)
+
+struct prjprm *prj;
+int nx, ny, sxy, spt;
+const double x[], y[];
+double phi[], theta[];
+int stat[];
+
+{
+  int mx, my, rowlen, rowoff, status;
+  double alpha, dy, dy2, r, xj;
+  register int ix, iy, *statp;
+  register const double *xp, *yp;
+  register double *phip, *thetap;
+
+  /* Initialize. */
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+  if (prj->flag != COD) {
+    if ((status = codset(prj))) return status;
+  }
+
+  if (ny > 0) {
+    mx = nx;
+    my = ny;
+  } else {
+    mx = 1;
+    my = 1;
+    ny = nx;
+  }
+
+
+  /* Do x dependence. */
+  xp = x;
+  rowoff = 0;
+  rowlen = nx*spt;
+  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
+    xj = *xp + prj->x0;
+
+    phip = phi + rowoff;
+    for (iy = 0; iy < my; iy++) {
+      *phip = xj;
+      phip += rowlen;
+    }
+  }
+
+
+  /* Do y dependence. */
+  yp = y;
+  phip   = phi;
+  thetap = theta;
+  statp  = stat;
+  for (iy = 0; iy < ny; iy++, yp += sxy) {
+    dy  = prj->w[2] - (*yp + prj->y0);
+    dy2 = dy*dy;
+
+    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
+      xj = *phip;
+
+      r = sqrt(xj*xj + dy2);
+      if (prj->pv[1] < 0.0) r = -r;
+
+      if (r == 0.0) {
+        alpha = 0.0;
+      } else {
+        alpha = atan2d(xj/r, dy/r);
+      }
+
+      *phip = alpha*prj->w[1];
+      *thetap = prj->w[3] - r;
+      *(statp++) = 0;
+    }
+  }
+
+  return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int cods2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)
+
+struct prjprm *prj;
+int nphi, ntheta, spt, sxy;
+const double phi[], theta[];
+double x[], y[];
+int stat[];
+
+{
+  int mphi, mtheta, rowlen, rowoff, status;
+  double alpha, cosalpha, r, sinalpha, y0;
+  register int iphi, itheta, *statp;
+  register const double *phip, *thetap;
+  register double *xp, *yp;
+
+  /* Initialize. */
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+  if (prj->flag != COD) {
+    if ((status = codset(prj))) return status;
+  }
+
+  if (ntheta > 0) {
+    mphi   = nphi;
+    mtheta = ntheta;
+  } else {
+    mphi   = 1;
+    mtheta = 1;
+    ntheta = nphi;
+  }
+
+
+  /* Do phi dependence. */
+  phip = phi;
+  rowoff = 0;
+  rowlen = nphi*sxy;
+  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
+    alpha = prj->w[0]*(*phip);
+    sincosd(alpha, &sinalpha, &cosalpha);
+
+    xp = x + rowoff;
+    yp = y + rowoff;
+    for (itheta = 0; itheta < mtheta; itheta++) {
+      *xp = sinalpha;
+      *yp = cosalpha;
+      xp += rowlen;
+      yp += rowlen;
+    }
+  }
+
+
+  /* Do theta dependence. */
+  thetap = theta;
+  xp = x;
+  yp = y;
+  statp = stat;
+  y0 = prj->y0 - prj->w[2];
+  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
+    r = prj->w[3] - *thetap;
+
+    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
+      *xp =  r*(*xp) - prj->x0;
+      *yp = -r*(*yp) - y0;
+      *(statp++) = 0;
+    }
+  }
+
+  return 0;
+}
+
+/*============================================================================
+*   COO: conic orthomorphic projection.
+*
+*   Given:
+*      prj->pv[1]   sigma = (theta2+theta1)/2
+*      prj->pv[2]   delta = (theta2-theta1)/2, where theta1 and theta2 are the
+*                   latitudes of the standard parallels, in degrees.
+*
+*   Given and/or returned:
+*      prj->r0      Reset to 180/pi if 0.
+*      prj->phi0    Reset to sigma if undefined.
+*      prj->theta0  Reset to sigma if undefined.
+*
+*   Returned:
+*      prj->flag     COO
+*      prj->code    "COO"
+*      prj->x0      Fiducial offset in x.
+*      prj->y0      Fiducial offset in y.
+*      prj->w[0]    C = ln(cos(theta2)/cos(theta1))/ln(tan(tau2)/tan(tau1))
+*                       where tau1 = (90 - theta1)/2
+*                             tau2 = (90 - theta2)/2
+*      prj->w[1]    1/C
+*      prj->w[2]    Y0 = psi*tan((90-sigma)/2)**C
+*      prj->w[3]    psi = (r0*cos(theta1)/C)/tan(tau1)**C
+*      prj->w[4]    1/psi
+*      prj->prjx2s  Pointer to coox2s().
+*      prj->prjs2x  Pointer to coos2x().
+*===========================================================================*/
+
+int cooset(prj)
+
+struct prjprm *prj;
+
+{
+  double cos1, cos2, tan1, tan2, theta1, theta2;
+
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+
+  prj->flag = COO;
+  strcpy(prj->code, "COO");
+  strcpy(prj->name, "conic orthomorphic");
+
+  if (undefined(prj->pv[1])) {
+    return PRJERR_BAD_PARAM_SET("cooset");
+  }
+  if (undefined(prj->pv[2])) prj->pv[2] = 0.0;
+  if (prj->r0 == 0.0) prj->r0 = R2D;
+
+  prj->category  = CONIC;
+  prj->pvrange   = 102;
+  prj->simplezen = 0;
+  prj->equiareal = 0;
+  prj->conformal = 1;
+  prj->global    = 0;
+  prj->divergent = 1;
+
+  theta1 = prj->pv[1] - prj->pv[2];
+  theta2 = prj->pv[1] + prj->pv[2];
+
+  tan1 = tand((90.0 - theta1)/2.0);
+  cos1 = cosd(theta1);
+
+  if (theta1 == theta2) {
+    prj->w[0] = sind(theta1);
+  } else {
+    tan2 = tand((90.0 - theta2)/2.0);
+    cos2 = cosd(theta2);
+    prj->w[0] = log(cos2/cos1)/log(tan2/tan1);
+  }
+  if (prj->w[0] == 0.0) {
+    return PRJERR_BAD_PARAM_SET("cooset");
+  }
+
+  prj->w[1] = 1.0/prj->w[0];
+
+  prj->w[3] = prj->r0*(cos1/prj->w[0])/pow(tan1,prj->w[0]);
+  if (prj->w[3] == 0.0) {
+    return PRJERR_BAD_PARAM_SET("cooset");
+  }
+  prj->w[2] = prj->w[3]*pow(tand((90.0 - prj->pv[1])/2.0),prj->w[0]);
+  prj->w[4] = 1.0/prj->w[3];
+
+  prj->prjx2s = coox2s;
+  prj->prjs2x = coos2x;
+
+  return prjoff(prj, 0.0, prj->pv[1]);
+}
+
+/*--------------------------------------------------------------------------*/
+
+int coox2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)
+
+struct prjprm *prj;
+int nx, ny, sxy, spt;
+const double x[], y[];
+double phi[], theta[];
+int stat[];
+
+{
+  int mx, my, rowlen, rowoff, status;
+  double alpha, dy, dy2, r, t, xj;
+  register int ix, iy, istat, *statp;
+  register const double *xp, *yp;
+  register double *phip, *thetap;
+
+  /* Initialize. */
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+  if (prj->flag != COO) {
+    if ((status = cooset(prj))) return status;
+  }
+
+  if (ny > 0) {
+    mx = nx;
+    my = ny;
+  } else {
+    mx = 1;
+    my = 1;
+    ny = nx;
+  }
+
+  status = 0;
+
+
+  /* Do x dependence. */
+  xp = x;
+  rowoff = 0;
+  rowlen = nx*spt;
+  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
+    xj = *xp + prj->x0;
+
+    phip = phi + rowoff;
+    for (iy = 0; iy < my; iy++) {
+      *phip = xj;
+      phip += rowlen;
+    }
+  }
+
+
+  /* Do y dependence. */
+  yp = y;
+  phip   = phi;
+  thetap = theta;
+  statp  = stat;
+  for (iy = 0; iy < ny; iy++, yp += sxy) {
+    dy  = prj->w[2] - (*yp + prj->y0);
+    dy2 = dy*dy;
+
+    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
+      xj = *phip;
+
+      r = sqrt(xj*xj + dy2);
+      if (prj->pv[1] < 0.0) r = -r;
+
+      if (r == 0.0) {
+        alpha = 0.0;
+      } else {
+        alpha = atan2d(xj/r, dy/r);
+      }
+
+      istat = 0;
+      if (r == 0.0) {
+        if (prj->w[0] < 0.0) {
+          t = -90.0;
+        } else {
+          t = 0.0;
+          istat = 1;
+          if (!status) status = PRJERR_BAD_PIX_SET("coox2s");
+        }
+      } else {
+        t = 90.0 - 2.0*atand(pow(r*prj->w[4],prj->w[1]));
+      }
+
+      *phip = alpha*prj->w[1];
+      *thetap = t;
+      *(statp++) = istat;
+    }
+  }
+
+  return status;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int coos2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)
+
+struct prjprm *prj;
+int nphi, ntheta, spt, sxy;
+const double phi[], theta[];
+double x[], y[];
+int stat[];
+
+{
+  int mphi, mtheta, rowlen, rowoff, status;
+  double alpha, cosalpha, r, sinalpha, y0;
+  register int iphi, itheta, istat, *statp;
+  register const double *phip, *thetap;
+  register double *xp, *yp;
+
+  /* Initialize. */
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+  if (prj->flag != COO) {
+    if ((status = cooset(prj))) return status;
+  }
+
+  if (ntheta > 0) {
+    mphi   = nphi;
+    mtheta = ntheta;
+  } else {
+    mphi   = 1;
+    mtheta = 1;
+    ntheta = nphi;
+  }
+
+  status = 0;
+
+
+  /* Do phi dependence. */
+  phip = phi;
+  rowoff = 0;
+  rowlen = nphi*sxy;
+  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
+    alpha = prj->w[0]*(*phip);
+    sincosd(alpha, &sinalpha, &cosalpha);
+
+    xp = x + rowoff;
+    yp = y + rowoff;
+    for (itheta = 0; itheta < mtheta; itheta++) {
+      *xp = sinalpha;
+      *yp = cosalpha;
+      xp += rowlen;
+      yp += rowlen;
+    }
+  }
+
+
+  /* Do theta dependence. */
+  thetap = theta;
+  xp = x;
+  yp = y;
+  statp = stat;
+  y0 = prj->y0 - prj->w[2];
+  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
+    istat = 0;
+
+    if (*thetap == -90.0) {
+      r = 0.0;
+      if (prj->w[0] >= 0.0) {
+        istat = 1;
+        if (!status) status = PRJERR_BAD_WORLD_SET("coos2x");
+      }
+    } else {
+      r = prj->w[3]*pow(tand((90.0 - *thetap)/2.0),prj->w[0]);
+    }
+
+    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
+      *xp =  r*(*xp) - prj->x0;
+      *yp = -r*(*yp) - y0;
+      *(statp++) = istat;
+    }
+  }
+
+  return status;
+}
+
+/*============================================================================
+*   BON: Bonne's projection.
+*
+*   Given:
+*      prj->pv[1]   Bonne conformal latitude, theta1, in degrees.
+*
+*   Given and/or returned:
+*      prj->r0      Reset to 180/pi if 0.
+*      prj->phi0    Reset to 0.0 if undefined.
+*      prj->theta0  Reset to 0.0 if undefined.
+*
+*   Returned:
+*      prj->flag     BON
+*      prj->code    "BON"
+*      prj->x0      Fiducial offset in x.
+*      prj->y0      Fiducial offset in y.
+*      prj->w[1]    r0*pi/180
+*      prj->w[2]    Y0 = r0*(cot(theta1) + theta1*pi/180)
+*      prj->prjx2s  Pointer to bonx2s().
+*      prj->prjs2x  Pointer to bons2x().
+*===========================================================================*/
+
+int bonset(prj)
+
+struct prjprm *prj;
+
+{
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+
+  prj->flag = BON;
+  strcpy(prj->code, "BON");
+  strcpy(prj->name, "Bonne's");
+
+  if (undefined(prj->pv[1])) {
+    return PRJERR_BAD_PARAM_SET("bonset");
+  }
+
+  if (prj->pv[1] == 0.0) {
+    /* Sanson-Flamsteed. */
+    return sflset(prj);
+  }
+
+  prj->category  = POLYCONIC;
+  prj->pvrange   = 101;
+  prj->simplezen = 0;
+  prj->equiareal = 1;
+  prj->conformal = 0;
+  prj->global    = 1;
+  prj->divergent = 0;
+
+  if (prj->r0 == 0.0) {
+    prj->r0 = R2D;
+    prj->w[1] = 1.0;
+    prj->w[2] = prj->r0*cosd(prj->pv[1])/sind(prj->pv[1]) + prj->pv[1];
+  } else {
+    prj->w[1] = prj->r0*D2R;
+    prj->w[2] = prj->r0*(cosd(prj->pv[1])/sind(prj->pv[1]) + prj->pv[1]*D2R);
+  }
+
+  prj->prjx2s = bonx2s;
+  prj->prjs2x = bons2x;
+
+  return prjoff(prj, 0.0, 0.0);
+}
+
+/*--------------------------------------------------------------------------*/
+
+int bonx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)
+
+struct prjprm *prj;
+int nx, ny, sxy, spt;
+const double x[], y[];
+double phi[], theta[];
+int stat[];
+
+{
+  int mx, my, rowlen, rowoff, status;
+  double alpha, dy, dy2, costhe, r, s, t, xj;
+  register int ix, iy, *statp;
+  register const double *xp, *yp;
+  register double *phip, *thetap;
+
+
+  /* Initialize. */
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+  if (prj->pv[1] == 0.0) {
+    /* Sanson-Flamsteed. */
+    return sflx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat);
+  }
+
+  if (prj->flag != BON) {
+    if ((status = bonset(prj))) return status;
+  }
+
+  if (ny > 0) {
+    mx = nx;
+    my = ny;
+  } else {
+    mx = 1;
+    my = 1;
+    ny = nx;
+  }
+
+
+  /* Do x dependence. */
+  xp = x;
+  rowoff = 0;
+  rowlen = nx*spt;
+  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
+    xj = *xp + prj->x0;
+
+    phip = phi + rowoff;
+    for (iy = 0; iy < my; iy++) {
+      *phip = xj;
+      phip += rowlen;
+    }
+  }
+
+
+  /* Do y dependence. */
+  yp = y;
+  phip   = phi;
+  thetap = theta;
+  statp  = stat;
+  for (iy = 0; iy < ny; iy++, yp += sxy) {
+    dy  = prj->w[2] - (*yp + prj->y0);
+    dy2 = dy*dy;
+
+    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
+      xj = *phip;
+
+      r = sqrt(xj*xj + dy2);
+      if (prj->pv[1] < 0.0) r = -r;
+
+      if (r == 0.0) {
+        alpha = 0.0;
+      } else {
+        alpha = atan2d(xj/r, dy/r);
+      }
+
+      t = (prj->w[2] - r)/prj->w[1];
+      costhe = cosd(t);
+      if (costhe == 0.0) {
+        s = 0.0;
+      } else {
+        s = alpha*(r/prj->r0)/costhe;
+      }
+
+      *phip = s;
+      *thetap = t;
+      *(statp++) = 0;
+    }
+  }
+
+  return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int bons2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)
+
+struct prjprm *prj;
+int nphi, ntheta, spt, sxy;
+const double phi[], theta[];
+double x[], y[];
+int stat[];
+
+{
+  int mphi, mtheta, rowlen, rowoff, status;
+  double alpha, cosalpha, r, s, sinalpha, y0;
+  register int iphi, itheta, *statp;
+  register const double *phip, *thetap;
+  register double *xp, *yp;
+
+  /* Initialize. */
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+  if (prj->pv[1] == 0.0) {
+    /* Sanson-Flamsteed. */
+    return sfls2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat);
+  }
+
+  if (prj->flag != BON) {
+    if ((status = bonset(prj))) return status;
+  }
+
+  if (ntheta > 0) {
+    mphi   = nphi;
+    mtheta = ntheta;
+  } else {
+    mphi   = 1;
+    mtheta = 1;
+    ntheta = nphi;
+  }
+
+  y0 = prj->y0 - prj->w[2];
+
+
+  /* Do phi dependence. */
+  phip = phi;
+  rowoff = 0;
+  rowlen = nphi*sxy;
+  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
+    s = prj->r0*(*phip);
+
+    xp = x + rowoff;
+    for (itheta = 0; itheta < mtheta; itheta++) {
+      *xp = s;
+      xp += rowlen;
+    }
+  }
+
+
+  /* Do theta dependence. */
+  thetap = theta;
+  xp = x;
+  yp = y;
+  statp = stat;
+  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
+    r = prj->w[2] - prj->w[1]*(*thetap);
+    s = cosd(*thetap)/r;
+
+    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
+      alpha = s*(*xp);
+      sincosd(alpha, &sinalpha, &cosalpha);
+      *xp =  r*sinalpha - prj->x0;
+      *yp = -r*cosalpha - y0;
+      *(statp++) = 0;
+    }
+  }
+
+  return 0;
+}
+
+/*============================================================================
+*   PCO: polyconic projection.
+*
+*   Given and/or returned:
+*      prj->r0      Reset to 180/pi if 0.
+*      prj->phi0    Reset to 0.0 if undefined.
+*      prj->theta0  Reset to 0.0 if undefined.
+*
+*   Returned:
+*      prj->flag     PCO
+*      prj->code    "PCO"
+*      prj->x0      Fiducial offset in x.
+*      prj->y0      Fiducial offset in y.
+*      prj->w[0]    r0*(pi/180)
+*      prj->w[1]    1/r0
+*      prj->w[2]    2*r0
+*      prj->prjx2s  Pointer to pcox2s().
+*      prj->prjs2x  Pointer to pcos2x().
+*===========================================================================*/
+
+int pcoset(prj)
+
+struct prjprm *prj;
+
+{
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+
+  prj->flag = PCO;
+  strcpy(prj->code, "PCO");
+
+  strcpy(prj->name, "polyconic");
+  prj->category  = POLYCONIC;
+  prj->pvrange   = 0;
+  prj->simplezen = 0;
+  prj->equiareal = 0;
+  prj->conformal = 0;
+  prj->global    = 1;
+  prj->divergent = 0;
+
+  if (prj->r0 == 0.0) {
+    prj->r0 = R2D;
+    prj->w[0] = 1.0;
+    prj->w[1] = 1.0;
+    prj->w[2] = 360.0/PI;
+  } else {
+    prj->w[0] = prj->r0*D2R;
+    prj->w[1] = 1.0/prj->w[0];
+    prj->w[2] = 2.0*prj->r0;
+  }
+
+  prj->prjx2s = pcox2s;
+  prj->prjs2x = pcos2x;
+
+  return prjoff(prj, 0.0, 0.0);
+}
+
+/*--------------------------------------------------------------------------*/
+
+int pcox2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)
+
+struct prjprm *prj;
+int nx, ny, sxy, spt;
+const double x[], y[];
+double phi[], theta[];
+int stat[];
+
+{
+  int mx, my, rowlen, rowoff, status;
+  double f, fneg, fpos, lambda, tanthe, the, theneg, thepos, w, x1, xj, xx,
+         yj, ymthe, y1;
+  const double tol = 1.0e-12;
+  register int ix, iy, k, *statp;
+  register const double *xp, *yp;
+  register double *phip, *thetap;
+
+
+  /* Initialize. */
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+  if (prj->flag != PCO) {
+    if ((status = pcoset(prj))) return status;
+  }
+
+  if (ny > 0) {
+    mx = nx;
+    my = ny;
+  } else {
+    mx = 1;
+    my = 1;
+    ny = nx;
+  }
+
+
+  /* Do x dependence. */
+  xp = x;
+  rowoff = 0;
+  rowlen = nx*spt;
+  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
+    xj = *xp + prj->x0;
+
+    phip = phi + rowoff;
+    for (iy = 0; iy < my; iy++) {
+      *phip = xj;
+      phip += rowlen;
+    }
+  }
+
+
+  /* Do y dependence. */
+  yp = y;
+  phip   = phi;
+  thetap = theta;
+  statp  = stat;
+  for (iy = 0; iy < ny; iy++, yp += sxy) {
+    yj = *yp + prj->y0;
+    w  = fabs(yj*prj->w[1]);
+
+    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
+      xj = *phip;
+
+      if (w < tol) {
+        *phip = xj*prj->w[1];
+        *thetap = 0.0;
+
+      } else if (fabs(w-90.0) < tol) {
+        *phip = 0.0;
+        *thetap = copysign(90.0, yj);
+
+      } else {
+        /* Iterative solution using weighted division of the interval. */
+        if (yj > 0.0) {
+          thepos =  90.0;
+        } else {
+          thepos = -90.0;
+        }
+        theneg = 0.0;
+
+        xx = xj*xj;
+        ymthe = yj - prj->w[0]*thepos;
+        fpos = xx + ymthe*ymthe;
+        fneg = -999.0;
+
+        for (k = 0; k < 64; k++) {
+          if (fneg < -100.0) {
+            /* Equal division of the interval. */
+            the = (thepos+theneg)/2.0;
+          } else {
+            /* Weighted division of the interval. */
+            lambda = fpos/(fpos-fneg);
+            if (lambda < 0.1) {
+              lambda = 0.1;
+            } else if (lambda > 0.9) {
+              lambda = 0.9;
+            }
+            the = thepos - lambda*(thepos-theneg);
+          }
+
+          /* Compute the residue. */
+          ymthe = yj - prj->w[0]*(the);
+          tanthe = tand(the);
+          f = xx + ymthe*(ymthe - prj->w[2]/tanthe);
+
+          /* Check for convergence. */
+          if (fabs(f) < tol) break;
+          if (fabs(thepos-theneg) < tol) break;
+
+          /* Redefine the interval. */
+          if (f > 0.0) {
+            thepos = the;
+            fpos = f;
+          } else {
+            theneg = the;
+            fneg = f;
+          }
+        }
+
+        x1 = prj->r0 - ymthe*tanthe;
+        y1 = xj*tanthe;
+        if (x1 == 0.0 && y1 == 0.0) {
+          *phip = 0.0;
+        } else {
+          *phip = atan2d(y1, x1)/sind(the);
+        }
+
+        *thetap = the;
+      }
+
+      *(statp++) = 0;
+    }
+  }
+
+  return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int pcos2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)
+
+struct prjprm *prj;
+int nphi, ntheta, spt, sxy;
+const double phi[], theta[];
+double x[], y[];
+int stat[];
+
+{
+  int mphi, mtheta, rowlen, rowoff, status;
+  double alpha, costhe, cotthe, sinthe, therad;
+  register int iphi, itheta, *statp;
+  register const double *phip, *thetap;
+  register double *xp, *yp;
+
+  /* Initialize. */
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+  if (prj->flag != PCO) {
+    if ((status = pcoset(prj))) return status;
+  }
+
+  if (ntheta > 0) {
+    mphi   = nphi;
+    mtheta = ntheta;
+  } else {
+    mphi   = 1;
+    mtheta = 1;
+    ntheta = nphi;
+  }
+
+
+  /* Do phi dependence. */
+  phip = phi;
+  rowoff = 0;
+  rowlen = nphi*sxy;
+  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
+    xp = x + rowoff;
+    for (itheta = 0; itheta < mtheta; itheta++) {
+      *xp = *phip;
+      xp += rowlen;
+    }
+  }
+
+
+  /* Do theta dependence. */
+  thetap = theta;
+  xp = x;
+  yp = y;
+  statp = stat;
+  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
+    therad = (*thetap)*D2R;
+    sincosd(*thetap, &sinthe, &costhe);
+
+    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
+      if (sinthe == 0.0) {
+        *xp =  prj->w[0]*(*xp) - prj->x0;
+        *yp = -prj->y0;
+      } else {
+        alpha  = (*xp)*sinthe;
+        cotthe = costhe/sinthe;
+        *xp = prj->r0*cotthe*sind(alpha) - prj->x0;
+        *yp = prj->r0*(cotthe*(1.0 - cosd(alpha)) + therad) - prj->y0;
+      }
+
+      *(statp++) = 0;
+    }
+  }
+
+  return 0;
+}
+
+/*============================================================================
+*   TSC: tangential spherical cube projection.
+*
+*   Given and/or returned:
+*      prj->r0      Reset to 180/pi if 0.
+*      prj->phi0    Reset to 0.0 if undefined.
+*      prj->theta0  Reset to 0.0 if undefined.
+*
+*   Returned:
+*      prj->flag     TSC
+*      prj->code    "TSC"
+*      prj->x0      Fiducial offset in x.
+*      prj->y0      Fiducial offset in y.
+*      prj->w[0]    r0*(pi/4)
+*      prj->w[1]    (4/pi)/r0
+*      prj->prjx2s  Pointer to tscx2s().
+*      prj->prjs2x  Pointer to tscs2x().
+*===========================================================================*/
+
+int tscset(prj)
+
+struct prjprm *prj;
+
+{
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+
+  prj->flag = TSC;
+  strcpy(prj->code, "TSC");
+
+  strcpy(prj->name, "tangential spherical cube");
+  prj->category  = QUADCUBE;
+  prj->pvrange   = 0;
+  prj->simplezen = 0;
+  prj->equiareal = 0;
+  prj->conformal = 0;
+  prj->global    = 1;
+  prj->divergent = 0;
+
+  if (prj->r0 == 0.0) {
+    prj->r0 = R2D;
+    prj->w[0] = 45.0;
+    prj->w[1] = 1.0/45.0;
+  } else {
+    prj->w[0] = prj->r0*PI/4.0;
+    prj->w[1] = 1.0/prj->w[0];
+  }
+
+  prj->prjx2s = tscx2s;
+  prj->prjs2x = tscs2x;
+
+  return prjoff(prj, 0.0, 0.0);
+}
+
+/*--------------------------------------------------------------------------*/
+
+int tscx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)
+
+struct prjprm *prj;
+int nx, ny, sxy, spt;
+const double x[], y[];
+double phi[], theta[];
+int stat[];
+
+{
+  int mx, my, rowlen, rowoff, status;
+  double l, m, n, xf, yf;
+  register int ix, iy, *statp;
+  register const double *xp, *yp;
+  register double *phip, *thetap;
+
+
+  /* Initialize. */
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+  if (prj->flag != TSC) {
+    if ((status = tscset(prj))) return status;
+  }
+
+  if (ny > 0) {
+    mx = nx;
+    my = ny;
+  } else {
+    mx = 1;
+    my = 1;
+    ny = nx;
+  }
+
+  status = 0;
+
+
+  /* Do x dependence. */
+  xp = x;
+  rowoff = 0;
+  rowlen = nx*spt;
+  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
+    xf = (*xp + prj->x0)*prj->w[1];
+
+    phip = phi + rowoff;
+    for (iy = 0; iy < my; iy++) {
+      *phip = xf;
+      phip += rowlen;
+    }
+  }
+
+
+  /* Do y dependence. */
+  yp = y;
+  phip   = phi;
+  thetap = theta;
+  statp  = stat;
+  for (iy = 0; iy < ny; iy++, yp += sxy) {
+    yf = (*yp + prj->y0)*prj->w[1];
+
+    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
+      xf = *phip;
+
+      /* Check bounds. */
+      if (fabs(xf) <= 1.0) {
+        if (fabs(yf) > 3.0) {
+          *phip = 0.0;
+          *thetap = 0.0;
+          *(statp++) = 1;
+          if (!status) status = PRJERR_BAD_PIX_SET("tscx2s");
+          continue;
+        }
+      } else {
+        if (fabs(xf) > 7.0 || fabs(yf) > 1.0) {
+          *phip = 0.0;
+          *thetap = 0.0;
+          *(statp++) = 1;
+          if (!status) status = PRJERR_BAD_PIX_SET("tscx2s");
+          continue;
+        }
+      }
+
+      /* Map negative faces to the other side. */
+      if (xf < -1.0) xf += 8.0;
+
+      /* Determine the face. */
+      if (xf > 5.0) {
+        /* face = 4 */
+        xf = xf - 6.0;
+        m  = -1.0/sqrt(1.0 + xf*xf + yf*yf);
+        l  = -m*xf;
+        n  = -m*yf;
+      } else if (xf > 3.0) {
+        /* face = 3 */
+        xf = xf - 4.0;
+        l  = -1.0/sqrt(1.0 + xf*xf + yf*yf);
+        m  =  l*xf;
+        n  = -l*yf;
+      } else if (xf > 1.0) {
+        /* face = 2 */
+        xf = xf - 2.0;
+        m  =  1.0/sqrt(1.0 + xf*xf + yf*yf);
+        l  = -m*xf;
+        n  =  m*yf;
+      } else if (yf > 1.0) {
+        /* face = 0 */
+        yf = yf - 2.0;
+        n  = 1.0/sqrt(1.0 + xf*xf + yf*yf);
+        l  = -n*yf;
+        m  =  n*xf;
+      } else if (yf < -1.0) {
+        /* face = 5 */
+        yf = yf + 2.0;
+        n  = -1.0/sqrt(1.0 + xf*xf + yf*yf);
+        l  = -n*yf;
+        m  = -n*xf;
+      } else {
+        /* face = 1 */
+        l  =  1.0/sqrt(1.0 + xf*xf + yf*yf);
+        m  =  l*xf;
+        n  =  l*yf;
+      }
+
+      if (l == 0.0 && m == 0.0) {
+        *phip = 0.0;
+      } else {
+        *phip = atan2d(m, l);
+      }
+
+      *thetap = asind(n);
+      *(statp++) = 0;
+    }
+  }
+
+  return status;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int tscs2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)
+
+struct prjprm *prj;
+int nphi, ntheta, spt, sxy;
+const double phi[], theta[];
+double x[], y[];
+int stat[];
+
+{
+  int face, mphi, mtheta, rowlen, rowoff, status;
+  double cosphi, costhe, l, m, n, sinphi, sinthe, x0, xf, y0, yf, zeta;
+  const double tol = 1.0e-12;
+  register int iphi, istat, itheta, *statp;
+  register const double *phip, *thetap;
+  register double *xp, *yp;
+
+  /* Initialize. */
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+  if (prj->flag != TSC) {
+    if ((status = tscset(prj))) return status;
+  }
+
+  if (ntheta > 0) {
+    mphi   = nphi;
+    mtheta = ntheta;
+  } else {
+    mphi   = 1;
+    mtheta = 1;
+    ntheta = nphi;
+  }
+
+  status = 0;
+
+
+  /* Do phi dependence. */
+  phip = phi;
+  rowoff = 0;
+  rowlen = nphi*sxy;
+  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
+    sincosd(*phip, &sinphi, &cosphi);
+
+    xp = x + rowoff;
+    yp = y + rowoff;
+    for (itheta = 0; itheta < mtheta; itheta++) {
+      *xp = cosphi;
+      *yp = sinphi;
+      xp += rowlen;
+      yp += rowlen;
+    }
+  }
+
+
+  /* Do theta dependence. */
+  thetap = theta;
+  xp = x;
+  yp = y;
+  statp = stat;
+  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
+    sincosd(*thetap, &sinthe, &costhe);
+
+    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
+      l = costhe*(*xp);
+      m = costhe*(*yp);
+      n = sinthe;
+
+      face = 0;
+      zeta = n;
+      if (l > zeta) {
+        face = 1;
+        zeta = l;
+      }
+      if (m > zeta) {
+        face = 2;
+        zeta = m;
+      }
+      if (-l > zeta) {
+        face = 3;
+        zeta = -l;
+      }
+      if (-m > zeta) {
+        face = 4;
+        zeta = -m;
+      }
+      if (-n > zeta) {
+        face = 5;
+        zeta = -n;
+      }
+
+      switch (face) {
+      case 1:
+        xf =  m/zeta;
+        yf =  n/zeta;
+        x0 =  0.0;
+        y0 =  0.0;
+        break;
+      case 2:
+        xf = -l/zeta;
+        yf =  n/zeta;
+        x0 =  2.0;
+        y0 =  0.0;
+        break;
+      case 3:
+        xf = -m/zeta;
+        yf =  n/zeta;
+        x0 =  4.0;
+        y0 =  0.0;
+        break;
+      case 4:
+        xf =  l/zeta;
+        yf =  n/zeta;
+        x0 =  6.0;
+        y0 =  0.0;
+        break;
+      case 5:
+        xf =  m/zeta;
+        yf =  l/zeta;
+        x0 =  0.0;
+        y0 = -2.0;
+        break;
+      default:
+        /* face == 0 */
+        xf =  m/zeta;
+        yf = -l/zeta;
+        x0 =  0.0;
+        y0 =  2.0;
+        break;
+      }
+
+      istat = 0;
+      if (fabs(xf) > 1.0) {
+        if (fabs(xf) > 1.0+tol) {
+          istat = 1;
+          if (!status) status = PRJERR_BAD_WORLD_SET("tscs2x");
+        }
+        xf = copysign(1.0, xf);
+      }
+      if (fabs(yf) > 1.0) {
+        if (fabs(yf) > 1.0+tol) {
+          istat = 1;
+          if (!status) status = PRJERR_BAD_WORLD_SET("tscs2x");
+        }
+        yf = copysign(1.0, yf);
+      }
+
+      *xp = prj->w[0]*(xf + x0) - prj->x0;
+      *yp = prj->w[0]*(yf + y0) - prj->y0;
+      *(statp++) = istat;
+    }
+  }
+
+  return status;
+}
+
+/*============================================================================
+*   CSC: COBE quadrilateralized spherical cube projection.
+*
+*   Given and/or returned:
+*      prj->r0      Reset to 180/pi if 0.
+*      prj->phi0    Reset to 0.0 if undefined.
+*      prj->theta0  Reset to 0.0 if undefined.
+*
+*   Returned:
+*      prj->flag     CSC
+*      prj->code    "CSC"
+*      prj->x0      Fiducial offset in x.
+*      prj->y0      Fiducial offset in y.
+*      prj->w[0]    r0*(pi/4)
+*      prj->w[1]    (4/pi)/r0
+*      prj->prjx2s  Pointer to cscx2s().
+*      prj->prjs2x  Pointer to cscs2x().
+*===========================================================================*/
+
+int cscset(prj)
+
+struct prjprm *prj;
+
+{
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+
+  prj->flag = CSC;
+  strcpy(prj->code, "CSC");
+
+  strcpy(prj->name, "COBE quadrilateralized spherical cube");
+  prj->category  = QUADCUBE;
+  prj->pvrange   = 0;
+  prj->simplezen = 0;
+  prj->equiareal = 0;
+  prj->conformal = 0;
+  prj->global    = 1;
+  prj->divergent = 0;
+
+  if (prj->r0 == 0.0) {
+    prj->r0 = R2D;
+    prj->w[0] = 45.0;
+    prj->w[1] = 1.0/45.0;
+  } else {
+    prj->w[0] = prj->r0*PI/4.0;
+    prj->w[1] = 1.0/prj->w[0];
+  }
+
+  prj->prjx2s = cscx2s;
+  prj->prjs2x = cscs2x;
+
+  return prjoff(prj, 0.0, 0.0);
+}
+
+/*--------------------------------------------------------------------------*/
+
+int cscx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)
+
+struct prjprm *prj;
+int nx, ny, sxy, spt;
+const double x[], y[];
+double phi[], theta[];
+int stat[];
+
+{
+  int face, mx, my, rowlen, rowoff, status;
+  double l, m, n, t;
+  register int ix, iy, *statp;
+  register const double *xp, *yp;
+  register double *phip, *thetap;
+
+  float chi, psi, xf, xx, yf, yy, z0, z1, z2, z3, z4, z5, z6;
+  const float p00 = -0.27292696f;
+  const float p10 = -0.07629969f;
+  const float p20 = -0.22797056f;
+  const float p30 =  0.54852384f;
+  const float p40 = -0.62930065f;
+  const float p50 =  0.25795794f;
+  const float p60 =  0.02584375f;
+  const float p01 = -0.02819452f;
+  const float p11 = -0.01471565f;
+  const float p21 =  0.48051509f;
+  const float p31 = -1.74114454f;
+  const float p41 =  1.71547508f;
+  const float p51 = -0.53022337f;
+  const float p02 =  0.27058160f;
+  const float p12 = -0.56800938f;
+  const float p22 =  0.30803317f;
+  const float p32 =  0.98938102f;
+  const float p42 = -0.83180469f;
+  const float p03 = -0.60441560f;
+  const float p13 =  1.50880086f;
+  const float p23 = -0.93678576f;
+  const float p33 =  0.08693841f;
+  const float p04 =  0.93412077f;
+  const float p14 = -1.41601920f;
+  const float p24 =  0.33887446f;
+  const float p05 = -0.63915306f;
+  const float p15 =  0.52032238f;
+  const float p06 =  0.14381585f;
+
+  /* Initialize. */
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+  if (prj->flag != CSC) {
+    if ((status = cscset(prj))) return status;
+  }
+
+  if (ny > 0) {
+    mx = nx;
+    my = ny;
+  } else {
+    mx = 1;
+    my = 1;
+    ny = nx;
+  }
+
+  status = 0;
+
+
+  /* Do x dependence. */
+  xp = x;
+  rowoff = 0;
+  rowlen = nx*spt;
+  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
+    xf = (float)((*xp + prj->x0)*prj->w[1]);
+
+    phip = phi + rowoff;
+    for (iy = 0; iy < my; iy++) {
+      *phip = xf;
+      phip += rowlen;
+    }
+  }
+
+
+  /* Do y dependence. */
+  yp = y;
+  phip   = phi;
+  thetap = theta;
+  statp  = stat;
+  for (iy = 0; iy < ny; iy++, yp += sxy) {
+    yf = (float)((*yp + prj->y0)*prj->w[1]);
+
+    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
+      xf = (float)(*phip);
+
+      /* Check bounds. */
+      if (fabs((double)xf) <= 1.0) {
+        if (fabs((double)yf) > 3.0) {
+          *phip = 0.0;
+          *thetap = 0.0;
+          *(statp++) = 1;
+          if (!status) status = PRJERR_BAD_PIX_SET("cscx2s");
+          continue;
+        }
+      } else {
+        if (fabs((double)xf) > 7.0 || fabs((double)yf) > 1.0) {
+          *phip = 0.0;
+          *thetap = 0.0;
+          *(statp++) = 1;
+          if (!status) status = PRJERR_BAD_PIX_SET("cscx2s");
+          continue;
+        }
+      }
+
+      /* Map negative faces to the other side. */
+      if (xf < -1.0f) xf += 8.0f;
+
+      /* Determine the face. */
+      if (xf > 5.0f) {
+        face = 4;
+        xf = xf - 6.0f;
+      } else if (xf > 3.0f) {
+        face = 3;
+        xf = xf - 4.0f;
+      } else if (xf > 1.0f) {
+        face = 2;
+        xf = xf - 2.0f;
+      } else if (yf > 1.0f) {
+        face = 0;
+        yf = yf - 2.0f;
+      } else if (yf < -1.0f) {
+        face = 5;
+        yf = yf + 2.0f;
+      } else {
+        face = 1;
+      }
+
+      xx  =  xf*xf;
+      yy  =  yf*yf;
+
+      z0 = p00 + xx*(p10 + xx*(p20 + xx*(p30 + xx*(p40 + xx*(p50 +
+                 xx*(p60))))));
+      z1 = p01 + xx*(p11 + xx*(p21 + xx*(p31 + xx*(p41 + xx*(p51)))));
+      z2 = p02 + xx*(p12 + xx*(p22 + xx*(p32 + xx*(p42))));
+      z3 = p03 + xx*(p13 + xx*(p23 + xx*(p33)));
+      z4 = p04 + xx*(p14 + xx*(p24));
+      z5 = p05 + xx*(p15);
+      z6 = p06;
+
+      chi = z0 + yy*(z1 + yy*(z2 + yy*(z3 + yy*(z4 + yy*(z5 + yy*z6)))));
+      chi = xf + xf*(1.0f - xx)*chi;
+
+      z0 = p00 + yy*(p10 + yy*(p20 + yy*(p30 + yy*(p40 + yy*(p50 +
+                 yy*(p60))))));
+      z1 = p01 + yy*(p11 + yy*(p21 + yy*(p31 + yy*(p41 + yy*(p51)))));
+      z2 = p02 + yy*(p12 + yy*(p22 + yy*(p32 + yy*(p42))));
+      z3 = p03 + yy*(p13 + yy*(p23 + yy*(p33)));
+      z4 = p04 + yy*(p14 + yy*(p24));
+      z5 = p05 + yy*(p15);
+      z6 = p06;
+
+      psi = z0 + xx*(z1 + xx*(z2 + xx*(z3 + xx*(z4 + xx*(z5 + xx*z6)))));
+      psi = yf + yf*(1.0f - yy)*psi;
+
+      t = 1.0/sqrt((double)(chi*chi + psi*psi) + 1.0);
+      switch (face) {
+      case 1:
+        l =  t;
+        m =  chi*l;
+        n =  psi*l;
+        break;
+      case 2:
+        m =  t;
+        l = -chi*m;
+        n =  psi*m;
+        break;
+      case 3:
+        l = -t;
+        m =  chi*l;
+        n = -psi*l;
+        break;
+      case 4:
+        m = -t;
+        l = -chi*m;
+        n = -psi*m;
+        break;
+      case 5:
+        n = -t;
+        l = -psi*n;
+        m = -chi*n;
+        break;
+      default:
+        /* face == 0 */
+        n =  t;
+        l = -psi*n;
+        m =  chi*n;
+        break;
+      }
+
+      if (l == 0.0 && m == 0.0) {
+        *phip = 0.0;
+      } else {
+        *phip = atan2d(m, l);
+      }
+
+      *thetap = asind(n);
+      *(statp++) = 0;
+    }
+  }
+
+  return status;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int cscs2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)
+
+struct prjprm *prj;
+int nphi, ntheta, spt, sxy;
+const double phi[], theta[];
+double x[], y[];
+int stat[];
+
+{
+  int face, mphi, mtheta, rowlen, rowoff, status;
+  double cosphi, costhe, eta, l, m, n, sinphi, sinthe, xi, zeta;
+  const float tol = 1.0e-7;
+  register int iphi, istat, itheta, *statp;
+  register const double *phip, *thetap;
+  register double *xp, *yp;
+
+  float chi, chi2, chi2psi2, chi4, chipsi, psi, psi2, psi4, chi2co, psi2co,
+        x0, xf, y0, yf;
+  const float gstar  =  1.37484847732f;
+  const float mm     =  0.004869491981f;
+  const float gamma  = -0.13161671474f;
+  const float omega1 = -0.159596235474f;
+  const float d0  =  0.0759196200467f;
+  const float d1  = -0.0217762490699f;
+  const float c00 =  0.141189631152f;
+  const float c10 =  0.0809701286525f;
+  const float c01 = -0.281528535557f;
+  const float c11 =  0.15384112876f;
+  const float c20 = -0.178251207466f;
+  const float c02 =  0.106959469314f;
+
+
+  /* Initialize. */
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+  if (prj->flag != CSC) {
+    if ((status = cscset(prj))) return status;
+  }
+
+  if (ntheta > 0) {
+    mphi   = nphi;
+    mtheta = ntheta;
+  } else {
+    mphi   = 1;
+    mtheta = 1;
+    ntheta = nphi;
+  }
+
+  status = 0;
+
+
+  /* Do phi dependence. */
+  phip = phi;
+  rowoff = 0;
+  rowlen = nphi*sxy;
+  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
+    sincosd(*phip, &sinphi, &cosphi);
+
+    xp = x + rowoff;
+    yp = y + rowoff;
+    for (itheta = 0; itheta < mtheta; itheta++) {
+      *xp = cosphi;
+      *yp = sinphi;
+      xp += rowlen;
+      yp += rowlen;
+    }
+  }
+
+
+  /* Do theta dependence. */
+  thetap = theta;
+  xp = x;
+  yp = y;
+  statp = stat;
+  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
+    sincosd(*thetap, &sinthe, &costhe);
+
+    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
+      l = costhe*(*xp);
+      m = costhe*(*yp);
+      n = sinthe;
+
+      face = 0;
+      zeta = n;
+      if (l > zeta) {
+        face = 1;
+        zeta = l;
+      }
+      if (m > zeta) {
+        face = 2;
+        zeta = m;
+      }
+      if (-l > zeta) {
+        face = 3;
+        zeta = -l;
+      }
+      if (-m > zeta) {
+        face = 4;
+        zeta = -m;
+      }
+      if (-n > zeta) {
+        face = 5;
+        zeta = -n;
+      }
+
+      switch (face) {
+      case 1:
+        xi  =  m;
+        eta =  n;
+        x0  =  0.0;
+        y0  =  0.0;
+        break;
+      case 2:
+        xi  = -l;
+        eta =  n;
+        x0  =  2.0;
+        y0  =  0.0;
+        break;
+      case 3:
+        xi  = -m;
+        eta =  n;
+        x0  =  4.0;
+        y0  =  0.0;
+        break;
+      case 4:
+        xi  =  l;
+        eta =  n;
+        x0  =  6.0;
+        y0  =  0.0;
+        break;
+      case 5:
+        xi  =  m;
+        eta =  l;
+        x0  =  0.0;
+        y0  = -2.0;
+        break;
+      default:
+        /* face == 0 */
+        xi  =  m;
+        eta = -l;
+        x0  =  0.0;
+        y0  =  2.0;
+        break;
+      }
+
+      chi = (float)( xi/zeta);
+      psi = (float)(eta/zeta);
+
+      chi2 = chi*chi;
+      psi2 = psi*psi;
+      chi2co = 1.0f - chi2;
+      psi2co = 1.0f - psi2;
+
+      /* Avoid floating underflows. */
+      chipsi = (float)fabs((double)(chi*psi));
+      chi4   = (chi2 > 1.0e-16f) ? chi2*chi2 : 0.0f;
+      psi4   = (psi2 > 1.0e-16f) ? psi2*psi2 : 0.0f;
+      chi2psi2 = (chipsi > 1.0e-16f) ? chi2*psi2 : 0.0f;
+
+      xf = chi*(chi2 + chi2co*(gstar + psi2*(gamma*chi2co + mm*chi2 +
+                psi2co*(c00 + c10*chi2 + c01*psi2 + c11*chi2psi2 + c20*chi4 +
+                c02*psi4)) + chi2*(omega1 - chi2co*(d0 + d1*chi2))));
+      yf = psi*(psi2 + psi2co*(gstar + chi2*(gamma*psi2co + mm*psi2 +
+                chi2co*(c00 + c10*psi2 + c01*chi2 + c11*chi2psi2 + c20*psi4 +
+                c02*chi4)) + psi2*(omega1 - psi2co*(d0 + d1*psi2))));
+
+      istat = 0;
+      if (fabs((double)xf) > 1.0) {
+        if (fabs((double)xf) > 1.0+tol) {
+          istat = 1;
+          if (!status) status = PRJERR_BAD_WORLD_SET("cscs2x");
+        }
+        xf = (float)copysign(1.0, (double)xf);
+      }
+      if (fabs((double)yf) > 1.0) {
+        if (fabs((double)yf) > 1.0+tol) {
+          istat = 1;
+          if (!status) status = PRJERR_BAD_WORLD_SET("cscs2x");
+        }
+        yf = (float)copysign(1.0, (double)yf);
+      }
+
+      *xp = prj->w[0]*(xf + x0) - prj->x0;
+      *yp = prj->w[0]*(yf + y0) - prj->y0;
+      *(statp++) = istat;
+    }
+  }
+
+  return status;
+}
+
+/*============================================================================
+*   QSC: quadrilaterilized spherical cube projection.
+*
+*   Given and/or returned:
+*      prj->r0      Reset to 180/pi if 0.
+*      prj->phi0    Reset to 0.0 if undefined.
+*      prj->theta0  Reset to 0.0 if undefined.
+*
+*   Returned:
+*      prj->flag     QSC
+*      prj->code    "QSC"
+*      prj->x0      Fiducial offset in x.
+*      prj->y0      Fiducial offset in y.
+*      prj->w[0]    r0*(pi/4)
+*      prj->w[1]    (4/pi)/r0
+*      prj->prjx2s  Pointer to qscx2s().
+*      prj->prjs2x  Pointer to qscs2x().
+*===========================================================================*/
+
+int qscset(prj)
+
+struct prjprm *prj;
+
+{
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+
+  prj->flag = QSC;
+  strcpy(prj->code, "QSC");
+
+  strcpy(prj->name, "quadrilateralized spherical cube");
+  prj->category  = QUADCUBE;
+  prj->pvrange   = 0;
+  prj->simplezen = 0;
+  prj->equiareal = 1;
+  prj->conformal = 0;
+  prj->global    = 1;
+  prj->divergent = 0;
+
+  if (prj->r0 == 0.0) {
+    prj->r0 = R2D;
+    prj->w[0] = 45.0;
+    prj->w[1] = 1.0/45.0;
+  } else {
+    prj->w[0] = prj->r0*PI/4.0;
+    prj->w[1] = 1.0/prj->w[0];
+  }
+
+  prj->prjx2s = qscx2s;
+  prj->prjs2x = qscs2x;
+
+  return prjoff(prj, 0.0, 0.0);
+}
+
+/*--------------------------------------------------------------------------*/
+
+int qscx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)
+
+struct prjprm *prj;
+int nx, ny, sxy, spt;
+const double x[], y[];
+double phi[], theta[];
+int stat[];
+
+{
+  int direct, face, mx, my, rowlen, rowoff, status;
+  double cosw, l, m, n, omega, sinw, tau, xf, yf, w, zeco, zeta;
+  const double tol = 1.0e-12;
+  register int ix, iy, *statp;
+  register const double *xp, *yp;
+  register double *phip, *thetap;
+
+
+  /* Initialize. */
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+  if (prj->flag != QSC) {
+    if ((status = qscset(prj))) return status;
+  }
+
+  if (ny > 0) {
+    mx = nx;
+    my = ny;
+  } else {
+    mx = 1;
+    my = 1;
+    ny = nx;
+  }
+
+  status = 0;
+
+
+  /* Do x dependence. */
+  xp = x;
+  rowoff = 0;
+  rowlen = nx*spt;
+  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
+    xf = (*xp + prj->x0)*prj->w[1];
+
+    phip = phi + rowoff;
+    for (iy = 0; iy < my; iy++) {
+      *phip = xf;
+      phip += rowlen;
+    }
+  }
+
+
+  /* Do y dependence. */
+  yp = y;
+  phip   = phi;
+  thetap = theta;
+  statp  = stat;
+  for (iy = 0; iy < ny; iy++, yp += sxy) {
+    yf = (*yp + prj->y0)*prj->w[1];
+
+    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
+      xf = *phip;
+
+      /* Check bounds. */
+      if (fabs(xf) <= 1.0) {
+        if (fabs(yf) > 3.0) {
+          *phip = 0.0;
+          *thetap = 0.0;
+          *(statp++) = 1;
+          if (!status) status = PRJERR_BAD_PIX_SET("qscx2s");
+          continue;
+        }
+      } else {
+        if (fabs(xf) > 7.0 || fabs(yf) > 1.0) {
+          *phip = 0.0;
+          *thetap = 0.0;
+          *(statp++) = 1;
+          if (!status) status = PRJERR_BAD_PIX_SET("qscx2s");
+          continue;
+        }
+      }
+
+      /* Map negative faces to the other side. */
+      if (xf < -1.0) xf += 8.0;
+
+      /* Determine the face. */
+      if (xf > 5.0) {
+        face = 4;
+        xf -= 6.0;
+      } else if (xf > 3.0) {
+        face = 3;
+        xf -= 4.0;
+      } else if (xf > 1.0) {
+        face = 2;
+        xf -= 2.0;
+      } else if (yf > 1.0) {
+        face = 0;
+        yf -= 2.0;
+      } else if (yf < -1.0) {
+        face = 5;
+        yf += 2.0;
+      } else {
+        face = 1;
+      }
+
+      direct = (fabs(xf) > fabs(yf));
+      if (direct) {
+        if (xf == 0.0) {
+          omega = 0.0;
+          tau  = 1.0;
+          zeta = 1.0;
+          zeco = 0.0;
+        } else {
+          w = 15.0*yf/xf;
+          omega = sind(w)/(cosd(w) - SQRT2INV);
+          tau  = 1.0 + omega*omega;
+          zeco = xf*xf*(1.0 - 1.0/sqrt(1.0 + tau));
+          zeta = 1.0 - zeco;
+        }
+      } else {
+        if (yf == 0.0) {
+          omega = 0.0;
+          tau  = 1.0;
+          zeta = 1.0;
+          zeco = 0.0;
+        } else {
+          w = 15.0*xf/yf;
+          sincosd(w, &sinw, &cosw);
+          omega = sinw/(cosw - SQRT2INV);
+          tau  = 1.0 + omega*omega;
+          zeco = yf*yf*(1.0 - 1.0/sqrt(1.0 + tau));
+          zeta = 1.0 - zeco;
+        }
+      }
+
+      if (zeta < -1.0) {
+        if (zeta < -1.0-tol) {
+          *phip = 0.0;
+          *thetap = 0.0;
+          *(statp++) = 1;
+          if (!status) status = PRJERR_BAD_PIX_SET("qscx2s");
+          continue;
+        }
+
+        zeta = -1.0;
+        zeco =  2.0;
+        w    =  0.0;
+      } else {
+        w = sqrt(zeco*(2.0-zeco)/tau);
+      }
+
+      switch (face) {
+      case 1:
+        l = zeta;
+        if (direct) {
+          m = w;
+          if (xf < 0.0) m = -m;
+          n = m*omega;
+        } else {
+          n = w;
+          if (yf < 0.0) n = -n;
+          m = n*omega;
+        }
+        break;
+      case 2:
+        m = zeta;
+        if (direct) {
+          l = w;
+          if (xf > 0.0) l = -l;
+          n = -l*omega;
+        } else {
+          n = w;
+          if (yf < 0.0) n = -n;
+          l = -n*omega;
+        }
+        break;
+      case 3:
+        l = -zeta;
+        if (direct) {
+          m = w;
+          if (xf > 0.0) m = -m;
+          n = -m*omega;
+        } else {
+          n = w;
+          if (yf < 0.0) n = -n;
+          m = -n*omega;
+        }
+        break;
+      case 4:
+        m = -zeta;
+        if (direct) {
+          l = w;
+          if (xf < 0.0) l = -l;
+          n = l*omega;
+        } else {
+          n = w;
+          if (yf < 0.0) n = -n;
+          l = n*omega;
+        }
+        break;
+      case 5:
+        n = -zeta;
+        if (direct) {
+          m = w;
+          if (xf < 0.0) m = -m;
+          l = m*omega;
+        } else {
+          l = w;
+          if (yf < 0.0) l = -l;
+          m = l*omega;
+        }
+        break;
+      default:
+        /* face == 0 */
+        n = zeta;
+        if (direct) {
+          m = w;
+          if (xf < 0.0) m = -m;
+          l = -m*omega;
+        } else {
+          l = w;
+          if (yf > 0.0) l = -l;
+          m = -l*omega;
+        }
+        break;
+      }
+
+      if (l == 0.0 && m == 0.0) {
+        *phip = 0.0;
+      } else {
+        *phip = atan2d(m, l);
+      }
+
+      *thetap = asind(n);
+      *(statp++) = 0;
+    }
+  }
+
+  return status;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int qscs2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)
+
+struct prjprm *prj;
+int nphi, ntheta, spt, sxy;
+const double phi[], theta[];
+double x[], y[];
+int stat[];
+
+{
+  int face, mphi, mtheta, rowlen, rowoff, status;
+  double cosphi, costhe, eta, l, m, n, omega, p, sinphi, sinthe, t, tau, x0,
+         xf, xi, y0, yf, zeco, zeta;
+  const double tol = 1.0e-12;
+  register int iphi, istat, itheta, *statp;
+  register const double *phip, *thetap;
+  register double *xp, *yp;
+
+
+  /* Initialize. */
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+  if (prj->flag != QSC) {
+    if ((status = qscset(prj))) return status;
+  }
+
+  if (ntheta > 0) {
+    mphi   = nphi;
+    mtheta = ntheta;
+  } else {
+    mphi   = 1;
+    mtheta = 1;
+    ntheta = nphi;
+  }
+
+  status = 0;
+
+
+  /* Do phi dependence. */
+  phip = phi;
+  rowoff = 0;
+  rowlen = nphi*sxy;
+  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
+    sincosd(*phip, &sinphi, &cosphi);
+
+    xp = x + rowoff;
+    yp = y + rowoff;
+    for (itheta = 0; itheta < mtheta; itheta++) {
+      *xp = cosphi;
+      *yp = sinphi;
+      xp += rowlen;
+      yp += rowlen;
+    }
+  }
+
+
+  /* Do theta dependence. */
+  thetap = theta;
+  xp = x;
+  yp = y;
+  statp = stat;
+  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
+    sincosd(*thetap, &sinthe, &costhe);
+
+    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
+      if (fabs(*thetap) == 90.0) {
+        *xp = -prj->x0;
+        *yp = copysign(2.0*prj->w[0], *thetap) - prj->y0;
+        *(statp++) = 0;
+        continue;
+      }
+
+      l = costhe*(*xp);
+      m = costhe*(*yp);
+      n = sinthe;
+
+      face = 0;
+      zeta = n;
+      if (l > zeta) {
+        face = 1;
+        zeta = l;
+      }
+      if (m > zeta) {
+        face = 2;
+        zeta = m;
+      }
+      if (-l > zeta) {
+        face = 3;
+        zeta = -l;
+      }
+      if (-m > zeta) {
+        face = 4;
+        zeta = -m;
+      }
+      if (-n > zeta) {
+        face = 5;
+        zeta = -n;
+      }
+
+      zeco = 1.0 - zeta;
+
+      switch (face) {
+      case 1:
+        xi  = m;
+        eta = n;
+        if (zeco < 1.0e-8) {
+          /* Small angle formula. */
+          t = (*thetap)*D2R;
+          p = atan2(*yp, *xp);
+          zeco = (p*p + t*t)/2.0;
+        }
+        x0 = 0.0;
+        y0 = 0.0;
+        break;
+      case 2:
+        xi  = -l;
+        eta =  n;
+        if (zeco < 1.0e-8) {
+          /* Small angle formula. */
+          t = (*thetap)*D2R;
+          p = atan2(*yp, *xp) - PI/2.0;
+          zeco = (p*p + t*t)/2.0;
+        }
+        x0 = 2.0;
+        y0 = 0.0;
+        break;
+      case 3:
+        xi  = -m;
+        eta =  n;
+        if (zeco < 1.0e-8) {
+          /* Small angle formula. */
+          t = (*thetap)*D2R;
+          p = atan2(*yp, *xp);
+          p -= copysign(PI, p);
+          zeco = (p*p + t*t)/2.0;
+        }
+        x0 = 4.0;
+        y0 = 0.0;
+        break;
+      case 4:
+        xi  = l;
+        eta = n;
+        if (zeco < 1.0e-8) {
+          /* Small angle formula. */
+          t = (*thetap)*D2R;
+          p = atan2(*yp, *xp) + PI/2.0;
+          zeco = (p*p + t*t)/2.0;
+        }
+        x0 = 6;
+        y0 = 0.0;
+        break;
+      case 5:
+        xi  =  m;
+        eta =  l;
+        if (zeco < 1.0e-8) {
+          /* Small angle formula. */
+          t = (*thetap + 90.0)*D2R;
+          zeco = t*t/2.0;
+        }
+        x0 =  0.0;
+        y0 = -2;
+         break;
+      default:
+        /* face == 0 */
+        xi  =  m;
+        eta = -l;
+        if (zeco < 1.0e-8) {
+          /* Small angle formula. */
+          t = (90.0 - *thetap)*D2R;
+          zeco = t*t/2.0;
+        }
+        x0 = 0.0;
+        y0 = 2.0;
+        break;
+      }
+
+      xf = 0.0;
+      yf = 0.0;
+      if (xi != 0.0 || eta != 0.0) {
+        if (-xi > fabs(eta)) {
+          omega = eta/xi;
+          tau = 1.0 + omega*omega;
+          xf  = -sqrt(zeco/(1.0 - 1.0/sqrt(1.0+tau)));
+          yf  = (xf/15.0)*(atand(omega) - asind(omega/sqrt(tau+tau)));
+        } else if (xi > fabs(eta)) {
+          omega = eta/xi;
+          tau = 1.0 + omega*omega;
+          xf  =  sqrt(zeco/(1.0 - 1.0/sqrt(1.0+tau)));
+          yf  = (xf/15.0)*(atand(omega) - asind(omega/sqrt(tau+tau)));
+        } else if (-eta >= fabs(xi)) {
+          omega = xi/eta;
+          tau = 1.0 + omega*omega;
+          yf  = -sqrt(zeco/(1.0 - 1.0/sqrt(1.0+tau)));
+          xf  = (yf/15.0)*(atand(omega) - asind(omega/sqrt(tau+tau)));
+        } else if (eta >= fabs(xi)) {
+          omega = xi/eta;
+          tau = 1.0 + omega*omega;
+          yf  =  sqrt(zeco/(1.0 - 1.0/sqrt(1.0+tau)));
+          xf  = (yf/15.0)*(atand(omega) - asind(omega/sqrt(tau+tau)));
+        }
+      }
+
+      istat = 0;
+      if (fabs(xf) > 1.0) {
+        if (fabs(xf) > 1.0+tol) {
+          istat = 1;
+          if (!status) status = PRJERR_BAD_WORLD_SET("qscs2x");
+        }
+        xf = copysign(1.0, xf);
+      }
+      if (fabs(yf) > 1.0) {
+        if (fabs(yf) > 1.0+tol) {
+          istat = 1;
+          if (!status) status = PRJERR_BAD_WORLD_SET("qscs2x");
+        }
+        yf = copysign(1.0, yf);
+      }
+
+      *xp = prj->w[0]*(xf + x0) - prj->x0;
+      *yp = prj->w[0]*(yf + y0) - prj->y0;
+      *(statp++) = istat;
+    }
+  }
+
+  return status;
+}
+
+/*============================================================================
+*   HPX: HEALPix projection.
+*
+*   Given:
+*      prj->pv[1]   H - the number of facets in longitude.
+*      prj->pv[2]   K - the number of facets in latitude
+*
+*   Given and/or returned:
+*      prj->r0      Reset to 180/pi if 0.
+*      prj->phi0    Reset to 0.0 if undefined.
+*      prj->theta0  Reset to 0.0 if undefined.
+*
+*   Returned:
+*      prj->flag     HPX
+*      prj->code    "HPX"
+*      prj->x0      Fiducial offset in x.
+*      prj->y0      Fiducial offset in y.
+*      prj->m       True if H is odd.
+*      prj->n       True if K is odd.
+*      prj->w[0]    r0*(pi/180)
+*      prj->w[1]    (180/pi)/r0
+*      prj->w[2]    (K-1)/K
+*      prj->w[3]    90*K/H
+*      prj->w[4]    (K+1)/2
+*      prj->w[5]    90*(K-1)/H
+*      prj->w[6]    180/H
+*      prj->w[7]    H/360
+*      prj->w[8]    r0*(pi/180)*(90*K/H)
+*      prj->w[9]    r0*(pi/180)*(180/H)
+*      prj->prjx2s  Pointer to hpxx2s().
+*      prj->prjs2x  Pointer to hpxs2x().
+*===========================================================================*/
+
+int hpxset(prj)
+
+struct prjprm *prj;
+
+{
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+
+  prj->flag = HPX;
+  strcpy(prj->code, "HPX");
+
+  if (undefined(prj->pv[1])) prj->pv[1] = 4.0;
+  if (undefined(prj->pv[2])) prj->pv[2] = 3.0;
+
+  strcpy(prj->name, "HEALPix");
+  prj->category  = HEALPIX;
+  prj->pvrange   = 102;
+  prj->simplezen = 0;
+  prj->equiareal = 1;
+  prj->conformal = 0;
+  prj->global    = 1;
+  prj->divergent = 0;
+
+  if (prj->pv[1] <= 0.0 || prj->pv[2] <= 0.0) {
+    return PRJERR_BAD_PARAM_SET("hpxset");
+  }
+
+  prj->m = ((int)(prj->pv[1]+0.5))%2;
+  prj->n = ((int)(prj->pv[2]+0.5))%2;
+
+  if (prj->r0 == 0.0) {
+    prj->r0 = R2D;
+    prj->w[0] = 1.0;
+    prj->w[1] = 1.0;
+  } else {
+    prj->w[0] = prj->r0*D2R;
+    prj->w[1] = R2D/prj->r0;
+  }
+
+  prj->w[2] = (prj->pv[2] - 1.0) / prj->pv[2];
+  prj->w[3] = 90.0 * prj->pv[2] / prj->pv[1];
+  prj->w[4] = (prj->pv[2] + 1.0) / 2.0;
+  prj->w[5] = 90.0 * (prj->pv[2] - 1.0) / prj->pv[1];
+  prj->w[6] = 180.0 / prj->pv[1];
+  prj->w[7] = prj->pv[1] / 360.0;
+  prj->w[8] = prj->w[3] * prj->w[0];
+  prj->w[9] = prj->w[6] * prj->w[0];
+
+  prj->prjx2s = hpxx2s;
+  prj->prjs2x = hpxs2x;
+
+  return prjoff(prj, 0.0, 0.0);
+}
+
+/*--------------------------------------------------------------------------*/
+
+int hpxx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)
+
+struct prjprm *prj;
+int nx, ny, sxy, spt;
+const double x[], y[];
+double phi[], theta[];
+int stat[];
+
+{
+  int h, mx, my, offset, rowlen, rowoff, status;
+  double absy, s, sigma, t, yr;
+  const double slim = prj->w[6] + 1e-12;
+  const double ylim = prj->w[9] * prj->w[4];
+  register int istat, ix, iy, *statp;
+  register const double *xp, *yp;
+  register double *phip, *thetap;
+
+
+  /* Initialize. */
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+  if (prj->flag != HPX) {
+    if ((status = hpxset(prj))) return status;
+  }
+
+  if (ny > 0) {
+    mx = nx;
+    my = ny;
+  } else {
+    mx = 1;
+    my = 1;
+    ny = nx;
+  }
+
+  status = 0;
+
+
+  /* Do x dependence. */
+  xp = x;
+  rowoff = 0;
+  rowlen = nx*spt;
+  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
+    s = prj->w[1] * (*xp + prj->x0);
+    /* x_c for K odd or theta > 0. */
+    t = -180.0 + (2.0 * floor((*xp + 180.0) * prj->w[7]) + 1.0) * prj->w[6];
+    t = prj->w[1] * (*xp - t);
+
+    phip   = phi + rowoff;
+    thetap = theta + rowoff;
+    for (iy = 0; iy < my; iy++) {
+      /* theta[] is used to hold (x - x_c). */
+      *phip   = s;
+      *thetap = t;
+      phip   += rowlen;
+      thetap += rowlen;
+    }
+  }
+
+
+  /* Do y dependence. */
+  yp = y;
+  phip   = phi;
+  thetap = theta;
+  statp  = stat;
+  for (iy = 0; iy < ny; iy++, yp += sxy) {
+    yr = prj->w[1]*(*yp + prj->y0);
+    absy = fabs(yr);
+
+    istat = 0;
+    if (absy <= prj->w[5]) {
+      /* Equatorial regime. */
+      t = asind(yr/prj->w[3]);
+      for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
+        *thetap = t;
+        *(statp++) = 0;
+      }
+
+    } else if (absy <= ylim) {
+      /* Polar regime. */
+      offset = (prj->n || *yp > 0.0) ? 0 : 1;
+
+      sigma = prj->w[4] - absy / prj->w[6];
+
+      if (sigma == 0.0) {
+        s = 1e9;
+        t = 90.0;
+
+      } else {
+        t = 1.0 - sigma*sigma/prj->pv[2];
+        if (t < -1.0) {
+          s = 0.0;
+          t = 0.0;
+          istat = 1;
+          if (!status) status = PRJERR_BAD_PIX_SET("hpxx2s");
+        } else {
+          s = 1.0/sigma;
+          t = asind(t);
+        }
+      }
+      if (*yp < 0.0) t = -t;
+
+      for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
+        if (offset) {
+          /* Offset the southern polar half-facets for even K. */
+          h = (int)floor(*phip / prj->w[6]) + prj->m;
+          if (h%2) {
+            *thetap -= prj->w[6];
+          } else {
+            *thetap += prj->w[6];
+          }
+        }
+
+        /* Recall that theta[] holds (x - x_c). */
+        s *= *thetap;
+        if (fabs(s) < slim) {
+          if (s != 0.0) s -= *thetap;
+          *phip += s;
+          *thetap = t;
+          *(statp++) = istat;
+        } else {
+          /* Out-of-bounds. */
+          *phip   = 0.0;
+          *thetap = 0.0;
+          *(statp++) = 1;
+          if (!status) status = PRJERR_BAD_PIX_SET("hpxx2s");
+        }
+      }
+
+    } else {
+      /* Beyond latitude range. */
+      for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
+        *phip   = 0.0;
+        *thetap = 0.0;
+        *(statp++) = 1;
+      }
+      if (!status) status = PRJERR_BAD_PIX_SET("hpxx2s");
+    }
+  }
+
+  return status;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int hpxs2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)
+
+struct prjprm *prj;
+int nphi, ntheta, spt, sxy;
+const double phi[], theta[];
+double x[], y[];
+int stat[];
+
+{
+  int h, mphi, mtheta, offset, rowlen, rowoff, status;
+  double abssin, eta, sigma, sinthe, t, xi;
+  register int iphi, itheta, *statp;
+  register const double *phip, *thetap;
+  register double *xp, *yp;
+
+
+  /* Initialize. */
+  if (prj == 0x0) return PRJERR_NULL_POINTER;
+  if (prj->flag != HPX) {
+    if ((status = hpxset(prj))) return status;
+  }
+
+  if (ntheta > 0) {
+    mphi   = nphi;
+    mtheta = ntheta;
+  } else {
+    mphi   = 1;
+    mtheta = 1;
+    ntheta = nphi;
+  }
+
+
+  /* Do phi dependence. */
+  phip = phi;
+  rowoff = 0;
+  rowlen = nphi*sxy;
+  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
+    xi = prj->w[0] * (*phip) - prj->x0;
+
+    /* phi_c for K odd or theta > 0. */
+    t = -180.0 + (2.0*floor((*phip+180.0) * prj->w[7]) + 1.0) * prj->w[6];
+    t = prj->w[0] * (*phip - t);
+
+    xp = x + rowoff;
+    yp = y + rowoff;
+    for (itheta = 0; itheta < mtheta; itheta++) {
+      /* y[] is used to hold (phi - phi_c). */
+      *xp = xi;
+      *yp = t;
+      xp += rowlen;
+      yp += rowlen;
+    }
+  }
+
+
+  /* Do theta dependence. */
+  thetap = theta;
+  xp = x;
+  yp = y;
+  statp = stat;
+  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
+    sinthe = sind(*thetap);
+    abssin = fabs(sinthe);
+
+    if (abssin <= prj->w[2]) {
+      /* Equatorial regime. */
+      eta = prj->w[8] * sinthe - prj->y0;
+      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
+        *yp = eta;
+        *(statp++) = 0;
+      }
+
+    } else {
+      /* Polar regime. */
+      offset = (prj->n || *thetap > 0.0) ? 0 : 1;
+
+      sigma = sqrt(prj->pv[2]*(1.0 - abssin));
+      xi = sigma - 1.0;
+
+      eta = prj->w[9] * (prj->w[4] - sigma);
+      if (*thetap < 0) eta = -eta;
+      eta -= prj->y0;
+
+      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
+        if (offset) {
+          /* Offset the southern polar half-facets for even K. */
+          h = (int)floor((*xp + prj->x0) / prj->w[9]) + prj->m;
+          if (h%2) {
+            *yp -= prj->w[9];
+          } else {
+            *yp += prj->w[9];
+          }
+        }
+
+        /* Recall that y[] holds (phi - phi_c). */
+        *xp += *yp * xi;
+        *yp = eta;
+        *(statp++) = 0;
+
+        /* Put the phi = 180 meridian in the expected place. */
+        if (180.0 < *xp) *xp = 360.0 - *xp;
+      }
+    }
+  }
+
+  return 0;
+}
diff --git a/cextern/wcslib/C/prj.h b/cextern/wcslib/C/prj.h
new file mode 100644
index 0000000..403a8c6
--- /dev/null
+++ b/cextern/wcslib/C/prj.h
@@ -0,0 +1,758 @@
+/*============================================================================
+
+  WCSLIB 4.16 - an implementation of the FITS WCS standard.
+  Copyright (C) 1995-2012, Mark Calabretta
+
+  This file is part of WCSLIB.
+
+  WCSLIB is free software: you can redistribute it and/or modify it under the
+  terms of the GNU Lesser General Public License as published by the Free
+  Software Foundation, either version 3 of the License, or (at your option)
+  any later version.
+
+  WCSLIB 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 Lesser General Public License for
+  more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with WCSLIB.  If not, see http://www.gnu.org/licenses.
+
+  Direct correspondence concerning WCSLIB to mark at calabretta.id.au
+
+  Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
+  http://www.atnf.csiro.au/people/Mark.Calabretta
+  $Id: prj.h,v 4.16 2012/11/07 04:42:44 cal103 Exp $
+*=============================================================================
+*
+* WCSLIB 4.16 - C routines that implement the spherical map projections
+* recognized by the FITS World Coordinate System (WCS) standard.  Refer to
+*
+*   "Representations of world coordinates in FITS",
+*   Greisen, E.W., & Calabretta, M.R. 2002, A&A, 395, 1061 (Paper I)
+*
+*   "Representations of celestial coordinates in FITS",
+*   Calabretta, M.R., & Greisen, E.W. 2002, A&A, 395, 1077 (Paper II)
+*
+* Refer to the README file provided with WCSLIB for an overview of the
+* library.
+*
+*
+* Summary of the prj routines
+* ---------------------------
+* These routines implement the spherical map projections defined by the FITS
+* WCS standard.  They are based on the prjprm struct which contains all
+* information needed for the computations.  The struct contains some members
+* that must be set by the user, and others that are maintained by these
+* routines, somewhat like a C++ class but with no encapsulation.
+*
+* Routine prjini() is provided to initialize the prjprm struct with default
+* values, prjfree() reclaims any memory that may have been allocated to store
+* an error message, and prjprt() prints its contents.
+*
+* Setup routines for each projection with names of the form ???set(), where
+* "???" is the down-cased three-letter projection code, compute intermediate
+* values in the prjprm struct from parameters in it that were supplied by the
+* user.  The struct always needs to be set by the projection's setup routine
+* but that need not be called explicitly - refer to the explanation of
+* prjprm::flag.
+*
+* Each map projection is implemented via separate functions for the spherical
+* projection, ???s2x(), and deprojection, ???x2s().
+*
+* A set of driver routines, prjset(), prjx2s(), and prjs2x(), provides a
+* generic interface to the specific projection routines which they invoke
+* via pointers-to-functions stored in the prjprm struct.
+*
+* In summary, the routines are:
+*   - prjini()                Initialization routine for the prjprm struct.
+*   - prjprt()                Routine to print the prjprm struct.
+*
+*   - prjset(), prjx2s(), prjs2x():   Generic driver routines
+*
+*   - azpset(), azpx2s(), azps2x():   AZP (zenithal/azimuthal perspective)
+*   - szpset(), szpx2s(), szps2x():   SZP (slant zenithal perspective)
+*   - tanset(), tanx2s(), tans2x():   TAN (gnomonic)
+*   - stgset(), stgx2s(), stgs2x():   STG (stereographic)
+*   - sinset(), sinx2s(), sins2x():   SIN (orthographic/synthesis)
+*   - arcset(), arcx2s(), arcs2x():   ARC (zenithal/azimuthal equidistant)
+*   - zpnset(), zpnx2s(), zpns2x():   ZPN (zenithal/azimuthal polynomial)
+*   - zeaset(), zeax2s(), zeas2x():   ZEA (zenithal/azimuthal equal area)
+*   - airset(), airx2s(), airs2x():   AIR (Airy)
+*   - cypset(), cypx2s(), cyps2x():   CYP (cylindrical perspective)
+*   - ceaset(), ceax2s(), ceas2x():   CEA (cylindrical equal area)
+*   - carset(), carx2s(), cars2x():   CAR (Plate carree)
+*   - merset(), merx2s(), mers2x():   MER (Mercator)
+*   - sflset(), sflx2s(), sfls2x():   SFL (Sanson-Flamsteed)
+*   - parset(), parx2s(), pars2x():   PAR (parabolic)
+*   - molset(), molx2s(), mols2x():   MOL (Mollweide)
+*   - aitset(), aitx2s(), aits2x():   AIT (Hammer-Aitoff)
+*   - copset(), copx2s(), cops2x():   COP (conic perspective)
+*   - coeset(), coex2s(), coes2x():   COE (conic equal area)
+*   - codset(), codx2s(), cods2x():   COD (conic equidistant)
+*   - cooset(), coox2s(), coos2x():   COO (conic orthomorphic)
+*   - bonset(), bonx2s(), bons2x():   BON (Bonne)
+*   - pcoset(), pcox2s(), pcos2x():   PCO (polyconic)
+*   - tscset(), tscx2s(), tscs2x():   TSC (tangential spherical cube)
+*   - cscset(), cscx2s(), cscs2x():   CSC (COBE spherical cube)
+*   - qscset(), qscx2s(), qscs2x():   QSC (quadrilateralized spherical cube)
+*   - hpxset(), hpxx2s(), hpxs2x():   HPX (HEALPix)
+*
+* Argument checking (projection routines):
+* ----------------------------------------
+* The values of phi and theta (the native longitude and latitude) normally lie
+* in the range [-180,180] for phi, and [-90,90] for theta.  However, all
+* projection routines will accept any value of phi and will not normalize it.
+*
+* The projection routines do not explicitly check that theta lies within the
+* range [-90,90].  They do check for any value of theta that produces an
+* invalid argument to the projection equations (e.g. leading to division by
+* zero).  The projection routines for AZP, SZP, TAN, SIN, ZPN, and COP also
+* return error 2 if (phi,theta) corresponds to the overlapped (far) side of
+* the projection but also return the corresponding value of (x,y).  This
+* strict bounds checking may be relaxed at any time by setting prjprm::bounds
+* to 0 (rather than 1); the projections need not be reinitialized.
+*
+* Argument checking (deprojection routines):
+* ------------------------------------------
+* Error checking on the projected coordinates (x,y) is limited to that
+* required to ascertain whether a solution exists.  Where a solution does
+* exist no check is made that the value of phi and theta obtained lie within
+* the ranges [-180,180] for phi, and [-90,90] for theta.
+*
+* Accuracy:
+* ---------
+* No warranty is given for the accuracy of these routines (refer to the
+* copyright notice); intending users must satisfy for themselves their
+* adequacy for the intended purpose.  However, closure to a precision of at
+* least 1E-10 degree of longitude and latitude has been verified for typical
+* projection parameters on the 1 degree graticule of native longitude and
+* latitude (to within 5 degrees of any latitude where the projection may
+* diverge).  Refer to the tprj1.c and tprj2.c test routines that accompany
+* this software.
+*
+*
+* prjini() - Default constructor for the prjprm struct
+* ----------------------------------------------------
+* prjini() sets all members of a prjprm struct to default values.  It should
+* be used to initialize every prjprm struct.
+*
+* Returned:
+*   prj       struct prjprm*
+*                       Projection parameters.
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         1: Null prjprm pointer passed.
+*
+*
+* prjfree() - Destructor for the prjprm struct
+* --------------------------------------------
+* prjfree() frees any memory that may have been allocated to store an error
+* message in the prjprm struct.
+*
+* Given:
+*   prj       struct prjprm*
+*                       Projection parameters.
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         1: Null prjprm pointer passed.
+*
+*
+* prjprt() - Print routine for the prjprm struct
+* ----------------------------------------------
+* prjprt() prints the contents of a prjprm struct using wcsprintf().  Mainly
+* intended for diagnostic purposes.
+*
+* Given:
+*   prj       const struct prjprm*
+*                       Projection parameters.
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         1: Null prjprm pointer passed.
+*
+*
+* prjset() - Generic setup routine for the prjprm struct
+* ------------------------------------------------------
+* prjset() sets up a prjprm struct according to information supplied within
+* it.
+*
+* Note that this routine need not be called directly; it will be invoked by
+* prjx2s() and prjs2x() if prj.flag is anything other than a predefined magic
+* value.
+*
+* The one important distinction between prjset() and the setup routines for
+* the specific projections is that the projection code must be defined in the
+* prjprm struct in order for prjset() to identify the required projection.
+* Once prjset() has initialized the prjprm struct, prjx2s() and prjs2x() use
+* the pointers to the specific projection and deprojection routines contained
+* therein.
+*
+* Given and returned:
+*   prj       struct prjprm*
+*                       Projection parameters.
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         1: Null prjprm pointer passed.
+*                         2: Invalid projection parameters.
+*
+*                       For returns > 1, a detailed error message is set in
+*                       prjprm::err if enabled, see wcserr_enable().
+*
+*
+* prjx2s() - Generic Cartesian-to-spherical deprojection
+* ------------------------------------------------------
+* Deproject Cartesian (x,y) coordinates in the plane of projection to native
+* spherical coordinates (phi,theta).
+*
+* The projection is that specified by prjprm::code.
+*
+* Given and returned:
+*   prj       struct prjprm*
+*                       Projection parameters.
+*
+* Given:
+*   nx,ny     int       Vector lengths.
+*
+*   sxy,spt   int       Vector strides.
+*
+*   x,y       const double[]
+*                       Projected coordinates.
+*
+* Returned:
+*   phi,theta double[]  Longitude and latitude (phi,theta) of the projected
+*                       point in native spherical coordinates [deg].
+*
+*   stat      int[]     Status return value for each vector element:
+*                         0: Success.
+*                         1: Invalid value of (x,y).
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         1: Null prjprm pointer passed.
+*                         2: Invalid projection parameters.
+*                         3: One or more of the (x,y) coordinates were
+*                            invalid, as indicated by the stat vector.
+*
+*                       For returns > 1, a detailed error message is set in
+*                       prjprm::err if enabled, see wcserr_enable().
+*
+*
+* prjs2x() - Generic spherical-to-Cartesian projection
+* ----------------------------------------------------
+* Project native spherical coordinates (phi,theta) to Cartesian (x,y)
+* coordinates in the plane of projection.
+*
+* The projection is that specified by prjprm::code.
+*
+* Given and returned:
+*   prj       struct prjprm*
+*                       Projection parameters.
+*
+* Given:
+*   nphi,
+*   ntheta    int       Vector lengths.
+*
+*   spt,sxy   int       Vector strides.
+*
+*   phi,theta const double[]
+*                       Longitude and latitude (phi,theta) of the projected
+*                       point in native spherical coordinates [deg].
+*
+* Returned:
+*   x,y       double[]  Projected coordinates.
+*
+*   stat      int[]     Status return value for each vector element:
+*                         0: Success.
+*                         1: Invalid value of (phi,theta).
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         1: Null prjprm pointer passed.
+*                         2: Invalid projection parameters.
+*                         4: One or more of the (phi,theta) coordinates
+*                            were, invalid, as indicated by the stat vector.
+*
+*                       For returns > 1, a detailed error message is set in
+*                       prjprm::err if enabled, see wcserr_enable().
+*
+*
+* ???set() - Specific setup routines for the prjprm struct
+* --------------------------------------------------------
+* Set up a prjprm struct for a particular projection according to information
+* supplied within it.
+*
+* Given and returned:
+*   prj       struct prjprm*
+*                       Projection parameters.
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         1: Null prjprm pointer passed.
+*                         2: Invalid projection parameters.
+*
+*                       For returns > 1, a detailed error message is set in
+*                       prjprm::err if enabled, see wcserr_enable().
+*
+*
+* ???x2s() - Specific Cartesian-to-spherical deprojection routines
+* ----------------------------------------------------------------
+* Transform (x,y) coordinates in the plane of projection to native spherical
+* coordinates (phi,theta).
+*
+* Given and returned:
+*   prj       struct prjprm*
+*                       Projection parameters.
+*
+* Given:
+*   nx,ny     int       Vector lengths.
+*
+*   sxy,spt   int       Vector strides.
+*
+*   x,y       const double[]
+*                       Projected coordinates.
+*
+* Returned:
+*   phi,theta double[]  Longitude and latitude of the projected point in
+*                       native spherical coordinates [deg].
+*
+*   stat      int[]     Status return value for each vector element:
+*                         0: Success.
+*                         1: Invalid value of (x,y).
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         1: Null prjprm pointer passed.
+*                         2: Invalid projection parameters.
+*                         3: One or more of the (x,y) coordinates were
+*                            invalid, as indicated by the stat vector.
+*
+*                       For returns > 1, a detailed error message is set in
+*                       prjprm::err if enabled, see wcserr_enable().
+*
+*
+* ???s2x() - Specific spherical-to-Cartesian projection routines
+*---------------------------------------------------------------
+* Transform native spherical coordinates (phi,theta) to (x,y) coordinates in
+* the plane of projection.
+*
+* Given and returned:
+*   prj       struct prjprm*
+*                       Projection parameters.
+*
+* Given:
+*   nphi,
+*   ntheta    int       Vector lengths.
+*
+*   spt,sxy   int       Vector strides.
+*
+*   phi,theta const double[]
+*                       Longitude and latitude of the projected point in
+*                       native spherical coordinates [deg].
+*
+* Returned:
+*   x,y       double[]  Projected coordinates.
+*
+*   stat      int[]     Status return value for each vector element:
+*                         0: Success.
+*                         1: Invalid value of (phi,theta).
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         1: Null prjprm pointer passed.
+*                         2: Invalid projection parameters.
+*                         4: One or more of the (phi,theta) coordinates
+*                            were, invalid, as indicated by the stat vector.
+*
+*                       For returns > 1, a detailed error message is set in
+*                       prjprm::err if enabled, see wcserr_enable().
+*
+*
+* prjprm struct - Projection parameters
+* -------------------------------------
+* The prjprm struct contains all information needed to project or deproject
+* native spherical coordinates.  It consists of certain members that must be
+* set by the user ("given") and others that are set by the WCSLIB routines
+* ("returned").  Some of the latter are supplied for informational purposes
+* while others are for internal use only.
+*
+*   int flag
+*     (Given and returned) This flag must be set to zero whenever any of the
+*     following prjprm struct members are set or changed:
+*
+*       - prjprm::code,
+*       - prjprm::r0,
+*       - prjprm::pv[],
+*       - prjprm::phi0,
+*       - prjprm::theta0.
+*
+*     This signals the initialization routine (prjset() or ???set()) to
+*     recompute the returned members of the prjprm struct.  flag will then be
+*     reset to indicate that this has been done.
+*
+*     Note that flag need not be reset when prjprm::bounds is changed.
+*
+*   char code[4]
+*     (Given) Three-letter projection code defined by the FITS standard.
+*
+*   double r0
+*     (Given) The radius of the generating sphere for the projection, a linear
+*     scaling parameter.  If this is zero, it will be reset to its default
+*     value of 180/pi (the value for FITS WCS).
+*
+*   double pv[30]
+*     (Given) Projection parameters.  These correspond to the PVi_ma keywords
+*     in FITS, so pv[0] is PVi_0a, pv[1] is PVi_1a, etc., where i denotes the
+*     latitude-like axis.  Many projections use pv[1] (PVi_1a), some also use
+*     pv[2] (PVi_2a) and SZP uses pv[3] (PVi_3a).  ZPN is currently the only
+*     projection that uses any of the others.
+*
+*     Usage of the pv[] array as it applies to each projection is described in
+*     the prologue to each trio of projection routines in prj.c.
+*
+*   double phi0
+*     (Given) The native longitude, phi_0 [deg], and ...
+*   double theta0
+*     (Given) ... the native latitude, theta_0 [deg], of the reference point,
+*     i.e. the point (x,y) = (0,0).  If undefined (set to a magic value by
+*     prjini()) the initialization routine will set this to a
+*     projection-specific default.
+*
+*   int bounds
+*     (Given) Controls strict bounds checking for the AZP, SZP, TAN, SIN, ZPN,
+*     and COP projections; set to zero to disable checking.
+*
+* The remaining members of the prjprm struct are maintained by the setup
+* routines and must not be modified elsewhere:
+*
+*   char name[40]
+*     (Returned) Long name of the projection.
+*
+*     Provided for information only, not used by the projection routines.
+*
+*   int  category
+*     (Returned) Projection category matching the value of the relevant global
+*     variable:
+*
+*     - ZENITHAL,
+*     - CYLINDRICAL,
+*     - PSEUDOCYLINDRICAL,
+*     - CONVENTIONAL,
+*     - CONIC,
+*     - POLYCONIC,
+*     - QUADCUBE, and
+*     - HEALPIX.
+*
+*     The category name may be identified via the prj_categories character
+*     array, e.g.
+*
+=       struct prjprm prj;
+=         ...
+=       printf("%s\n", prj_categories[prj.category]);
+*
+*     Provided for information only, not used by the projection routines.
+*
+*   int  pvrange
+*     (Returned) Range of projection parameter indices: 100 times the first
+*     allowed index plus the number of parameters, e.g. TAN is 0 (no
+*     parameters), SZP is 103 (1 to 3), and ZPN is 30 (0 to 29).
+*
+*     Provided for information only, not used by the projection routines.
+*
+*   int  simplezen
+*     (Returned) True if the projection is a radially-symmetric zenithal
+*     projection.
+*
+*     Provided for information only, not used by the projection routines.
+*
+*   int  equiareal
+*     (Returned) True if the projection is equal area.
+*
+*     Provided for information only, not used by the projection routines.
+*
+*   int  conformal
+*     (Returned) True if the projection is conformal.
+*
+*     Provided for information only, not used by the projection routines.
+*
+*   int  global
+*     (Returned) True if the projection can represent the whole sphere in a
+*     finite, non-overlapped mapping.
+*
+*     Provided for information only, not used by the projection routines.
+*
+*   int  divergent
+*     (Returned) True if the projection diverges in latitude.
+*
+*     Provided for information only, not used by the projection routines.
+*
+*   double x0
+*     (Returned) The offset in x, and ...
+*   double y0
+*     (Returned) ... the offset in y used to force (x,y) = (0,0) at
+*     (phi_0,theta_0).
+*
+*   struct wcserr *err
+*     (Returned) If enabled, when an error status is returned this struct
+*     contains detailed information about the error, see wcserr_enable().
+*
+*   void *padding
+*     (An unused variable inserted for alignment purposes only.)
+*
+*   double w[10]
+*     (Returned) Intermediate floating-point values derived from the
+*     projection parameters, cached here to save recomputation.
+*
+*     Usage of the w[] array as it applies to each projection is described in
+*     the prologue to each trio of projection routines in prj.c.
+*
+*   int n
+*     (Returned) Intermediate integer value (used only for the ZPN and HPX
+*     projections).
+*
+*   int (*prjx2s)(PRJX2S_ARGS)
+*     (Returned) Pointer to the projection ...
+*   int (*prjs2x)(PRJ_ARGS)
+*     (Returned) ... and deprojection routines.
+*
+*
+* Global variable: const char *prj_errmsg[] - Status return messages
+* ------------------------------------------------------------------
+* Error messages to match the status value returned from each function.
+*
+*===========================================================================*/
+
+#ifndef WCSLIB_PROJ
+#define WCSLIB_PROJ
+
+#include "wcserr.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* Total number of projection parameters; 0 to PVN-1. */
+#define PVN 30
+
+extern const char *prj_errmsg[];
+
+enum prj_errmsg_enum {
+  PRJERR_SUCCESS      = 0,	/* Success. */
+  PRJERR_NULL_POINTER = 1,	/* Null prjprm pointer passed. */
+  PRJERR_BAD_PARAM    = 2,	/* Invalid projection parameters. */
+  PRJERR_BAD_PIX      = 3,	/* One or more of the (x, y) coordinates were
+				   invalid. */
+  PRJERR_BAD_WORLD    = 4	/* One or more of the (phi, theta) coordinates
+				   were invalid. */
+};
+
+extern const int CONIC, CONVENTIONAL, CYLINDRICAL, POLYCONIC,
+                 PSEUDOCYLINDRICAL, QUADCUBE, ZENITHAL, HEALPIX;
+extern const char prj_categories[9][32];
+
+extern const int  prj_ncode;
+extern const char prj_codes[27][4];
+
+#ifdef PRJX2S_ARGS
+#undef PRJX2S_ARGS
+#endif
+
+#ifdef PRJS2X_ARGS
+#undef PRJS2X_ARGS
+#endif
+
+/* For use in declaring deprojection function prototypes. */
+#define PRJX2S_ARGS struct prjprm *prj, int nx, int ny, int sxy, int spt, \
+const double x[], const double y[], double phi[], double theta[], int stat[]
+
+/* For use in declaring projection function prototypes. */
+#define PRJS2X_ARGS struct prjprm *prj, int nx, int ny, int sxy, int spt, \
+const double phi[], const double theta[], double x[], double y[], int stat[]
+
+
+struct prjprm {
+  /* Initialization flag (see the prologue above).                          */
+  /*------------------------------------------------------------------------*/
+  int    flag;			/* Set to zero to force initialization.     */
+
+  /* Parameters to be provided (see the prologue above).                    */
+  /*------------------------------------------------------------------------*/
+  char   code[4];		/* Three-letter projection code.            */
+  double r0;			/* Radius of the generating sphere.         */
+  double pv[PVN];		/* Projection parameters.                   */
+  double phi0, theta0;		/* Fiducial native coordinates.             */
+  int    bounds;		/* Enable strict bounds checking.           */
+
+  /* Information derived from the parameters supplied.                      */
+  /*------------------------------------------------------------------------*/
+  char   name[40];		/* Projection name.                         */
+  int    category;		/* Projection category.                     */
+  int    pvrange;		/* Range of projection parameter indices.   */
+  int    simplezen;		/* Is it a simple zenithal projection?      */
+  int    equiareal;		/* Is it an equal area projection?          */
+  int    conformal;		/* Is it a conformal projection?            */
+  int    global;		/* Can it map the whole sphere?             */
+  int    divergent;		/* Does the projection diverge in latitude? */
+  double x0, y0;		/* Fiducial offsets.                        */
+
+  /* Error handling                                                         */
+  /*------------------------------------------------------------------------*/
+  struct wcserr *err;
+
+  /* Private                                                                */
+  /*------------------------------------------------------------------------*/
+  void   *padding;		/* (Dummy inserted for alignment purposes.) */
+  double w[10];			/* Intermediate values.                     */
+  int    m, n;			/* Intermediate values.                     */
+
+  int (*prjx2s)(PRJX2S_ARGS);	/* Pointers to the spherical projection and */
+  int (*prjs2x)(PRJS2X_ARGS);	/* deprojection functions.                  */
+};
+
+/* Size of the prjprm struct in int units, used by the Fortran wrappers. */
+#define PRJLEN (sizeof(struct prjprm)/sizeof(int))
+
+
+/* Use the preprocessor to help declare function prototypes (see above). */
+int prjini(struct prjprm *prj);
+int prjfree(struct prjprm *prj);
+int prjprt(const struct prjprm *prj);
+
+int prjset(struct prjprm *prj);
+int prjx2s(PRJX2S_ARGS);
+int prjs2x(PRJS2X_ARGS);
+
+int azpset(struct prjprm *prj);
+int azpx2s(PRJX2S_ARGS);
+int azps2x(PRJS2X_ARGS);
+
+int szpset(struct prjprm *prj);
+int szpx2s(PRJX2S_ARGS);
+int szps2x(PRJS2X_ARGS);
+
+int tanset(struct prjprm *prj);
+int tanx2s(PRJX2S_ARGS);
+int tans2x(PRJS2X_ARGS);
+
+int stgset(struct prjprm *prj);
+int stgx2s(PRJX2S_ARGS);
+int stgs2x(PRJS2X_ARGS);
+
+int sinset(struct prjprm *prj);
+int sinx2s(PRJX2S_ARGS);
+int sins2x(PRJS2X_ARGS);
+
+int arcset(struct prjprm *prj);
+int arcx2s(PRJX2S_ARGS);
+int arcs2x(PRJS2X_ARGS);
+
+int zpnset(struct prjprm *prj);
+int zpnx2s(PRJX2S_ARGS);
+int zpns2x(PRJS2X_ARGS);
+
+int zeaset(struct prjprm *prj);
+int zeax2s(PRJX2S_ARGS);
+int zeas2x(PRJS2X_ARGS);
+
+int airset(struct prjprm *prj);
+int airx2s(PRJX2S_ARGS);
+int airs2x(PRJS2X_ARGS);
+
+int cypset(struct prjprm *prj);
+int cypx2s(PRJX2S_ARGS);
+int cyps2x(PRJS2X_ARGS);
+
+int ceaset(struct prjprm *prj);
+int ceax2s(PRJX2S_ARGS);
+int ceas2x(PRJS2X_ARGS);
+
+int carset(struct prjprm *prj);
+int carx2s(PRJX2S_ARGS);
+int cars2x(PRJS2X_ARGS);
+
+int merset(struct prjprm *prj);
+int merx2s(PRJX2S_ARGS);
+int mers2x(PRJS2X_ARGS);
+
+int sflset(struct prjprm *prj);
+int sflx2s(PRJX2S_ARGS);
+int sfls2x(PRJS2X_ARGS);
+
+int parset(struct prjprm *prj);
+int parx2s(PRJX2S_ARGS);
+int pars2x(PRJS2X_ARGS);
+
+int molset(struct prjprm *prj);
+int molx2s(PRJX2S_ARGS);
+int mols2x(PRJS2X_ARGS);
+
+int aitset(struct prjprm *prj);
+int aitx2s(PRJX2S_ARGS);
+int aits2x(PRJS2X_ARGS);
+
+int copset(struct prjprm *prj);
+int copx2s(PRJX2S_ARGS);
+int cops2x(PRJS2X_ARGS);
+
+int coeset(struct prjprm *prj);
+int coex2s(PRJX2S_ARGS);
+int coes2x(PRJS2X_ARGS);
+
+int codset(struct prjprm *prj);
+int codx2s(PRJX2S_ARGS);
+int cods2x(PRJS2X_ARGS);
+
+int cooset(struct prjprm *prj);
+int coox2s(PRJX2S_ARGS);
+int coos2x(PRJS2X_ARGS);
+
+int bonset(struct prjprm *prj);
+int bonx2s(PRJX2S_ARGS);
+int bons2x(PRJS2X_ARGS);
+
+int pcoset(struct prjprm *prj);
+int pcox2s(PRJX2S_ARGS);
+int pcos2x(PRJS2X_ARGS);
+
+int tscset(struct prjprm *prj);
+int tscx2s(PRJX2S_ARGS);
+int tscs2x(PRJS2X_ARGS);
+
+int cscset(struct prjprm *prj);
+int cscx2s(PRJX2S_ARGS);
+int cscs2x(PRJS2X_ARGS);
+
+int qscset(struct prjprm *prj);
+int qscx2s(PRJX2S_ARGS);
+int qscs2x(PRJS2X_ARGS);
+
+int hpxset(struct prjprm *prj);
+int hpxx2s(PRJX2S_ARGS);
+int hpxs2x(PRJS2X_ARGS);
+
+
+/* Deprecated. */
+#define prjini_errmsg prj_errmsg
+#define prjprt_errmsg prj_errmsg
+#define prjset_errmsg prj_errmsg
+#define prjx2s_errmsg prj_errmsg
+#define prjs2x_errmsg prj_errmsg
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* WCSLIB_PROJ */
diff --git a/cextern/wcslib/C/spc.c b/cextern/wcslib/C/spc.c
new file mode 100644
index 0000000..ef559dc
--- /dev/null
+++ b/cextern/wcslib/C/spc.c
@@ -0,0 +1,1388 @@
+/*============================================================================
+
+  WCSLIB 4.16 - an implementation of the FITS WCS standard.
+  Copyright (C) 1995-2012, Mark Calabretta
+
+  This file is part of WCSLIB.
+
+  WCSLIB is free software: you can redistribute it and/or modify it under the
+  terms of the GNU Lesser General Public License as published by the Free
+  Software Foundation, either version 3 of the License, or (at your option)
+  any later version.
+
+  WCSLIB 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 Lesser General Public License for
+  more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with WCSLIB.  If not, see http://www.gnu.org/licenses.
+
+  Direct correspondence concerning WCSLIB to mark at calabretta.id.au
+
+  Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
+  http://www.atnf.csiro.au/people/Mark.Calabretta
+  $Id: spc.c,v 4.16 2012/11/07 04:42:44 cal103 Exp $
+*===========================================================================*/
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "wcserr.h"
+#include "wcsmath.h"
+#include "wcsprintf.h"
+#include "wcstrig.h"
+#include "wcsutil.h"
+#include "spc.h"
+#include "spx.h"
+
+/* Spectral algorithm codes. */
+#define F2S 100;		/* Axis linear in frequency.          */
+#define W2S 200;		/* Axis linear in vacuum wavelengths. */
+#define A2S 300;		/* Axis linear in air wavelengths.    */
+#define V2S 400;		/* Axis linear in velocity.           */
+#define GRI 500;		/* Grism in vacuum.                   */
+#define GRA 600;		/* Grism in air.                      */
+
+/* S-type spectral variables. */
+#define FREQ  0;		/* Frequency-like.                    */
+#define AFRQ  1;		/* Frequency-like.                    */
+#define ENER  2;		/* Frequency-like.                    */
+#define WAVN  3;		/* Frequency-like.                    */
+#define VRAD  4;		/* Frequency-like.                    */
+#define WAVE 10;		/* Vacuum wavelength-like.            */
+#define VOPT 11;		/* Vacuum wavelength-like.            */
+#define ZOPT 12;		/* Vacuum wavelength-like.            */
+#define AWAV 20;		/* Air wavelength-like.               */
+#define VELO 30;		/* Velocity-like.                     */
+#define BETA 31;		/* Velocity-like.                     */
+
+
+/* Map status return value to message. */
+const char *spc_errmsg[] = {
+  "Success",
+  "Null spcprm pointer passed",
+  "Invalid spectral parameters",
+  "One or more of x coordinates were invalid",
+  "One or more of the spec coordinates were invalid"};
+
+/* Convenience macro for invoking wcserr_set(). */
+#define SPC_ERRMSG(status) WCSERR_SET(status), spc_errmsg[status]
+
+
+#define C 2.99792458e8
+
+/*--------------------------------------------------------------------------*/
+
+int spcini(struct spcprm *spc)
+
+{
+  register int k;
+
+  if (spc == 0x0) return SPCERR_NULL_POINTER;
+
+  spc->flag = 0;
+
+  memset(spc->type, 0, 8);
+  strcpy(spc->type, "    ");
+  strcpy(spc->code, "   ");
+
+  spc->crval = UNDEFINED;
+  spc->restfrq =  0.0;
+  spc->restwav =  0.0;
+
+  for (k = 0; k < 7; k++) {
+    spc->pv[k] = UNDEFINED;
+  }
+
+  for (k = 0; k < 6; k++) {
+    spc->w[k] = 0.0;
+  }
+
+  spc->isGrism  = 0;
+  spc->padding1 = 0;
+
+  spc->err = 0x0;
+
+  spc->padding2 = 0x0;
+  spc->spxX2P = 0x0;
+  spc->spxP2S = 0x0;
+  spc->spxS2P = 0x0;
+  spc->spxP2X = 0x0;
+
+  return SPCERR_SUCCESS;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int spcfree(struct spcprm *spc)
+
+{
+  if (spc == 0x0) return SPCERR_NULL_POINTER;
+
+  if (spc->err) {
+    free(spc->err);
+    spc->err = 0x0;
+  }
+
+  return SPCERR_SUCCESS;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int spcprt(const struct spcprm *spc)
+
+{
+  char hext[32];
+  int  i;
+
+  if (spc == 0x0) return SPCERR_NULL_POINTER;
+
+  wcsprintf("       flag: %d\n", spc->flag);
+  wcsprintf("       type: \"%s\"\n", spc->type);
+  wcsprintf("       code: \"%s\"\n", spc->code);
+  if (undefined(spc->crval)) {
+    wcsprintf("      crval: UNDEFINED\n");
+  } else {
+    wcsprintf("      crval: %- 11.4g\n", spc->crval);
+  }
+  wcsprintf("    restfrq: %f\n", spc->restfrq);
+  wcsprintf("    restwav: %f\n", spc->restwav);
+
+  wcsprintf("         pv:");
+  if (spc->isGrism) {
+    for (i = 0; i < 5; i++) {
+      if (undefined(spc->pv[i])) {
+        wcsprintf("  UNDEFINED   ");
+      } else {
+        wcsprintf("  %- 11.4g", spc->pv[i]);
+      }
+    }
+    wcsprintf("\n            ");
+    for (i = 5; i < 7; i++) {
+      if (undefined(spc->pv[i])) {
+        wcsprintf("  UNDEFINED   ");
+      } else {
+        wcsprintf("  %- 11.4g", spc->pv[i]);
+      }
+    }
+    wcsprintf("\n");
+
+  } else {
+    wcsprintf(" (not used)\n");
+  }
+
+  wcsprintf("          w:");
+  for (i = 0; i < 3; i++) {
+    wcsprintf("  %- 11.4g", spc->w[i]);
+  }
+  if (spc->isGrism) {
+    wcsprintf("\n            ");
+    for (i = 3; i < 6; i++) {
+      wcsprintf("  %- 11.4g", spc->w[i]);
+    }
+    wcsprintf("\n");
+  } else {
+    wcsprintf("  (remainder unused)\n");
+  }
+
+  wcsprintf("    isGrism: %d\n", spc->isGrism);
+
+  WCSPRINTF_PTR("        err: ", spc->err, "\n");
+  if (spc->err) {
+    wcserr_prt(spc->err, "             ");
+  }
+
+  wcsprintf("     spxX2P: %s\n",
+    wcsutil_fptr2str((int (*)(void))spc->spxX2P, hext));
+  wcsprintf("     spxP2S: %s\n",
+    wcsutil_fptr2str((int (*)(void))spc->spxP2S, hext));
+  wcsprintf("     spxS2P: %s\n",
+    wcsutil_fptr2str((int (*)(void))spc->spxS2P, hext));
+  wcsprintf("     spxP2X: %s\n",
+    wcsutil_fptr2str((int (*)(void))spc->spxP2X, hext));
+
+  return SPCERR_SUCCESS;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int spcset(struct spcprm *spc)
+
+{
+  static const char *function = "spcset";
+
+  char   ctype[9], ptype, xtype;
+  int    restreq, status;
+  double alpha, beta_r, crvalX, dn_r, dXdS, epsilon, G, m, lambda_r, n_r,
+         t, restfrq, restwav, theta;
+  struct wcserr **err;
+
+  if (spc == 0x0) return SPCERR_NULL_POINTER;
+  err = &(spc->err);
+
+  if (undefined(spc->crval)) {
+    return wcserr_set(WCSERR_SET(SPCERR_BAD_SPEC_PARAMS),
+      "Spectral crval is undefined");
+  }
+
+  memset((spc->type)+4, 0, 4);
+  spc->code[3] = '\0';
+  wcsutil_blank_fill(4, spc->type);
+  wcsutil_blank_fill(3, spc->code);
+  spc->w[0] = 0.0;
+
+
+  /* Analyse the spectral axis type. */
+  memset(ctype, 0, 9);
+  strncpy(ctype, spc->type, 4);
+  if (*(spc->code) != ' ') {
+    sprintf(ctype+4, "-%s", spc->code);
+  }
+  restfrq = spc->restfrq;
+  restwav = spc->restwav;
+  if ((status = spcspxe(ctype, spc->crval, restfrq, restwav, &ptype, &xtype,
+                        &restreq, &crvalX, &dXdS, &(spc->err)))) {
+    return status;
+  }
+
+  /* Satisfy rest frequency/wavelength requirements. */
+  if (restreq) {
+    if (restreq == 3 && restfrq == 0.0 && restwav == 0.0) {
+      /* VRAD-V2F, VOPT-V2W, and ZOPT-V2W require the rest frequency or */
+      /* wavelength for the S-P and P-X transformations but not for S-X */
+      /* so supply a phoney value. */
+      restwav = 1.0;
+    }
+
+    if (restfrq == 0.0) {
+      restfrq = C/restwav;
+    } else {
+      restwav = C/restfrq;
+    }
+
+    if (ptype == 'F') {
+      spc->w[0] = restfrq;
+    } else if (ptype != 'V') {
+      spc->w[0] = restwav;
+    } else {
+      if (xtype == 'F') {
+        spc->w[0] = restfrq;
+      } else {
+        spc->w[0] = restwav;
+      }
+    }
+  }
+
+  spc->w[1] = crvalX;
+  spc->w[2] = dXdS;
+
+
+  /* Set pointers-to-functions for the linear part of the transformation. */
+  if (ptype == 'F') {
+    if (strcmp(spc->type, "FREQ") == 0) {
+      /* Frequency. */
+      spc->flag = FREQ;
+      spc->spxP2S = 0x0;
+      spc->spxS2P = 0x0;
+
+    } else if (strcmp(spc->type, "AFRQ") == 0) {
+      /* Angular frequency. */
+      spc->flag = AFRQ;
+      spc->spxP2S = freqafrq;
+      spc->spxS2P = afrqfreq;
+
+    } else if (strcmp(spc->type, "ENER") == 0) {
+      /* Photon energy. */
+      spc->flag = ENER;
+      spc->spxP2S = freqener;
+      spc->spxS2P = enerfreq;
+
+    } else if (strcmp(spc->type, "WAVN") == 0) {
+      /* Wave number. */
+      spc->flag = WAVN;
+      spc->spxP2S = freqwavn;
+      spc->spxS2P = wavnfreq;
+
+    } else if (strcmp(spc->type, "VRAD") == 0) {
+      /* Radio velocity. */
+      spc->flag = VRAD;
+      spc->spxP2S = freqvrad;
+      spc->spxS2P = vradfreq;
+    }
+
+  } else if (ptype == 'W') {
+    if (strcmp(spc->type, "WAVE") == 0) {
+      /* Vacuum wavelengths. */
+      spc->flag = WAVE;
+      spc->spxP2S = 0x0;
+      spc->spxS2P = 0x0;
+
+    } else if (strcmp(spc->type, "VOPT") == 0) {
+      /* Optical velocity. */
+      spc->flag = VOPT;
+      spc->spxP2S = wavevopt;
+      spc->spxS2P = voptwave;
+
+    } else if (strcmp(spc->type, "ZOPT") == 0) {
+      /* Redshift. */
+      spc->flag = ZOPT;
+      spc->spxP2S = wavezopt;
+      spc->spxS2P = zoptwave;
+    }
+
+  } else if (ptype == 'A') {
+    if (strcmp(spc->type, "AWAV") == 0) {
+      /* Air wavelengths. */
+      spc->flag = AWAV;
+      spc->spxP2S = 0x0;
+      spc->spxS2P = 0x0;
+    }
+
+  } else if (ptype == 'V') {
+    if (strcmp(spc->type, "VELO") == 0) {
+      /* Relativistic velocity. */
+      spc->flag = VELO;
+      spc->spxP2S = 0x0;
+      spc->spxS2P = 0x0;
+
+    } else if (strcmp(spc->type, "BETA") == 0) {
+      /* Velocity ratio (v/c). */
+      spc->flag = BETA;
+      spc->spxP2S = velobeta;
+      spc->spxS2P = betavelo;
+    }
+  }
+
+
+  /* Set pointers-to-functions for the non-linear part of the spectral */
+  /* transformation.                                                   */
+  spc->isGrism = 0;
+  if (xtype == 'F') {
+    /* Axis is linear in frequency. */
+    if (ptype == 'F') {
+      spc->spxX2P = 0x0;
+      spc->spxP2X = 0x0;
+
+    } else if (ptype == 'W') {
+      spc->spxX2P = freqwave;
+      spc->spxP2X = wavefreq;
+
+    } else if (ptype == 'A') {
+      spc->spxX2P = freqawav;
+      spc->spxP2X = awavfreq;
+
+    } else if (ptype == 'V') {
+      spc->spxX2P = freqvelo;
+      spc->spxP2X = velofreq;
+    }
+
+    spc->flag += F2S;
+
+  } else if (xtype == 'W' || xtype == 'w') {
+    /* Axis is linear in vacuum wavelengths. */
+    if (ptype == 'F') {
+      spc->spxX2P = wavefreq;
+      spc->spxP2X = freqwave;
+
+    } else if (ptype == 'W') {
+      spc->spxX2P = 0x0;
+      spc->spxP2X = 0x0;
+
+    } else if (ptype == 'A') {
+      spc->spxX2P = waveawav;
+      spc->spxP2X = awavwave;
+
+    } else if (ptype == 'V') {
+      spc->spxX2P = wavevelo;
+      spc->spxP2X = velowave;
+    }
+
+    if (xtype == 'W') {
+      spc->flag += W2S;
+    } else {
+      /* Grism in vacuum. */
+      spc->isGrism = 1;
+      spc->flag += GRI;
+    }
+
+  } else if (xtype == 'A' || xtype == 'a') {
+    /* Axis is linear in air wavelengths. */
+    if (ptype == 'F') {
+      spc->spxX2P = awavfreq;
+      spc->spxP2X = freqawav;
+
+    } else if (ptype == 'W') {
+      spc->spxX2P = awavwave;
+      spc->spxP2X = waveawav;
+
+    } else if (ptype == 'A') {
+      spc->spxX2P = 0x0;
+      spc->spxP2X = 0x0;
+
+    } else if (ptype == 'V') {
+      spc->spxX2P = awavvelo;
+      spc->spxP2X = veloawav;
+    }
+
+    if (xtype == 'A') {
+      spc->flag += A2S;
+    } else {
+      /* Grism in air. */
+      spc->isGrism = 2;
+      spc->flag += GRA;
+    }
+
+  } else if (xtype == 'V') {
+    /* Axis is linear in relativistic velocity. */
+    if (ptype == 'F') {
+      spc->spxX2P = velofreq;
+      spc->spxP2X = freqvelo;
+
+    } else if (ptype == 'W') {
+      spc->spxX2P = velowave;
+      spc->spxP2X = wavevelo;
+
+    } else if (ptype == 'A') {
+      spc->spxX2P = veloawav;
+      spc->spxP2X = awavvelo;
+
+    } else if (ptype == 'V') {
+      spc->spxX2P = 0x0;
+      spc->spxP2X = 0x0;
+    }
+
+    spc->flag += V2S;
+  }
+
+
+  /* Check for grism axes. */
+  if (spc->isGrism) {
+    /* Axis is linear in "grism parameter"; work in wavelength. */
+    lambda_r = crvalX;
+
+    /* Set defaults. */
+    if (undefined(spc->pv[0])) spc->pv[0] = 0.0;
+    if (undefined(spc->pv[1])) spc->pv[1] = 0.0;
+    if (undefined(spc->pv[2])) spc->pv[2] = 0.0;
+    if (undefined(spc->pv[3])) spc->pv[3] = 1.0;
+    if (undefined(spc->pv[4])) spc->pv[4] = 0.0;
+    if (undefined(spc->pv[5])) spc->pv[5] = 0.0;
+    if (undefined(spc->pv[6])) spc->pv[6] = 0.0;
+
+    /* Compute intermediaries. */
+    G       = spc->pv[0];
+    m       = spc->pv[1];
+    alpha   = spc->pv[2];
+    n_r     = spc->pv[3];
+    dn_r    = spc->pv[4];
+    epsilon = spc->pv[5];
+    theta   = spc->pv[6];
+
+    t = G*m/cosd(epsilon);
+    beta_r = asind(t*lambda_r - n_r*sind(alpha));
+
+    t -= dn_r*sind(alpha);
+
+    spc->w[1] = -tand(theta);
+    spc->w[2] *= t / (cosd(beta_r)*cosd(theta)*cosd(theta));
+    spc->w[3] = beta_r + theta;
+    spc->w[4] = (n_r - dn_r*lambda_r)*sind(alpha);
+    spc->w[5] = 1.0 / t;
+  }
+
+  return SPCERR_SUCCESS;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int spcx2s(
+  struct spcprm *spc,
+  int nx,
+  int sx,
+  int sspec,
+  const double x[],
+  double spec[],
+  int stat[])
+
+{
+  static const char *function = "spcx2s";
+
+  int statP2S, status = SPCERR_SUCCESS, statX2P;
+  double beta;
+  register int ix;
+  register int *statp;
+  register const double *xp;
+  register double *specp;
+  struct wcserr **err;
+
+  /* Initialize. */
+  if (spc == 0x0) return SPCERR_NULL_POINTER;
+  err = &(spc->err);
+
+  if (spc->flag == 0) {
+    if ((status = spcset(spc))) return status;
+  }
+
+  /* Convert intermediate world coordinate x to X. */
+  xp = x;
+  specp = spec;
+  statp = stat;
+  for (ix = 0; ix < nx; ix++, xp += sx, specp += sspec) {
+    *specp = spc->w[1] + (*xp)*spc->w[2];
+    *(statp++) = 0;
+  }
+
+  /* If X is the grism parameter then convert it to wavelength. */
+  if (spc->isGrism) {
+    specp = spec;
+    for (ix = 0; ix < nx; ix++, specp += sspec) {
+      beta = atand(*specp) + spc->w[3];
+      *specp = (sind(beta) + spc->w[4]) * spc->w[5];
+    }
+  }
+
+  /* Apply the non-linear step of the algorithm chain to convert the    */
+  /* X-type spectral variable to P-type intermediate spectral variable. */
+  if (spc->spxX2P) {
+    if ((statX2P = spc->spxX2P(spc->w[0], nx, sspec, sspec, spec, spec,
+                               stat))) {
+      if (statX2P == SPXERR_BAD_INSPEC_COORD) {
+        status = SPCERR_BAD_X;
+      } else if (statX2P == SPXERR_BAD_SPEC_PARAMS) {
+        return wcserr_set(WCSERR_SET(SPCERR_BAD_SPEC_PARAMS),
+          "Invalid spectral parameters: Frequency or wavelength is 0");
+      } else {
+        return wcserr_set(SPC_ERRMSG(statX2P));
+      }
+    }
+  }
+
+  /* Apply the linear step of the algorithm chain to convert P-type  */
+  /* intermediate spectral variable to the required S-type variable. */
+  if (spc->spxP2S) {
+    if ((statP2S = spc->spxP2S(spc->w[0], nx, sspec, sspec, spec, spec,
+                               stat))) {
+      if (statP2S == SPXERR_BAD_INSPEC_COORD) {
+        status = SPCERR_BAD_X;
+      } else if (statP2S == SPXERR_BAD_SPEC_PARAMS) {
+        return wcserr_set(WCSERR_SET(SPCERR_BAD_SPEC_PARAMS),
+          "Invalid spectral parameters: Frequency or wavelength is 0");
+      } else {
+        return wcserr_set(SPC_ERRMSG(statP2S));
+      }
+    }
+  }
+
+  if (status) {
+    wcserr_set(SPC_ERRMSG(status));
+  }
+  return status;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int spcs2x(
+  struct spcprm *spc,
+  int nspec,
+  int sspec,
+  int sx,
+  const double spec[],
+  double x[],
+  int stat[])
+
+{
+  static const char *function = "spcs2x";
+
+  int statP2X, status = SPCERR_SUCCESS, statS2P;
+  double beta, s;
+  register int ispec;
+  register int *statp;
+  register const double *specp;
+  register double *xp;
+  struct wcserr **err;
+
+  /* Initialize. */
+  if (spc == 0x0) return SPCERR_NULL_POINTER;
+  err = &(spc->err);
+
+  if (spc->flag == 0) {
+    if ((status = spcset(spc))) return status;
+  }
+
+  /* Apply the linear step of the algorithm chain to convert the S-type */
+  /* spectral variable to P-type intermediate spectral variable.        */
+  if (spc->spxS2P) {
+    if ((statS2P = spc->spxS2P(spc->w[0], nspec, sspec, sx, spec, x, stat))) {
+      if (statS2P == SPXERR_BAD_INSPEC_COORD) {
+        status = SPCERR_BAD_SPEC;
+      } else if (statS2P == SPXERR_BAD_SPEC_PARAMS) {
+        return wcserr_set(WCSERR_SET(SPCERR_BAD_SPEC_PARAMS),
+          "Invalid spectral parameters: Frequency or wavelength is 0");
+      } else {
+        return wcserr_set(SPC_ERRMSG(statS2P));
+      }
+    }
+
+  } else {
+    /* Just a copy. */
+    xp = x;
+    specp = spec;
+    statp = stat;
+    for (ispec = 0; ispec < nspec; ispec++, specp += sspec, xp += sx) {
+      *xp = *specp;
+      *(statp++) = 0;
+    }
+  }
+
+
+  /* Apply the non-linear step of the algorithm chain to convert P-type */
+  /* intermediate spectral variable to X-type spectral variable. */
+  if (spc->spxP2X) {
+    if ((statP2X = spc->spxP2X(spc->w[0], nspec, sx, sx, x, x, stat))) {
+      if (statP2X == SPCERR_BAD_SPEC) {
+        status = SPCERR_BAD_SPEC;
+      } else if (statP2X == SPXERR_BAD_SPEC_PARAMS) {
+        return wcserr_set(WCSERR_SET(SPCERR_BAD_SPEC_PARAMS),
+          "Invalid spectral parameters: Frequency or wavelength is 0");
+      } else {
+        return wcserr_set(SPC_ERRMSG(statP2X));
+      }
+    }
+  }
+
+  if (spc->isGrism) {
+    /* Convert X-type spectral variable (wavelength) to grism parameter. */
+    xp = x;
+    statp = stat;
+    for (ispec = 0; ispec < nspec; ispec++, xp += sx, statp++) {
+      if (*statp) continue;
+
+      s = *xp/spc->w[5] - spc->w[4];
+      if (fabs(s) <= 1.0) {
+        beta = asind(s);
+        *xp = tand(beta - spc->w[3]);
+      } else {
+        *statp = 1;
+      }
+    }
+  }
+
+
+  /* Convert X-type spectral variable to intermediate world coordinate x. */
+  xp = x;
+  statp = stat;
+  for (ispec = 0; ispec < nspec; ispec++, xp += sx) {
+    if (*(statp++)) continue;
+
+    *xp -= spc->w[1];
+    *xp /= spc->w[2];
+  }
+
+  if (status) {
+    wcserr_set(SPC_ERRMSG(status));
+  }
+  return status;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int spctyp(
+  const char ctypei[9],
+  char stype[],
+  char scode[],
+  char sname[],
+  char units[],
+  char *ptype,
+  char *xtype,
+  int  *restreq)
+
+{
+  return spctype(
+    ctypei, stype, scode, sname, units, ptype, xtype, restreq, NULL);
+}
+
+/* : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :  */
+
+int spctype(
+  const char ctypei[9],
+  char stype[],
+  char scode[],
+  char sname[],
+  char units[],
+  char *ptype,
+  char *xtype,
+  int  *restreq,
+  struct wcserr **err)
+
+{
+  static const char *function = "spctype";
+
+  char ctype[9], ptype_t, sname_t[32], units_t[8], xtype_t;
+  int  restreq_t = 0;
+
+  if (err) *err = 0x0;
+
+  /* Copy with blank padding. */
+  sprintf(ctype, "%-8.8s", ctypei);
+  ctype[8] = '\0';
+
+  /* Validate the S-type spectral variable. */
+  if (strncmp(ctype, "FREQ", 4) == 0) {
+    strcpy(sname_t, "Frequency");
+    strcpy(units_t, "Hz");
+    ptype_t = 'F';
+  } else if (strncmp(ctype, "AFRQ", 4) == 0) {
+    strcpy(sname_t, "Angular frequency");
+    strcpy(units_t, "rad/s");
+    ptype_t = 'F';
+  } else if (strncmp(ctype, "ENER", 4) == 0) {
+    strcpy(sname_t, "Photon energy");
+    strcpy(units_t, "J");
+    ptype_t = 'F';
+  } else if (strncmp(ctype, "WAVN", 4) == 0) {
+    strcpy(sname_t, "Wavenumber");
+    strcpy(units_t, "/m");
+    ptype_t = 'F';
+  } else if (strncmp(ctype, "VRAD", 4) == 0) {
+    strcpy(sname_t, "Radio velocity");
+    strcpy(units_t, "m/s");
+    ptype_t = 'F';
+    restreq_t = 1;
+  } else if (strncmp(ctype, "WAVE", 4) == 0) {
+    strcpy(sname_t, "Vacuum wavelength");
+    strcpy(units_t, "m");
+    ptype_t = 'W';
+  } else if (strncmp(ctype, "VOPT", 4) == 0) {
+    strcpy(sname_t, "Optical velocity");
+    strcpy(units_t, "m/s");
+    ptype_t = 'W';
+    restreq_t = 1;
+  } else if (strncmp(ctype, "ZOPT", 4) == 0) {
+    strcpy(sname_t, "Redshift");
+    strcpy(units_t, "");
+    ptype_t = 'W';
+    restreq_t = 1;
+  } else if (strncmp(ctype, "AWAV", 4) == 0) {
+    strcpy(sname_t, "Air wavelength");
+    strcpy(units_t, "m");
+    ptype_t = 'A';
+  } else if (strncmp(ctype, "VELO", 4) == 0) {
+    strcpy(sname_t, "Relativistic velocity");
+    strcpy(units_t, "m/s");
+    ptype_t = 'V';
+  } else if (strncmp(ctype, "BETA", 4) == 0) {
+    strcpy(sname_t, "Velocity ratio (v/c)");
+    strcpy(units_t, "");
+    ptype_t = 'V';
+  } else {
+    return wcserr_set(WCSERR_SET(SPCERR_BAD_SPEC_PARAMS),
+      "Unknown spectral type '%s'", ctype);
+  }
+
+
+  /* Determine X-type and validate the spectral algorithm code. */
+  if ((xtype_t = ctype[5]) == ' ') {
+    /* The algorithm code must be completely blank. */
+    if (strcmp(ctype+4, "    ") != 0) {
+      return wcserr_set(WCSERR_SET(SPCERR_BAD_SPEC_PARAMS),
+        "Invalid spectral algorithm '%s'", ctype+4);
+    }
+
+    xtype_t = ptype_t;
+
+  } else if (ctype[4] != '-') {
+    return wcserr_set(WCSERR_SET(SPCERR_BAD_SPEC_PARAMS),
+      "Invalid spectral type '%s'", ctype);
+
+  } else if (strcmp(ctype+5, "LOG") == 0 || strcmp(ctype+5, "TAB") == 0) {
+    /* Logarithmic or tabular axis, not linear in any spectral type. */
+
+  } else if (xtype_t == 'G') {
+    /* Validate the algorithm code. */
+    if (ctype[6] != 'R') {
+      return wcserr_set(WCSERR_SET(SPCERR_BAD_SPEC_PARAMS),
+        "Invalid spectral algorithm '%s'", xtype_t);
+    }
+
+    /* Grism coordinates... */
+    if (ctype[7] == 'I') {
+      /* ...in vacuum. */
+      xtype_t = 'w';
+    } else if (ctype[7] == 'A') {
+      /* ...in air. */
+      xtype_t = 'a';
+    } else {
+      return wcserr_set(WCSERR_SET(SPCERR_BAD_SPEC_PARAMS),
+        "Invalid spectral algorithm '%s'", xtype_t);
+    }
+
+  } else if (ctype[6] != '2') {
+    /* Algorithm code has invalid syntax. */
+    return wcserr_set(WCSERR_SET(SPCERR_BAD_SPEC_PARAMS),
+      "Invalid spectral algorithm syntax '%s'", xtype_t);
+  } else if (ctype[7] != ptype_t && ctype[7] != '?') {
+    /* The P-, and S-type variables are inconsistent. */
+    return wcserr_set(WCSERR_SET(SPCERR_BAD_SPEC_PARAMS),
+      "In spectral type '%s', P- and S-type variables are inconsistent",
+      ctype);
+
+  } else if (ctype[7] == ctype[5]) {
+    /* Degenerate algorithm code. */
+    sprintf(ctype+4, "    ");
+  }
+
+
+  /* Rest freq/wavelength required for transformation between P and X? */
+  if (strchr("FWAwa", (int)xtype_t)) {
+    if (ptype_t == 'V') {
+      restreq_t += 2;
+    }
+  } else if (xtype_t == 'V') {
+    if (strchr("FWAwa", (int)ptype_t)) {
+      restreq_t += 2;
+    }
+  } else if (strchr("LT", (int)xtype_t) == 0) {
+    /* Invalid X-type variable code. */
+    return wcserr_set(WCSERR_SET(SPCERR_BAD_SPEC_PARAMS),
+      "In spectral type '%s', invalid X-type variable code", ctype);
+  }
+
+
+  /* Copy results. */
+  if (stype) {
+    strncpy(stype, ctype, 4);
+    stype[4] = '\0';
+  }
+  if (scode) strcpy(scode, ctype+5);
+  if (sname) strcpy(sname, sname_t);
+  if (units) strcpy(units, units_t);
+  if (ptype) *ptype = ptype_t;
+  if (xtype) *xtype = xtype_t;
+  if (restreq) *restreq = restreq_t;
+
+
+  return SPCERR_SUCCESS;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int spcspx(
+  const char ctypeS[9],
+  double crvalS,
+  double restfrq,
+  double restwav,
+  char *ptype,
+  char *xtype,
+  int *restreq,
+  double *crvalX,
+  double *dXdS)
+
+{
+  return spcspxe(ctypeS, crvalS, restfrq, restwav, ptype, xtype, restreq,
+                 crvalX, dXdS, 0x0);
+}
+
+/* : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :  */
+
+int spcspxe(
+  const char ctypeS[9],
+  double crvalS,
+  double restfrq,
+  double restwav,
+  char *ptype,
+  char *xtype,
+  int *restreq,
+  double *crvalX,
+  double *dXdS,
+  struct wcserr **err)
+
+{
+  static const char *function = "spcspxe";
+
+  char scode[4], stype[5], type[8];
+  int  status;
+  double dPdS, dXdP;
+  struct spxprm spx;
+
+
+  /* Analyse the spectral axis code. */
+  if ((status = spctype(ctypeS, stype, scode, 0x0, 0x0, ptype, xtype, restreq,
+                        err))) {
+    return status;
+  }
+
+  if (strstr("LT", xtype)) {
+    /* Can't handle logarithmic or tabular coordinates. */
+    return wcserr_set(WCSERR_SET(SPCERR_BAD_SPEC_PARAMS),
+      "Can't handle logarithmic or tabular coordinates");
+  }
+
+  /* Do we have rest frequency and/or wavelength as required? */
+  if ((*restreq)%3 && restfrq == 0.0 && restwav == 0.0) {
+    return wcserr_set(WCSERR_SET(SPCERR_BAD_SPEC_PARAMS),
+      "Missing required rest frequency or wavelength");
+  }
+
+  /* Compute all spectral parameters and their derivatives. */
+  strcpy(type, stype);
+  spx.err = (err ? *err : 0x0);
+  if ((status = specx(type, crvalS, restfrq, restwav, &spx))) {
+    status = SPCERR_BAD_SPEC_PARAMS;
+    if (err) {
+      *err = spx.err;
+      (*err)->status = status;
+    } else {
+      free(spx.err);
+    }
+    return status;
+  }
+
+
+  /* Transform S-P (linear) and P-X (non-linear). */
+  dPdS = 0.0;
+  dXdP = 0.0;
+  if (*ptype == 'F') {
+    if (strcmp(stype, "FREQ") == 0) {
+      dPdS = 1.0;
+    } else if (strcmp(stype, "AFRQ") == 0) {
+      dPdS = spx.dfreqafrq;
+    } else if (strcmp(stype, "ENER") == 0) {
+      dPdS = spx.dfreqener;
+    } else if (strcmp(stype, "WAVN") == 0) {
+      dPdS = spx.dfreqwavn;
+    } else if (strcmp(stype, "VRAD") == 0) {
+      dPdS = spx.dfreqvrad;
+    }
+
+    if (*xtype == 'F') {
+      *crvalX = spx.freq;
+      dXdP = 1.0;
+    } else if (*xtype == 'W' || *xtype == 'w') {
+      *crvalX = spx.wave;
+      dXdP = spx.dwavefreq;
+    } else if (*xtype == 'A' || *xtype == 'a') {
+      *crvalX = spx.awav;
+      dXdP = spx.dawavfreq;
+    } else if (*xtype == 'V') {
+      *crvalX = spx.velo;
+      dXdP = spx.dvelofreq;
+    }
+
+  } else if (*ptype == 'W' || *ptype == 'w') {
+    if (strcmp(stype, "WAVE") == 0) {
+      dPdS = 1.0;
+    } else if (strcmp(stype, "VOPT") == 0) {
+      dPdS = spx.dwavevopt;
+    } else if (strcmp(stype, "ZOPT") == 0) {
+      dPdS = spx.dwavezopt;
+    }
+
+    if (*xtype == 'F') {
+      *crvalX = spx.freq;
+      dXdP = spx.dfreqwave;
+    } else if (*xtype == 'W' || *xtype == 'w') {
+      *crvalX = spx.wave;
+      dXdP = 1.0;
+    } else if (*xtype == 'A' || *xtype == 'a') {
+      *crvalX = spx.awav;
+      dXdP = spx.dawavwave;
+    } else if (*xtype == 'V') {
+      *crvalX = spx.velo;
+      dXdP = spx.dvelowave;
+    }
+
+  } else if (*ptype == 'A' || *ptype == 'a') {
+    if (strcmp(stype, "AWAV") == 0) {
+      dPdS = 1.0;
+    }
+
+    if (*xtype == 'F') {
+      *crvalX = spx.freq;
+      dXdP = spx.dfreqawav;
+    } else if (*xtype == 'W' || *xtype == 'w') {
+      *crvalX = spx.wave;
+      dXdP = spx.dwaveawav;
+    } else if (*xtype == 'A' || *xtype == 'a') {
+      *crvalX = spx.awav;
+      dXdP = 1.0;
+    } else if (*xtype == 'V') {
+      *crvalX = spx.velo;
+      dXdP = spx.dveloawav;
+    }
+
+  } else if (*ptype == 'V') {
+    if (strcmp(stype, "VELO") == 0) {
+      dPdS = 1.0;
+    } else if (strcmp(stype, "BETA") == 0) {
+      dPdS = spx.dvelobeta;
+    }
+
+    if (*xtype == 'F') {
+      *crvalX = spx.freq;
+      dXdP = spx.dfreqvelo;
+    } else if (*xtype == 'W' || *xtype == 'w') {
+      *crvalX = spx.wave;
+      dXdP = spx.dwavevelo;
+    } else if (*xtype == 'A' || *xtype == 'a') {
+      *crvalX = spx.awav;
+      dXdP = spx.dawavvelo;
+    } else if (*xtype == 'V') {
+      *crvalX = spx.velo;
+      dXdP = 1.0;
+    }
+  }
+
+  *dXdS = dXdP * dPdS;
+
+  return SPCERR_SUCCESS;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int spcxps(
+  const char ctypeS[9],
+  double crvalX,
+  double restfrq,
+  double restwav,
+  char *ptype,
+  char *xtype,
+  int *restreq,
+  double *crvalS,
+  double *dSdX)
+
+{
+  return spcxpse(ctypeS, crvalX, restfrq, restwav, ptype, xtype, restreq,
+                 crvalS, dSdX, NULL);
+}
+
+/* : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :  */
+
+int spcxpse(
+  const char ctypeS[9],
+  double crvalX,
+  double restfrq,
+  double restwav,
+  char *ptype,
+  char *xtype,
+  int *restreq,
+  double *crvalS,
+  double *dSdX,
+  struct wcserr **err)
+
+{
+  static const char *function = "spcxpse";
+
+  char scode[4], stype[5], type[8];
+  int  status;
+  double dPdX, dSdP;
+  struct spxprm spx;
+
+  /* Analyse the spectral axis type. */
+  if ((status = spctype(ctypeS, stype, scode, 0x0, 0x0, ptype, xtype, restreq,
+                        err))) {
+    return status;
+  }
+
+  if (strstr("LT", xtype)) {
+    /* Can't handle logarithmic or tabular coordinates. */
+    return wcserr_set(WCSERR_SET(SPCERR_BAD_SPEC_PARAMS),
+      "Can't handle logarithmic or tabular coordinates");
+  }
+
+  /* Do we have rest frequency and/or wavelength as required? */
+  if ((*restreq)%3 && restfrq == 0.0 && restwav == 0.0) {
+    return wcserr_set(WCSERR_SET(SPCERR_BAD_SPEC_PARAMS),
+      "Missing required rest frequency or wavelength");
+  }
+
+  /* Compute all spectral parameters and their derivatives. */
+  if (*xtype == 'F') {
+    strcpy(type, "FREQ");
+  } else if (*xtype == 'W' || *xtype == 'w') {
+    strcpy(type, "WAVE");
+  } else if (*xtype == 'A' || *xtype == 'a') {
+    strcpy(type, "AWAV");
+  } else if (*xtype == 'V') {
+    strcpy(type, "VELO");
+  }
+
+  spx.err = (err ? *err : 0x0);
+  if (specx(type, crvalX, restfrq, restwav, &spx)) {
+    status = SPCERR_BAD_SPEC_PARAMS;
+    if (err) {
+      *err = spx.err;
+      (*err)->status = status;
+    } else {
+      free(spx.err);
+    }
+    return status;
+  }
+
+
+  /* Transform X-P (non-linear) and P-S (linear). */
+  dPdX = 0.0;
+  dSdP = 0.0;
+  if (*ptype == 'F') {
+    if (*xtype == 'F') {
+      dPdX = 1.0;
+    } else if (*xtype == 'W' || *xtype == 'w') {
+      dPdX = spx.dfreqwave;
+    } else if (*xtype == 'A' || *xtype == 'a') {
+      dPdX = spx.dfreqawav;
+    } else if (*xtype == 'V') {
+      dPdX = spx.dfreqvelo;
+    }
+
+    if (strcmp(stype, "FREQ") == 0) {
+      *crvalS = spx.freq;
+      dSdP = 1.0;
+    } else if (strcmp(stype, "AFRQ") == 0) {
+      *crvalS = spx.afrq;
+      dSdP = spx.dafrqfreq;
+    } else if (strcmp(stype, "ENER") == 0) {
+      *crvalS = spx.ener;
+      dSdP = spx.denerfreq;
+    } else if (strcmp(stype, "WAVN") == 0) {
+      *crvalS = spx.wavn;
+      dSdP = spx.dwavnfreq;
+    } else if (strcmp(stype, "VRAD") == 0) {
+      *crvalS = spx.vrad;
+      dSdP = spx.dvradfreq;
+    }
+
+  } else if (*ptype == 'W') {
+    if (*xtype == 'F') {
+      dPdX = spx.dwavefreq;
+    } else if (*xtype == 'W' || *xtype == 'w') {
+      dPdX = 1.0;
+    } else if (*xtype == 'A' || *xtype == 'a') {
+      dPdX = spx.dwaveawav;
+    } else if (*xtype == 'V') {
+      dPdX = spx.dwavevelo;
+    }
+
+    if (strcmp(stype, "WAVE") == 0) {
+      *crvalS = spx.wave;
+      dSdP = 1.0;
+    } else if (strcmp(stype, "VOPT") == 0) {
+      *crvalS = spx.vopt;
+      dSdP = spx.dvoptwave;
+    } else if (strcmp(stype, "ZOPT") == 0) {
+      *crvalS = spx.zopt;
+      dSdP = spx.dzoptwave;
+    }
+
+  } else if (*ptype == 'A') {
+    if (*xtype == 'F') {
+      dPdX = spx.dawavfreq;
+    } else if (*xtype == 'W' || *xtype == 'w') {
+      dPdX = spx.dawavwave;
+    } else if (*xtype == 'A' || *xtype == 'a') {
+      dPdX = 1.0;
+    } else if (*xtype == 'V') {
+      dPdX = spx.dawavvelo;
+    }
+
+    if (strcmp(stype, "AWAV") == 0) {
+      *crvalS = spx.awav;
+      dSdP = 1.0;
+    }
+
+  } else if (*ptype == 'V') {
+    if (*xtype == 'F') {
+      dPdX = spx.dvelofreq;
+    } else if (*xtype == 'W' || *xtype == 'w') {
+      dPdX = spx.dvelowave;
+    } else if (*xtype == 'A' || *xtype == 'a') {
+      dPdX = spx.dveloawav;
+    } else if (*xtype == 'V') {
+      dPdX = 1.0;
+    }
+
+    if (strcmp(stype, "VELO") == 0) {
+      *crvalS = spx.velo;
+      dSdP = 1.0;
+    } else if (strcmp(stype, "BETA") == 0) {
+      *crvalS = spx.beta;
+      dSdP = spx.dbetavelo;
+    }
+  }
+
+  *dSdX = dSdP * dPdX;
+
+  return SPCERR_SUCCESS;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int spctrn(
+  const char ctypeS1[9],
+  double crvalS1,
+  double cdeltS1,
+  double restfrq,
+  double restwav,
+  char   ctypeS2[9],
+  double *crvalS2,
+  double *cdeltS2)
+
+{
+  return spctrne(ctypeS1, crvalS1, cdeltS1, restfrq, restwav,
+                 ctypeS2, crvalS2, cdeltS2, NULL);
+}
+
+/* : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :  */
+
+int spctrne(
+  const char ctypeS1[9],
+  double crvalS1,
+  double cdeltS1,
+  double restfrq,
+  double restwav,
+  char   ctypeS2[9],
+  double *crvalS2,
+  double *cdeltS2,
+  struct wcserr **err)
+
+{
+  static const char *function = "spctrne";
+
+  char *cp, ptype1, ptype2, stype1[5], stype2[5], xtype1, xtype2;
+  int  restreq, status;
+  double crvalX, dS2dX, dXdS1;
+
+  if (restfrq == 0.0 && restwav == 0.0) {
+    /* If translating between two velocity-characteristic types, or between
+       two wave-characteristic types, then we may need to set a dummy rest
+       frequency or wavelength to perform the calculations. */
+    strncpy(stype1, ctypeS1, 4);
+    strncpy(stype2, ctypeS2, 4);
+    stype1[4] = stype2[4] = '\0';
+    if ((strstr("VRAD VOPT ZOPT VELO BETA", stype1) != 0x0) ==
+        (strstr("VRAD VOPT ZOPT VELO BETA", stype2) != 0x0)) {
+      restwav = 1.0;
+    }
+  }
+
+  if ((status = spcspxe(ctypeS1, crvalS1, restfrq, restwav, &ptype1, &xtype1,
+                        &restreq, &crvalX, &dXdS1, err))) {
+    return status;
+  }
+
+  /* Pad with blanks. */
+  ctypeS2[8] = '\0';
+  for (cp = ctypeS2; *cp; cp++);
+  while (cp < ctypeS2+8) *(cp++) = ' ';
+
+  if (strncmp(ctypeS2+5, "???", 3) == 0) {
+    /* Set the algorithm code if required. */
+    if (xtype1 == 'w') {
+      strcpy(ctypeS2+5, "GRI");
+    } else if (xtype1 == 'a') {
+      strcpy(ctypeS2+5, "GRA");
+    } else {
+      ctypeS2[5] = xtype1;
+      ctypeS2[6] = '2';
+    }
+  }
+
+  if ((status = spcxpse(ctypeS2, crvalX, restfrq, restwav, &ptype2, &xtype2,
+                        &restreq, crvalS2, &dS2dX, err))) {
+    return status;
+  }
+
+  /* Are the X-types compatible? */
+  if (xtype2 != xtype1) {
+    return wcserr_set(WCSERR_SET(SPCERR_BAD_SPEC_PARAMS),
+      "Incompatible X-types '%c' and '%c'", xtype1, xtype2);
+  }
+
+  if (ctypeS2[7] == '?') {
+    if (ptype2 == xtype2) {
+      strcpy(ctypeS2+4, "    ");
+    } else {
+      ctypeS2[7] = ptype2;
+    }
+  }
+
+  *cdeltS2 = dS2dX * dXdS1 * cdeltS1;
+
+  return SPCERR_SUCCESS;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int spcaips(
+  const char ctypeA[9],
+  int  velref,
+  char ctype[9],
+  char specsys[9])
+
+{
+  const char *frames[] = {"LSRK", "BARYCENT", "TOPOCENT",
+                          "LSRD", "GEOCENTR", "SOURCE", "GALACTOC"};
+  char *fcode;
+  int  ivf, status;
+
+  /* Make a null-filled copy of ctypeA. */
+  if (ctype != ctypeA) strncpy(ctype, ctypeA, 8);
+  ctype[8] = '\0';
+  wcsutil_null_fill(9, ctype);
+  *specsys = '\0';
+
+  /* Is it a recognized AIPS-convention type? */
+  status = SPCERR_NO_CHANGE;
+  if (strncmp(ctype, "FREQ", 4) == 0 ||
+      strncmp(ctype, "VELO", 4) == 0 ||
+      strncmp(ctype, "FELO", 4) == 0) {
+    /* Look for the Doppler frame. */
+    if (*(fcode = ctype+4)) {
+      if (strcmp(fcode, "-LSR") == 0) {
+        strcpy(specsys, "LSRK");
+      } else if (strcmp(fcode, "-HEL") == 0) {
+        strcpy(specsys, "BARYCENT");
+      } else if (strcmp(fcode, "-OBS") == 0) {
+        strcpy(specsys, "TOPOCENT");
+      } else {
+        /* Not a recognized AIPS spectral type. */
+        return SPCERR_NO_CHANGE;
+      }
+
+      *fcode = '\0';
+      status = SPCERR_SUCCESS;
+    }
+
+    /* VELREF takes precedence if present. */
+    ivf = velref%256;
+    if (0 < ivf && ivf <= 7) {
+      strcpy(specsys, frames[ivf-1]);
+      status = SPCERR_SUCCESS;
+    } else if (ivf) {
+      status = SPCERR_BAD_SPEC_PARAMS;
+    }
+
+    if (strcmp(ctype, "VELO") == 0) {
+      /* Check that we found an AIPS-convention Doppler frame. */
+      if (*specsys) {
+        /* 'VELO' in AIPS means radio or optical depending on VELREF. */
+        ivf = velref/256;
+        if (ivf == 0) {
+          strcpy(ctype, "VOPT");
+        } else if (ivf == 1) {
+          strcpy(ctype, "VRAD");
+        } else {
+          status = SPCERR_BAD_SPEC_PARAMS;
+        }
+      }
+    } else if (strcmp(ctype, "FELO") == 0) {
+      /* Uniform in frequency but expressed as an optical velocity (strictly
+         we should also have found an AIPS-convention Doppler frame). */
+      strcpy(ctype, "VOPT-F2W");
+      if (status < 0) status = SPCERR_SUCCESS;
+    }
+  }
+
+  return status;
+}
diff --git a/cextern/wcslib/C/spc.h b/cextern/wcslib/C/spc.h
new file mode 100644
index 0000000..359f770
--- /dev/null
+++ b/cextern/wcslib/C/spc.h
@@ -0,0 +1,884 @@
+/*============================================================================
+
+  WCSLIB 4.16 - an implementation of the FITS WCS standard.
+  Copyright (C) 1995-2012, Mark Calabretta
+
+  This file is part of WCSLIB.
+
+  WCSLIB is free software: you can redistribute it and/or modify it under the
+  terms of the GNU Lesser General Public License as published by the Free
+  Software Foundation, either version 3 of the License, or (at your option)
+  any later version.
+
+  WCSLIB 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 Lesser General Public License for
+  more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with WCSLIB.  If not, see http://www.gnu.org/licenses.
+
+  Direct correspondence concerning WCSLIB to mark at calabretta.id.au
+
+  Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
+  http://www.atnf.csiro.au/people/Mark.Calabretta
+  $Id: spc.h,v 4.16 2012/11/07 04:42:44 cal103 Exp $
+*=============================================================================
+*
+* WCSLIB 4.16 - C routines that implement the spectral coordinate systems
+* recognized by the FITS World Coordinate System (WCS) standard.  Refer to
+*
+*   "Representations of world coordinates in FITS",
+*   Greisen, E.W., & Calabretta, M.R. 2002, A&A, 395, 1061 (Paper I)
+*
+*   "Representations of spectral coordinates in FITS",
+*   Greisen, E.W., Calabretta, M.R., Valdes, F.G., & Allen, S.L.
+*   2006, A&A, 446, 747 (Paper III)
+*
+* Refer to the README file provided with WCSLIB for an overview of the
+* library.
+*
+*
+* Summary of the spc routines
+* ---------------------------
+* These routines implement the part of the FITS WCS standard that deals with
+* spectral coordinates.  They define methods to be used for computing spectral
+* world coordinates from intermediate world coordinates (a linear
+* transformation of image pixel coordinates), and vice versa.  They are based
+* on the spcprm struct which contains all information needed for the
+* computations.  The struct contains some members that must be set by the
+* user, and others that are maintained by these routines, somewhat like a
+* C++ class but with no encapsulation.
+*
+* Routine spcini() is provided to initialize the spcprm struct with default
+* values, spcfree() reclaims any memory that may have been allocated to store
+* an error message, and spcprt() prints its contents.
+*
+* A setup routine, spcset(), computes intermediate values in the spcprm struct
+* from parameters in it that were supplied by the user.  The struct always
+* needs to be set up by spcset() but it need not be called explicitly - refer
+* to the explanation of spcprm::flag.
+*
+* spcx2s() and spcs2x() implement the WCS spectral coordinate transformations.
+* In fact, they are high level driver routines for the lower level spectral
+* coordinate transformation routines described in spx.h.
+*
+* A number of routines are provided to aid in analysing or synthesising sets
+* of FITS spectral axis keywords:
+*
+*   - spctype() checks a spectral CTYPEia keyword for validity and returns
+*     information derived from it.
+*
+*   - Spectral keyword analysis routine spcspxe() computes the values of the
+*     X-type spectral variables for the S-type variables supplied.
+*
+*   - Spectral keyword synthesis routine, spcxpse(), computes the S-type
+*     variables for the X-types supplied.
+*
+*   - Given a set of spectral keywords, a translation routine, spctrne(),
+*     produces the corresponding set for the specified spectral CTYPEia.
+*
+*   - spcaips() translates AIPS-convention spectral CTYPEia and VELREF
+*     keyvalues.
+*
+* Spectral variable types - S, P, and X:
+* --------------------------------------
+* A few words of explanation are necessary regarding spectral variable types
+* in FITS.
+*
+* Every FITS spectral axis has three associated spectral variables:
+*
+*   S-type: the spectral variable in which coordinates are to be
+*     expressed.  Each S-type is encoded as four characters and is
+*     linearly related to one of four basic types as follows:
+*
+*     F: frequency
+*       'FREQ':  frequency
+*       'AFRQ':  angular frequency
+*       'ENER':  photon energy
+*       'WAVN':  wave number
+*       'VRAD':  radio velocity
+*
+*     W: wavelength in vacuo
+*       'WAVE':  wavelength
+*       'VOPT':  optical velocity
+*       'ZOPT':  redshift
+*
+*     A: wavelength in air
+*       'AWAV':  wavelength in air
+*
+*     V: velocity
+*       'VELO':  relativistic velocity
+*       'BETA':  relativistic beta factor
+*
+*     The S-type forms the first four characters of the CTYPEia keyvalue,
+*     and CRVALia and CDELTia are expressed as S-type quantities so that
+*     they provide a first-order approximation to the S-type variable at
+*     the reference point.
+*
+*     Note that 'AFRQ', angular frequency, is additional to the variables
+*     defined in WCS Paper III.
+*
+*   P-type: the basic spectral variable (F, W, A, or V) with which the
+*     S-type variable is associated (see list above).
+*
+*     For non-grism axes, the P-type is encoded as the eighth character of
+*     CTYPEia.
+*
+*   X-type: the basic spectral variable (F, W, A, or V) for which the
+*     spectral axis is linear, grisms excluded (see below).
+*
+*     For non-grism axes, the X-type is encoded as the sixth character of
+*     CTYPEia.
+*
+*   Grisms: Grism axes have normal S-, and P-types but the axis is linear,
+*     not in any spectral variable, but in a special "grism parameter".
+*     The X-type spectral variable is either W or A for grisms in vacuo or
+*     air respectively, but is encoded as 'w' or 'a' to indicate that an
+*     additional transformation is required to convert to or from the
+*     grism parameter.  The spectral algorithm code for grisms also has a
+*     special encoding in CTYPEia, either 'GRI' (in vacuo) or 'GRA' (in air).
+*
+* In the algorithm chain, the non-linear transformation occurs between the
+* X-type and the P-type variables; the transformation between P-type and
+* S-type variables is always linear.
+*
+* When the P-type and X-type variables are the same, the spectral axis is
+* linear in the S-type variable and the second four characters of CTYPEia
+* are blank.  This can never happen for grism axes.
+*
+* As an example, correlating radio spectrometers always produce spectra that
+* are regularly gridded in frequency; a redshift scale on such a spectrum is
+* non-linear.  The required value of CTYPEia would be 'ZOPT-F2W', where the
+* desired S-type is 'ZOPT' (redshift), the P-type is necessarily 'W'
+* (wavelength), and the X-type is 'F' (frequency) by the nature of the
+* instrument.
+*
+* Argument checking:
+* ------------------
+* The input spectral values are only checked for values that would result in
+* floating point exceptions.  In particular, negative frequencies and
+* wavelengths are allowed, as are velocities greater than the speed of
+* light.  The same is true for the spectral parameters - rest frequency and
+* wavelength.
+*
+* Accuracy:
+* ---------
+* No warranty is given for the accuracy of these routines (refer to the
+* copyright notice); intending users must satisfy for themselves their
+* adequacy for the intended purpose.  However, closure effectively to within
+* double precision rounding error was demonstrated by test routine tspc.c
+* which accompanies this software.
+*
+*
+* spcini() - Default constructor for the spcprm struct
+* ----------------------------------------------------
+* spcini() sets all members of a spcprm struct to default values.  It should
+* be used to initialize every spcprm struct.
+*
+* Given and returned:
+*   spc       struct spcprm*
+*                       Spectral transformation parameters.
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         1: Null spcprm pointer passed.
+*
+*
+* spcfree() - Destructor for the spcprm struct
+* --------------------------------------------
+* spcfree() frees any memory that may have been allocated to store an error
+* message in the spcprm struct.
+*
+* Given:
+*   spc       struct spcprm*
+*                       Spectral transformation parameters.
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         1: Null spcprm pointer passed.
+*
+*
+* spcprt() - Print routine for the spcprm struct
+* ----------------------------------------------
+* spcprt() prints the contents of a spcprm struct using wcsprintf().  Mainly
+* intended for diagnostic purposes.
+*
+* Given:
+*   spc       const struct spcprm*
+*                       Spectral transformation parameters.
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         1: Null spcprm pointer passed.
+*
+*
+* spcset() - Setup routine for the spcprm struct
+* ----------------------------------------------
+* spcset() sets up a spcprm struct according to information supplied within
+* it.
+*
+* Note that this routine need not be called directly; it will be invoked by
+* spcx2s() and spcs2x() if spcprm::flag is anything other than a predefined
+* magic value.
+*
+* Given and returned:
+*   spc       struct spcprm*
+*                       Spectral transformation parameters.
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         1: Null spcprm pointer passed.
+*                         2: Invalid spectral parameters.
+*
+*                       For returns > 1, a detailed error message is set in
+*                       spcprm::err if enabled, see wcserr_enable().
+*
+*
+* spcx2s() - Transform to spectral coordinates
+* --------------------------------------------
+* spcx2s() transforms intermediate world coordinates to spectral coordinates.
+*
+* Given and returned:
+*   spc       struct spcprm*
+*                       Spectral transformation parameters.
+*
+* Given:
+*   nx        int       Vector length.
+*
+*   sx        int       Vector stride.
+*
+*   sspec     int       Vector stride.
+*
+*   x         const double[]
+*                       Intermediate world coordinates, in SI units.
+*
+* Returned:
+*   spec      double[]  Spectral coordinates, in SI units.
+*
+*   stat      int[]     Status return value status for each vector element:
+*                         0: Success.
+*                         1: Invalid value of x.
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         1: Null spcprm pointer passed.
+*                         2: Invalid spectral parameters.
+*                         3: One or more of the x coordinates were invalid,
+*                            as indicated by the stat vector.
+*
+*                       For returns > 1, a detailed error message is set in
+*                       spcprm::err if enabled, see wcserr_enable().
+*
+*
+* spcs2x() - Transform spectral coordinates
+* -----------------------------------------
+* spcs2x() transforms spectral world coordinates to intermediate world
+* coordinates.
+*
+* Given and returned:
+*   spc       struct spcprm*
+*                       Spectral transformation parameters.
+*
+* Given:
+*   nspec     int       Vector length.
+*
+*   sspec     int       Vector stride.
+*
+*   sx        int       Vector stride.
+*
+*   spec      const double[]
+*                       Spectral coordinates, in SI units.
+*
+* Returned:
+*   x         double[]  Intermediate world coordinates, in SI units.
+*
+*   stat      int[]     Status return value status for each vector element:
+*                         0: Success.
+*                         1: Invalid value of spec.
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         1: Null spcprm pointer passed.
+*                         2: Invalid spectral parameters.
+*                         4: One or more of the spec coordinates were
+*                            invalid, as indicated by the stat vector.
+*
+*                       For returns > 1, a detailed error message is set in
+*                       spcprm::err if enabled, see wcserr_enable().
+*
+*
+* spctype() - Spectral CTYPEia keyword analysis
+* ---------------------------------------------
+* spctype() checks whether a CTYPEia keyvalue is a valid spectral axis type
+* and if so returns information derived from it relating to the associated S-,
+* P-, and X-type spectral variables (see explanation above).
+*
+* The return arguments are guaranteed not be modified if CTYPEia is not a
+* valid spectral type; zero-pointers may be specified for any that are not of
+* interest.
+*
+* A deprecated form of this function, spctyp(), lacks the wcserr** parameter.
+*
+* Given:
+*   ctype     const char[9]
+*                       The CTYPEia keyvalue, (eight characters with null
+*                       termination).
+*
+* Returned:
+*   stype     char[]    The four-letter name of the S-type spectral variable
+*                       copied or translated from ctype.  If a non-zero
+*                       pointer is given, the array must accomodate a null-
+*                       terminated string of length 5.
+*
+*   scode     char[]    The three-letter spectral algorithm code copied or
+*                       translated from ctype.  Logarithmic ('LOG') and
+*                       tabular ('TAB') codes are also recognized.  If a
+*                       non-zero pointer is given, the array must accomodate a
+*                       null-terminated string of length 4.
+*
+*   sname     char[]    Descriptive name of the S-type spectral variable.
+*                       If a non-zero pointer is given, the array must
+*                       accomodate a null-terminated string of length 22.
+*
+*   units     char[]    SI units of the S-type spectral variable.  If a
+*                       non-zero pointer is given, the array must accomodate a
+*                       null-terminated string of length 8.
+*
+*   ptype     char*     Character code for the P-type spectral variable
+*                       derived from ctype, one of 'F', 'W', 'A', or 'V'.
+*
+*   xtype     char*     Character code for the X-type spectral variable
+*                       derived from ctype, one of 'F', 'W', 'A', or 'V'.
+*                       Also, 'w' and 'a' are synonymous to 'W' and 'A' for
+*                       grisms in vacuo and air respectively.  Set to 'L' or
+*                       'T' for logarithmic ('LOG') and tabular ('TAB') axes.
+*
+*   restreq   int*      Multivalued flag that indicates whether rest
+*                       frequency or wavelength is required to compute
+*                       spectral variables for this CTYPEia:
+*                         0: Not required.
+*                         1: Required for the conversion between S- and
+*                            P-types (e.g. 'ZOPT-F2W').
+*                         2: Required for the conversion between P- and
+*                            X-types (e.g. 'BETA-W2V').
+*                         3: Required for the conversion between S- and
+*                            P-types, and between P- and X-types, but not
+*                            between S- and X-types (this applies only for
+*                            'VRAD-V2F', 'VOPT-V2W', and 'ZOPT-V2W').
+*                        Thus the rest frequency or wavelength is required for
+*                        spectral coordinate computations (i.e. between S- and
+*                        X-types) only if restreq%3 != 0.
+*
+*   err       struct wcserr **
+*                       If enabled, for function return values > 1, this
+*                       struct will contain a detailed error message, see
+*                       wcserr_enable().  May be NULL if an error message is
+*                       not desired.  Otherwise, the user is responsible for
+*                       deleting the memory allocated for the wcserr struct.
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         2: Invalid spectral parameters (not a spectral
+*                            CTYPEia).
+*
+*
+* spcspxe() - Spectral keyword analysis
+* ------------------------------------
+* spcspxe() analyses the CTYPEia and CRVALia FITS spectral axis keyword values
+* and returns information about the associated X-type spectral variable.
+*
+* A deprecated form of this function, spcspx(), lacks the wcserr** parameter.
+*
+* Given:
+*   ctypeS    const char[9]
+*                       Spectral axis type, i.e. the CTYPEia keyvalue, (eight
+*                       characters with null termination).  For non-grism
+*                       axes, the character code for the P-type spectral
+*                       variable in the algorithm code (i.e. the eighth
+*                       character of CTYPEia) may be set to '?' (it will not
+*                       be reset).
+*
+*   crvalS    double    Value of the S-type spectral variable at the reference
+*                       point, i.e. the CRVALia keyvalue, SI units.
+*
+*   restfrq,
+*   restwav   double    Rest frequency [Hz] and rest wavelength in vacuo [m],
+*                       only one of which need be given, the other should be
+*                       set to zero.
+*
+* Returned:
+*   ptype     char*     Character code for the P-type spectral variable
+*                       derived from ctypeS, one of 'F', 'W', 'A', or 'V'.
+*
+*   xtype     char*     Character code for the X-type spectral variable
+*                       derived from ctypeS, one of 'F', 'W', 'A', or 'V'.
+*                       Also, 'w' and 'a' are synonymous to 'W' and 'A' for
+*                       grisms in vacuo and air respectively; crvalX and dXdS
+*                       (see below) will conform to these.
+*
+*   restreq   int*      Multivalued flag that indicates whether rest frequency
+*                       or wavelength is required to compute spectral
+*                       variables for this CTYPEia, as for spctype().
+*
+*   crvalX    double*   Value of the X-type spectral variable at the reference
+*                       point, SI units.
+*
+*   dXdS      double*   The derivative, dX/dS, evaluated at the reference
+*                       point, SI units.  Multiply the CDELTia keyvalue by
+*                       this to get the pixel spacing in the X-type spectral
+*                       coordinate.
+*
+*   err       struct wcserr **
+*                       If enabled, for function return values > 1, this
+*                       struct will contain a detailed error message, see
+*                       wcserr_enable().  May be NULL if an error message is
+*                       not desired.  Otherwise, the user is responsible for
+*                       deleting the memory allocated for the wcserr struct.
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         2: Invalid spectral parameters.
+*
+*
+* spcxpse() - Spectral keyword synthesis
+* -------------------------------------
+* spcxpse(), for the spectral axis type specified and the value provided for
+* the X-type spectral variable at the reference point, deduces the value of
+* the FITS spectral axis keyword CRVALia and also the derivative dS/dX which
+* may be used to compute CDELTia.  See above for an explanation of the S-,
+* P-, and X-type spectral variables.
+*
+* A deprecated form of this function, spcxps(), lacks the wcserr** parameter.
+*
+* Given:
+*   ctypeS    const char[9]
+*                       The required spectral axis type, i.e. the CTYPEia
+*                       keyvalue, (eight characters with null termination).
+*                       For non-grism axes, the character code for the P-type
+*                       spectral variable in the algorithm code (i.e. the
+*                       eighth character of CTYPEia) may be set to '?' (it
+*                       will not be reset).
+*
+*   crvalX    double    Value of the X-type spectral variable at the reference
+*                       point (N.B. NOT the CRVALia keyvalue), SI units.
+*
+*   restfrq,
+*   restwav   double    Rest frequency [Hz] and rest wavelength in vacuo [m],
+*                       only one of which need be given, the other should be
+*                       set to zero.
+*
+* Returned:
+*   ptype     char*     Character code for the P-type spectral variable
+*                       derived from ctypeS, one of 'F', 'W', 'A', or 'V'.
+*
+*   xtype     char*     Character code for the X-type spectral variable
+*                       derived from ctypeS, one of 'F', 'W', 'A', or 'V'.
+*                       Also, 'w' and 'a' are synonymous to 'W' and 'A' for
+*                       grisms; crvalX and cdeltX must conform to these.
+*
+*   restreq   int*      Multivalued flag that indicates whether rest frequency
+*                       or wavelength is required to compute spectral
+*                       variables for this CTYPEia, as for spctype().
+*
+*   crvalS    double*   Value of the S-type spectral variable at the reference
+*                       point (i.e. the appropriate CRVALia keyvalue), SI
+*                       units.
+*
+*   dSdX      double*   The derivative, dS/dX, evaluated at the reference
+*                       point, SI units.  Multiply this by the pixel spacing
+*                       in the X-type spectral coordinate to get the CDELTia
+*                       keyvalue.
+*
+*   err       struct wcserr **
+*                       If enabled, for function return values > 1, this
+*                       struct will contain a detailed error message, see
+*                       wcserr_enable().  May be NULL if an error message is
+*                       not desired.  Otherwise, the user is responsible for
+*                       deleting the memory allocated for the wcserr struct.
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         2: Invalid spectral parameters.
+*
+*
+* spctrne() - Spectral keyword translation
+* ---------------------------------------
+* spctrne() translates a set of FITS spectral axis keywords into the
+* corresponding set for the specified spectral axis type.  For example, a
+* 'FREQ' axis may be translated into 'ZOPT-F2W' and vice versa.
+*
+* A deprecated form of this function, spctrn(), lacks the wcserr** parameter.
+*
+* Given:
+*   ctypeS1   const char[9]
+*                       Spectral axis type, i.e. the CTYPEia keyvalue, (eight
+*                       characters with null termination).  For non-grism
+*                       axes, the character code for the P-type spectral
+*                       variable in the algorithm code (i.e. the eighth
+*                       character of CTYPEia) may be set to '?' (it will not
+*                       be reset).
+*
+*   crvalS1   double    Value of the S-type spectral variable at the reference
+*                       point, i.e. the CRVALia keyvalue, SI units.
+*
+*   cdeltS1   double    Increment of the S-type spectral variable at the
+*                       reference point, SI units.
+*
+*   restfrq,
+*   restwav   double    Rest frequency [Hz] and rest wavelength in vacuo [m],
+*                       only one of which need be given, the other should be
+*                       set to zero.  Neither are required if the translation
+*                       is between wave-characteristic types, or between
+*                       velocity-characteristic types.  E.g., required for
+*                       'FREQ'     -> 'ZOPT-F2W', but not required for
+*                       'VELO-F2V' -> 'ZOPT-F2W'.
+*
+* Given and returned:
+*   ctypeS2   char[9]   Required spectral axis type (eight characters with
+*                       null termination).  The first four characters are
+*                       required to be given and are never modified.  The
+*                       remaining four, the algorithm code, are completely
+*                       determined by, and must be consistent with, ctypeS1
+*                       and the first four characters of ctypeS2.  A non-zero
+*                       status value will be returned if they are inconsistent
+*                       (see below).  However, if the final three characters
+*                       are specified as "???", or if just the eighth
+*                       character is specified as '?', the correct algorithm
+*                       code will be substituted (applies for grism axes as
+*                       well as non-grism).
+*
+* Returned:
+*   crvalS2   double*   Value of the new S-type spectral variable at the
+*                       reference point, i.e. the new CRVALia keyvalue, SI
+*                       units.
+*
+*   cdeltS2   double*   Increment of the new S-type spectral variable at the
+*                       reference point, i.e. the new CDELTia keyvalue, SI
+*                       units.
+*
+*   err       struct wcserr **
+*                       If enabled, for function return values > 1, this
+*                       struct will contain a detailed error message, see
+*                       wcserr_enable().  May be NULL if an error message is
+*                       not desired.  Otherwise, the user is responsible for
+*                       deleting the memory allocated for the wcserr struct.
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         2: Invalid spectral parameters.
+*
+*                       A status value of 2 will be returned if restfrq or
+*                       restwav are not specified when required, or if ctypeS1
+*                       or ctypeS2 are self-inconsistent, or have different
+*                       spectral X-type variables.
+*
+*
+* spcaips() - Translate AIPS-convention spectral keywords
+* -------------------------------------------------------
+* spcaips() translates AIPS-convention spectral CTYPEia and VELREF keyvalues.
+*
+* Given:
+*   ctypeA    const char[9]
+*                       CTYPEia keyvalue possibly containing an
+*                       AIPS-convention spectral code (eight characters, need
+*                       not be null-terminated).
+*
+*   velref    int       AIPS-convention VELREF code.  It has the following
+*                       integer values:
+*                         1: LSR kinematic, originally described simply as
+*                            "LSR" without distinction between the kinematic
+*                            and dynamic definitions.
+*                         2: Barycentric, originally described as "HEL"
+*                            meaning heliocentric.
+*                         3: Topocentric, originally described as "OBS"
+*                            meaning geocentric but widely interpreted as
+*                            topocentric.
+*                       AIPS++ extensions to VELREF are also recognized:
+*                         4: LSR dynamic.
+*                         5: Geocentric.
+*                         6: Source rest frame.
+*                         7: Galactocentric.
+*
+*                       For an AIPS 'VELO' axis, a radio convention velocity
+*                       (VRAD) is denoted by adding 256 to VELREF, otherwise
+*                       an optical velocity (VOPT) is indicated (this is not
+*                       applicable to 'FREQ' or 'FELO' axes).  Setting velref
+*                       to 0 or 256 chooses between optical and radio velocity
+*                       without specifying a Doppler frame, provided that a
+*                       frame is encoded in ctypeA.  If not, i.e. for
+*                       ctypeA = 'VELO', ctype will be returned as 'VELO'.
+*
+*                       VELREF takes precedence over CTYPEia in defining the
+*                       Doppler frame, e.g.
+*
+=                         ctypeA = 'VELO-HEL'
+=                         velref = 1
+*
+*                       returns ctype = 'VOPT' with specsys set to 'LSRK'.
+*
+* Returned:
+*   ctype     char[9]   Translated CTYPEia keyvalue, or a copy of ctypeA if no
+*                       translation was performed (in which case any trailing
+*                       blanks in ctypeA will be replaced with nulls).
+*
+*   specsys   char[9]   Doppler reference frame indicated by VELREF or else
+*                       by CTYPEia with value corresponding to the SPECSYS
+*                       keyvalue in the FITS WCS standard.  May be returned
+*                       blank if neither specifies a Doppler frame, e.g.
+*                       ctypeA = 'FELO' and velref%256 == 0.
+*
+* Function return value:
+*             int       Status return value:
+*                        -1: No translation required (not an error).
+*                         0: Success.
+*                         2: Invalid value of VELREF.
+*
+*
+* spcprm struct - Spectral transformation parameters
+* --------------------------------------------------
+* The spcprm struct contains information required to transform spectral
+* coordinates.  It consists of certain members that must be set by the user
+* ("given") and others that are set by the WCSLIB routines ("returned").  Some
+* of the latter are supplied for informational purposes while others are for
+* internal use only.
+*
+*   int flag
+*     (Given and returned) This flag must be set to zero whenever any of the
+*     following spcprm structure members are set or changed:
+*
+*       - spcprm::type,
+*       - spcprm::code,
+*       - spcprm::crval,
+*       - spcprm::restfrq,
+*       - spcprm::restwav,
+*       - spcprm::pv[].
+*
+*     This signals the initialization routine, spcset(), to recompute the
+*     returned members of the spcprm struct.  spcset() will reset flag to
+*     indicate that this has been done.
+*
+*   char type[8]
+*     (Given) Four-letter spectral variable type, e.g "ZOPT" for
+*     CTYPEia = 'ZOPT-F2W'.  (Declared as char[8] for alignment reasons.)
+*
+*   char code[4]
+*     (Given) Three-letter spectral algorithm code, e.g "F2W" for
+*     CTYPEia = 'ZOPT-F2W'.
+*
+*   double crval
+*     (Given) Reference value (CRVALia), SI units.
+*
+*   double restfrq
+*     (Given) The rest frequency [Hz], and ...
+*
+*   double restwav
+*     (Given) ... the rest wavelength in vacuo [m], only one of which need be
+*     given, the other should be set to zero.  Neither are required if the
+*     X and S spectral variables are both wave-characteristic, or both
+*     velocity-characteristic, types.
+*
+*   double pv[7]
+*     (Given) Grism parameters for 'GRI' and 'GRA' algorithm codes:
+*       - 0: G, grating ruling density.
+*       - 1: m, interference order.
+*       - 2: alpha, angle of incidence [deg].
+*       - 3: n_r, refractive index at the reference wavelength, lambda_r.
+*       - 4: n'_r, dn/dlambda at the reference wavelength, lambda_r (/m).
+*       - 5: epsilon, grating tilt angle [deg].
+*       - 6: theta, detector tilt angle [deg].
+*
+* The remaining members of the spcprm struct are maintained by spcset() and
+* must not be modified elsewhere:
+*
+*   double w[6]
+*     (Returned) Intermediate values:
+*       - 0: Rest frequency or wavelength (SI).
+*       - 1: The value of the X-type spectral variable at the reference point
+*           (SI units).
+*       - 2: dX/dS at the reference point (SI units).
+*      The remainder are grism intermediates.
+*
+*   int isGrism
+*     (Returned) Grism coordinates?
+*       - 0: no,
+*       - 1: in vacuum,
+*       - 2: in air.
+*
+*   int padding1
+*     (An unused variable inserted for alignment purposes only.)
+*
+*   struct wcserr *err
+*     (Returned) If enabled, when an error status is returned this structure
+*     contains detailed information about the error, see wcserr_enable().
+*
+*   void *padding2
+*     (An unused variable inserted for alignment purposes only.)
+*   int (*spxX2P)(SPX_ARGS)
+*     (Returned) The first and ...
+*   int (*spxP2S)(SPX_ARGS)
+*     (Returned) ... the second of the pointers to the transformation
+*     functions in the two-step algorithm chain X -> P -> S in the
+*     pixel-to-spectral direction where the non-linear transformation is from
+*     X to P.  The argument list, SPX_ARGS, is defined in spx.h.
+*
+*   int (*spxS2P)(SPX_ARGS)
+*     (Returned) The first and ...
+*   int (*spxP2X)(SPX_ARGS)
+*     (Returned) ... the second of the pointers to the transformation
+*     functions in the two-step algorithm chain S -> P -> X in the
+*     spectral-to-pixel direction where the non-linear transformation is from
+*     P to X.  The argument list, SPX_ARGS, is defined in spx.h.
+*
+*
+* Global variable: const char *spc_errmsg[] - Status return messages
+* ------------------------------------------------------------------
+* Error messages to match the status value returned from each function.
+*
+*===========================================================================*/
+
+#ifndef WCSLIB_SPC
+#define WCSLIB_SPC
+
+#include "spx.h"
+#include "wcserr.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+extern const char *spc_errmsg[];
+
+enum spc_errmsg_enum {
+  SPCERR_NO_CHANGE       = -1,	/* No change. */
+  SPCERR_SUCCESS         =  0,	/* Success. */
+  SPCERR_NULL_POINTER    =  1,	/* Null spcprm pointer passed. */
+  SPCERR_BAD_SPEC_PARAMS =  2,	/* Invalid spectral parameters. */
+  SPCERR_BAD_X           =  3,	/* One or more of x coordinates were
+				   invalid. */
+  SPCERR_BAD_SPEC        =  4 	/* One or more of the spec coordinates were
+				   invalid. */
+};
+
+struct spcprm {
+  /* Initialization flag (see the prologue above).                          */
+  /*------------------------------------------------------------------------*/
+  int    flag;			/* Set to zero to force initialization.     */
+
+  /* Parameters to be provided (see the prologue above).                    */
+  /*------------------------------------------------------------------------*/
+  char   type[8];		/* Four-letter spectral variable type.      */
+  char   code[4];		/* Three-letter spectral algorithm code.    */
+
+  double crval;			/* Reference value (CRVALia), SI units.     */
+  double restfrq;		/* Rest frequency, Hz.                      */
+  double restwav;		/* Rest wavelength, m.                      */
+
+  double pv[7];			/* Grism parameters:                        */
+				/*   0: G, grating ruling density.          */
+				/*   1: m, interference order.              */
+				/*   2: alpha, angle of incidence.          */
+				/*   3: n_r, refractive index at lambda_r.  */
+				/*   4: n'_r, dn/dlambda at lambda_r.       */
+				/*   5: epsilon, grating tilt angle.        */
+				/*   6: theta, detector tilt angle.         */
+
+  /* Information derived from the parameters supplied.                      */
+  /*------------------------------------------------------------------------*/
+  double w[6];			/* Intermediate values.                     */
+				/*   0: Rest frequency or wavelength (SI).  */
+				/*   1: CRVALX (SI units).                  */
+				/*   2: CDELTX/CDELTia = dX/dS (SI units).  */
+				/* The remainder are grism intermediates.   */
+
+  int    isGrism;		/* Grism coordinates?  1: vacuum, 2: air.   */
+  int    padding1;		/* (Dummy inserted for alignment purposes.) */
+
+  /* Error handling                                                         */
+  /*------------------------------------------------------------------------*/
+  struct wcserr *err;
+
+  /* Private                                                                */
+  /*------------------------------------------------------------------------*/
+  void   *padding2;		/* (Dummy inserted for alignment purposes.) */
+  int (*spxX2P)(SPX_ARGS);	/* Pointers to the transformation functions */
+  int (*spxP2S)(SPX_ARGS);	/* in the two-step algorithm chain in the   */
+				/* pixel-to-spectral direction.             */
+
+  int (*spxS2P)(SPX_ARGS);	/* Pointers to the transformation functions */
+  int (*spxP2X)(SPX_ARGS);	/* in the two-step algorithm chain in the   */
+				/* spectral-to-pixel direction.             */
+};
+
+/* Size of the spcprm struct in int units, used by the Fortran wrappers. */
+#define SPCLEN (sizeof(struct spcprm)/sizeof(int))
+
+
+int spcini(struct spcprm *spc);
+
+int spcfree(struct spcprm *spc);
+
+int spcprt(const struct spcprm *spc);
+
+int spcset(struct spcprm *spc);
+
+int spcx2s(struct spcprm *spc, int nx, int sx, int sspec,
+           const double x[], double spec[], int stat[]);
+
+int spcs2x(struct spcprm *spc, int nspec, int sspec, int sx,
+           const double spec[], double x[], int stat[]);
+
+int spctype(const char ctype[], char stype[], char scode[], char sname[],
+            char units[], char *ptype, char *xtype, int *restreq,
+            struct wcserr **err);
+
+int spcspxe(const char ctypeS[], double crvalS, double restfrq,
+            double restwav, char *ptype, char *xtype, int *restreq,
+            double *crvalX, double *dXdS, struct wcserr **err);
+
+int spcxpse(const char ctypeS[], double crvalX, double restfrq,
+            double restwav, char *ptype, char *xtype, int *restreq,
+            double *crvalS, double *dSdX, struct wcserr **err);
+
+int spctrne(const char ctypeS1[], double crvalS1, double cdeltS1,
+            double restfrq, double restwav, char ctypeS2[], double *crvalS2,
+            double *cdeltS2, struct wcserr **err);
+
+int spcaips(const char ctypeA[], int velref, char ctype[], char specsys[]);
+
+
+/* Deprecated. */
+#define spcini_errmsg spc_errmsg
+#define spcprt_errmsg spc_errmsg
+#define spcset_errmsg spc_errmsg
+#define spcx2s_errmsg spc_errmsg
+#define spcs2x_errmsg spc_errmsg
+
+int spctyp(const char ctype[], char stype[], char scode[], char sname[],
+           char units[], char *ptype, char *xtype, int *restreq);
+int spcspx(const char ctypeS[], double crvalS, double restfrq, double restwav,
+           char *ptype, char *xtype, int *restreq, double *crvalX,
+           double *dXdS);
+int spcxps(const char ctypeS[], double crvalX, double restfrq, double restwav,
+           char *ptype, char *xtype, int *restreq, double *crvalS,
+           double *dSdX);
+int spctrn(const char ctypeS1[], double crvalS1, double cdeltS1,
+           double restfrq, double restwav, char ctypeS2[], double *crvalS2,
+           double *cdeltS2);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* WCSLIB_SPC */
diff --git a/cextern/wcslib/C/sph.c b/cextern/wcslib/C/sph.c
new file mode 100644
index 0000000..144369e
--- /dev/null
+++ b/cextern/wcslib/C/sph.c
@@ -0,0 +1,460 @@
+/*============================================================================
+
+  WCSLIB 4.16 - an implementation of the FITS WCS standard.
+  Copyright (C) 1995-2012, Mark Calabretta
+
+  This file is part of WCSLIB.
+
+  WCSLIB is free software: you can redistribute it and/or modify it under the
+  terms of the GNU Lesser General Public License as published by the Free
+  Software Foundation, either version 3 of the License, or (at your option)
+  any later version.
+
+  WCSLIB 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 Lesser General Public License for
+  more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with WCSLIB.  If not, see http://www.gnu.org/licenses.
+
+  Direct correspondence concerning WCSLIB to mark at calabretta.id.au
+
+  Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
+  http://www.atnf.csiro.au/people/Mark.Calabretta
+  $Id: sph.c,v 4.16 2012/11/07 04:42:44 cal103 Exp $
+*===========================================================================*/
+
+#include <math.h>
+#include "wcstrig.h"
+#include "sph.h"
+
+#define copysign(X, Y) ((Y) < 0.0 ? -fabs(X) : fabs(X))
+
+#define tol 1.0e-5
+
+/*--------------------------------------------------------------------------*/
+
+int sphx2s(
+  const double eul[5],
+  int nphi,
+  int ntheta,
+  int spt,
+  int sll,
+  const double phi[],
+  const double theta[],
+  double lng[],
+  double lat[])
+
+{
+  int mphi, mtheta, rowlen, rowoff;
+  double cosphi, costhe, costhe3, costhe4, dlng, dphi, sinphi, sinthe,
+         sinthe3, sinthe4, x, y, z;
+  register int iphi, itheta;
+  register const double *phip, *thetap;
+  register double *latp, *lngp;
+
+  if (ntheta > 0) {
+    mphi   = nphi;
+    mtheta = ntheta;
+  } else {
+    mphi   = 1;
+    mtheta = 1;
+    ntheta = nphi;
+  }
+
+
+  /* Check for a simple change in origin of longitude. */
+  if (eul[4] == 0.0) {
+    if (eul[1] == 0.0) {
+      dlng = fmod(eul[0] + 180.0 - eul[2], 360.0);
+
+      lngp = lng;
+      latp = lat;
+      phip   = phi;
+      thetap = theta;
+      for (itheta = 0; itheta < ntheta; itheta++) {
+        for (iphi = 0; iphi < mphi; iphi++) {
+          *lngp = *phip + dlng;
+          *latp = *thetap;
+
+          /* Normalize the celestial longitude. */
+          if (eul[0] >= 0.0) {
+            if (*lngp < 0.0) *lngp += 360.0;
+          } else {
+            if (*lngp > 0.0) *lngp -= 360.0;
+          }
+
+          if (*lngp > 360.0) {
+            *lngp -= 360.0;
+          } else if (*lngp < -360.0) {
+            *lngp += 360.0;
+          }
+
+          lngp   += sll;
+          latp   += sll;
+          phip   += spt;
+          thetap += spt;
+        }
+      }
+
+    } else {
+      dlng = fmod(eul[0] + eul[2], 360.0);
+
+      lngp = lng;
+      latp = lat;
+      phip   = phi;
+      thetap = theta;
+      for (itheta = 0; itheta < ntheta; itheta++) {
+        for (iphi = 0; iphi < mphi; iphi++) {
+          *lngp = dlng - *phip;
+          *latp = -(*thetap);
+
+          /* Normalize the celestial longitude. */
+          if (eul[0] >= 0.0) {
+            if (*lngp < 0.0) *lngp += 360.0;
+          } else {
+            if (*lngp > 0.0) *lngp -= 360.0;
+          }
+
+          if (*lngp > 360.0) {
+            *lngp -= 360.0;
+          } else if (*lngp < -360.0) {
+            *lngp += 360.0;
+          }
+
+          lngp   += sll;
+          latp   += sll;
+          phip   += spt;
+          thetap += spt;
+        }
+      }
+    }
+
+    return 0;
+  }
+
+
+  /* Do phi dependency. */
+  phip = phi;
+  rowoff = 0;
+  rowlen = nphi*sll;
+  for (iphi = 0; iphi < nphi; iphi++, rowoff += sll, phip += spt) {
+    dphi = *phip - eul[2];
+
+    lngp = lng + rowoff;
+    for (itheta = 0; itheta < mtheta; itheta++) {
+      *lngp = dphi;
+      lngp += rowlen;
+    }
+  }
+
+
+  /* Do theta dependency. */
+  thetap = theta;
+  lngp = lng;
+  latp = lat;
+  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
+    sincosd(*thetap, &sinthe, &costhe);
+    costhe3 = costhe*eul[3];
+    costhe4 = costhe*eul[4];
+    sinthe3 = sinthe*eul[3];
+    sinthe4 = sinthe*eul[4];
+
+    for (iphi = 0; iphi < mphi; iphi++, lngp += sll, latp += sll) {
+      dphi = *lngp;
+      sincosd(dphi, &sinphi, &cosphi);
+
+      /* Compute the celestial longitude. */
+      x = sinthe4 - costhe3*cosphi;
+      if (fabs(x) < tol) {
+        /* Rearrange formula to reduce roundoff errors. */
+        x = -cosd(*thetap + eul[1]) + costhe3*(1.0 - cosphi);
+      }
+
+      y = -costhe*sinphi;
+      if (x != 0.0 || y != 0.0) {
+        dlng = atan2d(y, x);
+      } else {
+        /* Change of origin of longitude. */
+        if (eul[1] < 90.0) {
+          dlng =  dphi + 180.0;
+        } else {
+          dlng = -dphi;
+        }
+      }
+      *lngp = eul[0] + dlng;
+
+      /* Normalize the celestial longitude. */
+      if (eul[0] >= 0.0) {
+        if (*lngp < 0.0) *lngp += 360.0;
+      } else {
+        if (*lngp > 0.0) *lngp -= 360.0;
+      }
+
+      if (*lngp > 360.0) {
+        *lngp -= 360.0;
+      } else if (*lngp < -360.0) {
+        *lngp += 360.0;
+      }
+
+      /* Compute the celestial latitude. */
+      if (fmod(dphi,180.0) == 0.0) {
+        *latp = *thetap + cosphi*eul[1];
+        if (*latp >  90.0) *latp =  180.0 - *latp;
+        if (*latp < -90.0) *latp = -180.0 - *latp;
+      } else {
+        z = sinthe3 + costhe4*cosphi;
+        if (fabs(z) > 0.99) {
+          /* Use an alternative formula for greater accuracy. */
+          *latp = copysign(acosd(sqrt(x*x+y*y)), z);
+        } else {
+          *latp = asind(z);
+        }
+      }
+    }
+  }
+
+  return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int sphs2x(
+  const double eul[5],
+  int nlng,
+  int nlat,
+  int sll,
+  int spt,
+  const double lng[],
+  const double lat[],
+  double phi[],
+  double theta[])
+
+{
+  int mlat, mlng, rowlen, rowoff;
+  double coslat, coslat3, coslat4, coslng, dlng, dphi, sinlat, sinlat3,
+         sinlat4, sinlng, x, y, z;
+  register int ilat, ilng;
+  register const double *latp, *lngp;
+  register double *phip, *thetap;
+
+  if (nlat > 0) {
+    mlng = nlng;
+    mlat = nlat;
+  } else {
+    mlng = 1;
+    mlat = 1;
+    nlat = nlng;
+  }
+
+
+  /* Check for a simple change in origin of longitude. */
+  if (eul[4] == 0.0) {
+    if (eul[1] == 0.0) {
+      dphi = fmod(eul[2] - 180.0 - eul[0], 360.0);
+
+      lngp = lng;
+      latp = lat;
+      phip   = phi;
+      thetap = theta;
+      for (ilat = 0; ilat < nlat; ilat++) {
+        for (ilng = 0; ilng < mlng; ilng++) {
+          *phip = fmod(*lngp + dphi, 360.0);
+          *thetap = *latp;
+
+          /* Normalize the native longitude. */
+          if (*phip > 180.0) {
+            *phip -= 360.0;
+          } else if (*phip < -180.0) {
+            *phip += 360.0;
+          }
+
+          phip   += spt;
+          thetap += spt;
+          lngp   += sll;
+          latp   += sll;
+        }
+      }
+
+    } else {
+      dphi = fmod(eul[2] + eul[0], 360.0);
+
+      lngp = lng;
+      latp = lat;
+      phip   = phi;
+      thetap = theta;
+      for (ilat = 0; ilat < nlat; ilat++) {
+        for (ilng = 0; ilng < mlng; ilng++) {
+          *phip = fmod(dphi - *lngp, 360.0);
+          *thetap = -(*latp);
+
+          /* Normalize the native longitude. */
+          if (*phip > 180.0) {
+            *phip -= 360.0;
+          } else if (*phip < -180.0) {
+            *phip += 360.0;
+          }
+
+          phip   += spt;
+          thetap += spt;
+          lngp   += sll;
+          latp   += sll;
+        }
+      }
+    }
+
+    return 0;
+  }
+
+
+  /* Do lng dependency. */
+  lngp = lng;
+  rowoff = 0;
+  rowlen = nlng*spt;
+  for (ilng = 0; ilng < nlng; ilng++, rowoff += spt, lngp += sll) {
+    dlng = *lngp - eul[0];
+
+    phip = phi + rowoff;
+    thetap = theta;
+    for (ilat = 0; ilat < mlat; ilat++) {
+      *phip = dlng;
+      phip += rowlen;
+    }
+  }
+
+
+  /* Do lat dependency. */
+  latp = lat;
+  phip   = phi;
+  thetap = theta;
+  for (ilat = 0; ilat < nlat; ilat++, latp += sll) {
+    sincosd(*latp, &sinlat, &coslat);
+    coslat3 = coslat*eul[3];
+    coslat4 = coslat*eul[4];
+    sinlat3 = sinlat*eul[3];
+    sinlat4 = sinlat*eul[4];
+
+    for (ilng = 0; ilng < mlng; ilng++, phip += spt, thetap += spt) {
+      dlng = *phip;
+      sincosd(dlng, &sinlng, &coslng);
+
+      /* Compute the native longitude. */
+      x = sinlat4 - coslat3*coslng;
+      if (fabs(x) < tol) {
+        /* Rearrange formula to reduce roundoff errors. */
+        x = -cosd(*latp+eul[1]) + coslat3*(1.0 - coslng);
+      }
+
+      y = -coslat*sinlng;
+      if (x != 0.0 || y != 0.0) {
+        dphi = atan2d(y, x);
+      } else {
+        /* Change of origin of longitude. */
+        if (eul[1] < 90.0) {
+          dphi =  dlng - 180.0;
+        } else {
+          dphi = -dlng;
+        }
+      }
+      *phip = fmod(eul[2] + dphi, 360.0);
+
+      /* Normalize the native longitude. */
+      if (*phip > 180.0) {
+        *phip -= 360.0;
+      } else if (*phip < -180.0) {
+        *phip += 360.0;
+      }
+
+      /* Compute the native latitude. */
+      if (fmod(dlng,180.0) == 0.0) {
+        *thetap = *latp + coslng*eul[1];
+        if (*thetap >  90.0) *thetap =  180.0 - *thetap;
+        if (*thetap < -90.0) *thetap = -180.0 - *thetap;
+      } else {
+        z = sinlat3 + coslat4*coslng;
+        if (fabs(z) > 0.99) {
+          /* Use an alternative formula for greater accuracy. */
+          *thetap = copysign(acosd(sqrt(x*x+y*y)), z);
+        } else {
+          *thetap = asind(z);
+        }
+      }
+    }
+  }
+
+  return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int sphdpa(
+  int nfield,
+  double lng0,
+  double lat0,
+  const double lng[],
+  const double lat[],
+  double dist[],
+  double pa[])
+
+{
+  int i;
+  double eul[5];
+
+  /* Set the Euler angles for the coordinate transformation. */
+  eul[0] = lng0;
+  eul[1] = 90.0 - lat0;
+  eul[2] = 0.0;
+  eul[3] = cosd(eul[1]);
+  eul[4] = sind(eul[1]);
+
+  /* Transform field points to the new system. */
+  sphs2x(eul, nfield, 0, 1, 1, lng, lat, pa, dist);
+
+  for (i = 0; i < nfield; i++) {
+    /* Angular distance is obtained from latitude in the new frame. */
+    dist[i] = 90.0 - dist[i];
+
+    /* Position angle is obtained from longitude in the new frame. */
+    pa[i] = -pa[i];
+    if (pa[i] < -180.0) pa[i] += 360.0;
+  }
+
+  return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int sphpad(
+  int nfield,
+  double lng0,
+  double lat0,
+  const double dist[],
+  const double pa[],
+  double lng[],
+  double lat[])
+
+{
+  int i;
+  double eul[5];
+
+  /* Set the Euler angles for the coordinate transformation. */
+  eul[0] = lng0;
+  eul[1] = 90.0 - lat0;
+  eul[2] = 0.0;
+  eul[3] = cosd(eul[1]);
+  eul[4] = sind(eul[1]);
+
+  for (i = 0; i < nfield; i++) {
+    /* Latitude in the new frame is obtained from angular distance. */
+    lat[i] = 90.0 - dist[i];
+
+    /* Longitude in the new frame is obtained from position angle. */
+    lng[i] = -pa[i];
+  }
+
+  /* Transform field points to the old system. */
+  sphx2s(eul, nfield, 0, 1, 1, lng, lat, lng, lat);
+
+  return 0;
+}
diff --git a/cextern/wcslib/C/sph.h b/cextern/wcslib/C/sph.h
new file mode 100644
index 0000000..bbfa033
--- /dev/null
+++ b/cextern/wcslib/C/sph.h
@@ -0,0 +1,251 @@
+/*============================================================================
+
+  WCSLIB 4.16 - an implementation of the FITS WCS standard.
+  Copyright (C) 1995-2012, Mark Calabretta
+
+  This file is part of WCSLIB.
+
+  WCSLIB is free software: you can redistribute it and/or modify it under the
+  terms of the GNU Lesser General Public License as published by the Free
+  Software Foundation, either version 3 of the License, or (at your option)
+  any later version.
+
+  WCSLIB 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 Lesser General Public License for
+  more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with WCSLIB.  If not, see http://www.gnu.org/licenses.
+
+  Direct correspondence concerning WCSLIB to mark at calabretta.id.au
+
+  Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
+  http://www.atnf.csiro.au/people/Mark.Calabretta
+  $Id: sph.h,v 4.16 2012/11/07 04:42:44 cal103 Exp $
+*=============================================================================
+*
+* WCSLIB 4.16 - C routines that implement the spherical coordinate
+* transformations used by the FITS World Coordinate System (WCS) standard.
+* Refer to
+*
+*   "Representations of world coordinates in FITS",
+*   Greisen, E.W., & Calabretta, M.R. 2002, A&A, 395, 1061 (Paper I)
+*
+*   "Representations of celestial coordinates in FITS",
+*   Calabretta, M.R., & Greisen, E.W. 2002, A&A, 395, 1077 (Paper II)
+*
+* Refer to the README file provided with WCSLIB for an overview of the
+* library.
+*
+*
+* Summary of the sph routines
+* ---------------------------
+* The WCS spherical coordinate transformations are implemented via separate
+* functions, sphx2s() and sphs2x(), for the transformation in each direction.
+*
+* A utility function, sphdpa(), computes the angular distances and position
+* angles from a given point on the sky to a number of other points.  sphpad()
+* does the complementary operation - computes the coordinates of points offset
+* by the given angular distances and position angles from a given point on the
+* sky.
+*
+*
+* sphx2s() - Rotation in the pixel-to-world direction
+* ---------------------------------------------------
+* sphx2s() transforms native coordinates of a projection to celestial
+* coordinates.
+*
+* Given:
+*   eul       const double[5]
+*                       Euler angles for the transformation:
+*                         0: Celestial longitude of the native pole [deg].
+*                         1: Celestial colatitude of the native pole, or
+*                            native colatitude of the celestial pole [deg].
+*                         2: Native longitude of the celestial pole [deg].
+*                         3: cos(eul[1])
+*                         4: sin(eul[1])
+*
+*   nphi,
+*   ntheta    int       Vector lengths.
+*
+*   spt,sxy   int       Vector strides.
+*
+*   phi,theta const double[]
+*                       Longitude and latitude in the native coordinate
+*                       system of the projection [deg].
+*
+* Returned:
+*   lng,lat   double[]  Celestial longitude and latitude [deg].  These may
+*                       refer to the same storage as phi and theta
+*                       respectively.
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*
+*
+* sphs2x() - Rotation in the world-to-pixel direction
+* ---------------------------------------------------
+* sphs2x() transforms celestial coordinates to the native coordinates of a
+* projection.
+*
+* Given:
+*   eul       const double[5]
+*                       Euler angles for the transformation:
+*                         0: Celestial longitude of the native pole [deg].
+*                         1: Celestial colatitude of the native pole, or
+*                            native colatitude of the celestial pole [deg].
+*                         2: Native longitude of the celestial pole [deg].
+*                         3: cos(eul[1])
+*                         4: sin(eul[1])
+*
+*   nlng,nlat int       Vector lengths.
+*
+*   sll,spt   int       Vector strides.
+*
+*   lng,lat   const double[]
+*                       Celestial longitude and latitude [deg].
+*
+* Returned:
+*   phi,theta double[]  Longitude and latitude in the native coordinate system
+*                       of the projection [deg].  These may refer to the same
+*                       storage as lng and lat respectively.
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*
+*
+* sphdpa() - Compute angular distance and position angle
+* ------------------------------------------------------
+* sphdpa() computes the angular distance and generalized position angle (see
+* notes) from a "reference" point to a number of "field" points on the sphere.
+* The points must be specified consistently in any spherical coordinate
+* system.
+*
+* sphdpa() is complementary to sphpad().
+*
+* Given:
+*   nfield    int       The number of field points.
+*
+*   lng0,lat0 double    Spherical coordinates of the reference point [deg].
+*
+*   lng,lat   const double[]
+*                       Spherical coordinates of the field points [deg].
+*
+* Returned:
+*   dist,pa   double[]  Angular distances and position angles [deg].  These
+*                       may refer to the same storage as lng and lat
+*                       respectively.
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*
+* Notes:
+*   sphdpa() uses sphs2x() to rotate coordinates so that the reference point
+*   is at the north pole of the new system with the north pole of the old
+*   system at zero longitude in the new.  The Euler angles required by
+*   sphs2x() for this rotation are
+*
+=     eul[0] = lng0;
+=     eul[1] = 90.0 - lat0;
+=     eul[2] =  0.0;
+*
+*   The angular distance and generalized position angle are readily obtained
+*   from the longitude and latitude of the field point in the new system.
+*   This applies even if the reference point is at one of the poles, in which
+*   case the "position angle" returned is as would be computed for a reference
+*   point at (lng0,+90-epsilon) or (lng0,-90+epsilon), in the limit as epsilon
+*   goes to zero.
+*
+*   It is evident that the coordinate system in which the two points are
+*   expressed is irrelevant to the determination of the angular separation
+*   between the points.  However, this is not true of the generalized position
+*   angle.
+*
+*   The generalized position angle is here defined as the angle of
+*   intersection of the great circle containing the reference and field points
+*   with that containing the reference point and the pole.  It has its normal
+*   meaning when the the reference and field points are specified in
+*   equatorial coordinates (right ascension and declination).
+*
+*   Interchanging the reference and field points changes the position angle in
+*   a non-intuitive way (because the sum of the angles of a spherical triangle
+*   normally exceeds 180 degrees).
+*
+*   The position angle is undefined if the reference and field points are
+*   coincident or antipodal.  This may be detected by checking for a distance
+*   of 0 or 180 degrees (within rounding tolerance).  sphdpa() will return an
+*   arbitrary position angle in such circumstances.
+*
+*
+* sphpad() - Compute field points offset from a given point
+* ---------------------------------------------------------
+* sphpad() computes the coordinates of a set of points that are offset by the
+* specified angular distances and position angles from a given "reference"
+* point on the sky.  The distances and position angles must be specified
+* consistently in any spherical coordinate system.
+*
+* sphpad() is complementary to sphdpa().
+*
+* Given:
+*   nfield    int       The number of field points.
+*
+*   lng0,lat0 double    Spherical coordinates of the reference point [deg].
+*
+*   dist,pa   const double[]
+*                       Angular distances and position angles [deg].
+*
+* Returned:
+*   lng,lat   double[]  Spherical coordinates of the field points [deg].
+*                       These may refer to the same storage as dist and pa
+*                       respectively.
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*
+* Notes:
+*   sphpad() is implemented analogously to sphdpa() although using sphx2s()
+*   for the inverse transformation.  In particular, when the reference point
+*   is at one of the poles, "position angle" is interpreted as though the
+*   reference point was at (lng0,+90-epsilon) or (lng0,-90+epsilon), in the
+*   limit as epsilon goes to zero.
+*
+*   Applying sphpad() with the distances and position angles computed by
+*   sphdpa() should return the original field points.
+*
+*===========================================================================*/
+
+#ifndef WCSLIB_SPH
+#define WCSLIB_SPH
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+int sphx2s(const double eul[5], int nphi, int ntheta, int spt, int sxy,
+           const double phi[], const double theta[],
+           double lng[], double lat[]);
+
+int sphs2x(const double eul[5], int nlng, int nlat, int sll , int spt,
+           const double lng[], const double lat[],
+           double phi[], double theta[]);
+
+int sphdpa(int nfield, double lng0, double lat0,
+           const double lng[], const double lat[],
+           double dist[], double pa[]);
+
+int sphpad(int nfield, double lng0, double lat0,
+           const double dist[], const double pa[],
+           double lng[], double lat[]);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* WCSLIB_SPH */
diff --git a/cextern/wcslib/C/spx.c b/cextern/wcslib/C/spx.c
new file mode 100644
index 0000000..45f0ef4
--- /dev/null
+++ b/cextern/wcslib/C/spx.c
@@ -0,0 +1,1148 @@
+/*============================================================================
+
+  WCSLIB 4.16 - an implementation of the FITS WCS standard.
+  Copyright (C) 1995-2012, Mark Calabretta
+
+  This file is part of WCSLIB.
+
+  WCSLIB is free software: you can redistribute it and/or modify it under the
+  terms of the GNU Lesser General Public License as published by the Free
+  Software Foundation, either version 3 of the License, or (at your option)
+  any later version.
+
+  WCSLIB 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 Lesser General Public License for
+  more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with WCSLIB.  If not, see http://www.gnu.org/licenses.
+
+  Direct correspondence concerning WCSLIB to mark at calabretta.id.au
+
+  Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
+  http://www.atnf.csiro.au/people/Mark.Calabretta
+  $Id: spx.c,v 4.16 2012/11/07 04:42:44 cal103 Exp $
+*===========================================================================*/
+
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "wcserr.h"
+#include "wcsmath.h"
+#include "spx.h"
+
+
+/* Map status return value to message. */
+const char *spx_errmsg[] = {
+  "Success",
+  "Null spxprm pointer passed",
+  "Invalid spectral parameters",
+  "Invalid spectral variable",
+  "One or more of the inspec coordinates were invalid"};
+
+/* Convenience macro for invoking wcserr_set(). */
+#define SPX_ERRMSG(status) WCSERR_SET(status), spx_errmsg[status]
+
+#define C 2.99792458e8
+#define h 6.6260755e-34
+
+/*============================================================================
+*   Spectral cross conversions; given one spectral coordinate it computes all
+*   the others, plus the required derivatives of each with respect to the
+*   others.
+*===========================================================================*/
+
+int specx(type, spec, restfrq, restwav, spx)
+
+const char *type;
+double spec, restfrq, restwav;
+struct spxprm *spx;
+
+{
+  static const char *function = "specx";
+
+  register int k;
+  int haverest;
+  double beta, dwaveawav, gamma, n, s, t, u;
+  struct wcserr **err;
+
+  if (spx == 0x0) return SPXERR_NULL_POINTER;
+  err = &(spx->err);
+
+  haverest = 1;
+  if (restfrq == 0.0) {
+    if (restwav == 0.0) {
+      /* No line rest frequency supplied. */
+      haverest = 0;
+
+      /* Temporarily set a dummy value for conversions. */
+      spx->restwav = 1.0;
+    } else {
+      spx->restwav = restwav;
+    }
+    spx->restfrq = C/spx->restwav;
+
+  } else {
+    spx->restfrq = restfrq;
+    spx->restwav = C/restfrq;
+  }
+
+  spx->err = 0x0;
+
+  /* Convert to frequency. */
+  spx->wavetype = 0;
+  spx->velotype = 0;
+  if (strcmp(type, "FREQ") == 0) {
+    if (spec == 0.0) {
+      return wcserr_set(WCSERR_SET(SPXERR_BAD_SPEC_VAR),
+        "Invalid spectral variable: frequency == 0");
+    }
+    spx->freq = spec;
+    spx->wavetype = 1;
+
+  } else if (strcmp(type, "AFRQ") == 0) {
+    if (spec == 0.0) {
+      return wcserr_set(WCSERR_SET(SPXERR_BAD_SPEC_VAR),
+        "Invalid spectral variable: frequency == 0");
+    }
+    spx->freq = spec/(2.0*PI);
+    spx->wavetype = 1;
+
+  } else if (strcmp(type, "ENER") == 0) {
+    if (spec == 0.0) {
+      return wcserr_set(WCSERR_SET(SPXERR_BAD_SPEC_VAR),
+        "Invalid spectral variable: frequency == 0");
+    }
+    spx->freq = spec/h;
+    spx->wavetype = 1;
+
+  } else if (strcmp(type, "WAVN") == 0) {
+    if (spec == 0.0) {
+      return wcserr_set(WCSERR_SET(SPXERR_BAD_SPEC_VAR),
+        "Invalid spectral variable: frequency == 0");
+    }
+    spx->freq = spec*C;
+    spx->wavetype = 1;
+
+  } else if (strcmp(type, "VRAD") == 0) {
+    spx->freq = spx->restfrq*(1.0 - spec/C);
+    spx->velotype = 1;
+
+  } else if (strcmp(type, "WAVE") == 0) {
+    if (spec == 0.0) {
+      return wcserr_set(WCSERR_SET(SPXERR_BAD_SPEC_VAR),
+        "Invalid spectral variable: frequency == 0");
+    }
+    spx->freq = C/spec;
+    spx->wavetype = 1;
+
+  } else if (strcmp(type, "VOPT") == 0) {
+    s = 1.0 + spec/C;
+    if (s == 0.0) {
+      return wcserr_set(WCSERR_SET(SPXERR_BAD_SPEC_VAR),
+        "Invalid spectral variable");
+    }
+    spx->freq = spx->restfrq/s;
+    spx->velotype = 1;
+
+  } else if (strcmp(type, "ZOPT") == 0) {
+    s = 1.0 + spec;
+    if (s == 0.0) {
+      return wcserr_set(WCSERR_SET(SPXERR_BAD_SPEC_VAR),
+        "Invalid spectral variable");
+    }
+    spx->freq = spx->restfrq/s;
+    spx->velotype = 1;
+
+  } else if (strcmp(type, "AWAV") == 0) {
+    if (spec == 0.0) {
+      return wcserr_set(WCSERR_SET(SPXERR_BAD_SPEC_VAR),
+        "Invalid spectral variable");
+    }
+    s = 1.0/spec;
+    s *= s;
+    n  =   2.554e8 / (0.41e14 - s);
+    n += 294.981e8 / (1.46e14 - s);
+    n += 1.000064328;
+    spx->freq = C/(spec*n);
+    spx->wavetype = 1;
+
+  } else if (strcmp(type, "VELO") == 0) {
+    beta = spec/C;
+    if (fabs(beta) == 1.0) {
+      return wcserr_set(WCSERR_SET(SPXERR_BAD_SPEC_VAR),
+        "Invalid spectral variable");
+    }
+    spx->freq = spx->restfrq*(1.0 - beta)/sqrt(1.0 - beta*beta);
+    spx->velotype = 1;
+
+  } else if (strcmp(type, "BETA") == 0) {
+    if (fabs(spec) == 1.0) {
+      return wcserr_set(WCSERR_SET(SPXERR_BAD_SPEC_VAR),
+        "Invalid spectral variable");
+    }
+    spx->freq = spx->restfrq*(1.0 - spec)/sqrt(1.0 - spec*spec);
+    spx->velotype = 1;
+
+  } else {
+    /* Unrecognized type. */
+    return wcserr_set(WCSERR_SET(SPXERR_BAD_SPEC_PARAMS),
+      "Unrecognized spectral type '%s'", type);
+  }
+
+
+  /* Convert frequency to the other spectral types. */
+  n = 1.0;
+  for (k = 0; k < 4; k++) {
+    s = n*spx->freq/C;
+    s *= s;
+    t = 0.41e14 - s;
+    u = 1.46e14 - s;
+    n = 1.000064328 + (2.554e8/t + 294.981e8/u);
+  }
+
+  dwaveawav = n - 2.0*s*(2.554e8/(t*t) + 294.981e8/(u*u));
+
+  s = spx->freq/spx->restfrq;
+
+  spx->ener = spx->freq*h;
+  spx->afrq = spx->freq*(2.0*PI);
+  spx->wavn = spx->freq/C;
+  spx->vrad = C*(1.0 - s);
+  spx->wave = C/spx->freq;
+  spx->awav = spx->wave/n;
+  spx->vopt = C*(1.0/s - 1.0);
+  spx->zopt = spx->vopt/C;
+  spx->velo = C*(1.0 - s*s)/(1.0 + s*s);
+  spx->beta = spx->velo/C;
+
+  /* Compute the required derivatives. */
+  gamma = 1.0/sqrt(1.0 - spx->beta*spx->beta);
+
+  spx->dfreqafrq = 1.0/(2.0*PI);
+  spx->dafrqfreq = 1.0/spx->dfreqafrq;
+
+  spx->dfreqener = 1.0/h;
+  spx->denerfreq = 1.0/spx->dfreqener;
+
+  spx->dfreqwavn = C;
+  spx->dwavnfreq = 1.0/spx->dfreqwavn;
+
+  spx->dfreqvrad = -spx->restfrq/C;
+  spx->dvradfreq = 1.0/spx->dfreqvrad;
+
+  spx->dfreqwave = -spx->freq/spx->wave;
+  spx->dwavefreq = 1.0/spx->dfreqwave;
+
+  spx->dfreqawav = spx->dfreqwave * dwaveawav;
+  spx->dawavfreq = 1.0/spx->dfreqawav;
+
+  spx->dfreqvelo = -gamma*spx->restfrq/(C + spx->velo);
+  spx->dvelofreq = 1.0/spx->dfreqvelo;
+
+  spx->dwavevopt = spx->restwav/C;
+  spx->dvoptwave = 1.0/spx->dwavevopt;
+
+  spx->dwavezopt = spx->restwav;
+  spx->dzoptwave = 1.0/spx->dwavezopt;
+
+  spx->dwaveawav = dwaveawav;
+  spx->dawavwave = 1.0/spx->dwaveawav;
+
+  spx->dwavevelo = gamma*spx->restwav/(C - spx->velo);
+  spx->dvelowave = 1.0/spx->dwavevelo;
+
+  spx->dawavvelo = spx->dwavevelo/dwaveawav;
+  spx->dveloawav = 1.0/spx->dawavvelo;
+
+  spx->dvelobeta = C;
+  spx->dbetavelo = 1.0/spx->dvelobeta;
+
+
+  /* Reset values if no line rest frequency was supplied. */
+  if (haverest) {
+    spx->wavetype = 1;
+    spx->velotype = 1;
+
+  } else {
+    spx->restfrq = 0.0;
+    spx->restwav = 0.0;
+
+    if (!spx->wavetype) {
+      /* Don't have wave characteristic types. */
+      spx->freq = 0.0;
+      spx->afrq = 0.0;
+      spx->ener = 0.0;
+      spx->wavn = 0.0;
+      spx->wave = 0.0;
+      spx->awav = 0.0;
+
+      spx->dfreqwave = 0.0;
+      spx->dwavefreq = 0.0;
+
+      spx->dfreqawav = 0.0;
+      spx->dawavfreq = 0.0;
+
+      spx->dwaveawav = 0.0;
+      spx->dawavwave = 0.0;
+
+    } else {
+      /* Don't have velocity types. */
+      spx->vrad = 0.0;
+      spx->vopt = 0.0;
+      spx->zopt = 0.0;
+      spx->velo = 0.0;
+      spx->beta = 0.0;
+    }
+
+    spx->dfreqvrad = 0.0;
+    spx->dvradfreq = 0.0;
+
+    spx->dfreqvelo = 0.0;
+    spx->dvelofreq = 0.0;
+
+    spx->dwavevopt = 0.0;
+    spx->dvoptwave = 0.0;
+
+    spx->dwavezopt = 0.0;
+    spx->dzoptwave = 0.0;
+
+    spx->dwavevelo = 0.0;
+    spx->dvelowave = 0.0;
+
+    spx->dawavvelo = 0.0;
+    spx->dveloawav = 0.0;
+  }
+
+  return 0;
+}
+
+
+/*============================================================================
+*   Conversions between frequency and vacuum wavelength.
+*===========================================================================*/
+
+int freqwave(dummy, nfreq, sfreq, swave, freq, wave, stat)
+
+double dummy;
+int nfreq, sfreq, swave;
+const double freq[];
+double wave[];
+int stat[];
+
+{
+  int status = 0;
+  register int ifreq, *statp;
+  register const double *freqp;
+  register double *wavep;
+
+  freqp = freq;
+  wavep = wave;
+  statp = stat;
+  for (ifreq = 0; ifreq < nfreq; ifreq++) {
+    if (*freqp != 0.0) {
+      *wavep = C/(*freqp);
+      *(statp++) = 0;
+    } else {
+      *(statp++) = 1;
+      status = SPXERR_BAD_INSPEC_COORD;
+    }
+
+    freqp += sfreq;
+    wavep += swave;
+  }
+
+  return status;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int wavefreq(dummy, nwave, swave, sfreq, wave, freq, stat)
+
+double dummy;
+int nwave, swave, sfreq;
+const double wave[];
+double freq[];
+int stat[];
+
+{
+  int status = 0;
+  register int iwave, *statp;
+  register const double *wavep;
+  register double *freqp;
+
+  wavep = wave;
+  freqp = freq;
+  statp = stat;
+  for (iwave = 0; iwave < nwave; iwave++) {
+    if (*wavep != 0.0) {
+      *freqp = C/(*wavep);
+      *(statp++) = 0;
+    } else {
+      *(statp++) = 1;
+      status = SPXERR_BAD_INSPEC_COORD;
+    }
+
+    wavep += swave;
+    freqp += sfreq;
+  }
+
+  return status;
+}
+
+/*============================================================================
+*   Conversions between frequency and air wavelength.
+*===========================================================================*/
+
+int freqawav(dummy, nfreq, sfreq, sawav, freq, awav, stat)
+
+double dummy;
+int nfreq, sfreq, sawav;
+const double freq[];
+double awav[];
+int stat[];
+
+{
+  int status;
+
+  if ((status = freqwave(dummy, nfreq, sfreq, sawav, freq, awav, stat))) {
+    return status;
+  }
+
+  return waveawav(dummy, nfreq, sawav, sawav, awav, awav, stat);
+}
+
+/*--------------------------------------------------------------------------*/
+
+int awavfreq(dummy, nawav, sawav, sfreq, awav, freq, stat)
+
+double dummy;
+int nawav, sawav, sfreq;
+const double awav[];
+double freq[];
+int stat[];
+
+{
+  int status;
+
+  if ((status = awavwave(dummy, nawav, sawav, sfreq, awav, freq, stat))) {
+    return status;
+  }
+
+  return wavefreq(dummy, nawav, sfreq, sfreq, freq, freq, stat);
+}
+
+/*============================================================================
+*   Conversions between frequency and relativistic velocity.
+*===========================================================================*/
+
+int freqvelo(restfrq, nfreq, sfreq, svelo, freq, velo, stat)
+
+double restfrq;
+int nfreq, sfreq, svelo;
+const double freq[];
+double velo[];
+int stat[];
+
+{
+  double r, s;
+  register int ifreq, *statp;
+  register const double *freqp;
+  register double *velop;
+
+  r = restfrq*restfrq;
+
+  freqp = freq;
+  velop = velo;
+  statp = stat;
+  for (ifreq = 0; ifreq < nfreq; ifreq++) {
+    s = *freqp * *freqp;
+    *velop = C*(r - s)/(r + s);
+    *(statp++) = 0;
+
+    freqp += sfreq;
+    velop += svelo;
+  }
+
+  return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int velofreq(restfrq, nvelo, svelo, sfreq, velo, freq, stat)
+
+double restfrq;
+int nvelo, svelo, sfreq;
+const double velo[];
+double freq[];
+int stat[];
+
+{
+  int status = 0;
+  double s;
+  register int ivelo, *statp;
+  register const double *velop;
+  register double *freqp;
+
+  velop = velo;
+  freqp = freq;
+  statp = stat;
+  for (ivelo = 0; ivelo < nvelo; ivelo++) {
+    s = C + *velop;
+    if (s != 0.0) {
+      *freqp = restfrq*sqrt((C - *velop)/s);
+      *(statp++) = 0;
+    } else {
+      *(statp++) = 1;
+      status = SPXERR_BAD_INSPEC_COORD;
+    }
+
+    velop += svelo;
+    freqp += sfreq;
+  }
+
+  return status;
+}
+
+/*============================================================================
+*   Conversions between vacuum wavelength and air wavelength.
+*===========================================================================*/
+
+int waveawav(dummy, nwave, swave, sawav, wave, awav, stat)
+
+double dummy;
+int nwave, swave, sawav;
+const double wave[];
+double awav[];
+int stat[];
+
+{
+  int status = 0;
+  double n, s;
+  register int iwave, k, *statp;
+  register const double *wavep;
+  register double *awavp;
+
+  wavep = wave;
+  awavp = awav;
+  statp = stat;
+  for (iwave = 0; iwave < nwave; iwave++) {
+    if (*wavep != 0.0) {
+      n = 1.0;
+      for (k = 0; k < 4; k++) {
+        s  = n/(*wavep);
+        s *= s;
+        n  =   2.554e8 / (0.41e14 - s);
+        n += 294.981e8 / (1.46e14 - s);
+        n += 1.000064328;
+      }
+
+      *awavp = (*wavep)/n;
+      *(statp++) = 0;
+    } else {
+      *(statp++) = 1;
+      status = SPXERR_BAD_INSPEC_COORD;
+    }
+
+    wavep += swave;
+    awavp += sawav;
+  }
+
+  return status;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int awavwave(dummy, nawav, sawav, swave, awav, wave, stat)
+
+double dummy;
+int nawav, sawav, swave;
+const double awav[];
+double wave[];
+int stat[];
+
+{
+  int status = 0;
+  double n, s;
+  register int iawav, *statp;
+  register const double *awavp;
+  register double *wavep;
+
+  awavp = awav;
+  wavep = wave;
+  statp = stat;
+  for (iawav = 0; iawav < nawav; iawav++) {
+    if (*awavp != 0.0) {
+      s = 1.0/(*awavp);
+      s *= s;
+      n  =   2.554e8 / (0.41e14 - s);
+      n += 294.981e8 / (1.46e14 - s);
+      n += 1.000064328;
+      *wavep = (*awavp)*n;
+      *(statp++) = 0;
+    } else {
+      *(statp++) = 1;
+      status = SPXERR_BAD_INSPEC_COORD;
+    }
+
+    awavp += sawav;
+    wavep += swave;
+  }
+
+  return status;
+}
+
+/*============================================================================
+*   Conversions between vacuum wavelength and relativistic velocity.
+*===========================================================================*/
+
+int wavevelo(restwav, nwave, swave, svelo, wave, velo, stat)
+
+double restwav;
+int nwave, swave, svelo;
+const double wave[];
+double velo[];
+int stat[];
+
+{
+  double r, s;
+  register int iwave, *statp;
+  register const double *wavep;
+  register double *velop;
+
+  r = restwav*restwav;
+
+  wavep = wave;
+  velop = velo;
+  statp = stat;
+  for (iwave = 0; iwave < nwave; iwave++) {
+    s = *wavep * *wavep;
+    *velop = C*(s - r)/(s + r);
+    *(statp++) = 0;
+
+    wavep += swave;
+    velop += svelo;
+  }
+
+  return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int velowave(restwav, nvelo, svelo, swave, velo, wave, stat)
+
+double restwav;
+int nvelo, svelo, swave;
+const double velo[];
+double wave[];
+int stat[];
+
+{
+  int status = 0;
+  double s;
+  register int ivelo, *statp;
+  register const double *velop;
+  register double *wavep;
+
+  velop = velo;
+  wavep = wave;
+  statp = stat;
+  for (ivelo = 0; ivelo < nvelo; ivelo++) {
+    s = C - *velop;
+    if (s != 0.0) {
+      *wavep = restwav*sqrt((C + *velop)/s);
+      *(statp++) = 0;
+    } else {
+      *(statp++) = 1;
+      status = SPXERR_BAD_INSPEC_COORD;
+    }
+
+    velop += svelo;
+    wavep += swave;
+  }
+
+  return status;
+}
+
+/*============================================================================
+*   Conversions between air wavelength and relativistic velocity.
+*===========================================================================*/
+
+int awavvelo(dummy, nawav, sawav, svelo, awav, velo, stat)
+
+double dummy;
+int nawav, sawav, svelo;
+const double awav[];
+double velo[];
+int stat[];
+
+{
+  int status;
+
+  if ((status = awavwave(dummy, nawav, sawav, svelo, awav, velo, stat))) {
+    return status;
+  }
+
+  return wavevelo(dummy, nawav, svelo, svelo, velo, velo, stat);
+}
+
+/*--------------------------------------------------------------------------*/
+
+int veloawav(dummy, nvelo, svelo, sawav, velo, awav, stat)
+
+double dummy;
+int nvelo, svelo, sawav;
+const double velo[];
+double awav[];
+int stat[];
+
+{
+  int status;
+
+  if ((status = velowave(dummy, nvelo, svelo, sawav, velo, awav, stat))) {
+    return status;
+  }
+
+  return waveawav(dummy, nvelo, sawav, sawav, awav, awav, stat);
+}
+
+/*============================================================================
+*   Conversions between frequency and angular frequency.
+*===========================================================================*/
+
+int freqafrq(dummy, nfreq, sfreq, safrq, freq, afrq, stat)
+
+double dummy;
+int nfreq, sfreq, safrq;
+const double freq[];
+double afrq[];
+int stat[];
+
+{
+  register int ifreq, *statp;
+  register const double *freqp;
+  register double *afrqp;
+
+  freqp = freq;
+  afrqp = afrq;
+  statp = stat;
+  for (ifreq = 0; ifreq < nfreq; ifreq++) {
+    *afrqp = (*freqp)*(2.0*PI);
+    *(statp++) = 0;
+
+    freqp += sfreq;
+    afrqp += safrq;
+  }
+
+  return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int afrqfreq(dummy, nafrq, safrq, sfreq, afrq, freq, stat)
+
+double dummy;
+int nafrq, safrq, sfreq;
+const double afrq[];
+double freq[];
+int stat[];
+
+{
+  register int iafrq, *statp;
+  register const double *afrqp;
+  register double *freqp;
+
+  afrqp = afrq;
+  freqp = freq;
+  statp = stat;
+  for (iafrq = 0; iafrq < nafrq; iafrq++) {
+    *freqp = (*afrqp)/(2.0*PI);
+    *(statp++) = 0;
+
+    afrqp += safrq;
+    freqp += sfreq;
+  }
+
+  return 0;
+}
+
+/*============================================================================
+*   Conversions between frequency and energy.
+*===========================================================================*/
+
+int freqener(dummy, nfreq, sfreq, sener, freq, ener, stat)
+
+double dummy;
+int nfreq, sfreq, sener;
+const double freq[];
+double ener[];
+int stat[];
+
+{
+  register int ifreq, *statp;
+  register const double *freqp;
+  register double *enerp;
+
+  freqp = freq;
+  enerp = ener;
+  statp = stat;
+  for (ifreq = 0; ifreq < nfreq; ifreq++) {
+    *enerp = (*freqp)*h;
+    *(statp++) = 0;
+
+    freqp += sfreq;
+    enerp += sener;
+  }
+
+  return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int enerfreq(dummy, nener, sener, sfreq, ener, freq, stat)
+
+double dummy;
+int nener, sener, sfreq;
+const double ener[];
+double freq[];
+int stat[];
+
+{
+  register int iener, *statp;
+  register const double *enerp;
+  register double *freqp;
+
+  enerp = ener;
+  freqp = freq;
+  statp = stat;
+  for (iener = 0; iener < nener; iener++) {
+    *freqp = (*enerp)/h;
+    *(statp++) = 0;
+
+    enerp += sener;
+    freqp += sfreq;
+  }
+
+  return 0;
+}
+
+/*============================================================================
+*   Conversions between frequency and wave number.
+*===========================================================================*/
+
+int freqwavn(dummy, nfreq, sfreq, swavn, freq, wavn, stat)
+
+double dummy;
+int nfreq, sfreq, swavn;
+const double freq[];
+double wavn[];
+int stat[];
+
+{
+  register int ifreq, *statp;
+  register const double *freqp;
+  register double *wavnp;
+
+  freqp = freq;
+  wavnp = wavn;
+  statp = stat;
+  for (ifreq = 0; ifreq < nfreq; ifreq++) {
+    *wavnp = (*freqp)/C;
+    *(statp++) = 0;
+
+    freqp += sfreq;
+    wavnp += swavn;
+  }
+
+  return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int wavnfreq(dummy, nwavn, swavn, sfreq, wavn, freq, stat)
+
+double dummy;
+int nwavn, swavn, sfreq;
+const double wavn[];
+double freq[];
+int stat[];
+
+{
+  register int iwavn, *statp;
+  register const double *wavnp;
+  register double *freqp;
+
+  wavnp = wavn;
+  freqp = freq;
+  statp = stat;
+  for (iwavn = 0; iwavn < nwavn; iwavn++) {
+    *freqp = (*wavnp)*C;
+    *(statp++) = 0;
+
+    wavnp += swavn;
+    freqp += sfreq;
+  }
+
+  return 0;
+}
+
+/*============================================================================
+*   Conversions between frequency and radio velocity.
+*===========================================================================*/
+
+int freqvrad(restfrq, nfreq, sfreq, svrad, freq, vrad, stat)
+
+double restfrq;
+int nfreq, sfreq, svrad;
+const double freq[];
+double vrad[];
+int stat[];
+
+{
+  double r;
+  register int ifreq, *statp;
+  register const double *freqp;
+  register double *vradp;
+
+  if (restfrq == 0.0) {
+    return SPXERR_BAD_SPEC_PARAMS;
+  }
+  r = C/restfrq;
+
+  freqp = freq;
+  vradp = vrad;
+  statp = stat;
+  for (ifreq = 0; ifreq < nfreq; ifreq++) {
+    *vradp = r*(restfrq - *freqp);
+    *(statp++) = 0;
+
+    freqp += sfreq;
+    vradp += svrad;
+  }
+
+  return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int vradfreq(restfrq, nvrad, svrad, sfreq, vrad, freq, stat)
+
+double restfrq;
+int nvrad, svrad, sfreq;
+const double vrad[];
+double freq[];
+int stat[];
+
+{
+  double r;
+  register int ivrad, *statp;
+  register const double *vradp;
+  register double *freqp;
+
+  r = restfrq/C;
+
+  vradp = vrad;
+  freqp = freq;
+  statp = stat;
+  for (ivrad = 0; ivrad < nvrad; ivrad++) {
+    *freqp = r*(C - *vradp);
+    *(statp++) = 0;
+    vradp += svrad;
+    freqp += sfreq;
+  }
+
+  return 0;
+}
+
+/*============================================================================
+*   Conversions between vacuum wavelength and optical velocity.
+*===========================================================================*/
+
+int wavevopt(restwav, nwave, swave, svopt, wave, vopt, stat)
+
+double restwav;
+int nwave, swave, svopt;
+const double wave[];
+double vopt[];
+int stat[];
+
+{
+  double r;
+  register int iwave, *statp;
+  register const double *wavep;
+  register double *voptp;
+
+  if (restwav == 0.0) {
+    return SPXERR_BAD_SPEC_PARAMS;
+  }
+  r = C/restwav;
+
+  wavep = wave;
+  voptp = vopt;
+  statp = stat;
+  for (iwave = 0; iwave < nwave; iwave++) {
+    *voptp = r*(*wavep) - C;
+    *(statp++) = 0;
+    wavep += swave;
+    voptp += svopt;
+  }
+
+  return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int voptwave(restwav, nvopt, svopt, swave, vopt, wave, stat)
+
+double restwav;
+int nvopt, svopt, swave;
+const double vopt[];
+double wave[];
+int stat[];
+
+{
+  double r;
+  register int ivopt, *statp;
+  register const double *voptp;
+  register double *wavep;
+
+  r = restwav/C;
+
+  voptp = vopt;
+  wavep = wave;
+  statp = stat;
+  for (ivopt = 0; ivopt < nvopt; ivopt++) {
+    *wavep = r*(C + *voptp);
+    *(statp++) = 0;
+    voptp += svopt;
+    wavep += swave;
+  }
+
+  return 0;
+}
+
+/*============================================================================
+*   Conversions between vacuum wavelength and redshift.
+*===========================================================================*/
+
+int wavezopt(restwav, nwave, swave, szopt, wave, zopt, stat)
+
+double restwav;
+int nwave, swave, szopt;
+const double wave[];
+double zopt[];
+int stat[];
+
+{
+  double r;
+  register int iwave, *statp;
+  register const double *wavep;
+  register double *zoptp;
+
+  if (restwav == 0.0) {
+    return SPXERR_BAD_SPEC_PARAMS;
+  }
+  r = 1.0/restwav;
+
+  wavep = wave;
+  zoptp = zopt;
+  statp = stat;
+  for (iwave = 0; iwave < nwave; iwave++) {
+    *zoptp = r*(*wavep) - 1.0;
+    *(statp++) = 0;
+    wavep += swave;
+    zoptp += szopt;
+  }
+
+  return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int zoptwave(restwav, nzopt, szopt, swave, zopt, wave, stat)
+
+double restwav;
+int nzopt, szopt, swave;
+const double zopt[];
+double wave[];
+int stat[];
+
+{
+  register int izopt, *statp;
+  register const double *zoptp;
+  register double *wavep;
+
+  zoptp = zopt;
+  wavep = wave;
+  statp = stat;
+  for (izopt = 0; izopt < nzopt; izopt++) {
+    *wavep = restwav*(1.0 + *zoptp);
+    *(statp++) = 0;
+    zoptp += szopt;
+    wavep += swave;
+  }
+
+  return 0;
+}
+
+/*============================================================================
+*   Conversions between relativistic velocity and beta (= v/c).
+*===========================================================================*/
+
+int velobeta(dummy, nvelo, svelo, sbeta, velo, beta, stat)
+
+double dummy;
+int nvelo, svelo, sbeta;
+const double velo[];
+double beta[];
+int stat[];
+
+{
+  register int ivelo, *statp;
+  register const double *velop;
+  register double *betap;
+
+  velop = velo;
+  betap = beta;
+  statp = stat;
+  for (ivelo = 0; ivelo < nvelo; ivelo++) {
+    *betap = (*velop)/C;
+    *(statp++) = 0;
+
+    velop += svelo;
+    betap += sbeta;
+  }
+
+  return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int betavelo(dummy, nbeta, sbeta, svelo, beta, velo, stat)
+
+double dummy;
+int nbeta, sbeta, svelo;
+const double beta[];
+double velo[];
+int stat[];
+
+{
+  register int ibeta, *statp;
+  register const double *betap;
+  register double *velop;
+
+  betap = beta;
+  velop = velo;
+  statp = stat;
+  for (ibeta = 0; ibeta < nbeta; ibeta++) {
+    *velop = (*betap)*C;
+    *(statp++) = 0;
+
+    betap += sbeta;
+    velop += svelo;
+  }
+
+  return 0;
+}
diff --git a/cextern/wcslib/C/spx.h b/cextern/wcslib/C/spx.h
new file mode 100644
index 0000000..33f2067
--- /dev/null
+++ b/cextern/wcslib/C/spx.h
@@ -0,0 +1,538 @@
+/*============================================================================
+
+  WCSLIB 4.16 - an implementation of the FITS WCS standard.
+  Copyright (C) 1995-2012, Mark Calabretta
+
+  This file is part of WCSLIB.
+
+  WCSLIB is free software: you can redistribute it and/or modify it under the
+  terms of the GNU Lesser General Public License as published by the Free
+  Software Foundation, either version 3 of the License, or (at your option)
+  any later version.
+
+  WCSLIB 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 Lesser General Public License for
+  more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with WCSLIB.  If not, see http://www.gnu.org/licenses.
+
+  Direct correspondence concerning WCSLIB to mark at calabretta.id.au
+
+  Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
+  http://www.atnf.csiro.au/people/Mark.Calabretta
+  $Id: spx.h,v 4.16 2012/11/07 04:42:44 cal103 Exp $
+*=============================================================================
+*
+* WCSLIB 4.16 - C routines that implement the spectral coordinate systems
+* recognized by the FITS World Coordinate System (WCS) standard.  Refer to
+*
+*   "Representations of world coordinates in FITS",
+*   Greisen, E.W., & Calabretta, M.R. 2002, A&A, 395, 1061 (Paper I)
+*
+*   "Representations of spectral coordinates in FITS",
+*   Greisen, E.W., Calabretta, M.R., Valdes, F.G., & Allen, S.L.
+*   2006, A&A, 446, 747 (Paper III)
+*
+* Refer to the README file provided with WCSLIB for an overview of the
+* library.
+*
+*
+* Summary of the spx routines
+* ---------------------------
+* specx() is a scalar routine that, given one spectral variable (e.g.
+* frequency), computes all the others (e.g. wavelength, velocity, etc.) plus
+* the required derivatives of each with respect to the others.  The results
+* are returned in the spxprm struct.
+*
+* The remaining routines are all vector conversions from one spectral
+* variable to another.  The API of these functions only differ in whether the
+* rest frequency or wavelength need be supplied.
+*
+* Non-linear:
+*   - freqwave()    frequency              ->  vacuum wavelength
+*   - wavefreq()    vacuum wavelength      ->  frequency
+*
+*   - freqawav()    frequency              ->  air wavelength
+*   - awavfreq()    air wavelength         ->  frequency
+*
+*   - freqvelo()    frequency              ->  relativistic velocity
+*   - velofreq()    relativistic velocity  ->  frequency
+*
+*   - waveawav()    vacuum wavelength      ->  air wavelength
+*   - awavwave()    air wavelength         ->  vacuum wavelength
+*
+*   - wavevelo()    vacuum wavelength      ->  relativistic velocity
+*   - velowave()    relativistic velocity  ->  vacuum wavelength
+*
+*   - awavvelo()    air wavelength         ->  relativistic velocity
+*   - veloawav()    relativistic velocity  ->  air wavelength
+*
+* Linear:
+*   - freqafrq()    frequency              ->  angular frequency
+*   - afrqfreq()    angular frequency      ->  frequency
+*
+*   - freqener()    frequency              ->  energy
+*   - enerfreq()    energy                 ->  frequency
+*
+*   - freqwavn()    frequency              ->  wave number
+*   - wavnfreq()    wave number            ->  frequency
+*
+*   - freqvrad()    frequency              ->  radio velocity
+*   - vradfreq()    radio velocity         ->  frequency
+*
+*   - wavevopt()    vacuum wavelength      ->  optical velocity
+*   - voptwave()    optical velocity       ->  vacuum wavelength
+*
+*   - wavezopt()    vacuum wavelength      ->  redshift
+*   - zoptwave()    redshift               ->  vacuum wavelength
+*
+*   - velobeta()    relativistic velocity  ->  beta (= v/c)
+*   - betavelo()    beta (= v/c)           ->  relativistic velocity
+*
+* These are the workhorse routines, to be used for fast transformations.
+* Conversions may be done "in place" by calling the routine with the output
+* vector set to the input.
+*
+* Argument checking:
+* ------------------
+* The input spectral values are only checked for values that would result
+* in floating point exceptions.  In particular, negative frequencies and
+* wavelengths are allowed, as are velocities greater than the speed of
+* light.  The same is true for the spectral parameters - rest frequency and
+* wavelength.
+*
+* Accuracy:
+* ---------
+* No warranty is given for the accuracy of these routines (refer to the
+* copyright notice); intending users must satisfy for themselves their
+* adequacy for the intended purpose.  However, closure effectively to within
+* double precision rounding error was demonstrated by test routine tspec.c
+* which accompanies this software.
+*
+*
+* specx() - Spectral cross conversions (scalar)
+* ---------------------------------------------
+* Given one spectral variable specx() computes all the others, plus the
+* required derivatives of each with respect to the others.
+*
+* Given:
+*   type      const char*
+*                       The type of spectral variable given by spec, FREQ,
+*                       AFRQ, ENER, WAVN, VRAD, WAVE, VOPT, ZOPT, AWAV, VELO,
+*                       or BETA (case sensitive).
+*
+*   spec      double    The spectral variable given, in SI units.
+*
+*   restfrq,
+*   restwav   double    Rest frequency [Hz] or rest wavelength in vacuo [m],
+*                       only one of which need be given.  The other should be
+*                       set to zero.  If both are zero, only a subset of the
+*                       spectral variables can be computed, the remainder are
+*                       set to zero.  Specifically, given one of FREQ, AFRQ,
+*                       ENER, WAVN, WAVE, or AWAV the others can be computed
+*                       without knowledge of the rest frequency.  Likewise,
+*                       VRAD, VOPT, ZOPT, VELO, and BETA.
+*
+* Given and returned:
+*   specs     struct spxprm*
+*                       Data structure containing all spectral variables and
+*                       their derivatives, in SI units.
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         1: Null spxprm pointer passed.
+*                         2: Invalid spectral parameters.
+*                         3: Invalid spectral variable.
+*
+*                       For returns > 1, a detailed error message is set in
+*                       spxprm::err if enabled, see wcserr_enable().
+*
+* freqafrq(), afrqfreq(), freqener(), enerfreq(), freqwavn(), wavnfreq(),
+* freqwave(), wavefreq(), freqawav(), awavfreq(), waveawav(), awavwave(),
+* velobeta(), and betavelo() implement vector conversions between wave-like
+* or velocity-like spectral types (i.e. conversions that do not need the rest
+* frequency or wavelength).  They all have the same API.
+*
+*
+* freqafrq() - Convert frequency to angular frequency (vector)
+* ------------------------------------------------------------
+* freqafrq() converts frequency to angular frequency.
+*
+* Given:
+*   param     double    Ignored.
+*
+*   nspec     int       Vector length.
+*
+*   instep,
+*   outstep   int       Vector strides.
+*
+*   inspec    const double[]
+*                       Input spectral variables, in SI units.
+*
+* Returned:
+*   outspec   double[]  Output spectral variables, in SI units.
+*
+*   stat      int[]     Status return value for each vector element:
+*                         0: Success.
+*                         1: Invalid value of inspec.
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         2: Invalid spectral parameters.
+*                         4: One or more of the inspec coordinates were
+*                            invalid, as indicated by the stat vector.
+*
+*
+* freqvelo(), velofreq(), freqvrad(), and vradfreq() implement vector
+* conversions between frequency and velocity spectral types.  They all have
+* the same API.
+*
+*
+* freqvelo() - Convert frequency to relativistic velocity (vector)
+* ----------------------------------------------------------------
+* freqvelo() converts frequency to relativistic velocity.
+*
+* Given:
+*   param     double    Rest frequency [Hz].
+*
+*   nspec     int       Vector length.
+*
+*   instep,
+*   outstep   int       Vector strides.
+*
+*   inspec    const double[]
+*                       Input spectral variables, in SI units.
+*
+* Returned:
+*   outspec   double[]  Output spectral variables, in SI units.
+*
+*   stat      int[]     Status return value for each vector element:
+*                         0: Success.
+*                         1: Invalid value of inspec.
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         2: Invalid spectral parameters.
+*                         4: One or more of the inspec coordinates were
+*                            invalid, as indicated by the stat vector.
+*
+*
+* wavevelo(), velowave(), awavvelo(), veloawav(), wavevopt(), voptwave(),
+* wavezopt(), and zoptwave() implement vector conversions between wavelength
+* and velocity spectral types.  They all have the same API.
+*
+*
+* wavevelo() - Conversions between wavelength and velocity types (vector)
+* -----------------------------------------------------------------------
+* wavevelo() converts vacuum wavelength to relativistic velocity.
+*
+* Given:
+*   param     double    Rest wavelength in vacuo [m].
+*
+*   nspec     int       Vector length.
+*
+*   instep,
+*   outstep   int       Vector strides.
+*
+*   inspec    const double[]
+*                       Input spectral variables, in SI units.
+*
+* Returned:
+*   outspec   double[]  Output spectral variables, in SI units.
+*
+*   stat      int[]     Status return value for each vector element:
+*                         0: Success.
+*                         1: Invalid value of inspec.
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         2: Invalid spectral parameters.
+*                         4: One or more of the inspec coordinates were
+*                            invalid, as indicated by the stat vector.
+*
+*
+* spxprm struct - Spectral variables and their derivatives
+* --------------------------------------------------------
+* The spxprm struct contains the value of all spectral variables and their
+* derivatives.   It is used solely by specx() which constructs it from
+* information provided via its function arguments.
+*
+* This struct should be considered read-only, no members need ever be set nor
+* should ever be modified by the user.
+*
+*   double restfrq
+*     (Returned) Rest frequency [Hz].
+*
+*   double restwav
+*     (Returned) Rest wavelength [m].
+*
+*   int wavetype
+*     (Returned) True if wave types have been computed, and ...
+*
+*   int velotype
+*     (Returned) ... true if velocity types have been computed; types are
+*     defined below.
+*
+*     If one or other of spxprm::restfrq and spxprm::restwav is given
+*     (non-zero) then all spectral variables may be computed.  If both are
+*     given, restfrq is used.  If restfrq and restwav are both zero, only wave
+*     characteristic xor velocity type spectral variables may be computed
+*     depending on the variable given.   These flags indicate what is
+*     available.
+*
+*   double freq
+*     (Returned) Frequency [Hz] (wavetype).
+*
+*   double afrq
+*     (Returned) Angular frequency [rad/s] (wavetype).
+*
+*   double ener
+*     (Returned) Photon energy [J] (wavetype).
+*
+*   double wavn
+*     (Returned) Wave number [/m] (wavetype).
+*
+*   double vrad
+*     (Returned) Radio velocity [m/s] (velotype).
+*
+*   double wave
+*     (Returned) Vacuum wavelength [m] (wavetype).
+*
+*   double vopt
+*     (Returned) Optical velocity [m/s] (velotype).
+*
+*   double zopt
+*     (Returned) Redshift [dimensionless] (velotype).
+*
+*   double awav
+*     (Returned) Air wavelength [m] (wavetype).
+*
+*   double velo
+*     (Returned) Relativistic velocity [m/s] (velotype).
+*
+*   double beta
+*     (Returned) Relativistic beta [dimensionless] (velotype).
+*
+*   double dfreqafrq
+*     (Returned) Derivative of frequency with respect to angular frequency
+*     [/rad] (constant, = 1 / 2*pi), and ...
+*   double dafrqfreq
+*     (Returned) ... vice versa [rad] (constant, = 2*pi, always available).
+*
+*   double dfreqener
+*     (Returned) Derivative of frequency with respect to photon energy
+*     [/J/s] (constant, = 1/h), and ...
+*   double denerfreq
+*     (Returned) ... vice versa [Js] (constant, = h, Planck's constant,
+*     always available).
+*
+*   double dfreqwavn
+*     (Returned) Derivative of frequency with respect to wave number [m/s]
+*     (constant, = c, the speed of light in vacuuo), and ...
+*   double dwavnfreq
+*     (Returned) ... vice versa [s/m] (constant, = 1/c, always available).
+*
+*   double dfreqvrad
+*     (Returned) Derivative of frequency with respect to radio velocity [/m],
+*     and ...
+*   double dvradfreq
+*     (Returned) ... vice versa [m] (wavetype && velotype).
+*
+*   double dfreqwave
+*     (Returned) Derivative of frequency with respect to vacuum wavelength
+*     [/m/s], and ...
+*   double dwavefreq
+*     (Returned) ... vice versa [m s] (wavetype).
+*
+*   double dfreqawav
+*     (Returned) Derivative of frequency with respect to air wavelength,
+*     [/m/s], and ...
+*   double dawavfreq
+*     (Returned) ... vice versa [m s] (wavetype).
+*
+*   double dfreqvelo
+*     (Returned) Derivative of frequency with respect to relativistic
+*     velocity [/m], and ...
+*   double dvelofreq
+*     (Returned) ... vice versa [m] (wavetype && velotype).
+*
+*   double dwavevopt
+*     (Returned) Derivative of vacuum wavelength with respect to optical
+*     velocity [s], and ...
+*   double dvoptwave
+*     (Returned) ... vice versa [/s] (wavetype && velotype).
+*
+*   double dwavezopt
+*     (Returned) Derivative of vacuum wavelength with respect to redshift [m],
+*     and ...
+*   double dzoptwave
+*     (Returned) ... vice versa [/m] (wavetype && velotype).
+*
+*   double dwaveawav
+*     (Returned) Derivative of vacuum wavelength with respect to air
+*     wavelength [dimensionless], and ...
+*   double dawavwave
+*     (Returned) ... vice versa [dimensionless] (wavetype).
+*
+*   double dwavevelo
+*     (Returned) Derivative of vacuum wavelength with respect to relativistic
+*     velocity [s], and ...
+*   double dvelowave
+*     (Returned) ... vice versa [/s] (wavetype && velotype).
+*
+*   double dawavvelo
+*     (Returned) Derivative of air wavelength with respect to relativistic
+*     velocity [s], and ...
+*   double dveloawav
+*     (Returned) ... vice versa [/s] (wavetype && velotype).
+*
+*   double dvelobeta
+*     (Returned) Derivative of relativistic velocity with respect to
+*     relativistic beta [m/s] (constant, = c, the speed of light in vacuu0),
+*     and ...
+*   double dbetavelo
+*     (Returned) ... vice versa [s/m] (constant, = 1/c, always available).
+*
+*   struct wcserr *err
+*     (Returned) If enabled, when an error status is returned this struct
+*     contains detailed information about the error, see wcserr_enable().
+*
+*   void *padding
+*     (An unused variable inserted for alignment purposes only.)
+*
+* Global variable: const char *spx_errmsg[] - Status return messages
+* ------------------------------------------------------------------
+* Error messages to match the status value returned from each function.
+*
+*===========================================================================*/
+
+#ifndef WCSLIB_SPEC
+#define WCSLIB_SPEC
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "wcserr.h"
+
+extern const char *spx_errmsg[];
+
+enum spx_errmsg {
+  SPXERR_SUCCESS          = 0,	/* Success. */
+  SPXERR_NULL_POINTER     = 1,	/* Null spxprm pointer passed. */
+  SPXERR_BAD_SPEC_PARAMS  = 2,	/* Invalid spectral parameters. */
+  SPXERR_BAD_SPEC_VAR     = 3,	/* Invalid spectral variable. */
+  SPXERR_BAD_INSPEC_COORD = 4 	/* One or more of the inspec coordinates were
+				   invalid. */
+};
+
+struct spxprm {
+  double restfrq, restwav;	/* Rest frequency [Hz] and wavelength [m].  */
+
+  int wavetype, velotype;	/* True if wave/velocity types have been    */
+				/* computed; types are defined below.       */
+
+  /* Spectral variables computed by specx().                                */
+  /*------------------------------------------------------------------------*/
+  double freq,			/* wavetype: Frequency [Hz].                */
+         afrq,			/* wavetype: Angular frequency [rad/s].     */
+         ener,			/* wavetype: Photon energy [J].             */
+         wavn,			/* wavetype: Wave number [/m].              */
+         vrad,			/* velotype: Radio velocity [m/s].          */
+         wave,			/* wavetype: Vacuum wavelength [m].         */
+         vopt,			/* velotype: Optical velocity [m/s].        */
+         zopt,			/* velotype: Redshift.                      */
+         awav,			/* wavetype: Air wavelength [m].            */
+         velo,			/* velotype: Relativistic velocity [m/s].   */
+         beta;			/* velotype: Relativistic beta.             */
+
+  /* Derivatives of spectral variables computed by specx().                 */
+  /*------------------------------------------------------------------------*/
+  double dfreqafrq, dafrqfreq,	/* Constant, always available.              */
+         dfreqener, denerfreq,	/* Constant, always available.              */
+         dfreqwavn, dwavnfreq,	/* Constant, always available.              */
+         dfreqvrad, dvradfreq,	/* wavetype && velotype.                    */
+         dfreqwave, dwavefreq,	/* wavetype.                                */
+         dfreqawav, dawavfreq,	/* wavetype.                                */
+         dfreqvelo, dvelofreq,	/* wavetype && velotype.                    */
+         dwavevopt, dvoptwave,	/* wavetype && velotype.                    */
+         dwavezopt, dzoptwave,	/* wavetype && velotype.                    */
+         dwaveawav, dawavwave,	/* wavetype.                                */
+         dwavevelo, dvelowave,	/* wavetype && velotype.                    */
+         dawavvelo, dveloawav,	/* wavetype && velotype.                    */
+         dvelobeta, dbetavelo;	/* Constant, always available.              */
+
+  /* Error handling                                                         */
+  /*------------------------------------------------------------------------*/
+  struct wcserr *err;
+
+  /* Private                                                                */
+  /*------------------------------------------------------------------------*/
+  void   *padding;		/* (Dummy inserted for alignment purposes.) */
+};
+
+/* Size of the spxprm struct in int units, used by the Fortran wrappers. */
+#define SPXLEN (sizeof(struct spxprm)/sizeof(int))
+
+
+int specx(const char *type, double spec, double restfrq, double restwav,
+          struct spxprm *specs);
+
+
+/* For use in declaring function prototypes, e.g. in spcprm. */
+#define SPX_ARGS double param, int nspec, int instep, int outstep, \
+    const double inspec[], double outspec[], int stat[]
+
+int freqafrq(SPX_ARGS);
+int afrqfreq(SPX_ARGS);
+
+int freqener(SPX_ARGS);
+int enerfreq(SPX_ARGS);
+
+int freqwavn(SPX_ARGS);
+int wavnfreq(SPX_ARGS);
+
+int freqwave(SPX_ARGS);
+int wavefreq(SPX_ARGS);
+
+int freqawav(SPX_ARGS);
+int awavfreq(SPX_ARGS);
+
+int waveawav(SPX_ARGS);
+int awavwave(SPX_ARGS);
+
+int velobeta(SPX_ARGS);
+int betavelo(SPX_ARGS);
+
+
+int freqvelo(SPX_ARGS);
+int velofreq(SPX_ARGS);
+
+int freqvrad(SPX_ARGS);
+int vradfreq(SPX_ARGS);
+
+
+int wavevelo(SPX_ARGS);
+int velowave(SPX_ARGS);
+
+int awavvelo(SPX_ARGS);
+int veloawav(SPX_ARGS);
+
+int wavevopt(SPX_ARGS);
+int voptwave(SPX_ARGS);
+
+int wavezopt(SPX_ARGS);
+int zoptwave(SPX_ARGS);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* WCSLIB_SPEC */
diff --git a/cextern/wcslib/C/tab.c b/cextern/wcslib/C/tab.c
new file mode 100644
index 0000000..c877b20
--- /dev/null
+++ b/cextern/wcslib/C/tab.c
@@ -0,0 +1,1583 @@
+/*============================================================================
+
+  WCSLIB 4.16 - an implementation of the FITS WCS standard.
+  Copyright (C) 1995-2012, Mark Calabretta
+
+  This file is part of WCSLIB.
+
+  WCSLIB is free software: you can redistribute it and/or modify it under the
+  terms of the GNU Lesser General Public License as published by the Free
+  Software Foundation, either version 3 of the License, or (at your option)
+  any later version.
+
+  WCSLIB 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 Lesser General Public License for
+  more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with WCSLIB.  If not, see http://www.gnu.org/licenses.
+
+  Direct correspondence concerning WCSLIB to mark at calabretta.id.au
+
+  Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
+  http://www.atnf.csiro.au/people/Mark.Calabretta
+  $Id: tab.c,v 4.16 2012/11/07 04:42:44 cal103 Exp $
+*===========================================================================*/
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "wcserr.h"
+#include "wcsmath.h"
+#include "wcsprintf.h"
+#include "tab.h"
+
+const int TABSET = 137;
+
+/* Map status return value to message. */
+const char *tab_errmsg[] = {
+  "Success",
+  "Null tabprm pointer passed",
+  "Memory allocation failed",
+  "Invalid tabular parameters",
+  "One or more of the x coordinates were invalid",
+  "One or more of the world coordinates were invalid"};
+
+/* Convenience macro for invoking wcserr_set(). */
+#define TAB_ERRMSG(status) WCSERR_SET(status), tab_errmsg[status]
+
+/*--------------------------------------------------------------------------*/
+
+int tabini(int alloc, int M, const int K[], struct tabprm *tab)
+
+{
+  static const char *function = "tabini";
+
+  int k, m, N;
+  double *dp;
+  struct wcserr **err;
+
+  if (tab == 0x0) return TABERR_NULL_POINTER;
+
+  /* Initialize error message handling. */
+  err = &(tab->err);
+  if (tab->err && tab->flag != -1) {
+    free(tab->err);
+  }
+  tab->err = 0x0;
+
+
+  if (M <= 0) {
+    return wcserr_set(WCSERR_SET(TABERR_BAD_PARAMS),
+      "M must be positive, got %d", M);
+  }
+
+  /* Determine the total number of elements in the coordinate array. */
+  if (K) {
+    N = M;
+
+    for (m = 0; m < M; m++) {
+      if (K[m] < 0) {
+        return wcserr_set(WCSERR_SET(TABERR_BAD_PARAMS),
+          "Invalid tabular parameters: Each element of K must be "
+          "non-negative, got %d", K[m]);
+      }
+
+      N *= K[m];
+    }
+
+  } else {
+    /* Axis lengths as yet unknown. */
+    N = 0;
+  }
+
+
+  /* Initialize memory management. */
+  if (tab->flag == -1 || tab->m_flag != TABSET) {
+    tab->m_flag  = 0;
+    tab->m_M     = 0;
+    tab->m_N     = 0;
+    tab->m_K     = 0x0;
+    tab->m_map   = 0x0;
+    tab->m_crval = 0x0;
+    tab->m_index = 0x0;
+    tab->m_indxs = 0x0;
+    tab->m_coord = 0x0;
+
+  } else {
+    /* Clear any outstanding signals set by wcstab(). */
+    for (m = 0; m < tab->m_M; m++) {
+      if (tab->m_indxs[m] == (double *)0x1) tab->m_indxs[m] = 0x0;
+    }
+
+    if (tab->m_coord == (double *)0x1) tab->m_coord = 0x0;
+  }
+
+  if (tab->flag == -1) {
+    tab->sense   = 0x0;
+    tab->p0      = 0x0;
+    tab->delta   = 0x0;
+    tab->extrema = 0x0;
+    tab->set_M   = 0;
+  }
+
+
+  /* Allocate memory for arrays if required. */
+  if (alloc ||
+     tab->K == 0x0 ||
+     tab->map == 0x0 ||
+     tab->crval == 0x0 ||
+     tab->index == 0x0 ||
+     tab->coord == 0x0) {
+
+    /* Was sufficient allocated previously? */
+    if (tab->m_flag == TABSET && (tab->m_M < M || tab->m_N < N)) {
+      /* No, free it. */
+      tabfree(tab);
+    }
+
+    if (alloc || tab->K == 0x0) {
+      if (tab->m_K) {
+        /* In case the caller fiddled with it. */
+        tab->K = tab->m_K;
+
+      } else {
+        if (!(tab->K = calloc(M, sizeof(int)))) {
+          return wcserr_set(TAB_ERRMSG(TABERR_MEMORY));
+        }
+
+        tab->m_flag = TABSET;
+        tab->m_M = M;
+        tab->m_K = tab->K;
+      }
+    }
+
+    if (alloc || tab->map == 0x0) {
+      if (tab->m_map) {
+        /* In case the caller fiddled with it. */
+        tab->map = tab->m_map;
+
+      } else {
+        if (!(tab->map = calloc(M, sizeof(int)))) {
+          return wcserr_set(TAB_ERRMSG(TABERR_MEMORY));
+        }
+
+        tab->m_flag = TABSET;
+        tab->m_M = M;
+        tab->m_map = tab->map;
+      }
+    }
+
+    if (alloc || tab->crval == 0x0) {
+      if (tab->m_crval) {
+        /* In case the caller fiddled with it. */
+        tab->crval = tab->m_crval;
+
+      } else {
+        if (!(tab->crval = calloc(M, sizeof(double)))) {
+          return wcserr_set(TAB_ERRMSG(TABERR_MEMORY));
+        }
+
+        tab->m_flag = TABSET;
+        tab->m_M = M;
+        tab->m_crval = tab->crval;
+      }
+    }
+
+    if (alloc || tab->index == 0x0) {
+      if (tab->m_index) {
+        /* In case the caller fiddled with it. */
+        tab->index = tab->m_index;
+
+      } else {
+        if (!(tab->index = calloc(M, sizeof(double *)))) {
+          return wcserr_set(TAB_ERRMSG(TABERR_MEMORY));
+        }
+
+        tab->m_flag = TABSET;
+        tab->m_M = M;
+        tab->m_N = N;
+        tab->m_index = tab->index;
+
+        if (!(tab->m_indxs = calloc(M, sizeof(double *)))) {
+          return wcserr_set(TAB_ERRMSG(TABERR_MEMORY));
+        }
+
+        /* Recall that calloc() initializes these pointers to zero. */
+        if (K) {
+          for (m = 0; m < M; m++) {
+            if (K[m]) {
+              if (!(tab->index[m] = calloc(K[m], sizeof(double)))) {
+                return wcserr_set(TAB_ERRMSG(TABERR_MEMORY));
+              }
+
+              tab->m_indxs[m] = tab->index[m];
+            }
+          }
+        }
+      }
+    }
+
+    if (alloc || tab->coord == 0x0) {
+      if (tab->m_coord) {
+        /* In case the caller fiddled with it. */
+        tab->coord = tab->m_coord;
+
+      } else if (N) {
+        if (!(tab->coord = calloc(N, sizeof(double)))) {
+          return wcserr_set(TAB_ERRMSG(TABERR_MEMORY));
+        }
+
+        tab->m_flag = TABSET;
+        tab->m_M = M;
+        tab->m_N = N;
+        tab->m_coord = tab->coord;
+      }
+    }
+  }
+
+  tab->flag = 0;
+  tab->M = M;
+
+  /* Set defaults. */
+  for (m = 0; m < M; m++) {
+    tab->map[m] = -1;
+    tab->crval[m] = 0.0;
+
+    if (K) {
+      tab->K[m] = K[m];
+      if ((dp = tab->index[m])) {
+        for (k = 0; k < K[m]; k++) {
+          *(dp++) = k;
+        }
+      }
+    } else {
+      tab->K[m] = 0;
+    }
+  }
+
+  /* Initialize the coordinate array. */
+  for (dp = tab->coord; dp < tab->coord + N; dp++) {
+    *dp = UNDEFINED;
+  }
+
+  return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int tabmem(struct tabprm *tab)
+
+{
+  static const char *function = "tabmem";
+
+  int m, M, N;
+  struct wcserr **err;
+
+  if (tab == 0x0) return TABERR_NULL_POINTER;
+  err = &(tab->err);
+
+  if (tab->M == 0 || tab->K == 0x0) {
+    /* Should have been set by this time. */
+    return wcserr_set(WCSERR_SET(TABERR_MEMORY),
+      "Null pointers in tabprm struct");
+  }
+
+
+  N = M = tab->M;
+  for (m = 0; m < M; m++) {
+    if (tab->K[m] < 0) {
+      return wcserr_set(WCSERR_SET(TABERR_BAD_PARAMS),
+        "Invalid tabular parameters: Each element of K must be "
+        "non-negative, got %d", M);
+    }
+
+    N *= tab->K[m];
+  }
+
+
+  if (tab->m_M == 0) {
+    tab->m_M = M;
+  } else if (tab->m_M < M) {
+    /* Only possible if the user changed M. */
+    return wcserr_set(WCSERR_SET(TABERR_MEMORY),
+      "tabprm struct inconsistent");
+  }
+
+  if (tab->m_N == 0) {
+    tab->m_N = N;
+  } else if (tab->m_N < N) {
+    /* Only possible if the user changed K[]. */
+    return wcserr_set(WCSERR_SET(TABERR_MEMORY),
+      "tabprm struct inconsistent");
+  }
+
+  if (tab->m_K == 0x0) {
+    if ((tab->m_K = tab->K)) {
+      tab->m_flag = TABSET;
+    }
+  }
+
+  if (tab->m_map == 0x0) {
+    if ((tab->m_map = tab->map)) {
+      tab->m_flag = TABSET;
+    }
+  }
+
+  if (tab->m_crval == 0x0) {
+    if ((tab->m_crval = tab->crval)) {
+      tab->m_flag = TABSET;
+    }
+  }
+
+  if (tab->m_index == 0x0) {
+    if ((tab->m_index = tab->index)) {
+      tab->m_flag = TABSET;
+    }
+  }
+
+  for (m = 0; m < tab->m_M; m++) {
+    if (tab->m_indxs[m] == 0x0 || tab->m_indxs[m] == (double *)0x1) {
+      if ((tab->m_indxs[m] = tab->index[m])) {
+        tab->m_flag = TABSET;
+      }
+    }
+  }
+
+  if (tab->m_coord == 0x0 || tab->m_coord == (double *)0x1) {
+    if ((tab->m_coord = tab->coord)) {
+      tab->m_flag = TABSET;
+    }
+  }
+
+  tab->flag = 0;
+
+  return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int tabcpy(int alloc, const struct tabprm *tabsrc, struct tabprm *tabdst)
+
+{
+  static const char *function = "tabcpy";
+
+  int k, m, M, n, N, status;
+  double *dstp, *srcp;
+  struct wcserr **err;
+
+  if (tabsrc == 0x0) return TABERR_NULL_POINTER;
+  if (tabdst == 0x0) return TABERR_NULL_POINTER;
+  err = &(tabdst->err);
+
+  M = tabsrc->M;
+  if (M <= 0) {
+    return wcserr_set(WCSERR_SET(TABERR_BAD_PARAMS),
+      "M must be positive, got %d", M);
+  }
+
+  if ((status = tabini(alloc, M, tabsrc->K, tabdst))) {
+    return status;
+  }
+
+  N = M;
+  for (m = 0; m < M; m++) {
+    tabdst->map[m]   = tabsrc->map[m];
+    tabdst->crval[m] = tabsrc->crval[m];
+    N *= tabsrc->K[m];
+  }
+
+  for (m = 0; m < M; m++) {
+    if ((srcp = tabsrc->index[m])) {
+      dstp = tabdst->index[m];
+      for (k = 0; k < tabsrc->K[m]; k++) {
+        *(dstp++) = *(srcp++);
+      }
+    }
+  }
+
+  srcp = tabsrc->coord;
+  dstp = tabdst->coord;
+  for (n = 0; n < N; n++) {
+    *(dstp++) = *(srcp++);
+  }
+
+  return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int tabfree(struct tabprm *tab)
+
+{
+  int m;
+
+  if (tab == 0x0) return TABERR_NULL_POINTER;
+
+  if (tab->flag != -1) {
+    /* Clear any outstanding signals set by wcstab(). */
+    for (m = 0; m < tab->m_M; m++) {
+      if (tab->m_indxs[m] == (double *)0x1) tab->m_indxs[m] = 0x0;
+    }
+
+    if (tab->m_coord == (double *)0x1) tab->m_coord = 0x0;
+
+    /* Free memory allocated by tabini(). */
+    if (tab->m_flag == TABSET) {
+      if (tab->K     == tab->m_K)     tab->K = 0x0;
+      if (tab->map   == tab->m_map)   tab->map = 0x0;
+      if (tab->crval == tab->m_crval) tab->crval = 0x0;
+      if (tab->index == tab->m_index) tab->index = 0x0;
+      if (tab->coord == tab->m_coord) tab->coord = 0x0;
+
+      if (tab->m_K)     free(tab->m_K);
+      if (tab->m_map)   free(tab->m_map);
+      if (tab->m_crval) free(tab->m_crval);
+
+      if (tab->m_index) {
+        for (m = 0; m < tab->m_M; m++) {
+          if (tab->m_indxs[m]) free(tab->m_indxs[m]);
+        }
+        free(tab->m_index);
+        free(tab->m_indxs);
+      }
+
+      if (tab->m_coord) free(tab->m_coord);
+    }
+
+    /* Free memory allocated by tabset(). */
+    if (tab->sense)   free(tab->sense);
+    if (tab->p0)      free(tab->p0);
+    if (tab->delta)   free(tab->delta);
+    if (tab->extrema) free(tab->extrema);
+  }
+
+  tab->m_flag  = 0;
+  tab->m_M     = 0;
+  tab->m_N     = 0;
+  tab->m_K     = 0x0;
+  tab->m_map   = 0x0;
+  tab->m_crval = 0x0;
+  tab->m_index = 0x0;
+  tab->m_indxs = 0x0;
+  tab->m_coord = 0x0;
+
+  tab->sense   = 0x0;
+  tab->p0      = 0x0;
+  tab->delta   = 0x0;
+  tab->extrema = 0x0;
+  tab->set_M   = 0;
+
+  if (tab->err) {
+    free(tab->err);
+    tab->err = 0x0;
+  }
+
+  tab->flag = 0;
+
+  return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int tabprt(const struct tabprm *tab)
+
+{
+  char   *cp, text[128];
+  int    j, k, m, n, nd;
+  double *dp;
+
+  if (tab == 0x0) return TABERR_NULL_POINTER;
+
+  if (tab->flag != TABSET) {
+    wcsprintf("The tabprm struct is UNINITIALIZED.\n");
+    return 0;
+  }
+
+  wcsprintf("       flag: %d\n", tab->flag);
+  wcsprintf("          M: %d\n", tab->M);
+
+  /* Array dimensions. */
+  WCSPRINTF_PTR("          K: ", tab->K, "\n");
+  wcsprintf("            ");
+  for (m = 0; m < tab->M; m++) {
+    wcsprintf("%6d", tab->K[m]);
+  }
+  wcsprintf("\n");
+
+  /* Map vector. */
+  WCSPRINTF_PTR("        map: ", tab->map, "\n");
+  wcsprintf("            ");
+  for (m = 0; m < tab->M; m++) {
+    wcsprintf("%6d", tab->map[m]);
+  }
+  wcsprintf("\n");
+
+  /* Reference index value. */
+  WCSPRINTF_PTR("      crval: ", tab->crval, "\n");
+  wcsprintf("            ");
+  for (m = 0; m < tab->M; m++) {
+    wcsprintf("  %- 11.5g", tab->crval[m]);
+  }
+  wcsprintf("\n");
+
+  /* Index vectors. */
+  WCSPRINTF_PTR("      index: ", tab->index, "\n");
+  for (m = 0; m < tab->M; m++) {
+    wcsprintf("   index[%d]: ", m);
+    WCSPRINTF_PTR("", tab->index[m], "");
+    if (tab->index[m]) {
+      for (k = 0; k < tab->K[m]; k++) {
+        if (k%5 == 0) {
+          wcsprintf("\n            ");
+        }
+        wcsprintf("  %- 11.5g", tab->index[m][k]);
+      }
+      wcsprintf("\n");
+    }
+  }
+
+  /* Coordinate array. */
+  WCSPRINTF_PTR("      coord: ", tab->coord, "\n");
+  dp = tab->coord;
+  for (n = 0; n < tab->nc; n++) {
+    /* Array index. */
+    j = n;
+    cp = text;
+    for (m = 0; m < tab->M; m++) {
+      nd = (tab->K[m] < 10) ? 1 : 2;
+      sprintf(cp, ",%*d", nd, j % tab->K[m] + 1);
+      j /= tab->K[m];
+      cp += strlen(cp);
+    }
+
+    wcsprintf("             (*%s)", text);
+    for (m = 0; m < tab->M; m++) {
+      wcsprintf("  %- 11.5g", *(dp++));
+    }
+    wcsprintf("\n");
+  }
+
+  wcsprintf("         nc: %d\n", tab->nc);
+
+  WCSPRINTF_PTR("      sense: ", tab->sense, "\n");
+  if (tab->sense) {
+    wcsprintf("            ");
+    for (m = 0; m < tab->M; m++) {
+      wcsprintf("%6d", tab->sense[m]);
+    }
+    wcsprintf("\n");
+  }
+
+  WCSPRINTF_PTR("         p0: ", tab->p0, "\n");
+  if (tab->p0) {
+    wcsprintf("            ");
+    for (m = 0; m < tab->M; m++) {
+      wcsprintf("%6d", tab->p0[m]);
+    }
+    wcsprintf("\n");
+  }
+
+  WCSPRINTF_PTR("      delta: ", tab->delta, "\n");
+  if (tab->delta) {
+    wcsprintf("            ");
+    for (m = 0; m < tab->M; m++) {
+      wcsprintf("  %- 11.5g", tab->delta[m]);
+    }
+    wcsprintf("\n");
+  }
+
+  WCSPRINTF_PTR("    extrema: ", tab->extrema, "\n");
+  dp = tab->extrema;
+  for (n = 0; n < tab->nc/tab->K[0]; n++) {
+    /* Array index. */
+    j = n;
+    cp = text;
+    *cp = '\0';
+    for (m = 1; m < tab->M; m++) {
+      nd = (tab->K[m] < 10) ? 1 : 2;
+      sprintf(cp, ",%*d", nd, j % tab->K[m] + 1);
+      j /= tab->K[m];
+      cp += strlen(cp);
+    }
+
+    wcsprintf("             (*,*%s)", text);
+    for (m = 0; m < 2*tab->M; m++) {
+      if (m == tab->M) wcsprintf("->  ");
+      wcsprintf("  %- 11.5g", *(dp++));
+    }
+    wcsprintf("\n");
+  }
+
+  WCSPRINTF_PTR("        err: ", tab->err, "\n");
+  if (tab->err) {
+    wcserr_prt(tab->err, "             ");
+  }
+
+  /* Memory management. */
+  wcsprintf("     m_flag: %d\n", tab->m_flag);
+  wcsprintf("        m_M: %d\n", tab->m_M);
+  wcsprintf("        m_N: %d\n", tab->m_N);
+
+  WCSPRINTF_PTR("        m_K: ", tab->m_K, "");
+  if (tab->m_K == tab->K) wcsprintf("  (= K)");
+  wcsprintf("\n");
+
+  WCSPRINTF_PTR("      m_map: ", tab->m_map, "");
+  if (tab->m_map == tab->map) wcsprintf("  (= map)");
+  wcsprintf("\n");
+
+  WCSPRINTF_PTR("    m_crval: ", tab->m_crval, "");
+  if (tab->m_crval == tab->crval) wcsprintf("  (= crval)");
+  wcsprintf("\n");
+
+  WCSPRINTF_PTR("    m_index: ", tab->m_index, "");
+  if (tab->m_index == tab->index) wcsprintf("  (= index)");
+  wcsprintf("\n");
+  for (m = 0; m < tab->M; m++) {
+    wcsprintf(" m_indxs[%d]: ", m);
+    WCSPRINTF_PTR("", tab->m_indxs[m], "");
+    if (tab->m_indxs[m] == tab->index[m]) wcsprintf("  (= index[%d])", m);
+    wcsprintf("\n");
+  }
+
+  WCSPRINTF_PTR("    m_coord: ", tab->m_coord, "");
+  if (tab->m_coord == tab->coord) wcsprintf("  (= coord)");
+  wcsprintf("\n");
+
+  return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int tabset(struct tabprm *tab)
+
+{
+  static const char *function = "tabset";
+
+  int i, ic, k, *Km, m, M, ne;
+  double *dcrd, *dmax, *dmin, dPsi, dval, *Psi;
+  struct wcserr **err;
+
+  if (tab == 0x0) return TABERR_NULL_POINTER;
+  err = &(tab->err);
+
+  /* Check the number of tabular coordinate axes. */
+  if ((M = tab->M) < 1) {
+    return wcserr_set(WCSERR_SET(TABERR_BAD_PARAMS),
+      "Invalid tabular parameters: M must be positive, got %d", M);
+  }
+
+  /* Check the axis lengths. */
+  if (!tab->K) {
+    return wcserr_set(WCSERR_SET(TABERR_MEMORY),
+      "Null pointers in tabprm struct");
+  }
+
+  tab->nc = 1;
+  for (m = 0; m < M; m++) {
+    if (tab->K[m] < 1) {
+      return wcserr_set(WCSERR_SET(TABERR_BAD_PARAMS),
+        "Invalid tabular parameters: Each element of K must be positive, "
+        "got %d", tab->K[m]);
+    }
+
+    /* Number of coordinate vectors in the coordinate array. */
+    tab->nc *= tab->K[m];
+  }
+
+  /* Check that the map vector is sensible. */
+  if (!tab->map) {
+    return wcserr_set(WCSERR_SET(TABERR_MEMORY),
+      "Null pointers in tabprm struct");
+  }
+
+  for (m = 0; m < M; m++) {
+    i = tab->map[m];
+    if (i < 0) {
+      return wcserr_set(WCSERR_SET(TABERR_BAD_PARAMS),
+        "Invalid tabular parameters: Each element of map must be "
+        "non-negative, got %d", i);
+    }
+  }
+
+  /* Check memory allocation for the remaining vectors. */
+  if (!tab->crval || !tab->index || !tab->coord) {
+    return wcserr_set(WCSERR_SET(TABERR_MEMORY),
+      "Null pointers in tabprm struct");
+  }
+
+  /* Take memory if signalled to by wcstab(). */
+  for (m = 0; m < tab->m_M; m++) {
+    if (tab->m_indxs[m] == (double *)0x1 &&
+      (tab->m_indxs[m] = tab->index[m])) {
+      tab->m_flag = TABSET;
+    }
+  }
+
+  if (tab->m_coord == (double *)0x1 &&
+    (tab->m_coord = tab->coord)) {
+    tab->m_flag = TABSET;
+  }
+
+
+  /* Allocate memory for work vectors. */
+  if (tab->flag != TABSET || tab->set_M < M) {
+    /* Free memory that may have been allocated previously. */
+    if (tab->sense)   free(tab->sense);
+    if (tab->p0)      free(tab->p0);
+    if (tab->delta)   free(tab->delta);
+    if (tab->extrema) free(tab->extrema);
+
+    /* Allocate memory for internal arrays. */
+    if (!(tab->sense = calloc(M, sizeof(int)))) {
+      return wcserr_set(TAB_ERRMSG(TABERR_MEMORY));
+    }
+
+    if (!(tab->p0 = calloc(M, sizeof(int)))) {
+      free(tab->sense);
+      return wcserr_set(TAB_ERRMSG(TABERR_MEMORY));
+    }
+
+    if (!(tab->delta = calloc(M, sizeof(double)))) {
+      free(tab->sense);
+      free(tab->p0);
+      return wcserr_set(TAB_ERRMSG(TABERR_MEMORY));
+    }
+
+    ne = M * tab->nc * 2 / tab->K[0];
+    if (!(tab->extrema = calloc(ne, sizeof(double)))) {
+      free(tab->sense);
+      free(tab->p0);
+      free(tab->delta);
+      return wcserr_set(TAB_ERRMSG(TABERR_MEMORY));
+    }
+
+    tab->set_M = M;
+  }
+
+  /* Check that the index vectors are monotonic. */
+  Km = tab->K;
+  for (m = 0; m < M; m++, Km++) {
+    tab->sense[m] = 0;
+
+    if (*Km > 1) {
+      if ((Psi = tab->index[m]) == 0x0) {
+        /* Default indexing. */
+        tab->sense[m] = 1;
+
+      } else {
+        for (k = 0; k < *Km-1; k++) {
+          switch (tab->sense[m]) {
+          case 0:
+            if (Psi[k] < Psi[k+1]) {
+              /* Monotonic increasing. */
+              tab->sense[m] = 1;
+            } else if (Psi[k] > Psi[k+1]) {
+              /* Monotonic decreasing. */
+              tab->sense[m] = -1;
+            }
+            break;
+
+          case 1:
+            if (Psi[k] > Psi[k+1]) {
+              /* Should be monotonic increasing. */
+              free(tab->sense);
+              free(tab->p0);
+              free(tab->delta);
+              free(tab->extrema);
+              return wcserr_set(WCSERR_SET(TABERR_BAD_PARAMS),
+                "Invalid tabular parameters: Index vectors are not "
+                "monotonically increasing");
+            }
+            break;
+
+          case -1:
+            if (Psi[k] < Psi[k+1]) {
+              /* Should be monotonic decreasing. */
+              free(tab->sense);
+              free(tab->p0);
+              free(tab->delta);
+              free(tab->extrema);
+              return wcserr_set(WCSERR_SET(TABERR_BAD_PARAMS),
+                "Invalid tabular parameters: Index vectors are not "
+                "monotonically decreasing");
+            }
+            break;
+          }
+        }
+      }
+
+      if (tab->sense[m] == 0) {
+        free(tab->sense);
+        free(tab->p0);
+        free(tab->delta);
+        free(tab->extrema);
+        return wcserr_set(WCSERR_SET(TABERR_BAD_PARAMS),
+          "Invalid tabular parameters: Index vectors are not monotonic");
+      }
+    }
+  }
+
+  /* Find the extremal values of the coordinate elements in each row. */
+  dcrd = tab->coord;
+  dmin = tab->extrema;
+  dmax = tab->extrema + M;
+  for (ic = 0; ic < tab->nc; ic += tab->K[0]) {
+    for (m = 0; m < M; m++, dcrd++) {
+      if (tab->K[0] > 1) {
+        /* Extrapolate a little before the start of the row. */
+        Psi = tab->index[0];
+        if (Psi == 0x0) {
+          dPsi = 1.0;
+        } else {
+          dPsi = Psi[1] - Psi[0];
+        }
+
+        dval = *dcrd;
+        if (dPsi != 0.0) {
+          dval -= 0.5 * (*(dcrd+M) - *dcrd)/dPsi;
+        }
+
+        *(dmax+m) = *(dmin+m) = dval;
+      } else {
+        *(dmax+m) = *(dmin+m) = *dcrd;
+      }
+    }
+
+    dcrd -= M;
+    for (i = 0; i < tab->K[0]; i++) {
+      for (m = 0; m < M; m++, dcrd++) {
+        if (*(dmax+m) < *dcrd) *(dmax+m) = *dcrd;
+        if (*(dmin+m) > *dcrd) *(dmin+m) = *dcrd;
+
+        if (tab->K[0] > 1 && i == tab->K[0]-1) {
+          /* Extrapolate a little beyond the end of the row. */
+          Psi = tab->index[0];
+          if (Psi == 0x0) {
+            dPsi = 1.0;
+          } else {
+            dPsi = Psi[i] - Psi[i-1];
+          }
+
+          dval = *dcrd;
+          if (dPsi != 0.0) {
+            dval += 0.5 * (*dcrd - *(dcrd-M))/dPsi;
+          }
+
+          if (*(dmax+m) < dval) *(dmax+m) = dval;
+          if (*(dmin+m) > dval) *(dmin+m) = dval;
+        }
+      }
+    }
+
+    dmin += 2*M;
+    dmax += 2*M;
+  }
+
+  tab->flag = TABSET;
+
+  return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int tabx2s(
+  struct tabprm *tab,
+  int ncoord,
+  int nelem,
+  const double x[],
+  double world[],
+  int stat[])
+
+{
+  static const char *function = "tabx2s";
+
+  int i, iv, k, *Km, m, M, n, nv, offset, p1, status;
+  double *coord, *Psi, psi_m, upsilon, wgt;
+  register int *statp;
+  register const double *xp;
+  register double *wp;
+  struct wcserr **err;
+
+  if (tab == 0x0) return TABERR_NULL_POINTER;
+  err = &(tab->err);
+
+  /* Initialize if required. */
+  if (tab->flag != TABSET) {
+    if ((status = tabset(tab))) return status;
+  }
+
+  /* This is used a lot. */
+  M = tab->M;
+
+  status = 0;
+  xp = x;
+  wp = world;
+  statp = stat;
+  for (n = 0; n < ncoord; n++) {
+    /* Determine the indexes. */
+    Km = tab->K;
+    for (m = 0; m < M; m++, Km++) {
+      /* N.B. psi_m and Upsilon_m are 1-relative FITS indexes. */
+      i = tab->map[m];
+      psi_m = *(xp+i) + tab->crval[m];
+
+      Psi = tab->index[m];
+      if (Psi == 0x0) {
+        /* Default indexing is simple. */
+        upsilon = psi_m;
+
+      } else {
+        /* To ease confusion, decrement Psi so that we can use 1-relative
+           C array indexing to match the 1-relative FITS indexing. */
+        Psi--;
+
+        if (*Km == 1) {
+          /* Index vector is degenerate. */
+          if (Psi[1]-0.5 <= psi_m && psi_m <= Psi[1]+0.5) {
+            upsilon = psi_m;
+          } else {
+            *statp = 1;
+            status = wcserr_set(TAB_ERRMSG(TABERR_BAD_X));
+            goto next;
+          }
+
+        } else {
+          /* Interpolate in the indexing vector. */
+          if (tab->sense[m] == 1) {
+            /* Monotonic increasing index values. */
+            if (psi_m < Psi[1]) {
+              if (Psi[1] - 0.5*(Psi[2]-Psi[1]) <= psi_m) {
+                /* Allow minor extrapolation. */
+                k = 1;
+
+              } else {
+                /* Index is out of range. */
+                *statp = 1;
+                status = wcserr_set(TAB_ERRMSG(TABERR_BAD_X));
+                goto next;
+              }
+
+            } else if (Psi[*Km] < psi_m) {
+              if (psi_m <= Psi[*Km] + 0.5*(Psi[*Km]-Psi[*Km-1])) {
+                /* Allow minor extrapolation. */
+                k = *Km - 1;
+
+              } else {
+                /* Index is out of range. */
+                *statp = 1;
+                status = wcserr_set(TAB_ERRMSG(TABERR_BAD_X));
+                goto next;
+              }
+
+            } else {
+              for (k = 1; k < *Km; k++) {
+                if (psi_m < Psi[k]) {
+                  continue;
+                }
+                if (Psi[k] == psi_m && psi_m < Psi[k+1]) {
+                  break;
+                }
+                if (Psi[k] < psi_m && psi_m <= Psi[k+1]) {
+                  break;
+                }
+              }
+            }
+
+          } else {
+            /* Monotonic decreasing index values. */
+            if (psi_m > Psi[1]) {
+              if (Psi[1] + 0.5*(Psi[1]-Psi[2]) >= psi_m) {
+                /* Allow minor extrapolation. */
+                k = 1;
+
+              } else {
+                /* Index is out of range. */
+                *statp = 1;
+                status = wcserr_set(TAB_ERRMSG(TABERR_BAD_X));
+                goto next;
+              }
+
+            } else if (psi_m < Psi[*Km]) {
+              if (Psi[*Km] - 0.5*(Psi[*Km-1]-Psi[*Km]) <= psi_m) {
+                /* Allow minor extrapolation. */
+                k = *Km - 1;
+
+              } else {
+                /* Index is out of range. */
+                *statp = 1;
+                status = wcserr_set(TAB_ERRMSG(TABERR_BAD_X));
+                goto next;
+              }
+
+            } else {
+              for (k = 1; k < *Km; k++) {
+                if (psi_m > Psi[k]) {
+                  continue;
+                }
+                if (Psi[k] == psi_m && psi_m > Psi[k+1]) {
+                  break;
+                }
+                if (Psi[k] > psi_m && psi_m >= Psi[k+1]) {
+                  break;
+                }
+              }
+            }
+          }
+
+          upsilon = k + (psi_m - Psi[k]) / (Psi[k+1] - Psi[k]);
+        }
+      }
+
+      if (upsilon < 0.5 || upsilon > *Km + 0.5) {
+        /* Index out of range. */
+        *statp = 1;
+        status = wcserr_set(TAB_ERRMSG(TABERR_BAD_X));
+        goto next;
+      }
+
+      /* Fiducial array indices and fractional offset.
+         p1 is 1-relative while tab::p0 is 0-relative. */
+      p1 = (int)floor(upsilon);
+      tab->p0[m] = p1 - 1;
+      tab->delta[m] = upsilon - p1;
+
+      if (p1 == 0) {
+        tab->p0[m] += 1;
+        tab->delta[m] -= 1.0;
+      } else if (p1 == *Km && *Km > 1) {
+        tab->p0[m] -= 1;
+        tab->delta[m] += 1.0;
+      }
+    }
+
+
+    /* Now interpolate in the coordinate array; the M-dimensional linear  */
+    /* interpolation algorithm is described in Sect. 3.4 of WCS Paper IV. */
+    for (m = 0; m < M; m++) {
+     i = tab->map[m];
+     *(wp+i) = 0.0;
+    }
+
+    /* Loop over the 2^M vertices surrounding P. */
+    nv = 1 << M;
+    for (iv = 0; iv < nv; iv++) {
+      /* Locate vertex in the coordinate array and compute its weight. */
+      offset = 0;
+      wgt = 1.0;
+      for (m = M-1; m >= 0; m--) {
+        offset *= tab->K[m];
+        offset += tab->p0[m];
+        if (iv & (1 << m)) {
+          if (tab->K[m] > 1) offset++;
+          wgt *= tab->delta[m];
+        } else {
+          wgt *= 1.0 - tab->delta[m];
+        }
+      }
+
+      if (wgt == 0.0) continue;
+
+      /* Add the contribution from this vertex to each element. */
+      coord = tab->coord + offset*M;
+      for (m = 0; m < M; m++) {
+        i = tab->map[m];
+        *(wp+i) += *(coord++) * wgt;
+      }
+
+      if (wgt == 1.0) break;
+    }
+
+    *statp = 0;
+
+next:
+    xp += nelem;
+    wp += nelem;
+    statp++;
+  }
+
+  return status;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int tabs2x(
+  struct tabprm* tab,
+  int ncoord,
+  int nelem,
+  const double world[],
+  double x[],
+  int stat[])
+
+{
+  static const char *function = "tabs2x";
+
+  int tabedge(struct tabprm *);
+  int tabrow(struct tabprm *, const double *);
+  int tabvox(struct tabprm *, const double *, int, double **, unsigned int *);
+
+  int edge, i, ic, iv, k, *Km, M, m, n, nv, offset, status;
+  double *dcrd, delta, *Psi, psi_m, **tabcoord, upsilon;
+  register int *statp;
+  register const double *wp;
+  register double *xp;
+  struct wcserr **err;
+
+  if (tab == 0x0) return TABERR_NULL_POINTER;
+  err = &(tab->err);
+
+  /* Initialize if required. */
+  if (tab->flag != TABSET) {
+    if ((status = tabset(tab))) return status;
+  }
+
+  /* This is used a lot. */
+  M = tab->M;
+
+  tabcoord = 0x0;
+  nv = 0;
+  if (M > 1) {
+    nv = 1 << M;
+    tabcoord = calloc(nv, sizeof(double *));
+  }
+
+
+  status = 0;
+  wp = world;
+  xp = x;
+  statp = stat;
+  for (n = 0; n < ncoord; n++) {
+    /* Locate this coordinate in the coordinate array. */
+    edge = 0;
+    for (m = 0; m < M; m++) {
+      tab->p0[m] = 0;
+    }
+
+    for (ic = 0; ic < tab->nc; ic++) {
+      if (tab->p0[0] == 0) {
+        /* New row, could it contain a solution? */
+        if (edge || tabrow(tab, wp)) {
+          /* No, skip it. */
+          ic += tab->K[0];
+          tab->p0[1]++;
+          edge = tabedge(tab);
+
+          /* Because ic will be incremented when the loop is reentered. */
+          ic--;
+          continue;
+        }
+      }
+
+      if (M == 1) {
+        /* Deal with the one-dimensional case separately for efficiency. */
+        if (*wp == tab->coord[0]) {
+          tab->p0[0] = 0;
+          tab->delta[0] = 0.0;
+          break;
+
+        } else if (ic < tab->nc - 1) {
+          if (((tab->coord[ic] <= *wp && *wp <= tab->coord[ic+1]) ||
+               (tab->coord[ic] >= *wp && *wp >= tab->coord[ic+1])) &&
+               (tab->index[0] == 0x0 ||
+                tab->index[0][ic] != tab->index[0][ic+1])) {
+            tab->p0[0] = ic;
+            tab->delta[0] = (*wp - tab->coord[ic]) /
+                            (tab->coord[ic+1] - tab->coord[ic]);
+            break;
+          }
+        }
+
+      } else {
+        /* Multi-dimensional tables are harder. */
+        if (!edge) {
+          /* Addresses of the coordinates for each corner of the "voxel". */
+          for (iv = 0; iv < nv; iv++) {
+            offset = 0;
+            for (m = M-1; m >= 0; m--) {
+              offset *= tab->K[m];
+              offset += tab->p0[m];
+              if ((iv & (1 << m)) && (tab->K[m] > 1)) offset++;
+            }
+            tabcoord[iv] = tab->coord + offset*M;
+          }
+
+          if (tabvox(tab, wp, 0, tabcoord, 0x0) == 0) {
+            /* Found a solution. */
+            break;
+          }
+        }
+
+        /* Next voxel. */
+        tab->p0[0]++;
+        edge = tabedge(tab);
+      }
+    }
+
+
+    if (ic == tab->nc) {
+      /* Coordinate not found; allow minor extrapolation. */
+      if (M == 1) {
+        /* Should there be a solution? */
+        if (tab->extrema[0] <= *wp && *wp <= tab->extrema[1]) {
+          dcrd = tab->coord;
+          for (i = 0; i < 2; i++) {
+            if (i) dcrd += tab->K[0] - 2;
+
+            delta = (*wp - *dcrd) / (*(dcrd+1) - *dcrd);
+
+            if (i == 0) {
+              if (-0.5 <= delta && delta <= 0.0) {
+                tab->p0[0] = 0;
+                tab->delta[0] = delta;
+                ic = 0;
+                break;
+              }
+            } else {
+              if (1.0 <= delta && delta <= 1.5) {
+                tab->p0[0] = tab->K[0] - 1;
+                tab->delta[0] = delta - 1.0;
+                ic = 0;
+              }
+            }
+          }
+        }
+
+      } else {
+        /* Multi-dimensional tables. */
+        /* >>> TBD <<< */
+      }
+    }
+
+
+    if (ic == tab->nc) {
+      /* Coordinate not found. */
+      *statp = 1;
+      status = wcserr_set(TAB_ERRMSG(TABERR_BAD_WORLD));
+    } else {
+      /* Determine the intermediate world coordinates. */
+      Km = tab->K;
+      for (m = 0; m < M; m++, Km++) {
+        /* N.B. Upsilon_m and psi_m are 1-relative FITS indexes. */
+        upsilon = (tab->p0[m] + 1) + tab->delta[m];
+
+        if (upsilon < 0.5 || upsilon > *Km + 0.5) {
+          /* Index out of range. */
+          *statp = 1;
+          status = wcserr_set(TAB_ERRMSG(TABERR_BAD_WORLD));
+
+        } else {
+          /* Do inverse lookup of the index vector. */
+          Psi = tab->index[m];
+          if (Psi == 0x0) {
+            /* Default indexing. */
+            psi_m = upsilon;
+
+          } else {
+            /* Decrement Psi and use 1-relative C array indexing to match the
+               1-relative FITS indexing. */
+            Psi--;
+
+            if (*Km == 1) {
+              /* Degenerate index vector. */
+              psi_m = Psi[1];
+            } else {
+              k = (int)(upsilon);
+              psi_m = Psi[k];
+              if (k < *Km) {
+                psi_m += (upsilon - k) * (Psi[k+1] - Psi[k]);
+              }
+            }
+          }
+
+          i = tab->map[m];
+          xp[i] = psi_m - tab->crval[m];
+        }
+      }
+      *statp = 0;
+    }
+
+    wp += nelem;
+    xp += nelem;
+    statp++;
+  }
+
+  if (tabcoord) free(tabcoord);
+
+  return status;
+}
+
+/*----------------------------------------------------------------------------
+* Convenience routine to deal with of edge effects in tabprm::p0.
+*---------------------------------------------------------------------------*/
+
+int tabedge(struct tabprm* tab)
+
+{
+  int edge, *Km, m;
+
+  edge = 0;
+  Km = tab->K;
+  for (m = 0; m < tab->M; m++, Km++) {
+    if (tab->p0[m] == *Km) {
+      /* p0 has been incremented beyond the end of the row, point it to the
+         next one. */
+      tab->p0[m] = 0;
+      tab->p0[m+1]++;
+    } else if (tab->p0[m] == *Km - 1 && *Km > 1) {
+      /* p0 is sitting at the end of a non-degenerate row. */
+      edge = 1;
+    }
+  }
+
+  return edge;
+}
+
+/*----------------------------------------------------------------------------
+* Quick test to see whether the world coordinate indicated by wp could lie
+* somewhere along (or near) the row of the image indexed by tabprm::p0.
+* Return 0 if so, 1 otherwise.
+*
+* tabprm::p0 selects a particular row of the image, p0[0] being ignored (i.e.
+* treated as zero).  Adjacent rows that delimit a row of "voxels" are formed
+* by incrementing elements other than p0[0] in all binary combinations.  N.B.
+* these are not the same as the voxels (pixels) that are indexed by, and
+* centred on, integral pixel coordinates in FITS.
+*
+* To see why it is necessary to examine the adjacent rows, consider the 2-D
+* case where the first world coordinate element is constant along each row.
+* If the first element of wp has value 0.5, and its value in the row indexed
+* by p0 has value 0, and in the next row it has value 1, then it is clear that
+* the solution lies in neither row but somewhere between them.  Thus both rows
+* will be involved in finding the solution.
+*
+* tabprm::extrema is the address of the first element of a 1-D array that
+* records the minimum and maximum value of each element of the coordinate
+* vector in each row of the coordinate array, treated as though it were
+* defined as
+*
+*   double extrema[K_M]...[K_2][2][M]
+*
+* The minimum is recorded in the first element of the compressed K_1
+* dimension, then the maximum.
+*---------------------------------------------------------------------------*/
+
+int tabrow(struct tabprm* tab, const double *wp)
+
+{
+  int iv, M, m, nv, offset;
+  unsigned int eq, gt, lt;
+  const double tol = 1e-10;
+  double *cp, w;
+
+  M = tab->M;
+
+  /* The number of corners in a "voxel".  We need examine only half this
+     number of rows.  The extra factor of two will be used to select between
+     the minimal and maximal values in each row. */
+  nv = 1 << M;
+
+  eq = 0;
+  lt = 0;
+  gt = 0;
+  for (iv = 0; iv < nv; iv++) {
+    /* Find the index into tabprm::extrema for this row. */
+    offset = 0;
+    for (m = M-1; m > 0; m--) {
+      offset *= tab->K[m];
+      offset += tab->p0[m];
+
+      /* Select the row. */
+      if (iv & (1 << m)) {
+        if (tab->K[m] > 1) offset++;
+      }
+    }
+
+    /* The K_1 dimension has length 2 (see prologue). */
+    offset *= 2;
+
+    /* Select the minimum on even numbered iterations, else the maximum. */
+    if (iv & 1) offset++;
+
+    /* The last dimension has length M (see prologue). */
+    offset *= M;
+
+    /* Address of the extremal elements (min or max) for this row. */
+    cp = tab->extrema + offset;
+
+    /* For each coordinate element, we only need to find one row where its
+       minimum value is less than that of wp, and one row where the maximum
+       value is greater.  That doesn't mean that there is a solution, only
+       that there might be. */
+    for (m = 0; m < M; m++, cp++) {
+      /* Apply the axis mapping. */
+      w = wp[tab->map[m]];
+
+      /* Finally the test itself; set bits in the bitmask. */
+      if (fabs(*cp - w) < tol) {
+        eq |= (1 << m);
+      } else if (*cp < w) {
+        lt |= (1 << m);
+      } else if (*cp > w) {
+        gt |= (1 << m);
+      }
+    }
+
+    /* Have all bits been switched on? */
+    if ((lt | eq) == nv-1 && (gt | eq) == nv-1) {
+      /* A solution could lie within this row of voxels. */
+      return 0;
+    }
+  }
+
+  /* No solution in this row. */
+  return 1;
+}
+
+/*----------------------------------------------------------------------------
+* Does the world coordinate indicated by wp lie within the voxel indexed by
+* tabprm::p0?  If so, do a binary chop of the interior of the voxel to find
+* it and return 0, with tabprm::delta set to the solution.  Else return 1.
+*
+* As in tabrow(), a "voxel" is formed by incrementing the elements of
+* tabprm::p0 in all binary combinations.  Note that these are not the same as
+* the voxels (pixels) that are indexed by, and centred on, integral pixel
+* coordinates in FITS.
+*
+* tabvox() calls itself recursively.  When called from outside, level, being
+* the level of recursion, should be given as zero.  tabcoord is an array
+* holding the addresses of the coordinates for each corner of the voxel.
+* vox is the address of a work array (vox2) used during recursive calls to
+* dissect the voxel.  It is ignored when tabvox() is called from outside
+* (level == 0).
+*
+* It is assumed that the image dimensions are no greater than 16.
+----------------------------------------------------------------------------*/
+
+int tabvox(
+  struct tabprm* tab,
+  const double *wp,
+  int level,
+  double **tabcoord,
+  unsigned int *vox)
+
+{
+  int i, iv, jv, M, m, nv;
+  unsigned int eq, et, gt, lt, vox2[16];
+  const double tol = 1e-10;
+  double coord[16], *cp, dv, w, wgt;
+
+  M = tab->M;
+
+  /* The number of corners in a voxel. */
+  nv = 1 << M;
+
+  dv = 1.0;
+  for (i = 0; i < level; i++) {
+    dv /= 2.0;
+  }
+
+  /* Could the coordinate lie within this voxel (level == 0) or sub-voxel
+     (level > 0)?  We use the fact that with linear interpolation the
+     coordinate elements are extremal in a corner and test each one. */
+  lt = 0;
+  gt = 0;
+  eq = 0;
+  for (iv = 0; iv < nv; iv++) {
+    /* Select a corner of the sub-voxel. */
+    for (m = 0; m < M; m++) {
+      coord[m] = 0.0;
+      tab->delta[m] = level ? dv*vox[m] : 0.0;
+
+      if (iv & (1 << m)) {
+        tab->delta[m] += dv;
+      }
+    }
+
+    /* Compute the coordinates of this corner of the sub-voxel by linear
+       interpolation using the weighting algorithm described in Sect. 3.4 of
+       WCS Paper IV. */
+    for (jv = 0; jv < nv; jv++) {
+      /* Find the weight for this corner of the parent voxel. */
+      wgt = 1.0;
+      for (m = 0; m < M; m++) {
+        if (jv & (1 << m)) {
+          wgt *= tab->delta[m];
+        } else {
+          wgt *= 1.0 - tab->delta[m];
+        }
+      }
+
+      if (wgt == 0.0) continue;
+
+      /* Add its contribution to each coordinate element. */
+      cp = tabcoord[jv];
+      for (m = 0; m < M; m++) {
+        coord[m] += *(cp++) * wgt;
+      }
+
+      if (wgt == 1.0) break;
+    }
+
+    /* Coordinate elements are minimal or maximal in a corner. */
+    et = 0;
+    for (m = 0; m < M; m++) {
+      /* Apply the axis mapping. */
+      w = wp[tab->map[m]];
+
+      /* Finally the test itself; set bits in the bitmask. */
+      if (fabs(coord[m] - w) < tol) {
+        et |= (1 << m);
+      } else if (coord[m] < w) {
+        lt |= (1 << m);
+      } else if (coord[m] > w) {
+        gt |= (1 << m);
+      }
+    }
+
+    if (et == nv-1) {
+      /* We've stumbled across a solution in this corner of the sub-voxel. */
+      return 0;
+    }
+
+    eq |= et;
+  }
+
+  /* Could the coordinate lie within this sub-voxel? */
+  if ((lt | eq) == nv-1 && (gt | eq) == nv-1) {
+    /* Yes it could, but does it? */
+
+    /* Is it time to stop the recursion? */
+    if (level == 31) {
+      /* We have a solution, squeeze out the last bit of juice. */
+      dv /= 2.0;
+      for (m = 0; m < M; m++) {
+        tab->delta[m] = dv * (2.0*vox[m] + 1.0);
+      }
+
+      return 0;
+    }
+
+    /* Subdivide the sub-voxel and try again for each subdivision. */
+    for (iv = 0; iv < nv; iv++) {
+      /* Select the subdivision. */
+      for (m = 0; m < M; m++) {
+        vox2[m] = level ? 2*vox[m] : 0;
+        if (iv & (1 << m)) {
+          vox2[m]++;
+        }
+      }
+
+      /* Recurse. */
+      if (tabvox(tab, wp, level+1, tabcoord, vox2) == 0) {
+        return 0;
+      }
+    }
+  }
+
+  /* No solution in this sub-voxel. */
+  return 1;
+}
diff --git a/cextern/wcslib/C/tab.h b/cextern/wcslib/C/tab.h
new file mode 100644
index 0000000..850e0fa
--- /dev/null
+++ b/cextern/wcslib/C/tab.h
@@ -0,0 +1,580 @@
+/*============================================================================
+
+  WCSLIB 4.16 - an implementation of the FITS WCS standard.
+  Copyright (C) 1995-2012, Mark Calabretta
+
+  This file is part of WCSLIB.
+
+  WCSLIB is free software: you can redistribute it and/or modify it under the
+  terms of the GNU Lesser General Public License as published by the Free
+  Software Foundation, either version 3 of the License, or (at your option)
+  any later version.
+
+  WCSLIB 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 Lesser General Public License for
+  more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with WCSLIB.  If not, see http://www.gnu.org/licenses.
+
+  Direct correspondence concerning WCSLIB to mark at calabretta.id.au
+
+  Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
+  http://www.atnf.csiro.au/people/Mark.Calabretta
+  $Id: tab.h,v 4.16 2012/11/07 04:42:44 cal103 Exp $
+*=============================================================================
+*
+* WCSLIB 4.16 - C routines that implement tabular coordinate systems as
+* defined by the FITS World Coordinate System (WCS) standard.  Refer to
+*
+*   "Representations of world coordinates in FITS",
+*   Greisen, E.W., & Calabretta, M.R. 2002, A&A, 395, 1061 (paper I)
+*
+*   "Representations of spectral coordinates in FITS",
+*   Greisen, E.W., Calabretta, M.R., Valdes, F.G., & Allen, S.L.
+*   2006, A&A, 446, 747 (Paper III)
+*
+* Refer to the README file provided with WCSLIB for an overview of the
+* library.
+*
+*
+* Summary of the tab routines
+* ---------------------------
+* These routines implement the part of the FITS WCS standard that deals with
+* tabular coordinates, i.e. coordinates that are defined via a lookup table.
+* They define methods to be used for computing tabular world coordinates from
+* intermediate world coordinates (a linear transformation of image pixel
+* coordinates), and vice versa.  They are based on the tabprm struct which
+* contains all information needed for the computations.  The struct contains
+* some members that must be set by the user, and others that are maintained
+* by these routines, somewhat like a C++ class but with no encapsulation.
+*
+* tabini(), tabmem(), tabcpy(), and tabfree() are provided to manage the
+* tabprm struct, and another, tabprt(), to print its contents.
+*
+* A setup routine, tabset(), computes intermediate values in the tabprm struct
+* from parameters in it that were supplied by the user.  The struct always
+* needs to be set up by tabset() but it need not be called explicitly - refer
+* to the explanation of tabprm::flag.
+*
+* tabx2s() and tabs2x() implement the WCS tabular coordinate transformations.
+*
+* Accuracy:
+* ---------
+* No warranty is given for the accuracy of these routines (refer to the
+* copyright notice); intending users must satisfy for themselves their
+* adequacy for the intended purpose.  However, closure effectively to within
+* double precision rounding error was demonstrated by test routine ttab.c
+* which accompanies this software.
+*
+*
+* tabini() - Default constructor for the tabprm struct
+* ----------------------------------------------------
+* tabini() allocates memory for arrays in a tabprm struct and sets all members
+* of the struct to default values.
+*
+* PLEASE NOTE: every tabprm struct should be initialized by tabini(), possibly
+* repeatedly.  On the first invokation, and only the first invokation, the
+* flag member of the tabprm struct must be set to -1 to initialize memory
+* management, regardless of whether tabini() will actually be used to allocate
+* memory.
+*
+* Given:
+*   alloc     int       If true, allocate memory unconditionally for arrays in
+*                       the tabprm struct.
+*
+*                       If false, it is assumed that pointers to these arrays
+*                       have been set by the user except if they are null
+*                       pointers in which case memory will be allocated for
+*                       them regardless.  (In other words, setting alloc true
+*                       saves having to initalize these pointers to zero.)
+*
+*   M         int       The number of tabular coordinate axes.
+*
+*   K         const int[]
+*                       Vector of length M whose elements (K_1, K_2,... K_M)
+*                       record the lengths of the axes of the coordinate array
+*                       and of each indexing vector.  M and K[] are used to
+*                       determine the length of the various tabprm arrays and
+*                       therefore the amount of memory to allocate for them.
+*                       Their values are copied into the tabprm struct.
+*
+*                       It is permissible to set K (i.e. the address of the
+*                       array) to zero which has the same effect as setting
+*                       each element of K[] to zero.  In this case no memory
+*                       will be allocated for the index vectors or coordinate
+*                       array in the tabprm struct.  These together with the
+*                       K vector must be set separately before calling
+*                       tabset().
+*
+* Given and returned:
+*   tab       struct tabprm*
+*                       Tabular transformation parameters.  Note that, in
+*                       order to initialize memory management tabprm::flag
+*                       should be set to -1 when tab is initialized for the
+*                       first time (memory leaks may result if it had already
+*                       been initialized).
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         1: Null tabprm pointer passed.
+*                         2: Memory allocation failed.
+*                         3: Invalid tabular parameters.
+*
+*                       For returns > 1, a detailed error message is set in
+*                       tabprm::err if enabled, see wcserr_enable().
+*
+*
+* tabmem() - Acquire tabular memory
+* ---------------------------------
+* tabmem() takes control of memory allocated by the user for arrays in the
+* tabprm struct.
+*
+* Given and returned:
+*   tab       struct tabprm*
+*                       Tabular transformation parameters.
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         1: Null tabprm pointer passed.
+*                         2: Memory allocation failed.
+*
+*                       For returns > 1, a detailed error message is set in
+*                       tabprm::err if enabled, see wcserr_enable().
+*
+*
+* tabcpy() - Copy routine for the tabprm struct
+* ---------------------------------------------
+* tabcpy() does a deep copy of one tabprm struct to another, using tabini() to
+* allocate memory for its arrays if required.  Only the "information to be
+* provided" part of the struct is copied; a call to tabset() is required to
+* set up the remainder.
+*
+* Given:
+*   alloc     int       If true, allocate memory unconditionally for arrays in
+*                       the tabprm struct.
+*
+*                       If false, it is assumed that pointers to these arrays
+*                       have been set by the user except if they are null
+*                       pointers in which case memory will be allocated for
+*                       them regardless.  (In other words, setting alloc true
+*                       saves having to initalize these pointers to zero.)
+*
+*   tabsrc    const struct tabprm*
+*                       Struct to copy from.
+*
+* Given and returned:
+*   tabdst    struct tabprm*
+*                       Struct to copy to.  tabprm::flag should be set to -1
+*                       if tabdst was not previously initialized (memory leaks
+*                       may result if it was previously initialized).
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         1: Null tabprm pointer passed.
+*                         2: Memory allocation failed.
+*
+*                       For returns > 1, a detailed error message is set in
+*                       tabprm::err (associated with tabdst) if enabled, see
+*                       wcserr_enable().
+*
+*
+* tabfree() - Destructor for the tabprm struct
+* --------------------------------------------
+* tabfree() frees memory allocated for the tabprm arrays by tabini().
+* tabini() records the memory it allocates and tabfree() will only attempt to
+* free this.
+*
+* PLEASE NOTE: tabfree() must not be invoked on a tabprm struct that was not
+* initialized by tabini().
+*
+* Returned:
+*   tab       struct tabprm*
+*                       Coordinate transformation parameters.
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         1: Null tabprm pointer passed.
+*
+*
+* tabprt() - Print routine for the tabprm struct
+* ----------------------------------------------
+* tabprt() prints the contents of a tabprm struct using wcsprintf().  Mainly
+* intended for diagnostic purposes.
+*
+* Given:
+*   tab       const struct tabprm*
+*                       Tabular transformation parameters.
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         1: Null tabprm pointer passed.
+*
+*
+* tabset() - Setup routine for the tabprm struct
+* -----------------------------------------------
+* tabset() allocates memory for work arrays in the tabprm struct and sets up
+* the struct according to information supplied within it.
+*
+* Note that this routine need not be called directly; it will be invoked by
+* tabx2s() and tabs2x() if tabprm::flag is anything other than a predefined
+* magic value.
+*
+* Given and returned:
+*   tab       struct tabprm*
+*                       Tabular transformation parameters.
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         1: Null tabprm pointer passed.
+*                         3: Invalid tabular parameters.
+*
+*                       For returns > 1, a detailed error message is set in
+*                       tabprm::err if enabled, see wcserr_enable().
+*
+*
+* tabx2s() - Pixel-to-world transformation
+* ----------------------------------------
+* tabx2s() transforms intermediate world coordinates to world coordinates
+* using coordinate lookup.
+*
+* Given and returned:
+*   tab       struct tabprm*
+*                       Tabular transformation parameters.
+*
+* Given:
+*   ncoord,
+*   nelem     int       The number of coordinates, each of vector length
+*                       nelem.
+*
+*   x         const double[ncoord][nelem]
+*                       Array of intermediate world coordinates, SI units.
+*
+* Returned:
+*   world     double[ncoord][nelem]
+*                       Array of world coordinates, in SI units.
+*
+*   stat      int[ncoord]
+*                       Status return value status for each coordinate:
+*                         0: Success.
+*                         1: Invalid intermediate world coordinate.
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         1: Null tabprm pointer passed.
+*                         3: Invalid tabular parameters.
+*                         4: One or more of the x coordinates were invalid,
+*                            as indicated by the stat vector.
+*
+*                       For returns > 1, a detailed error message is set in
+*                       tabprm::err if enabled, see wcserr_enable().
+*
+*
+* tabs2x() - World-to-pixel transformation
+* ----------------------------------------
+* tabs2x() transforms world coordinates to intermediate world coordinates.
+*
+* Given and returned:
+*   tab       struct tabprm*
+*                       Tabular transformation parameters.
+*
+* Given:
+*   ncoord,
+*   nelem     int       The number of coordinates, each of vector length
+*                       nelem.
+*   world     const double[ncoord][nelem]
+*                       Array of world coordinates, in SI units.
+*
+* Returned:
+*   x         double[ncoord][nelem]
+*                       Array of intermediate world coordinates, SI units.
+*   stat      int[ncoord]
+*                       Status return value status for each vector element:
+*                         0: Success.
+*                         1: Invalid world coordinate.
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         1: Null tabprm pointer passed.
+*                         3: Invalid tabular parameters.
+*                         5: One or more of the world coordinates were
+*                            invalid, as indicated by the stat vector.
+*
+*                       For returns > 1, a detailed error message is set in
+*                       tabprm::err if enabled, see wcserr_enable().
+*
+*
+* tabprm struct - Tabular transformation parameters
+* -------------------------------------------------
+* The tabprm struct contains information required to transform tabular
+* coordinates.  It consists of certain members that must be set by the user
+* ("given") and others that are set by the WCSLIB routines ("returned").  Some
+* of the latter are supplied for informational purposes while others are for
+* internal use only.
+*
+*   int flag
+*     (Given and returned) This flag must be set to zero whenever any of the
+*     following tabprm structure members are set or changed:
+*
+*       - tabprm::M (q.v., not normally set by the user),
+*       - tabprm::K (q.v., not normally set by the user),
+*       - tabprm::map,
+*       - tabprm::crval,
+*       - tabprm::index,
+*       - tabprm::coord.
+*
+*     This signals the initialization routine, tabset(), to recompute the
+*     returned members of the tabprm struct.  tabset() will reset flag to
+*     indicate that this has been done.
+*
+*     PLEASE NOTE: flag should be set to -1 when tabini() is called for the
+*     first time for a particular tabprm struct in order to initialize memory
+*     management.  It must ONLY be used on the first initialization otherwise
+*     memory leaks may result.
+*
+*   int M
+*     (Given or returned) Number of tabular coordinate axes.
+*
+*     If tabini() is used to initialize the linprm struct (as would normally
+*     be the case) then it will set M from the value passed to it as a
+*     function argument.  The user should not subsequently modify it.
+*
+*   int *K
+*     (Given or returned) Pointer to the first element of a vector of length
+*     tabprm::M whose elements (K_1, K_2,... K_M) record the lengths of the
+*     axes of the coordinate array and of each indexing vector.
+*
+*     If tabini() is used to initialize the linprm struct (as would normally
+*     be the case) then it will set K from the array passed to it as a
+*     function argument.  The user should not subsequently modify it.
+*
+*   int *map
+*     (Given) Pointer to the first element of a vector of length tabprm::M
+*     that defines the association between axis m in the M-dimensional
+*     coordinate array (1 <= m <= M) and the indices of the intermediate world
+*     coordinate and world coordinate arrays, x[] and world[], in the argument
+*     lists for tabx2s() and tabs2x().
+*
+*     When x[] and world[] contain the full complement of coordinate elements
+*     in image-order, as will usually be the case, then map[m-1] == i-1 for
+*     axis i in the N-dimensional image (1 <= i <= N).  In terms of the FITS
+*     keywords
+*
+*       map[PVi_3a - 1] == i - 1.
+*
+*     However, a different association may result if x[], for example, only
+*     contains a (relevant) subset of intermediate world coordinate elements.
+*     For example, if M == 1 for an image with N > 1, it is possible to fill
+*     x[] with the relevant coordinate element with nelem set to 1.  In this
+*     case map[0] = 0 regardless of the value of i.
+*
+*   double *crval
+*     (Given) Pointer to the first element of a vector of length tabprm::M
+*     whose elements contain the index value for the reference pixel for each
+*     of the tabular coordinate axes.
+*
+*   double **index
+*     (Given) Pointer to the first element of a vector of length tabprm::M of
+*     pointers to vectors of lengths (K_1, K_2,... K_M) of 0-relative indexes
+*     (see tabprm::K).
+*
+*     The address of any or all of these index vectors may be set to zero,
+*     i.e.
+*
+=       index[m] == 0;
+*
+*     this is interpreted as default indexing, i.e.
+*
+=       index[m][k] = k;
+*
+*   double *coord
+*     (Given) Pointer to the first element of the tabular coordinate array,
+*     treated as though it were defined as
+*
+=       double coord[K_M]...[K_2][K_1][M];
+*
+*     (see tabprm::K) i.e. with the M dimension varying fastest so that the
+*     M elements of a coordinate vector are stored contiguously in memory.
+*
+*   int nc
+*     (Returned) Total number of coordinate vectors in the coordinate array
+*     being the product K_1 * K_2 * ... * K_M (see tabprm::K).
+*
+*   int padding
+*     (An unused variable inserted for alignment purposes only.)
+*
+*   int *sense
+*     (Returned) Pointer to the first element of a vector of length tabprm::M
+*     whose elements indicate whether the corresponding indexing vector is
+*     monotonic increasing (+1), or decreasing (-1).
+*
+*   int *p0
+*     (Returned) Pointer to the first element of a vector of length tabprm::M
+*     of interpolated indices into the coordinate array such that Upsilon_m,
+*     as defined in Paper III, is equal to (p0[m] + 1) + tabprm::delta[m].
+*
+*   double *delta
+*     (Returned) Pointer to the first element of a vector of length tabprm::M
+*     of interpolated indices into the coordinate array such that Upsilon_m,
+*     as defined in Paper III, is equal to (tabprm::p0[m] + 1) + delta[m].
+*
+*   double *extrema
+*     (Returned) Pointer to the first element of an array that records the
+*     minimum and maximum value of each element of the coordinate vector in
+*     each row of the coordinate array, treated as though it were defined as
+*
+=       double extrema[K_M]...[K_2][2][M]
+*
+*     (see tabprm::K).  The minimum is recorded in the first element of the
+*     compressed K_1 dimension, then the maximum.  This array is used by the
+*     inverse table lookup function, tabs2x(), to speed up table searches.
+*
+*   struct wcserr *err
+*     (Returned) If enabled, when an error status is returned this struct
+*     contains detailed information about the error, see wcserr_enable().
+*
+*   int m_flag
+*     (For internal use only.)
+*   int m_M
+*     (For internal use only.)
+*   int m_N
+*     (For internal use only.)
+*   int set_M
+*     (For internal use only.)
+*   int m_K
+*     (For internal use only.)
+*   int m_map
+*     (For internal use only.)
+*   int m_crval
+*     (For internal use only.)
+*   int m_index
+*     (For internal use only.)
+*   int m_indxs
+*     (For internal use only.)
+*   int m_coord
+*     (For internal use only.)
+*
+*
+* Global variable: const char *tab_errmsg[] - Status return messages
+* ------------------------------------------------------------------
+* Error messages to match the status value returned from each function.
+*
+*===========================================================================*/
+
+#ifndef WCSLIB_TAB
+#define WCSLIB_TAB
+
+#include "wcserr.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+extern const char *tab_errmsg[];
+
+enum tab_errmsg_enum {
+  TABERR_SUCCESS      = 0,	/* Success. */
+  TABERR_NULL_POINTER = 1,	/* Null tabprm pointer passed. */
+  TABERR_MEMORY       = 2,	/* Memory allocation failed. */
+  TABERR_BAD_PARAMS   = 3,	/* Invalid tabular parameters. */
+  TABERR_BAD_X        = 4,	/* One or more of the x coordinates were
+				   invalid. */
+  TABERR_BAD_WORLD    = 5	/* One or more of the world coordinates were
+				   invalid. */
+};
+
+struct tabprm {
+  /* Initialization flag (see the prologue above).                          */
+  /*------------------------------------------------------------------------*/
+  int    flag;			/* Set to zero to force initialization.     */
+
+  /* Parameters to be provided (see the prologue above).                    */
+  /*------------------------------------------------------------------------*/
+  int    M;			/* Number of tabular coordinate axes.       */
+  int    *K;			/* Vector of length M whose elements        */
+				/* (K_1, K_2,... K_M) record the lengths of */
+				/* the axes of the coordinate array and of  */
+				/* each indexing vector.                    */
+  int    *map;			/* Vector of length M usually such that     */
+				/* map[m-1] == i-1 for coordinate array     */
+				/* axis m and image axis i (see above).     */
+  double *crval;		/* Vector of length M containing the index  */
+				/* value for the reference pixel for each   */
+				/* of the tabular coordinate axes.          */
+  double **index;		/* Vector of pointers to M indexing vectors */
+				/* of lengths (K_1, K_2,... K_M).           */
+  double *coord;		/* (1+M)-dimensional tabular coordinate     */
+				/* array (see above).                       */
+
+  /* Information derived from the parameters supplied.                      */
+  /*------------------------------------------------------------------------*/
+  int    nc;			/* Number of coordinate vectors (of length  */
+				/* M) in the coordinate array.              */
+  int    padding;		/* (Dummy inserted for alignment purposes.) */
+  int    *sense;		/* Vector of M flags that indicate whether  */
+				/* the Mth indexing vector is monotonic     */
+				/* increasing, or else decreasing.          */
+  int    *p0;			/* Vector of M indices.                     */
+  double *delta;		/* Vector of M increments.                  */
+  double *extrema;		/* (1+M)-dimensional array of coordinate    */
+				/* extrema.                                 */
+
+  /* Error handling                                                         */
+  /*------------------------------------------------------------------------*/
+  struct wcserr *err;
+
+  /* Private - the remainder are for memory management.                     */
+  /*------------------------------------------------------------------------*/
+  int    m_flag, m_M, m_N;
+  int    set_M;
+  int    *m_K, *m_map;
+  double *m_crval, **m_index, **m_indxs, *m_coord;
+};
+
+/* Size of the tabprm struct in int units, used by the Fortran wrappers. */
+#define TABLEN (sizeof(struct tabprm)/sizeof(int))
+
+
+int tabini(int alloc, int M, const int K[], struct tabprm *tab);
+
+int tabmem(struct tabprm *tab);
+
+int tabcpy(int alloc, const struct tabprm *tabsrc, struct tabprm *tabdst);
+
+int tabfree(struct tabprm *tab);
+
+int tabprt(const struct tabprm *tab);
+
+int tabset(struct tabprm *tab);
+
+int tabx2s(struct tabprm *tab, int ncoord, int nelem, const double x[],
+           double world[], int stat[]);
+
+int tabs2x(struct tabprm *tab, int ncoord, int nelem, const double world[],
+           double x[], int stat[]);
+
+
+/* Deprecated. */
+#define tabini_errmsg tab_errmsg
+#define tabcpy_errmsg tab_errmsg
+#define tabfree_errmsg tab_errmsg
+#define tabprt_errmsg tab_errmsg
+#define tabset_errmsg tab_errmsg
+#define tabx2s_errmsg tab_errmsg
+#define tabs2x_errmsg tab_errmsg
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* WCSLIB_TAB */
diff --git a/cextern/wcslib/C/wcs.c b/cextern/wcslib/C/wcs.c
new file mode 100644
index 0000000..2e73798
--- /dev/null
+++ b/cextern/wcslib/C/wcs.c
@@ -0,0 +1,3226 @@
+/*============================================================================
+
+  WCSLIB 4.16 - an implementation of the FITS WCS standard.
+  Copyright (C) 1995-2012, Mark Calabretta
+
+  This file is part of WCSLIB.
+
+  WCSLIB is free software: you can redistribute it and/or modify it under the
+  terms of the GNU Lesser General Public License as published by the Free
+  Software Foundation, either version 3 of the License, or (at your option)
+  any later version.
+
+  WCSLIB 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 Lesser General Public License for
+  more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with WCSLIB.  If not, see http://www.gnu.org/licenses.
+
+  Direct correspondence concerning WCSLIB to mark at calabretta.id.au
+
+  Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
+  http://www.atnf.csiro.au/people/Mark.Calabretta
+  $Id: wcs.c,v 4.16 2012/11/07 04:42:44 cal103 Exp $
+*===========================================================================*/
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "wcserr.h"
+#include "wcsmath.h"
+#include "wcsprintf.h"
+#include "wcstrig.h"
+#include "wcsunits.h"
+#include "wcsutil.h"
+#include "lin.h"
+#include "log.h"
+#include "spc.h"
+#include "prj.h"
+#include "sph.h"
+#include "cel.h"
+#include "tab.h"
+#include "wcs.h"
+
+const int WCSSET = 137;
+
+/* Maximum number of PVi_ma and PSi_ma keywords. */
+int NPVMAX = 64;
+int NPSMAX =  8;
+
+/* Map status return value to message. */
+const char *wcs_errmsg[] = {
+  "Success",
+  "Null wcsprm pointer passed",
+  "Memory allocation failed",
+  "Linear transformation matrix is singular",
+  "Inconsistent or unrecognized coordinate axis types",
+  "Invalid parameter value",
+  "Invalid coordinate transformation parameters",
+  "Ill-conditioned coordinate transformation parameters",
+  "One or more of the pixel coordinates were invalid",
+  "One or more of the world coordinates were invalid",
+  "Invalid world coordinate",
+  "No solution found in the specified interval",
+  "Invalid subimage specification",
+  "Non-separable subimage coordinate system"};
+
+/* Convenience macro for invoking wcserr_set(). */
+#define WCS_ERRMSG(status) WCSERR_SET(status), wcs_errmsg[status]
+
+#ifndef signbit
+#define signbit(X) ((X) < 0.0 ? 1 : 0)
+#endif
+
+/* Internal helper functions, not for general use. */
+static int wcs_types(struct wcsprm *);
+static int wcs_units(struct wcsprm *);
+
+/*--------------------------------------------------------------------------*/
+
+int wcsnpv(int npvmax) { if (npvmax >= 0) NPVMAX = npvmax; return NPVMAX; }
+int wcsnps(int npsmax) { if (npsmax >= 0) NPSMAX = npsmax; return NPSMAX; }
+
+/*--------------------------------------------------------------------------*/
+
+int wcsini(int alloc, int naxis, struct wcsprm *wcs)
+
+{
+  static const char *function = "wcsini";
+
+  int i, j, k, status;
+  double *cd;
+  struct wcserr **err;
+
+  if (wcs == 0x0) return WCSERR_NULL_POINTER;
+
+  /* Initialize error message handling. */
+  err = &(wcs->err);
+  if (wcs->flag != -1) {
+    if (wcs->err) free(wcs->err);
+    if (wcs->lin.err) free(wcs->lin.err);
+    if (wcs->cel.err) free(wcs->cel.err);
+    if (wcs->spc.err) free(wcs->spc.err);
+    if (wcs->cel.prj.err) free(wcs->cel.prj.err);
+  }
+  wcs->err = 0x0;
+  wcs->lin.err = 0x0;
+  wcs->cel.err = 0x0;
+  wcs->spc.err = 0x0;
+  wcs->cel.prj.err = 0x0;
+
+
+  /* Initialize pointers. */
+  if (wcs->flag == -1 || wcs->m_flag != WCSSET) {
+    if (wcs->flag == -1) {
+      wcs->types = 0x0;
+      wcs->lin.flag = -1;
+      wcs->tab = 0x0;
+    }
+
+    /* Initialize memory management. */
+    wcs->m_flag  = 0;
+    wcs->m_naxis = 0;
+    wcs->m_crpix = 0x0;
+    wcs->m_pc    = 0x0;
+    wcs->m_cdelt = 0x0;
+    wcs->m_crval = 0x0;
+    wcs->m_cunit = 0x0;
+    wcs->m_ctype = 0x0;
+    wcs->m_pv    = 0x0;
+    wcs->m_ps    = 0x0;
+    wcs->m_cd    = 0x0;
+    wcs->m_crota = 0x0;
+    wcs->m_colax = 0x0;
+    wcs->m_cname = 0x0;
+    wcs->m_crder = 0x0;
+    wcs->m_csyer = 0x0;
+    wcs->m_tab   = 0x0;
+    wcs->m_wtb   = 0x0;
+  }
+
+  if (naxis < 0) {
+    return wcserr_set(WCSERR_SET(WCSERR_MEMORY),
+      "naxis must not be negative (got %d)", naxis);
+  }
+
+
+  /* Allocate memory for arrays if required. */
+  if (alloc ||
+     wcs->crpix == 0x0 ||
+     wcs->pc    == 0x0 ||
+     wcs->cdelt == 0x0 ||
+     wcs->crval == 0x0 ||
+     wcs->cunit == 0x0 ||
+     wcs->ctype == 0x0 ||
+     (NPVMAX && wcs->pv == 0x0) ||
+     (NPSMAX && wcs->ps == 0x0) ||
+     wcs->cd    == 0x0 ||
+     wcs->crota == 0x0 ||
+     wcs->colax == 0x0 ||
+     wcs->cname == 0x0 ||
+     wcs->crder == 0x0 ||
+     wcs->csyer == 0x0) {
+
+    /* Was sufficient allocated previously? */
+    if (wcs->m_flag == WCSSET &&
+       (wcs->m_naxis < naxis  ||
+        wcs->npvmax  < NPVMAX ||
+        wcs->npsmax  < NPSMAX)) {
+      /* No, free it. */
+      wcsfree(wcs);
+    }
+
+
+    if (alloc || wcs->crpix == 0x0) {
+      if (wcs->m_crpix) {
+        /* In case the caller fiddled with it. */
+        wcs->crpix = wcs->m_crpix;
+
+      } else {
+        if (!(wcs->crpix = calloc(naxis, sizeof(double)))) {
+          return wcserr_set(WCS_ERRMSG(WCSERR_MEMORY));
+        }
+
+        wcs->m_flag  = WCSSET;
+        wcs->m_naxis = naxis;
+        wcs->m_crpix = wcs->crpix;
+      }
+    }
+
+    if (alloc || wcs->pc == 0x0) {
+      if (wcs->m_pc) {
+        /* In case the caller fiddled with it. */
+        wcs->pc = wcs->m_pc;
+
+      } else {
+        if (!(wcs->pc = calloc(naxis*naxis, sizeof(double)))) {
+          wcsfree(wcs);
+          return wcserr_set(WCS_ERRMSG(WCSERR_MEMORY));
+        }
+
+        wcs->m_flag  = WCSSET;
+        wcs->m_naxis = naxis;
+        wcs->m_pc    = wcs->pc;
+      }
+    }
+
+    if (alloc || wcs->cdelt == 0x0) {
+      if (wcs->m_cdelt) {
+        /* In case the caller fiddled with it. */
+        wcs->cdelt = wcs->m_cdelt;
+
+      } else {
+        if (!(wcs->cdelt = calloc(naxis, sizeof(double)))) {
+          wcsfree(wcs);
+          return wcserr_set(WCS_ERRMSG(WCSERR_MEMORY));
+        }
+
+        wcs->m_flag  = WCSSET;
+        wcs->m_naxis = naxis;
+        wcs->m_cdelt = wcs->cdelt;
+      }
+    }
+
+    if (alloc || wcs->crval == 0x0) {
+      if (wcs->m_crval) {
+        /* In case the caller fiddled with it. */
+        wcs->crval = wcs->m_crval;
+
+      } else {
+        if (!(wcs->crval = calloc(naxis, sizeof(double)))) {
+          wcsfree(wcs);
+          return wcserr_set(WCS_ERRMSG(WCSERR_MEMORY));
+        }
+
+        wcs->m_flag  = WCSSET;
+        wcs->m_naxis = naxis;
+        wcs->m_crval = wcs->crval;
+      }
+    }
+
+    if (alloc || wcs->cunit == 0x0) {
+      if (wcs->m_cunit) {
+        /* In case the caller fiddled with it. */
+        wcs->cunit = wcs->m_cunit;
+
+      } else {
+        if (!(wcs->cunit = calloc(naxis, sizeof(char [72])))) {
+          wcsfree(wcs);
+          return wcserr_set(WCS_ERRMSG(WCSERR_MEMORY));
+        }
+
+        wcs->m_flag  = WCSSET;
+        wcs->m_naxis = naxis;
+        wcs->m_cunit = wcs->cunit;
+      }
+    }
+
+    if (alloc || wcs->ctype == 0x0) {
+      if (wcs->m_ctype) {
+        /* In case the caller fiddled with it. */
+        wcs->ctype = wcs->m_ctype;
+
+      } else {
+        if (!(wcs->ctype = calloc(naxis, sizeof(char [72])))) {
+          wcsfree(wcs);
+          return wcserr_set(WCS_ERRMSG(WCSERR_MEMORY));
+        }
+
+        wcs->m_flag  = WCSSET;
+        wcs->m_naxis = naxis;
+        wcs->m_ctype = wcs->ctype;
+      }
+    }
+
+    if (alloc || wcs->pv == 0x0) {
+      if (wcs->m_pv) {
+        /* In case the caller fiddled with it. */
+        wcs->pv = wcs->m_pv;
+
+      } else {
+        if (NPVMAX) {
+          if (!(wcs->pv = calloc(NPVMAX, sizeof(struct pvcard)))) {
+            wcsfree(wcs);
+            return wcserr_set(WCS_ERRMSG(WCSERR_MEMORY));
+          }
+        } else {
+          wcs->pv = (struct pvcard *)0;
+        }
+
+        wcs->npvmax  = NPVMAX;
+
+        wcs->m_flag  = WCSSET;
+        wcs->m_naxis = naxis;
+        wcs->m_pv    = wcs->pv;
+      }
+    }
+
+    if (alloc || wcs->ps == 0x0) {
+      if (wcs->m_ps) {
+        /* In case the caller fiddled with it. */
+        wcs->ps = wcs->m_ps;
+
+      } else {
+        if (NPSMAX) {
+          if (!(wcs->ps = calloc(NPSMAX, sizeof(struct pscard)))) {
+            wcsfree(wcs);
+            return wcserr_set(WCS_ERRMSG(WCSERR_MEMORY));
+          }
+        } else {
+          wcs->ps = (struct pscard *)0;
+        }
+
+        wcs->npsmax  = NPSMAX;
+
+        wcs->m_flag  = WCSSET;
+        wcs->m_naxis = naxis;
+        wcs->m_ps    = wcs->ps;
+      }
+    }
+
+    if (alloc || wcs->cd == 0x0) {
+      if (wcs->m_cd) {
+        /* In case the caller fiddled with it. */
+        wcs->cd = wcs->m_cd;
+
+      } else {
+        if (!(wcs->cd = calloc(naxis*naxis, sizeof(double)))) {
+          wcsfree(wcs);
+          return wcserr_set(WCS_ERRMSG(WCSERR_MEMORY));
+        }
+
+        wcs->m_flag  = WCSSET;
+        wcs->m_naxis = naxis;
+        wcs->m_cd    = wcs->cd;
+      }
+    }
+
+    if (alloc || wcs->crota == 0x0) {
+      if (wcs->m_crota) {
+        /* In case the caller fiddled with it. */
+        wcs->crota = wcs->m_crota;
+
+      } else {
+        if (!(wcs->crota = calloc(naxis, sizeof(double)))) {
+          wcsfree(wcs);
+          return wcserr_set(WCS_ERRMSG(WCSERR_MEMORY));
+        }
+
+        wcs->m_flag  = WCSSET;
+        wcs->m_naxis = naxis;
+        wcs->m_crota = wcs->crota;
+      }
+    }
+
+    if (alloc || wcs->colax == 0x0) {
+      if (wcs->m_colax) {
+        /* In case the caller fiddled with it. */
+        wcs->colax = wcs->m_colax;
+
+      } else {
+        if (!(wcs->colax = calloc(naxis, sizeof(int)))) {
+          wcsfree(wcs);
+          return wcserr_set(WCS_ERRMSG(WCSERR_MEMORY));
+        }
+
+        wcs->m_flag  = WCSSET;
+        wcs->m_naxis = naxis;
+        wcs->m_colax = wcs->colax;
+      }
+    }
+
+    if (alloc || wcs->cname == 0x0) {
+      if (wcs->m_cname) {
+        /* In case the caller fiddled with it. */
+        wcs->cname = wcs->m_cname;
+
+      } else {
+        if (!(wcs->cname = calloc(naxis, sizeof(char [72])))) {
+          wcsfree(wcs);
+          return wcserr_set(WCS_ERRMSG(WCSERR_MEMORY));
+        }
+
+        wcs->m_flag  = WCSSET;
+        wcs->m_naxis = naxis;
+        wcs->m_cname = wcs->cname;
+      }
+    }
+
+    if (alloc || wcs->crder == 0x0) {
+      if (wcs->m_crder) {
+        /* In case the caller fiddled with it. */
+        wcs->crder = wcs->m_crder;
+
+      } else {
+        if (!(wcs->crder = calloc(naxis, sizeof(double)))) {
+          wcsfree(wcs);
+          return wcserr_set(WCS_ERRMSG(WCSERR_MEMORY));
+        }
+
+        wcs->m_flag  = WCSSET;
+        wcs->m_naxis = naxis;
+        wcs->m_crder = wcs->crder;
+      }
+    }
+
+    if (alloc || wcs->csyer == 0x0) {
+      if (wcs->m_csyer) {
+        /* In case the caller fiddled with it. */
+        wcs->csyer = wcs->m_csyer;
+
+      } else {
+        if (!(wcs->csyer = calloc(naxis, sizeof(double)))) {
+          wcsfree(wcs);
+          return wcserr_set(WCS_ERRMSG(WCSERR_MEMORY));
+        }
+
+        wcs->m_flag  = WCSSET;
+        wcs->m_naxis = naxis;
+        wcs->m_csyer = wcs->csyer;
+      }
+    }
+  }
+
+
+  wcs->flag  = 0;
+  wcs->naxis = naxis;
+
+
+  /* Set defaults for the linear transformation. */
+  wcs->lin.crpix  = wcs->crpix;
+  wcs->lin.pc     = wcs->pc;
+  wcs->lin.cdelt  = wcs->cdelt;
+  wcs->lin.m_flag = 0;
+  if ((status = linini(0, naxis, &(wcs->lin)))) {
+    return wcserr_set(WCS_ERRMSG(status));
+  }
+
+
+  /* CRVALia defaults to 0.0. */
+  for (i = 0; i < naxis; i++) {
+    wcs->crval[i] = 0.0;
+  }
+
+
+  /* CUNITia and CTYPEia are blank by default. */
+  for (i = 0; i < naxis; i++) {
+    memset(wcs->cunit[i], 0, 72);
+    memset(wcs->ctype[i], 0, 72);
+  }
+
+
+  /* Set defaults for the celestial transformation parameters. */
+  wcs->lonpole = UNDEFINED;
+  wcs->latpole = +90.0;
+
+  /* Set defaults for the spectral transformation parameters. */
+  wcs->restfrq = 0.0;
+  wcs->restwav = 0.0;
+
+  /* Default parameter values. */
+  wcs->npv = 0;
+  for (k = 0; k < wcs->npvmax; k++) {
+    wcs->pv[k].i = 0;
+    wcs->pv[k].m = 0;
+    wcs->pv[k].value = 0.0;
+  }
+
+  wcs->nps = 0;
+  for (k = 0; k < wcs->npsmax; k++) {
+    wcs->ps[k].i = 0;
+    wcs->ps[k].m = 0;
+    memset(wcs->ps[k].value, 0, 72);
+  }
+
+  /* Defaults for alternate linear transformations. */
+  cd = wcs->cd;
+  for (i = 0; i < naxis; i++) {
+    for (j = 0; j < naxis; j++) {
+      *(cd++) = 0.0;
+    }
+  }
+  for (i = 0; i < naxis; i++) {
+    wcs->crota[i] = 0.0;
+  }
+  wcs->altlin = 0;
+  wcs->velref = 0;
+
+  /* Defaults for auxiliary coordinate system information. */
+  memset(wcs->alt, 0, 4);
+  wcs->alt[0] = ' ';
+  wcs->colnum = 0;
+
+  memset(wcs->wcsname, 0, 72);
+  for (i = 0; i < naxis; i++) {
+    wcs->colax[i] = 0;
+    memset(wcs->cname[i], 0, 72);
+    wcs->crder[i] = UNDEFINED;
+    wcs->csyer[i] = UNDEFINED;
+  }
+  memset(wcs->radesys, 0, 72);
+  wcs->equinox    = UNDEFINED;
+  memset(wcs->specsys, 0, 72);
+  memset(wcs->ssysobs, 0, 72);
+  wcs->velosys    = UNDEFINED;
+  memset(wcs->ssyssrc, 0, 72);
+  wcs->zsource    = UNDEFINED;
+  wcs->obsgeo[0]  = UNDEFINED;
+  wcs->obsgeo[1]  = UNDEFINED;
+  wcs->obsgeo[2]  = UNDEFINED;
+  memset(wcs->dateobs, 0, 72);
+  memset(wcs->dateavg, 0, 72);
+  wcs->mjdobs     = UNDEFINED;
+  wcs->mjdavg     = UNDEFINED;
+
+  wcs->ntab = 0;
+  wcs->tab  = 0x0;
+  wcs->nwtb = 0;
+  wcs->wtb  = 0x0;
+
+  /* Reset derived values. */
+  strcpy(wcs->lngtyp, "    ");
+  strcpy(wcs->lattyp, "    ");
+  wcs->lng  = -1;
+  wcs->lat  = -1;
+  wcs->spec = -1;
+  wcs->cubeface = -1;
+
+  celini(&(wcs->cel));
+  spcini(&(wcs->spc));
+
+  return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int wcssub(
+  int alloc,
+  const struct wcsprm *wcssrc,
+  int *nsub,
+  int axes[],
+  struct wcsprm *wcsdst)
+
+{
+  static const char *function = "wcssub";
+
+  char *c, ctypei[16];
+  int  axis, cubeface, dealloc, dummy, i, itab, j, k, latitude, longitude, m,
+       *map = 0x0, msub, naxis, npv, nps, other, spectral, status, stokes;
+  const double *srcp;
+  double *dstp;
+  struct tabprm *tabp;
+  struct wcserr **err;
+
+  if (wcssrc == 0x0) return WCSERR_NULL_POINTER;
+  err = &(wcsdst->err);
+
+  if ((naxis = wcssrc->naxis) <= 0) {
+    return wcserr_set(WCSERR_SET(WCSERR_MEMORY),
+      "naxis must be positive (got %d)", naxis);
+  }
+
+  if (!(map = calloc(naxis, sizeof(int)))) {
+    return wcserr_set(WCS_ERRMSG(WCSERR_MEMORY));
+  }
+
+  if (nsub == 0x0) {
+    nsub = &dummy;
+    *nsub = naxis;
+  } else if (*nsub == 0) {
+    *nsub = naxis;
+  }
+
+  if ((dealloc = (axes == 0x0))) {
+    /* Construct an index array. */
+    if (!(axes = calloc(naxis, sizeof(int)))) {
+      free(map);
+      return wcserr_set(WCS_ERRMSG(WCSERR_MEMORY));
+    }
+
+    for (i = 0; i < naxis; i++) {
+      axes[i] = i+1;
+    }
+  }
+
+  /* So that we don't try to free an uninitialized pointer on cleanup. */
+  wcsdst->m_tab = 0x0;
+
+
+  msub = 0;
+  for (j = 0; j < *nsub; j++) {
+    axis = axes[j];
+
+    if (abs(axis) > 0x1000) {
+      /* Subimage extraction by type. */
+      k = abs(axis) & 0xFF;
+
+      longitude = k & WCSSUB_LONGITUDE;
+      latitude  = k & WCSSUB_LATITUDE;
+      cubeface  = k & WCSSUB_CUBEFACE;
+      spectral  = k & WCSSUB_SPECTRAL;
+      stokes    = k & WCSSUB_STOKES;
+
+      if ((other = (axis < 0))) {
+        longitude = !longitude;
+        latitude  = !latitude;
+        cubeface  = !cubeface;
+        spectral  = !spectral;
+        stokes    = !stokes;
+      }
+
+      for (i = 0; i < naxis; i++) {
+        strncpy (ctypei, (char *)(wcssrc->ctype + i), 8);
+        ctypei[8] = '\0';
+
+        /* Find the last non-blank character. */
+        c = ctypei + 8;
+        while (c-- > ctypei) {
+          if (*c == ' ') *c = '\0';
+          if (*c != '\0') break;
+        }
+
+        if (
+          strcmp(ctypei,   "RA")  == 0 ||
+          strcmp(ctypei+1, "LON") == 0 ||
+          strcmp(ctypei+2, "LN")  == 0 ||
+          strncmp(ctypei,   "RA---", 5) == 0 ||
+          strncmp(ctypei+1, "LON-", 4) == 0 ||
+          strncmp(ctypei+2, "LN-", 3) == 0) {
+          if (!longitude) {
+            continue;
+          }
+
+        } else if (
+          strcmp(ctypei,   "DEC") == 0 ||
+          strcmp(ctypei+1, "LAT") == 0 ||
+          strcmp(ctypei+2, "LT")  == 0 ||
+          strncmp(ctypei,   "DEC--", 5) == 0 ||
+          strncmp(ctypei+1, "LAT-", 4) == 0 ||
+          strncmp(ctypei+2, "LT-", 3) == 0) {
+          if (!latitude) {
+            continue;
+          }
+
+        } else if (strcmp(ctypei, "CUBEFACE") == 0) {
+          if (!cubeface) {
+            continue;
+          }
+
+        } else if ((
+          strncmp(ctypei, "FREQ", 4) == 0 ||
+          strncmp(ctypei, "ENER", 4) == 0 ||
+          strncmp(ctypei, "WAVN", 4) == 0 ||
+          strncmp(ctypei, "VRAD", 4) == 0 ||
+          strncmp(ctypei, "WAVE", 4) == 0 ||
+          strncmp(ctypei, "VOPT", 4) == 0 ||
+          strncmp(ctypei, "ZOPT", 4) == 0 ||
+          strncmp(ctypei, "AWAV", 4) == 0 ||
+          strncmp(ctypei, "VELO", 4) == 0 ||
+          strncmp(ctypei, "BETA", 4) == 0) &&
+          (ctypei[4] == '\0' || ctypei[4] == '-')) {
+          if (!spectral) {
+            continue;
+          }
+
+        } else if (strcmp(ctypei, "STOKES") == 0) {
+          if (!stokes) {
+            continue;
+          }
+
+        } else if (!other) {
+          continue;
+        }
+
+        /* This axis is wanted, but has it already been added? */
+        for (k = 0; k < msub; k++) {
+          if (map[k] == i+1) {
+            break;
+          }
+        }
+        if (k == msub) map[msub++] = i+1;
+      }
+
+    } else if (0 < axis && axis <= naxis) {
+      /* Check that the requested axis has not already been added. */
+      for (k = 0; k < msub; k++) {
+        if (map[k] == axis) {
+          break;
+        }
+      }
+      if (k == msub) map[msub++] = axis;
+
+    } else if (axis == 0) {
+      /* Graft on a new axis. */
+      map[msub++] = 0;
+
+    } else {
+      status = wcserr_set(WCS_ERRMSG(WCSERR_BAD_SUBIMAGE));
+      goto cleanup;
+    }
+  }
+
+  if ((*nsub = msub) == 0) {
+    status = wcsini(alloc, 0, wcsdst);
+    goto cleanup;
+  }
+
+  for (i = 0; i < *nsub; i++) {
+    axes[i] = map[i];
+  }
+
+
+  /* Construct the inverse axis map:
+     axes[i] == j means that output axis i+1 comes from input axis j,
+     axes[i] == 0 means to create a new axis,
+      map[i] == j means that input axis i+1 goes to output axis j,
+      map[i] == 0 means that input axis i+1 is not used. */
+  for (i = 0; i < naxis; i++) {
+    map[i] = 0;
+  }
+
+  for (i = 0; i < *nsub; i++) {
+    if (axes[i] > 0) {
+      map[axes[i]-1] = i+1;
+    }
+  }
+
+  /* Check that the subimage coordinate system is separable. */
+  if (*nsub < naxis) {
+    srcp = wcssrc->pc;
+    for (i = 0; i < naxis; i++) {
+      for (j = 0; j < naxis; j++) {
+        if (*(srcp++) == 0.0 || j == i) continue;
+
+        if ((map[i] == 0) != (map[j] == 0)) {
+          status = wcserr_set(WCS_ERRMSG(WCSERR_NON_SEPARABLE));
+          goto cleanup;
+        }
+      }
+    }
+  }
+
+
+  /* Initialize the destination. */
+  npv = NPVMAX;
+  nps = NPSMAX;
+
+  NPVMAX = 0;
+  for (k = 0; k < wcssrc->npv; k++) {
+    i = wcssrc->pv[k].i;
+    if (i == 0 || (i > 0 && map[i-1])) {
+      NPVMAX++;
+    }
+  }
+
+  NPSMAX = 0;
+  for (k = 0; k < wcssrc->nps; k++) {
+    i = wcssrc->ps[k].i;
+    if (i > 0 && map[i-1]) {
+      NPSMAX++;
+    }
+  }
+
+  status = wcsini(alloc, *nsub, wcsdst);
+
+  NPVMAX = npv;
+  NPSMAX = nps;
+
+  if (status) {
+    goto cleanup;
+  }
+
+
+  /* Linear transformation. */
+  srcp = wcssrc->crpix;
+  dstp = wcsdst->crpix;
+  for (j = 0; j < *nsub; j++, dstp++) {
+    if (axes[j] > 0) {
+      k = axes[j] - 1;
+      *dstp = *(srcp+k);
+    }
+  }
+
+  srcp = wcssrc->pc;
+  dstp = wcsdst->pc;
+  for (i = 0; i < *nsub; i++) {
+    if (axes[i] > 0) {
+      for (j = 0; j < *nsub; j++, dstp++) {
+        if (axes[j] > 0) {
+          k = (axes[i]-1)*naxis + (axes[j]-1);
+          *dstp = *(srcp+k);
+        }
+      }
+    }
+  }
+
+  srcp = wcssrc->cdelt;
+  dstp = wcsdst->cdelt;
+  for (i = 0; i < *nsub; i++, dstp++) {
+    if (axes[i] > 0) {
+      k = axes[i] - 1;
+      *dstp = *(srcp+k);
+    }
+  }
+
+  /* Coordinate reference value. */
+  srcp = wcssrc->crval;
+  dstp = wcsdst->crval;
+  for (i = 0; i < *nsub; i++, dstp++) {
+    if (axes[i] > 0) {
+      k = axes[i] - 1;
+      *dstp = *(srcp+k);
+    }
+  }
+
+  /* Coordinate units and type. */
+  for (i = 0; i < *nsub; i++) {
+    if (axes[i] > 0) {
+      k = axes[i] - 1;
+      strncpy(wcsdst->cunit[i], wcssrc->cunit[k], 72);
+      strncpy(wcsdst->ctype[i], wcssrc->ctype[k], 72);
+    }
+  }
+
+  /* Celestial and spectral transformation parameters. */
+  wcsdst->lonpole = wcssrc->lonpole;
+  wcsdst->latpole = wcssrc->latpole;
+  wcsdst->restfrq = wcssrc->restfrq;
+  wcsdst->restwav = wcssrc->restwav;
+
+  /* Parameter values. */
+  npv = 0;
+  for (k = 0; k < wcssrc->npv; k++) {
+    i = wcssrc->pv[k].i;
+    if (i == 0 || (i > 0 && map[i-1])) {
+      /* i == 0 is a special code for the latitude axis. */
+      wcsdst->pv[npv] = wcssrc->pv[k];
+      wcsdst->pv[npv].i = map[i-1];
+      npv++;
+    }
+  }
+  wcsdst->npv = npv;
+
+  nps = 0;
+  for (k = 0; k < wcssrc->nps; k++) {
+    i = wcssrc->ps[k].i;
+    if (i > 0 && map[i-1]) {
+      wcsdst->ps[nps] = wcssrc->ps[k];
+      wcsdst->ps[nps].i = map[i-1];
+      nps++;
+    }
+  }
+  wcsdst->nps = nps;
+
+  /* Alternate linear transformations. */
+  srcp = wcssrc->cd;
+  dstp = wcsdst->cd;
+  for (i = 0; i < *nsub; i++) {
+    if (axes[i] > 0) {
+      for (j = 0; j < *nsub; j++, dstp++) {
+        if (axes[j] > 0) {
+          k = (axes[i]-1)*naxis + (axes[j]-1);
+          *dstp = *(srcp+k);
+        }
+      }
+    }
+  }
+
+  srcp = wcssrc->crota;
+  dstp = wcsdst->crota;
+  for (i = 0; i < *nsub; i++, dstp++) {
+    if (axes[i] > 0) {
+      k = axes[i] - 1;
+      *dstp = *(srcp+k);
+    }
+  }
+
+  wcsdst->altlin = wcssrc->altlin;
+  wcsdst->velref = wcssrc->velref;
+
+  /* Auxiliary coordinate system information. */
+  strncpy(wcsdst->alt, wcssrc->alt, 4);
+  wcsdst->colnum = wcssrc->colnum;
+
+  strncpy(wcsdst->wcsname, wcssrc->wcsname, 72);
+  for (i = 0; i < *nsub; i++) {
+    if (axes[i] > 0) {
+      k = axes[i] - 1;
+      wcsdst->colax[i] = wcssrc->colax[k];
+      strncpy(wcsdst->cname[i], wcssrc->cname[k], 72);
+      wcsdst->crder[i] = wcssrc->crder[k];
+      wcsdst->csyer[i] = wcssrc->csyer[k];
+    }
+  }
+
+  strncpy(wcsdst->radesys, wcssrc->radesys, 72);
+  wcsdst->equinox = wcssrc->equinox;
+
+  strncpy(wcsdst->specsys, wcssrc->specsys, 72);
+  strncpy(wcsdst->ssysobs, wcssrc->ssysobs, 72);
+  wcsdst->velosys = wcssrc->velosys;
+  strncpy(wcsdst->ssyssrc, wcssrc->ssyssrc, 72);
+  wcsdst->zsource = wcssrc->zsource;
+
+  wcsdst->obsgeo[0] = wcssrc->obsgeo[0];
+  wcsdst->obsgeo[1] = wcssrc->obsgeo[1];
+  wcsdst->obsgeo[2] = wcssrc->obsgeo[2];
+
+  strncpy(wcsdst->dateobs, wcssrc->dateobs, 72);
+  strncpy(wcsdst->dateavg, wcssrc->dateavg, 72);
+  wcsdst->mjdobs = wcssrc->mjdobs;
+  wcsdst->mjdavg = wcssrc->mjdavg;
+
+
+  /* Coordinate lookup tables; only copy what's needed. */
+  wcsdst->ntab = 0;
+  for (itab = 0; itab < wcssrc->ntab; itab++) {
+    /* Is this table wanted? */
+    for (m = 0; m < wcssrc->tab[itab].M; m++) {
+      i = wcssrc->tab[itab].map[m];
+
+      if (map[i-1]) {
+        wcsdst->ntab++;
+        break;
+      }
+    }
+  }
+
+  if (wcsdst->ntab) {
+    /* Allocate memory for tabprm structs. */
+    if (!(wcsdst->tab = calloc(wcsdst->ntab, sizeof(struct tabprm)))) {
+      wcsdst->ntab = 0;
+
+      status = wcserr_set(WCS_ERRMSG(WCSERR_MEMORY));
+      goto cleanup;
+    }
+
+    wcsdst->m_tab = wcsdst->tab;
+  }
+
+  tabp = wcsdst->tab;
+  for (itab = 0; itab < wcssrc->ntab; itab++) {
+    for (m = 0; m < wcssrc->tab[itab].M; m++) {
+      i = wcssrc->tab[itab].map[m];
+
+      if (map[i-1]) {
+        if ((status = tabcpy(1, wcssrc->tab + itab, tabp))) {
+          wcserr_set(WCS_ERRMSG(status));
+          goto cleanup;
+        }
+
+        tabp++;
+        break;
+      }
+    }
+  }
+
+
+cleanup:
+  if (map) free(map);
+  if (dealloc) {
+    free(axes);
+  }
+
+  if (status && wcsdst->m_tab) free(wcsdst->m_tab);
+
+  return status;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int wcsfree(struct wcsprm *wcs)
+
+{
+  int j;
+
+  if (wcs == 0x0) return WCSERR_NULL_POINTER;
+
+  if (wcs->flag == -1) {
+    wcs->lin.flag = -1;
+
+  } else {
+    /* Free memory allocated by wcsini(). */
+    if (wcs->m_flag == WCSSET) {
+      if (wcs->crpix == wcs->m_crpix) wcs->crpix = 0x0;
+      if (wcs->pc    == wcs->m_pc)    wcs->pc    = 0x0;
+      if (wcs->cdelt == wcs->m_cdelt) wcs->cdelt = 0x0;
+      if (wcs->crval == wcs->m_crval) wcs->crval = 0x0;
+      if (wcs->cunit == wcs->m_cunit) wcs->cunit = 0x0;
+      if (wcs->ctype == wcs->m_ctype) wcs->ctype = 0x0;
+      if (wcs->pv    == wcs->m_pv)    wcs->pv    = 0x0;
+      if (wcs->ps    == wcs->m_ps)    wcs->ps    = 0x0;
+      if (wcs->cd    == wcs->m_cd)    wcs->cd    = 0x0;
+      if (wcs->crota == wcs->m_crota) wcs->crota = 0x0;
+      if (wcs->colax == wcs->m_colax) wcs->colax = 0x0;
+      if (wcs->cname == wcs->m_cname) wcs->cname = 0x0;
+      if (wcs->crder == wcs->m_crder) wcs->crder = 0x0;
+      if (wcs->csyer == wcs->m_csyer) wcs->csyer = 0x0;
+      if (wcs->tab   == wcs->m_tab)   wcs->tab   = 0x0;
+      if (wcs->wtb   == wcs->m_wtb)   wcs->wtb   = 0x0;
+
+      if (wcs->m_crpix)  free(wcs->m_crpix);
+      if (wcs->m_pc)     free(wcs->m_pc);
+      if (wcs->m_cdelt)  free(wcs->m_cdelt);
+      if (wcs->m_crval)  free(wcs->m_crval);
+      if (wcs->m_cunit)  free(wcs->m_cunit);
+      if (wcs->m_ctype)  free(wcs->m_ctype);
+      if (wcs->m_pv)     free(wcs->m_pv);
+      if (wcs->m_ps)     free(wcs->m_ps);
+      if (wcs->m_cd)     free(wcs->m_cd);
+      if (wcs->m_crota)  free(wcs->m_crota);
+      if (wcs->m_colax)  free(wcs->m_colax);
+      if (wcs->m_cname)  free(wcs->m_cname);
+      if (wcs->m_crder)  free(wcs->m_crder);
+      if (wcs->m_csyer)  free(wcs->m_csyer);
+
+      /* Free memory allocated by wcstab(). */
+      if (wcs->m_tab) {
+        for (j = 0; j < wcs->ntab; j++) {
+          tabfree(wcs->m_tab + j);
+        }
+
+        free(wcs->m_tab);
+      }
+      if (wcs->m_wtb) free(wcs->m_wtb);
+    }
+
+    /* Free memory allocated by wcsset(). */
+    if (wcs->types) free(wcs->types);
+
+    if (wcs->lin.crpix == wcs->m_crpix) wcs->lin.crpix = 0x0;
+    if (wcs->lin.pc    == wcs->m_pc)    wcs->lin.pc    = 0x0;
+    if (wcs->lin.cdelt == wcs->m_cdelt) wcs->lin.cdelt = 0x0;
+  }
+
+  wcs->m_flag   = 0;
+  wcs->m_naxis  = 0x0;
+  wcs->m_crpix  = 0x0;
+  wcs->m_pc     = 0x0;
+  wcs->m_cdelt  = 0x0;
+  wcs->m_crval  = 0x0;
+  wcs->m_cunit  = 0x0;
+  wcs->m_ctype  = 0x0;
+  wcs->m_pv     = 0x0;
+  wcs->m_ps     = 0x0;
+  wcs->m_cd     = 0x0;
+  wcs->m_crota  = 0x0;
+  wcs->m_colax  = 0x0;
+  wcs->m_cname  = 0x0;
+  wcs->m_crder  = 0x0;
+  wcs->m_csyer  = 0x0;
+
+  wcs->ntab  = 0;
+  wcs->m_tab = 0x0;
+  wcs->nwtb  = 0;
+  wcs->m_wtb = 0x0;
+
+  wcs->types = 0x0;
+
+  wcs->flag = 0;
+
+  if (wcs->err) {
+    free(wcs->err);
+    wcs->err = 0x0;
+  }
+
+  linfree(&(wcs->lin));
+  celfree(&(wcs->cel));
+  spcfree(&(wcs->spc));
+
+  return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int wcsprt(const struct wcsprm *wcs)
+
+{
+  int i, j, k;
+  struct wtbarr *wtbp;
+
+  if (wcs == 0x0) return WCSERR_NULL_POINTER;
+
+  if (wcs->flag != WCSSET) {
+    wcsprintf("The wcsprm struct is UNINITIALIZED.\n");
+    return 0;
+  }
+
+  wcsprintf("       flag: %d\n", wcs->flag);
+  wcsprintf("      naxis: %d\n", wcs->naxis);
+  WCSPRINTF_PTR("      crpix: ", wcs->crpix, "\n");
+  wcsprintf("            ");
+  for (i = 0; i < wcs->naxis; i++) {
+    wcsprintf("  %- 11.5g", wcs->crpix[i]);
+  }
+  wcsprintf("\n");
+
+  /* Linear transformation. */
+  k = 0;
+  WCSPRINTF_PTR("         pc: ", wcs->pc, "\n");
+  for (i = 0; i < wcs->naxis; i++) {
+    wcsprintf("    pc[%d][]:", i);
+    for (j = 0; j < wcs->naxis; j++) {
+      wcsprintf("  %- 11.5g", wcs->pc[k++]);
+    }
+    wcsprintf("\n");
+  }
+
+  /* Coordinate increment at reference point. */
+  WCSPRINTF_PTR("      cdelt: ", wcs->cdelt, "\n");
+  wcsprintf("            ");
+  for (i = 0; i < wcs->naxis; i++) {
+    wcsprintf("  %- 11.5g", wcs->cdelt[i]);
+  }
+  wcsprintf("\n");
+
+  /* Coordinate value at reference point. */
+  WCSPRINTF_PTR("      crval: ", wcs->crval, "\n");
+  wcsprintf("            ");
+  for (i = 0; i < wcs->naxis; i++) {
+    wcsprintf("  %- 11.5g", wcs->crval[i]);
+  }
+  wcsprintf("\n");
+
+  /* Coordinate units and type. */
+  WCSPRINTF_PTR("      cunit: ", wcs->cunit, "\n");
+  for (i = 0; i < wcs->naxis; i++) {
+    wcsprintf("             \"%s\"\n", wcs->cunit[i]);
+  }
+
+  WCSPRINTF_PTR("      ctype: ", wcs->ctype, "\n");
+  for (i = 0; i < wcs->naxis; i++) {
+    wcsprintf("             \"%s\"\n", wcs->ctype[i]);
+  }
+
+  /* Celestial and spectral transformation parameters. */
+  if (undefined(wcs->lonpole)) {
+    wcsprintf("    lonpole: UNDEFINED\n");
+  } else {
+    wcsprintf("    lonpole: %9f\n", wcs->lonpole);
+  }
+  wcsprintf("    latpole: %9f\n", wcs->latpole);
+  wcsprintf("    restfrq: %f\n", wcs->restfrq);
+  wcsprintf("    restwav: %f\n", wcs->restwav);
+
+  /* Parameter values. */
+  wcsprintf("        npv: %d\n", wcs->npv);
+  wcsprintf("     npvmax: %d\n", wcs->npvmax);
+  WCSPRINTF_PTR("         pv: ", wcs->pv, "\n");
+  for (i = 0; i < wcs->npv; i++) {
+    wcsprintf("             %3d%4d  %- 11.5g\n", (wcs->pv[i]).i,
+      (wcs->pv[i]).m, (wcs->pv[i]).value);
+  }
+  wcsprintf("        nps: %d\n", wcs->nps);
+  wcsprintf("     npsmax: %d\n", wcs->npsmax);
+  WCSPRINTF_PTR("         ps: ", wcs->ps, "\n");
+  for (i = 0; i < wcs->nps; i++) {
+    wcsprintf("             %3d%4d  %s\n", (wcs->ps[i]).i,
+      (wcs->ps[i]).m, (wcs->ps[i]).value);
+  }
+
+  /* Alternate linear transformations. */
+  k = 0;
+  WCSPRINTF_PTR("         cd: ", wcs->cd, "\n");
+  if (wcs->cd) {
+    for (i = 0; i < wcs->naxis; i++) {
+      wcsprintf("    cd[%d][]:", i);
+      for (j = 0; j < wcs->naxis; j++) {
+        wcsprintf("  %- 11.5g", wcs->cd[k++]);
+      }
+      wcsprintf("\n");
+    }
+  }
+
+  WCSPRINTF_PTR("      crota: ", wcs->crota, "\n");
+  if (wcs->crota) {
+    wcsprintf("            ");
+    for (i = 0; i < wcs->naxis; i++) {
+      wcsprintf("  %- 11.5g", wcs->crota[i]);
+    }
+    wcsprintf("\n");
+  }
+
+  wcsprintf("     altlin: %d\n", wcs->altlin);
+  wcsprintf("     velref: %d\n", wcs->velref);
+
+
+
+  /* Auxiliary coordinate system information. */
+  wcsprintf("        alt: '%c'\n", wcs->alt[0]);
+  wcsprintf("     colnum: %d\n", wcs->colnum);
+
+  WCSPRINTF_PTR("      colax: ", wcs->colax, "\n");
+  if (wcs->colax) {
+    wcsprintf("           ");
+    for (i = 0; i < wcs->naxis; i++) {
+      wcsprintf("  %5d", wcs->colax[i]);
+    }
+    wcsprintf("\n");
+  }
+
+  if (wcs->wcsname[0] == '\0') {
+    wcsprintf("    wcsname: UNDEFINED\n");
+  } else {
+    wcsprintf("    wcsname: \"%s\"\n", wcs->wcsname);
+  }
+
+  WCSPRINTF_PTR("      cname: ", wcs->cname, "\n");
+  if (wcs->cname) {
+    for (i = 0; i < wcs->naxis; i++) {
+      if (wcs->cname[i][0] == '\0') {
+        wcsprintf("             UNDEFINED\n");
+      } else {
+        wcsprintf("             \"%s\"\n", wcs->cname[i]);
+      }
+    }
+  }
+
+  WCSPRINTF_PTR("      crder: ", wcs->crder, "\n");
+  if (wcs->crder) {
+    wcsprintf("           ");
+    for (i = 0; i < wcs->naxis; i++) {
+      if (undefined(wcs->crder[i])) {
+        wcsprintf("  UNDEFINED   ");
+      } else {
+        wcsprintf("  %- 11.5g", wcs->crder[i]);
+      }
+    }
+    wcsprintf("\n");
+  }
+
+  WCSPRINTF_PTR("      csyer: ", wcs->csyer, "\n");
+  if (wcs->csyer) {
+    wcsprintf("           ");
+    for (i = 0; i < wcs->naxis; i++) {
+      if (undefined(wcs->csyer[i])) {
+        wcsprintf("  UNDEFINED   ");
+      } else {
+        wcsprintf("  %- 11.5g", wcs->csyer[i]);
+      }
+    }
+    wcsprintf("\n");
+  }
+
+  if (wcs->radesys[0] == '\0') {
+    wcsprintf("    radesys: UNDEFINED\n");
+  } else {
+    wcsprintf("    radesys: \"%s\"\n", wcs->radesys);
+  }
+
+  if (undefined(wcs->equinox)) {
+    wcsprintf("    equinox: UNDEFINED\n");
+  } else {
+    wcsprintf("    equinox: %9f\n", wcs->equinox);
+  }
+
+  if (wcs->specsys[0] == '\0') {
+    wcsprintf("    specsys: UNDEFINED\n");
+  } else {
+    wcsprintf("    specsys: \"%s\"\n", wcs->specsys);
+  }
+
+  if (wcs->ssysobs[0] == '\0') {
+    wcsprintf("    ssysobs: UNDEFINED\n");
+  } else {
+    wcsprintf("    ssysobs: \"%s\"\n", wcs->ssysobs);
+  }
+
+  if (undefined(wcs->velosys)) {
+    wcsprintf("    velosys: UNDEFINED\n");
+  } else {
+    wcsprintf("    velosys: %9f\n", wcs->velosys);
+  }
+
+  if (wcs->ssyssrc[0] == '\0') {
+    wcsprintf("    ssyssrc: UNDEFINED\n");
+  } else {
+    wcsprintf("    ssyssrc: \"%s\"\n", wcs->ssyssrc);
+  }
+
+  if (undefined(wcs->zsource)) {
+    wcsprintf("    zsource: UNDEFINED\n");
+  } else {
+    wcsprintf("    zsource: %9f\n", wcs->zsource);
+  }
+
+  wcsprintf("     obsgeo: ");
+  for (i = 0; i < 3; i++) {
+    if (undefined(wcs->obsgeo[i])) {
+      wcsprintf("UNDEFINED     ");
+    } else {
+      wcsprintf("%- 11.5g  ", wcs->obsgeo[i]);
+    }
+  }
+  wcsprintf("\n");
+
+  if (wcs->dateobs[0] == '\0') {
+    wcsprintf("    dateobs: UNDEFINED\n");
+  } else {
+    wcsprintf("    dateobs: \"%s\"\n", wcs->dateobs);
+  }
+
+  if (wcs->dateavg[0] == '\0') {
+    wcsprintf("    dateavg: UNDEFINED\n");
+  } else {
+    wcsprintf("    dateavg: \"%s\"\n", wcs->dateavg);
+  }
+
+  if (undefined(wcs->mjdobs)) {
+    wcsprintf("     mjdobs: UNDEFINED\n");
+  } else {
+    wcsprintf("     mjdobs: %9f\n", wcs->mjdobs);
+  }
+
+  if (undefined(wcs->mjdavg)) {
+    wcsprintf("     mjdavg: UNDEFINED\n");
+  } else {
+    wcsprintf("     mjdavg: %9f\n", wcs->mjdavg);
+  }
+
+  wcsprintf("       ntab: %d\n", wcs->ntab);
+  WCSPRINTF_PTR("        tab: ", wcs->tab, "");
+  if (wcs->tab != 0x0) wcsprintf("  (see below)");
+  wcsprintf("\n");
+  wcsprintf("       nwtb: %d\n", wcs->nwtb);
+  WCSPRINTF_PTR("        wtb: ", wcs->wtb, "");
+  if (wcs->wtb != 0x0) wcsprintf("  (see below)");
+  wcsprintf("\n");
+
+  /* Derived values. */
+  WCSPRINTF_PTR("      types: ", wcs->types, "\n           ");
+  for (i = 0; i < wcs->naxis; i++) {
+    wcsprintf("%5d", wcs->types[i]);
+  }
+  wcsprintf("\n");
+
+  wcsprintf("     lngtyp: \"%s\"\n", wcs->lngtyp);
+  wcsprintf("     lattyp: \"%s\"\n", wcs->lattyp);
+  wcsprintf("        lng: %d\n", wcs->lng);
+  wcsprintf("        lat: %d\n", wcs->lat);
+  wcsprintf("       spec: %d\n", wcs->spec);
+  wcsprintf("   cubeface: %d\n", wcs->cubeface);
+
+  WCSPRINTF_PTR("        err: ", wcs->err, "\n");
+  if (wcs->err) {
+    wcserr_prt(wcs->err, "             ");
+  }
+
+  wcsprintf("        lin: (see below)\n");
+  wcsprintf("        cel: (see below)\n");
+  wcsprintf("        spc: (see below)\n");
+
+  /* Memory management. */
+  wcsprintf("     m_flag: %d\n", wcs->m_flag);
+  wcsprintf("    m_naxis: %d\n", wcs->m_naxis);
+  WCSPRINTF_PTR("    m_crpix: ", wcs->m_crpix, "");
+  if (wcs->m_crpix == wcs->crpix) wcsprintf("  (= crpix)");
+  wcsprintf("\n");
+  WCSPRINTF_PTR("       m_pc: ", wcs->m_pc, "");
+  if (wcs->m_pc == wcs->pc) wcsprintf("  (= pc)");
+  wcsprintf("\n");
+  WCSPRINTF_PTR("    m_cdelt: ", wcs->m_cdelt, "");
+  if (wcs->m_cdelt == wcs->cdelt) wcsprintf("  (= cdelt)");
+  wcsprintf("\n");
+  WCSPRINTF_PTR("    m_crval: ", wcs->m_crval, "");
+  if (wcs->m_crval == wcs->crval) wcsprintf("  (= crval)");
+  wcsprintf("\n");
+  WCSPRINTF_PTR("    m_cunit: ", wcs->m_cunit, "");
+  if (wcs->m_cunit == wcs->cunit) wcsprintf("  (= cunit)");
+  wcsprintf("\n");
+  WCSPRINTF_PTR("    m_ctype: ", wcs->m_ctype, "");
+  if (wcs->m_ctype == wcs->ctype) wcsprintf("  (= ctype)");
+  wcsprintf("\n");
+  WCSPRINTF_PTR("       m_pv: ", wcs->m_pv, "");
+  if (wcs->m_pv == wcs->pv) wcsprintf("  (= pv)");
+  wcsprintf("\n");
+  WCSPRINTF_PTR("       m_ps: ", wcs->m_ps, "");
+  if (wcs->m_ps == wcs->ps) wcsprintf("  (= ps)");
+  wcsprintf("\n");
+  WCSPRINTF_PTR("       m_cd: ", wcs->m_cd, "");
+  if (wcs->m_cd == wcs->cd) wcsprintf("  (= cd)");
+  wcsprintf("\n");
+  WCSPRINTF_PTR("    m_crota: ", wcs->m_crota, "");
+  if (wcs->m_crota == wcs->crota) wcsprintf("  (= crota)");
+  wcsprintf("\n");
+  wcsprintf("\n");
+  WCSPRINTF_PTR("    m_colax: ", wcs->m_colax, "");
+  if (wcs->m_colax == wcs->colax) wcsprintf("  (= colax)");
+  wcsprintf("\n");
+  WCSPRINTF_PTR("    m_cname: ", wcs->m_cname, "");
+  if (wcs->m_cname == wcs->cname) wcsprintf("  (= cname)");
+  wcsprintf("\n");
+  WCSPRINTF_PTR("    m_crder: ", wcs->m_crder, "");
+  if (wcs->m_crder == wcs->crder) wcsprintf("  (= crder)");
+  wcsprintf("\n");
+  WCSPRINTF_PTR("    m_csyer: ", wcs->m_csyer, "");
+  if (wcs->m_csyer == wcs->csyer) wcsprintf("  (= csyer)");
+  wcsprintf("\n");
+  WCSPRINTF_PTR("      m_tab: ", wcs->m_tab, "");
+  if (wcs->m_tab == wcs->tab) wcsprintf("  (= tab)");
+  wcsprintf("\n");
+  WCSPRINTF_PTR("      m_wtb: ", wcs->m_wtb, "");
+  if (wcs->m_wtb == wcs->wtb) wcsprintf("  (= wtb)");
+  wcsprintf("\n");
+
+  /* Tabular transformation parameters. */
+  if ((wtbp = wcs->wtb)) {
+    for (j = 0; j < wcs->nwtb; j++, wtbp++) {
+      wcsprintf("\n");
+      wcsprintf("wtb[%d].*\n", j);
+      wcsprintf("          i: %d\n", wtbp->i);
+      wcsprintf("          m: %d\n", wtbp->m);
+      wcsprintf("       kind: %c\n", wtbp->kind);
+      wcsprintf("     extnam: %s\n", wtbp->extnam);
+      wcsprintf("     extver: %d\n", wtbp->extver);
+      wcsprintf("     extlev: %d\n", wtbp->extlev);
+      wcsprintf("      ttype: %s\n", wtbp->ttype);
+      wcsprintf("        row: %ld\n", wtbp->row);
+      wcsprintf("       ndim: %d\n", wtbp->ndim);
+      WCSPRINTF_PTR("     dimlen: ", wtbp->dimlen, "\n");
+      WCSPRINTF_PTR("     arrayp: ", wtbp->arrayp, " -> ");
+      WCSPRINTF_PTR("", *(wtbp->arrayp), "\n");
+    }
+  }
+
+  if (wcs->tab) {
+    for (j = 0; j < wcs->ntab; j++) {
+      wcsprintf("\n");
+      wcsprintf("tab[%d].*\n", j);
+      tabprt(wcs->tab + j);
+    }
+  }
+
+  /* Linear transformation parameters. */
+  wcsprintf("\n");
+  wcsprintf("   lin.*\n");
+  linprt(&(wcs->lin));
+
+  /* Celestial transformation parameters. */
+  wcsprintf("\n");
+  wcsprintf("   cel.*\n");
+  celprt(&(wcs->cel));
+
+  /* Spectral transformation parameters. */
+  wcsprintf("\n");
+  wcsprintf("   spc.*\n");
+  spcprt(&(wcs->spc));
+
+  return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int wcsperr(const struct wcsprm *wcs, const char *prefix)
+
+{
+  int j;
+
+  if (wcs == 0x0) return WCSERR_NULL_POINTER;
+
+  if (!wcserr_prt(wcs->err, prefix)) {
+    wcserr_prt(wcs->lin.err, prefix);
+    wcserr_prt(wcs->cel.err, prefix);
+    wcserr_prt(wcs->cel.prj.err, prefix);
+    wcserr_prt(wcs->spc.err, prefix);
+    if (wcs->tab) {
+      for (j = 0; j < wcs->ntab; j++) {
+        wcserr_prt((wcs->tab + j)->err, prefix);
+      }
+    }
+  }
+
+  return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int wcsset(struct wcsprm *wcs)
+
+{
+  static const char *function = "wcsset";
+
+  char scode[4], stype[5];
+  int i, j, k, m, naxis, status;
+  double lambda, rho;
+  double *cd, *pc;
+  struct celprm *wcscel = &(wcs->cel);
+  struct prjprm *wcsprj = &(wcscel->prj);
+  struct spcprm *wcsspc = &(wcs->spc);
+  struct wcserr **err;
+
+
+  if (wcs == 0x0) return WCSERR_NULL_POINTER;
+  err = &(wcs->err);
+
+  /* Determine axis types from CTYPEia. */
+  if ((status = wcs_types(wcs))) {
+    return status;
+  }
+
+  /* Convert to canonical units. */
+  if ((status = wcs_units(wcs))) {
+    return status;
+  }
+
+
+  /* Non-linear celestial axes present? */
+  if (wcs->lng >= 0 && wcs->types[wcs->lng] == 2200) {
+    celini(wcscel);
+
+    /* CRVALia, LONPOLEa, and LATPOLEa keyvalues. */
+    wcscel->ref[0] = wcs->crval[wcs->lng];
+    wcscel->ref[1] = wcs->crval[wcs->lat];
+    wcscel->ref[2] = wcs->lonpole;
+    wcscel->ref[3] = wcs->latpole;
+
+    /* PVi_ma keyvalues. */
+    for (k = 0; k < wcs->npv; k++) {
+      i = wcs->pv[k].i - 1;
+      m = wcs->pv[k].m;
+
+      if (i == -1) {
+        /* From a PROJPn keyword. */
+        i = wcs->lat;
+      }
+
+      if (i == wcs->lat) {
+        /* PVi_ma associated with latitude axis. */
+        if (m < 30) {
+          wcsprj->pv[m] = wcs->pv[k].value;
+        }
+
+      } else if (i == wcs->lng) {
+        /* PVi_ma associated with longitude axis. */
+        switch (m) {
+        case 0:
+          wcscel->offset = (wcs->pv[k].value != 0.0);
+          break;
+        case 1:
+          wcscel->phi0   = wcs->pv[k].value;
+          break;
+        case 2:
+          wcscel->theta0 = wcs->pv[k].value;
+          break;
+        case 3:
+          /* If present, overrides LONPOLEa. */
+          wcscel->ref[2] = wcs->pv[k].value;
+          break;
+        case 4:
+          /* If present, overrides LATPOLEa. */
+          wcscel->ref[3] = wcs->pv[k].value;
+          break;
+        default:
+          return wcserr_set(WCSERR_SET(WCSERR_BAD_COORD_TRANS),
+            "PV%i_%i%s: Unrecognized coordinate transformation parameter",
+            i+1, m, wcs->alt);
+          break;
+        }
+      }
+    }
+
+    /* Do simple alias translations. */
+    if (strncmp(wcs->ctype[wcs->lng]+5, "GLS", 3) == 0) {
+      wcscel->offset = 1;
+      wcscel->phi0   = 0.0;
+      wcscel->theta0 = wcs->crval[wcs->lat];
+      strcpy(wcsprj->code, "SFL");
+
+    } else if (strncmp(wcs->ctype[wcs->lng]+5, "NCP", 3) == 0) {
+      /* Convert NCP to SIN. */
+      if (wcscel->ref[1] == 0.0) {
+        return wcserr_set(WCSERR_SET(WCSERR_BAD_PARAM),
+          "Invalid projection: NCP blows up on the equator");
+      }
+
+      strcpy(wcsprj->code, "SIN");
+      wcsprj->pv[1] = 0.0;
+      wcsprj->pv[2] = cosd(wcscel->ref[1])/sind(wcscel->ref[1]);
+
+    } else {
+      strncpy(wcsprj->code, wcs->ctype[wcs->lng]+5, 3);
+      wcsprj->code[3] = '\0';
+    }
+
+    /* Initialize the celestial transformation routines. */
+    wcsprj->r0 = 0.0;
+    if ((status = celset(wcscel))) {
+      return wcserr_set(WCS_ERRMSG(status+3));
+    }
+
+    /* Update LONPOLE, LATPOLE, and PVi_ma keyvalues. */
+    wcs->lonpole = wcscel->ref[2];
+    wcs->latpole = wcscel->ref[3];
+
+    for (k = 0; k < wcs->npv; k++) {
+      i = wcs->pv[k].i - 1;
+      m = wcs->pv[k].m;
+
+      if (i == wcs->lng) {
+        switch (m) {
+        case 1:
+          wcs->pv[k].value = wcscel->phi0;
+          break;
+        case 2:
+          wcs->pv[k].value = wcscel->theta0;
+          break;
+        case 3:
+          wcs->pv[k].value = wcscel->ref[2];
+          break;
+        case 4:
+          wcs->pv[k].value = wcscel->ref[3];
+          break;
+        }
+      }
+    }
+  }
+
+
+  /* Non-linear spectral axis present? */
+  if (wcs->spec >= 0 && wcs->types[wcs->spec] == 3300) {
+    spcini(wcsspc);
+    if ((status = spctype(wcs->ctype[wcs->spec], stype, scode, 0x0, 0x0, 0x0,
+                          0x0, 0x0, err))) {
+      return status;
+    }
+    strcpy(wcsspc->type, stype);
+    strcpy(wcsspc->code, scode);
+
+    /* CRVALia, RESTFRQa, and RESTWAVa keyvalues. */
+    wcsspc->crval = wcs->crval[wcs->spec];
+    wcsspc->restfrq = wcs->restfrq;
+    wcsspc->restwav = wcs->restwav;
+
+    /* PVi_ma keyvalues. */
+    for (k = 0; k < wcs->npv; k++) {
+      i = wcs->pv[k].i - 1;
+      m = wcs->pv[k].m;
+
+      if (i == wcs->spec) {
+        /* PVi_ma associated with grism axis. */
+        if (m < 7) {
+          wcsspc->pv[m] = wcs->pv[k].value;
+        }
+      }
+    }
+
+    /* Initialize the spectral transformation routines. */
+    if ((status = spcset(wcsspc))) {
+      return wcserr_set(WCS_ERRMSG(status+3));
+    }
+  }
+
+
+  /* Tabular axes present? */
+  for (j = 0; j < wcs->ntab; j++) {
+    if ((status = tabset(wcs->tab + j))) {
+      return wcserr_set(WCS_ERRMSG(status+3));
+    }
+  }
+
+
+  /* Initialize the linear transformation. */
+  naxis = wcs->naxis;
+  wcs->altlin &= 7;
+  if (wcs->altlin > 1 && !(wcs->altlin & 1)) {
+    pc = wcs->pc;
+
+    if (wcs->altlin & 2) {
+      /* Copy CDi_ja to PCi_ja and reset CDELTia. */
+      cd = wcs->cd;
+      for (i = 0; i < naxis; i++) {
+        for (j = 0; j < naxis; j++) {
+          *(pc++) = *(cd++);
+        }
+        wcs->cdelt[i] = 1.0;
+      }
+
+    } else if (wcs->altlin & 4) {
+      /* Construct PCi_ja from CROTAia. */
+      if ((i = wcs->lng) >= 0 && (j = wcs->lat) >= 0) {
+        rho = wcs->crota[j];
+
+        if (wcs->cdelt[i] == 0.0) {
+          return wcserr_set(WCSERR_SET(WCSERR_SINGULAR_MTX),
+            "Singular transformation matrix, CDELT%d is zero", i+1);
+        }
+        lambda = wcs->cdelt[j]/wcs->cdelt[i];
+
+        *(pc + i*naxis + i) = *(pc + j*naxis + j) = cosd(rho);
+        *(pc + i*naxis + j) = *(pc + j*naxis + i) = sind(rho);
+        *(pc + i*naxis + j) *= -lambda;
+        *(pc + j*naxis + i) /=  lambda;
+      }
+    }
+  }
+
+  wcs->lin.crpix  = wcs->crpix;
+  wcs->lin.pc     = wcs->pc;
+  wcs->lin.cdelt  = wcs->cdelt;
+  if ((status = linset(&(wcs->lin)))) {
+    return wcserr_set(WCS_ERRMSG(status));
+  }
+
+
+  /* Strip off trailing blanks and null-fill auxiliary string members. */
+  wcsutil_null_fill(4, wcs->alt);
+  wcsutil_null_fill(72, wcs->wcsname);
+  for (i = 0; i < naxis; i++) {
+    wcsutil_null_fill(72, wcs->cname[i]);
+  }
+  wcsutil_null_fill(72, wcs->radesys);
+  wcsutil_null_fill(72, wcs->specsys);
+  wcsutil_null_fill(72, wcs->ssysobs);
+  wcsutil_null_fill(72, wcs->ssyssrc);
+  wcsutil_null_fill(72, wcs->dateobs);
+  wcsutil_null_fill(72, wcs->dateavg);
+
+  wcs->flag = WCSSET;
+
+  return 0;
+}
+
+/* : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :  */
+
+int wcs_types(struct wcsprm *wcs)
+
+{
+  static const char *function = "wcs_types";
+
+  const int  nalias = 2;
+  const char aliases [2][4] = {"NCP", "GLS"};
+
+  const char *alt = "";
+  char ctypei[16], pcode[4], requir[9], scode[4], specsys[9];
+  int i, j, m, naxis, *ndx = 0x0, type;
+  struct wcserr **err;
+
+  if (wcs == 0x0) return WCSERR_NULL_POINTER;
+  err = &(wcs->err);
+
+  /* Parse the CTYPEia keyvalues. */
+  pcode[0]  = '\0';
+  requir[0] = '\0';
+  wcs->lng  = -1;
+  wcs->lat  = -1;
+  wcs->spec = -1;
+  wcs->cubeface = -1;
+
+  if (*(wcs->alt) != ' ') alt = wcs->alt;
+
+
+  naxis = wcs->naxis;
+  if (wcs->types) free(wcs->types);
+  wcs->types = calloc(naxis, sizeof(int));
+  if (wcs->types == NULL) {
+    return wcserr_set(WCS_ERRMSG(WCSERR_MEMORY));
+  }
+
+  for (i = 0; i < naxis; i++) {
+    /* Null fill. */
+    wcsutil_null_fill(72, wcs->ctype[i]);
+
+    strncpy(ctypei, wcs->ctype[i], 15);
+    ctypei[15] = '\0';
+
+    /* Check for early Paper IV syntax (e.g. '-SIP' used by Spitzer). */
+    if (strlen(ctypei) == 12 && ctypei[8] == '-') {
+      /* Excise the "4-3-3" or "8-3"-form distortion code. */
+      ctypei[8] = '\0';
+
+      /* Remove trailing dashes from "8-3"-form codes. */
+      for (j = 7; j > 0; j--) {
+        if (ctypei[j] != '-') break;
+        ctypei[j] = '\0';
+      }
+    }
+
+    /* Logarithmic or tabular axis? */
+    wcs->types[i] = 0;
+    if (strcmp(ctypei+4, "-LOG") == 0) {
+      /* Logarithmic axis. */
+      wcs->types[i] = 400;
+
+    } else if (strcmp(ctypei+4, "-TAB") == 0) {
+      /* Tabular axis. */
+      wcs->types[i] = 500;
+    }
+
+    if (wcs->types[i]) {
+      /* Could have -LOG or -TAB with celestial or spectral types. */
+      ctypei[4] = '\0';
+
+      /* Take care of things like 'FREQ-LOG' or 'RA---TAB'. */
+      for (j = 3; j >= 0; j--) {
+        if (ctypei[j] != '-') break;
+        ctypei[j] = '\0';
+      }
+    }
+
+    /* Translate AIPS spectral types for spctyp(). */
+    if (spcaips(ctypei, wcs->velref, ctypei, specsys) == 0) {
+      strcpy(wcs->ctype[i], ctypei);
+      if (wcs->specsys[0] == '\0') strcpy(wcs->specsys, specsys);
+    }
+
+    /* Process linear axes. */
+    if (!(strlen(ctypei) == 8 && ctypei[4] == '-')) {
+      /* Identify Stokes, celestial and spectral types. */
+      if (strcmp(ctypei, "STOKES") == 0) {
+        /* STOKES axis. */
+        wcs->types[i] = 1100;
+
+      } else if (strcmp(ctypei, "RA")  == 0 ||
+        strcmp(ctypei+1, "LON") == 0 ||
+        strcmp(ctypei+2, "LN")  == 0) {
+        /* Longitude axis. */
+        if (wcs->lng < 0) wcs->lng = i;
+        wcs->types[i] += 2000;
+
+      } else if (strcmp(ctypei,   "DEC") == 0 ||
+                 strcmp(ctypei+1, "LAT") == 0 ||
+                 strcmp(ctypei+2, "LT")  == 0) {
+        /* Latitude axis. */
+        if (wcs->lat < 0) wcs->lat = i;
+        wcs->types[i] += 2001;
+
+      } else if (strcmp(ctypei, "CUBEFACE") == 0) {
+        /* CUBEFACE axis. */
+        if (wcs->cubeface == -1) {
+          wcs->types[i] = 2102;
+          wcs->cubeface = i;
+        } else {
+          /* Multiple CUBEFACE axes! */
+          return wcserr_set(WCSERR_SET(WCSERR_BAD_CTYPE),
+            "Multiple CUBEFACE axes (in CTYPE%d%.1s and CTYPE%d%.1s)",
+            wcs->cubeface+1, alt, i+1, alt);
+        }
+
+      } else if (spctyp(ctypei, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0) == 0) {
+        /* Spectral axis. */
+        if (wcs->spec < 0) wcs->spec = i;
+        wcs->types[i] += 3000;
+      }
+
+      continue;
+    }
+
+
+    /* CTYPEia is in "4-3" form; is it a recognized spectral type? */
+    if (spctyp(ctypei, 0x0, scode, 0x0, 0x0, 0x0, 0x0, 0x0) == 0) {
+      /* Non-linear spectral axis found. */
+      wcs->types[i] = 3300;
+
+      /* Check uniqueness. */
+      if (wcs->spec >= 0) {
+        return wcserr_set(WCSERR_SET(WCSERR_BAD_CTYPE),
+          "Multiple spectral axes (in CTYPE%d%.1s and CTYPE%d%.1s)",
+          wcs->spec+1, alt, i+1, alt);
+      }
+
+      wcs->spec = i;
+
+      continue;
+    }
+
+
+    /* Is it a recognized celestial projection? */
+    for (j = 0; j < prj_ncode; j++) {
+      if (strncmp(ctypei+5, prj_codes[j], 3) == 0) break;
+    }
+
+    if (j == prj_ncode) {
+      /* Not a standard projection code, maybe it's an alias. */
+      for (j = 0; j < nalias; j++) {
+        if (strncmp(ctypei+5, aliases[j], 3) == 0) break;
+      }
+
+      if (j == nalias) {
+        /* Not a recognized algorithm code of any type. */
+        wcs->types[i] = -1;
+        return wcserr_set(WCSERR_SET(WCSERR_BAD_CTYPE),
+          "Unrecognized projection code (%s in CTYPE%d%.1s)",
+          ctypei+5, i+1, alt);
+      }
+    }
+
+    /* Parse the celestial axis type. */
+    wcs->types[i] = 2200;
+    if (*pcode == '\0') {
+      /* The first of the two celestial axes. */
+      sprintf(pcode, "%.3s", ctypei+5);
+
+      if (strncmp(ctypei, "RA--", 4) == 0) {
+        wcs->lng = i;
+        strcpy(wcs->lngtyp, "RA");
+        strcpy(wcs->lattyp, "DEC");
+        ndx = &wcs->lat;
+        sprintf(requir, "DEC--%s", pcode);
+      } else if (strncmp(ctypei, "DEC-", 4) == 0) {
+        wcs->lat = i;
+        strcpy(wcs->lngtyp, "RA");
+        strcpy(wcs->lattyp, "DEC");
+        ndx = &wcs->lng;
+        sprintf(requir, "RA---%s", pcode);
+      } else if (strncmp(ctypei+1, "LON", 3) == 0) {
+        wcs->lng = i;
+        sprintf(wcs->lngtyp, "%cLON", ctypei[0]);
+        sprintf(wcs->lattyp, "%cLAT", ctypei[0]);
+        ndx = &wcs->lat;
+        sprintf(requir, "%s-%s", wcs->lattyp, pcode);
+      } else if (strncmp(ctypei+1, "LAT", 3) == 0) {
+        wcs->lat = i;
+        sprintf(wcs->lngtyp, "%cLON", ctypei[0]);
+        sprintf(wcs->lattyp, "%cLAT", ctypei[0]);
+        ndx = &wcs->lng;
+        sprintf(requir, "%s-%s", wcs->lngtyp, pcode);
+      } else if (strncmp(ctypei+2, "LN", 2) == 0) {
+        wcs->lng = i;
+        sprintf(wcs->lngtyp, "%c%cLN", ctypei[0], ctypei[1]);
+        sprintf(wcs->lattyp, "%c%cLT", ctypei[0], ctypei[1]);
+        ndx = &wcs->lat;
+        sprintf(requir, "%s-%s", wcs->lattyp, pcode);
+      } else if (strncmp(ctypei+2, "LT", 2) == 0) {
+        wcs->lat = i;
+        sprintf(wcs->lngtyp, "%c%cLN", ctypei[0], ctypei[1]);
+        sprintf(wcs->lattyp, "%c%cLT", ctypei[0], ctypei[1]);
+        ndx = &wcs->lng;
+        sprintf(requir, "%s-%s", wcs->lngtyp, pcode);
+      } else {
+        /* Unrecognized celestial type. */
+        wcs->types[i] = -1;
+
+        wcs->lng = -1;
+        wcs->lat = -1;
+        return wcserr_set(WCSERR_SET(WCSERR_BAD_CTYPE),
+          "Unrecognized celestial type (%5s in CTYPE%d%.1s)",
+          ctypei, i+1, alt);
+      }
+
+      if (wcs->lat >= 0) wcs->types[i]++;
+
+    } else {
+      /* Looking for the complementary celestial axis. */
+      if (wcs->lat < 0) wcs->types[i]++;
+
+      if (strncmp(ctypei, requir, 8) != 0) {
+        /* Inconsistent projection types. */
+        wcs->lng = -1;
+        wcs->lat = -1;
+        return wcserr_set(WCSERR_SET(WCSERR_BAD_CTYPE), "Inconsistent "
+          "projection types (expected %s, got %s in CTYPE%d%.1s)", requir,
+          ctypei, i+1, alt);
+      }
+
+      *ndx = i;
+      requir[0] = '\0';
+    }
+  }
+
+  /* Do we have a complementary pair of celestial axes? */
+  if (strcmp(requir, "")) {
+    /* Unmatched celestial axis. */
+    wcs->lng = -1;
+    wcs->lat = -1;
+    return wcserr_set(WCSERR_SET(WCSERR_BAD_CTYPE),
+      "Unmatched celestial axes");
+  }
+
+  /* Table group numbers. */
+  for (j = 0; j < wcs->ntab; j++) {
+    for (m = 0; m < wcs->tab[j].M; m++) {
+      /* Get image axis number. */
+      i = wcs->tab[j].map[m];
+
+      type = (wcs->types[i] / 100) % 10;
+      if (type != 5) {
+        return wcserr_set(WCSERR_SET(WCSERR_BAD_CTYPE),
+          "Table parameters set for non-table axis type");
+      }
+      wcs->types[i] += 10 * j;
+    }
+  }
+
+  return 0;
+}
+
+/* : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :  */
+
+int wcs_units(struct wcsprm *wcs)
+
+{
+  static const char *function = "wcs_units";
+
+  char ctype[9], units[16];
+  int  i, j, naxis;
+  double scale, offset, power;
+  struct wcserr *uniterr = 0x0, **err;
+
+  if (wcs == 0x0) return WCSERR_NULL_POINTER;
+  err = &(wcs->err);
+
+  naxis = wcs->naxis;
+  for (i = 0; i < naxis; i++) {
+    /* Use types set by wcs_types(). */
+    switch (wcs->types[i]/1000) {
+    case 2:
+      /* Celestial axis. */
+      strcpy(units, "deg");
+      break;
+
+    case 3:
+      /* Spectral axis. */
+      strncpy(ctype, wcs->ctype[i], 8);
+      ctype[8] = '\0';
+      spctyp(ctype, 0x0, 0x0, 0x0, units, 0x0, 0x0, 0x0);
+      break;
+
+    default:
+      continue;
+    }
+
+    /* Tabular axis, CDELTia and CRVALia relate to indices. */
+    if ((wcs->types[i]/100)%10 == 5) {
+      continue;
+    }
+
+    wcsutil_null_fill(72, wcs->cunit[i]);
+    if (wcs->cunit[i][0]) {
+      if (wcsunitse(wcs->cunit[i], units, &scale, &offset, &power,
+                    &uniterr)) {
+        wcserr_set(WCSERR_SET(WCSERR_BAD_COORD_TRANS),
+          "In CUNIT%d%.1s: %s", i, (*wcs->alt)?wcs->alt:"", uniterr->msg);
+        free(uniterr);
+        return WCSERR_BAD_COORD_TRANS;
+      }
+
+      if (scale != 1.0) {
+        wcs->cdelt[i] *= scale;
+        wcs->crval[i] *= scale;
+
+        for (j = 0; j < naxis; j++) {
+          *(wcs->cd + i*naxis + j) *= scale;
+        }
+
+        strcpy(wcs->cunit[i], units);
+      }
+
+    } else {
+      strcpy(wcs->cunit[i], units);
+    }
+  }
+
+  return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int wcsp2s(
+  struct wcsprm *wcs,
+  int ncoord,
+  int nelem,
+  const double pixcrd[],
+  double imgcrd[],
+  double phi[],
+  double theta[],
+  double world[],
+  int stat[])
+
+{
+  static const char *function = "wcsp2s";
+
+  int    bits, face, i, iso_x, iso_y, istat, *istatp, itab, k, m, nx, ny,
+        *statp, status, type;
+  double crvali, offset;
+  register double *img, *wrl;
+  struct celprm *wcscel = &(wcs->cel);
+  struct prjprm *wcsprj = &(wcscel->prj);
+  struct wcserr **err;
+
+  /* Initialize if required. */
+  if (wcs == 0x0) return WCSERR_NULL_POINTER;
+  err = &(wcs->err);
+
+  if (wcs->flag != WCSSET) {
+    if ((status = wcsset(wcs))) return status;
+  }
+
+  /* Sanity check. */
+  if (ncoord < 1 || (ncoord > 1 && nelem < wcs->naxis)) {
+    return wcserr_set(WCSERR_SET(WCSERR_BAD_CTYPE),
+      "ncoord and/or nelem inconsistent with the wcsprm");
+  }
+
+
+  /* Apply pixel-to-world linear transformation. */
+  if ((status = linp2x(&(wcs->lin), ncoord, nelem, pixcrd, imgcrd))) {
+    return wcserr_set(WCS_ERRMSG(status));
+  }
+
+  /* Initialize status vectors. */
+  if (!(istatp = calloc(ncoord, sizeof(int)))) {
+    return wcserr_set(WCS_ERRMSG(WCSERR_MEMORY));
+  }
+
+  stat[0] = 0;
+  wcsutil_setAli(ncoord, 1, stat);
+
+
+  /* Convert intermediate world coordinates to world coordinates. */
+  for (i = 0; i < wcs->naxis; i++) {
+    /* Extract the second digit of the axis type code. */
+    type = (wcs->types[i] / 100) % 10;
+
+    if (type <= 1) {
+      /* Linear or quantized coordinate axis. */
+      img = imgcrd + i;
+      wrl = world  + i;
+      crvali = wcs->crval[i];
+      for (k = 0; k < ncoord; k++) {
+        *wrl = *img + crvali;
+        img += nelem;
+        wrl += nelem;
+      }
+
+    } else if (wcs->types[i] == 2200) {
+      /* Convert celestial coordinates; do we have a CUBEFACE axis? */
+      if (wcs->cubeface != -1) {
+        /* Separation between faces. */
+        if (wcsprj->r0 == 0.0) {
+          offset = 90.0;
+        } else {
+          offset = wcsprj->r0*PI/2.0;
+        }
+
+        /* Lay out faces in a plane. */
+        img = imgcrd;
+        statp = stat;
+        bits = (1 << i) | (1 << wcs->lat);
+        for (k = 0; k < ncoord; k++, statp++) {
+          face = (int)(*(img+wcs->cubeface) + 0.5);
+          if (fabs(*(img+wcs->cubeface) - face) > 1e-10) {
+            *statp |= bits;
+            status = wcserr_set(WCS_ERRMSG(WCSERR_BAD_PIX));
+
+          } else {
+            *statp = 0;
+
+            switch (face) {
+            case 0:
+              *(img+wcs->lat) += offset;
+              break;
+            case 1:
+              break;
+            case 2:
+              *(img+i) += offset;
+              break;
+            case 3:
+              *(img+i) += offset*2;
+              break;
+            case 4:
+              *(img+i) += offset*3;
+              break;
+            case 5:
+              *(img+wcs->lat) -= offset;
+              break;
+            default:
+              *statp |= bits;
+              status = wcserr_set(WCS_ERRMSG(WCSERR_BAD_PIX));
+            }
+          }
+
+          img += nelem;
+        }
+      }
+
+      /* Check for constant x and/or y. */
+      nx = ncoord;
+      ny = 0;
+
+      if ((iso_x = wcsutil_allEq(ncoord, nelem, imgcrd+i))) {
+        nx = 1;
+        ny = ncoord;
+      }
+      if ((iso_y = wcsutil_allEq(ncoord, nelem, imgcrd+wcs->lat))) {
+        ny = 1;
+      }
+
+      /* Transform projection plane coordinates to celestial coordinates. */
+      if ((istat = celx2s(wcscel, nx, ny, nelem, nelem, imgcrd+i,
+                          imgcrd+wcs->lat, phi, theta, world+i,
+                          world+wcs->lat, istatp))) {
+        if (istat == CELERR_BAD_PIX) {
+          status = wcserr_set(WCS_ERRMSG(WCSERR_BAD_PIX));
+        } else {
+          status = wcserr_set(WCS_ERRMSG(istat+3));
+          goto cleanup;
+        }
+      }
+
+      /* If x and y were both constant, replicate values. */
+      if (iso_x && iso_y) {
+        wcsutil_setAll(ncoord, nelem, world+i);
+        wcsutil_setAll(ncoord, nelem, world+wcs->lat);
+        wcsutil_setAll(ncoord, 1, phi);
+        wcsutil_setAll(ncoord, 1, theta);
+        wcsutil_setAli(ncoord, 1, istatp);
+      }
+
+      if (istat == 5) {
+        bits = (1 << i) | (1 << wcs->lat);
+        wcsutil_setBit(ncoord, istatp, bits, stat);
+      }
+
+    } else if (type == 3 || type == 4) {
+      /* Check for constant x. */
+      nx = ncoord;
+      if ((iso_x = wcsutil_allEq(ncoord, nelem, imgcrd+i))) {
+        nx = 1;
+      }
+
+      istat = 0;
+      if (wcs->types[i] == 3300) {
+        /* Spectral coordinates. */
+        istat = spcx2s(&(wcs->spc), nx, nelem, nelem, imgcrd+i, world+i,
+                       istatp);
+        if (istat == SPCERR_BAD_X) {
+          status = wcserr_set(WCS_ERRMSG(WCSERR_BAD_PIX));
+        } else if (istat) {
+          status = wcserr_set(WCS_ERRMSG(istat+3));
+          goto cleanup;
+        }
+      } else if (type == 4) {
+        /* Logarithmic coordinates. */
+        istat = logx2s(wcs->crval[i], nx, nelem, nelem, imgcrd+i, world+i,
+                       istatp);
+        if (istat == LOGERR_BAD_X) {
+          if (*err == 0x0) {
+            wcserr_set(WCS_ERRMSG(WCSERR_BAD_PIX));
+          }
+        } else if (istat == LOGERR_BAD_LOG_REF_VAL) {
+          wcserr_set(WCSERR_SET(WCSERR_BAD_PARAM), log_errmsg[istat]);
+          goto cleanup;
+        }
+      }
+
+      /* If x was constant, replicate values. */
+      if (iso_x) {
+        wcsutil_setAll(ncoord, nelem, world+i);
+        wcsutil_setAli(ncoord, 1, istatp);
+      }
+
+      if (istat == 3) {
+        wcsutil_setBit(ncoord, istatp, 1 << i, stat);
+      }
+    }
+  }
+
+
+  /* Do tabular coordinates. */
+  for (itab = 0; itab < wcs->ntab; itab++) {
+    istat = tabx2s(wcs->tab + itab, ncoord, nelem, imgcrd, world, istatp);
+
+    if (istat == TABERR_BAD_X) {
+      status = wcserr_set(WCS_ERRMSG(WCSERR_BAD_PIX));
+
+      bits = 0;
+      for (m = 0; m < wcs->tab[itab].M; m++) {
+        bits |= 1 << wcs->tab[itab].map[m];
+      }
+      wcsutil_setBit(ncoord, istatp, bits, stat);
+
+    } else if (istat) {
+      if (istat == TABERR_BAD_PARAMS) istat = WCSERR_BAD_PARAM;
+      status = wcserr_set(WCS_ERRMSG(istat));
+      goto cleanup;
+    }
+  }
+
+
+  /* Zero the unused world coordinate elements. */
+  for (i = wcs->naxis; i < nelem; i++) {
+    world[i] = 0.0;
+    wcsutil_setAll(ncoord, nelem, world+i);
+  }
+
+cleanup:
+  free(istatp);
+  return status;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int wcss2p(
+  struct wcsprm* wcs,
+  int ncoord,
+  int nelem,
+  const double world[],
+  double phi[],
+  double theta[],
+  double imgcrd[],
+  double pixcrd[],
+  int stat[])
+
+{
+  static const char *function = "wcss2p";
+
+  int    bits, i, isolat, isolng, isospec, istat, *istatp, itab, k, m, nlat,
+         nlng, nwrld, status, type;
+  double crvali, offset;
+  register const double *wrl;
+  register double *img;
+  struct celprm *wcscel = &(wcs->cel);
+  struct prjprm *wcsprj = &(wcscel->prj);
+  struct wcserr **err;
+
+
+  /* Initialize if required. */
+  if (wcs == 0x0) return WCSERR_NULL_POINTER;
+  err = &(wcs->err);
+
+  if (wcs->flag != WCSSET) {
+    if ((status = wcsset(wcs))) return status;
+  }
+
+  /* Sanity check. */
+  if (ncoord < 1 || (ncoord > 1 && nelem < wcs->naxis)) {
+    return wcserr_set(WCSERR_SET(WCSERR_BAD_CTYPE),
+      "ncoord and/or nelem inconsistent with the wcsprm");
+  }
+
+  /* Initialize status vectors. */
+  if (!(istatp = calloc(ncoord, sizeof(int)))) {
+    return wcserr_set(WCS_ERRMSG(WCSERR_MEMORY));
+  }
+
+  status = 0;
+  stat[0] = 0;
+  wcsutil_setAli(ncoord, 1, stat);
+
+
+  /* Convert world coordinates to intermediate world coordinates. */
+  for (i = 0; i < wcs->naxis; i++) {
+    /* Extract the second digit of the axis type code. */
+    type = (wcs->types[i] / 100) % 10;
+
+    if (type <= 1) {
+      /* Linear or quantized coordinate axis. */
+      wrl = world  + i;
+      img = imgcrd + i;
+      crvali = wcs->crval[i];
+      for (k = 0; k < ncoord; k++) {
+        *img = *wrl - crvali;
+        wrl += nelem;
+        img += nelem;
+      }
+
+    } else if (wcs->types[i] == 2200) {
+      /* Celestial coordinates; check for constant lng and/or lat. */
+      nlng = ncoord;
+      nlat = 0;
+
+      if ((isolng = wcsutil_allEq(ncoord, nelem, world+i))) {
+        nlng = 1;
+        nlat = ncoord;
+      }
+      if ((isolat = wcsutil_allEq(ncoord, nelem, world+wcs->lat))) {
+        nlat = 1;
+      }
+
+      /* Transform celestial coordinates to projection plane coordinates. */
+      if ((istat = cels2x(wcscel, nlng, nlat, nelem, nelem, world+i,
+                          world+wcs->lat, phi, theta, imgcrd+i,
+                          imgcrd+wcs->lat, istatp))) {
+        if (istat == CELERR_BAD_WORLD) {
+          status = wcserr_set(WCS_ERRMSG(WCSERR_BAD_WORLD));
+        } else {
+          status = wcserr_set(WCS_ERRMSG(istat+3));
+          goto cleanup;
+        }
+      }
+
+      /* If lng and lat were both constant, replicate values. */
+      if (isolng && isolat) {
+        wcsutil_setAll(ncoord, nelem, imgcrd+i);
+        wcsutil_setAll(ncoord, nelem, imgcrd+wcs->lat);
+        wcsutil_setAll(ncoord, 1, phi);
+        wcsutil_setAll(ncoord, 1, theta);
+        wcsutil_setAli(ncoord, 1, istatp);
+      }
+
+      if (istat == CELERR_BAD_WORLD) {
+        bits = (1 << i) | (1 << wcs->lat);
+        wcsutil_setBit(ncoord, istatp, bits, stat);
+      }
+
+      /* Do we have a CUBEFACE axis? */
+      if (wcs->cubeface != -1) {
+        /* Separation between faces. */
+        if (wcsprj->r0 == 0.0) {
+          offset = 90.0;
+        } else {
+          offset = wcsprj->r0*PI/2.0;
+        }
+
+        /* Stack faces in a cube. */
+        img = imgcrd;
+        for (k = 0; k < ncoord; k++) {
+          if (*(img+wcs->lat) < -0.5*offset) {
+            *(img+wcs->lat) += offset;
+            *(img+wcs->cubeface) = 5.0;
+          } else if (*(img+wcs->lat) > 0.5*offset) {
+            *(img+wcs->lat) -= offset;
+            *(img+wcs->cubeface) = 0.0;
+          } else if (*(img+i) > 2.5*offset) {
+            *(img+i) -= 3.0*offset;
+            *(img+wcs->cubeface) = 4.0;
+          } else if (*(img+i) > 1.5*offset) {
+            *(img+i) -= 2.0*offset;
+            *(img+wcs->cubeface) = 3.0;
+          } else if (*(img+i) > 0.5*offset) {
+            *(img+i) -= offset;
+            *(img+wcs->cubeface) = 2.0;
+          } else {
+            *(img+wcs->cubeface) = 1.0;
+          }
+
+          img += nelem;
+        }
+      }
+
+    } else if (type == 3 || type == 4) {
+      /* Check for constancy. */
+      nwrld = ncoord;
+      if ((isospec = wcsutil_allEq(ncoord, nelem, world+i))) {
+        nwrld = 1;
+      }
+
+      istat = 0;
+      if (wcs->types[i] == 3300) {
+        /* Spectral coordinates. */
+        istat = spcs2x(&(wcs->spc), nwrld, nelem, nelem, world+i,
+                       imgcrd+i, istatp);
+        if (istat == SPCERR_BAD_SPEC) {
+          status = wcserr_set(WCS_ERRMSG(WCSERR_BAD_WORLD));
+        } else if (istat) {
+          status = wcserr_set(WCS_ERRMSG(istat+3));
+          goto cleanup;
+        }
+      } else if (type == 4) {
+        /* Logarithmic coordinates. */
+        istat = logs2x(wcs->crval[i], nwrld, nelem, nelem, world+i,
+                       imgcrd+i, istatp);
+        if (istat == LOGERR_BAD_WORLD) {
+          status = wcserr_set(WCS_ERRMSG(WCSERR_BAD_WORLD));
+        } else if (istat == LOGERR_BAD_LOG_REF_VAL) {
+          status = wcserr_set(WCSERR_SET(WCSERR_BAD_PARAM),
+                     log_errmsg[istat]);
+          goto cleanup;
+        }
+      }
+
+      /* If constant, replicate values. */
+      if (isospec) {
+        wcsutil_setAll(ncoord, nelem, imgcrd+i);
+        wcsutil_setAli(ncoord, 1, istatp);
+      }
+
+      if (istat == 4) {
+        wcsutil_setBit(ncoord, istatp, 1 << i, stat);
+      }
+    }
+  }
+
+
+  /* Do tabular coordinates. */
+  for (itab = 0; itab < wcs->ntab; itab++) {
+    istat = tabs2x(wcs->tab + itab, ncoord, nelem, world, imgcrd, istatp);
+
+    if (istat == TABERR_BAD_WORLD) {
+      status = wcserr_set(WCS_ERRMSG(WCSERR_BAD_WORLD));
+
+      bits = 0;
+      for (m = 0; m < wcs->tab[itab].M; m++) {
+        bits |= 1 << wcs->tab[itab].map[m];
+      }
+      wcsutil_setBit(ncoord, istatp, bits, stat);
+
+    } else if (istat) {
+      if (istat == TABERR_BAD_PARAMS) istat = WCSERR_BAD_PARAM;
+      status = wcserr_set(WCS_ERRMSG(istat));
+      goto cleanup;
+    }
+  }
+
+
+  /* Zero the unused intermediate world coordinate elements. */
+  for (i = wcs->naxis; i < nelem; i++) {
+    imgcrd[i] = 0.0;
+    wcsutil_setAll(ncoord, nelem, imgcrd+i);
+  }
+
+
+  /* Apply world-to-pixel linear transformation. */
+  if ((istat = linx2p(&(wcs->lin), ncoord, nelem, imgcrd, pixcrd))) {
+    status = wcserr_set(WCS_ERRMSG(istat));
+    goto cleanup;
+  }
+
+cleanup:
+  free(istatp);
+  return status;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int wcsmix(
+  struct wcsprm *wcs,
+  int mixpix,
+  int mixcel,
+  const double vspan[2],
+  double vstep,
+  int viter,
+  double world[],
+  double phi[],
+  double theta[],
+  double imgcrd[],
+  double pixcrd[])
+
+{
+  static const char *function = "wcsmix";
+
+  const int niter = 60;
+  int    crossed, istep, iter, j, k, nstep, retry, stat[1], status;
+  const double tol  = 1.0e-10;
+  const double tol2 = 100.0*tol;
+  double *worldlat, *worldlng;
+  double lambda, span[2], step;
+  double pixmix;
+  double dlng, lng, lng0, lng0m, lng1, lng1m;
+  double dlat, lat, lat0, lat0m, lat1, lat1m;
+  double d, d0, d0m, d1, d1m, dx = 0.0;
+  double dabs, dmin, lmin;
+  double dphi, phi0, phi1;
+  struct celprm *wcscel = &(wcs->cel);
+  struct wcsprm wcs0;
+  struct wcserr **err;
+
+  /* Initialize if required. */
+  if (wcs == 0x0) return WCSERR_NULL_POINTER;
+  err = &(wcs->err);
+
+  if (wcs->flag != WCSSET) {
+    if ((status = wcsset(wcs))) return status;
+  }
+
+  worldlng = world + wcs->lng;
+  worldlat = world + wcs->lat;
+
+
+  /* Check vspan. */
+  if (vspan[0] <= vspan[1]) {
+    span[0] = vspan[0];
+    span[1] = vspan[1];
+  } else {
+    /* Swap them. */
+    span[0] = vspan[1];
+    span[1] = vspan[0];
+  }
+
+  /* Check vstep. */
+  step = fabs(vstep);
+  if (step == 0.0) {
+    step = (span[1] - span[0])/10.0;
+    if (step > 1.0 || step == 0.0) step = 1.0;
+  }
+
+  /* Check viter. */
+  nstep = viter;
+  if (nstep < 5) {
+    nstep = 5;
+  } else if (nstep > 10) {
+    nstep = 10;
+  }
+
+  /* Given pixel element. */
+  pixmix = pixcrd[mixpix];
+
+  /* Iterate on the step size. */
+  for (istep = 0; istep <= nstep; istep++) {
+    if (istep) step /= 2.0;
+
+    /* Iterate on the sky coordinate between the specified range. */
+    if (mixcel == 1) {
+      /* Celestial longitude is given. */
+
+      /* Check whether the solution interval is a crossing interval. */
+      lat0 = span[0];
+      *worldlat = lat0;
+      if ((status = wcss2p(wcs, 1, 0, world, phi, theta, imgcrd, pixcrd,
+                           stat))) {
+        if (status == WCSERR_BAD_WORLD) {
+          status = wcserr_set(WCS_ERRMSG(WCSERR_BAD_WORLD_COORD));
+        }
+        return status;
+      }
+      d0 = pixcrd[mixpix] - pixmix;
+
+      dabs = fabs(d0);
+      if (dabs < tol) return 0;
+
+      lat1 = span[1];
+      *worldlat = lat1;
+      if ((status = wcss2p(wcs, 1, 0, world, phi, theta, imgcrd, pixcrd,
+                           stat))) {
+        if (status == WCSERR_BAD_WORLD) {
+          status = wcserr_set(WCS_ERRMSG(WCSERR_BAD_WORLD_COORD));
+        }
+        return status;
+      }
+      d1 = pixcrd[mixpix] - pixmix;
+
+      dabs = fabs(d1);
+      if (dabs < tol) return 0;
+
+      lmin = lat1;
+      dmin = dabs;
+
+      /* Check for a crossing point. */
+      if (signbit(d0) != signbit(d1)) {
+        crossed = 1;
+        dx = d1;
+      } else {
+        crossed = 0;
+        lat0 = span[1];
+      }
+
+      for (retry = 0; retry < 4; retry++) {
+        /* Refine the solution interval. */
+        while (lat0 > span[0]) {
+          lat0 -= step;
+          if (lat0 < span[0]) lat0 = span[0];
+          *worldlat = lat0;
+          if ((status = wcss2p(wcs, 1, 0, world, phi, theta, imgcrd, pixcrd,
+                               stat))) {
+            if (status == WCSERR_BAD_WORLD) {
+              status = wcserr_set(WCS_ERRMSG(WCSERR_BAD_WORLD_COORD));
+            }
+            return status;
+          }
+          d0 = pixcrd[mixpix] - pixmix;
+
+          /* Check for a solution. */
+          dabs = fabs(d0);
+          if (dabs < tol) return 0;
+
+          /* Record the point of closest approach. */
+          if (dabs < dmin) {
+            lmin = lat0;
+            dmin = dabs;
+          }
+
+          /* Check for a crossing point. */
+          if (signbit(d0) != signbit(d1)) {
+            crossed = 2;
+            dx = d0;
+            break;
+          }
+
+          /* Advance to the next subinterval. */
+          lat1 = lat0;
+          d1 = d0;
+        }
+
+        if (crossed) {
+          /* A crossing point was found. */
+          for (iter = 0; iter < niter; iter++) {
+            /* Use regula falsi division of the interval. */
+            lambda = d0/(d0-d1);
+            if (lambda < 0.1) {
+              lambda = 0.1;
+            } else if (lambda > 0.9) {
+              lambda = 0.9;
+            }
+
+            dlat = lat1 - lat0;
+            lat = lat0 + lambda*dlat;
+            *worldlat = lat;
+            if ((status = wcss2p(wcs, 1, 0, world, phi, theta, imgcrd, pixcrd,
+                                 stat))) {
+              if (status == WCSERR_BAD_WORLD) {
+                status = wcserr_set(WCS_ERRMSG(WCSERR_BAD_WORLD_COORD));
+              }
+              return status;
+            }
+
+            /* Check for a solution. */
+            d = pixcrd[mixpix] - pixmix;
+            dabs = fabs(d);
+            if (dabs < tol) return 0;
+
+            if (dlat < tol) {
+              /* An artifact of numerical imprecision. */
+              if (dabs < tol2) return 0;
+
+              /* Must be a discontinuity. */
+              break;
+            }
+
+            /* Record the point of closest approach. */
+            if (dabs < dmin) {
+              lmin = lat;
+              dmin = dabs;
+            }
+
+            if (signbit(d0) == signbit(d)) {
+              lat0 = lat;
+              d0 = d;
+            } else {
+              lat1 = lat;
+              d1 = d;
+            }
+          }
+
+          /* No convergence, must have been a discontinuity. */
+          if (crossed == 1) lat0 = span[1];
+          lat1 = lat0;
+          d1 = dx;
+          crossed = 0;
+
+        } else {
+          /* No crossing point; look for a tangent point. */
+          if (lmin == span[0]) break;
+          if (lmin == span[1]) break;
+
+          lat = lmin;
+          lat0 = lat - step;
+          if (lat0 < span[0]) lat0 = span[0];
+          lat1 = lat + step;
+          if (lat1 > span[1]) lat1 = span[1];
+
+          *worldlat = lat0;
+          if ((status = wcss2p(wcs, 1, 0, world, phi, theta, imgcrd, pixcrd,
+                               stat))) {
+            if (status == WCSERR_BAD_WORLD) {
+              status = wcserr_set(WCS_ERRMSG(WCSERR_BAD_WORLD_COORD));
+            }
+            return status;
+          }
+          d0 = fabs(pixcrd[mixpix] - pixmix);
+
+          d  = dmin;
+
+          *worldlat = lat1;
+          if ((status = wcss2p(wcs, 1, 0, world, phi, theta, imgcrd, pixcrd,
+                               stat))) {
+            if (status == WCSERR_BAD_WORLD) {
+              status = wcserr_set(WCS_ERRMSG(WCSERR_BAD_WORLD_COORD));
+            }
+            return status;
+          }
+          d1 = fabs(pixcrd[mixpix] - pixmix);
+
+          for (iter = 0; iter < niter; iter++) {
+            lat0m = (lat0 + lat)/2.0;
+            *worldlat = lat0m;
+            if ((status = wcss2p(wcs, 1, 0, world, phi, theta, imgcrd, pixcrd,
+                                 stat))) {
+              if (status == WCSERR_BAD_WORLD) {
+                status = wcserr_set(WCS_ERRMSG(WCSERR_BAD_WORLD_COORD));
+              }
+              return status;
+            }
+            d0m = fabs(pixcrd[mixpix] - pixmix);
+
+            if (d0m < tol) return 0;
+
+            lat1m = (lat1 + lat)/2.0;
+            *worldlat = lat1m;
+            if ((status = wcss2p(wcs, 1, 0, world, phi, theta, imgcrd, pixcrd,
+                                 stat))) {
+              if (status == WCSERR_BAD_WORLD) {
+                status = wcserr_set(WCS_ERRMSG(WCSERR_BAD_WORLD_COORD));
+              }
+              return status;
+            }
+            d1m = fabs(pixcrd[mixpix] - pixmix);
+
+            if (d1m < tol) return 0;
+
+            if (d0m < d && d0m <= d1m) {
+              lat1 = lat;
+              d1   = d;
+              lat  = lat0m;
+              d    = d0m;
+            } else if (d1m < d) {
+              lat0 = lat;
+              d0   = d;
+              lat  = lat1m;
+              d    = d1m;
+            } else {
+              lat0 = lat0m;
+              d0   = d0m;
+              lat1 = lat1m;
+              d1   = d1m;
+            }
+          }
+        }
+      }
+
+    } else {
+      /* Celestial latitude is given. */
+
+      /* Check whether the solution interval is a crossing interval. */
+      lng0 = span[0];
+      *worldlng = lng0;
+      if ((status = wcss2p(wcs, 1, 0, world, phi, theta, imgcrd, pixcrd,
+                           stat))) {
+        if (status == WCSERR_BAD_WORLD) {
+          status = wcserr_set(WCS_ERRMSG(WCSERR_BAD_WORLD_COORD));
+        }
+        return status;
+      }
+      d0 = pixcrd[mixpix] - pixmix;
+
+      dabs = fabs(d0);
+      if (dabs < tol) return 0;
+
+      lng1 = span[1];
+      *worldlng = lng1;
+      if ((status = wcss2p(wcs, 1, 0, world, phi, theta, imgcrd, pixcrd,
+                           stat))) {
+        if (status == WCSERR_BAD_WORLD) {
+          status = wcserr_set(WCS_ERRMSG(WCSERR_BAD_WORLD_COORD));
+        }
+        return status;
+      }
+      d1 = pixcrd[mixpix] - pixmix;
+
+      dabs = fabs(d1);
+      if (dabs < tol) return 0;
+      lmin = lng1;
+      dmin = dabs;
+
+      /* Check for a crossing point. */
+      if (signbit(d0) != signbit(d1)) {
+        crossed = 1;
+        dx = d1;
+      } else {
+        crossed = 0;
+        lng0 = span[1];
+      }
+
+      for (retry = 0; retry < 4; retry++) {
+        /* Refine the solution interval. */
+        while (lng0 > span[0]) {
+          lng0 -= step;
+          if (lng0 < span[0]) lng0 = span[0];
+          *worldlng = lng0;
+          if ((status = wcss2p(wcs, 1, 0, world, phi, theta, imgcrd, pixcrd,
+                               stat))) {
+            if (status == WCSERR_BAD_WORLD) {
+              status = wcserr_set(WCS_ERRMSG(WCSERR_BAD_WORLD_COORD));
+            }
+            return status;
+          }
+          d0 = pixcrd[mixpix] - pixmix;
+
+          /* Check for a solution. */
+          dabs = fabs(d0);
+          if (dabs < tol) return 0;
+
+          /* Record the point of closest approach. */
+          if (dabs < dmin) {
+            lmin = lng0;
+            dmin = dabs;
+          }
+
+          /* Check for a crossing point. */
+          if (signbit(d0) != signbit(d1)) {
+            crossed = 2;
+            dx = d0;
+            break;
+          }
+
+          /* Advance to the next subinterval. */
+          lng1 = lng0;
+          d1 = d0;
+        }
+
+        if (crossed) {
+          /* A crossing point was found. */
+          for (iter = 0; iter < niter; iter++) {
+            /* Use regula falsi division of the interval. */
+            lambda = d0/(d0-d1);
+            if (lambda < 0.1) {
+              lambda = 0.1;
+            } else if (lambda > 0.9) {
+              lambda = 0.9;
+            }
+
+            dlng = lng1 - lng0;
+            lng = lng0 + lambda*dlng;
+            *worldlng = lng;
+            if ((status = wcss2p(wcs, 1, 0, world, phi, theta, imgcrd, pixcrd,
+                                 stat))) {
+              if (status == WCSERR_BAD_WORLD) {
+                status = wcserr_set(WCS_ERRMSG(WCSERR_BAD_WORLD_COORD));
+              }
+              return status;
+            }
+
+            /* Check for a solution. */
+            d = pixcrd[mixpix] - pixmix;
+            dabs = fabs(d);
+            if (dabs < tol) return 0;
+
+            if (dlng < tol) {
+              /* An artifact of numerical imprecision. */
+              if (dabs < tol2) return 0;
+
+              /* Must be a discontinuity. */
+              break;
+            }
+
+            /* Record the point of closest approach. */
+            if (dabs < dmin) {
+              lmin = lng;
+              dmin = dabs;
+            }
+
+            if (signbit(d0) == signbit(d)) {
+              lng0 = lng;
+              d0 = d;
+            } else {
+              lng1 = lng;
+              d1 = d;
+            }
+          }
+
+          /* No convergence, must have been a discontinuity. */
+          if (crossed == 1) lng0 = span[1];
+          lng1 = lng0;
+          d1 = dx;
+          crossed = 0;
+
+        } else {
+          /* No crossing point; look for a tangent point. */
+          if (lmin == span[0]) break;
+          if (lmin == span[1]) break;
+
+          lng = lmin;
+          lng0 = lng - step;
+          if (lng0 < span[0]) lng0 = span[0];
+          lng1 = lng + step;
+          if (lng1 > span[1]) lng1 = span[1];
+
+          *worldlng = lng0;
+          if ((status = wcss2p(wcs, 1, 0, world, phi, theta, imgcrd, pixcrd,
+                               stat))) {
+            if (status == WCSERR_BAD_WORLD) {
+              status = wcserr_set(WCS_ERRMSG(WCSERR_BAD_WORLD_COORD));
+            }
+            return status;
+          }
+          d0 = fabs(pixcrd[mixpix] - pixmix);
+
+          d  = dmin;
+
+          *worldlng = lng1;
+          if ((status = wcss2p(wcs, 1, 0, world, phi, theta, imgcrd, pixcrd,
+                               stat))) {
+            if (status == WCSERR_BAD_WORLD) {
+              status = wcserr_set(WCS_ERRMSG(WCSERR_BAD_WORLD_COORD));
+            }
+            return status;
+          }
+          d1 = fabs(pixcrd[mixpix] - pixmix);
+
+          for (iter = 0; iter < niter; iter++) {
+            lng0m = (lng0 + lng)/2.0;
+            *worldlng = lng0m;
+            if ((status = wcss2p(wcs, 1, 0, world, phi, theta, imgcrd, pixcrd,
+                                 stat))) {
+              if (status == WCSERR_BAD_WORLD) {
+                status = wcserr_set(WCS_ERRMSG(WCSERR_BAD_WORLD_COORD));
+              }
+              return status;
+            }
+            d0m = fabs(pixcrd[mixpix] - pixmix);
+
+            if (d0m < tol) return 0;
+
+            lng1m = (lng1 + lng)/2.0;
+            *worldlng = lng1m;
+            if ((status = wcss2p(wcs, 1, 0, world, phi, theta, imgcrd, pixcrd,
+                                 stat))) {
+              if (status == WCSERR_BAD_WORLD) {
+                status = wcserr_set(WCS_ERRMSG(WCSERR_BAD_WORLD_COORD));
+              }
+              return status;
+            }
+            d1m = fabs(pixcrd[mixpix] - pixmix);
+
+            if (d1m < tol) return 0;
+
+            if (d0m < d && d0m <= d1m) {
+              lng1 = lng;
+              d1   = d;
+              lng  = lng0m;
+              d    = d0m;
+            } else if (d1m < d) {
+              lng0 = lng;
+              d0   = d;
+              lng  = lng1m;
+              d    = d1m;
+            } else {
+              lng0 = lng0m;
+              d0   = d0m;
+              lng1 = lng1m;
+              d1   = d1m;
+            }
+          }
+        }
+      }
+    }
+  }
+
+
+  /* Set cel0 to the unity transformation. */
+  wcs0 = *wcs;
+  wcs0.cel.euler[0] = -90.0;
+  wcs0.cel.euler[1] =   0.0;
+  wcs0.cel.euler[2] =  90.0;
+  wcs0.cel.euler[3] =   1.0;
+  wcs0.cel.euler[4] =   0.0;
+
+  /* No convergence, check for aberrant behaviour at a native pole. */
+  *theta = -90.0;
+  for (j = 1; j <= 2; j++) {
+    /* Could the celestial coordinate element map to a native pole? */
+    *phi = 0.0;
+    *theta = -*theta;
+    sphx2s(wcscel->euler, 1, 1, 1, 1, phi, theta, &lng, &lat);
+
+    if (mixcel == 1) {
+      if (fabs(fmod(*worldlng-lng, 360.0)) > tol) continue;
+      if (lat < span[0]) continue;
+      if (lat > span[1]) continue;
+      *worldlat = lat;
+    } else {
+      if (fabs(*worldlat-lat) > tol) continue;
+      if (lng < span[0]) lng += 360.0;
+      if (lng > span[1]) lng -= 360.0;
+      if (lng < span[0]) continue;
+      if (lng > span[1]) continue;
+      *worldlng = lng;
+    }
+
+    /* Is there a solution for the given pixel coordinate element? */
+    lng = *worldlng;
+    lat = *worldlat;
+
+    /* Feed native coordinates to wcss2p() with cel0 set to unity. */
+    *worldlng = -180.0;
+    *worldlat = *theta;
+    if ((status = wcss2p(&wcs0, 1, 0, world, phi, theta, imgcrd, pixcrd,
+                         stat))) {
+      if (wcs->err) free(wcs->err);
+      wcs->err = wcs0.err;
+      if (status == WCSERR_BAD_WORLD) {
+        status = wcserr_set(WCS_ERRMSG(WCSERR_BAD_WORLD_COORD));
+      }
+      return status;
+    }
+    d0 = pixcrd[mixpix] - pixmix;
+
+    /* Check for a solution. */
+    if (fabs(d0) < tol) {
+      /* Recall saved world coordinates. */
+      *worldlng = lng;
+      *worldlat = lat;
+      return 0;
+    }
+
+    /* Search for a crossing interval. */
+    phi0 = -180.0;
+    for (k = -179; k <= 180; k++) {
+      phi1 = (double) k;
+      *worldlng = phi1;
+      if ((status = wcss2p(&wcs0, 1, 0, world, phi, theta, imgcrd, pixcrd,
+                           stat))) {
+        if (wcs->err) free(wcs->err);
+        wcs->err = wcs0.err;
+        if (status == WCSERR_BAD_WORLD) {
+          status = wcserr_set(WCS_ERRMSG(WCSERR_BAD_WORLD_COORD));
+        }
+        return status;
+      }
+      d1 = pixcrd[mixpix] - pixmix;
+
+      /* Check for a solution. */
+      dabs = fabs(d1);
+      if (dabs < tol) {
+        /* Recall saved world coordinates. */
+        *worldlng = lng;
+        *worldlat = lat;
+        return 0;
+      }
+
+      /* Is it a crossing interval? */
+      if (signbit(d0) != signbit(d1)) break;
+
+      phi0 = phi1;
+      d0 = d1;
+    }
+
+    for (iter = 1; iter <= niter; iter++) {
+      /* Use regula falsi division of the interval. */
+      lambda = d0/(d0-d1);
+      if (lambda < 0.1) {
+        lambda = 0.1;
+      } else if (lambda > 0.9) {
+        lambda = 0.9;
+      }
+
+      dphi = phi1 - phi0;
+      *worldlng = phi0 + lambda*dphi;
+      if ((status = wcss2p(&wcs0, 1, 0, world, phi, theta, imgcrd, pixcrd,
+                           stat))) {
+        if (wcs->err) free(wcs->err);
+        wcs->err = wcs0.err;
+        if (status == WCSERR_BAD_WORLD) {
+          status = wcserr_set(WCS_ERRMSG(WCSERR_BAD_WORLD_COORD));
+        }
+        return status;
+      }
+
+      /* Check for a solution. */
+      d = pixcrd[mixpix] - pixmix;
+      dabs = fabs(d);
+      if (dabs < tol || (dphi < tol && dabs < tol2)) {
+        /* Recall saved world coordinates. */
+        *worldlng = lng;
+        *worldlat = lat;
+        return 0;
+      }
+
+      if (signbit(d0) == signbit(d)) {
+        phi0 = *worldlng;
+        d0 = d;
+      } else {
+        phi1 = *worldlng;
+        d1 = d;
+      }
+    }
+  }
+
+
+  /* No solution. */
+  return wcserr_set(WCS_ERRMSG(WCSERR_NO_SOLUTION));
+}
+
+/*--------------------------------------------------------------------------*/
+
+int wcssptr(
+  struct wcsprm *wcs,
+  int  *i,
+  char ctype[9])
+
+{
+  static const char *function = "wcssptr";
+
+  int    j, status;
+  double cdelt, crval;
+  struct wcserr **err;
+
+  /* Initialize if required. */
+  if (wcs == 0x0) return WCSERR_NULL_POINTER;
+  err = &(wcs->err);
+
+  if (wcs->flag != WCSSET) {
+    if ((status = wcsset(wcs))) return status;
+  }
+
+  if ((j = *i) < 0) {
+    if ((j = wcs->spec) < 0) {
+      /* Look for a linear spectral axis. */
+      for (j = 0; j < wcs->naxis; j++) {
+        if (wcs->types[j]/100 == 30) {
+          break;
+        }
+      }
+
+      if (j >= wcs->naxis) {
+        /* No spectral axis. */
+        return wcserr_set(WCSERR_SET(WCSERR_BAD_SUBIMAGE),
+          "No spectral axis found.");
+      }
+    }
+
+    *i = j;
+  }
+
+  /* Translate the spectral axis. */
+  if (spctrne(wcs->ctype[j], wcs->crval[j], wcs->cdelt[j], wcs->restfrq,
+              wcs->restwav, ctype, &crval, &cdelt, &(wcs->spc.err))) {
+    return wcserr_set(WCS_ERRMSG(WCSERR_BAD_COORD_TRANS));
+  }
+
+
+  /* Translate keyvalues. */
+  wcs->flag = 0;
+  wcs->cdelt[j] = cdelt;
+  wcs->crval[j] = crval;
+  spctyp(ctype, 0x0, 0x0, 0x0, wcs->cunit[j], 0x0, 0x0, 0x0);
+  strcpy(wcs->ctype[j], ctype);
+
+  /* This keeps things tidy if the spectral axis is linear. */
+  spcfree(&(wcs->spc));
+  spcini(&(wcs->spc));
+
+  return 0;
+}
diff --git a/cextern/wcslib/C/wcs.h b/cextern/wcslib/C/wcs.h
new file mode 100644
index 0000000..67b8838
--- /dev/null
+++ b/cextern/wcslib/C/wcs.h
@@ -0,0 +1,1534 @@
+/*============================================================================
+
+  WCSLIB 4.16 - an implementation of the FITS WCS standard.
+  Copyright (C) 1995-2012, Mark Calabretta
+
+  This file is part of WCSLIB.
+
+  WCSLIB is free software: you can redistribute it and/or modify it under the
+  terms of the GNU Lesser General Public License as published by the Free
+  Software Foundation, either version 3 of the License, or (at your option)
+  any later version.
+
+  WCSLIB 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 Lesser General Public License for
+  more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with WCSLIB.  If not, see http://www.gnu.org/licenses.
+
+  Direct correspondence concerning WCSLIB to mark at calabretta.id.au
+
+  Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
+  http://www.atnf.csiro.au/people/Mark.Calabretta
+  $Id: wcs.h,v 4.16 2012/11/07 04:42:44 cal103 Exp $
+*=============================================================================
+*
+* WCSLIB 4.16 - C routines that implement the FITS World Coordinate System
+* (WCS) standard.  Refer to
+*
+*   "Representations of world coordinates in FITS",
+*   Greisen, E.W., & Calabretta, M.R. 2002, A&A, 395, 1061 (Paper I)
+*
+*   "Representations of celestial coordinates in FITS",
+*   Calabretta, M.R., & Greisen, E.W. 2002, A&A, 395, 1077 (Paper II)
+*
+*   "Representations of spectral coordinates in FITS",
+*   Greisen, E.W., Calabretta, M.R., Valdes, F.G., & Allen, S.L.
+*   2006, A&A, 446, 747 (Paper III)
+*
+* Refer to the README file provided with WCSLIB for an overview of the
+* library.
+*
+*
+* Summary of the wcs routines
+* ---------------------------
+* These routines implement the FITS World Coordinate System (WCS) standard
+* which defines methods to be used for computing world coordinates from image
+* pixel coordinates, and vice versa.  They are based on the wcsprm struct
+* which contains all information needed for the computations.  The struct
+* contains some members that must be set by the user, and others that are
+* maintained by these routines, somewhat like a C++ class but with no
+* encapsulation.
+*
+* Three routines, wcsini(), wcssub(), and wcsfree() are provided to manage the
+* wcsprm struct and another, wcsprt(), to prints its contents.  Refer to the
+* description of the wcsprm struct for an explanation of the anticipated usage
+* of these routines.  wcscopy(), which does a deep copy of one wcsprm struct
+* to another, is defined as a preprocessor macro function that invokes
+* wcssub().
+*
+* wcsperr() prints the error message(s) (if any) stored in a wcsprm struct,
+* and the linprm, celprm, prjprm, spcprm, and tabprm structs that it contains.
+*
+* A setup routine, wcsset(), computes intermediate values in the wcsprm struct
+* from parameters in it that were supplied by the user.  The struct always
+* needs to be set up by wcsset() but this need not be called explicitly -
+* refer to the explanation of wcsprm::flag.
+*
+* wcsp2s() and wcss2p() implement the WCS world coordinate transformations.
+* In fact, they are high level driver routines for the WCS linear,
+* logarithmic, celestial, spectral and tabular transformation routines
+* described in lin.h, log.h, cel.h, spc.h and tab.h.
+*
+* Given either the celestial longitude or latitude plus an element of the
+* pixel coordinate a hybrid routine, wcsmix(), iteratively solves for the
+* unknown elements.
+*
+* wcssptr() translates the spectral axis in a wcsprm struct.  For example, a
+* 'FREQ' axis may be translated into 'ZOPT-F2W' and vice versa.
+*
+* Quadcube projections:
+* ---------------------
+*   The quadcube projections (TSC, CSC, QSC) may be represented in FITS in
+*   either of two ways:
+*
+*     a: The six faces may be laid out in one plane and numbered as follows:
+*
+=                                 0
+=
+=                        4  3  2  1  4  3  2
+=
+=                                 5
+*
+*        Faces 2, 3 and 4 may appear on one side or the other (or both).  The
+*        world-to-pixel routines map faces 2, 3 and 4 to the left but the
+*        pixel-to-world routines accept them on either side.
+*
+*     b: The "COBE" convention in which the six faces are stored in a
+*        three-dimensional structure using a CUBEFACE axis indexed from
+*        0 to 5 as above.
+*
+*   These routines support both methods; wcsset() determines which is being
+*   used by the presence or absence of a CUBEFACE axis in ctype[].  wcsp2s()
+*   and wcss2p() translate the CUBEFACE axis representation to the single
+*   plane representation understood by the lower-level WCSLIB projection
+*   routines.
+*
+*
+* wcsini() - Default constructor for the wcsprm struct
+* ----------------------------------------------------
+* wcsini() optionally allocates memory for arrays in a wcsprm struct and sets
+* all members of the struct to default values.  Memory is allocated for up to
+* NPVMAX PVi_ma keywords or NPSMAX PSi_ma keywords per WCS representation.
+* These may be changed via wcsnpv() and wcsnps() before wcsini() is called.
+*
+* PLEASE NOTE: every wcsprm struct should be initialized by wcsini(), possibly
+* repeatedly.  On the first invokation, and only the first invokation,
+* wcsprm::flag must be set to -1 to initialize memory management, regardless
+* of whether wcsini() will actually be used to allocate memory.
+*
+* Given:
+*   alloc     int       If true, allocate memory unconditionally for the
+*                       crpix, etc. arrays.
+*
+*                       If false, it is assumed that pointers to these arrays
+*                       have been set by the user except if they are null
+*                       pointers in which case memory will be allocated for
+*                       them regardless.  (In other words, setting alloc true
+*                       saves having to initalize these pointers to zero.)
+*
+*   naxis     int       The number of world coordinate axes.  This is used to
+*                       determine the length of the various wcsprm vectors and
+*                       matrices and therefore the amount of memory to
+*                       allocate for them.
+*
+* Given and returned:
+*   wcs       struct wcsprm*
+*                       Coordinate transformation parameters.
+*
+*                       Note that, in order to initialize memory management,
+*                       wcsprm::flag should be set to -1 when wcs is
+*                       initialized for the first time (memory leaks may
+*                       result if it had already been initialized).
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         1: Null wcsprm pointer passed.
+*                         2: Memory allocation failed.
+*
+*                       For returns > 1, a detailed error message is set in
+*                       wcsprm::err if enabled, see wcserr_enable().
+*
+*
+* wcsnpv() - Memory allocation for PVi_ma
+* ---------------------------------------
+* wcsnpv() changes the value of NPVMAX (default 64).  This global variable
+* controls the number of PVi_ma keywords that wcsini() should allocate space
+* for.
+*
+* PLEASE NOTE: This function is not thread-safe.
+*
+* Given:
+*   n         int       Value of NPVMAX; ignored if < 0.
+*
+* Function return value:
+*             int       Current value of NPVMAX.
+*
+*
+* wcsnps() - Memory allocation for PSi_ma
+* ---------------------------------------
+* wcsnps() changes the values of NPSMAX (default 8).  This global variable
+* controls the number of PSi_ma keywords that wcsini() should allocate space
+* for.
+*
+* PLEASE NOTE: This function is not thread-safe.
+*
+* Given:
+*   n         int       Value of NPSMAX; ignored if < 0.
+*
+* Function return value:
+*             int       Current value of NPSMAX.
+*
+*
+* wcssub() - Subimage extraction routine for the wcsprm struct
+* ------------------------------------------------------------
+* wcssub() extracts the coordinate description for a subimage from a wcsprm
+* struct.  It does a deep copy, using wcsini() to allocate memory for its
+* arrays if required.  Only the "information to be provided" part of the
+* struct is extracted; a call to wcsset() is required to set up the remainder.
+*
+* The world coordinate system of the subimage must be separable in the sense
+* that the world coordinates at any point in the subimage must depend only on
+* the pixel coordinates of the axes extracted.  In practice, this means that
+* the PCi_ja matrix of the original image must not contain non-zero
+* off-diagonal terms that associate any of the subimage axes with any of the
+* non-subimage axes.
+*
+* Note that while the required elements of the tabprm array are extracted, the
+* wtbarr array is not.  (Thus it is not appropriate to call wcssub() after
+* wcstab() but before filling the tabprm structs - refer to wcshdr.h.)
+*
+* wcssub() can also add axes to a wcsprm struct.  The new axes will be created
+* using the defaults set by wcsini() which produce a simple, unnamed, linear
+* axis with world coordinate equal to the pixel coordinate.  These default
+* values can be changed in before invoking wcsset().
+*
+* Given:
+*   alloc     int       If true, allocate memory for the crpix, etc. arrays in
+*                       the destination.  Otherwise, it is assumed that
+*                       pointers to these arrays have been set by the user
+*                       except if they are null pointers in which case memory
+*                       will be allocated for them regardless.
+*
+*   wcssrc    const struct wcsprm*
+*                       Struct to extract from.
+*
+* Given and returned:
+*   nsub      int*
+*   axes      int[]     Vector of length *nsub containing the image axis
+*                       numbers (1-relative) to extract.  Order is
+*                       significant; axes[0] is the axis number of the input
+*                       image that corresponds to the first axis in the
+*                       subimage, etc.
+*
+*                       Use an axis number of 0 to create a new axis using
+*                       the defaults set by wcsini().
+*
+*                       nsub (the pointer) may be set to zero, and so also may
+*                       nsub, to indicate the number of axes in the input
+*                       image; the number of axes will be returned if
+*                       nsub != 0x0.  axes itself (the pointer) may be set to
+*                       zero to indicate the first *nsub axes in their
+*                       original order.
+*
+*                       Set both nsub and axes to zero to do a deep copy of
+*                       one wcsprm struct to another.
+*
+*                       Subimage extraction by coordinate axis type may be
+*                       done by setting the elements of axes[] to the
+*                       following special preprocessor macro values:
+*
+*                         WCSSUB_LONGITUDE: Celestial longitude.
+*                         WCSSUB_LATITUDE:  Celestial latitude.
+*                         WCSSUB_CUBEFACE:  Quadcube CUBEFACE axis.
+*                         WCSSUB_SPECTRAL:  Spectral axis.
+*                         WCSSUB_STOKES:    Stokes axis.
+*
+*                       Refer to the notes (below) for further usage examples.
+*
+*                       On return, *nsub will contain the number of axes in
+*                       the subimage; this may be zero if there were no axes
+*                       of the required type(s) (in which case no memory will
+*                       be allocated).  axes[] will contain the axis numbers
+*                       that were extracted, or 0 for newly created axes.  The
+*                       vector length must be sufficient to contain all axis
+*                       numbers.  No checks are performed to verify that the
+*                       coordinate axes are consistent, this is done by
+*                       wcsset().
+*
+*   wcsdst    struct wcsprm*
+*                       Struct describing the subimage.  wcsprm::flag should
+*                       be set to -1 if wcsdst was not previously initialized
+*                       (memory leaks may result if it was previously
+*                       initialized).
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         1: Null wcsprm pointer passed.
+*                         2: Memory allocation failed.
+*                        12: Invalid subimage specification.
+*                        13: Non-separable subimage coordinate system.
+*
+*                       For returns > 1, a detailed error message is set in
+*                       wcsprm::err if enabled, see wcserr_enable().
+*
+* Notes:
+*   Combinations of subimage axes of particular types may be extracted in the
+*   same order as they occur in the input image by combining preprocessor
+*   codes, for example
+*
+=     *nsub = 1;
+=     axes[0] = WCSSUB_LONGITUDE | WCSSUB_LATITUDE | WCSSUB_SPECTRAL;
+*
+*   would extract the longitude, latitude, and spectral axes in the same order
+*   as the input image.  If one of each were present, *nsub = 3 would be
+*   returned.
+*
+*   For convenience, WCSSUB_CELESTIAL is defined as the combination
+*   WCSSUB_LONGITUDE | WCSSUB_LATITUDE | WCSSUB_CUBEFACE.
+*
+*   The codes may also be negated to extract all but the types specified, for
+*   example
+*
+=     *nsub = 4;
+=     axes[0] = WCSSUB_LONGITUDE;
+=     axes[1] = WCSSUB_LATITUDE;
+=     axes[2] = WCSSUB_CUBEFACE;
+=     axes[3] = -(WCSSUB_SPECTRAL | WCSSUB_STOKES);
+*
+*   The last of these specifies all axis types other than spectral or Stokes.
+*   Extraction is done in the order specified by axes[] a longitude axis (if
+*   present) would be extracted first (via axes[0]) and not subsequently (via
+*   axes[3]).  Likewise for the latitude and cubeface axes in this example.
+*
+*   From the foregoing, it is apparent that the value of *nsub returned may be
+*   less than or greater than that given.  However, it will never exceed the
+*   number of axes in the input image (plus the number of newly-created axes
+*   if any were specified on input).
+*
+*
+* wcscopy() macro - Copy routine for the wcsprm struct
+* ----------------------------------------------------
+* wcscopy() does a deep copy of one wcsprm struct to another.  As of
+* WCSLIB 3.6, it is implemented as a preprocessor macro that invokes
+* wcssub() with the nsub and axes pointers both set to zero.
+*
+*
+* wcsfree() - Destructor for the wcsprm struct
+* --------------------------------------------
+* wcsfree() frees memory allocated for the wcsprm arrays by wcsini() and/or
+* wcsset().  wcsini() records the memory it allocates and wcsfree() will only
+* attempt to free this.
+*
+* PLEASE NOTE: wcsfree() must not be invoked on a wcsprm struct that was not
+* initialized by wcsini().
+*
+* Returned:
+*   wcs       struct wcsprm*
+*                       Coordinate transformation parameters.
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         1: Null wcsprm pointer passed.
+*
+*
+* wcsprt() - Print routine for the wcsprm struct
+* ----------------------------------------------
+* wcsprt() prints the contents of a wcsprm struct using wcsprintf().  Mainly
+* intended for diagnostic purposes.
+*
+* Given:
+*   wcs       const struct wcsprm*
+*                       Coordinate transformation parameters.
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         1: Null wcsprm pointer passed.
+*
+*
+* wcsperr() - Print error messages from a wcsprm struct
+* -----------------------------------------------------
+* wcsperr() prints the error message(s), if any, stored in a wcsprm struct,
+* and the linprm, celprm, prjprm, spcprm, and tabprm structs that it contains.
+* If there are no errors then nothing is printed.  It uses wcserr_prt(), q.v.
+*
+* Given:
+*   wcs       const struct wcsprm*
+*                       Coordinate transformation parameters.
+*
+*   prefix    const char *
+*                       If non-NULL, each output line will be prefixed with
+*                       this string.
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         1: Null wcsprm pointer passed.
+*
+*
+* wcsset() - Setup routine for the wcsprm struct
+* ----------------------------------------------
+* wcsset() sets up a wcsprm struct according to information supplied within
+* it (refer to the description of the wcsprm struct).
+*
+* wcsset() recognizes the NCP projection and converts it to the equivalent SIN
+* projection and likewise translates GLS into SFL.  It also translates the
+* AIPS spectral types ('FREQ-LSR', 'FELO-HEL', etc.), possibly changing the
+* input header keywords wcsprm::ctype and/or wcsprm::specsys if necessary.
+*
+* Note that this routine need not be called directly; it will be invoked by
+* wcsp2s() and wcss2p() if the wcsprm::flag is anything other than a
+* predefined magic value.
+*
+* Given and returned:
+*   wcs       struct wcsprm*
+*                       Coordinate transformation parameters.
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         1: Null wcsprm pointer passed.
+*                         2: Memory allocation failed.
+*                         3: Linear transformation matrix is singular.
+*                         4: Inconsistent or unrecognized coordinate axis
+*                            types.
+*                         5: Invalid parameter value.
+*                         6: Invalid coordinate transformation parameters.
+*                         7: Ill-conditioned coordinate transformation
+*                            parameters.
+*
+*                       For returns > 1, a detailed error message is set in
+*                       wcsprm::err if enabled, see wcserr_enable().
+*
+*
+* wcsp2s() - Pixel-to-world transformation
+* ----------------------------------------
+* wcsp2s() transforms pixel coordinates to world coordinates.
+*
+* Given and returned:
+*   wcs       struct wcsprm*
+*                       Coordinate transformation parameters.
+*
+* Given:
+*   ncoord,
+*   nelem     int       The number of coordinates, each of vector length
+*                       nelem but containing wcs.naxis coordinate elements.
+*                       Thus nelem must equal or exceed the value of the
+*                       NAXIS keyword unless ncoord == 1, in which case nelem
+*                       is not used.
+*
+*   pixcrd    const double[ncoord][nelem]
+*                       Array of pixel coordinates.
+*
+* Returned:
+*   imgcrd    double[ncoord][nelem]
+*                       Array of intermediate world coordinates.  For
+*                       celestial axes, imgcrd[][wcs.lng] and
+*                       imgcrd[][wcs.lat] are the projected x-, and
+*                       y-coordinates in pseudo "degrees".  For spectral
+*                       axes, imgcrd[][wcs.spec] is the intermediate spectral
+*                       coordinate, in SI units.
+*
+*   phi,theta double[ncoord]
+*                       Longitude and latitude in the native coordinate system
+*                       of the projection [deg].
+*
+*   world     double[ncoord][nelem]
+*                       Array of world coordinates.  For celestial axes,
+*                       world[][wcs.lng] and world[][wcs.lat] are the
+*                       celestial longitude and latitude [deg].  For
+*                       spectral axes, imgcrd[][wcs.spec] is the intermediate
+*                       spectral coordinate, in SI units.
+*
+*   stat      int[ncoord]
+*                       Status return value for each coordinate:
+*                         0: Success.
+*                         1+: A bit mask indicating invalid pixel coordinate
+*                            element(s).
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         1: Null wcsprm pointer passed.
+*                         2: Memory allocation failed.
+*                         3: Linear transformation matrix is singular.
+*                         4: Inconsistent or unrecognized coordinate axis
+*                            types.
+*                         5: Invalid parameter value.
+*                         6: Invalid coordinate transformation parameters.
+*                         7: Ill-conditioned coordinate transformation
+*                            parameters.
+*                         8: One or more of the pixel coordinates were
+*                            invalid, as indicated by the stat vector.
+*
+*                       For returns > 1, a detailed error message is set in
+*                       wcsprm::err if enabled, see wcserr_enable().
+*
+*
+* wcss2p() - World-to-pixel transformation
+* ----------------------------------------
+* wcss2p() transforms world coordinates to pixel coordinates.
+*
+* Given and returned:
+*   wcs       struct wcsprm*
+*                       Coordinate transformation parameters.
+*
+* Given:
+*   ncoord,
+*   nelem     int       The number of coordinates, each of vector length nelem
+*                       but containing wcs.naxis coordinate elements.  Thus
+*                       nelem must equal or exceed the value of the NAXIS
+*                       keyword unless ncoord == 1, in which case nelem is not
+*                       used.
+*
+*   world     const double[ncoord][nelem]
+*                       Array of world coordinates.  For celestial axes,
+*                       world[][wcs.lng] and world[][wcs.lat] are the
+*                       celestial longitude and latitude [deg]. For spectral
+*                       axes, world[][wcs.spec] is the spectral coordinate, in
+*                       SI units.
+*
+* Returned:
+*   phi,theta double[ncoord]
+*                       Longitude and latitude in the native coordinate
+*                       system of the projection [deg].
+*
+*   imgcrd    double[ncoord][nelem]
+*                       Array of intermediate world coordinates.  For
+*                       celestial axes, imgcrd[][wcs.lng] and
+*                       imgcrd[][wcs.lat] are the projected x-, and
+*                       y-coordinates in pseudo "degrees".  For quadcube
+*                       projections with a CUBEFACE axis the face number is
+*                       also returned in imgcrd[][wcs.cubeface].  For
+*                       spectral axes, imgcrd[][wcs.spec] is the intermediate
+*                       spectral coordinate, in SI units.
+*
+*   pixcrd    double[ncoord][nelem]
+*                       Array of pixel coordinates.
+*
+*   stat      int[ncoord]
+*                       Status return value for each coordinate:
+*                         0: Success.
+*                         1+: A bit mask indicating invalid world coordinate
+*                            element(s).
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         1: Null wcsprm pointer passed.
+*                         2: Memory allocation failed.
+*                         3: Linear transformation matrix is singular.
+*                         4: Inconsistent or unrecognized coordinate axis
+*                            types.
+*                         5: Invalid parameter value.
+*                         6: Invalid coordinate transformation parameters.
+*                         7: Ill-conditioned coordinate transformation
+*                            parameters.
+*                         9: One or more of the world coordinates were
+*                            invalid, as indicated by the stat vector.
+*
+*                       For returns > 1, a detailed error message is set in
+*                       wcsprm::err if enabled, see wcserr_enable().
+*
+*
+* wcsmix() - Hybrid coordinate transformation
+* -------------------------------------------
+* wcsmix(), given either the celestial longitude or latitude plus an element
+* of the pixel coordinate, solves for the remaining elements by iterating on
+* the unknown celestial coordinate element using wcss2p().  Refer also to the
+* notes below.
+*
+* Given and returned:
+*   wcs       struct wcsprm*
+*                       Indices for the celestial coordinates obtained
+*                       by parsing the wcsprm::ctype[].
+*
+* Given:
+*   mixpix    int       Which element of the pixel coordinate is given.
+*
+*   mixcel    int       Which element of the celestial coordinate is given:
+*                         1: Celestial longitude is given in
+*                            world[wcs.lng], latitude returned in
+*                            world[wcs.lat].
+*                         2: Celestial latitude is given in
+*                            world[wcs.lat], longitude returned in
+*                            world[wcs.lng].
+*
+*   vspan     const double[2]
+*                       Solution interval for the celestial coordinate [deg].
+*                       The ordering of the two limits is irrelevant.
+*                       Longitude ranges may be specified with any convenient
+*                       normalization, for example [-120,+120] is the same as
+*                       [240,480], except that the solution will be returned
+*                       with the same normalization, i.e. lie within the
+*                       interval specified.
+*
+*   vstep     const double
+*                       Step size for solution search [deg].  If zero, a
+*                       sensible, although perhaps non-optimal default will be
+*                       used.
+*
+*   viter     int       If a solution is not found then the step size will be
+*                       halved and the search recommenced.  viter controls how
+*                       many times the step size is halved.  The allowed range
+*                       is 5 - 10.
+*
+* Given and returned:
+*   world     double[naxis]
+*                       World coordinate elements.  world[wcs.lng] and
+*                       world[wcs.lat] are the celestial longitude and
+*                       latitude [deg].  Which is given and which returned
+*                       depends on the value of mixcel.  All other elements
+*                       are given.
+*
+* Returned:
+*   phi,theta double[naxis]
+*                       Longitude and latitude in the native coordinate
+*                       system of the projection [deg].
+*
+*   imgcrd    double[naxis]
+*                       Image coordinate elements.  imgcrd[wcs.lng] and
+*                       imgcrd[wcs.lat] are the projected x-, and
+*                       y-coordinates in pseudo "degrees".
+*
+* Given and returned:
+*   pixcrd    double[naxis]
+*                       Pixel coordinate.  The element indicated by mixpix is
+*                       given and the remaining elements are returned.
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         1: Null wcsprm pointer passed.
+*                         2: Memory allocation failed.
+*                         3: Linear transformation matrix is singular.
+*                         4: Inconsistent or unrecognized coordinate axis
+*                            types.
+*                         5: Invalid parameter value.
+*                         6: Invalid coordinate transformation parameters.
+*                         7: Ill-conditioned coordinate transformation
+*                            parameters.
+*                        10: Invalid world coordinate.
+*                        11: No solution found in the specified interval.
+*
+*                       For returns > 1, a detailed error message is set in
+*                       wcsprm::err if enabled, see wcserr_enable().
+*
+* Notes:
+*   Initially the specified solution interval is checked to see if it's a
+*   "crossing" interval.  If it isn't, a search is made for a crossing
+*   solution by iterating on the unknown celestial coordinate starting at the
+*   upper limit of the solution interval and decrementing by the specified
+*   step size.  A crossing is indicated if the trial value of the pixel
+*   coordinate steps through the value specified.  If a crossing interval is
+*   found then the solution is determined by a modified form of "regula falsi"
+*   division of the crossing interval.  If no crossing interval was found
+*   within the specified solution interval then a search is made for a
+*   "non-crossing" solution as may arise from a point of tangency.  The
+*   process is complicated by having to make allowance for the discontinuities
+*   that occur in all map projections.
+*
+*   Once one solution has been determined others may be found by subsequent
+*   invokations of wcsmix() with suitably restricted solution intervals.
+*
+*   Note the circumstance that arises when the solution point lies at a native
+*   pole of a projection in which the pole is represented as a finite curve,
+*   for example the zenithals and conics.  In such cases two or more valid
+*   solutions may exist but wcsmix() only ever returns one.
+*
+*   Because of its generality wcsmix() is very compute-intensive.  For
+*   compute-limited applications more efficient special-case solvers could be
+*   written for simple projections, for example non-oblique cylindrical
+*   projections.
+*
+*
+* wcssptr() - Spectral axis translation
+* -------------------------------------
+* wcssptr() translates the spectral axis in a wcsprm struct.  For example, a
+* 'FREQ' axis may be translated into 'ZOPT-F2W' and vice versa.
+*
+* Given and returned:
+*   wcs       struct wcsprm*
+*                       Coordinate transformation parameters.
+*
+*   i         int*      Index of the spectral axis (0-relative).  If given < 0
+*                       it will be set to the first spectral axis identified
+*                       from the ctype[] keyvalues in the wcsprm struct.
+*
+*   ctype     char[9]   Desired spectral CTYPEia.  Wildcarding may be used as
+*                       for the ctypeS2 argument to spctrn() as described in
+*                       the prologue of spc.h, i.e. if the final three
+*                       characters are specified as "???", or if just the
+*                       eighth character is specified as '?', the correct
+*                       algorithm code will be substituted and returned.
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         1: Null wcsprm pointer passed.
+*                         2: Memory allocation failed.
+*                         3: Linear transformation matrix is singular.
+*                         4: Inconsistent or unrecognized coordinate axis
+*                            types.
+*                         5: Invalid parameter value.
+*                         6: Invalid coordinate transformation parameters.
+*                         7: Ill-conditioned coordinate transformation
+*                            parameters.
+*                        12: Invalid subimage specification (no spectral
+*                            axis).
+*
+*                       For returns > 1, a detailed error message is set in
+*                       wcsprm::err if enabled, see wcserr_enable().
+*
+*
+* wcsprm struct - Coordinate transformation parameters
+* ----------------------------------------------------
+* The wcsprm struct contains information required to transform world
+* coordinates.  It consists of certain members that must be set by the user
+* ("given") and others that are set by the WCSLIB routines ("returned").
+* Some of the former are not actually required for transforming coordinates.
+* These are described as "auxiliary"; the struct simply provides a place to
+* store them, though they may be used by wcshdo() in constructing a FITS
+* header from a wcsprm struct.  Some of the returned values are supplied for
+* informational purposes and others are for internal use only as indicated.
+*
+* In practice, it is expected that a WCS parser would scan the FITS header to
+* determine the number of coordinate axes.  It would then use wcsini() to
+* allocate memory for arrays in the wcsprm struct and set default values.
+* Then as it reread the header and identified each WCS keyrecord it would load
+* the value into the relevant wcsprm array element.  This is essentially what
+* wcspih() does - refer to the prologue of wcshdr.h.  As the final step,
+* wcsset() is invoked, either directly or indirectly, to set the derived
+* members of the wcsprm struct.  wcsset() strips off trailing blanks in all
+* string members and null-fills the character array.
+*
+*   int flag
+*     (Given and returned) This flag must be set to zero whenever any of the
+*     following wcsprm struct members are set or changed:
+*
+*       - wcsprm::naxis (q.v., not normally set by the user),
+*       - wcsprm::crpix,
+*       - wcsprm::pc,
+*       - wcsprm::cdelt,
+*       - wcsprm::crval,
+*       - wcsprm::cunit,
+*       - wcsprm::ctype,
+*       - wcsprm::lonpole,
+*       - wcsprm::latpole,
+*       - wcsprm::restfrq,
+*       - wcsprm::restwav,
+*       - wcsprm::npv,
+*       - wcsprm::pv,
+*       - wcsprm::nps,
+*       - wcsprm::ps,
+*       - wcsprm::cd,
+*       - wcsprm::crota,
+*       - wcsprm::altlin.
+*
+*     This signals the initialization routine, wcsset(), to recompute the
+*     returned members of the celprm struct.  celset() will reset flag to
+*     indicate that this has been done.
+*
+*     PLEASE NOTE: flag should be set to -1 when wcsini() is called for the
+*     first time for a particular wcsprm struct in order to initialize memory
+*     management.  It must ONLY be used on the first initialization otherwise
+*     memory leaks may result.
+*
+*   int naxis
+*     (Given or returned) Number of pixel and world coordinate elements.
+*
+*     If wcsini() is used to initialize the linprm struct (as would normally
+*     be the case) then it will set naxis from the value passed to it as a
+*     function argument.  The user should not subsequently modify it.
+*
+*   double *crpix
+*     (Given) Address of the first element of an array of double containing
+*     the coordinate reference pixel, CRPIXja.
+*
+*   double *pc
+*     (Given) Address of the first element of the PCi_ja (pixel coordinate)
+*     transformation matrix.  The expected order is
+*
+=       struct wcsprm wcs;
+=       wcs.pc = {PC1_1, PC1_2, PC2_1, PC2_2};
+*
+*     This may be constructed conveniently from a 2-D array via
+*
+=       double m[2][2] = {{PC1_1, PC1_2},
+=                         {PC2_1, PC2_2}};
+*
+*     which is equivalent to
+*
+=       double m[2][2];
+=       m[0][0] = PC1_1;
+=       m[0][1] = PC1_2;
+=       m[1][0] = PC2_1;
+=       m[1][1] = PC2_2;
+*
+*     The storage order for this 2-D array is the same as for the 1-D array,
+*     whence
+*
+=       wcs.pc = *m;
+*
+*     would be legitimate.
+*
+*   double *cdelt
+*     (Given) Address of the first element of an array of double containing
+*     the coordinate increments, CDELTia.
+*
+*   double *crval
+*     (Given) Address of the first element of an array of double containing
+*     the coordinate reference values, CRVALia.
+*
+*   char (*cunit)[72]
+*     (Given) Address of the first element of an array of char[72] containing
+*     the CUNITia keyvalues which define the units of measurement of the
+*     CRVALia, CDELTia, and CDi_ja keywords.
+*
+*     As CUNITia is an optional header keyword, cunit[][72] may be left blank
+*     but otherwise is expected to contain a standard units specification as
+*     defined by WCS Paper I.  Utility function wcsutrn(), described in
+*     wcsunits.h, is available to translate commonly used non-standard units
+*     specifications but this must be done as a separate step before invoking
+*     wcsset().
+*
+*     For celestial axes, if cunit[][72] is not blank, wcsset() uses
+*     wcsunits() to parse it and scale cdelt[], crval[], and cd[][*] to
+*     degrees.  It then resets cunit[][72] to "deg".
+*
+*     For spectral axes, if cunit[][72] is not blank, wcsset() uses wcsunits()
+*     to parse it and scale cdelt[], crval[], and cd[][*] to SI units.  It
+*     then resets cunit[][72] accordingly.
+*
+*     wcsset() ignores cunit[][72] for other coordinate types; cunit[][72] may
+*     be used to label coordinate values.
+*
+*     These variables accomodate the longest allowed string-valued FITS
+*     keyword, being limited to 68 characters, plus the null-terminating
+*     character.
+*
+*   char (*ctype)[72]
+*     (Given) Address of the first element of an array of char[72] containing
+*     the coordinate axis types, CTYPEia.
+*
+*     The ctype[][72] keyword values must be in upper case and there must be
+*     zero or one pair of matched celestial axis types, and zero or one
+*     spectral axis.  The ctype[][72] strings should be padded with blanks on
+*     the right and null-terminated so that they are at least eight characters
+*     in length.
+*
+*     These variables accomodate the longest allowed string-valued FITS
+*     keyword, being limited to 68 characters, plus the null-terminating
+*     character.
+*
+*   double lonpole
+*     (Given and returned) The native longitude of the celestial pole, phi_p,
+*     given by LONPOLEa [deg] or by PVi_2a [deg] attached to the longitude
+*     axis which takes precedence if defined, and ...
+*   double latpole
+*     (Given and returned) ... the native latitude of the celestial pole,
+*     theta_p, given by LATPOLEa [deg] or by PVi_3a [deg] attached to the
+*     longitude axis which takes precedence if defined.
+*
+*     lonpole and latpole may be left to default to values set by wcsini()
+*     (see celprm::ref), but in any case they will be reset by wcsset() to
+*     the values actually used.  Note therefore that if the wcsprm struct is
+*     reused without resetting them, whether directly or via wcsini(), they
+*     will no longer have their default values.
+*
+*   double restfrq
+*     (Given) The rest frequency [Hz], and/or ...
+*   double restwav
+*     (Given) ... the rest wavelength in vacuuo [m], only one of which need be
+*     given, the other should be set to zero.
+*
+*   int npv
+*     (Given) The number of entries in the wcsprm::pv[] array.
+*
+*   int npvmax
+*     (Given or returned) The length of the wcsprm::pv[] array.
+*
+*     npvmax will be set by wcsini() if it allocates memory for wcsprm::pv[],
+*     otherwise it must be set by the user.  See also wcsnpv().
+*
+*   struct pvcard *pv
+*     (Given or returned) Address of the first element of an array of length
+*     npvmax of pvcard structs.  Set by wcsini() if it allocates memory for
+*     pv[], otherwise it must be set by the user.  See also wcsnpv().
+*
+*     As a FITS header parser encounters each PVi_ma keyword it should load it
+*     into a pvcard struct in the array and increment npv.  wcsset()
+*     interprets these as required.
+*
+*     Note that, if they were not given, wcsset() resets the entries for
+*     PVi_1a, PVi_2a, PVi_3a, and PVi_4a for longitude axis i to match
+*     phi_0 and theta_0 (the native longitude and latitude of the reference
+*     point), LONPOLEa and LATPOLEa respectively.
+*
+*   int nps
+*     (Given) The number of entries in the wcsprm::ps[] array.
+*
+*   int npsmax
+*     (Given or returned) The length of the wcsprm::ps[] array.
+*
+*     npsmax will be set by wcsini() if it allocates memory for wcsprm::ps[],
+*     otherwise it must be set by the user.  See also wcsnps().
+*
+*   struct pscard *ps
+*     (Given or returned) Address of the first element of an array of length
+*     npsmax of pscard structs.  Set by wcsini() if it allocates memory for
+*     ps[], otherwise it must be set by the user.  See also wcsnps().
+*
+*     As a FITS header parser encounters each PSi_ma keyword it should load it
+*     into a pscard struct in the array and increment nps.  wcsset()
+*     interprets these as required (currently no PSi_ma keyvalues are
+*     recognized).
+*
+*   double *cd
+*     (Given) For historical compatibility, the wcsprm struct supports two
+*     alternate specifications of the linear transformation matrix, those
+*     associated with the CDi_ja keywords, and ...
+*   double *crota
+*     (Given) ... those associated with the CROTAia keywords.  Although these
+*     may not formally co-exist with PCi_ja, the approach taken here is simply
+*     to ignore them if given in conjunction with PCi_ja.
+*
+*   int altlin
+*     (Given) altlin is a bit flag that denotes which of the PCi_ja, CDi_ja
+*     and CROTAia keywords are present in the header:
+*
+*     - Bit 0: PCi_ja is present.
+*
+*     - Bit 1: CDi_ja is present.
+*
+*       Matrix elements in the IRAF convention are
+*       equivalent to the product CDi_ja = CDELTia * PCi_ja, but the
+*       defaults differ from that of the PCi_ja matrix.  If one or more
+*       CDi_ja keywords are present then all unspecified CDi_ja default to
+*       zero.  If no CDi_ja (or CROTAia) keywords are present, then the
+*       header is assumed to be in PCi_ja form whether or not any PCi_ja
+*       keywords are present since this results in an interpretation of
+*       CDELTia consistent with the original FITS specification.
+*
+*       While CDi_ja may not formally co-exist with PCi_ja, it may co-exist
+*       with CDELTia and CROTAia which are to be ignored.
+*
+*     - Bit 2: CROTAia is present.
+*
+*       In the AIPS convention, CROTAia may only be
+*       associated with the latitude axis of a celestial axis pair.  It
+*       specifies a rotation in the image plane that is applied AFTER the
+*       CDELTia; any other CROTAia keywords are ignored.
+*
+*       CROTAia may not formally co-exist with PCi_ja.
+*
+*       CROTAia and CDELTia may formally co-exist with CDi_ja but if so are to
+*       be ignored.
+*
+*     CDi_ja and CROTAia keywords, if found, are to be stored in the
+*     wcsprm::cd and wcsprm::crota arrays which are dimensioned similarly to
+*     wcsprm::pc and wcsprm::cdelt.  FITS
+*     header parsers should use the following procedure:
+*
+*     - Whenever a PCi_ja  keyword is encountered: altlin |= 1;
+*
+*     - Whenever a CDi_ja  keyword is encountered: altlin |= 2;
+*
+*     - Whenever a CROTAia keyword is encountered: altlin |= 4;
+*
+*     If none of these bits are set the PCi_ja representation results, i.e.
+*     wcsprm::pc and wcsprm::cdelt will be used as given.
+*
+*     These alternate specifications of the linear transformation matrix are
+*     translated immediately to PCi_ja by wcsset() and are invisible to the
+*     lower-level WCSLIB routines.  In particular, wcsset() resets
+*     wcsprm::cdelt to unity if CDi_ja is present (and no PCi_ja).
+*
+*     If CROTAia are present but none is associated with the latitude axis
+*     (and no PCi_ja or CDi_ja), then wcsset() reverts to a unity PCi_ja
+*     matrix.
+*
+*   int velref
+*     (Given) AIPS velocity code VELREF, refer to spcaips().
+*
+*   char alt[4]
+*     (Given, auxiliary) Character code for alternate coordinate descriptions
+*     (i.e. the 'a' in keyword names such as CTYPEia).  This is blank for the
+*     primary coordinate description, or one of the 26 upper-case letters,
+*     A-Z.
+*
+*     An array of four characters is provided for alignment purposes, only the
+*     first is used.
+*
+*   int colnum
+*     (Given, auxiliary) Where the coordinate representation is associated
+*     with an image-array column in a FITS binary table, this variable may be
+*     used to record the relevant column number.
+*
+*     It should be set to zero for an image header or pixel list.
+*
+*   int *colax
+*     (Given, auxiliary) Address of the first element of an array of int
+*     recording the column numbers for each axis in a pixel list.
+*
+*     The array elements should be set to zero for an image header or image
+*     array in a binary table.
+*
+*   char (*cname)[72]
+*     (Given, auxiliary) The address of the first element of an array of
+*     char[72] containing the coordinate axis names, CNAMEia.
+*
+*     These variables accomodate the longest allowed string-valued FITS
+*     keyword, being limited to 68 characters, plus the null-terminating
+*     character.
+*
+*   double *crder
+*     (Given, auxiliary) Address of the first element of an array of double
+*     recording the random error in the coordinate value, CRDERia.
+*   double *csyer
+*     (Given, auxiliary) Address of the first element of an array of double
+*     recording the systematic error in the coordinate value, CSYERia.
+*
+*   char dateavg[72]
+*     (Given, auxiliary) The date of a representative mid-point of the
+*     observation in ISO format, yyyy-mm-ddThh:mm:ss.
+*   char dateobs[72]
+*     (Given, auxiliary) The date of the start of the observation unless
+*     otherwise explained in the comment field of the DATE-OBS keyword, in
+*     ISO format, yyyy-mm-ddThh:mm:ss.
+*
+*   double equinox
+*     (Given, auxiliary) The equinox associated with dynamical equatorial or
+*     ecliptic coordinate systems, EQUINOXa (or EPOCH in older headers).  Not
+*     applicable to ICRS equatorial or ecliptic coordinates.
+*
+*   double mjdavg
+*     (Given, auxiliary) Modified Julian Date (MJD = JD - 2400000.5), MJD-AVG,
+*     corresponding to DATE-AVG.
+*   double mjdobs
+*     (Given, auxiliary) Modified Julian Date (MJD = JD - 2400000.5), MJD-OBS,
+*     corresponding to DATE-OBS.
+*
+*   double obsgeo[3]
+*     (Given, auxiliary) Location of the observer in a standard terrestrial
+*     reference frame, OBSGEO-X, OBSGEO-Y, OBSGEO-Z [m].
+*
+*   char radesys[72]
+*     (Given, auxiliary) The equatorial or ecliptic coordinate system type,
+*     RADESYSa.
+*
+*   char specsys[72]
+*     (Given, auxiliary) Spectral reference frame (standard of rest),
+*     SPECSYSa, and ...
+*   char ssysobs[72]
+*     (Given, auxiliary) ... the actual frame in which there is no
+*     differential variation in the spectral coordinate across the
+*     field-of-view, SSYSOBSa.
+*   double velosys
+*     (Given, auxiliary) The relative radial velocity [m/s] between the
+*     observer and the selected standard of rest in the direction of the
+*     celestial reference coordinate, VELOSYSa.
+*
+*   double zsource
+*     (Given, auxiliary) The redshift, ZSOURCEa, of the source, and ...
+*   char ssyssrc[72]
+*     (Given, auxiliary) ... the spectral reference frame (standard of rest)
+*     in which this was measured, SSYSSRCa.
+*
+*   double velangl
+*     (Given, auxiliary) The angle [deg] that should be used to decompose an
+*     observed velocity into radial and transverse components.
+*
+*   char wcsname[72]
+*     (Given, auxiliary) The name given to the coordinate representation,
+*     WCSNAMEa.  This variable accomodates the longest allowed string-valued
+*     FITS keyword, being limited to 68 characters, plus the null-terminating
+*     character.
+*
+*   int ntab
+*     (Given) See wcsprm::tab.
+*
+*   int nwtb
+*     (Given) See wcsprm::wtb.
+*
+*   struct tabprm *tab
+*     (Given) Address of the first element of an array of ntab tabprm structs
+*     for which memory has been allocated.  These are used to store tabular
+*     transformation parameters.
+*
+*     Although technically wcsprm::ntab and tab are "given", they will
+*     normally be set by invoking wcstab(), whether directly or indirectly.
+*
+*     The tabprm structs contain some members that must be supplied and others
+*     that are derived.  The information to be supplied comes primarily from
+*     arrays stored in one or more FITS binary table extensions.  These
+*     arrays, referred to here as "wcstab arrays", are themselves located by
+*     parameters stored in the FITS image header.
+*
+*   struct wtbarr *wtb
+*     (Given) Address of the first element of an array of nwtb wtbarr structs
+*     for which memory has been allocated.  These are used in extracting
+*     wcstab arrays from a FITS binary table.
+*
+*     Although technically wcsprm::nwtb and wtb are "given", they will
+*     normally be set by invoking wcstab(), whether directly or indirectly.
+*
+*   char lngtyp[8]
+*     (Returned) Four-character WCS celestial longitude and ...
+*   char lattyp[8]
+*     (Returned) ... latitude axis types. e.g. "RA", "DEC", "GLON", "GLAT",
+*     etc. extracted from 'RA--', 'DEC-', 'GLON', 'GLAT', etc. in the first
+*     four characters of CTYPEia but with trailing dashes removed.  (Declared
+*     as char[8] for alignment reasons.)
+*
+*   int lng
+*     (Returned) Index for the longitude coordinate, and ...
+*   int lat
+*     (Returned) ... index for the latitude coordinate, and ...
+*   int spec
+*     (Returned) ... index for the spectral coordinate in the imgcrd[][] and
+*     world[][] arrays in the API of wcsp2s(), wcss2p() and wcsmix().
+*
+*     These may also serve as indices into the pixcrd[][] array provided that
+*     the PCi_ja matrix does not transpose axes.
+*
+*   int cubeface
+*     (Returned) Index into the pixcrd[][] array for the CUBEFACE axis.  This
+*     is used for quadcube projections where the cube faces are stored on a
+*     separate axis (see wcs.h).
+*
+*   int *types
+*     (Returned) Address of the first element of an array of int containing a
+*     four-digit type code for each axis.
+*
+*     - First digit (i.e. 1000s):
+*       - 0: Non-specific coordinate type.
+*       - 1: Stokes coordinate.
+*       - 2: Celestial coordinate (including CUBEFACE).
+*       - 3: Spectral coordinate.
+*
+*     - Second digit (i.e. 100s):
+*       - 0: Linear axis.
+*       - 1: Quantized axis (STOKES, CUBEFACE).
+*       - 2: Non-linear celestial axis.
+*       - 3: Non-linear spectral axis.
+*       - 4: Logarithmic axis.
+*       - 5: Tabular axis.
+*
+*     - Third digit (i.e. 10s):
+*       - 0: Group number, e.g. lookup table number, being an index into the
+*            tabprm array (see above).
+*
+*     - The fourth digit is used as a qualifier depending on the axis type.
+*
+*       - For celestial axes:
+*         - 0: Longitude coordinate.
+*         - 1: Latitude coordinate.
+*         - 2: CUBEFACE number.
+*
+*       - For lookup tables: the axis number in a multidimensional table.
+*
+*     CTYPEia in "4-3" form with unrecognized algorithm code will have its
+*     type set to -1 and generate an error.
+*
+*   void *padding
+*     (An unused variable inserted for alignment purposes only.)
+*
+*   struct linprm lin
+*     (Returned) Linear transformation parameters (usage is described in the
+*     prologue to lin.h).
+*
+*   struct celprm cel
+*     (Returned) Celestial transformation parameters (usage is described in
+*     the prologue to cel.h).
+*
+*   struct spcprm spc
+*     (Returned) Spectral transformation parameters (usage is described in the
+*     prologue to spc.h).
+*
+*   struct wcserr *err
+*     (Returned) If enabled, when an error status is returned this struct
+*     contains detailed information about the error, see wcserr_enable().
+*
+*   void *m_padding
+*     (For internal use only.)
+*   int m_flag
+*     (For internal use only.)
+*   int m_naxis
+*     (For internal use only.)
+*   double *m_crpix
+*     (For internal use only.)
+*   double *m_pc
+*     (For internal use only.)
+*   double *m_cdelt
+*     (For internal use only.)
+*   double *m_crval
+*     (For internal use only.)
+*   char (*m_cunit)[72]
+*     (For internal use only.)
+*   char (*m_ctype)[72]
+*     (For internal use only.)
+*   struct pvcard *m_pv
+*     (For internal use only.)
+*   struct pscard *m_ps
+*     (For internal use only.)
+*   double *m_cd
+*     (For internal use only.)
+*   double *m_crota
+*     (For internal use only.)
+*   int *m_colax
+*     (For internal use only.)
+*   char (*m_cname)[72]
+*     (For internal use only.)
+*   double *m_crder
+*     (For internal use only.)
+*   double *m_csyer
+*     (For internal use only.)
+*   struct tabprm *m_tab
+*     (For internal use only.)
+*   struct wtbarr *m_wtb
+*     (For internal use only.)
+*
+*
+* pscard struct - Store for PSi_ma keyrecords
+* -------------------------------------------
+* The pscard struct is used to pass the parsed contents of PSi_ma keyrecords
+* to wcsset() via the wcsprm struct.
+*
+* All members of this struct are to be set by the user.
+*
+*   int i
+*     (Given) Axis number (1-relative), as in the FITS PSi_ma keyword.
+*
+*   int m
+*     (Given) Parameter number (non-negative), as in the FITS PSi_ma keyword.
+*
+*   char value[72]
+*     (Given) Parameter value.
+*
+*
+* pvcard struct - Store for PVi_ma keyrecords
+* -------------------------------------------
+* The pvcard struct is used to pass the parsed contents of PVi_ma keyrecords
+* to wcsset() via the wcsprm struct.
+*
+* All members of this struct are to be set by the user.
+*
+*   int i
+*     (Given) Axis number (1-relative), as in the FITS PVi_ma keyword.  If
+*     i == 0, wcsset() will replace it with the latitude axis number.
+*
+*   int m
+*     (Given) Parameter number (non-negative), as in the FITS PVi_ma keyword.
+*
+*   double value
+*     (Given) Parameter value.
+*
+*
+* wtbarr struct - Extraction of coordinate lookup tables from BINTABLE
+* --------------------------------------------------------------------
+* Function wcstab(), which is invoked automatically by wcspih(), sets up an
+* array of wtbarr structs to assist in extracting coordinate lookup tables
+* from a binary table extension (BINTABLE) and copying them into the tabprm
+* structs stored in wcsprm.  Refer to the usage notes for wcspih() and
+* wcstab() in wcshdr.h, and also the prologue to tab.h.
+*
+* For C++ usage, because of a name space conflict with the wtbarr typedef
+* defined in CFITSIO header fitsio.h, the wtbarr struct is renamed to wtbarr_s
+* by preprocessor macro substitution with scope limited to wcs.h itself.
+*
+*   int i
+*     (Given) Image axis number.
+*
+*   int m
+*     (Given) wcstab array axis number for index vectors.
+*
+*   int kind
+*     (Given) Character identifying the wcstab array type:
+*       - c: coordinate array,
+*       - i: index vector.
+*
+*   char extnam[72]
+*     (Given) EXTNAME identifying the binary table extension.
+*
+*   int extver
+*     (Given) EXTVER identifying the binary table extension.
+*
+*   int extlev
+*     (Given) EXTLEV identifying the binary table extension.
+*
+*   char ttype[72]
+*     (Given) TTYPEn identifying the column of the binary table that contains
+*     the wcstab array.
+*
+*   long row
+*     (Given) Table row number.
+*
+*   int ndim
+*     (Given) Expected dimensionality of the wcstab array.
+*
+*   int *dimlen
+*     (Given) Address of the first element of an array of int of length ndim
+*     into which the wcstab array axis lengths are to be written.
+*
+*   double **arrayp
+*     (Given) Pointer to an array of double which is to be allocated by the
+*     user and into which the wcstab array is to be written.
+*
+*
+* Global variable: const char *wcs_errmsg[] - Status return messages
+* ------------------------------------------------------------------
+* Error messages to match the status value returned from each function.
+*
+*===========================================================================*/
+
+#ifndef WCSLIB_WCS
+#define WCSLIB_WCS
+
+#include "lin.h"
+#include "cel.h"
+#include "spc.h"
+#include "tab.h"
+#include "wcserr.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define WCSSUB_LONGITUDE 0x1001
+#define WCSSUB_LATITUDE  0x1002
+#define WCSSUB_CUBEFACE  0x1004
+#define WCSSUB_CELESTIAL 0x1007
+#define WCSSUB_SPECTRAL  0x1008
+#define WCSSUB_STOKES    0x1010
+
+
+extern const char *wcs_errmsg[];
+
+enum wcs_errmsg_enum {
+  WCSERR_SUCCESS         =  0,	/* Success. */
+  WCSERR_NULL_POINTER    =  1,	/* Null wcsprm pointer passed. */
+  WCSERR_MEMORY          =  2,	/* Memory allocation failed. */
+  WCSERR_SINGULAR_MTX    =  3,	/* Linear transformation matrix is
+				   singular. */
+  WCSERR_BAD_CTYPE       =  4,	/* Inconsistent or unrecognized coordinate
+				   axis types. */
+  WCSERR_BAD_PARAM       =  5,	/* Invalid parameter value. */
+  WCSERR_BAD_COORD_TRANS =  6,	/* Invalid coordinate transformation
+				   parameters. */
+  WCSERR_ILL_COORD_TRANS =  7,	/* Ill-conditioned coordinate transformation
+				   parameters. */
+  WCSERR_BAD_PIX         =  8,	/* One or more of the pixel coordinates were
+				   invalid. */
+  WCSERR_BAD_WORLD       =  9,	/* One or more of the world coordinates were
+				   invalid. */
+  WCSERR_BAD_WORLD_COORD = 10,	/* Invalid world coordinate. */
+  WCSERR_NO_SOLUTION     = 11,	/* No solution found in the specified
+				   interval. */
+  WCSERR_BAD_SUBIMAGE    = 12,	/* Invalid subimage specification. */
+  WCSERR_NON_SEPARABLE   = 13	/* Non-separable subimage coordinate
+				   system. */
+};
+
+
+/* Struct used for storing PVi_ma keywords. */
+struct pvcard {
+  int i;			/* Axis number, as in PVi_ma (1-relative).  */
+  int m;			/* Parameter number, ditto  (0-relative).   */
+  double value;			/* Parameter value.                         */
+};
+
+/* Struct used for storing PSi_ma keywords. */
+struct pscard {
+  int i;			/* Axis number, as in PSi_ma (1-relative).  */
+  int m;			/* Parameter number, ditto  (0-relative).   */
+  char value[72];		/* Parameter value.                         */
+};
+
+				/* For extracting wcstab arrays.  Matches   */
+				/* the wtbarr typedef defined in CFITSIO    */
+				/* header fitsio.h.                         */
+#ifdef __cplusplus
+#define wtbarr wtbarr_s		/* See prologue above.                      */
+#endif
+struct wtbarr {
+  int  i;			/* Image axis number.                       */
+  int  m;			/* Array axis number for index vectors.     */
+  int  kind;			/* wcstab array type.                       */
+  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 wcstab 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 wcstab array.     */
+};
+
+
+struct wcsprm {
+  /* Initialization flag (see the prologue above).                          */
+  /*------------------------------------------------------------------------*/
+  int    flag;			/* Set to zero to force initialization.     */
+
+  /* FITS header keyvalues to be provided (see the prologue above).         */
+  /*------------------------------------------------------------------------*/
+  int    naxis;			/* Number of axes (pixel and coordinate).   */
+  double *crpix;		/* CRPIXja keyvalues for each pixel axis.   */
+  double *pc;			/* PCi_ja  linear transformation matrix.    */
+  double *cdelt;		/* CDELTia keyvalues for each coord axis.   */
+  double *crval;		/* CRVALia keyvalues for each coord axis.   */
+
+  char   (*cunit)[72];		/* CUNITia keyvalues for each coord axis.   */
+  char   (*ctype)[72];		/* CTYPEia keyvalues for each coord axis.   */
+
+  double lonpole;		/* LONPOLEa keyvalue.                       */
+  double latpole;		/* LATPOLEa keyvalue.                       */
+
+  double restfrq;		/* RESTFRQa keyvalue.                       */
+  double restwav;		/* RESTWAVa keyvalue.                       */
+
+  int    npv;			/* Number of PVi_ma keywords, and the       */
+  int    npvmax;		/* number for which space was allocated.    */
+  struct pvcard *pv;		/* PVi_ma keywords for each i and m.        */
+
+  int    nps;			/* Number of PSi_ma keywords, and the       */
+  int    npsmax;		/* number for which space was allocated.    */
+  struct pscard *ps;		/* PSi_ma keywords for each i and m.        */
+
+  /* Alternative header keyvalues (see the prologue above).                 */
+  /*------------------------------------------------------------------------*/
+  double *cd;			/* CDi_ja linear transformation matrix.     */
+  double *crota;		/* CROTAia keyvalues for each coord axis.   */
+  int    altlin;		/* Alternative representations              */
+				/*   Bit 0: PCi_ja  is present,             */
+				/*   Bit 1: CDi_ja  is present,             */
+				/*   Bit 2: CROTAia is present.             */
+  int    velref;		/* AIPS velocity code, VELREF.              */
+
+  /* Auxiliary coordinate system information, not used by WCSLIB.           */
+  char   alt[4];
+  int    colnum;
+  int    *colax;
+
+  char   (*cname)[72];
+  double *crder;
+  double *csyer;
+  char   dateavg[72];
+  char   dateobs[72];
+  double equinox;
+  double mjdavg;
+  double mjdobs;
+  double obsgeo[3];
+  char   radesys[72];
+  char   specsys[72];
+  char   ssysobs[72];
+  double velosys;
+  double zsource;
+  char   ssyssrc[72];
+  double velangl;
+  char   wcsname[72];
+
+  /* Coordinate lookup tables (see the prologue above).                     */
+  /*------------------------------------------------------------------------*/
+  int    ntab;			/* Number of separate tables.               */
+  int    nwtb;			/* Number of wtbarr structs.                */
+  struct tabprm *tab;		/* Tabular transformation parameters.       */
+  struct wtbarr *wtb;		/* Array of wtbarr structs.                 */
+
+  /* Information derived from the FITS header keyvalues by wcsset().        */
+  /*------------------------------------------------------------------------*/
+  char   lngtyp[8], lattyp[8];	/* Celestial axis types, e.g. RA, DEC.      */
+  int    lng, lat, spec;	/* Longitude, latitude and spectral axis    */
+				/* indices (0-relative).                    */
+  int    cubeface;		/* True if there is a CUBEFACE axis.        */
+  int    *types;		/* Coordinate type codes for each axis.     */
+  void   *padding;		/* (Dummy inserted for alignment purposes.) */
+
+  struct linprm lin;		/* Linear    transformation parameters.     */
+  struct celprm cel;		/* Celestial transformation parameters.     */
+  struct spcprm spc;		/* Spectral  transformation parameters.     */
+
+  /* Error handling                                                         */
+  /*------------------------------------------------------------------------*/
+  struct wcserr *err;
+
+  /* Private - the remainder are for memory management.                     */
+  /*------------------------------------------------------------------------*/
+  void   *m_padding;
+  int    m_flag, m_naxis;
+  double *m_crpix, *m_pc, *m_cdelt, *m_crval;
+  char  (*m_cunit)[72], (*m_ctype)[72];
+  struct pvcard *m_pv;
+  struct pscard *m_ps;
+  double *m_cd, *m_crota;
+  int    *m_colax;
+  char  (*m_cname)[72];
+  double *m_crder, *m_csyer;
+  struct tabprm *m_tab;
+  struct wtbarr *m_wtb;
+};
+
+/* Size of the wcsprm struct in int units, used by the Fortran wrappers. */
+#define WCSLEN (sizeof(struct wcsprm)/sizeof(int))
+
+
+int wcsnpv(int n);
+
+int wcsnps(int n);
+
+int wcsini(int alloc, int naxis, struct wcsprm *wcs);
+
+int wcssub(int alloc, const struct wcsprm *wcssrc, int *nsub, int axes[],
+           struct wcsprm *wcsdst);
+
+int wcsfree(struct wcsprm *wcs);
+
+int wcsprt(const struct wcsprm *wcs);
+
+int wcsperr(const struct wcsprm *wcs, const char *prefix);
+
+int wcsset(struct wcsprm *wcs);
+
+int wcsp2s(struct wcsprm *wcs, int ncoord, int nelem, const double pixcrd[],
+           double imgcrd[], double phi[], double theta[], double world[],
+           int stat[]);
+
+int wcss2p(struct wcsprm *wcs, int ncoord, int nelem, const double world[],
+           double phi[], double theta[], double imgcrd[], double pixcrd[],
+           int stat[]);
+
+int wcsmix(struct wcsprm *wcs, int mixpix, int mixcel, const double vspan[],
+           double vstep, int viter, double world[], double phi[],
+           double theta[], double imgcrd[], double pixcrd[]);
+
+int wcssptr(struct wcsprm *wcs, int *i, char ctype[9]);
+
+/* Defined mainly for backwards compatibility, use wcssub() instead. */
+#define wcscopy(alloc, wcssrc, wcsdst) wcssub(alloc, wcssrc, 0x0, 0x0, wcsdst)
+
+
+/* Deprecated. */
+#define wcsini_errmsg wcs_errmsg
+#define wcssub_errmsg wcs_errmsg
+#define wcscopy_errmsg wcs_errmsg
+#define wcsfree_errmsg wcs_errmsg
+#define wcsprt_errmsg wcs_errmsg
+#define wcsset_errmsg wcs_errmsg
+#define wcsp2s_errmsg wcs_errmsg
+#define wcss2p_errmsg wcs_errmsg
+#define wcsmix_errmsg wcs_errmsg
+
+#ifdef __cplusplus
+#undef wtbarr
+}
+#endif
+
+#endif /* WCSLIB_WCS */
diff --git a/cextern/wcslib/C/wcsbth.l b/cextern/wcslib/C/wcsbth.l
new file mode 100644
index 0000000..162850c
--- /dev/null
+++ b/cextern/wcslib/C/wcsbth.l
@@ -0,0 +1,2563 @@
+/*============================================================================
+
+  WCSLIB 4.16 - an implementation of the FITS WCS standard.
+  Copyright (C) 1995-2012, Mark Calabretta
+
+  This file is part of WCSLIB.
+
+  WCSLIB is free software: you can redistribute it and/or modify it under the
+  terms of the GNU Lesser General Public License as published by the Free
+  Software Foundation, either version 3 of the License, or (at your option)
+  any later version.
+
+  WCSLIB 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 Lesser General Public License for
+  more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with WCSLIB.  If not, see http://www.gnu.org/licenses.
+
+  Direct correspondence concerning WCSLIB to mark at calabretta.id.au
+
+  Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
+  http://www.atnf.csiro.au/people/Mark.Calabretta
+  $Id: wcsbth.l,v 4.16 2012/11/07 04:42:44 cal103 Exp $
+*=============================================================================
+*
+* wcsbth.l is a Flex description file containing the definition of a lexical
+* scanner for parsing the WCS keyrecords for one or more image arrays and/or
+* pixel lists in a FITS binary table header.  It can also handle primary image
+* and image extension headers.
+*
+* wcsbth.l requires Flex v2.5.4 or later.  Refer to wcshdr.h for a description
+* of the user interface and operating notes.
+*
+* Implementation notes
+* --------------------
+* wcsbth() may be invoked with an option that causes it to recognise the
+* image-header form of WCS keywords as defaults for each alternate coordinate
+* representation (up to 27).  By design, with this option enabled wcsbth() can
+* also handle primary image and image extension headers, effectively treating
+* them as a single-column binary table though with WCS keywords of a different
+* form.
+*
+* NAXIS is always 2 for binary tables, it refers to the two-dimensional nature
+* of the table.  Thus NAXIS does not count the number of image axes in either
+* image arrays or pixels lists and for the latter there is not even a formal
+* equivalent of WCSAXESa.  Hence NAXIS is always ignored and a first pass
+* through the header is required to determine the number of images, the number
+* of alternate coordinate representations for each image (up to 27), and the
+* number of coordinate axes in each representation; this pass also counts the
+* number of iPVn_ma and iPSn_ma or TVk_ma and TSk_ma keywords in each
+* representation.
+*
+* On completion of the first pass, the association between column number and
+* axis number is defined for each representation of a pixel list.  Memory is
+* allocated for an array of the required number of wcsprm structs and each of
+* these is initialized appropriately.  These structs are filled in the second
+* pass.
+*
+* It is permissible for a scalar table column to contain degenerate (single-
+* point) image arrays and simultaneously form one axis of a pixel list.
+*
+* The parser does not check for duplicated keywords, for most keywords it
+* accepts the last encountered.
+*
+* wcsbth() does not currently handle the Green Bank convention.
+*
+*===========================================================================*/
+
+/* Options. */
+%option full
+%option never-interactive
+%option noyywrap
+%option outfile="wcsbth.c"
+%option prefix="wcsbth"
+
+/* Indices for parameterized keywords. */
+I0	[0-9]
+I1	[1-9]
+I2	[1-9][0-9]
+I3	[1-9][0-9]{2}
+I4	[1-9][0-9]{3}
+
+/* Alternate coordinate system identifier. */
+ALT	[ A-Z]
+
+/* Keyvalue data types. */
+INTEGER	[+-]?[0-9]+
+FLOAT	[+-]?([0-9]+\.?[0-9]*|\.[0-9]+)([eE][+-]?[0-9]+)?
+STRING	'([^']|'')*'
+
+/* Exclusive start states. */
+%x CCCCCia   iCCCna iCCCCn    TCCCna TCCCCn
+%x CCi_ja    ijCCna           TCn_ka TCCn_ka
+%x CROTAi           iCROTn           TCROTn
+%x CCi_ma    iCn_ma iCCn_ma   TCn_ma TCCn_ma
+%x PROJPm
+%x CCCCCCCC CCCCCCCa
+%x CCCCna   CCCCCna
+%x CCCCn    CCCCCn
+%x VALUE INTEGER_VAL FLOAT_VAL STRING_VAL
+%x COMMENT DISCARD ERROR FLUSH
+
+%{
+#include <math.h>
+#include <setjmp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "wcs.h"
+#include "wcshdr.h"
+#include "wcsmath.h"
+#include "wcsutil.h"
+
+			/* Codes used for keyvalue data types. */
+#define INTEGER 0
+#define FLOAT   1
+#define STRING  2
+
+			/* Bit masks used for keyword types:        */
+#define IMGAUX  0x1	/* Auxiliary image header, e.g. LONPOLEa or */
+			/* DATE-OBS.                                */
+#define IMGAXIS 0x2	/* Image header with axis number, e.g.      */
+			/* CTYPEia.                                 */
+#define IMGHEAD 0x3	/* Image header of either type.             */
+#define BIMGARR 0x4	/* Binary table image array with axis       */
+			/* number, e.g. iCTYna.                     */
+#define PIXLIST 0x8	/* Pixel list, e.g. TCTYna.                 */
+#define BINTAB  0xC	/* Shared binary table image array (without */
+			/* axis number) or pixel list, e.g. LONPna  */
+			/* or OBSGXn.                               */
+
+#define YY_DECL int wcsbth(char *header, int nkeyrec, int relax, int ctrl, \
+                           int keysel, int *colsel, int *nreject, int *nwcs, \
+			   struct wcsprm **wcs)
+
+#define YY_INPUT(inbuff, count, bufsize) \
+	{ \
+	  if (wcsbth_nkeyrec) { \
+	    strncpy(inbuff, wcsbth_hdr, 80); \
+	    inbuff[80] = '\n'; \
+	    wcsbth_hdr += 80; \
+	    wcsbth_nkeyrec--; \
+	    count = 81; \
+	  } else { \
+	    count = YY_NULL; \
+	  } \
+	}
+
+/* A convenience macro to get around incompatibilities between unput() and
+   yyless(): put yytext followed by a blank back onto the input stream. */
+#define WCSBTH_PUTBACK \
+  sprintf(stmp, "%s ", yytext); \
+  itmp = strlen(stmp); \
+  while (itmp) unput(stmp[--itmp]);
+
+/* These global variables are required by YY_INPUT. */
+char *wcsbth_hdr;
+int  wcsbth_nkeyrec;
+
+/* Used in preempting the call to exit() by yy_fatal_error(). */
+jmp_buf wcsbth_abort_jmp_env;
+#define exit(status) longjmp(wcsbth_abort_jmp_env, status)
+
+/* Struct used internally for header bookkeeping. */
+struct wcsbth_alts {
+  int ncol, ialt, icol, imgherit;
+  short int (*arridx)[27];
+  short int pixidx[27];
+  short int pad1;
+  unsigned int *pixlist;
+
+  unsigned char (*npv)[27];
+  unsigned char (*nps)[27];
+  unsigned char pixnpv[27];
+  unsigned char pixnps[27];
+  unsigned char pad2[2];
+};
+
+int wcsbth_pass1(int keytype, int i, int j, int n, int k, char a, char ptype,
+        struct wcsbth_alts *alts);
+int wcsbth_init1(struct wcsbth_alts *alts, int *nwcs, struct wcsprm **wcs);
+
+struct wcsprm *wcsbth_idx(struct wcsprm *wcs, struct wcsbth_alts *alts,
+        int keytype, int n, char a);
+int wcsbth_colax(struct wcsprm *wcs, struct wcsbth_alts *alts, int k, char a);
+
+int wcsbth_epoch(void *wptr);
+int wcsbth_vsource(void *wptr);
+
+int wcsbth_final(struct wcsbth_alts *alts, int *nwcs, struct wcsprm **wcs);
+
+%}
+
+%%
+	/* Keyword indices, as used in the WCS papers, e.g. iVn_ma, TPn_ka. */
+	char a;
+	int  i, j, k, m, n;
+	
+	char *cptr, *errmsg, errtxt[80], exclude[1000], *extkey, *hptr, ptype,
+	     stmp[16];
+	int  altlin, ialt, icol, incl, ipass, ipx, itmp, ix, jx, keytype,
+	     nsel, npass, status, valtype, voff;
+	void   *vptr, *wptr;
+	struct wcsbth_alts alts;
+	struct wcsprm *wcsp, wcstem;
+	int (*special)(void *);
+	int yylex_destroy(void);
+	
+	/* The data structures produced. */
+	*nwcs = 0;
+	*wcs  = 0x0;
+	
+	/* Parameters used to implement YY_INPUT. */
+	wcsbth_hdr = header;
+	wcsbth_nkeyrec = nkeyrec;
+	
+	/* Our handle on the input stream. */
+	hptr = header;
+	*nreject = 0;
+	
+	/* Keyword parameters. */
+	i = j = 0;
+	n = k = 0;
+	m = 0;
+	a = ' ';
+	
+	/* Header bookkeeping. */
+	alts.ncol = 0;
+	alts.arridx  = 0x0;
+	alts.pixlist = 0x0;
+	alts.npv = 0x0;
+	alts.nps = 0x0;
+	
+	for (ialt = 0; ialt < 27; ialt++) {
+	  alts.pixidx[ialt] = 0;
+	  alts.pixnpv[ialt] = 0;
+	  alts.pixnps[ialt] = 0;
+	}
+	
+	/* For decoding the keyvalue. */
+	keytype =  0;
+	valtype = -1;
+	vptr    = 0x0;
+	
+	/* For keywords that require special handling. */
+	altlin = 0;
+	ptype  = ' ';
+	special = 0x0;
+	
+	/* Selection by column number. */
+	nsel = colsel ? colsel[0] : 0;
+	incl = (nsel > 0);
+	for (icol = 0; icol < 1000; icol++) {
+	  exclude[icol] = incl;
+	}
+	for (icol = 1; icol <= abs(nsel); icol++) {
+	  itmp = colsel[icol];
+	  if (0 < itmp && itmp < 1000) {
+	    exclude[itmp] = !incl;
+	  }
+	}
+	exclude[0] = 0;
+	
+	/* Selection by keyword type. */
+	itmp = keysel;
+	keysel = 0;
+	if (itmp) {
+	  if (itmp & WCSHDR_IMGHEAD) keysel |= IMGHEAD;
+	  if (itmp & WCSHDR_BIMGARR) keysel |= BIMGARR;
+	  if (itmp & WCSHDR_PIXLIST) keysel |= PIXLIST;
+	}
+	if (keysel == 0) {
+	  keysel = IMGHEAD | BINTAB;
+	}
+	
+	/* Control variables. */
+	ipass = 1;
+	npass = 2;
+	
+	/* Return here via longjmp() invoked by yy_fatal_error(). */
+	if (setjmp(wcsbth_abort_jmp_env)) {
+	  return 4;
+	}
+	
+	BEGIN(INITIAL);
+
+
+^TFIELDS" = "" "*{INTEGER} {
+	  if (ipass == 1) {
+	    if (alts.ncol == 0) {
+	      sscanf(yytext, "TFIELDS = %d", &(alts.ncol));
+	      BEGIN(FLUSH);
+	    } else {
+	      errmsg = "Duplicate or out-of-sequence TFIELDS keyword";
+	      BEGIN(ERROR);
+	    }
+	
+	  } else {
+	    BEGIN(FLUSH);
+	  }
+	}
+
+^WCSAXES{ALT}=" "" "*{INTEGER} {
+	  keytype = IMGAXIS;
+	
+	  if (!(keytype & keysel)) {
+	    /* Ignore this key type. */
+	    BEGIN(DISCARD);
+	
+	  } else {
+	    if (relax & WCSHDR_ALLIMG) {
+	      if (ipass == 1) {
+	        sscanf(yytext, "WCSAXES%c= %d", &a, &i);
+	        wcsbth_pass1(IMGAXIS, i, 0, 0, 0, a, ' ', &alts);
+	      }
+	
+	      BEGIN(FLUSH);
+	
+	    } else if (relax & WCSHDR_reject) {
+	      errmsg = "Image-header keyword WCSAXESa in binary table";
+	      BEGIN(ERROR);
+	
+	    } else {
+	      /* Pretend we don't recognize it. */
+	      BEGIN(DISCARD);
+	    }
+	  }
+	}
+
+^WCAX{I1}{ALT}"  = "" "*{INTEGER} |
+^WCAX{I2}{ALT}" = "" "*{INTEGER}  |
+^WCAX{I3}{ALT}"= "" "*{INTEGER} {
+	  keytype = BIMGARR;
+	
+	  /* Note that a blank in the sscanf() format string matches zero or
+	     more of them in the input. */
+	  sscanf(yytext, "WCAX%d%c = %d", &n, &a, &i);
+	
+	  if (!(keytype & keysel) || exclude[n]) {
+	    /* Ignore this key type or column. */
+	    BEGIN(DISCARD);
+	  } else {
+	    if (ipass == 1) {
+	      wcsbth_pass1(BIMGARR, i, 0, n, 0, a, ' ', &alts);
+	    }
+	    BEGIN(FLUSH);
+	  }
+	}
+
+^WCST{I1}{ALT}"  = "" "*{STRING} |
+^WCST{I2}{ALT}" = "" "*{STRING} |
+^WCST{I3}{ALT}"= "" "*{STRING} {
+	  /* Cross-reference supplier. */
+	  keytype = BIMGARR;
+	  errmsg = "Cross-references are not currently implemented";
+	  BEGIN(ERROR);
+	}
+
+^WCSX{I1}{ALT}"  = "" "*{STRING} |
+^WCSX{I2}{ALT}" = "" "*{STRING} |
+^WCSX{I3}{ALT}"= "" "*{STRING} {
+	  /* Cross-reference consumer. */
+	  keytype = BIMGARR;
+	  errmsg = "Cross-references are not currently implemented";
+	  BEGIN(ERROR);
+	}
+
+^CRPIX	{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.crpix);
+	
+	  extkey = "CRPIXja";
+	  BEGIN(CCCCCia);
+	}
+
+^{I1}CRP  |
+^{I1}CRPX {
+	  valtype = FLOAT;
+	  vptr = &(wcstem.crpix);
+	
+	  sscanf(yytext, "%d", &i);
+	
+	  if (yyleng == 4) {
+	    BEGIN(iCCCna);
+	  } else {
+	    extkey = "jCRPXn";
+	    BEGIN(iCCCCn);
+	  }
+	}
+
+^TCRP	|
+^TCRPX	{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.crpix);
+	
+	  if (yyleng == 4) {
+	    BEGIN(TCCCna);
+	  } else {
+	    extkey = "TCRPXn";
+	    BEGIN(TCCCCn);
+	  }
+	}
+
+^PC	{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.pc);
+	  altlin = 1;
+	
+	  extkey = "PCi_ja";
+	  BEGIN(CCi_ja);
+	}
+
+^{I2}PC	{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.pc);
+	  altlin = 1;
+	
+	  sscanf(yytext, "%1d%1d", &i, &j);
+	
+	  BEGIN(ijCCna);
+	}
+
+^TP	|
+^TPC	{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.pc);
+	  altlin = 1;
+	
+	  if (yyleng == 2) {
+	    BEGIN(TCn_ka);
+	  } else {
+	    extkey = "TPCn_ka";
+	    BEGIN(TCCn_ka);
+	  }
+	}
+
+^CD	{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.cd);
+	  altlin = 2;
+	
+	  extkey = "CDi_ja";
+	  BEGIN(CCi_ja);
+	}
+
+^{I2}CD	{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.cd);
+	  altlin = 2;
+	
+	  sscanf(yytext, "%1d%1d", &i, &j);
+	
+	  BEGIN(ijCCna);
+	}
+
+^TC	|
+^TCD	{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.cd);
+	  altlin = 2;
+	
+	  if (yyleng == 2) {
+	    BEGIN(TCn_ka);
+	  } else {
+	    extkey = "TCDn_ka";
+	    BEGIN(TCCn_ka);
+	  }
+	}
+
+^CDELT	{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.cdelt);
+	
+	  extkey = "CDELTia";
+	  BEGIN(CCCCCia);
+	}
+
+^{I1}CDE  |
+^{I1}CDLT {
+	  valtype = FLOAT;
+	  vptr = &(wcstem.cdelt);
+	
+	  sscanf(yytext, "%d", &i);
+	
+	  if (yyleng == 4) {
+	    BEGIN(iCCCna);
+	  } else {
+	    extkey = "iCDLTn";
+	    BEGIN(iCCCCn);
+	  }
+	}
+
+^TCDE	|
+^TCDLT	{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.cdelt);
+	
+	  if (yyleng == 4) {
+	    BEGIN(TCCCna);
+	  } else {
+	    extkey = "TCDLTn";
+	    BEGIN(TCCCCn);
+	  }
+	}
+
+^CROTA	{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.crota);
+	  altlin = 4;
+	
+	  extkey = "CROTAi";
+	  BEGIN(CROTAi);
+	}
+
+^{I1}CROT {
+	  valtype = FLOAT;
+	  vptr = &(wcstem.crota);
+	  altlin = 4;
+	
+	  sscanf(yytext, "%d", &i);
+	
+	  extkey = "iCROTn";
+	  BEGIN(iCROTn);
+	}
+
+^TCROT	{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.crota);
+	  altlin = 4;
+	
+	  extkey = "TCROTn";
+	  BEGIN(TCROTn);
+	}
+
+^CUNIT	{
+	  valtype = STRING;
+	  vptr = &(wcstem.cunit);
+	
+	  extkey = "CUNITia";
+	  BEGIN(CCCCCia);
+	}
+
+^{I1}CUN  |
+^{I1}CUNI {
+	  valtype = STRING;
+	  vptr = &(wcstem.cunit);
+	
+	  sscanf(yytext, "%d", &i);
+	
+	  if (yyleng == 4) {
+	    BEGIN(iCCCna);
+	  } else {
+	    extkey = "iCUNIn";
+	    BEGIN(iCCCCn);
+	  }
+	}
+
+^TCUN	|
+^TCUNI	{
+	  valtype = STRING;
+	  vptr = &(wcstem.cunit);
+	
+	  if (yyleng == 4) {
+	    BEGIN(TCCCna);
+	  } else {
+	    extkey = "TCUNIn";
+	    BEGIN(TCCCCn);
+	  }
+	}
+
+^CTYPE	{
+	  valtype = STRING;
+	  vptr = &(wcstem.ctype);
+	
+	  extkey = "CTYPEia";
+	  BEGIN(CCCCCia);
+	}
+
+^{I1}CTY  |
+^{I1}CTYP {
+	  valtype = STRING;
+	  vptr = &(wcstem.ctype);
+	
+	  sscanf(yytext, "%d", &i);
+	
+	  if (yyleng == 4) {
+	    BEGIN(iCCCna);
+	  } else {
+	    extkey = "iCTYPn";
+	    BEGIN(iCCCCn);
+	  }
+	}
+
+^TCTY	|
+^TCTYP	{
+	  valtype = STRING;
+	  vptr = &(wcstem.ctype);
+	
+	  if (yyleng == 4) {
+	    BEGIN(TCCCna);
+	  } else {
+	    extkey = "TCTYPn";
+	    BEGIN(TCCCCn);
+	  }
+	}
+
+^CRVAL	{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.crval);
+	
+	  extkey = "CRVALia";
+	  BEGIN(CCCCCia);
+	}
+
+^{I1}CRV  |
+^{I1}CRVL {
+	  valtype = FLOAT;
+	  vptr = &(wcstem.crval);
+	
+	  sscanf(yytext, "%d", &i);
+	
+	  if (yyleng == 4) {
+	    BEGIN(iCCCna);
+	  } else {
+	    extkey = "iCRVLn";
+	    BEGIN(iCCCCn);
+	  }
+	}
+
+^TCRV	|
+^TCRVL	{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.crval);
+	
+	  if (yyleng == 4) {
+	    BEGIN(TCCCna);
+	  } else {
+	    extkey = "TCRVLn";
+	    BEGIN(TCCCCn);
+	  }
+	}
+
+^LONPOLE |
+^LONP	{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.lonpole);
+	
+	  if (yyleng == 7) {
+	    extkey = "LONPOLEa";
+	    BEGIN(CCCCCCCa);
+	  } else {
+	    BEGIN(CCCCna);
+	  }
+	}
+
+^LATPOLE |
+^LATP	{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.latpole);
+	
+	  if (yyleng == 7) {
+	    extkey = "LATPOLEa";
+	    BEGIN(CCCCCCCa);
+	  } else {
+	    BEGIN(CCCCna);
+	  }
+	}
+
+^RESTFRQ  |
+^RESTFREQ |
+^RFRQ	{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.restfrq);
+	
+	  if (yyleng == 8) {
+	    unput(' ');
+	    extkey = "RESTFREQ";
+	    BEGIN(CCCCCCCa);
+	  } else if (yyleng == 7) {
+	    extkey = "RESTFRQa";
+	    BEGIN(CCCCCCCa);
+	  } else {
+	    BEGIN(CCCCna);
+	  }
+	}
+
+^RESTWAV |
+^RWAV	{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.restwav);
+	
+	  if (yyleng == 7) {
+	    extkey = "RESTWAVa";
+	    BEGIN(CCCCCCCa);
+	  } else {
+	    BEGIN(CCCCna);
+	  }
+	}
+
+^PV	{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.pv);
+	  ptype = 'v';
+	
+	  extkey = "PVi_ma";
+	  BEGIN(CCi_ma);
+	}
+
+^{I1}V	|
+^{I1}PV	{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.pv);
+	  ptype = 'v';
+	
+	  sscanf(yytext, "%d", &i);
+	
+	  if (yyleng == 2) {
+	    BEGIN(iCn_ma);
+	  } else {
+	    extkey = "iPVn_ma";
+	    BEGIN(iCCn_ma);
+	  }
+	}
+
+^TV	|
+^TPV	{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.pv);
+	  ptype = 'v';
+	
+	  if (yyleng == 2) {
+	    BEGIN(TCn_ma);
+	  } else {
+	    extkey = "TPVn_ma";
+	    BEGIN(TCCn_ma);
+	  }
+	}
+
+^PROJP	{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.pv);
+	  ptype = 'v';
+	
+	  BEGIN(PROJPm);
+	}
+
+^PS	{
+	  valtype = STRING;
+	  vptr = &(wcstem.ps);
+	  ptype = 's';
+	
+	  extkey = "PSi_ma";
+	  BEGIN(CCi_ma);
+	}
+
+^{I1}S	|
+^{I1}PS	{
+	  valtype = STRING;
+	  vptr = &(wcstem.ps);
+	  ptype = 's';
+	
+	  sscanf(yytext, "%d", &i);
+	
+	  if (yyleng == 2) {
+	    BEGIN(iCn_ma);
+	  } else {
+	    extkey = "iPSn_ma";
+	    BEGIN(iCCn_ma);
+	  }
+	}
+
+^TS	|
+^TPS	{
+	  valtype = STRING;
+	  vptr = &(wcstem.ps);
+	  ptype = 's';
+	
+	  if (yyleng == 2) {
+	    BEGIN(TCn_ma);
+	  } else {
+	    extkey = "TPSn_ma";
+	    BEGIN(TCCn_ma);
+	  }
+	}
+
+^CNAME	{
+	  valtype = STRING;
+	  vptr = &(wcstem.cname);
+	
+	  extkey = "CNAMEia";
+	  BEGIN(CCCCCia);
+	}
+
+^{I1}CNA  |
+^{I1}CNAM {
+	  valtype = STRING;
+	  vptr = &(wcstem.cname);
+	
+	  sscanf(yytext, "%d", &i);
+	
+	  if (yyleng == 4) {
+	    BEGIN(iCCCna);
+	  } else {
+	    if (!(relax & WCSHDR_CNAMn)) vptr = 0x0;
+	    extkey = "iCNAMn";
+	    BEGIN(iCCCCn);
+	  }
+	}
+
+^TCNA	|
+^TCNAM	{
+	  valtype = STRING;
+	  vptr = &(wcstem.cname);
+	
+	  if (yyleng == 4) {
+	    BEGIN(TCCCna);
+	  } else {
+	    if (!(relax & WCSHDR_CNAMn)) vptr = 0x0;
+	    extkey = "TCNAMn";
+	    BEGIN(TCCCCn);
+	  }
+	}
+
+^CRDER	{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.crder);
+	
+	  extkey = "CRDERia";
+	  BEGIN(CCCCCia);
+	}
+
+^{I1}CRD |
+^{I1}CRDE {
+	  valtype = FLOAT;
+	  vptr = &(wcstem.crder);
+	
+	  sscanf(yytext, "%d", &i);
+	
+	  if (yyleng == 4) {
+	    BEGIN(iCCCna);
+	  } else {
+	    if (!(relax & WCSHDR_CNAMn)) vptr = 0x0;
+	    extkey = "iCRDEn";
+	    BEGIN(iCCCCn);
+	  }
+	}
+
+^TCRD	|
+^TCRDE	{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.crder);
+	
+	  if (yyleng == 4) {
+	    BEGIN(TCCCna);
+	  } else {
+	    if (!(relax & WCSHDR_CNAMn)) vptr = 0x0;
+	    extkey = "TCRDEn";
+	    BEGIN(TCCCCn);
+	  }
+	}
+
+^CSYER	{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.csyer);
+	
+	  extkey = "CSYERia";
+	  BEGIN(CCCCCia);
+	}
+
+^{I1}CSY  |
+^{I1}CSYE {
+	  valtype = FLOAT;
+	  vptr = &(wcstem.csyer);
+	
+	  sscanf(yytext, "%d", &i);
+	
+	  if (yyleng == 4) {
+	    BEGIN(iCCCna);
+	  } else {
+	    if (!(relax & WCSHDR_CNAMn)) vptr = 0x0;
+	    extkey = "iCSYEn";
+	    BEGIN(iCCCCn);
+	  }
+	}
+
+^TCSY	|
+^TCSYE	{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.csyer);
+	
+	  if (yyleng == 4) {
+	    BEGIN(TCCCna);
+	  } else {
+	    if (!(relax & WCSHDR_CNAMn)) vptr = 0x0;
+	    extkey = "TCSYEn";
+	    BEGIN(TCCCCn);
+	  }
+	}
+
+^DATE-AVG |
+^DAVG   {
+	  valtype = STRING;
+	  vptr = wcstem.dateavg;
+	
+	  if (yyleng == 8) {
+	    extkey = "DATE-AVG";
+	    BEGIN(CCCCCCCC);
+	  } else {
+	    BEGIN(CCCCn);
+	  }
+	}
+
+^DATE-OBS {
+	  valtype = STRING;
+	  vptr = wcstem.dateobs;
+	
+	  extkey = "DATE-OBS";
+	  BEGIN(CCCCCCCC);
+	}
+
+^DOBS{I1}"   " |
+^DOBS{I2}"  "  |
+^DOBS{I3}" " {
+	  if (relax & WCSHDR_DOBSn) {
+	    valtype = STRING;
+	    vptr = wcstem.dateobs;
+	
+	    yyless(4);
+	    BEGIN(CCCCn);
+	
+	  } else {
+	    keytype = BINTAB;
+	    if (relax & WCSHDR_reject) {
+	      errmsg = "DOBSna keyword is non-standard";
+	      BEGIN(ERROR);
+	    } else {
+	      BEGIN(DISCARD);
+	    }
+	  }
+	}
+
+^EPOCH{ALT}"  " {
+	  sscanf(yytext, "EPOCH%c", &a);
+	
+	  if (a == ' ' || (relax & WCSHDR_EPOCHa)) {
+	    valtype = FLOAT;
+	    vptr = &(wcstem.equinox);
+	    special = wcsbth_epoch;
+	
+	    unput(a);
+	    extkey = "EPOCH";
+	    BEGIN(CCCCCCCa);
+	
+	  } else {
+	    keytype = IMGAUX;
+	    if (relax & WCSHDR_reject) {
+	      errmsg = "EPOCH keyword may not have an alternate version code";
+	      BEGIN(ERROR);
+	    } else {
+	      BEGIN(DISCARD);
+	    }
+	  }
+	}
+
+^EQUINOX |
+^EQUI	{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.equinox);
+	
+	  if (yyleng == 7) {
+	    extkey = "EQUINOXa";
+	    BEGIN(CCCCCCCa);
+	  } else {
+	    BEGIN(CCCCna);
+	  }
+	}
+
+^MJD-AVG" " |
+^MJDA	{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.mjdavg);
+	
+	  if (yyleng == 8) {
+	    extkey = "MJD-AVG";
+	    BEGIN(CCCCCCCC);
+	  } else {
+	    BEGIN(CCCCn);
+	  }
+	}
+
+^MJD-OBS" " |
+^MJDOB	{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.mjdobs);
+	
+	  if (yyleng == 8) {
+	    extkey = "MJD-OBS";
+	    BEGIN(CCCCCCCC);
+	  } else {
+	    BEGIN(CCCCCn);
+	  }
+	}
+
+^OBSGEO-X |
+^OBSGX	{
+	  valtype = FLOAT;
+	  vptr = wcstem.obsgeo;
+	
+	  if (yyleng == 8) {
+	    extkey = "OBSGEO-X";
+	    BEGIN(CCCCCCCC);
+	  } else {
+	    BEGIN(CCCCCn);
+	  }
+	}
+
+^OBSGEO-Y |
+^OBSGY	{
+	  valtype = FLOAT;
+	  vptr = wcstem.obsgeo + 1;
+	
+	  if (yyleng == 8) {
+	    extkey = "OBSGEO-Y";
+	    BEGIN(CCCCCCCC);
+	  } else {
+	    BEGIN(CCCCCn);
+	  }
+	}
+
+^OBSGEO-Z |
+^OBSGZ	{
+	  valtype = FLOAT;
+	  vptr = wcstem.obsgeo + 2;
+	
+	  if (yyleng == 8) {
+	    extkey = "OBSGEO-Z";
+	    BEGIN(CCCCCCCC);
+	  } else {
+	    BEGIN(CCCCCn);
+	  }
+	}
+
+^RADESYS |
+^RADE	{
+	  valtype = STRING;
+	  vptr = wcstem.radesys;
+	
+	  if (yyleng == 7) {
+	    extkey = "RADESYSa";
+	    BEGIN(CCCCCCCa);
+	  } else {
+	    BEGIN(CCCCna);
+	  }
+	}
+
+^RADECSYS {
+	  if (relax & WCSHDR_RADECSYS) {
+	    valtype = STRING;
+	    vptr = wcstem.radesys;
+	
+	    unput(' ');
+	    extkey = "RADECSYS";
+	    BEGIN(CCCCCCCa);
+	
+	  } else {
+	    keytype = IMGAUX;
+	    if (relax & WCSHDR_reject) {
+	      errmsg = "RADECSYS keyword is non-standard";
+	      BEGIN(ERROR);
+	    } else {
+	      BEGIN(DISCARD);
+	    }
+	  }
+	}
+
+^SPECSYS |
+^SPEC	{
+	  valtype = STRING;
+	  vptr = wcstem.specsys;
+	
+	  if (yyleng == 7) {
+	    extkey = "SPECSYSa";
+	    BEGIN(CCCCCCCa);
+	  } else {
+	    BEGIN(CCCCna);
+	  }
+	}
+
+^SSYSOBS |
+^SOBS	{
+	  valtype = STRING;
+	  vptr = wcstem.ssysobs;
+	
+	  if (yyleng == 7) {
+	    extkey = "SSYSOBSa";
+	    BEGIN(CCCCCCCa);
+	  } else {
+	    BEGIN(CCCCna);
+	  }
+	}
+
+^SSYSSRC |
+^SSRC	{
+	  valtype = STRING;
+	  vptr = wcstem.ssyssrc;
+	
+	  if (yyleng == 7) {
+	    extkey = "SSYSSRCa";
+	    BEGIN(CCCCCCCa);
+	  } else {
+	    BEGIN(CCCCna);
+	  }
+	}
+
+^VELOSYS |
+^VSYS	{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.velosys);
+	
+	  if (yyleng == 7) {
+	    extkey = "VELOSYSa";
+	    BEGIN(CCCCCCCa);
+	  } else {
+	    BEGIN(CCCCna);
+	  }
+	}
+
+^VELANGL |
+^VANG	{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.velangl);
+	
+	  if (yyleng == 7) {
+	    extkey = "VELANGLa";
+	    BEGIN(CCCCCCCa);
+	  } else {
+	    BEGIN(CCCCna);
+	  }
+	}
+
+^VELREF{ALT}" " {
+	  sscanf(yytext, "VELREF%c", &a);
+	
+	  if (a == ' ' || (relax & WCSHDR_VELREFa)) {
+	    valtype = INTEGER;
+	    vptr = &(wcstem.velref);
+	
+	    unput(a);
+	    extkey = "VELREF";
+	    BEGIN(CCCCCCCa);
+	
+	  } else {
+	    keytype = IMGAUX;
+	    if (relax & WCSHDR_reject) {
+	      errmsg = "VELREF keyword may not have an alternate version code";
+	      BEGIN(ERROR);
+	    } else {
+	      BEGIN(DISCARD);
+	    }
+	  }
+	}
+
+^VSOURCE{ALT} {
+	  if (relax & WCSHDR_VSOURCE) {
+	    valtype = FLOAT;
+	    vptr = &(wcstem.zsource);
+	    special = wcsbth_vsource;
+	
+	    yyless(7);
+	    extkey = "VSOURCEa";
+	    BEGIN(CCCCCCCa);
+	
+	  } else {
+	    keytype = IMGAUX;
+	    if (relax & WCSHDR_reject) {
+	      errmsg = "VSOURCEa keyword is deprecated";
+	      BEGIN(ERROR);
+	    } else {
+	      BEGIN(DISCARD);
+	    }
+	  }
+	}
+
+^VSOU{I1}{ALT}"  " |
+^VSOU{I2}{ALT}" "  |
+^VSOU{I3}{ALT} {
+	  if (relax & WCSHDR_VSOURCE) {
+	    valtype = FLOAT;
+	    vptr = &(wcstem.zsource);
+	    special = wcsbth_vsource;
+	
+	    yyless(4);
+	    BEGIN(CCCCna);
+	
+	  } else {
+	    keytype = BINTAB;
+	    if (relax & WCSHDR_reject) {
+	      errmsg = "VSOUna keyword is deprecated";
+	      BEGIN(ERROR);
+	    } else {
+	      /* Pretend we don't recognize it. */
+	      BEGIN(DISCARD);
+	    }
+	  }
+	}
+
+^WCSNAME |
+^WCSN	 |
+^TWCS	{
+	  valtype = STRING;
+	  vptr = wcstem.wcsname;
+	
+	  if (yyleng == 7) {
+	    extkey = "WCSNAMEa";
+	    BEGIN(CCCCCCCa);
+	  } else {
+	    BEGIN(CCCCna);
+	  }
+	}
+
+^ZSOURCE |
+^ZSOU	{
+	  valtype = FLOAT;
+	  vptr = &(wcstem.zsource);
+	
+	  if (yyleng == 7) {
+	    extkey = "ZSOURCEa";
+	    BEGIN(CCCCCCCa);
+	  } else {
+	    BEGIN(CCCCna);
+	  }
+	}
+
+^END" "{77} {
+	  yyless(0);
+	  if (wcsbth_nkeyrec) {
+	    wcsbth_nkeyrec = 0;
+	    errmsg = "Keyrecords following the END keyrecord were ignored";
+	    BEGIN(ERROR);
+	  } else {
+	    BEGIN(DISCARD);
+	  }
+	}
+
+^.	{
+	  yyless(0);
+	  BEGIN(DISCARD);
+	}
+
+<CCCCCia>{I1}{ALT}" " |
+<CCCCCia>{I2}{ALT} {
+	  /* Image-header keyword. */
+	  keytype = IMGAXIS;
+	  if (relax & WCSHDR_ALLIMG) {
+	    sscanf(yytext, "%d%c", &i, &a);
+	    BEGIN(VALUE);
+	
+	  } else if (relax & WCSHDR_reject) {
+	    errmsg = errtxt;
+	    sprintf(errmsg,
+	      "Image-header keyword %s in binary table", extkey);
+	    BEGIN(ERROR);
+	
+	  } else {
+	    /* Pretend we don't recognize it. */
+	    BEGIN(DISCARD);
+	  }
+	}
+
+<CCCCCia>{I3} {
+	  /* Invalid axis number in image-header keyword. */
+	  keytype = IMGAXIS;
+	  if (relax & WCSHDR_ALLIMG) {
+	    /* Will also be flagged by <VALUE> as invalid. */
+	    sscanf(yytext, "%3d", &i);
+	    BEGIN(VALUE);
+	
+	  } else {
+	    /* Pretend we don't recognize it. */
+	    BEGIN(DISCARD);
+	  }
+	}
+
+<iCCCCn>{I1}"  " |
+<iCCCCn>{I2}" "  |
+<iCCCCn>{I3}     |
+<TCCCCn>{I1}"  " |
+<TCCCCn>{I2}" "  |
+<TCCCCn>{I3} {
+	  if (vptr) {
+	    WCSBTH_PUTBACK;
+	    BEGIN((YY_START == iCCCCn) ? iCCCna : TCCCna);
+	  } else {
+	    keytype = (YY_START == iCCCCn) ? BIMGARR : PIXLIST;
+	    if (relax & WCSHDR_reject) {
+	      errmsg = errtxt;
+	      sprintf(errmsg, "%s keyword is non-standard", extkey);
+	      BEGIN(ERROR);
+	    } else {
+	      BEGIN(DISCARD);
+	    }
+	  }
+	}
+
+<iCCCCn>{I1}[A-Z]" " |
+<iCCCCn>{I2}[A-Z]    |
+<TCCCCn>{I1}[A-Z]" " |
+<TCCCCn>{I2}[A-Z] {
+	  if (vptr && (relax & WCSHDR_LONGKEY)) {
+	    WCSBTH_PUTBACK;
+	    BEGIN((YY_START == iCCCCn) ? iCCCna : TCCCna);
+	
+	  } else {
+	    keytype = (YY_START == iCCCna) ? BIMGARR : PIXLIST;
+	    if (relax & WCSHDR_reject) {
+	      errmsg = errtxt;
+	      if (!vptr) {
+	        sprintf(errmsg, "%s keyword is non-standard", extkey);
+	      } else {
+	        sprintf(errmsg,
+	          "%s keyword may not have an alternate version code", extkey);
+	      }
+	      BEGIN(ERROR);
+	
+	    } else {
+	      /* Pretend we don't recognize it. */
+	      BEGIN(DISCARD);
+	    }
+	  }
+	}
+
+<iCCCCn>. |
+<TCCCCn>. {
+	  BEGIN(DISCARD);
+	}
+
+<iCCCna>{I1}{ALT}"  " |
+<iCCCna>{I2}{ALT}" "  |
+<iCCCna>{I3}{ALT}     |
+<TCCCna>{I1}{ALT}"  " |
+<TCCCna>{I2}{ALT}" "  |
+<TCCCna>{I3}{ALT} {
+	  sscanf(yytext, "%d%c", &n, &a);
+	  if (YY_START == TCCCna) i = wcsbth_colax(*wcs, &alts, n, a);
+	  keytype = (YY_START == iCCCna) ? BIMGARR : PIXLIST;
+	  BEGIN(VALUE);
+	}
+
+<iCCCna>. |
+<TCCCna>. {
+	  BEGIN(DISCARD);
+	}
+
+<CCi_ja>{I1}_{I1}{ALT}"  " |
+<CCi_ja>{I1}_{I2}{ALT}" " |
+<CCi_ja>{I2}_{I1}{ALT}" " |
+<CCi_ja>{I2}_{I2}{ALT} {
+	  /* Image-header keyword. */
+	  if (relax & WCSHDR_ALLIMG) {
+	    sscanf(yytext, "%d_%d%c", &i, &j, &a);
+	    keytype = IMGAXIS;
+	    BEGIN(VALUE);
+	
+	  } else if (relax & WCSHDR_reject) {
+	    errmsg = errtxt;
+	    sprintf(errmsg,
+	      "Image-header keyword %s in binary table", extkey);
+	    BEGIN(ERROR);
+	
+	  } else {
+	    /* Pretend we don't recognize it. */
+	    BEGIN(DISCARD);
+	  }
+	}
+
+<CCi_ja>{I1}_{I3}{ALT} |
+<CCi_ja>{I3}_{I1}{ALT} |
+<CCi_ja>{I1}_{I4} |
+<CCi_ja>{I2}_{I3} |
+<CCi_ja>{I3}_{I2} |
+<CCi_ja>{I4}_{I1} {
+	  /* Invalid axis number in image-header keyword. */
+	  if (relax & WCSHDR_ALLIMG) {
+	    /* Will be flagged by <VALUE> as invalid. */
+	    sscanf(yytext, "%d_%d", &i, &j);
+	    keytype = IMGAXIS;
+	    BEGIN(VALUE);
+	
+	  } else {
+	    /* Pretend we don't recognize it. */
+	    BEGIN(DISCARD);
+	  }
+	}
+
+<CCi_ja>{I0}{6} {
+	  /* This covers the defunct forms CD00i00j and PC00i00j. */
+	  if (((relax & WCSHDR_PC00i00j) && (altlin == 1)) ||
+	      ((relax & WCSHDR_CD00i00j) && (altlin == 2))) {
+	    sscanf(yytext, "%3d%3d", &i, &j);
+	    a = ' ';
+	    keytype = IMGAXIS;
+	    BEGIN(VALUE);
+	
+	  } else if (relax & WCSHDR_reject) {
+	    errmsg = errtxt;
+	    sprintf(errmsg, "Defunct form of %si_ja keyword",
+	                     (altlin==1) ? "PC" : "CD");
+	    BEGIN(ERROR);
+	
+	  } else {
+	    /* Pretend we don't recognize it. */
+	    BEGIN(DISCARD);
+	  }
+	}
+
+<CCi_ja>. {
+	  BEGIN(DISCARD);
+	}
+
+<ijCCna>{I1}{ALT}"  " |
+<ijCCna>{I2}{ALT}" "  |
+<ijCCna>{I3}{ALT} {
+	  sscanf(yytext, "%d%c", &n, &a);
+	  keytype = BIMGARR;
+	  BEGIN(VALUE);
+	}
+
+<TCCn_ka>{I1}_{I1}{ALT}" " |
+<TCCn_ka>{I1}_{I2}{ALT} |
+<TCCn_ka>{I2}_{I1}{ALT} |
+<TCCn_ka>{I1}_{I3} |
+<TCCn_ka>{I2}_{I2} |
+<TCCn_ka>{I3}_{I1} {
+	  if (relax & WCSHDR_LONGKEY) {
+	    WCSBTH_PUTBACK;
+	    BEGIN(TCn_ka);
+	
+	  } else if (relax & WCSHDR_reject) {
+	    errmsg = errtxt;
+	    sprintf(errmsg, "%s keyword is non-standard", extkey);
+	    BEGIN(ERROR);
+	
+	  } else {
+	    /* Pretend we don't recognize it. */
+	    BEGIN(DISCARD);
+	  }
+	}
+
+<TCCn_ka>. {
+	  BEGIN(DISCARD);
+	}
+
+<TCn_ka>{I1}_{I1}{ALT}"  " |
+<TCn_ka>{I1}_{I2}{ALT}" " |
+<TCn_ka>{I2}_{I1}{ALT}" " |
+<TCn_ka>{I1}_{I3}{ALT} |
+<TCn_ka>{I2}_{I2}{ALT} |
+<TCn_ka>{I3}_{I1}{ALT} {
+	  sscanf(yytext, "%d_%d%c", &n, &k, &a);
+	  i = wcsbth_colax(*wcs, &alts, n, a);
+	  j = wcsbth_colax(*wcs, &alts, k, a);
+	  keytype = PIXLIST;
+	  BEGIN(VALUE);
+	}
+
+<TCn_ka>{I1}_{I4} |
+<TCn_ka>{I2}_{I3} |
+<TCn_ka>{I3}_{I2} |
+<TCn_ka>{I4}_{I1} {
+	  sscanf(yytext, "%d_%d", &n, &k);
+	  a = ' ';
+	  i = wcsbth_colax(*wcs, &alts, n, a);
+	  j = wcsbth_colax(*wcs, &alts, k, a);
+	  keytype = PIXLIST;
+	  BEGIN(VALUE);
+	}
+
+<TCn_ka>. {
+	  BEGIN(DISCARD);
+	}
+
+<CROTAi>{I1}"  " |
+<CROTAi>{I2}" " {
+	  yyless(0);
+	  BEGIN(CCCCCia);
+	}
+
+<CROTAi>{I1}[A-Z]" " |
+<CROTAi>{I2}[A-Z] {
+	  if (relax & WCSHDR_CROTAia) {
+	    yyless(0);
+	    BEGIN(CCCCCia);
+	
+	  } else if (relax & WCSHDR_reject) {
+	    errmsg = "CROTAn keyword may not have an alternate version code";
+	    BEGIN(ERROR);
+	
+	  } else {
+	    /* Pretend we don't recognize it. */
+	    BEGIN(DISCARD);
+	  }
+	}
+
+<CROTAi>. {
+	  BEGIN(DISCARD);
+	}
+
+<iCROTn>{I1}"  " |
+<iCROTn>{I2}" "  |
+<iCROTn>{I3}     |
+<TCROTn>{I1}"  " |
+<TCROTn>{I2}" "  |
+<TCROTn>{I3} {
+	  WCSBTH_PUTBACK;
+	  BEGIN((YY_START == iCROTn) ? iCCCna : TCCCna);
+	}
+
+<iCROTn>{I1}[A-Z]" " |
+<iCROTn>{I2}[A-Z]    |
+<TCROTn>{I1}[A-Z]" " |
+<TCROTn>{I2}[A-Z] {
+	  if (relax & WCSHDR_CROTAia) {
+	    WCSBTH_PUTBACK;
+	    BEGIN((YY_START == iCROTn) ? iCCCna : TCCCna);
+	
+	  } else if (relax & WCSHDR_reject) {
+	    errmsg = errtxt;
+	    sprintf(errmsg,
+	      "%s keyword may not have an alternate version code", extkey);
+	    BEGIN(ERROR);
+	
+	  } else {
+	    /* Pretend we don't recognize it. */
+	    BEGIN(DISCARD);
+	  }
+	}
+
+<iCROTn>. |
+<TCROTn>. {
+	  BEGIN(DISCARD);
+	}
+
+<CCCCCCCa>{ALT} |
+<CCCCCCCC>. {
+	  /* Image-header keyword. */
+	  if (relax & (WCSHDR_AUXIMG | WCSHDR_ALLIMG)) {
+	    if (YY_START == CCCCCCCa) {
+	      sscanf(yytext, "%c", &a);
+	    } else {
+	      a = 0;
+	      unput(yytext[0]);
+	    }
+	    keytype = IMGAUX;
+	    BEGIN(VALUE);
+	
+	  } else if (relax & WCSHDR_reject) {
+	    errmsg = errtxt;
+	    sprintf(errmsg,
+	      "Image-header keyword %s in binary table", extkey);
+	    BEGIN(ERROR);
+	
+	  } else {
+	    /* Pretend we don't recognize it. */
+	    BEGIN(DISCARD);
+	  }
+	}
+
+<CCCCCCCa>. {
+	  BEGIN(DISCARD);
+	}
+
+<CCCCna>{I1}{ALT}"  " |
+<CCCCna>{I2}{ALT}" "  |
+<CCCCna>{I3}{ALT}     |
+<CCCCCna>{I1}{ALT}" " |
+<CCCCCna>{I2}{ALT} {
+	  sscanf(yytext, "%d%c", &n, &a);
+	  keytype = BINTAB;
+	  BEGIN(VALUE);
+	}
+
+<CCCCCna>{I3} {
+	  sscanf(yytext, "%d", &n);
+	  a = ' ';
+	  keytype = BINTAB;
+	  BEGIN(VALUE);
+	}
+
+<CCCCna>. |
+<CCCCCna>. {
+	  BEGIN(DISCARD);
+	}
+
+<CCCCn>{I1}"   " |
+<CCCCn>{I2}"  "  |
+<CCCCn>{I3}" "   |
+<CCCCn>{I4}      |
+<CCCCCn>{I1}"  " |
+<CCCCCn>{I2}" "  |
+<CCCCCn>{I3} {
+	  sscanf(yytext, "%d", &n);
+	  a = 0;
+	  keytype = BINTAB;
+	  BEGIN(VALUE);
+	}
+
+<CCCCn>. |
+<CCCCCn>. {
+	  BEGIN(DISCARD);
+	}
+
+<CCi_ma>{I1}_{I0}{ALT}"  " |
+<CCi_ma>{I1}_{I2}{ALT}" " |
+<CCi_ma>{I2}_{I0}{ALT}" " |
+<CCi_ma>{I2}_{I2}{ALT} {
+	  /* Image-header keyword. */
+	  if (relax & WCSHDR_ALLIMG) {
+	    sscanf(yytext, "%d_%d%c", &i, &m, &a);
+	    keytype = IMGAXIS;
+	    BEGIN(VALUE);
+	
+	  } else if (relax & WCSHDR_reject) {
+	    errmsg = errtxt;
+	    sprintf(errmsg,
+	      "Image-header keyword %s in binary table", extkey);
+	    BEGIN(ERROR);
+	
+	  } else {
+	    /* Pretend we don't recognize it. */
+	    BEGIN(DISCARD);
+	  }
+	}
+
+<CCi_ma>{I1}_{I3}{ALT} |
+<CCi_ma>{I3}_{I0}{ALT} |
+<CCi_ma>{I1}_{I4} |
+<CCi_ma>{I2}_{I3} |
+<CCi_ma>{I3}_{I2} |
+<CCi_ma>{I4}_{I0} {
+	  /* Invalid parameter in image-header keyword. */
+	  if (relax & WCSHDR_ALLIMG) {
+	    /* Will be flagged by <VALUE> as invalid. */
+	    sscanf(yytext, "%d_%d", &i, &m);
+	    keytype = IMGAXIS;
+	    BEGIN(VALUE);
+	
+	  } else {
+	    /* Pretend we don't recognize it. */
+	    BEGIN(DISCARD);
+	  }
+	}
+
+<CCi_ma>. {
+	  BEGIN(DISCARD);
+	}
+
+<iCCn_ma>{I1}_{I0}{ALT}" " |
+<iCCn_ma>{I1}_{I2}{ALT}    |
+<iCCn_ma>{I1}_{I3}         |
+<iCCn_ma>{I2}_{I0}{ALT}    |
+<iCCn_ma>{I2}_{I2}         |
+<iCCn_ma>{I3}_{I0}         |
+<TCCn_ma>{I1}_{I0}{ALT}" " |
+<TCCn_ma>{I1}_{I2}{ALT}    |
+<TCCn_ma>{I1}_{I3}         |
+<TCCn_ma>{I2}_{I0}{ALT}    |
+<TCCn_ma>{I2}_{I2}         |
+<TCCn_ma>{I3}_{I0} {
+	  if (relax & WCSHDR_LONGKEY) {
+	    WCSBTH_PUTBACK;
+	    BEGIN((YY_START == iCCn_ma) ? iCn_ma : TCn_ma);
+	
+	  } else if (relax & WCSHDR_reject) {
+	    errmsg = errtxt;
+	    sprintf(errmsg, "%s keyword is non-standard", extkey);
+	    BEGIN(ERROR);
+	
+	  } else {
+	    /* Pretend we don't recognize it. */
+	    BEGIN(DISCARD);
+	  }
+	}
+
+<iCCn_ma>. |
+<TCCn_ma>. {
+	  BEGIN(DISCARD);
+	}
+
+<iCn_ma>{I1}_{I0}{ALT}"  " |
+<iCn_ma>{I1}_{I2}{ALT}" "  |
+<iCn_ma>{I1}_{I3}{ALT}     |
+<iCn_ma>{I2}_{I0}{ALT}" "  |
+<iCn_ma>{I2}_{I2}{ALT}     |
+<iCn_ma>{I3}_{I0}{ALT}     |
+<TCn_ma>{I1}_{I0}{ALT}"  " |
+<TCn_ma>{I1}_{I2}{ALT}" "  |
+<TCn_ma>{I1}_{I3}{ALT}     |
+<TCn_ma>{I2}_{I0}{ALT}" "  |
+<TCn_ma>{I2}_{I2}{ALT}     |
+<TCn_ma>{I3}_{I0}{ALT} {
+	  sscanf(yytext, "%d_%d%c", &n, &m, &a);
+	  if (YY_START == TCn_ma) i = wcsbth_colax(*wcs, &alts, n, a);
+	  keytype = (YY_START == iCn_ma) ? BIMGARR : PIXLIST;
+	  BEGIN(VALUE);
+	}
+
+<iCn_ma>{I1}_{I4} |
+<iCn_ma>{I2}_{I3} |
+<iCn_ma>{I3}_{I2} |
+<iCn_ma>{I4}_{I0} |
+<TCn_ma>{I1}_{I4} |
+<TCn_ma>{I2}_{I3} |
+<TCn_ma>{I3}_{I2} |
+<TCn_ma>{I4}_{I0} {
+	  /* Invalid combinations will be flagged by <VALUE>. */
+	  sscanf(yytext, "%d_%d", &n, &m);
+	  a = ' ';
+	  if (YY_START == TCn_ma) i = wcsbth_colax(*wcs, &alts, n, a);
+	  keytype = (YY_START == iCn_ma) ? BIMGARR : PIXLIST;
+	  BEGIN(VALUE);
+	}
+
+<iCn_ma>. |
+<TCn_ma>. {
+	  BEGIN(DISCARD);
+	}
+
+<PROJPm>{I0}"  " {
+	  if (relax & WCSHDR_PROJPn) {
+	    sscanf(yytext, "%d", &m);
+	    i = 0;
+	    a = ' ';
+	    keytype = IMGAXIS;
+	    BEGIN(VALUE);
+	
+	  } else if (relax & WCSHDR_reject) {
+	    errmsg = "PROJPn keyword is defunct";
+	    BEGIN(ERROR);
+	
+	  } else {
+	    /* Pretend we don't recognize it. */
+	    BEGIN(DISCARD);
+	  }
+	}
+
+<PROJPm>. {
+	  BEGIN(DISCARD);
+	}
+
+<VALUE>=" "+ {
+	  /* Do checks on i, j, m, n, k. */
+	  if (!(keytype & keysel)) {
+	    /* Selection by keyword type. */
+	    BEGIN(DISCARD);
+	
+	  } else if (exclude[n] || exclude[k]) {
+	    /* One or other column is not selected. */
+	    if (k && (exclude[n] != exclude[k])) {
+	      /* For keywords such as TCn_ka, both columns must be excluded.
+	         User error, so return immediately. */
+	      yylex_destroy();
+	      return 3;
+	
+	    } else {
+	      BEGIN(DISCARD);
+	    }
+	
+	  } else if (i > 99 || j > 99 || m > 99 || n > 999 || k > 999) {
+	    if (relax & WCSHDR_reject) {
+	      errmsg = errtxt;
+	      if (i > 99 || j > 99) {
+	        sprintf(errmsg, "Axis number exceeds 99");
+	      } else if (m > 99) {
+	        sprintf(errmsg, "Parameter number exceeds 99");
+	      } else if (n > 999 || k > 999) {
+	        sprintf(errmsg, "Column number exceeds 999");
+	      }
+	      BEGIN(ERROR);
+	
+	    } else {
+	      /* Pretend we don't recognize it. */
+	      BEGIN(DISCARD);
+	    }
+	
+	  } else if (ipass == 2 && npass == 3 && (keytype & BINTAB)) {
+	    /* Skip keyvalues that won't be inherited. */
+	    BEGIN(FLUSH);
+	
+	  } else if (ipass == 3 && (keytype & IMGHEAD)) {
+	    /* IMGHEAD keytypes are always dealt with on the second pass. */
+	    BEGIN(FLUSH);
+	
+	  } else if (vptr) {
+	    alts.icol = 0;
+	    alts.ialt = 0;
+	    voff = (char *)vptr - (char *)(&wcstem);
+	
+	    if (valtype == INTEGER) {
+	      BEGIN(INTEGER_VAL);
+	    } else if (valtype == FLOAT) {
+	      BEGIN(FLOAT_VAL);
+	    } else if (valtype == STRING) {
+	      BEGIN(STRING_VAL);
+	    } else {
+	      errmsg = errtxt;
+	      sprintf(errmsg, "Internal parser ERROR, bad data type: %d",
+	        valtype);
+	      BEGIN(ERROR);
+	    }
+	
+	  } else {
+	    errmsg = "Internal parser ERROR, null pointer";
+	    BEGIN(ERROR);
+	  }
+	}
+
+<VALUE>. {
+	  errmsg = "Invalid KEYWORD = VALUE syntax";
+	  BEGIN(ERROR);
+	}
+
+<INTEGER_VAL>{INTEGER} {
+	  if (ipass == 1) {
+	    /* Do first-pass bookkeeping. */
+	    wcsbth_pass1(keytype, i, j, n, k, a, ptype, &alts);
+	    BEGIN(FLUSH);
+	
+	  } else {
+	    /* Update each coordinate representation. */
+	    while ((wcsp = wcsbth_idx(*wcs, &alts, keytype, n, a))) {
+	      wptr = (void *)((char *)wcsp + voff);
+	
+	      /* Read the keyvalue. */
+	      if (special) {
+	        special(wptr);
+	      } else {
+	        sscanf(yytext, "%d", (int *)wptr);
+	      }
+	    }
+	
+	    BEGIN(COMMENT);
+	  }
+	}
+
+<INTEGER_VAL>. {
+	  errmsg = "An integer value was expected";
+	  BEGIN(ERROR);
+	}
+
+<FLOAT_VAL>{FLOAT} {
+	  if (ipass == 1) {
+	    /* Do first-pass bookkeeping. */
+	    wcsbth_pass1(keytype, i, j, n, k, a, ptype, &alts);
+	    BEGIN(FLUSH);
+	
+	  } else {
+	    /* Update each coordinate representation. */
+	    while ((wcsp = wcsbth_idx(*wcs, &alts, keytype, n, a))) {
+	      wptr = (void *)((char *)wcsp + voff);
+	
+	      /* Apply keyword parameterization. */
+	      if (ptype == 'v') {
+	        ipx = wcsp->npv++;
+	        wcsp->pv[ipx].i = i;
+	        wcsp->pv[ipx].m = m;
+	        wptr = &(wcsp->pv[ipx].value);
+	
+	      } else if (j) {
+	        /* Is the de-reference necessary? */
+	        wptr = *((double **)wptr) + (i - 1)*(wcsp->naxis) + (j - 1);
+	
+	      } else if (i) {
+	        wptr = *((double **)wptr) + (i - 1);
+	      }
+	
+	      /* Read the keyvalue. */
+	      if (special) {
+	        special(wptr);
+	      } else {
+	        wcsutil_str2double(yytext, "%lf", (double *)wptr);
+	      }
+	
+	      /* Flag the presence of PC, or CD and/or CROTA. */
+	      if (altlin) {
+	        wcsp->altlin |= altlin;
+	        altlin = 0;
+	      }
+	    }
+	
+	    BEGIN(COMMENT);
+	  }
+	}
+
+<FLOAT_VAL>. {
+	  errmsg = "A floating-point value was expected";
+	  BEGIN(ERROR);
+	}
+
+<STRING_VAL>{STRING} {
+	  if (ipass == 1) {
+	    /* Do first-pass bookkeeping. */
+	    wcsbth_pass1(keytype, i, j, n, k, a, ptype, &alts);
+	    BEGIN(FLUSH);
+	
+	  } else {
+	    /* Update each coordinate representation. */
+	    while ((wcsp = wcsbth_idx(*wcs, &alts, keytype, n, a))) {
+	      wptr = (void *)((char *)wcsp + voff);
+	
+	      /* Apply keyword parameterization. */
+	      if (ptype == 's') {
+	        ipx = wcsp->nps++;
+	        wcsp->ps[ipx].i = i;
+	        wcsp->ps[ipx].m = m;
+	        wptr = wcsp->ps[ipx].value;
+	
+	      } else if (j) {
+	        wptr = *((char (**)[72])wptr) +
+	                (i - 1)*(wcsp->naxis) + (j - 1);
+	
+	      } else if (i) {
+	        wptr = *((char (**)[72])wptr) + (i - 1);
+	      }
+	
+	      /* Read the keyvalue. */
+	      cptr = (char *)wptr;
+	      strcpy(cptr, yytext+1);
+	
+	      /* Squeeze out repeated quotes. */
+	      ix = 0;
+	      for (jx = 0; jx < 72; jx++) {
+	        if (ix < jx) {
+	          cptr[ix] = cptr[jx];
+	        }
+	
+	        if (cptr[jx] == '\0') {
+	          if (ix) cptr[ix-1] = '\0';
+	          break;
+	        } else if (cptr[jx] == '\'' && cptr[jx+1] == '\'') {
+	          jx++;
+	        }
+	
+	        ix++;
+	      }
+	    }
+	
+	    BEGIN(COMMENT);
+	  }
+	}
+
+<STRING_VAL>. {
+	  errmsg = "A string value was expected";
+	  BEGIN(ERROR);
+	}
+
+<COMMENT>" "*\/.* |
+<COMMENT>" "* {
+	  BEGIN(FLUSH);
+	}
+
+<COMMENT>. {
+	  errmsg = "Malformed keycomment";
+	  BEGIN(ERROR);
+	}
+
+<DISCARD>.* {
+	  if (ipass == npass) {
+	    if (ctrl < 0) {
+	      /* Preserve discards. */
+	      if (hptr < wcsbth_hdr-80) {
+	        strncpy(hptr, wcsbth_hdr-80, 80);
+	      }
+	      hptr += 80;
+	
+	    } else if (ctrl > 2) {
+	      fprintf(stderr, "%.80s\n  Discarded.\n", wcsbth_hdr-80);
+	    }
+	  }
+	
+	  BEGIN(FLUSH);
+	}
+
+<ERROR>.* {
+	  (*nreject)++;
+	  if (ipass == npass) {
+	    if (ctrl == -1) {
+	      if (hptr < wcsbth_hdr-80) {
+	        /* Preserve rejects. */
+	        strncpy(hptr, wcsbth_hdr-80, 80);
+	      }
+	      hptr += 80;
+	    }
+	
+	    if (abs(ctrl) > 1) {
+	      fprintf(stderr, "%.80s\n%4d: %s.\n", wcsbth_hdr-80, *nreject,
+	        errmsg);
+	    }
+	  }
+	
+	  BEGIN(FLUSH);
+	}
+
+<FLUSH>.*\n {
+	  /* Throw away the rest of the line and reset for the next one. */
+	  i = j = 0;
+	  n = k = 0;
+	  m = 0;
+	  a = ' ';
+	
+	  keytype =  0;
+	  valtype = -1;
+	  vptr    = 0x0;
+	
+	  altlin = 0;
+	  ptype  = ' ';
+	  special = 0x0;
+	  BEGIN(INITIAL);
+	}
+
+<<EOF>>	 {
+	  /* End-of-input. */
+	  if (ipass == 1) {
+	    if ((status = wcsbth_init1(&alts, nwcs, wcs)) || *nwcs == 0) {
+	      yylex_destroy();
+	      return status;
+	    }
+
+	    if (alts.imgherit) npass = 3;
+	
+	    if (abs(ctrl) > 2) {
+	      if (*nwcs == 1) {
+	        fprintf(stderr, "Found one coordinate representation.\n");
+	      } else {
+	        fprintf(stderr, "Found %d coordinate representations.\n",
+	          *nwcs);
+	      }
+	    }
+	  }
+	
+	  if (ipass++ < npass) {
+	    wcsbth_hdr = header;
+	    wcsbth_nkeyrec = nkeyrec;
+	    *nreject = 0;
+	
+	    i = j = 0;
+	    k = n = 0;
+	    m = 0;
+	    a = ' ';
+	
+	    keytype =  0;
+	    valtype = -1;
+	    vptr    = 0x0;
+	
+	    altlin = 0;
+	    ptype  = ' ';
+	    special = 0x0;
+	
+	    yyrestart(yyin);
+	
+	  } else {
+	    yylex_destroy();
+	
+	    if (ctrl < 0) {
+	      *hptr = '\0';
+	    } else if (ctrl == 1) {
+	      fprintf(stderr, "%d WCS keyrecords were rejected.\n", *nreject);
+	    }
+	
+	    return wcsbth_final(&alts, nwcs, wcs);
+	  }
+	}
+
+%%
+
+/*----------------------------------------------------------------------------
+* Perform first-pass tasks:
+*
+* 1) Count the number of coordinate axes in each of the 27 possible alternate
+*    image-header coordinate representations.  Also count the number of PVi_ma
+*    and PSi_ma keywords in each representation.
+*
+* 2) Determine the number of binary table columns that have an image array
+*    with a coordinate representation (up to 999), and count the number of
+*    coordinate axes in each of the 27 possible alternates.  Also count the
+*    number of iVn_ma and iSn_ma keywords in each representation.
+*
+* 3) Determine the number of alternate pixel list coordinate representations
+*    (up to 27) and the table columns associated with each.  Also count the
+*    number of TVn_ma and TSn_ma keywords in each representation.
+*
+* In the first pass alts->arridx[icol][27] is used to determine the number of
+* axes in each of 27 possible image-header coordinate descriptions (icol == 0)
+* and each of the 27 possible coordinate representations for an image array in
+* each column.
+*
+* The elements of alts->pixlist[icol] are used as bit arrays to flag which of
+* the 27 possible pixel list coordinate representations are associated with
+* each table column.
+*---------------------------------------------------------------------------*/
+
+int wcsbth_pass1(
+  int keytype,
+  int i,
+  int j,
+  int n,
+  int k,
+  char a,
+  char ptype,
+  struct wcsbth_alts *alts)
+
+{
+  int ialt, icol, mask, ncol;
+
+  if (a == 0) {
+    /* Keywords such as DATE-OBS go along for the ride. */
+    return 0;
+  }
+
+  ncol = alts->ncol;
+
+  /* Do we need to allocate memory for alts? */
+  if (alts->arridx == 0x0) {
+    if (ncol == 0) {
+      /* Can only happen if TFIELDS is missing or out-of-sequence.  If n and
+         k are both zero then we may be processing an image header so leave
+         ncol alone - the array will be realloc'd later if required. */
+      if (n || k) {
+        /* The header is mangled, assume the worst. */
+        ncol = 999;
+      }
+    }
+
+    if (!(alts->arridx  =  calloc((1 + ncol)*27, sizeof(short int))) ||
+        !(alts->npv     =  calloc((1 + ncol)*27, sizeof(unsigned char)))  ||
+        !(alts->nps     =  calloc((1 + ncol)*27, sizeof(unsigned char)))  ||
+        !(alts->pixlist =  calloc((1 + ncol),    sizeof(unsigned int)))) {
+      if (alts->arridx)  free(alts->arridx);
+      if (alts->npv)     free(alts->npv);
+      if (alts->nps)     free(alts->nps);
+      if (alts->pixlist) free(alts->pixlist);
+      return 2;
+    }
+
+    alts->ncol = ncol;
+
+  } else if (n > ncol || k > ncol) {
+    /* Can only happen if TFIELDS or the WCS keyword is wrong; carry on. */
+    ncol = 999;
+    if (!(alts->arridx  = realloc(alts->arridx,
+                                    27*(1 + ncol)*sizeof(short int))) ||
+        !(alts->npv     = realloc(alts->npv,
+                                    27*(1 + ncol)*sizeof(unsigned char)))  ||
+        !(alts->nps     = realloc(alts->nps,
+                                    27*(1 + ncol)*sizeof(unsigned char)))  ||
+        !(alts->pixlist = realloc(alts->pixlist,
+                                       (1 + ncol)*sizeof(unsigned int)))) {
+      if (alts->arridx)  free(alts->arridx);
+      if (alts->npv)     free(alts->npv);
+      if (alts->nps)     free(alts->nps);
+      if (alts->pixlist) free(alts->pixlist);
+      return 2;
+    }
+
+    /* Since realloc() doesn't initialize the extra memory. */
+    for (icol = (1 + alts->ncol); icol < (1 + ncol); icol++) {
+      for (ialt = 0; ialt < 27; ialt++) {
+        alts->arridx[icol][ialt] = 0;
+        alts->npv[icol][ialt] = 0;
+        alts->nps[icol][ialt] = 0;
+        alts->pixlist[icol]   = 0;
+      }
+    }
+
+    alts->ncol = ncol;
+  }
+
+  ialt = 0;
+  if (a != ' ') {
+    ialt = a - 'A' + 1;
+  }
+
+  /* A BINTAB keytype such as LONPna, in conjunction with an IMGAXIS keytype
+     causes a table column to be recognized as an image array. */
+  if (keytype & IMGHEAD || keytype & BIMGARR) {
+    /* n == 0 is expected for IMGHEAD keywords. */
+    if (i == 0 && j == 0) {
+      if (alts->arridx[n][ialt] == 0) {
+        /* Flag that an auxiliary keyword was seen. */
+        alts->arridx[n][ialt] = -1;
+      }
+
+    } else {
+      /* Record the maximum axis number found. */
+      if (alts->arridx[n][ialt] < i) {
+        alts->arridx[n][ialt] = i;
+      }
+
+      if (alts->arridx[n][ialt] < j) {
+        alts->arridx[n][ialt] = j;
+      }
+    }
+
+    if (ptype == 'v') {
+      alts->npv[n][ialt]++;
+    } else if (ptype == 's') {
+      alts->nps[n][ialt]++;
+    }
+  }
+
+  /* BINTAB keytypes, which apply both to pixel lists as well as binary table
+     image arrays, never contribute to recognizing a table column as a pixel
+     list axis.  A PIXLIST keytype is required for that. */
+  if (keytype == PIXLIST) {
+    mask = 1 << ialt;
+
+    /* n > 0 for PIXLIST keytypes. */
+    alts->pixlist[n] |= mask;
+    if (k) alts->pixlist[k] |= mask;
+
+    /* Used as a flag over all columns. */
+    alts->pixlist[0] |= mask;
+
+    if (ptype == 'v') {
+      alts->pixnpv[ialt]++;
+    } else if (ptype == 's') {
+      alts->pixnps[ialt]++;
+    }
+  }
+
+  return 0;
+}
+
+
+/*----------------------------------------------------------------------------
+* Perform initializations at the end of the first pass:
+*
+* 1) Determine the required number of wcsprm structs, allocate memory for
+*    an array of them and initialize each one.
+*---------------------------------------------------------------------------*/
+
+int wcsbth_init1(
+  struct wcsbth_alts *alts,
+  int *nwcs,
+  struct wcsprm **wcs)
+
+{
+  int ialt, icol, inherit[27], ix, mask, ncol, npsmax, npvmax, status = 0;
+  struct wcsprm *wcsp;
+
+
+  if (alts->arridx == 0x0) {
+    *nwcs = 0;
+    return 0;
+  }
+
+  /* Determine the number of axes in each pixel list representation. */
+  ncol = alts->ncol;
+  for (ialt = 0, mask = 1; ialt < 27; ialt++, mask <<= 1) {
+    alts->pixidx[ialt] = 0;
+
+    if (alts->pixlist[0] | mask) {
+      for (icol = 1; icol <= ncol; icol++) {
+        if (alts->pixlist[icol] & mask) {
+          alts->pixidx[ialt]++;
+        }
+      }
+    }
+  }
+
+  /* Find the total number of coordinate representations. */
+  *nwcs = 0;
+  alts->imgherit = 0;
+  for (ialt = 0; ialt < 27; ialt++) {
+    inherit[ialt] = 0;
+
+    for (icol = 1; icol <= ncol; icol++) {
+      if (alts->arridx[icol][ialt] < 0) {
+        /* No BIMGARR keytype but there's at least one BINTAB. */
+        if (alts->arridx[0][ialt] > 0) {
+          /* There is an IMGAXIS keytype that we will inherit, so count this
+             representation. */
+          alts->arridx[icol][ialt] = alts->arridx[0][ialt];
+        } else {
+          alts->arridx[icol][ialt] = 0;
+        }
+      }
+
+      if (alts->arridx[icol][ialt]) {
+        if (alts->arridx[0][ialt]) {
+          /* All IMGHEAD keywords are inherited for this ialt. */
+          inherit[ialt] = 1;
+
+          if (alts->arridx[icol][ialt] < alts->arridx[0][ialt]) {
+            /* The extra axes are also inherited. */
+            alts->arridx[icol][ialt] = alts->arridx[0][ialt];
+          }
+        }
+
+        (*nwcs)++;
+      }
+    }
+
+    /* Count every "a" found in any IMGHEAD keyword... */
+    if (alts->arridx[0][ialt]) {
+      if (inherit[ialt]) {
+        /* ...but not if the IMGHEAD keywords will be inherited. */
+        alts->arridx[0][ialt] = 0;
+        alts->imgherit = 1;
+      } else {
+        (*nwcs)++;
+      }
+    }
+
+    /* We need a struct for every "a" found in a PIXLIST keyword. */
+    if (alts->pixidx[ialt]) {
+      (*nwcs)++;
+    }
+  }
+
+
+  if (*nwcs) {
+    /* Allocate memory for the required number of wcsprm structs. */
+    if (!(*wcs = calloc(*nwcs, sizeof(struct wcsprm)))) {
+      return 2;
+    }
+
+    /* Record the current values of NPVMAX and NPSMAX. */
+    npvmax = wcsnpv(-1);
+    npsmax = wcsnps(-1);
+
+    /* Initialize each wcsprm struct. */
+    wcsp = *wcs;
+    *nwcs = 0;
+    for (icol = 0; icol <= ncol; icol++) {
+      for (ialt = 0; ialt < 27; ialt++) {
+        if (alts->arridx[icol][ialt]) {
+          /* Image-header representations that are not for inheritance
+             (icol == 0) or binary table image array representations. */
+          wcsp->flag = -1;
+          wcsnpv(alts->npv[icol][ialt]);
+          wcsnps(alts->nps[icol][ialt]);
+          if ((status = wcsini(1, (int)(alts->arridx[icol][ialt]), wcsp))) {
+            wcsvfree(nwcs, wcs);
+            break;
+          }
+
+          /* Record the alternate version code. */
+          if (ialt) {
+            wcsp->alt[0] = 'A' + ialt - 1;
+          }
+
+          /* Record the table column number. */
+          wcsp->colnum = icol;
+
+          /* On the second pass alts->arridx[icol][27] indexes the array of
+             wcsprm structs. */
+          alts->arridx[icol][ialt] = (*nwcs)++;
+
+          wcsp++;
+
+        } else {
+          /* Signal that this column has no WCS for this "a". */
+          alts->arridx[icol][ialt] = -1;
+        }
+      }
+    }
+
+    for (ialt = 0; ialt < 27; ialt++) {
+      if (alts->pixidx[ialt]) {
+        /* Pixel lists representations. */
+        wcsp->flag = -1;
+        wcsnpv(alts->pixnpv[ialt]);
+        wcsnps(alts->pixnps[ialt]);
+        if ((status = wcsini(1, (int)(alts->pixidx[ialt]), wcsp))) {
+          wcsvfree(nwcs, wcs);
+          break;
+        }
+
+        /* Record the alternate version code. */
+        if (ialt) {
+          wcsp->alt[0] = 'A' + ialt - 1;
+        }
+
+        /* Record the pixel list column numbers. */
+        mask = (1 << ialt);
+        for (icol = 1, ix = 0; icol <= ncol; icol++) {
+          if (alts->pixlist[icol] & mask) {
+            wcsp->colax[ix++] = icol;
+          }
+        }
+
+        /* alts->pixidx[] indexes the array of wcsprm structs. */
+        alts->pixidx[ialt] = (*nwcs)++;
+
+        wcsp++;
+
+      } else {
+        /* Signal that this column is not a pixel list axis for this "a". */
+        alts->pixidx[ialt] = -1;
+      }
+    }
+
+    /* Restore the original values of NPVMAX and NPSMAX. */
+    wcsnpv(npvmax);
+    wcsnps(npsmax);
+  }
+
+  return status;
+}
+
+
+/*----------------------------------------------------------------------------
+* Return a pointer to the next wcsprm struct for a particular column number
+* and alternate.
+*---------------------------------------------------------------------------*/
+
+struct wcsprm *wcsbth_idx(
+  struct wcsprm *wcs,
+  struct wcsbth_alts *alts,
+  int  keytype,
+  int  n,
+  char a)
+
+{
+  const char as[] = " ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+  int iwcs;
+
+  if (!wcs) return 0x0;
+
+  iwcs = -1;
+  for (; iwcs < 0 && alts->ialt < 27; alts->ialt++) {
+    /* Note that a == 0 applies to every alternate, otherwise this
+       loop simply determines the appropriate value of alts->ialt. */
+    if (a && a != as[alts->ialt]) continue;
+
+    if (keytype & (IMGHEAD | BIMGARR)) {
+      for (; iwcs < 0 && alts->icol <= alts->ncol; alts->icol++) {
+        /* Image header keywords, n == 0, apply to all columns, otherwise this
+           loop simply determines the appropriate value of alts->icol. */
+        if (n && n != alts->icol) continue;
+        iwcs = alts->arridx[alts->icol][alts->ialt];
+      }
+
+      /* Break out of the loop to stop alts->ialt from being incremented. */
+      if (iwcs >= 0) break;
+
+      /* Start from scratch for the next alts->ialt. */
+      alts->icol = 0;
+    }
+
+    if (keytype & (IMGAUX | PIXLIST)) {
+      iwcs = alts->pixidx[alts->ialt];
+    }
+  }
+
+  return (iwcs >= 0) ? (wcs + iwcs) : 0x0;
+}
+
+
+/*----------------------------------------------------------------------------
+* Return the axis number associated with the specified column number in a
+* particular pixel list coordinate representation.
+*---------------------------------------------------------------------------*/
+
+int wcsbth_colax(
+  struct wcsprm *wcs,
+  struct wcsbth_alts *alts,
+  int n,
+  char a)
+
+{
+  int ix;
+  struct wcsprm *wcsp;
+
+  if (!wcs) return 0;
+
+  wcsp = wcs;
+  if (a != ' ') {
+    wcsp += alts->pixidx[a-'A'+1];
+  }
+
+  for (ix = 0; ix < wcsp->naxis; ix++) {
+    if (wcsp->colax[ix] == n) {
+      return ++ix;
+    }
+  }
+
+  return 0;
+}
+
+
+/*----------------------------------------------------------------------------
+* Interpret EPOCH keywords.
+*---------------------------------------------------------------------------*/
+
+int wcsbth_epoch(void *wptr)
+
+{
+  double *equinox;
+
+  /* If EQUINOXa is currently undefined then set it from EPOCHa. */
+  equinox = (double *)wptr;
+  if (undefined(*equinox)) {
+    wcsutil_str2double(yytext, "%lf", equinox);
+  }
+
+  return 0;
+}
+
+
+/*----------------------------------------------------------------------------
+* Interpret VSOURCE keywords.
+*---------------------------------------------------------------------------*/
+
+int wcsbth_vsource(void *wptr)
+
+{
+  double beta, c = 299792458.0, vsource, *zsource;
+
+  /* If ZSOURCEa is currently undefined then set it from VSOURCEa. */
+  zsource = (double *)wptr;
+  if (undefined(*zsource)) {
+    wcsutil_str2double(yytext, "%lf", &vsource);
+
+    /* Convert relativistic Doppler velocity to redshift. */
+    beta = vsource/c;
+    *zsource = (1.0 + beta)/sqrt(1.0 - beta*beta) - 1.0;
+  }
+
+  return 0;
+}
+
+
+/*----------------------------------------------------------------------------
+* Tie up loose ends.
+*---------------------------------------------------------------------------*/
+
+int wcsbth_final(
+  struct wcsbth_alts *alts,
+  int *nwcs,
+  struct wcsprm **wcs)
+
+{
+  int ialt, status;
+
+  if (alts->arridx)  free(alts->arridx);
+  if (alts->npv)     free(alts->npv);
+  if (alts->nps)     free(alts->nps);
+  if (alts->pixlist) free(alts->pixlist);
+
+  for (ialt = 0; ialt < *nwcs; ialt++) {
+    /* Interpret -TAB header keywords. */
+    if ((status = wcstab(*wcs+ialt))) {
+       wcsvfree(nwcs, wcs);
+       return status;
+    }
+  }
+
+  return 0;
+}
diff --git a/cextern/wcslib/C/wcserr.c b/cextern/wcslib/C/wcserr.c
new file mode 100644
index 0000000..3cec270
--- /dev/null
+++ b/cextern/wcslib/C/wcserr.c
@@ -0,0 +1,160 @@
+/*============================================================================
+
+  WCSLIB 4.16 - an implementation of the FITS WCS standard.
+  Copyright (C) 1995-2012, Mark Calabretta
+
+  This file is part of WCSLIB.
+
+  WCSLIB is free software: you can redistribute it and/or modify it under the
+  terms of the GNU Lesser General Public License as published by the Free
+  Software Foundation, either version 3 of the License, or (at your option)
+  any later version.
+
+  WCSLIB 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 Lesser General Public License for
+  more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with WCSLIB.  If not, see http://www.gnu.org/licenses.
+
+  Direct correspondence concerning WCSLIB to mark at calabretta.id.au
+
+  Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
+  Module author: Michael Droettboom
+  http://www.atnf.csiro.au/people/Mark.Calabretta
+  $Id: wcserr.c,v 4.16 2012/11/07 04:42:44 cal103 Exp $
+*===========================================================================*/
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "wcserr.h"
+#include "wcsprintf.h"
+
+static int wcserr_enabled = 0;
+
+/*--------------------------------------------------------------------------*/
+
+int wcserr_enable(int enable)
+
+{
+  return wcserr_enabled = (enable ? 1 : 0);
+}
+
+/*--------------------------------------------------------------------------*/
+
+int wcserr_prt(
+  const struct wcserr *err,
+  const char *prefix)
+
+{
+  if (!wcserr_enabled) {
+    wcsprintf("Error messaging is not enabled, use wcserr_enable().\n");
+    return 2;
+  }
+
+  if (err == 0x0) {
+    return 0;
+  }
+
+  if (err->status) {
+    if (prefix == 0x0) prefix = "";
+
+    if (err->status > 0) {
+      wcsprintf("%sERROR %d in %s() at line %d of file %s:\n%s%s.\n",
+        prefix, err->status, err->function, err->line_no, err->file, prefix,
+        err->msg);
+    } else {
+      /* An informative message only. */
+      wcsprintf("%sINFORMATIVE message from %s() at line %d of file "
+        "%s:\n%s%s.\n", prefix, err->function, err->line_no, err->file,
+        prefix, err->msg);
+    }
+  }
+
+  return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int wcserr_clear(
+  struct wcserr **errp)
+
+{
+  if (*errp) free(*errp);
+  *errp = 0x0;
+
+  return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int wcserr_set(
+  struct wcserr **errp,
+  int status,
+  const char *function,
+  const char *file,
+  int line_no,
+  const char *format,
+  ...)
+
+{
+  char fmt[128];
+  struct wcserr *err;
+  va_list argp;
+
+  if (!wcserr_enabled) return status;
+
+  if (errp == 0x0) {
+    return status;
+  }
+  err = *errp;
+
+  if (status) {
+    if (err == 0x0) {
+      *errp = err = calloc(1, sizeof(struct wcserr));
+    }
+
+    err->status   = status;
+    err->function = function;
+    err->file     = file;
+    err->line_no  = line_no;
+
+    /* Workaround for a compiler segv from gcc 4.2.1 in MacOSX 10.7. */
+    strncpy(fmt, format, 128);
+
+    va_start(argp, format);
+    vsnprintf(err->msg, WCSERR_MSG_LENGTH, fmt, argp);
+    va_end(argp);
+
+  } else if (err) {
+    free(err);
+    *errp = 0x0;
+  }
+
+  return status;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int wcserr_copy(
+  const struct wcserr *src,
+  struct wcserr *dst)
+
+{
+  if (src == 0x0) {
+    if (dst) {
+      memset(dst, 0, sizeof(struct wcserr));
+    }
+    return 0;
+  }
+
+  if (dst) {
+    memcpy(dst, src, sizeof(struct wcserr));
+  }
+
+  return src->status;
+}
diff --git a/cextern/wcslib/C/wcserr.h b/cextern/wcslib/C/wcserr.h
new file mode 100644
index 0000000..f422e29
--- /dev/null
+++ b/cextern/wcslib/C/wcserr.h
@@ -0,0 +1,245 @@
+/*============================================================================
+
+  WCSLIB 4.16 - an implementation of the FITS WCS standard.
+  Copyright (C) 1995-2012, Mark Calabretta
+
+  This file is part of WCSLIB.
+
+  WCSLIB is free software: you can redistribute it and/or modify it under the
+  terms of the GNU Lesser General Public License as published by the Free
+  Software Foundation, either version 3 of the License, or (at your option)
+  any later version.
+
+  WCSLIB 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 Lesser General Public License for
+  more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with WCSLIB.  If not, see http://www.gnu.org/licenses.
+
+  Direct correspondence concerning WCSLIB to mark at calabretta.id.au
+
+  Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
+  Module author: Michael Droettboom
+  http://www.atnf.csiro.au/people/Mark.Calabretta
+  $Id: wcserr.h,v 4.16 2012/11/07 04:42:44 cal103 Exp $
+*=============================================================================
+*
+* Summary of the wcserr routines
+* ------------------------------
+* Most of the structs in WCSLIB contain a pointer to a wcserr struct as a
+* member.  Functions in WCSLIB that return an error status code can also
+* allocate and set a detailed error message in this struct which also
+* identifies the function, source file, and line number where the error
+* occurred.
+*
+* For example:
+*
+=     struct prjprm prj;
+=     wcserr_enable(1);
+=     if (prjini(&prj)) {
+=       // Print the error message to stderr.
+=       wcsprintf_set(stderr);
+=       wcserr_prt(prj.err, 0x0);
+=     }
+*
+* A number of utility functions used in managing the wcserr struct are for
+* internal use only.  They are documented here solely as an aid to
+* understanding the code.  They are not intended for external use - the API
+* may change without notice!
+*
+*
+* wcserr struct - Error message handling
+* --------------------------------------
+* The wcserr struct contains the numeric error code, a textual description of
+* the error, and information about the function, source file, and line number
+* where the error was generated.
+*
+*   int status
+*     Numeric status code associated with the error, the meaning of which
+*     depends on the function that generated it.  See the documentation for
+*     the particular function.
+*
+*   int line_no
+*     Line number where the error occurred as given by the __LINE__
+*     preprocessor macro.
+*
+*   const char *function
+*     Name of the function where the error occurred.
+*
+*   const char *file
+*     Name of the source file where the error occurred as given by the
+*     __FILE__ preprocessor macro.
+*
+*   char msg[WCSERR_MSG_LENGTH]
+*     Informative error message.
+*
+*
+* wcserr_enable() - Enable/disable error messaging
+* ------------------------------------------------
+* wcserr_enable() enables or disables wcserr error messaging.  By default it
+* is disabled.
+*
+* PLEASE NOTE: This function is not thread-safe.
+*
+* Given:
+*   enable    int       If true (non-zero), enable error messaging, else
+*                       disable it.
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Error messaging is disabled.
+*                         1: Error messaging is enabled.
+*
+*
+* wcserr_prt() - Print a wcserr struct
+* ------------------------------------
+* wcserr_prt() prints the error message (if any) contained in a wcserr struct.
+* It uses the wcsprintf() functions.
+*
+* Given:
+*   err       const struct wcserr*
+*                       The error object.  If NULL, nothing is printed.
+*
+*   prefix    const char *
+*                       If non-NULL, each output line will be prefixed with
+*                       this string.
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         2: Error messaging is not enabled.
+*
+*
+* wcserr_clear() - Clear a wcserr struct
+* --------------------------------------
+* wcserr_clear() clears the error (if any) contained in a wcserr struct.
+*
+* Given and returned:
+*   err       struct wcserr**
+*                       The error object.  If NULL, nothing is done.  Set to
+*                       NULL on return.
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*
+*
+* wcserr_set() - Fill in the contents of an error object
+* ------------------------------------------------------
+* INTERNAL USE ONLY.
+*
+* wcserr_set() fills a wcserr struct with information about an error.
+*
+* A convenience macro, WCSERR_SET, provides the source file and line number
+* information automatically.
+*
+* Given and returned:
+*   err       struct wcserr**
+*                       Error object.
+*
+*                       If err is NULL, returns the status code given without
+*                       setting an error message.
+*
+*                       If *err is NULL, allocates memory for a wcserr struct
+*                       (provided that status is non-zero).
+*
+* Given:
+*   status    int       Numeric status code to set.  If 0, then *err will be
+*                       deleted and *err will be returned as NULL.
+*
+*   function  const char *
+*                       Name of the function generating the error.  This
+*                       must point to a constant string, i.e. in the
+*                       initialized read-only data section ("data") of the
+*                       executable.
+*
+*   file      const char *
+*                       Name of the source file generating the error.  This
+*                       must point to a constant string, i.e. in the
+*                       initialized read-only data section ("data") of the
+*                       executable such as given by the __FILE__ preprocessor
+*                       macro.
+*
+*   line_no   int       Line number in the source file generating the error
+*                       such as given by the __LINE__ preprocessor macro.
+*
+*   format    const char *
+*                       Format string of the error message.  May contain
+*                       printf-style %-formatting codes.
+*
+*   ...       mixed     The remaining variable arguments are applied (like
+*                       printf) to the format string to generate the error
+*                       message.
+*
+* Function return value:
+*             int       The status return code passed in.
+*
+*
+* wcserr_copy() - Copy an error object
+* ------------------------------------
+* INTERNAL USE ONLY.
+*
+* wcserr_copy() copies one error object to another.  Use of this function
+* should be avoided in general since the function, source file, and line
+* number information copied to the destination may lose its context.
+*
+* Given:
+*   src       const struct wcserr*
+*                       Source error object.  If src is NULL, dst is cleared.
+*
+* Returned:
+*   dst       struct wcserr*
+*                       Destination error object.  If NULL, no copy is made.
+*
+* Function return value:
+*             int       Numeric status code of the source error object.
+*
+*
+* WCSERR_SET() macro - Fill in the contents of an error object
+* ------------------------------------------------------------
+* INTERNAL USE ONLY.
+*
+* WCSERR_SET() is a preprocessor macro that helps to fill in the argument list
+* of wcserr_set().  It takes status as an argument of its own and provides the
+* name of the source file and the line number at the point where invoked.  It
+* assumes that the err and function arguments of wcserr_set() will be provided
+* by variables of the same names.
+*
+*===========================================================================*/
+
+#ifndef WCSLIB_WCSERR
+#define WCSLIB_WCSERR
+
+#define WCSERR_MSG_LENGTH 160
+
+struct wcserr {
+  int  status;			/* Status code for the error.               */
+  int  line_no;			/* Line number where the error occurred.    */
+  const char *function;		/* Function name.                           */
+  const char *file;		/* Source file name.                        */
+  char msg[WCSERR_MSG_LENGTH];	/* Informative error message.               */
+};
+
+/* Size of the wcserr struct in int units, used by the Fortran wrappers. */
+#define ERRLEN (sizeof(struct wcserr)/sizeof(int))
+
+int wcserr_enable(int enable);
+
+int wcserr_prt(const struct wcserr *err, const char *prefix);
+
+int wcserr_clear(struct wcserr **err);
+
+
+/* INTERNAL USE ONLY -------------------------------------------------------*/
+
+int wcserr_set(struct wcserr **err, int status, const char *function,
+  const char *file, int line_no, const char *format, ...);
+
+int wcserr_copy(const struct wcserr *src, struct wcserr *dst);
+
+/* Convenience macro for invoking wcserr_set(). */
+#define WCSERR_SET(status) err, status, function, __FILE__, __LINE__
+
+#endif /* WSCLIB_WCSERR */
diff --git a/cextern/wcslib/C/wcsfix.c b/cextern/wcslib/C/wcsfix.c
new file mode 100644
index 0000000..86731c2
--- /dev/null
+++ b/cextern/wcslib/C/wcsfix.c
@@ -0,0 +1,743 @@
+/*============================================================================
+
+  WCSLIB 4.16 - an implementation of the FITS WCS standard.
+  Copyright (C) 1995-2012, Mark Calabretta
+
+  This file is part of WCSLIB.
+
+  WCSLIB is free software: you can redistribute it and/or modify it under the
+  terms of the GNU Lesser General Public License as published by the Free
+  Software Foundation, either version 3 of the License, or (at your option)
+  any later version.
+
+  WCSLIB 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 Lesser General Public License for
+  more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with WCSLIB.  If not, see http://www.gnu.org/licenses.
+
+  Direct correspondence concerning WCSLIB to mark at calabretta.id.au
+
+  Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
+  http://www.atnf.csiro.au/people/Mark.Calabretta
+  $Id: wcsfix.c,v 4.16 2012/11/07 04:42:44 cal103 Exp $
+*===========================================================================*/
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "wcserr.h"
+#include "wcsmath.h"
+#include "wcsutil.h"
+#include "sph.h"
+#include "wcs.h"
+#include "wcsunits.h"
+#include "wcsfix.h"
+
+extern const int WCSSET;
+
+/* Maximum number of coordinate axes that can be handled. */
+#define NMAX 16
+
+/* Map status return value to message. */
+const char *wcsfix_errmsg[] = {
+  "Success",
+  "Null wcsprm pointer passed",
+  "Memory allocation failed",
+  "Linear transformation matrix is singular",
+  "Inconsistent or unrecognized coordinate axis types",
+  "Invalid parameter value",
+  "Invalid coordinate transformation parameters",
+  "Ill-conditioned coordinate transformation parameters",
+  "All of the corner pixel coordinates are invalid",
+  "Could not determine reference pixel coordinate",
+  "Could not determine reference pixel value"};
+
+/* Convenience macro for invoking wcserr_set(). */
+#define WCSFIX_ERRMSG(status) WCSERR_SET(status), wcsfix_errmsg[status]
+
+/*--------------------------------------------------------------------------*/
+
+int wcsfix(int ctrl, const int naxis[], struct wcsprm *wcs, int stat[])
+
+{
+  int status = 0;
+
+  if ((stat[CDFIX] = cdfix(wcs)) > 0) {
+    status = 1;
+  }
+
+  if ((stat[DATFIX] = datfix(wcs)) > 0) {
+    status = 1;
+  }
+
+  if ((stat[UNITFIX] = unitfix(ctrl, wcs)) > 0) {
+    status = 1;
+  }
+
+  if ((stat[SPCFIX] = spcfix(wcs)) > 0) {
+    status = 1;
+  }
+
+  if ((stat[CELFIX] = celfix(wcs)) > 0) {
+    status = 1;
+  }
+
+  if ((stat[CYLFIX] = cylfix(naxis, wcs)) > 0) {
+    status = 1;
+  }
+
+  return status;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int wcsfixi(int ctrl, const int naxis[], struct wcsprm *wcs, int stat[],
+            struct wcserr info[])
+
+{
+  int ifix, status = 0;
+  struct wcserr err;
+
+  /* Handling the status values returned from the sub-fixers is trickier than
+  it might seem, especially considering that wcs->err may contain an error
+  status on input which should be preserved if no translation errors occur.
+  The simplest way seems to be to save a copy of wcs->err and clear it before
+  each sub-fixer.  The last real error to occur, excluding informative
+  messages, is the one returned.
+
+  To get informative messages from spcfix() it must precede celfix() and
+  cylfix().  The latter call wcsset() which also translates AIPS-convention
+  spectral axes. */
+  wcserr_copy(wcs->err, &err);
+
+  for (ifix = CDFIX; ifix < NWCSFIX; ifix++) {
+    /* Clear (delete) wcs->err. */
+    wcserr_clear(&(wcs->err));
+
+    switch (ifix) {
+    case CDFIX:
+      stat[ifix] = cdfix(wcs);
+      break;
+    case DATFIX:
+      stat[ifix] = datfix(wcs);
+      break;
+    case UNITFIX:
+      stat[ifix] = unitfix(ctrl, wcs);
+      break;
+    case SPCFIX:
+      stat[ifix] = spcfix(wcs);
+      break;
+    case CELFIX:
+      stat[ifix] = celfix(wcs);
+      break;
+    case CYLFIX:
+      stat[ifix] = cylfix(naxis, wcs);
+      break;
+    default:
+      continue;
+    }
+
+    if (stat[ifix] == FIXERR_NO_CHANGE) {
+      /* No change => no message. */
+      wcserr_copy(0x0, info+ifix);
+
+    } else if (stat[ifix] == FIXERR_SUCCESS) {
+      /* Successful translation, but there may be an informative message. */
+      if (wcs->err && wcs->err->status < 0) {
+        wcserr_copy(wcs->err, info+ifix);
+      } else {
+        wcserr_copy(0x0, info+ifix);
+      }
+
+    } else {
+      /* An informative message or error message. */
+      wcserr_copy(wcs->err, info+ifix);
+
+      if ((status = (stat[ifix] > 0))) {
+        /* It was an error, replace the previous one. */
+        wcserr_copy(wcs->err, &err);
+      }
+    }
+  }
+
+  /* Restore the last error to occur. */
+  if (err.status) {
+    wcserr_copy(&err, wcs->err);
+  } else {
+    wcserr_clear(&(wcs->err));
+  }
+
+  return status;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int cdfix(struct wcsprm *wcs)
+
+{
+  int  i, k, naxis, status = FIXERR_NO_CHANGE;
+  double *cd;
+
+  if (wcs == 0x0) return FIXERR_NULL_POINTER;
+
+  if ((wcs->altlin & 1) || !(wcs->altlin & 2)) {
+    /* Either we have PCi_ja or there are no CDi_ja. */
+    return FIXERR_NO_CHANGE;
+  }
+
+  naxis = wcs->naxis;
+  status = FIXERR_NO_CHANGE;
+  for (i = 0; i < naxis; i++) {
+    /* Row of zeros? */
+    cd = wcs->cd + i * naxis;
+    for (k = 0; k < naxis; k++, cd++) {
+      if (*cd != 0.0) goto next;
+    }
+
+    /* Column of zeros? */
+    cd = wcs->cd + i;
+    for (k = 0; k < naxis; k++, cd += naxis) {
+      if (*cd != 0.0) goto next;
+    }
+
+    cd = wcs->cd + i * (naxis + 1);
+    *cd = 1.0;
+    status = FIXERR_SUCCESS;
+
+next: ;
+  }
+
+  return status;
+}
+
+/*--------------------------------------------------------------------------*/
+
+static int parse_date(const char *buf, int *hour, int *minute, double *sec)
+
+{
+  char ctmp[72];
+
+  if (sscanf(buf, "%2d:%2d:%s", hour, minute, ctmp) < 3 ||
+      wcsutil_str2double(ctmp, "%lf", sec)) {
+    return 1;
+  }
+
+  return 0;
+}
+
+static void write_date(char *buf, int hour, int minute, double sec)
+
+{
+  char ctmp[72];
+
+  wcsutil_double2str(ctmp, "%04.1f", sec);
+  sprintf(buf, "T%.2d:%.2d:%s", hour, minute, ctmp);
+}
+
+int datfix(struct wcsprm *wcs)
+
+{
+  static const char *function = "datfix";
+
+  char orig_dateobs[72];
+  char ctmp[72], ctmp2[72];
+  char *dateobs;
+  int  day, dd, hour = 0, jd, minute = 0, month, msec, n4, year;
+  double mjdobs, sec = 0.0, t;
+  struct wcserr **err;
+
+  if (wcs == 0x0) return FIXERR_NULL_POINTER;
+  err = &(wcs->err);
+
+  dateobs = wcs->dateobs;
+  strncpy(orig_dateobs, dateobs, 72);
+  if (dateobs[0] == '\0') {
+    if (undefined(wcs->mjdobs)) {
+     /* No date information was provided. */
+      return FIXERR_NO_CHANGE;
+
+    } else {
+      /* Calendar date from MJD. */
+      jd = 2400001 + (int)wcs->mjdobs;
+
+      n4 =  4*(jd + ((2*((4*jd - 17918)/146097)*3)/4 + 1)/2 - 37);
+      dd = 10*(((n4-237)%1461)/4) + 5;
+
+      year  = n4/1461 - 4712;
+      month = (2 + dd/306)%12 + 1;
+      day   = (dd%306)/10 + 1;
+      sprintf(dateobs, "%.4d-%.2d-%.2d", year, month, day);
+
+      /* Write time part only if non-zero. */
+      if ((t = wcs->mjdobs - (int)wcs->mjdobs) > 0.0) {
+        t *= 24.0;
+        hour = (int)t;
+        t = 60.0 * (t - hour);
+        minute = (int)t;
+        sec    = 60.0 * (t - minute);
+
+        /* Round to 1ms. */
+        dd = 60000*(60*hour + minute) + (int)(1000*(sec+0.0005));
+        hour = dd / 3600000;
+        dd -= 3600000 * hour;
+        minute = dd / 60000;
+        msec = dd - 60000 * minute;
+        sprintf(dateobs+10, "T%.2d:%.2d:%.2d", hour, minute, msec/1000);
+
+        /* Write fractions of a second only if non-zero. */
+        if (msec%1000) {
+          sprintf(dateobs+19, ".%.3d", msec%1000);
+        }
+      }
+    }
+
+  } else {
+    if (strlen(dateobs) < 8) {
+      /* Can't be a valid date. */
+      return wcserr_set(WCSERR_SET(FIXERR_BAD_PARAM),
+        "Invalid parameter value: date string too short '%s'", dateobs);
+    }
+
+    /* Identify the date format. */
+    if (dateobs[4] == '-' && dateobs[7] == '-') {
+      /* Standard year-2000 form: CCYY-MM-DD[Thh:mm:ss[.sss...]] */
+      if (sscanf(dateobs, "%4d-%2d-%2d", &year, &month, &day) < 3) {
+        return wcserr_set(WCSERR_SET(FIXERR_BAD_PARAM),
+          "Invalid parameter value: invalid date '%s'", dateobs);
+      }
+
+      if (dateobs[10] == 'T') {
+        if (parse_date(dateobs+11, &hour, &minute, &sec)) {
+          return wcserr_set(WCSERR_SET(FIXERR_BAD_PARAM),
+            "Invalid parameter value: invalid time '%s'", dateobs+11);
+        }
+      } else if (dateobs[10] == ' ') {
+        hour = 0;
+        minute = 0;
+        sec = 0.0;
+        if (parse_date(dateobs+11, &hour, &minute, &sec)) {
+          write_date(dateobs+10, hour, minute, sec);
+        } else {
+          dateobs[10] = 'T';
+        }
+      }
+
+    } else if (dateobs[4] == '/' && dateobs[7] == '/') {
+      /* Also allow CCYY/MM/DD[Thh:mm:ss[.sss...]] */
+      if (sscanf(dateobs, "%4d/%2d/%2d", &year, &month, &day) < 3) {
+        return wcserr_set(WCSERR_SET(FIXERR_BAD_PARAM),
+          "Invalid parameter value: invalid date '%s'", dateobs);
+      }
+
+      if (dateobs[10] == 'T') {
+        if (parse_date(dateobs+11, &hour, &minute, &sec)) {
+          return wcserr_set(WCSERR_SET(FIXERR_BAD_PARAM),
+            "Invalid parameter value: invalid time '%s'", dateobs+11);
+        }
+      } else if (dateobs[10] == ' ') {
+        hour = 0;
+        minute = 0;
+        sec = 0.0;
+        if (parse_date(dateobs+11, &hour, &minute, &sec)) {
+          write_date(dateobs+10, hour, minute, sec);
+        } else {
+          dateobs[10] = 'T';
+        }
+      }
+
+      /* Looks ok, fix it up. */
+      dateobs[4]  = '-';
+      dateobs[7]  = '-';
+
+    } else {
+      if (dateobs[2] == '/' && dateobs[5] == '/') {
+        /* Old format date: DD/MM/YY, also allowing DD/MM/CCYY. */
+        if (sscanf(dateobs, "%2d/%2d/%4d", &day, &month, &year) < 3) {
+          return wcserr_set(WCSERR_SET(FIXERR_BAD_PARAM),
+            "Invalid parameter value: invalid date '%s'", dateobs);
+        }
+
+      } else if (dateobs[2] == '-' && dateobs[5] == '-') {
+        /* Also recognize DD-MM-YY and DD-MM-CCYY */
+        if (sscanf(dateobs, "%2d-%2d-%4d", &day, &month, &year) < 3) {
+          return wcserr_set(WCSERR_SET(FIXERR_BAD_PARAM),
+            "Invalid parameter value: invalid date '%s'", dateobs);
+        }
+
+      } else {
+        /* Not a valid date format. */
+        return wcserr_set(WCSERR_SET(FIXERR_BAD_PARAM),
+          "Invalid parameter value: invalid date '%s'", dateobs);
+      }
+
+      if (year < 100) year += 1900;
+
+      /* Doesn't have a time. */
+      sprintf(dateobs, "%.4d-%.2d-%.2d", year, month, day);
+    }
+
+    /* Compute MJD. */
+    mjdobs = (double)((1461*(year - (12-month)/10 + 4712))/4
+             + (306*((month+9)%12) + 5)/10
+             - (3*((year - (12-month)/10 + 4900)/100))/4
+             + day - 2399904)
+             + (hour + (minute + sec/60.0)/60.0)/24.0;
+
+    if (undefined(wcs->mjdobs)) {
+      wcs->mjdobs = mjdobs;
+    } else {
+      /* Check for consistency. */
+      if (fabs(mjdobs - wcs->mjdobs) > 0.5) {
+        return wcserr_set(WCSERR_SET(FIXERR_BAD_PARAM),
+          "Invalid parameter value: inconsistent date '%s'", dateobs);
+      }
+    }
+  }
+
+  if (strncmp(orig_dateobs, dateobs, 72)) {
+    wcserr_set(WCSERR_SET(FIXERR_DATE_FIX),
+      "Changed '%s' to '%s'", orig_dateobs, dateobs);
+
+    return FIXERR_SUCCESS;
+  }
+
+  return FIXERR_NO_CHANGE;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int unitfix(int ctrl, struct wcsprm *wcs)
+
+{
+  int  i, k, status = FIXERR_NO_CHANGE;
+  char orig_unit[80], msg[WCSERR_MSG_LENGTH];
+  const char *function = "unitfix";
+  struct wcserr **err;
+
+  if (wcs == 0x0) return FIXERR_NULL_POINTER;
+  err = &(wcs->err);
+
+  strcpy(msg, "Changed units: ");
+  for (i = 0; i < wcs->naxis; i++) {
+    strncpy(orig_unit, wcs->cunit[i], 80);
+    if (wcsutrne(ctrl, wcs->cunit[i], &(wcs->err)) == 0) {
+      k = strlen(msg);
+      sprintf(msg+k, "'%s' -> '%s', ", orig_unit, wcs->cunit[i]);
+      status = FIXERR_UNITS_ALIAS;
+    }
+  }
+
+  if (status == FIXERR_UNITS_ALIAS) {
+    k = strlen(msg) - 2;
+    msg[k] = '\0';
+    wcserr_set(WCSERR_SET(FIXERR_UNITS_ALIAS), msg);
+
+    status = FIXERR_SUCCESS;
+  }
+
+  return status;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int spcfix(struct wcsprm *wcs)
+
+{
+  static const char *function = "spcfix";
+
+  char ctype[9], specsys[9];
+  int  i, status;
+  struct wcserr **err;
+
+  if (wcs == 0x0) return FIXERR_NULL_POINTER;
+  err = &(wcs->err);
+
+  for (i = 0; i < wcs->naxis; i++) {
+    /* Translate an AIPS-convention spectral type if present. */
+    status = spcaips(wcs->ctype[i], wcs->velref, ctype, specsys);
+    if (status == 0) {
+      /* An AIPS type was found but it may match what we already have. */
+      status = FIXERR_NO_CHANGE;
+
+      /* Was specsys translated? */
+      if (wcs->specsys[0] == '\0' && *specsys) {
+        strncpy(wcs->specsys, specsys, 9);
+        wcserr_set(WCSERR_SET(FIXERR_SPC_UPDATE),
+          "Changed SPECSYS to '%s'", specsys);
+        status = FIXERR_SUCCESS;
+      }
+
+      /* Was ctype translated?  Have to null-fill for comparing them. */
+      wcsutil_null_fill(9, wcs->ctype[i]);
+      if (strncmp(wcs->ctype[i], ctype, 9)) {
+        /* ctype was translated... */
+        if (status == FIXERR_SUCCESS) {
+          /* ...and specsys was also. */
+          wcserr_set(WCSERR_SET(FIXERR_SPC_UPDATE),
+            "Changed CTYPE%d from '%s' to '%s', and SPECSYS to '%s'",
+            i+1, wcs->ctype[i], ctype, wcs->specsys);
+        } else {
+          wcserr_set(WCSERR_SET(FIXERR_SPC_UPDATE),
+            "Changed CTYPE%d from '%s' to '%s'", i+1, wcs->ctype[i], ctype);
+          status = FIXERR_SUCCESS;
+        }
+
+        strncpy(wcs->ctype[i], ctype, 9);
+      }
+
+      /* Tidy up. */
+      if (status == FIXERR_SUCCESS) {
+        wcsutil_null_fill(72, wcs->ctype[i]);
+        wcsutil_null_fill(72, wcs->specsys);
+      }
+
+      /* No need to check for others, wcsset() will fail if so. */
+      return status;
+
+    } else if (status == SPCERR_BAD_SPEC_PARAMS) {
+      /* An AIPS spectral type was found but with invalid velref. */
+      return wcserr_set(WCSERR_SET(FIXERR_BAD_PARAM),
+        "Invalid parameter value: velref = %d", wcs->velref);
+    }
+  }
+
+  return FIXERR_NO_CHANGE;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int celfix(struct wcsprm *wcs)
+
+{
+  static const char *function = "celfix";
+
+  int k, status;
+  struct celprm *wcscel = &(wcs->cel);
+  struct prjprm *wcsprj = &(wcscel->prj);
+  struct wcserr **err;
+
+  if (wcs == 0x0) return FIXERR_NULL_POINTER;
+  err = &(wcs->err);
+
+  /* Initialize if required. */
+  if (wcs->flag != WCSSET) {
+    if ((status = wcsset(wcs))) return status;
+  }
+
+  /* Was an NCP or GLS projection code translated? */
+  if (wcs->lat >= 0) {
+    /* Check ctype. */
+    if (strcmp(wcs->ctype[wcs->lat]+5, "NCP") == 0) {
+      strcpy(wcs->ctype[wcs->lng]+5, "SIN");
+      strcpy(wcs->ctype[wcs->lat]+5, "SIN");
+
+      if (wcs->npvmax < wcs->npv + 2) {
+        /* Allocate space for two more PVi_ja keyvalues. */
+        if (wcs->m_flag == WCSSET && wcs->pv == wcs->m_pv) {
+          if (!(wcs->pv = calloc(wcs->npv+2, sizeof(struct pvcard)))) {
+            wcs->pv = wcs->m_pv;
+            return wcserr_set(WCSFIX_ERRMSG(FIXERR_MEMORY));
+          }
+
+          wcs->npvmax = wcs->npv + 2;
+          wcs->m_flag = WCSSET;
+
+          for (k = 0; k < wcs->npv; k++) {
+            wcs->pv[k] = wcs->m_pv[k];
+          }
+
+          if (wcs->m_pv) free(wcs->m_pv);
+          wcs->m_pv = wcs->pv;
+
+        } else {
+          return wcserr_set(WCSFIX_ERRMSG(FIXERR_MEMORY));
+        }
+      }
+
+      wcs->pv[wcs->npv].i = wcs->lat + 1;
+      wcs->pv[wcs->npv].m = 1;
+      wcs->pv[wcs->npv].value = wcsprj->pv[1];
+      (wcs->npv)++;
+
+      wcs->pv[wcs->npv].i = wcs->lat + 1;
+      wcs->pv[wcs->npv].m = 2;
+      wcs->pv[wcs->npv].value = wcsprj->pv[2];
+      (wcs->npv)++;
+
+      return FIXERR_SUCCESS;
+
+    } else if (strcmp(wcs->ctype[wcs->lat]+5, "GLS") == 0) {
+      strcpy(wcs->ctype[wcs->lng]+5, "SFL");
+      strcpy(wcs->ctype[wcs->lat]+5, "SFL");
+
+      if (wcs->crval[wcs->lng] != 0.0 || wcs->crval[wcs->lat] != 0.0) {
+        /* In the AIPS convention, setting the reference longitude and
+         * latitude for GLS does not create an oblique graticule.  A non-zero
+         * reference longitude introduces an offset in longitude in the normal
+         * way, whereas a non-zero reference latitude simply translates the
+         * reference point (i.e. the map as a whole) to that latitude.  This
+         * might be effected by adjusting CRPIXja but that is complicated by
+         * the linear transformation and instead is accomplished here by
+         * setting theta_0. */
+        if (wcs->npvmax < wcs->npv + 2) {
+          /* Allocate space for three more PVi_ja keyvalues. */
+          if (wcs->m_flag == WCSSET && wcs->pv == wcs->m_pv) {
+            if (!(wcs->pv = calloc(wcs->npv+3, sizeof(struct pvcard)))) {
+              wcs->pv = wcs->m_pv;
+              return wcserr_set(WCSFIX_ERRMSG(FIXERR_MEMORY));
+            }
+
+            wcs->npvmax = wcs->npv + 3;
+            wcs->m_flag = WCSSET;
+
+            for (k = 0; k < wcs->npv; k++) {
+              wcs->pv[k] = wcs->m_pv[k];
+            }
+
+            if (wcs->m_pv) free(wcs->m_pv);
+            wcs->m_pv = wcs->pv;
+
+          } else {
+            return wcserr_set(WCSFIX_ERRMSG(FIXERR_MEMORY));
+          }
+        }
+
+        wcs->pv[wcs->npv].i = wcs->lng + 1;
+        wcs->pv[wcs->npv].m = 0;
+        wcs->pv[wcs->npv].value = 1.0;
+        (wcs->npv)++;
+
+        /* Note that the reference longitude is still zero. */
+        wcs->pv[wcs->npv].i = wcs->lng + 1;
+        wcs->pv[wcs->npv].m = 1;
+        wcs->pv[wcs->npv].value = 0.0;
+        (wcs->npv)++;
+
+        wcs->pv[wcs->npv].i = wcs->lng + 1;
+        wcs->pv[wcs->npv].m = 2;
+        wcs->pv[wcs->npv].value = wcs->crval[wcs->lat];
+        (wcs->npv)++;
+      }
+
+      return FIXERR_SUCCESS;
+    }
+  }
+
+  return FIXERR_NO_CHANGE;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int cylfix(const int naxis[], struct wcsprm *wcs)
+
+{
+  static const char *function = "cylfix";
+
+  unsigned short icnr, indx[NMAX], ncnr;
+  int    j, k, stat[4], status;
+  double img[4][NMAX], lat, lng, phi[4], phi0, phimax, phimin, pix[4][NMAX],
+         *pixj, theta[4], theta0, world[4][NMAX], x, y;
+  struct wcserr **err;
+
+  if (naxis == 0x0) return FIXERR_NO_CHANGE;
+  if (wcs == 0x0) return FIXERR_NULL_POINTER;
+  err = &(wcs->err);
+
+  /* Initialize if required. */
+  if (wcs->flag != WCSSET) {
+    if ((status = wcsset(wcs))) return status;
+  }
+
+  /* Check that we have a cylindrical projection. */
+  if (wcs->cel.prj.category != CYLINDRICAL) return FIXERR_NO_CHANGE;
+  if (wcs->naxis < 2) return FIXERR_NO_CHANGE;
+
+
+  /* Compute the native longitude in each corner of the image. */
+  ncnr = 1 << wcs->naxis;
+
+  for (k = 0; k < NMAX; k++) {
+    indx[k] = 1 << k;
+  }
+
+  phimin =  1.0e99;
+  phimax = -1.0e99;
+  for (icnr = 0; icnr < ncnr;) {
+    /* Do four corners at a time. */
+    for (j = 0; j < 4; j++, icnr++) {
+      pixj = pix[j];
+
+      for (k = 0; k < wcs->naxis; k++) {
+        if (icnr & indx[k]) {
+          *(pixj++) = naxis[k] + 0.5;
+        } else {
+          *(pixj++) = 0.5;
+        }
+      }
+    }
+
+    if (!(status = wcsp2s(wcs, 4, NMAX, pix[0], img[0], phi, theta, world[0],
+                          stat))) {
+      for (j = 0; j < 4; j++) {
+        if (phi[j] < phimin) phimin = phi[j];
+        if (phi[j] > phimax) phimax = phi[j];
+      }
+    }
+  }
+
+  if (phimin > phimax) return status;
+
+  /* Any changes needed? */
+  if (phimin >= -180.0 && phimax <= 180.0) return FIXERR_NO_CHANGE;
+
+
+  /* Compute the new reference pixel coordinates. */
+  phi0 = (phimin + phimax) / 2.0;
+  theta0 = 0.0;
+
+  if ((status = prjs2x(&(wcs->cel.prj), 1, 1, 1, 1, &phi0, &theta0, &x, &y,
+                       stat))) {
+    if (status == PRJERR_BAD_PARAM) {
+      return wcserr_set(WCSFIX_ERRMSG(FIXERR_BAD_PARAM));
+    }
+    return wcserr_set(WCSFIX_ERRMSG(FIXERR_NO_REF_PIX_COORD));
+  }
+
+  for (k = 0; k < wcs->naxis; k++) {
+    img[0][k] = 0.0;
+  }
+  img[0][wcs->lng] = x;
+  img[0][wcs->lat] = y;
+
+  if ((status = linx2p(&(wcs->lin), 1, 0, img[0], pix[0]))) {
+    return wcserr_set(WCSFIX_ERRMSG(status));
+  }
+
+
+  /* Compute celestial coordinates at the new reference pixel. */
+  if ((status = wcsp2s(wcs, 1, 0, pix[0], img[0], phi, theta, world[0],
+                       stat))) {
+    if (wcs->err->status == WCSERR_BAD_PIX) {
+      wcs->err->status = FIXERR_NO_REF_PIX_COORD;
+    }
+    return wcs->err->status;
+  }
+
+  /* Compute native coordinates of the celestial pole. */
+  lng =  0.0;
+  lat = 90.0;
+  (void)sphs2x(wcs->cel.euler, 1, 1, 1, 1, &lng, &lat, phi, theta);
+
+  wcs->crpix[wcs->lng] = pix[0][wcs->lng];
+  wcs->crpix[wcs->lat] = pix[0][wcs->lat];
+  wcs->crval[wcs->lng] = world[0][wcs->lng];
+  wcs->crval[wcs->lat] = world[0][wcs->lat];
+  wcs->lonpole = phi[0] - phi0;
+
+  return wcsset(wcs);
+}
diff --git a/cextern/wcslib/C/wcsfix.h b/cextern/wcslib/C/wcsfix.h
new file mode 100644
index 0000000..9d42aed
--- /dev/null
+++ b/cextern/wcslib/C/wcsfix.h
@@ -0,0 +1,398 @@
+/*============================================================================
+
+  WCSLIB 4.16 - an implementation of the FITS WCS standard.
+  Copyright (C) 1995-2012, Mark Calabretta
+
+  This file is part of WCSLIB.
+
+  WCSLIB is free software: you can redistribute it and/or modify it under the
+  terms of the GNU Lesser General Public License as published by the Free
+  Software Foundation, either version 3 of the License, or (at your option)
+  any later version.
+
+  WCSLIB 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 Lesser General Public License for
+  more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with WCSLIB.  If not, see http://www.gnu.org/licenses.
+
+  Direct correspondence concerning WCSLIB to mark at calabretta.id.au
+
+  Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
+  http://www.atnf.csiro.au/people/Mark.Calabretta
+  $Id: wcsfix.h,v 4.16 2012/11/07 04:42:44 cal103 Exp $
+*=============================================================================
+*
+* WCSLIB 4.16 - C routines that implement the FITS World Coordinate System
+* (WCS) standard.  Refer to
+*
+*   "Representations of world coordinates in FITS",
+*   Greisen, E.W., & Calabretta, M.R. 2002, A&A, 395, 1061 (Paper I)
+*
+*   "Representations of celestial coordinates in FITS",
+*   Calabretta, M.R., & Greisen, E.W. 2002, A&A, 395, 1077 (Paper II)
+*
+*   "Representations of spectral coordinates in FITS",
+*   Greisen, E.W., Calabretta, M.R., Valdes, F.G., & Allen, S.L.
+*   2006, A&A, 446, 747 (Paper III)
+*
+* Refer to the README file provided with WCSLIB for an overview of the
+* library.
+*
+*
+* Summary of the wcsfix routines
+* ------------------------------
+* Routines in this suite identify and translate various forms of non-standard
+* construct that are known to occur in FITS WCS headers.  These range from the
+* translation of non-standard values for standard WCS keywords, to the repair
+* of malformed coordinate representations.
+*
+* Non-standard keyvalues:
+* -----------------------
+*   AIPS-convention celestial projection types, NCP and GLS, and spectral
+*   types, 'FREQ-LSR', 'FELO-HEL', etc., set in CTYPEia are translated
+*   on-the-fly by wcsset() but without modifying the relevant ctype[], pv[] or
+*   specsys members of the wcsprm struct.  That is, only the information
+*   extracted from ctype[] is translated when wcsset() fills in wcsprm::cel
+*   (celprm struct) or wcsprm::spc (spcprm struct).
+*
+*   On the other hand, these routines do change the values of wcsprm::ctype[],
+*   wcsprm::pv[], wcsprm::specsys and other wcsprm struct members as
+*   appropriate to produce the same result as if the FITS header itself had
+*   been translated.
+*
+*   Auxiliary WCS header information not used directly by WCSLIB may also be
+*   translated.  For example, the older DATE-OBS date format (wcsprm::dateobs)
+*   is recast to year-2000 standard form, and MJD-OBS (wcsprm::mjdobs) will be
+*   deduced from it if not already set.
+*
+*   Certain combinations of keyvalues that result in malformed coordinate
+*   systems, as described in Sect. 7.3.4 of Paper I, may also be repaired.
+*   These are handled by cylfix().
+*
+* Non-standard keywords:
+* ----------------------
+*   The AIPS-convention CROTAn keywords are recognized as quasi-standard and
+*   as such are accomodated by the wcsprm::crota[] and translated to
+*   wcsprm::pc[][] by wcsset().  These are not dealt with here, nor are any
+*   other non-standard keywords since these routines work only on the contents
+*   of a wcsprm struct and do not deal with FITS headers per se.  In
+*   particular, they do not identify or translate CD00i00j, PC00i00j, PROJPn,
+*   EPOCH, VELREF or VSOURCEa keywords; this may be done by the FITS WCS
+*   header parser supplied with WCSLIB, refer to wcshdr.h.
+*
+* wcsfix() and wcsfixi() apply all of the corrections handled by the following
+* specific functions which may also be invoked separately:
+*
+*   - cdfix(): Sets the diagonal element of the CDi_ja matrix to 1.0 if all
+*     CDi_ja keywords associated with a particular axis are omitted.
+*
+*   - datfix(): recast an older DATE-OBS date format in dateobs to year-2000
+*     standard form and derive mjdobs from it if not already set.
+*     Alternatively, if mjdobs is set and dateobs isn't, then derive dateobs
+*     from it.
+*
+*   - unitfix(): translate some commonly used but non-standard unit strings in
+*     the CUNITia keyvalues, e.g. 'DEG' -> 'deg'.
+*
+*   - spcfix(): translate AIPS-convention spectral types, 'FREQ-LSR',
+*     'FELO-HEL', etc., in ctype[] as set from CTYPEia.
+*
+*   - celfix(): translate AIPS-convention celestial projection types, NCP and
+*     GLS, in ctype[] as set from CTYPEia.
+*
+*   - cylfix(): fixes WCS keyvalues for malformed cylindrical projections that
+*     suffer from the problem described in Sect. 7.3.4 of Paper I.
+*
+*
+* wcsfix() - Translate a non-standard WCS struct
+* ----------------------------------------------
+* wcsfix() is identical to wcsfixi(), but lacks the info argument.
+*
+*
+* wcsfixi() - Translate a non-standard WCS struct
+* -----------------------------------------------
+* wcsfix() applies all of the corrections handled separately by cdfix(),
+* datfix(), unitfix(), spcfix(), celfix(), and cylfix().
+*
+* Given:
+*   ctrl      int       Do potentially unsafe translations of non-standard
+*                       unit strings as described in the usage notes to
+*                       wcsutrn().
+*
+*   naxis     const int []
+*                       Image axis lengths.  If this array pointer is set to
+*                       zero then cylfix() will not be invoked.
+*
+* Given and returned:
+*   wcs       struct wcsprm*
+*                       Coordinate transformation parameters.
+*
+* Returned:
+*   stat      int [NWCSFIX]
+*                       Status returns from each of the functions.  Use the
+*                       preprocessor macros NWCSFIX to dimension this vector
+*                       and CDFIX, DATFIX, UNITFIX, SPCFIX, CELFIX, and CYLFIX
+*                       to access its elements.  A status value of -2 is set
+*                       for functions that were not invoked.
+*
+*   info      struct wcserr [NWCSFIX]
+*                       Status messages from each of the functions.  Use the
+*                       preprocessor macros NWCSFIX to dimension this vector
+*                       and CDFIX, DATFIX, UNITFIX, SPCFIX, CELFIX, and CYLFIX
+*                       to access its elements.
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         1: One or more of the translation functions
+*                            returned an error.
+*
+*
+* cdfix() - Fix erroneously omitted CDi_ja keywords
+* -------------------------------------------------
+* cdfix() sets the diagonal element of the CDi_ja matrix to unity if all
+* CDi_ja keywords associated with a given axis were omitted.  According to
+* Paper I, if any CDi_ja keywords at all are given in a FITS header then those
+* not given default to zero.  This results in a singular matrix with an
+* intersecting row and column of zeros.
+*
+* Given and returned:
+*   wcs       struct wcsprm*
+*                       Coordinate transformation parameters.
+*
+* Function return value:
+*             int       Status return value:
+*                        -1: No change required (not an error).
+*                         0: Success.
+*                         1: Null wcsprm pointer passed.
+*
+*
+* datfix() - Translate DATE-OBS and derive MJD-OBS or vice versa
+* --------------------------------------------------------------
+* datfix() translates the old DATE-OBS date format set in wcsprm::dateobs to
+* year-2000 standard form (yyyy-mm-ddThh:mm:ss) and derives MJD-OBS from it if
+* not already set.  Alternatively, if wcsprm::mjdobs is set and
+* wcsprm::dateobs isn't, then datfix() derives wcsprm::dateobs from it.  If
+* both are set but disagree by more than half a day then status 5 is returned.
+*
+* Given and returned:
+*   wcs       struct wcsprm*
+*                       Coordinate transformation parameters.  wcsprm::dateobs
+*                       and/or wcsprm::mjdobs may be changed.
+*
+* Function return value:
+*             int       Status return value:
+*                        -1: No change required (not an error).
+*                         0: Success.
+*                         1: Null wcsprm pointer passed.
+*                         5: Invalid parameter value.
+*
+*                       For returns > 1, a detailed error message is set in
+*                       wcsprm::err if enabled, see wcserr_enable().
+*
+* Notes:
+*   The MJD algorithms used by datfix() are from D.A. Hatcher, 1984, QJRAS,
+*   25, 53-55, as modified by P.T. Wallace for use in SLALIB subroutines CLDJ
+*   and DJCL.
+*
+*
+* unitfix() - Correct aberrant CUNITia keyvalues
+* ----------------------------------------------
+* unitfix() applies wcsutrn() to translate non-standard CUNITia keyvalues,
+* e.g. 'DEG' -> 'deg', also stripping off unnecessary whitespace.
+*
+* Given:
+*   ctrl      int       Do potentially unsafe translations described in the
+*                       usage notes to wcsutrn().
+*
+* Given and returned:
+*   wcs       struct wcsprm*
+*                       Coordinate transformation parameters.
+*
+* Function return value:
+*             int       Status return value:
+*                        -1: No change required (not an error).
+*                         0: Success (an alias was applied).
+*                         1: Null wcsprm pointer passed.
+*
+*                       When units are translated (i.e. status 0), status -2
+*                       is set in the wcserr struct to allow an informative
+*                       message to be returned.
+*
+*
+* spcfix() - Translate AIPS-convention spectral types
+* ---------------------------------------------------
+* spcfix() translates AIPS-convention spectral coordinate types,
+* '{FREQ,FELO,VELO}-{LSR,HEL,OBS}' (e.g. 'FREQ-OBS', 'FELO-HEL', 'VELO-LSR')
+* set in wcsprm::ctype[], subject to VELREF set in wcsprm::velref.
+*
+* Note that if wcs::specsys is already set then it will not be overridden.
+*
+* Given and returned:
+*   wcs       struct wcsprm*
+*                       Coordinate transformation parameters.  wcsprm::ctype[]
+*                       and/or wcsprm::specsys may be changed.
+*
+* Function return value:
+*             int       Status return value:
+*                        -1: No change required (not an error).
+*                         0: Success.
+*                         1: Null wcsprm pointer passed.
+*                         2: Memory allocation failed.
+*                         3: Linear transformation matrix is singular.
+*                         4: Inconsistent or unrecognized coordinate axis
+*                            types.
+*                         5: Invalid parameter value.
+*                         6: Invalid coordinate transformation parameters.
+*                         7: Ill-conditioned coordinate transformation
+*                            parameters.
+*
+*                       For returns > 1, a detailed error message is set in
+*                       wcsprm::err if enabled, see wcserr_enable().
+*
+*
+* celfix() - Translate AIPS-convention celestial projection types
+* ---------------------------------------------------------------
+* celfix() translates AIPS-convention celestial projection types, NCP and
+* GLS, set in the ctype[] member of the wcsprm struct.
+*
+* Two additional pv[] keyvalues are created when translating NCP.  If the
+* pv[] array was initially allocated by wcsini() then the array will be
+* expanded if necessary.  Otherwise, error 2 will be returned if two empty
+* slots are not already available for use.
+*
+* Given and returned:
+*   wcs       struct wcsprm*
+*                       Coordinate transformation parameters.  wcsprm::ctype[]
+*                       and/or wcsprm::pv[] may be changed.
+*
+* Function return value:
+*             int       Status return value:
+*                        -1: No change required (not an error).
+*                         0: Success.
+*                         1: Null wcsprm pointer passed.
+*                         2: Memory allocation failed.
+*                         3: Linear transformation matrix is singular.
+*                         4: Inconsistent or unrecognized coordinate axis
+*                            types.
+*                         5: Invalid parameter value.
+*                         6: Invalid coordinate transformation parameters.
+*                         7: Ill-conditioned coordinate transformation
+*                            parameters.
+*
+*                       For returns > 1, a detailed error message is set in
+*                       wcsprm::err if enabled, see wcserr_enable().
+*
+*
+* cylfix() - Fix malformed cylindrical projections
+* ------------------------------------------------
+* cylfix() fixes WCS keyvalues for malformed cylindrical projections that
+* suffer from the problem described in Sect. 7.3.4 of Paper I.
+*
+* Given:
+*   naxis     const int []
+*                       Image axis lengths.
+*
+* Given and returned:
+*   wcs       struct wcsprm*
+*                       Coordinate transformation parameters.
+*
+* Function return value:
+*             int       Status return value:
+*                        -1: No change required (not an error).
+*                         0: Success.
+*                         1: Null wcsprm pointer passed.
+*                         2: Memory allocation failed.
+*                         3: Linear transformation matrix is singular.
+*                         4: Inconsistent or unrecognized coordinate axis
+*                            types.
+*                         5: Invalid parameter value.
+*                         6: Invalid coordinate transformation parameters.
+*                         7: Ill-conditioned coordinate transformation
+*                            parameters.
+*                         8: All of the corner pixel coordinates are invalid.
+*                         9: Could not determine reference pixel coordinate.
+*                        10: Could not determine reference pixel value.
+*
+*                       For returns > 1, a detailed error message is set in
+*                       wcsprm::err if enabled, see wcserr_enable().
+*
+*
+* Global variable: const char *wcsfix_errmsg[] - Status return messages
+* ---------------------------------------------------------------------
+* Error messages to match the status value returned from each function.
+*
+*===========================================================================*/
+
+#ifndef WCSLIB_WCSFIX
+#define WCSLIB_WCSFIX
+
+#include "wcs.h"
+#include "wcserr.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define CDFIX    0
+#define DATFIX   1
+#define UNITFIX  2
+#define SPCFIX   3
+#define CELFIX   4
+#define CYLFIX   5
+#define NWCSFIX  6
+
+extern const char *wcsfix_errmsg[];
+#define cylfix_errmsg wcsfix_errmsg
+
+enum wcsfix_errmsg_enum {
+  FIXERR_DATE_FIX         = -4, /* The date formatting has been fixed up. */
+  FIXERR_SPC_UPDATE       = -3, /* Spectral axis type modified. */
+  FIXERR_UNITS_ALIAS      = -2,	/* Units alias translation. */
+  FIXERR_NO_CHANGE        = -1,	/* No change. */
+  FIXERR_SUCCESS          =  0,	/* Success. */
+  FIXERR_NULL_POINTER     =  1,	/* Null wcsprm pointer passed. */
+  FIXERR_MEMORY           =  2,	/* Memory allocation failed. */
+  FIXERR_SINGULAR_MTX     =  3,	/* Linear transformation matrix is
+				   singular. */
+  FIXERR_BAD_CTYPE        =  4,	/* Inconsistent or unrecognized coordinate
+				   axis types. */
+  FIXERR_BAD_PARAM        =  5,	/* Invalid parameter value. */
+  FIXERR_BAD_COORD_TRANS  =  6,	/* Invalid coordinate transformation
+				   parameters. */
+  FIXERR_ILL_COORD_TRANS  =  7,	/* Ill-conditioned coordinate transformation
+				   parameters. */
+  FIXERR_BAD_CORNER_PIX   =  8,	/* All of the corner pixel coordinates are
+				   invalid. */
+  FIXERR_NO_REF_PIX_COORD =  9,	/* Could not determine reference pixel
+				   coordinate. */
+  FIXERR_NO_REF_PIX_VAL   = 10	/* Could not determine reference pixel
+				   value. */
+};
+
+int wcsfix(int ctrl, const int naxis[], struct wcsprm *wcs, int stat[]);
+
+int wcsfixi(int ctrl, const int naxis[], struct wcsprm *wcs, int stat[],
+            struct wcserr info[]);
+
+int cdfix(struct wcsprm *wcs);
+
+int datfix(struct wcsprm *wcs);
+
+int unitfix(int ctrl, struct wcsprm *wcs);
+
+int spcfix(struct wcsprm *wcs);
+
+int celfix(struct wcsprm *wcs);
+
+int cylfix(const int naxis[], struct wcsprm *wcs);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* WCSLIB_WCSFIX */
diff --git a/cextern/wcslib/C/wcshdr.c b/cextern/wcslib/C/wcshdr.c
new file mode 100644
index 0000000..15f2ad7
--- /dev/null
+++ b/cextern/wcslib/C/wcshdr.c
@@ -0,0 +1,1073 @@
+/*============================================================================
+
+  WCSLIB 4.16 - an implementation of the FITS WCS standard.
+  Copyright (C) 1995-2012, Mark Calabretta
+
+  This file is part of WCSLIB.
+
+  WCSLIB is free software: you can redistribute it and/or modify it under the
+  terms of the GNU Lesser General Public License as published by the Free
+  Software Foundation, either version 3 of the License, or (at your option)
+  any later version.
+
+  WCSLIB 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 Lesser General Public License for
+  more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with WCSLIB.  If not, see http://www.gnu.org/licenses.
+
+  Direct correspondence concerning WCSLIB to mark at calabretta.id.au
+
+  Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
+  http://www.atnf.csiro.au/people/Mark.Calabretta
+  $Id: wcshdr.c,v 4.16 2012/11/07 04:42:44 cal103 Exp $
+*===========================================================================*/
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "wcsutil.h"
+#include "wcsmath.h"
+#include "wcshdr.h"
+#include "tab.h"
+#include "wcs.h"
+
+extern const int WCSSET;
+
+/* Map status return value to message. */
+const char *wcshdr_errmsg[] = {
+  "Success",
+  "Null wcsprm pointer passed",
+  "Memory allocation failed",
+  "Invalid column selection",
+  "Fatal error returned by Flex parser",
+  "Invalid tabular parameters"};
+
+/* Convenience macro for invoking wcserr_set(). */
+#define WCSHDR_ERRMSG(status) WCSERR_SET(status), wcshdr_errmsg[status]
+
+static void wcshdo_util(int, const char [], const char [], int, const char [],
+  int, int, int, char, int, int [], char [], const char [], int *, char **,
+  int *);
+
+/*--------------------------------------------------------------------------*/
+
+int wcstab(struct wcsprm *wcs)
+
+{
+  static const char *function = "wcstab";
+
+  char (*PSi_0a)[72] = 0x0, (*PSi_1a)[72] = 0x0, (*PSi_2a)[72] = 0x0;
+  int  *PVi_1a = 0x0, *PVi_2a = 0x0, *PVi_3a = 0x0, *tabax, *tabidx = 0x0;
+  int   getcrd, i, ip, itab, itabax, j, jtabax, m, naxis, ntabax, status;
+  struct wtbarr *wtbp;
+  struct tabprm *tabp;
+  struct wcserr **err;
+
+  if (wcs == 0x0) return WCSHDRERR_NULL_POINTER;
+  err = &(wcs->err);
+
+  /* Free memory previously allocated by wcstab(). */
+  if (wcs->flag != -1 && wcs->m_flag == WCSSET) {
+    if (wcs->wtb == wcs->m_wtb) wcs->wtb = 0x0;
+    if (wcs->tab == wcs->m_tab) wcs->tab = 0x0;
+
+    if (wcs->m_wtb) free(wcs->m_wtb);
+    if (wcs->m_tab) {
+      for (j = 0; j < wcs->ntab; j++) {
+        tabfree(wcs->m_tab + j);
+      }
+
+      free(wcs->m_tab);
+    }
+  }
+
+  wcs->ntab = 0;
+  wcs->nwtb = 0;
+  wcs->wtb  = 0x0;
+  wcs->tab  = 0x0;
+
+
+  /* Determine the number of -TAB axes. */
+  naxis = wcs->naxis;
+  if (!(tabax = calloc(naxis, sizeof(int)))) {
+    return wcserr_set(WCSHDR_ERRMSG(WCSHDRERR_MEMORY));
+  }
+
+  ntabax = 0;
+  for (i = 0; i < naxis; i++) {
+    /* Null fill. */
+    wcsutil_null_fill(72, wcs->ctype[i]);
+
+    if (!strcmp(wcs->ctype[i]+4, "-TAB")) {
+      tabax[i] = ntabax++;
+    } else {
+      tabax[i] = -1;
+    }
+  }
+
+  if (ntabax == 0) {
+    /* No lookup tables. */
+    status = 0;
+    goto cleanup;
+  }
+
+
+  /* Collect information from the PSi_ma and PVi_ma keyvalues. */
+  if (!((PSi_0a = calloc(ntabax, sizeof(char[72]))) &&
+        (PVi_1a = calloc(ntabax, sizeof(int)))      &&
+        (PVi_2a = calloc(ntabax, sizeof(int)))      &&
+        (PSi_1a = calloc(ntabax, sizeof(char[72]))) &&
+        (PSi_2a = calloc(ntabax, sizeof(char[72]))) &&
+        (PVi_3a = calloc(ntabax, sizeof(int)))      &&
+        (tabidx = calloc(ntabax, sizeof(int))))) {
+    status = wcserr_set(WCSHDR_ERRMSG(WCSHDRERR_MEMORY));
+    goto cleanup;
+  }
+
+  for (itabax = 0; itabax < ntabax; itabax++) {
+    /* Remember that calloc() zeroes allocated memory. */
+    PVi_1a[itabax] = 1;
+    PVi_2a[itabax] = 1;
+    PVi_3a[itabax] = 1;
+  }
+
+  for (ip = 0; ip < wcs->nps; ip++) {
+    itabax = tabax[wcs->ps[ip].i - 1];
+    if (itabax >= 0) {
+      switch (wcs->ps[ip].m) {
+      case 0:
+        /* EXTNAME. */
+        strcpy(PSi_0a[itabax], wcs->ps[ip].value);
+        wcsutil_null_fill(72, PSi_0a[itabax]);
+        break;
+      case 1:
+        /* TTYPEn for coordinate array. */
+        strcpy(PSi_1a[itabax], wcs->ps[ip].value);
+        wcsutil_null_fill(72, PSi_1a[itabax]);
+        break;
+      case 2:
+        /* TTYPEn for index vector. */
+        strcpy(PSi_2a[itabax], wcs->ps[ip].value);
+        wcsutil_null_fill(72, PSi_2a[itabax]);
+        break;
+      }
+    }
+  }
+
+  for (ip = 0; ip < wcs->npv; ip++) {
+    itabax = tabax[wcs->pv[ip].i - 1];
+    if (itabax >= 0) {
+      switch (wcs->pv[ip].m) {
+      case 1:
+        /* EXTVER. */
+        PVi_1a[itabax] = (int)(wcs->pv[ip].value + 0.5);
+        break;
+      case 2:
+        /* EXTLEVEL. */
+        PVi_2a[itabax] = (int)(wcs->pv[ip].value + 0.5);
+        break;
+      case 3:
+        /* Table axis number. */
+        PVi_3a[itabax] = (int)(wcs->pv[ip].value + 0.5);
+        break;
+      }
+    }
+  }
+
+
+  /* Determine the number of independent tables. */
+  for (itabax = 0; itabax < ntabax; itabax++) {
+    /* These have no defaults. */
+    if (!PSi_0a[itabax][0] || !PSi_1a[itabax][0]) {
+      status = wcserr_set(WCSERR_SET(WCSHDRERR_BAD_TABULAR_PARAMS),
+        "Invalid tabular parameters: PSi_0a and PSi_1a must be specified");
+      goto cleanup;
+    }
+
+    tabidx[itabax] = -1;
+    for (jtabax = 0; jtabax < i; jtabax++) {
+      /* EXTNAME, EXTVER, EXTLEVEL, and TTYPEn for the coordinate array */
+      /* must match for each axis of a multi-dimensional lookup table.  */
+      if (strcmp(PSi_0a[itabax], PSi_0a[jtabax]) == 0 &&
+          strcmp(PSi_1a[itabax], PSi_1a[jtabax]) == 0 &&
+          PVi_1a[itabax] == PVi_1a[jtabax] &&
+          PVi_2a[itabax] == PVi_2a[jtabax]) {
+        tabidx[itabax] = tabidx[jtabax];
+        break;
+      }
+    }
+
+    if (jtabax == itabax) {
+      tabidx[itabax] = wcs->ntab;
+      wcs->ntab++;
+    }
+  }
+
+  if (!(wcs->tab = calloc(wcs->ntab, sizeof(struct tabprm)))) {
+    status = wcserr_set(WCSHDR_ERRMSG(WCSHDRERR_MEMORY));
+    goto cleanup;
+  }
+  wcs->m_tab = wcs->tab;
+
+  /* Table dimensionality; find the largest axis number. */
+  for (itabax = 0; itabax < ntabax; itabax++) {
+    tabp = wcs->tab + tabidx[itabax];
+
+    /* PVi_3a records the 1-relative table axis number. */
+    if (PVi_3a[itabax] > tabp->M) {
+      tabp->M = PVi_3a[itabax];
+    }
+  }
+
+  for (itab = 0; itab < wcs->ntab; itab++) {
+    if ((status = tabini(1, wcs->tab[itab].M, 0, wcs->tab + itab))) {
+      if (status == 3) status = 5;
+      wcserr_set(WCSHDR_ERRMSG(status));
+      goto cleanup;
+    }
+  }
+
+
+  /* Copy parameters into the tabprm structs. */
+  for (i = 0; i < naxis; i++) {
+    if ((itabax = tabax[i]) < 0) {
+      /* Not a -TAB axis. */
+      continue;
+    }
+
+    /* PVi_3a records the 1-relative table axis number. */
+    m = PVi_3a[itabax] - 1;
+
+    tabp = wcs->tab + tabidx[itabax];
+    tabp->map[m] = i;
+    tabp->crval[m] = wcs->crval[i];
+  }
+
+  /* Check for completeness. */
+  for (itab = 0; itab < wcs->ntab; itab++) {
+    for (m = 0; m < wcs->tab[itab].M; m++) {
+      if (wcs->tab[itab].map[m] < 0) {
+        status = wcserr_set(WCSERR_SET(WCSHDRERR_BAD_TABULAR_PARAMS),
+          "Invalid tabular parameters: the axis mapping is undefined");
+        goto cleanup;
+      }
+    }
+  }
+
+
+  /* Set up for reading the arrays; how many arrays are there? */
+  for (itabax = 0; itabax < ntabax; itabax++) {
+    /* Does this -TAB axis have a non-degenerate index array? */
+    if (PSi_2a[itabax][0]) {
+      wcs->nwtb++;
+    }
+  }
+
+  /* Add one coordinate array for each table. */
+  wcs->nwtb += wcs->ntab;
+
+  /* Allocate memory for structs to be returned. */
+  if (!(wcs->wtb = calloc(wcs->nwtb, sizeof(struct wtbarr)))) {
+    wcs->nwtb = 0;
+
+    status = wcserr_set(WCSHDR_ERRMSG(WCSHDRERR_MEMORY));
+    goto cleanup;
+  }
+  wcs->m_wtb = wcs->wtb;
+
+  /* Set pointers for the index and coordinate arrays. */
+  wtbp = wcs->wtb;
+  for (itab = 0; itab < wcs->ntab; itab++) {
+    getcrd = 1;
+    for (itabax = 0; itabax < ntabax; itabax++) {
+      if (tabidx[itabax] != itab) continue;
+
+      if (getcrd) {
+        /* Coordinate array. */
+        wtbp->i = itabax + 1;
+        wtbp->m = PVi_3a[itabax];
+        wtbp->kind = 'c';
+
+        strcpy(wtbp->extnam, PSi_0a[itabax]);
+        wtbp->extver = PVi_1a[itabax];
+        wtbp->extlev = PVi_2a[itabax];
+        strcpy(wtbp->ttype, PSi_1a[itabax]);
+        wtbp->row    = 1L;
+        wtbp->ndim   = wcs->tab[itab].M + 1;
+        wtbp->dimlen = wcs->tab[itab].K;
+        wtbp->arrayp = &(wcs->tab[itab].coord);
+
+        /* Signal for tabset() to take this memory. */
+        wcs->tab[itab].m_coord = (double *)0x1;
+
+        wtbp++;
+        getcrd = 0;
+      }
+
+      if (PSi_2a[itabax][0]) {
+        /* Index array. */
+        wtbp->i = itabax + 1;
+        wtbp->m = PVi_3a[itabax];
+        wtbp->kind = 'i';
+
+        m = wtbp->m - 1;
+        strcpy(wtbp->extnam, PSi_0a[itabax]);
+        wtbp->extver = PVi_1a[itabax];
+        wtbp->extlev = PVi_2a[itabax];
+        strcpy(wtbp->ttype, PSi_2a[itabax]);
+        wtbp->row    = 1L;
+        wtbp->ndim   = 1;
+        wtbp->dimlen = wcs->tab[itab].K + m;
+        wtbp->arrayp = wcs->tab[itab].index + m;
+
+        /* Signal for tabset() to take this memory. */
+        wcs->tab[itab].m_indxs[m] = (double *)0x1;
+
+        wtbp++;
+      }
+    }
+  }
+
+  status = 0;
+
+cleanup:
+  if (tabax)  free(tabax);
+  if (tabidx) free(tabidx);
+  if (PSi_0a) free(PSi_0a);
+  if (PVi_1a) free(PVi_1a);
+  if (PVi_2a) free(PVi_2a);
+  if (PSi_1a) free(PSi_1a);
+  if (PSi_2a) free(PSi_2a);
+  if (PVi_3a) free(PVi_3a);
+
+  if (status) {
+    if (wcs->tab) free(wcs->tab);
+    if (wcs->wtb) free(wcs->wtb);
+  }
+
+  return status;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int wcsidx(int nwcs, struct wcsprm **wcs, int alts[27])
+
+{
+  int a, iwcs;
+  struct wcsprm *wcsp;
+
+  for (a = 0; a < 27; a++) {
+    alts[a] = -1;
+  }
+
+  if (wcs == 0x0) {
+    return WCSHDRERR_NULL_POINTER;
+  }
+
+  wcsp = *wcs;
+  for (iwcs = 0; iwcs < nwcs; iwcs++, wcsp++) {
+    if (wcsp->colnum || wcsp->colax[0]) continue;
+
+    if (wcsp->alt[0] == ' ') {
+      a = 0;
+    } else {
+      a = wcsp->alt[0] - 'A' + 1;
+    }
+
+    alts[a] = iwcs;
+  }
+
+  return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int wcsbdx(int nwcs, struct wcsprm **wcs, int type, short alts[1000][28])
+
+{
+  short  *ip;
+  int    a, i, icol, iwcs;
+  struct wcsprm *wcsp;
+
+  for (ip = alts[0]; ip < alts[0] + 28*1000; ip++) {
+    *ip = -1;
+  }
+
+  for (icol = 0; icol < 1000; icol++) {
+    alts[icol][27] = 0;
+  }
+
+  if (wcs == 0x0) {
+    return WCSHDRERR_NULL_POINTER;
+  }
+
+  wcsp = *wcs;
+  for (iwcs = 0; iwcs < nwcs; iwcs++, wcsp++) {
+    if (wcsp->alt[0] == ' ') {
+      a = 0;
+    } else {
+      a = wcsp->alt[0] - 'A' + 1;
+    }
+
+    if (type) {
+      /* Pixel list. */
+      if (wcsp->colax[0]) {
+        for (i = 0; i < wcsp->naxis; i++) {
+          alts[wcsp->colax[i]][a]  = iwcs;
+          alts[wcsp->colax[i]][27]++;
+        }
+      } else if (!wcsp->colnum) {
+        alts[0][a]  = iwcs;
+        alts[0][27]++;
+      }
+
+    } else {
+      /* Binary table image array. */
+      if (wcsp->colnum) {
+        alts[wcsp->colnum][a] = iwcs;
+        alts[wcsp->colnum][27]++;
+      } else if (!wcsp->colax[0]) {
+        alts[0][a]  = iwcs;
+        alts[0][27]++;
+      }
+    }
+  }
+
+  return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int wcsvfree(int *nwcs, struct wcsprm **wcs)
+
+{
+  int a, status = 0;
+  struct wcsprm *wcsp;
+
+  if (wcs == 0x0) {
+    return WCSHDRERR_NULL_POINTER;
+  }
+
+  wcsp = *wcs;
+  for (a = 0; a < *nwcs; a++, wcsp++) {
+    status |= wcsfree(wcsp);
+  }
+
+  free(*wcs);
+
+  *nwcs = 0;
+  *wcs = 0x0;
+
+  return status;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int wcshdo(int relax, struct wcsprm *wcs, int *nkeyrec, char **header)
+
+/* ::: CUBEFACE and STOKES handling? */
+
+{
+  static const char *function = "wcshdo";
+
+  char alt, comment[72], keyvalue[72], keyword[16], obsg[8] = "OBSG?",
+       obsgeo[8] = "OBSGEO-?", ptype, xtype, xyz[] = "XYZ";
+  int  bintab, col0, *colax, colnum, i, j, k, naxis, pixlist, primage,
+       status = 0;
+  struct wcserr **err;
+
+  *nkeyrec = 0;
+  *header  = 0x0;
+
+  if (wcs == 0x0) return WCSHDRERR_NULL_POINTER;
+  err = &(wcs->err);
+
+  if (wcs->flag != WCSSET) {
+    if ((status = wcsset(wcs))) return status;
+  }
+
+  if ((naxis = wcs->naxis) == 0) {
+    return 0;
+  }
+
+
+  /* These are mainly for convenience. */
+  alt = wcs->alt[0];
+  if (alt == ' ') alt = '\0';
+  colnum = wcs->colnum;
+  colax  = wcs->colax;
+
+  primage = 0;
+  bintab  = 0;
+  pixlist = 0;
+  if (colnum) {
+    bintab  = 1;
+    col0 = colnum;
+  } else if (colax[0]) {
+    pixlist = 1;
+    col0 = colax[0];
+  } else {
+    primage = 1;
+  }
+
+
+  /* WCS dimension. */
+  if (!pixlist) {
+    sprintf(keyvalue, "%20d", naxis);
+    wcshdo_util(relax, "WCSAXES", "WCAX", 0, 0x0, 0, 0, 0, alt, colnum, colax,
+      keyvalue, "Number of coordinate axes", nkeyrec, header, &status);
+  }
+
+  /* Reference pixel coordinates. */
+  for (j = 0; j < naxis; j++) {
+    wcsutil_double2str(keyvalue, "%20.12G", wcs->crpix[j]);
+    wcshdo_util(relax, "CRPIX", "CRP", WCSHDO_CRPXna, "CRPX", 0, j+1, 0, alt,
+      colnum, colax, keyvalue, "Pixel coordinate of reference point", nkeyrec,
+      header, &status);
+  }
+
+  /* Linear transformation matrix. */
+  k = 0;
+  for (i = 0; i < naxis; i++) {
+    for (j = 0; j < naxis; j++, k++) {
+      if (i == j) {
+        if (wcs->pc[k] == 1.0) continue;
+      } else {
+        if (wcs->pc[k] == 0.0) continue;
+      }
+
+      wcsutil_double2str(keyvalue, "%20.12G", wcs->pc[k]);
+      wcshdo_util(relax, "PC", bintab ? "PC" : "P", WCSHDO_TPCn_ka,
+        bintab ? 0x0 : "PC", i+1, j+1, 0, alt, colnum, colax,
+        keyvalue, "Coordinate transformation matrix element",
+        nkeyrec, header, &status);
+    }
+  }
+
+  /* Coordinate increment at reference point. */
+  for (i = 0; i < naxis; i++) {
+    wcsutil_double2str(keyvalue, "%20.12G", wcs->cdelt[i]);
+    comment[0] = '\0';
+    if (wcs->cunit[i][0]) sprintf(comment, "[%s] ", wcs->cunit[i]);
+    strcat(comment, "Coordinate increment at reference point");
+    wcshdo_util(relax, "CDELT", "CDE", WCSHDO_CRPXna, "CDLT", i+1, 0, 0, alt,
+      colnum, colax, keyvalue, comment, nkeyrec, header, &status);
+  }
+
+  /* Units of coordinate increment and reference value. */
+  for (i = 0; i < naxis; i++) {
+    if (wcs->cunit[i][0] == '\0') continue;
+
+    sprintf(keyvalue, "'%s'", wcs->cunit[i]);
+    wcshdo_util(relax, "CUNIT", "CUN", WCSHDO_CRPXna, "CUNI", i+1, 0, 0, alt,
+      colnum, colax, keyvalue, "Units of coordinate increment and value",
+      nkeyrec, header, &status);
+  }
+
+  /* Coordinate type. */
+  for (i = 0; i < naxis; i++) {
+    if (wcs->ctype[i][0] == '\0') continue;
+
+    sprintf(keyvalue, "'%s'", wcs->ctype[i]);
+    strcpy(comment, "Coordinate type code");
+    if (i == wcs->lng || i == wcs->lat) {
+      if (strncmp(wcs->ctype[i], "RA--", 4) == 0) {
+        strcpy(comment, "Right ascension, ");
+      } else if (strncmp(wcs->ctype[i], "DEC-", 4) == 0) {
+        strcpy(comment, "Declination, ");
+      } else if (strncmp(wcs->ctype[i]+1, "LON", 3) == 0 ||
+                 strncmp(wcs->ctype[i]+1, "LAT", 3) == 0) {
+        switch (wcs->ctype[i][0]) {
+        case 'G':
+          strcpy(comment, "galactic ");
+          break;
+        case 'E':
+          strcpy(comment, "ecliptic ");
+        case 'H':
+          strcpy(comment, "helioecliptic ");
+        case 'S':
+          strcpy(comment, "supergalactic ");
+        }
+
+        if (i == wcs->lng) {
+          strcat(comment, "longitude, ");
+        } else {
+          strcat(comment, "latitude, ");
+        }
+
+        wcs->ctype[i][0] = toupper(wcs->ctype[i][0]);
+      }
+
+      strcat(comment, wcs->cel.prj.name);
+      strcat(comment, " projection");
+
+    } else if (i == wcs->spec) {
+      spctyp(wcs->ctype[i], 0x0, 0x0, comment, 0x0, &ptype, &xtype, 0x0);
+      if (ptype == xtype) {
+        strcat(comment, " (linear)");
+      } else {
+        switch (xtype) {
+        case 'F':
+          strcat(comment, " (linear in frequency)");
+          break;
+        case 'V':
+          strcat(comment, " (linear in velocity)");
+          break;
+        case 'W':
+          strcat(comment, " (linear in wavelength)");
+          break;
+        }
+      }
+    }
+
+    wcshdo_util(relax, "CTYPE", "CTY", WCSHDO_CRPXna, "CTYP", i+1, 0, 0, alt,
+      colnum, colax, keyvalue, comment, nkeyrec, header, &status);
+  }
+
+  /* Coordinate value at reference point. */
+  for (i = 0; i < naxis; i++) {
+    wcsutil_double2str(keyvalue, "%20.12G", wcs->crval[i]);
+    comment[0] = '\0';
+    if (wcs->cunit[i][0]) sprintf(comment, "[%s] ", wcs->cunit[i]);
+    strcat(comment, "Coordinate value at reference point");
+    wcshdo_util(relax, "CRVAL", "CRV", WCSHDO_CRPXna, "CRVL", i+1, 0, 0, alt,
+      colnum, colax, keyvalue, comment, nkeyrec, header, &status);
+  }
+
+  /* Parameter values. */
+  for (k = 0; k < wcs->npv; k++) {
+    wcsutil_double2str(keyvalue, "%20.12G", (wcs->pv[k]).value);
+    if ((wcs->pv[k]).i == (wcs->lng + 1)) {
+      switch ((wcs->pv[k]).m) {
+      case 1:
+        strcpy(comment, "[deg] Native longitude of the reference point");
+        break;
+      case 2:
+        strcpy(comment, "[deg] Native latitude  of the reference point");
+        break;
+      case 3:
+        if (primage) {
+          sprintf(keyword, "LONPOLE%c", alt);
+        } else if (bintab) {
+          sprintf(keyword, "LONP%d%c", colnum, alt);
+        } else {
+          sprintf(keyword, "LONP%d%c", colax[(wcs->pv[k]).i - 1], alt);
+        }
+        sprintf(comment, "[deg] alias for %s (has precedence)", keyword);
+        break;
+      case 4:
+        if (primage) {
+          sprintf(keyword, "LATPOLE%c", alt);
+        } else if (bintab) {
+          sprintf(keyword, "LATP%d%c", colnum, alt);
+        } else {
+          sprintf(keyword, "LATP%d%c", colax[(wcs->pv[k]).i - 1], alt);
+        }
+        sprintf(comment, "[deg] alias for %s (has precedence)", keyword);
+        break;
+      }
+    } else if ((wcs->pv[k]).i == (wcs->lat + 1)) {
+      sprintf(comment, "%s projection parameter", wcs->cel.prj.code);
+    } else {
+      strcpy(comment, "Coordinate transformation parameter");
+    }
+
+    wcshdo_util(relax, "PV", "V", WCSHDO_PVn_ma, "PV", wcs->pv[k].i, -1,
+      wcs->pv[k].m, alt, colnum, colax, keyvalue, comment,
+      nkeyrec, header, &status);
+  }
+
+  for (k = 0; k < wcs->nps; k++) {
+    sprintf(keyvalue, "'%s'", (wcs->ps[k]).value);
+
+    wcshdo_util(relax, "PS", "S", WCSHDO_PVn_ma, "PS", wcs->ps[k].i, -1,
+      wcs->ps[k].m, alt, colnum, colax, keyvalue,
+      "Coordinate transformation parameter",
+      nkeyrec, header, &status);
+  }
+
+  /* Celestial and spectral transformation parameters. */
+  if (!undefined(wcs->lonpole)) {
+    wcsutil_double2str(keyvalue, "%20.12G", wcs->lonpole);
+    wcshdo_util(relax, "LONPOLE", "LONP", 0, 0x0, 0, 0, 0, alt,
+      colnum, colax, keyvalue, "[deg] Native longitude of celestial pole",
+      nkeyrec, header, &status);
+  }
+
+  if (!undefined(wcs->latpole)) {
+    wcsutil_double2str(keyvalue, "%20.12G", wcs->latpole);
+    wcshdo_util(relax, "LATPOLE", "LATP", 0, 0x0, 0, 0, 0, alt,
+      colnum, colax, keyvalue, "[deg] Native latitude of celestial pole",
+      nkeyrec, header, &status);
+  }
+
+  if (!undefined(wcs->restfrq)) {
+    wcsutil_double2str(keyvalue, "%20.12G", wcs->restfrq);
+    wcshdo_util(relax, "RESTFRQ", "RFRQ", 0, 0x0, 0, 0, 0, alt,
+      colnum, colax, keyvalue, "[Hz] Line rest frequency",
+      nkeyrec, header, &status);
+  }
+
+  if (!undefined(wcs->restwav)) {
+    wcsutil_double2str(keyvalue, "%20.12G", wcs->restwav);
+    wcshdo_util(relax, "RESTWAV", "RWAV", 0, 0x0, 0, 0, 0, alt,
+      colnum, colax, keyvalue, "[Hz] Line rest wavelength",
+      nkeyrec, header, &status);
+  }
+
+  /* Coordinate system title. */
+  if (wcs->wcsname[0]) {
+    sprintf(keyvalue, "'%s'", wcs->wcsname);
+    if (bintab) {
+      wcshdo_util(relax, "WCSNAME", "WCSN", 0, 0x0, 0, 0, 0, alt,
+        colnum, colax, keyvalue, "Coordinate system title",
+        nkeyrec, header, &status);
+    } else {
+      /* TWCS was a mistake. */
+      wcshdo_util(relax, "WCSNAME", "TWCS", WCSHDO_WCSNna, "WCSN", 0, 0, 0,
+        alt, colnum, colax, keyvalue, "Coordinate system title",
+        nkeyrec, header, &status);
+    }
+  }
+
+  /* Coordinate axis title. */
+  if (wcs->cname) {
+    for (i = 0; i < naxis; i++) {
+      if (wcs->cname[i][0] == '\0') continue;
+
+      sprintf(keyvalue, "'%s'", wcs->cname[i]);
+      wcshdo_util(relax, "CNAME", "CNA", WCSHDO_CNAMna, "CNAM", i+1, 0, 0,
+        alt, colnum, colax, keyvalue, "Axis name for labelling purposes",
+        nkeyrec, header, &status);
+    }
+  }
+
+  /* Random error in coordinate. */
+  if (wcs->crder) {
+    for (i = 0; i < naxis; i++) {
+      if (undefined(wcs->crder[i])) continue;
+
+      wcsutil_double2str(keyvalue, "%20.12G", wcs->crder[i]);
+      comment[0] = '\0';
+      if (wcs->cunit[i][0]) sprintf(comment, "[%s] ", wcs->cunit[i]);
+      strcat(comment, "Random error in coordinate");
+      wcshdo_util(relax, "CRDER", "CRD", WCSHDO_CNAMna, "CRDE", i+1, 0, 0,
+        alt, colnum, colax, keyvalue, comment, nkeyrec, header, &status);
+    }
+  }
+
+  /* Systematic error in coordinate. */
+  if (wcs->csyer) {
+    for (i = 0; i < naxis; i++) {
+      if (undefined(wcs->csyer[i])) continue;
+
+      wcsutil_double2str(keyvalue, "%20.12G", wcs->csyer[i]);
+      comment[0] = '\0';
+      if (wcs->cunit[i][0]) sprintf(comment, "[%s] ", wcs->cunit[i]);
+      strcat(comment, "Systematic error in coordinate");
+      wcshdo_util(relax, "CSYER", "CSY", WCSHDO_CNAMna, "CSYE", i+1, 0, 0,
+        alt, colnum, colax, keyvalue, comment, nkeyrec, header, &status);
+    }
+  }
+
+  /* Equatorial coordinate system type. */
+  if (wcs->radesys[0]) {
+    sprintf(keyvalue, "'%s'", wcs->radesys);
+    wcshdo_util(relax, "RADESYS", "RADE", 0, 0x0, 0, 0, 0, alt,
+      colnum, colax, keyvalue, "Equatorial coordinate system",
+      nkeyrec, header, &status);
+  }
+
+  /* Equinox of equatorial coordinate system. */
+  if (!undefined(wcs->equinox)) {
+    wcsutil_double2str(keyvalue, "%20.12G", wcs->equinox);
+    wcshdo_util(relax, "EQUINOX", "EQUI", 0, 0x0, 0, 0, 0, alt,
+      colnum, colax, keyvalue, "[yr] Equinox of equatorial coordinates",
+      nkeyrec, header, &status);
+  }
+
+  /* Reference frame of spectral coordinates. */
+  if (wcs->specsys[0]) {
+    sprintf(keyvalue, "'%s'", wcs->specsys);
+    wcshdo_util(relax, "SPECSYS", "SPEC", 0, 0x0, 0, 0, 0, alt,
+      colnum, colax, keyvalue, "Reference frame of spectral coordinates",
+      nkeyrec, header, &status);
+  }
+
+  /* Reference frame of spectral observation. */
+  if (wcs->ssysobs[0]) {
+    sprintf(keyvalue, "'%s'", wcs->ssysobs);
+    wcshdo_util(relax, "SSYSOBS", "SOBS", 0, 0x0, 0, 0, 0, alt,
+      colnum, colax, keyvalue, "Reference frame of spectral observation",
+      nkeyrec, header, &status);
+  }
+
+  /* Observer's velocity towards source. */
+  if (!undefined(wcs->velosys)) {
+    wcsutil_double2str(keyvalue, "%20.12G", wcs->velosys);
+    wcshdo_util(relax, "VELOSYS", "VSYS", 0, 0x0, 0, 0, 0, alt,
+      colnum, colax, keyvalue, "[m/s] Velocity towards source",
+      nkeyrec, header, &status);
+  }
+
+  /* Reference frame of source redshift. */
+  if (wcs->ssyssrc[0]) {
+    sprintf(keyvalue, "'%s'", wcs->ssyssrc);
+    wcshdo_util(relax, "SSYSSRC", "SSRC", 0, 0x0, 0, 0, 0, alt,
+      colnum, colax, keyvalue, "Reference frame of source redshift",
+      nkeyrec, header, &status);
+  }
+
+  /* Redshift of the source. */
+  if (!undefined(wcs->zsource)) {
+    wcsutil_double2str(keyvalue, "%20.12G", wcs->zsource);
+    wcshdo_util(relax, "ZSOURCE", "ZSOU", 0, 0x0, 0, 0, 0, alt,
+      colnum, colax, keyvalue, "Redshift of the source",
+      nkeyrec, header, &status);
+  }
+
+  /* Observatory coordinates. */
+  for (k = 0; k < 3; k++) {
+    if (undefined(wcs->obsgeo[k])) continue;
+
+    wcsutil_double2str(keyvalue, "%20.12G", wcs->obsgeo[k]);
+    sprintf(comment, "[m] ITRF observatory %c-coordinate", xyz[k]);
+    obsgeo[7] = xyz[k];
+    obsg[4]   = xyz[k];
+    wcshdo_util(relax, obsgeo, obsg, 0, 0x0, 0, 0, 0, ' ',
+      colnum, colax, keyvalue, comment, nkeyrec, header, &status);
+  }
+
+  /* MJD of observation. */
+  if (!undefined(wcs->mjdobs)) {
+    wcsutil_double2str(keyvalue, "%20.12G", wcs->mjdobs);
+
+    strcpy(comment, "[d] MJD of observation");
+    if (wcs->dateobs[0]) {
+      if (primage || (relax & 1) == 0) {
+        sprintf(comment+22, " matching DATE-OBS");
+      } else {
+        sprintf(comment+22, " matching DOBS%d", col0);
+      }
+    }
+
+    wcshdo_util(relax, "MJD-OBS", "MJDOB", 0, 0x0, 0, 0, 0, ' ',
+      colnum, colax, keyvalue, comment, nkeyrec, header, &status);
+  }
+
+  /* MJD mid-observation time. */
+  if (!undefined(wcs->mjdavg)) {
+    wcsutil_double2str(keyvalue, "%20.12G", wcs->mjdavg);
+
+    strcpy(comment, "[d] MJD mid-observation");
+    if (wcs->dateavg[0]) {
+      if (primage) {
+        sprintf(comment+23, " matching DATE-AVG");
+      } else {
+        sprintf(comment+23, " matching DAVG%d", col0);
+      }
+    }
+
+    wcshdo_util(relax, "MJD-AVG", "MJDA", 0, 0x0, 0, 0, 0, ' ',
+      colnum, colax, keyvalue, comment, nkeyrec, header, &status);
+  }
+
+  /* ISO-8601 date corresponding to MJD-OBS. */
+  if (wcs->dateobs[0]) {
+    sprintf(keyvalue, "'%s'", wcs->dateobs);
+
+    strcpy(comment, "ISO-8601 observation date");
+    if (!undefined(wcs->mjdobs)) {
+      if (primage) {
+        sprintf(comment+25, " matching MJD-OBS");
+      } else {
+        sprintf(comment+25, " matching MJDOB%d", col0);
+      }
+    }
+
+    if (relax & 1) {
+      /* Allow DOBSn. */
+      wcshdo_util(relax, "DATE-OBS", "DOBS", WCSHDO_DOBSn, 0x0, 0, 0, 0,
+        ' ', colnum, colax, keyvalue, comment, nkeyrec, header, &status);
+    } else {
+      /* Force DATE-OBS. */
+      wcshdo_util(relax, "DATE-OBS", 0x0, 0, 0x0, 0, 0, 0, ' ', 0,
+        0x0, keyvalue, comment, nkeyrec, header, &status);
+    }
+  }
+
+  /* ISO-8601 date corresponding to MJD-OBS. */
+  if (wcs->dateavg[0]) {
+    sprintf(keyvalue, "'%s'", wcs->dateavg);
+
+    strcpy(comment, "ISO-8601 mid-observation date");
+    if (!undefined(wcs->mjdavg)) {
+      if (primage) {
+        sprintf(comment+29, " matching MJD-AVG");
+      } else {
+        sprintf(comment+29, " matching MJDA%d", col0);
+      }
+    }
+
+    wcshdo_util(relax, "DATE-AVG", "DAVG", 0, 0x0, 0, 0, 0, ' ',
+      colnum, colax, keyvalue, comment, nkeyrec, header, &status);
+  }
+
+  if (status == WCSHDRERR_MEMORY) {
+    wcserr_set(WCSHDR_ERRMSG(status));
+  }
+  return status;
+}
+
+/*--------------------------------------------------------------------------*/
+
+void wcshdo_util(
+  int relax,
+  const char pikey[],
+  const char tbkey[],
+  int level,
+  const char tlkey[],
+  int i,
+  int j,
+  int m,
+  char alt,
+  int  btcol,
+  int  plcol[],
+  char keyvalue[],
+  const char keycomment[],
+  int  *nkeyrec,
+  char **header,
+  int  *status)
+
+{
+  char ch0, ch1, *hptr, keyword[16], *kptr;
+  int  nbyte, nc = 47, nv;
+
+  if (*status) return;
+
+  /* Reallocate memory in blocks of 2880 bytes. */
+  if ((*nkeyrec)%32 == 0) {
+    nbyte = ((*nkeyrec)/32 + 1) * 2880;
+    if (!(hptr = realloc(*header, nbyte))) {
+      *status = WCSHDRERR_MEMORY;
+      return;
+    }
+
+    *header = hptr;
+  }
+
+  /* Construct the keyword. */
+  if (alt == ' ') alt = '\0';
+  if (btcol) {
+    /* Binary table image array. */
+    if (i > 0 && j) {
+      if (j > 0) {
+        sprintf(keyword, "%d%d%s%d%c", i, j, tbkey, btcol, alt);
+      } else {
+        sprintf(keyword, "%d%s%d_%d%c", i, tbkey, btcol, m, alt);
+      }
+    } else if (i > 0) {
+      sprintf(keyword, "%d%s%d%c", i, tbkey, btcol, alt);
+    } else if (j > 0) {
+      sprintf(keyword, "%d%s%d%c", j, tbkey, btcol, alt);
+    } else {
+      sprintf(keyword, "%s%d%c", tbkey, btcol, alt);
+    }
+
+    if ((strlen(keyword) < 8) && tlkey && (relax & level)) {
+      /* Use the long form. */
+      if (i > 0 && j) {
+        if (j > 0) {
+          sprintf(keyword, "%d%d%s%d%c", i, j, tlkey, btcol, alt);
+        } else {
+          sprintf(keyword, "%d%s%d_%d%c", i, tlkey, btcol, m, alt);
+        }
+      } else if (i > 0) {
+        sprintf(keyword, "%d%s%d%c", i, tlkey, btcol, alt);
+      } else if (j > 0) {
+        sprintf(keyword, "%d%s%d%c", j, tlkey, btcol, alt);
+      } else {
+        sprintf(keyword, "%s%d%c", tlkey, btcol, alt);
+      }
+    }
+
+  } else if (plcol && plcol[0]) {
+    /* Pixel list. */
+    if (i > 0 && j) {
+      if (j > 0) {
+        sprintf(keyword, "T%s%d_%d%c", tbkey, plcol[i-1], plcol[j-1], alt);
+      } else {
+        sprintf(keyword, "T%s%d_%d%c", tbkey, plcol[i-1], m, alt);
+      }
+    } else if (i > 0) {
+      sprintf(keyword, "T%s%d%c", tbkey, plcol[i-1], alt);
+    } else if (j > 0) {
+      sprintf(keyword, "T%s%d%c", tbkey, plcol[j-1], alt);
+    } else {
+      sprintf(keyword, "%s%d%c", tbkey, plcol[0], alt);
+    }
+
+    if ((strlen(keyword) < 8) && tlkey && (relax & level)) {
+      /* Use the long form. */
+      if (i > 0 && j) {
+        if (j > 0) {
+          sprintf(keyword, "T%s%d_%d%c", tlkey, plcol[i-1], plcol[j-1], alt);
+        } else {
+          sprintf(keyword, "T%s%d_%d%c", tlkey, plcol[i-1], m, alt);
+        }
+      } else if (i > 0) {
+        sprintf(keyword, "T%s%d%c", tlkey, plcol[i-1], alt);
+      } else if (j > 0) {
+        sprintf(keyword, "T%s%d%c", tlkey, plcol[j-1], alt);
+      } else {
+        sprintf(keyword, "%s%d%c", tlkey, plcol[0], alt);
+      }
+    }
+  } else {
+    if (i > 0 && j) {
+      if (j > 0) {
+        sprintf(keyword, "%s%d_%d%c", pikey, i, j, alt);
+      } else {
+        sprintf(keyword, "%s%d_%d%c", pikey, i, m, alt);
+      }
+    } else if (i > 0) {
+      sprintf(keyword, "%s%d%c", pikey, i, alt);
+    } else if (j > 0) {
+      sprintf(keyword, "%s%d%c", pikey, j, alt);
+    } else {
+      sprintf(keyword, "%s%c", pikey, alt);
+    }
+  }
+
+  /* Double-up single-quotes in the keyvalue. */
+  hptr = keyvalue + 1;
+  while (*hptr) {
+    if (*hptr == '\'') {
+      kptr = hptr++;
+      if (*hptr) {
+        ch0 = *kptr;
+        while (*kptr) {
+          ch1 = *(++kptr);
+          *kptr = ch0;
+          ch0 = ch1;
+        }
+      }
+    }
+
+    hptr++;
+  }
+
+  if ((nv = strlen(keyvalue) > 20)) {
+    /* Rob the keycomment to make space for the keyvalue. */
+    nc -= (nv - 20);
+  }
+
+  hptr = *header + (80 * ((*nkeyrec)++));
+  sprintf(hptr, "%-8.8s= %-20s / %-*.*s", keyword, keyvalue, nc, nc,
+    keycomment);
+}
diff --git a/cextern/wcslib/C/wcshdr.h b/cextern/wcslib/C/wcshdr.h
new file mode 100644
index 0000000..f0b4d84
--- /dev/null
+++ b/cextern/wcslib/C/wcshdr.h
@@ -0,0 +1,1127 @@
+/*============================================================================
+
+  WCSLIB 4.16 - an implementation of the FITS WCS standard.
+  Copyright (C) 1995-2012, Mark Calabretta
+
+  This file is part of WCSLIB.
+
+  WCSLIB is free software: you can redistribute it and/or modify it under the
+  terms of the GNU Lesser General Public License as published by the Free
+  Software Foundation, either version 3 of the License, or (at your option)
+  any later version.
+
+  WCSLIB 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 Lesser General Public License for
+  more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with WCSLIB.  If not, see http://www.gnu.org/licenses.
+
+  Direct correspondence concerning WCSLIB to mark at calabretta.id.au
+
+  Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
+  http://www.atnf.csiro.au/people/Mark.Calabretta
+  $Id: wcshdr.h,v 4.16 2012/11/07 04:42:44 cal103 Exp $
+*=============================================================================
+*
+* WCSLIB 4.16 - C routines that implement the FITS World Coordinate System
+* (WCS) standard.  Refer to
+*
+*   "Representations of world coordinates in FITS",
+*   Greisen, E.W., & Calabretta, M.R. 2002, A&A, 395, 1061 (Paper I)
+*
+*   "Representations of celestial coordinates in FITS",
+*   Calabretta, M.R., & Greisen, E.W. 2002, A&A, 395, 1077 (Paper II)
+*
+*   "Representations of spectral coordinates in FITS",
+*   Greisen, E.W., Calabretta, M.R., Valdes, F.G., & Allen, S.L.
+*   2006, A&A, 446, 747 (Paper III)
+*
+* Refer to the README file provided with WCSLIB for an overview of the
+* library.
+*
+*
+* Summary of the wcshdr routines
+* ------------------------------
+* Routines in this suite are aimed at extracting WCS information from a FITS
+* file.  They provide the high-level interface between the FITS file and the
+* WCS coordinate transformation routines.
+*
+* Additionally, function wcshdo() is provided to write out the contents of a
+* wcsprm struct as a FITS header.
+*
+* Briefly, the anticipated sequence of operations is as follows:
+*
+*   - 1: Open the FITS file and read the image or binary table header, e.g.
+*        using CFITSIO routine fits_hdr2str().
+*
+*   - 2: Parse the header using wcspih() or wcsbth(); they will automatically
+*        interpret 'TAB' header keywords using wcstab().
+*
+*   - 3: Allocate memory for, and read 'TAB' arrays from the binary table
+*        extension, e.g. using CFITSIO routine fits_read_wcstab() - refer to
+*        the prologue of getwcstab.h.  wcsset() will automatically take
+*        control of this allocated memory, in particular causing it to be
+*        free'd by wcsfree().
+*
+*   - 4: Translate non-standard WCS usage using wcsfix(), see wcsfix.h.
+*
+*   - 5: Initialize wcsprm struct(s) using wcsset() and calculate coordinates
+*        using wcsp2s() and/or wcss2p().  Refer to the prologue of wcs.h for a
+*        description of these and other high-level WCS coordinate
+*        transformation routines.
+*
+*   - 6: Clean up by freeing memory with wcsvfree().
+*
+* In detail:
+*
+* - wcspih() is a high-level FITS WCS routine that parses an image header.  It
+*   returns an array of up to 27 wcsprm structs on each of which it invokes
+*   wcstab().
+*
+* - wcsbth() is the analogue of wcspih() for use with binary tables; it
+*   handles image array and pixel list keywords.  As an extension of the FITS
+*   WCS standard, it also recognizes image header keywords which may be used
+*   to provide default values via an inheritance mechanism.
+*
+* - wcstab() assists in filling in members of the wcsprm struct associated
+*   with coordinate lookup tables ('TAB').  These are based on arrays stored
+*   in a FITS binary table extension (BINTABLE) that are located by PVi_ma
+*   keywords in the image header.
+*
+* - wcsidx() and wcsbdx() are utility routines that return the index for a
+*   specified alternate coordinate descriptor in the array of wcsprm structs
+*   returned by wcspih() or wcsbth().
+*
+* - wcsvfree() deallocates memory for an array of wcsprm structs, such as
+*   returned by wcspih() or wcsbth().
+*
+* - wcshdo() writes out a wcsprm struct as a FITS header.
+*
+*
+* wcspih() - FITS WCS parser routine for image headers
+* ----------------------------------------------------
+* wcspih() is a high-level FITS WCS routine that parses an image header,
+* either that of a primary HDU or of an image extension.  All WCS keywords
+* defined in Papers I, II, and III are recognized, and also those used by the
+* AIPS convention and certain other keywords that existed in early drafts of
+* the WCS papers as explained in wcsbth() note 5.
+*
+* Given a character array containing a FITS image header, wcspih() identifies
+* and reads all WCS keywords for the primary coordinate representation and up
+* to 26 alternate representations.  It returns this information as an array of
+* wcsprm structs.
+*
+* wcspih() invokes wcstab() on each of the wcsprm structs that it returns.
+*
+* Use wcsbth() in preference to wcspih() for FITS headers of unknown type;
+* wcsbth() can parse image headers as well as binary table and pixel list
+* headers.
+*
+* Given and returned:
+*   header    char[]    Character array containing the (entire) FITS image
+*                       header from which to identify and construct the
+*                       coordinate representations, for example, as might be
+*                       obtained conveniently via the CFITSIO routine
+*                       fits_hdr2str().
+*
+*                       Each header "keyrecord" (formerly "card image")
+*                       consists of exactly 80 7-bit ASCII printing characters
+*                       in the range 0x20 to 0x7e (which excludes NUL, BS,
+*                       TAB, LF, FF and CR) especially noting that the
+*                       keyrecords are NOT null-terminated.
+*
+*                       For negative values of ctrl (see below), header[] is
+*                       modified so that WCS keyrecords processed by wcspih()
+*                       are removed from it.
+*
+* Given:
+*   nkeyrec   int       Number of keyrecords in header[].
+*
+*   relax     int       Degree of permissiveness:
+*                         0: Recognize only FITS keywords defined by the
+*                            published WCS standard.
+*                         WCSHDR_all: Admit all recognized informal
+*                            extensions of the WCS standard.
+*                       Fine-grained control of the degree of permissiveness
+*                       is also possible as explained in wcsbth() note 5.
+*
+*   ctrl      int       Error reporting and other control options for invalid
+*                       WCS and other header keyrecords:
+*                           0: Do not report any rejected header keyrecords.
+*                           1: Produce a one-line message stating the number
+*                              of WCS keyrecords rejected (nreject).
+*                           2: Report each rejected keyrecord and the reason
+*                              why it was rejected.
+*                           3: As above, but also report all non-WCS
+*                              keyrecords that were discarded, and the number
+*                              of coordinate representations (nwcs) found.
+*                       The report is written to stderr.
+*
+*                       For ctrl < 0, WCS keyrecords processed by wcspih()
+*                       are removed from header[]:
+*                          -1: Remove only valid WCS keyrecords whose values
+*                              were successfully extracted, nothing is
+*                              reported.
+*                          -2: Also remove WCS keyrecords that were rejected,
+*                              reporting each one and the reason that it was
+*                              rejected.
+*                          -3: As above, and also report the number of
+*                              coordinate representations (nwcs) found.
+*                         -11: Same as -1 but preserving the basic keywords
+*                              '{DATE,MJD}-{OBS,AVG}' and 'OBSGEO-{X,Y,Z}'.
+*                       If any keyrecords are removed from header[] it will
+*                       be null-terminated (NUL not being a legal FITS header
+*                       character), otherwise it will contain its original
+*                       complement of nkeyrec keyrecords and possibly not be
+*                       null-terminated.
+*
+* Returned:
+*   nreject   int*      Number of WCS keywords rejected for syntax errors,
+*                       illegal values, etc.  Keywords not recognized as WCS
+*                       keywords are simply ignored.  Refer also to wcsbth()
+*                       note 5.
+*
+*   nwcs      int*      Number of coordinate representations found.
+*
+*   wcs       struct wcsprm**
+*                       Pointer to an array of wcsprm structs containing up to
+*                       27 coordinate representations.
+*
+*                       Memory for the array is allocated by wcspih() which
+*                       also invokes wcsini() for each struct to allocate
+*                       memory for internal arrays and initialize their
+*                       members to default values.  Refer also to wcsbth()
+*                       note 8.  Note that wcsset() is not invoked on these
+*                       structs.
+*
+*                       This allocated memory must be freed by the user, first
+*                       by invoking wcsfree() for each struct, and then by
+*                       freeing the array itself.  A routine, wcsvfree(), is
+*                       provided to do this (see below).
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         1: Null wcsprm pointer passed.
+*                         2: Memory allocation failed.
+*                         4: Fatal error returned by Flex parser.
+*
+* Notes:
+*   Refer to wcsbth() notes 1, 2, 3, 5, 7, and 8.
+*
+*
+* wcsbth() - FITS WCS parser routine for binary table and image headers
+* ---------------------------------------------------------------------
+* wcsbth() is a high-level FITS WCS routine that parses a binary table header.
+* It handles image array and pixel list WCS keywords which may be present
+* together in one header.
+*
+* As an extension of the FITS WCS standard, wcsbth() also recognizes image
+* header keywords in a binary table header.  These may be used to provide
+* default values via an inheritance mechanism discussed in note 5 (c.f.
+* WCSHDR_AUXIMG and WCSHDR_ALLIMG), or may instead result in wcsprm structs
+* that are not associated with any particular column.  Thus wcsbth() can
+* handle primary image and image extension headers in addition to binary table
+* headers (it ignores NAXIS and does not rely on the presence of the TFIELDS
+* keyword).
+*
+* All WCS keywords defined in Papers I, II, and III are recognized, and also
+* those used by the AIPS convention and certain other keywords that existed in
+* early drafts of the WCS papers as explained in note 5 below.
+*
+* wcsbth() sets the colnum or colax[] members of the wcsprm structs that it
+* returns with the column number of an image array or the column numbers
+* associated with each pixel coordinate element in a pixel list.  wcsprm
+* structs that are not associated with any particular column, as may be
+* derived from image header keywords, have colnum == 0.
+*
+* Note 6 below discusses the number of wcsprm structs returned by wcsbth(),
+* and the circumstances in which image header keywords cause a struct to be
+* created.  See also note 9 concerning the number of separate images that may
+* be stored in a pixel list.
+*
+* The API to wcsbth() is similar to that of wcspih() except for the addition
+* of extra arguments that may be used to restrict its operation.  Like
+* wcspih(), wcsbth() invokes wcstab() on each of the wcsprm structs that it
+* returns.
+*
+* Given and returned:
+*   header    char[]    Character array containing the (entire) FITS binary
+*                       table, primary image, or image extension header from
+*                       which to identify and construct the coordinate
+*                       representations, for example, as might be obtained
+*                       conveniently via the CFITSIO routine fits_hdr2str().
+*
+*                       Each header "keyrecord" (formerly "card image")
+*                       consists of exactly 80 7-bit ASCII printing
+*                       characters in the range 0x20 to 0x7e (which excludes
+*                       NUL, BS, TAB, LF, FF and CR) especially noting that
+*                       the keyrecords are NOT null-terminated.
+*
+*                       For negative values of ctrl (see below), header[] is
+*                       modified so that WCS keyrecords processed by wcsbth()
+*                       are removed from it.
+*
+* Given:
+*   nkeyrec   int       Number of keyrecords in header[].
+*
+*   relax     int       Degree of permissiveness:
+*                         0: Recognize only FITS keywords defined by the
+*                            published WCS standard.
+*                         WCSHDR_all: Admit all recognized informal
+*                            extensions of the WCS standard.
+*                       Fine-grained control of the degree of permissiveness
+*                       is also possible, as explained in note 5 below.
+*
+*   ctrl      int       Error reporting and other control options for invalid
+*                       WCS and other header keyrecords:
+*                           0: Do not report any rejected header keyrecords.
+*                           1: Produce a one-line message stating the number
+*                              of WCS keyrecords rejected (nreject).
+*                           2: Report each rejected keyrecord and the reason
+*                              why it was rejected.
+*                           3: As above, but also report all non-WCS
+*                              keyrecords that were discarded, and the number
+*                              of coordinate representations (nwcs) found.
+*                       The report is written to stderr.
+*
+*                       For ctrl < 0, WCS keyrecords processed by wcsbth()
+*                       are removed from header[]:
+*                          -1: Remove only valid WCS keyrecords whose values
+*                              were successfully extracted, nothing is
+*                              reported.
+*                          -2: Also remove WCS keyrecords that were rejected,
+*                              reporting each one and the reason that it was
+*                              rejected.
+*                          -3: As above, and also report the number of
+*                              coordinate representations (nwcs) found.
+*                         -11: Same as -1 but preserving the basic keywords
+*                              '{DATE,MJD}-{OBS,AVG}' and 'OBSGEO-{X,Y,Z}'.
+*                       If any keyrecords are removed from header[] it will
+*                       be null-terminated (NUL not being a legal FITS header
+*                       character), otherwise it will contain its original
+*                       complement of nkeyrec keyrecords and possibly not be
+*                       null-terminated.
+*
+*   keysel    int       Vector of flag bits that may be used to restrict the
+*                       keyword types considered:
+*                         WCSHDR_IMGHEAD: Image header keywords.
+*                         WCSHDR_BIMGARR: Binary table image array.
+*                         WCSHDR_PIXLIST: Pixel list keywords.
+*                       If zero, there is no restriction.
+*
+*                       Keywords such as EQUIna or RFRQna that are common to
+*                       binary table image arrays and pixel lists (including
+*                       WCSNna and TWCSna, as explained in note 4 below) are
+*                       selected by both WCSHDR_BIMGARR and WCSHDR_PIXLIST.
+*                       Thus if inheritance via WCSHDR_ALLIMG is enabled as
+*                       discussed in note 5 and one of these shared keywords
+*                       is present, then WCSHDR_IMGHEAD and WCSHDR_PIXLIST
+*                       alone may be sufficient to cause the construction of
+*                       coordinate descriptions for binary table image arrays.
+*
+*   colsel    int*      Pointer to an array of table column numbers used to
+*                       restrict the keywords considered by wcsbth().
+*
+*                       A null pointer may be specified to indicate that there
+*                       is no restriction.  Otherwise, the magnitude of
+*                       cols[0] specifies the length of the array:
+*                         cols[0] > 0: the columns are included,
+*                         cols[0] < 0: the columns are excluded.
+*
+*                       For the pixel list keywords TPn_ka and TCn_ka (and
+*                       TPCn_ka and TCDn_ka if WCSHDR_LONGKEY is enabled), it
+*                       is an error for one column to be selected but not the
+*                       other.  This is unlike the situation with invalid
+*                       keyrecords, which are simply rejected, because the
+*                       error is not intrinsic to the header itself but
+*                       arises in the way that it is processed.
+*
+* Returned:
+*   nreject   int*      Number of WCS keywords rejected for syntax errors,
+*                       illegal values, etc.  Keywords not recognized as WCS
+*                       keywords are simply ignored, refer also to note 5
+*                       below.
+*
+*   nwcs      int*      Number of coordinate representations found.
+*
+*   wcs       struct wcsprm**
+*                       Pointer to an array of wcsprm structs containing up
+*                       to 27027 coordinate representations, refer to note 6
+*                       below.
+*
+*                       Memory for the array is allocated by wcsbth() which
+*                       also invokes wcsini() for each struct to allocate
+*                       memory for internal arrays and initialize their
+*                       members to default values.  Refer also to note 8
+*                       below.  Note that wcsset() is not invoked on these
+*                       structs.
+*
+*                       This allocated memory must be freed by the user, first
+*                       by invoking wcsfree() for each struct, and then by
+*                       freeing the array itself.  A routine, wcsvfree(), is
+*                       provided to do this (see below).
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         1: Null wcsprm pointer passed.
+*                         2: Memory allocation failed.
+*                         3: Invalid column selection.
+*                         4: Fatal error returned by Flex parser.
+*
+* Notes:
+*   1: wcspih() determines the number of coordinate axes independently for
+*      each alternate coordinate representation (denoted by the "a" value in
+*      keywords like CTYPEia) from the higher of
+*
+*        a: NAXIS,
+*        b: WCSAXESa,
+*        c: The highest axis number in any parameterized WCS keyword.  The
+*           keyvalue, as well as the keyword, must be syntactically valid
+*           otherwise it will not be considered.
+*
+*      If none of these keyword types is present, i.e. if the header only
+*      contains auxiliary WCS keywords for a particular coordinate
+*      representation, then no coordinate description is constructed for it.
+*
+*      wcsbth() is similar except that it ignores the NAXIS keyword if given
+*      an image header to process.
+*
+*      The number of axes, which is returned as a member of the wcsprm
+*      struct, may differ for different coordinate representations of the
+*      same image.
+*
+*   2: wcspih() and wcsbth() enforce correct FITS "keyword = value" syntax
+*      with regard to "= " occurring in columns 9 and 10.
+*
+*      However, they do recognize free-format character (NOST 100-2.0,
+*      Sect. 5.2.1), integer (Sect. 5.2.3), and floating-point values
+*      (Sect. 5.2.4) for all keywords.
+*
+*   3: Where CROTAn, CDi_ja, and PCi_ja occur together in one header wcspih()
+*      and wcsbth() treat them as described in the prologue to wcs.h.
+*
+*   4: WCS Paper I mistakenly defined the pixel list form of WCSNAMEa as
+*      TWCSna instead of WCSNna; the 'T' is meant to substitute for the axis
+*      number in the binary table form of the keyword - note that keywords
+*      defined in WCS Papers II and III that are not parameterised by axis
+*      number have identical forms for binary tables and pixel lists.
+*      Consequently wcsbth() always treats WCSNna and TWCSna as equivalent.
+*
+*   5: wcspih() and wcsbth() interpret the "relax" argument as a vector of
+*      flag bits to provide fine-grained control over what non-standard WCS
+*      keywords to accept.  The flag bits are subject to change in future and
+*      should be set by using the preprocessor macros (see below) for the
+*      purpose.
+*
+*      - WCSHDR_none: Don't accept any extensions (not even those in the
+*              errata).  Treat non-conformant keywords in the same way as
+*              non-WCS keywords in the header, i.e. simply ignore them.
+*
+*      - WCSHDR_all: Accept all extensions recognized by the parser.
+*
+*      - WCSHDR_reject: Reject non-standard keywords (that are not otherwise
+*              accepted).  A message will optionally be printed on stderr, as
+*              determined by the ctrl argument, and nreject will be
+*              incremented.
+*
+*              This flag may be used to signal the presence of non-standard
+*              keywords, otherwise they are simply passed over as though they
+*              did not exist in the header.
+*
+*              Useful for testing conformance of a FITS header to the WCS
+*              standard.
+*
+*      - WCSHDR_CROTAia: Accept CROTAia (wcspih()),
+*                               iCROTna (wcsbth()),
+*                               TCROTna (wcsbth()).
+*      - WCSHDR_EPOCHa:  Accept EPOCHa.
+*      - WCSHDR_VELREFa: Accept VELREFa.
+*              wcspih() always recognizes the AIPS-convention keywords,
+*              CROTAn, EPOCH, and VELREF for the primary representation
+*              (a = ' ') but alternates are non-standard.
+*
+*              wcsbth() accepts EPOCHa and VELREFa only if WCSHDR_AUXIMG is
+*              also enabled.
+*
+*      - WCSHDR_CD00i00j: Accept CD00i00j (wcspih()).
+*      - WCSHDR_PC00i00j: Accept PC00i00j (wcspih()).
+*      - WCSHDR_PROJPn:   Accept PROJPn   (wcspih()).
+*              These appeared in early drafts of WCS Paper I+II (before they
+*              were split) and are equivalent to CDi_ja, PCi_ja, and PVi_ma
+*              for the primary representation (a = ' ').  PROJPn is
+*              equivalent to PVi_ma with m = n <= 9, and is associated
+*              exclusively with the latitude axis.
+*
+*      - WCSHDR_RADECSYS: Accept RADECSYS.  This appeared in early drafts of
+*              WCS Paper I+II and was subsequently replaced by RADESYSa.
+*
+*              wcsbth() accepts RADECSYS only if WCSHDR_AUXIMG is also
+*              enabled.
+*
+*      - WCSHDR_VSOURCE: Accept VSOURCEa or VSOUna (wcsbth()).  This appeared
+*              in early drafts of WCS Paper III and was subsequently dropped
+*              in favour of ZSOURCEa and ZSOUna.
+*
+*              wcsbth() accepts VSOURCEa only if WCSHDR_AUXIMG is also
+*              enabled.
+*
+*      - WCSHDR_DOBSn (wcsbth() only): Allow DOBSn, the column-specific analogue
+*              of DATE-OBS.  By an oversight this was never formally defined
+*              in the standard.
+*
+*      - WCSHDR_LONGKEY (wcsbth() only): Accept long forms of the alternate
+*              binary table and pixel list WCS keywords, i.e. with "a" non-
+*              blank.  Specifically
+*
+#                jCRPXna  TCRPXna  :  jCRPXn  jCRPna  TCRPXn  TCRPna  CRPIXja
+#                   -     TPCn_ka  :    -     ijPCna    -     TPn_ka  PCi_ja
+#                   -     TCDn_ka  :    -     ijCDna    -     TCn_ka  CDi_ja
+#                iCDLTna  TCDLTna  :  iCDLTn  iCDEna  TCDLTn  TCDEna  CDELTia
+#                iCUNIna  TCUNIna  :  iCUNIn  iCUNna  TCUNIn  TCUNna  CUNITia
+#                iCTYPna  TCTYPna  :  iCTYPn  iCTYna  TCTYPn  TCTYna  CTYPEia
+#                iCRVLna  TCRVLna  :  iCRVLn  iCRVna  TCRVLn  TCRVna  CRVALia
+#                iPVn_ma  TPVn_ma  :    -     iVn_ma    -     TVn_ma  PVi_ma
+#                iPSn_ma  TPSn_ma  :    -     iSn_ma    -     TSn_ma  PSi_ma
+*
+*              where the primary and standard alternate forms together with
+*              the image-header equivalent are shown rightwards of the colon.
+*
+*              The long form of these keywords could be described as quasi-
+*              standard.  TPCn_ka, iPVn_ma, and TPVn_ma appeared by mistake
+*              in the examples in WCS Paper II and subsequently these and
+*              also TCDn_ka, iPSn_ma and TPSn_ma were legitimized by the
+*              errata to the WCS papers.
+*
+*              Strictly speaking, the other long forms are non-standard and
+*              in fact have never appeared in any draft of the WCS papers nor
+*              in the errata.  However, as natural extensions of the primary
+*              form they are unlikely to be written with any other intention.
+*              Thus it should be safe to accept them provided, of course,
+*              that the resulting keyword does not exceed the 8-character
+*              limit.
+*
+*              If WCSHDR_CNAMn is enabled then also accept
+*
+#                iCNAMna  TCNAMna  :   ---   iCNAna    ---   TCNAna  CNAMEia
+#                iCRDEna  TCRDEna  :   ---   iCRDna    ---   TCRDna  CRDERia
+#                iCSYEna  TCSYEna  :   ---   iCSYna    ---   TCSYna  CSYERia
+*
+*              Note that CNAMEia, CRDERia, CSYERia, and their variants are
+*              not used by WCSLIB but are stored in the wcsprm struct as
+*              auxiliary information.
+*
+*      - WCSHDR_CNAMn (wcsbth() only): Accept iCNAMn, iCRDEn, iCSYEn, TCNAMn,
+*              TCRDEn, and TCSYEn, i.e. with "a" blank.  While non-standard,
+*              these are the obvious analogues of iCTYPn, TCTYPn, etc.
+*
+*      - WCSHDR_AUXIMG (wcsbth() only): Allow the image-header form of an
+*              auxiliary WCS keyword with representation-wide scope to
+*              provide a default value for all images.  This default may be
+*              overridden by the column-specific form of the keyword.
+*
+*              For example, a keyword like EQUINOXa would apply to all image
+*              arrays in a binary table, or all pixel list columns with
+*              alternate representation "a" unless overridden by EQUIna.
+*
+*              Specifically the keywords are:
+*
+#                LATPOLEa  for LATPna
+#                LONPOLEa  for LONPna
+#                RESTFREQ  for RFRQna
+#                RESTFRQa  for RFRQna
+#                RESTWAVa  for RWAVna
+*
+*              whose keyvalues are actually used by WCSLIB, and also keywords
+*              that provide auxiliary information that is simply stored in
+*              the wcsprm struct:
+*
+#                EPOCH         -       ... (No column-specific form.)
+#                EPOCHa        -       ... Only if WCSHDR_EPOCHa is set.
+#                EQUINOXa  for EQUIna
+#                RADESYSa  for RADEna
+#                RADECSYS  for RADEna  ... Only if WCSHDR_RADECSYS is set.
+#                SPECSYSa  for SPECna
+#                SSYSOBSa  for SOBSna
+#                SSYSSRCa  for SSRCna
+#                VELOSYSa  for VSYSna
+#                VELANGLa  for VANGna
+#                VELREF        -       ... (No column-specific form.)
+#                VELREFa       -       ... Only if WCSHDR_VELREFa is set.
+#                VSOURCEa  for VSOUna  ... Only if WCSHDR_VSOURCE is set.
+#                WCSNAMEa  for WCSNna  ... Or TWCSna (see below).
+#                ZSOURCEa  for ZSOUna
+*
+#                DATE-AVG  for DAVGn
+#                DATE-OBS  for DOBSn
+#                MJD-AVG   for MJDAn
+#                MJD-OBS   for MJDOBn
+#                OBSGEO-X  for OBSGXn
+#                OBSGEO-Y  for OBSGYn
+#                OBSGEO-Z  for OBSGZn
+*
+*              where the image-header keywords on the left provide default
+*              values for the column specific keywords on the right.
+*
+*              Keywords in the last group, such as MJD-OBS, apply to all
+*              alternate representations, so MJD-OBS would provide a default
+*              value for all images in the header.
+*
+*              This auxiliary inheritance mechanism applies to binary table
+*              image arrays and pixel lists alike.  Most of these keywords
+*              have no default value, the exceptions being LONPOLEa and
+*              LATPOLEa, and also RADESYSa and EQUINOXa which provide
+*              defaults for each other.  Thus the only potential difficulty
+*              in using WCSHDR_AUXIMG is that of erroneously inheriting one
+*              of these four keywords.
+*
+*              Unlike WCSHDR_ALLIMG, the existence of one (or all) of these
+*              auxiliary WCS image header keywords will not by itself cause a
+*              wcsprm struct to be created for alternate representation "a".
+*              This is because they do not provide sufficient information to
+*              create a non-trivial coordinate representation when used in
+*              conjunction with the default values of those keywords, such as
+*              CTYPEia, that are parameterized by axis number.
+*
+*      - WCSHDR_ALLIMG (wcsbth() only): Allow the image-header form of *all*
+*              image header WCS keywords to provide a default value for all
+*              image arrays in a binary table (n.b. not pixel list).  This
+*              default may be overridden by the column-specific form of the
+*              keyword.
+*
+*              For example, a keyword like CRPIXja would apply to all image
+*              arrays in a binary table with alternate representation "a"
+*              unless overridden by jCRPna.
+*
+*              Specifically the keywords are those listed above for
+*              WCSHDR_AUXIMG plus
+*
+#                WCSAXESa  for WCAXna
+*
+*              which defines the coordinate dimensionality, and the following
+*              keywords which are parameterized by axis number:
+*
+#                CRPIXja   for jCRPna
+#                PCi_ja    for ijPCna
+#                CDi_ja    for ijCDna
+#                CDELTia   for iCDEna
+#                CROTAi    for iCROTn
+#                CROTAia        -      ... Only if WCSHDR_CROTAia is set.
+#                CUNITia   for iCUNna
+#                CTYPEia   for iCTYna
+#                CRVALia   for iCRVna
+#                PVi_ma    for iVn_ma
+#                PSi_ma    for iSn_ma
+*
+#                CNAMEia   for iCNAna
+#                CRDERia   for iCRDna
+#                CSYERia   for iCSYna
+*
+*              where the image-header keywords on the left provide default
+*              values for the column specific keywords on the right.
+*
+*              This full inheritance mechanism only applies to binary table
+*              image arrays, not pixel lists, because in the latter case
+*              there is no well-defined association between coordinate axis
+*              number and column number.
+*
+*              Note that CNAMEia, CRDERia, CSYERia, and their variants are
+*              not used by WCSLIB but are stored in the wcsprm struct as
+*              auxiliary information.
+*
+*              Note especially that at least one wcsprm struct will be
+*              returned for each "a" found in one of the image header
+*              keywords listed above:
+*
+*              - If the image header keywords for "a" ARE NOT inherited by a
+*                binary table, then the struct will not be associated with
+*                any particular table column number and it is up to the user
+*                to provide an association.
+*
+*              - If the image header keywords for "a" ARE inherited by a
+*                binary table image array, then those keywords are considered
+*                to be "exhausted" and do not result in a separate wcsprm
+*                struct.
+*
+*      For example, to accept CD00i00j and PC00i00j and reject all other
+*      extensions, use
+*
+=        relax = WCSHDR_reject | WCSHDR_CD00i00j | WCSHDR_PC00i00j;
+*
+*      The parser always treats EPOCH as subordinate to EQUINOXa if both are
+*      present, and VSOURCEa is always subordinate to ZSOURCEa.
+*
+*      Likewise, VELREF is subordinate to the formalism of WCS Paper III, see
+*      spcaips().
+*
+*      Neither wcspih() nor wcsbth() currently recognize the AIPS-convention
+*      keywords ALTRPIX or ALTRVAL which effectively define an alternative
+*      representation for a spectral axis.
+*
+*   6: Depending on what flags have been set in its "relax" argument,
+*      wcsbth() could return as many as 27027 wcsprm structs:
+*
+*      - Up to 27 unattached representations derived from image header
+*        keywords.
+*
+*      - Up to 27 structs for each of up to 999 columns containing an image
+*        arrays.
+*
+*      - Up to 27 structs for a pixel list.
+*
+*      Note that it is considered legitimate for a column to contain an image
+*      array and also form part of a pixel list, and in particular that
+*      wcsbth() does not check the TFORM keyword for a pixel list column to
+*      check that it is scalar.
+*
+*      In practice, of course, a realistic binary table header is unlikely to
+*      contain more than a handful of images.
+*
+*      In order for wcsbth() to create a wcsprm struct for a particular
+*      coordinate representation, at least one WCS keyword that defines an
+*      axis number must be present, either directly or by inheritance if
+*      WCSHDR_ALLIMG is set.
+*
+*      When the image header keywords for an alternate representation are
+*      inherited by a binary table image array via WCSHDR_ALLIMG, those
+*      keywords are considered to be "exhausted" and do not result in a
+*      separate wcsprm struct.  Otherwise they do.
+*
+*   7: Neither wcspih() nor wcsbth() check for duplicated keywords, in most
+*      cases they accept the last encountered.
+*
+*   8: wcspih() and wcsbth() use wcsnpv() and wcsnps() (refer to the prologue
+*      of wcs.h) to match the size of the pv[] and ps[] arrays in the wcsprm
+*      structs to the number in the header.  Consequently there are no unused
+*      elements in the pv[] and ps[] arrays, indeed they will often be of
+*      zero length.
+*
+*   9: The FITS WCS standard for pixel lists assumes that a pixel list
+*      defines one and only one image, i.e. that each row of the binary table
+*      refers to just one event, e.g. the detection of a single photon or
+*      neutrino.
+*
+*      In the absence of a formal mechanism for identifying the columns
+*      containing pixel coordinates (as opposed to pixel values or ancillary
+*      data recorded at the time the photon or neutrino was detected),
+*      Paper I discusses how the WCS keywords themselves may be used to
+*      identify them.
+*
+*      In practice, however, pixel lists have been used to store multiple
+*      images.  Besides not specifying how to identify columns, the pixel
+*      list convention is also silent on the method to be used to associate
+*      table columns with image axes.
+*
+*      wcsbth() simply collects all WCS keywords for a particular coordinate
+*      representation (i.e. the "a" value in TCTYna) into one wcsprm struct.
+*      However, these alternates need not be associated with the same table
+*      columns and this allows a pixel list to contain up to 27 separate
+*      images.  As usual, if one of these representations happened to contain
+*      more than two celestial axes, for example, then an error would result
+*      when wcsset() is invoked on it.  In this case the "colsel" argument
+*      could be used to restrict the columns used to construct the
+*      representation so that it only contained one pair of celestial axes.
+*
+*
+* wcstab() - Tabular construction routine
+* ---------------------------------------
+* wcstab() assists in filling in the information in the wcsprm struct relating
+* to coordinate lookup tables.
+*
+* Tabular coordinates ('TAB') present certain difficulties in that the main
+* components of the lookup table - the multidimensional coordinate array plus
+* an index vector for each dimension - are stored in a FITS binary table
+* extension (BINTABLE).  Information required to locate these arrays is stored
+* in PVi_ma and PSi_ma keywords in the image header.
+*
+* wcstab() parses the PVi_ma and PSi_ma keywords associated with each 'TAB'
+* axis and allocates memory in the wcsprm struct for the required number of
+* tabprm structs.  It sets as much of the tabprm struct as can be gleaned from
+* the image header, and also sets up an array of wtbarr structs (described in
+* the prologue of wcs.h) to assist in extracting the required arrays from the
+* BINTABLE extension(s).
+*
+* It is then up to the user to allocate memory for, and copy arrays from the
+* BINTABLE extension(s) into the tabprm structs.  A CFITSIO routine,
+* fits_read_wcstab(), has been provided for this purpose, see getwcstab.h.
+* wcsset() will automatically take control of this allocated memory, in
+* particular causing it to be free'd by wcsfree(); the user must not attempt
+* to free it after wcsset() has been called.
+*
+* Note that wcspih() and wcsbth() automatically invoke wcstab() on each of the
+* wcsprm structs that they return.
+*
+* Given and returned:
+*   wcs       struct wcsprm*
+*                       Coordinate transformation parameters (see below).
+*
+*                       wcstab() sets ntab, tab, nwtb and wtb, allocating
+*                       memory for the tab and wtb arrays.  This allocated
+*                       memory will be free'd automatically by wcsfree().
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         1: Null wcsprm pointer passed.
+*                         2: Memory allocation failed.
+*                         3: Invalid tabular parameters.
+*
+*                       For returns > 1, a detailed error message is set in
+*                       wcsprm::err if enabled, see wcserr_enable().
+*
+*
+* wcsidx() - Index alternate coordinate representations
+* -----------------------------------------------------
+* wcsidx() returns an array of 27 indices for the alternate coordinate
+* representations in the array of wcsprm structs returned by wcspih().  For
+* the array returned by wcsbth() it returns indices for the unattached
+* (colnum == 0) representations derived from image header keywords - use
+* wcsbdx() for those derived from binary table image arrays or pixel lists
+* keywords.
+*
+* Given:
+*   nwcs      int       Number of coordinate representations in the array.
+*
+*   wcs       const struct wcsprm**
+*                       Pointer to an array of wcsprm structs returned by
+*                       wcspih() or wcsbth().
+*
+* Returned:
+*   alts      int[27]   Index of each alternate coordinate representation in
+*                       the array: alts[0] for the primary, alts[1] for 'A',
+*                       etc., set to -1 if not present.
+*
+*                       For example, if there was no 'P' representation then
+*
+=                         alts['P'-'A'+1] == -1;
+*
+*                       Otherwise, the address of its wcsprm struct would be
+*
+=                         wcs + alts['P'-'A'+1];
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         1: Null wcsprm pointer passed.
+*
+*
+* wcsbdx() - Index alternate coordinate representions
+* ---------------------------------------------------
+* wcsbdx() returns an array of 999 x 27 indices for the alternate coordinate
+* representions for binary table image arrays xor pixel lists in the array of
+* wcsprm structs returned by wcsbth().  Use wcsidx() for the unattached
+* representations derived from image header keywords.
+*
+* Given:
+*   nwcs      int       Number of coordinate representations in the array.
+*
+*   wcs       const struct wcsprm**
+*                       Pointer to an array of wcsprm structs returned by
+*                       wcsbth().
+*
+*   type      int       Select the type of coordinate representation:
+*                         0: binary table image arrays,
+*                         1: pixel lists.
+*
+* Returned:
+*   alts      short[1000][28]
+*                       Index of each alternate coordinate represention in the
+*                       array: alts[col][0] for the primary, alts[col][1] for
+*                       'A', to alts[col][26] for 'Z', where col is the
+*                       1-relative column number, and col == 0 is used for
+*                       unattached image headers.  Set to -1 if not present.
+*
+*                       alts[col][27] counts the number of coordinate
+*                       representations of the chosen type for each column.
+*
+*                       For example, if there was no 'P' represention for
+*                       column 13 then
+*
+=                         alts[13]['P'-'A'+1] == -1;
+*
+*                       Otherwise, the address of its wcsprm struct would be
+*
+=                         wcs + alts[13]['P'-'A'+1];
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         1: Null wcsprm pointer passed.
+*
+*
+* wcsvfree() - Free the array of wcsprm structs
+* ---------------------------------------------
+* wcsvfree() frees the memory allocated by wcspih() or wcsbth() for the array
+* of wcsprm structs, first invoking wcsfree() on each of the array members.
+*
+* Given and returned:
+*   nwcs      int*      Number of coordinate representations found; set to 0
+*                       on return.
+*
+*   wcs       struct wcsprm**
+*                       Pointer to the array of wcsprm structs; set to 0 on
+*                       return.
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         1: Null wcsprm pointer passed.
+*
+*
+* wcshdo() - Write out a wcsprm struct as a FITS header
+* -----------------------------------------------------
+* wcshdo() translates a wcsprm struct into a FITS header.  If the colnum
+* member of the struct is non-zero then a binary table image array header will
+* be produced.  Otherwise, if the colax[] member of the struct is set non-zero
+* then a pixel list header will be produced.  Otherwise, a primary image or
+* image extension header will be produced.
+*
+* If the struct was originally constructed from a header, e.g. by wcspih(),
+* the output header will almost certainly differ in a number of respects:
+*
+*   - The output header only contains WCS-related keywords.  In particular, it
+*     does not contain syntactically-required keywords such as SIMPLE, NAXIS,
+*     BITPIX, or END.
+*
+*   - Deprecated (e.g. CROTAn) or non-standard usage will be translated to
+*     standard (this is partially dependent on whether wcsfix() was applied).
+*
+*   - Quantities will be converted to the units used internally, basically SI
+*     with the addition of degrees.
+*
+*   - Floating-point quantities may be given to a different decimal precision.
+*
+*   - Elements of the PCi_ja matrix will be written if and only if they differ
+*     from the unit matrix.  Thus, if the matrix is unity then no elements
+*     will be written.
+*
+*   - Additional keywords such as WCSAXESa, CUNITia, LONPOLEa and LATPOLEa may
+*     appear.
+*
+*   - The original keycomments will be lost, although wcshdo() tries hard to
+*     write meaningful comments.
+*
+*   - Keyword order may be changed.
+*
+* Keywords can be translated between the image array, binary table, and pixel
+* lists forms by manipulating the colnum or colax[] members of the wcsprm
+* struct.
+*
+* Given:
+*   relax     int       Degree of permissiveness:
+*                          0: Recognize only FITS keywords defined by the
+*                             published WCS standard.
+*                         -1: Admit all informal extensions of the WCS
+*                             standard.
+*                       Fine-grained control of the degree of permissiveness
+*                       is also possible as explained in the notes below.
+*
+* Given and returned:
+*   wcs       struct wcsprm*
+*                       Pointer to a wcsprm struct containing coordinate
+*                       transformation parameters.  Will be initialized if
+*                       necessary.
+*
+* Returned:
+*   nkeyrec   int*      Number of FITS header keyrecords returned in the
+*                       "header" array.
+*
+*   header    char**    Pointer to an array of char holding the header.
+*                       Storage for the array is allocated by wcshdo() in
+*                       blocks of 2880 bytes (32 x 80-character keyrecords)
+*                       and must be free'd by the user to avoid memory leaks.
+*
+*                       Each keyrecord is 80 characters long and is *NOT*
+*                       null-terminated, so the first keyrecord starts at
+*                       (*header)[0], the second at (*header)[80], etc.
+*
+* Function return value:
+*             int       Status return value (associated with wcs_errmsg[]):
+*                         0: Success.
+*                         1: Null wcsprm pointer passed.
+*                         2: Memory allocation failed.
+*                         3: Linear transformation matrix is singular.
+*                         4: Inconsistent or unrecognized coordinate axis
+*                            types.
+*                         5: Invalid parameter value.
+*                         6: Invalid coordinate transformation parameters.
+*                         7: Ill-conditioned coordinate transformation
+*                            parameters.
+*
+*                       For returns > 1, a detailed error message is set in
+*                       wcsprm::err if enabled, see wcserr_enable().
+*
+* Notes:
+*   wcshdo() interprets the "relax" argument as a vector of flag bits to
+*   provide fine-grained control over what non-standard WCS keywords to write.
+*   The flag bits are subject to change in future and should be set by using
+*   the preprocessor macros (see below) for the purpose.
+*
+*   - WCSHDO_none: Don't use any extensions.
+*
+*   - WCSHDO_all: Write all recognized extensions, equivalent to setting each
+*           flag bit.
+*
+*   - WCSHDO_safe: Write all extensions that are considered to be safe and
+*           recommended.
+*
+*   - WCSHDO_DOBSn: Write DOBSn, the column-specific analogue of DATE-OBS for
+*           use in binary tables and pixel lists.  WCS Paper III introduced
+*           DATE-AVG and DAVGn but by an oversight DOBSn (the obvious analogy)
+*           was never formally defined by the standard.  The alternative to
+*           using DOBSn is to write DATE-OBS which applies to the whole table.
+*           This usage is considered to be safe and is recommended.
+*
+*   - WCSHDO_TPCn_ka: WCS Paper I defined
+*
+*           - TPn_ka and TCn_ka for pixel lists
+*
+*           but WCS Paper II uses TPCn_ka in one example and subsequently the
+*           errata for the WCS papers legitimized the use of
+*
+*           - TPCn_ka and TCDn_ka for pixel lists
+*
+*           provided that the keyword does not exceed eight characters.  This
+*           usage is considered to be safe and is recommended because of the
+*           non-mnemonic terseness of the shorter forms.
+*
+*   - WCSHDO_PVn_ma: WCS Paper I defined
+*
+*           - iVn_ma and iSn_ma for bintables and
+*           - TVn_ma and TSn_ma for pixel lists
+*
+*           but WCS Paper II uses iPVn_ma and TPVn_ma in the examples and
+*           subsequently the errata for the WCS papers legitimized the use of
+*
+*           - iPVn_ma and iPSn_ma for bintables and
+*           - TPVn_ma and TPSn_ma for pixel lists
+*
+*           provided that the keyword does not exceed eight characters.  This
+*           usage is considered to be safe and is recommended because of the
+*           non-mnemonic terseness of the shorter forms.
+*
+*   - WCSHDO_CRPXna: For historical reasons WCS Paper I defined
+*
+*           - jCRPXn, iCDLTn, iCUNIn, iCTYPn, and iCRVLn for bintables and
+*           - TCRPXn, TCDLTn, TCUNIn, TCTYPn, and TCRVLn for pixel lists
+*
+*           for use without an alternate version specifier.  However, because
+*           of the eight-character keyword constraint, in order to accommodate
+*           column numbers greater than 99 WCS Paper I also defined
+*
+*           - jCRPna, iCDEna, iCUNna, iCTYna and iCRVna for bintables and
+*           - TCRPna, TCDEna, TCUNna, TCTYna and TCRVna for pixel lists
+*
+*           for use with an alternate version specifier (the "a").  Like the
+*           PC, CD, PV, and PS keywords there is an obvious tendency to
+*           confuse these two forms for column numbers up to 99.  It is very
+*           unlikely that any parser would reject keywords in the first set
+*           with a non-blank alternate version specifier so this usage is
+*           considered to be safe and is recommended.
+*
+*   - WCSHDO_CNAMna: WCS Papers I and III defined
+*
+*           - iCNAna,  iCRDna,  and iCSYna  for bintables and
+*           - TCNAna,  TCRDna,  and TCSYna  for pixel lists
+*
+*           By analogy with the above, the long forms would be
+*
+*           - iCNAMna, iCRDEna, and iCSYEna for bintables and
+*           - TCNAMna, TCRDEna, and TCSYEna for pixel lists
+*
+*           Note that these keywords provide auxiliary information only, none
+*           of them are needed to compute world coordinates.  This usage is
+*           potentially unsafe and is not recommended at this time.
+*
+*   - WCSHDO_WCSNna: In light of wcsbth() note 4, write WCSNna instead of
+*           TWCSna for pixel lists.  While wcsbth() treats WCSNna and TWCSna
+*           as equivalent, other parsers may not.  Consequently, this usage
+*           is potentially unsafe and is not recommended at this time.
+*
+*
+* Global variable: const char *wcshdr_errmsg[] - Status return messages
+* ---------------------------------------------------------------------
+* Error messages to match the status value returned from each function.
+* Use wcs_errmsg[] for status returns from wcshdo().
+*
+*===========================================================================*/
+
+#ifndef WCSLIB_WCSHDR
+#define WCSLIB_WCSHDR
+
+#include "wcs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define WCSHDR_none     0x00000000
+#define WCSHDR_all      0x000FFFFF
+#define WCSHDR_reject   0x10000000
+
+#define WCSHDR_CROTAia  0x00000001
+#define WCSHDR_EPOCHa   0x00000002
+#define WCSHDR_VELREFa  0x00000004
+#define WCSHDR_CD00i00j 0x00000008
+#define WCSHDR_PC00i00j 0x00000010
+#define WCSHDR_PROJPn   0x00000020
+#define WCSHDR_RADECSYS 0x00000040
+#define WCSHDR_VSOURCE  0x00000080
+#define WCSHDR_DOBSn    0x00000100
+#define WCSHDR_LONGKEY  0x00000200
+#define WCSHDR_CNAMn    0x00000400
+#define WCSHDR_AUXIMG   0x00000800
+#define WCSHDR_ALLIMG   0x00001000
+
+#define WCSHDR_IMGHEAD  0x00010000
+#define WCSHDR_BIMGARR  0x00020000
+#define WCSHDR_PIXLIST  0x00040000
+
+#define WCSHDO_none     0x00
+#define WCSHDO_all      0xFF
+#define WCSHDO_safe     0x0F
+#define WCSHDO_DOBSn    0x01
+#define WCSHDO_TPCn_ka  0x02
+#define WCSHDO_PVn_ma   0x04
+#define WCSHDO_CRPXna   0x08
+#define WCSHDO_CNAMna   0x10
+#define WCSHDO_WCSNna   0x20
+
+
+extern const char *wcshdr_errmsg[];
+
+enum wcshdr_errmsg_enum {
+  WCSHDRERR_SUCCESS            = 0,	/* Success. */
+  WCSHDRERR_NULL_POINTER       = 1,	/* Null wcsprm pointer passed. */
+  WCSHDRERR_MEMORY             = 2,	/* Memory allocation failed. */
+  WCSHDRERR_BAD_COLUMN         = 3,	/* Invalid column selection. */
+  WCSHDRERR_PARSER             = 4,	/* Fatal error returned by Flex
+					   parser. */
+  WCSHDRERR_BAD_TABULAR_PARAMS = 5 	/* Invalid tabular parameters. */
+};
+
+int wcspih(char *header, int nkeyrec, int relax, int ctrl, int *nreject,
+           int *nwcs, struct wcsprm **wcs);
+
+int wcsbth(char *header, int nkeyrec, int relax, int ctrl, int keysel,
+           int *colsel, int *nreject, int *nwcs, struct wcsprm **wcs);
+
+int wcstab(struct wcsprm *wcs);
+
+int wcsidx(int nwcs, struct wcsprm **wcs, int alts[27]);
+
+int wcsbdx(int nwcs, struct wcsprm **wcs, int type, short alts[1000][28]);
+
+int wcsvfree(int *nwcs, struct wcsprm **wcs);
+
+int wcshdo(int relax, struct wcsprm *wcs, int *nkeyrec, char **header);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* WCSLIB_WCSHDR */
diff --git a/cextern/wcslib/C/wcslib.h b/cextern/wcslib/C/wcslib.h
new file mode 100644
index 0000000..a32d80c
--- /dev/null
+++ b/cextern/wcslib/C/wcslib.h
@@ -0,0 +1,60 @@
+/*============================================================================
+
+  WCSLIB 4.16 - an implementation of the FITS WCS standard.
+  Copyright (C) 1995-2012, Mark Calabretta
+
+  This file is part of WCSLIB.
+
+  WCSLIB is free software: you can redistribute it and/or modify it under the
+  terms of the GNU Lesser General Public License as published by the Free
+  Software Foundation, either version 3 of the License, or (at your option)
+  any later version.
+
+  WCSLIB 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 Lesser General Public License for
+  more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with WCSLIB.  If not, see http://www.gnu.org/licenses.
+
+  Direct correspondence concerning WCSLIB to mark at calabretta.id.au
+
+  Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
+  http://www.atnf.csiro.au/people/Mark.Calabretta
+  $Id: wcslib.h,v 4.16 2012/11/07 04:42:44 cal103 Exp $
+*=============================================================================
+*
+* WCSLIB 4.16 - C routines that implement the FITS World Coordinate System
+* (WCS) standard.
+*
+* Summary of wcslib.h
+* -------------------
+* This header file is provided purely for convenience.  Use it to include all
+* of the separate WCSLIB headers.
+*
+*===========================================================================*/
+
+#ifndef WCSLIB_WCSLIB
+#define WCSLIB_WCSLIB
+
+#include "cel.h"
+#include "fitshdr.h"
+#include "lin.h"
+#include "log.h"
+#include "prj.h"
+#include "spc.h"
+#include "sph.h"
+#include "spx.h"
+#include "tab.h"
+#include "wcs.h"
+#include "wcserr.h"
+#include "wcsfix.h"
+#include "wcshdr.h"
+#include "wcsmath.h"
+#include "wcsprintf.h"
+#include "wcstrig.h"
+#include "wcsunits.h"
+#include "wcsutil.h"
+
+#endif /* WCSLIB_WCSLIB */
diff --git a/cextern/wcslib/C/wcsmath.h b/cextern/wcslib/C/wcsmath.h
new file mode 100644
index 0000000..f5eb660
--- /dev/null
+++ b/cextern/wcslib/C/wcsmath.h
@@ -0,0 +1,70 @@
+/*============================================================================
+
+  WCSLIB 4.16 - an implementation of the FITS WCS standard.
+  Copyright (C) 1995-2012, Mark Calabretta
+
+  This file is part of WCSLIB.
+
+  WCSLIB is free software: you can redistribute it and/or modify it under the
+  terms of the GNU Lesser General Public License as published by the Free
+  Software Foundation, either version 3 of the License, or (at your option)
+  any later version.
+
+  WCSLIB 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 Lesser General Public License for
+  more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with WCSLIB.  If not, see http://www.gnu.org/licenses.
+
+  Direct correspondence concerning WCSLIB to mark at calabretta.id.au
+
+  Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
+  http://www.atnf.csiro.au/people/Mark.Calabretta
+  $Id: wcsmath.h,v 4.16 2012/11/07 04:42:44 cal103 Exp $
+*=============================================================================
+*
+* Summary of wcsmath.h
+* --------------------
+* Definition of mathematical constants used by WCSLIB.
+*
+*===========================================================================*/
+
+#ifndef WCSLIB_WCSMATH
+#define WCSLIB_WCSMATH
+
+#ifdef PI
+#undef PI
+#endif
+
+#ifdef D2R
+#undef D2R
+#endif
+
+#ifdef R2D
+#undef R2D
+#endif
+
+#ifdef SQRT2
+#undef SQRT2
+#endif
+
+#ifdef SQRT2INV
+#undef SQRT2INV
+#endif
+
+#define PI 3.141592653589793238462643
+#define D2R PI/180.0
+#define R2D 180.0/PI
+#define SQRT2 1.4142135623730950488
+#define SQRT2INV 1.0/SQRT2
+
+#ifdef UNDEFINED
+#undef UNDEFINED
+#endif
+
+#define UNDEFINED 987654321.0e99
+#define undefined(value) (value == UNDEFINED)
+
+#endif /* WCSLIB_WCSMATH */
diff --git a/cextern/wcslib/C/wcspih.l b/cextern/wcslib/C/wcspih.l
new file mode 100644
index 0000000..42182f7
--- /dev/null
+++ b/cextern/wcslib/C/wcspih.l
@@ -0,0 +1,1182 @@
+/*============================================================================
+
+  WCSLIB 4.16 - an implementation of the FITS WCS standard.
+  Copyright (C) 1995-2012, Mark Calabretta
+
+  This file is part of WCSLIB.
+
+  WCSLIB is free software: you can redistribute it and/or modify it under the
+  terms of the GNU Lesser General Public License as published by the Free
+  Software Foundation, either version 3 of the License, or (at your option)
+  any later version.
+
+  WCSLIB 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 Lesser General Public License for
+  more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with WCSLIB.  If not, see http://www.gnu.org/licenses.
+
+  Direct correspondence concerning WCSLIB to mark at calabretta.id.au
+
+  Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
+  http://www.atnf.csiro.au/people/Mark.Calabretta
+  $Id: wcspih.l,v 4.16 2012/11/07 04:42:44 cal103 Exp $
+*=============================================================================
+*
+* wcspih.l is a Flex description file containing the definition of a lexical
+* scanner for parsing the WCS keyrecords from a FITS primary image or image
+* extension header.
+*
+* wcspih.l requires Flex v2.5.4 or later.  Refer to wcshdr.h for a description
+* of the user interface and operating notes.
+*
+* Implementation notes
+* --------------------
+* Use of the WCSAXESa keyword is not mandatory.  Its default value is "the
+* larger of NAXIS and the largest index of these keywords [i.e. CRPIXj, PCi_j
+* or CDi_j, CDELTi, CTYPEi, CRVALi, and CUNITi] found in the FITS header".
+* Consequently the definition of WCSAXESa effectively invalidates the use of
+* NAXIS for determining the number of coordinate axes and forces a preliminary
+* pass through the header to determine the "largest index" in headers where
+* WCSAXESa was omitted.
+*
+* Furthermore, since the use of WCSAXESa is optional, there is no way to
+* determine the number of coordinate representations (the "a" value) other
+* than by parsing all of the WCS keywords in the header; even if WCSAXESa was
+* specified for some representations it cannot be known in advance whether it
+* was specified for all of those present in the header.
+*
+* Hence the definition of WCSAXESa forces the scanner to be implemented in two
+* passes.  The first pass is used to determine the number of coordinate
+* representations (up to 27) and the number of coordinate axes in each.
+* Effectively WCSAXESa is ignored unless it exceeds the "largest index" in
+* which case the keywords for the extra axes assume their default values.  The
+* number of PVi_ma and PSi_ma keywords in each representation is also counted
+* in the first pass.
+*
+* On completion of the first pass, memory is allocated for an array of the
+* required number of wcsprm structs and each of these is initialized
+* appropriately.  These structs are filled in the second pass.
+*
+* The parser does not check for duplicated keywords, it accepts the last
+* encountered.
+*
+*===========================================================================*/
+
+/* Options. */
+%option full
+%option never-interactive
+%option noyywrap
+%option outfile="wcspih.c"
+%option prefix="wcspih"
+
+/* Indices for parameterized keywords. */
+I0	[0-9]
+I1	[1-9]
+I2	[1-9][0-9]
+I3	[1-9][0-9]{2}
+I4	[1-9][0-9]{3}
+
+/* Alternate coordinate system identifier. */
+ALT	[ A-Z]
+
+/* Keyvalue data types. */
+INTEGER	[+-]?[0-9]+
+FLOAT	[+-]?([0-9]+\.?[0-9]*|\.[0-9]+)([eE][+-]?[0-9]+)?
+STRING	'([^']|'')*'
+
+/* Exclusive start states. */
+%x CROTAi PROJPn
+%x CCCCCia CCi_ja CCi_ma CCCCCCCa CCCCCCCC
+%x VALUE
+%x INTEGER_VAL FLOAT_VAL STRING_VAL
+%x COMMENT
+%x DISCARD ERROR FLUSH
+
+%{
+#include <math.h>
+#include <setjmp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "wcs.h"
+#include "wcshdr.h"
+#include "wcsmath.h"
+#include "wcsutil.h"
+
+#define INTEGER 0
+#define FLOAT   1
+#define STRING  2
+
+#define YY_DECL int wcspih(char *header, int nkeyrec, int relax, int ctrl, \
+                           int *nreject, int *nwcs, struct wcsprm **wcs)
+
+#define YY_INPUT(inbuff, count, bufsize) \
+	{ \
+	  if (wcspih_nkeyrec) { \
+	    strncpy(inbuff, wcspih_hdr, 80); \
+	    inbuff[80] = '\n'; \
+	    wcspih_hdr += 80; \
+	    wcspih_nkeyrec--; \
+	    count = 81; \
+	  } else { \
+	    count = YY_NULL; \
+	  } \
+	}
+
+/* These global variables are required by YY_INPUT. */
+char *wcspih_hdr;
+int  wcspih_nkeyrec;
+
+int wcspih_final(int alts[], double epoch[], double vsource[], int *nwcs,
+        struct wcsprm **wcs);
+int wcspih_inits(int naxis, int alts[], int npv[], int nps[], int *nwcs,
+        struct wcsprm **wcs);
+void wcspih_naxes(int naxis, int i, int j, char a, int alts[], int *npptr);
+
+/* Used in preempting the call to exit() by yy_fatal_error(). */
+jmp_buf wcspih_abort_jmp_env;
+#define exit(status) longjmp(wcspih_abort_jmp_env, status)
+
+%}
+
+%%
+	/* Keyword indices, as used in the WCS papers, e.g. PCi_ja, PVi_ma. */
+	char a;
+	int  i, j, m;
+	
+	char *cptr, *errmsg, errtxt[80], *hptr, *keep;
+	int  altlin, alts[27], ialt, idx, ipx, ix, jx, naxis, *npptr,
+	     nps[27], npv[27], pass, status, valtype, voff;
+	double epoch[27], vsource[27];
+	void *vptr, *wptr;
+	struct wcsprm *wcsp;
+	int yylex_destroy(void);
+	
+	naxis = 0;
+	for (ialt = 0; ialt < 27; ialt++) {
+	  alts[ialt] = 0;
+	  npv[ialt] = 0;
+	  nps[ialt] = 0;
+	  epoch[ialt]   = UNDEFINED;
+	  vsource[ialt] = UNDEFINED;
+	}
+	
+	/* Parameters used to implement YY_INPUT. */
+	wcspih_hdr = header;
+	wcspih_nkeyrec = nkeyrec;
+	
+	/* Our handle on the input stream. */
+	hptr = header;
+	keep = 0x0;
+	*nreject = 0;
+	
+	/* Keyword parameters. */
+	i = j = m = 0;
+	a = ' ';
+	
+	/* For decoding the keyvalue. */
+	valtype = -1;
+	idx     = -1;
+	vptr    = 0x0;
+	
+	/* For keywords that require special handling. */
+	altlin = 0;
+	npptr  = 0x0;
+	
+	/* The data structures produced. */
+	*nwcs = 0;
+	*wcs  = 0x0;
+	
+	pass = 1;
+	
+	/* Return here via longjmp() invoked by yy_fatal_error(). */
+	if (setjmp(wcspih_abort_jmp_env)) {
+	  return 3;
+	}
+	
+	BEGIN(INITIAL);
+
+
+^NAXIS"   = "" "*{INTEGER} {
+	  if (pass == 1) {
+	    sscanf(yytext, "NAXIS   = %d", &naxis);
+	  }
+	
+	  if (naxis < 0) {
+	    errmsg = errtxt;
+	    sprintf(errmsg, "Negative value of NAXIS ignored: %d", naxis);
+	    naxis = 0;
+	    BEGIN(ERROR);
+	  } else {
+	    BEGIN(DISCARD);
+	  }
+	}
+
+^WCSAXES{ALT}=" "" "*{INTEGER} {
+	  if (pass == 1) {
+	    sscanf(yytext, "WCSAXES%c= %d", &a, &i);
+	    wcspih_naxes(naxis, i, 0, a, alts, 0);
+	  }
+	  BEGIN(FLUSH);
+	}
+
+^CRPIX	{
+	  valtype = FLOAT;
+	  if (pass == 2) vptr = &((*wcs)->crpix);
+	  BEGIN(CCCCCia);
+	}
+
+^PC	{
+	  valtype = FLOAT;
+	  if (pass == 2) vptr = &((*wcs)->pc);
+	  altlin = 1;
+	  BEGIN(CCi_ja);
+	}
+
+^CD	{
+	  valtype = FLOAT;
+	  if (pass == 2) vptr = &((*wcs)->cd);
+	  altlin = 2;
+	  BEGIN(CCi_ja);
+	}
+
+^CDELT	{
+	  valtype = FLOAT;
+	  if (pass == 2) vptr = &((*wcs)->cdelt);
+	  BEGIN(CCCCCia);
+	}
+
+^CROTA	{
+	  valtype = FLOAT;
+	  if (pass == 2) vptr = &((*wcs)->crota);
+	  altlin = 4;
+	  BEGIN(CROTAi);
+	}
+
+^CUNIT	{
+	  valtype = STRING;
+	  if (pass == 2) vptr = &((*wcs)->cunit);
+	  BEGIN(CCCCCia);
+	}
+
+^CTYPE	{
+	  valtype = STRING;
+	  if (pass == 2) vptr = &((*wcs)->ctype);
+	  BEGIN(CCCCCia);
+	}
+
+^CRVAL	{
+	  valtype = FLOAT;
+	  if (pass == 2) vptr = &((*wcs)->crval);
+	  BEGIN(CCCCCia);
+	}
+
+^LONPOLE {
+	  valtype = FLOAT;
+	  if (pass == 2) vptr = &((*wcs)->lonpole);
+	  BEGIN(CCCCCCCa);
+	}
+
+^LATPOLE {
+	  valtype = FLOAT;
+	  if (pass == 2) vptr = &((*wcs)->latpole);
+	  BEGIN(CCCCCCCa);
+	}
+
+^RESTFRQ {
+	  valtype = FLOAT;
+	  if (pass == 2) vptr = &((*wcs)->restfrq);
+	  BEGIN(CCCCCCCa);
+	}
+
+^RESTFREQ {
+	  valtype = FLOAT;
+	  if (pass == 2) vptr = &((*wcs)->restfrq);
+	  unput(' ');
+	  BEGIN(CCCCCCCa);
+	}
+
+^RESTWAV {
+	  valtype = FLOAT;
+	  if (pass == 2) vptr = &((*wcs)->restwav);
+	  BEGIN(CCCCCCCa);
+	}
+
+^PV	{
+	  valtype = FLOAT;
+	  if (pass == 2) vptr = &((*wcs)->pv);
+	  npptr = npv;
+	  BEGIN(CCi_ma);
+	}
+
+^PROJP	{
+	  valtype = FLOAT;
+	  if (pass == 2) vptr = &((*wcs)->pv);
+	  npptr = npv;
+	  BEGIN(PROJPn);
+	}
+
+^PS	{
+	  valtype = STRING;
+	  if (pass == 2) vptr = &((*wcs)->ps);
+	  npptr = nps;
+	  BEGIN(CCi_ma);
+	}
+
+^CNAME	{
+	  valtype = STRING;
+	  if (pass == 2) vptr = &((*wcs)->cname);
+	  BEGIN(CCCCCia);
+	}
+
+^CRDER	{
+	  valtype = FLOAT;
+	  if (pass == 2) vptr = &((*wcs)->crder);
+	  BEGIN(CCCCCia);
+	}
+
+^CSYER	{
+	  valtype = FLOAT;
+	  if (pass == 2) vptr = &((*wcs)->csyer);
+	  BEGIN(CCCCCia);
+	}
+
+^DATE-AVG {
+	  valtype = STRING;
+	  if (pass == 2) vptr = (*wcs)->dateavg;
+	  if (ctrl < -10) keep = wcspih_hdr - 80;
+	  BEGIN(CCCCCCCC);
+	}
+
+^DATE-OBS {
+	  valtype = STRING;
+	  if (pass == 2) vptr = (*wcs)->dateobs;
+	  if (ctrl < -10) keep = wcspih_hdr - 80;
+	  BEGIN(CCCCCCCC);
+	}
+
+^EPOCH{ALT}"  " {
+	  sscanf(yytext, "EPOCH%c", &a);
+	
+	  if (a == ' ' || relax & WCSHDR_EPOCHa) {
+	    valtype = FLOAT;
+	    if (pass == 2) {
+	      vptr = epoch;
+	      if (a >= 'A') {
+	        vptr = (void *)((double *)vptr + alts[a-'A'+1]);
+	      }
+	    }
+	
+	    unput(' ');
+	    BEGIN(CCCCCCCa);
+	
+	  } else if (relax & WCSHDR_reject) {
+	    errmsg = "EPOCH keyword may not have an alternate version code";
+	    BEGIN(ERROR);
+	
+	  } else {
+	    BEGIN(DISCARD);
+	  }
+	}
+
+^EQUINOX {
+	  valtype = FLOAT;
+	  if (pass == 2) vptr = &((*wcs)->equinox);
+	  BEGIN(CCCCCCCa);
+	}
+
+^MJD-AVG" " {
+	  valtype = FLOAT;
+	  if (pass == 2) vptr = &((*wcs)->mjdavg);
+	  if (ctrl < -10) keep = wcspih_hdr - 80;
+	  BEGIN(CCCCCCCC);
+	}
+
+^MJD-OBS" " {
+	  valtype = FLOAT;
+	  if (pass == 2) vptr = &((*wcs)->mjdobs);
+	  if (ctrl < -10) keep = wcspih_hdr - 80;
+	  BEGIN(CCCCCCCC);
+	}
+
+^OBSGEO-X {
+	  valtype = FLOAT;
+	  if (pass == 2) vptr = (*wcs)->obsgeo;
+	  if (ctrl < -10) keep = wcspih_hdr - 80;
+	  BEGIN(CCCCCCCC);
+	}
+
+^OBSGEO-Y {
+	  valtype = FLOAT;
+	  if (pass == 2) vptr = (*wcs)->obsgeo + 1;
+	  if (ctrl < -10) keep = wcspih_hdr - 80;
+	  BEGIN(CCCCCCCC);
+	}
+
+^OBSGEO-Z {
+	  valtype = FLOAT;
+	  if (pass == 2) vptr = (*wcs)->obsgeo + 2;
+	  if (ctrl < -10) keep = wcspih_hdr - 80;
+	  BEGIN(CCCCCCCC);
+	}
+
+^RADESYS {
+	  valtype = STRING;
+	  if (pass == 2) vptr = (*wcs)->radesys;
+	  BEGIN(CCCCCCCa);
+	}
+
+^RADECSYS {
+	  if (relax & WCSHDR_RADECSYS) {
+	    valtype = STRING;
+	    if (pass == 2) vptr = (*wcs)->radesys;
+	    unput(' ');
+	    BEGIN(CCCCCCCa);
+	
+	  } else if (relax & WCSHDR_reject) {
+	    errmsg = "RADECSYS is non-standard, use RADESYSa";
+	    BEGIN(ERROR);
+	
+	  } else {
+	    BEGIN(DISCARD);
+	  }
+	}
+
+^SPECSYS {
+	  valtype = STRING;
+	  if (pass == 2) vptr = (*wcs)->specsys;
+	  BEGIN(CCCCCCCa);
+	}
+
+^SSYSOBS {
+	  valtype = STRING;
+	  if (pass == 2) vptr = (*wcs)->ssysobs;
+	  BEGIN(CCCCCCCa);
+	}
+
+^SSYSSRC {
+	  valtype = STRING;
+	  if (pass == 2) vptr = (*wcs)->ssyssrc;
+	  BEGIN(CCCCCCCa);
+	}
+
+^VELANGL {
+	  valtype = FLOAT;
+	  if (pass == 2) vptr = &((*wcs)->velangl);
+	  BEGIN(CCCCCCCa);
+	}
+
+^VELOSYS {
+	  valtype = FLOAT;
+	  if (pass == 2) vptr = &((*wcs)->velosys);
+	  BEGIN(CCCCCCCa);
+	}
+
+^VELREF{ALT}" " {
+	  sscanf(yytext, "VELREF%c", &a);
+	
+	  if (a == ' ' || relax & WCSHDR_VELREFa) {
+	    valtype = INTEGER;
+	    if (pass == 2) vptr = &((*wcs)->velref);
+	
+	    unput(a);
+	    BEGIN(CCCCCCCa);
+	
+	  } else if (relax & WCSHDR_reject) {
+	    errmsg = "VELREF keyword may not have an alternate version code";
+	    BEGIN(ERROR);
+	
+	  } else {
+	    BEGIN(DISCARD);
+	  }
+	}
+
+^VSOURCE{ALT} {
+	  sscanf(yytext, "VSOURCE%c", &a);
+	
+	  if (relax & WCSHDR_VSOURCE) {
+	    valtype = FLOAT;
+	    if (pass == 2) {
+	      vptr = vsource;
+	      if (a >= 'A') {
+	        vptr = (void *)((double *)vptr + alts[a-'A'+1]);
+	      }
+	    }
+	
+	    unput(' ');
+	    BEGIN(CCCCCCCa);
+	
+	  } else if (relax & WCSHDR_reject) {
+	    errmsg = "Deprecated VSOURCEa keyword rejected";
+	    BEGIN(ERROR);
+	
+	  } else {
+	    BEGIN(DISCARD);
+	  }
+	}
+
+^WCSNAME {
+	  valtype = STRING;
+	  if (pass == 2) vptr = (*wcs)->wcsname;
+	  BEGIN(CCCCCCCa);
+	}
+
+^ZSOURCE {
+	  valtype = FLOAT;
+	  if (pass == 2) vptr = &((*wcs)->zsource);
+	  BEGIN(CCCCCCCa);
+	}
+
+^END" "{77} {
+	  yyless(0);
+	  if (wcspih_nkeyrec) {
+	    wcspih_nkeyrec = 0;
+	    errmsg = "Keyrecords following the END keyrecord were ignored";
+	    BEGIN(ERROR);
+	  } else {
+	    BEGIN(DISCARD);
+	  }
+	}
+
+^.	{
+	  BEGIN(DISCARD);
+	}
+
+<CCCCCia>{I1}{ALT}" " |
+<CCCCCia>{I2}{ALT} {
+	  sscanf(yytext, "%d%c", &i, &a);
+	  idx = i - 1;
+	  BEGIN(VALUE);
+	}
+
+<CCCCCia>{I3} {
+	  /* Invalid axis number will be caught by <VALUE>. */
+	  sscanf(yytext, "%3d", &i);
+	  BEGIN(VALUE);
+	}
+
+<CCCCCia>. {
+	  BEGIN(DISCARD);
+	}
+
+<CCi_ja>{I1}_{I1}{ALT}"  " |
+<CCi_ja>{I1}_{I2}{ALT}" " |
+<CCi_ja>{I2}_{I1}{ALT}" " |
+<CCi_ja>{I2}_{I2}{ALT} {
+	  sscanf(yytext, "%d_%d%c", &i, &j, &a);
+	  if (pass == 2) {
+	    wcsp = *wcs;
+	    if (a != ' ') {
+	      wcsp += alts[a-'A'+1];
+	    }
+	
+	    idx = (i-1)*(wcsp->naxis) + j - 1;
+	  }
+	  BEGIN(VALUE);
+	}
+
+<CCi_ja>{I1}_{I3}{ALT} |
+<CCi_ja>{I3}_{I1}{ALT} |
+<CCi_ja>{I1}_{I4} |
+<CCi_ja>{I2}_{I3} |
+<CCi_ja>{I3}_{I2} |
+<CCi_ja>{I4}_{I1} {
+	  /* Invalid axis numbers will be caught by <VALUE>. */
+	  sscanf(yytext, "%d_%d", &i, &j);
+	  BEGIN(VALUE);
+	}
+
+<CCi_ja>{I0}{6} {
+	  /* This covers the defunct forms CD00i00j and PC00i00j. */
+	  if (((relax & WCSHDR_PC00i00j) && (altlin == 1)) ||
+	      ((relax & WCSHDR_CD00i00j) && (altlin == 2))) {
+	    sscanf(yytext, "%3d%3d", &i, &j);
+	    a = ' ';
+	    if (pass == 2) {
+	      idx = (i-1)*((*wcs)->naxis) + j - 1;
+	    }
+	    BEGIN(VALUE);
+	
+	  } else if (relax & WCSHDR_reject) {
+	    errmsg = errtxt;
+	    sprintf(errmsg, "Defunct form of %si_ja keyword",
+	                     (altlin==1) ? "PC" : "CD");
+	    BEGIN(ERROR);
+	
+	  } else {
+	    BEGIN(DISCARD);
+	  }
+	}
+
+<CCi_ja>. {
+	  BEGIN(DISCARD);
+	}
+
+<CROTAi>{I1}{ALT}" " |
+<CROTAi>{I2}{ALT} {
+	  sscanf(yytext, "%d%c", &i, &a);
+	  if (a == ' ' || relax & WCSHDR_CROTAia) {
+	    idx = i - 1;
+	    BEGIN(VALUE);
+	
+	  } else if (relax & WCSHDR_reject) {
+	    errmsg = "CROTAn keyword may not have an alternate version code";
+	    BEGIN(ERROR);
+	
+	  } else {
+	    BEGIN(DISCARD);
+	  }
+	}
+
+<CROTAi>{I3} {
+	  sscanf(yytext, "%d", &i);
+	  a = ' ';
+	  idx = i - 1;
+	  BEGIN(VALUE);
+	}
+
+<CROTAi>. {
+	  BEGIN(DISCARD);
+	}
+
+<CCCCCCCa>{ALT} |
+<CCCCCCCC>. {
+	  idx = -1;
+	
+	  if (YY_START == CCCCCCCa) {
+	    sscanf(yytext, "%c", &a);
+	  } else {
+	    unput(yytext[0]);
+	    a = 0;
+	  }
+	  BEGIN(VALUE);
+	}
+
+<CCCCCCCa>. {
+	  BEGIN(DISCARD);
+	}
+
+<CCi_ma>{I1}_{I0}{ALT}"  " |
+<CCi_ma>{I1}_{I2}{ALT}" " |
+<CCi_ma>{I2}_{I0}{ALT}" " |
+<CCi_ma>{I2}_{I2}{ALT} {
+	  sscanf(yytext, "%d_%d%c", &i, &m, &a);
+	  idx = -1;
+	  BEGIN(VALUE);
+	}
+
+<CCi_ma>{I1}_{I3}{ALT} |
+<CCi_ma>{I3}_{I0}{ALT} |
+<CCi_ma>{I1}_{I4} |
+<CCi_ma>{I2}_{I3} |
+<CCi_ma>{I3}_{I2} |
+<CCi_ma>{I4}_{I0} {
+	  /* Invalid parameters will be caught by <VALUE>. */
+	  sscanf(yytext, "%d_%d", &i, &m);
+	  BEGIN(VALUE);
+	}
+
+<CCi_ma>. {
+	  BEGIN(DISCARD);
+	}
+
+<PROJPn>{I0}"  " {
+	  if (relax & WCSHDR_PROJPn) {
+	    sscanf(yytext, "%d", &m);
+	    i = 0;
+	    a = ' ';
+	    idx = -1;
+	    BEGIN(VALUE);
+	
+	  } else if (relax & WCSHDR_reject) {
+	    errmsg = "Defunct PROJPn keyword rejected";
+	    BEGIN(ERROR);
+	
+	  } else {
+	    BEGIN(DISCARD);
+	  }
+	}
+
+<PROJPn>. {
+	  BEGIN(DISCARD);
+	}
+
+<VALUE>=" "+ {
+	  /* Do checks on i, j & m. */
+	  if (i > 99 || j > 99 || m > 99) {
+	    if (relax & WCSHDR_reject) {
+	      errmsg = errtxt;
+	      if (i > 99 || j > 99) {
+	        sprintf(errmsg, "Axis number exceeds 99");
+	      } else if (m > 99) {
+	        sprintf(errmsg, "Parameter number exceeds 99");
+	      }
+	      BEGIN(ERROR);
+	
+	    } else {
+	      /* Pretend we don't recognize it. */
+	      BEGIN(DISCARD);
+	    }
+	
+	  } else {
+	    if (valtype == INTEGER) {
+	      BEGIN(INTEGER_VAL);
+	    } else if (valtype == FLOAT) {
+	      BEGIN(FLOAT_VAL);
+	    } else if (valtype == STRING) {
+	      BEGIN(STRING_VAL);
+	    } else {
+	      errmsg = errtxt;
+	      sprintf(errmsg, "Internal parser ERROR, bad data type: %d",
+	        valtype);
+	      BEGIN(ERROR);
+	    }
+	  }
+	}
+
+<VALUE>. {
+	  errmsg = "Invalid KEYWORD = VALUE syntax";
+	  BEGIN(ERROR);
+	}
+
+<INTEGER_VAL>{INTEGER} {
+	  if (pass == 1) {
+	    wcspih_naxes(naxis, i, j, a, alts, npptr);
+	    BEGIN(FLUSH);
+	
+	  } else {
+	    if (vptr) {
+	      /* Determine the coordinate representation. */
+	      for (ialt = 0; ialt < *nwcs; ialt++) {
+	        /* The loop here is for keywords that apply */
+	        /* to every alternate; these have a == 0. */
+	        if (a >= 'A') {
+	          ialt = alts[a-'A'+1];
+	        }
+	
+	        wptr = vptr;
+	        if (ialt) {
+	          voff = (char *)(*wcs+ialt) - (char *)(*wcs);
+	          wptr = (void *)((char *)vptr + voff);
+	        }
+	
+	        /* Apply keyword parameterization. */
+	        if (idx >= 0) {
+	          wptr = *((int **)wptr) + idx;
+	        }
+	
+	        /* Read the keyvalue. */
+	        sscanf(yytext, "%d", (int *)wptr);
+	
+	        if (a) break;
+	      }
+	
+	      BEGIN(COMMENT);
+	
+	    } else {
+	      errmsg = "Internal parser ERROR, null int pointer";
+	      BEGIN(ERROR);
+	    }
+	  }
+	}
+
+<INTEGER_VAL>. {
+	  errmsg = "An integer value was expected";
+	  BEGIN(ERROR);
+	}
+
+<FLOAT_VAL>{FLOAT} {
+	  if (pass == 1) {
+	    wcspih_naxes(naxis, i, j, a, alts, npptr);
+	    BEGIN(FLUSH);
+	
+	  } else {
+	    if (vptr) {
+	      /* Determine the coordinate representation. */
+	      for (ialt = 0; ialt < *nwcs; ialt++) {
+	        /* The loop here is for keywords like MJD-OBS that */
+	        /* apply to every alternate; these have a == 0.  */
+	        if (a >= 'A') {
+	          ialt = alts[a-'A'+1];
+	        }
+	
+	        wptr = vptr;
+	        if (ialt) {
+	          voff = (char *)(*wcs+ialt) - (char *)(*wcs);
+	          wptr = (void *)((char *)vptr + voff);
+	        }
+	
+	        /* Apply keyword parameterization. */
+	        if (idx >= 0) {
+	          wptr = *((double **)wptr) + idx;
+	
+	        } else if (npptr == npv) {
+	          ipx = (*wcs+ialt)->npv++;
+	          (*wcs+ialt)->pv[ipx].i = i;
+	          (*wcs+ialt)->pv[ipx].m = m;
+	          wptr = &((*wcs+ialt)->pv[ipx].value);
+	        }
+	
+	        /* Read the keyvalue. */
+	        wcsutil_str2double(yytext, "%lf", (double *)wptr);
+	
+	        /* Flag the presence of PCi_ja, or CDi_ja and/or CROTAia. */
+	        if (altlin) {
+	          (*wcs+ialt)->altlin |= altlin;
+	          altlin = 0;
+	        }
+	
+	        if (a) break;
+	      }
+	
+	      BEGIN(COMMENT);
+	
+	    } else {
+	      errmsg = "Internal parser ERROR, null float pointer";
+	      BEGIN(ERROR);
+	    }
+	  }
+	}
+
+<FLOAT_VAL>. {
+	  errmsg = "A floating-point value was expected";
+	  BEGIN(ERROR);
+	}
+
+<STRING_VAL>{STRING} {
+	  if (pass == 1) {
+	    wcspih_naxes(naxis, i, j, a, alts, npptr);
+	    BEGIN(FLUSH);
+	
+	  } else {
+	    if (vptr) {
+	      /* Determine the coordinate representation. */
+	      for (ialt = 0; ialt < *nwcs; ialt++) {
+	        /* The loop here is for keywords like DATE-OBS that */
+	        /* apply to every alternate; these have a == 0.   */
+	        if (a >= 'A') {
+	          ialt = alts[a-'A'+1];
+	        }
+	
+	        wptr = vptr;
+	        if (ialt) {
+	          voff = (char *)(*wcs+ialt) - (char *)(*wcs);
+	          wptr = (void *)((char *)vptr + voff);
+	        }
+	
+	        /* Apply keyword parameterization. */
+	        if (idx >= 0) {
+	          wptr = *((char (**)[72])wptr) + idx;
+	
+	        } else if (npptr == nps) {
+	          ipx = (*wcs+ialt)->nps++;
+	          (*wcs+ialt)->ps[ipx].i = i;
+	          (*wcs+ialt)->ps[ipx].m = m;
+	          wptr = (*wcs+ialt)->ps[ipx].value;
+	        }
+	
+	        /* Read the keyvalue. */
+	        cptr = (char *)wptr;
+	        strcpy(cptr, yytext+1);
+	
+	        /* Squeeze out repeated quotes. */
+	        ix = 0;
+	        for (jx = 0; jx < 72; jx++) {
+	          if (ix < jx) {
+	            cptr[ix] = cptr[jx];
+	          }
+	
+	          if (cptr[jx] == '\0') {
+	            if (ix) cptr[ix-1] = '\0';
+	            break;
+	          } else if (cptr[jx] == '\'' && cptr[jx+1] == '\'') {
+	            jx++;
+	          }
+	
+	          ix++;
+	        }
+	
+	        if (a) break;
+	      }
+	
+	      BEGIN(COMMENT);
+	
+	    } else {
+	      errmsg = "Internal parser ERROR, null string pointer";
+	      BEGIN(ERROR);
+	    }
+	  }
+	}
+
+<STRING_VAL>. {
+	  errmsg = "A string value was expected";
+	  BEGIN(ERROR);
+	}
+
+<COMMENT>" "*\/.* |
+<COMMENT>" "* {
+	  BEGIN(FLUSH);
+	}
+
+<COMMENT>. {
+	  errmsg = "Malformed keycomment";
+	  BEGIN(ERROR);
+	}
+
+<DISCARD>.* {
+	  if (pass == 2) {
+	    if (ctrl < 0) {
+	      /* Preserve discards. */
+	      keep = wcspih_hdr - 80;
+	
+	    } else if (ctrl > 2) {
+	      fprintf(stderr, "%.80s\n  Discarded.\n", wcspih_hdr-80);
+	    }
+	  }
+	  BEGIN(FLUSH);
+	}
+
+<ERROR>.* {
+	  (*nreject)++;
+	  if (pass == 2) {
+	    if (ctrl%10 == -1) {
+	      /* Preserve rejects. */
+	      keep = wcspih_hdr - 80;
+	    }
+	
+	    if (abs(ctrl%10) > 1) {
+	      fprintf(stderr, "%.80s\n%4d: %s.\n", wcspih_hdr-80, *nreject,
+	        errmsg);
+	    }
+	  }
+	  BEGIN(FLUSH);
+	}
+
+<FLUSH>.*\n {
+	  if (pass == 2 && keep) {
+	    if (hptr < keep) {
+	      strncpy(hptr, keep, 80);
+	    }
+	    hptr += 80;
+	  }
+	
+	  i = j = m = 0;
+	  a = ' ';
+	  valtype = -1;
+	  keep = 0x0;
+	  altlin = 0;
+	  npptr = 0x0;
+	  BEGIN(INITIAL);
+	}
+
+<<EOF>>	 {
+	  /* End-of-input. */
+	  if (pass == 1) {
+	    if ((status = wcspih_inits(naxis, alts, npv, nps, nwcs, wcs)) ||
+	         *nwcs == 0) {
+	      yylex_destroy();
+	      return status;
+	    }
+	
+	    if (abs(ctrl%10) > 2) {
+	      if (*nwcs == 1) {
+	        if (strcmp(wcs[0]->wcsname, "DEFAULTS") != 0) {
+	          fprintf(stderr, "Found one coordinate representation.\n");
+	        }
+	      } else {
+	        fprintf(stderr, "Found %d coordinate representations.\n",
+	          *nwcs);
+	      }
+	    }
+	
+	    wcspih_hdr = header;
+	    wcspih_nkeyrec = nkeyrec;
+	    *nreject = 0;
+	
+	    pass = 2;
+	    i = j = m = 0;
+	    a = ' ';
+	    valtype = -1;
+	
+	    yyrestart(yyin);
+	
+	  } else {
+	    yylex_destroy();
+	
+	    if (ctrl < 0) {
+	      *hptr = '\0';
+	    } else if (ctrl == 1) {
+	      fprintf(stderr, "%d WCS keyrecords were rejected.\n",
+	        *nreject);
+	    }
+	
+	    return wcspih_final(alts, epoch, vsource, nwcs, wcs);
+	  }
+	}
+
+%%
+
+/*----------------------------------------------------------------------------
+* Determine the number of coordinate representations (up to 27) and the
+* number of coordinate axes in each, and count the number of PVi_ma and
+* PSi_ma keywords in each representation.
+*---------------------------------------------------------------------------*/
+
+void wcspih_naxes(int naxis, int i, int j, char a, int alts[], int *npptr)
+
+{
+  /* On the first pass alts[] is used to determine the number of axes */
+  /* for each of the 27 possible alternate coordinate descriptions.   */
+  int ialt, *ip;
+
+  if (a == 0) {
+    return;
+  }
+
+  ialt = 0;
+  if (a != ' ') {
+    ialt = a - 'A' + 1;
+  }
+
+  ip = alts + ialt;
+
+  if (*ip < naxis) {
+    *ip = naxis;
+  }
+
+  /* i or j can be greater than naxis. */
+  if (*ip < i) {
+    *ip = i;
+  }
+
+  if (*ip < j) {
+    *ip = j;
+  }
+
+  if (npptr) {
+    npptr[ialt]++;
+  }
+}
+
+
+/*----------------------------------------------------------------------------
+* Allocate memory for an array of the required number of wcsprm structs and
+* initialize each of them.
+*---------------------------------------------------------------------------*/
+
+int wcspih_inits(
+  int naxis,
+  int alts[],
+  int npv[],
+  int nps[],
+  int *nwcs,
+  struct wcsprm **wcs)
+
+{
+  int ialt, defaults, npsmax, npvmax, status = 0;
+  struct wcsprm *wcsp;
+
+  /* Find the number of coordinate descriptions. */
+  *nwcs = 0;
+  for (ialt = 0; ialt < 27; ialt++) {
+    if (alts[ialt]) (*nwcs)++;
+  }
+
+  if ((defaults = !(*nwcs) && naxis)) {
+    /* NAXIS is non-zero but there were no WCS keywords with an alternate
+       version code; create a default WCS with blank alternate version. */
+    wcspih_naxes(naxis, 0, 0, ' ', alts, 0x0);
+    *nwcs = 1;
+  }
+
+  if (*nwcs) {
+    /* Allocate memory for the required number of wcsprm structs. */
+    if (!(*wcs = calloc(*nwcs, sizeof(struct wcsprm)))) {
+      return 2;
+    }
+
+    /* Record the current values of NPVMAX and NPSMAX. */
+    npvmax = wcsnpv(-1);
+    npsmax = wcsnps(-1);
+
+    /* Initialize each wcsprm struct. */
+    wcsp = *wcs;
+    *nwcs = 0;
+    for (ialt = 0; ialt < 27; ialt++) {
+      if (alts[ialt]) {
+        wcsp->flag = -1;
+        wcsnpv(npv[ialt]);
+        wcsnps(nps[ialt]);
+        if ((status = wcsini(1, alts[ialt], wcsp))) {
+          wcsvfree(nwcs, wcs);
+          break;
+        }
+
+        /* Record the alternate version code. */
+        if (ialt) {
+          wcsp->alt[0] = 'A' + ialt - 1;
+        }
+
+        /* Record in wcsname whether this is a default description. */
+        if (defaults) {
+          strcpy(wcsp->wcsname, "DEFAULTS");
+        }
+
+        /* On the second pass alts[] indexes the array of wcsprm structs. */
+        alts[ialt] = (*nwcs)++;
+
+        wcsp++;
+      }
+    }
+
+    /* Restore the original values of NPVMAX and NPSMAX. */
+    wcsnpv(npvmax);
+    wcsnps(npsmax);
+  }
+
+  return status;
+}
+
+
+/*----------------------------------------------------------------------------
+* Interpret special keywords encountered for each coordinate representation.
+*---------------------------------------------------------------------------*/
+
+int wcspih_final(
+  int alts[],
+  double epoch[],
+  double vsource[],
+  int *nwcs,
+  struct wcsprm **wcs)
+
+{
+  int ialt, status;
+  double beta, c = 299792458.0;
+
+  for (ialt = 0; ialt < *nwcs; ialt++) {
+    /* Check for EPOCH overriding EQUINOXa. */
+    if (undefined((*wcs+ialt)->equinox) && !undefined(epoch[ialt])) {
+      /* Set EQUINOXa. */
+      (*wcs+ialt)->equinox = epoch[ialt];
+    }
+
+    /* Check for VSOURCEa overriding ZSOURCEa. */
+    if (undefined((*wcs+ialt)->zsource) && !undefined(vsource[ialt])) {
+      /* Convert relativistic Doppler velocity to redshift. */
+      beta = vsource[ialt]/c;
+      (*wcs+ialt)->zsource = (1.0+beta)/sqrt(1.0 - beta*beta) - 1.0;
+    }
+
+    /* Interpret -TAB header keywords. */
+    if ((status = wcstab(*wcs+ialt))) {
+       wcsvfree(nwcs, wcs);
+       return status;
+    }
+  }
+
+  return 0;
+}
diff --git a/cextern/wcslib/C/wcsprintf.c b/cextern/wcslib/C/wcsprintf.c
new file mode 100644
index 0000000..5c4b5fb
--- /dev/null
+++ b/cextern/wcslib/C/wcsprintf.c
@@ -0,0 +1,118 @@
+/*============================================================================
+
+  WCSLIB 4.16 - an implementation of the FITS WCS standard.
+  Copyright (C) 1995-2012, Mark Calabretta
+
+  This file is part of WCSLIB.
+
+  WCSLIB is free software: you can redistribute it and/or modify it under the
+  terms of the GNU Lesser General Public License as published by the Free
+  Software Foundation, either version 3 of the License, or (at your option)
+  any later version.
+
+  WCSLIB 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 Lesser General Public License for
+  more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with WCSLIB.  If not, see http://www.gnu.org/licenses.
+
+  Direct correspondence concerning WCSLIB to mark at calabretta.id.au
+
+  Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
+  http://www.atnf.csiro.au/people/Mark.Calabretta
+  $Id: wcsprintf.c,v 4.16 2012/11/07 04:42:44 cal103 Exp $
+*===========================================================================*/
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "wcsprintf.h"
+
+static FILE  *wcsprintf_file = 0x0;
+static char  *wcsprintf_buff = 0x0;
+static char  *wcsprintf_bufp = 0x0;
+static size_t wcsprintf_size = 0;
+
+/*--------------------------------------------------------------------------*/
+
+int wcsprintf_set(FILE *wcsout)
+{
+  if (wcsout != 0x0) {
+    /* Output to file. */
+    wcsprintf_file = wcsout;
+
+    if (wcsprintf_buff != 0x0) {
+      /* Release the buffer. */
+      free(wcsprintf_buff);
+      wcsprintf_buff = 0x0;
+    }
+
+  } else {
+    /* Output to buffer. */
+    if (wcsprintf_buff == 0x0) {
+      /* Allocate a buffer. */
+      wcsprintf_buff = malloc(1024);
+      if (wcsprintf_buff == NULL) {
+        return 1;
+      }
+      wcsprintf_size = 1024;
+    }
+
+    /* Reset pointer to the start of the buffer. */
+    wcsprintf_bufp = wcsprintf_buff;
+    *wcsprintf_bufp = '\0';
+  }
+
+  return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+
+const char *wcsprintf_buf(void)
+{
+  return wcsprintf_buff;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int wcsprintf(const char *format, ...)
+{
+  int  nbytes;
+  size_t  used;
+  va_list arg_list;
+
+  if (wcsprintf_buff == 0x0 && wcsprintf_file == 0x0) {
+    /* Send output to stdout if wcsprintf_set() hasn't been called. */
+    wcsprintf_file = stdout;
+  }
+
+  va_start(arg_list, format);
+
+  if (wcsprintf_file) {
+    /* Output to file. */
+    nbytes = vfprintf(wcsprintf_file, format, arg_list);
+
+  } else {
+    /* Output to buffer. */
+    used = wcsprintf_bufp - wcsprintf_buff;
+    if (wcsprintf_size - used < 128) {
+      /* Expand the buffer. */
+      wcsprintf_size += 1024;
+      wcsprintf_buff = realloc(wcsprintf_buff, wcsprintf_size);
+      if (wcsprintf_buff == NULL) {
+        return 1;
+      }
+      wcsprintf_bufp = wcsprintf_buff + used;
+    }
+
+    nbytes = vsprintf(wcsprintf_bufp, format, arg_list);
+    wcsprintf_bufp += nbytes;
+  }
+
+  va_end(arg_list);
+
+  return nbytes;
+}
diff --git a/cextern/wcslib/C/wcsprintf.h b/cextern/wcslib/C/wcsprintf.h
new file mode 100644
index 0000000..3420f2d
--- /dev/null
+++ b/cextern/wcslib/C/wcsprintf.h
@@ -0,0 +1,125 @@
+/*============================================================================
+
+  WCSLIB 4.16 - an implementation of the FITS WCS standard.
+  Copyright (C) 1995-2012, Mark Calabretta
+
+  This file is part of WCSLIB.
+
+  WCSLIB is free software: you can redistribute it and/or modify it under the
+  terms of the GNU Lesser General Public License as published by the Free
+  Software Foundation, either version 3 of the License, or (at your option)
+  any later version.
+
+  WCSLIB 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 Lesser General Public License for
+  more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with WCSLIB.  If not, see http://www.gnu.org/licenses.
+
+  Direct correspondence concerning WCSLIB to mark at calabretta.id.au
+
+  Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
+  http://www.atnf.csiro.au/people/Mark.Calabretta
+  $Id: wcsprintf.h,v 4.16 2012/11/07 04:42:44 cal103 Exp $
+*=============================================================================
+*
+* WCSLIB 4.16 - C routines that implement the FITS World Coordinate System
+* (WCS) standard.
+*
+* Summary of the wcsprintf routines
+* ---------------------------------
+* These routines allow diagnostic output from celprt(), linprt(), prjprt(),
+* spcprt(), tabprt(), wcsprt(), and wcserr_prt() to be redirected to a file or
+* captured in a string buffer.  Those routines all use wcsprintf() for output.
+*
+*
+* wcsprintf() - Print function used by WCSLIB diagnostic routines
+* ---------------------------------------------------------------
+* wcsprintf() is used by the celprt(), linprt(), prjprt(), spcprt(), tabprt(),
+* wcsprt(), and wcserr_prt() routines.  Its output may be redirected to a file
+* or string buffer via wcsprintf_set().  By default output goes to stdout.
+*
+* Given:
+*   format    char*     Format string, passed to one of the printf(3) family
+*                       of stdio library functions.
+*
+*   ...       mixed     Argument list matching format, as per printf(3).
+*
+* Function return value:
+*             int       Number of bytes written.
+*
+*
+* wcsprintf_set() - Set output disposition for wcsprintf()
+* --------------------------------------------------------
+* wcsprintf_set() sets the output disposition for wcsprintf() which is used by
+* the celprt(), linprt(), prjprt(), spcprt(), tabprt(), wcsprt(), and
+* wcserr_prt() routines.
+*
+* Output goes to stdout by default if wcsprintf_set() has not been called.
+*
+* Given:
+*   wcsout    FILE*     Pointer to an output stream that has been opened for
+*                       writing, e.g. by the fopen() stdio library function,
+*                       or one of the predefined stdio output streams - stdout
+*                       and stderr.  If zero (NULL), output is written to an
+*                       internally-allocated string buffer, the address of
+*                       which may be obtained by wcsprintf_buf().
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*
+*
+* wcsprintf_buf() - Get the address of the internal string buffer
+* ---------------------------------------------------------------
+* wcsprintf_buf() returns the address of the internal string buffer created
+* when wcsprintf_set() is invoked with its FILE* argument set to zero.
+*
+* Function return value:
+*             const char *
+*                       Address of the internal string buffer.  The user may
+*                       free this buffer by calling wcsprintf_set() with a
+*                       valid FILE*, e.g. stdout.  The free() stdlib library
+*                       function must NOT be invoked on this const pointer.
+*
+*
+* WCSPRINTF_PTR() macro - Print addresses in a consistent way
+* -----------------------------------------------------------
+* WCSPRINTF_PTR() is a preprocessor macro used to print addresses in a
+* consistent way.
+*
+* On some systems the "%p" format descriptor renders a NULL pointer as the
+* string "0x0".  On others, however, it produces "0" or even "(nil)".  On
+* some systems a non-zero address is prefixed with "0x", on others, not.
+*
+* The WCSPRINTF_PTR() macro ensures that a NULL pointer is always rendered as
+* "0x0" and that non-zero addresses are prefixed with "0x" thus providing
+* consistency, for example, for comparing the output of test programs.
+*
+*===========================================================================*/
+
+#ifndef WCSLIB_WCSPRINTF
+#define WCSLIB_WCSPRINTF
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define WCSPRINTF_PTR(str1, ptr, str2) \
+  if (ptr) { \
+    wcsprintf("%s%#lx%s", (str1), (unsigned long)(ptr), (str2)); \
+  } else { \
+    wcsprintf("%s0x0%s", (str1), (str2)); \
+  }
+
+int wcsprintf_set(FILE *wcsout);
+int wcsprintf(const char *format, ...);
+const char *wcsprintf_buf(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* WCSLIB_WCSPRINTF */
diff --git a/cextern/wcslib/C/wcstrig.c b/cextern/wcslib/C/wcstrig.c
new file mode 100644
index 0000000..2c01bcd
--- /dev/null
+++ b/cextern/wcslib/C/wcstrig.c
@@ -0,0 +1,219 @@
+/*============================================================================
+
+  WCSLIB 4.16 - an implementation of the FITS WCS standard.
+  Copyright (C) 1995-2012, Mark Calabretta
+
+  This file is part of WCSLIB.
+
+  WCSLIB is free software: you can redistribute it and/or modify it under the
+  terms of the GNU Lesser General Public License as published by the Free
+  Software Foundation, either version 3 of the License, or (at your option)
+  any later version.
+
+  WCSLIB 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 Lesser General Public License for
+  more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with WCSLIB.  If not, see http://www.gnu.org/licenses.
+
+  Direct correspondence concerning WCSLIB to mark at calabretta.id.au
+
+  Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
+  http://www.atnf.csiro.au/people/Mark.Calabretta
+  $Id: wcstrig.c,v 4.16 2012/11/07 04:42:44 cal103 Exp $
+*===========================================================================*/
+
+#include <math.h>
+#include <stdlib.h>
+#include "wcsmath.h"
+#include "wcstrig.h"
+
+double cosd(angle)
+
+double angle;
+
+{
+  int i;
+
+  if (fmod(angle,90.0) == 0.0) {
+    i = abs((int)floor(angle/90.0 + 0.5))%4;
+    switch (i) {
+    case 0:
+      return 1.0;
+    case 1:
+      return 0.0;
+    case 2:
+      return -1.0;
+    case 3:
+      return 0.0;
+    }
+  }
+
+  return cos(angle*D2R);
+}
+
+/*--------------------------------------------------------------------------*/
+
+double sind(angle)
+
+double angle;
+
+{
+  int i;
+
+  if (fmod(angle,90.0) == 0.0) {
+    i = abs((int)floor(angle/90.0 - 0.5))%4;
+    switch (i) {
+    case 0:
+      return 1.0;
+    case 1:
+      return 0.0;
+    case 2:
+      return -1.0;
+    case 3:
+      return 0.0;
+    }
+  }
+
+  return sin(angle*D2R);
+}
+
+/*--------------------------------------------------------------------------*/
+
+void sincosd(double angle, double *s, double *c)
+
+{
+  int i;
+
+  if (fmod(angle,90.0) == 0.0) {
+    i = abs((int)floor(angle/90.0 + 0.5))%4;
+    switch (i) {
+    case 0:
+      *s = 0.0;
+      *c = 1.0;
+      return;
+    case 1:
+      *s = (angle > 0.0) ? 1.0 : -1.0;
+      *c = 0.0;
+      return;
+    case 2:
+      *s =  0.0;
+      *c = -1.0;
+      return;
+    case 3:
+      *s = (angle > 0.0) ? -1.0 : 1.0;
+      *c = 0.0;
+      return;
+    }
+  }
+
+#ifdef HAVE_SINCOS
+  sincos(angle*D2R, s, c);
+#else
+  *s = sin(angle*D2R);
+  *c = cos(angle*D2R);
+#endif
+
+  return;
+}
+
+/*--------------------------------------------------------------------------*/
+
+double tand(angle)
+
+double angle;
+
+{
+  double resid;
+
+  resid = fmod(angle,360.0);
+  if (resid == 0.0 || fabs(resid) == 180.0) {
+    return 0.0;
+  } else if (resid == 45.0 || resid == 225.0) {
+    return 1.0;
+  } else if (resid == -135.0 || resid == -315.0) {
+    return -1.0;
+  }
+
+  return tan(angle*D2R);
+}
+
+/*--------------------------------------------------------------------------*/
+
+double acosd(v)
+
+double v;
+
+{
+  if (v >= 1.0) {
+    if (v-1.0 <  WCSTRIG_TOL) return 0.0;
+  } else if (v == 0.0) {
+    return 90.0;
+  } else if (v <= -1.0) {
+    if (v+1.0 > -WCSTRIG_TOL) return 180.0;
+  }
+
+  return acos(v)*R2D;
+}
+
+/*--------------------------------------------------------------------------*/
+
+double asind(v)
+
+double v;
+
+{
+  if (v <= -1.0) {
+    if (v+1.0 > -WCSTRIG_TOL) return -90.0;
+  } else if (v == 0.0) {
+    return 0.0;
+  } else if (v >= 1.0) {
+    if (v-1.0 <  WCSTRIG_TOL) return 90.0;
+  }
+
+  return asin(v)*R2D;
+}
+
+/*--------------------------------------------------------------------------*/
+
+double atand(v)
+
+double v;
+
+{
+  if (v == -1.0) {
+    return -45.0;
+  } else if (v == 0.0) {
+    return 0.0;
+  } else if (v == 1.0) {
+    return 45.0;
+  }
+
+  return atan(v)*R2D;
+}
+
+/*--------------------------------------------------------------------------*/
+
+double atan2d(y, x)
+
+double x, y;
+
+{
+  if (y == 0.0) {
+    if (x >= 0.0) {
+      return 0.0;
+    } else if (x < 0.0) {
+      return 180.0;
+    }
+  } else if (x == 0.0) {
+    if (y > 0.0) {
+      return 90.0;
+    } else if (y < 0.0) {
+      return -90.0;
+    }
+   }
+
+   return atan2(y,x)*R2D;
+}
diff --git a/cextern/wcslib/C/wcstrig.h b/cextern/wcslib/C/wcstrig.h
new file mode 100644
index 0000000..910230b
--- /dev/null
+++ b/cextern/wcslib/C/wcstrig.h
@@ -0,0 +1,212 @@
+/*============================================================================
+
+  WCSLIB 4.16 - an implementation of the FITS WCS standard.
+  Copyright (C) 1995-2012, Mark Calabretta
+
+  This file is part of WCSLIB.
+
+  WCSLIB is free software: you can redistribute it and/or modify it under the
+  terms of the GNU Lesser General Public License as published by the Free
+  Software Foundation, either version 3 of the License, or (at your option)
+  any later version.
+
+  WCSLIB 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 Lesser General Public License for
+  more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with WCSLIB.  If not, see http://www.gnu.org/licenses.
+
+  Direct correspondence concerning WCSLIB to mark at calabretta.id.au
+
+  Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
+  http://www.atnf.csiro.au/people/Mark.Calabretta
+  $Id: wcstrig.h,v 4.16 2012/11/07 04:42:44 cal103 Exp $
+*=============================================================================
+*
+* Summary of the wcstrig routines
+* -------------------------------
+* When dealing with celestial coordinate systems and spherical projections
+* (some moreso than others) it is often desirable to use an angular measure
+* that provides an exact representation of the latitude of the north or south
+* pole.  The WCSLIB routines use the following trigonometric functions that
+* take or return angles in degrees:
+*
+*   - cosd()
+*   - sind()
+*   - tand()
+*   - acosd()
+*   - asind()
+*   - atand()
+*   - atan2d()
+*   - sincosd()
+*
+* These "trigd" routines are expected to handle angles that are a multiple of
+* 90 degrees returning an exact result.  Some C implementations provide these
+* as part of a system library and in such cases it may (or may not!) be
+* preferable to use them.  WCSLIB provides wrappers on the standard trig
+* functions based on radian measure, adding tests for multiples of 90 degrees.
+*
+* However, wcstrig.h also provides the choice of using preprocessor macro
+* implementations of the trigd functions that don't test for multiples of
+* 90 degrees (compile with -DWCSTRIG_MACRO).  These are typically 20% faster
+* but may lead to problems near the poles.
+*
+*
+* cosd() - Cosine of an angle in degrees
+* --------------------------------------
+* cosd() returns the cosine of an angle given in degrees.
+*
+* Given:
+*   angle     double    [deg].
+*
+* Function return value:
+*             double    Cosine of the angle.
+*
+*
+* sind() - Sine of an angle in degrees
+* ------------------------------------
+* sind() returns the sine of an angle given in degrees.
+*
+* Given:
+*   angle     double    [deg].
+*
+* Function return value:
+*             double    Sine of the angle.
+*
+*
+* sincosd() - Sine and cosine of an angle in degrees
+* --------------------------------------------------
+* sincosd() returns the sine and cosine of an angle given in degrees.
+*
+* Given:
+*   angle     double    [deg].
+*
+* Returned:
+*   sin       *double   Sine of the angle.
+*
+*   cos       *double   Cosine of the angle.
+*
+* Function return value:
+*             void
+*
+*
+* tand() - Tangent of an angle in degrees
+* ---------------------------------------
+* tand() returns the tangent of an angle given in degrees.
+*
+* Given:
+*   angle     double    [deg].
+*
+* Function return value:
+*             double    Tangent of the angle.
+*
+*
+* acosd() - Inverse cosine, returning angle in degrees
+* ----------------------------------------------------
+* acosd() returns the inverse cosine in degrees.
+*
+* Given:
+*   x         double    in the range [-1,1].
+*
+* Function return value:
+*             double    Inverse cosine of x [deg].
+*
+*
+* asind() - Inverse sine, returning angle in degrees
+* --------------------------------------------------
+* asind() returns the inverse sine in degrees.
+*
+* Given:
+*   y         double    in the range [-1,1].
+*
+* Function return value:
+*             double    Inverse sine of y [deg].
+*
+*
+* atand() - Inverse tangent, returning angle in degrees
+* -----------------------------------------------------
+* atand() returns the inverse tangent in degrees.
+*
+* Given:
+*   s         double
+*
+* Function return value:
+*             double    Inverse tangent of s [deg].
+*
+*
+* atan2d() - Polar angle of (x,y), in degrees
+* -------------------------------------------
+* atan2d() returns the polar angle, beta, in degrees, of polar coordinates
+* (rho,beta) corresponding Cartesian coordinates (x,y).  It is equivalent to
+* the arg(x,y) function of WCS Paper II, though with transposed arguments.
+*
+* Given:
+*   y         double    Cartesian y-coordinate.
+*
+*   x         double    Cartesian x-coordinate.
+*
+* Function return value:
+*             double    Polar angle of (x,y) [deg].
+*
+*===========================================================================*/
+
+#ifndef WCSLIB_WCSTRIG
+#define WCSLIB_WCSTRIG
+
+#include <math.h>
+
+#include "wcsconfig.h"
+
+#ifdef HAVE_SINCOS
+  void sincos(double angle, double *sin, double *cos);
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#ifdef WCSTRIG_MACRO
+
+/* Macro implementation of the trigd functions. */
+#include "wcsmath.h"
+
+#define cosd(X) cos((X)*D2R)
+#define sind(X) sin((X)*D2R)
+#define tand(X) tan((X)*D2R)
+#define acosd(X) acos(X)*R2D
+#define asind(X) asin(X)*R2D
+#define atand(X) atan(X)*R2D
+#define atan2d(Y,X) atan2(Y,X)*R2D
+#ifdef HAVE_SINCOS
+  #define sincosd(X,S,C) sincos((X)*D2R,(S),(C))
+#else
+  #define sincosd(X,S,C) *(S) = sin((X)*D2R); *(C) = cos((X)*D2R);
+#endif
+
+#else
+
+/* Use WCSLIB wrappers or native trigd functions. */
+
+double cosd(double angle);
+double sind(double angle);
+void sincosd(double angle, double *sin, double *cos);
+double tand(double angle);
+double acosd(double x);
+double asind(double y);
+double atand(double s);
+double atan2d(double y, double x);
+
+/* Domain tolerance for asin() and acos() functions. */
+#define WCSTRIG_TOL 1e-10
+
+#endif /* WCSTRIG_MACRO */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* WCSLIB_WCSTRIG */
diff --git a/cextern/wcslib/C/wcsulex.l b/cextern/wcslib/C/wcsulex.l
new file mode 100644
index 0000000..014394f
--- /dev/null
+++ b/cextern/wcslib/C/wcsulex.l
@@ -0,0 +1,996 @@
+/*============================================================================
+
+  WCSLIB 4.16 - an implementation of the FITS WCS standard.
+  Copyright (C) 1995-2012, Mark Calabretta
+
+  This file is part of WCSLIB.
+
+  WCSLIB is free software: you can redistribute it and/or modify it under the
+  terms of the GNU Lesser General Public License as published by the Free
+  Software Foundation, either version 3 of the License, or (at your option)
+  any later version.
+
+  WCSLIB 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 Lesser General Public License for
+  more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with WCSLIB.  If not, see http://www.gnu.org/licenses.
+
+  Direct correspondence concerning WCSLIB to mark at calabretta.id.au
+
+  Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
+  http://www.atnf.csiro.au/people/Mark.Calabretta
+  $Id: wcsulex.l,v 4.16 2012/11/07 04:42:44 cal103 Exp $
+*=============================================================================
+*
+* wcsulex.l is a Flex description file containing the definition of a
+* recursive, multi-buffered lexical scanner that parses FITS units
+* specifications.
+*
+* It requires Flex v2.5.4 or later.
+*
+* Refer to wcsunits.h for a description of the user interface and operating
+* notes.
+*
+*===========================================================================*/
+
+/* Options. */
+%option full
+%option never-interactive
+%option noyywrap
+%option outfile="wcsulex.c"
+%option prefix="wcsulex"
+
+/* Exponents. */
+INTEGER	  [+-]?[1-9][0-9]*
+FRAC	  {INTEGER}"/"[1-9][0-9]*
+FLOAT	  [+-]?([0-9]+\.?[0-9]*|\.[0-9]+)
+
+/* Metric prefixes. */
+SUB3	  [munpfazy]
+SUBPREFIX [dc]|{SUB3}
+SUP3	  [kMGTPEZY]
+SUPPREFIX da|h|{SUP3}
+PREFIX	  {SUBPREFIX}|{SUPPREFIX}
+
+/* Basic and derived SI units. */
+BASIC	  m|s|g|rad|sr|K|A|mol|cd
+DERIVED	  Hz|J|W|V|N|Pa|C|[Oo]hm|S|F|Wb|T|H|lm|lx
+SI_UNIT	  {BASIC}|{DERIVED}
+
+/* Additional recognized units: all metric prefixes allowed. */
+ADD_ALL	  eV|Jy|R|G|barn
+
+/* Additional recognized units: only super-metric prefixes allowed. */
+ADD_SUP	  a|yr|pc|bit|[bB]yte
+
+/* Additional recognized units: only sub-metric prefixes allowed. */
+ADD_SUB	  mag
+
+/* Additional recognized units for which NO metric prefixes are allowed. */
+GENERAL	  deg|arcmin|arcsec|mas|d|h|min|erg|Ry|u|D
+ASTRO	  [Aa]ngstrom|AU|lyr|beam|solRad|solMass|solLum|Sun
+DEVICE	  adu|bin|chan|count|ct|photon|ph|pixel|pix|voxel
+ADD_NONE  {GENERAL}|{ASTRO}|{DEVICE}
+
+/* All additional recognized units. */
+ADD_UNIT  {ADD_ALL}|{ADD_SUP}|{ADD_SUB}|{ADD_NONE}
+
+/* Exclusive start states. */
+%x PAREN PREFIX UNITS EXPON FLUSH
+
+%{
+/* To get the prototype for fileno() from stdio.h when gcc is invoked with
+ * -std=c89 (same as -ansi) or -std=c99 since we do not define YY_INPUT. */
+#define _POSIX_SOURCE 1
+
+#include <math.h>
+#include <setjmp.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "wcserr.h"
+#include "wcsmath.h"
+#include "wcsunits.h"
+#include "wcsutil.h"
+
+#define YY_DECL int wcsulexe(const char unitstr[], int *func, double *scale, \
+                             double units[], struct wcserr **err)
+
+/* Used in preempting the call to exit() by yy_fatal_error(). */
+jmp_buf wcsulex_abort_jmp_env;
+#define exit(status) longjmp(wcsulex_abort_jmp_env, status)
+
+%}
+
+%%
+	static const char *function = "wcsulexe";
+	
+	char ctmp[72];
+	int bracket  = 0;
+	int operator = 0;
+	int paren    = 0;
+	int status   = 0;
+	int func_r, i, j;
+	double dexp, expon, factor, factor_r, types[WCSUNITS_NTYPE];
+	YY_BUFFER_STATE buf;
+	void add(double *factor, double types[], double *expon, double *scale,
+	    double units[]);
+	int yylex_destroy(void);
+	
+	if (err) *err = 0x0;
+	
+	*func = 0;
+	for (i = 0; i < WCSUNITS_NTYPE; i++) {
+	  units[i] = 0.0;
+	  types[i] = 0.0;
+	}
+	expon  = 1.0;
+	factor = 1.0;
+	*scale = 1.0;
+	
+	yy_scan_string(unitstr);
+	
+	/* Return here via longjmp() invoked by yy_fatal_error(). */
+	if (setjmp(wcsulex_abort_jmp_env)) {
+	  return wcserr_set(WCSERR_SET(UNITSERR_PARSER_ERROR),
+	    "Internal units parser error parsing '%s'", unitstr);
+	}
+	
+	BEGIN(INITIAL);
+	
+	#ifdef DEBUG
+	fprintf(stderr, "\n%s ->\n", unitstr);
+	#endif
+
+^" "+	{
+	  /* Pretend initial whitespace doesn't exist. */
+	  yy_set_bol(1);
+	}
+
+^"["	{
+	  if (bracket++) {
+	    BEGIN(FLUSH);
+	  } else {
+	    yy_set_bol(1);
+	  }
+	}
+
+^10[0-9] {
+	  status = wcserr_set(WCSERR_SET(UNITSERR_BAD_NUM_MULTIPLIER),
+	    "Invalid exponent in '%s'", unitstr);
+	  BEGIN(FLUSH);
+	}
+
+^10	{
+	  factor = 10.0;
+	  BEGIN(EXPON);
+	}
+
+^log" "*"(" {
+	  *func = 1;
+	  unput('(');
+	  BEGIN(PAREN);
+	}
+
+^ln" "*"(" {
+	  *func = 2;
+	  unput('(');
+	  BEGIN(PAREN);
+	}
+
+^exp" "*"(" {
+	  *func = 3;
+	  unput('(');
+	  BEGIN(PAREN);
+	}
+
+^[*.]	{
+	  /* Leading binary multiply. */
+	  status = wcserr_set(WCSERR_SET(UNITSERR_DANGLING_BINOP),
+	    "Dangling binary operator in '%s'", unitstr);
+	  BEGIN(FLUSH);
+	}
+
+" "+	  /* Discard whitespace in INITIAL context. */
+
+sqrt" "*"(" {
+	  expon /= 2.0;
+	  unput('(');
+	  BEGIN(PAREN);
+	}
+
+"("	{
+	  /* Gather terms in parentheses. */
+	  yyless(0);
+	  BEGIN(PAREN);
+	}
+
+[*.]	{
+	  if (operator++) {
+	    BEGIN(FLUSH);
+	  }
+	}
+
+^1"/" |
+"/"	{
+	  if (operator++) {
+	    BEGIN(FLUSH);
+	  } else {
+	    expon *= -1.0;
+	  }
+	}
+
+{SI_UNIT}|{ADD_UNIT} {
+	  operator = 0;
+	  yyless(0);
+	  BEGIN(UNITS);
+	}
+
+{PREFIX}({SI_UNIT}|{ADD_ALL}) |
+{SUPPREFIX}{ADD_SUP} |
+{SUBPREFIX}{ADD_SUB} {
+	  operator = 0;
+	  yyless(0);
+	  BEGIN(PREFIX);
+	}
+
+"]"	{
+	  bracket = !bracket;
+	  BEGIN(FLUSH);
+	}
+
+.	{
+	  status = wcserr_set(WCSERR_SET(UNITSERR_BAD_INITIAL_SYMBOL),
+	    "Invalid symbol in INITIAL context in '%s'", unitstr);
+	  BEGIN(FLUSH);
+	}
+
+<PAREN>"(" {
+	  paren++;
+	  operator = 0;
+	  yymore();
+	}
+
+<PAREN>")" {
+	  paren--;
+	  if (paren) {
+	    /* Not balanced yet. */
+	    yymore();
+	
+	  } else {
+	    /* Balanced; strip off the outer parentheses and recurse. */
+	    yytext[yyleng-1] = '\0';
+	
+	    buf = YY_CURRENT_BUFFER;
+	    status = wcsulexe(yytext+1, &func_r, &factor_r, types, err);
+	    yy_switch_to_buffer(buf);
+	
+	    if (func_r) {
+	      status = wcserr_set(WCSERR_SET(UNITSERR_FUNCTION_CONTEXT),
+	        "Function in invalid context in '%s'", unitstr);
+	    }
+	
+	    if (status) {
+	      BEGIN(FLUSH);
+	    } else {
+	      factor *= factor_r;
+	      BEGIN(EXPON);
+	    }
+	  }
+	}
+
+<PAREN>[^()]+ {
+	  yymore();
+	}
+
+<PREFIX>d {
+	  factor = 1e-1;
+	  BEGIN(UNITS);
+	}
+
+<PREFIX>c {
+	  factor = 1e-2;
+	  BEGIN(UNITS);
+	}
+
+<PREFIX>m {
+	  factor = 1e-3;
+	  BEGIN(UNITS);
+	}
+
+<PREFIX>u {
+	  factor = 1e-6;
+	  BEGIN(UNITS);
+	}
+
+<PREFIX>n {
+	  factor = 1e-9;
+	  BEGIN(UNITS);
+	}
+
+<PREFIX>p {
+	  factor = 1e-12;
+	  BEGIN(UNITS);
+	}
+
+<PREFIX>f {
+	  factor = 1e-15;
+	  BEGIN(UNITS);
+	}
+
+<PREFIX>a {
+	  factor = 1e-18;
+	  BEGIN(UNITS);
+	}
+
+<PREFIX>z {
+	  factor = 1e-21;
+	  BEGIN(UNITS);
+	}
+
+<PREFIX>y {
+	  factor = 1e-24;
+	  BEGIN(UNITS);
+	}
+
+<PREFIX>da {
+	  factor = 1e+1;
+	  BEGIN(UNITS);
+	}
+
+<PREFIX>h {
+	  factor = 1e+2;
+	  BEGIN(UNITS);
+	}
+
+<PREFIX>k {
+	  factor = 1e+3;
+	  BEGIN(UNITS);
+	}
+
+<PREFIX>M {
+	  factor = 1e+6;
+	  BEGIN(UNITS);
+	}
+
+<PREFIX>G {
+	  factor = 1e+9;
+	  BEGIN(UNITS);
+	}
+
+<PREFIX>T {
+	  factor = 1e+12;
+	  BEGIN(UNITS);
+	}
+
+<PREFIX>P {
+	  factor = 1e+15;
+	  BEGIN(UNITS);
+	}
+
+<PREFIX>E {
+	  factor = 1e+18;
+	  BEGIN(UNITS);
+	}
+
+<PREFIX>Z {
+	  factor = 1e+21;
+	  BEGIN(UNITS);
+	}
+
+<PREFIX>Y {
+	  factor = 1e+24;
+	  BEGIN(UNITS);
+	}
+
+<PREFIX>. {
+	  /* Internal parser error. */
+	  status = wcserr_set(WCSERR_SET(UNITSERR_PARSER_ERROR),
+	    "Internal units parser error parsing '%s'", unitstr);
+	  BEGIN(FLUSH);
+	}
+
+<UNITS>A {
+	  /* Ampere. */
+	  types[WCSUNITS_CHARGE] += 1.0;
+	  types[WCSUNITS_TIME]   -= 1.0;
+	  BEGIN(EXPON);
+	}
+
+<UNITS>a|yr {
+	  /* Year (annum). */
+	  factor *= 31557600.0;
+	  types[WCSUNITS_TIME] += 1.0;
+	  BEGIN(EXPON);
+	}
+
+<UNITS>adu {
+	  /* Analogue-to-digital converter units. */
+	  types[WCSUNITS_COUNT] += 1.0;
+	  BEGIN(EXPON);
+	}
+
+<UNITS>[Aa]ngstrom {
+	  /* Angstrom. */
+	  factor *= 1e-10;
+	  types[WCSUNITS_LENGTH] += 1.0;
+	  BEGIN(EXPON);
+	}
+
+<UNITS>arcmin {
+	  /* Minute of arc. */
+	  factor /= 60.0;
+	  types[WCSUNITS_PLANE_ANGLE] += 1.0;
+	  BEGIN(EXPON);
+	}
+
+<UNITS>arcsec {
+	  /* Second of arc. */
+	  factor /= 3600.0;
+	  types[WCSUNITS_PLANE_ANGLE] += 1.0;
+	  BEGIN(EXPON);
+	}
+
+<UNITS>AU {
+	  /* Astronomical unit. */
+	  factor *= 1.49598e+11;
+	  types[WCSUNITS_LENGTH] += 1.0;
+	  BEGIN(EXPON);
+	}
+
+<UNITS>barn {
+	  /* Barn. */
+	  factor *= 1e-28;
+	  types[WCSUNITS_LENGTH] += 2.0;
+	  BEGIN(EXPON);
+	}
+
+<UNITS>beam {
+	  /* Beam, as in Jy/beam. */
+	  types[WCSUNITS_BEAM] += 1.0;
+	  BEGIN(EXPON);
+	}
+
+<UNITS>bin {
+	  /* Bin (e.g. histogram). */
+	  types[WCSUNITS_BIN] += 1.0;
+	  BEGIN(EXPON);
+	}
+
+<UNITS>bit {
+	  /* Bit. */
+	  types[WCSUNITS_BIT] += 1.0;
+	  BEGIN(EXPON);
+	}
+
+<UNITS>[bB]yte {
+	  /* Byte. */
+	  factor *= 8.0;
+	  types[WCSUNITS_BIT] += 1.0;
+	  BEGIN(EXPON);
+	}
+
+<UNITS>C {
+	  /* Coulomb. */
+	  types[WCSUNITS_CHARGE] += 1.0;
+	  BEGIN(EXPON);
+	}
+
+<UNITS>cd {
+	  /* Candela. */
+	  types[WCSUNITS_LUMINTEN] += 1.0;
+	  BEGIN(EXPON);
+	}
+
+<UNITS>chan {
+	  /* Channel. */
+	  types[WCSUNITS_BIN] += 1.0;
+	  BEGIN(EXPON);
+	}
+
+<UNITS>count|ct {
+	  /* Count. */
+	  types[WCSUNITS_COUNT] += 1.0;
+	  BEGIN(EXPON);
+	}
+
+<UNITS>D {
+	  /* Debye. */
+	  factor *= 1e-29 / 3.0;
+	  types[WCSUNITS_CHARGE] += 1.0;
+	  types[WCSUNITS_LENGTH] += 1.0;
+	  BEGIN(EXPON);
+	}
+
+<UNITS>d {
+	  /* Day. */
+	  factor *= 86400.0;
+	  types[WCSUNITS_TIME] += 1.0;
+	  BEGIN(EXPON);
+	}
+
+<UNITS>deg {
+	  /* Degree. */
+	  types[WCSUNITS_PLANE_ANGLE] += 1.0;
+	  BEGIN(EXPON);
+	}
+
+<UNITS>erg {
+	  /* Erg. */
+	  factor *= 1e-7;
+	  types[WCSUNITS_MASS]   += 1.0;
+	  types[WCSUNITS_LENGTH] += 2.0;
+	  types[WCSUNITS_TIME]   -= 2.0;
+	  BEGIN(EXPON);
+	}
+
+<UNITS>eV {
+	  /* Electron volt. */
+	  factor *= 1.6021765e-19;
+	  types[WCSUNITS_MASS]   += 1.0;
+	  types[WCSUNITS_LENGTH] += 2.0;
+	  types[WCSUNITS_TIME]   -= 2.0;
+	  BEGIN(EXPON);
+	}
+
+<UNITS>F {
+	  /* Farad. */
+	  types[WCSUNITS_MASS]   -= 1.0;
+	  types[WCSUNITS_LENGTH] -= 2.0;
+	  types[WCSUNITS_TIME]   += 3.0;
+	  types[WCSUNITS_CHARGE] += 2.0;
+	  BEGIN(EXPON);
+	}
+
+<UNITS>G {
+	  /* Gauss. */
+	  factor *= 1e-4;
+	  types[WCSUNITS_MASS]   += 1.0;
+	  types[WCSUNITS_TIME]   += 1.0;
+	  types[WCSUNITS_CHARGE] -= 1.0;
+	  BEGIN(EXPON);
+	}
+
+<UNITS>g {
+	  /* Gram. */
+	  factor *= 1e-3;
+	  types[WCSUNITS_MASS] += 1.0;
+	  BEGIN(EXPON);
+	}
+
+<UNITS>H {
+	  /* Henry. */
+	  types[WCSUNITS_MASS]   += 1.0;
+	  types[WCSUNITS_LENGTH] += 2.0;
+	  types[WCSUNITS_TIME]   += 2.0;
+	  types[WCSUNITS_CHARGE] -= 2.0;
+	  BEGIN(EXPON);
+	}
+
+<UNITS>h {
+	  /* Hour. */
+	  factor *= 3600.0;
+	  types[WCSUNITS_TIME] += 1.0;
+	  BEGIN(EXPON);
+	}
+
+<UNITS>Hz {
+	  /* Hertz. */
+	  types[WCSUNITS_TIME] -= 1.0;
+	  BEGIN(EXPON);
+	}
+
+<UNITS>J {
+	  /* Joule. */
+	  types[WCSUNITS_MASS]   += 1.0;
+	  types[WCSUNITS_LENGTH] += 2.0;
+	  types[WCSUNITS_TIME]   -= 2.0;
+	  BEGIN(EXPON);
+	}
+
+<UNITS>Jy {
+	  /* Jansky. */
+	  factor *= 1e-26;
+	  types[WCSUNITS_MASS] += 1.0;
+	  types[WCSUNITS_TIME] -= 2.0;
+	  BEGIN(EXPON);
+	}
+
+<UNITS>K {
+	  /* Kelvin. */
+	  types[WCSUNITS_TEMPERATURE] += 1.0;
+	  BEGIN(EXPON);
+	}
+
+<UNITS>lm {
+	  /* Lumen. */
+	  types[WCSUNITS_LUMINTEN]    += 1.0;
+	  types[WCSUNITS_SOLID_ANGLE] += 1.0;
+	  BEGIN(EXPON);
+	}
+
+<UNITS>lx {
+	  /* Lux. */
+	  types[WCSUNITS_LUMINTEN]    += 1.0;
+	  types[WCSUNITS_SOLID_ANGLE] += 1.0;
+	  types[WCSUNITS_LENGTH]      -= 2.0;
+	  BEGIN(EXPON);
+	}
+
+<UNITS>lyr {
+	  /* Light year. */
+	  factor *= 2.99792458e8 * 31557600.0;
+	  types[WCSUNITS_LENGTH] += 1.0;
+	  BEGIN(EXPON);
+	}
+
+<UNITS>m {
+	  /* Metre. */
+	  types[WCSUNITS_LENGTH] += 1.0;
+	  BEGIN(EXPON);
+	}
+
+<UNITS>mag {
+	  /* Stellar magnitude. */
+	  types[WCSUNITS_MAGNITUDE] += 1.0;
+	  BEGIN(EXPON);
+	}
+
+<UNITS>mas {
+	  /* Milli-arcsec. */
+	  factor /= 3600e+3;
+	  types[WCSUNITS_PLANE_ANGLE] += 1.0;
+	  BEGIN(EXPON);
+	}
+
+<UNITS>min {
+	  /* Minute. */
+	  factor *= 60.0;
+	  types[WCSUNITS_TIME] += 1.0;
+	  BEGIN(EXPON);
+	}
+
+<UNITS>mol {
+	  /* Mole. */
+	  types[WCSUNITS_MOLE] += 1.0;
+	  BEGIN(EXPON);
+	}
+
+<UNITS>N {
+	  /* Newton. */
+	  types[WCSUNITS_MASS]   += 1.0;
+	  types[WCSUNITS_LENGTH] += 1.0;
+	  types[WCSUNITS_TIME]   -= 2.0;
+	  BEGIN(EXPON);
+	}
+
+<UNITS>[Oo]hm {
+	  /* Ohm. */
+	  types[WCSUNITS_MASS]   += 1.0;
+	  types[WCSUNITS_LENGTH] += 2.0;
+	  types[WCSUNITS_TIME]   -= 1.0;
+	  types[WCSUNITS_CHARGE] -= 2.0;
+	  BEGIN(EXPON);
+	}
+
+<UNITS>Pa {
+	  /* Pascal. */
+	  types[WCSUNITS_MASS]   += 1.0;
+	  types[WCSUNITS_LENGTH] -= 1.0;
+	  types[WCSUNITS_TIME]   -= 2.0;
+	  BEGIN(EXPON);
+	}
+
+<UNITS>pc {
+	  /* Parsec. */
+	  factor *= 3.0857e16;
+	  types[WCSUNITS_LENGTH] += 1.0;
+	  BEGIN(EXPON);
+	}
+
+<UNITS>photon|ph {
+	  /* Photon. */
+	  types[WCSUNITS_COUNT] += 1.0;
+	  BEGIN(EXPON);
+	}
+
+<UNITS>pixel|pix {
+	  /* Pixel. */
+	  types[WCSUNITS_PIXEL] += 1.0;
+	  BEGIN(EXPON);
+	}
+
+<UNITS>R {
+	  /* Rayleigh. */
+	  factor *= 1e10 / (4.0 * PI);
+	  types[WCSUNITS_LENGTH]      -= 2.0;
+	  types[WCSUNITS_TIME]        -= 1.0;
+	  types[WCSUNITS_SOLID_ANGLE] -= 1.0;
+	  BEGIN(EXPON);
+	}
+
+<UNITS>rad {
+	  /* Radian. */
+	  factor *= 180.0 / PI;
+	  types[WCSUNITS_PLANE_ANGLE] += 1.0;
+	  BEGIN(EXPON);
+	}
+
+<UNITS>Ry {
+	  /* Rydberg. */
+	  factor *= 13.605692 * 1.6021765e-19;
+	  types[WCSUNITS_MASS]   += 1.0;
+	  types[WCSUNITS_LENGTH] += 2.0;
+	  types[WCSUNITS_TIME]   -= 2.0;
+	  BEGIN(EXPON);
+	}
+
+<UNITS>S {
+	  /* Siemen. */
+	  types[WCSUNITS_MASS]   -= 1.0;
+	  types[WCSUNITS_LENGTH] -= 2.0;
+	  types[WCSUNITS_TIME]   += 1.0;
+	  types[WCSUNITS_CHARGE] += 2.0;
+	  BEGIN(EXPON);
+	}
+
+<UNITS>s {
+	  /* Second. */
+	  types[WCSUNITS_TIME] += 1.0;
+	  BEGIN(EXPON);
+	}
+
+<UNITS>solLum {
+	  /* Solar luminosity. */
+	  factor *= 3.8268e26;
+	  types[WCSUNITS_MASS]   += 1.0;
+	  types[WCSUNITS_LENGTH] += 2.0;
+	  types[WCSUNITS_TIME]   -= 3.0;
+	  BEGIN(EXPON);
+	}
+
+<UNITS>solMass {
+	  /* Solar mass. */
+	  factor *= 1.9891e30;
+	  types[WCSUNITS_MASS] += 1.0;
+	  BEGIN(EXPON);
+	}
+
+<UNITS>solRad {
+	  /* Solar radius. */
+	  factor *= 6.9599e8;
+	  types[WCSUNITS_LENGTH] += 1.0;
+	  BEGIN(EXPON);
+	}
+
+<UNITS>sr {
+	  /* Steradian. */
+	  types[WCSUNITS_SOLID_ANGLE] += 1.0;
+	  BEGIN(EXPON);
+	}
+
+<UNITS>Sun {
+	  /* Sun (with respect to). */
+	  types[WCSUNITS_SOLRATIO] += 1.0;
+	  BEGIN(EXPON);
+	}
+
+<UNITS>T {
+	  /* Tesla. */
+	  types[WCSUNITS_MASS]   += 1.0;
+	  types[WCSUNITS_TIME]   += 1.0;
+	  types[WCSUNITS_CHARGE] -= 1.0;
+	  BEGIN(EXPON);
+	}
+
+<UNITS>u {
+	  /* Unified atomic mass unit. */
+	  factor *= 1.6605387e-27;
+	  types[WCSUNITS_MASS] += 1.0;
+	  BEGIN(EXPON);
+	}
+
+<UNITS>V {
+	  /* Volt. */
+	  types[WCSUNITS_MASS]   += 1.0;
+	  types[WCSUNITS_LENGTH] += 1.0;
+	  types[WCSUNITS_TIME]   -= 2.0;
+	  types[WCSUNITS_CHARGE] -= 1.0;
+	  BEGIN(EXPON);
+	}
+
+<UNITS>voxel {
+	  /* Voxel. */
+	  types[WCSUNITS_VOXEL] += 1.0;
+	  BEGIN(EXPON);
+	}
+
+<UNITS>W {
+	  /* Watt. */
+	  types[WCSUNITS_MASS]   += 1.0;
+	  types[WCSUNITS_LENGTH] += 2.0;
+	  types[WCSUNITS_TIME]   -= 3.0;
+	  BEGIN(EXPON);
+	}
+
+<UNITS>Wb {
+	  /* Weber. */
+	  types[WCSUNITS_MASS]   += 1.0;
+	  types[WCSUNITS_LENGTH] += 2.0;
+	  types[WCSUNITS_TIME]   += 1.0;
+	  types[WCSUNITS_CHARGE] -= 1.0;
+	  BEGIN(EXPON);
+	}
+
+<UNITS>. {
+	  /* Internal parser error. */
+	  status = wcserr_set(WCSERR_SET(UNITSERR_PARSER_ERROR),
+	    "Internal units parser error parsing '%s'", unitstr);
+	  BEGIN(FLUSH);
+	}
+
+<EXPON>" "*("**"|^) {
+	  /* Exponentiation. */
+	  if (operator++) {
+	    BEGIN(FLUSH);
+	  }
+	}
+
+<EXPON>" "*{INTEGER} {
+	  sscanf(yytext, " %d", &i);
+	  expon *= (double)i;
+	  add(&factor, types, &expon, scale, units);
+	  operator = 0;
+	  BEGIN(INITIAL);
+	}
+
+<EXPON>" "*"("" "*{INTEGER}" "*")" {
+	  sscanf(yytext, " (%d)", &i);
+	  expon *= (double)i;
+	  add(&factor, types, &expon, scale, units);
+	  operator = 0;
+	  BEGIN(INITIAL);
+	}
+
+<EXPON>" "*"("" "*{FRAC}" "*")" {
+	  sscanf(yytext, " (%d/%d)", &i, &j);
+	  expon *= (double)i / (double)j;
+	  add(&factor, types, &expon, scale, units);
+	  operator = 0;
+	  BEGIN(INITIAL);
+	}
+
+<EXPON>" "*"("" "*{FLOAT}" "*")" {
+	  sscanf(yytext, " (%s)", ctmp);
+	  wcsutil_str2double(ctmp, "%lf", &dexp);
+	  expon *= dexp;
+	  add(&factor, types, &expon, scale, units);
+	  operator = 0;
+	  BEGIN(INITIAL);
+	}
+
+<EXPON>" "*[.*]" "* {
+	  /* Multiply. */
+	  if (operator++) {
+	    BEGIN(FLUSH);
+	  } else {
+	    add(&factor, types, &expon, scale, units);
+	    BEGIN(INITIAL);
+	  }
+	}
+
+<EXPON>" "*"(" {
+	  /* Multiply. */
+	  if (operator) {
+	    BEGIN(FLUSH);
+	  } else {
+	    add(&factor, types, &expon, scale, units);
+	    unput('(');
+	    BEGIN(INITIAL);
+	  }
+	}
+
+<EXPON>" "+ {
+	  /* Multiply. */
+	  if (operator) {
+	    BEGIN(FLUSH);
+	  } else {
+	    add(&factor, types, &expon, scale, units);
+	    BEGIN(INITIAL);
+	  }
+	}
+
+<EXPON>" "*"/"" "* {
+	  /* Divide. */
+	  if (operator++) {
+	    BEGIN(FLUSH);
+	  } else {
+	    add(&factor, types, &expon, scale, units);
+	    expon = -1.0;
+	    BEGIN(INITIAL);
+	  }
+	}
+
+<EXPON>" "*"]" {
+	  add(&factor, types, &expon, scale, units);
+	  bracket = !bracket;
+	  BEGIN(FLUSH);
+	}
+
+<EXPON>. {
+	  status = wcserr_set(WCSERR_SET(UNITSERR_BAD_EXPON_SYMBOL),
+	    "Invalid symbol in EXPON context in '%s'", unitstr);
+	  BEGIN(FLUSH);
+	}
+
+<FLUSH>.* {
+	  /* Discard any remaining input. */
+	}
+
+<<EOF>>	{
+	  /* End-of-string. */
+	  if (YY_START == EXPON) {
+	    add(&factor, types, &expon, scale, units);
+	  }
+	
+	  yylex_destroy();
+	
+	  if (bracket) {
+	    status = wcserr_set(WCSERR_SET(UNITSERR_UNBAL_BRACKET),
+	      "Unbalanced bracket in '%s'", unitstr);
+	  } else if (paren) {
+	    status = wcserr_set(WCSERR_SET(UNITSERR_UNBAL_PAREN),
+	      "Unbalanced parenthesis in '%s'", unitstr);
+	  } else if (operator == 1) {
+	    status = wcserr_set(WCSERR_SET(UNITSERR_DANGLING_BINOP),
+	      "Dangling binary operator in '%s'", unitstr);
+	  } else if (operator) {
+	    status = wcserr_set(WCSERR_SET(UNITSERR_CONSEC_BINOPS),
+	      "Consecutive binary operators in '%s'", unitstr);
+	  #ifdef DEBUG
+	  } else {
+	    fprintf(stderr, "EOS\n");
+	  #endif
+	  }
+	
+	  if (status) {
+	    for (i = 0; i < WCSUNITS_NTYPE; i++) {
+	      units[i] = 0.0;
+	      *scale = 0.0;
+	    }
+	  }
+	
+	  return status;
+	}
+
+%%
+
+/*----------------------------------------------------------------------------
+* Accumulate a term in a units specification and reset work variables.
+*---------------------------------------------------------------------------*/
+
+void add(
+  double *factor,
+  double types[],
+  double *expon,
+  double *scale,
+  double units[])
+
+{
+  int i;
+
+  *scale *= pow(*factor, *expon);
+
+  for (i = 0; i < WCSUNITS_NTYPE; i++) {
+    units[i] += *expon * types[i];
+    types[i] = 0.0;
+  }
+
+  *expon  = 1.0;
+  *factor = 1.0;
+
+  return;
+}
diff --git a/cextern/wcslib/C/wcsunits.c b/cextern/wcslib/C/wcsunits.c
new file mode 100644
index 0000000..d086c3d
--- /dev/null
+++ b/cextern/wcslib/C/wcsunits.c
@@ -0,0 +1,225 @@
+/*============================================================================
+
+  WCSLIB 4.16 - an implementation of the FITS WCS standard.
+  Copyright (C) 1995-2012, Mark Calabretta
+
+  This file is part of WCSLIB.
+
+  WCSLIB is free software: you can redistribute it and/or modify it under the
+  terms of the GNU Lesser General Public License as published by the Free
+  Software Foundation, either version 3 of the License, or (at your option)
+  any later version.
+
+  WCSLIB 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 Lesser General Public License for
+  more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with WCSLIB.  If not, see http://www.gnu.org/licenses.
+
+  Direct correspondence concerning WCSLIB to mark at calabretta.id.au
+
+  Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
+  http://www.atnf.csiro.au/people/Mark.Calabretta
+  $Id: wcsunits.c,v 4.16 2012/11/07 04:42:44 cal103 Exp $
+*===========================================================================*/
+
+#include <math.h>
+
+#include "wcsunits.h"
+
+/* Map status return value to message. */
+const char *wcsunits_errmsg[] = {
+  "Success",
+  "Invalid numeric multiplier",
+  "Dangling binary operator",
+  "Invalid symbol in INITIAL context",
+  "Function in invalid context",
+  "Invalid symbol in EXPON context",
+  "Unbalanced bracket",
+  "Unbalanced parenthesis",
+  "Consecutive binary operators",
+  "Internal parser error",
+  "Non-conformant unit specifications",
+  "Non-conformant functions",
+  "Potentially unsafe translation"};
+
+
+/* Unit types. */
+const char *wcsunits_types[] = {
+  "plane angle",
+  "solid angle",
+  "charge",
+  "mole",
+  "temperature",
+  "luminous intensity",
+  "mass",
+  "length",
+  "time",
+  "beam",
+  "bin",
+  "bit",
+  "count",
+  "stellar magnitude",
+  "pixel",
+  "solar ratio",
+  "voxel"};
+
+const char *wcsunits_units[] = {
+  "degree",
+  "steradian",
+  "Coulomb",
+  "mole",
+  "Kelvin",
+  "candela",
+  "kilogram",
+  "metre",
+  "second",
+  "", "", "", "", "", "", "", ""};
+
+const char *wcsunits_funcs[] = {
+  "none",
+  "log",
+  "ln",
+  "exp"};
+
+/*--------------------------------------------------------------------------*/
+
+int wcsunits(
+  const char have[],
+  const char want[],
+  double *scale,
+  double *offset,
+  double *power)
+
+{
+  return wcsunitse(
+    have, want, scale, offset, power, 0x0);
+}
+
+/* : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :  */
+
+int wcsunitse(
+  const char have[],
+  const char want[],
+  double *scale,
+  double *offset,
+  double *power,
+  struct wcserr **err)
+
+{
+  static const char *function = "wcsunitse";
+
+  int    func1, func2, i, status;
+  double scale1, scale2, units1[WCSUNITS_NTYPE], units2[WCSUNITS_NTYPE];
+
+  if ((status = wcsulexe(have, &func1, &scale1, units1, err))) {
+    return status;
+  }
+
+  if ((status = wcsulexe(want, &func2, &scale2, units2, err))) {
+    return status;
+  }
+
+  /* Check conformance. */
+  for (i = 0; i < WCSUNITS_NTYPE; i++) {
+    if (units1[i] != units2[i]) {
+      return wcserr_set(WCSERR_SET(UNITSERR_BAD_UNIT_SPEC),
+        "Mismatched units type '%s': have '%s', want '%s'",
+        wcsunits_types[i], have, want);
+    }
+  }
+
+  *scale  = 0.0;
+  *offset = 0.0;
+  *power  = 1.0;
+
+  switch (func1) {
+  case 0:
+    /* No function. */
+    if (func2) {
+      return wcserr_set(WCSERR_SET(UNITSERR_BAD_FUNCS),
+        "Mismatched unit functions: have '%s' (%s), want '%s' (%s)",
+        have, wcsunits_funcs[func1], want, wcsunits_funcs[func2]);
+    }
+
+    *scale = scale1 / scale2;
+    break;
+
+  case 1:
+    /* log(). */
+    if (func2 == 1) {
+      /* log(). */
+      *scale  = 1.0;
+      *offset = log10(scale1 / scale2);
+
+    } else if (func2 == 2) {
+      /* ln(). */
+      *scale  = log(10.0);
+      *offset = log(scale1 / scale2);
+
+    } else {
+      return wcserr_set(WCSERR_SET(UNITSERR_BAD_FUNCS),
+        "Mismatched unit functions: have '%s' (%s), want '%s' (%s)",
+        have, wcsunits_funcs[func1], want, wcsunits_funcs[func2]);
+    }
+
+    break;
+
+  case 2:
+    /* ln(). */
+    if (func2 == 1) {
+      /* log(). */
+      *scale  = 1.0 / log(10.0);
+      *offset = log(scale1 / scale2);
+
+    } else if (func2 == 2) {
+      /* ln(). */
+      *scale  = 1.0;
+      *offset = log(scale1 / scale2);
+
+    } else {
+      return wcserr_set(WCSERR_SET(UNITSERR_BAD_FUNCS),
+        "Mismatched unit functions: have '%s' (%s), want '%s' (%s)",
+        have, wcsunits_funcs[func1], want, wcsunits_funcs[func2]);
+    }
+
+    break;
+
+  case 3:
+    /* exp(). */
+    if (func2 != 3) {
+      return wcserr_set(WCSERR_SET(UNITSERR_BAD_FUNCS),
+        "Mismatched unit functions: have '%s' (%s), want '%s' (%s)",
+        have, wcsunits_funcs[func1], want, wcsunits_funcs[func2]);
+    }
+
+    *scale = 1.0;
+    *power = scale1 / scale2;
+    break;
+
+  default:
+    /* Internal parser error. */
+    return wcserr_set(WCSERR_SET(UNITSERR_PARSER_ERROR),
+      "Internal units parser error");
+  }
+
+  return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int wcsutrn(int ctrl, char unitstr[])
+
+{
+  return wcsutrne(ctrl, unitstr, 0x0);
+}
+
+/*--------------------------------------------------------------------------*/
+
+int wcsulex(const char unitstr[], int *func, double *scale, double units[])
+
+{
+  return wcsulexe(unitstr, func, scale, units, 0x0);
+}
diff --git a/cextern/wcslib/C/wcsunits.h b/cextern/wcslib/C/wcsunits.h
new file mode 100644
index 0000000..e9fc703
--- /dev/null
+++ b/cextern/wcslib/C/wcsunits.h
@@ -0,0 +1,409 @@
+/*============================================================================
+
+  WCSLIB 4.16 - an implementation of the FITS WCS standard.
+  Copyright (C) 1995-2012, Mark Calabretta
+
+  This file is part of WCSLIB.
+
+  WCSLIB is free software: you can redistribute it and/or modify it under the
+  terms of the GNU Lesser General Public License as published by the Free
+  Software Foundation, either version 3 of the License, or (at your option)
+  any later version.
+
+  WCSLIB 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 Lesser General Public License for
+  more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with WCSLIB.  If not, see http://www.gnu.org/licenses.
+
+  Direct correspondence concerning WCSLIB to mark at calabretta.id.au
+
+  Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
+  http://www.atnf.csiro.au/people/Mark.Calabretta
+  $Id: wcsunits.h,v 4.16 2012/11/07 04:42:44 cal103 Exp $
+*=============================================================================
+*
+* WCSLIB 4.16 - C routines that implement the FITS World Coordinate System
+* (WCS) standard.  Refer to
+*
+*   "Representations of world coordinates in FITS",
+*   Greisen, E.W., & Calabretta, M.R. 2002, A&A, 395, 1061 (Paper I)
+*
+* The Flexible Image Transport System (FITS), a data format widely used in
+* astronomy for data interchange and archive, is described in
+*
+*   "Definition of The Flexible Image Transport System (FITS)",
+*   Hanisch, R.J., Farris, A., Greisen, E.W., et al. 2001, A&A, 376, 359
+*
+* which formalizes NOST 100-2.0, a document produced by the NASA/Science
+* Office of Standards and Technology, see http://fits.gsfc.nasa.gov.
+*
+* Refer to the README file provided with WCSLIB for an overview of the
+* library.
+*
+*
+* Summary of the wcsunits routines
+* --------------------------------
+* Routines in this suite deal with units specifications and conversions:
+*
+*   - wcsunitse(): given two unit specifications, derive the conversion from
+*     one to the other.
+*
+*   - wcsutrne(): translates certain commonly used but non-standard unit
+*     strings.  It is intended to be called before wcsulexe() which only
+*     handles standard FITS units specifications.
+*
+*   - wcsulexe(): parses a standard FITS units specification of arbitrary
+*     complexity, deriving the conversion to canonical units.
+*
+*
+* wcsunitse() - FITS units specification conversion
+* -------------------------------------------------
+* wcsunitse() derives the conversion from one system of units to another.
+*
+* A deprecated form of this function, wcsunits(), lacks the wcserr**
+* parameter.
+*
+* Given:
+*   have      const char []
+*                       FITS units specification to convert from (null-
+*                       terminated), with or without surrounding square
+*                       brackets (for inline specifications); text following
+*                       the closing bracket is ignored.
+*
+*   want      const char []
+*                       FITS units specification to convert to (null-
+*                       terminated), with or without surrounding square
+*                       brackets (for inline specifications); text following
+*                       the closing bracket is ignored.
+*
+* Returned:
+*   scale,
+*   offset,
+*   power     double*   Convert units using
+*
+=                         pow(scale*value + offset, power);
+*
+*                       Normally offset is zero except for log() or ln()
+*                       conversions, e.g. "log(MHz)" to "ln(Hz)".  Likewise,
+*                       power is normally unity except for exp() conversions,
+*                       e.g. "exp(ms)" to "exp(/Hz)".  Thus conversions
+*                       ordinarily consist of
+*
+=                         value *= scale;
+*
+*   err       struct wcserr **
+*                       If enabled, for function return values > 1, this
+*                       struct will contain a detailed error message, see
+*                       wcserr_enable().  May be NULL if an error message is
+*                       not desired.  Otherwise, the user is responsible for
+*                       deleting the memory allocated for the wcserr struct.
+*
+* Function return value:
+*             int       Status return value:
+*                          0: Success.
+*                        1-9: Status return from wcsulexe().
+*                         10: Non-conformant unit specifications.
+*                         11: Non-conformant functions.
+*
+*                       scale is zeroed on return if an error occurs.
+*
+*
+* wcsutrne() - Translation of non-standard unit specifications
+* ------------------------------------------------------------
+* wcsutrne() translates certain commonly used but non-standard unit strings,
+* e.g. "DEG", "MHZ", "KELVIN", that are not recognized by wcsulexe(), refer to
+* the notes below for a full list.  Compounds are also recognized, e.g.
+* "JY/BEAM" and "KM/SEC/SEC".  Extraneous embedded blanks are removed.
+*
+* A deprecated form of this function, wcsutrn(), lacks the wcserr** parameter.
+*
+* Given:
+*   ctrl      int       Although "S" is commonly used to represent seconds,
+*                       its translation to "s" is potentially unsafe since the
+*                       standard recognizes "S" formally as Siemens, however
+*                       rarely that may be used.  The same applies to "H" for
+*                       hours (Henry), and "D" for days (Debye).  This
+*                       bit-flag controls what to do in such cases:
+*                         1: Translate "S" to "s".
+*                         2: Translate "H" to "h".
+*                         4: Translate "D" to "d".
+*                       Thus ctrl == 0 doesn't do any unsafe translations,
+*                       whereas ctrl == 7 does all of them.
+*
+* Given and returned:
+*   unitstr   char []   Null-terminated character array containing the units
+*                       specification to be translated.
+*
+*                       Inline units specifications in the a FITS header
+*                       keycomment are also handled.  If the first non-blank
+*                       character in unitstr is '[' then the unit string is
+*                       delimited by its matching ']'.  Blanks preceding '['
+*                       will be stripped off, but text following the closing
+*                       bracket will be preserved without modification.
+*
+*   err       struct wcserr **
+*                       If enabled, for function return values > 1, this
+*                       struct will contain a detailed error message, see
+*                       wcserr_enable().  May be NULL if an error message is
+*                       not desired.  Otherwise, the user is responsible for
+*                       deleting the memory allocated for the wcserr struct.
+*
+* Function return value:
+*             int       Status return value:
+*                        -1: No change was made, other than stripping blanks
+*                            (not an error).
+*                         0: Success.
+*                         9: Internal parser error.
+*                        12: Potentially unsafe translation, whether applied
+*                             or not (see notes).
+*
+* Notes:
+*   Translation of non-standard unit specifications: apart from leading and
+*   trailing blanks, a case-sensitive match is required for the aliases listed
+*   below, in particular the only recognized aliases with metric prefixes are
+*   "KM", "KHZ", "MHZ", and "GHZ".  Potentially unsafe translations of "D",
+*   "H", and "S", shown in parentheses, are optional.
+*
+=     Unit       Recognized aliases
+=     ----       -------------------------------------------------------------
+=     Angstrom   angstrom
+=     arcmin     arcmins, ARCMIN, ARCMINS
+=     arcsec     arcsecs, ARCSEC, ARCSECS
+=     beam       BEAM
+=     byte       Byte
+=     d          day, days, (D), DAY, DAYS
+=     deg        degree, degrees, DEG, DEGREE, DEGREES
+=     GHz        GHZ
+=     h          hr, (H), HR
+=     Hz         hz, HZ
+=     kHz        KHZ
+=     Jy         JY
+=     K          kelvin, kelvins, Kelvin, Kelvins, KELVIN, KELVINS
+=     km         KM
+=     m          metre, meter, metres, meters, M, METRE, METER, METRES, METERS
+=     min        MIN
+=     MHz        MHZ
+=     Ohm        ohm
+=     Pa         pascal, pascals, Pascal, Pascals, PASCAL, PASCALS
+=     pixel      pixels, PIXEL, PIXELS
+=     rad        radian, radians, RAD, RADIAN, RADIANS
+=     s          sec, second, seconds, (S), SEC, SECOND, SECONDS
+=     V          volt, volts, Volt, Volts, VOLT, VOLTS
+=     yr         year, years, YR, YEAR, YEARS
+*
+*   The aliases "angstrom", "ohm", and "Byte" for (Angstrom, Ohm, and byte)
+*   are recognized by wcsulexe() itself as an unofficial extension of the
+*   standard, but they are converted to the standard form here.
+*
+*
+* wcsulexe() - FITS units specification parser
+* --------------------------------------------
+* wcsulexe() parses a standard FITS units specification of arbitrary
+* complexity, deriving the scale factor required to convert to canonical
+* units - basically SI with degrees and "dimensionless" additions such as
+* byte, pixel and count.
+*
+* A deprecated form of this function, wcsulex(), lacks the wcserr** parameter.
+*
+* Given:
+*   unitstr   const char []
+*                       Null-terminated character array containing the units
+*                       specification, with or without surrounding square
+*                       brackets (for inline specifications); text following
+*                       the closing bracket is ignored.
+*
+* Returned:
+*   func      int*      Special function type, see note 4:
+*                         0: None
+*                         1: log()  ...base 10
+*                         2: ln()   ...base e
+*                         3: exp()
+*
+*   scale     double*   Scale factor for the unit specification; multiply a
+*                       value expressed in the given units by this factor to
+*                       convert it to canonical units.
+*
+*   units     double[WCSUNITS_NTYPE]
+*                       A units specification is decomposed into powers of 16
+*                       fundamental unit types: angle, mass, length, time,
+*                       count, pixel, etc.  Preprocessor macro WCSUNITS_NTYPE
+*                       is defined to dimension this vector, and others such
+*                       WCSUNITS_PLANE_ANGLE, WCSUNITS_LENGTH, etc. to access
+*                       its elements.
+*
+*                       Corresponding character strings, wcsunits_types[] and
+*                       wcsunits_units[], are predefined to describe each
+*                       quantity and its canonical units.
+*
+*   err       struct wcserr **
+*                       If enabled, for function return values > 1, this
+*                       struct will contain a detailed error message, see
+*                       wcserr_enable().  May be NULL if an error message is
+*                       not desired.  Otherwise, the user is responsible for
+*                       deleting the memory allocated for the wcserr struct.
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Success.
+*                         1: Invalid numeric multiplier.
+*                         2: Dangling binary operator.
+*                         3: Invalid symbol in INITIAL context.
+*                         4: Function in invalid context.
+*                         5: Invalid symbol in EXPON context.
+*                         6: Unbalanced bracket.
+*                         7: Unbalanced parenthesis.
+*                         8: Consecutive binary operators.
+*                         9: Internal parser error.
+*
+*                       scale and units[] are zeroed on return if an error
+*                       occurs.
+*
+* Notes:
+*   1: wcsulexe() is permissive in accepting whitespace in all contexts in a
+*      units specification where it does not create ambiguity (e.g. not
+*      between a metric prefix and a basic unit string), including in strings
+*      like "log (m ** 2)" which is formally disallowed.
+*
+*   2: Supported extensions:
+*      - "angstrom" (OGIP usage) is allowed in addition to "Angstrom".
+*      - "ohm"      (OGIP usage) is allowed in addition to "Ohm".
+*      - "Byte"   (common usage) is allowed in addition to "byte".
+*
+*   3: Table 6 of WCS Paper I lists eleven units for which metric prefixes are
+*      allowed.  However, in this implementation only prefixes greater than
+*      unity are allowed for "a" (annum), "yr" (year), "pc" (parsec), "bit",
+*      and "byte", and only prefixes less than unity are allowed for "mag"
+*      (stellar magnitude).
+*
+*      Metric prefix "P" (peta) is specifically forbidden for "a" (annum) to
+*      avoid confusion with "Pa" (Pascal, not peta-annum).  Note that metric
+*      prefixes are specifically disallowed for "h" (hour) and "d" (day) so
+*      that "ph" (photons) cannot be interpreted as pico-hours, nor "cd"
+*      (candela) as centi-days.
+*
+*   4: Function types log(), ln() and exp() may only occur at the start of the
+*      units specification.  The scale and units[] returned for these refers
+*      to the string inside the function "argument", e.g. to "MHz" in log(MHz)
+*      for which a scale of 1e6 will be returned.
+*
+*
+* Global variable: const char *wcsunits_errmsg[] - Status return messages
+* -----------------------------------------------------------------------
+* Error messages to match the status value returned from each function.
+*
+*
+* Global variable: const char *wcsunits_types[] - Names of physical quantities
+* ----------------------------------------------------------------------------
+* Names for physical quantities to match the units vector returned by
+* wcsulexe():
+*   -  0: plane angle
+*   -  1: solid angle
+*   -  2: charge
+*   -  3: mole
+*   -  4: temperature
+*   -  5: luminous intensity
+*   -  6: mass
+*   -  7: length
+*   -  8: time
+*   -  9: beam
+*   - 10: bin
+*   - 11: bit
+*   - 12: count
+*   - 13: stellar magnitude
+*   - 14: pixel
+*   - 15: solar ratio
+*   - 16: voxel
+*
+*
+* Global variable: const char *wcsunits_units[] - Names of units
+* --------------------------------------------------------------
+* Names for the units (SI) to match the units vector returned by wcsulexe():
+*   -  0: degree
+*   -  1: steradian
+*   -  2: Coulomb
+*   -  3: mole
+*   -  4: Kelvin
+*   -  5: candela
+*   -  6: kilogram
+*   -  7: metre
+*   -  8: second
+*
+* The remainder are dimensionless.
+*===========================================================================*/
+
+#ifndef WCSLIB_WCSUNITS
+#define WCSLIB_WCSUNITS
+
+#include "wcserr.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+extern const char *wcsunits_errmsg[];
+
+enum wcsunits_errmsg_enum {
+  UNITSERR_SUCCESS            =  0,	/* Success. */
+  UNITSERR_BAD_NUM_MULTIPLIER =  1,	/* Invalid numeric multiplier. */
+  UNITSERR_DANGLING_BINOP     =  2,	/* Dangling binary operator. */
+  UNITSERR_BAD_INITIAL_SYMBOL =  3,	/* Invalid symbol in INITIAL
+					   context. */
+  UNITSERR_FUNCTION_CONTEXT   =  4,	/* Function in invalid context. */
+  UNITSERR_BAD_EXPON_SYMBOL   =  5,	/* Invalid symbol in EXPON context. */
+  UNITSERR_UNBAL_BRACKET      =  6,	/* Unbalanced bracket. */
+  UNITSERR_UNBAL_PAREN        =  7,	/* Unbalanced parenthesis. */
+  UNITSERR_CONSEC_BINOPS      =  8,	/* Consecutive binary operators. */
+  UNITSERR_PARSER_ERROR       =  9,	/* Internal parser error. */
+  UNITSERR_BAD_UNIT_SPEC      = 10,	/* Non-conformant unit
+					   specifications. */
+  UNITSERR_BAD_FUNCS          = 11,	/* Non-conformant functions. */
+  UNITSERR_UNSAFE_TRANS       = 12	/* Potentially unsafe translation. */
+};
+
+extern const char *wcsunits_types[];
+extern const char *wcsunits_units[];
+
+#define WCSUNITS_PLANE_ANGLE 0
+#define WCSUNITS_SOLID_ANGLE 1
+#define WCSUNITS_CHARGE      2
+#define WCSUNITS_MOLE        3
+#define WCSUNITS_TEMPERATURE 4
+#define WCSUNITS_LUMINTEN    5
+#define WCSUNITS_MASS        6
+#define WCSUNITS_LENGTH      7
+#define WCSUNITS_TIME        8
+#define WCSUNITS_BEAM        9
+#define WCSUNITS_BIN        10
+#define WCSUNITS_BIT        11
+#define WCSUNITS_COUNT      12
+#define WCSUNITS_MAGNITUDE  13
+#define WCSUNITS_PIXEL      14
+#define WCSUNITS_SOLRATIO   15
+#define WCSUNITS_VOXEL      16
+
+#define WCSUNITS_NTYPE      17
+
+
+int wcsunitse(const char have[], const char want[], double *scale,
+              double *offset, double *power, struct wcserr **err);
+
+int wcsutrne(int ctrl, char unitstr[], struct wcserr **err);
+
+int wcsulexe(const char unitstr[], int *func, double *scale, double units[],
+             struct wcserr **err);
+
+/* Deprecated. */
+int wcsunits(const char have[], const char want[], double *scale,
+             double *offset, double *power);
+int wcsutrn(int ctrl, char unitstr[]);
+int wcsulex(const char unitstr[], int *func, double *scale, double units[]);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* WCSLIB_WCSUNITS */
diff --git a/cextern/wcslib/C/wcsutil.c b/cextern/wcslib/C/wcsutil.c
new file mode 100644
index 0000000..021d3ef
--- /dev/null
+++ b/cextern/wcslib/C/wcsutil.c
@@ -0,0 +1,253 @@
+/*============================================================================
+
+  WCSLIB 4.16 - an implementation of the FITS WCS standard.
+  Copyright (C) 1995-2012, Mark Calabretta
+
+  This file is part of WCSLIB.
+
+  WCSLIB is free software: you can redistribute it and/or modify it under the
+  terms of the GNU Lesser General Public License as published by the Free
+  Software Foundation, either version 3 of the License, or (at your option)
+  any later version.
+
+  WCSLIB 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 Lesser General Public License for
+  more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with WCSLIB.  If not, see http://www.gnu.org/licenses.
+
+  Direct correspondence concerning WCSLIB to mark at calabretta.id.au
+
+  Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
+  http://www.atnf.csiro.au/people/Mark.Calabretta
+  $Id: wcsutil.c,v 4.16 2012/11/07 04:42:44 cal103 Exp $
+*===========================================================================*/
+
+#include <ctype.h>
+#include <locale.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "wcsutil.h"
+
+/*--------------------------------------------------------------------------*/
+
+void wcsutil_blank_fill(int n, char c[])
+
+{
+  int k;
+
+  for (k = strlen(c); k < n; k++) {
+    c[k] = ' ';
+  }
+
+  return;
+}
+
+/*--------------------------------------------------------------------------*/
+
+void wcsutil_null_fill(int n, char c[])
+
+{
+  int j, k;
+
+  if (n <= 0) return;
+
+  /* Null-fill the string. */
+  *(c+n-1) = '\0';
+  for (j = 0; j < n; j++) {
+    if (c[j] == '\0') {
+      for (k = j+1; k < n; k++) {
+        c[k] = '\0';
+      }
+      break;
+    }
+  }
+
+  for (k = j-1; k > 0; k--) {
+    if (c[k] != ' ') break;
+    c[k] = '\0';
+  }
+
+   return;
+}
+
+/*--------------------------------------------------------------------------*/
+
+int wcsutil_allEq(int nvec, int nelem, const double *first)
+
+{
+  double v0;
+  const double *vp;
+
+  if (nvec <= 0 || nelem <= 0) return 0;
+
+  v0 = *first;
+  for (vp = first+nelem; vp < first + nvec*nelem; vp += nelem) {
+    if (*vp != v0) return 0;
+  }
+
+  return 1;
+}
+
+/*--------------------------------------------------------------------------*/
+
+void wcsutil_setAll(int nvec, int nelem, double *first)
+
+{
+  double v0, *vp;
+
+  if (nvec <= 0 || nelem <= 0) return;
+
+  v0 = *first;
+  for (vp = first+nelem; vp < first + nvec*nelem; vp += nelem) {
+    *vp = v0;
+  }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void wcsutil_setAli(int nvec, int nelem, int *first)
+
+{
+  int v0, *vp;
+
+  if (nvec <= 0 || nelem <= 0) return;
+
+  v0 = *first;
+  for (vp = first+nelem; vp < first + nvec*nelem; vp += nelem) {
+    *vp = v0;
+  }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void wcsutil_setBit(int nelem, const int *sel, int bits, int *array)
+
+{
+  int *arrp;
+
+  if (bits == 0 || nelem <= 0) return;
+
+  if (sel == 0x0) {
+    /* All elements selected. */
+    for (arrp = array; arrp < array + nelem; arrp++) {
+      *arrp |= bits;
+    }
+
+  } else {
+    /* Some elements selected. */
+    for (arrp = array; arrp < array + nelem; arrp++) {
+      if (*(sel++)) *arrp |= bits;
+    }
+  }
+}
+
+/*--------------------------------------------------------------------------*/
+
+char *wcsutil_fptr2str(int (*func)(void), char hext[])
+
+{
+  unsigned char *p = (unsigned char *)(&func);
+  char *t = hext;
+  int i, *(ip[2]), j[2], le = 1, gotone = 0;
+
+  /* Test for little-endian addresses. */
+  ip[0] = j;
+  ip[1] = j + 1;
+  if ((unsigned char *)ip[0] < (unsigned char *)ip[1]) {
+    /* Little-endian, reverse it. */
+    p += sizeof(func) - 1;
+    le = -1;
+  }
+
+  sprintf(t, "0x0");
+  t += 2;
+
+  for (i = 0; i < sizeof(func); i++) {
+    /* Skip leading zeroes. */
+    if (*p) gotone = 1;
+
+    if (gotone) {
+      sprintf(t, "%02x", *p);
+      t += 2;
+    }
+
+    p += le;
+  }
+
+  return hext;
+}
+
+/*--------------------------------------------------------------------------*/
+
+static const char *wcsutil_dot_to_locale(const char *inbuf, char *outbuf)
+
+{
+  struct lconv *locale_data = localeconv();
+  const char *decimal_point = locale_data->decimal_point;
+
+  if (decimal_point[0] != '.' || decimal_point[1] != 0) {
+    char *out = outbuf;
+    size_t decimal_point_len = strlen(decimal_point);
+
+    for ( ; *inbuf; ++inbuf) {
+      if (*inbuf == '.') {
+        strncpy(out, decimal_point, decimal_point_len);
+        out += decimal_point_len;
+      } else {
+        *out++ = *inbuf;
+      }
+    }
+
+    *out = '\0';
+
+    return outbuf;
+  } else {
+    return inbuf;
+  }
+}
+
+
+int wcsutil_str2double(const char *buf, const char *format, double *value)
+
+{
+  char ctmp[72];
+  return sscanf(wcsutil_dot_to_locale(buf, ctmp), "%lf", value) < 1;
+}
+
+/*--------------------------------------------------------------------------*/
+
+static void wcsutil_locale_to_dot(char *buf)
+
+{
+  struct lconv *locale_data = localeconv();
+  const char *decimal_point = locale_data->decimal_point;
+
+  if (decimal_point[0] != '.' || decimal_point[1] != 0) {
+    size_t decimal_point_len = strlen(decimal_point);
+    char *inbuf = buf;
+    char *outbuf = buf;
+
+    for ( ; *inbuf; ++inbuf) {
+      if (strncmp(inbuf, decimal_point, decimal_point_len) == 0) {
+        *outbuf++ = '.';
+        inbuf += decimal_point_len - 1;
+      } else {
+        *outbuf++ = *inbuf;
+      }
+    }
+
+    *outbuf = '\0';
+  }
+}
+
+
+void wcsutil_double2str(char *buf, const char *format, double value)
+
+{
+  sprintf(buf, format, value);
+  wcsutil_locale_to_dot(buf);
+}
diff --git a/cextern/wcslib/C/wcsutil.h b/cextern/wcslib/C/wcsutil.h
new file mode 100644
index 0000000..e5ffb50
--- /dev/null
+++ b/cextern/wcslib/C/wcsutil.h
@@ -0,0 +1,262 @@
+/*============================================================================
+
+  WCSLIB 4.16 - an implementation of the FITS WCS standard.
+  Copyright (C) 1995-2012, Mark Calabretta
+
+  This file is part of WCSLIB.
+
+  WCSLIB is free software: you can redistribute it and/or modify it under the
+  terms of the GNU Lesser General Public License as published by the Free
+  Software Foundation, either version 3 of the License, or (at your option)
+  any later version.
+
+  WCSLIB 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 Lesser General Public License for
+  more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with WCSLIB.  If not, see http://www.gnu.org/licenses.
+
+  Direct correspondence concerning WCSLIB to mark at calabretta.id.au
+
+  Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
+  http://www.atnf.csiro.au/people/Mark.Calabretta
+  $Id: wcsutil.h,v 4.16 2012/11/07 04:42:44 cal103 Exp $
+*=============================================================================
+*
+* Summary of the wcsutil routines
+* -------------------------------
+* Simple utility functions for internal use only by WCSLIB.  They are
+* documented here solely as an aid to understanding the code.  They are not
+* intended for external use - the API may change without notice!
+*
+*
+* wcsutil_blank_fill() - Fill a character string with blanks
+* ----------------------------------------------------------
+* INTERNAL USE ONLY.
+*
+* wcsutil_blank_fill() pads a character string with blanks starting with the
+* terminating NULL character.
+*
+* Used by the Fortran wrapper functions in translating C character strings
+* into Fortran CHARACTER variables.
+*
+* Given:
+*   n         int       Length of the character array, c[].
+*
+* Given and returned:
+*   c         char[]    The character string.  It will not be null-terminated
+*                       on return.
+*
+* Function return value:
+*             void
+*
+*
+* wcsutil_null_fill() - Fill a character string with NULLs
+* --------------------------------------------------------
+* INTERNAL USE ONLY.
+*
+* wcsutil_null_fill() strips off trailing blanks and pads the character array
+* holding the string with NULL characters.
+*
+* Used mainly to make character strings intelligible in the GNU debugger which
+* prints the rubbish following the terminating NULL, obscuring the valid part
+* of the string.
+*
+* Given:
+*   n         int       Number of characters.
+*
+* Given and returned:
+*   c         char[]    The character string.
+*
+* Function return value:
+*             void
+*
+*
+* wcsutil_allEq() - Test for equality of a particular vector element
+* ------------------------------------------------------------------
+* INTERNAL USE ONLY.
+*
+* wcsutil_allEq() tests for equality of a particular element in a set of
+* vectors.
+*
+* Given:
+*   nvec      int       The number of vectors.
+*
+*   nelem     int       The length of each vector.
+*
+*   first     const double*
+*                       Pointer to the first element to test in the array.
+*                       The elements tested for equality are
+*
+=                         *first == *(first + nelem)
+=                                == *(first + nelem*2)
+=                                           :
+=                                == *(first + nelem*(nvec-1));
+*
+*                       The array might be dimensioned as
+*
+=                         double v[nvec][nelem];
+*
+* Function return value:
+*             int       Status return value:
+*                         0: Not all equal.
+*                         1: All equal.
+*
+*
+* wcsutil_setAll() - Set a particular vector element
+* --------------------------------------------------
+* INTERNAL USE ONLY.
+*
+* wcsutil_setAll() sets the value of a particular element in a set of vectors.
+*
+* Given:
+*   nvec      int       The number of vectors.
+*
+*   nelem     int       The length of each vector.
+*
+* Given and returned:
+*   first     double*   Pointer to the first element in the array, the value
+*                       of which is used to set the others
+*
+=                         *(first + nelem) = *first;
+=                         *(first + nelem*2) = *first;
+=                                 :
+=                         *(first + nelem*(nvec-1)) = *first;
+*
+*                       The array might be dimensioned as
+*
+=                         double v[nvec][nelem];
+*
+* Function return value:
+*             void
+*
+*
+* wcsutil_setAli() - Set a particular vector element
+* --------------------------------------------------
+* INTERNAL USE ONLY.
+*
+* wcsutil_setAli() sets the value of a particular element in a set of vectors.
+*
+* Given:
+*   nvec      int       The number of vectors.
+*
+*   nelem     int       The length of each vector.
+*
+* Given and returned:
+*   first     int*      Pointer to the first element in the array, the value
+*                       of which is used to set the others
+*
+=                         *(first + nelem) = *first;
+=                         *(first + nelem*2) = *first;
+=                                 :
+=                         *(first + nelem*(nvec-1)) = *first;
+*
+*                       The array might be dimensioned as
+*
+=                         int v[nvec][nelem];
+*
+* Function return value:
+*             void
+*
+*
+* wcsutil_setBit() - Set bits in selected elements of an array
+* ------------------------------------------------------------
+* INTERNAL USE ONLY.
+*
+* wcsutil_setBit() sets bits in selected elements of an array.
+*
+* Given:
+*   nelem     int       Number of elements in the array.
+*
+*   sel       const int*
+*                       Address of a selection array of length nelem.  May
+*                       be specified as the null pointer in which case all
+*                       elements are selected.
+*
+*   bits      int       Bit mask.
+*
+* Given and returned:
+*   array     int*      Address of the array of length nelem.
+*
+* Function return value:
+*             void
+*
+*
+* wcsutil_fptr2str() - Translate pointer-to-function to string
+* ------------------------------------------------------------
+* INTERNAL USE ONLY.
+*
+* wcsutil_fptr2str() translates a pointer-to-function to hexadecimal string
+* representation for output.  It is used by the various routines that print
+* the contents of WCSLIB structs.  Note that it is not strictly legal to
+* type-pun a function pointer to void*.
+*
+* See stackoverflow.com/questions/2741683/how-to-format-a-function-pointer
+*
+* Given:
+*   fptr      int (*)() Pointer to function.
+*
+* Returned:
+*   hext      char[]    Null-terminated string.  Should be at least 19 bytes
+*                       in size to accomodate a 64-bit address (16 bytes in
+*                       hex), plus the leading "0x" and trailing '\0'.
+*
+* Function return value:
+*             char *    The address of hext.
+*
+*
+* wcsutil_double2str() - Translate double to string ignoring the locale
+* ---------------------------------------------------------------------
+* INTERNAL USE ONLY.
+*
+* wcsutil_double2str() converts a double to a string, but unlike sprintf it
+* ignores the locale and always uses a '.' as the decimal separator.
+*
+* Returned:
+*   buf       char *    The buffer to write the string into.
+*
+* Given:
+*   format    char *    The formatting directive, such as "%f".  This
+*                       may be any of the forms accepted by sprintf, but
+*                       should only include a formatting directive and
+*                       nothing else.
+*
+*   value     double    The value to convert to a string.
+*
+*
+* wcsutil_str2double() - Translate string to a double, ignoring the locale
+* ------------------------------------------------------------------------
+* INTERNAL USE ONLY.
+*
+* wcsutil_str2double() converts a string to a double, but unlike sscanf it
+* ignores the locale and always expects a '.' as the decimal separator.
+*
+* Given:
+*   buf       char *    The string containing the value
+*
+*   format    char *    The formatting directive, such as "%lf".  This
+*                       may be any of the forms accepted by sscanf, but
+*                       should only include a single formatting directive.
+*
+* Returned:
+*   value     double *  The double value parsed from the string.
+*
+*===========================================================================*/
+
+#ifndef WCSLIB_WCSUTIL
+#define WCSLIB_WCSUTIL
+
+void wcsutil_blank_fill(int n, char c[]);
+void wcsutil_null_fill (int n, char c[]);
+
+int  wcsutil_allEq (int nvec, int nelem, const double *first);
+void wcsutil_setAll(int nvec, int nelem, double *first);
+void wcsutil_setAli(int nvec, int nelem, int *first);
+void wcsutil_setBit(int nelem, const int *sel, int bits, int *array);
+char *wcsutil_fptr2str(int (*func)(void), char hext[]);
+int  wcsutil_str2double(const char *buf, const char *format, double *value);
+void wcsutil_double2str(char *buf, const char *format, double value);
+
+#endif /* WCSLIB_WCSUTIL */
diff --git a/cextern/wcslib/C/wcsutrn.l b/cextern/wcslib/C/wcsutrn.l
new file mode 100644
index 0000000..b4a64fb
--- /dev/null
+++ b/cextern/wcslib/C/wcsutrn.l
@@ -0,0 +1,337 @@
+/*============================================================================
+
+  WCSLIB 4.16 - an implementation of the FITS WCS standard.
+  Copyright (C) 1995-2012, Mark Calabretta
+
+  This file is part of WCSLIB.
+
+  WCSLIB is free software: you can redistribute it and/or modify it under the
+  terms of the GNU Lesser General Public License as published by the Free
+  Software Foundation, either version 3 of the License, or (at your option)
+  any later version.
+
+  WCSLIB 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 Lesser General Public License for
+  more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with WCSLIB.  If not, see http://www.gnu.org/licenses.
+
+  Direct correspondence concerning WCSLIB to mark at calabretta.id.au
+
+  Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
+  http://www.atnf.csiro.au/people/Mark.Calabretta
+  $Id: wcsutrn.l,v 4.16 2012/11/07 04:42:44 cal103 Exp $
+*=============================================================================
+*
+* wcsutrn.l is a Flex description file containing the definition of a lexical
+* scanner that translates non-standard FITS units specifications.
+*
+* It requires Flex v2.5.4 or later.
+*
+* Refer to wcsunits.h for a description of the user interface and operating
+* notes.
+*
+*===========================================================================*/
+
+/* Options. */
+%option full
+%option never-interactive
+%option noyywrap
+%option outfile="wcsutrn.c"
+%option prefix="wcsutrn"
+
+/* Exclusive start states. */
+%x NEXT FLUSH
+
+%{
+/* To get the prototype for fileno() from stdio.h when gcc is invoked with
+ * -std=c89 (same as -ansi) or -std=c99 since we do not define YY_INPUT. */
+#define _POSIX_SOURCE 1
+
+#include <setjmp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "wcserr.h"
+#include "wcsunits.h"
+
+#define YY_DECL int wcsutrne(int ctrl, char unitstr[], struct wcserr **err)
+
+/* Used in preempting the call to exit() by yy_fatal_error(). */
+jmp_buf wcsutrn_abort_jmp_env;
+#define exit(status) longjmp(wcsutrn_abort_jmp_env, status)
+
+%}
+
+%%
+	static const char *function = "wcsutrne";
+	
+	char orig[80], subs[80];
+	int bracket = 0;
+	int unsafe  = 0;
+	int status  = -1;
+	YY_BUFFER_STATE inbuff;
+	int yylex_destroy(void);
+	
+	if (err) *err = 0x0;
+	
+	*orig = '\0';
+	*subs = '\0';
+	
+	inbuff = yy_scan_string(unitstr);
+	*unitstr = '\0';
+	
+	/* Return here via longjmp() invoked by yy_fatal_error(). */
+	if (setjmp(wcsutrn_abort_jmp_env)) {
+	  return wcserr_set(WCSERR_SET(UNITSERR_PARSER_ERROR),
+	    "Internal units translator error parsing '%s'", unitstr);
+	}
+	
+	BEGIN(INITIAL);
+	
+	#ifdef DEBUG
+	fprintf(stderr, "\n%s ->\n", unitstr);
+	#endif
+
+^" "*"[" {
+	  /* Looks like a keycomment. */
+	  strcat(unitstr, "[");
+	  bracket = 1;
+	}
+
+" "+	  /* Discard leading whitespace. */
+
+[^A-Za-z] {
+	  /* Non-alphabetic character. */
+	  strcat(unitstr, yytext);
+	  if (bracket && *yytext == ']') {
+	    BEGIN(FLUSH);
+	  }
+	}
+
+angstrom {
+	  strcpy(orig, yytext);
+	  strcpy(subs, "Angstrom");
+	  BEGIN(NEXT);
+	}
+
+arcmins|ARCMINS? {
+	  strcpy(orig, yytext);
+	  strcpy(subs, "arcmin");
+	  BEGIN(NEXT);
+	}
+
+arcsecs|ARCSECS? {
+	  strcpy(orig, yytext);
+	  strcpy(subs, "arcsec");
+	  BEGIN(NEXT);
+	}
+
+BEAM	{
+	  strcpy(orig, yytext);
+	  strcpy(subs, "beam");
+	  BEGIN(NEXT);
+	}
+
+Byte	{
+	  strcpy(orig, yytext);
+	  strcpy(subs, "byte");
+	  BEGIN(NEXT);
+	}
+
+days?|DAYS? {
+	  strcpy(orig, yytext);
+	  strcpy(subs, "d");
+	  BEGIN(NEXT);
+	}
+
+D	{
+	  unsafe = 1;
+	  strcpy(orig, yytext);
+	  strcpy(subs, (ctrl & 4) ? "d" : "D");
+	  BEGIN(NEXT);
+	}
+
+degrees?|DEG|DEGREES? {
+	  strcpy(orig, yytext);
+	  strcpy(subs, "deg");
+	  BEGIN(NEXT);
+	}
+
+GHZ	{
+	  strcpy(orig, yytext);
+	  strcpy(subs, "GHz");
+	  BEGIN(NEXT);
+	}
+
+hr|HR	{
+	  strcpy(orig, yytext);
+	  strcpy(subs, "h");
+	  BEGIN(NEXT);
+	}
+
+H	{
+	  unsafe = 1;
+	  strcpy(orig, yytext);
+	  strcpy(subs, (ctrl & 2) ? "h" : "H");
+	  BEGIN(NEXT);
+	}
+
+hz|HZ	{
+	  strcpy(orig, yytext);
+	  strcpy(subs, "Hz");
+	  BEGIN(NEXT);
+	}
+
+KHZ	{
+	  strcpy(orig, yytext);
+	  strcpy(subs, "kHz");
+	  BEGIN(NEXT);
+	}
+
+JY	{
+	  strcpy(orig, yytext);
+	  strcpy(subs, "Jy");
+	  BEGIN(NEXT);
+	}
+
+[kK]elvins?|KELVINS? {
+	  strcpy(orig, yytext);
+	  strcpy(subs, "K");
+	  BEGIN(NEXT);
+	}
+
+KM	{
+	  strcpy(orig, yytext);
+	  strcpy(subs, "km");
+	  BEGIN(NEXT);
+	}
+
+metres?|meters?|M|METRES?|METERS? {
+	  strcpy(orig, yytext);
+	  strcpy(subs, "m");
+	  BEGIN(NEXT);
+	}
+
+MIN	{
+	  strcpy(orig, yytext);
+	  strcpy(subs, "min");
+	  BEGIN(NEXT);
+	}
+
+MHZ	{
+	  strcpy(orig, yytext);
+	  strcpy(subs, "MHz");
+	  BEGIN(NEXT);
+	}
+
+Ohm	{
+	  strcpy(orig, yytext);
+	  strcpy(subs, "ohm");
+	  BEGIN(NEXT);
+	}
+
+[pP]ascals?|PASCALS? {
+	  strcpy(orig, yytext);
+	  strcpy(subs, "Pa");
+	  BEGIN(NEXT);
+	}
+
+pixels|PIXELS? {
+	  strcpy(orig, yytext);
+	  strcpy(subs, "pixel");
+	  BEGIN(NEXT);
+	}
+
+radians?|RAD|RADIANS? {
+	  strcpy(orig, yytext);
+	  strcpy(subs, "rad");
+	  BEGIN(NEXT);
+	}
+
+sec|seconds?|SEC|SECONDS? {
+	  strcpy(orig, yytext);
+	  strcpy(subs, "s");
+	  BEGIN(NEXT);
+	}
+
+S	{
+	  unsafe = 1;
+	  strcpy(orig, yytext);
+	  strcpy(subs, (ctrl & 1) ? "s" : "S");
+	  BEGIN(NEXT);
+	}
+
+[vV]olts?|VOLTS? {
+	  strcpy(orig, yytext);
+	  strcpy(subs, "V");
+	  BEGIN(NEXT);
+	}
+
+years?|YR|YEARS? {
+	  strcpy(orig, yytext);
+	  strcpy(subs, "yr");
+	  BEGIN(NEXT);
+	}
+
+[A-Za-z]+ {
+	  /* Not a recognized alias. */
+	  strcpy(orig, yytext);
+	  strcpy(subs, orig);
+	  BEGIN(NEXT);
+	}
+
+<NEXT>[A-Za-z]+ {
+	  /* Reject the alias match. */
+	  strcat(orig, yytext);
+	  strcpy(subs, orig);
+	}
+
+<NEXT>" "+[^A-Za-z] {
+	  /* Discard separating whitespace. */
+	  unput(yytext[yyleng-1]);
+	}
+
+<NEXT>" "+[A-Za-z] {
+	  /* Compress separating whitespace. */
+	  strcat(unitstr, subs);
+	  strcat(unitstr, " ");
+	  if (strcmp(orig, subs)) status = 0;
+	  unput(yytext[yyleng-1]);
+	  *subs = '\0';
+	  BEGIN(INITIAL);
+	}
+
+<NEXT>.	{
+	  /* Copy anything else unchanged. */
+	  strcat(unitstr, subs);
+	  if (strcmp(orig, subs)) status = 0;
+	  unput(*yytext);
+	  *subs = '\0';
+	  BEGIN(INITIAL);
+	}
+
+<FLUSH>.* {
+	  /* Copy out remaining input. */
+	  strcat(unitstr, yytext);
+	}
+
+<<EOF>>	{
+	  /* End-of-string. */
+	  if (*subs) {
+	    strcat(unitstr, subs);
+	    if (strcmp(orig, subs)) status = 0;
+	  }
+	
+	  yylex_destroy();
+	  if (unsafe) {
+	    return wcserr_set(WCSERR_SET(UNITSERR_UNSAFE_TRANS),
+	      "Unsafe unit translation in '%s'", unitstr);
+	  }
+	  return status;
+	}
+
+%%
diff --git a/cextern/wcslib/CHANGES b/cextern/wcslib/CHANGES
new file mode 100644
index 0000000..0521660
--- /dev/null
+++ b/cextern/wcslib/CHANGES
@@ -0,0 +1,1985 @@
+WCSLIB version 4.16 (2012/11/07)
+--------------------------------
+
+* C library
+
+  - When wcspih() constructs a default coordinate representation it will
+    give it the special name "DEFAULTS", and will not report "Found one
+    coordinate representation" (if reporting is enabled).
+
+* Utilities
+    
+  - wcsware has a new option, -P, which does the same as -p except that
+    it won't print a wcsprm struct with the name "DEFAULTS".
+
+
+WCSLIB version 4.15 (2012/09/26)
+--------------------------------
+
+* C library
+
+  - Bug fixes in spctype(), spcspxe(), spcxpse, and spctrne() for
+    propagating an error status correctly from lower-level routines.
+    Amendments to the prologues of these routines.  Reported by
+    Hans Terlouw.
+
+  - Similarly for wcsunitse(), wcsulexe(), and wcsutrne().
+
+* PGSBOX
+
+  - Bug fix in PGSBOX for handling cycles in angle when both world
+    coordinate elements are angular.  Reported by Thomas Robitaille.
+
+
+WCSLIB version 4.14 (2012/07/13)
+--------------------------------
+
+* C library
+
+  - Problems were caused for fitshdr(), wcsbth(), wcspih(), wcsulex(),
+    datfix() and wcshdo(), by locales such as "fr_FR" in which commas
+    are used to delimit the decimal part of floating point numbers.
+    In particular, these locales adversely affect the behaviour of
+    sscanf() and sprintf() when reading and writing FITS header
+    keyvalues.  Thread-safe fixes provided by Michael Droettboom.
+
+  - Applied astropy patches from Michael Droettboom: attend to compiler
+    warnings in prj.c, spc.c, tab.c, and wcsutil.c, including those for
+    MS-Windows.
+
+
+WCSLIB version 4.13.4 (2012/04/02)
+----------------------------------
+
+* Installation
+
+  - Relaxed the closure tolerance slightly in tlog.f as for tlog.c
+    previously.
+
+
+WCSLIB version 4.13.3 (2012/03/26)
+----------------------------------
+
+* Installation
+
+  - Relaxed the closure tolerance slightly in tlog.c for gcc 4.6.3 on
+    Ubuntu 12.04 (reported by Ole Streicher).
+
+
+WCSLIB version 4.13.2 (2012/03/21)
+----------------------------------
+
+* Installation
+
+  - Changes to configure.ac and the GNUmakefiles to put '-lm' strictly
+    in the correct sequence when producing the sharable library
+    (reported by Ole Streicher).
+
+
+WCSLIB version 4.13.1 (2012/03/15)
+----------------------------------
+
+* C library
+
+  - Workaround in wcserr_set() for an unfortunate compiler segv from
+    gcc 4.2.1 in MacOSX 10.7.
+
+
+WCSLIB version 4.13 (2012/03/14)
+--------------------------------
+
+* C library
+
+  - Allow naxis == 0 in wcsini() and linini() for a degenerate
+    coordinate system as may be produced by wcssub().  In wcssub(),
+    ensure that wcsini() is called for coordinate systems with
+    naxis == 0.  In wcssptr(), call spcfree() before spcini() to plug a
+    memory leak.
+
+
+WCSLIB version 4.12 (2012/02/29)
+--------------------------------
+
+* C library
+
+  - In spctrne(), guard against restfrq == restwav == 0.0 when
+    translating between two velocity-characteristic types, or between
+    two wave-characteristic types (the translation is independent of
+    restfrq and restwav, but a dummy value is needed for intermediate
+    calculations).
+
+
+WCSLIB version 4.11 (2012/02/21)
+--------------------------------
+
+* C library
+
+  - Bug fix in spcset() for handling simple linear spectral axes.
+
+* Fortran wrappers
+
+  - Bug fix in spctrne_() for handling ctypeS2.
+
+
+WCSLIB version 4.10 (2012/02/06)
+--------------------------------
+
+* C library
+
+  - datfix() and spcfix() now return informative messages when dates and
+    AIPS-convention spectral axes are translated (changes contributed by
+    Michael Droettboom).  spcaips() now returns an error status for
+    invalid values of VELREF.
+
+  - wcssub() has been augmented with the ability to add new axes onto a
+    wcsprm struct.
+
+
+WCSLIB version 4.9 (2012/01/24)
+-------------------------------
+
+* C library
+
+  - Fixes to wcsfixi() for collecting the messages properly in the info
+    array (from Michael Droettboom).
+
+  - Handle certain malformed date strings more gracefully in datfix().
+
+  - Make informative messages printed by wcserr_prt() a bit more
+    informative.
+
+
+WCSLIB version 4.8.4 (2011/12/05)
+---------------------------------
+
+* C library
+
+  - Fixed the pseudo-random number generator in twcstab.c - gcc 4.6 with
+    '-O2' baulked at testing for signed integer overflow.
+
+* Installation
+
+  - In configure.ac, the Fortran compiler's libraries must be added to
+    the link list when checking for the PGPLOT libraries since gcc is
+    driving the linker.  Likewise in C/GNUmakefile when linking test
+    programs that use PGPLOT.
+
+  - Use 'make CHECK=nopgplot check' to run only the non-graphical tests
+    (even if PGPLOT is available).
+
+  - After compiling and running the tests, 'make check' now summarizes
+    the non-graphical test results and stops if any failed.
+
+
+WCSLIB version 4.8.3 (2011/11/17)
+---------------------------------
+
+* C library
+
+  - Minor generalization of the wcserr diagnostics to allow the return
+    of informative messages which are associated with negative status
+    values.  wcserr_prt() will now recognize and print them as such.
+    Added wcserr_clear() to reset (clear) a wcserr struct.
+
+  - Modified unitfix() to return an informative message if a units
+    alias is applied, and wcsfixi() to allow such messages to be
+    propagated through the info array (from Michael Droettboom).
+
+  - Modified twcsfix.c to use wcserr diagnostics, in particular to
+    report units alias translations.
+
+* Fortran wrappers
+
+  - In wcsfix_(), interpret *naxis == 0 as meaning naxis == 0x0, thus
+    causing cylfix() to be skipped.
+
+  - Modified twcsfix.f to reflect changes made to twcsfix.c.
+
+
+WCSLIB version 4.8.2 (2011/10/04)
+---------------------------------
+
+* Installation
+
+  - Changes for Debian package generation contributed by Ole Streicher:
+    - Corrections to 'configure' reported by 'lintian'.
+    - Generate man pages for the utility programs and install them.
+
+
+WCSLIB version 4.8.1 (2011/09/19)
+---------------------------------
+
+* Installation
+
+  - Set SONAME in the sharable library in accordance with
+    tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html
+    (reported by Ole Streicher, Debian package maintainer).  The
+    sharable library will again be installed with full release number
+    and with a symbolic link from SONAME pointing to it.  If defined,
+    SHRLN will point to SONAME.
+
+
+WCSLIB version 4.8 (2011/08/15)
+-------------------------------
+
+* C library
+
+  - New error diagnostics mechanism contributed by Michael Droettboom:
+
+    Most functions that return a numeric status (error) code now also
+    write a detailed error message to a wcserr struct attached to the
+    passed-in *prm struct.  See wcserr.h for more information.
+
+    Functions that didn't have a *prm struct as an argument have no
+    direct way to return an error message.  Therefore, these functions
+    now have duplicate versions with the suffix "e" that take an
+    additional "struct wcserr *" parameter.  These functions are:
+
+        spcspx()    ->  spcspxe()
+        spctrn()    ->  spctrne()
+        spctyp()    ->  spctype()
+        spcxps()    ->  spcxpse()
+        wcsulex()   ->  wcsulexe()
+        wcsunits()  ->  wcsunitse()
+        wcsutrn()   ->  wcsutrne()
+
+    A new function wcsfixi() was added which is identical to wcsfix()
+    but in addition stores all of the detailed textual messages about
+    the fixes that were performed.
+
+  - In wcssub(), ensure that wcstab->m_tab has been initialized
+    before trying to free it on status return 12 or 13 (reported by
+    Hans Terlow).
+
+  - Bug fixes:
+    - In sphx2s() and sphs2x() for the case where |eul[1]| = 180.0.
+    - For parsing AIPS-convention VELREF in wcsbth().
+    - In spcaips() for translating AIPS-convention CTYPEia without
+      Doppler frame.
+
+  - Non-graphical test programs now simply report "PASS" if they satisfy
+    the reporting tolerance for closure residuals, etc.  Their full
+    output is reported otherwise.  Run 'make MODE=interactive check' to
+    revert to the previous behaviour of reporting the full output for
+    tests that succeed.
+
+  - Eliminated compiler warnings about type-punning of pointer-to-
+    function.
+
+* Fortran wrappers
+
+    Extensive modifications to track the new error handling mechanism
+    in the C library.
+
+* Installation
+
+  - configure now prefers gfortran over g77 if available.
+
+  - Don't rely on "." being in the PATH if config.status needs to be
+    run in the pgsbox and utils makefile (reported by Peter Teuben).
+
+
+WCSLIB version 4.7 (2011/02/07)
+-------------------------------
+
+* C library
+
+  - Bug fix in celset() for interpreting LATPOLEa when LONPOLEa = phi0.
+    Crept in at version 4.4.
+
+  - Fixed the bounds test on y in hpxx2s() (HEALPix projection) for
+    unconventional values of H and K.  In hpxx2s() and hpxs2x(),
+    corrected the offset of the southern polar half-facets for
+    even K.  In hpxs2x(), put the phi = 180 meridian in the expected
+    place.
+
+  - Bug fixes in tabx2s() and tabs2x() for default indexes (reported
+    by David Berry).  In tabs2x(), if no solution is found then do
+    minor extrapolation past the ends of each row (1-D case only).
+    Sped up tabs2x() by about 50%.
+
+  - New functions wcsprintf(), wcsprintf_set(), and wcsprintf_buf(),
+    declared in wcsprintf.h, provide control over the disposition of
+    output from celprt(), linprt(), prjprt(), spcprt(), tabprt(), and
+    wcsprt() routines.  Prompted by Michael Droettboom, with an initial
+    implementation.
+
+* Fortran wrappers
+
+  - In the various test programs, used EQUIVALENCEs to ensure that the
+    CEL, LIN, PRJ, etc. arrays are aligned on a DOUBLE PRECISION
+    boundary.
+
+* PGSBOX
+
+  - Bug fix for the case where NG1 == 0 and GRID1(0) < 0, and likewise
+    for NG2 and GRID2.
+
+* Utilities
+
+  - In wcsware, added a '-w' option to convert world coordinates
+    obtained from stdin to pixel coordinates using wcss2p().  Allow
+    multiple sets of input coordinates with the '-x' and '-w' options
+    and report the value of the intermediate world coordinates.
+
+* User manual
+
+  - Fixed list formatting for function return values < 0 or > 9.
+
+  - New section for wcsprintf() and related routines.
+
+* Installation
+
+  - Changes prompted by Sébastien Fabbro for the Gentoo Linux package:
+      a) autoconf updates,
+      b) respect LDFLAGS when building the shared library,
+      c) install documentation,
+      d) recognise DESTDIR for doing a staged installation.
+
+  - As of this release, the minor WCSLIB version number (second field)
+    will be incremented if and only if a change is made that affects the
+    library itself, not the documentation or utilities.  The version
+    number on the installed libraries and header files will omit the
+    patch number (third field).
+
+
+WCSLIB version 4.6.3 (2010/11/24)
+---------------------------------
+
+* C library
+
+  - Bug fix in wcsbth() for handling the inheritance of image header
+    keywords (uncovered by valgrind, reported by Jim Lewis).
+
+
+WCSLIB version 4.6.2 (2010/11/22)
+---------------------------------
+
+* C library
+
+  - Fixed a memory leak in wcsbth.l (reported by Jim Lewis).
+
+
+WCSLIB version 4.6.1 (2010/11/18)
+---------------------------------
+
+* Fortran wrappers
+
+  - Fixed typos in cel_f.c, celget[cdi] -> celgt[cdi].
+
+
+WCSLIB version 4.6 (2010/11/16)
+-------------------------------
+
+* C library
+
+  - In wcsulex.l and wcsutrn.l, stdlib.h must be included explicitly
+    before the redefinition of exit() - most versions of flex do include
+    it upfront but some don't (reported by Peter Williams).
+
+* Fortran wrappers
+
+  - Changes intended to avert nuisance compiler warnings that could
+    potentially obscure warnings indicative of a genuine problem:
+
+    - To stop messages about unused variables when the relevant compiler
+      option is set, e.g. 'g77 -Wunused', the various *_ERRMSG arrays
+      defined in the Fortran include files and (formerly) initialized
+      therein via DATA statements, e.g. PRJ_ERRMSG in prj.inc, have now
+      been placed into COMMON blocks with names such as PRJ_DATA, and
+      are initialized via DATA statements in BLOCK DATA subprograms
+      defined in separate files, e.g. prj_data.f.
+
+    - To stop messages about subroutines being invoked with inconsistent
+      argument lists if the relevant compiler option is not set, e.g.
+      'g77 -Wno-globals', the C wrapper functions that take 'void *'
+      arguments now have separate forms for INTEGER, DOUBLE PRECISION,
+      and CHARACTER arguments that simply invoke the generic function.
+      Application code must be modified to take advantage of this.
+
+* User manual
+
+  - In the section on the Fortran wrappers in the manual, warn about the
+    need for the INTEGER array holding a data structure to be aligned on
+    a DOUBLE PRECISION boundary.
+
+
+WCSLIB version 4.5.6 (2010/10/28)
+---------------------------------
+
+* Installation
+
+  - Fixed the search for CFITSIO and PGPLOT library and include
+    directories.
+
+
+WCSLIB version 4.5.5 (2010/10/14)
+---------------------------------
+
+* Installation
+
+  - Build the PGSBOX sharable library.
+
+
+WCSLIB version 4.5.4 (2010/09/28)
+---------------------------------
+
+* C library
+
+  - In wcshdo(), according to the FITS standard, "Letters in the
+    exponential form ('E' or 'D') shall be upper case" (reported by
+    Michael Droettboom).
+
+
+WCSLIB version 4.5.3 (2010/09/23)
+---------------------------------
+
+* Utilities
+
+  - Various improvements to wcsgrid: correct the scaling set via
+    cpgwnad(); label angles other than RA,Dec in decimal degrees;
+    draw the projection boundary for projections other than zenithals.
+
+
+WCSLIB version 4.5.2 (2010/09/23)
+---------------------------------
+
+* C library
+
+  - Fixed the translation of GLS to SFL in wcsset() and celfix() when
+    the reference longitude is non-zero - it introduces an offset in
+    longitude in the normal way.  (This undoes part of the change
+    applied in version 4.4.)
+
+
+WCSLIB version 4.5.1 (2010/08/12)
+---------------------------------
+
+* C library
+
+  - New utility function, sphpad(), computes the coordinates of points
+    offset by given angular distances and position angles from a given
+    point on the sky (complementary to sphdpa()).
+
+* Fortran wrappers
+
+  - New wrapper function:
+    - SPHPAD for sphpad().
+
+
+WCSLIB version 4.5 (2010/07/16)
+-------------------------------
+
+* C library
+
+  - Fixed the interpretation of VELREF when translating AIPS-convention
+    spectral types.  Such translation is now handled by a new special-
+    purpose function, spcaips().  The wcsprm struct has been augmented
+    with an entry for velref which is filled by wcspih() and wcsbth().
+    Previously, selection by VELREF of the radio or optical velocity
+    convention for type VELO was not properly handled.
+
+* Fortran wrappers
+
+  - New wrapper function:
+    - SPCAIPS for spcaips().
+
+  - Changed spc.inc, spc_f.c, wcs.inc and wcs_f.c to track VELREF
+    changes.
+
+  - Declared functions external in the include files to avoid compiler
+    warnings about unused variables (if the particular option is set).
+
+* Utilities
+
+  - Added a '-q' option to fitshdr to quit after a specified number
+    of HDUs.
+
+
+WCSLIB version 4.4.4 (2009/09/14)
+---------------------------------
+
+* Installation
+
+  - Added more configure options for controlling the build:
+    --disable-fortran, --disable-utils, --without-cfitsio, and
+    --without-pgplot.
+
+
+WCSLIB version 4.4.3 (2009/09/03)
+---------------------------------
+
+* C library
+
+  - Set wave number units to "/m" in spctyp(), was "1/m" which is not
+    strictly legal and wasn't handled by wcsulex() (reported by
+    Hans Terlow).  Also fixed a number of units specifications in the
+    prologue of spx.h to conform with Paper I usage.
+
+  - In wcsulex(), allow unit strings like "1/m" in addition to "/m",
+    provided that the superfluous "1" is the first non-blank character
+    in the expression, or parenthesised sub-expression.
+
+  - In wcssptr(), ensure that i is always reset if given < 0.
+
+* User manual
+
+  - Augmented the list of FITS WCS and related software in the manual.
+
+
+WCSLIB version 4.4.2 (2009/08/13)
+---------------------------------
+
+* C library
+
+  - In sphx2s() and sphs2x(), handle the case where |eul[1]| = 180.0
+    separately for speed and accuracy.  This change also fixes a rare
+    and subtle bug in cels2x() that occurs when celprm::isolat is set
+    and the magnitude of the first latitude in the lat[] vector exceeds
+    90 deg (reported by Hans Terlouw).
+
+* Installation
+
+  - Fix relating to creation of symlinks when installing the libraries.
+
+
+WCSLIB version 4.4.1 (2009/08/11)
+---------------------------------
+
+* Installation
+
+  - Fixes for installation of the CHANGES file and for the creation of a
+    symbolic link for the sharable library if one already exists.
+
+
+WCSLIB version 4.4 (2009/08/10)
+-------------------------------
+
+* C library
+
+  - Creation of WCSLIB user manual from the header file prologues using
+    a special-purpose parser, doxextr, and sed scripts to generate input
+    for doxygen.  This required minor formatting changes to all
+    prologues plus miscellaneous changes such as naming of arguments in
+    function prototypes.
+
+  - Bug fix in wcsset() that affected handling of PROJPn (deprecated)
+    and PVi_ma attached to the longitude (not latitude) axis.  Guard
+    against long strings when copying the projection code.  In
+    wcs_types(), allow for early Paper IV distortion codes (e.g.
+    "RA---TAN-SIP") when parsing CTYPEia.
+
+  - Use sincos() whereever possible for a ~15% speedup (patches for
+    cel.c, prj.c and sph.c supplied by Michael Droettboom).  configure
+    checks for, and uses it automatically if available.
+
+  - Fixed the translation of GLS to SFL in wcsset() and celfix() when
+    the reference longitude and latitude are non-zero.  (In the AIPS
+    convention, this simply translates the reference point, i.e. the map
+    as a whole, to those coordinates without creating an oblique grid.)
+
+  - Bug fix in prjoff(), a utility function used by the prj routines.
+    It forces (x,y) = (0,0) at (phi_0,theta_0) when the latter are set
+    by PVi_[012]a attached to the longitude (not latitude) axis.  Rarely
+    used in practice.
+
+  - New utility function, sphdpa(), computes the distance and position
+    angle from a point on the sphere to a set of field points.
+
+  - In sphx2s() and sphx2s(), handle a simple change in origin of
+    longitude using a short-cut calculation for speed and accuracy.
+    Similarly in celset(), check whether phip == phi0 when computing
+    latp and if so use a short-cut that ensures latp == 90.0 (exactly)
+    if lat0 == theta0.  The resulting spherical rotation then becomes a
+    simple change in origin of longitude.  In particular, these changes
+    should assist PGSBOX in drawing grid lines of +/-180 longitude, to
+    prevent flip-flopping between one and the other.
+
+  - wcsbth() & wcspih(): resolved an inconsistency between the
+    documentation and code by renamimg WCSHDR_VSOURCEa as
+    WCSHDR_VSOURCE.
+
+  - Flex code: moved declaration of helper functions out of global
+    scope.
+
+  - Fixed the call to wcss2p() in twcshdr (in a section of code not
+    usually exercised).
+
+* Fortran wrappers
+
+  - New wrapper functions:
+    - WCSBTH for wcsbth(),
+    - WCSBDX for wcsbdx(),
+    - CDFIX  for cdfix(),
+    - SPHDPA for sphdpa().
+
+  - Updated WCSLEN (in wcs.inc) and added WCS_COLAX and WCS_VELANGL to
+    match changes to wcsprm made in v4.3 with corresponding changes to
+    the wrapper functions.  Likewise updated TABLEN (in tab.inc) for
+    changes to tabprm, and added CEL_LATPREQ for celprm.
+
+  - Struct lengths (WCSLEN, PRJLEN, etc.) are now long enough to
+    accomodate 64-bit machines.
+
+  - Updated the flag bits for the RELAX argument in wcshdr.inc to
+    reflect changes to wcshdr.h made in v4.3.  Renamed WCSHDR_VSOURCEa
+    to WCSHDR_VSOURCE for consistency with the C library.
+
+* PGSBOX
+
+  - Improved grid labelling, particularly in minimizing the number of
+    fields required in sexagesimal labels.
+
+* Utilities
+
+  - New utility program:
+
+    - wcsware extracts the WCS keywords for an image from the specified
+      FITS file, constructs wcsprm structs for each coordinate
+      representation found, and performs a variety of operations using
+      them.
+
+  - Old utility programs (first appeared in 4.3 but were not recorded):
+
+    - HPXcvt reorganises HEALPix data into a 2-D FITS image with HPX
+      coordinate system.
+
+    - wcsgrid extracts the WCS keywords for an image from the specified
+      FITS file and uses pgsbox() to plot a 2-D coordinate graticule for
+      each alternate representation found.
+
+    - fitshdr lists headers from a FITS file specified on the command
+      line, or else on stdin, printing them as 80-character keyrecords
+      without trailing blanks.
+
+* Installation
+
+  - New configure options, --with-pgplotinc, --with-pgplotlib,
+    --with-cfitsioinc and --with-cfitsiolib allow additional directories
+    to be added to the library and include file search path.
+
+  - Miscellaneous fixes and improvements to the installation process.
+
+  - Generate a metadata file for pkg-config.
+
+  - Added 'make MODE=interactive check' to run the test programs in
+    interactive mode rather than batch.
+
+  - Merged the separate CHANGES files for C, Fortran and PGSBOX into
+    one (this), with a new section for utilities.
+
+
+WCSLIB version 4.3.3 (2009/04/30)
+---------------------------------
+
+* C library
+
+  - fitshdr.l, wcsbth.l, and wcspih.l: use setjmp/longjmp to preempt
+    the call to exit() which is hard-coded in function yy_fatal_error()
+    supplied by flex.
+
+  - wcspih.l: if NAXIS is non-zero but there were no WCS keywords at
+    all in the header then create a default WCS with blank alternate
+    version.
+
+
+WCSLIB version 4.3.2 (2009/03/16)
+---------------------------------
+
+* C library
+
+  - utils/GNUmakefile: create BINDIR if necessary prior to installing
+    utilities.
+
+
+WCSLIB version 4.3.1 (2008/09/08)
+---------------------------------
+
+* Installation
+
+  - Top-level GNUmakefile: install header files.
+
+
+WCSLIB version 4.3 (2007/12/27)
+-------------------------------
+
+* C library
+
+  - A new general WCS header parser wcsbth() handles binary table image
+    arrays and pixel lists as well as image array headers.  Added
+    "colax" to the wcsprm struct to record the column numbers for each
+    axis in a pixel list.
+
+  - New function wcsbdx() is the analog of wcsidx() for the array of
+    wcsprm structs returned by wcsbth().
+
+  - New function wcshdo() writes out a wcsprm struct as a FITS header.
+
+  - Changes to wcspih():
+    - Bug fix, check for a == 0 (indication of a keyword that applies
+      to all alternates) in internal helper function wcspih_naxes()
+      (reported by Craig Markwardt).
+    - Added a new ctrl option to remove valid WCS keyrecords except for
+      those with a more general role, namely {DATE,MJD}-{OBS,AVG} and
+      OBSGEO-{X,Y,Z} (suggested by Jim Lewis).
+    - Added a rule for VELANGLa.  Also added "velangl" to the wcsprm
+      struct.
+    - Do checks on the i, k & m keyword parameters in <VALUE>.
+    - Fixed the test for repeated blanks in the NAXIS and WCSAXES
+      patterns.
+    - Fixed three <CCi_ma> rules to allow m == 0.
+    - Reworked the implementation notes in the prologue.
+
+  - The flex scanners, fitshdr.l, wcsbth.l, wcspih.l, wcsulex.l, and
+    wcsutrn.l, invoke yylex_destroy() before returning to avoid a 16kiB
+    memory leak.  This was reported by several people, however it may be
+    problematic depending on the version of flex used - version 2.5.9 or
+    later is required.  If this is not available, C sources pre-
+    generated by flex 2.5.33 will be used.
+
+  - In wcs.c, don't define the signbit macro if already defined (for
+    MacOSX).
+
+  - In wcs.h, documented wtbarr namespace issues in C++.
+
+  - In wcsset(), always set wcsprm.cunit[i], if possible (primarily for
+    use by wcshdo()).
+
+  - In wcsfix.c, parenthesised a boolean expression that was otherwise
+    incorrect.
+
+  - Fixed an obscure floating point rounding error in celset() that
+    appeared with -O2 optimization in gcc v3.3.5 (Linux).
+
+  - prjset() now correctly propagates the status value returned by the
+    specific projection-setting functions (reported by Bill Pence).
+
+  - Bug fix in hpxx2s(), also added bounds checking.  Minor efficiencies
+    in carx2s() and merx2s().
+
+  - In the various functions that print the contents of the structs, use
+    the "%p" printf conversion specifier to print addresses rather than
+    casting the pointer to int and using "#x".  The latter does not work
+    on 64-bit machines where sizeof(int) != sizeof(void*).
+
+  - Reorganized the various structs to get alignment on 64-bit machines.
+
+  - All header file prologues now reference the README file for an
+    overview of the library.
+
+  - Miscellaneous portability fixes for 64-bit, MacOSX, OSF compiler,
+    etc.
+
+  - Elimination of compiler warnings, e.g. parenthesised assignments
+    used as truth values (a favourite gcc gripe!), etc.
+
+  - Process flex descriptions using a newer version of flex, primarily
+    for MacOSX.  However, the processed files are now only used when
+    flex 2.5.9 or later is not available.
+
+  - Removed WCSLIB 2.x backwards-compatibility measures from lin.h,
+    prj.h, prj.c, and sph.h.
+
+* Fortran wrappers
+
+  - (No substantive changes.)
+
+* PGSBOX
+
+  - Miscellaneous improvements to PGSBOX.
+
+* General
+
+  - Switched licensing to LGPL 3.0.
+
+  - In comment text, replaced use of the obsolete term "card" with
+    "keyrecord" which consists of a "keyword", "keyvalue", and
+    "keycomment".
+
+* Installation
+
+  - General improvements to the installation process: autoconf-related
+    portability improvements, particularly relating to Fortran name
+    mangling; makefile rules for building the shared library, for
+    processing flex descriptions; don't rely on "." being in the PATH
+    when running tests.
+
+
+WCSLIB version 4.2 (2005/09/23)
+-------------------------------
+
+* C library
+
+  - Brought the installation process under control of GNU autoconf,
+    the top-level makefile now builds and tests everything, and the C
+    library has a config.h in which WCS_INT64 is set.  Added an INSTALL
+    file.
+
+  - Merged the FORTRAN, C and PGSBOX READMEs into one top-level README.
+
+  - Extensions for -TAB coordinate handling: in tabx2s() and tabs2x(),
+    allow extrapolation by half a cell at either end of the index and
+    coordinate tables; fits_read_wcstab() (in getwcstab.{h,c}) allows
+    TDIMn to be omitted for 1-D lookup tables for which it has the form
+    '(1,K)', i.e. describing a degenerate 2-D array; wcsprt() now prints
+    the wtbarr structs in wcsprm.
+
+  - Bug fixes for -TAB coordinate handling: in tabx2s() and tabs2x()
+    the incorrect indexing variable, m instead of i, was used for
+    tab->crval[]; wcsp2s() and wcss2p() returned prematurely in the
+    tabular coordinate loop; in wcstab(), removed an extraneous
+    assignment to wtbp->kind for index arrays.
+
+  - In wcsp2s() and wcss2p(), elements of the stat[] vector that had
+    been set were being reset incorrectly to zero.  The stat[] values
+    are now set as flag bits for each coordinate element.
+
+  - Added cdfix() to the wcsfix() suite to fix erroneously omitted
+    CDi_ja cards.
+
+  - PGSBOX is now compiled into a separate object library, and is
+    installed alongside WCSLIB.
+
+  - Eliminated several instances of non-ANSI C library functions and
+    header files and some residual K&R C usage.  The Sun C compiler
+    complained about const int definitions of initializers used in
+    variable declarations in some of the test programs; changed these
+    to preprocessor macros.
+
+* Fortran wrappers
+
+  - Fixed handling of 64-bit integer keyvalues in keyget_().
+
+  - Fixed output formatting of 64-bit integer keyvalues in tfitshdr.f.
+
+  - Fixed minor syntax errors in twcsfix.f and tpih1.f reported by the
+    Sun Fortran compiler.
+
+  - The output of each test program now identifies the source file.
+
+* PGSBOX
+
+  - (No substantive changes.)
+
+
+WCSLIB version 4.1 (2005/08/31)
+-------------------------------
+
+* C library
+
+  Summary of added functionality:
+
+  - -TAB coordinate axes are now fully implemented in the WCSLIB driver
+    functions (in wcs.{h,c}); multiple -TAB axes are supported.  A new
+    function, wcstab(), which is automatically invoked by wcspih(),
+    parses -TAB-related header cards and sets up structs for a separate
+    routine that reads the necessary arrays from a FITS binary table
+    extension.
+
+    An implementation of this routine in CFITSIO, fits_read_wcstab(),
+    is provided.  Note however that the interface of this function is
+    experimental, and the code itself must be considered beta-release in
+    WCSLIB 4.1.
+
+  - Units specifications, either from CNAMEia or inline comments (with
+    brackets), of arbitrary complexity are now fully implemented via a
+    parser, wcsulex(), and converter, wcsunits().  This is invoked
+    automatically by wcsset().
+
+  - Translators for non-standard WCS constructs are provided.  These
+    cover date formats, units specifications, defunct celestial
+    projection types, AIPS spectral axis types, and the repair of
+    malformed cylindrical coordinate systems.
+
+  - wcspih() now has options to remove the WCS cards it has processed
+    from the header and a new generic FITS header parser, fitshdr(), may
+    be used to parse the remaining non-WCS cards.  In addition to the
+    more basic types, it handles 64-bit and 'very long' (70 digit)
+    integer keyvalues, and also continued string keyvalues.  It also
+    does keyword matching and extracts units specifications in inline
+    comments.
+
+  - -LOG coordinates are now implemented independently of spectral
+    coordinate types.  Multiple -LOG axes are supported.
+
+  - New function wcssptr() translates the spectral axis in a wcsprm
+    struct to the required type.
+
+  - The README file now gives an introduction to, and complete overview
+    of, WCSLIB.  It provides a point of entry to programming with
+    WCSLIB.  Complete descriptions and usage notes for all functions are
+    contained in the header files.
+
+  - The FORTRAN wrappers and test programs are now completely up-to-date
+    with respect to the C implementation.
+
+  - All code, including the FORTRAN wrappers, PGSBOX, and all test
+    programs, now pass 'purify' without memory leaks, uninitialized
+    memory reads, memory access violations, or other memory faults.
+
+  Change notes:
+
+  - Added options to wcspih() to remove WCS cards from the input header
+    leaving only non-WCS cards behind.  Modified test programs tpih1.c
+    and tpih2.c to use CFITSIO optionally via preprocessor macro
+    DO_CFITSIO.
+
+  - New function wcstab() in wcshdr.{h,c} parses -TAB-related header
+    cards and sets up structs for a separate routine that reads the
+    necessary arrays from a FITS binary table extension.  New
+    test/demo program twcstab.c using header defined in wcstab.cards.
+
+  - CFITSIO implementation, fits_read_wcstab() in getwcstab.{h,c}, of a
+    function, independent of WCSLIB, for extracting arrays from a binary
+    table as required in constructing -TAB coordinates.
+
+  - New units specification parser, wcsulex() in wcsunits.h and
+    wcsulex.l, and converter, wcsunits() in wcsunits.{h,c}.  New
+    test/demo program tunits.c.
+
+  - New parser for non-standard units specifications, wcsutrn() in
+    wcsunits.h and wcsutrn.l, also tested by tunits.c.
+
+  - New functions datfix(), unitfix() (which applies wcsutrn()),
+    celfix(), and spcfix() join cylfix() in wcsfix.{h,c} to translate
+    various forms of non-standard or quasi-standard FITS WCS keyvalues
+    in a wcsprm struct.  wcsfix() applies all of these in sequence.
+    New test/demo program twcsfix.c, with wcsfix() also now invoked by
+    tpih1.c.
+
+  - New generic FITS header parser, fitshdr() in fitshdr.{h,l}.  New
+    test/demo program tfitshdr.c uses wcs.cards with extra non-WCS
+    cards added.
+
+  - -LOG coordinates are now treated as a coordinate type separate from
+    spectral coordinates, implemented via log.{h,c} and test program
+    tlog.c.  The logarithmic functions were removed from spx.{h,c}, and
+    spc.c.
+
+  - Extensive changes to wcs.{h,c} to support multiple -TAB and -LOG
+    coordinate axes and units conversion.  Substantially changed the
+    test program, twcs.c, to test the more general functionality.
+
+  - New function wcssptr() in wcs.{h,c} translates the spectral axis in
+    a wcsprm struct.
+
+  - Added DATE-AVG to wcsprm.  Also ntab, tab, nwtb, and wtb required
+    for -TAB implementation.  Define struct wtbarr.
+
+  - Added a types[] member to the wcsprm struct to identify axis
+    coordinate types using a four-digit code.
+
+  - Use memset() in wcsini() to null-fill character arrays in the wcsprm
+    struct so that they don't appear to be padded with garbage when
+    displayed by gdb.
+
+  - Do alias translation for AIPS-convention spectral types in wcsset()
+    using spctyp().  If wcsset() finds a CTYPEia in "4-3" form with an
+    unrecognized algorithm code it now returns an error rather than
+    assume that it's a linear axis.  wcsset() now also resets lonpole
+    and latpole to the values actually used.
+
+  - Modified spctyp() to translate AIPS-convention spectral ctypes, and
+    modified the argument list to return the parsed spectral type and
+    algorithm code.  The return arguments will not be modified if
+    CTYPEia is not a valid spectral type; zero-pointers may be specified
+    for any that are not of interest.  Removed the external const
+    variables, spc_codes and spc_ncode, as their function is now
+    fulfilled by spctyp().
+
+  - Fixed a bug in spctrn() in resolving ctypeS2 wildcarding.
+
+  - Added latpreq member to the celprm struct, set by celset() to
+    indicate how LATPOLE is used.  Augmented tcel2.c to report it.
+
+  - New function tabmem() in tab.{h,c} takes control of user-allocated
+    memory.
+
+  - tabini() allows K == 0 and also K[m] == 0 to initialize partially
+    the tabprm struct (for wcstab()).  It now does fine-grained
+    bookkeeping of memory allocation for the index arrays and allocates
+    each individually.  tabprm.index[] == 0x0 is recognized as default
+    indexing in tabset(), tabx2s() and tabs2x().
+
+  - The *prt() functions report parameters to an extra decimal place.
+
+  - tabprt() prints the array index for elements of the coordinate and
+    index vectors.
+
+  - Set the 0th element in all *_errmsg arrays to "Success".
+
+  - Extracted string utility functions used by WCSLIB into
+    wcsutil.{h,c}.
+
+  - Removed support for K&R C.
+
+* Fortran wrappers
+
+  - The FORTRAN wrappers and test programs are now completely up-to-date
+    with respect to the C implementation.
+
+  - New include files, wrappers, and test programs:
+    fitshdr.inc, fitshdr_f.c, getwcstab.inc, getwcstab_f.c, log.inc,
+    log_f.c, sph.inc, tab.inc, tab_f.c, tfitshdr.f, tlog.f, ttab1.f,
+    ttab2.f, ttab3.f, tunits.f, twcsfix.f, twcstab.f, wcsfix.inc,
+    wcsfix_f.c, wcsunits.inc, wcsunits_f.c.
+
+  - Updates to reflect changes to the C library and test programs:
+    cel.inc, cel_f.c, prj.inc, spc.inc, spc_f.c, spx.inc, spx_f.c,
+    tlin.f, tpih1.f, tpih2.f, tprj1.f, tprj2.f, tspc.f, tsph.f, tspx.f,
+    twcs.f, twcsmix.f, twcssub.f, wcs.inc, wcs_f.c, wcshdr.inc,
+    wcshdr_f.c.
+
+  - Added *_ERRMSG arrays containing status messages to all include
+    files.
+
+  - Removed support for K&R C.
+
+* PGSBOX
+
+  - Fixed a subtle though benign memory fault identified by 'purify'.
+
+  - Reset LATPOLE in the COE example in cpgtest.f when drawing the
+    second (native) grid because it will have been set to a non-default
+    value by wcsset() when the first grid was drawn; set wcs.flag to -1
+    before wcsinit() and call wcsfree() at the end.  Similarly for
+    pgtest.f.
+
+
+WCSLIB version 4.0 (2005/02/07)
+-------------------------------
+
+* C library
+
+  - Implemented tabular coordinates (-TAB).  New files: tab.h and tab.c,
+    and test programs ttab[123].c.  These have not been incorporated
+    into the higher-level (wcs.h) functions at this stage.
+
+  - New spectral functions: spchek() checks a spectral algorithm code
+    for legitimacy; from the spectral keywords given, spcspx() derives
+    the corresponding CRVALi and CDELTi keywords for the underlying P-,
+    and X-type spectral coordinates; spcxps() does the opposite;
+    spctrn() combines spcspx() and spcxps() to translate one set of
+    spectral keywords into another, e.g.  'FREQ' -> 'ZOPT-F2W'.
+
+  - Implemented the HEALPix (HPX) projection in the prj functions.
+
+  - Added a new function, wcsidx(), to return an array that indexes the
+    alternate coordinate descriptions found by wcspih() (suggested by
+    Bill Pence, NASA/Goddard).  Modified tpih1.c to exercise it.
+
+  - In wcsp2s() and wcss2p(), check that nelem equals or exceeds
+    wcs.naxis; emphasised this in the usage notes for these functions
+    in tab.h (suggested by Bill Pence, NASA/Goddard).
+
+  - Moved the macros used for UNDEFINED values and the corresponding
+    macro test function, undefined(), to wcsmath.h for general use.
+    Previously, UNDEFINED values were only used internally, but they are
+    now visible in some of the structs, particularly values of undefined
+    auxiliary header cards in the wcsprm struct.
+
+  - Remove const from the double args in the specx() prototype in spx.h
+    to match the definition in spx.c (reported by Bryan Irby,
+    NASA/Goddard).
+
+  - Fixed the interaction between the FLAVOUR and PGPLOTLIB definitions
+    in the C and FORTRAN Makefiles by introducing a separate variable,
+    DO_PLOTS, to control whether to exercise test programs that require
+    PGPLOT (reported by Bill Pence, NASA/Goddard).
+
+* Fortran wrappers
+
+  - New wrapper defined in wcshdr_f.c: wcsidx_().  Modified test program
+    tpih1.f to use it.
+
+* PGSBOX
+
+  - (No substantive changes.)
+
+* General
+
+  - Changed the copyright notice in all library routines from LGPL to
+    GPL as recommended by the FSF (http://www.gnu.org/licenses/why-not-
+    lgpl.html).
+
+* Installation
+
+  - General improvements to the installation process: fixed the
+    interaction between the FLAVOUR and PGPLOTLIB definitions in the
+    Makefile by introducing a separate variable, DO_PLOTS, to control
+    whether to exercise test programs that require PGPLOT (reported by
+    Bill Pence, NASA/Goddard).  Added an "install" target to the
+    Makefile.
+
+
+WCSLIB version 3.6 (2004/08/25)
+-------------------------------
+
+* C library
+
+  - New service routine, wcssub() extracts the coordinate description
+    for a subimage from a wcsprm struct.  wcscopy() is now implemented
+    as a preprocessor macro that invokes wcssub().  New test program,
+    twcssub.c, tests wcssub().
+
+  - In wcspih():
+
+    1) Fixed handling of string-valued keywords where the inline comment
+       contains a single-quote character (').
+
+    2) Fixed the address arithmetic for EPOCH and VELREF.
+
+    3) Translate VSOURCEa into ZSOURCEa if required.
+
+    4) Recognize SSYSSRCa.
+
+    5) Support free-format string keyvalues, as well as integer and
+       floating-point keyvalues; documented this in the prologue of
+       wcshdr.h.
+
+    6) Allow header cards without inline comments.
+
+    7) Fixed function prototyping in wcspih.l (i.e. ANSI and non-ANSI
+       forms were potentially mixed).
+
+    8) Catch an unhandled newline character on the END card that was
+       echoed to stdout.
+
+    9) In error messages, print "ERROR" (uppercase) - POSIX standard.
+
+  - Modified wcs.cards to explain and test free-format keyvalues, and
+    also augmented the inline comment on illegal WCS cards that are to
+    be rejected, and WCS-like cards to be discarded.  Added a header
+    card with no inline comment.
+
+  - Removed vsource from the wcsprm struct and added ssyssrc.
+
+  - In wcsini(), fixed a problem with memory management for wcs.pv when
+    NPVMAX is zero; likewise for wcs.ps and NPSMAX.
+
+  - In wcsprt(), don't print auxiliary coordinate system information in
+    arrays with zero address.
+
+  - In wcss2p(), status == 9 (one or more invalid world coordinates) was
+    not returned appropriately.
+
+  - Renamed twcs1.c to twcs.c, and twcs2.c to twcsmix.c.
+
+  - "Error status/code/number" is now referred to consistently as the
+    "status return value".
+
+  - Some vestiges of K&R C were removed: preprocessor definition of
+    const, and K&R function prototypes.
+
+* Fortran wrappers
+
+  - New wrapper defined in wcs_f.c: wcssub_().  New test program,
+    twcssub.f.
+
+  - Renamed twcs1.f to twcs.f, and twcs2.f to twcsmix.f.
+
+* PGSBOX
+
+  - (No substantive changes.)
+
+* Installation
+
+  - Worked over the C, FORTRAN, and PGSBOX makefiles, in particular to
+    make them all consistent.
+
+
+WCSLIB version 3.5 (2004/06/28)
+-------------------------------
+
+* C library
+
+  - WCSLIB now provides a function, wcspih() implemented as a Flex
+    description, that parses a FITS image header, either that of a
+    primary HDU or an image extension.  Given a character array
+    containing the header it identifies and reads all WCS cards for
+    the primary coordinate description and up to 26 alternate
+    descriptions and returns this information as an array of wcsprm
+    structs.  A service routine, wcsvfree(), is provided to free the
+    memory allocated by wcspih().  The relevant header file for these
+    functions is wcshdr.h.
+
+    Test programs, tpih1 and tpih2, are provided to verify wcspih.  The
+    first simply prints the contents of the structs using wcsprt().  The
+    second uses cpgsbox() to draw coordinate graticules.  A FITS WCS
+    test header has been developed to provide input to these test
+    programs.  It is implemented as a list of card images, wcs.cards,
+    one card per line, together with a program, tofits, that compiles
+    these into a valid FITS file.  tpih1 uses its own code to read this,
+    whereas tpih2 uses the fits_hdr2str() function from CFITSIO.
+
+  - Removed twcsprt, tpih exercises wcsprt() much more thoroughly than
+    twcsprt ever did.  Modified twcs1 to print the size of the various
+    structs as twcsprt used to.
+
+  - Although they are not used in any coordinate calculations, the
+    wcsprm struct now provides data members for storing all of the
+    auxiliary FITS WCS header cards defined in Papers I, II, and III,
+    such as WCSNAMEa, EQUINOXa, and CNAMEia.  Members are also provided
+    for storing the alternate descriptor code (the "a" in CTYPEia), and
+    the binary table column number.  These are supported by the high
+    level WCSLIB routines, wcsini(), wcscopy(), wcsfree(), and wcsprt().
+    Refer to wcs.h for details.
+
+  - The number of PVi_ma cards for which wcsini() allocates memory is
+    now set by a global variable, NPVMAX (previously a C-preprocessor
+    macro).  This defaults to 64 but may be changed by a new function,
+    wcsnpv().  The wcsprm struct contains a new member, npvmax, that
+    records the value of this number at the time the struct was
+    initialized.  This is in addition to npv which records the actual
+    number of cards that were encountered.
+
+    Similarly, NPSMAX (default 8) is used for the number of PSi_ma
+    cards, and it may be changed via wcsnps().
+
+    The axis number, i, in the pvcard struct used for storing PVi_ma
+    cards may now be set to 0 to indicate the latitude axis.
+
+  - calloc() is now used in place of malloc() in allocating memory for
+    arrays, and inclusion of malloc.h has been replaced with stdlib.h
+    for all platforms.
+
+    wcsfree() checks that wcs.flag != -1 before testing wcs.m_flag when
+    freeing memory allocated by wcsini() in case the struct is
+    uninitialized.  Similarly for linfree().
+
+  - In prj.h, renamed C-preprocessor macros INI, PRT, SET, X2S and S2X
+    to PRJINI, PRJPRT, PRJSET, PRJX2S and PRJS2X to reduce the
+    likelihood of namespace clashes.  Similarly in spc.h.
+
+    Also, in prj.c, changed the name of helper routine offset() to
+    prjoff() to reduce the likelihood of global namespace conflicts.
+
+  - In line with bonx2s() and bons2x(), bonset() now recognizes the
+    equatorial case of Bonne's projection as Sanson-Flamsteed, mainly so
+    that the auxiliary information in the prjprm struct more accurately
+    reflects the truth.  Modified tcel2 to exercise this by using an
+    equatorial Bonne projection in place of the Hammer-Aitov.
+
+  - zpns2x() used prj.w[0] for bounds checking, though this had not been
+    set by zpnset() for polynomials of degree N < 3.  Consequently,
+    bounds checking for N < 3 was unreliable (reported by David Berry,
+    STARLINK).
+
+  - Changed some variable names in tscs2x(), cscx2s(), cscs2x(),
+    qscx2s(), and qscs2x() to match Paper II, and likewise changed some
+    inequality tests in qscs2x() without changing the results.
+
+  - Minor tidying up of output formatting in prjprt().
+
+  - Added the alternate version code to FITS WCS keywords mentioned in
+    comments, e.g. CTYPEi changed to CTYPEia.
+
+* Fortran wrappers
+
+  - New wrappers defined in wcshdr_f.c: wcspih_() and wcsvfree_(), and
+    also a new service function, wcsvcopy_().
+
+    New test programs, TPIH1 and TPIH2, being analogues of tpih1 and
+    tpih2.  Removed TWCSPRT.
+
+  - In wcs_f.c, new wrappers wcsnpv_() and wcsnps_(); modified wcsput_()
+    and wcsget_() to handle new members of the wcsprm struct.  Also
+    modified wcsput_() to null-fill all char[] members of the wcsprm
+    struct, and likewise wcsget_() to blank-fill them.
+
+  - Modified wcs.inc to support changes to the wcsprm struct.
+
+* PGSBOX
+
+  - In PGSBOX, increased the dimension of the WORLD and XY vectors from
+    2 to 9 to accomodate higher-dimensional coordinate representations
+    of up to 9 elements.  Similarly for pgwcsl().  The assumption
+    (presently) is that the first two world, and pixel, coordinate
+    elements are the relevant ones; the others are all set to zero when
+    pgwcsl() initializes and otherwise ignored.
+
+    Assigned some variables in DATA to stop compiler messages about
+    uninitialized variables.
+
+  - Generalized the Makefile, bringing it into line with the WCSLIB
+    Makefile, and adding separate targets for compiling and running the
+    test programs.  The default target now simply compiles pgsbox.c and
+    cpgsbox.c.  A separate target compiles pgwcsl.c and inserts it into
+    ../C/libwcs.a.
+
+
+WCSLIB version 3.4 (2004/02/11)
+-------------------------------
+
+* C library
+
+  - In aitx2s(), apply the boundary condition 0.5 <= Z^2 <= 1 given
+    after Eq. (109) in WCS Paper II to detect outlying pixels.
+
+  - Fixed several special-case bugs in celset():
+
+    1) For theta_0 = 90, in substituting the default value for phi_p
+       (LONPOLE),
+
+       a) for the special case when delta_0 = 90, celset() provided the
+          wrong value (180 instead of 0),
+
+       b) celset() neglected to add phi_0 (normally 0).
+
+    2) For theta_0 != 90,
+
+       a) for the special case when delta_0 = -90, celset() incorrectly
+          computed delta_p (as theta_0 instead of -theta_0),
+
+       b) for the special case when delta_p = +90 (or -90), celset()
+          neglected to subtract (or add) phi_0 (normally 0).
+
+    3) For |delta_0| = 90, celset() incorrectly allowed the particular,
+       invalid, value of phi_p (LONPOLE) that put the other pole at the
+       fiducial point.
+
+    4) For theta_0 = 0, delta_0 = 0 LATPOLE determines delta_p
+       completely.  For LATPOLE > 90 celset() now sets delta_p to 90,
+       and for LATPOLE < -90 it sets it to -90.
+
+  - Additional refinements in celset():
+
+    1) cel->ref[2] is normalized in the range [-180,180].
+
+    2) Account for rounding error in the computation of delta_p.
+
+  - sphx2s() and sphs2x() incorrectly handled the "change in the origin
+    of longitude" special case that arises when delta_p = -90, in the
+    even more restrictive case where |theta| = 90 also; it applied
+    Eq. (3) instead of Eq. (4) of Paper II.
+
+  - Added a new test program, tcel2.c, to exercise celset() more
+    thoroughly.  Renamed the original tcel.c to tcel1.c and modified the
+    Makefile to suit.
+
+* Fortran wrappers
+
+  - (No changes.)
+
+* PGSBOX
+
+  - (No substantive changes.)
+
+
+WCSLIB version 3.3 (2003/10/21)
+-------------------------------
+
+* C library
+
+  - In celset(), the default value for phi_p (LONPOLE) is
+
+       phi_p = phi_0 + ((delta_0 < theta_0) ?  180.0 : 0.0)
+
+    Previously phi_0 (which is normally zero) was not added (reported by
+    David Berry, STARLINK).
+
+  - wcsprt() and linprt() now check that the structs have been
+    initialized.
+
+  - In wcsini(), when the wcsprm flag is -1 also set the linprm flag to
+    -1 to force initialization of the memory managed by linset().
+
+  - wcsset() now explicitly initializes the celprm and spcprm structs
+    via celini() and spcini().
+
+  - Fixed syntax errors in the macro definitions of linrev_errmsg and
+    linfwd_errmsg.
+
+  - In Makefile, added the -ansi option to gcc to force it to behave
+    like a strict ANSI C compiler, specifically in setting the __STDC__
+    preprocessor macro.
+
+* Fortran wrappers
+
+  - (No changes.)
+
+* PGSBOX
+
+  - PGSBOX now recognizes status returns -1, -2, and -3 from NLFUNC for
+    opcodes +2 and +1 which cause it to accept the returned (x,y)
+    coordinates but not consider them as one end of a crossing segment
+    for labelling world coordinate 1, 2, or both.
+
+  - PGSBOX now takes care not to lose vertical tick marks (and hence
+    labels) at the left or right edge of the frame.  Likewise for
+    horizontal tick marks at the top or bottom edge of the frame.
+
+  - Tightened up the test in PGSBOX for cycles in angle to catch the
+    case where the coordinate value spans a full 360 degrees.
+
+  - PGSBOX will no longer accept frame crossings that are too oblique;
+    floating point rounding errors may cause grid lines that should
+    otherwise track along the frame to weave down it from side-to-side
+    resulting in spurious crossing points.
+
+  - Fixed a bug in pgwcsl_() for processing simple linear coordinates.
+
+  - pgwcsl_() now returns error -2 if the latitude is outside -90 to +90
+    for opcodes +2 and +1.
+
+  - Amended the translation of status return codes from WCSLIB in
+    pgwcsl_().
+
+  - Provided a header file for pgwcsl_() (mainly for C++ usage).
+
+  - Added extra test plots to PGTEST and cpgtest.
+
+  - Added extra functionality to the Makefile.
+
+
+WCSLIB version 3.2 (2003/09/09)
+-------------------------------
+
+* C library
+
+  - Added the facility of setting the flag member of a wcsprm struct to
+    -1 before calling wcsini() for the first time in order to initialize
+    memory management.  Likewise for linprm and linini().
+
+  - Renamed wcscpy() to wcscopy() to avoid a conflict with the Posix
+    "wide character string" function of the same name (wchar.h).  In
+    particular, this is used by the GNU C++ string class.
+
+  - The higher level functions (wcs, cel, spc) no longer return
+    prematurely if some of the input coordinate values are invalid.
+
+  - All functions now test whether a null pointer for the particular
+    struct (wcsprm, celprm, etc.) has been passed to them.
+
+  - Function return codes have been rationalized into a consistent set
+    within each of the wcs, cel, lin, prj, spc, and spx suites of
+    functions.  Error messages to match these error codes are now
+    encoded in a single character array, e.g. wcs_errmsg and prj_errmsg,
+    instead of a separate array for each function.  Macro definitions
+    for the older character arrays (e.g. wcsini_errmsg) have been
+    provided for backward compatibility.
+
+  - Declared prj_stat as extern in prj.h.
+
+* Fortran wrappers
+
+  - (No changes.)
+
+* PGSBOX
+
+  - Added an ENTRY point, PGLBOX, that provides a simplified interface
+    to PGSBOX for linear axes without having to specify an NLFUNC or the
+    associated parameters.
+
+
+WCSLIB version 3.1 (2003/04/29)
+-------------------------------
+
+* C library
+
+  - Added "global" and "divergent" prjprm struct informational members
+    to record whether the projection is capable of mapping the whole
+    sphere, and whether it is divergent in latitude.
+
+  - Function cylfix() provided to fix WCS FITS header cards for
+    malformed cylindrical projections (c.f. Paper II, Sect. 7.3.4).
+
+  - Added support for CUNITi cards to wcsprm (but not currently
+    implemented).
+
+  - Added macro implementations of the trigd functions to wcstrig.h,
+    enabled if WCSTRIG_MACRO is defined.
+
+  - Improved printing of the WCSLIB structs.
+
+  - Added macro definitions for the lengths of the WCSLIB structs
+    measured in sizeof(int) units (mainly for the FORTRAN wrappers).
+
+* Fortran wrappers
+
+  - FORTRAN is now supported via a set of wrappers on the C library.
+    Refer to the README file.
+
+* PGSBOX
+
+
+
+WCSLIB version 3.0 beta release (2003/04/01)
+--------------------------------------------
+
+* C library
+
+  - Fully vectorized function interfaces (C preprocessor macros are
+    available to implement the scalar interfaces of the proj.c, sph.c,
+    and lin.c routines from WCSLIB 2.x).
+
+  - Implementation of Paper II, Sect. 2.5: User-specified
+    (phi0, theta0).
+
+  - Implementation of Paper III (excluding "-TAB").
+
+  - Memory management is now implemented in the upper-level (wcs.c)
+    routines.
+
+  - New extensible design should accomodate Paper IV (and any other)
+    without further change to the function interfaces.
+
+* PGSBOX
+
+  - Added a C wrapper function, cpgsbox(), and C test/demo program,
+    cpgtest, that duplicates PGTEST and serves as a C coding template.
+
+  - Added calendar date axes.
+
+  - Sped up the max/min search - if only tickmarks are required there is
+    no need to search the interior of the image.
+
+  - Return margin widths in CACHE(,NC).
+
+  - Fixed a buglet that caused ticks at the frame edges to be skipped.
+
+  - Return error 3 if CACHE overflows.
+
+  - Adapted PGWCSL for WCSLIB 3.x - it is now a C function (for
+    interfacing to WCSLIB) with a FORTRAN-like interface (for PGSBOX).
+
+
+WCSLIB version 2.9 (2002/04/03)
+-------------------------------
+
+* C library
+
+  - Fixed a bug with alias translation in wcsset().
+
+  - Added a conditional compilation directive to lin.c for Apple's
+    MacOS X.
+
+* Fortran library
+
+  - Fixed CUBEFACE handling in WCSSET.
+
+
+WCSLIB version 2.8 (2001/11/16)
+-------------------------------
+
+* C library
+
+  - Added support for the SZP projection with szpset(), szpfwd() and
+    szprev(), and generalized AZP with support for the tilt parameter,
+    gamma.
+
+  - Added phi0 to the prjprm struct, this is set by the projection
+    initialization routines along with theta0.
+
+  - Fixed a problem in wcsmix() caused by numerical imprecision that
+    could cause it not to recognize when convergence was reached; break
+    out of the loop early if a discontinuity is detected.
+
+  - Clarified the usage of vspan in the prologue to wcsmix().
+
+  - Fixed comments relating to LATPOLE in the prologue to cel.c and
+    tcel.c, and replaced references to LONGPOLE with LONPOLE.
+
+  - Augmented the error reports in twcs2.
+
+  - Modified projex() in tproj1 and prjplt() in tproj2 to make use of
+    the information stored in the prjprm struct.
+
+* Fortran library
+
+  - Added support for the SZP projection with SZPSET, SZPFWD and SZPREV,
+    and generalized AZP with support for the tilt parameter, gamma.
+
+  - Changed the call sequence to PRJSET to return PHI0 along with
+    THETA0.
+
+  - Fixed a problem in WCSMIX caused by numerical imprecision that could
+    cause it not to recognize when convergence was reached; break out of
+    the loop early if a discontinuity is detected.
+
+  - Clarified the usage of VSPAN in the prologue to WCSMIX.
+
+  - Fixed comments relating to LATPOLE in the prologue to CEL and TCEL,
+    and replaced references to LONGPOLE with LONPOLE.
+
+  - Augmented the error reports in TWCS2.
+
+  - Modified PROJEX in TPROJ1 and PRJPLT in TPROJ2 to use the generic
+    driver routines PRJSET, PRJFWD and PRJREV.  PRJPLT also now uses the
+    projection type encoded in PRJ(11).
+
+
+WCSLIB version 2.7 (2001/02/19)
+-------------------------------
+
+* C library
+
+  - Added generic driver routines prjset(), prjfwd() and prjrev().
+    These invoke specific projection routines via the pointer-to-
+    function elements, prjfwd and prjrev, transferred to the prjprm
+    struct from celprm.
+
+  - Added code (3-letter projection code) and theta0 (reference
+    latitude) elements to prjprm.
+
+  - The projection code for the Sanson-Flamsteed projection is now SFL.
+    The upper-level routines, wcsset(), wcsfwd(), and wcsrev(),
+    recognize GLS as an alias for this.
+
+  - wcsset() now recognizes 'xyLN/xyLT' axis pairs.
+
+  - Two bugs in the translation from NCP to SIN in wcsfwd() and wcsrev()
+    were fixed: (1) the projection parameter was computed incorrectly
+    and (2) they did not honour prj->flag set to -1 to disable strict
+    bounds checking.
+
+  - A bug in wcsmix() was fixed - it was relying on the wcsprm struct to
+    have been initialized beforehand.
+
+  - The test programs now use the cpgplot interface to PGPLOT, the old
+    tpgc.c and tpgf.f wrappers have been removed.
+
+* Fortran library
+
+  - Added generic driver routines PRJSET, PRJFWD and PRJREV.  These are
+    keyed to specific projection routines via the value of PRJ(11) which
+    now differs for each projection.
+
+  - The projection code for the Sanson-Flamsteed projection is now SFL.
+    The upper-level routines, WCSSET, WCSFWD, and WCSREV, recognize GLS
+    as an alias for this.
+
+  - WCSSET now recognizes 'xyLN/xyLT' axis pairs.
+
+  - A bug in the translation from NCP to SIN in WCSFWD and WCSREV was
+    fixed; they did not honour PRJ(11) set to -1 to disable strict
+    bounds checking.
+
+  - A bug in WCSMIX was fixed - it was relying on the WCS array to have
+    been initialized beforehand.
+
+
+WCSLIB version 2.6 (2000/05/10)
+-------------------------------
+
+* C library
+
+  - Check for invalid (x,y) in zearev().
+
+  - In wcsmath.h, guard against prior definition of PI and other
+    preprocessor variables.
+
+* Fortran library
+
+  - Check for invalid (X,Y) in ZEAREV.
+
+  - Declare COSD and SIND in WCSFWD and WCSREV, reported by Clive Page
+    (cgp at star.le.ac.uk).
+
+
+WCSLIB version 2.5 (1999/12/14)
+-------------------------------
+
+* C library
+
+  - Added copyright notice to header files and prefixed include guard
+    names with "WCSLIB_".
+
+  - Fixed cube face handling in wcsfwd() and wcsrev() (reported by
+    Doug Mink, CfA).  Allow more general face layout in the inverse
+    quadcube projections.
+
+  - Fixed the problem in wcsmix() where it failed to find a valid
+    solution when the solution point lay at a native pole of a
+    projection in which the pole is represented as a finite interval.
+    However, wcsmix() will only ever return one solution even when two
+    or more valid solutions may exist.
+
+  - wcsmix() now accepts viter in the range 5 - 10, the specified value
+    will be pushed up or down into this range if necessary.
+
+  - The projection routines for AZP, TAN, SIN, ZPN, and COP now return
+    error 2 if (phi,theta) correspond to the overlapped (far) side of
+    the projection.  This strict bounds checking can be switched off by
+    setting prj->flag to -1 (rather than 0) when the projections are
+    initialized.
+
+  - The upper level routines, wcsset(), wcsfwd(), wcsrev(), and
+    wcsmix(), now recognize the NCP projection and convert it to the
+    equivalent SIN projection.  The lower level routines do not
+    recognize NCP.
+
+  - Extracted definitions of mathematical constants (PI etc.) from
+    proj.h into wcsmath.h in order to avoid conflicts with their
+    definition in math.h in some systems (such as Linux).
+
+  - Describe the two alternate representations of the quadcube
+    projections (i.e. faces laid out or stacked) in the prologue of
+    wcs.c.
+
+* Fortran library
+
+  - Fixed cube face handling in WCSFWD and WCSREV, reported by Doug Mink
+    (dmink at cfa.harvard.edu).  Allow more general face layout in the
+    inverse quadcube projections.
+
+  - Fixed the problem in WCSMIX where it failed to find a valid solution
+    when the solution point lay at a native pole of a projection in
+    which the pole is represented as a finite interval.  However, WCSMIX
+    will only ever return one solution even when two or more valid
+    solutions may exist.
+
+  - WCSMIX now accepts VITER in the range 5 - 10, the specified value
+    will be pushed up or down into this range if necessary.
+
+  - The projection routines for AZP, TAN, SIN, ZPN, and COP now return
+    error 2 if (phi,theta) correspond to the overlapped (far) side of
+    the projection.  This strict bounds checking can be switched off by
+    setting PRJ(11) to -1 (rather than 0) when the projections are
+    initialized.
+
+  - The upper level routines, WCSSET, WCSFWD, WCSREV, and WCSMIX, now
+    recognize the NCP projection and convert it to the equivalent SIN
+    projection.  The lower level routines do not recognize NCP.
+
+  - Describe the two alternate representations of the quadcube
+    projections (i.e. faces laid out or stacked) in the prologue of
+    wcs.f.
+
+
+WCSLIB version 2.4 (1996/09/23)
+-------------------------------
+
+* C library
+
+  - In sinrev(), cscrev(), qscrev(), and tscrev(), return error 2 if
+    (x,y) do not lie within the perimeter of the projection.  In
+    sinrev(), stop the computation of phi for the "synthesis" projection
+    being applied to the pure "orthographic" case (reported by
+    David Berry, STARLINK).
+
+  - (Internal change) Renamed variables l <-> m in the quadcube
+    projections to accord with standard usage (and revised WCS draft
+    paper).
+
+* Fortran library
+
+  - In SINREV, CSCREV, QSCREV, and TSCREV, return error 2 if (X,Y) do
+    not lie within the perimeter of the projection.  In SINREV, stop the
+    computation of PHI for the "synthesis" projection being applied to
+    the pure "orthographic" case.  Reported by David Berry
+    (dsb at ast.man.ac.uk).
+
+  - (Internal change) Renamed variables L <-> M in the quadcube
+    projections to accord with standard usage (and revised WCS draft
+    paper).
+
+  - (Internal change) Stopped PRJ(11) doing double service in any
+    projection.  It is now set and tested for a specific magic value
+    rather than simply being non-zero.
+
+
+WCSLIB version 2.3 (1996/06/24)
+-------------------------------
+
+* C library
+
+  - Fixed two bugs in zpnset().  The first led to an incorrect
+    determination of the degree of the polynomial and would mainly have
+    affected the efficiency of zpnrev().  The second affected the
+    determination of the boundary of the projection but would only have
+    been significant for projections with a point of inflection between
+    9 and 10 degrees of the pole.  Reported by David Berry, STARLINK.
+
+  - Replaced usage of alloca() in lin.c with malloc() and free() for
+    portability as suggested by Klaus Banse, ESO (kbanse at eso.org).
+
+  - Allow for C implementations that provide their own versions of
+    cosd(), sind(), tand(), acosd(), asind(), atand(), and atan2d().
+    From Klaus Banse, ESO (kbanse at eso.org).
+
+  - Implemented the CUBEFACE axis for quadcube projections.
+
+  - Made all function prototypes const-correct.
+
+  - Adapted the header files to C++ usage.
+
+  - Added a new test program, twcs1, to verify closure of wcsfwd() and
+    wcsrev().  The old twcs test program is now called twcs2.
+
+  - Added external arrays of error messages indexed by function return
+    value.  For example, extern const char *wcsmix_errmsg[] for
+    wcsmix().  Messages for the many proj.c functions are in
+    prjfwd_errmsg[], etc.
+
+* Fortran library
+
+  - Implemented the CUBEFACE axis for quadcube projections.
+
+  - Added a new test program, TWCS1, to verify closure of WCSFWD and
+    WCSREV.  The old TWCS test program is now called TWCS2.
+
+
+WCSLIB version 2.2 (1996/01/18)
+-------------------------------
+
+* C library
+
+  - Amended the projection equations for the conics (COP, COD, COE, COO)
+    and Bonne's projection (BON) to correctly handle southern hemisphere
+    projections with PROJP1 < 0 (reported by Lindsay Davis, NOAO).
+    Revised tproj1 and tproj2 to test such cases.
+
+* Fortran library
+
+  - Amended the projection equations for the conics (COP, COD, COE, COO)
+    and Bonne's projection (BON) to correctly handle southern hemisphere
+    projections with PROJP1 < 0 (reported by Lindsay Davis, NOAO).
+    Revised TPROJ1 and TPROJ2 to test such cases.
+
+  - Increased the dimension of the WCS array from WCS(0:2) to WCS(0:3)
+    to allow for future handling of the CUBEFACE keyword - WCS(3) will
+    store an index to the CUBEFACE axis.  This affects the call
+    sequences of WCSSET, WCSFWD, WCSREV, and WCSMIX.
+
+
+WCSLIB version 2.1 (1995/11/17)
+-------------------------------
+
+* C library
+
+  The main change of interest to programmers is that of changed argument
+  lists for wcsfwd() and wcsrev() as described below.
+
+  - The WCS linear transformations are now implemented in WCSLIB,
+    complete with matrix inverter.  The new files are lin.c, lin.h, and
+    test program tlin.c.
+
+  - Given either the celestial longitude or latitude plus an element of
+    the pixel coordinate a new routine, wcsmix(), solves for the
+    remaining elements by iterating on the unknown celestial coordinate
+    element using wcsfwd().
+
+  - The high level driver routines wcsfwd(), wcsrev(), and wcsmix() now
+    apply the full WCS algorithm chain (except for pixel regularization
+    table), including parsing the CTYPEn header cards and computing non-
+    celestial elements of the world coordinate.  This required a change
+    to their argument lists which now more closely reflect the sequence
+    of algorithms applied.  A new routine, wcsset(), parses the CTYPEn.
+
+  - The high level driver routines of WCSLIB 1.0 are available as
+    intermediate level drivers celset(), celfwd(), and celrev(), but
+    note that their argument lists have been extended to return native
+    coordinates.  The related struct is now called celprm instead of
+    wcsprm.
+
+  - The reference point for conic projections is now at the midpoint of
+    the standard parallels.  The FITS header cards PROJP1 and PROJP2 now
+    give the half-sum (midpoint) and half-difference of the latitudes of
+    the standard parallels; previously they gave the latitudes of the
+    standard parallels themselves.  The change is reflected in this
+    release of WCSLIB.
+
+  - A bug in celset() (formerly wcsset()) that misapplied WCS draft
+    equations 7 has been fixed (thanks to Rick Ebert IPAC/JPL and
+    Lindsey Davis, NOAO for reporting this).  This affected the
+    computation of Euler angles for the celestial coordinate
+    transformation for those projections that have their reference point
+    away from the native pole.  In investigating this a deficiency with
+    the formalism was discovered that led to the introduction of a
+    LATPOLE FITS header card which may be used to disambiguate where
+    CRVAL1, CRVAL2, and LONGPOLE do not uniquely determine the latitude
+    of the native pole.  The celprm struct (formerly wcsprm) has been
+    extended to accomodate LATPOLE.
+
+  - Default values of LONGPOLE and LATPOLE are now supported and their
+    use is recommended where appropriate.
+
+  - Numerical precision was being lost near the native poles in the SIN,
+    AIR, and QSC projections and this has been recovered (reported by
+    Lindsey Davis, NOAO).  Floating underflows in CSC are now avoided.
+
+  - Numerical precision was also lost in certain circumstances in the
+    spherical coordinate transformation routines and this has been
+    fixed.
+
+  - The test programs have been enhanced in various ways and the library
+    has been validated on an SGI machine using both 32-bit and 64-bit
+    compilers.
+
+* Fortran library
+
+  The main change of interest to programmers is that of changed call
+  sequences for WCSFWD and WCSREV as described below.
+
+  - The WCS linear transformations are now implemented in WCSLIB,
+    complete with matrix inverter.  The new files are lin.f and test
+    program tlin.f.
+
+  - Given either the celestial longitude or latitude plus an element of
+    the pixel coordinate a new routine, WCSMIX, solves for the remaining
+    elements by iterating on the unknown celestial coordinate element
+    using WCSFWD.
+
+  - The high level driver routines WCSFWD, WCSREV, and WCSMIX now apply
+    the full WCS algorithm chain (except for pixel regularization
+    table), including parsing the CTYPEn header cards and computing non-
+    celestial elements of the world coordinate.  This required a change
+    to their call sequences which now more closely reflect the sequence
+    of algorithms applied.  A new routine, WCSSET, parses the CTYPEn.
+
+  - The high level driver routines of WCSLIB 1.0 are available as
+    intermediate level drivers CELSET, CELFWD, and CELREV, but note
+    that their call sequences have been extended to return native
+    coordinates.  The related parameter array is now called CEL instead
+    of WCS.
+
+  - The reference point for conic projections is now at the midpoint of
+    the standard parallels.  The FITS header cards PROJP1 and PROJP2 now
+    give the half-sum (midpoint) and half-difference of the latitudes of
+    the standard parallels; previously they gave the latitudes of the
+    standard parallels themselves.  The change is reflected in this
+    release of WCSLIB.
+
+  - A bug in CELSET (formerly WCSSET) that misapplied WCS draft
+    equations 7 has been fixed (thanks to Rick Ebert IPAC/JPL and
+    Lindsey Davis, NOAO for reporting this).  This affected the
+    computation of Euler angles for the celestial coordinate
+    transformation for those projections that have their reference point
+    away from the native pole.  In investigating this a deficiency with
+    the formalism was discovered that led to the introduction of a
+    LATPOLE FITS header card which may be used to disambiguate where
+    CRVAL1, CRVAL2, and LONGPOLE do not uniquely determine the latitude
+    of the native pole.  The CEL parameter array (formerly WCS) has been
+    extended to accomodate LATPOLE as CEL(4), and the flag variable is
+    now CEL(5) (formerly WCS(4)).
+
+  - Default values of LONGPOLE and LATPOLE are now supported and their
+    use is recommended where appropriate.
+
+  - Numerical precision was being lost near the native poles in the SIN,
+    AIR, and QSC projections and this has been recovered (reported by
+    Lindsey Davis, NOAO).  Floating underflows in CSC are now avoided.
+
+  - Numerical precision was also lost in certain circumstances in the
+    spherical coordinate transformation routines and this has been
+    fixed.
+
+  - The test programs have been enhanced in various ways and the
+    library has been validated on an SGI machine using both 32-bit and
+    64-bit compilers.
+
+
+WCSLIB version 1.0 (1995/01/31)
+-------------------------------
+
+* C library
+
+  Initial release.
+
+* Fortran library
+
+  Initial release.
+
+------------------------------------------------------------------------
+$Id: CHANGES,v 4.16 2012/11/07 04:42:45 cal103 Exp $
diff --git a/astropy/wcs/src/wcslib/COPYING b/cextern/wcslib/COPYING
similarity index 100%
rename from astropy/wcs/src/wcslib/COPYING
rename to cextern/wcslib/COPYING
diff --git a/astropy/wcs/src/wcslib/COPYING.LESSER b/cextern/wcslib/COPYING.LESSER
similarity index 100%
rename from astropy/wcs/src/wcslib/COPYING.LESSER
rename to cextern/wcslib/COPYING.LESSER
diff --git a/cextern/wcslib/GNUmakefile b/cextern/wcslib/GNUmakefile
new file mode 100644
index 0000000..a82e18b
--- /dev/null
+++ b/cextern/wcslib/GNUmakefile
@@ -0,0 +1,204 @@
+#-----------------------------------------------------------------------------
+# GNU makefile for building WCSLIB 4.16
+#
+# Summary of the main targets
+# ---------------------------
+#   all:       Do 'make all' in each subdirectory (excluding ./doxygen).
+#   check:     Do 'make check' in each subdirectory (compile and run tests).
+#   tests:     Do 'make tests' in each subdirectory (compile test programs but
+#              don't run them).
+#   install:   Do 'make install' in each subdirectory.
+#   clean:     Recursively delete intermediate files produced as part of the
+#              build, e.g. object modules, core dumps, etc.
+#   cleaner:   Recursively clean, and also delete test executables, test
+#              input and output, and intermediates produced in compiling the
+#              programmers' manual.
+#   distclean (or realclean): Recursively delete all platform-dependent files
+#              generated during the build, preserving only the programmers'
+#              manual and man pages (which are normally provided pre-built).
+#              It is the one to use between builds for multiple platforms.
+#   cleanest:  Like distclean, but deletes everything that can be regenerated
+#              from the source files, including the programmers' manual and
+#              man pages, but excluding 'configure'.
+#   show:      Print the values of important variables used in this and the
+#              other makefiles.
+#   writable:  Run chmod recursively to make all sources writable.
+#
+# Notes:
+#   1) If you need to make changes then preferably modify makedefs.in instead.
+#
+#   2) Refer also to the makefiles in subdirectories, particularly
+#      C/GNUmakefile.
+#
+# Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
+# http://www.atnf.csiro.au/people/Mark.Calabretta
+# $Id: GNUmakefile,v 4.16 2012/11/07 04:42:45 cal103 Exp $
+#-----------------------------------------------------------------------------
+# Get configure settings.
+include makedefs
+
+ifeq "$(CHECK)" "nopgplot"
+  TSTDIRS := $(filter-out pgsbox,$(TSTDIRS))
+endif
+
+.PHONY : build check chmod clean cleaner cleanest distclean install \
+         realclean show tests writable
+
+build :
+	-@ for DIR in $(SUBDIRS) ; do \
+	     echo '' ; \
+	     $(TIMER) ; \
+	     $(MAKE) -k -C $$DIR build ; \
+	   done
+
+check tests :: show
+	-@ echo ''
+	-@ $(TIMER)
+	 @ for DIR in $(SUBDIRS) ; do \
+	     echo '' ; \
+	     $(MAKE) -i -C $$DIR cleaner ; \
+	   done
+	-@ echo ''
+	 @ for DIR in $(TSTDIRS) ; do \
+	     echo '' ; \
+	     $(TIMER) ; \
+	     $(MAKE) -k -C $$DIR $@ ; \
+	   done
+
+check ::
+	-@ echo ''
+	-@ echo 'Summary of results for non-graphical tests'
+	-@ echo '------------------------------------------'
+	-@ cat ./*/test_results
+	 @ if grep 'FAIL:' ./*/test_results > /dev/null ; then \
+	     exit 1 ; \
+	   else \
+	     exit 0 ; \
+	   fi
+
+install :
+	 @ for DIR in $(INSTDIR) ; do \
+	     $(MAKE) -k -C $$DIR $@ ; \
+	   done
+	   $(INSTALL) -m 444 wcsconfig.h wcsconfig_f77.h $(INCDIR)
+	-  if [ ! -d "$(DOCDIR)" ] ; then \
+	     $(INSTALL) -d -m 2775 $(DOCDIR) ; \
+	   fi
+	   $(INSTALL) -m 444 CHANGES COPYING* README $(DOCDIR)
+	-  if [ -h $(DOCLINK) ] ; then \
+	     $(RM) $(DOCLINK) ; \
+	     $(LN_S) $(notdir $(DOCDIR)) $(DOCLINK) ; \
+	   fi
+	-  if [ ! -d "$(PDFDIR)" ] ; then \
+	     $(INSTALL) -d -m 2775 $(PDFDIR) ; \
+	   fi
+	   $(INSTALL) -m 444 wcslib.pdf $(PDFDIR)
+	-  if [ ! -d "$(HTMLDIR)/html" ] ; then \
+	     $(INSTALL) -d -m 2775 $(HTMLDIR)/html ; \
+	   fi
+	   $(INSTALL) -m 444 html/* $(HTMLDIR)/html
+	   if [ ! -d "$(LIBDIR)/pkgconfig" ] ; then \
+	     $(INSTALL) -d -m 2775 $(LIBDIR)/pkgconfig ; \
+	   fi
+	   $(INSTALL) -m 444 wcslib.pc $(LIBDIR)/pkgconfig/wcslib.pc
+
+clean cleaner :
+	   for DIR in $(SUBDIRS) doxygen ; do \
+	     $(MAKE) -C $$DIR $@ ; \
+	   done
+
+cleanest distclean realclean :
+	   for DIR in $(SUBDIRS) doxygen ; do \
+	     $(MAKE) -C $$DIR $@ ; \
+	   done
+	-  $(RM) *.log
+	-  $(RM) -r autom4te.cache autoscan.log
+	-  $(RM) confdefs.h conftest.*
+	-  $(RM) config.log config.status configure.lineno
+	-  $(RM) makedefs wcslib.pc
+	-  $(RM) wcsconfig.h wcsconfig_*.h
+	-  $(RM) wcslib-*.tar.gz
+
+show ::
+	-@ echo 'Subdirectories to be built...'
+	-@ echo '  SUBDIRS     := $(SUBDIRS)'
+	-@ echo '  TSTDIRS     := $(TSTDIRS)'
+	-@ echo ''
+
+writable :
+	  chmod -R u+w .
+
+GNUmakefile : makedefs ;
+
+makedefs : makedefs.in config.status
+	-@ echo ''
+	-@ $(TIMER)
+	   ./config.status
+
+config.status : configure
+	-@ echo ''
+	-@ $(TIMER)
+	-@ echo ''
+	-@ echo "Environment variables that affect 'configure':"
+	-@ echo "  CC       = $${CC-(undefined)}"
+	-@ echo "  CFLAGS   = $${CFLAGS-(undefined)}"
+	-@ echo "  CPP      = $${CPP-(undefined)}"
+	-@ echo "  CPPFLAGS = $${CPPFLAGS-(undefined)}"
+	-@ echo "  F77      = $${F77-(undefined)}"
+	-@ echo "  FFLAGS   = $${FFLAGS-(undefined)}"
+	-@ echo "  LDFLAGS  = $${LDFLAGS-(undefined)}"
+	-@ echo ''
+	   ./configure --no-create
+
+
+#-----------------------------------------------------------------------------
+# These are for code management.
+
+.PHONY : dist
+
+dist :
+	   $(MAKE) -C doxygen cleanest build
+	   $(MAKE) -C utils man
+	   $(MAKE) distclean
+	-@ echo $(WCSLIBPKG)/C/RCS        >  wcslib.X
+	-@ echo $(WCSLIBPKG)/C/flexed/RCS >> wcslib.X
+	-@ echo $(WCSLIBPKG)/C/test/RCS   >> wcslib.X
+	-@ echo $(WCSLIBPKG)/doxygen/RCS  >> wcslib.X
+	-@ echo $(WCSLIBPKG)/Fortran/RCS  >> wcslib.X
+	-@ echo $(WCSLIBPKG)/Fortran/test/RCS >> wcslib.X
+	-@ echo $(WCSLIBPKG)/makedefs     >> wcslib.X
+	-@ echo $(WCSLIBPKG)/other        >> wcslib.X
+	-@ echo $(WCSLIBPKG)/pgsbox/RCS   >> wcslib.X
+	-@ echo $(WCSLIBPKG)/RCS          >> wcslib.X
+	-@ echo $(WCSLIBPKG)/TODO         >> wcslib.X
+	-@ echo $(WCSLIBPKG)/utils/RCS    >> wcslib.X
+	-@ echo $(WCSLIBPKG)/wcslib.T     >> wcslib.X
+	-@ echo $(WCSLIBPKG)/wcslib.X     >> wcslib.X
+	   rm -f $(WCSLIBPKG).tar.bz2
+	   tar cf - -C .. -X wcslib.X $(WCSLIBPKG) | \
+	     tar t | \
+	     grep -v '/$$' | \
+	     sort > wcslib.T
+	   rm -f wcslib.X
+	   tar cvf $(WCSLIBPKG).tar -C .. -T wcslib.T
+	   rm -f wcslib.T
+	   bzip2 $(WCSLIBPKG).tar
+	   chmod 444 $(WCSLIBPKG).tar.bz2
+
+install_dist :
+	   scp -p $(WCSLIBPKG).tar.bz2 venice:/nfs/ftp/software/wcslib/
+	   mv -f  $(WCSLIBPKG).tar.bz2 ../wcslib-releases/
+	   ssh venice "cd /nfs/ftp/software/wcslib/ && \
+	     rm -f wcslib.tar.bz2 && \
+	     ln -s $(WCSLIBPKG).tar.bz2 wcslib.tar.bz2"
+	   cp -fp CHANGES wcslib.pdf ~/public_html/WCS/
+	   rsync --archive --delete html/ ~/public_html/WCS/wcslib/
+
+configure : configure.ac
+	-@ echo ''
+	-@ $(TIMER)
+	   autoconf
+
+# Code development overrides must be included specifically before 'configure'
+# generates makedefs.
+-include flavours
diff --git a/cextern/wcslib/INSTALL b/cextern/wcslib/INSTALL
new file mode 100644
index 0000000..b0dac10
--- /dev/null
+++ b/cextern/wcslib/INSTALL
@@ -0,0 +1,327 @@
+------------------------------------------------------------------------------
+WCSLIB 4.16 and PGSBOX 4.16 INSTALLATION
+--------------------------------------
+
+WCSLIB requires an ANSI C compiler with standard ANSI C environment, that is,
+a standard C library and header files as defined in Appendix B of Kernigan &
+Ritchie, 2nd ed.
+
+Installation of WCSLIB is handled by GNU autoconf; GNU make (referred to here
+as 'gmake') must be used.  The WCSLIB distribution also includes PGSBOX (refer
+to the README file), to unpack it type
+
+  zcat wcslib-4.16.tar.gz | tar pvxf -
+  cd wcslib-4.16
+
+then if you do not need to specify any configuration options, simply run
+
+  gmake
+
+This will run 'configure' to generate "makedefs" which is included by the top-
+level GNUmakefile and those in each subdirectory, and then build 'libwcs.a',
+which includes both the C library and Fortran wrappers, and also libpgsbox.a.
+
+(WARNING: The build may fail with gmake 3.79, upgrade to 3.79.1 or later.)
+
+configure tries to determine the location of the PGPLOT and CFITSIO libraries
+required by some programs in the test suite.  If it fails to find them you
+can, if you wish, tailor the few variables found at the start of "makedefs".
+Of course you do not need to exercise the test suite in order to build and
+install the library - if configure fails to find anything required for that it
+will issue an explicit error message.
+
+To build and exercise the test suite use
+
+  gmake check
+
+To install the object libraries and header files, do
+
+  gmake install
+
+
+TWEAKING THE INSTALLATION DEFAULTS
+----------------------------------
+
+By default the library and header files are installed in the lib and include
+subdirectories of /usr/local/.  To change this, or any other options, run
+configure separately before gmake:
+
+  ./configure --prefix=/some/other/dir
+  gmake
+
+Use
+
+  ./configure --help
+
+to list configure's options.  Useful options are
+
+  --with-pgplotinc
+  --with-pgplotlib
+  --with-cfitsioinc
+  --with-cfitsiolib
+
+Which allow additional directories to be added to the library and include
+file search path.
+
+Installation of WCSLIB differs a little from most packages in that all
+configurable makefile variables are defined in a single file, "makedefs",
+which configure generates from "makedefs.in".  If you need to redefine any of
+the makefile variables you can modify makedefs, or preferably makedefs.in.
+The makefile will automatically detect this and re-run config.status to
+re-generate a new makedefs.  configure also creates four header files:
+
+  wcsconfig.h: Contains general purpose preprocessor definitions.  It is
+    included by the other wcsconfig header files.
+
+  wcsconfig_f77.h: By common convention the WCSLIB Fortran wrappers have
+    been written (in C) using function names in lower case with an
+    underscore ("_") suffix.  wcsconfig_f77.h defines a preprocessor macro,
+    F77_FUNC(name,NAME), that may redefine these to suit different name
+    mangling schemes used by some Fortran compilers.
+
+  wcsconfig_tests.h: Contains C preprocessor definitions for compiling the
+    test/demo programs.
+
+  wcsconfig_utils.h: Contains C preprocessor macro definitions for compiling
+    the utility programs provided with WCSLIB.
+
+If you do have trouble building the library please send me config.log.
+
+
+The INSTALL file provided with GNU autoconf 2.53 is appended without change.
+
+
+Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
+http://www.atnf.csiro.au/people/Mark.Calabretta
+$Id: INSTALL,v 4.16 2012/11/07 04:42:45 cal103 Exp $
+
+==============================================================================
+
+Copyright 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software
+Foundation, Inc.
+
+   This file is free documentation; the Free Software Foundation gives
+unlimited permission to copy, distribute and modify it.
+
+Basic Installation
+==================
+
+   These are generic installation instructions.
+
+   The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation.  It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions.  Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, and a
+file `config.log' containing compiler output (useful mainly for
+debugging `configure').
+
+   It can also use an optional file (typically called `config.cache'
+and enabled with `--cache-file=config.cache' or simply `-C') that saves
+the results of its tests to speed up reconfiguring.  (Caching is
+disabled by default to prevent problems with accidental use of stale
+cache files.)
+
+   If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release.  If you are using the cache, and at
+some point `config.cache' contains results you don't want to keep, you
+may remove or edit it.
+
+   The file `configure.ac' (or `configure.in') is used to create
+`configure' by a program called `autoconf'.  You only need
+`configure.ac' if you want to change it or regenerate `configure' using
+a newer version of `autoconf'.
+
+The simplest way to compile this package is:
+
+  1. `cd' to the directory containing the package's source code and type
+     `./configure' to configure the package for your system.  If you're
+     using `csh' on an old version of System V, you might need to type
+     `sh ./configure' instead to prevent `csh' from trying to execute
+     `configure' itself.
+
+     Running `configure' takes awhile.  While running, it prints some
+     messages telling which features it is checking for.
+
+  2. Type `make' to compile the package.
+
+  3. Optionally, type `make check' to run any self-tests that come with
+     the package.
+
+  4. Type `make install' to install the programs and any data files and
+     documentation.
+
+  5. You can remove the program binaries and object files from the
+     source code directory by typing `make clean'.  To also remove the
+     files that `configure' created (so you can compile the package for
+     a different kind of computer), type `make distclean'.  There is
+     also a `make maintainer-clean' target, but that is intended mainly
+     for the package's developers.  If you use it, you may have to get
+     all sorts of other programs in order to regenerate files that came
+     with the distribution.
+
+Compilers and Options
+=====================
+
+   Some systems require unusual options for compilation or linking that
+the `configure' script does not know about.  Run `./configure --help'
+for details on some of the pertinent environment variables.
+
+   You can give `configure' initial values for variables by setting
+them in the environment.  You can do that on the command line like this:
+
+     ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix
+
+   *Note Defining Variables::, for more details.
+
+Compiling For Multiple Architectures
+====================================
+
+   You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory.  To do this, you must use a version of `make' that
+supports the `VPATH' variable, such as GNU `make'.  `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script.  `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+   If you have to use a `make' that does not support the `VPATH'
+variable, you have to compile the package for one architecture at a
+time in the source code directory.  After you have installed the
+package for one architecture, use `make distclean' before reconfiguring
+for another architecture.
+
+Installation Names
+==================
+
+   By default, `make install' will install the package's files in
+`/usr/local/bin', `/usr/local/man', etc.  You can specify an
+installation prefix other than `/usr/local' by giving `configure' the
+option `--prefix=PATH'.
+
+   You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files.  If you
+give `configure' the option `--exec-prefix=PATH', the package will use
+PATH as the prefix for installing programs and libraries.
+Documentation and other data files will still use the regular prefix.
+
+   In addition, if you use an unusual directory layout you can give
+options like `--bindir=PATH' to specify different values for particular
+kinds of files.  Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them.
+
+   If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+   Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System).  The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+   For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+   There may be some features `configure' cannot figure out
+automatically, but needs to determine by the type of machine the package
+will run on.  Usually, assuming the package is built to be run on the
+_same_ architectures, `configure' can figure that out, but if it prints
+a message saying it cannot guess the machine type, give it the
+`--build=TYPE' option.  TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name which has the form:
+
+     CPU-COMPANY-SYSTEM
+
+where SYSTEM can have one of these forms:
+
+     OS KERNEL-OS
+
+   See the file `config.sub' for the possible values of each field.  If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the machine type.
+
+   If you are _building_ compiler tools for cross-compiling, you should
+use the `--target=TYPE' option to select the type of system they will
+produce code for.
+
+   If you want to _use_ a cross compiler, that generates code for a
+platform different from the build platform, you should specify the
+"host" platform (i.e., that on which the generated programs will
+eventually be run) with `--host=TYPE'.
+
+Sharing Defaults
+================
+
+   If you want to set default values for `configure' scripts to share,
+you can create a site shell script called `config.site' that gives
+default values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists.  Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Defining Variables
+==================
+
+   Variables not defined in a site shell script can be set in the
+environment passed to `configure'.  However, some packages may run
+configure again during the build, and the customized values of these
+variables may be lost.  In order to avoid this problem, you should set
+them in the `configure' command line, using `VAR=value'.  For example:
+
+     ./configure CC=/usr/local2/bin/gcc
+
+will cause the specified gcc to be used as the C compiler (unless it is
+overridden in the site shell script).
+
+`configure' Invocation
+======================
+
+   `configure' recognizes the following options to control how it
+operates.
+
+`--help'
+`-h'
+     Print a summary of the options to `configure', and exit.
+
+`--version'
+`-V'
+     Print the version of Autoconf used to generate the `configure'
+     script, and exit.
+
+`--cache-file=FILE'
+     Enable the cache: use and save the results of the tests in FILE,
+     traditionally `config.cache'.  FILE defaults to `/dev/null' to
+     disable caching.
+
+`--config-cache'
+`-C'
+     Alias for `--cache-file=config.cache'.
+
+`--quiet'
+`--silent'
+`-q'
+     Do not print messages saying which checks are being made.  To
+     suppress all normal output, redirect it to `/dev/null' (any error
+     messages will still be shown).
+
+`--srcdir=DIR'
+     Look for the package's source code in directory DIR.  Usually
+     `configure' can determine that directory automatically.
+
+`configure' also accepts some other, not widely useful, options.  Run
+`configure --help' for more details.
+
diff --git a/cextern/wcslib/README b/cextern/wcslib/README
new file mode 100644
index 0000000..d644c06
--- /dev/null
+++ b/cextern/wcslib/README
@@ -0,0 +1,44 @@
+------------------------------------------------------------------------------
+                         WCSLIB 4.16 and PGSBOX 4.16
+------------------------------------------------------------------------------
+  WCSLIB 4.16 - an implementation of the FITS WCS standard.
+  Copyright (C) 1995-2012, Mark Calabretta
+
+  This file is part of WCSLIB.
+
+  WCSLIB is free software: you can redistribute it and/or modify it under
+  the terms of the GNU Lesser General Public License as published by the
+  Free Software Foundation, either version 3 of the License, or (at your
+  option) any later version.
+
+  WCSLIB 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 Lesser General Public License for
+  more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with WCSLIB.  If not, see http://www.gnu.org/licenses.
+
+  Direct correspondence concerning WCSLIB to mark at calabretta.id.au
+
+  Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
+  http://www.atnf.csiro.au/people/Mark.Calabretta
+  $Id: README,v 4.16 2012/11/07 04:42:45 cal103 Exp $
+------------------------------------------------------------------------------
+
+Please refer to
+
+  ./INSTALL		...Installation instructions.
+
+  ./html/index.html	...The WCSLIB programmer's manual in HTML format.
+  ./wcslib.pdf		...The WCSLIB programmer's manual in PDF format.
+
+  ./CHANGES		...Log of changes made to WCSLIB.
+
+  ./THANKS		...List of contributors to WCSLIB.
+
+  ./VALIDATION		...List of platforms on which the installation
+			   procedures and test suite were exercised.
+
+  ./COPYING		...A copy of the GNU General Public License, v3.0.
+  ./COPYING.LESSER	...A copy of the Lesser GNU General Public License.
diff --git a/cextern/wcslib/THANKS b/cextern/wcslib/THANKS
new file mode 100644
index 0000000..a56778c
--- /dev/null
+++ b/cextern/wcslib/THANKS
@@ -0,0 +1,82 @@
+I would like to acknowledge the following people who have contributed
+to WCSLIB and/or PGSBOX in some way since 1995 - via bug reports,
+patches, suggestions for improvements, positive feedback, etc.
+
+James M. Anderson (MPIfR)
+Robbie Auld (Cardiff U.)
+Klaus Banse (ESO)
+David Barnes (ATNF/CSIRO)
+David Berry (STARLINK & JAC)
+Emmanuel Bertin (IAP)
+Jeremy Brewer (U. Pittsburgh)
+Wim Brouw (ATNF/CSIRO)
+Peter Bunclark (IoA, U. Cambridge)
+Pan Chai (GSFC/NASA)
+Charles Copley
+Neil Crighton
+Cesar Enrique Garcia Dabo (ESO)
+Lindsey Davis (NOAO)
+Ger van Diepen (ASTRON)
+Patrick Dowler (CADC/NRC)
+Michael Droettboom (STScI)
+Rick Ebert (IPAC/NASA)
+Ken Ebisawa (GSFC/NASA)
+Sébastien Fabbro (Gentoo linux maintainer)
+Bob Garwood (NRAO)
+Brian Glendenning (NRAO)
+Eric Greisen (NRAO)
+Michael Halle (AM/Harvard)
+Booth Hartley (IPAC/NASA)
+Phil Hodge (STScI)
+Bryan Irby (GSFC/NASA)
+Justin Jonas (Rhodes U.)
+Yves Jung (ESO)
+David Kaplan (KITP/UCSB)
+Daniel S. Katz (JPL/NASA)
+Neil Killeen (ATNF/CSIRO)
+David King (NRAO)
+Paul F. Kunz (SLAC/Stanford U.)
+Jonas Møller Larsen (ESO)
+Jim Lewis (IoA, U. Cambridge)
+Marco Lombardi (ESO)
+Lars Kristian Lundin (ESO)
+Robert Lupton (Princeton U.)
+Craig Markwardt (GSFC/NASA)
+Malte Marquarding (ATNF/CSIRO)
+Tom Marsh (U. Warwick)
+Sean Mattingly (IPAC/NASA)
+Dave McConnell (ATNF/CSIRO)
+Thomas A. McGlynn (GSFC/NASA)
+Michelle Miller (NOAO)
+Jessica Mink (CfA)
+August Muench (CfA)
+Fergal Mullally (Princeton U.)
+Clive Page (U. Leicester)
+Sergio Pascual (U. Complutense de Madrid)
+Bill Pence (NASA/GSFC)
+Olivier Perdereau (LAL/IN2P3)
+Dirk Petry (ESO)
+Ray Plante (NCSA/UIUC)
+Niruj Mohan Ramanujam (Leiden Obs)
+Harold Ravlin (U. Illinois)
+Thomas Robitaille (MPIA)
+Boud Roukema (TCfA)
+Keith A. Scollick (GSFC/NASA)
+Arno Schoenmakers (ASTRON)
+Hanno Spreeuw (ASTRON)
+Ole Streicher (Debian maintainer)
+Hans Terlouw (Kapteyn, Groningen)
+Peter Teuben (U. Maryland)
+Harro Verkouter (JIVE)
+John C. Vernaleo (GSFC/NASA)
+Martin Vogelaar (Kapteyn, Groningen)
+Stephen Walton (CSUN)
+Boyd Waters NRAO)
+Randall Wayth (Curtin U.)
+Matthew Whiting (ATNF/CSIRO)
+Peter Williams (UCB)
+Daren Scot Wilson (NRAO)
+Tony Wong (ATNF/CSIRO)
+
+
+$Id: THANKS,v 4.16 2012/11/07 04:42:45 cal103 Exp $
diff --git a/cextern/wcslib/VALIDATION b/cextern/wcslib/VALIDATION
new file mode 100644
index 0000000..68ebdd2
--- /dev/null
+++ b/cextern/wcslib/VALIDATION
@@ -0,0 +1,239 @@
+Platforms on which the installation procedures and test suite were exercised
+
+
+WCSLIB version 4.15 (2012/09/26)
+--------------------------------
+
+* Dell Latitude D620 (Intel Centrino, i686) running Debian linux 5.0.9 (lenny)
+  uname -r (kernel version): 2.6.26-2-686
+  gcc --version: gcc (Debian 4.3.2-1.1) 4.3.2
+  gfortran --version: GNU Fortran (Debian 4.3.2-1.1) 4.3.2
+
+
+WCSLIB version 4.14 (2012/07/13)
+--------------------------------
+
+* Dell Latitude D620 (Intel Centrino, i686) running Debian linux 5.0.9 (lenny)
+  uname -r (kernel version): 2.6.26-2-686
+  gcc --version: gcc (Debian 4.3.2-1.1) 4.3.2
+  gfortran --version: GNU Fortran (Debian 4.3.2-1.1) 4.3.2
+
+
+* MacBook Pro (Intel Core 2 Duo) running MacOSX 10.7.3 (11D50)
+  uname -r (Darwin kernel version): 11.3.0
+  gcc --version: i686-apple-darwin11-llvm-gcc-4.2 (GCC) 4.2.1
+                 (Apple Inc. build 5658) (LLVM build 2336.1.00)
+  gfortran --version: GNU Fortran (GCC) 4.6.1
+  (Non-graphics tests only.)
+
+
+WCSLIB version 4.13.1 (2012/03/15)
+----------------------------------
+
+* Dell Latitude D630 (Intel Centrino, i686) running Debian linux 5.0.9 (lenny)
+  uname -r (kernel version): 2.6.32-bpo.5-686
+  gcc --version: gcc (Debian 4.3.2-1.1) 4.3.2
+  gfortran --version: GNU Fortran (Debian 4.3.2-1.1) 4.3.2
+
+
+* MacBook Pro (Intel Core 2 Duo) running MacOSX 10.7.3 (11D50)
+  uname -r (Darwin kernel version): 11.3.0
+  gcc --version: i686-apple-darwin11-llvm-gcc-4.2 (GCC) 4.2.1
+                 (Apple Inc. build 5658) (LLVM build 2336.1.00)
+  gfortran --version: GNU Fortran (GCC) 4.6.1
+  (Non-graphics tests only.)
+
+
+WCSLIB version 4.10 (2012/02/06)
+--------------------------------
+
+* Dell Latitude D630 (Intel Centrino, i686) running Debian linux 5.0.9 (lenny)
+  uname -r (kernel version): 2.6.32-bpo.5-686
+  gcc --version: gcc (Debian 4.3.2-1.1) 4.3.2
+  gfortran --version: GNU Fortran (Debian 4.3.2-1.1) 4.3.2
+
+
+WCSLIB version 4.8 (2011/08/15)
+-------------------------------
+
+* Dell Latitude D620 (Intel Centrino Duo, i686), Debian linux 4.0 (etch)
+  uname -r (kernel version): 2.6.24-1-686 (32-bit)
+  gcc --version: gcc (GCC) 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)
+  g77 --version: GNU Fortran (GCC) 3.4.6 (Debian 3.4.6-5)
+
+
+* Dell PowerEdge 2950 (Intel Xeon, 8 x X5460), Debian linux 5.0.8 (lenny)
+  uname -r (kernel version): 2.6.26-2-amd64 (64-bit)
+  gcc --version: gcc (Debian 4.3.2-1.1) 4.3.2
+  gfortran --version: GNU Fortran (Debian 4.3.2-1.1) 4.3.2
+
+
+* Marvell SheevaPlug (Feroceon 88FR131 rev 1 ARM v5L), Debian linux 6.0 
+  (squeeze)
+  uname -r (kernel version): 2.6.32-5-kirkwood
+  gcc --version: gcc (Debian 4.4.5-8) 4.4.5
+  gfortran --version: GNU Fortran (Debian 4.4.5-8) 4.4.5
+
+
+* Mac mini (Intel Core 2 Duo) running MacOSX 10.6.2 (10C540)
+  uname -r (Darwin kernel version): 10.2.0
+  gcc --version: i686-apple-darwin10-gcc-4.2.1 (GCC) 4.2.1
+                 (Apple Inc. build 5646)
+  gfortran --version: GNU Fortran (GCC) 4.5.0 20100107 (experimental)
+
+
+* Enterprise 450 Model 2250 (Sparc, sun4u 64-bit), SunOS 5.9 (Solaris 9)
+  uname -r (SunOS version): 5.9
+  gcc --version: gcc (GCC) 4.5.1
+  gfortran --version: GNU Fortran (GCC) 4.5.1
+
+
+WCSLIB version 4.7 (2011/02/07)
+-------------------------------
+
+* Dell Latitude D630 (Intel Centrino, i686) running Debian linux 4.0 (etch)
+  uname -r (kernel version): 2.6.24-1-686
+  gcc --version: gcc (GCC) 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)
+  g77 --version: GNU Fortran (GCC) 3.4.6 (Debian 3.4.6-5)
+
+
+* Sun SunFire V20z (AMD Opteron, x86_64) running Debian linux 4.0 (etch)
+  uname -r (kernel version): 2.6.18-6-amd64
+  gcc --version: gcc (GCC) 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)
+  g77 --version: GNU Fortran (GCC) 3.4.6 (Debian 3.4.6-5)
+
+
+* Enterprise 450 Model 2250 (Sparc, sun4u 64-bit), SunOS 5.9 (Solaris 9)
+  uname -r (SunOS version): 5.9
+  gcc --version: gcc (GCC) 4.5.1
+  gfortran --version: GNU Fortran (GCC) 4.5.1
+
+    and
+
+  cc -V: cc: Sun WorkShop 6 update 2 C 5.3 Patch 111679-14 2004/02/20
+  f77 -V: f77: Sun WorkShop 6 update 2 FORTRAN 77 5.3 Patch 111691-07
+          2004/04/23
+
+
+* Mac Xserve (Quad-Core Intel Xeon) running MacOSX 10.6.5 (10H575)
+  uname -r (Darwin kernel version): 10.5.0
+  gcc --version: 4.2.1 (Apple Inc. build 5664)
+  gfortran --version: GNU Fortran (GCC) 4.5.0 20100107 (experimental)
+
+
+* Mac mini (Intel Core 2 Duo) running MacOSX 10.6.2 (10C540)
+  uname -r (Darwin kernel version): 10.2.0
+  gcc --version: i686-apple-darwin10-gcc-4.2.1 (GCC) 4.2.1
+                 (Apple Inc. build 5646)
+  gfortran --version: GNU Fortran (GCC) 4.5.0 20100107 (experimental)
+
+
+* Mac mini (Intel Core Duo) running MacOSX 10.4.9 (8P2137)
+  uname -r (Darwin kernel version): 8.9.1
+  gcc --version: gcc (GCC) 4.3.0 20070316 (experimental)
+  g77 --version: GNU Fortran (GCC) 3.4.0
+
+
+WCSLIB version 4.5 (2010/07/16)
+-------------------------------
+
+* Dell Latitude D630 (Intel Centrino, i686) running Debian linux 4.0 (etch)
+  uname -r (kernel version): 2.6.24-1-686
+  gcc --version: gcc (GCC) 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)
+  g77 --version: GNU Fortran (GCC) 3.4.6 (Debian 3.4.6-5)
+
+    and
+
+  gcc --version: gcc (GCC) 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)
+  ifort -V: Intel(R) Fortran Compiler for 32-bit applications, Version 8.1
+            Build 20041118Z Package ID: l_fc_pc_8.1.023
+
+
+* Mac mini (Intel Core 2 Duo, i386) running MacOSX 10.6.2 (10C540)
+  uname -r (Darwin kernel version): 10.2.0
+  gcc --version: i686-apple-darwin10-gcc-4.2.1 (GCC) 4.2.1
+                 (Apple Inc. build 5646)
+  gfortran --version: GNU Fortran (GCC) 4.5.0 20100107 (experimental)
+
+
+* Mac mini (Intel Core Duo, i386) running MacOSX 10.4.9 (8P2137)
+  uname -r (Darwin kernel version): 8.9.1
+  gcc --version: gcc (GCC) 4.3.0 20070316 (experimental)
+  g77 --version: GNU Fortran (GCC) 3.4.0
+
+    and
+
+  gcc --version: gcc (GCC) 4.3.0 20070316 (experimental)
+  gfortran --version: GNU Fortran (GCC) 4.3.0 20070316 (experimental)
+
+
+* Sun SunFire V20z (AMD Opteron, x86_64) running Debian linux 4.0 (etch)
+  uname -r (kernel version): 2.6.18-6-amd64
+  gcc --version: gcc (GCC) 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)
+  g77 --version: GNU Fortran (GCC) 3.4.6 (Debian 3.4.6-5)
+
+    and
+
+  gcc --version: gcc (GCC) 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)
+  gfortran --version: GNU Fortran 95 (GCC) 4.1.2 20061115 (prerelease)
+                      (Debian 4.1.1-21)
+
+
+* Sun Ultra-60 (Sparc, sun4u) running SunOS 5.6 (Solaris 2.6)
+  uname -r (SunOS version): 5.6
+  gcc --version: 2.95.3
+  g77 --version: GNU Fortran 0.5.25 20010315 (release)
+
+    and
+
+  cc -V: cc: Sun WorkShop 6 update 2 C 5.3 Patch 111679-14 2004/02/20
+  f77 -V: f77: Sun WorkShop 6 update 2 FORTRAN 77 5.3 Patch 111691-07
+          2004/04/23
+
+
+
+WCSLIB version 4.4 (2009/08/06)
+-------------------------------
+
+* Dell Latitude D630 (Intel Centrino, i686) running Debian linux 4.0 (etch)
+  uname -r (kernel version): 2.6.24-1-686
+  gcc --version: gcc (GCC) 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)
+  g77 --version: GNU Fortran (GCC) 3.4.6 (Debian 3.4.6-5)
+
+
+* Mac mini (Intel Core Duo, i386) running MacOSX 10.4.9 (8P2137)
+  uname -r (Darwin kernel version): 8.9.1
+  gcc --version: gcc (GCC) 4.3.0 20070316 (experimental)
+  g77 --version: GNU Fortran (GCC) 3.4.0
+
+    and
+
+  gcc --version: gcc (GCC) 4.3.0 20070316 (experimental)
+  gfortran --version: GNU Fortran (GCC) 4.3.0 20070316 (experimental)
+
+
+* Sun SunFire V20z (AMD Opteron, x86_64) running Debian linux 4.0 (etch)
+  uname -r (kernel version): 2.6.18-6-amd64
+  gcc --version: gcc (GCC) 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)
+  g77 --version: GNU Fortran (GCC) 3.4.6 (Debian 3.4.6-5)
+
+    and
+
+  gcc --version: gcc (GCC) 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)
+  gfortran --version: GNU Fortran 95 (GCC) 4.1.2 20061115 (prerelease)
+                      (Debian 4.1.1-21)
+
+
+* Sun SunBlade 1000 (Sparc, sun4u) running SunOS 5.8 (Solaris 2.8)
+  uname -r (SunOS version): 5.8
+  gcc --version: 2.95.3
+  g77 --version: GNU Fortran 0.5.25 20010315 (release)
+
+    and
+
+  cc -V: cc: Sun WorkShop 6 update 2 C 5.3 Patch 111679-14 2004/02/20
+  f77 -V: f77: Sun WorkShop 6 update 2 FORTRAN 77 5.3 Patch 111691-07
+          2004/04/23
+
+------------------------------------------------------------------------------
+$Id: VALIDATION,v 4.16 2012/11/07 04:42:45 cal103 Exp $
diff --git a/astropy/wcs/src/wcslib/config/config.guess b/cextern/wcslib/config/config.guess
similarity index 100%
rename from astropy/wcs/src/wcslib/config/config.guess
rename to cextern/wcslib/config/config.guess
diff --git a/astropy/wcs/src/wcslib/config/config.sub b/cextern/wcslib/config/config.sub
similarity index 100%
rename from astropy/wcs/src/wcslib/config/config.sub
rename to cextern/wcslib/config/config.sub
diff --git a/astropy/wcs/src/wcslib/config/elisp-comp b/cextern/wcslib/config/elisp-comp
similarity index 100%
rename from astropy/wcs/src/wcslib/config/elisp-comp
rename to cextern/wcslib/config/elisp-comp
diff --git a/astropy/wcs/src/wcslib/config/install-sh b/cextern/wcslib/config/install-sh
similarity index 100%
rename from astropy/wcs/src/wcslib/config/install-sh
rename to cextern/wcslib/config/install-sh
diff --git a/astropy/wcs/src/wcslib/config/mdate-sh b/cextern/wcslib/config/mdate-sh
similarity index 100%
rename from astropy/wcs/src/wcslib/config/mdate-sh
rename to cextern/wcslib/config/mdate-sh
diff --git a/astropy/wcs/src/wcslib/config/missing b/cextern/wcslib/config/missing
similarity index 100%
rename from astropy/wcs/src/wcslib/config/missing
rename to cextern/wcslib/config/missing
diff --git a/astropy/wcs/src/wcslib/config/mkinstalldirs b/cextern/wcslib/config/mkinstalldirs
similarity index 100%
rename from astropy/wcs/src/wcslib/config/mkinstalldirs
rename to cextern/wcslib/config/mkinstalldirs
diff --git a/astropy/wcs/src/wcslib/config/move-if-change b/cextern/wcslib/config/move-if-change
similarity index 100%
rename from astropy/wcs/src/wcslib/config/move-if-change
rename to cextern/wcslib/config/move-if-change
diff --git a/cextern/wcslib/configure b/cextern/wcslib/configure
new file mode 100755
index 0000000..83e28b8
--- /dev/null
+++ b/cextern/wcslib/configure
@@ -0,0 +1,13254 @@
+#! /bin/sh
+# From configure.ac Revision: 4.16 .
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.61 for WCSLIB 4.16.
+#
+# Report bugs to <mark at calabretta.id.au>.
+#
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+# 2002, 2003, 2004, 2005, 2006 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=:
+  # Zsh 3.x and 4.x performs 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
+
+
+
+
+# PATH needs CR
+# 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
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  echo "#! /bin/sh" >conf$$.sh
+  echo  "exit 0"   >>conf$$.sh
+  chmod +x conf$$.sh
+  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+    PATH_SEPARATOR=';'
+  else
+    PATH_SEPARATOR=:
+  fi
+  rm -f conf$$.sh
+fi
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  as_unset=unset
+else
+  as_unset=false
+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.)
+as_nl='
+'
+IFS=" ""	$as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+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
+  echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  { (exit 1); exit 1; }
+fi
+
+# Work around bugs in pre-3.0 UWIN ksh.
+for as_var in ENV MAIL MAILPATH
+do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+  LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+  LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+  LC_TELEPHONE LC_TIME
+do
+  if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+    eval $as_var=C; export $as_var
+  else
+    ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+  fi
+done
+
+# Required to use basename.
+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
+
+
+# Name of the executable.
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+
+# CDPATH.
+$as_unset CDPATH
+
+
+if test "x$CONFIG_SHELL" = x; then
+  if (eval ":") 2>/dev/null; then
+  as_have_required=yes
+else
+  as_have_required=no
+fi
+
+  if test $as_have_required = yes && 	 (eval ":
+(as_func_return () {
+  (exit \$1)
+}
+as_func_success () {
+  as_func_return 0
+}
+as_func_failure () {
+  as_func_return 1
+}
+as_func_ret_success () {
+  return 0
+}
+as_func_ret_failure () {
+  return 1
+}
+
+exitcode=0
+if as_func_success; then
+  :
+else
+  exitcode=1
+  echo as_func_success failed.
+fi
+
+if as_func_failure; then
+  exitcode=1
+  echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+  :
+else
+  exitcode=1
+  echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+  exitcode=1
+  echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
+  :
+else
+  exitcode=1
+  echo positional parameters were not saved.
+fi
+
+test \$exitcode = 0) || { (exit 1); exit 1; }
+
+(
+  as_lineno_1=\$LINENO
+  as_lineno_2=\$LINENO
+  test \"x\$as_lineno_1\" != \"x\$as_lineno_2\" &&
+  test \"x\`expr \$as_lineno_1 + 1\`\" = \"x\$as_lineno_2\") || { (exit 1); exit 1; }
+") 2> /dev/null; then
+  :
+else
+  as_candidate_shells=
+    as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  case $as_dir in
+	 /*)
+	   for as_base in sh bash ksh sh5; do
+	     as_candidate_shells="$as_candidate_shells $as_dir/$as_base"
+	   done;;
+       esac
+done
+IFS=$as_save_IFS
+
+
+      for as_shell in $as_candidate_shells $SHELL; do
+	 # Try only shells that exist, to save several forks.
+	 if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+		{ ("$as_shell") 2> /dev/null <<\_ASEOF
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs 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
+
+
+:
+_ASEOF
+}; then
+  CONFIG_SHELL=$as_shell
+	       as_have_required=yes
+	       if { "$as_shell" 2> /dev/null <<\_ASEOF
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs 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_func_return () {
+  (exit $1)
+}
+as_func_success () {
+  as_func_return 0
+}
+as_func_failure () {
+  as_func_return 1
+}
+as_func_ret_success () {
+  return 0
+}
+as_func_ret_failure () {
+  return 1
+}
+
+exitcode=0
+if as_func_success; then
+  :
+else
+  exitcode=1
+  echo as_func_success failed.
+fi
+
+if as_func_failure; then
+  exitcode=1
+  echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+  :
+else
+  exitcode=1
+  echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+  exitcode=1
+  echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = "$1" ); then
+  :
+else
+  exitcode=1
+  echo positional parameters were not saved.
+fi
+
+test $exitcode = 0) || { (exit 1); exit 1; }
+
+(
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2") || { (exit 1); exit 1; }
+
+_ASEOF
+}; then
+  break
+fi
+
+fi
+
+      done
+
+      if test "x$CONFIG_SHELL" != x; then
+  for as_var in BASH_ENV ENV
+        do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+        done
+        export CONFIG_SHELL
+        exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"}
+fi
+
+
+    if test $as_have_required = no; then
+  echo This script requires a shell more modern than all the
+      echo shells that I found on your system.  Please install a
+      echo modern shell, or manually run the script under such a
+      echo shell if you do have one.
+      { (exit 1); exit 1; }
+fi
+
+
+fi
+
+fi
+
+
+
+(eval "as_func_return () {
+  (exit \$1)
+}
+as_func_success () {
+  as_func_return 0
+}
+as_func_failure () {
+  as_func_return 1
+}
+as_func_ret_success () {
+  return 0
+}
+as_func_ret_failure () {
+  return 1
+}
+
+exitcode=0
+if as_func_success; then
+  :
+else
+  exitcode=1
+  echo as_func_success failed.
+fi
+
+if as_func_failure; then
+  exitcode=1
+  echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+  :
+else
+  exitcode=1
+  echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+  exitcode=1
+  echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
+  :
+else
+  exitcode=1
+  echo positional parameters were not saved.
+fi
+
+test \$exitcode = 0") || {
+  echo No shell found that supports shell functions.
+  echo Please tell autoconf at gnu.org about your system,
+  echo including any error possibly output before this
+  echo message
+}
+
+
+
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
+
+  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+  # uniformly replaced by the line number.  The first 'sed' inserts a
+  # line-number line after each line using $LINENO; the second 'sed'
+  # does the real work.  The second script uses 'N' to pair each
+  # line-number line with the line containing $LINENO, and appends
+  # trailing '-' during substitution so that $LINENO is not a special
+  # case at line end.
+  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+  # scripts with optimization help from Paolo Bonzini.  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" ||
+    { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+   { (exit 1); exit 1; }; }
+
+  # 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
+}
+
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in
+-n*)
+  case `echo 'x\c'` in
+  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
+  *)   ECHO_C='\c';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+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
+fi
+echo >conf$$.file
+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 -p'.
+  ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+    as_ln_s='cp -p'
+elif ln conf$$.file conf$$ 2>/dev/null; then
+  as_ln_s=ln
+else
+  as_ln_s='cp -p'
+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=:
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+  as_test_x='test -x'
+else
+  if ls -dL / >/dev/null 2>&1; then
+    as_ls_L_option=L
+  else
+    as_ls_L_option=
+  fi
+  as_test_x='
+    eval sh -c '\''
+      if test -d "$1"; then
+        test -d "$1/.";
+      else
+	case $1 in
+        -*)set "./$1";;
+	esac;
+	case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in
+	???[sx]*):;;*)false;;esac;fi
+    '\'' sh
+  '
+fi
+as_executable_p=$as_test_x
+
+# 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 7<&0 </dev/null 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, 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=
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+# Identity of this package.
+PACKAGE_NAME='WCSLIB'
+PACKAGE_TARNAME='wcslib-4.16'
+PACKAGE_VERSION='4.16'
+PACKAGE_STRING='WCSLIB 4.16'
+PACKAGE_BUGREPORT='mark at calabretta.id.au'
+
+ac_unique_file="C/wcs.h"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+#  include <stdlib.h>
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+#  include <memory.h>
+# endif
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='SHELL
+PATH_SEPARATOR
+PACKAGE_NAME
+PACKAGE_TARNAME
+PACKAGE_VERSION
+PACKAGE_STRING
+PACKAGE_BUGREPORT
+exec_prefix
+prefix
+program_transform_name
+bindir
+sbindir
+libexecdir
+datarootdir
+datadir
+sysconfdir
+sharedstatedir
+localstatedir
+includedir
+oldincludedir
+docdir
+infodir
+htmldir
+dvidir
+pdfdir
+psdir
+libdir
+localedir
+mandir
+DEFS
+ECHO_C
+ECHO_N
+ECHO_T
+LIBS
+build_alias
+host_alias
+target_alias
+LIBVER
+build
+build_cpu
+build_vendor
+build_os
+ARCH
+FLEX
+CC
+CFLAGS
+LDFLAGS
+CPPFLAGS
+ac_ct_CC
+EXEEXT
+OBJEXT
+CPP
+GREP
+EGREP
+LIBOBJS
+F77
+FFLAGS
+ac_ct_F77
+FLIBS
+RANLIB
+SHRLIB
+SONAME
+SHRFLAGS
+SHRLD
+SHRSFX
+SHRLN
+LN_S
+INSTALL_PROGRAM
+INSTALL_SCRIPT
+INSTALL_DATA
+XMKMF
+CFITSIOINC
+CFITSIOLIB
+GETWCSTAB
+PGPLOTINC
+PGPLOTLIB
+SUBDIRS
+TSTDIRS
+INSTDIR
+LTLIBOBJS'
+ac_subst_files=''
+      ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CPP
+F77
+FFLAGS
+XMKMF'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+# 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_TARNAME}'
+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=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_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+   { (exit 1); exit 1; }; }
+    ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'`
+    eval enable_$ac_feature=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_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+   { (exit 1); exit 1; }; }
+    ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'`
+    eval enable_$ac_feature=\$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_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid package name: $ac_package" >&2
+   { (exit 1); exit 1; }; }
+    ac_package=`echo $ac_package | sed 's/[-.]/_/g'`
+    eval with_$ac_package=\$ac_optarg ;;
+
+  -without-* | --without-*)
+    ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid package name: $ac_package" >&2
+   { (exit 1); exit 1; }; }
+    ac_package=`echo $ac_package | sed 's/[-.]/_/g'`
+    eval with_$ac_package=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 ;;
+
+  -*) { echo "$as_me: error: unrecognized option: $ac_option
+Try \`$0 --help' for more information." >&2
+   { (exit 1); exit 1; }; }
+    ;;
+
+  *=*)
+    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
+   { (exit 1); exit 1; }; }
+    eval $ac_envvar=\$ac_optarg
+    export $ac_envvar ;;
+
+  *)
+    # FIXME: should be removed in autoconf 3.0.
+    echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      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'`
+  { echo "$as_me: error: missing argument to $ac_option" >&2
+   { (exit 1); exit 1; }; }
+fi
+
+# Be sure to have absolute directory names.
+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
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* )  continue;;
+    NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+  esac
+  { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+   { (exit 1); exit 1; }; }
+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
+    echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+    If a cross compiler is detected then cross compile mode will be used." >&2
+  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 .` ||
+  { echo "$as_me: error: Working directory cannot be determined" >&2
+   { (exit 1); exit 1; }; }
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+  { echo "$as_me: error: pwd does not report name of working directory" >&2
+   { (exit 1); exit 1; }; }
+
+
+# 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 -- "$0" ||
+$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$0" : 'X\(//\)[^/]' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$0" |
+    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 .."
+  { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
+   { (exit 1); exit 1; }; }
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+	cd "$srcdir" && test -r "./$ac_unique_file" || { echo "$as_me: error: $ac_msg" >&2
+   { (exit 1); exit 1; }; }
+	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 WCSLIB 4.16 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/wcslib-4.16]
+  --htmldir=DIR          html documentation [DOCDIR]
+  --dvidir=DIR           dvi documentation [DOCDIR]
+  --pdfdir=DIR           pdf documentation [DOCDIR]
+  --psdir=DIR            ps documentation [DOCDIR]
+_ACEOF
+
+  cat <<\_ACEOF
+
+X features:
+  --x-includes=DIR    X include files are in DIR
+  --x-libraries=DIR   X library files are in DIR
+
+System types:
+  --build=BUILD     configure for building on BUILD [guessed]
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+  case $ac_init_help in
+     short | recursive ) echo "Configuration of WCSLIB 4.16:";;
+   esac
+  cat <<\_ACEOF
+
+Optional Features:
+  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
+  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
+  --enable-fortran=ARG    Fortran compiler to use
+  --disable-fortran       don't build the Fortran wrappers or PGSBOX
+  --disable-largefile     omit support for large files
+  --disable-utils         don't build the WCS utilities
+
+Optional Packages:
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --without-cfitsio       eschew CFITSIO
+  --with-cfitsiolib=DIR   directory containing cfitsio library
+  --with-cfitsioinc=DIR   directory containing cfitsio header files
+  --without-pgplot        eschew PGPLOT
+  --with-pgplotlib=DIR    directory containing pgplot library
+  --with-pgplotinc=DIR    directory containing pgplot header files
+  --with-x                use the X Window System
+
+Some influential environment variables:
+  CC          C compiler command
+  CFLAGS      C compiler flags
+  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
+              nonstandard directory <lib dir>
+  LIBS        libraries to pass to the linker, e.g. -l<library>
+  CPPFLAGS    C/C++/Objective C preprocessor flags, e.g. -I<include dir> if
+              you have headers in a nonstandard directory <include dir>
+  CPP         C preprocessor
+  F77         Fortran 77 compiler command
+  FFLAGS      Fortran 77 compiler flags
+  XMKMF       Path to xmkmf, Makefile generator for X Window System
+
+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 <mark at calabretta.id.au>.
+_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" || continue
+    ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`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
+      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
+WCSLIB configure 4.16
+generated by GNU Autoconf 2.61
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+2002, 2003, 2004, 2005, 2006 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
+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 WCSLIB $as_me 4.16, which was
+generated by GNU Autoconf 2.61.  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=.
+  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=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    case $ac_pass in
+    1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
+    2)
+      ac_configure_args1="$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
+      ac_configure_args="$ac_configure_args '$ac_arg'"
+      ;;
+    esac
+  done
+done
+$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
+$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export 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
+
+    cat <<\_ASBOX
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+_ASBOX
+    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_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5
+echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      *) $as_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
+
+    cat <<\_ASBOX
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+_ASBOX
+    echo
+    for ac_var in $ac_subst_vars
+    do
+      eval ac_val=\$$ac_var
+      case $ac_val in
+      *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+      esac
+      echo "$ac_var='\''$ac_val'\''"
+    done | sort
+    echo
+
+    if test -n "$ac_subst_files"; then
+      cat <<\_ASBOX
+## ------------------- ##
+## File substitutions. ##
+## ------------------- ##
+_ASBOX
+      echo
+      for ac_var in $ac_subst_files
+      do
+	eval ac_val=\$$ac_var
+	case $ac_val in
+	*\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+	esac
+	echo "$ac_var='\''$ac_val'\''"
+      done | sort
+      echo
+    fi
+
+    if test -s confdefs.h; then
+      cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+      echo
+      cat confdefs.h
+      echo
+    fi
+    test "$ac_signal" != 0 &&
+      echo "$as_me: caught signal $ac_signal"
+    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'; { (exit 1); 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
+
+# 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
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer explicitly selected file to automatically selected ones.
+if test -n "$CONFIG_SITE"; then
+  set x "$CONFIG_SITE"
+elif test "x$prefix" != xNONE; then
+  set x "$prefix/share/config.site" "$prefix/etc/config.site"
+else
+  set x "$ac_default_prefix/share/config.site" \
+	"$ac_default_prefix/etc/config.site"
+fi
+shift
+for ac_site_file
+do
+  if test -r "$ac_site_file"; then
+    { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
+echo "$as_me: loading site script $ac_site_file" >&6;}
+    sed 's/^/| /' "$ac_site_file" >&5
+    . "$ac_site_file"
+  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.
+  if test -f "$cache_file"; then
+    { echo "$as_me:$LINENO: loading cache $cache_file" >&5
+echo "$as_me: loading cache $cache_file" >&6;}
+    case $cache_file in
+      [\\/]* | ?:[\\/]* ) . "$cache_file";;
+      *)                      . "./$cache_file";;
+    esac
+  fi
+else
+  { echo "$as_me:$LINENO: creating cache $cache_file" >&5
+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,)
+      { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,set)
+      { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
+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
+	{ echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
+echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+	{ echo "$as_me:$LINENO:   former value:  $ac_old_val" >&5
+echo "$as_me:   former value:  $ac_old_val" >&2;}
+	{ echo "$as_me:$LINENO:   current value: $ac_new_val" >&5
+echo "$as_me:   current value: $ac_new_val" >&2;}
+	ac_cache_corrupted=:
+      fi;;
+  esac
+  # Pass precious variables to config.status.
+  if test "$ac_new_set" = set; then
+    case $ac_new_val in
+    *\'*) ac_arg=$ac_var=`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.
+      *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+    esac
+  fi
+done
+if $ac_cache_corrupted; then
+  { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
+echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+  { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
+echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
+   { (exit 1); exit 1; }; }
+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
+
+
+
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define WCSLIB_VERSION $PACKAGE_VERSION
+_ACEOF
+
+
+# Library version number, same as package version.
+LIBVER="$PACKAGE_VERSION"
+
+
+
+ac_aux_dir=
+for ac_dir in config "$srcdir"/config; 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
+  { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in config \"$srcdir\"/config" >&5
+echo "$as_me: error: cannot find install-sh or install.sh in config \"$srcdir\"/config" >&2;}
+   { (exit 1); exit 1; }; }
+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.
+
+
+
+# Get the system type.
+# Make sure we can run config.sub.
+$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
+  { { echo "$as_me:$LINENO: error: cannot run $SHELL $ac_aux_dir/config.sub" >&5
+echo "$as_me: error: cannot run $SHELL $ac_aux_dir/config.sub" >&2;}
+   { (exit 1); exit 1; }; }
+
+{ echo "$as_me:$LINENO: checking build system type" >&5
+echo $ECHO_N "checking build system type... $ECHO_C" >&6; }
+if test "${ac_cv_build+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&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 &&
+  { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5
+echo "$as_me: error: cannot guess build type; you must specify one" >&2;}
+   { (exit 1); exit 1; }; }
+ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
+  { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&5
+echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&2;}
+   { (exit 1); exit 1; }; }
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_build" >&5
+echo "${ECHO_T}$ac_cv_build" >&6; }
+case $ac_cv_build in
+*-*-*) ;;
+*) { { echo "$as_me:$LINENO: error: invalid value of canonical build" >&5
+echo "$as_me: error: invalid value of canonical build" >&2;}
+   { (exit 1); exit 1; }; };;
+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
+
+
+ARCH="${build_cpu}-$build_os"
+
+
+
+# Look for Flex.
+# Extract the first word of "flex", so it can be a program name with args.
+set dummy flex; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_FLEX+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$FLEX"; then
+  ac_cv_prog_FLEX="$FLEX" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_FLEX="flex"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+FLEX=$ac_cv_prog_FLEX
+if test -n "$FLEX"; then
+  { echo "$as_me:$LINENO: result: $FLEX" >&5
+echo "${ECHO_T}$FLEX" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+if test "x$FLEX" = xflex ; then
+  # Version 2.5.9 or later is required.
+  V=`flex --version | awk '{print $NF}'`
+  W=`echo $V | awk -F. '{if ((($1*100 + $2)*100 + $3) < 20509) print "no"}'`
+  if test "x$W" != x ; then
+    { echo "$as_me:$LINENO: Flex version $V is too old, ignored." >&5
+echo "$as_me: Flex version $V is too old, ignored." >&6;}
+    FLEX=
+  else
+    { echo "$as_me:$LINENO: Using Flex version $V." >&5
+echo "$as_me: Using Flex version $V." >&6;}
+  fi
+fi
+
+if test "x$FLEX" = x ; then
+  { echo "$as_me:$LINENO: WARNING: Flex version 2.5.9 or later does not appear to be
+           available, will use pre-generated sources." >&5
+echo "$as_me: WARNING: Flex version 2.5.9 or later does not appear to be
+           available, will use pre-generated sources." >&2;}
+fi
+
+
+# Look for an ANSI C compiler.
+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
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="${ac_tool_prefix}gcc"
+    echo "$as_me:$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
+  { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}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
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_CC="gcc"
+    echo "$as_me:$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
+  { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf at gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf at gnu.org." >&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
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="${ac_tool_prefix}cc"
+    echo "$as_me:$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
+  { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}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
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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"
+    echo "$as_me:$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
+  { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}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
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+    echo "$as_me:$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
+  { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}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
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_CC="$ac_prog"
+    echo "$as_me:$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
+  { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}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:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf at gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf at gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+fi
+
+fi
+
+
+test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&5
+echo "$as_me: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO: checking for C compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (ac_try="$ac_compiler --version >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compiler --version >&5") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (ac_try="$ac_compiler -v >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compiler -v >&5") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (ac_try="$ac_compiler -V >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compiler -V >&5") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out 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.
+{ echo "$as_me:$LINENO: checking for C compiler default output file name" >&5
+echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6; }
+ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+#
+# List of possible output files, starting from the most likely.
+# The algorithm is not robust to junk in `.', hence go to wildcards (a.*)
+# only as a last resort.  b.out is created by i960 compilers.
+ac_files='a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out'
+#
+# The IRIX 6 linker writes into existing files which may not be
+# executable, retaining their permissions.  Remove them first so a
+# subsequent execution test works.
+ac_rmfiles=
+for ac_file in $ac_files
+do
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link_default") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; 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 | *.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
+
+{ echo "$as_me:$LINENO: result: $ac_file" >&5
+echo "${ECHO_T}$ac_file" >&6; }
+if test -z "$ac_file"; then
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: C compiler cannot create executables
+See \`config.log' for more details." >&5
+echo "$as_me: error: C compiler cannot create executables
+See \`config.log' for more details." >&2;}
+   { (exit 77); exit 77; }; }
+fi
+
+ac_exeext=$ac_cv_exeext
+
+# Check that the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+{ echo "$as_me:$LINENO: checking whether the C compiler works" >&5
+echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6; }
+# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
+# If not cross compiling, check that we can run a simple program.
+if test "$cross_compiling" != yes; then
+  if { ac_try='./$ac_file'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+    cross_compiling=no
+  else
+    if test "$cross_compiling" = maybe; then
+	cross_compiling=yes
+    else
+	{ { echo "$as_me:$LINENO: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+    fi
+  fi
+fi
+{ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+
+rm -f a.out a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+# Check that the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+{ echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
+echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6; }
+{ echo "$as_me:$LINENO: result: $cross_compiling" >&5
+echo "${ECHO_T}$cross_compiling" >&6; }
+
+{ echo "$as_me:$LINENO: checking for suffix of executables" >&5
+echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6; }
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; 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 | *.o | *.obj ) ;;
+    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+	  break;;
+    * ) break;;
+  esac
+done
+else
+  { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest$ac_cv_exeext
+{ echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
+echo "${ECHO_T}$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+{ echo "$as_me:$LINENO: checking for suffix of object files" >&5
+echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6; }
+if test "${ac_cv_objext+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; 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 ) ;;
+    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+       break;;
+  esac
+done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
+echo "${ECHO_T}$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6; }
+if test "${ac_cv_c_compiler_gnu+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_compiler_gnu=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	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
+{ echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6; }
+GCC=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
+echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6; }
+if test "${ac_cv_prog_cc_g+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&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 >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_prog_cc_g=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	CFLAGS=""
+      cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_c_werror_flag=$ac_save_c_werror_flag
+	 CFLAGS="-g"
+	 cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_prog_cc_g=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+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
+{ echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
+echo "${ECHO_T}$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
+{ echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5
+echo $ECHO_N "checking for $CC option to accept ISO C89... $ECHO_C" >&6; }
+if test "${ac_cv_prog_cc_c89+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* 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"
+  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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_prog_cc_c89=$ac_arg
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+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)
+    { echo "$as_me:$LINENO: result: none needed" >&5
+echo "${ECHO_T}none needed" >&6; } ;;
+  xno)
+    { echo "$as_me:$LINENO: result: unsupported" >&5
+echo "${ECHO_T}unsupported" >&6; } ;;
+  *)
+    CC="$CC $ac_cv_prog_cc_c89"
+    { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+
+
+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
+{ echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
+echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+  if test "${ac_cv_prog_CPP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&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 <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> 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 >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+		     Syntax error
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Broken: fails on valid input.
+continue
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  # Broken: success on invalid input.
+continue
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f 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
+{ echo "$as_me:$LINENO: result: $CPP" >&5
+echo "${ECHO_T}$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 <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> 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 >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+		     Syntax error
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Broken: fails on valid input.
+continue
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  # Broken: success on invalid input.
+continue
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  :
+else
+  { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&5
+echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+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
+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
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="${ac_tool_prefix}gcc"
+    echo "$as_me:$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
+  { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}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
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_CC="gcc"
+    echo "$as_me:$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
+  { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf at gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf at gnu.org." >&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
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="${ac_tool_prefix}cc"
+    echo "$as_me:$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
+  { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}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
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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"
+    echo "$as_me:$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
+  { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}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
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+    echo "$as_me:$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
+  { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}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
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_CC="$ac_prog"
+    echo "$as_me:$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
+  { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}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:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf at gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf at gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+fi
+
+fi
+
+
+test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&5
+echo "$as_me: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO: checking for C compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (ac_try="$ac_compiler --version >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compiler --version >&5") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (ac_try="$ac_compiler -v >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compiler -v >&5") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (ac_try="$ac_compiler -V >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compiler -V >&5") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+
+{ echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6; }
+if test "${ac_cv_c_compiler_gnu+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_compiler_gnu=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	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
+{ echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6; }
+GCC=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
+echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6; }
+if test "${ac_cv_prog_cc_g+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&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 >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_prog_cc_g=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	CFLAGS=""
+      cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_c_werror_flag=$ac_save_c_werror_flag
+	 CFLAGS="-g"
+	 cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_prog_cc_g=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+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
+{ echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
+echo "${ECHO_T}$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
+{ echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5
+echo $ECHO_N "checking for $CC option to accept ISO C89... $ECHO_C" >&6; }
+if test "${ac_cv_prog_cc_c89+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* 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"
+  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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_prog_cc_c89=$ac_arg
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+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)
+    { echo "$as_me:$LINENO: result: none needed" >&5
+echo "${ECHO_T}none needed" >&6; } ;;
+  xno)
+    { echo "$as_me:$LINENO: result: unsupported" >&5
+echo "${ECHO_T}unsupported" >&6; } ;;
+  *)
+    CC="$CC $ac_cv_prog_cc_c89"
+    { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+
+
+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
+
+   case $ac_cv_prog_cc_stdc in
+  no) ac_cv_prog_cc_c99=no; ac_cv_prog_cc_c89=no ;;
+  *) { echo "$as_me:$LINENO: checking for $CC option to accept ISO C99" >&5
+echo $ECHO_N "checking for $CC option to accept ISO C99... $ECHO_C" >&6; }
+if test "${ac_cv_prog_cc_c99+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_prog_cc_c99=no
+ac_save_CC=$CC
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <wchar.h>
+#include <stdio.h>
+
+// Check varargs macros.  These examples are taken from C99 6.10.3.5.
+#define debug(...) fprintf (stderr, __VA_ARGS__)
+#define showlist(...) puts (#__VA_ARGS__)
+#define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__))
+static void
+test_varargs_macros (void)
+{
+  int x = 1234;
+  int y = 5678;
+  debug ("Flag");
+  debug ("X = %d\n", x);
+  showlist (The first, second, and third items.);
+  report (x>y, "x is %d but y is %d", x, y);
+}
+
+// Check long long types.
+#define BIG64 18446744073709551615ull
+#define BIG32 4294967295ul
+#define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0)
+#if !BIG_OK
+  your preprocessor is broken;
+#endif
+#if BIG_OK
+#else
+  your preprocessor is broken;
+#endif
+static long long int bignum = -9223372036854775807LL;
+static unsigned long long int ubignum = BIG64;
+
+struct incomplete_array
+{
+  int datasize;
+  double data[];
+};
+
+struct named_init {
+  int number;
+  const wchar_t *name;
+  double average;
+};
+
+typedef const char *ccp;
+
+static inline int
+test_restrict (ccp restrict text)
+{
+  // See if C++-style comments work.
+  // Iterate through items via the restricted pointer.
+  // Also check for declarations in for loops.
+  for (unsigned int i = 0; *(text+i) != '\0'; ++i)
+    continue;
+  return 0;
+}
+
+// Check varargs and va_copy.
+static void
+test_varargs (const char *format, ...)
+{
+  va_list args;
+  va_start (args, format);
+  va_list args_copy;
+  va_copy (args_copy, args);
+
+  const char *str;
+  int number;
+  float fnumber;
+
+  while (*format)
+    {
+      switch (*format++)
+	{
+	case 's': // string
+	  str = va_arg (args_copy, const char *);
+	  break;
+	case 'd': // int
+	  number = va_arg (args_copy, int);
+	  break;
+	case 'f': // float
+	  fnumber = va_arg (args_copy, double);
+	  break;
+	default:
+	  break;
+	}
+    }
+  va_end (args_copy);
+  va_end (args);
+}
+
+int
+main ()
+{
+
+  // Check bool.
+  _Bool success = false;
+
+  // Check restrict.
+  if (test_restrict ("String literal") == 0)
+    success = true;
+  char *restrict newvar = "Another string";
+
+  // Check varargs.
+  test_varargs ("s, d' f .", "string", 65, 34.234);
+  test_varargs_macros ();
+
+  // Check flexible array members.
+  struct incomplete_array *ia =
+    malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10));
+  ia->datasize = 10;
+  for (int i = 0; i < ia->datasize; ++i)
+    ia->data[i] = i * 1.234;
+
+  // Check named initializers.
+  struct named_init ni = {
+    .number = 34,
+    .name = L"Test wide string",
+    .average = 543.34343,
+  };
+
+  ni.number = 58;
+
+  int dynamic_array[ni.number];
+  dynamic_array[ni.number - 1] = 543;
+
+  // work around unused variable warnings
+  return (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == 'x'
+	  || dynamic_array[ni.number - 1] != 543);
+
+  ;
+  return 0;
+}
+_ACEOF
+for ac_arg in '' -std=gnu99 -c99 -qlanglvl=extc99
+do
+  CC="$ac_save_CC $ac_arg"
+  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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_prog_cc_c99=$ac_arg
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext
+  test "x$ac_cv_prog_cc_c99" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c99" in
+  x)
+    { echo "$as_me:$LINENO: result: none needed" >&5
+echo "${ECHO_T}none needed" >&6; } ;;
+  xno)
+    { echo "$as_me:$LINENO: result: unsupported" >&5
+echo "${ECHO_T}unsupported" >&6; } ;;
+  *)
+    CC="$CC $ac_cv_prog_cc_c99"
+    { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c99" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_c99" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c99" != xno; then
+  ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99
+else
+  { echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5
+echo $ECHO_N "checking for $CC option to accept ISO C89... $ECHO_C" >&6; }
+if test "${ac_cv_prog_cc_c89+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* 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"
+  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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_prog_cc_c89=$ac_arg
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+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)
+    { echo "$as_me:$LINENO: result: none needed" >&5
+echo "${ECHO_T}none needed" >&6; } ;;
+  xno)
+    { echo "$as_me:$LINENO: result: unsupported" >&5
+echo "${ECHO_T}unsupported" >&6; } ;;
+  *)
+    CC="$CC $ac_cv_prog_cc_c89"
+    { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then
+  ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89
+else
+  ac_cv_prog_cc_stdc=no
+fi
+
+
+fi
+
+ ;;
+esac
+  { echo "$as_me:$LINENO: checking for $CC option to accept ISO Standard C" >&5
+echo $ECHO_N "checking for $CC option to accept ISO Standard C... $ECHO_C" >&6; }
+  if test "${ac_cv_prog_cc_stdc+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+
+  case $ac_cv_prog_cc_stdc in
+  no) { echo "$as_me:$LINENO: result: unsupported" >&5
+echo "${ECHO_T}unsupported" >&6; } ;;
+  '') { echo "$as_me:$LINENO: result: none needed" >&5
+echo "${ECHO_T}none needed" >&6; } ;;
+  *) { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6; } ;;
+esac
+
+
+
+{ echo "$as_me:$LINENO: checking for an ANSI C-conforming const" >&5
+echo $ECHO_N "checking for an ANSI C-conforming const... $ECHO_C" >&6; }
+if test "${ac_cv_c_const+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+/* FIXME: Include the comments suggested by Paul. */
+#ifndef __cplusplus
+  /* Ultrix mips cc rejects this.  */
+  typedef int charset[2];
+  const charset cs;
+  /* SunOS 4.1.1 cc rejects this.  */
+  char const *const *pcpcc;
+  char **ppc;
+  /* NEC SVR4.0.2 mips cc rejects this.  */
+  struct point {int x, y;};
+  static struct point const zero = {0,0};
+  /* AIX XL C 1.02.0.0 rejects this.
+     It does not let you subtract one const X* pointer from another in
+     an arm of an if-expression whose if-part is not a constant
+     expression */
+  const char *g = "string";
+  pcpcc = &g + (g ? g-g : 0);
+  /* HPUX 7.0 cc rejects these. */
+  ++pcpcc;
+  ppc = (char**) pcpcc;
+  pcpcc = (char const *const *) ppc;
+  { /* SCO 3.2v4 cc rejects this.  */
+    char *t;
+    char const *s = 0 ? (char *) 0 : (char const *) 0;
+
+    *t++ = 0;
+    if (s) return 0;
+  }
+  { /* Someone thinks the Sun supposedly-ANSI compiler will reject this.  */
+    int x[] = {25, 17};
+    const int *foo = &x[0];
+    ++foo;
+  }
+  { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
+    typedef const int *iptr;
+    iptr p = 0;
+    ++p;
+  }
+  { /* AIX XL C 1.02.0.0 rejects this saying
+       "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
+    struct s { int j; const int *ap[3]; };
+    struct s *b; b->j = 5;
+  }
+  { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
+    const int foo = 10;
+    if (!foo) return 0;
+  }
+  return !cs[0] && !zero.x;
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_c_const=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_c_const=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_const" >&5
+echo "${ECHO_T}$ac_cv_c_const" >&6; }
+if test $ac_cv_c_const = no; then
+
+cat >>confdefs.h <<\_ACEOF
+#define const
+_ACEOF
+
+fi
+
+
+{ echo "$as_me:$LINENO: checking for grep that handles long lines and -e" >&5
+echo $ECHO_N "checking for grep that handles long lines and -e... $ECHO_C" >&6; }
+if test "${ac_cv_path_GREP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  # Extract the first word of "grep ggrep" to use in msg output
+if test -z "$GREP"; then
+set dummy grep ggrep; ac_prog_name=$2
+if test "${ac_cv_path_GREP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  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"
+    { test -f "$ac_path_GREP" && $as_test_x "$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
+  echo $ECHO_N "0123456789$ECHO_C" >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    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
+    ac_count=`expr $ac_count + 1`
+    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
+
+
+fi
+
+GREP="$ac_cv_path_GREP"
+if test -z "$GREP"; then
+  { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5
+echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+else
+  ac_cv_path_GREP=$GREP
+fi
+
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_path_GREP" >&5
+echo "${ECHO_T}$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ echo "$as_me:$LINENO: checking for egrep" >&5
+echo $ECHO_N "checking for egrep... $ECHO_C" >&6; }
+if test "${ac_cv_path_EGREP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+   then ac_cv_path_EGREP="$GREP -E"
+   else
+     # Extract the first word of "egrep" to use in msg output
+if test -z "$EGREP"; then
+set dummy egrep; ac_prog_name=$2
+if test "${ac_cv_path_EGREP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  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"
+    { test -f "$ac_path_EGREP" && $as_test_x "$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
+  echo $ECHO_N "0123456789$ECHO_C" >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    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
+    ac_count=`expr $ac_count + 1`
+    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
+
+
+fi
+
+EGREP="$ac_cv_path_EGREP"
+if test -z "$EGREP"; then
+  { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5
+echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+else
+  ac_cv_path_EGREP=$EGREP
+fi
+
+
+   fi
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_path_EGREP" >&5
+echo "${ECHO_T}$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+{ echo "$as_me:$LINENO: checking for ANSI C header files" >&5
+echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6; }
+if test "${ac_cv_header_stdc+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_header_stdc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	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 >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <string.h>
+
+_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 -r conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+
+_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 -r 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 >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ctype.h>
+#include <stdlib.h>
+#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
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
+echo "${ECHO_T}$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define STDC_HEADERS 1
+_ACEOF
+
+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=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+
+#include <$ac_header>
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  eval "$as_ac_Header=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	eval "$as_ac_Header=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+{ echo "$as_me:$LINENO: checking for size_t" >&5
+echo $ECHO_N "checking for size_t... $ECHO_C" >&6; }
+if test "${ac_cv_type_size_t+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+typedef size_t ac__type_new_;
+int
+main ()
+{
+if ((ac__type_new_ *) 0)
+  return 0;
+if (sizeof (ac__type_new_))
+  return 0;
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_type_size_t=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_type_size_t=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_type_size_t" >&5
+echo "${ECHO_T}$ac_cv_type_size_t" >&6; }
+if test $ac_cv_type_size_t = yes; then
+  :
+else
+
+cat >>confdefs.h <<_ACEOF
+#define size_t unsigned int
+_ACEOF
+
+fi
+
+if test "x$ac_cv_prog_cc_stdc" = xno -o \
+        "x$ac_cv_c_const"      = xno -o \
+        "x$ac_cv_type_size_t"  = xno; then
+  { { echo "$as_me:$LINENO: error:
+    -------------------------------------------------------
+    An ANSI standard C library is required to build WCSLIB.
+
+    ERROR: WCSLIB configuration failure.
+    -------------------------------------------------------" >&5
+echo "$as_me: error:
+    -------------------------------------------------------
+    An ANSI standard C library is required to build WCSLIB.
+
+    ERROR: WCSLIB configuration failure.
+    -------------------------------------------------------" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+# Check for data types (suggested by autoscan - off_t is only required by
+# fitshdr).
+{ echo "$as_me:$LINENO: checking for off_t" >&5
+echo $ECHO_N "checking for off_t... $ECHO_C" >&6; }
+if test "${ac_cv_type_off_t+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+typedef off_t ac__type_new_;
+int
+main ()
+{
+if ((ac__type_new_ *) 0)
+  return 0;
+if (sizeof (ac__type_new_))
+  return 0;
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_type_off_t=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_type_off_t=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_type_off_t" >&5
+echo "${ECHO_T}$ac_cv_type_off_t" >&6; }
+if test $ac_cv_type_off_t = yes; then
+  :
+else
+
+cat >>confdefs.h <<_ACEOF
+#define off_t long int
+_ACEOF
+
+fi
+
+
+  { echo "$as_me:$LINENO: checking for int8_t" >&5
+echo $ECHO_N "checking for int8_t... $ECHO_C" >&6; }
+if test "${ac_cv_c_int8_t+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_c_int8_t=no
+     for ac_type in 'int8_t' 'int' 'long int' \
+	 'long long int' 'short int' 'signed char'; do
+       cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(0 < ($ac_type) (((($ac_type) 1 << (8 - 2)) - 1) * 2 + 1))];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(($ac_type) (((($ac_type) 1 << (8 - 2)) - 1) * 2 + 1)
+	         < ($ac_type) (((($ac_type) 1 << (8 - 2)) - 1) * 2 + 2))];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	case $ac_type in
+  int8_t) ac_cv_c_int8_t=yes ;;
+  *) ac_cv_c_int8_t=$ac_type ;;
+esac
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+       test "$ac_cv_c_int8_t" != no && break
+     done
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_int8_t" >&5
+echo "${ECHO_T}$ac_cv_c_int8_t" >&6; }
+  case $ac_cv_c_int8_t in #(
+  no|yes) ;; #(
+  *)
+
+cat >>confdefs.h <<_ACEOF
+#define int8_t $ac_cv_c_int8_t
+_ACEOF
+;;
+  esac
+
+
+  { echo "$as_me:$LINENO: checking for int16_t" >&5
+echo $ECHO_N "checking for int16_t... $ECHO_C" >&6; }
+if test "${ac_cv_c_int16_t+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_c_int16_t=no
+     for ac_type in 'int16_t' 'int' 'long int' \
+	 'long long int' 'short int' 'signed char'; do
+       cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(0 < ($ac_type) (((($ac_type) 1 << (16 - 2)) - 1) * 2 + 1))];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(($ac_type) (((($ac_type) 1 << (16 - 2)) - 1) * 2 + 1)
+	         < ($ac_type) (((($ac_type) 1 << (16 - 2)) - 1) * 2 + 2))];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	case $ac_type in
+  int16_t) ac_cv_c_int16_t=yes ;;
+  *) ac_cv_c_int16_t=$ac_type ;;
+esac
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+       test "$ac_cv_c_int16_t" != no && break
+     done
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_int16_t" >&5
+echo "${ECHO_T}$ac_cv_c_int16_t" >&6; }
+  case $ac_cv_c_int16_t in #(
+  no|yes) ;; #(
+  *)
+
+cat >>confdefs.h <<_ACEOF
+#define int16_t $ac_cv_c_int16_t
+_ACEOF
+;;
+  esac
+
+
+  { echo "$as_me:$LINENO: checking for int32_t" >&5
+echo $ECHO_N "checking for int32_t... $ECHO_C" >&6; }
+if test "${ac_cv_c_int32_t+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_c_int32_t=no
+     for ac_type in 'int32_t' 'int' 'long int' \
+	 'long long int' 'short int' 'signed char'; do
+       cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(0 < ($ac_type) (((($ac_type) 1 << (32 - 2)) - 1) * 2 + 1))];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(($ac_type) (((($ac_type) 1 << (32 - 2)) - 1) * 2 + 1)
+	         < ($ac_type) (((($ac_type) 1 << (32 - 2)) - 1) * 2 + 2))];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	case $ac_type in
+  int32_t) ac_cv_c_int32_t=yes ;;
+  *) ac_cv_c_int32_t=$ac_type ;;
+esac
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+       test "$ac_cv_c_int32_t" != no && break
+     done
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_int32_t" >&5
+echo "${ECHO_T}$ac_cv_c_int32_t" >&6; }
+  case $ac_cv_c_int32_t in #(
+  no|yes) ;; #(
+  *)
+
+cat >>confdefs.h <<_ACEOF
+#define int32_t $ac_cv_c_int32_t
+_ACEOF
+;;
+  esac
+
+
+  { echo "$as_me:$LINENO: checking for uint8_t" >&5
+echo $ECHO_N "checking for uint8_t... $ECHO_C" >&6; }
+if test "${ac_cv_c_uint8_t+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_c_uint8_t=no
+     for ac_type in 'uint8_t' 'unsigned int' 'unsigned long int' \
+	 'unsigned long long int' 'unsigned short int' 'unsigned char'; do
+       cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(($ac_type) -1 >> (8 - 1) == 1)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  case $ac_type in
+  uint8_t) ac_cv_c_uint8_t=yes ;;
+  *) ac_cv_c_uint8_t=$ac_type ;;
+esac
+
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+       test "$ac_cv_c_uint8_t" != no && break
+     done
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_uint8_t" >&5
+echo "${ECHO_T}$ac_cv_c_uint8_t" >&6; }
+  case $ac_cv_c_uint8_t in #(
+  no|yes) ;; #(
+  *)
+
+cat >>confdefs.h <<\_ACEOF
+#define _UINT8_T 1
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define uint8_t $ac_cv_c_uint8_t
+_ACEOF
+;;
+  esac
+
+
+  { echo "$as_me:$LINENO: checking for uint16_t" >&5
+echo $ECHO_N "checking for uint16_t... $ECHO_C" >&6; }
+if test "${ac_cv_c_uint16_t+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_c_uint16_t=no
+     for ac_type in 'uint16_t' 'unsigned int' 'unsigned long int' \
+	 'unsigned long long int' 'unsigned short int' 'unsigned char'; do
+       cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(($ac_type) -1 >> (16 - 1) == 1)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  case $ac_type in
+  uint16_t) ac_cv_c_uint16_t=yes ;;
+  *) ac_cv_c_uint16_t=$ac_type ;;
+esac
+
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+       test "$ac_cv_c_uint16_t" != no && break
+     done
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_uint16_t" >&5
+echo "${ECHO_T}$ac_cv_c_uint16_t" >&6; }
+  case $ac_cv_c_uint16_t in #(
+  no|yes) ;; #(
+  *)
+
+
+cat >>confdefs.h <<_ACEOF
+#define uint16_t $ac_cv_c_uint16_t
+_ACEOF
+;;
+  esac
+
+
+  { echo "$as_me:$LINENO: checking for uint32_t" >&5
+echo $ECHO_N "checking for uint32_t... $ECHO_C" >&6; }
+if test "${ac_cv_c_uint32_t+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_c_uint32_t=no
+     for ac_type in 'uint32_t' 'unsigned int' 'unsigned long int' \
+	 'unsigned long long int' 'unsigned short int' 'unsigned char'; do
+       cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(($ac_type) -1 >> (32 - 1) == 1)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  case $ac_type in
+  uint32_t) ac_cv_c_uint32_t=yes ;;
+  *) ac_cv_c_uint32_t=$ac_type ;;
+esac
+
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+       test "$ac_cv_c_uint32_t" != no && break
+     done
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_uint32_t" >&5
+echo "${ECHO_T}$ac_cv_c_uint32_t" >&6; }
+  case $ac_cv_c_uint32_t in #(
+  no|yes) ;; #(
+  *)
+
+cat >>confdefs.h <<\_ACEOF
+#define _UINT32_T 1
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define uint32_t $ac_cv_c_uint32_t
+_ACEOF
+;;
+  esac
+
+
+# Check for ANSI C headers.
+{ echo "$as_me:$LINENO: checking for ANSI C header files" >&5
+echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6; }
+if test "${ac_cv_header_stdc+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_header_stdc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	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 >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <string.h>
+
+_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 -r conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+
+_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 -r 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 >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ctype.h>
+#include <stdlib.h>
+#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
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
+echo "${ECHO_T}$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define STDC_HEADERS 1
+_ACEOF
+
+fi
+
+
+
+
+
+
+
+
+
+
+
+for ac_header in ctype.h errno.h limits.h locale.h math.h setjmp.h stdarg.h \
+                  stdio.h stdlib.h string.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+    ( cat <<\_ASBOX
+## ------------------------------------ ##
+## Report this to mark at calabretta.id.au ##
+## ------------------------------------ ##
+_ASBOX
+     ) | sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+if test "x$ac_cv_header_stdc" = xno; then
+  { { echo "$as_me:$LINENO: error:
+    -------------------------------------------------------------------
+    An ANSI standard C library is required to build WCSLIB.  One of the
+    ANSI C header files it requires is missing or unusable.
+
+    ERROR: WCSLIB configuration failure.
+    -------------------------------------------------------------------" >&5
+echo "$as_me: error:
+    -------------------------------------------------------------------
+    An ANSI standard C library is required to build WCSLIB.  One of the
+    ANSI C header files it requires is missing or unusable.
+
+    ERROR: WCSLIB configuration failure.
+    -------------------------------------------------------------------" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+# Checks for ANSI C library functions (suggested by autoscan - fseeko and
+# stat are only required by fitshdr).
+
+{ echo "$as_me:$LINENO: checking for floor in -lm" >&5
+echo $ECHO_N "checking for floor in -lm... $ECHO_C" >&6; }
+if test "${ac_cv_lib_m_floor+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lm  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* 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 floor ();
+int
+main ()
+{
+return floor ();
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_m_floor=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_lib_m_floor=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_m_floor" >&5
+echo "${ECHO_T}$ac_cv_lib_m_floor" >&6; }
+if test $ac_cv_lib_m_floor = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBM 1
+_ACEOF
+
+  LIBS="-lm $LIBS"
+
+fi
+
+{ echo "$as_me:$LINENO: checking for _LARGEFILE_SOURCE value needed for large files" >&5
+echo $ECHO_N "checking for _LARGEFILE_SOURCE value needed for large files... $ECHO_C" >&6; }
+if test "${ac_cv_sys_largefile_source+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  while :; do
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdio.h>
+int
+main ()
+{
+return fseeko (stdin, 0, 0) && (fseeko) (stdin, 0, 0);
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_sys_largefile_source=no; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#define _LARGEFILE_SOURCE 1
+#include <stdio.h>
+int
+main ()
+{
+return fseeko (stdin, 0, 0) && (fseeko) (stdin, 0, 0);
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_sys_largefile_source=1; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+  ac_cv_sys_largefile_source=unknown
+  break
+done
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_sys_largefile_source" >&5
+echo "${ECHO_T}$ac_cv_sys_largefile_source" >&6; }
+case $ac_cv_sys_largefile_source in #(
+  no | unknown) ;;
+  *)
+cat >>confdefs.h <<_ACEOF
+#define _LARGEFILE_SOURCE $ac_cv_sys_largefile_source
+_ACEOF
+;;
+esac
+rm -f -r conftest*
+
+# We used to try defining _XOPEN_SOURCE=500 too, to work around a bug
+# in glibc 2.1.3, but that breaks too many other things.
+# If you want fseeko and ftello with glibc, upgrade to a fixed glibc.
+if test $ac_cv_sys_largefile_source != unknown; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_FSEEKO 1
+_ACEOF
+
+fi
+
+
+for ac_header in stdlib.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+    ( cat <<\_ASBOX
+## ------------------------------------ ##
+## Report this to mark at calabretta.id.au ##
+## ------------------------------------ ##
+_ASBOX
+     ) | sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+{ echo "$as_me:$LINENO: checking for GNU libc compatible malloc" >&5
+echo $ECHO_N "checking for GNU libc compatible malloc... $ECHO_C" >&6; }
+if test "${ac_cv_func_malloc_0_nonnull+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "$cross_compiling" = yes; then
+  ac_cv_func_malloc_0_nonnull=no
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#if defined STDC_HEADERS || defined HAVE_STDLIB_H
+# include <stdlib.h>
+#else
+char *malloc ();
+#endif
+
+int
+main ()
+{
+return ! malloc (0);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func_malloc_0_nonnull=yes
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_func_malloc_0_nonnull=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_malloc_0_nonnull" >&5
+echo "${ECHO_T}$ac_cv_func_malloc_0_nonnull" >&6; }
+if test $ac_cv_func_malloc_0_nonnull = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_MALLOC 1
+_ACEOF
+
+else
+  cat >>confdefs.h <<\_ACEOF
+#define HAVE_MALLOC 0
+_ACEOF
+
+   case " $LIBOBJS " in
+  *" malloc.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS malloc.$ac_objext"
+ ;;
+esac
+
+
+cat >>confdefs.h <<\_ACEOF
+#define malloc rpl_malloc
+_ACEOF
+
+fi
+
+
+
+
+for ac_header in stdlib.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+    ( cat <<\_ASBOX
+## ------------------------------------ ##
+## Report this to mark at calabretta.id.au ##
+## ------------------------------------ ##
+_ASBOX
+     ) | sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+{ echo "$as_me:$LINENO: checking for GNU libc compatible realloc" >&5
+echo $ECHO_N "checking for GNU libc compatible realloc... $ECHO_C" >&6; }
+if test "${ac_cv_func_realloc_0_nonnull+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "$cross_compiling" = yes; then
+  ac_cv_func_realloc_0_nonnull=no
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#if defined STDC_HEADERS || defined HAVE_STDLIB_H
+# include <stdlib.h>
+#else
+char *realloc ();
+#endif
+
+int
+main ()
+{
+return ! realloc (0, 0);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func_realloc_0_nonnull=yes
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_func_realloc_0_nonnull=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_realloc_0_nonnull" >&5
+echo "${ECHO_T}$ac_cv_func_realloc_0_nonnull" >&6; }
+if test $ac_cv_func_realloc_0_nonnull = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_REALLOC 1
+_ACEOF
+
+else
+  cat >>confdefs.h <<\_ACEOF
+#define HAVE_REALLOC 0
+_ACEOF
+
+   case " $LIBOBJS " in
+  *" realloc.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS realloc.$ac_objext"
+ ;;
+esac
+
+
+cat >>confdefs.h <<\_ACEOF
+#define realloc rpl_realloc
+_ACEOF
+
+fi
+
+
+
+{ echo "$as_me:$LINENO: checking for function prototypes" >&5
+echo $ECHO_N "checking for function prototypes... $ECHO_C" >&6; }
+if test "$ac_cv_prog_cc_c89" != no; then
+  { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+
+cat >>confdefs.h <<\_ACEOF
+#define PROTOTYPES 1
+_ACEOF
+
+
+cat >>confdefs.h <<\_ACEOF
+#define __PROTOTYPES 1
+_ACEOF
+
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+{ echo "$as_me:$LINENO: checking whether setvbuf arguments are reversed" >&5
+echo $ECHO_N "checking whether setvbuf arguments are reversed... $ECHO_C" >&6; }
+if test "${ac_cv_func_setvbuf_reversed+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_func_setvbuf_reversed=no
+   cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdio.h>
+#	  ifdef PROTOTYPES
+	   int (setvbuf) (FILE *, int, char *, size_t);
+#	  endif
+int
+main ()
+{
+char buf; return setvbuf (stdout, _IOLBF, &buf, 1);
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdio.h>
+#	     ifdef PROTOTYPES
+	      int (setvbuf) (FILE *, int, char *, size_t);
+#	     endif
+int
+main ()
+{
+char buf; return setvbuf (stdout, &buf, _IOLBF, 1);
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  # It compiles and links either way, so it must not be declared
+	 # with a prototype and most likely this is a K&R C compiler.
+	 # Try running it.
+	 if test "$cross_compiling" = yes; then
+  : # Assume setvbuf is not reversed when cross-compiling.
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+/* This call has the arguments reversed.
+		   A reversed system may check and see that the address of buf
+		   is not _IOLBF, _IONBF, or _IOFBF, and return nonzero.  */
+		char buf;
+		if (setvbuf (stdout, _IOLBF, &buf, 1) != 0)
+		  return 1;
+		putchar ('\r');
+		return 0; /* Non-reversed systems SEGV here.  */
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func_setvbuf_reversed=yes
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+	ac_cv_func_setvbuf_reversed=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_setvbuf_reversed" >&5
+echo "${ECHO_T}$ac_cv_func_setvbuf_reversed" >&6; }
+if test $ac_cv_func_setvbuf_reversed = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define SETVBUF_REVERSED 1
+_ACEOF
+
+fi
+
+{ echo "$as_me:$LINENO: checking whether lstat dereferences a symlink specified with a trailing slash" >&5
+echo $ECHO_N "checking whether lstat dereferences a symlink specified with a trailing slash... $ECHO_C" >&6; }
+if test "${ac_cv_func_lstat_dereferences_slashed_symlink+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  rm -f conftest.sym conftest.file
+echo >conftest.file
+if test "$as_ln_s" = "ln -s" && ln -s conftest.file conftest.sym; then
+  if test "$cross_compiling" = yes; then
+  ac_cv_func_lstat_dereferences_slashed_symlink=no
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+struct stat sbuf;
+     /* Linux will dereference the symlink and fail.
+	That is better in the sense that it means we will not
+	have to compile and use the lstat wrapper.  */
+     return lstat ("conftest.sym/", &sbuf) == 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func_lstat_dereferences_slashed_symlink=yes
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_func_lstat_dereferences_slashed_symlink=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+else
+  # If the `ln -s' command failed, then we probably don't even
+  # have an lstat function.
+  ac_cv_func_lstat_dereferences_slashed_symlink=no
+fi
+rm -f conftest.sym conftest.file
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_lstat_dereferences_slashed_symlink" >&5
+echo "${ECHO_T}$ac_cv_func_lstat_dereferences_slashed_symlink" >&6; }
+
+test $ac_cv_func_lstat_dereferences_slashed_symlink = yes &&
+
+cat >>confdefs.h <<_ACEOF
+#define LSTAT_FOLLOWS_SLASHED_SYMLINK 1
+_ACEOF
+
+
+if test $ac_cv_func_lstat_dereferences_slashed_symlink = no; then
+  case " $LIBOBJS " in
+  *" lstat.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS lstat.$ac_objext"
+ ;;
+esac
+
+fi
+
+{ echo "$as_me:$LINENO: checking whether stat accepts an empty string" >&5
+echo $ECHO_N "checking whether stat accepts an empty string... $ECHO_C" >&6; }
+if test "${ac_cv_func_stat_empty_string_bug+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "$cross_compiling" = yes; then
+  ac_cv_func_stat_empty_string_bug=yes
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+struct stat sbuf;
+  return stat ("", &sbuf) == 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func_stat_empty_string_bug=no
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_func_stat_empty_string_bug=yes
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_stat_empty_string_bug" >&5
+echo "${ECHO_T}$ac_cv_func_stat_empty_string_bug" >&6; }
+if test $ac_cv_func_stat_empty_string_bug = yes; then
+  case " $LIBOBJS " in
+  *" stat.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS stat.$ac_objext"
+ ;;
+esac
+
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STAT_EMPTY_STRING_BUG 1
+_ACEOF
+
+fi
+
+
+for ac_func in vprintf
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
+if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* 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 $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_$ac_func || defined __stub___$ac_func
+choke me
+#endif
+
+int
+main ()
+{
+return $ac_func ();
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	eval "$as_ac_var=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_var'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+{ echo "$as_me:$LINENO: checking for _doprnt" >&5
+echo $ECHO_N "checking for _doprnt... $ECHO_C" >&6; }
+if test "${ac_cv_func__doprnt+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define _doprnt to an innocuous variant, in case <limits.h> declares _doprnt.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define _doprnt innocuous__doprnt
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char _doprnt (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef _doprnt
+
+/* 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 _doprnt ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub__doprnt || defined __stub____doprnt
+choke me
+#endif
+
+int
+main ()
+{
+return _doprnt ();
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_func__doprnt=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_func__doprnt=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func__doprnt" >&5
+echo "${ECHO_T}$ac_cv_func__doprnt" >&6; }
+if test $ac_cv_func__doprnt = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_DOPRNT 1
+_ACEOF
+
+fi
+
+fi
+done
+
+
+
+
+
+
+
+
+
+for ac_func in floor memset pow setlocale sqrt strchr strstr
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
+if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* 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 $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_$ac_func || defined __stub___$ac_func
+choke me
+#endif
+
+int
+main ()
+{
+return $ac_func ();
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	eval "$as_ac_var=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_var'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+# System libraries that may be required by WCSLIB itself.
+# SunOS, extra maths functions.
+{ echo "$as_me:$LINENO: checking for cosd in -lsunmath" >&5
+echo $ECHO_N "checking for cosd in -lsunmath... $ECHO_C" >&6; }
+if test "${ac_cv_lib_sunmath_cosd+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsunmath  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* 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 cosd ();
+int
+main ()
+{
+return cosd ();
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_sunmath_cosd=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_lib_sunmath_cosd=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_sunmath_cosd" >&5
+echo "${ECHO_T}$ac_cv_lib_sunmath_cosd" >&6; }
+if test $ac_cv_lib_sunmath_cosd = yes; then
+  LIBS="-lsunmath $LIBS"
+fi
+
+
+# See if we can find sincos().
+
+for ac_func in sincos
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
+if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* 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 $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_$ac_func || defined __stub___$ac_func
+choke me
+#endif
+
+int
+main ()
+{
+return $ac_func ();
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	eval "$as_ac_var=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_var'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+# Check the size and availability of integer data types.
+{ echo "$as_me:$LINENO: checking for int" >&5
+echo $ECHO_N "checking for int... $ECHO_C" >&6; }
+if test "${ac_cv_type_int+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+typedef int ac__type_new_;
+int
+main ()
+{
+if ((ac__type_new_ *) 0)
+  return 0;
+if (sizeof (ac__type_new_))
+  return 0;
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_type_int=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_type_int=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_type_int" >&5
+echo "${ECHO_T}$ac_cv_type_int" >&6; }
+
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ echo "$as_me:$LINENO: checking size of int" >&5
+echo $ECHO_N "checking size of int... $ECHO_C" >&6; }
+if test "${ac_cv_sizeof_int+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "$cross_compiling" = yes; then
+  # Depending upon the size, compute the lo and hi bounds.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+   typedef int ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= 0)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_lo=0 ac_mid=0
+  while :; do
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+   typedef int ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_hi=$ac_mid; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_lo=`expr $ac_mid + 1`
+			if test $ac_lo -le $ac_mid; then
+			  ac_lo= ac_hi=
+			  break
+			fi
+			ac_mid=`expr 2 '*' $ac_mid + 1`
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+   typedef int ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) < 0)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_hi=-1 ac_mid=-1
+  while :; do
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+   typedef int ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_lo=$ac_mid; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_hi=`expr '(' $ac_mid ')' - 1`
+			if test $ac_mid -le $ac_hi; then
+			  ac_lo= ac_hi=
+			  break
+			fi
+			ac_mid=`expr 2 '*' $ac_mid`
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_lo= ac_hi=
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+# Binary search between lo and hi bounds.
+while test "x$ac_lo" != "x$ac_hi"; do
+  ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo`
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+   typedef int ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_hi=$ac_mid
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_lo=`expr '(' $ac_mid ')' + 1`
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+case $ac_lo in
+?*) ac_cv_sizeof_int=$ac_lo;;
+'') if test "$ac_cv_type_int" = yes; then
+     { { echo "$as_me:$LINENO: error: cannot compute sizeof (int)
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (int)
+See \`config.log' for more details." >&2;}
+   { (exit 77); exit 77; }; }
+   else
+     ac_cv_sizeof_int=0
+   fi ;;
+esac
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+   typedef int ac__type_sizeof_;
+static long int longval () { return (long int) (sizeof (ac__type_sizeof_)); }
+static unsigned long int ulongval () { return (long int) (sizeof (ac__type_sizeof_)); }
+#include <stdio.h>
+#include <stdlib.h>
+int
+main ()
+{
+
+  FILE *f = fopen ("conftest.val", "w");
+  if (! f)
+    return 1;
+  if (((long int) (sizeof (ac__type_sizeof_))) < 0)
+    {
+      long int i = longval ();
+      if (i != ((long int) (sizeof (ac__type_sizeof_))))
+	return 1;
+      fprintf (f, "%ld\n", i);
+    }
+  else
+    {
+      unsigned long int i = ulongval ();
+      if (i != ((long int) (sizeof (ac__type_sizeof_))))
+	return 1;
+      fprintf (f, "%lu\n", i);
+    }
+  return ferror (f) || fclose (f) != 0;
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_sizeof_int=`cat conftest.val`
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+if test "$ac_cv_type_int" = yes; then
+     { { echo "$as_me:$LINENO: error: cannot compute sizeof (int)
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (int)
+See \`config.log' for more details." >&2;}
+   { (exit 77); exit 77; }; }
+   else
+     ac_cv_sizeof_int=0
+   fi
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f conftest.val
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_sizeof_int" >&5
+echo "${ECHO_T}$ac_cv_sizeof_int" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_INT $ac_cv_sizeof_int
+_ACEOF
+
+
+{ echo "$as_me:$LINENO: checking for long int" >&5
+echo $ECHO_N "checking for long int... $ECHO_C" >&6; }
+if test "${ac_cv_type_long_int+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+typedef long int ac__type_new_;
+int
+main ()
+{
+if ((ac__type_new_ *) 0)
+  return 0;
+if (sizeof (ac__type_new_))
+  return 0;
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_type_long_int=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_type_long_int=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_type_long_int" >&5
+echo "${ECHO_T}$ac_cv_type_long_int" >&6; }
+
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ echo "$as_me:$LINENO: checking size of long int" >&5
+echo $ECHO_N "checking size of long int... $ECHO_C" >&6; }
+if test "${ac_cv_sizeof_long_int+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "$cross_compiling" = yes; then
+  # Depending upon the size, compute the lo and hi bounds.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+   typedef long int ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= 0)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_lo=0 ac_mid=0
+  while :; do
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+   typedef long int ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_hi=$ac_mid; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_lo=`expr $ac_mid + 1`
+			if test $ac_lo -le $ac_mid; then
+			  ac_lo= ac_hi=
+			  break
+			fi
+			ac_mid=`expr 2 '*' $ac_mid + 1`
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+   typedef long int ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) < 0)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_hi=-1 ac_mid=-1
+  while :; do
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+   typedef long int ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_lo=$ac_mid; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_hi=`expr '(' $ac_mid ')' - 1`
+			if test $ac_mid -le $ac_hi; then
+			  ac_lo= ac_hi=
+			  break
+			fi
+			ac_mid=`expr 2 '*' $ac_mid`
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_lo= ac_hi=
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+# Binary search between lo and hi bounds.
+while test "x$ac_lo" != "x$ac_hi"; do
+  ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo`
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+   typedef long int ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_hi=$ac_mid
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_lo=`expr '(' $ac_mid ')' + 1`
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+case $ac_lo in
+?*) ac_cv_sizeof_long_int=$ac_lo;;
+'') if test "$ac_cv_type_long_int" = yes; then
+     { { echo "$as_me:$LINENO: error: cannot compute sizeof (long int)
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (long int)
+See \`config.log' for more details." >&2;}
+   { (exit 77); exit 77; }; }
+   else
+     ac_cv_sizeof_long_int=0
+   fi ;;
+esac
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+   typedef long int ac__type_sizeof_;
+static long int longval () { return (long int) (sizeof (ac__type_sizeof_)); }
+static unsigned long int ulongval () { return (long int) (sizeof (ac__type_sizeof_)); }
+#include <stdio.h>
+#include <stdlib.h>
+int
+main ()
+{
+
+  FILE *f = fopen ("conftest.val", "w");
+  if (! f)
+    return 1;
+  if (((long int) (sizeof (ac__type_sizeof_))) < 0)
+    {
+      long int i = longval ();
+      if (i != ((long int) (sizeof (ac__type_sizeof_))))
+	return 1;
+      fprintf (f, "%ld\n", i);
+    }
+  else
+    {
+      unsigned long int i = ulongval ();
+      if (i != ((long int) (sizeof (ac__type_sizeof_))))
+	return 1;
+      fprintf (f, "%lu\n", i);
+    }
+  return ferror (f) || fclose (f) != 0;
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_sizeof_long_int=`cat conftest.val`
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+if test "$ac_cv_type_long_int" = yes; then
+     { { echo "$as_me:$LINENO: error: cannot compute sizeof (long int)
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (long int)
+See \`config.log' for more details." >&2;}
+   { (exit 77); exit 77; }; }
+   else
+     ac_cv_sizeof_long_int=0
+   fi
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f conftest.val
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_sizeof_long_int" >&5
+echo "${ECHO_T}$ac_cv_sizeof_long_int" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_LONG_INT $ac_cv_sizeof_long_int
+_ACEOF
+
+
+{ echo "$as_me:$LINENO: checking for long long int" >&5
+echo $ECHO_N "checking for long long int... $ECHO_C" >&6; }
+if test "${ac_cv_type_long_long_int+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+typedef long long int ac__type_new_;
+int
+main ()
+{
+if ((ac__type_new_ *) 0)
+  return 0;
+if (sizeof (ac__type_new_))
+  return 0;
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_type_long_long_int=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_type_long_long_int=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_type_long_long_int" >&5
+echo "${ECHO_T}$ac_cv_type_long_long_int" >&6; }
+
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ echo "$as_me:$LINENO: checking size of long long int" >&5
+echo $ECHO_N "checking size of long long int... $ECHO_C" >&6; }
+if test "${ac_cv_sizeof_long_long_int+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "$cross_compiling" = yes; then
+  # Depending upon the size, compute the lo and hi bounds.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+   typedef long long int ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= 0)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_lo=0 ac_mid=0
+  while :; do
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+   typedef long long int ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_hi=$ac_mid; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_lo=`expr $ac_mid + 1`
+			if test $ac_lo -le $ac_mid; then
+			  ac_lo= ac_hi=
+			  break
+			fi
+			ac_mid=`expr 2 '*' $ac_mid + 1`
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+   typedef long long int ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) < 0)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_hi=-1 ac_mid=-1
+  while :; do
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+   typedef long long int ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_lo=$ac_mid; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_hi=`expr '(' $ac_mid ')' - 1`
+			if test $ac_mid -le $ac_hi; then
+			  ac_lo= ac_hi=
+			  break
+			fi
+			ac_mid=`expr 2 '*' $ac_mid`
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_lo= ac_hi=
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+# Binary search between lo and hi bounds.
+while test "x$ac_lo" != "x$ac_hi"; do
+  ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo`
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+   typedef long long int ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_hi=$ac_mid
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_lo=`expr '(' $ac_mid ')' + 1`
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+case $ac_lo in
+?*) ac_cv_sizeof_long_long_int=$ac_lo;;
+'') if test "$ac_cv_type_long_long_int" = yes; then
+     { { echo "$as_me:$LINENO: error: cannot compute sizeof (long long int)
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (long long int)
+See \`config.log' for more details." >&2;}
+   { (exit 77); exit 77; }; }
+   else
+     ac_cv_sizeof_long_long_int=0
+   fi ;;
+esac
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+   typedef long long int ac__type_sizeof_;
+static long int longval () { return (long int) (sizeof (ac__type_sizeof_)); }
+static unsigned long int ulongval () { return (long int) (sizeof (ac__type_sizeof_)); }
+#include <stdio.h>
+#include <stdlib.h>
+int
+main ()
+{
+
+  FILE *f = fopen ("conftest.val", "w");
+  if (! f)
+    return 1;
+  if (((long int) (sizeof (ac__type_sizeof_))) < 0)
+    {
+      long int i = longval ();
+      if (i != ((long int) (sizeof (ac__type_sizeof_))))
+	return 1;
+      fprintf (f, "%ld\n", i);
+    }
+  else
+    {
+      unsigned long int i = ulongval ();
+      if (i != ((long int) (sizeof (ac__type_sizeof_))))
+	return 1;
+      fprintf (f, "%lu\n", i);
+    }
+  return ferror (f) || fclose (f) != 0;
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_sizeof_long_long_int=`cat conftest.val`
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+if test "$ac_cv_type_long_long_int" = yes; then
+     { { echo "$as_me:$LINENO: error: cannot compute sizeof (long long int)
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (long long int)
+See \`config.log' for more details." >&2;}
+   { (exit 77); exit 77; }; }
+   else
+     ac_cv_sizeof_long_long_int=0
+   fi
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f conftest.val
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_sizeof_long_long_int" >&5
+echo "${ECHO_T}$ac_cv_sizeof_long_long_int" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_LONG_LONG_INT $ac_cv_sizeof_long_long_int
+_ACEOF
+
+
+
+# 64-bit integer data type; use long long int preferentially since that
+# accords with "%lld" formatting used in fitshdr.l, e.g.
+#                int   size_t  long int  long long int
+#                ---   ------  --------  -------------
+#   gcc x86:      32     32       32          64
+#   gcc x86_64:   32     64       64          64
+if test "x$ac_cv_sizeof_long_long_int" = x8; then
+
+cat >>confdefs.h <<\_ACEOF
+#define WCSLIB_INT64 long long int
+_ACEOF
+
+elif test "x$ac_cv_sizeof_long_int" = x8; then
+
+cat >>confdefs.h <<\_ACEOF
+#define WCSLIB_INT64 long int
+_ACEOF
+
+elif test "x$ac_cv_sizeof_int" = x8; then
+
+cat >>confdefs.h <<\_ACEOF
+#define WCSLIB_INT64 int
+_ACEOF
+
+fi
+
+# Does printf() have the z modifier for size_t type?  Important for 64-bit.
+{ echo "$as_me:$LINENO: checking for printf z format modifier for size_t type" >&5
+echo $ECHO_N "checking for printf z format modifier for size_t type... $ECHO_C" >&6; }
+if test "$cross_compiling" = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define MODZ ""
+_ACEOF
+
+    { echo "$as_me:$LINENO: result: assumed not" >&5
+echo "${ECHO_T}assumed not" >&6; }
+
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+char buf[64];
+                     if (sprintf(buf, "%zu", (size_t)1) != 1)
+                       return 1;
+                     else if (strcmp(buf, "1"))
+                       return 2;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+
+cat >>confdefs.h <<\_ACEOF
+#define MODZ "z"
+_ACEOF
+
+    { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+
+cat >>confdefs.h <<\_ACEOF
+#define MODZ ""
+_ACEOF
+
+    { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+
+
+# Starting values, may be augmented later.
+SUBDIRS="C"
+TSTDIRS="C"
+INSTDIR="C"
+
+
+# Ways of specifying the Fortran compiler, in order of precedence:
+#   configure --enable-fortran=<compiler>
+#   F77=<compiler> configure    ...bash
+#
+# Ways of disabling Fortran:
+#   configure --disable-fortran
+#   configure --enable-fortran=no
+#   F77=no configure            ...bash
+# Check whether --enable-fortran was given.
+if test "${enable_fortran+set}" = set; then
+  enableval=$enable_fortran;
+fi
+
+# Check whether --enable-fortran was given.
+if test "${enable_fortran+set}" = set; then
+  enableval=$enable_fortran;
+fi
+
+if test "x$enable_fortran" != x -a "x$enable_fortran" != xyes ; then
+  F77="$enable_fortran"
+fi
+
+if test "x$F77" = xno ; then
+  F77=
+
+  { echo "$as_me:$LINENO: WARNING: Compilation of Fortran wrappers and PGSBOX disabled" >&5
+echo "$as_me: WARNING: Compilation of Fortran wrappers and PGSBOX disabled" >&2;}
+
+else
+  if test "x$F77" = x ; then
+    # Look for a Fortran compiler.
+    ac_ext=f
+ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5'
+ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_f77_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  for ac_prog in gfortran g77 f77 ifort xlf frt pgf77 fl32 af77 fort77 f90 \
+                 xlf90 pgf90 epcf90 f95 fort xlf95 lf95 g95
+  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
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_F77+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$F77"; then
+  ac_cv_prog_F77="$F77" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_F77="$ac_tool_prefix$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+F77=$ac_cv_prog_F77
+if test -n "$F77"; then
+  { echo "$as_me:$LINENO: result: $F77" >&5
+echo "${ECHO_T}$F77" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+    test -n "$F77" && break
+  done
+fi
+if test -z "$F77"; then
+  ac_ct_F77=$F77
+  for ac_prog in gfortran g77 f77 ifort xlf frt pgf77 fl32 af77 fort77 f90 \
+                 xlf90 pgf90 epcf90 f95 fort xlf95 lf95 g95
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_F77+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_F77"; then
+  ac_cv_prog_ac_ct_F77="$ac_ct_F77" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_F77="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_F77=$ac_cv_prog_ac_ct_F77
+if test -n "$ac_ct_F77"; then
+  { echo "$as_me:$LINENO: result: $ac_ct_F77" >&5
+echo "${ECHO_T}$ac_ct_F77" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+  test -n "$ac_ct_F77" && break
+done
+
+  if test "x$ac_ct_F77" = x; then
+    F77=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf at gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf at gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+    F77=$ac_ct_F77
+  fi
+fi
+
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO: checking for Fortran 77 compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (ac_try="$ac_compiler --version >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compiler --version >&5") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (ac_try="$ac_compiler -v >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compiler -v >&5") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (ac_try="$ac_compiler -V >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compiler -V >&5") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+rm -f a.out
+
+# If we don't use `.F' as extension, the preprocessor is not run on the
+# input file.  (Note that this only needs to work for GNU compilers.)
+ac_save_ext=$ac_ext
+ac_ext=F
+{ echo "$as_me:$LINENO: checking whether we are using the GNU Fortran 77 compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU Fortran 77 compiler... $ECHO_C" >&6; }
+if test "${ac_cv_f77_compiler_gnu+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+      program main
+#ifndef __GNUC__
+       choke me
+#endif
+
+      end
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_f77_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_compiler_gnu=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_compiler_gnu=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_f77_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_f77_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_f77_compiler_gnu" >&6; }
+ac_ext=$ac_save_ext
+ac_test_FFLAGS=${FFLAGS+set}
+ac_save_FFLAGS=$FFLAGS
+FFLAGS=
+{ echo "$as_me:$LINENO: checking whether $F77 accepts -g" >&5
+echo $ECHO_N "checking whether $F77 accepts -g... $ECHO_C" >&6; }
+if test "${ac_cv_prog_f77_g+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  FFLAGS=-g
+cat >conftest.$ac_ext <<_ACEOF
+      program main
+
+      end
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_f77_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_prog_f77_g=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_prog_f77_g=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_prog_f77_g" >&5
+echo "${ECHO_T}$ac_cv_prog_f77_g" >&6; }
+if test "$ac_test_FFLAGS" = set; then
+  FFLAGS=$ac_save_FFLAGS
+elif test $ac_cv_prog_f77_g = yes; then
+  if test "x$ac_cv_f77_compiler_gnu" = xyes; then
+    FFLAGS="-g -O2"
+  else
+    FFLAGS="-g"
+  fi
+else
+  if test "x$ac_cv_f77_compiler_gnu" = xyes; then
+    FFLAGS="-O2"
+  else
+    FFLAGS=
+  fi
+fi
+
+G77=`test $ac_compiler_gnu = yes && echo yes`
+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
+
+  fi
+
+  if test "x$F77" = x; then
+    { echo "$as_me:$LINENO: WARNING:
+      ------------------------------------------------------------------
+      Fortran compiler not found, will skip Fortran wrappers and PGSBOX.
+      ------------------------------------------------------------------" >&5
+echo "$as_me: WARNING:
+      ------------------------------------------------------------------
+      Fortran compiler not found, will skip Fortran wrappers and PGSBOX.
+      ------------------------------------------------------------------" >&2;}
+
+    # Best guess at Fortran name mangling for use if a compiler does ever
+    # become available.
+    cat >>confdefs.h <<\_ACEOF
+#define F77_FUNC(name,NAME) name ## _
+_ACEOF
+
+
+  else
+    if test "x$ac_cv_f77_compiler_gnu" = xyes ; then
+      if test "x$F77" = xg77 -o "x$F77" = xf77 ; then
+        # Not recognized by gfortran.
+        FFLAGS="$FFLAGS -Wno-globals"
+      fi
+    fi
+
+    { echo "$as_me:$LINENO: checking whether $F77 accepts -I" >&5
+echo $ECHO_N "checking whether $F77 accepts -I... $ECHO_C" >&6; }
+    ac_ext=f
+ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5'
+ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_f77_compiler_gnu
+
+    FFLAGS_save=$FFLAGS
+    FFLAGS=-I.
+
+cat >conftest.$ac_ext <<_ACEOF
+      program main
+
+      end
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_f77_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  FFLAGS="$FFLAGS_save -I."; { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	FFLAGS="$FFLAGS_save"; { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+    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
+
+
+    # Libraries required by the Fortran compiler itself (sets FLIBS).
+    # Required by utilities and test programs written in C that link to
+    # Fortran object modules such as pgsbox.
+    ac_ext=f
+ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5'
+ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_f77_compiler_gnu
+{ echo "$as_me:$LINENO: checking how to get verbose linking output from $F77" >&5
+echo $ECHO_N "checking how to get verbose linking output from $F77... $ECHO_C" >&6; }
+if test "${ac_cv_prog_f77_v+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+      program main
+
+      end
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_f77_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_prog_f77_v=
+# Try some options frequently used verbose output
+for ac_verb in -v -verbose --verbose -V -\#\#\#; do
+  cat >conftest.$ac_ext <<_ACEOF
+      program main
+
+      end
+_ACEOF
+
+# Compile and link our simple test program by passing a flag (argument
+# 1 to this macro) to the Fortran compiler in order to get
+# "verbose" output that we can then parse for the Fortran linker
+# flags.
+ac_save_FFLAGS=$FFLAGS
+FFLAGS="$FFLAGS $ac_verb"
+eval "set x $ac_link"
+shift
+echo "$as_me:$LINENO: $*" >&5
+ac_f77_v_output=`eval $ac_link 5>&1 2>&1 | grep -v 'Driving:'`
+echo "$ac_f77_v_output" >&5
+FFLAGS=$ac_save_FFLAGS
+
+rm -f -r conftest*
+
+# On HP/UX there is a line like: "LPATH is: /foo:/bar:/baz" where
+# /foo, /bar, and /baz are search directories for the Fortran linker.
+# Here, we change these into -L/foo -L/bar -L/baz (and put it first):
+ac_f77_v_output="`echo $ac_f77_v_output |
+	grep 'LPATH is:' |
+	sed 's,.*LPATH is\(: *[^ ]*\).*,\1,;s,: */, -L/,g'` $ac_f77_v_output"
+
+# FIXME: we keep getting bitten by quoted arguments; a more general fix
+#        that detects unbalanced quotes in FLIBS should be implemented
+#        and (ugh) tested at some point.
+case $ac_f77_v_output in
+  # If we are using xlf then replace all the commas with spaces.
+  *xlfentry*)
+    ac_f77_v_output=`echo $ac_f77_v_output | sed 's/,/ /g'` ;;
+
+  # With Intel ifc, ignore the quoted -mGLOB_options_string stuff (quoted
+  # $LIBS confuse us, and the libraries appear later in the output anyway).
+  *mGLOB_options_string*)
+    ac_f77_v_output=`echo $ac_f77_v_output | sed 's/"-mGLOB[^"]*"/ /g'` ;;
+
+  # Portland Group compiler has singly- or doubly-quoted -cmdline argument
+  # Singly-quoted arguments were reported for versions 5.2-4 and 6.0-4.
+  # Doubly-quoted arguments were reported for "PGF90/x86 Linux/x86 5.0-2".
+  *-cmdline\ * | *-ignore\ * | *-def\ *)
+    ac_f77_v_output=`echo $ac_f77_v_output | sed "\
+        s/-cmdline  *'[^']*'/ /g; s/-cmdline  *\"[^\"]*\"/ /g
+        s/-ignore  *'[^']*'/ /g; s/-ignore  *\"[^\"]*\"/ /g
+        s/-def  *'[^']*'/ /g; s/-def  *\"[^\"]*\"/ /g"` ;;
+
+  # If we are using Cray Fortran then delete quotes.
+  *cft90*)
+    ac_f77_v_output=`echo $ac_f77_v_output | sed 's/"//g'` ;;
+esac
+
+
+  # look for -l* and *.a constructs in the output
+  for ac_arg in $ac_f77_v_output; do
+     case $ac_arg in
+        [\\/]*.a | ?:[\\/]*.a | -[lLRu]*)
+          ac_cv_prog_f77_v=$ac_verb
+          break 2 ;;
+     esac
+  done
+done
+if test -z "$ac_cv_prog_f77_v"; then
+   { echo "$as_me:$LINENO: WARNING: cannot determine how to obtain linking information from $F77" >&5
+echo "$as_me: WARNING: cannot determine how to obtain linking information from $F77" >&2;}
+fi
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	{ echo "$as_me:$LINENO: WARNING: compilation failed" >&5
+echo "$as_me: WARNING: compilation failed" >&2;}
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_prog_f77_v" >&5
+echo "${ECHO_T}$ac_cv_prog_f77_v" >&6; }
+{ echo "$as_me:$LINENO: checking for Fortran 77 libraries of $F77" >&5
+echo $ECHO_N "checking for Fortran 77 libraries of $F77... $ECHO_C" >&6; }
+if test "${ac_cv_f77_libs+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "x$FLIBS" != "x"; then
+  ac_cv_f77_libs="$FLIBS" # Let the user override the test.
+else
+
+cat >conftest.$ac_ext <<_ACEOF
+      program main
+
+      end
+_ACEOF
+
+# Compile and link our simple test program by passing a flag (argument
+# 1 to this macro) to the Fortran compiler in order to get
+# "verbose" output that we can then parse for the Fortran linker
+# flags.
+ac_save_FFLAGS=$FFLAGS
+FFLAGS="$FFLAGS $ac_cv_prog_f77_v"
+eval "set x $ac_link"
+shift
+echo "$as_me:$LINENO: $*" >&5
+ac_f77_v_output=`eval $ac_link 5>&1 2>&1 | grep -v 'Driving:'`
+echo "$ac_f77_v_output" >&5
+FFLAGS=$ac_save_FFLAGS
+
+rm -f -r conftest*
+
+# On HP/UX there is a line like: "LPATH is: /foo:/bar:/baz" where
+# /foo, /bar, and /baz are search directories for the Fortran linker.
+# Here, we change these into -L/foo -L/bar -L/baz (and put it first):
+ac_f77_v_output="`echo $ac_f77_v_output |
+	grep 'LPATH is:' |
+	sed 's,.*LPATH is\(: *[^ ]*\).*,\1,;s,: */, -L/,g'` $ac_f77_v_output"
+
+# FIXME: we keep getting bitten by quoted arguments; a more general fix
+#        that detects unbalanced quotes in FLIBS should be implemented
+#        and (ugh) tested at some point.
+case $ac_f77_v_output in
+  # If we are using xlf then replace all the commas with spaces.
+  *xlfentry*)
+    ac_f77_v_output=`echo $ac_f77_v_output | sed 's/,/ /g'` ;;
+
+  # With Intel ifc, ignore the quoted -mGLOB_options_string stuff (quoted
+  # $LIBS confuse us, and the libraries appear later in the output anyway).
+  *mGLOB_options_string*)
+    ac_f77_v_output=`echo $ac_f77_v_output | sed 's/"-mGLOB[^"]*"/ /g'` ;;
+
+  # Portland Group compiler has singly- or doubly-quoted -cmdline argument
+  # Singly-quoted arguments were reported for versions 5.2-4 and 6.0-4.
+  # Doubly-quoted arguments were reported for "PGF90/x86 Linux/x86 5.0-2".
+  *-cmdline\ * | *-ignore\ * | *-def\ *)
+    ac_f77_v_output=`echo $ac_f77_v_output | sed "\
+        s/-cmdline  *'[^']*'/ /g; s/-cmdline  *\"[^\"]*\"/ /g
+        s/-ignore  *'[^']*'/ /g; s/-ignore  *\"[^\"]*\"/ /g
+        s/-def  *'[^']*'/ /g; s/-def  *\"[^\"]*\"/ /g"` ;;
+
+  # If we are using Cray Fortran then delete quotes.
+  *cft90*)
+    ac_f77_v_output=`echo $ac_f77_v_output | sed 's/"//g'` ;;
+esac
+
+
+
+ac_cv_f77_libs=
+
+# Save positional arguments (if any)
+ac_save_positional="$@"
+
+set X $ac_f77_v_output
+while test $# != 1; do
+  shift
+  ac_arg=$1
+  case $ac_arg in
+        [\\/]*.a | ?:[\\/]*.a)
+            ac_exists=false
+  for ac_i in $ac_cv_f77_libs; do
+    if test x"$ac_arg" = x"$ac_i"; then
+      ac_exists=true
+      break
+    fi
+  done
+
+  if test x"$ac_exists" = xtrue; then
+  :
+else
+  ac_cv_f77_libs="$ac_cv_f77_libs $ac_arg"
+fi
+
+          ;;
+        -bI:*)
+            ac_exists=false
+  for ac_i in $ac_cv_f77_libs; do
+    if test x"$ac_arg" = x"$ac_i"; then
+      ac_exists=true
+      break
+    fi
+  done
+
+  if test x"$ac_exists" = xtrue; then
+  :
+else
+  if test "$ac_compiler_gnu" = yes; then
+  for ac_link_opt in $ac_arg; do
+    ac_cv_f77_libs="$ac_cv_f77_libs -Xlinker $ac_link_opt"
+  done
+else
+  ac_cv_f77_libs="$ac_cv_f77_libs $ac_arg"
+fi
+fi
+
+          ;;
+          # Ignore these flags.
+        -lang* | -lcrt*.o | -lc | -lgcc* | -lSystem | -libmil | -LANG:=* | -LIST:* | -LNO:*)
+          ;;
+        -lkernel32)
+          test x"$CYGWIN" != xyes && ac_cv_f77_libs="$ac_cv_f77_libs $ac_arg"
+          ;;
+        -[LRuYz])
+          # These flags, when seen by themselves, take an argument.
+          # We remove the space between option and argument and re-iterate
+          # unless we find an empty arg or a new option (starting with -)
+	  case $2 in
+	     "" | -*);;
+	     *)
+		ac_arg="$ac_arg$2"
+		shift; shift
+		set X $ac_arg "$@"
+		;;
+	  esac
+          ;;
+        -YP,*)
+          for ac_j in `echo $ac_arg | sed -e 's/-YP,/-L/;s/:/ -L/g'`; do
+              ac_exists=false
+  for ac_i in $ac_cv_f77_libs; do
+    if test x"$ac_j" = x"$ac_i"; then
+      ac_exists=true
+      break
+    fi
+  done
+
+  if test x"$ac_exists" = xtrue; then
+  :
+else
+  ac_arg="$ac_arg $ac_j"
+                               ac_cv_f77_libs="$ac_cv_f77_libs $ac_j"
+fi
+
+          done
+          ;;
+        -[lLR]*)
+            ac_exists=false
+  for ac_i in $ac_cv_f77_libs; do
+    if test x"$ac_arg" = x"$ac_i"; then
+      ac_exists=true
+      break
+    fi
+  done
+
+  if test x"$ac_exists" = xtrue; then
+  :
+else
+  ac_cv_f77_libs="$ac_cv_f77_libs $ac_arg"
+fi
+
+          ;;
+	-zallextract*| -zdefaultextract)
+	  ac_cv_f77_libs="$ac_cv_f77_libs $ac_arg"
+	  ;;
+          # Ignore everything else.
+  esac
+done
+# restore positional arguments
+set X $ac_save_positional; shift
+
+# We only consider "LD_RUN_PATH" on Solaris systems.  If this is seen,
+# then we insist that the "run path" must be an absolute path (i.e. it
+# must begin with a "/").
+case `(uname -sr) 2>/dev/null` in
+   "SunOS 5"*)
+      ac_ld_run_path=`echo $ac_f77_v_output |
+                        sed -n 's,^.*LD_RUN_PATH *= *\(/[^ ]*\).*$,-R\1,p'`
+      test "x$ac_ld_run_path" != x &&
+        if test "$ac_compiler_gnu" = yes; then
+  for ac_link_opt in $ac_ld_run_path; do
+    ac_cv_f77_libs="$ac_cv_f77_libs -Xlinker $ac_link_opt"
+  done
+else
+  ac_cv_f77_libs="$ac_cv_f77_libs $ac_ld_run_path"
+fi
+      ;;
+esac
+fi # test "x$[]_AC_LANG_PREFIX[]LIBS" = "x"
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_f77_libs" >&5
+echo "${ECHO_T}$ac_cv_f77_libs" >&6; }
+FLIBS="$ac_cv_f77_libs"
+
+
+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
+
+
+    # F77 name mangling (defines the F77_FUNC preprocessor macro).
+    ac_ext=f
+ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5'
+ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_f77_compiler_gnu
+
+{ echo "$as_me:$LINENO: checking for dummy main to link with Fortran 77 libraries" >&5
+echo $ECHO_N "checking for dummy main to link with Fortran 77 libraries... $ECHO_C" >&6; }
+if test "${ac_cv_f77_dummy_main+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_f77_dm_save_LIBS=$LIBS
+ LIBS="$LIBS $FLIBS"
+ ac_fortran_dm_var=F77_DUMMY_MAIN
+ 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
+
+ # First, try linking without a dummy main:
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+#ifdef F77_DUMMY_MAIN
+
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+
+#endif
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_fortran_dummy_main=none
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_fortran_dummy_main=unknown
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+
+ if test $ac_cv_fortran_dummy_main = unknown; then
+   for ac_func in MAIN__ MAIN_ __main MAIN _MAIN __MAIN main_ main__ _main; do
+     cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#define $ac_fortran_dm_var $ac_func
+#ifdef F77_DUMMY_MAIN
+
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+
+#endif
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_fortran_dummy_main=$ac_func; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+   done
+ fi
+ ac_ext=f
+ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5'
+ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_f77_compiler_gnu
+ ac_cv_f77_dummy_main=$ac_cv_fortran_dummy_main
+ rm -f -r conftest*
+ LIBS=$ac_f77_dm_save_LIBS
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_f77_dummy_main" >&5
+echo "${ECHO_T}$ac_cv_f77_dummy_main" >&6; }
+F77_DUMMY_MAIN=$ac_cv_f77_dummy_main
+if test "$F77_DUMMY_MAIN" != unknown; then
+  if test $F77_DUMMY_MAIN != none; then
+
+cat >>confdefs.h <<_ACEOF
+#define F77_DUMMY_MAIN $F77_DUMMY_MAIN
+_ACEOF
+
+  if test "x$ac_cv_fc_dummy_main" = "x$ac_cv_f77_dummy_main"; then
+
+cat >>confdefs.h <<\_ACEOF
+#define FC_DUMMY_MAIN_EQ_F77 1
+_ACEOF
+
+  fi
+fi
+else
+  { { echo "$as_me:$LINENO: error: linking to Fortran libraries from C fails
+See \`config.log' for more details." >&5
+echo "$as_me: error: linking to Fortran libraries from C fails
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+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=f
+ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5'
+ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_f77_compiler_gnu
+{ echo "$as_me:$LINENO: checking for Fortran 77 name-mangling scheme" >&5
+echo $ECHO_N "checking for Fortran 77 name-mangling scheme... $ECHO_C" >&6; }
+if test "${ac_cv_f77_mangling+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+      subroutine foobar()
+      return
+      end
+      subroutine foo_bar()
+      return
+      end
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_f77_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  mv conftest.$ac_objext cfortran_test.$ac_objext
+
+  ac_save_LIBS=$LIBS
+  LIBS="cfortran_test.$ac_objext $LIBS $FLIBS"
+
+  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_success=no
+  for ac_foobar in foobar FOOBAR; do
+    for ac_underscore in "" "_"; do
+      ac_func="$ac_foobar$ac_underscore"
+      cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* 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 $ac_func ();
+#ifdef F77_DUMMY_MAIN
+
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+
+#endif
+int
+main ()
+{
+return $ac_func ();
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_success=yes; break 2
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+    done
+  done
+  ac_ext=f
+ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5'
+ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_f77_compiler_gnu
+
+  if test "$ac_success" = "yes"; then
+     case $ac_foobar in
+	foobar)
+	   ac_case=lower
+	   ac_foo_bar=foo_bar
+	   ;;
+	FOOBAR)
+	   ac_case=upper
+	   ac_foo_bar=FOO_BAR
+	   ;;
+     esac
+
+     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_success_extra=no
+     for ac_extra in "" "_"; do
+	ac_func="$ac_foo_bar$ac_underscore$ac_extra"
+	cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* 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 $ac_func ();
+#ifdef F77_DUMMY_MAIN
+
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+
+#endif
+int
+main ()
+{
+return $ac_func ();
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_success_extra=yes; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+     done
+     ac_ext=f
+ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5'
+ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_f77_compiler_gnu
+
+     if test "$ac_success_extra" = "yes"; then
+	ac_cv_f77_mangling="$ac_case case"
+        if test -z "$ac_underscore"; then
+           ac_cv_f77_mangling="$ac_cv_f77_mangling, no underscore"
+	else
+           ac_cv_f77_mangling="$ac_cv_f77_mangling, underscore"
+        fi
+        if test -z "$ac_extra"; then
+           ac_cv_f77_mangling="$ac_cv_f77_mangling, no extra underscore"
+	else
+           ac_cv_f77_mangling="$ac_cv_f77_mangling, extra underscore"
+        fi
+      else
+	ac_cv_f77_mangling="unknown"
+      fi
+  else
+     ac_cv_f77_mangling="unknown"
+  fi
+
+  LIBS=$ac_save_LIBS
+  rm -f -r cfortran_test* conftest*
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	{ { echo "$as_me:$LINENO: error: cannot compile a simple Fortran program
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compile a simple Fortran program
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_f77_mangling" >&5
+echo "${ECHO_T}$ac_cv_f77_mangling" >&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
+
+ac_ext=f
+ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5'
+ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_f77_compiler_gnu
+
+
+case $ac_cv_f77_mangling in
+  "lower case, no underscore, no extra underscore")
+          cat >>confdefs.h <<\_ACEOF
+#define F77_FUNC(name,NAME) name
+_ACEOF
+
+          cat >>confdefs.h <<\_ACEOF
+#define F77_FUNC_(name,NAME) name
+_ACEOF
+ ;;
+  "lower case, no underscore, extra underscore")
+          cat >>confdefs.h <<\_ACEOF
+#define F77_FUNC(name,NAME) name
+_ACEOF
+
+          cat >>confdefs.h <<\_ACEOF
+#define F77_FUNC_(name,NAME) name ## _
+_ACEOF
+ ;;
+  "lower case, underscore, no extra underscore")
+          cat >>confdefs.h <<\_ACEOF
+#define F77_FUNC(name,NAME) name ## _
+_ACEOF
+
+          cat >>confdefs.h <<\_ACEOF
+#define F77_FUNC_(name,NAME) name ## _
+_ACEOF
+ ;;
+  "lower case, underscore, extra underscore")
+          cat >>confdefs.h <<\_ACEOF
+#define F77_FUNC(name,NAME) name ## _
+_ACEOF
+
+          cat >>confdefs.h <<\_ACEOF
+#define F77_FUNC_(name,NAME) name ## __
+_ACEOF
+ ;;
+  "upper case, no underscore, no extra underscore")
+          cat >>confdefs.h <<\_ACEOF
+#define F77_FUNC(name,NAME) NAME
+_ACEOF
+
+          cat >>confdefs.h <<\_ACEOF
+#define F77_FUNC_(name,NAME) NAME
+_ACEOF
+ ;;
+  "upper case, no underscore, extra underscore")
+          cat >>confdefs.h <<\_ACEOF
+#define F77_FUNC(name,NAME) NAME
+_ACEOF
+
+          cat >>confdefs.h <<\_ACEOF
+#define F77_FUNC_(name,NAME) NAME ## _
+_ACEOF
+ ;;
+  "upper case, underscore, no extra underscore")
+          cat >>confdefs.h <<\_ACEOF
+#define F77_FUNC(name,NAME) NAME ## _
+_ACEOF
+
+          cat >>confdefs.h <<\_ACEOF
+#define F77_FUNC_(name,NAME) NAME ## _
+_ACEOF
+ ;;
+  "upper case, underscore, extra underscore")
+          cat >>confdefs.h <<\_ACEOF
+#define F77_FUNC(name,NAME) NAME ## _
+_ACEOF
+
+          cat >>confdefs.h <<\_ACEOF
+#define F77_FUNC_(name,NAME) NAME ## __
+_ACEOF
+ ;;
+  *)
+          { echo "$as_me:$LINENO: WARNING: unknown Fortran name-mangling scheme" >&5
+echo "$as_me: WARNING: unknown Fortran name-mangling scheme" >&2;}
+          ;;
+esac
+
+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
+
+
+    SUBDIRS="C Fortran"
+    TSTDIRS="C Fortran"
+    INSTDIR="Fortran"
+  fi
+fi
+
+
+# System-dependent system libraries (for building the sharable library).
+#-----------------------------------------------------------------------
+# Darwin (contains stubs for long double).
+as_ac_Lib=`echo "ac_cv_lib_SystemStubs_printf\$LDBLStub" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for printf\$LDBLStub in -lSystemStubs" >&5
+echo $ECHO_N "checking for printf\$LDBLStub in -lSystemStubs... $ECHO_C" >&6; }
+if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lSystemStubs  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* 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 printf\$LDBLStub ();
+#ifdef F77_DUMMY_MAIN
+
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+
+#endif
+int
+main ()
+{
+return printf\$LDBLStub ();
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  eval "$as_ac_Lib=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	eval "$as_ac_Lib=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+ac_res=`eval echo '${'$as_ac_Lib'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_Lib'}'` = yes; then
+  LIBS="$LIBS -lSystemStubs"
+fi
+
+
+
+# Library and installation utilities.
+#------------------------------------
+# Static library generation.
+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
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_RANLIB+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+    echo "$as_me:$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
+  { echo "$as_me:$LINENO: result: $RANLIB" >&5
+echo "${ECHO_T}$RANLIB" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}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
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_RANLIB="ranlib"
+    echo "$as_me:$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
+  { echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5
+echo "${ECHO_T}$ac_ct_RANLIB" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+  if test "x$ac_ct_RANLIB" = x; then
+    RANLIB=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf at gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf at gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+    RANLIB=$ac_ct_RANLIB
+  fi
+else
+  RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+
+# Shared library generation.
+if test "x$ac_cv_c_compiler_gnu" = xyes ; then
+  SHVER=`echo "$LIBVER" | sed -e 's/\..*$//'`
+
+  # Note that -fPIC is on by default for Macs, this just makes it obvious.
+  SHRFLAGS="-fPIC"
+  SHRLD="\$(CC) \$(SHRFLAGS)"
+
+  case "$build_os" in
+  darwin*)
+    SHRLIB="libwcs.$LIBVER.dylib"
+    SONAME="libwcs.$SHVER.dylib"
+    SHRLD="$SHRLD -dynamiclib -single_module"
+    SHRLD="$SHRLD -compatibility_version $SHVER -current_version $LIBVER"
+    SHRLN=
+
+    case "$build_cpu" in
+    powerpc*)
+      # Switch off -fPIC (not applicable for PowerPC Macs).
+      CFLAGS="$CFLAGS -mdynamic-no-pic"
+      ;;
+    esac
+    ;;
+  *)
+    # Covers Linux and Solaris at least.
+    SHRLIB="libwcs.so.$LIBVER"
+    SONAME="libwcs.so.$SHVER"
+    SHRLD="$SHRLD -shared -Wl,-h\$(SONAME)"
+    SHRLN="libwcs.so"
+    ;;
+  esac
+
+else
+  SHRLIB=
+  SONAME=
+  SHRFLAGS=
+  SHRLD=
+  SHRSFX=
+  SHRLN=
+fi
+
+
+
+
+
+
+
+
+# Installation utilities.
+{ echo "$as_me:$LINENO: checking whether ln -s works" >&5
+echo $ECHO_N "checking whether ln -s works... $ECHO_C" >&6; }
+LN_S=$as_ln_s
+if test "$LN_S" = "ln -s"; then
+  { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no, using $LN_S" >&5
+echo "${ECHO_T}no, using $LN_S" >&6; }
+fi
+
+# Find a good install program.  We prefer a C program (faster),
+# so one script is as good as another.  But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+{ echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5
+echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6; }
+if test -z "$INSTALL"; then
+if test "${ac_cv_path_install+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in
+  ./ | .// | /cC/* | \
+  /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+  ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \
+  /usr/ucb/* ) ;;
+  *)
+    # OSF1 and SCO ODT 3.0 have their own names for install.
+    # Don't use installbsd from OSF since it installs stuff as root
+    # by default.
+    for ac_prog in ginstall scoinst install; do
+      for ac_exec_ext in '' $ac_executable_extensions; do
+	if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then
+	  if test $ac_prog = install &&
+	    grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+	    # AIX install.  It has an incompatible calling convention.
+	    :
+	  elif test $ac_prog = install &&
+	    grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+	    # program-specific install script used by HP pwplus--don't use.
+	    :
+	  else
+	    ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+	    break 3
+	  fi
+	fi
+      done
+    done
+    ;;
+esac
+done
+IFS=$as_save_IFS
+
+
+fi
+  if test "${ac_cv_path_install+set}" = set; then
+    INSTALL=$ac_cv_path_install
+  else
+    # As a last resort, use the slow shell script.  Don't cache a
+    # value for INSTALL within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the value is a relative name.
+    INSTALL=$ac_install_sh
+  fi
+fi
+{ echo "$as_me:$LINENO: result: $INSTALL" >&5
+echo "${ECHO_T}$INSTALL" >&6; }
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+
+{ echo "$as_me:$LINENO: End of primary configuration.
+" >&5
+echo "$as_me: End of primary configuration.
+" >&6;}
+
+
+# The following are required to build utilities and test programs.
+# ----------------------------------------------------------------
+{ echo "$as_me:$LINENO: Looking for libraries etc. for utilities and test suite..." >&5
+echo "$as_me: Looking for libraries etc. for utilities and test suite..." >&6;}
+
+# Check for other quasi-standard header files.
+
+for ac_header in unistd.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+    ( cat <<\_ASBOX
+## ------------------------------------ ##
+## Report this to mark at calabretta.id.au ##
+## ------------------------------------ ##
+_ASBOX
+     ) | sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+# Large file support.
+{ echo "$as_me:$LINENO: checking for _LARGEFILE_SOURCE value needed for large files" >&5
+echo $ECHO_N "checking for _LARGEFILE_SOURCE value needed for large files... $ECHO_C" >&6; }
+if test "${ac_cv_sys_largefile_source+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  while :; do
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdio.h>
+#ifdef F77_DUMMY_MAIN
+
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+
+#endif
+int
+main ()
+{
+return fseeko (stdin, 0, 0) && (fseeko) (stdin, 0, 0);
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_sys_largefile_source=no; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#define _LARGEFILE_SOURCE 1
+#include <stdio.h>
+#ifdef F77_DUMMY_MAIN
+
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+
+#endif
+int
+main ()
+{
+return fseeko (stdin, 0, 0) && (fseeko) (stdin, 0, 0);
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_sys_largefile_source=1; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+  ac_cv_sys_largefile_source=unknown
+  break
+done
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_sys_largefile_source" >&5
+echo "${ECHO_T}$ac_cv_sys_largefile_source" >&6; }
+case $ac_cv_sys_largefile_source in #(
+  no | unknown) ;;
+  *)
+cat >>confdefs.h <<_ACEOF
+#define _LARGEFILE_SOURCE $ac_cv_sys_largefile_source
+_ACEOF
+;;
+esac
+rm -f -r conftest*
+
+# We used to try defining _XOPEN_SOURCE=500 too, to work around a bug
+# in glibc 2.1.3, but that breaks too many other things.
+# If you want fseeko and ftello with glibc, upgrade to a fixed glibc.
+if test $ac_cv_sys_largefile_source != unknown; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_FSEEKO 1
+_ACEOF
+
+fi
+
+# Check whether --enable-largefile was given.
+if test "${enable_largefile+set}" = set; then
+  enableval=$enable_largefile;
+fi
+
+if test "$enable_largefile" != no; then
+
+  { echo "$as_me:$LINENO: checking for special C compiler options needed for large files" >&5
+echo $ECHO_N "checking for special C compiler options needed for large files... $ECHO_C" >&6; }
+if test "${ac_cv_sys_largefile_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_sys_largefile_CC=no
+     if test "$GCC" != yes; then
+       ac_save_CC=$CC
+       while :; do
+	 # IRIX 6.2 and later do not support large files by default,
+	 # so use the C compiler's -n32 option if that helps.
+	 cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+		       && LARGE_OFF_T % 2147483647 == 1)
+		      ? 1 : -1];
+#ifdef F77_DUMMY_MAIN
+
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+
+#endif
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+	 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext
+	 CC="$CC -n32"
+	 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_sys_largefile_CC=' -n32'; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext
+	 break
+       done
+       CC=$ac_save_CC
+       rm -f conftest.$ac_ext
+    fi
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_sys_largefile_CC" >&5
+echo "${ECHO_T}$ac_cv_sys_largefile_CC" >&6; }
+  if test "$ac_cv_sys_largefile_CC" != no; then
+    CC=$CC$ac_cv_sys_largefile_CC
+  fi
+
+  { echo "$as_me:$LINENO: checking for _FILE_OFFSET_BITS value needed for large files" >&5
+echo $ECHO_N "checking for _FILE_OFFSET_BITS value needed for large files... $ECHO_C" >&6; }
+if test "${ac_cv_sys_file_offset_bits+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  while :; do
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+		       && LARGE_OFF_T % 2147483647 == 1)
+		      ? 1 : -1];
+#ifdef F77_DUMMY_MAIN
+
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+
+#endif
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_sys_file_offset_bits=no; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#define _FILE_OFFSET_BITS 64
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+		       && LARGE_OFF_T % 2147483647 == 1)
+		      ? 1 : -1];
+#ifdef F77_DUMMY_MAIN
+
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+
+#endif
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_sys_file_offset_bits=64; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  ac_cv_sys_file_offset_bits=unknown
+  break
+done
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_sys_file_offset_bits" >&5
+echo "${ECHO_T}$ac_cv_sys_file_offset_bits" >&6; }
+case $ac_cv_sys_file_offset_bits in #(
+  no | unknown) ;;
+  *)
+cat >>confdefs.h <<_ACEOF
+#define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits
+_ACEOF
+;;
+esac
+rm -f -r conftest*
+  if test $ac_cv_sys_file_offset_bits = unknown; then
+    { echo "$as_me:$LINENO: checking for _LARGE_FILES value needed for large files" >&5
+echo $ECHO_N "checking for _LARGE_FILES value needed for large files... $ECHO_C" >&6; }
+if test "${ac_cv_sys_large_files+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  while :; do
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+		       && LARGE_OFF_T % 2147483647 == 1)
+		      ? 1 : -1];
+#ifdef F77_DUMMY_MAIN
+
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+
+#endif
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_sys_large_files=no; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#define _LARGE_FILES 1
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+		       && LARGE_OFF_T % 2147483647 == 1)
+		      ? 1 : -1];
+#ifdef F77_DUMMY_MAIN
+
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+
+#endif
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_sys_large_files=1; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  ac_cv_sys_large_files=unknown
+  break
+done
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_sys_large_files" >&5
+echo "${ECHO_T}$ac_cv_sys_large_files" >&6; }
+case $ac_cv_sys_large_files in #(
+  no | unknown) ;;
+  *)
+cat >>confdefs.h <<_ACEOF
+#define _LARGE_FILES $ac_cv_sys_large_files
+_ACEOF
+;;
+esac
+rm -f -r conftest*
+  fi
+fi
+
+
+
+# Extra places to look for third-party libraries and header files.
+LIBDIRS=
+
+
+# Check whether --with-cfitsio was given.
+if test "${with_cfitsio+set}" = set; then
+  withval=$with_cfitsio;
+fi
+
+if test "x$with_cfitsio" = xno ; then
+  { echo "$as_me:$LINENO: WARNING: CFITSIO disabled" >&5
+echo "$as_me: WARNING: CFITSIO disabled" >&2;}
+else
+
+# Check whether --with-cfitsiolib was given.
+if test "${with_cfitsiolib+set}" = set; then
+  withval=$with_cfitsiolib;
+fi
+
+  if test "x$with_cfitsiolib" != x ; then
+    LIBDIRS="$LIBDIRS $with_cfitsiolib"
+  fi
+
+
+# Check whether --with-cfitsioinc was given.
+if test "${with_cfitsioinc+set}" = set; then
+  withval=$with_cfitsioinc;
+fi
+
+  if test "x$with_cfitsioinc" != x ; then
+    CFITSIO_INCDIRS="$with_cfitsioinc"
+  fi
+
+  CFITSIO_INCDIRS="$CFITSIO_INCDIRS   \
+           /usr/local/cfitsio/include \
+           /local/cfitsio/include"
+
+  LIBDIRS="$LIBDIRS           \
+           /usr/local/cfitsio/lib \
+           /local/cfitsio/lib"
+fi
+
+
+# Check whether --with-pgplot was given.
+if test "${with_pgplot+set}" = set; then
+  withval=$with_pgplot;
+fi
+
+if test "x$with_pgplot" = xno ; then
+  { echo "$as_me:$LINENO: WARNING: PGPLOT disabled" >&5
+echo "$as_me: WARNING: PGPLOT disabled" >&2;}
+else
+
+# Check whether --with-pgplotlib was given.
+if test "${with_pgplotlib+set}" = set; then
+  withval=$with_pgplotlib;
+fi
+
+  if test "x$with_pgplotlib" != x ; then
+    LIBDIRS="$LIBDIRS $with_pgplotlib"
+  fi
+
+
+# Check whether --with-pgplotinc was given.
+if test "${with_pgplotinc+set}" = set; then
+  withval=$with_pgplotinc;
+fi
+
+  if test "x$with_pgplotinc" != x ; then
+    PGPLOT_INCDIRS="$with_pgplotinc"
+  fi
+
+  PGPLOT_INCDIRS="$PGPLOT_INCDIRS    \
+           /usr/local/pgplot/include \
+           /local/pgplot/include"
+
+  LIBDIRS="$LIBDIRS           \
+           /usr/local/pgplot/lib  \
+           /local/pgplot/lib"
+fi
+
+
+if test "x$with_cfitsio" != xno -o \
+        "x$with_pgplot"  != xno ; then
+  LIBDIRS="$LIBDIRS           \
+           /usr/local/lib     \
+           /local/lib         \
+           /opt/local/lib     \
+           /opt/SUNWspro/lib  \
+           /sw/lib"
+
+  for LIBDIR in $LIBDIRS ; do
+    as_ac_File=`echo "ac_cv_file_$LIBDIR" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $LIBDIR" >&5
+echo $ECHO_N "checking for $LIBDIR... $ECHO_C" >&6; }
+if { as_var=$as_ac_File; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  test "$cross_compiling" = yes &&
+  { { echo "$as_me:$LINENO: error: cannot check for file existence when cross compiling" >&5
+echo "$as_me: error: cannot check for file existence when cross compiling" >&2;}
+   { (exit 1); exit 1; }; }
+if test -r "$LIBDIR"; then
+  eval "$as_ac_File=yes"
+else
+  eval "$as_ac_File=no"
+fi
+fi
+ac_res=`eval echo '${'$as_ac_File'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_File'}'` = yes; then
+  LDFLAGS="$LDFLAGS -L$LIBDIR"
+else
+  continue
+fi
+
+  done
+
+  # Generic include directories.
+  INCDIRS="/usr/local/include \
+           /local/include     \
+           /opt/local/include \
+           /sw/include        \
+           /local             \
+           /usr/include"
+
+
+  # CFITSIO.
+  if test "x$with_cfitsio" != xno ; then
+    # Search for CFITSIO.
+    for INCDIR in $CFITSIO_INCDIRS $INCDIRS ; do
+      as_ac_File=`echo "ac_cv_file_$INCDIR/cfitsio/fitsio.h" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $INCDIR/cfitsio/fitsio.h" >&5
+echo $ECHO_N "checking for $INCDIR/cfitsio/fitsio.h... $ECHO_C" >&6; }
+if { as_var=$as_ac_File; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  test "$cross_compiling" = yes &&
+  { { echo "$as_me:$LINENO: error: cannot check for file existence when cross compiling" >&5
+echo "$as_me: error: cannot check for file existence when cross compiling" >&2;}
+   { (exit 1); exit 1; }; }
+if test -r "$INCDIR/cfitsio/fitsio.h"; then
+  eval "$as_ac_File=yes"
+else
+  eval "$as_ac_File=no"
+fi
+fi
+ac_res=`eval echo '${'$as_ac_File'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_File'}'` = yes; then
+  CFITSIOINC="-I$INCDIR/cfitsio"; break
+fi
+
+      as_ac_File=`echo "ac_cv_file_$INCDIR/fitsio.h" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $INCDIR/fitsio.h" >&5
+echo $ECHO_N "checking for $INCDIR/fitsio.h... $ECHO_C" >&6; }
+if { as_var=$as_ac_File; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  test "$cross_compiling" = yes &&
+  { { echo "$as_me:$LINENO: error: cannot check for file existence when cross compiling" >&5
+echo "$as_me: error: cannot check for file existence when cross compiling" >&2;}
+   { (exit 1); exit 1; }; }
+if test -r "$INCDIR/fitsio.h"; then
+  eval "$as_ac_File=yes"
+else
+  eval "$as_ac_File=no"
+fi
+fi
+ac_res=`eval echo '${'$as_ac_File'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_File'}'` = yes; then
+  CFITSIOINC="-I$INCDIR"; break
+fi
+
+    done
+
+    { echo "$as_me:$LINENO: checking for recv in -lsocket" >&5
+echo $ECHO_N "checking for recv in -lsocket... $ECHO_C" >&6; }
+if test "${ac_cv_lib_socket_recv+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsocket $LIBS $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* 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 recv ();
+#ifdef F77_DUMMY_MAIN
+
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+
+#endif
+int
+main ()
+{
+return recv ();
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_socket_recv=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_lib_socket_recv=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_socket_recv" >&5
+echo "${ECHO_T}$ac_cv_lib_socket_recv" >&6; }
+if test $ac_cv_lib_socket_recv = yes; then
+  CFITSIOLIB="-lsocket"
+fi
+
+    { echo "$as_me:$LINENO: checking for ffopen in -lcfitsio" >&5
+echo $ECHO_N "checking for ffopen in -lcfitsio... $ECHO_C" >&6; }
+if test "${ac_cv_lib_cfitsio_ffopen+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lcfitsio $CFITSIOLIB $LIBS $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* 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 ffopen ();
+#ifdef F77_DUMMY_MAIN
+
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+
+#endif
+int
+main ()
+{
+return ffopen ();
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_cfitsio_ffopen=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_lib_cfitsio_ffopen=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_cfitsio_ffopen" >&5
+echo "${ECHO_T}$ac_cv_lib_cfitsio_ffopen" >&6; }
+if test $ac_cv_lib_cfitsio_ffopen = yes; then
+  CFITSIOLIB="-lcfitsio $CFITSIOLIB"
+fi
+
+
+    if test "x$CFITSIOINC" = x -o "x$CFITSIOLIB" = x; then
+      { echo "$as_me:$LINENO: WARNING: CFITSIO not found, skipping CFITSIO-dependent tests." >&5
+echo "$as_me: WARNING: CFITSIO not found, skipping CFITSIO-dependent tests." >&2;}
+    else
+      { echo "$as_me:$LINENO: CFITSIO appears to be available." >&5
+echo "$as_me: CFITSIO appears to be available." >&6;}
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_CFITSIO 1
+_ACEOF
+
+
+      # Check for fits_read_wcstab, present in CFITSIO 3.004beta and later.
+      { echo "$as_me:$LINENO: checking for fits_read_wcstab in -lcfitsio" >&5
+echo $ECHO_N "checking for fits_read_wcstab in -lcfitsio... $ECHO_C" >&6; }
+if test "${ac_cv_lib_cfitsio_fits_read_wcstab+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lcfitsio $CFITSIOLIB $LIBS $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* 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 fits_read_wcstab ();
+#ifdef F77_DUMMY_MAIN
+
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+
+#endif
+int
+main ()
+{
+return fits_read_wcstab ();
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_cfitsio_fits_read_wcstab=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_lib_cfitsio_fits_read_wcstab=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_cfitsio_fits_read_wcstab" >&5
+echo "${ECHO_T}$ac_cv_lib_cfitsio_fits_read_wcstab" >&6; }
+if test $ac_cv_lib_cfitsio_fits_read_wcstab = yes; then
+  GETWCSTAB=
+else
+  GETWCSTAB=getwcstab.o
+fi
+
+      if test "x$GETWCSTAB" != x ; then
+        { echo "$as_me:$LINENO: WARNING: fits_read_wcstab not found in CFITSIO, will use
+                        getwcstab.c to compile test programs." >&5
+echo "$as_me: WARNING: fits_read_wcstab not found in CFITSIO, will use
+                        getwcstab.c to compile test programs." >&2;}
+      fi
+    fi
+  fi
+
+  # PGPLOT.
+  if test "x$F77" != x -a "x$with_pgplot" != xno ; then
+    # Search for PGPLOT.
+    for INCDIR in $PGPLOT_INCDIRS $INCDIRS ; do
+      as_ac_File=`echo "ac_cv_file_$INCDIR/pgplot/cpgplot.h" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $INCDIR/pgplot/cpgplot.h" >&5
+echo $ECHO_N "checking for $INCDIR/pgplot/cpgplot.h... $ECHO_C" >&6; }
+if { as_var=$as_ac_File; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  test "$cross_compiling" = yes &&
+  { { echo "$as_me:$LINENO: error: cannot check for file existence when cross compiling" >&5
+echo "$as_me: error: cannot check for file existence when cross compiling" >&2;}
+   { (exit 1); exit 1; }; }
+if test -r "$INCDIR/pgplot/cpgplot.h"; then
+  eval "$as_ac_File=yes"
+else
+  eval "$as_ac_File=no"
+fi
+fi
+ac_res=`eval echo '${'$as_ac_File'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_File'}'` = yes; then
+  PGPLOTINC="-I$INCDIR/pgplot"; break
+fi
+
+      as_ac_File=`echo "ac_cv_file_$INCDIR/cpgplot.h" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $INCDIR/cpgplot.h" >&5
+echo $ECHO_N "checking for $INCDIR/cpgplot.h... $ECHO_C" >&6; }
+if { as_var=$as_ac_File; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  test "$cross_compiling" = yes &&
+  { { echo "$as_me:$LINENO: error: cannot check for file existence when cross compiling" >&5
+echo "$as_me: error: cannot check for file existence when cross compiling" >&2;}
+   { (exit 1); exit 1; }; }
+if test -r "$INCDIR/cpgplot.h"; then
+  eval "$as_ac_File=yes"
+else
+  eval "$as_ac_File=no"
+fi
+fi
+ac_res=`eval echo '${'$as_ac_File'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_File'}'` = yes; then
+  PGPLOTINC="-I$INCDIR"; break
+fi
+
+    done
+
+    # FLIBS (found above via AC_F77_LIBRARY_LDFLAGS) only helps if PGPLOT was
+    # built using the same Fortran compiler that we are using here.
+
+    # PGPLOT compiled by the SUN Fortran compiler but linked with something
+    # else.
+    { echo "$as_me:$LINENO: checking for iand_ in -lM77" >&5
+echo $ECHO_N "checking for iand_ in -lM77... $ECHO_C" >&6; }
+if test "${ac_cv_lib_M77_iand_+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lM77 $PGPLOTLIB $LIBS $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* 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 iand_ ();
+#ifdef F77_DUMMY_MAIN
+
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+
+#endif
+int
+main ()
+{
+return iand_ ();
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_M77_iand_=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_lib_M77_iand_=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_M77_iand_" >&5
+echo "${ECHO_T}$ac_cv_lib_M77_iand_" >&6; }
+if test $ac_cv_lib_M77_iand_ = yes; then
+  PGPLOTLIB="-lM77 $PGPLOTLIB"
+fi
+
+    { echo "$as_me:$LINENO: checking for f77_init in -lF77" >&5
+echo $ECHO_N "checking for f77_init in -lF77... $ECHO_C" >&6; }
+if test "${ac_cv_lib_F77_f77_init+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lF77 $PGPLOTLIB $LIBS $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* 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 f77_init ();
+#ifdef F77_DUMMY_MAIN
+
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+
+#endif
+int
+main ()
+{
+return f77_init ();
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_F77_f77_init=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_lib_F77_f77_init=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_F77_f77_init" >&5
+echo "${ECHO_T}$ac_cv_lib_F77_f77_init" >&6; }
+if test $ac_cv_lib_F77_f77_init = yes; then
+  PGPLOTLIB="-lF77 $PGPLOTLIB"
+fi
+
+
+    if test "x$F77" != xg77; then
+      # For PGPLOT compiled with g77 but linked with something else.
+      { echo "$as_me:$LINENO: checking for main in -lfrtbegin" >&5
+echo $ECHO_N "checking for main in -lfrtbegin... $ECHO_C" >&6; }
+if test "${ac_cv_lib_frtbegin_main+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lfrtbegin $PGPLOTLIB $LIBS $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+
+#ifdef F77_DUMMY_MAIN
+
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+
+#endif
+int
+main ()
+{
+return main ();
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_frtbegin_main=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_lib_frtbegin_main=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_frtbegin_main" >&5
+echo "${ECHO_T}$ac_cv_lib_frtbegin_main" >&6; }
+if test $ac_cv_lib_frtbegin_main = yes; then
+  PGPLOTLIB="-lfrtbegin $PGPLOTLIB"
+fi
+
+      { echo "$as_me:$LINENO: checking for gerror_ in -lg2c" >&5
+echo $ECHO_N "checking for gerror_ in -lg2c... $ECHO_C" >&6; }
+if test "${ac_cv_lib_g2c_gerror_+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lg2c $PGPLOTLIB $LIBS $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* 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 gerror_ ();
+#ifdef F77_DUMMY_MAIN
+
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+
+#endif
+int
+main ()
+{
+return gerror_ ();
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_g2c_gerror_=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_lib_g2c_gerror_=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_g2c_gerror_" >&5
+echo "${ECHO_T}$ac_cv_lib_g2c_gerror_" >&6; }
+if test $ac_cv_lib_g2c_gerror_ = yes; then
+  PGPLOTLIB="-lg2c $PGPLOTLIB"
+fi
+
+    fi
+
+    if test "x$F77" != xgfortran; then
+      # For PGPLOT compiled with gfortran but linked with something else.
+      # Note that if gfortran itself is driving the linker it can be harmful
+      # to add -lgfortran to the link list without also adding -lgfortranbegin.
+      # Doing so stops gfortran from adding -lgfortranbegin which is needed to
+      # resolve "main".
+      { echo "$as_me:$LINENO: checking for _gfortran_abort in -lgfortran" >&5
+echo $ECHO_N "checking for _gfortran_abort in -lgfortran... $ECHO_C" >&6; }
+if test "${ac_cv_lib_gfortran__gfortran_abort+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lgfortran $PGPLOTLIB $LIBS $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* 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 _gfortran_abort ();
+#ifdef F77_DUMMY_MAIN
+
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+
+#endif
+int
+main ()
+{
+return _gfortran_abort ();
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_gfortran__gfortran_abort=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_lib_gfortran__gfortran_abort=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_gfortran__gfortran_abort" >&5
+echo "${ECHO_T}$ac_cv_lib_gfortran__gfortran_abort" >&6; }
+if test $ac_cv_lib_gfortran__gfortran_abort = yes; then
+  PGPLOTLIB="-lgfortran $PGPLOTLIB"
+fi
+
+    fi
+
+    # Search for X11 includes and libraries.
+    { echo "$as_me:$LINENO: checking for X" >&5
+echo $ECHO_N "checking for X... $ECHO_C" >&6; }
+
+
+# Check whether --with-x was given.
+if test "${with_x+set}" = set; then
+  withval=$with_x;
+fi
+
+# $have_x is `yes', `no', `disabled', or empty when we do not yet know.
+if test "x$with_x" = xno; then
+  # The user explicitly disabled X.
+  have_x=disabled
+else
+  case $x_includes,$x_libraries in #(
+    *\'*) { { echo "$as_me:$LINENO: error: Cannot use X directory names containing '" >&5
+echo "$as_me: error: Cannot use X directory names containing '" >&2;}
+   { (exit 1); exit 1; }; };; #(
+    *,NONE | NONE,*) if test "${ac_cv_have_x+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  # One or both of the vars are not set, and there is no cached value.
+ac_x_includes=no ac_x_libraries=no
+rm -f -r conftest.dir
+if mkdir conftest.dir; then
+  cd conftest.dir
+  cat >Imakefile <<'_ACEOF'
+incroot:
+	@echo incroot='${INCROOT}'
+usrlibdir:
+	@echo usrlibdir='${USRLIBDIR}'
+libdir:
+	@echo libdir='${LIBDIR}'
+_ACEOF
+  if (export CC; ${XMKMF-xmkmf}) >/dev/null 2>/dev/null && test -f Makefile; then
+    # GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+    for ac_var in incroot usrlibdir libdir; do
+      eval "ac_im_$ac_var=\`\${MAKE-make} $ac_var 2>/dev/null | sed -n 's/^$ac_var=//p'\`"
+    done
+    # Open Windows xmkmf reportedly sets LIBDIR instead of USRLIBDIR.
+    for ac_extension in a so sl dylib la dll; do
+      if test ! -f "$ac_im_usrlibdir/libX11.$ac_extension" &&
+	 test -f "$ac_im_libdir/libX11.$ac_extension"; then
+	ac_im_usrlibdir=$ac_im_libdir; break
+      fi
+    done
+    # Screen out bogus values from the imake configuration.  They are
+    # bogus both because they are the default anyway, and because
+    # using them would break gcc on systems where it needs fixed includes.
+    case $ac_im_incroot in
+	/usr/include) ac_x_includes= ;;
+	*) test -f "$ac_im_incroot/X11/Xos.h" && ac_x_includes=$ac_im_incroot;;
+    esac
+    case $ac_im_usrlibdir in
+	/usr/lib | /lib) ;;
+	*) test -d "$ac_im_usrlibdir" && ac_x_libraries=$ac_im_usrlibdir ;;
+    esac
+  fi
+  cd ..
+  rm -f -r conftest.dir
+fi
+
+# Standard set of common directories for X headers.
+# Check X11 before X11Rn because it is often a symlink to the current release.
+ac_x_header_dirs='
+/usr/X11/include
+/usr/X11R6/include
+/usr/X11R5/include
+/usr/X11R4/include
+
+/usr/include/X11
+/usr/include/X11R6
+/usr/include/X11R5
+/usr/include/X11R4
+
+/usr/local/X11/include
+/usr/local/X11R6/include
+/usr/local/X11R5/include
+/usr/local/X11R4/include
+
+/usr/local/include/X11
+/usr/local/include/X11R6
+/usr/local/include/X11R5
+/usr/local/include/X11R4
+
+/usr/X386/include
+/usr/x386/include
+/usr/XFree86/include/X11
+
+/usr/include
+/usr/local/include
+/usr/unsupported/include
+/usr/athena/include
+/usr/local/x11r5/include
+/usr/lpp/Xamples/include
+
+/usr/openwin/include
+/usr/openwin/share/include'
+
+if test "$ac_x_includes" = no; then
+  # Guess where to find include files, by looking for Xlib.h.
+  # First, try using that file with no special directory specified.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <X11/Xlib.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  # We can compile using X headers with no special include directory.
+ac_x_includes=
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  for ac_dir in $ac_x_header_dirs; do
+  if test -r "$ac_dir/X11/Xlib.h"; then
+    ac_x_includes=$ac_dir
+    break
+  fi
+done
+fi
+
+rm -f conftest.err conftest.$ac_ext
+fi # $ac_x_includes = no
+
+if test "$ac_x_libraries" = no; then
+  # Check for the libraries.
+  # See if we find them without any special options.
+  # Don't add to $LIBS permanently.
+  ac_save_LIBS=$LIBS
+  LIBS="-lX11 $LIBS"
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <X11/Xlib.h>
+#ifdef F77_DUMMY_MAIN
+
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+
+#endif
+int
+main ()
+{
+XrmInitialize ()
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  LIBS=$ac_save_LIBS
+# We can link X programs with no special library path.
+ac_x_libraries=
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	LIBS=$ac_save_LIBS
+for ac_dir in `echo "$ac_x_includes $ac_x_header_dirs" | sed s/include/lib/g`
+do
+  # Don't even attempt the hair of trying to link an X program!
+  for ac_extension in a so sl dylib la dll; do
+    if test -r "$ac_dir/libX11.$ac_extension"; then
+      ac_x_libraries=$ac_dir
+      break 2
+    fi
+  done
+done
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi # $ac_x_libraries = no
+
+case $ac_x_includes,$ac_x_libraries in #(
+  no,* | *,no | *\'*)
+    # Didn't find X, or a directory has "'" in its name.
+    ac_cv_have_x="have_x=no";; #(
+  *)
+    # Record where we found X for the cache.
+    ac_cv_have_x="have_x=yes\
+	ac_x_includes='$ac_x_includes'\
+	ac_x_libraries='$ac_x_libraries'"
+esac
+fi
+;; #(
+    *) have_x=yes;;
+  esac
+  eval "$ac_cv_have_x"
+fi # $with_x != no
+
+if test "$have_x" != yes; then
+  { echo "$as_me:$LINENO: result: $have_x" >&5
+echo "${ECHO_T}$have_x" >&6; }
+  no_x=yes
+else
+  # If each of the values was on the command line, it overrides each guess.
+  test "x$x_includes" = xNONE && x_includes=$ac_x_includes
+  test "x$x_libraries" = xNONE && x_libraries=$ac_x_libraries
+  # Update the cache value to reflect the command line values.
+  ac_cv_have_x="have_x=yes\
+	ac_x_includes='$x_includes'\
+	ac_x_libraries='$x_libraries'"
+  { echo "$as_me:$LINENO: result: libraries $x_libraries, headers $x_includes" >&5
+echo "${ECHO_T}libraries $x_libraries, headers $x_includes" >&6; }
+fi
+
+    if test "x$no_x" = x; then
+      if test "x$ac_x_libraries" != x ; then
+        # Not needed for systems that keep the X11 libraries in /usr/lib.
+        LDFLAGS="$LDFLAGS -L$ac_x_libraries"
+      fi
+      PGPLOTLIB="-lX11 $PGPLOTLIB"
+    fi
+
+    # It is possible that other libraries may be required depending on what
+    # graphics drivers were installed with PGPLOT.
+    { echo "$as_me:$LINENO: checking for deflate in -lz" >&5
+echo $ECHO_N "checking for deflate in -lz... $ECHO_C" >&6; }
+if test "${ac_cv_lib_z_deflate+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lz $PGPLOTLIB $LIBS $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* 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 deflate ();
+#ifdef F77_DUMMY_MAIN
+
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+
+#endif
+int
+main ()
+{
+return deflate ();
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_z_deflate=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_lib_z_deflate=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_z_deflate" >&5
+echo "${ECHO_T}$ac_cv_lib_z_deflate" >&6; }
+if test $ac_cv_lib_z_deflate = yes; then
+  PGPLOTLIB="-lz $PGPLOTLIB"
+fi
+
+    { echo "$as_me:$LINENO: checking for png_error in -lpng" >&5
+echo $ECHO_N "checking for png_error in -lpng... $ECHO_C" >&6; }
+if test "${ac_cv_lib_png_png_error+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lpng $PGPLOTLIB $LIBS $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* 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 png_error ();
+#ifdef F77_DUMMY_MAIN
+
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+
+#endif
+int
+main ()
+{
+return png_error ();
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_png_png_error=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_lib_png_png_error=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_png_png_error" >&5
+echo "${ECHO_T}$ac_cv_lib_png_png_error" >&6; }
+if test $ac_cv_lib_png_png_error = yes; then
+  PGPLOTLIB="-lpng $PGPLOTLIB"
+fi
+
+    { echo "$as_me:$LINENO: checking for pgbeg_ in -lpgplot" >&5
+echo $ECHO_N "checking for pgbeg_ in -lpgplot... $ECHO_C" >&6; }
+if test "${ac_cv_lib_pgplot_pgbeg_+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lpgplot $PGPLOTLIB $FLIBS $LIBS $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* 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 pgbeg_ ();
+#ifdef F77_DUMMY_MAIN
+
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+
+#endif
+int
+main ()
+{
+return pgbeg_ ();
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_pgplot_pgbeg_=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_lib_pgplot_pgbeg_=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_pgplot_pgbeg_" >&5
+echo "${ECHO_T}$ac_cv_lib_pgplot_pgbeg_" >&6; }
+if test $ac_cv_lib_pgplot_pgbeg_ = yes; then
+  PGPLOTLIB="-lpgplot $PGPLOTLIB"
+fi
+
+    { echo "$as_me:$LINENO: checking for cpgbeg in -lcpgplot" >&5
+echo $ECHO_N "checking for cpgbeg in -lcpgplot... $ECHO_C" >&6; }
+if test "${ac_cv_lib_cpgplot_cpgbeg+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lcpgplot $PGPLOTLIB $FLIBS $LIBS $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* 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 cpgbeg ();
+#ifdef F77_DUMMY_MAIN
+
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+
+#endif
+int
+main ()
+{
+return cpgbeg ();
+  ;
+  return 0;
+}
+_ACEOF
+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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_cpgplot_cpgbeg=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_lib_cpgplot_cpgbeg=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_cpgplot_cpgbeg" >&5
+echo "${ECHO_T}$ac_cv_lib_cpgplot_cpgbeg" >&6; }
+if test $ac_cv_lib_cpgplot_cpgbeg = yes; then
+  PGPLOTLIB="-lcpgplot $PGPLOTLIB"
+else
+  PGPLOTLIB=
+fi
+
+
+    # Only need the PGPLOT include file to build PGSBOX.
+    if test "x$PGPLOTINC" != x; then
+      SUBDIRS="$SUBDIRS pgsbox"
+      INSTDIR="pgsbox"
+    fi
+
+    # Also need the PGPLOT library to build pgtest and cpgtest.
+    if test "x$PGPLOTLIB" = x; then
+      { echo "$as_me:$LINENO: WARNING: PGPLOT not found, skipping PGPLOT-dependent tests." >&5
+echo "$as_me: WARNING: PGPLOT not found, skipping PGPLOT-dependent tests." >&2;}
+    else
+      { echo "$as_me:$LINENO: PGPLOT appears to be available." >&5
+echo "$as_me: PGPLOT appears to be available." >&6;}
+
+      TSTDIRS="$TSTDIRS pgsbox"
+    fi
+  fi
+fi
+
+
+# Utilities are compiled last since they need the libraries.
+# Ways of disabling them:
+#   configure --disable-utils
+#   configure --enable-utils=no
+# Check whether --enable-utils was given.
+if test "${enable_utils+set}" = set; then
+  enableval=$enable_utils;
+fi
+
+if test "x$enable_utils" != xno ; then
+  SUBDIRS="$SUBDIRS utils"
+  INSTDIR="$INSTDIR utils"
+else
+  { echo "$as_me:$LINENO: WARNING: Compilation of WCS utilities disabled" >&5
+echo "$as_me: WARNING: Compilation of WCS utilities disabled" >&2;}
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+{ echo "$as_me:$LINENO: End of auxiliary configuration.
+" >&5
+echo "$as_me: End of auxiliary configuration.
+" >&6;}
+
+
+# Do it.
+{ echo "$as_me:$LINENO: Configuring files..." >&5
+echo "$as_me: Configuring files..." >&6;}
+ac_config_files="$ac_config_files makedefs wcslib.pc"
+
+ac_config_headers="$ac_config_headers wcsconfig.h wcsconfig_f77.h wcsconfig_tests.h wcsconfig_utils.h"
+
+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_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5
+echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      *) $as_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
+    test "x$cache_file" != "x/dev/null" &&
+      { echo "$as_me:$LINENO: updating cache $cache_file" >&5
+echo "$as_me: updating cache $cache_file" >&6;}
+    cat confcache >$cache_file
+  else
+    { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5
+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}'
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+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=`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.
+  ac_libobjs="$ac_libobjs \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+  ac_ltlibobjs="$ac_ltlibobjs \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+: ${CONFIG_STATUS=./config.status}
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
+echo "$as_me: creating $CONFIG_STATUS" >&6;}
+cat >$CONFIG_STATUS <<_ACEOF
+#! $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}
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+## --------------------- ##
+## 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=:
+  # Zsh 3.x and 4.x performs 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
+
+
+
+
+# PATH needs CR
+# 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
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  echo "#! /bin/sh" >conf$$.sh
+  echo  "exit 0"   >>conf$$.sh
+  chmod +x conf$$.sh
+  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+    PATH_SEPARATOR=';'
+  else
+    PATH_SEPARATOR=:
+  fi
+  rm -f conf$$.sh
+fi
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  as_unset=unset
+else
+  as_unset=false
+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.)
+as_nl='
+'
+IFS=" ""	$as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+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
+  echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  { (exit 1); exit 1; }
+fi
+
+# Work around bugs in pre-3.0 UWIN ksh.
+for as_var in ENV MAIL MAILPATH
+do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+  LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+  LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+  LC_TELEPHONE LC_TIME
+do
+  if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+    eval $as_var=C; export $as_var
+  else
+    ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+  fi
+done
+
+# Required to use basename.
+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
+
+
+# Name of the executable.
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+
+# CDPATH.
+$as_unset CDPATH
+
+
+
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
+
+  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+  # uniformly replaced by the line number.  The first 'sed' inserts a
+  # line-number line after each line using $LINENO; the second 'sed'
+  # does the real work.  The second script uses 'N' to pair each
+  # line-number line with the line containing $LINENO, and appends
+  # trailing '-' during substitution so that $LINENO is not a special
+  # case at line end.
+  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+  # scripts with optimization help from Paolo Bonzini.  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" ||
+    { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+   { (exit 1); exit 1; }; }
+
+  # 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
+}
+
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in
+-n*)
+  case `echo 'x\c'` in
+  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
+  *)   ECHO_C='\c';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+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
+fi
+echo >conf$$.file
+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 -p'.
+  ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+    as_ln_s='cp -p'
+elif ln conf$$.file conf$$ 2>/dev/null; then
+  as_ln_s=ln
+else
+  as_ln_s='cp -p'
+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=:
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+  as_test_x='test -x'
+else
+  if ls -dL / >/dev/null 2>&1; then
+    as_ls_L_option=L
+  else
+    as_ls_L_option=
+  fi
+  as_test_x='
+    eval sh -c '\''
+      if test -d "$1"; then
+        test -d "$1/.";
+      else
+	case $1 in
+        -*)set "./$1";;
+	esac;
+	case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in
+	???[sx]*):;;*)false;;esac;fi
+    '\'' sh
+  '
+fi
+as_executable_p=$as_test_x
+
+# 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
+
+# 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 WCSLIB $as_me 4.16, which was
+generated by GNU Autoconf 2.61.  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
+
+cat >>$CONFIG_STATUS <<_ACEOF
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_headers="$ac_config_headers"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+ac_cs_usage="\
+\`$as_me' instantiates files from templates according to the
+current configuration.
+
+Usage: $0 [OPTIONS] [FILE]...
+
+  -h, --help       print this help, then exit
+  -V, --version    print version number and configuration settings, then exit
+  -q, --quiet      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
+  --header=FILE[:TEMPLATE]
+		   instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Report bugs to <bug-autoconf at gnu.org>."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+ac_cs_version="\\
+WCSLIB config.status 4.16
+configured by $0, generated by GNU Autoconf 2.61,
+  with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright (C) 2006 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'
+INSTALL='$INSTALL'
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If no file are specified by the user, then we need to provide default
+# value.  By we need to know if files were specified by the user.
+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=$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 )
+    echo "$ac_cs_version"; exit ;;
+  --debug | --debu | --deb | --de | --d | -d )
+    debug=: ;;
+  --file | --fil | --fi | --f )
+    $ac_shift
+    CONFIG_FILES="$CONFIG_FILES $ac_optarg"
+    ac_need_defaults=false;;
+  --header | --heade | --head | --hea )
+    $ac_shift
+    CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
+    ac_need_defaults=false;;
+  --he | --h)
+    # Conflict between --help and --header
+    { echo "$as_me: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&2
+   { (exit 1); exit 1; }; };;
+  --help | --hel | -h )
+    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.
+  -*) { echo "$as_me: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&2
+   { (exit 1); exit 1; }; } ;;
+
+  *) ac_config_targets="$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
+if \$ac_cs_recheck; then
+  echo "running CONFIG_SHELL=$SHELL $SHELL $0 "$ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
+  CONFIG_SHELL=$SHELL
+  export CONFIG_SHELL
+  exec $SHELL "$0"$ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+exec 5>>config.log
+{
+  echo
+  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+  echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+  case $ac_config_target in
+    "makedefs") CONFIG_FILES="$CONFIG_FILES makedefs" ;;
+    "wcslib.pc") CONFIG_FILES="$CONFIG_FILES wcslib.pc" ;;
+    "wcsconfig.h") CONFIG_HEADERS="$CONFIG_HEADERS wcsconfig.h" ;;
+    "wcsconfig_f77.h") CONFIG_HEADERS="$CONFIG_HEADERS wcsconfig_f77.h" ;;
+    "wcsconfig_tests.h") CONFIG_HEADERS="$CONFIG_HEADERS wcsconfig_tests.h" ;;
+    "wcsconfig_utils.h") CONFIG_HEADERS="$CONFIG_HEADERS wcsconfig_utils.h" ;;
+
+  *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
+echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
+   { (exit 1); exit 1; }; };;
+  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
+  test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+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=
+  trap 'exit_status=$?
+  { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status
+' 0
+  trap '{ (exit 1); exit 1; }' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+  tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+  test -n "$tmp" && test -d "$tmp"
+}  ||
+{
+  tmp=./conf$$-$RANDOM
+  (umask 077 && mkdir "$tmp")
+} ||
+{
+   echo "$me: cannot create a temporary directory in ." >&2
+   { (exit 1); exit 1; }
+}
+
+#
+# Set up the sed scripts for CONFIG_FILES section.
+#
+
+# No need to generate the scripts if there are no CONFIG_FILES.
+# This happens for instance when ./config.status config.h
+if test -n "$CONFIG_FILES"; then
+
+_ACEOF
+
+
+
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+  cat >conf$$subs.sed <<_ACEOF
+SHELL!$SHELL$ac_delim
+PATH_SEPARATOR!$PATH_SEPARATOR$ac_delim
+PACKAGE_NAME!$PACKAGE_NAME$ac_delim
+PACKAGE_TARNAME!$PACKAGE_TARNAME$ac_delim
+PACKAGE_VERSION!$PACKAGE_VERSION$ac_delim
+PACKAGE_STRING!$PACKAGE_STRING$ac_delim
+PACKAGE_BUGREPORT!$PACKAGE_BUGREPORT$ac_delim
+exec_prefix!$exec_prefix$ac_delim
+prefix!$prefix$ac_delim
+program_transform_name!$program_transform_name$ac_delim
+bindir!$bindir$ac_delim
+sbindir!$sbindir$ac_delim
+libexecdir!$libexecdir$ac_delim
+datarootdir!$datarootdir$ac_delim
+datadir!$datadir$ac_delim
+sysconfdir!$sysconfdir$ac_delim
+sharedstatedir!$sharedstatedir$ac_delim
+localstatedir!$localstatedir$ac_delim
+includedir!$includedir$ac_delim
+oldincludedir!$oldincludedir$ac_delim
+docdir!$docdir$ac_delim
+infodir!$infodir$ac_delim
+htmldir!$htmldir$ac_delim
+dvidir!$dvidir$ac_delim
+pdfdir!$pdfdir$ac_delim
+psdir!$psdir$ac_delim
+libdir!$libdir$ac_delim
+localedir!$localedir$ac_delim
+mandir!$mandir$ac_delim
+DEFS!$DEFS$ac_delim
+ECHO_C!$ECHO_C$ac_delim
+ECHO_N!$ECHO_N$ac_delim
+ECHO_T!$ECHO_T$ac_delim
+LIBS!$LIBS$ac_delim
+build_alias!$build_alias$ac_delim
+host_alias!$host_alias$ac_delim
+target_alias!$target_alias$ac_delim
+LIBVER!$LIBVER$ac_delim
+build!$build$ac_delim
+build_cpu!$build_cpu$ac_delim
+build_vendor!$build_vendor$ac_delim
+build_os!$build_os$ac_delim
+ARCH!$ARCH$ac_delim
+FLEX!$FLEX$ac_delim
+CC!$CC$ac_delim
+CFLAGS!$CFLAGS$ac_delim
+LDFLAGS!$LDFLAGS$ac_delim
+CPPFLAGS!$CPPFLAGS$ac_delim
+ac_ct_CC!$ac_ct_CC$ac_delim
+EXEEXT!$EXEEXT$ac_delim
+OBJEXT!$OBJEXT$ac_delim
+CPP!$CPP$ac_delim
+GREP!$GREP$ac_delim
+EGREP!$EGREP$ac_delim
+LIBOBJS!$LIBOBJS$ac_delim
+F77!$F77$ac_delim
+FFLAGS!$FFLAGS$ac_delim
+ac_ct_F77!$ac_ct_F77$ac_delim
+FLIBS!$FLIBS$ac_delim
+RANLIB!$RANLIB$ac_delim
+SHRLIB!$SHRLIB$ac_delim
+SONAME!$SONAME$ac_delim
+SHRFLAGS!$SHRFLAGS$ac_delim
+SHRLD!$SHRLD$ac_delim
+SHRSFX!$SHRSFX$ac_delim
+SHRLN!$SHRLN$ac_delim
+LN_S!$LN_S$ac_delim
+INSTALL_PROGRAM!$INSTALL_PROGRAM$ac_delim
+INSTALL_SCRIPT!$INSTALL_SCRIPT$ac_delim
+INSTALL_DATA!$INSTALL_DATA$ac_delim
+XMKMF!$XMKMF$ac_delim
+CFITSIOINC!$CFITSIOINC$ac_delim
+CFITSIOLIB!$CFITSIOLIB$ac_delim
+GETWCSTAB!$GETWCSTAB$ac_delim
+PGPLOTINC!$PGPLOTINC$ac_delim
+PGPLOTLIB!$PGPLOTLIB$ac_delim
+SUBDIRS!$SUBDIRS$ac_delim
+TSTDIRS!$TSTDIRS$ac_delim
+INSTDIR!$INSTDIR$ac_delim
+LTLIBOBJS!$LTLIBOBJS$ac_delim
+_ACEOF
+
+  if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 80; then
+    break
+  elif $ac_last_try; then
+    { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
+echo "$as_me: error: could not make $CONFIG_STATUS" >&2;}
+   { (exit 1); exit 1; }; }
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+
+ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed`
+if test -n "$ac_eof"; then
+  ac_eof=`echo "$ac_eof" | sort -nru | sed 1q`
+  ac_eof=`expr $ac_eof + 1`
+fi
+
+cat >>$CONFIG_STATUS <<_ACEOF
+cat >"\$tmp/subs-1.sed" <<\CEOF$ac_eof
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b end
+_ACEOF
+sed '
+s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g
+s/^/s,@/; s/!/@,|#_!!_#|/
+:n
+t n
+s/'"$ac_delim"'$/,g/; t
+s/$/\\/; p
+N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n
+' >>$CONFIG_STATUS <conf$$subs.sed
+rm -f conf$$subs.sed
+cat >>$CONFIG_STATUS <<_ACEOF
+:end
+s/|#_!!_#|//g
+CEOF$ac_eof
+_ACEOF
+
+
+# VPATH may cause trouble with some makes, so we remove $(srcdir),
+# ${srcdir} and @srcdir@ 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[	 ]*=/{
+s/:*\$(srcdir):*/:/
+s/:*\${srcdir}:*/:/
+s/:*@srcdir@:*/:/
+s/^\([^=]*=[	 ]*\):*/\1/
+s/:*$//
+s/^[^=]*=[	 ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+fi # test -n "$CONFIG_FILES"
+
+
+for ac_tag in  :F $CONFIG_FILES  :H $CONFIG_HEADERS
+do
+  case $ac_tag in
+  :[FHLC]) ac_mode=$ac_tag; continue;;
+  esac
+  case $ac_mode$ac_tag in
+  :[FHL]*:*);;
+  :L* | :C*:*) { { echo "$as_me:$LINENO: error: Invalid tag $ac_tag." >&5
+echo "$as_me: error: Invalid tag $ac_tag." >&2;}
+   { (exit 1); exit 1; }; };;
+  :[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="$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 ||
+	   { { echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5
+echo "$as_me: error: cannot find input file: $ac_f" >&2;}
+   { (exit 1); exit 1; }; };;
+      esac
+      ac_file_inputs="$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 "`IFS=:
+	  echo $* | sed 's|^[^:]*/||;s|:[^:]*/|, |g'`" by configure."
+    if test x"$ac_file" != x-; then
+      configure_input="$ac_file.  $configure_input"
+      { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+    fi
+
+    case $ac_tag in
+    *:-:* | *:-) cat >"$tmp/stdin";;
+    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 ||
+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"
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`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 ||
+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" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5
+echo "$as_me: error: cannot create directory $as_dir" >&2;}
+   { (exit 1); exit 1; }; }; }
+  ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`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
+  #
+
+  case $INSTALL in
+  [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+  *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
+  esac
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# 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=
+
+case `sed -n '/datarootdir/ {
+  p
+  q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p
+' $ac_file_inputs` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+  { echo "$as_me:$LINENO: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+  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
+  sed "$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s&@configure_input@&$configure_input&;t t
+s&@top_builddir@&$ac_top_builddir_sub&;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
+s&@INSTALL@&$ac_INSTALL&;t t
+$ac_datarootdir_hack
+" $ac_file_inputs | sed -f "$tmp/subs-1.sed" >$tmp/out
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+  { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } &&
+  { ac_out=`sed -n '/^[	 ]*datarootdir[	 ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } &&
+  { echo "$as_me:$LINENO: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined." >&5
+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 "$tmp/stdin"
+  case $ac_file in
+  -) cat "$tmp/out"; rm -f "$tmp/out";;
+  *) rm -f "$ac_file"; mv "$tmp/out" $ac_file;;
+  esac
+ ;;
+  :H)
+  #
+  # CONFIG_HEADER
+  #
+_ACEOF
+
+# Transform confdefs.h into a sed script `conftest.defines', that
+# substitutes the proper values into config.h.in to produce config.h.
+rm -f conftest.defines conftest.tail
+# First, append a space to every undef/define line, to ease matching.
+echo 's/$/ /' >conftest.defines
+# Then, protect against being on the right side of a sed subst, or in
+# an unquoted here document, in config.status.  If some macros were
+# called several times there might be several #defines for the same
+# symbol, which is useless.  But do not sort them, since the last
+# AC_DEFINE must be honored.
+ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
+# These sed commands are passed to sed as "A NAME B PARAMS C VALUE D", where
+# NAME is the cpp macro being defined, VALUE is the value it is being given.
+# PARAMS is the parameter list in the macro definition--in most cases, it's
+# just an empty string.
+ac_dA='s,^\\([	 #]*\\)[^	 ]*\\([	 ]*'
+ac_dB='\\)[	 (].*,\\1define\\2'
+ac_dC=' '
+ac_dD=' ,'
+
+uniq confdefs.h |
+  sed -n '
+	t rset
+	:rset
+	s/^[	 ]*#[	 ]*define[	 ][	 ]*//
+	t ok
+	d
+	:ok
+	s/[\\&,]/\\&/g
+	s/^\('"$ac_word_re"'\)\(([^()]*)\)[	 ]*\(.*\)/ '"$ac_dA"'\1'"$ac_dB"'\2'"${ac_dC}"'\3'"$ac_dD"'/p
+	s/^\('"$ac_word_re"'\)[	 ]*\(.*\)/'"$ac_dA"'\1'"$ac_dB$ac_dC"'\2'"$ac_dD"'/p
+  ' >>conftest.defines
+
+# Remove the space that was appended to ease matching.
+# Then replace #undef with comments.  This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+# (The regexp can be short, since the line contains either #define or #undef.)
+echo 's/ $//
+s,^[	 #]*u.*,/* & */,' >>conftest.defines
+
+# Break up conftest.defines:
+ac_max_sed_lines=50
+
+# First sed command is:	 sed -f defines.sed $ac_file_inputs >"$tmp/out1"
+# Second one is:	 sed -f defines.sed "$tmp/out1" >"$tmp/out2"
+# Third one will be:	 sed -f defines.sed "$tmp/out2" >"$tmp/out1"
+# et cetera.
+ac_in='$ac_file_inputs'
+ac_out='"$tmp/out1"'
+ac_nxt='"$tmp/out2"'
+
+while :
+do
+  # Write a here document:
+    cat >>$CONFIG_STATUS <<_ACEOF
+    # First, check the format of the line:
+    cat >"\$tmp/defines.sed" <<\\CEOF
+/^[	 ]*#[	 ]*undef[	 ][	 ]*$ac_word_re[	 ]*\$/b def
+/^[	 ]*#[	 ]*define[	 ][	 ]*$ac_word_re[(	 ]/b def
+b
+:def
+_ACEOF
+  sed ${ac_max_sed_lines}q conftest.defines >>$CONFIG_STATUS
+  echo 'CEOF
+    sed -f "$tmp/defines.sed"' "$ac_in >$ac_out" >>$CONFIG_STATUS
+  ac_in=$ac_out; ac_out=$ac_nxt; ac_nxt=$ac_in
+  sed 1,${ac_max_sed_lines}d conftest.defines >conftest.tail
+  grep . conftest.tail >/dev/null || break
+  rm -f conftest.defines
+  mv conftest.tail conftest.defines
+done
+rm -f conftest.defines conftest.tail
+
+echo "ac_result=$ac_in" >>$CONFIG_STATUS
+cat >>$CONFIG_STATUS <<\_ACEOF
+  if test x"$ac_file" != x-; then
+    echo "/* $configure_input  */" >"$tmp/config.h"
+    cat "$ac_result" >>"$tmp/config.h"
+    if diff $ac_file "$tmp/config.h" >/dev/null 2>&1; then
+      { echo "$as_me:$LINENO: $ac_file is unchanged" >&5
+echo "$as_me: $ac_file is unchanged" >&6;}
+    else
+      rm -f $ac_file
+      mv "$tmp/config.h" $ac_file
+    fi
+  else
+    echo "/* $configure_input  */"
+    cat "$ac_result"
+  fi
+  rm -f "$tmp/out12"
+ ;;
+
+
+  esac
+
+done # for ac_tag
+
+
+{ (exit 0); exit 0; }
+_ACEOF
+chmod +x $CONFIG_STATUS
+ac_clean_files=$ac_clean_files_save
+
+
+# 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 || { (exit 1); exit 1; }
+fi
+
diff --git a/cextern/wcslib/configure.ac b/cextern/wcslib/configure.ac
new file mode 100644
index 0000000..22a83c8
--- /dev/null
+++ b/cextern/wcslib/configure.ac
@@ -0,0 +1,522 @@
+#-----------------------------------------------------------------------------
+# Process this file with autoconf-2.53 or later to produce a configure script.
+#-----------------------------------------------------------------------------
+# N.B. it is necessary to run autoconf on a Mac in order for configure to
+# locate the X11 dylibs for PGPLOT.  Use autoconf-2.61 in MacOSX 10.6.2 or
+# later to avoid spurious messages about deleting conftest.dSYM when
+# configuring in MacOSX 10.6.
+#
+# Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
+# http://www.atnf.csiro.au/people/Mark.Calabretta
+# $Id: configure.ac,v 4.16 2012/11/07 04:42:45 cal103 Exp $
+#-----------------------------------------------------------------------------
+
+AC_INIT([WCSLIB], [4.16], [mark at calabretta.id.au], [wcslib-4.16])
+AC_PREREQ([2.53])
+AC_REVISION([$Revision: 4.16 $])
+AC_SUBST([PACKAGE_VERSION])
+AC_DEFINE_UNQUOTED([WCSLIB_VERSION], [$PACKAGE_VERSION], [Define wcslib version])
+
+# Library version number, same as package version.
+LIBVER="$PACKAGE_VERSION"
+AC_SUBST([LIBVER])
+
+AC_CONFIG_SRCDIR([C/wcs.h])
+AC_CONFIG_AUX_DIR([config])
+
+# Get the system type.
+AC_CANONICAL_BUILD
+ARCH="${build_cpu}-$build_os"
+AC_SUBST([ARCH])
+
+
+# Look for Flex.
+AC_CHECK_PROG([FLEX], [flex], [flex], [], [], [])
+if test "x$FLEX" = xflex ; then
+  # Version 2.5.9 or later is required.
+  V=`flex --version | awk '{print $NF}'`
+  W=`echo $V | awk -F. '{if ((($1*100 + $2)*100 + $3) < 20509) print "no"}'`
+  if test "x$W" != x ; then
+    AC_MSG_NOTICE([Flex version $V is too old, ignored.])
+    FLEX=
+  else
+    AC_MSG_NOTICE([Using Flex version $V.])
+  fi
+fi
+
+if test "x$FLEX" = x ; then
+  AC_MSG_WARN([Flex version 2.5.9 or later does not appear to be
+           available, will use pre-generated sources.])
+fi
+
+
+# Look for an ANSI C compiler.
+AC_PROG_CPP
+AC_PROG_CC
+AC_PROG_CC_STDC
+AC_C_CONST
+AC_TYPE_SIZE_T
+if test "x$ac_cv_prog_cc_stdc" = xno -o \
+        "x$ac_cv_c_const"      = xno -o \
+        "x$ac_cv_type_size_t"  = xno; then
+  AC_MSG_ERROR([
+    -------------------------------------------------------
+    An ANSI standard C library is required to build WCSLIB.
+
+    ERROR: WCSLIB configuration failure.
+    -------------------------------------------------------], [1])
+fi
+
+# Check for data types (suggested by autoscan - off_t is only required by
+# fitshdr).
+AC_TYPE_OFF_T
+AC_TYPE_INT8_T
+AC_TYPE_INT16_T
+AC_TYPE_INT32_T
+AC_TYPE_UINT8_T
+AC_TYPE_UINT16_T
+AC_TYPE_UINT32_T
+
+# Check for ANSI C headers.
+AC_HEADER_STDC
+AC_CHECK_HEADERS([ctype.h errno.h limits.h locale.h math.h setjmp.h stdarg.h \
+                  stdio.h stdlib.h string.h])
+if test "x$ac_cv_header_stdc" = xno; then
+  AC_MSG_ERROR([
+    -------------------------------------------------------------------
+    An ANSI standard C library is required to build WCSLIB.  One of the
+    ANSI C header files it requires is missing or unusable.
+
+    ERROR: WCSLIB configuration failure.
+    -------------------------------------------------------------------], [1])
+fi
+
+# Checks for ANSI C library functions (suggested by autoscan - fseeko and
+# stat are only required by fitshdr).
+AC_CHECK_LIB([m], [floor])
+AC_FUNC_FSEEKO
+AC_FUNC_MALLOC
+AC_FUNC_REALLOC
+AC_FUNC_SETVBUF_REVERSED
+AC_FUNC_STAT
+AC_FUNC_VPRINTF
+AC_CHECK_FUNCS([floor memset pow setlocale sqrt strchr strstr])
+
+# System libraries that may be required by WCSLIB itself.
+# SunOS, extra maths functions.
+AC_CHECK_LIB([sunmath], [cosd], [LIBS="-lsunmath $LIBS"], [], [])
+
+# See if we can find sincos().
+AC_CHECK_FUNCS([sincos])
+
+# Check the size and availability of integer data types.
+AC_CHECK_SIZEOF([int])
+AC_CHECK_SIZEOF([long int])
+AC_CHECK_SIZEOF([long long int])
+
+# 64-bit integer data type; use long long int preferentially since that
+# accords with "%lld" formatting used in fitshdr.l, e.g.
+#                int   size_t  long int  long long int
+#                ---   ------  --------  -------------
+#   gcc x86:      32     32       32          64
+#   gcc x86_64:   32     64       64          64
+if test "x$ac_cv_sizeof_long_long_int" = x8; then
+  AC_DEFINE([WCSLIB_INT64], [long long int], [64-bit integer data type.])
+elif test "x$ac_cv_sizeof_long_int" = x8; then
+  AC_DEFINE([WCSLIB_INT64], [long int], [64-bit integer data type.])
+elif test "x$ac_cv_sizeof_int" = x8; then
+  AC_DEFINE([WCSLIB_INT64], [int], [64-bit integer data type.])
+fi
+
+# Does printf() have the z modifier for size_t type?  Important for 64-bit.
+AC_MSG_CHECKING([for printf z format modifier for size_t type])
+AC_RUN_IFELSE(
+  [AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT],
+                   [[char buf[64];
+                     if (sprintf(buf, "%zu", (size_t)1) != 1)
+                       return 1;
+                     else if (strcmp(buf, "1"))
+                       return 2;]])],
+  AC_DEFINE([MODZ], ["z"], [printf format modifier for size_t type.])
+    AC_MSG_RESULT(yes),
+  AC_DEFINE([MODZ], [""],  [printf format modifier for size_t type.])
+    AC_MSG_RESULT(no),
+  AC_DEFINE([MODZ], [""],  [printf format modifier for size_t type.])
+    AC_MSG_RESULT(assumed not)
+)
+
+
+# Starting values, may be augmented later.
+SUBDIRS="C"
+TSTDIRS="C"
+INSTDIR="C"
+
+
+# Ways of specifying the Fortran compiler, in order of precedence:
+#   configure --enable-fortran=<compiler>
+#   F77=<compiler> configure    ...bash
+#
+# Ways of disabling Fortran:
+#   configure --disable-fortran
+#   configure --enable-fortran=no
+#   F77=no configure            ...bash
+AC_ARG_ENABLE([fortran], [AS_HELP_STRING([--enable-fortran=ARG],
+            [Fortran compiler to use])], [])
+AC_ARG_ENABLE([fortran], [AS_HELP_STRING([--disable-fortran],
+            [don't build the Fortran wrappers or PGSBOX])], [])
+if test "x$enable_fortran" != x -a "x$enable_fortran" != xyes ; then
+  F77="$enable_fortran"
+fi
+
+if test "x$F77" = xno ; then
+  F77=
+
+  AC_MSG_WARN([Compilation of Fortran wrappers and PGSBOX disabled])
+
+else
+  if test "x$F77" = x ; then
+    # Look for a Fortran compiler.
+    AC_PROG_F77([gfortran g77 f77 ifort xlf frt pgf77 fl32 af77 fort77 f90 \
+                 xlf90 pgf90 epcf90 f95 fort xlf95 lf95 g95])
+  fi
+
+  if test "x$F77" = x; then
+    AC_MSG_WARN([
+      ------------------------------------------------------------------
+      Fortran compiler not found, will skip Fortran wrappers and PGSBOX.
+      ------------------------------------------------------------------])
+
+    # Best guess at Fortran name mangling for use if a compiler does ever
+    # become available.
+    AC_DEFINE([F77_FUNC(name,NAME)], [name ## _])
+
+  else
+    if test "x$ac_cv_f77_compiler_gnu" = xyes ; then
+      if test "x$F77" = xg77 -o "x$F77" = xf77 ; then
+        # Not recognized by gfortran.
+        FFLAGS="$FFLAGS -Wno-globals"
+      fi
+    fi
+
+    AC_MSG_CHECKING(whether $F77 accepts -I)
+    AC_LANG_PUSH(Fortran 77)
+    FFLAGS_save=$FFLAGS
+    FFLAGS=-I.
+    AC_COMPILE_IFELSE(AC_LANG_PROGRAM([], []),
+      [FFLAGS="$FFLAGS_save -I."; AC_MSG_RESULT(yes)],
+      [FFLAGS="$FFLAGS_save"; AC_MSG_RESULT(no)])
+    AC_LANG_POP()
+
+    # Libraries required by the Fortran compiler itself (sets FLIBS).
+    # Required by utilities and test programs written in C that link to
+    # Fortran object modules such as pgsbox.
+    AC_F77_LIBRARY_LDFLAGS
+
+    # F77 name mangling (defines the F77_FUNC preprocessor macro).
+    AC_F77_WRAPPERS
+
+    SUBDIRS="C Fortran"
+    TSTDIRS="C Fortran"
+    INSTDIR="Fortran"
+  fi
+fi
+
+
+# System-dependent system libraries (for building the sharable library).
+#-----------------------------------------------------------------------
+# Darwin (contains stubs for long double).
+AC_CHECK_LIB([SystemStubs], [printf\$LDBLStub], [LIBS="$LIBS -lSystemStubs"],
+             [], [])
+
+
+# Library and installation utilities.
+#------------------------------------
+# Static library generation.
+AC_PROG_RANLIB
+
+# Shared library generation.
+if test "x$ac_cv_c_compiler_gnu" = xyes ; then
+  SHVER=`echo "$LIBVER" | sed -e 's/\..*$//'`
+
+  # Note that -fPIC is on by default for Macs, this just makes it obvious.
+  SHRFLAGS="-fPIC"
+  SHRLD="\$(CC) \$(SHRFLAGS)"
+
+  case "$build_os" in
+  darwin*)
+    SHRLIB="libwcs.$LIBVER.dylib"
+    SONAME="libwcs.$SHVER.dylib"
+    SHRLD="$SHRLD -dynamiclib -single_module"
+    SHRLD="$SHRLD -compatibility_version $SHVER -current_version $LIBVER"
+    SHRLN=
+
+    case "$build_cpu" in
+    powerpc*)
+      # Switch off -fPIC (not applicable for PowerPC Macs).
+      CFLAGS="$CFLAGS -mdynamic-no-pic"
+      ;;
+    esac
+    ;;
+  *)
+    # Covers Linux and Solaris at least.
+    SHRLIB="libwcs.so.$LIBVER"
+    SONAME="libwcs.so.$SHVER"
+    SHRLD="$SHRLD -shared -Wl,-h\$(SONAME)"
+    SHRLN="libwcs.so"
+    ;;
+  esac
+
+else
+  SHRLIB=
+  SONAME=
+  SHRFLAGS=
+  SHRLD=
+  SHRSFX=
+  SHRLN=
+fi
+
+AC_SUBST([SHRLIB])
+AC_SUBST([SONAME])
+AC_SUBST([SHRFLAGS])
+AC_SUBST([SHRLD])
+AC_SUBST([SHRSFX])
+AC_SUBST([SHRLN])
+
+# Installation utilities.
+AC_PROG_LN_S
+AC_PROG_INSTALL
+
+AC_MSG_NOTICE([End of primary configuration.
+])
+
+
+# The following are required to build utilities and test programs.
+# ----------------------------------------------------------------
+AC_MSG_NOTICE([Looking for libraries etc. for utilities and test suite...])
+
+# Check for other quasi-standard header files.
+AC_CHECK_HEADERS([unistd.h])
+
+# Large file support.
+AC_FUNC_FSEEKO
+AC_SYS_LARGEFILE
+
+
+# Extra places to look for third-party libraries and header files.
+LIBDIRS=
+
+AC_ARG_WITH([cfitsio], [AS_HELP_STRING([--without-cfitsio],
+            [eschew CFITSIO])], [])
+if test "x$with_cfitsio" = xno ; then
+  AC_MSG_WARN([CFITSIO disabled])
+else
+  AC_ARG_WITH([cfitsiolib], [AS_HELP_STRING([--with-cfitsiolib=DIR],
+              [directory containing cfitsio library])], [])
+  if test "x$with_cfitsiolib" != x ; then
+    LIBDIRS="$LIBDIRS $with_cfitsiolib"
+  fi
+
+  AC_ARG_WITH([cfitsioinc], [AS_HELP_STRING([--with-cfitsioinc=DIR],
+              [directory containing cfitsio header files])], [])
+  if test "x$with_cfitsioinc" != x ; then
+    CFITSIO_INCDIRS="$with_cfitsioinc"
+  fi
+
+  CFITSIO_INCDIRS="$CFITSIO_INCDIRS   \
+           /usr/local/cfitsio/include \
+           /local/cfitsio/include"
+
+  LIBDIRS="$LIBDIRS           \
+           /usr/local/cfitsio/lib \
+           /local/cfitsio/lib"
+fi
+
+AC_ARG_WITH([pgplot], [AS_HELP_STRING([--without-pgplot],
+            [eschew PGPLOT])], [])
+if test "x$with_pgplot" = xno ; then
+  AC_MSG_WARN([PGPLOT disabled])
+else
+  AC_ARG_WITH([pgplotlib], [AS_HELP_STRING([--with-pgplotlib=DIR],
+              [directory containing pgplot library])], [])
+  if test "x$with_pgplotlib" != x ; then
+    LIBDIRS="$LIBDIRS $with_pgplotlib"
+  fi
+
+  AC_ARG_WITH([pgplotinc], [AS_HELP_STRING([--with-pgplotinc=DIR],
+              [directory containing pgplot header files])], [])
+  if test "x$with_pgplotinc" != x ; then
+    PGPLOT_INCDIRS="$with_pgplotinc"
+  fi
+
+  PGPLOT_INCDIRS="$PGPLOT_INCDIRS    \
+           /usr/local/pgplot/include \
+           /local/pgplot/include"
+
+  LIBDIRS="$LIBDIRS           \
+           /usr/local/pgplot/lib  \
+           /local/pgplot/lib"
+fi
+
+
+if test "x$with_cfitsio" != xno -o \
+        "x$with_pgplot"  != xno ; then
+  LIBDIRS="$LIBDIRS           \
+           /usr/local/lib     \
+           /local/lib         \
+           /opt/local/lib     \
+           /opt/SUNWspro/lib  \
+           /sw/lib"
+
+  for LIBDIR in $LIBDIRS ; do
+    AC_CHECK_FILE([$LIBDIR], [LDFLAGS="$LDFLAGS -L$LIBDIR"], [continue])
+  done
+
+  # Generic include directories.
+  INCDIRS="/usr/local/include \
+           /local/include     \
+           /opt/local/include \
+           /sw/include        \
+           /local             \
+           /usr/include"
+
+
+  # CFITSIO.
+  if test "x$with_cfitsio" != xno ; then
+    # Search for CFITSIO.
+    for INCDIR in $CFITSIO_INCDIRS $INCDIRS ; do
+      AC_CHECK_FILE([$INCDIR/cfitsio/fitsio.h],
+                    [CFITSIOINC="-I$INCDIR/cfitsio"; break])
+      AC_CHECK_FILE([$INCDIR/fitsio.h], [CFITSIOINC="-I$INCDIR"; break])
+    done
+
+    AC_CHECK_LIB([socket],  [recv],   [CFITSIOLIB="-lsocket"], [], [$LIBS])
+    AC_CHECK_LIB([cfitsio], [ffopen], [CFITSIOLIB="-lcfitsio $CFITSIOLIB"], [],
+                 [$CFITSIOLIB $LIBS])
+
+    if test "x$CFITSIOINC" = x -o "x$CFITSIOLIB" = x; then
+      AC_MSG_WARN([CFITSIO not found, skipping CFITSIO-dependent tests.])
+    else
+      AC_MSG_NOTICE([CFITSIO appears to be available.])
+      AC_DEFINE([HAVE_CFITSIO], [1], [Define to 1 if CFITSIO is available.])
+
+      # Check for fits_read_wcstab, present in CFITSIO 3.004beta and later.
+      AC_CHECK_LIB([cfitsio], [fits_read_wcstab], [GETWCSTAB=],
+                   [GETWCSTAB=getwcstab.o], [$CFITSIOLIB $LIBS])
+      if test "x$GETWCSTAB" != x ; then
+        AC_MSG_WARN([fits_read_wcstab not found in CFITSIO, will use
+                        getwcstab.c to compile test programs.])
+      fi
+    fi
+  fi
+
+  # PGPLOT.
+  if test "x$F77" != x -a "x$with_pgplot" != xno ; then
+    # Search for PGPLOT.
+    for INCDIR in $PGPLOT_INCDIRS $INCDIRS ; do
+      AC_CHECK_FILE([$INCDIR/pgplot/cpgplot.h],
+                    [PGPLOTINC="-I$INCDIR/pgplot"; break])
+      AC_CHECK_FILE([$INCDIR/cpgplot.h], [PGPLOTINC="-I$INCDIR"; break])
+    done
+
+    # FLIBS (found above via AC_F77_LIBRARY_LDFLAGS) only helps if PGPLOT was
+    # built using the same Fortran compiler that we are using here.
+
+    # PGPLOT compiled by the SUN Fortran compiler but linked with something
+    # else.
+    AC_CHECK_LIB([M77],     [iand_],     [PGPLOTLIB="-lM77 $PGPLOTLIB"],
+                 [], [$PGPLOTLIB $LIBS])
+    AC_CHECK_LIB([F77],     [f77_init],  [PGPLOTLIB="-lF77 $PGPLOTLIB"],
+                 [], [$PGPLOTLIB $LIBS])
+
+    if test "x$F77" != xg77; then
+      # For PGPLOT compiled with g77 but linked with something else.
+      AC_CHECK_LIB([frtbegin], [main],     [PGPLOTLIB="-lfrtbegin $PGPLOTLIB"],
+                   [], [$PGPLOTLIB $LIBS])
+      AC_CHECK_LIB([g2c],      [gerror_],  [PGPLOTLIB="-lg2c $PGPLOTLIB"],
+                   [], [$PGPLOTLIB $LIBS])
+    fi
+
+    if test "x$F77" != xgfortran; then
+      # For PGPLOT compiled with gfortran but linked with something else.
+      # Note that if gfortran itself is driving the linker it can be harmful
+      # to add -lgfortran to the link list without also adding -lgfortranbegin.
+      # Doing so stops gfortran from adding -lgfortranbegin which is needed to
+      # resolve "main".
+      AC_CHECK_LIB([gfortran], [_gfortran_abort],
+                   [PGPLOTLIB="-lgfortran $PGPLOTLIB"], [],
+                   [$PGPLOTLIB $LIBS])
+    fi
+
+    # Search for X11 includes and libraries.
+    AC_PATH_X
+    if test "x$no_x" = x; then
+      if test "x$ac_x_libraries" != x ; then
+        # Not needed for systems that keep the X11 libraries in /usr/lib.
+        LDFLAGS="$LDFLAGS -L$ac_x_libraries"
+      fi
+      PGPLOTLIB="-lX11 $PGPLOTLIB"
+    fi
+
+    # It is possible that other libraries may be required depending on what
+    # graphics drivers were installed with PGPLOT.
+    AC_CHECK_LIB([z],       [deflate],   [PGPLOTLIB="-lz $PGPLOTLIB"],
+                 [], [$PGPLOTLIB $LIBS])
+    AC_CHECK_LIB([png],     [png_error], [PGPLOTLIB="-lpng $PGPLOTLIB"],
+                 [], [$PGPLOTLIB $LIBS])
+    AC_CHECK_LIB([pgplot],  [pgbeg_],    [PGPLOTLIB="-lpgplot $PGPLOTLIB"],
+                 [], [$PGPLOTLIB $FLIBS $LIBS])
+    AC_CHECK_LIB([cpgplot], [cpgbeg],    [PGPLOTLIB="-lcpgplot $PGPLOTLIB"],
+                 [PGPLOTLIB=], [$PGPLOTLIB $FLIBS $LIBS])
+
+    # Only need the PGPLOT include file to build PGSBOX.
+    if test "x$PGPLOTINC" != x; then
+      SUBDIRS="$SUBDIRS pgsbox"
+      INSTDIR="pgsbox"
+    fi
+
+    # Also need the PGPLOT library to build pgtest and cpgtest.
+    if test "x$PGPLOTLIB" = x; then
+      AC_MSG_WARN([PGPLOT not found, skipping PGPLOT-dependent tests.])
+    else
+      AC_MSG_NOTICE([PGPLOT appears to be available.])
+
+      TSTDIRS="$TSTDIRS pgsbox"
+    fi
+  fi
+fi
+
+
+# Utilities are compiled last since they need the libraries.
+# Ways of disabling them:
+#   configure --disable-utils
+#   configure --enable-utils=no
+AC_ARG_ENABLE([utils], [AS_HELP_STRING([--disable-utils],
+            [don't build the WCS utilities])], [])
+if test "x$enable_utils" != xno ; then
+  SUBDIRS="$SUBDIRS utils"
+  INSTDIR="$INSTDIR utils"
+else
+  AC_MSG_WARN([Compilation of WCS utilities disabled])
+fi
+
+
+AC_SUBST([CFITSIOINC])
+AC_SUBST([CFITSIOLIB])
+AC_SUBST([GETWCSTAB])
+
+AC_SUBST([PGPLOTINC])
+AC_SUBST([PGPLOTLIB])
+
+AC_SUBST([SUBDIRS])
+AC_SUBST([TSTDIRS])
+AC_SUBST([INSTDIR])
+
+AC_MSG_NOTICE([End of auxiliary configuration.
+])
+
+
+# Do it.
+AC_MSG_NOTICE([Configuring files...])
+AC_CONFIG_FILES([makedefs wcslib.pc])
+AC_CONFIG_HEADERS([wcsconfig.h wcsconfig_f77.h wcsconfig_tests.h wcsconfig_utils.h])
+AC_OUTPUT
diff --git a/cextern/wcslib/flavours b/cextern/wcslib/flavours
new file mode 100644
index 0000000..e95dc00
--- /dev/null
+++ b/cextern/wcslib/flavours
@@ -0,0 +1,160 @@
+#-----------------------------------------------------------------------------
+# Makefile overrides for various combinations of architecture, operating
+# system and compiler.  Used for development and testing only, not required
+# for building WCSLIB.
+#
+# Variables like CC and CFLAGS are exported into the environment so that they
+# will be seen by 'configure'.  Thus, normal usage is as follows:
+#
+#   make distclean
+#   make FLAVOUR=Linux configure
+#   make
+#
+# Reminder: add '-d' to FLFLAGS for debugging.
+#
+# $Id: flavours,v 4.16 2012/11/07 04:42:45 cal103 Exp $
+#-----------------------------------------------------------------------------
+
+# The list of FLAVOURs can be set on the command line.
+F := $(shell echo $(FLAVOURS) | tr a-z A-Z)
+ifeq "$F" ""
+  F :=
+  FLAVOURS := ""
+endif
+
+ifeq "$F" "LINUX"
+  override FLAVOURS := "" Linux Linuxp
+endif
+
+ifeq "$F" "SUN"
+  override FLAVOURS := "" SUN/GNU SUN/GNU3 SUN/GNUp SUN/ANSI
+endif
+
+ifeq "$F" "PURE"
+  override FLAVOURS := SUN/Pure SUN/Quant
+endif
+
+F :=
+
+
+# Various C standards handled by features.h in Linux.
+FEATURES :=
+ifeq "$(notdir $(shell pwd))" "utils"
+  # To get off_t for fseeko() usage in fitshdr when gcc is invoked with the
+  # -std=c89 (same as -ansi) or the -std=c99 options.
+  FEATURES := -D_XOPEN_SOURCE
+endif
+
+
+# Linux with gcc/gfortran (also works for Darwin).
+ifeq "$(FLAVOUR)" "Linux"
+  F := $(FLAVOUR)
+  export CC       := gcc -std=c89 -pedantic
+  export CPPFLAGS := $(FEATURES)
+  export CFLAGS   := -g -O0 -Wall -Wpadded -Wno-long-long
+  export FFLAGS   := -g -O0 -fimplicit-none -Wall -I.
+         VALGRIND := valgrind -v --leak-check=yes
+endif
+
+ifeq "$(FLAVOUR)" "Linuxp"
+  F := $(FLAVOUR)
+  export CC       := gcc -std=c89 -pedantic
+  export CPPFLAGS := $(FEATURES)
+  export CFLAGS   := -pg -g -O -Wall -Wpadded -Wno-long-long
+  export FFLAGS   := -pg -a -g -O -fimplicit-none -Wall -I.
+  export LDFLAGS  := -pg -g $(filter -L%, $(LDFLAGS))
+  override EXTRA_CLEAN := gmon.out bb.out
+endif
+
+
+# Solaris with gcc/gfortran 4.x (lynx).
+ifeq "$(FLAVOUR)" "SUN/GNU"
+  F := $(FLAVOUR)
+  export CC       := gcc -std=c89
+  export CPPFLAGS := $(FEATURES)
+  export CFLAGS   := -g -Wall -Wpadded -Wno-long-long
+  export F77      := gfortran
+  export FFLAGS   := -g -fimplicit-none -Wall -I.
+  LD      := gcc
+endif
+
+ifeq "$(FLAVOUR)" "SUN/GNU3"
+  F := $(FLAVOUR)
+  export CC       := gcc-3.1.1 -std=c89
+  export CPPFLAGS := $(FEATURES)
+  export CFLAGS   := -g -Wall -Wpadded -Wno-long-long
+  export F77      := g77-3.1.1
+  export FFLAGS   := -g -Wimplicit -Wunused -Wno-globals -I.
+  LD      := gcc-3.1.1
+endif
+
+ifeq "$(FLAVOUR)" "SUN/GNUp"
+  F := $(FLAVOUR)
+  export CC       := gcc -std=c89 -pedantic
+  export CPPFLAGS := $(FEATURES)
+  export CFLAGS   := -pg -a -g -O -Wall -Wpadded -Wno-long-long
+  export FFLAGS   := -pg -a -g -O -fimplicit-none -Wall -I.
+  export LDFLAGS  := -pg -a -g $(filter -L%, $(LDFLAGS))
+  override EXTRA_CLEAN := gmon.out bb.out
+endif
+
+
+# Solaris with SUN cc/f77.
+ifeq "$(FLAVOUR)" "SUN/ANSI"
+  F := $(FLAVOUR)
+  WCSTRIG := NATIVE
+  export CC       := cc
+  export CFLAGS   := -g -I/usr/local/include
+  export F77      := f77
+  export FFLAGS   := -g -erroff=WDECL_LOCAL_NOTUSED
+  LD      := f77
+endif
+
+
+# Purify and quantify in Solaris.
+ifeq "$(FLAVOUR)" "SUN/Pure"
+  F := $(FLAVOUR)
+  WCSTRIG := NATIVE
+  export CC       := purify gcc
+  export CFLAGS   := -g
+  export F77      := purify gcc
+  export FFLAGS   := -g -Wimplicit -Wno-globals -I.
+  export LDFLAGS  := $(filter -L%, $(LDFLAGS))
+  override EXTRA_CLEAN := *_pure_p*.[ao] *.pcv .pure ../C/*_pure_p*.[ao]
+endif
+
+ifeq "$(FLAVOUR)" "SUN/Quant"
+  F := $(FLAVOUR)
+  WCSTRIG := NATIVE
+  export CC       := quantify gcc
+  export CFLAGS   := -g
+  export F77      := quantify gcc
+  export FFLAGS   := -g -Wimplicit -Wno-globals -I.
+  export LDFLAGS  := $(filter -L%, $(LDFLAGS))
+  override EXTRA_CLEAN := *_pure_q*.[ao] .pure
+endif
+
+ifneq "$F" "$(FLAVOUR)"
+  override FLAVOUR := unrecognised
+endif
+
+# gmake uses FC in place of configure's F77.
+ifdef F77
+  FC := $(F77)
+endif
+
+ifndef TIMER
+  TIMER := date +"%a %Y/%m/%d %X %z, executing on $$HOST"
+endif
+
+ifdef FLAVOUR
+  TIMER := $(TIMER) ; echo "    with $(FLAVOUR) FLAVOUR."
+endif
+
+show ::
+	-@ echo 'For code development...'
+	-@ echo '  FLAVOURS    := $(FLAVOURS)'
+	-@ echo '  FLAVOUR     := $(FLAVOUR)'
+	-@ echo '  VALGRIND    := $(VALGRIND)'
+	-@ echo '  EXTRA_CLEAN := $(EXTRA_CLEAN)'
+	-@ echo ''
diff --git a/cextern/wcslib/makedefs.in b/cextern/wcslib/makedefs.in
new file mode 100644
index 0000000..7785263
--- /dev/null
+++ b/cextern/wcslib/makedefs.in
@@ -0,0 +1,240 @@
+#-----------------------------------------------------------------------------
+# GNU makefile definitions for building WCSLIB 4.16
+#
+# makedefs is generated from makedefs.in by configure.  It contains variable
+# definitions and some general-purpose rules for building WCSLIB.
+#
+# Targets defined here
+# --------------------
+#   printenv:  Print the environment as seen within makefile rules.
+#   show:      Print the values of all makefile variables used.
+#
+# Notes:
+#   1) If you need to make changes then it may be preferable to modify
+#      makedefs.in (not makedefs).  The makefile will detect this and
+#      automatically re-run config.status to regenerate makedefs.
+#
+#   2) There are three choices for trigd functions - cosd(), sind(), tand(),
+#      acosd(), asind(), atand(), and atan2d(), made by setting WCSTRIG:
+#
+#      1: Use the wrapper functions supplied with WCSLIB (default):
+#         WCSTRIG := WRAPPER
+#
+#      2: Use native trigd functions supplied in a mathematics library such
+#         as libsunmath (you will also need to add the library to the LIBS
+#         variable below):
+#         WCSTRIG := NATIVE
+#
+#      3: Use C preprocessor macro implementations of the trigd functions
+#         (this method is typically 20% faster but may lead to rounding
+#         errors near the poles):
+#         WCSTRIG := MACRO
+#
+#   3) Variables for creating the shared (dynamic) library are currently
+#      only set by 'configure' if the GNU C compiler is used.  However,
+#      you can set these variables by hand, preferably in makedefs.in.
+#
+#      Shared libraries require position-independent code (PIC) which imposes
+#      a performance overhead.  Consequently the static libraries are
+#      compiled separately without this option.
+#
+#      The shared library will be installed with version number, e.g. as
+#      libwcs.so.4.16 or libwcs.4.16.dylib with or without the symlink
+#      required to make it visible to the linker (controlled by the SHRLN
+#      variable).  On Macs it is deliberately not created because its very
+#      existence precludes static linking with the cctools linker.  You can
+#      still link dynamically by using -lwcs.4.16.
+#
+#   4) PGPLOT is Tim Pearson's Fortran graphics library with separate C
+#      interface available from astro.caltech.edu.  It is only required by
+#      one utility, wcsgrid, and the test programs that plot test grids
+#      (tprj2, tcel1, tcel2, tspc, ttab2, ttab3, twcsmix, and tpih2).  You can
+#      skip these by setting PGPLOTLIB to blank.
+#
+#      It is difficult for configure to deduce what auxiliary graphics
+#      libraries may be needed for PGPLOT since it depends on which of many
+#      possible graphics drivers were selected when PGPLOT was installed.
+#      Therefore it is quite likely that you will need to add additional
+#      libraries to PGPLOTLIB.
+#
+#   5) CFITSIO is Bill Pence's FITS I/O library written in C with Fortran
+#      wrappers, available from http://heasarc.gsfc.nasa.gov/fitsio.
+#
+#      CFITSIO is required by three utilities, HPXcvt, wcsgrid, and wcsware,
+#      and also by the test programs twcstab and twcshdr.  wcsware and the
+#      test programs use fits_read_wcstab() which is implemented by
+#      getwcstab.c.  However, this implementation is included in CFITSIO post
+#      3.004beta, so getwcstab.c is required here only for older releases
+#      (controlled by variable GETWCSTAB).  getwcstab.o itself is not inserted
+#      into the WCSLIB object library.
+#
+#      If available, CFITSIO is also optionally used for test programs
+#      tfitshdr, tbth1, tpih1 and tpih2 by setting preprocessor macro
+#      -DDO_CFITSIO.
+#
+# Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
+# http://www.atnf.csiro.au/people/Mark.Calabretta
+# $Id: makedefs.in,v 4.16 2012/11/07 04:42:45 cal103 Exp $
+#-----------------------------------------------------------------------------
+# Version.
+  LIBVER    := @LIBVER@
+  WCSLIBPKG := wcslib- at PACKAGE_VERSION@
+
+# System architecture.
+  ARCH     := @ARCH@
+
+# Flex and options.
+  FLEX     := @FLEX@
+  FLFLAGS  :=
+
+# C preprocessor and options.
+  CPP      := @CPP@
+  CPPFLAGS := @DEFS@
+  WCSTRIG  := WRAPPER
+
+# C compiler and options.
+  CC       := @CC@
+  CFLAGS   := @CFLAGS@
+
+# Fortran compiler and options.
+  FC       := @F77@
+  FFLAGS   := @FFLAGS@
+
+# Static object library.
+  WCSLIB   := libwcs-$(LIBVER).a
+  RANLIB   := @RANLIB@
+
+# Shared (dynamic) library (see note 3 above).
+  SHRLIB   := @SHRLIB@
+  SONAME   := @SONAME@
+  SHRFLAGS := @SHRFLAGS@
+  SHRLD    := @SHRLD@
+  SHRLN    := @SHRLN@
+
+# What subdirectories to build.
+  SUBDIRS  := @SUBDIRS@
+  TSTDIRS  := @TSTDIRS@
+
+# Top of the 'make install' hierarchy: pgsbox -> Fortran -> C.
+  INSTDIR  := @INSTDIR@
+
+# Installation utilities and locations.
+  LN_S     := @LN_S@
+  INSTALL  := @INSTALL@
+
+  # Needed for the definitions provided by autoconf.
+  prefix          := @prefix@
+  exec_prefix     := @exec_prefix@
+  datarootdir     := @datarootdir@
+  PACKAGE_TARNAME := @PACKAGE_TARNAME@
+  docdir          := @docdir@
+
+  LIBDIR   := $(DESTDIR)@libdir@
+  BINDIR   := $(DESTDIR)@bindir@
+  INCDIR   := $(DESTDIR)@includedir@/wcslib-$(LIBVER)
+  INCLINK  := $(DESTDIR)@includedir@/wcslib
+  DOCDIR   := $(DESTDIR)@docdir@
+  DOCLINK  := $(dir $(DESTDIR)@docdir@)wcslib
+  HTMLDIR  := $(DESTDIR)@htmldir@
+  PDFDIR   := $(DESTDIR)@pdfdir@
+  MANDIR   := $(DESTDIR)@mandir@
+
+# For putting timestamps in the build log.
+  TIMER    := date +"%a %Y/%m/%d %X %z, executing on $$HOST"
+
+
+# The remaining options are for building utilities and test programs.
+# -------------------------------------------------------------------
+# Linker options (use CC for linking).
+  LD       = $(CC)
+  LDFLAGS := @LDFLAGS@
+
+# PGPLOT (see note 4 above).
+  PGPLOTINC := @PGPLOTINC@
+  PGPLOTLIB := @PGPLOTLIB@
+
+# CFITSIO (see note 5 above).
+  CFITSIOINC := @CFITSIOINC@
+  CFITSIOLIB := @CFITSIOLIB@
+  GETWCSTAB  := @GETWCSTAB@
+
+# Libraries required by the above Fortran compiler.
+  FLIBS := @FLIBS@
+
+# Libraries required by WCSLIB itself.
+  LIBS := @LIBS@
+
+
+#-----------------------------------------------------------------------------
+# You shouldn't need to change anything below here.
+#-----------------------------------------------------------------------------
+
+SHELL := /bin/sh
+VPATH := ..
+
+# Common targets.
+.PHONY : all build printenv show
+
+all : show build
+
+# Print the environment as seen by makefile rules.
+printenv :
+	-@ printenv | sort
+
+# Print variable definitions.
+show :: wcsconfig.h
+	-@ echo ''
+	-@ uname -a
+	-@ echo ''
+	-@ $(MAKE) --version | head -1
+	-@ echo '  MAKEFLAGS   := $(MAKEFLAGS)'
+	-@ echo ''
+	-@ echo 'For building and installing $(WCSLIBPKG)...'
+	-@ echo '  ARCH        := $(ARCH)'
+	-@ echo '  FLEX        := $(FLEX)'
+	-@ echo '  FLFLAGS     := $(FLFLAGS)'
+	-@ echo '  CPP         := $(CPP)'
+	-@ echo '  CPPFLAGS    := $(CPPFLAGS)'
+	-@ echo '  WCSTRIG     := $(WCSTRIG)'
+	-@ echo '  CC          := $(CC)'
+	-@ echo '  CFLAGS      := $(CFLAGS)'
+	-@ echo '  FC          := $(FC)'
+	-@ echo '  FFLAGS      := $(FFLAGS)'
+	-@ echo '  WCSLIB      := $(WCSLIB)'
+	-@ echo '  RANLIB      := $(RANLIB)'
+	-@ echo '  SHRLIB      := $(SHRLIB)'
+	-@ echo '  SONAME      := $(SONAME)'
+	-@ echo '  SHRFLAGS    := $(SHRFLAGS)'
+	-@ echo '  SHRLD       := $(SHRLD)'
+	-@ echo '  SHRLN       := $(SHRLN)'
+	-@ echo '  LN_S        := $(LN_S)'
+	-@ echo '  INSTALL     := $(INSTALL)'
+	-@ echo '  LIBDIR      := $(LIBDIR)'
+	-@ echo '  BINDIR      := $(BINDIR)'
+	-@ echo '  INCDIR      := $(INCDIR)'
+	-@ echo '  INCLINK     := $(INCLINK)'
+	-@ echo '  DOCDIR      := $(DOCDIR)'
+	-@ echo '  DOCLINK     := $(DOCLINK)'
+	-@ echo '  HTMLDIR     := $(HTMLDIR)'
+	-@ echo '  PDFDIR      := $(PDFDIR)'
+	-@ echo '  MANDIR      := $(MANDIR)'
+	-@ echo '  TIMER       := $(TIMER)'
+	-@ echo ''
+	-@ echo 'Important wcsconfig.h defines...'
+	-@ echo "  `grep HAVE_SINCOS $<`"
+	-@ echo "  `grep WCSLIB_INT64 $<`"
+	-@ echo ''
+	-@ echo 'To build utilities and test programs...'
+	-@ echo '  LD          := $(LD)'
+	-@ echo '  LDFLAGS     := $(LDFLAGS)'
+	-@ echo '  PGPLOTINC   := $(PGPLOTINC)'
+	-@ echo '  PGPLOTLIB   := $(PGPLOTLIB)'
+	-@ echo '  CFITSIOINC  := $(CFITSIOINC)'
+	-@ echo '  CFITSIOLIB  := $(CFITSIOLIB)'
+	-@ echo '  GETWCSTAB   := $(GETWCSTAB)'
+	-@ echo '  FLIBS       := $(FLIBS)'
+	-@ echo '  LIBS        := $(LIBS)'
+	-@ echo ''
+
+# Code development overrides, for use in the code subdirectories.
+-include ../flavours
diff --git a/cextern/wcslib/wcsconfig.h.in b/cextern/wcslib/wcsconfig.h.in
new file mode 100644
index 0000000..b201b39
--- /dev/null
+++ b/cextern/wcslib/wcsconfig.h.in
@@ -0,0 +1,18 @@
+/*============================================================================
+*
+* wcsconfig.h is generated from wcsconfig.h.in by 'configure'.  It contains
+* C preprocessor macro definitions for compiling WCSLIB 4.16
+*
+* Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
+* http://www.atnf.csiro.au/people/Mark.Calabretta
+* $Id: wcsconfig.h.in,v 4.16 2012/11/07 04:42:45 cal103 Exp $
+*===========================================================================*/
+
+/* WCSLIB library version number. */
+#undef WCSLIB_VERSION
+
+/* Define to 1 if sincos() is available. */
+#undef HAVE_SINCOS
+
+/* 64-bit integer data type. */
+#undef WCSLIB_INT64
diff --git a/cextern/wcslib/wcsconfig_f77.h.in b/cextern/wcslib/wcsconfig_f77.h.in
new file mode 100644
index 0000000..6e1600d
--- /dev/null
+++ b/cextern/wcslib/wcsconfig_f77.h.in
@@ -0,0 +1,21 @@
+/*============================================================================
+*
+* wcsconfig_f77.h is generated from wcsconfig_f77.h.in by 'configure'.  It
+* contains C preprocessor definitions for building the WCSLIB 4.16 Fortran
+* wrappers.
+*
+* Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
+* http://www.atnf.csiro.au/people/Mark.Calabretta
+* $Id: wcsconfig_f77.h.in,v 4.16 2012/11/07 04:42:45 cal103 Exp $
+*===========================================================================*/
+
+/* Integer array type large enough to hold an address.  Set here to int[2] for
+ * 64-bit addresses, but could be defined as int* on 32-bit machines. */
+typedef int iptr[2];
+
+/* Macro for mangling Fortran subroutine names that do not contain
+ * underscores.  Typically a name like "WCSINI" (case-insensitive) will become
+ * something like "wcsini_" (case-sensitive).  The Fortran wrappers, which are
+ * written in C, are preprocessed into names that match the latter.  The macro
+ * takes two arguments which specify the name in lower and upper case. */
+#undef F77_FUNC
diff --git a/cextern/wcslib/wcsconfig_tests.h.in b/cextern/wcslib/wcsconfig_tests.h.in
new file mode 100644
index 0000000..9b390ae
--- /dev/null
+++ b/cextern/wcslib/wcsconfig_tests.h.in
@@ -0,0 +1,18 @@
+/*============================================================================
+*
+* wcsconfig_test.h is generated from wcsconfig_test.h.in by 'configure'.  It
+* contains C preprocessor definitions for compiling the WCSLIB 4.16 test/demo
+* programs.
+*
+* Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
+* http://www.atnf.csiro.au/people/Mark.Calabretta
+* $Id: wcsconfig_tests.h.in,v 4.16 2012/11/07 04:42:45 cal103 Exp $
+*===========================================================================*/
+
+#include <wcsconfig.h>
+
+/* Define to 1 if the CFITSIO library is available. */
+#undef HAVE_CFITSIO
+
+/* Define to the printf format modifier for size_t type. */
+#undef MODZ
diff --git a/cextern/wcslib/wcsconfig_utils.h.in b/cextern/wcslib/wcsconfig_utils.h.in
new file mode 100644
index 0000000..9a0d31a
--- /dev/null
+++ b/cextern/wcslib/wcsconfig_utils.h.in
@@ -0,0 +1,35 @@
+/*============================================================================
+*
+* wcsconfig_utils.h is generated from wcsconfig_utils.h.in by 'configure'.
+* It contains C preprocessor macro definitions for compiling the WCSLIB 4.16
+* utilities.
+*
+* Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
+* http://www.atnf.csiro.au/people/Mark.Calabretta
+* $Id: wcsconfig_utils.h.in,v 4.16 2012/11/07 04:42:45 cal103 Exp $
+*===========================================================================*/
+
+#include <wcsconfig.h>
+
+/* Definitions for Large File Support (LFS), i.e. files larger than 2GiB, for
+ * the fitshdr utility. */
+
+/* Define to 1 if fseeko() is available (for small or large files). */
+#undef HAVE_FSEEKO
+
+/* Define _LARGEFILE_SOURCE to get prototypes from stdio.h for the LFS
+ * functions fseeko() and ftello() which use an off_t argument in place of a
+ * long. */
+#undef _LARGEFILE_SOURCE
+
+/* There seems to be a bug in autoconf that causes _LARGEFILE_SOURCE not to be
+ * set in Linux.  This dreadful kludge gets around it for now. */
+#if (defined HAVE_FSEEKO && !defined _LARGEFILE_SOURCE)
+#define _LARGEFILE_SOURCE
+#endif
+
+/* Number of bits in a file offset (off_t) on systems where it can be set. */
+#undef _FILE_OFFSET_BITS
+
+/* Define for large files needed on AIX-type systems. */
+#undef _LARGE_FILES
diff --git a/astropy/wcs/src/wcslib/wcslib.pc.in b/cextern/wcslib/wcslib.pc.in
similarity index 100%
rename from astropy/wcs/src/wcslib/wcslib.pc.in
rename to cextern/wcslib/wcslib.pc.in
diff --git a/distribute_setup.py b/distribute_setup.py
index bbb6f3c..8f5b063 100644
--- a/distribute_setup.py
+++ b/distribute_setup.py
@@ -46,7 +46,7 @@ except ImportError:
             args = [quote(arg) for arg in args]
         return os.spawnl(os.P_WAIT, sys.executable, *args) == 0
 
-DEFAULT_VERSION = "0.6.19"
+DEFAULT_VERSION = "0.6.28"
 DEFAULT_URL = "http://pypi.python.org/packages/source/d/distribute/"
 SETUPTOOLS_FAKED_VERSION = "0.6c11"
 
@@ -63,7 +63,7 @@ Description: xxx
 """ % SETUPTOOLS_FAKED_VERSION
 
 
-def _install(tarball):
+def _install(tarball, install_args=()):
     # extracting the tarball
     tmpdir = tempfile.mkdtemp()
     log.warn('Extracting in %s', tmpdir)
@@ -81,7 +81,7 @@ def _install(tarball):
 
         # installing
         log.warn('Installing Distribute')
-        if not _python_cmd('setup.py', 'install'):
+        if not _python_cmd('setup.py', 'install', *install_args):
             log.warn('Something went wrong during the installation.')
             log.warn('See the error message above.')
     finally:
@@ -144,7 +144,7 @@ def use_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
         except ImportError:
             return _do_download(version, download_base, to_dir, download_delay)
         try:
-            pkg_resources.require("distribute>="+version)
+            pkg_resources.require("distribute>=" + version)
             return
         except pkg_resources.VersionConflict:
             e = sys.exc_info()[1]
@@ -167,6 +167,7 @@ def use_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
         if not no_fake:
             _create_fake_setuptools_pkg_info(to_dir)
 
+
 def download_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
                         to_dir=os.curdir, delay=15):
     """Download distribute from a specified location and return its filename
@@ -203,6 +204,7 @@ def download_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
                 dst.close()
     return os.path.realpath(saveto)
 
+
 def _no_sandbox(function):
     def __no_sandbox(*args, **kw):
         try:
@@ -227,6 +229,7 @@ def _no_sandbox(function):
 
     return __no_sandbox
 
+
 def _patch_file(path, content):
     """Will backup the file then patch it"""
     existing_content = open(path).read()
@@ -245,15 +248,18 @@ def _patch_file(path, content):
 
 _patch_file = _no_sandbox(_patch_file)
 
+
 def _same_content(path, content):
     return open(path).read() == content
 
+
 def _rename_path(path):
     new_name = path + '.OLD.%s' % time.time()
     log.warn('Renaming %s into %s', path, new_name)
     os.rename(path, new_name)
     return new_name
 
+
 def _remove_flat_installation(placeholder):
     if not os.path.isdir(placeholder):
         log.warn('Unkown installation at %s', placeholder)
@@ -289,11 +295,13 @@ def _remove_flat_installation(placeholder):
 
 _remove_flat_installation = _no_sandbox(_remove_flat_installation)
 
+
 def _after_install(dist):
     log.warn('After install bootstrap.')
     placeholder = dist.get_command_obj('install').install_purelib
     _create_fake_setuptools_pkg_info(placeholder)
 
+
 def _create_fake_setuptools_pkg_info(placeholder):
     if not placeholder or not os.path.exists(placeholder):
         log.warn('Could not find the install location')
@@ -306,6 +314,9 @@ def _create_fake_setuptools_pkg_info(placeholder):
         log.warn('%s already exists', pkg_info)
         return
 
+    if not os.access(pkg_info, os.W_OK):
+        log.warn("Don't have permissions to write %s, skipping", pkg_info)
+
     log.warn('Creating %s', pkg_info)
     f = open(pkg_info, 'w')
     try:
@@ -321,7 +332,10 @@ def _create_fake_setuptools_pkg_info(placeholder):
     finally:
         f.close()
 
-_create_fake_setuptools_pkg_info = _no_sandbox(_create_fake_setuptools_pkg_info)
+_create_fake_setuptools_pkg_info = _no_sandbox(
+    _create_fake_setuptools_pkg_info
+)
+
 
 def _patch_egg_dir(path):
     # let's check if it's already patched
@@ -343,6 +357,7 @@ def _patch_egg_dir(path):
 
 _patch_egg_dir = _no_sandbox(_patch_egg_dir)
 
+
 def _before_install():
     log.warn('Before install bootstrap.')
     _fake_setuptools()
@@ -351,7 +366,7 @@ def _before_install():
 def _under_prefix(location):
     if 'install' not in sys.argv:
         return True
-    args = sys.argv[sys.argv.index('install')+1:]
+    args = sys.argv[sys.argv.index('install') + 1:]
     for index, arg in enumerate(args):
         for option in ('--root', '--prefix'):
             if arg.startswith('%s=' % option):
@@ -359,7 +374,7 @@ def _under_prefix(location):
                 return location.startswith(top_dir)
             elif arg == option:
                 if len(args) > index:
-                    top_dir = args[index+1]
+                    top_dir = args[index + 1]
                     return location.startswith(top_dir)
         if arg == '--user' and USER_SITE is not None:
             return location.startswith(USER_SITE)
@@ -376,11 +391,14 @@ def _fake_setuptools():
         return
     ws = pkg_resources.working_set
     try:
-        setuptools_dist = ws.find(pkg_resources.Requirement.parse('setuptools',
-                                  replacement=False))
+        setuptools_dist = ws.find(
+            pkg_resources.Requirement.parse('setuptools', replacement=False)
+            )
     except TypeError:
         # old distribute API
-        setuptools_dist = ws.find(pkg_resources.Requirement.parse('setuptools'))
+        setuptools_dist = ws.find(
+            pkg_resources.Requirement.parse('setuptools')
+        )
 
     if setuptools_dist is None:
         log.warn('No setuptools distribution found')
@@ -422,7 +440,8 @@ def _relaunch():
     log.warn('Relaunching...')
     # we have to relaunch the process
     # pip marker to avoid a relaunch bug
-    if sys.argv[:3] == ['-c', 'install', '--single-version-externally-managed']:
+    _cmd = ['-c', 'install', '--single-version-externally-managed']
+    if sys.argv[:3] == _cmd:
         sys.argv[0] = 'setup.py'
     args = [sys.executable] + sys.argv
     sys.exit(subprocess.call(args))
@@ -448,7 +467,7 @@ def _extractall(self, path=".", members=None):
             # Extract directories with a safe mode.
             directories.append(tarinfo)
             tarinfo = copy.copy(tarinfo)
-            tarinfo.mode = 448 # decimal for oct 0700
+            tarinfo.mode = 448  # decimal for oct 0700
         self.extract(tarinfo, path)
 
     # Reverse sort directories.
@@ -475,10 +494,21 @@ def _extractall(self, path=".", members=None):
                 self._dbg(1, "tarfile: %s" % e)
 
 
+def _build_install_args(argv):
+    install_args = []
+    user_install = '--user' in argv
+    if user_install and sys.version_info < (2, 6):
+        log.warn("--user requires Python 2.6 or later")
+        raise SystemExit(1)
+    if user_install:
+        install_args.append('--user')
+    return install_args
+
+
 def main(argv, version=DEFAULT_VERSION):
     """Install or upgrade setuptools and EasyInstall"""
     tarball = download_setuptools()
-    _install(tarball)
+    _install(tarball, _build_install_args(argv))
 
 
 if __name__ == '__main__':
diff --git a/docs/_generated/astropy.config.configuration.ConfigurationItem.rst b/docs/_generated/astropy.config.configuration.ConfigurationItem.rst
deleted file mode 100644
index 1ec7918..0000000
--- a/docs/_generated/astropy.config.configuration.ConfigurationItem.rst
+++ /dev/null
@@ -1,50 +0,0 @@
-
-
-ConfigurationItem
-==============================================
-
-.. currentmodule:: astropy.config.configuration
-
-.. autoclass:: ConfigurationItem
-   :show-inheritance:
-
-   
-     None
-   
-
-   
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Summary
-
-   .. autosummary::
-   
-      ~ConfigurationItem.set
-      ~ConfigurationItem.reload
-      ~ConfigurationItem.save
-      ~ConfigurationItem.set_temp
-
-   
-   
-
-   
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Documentation
-
-   
-   .. automethod:: set
-   .. automethod:: reload
-   .. automethod:: save
-   .. automethod:: set_temp
-
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.config.configuration.ConfigurationMissingWarning.rst b/docs/_generated/astropy.config.configuration.ConfigurationMissingWarning.rst
deleted file mode 100644
index 8250d0e..0000000
--- a/docs/_generated/astropy.config.configuration.ConfigurationMissingWarning.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-ConfigurationMissingWarning
-========================================================
-
-.. currentmodule:: astropy.config.configuration
-
-.. autoexception:: ConfigurationMissingWarning
\ No newline at end of file
diff --git a/docs/_generated/astropy.config.configuration.InvalidConfigurationItemWarning.rst b/docs/_generated/astropy.config.configuration.InvalidConfigurationItemWarning.rst
deleted file mode 100644
index 4f0a1db..0000000
--- a/docs/_generated/astropy.config.configuration.InvalidConfigurationItemWarning.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-InvalidConfigurationItemWarning
-============================================================
-
-.. currentmodule:: astropy.config.configuration
-
-.. autoexception:: InvalidConfigurationItemWarning
\ No newline at end of file
diff --git a/docs/_generated/astropy.config.configuration.get_config.rst b/docs/_generated/astropy.config.configuration.get_config.rst
deleted file mode 100644
index 9733759..0000000
--- a/docs/_generated/astropy.config.configuration.get_config.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-get_config
-=======================================
-
-.. currentmodule:: astropy.config.configuration
-
-.. autofunction:: get_config
\ No newline at end of file
diff --git a/docs/_generated/astropy.config.configuration.reload_config.rst b/docs/_generated/astropy.config.configuration.reload_config.rst
deleted file mode 100644
index 328a797..0000000
--- a/docs/_generated/astropy.config.configuration.reload_config.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-reload_config
-==========================================
-
-.. currentmodule:: astropy.config.configuration
-
-.. autofunction:: reload_config
\ No newline at end of file
diff --git a/docs/_generated/astropy.config.configuration.save_config.rst b/docs/_generated/astropy.config.configuration.save_config.rst
deleted file mode 100644
index 34dd932..0000000
--- a/docs/_generated/astropy.config.configuration.save_config.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-save_config
-========================================
-
-.. currentmodule:: astropy.config.configuration
-
-.. autofunction:: save_config
\ No newline at end of file
diff --git a/docs/_generated/astropy.config.data.CacheMissingWarning.rst b/docs/_generated/astropy.config.data.CacheMissingWarning.rst
deleted file mode 100644
index 068b9e8..0000000
--- a/docs/_generated/astropy.config.data.CacheMissingWarning.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-CacheMissingWarning
-=======================================
-
-.. currentmodule:: astropy.config.data
-
-.. autoexception:: CacheMissingWarning
\ No newline at end of file
diff --git a/docs/_generated/astropy.config.data.clear_data_cache.rst b/docs/_generated/astropy.config.data.clear_data_cache.rst
deleted file mode 100644
index c6b8b3a..0000000
--- a/docs/_generated/astropy.config.data.clear_data_cache.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-clear_data_cache
-====================================
-
-.. currentmodule:: astropy.config.data
-
-.. autofunction:: clear_data_cache
\ No newline at end of file
diff --git a/docs/_generated/astropy.config.data.compute_hash.rst b/docs/_generated/astropy.config.data.compute_hash.rst
deleted file mode 100644
index cc4d431..0000000
--- a/docs/_generated/astropy.config.data.compute_hash.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-compute_hash
-================================
-
-.. currentmodule:: astropy.config.data
-
-.. autofunction:: compute_hash
\ No newline at end of file
diff --git a/docs/_generated/astropy.config.data.get_data_contents.rst b/docs/_generated/astropy.config.data.get_data_contents.rst
deleted file mode 100644
index d15ba22..0000000
--- a/docs/_generated/astropy.config.data.get_data_contents.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-get_data_contents
-=====================================
-
-.. currentmodule:: astropy.config.data
-
-.. autofunction:: get_data_contents
\ No newline at end of file
diff --git a/docs/_generated/astropy.config.data.get_data_filename.rst b/docs/_generated/astropy.config.data.get_data_filename.rst
deleted file mode 100644
index aaf7cf9..0000000
--- a/docs/_generated/astropy.config.data.get_data_filename.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-get_data_filename
-=====================================
-
-.. currentmodule:: astropy.config.data
-
-.. autofunction:: get_data_filename
\ No newline at end of file
diff --git a/docs/_generated/astropy.config.data.get_data_filenames.rst b/docs/_generated/astropy.config.data.get_data_filenames.rst
deleted file mode 100644
index 39ec0b4..0000000
--- a/docs/_generated/astropy.config.data.get_data_filenames.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-get_data_filenames
-======================================
-
-.. currentmodule:: astropy.config.data
-
-.. autofunction:: get_data_filenames
\ No newline at end of file
diff --git a/docs/_generated/astropy.config.data.get_data_fileobj.rst b/docs/_generated/astropy.config.data.get_data_fileobj.rst
deleted file mode 100644
index 2d1f82f..0000000
--- a/docs/_generated/astropy.config.data.get_data_fileobj.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-get_data_fileobj
-====================================
-
-.. currentmodule:: astropy.config.data
-
-.. autofunction:: get_data_fileobj
\ No newline at end of file
diff --git a/docs/_generated/astropy.config.data.get_data_fileobjs.rst b/docs/_generated/astropy.config.data.get_data_fileobjs.rst
deleted file mode 100644
index d319397..0000000
--- a/docs/_generated/astropy.config.data.get_data_fileobjs.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-get_data_fileobjs
-=====================================
-
-.. currentmodule:: astropy.config.data
-
-.. autofunction:: get_data_fileobjs
\ No newline at end of file
diff --git a/docs/_generated/astropy.config.paths.get_cache_dir.rst b/docs/_generated/astropy.config.paths.get_cache_dir.rst
deleted file mode 100644
index 32716fb..0000000
--- a/docs/_generated/astropy.config.paths.get_cache_dir.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-get_cache_dir
-==================================
-
-.. currentmodule:: astropy.config.paths
-
-.. autofunction:: get_cache_dir
\ No newline at end of file
diff --git a/docs/_generated/astropy.config.paths.get_config_dir.rst b/docs/_generated/astropy.config.paths.get_config_dir.rst
deleted file mode 100644
index 15b4507..0000000
--- a/docs/_generated/astropy.config.paths.get_config_dir.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-get_config_dir
-===================================
-
-.. currentmodule:: astropy.config.paths
-
-.. autofunction:: get_config_dir
\ No newline at end of file
diff --git a/docs/_generated/astropy.cosmology.core.FLRWCosmology.rst b/docs/_generated/astropy.cosmology.core.FLRWCosmology.rst
deleted file mode 100644
index c6cffcd..0000000
--- a/docs/_generated/astropy.cosmology.core.FLRWCosmology.rst
+++ /dev/null
@@ -1,68 +0,0 @@
-
-
-FLRWCosmology
-====================================
-
-.. currentmodule:: astropy.cosmology.core
-
-.. autoclass:: FLRWCosmology
-   :show-inheritance:
-
-   
-     None
-   
-
-   
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Summary
-
-   .. autosummary::
-   
-      ~FLRWCosmology.scale_factor
-      ~FLRWCosmology.angular_diameter_distance
-      ~FLRWCosmology.distmod
-      ~FLRWCosmology.lookback_time
-      ~FLRWCosmology.absorption_distance
-      ~FLRWCosmology.comoving_distance
-      ~FLRWCosmology.comoving_transverse_distance
-      ~FLRWCosmology.age
-      ~FLRWCosmology.luminosity_distance
-      ~FLRWCosmology.angular_diameter_distance_z1z2
-      ~FLRWCosmology.H
-      ~FLRWCosmology.comoving_volume
-      ~FLRWCosmology.critical_density
-
-   
-   
-
-   
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Documentation
-
-   
-   .. automethod:: scale_factor
-   .. automethod:: angular_diameter_distance
-   .. automethod:: distmod
-   .. automethod:: lookback_time
-   .. automethod:: absorption_distance
-   .. automethod:: comoving_distance
-   .. automethod:: comoving_transverse_distance
-   .. automethod:: age
-   .. automethod:: luminosity_distance
-   .. automethod:: angular_diameter_distance_z1z2
-   .. automethod:: H
-   .. automethod:: comoving_volume
-   .. automethod:: critical_density
-
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.cosmology.core.get_current.rst b/docs/_generated/astropy.cosmology.core.get_current.rst
deleted file mode 100644
index 6a9bf8f..0000000
--- a/docs/_generated/astropy.cosmology.core.get_current.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-get_current
-==================================
-
-.. currentmodule:: astropy.cosmology.core
-
-.. autofunction:: get_current
\ No newline at end of file
diff --git a/docs/_generated/astropy.cosmology.core.set_current.rst b/docs/_generated/astropy.cosmology.core.set_current.rst
deleted file mode 100644
index 009a5d9..0000000
--- a/docs/_generated/astropy.cosmology.core.set_current.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-set_current
-==================================
-
-.. currentmodule:: astropy.cosmology.core
-
-.. autofunction:: set_current
\ No newline at end of file
diff --git a/docs/_generated/astropy.cosmology.funcs.H.rst b/docs/_generated/astropy.cosmology.funcs.H.rst
deleted file mode 100644
index 730033e..0000000
--- a/docs/_generated/astropy.cosmology.funcs.H.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-H
-=========================
-
-.. currentmodule:: astropy.cosmology.funcs
-
-.. autofunction:: H
\ No newline at end of file
diff --git a/docs/_generated/astropy.cosmology.funcs.angular_diameter_distance.rst b/docs/_generated/astropy.cosmology.funcs.angular_diameter_distance.rst
deleted file mode 100644
index d6608a0..0000000
--- a/docs/_generated/astropy.cosmology.funcs.angular_diameter_distance.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-angular_diameter_distance
-=================================================
-
-.. currentmodule:: astropy.cosmology.funcs
-
-.. autofunction:: angular_diameter_distance
\ No newline at end of file
diff --git a/docs/_generated/astropy.cosmology.funcs.arcsec_per_kpc_comoving.rst b/docs/_generated/astropy.cosmology.funcs.arcsec_per_kpc_comoving.rst
deleted file mode 100644
index 46ba7e0..0000000
--- a/docs/_generated/astropy.cosmology.funcs.arcsec_per_kpc_comoving.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-arcsec_per_kpc_comoving
-===============================================
-
-.. currentmodule:: astropy.cosmology.funcs
-
-.. autofunction:: arcsec_per_kpc_comoving
\ No newline at end of file
diff --git a/docs/_generated/astropy.cosmology.funcs.arcsec_per_kpc_proper.rst b/docs/_generated/astropy.cosmology.funcs.arcsec_per_kpc_proper.rst
deleted file mode 100644
index f601f11..0000000
--- a/docs/_generated/astropy.cosmology.funcs.arcsec_per_kpc_proper.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-arcsec_per_kpc_proper
-=============================================
-
-.. currentmodule:: astropy.cosmology.funcs
-
-.. autofunction:: arcsec_per_kpc_proper
\ No newline at end of file
diff --git a/docs/_generated/astropy.cosmology.funcs.comoving_distance.rst b/docs/_generated/astropy.cosmology.funcs.comoving_distance.rst
deleted file mode 100644
index 0617f77..0000000
--- a/docs/_generated/astropy.cosmology.funcs.comoving_distance.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-comoving_distance
-=========================================
-
-.. currentmodule:: astropy.cosmology.funcs
-
-.. autofunction:: comoving_distance
\ No newline at end of file
diff --git a/docs/_generated/astropy.cosmology.funcs.critical_density.rst b/docs/_generated/astropy.cosmology.funcs.critical_density.rst
deleted file mode 100644
index 106a870..0000000
--- a/docs/_generated/astropy.cosmology.funcs.critical_density.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-critical_density
-========================================
-
-.. currentmodule:: astropy.cosmology.funcs
-
-.. autofunction:: critical_density
\ No newline at end of file
diff --git a/docs/_generated/astropy.cosmology.funcs.distmod.rst b/docs/_generated/astropy.cosmology.funcs.distmod.rst
deleted file mode 100644
index f076123..0000000
--- a/docs/_generated/astropy.cosmology.funcs.distmod.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-distmod
-===============================
-
-.. currentmodule:: astropy.cosmology.funcs
-
-.. autofunction:: distmod
\ No newline at end of file
diff --git a/docs/_generated/astropy.cosmology.funcs.kpc_comoving_per_arcmin.rst b/docs/_generated/astropy.cosmology.funcs.kpc_comoving_per_arcmin.rst
deleted file mode 100644
index 6b17c3c..0000000
--- a/docs/_generated/astropy.cosmology.funcs.kpc_comoving_per_arcmin.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-kpc_comoving_per_arcmin
-===============================================
-
-.. currentmodule:: astropy.cosmology.funcs
-
-.. autofunction:: kpc_comoving_per_arcmin
\ No newline at end of file
diff --git a/docs/_generated/astropy.cosmology.funcs.kpc_proper_per_arcmin.rst b/docs/_generated/astropy.cosmology.funcs.kpc_proper_per_arcmin.rst
deleted file mode 100644
index 0a45611..0000000
--- a/docs/_generated/astropy.cosmology.funcs.kpc_proper_per_arcmin.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-kpc_proper_per_arcmin
-=============================================
-
-.. currentmodule:: astropy.cosmology.funcs
-
-.. autofunction:: kpc_proper_per_arcmin
\ No newline at end of file
diff --git a/docs/_generated/astropy.cosmology.funcs.lookback_time.rst b/docs/_generated/astropy.cosmology.funcs.lookback_time.rst
deleted file mode 100644
index 056a40d..0000000
--- a/docs/_generated/astropy.cosmology.funcs.lookback_time.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-lookback_time
-=====================================
-
-.. currentmodule:: astropy.cosmology.funcs
-
-.. autofunction:: lookback_time
\ No newline at end of file
diff --git a/docs/_generated/astropy.cosmology.funcs.luminosity_distance.rst b/docs/_generated/astropy.cosmology.funcs.luminosity_distance.rst
deleted file mode 100644
index 322fdc4..0000000
--- a/docs/_generated/astropy.cosmology.funcs.luminosity_distance.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-luminosity_distance
-===========================================
-
-.. currentmodule:: astropy.cosmology.funcs
-
-.. autofunction:: luminosity_distance
\ No newline at end of file
diff --git a/docs/_generated/astropy.cosmology.funcs.scale_factor.rst b/docs/_generated/astropy.cosmology.funcs.scale_factor.rst
deleted file mode 100644
index e1d0636..0000000
--- a/docs/_generated/astropy.cosmology.funcs.scale_factor.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-scale_factor
-====================================
-
-.. currentmodule:: astropy.cosmology.funcs
-
-.. autofunction:: scale_factor
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.ascii.basic.Basic.rst b/docs/_generated/astropy.io.ascii.basic.Basic.rst
deleted file mode 100644
index d163979..0000000
--- a/docs/_generated/astropy.io.ascii.basic.Basic.rst
+++ /dev/null
@@ -1,31 +0,0 @@
-
-.. include:: ../io/ascii/references.txt
-
-
-Basic
-============================
-
-.. currentmodule:: astropy.io.ascii.basic
-
-.. autoclass:: Basic
-   :show-inheritance:
-
-   
-     None
-   
-
-   
-   
-   
-
-   
-   
-   
-
-   
-   
-   
-
-   
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.ascii.basic.CommentedHeader.rst b/docs/_generated/astropy.io.ascii.basic.CommentedHeader.rst
deleted file mode 100644
index 4ea04e8..0000000
--- a/docs/_generated/astropy.io.ascii.basic.CommentedHeader.rst
+++ /dev/null
@@ -1,31 +0,0 @@
-
-.. include:: ../io/ascii/references.txt
-
-
-CommentedHeader
-======================================
-
-.. currentmodule:: astropy.io.ascii.basic
-
-.. autoclass:: CommentedHeader
-   :show-inheritance:
-
-   
-     None
-   
-
-   
-   
-   
-
-   
-   
-   
-
-   
-   
-   
-
-   
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.ascii.basic.NoHeader.rst b/docs/_generated/astropy.io.ascii.basic.NoHeader.rst
deleted file mode 100644
index 8a312d2..0000000
--- a/docs/_generated/astropy.io.ascii.basic.NoHeader.rst
+++ /dev/null
@@ -1,31 +0,0 @@
-
-.. include:: ../io/ascii/references.txt
-
-
-NoHeader
-===============================
-
-.. currentmodule:: astropy.io.ascii.basic
-
-.. autoclass:: NoHeader
-   :show-inheritance:
-
-   
-     None
-   
-
-   
-   
-   
-
-   
-   
-   
-
-   
-   
-   
-
-   
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.ascii.basic.Rdb.rst b/docs/_generated/astropy.io.ascii.basic.Rdb.rst
deleted file mode 100644
index d81f847..0000000
--- a/docs/_generated/astropy.io.ascii.basic.Rdb.rst
+++ /dev/null
@@ -1,31 +0,0 @@
-
-.. include:: ../io/ascii/references.txt
-
-
-Rdb
-==========================
-
-.. currentmodule:: astropy.io.ascii.basic
-
-.. autoclass:: Rdb
-   :show-inheritance:
-
-   
-     None
-   
-
-   
-   
-   
-
-   
-   
-   
-
-   
-   
-   
-
-   
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.ascii.basic.Tab.rst b/docs/_generated/astropy.io.ascii.basic.Tab.rst
deleted file mode 100644
index 7ca0535..0000000
--- a/docs/_generated/astropy.io.ascii.basic.Tab.rst
+++ /dev/null
@@ -1,31 +0,0 @@
-
-.. include:: ../io/ascii/references.txt
-
-
-Tab
-==========================
-
-.. currentmodule:: astropy.io.ascii.basic
-
-.. autoclass:: Tab
-   :show-inheritance:
-
-   
-     None
-   
-
-   
-   
-   
-
-   
-   
-   
-
-   
-   
-   
-
-   
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.ascii.cds.Cds.rst b/docs/_generated/astropy.io.ascii.cds.Cds.rst
deleted file mode 100644
index c1ec6d6..0000000
--- a/docs/_generated/astropy.io.ascii.cds.Cds.rst
+++ /dev/null
@@ -1,46 +0,0 @@
-
-.. include:: ../io/ascii/references.txt
-
-
-Cds
-========================
-
-.. currentmodule:: astropy.io.ascii.cds
-
-.. autoclass:: Cds
-   :show-inheritance:
-
-   
-     None
-   
-
-   
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Summary
-
-   .. autosummary::
-   
-      ~Cds.write
-
-   
-   
-
-   
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Documentation
-
-   
-   .. automethod:: write
-
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.ascii.core.AllType.rst b/docs/_generated/astropy.io.ascii.core.AllType.rst
deleted file mode 100644
index d35f52b..0000000
--- a/docs/_generated/astropy.io.ascii.core.AllType.rst
+++ /dev/null
@@ -1,29 +0,0 @@
-
-.. include:: ../io/ascii/references.txt
-
-
-AllType
-=============================
-
-.. currentmodule:: astropy.io.ascii.core
-
-.. autoclass:: AllType
-   :show-inheritance:
-
-   
-
-   
-   
-   
-
-   
-   
-   
-
-   
-   
-   
-
-   
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.ascii.core.BaseData.rst b/docs/_generated/astropy.io.ascii.core.BaseData.rst
deleted file mode 100644
index 4eb3bfd..0000000
--- a/docs/_generated/astropy.io.ascii.core.BaseData.rst
+++ /dev/null
@@ -1,83 +0,0 @@
-
-.. include:: ../io/ascii/references.txt
-
-
-BaseData
-==============================
-
-.. currentmodule:: astropy.io.ascii.core
-
-.. autoclass:: BaseData
-   :show-inheritance:
-
-   
-     None
-   
-
-   
-   
-
-   .. rubric:: Attributes Summary
-
-   .. autosummary::
-   
-      ~BaseData.comment
-      ~BaseData.fill_values
-      ~BaseData.start_line
-      ~BaseData.write_spacer_lines
-      ~BaseData.end_line
-      ~BaseData.formats
-      ~BaseData.fill_exclude_names
-      ~BaseData.fill_include_names
-
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Summary
-
-   .. autosummary::
-   
-      ~BaseData.process_lines
-      ~BaseData.masks
-      ~BaseData.get_data_lines
-      ~BaseData.get_str_vals
-      ~BaseData.write
-
-   
-   
-
-   
-   
-
-   .. rubric:: Attributes Documentation
-
-   
-   .. autoattribute:: comment
-   .. autoattribute:: fill_values
-   .. autoattribute:: start_line
-   .. autoattribute:: write_spacer_lines
-   .. autoattribute:: end_line
-   .. autoattribute:: formats
-   .. autoattribute:: fill_exclude_names
-   .. autoattribute:: fill_include_names
-
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Documentation
-
-   
-   .. automethod:: process_lines
-   .. automethod:: masks
-   .. automethod:: get_data_lines
-   .. automethod:: get_str_vals
-   .. automethod:: write
-
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.ascii.core.BaseHeader.rst b/docs/_generated/astropy.io.ascii.core.BaseHeader.rst
deleted file mode 100644
index 02b9720..0000000
--- a/docs/_generated/astropy.io.ascii.core.BaseHeader.rst
+++ /dev/null
@@ -1,85 +0,0 @@
-
-.. include:: ../io/ascii/references.txt
-
-
-BaseHeader
-================================
-
-.. currentmodule:: astropy.io.ascii.core
-
-.. autoclass:: BaseHeader
-   :show-inheritance:
-
-   
-     None
-   
-
-   
-   
-
-   .. rubric:: Attributes Summary
-
-   .. autosummary::
-   
-      ~BaseHeader.comment
-      ~BaseHeader.exclude_names
-      ~BaseHeader.names
-      ~BaseHeader.colnames
-      ~BaseHeader.start_line
-      ~BaseHeader.include_names
-      ~BaseHeader.n_data_cols
-      ~BaseHeader.write_spacer_lines
-      ~BaseHeader.auto_format
-
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Summary
-
-   .. autosummary::
-   
-      ~BaseHeader.get_type_map_key
-      ~BaseHeader.process_lines
-      ~BaseHeader.get_cols
-      ~BaseHeader.get_col_type
-      ~BaseHeader.write
-
-   
-   
-
-   
-   
-
-   .. rubric:: Attributes Documentation
-
-   
-   .. autoattribute:: comment
-   .. autoattribute:: exclude_names
-   .. autoattribute:: names
-   .. autoattribute:: colnames
-   .. autoattribute:: start_line
-   .. autoattribute:: include_names
-   .. autoattribute:: n_data_cols
-   .. autoattribute:: write_spacer_lines
-   .. autoattribute:: auto_format
-
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Documentation
-
-   
-   .. automethod:: get_type_map_key
-   .. automethod:: process_lines
-   .. automethod:: get_cols
-   .. automethod:: get_col_type
-   .. automethod:: write
-
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.ascii.core.BaseInputter.rst b/docs/_generated/astropy.io.ascii.core.BaseInputter.rst
deleted file mode 100644
index 06836e4..0000000
--- a/docs/_generated/astropy.io.ascii.core.BaseInputter.rst
+++ /dev/null
@@ -1,46 +0,0 @@
-
-.. include:: ../io/ascii/references.txt
-
-
-BaseInputter
-==================================
-
-.. currentmodule:: astropy.io.ascii.core
-
-.. autoclass:: BaseInputter
-   :show-inheritance:
-
-   
-
-   
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Summary
-
-   .. autosummary::
-   
-      ~BaseInputter.process_lines
-      ~BaseInputter.get_lines
-
-   
-   
-
-   
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Documentation
-
-   
-   .. automethod:: process_lines
-   .. automethod:: get_lines
-
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.ascii.core.BaseOutputter.rst b/docs/_generated/astropy.io.ascii.core.BaseOutputter.rst
deleted file mode 100644
index e776753..0000000
--- a/docs/_generated/astropy.io.ascii.core.BaseOutputter.rst
+++ /dev/null
@@ -1,44 +0,0 @@
-
-.. include:: ../io/ascii/references.txt
-
-
-BaseOutputter
-===================================
-
-.. currentmodule:: astropy.io.ascii.core
-
-.. autoclass:: BaseOutputter
-   :show-inheritance:
-
-   
-
-   
-   
-
-   .. rubric:: Attributes Summary
-
-   .. autosummary::
-   
-      ~BaseOutputter.converters
-
-   
-   
-
-   
-   
-   
-
-   
-   
-
-   .. rubric:: Attributes Documentation
-
-   
-   .. autoattribute:: converters
-
-   
-   
-
-   
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.ascii.core.BaseReader.rst b/docs/_generated/astropy.io.ascii.core.BaseReader.rst
deleted file mode 100644
index 766c6e0..0000000
--- a/docs/_generated/astropy.io.ascii.core.BaseReader.rst
+++ /dev/null
@@ -1,65 +0,0 @@
-
-.. include:: ../io/ascii/references.txt
-
-
-BaseReader
-================================
-
-.. currentmodule:: astropy.io.ascii.core
-
-.. autoclass:: BaseReader
-   :show-inheritance:
-
-   
-     None
-   
-
-   
-   
-
-   .. rubric:: Attributes Summary
-
-   .. autosummary::
-   
-      ~BaseReader.comment_lines
-
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Summary
-
-   .. autosummary::
-   
-      ~BaseReader.write
-      ~BaseReader.inconsistent_handler
-      ~BaseReader.read
-
-   
-   
-
-   
-   
-
-   .. rubric:: Attributes Documentation
-
-   
-   .. autoattribute:: comment_lines
-
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Documentation
-
-   
-   .. automethod:: write
-   .. automethod:: inconsistent_handler
-   .. automethod:: read
-
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.ascii.core.BaseSplitter.rst b/docs/_generated/astropy.io.ascii.core.BaseSplitter.rst
deleted file mode 100644
index 7af6e20..0000000
--- a/docs/_generated/astropy.io.ascii.core.BaseSplitter.rst
+++ /dev/null
@@ -1,63 +0,0 @@
-
-.. include:: ../io/ascii/references.txt
-
-
-BaseSplitter
-==================================
-
-.. currentmodule:: astropy.io.ascii.core
-
-.. autoclass:: BaseSplitter
-   :show-inheritance:
-
-   
-
-   
-   
-
-   .. rubric:: Attributes Summary
-
-   .. autosummary::
-   
-      ~BaseSplitter.delimiter
-
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Summary
-
-   .. autosummary::
-   
-      ~BaseSplitter.process_line
-      ~BaseSplitter.process_val
-      ~BaseSplitter.join
-
-   
-   
-
-   
-   
-
-   .. rubric:: Attributes Documentation
-
-   
-   .. autoattribute:: delimiter
-
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Documentation
-
-   
-   .. automethod:: process_line
-   .. automethod:: process_val
-   .. automethod:: join
-
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.ascii.core.Column.rst b/docs/_generated/astropy.io.ascii.core.Column.rst
deleted file mode 100644
index d6f0331..0000000
--- a/docs/_generated/astropy.io.ascii.core.Column.rst
+++ /dev/null
@@ -1,31 +0,0 @@
-
-.. include:: ../io/ascii/references.txt
-
-
-Column
-============================
-
-.. currentmodule:: astropy.io.ascii.core
-
-.. autoclass:: Column
-   :show-inheritance:
-
-   
-     None
-   
-
-   
-   
-   
-
-   
-   
-   
-
-   
-   
-   
-
-   
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.ascii.core.ContinuationLinesInputter.rst b/docs/_generated/astropy.io.ascii.core.ContinuationLinesInputter.rst
deleted file mode 100644
index ca48893..0000000
--- a/docs/_generated/astropy.io.ascii.core.ContinuationLinesInputter.rst
+++ /dev/null
@@ -1,59 +0,0 @@
-
-.. include:: ../io/ascii/references.txt
-
-
-ContinuationLinesInputter
-===============================================
-
-.. currentmodule:: astropy.io.ascii.core
-
-.. autoclass:: ContinuationLinesInputter
-   :show-inheritance:
-
-   
-
-   
-   
-
-   .. rubric:: Attributes Summary
-
-   .. autosummary::
-   
-      ~ContinuationLinesInputter.continuation_char
-
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Summary
-
-   .. autosummary::
-   
-      ~ContinuationLinesInputter.process_lines
-
-   
-   
-
-   
-   
-
-   .. rubric:: Attributes Documentation
-
-   
-   .. autoattribute:: continuation_char
-
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Documentation
-
-   
-   .. automethod:: process_lines
-
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.ascii.core.DefaultSplitter.rst b/docs/_generated/astropy.io.ascii.core.DefaultSplitter.rst
deleted file mode 100644
index 7180b3d..0000000
--- a/docs/_generated/astropy.io.ascii.core.DefaultSplitter.rst
+++ /dev/null
@@ -1,73 +0,0 @@
-
-.. include:: ../io/ascii/references.txt
-
-
-DefaultSplitter
-=====================================
-
-.. currentmodule:: astropy.io.ascii.core
-
-.. autoclass:: DefaultSplitter
-   :show-inheritance:
-
-   
-     None
-   
-
-   
-   
-
-   .. rubric:: Attributes Summary
-
-   .. autosummary::
-   
-      ~DefaultSplitter.escapechar
-      ~DefaultSplitter.skipinitialspace
-      ~DefaultSplitter.quoting
-      ~DefaultSplitter.delimiter
-      ~DefaultSplitter.doublequote
-      ~DefaultSplitter.quotechar
-
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Summary
-
-   .. autosummary::
-   
-      ~DefaultSplitter.join
-      ~DefaultSplitter.process_line
-
-   
-   
-
-   
-   
-
-   .. rubric:: Attributes Documentation
-
-   
-   .. autoattribute:: escapechar
-   .. autoattribute:: skipinitialspace
-   .. autoattribute:: quoting
-   .. autoattribute:: delimiter
-   .. autoattribute:: doublequote
-   .. autoattribute:: quotechar
-
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Documentation
-
-   
-   .. automethod:: join
-   .. automethod:: process_line
-
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.ascii.core.FloatType.rst b/docs/_generated/astropy.io.ascii.core.FloatType.rst
deleted file mode 100644
index 5ccf106..0000000
--- a/docs/_generated/astropy.io.ascii.core.FloatType.rst
+++ /dev/null
@@ -1,29 +0,0 @@
-
-.. include:: ../io/ascii/references.txt
-
-
-FloatType
-===============================
-
-.. currentmodule:: astropy.io.ascii.core
-
-.. autoclass:: FloatType
-   :show-inheritance:
-
-   
-
-   
-   
-   
-
-   
-   
-   
-
-   
-   
-   
-
-   
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.ascii.core.InconsistentTableError.rst b/docs/_generated/astropy.io.ascii.core.InconsistentTableError.rst
deleted file mode 100644
index a43d0c0..0000000
--- a/docs/_generated/astropy.io.ascii.core.InconsistentTableError.rst
+++ /dev/null
@@ -1,10 +0,0 @@
-
-.. include:: ../io/ascii/references.txt
-
-
-InconsistentTableError
-============================================
-
-.. currentmodule:: astropy.io.ascii.core
-
-.. autoexception:: InconsistentTableError
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.ascii.core.IntType.rst b/docs/_generated/astropy.io.ascii.core.IntType.rst
deleted file mode 100644
index 60ae588..0000000
--- a/docs/_generated/astropy.io.ascii.core.IntType.rst
+++ /dev/null
@@ -1,29 +0,0 @@
-
-.. include:: ../io/ascii/references.txt
-
-
-IntType
-=============================
-
-.. currentmodule:: astropy.io.ascii.core
-
-.. autoclass:: IntType
-   :show-inheritance:
-
-   
-
-   
-   
-   
-
-   
-   
-   
-
-   
-   
-   
-
-   
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.ascii.core.Keyword.rst b/docs/_generated/astropy.io.ascii.core.Keyword.rst
deleted file mode 100644
index 3498ad8..0000000
--- a/docs/_generated/astropy.io.ascii.core.Keyword.rst
+++ /dev/null
@@ -1,31 +0,0 @@
-
-.. include:: ../io/ascii/references.txt
-
-
-Keyword
-=============================
-
-.. currentmodule:: astropy.io.ascii.core
-
-.. autoclass:: Keyword
-   :show-inheritance:
-
-   
-     None
-   
-
-   
-   
-   
-
-   
-   
-   
-
-   
-   
-   
-
-   
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.ascii.core.NoType.rst b/docs/_generated/astropy.io.ascii.core.NoType.rst
deleted file mode 100644
index 2a5b653..0000000
--- a/docs/_generated/astropy.io.ascii.core.NoType.rst
+++ /dev/null
@@ -1,29 +0,0 @@
-
-.. include:: ../io/ascii/references.txt
-
-
-NoType
-============================
-
-.. currentmodule:: astropy.io.ascii.core
-
-.. autoclass:: NoType
-   :show-inheritance:
-
-   
-
-   
-   
-   
-
-   
-   
-   
-
-   
-   
-   
-
-   
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.ascii.core.NumType.rst b/docs/_generated/astropy.io.ascii.core.NumType.rst
deleted file mode 100644
index 6c49194..0000000
--- a/docs/_generated/astropy.io.ascii.core.NumType.rst
+++ /dev/null
@@ -1,29 +0,0 @@
-
-.. include:: ../io/ascii/references.txt
-
-
-NumType
-=============================
-
-.. currentmodule:: astropy.io.ascii.core
-
-.. autoclass:: NumType
-   :show-inheritance:
-
-   
-
-   
-   
-   
-
-   
-   
-   
-
-   
-   
-   
-
-   
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.ascii.core.NumpyOutputter.rst b/docs/_generated/astropy.io.ascii.core.NumpyOutputter.rst
deleted file mode 100644
index b5524b6..0000000
--- a/docs/_generated/astropy.io.ascii.core.NumpyOutputter.rst
+++ /dev/null
@@ -1,48 +0,0 @@
-
-.. include:: ../io/ascii/references.txt
-
-
-NumpyOutputter
-====================================
-
-.. currentmodule:: astropy.io.ascii.core
-
-.. autoclass:: NumpyOutputter
-   :show-inheritance:
-
-   
-
-   
-   
-
-   .. rubric:: Attributes Summary
-
-   .. autosummary::
-   
-      ~NumpyOutputter.auto_masked_array
-      ~NumpyOutputter.default_masked_array
-      ~NumpyOutputter.default_converters
-
-   
-   
-
-   
-   
-   
-
-   
-   
-
-   .. rubric:: Attributes Documentation
-
-   
-   .. autoattribute:: auto_masked_array
-   .. autoattribute:: default_masked_array
-   .. autoattribute:: default_converters
-
-   
-   
-
-   
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.ascii.core.StrType.rst b/docs/_generated/astropy.io.ascii.core.StrType.rst
deleted file mode 100644
index 03cf410..0000000
--- a/docs/_generated/astropy.io.ascii.core.StrType.rst
+++ /dev/null
@@ -1,29 +0,0 @@
-
-.. include:: ../io/ascii/references.txt
-
-
-StrType
-=============================
-
-.. currentmodule:: astropy.io.ascii.core
-
-.. autoclass:: StrType
-   :show-inheritance:
-
-   
-
-   
-   
-   
-
-   
-   
-   
-
-   
-   
-   
-
-   
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.ascii.core.TableOutputter.rst b/docs/_generated/astropy.io.ascii.core.TableOutputter.rst
deleted file mode 100644
index bebbc45..0000000
--- a/docs/_generated/astropy.io.ascii.core.TableOutputter.rst
+++ /dev/null
@@ -1,44 +0,0 @@
-
-.. include:: ../io/ascii/references.txt
-
-
-TableOutputter
-====================================
-
-.. currentmodule:: astropy.io.ascii.core
-
-.. autoclass:: TableOutputter
-   :show-inheritance:
-
-   
-
-   
-   
-
-   .. rubric:: Attributes Summary
-
-   .. autosummary::
-   
-      ~TableOutputter.default_converters
-
-   
-   
-
-   
-   
-   
-
-   
-   
-
-   .. rubric:: Attributes Documentation
-
-   
-   .. autoattribute:: default_converters
-
-   
-   
-
-   
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.ascii.core.WhitespaceSplitter.rst b/docs/_generated/astropy.io.ascii.core.WhitespaceSplitter.rst
deleted file mode 100644
index a237543..0000000
--- a/docs/_generated/astropy.io.ascii.core.WhitespaceSplitter.rst
+++ /dev/null
@@ -1,44 +0,0 @@
-
-.. include:: ../io/ascii/references.txt
-
-
-WhitespaceSplitter
-========================================
-
-.. currentmodule:: astropy.io.ascii.core
-
-.. autoclass:: WhitespaceSplitter
-   :show-inheritance:
-
-   
-
-   
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Summary
-
-   .. autosummary::
-   
-      ~WhitespaceSplitter.process_line
-
-   
-   
-
-   
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Documentation
-
-   
-   .. automethod:: process_line
-
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.ascii.core.convert_numpy.rst b/docs/_generated/astropy.io.ascii.core.convert_numpy.rst
deleted file mode 100644
index e97ec9e..0000000
--- a/docs/_generated/astropy.io.ascii.core.convert_numpy.rst
+++ /dev/null
@@ -1,10 +0,0 @@
-
-.. include:: ../io/ascii/references.txt
-
-
-convert_numpy
-===================================
-
-.. currentmodule:: astropy.io.ascii.core
-
-.. autofunction:: convert_numpy
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.ascii.daophot.Daophot.rst b/docs/_generated/astropy.io.ascii.daophot.Daophot.rst
deleted file mode 100644
index d9a5dbd..0000000
--- a/docs/_generated/astropy.io.ascii.daophot.Daophot.rst
+++ /dev/null
@@ -1,48 +0,0 @@
-
-.. include:: ../io/ascii/references.txt
-
-
-Daophot
-================================
-
-.. currentmodule:: astropy.io.ascii.daophot
-
-.. autoclass:: Daophot
-   :show-inheritance:
-
-   
-     None
-   
-
-   
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Summary
-
-   .. autosummary::
-   
-      ~Daophot.read
-      ~Daophot.write
-
-   
-   
-
-   
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Documentation
-
-   
-   .. automethod:: read
-   .. automethod:: write
-
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.ascii.fixedwidth.FixedWidth.rst b/docs/_generated/astropy.io.ascii.fixedwidth.FixedWidth.rst
deleted file mode 100644
index b505b6d..0000000
--- a/docs/_generated/astropy.io.ascii.fixedwidth.FixedWidth.rst
+++ /dev/null
@@ -1,31 +0,0 @@
-
-.. include:: ../io/ascii/references.txt
-
-
-FixedWidth
-======================================
-
-.. currentmodule:: astropy.io.ascii.fixedwidth
-
-.. autoclass:: FixedWidth
-   :show-inheritance:
-
-   
-     None
-   
-
-   
-   
-   
-
-   
-   
-   
-
-   
-   
-   
-
-   
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.ascii.fixedwidth.FixedWidthData.rst b/docs/_generated/astropy.io.ascii.fixedwidth.FixedWidthData.rst
deleted file mode 100644
index 91c768e..0000000
--- a/docs/_generated/astropy.io.ascii.fixedwidth.FixedWidthData.rst
+++ /dev/null
@@ -1,44 +0,0 @@
-
-.. include:: ../io/ascii/references.txt
-
-
-FixedWidthData
-==========================================
-
-.. currentmodule:: astropy.io.ascii.fixedwidth
-
-.. autoclass:: FixedWidthData
-   :show-inheritance:
-
-   
-
-   
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Summary
-
-   .. autosummary::
-   
-      ~FixedWidthData.write
-
-   
-   
-
-   
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Documentation
-
-   
-   .. automethod:: write
-
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.ascii.fixedwidth.FixedWidthHeader.rst b/docs/_generated/astropy.io.ascii.fixedwidth.FixedWidthHeader.rst
deleted file mode 100644
index 4c13322..0000000
--- a/docs/_generated/astropy.io.ascii.fixedwidth.FixedWidthHeader.rst
+++ /dev/null
@@ -1,65 +0,0 @@
-
-.. include:: ../io/ascii/references.txt
-
-
-FixedWidthHeader
-============================================
-
-.. currentmodule:: astropy.io.ascii.fixedwidth
-
-.. autoclass:: FixedWidthHeader
-   :show-inheritance:
-
-   
-
-   
-   
-
-   .. rubric:: Attributes Summary
-
-   .. autosummary::
-   
-      ~FixedWidthHeader.position_line
-
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Summary
-
-   .. autosummary::
-   
-      ~FixedWidthHeader.write
-      ~FixedWidthHeader.get_cols
-      ~FixedWidthHeader.get_line
-      ~FixedWidthHeader.get_fixedwidth_params
-
-   
-   
-
-   
-   
-
-   .. rubric:: Attributes Documentation
-
-   
-   .. autoattribute:: position_line
-
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Documentation
-
-   
-   .. automethod:: write
-   .. automethod:: get_cols
-   .. automethod:: get_line
-   .. automethod:: get_fixedwidth_params
-
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.ascii.fixedwidth.FixedWidthNoHeader.rst b/docs/_generated/astropy.io.ascii.fixedwidth.FixedWidthNoHeader.rst
deleted file mode 100644
index 2feaaab..0000000
--- a/docs/_generated/astropy.io.ascii.fixedwidth.FixedWidthNoHeader.rst
+++ /dev/null
@@ -1,31 +0,0 @@
-
-.. include:: ../io/ascii/references.txt
-
-
-FixedWidthNoHeader
-==============================================
-
-.. currentmodule:: astropy.io.ascii.fixedwidth
-
-.. autoclass:: FixedWidthNoHeader
-   :show-inheritance:
-
-   
-     None
-   
-
-   
-   
-   
-
-   
-   
-   
-
-   
-   
-   
-
-   
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.ascii.fixedwidth.FixedWidthSplitter.rst b/docs/_generated/astropy.io.ascii.fixedwidth.FixedWidthSplitter.rst
deleted file mode 100644
index 026cac7..0000000
--- a/docs/_generated/astropy.io.ascii.fixedwidth.FixedWidthSplitter.rst
+++ /dev/null
@@ -1,61 +0,0 @@
-
-.. include:: ../io/ascii/references.txt
-
-
-FixedWidthSplitter
-==============================================
-
-.. currentmodule:: astropy.io.ascii.fixedwidth
-
-.. autoclass:: FixedWidthSplitter
-   :show-inheritance:
-
-   
-
-   
-   
-
-   .. rubric:: Attributes Summary
-
-   .. autosummary::
-   
-      ~FixedWidthSplitter.delimiter_pad
-      ~FixedWidthSplitter.bookend
-
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Summary
-
-   .. autosummary::
-   
-      ~FixedWidthSplitter.join
-
-   
-   
-
-   
-   
-
-   .. rubric:: Attributes Documentation
-
-   
-   .. autoattribute:: delimiter_pad
-   .. autoattribute:: bookend
-
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Documentation
-
-   
-   .. automethod:: join
-
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.ascii.fixedwidth.FixedWidthTwoLine.rst b/docs/_generated/astropy.io.ascii.fixedwidth.FixedWidthTwoLine.rst
deleted file mode 100644
index 5a3c3a6..0000000
--- a/docs/_generated/astropy.io.ascii.fixedwidth.FixedWidthTwoLine.rst
+++ /dev/null
@@ -1,31 +0,0 @@
-
-.. include:: ../io/ascii/references.txt
-
-
-FixedWidthTwoLine
-=============================================
-
-.. currentmodule:: astropy.io.ascii.fixedwidth
-
-.. autoclass:: FixedWidthTwoLine
-   :show-inheritance:
-
-   
-     None
-   
-
-   
-   
-   
-
-   
-   
-   
-
-   
-   
-   
-
-   
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.ascii.ipac.Ipac.rst b/docs/_generated/astropy.io.ascii.ipac.Ipac.rst
deleted file mode 100644
index 79f9543..0000000
--- a/docs/_generated/astropy.io.ascii.ipac.Ipac.rst
+++ /dev/null
@@ -1,46 +0,0 @@
-
-.. include:: ../io/ascii/references.txt
-
-
-Ipac
-==========================
-
-.. currentmodule:: astropy.io.ascii.ipac
-
-.. autoclass:: Ipac
-   :show-inheritance:
-
-   
-     None
-   
-
-   
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Summary
-
-   .. autosummary::
-   
-      ~Ipac.write
-
-   
-   
-
-   
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Documentation
-
-   
-   .. automethod:: write
-
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.ascii.latex.AASTex.rst b/docs/_generated/astropy.io.ascii.latex.AASTex.rst
deleted file mode 100644
index 55ee39a..0000000
--- a/docs/_generated/astropy.io.ascii.latex.AASTex.rst
+++ /dev/null
@@ -1,31 +0,0 @@
-
-.. include:: ../io/ascii/references.txt
-
-
-AASTex
-=============================
-
-.. currentmodule:: astropy.io.ascii.latex
-
-.. autoclass:: AASTex
-   :show-inheritance:
-
-   
-     None
-   
-
-   
-   
-   
-
-   
-   
-   
-
-   
-   
-   
-
-   
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.ascii.latex.Latex.rst b/docs/_generated/astropy.io.ascii.latex.Latex.rst
deleted file mode 100644
index f780d8d..0000000
--- a/docs/_generated/astropy.io.ascii.latex.Latex.rst
+++ /dev/null
@@ -1,46 +0,0 @@
-
-.. include:: ../io/ascii/references.txt
-
-
-Latex
-============================
-
-.. currentmodule:: astropy.io.ascii.latex
-
-.. autoclass:: Latex
-   :show-inheritance:
-
-   
-     None
-   
-
-   
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Summary
-
-   .. autosummary::
-   
-      ~Latex.write
-
-   
-   
-
-   
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Documentation
-
-   
-   .. automethod:: write
-
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.ascii.memory.Memory.rst b/docs/_generated/astropy.io.ascii.memory.Memory.rst
deleted file mode 100644
index fee3d48..0000000
--- a/docs/_generated/astropy.io.ascii.memory.Memory.rst
+++ /dev/null
@@ -1,48 +0,0 @@
-
-.. include:: ../io/ascii/references.txt
-
-
-Memory
-==============================
-
-.. currentmodule:: astropy.io.ascii.memory
-
-.. autoclass:: Memory
-   :show-inheritance:
-
-   
-     None
-   
-
-   
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Summary
-
-   .. autosummary::
-   
-      ~Memory.read
-      ~Memory.write
-
-   
-   
-
-   
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Documentation
-
-   
-   .. automethod:: read
-   .. automethod:: write
-
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.ascii.ui.get_reader.rst b/docs/_generated/astropy.io.ascii.ui.get_reader.rst
deleted file mode 100644
index 46d5841..0000000
--- a/docs/_generated/astropy.io.ascii.ui.get_reader.rst
+++ /dev/null
@@ -1,10 +0,0 @@
-
-.. include:: ../io/ascii/references.txt
-
-
-get_reader
-==============================
-
-.. currentmodule:: astropy.io.ascii.ui
-
-.. autofunction:: get_reader
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.ascii.ui.get_writer.rst b/docs/_generated/astropy.io.ascii.ui.get_writer.rst
deleted file mode 100644
index 87a3057..0000000
--- a/docs/_generated/astropy.io.ascii.ui.get_writer.rst
+++ /dev/null
@@ -1,10 +0,0 @@
-
-.. include:: ../io/ascii/references.txt
-
-
-get_writer
-==============================
-
-.. currentmodule:: astropy.io.ascii.ui
-
-.. autofunction:: get_writer
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.ascii.ui.read.rst b/docs/_generated/astropy.io.ascii.ui.read.rst
deleted file mode 100644
index 17bcacc..0000000
--- a/docs/_generated/astropy.io.ascii.ui.read.rst
+++ /dev/null
@@ -1,10 +0,0 @@
-
-.. include:: ../io/ascii/references.txt
-
-
-read
-========================
-
-.. currentmodule:: astropy.io.ascii.ui
-
-.. autofunction:: read
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.ascii.ui.set_guess.rst b/docs/_generated/astropy.io.ascii.ui.set_guess.rst
deleted file mode 100644
index cf85ea1..0000000
--- a/docs/_generated/astropy.io.ascii.ui.set_guess.rst
+++ /dev/null
@@ -1,10 +0,0 @@
-
-.. include:: ../io/ascii/references.txt
-
-
-set_guess
-=============================
-
-.. currentmodule:: astropy.io.ascii.ui
-
-.. autofunction:: set_guess
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.ascii.ui.write.rst b/docs/_generated/astropy.io.ascii.ui.write.rst
deleted file mode 100644
index 9c0cfd7..0000000
--- a/docs/_generated/astropy.io.ascii.ui.write.rst
+++ /dev/null
@@ -1,10 +0,0 @@
-
-.. include:: ../io/ascii/references.txt
-
-
-write
-=========================
-
-.. currentmodule:: astropy.io.ascii.ui
-
-.. autofunction:: write
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.vo.converters.Converter.rst b/docs/_generated/astropy.io.vo.converters.Converter.rst
deleted file mode 100644
index fce32fe..0000000
--- a/docs/_generated/astropy.io.vo.converters.Converter.rst
+++ /dev/null
@@ -1,54 +0,0 @@
-
-.. include:: ../io/vo/references.txt
-
-
-Converter
-==================================
-
-.. currentmodule:: astropy.io.vo.converters
-
-.. autoclass:: Converter
-   :show-inheritance:
-
-   
-     None
-   
-
-   
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Summary
-
-   .. autosummary::
-   
-      ~Converter.binparse
-      ~Converter.parse
-      ~Converter.output
-      ~Converter.parse_scalar
-      ~Converter.binoutput
-
-   
-   
-
-   
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Documentation
-
-   
-   .. automethod:: binparse
-   .. automethod:: parse
-   .. automethod:: output
-   .. automethod:: parse_scalar
-   .. automethod:: binoutput
-
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.vo.converters.get_converter.rst b/docs/_generated/astropy.io.vo.converters.get_converter.rst
deleted file mode 100644
index e969e69..0000000
--- a/docs/_generated/astropy.io.vo.converters.get_converter.rst
+++ /dev/null
@@ -1,10 +0,0 @@
-
-.. include:: ../io/vo/references.txt
-
-
-get_converter
-======================================
-
-.. currentmodule:: astropy.io.vo.converters
-
-.. autofunction:: get_converter
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.vo.table.parse.rst b/docs/_generated/astropy.io.vo.table.parse.rst
deleted file mode 100644
index accd4e9..0000000
--- a/docs/_generated/astropy.io.vo.table.parse.rst
+++ /dev/null
@@ -1,10 +0,0 @@
-
-.. include:: ../io/vo/references.txt
-
-
-parse
-=========================
-
-.. currentmodule:: astropy.io.vo.table
-
-.. autofunction:: parse
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.vo.table.parse_single_table.rst b/docs/_generated/astropy.io.vo.table.parse_single_table.rst
deleted file mode 100644
index 5bfc71e..0000000
--- a/docs/_generated/astropy.io.vo.table.parse_single_table.rst
+++ /dev/null
@@ -1,10 +0,0 @@
-
-.. include:: ../io/vo/references.txt
-
-
-parse_single_table
-======================================
-
-.. currentmodule:: astropy.io.vo.table
-
-.. autofunction:: parse_single_table
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.vo.table.validate.rst b/docs/_generated/astropy.io.vo.table.validate.rst
deleted file mode 100644
index cb039ac..0000000
--- a/docs/_generated/astropy.io.vo.table.validate.rst
+++ /dev/null
@@ -1,10 +0,0 @@
-
-.. include:: ../io/vo/references.txt
-
-
-validate
-============================
-
-.. currentmodule:: astropy.io.vo.table
-
-.. autofunction:: validate
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.vo.tree.CooSys.rst b/docs/_generated/astropy.io.vo.tree.CooSys.rst
deleted file mode 100644
index cd626e4..0000000
--- a/docs/_generated/astropy.io.vo.tree.CooSys.rst
+++ /dev/null
@@ -1,52 +0,0 @@
-
-.. include:: ../io/vo/references.txt
-
-
-CooSys
-=========================
-
-.. currentmodule:: astropy.io.vo.tree
-
-.. autoclass:: CooSys
-   :show-inheritance:
-
-   
-     None
-   
-
-   
-   
-
-   .. rubric:: Attributes Summary
-
-   .. autosummary::
-   
-      ~CooSys.equinox
-      ~CooSys.system
-      ~CooSys.ID
-      ~CooSys.epoch
-
-   
-   
-
-   
-   
-   
-
-   
-   
-
-   .. rubric:: Attributes Documentation
-
-   
-   .. autoattribute:: equinox
-   .. autoattribute:: system
-   .. autoattribute:: ID
-   .. autoattribute:: epoch
-
-   
-   
-
-   
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.vo.tree.Field.rst b/docs/_generated/astropy.io.vo.tree.Field.rst
deleted file mode 100644
index 69ff35e..0000000
--- a/docs/_generated/astropy.io.vo.tree.Field.rst
+++ /dev/null
@@ -1,81 +0,0 @@
-
-.. include:: ../io/vo/references.txt
-
-
-Field
-========================
-
-.. currentmodule:: astropy.io.vo.tree
-
-.. autoclass:: Field
-   :show-inheritance:
-
-   
-     None
-   
-
-   
-   
-
-   .. rubric:: Attributes Summary
-
-   .. autosummary::
-   
-      ~Field.links
-      ~Field.precision
-      ~Field.arraysize
-      ~Field.unit
-      ~Field.datatype
-      ~Field.type
-      ~Field.width
-      ~Field.values
-      ~Field.ref
-
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Summary
-
-   .. autosummary::
-   
-      ~Field.parse
-      ~Field.to_xml
-      ~Field.uniqify_names
-
-   
-   
-
-   
-   
-
-   .. rubric:: Attributes Documentation
-
-   
-   .. autoattribute:: links
-   .. autoattribute:: precision
-   .. autoattribute:: arraysize
-   .. autoattribute:: unit
-   .. autoattribute:: datatype
-   .. autoattribute:: type
-   .. autoattribute:: width
-   .. autoattribute:: values
-   .. autoattribute:: ref
-
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Documentation
-
-   
-   .. automethod:: parse
-   .. automethod:: to_xml
-   .. automethod:: uniqify_names
-
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.vo.tree.FieldRef.rst b/docs/_generated/astropy.io.vo.tree.FieldRef.rst
deleted file mode 100644
index e62a130..0000000
--- a/docs/_generated/astropy.io.vo.tree.FieldRef.rst
+++ /dev/null
@@ -1,61 +0,0 @@
-
-.. include:: ../io/vo/references.txt
-
-
-FieldRef
-===========================
-
-.. currentmodule:: astropy.io.vo.tree
-
-.. autoclass:: FieldRef
-   :show-inheritance:
-
-   
-     None
-   
-
-   
-   
-
-   .. rubric:: Attributes Summary
-
-   .. autosummary::
-   
-      ~FieldRef.ref
-
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Summary
-
-   .. autosummary::
-   
-      ~FieldRef.get_ref
-
-   
-   
-
-   
-   
-
-   .. rubric:: Attributes Documentation
-
-   
-   .. autoattribute:: ref
-
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Documentation
-
-   
-   .. automethod:: get_ref
-
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.vo.tree.Group.rst b/docs/_generated/astropy.io.vo.tree.Group.rst
deleted file mode 100644
index 5a9ecc3..0000000
--- a/docs/_generated/astropy.io.vo.tree.Group.rst
+++ /dev/null
@@ -1,69 +0,0 @@
-
-.. include:: ../io/vo/references.txt
-
-
-Group
-========================
-
-.. currentmodule:: astropy.io.vo.tree
-
-.. autoclass:: Group
-   :show-inheritance:
-
-   
-     None
-   
-
-   
-   
-
-   .. rubric:: Attributes Summary
-
-   .. autosummary::
-   
-      ~Group.entries
-      ~Group.ref
-
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Summary
-
-   .. autosummary::
-   
-      ~Group.parse
-      ~Group.iter_groups
-      ~Group.to_xml
-      ~Group.iter_fields_and_params
-
-   
-   
-
-   
-   
-
-   .. rubric:: Attributes Documentation
-
-   
-   .. autoattribute:: entries
-   .. autoattribute:: ref
-
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Documentation
-
-   
-   .. automethod:: parse
-   .. automethod:: iter_groups
-   .. automethod:: to_xml
-   .. automethod:: iter_fields_and_params
-
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.vo.tree.Info.rst b/docs/_generated/astropy.io.vo.tree.Info.rst
deleted file mode 100644
index e3a592d..0000000
--- a/docs/_generated/astropy.io.vo.tree.Info.rst
+++ /dev/null
@@ -1,54 +0,0 @@
-
-.. include:: ../io/vo/references.txt
-
-
-Info
-=======================
-
-.. currentmodule:: astropy.io.vo.tree
-
-.. autoclass:: Info
-   :show-inheritance:
-
-   
-     None
-   
-
-   
-   
-
-   .. rubric:: Attributes Summary
-
-   .. autosummary::
-   
-      ~Info.name
-      ~Info.value
-      ~Info.content
-      ~Info.ref
-      ~Info.unit
-
-   
-   
-
-   
-   
-   
-
-   
-   
-
-   .. rubric:: Attributes Documentation
-
-   
-   .. autoattribute:: name
-   .. autoattribute:: value
-   .. autoattribute:: content
-   .. autoattribute:: ref
-   .. autoattribute:: unit
-
-   
-   
-
-   
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.vo.tree.Link.rst b/docs/_generated/astropy.io.vo.tree.Link.rst
deleted file mode 100644
index aaf063c..0000000
--- a/docs/_generated/astropy.io.vo.tree.Link.rst
+++ /dev/null
@@ -1,50 +0,0 @@
-
-.. include:: ../io/vo/references.txt
-
-
-Link
-=======================
-
-.. currentmodule:: astropy.io.vo.tree
-
-.. autoclass:: Link
-   :show-inheritance:
-
-   
-     None
-   
-
-   
-   
-
-   .. rubric:: Attributes Summary
-
-   .. autosummary::
-   
-      ~Link.href
-      ~Link.content_role
-      ~Link.content_type
-
-   
-   
-
-   
-   
-   
-
-   
-   
-
-   .. rubric:: Attributes Documentation
-
-   
-   .. autoattribute:: href
-   .. autoattribute:: content_role
-   .. autoattribute:: content_type
-
-   
-   
-
-   
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.vo.tree.Param.rst b/docs/_generated/astropy.io.vo.tree.Param.rst
deleted file mode 100644
index 9095492..0000000
--- a/docs/_generated/astropy.io.vo.tree.Param.rst
+++ /dev/null
@@ -1,61 +0,0 @@
-
-.. include:: ../io/vo/references.txt
-
-
-Param
-========================
-
-.. currentmodule:: astropy.io.vo.tree
-
-.. autoclass:: Param
-   :show-inheritance:
-
-   
-     None
-   
-
-   
-   
-
-   .. rubric:: Attributes Summary
-
-   .. autosummary::
-   
-      ~Param.value
-
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Summary
-
-   .. autosummary::
-   
-      ~Param.to_xml
-
-   
-   
-
-   
-   
-
-   .. rubric:: Attributes Documentation
-
-   
-   .. autoattribute:: value
-
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Documentation
-
-   
-   .. automethod:: to_xml
-
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.vo.tree.ParamRef.rst b/docs/_generated/astropy.io.vo.tree.ParamRef.rst
deleted file mode 100644
index 7cd9a86..0000000
--- a/docs/_generated/astropy.io.vo.tree.ParamRef.rst
+++ /dev/null
@@ -1,61 +0,0 @@
-
-.. include:: ../io/vo/references.txt
-
-
-ParamRef
-===========================
-
-.. currentmodule:: astropy.io.vo.tree
-
-.. autoclass:: ParamRef
-   :show-inheritance:
-
-   
-     None
-   
-
-   
-   
-
-   .. rubric:: Attributes Summary
-
-   .. autosummary::
-   
-      ~ParamRef.ref
-
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Summary
-
-   .. autosummary::
-   
-      ~ParamRef.get_ref
-
-   
-   
-
-   
-   
-
-   .. rubric:: Attributes Documentation
-
-   
-   .. autoattribute:: ref
-
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Documentation
-
-   
-   .. automethod:: get_ref
-
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.vo.tree.Resource.rst b/docs/_generated/astropy.io.vo.tree.Resource.rst
deleted file mode 100644
index 92c022d..0000000
--- a/docs/_generated/astropy.io.vo.tree.Resource.rst
+++ /dev/null
@@ -1,83 +0,0 @@
-
-.. include:: ../io/vo/references.txt
-
-
-Resource
-===========================
-
-.. currentmodule:: astropy.io.vo.tree
-
-.. autoclass:: Resource
-   :show-inheritance:
-
-   
-     None
-   
-
-   
-   
-
-   .. rubric:: Attributes Summary
-
-   .. autosummary::
-   
-      ~Resource.coordinate_systems
-      ~Resource.links
-      ~Resource.extra_attributes
-      ~Resource.infos
-      ~Resource.tables
-      ~Resource.params
-      ~Resource.type
-      ~Resource.resources
-
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Summary
-
-   .. autosummary::
-   
-      ~Resource.parse
-      ~Resource.to_xml
-      ~Resource.iter_fields_and_params
-      ~Resource.iter_tables
-      ~Resource.iter_coosys
-
-   
-   
-
-   
-   
-
-   .. rubric:: Attributes Documentation
-
-   
-   .. autoattribute:: coordinate_systems
-   .. autoattribute:: links
-   .. autoattribute:: extra_attributes
-   .. autoattribute:: infos
-   .. autoattribute:: tables
-   .. autoattribute:: params
-   .. autoattribute:: type
-   .. autoattribute:: resources
-
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Documentation
-
-   
-   .. automethod:: parse
-   .. automethod:: to_xml
-   .. automethod:: iter_fields_and_params
-   .. automethod:: iter_tables
-   .. automethod:: iter_coosys
-
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.vo.tree.Table.rst b/docs/_generated/astropy.io.vo.tree.Table.rst
deleted file mode 100644
index 4ee4019..0000000
--- a/docs/_generated/astropy.io.vo.tree.Table.rst
+++ /dev/null
@@ -1,91 +0,0 @@
-
-.. include:: ../io/vo/references.txt
-
-
-Table
-========================
-
-.. currentmodule:: astropy.io.vo.tree
-
-.. autoclass:: Table
-   :show-inheritance:
-
-   
-     None
-   
-
-   
-   
-
-   .. rubric:: Attributes Summary
-
-   .. autosummary::
-   
-      ~Table.links
-      ~Table.format
-      ~Table.groups
-      ~Table.infos
-      ~Table.nrows
-      ~Table.fields
-      ~Table.params
-      ~Table.ref
-
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Summary
-
-   .. autosummary::
-   
-      ~Table.parse
-      ~Table.is_empty
-      ~Table.to_xml
-      ~Table.iter_fields_and_params
-      ~Table.get_field_by_id_or_name
-      ~Table.get_field_by_id
-      ~Table.iter_groups
-      ~Table.create_arrays
-      ~Table.get_group_by_id
-
-   
-   
-
-   
-   
-
-   .. rubric:: Attributes Documentation
-
-   
-   .. autoattribute:: links
-   .. autoattribute:: format
-   .. autoattribute:: groups
-   .. autoattribute:: infos
-   .. autoattribute:: nrows
-   .. autoattribute:: fields
-   .. autoattribute:: params
-   .. autoattribute:: ref
-
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Documentation
-
-   
-   .. automethod:: parse
-   .. automethod:: is_empty
-   .. automethod:: to_xml
-   .. automethod:: iter_fields_and_params
-   .. automethod:: get_field_by_id_or_name
-   .. automethod:: get_field_by_id
-   .. automethod:: iter_groups
-   .. automethod:: create_arrays
-   .. automethod:: get_group_by_id
-
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.vo.tree.VOTableFile.rst b/docs/_generated/astropy.io.vo.tree.VOTableFile.rst
deleted file mode 100644
index a9bf153..0000000
--- a/docs/_generated/astropy.io.vo.tree.VOTableFile.rst
+++ /dev/null
@@ -1,101 +0,0 @@
-
-.. include:: ../io/vo/references.txt
-
-
-VOTableFile
-==============================
-
-.. currentmodule:: astropy.io.vo.tree
-
-.. autoclass:: VOTableFile
-   :show-inheritance:
-
-   
-     None
-   
-
-   
-   
-
-   .. rubric:: Attributes Summary
-
-   .. autosummary::
-   
-      ~VOTableFile.coordinate_systems
-      ~VOTableFile.groups
-      ~VOTableFile.infos
-      ~VOTableFile.version
-      ~VOTableFile.params
-      ~VOTableFile.resources
-
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Summary
-
-   .. autosummary::
-   
-      ~VOTableFile.get_first_table
-      ~VOTableFile.parse
-      ~VOTableFile.get_field_by_id_or_name
-      ~VOTableFile.get_table_by_id
-      ~VOTableFile.to_xml
-      ~VOTableFile.iter_fields_and_params
-      ~VOTableFile.iter_values
-      ~VOTableFile.get_values_by_id
-      ~VOTableFile.set_all_tables_format
-      ~VOTableFile.iter_tables
-      ~VOTableFile.iter_coosys
-      ~VOTableFile.get_field_by_id
-      ~VOTableFile.iter_groups
-      ~VOTableFile.get_coosys_by_id
-      ~VOTableFile.get_table_by_index
-      ~VOTableFile.get_group_by_id
-
-   
-   
-
-   
-   
-
-   .. rubric:: Attributes Documentation
-
-   
-   .. autoattribute:: coordinate_systems
-   .. autoattribute:: groups
-   .. autoattribute:: infos
-   .. autoattribute:: version
-   .. autoattribute:: params
-   .. autoattribute:: resources
-
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Documentation
-
-   
-   .. automethod:: get_first_table
-   .. automethod:: parse
-   .. automethod:: get_field_by_id_or_name
-   .. automethod:: get_table_by_id
-   .. automethod:: to_xml
-   .. automethod:: iter_fields_and_params
-   .. automethod:: iter_values
-   .. automethod:: get_values_by_id
-   .. automethod:: set_all_tables_format
-   .. automethod:: iter_tables
-   .. automethod:: iter_coosys
-   .. automethod:: get_field_by_id
-   .. automethod:: iter_groups
-   .. automethod:: get_coosys_by_id
-   .. automethod:: get_table_by_index
-   .. automethod:: get_group_by_id
-
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.vo.tree.Values.rst b/docs/_generated/astropy.io.vo.tree.Values.rst
deleted file mode 100644
index df3c5a3..0000000
--- a/docs/_generated/astropy.io.vo.tree.Values.rst
+++ /dev/null
@@ -1,79 +0,0 @@
-
-.. include:: ../io/vo/references.txt
-
-
-Values
-=========================
-
-.. currentmodule:: astropy.io.vo.tree
-
-.. autoclass:: Values
-   :show-inheritance:
-
-   
-     None
-   
-
-   
-   
-
-   .. rubric:: Attributes Summary
-
-   .. autosummary::
-   
-      ~Values.ref
-      ~Values.min
-      ~Values.max_inclusive
-      ~Values.max
-      ~Values.min_inclusive
-      ~Values.null
-      ~Values.type
-      ~Values.options
-
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Summary
-
-   .. autosummary::
-   
-      ~Values.parse
-      ~Values.to_xml
-      ~Values.is_defaults
-
-   
-   
-
-   
-   
-
-   .. rubric:: Attributes Documentation
-
-   
-   .. autoattribute:: ref
-   .. autoattribute:: min
-   .. autoattribute:: max_inclusive
-   .. autoattribute:: max
-   .. autoattribute:: min_inclusive
-   .. autoattribute:: null
-   .. autoattribute:: type
-   .. autoattribute:: options
-
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Documentation
-
-   
-   .. automethod:: parse
-   .. automethod:: to_xml
-   .. automethod:: is_defaults
-
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.vo.ucd.check_ucd.rst b/docs/_generated/astropy.io.vo.ucd.check_ucd.rst
deleted file mode 100644
index 474a424..0000000
--- a/docs/_generated/astropy.io.vo.ucd.check_ucd.rst
+++ /dev/null
@@ -1,10 +0,0 @@
-
-.. include:: ../io/vo/references.txt
-
-
-check_ucd
-===========================
-
-.. currentmodule:: astropy.io.vo.ucd
-
-.. autofunction:: check_ucd
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.vo.ucd.parse_ucd.rst b/docs/_generated/astropy.io.vo.ucd.parse_ucd.rst
deleted file mode 100644
index df98382..0000000
--- a/docs/_generated/astropy.io.vo.ucd.parse_ucd.rst
+++ /dev/null
@@ -1,10 +0,0 @@
-
-.. include:: ../io/vo/references.txt
-
-
-parse_ucd
-===========================
-
-.. currentmodule:: astropy.io.vo.ucd
-
-.. autofunction:: parse_ucd
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.vo.unit.check_unit.rst b/docs/_generated/astropy.io.vo.unit.check_unit.rst
deleted file mode 100644
index 2b82b45..0000000
--- a/docs/_generated/astropy.io.vo.unit.check_unit.rst
+++ /dev/null
@@ -1,10 +0,0 @@
-
-.. include:: ../io/vo/references.txt
-
-
-check_unit
-=============================
-
-.. currentmodule:: astropy.io.vo.unit
-
-.. autofunction:: check_unit
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.vo.unit.is_unit.rst b/docs/_generated/astropy.io.vo.unit.is_unit.rst
deleted file mode 100644
index 3d1c47c..0000000
--- a/docs/_generated/astropy.io.vo.unit.is_unit.rst
+++ /dev/null
@@ -1,10 +0,0 @@
-
-.. include:: ../io/vo/references.txt
-
-
-is_unit
-==========================
-
-.. currentmodule:: astropy.io.vo.unit
-
-.. autofunction:: is_unit
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.vo.util.coerce_range_list_param.rst b/docs/_generated/astropy.io.vo.util.coerce_range_list_param.rst
deleted file mode 100644
index 76eaec8..0000000
--- a/docs/_generated/astropy.io.vo.util.coerce_range_list_param.rst
+++ /dev/null
@@ -1,10 +0,0 @@
-
-.. include:: ../io/vo/references.txt
-
-
-coerce_range_list_param
-==========================================
-
-.. currentmodule:: astropy.io.vo.util
-
-.. autofunction:: coerce_range_list_param
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.vo.util.convert_to_writable_filelike.rst b/docs/_generated/astropy.io.vo.util.convert_to_writable_filelike.rst
deleted file mode 100644
index a5130d8..0000000
--- a/docs/_generated/astropy.io.vo.util.convert_to_writable_filelike.rst
+++ /dev/null
@@ -1,10 +0,0 @@
-
-.. include:: ../io/vo/references.txt
-
-
-convert_to_writable_filelike
-===============================================
-
-.. currentmodule:: astropy.io.vo.util
-
-.. autofunction:: convert_to_writable_filelike
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.vo.util.is_callable.rst b/docs/_generated/astropy.io.vo.util.is_callable.rst
deleted file mode 100644
index f36a06f..0000000
--- a/docs/_generated/astropy.io.vo.util.is_callable.rst
+++ /dev/null
@@ -1,10 +0,0 @@
-
-.. include:: ../io/vo/references.txt
-
-
-is_callable
-==============================
-
-.. currentmodule:: astropy.io.vo.util
-
-.. autofunction:: is_callable
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.vo.validator.main.make_validation_report.rst b/docs/_generated/astropy.io.vo.validator.main.make_validation_report.rst
deleted file mode 100644
index 609869b..0000000
--- a/docs/_generated/astropy.io.vo.validator.main.make_validation_report.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-make_validation_report
-===================================================
-
-.. currentmodule:: astropy.io.vo.validator.main
-
-.. autofunction:: make_validation_report
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.vo.xmlutil.check_anyuri.rst b/docs/_generated/astropy.io.vo.xmlutil.check_anyuri.rst
deleted file mode 100644
index 37b851b..0000000
--- a/docs/_generated/astropy.io.vo.xmlutil.check_anyuri.rst
+++ /dev/null
@@ -1,10 +0,0 @@
-
-.. include:: ../io/vo/references.txt
-
-
-check_anyuri
-==================================
-
-.. currentmodule:: astropy.io.vo.xmlutil
-
-.. autofunction:: check_anyuri
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.vo.xmlutil.check_id.rst b/docs/_generated/astropy.io.vo.xmlutil.check_id.rst
deleted file mode 100644
index 51ec351..0000000
--- a/docs/_generated/astropy.io.vo.xmlutil.check_id.rst
+++ /dev/null
@@ -1,10 +0,0 @@
-
-.. include:: ../io/vo/references.txt
-
-
-check_id
-==============================
-
-.. currentmodule:: astropy.io.vo.xmlutil
-
-.. autofunction:: check_id
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.vo.xmlutil.check_mime_content_type.rst b/docs/_generated/astropy.io.vo.xmlutil.check_mime_content_type.rst
deleted file mode 100644
index 6dcce26..0000000
--- a/docs/_generated/astropy.io.vo.xmlutil.check_mime_content_type.rst
+++ /dev/null
@@ -1,10 +0,0 @@
-
-.. include:: ../io/vo/references.txt
-
-
-check_mime_content_type
-=============================================
-
-.. currentmodule:: astropy.io.vo.xmlutil
-
-.. autofunction:: check_mime_content_type
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.vo.xmlutil.check_token.rst b/docs/_generated/astropy.io.vo.xmlutil.check_token.rst
deleted file mode 100644
index 4244b6b..0000000
--- a/docs/_generated/astropy.io.vo.xmlutil.check_token.rst
+++ /dev/null
@@ -1,10 +0,0 @@
-
-.. include:: ../io/vo/references.txt
-
-
-check_token
-=================================
-
-.. currentmodule:: astropy.io.vo.xmlutil
-
-.. autofunction:: check_token
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.vo.xmlutil.fix_id.rst b/docs/_generated/astropy.io.vo.xmlutil.fix_id.rst
deleted file mode 100644
index 73c44de..0000000
--- a/docs/_generated/astropy.io.vo.xmlutil.fix_id.rst
+++ /dev/null
@@ -1,10 +0,0 @@
-
-.. include:: ../io/vo/references.txt
-
-
-fix_id
-============================
-
-.. currentmodule:: astropy.io.vo.xmlutil
-
-.. autofunction:: fix_id
\ No newline at end of file
diff --git a/docs/_generated/astropy.io.vo.xmlutil.validate_schema.rst b/docs/_generated/astropy.io.vo.xmlutil.validate_schema.rst
deleted file mode 100644
index 0075218..0000000
--- a/docs/_generated/astropy.io.vo.xmlutil.validate_schema.rst
+++ /dev/null
@@ -1,10 +0,0 @@
-
-.. include:: ../io/vo/references.txt
-
-
-validate_schema
-=====================================
-
-.. currentmodule:: astropy.io.vo.xmlutil
-
-.. autofunction:: validate_schema
\ No newline at end of file
diff --git a/docs/_generated/astropy.logger.AstropyLogger.rst b/docs/_generated/astropy.logger.AstropyLogger.rst
deleted file mode 100644
index bf50ccb..0000000
--- a/docs/_generated/astropy.logger.AstropyLogger.rst
+++ /dev/null
@@ -1,64 +0,0 @@
-
-
-AstropyLogger
-============================
-
-.. currentmodule:: astropy.logger
-
-.. autoclass:: AstropyLogger
-   :show-inheritance:
-
-   
-
-   
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Summary
-
-   .. autosummary::
-   
-      ~AstropyLogger.warnings_logging_enabled
-      ~AstropyLogger.exception_logging_enabled
-      ~AstropyLogger.log_to_file
-      ~AstropyLogger.disable_color
-      ~AstropyLogger.setLevel
-      ~AstropyLogger.enable_warnings_logging
-      ~AstropyLogger.enable_color
-      ~AstropyLogger.enable_exception_logging
-      ~AstropyLogger.disable_warnings_logging
-      ~AstropyLogger.disable_exception_logging
-      ~AstropyLogger.log_to_list
-      ~AstropyLogger.makeRecord
-
-   
-   
-
-   
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Documentation
-
-   
-   .. automethod:: warnings_logging_enabled
-   .. automethod:: exception_logging_enabled
-   .. automethod:: log_to_file
-   .. automethod:: disable_color
-   .. automethod:: setLevel
-   .. automethod:: enable_warnings_logging
-   .. automethod:: enable_color
-   .. automethod:: enable_exception_logging
-   .. automethod:: disable_warnings_logging
-   .. automethod:: disable_exception_logging
-   .. automethod:: log_to_list
-   .. automethod:: makeRecord
-
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.logger.LoggingError.rst b/docs/_generated/astropy.logger.LoggingError.rst
deleted file mode 100644
index dc86cfb..0000000
--- a/docs/_generated/astropy.logger.LoggingError.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-LoggingError
-===========================
-
-.. currentmodule:: astropy.logger
-
-.. autoexception:: LoggingError
\ No newline at end of file
diff --git a/docs/_generated/astropy.nddata.convolution.convolve.convolve.rst b/docs/_generated/astropy.nddata.convolution.convolve.convolve.rst
deleted file mode 100644
index 5ab8d69..0000000
--- a/docs/_generated/astropy.nddata.convolution.convolve.convolve.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-convolve
-============================================
-
-.. currentmodule:: astropy.nddata.convolution.convolve
-
-.. autofunction:: convolve
\ No newline at end of file
diff --git a/docs/_generated/astropy.nddata.convolution.convolve.convolve_fft.rst b/docs/_generated/astropy.nddata.convolution.convolve.convolve_fft.rst
deleted file mode 100644
index 08665fd..0000000
--- a/docs/_generated/astropy.nddata.convolution.convolve.convolve_fft.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-convolve_fft
-================================================
-
-.. currentmodule:: astropy.nddata.convolution.convolve
-
-.. autofunction:: convolve_fft
\ No newline at end of file
diff --git a/docs/_generated/astropy.nddata.convolution.make_kernel.make_kernel.rst b/docs/_generated/astropy.nddata.convolution.make_kernel.make_kernel.rst
deleted file mode 100644
index fe57f1d..0000000
--- a/docs/_generated/astropy.nddata.convolution.make_kernel.make_kernel.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-make_kernel
-==================================================
-
-.. currentmodule:: astropy.nddata.convolution.make_kernel
-
-.. autofunction:: make_kernel
\ No newline at end of file
diff --git a/docs/_generated/astropy.nddata.nddata.NDData.rst b/docs/_generated/astropy.nddata.nddata.NDData.rst
deleted file mode 100644
index faef6bd..0000000
--- a/docs/_generated/astropy.nddata.nddata.NDData.rst
+++ /dev/null
@@ -1,52 +0,0 @@
-
-
-NDData
-============================
-
-.. currentmodule:: astropy.nddata.nddata
-
-.. autoclass:: NDData
-   :show-inheritance:
-
-   
-     None
-   
-
-   
-   
-
-   .. rubric:: Attributes Summary
-
-   .. autosummary::
-   
-      ~NDData.ndim
-      ~NDData.dtype
-      ~NDData.boolmask
-      ~NDData.shape
-      ~NDData.size
-
-   
-   
-
-   
-   
-   
-
-   
-   
-
-   .. rubric:: Attributes Documentation
-
-   
-   .. autoattribute:: ndim
-   .. autoattribute:: dtype
-   .. autoattribute:: boolmask
-   .. autoattribute:: shape
-   .. autoattribute:: size
-
-   
-   
-
-   
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.table.table.Column.rst b/docs/_generated/astropy.table.table.Column.rst
deleted file mode 100644
index e66eb7e..0000000
--- a/docs/_generated/astropy.table.table.Column.rst
+++ /dev/null
@@ -1,71 +0,0 @@
-
-.. include:: ../table/references.txt
-
-
-Column
-==========================
-
-.. currentmodule:: astropy.table.table
-
-.. autoclass:: Column
-   :show-inheritance:
-
-   
-
-   
-   
-
-   .. rubric:: Attributes Summary
-
-   .. autosummary::
-   
-      ~Column.data
-      ~Column.name
-      ~Column.descr
-
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Summary
-
-   .. autosummary::
-   
-      ~Column.copy
-      ~Column.pprint
-      ~Column.pformat
-      ~Column.attrs_equal
-      ~Column.more
-
-   
-   
-
-   
-   
-
-   .. rubric:: Attributes Documentation
-
-   
-   .. autoattribute:: data
-   .. autoattribute:: name
-   .. autoattribute:: descr
-
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Documentation
-
-   
-   .. automethod:: copy
-   .. automethod:: pprint
-   .. automethod:: pformat
-   .. automethod:: attrs_equal
-   .. automethod:: more
-
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.table.table.Row.rst b/docs/_generated/astropy.table.table.Row.rst
deleted file mode 100644
index 96edaf7..0000000
--- a/docs/_generated/astropy.table.table.Row.rst
+++ /dev/null
@@ -1,58 +0,0 @@
-
-.. include:: ../table/references.txt
-
-
-Row
-=======================
-
-.. currentmodule:: astropy.table.table
-
-.. autoclass:: Row
-   :show-inheritance:
-
-   
-     None
-   
-
-   
-   
-
-   .. rubric:: Attributes Summary
-
-   .. autosummary::
-   
-      ~Row.dtype
-      ~Row.meta
-      ~Row.table
-      ~Row.colnames
-      ~Row.data
-      ~Row.index
-      ~Row.columns
-
-   
-   
-
-   
-   
-   
-
-   
-   
-
-   .. rubric:: Attributes Documentation
-
-   
-   .. autoattribute:: dtype
-   .. autoattribute:: meta
-   .. autoattribute:: table
-   .. autoattribute:: colnames
-   .. autoattribute:: data
-   .. autoattribute:: index
-   .. autoattribute:: columns
-
-   
-   
-
-   
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.table.table.Table.rst b/docs/_generated/astropy.table.table.Table.rst
deleted file mode 100644
index 9816521..0000000
--- a/docs/_generated/astropy.table.table.Table.rst
+++ /dev/null
@@ -1,93 +0,0 @@
-
-.. include:: ../table/references.txt
-
-
-Table
-=========================
-
-.. currentmodule:: astropy.table.table
-
-.. autoclass:: Table
-   :show-inheritance:
-
-   
-     None
-   
-
-   
-   
-
-   .. rubric:: Attributes Summary
-
-   .. autosummary::
-   
-      ~Table.dtype
-      ~Table.colnames
-
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Summary
-
-   .. autosummary::
-   
-      ~Table.rename_column
-      ~Table.pprint
-      ~Table.index_column
-      ~Table.next
-      ~Table.field
-      ~Table.add_column
-      ~Table.more
-      ~Table.sort
-      ~Table.keys
-      ~Table.remove_columns
-      ~Table.reverse
-      ~Table.add_columns
-      ~Table.keep_columns
-      ~Table.remove_column
-      ~Table.pformat
-      ~Table.add_row
-
-   
-   
-
-   
-   
-
-   .. rubric:: Attributes Documentation
-
-   
-   .. autoattribute:: dtype
-   .. autoattribute:: colnames
-
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Documentation
-
-   
-   .. automethod:: rename_column
-   .. automethod:: pprint
-   .. automethod:: index_column
-   .. automethod:: next
-   .. automethod:: field
-   .. automethod:: add_column
-   .. automethod:: more
-   .. automethod:: sort
-   .. automethod:: keys
-   .. automethod:: remove_columns
-   .. automethod:: reverse
-   .. automethod:: add_columns
-   .. automethod:: keep_columns
-   .. automethod:: remove_column
-   .. automethod:: pformat
-   .. automethod:: add_row
-
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.table.table.TableColumns.rst b/docs/_generated/astropy.table.table.TableColumns.rst
deleted file mode 100644
index 05c6615..0000000
--- a/docs/_generated/astropy.table.table.TableColumns.rst
+++ /dev/null
@@ -1,48 +0,0 @@
-
-.. include:: ../table/references.txt
-
-
-TableColumns
-================================
-
-.. currentmodule:: astropy.table.table
-
-.. autoclass:: TableColumns
-   :show-inheritance:
-
-   
-     None
-   
-
-   
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Summary
-
-   .. autosummary::
-   
-      ~TableColumns.keys
-      ~TableColumns.values
-
-   
-   
-
-   
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Documentation
-
-   
-   .. automethod:: keys
-   .. automethod:: values
-
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.tools.misc.sigma_clip.rst b/docs/_generated/astropy.tools.misc.sigma_clip.rst
deleted file mode 100644
index 99f950c..0000000
--- a/docs/_generated/astropy.tools.misc.sigma_clip.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-sigma_clip
-=============================
-
-.. currentmodule:: astropy.tools.misc
-
-.. autofunction:: sigma_clip
\ No newline at end of file
diff --git a/docs/_generated/astropy.utils.collections.HomogeneousList.rst b/docs/_generated/astropy.utils.collections.HomogeneousList.rst
deleted file mode 100644
index a3147da..0000000
--- a/docs/_generated/astropy.utils.collections.HomogeneousList.rst
+++ /dev/null
@@ -1,48 +0,0 @@
-
-
-HomogeneousList
-=========================================
-
-.. currentmodule:: astropy.utils.collections
-
-.. autoclass:: HomogeneousList
-   :show-inheritance:
-
-   
-     None
-   
-
-   
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Summary
-
-   .. autosummary::
-   
-      ~HomogeneousList.insert
-      ~HomogeneousList.extend
-      ~HomogeneousList.append
-
-   
-   
-
-   
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Documentation
-
-   
-   .. automethod:: insert
-   .. automethod:: extend
-   .. automethod:: append
-
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.utils.console.ProgressBar.rst b/docs/_generated/astropy.utils.console.ProgressBar.rst
deleted file mode 100644
index e532a97..0000000
--- a/docs/_generated/astropy.utils.console.ProgressBar.rst
+++ /dev/null
@@ -1,48 +0,0 @@
-
-
-ProgressBar
-=================================
-
-.. currentmodule:: astropy.utils.console
-
-.. autoclass:: ProgressBar
-   :show-inheritance:
-
-   
-     None
-   
-
-   
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Summary
-
-   .. autosummary::
-   
-      ~ProgressBar.map
-      ~ProgressBar.update
-      ~ProgressBar.iterate
-
-   
-   
-
-   
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Documentation
-
-   
-   .. automethod:: map
-   .. automethod:: update
-   .. automethod:: iterate
-
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.utils.console.ProgressBarOrSpinner.rst b/docs/_generated/astropy.utils.console.ProgressBarOrSpinner.rst
deleted file mode 100644
index 5532b29..0000000
--- a/docs/_generated/astropy.utils.console.ProgressBarOrSpinner.rst
+++ /dev/null
@@ -1,44 +0,0 @@
-
-
-ProgressBarOrSpinner
-==========================================
-
-.. currentmodule:: astropy.utils.console
-
-.. autoclass:: ProgressBarOrSpinner
-   :show-inheritance:
-
-   
-     None
-   
-
-   
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Summary
-
-   .. autosummary::
-   
-      ~ProgressBarOrSpinner.update
-
-   
-   
-
-   
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Documentation
-
-   
-   .. automethod:: update
-
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.utils.console.Spinner.rst b/docs/_generated/astropy.utils.console.Spinner.rst
deleted file mode 100644
index d7135f7..0000000
--- a/docs/_generated/astropy.utils.console.Spinner.rst
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-Spinner
-=============================
-
-.. currentmodule:: astropy.utils.console
-
-.. autoclass:: Spinner
-   :show-inheritance:
-
-   
-     None
-   
-
-   
-   
-   
-
-   
-   
-   
-
-   
-   
-   
-
-   
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.utils.console.color_print.rst b/docs/_generated/astropy.utils.console.color_print.rst
deleted file mode 100644
index cffe427..0000000
--- a/docs/_generated/astropy.utils.console.color_print.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-color_print
-=================================
-
-.. currentmodule:: astropy.utils.console
-
-.. autofunction:: color_print
\ No newline at end of file
diff --git a/docs/_generated/astropy.utils.console.human_time.rst b/docs/_generated/astropy.utils.console.human_time.rst
deleted file mode 100644
index c1ee654..0000000
--- a/docs/_generated/astropy.utils.console.human_time.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-human_time
-================================
-
-.. currentmodule:: astropy.utils.console
-
-.. autofunction:: human_time
\ No newline at end of file
diff --git a/docs/_generated/astropy.utils.console.isatty.rst b/docs/_generated/astropy.utils.console.isatty.rst
deleted file mode 100644
index 2c1b13d..0000000
--- a/docs/_generated/astropy.utils.console.isatty.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-isatty
-============================
-
-.. currentmodule:: astropy.utils.console
-
-.. autofunction:: isatty
\ No newline at end of file
diff --git a/docs/_generated/astropy.utils.console.print_code_line.rst b/docs/_generated/astropy.utils.console.print_code_line.rst
deleted file mode 100644
index e123b8a..0000000
--- a/docs/_generated/astropy.utils.console.print_code_line.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-print_code_line
-=====================================
-
-.. currentmodule:: astropy.utils.console
-
-.. autofunction:: print_code_line
\ No newline at end of file
diff --git a/docs/_generated/astropy.utils.misc.deprecated.rst b/docs/_generated/astropy.utils.misc.deprecated.rst
deleted file mode 100644
index c7e54d7..0000000
--- a/docs/_generated/astropy.utils.misc.deprecated.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-deprecated
-=============================
-
-.. currentmodule:: astropy.utils.misc
-
-.. autofunction:: deprecated
\ No newline at end of file
diff --git a/docs/_generated/astropy.utils.misc.find_current_module.rst b/docs/_generated/astropy.utils.misc.find_current_module.rst
deleted file mode 100644
index 8ae6b26..0000000
--- a/docs/_generated/astropy.utils.misc.find_current_module.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-find_current_module
-======================================
-
-.. currentmodule:: astropy.utils.misc
-
-.. autofunction:: find_current_module
\ No newline at end of file
diff --git a/docs/_generated/astropy.utils.misc.fnpickle.rst b/docs/_generated/astropy.utils.misc.fnpickle.rst
deleted file mode 100644
index fbb059c..0000000
--- a/docs/_generated/astropy.utils.misc.fnpickle.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-fnpickle
-===========================
-
-.. currentmodule:: astropy.utils.misc
-
-.. autofunction:: fnpickle
\ No newline at end of file
diff --git a/docs/_generated/astropy.utils.misc.fnunpickle.rst b/docs/_generated/astropy.utils.misc.fnunpickle.rst
deleted file mode 100644
index 0a74231..0000000
--- a/docs/_generated/astropy.utils.misc.fnunpickle.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-fnunpickle
-=============================
-
-.. currentmodule:: astropy.utils.misc
-
-.. autofunction:: fnunpickle
\ No newline at end of file
diff --git a/docs/_generated/astropy.utils.misc.isiterable.rst b/docs/_generated/astropy.utils.misc.isiterable.rst
deleted file mode 100644
index d606e59..0000000
--- a/docs/_generated/astropy.utils.misc.isiterable.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-isiterable
-=============================
-
-.. currentmodule:: astropy.utils.misc
-
-.. autofunction:: isiterable
\ No newline at end of file
diff --git a/docs/_generated/astropy.utils.misc.lazyproperty.rst b/docs/_generated/astropy.utils.misc.lazyproperty.rst
deleted file mode 100644
index fac8762..0000000
--- a/docs/_generated/astropy.utils.misc.lazyproperty.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-misc.lazyproperty
-===============================
-
-.. currentmodule:: astropy.utils
-
-.. autoattribute:: misc.lazyproperty
\ No newline at end of file
diff --git a/docs/_generated/astropy.utils.xml.check.check_anyuri.rst b/docs/_generated/astropy.utils.xml.check.check_anyuri.rst
deleted file mode 100644
index be4a862..0000000
--- a/docs/_generated/astropy.utils.xml.check.check_anyuri.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-check_anyuri
-====================================
-
-.. currentmodule:: astropy.utils.xml.check
-
-.. autofunction:: check_anyuri
\ No newline at end of file
diff --git a/docs/_generated/astropy.utils.xml.check.check_id.rst b/docs/_generated/astropy.utils.xml.check.check_id.rst
deleted file mode 100644
index 69e3edb..0000000
--- a/docs/_generated/astropy.utils.xml.check.check_id.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-check_id
-================================
-
-.. currentmodule:: astropy.utils.xml.check
-
-.. autofunction:: check_id
\ No newline at end of file
diff --git a/docs/_generated/astropy.utils.xml.check.check_mime_content_type.rst b/docs/_generated/astropy.utils.xml.check.check_mime_content_type.rst
deleted file mode 100644
index 44f8b0f..0000000
--- a/docs/_generated/astropy.utils.xml.check.check_mime_content_type.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-check_mime_content_type
-===============================================
-
-.. currentmodule:: astropy.utils.xml.check
-
-.. autofunction:: check_mime_content_type
\ No newline at end of file
diff --git a/docs/_generated/astropy.utils.xml.check.check_token.rst b/docs/_generated/astropy.utils.xml.check.check_token.rst
deleted file mode 100644
index 6ff6006..0000000
--- a/docs/_generated/astropy.utils.xml.check.check_token.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-check_token
-===================================
-
-.. currentmodule:: astropy.utils.xml.check
-
-.. autofunction:: check_token
\ No newline at end of file
diff --git a/docs/_generated/astropy.utils.xml.check.fix_id.rst b/docs/_generated/astropy.utils.xml.check.fix_id.rst
deleted file mode 100644
index 61861e6..0000000
--- a/docs/_generated/astropy.utils.xml.check.fix_id.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-fix_id
-==============================
-
-.. currentmodule:: astropy.utils.xml.check
-
-.. autofunction:: fix_id
\ No newline at end of file
diff --git a/docs/_generated/astropy.utils.xml.iterparser.get_xml_encoding.rst b/docs/_generated/astropy.utils.xml.iterparser.get_xml_encoding.rst
deleted file mode 100644
index 24a870e..0000000
--- a/docs/_generated/astropy.utils.xml.iterparser.get_xml_encoding.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-get_xml_encoding
-=============================================
-
-.. currentmodule:: astropy.utils.xml.iterparser
-
-.. autofunction:: get_xml_encoding
\ No newline at end of file
diff --git a/docs/_generated/astropy.utils.xml.iterparser.get_xml_iterator.rst b/docs/_generated/astropy.utils.xml.iterparser.get_xml_iterator.rst
deleted file mode 100644
index b6ea44c..0000000
--- a/docs/_generated/astropy.utils.xml.iterparser.get_xml_iterator.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-get_xml_iterator
-=============================================
-
-.. currentmodule:: astropy.utils.xml.iterparser
-
-.. autofunction:: get_xml_iterator
\ No newline at end of file
diff --git a/docs/_generated/astropy.utils.xml.iterparser.xml_readlines.rst b/docs/_generated/astropy.utils.xml.iterparser.xml_readlines.rst
deleted file mode 100644
index c86085c..0000000
--- a/docs/_generated/astropy.utils.xml.iterparser.xml_readlines.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-xml_readlines
-==========================================
-
-.. currentmodule:: astropy.utils.xml.iterparser
-
-.. autofunction:: xml_readlines
\ No newline at end of file
diff --git a/docs/_generated/astropy.utils.xml.validate.validate_schema.rst b/docs/_generated/astropy.utils.xml.validate.validate_schema.rst
deleted file mode 100644
index ded71b5..0000000
--- a/docs/_generated/astropy.utils.xml.validate.validate_schema.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-validate_schema
-==========================================
-
-.. currentmodule:: astropy.utils.xml.validate
-
-.. autofunction:: validate_schema
\ No newline at end of file
diff --git a/docs/_generated/astropy.utils.xml.writer.XMLWriter.rst b/docs/_generated/astropy.utils.xml.writer.XMLWriter.rst
deleted file mode 100644
index 87fb36a..0000000
--- a/docs/_generated/astropy.utils.xml.writer.XMLWriter.rst
+++ /dev/null
@@ -1,64 +0,0 @@
-
-
-XMLWriter
-==================================
-
-.. currentmodule:: astropy.utils.xml.writer
-
-.. autoclass:: XMLWriter
-   :show-inheritance:
-
-   
-     None
-   
-
-   
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Summary
-
-   .. autosummary::
-   
-      ~XMLWriter.comment
-      ~XMLWriter.end
-      ~XMLWriter.start
-      ~XMLWriter.get_indentation_spaces
-      ~XMLWriter.element
-      ~XMLWriter.tag
-      ~XMLWriter.object_attrs
-      ~XMLWriter.flush
-      ~XMLWriter.close
-      ~XMLWriter.get_indentation
-      ~XMLWriter.data
-
-   
-   
-
-   
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Documentation
-
-   
-   .. automethod:: comment
-   .. automethod:: end
-   .. automethod:: start
-   .. automethod:: get_indentation_spaces
-   .. automethod:: element
-   .. automethod:: tag
-   .. automethod:: object_attrs
-   .. automethod:: flush
-   .. automethod:: close
-   .. automethod:: get_indentation
-   .. automethod:: data
-
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.utils.xml.writer.xml_escape.rst b/docs/_generated/astropy.utils.xml.writer.xml_escape.rst
deleted file mode 100644
index 8ee6253..0000000
--- a/docs/_generated/astropy.utils.xml.writer.xml_escape.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-xml_escape
-===================================
-
-.. currentmodule:: astropy.utils.xml.writer
-
-.. autofunction:: xml_escape
\ No newline at end of file
diff --git a/docs/_generated/astropy.utils.xml.writer.xml_escape_cdata.rst b/docs/_generated/astropy.utils.xml.writer.xml_escape_cdata.rst
deleted file mode 100644
index 41af27a..0000000
--- a/docs/_generated/astropy.utils.xml.writer.xml_escape_cdata.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-xml_escape_cdata
-=========================================
-
-.. currentmodule:: astropy.utils.xml.writer
-
-.. autofunction:: xml_escape_cdata
\ No newline at end of file
diff --git a/docs/_generated/astropy.wcs.DistortionLookupTable.rst b/docs/_generated/astropy.wcs.DistortionLookupTable.rst
deleted file mode 100644
index af0bb32..0000000
--- a/docs/_generated/astropy.wcs.DistortionLookupTable.rst
+++ /dev/null
@@ -1,65 +0,0 @@
-
-.. include:: ../wcs/references.txt
-
-
-DistortionLookupTable
-=================================
-
-.. currentmodule:: astropy.wcs
-
-.. autoclass:: DistortionLookupTable
-   :show-inheritance:
-
-   
-
-   
-   
-
-   .. rubric:: Attributes Summary
-
-   .. autosummary::
-   
-      ~DistortionLookupTable.crpix
-      ~DistortionLookupTable.cdelt
-      ~DistortionLookupTable.crval
-      ~DistortionLookupTable.data
-
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Summary
-
-   .. autosummary::
-   
-      ~DistortionLookupTable.get_offset
-
-   
-   
-
-   
-   
-
-   .. rubric:: Attributes Documentation
-
-   
-   .. autoattribute:: crpix
-   .. autoattribute:: cdelt
-   .. autoattribute:: crval
-   .. autoattribute:: data
-
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Documentation
-
-   
-   .. automethod:: get_offset
-
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.wcs.Sip.rst b/docs/_generated/astropy.wcs.Sip.rst
deleted file mode 100644
index 7dd914c..0000000
--- a/docs/_generated/astropy.wcs.Sip.rst
+++ /dev/null
@@ -1,77 +0,0 @@
-
-.. include:: ../wcs/references.txt
-
-
-Sip
-===============
-
-.. currentmodule:: astropy.wcs
-
-.. autoclass:: Sip
-   :show-inheritance:
-
-   
-
-   
-   
-
-   .. rubric:: Attributes Summary
-
-   .. autosummary::
-   
-      ~Sip.a
-      ~Sip.b
-      ~Sip.b_order
-      ~Sip.bp_order
-      ~Sip.ap
-      ~Sip.a_order
-      ~Sip.bp
-      ~Sip.ap_order
-      ~Sip.crpix
-
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Summary
-
-   .. autosummary::
-   
-      ~Sip.pix2foc
-      ~Sip.foc2pix
-
-   
-   
-
-   
-   
-
-   .. rubric:: Attributes Documentation
-
-   
-   .. autoattribute:: a
-   .. autoattribute:: b
-   .. autoattribute:: b_order
-   .. autoattribute:: bp_order
-   .. autoattribute:: ap
-   .. autoattribute:: a_order
-   .. autoattribute:: bp
-   .. autoattribute:: ap_order
-   .. autoattribute:: crpix
-
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Documentation
-
-   
-   .. automethod:: pix2foc
-   .. automethod:: foc2pix
-
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.wcs.Tabprm.rst b/docs/_generated/astropy.wcs.Tabprm.rst
deleted file mode 100644
index df8ec04..0000000
--- a/docs/_generated/astropy.wcs.Tabprm.rst
+++ /dev/null
@@ -1,79 +0,0 @@
-
-.. include:: ../wcs/references.txt
-
-
-Tabprm
-==================
-
-.. currentmodule:: astropy.wcs
-
-.. autoclass:: Tabprm
-   :show-inheritance:
-
-   
-
-   
-   
-
-   .. rubric:: Attributes Summary
-
-   .. autosummary::
-   
-      ~Tabprm.map
-      ~Tabprm.p0
-      ~Tabprm.sense
-      ~Tabprm.nc
-      ~Tabprm.M
-      ~Tabprm.coord
-      ~Tabprm.delta
-      ~Tabprm.extrema
-      ~Tabprm.K
-      ~Tabprm.crval
-
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Summary
-
-   .. autosummary::
-   
-      ~Tabprm.print_contents
-      ~Tabprm.set
-
-   
-   
-
-   
-   
-
-   .. rubric:: Attributes Documentation
-
-   
-   .. autoattribute:: map
-   .. autoattribute:: p0
-   .. autoattribute:: sense
-   .. autoattribute:: nc
-   .. autoattribute:: M
-   .. autoattribute:: coord
-   .. autoattribute:: delta
-   .. autoattribute:: extrema
-   .. autoattribute:: K
-   .. autoattribute:: crval
-
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Documentation
-
-   
-   .. automethod:: print_contents
-   .. automethod:: set
-
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.wcs.UnitConverter.rst b/docs/_generated/astropy.wcs.UnitConverter.rst
deleted file mode 100644
index f564edf..0000000
--- a/docs/_generated/astropy.wcs.UnitConverter.rst
+++ /dev/null
@@ -1,67 +0,0 @@
-
-.. include:: ../wcs/references.txt
-
-
-UnitConverter
-=========================
-
-.. currentmodule:: astropy.wcs
-
-.. autoclass:: UnitConverter
-   :show-inheritance:
-
-   
-
-   
-   
-
-   .. rubric:: Attributes Summary
-
-   .. autosummary::
-   
-      ~UnitConverter.scale
-      ~UnitConverter.want
-      ~UnitConverter.power
-      ~UnitConverter.have
-      ~UnitConverter.offset
-
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Summary
-
-   .. autosummary::
-   
-      ~UnitConverter.convert
-
-   
-   
-
-   
-   
-
-   .. rubric:: Attributes Documentation
-
-   
-   .. autoattribute:: scale
-   .. autoattribute:: want
-   .. autoattribute:: power
-   .. autoattribute:: have
-   .. autoattribute:: offset
-
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Documentation
-
-   
-   .. automethod:: convert
-
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.wcs.Wcsprm.rst b/docs/_generated/astropy.wcs.Wcsprm.rst
deleted file mode 100644
index 7ffd1a9..0000000
--- a/docs/_generated/astropy.wcs.Wcsprm.rst
+++ /dev/null
@@ -1,29 +0,0 @@
-
-.. include:: ../wcs/references.txt
-
-
-Wcsprm
-==================
-
-.. currentmodule:: astropy.wcs
-
-.. autoclass:: Wcsprm
-   :show-inheritance:
-
-   
-
-   
-   
-   
-
-   
-   
-   
-
-   
-   
-   
-
-   
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.wcs.wcs.FITSFixedWarning.rst b/docs/_generated/astropy.wcs.wcs.FITSFixedWarning.rst
deleted file mode 100644
index 34659cf..0000000
--- a/docs/_generated/astropy.wcs.wcs.FITSFixedWarning.rst
+++ /dev/null
@@ -1,10 +0,0 @@
-
-.. include:: ../wcs/references.txt
-
-
-FITSFixedWarning
-================================
-
-.. currentmodule:: astropy.wcs.wcs
-
-.. autoexception:: FITSFixedWarning
\ No newline at end of file
diff --git a/docs/_generated/astropy.wcs.wcs.WCS.rst b/docs/_generated/astropy.wcs.wcs.WCS.rst
deleted file mode 100644
index 167bb27..0000000
--- a/docs/_generated/astropy.wcs.wcs.WCS.rst
+++ /dev/null
@@ -1,90 +0,0 @@
-
-.. include:: ../wcs/references.txt
-
-
-WCS
-===================
-
-.. currentmodule:: astropy.wcs.wcs
-
-.. autoclass:: WCS
-   :show-inheritance:
-
-   
-     None
-   
-
-   
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Summary
-
-   .. autosummary::
-   
-      ~WCS.get_naxis
-      ~WCS.pix2foc
-      ~WCS.calcFootprint
-      ~WCS.wcs_sky2pix
-      ~WCS.printwcs
-      ~WCS.deepcopy
-      ~WCS.sip_foc2pix
-      ~WCS.to_header_string
-      ~WCS.sub
-      ~WCS.footprint_to_file
-      ~WCS.to_fits
-      ~WCS.wcs_pix2world
-      ~WCS.wcs_world2pix
-      ~WCS.p4_pix2foc
-      ~WCS.rotateCD
-      ~WCS.wcs_pix2sky
-      ~WCS.get_axis_types
-      ~WCS.det2im
-      ~WCS.copy
-      ~WCS.all_pix2world
-      ~WCS.to_header
-      ~WCS.sip_pix2foc
-      ~WCS.all_pix2sky
-
-   
-   
-
-   
-   
-   
-
-   
-   
-
-   .. rubric:: Methods Documentation
-
-   
-   .. automethod:: get_naxis
-   .. automethod:: pix2foc
-   .. automethod:: calcFootprint
-   .. automethod:: wcs_sky2pix
-   .. automethod:: printwcs
-   .. automethod:: deepcopy
-   .. automethod:: sip_foc2pix
-   .. automethod:: to_header_string
-   .. automethod:: sub
-   .. automethod:: footprint_to_file
-   .. automethod:: to_fits
-   .. automethod:: wcs_pix2world
-   .. automethod:: wcs_world2pix
-   .. automethod:: p4_pix2foc
-   .. automethod:: rotateCD
-   .. automethod:: wcs_pix2sky
-   .. automethod:: get_axis_types
-   .. automethod:: det2im
-   .. automethod:: copy
-   .. automethod:: all_pix2world
-   .. automethod:: to_header
-   .. automethod:: sip_pix2foc
-   .. automethod:: all_pix2sky
-
-   
-   
\ No newline at end of file
diff --git a/docs/_generated/astropy.wcs.wcs.find_all_wcs.rst b/docs/_generated/astropy.wcs.wcs.find_all_wcs.rst
deleted file mode 100644
index f108742..0000000
--- a/docs/_generated/astropy.wcs.wcs.find_all_wcs.rst
+++ /dev/null
@@ -1,10 +0,0 @@
-
-.. include:: ../wcs/references.txt
-
-
-find_all_wcs
-============================
-
-.. currentmodule:: astropy.wcs.wcs
-
-.. autofunction:: find_all_wcs
\ No newline at end of file
diff --git a/docs/_pkgtemplate.rst b/docs/_pkgtemplate.rst
index 0065696..f9ec534 100644
--- a/docs/_pkgtemplate.rst
+++ b/docs/_pkgtemplate.rst
@@ -41,6 +41,19 @@ A Complex example
 
 Content if needed
 
+Sub-sub topic 1
+^^^^^^^^^^^^^^^^
+
+Content if needed (note the use of ^^^^ at this level).
+
+Sub-sub-sub topic 1
+"""""""""""""""""""
+
+Content if needed (note the use of """"" at this level).
+This is probably the deepest level that is practical.  However,
+just in case, the next levels of detail should use the +, :, and ~
+characters respectively.
+
 
 .. OR IF MORE COMPLICATED,
 
@@ -60,6 +73,9 @@ should be ``docs/packagename/index.rst``, and the other documents should
 be ``docs/packagename/subdoc1.rst``, ``docs/packagename/subdoc2.rst``,
 and ``docs/packagename/subdoc3.rst``.
 
+In the "more complicated" case of using ``subdoc.rst`` files, each of those
+should likewise use the section character header order of ``* = - ^ " + : ~``.
+
 
 See Also (optional)
 ===================
diff --git a/docs/_static/astropy.css b/docs/_static/astropy.css
deleted file mode 100644
index df9258e..0000000
--- a/docs/_static/astropy.css
+++ /dev/null
@@ -1,31 +0,0 @@
-
-/* TODO: I'd like to put some of the fixes in here into stsci_sphinxext proper
- * at which point this file might be able to go away */
-
-
-
-.figure.align-center {
-    clear: none;
-}
-
-/* This is a div for containing multiple figures side-by-side, for use with
- * .. container:: figures */
-div.figures {
-    border: 1px solid #CCCCCC;
-    background-color: #F8F8F8;
-    margin: 1em;
-    text-align: center;
-}
-
-div.figures .figure {
-    clear: none;
-    float: none;
-    display: inline-block;
-    border: none;
-    margin-left: 0.5em;
-    margin-right: 0.5em;
-}
-
-.field-list th {
-    white-space: nowrap;
-}
\ No newline at end of file
diff --git a/docs/_static/astropy_logo.pdf b/docs/_static/astropy_logo.pdf
new file mode 100644
index 0000000..b2ae8d6
Binary files /dev/null and b/docs/_static/astropy_logo.pdf differ
diff --git a/docs/_static/dev.png b/docs/_static/dev.png
new file mode 100644
index 0000000..6433fcf
Binary files /dev/null and b/docs/_static/dev.png differ
diff --git a/docs/_static/mature.png b/docs/_static/mature.png
new file mode 100644
index 0000000..9219cc9
Binary files /dev/null and b/docs/_static/mature.png differ
diff --git a/docs/_static/planned.png b/docs/_static/planned.png
new file mode 100644
index 0000000..fd23a59
Binary files /dev/null and b/docs/_static/planned.png differ
diff --git a/docs/_static/stable.png b/docs/_static/stable.png
new file mode 100644
index 0000000..5c08992
Binary files /dev/null and b/docs/_static/stable.png differ
diff --git a/docs/_templates/autosummary/base.rst b/docs/_templates/autosummary/base.rst
index a58aa35..5f65cb9 100644
--- a/docs/_templates/autosummary/base.rst
+++ b/docs/_templates/autosummary/base.rst
@@ -1,10 +1 @@
-{% if referencefile %}
-.. include:: {{ referencefile }}
-{% endif %}
-
-{{ objname }}
-{{ underline }}
-
-.. currentmodule:: {{ module }}
-
-.. auto{{ objtype }}:: {{ objname }}
+{% extends "autosummary_core/base.rst" %}
diff --git a/docs/_templates/autosummary/class.rst b/docs/_templates/autosummary/class.rst
index e76b633..16e30f8 100644
--- a/docs/_templates/autosummary/class.rst
+++ b/docs/_templates/autosummary/class.rst
@@ -1,65 +1 @@
-{% if referencefile %}
-.. include:: {{ referencefile }}
-{% endif %}
-
-{{ objname }}
-{{ underline }}
-
-.. currentmodule:: {{ module }}
-
-.. autoclass:: {{ objname }}
-   :show-inheritance:
-
-   {% if '__init__' in methods %}
-     {{ methods.remove('__init__') }}
-   {% endif %}
-
-   {% block attributes_summary %}
-   {% if attributes %}
-
-   .. rubric:: Attributes Summary
-
-   .. autosummary::
-   {% for item in attributes %}
-      ~{{ name }}.{{ item }}
-   {%- endfor %}
-
-   {% endif %}
-   {% endblock %}
-
-   {% block methods_summary %}
-   {% if methods %}
-
-   .. rubric:: Methods Summary
-
-   .. autosummary::
-   {% for item in methods %}
-      ~{{ name }}.{{ item }}
-   {%- endfor %}
-
-   {% endif %}
-   {% endblock %}
-
-   {% block attributes_documentation %}
-   {% if attributes %}
-
-   .. rubric:: Attributes Documentation
-
-   {% for item in attributes %}
-   .. autoattribute:: {{ item }}
-   {%- endfor %}
-
-   {% endif %}
-   {% endblock %}
-
-   {% block methods_documentation %}
-   {% if methods %}
-
-   .. rubric:: Methods Documentation
-
-   {% for item in methods %}
-   .. automethod:: {{ item }}
-   {%- endfor %}
-
-   {% endif %}
-   {% endblock %}
+{% extends "autosummary_core/class.rst" %}
diff --git a/docs/_templates/autosummary/module.rst b/docs/_templates/autosummary/module.rst
index 11208a2..ad9d7d7 100644
--- a/docs/_templates/autosummary/module.rst
+++ b/docs/_templates/autosummary/module.rst
@@ -1,41 +1 @@
-{% if referencefile %}
-.. include:: {{ referencefile }}
-{% endif %}
-
-{{ objname }}
-{{ underline }}
-
-.. automodule:: {{ fullname }}
-
-   {% block functions %}
-   {% if functions %}
-   .. rubric:: Functions
-
-   .. autosummary::
-   {% for item in functions %}
-      {{ item }}
-   {%- endfor %}
-   {% endif %}
-   {% endblock %}
-
-   {% block classes %}
-   {% if classes %}
-   .. rubric:: Classes
-
-   .. autosummary::
-   {% for item in classes %}
-      {{ item }}
-   {%- endfor %}
-   {% endif %}
-   {% endblock %}
-
-   {% block exceptions %}
-   {% if exceptions %}
-   .. rubric:: Exceptions
-
-   .. autosummary::
-   {% for item in exceptions %}
-      {{ item }}
-   {%- endfor %}
-   {% endif %}
-   {% endblock %}
+{% extends "autosummary_core/module.rst" %}
diff --git a/docs/_themes/bootstrap-astropy/static/astropylogo.ico b/docs/_themes/bootstrap-astropy/static/astropylogo.ico
deleted file mode 100644
index 652a4ed..0000000
Binary files a/docs/_themes/bootstrap-astropy/static/astropylogo.ico and /dev/null differ
diff --git a/docs/_themes/bootstrap-astropy/static/astropylogo_docs_32.png b/docs/_themes/bootstrap-astropy/static/astropylogo_docs_32.png
deleted file mode 100644
index 9adf556..0000000
Binary files a/docs/_themes/bootstrap-astropy/static/astropylogo_docs_32.png and /dev/null differ
diff --git a/docs/_themes/bootstrap-astropy/static/astropylogo_homelink_20.png b/docs/_themes/bootstrap-astropy/static/astropylogo_homelink_20.png
deleted file mode 100644
index 857cc7e..0000000
Binary files a/docs/_themes/bootstrap-astropy/static/astropylogo_homelink_20.png and /dev/null differ
diff --git a/docs/_themes/bootstrap-astropy/static/bootstrap-astropy.css b/docs/_themes/bootstrap-astropy/static/bootstrap-astropy.css
deleted file mode 100644
index 6a3caf2..0000000
--- a/docs/_themes/bootstrap-astropy/static/bootstrap-astropy.css
+++ /dev/null
@@ -1,501 +0,0 @@
-/*!
- * Bootstrap v1.4.0
- *
- * Copyright 2011 Twitter, Inc
- * Licensed under the Apache License v2.0
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Heavily modified by Kyle Barbary for the AstroPy Project for use with Sphinx.
- */
-
- at import url("basic.css");
-
-body {
-  background-color: #ffffff;
-  margin: 0;
-  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
-  font-size: 13px;
-  font-weight: normal;
-  line-height: 18px;
-  color: #404040;
-}
-
-/* Hyperlinks ----------------------------------------------------------------*/
-
-a {
-  color: #0069d6;
-  text-decoration: none;
-  line-height: inherit;
-  font-weight: inherit;
-}
-
-a:hover {
-  color: #00438a;
-  text-decoration: underline;
-}
-
-/* Typography ----------------------------------------------------------------*/
-
-h1,h2,h3,h4,h5,h6 {
-  color: #404040;
-  margin: 0.7em 0 0 0;
-  line-height: 1.5em;
-}
-h1 {
-  font-size: 24px;
-  margin: 0;
-}
-h2 {
-  font-size: 21px;
-  line-height: 1.2em;
-  margin: 1em 0 0.5em 0;
-  border-bottom: 1px solid #404040;
-}
-h3 {
-  font-size: 18px;
-}
-h4 {
-  font-size: 16px;
-}
-h5 {
-  font-size: 14px;
-}
-h6 {
-  font-size: 13px;
-  text-transform: uppercase;
-}
-
-p {
-  font-size: 13px;
-  font-weight: normal;
-  line-height: 18px;
-  margin-top: 0px;
-  margin-bottom: 9px;
-}
-
-ul, ol {
-  margin-left: 0;
-  padding: 0 0 0 25px;
-}
-ul ul, ul ol, ol ol, ol ul {
-  margin-bottom: 0;
-}
-ul {
-  list-style: disc;
-}
-ol {
-  list-style: decimal;
-}
-li {
-  line-height: 18px;
-  color: #404040;
-}
-ul.unstyled {
-  list-style: none;
-  margin-left: 0;
-}
-dl {
-  margin-bottom: 18px;
-}
-dl dt, dl dd {
-  line-height: 18px;
-}
-dl dd {
-  margin-left: 9px;
-}
-hr {
-  margin: 20px 0 19px;
-  border: 0;
-  border-bottom: 1px solid #eee;
-}
-strong {
-  font-style: inherit;
-  font-weight: bold;
-}
-em {
-  font-style: italic;
-  font-weight: inherit;
-  line-height: inherit;
-}
-.muted {
-  color: #bfbfbf;
-}
-
-address {
-  display: block;
-  line-height: 18px;
-  margin-bottom: 18px;
-}
-code, pre {
-  padding: 0 3px 2px;
-  font-family: Monaco, Andale Mono, Courier New, monospace;
-  font-size: 12px;
-  -webkit-border-radius: 3px;
-  -moz-border-radius: 3px;
-  border-radius: 3px;
-}
-code {
-  background-color: #fee9cc;
-  color: rgba(0, 0, 0, 0.75);
-  padding: 1px 3px;
-}
-pre {
-  background-color: #eee;
-  display: block;
-  padding: 8.5px;
-  margin: 0 0 18px;
-  line-height: 18px;
-  font-size: 12px;
-  border: 1px solid #ccc;
-  border: 1px solid rgba(0, 0, 0, 0.15);
-  -webkit-border-radius: 3px;
-  -moz-border-radius: 3px;
-  border-radius: 3px;
-  white-space: pre;
-  white-space: pre-wrap;
-  word-wrap: break-word;
-}
-
-img {
-  margin: 9px 0;
-}
-
-tt {
-    padding: 0 1px 0 1px;
-    font-size: 0.95em;
-}
-th {
-    background-color: #dddddd;
-}
-
-.viewcode-back {
-    font-family: sans-serif;
-}
-
-div.viewcode-block:target {
-    background-color: #f4debf;
-    border-top: 1px solid #ac9;
-    border-bottom: 1px solid #ac9;
-}
-
-table.docutils {
-    border-spacing: 5px;
-    border-collapse: separate;
-}
-
-/* Topbar --------------------------------------------------------------------*/
-
-div.topbar {
-  height: 40px;
-  position: absolute;
-  top: 0;
-  left: 0;
-  right: 0;
-  z-index: 10000;
-  padding: 0px 10px;
-  background-color: #222;
-  background-color: #222222;
-  background-repeat: repeat-x;
-  background-image: -khtml-gradient(linear, left top, left bottom, from(#333333), to(#222222));
-  background-image: -moz-linear-gradient(top, #333333, #222222);
-  background-image: -ms-linear-gradient(top, #333333, #222222);
-  background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #333333), color-stop(100%, #222222));
-  background-image: -webkit-linear-gradient(top, #333333, #222222);
-  background-image: -o-linear-gradient(top, #333333, #222222);
-  background-image: linear-gradient(top, #333333, #222222);
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#333333', endColorstr='#222222', GradientType=0);
-}
-
-div.topbar .brand {
-  float: left;
-  display: block;
-  width: 130px;
-  height: 32px;
-  padding: 8px 0px 0px 62px;
-  margin-left: -10px;
-  background: transparent url("astropylogo_docs_32.png") no-repeat 10px 4px;
-}
-div.topbar .brand:hover, div.topbar ul li a.homelink:hover {
-  background-color: #333;
-  background-color: rgba(255, 255, 255, 0.05);
-}
-
-div.topbar ul {
-    font-size: 110%;
-    list-style: none;
-    margin: 0;
-    padding: 0 0 0 10px;
-    float: right;
-    color: #bfbfbf;
-    text-align: center;
-    text-decoration: none;
-    height: 100%;
-}
-div.topbar ul li {
-    float: left;
-    display: inline;
-    height: 30px;
-    margin: 5px;
-    padding: 0px;
-}
-
-div.topbar ul li a {
-  color: #bfbfbf;
-  text-decoration: none;
-  padding: 5px;
-  display: block;
-  height: auto;
-  text-align: center;
-  vertical-align: middle;
-  border-radius: 4px;
-}
-
-div.topbar ul li a:hover {
-  color: #ffffff;
-  text-decoration: none;
-}
-
-div.topbar ul li a.homelink {
-  width: 112px;
-  display: block;
-  height: 20px;
-  padding: 5px 0px;
-  background: transparent url("astropylogo_homelink_20.png") no-repeat 10px 5px;
-}
-
-div.topbar form {
-  text-align: left;
-  margin: 0 0 0 5px;
-  position: relative;
-  filter: alpha(opacity=100);
-  -khtml-opacity: 1;
-  -moz-opacity: 1;
-  opacity: 1;
-}
-
-div.topbar input {
-  background-color: #444;
-  background-color: rgba(255, 255, 255, 0.3);
-  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
-  font-size: normal;
-  font-weight: 13px;
-  line-height: 1;
-  padding: 4px 9px;
-  color: #ffffff;
-  color: rgba(255, 255, 255, 0.75);
-  border: 1px solid #111;
-  -webkit-border-radius: 4px;
-  -moz-border-radius: 4px;
-  border-radius: 4px;
-  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0px rgba(255, 255, 255, 0.25);
-  -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0px rgba(255, 255, 255, 0.25);
-  box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0px rgba(255, 255, 255, 0.25);
-  -webkit-transition: none;
-  -moz-transition: none;
-  -ms-transition: none;
-  -o-transition: none;
-  transition: none;
-}
-div.topbar input:-moz-placeholder {
-  color: #e6e6e6;
-}
-div.topbar input::-webkit-input-placeholder {
-  color: #e6e6e6;
-}
-div.topbar input:hover {
-  background-color: #bfbfbf;
-  background-color: rgba(255, 255, 255, 0.5);
-  color: #ffffff;
-}
-div.topbar input:focus, div.topbar input.focused {
-  outline: 0;
-  background-color: #ffffff;
-  color: #404040;
-  text-shadow: 0 1px 0 #ffffff;
-  border: 0;
-  padding: 5px 10px;
-  -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);
-  -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);
-  box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);
-}
-
-
-/* Relation bar (breadcrumbs, prev, next) ------------------------------------*/
-
-div.related {
-    height: 21px;
-    width: auto;
-    margin: 0 10px;
-    position: absolute;
-    top: 42px;
-    clear: both;
-    left: 0;
-    right: 0;
-    z-index: 10000;
-    font-size: 100%;
-    vertical-align: middle;
-    background-color: #fff;
-    border-bottom: 1px solid #bbb;
-}
-div.related ul {
-    padding: 0;
-    margin: 0;
-}
-
-
-/* Footer --------------------------------------------------------------------*/
-
-footer {
-  display: block;
-  margin: 10px 10px 0px;
-  padding: 10px 0 0 0;
-  border-top: 1px solid #bbb;
-}
-.pull-right {
-  float: right;
-  width: 280px;
-  text-align: right;
-}
-
-
-/* Sphinx sidebar ------------------------------------------------------------*/
-
-div.sphinxsidebar {
-    font-size: inherit;
-    border-radius: 3px;
-    background-color: #eee;
-    border: 1px solid #bbb;
-}
-
-div.sphinxsidebarwrapper {
-    padding: 0px 0px 0px 5px;
-}
-
-div.sphinxsidebar h3 {
-    font-family: 'Trebuchet MS', sans-serif;
-    font-size: 1.4em;
-    font-weight: normal;
-    margin: 5px 0px 0px 5px;
-    padding: 0;
-    line-height: 1.6em;
-}
-div.sphinxsidebar h4 {
-    font-family: 'Trebuchet MS', sans-serif;
-    font-size: 1.3em;
-    font-weight: normal;
-    margin: 5px 0 0 0;
-    padding: 0;
-}
-div.sphinxsidebar p {
-}
-div.sphinxsidebar p.topless {
-    margin: 5px 10px 10px 10px;
-}
-div.sphinxsidebar ul {
-    margin: 0px 0px 0px 5px;
-    padding: 0;
-}
-
-div.sphinxsidebar ul ul {
-    margin-left: 15px;
-    list-style-type: disc;
-}
-
-/* If showing the global TOC (toctree),
-   color the current page differently */
-div.sphinxsidebar a.current {
-    color: #404040;
-}
-div.sphinxsidebar a.current:hover {
-    color: #404040;
-}
-
-
-/* document, documentwrapper, body, bodywrapper ----------------------------- */
-
-div.document {
-    margin-top: 72px;
-    margin-left: 10px;
-    margin-right: 10px;
-}
-
-div.documentwrapper {
-    float: left;
-    width: 100%;
-}
-
-div.body {
-    background-color: #ffffff;
-    padding: 0 0 0px 20px;
-}
-
-div.bodywrapper {
-    margin: 0 0 0 230px;
-}
-
-
-/* Header links ------------------------------------------------------------- */
-
-a.headerlink {
-    font-size: 0.8em;
-    padding: 0 4px 0 4px;
-    text-decoration: none;
-}
-
-a.headerlink:hover {
-    background-color: #0069d6;
-    color: white;
-    text-docoration: none;
-}
-
-
-/* Admonitions and warnings ------------------------------------------------- */
-
-/* Shared by admonitions and warnings */
-div.admonition,
-div.warning {
-    padding: 0px;
-    border-radius: 3px;
-    -moz-border-radius: 3px;
-    -webkit-border-radius: 3px;
-}
-div.admonition p,
-div.warning p {
-    margin: 0.5em 1em 0.5em 1em;
-    padding: 0;
-}
-div.admonition pre,
-div.warning pre {
-    margin: 0.4em 1em 0.4em 1em;
-}
-div.admonition p.admonition-title,
-div.warning p.admonition-title {
-    margin: 0;
-    padding: 0.1em 0 0.1em 0.5em;
-    color: white;
-    font-weight: bold;
-    font-size: 1.1em;
-}
-div.admonition ul, div.admonition ol,
-div.warning ul, div.warning ol {
-    margin: 0.1em 0.5em 0.5em 3em;
-    padding: 0;
-}
-
-/* Admonitions only */
-div.admonition {
-    border: 1px solid #609060;
-    background-color: #e9ffe9;
-}
-div.admonition p.admonition-title {
-    background-color: #70A070;
-}
-
-/* Warnings only */
-div.warning {
-    border: 1px solid #900000;
-    background-color: #ffe9e9;
-}
-div.warning p.admonition-title {
-    background-color: #b04040;
-}
diff --git a/docs/_themes/bootstrap-astropy/theme.conf b/docs/_themes/bootstrap-astropy/theme.conf
deleted file mode 100644
index a7a3510..0000000
--- a/docs/_themes/bootstrap-astropy/theme.conf
+++ /dev/null
@@ -1,5 +0,0 @@
-# AstroPy theme based on Twitter Bootstrap CSS
-[theme]
-inherit = basic
-stylesheet = bootstrap-astropy.css
-pygments_style = tango
diff --git a/docs/astropy_banner_96.png b/docs/astropy_banner_96.png
new file mode 100644
index 0000000..3bd9674
Binary files /dev/null and b/docs/astropy_banner_96.png differ
diff --git a/docs/changelog.rst b/docs/changelog.rst
new file mode 100644
index 0000000..f34a16c
--- /dev/null
+++ b/docs/changelog.rst
@@ -0,0 +1,7 @@
+.. _changelog:
+
+**************
+Full Changelog
+**************
+
+.. include:: ../CHANGES.rst
diff --git a/docs/conf.py b/docs/conf.py
index ade680a..72bfc4b 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -1,19 +1,15 @@
 # -*- coding: utf-8 -*-
 # Licensed under a 3-clause BSD style license - see LICENSE.rst
 #
-# Astropy documentation build configuration file, created by
-# sphinx-quickstart on Tue Jul 26 02:59:34 2011.
+# Astropy documentation build configuration file.
 #
 # This file is execfile()d with the current directory set to its containing dir.
 #
-# Note that not all possible configuration values are present in this
-# autogenerated file.
+# Note that not all possible configuration values are present in this file.
 #
-# All configuration values have a default; values that are commented out
-# serve to show the default.
-
-#some of the docs require the autodoc special-members option, in 1.1
-needs_sphinx = '1.1'
+# All configuration values have a default. Some values are defined in
+# the global Astropy configuration which is loaded here before anything else.
+# See astropy.sphinx.conf for which values are set there.
 
 # If extensions (or modules to document with autodoc) are in another directory,
 # add these directories to sys.path here. If the directory is relative to the
@@ -32,18 +28,38 @@ needs_sphinx = '1.1'
 # Load all of the global Astropy configuration
 from astropy.sphinx.conf import *
 
+
+# -- General configuration ----------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+#needs_sphinx = '1.1'
+
 # The intersphinx_mapping in astropy.sphinx.conf refers to astropy for
-# the benefit of affiliated packages who want to refer to objeects in
+# the benefit of affiliated packages who want to refer to objects in
 # the astropy core.  However, we don't want to cyclically reference
 # astropy in its own build so we remove it here.
 del intersphinx_mapping['astropy']
 
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+exclude_patterns.append('_templates')
+exclude_patterns.append('_pkgtemplate.rst')
 
-# -- General configuration -----------------------------------------------------
+# Add any paths that contain templates here, relative to this directory.
+if 'templates_path' not in locals():  # in case parent conf.py defines it
+    templates_path = []
+templates_path.append('_templates')
+
+# This is added to the end of RST files - a good place to put substitutions to
+# be used globally.
+rst_epilog += """
+"""
+
+# -- Project information ------------------------------------------------------
 
-# General information about the project.
 project = u'Astropy'
-copyright = u'2012, The Astropy Collaboration'
+author = u'The Astropy Developers'
+copyright = u'2012, ' + author
 
 # The version info for the project you're documenting, acts as replacement for
 # |version| and |release|, also used in various other places throughout the
@@ -56,95 +72,74 @@ version = astropy.__version__.split('-', 1)[0]
 # The full version, including alpha/beta/rc tags.
 release = astropy.__version__
 
-# If true, '()' will be appended to :func: etc. cross-reference text.
-#add_function_parentheses = True
-
-# If true, the current module name will be prepended to all description
-# unit titles (such as .. function::).
-#add_module_names = True
-
-# If true, sectionauthor and moduleauthor directives will be shown in the
-# output. They are ignored by default.
-#show_authors = False
-
-# The name of the Pygments (syntax highlighting) style to use.
-pygments_style = 'sphinx'
-
-# A list of ignored prefixes for module index sorting.
-#modindex_common_prefix = []
-
-# List of patterns, relative to source directory, that match files and
-# directories to ignore when looking for source files.
-exclude_patterns.append('_templates')
-exclude_patterns.append('_pkgtemplate.rst')
-
-# Add any paths that contain templates here, relative to this directory.
-if 'templates_path' not in locals():  # in case parent conf.py defines it
-    templates_path = []
-templates_path.append('_templates')
-
 
 # -- Options for HTML output ---------------------------------------------------
 
-import sys
-import os
-sys.path.append(os.path.abspath('_themes'))
-html_theme_path = ['_themes']
+# A NOTE ON HTML THEMES
+# The global astropy configuration uses a custom theme, 'bootstrap-astropy',
+# which is installed along with astropy. A different theme can be used or
+# the options for this theme can be modified by overriding some of the
+# variables set in the global configuration. The variables set in the
+# global configuration are listed below, commented out.
+
+# Add any paths that contain custom themes here, relative to this directory.
+# To use a different custom theme, add the directory containing the theme.
+#html_theme_path = []
 
 # The theme to use for HTML and HTML Help pages.  See the documentation for
-# a list of builtin themes.
-html_theme = 'bootstrap-astropy'
-html_sidebars = {'**': ['localtoc.html']}
+# a list of builtin themes. To override the custom theme, set this to the
+# name of a builtin theme or the name of a custom theme in html_theme_path.
+#html_theme = None
 
-# The name for this set of Sphinx documents.  If None, it defaults to
-# "<project> v<release> documentation".
-html_title = '{0} v{1}'.format(project, release)
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
 
 # The name of an image file (within the static path) to use as favicon of the
 # docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
 # pixels large.
-html_favicon = 'astropylogo.ico' # included in the bootstrap-astropy theme
+#html_favicon = ''
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+#html_last_updated_fmt = ''
 
-# Add any paths that contain custom static files (such as style sheets) here,
-# relative to this directory. They are copied after the builtin static files,
-# so a file named "default.css" will overwrite the builtin "default.css".
-html_static_path = ['_static']
+# The name for this set of Sphinx documents.  If None, it defaults to
+# "<project> v<release> documentation".
+html_title = '{0} v{1}'.format(project, release)
 
 # Output file base name for HTML help builder.
-htmlhelp_basename = 'Astropydoc'
+htmlhelp_basename = project + 'doc'
 
-# Format for date last built.
-html_last_updated_fmt = '%d %b %Y'
 
 # -- Options for LaTeX output --------------------------------------------------
 
 # Grouping the document tree into LaTeX files. List of tuples
 # (source start file, target name, title, author, documentclass [howto/manual]).
-latex_documents = [
-  ('index', 'Astropy.tex', u'Astropy Documentation',
-   u'Erik Tollerud, Thomas Robitaille, Perry Greenfield, and the Astropy Collaboration', 'manual'),
-]
+latex_documents = [('index', project + '.tex', project + u' Documentation',
+                    author, 'manual')]
 
-# The name of an image file (relative to this directory) to place at the top of
-# the title page.
-#latex_logo = None
+latex_logo = '_static/astropy_logo.pdf'
 
 
 # -- Options for manual page output --------------------------------------------
 
 # One entry per manual page. List of tuples
 # (source start file, name, description, authors, manual section).
-man_pages = [
-    ('index', 'astropy', u'Astropy Documentation',
-     [u'Erik Tollerud, Thomas Robitaille, Perry Greenfield, and the Astropy Collaboration'], 1)
-]
+man_pages = [('index', project.lower(), project + u' Documentation',
+              [author], 1)]
 
-# This is added to the end of RST files - a good place to put substitutions to
-# be used globally.
-rst_epilog += """
-"""
 
-# -- Options for linkcheck --------------------------------------------
+# -- Options for the edit_on_github extension ----------------------------------------
+
+extensions += ['astropy.sphinx.ext.edit_on_github']
 
-# A timeout value, in seconds, for the linkcheck builder
-linkcheck_timeout = 60
+# Don't import the module as "version" or it will override the
+# "version" configuration parameter
+from astropy import version as versionmod
+edit_on_github_project = "astropy/astropy"
+if versionmod.release:
+    edit_on_github_branch = "v" + versionmod.version
+else:
+    edit_on_github_branch = "master"
+edit_on_github_source_root = ""
+edit_on_github_doc_root = "docs"
diff --git a/docs/configs/index.rst b/docs/configs/index.rst
index dc000a6..3da1b20 100644
--- a/docs/configs/index.rst
+++ b/docs/configs/index.rst
@@ -33,7 +33,7 @@ type of the value that is accepted.  Feel free to edit this as you wish, and
 any of these changes will be reflected when you next start Astropy.  Or, if you
 want to see your changes immediately in your current Astropy session, just do::
 
-    from astropy.config import reload_config()
+    from astropy.config import reload_config
 
     reload_config()
 
@@ -75,7 +75,8 @@ caps. Alternatively, they may be located with the
 
 For example, if there is a part of your configuration file that looks like::
 
-    [config.data]
+    [utils.data]
+
     # URL for astropy remote data site.
     dataurl = http://data.astropy.org/
 
@@ -85,7 +86,7 @@ For example, if there is a part of your configuration file that looks like::
 
 You should be able to modify the values at run-time this way::
 
-    >>> from astropy.config.data import DATAURL, REMOTE_TIMEOUT
+    >>> from astropy.utils.data import DATAURL, REMOTE_TIMEOUT
     >>> DATAURL()
     'http://data.astropy.org/'
     >>> DATAURL.set('http://astropydata.mywebsite.com')
@@ -99,11 +100,11 @@ You should be able to modify the values at run-time this way::
 
 Or alternatively::
 
-    from astropy.config import get_config_items
+    >>> from astropy.config import get_config
 
-    >>> items = get_config_items('astropy.config.data')
-    >>> items['DATAURL'].set('http://astropydata.mywebsite.com')
-    >>> items['REMOTE_TIMEOUT'].set('4.5')
+    >>> items = get_config('astropy.utils.data')
+    >>> items['dataurl'].set('http://astropydata.mywebsite.com')
+    >>> items['remote_timeout'].set('4.5')
 
 Note that this will *not* permanently change these values in the configuration
 files - just for the current session.  To change the configuration files,
@@ -112,11 +113,11 @@ after you've made your changes, you can do::
     >>> DATAURL.save()
     >>> REMOTE_TIMEOUT.save()
 
-Or to save all modifications to configuration items in `astropy.config.data`
+Or to save all modifications to configuration items in `astropy.utils.data`
 (which includes the changes made above), do::
 
     >>> from astropy.config import save_config
-    >>> save_config('astropy.config.data')
+    >>> save_config('astropy.utils.data')
 
 Reloading Configuration
 -----------------------
@@ -125,7 +126,8 @@ Instead of modifying the variables in python, you can also modify the
 configuration files and then reload them.  For example, if you modify the
 configuration file to say::
 
-    [config.data]
+    [utils.data]
+
     # URL for astropy remote data site.
     dataurl = http://myotherdata.mywebsite.com/
 
@@ -240,7 +242,7 @@ Or, if the option needs to be available as a function parameter::
 See Also
 ========
 
-:doc:`/logging` (overview of `astropy.config.logging`)
+:doc:`/logging` (overview of `astropy.logger`)
 
 
 Reference/API
@@ -248,9 +250,3 @@ Reference/API
 
 .. automodapi:: astropy.config
     :no-inheritance-diagram:
-
-
-
-
-
-
diff --git a/docs/coordinates/angles.rst b/docs/coordinates/angles.rst
new file mode 100644
index 0000000..b8b4dbb
--- /dev/null
+++ b/docs/coordinates/angles.rst
@@ -0,0 +1,66 @@
+Working with Angles
+-------------------
+
+The angular components of a coordinate are represented by objects of the
+`~astropy.coordinates.angles.Angle` class. These objects can be instantiated on
+their own anywhere a representation of an angle is needed, and support a variety
+of ways of representing the value of the angle::
+
+    >>> from astropy.coordinates import Angle
+    >>> a = Angle(1, u.radian)
+    >>> a
+    <astropy.coordinates.angles.Angle 57.29578 deg>
+    >>> a.radians
+    1
+    >>> a.degrees
+    57.29577951308232
+    >>> a.hours
+    3.819718634205488
+    >>> a.hms
+    (3.0, 49, 10.987083139757061)
+    >>> a.dms
+    (57.0, 17, 44.80624709636231)
+    >>> a.format()
+    '57d17m44.80625s'
+    >>> a.format(sep=':')
+    '57:17:44.80625'
+    >>> a.format(sep=('deg','m','s'))
+    '57deg17m44.80625s'
+    >>> a.format(u.hour)
+    '3h49m10.98708s'
+    >>> a.format(u.radian)
+    '1.0radian'
+    >>> a.format(u.radian, decimal=True)
+    '1.0'
+
+`~astropy.corodinates.angles.Angle` objects can also have bounds.  These specify
+either a limited range in which the angle is valid (if it's <360 degrees), or
+the limit at which an angle is wrapped back around to 0::
+
+    >>> Angle(90, unit=u.degree, bounds=(0,180))
+    <Angle 90.00000 deg>
+    >>> Angle(-270, unit=u.degree, bounds=(0,180))
+    <Angle 90.00000 deg>
+    >>> Angle(181, unit=u.degree, bounds=(0,180))
+    BoundsError: The angle given falls outside of the specified bounds.
+    >>> Angle(361, unit=u.degree, bounds=(0,360))
+    <Angle 1.00000 deg>
+
+Angles will also behave correctly for appropriate arithmetic operations::
+
+    >>> a = Angle(1, u.radian)
+    >>> a + a
+    <Angle 114.59156 deg>
+    >>> a - a
+    <Angle 0.00000 deg>
+    >>> a == a
+    True
+    >>> a == (a + a)
+    False
+
+Angle objects can also be used for creating coordinate objects::
+
+    >>> ICRSCoordinates(Angle(1, u.radian), Angle(2, u.radian))
+    <ICRSCoordinates RA=57.29578 deg, Dec=114.59156 deg>
+    >>> ICRSCoordinates(RA(1, u.radian), Dec(2, u.radian))
+    <ICRSCoordinates RA=57.29578 deg, Dec=114.59156 deg>
\ No newline at end of file
diff --git a/docs/coordinates/creating.rst b/docs/coordinates/creating.rst
new file mode 100644
index 0000000..5cc2fcc
--- /dev/null
+++ b/docs/coordinates/creating.rst
@@ -0,0 +1,62 @@
+Creating Coordinate Objects
+---------------------------
+
+Creating new coordinate objects is of course crucial to using
+`~astropy.coordinates`.  The typical way to create a new coordinate object
+is to directly initialize your preferred coordinate system using standard
+python class creation, using the name of the class representing that
+system and a number for the two angles.  For example::
+
+    >>> from astropy.coordinates import ICRSCoordinates, FK4Coordinates, GalacticCoordinates
+    >>> ICRSCoordinates(187.70592, 12.39112, unit=(u.degree, u.degree))
+    <ICRSCoordinates RA=187.70592 deg, Dec=12.39112 deg>
+    >>> FK4Coordinates(187.07317, 12.66715, unit=(u.degree, u.degree))
+    <FK4Coordinates RA=187.07317 deg, Dec=12.66715 deg>
+    >>> GalacticCoordinates(-76.22237, 74.49108, unit=(u.degree, u.degree))
+    <GalacticCoordinates l=-76.22237 deg, b=74.49108 deg>
+
+Note that if you do not provide units explicitly, this will fail::
+
+    >>> ICRSCoordinates(23, 1)
+    UnitsError: No unit was specified in Angle initializer; the unit parameter should be an object from the  astropy.units module (e.g. 'from astropy import units as u', then use 'u.degree').
+
+While the above example uses python numerical types, you can also provide strings to create coordinates.
+If the `unit` parameter is ``(None, None)`` (the default), strings will be interpreted using the `Angle` 
+class' parsing scheme, and has a guiding principal of being able to interpret any *unambiguous* string 
+specifying an angle. For the exact rules for how each string is parsed, see the 
+`~astropy.coordinates.angles.Angle` documentation.  Some examples::
+
+    >>> ICRSCoordinates("3h36m29.7888s -41d08m15.162342s", unit=(None, None))
+    <ICRSCoordinates RA=54.12412 deg, Dec=-41.13755 deg>
+    >>> ICRSCoordinates("3h36m29.7888s -41d08m15.162342s")
+    <ICRSCoordinates RA=54.12412 deg, Dec=-41.13755 deg>
+    >>> ICRSCoordinates("14.12412 hours", "-41:08:15.162342 degrees")
+    <ICRSCoordinates RA=211.86180 deg, Dec=-41.13755 deg>
+    >>> ICRSCoordinates("14.12412 -41:08:15.162342")
+    UnitsError: Could not infer Angle units from provided string 14.12412
+
+You can also directly specify the units for both to resolve ambiguities in parsing the angle strings::
+
+    >>> ICRSCoordinates("14.12412 -41:08:15.162342", unit=(u.hour, u.degree))
+    <ICRSCoordinates RA=211.86180 deg, Dec=-41.13755 deg>
+    >>> ICRSCoordinates("54:7:26.832 -41:08:15.162342", unit=(u.degree, u.degree))
+    <ICRSCoordinates RA=54.12412 deg, Dec=-41.13755 deg>
+    >>> ICRSCoordinates('3 4 5 +6 7 8', unit=(u.hour, u.degree))
+    <ICRSCoordinates RA=46.02083 deg, Dec=6.11889 deg>
+    >>> ICRSCoordinates('3h4m5s +6d7m8s', unit=(u.hour, u.degree))
+    <ICRSCoordinates RA=46.02083 deg, Dec=6.11889 deg>
+
+This will also give you an error if you give a string with units that conflict with your desired units::
+
+    >>> ICRSCoordinates('3d4m5s +6h7m8s', unit=(u.hour, u.degree))
+    ValueError: parse_hours: Invalid input string, can't parse to HMS. (3d4m5s)
+
+One final way to create coordinates is to copy them from an already existing coordinate::
+
+    >>> i1 = ICRSCoordinates(187.70592, 12.39112, unit=(u.degree, u.degree))
+    >>> i2 = ICRSCoordinates(i1)
+    >>> i1
+    <ICRSCoordinates RA=187.70592 deg, Dec=12.39112 deg>
+    >>> i2
+    <ICRSCoordinates RA=187.70592 deg, Dec=12.39112 deg>
+    
\ No newline at end of file
diff --git a/docs/coordinates/designing.rst b/docs/coordinates/designing.rst
new file mode 100644
index 0000000..067cdcc
--- /dev/null
+++ b/docs/coordinates/designing.rst
@@ -0,0 +1,21 @@
+Designing Coordinate Systems
+----------------------------
+
+New coordinate systems can easily be added by users by simply subclassing the
+`~astropy.coordinates.coordsystems.SphericalCoordinatesBase` object.
+Detailed instructions for subclassing are in the docstrings for that class.  If
+defining a latitude/longitude style of coordinate system, the
+`_initialize_latlong` method and `_init_docstring_param_templ` attribute are
+helpful for automated processing of the inputs.
+
+To define transformations to and from this coordinate, the easiest method is to
+define a function that accepts an object in one coordinate system and returns
+the other.  Decorate this function with
+`~astropy.coordinates.transformations.transform_function` function decorator,
+supplying the information to determine which coordinates the function transforms
+to or from.  This will register the transformation, allowing any other
+coordinate object to use this converter.  You can also use the
+`~astropy.coordinates.transformations.static_transform_matrix` and
+`~astropy.coordinates.transformations.dynamic_transform_matrix` decorators to
+specify the transformation in terms of 3 x 3 cartesian coordinate transformation
+matrices (typically rotations).
\ No newline at end of file
diff --git a/docs/coordinates/distances.rst b/docs/coordinates/distances.rst
new file mode 100644
index 0000000..d614213
--- /dev/null
+++ b/docs/coordinates/distances.rst
@@ -0,0 +1,79 @@
+Distances and Cartesian Representations
+---------------------------------------
+
+Coordinates can also have line-of-sight distances.  If these are provided, a
+coordinate object becomes a full-fledged point in three-dimensional space.  If
+not (i.e., the `distance` attribute of the coordinate object is `None`), the
+point is interpreted as lying on the (dimensionless) unit sphere.
+
+The `~astropy.coordinates.distances.Distance` class is provided to represent a
+line-of-sight distance for a coordinate.  It must include a length unit to be
+valid.::
+
+    >>> from astropy.coordinates import Distance
+    >>> d = Distance(770)
+    UnitsError: A unit must be provided for distance.
+    >>> d = Distance(770, u.kpc)
+    >>> c = ICRSCoordinates('00h42m44.3s +41d16m9s', distance=d)
+    >>> c
+    <ICRSCoordinates RA=10.68458 deg, Dec=41.26917 deg, Distance=7.7e+02 kpc>
+
+If a distance is available, the coordinate can be converted into cartesian
+coordinates using the `x`/`y`/`z` attributes::
+
+    >>> c.x
+    568.7128882165681
+    >>> c.y
+    107.3009359688103
+    >>> c.z
+    507.8899092486349
+
+.. note::
+
+    The location of the origin is different for different coordinate
+    systems, but for common celestial coordinate systems it is often
+    the Earth center (or for precision work, the Earth/Moon barycenter).
+
+The cartesian coordinates can also be accessed via the
+`~astropy.coordinates.distances.CartesianCoordinates` object, which has
+additional capabilities like arithmetic operations::
+
+    >>> cp = c.cartesian
+    >>> cp
+    <CartesianPoints (568.712888217, 107.300935969, 507.889909249) kpc>
+    >>> cp.x
+    568.7128882165681
+    >>> cp.y
+    107.3009359688103
+    >>> cp.z
+    507.8899092486349
+    >>> cp.unit
+    Unit("kpc")
+    >>> cp + cp
+    <CartesianPoints (1137.42577643, 214.601871938, 1015.7798185) kpc>
+    >>> cp - cp
+    <CartesianPoints (0.0, 0.0, 0.0) kpc>
+
+This cartesian representation can also be used to create a new coordinate
+object, either directly or through a `CartesianPoints` object::
+
+    >>> ICRSCoordinates(x=568.7129, y=107.3009, z=507.8899, unit=u.kpc)
+    <ICRSCoordinates RA=10.68458 deg, Dec=41.26917 deg, Distance=7.7e+02 kpc>
+    >>> cp = CartesianPoints(x=568.7129, y=107.3009, z=507.8899, unit=u.kpc)
+    >>> ICRSCoordinates(cp)
+    <ICRSCoordinates RA=10.68458 deg, Dec=41.26917 deg, Distance=7.7e+02 kpc>
+
+Finally, two coordinates with distances can be used to derive a real-space
+distance (i.e., non-projected separation)::
+
+    >>> c1 = ICRSCoordinates('5h23m34.5s -69d45m22s', distance=Distance(49, u.kpc))
+    >>> c2 = ICRSCoordinates('0h52m44.8s -72d49m43s', distance=Distance(61, u.kpc))
+    >>> sep3d = c1.separation_3d(c2)
+    >>> sep3d
+    <Distance 23.05685 kpc>
+    >>> sep3d.kpc
+    23.05684814695706
+    >>> sep3d.Mpc
+    0.02305684814695706
+    >>> sep3d.au
+    4755816315.663559
\ No newline at end of file
diff --git a/docs/coordinates/index.rst b/docs/coordinates/index.rst
new file mode 100644
index 0000000..671f275
--- /dev/null
+++ b/docs/coordinates/index.rst
@@ -0,0 +1,121 @@
+*******************************************************
+Astronomical Coordinate Systems (`astropy.coordinates`)
+*******************************************************
+
+Introduction
+============
+
+The `~astropy.coordinates` package provides classes for representing celestial
+coordinates, as well as tools for converting between standard systems in a
+uniform way.
+
+.. note::
+    The current `~astropy.coordinates` framework only accepts scalar
+    coordinates, i.e. one coordinate per object.  In the next release it will
+    be expanded to accept arrays of coordinates.
+
+.. warning::
+    `~astropy.coordinates` is currently a work-in-progress, and thus it is
+    possible there will be significant API changes in later versions of
+    Astropy.
+
+
+Getting Started
+===============
+
+Coordinate objects are instantiated with a flexible and natural approach that
+supports both numeric angle values and (limited) string parsing::
+
+    >>> from astropy import coordinates as coord
+    >>> from astropy import units as u
+    >>> coord.ICRSCoordinates(ra=10.68458, dec=41.26917, unit=(u.degree, u.degree))
+    <ICRSCoordinates RA=10.68458 deg, Dec=41.26917 deg>
+    >>> coord.ICRSCoordinates('00h42m44.3s +41d16m9s')
+    <ICRSCoordinates RA=10.68458 deg, Dec=41.26917 deg>
+
+The individual components of a coordinate are `~astropy.coordinates.angles.Angle`
+objects, and their values are accessed using special attributes::
+
+    >>> c = coord.ICRSCoordinates(ra=10.68458, dec=41.26917, unit=(u.degree, u.degree))
+    >>> c.ra
+    <RA 10.68458 deg>
+    >>> c.ra.hours
+    0.7123053333333333
+    >>> c.ra.hms
+    (0.0, 42, 44.2992000000001)
+    >>> c.dec
+    <Dec 41.26917 deg>
+    >>> c.dec.radians
+    0.7202828960652683
+
+To convert to some other coordinate system, the easiest method is to use
+attribute-style access with short names for the built-in systems, but explicit
+transformations via the `transform_to` method are also available::
+
+    >>> c.galactic
+    <GalacticCoordinates l=121.17422 deg, b=-21.57283 deg>
+    >>> c.transform_to(coord.GalacticCoordinates)
+    <GalacticCoordinates l=121.17422 deg, b=-21.57283 deg>
+
+Distances from the origin (which is system-dependent, but often the Earth
+center) can also be assigned to a coordinate. This specifies a unique point
+in 3D space, which also allows conversion to cartesian coordinates::
+
+    >>> c = coord.ICRSCoordinates(ra=10.68458, dec=41.26917, unit=(u.degree, u.degree), distance=coord.Distance(770, u.kpc))
+    >>> c.x
+    568.7128654235232
+    >>> c.y
+    107.3008974042025
+    >>> c.z
+    507.88994291875713
+
+
+Using `astropy.coordinates`
+===========================
+
+More details of using `astropy.coordinates` are provided in the following sections:
+
+.. toctree::
+   :maxdepth: 2
+
+   angles
+   creating
+   separations
+   distances
+   transforming
+   designing
+
+
+In addition, another resource for the capabilities of this package is the
+`astropy.coordinates.tests.test_api` testing file. It showcases most of the
+major capabilities of the package, and hence is a useful supplement to this
+document.  You can see it by either looking at it directly if you downloaded a
+copy of the astropy source code, or typing the following in an IPython session::
+
+    In [1]: from astropy.coordinates.tests import test_api
+    In [2]: test_api??
+
+
+See Also
+========
+
+Some references particularly useful in understanding subtleties of the
+coordinate systems implemented here include:
+
+* `Standards Of Fundamental Astronomy <http://www.iausofa.org/>`_
+    The definitive implementation of IAU-defined algorithms.  The "SOFA Tools
+    for Earth Attitude" document is particularly valuable for understanding
+    the latest IAU standards in detail.
+* `USNO Circular 179 <http://www.usno.navy.mil/USNO/astronomical-applications/publications/circ-179>`_
+    A useful guide to the IAU 2000/2003 work surrounding ICRS/IERS/CIRS and
+    related problems in precision coordinate system work.
+* Meeus, J. "Astronomical Algorithms"
+    A valuable text describing details of a wide range of coordinate-related
+    problems and concepts.
+
+
+
+Reference/API
+=============
+
+.. automodapi:: astropy.coordinates
diff --git a/docs/coordinates/separations.rst b/docs/coordinates/separations.rst
new file mode 100644
index 0000000..0e84580
--- /dev/null
+++ b/docs/coordinates/separations.rst
@@ -0,0 +1,24 @@
+Separations
+-----------
+
+The on-sky separation is easily computed with the `separation` method, which
+computes the great-circle distance (*not* the small-angle approximation)::
+
+    >>> c1 = ICRSCoordinates('5h23m34.5s -69d45m22s')
+    >>> c2 = ICRSCoordinates('0h52m44.8s -72d49m43s')
+    >>> sep = c1.separation(c2)
+    >>> sep
+    <AngularSeparation 20.74612 deg>
+
+The `~astropy.coordinates.angles.AngularSeparation` object is a subclass of
+`~astropy.coordinates.angles.Angle`, so it can be accessed in the same ways,
+along with a few additions::
+
+    >>> sep.radians
+    0.36208807374669766
+    >>> sep.hours
+    1.383074562513832
+    >>> sep.arcmins
+    1244.7671062624488
+    >>> sep.arcsecs
+    74686.02637574692
\ No newline at end of file
diff --git a/docs/coordinates/transforming.rst b/docs/coordinates/transforming.rst
new file mode 100644
index 0000000..ea8efc2
--- /dev/null
+++ b/docs/coordinates/transforming.rst
@@ -0,0 +1,66 @@
+Transforming Between Systems
+----------------------------
+
+`astropy.coordinates` supports a rich system for transforming coordinates from
+one system to another.  The key concept is that a registry of all the
+transformations is used to determine which coordinates can convert to others.
+When you ask for a transformation, the registry (or "transformation graph") is
+searched for the shortest path from your starting coordinate to your target, and
+it applies all of the transformations in that path in series.   This allows only
+the simplest transformations to be defined, and the package will automatically
+determine how to combine those transformations to get from one system to
+another.
+
+As described above, there are two ways of transforming coordinates.  Coordinates
+that have an alias (created with
+`~astropy.coordinates.transformations.coordinate_alias`) can be converted by
+simply using attribute style access to any other coordinate system::
+
+    >>> gc = GalacticCoordinates(l=0, b=45, unit=(u.degree, u.degree))
+    >>> gc.fk5
+    <FK5Coordinates RA=229.27250 deg, Dec=-1.12842 deg>
+    >>> ic = ICRSCoordinates(ra=0, dec=45, unit=(u.degree, u.degree)))
+    >>> ic.fk5
+    <FK5Coordinates RA=0.00001 deg, Dec=45.00000 deg>
+
+While this appears to be simple attribute-style access, it is actually just
+syntactic sugar for the `transform_to` method::
+
+    >>> from astropy.coordinates import FK5Coordinates
+    >>> gc.transform_to(FK5Coordinates)
+    <FK5Coordinates RA=229.27250 deg, Dec=-1.12842 deg>
+    >>> ic.transform_to(FK5Coordinates)
+    <FK5Coordinates RA=0.00001 deg, Dec=45.00000 deg>
+
+The full list of supported coordinate systems and transformations is in the
+`astropy.coordinates` API documentation below.
+
+Additionally, some coordinate systems support precessing the coordinate to
+produce a new coordinate in the same system but at a different equinox.  Note 
+that these systems have a default equinox they start with if you don't specify 
+one::
+
+    >>> fk5c = FK5Coordinates('02h31m49.09s +89d15m50.8s')
+    >>> fk5c.equinox
+    <Time object: scale='utc' format='jyear_str' vals=J2000.000>
+    >>> fk5c
+    <FK5Coordinates RA=37.95454 deg, Dec=89.26411 deg>
+    >>> fk5c.precess_to(Time(2100, format='jyear', scale='utc'))
+    <FK5Coordinates RA=88.32396 deg, Dec=89.54057 deg>
+
+You can also specify the equinox when you create a coordinate using an 
+`astropy.time.Time` object::
+
+    >>> from astropy.time import Time
+    >>> fk5c = FK5Coordinates('02h31m49.09s +89d15m50.8s', equinox=Time('J1970', scale='utc'))
+    <FK5Coordinates RA=37.95454 deg, Dec=89.26411 deg>
+    >>> fk5c.precess_to(Time(2000, format='jyear', scale='utc'))
+    <FK5Coordinates RA=48.02317 deg, Dec=89.38672 deg>
+
+Coordinate systems do not necessarily all support an equinox nor precession, as it is a
+meaningless action for coordinate systems that do not depend on a particular equinox.
+
+Furthermore, coordinates typically have an `obstime` attribute, intended to record the
+time of the observation.  Some systems (especially FK4) require this information due
+to being non-inertial frames (i.e., they rotate over time due to motions of the
+defining stars).
\ No newline at end of file
diff --git a/docs/cosmology/index.rst b/docs/cosmology/index.rst
index ff4e98d..b7b1c8a 100644
--- a/docs/cosmology/index.rst
+++ b/docs/cosmology/index.rst
@@ -8,126 +8,173 @@ Introduction
 The `astropy.cosmology` subpackage contains classes for representing
 cosmologies, and utility functions for calculating commonly used
 quantities that depend on a cosmological model. This includes
-distances, ages and lookback times corresponding to a measured redshift
-or the transverse separation corresponding to a measured angular
-separation.
+distances, ages and lookback times corresponding to a measured
+redshift or the transverse separation corresponding to a measured
+angular separation.
 
-An important concept in `astropy.cosmology` is the "current" cosmology.
-This is the specific cosmological model and choice of parameters that are
-currently active in `astropy`. Other parts of Astropy that need to
-assume acosmology will use this cosmology in their calculations to
-maintain consistency. See `Getting Started`_ for a description of how to
-change the current cosmology that is in use.
 
+Getting Started
+===============
 
+There are many functions available to calculate cosmological quantities.
+They generally take a redshift as input. For example, the two cases
+below give you the value of the hubble constant at z=0 (i.e., `H0`), and
+the number of transverse proper kpc corresponding to an arcminute at z=3:
+
+  >>> from astropy import cosmology
+  >>> cosmology.H(0)
+  70.4
+  >>> cosmology.kpc_proper_per_arcmin(3)
+  472.8071851564037
 
+All the functions available are listed in the `Reference/API`_
+section. These will use the "current" cosmology to calculate the
+values (see `The Current Cosmology`_ section below for more
+details). If you haven't set this explicitly, they will use the 7-year
+WMAP cosmological parameters and print a warning message.
 
-Getting Started
-===============
+There are also several standard cosmologies already defined. These are
+objects with methods and attributes that calculate cosmological
+values. For example, the comoving distance in Mpc to redshift 4 using
+the 5-year WMAP parameters:
 
-To do a calculation defined in one of the convenience functions, you can
-simply call the function with the relevant redshift::
-
-    >>> from astropy import cosmology
-    >>> cosmology.distmod(0.5)
-    WARNING: No default cosmology has been specified, using 7-year WMAP. [astropy.cosmology.core]
-    42.270203330485998
-
-Note that calling these functions without specifying a cosmology will
-cause a warning to appear and the default (WMAP7) will be adopted. You
-can get rid of this by specifying a default cosmology or setting the
-current cosmology directly. The default current cosmology can be changed
-by changing the "default_cosmology" option in the ``[cosmology.core]``
-section of the configuration file to your preferred cosmology (see
-:ref:`astropy_config`). Alternatively, you can use the
-`~astropy.cosmology.core.set_current` function to specify a cosmology
-for use in the current python session.
-
-More functionality is available as methods or attributes of the current
-cosmology object. Use `~astropy.cosmology.core.get_current` to get this
-object::
-
-    >>> from astropy.cosmology import get_current
-    >>> cosmo = get_current()
-    >>> cosmo.h
-    0.704
-    >>> cosmo.lookback_time(1)
-    7.788414051773566
-    >>> cosmo.critical_density(0)
-    9.3100031320204701e-30
-    >>> cosmo.critical_density(0.5)
-    1.5324265155305696e-29
+  >>> from astropy.cosmology import WMAP5
+  >>> WMAP5.comoving_distance(4)
+  7329.328120760829
 
+A full list of the pre-defined cosmologies is given by
+`cosmology.parameters.available`.
 
+An important point is that the cosmological parameters of each
+instance are immutable -- that is, if you want to change, say,
+`Om`, you need to make a new instance of the class.
 
 Using `cosmology`
 =================
 
 Most of the functionality is enabled by the
-`~astropy.cosmology.core.FLRWCosmology` object. This represents a
+`~astropy.cosmology.core.FLRW` object. This represents a
 homogenous and isotropic cosmology (a cosmology characterized by the
 Friedmann-Lemaitre-Robertson-Walker metric, named after the people who
-solved Einstein's field equation for this special case).
+solved Einstein's field equation for this special case).  However,
+you can't work with this class directly, as you must specify a
+dark energy model by using one of its subclasses instead,
+such as `~astropy.cosmology.core.FlatLambdaCDM`.
 
-While `astropy.cosmology` includes a variety of standard cosmologies
-with the parameters already defined (see below), you can create a new
-`FLRWCosmology` object with arguments giving the hubble parameter, omega
-matter and omega lambda (all at z=0):
+You can create a new `~astropy.cosmology.core.FlatLambdaCDM` object with
+arguments giving the hubble parameter and omega matter (both at z=0):
 
-  >>> from astropy.cosmology import FLRWCosmology
-  >>> cosmo = FLRWCosmology(H0=70, Om=0.3, Ol=0.7)
+  >>> from astropy.cosmology import FlatLambdaCDM
+  >>> cosmo = FlatLambdaCDM(H0=70, Om0=0.3)
   >>> cosmo
-  FLRWCosmology(H0=70, Om=0.3, Ol=0.7, Ok=0)
+  LambdaCDM(H0=70, Om0=0.3, Ode0=0.7)
+
+A number of additional dark energy models are provided (described below).
+Note that photons and neutrinos are included in these models, so
+Om0 + Ode0 is not quite one.
 
-The methods of this object calculate commonly used quantities with
-your cosmology. For example, the comoving distance in Mpc at redshift
-4 is given by:
+The pre-defined cosmologies described in the `Getting Started`_
+section are instances of `~astropy.cosmology.core.FlatLambdaCDM`, and have
+the same methods. So we can find the luminosity distance in Mpc to
+redshift 4 by:
 
-  >>> cosmo.comoving_distance(4)
-  7170.366414463296
+  >>> cosmo.luminosity_distance(4)
+  35842.35374316948
 
-The age of the universe at z = 0 in Gyr:
+or the age of the universe at z = 0 in Gyr:
 
   >>> cosmo.age(0)
-  13.46698402784007
+  13.461701807287566
 
-See the `FLRWCosmology` object docstring for all the methods and
-variables available.  There are several standard cosmologies already
-defined:
+They also accept arrays of redshifts:
 
-  >>> from cosmology import WMAP7   # WMAP 7-year cosmology
+  >>> cosmo.age([0.5, 1, 1.5])
+  array([ 8.42128059,  5.74698062,  4.1964541 ])
+
+See the `~astropy.cosmology.core.FLRW` and
+`~astropy.cosmology.core.FlatLambdaCDM` object docstring for all the
+methods and attributes available. In addition to flat Universes,
+non-flat varieties are supported such as
+`~astropy.cosmology.core.LambdaCDM`.  There are also a variety of
+standard cosmologies with the parameters already defined:
+
+  >>> from astropy.cosmology import WMAP7   # WMAP 7-year cosmology
   >>> WMAP7.critical_density(0)       # critical density at z = 0 in g/cm^3
   9.31000313202047e-30
 
-  >>> from cosmology import WMAP5   # WMAP 5-year
+  >>> from astropy.cosmology import WMAP5   # WMAP 5-year
   >>> WMAP5.H(3)                    # Hubble parameter at z = 3 in km/s/Mpc
-  301.54148311633674
+  301.71804314602889
+
+You can see how the density parameters evolve with redshift as well
+
+  >>> from astropy.cosmology import WMAP7   # WMAP 7-year cosmology
+  >>> WMAP7.Om([0,1.0,2.0]), WMAP7.Ode([0.,1.0,2.0])
+  (array([ 0.272     ,  0.74898525,  0.9090524 ]),
+   array([ 0.72791572,  0.25055062,  0.09010261]))
 
+Note that these don't quite add up to one even though WMAP7 assumes a
+flat Universe because photons and neutrinos are included.
 
-There are also several convenience functions that calculate quantities
-without needing to create a Cosmology object.
+In addition to the `~astropy.cosmology.core.LambdaCDM` object, there
+are convenience functions that calculate some of these quantities
+without needing to explicitly give a cosmology - but there are more
+methods available if you work directly with the cosmology object.
 
   >>> from astropy import cosmology
   >>> cosmology.kpc_proper_per_arcmin(3)
-  472.91882815884907
+  472.8071851564037
   >>> cosmology.arcsec_per_kpc_proper(3)
-  0.12687166682195736
+  0.12690162477152736
+
+These functions will perform calculations using the "current"
+cosmology. This is a specific cosmology that is currently active in
+`astropy` and it's described further in the following section. They
+can also be explicitly given a cosmology using the `cosmo` keyword
+argument. A full list of convenience functions is included below, in
+the `Reference/API`_ section.
+
+
+The Current Cosmology
+=======================
+
+Sometimes it's useful for Astropy functions to assume a default
+cosmology so that the desired cosmology doesn't have to be specified
+every time the function is called -- the convenience functions
+described in the previous section are one example. For these cases
+it's possible to specify a "current" cosmology.
+
+You can set the current cosmology to a pre-defined value by using the
+"default_cosmology" option in the ``[cosmology.core]`` section of the
+configuration file (see :ref:`astropy_config`). Alternatively, you can
+use the `~astropy.cosmology.core.set_current` function to set a
+cosmology for the current Python session.
+
+If you haven't set a current cosmology using one of the methods
+described above, then the cosmology module will use the 7-year WMAP
+parameters and print a warning message letting you know this. For
+example, if you call a convenience function without setting the
+current cosmology or using the `cosmo=` keyword you see the following
+message:
 
-These use the current cosmology, unless overridden by a `cosmo=` keyword
-argument. A full list of convenience functions is included below, in the
-`Reference/API`_ section.
+  >>> from astropy import cosmology
+  >>> cosmology.lookback_time(1)          # lookback time in Gyr at z=1
+  WARNING: No default cosmology has been specified, using 7-year WMAP.
+  [astropy.cosmology.core]
+  7.787767002228743
 
 .. note::
-    In general it's better to use an explicit cosmology in actual
-    science code, when possible (e.g., ``WMAP7.H(0)`` instead of
-    ``cosmology.H(0)``). The motivation for this is that when you go back
-    to use the code at a later date, the default cosmology may have
-    changed. Use of the convenience functions should generally be
+
+    In general it's better to use an explicit cosmology (for example
+    ``WMAP7.H(0)`` instead of ``cosmology.H(0)``). The motivation for
+    this is that when you go back to use the code at a later date or
+    share your scripts with someone else, the default cosmology may
+    have changed. Use of the convenience functions should generally be
     reserved for interactive work or cases where the flexibility of
     quickly changing between different cosmologies is for some reason
-    useful. Alternatively, doing ``cosmology.set_current(WMAP7)`` at the
-    top of your code will ensure that these are always consistent.
-
+    useful. Alternatively, putting (for example)
+    ``cosmology.set_current(WMAP7)`` at the top of your code will
+    ensure that the right cosmology is always used.
 
 Using `cosmology` inside Astropy
 --------------------------------
@@ -138,26 +185,98 @@ through the `~astropy.cosmology.core.get_current` function. It is also
 recommended that you provide an override option something like the
 following::
 
-    def myfunc(...,cosmo=None):
-        from astropy.cosmology import get_current
+    def myfunc(..., cosmo=None):
+	from astropy.cosmology import get_current
 
-        if cosmo is None:
-            cosmo = get_current()
+	if cosmo is None:
+	    cosmo = get_current()
 
-        ... your code here ...
+	... your code here ...
 
 This ensures that all code consistently uses the current cosmology
 unless explicitly overridden.
 
+Specifying a dark energy model
+==============================
+
+In addition to the standard `~astropy.cosmology.core.FlatLambdaCDM` model
+described above, a number of additional dark energy models are
+provided.  `~astropy.cosmology.core.FlatLambdaCDM` 
+and `~astropy.cosmology.core.FlatLambdaCDM` assume that dark
+energy is a cosmological constant, and should be the most commonly
+used case.  `~astropy.cosmology.core.wCDM` assumes a constant dark
+energy equation of state parameterized by :math:`w_0`. Two forms of a
+variable dark energy equation of state are provided: the simple first
+order linear expansion :math:`w(z) = w_0 + w_z z` by
+`~astropy.cosmology.core.w0wzCDM`, as well as the common CPL form by
+`~astropy.cosmology.core.w0waCDM`: :math:`w(z) = w_0 + w_a (1 - a) =
+w_0 + w_a z / (1 + z)` and its generalization to include a pivot
+redshift by `~astropy.cosmology.core.wpwaCDM`: :math:`w(z) = w_p + w_a
+(a_p - a)`.
+
+Users can specify their own equation of state by sub-classing
+`~astropy.cosmology.core.FLRW`.  See the provided subclasses for
+examples.
+
+Relativistic Species
+====================
+The cosmology classes include the contribution to the energy density
+from both photons and massless neutrinos.  The two parameters
+controlling the proporties of these species are Tcmb0 (the temperature
+of the CMB at z=0) and Neff, the effective number of neutrino species.
+Both have standard default values (2.725 and 3.04, respectively; the
+reason that Neff is not 3 has to do with a small bump in the neutrino
+energy spectrum due to electron-positron annihilation).
+
+  >>> from astropy.cosmology import WMAP7   # WMAP 7-year cosmology
+  >>> z = [0,1.0,2.0]
+  >>> WMAP7.Ogamma(z), WMAP7.Onu(z)
+  (array([  4.98569503e-05,   2.74574414e-04]),
+   array([  3.44204408e-05,   1.89561782e-04]),
+   array([  8.42773911e-05,   4.64136197e-04]))
+
+If you want to exclude photons and neutrinos from your calculations,
+simply set the CMB Temperature to 0:
+
+  >>> from astropy.cosmology import FlatLambdaCDM
+  >>> cos = FlatLambdaCDM(70.4, 0.272, Tcmb0 = 0.0)
+  >>> cos.Ogamma0, cos.Onu0
+  (0.0, 0.0)
+
+Neutrinos can be removed (while leaving photons) by setting Neff=0:
+
+  >>> from astropy.cosmology import FlatLambdaCDM
+  >>> cos = FlatLambdaCDM(70.4, 0.272, Neff=0)
+  >>> cos.Ogamma([0,1,2]),cos.Onu([0,1,2])
+  (array([  4.98569503e-05,   2.74623219e-04,   5.00051845e-04]),
+   array([ 0.,  0.,  0.]))
+
+While these examples used `~astropy.cosmology.core.FlatLambdaCDM`,
+the above examples also apply for all of the other cosmology classes.
 
 See Also
 ========
 
-* Hogg, "Distance measures in cosmology", http://arxiv.org/abs/astroph/9905116
-* NASA's Legacy Archive for Microwave Background Data Analysis, http://lambda.gsfc.nasa.gov/
+* Hogg, "Distance measures in cosmology",
+  http://arxiv.org/abs/astroph/9905116
+* Linder, "Exploring the Expansion History of the Universe", http://arxiv.org/abs/astro-ph/0208512
+* NASA's Legacy Archive for Microwave Background Data Analysis,
+  http://lambda.gsfc.nasa.gov/
+
+Range of validity and reliability
+=================================
+
+The code in this sub-package is tested against several widely-used
+online cosmology calculators, and has been used to perform
+calculations in refereed papers. You can check the range of redshifts
+over which the code is regularly tested in the module
+`astropy.cosmology.tests.test_cosmology`. Note that the energy density
+due to radiation is assumed to be negligible, which is valid for
+redshifts less than about 10. If you find any bugs, please let us know
+by `opening an issue at the github repository
+<https://github.com/astropy/astropy/issues>`_!
 
 Reference/API
 =============
 
 .. automodapi:: astropy.cosmology
-
diff --git a/docs/creditsandlicense.rst b/docs/creditsandlicense.rst
index 072ba21..23217bc 100644
--- a/docs/creditsandlicense.rst
+++ b/docs/creditsandlicense.rst
@@ -13,9 +13,11 @@ package as of the most recent release:
  * Paul Barrett
  * Erik Bray
  * Neil Crighton
+ * Alex Conley
  * Matt Davis
  * Christoph Deil
  * Michael Droettboom
+ * Henry Ferguson
  * Adam Ginsburg
  * Perry Greenfield
  * Frédéric Grollier
@@ -25,8 +27,12 @@ package as of the most recent release:
  * Roban Kramer
  * Prasanth Nair
  * Thomas Robitaille
+ * Adrian Price-Whelan
+ * Leo Singer
  * James Taylor
  * Erik Tollerud
+ * James Turner
+ * Julien Woillez
 
 
 License
diff --git a/docs/development/building_packaging.rst b/docs/development/building_packaging.rst
index 98d8bdc..a15f1b7 100644
--- a/docs/development/building_packaging.rst
+++ b/docs/development/building_packaging.rst
@@ -29,8 +29,8 @@ process:
 
     It is recommended that all such data be in a directory named "data" inside
     the package within which it is supposed to be used, and package data should
-    be accessed via the `astropy.config.data.get_data_filename` and
-    `astropy.config.data.get_data_fileobj` functions.
+    be accessed via the `astropy.utils.data.get_data_filename` and
+    `astropy.utils.data.get_data_fileobj` functions.
 
 * :func:`get_extensions`
     This provides information for building C or Cython extensions. If defined,
@@ -46,6 +46,33 @@ process:
     this function should call `astropy.setup_helpers.add_legacy_alias`
     to generate a legacy module and then return what it returns.
 
+* :func:`get_build_options`
+    This function allows a package to add extra build options.  It
+    should return a list of tuples, where each element has:
+
+    - *name*: The name of the option as it would appear on the
+      commandline or in the `setup.cfg` file.
+
+    - *doc*: A short doc string for the option, displayed by
+      `setup.py build --help`.
+
+    - *is_bool* (optional): When `True`, the option is a boolean
+      option and doesn't have an associated value.
+
+    Once an option has been added, its value can be looked up using
+    `astropy.setup_helpers.get_distutils_build_option`.
+
+* :func:`get_external_libraries`
+    This function declares that the package uses libraries that are
+    included in the astropy distribution that may also be distributed
+    elsewhere on the users system.  It should return a list of library
+    names.  For each library, a new build option is created,
+    `--use-system-X` which allows the user to request to use the
+    system's copy of the library.  The package would typically call
+    `astropy.setup_helpers.use_system_library` from its
+    `get_extensions` function to determine if the package should use
+    the system library or the included one.
+
 The `astropy.setup_helpers` modules includes a :func:`update_package_files`
 function which automatically searches the given source path for
 ``setup_package.py`` modules and calls each of the above functions, if they
@@ -126,9 +153,9 @@ that will not be available in the source tree.  In this case,
 Release
 -------
 
-The release procedure for the first version of Astropy will involve a
-combination of an automated release script and some manual steps.  Future
-versions will automate more of the process, if not all.
+The current release procedure for Astropy involves a combination of an
+automated release script and some manual steps.  Future versions will automate
+more of the process, if not all.
 
 One of the main steps in performing a release is to create a tag in the git
 repository representing the exact state of the repository that represents the
@@ -176,9 +203,9 @@ both your public and private key::
     $ gpg --export --armor > public.key
     $ gpg --export-secret-key --armor > private.key
 
-Back up these files to a trusted location--preferably a write-one physical
-medium that can be stored safely somewhere.  I also back up my keys to a
-trusted online encrypted storage, though some might not find that secure
+Back up these files to a trusted location--preferably a write-once physical
+medium that can be stored safely somewhere.  One may also back up their keys to
+a trusted online encrypted storage, though some might not find that secure
 enough--it's up to you and what you're comfortable with.
 
 Add your public key to a keyserver
@@ -295,9 +322,11 @@ procedure is that ensures a consistent release process each time.
     Cython .pyx files, and the .c files are necessary for the source
     distribution.
 
- 6. Install zest.releaser into the virtualenv::
+ 6. Install zest.releaser into the virtualenv; use ``--upgrade --force`` to
+    ensure that the latest version is installed in the virtualenv (if you're
+    running a csh variant make sure to run ``rehash`` afterwards too)::
 
-    $ pip install zest.releaser
+    $ pip install zest.releaser --upgrade --force
 
  7. Ensure that all changes to the code have been committed, then start the
     release by running::
@@ -315,9 +344,9 @@ procedure is that ensures a consistent release process each time.
     Enter 'Y' to confirm and run the command.
 
  10. When asked "Check out the tag (for tweaks or pypi/distutils server
-     upload)" enter 'N': We will be uploading the source to GitHub instead of
-     PyPI, so for now registering on PyPI and uploading the source will be
-     performed manually.
+     upload)" enter 'N': zest.releaser does not offer enough control yet over
+     how the register and upload are performed so we will do this manually
+     until the release scripts have been improved.
 
  11. You will be asked to enter a new development version.  Normally the next
      logical version will be selected--press enter to accept the default, or
@@ -344,19 +373,25 @@ procedure is that ensures a consistent release process each time.
      $ python setup.py sdist
 
      Copy the produced ``.tar.gz`` somewhere and verify that you can unpack it,
-     build it, and get all the tests to pass. If all looks good, upload the
-     file to the GitHub "downloads" section.
+     build it, and get all the tests to pass.  It would be best to create a new
+     virtualenv in which to do this.
 
  16. Register the release on PyPI with::
 
      $ python setup.py register
 
- 17. Update the website to reflect the fact there is now a stable release.
+ 17. Upload the source distribution to PyPI; this is preceded by re-running
+     the sdist command, which is necessary for the upload command to know
+     which distribution to upload::
+
+     $ python setup.py sdist upload
+
+ 18. Update the website to reflect the fact there is now a stable release.
 
- 18. Update Readthedocs so that it builds docs for the corresponding github tag,
+ 19. Update Readthedocs so that it builds docs for the corresponding github tag,
      and set the default page to the new release.
 
- 19. Create a bug fix branch.  If the version just was released was a "X.Y.0"
+ 20. Create a bug fix branch.  If the version just was released was a "X.Y.0"
      version ("0.1" or "0.2" for example--the final ".0" is typically ommitted)
      it is good to create a bug fix branch as well.  Starting from the tagged
      changset, just checkout a new branch and push it to the remote server.
@@ -378,12 +413,43 @@ procedure is that ensures a consistent release process each time.
      the master branch.  Only changesets that fix bugs without making
      significant API changes should be merged to the bug fix branches.
 
+ 21. Create a bug fix label on GitHub; this should have the same name as the
+     just created bug fix branch.  This label should be applied to all issues
+     that should be backported to the bug fix branch.
+
 
 .. _signed tags: http://git-scm.com/book/en/Git-Basics-Tagging#Signed-Tags
 .. _zest.releaser: http://pypi.python.org/pypi/zest.releaser
 .. _virtualenv: http://pypi.python.org/pypi/virtualenv
 .. _cython: http://www.cython.org/
 
+Creating a MacOS X Installer on a DMG
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The ``bdist_dmg`` command can be used to create a ``.dmg`` disk image for
+MacOS X with a ``.pkg`` installer. In order to do this, you will need to
+ensure that you have the following dependencies installed:
+
+* `Numpy <http://www.numpy.org>`_
+* `Sphinx <http://sphinx.pocoo.org>`_
+* `bdist_mpkg <http://pypi.python.org/pypi/bdist_mpkg/>`_
+
+To create a ``.dmg`` file, run::
+
+    python setup.py bdist_dmg
+
+Note that for the actual release version, you should do this with the Python
+distribution from `python.org <http://python.org>`_ (not e.g. MacPorts, EPD,
+etc.). The best way to ensure maximum compatibility is to make sure that
+Python and Numpy are installed into ``/Library/Frameworks/Python.framework``
+using the latest stable ``.dmg`` installers available for those packages. In
+addition, the ``.dmg`` should be build on a MacOS 10.6 system, to ensure
+compatibility with 10.6, 10.7, and 10.8.
+
+Before distributing, you should test out an installation of Python, Numpy, and
+Astropy from scratch using the ``.dmg`` installers, preferably on a clean
+virtual machine.
+
 Future directions
 -----------------
 
diff --git a/docs/development/docguide.rst b/docs/development/docguide.rst
index 86f5922..29c9d01 100644
--- a/docs/development/docguide.rst
+++ b/docs/development/docguide.rst
@@ -1,6 +1,6 @@
-=======================
-Documentation Guideline
-=======================
+========================
+Documentation Guidelines
+========================
 
 Building the Documentation from source
 --------------------------------------
@@ -578,3 +578,38 @@ on how to use Sphinx_ to build the manual.
 .. _SciPy: http://www.scipy.org
 .. _numpy-discussion list: http://www.scipy.org/Mailing_Lists
 .. _Sphinx: http://sphinx.pocoo.org
+
+
+Sphinx Documentation Themes
+---------------------------
+
+A custom Sphinx HTML theme is included in the astropy source tree and
+installed along with astropy. This allows the theme to be used by
+default from both astropy and affiliated packages. This is done by
+setting the theme in the global astropy sphinx configuration, which is
+imported in the sphinx configuration of both `astropy` and affiliated
+packages.
+
+Using a different theme for `astropy` or affiliated packages
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+A different theme can be used by overriding a few sphinx
+configuration variables set in the global configuration.
+
+* To use a different theme, set `html_theme` to the name of a desired
+  builtin Sphinx theme or a custom theme in
+  `package-name/docs/conf.py` (where `package-name` is "astropy" or
+  the name of the affiliated package).
+
+* To use a custom theme, additionally: place the theme in
+  `package-name/docs/_themes` and add `'_themes'` to the
+  `html_theme_path` variable. See the Sphinx_ documentation for more
+  details on theming.
+
+Adding more custom themes to astropy
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Additional custom themes can be included in the astropy source tree by
+placing them in the directory `astropy/astropy/sphinx/themes`, and
+editing `astropy/astropy/sphinx/setup_package.py` to include the theme
+(so that it is installed).
diff --git a/docs/development/testguide.rst b/docs/development/testguide.rst
index 64a719c..13a70c2 100644
--- a/docs/development/testguide.rst
+++ b/docs/development/testguide.rst
@@ -239,8 +239,8 @@ Working with data files
 -----------------------
 
 Tests that need to make use of a data file should use the
-`~astropy.config.data.get_data_fileobj` or
-`~astropy.config.data.get_data_filename` functions.  These functions search
+`~astropy.utils.data.get_data_fileobj` or
+`~astropy.utils.data.get_data_filename` functions.  These functions search
 locally first, and then on the astropy data server or an arbitrary URL, and
 return a file-like object or a local filename, respectively.  They automatically
 cache the data locally if remote data is obtained, and from then on the local
@@ -248,7 +248,7 @@ copy will be used transparently.
 
 They also support the use of an MD5 hash to get a specific version of a data
 file.  This hash can be obtained prior to submitting a file to the astropy
-data server by using the `~astropy.config.data.compute_hash` function on a
+data server by using the `~astropy.utils.data.compute_hash` function on a
 local copy of the file.
 
 Tests that may retrieve remote data should be marked with the ``@remote_data``
diff --git a/docs/development/workflow/development_workflow.rst b/docs/development/workflow/development_workflow.rst
index c5e5ff6..c1155ab 100644
--- a/docs/development/workflow/development_workflow.rst
+++ b/docs/development/workflow/development_workflow.rst
@@ -1,4 +1,4 @@
-.. _advanced-workflow:
+.. _development-workflow:
 
 =======================
 Workflow for Developers
@@ -79,7 +79,7 @@ In detail
    This tells you that you are currently on the ``master`` branch, and
    that you also have a ``remote`` connection to ``origin/master``.
    What remote repository is ``remote/origin``? Try ``git remote -v`` to
-   see the URLs for the remote.  They will point to your github fork.
+   see the URLs for the remote.  They will point to your GitHub fork.
 
    Now you want to connect to the Astropy repository, so you can
    merge in changes from the trunk::
@@ -150,7 +150,7 @@ details.
 Updating the mirror of trunk
 ============================
 
-From time to time you should fetch the upstream (trunk) changes from github::
+From time to time you should fetch the upstream (trunk) changes from GitHub::
 
    git fetch upstream
 
@@ -184,7 +184,7 @@ or ``buxfix-for-issue-42``.
     git branch my-new-feature upstream/master
     git checkout my-new-feature
 
-Generally, you will want to keep your feature branches on your public github_
+Generally, you will want to keep your feature branches on your public GitHub_
 fork. To do this, you `git push`_ this new branch up to your
 github repo. Generally (if you followed the instructions in these pages, and
 by default), git will have a link to your GitHub repo, called ``origin``. You
@@ -254,7 +254,7 @@ In more detail
    signals that you're going to type a message on the command line. The `git
    commit`_ manual page might also be useful.
 
-#. To push the changes up to your forked repo on github, do a ``git
+#. To push the changes up to your forked repo on GitHub, do a ``git
    push`` (see `git push`_).
 
 Asking for your changes to be reviewed or merged
@@ -285,7 +285,7 @@ When you are ready to ask for someone to review your code and consider a merge:
 Some other things you might want to do
 ======================================
 
-Delete a branch on github
+Delete a branch on GitHub
 -------------------------
 
 ::
@@ -297,7 +297,7 @@ Delete a branch on github
    # delete branch locally
    git branch -D my-unwanted-branch
 
-   # delete branch on github
+   # delete branch on GitHub
    git push origin :my-unwanted-branch
 
 (Note the colon ``:`` before ``test-branch``.  See also:
@@ -308,7 +308,7 @@ Several people sharing a single repository
 
 If you want to work on some stuff with other people, where you are all
 committing into the same repository, or even the same branch, then just
-share it via github.
+share it via GitHub.
 
 First fork Astropy into your account, as from :ref:`forking`.
 
@@ -345,7 +345,7 @@ To see a linear list of commits for this branch::
 
    git log
 
-You can also look at the `network graph visualizer`_ for your github
+You can also look at the `network graph visualizer`_ for your GitHub
 repo.
 
 Finally the :ref:`fancy-log` ``lg`` alias will give you a reasonable
@@ -417,6 +417,19 @@ page for some instructions at the end of the "Description" section. There is
 some related help on merging in the git user manual - see `resolving a
 merge`_.
 
+If your feature branch is already on GitHub and you rebase, you will have to force
+push the branch; a normal push would give an error. If the branch you rebased is
+called ``cool-feature`` and your GitHub fork is available as the remote called ``origin``,
+you use this command to force-push::
+
+   git push -f origin cool-feature
+
+Note that this will overwrite the branch on GitHub, i.e. this is one of the few ways
+you can actually lose commits with git.
+Also note that it is never allowed to force push to the main astropy repo (typically
+called ``upstream``), because this would re-write commit history and thus cause problems
+for all others.
+
 .. _recovering-from-mess-up:
 
 Recovering from mess-ups
diff --git a/docs/getting_started.rst b/docs/getting_started.rst
new file mode 100644
index 0000000..bd2326c
--- /dev/null
+++ b/docs/getting_started.rst
@@ -0,0 +1,52 @@
+****************************
+Getting Started with Astropy
+****************************
+
+Importing Astropy
+=================
+
+In order to encourage consistency amongst users in importing and using Astropy
+functionality, we have put together the following guidelines.
+
+Since most of the functionality in Astropy resides in sub-packages, importing
+astropy as::
+
+    >>> import astropy
+
+is not very useful. Instead, it is best to import the desired sub-pacakge
+with the syntax::
+
+    >>> from astropy import subpackage
+
+For example, to access the FITS-related functionality, you can import
+`astropy.io.fits` with::
+
+    >>> from astropy.io import fits
+    >>> hdulist = fits.open('data.fits')
+
+In specific cases, we have recommended shortcuts in the documentation for
+specific sub-packages, for example::
+
+    >>> from astropy import units as u
+    >>> from astropy import coordinates as coord
+    >>> coord.ICRSCoordinates(ra=10.68458, dec=41.26917, unit=(u.degree, u.degree)))
+    <ICRSCoordinates RA=10.68458 deg, Dec=41.26917 deg>
+
+Finally, in some cases, most of the required functionality is contained in a
+single class (or a few classes). In those cases, the class can be directly
+imported::
+
+    >>> from astropy.cosmology import WMAP7
+    >>> from astropy.table import Table
+    >>> from astropy.wcs import WCS
+
+Note that for clarity, and to avoid any issues, we recommend to **never**
+import any Astropy functionality using ``*``, for example::
+
+    >>> from astropy.io.fits import *  # NOT recommended
+
+Some components of Astropy started off as standalone packages (e.g. PyFITS, PyWCS),
+so in cases where Astropy needs to be used as a drop-in replacement, the following
+syntax is also acceptable::
+
+    >>> from astropy.io import fits as pyfits
diff --git a/docs/index.rst b/docs/index.rst
index 99f24fe..6de3bfe 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -7,7 +7,7 @@
 Welcome to Astropy's Documentation!
 ###################################
 
-.. image:: logo/astropy_banner_96.png
+.. image:: astropy_banner_96.png
 
 Astropy is a community-driven package intended to contain much of the
 core functionality and some common tools needed for performing astronomy
@@ -19,24 +19,58 @@ and astrophysics with Python.
 User Documentation
 ******************
 
+:ref:`whatsnew-0.2`
+===================
+
 .. toctree::
    :maxdepth: 1
 
    overview
    install
+   getting_started
    nddata/index
+   units/index
+   time/index
+   coordinates/index
    table/index
    cosmology/index
    io/fits/index
    io/ascii/index
-   io/vo/index
+   io/votable/index
+   io/misc
    wcs/index
-   tools/index
+   stats/index
    utils/index
    configs/index
    logging
+   stability
+   whatsnew/index
    creditsandlicense
 
+***********************
+Getting help
+***********************
+
+If you want to get help or discuss issues with other Astropy users, you can
+sign up for the `astropy mailing list <http://mail.scipy.org/mailman/listinfo/astropy>`_.
+Alternatively, the `astropy-dev
+<http://groups.google.com/group/astropy-dev>`_ list is where you should go to
+discuss more technical aspects of Astropy with the developers.
+
+***********************
+Reporting issues
+***********************
+
+If you have come across something that you believe is a bug, please open a
+ticket in the Astropy `issue tracker
+<http://github.com/astropy/astropy/issues>`_, and we will look into it
+promptly.
+
+Please try to include an example that demonstrates the issue and will allow the
+developers to reproduce and fix the problem.  If you are seeing a crash
+then frequently it will help to include the full Python stack trace as well as
+information about your operating system (e.g. MacOSX version or Linux version).
+
 .. _developer-docs:
 
 ***********************
@@ -58,6 +92,7 @@ testing guidelines.
    development/building_packaging
    development/scripts
    development/sphinxext
+   changelog
 
 ******************
 Indices and Tables
diff --git a/docs/install.rst b/docs/install.rst
index 70a90df..98bcde8 100644
--- a/docs/install.rst
+++ b/docs/install.rst
@@ -11,10 +11,19 @@ Astropy has the following strict requirements:
 
 - `Numpy <http://www.numpy.org/>`_ 1.4 or later
 
-Astropy also depends on other projects for optional features.
+Astropy also depends on other packages for optional features:
+
+- `h5py <http://alfven.org/wp/hdf5-for-python/>`_: To read/write
+  :class:`~astropy.table.table.Table` objects from/to HDF5 files
+
+- `scipy <http://www.scipy.org/>`_: To power a variety of features (currently
+  mainly cosmology-related functionality)
 
 - `xmllint <http://www.xmlsoft.org/>`_: To validate VOTABLE XML files.
 
+However, note that these only need to be installed if those particular features
+are needed. Astropy will import even if these dependencies are not installed.
+
 .. TODO: Link to the planned dependency checker/installer tool.
 
 Installing Astropy
@@ -32,6 +41,19 @@ Binary installers
 
 No binary installers are available at this time.
 
+Testing Astropy
+---------------
+
+The easiest way to test your installed version of astropy is running
+correctly is to use the :func:`astropy.test` function::
+
+    import astropy
+    astropy.test()
+
+The tests should run and print out any failures, which you can report at
+the `Astropy issue tracker <http://github.com/astropy/astropy/issues>`_.
+
+
 Building from source
 ====================
 
@@ -46,8 +68,20 @@ The `instructions for building Numpy from source
 <http://docs.scipy.org/doc/numpy/user/install.html>`_ are also a good
 resource for setting up your environment to build Python packages.
 
-Obtaining the source
---------------------
+You will also need `Cython <http://cython.org/>`_ installed to build
+from source, unless you are installing a numbered release. (The releases
+packages have the necessary C files packaged with them, and hence do not
+require Cython.)
+
+.. note:: If you are using MacOS X, the easiest way to install a compiler
+          suite is to install the MacOS X developer tools (XCode) As of XCode
+          4.3, the command-line compilers are no longer installed by default:
+          you will need to open the XCode application, go to **Preferences**,
+          then **Downloads**, and then under **Components**, click on the
+          Install button to the right of **Command Line Tools**.
+
+Obtaining the source packages
+-----------------------------
 
 Source packages
 ^^^^^^^^^^^^^^^
@@ -70,7 +104,7 @@ using this command::
    necessary to install Astropy.
 
 Building and Installing
-^^^^^^^^^^^^^^^^^^^^^^^
+-----------------------
 
 Astropy uses the Python `distutils framework
 <http://docs.python.org/install/index.html>`_ for building and
@@ -84,10 +118,84 @@ To install Astropy (from the root of the source tree)::
 
     python setup.py install
 
+External C libraries
+^^^^^^^^^^^^^^^^^^^^
+
+The Astropy source ships with the C source code of a number of
+libraries.  By default, these internal copies are used to build
+Astropy.  However, if you wish to use the system-wide installation of
+one of those libraries, you can pass one or more of the
+`--use-system-X` flags to the `setup.py build` command.
+
+For example, to build Astropy using the system `libexpat`, use::
+
+    python setup.py build --use-system-expat
+
+To build using all of the system libraries, use::
+
+    python setup.py build --use-system-libraries
+
+To see which system libraries Astropy knows how to build against, use::
+
+    python setup.py build --help
+
+As with all distutils commandline options, they may also be provided
+in a `setup.cfg` in the same directory as `setup.py`.  For example, to
+use the system `libexpat`, add the following to the `setup.cfg` file::
+
+    [build]
+    use_system_expat=1
+
+Compatibility packages
+^^^^^^^^^^^^^^^^^^^^^^
+
+.. warning:: This feature is still experimental, and you may run into
+             unexpected issues with other packages, so we strongly
+             recommend simply updating your code to use Astropy if
+             possible, rather than rely on these compatibility packages.
+
+Optionally, it is possible to install 'compatibility' packages that
+emulate the behavior of previous packages that have now been
+incorporated into Astropy. These are:
+
+* `PyFITS <http://www.stsci.edu/institute/software_hardware/pyfits/>`_
+* `vo <https://trac.assembla.com/astrolib/>`_
+* `PyWCS <https://trac.assembla.com/astrolib/>`_
+
+If you build Astropy with::
+
+    python setup.py build --enable-legacy
+    python setup.py install
+
+or simply::
+
+    python setup.py install --enable-legacy
+
+then you will be able to import these modules from your scripts as if
+the original packages had been installed. Using::
+
+    import pyfits
+    import vo
+    import pywcs
+
+will then be equivalent to::
+
+    from astropy.io import fits as pyfits
+    from astropy.io import vo
+    from astropy import wcs as pywcs
+
+In order to install the compatibility packages none of the
+original packages should be present.
+
+.. note:: If you are interested in testing out existing code with Astropy
+          without modifying the import statements, but don't want to
+          uninstall existing packages, you can use `virtualenv
+          <http://www.virtualenv.org/>`_ to set up a clean environment.
+
 .. _builddocs:
 
 Building documentation
-^^^^^^^^^^^^^^^^^^^^^^
+----------------------
 
 .. note::
     Building the documentation is in general not necessary unless you
@@ -119,11 +227,11 @@ Alternatively, you can do::
 And the documentation will be generated in the same location, but using the
 *installed* version of Astropy.
 
-Testing Astropy
-^^^^^^^^^^^^^^^
+Testing your Astropy build
+--------------------------
 
-The easiest way to test that your Astropy built correctly is to run
-(from the root of the source tree)::
+The easiest way to test that your Astropy built correctly (without
+installing astropy) is to run this from the root of the source tree::
 
     python setup.py test
 
diff --git a/docs/io/ascii/extension_classes.rst b/docs/io/ascii/extension_classes.rst
index 902634e..d674a44 100644
--- a/docs/io/ascii/extension_classes.rst
+++ b/docs/io/ascii/extension_classes.rst
@@ -23,5 +23,6 @@ well-defined but idiosyncratic formats.
 * :class:`~astropy.io.ascii.latex.Latex`: LaTeX table with datavalue in the `tabular` environment
 * :class:`~astropy.io.ascii.basic.NoHeader`: basic table with no header where columns are auto-named
 * :class:`~astropy.io.ascii.basic.Rdb`: tab-separated values with an extra line after the column definition line
+* :class:`~astropy.io.ascii.sextractor.SExtractor`: `SExtractor format table <http://www.astromatic.net/software/sextractor>`_
 * :class:`~astropy.io.ascii.basic.Tab`: tab-separated values
 
diff --git a/docs/io/ascii/index.rst b/docs/io/ascii/index.rst
index 41abc6b..a114b68 100644
--- a/docs/io/ascii/index.rst
+++ b/docs/io/ascii/index.rst
@@ -22,12 +22,19 @@ The following formats are supported:
 * :class:`~astropy.io.ascii.latex.Latex`: LaTeX table with datavalue in the `tabular` environment
 * :class:`~astropy.io.ascii.basic.NoHeader`: basic table with no header where columns are auto-named
 * :class:`~astropy.io.ascii.basic.Rdb`: tab-separated values with an extra line after the column definition line
+* :class:`~astropy.io.ascii.sextractor.SExtractor`: `SExtractor format table <http://www.astromatic.net/software/sextractor>`_
 * :class:`~astropy.io.ascii.basic.Tab`: tab-separated values
 
 The :mod:`astropy.io.ascii` package is built on a modular and extensible class
 structure with independent :ref:`base_class_elements` so that new formats can
 be easily accomodated.
 
+.. note::
+
+    It is also possible to use the functionality from
+    :mod:`astropy.io.ascii` through a higher-level interface in the
+    :mod:`astropy.table` package. See :ref:`table_io` for more details.
+
 Getting Started
 ===============
 
diff --git a/docs/io/ascii/read.rst b/docs/io/ascii/read.rst
index 3af58b7..b6b3ab1 100644
--- a/docs/io/ascii/read.rst
+++ b/docs/io/ascii/read.rst
@@ -209,7 +209,7 @@ look like a number.
 
 The order of guessing is shown by this Python code::
   
-  for Reader in (Rdb, Tab, Cds, Daophot, Ipac):
+  for Reader in (Rdb, Tab, Cds, Daophot, SExtractor, Ipac):
       read(Reader=Reader)
   for Reader in (CommentedHeader, Basic, NoHeader):
       for delimiter in ("|", ",", " ", "\\s"):
diff --git a/docs/io/fits/appendix/history.rst b/docs/io/fits/appendix/history.rst
index a254868..a278a97 100644
--- a/docs/io/fits/appendix/history.rst
+++ b/docs/io/fits/appendix/history.rst
@@ -12,8 +12,139 @@ Astropy.
    :local:
 
 
-3.1.0 (unreleased)
---------------------
+3.2 (unreleased)
+----------------
+
+- Rewrote CFITSIO-based backend for handling tile compression of FITS files.
+  It now uses a standard CFITSIO instead of heavily modified pieces of CFITSIO
+  as before.  PyFITS ships with its own copy of CFITSIO v3.30, but system
+  packagers may choose instead to strip this out in favor of a
+  system-installed version of CFITSIO.  Earlier versions may work, but nothing
+  earlier than 3.28 has been tested yet. (#169)
+
+
+3.1.1 (unreleased)
+------------------
+
+This is a bug fix release for the 3.1.x series.
+
+Bug Fixes
+^^^^^^^^^
+
+- Improved handling of scaled images and pseudo-unsigned integer images in
+  compressed image HDUs.  They now work more transparently like normal image
+  HDUs with support for the ``do_not_scale_image_data`` and ``uint`` options,
+  as well as ``scale_back`` and ``save_backup``.  The ``.scale()`` method
+  works better too. (#88)
+
+- Permits non-string values for the EXTNAME keyword when reading in a file,
+  rather than throwing an exception due to the malformatting.  Added
+  verification for the format of the EXTNAME keyword when writing. (#96)
+
+- Added support for EXTNAME and EXTVER in PRIMARY HDUs.  That is, if EXTNAME
+  is specified in the header, it will also be reflected in the ``.name``
+  attribute and in ``pyfits.info()``.  These keywords used to be verboten in
+  PRIMARY HDUs, but the latest version of the FITS standard allows them.
+  (#151)
+
+- HCOMPRESS can again be used to compress data cubes (and higher-dimensional
+  arrays) so long as the tile size is effectively 2-dimensional. In fact,
+  PyFITS will automatically use compatible tile sizes even if they're not
+  explicitly specified. (#171)
+
+- Added support for the optional ``endcard`` parameter in the
+  ``Header.fromtextfile()`` and ``Header.totextfile()`` methods.  Although
+  ``endcard=False`` was a reasonable default assumption, there are still text
+  dumps of FITS headers that include the END card, so this should have been
+  more flexible. (#176)
+
+- Fixed a crash when running fitsdiff on two empty (that is, zero row) tables.
+  (#178)
+
+- Fixed an issue where opening files containing random groups HDUs in update
+  mode could cause an unnecessary rewrite of the file even if none of the
+  data is modified. (#179)
+
+- Fixed a bug that could caused a deadlock in the filesystem on OSX if PyFITS
+  is used with Numpy 1.7 in some cases. (#180)
+
+- Fixed a crash when generating diff reports from diffs using the
+  ``ignore_comments`` options. (#181)
+
+- Fixed some bugs with WCS Paper IV record-valued keyword cards:
+
+  - Cards that looked kind of like RVKCs but were not intended to be were
+    over-permissively treated as such--commentary keywords like COMMENT and
+    HISTORY were particularly affected. (#183)
+
+  - Looking up a card in a header by its standard FITS keyword only should
+    always return the raw value of that card.  That way cards containing
+    values that happen to valid RVKCs but were not intended to be will still
+    be treated like normal cards. (#184)
+
+  - Looking up a RVKC in a header with only part of the field-specifier (for
+    example "DP1.AXIS" instead of "DP1.AXIS.1") was implicitly treated as a
+    wildcard lookup. (#184)
+
+- Fixed a crash when diffing two FITS files where at least one contains a
+  compressed image HDU which was not recognized as an image instead of a
+  table. (#187)
+
+- Fixed bugs in the backwards compatibility layer for the ``CardList.index``
+  and ``CardList.count`` methods. (#190)
+
+- Improved ``__repr__`` and text file representation of cards with long values
+  that are split into CONTINUE cards. (#193)
+
+- Fixed a crash when trying to assign a long (> 72 character) value to blank
+  ('') keywords. This also changed how blank keywords are represented--there
+  are still exactly 8 spaces before any commentary content can begin; this
+  *may* affect the exact display of header cards that assumed there could be
+  fewer spaces in a blank keyword card before the content begins. However, the
+  current approach is more in line with the requirements of the FITS standard.
+  (#194)
+
+
+3.0.10 (unreleased)
+-------------------
+
+This is a bug fix release for the 3.0.x series.
+
+Bug Fixes
+^^^^^^^^^
+
+- Improved handling of scaled images and pseudo-unsigned integer images in
+  compressed image HDUs.  They now work more transparently like normal image
+  HDUs with support for the ``do_not_scale_image_data`` and ``uint`` options,
+  as well as ``scale_back`` and ``save_backup``.  The ``.scale()`` method
+  works better too.  Backported from 3.1.1. (#88)
+
+- Permits non-string values for the EXTNAME keyword when reading in a file,
+  rather than throwing an exception due to the malformatting.  Added
+  verification for the format of the EXTNAME keyword when writing.  Backported
+  from 3.1.1. (#96)
+
+- Added support for EXTNAME and EXTVER in PRIMARY HDUs.  That is, if EXTNAME
+  is specified in the header, it will also be reflected in the ``.name``
+  attribute and in ``pyfits.info()``.  These keywords used to be verbotten in
+  PRIMARY HDUs, but the latest version of the FITS standard allows them.
+  Backported from 3.1.1. (#151)
+
+- HCOMPRESS can again be used to compress data cubes (and higher-dimensional
+  arrays) so long as the tile size is effectively 2-dimensional. In fact,
+  PyFITS will not automatically use compatible tile sizes even if they're not
+  explicitly specified.  Backported from 3.1.1. (#171)
+
+- Fixed an issue where opening files containing random groups HDUs in update
+  mode could cause an unnecessary rewrite of the file even if none of the
+  data is modified.  Backported from 3.1.1. (#179)
+
+- Fixed a bug that could caused a deadlock in the filesystem on OSX if PyFITS
+  is used with Numpy 1.7 in some cases. Backported from 3.1.1. (#180)
+
+
+3.1 (2012-08-08)
+----------------
 
 Highlights
 ^^^^^^^^^^
@@ -192,6 +323,14 @@ New Features
   mode).  This may be especially useful when working with scaled image data.
   (#121)
 
+Changes in Behavior
+^^^^^^^^^^^^^^^^^^^
+
+- Warnings from PyFITS are not output to stderr by default, instead of stdout
+  as it has been for some time.  This is contrary to most users' expectations
+  and makes it more difficult for them to separate output from PyFITS from the
+  desired output for their scripts. (r1319)
+
 Bug Fixes
 ^^^^^^^^^
 
@@ -224,6 +363,43 @@ Bug Fixes
 - Fixed a bug where ``ImageHDU.scale(option='old')`` wasn't working at all--it
   was not restoring the image to its original BSCALE and BZERO values. (#162)
 
+- Fixed a bug when writing out files containing zero-width table columns,
+  where the TFIELDS keyword would be updated incorrectly, leaving the table
+  largely unreadable.  This fix will be backported to the 3.0.x series in
+  version 3.0.10.  (#174)
+
+
+3.0.9 (2012-08-06)
+------------------
+
+This is a bug fix release for the 3.0.x series.
+
+Bug Fixes
+^^^^^^^^^
+
+- Fixed ``Header.values()``/``Header.itervalues()`` and ``Header.items()``/
+  ``Header.iteritems()`` to correctly return the different values for
+  duplicate keywords (particularly commentary keywords like HISTORY and
+  COMMENT).  This makes the old Header implementation slightly more compatible
+  with the new implementation in PyFITS 3.1. (#127)
+
+  .. note::
+      This fix did not change the existing behavior from earlier PyFITS
+      versions where ``Header.keys()`` returns all keywords in the header with
+      duplicates removed.  PyFITS 3.1 changes that behavior, so that
+      ``Header.keys()`` includes duplicates.
+
+- Fixed a bug where ``ImageHDU.scale(option='old')`` wasn't working at all--it
+  was not restoring the image to its original BSCALE and BZERO values. (#162)
+
+- Fixed a bug where opening a file containing compressed image HDUs in
+  'update' mode and then immediately closing it without making any changes
+  caused the file to be rewritten unncessarily. (#167)
+
+- Fixed two memory leaks that could occur when writing compressed image data,
+  or in some cases when opening files containing compressed image HDUs in
+  'update' mode. (#168)
+
 
 3.0.8 (2012-06-04)
 ---------------------
@@ -2173,6 +2349,7 @@ Changes since 0.7.6:
 
 
 0.7.6 (2002-11-22)
+------------------
 
 **NOTE:** This version will only work with numarray Version 0.4.
 
diff --git a/docs/_static/images/io/fits/Blue.jpg b/docs/io/fits/images/Blue.jpg
similarity index 100%
rename from docs/_static/images/io/fits/Blue.jpg
rename to docs/io/fits/images/Blue.jpg
diff --git a/docs/_static/images/io/fits/Green.jpg b/docs/io/fits/images/Green.jpg
similarity index 100%
rename from docs/_static/images/io/fits/Green.jpg
rename to docs/io/fits/images/Green.jpg
diff --git a/docs/_static/images/io/fits/Hs-2009-14-a-web.jpg b/docs/io/fits/images/Hs-2009-14-a-web.jpg
similarity index 100%
rename from docs/_static/images/io/fits/Hs-2009-14-a-web.jpg
rename to docs/io/fits/images/Hs-2009-14-a-web.jpg
diff --git a/docs/_static/images/io/fits/Red.jpg b/docs/io/fits/images/Red.jpg
similarity index 100%
rename from docs/_static/images/io/fits/Red.jpg
rename to docs/io/fits/images/Red.jpg
diff --git a/docs/io/fits/index.rst b/docs/io/fits/index.rst
index 4c3382e..f4d94fb 100644
--- a/docs/io/fits/index.rst
+++ b/docs/io/fits/index.rst
@@ -25,13 +25,7 @@ Reading and Updating Existing FITS Files
 Opening a FITS file
 ^^^^^^^^^^^^^^^^^^^
 
-Once the `astropy.io.fits` package is loaded, we can open an existing FITS
-file:
-
-    >>> import astropy.io.fits
-    >>> hdulist = astropy.io.fits.open('input.fits')
-
-For the sake of brevity, one may also use `astropy.io.fits` like so:
+Once the `astropy.io.fits` package is loaded using the standard convention\ [#f1]_, we can open an existing FITS file:
 
     >>> from astropy.io import fits
     >>> hdulist = fits.open('input.fits')
@@ -246,7 +240,7 @@ to flux:
 
     >>> photflam = hdulist[1].header['photflam']
     >>> exptime = prihdr['exptime']
-    >>> scidata \*= photflam / exptime
+    >>> scidata *= photflam / exptime
 
 This example performs the math on the array in-place, thereby keeping the
 memory usage to a minimum.
@@ -267,7 +261,7 @@ with record arrays is not a prerequisite for this Guide.
 Like images, the data portion of a FITS table extension is in the ``.data``
 attribute:
 
-    >>> hdulist = astropy.io.fits.open('table.fits')
+    >>> hdulist = fits.open('table.fits')
     >>> tbdata = hdulist[1].data # assuming the first extension is a table
 
 To see the first row of the table:
@@ -354,7 +348,7 @@ also be used to write all the changes made since :func:`open`, back to the
 original file. The :meth:`~HDUList.close` method will do the same for a FITS
 file opened with update mode.
 
-    >>> f = astropy.io.fits.open('original.fits', mode='update')
+    >>> f = fits.open('original.fits', mode='update')
     ... # making changes in data and/or header
     >>> f.flush() # changes are written back to original.fits
 
@@ -373,16 +367,16 @@ consisting only the primary HDU with image data.
 First, we create a numpy object for the data part:
 
     >>> import numpy as np
-    >>> n = np.arange(100) # a simple sequence from 0 to 99
+    >>> n = np.arange(100.0) # a simple sequence of floats from 0.0 to 99.9
 
 Next, we create a :class:`PrimaryHDU` object to encapsulate the data:
 
-    >>> hdu = astropy.io.fits.PrimaryHDU(n)
+    >>> hdu = fits.PrimaryHDU(n)
 
 We then create a HDUList to contain the newly created primary HDU, and write to
 a new file:
 
-    >>> hdulist = astropy.io.fits.HDUList([hdu])
+    >>> hdulist = fits.HDUList([hdu])
     >>> hdulist.writeto('new.fits')
 
 That's it! In fact, Astropy even provides a shortcut for the last two lines to
@@ -404,21 +398,21 @@ constructing the :class:`Column` objects and their data. Suppose we have two
 columns, the first containing strings, and the second containing floating point
 numbers:
 
-    >>> import astropy.io.fits
+    >>> from astropy.io import fits
     >>> import numpy as np
     >>> a1 = np.array(['NGC1001', 'NGC1002', 'NGC1003'])
     >>> a2 = np.array([11.1, 12.3, 15.2])
-    >>> col1 = astropy.io.fits.Column(name='target', format='20A', array=a1)
-    >>> col2 = astropy.io.fits.Column(name='V_mag', format='E', array=a2)
+    >>> col1 = fits.Column(name='target', format='20A', array=a1)
+    >>> col2 = fits.Column(name='V_mag', format='E', array=a2)
 
 Next, create a :class:`ColDefs` (column-definitions) object for all columns:
 
-    >>> cols = astropy.io.fits.ColDefs([col1, col2])
+    >>> cols = fits.ColDefs([col1, col2])
 
 Now, create a new binary table HDU object by using the :func:`new_table()`
 function:
 
-    >>> tbhdu = astropy.io.fits.new_table(cols)
+    >>> tbhdu = fits.new_table(cols)
 
 This function returns (in this case) a :class:`BinTableHDU`.
 
@@ -431,12 +425,12 @@ Of course, you can do this more concisely:
 
 As before, we create a :class:`PrimaryHDU` object to encapsulate the data:
 
-    >>> hdu = astropy.io.fits.PrimaryHDU(n)
+    >>> hdu = fits.PrimaryHDU(n)
 
 We then create a HDUList containing both the primary HDU and the newly created
 table extension, and write to a new file:
 
-    >>> thdulist = astropy.io.fits.HDUList([hdu, tbhdu])
+    >>> thdulist = fits.HDUList([hdu, tbhdu])
     >>> thdulist.writeto('table.fits')
 
 If this will be the only extension of the new FITS file and you only have a
@@ -521,12 +515,12 @@ both data and header, otherwise only data is returned.
 The functions introduced above are for reading. The next few functions
 demonstrate convenience functions for writing:
 
-    >>> astropy.io.fits.writeto('out.fits', data, header)
+    >>> fits.writeto('out.fits', data, header)
 
 The :func:`writeto` function uses the provided data and an optional header to
 write to an output FITS file.
 
-    >>> astropy.io.fits.append('out.fits', data, header)
+    >>> fits.append('out.fits', data, header)
 
 The :func:`append` function will use the provided data and the optional header
 to append to an existing FITS file. If the specified output file does not
@@ -549,7 +543,7 @@ also be keyword arguments.
 Finally, the :func:`info` function will print out information of the specified
 FITS file:
 
-    >>> astropy.io.fits.info('test0.fits')
+    >>> fits.info('test0.fits')
     Filename: test0.fits
     No. Name    Type       Cards Dimensions Format
     0   PRIMARY PrimaryHDU   138 ()         Int16
@@ -596,3 +590,9 @@ Reference/API
     api/images.rst
     api/diff.rst
     api/verification.rst
+
+
+.. rubric:: Footnotes
+
+.. [#f1]  For legacy code only that already depends on PyFITS, it's acceptable to continue using "from astropy.io import fits as pyfits".
+
diff --git a/docs/io/fits/usage/examples.rst b/docs/io/fits/usage/examples.rst
index 025544a..ce3c82a 100644
--- a/docs/io/fits/usage/examples.rst
+++ b/docs/io/fits/usage/examples.rst
@@ -4,29 +4,29 @@ Examples
 Converting a 3-color image (JPG) to separate FITS images
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-.. figure:: ../../../_static/images/io/fits/Hs-2009-14-a-web.jpg
+.. figure:: ../images/Hs-2009-14-a-web.jpg
    :scale: 100 %
    :align: center
    :alt: Starting image
 
 .. container:: figures
 
-    .. figure:: ../../../_static/images/io/fits/Red.jpg
-       :target: ../../../_static/images/io/fits/Red.jpg
+    .. figure:: ../images/Red.jpg
+       :target: ../images/Red.jpg
        :scale: 50
        :alt: Red color information
 
        Red color information
 
-    .. figure:: ../../../_static/images/io/fits/Green.jpg
-       :target: ../../../_static/images/io/fits/Green.jpg
+    .. figure:: ../images/Green.jpg
+       :target: ../images/Green.jpg
        :scale: 50
        :alt: Green color information
 
        Green color information
 
-    .. figure:: ../../../_static/images/io/fits/Blue.jpg
-       :target: ../../../_static/images/io/fits/Blue.jpg
+    .. figure:: ../images/Blue.jpg
+       :target: ../images/Blue.jpg
        :scale: 50
        :alt: Blue color information
 
diff --git a/docs/io/fits/usage/headers.rst b/docs/io/fits/usage/headers.rst
index 588038e..aac5cd7 100644
--- a/docs/io/fits/usage/headers.rst
+++ b/docs/io/fits/usage/headers.rst
@@ -22,7 +22,7 @@ an existing HDU's header and the data value from  a numpy array. If the
 defaults (``None``) are used, the new HDU will have the minimal required
 keywords for an HDU of that type:
 
-    >>> hdu = astropy.io.fits.PrimaryHDU()
+    >>> hdu = fits.PrimaryHDU()
     >>> hdu.header # show the all of the header cards
     SIMPLE = T / conforms to FITS standard
     BITPIX = 8 / array data type
@@ -46,7 +46,7 @@ Value Access, Updating, and Creating
 As shown in the Quick Tutorial, keyword values can be accessed via keyword name
 or index of an HDU's header attribute. Here is a quick summary:
 
-    >>> hdulist = astropy.io.fits.open('input.fits') # open a FITS file
+    >>> hdulist = fits.open('input.fits') # open a FITS file
     >>> prihdr = hdulist[0].header # the primary HDU header
     >>> print prihdr[3] # get the 4th keyword's value
     10
@@ -210,23 +210,23 @@ card image.  The latter will be discussed later.
 
 Most of the time the details of dealing with cards are handled by the
 :class:`Header` object, and it is not necessary to directly manipulate cards.
-In fact, most :class:`Header` methods that accept a (keyword, value) or
-(keyword, value, comment) tuple as an argument can also take a :class:`Card`
-object as an argument.  :class:`Card` objects are just wrappers around that
-header that provide the logic for parsing and formatting individual cards in a
-header.  But there's nothing gained by manually using a :class:`Card` object,
-except to examine how a card might appear in a header before actually adding it
-to the header.
+In fact, most :class:`Header` methods that accept a ``(keyword, value)`` or
+``(keyword, value, comment)`` tuple as an argument can also take a
+:class:`Card` object as an argument.  :class:`Card` objects are just wrappers
+around such tuples that provide the logic for parsing and formatting individual
+cards in a header.  But there's usually nothing gained by manually using a
+:class:`Card` object, except to examine how a card might appear in a header
+before actually adding it to the header.
 
 A new Card object is created with the :class:`Card` constructor:
 ``Card(key, value, comment)``. For example:
 
-    >>> c1 = astropy.io.fits.Card('TEMP', 80.0, 'temperature, floating value')
-    >>> c2 = astropy.io.fits.Card('DETECTOR', 1) # comment is optional
-    >>> c3 = astropy.io.fits.Card('MIR_REVR', True,
-    ...                           'mirror reversed? Boolean value)
-    >>> c4 = astropy.io.fits.Card('ABC', 2+3j, 'complex value')
-    >>> c5 = astropy.io.fits.Card('OBSERVER', 'Hubble', 'string value')
+    >>> c1 = fits.Card('TEMP', 80.0, 'temperature, floating value')
+    >>> c2 = fits.Card('DETECTOR', 1)  # comment is optional
+    >>> c3 = fits.Card('MIR_REVR', True,
+    ...                'mirror reversed? Boolean value')
+    >>> c4 = fits.Card('ABC', 2+3j, 'complex value')
+    >>> c5 = fits.Card('OBSERVER', 'Hubble', 'string value')
 
     >>> print c1; print c2; print c3; print c4; print c5 # show the card images
     TEMP = 80.0 / temperature, floating value
@@ -248,8 +248,8 @@ Cards can be verified with :meth:`Card.verify`. The non-standard card ``c2`` in
 the example below is flagged by such verification. More about verification in
 Astropy will be discussed in a later chapter.
 
-    >>> c1 = astropy.io.fits.Card.fromstring('ABC = 3.456D023')
-    >>> c2 = astropy.io.fits.Card.fromstring("P.I. ='Hubble'")
+    >>> c1 = fits.Card.fromstring('ABC = 3.456D023')
+    >>> c2 = fits.Card.fromstring("P.I. ='Hubble'")
     >>> print c1; print c2
     ABC = 3.456D023
     P.I. ='Hubble'
@@ -279,7 +279,7 @@ keyword. Astropy does support this convention, even though it is not a FITS
 standard. The examples below show the use of CONTINUE is automatic for long
 string values.
 
-    >>> header = astropy.io.fits.Header()
+    >>> header = fits.Header()
     >>> header['abc'] = 'abcdefg' * 20
     >>> header
     ABC = 'abcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcd&'
@@ -325,15 +325,15 @@ case-sensitive.
 
 Examples follow:
 
-    >>> c = astropy.io.fits.Card('abcdefghi', 10)
+    >>> c = fits.Card('abcdefghi', 10)
     Keyword name 'abcdefghi' is greater than 8 characters; a HIERARCH card will
     be created.
     >>> print c
     HIERARCH abcdefghi = 10
-    >>> c = astropy.io.fits.Card('hierarch abcdefghi', 10)
+    >>> c = fits.Card('hierarch abcdefghi', 10)
     >>> print c
     HIERARCH abcdefghi = 10
-    >>> h = astropy.io.fits.PrimaryHDU()
+    >>> h = fits.PrimaryHDU()
     >>> h.header['hierarch abcdefghi'] =  99
     >>> h.header['abcdefghi']
     99
diff --git a/docs/io/fits/usage/image.rst b/docs/io/fits/usage/image.rst
index 96eaba8..4a05342 100644
--- a/docs/io/fits/usage/image.rst
+++ b/docs/io/fits/usage/image.rst
@@ -31,7 +31,7 @@ the numpy array of its data will have the shape of (400, 300).
 
 Here is a summary of reading and updating image data values:
 
-    >>> f = astropy.io.fits.open('image.fits') # open a FITS file
+    >>> f = fits.open('image.fits') # open a FITS file
     >>> scidata = f[1].data # assume the first extension is an image
     >>> print scidata[1,4] # get the pixel value at x=5, y=2
     >>> scidata[30:40, 10:20] # get values of the subsection
@@ -88,7 +88,7 @@ For integer data type, the scaled data will always be single precision floating
 point (numpy.float32). Here is an example of what happens to such a file,
 before and after the data is touched
 
-    >>> f = astropy.io.fits.open('scaled_uint16.fits')
+    >>> f = fits.open('scaled_uint16.fits')
     >>> hdu = f[1]
     >>> print hdu.header['bitpix'], hdu.header['bzero']
     16 32768
@@ -112,7 +112,7 @@ before and after the data is touched
     when saving could result in a loss of information.
 
     To prevent this automatic scaling, open the file with the
-    ``do_not_scale_image_data=True`` argument to ``pyfits.open()``.  This is
+    ``do_not_scale_image_data=True`` argument to ``fits.open()``.  This is
     especially useful for updating some header values, while ensuring that the
     data is not modified.
 
@@ -147,7 +147,7 @@ files, i.e. calls of :meth:`~HDUList.writeto`, :meth:`~HDUList.flush`, or
 an example of what happens to the :attr:`~ImageHDU.data` attribute after the
 :meth:`~ImageHDU.scale` call:
 
-    >>> hdu = astropy.io.fits.PrimaryHDU(numpy.array([0., 1, 2, 3]))
+    >>> hdu = fits.PrimaryHDU(numpy.array([0., 1, 2, 3]))
     >>> print hdu.data
     [ 0. 1. 2. 3.]
     >>> hdu.scale('int16', bzero=32768)
@@ -181,9 +181,9 @@ such cases it may be necessary to use sections.
 Here is an example of getting the median image from 3 input images of the size
 5000x5000:
 
-    >>> f1 = astropy.io.fits.open('file1.fits')
-    >>> f2 = astropy.io.fits.open('file2.fits')
-    >>> f3 = astropy.io.fits.open('file3.fits')
+    >>> f1 = fits.open('file1.fits')
+    >>> f2 = fits.open('file2.fits')
+    >>> f3 = fits.open('file3.fits')
     >>> output = numpy.zeros(5000 * 5000)
     >>> for i in range(50):
     ... j = i * 100
diff --git a/docs/io/fits/usage/table.rst b/docs/io/fits/usage/table.rst
index 7f1156d..f41840d 100644
--- a/docs/io/fits/usage/table.rst
+++ b/docs/io/fits/usage/table.rst
@@ -57,7 +57,7 @@ Reading a FITS Table
 Like images, the .data attribute of a table HDU contains the data of the table.
 To recap, the simple example in the Quick Tutorial:
 
-    >>> f = astropy.io.fits.open('bright_stars.fits') # open a FITS file
+    >>> f = fits.open('bright_stars.fits') # open a FITS file
     >>> tbdata = f[1].data # assume the first extension is a table
     >>> print tbdata[:2] # show the first two rows
     [(1, 'Sirius', -1.4500000476837158, 'A1V'),
@@ -114,11 +114,11 @@ Merging Tables
 Merging different tables is straightforward in Astropy. Simply merge the column
 definitions of the input tables:
 
-    >>> t1 = astropy.io.fits.open('table1.fits')
-    >>> t2 = astropy.io.fits.open('table2.fits')
+    >>> t1 = fits.open('table1.fits')
+    >>> t2 = fits.open('table2.fits')
     # the column attribute is the column definitions
     >>> t = t1[1].columns + t2[1].columns
-    >>> hdu = astropy.io.fits.new_table(t)
+    >>> hdu = fits.new_table(t)
     >>> hdu.writeto('newtable.fits')
 
 The number of fields in the output table will be the sum of numbers of fields
@@ -137,15 +137,15 @@ append by field indices, the second one is to append by field names. In both
 cases, the output table will inherit column attributes (name, format, etc.) of
 the first table.
 
-    >>> t1 = astropy.io.fits.open('table1.fits')
-    >>> t2 = astropy.io.fits.open('table2.fits')
+    >>> t1 = fits.open('table1.fits')
+    >>> t2 = fits.open('table2.fits')
     # one way to find the number of records
     >>> nrows1 = t1[1].data.shape[0]
     # another way to find the number of records
     >>> nrows2 = t2[1].header['naxis2']
     # total number of rows in the table to be generated
     >>> nrows = nrows1 + nrows2
-    >>> hdu = astropy.io.fits.new_table(t1[1].columns, nrows=nrows)
+    >>> hdu = fits.new_table(t1[1].columns, nrows=nrows)
     # first case, append by the order of fields
     >>> for i in range(len(t1[1].columns)):
     ... hdu.data.field(i)[nrows1:]=t2[1].data.field(i)
@@ -233,7 +233,7 @@ header keywords and descriptions:
 Here are a few Columns using various combination of these arguments:
 
     >>> import numpy as np
-    >>> from astropy.io.fits import Column
+    >>> from fits import Column
     >>> counts = np.array([312, 334, 308, 317])
     >>> names = np.array(['NGC1', 'NGC2', 'NGC3', 'NGC4'])
     >>> c1 = Column(name='target', format='10A', array=names)
@@ -255,12 +255,12 @@ dimension number must be before the letter code, not after.
 After the columns are constructed, the :func:`new_table` function can be used to
 construct a table HDU. We can either go through the column definition object:
 
-    >>> coldefs = astropy.io.fits.ColDefs([c1, c2, c3, c4, c5])
-    >>> tbhdu = astropy.io.fits.new_table(coldefs)
+    >>> coldefs = fits.ColDefs([c1, c2, c3, c4, c5])
+    >>> tbhdu = fits.new_table(coldefs)
 
 or directly use the :func:`new_table` function:
 
-    >>> tbhdu = astropy.io.fits.new_table([c1, c2, c3, c4, c5])
+    >>> tbhdu = fits.new_table([c1, c2, c3, c4, c5])
 
 A look of the newly created HDU's header will show that relevant keywords are
 properly populated:
@@ -302,7 +302,7 @@ any copying.  First, create the Columns as before, but without using the
 
 Then call :func:`new_table`:
 
-    >>> tbhdu = astropy.io.fits.new_table([c1, c2, c3, c4, c5])
+    >>> tbhdu = fits.new_table([c1, c2, c3, c4, c5])
 
 This will create a new table HDU as before, with the correct column
 definitions, but an empty data section.  Now simply assign your array directly
diff --git a/docs/io/fits/usage/unfamiliar.rst b/docs/io/fits/usage/unfamiliar.rst
index d87d615..96820b0 100644
--- a/docs/io/fits/usage/unfamiliar.rst
+++ b/docs/io/fits/usage/unfamiliar.rst
@@ -20,7 +20,8 @@ same, i.e. the data is in the ``.data`` attribute and the ``field()`` method
 is used to refer to the columns and returns a numpy array. When reading the
 table, Astropy will automatically detect what kind of table it is.
 
-    >>> hdus = astropy.io.fits.open('ascii_table.fits')
+    >>> from astropy.io import fits
+    >>> hdus = fits.open('ascii_table.fits')
     >>> hdus[1].data[:1]
     FITS_rec(
     ... [(10.123000144958496, 37)],
@@ -70,18 +71,18 @@ The default value for tbtype is ``BinTableHDU``.
      >>>
      # Define the columns
      >>> import numpy as np
-     >>> import astropy.io.fits
+     >>> from astropy.io import fits
      >>> a1 = np.array(['abcd', 'def'])
      >>> r1 = np.array([11., 12.])
-     >>> c1 = astropy.io.fits.Column(name='abc', format='A3', array=a1)
-     >>> c2 = astropy.io.fits.Column(name='def', format='E', array=r1,
-     ...                             bscale=2.3, bzero=0.6)
-     >>> c3 = astropy.io.fits.Column(name='t1', format='I', array=[91, 92, 93])
+     >>> c1 = fits.Column(name='abc', format='A3', array=a1)
+     >>> c2 = fits.Column(name='def', format='E', array=r1,
+     ...                  bscale=2.3, bzero=0.6)
+     >>> c3 = fits.Column(name='t1', format='I', array=[91, 92, 93])
      # Create the table
-     >>> x = astropy.io.fits.ColDefs([c1, c2, c3], tbtype='TableHDU')
-     >>> hdu = astropy.io.fits.new_table(x, tbtype='TableHDU')
+     >>> x = fits.ColDefs([c1, c2, c3], tbtype='TableHDU')
+     >>> hdu = fits.new_table(x, tbtype='TableHDU')
      # Or, simply,
-     >>> hdu = astropy.io.fits.new_table([c1, c2, c3], tbtype='TableHDU')
+     >>> hdu = fits.new_table([c1, c2, c3], tbtype='TableHDU')
      >>> hdu.writeto('ascii.fits')
      >>> hdu.data
      FITS_rec([('abcd', 11.0, 91), ('def', 12.0, 92), ('', 0.0, 93)],
@@ -115,7 +116,7 @@ length array field in Astropy), and max is the maximum number of elements. So,
 for a variable length field of int32, The corresponding format spec is,
 e.g. 'PJ(100)'.
 
-    >>> f = astropy.io.fits.open('variable_length_table.fits')
+    >>> f = fits.open('variable_length_table.fits')
     >>> print f[1].header['tform5']
     1PI(20)
     >>> print f[1].data.field(4)[:3]
@@ -157,7 +158,7 @@ is regular and the other variable length array.
     >>> tbhdu.writeto('var_table.fits')
     >>> hdu = fits.open('var_table.fits')
     # Note that heap info is taken care of (PCOUNT) when written to FITS file.
-    >>> print hdu[1].header.ascardlist()
+    >>> hdu[1].header
     XTENSION= 'BINTABLE'       / binary table extension
     BITPIX  =                8 / array data type
     NAXIS   =                2 / number of array dimensions
@@ -206,7 +207,7 @@ other HDU. Just use the .header attribute.
 The content of the HDU can similarly be summarized by using the
 :meth:`HDUList.info` method:
 
-    >>> f = astropy.io.fits.open('random_group.fits')
+    >>> f = fits.open('random_group.fits')
     >>> print f[0].header['groups']
     True
     >>> print f[0].header['gcount']
@@ -327,7 +328,7 @@ to create the HDU itself:
 
     >>>
     # Create the image arrays. The first dimension is the number of groups.
-    >>> imdata = numpy.arange(100., shape=(10, 1, 1, 2, 5))
+    >>> imdata = numpy.arange(100.0, shape=(10, 1, 1, 2, 5))
     # Next, create the group parameter data, we'll have two parameters.
     # Note that the size of each parameter's data is also the number of groups.
     # A parameter's data can also be a numeric constant.
@@ -337,12 +338,12 @@ to create the HDU itself:
     # in lists assigned to their corresponding arguments.
     # If the data type (bitpix) is not specified, the data type of the image
     # will be used.
-    >>> x = astropy.io.fits.GroupData(imdata, parnames=['abc', 'xyz'],
-             ...                      pardata=[pdata1, pdata2], bitpix=-32)
+    >>> x = fits.GroupData(imdata, parnames=['abc', 'xyz'],
+    ...                    pardata=[pdata1, pdata2], bitpix=-32)
     # Now, create the GroupsHDU and write to a FITS file.
-    >>> hdu = astropy.io.fits.GroupsHDU(x)
+    >>> hdu = fits.GroupsHDU(x)
     >>> hdu.writeto('test_group.fits')
-    >>> print hdu.header.ascardlist()[:]
+    >>> hdu.header
     SIMPLE =            T / conforms to FITS standard
     BITPIX =          -32 / array data type
     NAXIS  =            5 / number of array dimensions
@@ -409,7 +410,7 @@ a FITS file.
 
 The content of the HDU header may be accessed using the ``.header`` attribute:
 
-    >>> f = astropy.io.fits.open('compressed_image.fits')
+    >>> f = fits.open('compressed_image.fits')
     >>> print f[1].header
     XTENSION= 'IMAGE   '           / extension type
     BITPIX  =                   16 / array data type
@@ -424,7 +425,7 @@ The contents of the corresponding binary table HDU may be accessed using the
 hidden ``._header`` attribute.  However, all user interface with the HDU header
 should be accomplished through the image header (the ``.header`` attribute).
 
-    >>> f = astropy.io.fits.open('compressed_image.fits')
+    >>> f = fits.open('compressed_image.fits')
     >>> print f[1]._header
     XTENSION= 'BINTABLE'           / binary table extension
     BITPIX  =                    8 / 8-bit bytes
@@ -451,13 +452,13 @@ should be accomplished through the image header (the ``.header`` attribute).
 The contents of the HDU can be summarized by using either the :func:`info`
 convenience function or method:
 
-    >>> astropy.io.fits.info('compressed_image.fits')
+    >>> fits.info('compressed_image.fits')
     Filename: compressed_image.fits
     No.    Name         Type      Cards   Dimensions   Format
     0    PRIMARY     PrimaryHDU       6  ()            int16
     1    COMPRESSED  CompImageHDU    52  (512, 512)    int16
     >>>
-    >>> f = astropy.io.fits.open('compressed_image.fits')
+    >>> f = fits.open('compressed_image.fits')
     >>> f.info()
     Filename: compressed_image.fits
     No.    Name         Type      Cards   Dimensions   Format
@@ -483,7 +484,7 @@ any) in the image.
 
 The content of the HDU data may be accessed using the ``.data`` attribute:
 
-    >>> f = astropy.io.fits.open('compressed_image.fits')
+    >>> f = fits.open('compressed_image.fits')
     >>> f[1].data
     array([[38, 43, 35, ..., 45, 43, 41],
            [36, 41, 37, ..., 42, 41, 39],
@@ -502,7 +503,7 @@ To create a compressed image HDU from scratch, simply construct a
 associated image header.  From there, the HDU can be treated just like any
 other image HDU.
 
-    >>> hdu = astropy.io.fits.CompImageHDU(imageData, imageHeader)
+    >>> hdu = fits.CompImageHDU(imageData, imageHeader)
     >>> hdu.writeto('compressed_image.fits')
     >>>
 
diff --git a/docs/io/fits/usage/verification.rst b/docs/io/fits/usage/verification.rst
index 05dfae1..bbb1c7d 100644
--- a/docs/io/fits/usage/verification.rst
+++ b/docs/io/fits/usage/verification.rst
@@ -215,7 +215,7 @@ Unfixable Cards:
 
 We'll summarize the verification with a "life-cycle" example:
 
-    >>> h = astropy.io.fits.PrimaryHDU() # create a PrimaryHDU
+    >>> h = fits.PrimaryHDU() # create a PrimaryHDU
     # Try to add an non-standard FITS keyword 'P.I.' (FITS does no allow '.'
     # in the keyword), if using the update() method - doesn't work!
     >>> h['P.I.'] = 'Hubble'
@@ -223,7 +223,7 @@ We'll summarize the verification with a "life-cycle" example:
     # Have to do it the hard way (so a user will not do this by accident)
     # First, create a card image and give verbatim card content (including
     # the proper spacing, but no need to add the trailing blanks)
-    >>> c = astropy.io.fits.Card.fromstring("P.I. = 'Hubble'")
+    >>> c = fits.Card.fromstring("P.I. = 'Hubble'")
     # then append it to the header
     >>> h.header.append(c)
     # Now if we try to write to a FITS file, the default output verification
@@ -241,7 +241,7 @@ We'll summarize the verification with a "life-cycle" example:
     >>> h.writeto('pi.fits', output_verify='ignore')
     # Now reading a non-standard FITS file
     # astropy.io.fits is magnanimous in reading non-standard FITS files
-    >>> hdus = astropy.io.fits.open('pi.fits')
+    >>> hdus = fits.open('pi.fits')
     >>> hdus[0].header
     SIMPLE =            T / conforms to FITS standard
     BITPIX =            8 / array data type
@@ -296,16 +296,16 @@ header by supplying the checksum keyword argument with a value of 'datasum'.
 Here are some examples:
 
      >>> # Open the file pix.fits verifying the checksum values for all HDUs
-     >>> hdul = astropy.io.fits.open('pix.fits', checksum=True)
+     >>> hdul = fits.open('pix.fits', checksum=True)
      >>>
      >>> # Open the file in.fits where checksum verification fails for the
      >>> # primary HDU
-     >>> hdul = astropy.io.fits.open('in.fits', checksum=True)
+     >>> hdul = fits.open('in.fits', checksum=True)
      Warning:  Checksum verification failed for HDU #0.
      >>>
      >>> # Create file out.fits containing an HDU constructed from data and
      >>> # header containing both CHECKSUM and DATASUM cards.
-     >>> astropy.io.fits.writeto('out.fits', data, header, checksum=True)
+     >>> fits.writeto('out.fits', data, header, checksum=True)
      >>>
      >>> # Create file out.fits containing all the HDUs in the HDULIST
      >>> # hdul with each HDU header containing only the DATASUM card
@@ -318,4 +318,4 @@ Here are some examples:
      >>> # Append a new HDU constructed from array data to the end of
      >>> # the file existingfile.fits with only the appended HDU
      >>> # containing both CHECKSUM and DATASUM cards.
-     >>> astropy.io.fits.append('existingfile.fits', data, checksum=True)
+     >>> fits.append('existingfile.fits', data, checksum=True)
diff --git a/docs/io/misc.rst b/docs/io/misc.rst
new file mode 100644
index 0000000..125b3d4
--- /dev/null
+++ b/docs/io/misc.rst
@@ -0,0 +1,16 @@
+**********************************************
+Miscellaneous Input/Output (`astropy.io.misc`)
+**********************************************
+
+The `astropy.io.misc` module contains miscellaneous input/output routines that
+do not fit elsewhere, and are often used by other Astropy sub-packages. For
+example, `astropy.io.misc.hdf5` contains functions to read/write
+:class:`~astropy.table.table.Table` objects from/to HDF5 files, but these
+should not be imported directly by users. Instead, users can access this
+functionality via the :class:`~astropy.table.table.Table` class itself (see
+:ref:`table_io`). Routines that are intended to be used directly by users are
+listed in the `astropy.io.misc` section.
+
+.. automodapi:: astropy.io.misc
+
+.. automodapi:: astropy.io.misc.hdf5
diff --git a/docs/io/vo/api_exceptions.rst b/docs/io/vo/api_exceptions.rst
deleted file mode 100644
index 426173e..0000000
--- a/docs/io/vo/api_exceptions.rst
+++ /dev/null
@@ -1,41 +0,0 @@
-.. include:: references.txt
-
-`astropy.io.vo.exceptions`
-==========================
-
-.. contents::
-
-.. automodule:: astropy.io.vo.exceptions
-
-Exception utilities
--------------------
-
-.. currentmodule:: astropy.io.vo.exceptions
-
-.. autofunction:: warn_or_raise
-
-.. autofunction:: vo_raise
-
-.. autofunction:: vo_reraise
-
-.. autofunction:: vo_warn
-
-.. autofunction:: parse_vowarning
-
-.. autoclass:: VOWarning
-   :show-inheritance:
-
-.. autoclass:: VOTableChangeWarning
-   :show-inheritance:
-
-.. autoclass:: VOTableSpecWarning
-   :show-inheritance:
-
-.. autoclass:: UnimplementedWarning
-   :show-inheritance:
-
-.. autoclass:: IOWarning
-   :show-inheritance:
-
-.. autoclass:: VOTableSpecError
-   :show-inheritance:
diff --git a/docs/io/vo/index.rst b/docs/io/vo/index.rst
deleted file mode 100644
index 7d70e93..0000000
--- a/docs/io/vo/index.rst
+++ /dev/null
@@ -1,316 +0,0 @@
-.. include:: references.txt
-
-**************************************
-VOTable XML handling (`astropy.io.vo`)
-**************************************
-
-Introduction
-============
-
-The `astropy.io.vo` subpackage converts VOTable XML files to and from
-Numpy record arrays.
-
-Getting Started
-===============
-
-Reading a VOTable file
-----------------------
-
-To read in a VOTable file, pass a file path to
-`astropy.io.vo.table.parse`::
-
-  from astropy.io.vo.table import parse
-  votable = parse("votable.xml")
-
-``votable`` is a `~astropy.io.vo.tree.VOTableFile` object, which can
-be used to retrieve and manipulate the data and save it back out to
-disk.
-
-VOTable files are made up of nested ``RESOURCE`` elements, each of
-which may contain one or more ``TABLE`` elements.  The ``TABLE``
-elements contain the arrays of data.
-
-To get at the ``TABLE`` elements, one can write a loop over the
-resources in the ``VOTABLE`` file::
-
-  for resource in votable.resources:
-    for table in resource.tables:
-      # ... do something with the table ...
-      pass
-
-However, if the nested structure of the resources is not important,
-one can use `~astropy.io.vo.tree.VOTable.iter_tables` to return a flat
-list of all tables::
-
-  for table in votable.iter_tables():
-    # ... do something with the table ...
-    pass
-
-Finally, if there is expected to be only one table in the file, it
-might be simplest to just use
-`~astropy.io.vo.tree.VOTable.get_first_table`::
-
-  table = votable.get_first_table()
-
-Even easier, there is a convenience method to parse a VOTable file and
-return the first table all in one step::
-
-  from astropy.io.vo.table import parse_single_table
-  table = parse_single_table("votable.xml")
-
-From a `~astropy.io.vo.tree.Table` object, one can get the data itself
-in the ``array`` member variable::
-
-  data = table.array
-
-This data is a Numpy record array.  The columns get their names from
-both the ``ID`` and ``name`` attributes of the ``FIELD`` elements in
-the ``VOTABLE`` file.  For example, suppose we had a ``FIELD``
-specified as follows:
-
-.. code-block:: xml
-
-   <FIELD ID="Dec" name="dec_targ" datatype="char" ucd="POS_EQ_DEC_MAIN"
-          unit="deg">
-    <DESCRIPTION>
-     representing the ICRS declination of the center of the image.
-    </DESCRIPTION>
-   </FIELD>
-
-This column of data can be extracted from the record array using::
-
-  >>> table.array['dec_targ']
-  array([17.15153360566, 17.15153360566, 17.15153360566, 17.1516686826,
-         17.1516686826, 17.1516686826, 17.1536197136, 17.1536197136,
-         17.1536197136, 17.15375479055, 17.15375479055, 17.15375479055,
-         17.1553884541, 17.15539736932, 17.15539752176,
-         17.25736014763,
-         # ...
-         17.2765703], dtype=object)
-
-or equivalently::
-
-  >>> table.array['Dec']
-  array([17.15153360566, 17.15153360566, 17.15153360566, 17.1516686826,
-         17.1516686826, 17.1516686826, 17.1536197136, 17.1536197136,
-         17.1536197136, 17.15375479055, 17.15375479055, 17.15375479055,
-         17.1553884541, 17.15539736932, 17.15539752176,
-         17.25736014763,
-         # ...
-         17.2765703], dtype=object)
-
-Building a new table from scratch
----------------------------------
-
-It is also possible to build a new table, define some field datatypes
-and populate it with data::
-
-  from astropy.io.vo.tree import VOTableFile, Resource, Table, Field
-
-  # Create a new VOTable file...
-  votable = VOTableFile()
-
-  # ...with one resource...
-  resource = Resource()
-  votable.resources.append(resource)
-
-  # ... with one table
-  table = Table(votable)
-  resource.tables.append(table)
-
-  # Define some fields
-  table.fields.extend([
-          Field(votable, name="filename", datatype="char", arraysize="*"),
-          Field(votable, name="matrix", datatype="double", arraysize="2x2")])
-
-  # Now, use those field definitions to create the numpy record arrays, with
-  # the given number of rows
-  table.create_arrays(2)
-
-  # Now table.array can be filled with data
-  table.array[0] = ('test1.xml', [[1, 0], [0, 1]])
-  table.array[1] = ('test2.xml', [[0.5, 0.3], [0.2, 0.1]])
-
-  # Now write the whole thing to a file.
-  # Note, we have to use the top-level votable file object
-  votable.to_xml("new_votable.xml")
-
-Outputting a VOTable file
--------------------------
-
-To save a VOTable file, simply call the
-`~astropy.io.vo.tree.VOTableFile.to_xml` method.  It accepts either a
-string or unicode path, or a Python file-like object::
-
-  votable.to_xml('output.xml')
-
-There are currently two data storage formats supported by
-`astropy.io.vo`.  The ``TABLEDATA`` format is XML-based and stores
-values as strings representing numbers.  The ``BINARY`` format is more
-compact, and stores numbers in base64-encoded binary.  The storage
-format can be set on a per-table basis using the
-`~astropy.io.vo.tree.Table.format` attribute, or globally using the
-`~astropy.io.vo.tree.VOTableFile.set_all_tables_format` method::
-
-  votable.get_first_table().format = 'binary'
-  votable.set_all_tables_format('binary')
-  votable.to_xml('binary.xml')
-
-Using `io.vo`
-=============
-
-Standard compliance
--------------------
-
-`astropy.io.vo.table` supports the `VOTable Format Definition Version
-1.1
-<http://www.ivoa.net/Documents/REC/VOTable/VOTable-20040811.html>`_
-and `Version 1.2
-<http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html>`_.
-Some flexibility is provided to support the 1.0 draft version and
-other non-standard usage in the wild.  To support these cases, set the
-keyword argument ``pedantic`` to ``False`` when parsing.
-
-.. note::
-
-  Each warning and VOTABLE-specific exception emitted has a number and
-  is documented in more detail in :ref:`warnings` and
-  :ref:`exceptions`.
-
-Output always conforms to the 1.1 or 1.2 spec, depending on the input.
-
-.. _pedantic-mode:
-
-Pedantic mode
-^^^^^^^^^^^^^
-
-Many VOTABLE files in the wild do not conform to the VOTABLE
-specification.  If reading one of these files causes exceptions, you
-may turn off pedantic mode in `astropy.io.vo` by passing
-``pedantic=False`` to the `~astropy.io.vo.table.parse` or
-`~astropy.io.vo.table.parse_single_table` functions::
-
-  from astropy.io.vo.table import parse
-  votable = parse("votable.xml", pedantic=False)
-
-Note, however, that it is good practice to report these errors to the
-author of the application that generated the VOTABLE file to bring the
-file into compliance with the specification.
-
-Even with ``pedantic`` turned off, many warnings may still be omitted.
-These warnings are all of the type
-`~astropy.io.vo.exceptions.VOTableSpecWarning` and can be turned off
-using the standard Python `warnings` module.
-
-Missing values
---------------
-
-Any value in the table may be "missing".  `astropy.io.vo.table` stores
-a parallel array in each `~astropy.io.vo.tree.Table` instance called
-`~astropy.io.vo.tree.Table.mask` to keep track of missing values.
-This array is ``False`` anywhere the value is missing.
-
-.. note::
-   In the future, the ``array`` and ``mask`` members will likely be
-   combined into a single masked record array.  There are
-   implementation bugs in current versions of Numpy that prevent this
-   at the moment.
-
-Datatype mappings
------------------
-
-The datatype specified by a ``FIELD`` element is mapped to a Numpy
-type according to the following table:
-
-  ================================ ========================================================================
-  VOTABLE type                     Numpy type
-  ================================ ========================================================================
-  boolean                          b1
-  -------------------------------- ------------------------------------------------------------------------
-  bit                              b1
-  -------------------------------- ------------------------------------------------------------------------
-  unsignedByte                     u1
-  -------------------------------- ------------------------------------------------------------------------
-  char (*variable length*)         O - In Python 2.x, a `str` object; in 3.x, a `bytes` object.
-  -------------------------------- ------------------------------------------------------------------------
-  char (*fixed length*)            S
-  -------------------------------- ------------------------------------------------------------------------
-  unicodeChar (*variable length*)  O - In Python 2.x, a `unicode` object, in utf-16; in 3.x a `str` object
-  -------------------------------- ------------------------------------------------------------------------
-  unicodeChar (*fixed length*)     U
-  -------------------------------- ------------------------------------------------------------------------
-  short                            i2
-  -------------------------------- ------------------------------------------------------------------------
-  int                              i4
-  -------------------------------- ------------------------------------------------------------------------
-  long                             i8
-  -------------------------------- ------------------------------------------------------------------------
-  float                            f4
-  -------------------------------- ------------------------------------------------------------------------
-  double                           f8
-  -------------------------------- ------------------------------------------------------------------------
-  floatComplex                     c8
-  -------------------------------- ------------------------------------------------------------------------
-  doubleComplex                    c16
-  ================================ ========================================================================
-
-If the field is a fixed size array, the data is stored as a Numpy
-fixed-size array.
-
-If the field is a variable size array (that is ``arraysize`` contains
-a '*'), the cell will contain a Python list of Numpy values.  Each
-value may be either an array or scalar depending on the ``arraysize``
-specifier.
-
-Examining field types
----------------------
-
-To look up more information about a field in a table, one can use the
-`~astropy.io.vo.tree.Table.get_field_or_param_by_id` method, which
-returns the `~astropy.io.vo.tree.Field` object with the given ID.  For
-example::
-
-  >>> field = table.get_field_or_param_by_id('Dec')
-  >>> field.datatype
-  'char'
-  >>> field.unit
-  'deg'
-
-.. note::
-   Field descriptors should not be mutated -- they will have no effect
-   on the record arrays storing the data.  This shortcoming will be
-   addressed in a future version of `astropy.io.vo`.
-
-Performance considerations
---------------------------
-
-File reads will be moderately faster if the ``TABLE`` element includes
-an nrows_ attribute.  If the number of rows is not specified, the
-record array must be resized repeatedly during load.
-
-.. _nrows: http://www.ivoa.net/Documents/REC/VOTable/VOTable-20040811.html#ToC10
-
-See Also
-========
-
-- `VOTable Format Definition Version 1.1
-  <http://www.ivoa.net/Documents/REC/VOTable/VOTable-20040811.html>`_
-
-- `VOTable Format Definition Version 1.2
-  <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html>`_
-
-Reference/API
-=============
-
-.. automodapi:: astropy.io.vo
-   :no-main-section:
-   :subsections: table, tree, converters, ucd, unit, util, validator, xmlutil
-   :no-inheritance-diagram:
-
-astropy.io.vo.exceptions Module
--------------------------------
-
-.. toctree::
-   :maxdepth: 1
-
-   api_exceptions.rst
diff --git a/docs/io/vo/.gitignore b/docs/io/votable/.gitignore
similarity index 100%
rename from docs/io/vo/.gitignore
rename to docs/io/votable/.gitignore
diff --git a/docs/io/votable/api_exceptions.rst b/docs/io/votable/api_exceptions.rst
new file mode 100644
index 0000000..669e837
--- /dev/null
+++ b/docs/io/votable/api_exceptions.rst
@@ -0,0 +1,41 @@
+.. include:: references.txt
+
+`astropy.io.votable.exceptions`
+===============================
+
+.. contents::
+
+.. automodule:: astropy.io.votable.exceptions
+
+Exception utilities
+-------------------
+
+.. currentmodule:: astropy.io.votable.exceptions
+
+.. autofunction:: warn_or_raise
+
+.. autofunction:: vo_raise
+
+.. autofunction:: vo_reraise
+
+.. autofunction:: vo_warn
+
+.. autofunction:: parse_vowarning
+
+.. autoclass:: VOWarning
+   :show-inheritance:
+
+.. autoclass:: VOTableChangeWarning
+   :show-inheritance:
+
+.. autoclass:: VOTableSpecWarning
+   :show-inheritance:
+
+.. autoclass:: UnimplementedWarning
+   :show-inheritance:
+
+.. autoclass:: IOWarning
+   :show-inheritance:
+
+.. autoclass:: VOTableSpecError
+   :show-inheritance:
diff --git a/docs/io/votable/index.rst b/docs/io/votable/index.rst
new file mode 100644
index 0000000..719b149
--- /dev/null
+++ b/docs/io/votable/index.rst
@@ -0,0 +1,354 @@
+.. include:: references.txt
+
+*******************************************
+VOTable XML handling (`astropy.io.votable`)
+*******************************************
+
+Introduction
+============
+
+The `astropy.io.votable` subpackage converts VOTable XML files to and
+from Numpy record arrays.
+
+Getting Started
+===============
+
+Reading a VOTable file
+----------------------
+
+To read in a VOTable file, pass a file path to
+`~astropy.io.votable.parse`::
+
+  from astropy.io.votable import parse
+  votable = parse("votable.xml")
+
+``votable`` is a `~astropy.io.votable.tree.VOTableFile` object, which
+can be used to retrieve and manipulate the data and save it back out
+to disk.
+
+VOTable files are made up of nested ``RESOURCE`` elements, each of
+which may contain one or more ``TABLE`` elements.  The ``TABLE``
+elements contain the arrays of data.
+
+To get at the ``TABLE`` elements, one can write a loop over the
+resources in the ``VOTABLE`` file::
+
+  for resource in votable.resources:
+    for table in resource.tables:
+      # ... do something with the table ...
+      pass
+
+However, if the nested structure of the resources is not important,
+one can use `~astropy.io.votable.tree.VOTableFile.iter_tables` to
+return a flat list of all tables::
+
+  for table in votable.iter_tables():
+    # ... do something with the table ...
+    pass
+
+Finally, if there is expected to be only one table in the file, it
+might be simplest to just use
+`~astropy.io.votable.tree.VOTableFile.get_first_table`::
+
+  table = votable.get_first_table()
+
+Even easier, there is a convenience method to parse a VOTable file and
+return the first table all in one step::
+
+  from astropy.io.votable import parse_single_table
+  table = parse_single_table("votable.xml")
+
+From a `~astropy.io.votable.tree.Table` object, one can get the data itself
+in the ``array`` member variable::
+
+  data = table.array
+
+This data is a Numpy record array.  The columns get their names from
+both the ``ID`` and ``name`` attributes of the ``FIELD`` elements in
+the ``VOTABLE`` file.  For example, suppose we had a ``FIELD``
+specified as follows:
+
+.. code-block:: xml
+
+   <FIELD ID="Dec" name="dec_targ" datatype="char" ucd="POS_EQ_DEC_MAIN"
+          unit="deg">
+    <DESCRIPTION>
+     representing the ICRS declination of the center of the image.
+    </DESCRIPTION>
+   </FIELD>
+
+This column of data can be extracted from the record array using::
+
+  >>> table.array['dec_targ']
+  array([17.15153360566, 17.15153360566, 17.15153360566, 17.1516686826,
+         17.1516686826, 17.1516686826, 17.1536197136, 17.1536197136,
+         17.1536197136, 17.15375479055, 17.15375479055, 17.15375479055,
+         17.1553884541, 17.15539736932, 17.15539752176,
+         17.25736014763,
+         # ...
+         17.2765703], dtype=object)
+
+or equivalently::
+
+  >>> table.array['Dec']
+  array([17.15153360566, 17.15153360566, 17.15153360566, 17.1516686826,
+         17.1516686826, 17.1516686826, 17.1536197136, 17.1536197136,
+         17.1536197136, 17.15375479055, 17.15375479055, 17.15375479055,
+         17.1553884541, 17.15539736932, 17.15539752176,
+         17.25736014763,
+         # ...
+         17.2765703], dtype=object)
+
+Building a new table from scratch
+---------------------------------
+
+It is also possible to build a new table, define some field datatypes
+and populate it with data::
+
+  from astropy.io.votable.tree import VOTableFile, Resource, Table, Field
+
+  # Create a new VOTable file...
+  votable = VOTableFile()
+
+  # ...with one resource...
+  resource = Resource()
+  votable.resources.append(resource)
+
+  # ... with one table
+  table = Table(votable)
+  resource.tables.append(table)
+
+  # Define some fields
+  table.fields.extend([
+          Field(votable, name="filename", datatype="char", arraysize="*"),
+          Field(votable, name="matrix", datatype="double", arraysize="2x2")])
+
+  # Now, use those field definitions to create the numpy record arrays, with
+  # the given number of rows
+  table.create_arrays(2)
+
+  # Now table.array can be filled with data
+  table.array[0] = ('test1.xml', [[1, 0], [0, 1]])
+  table.array[1] = ('test2.xml', [[0.5, 0.3], [0.2, 0.1]])
+
+  # Now write the whole thing to a file.
+  # Note, we have to use the top-level votable file object
+  votable.to_xml("new_votable.xml")
+
+Outputting a VOTable file
+-------------------------
+
+To save a VOTable file, simply call the
+`~astropy.io.votable.tree.VOTableFile.to_xml` method.  It accepts
+either a string or unicode path, or a Python file-like object::
+
+  votable.to_xml('output.xml')
+
+There are currently two data storage formats supported by
+`astropy.io.votable`.  The ``TABLEDATA`` format is XML-based and
+stores values as strings representing numbers.  The ``BINARY`` format
+is more compact, and stores numbers in base64-encoded binary.  The
+storage format can be set on a per-table basis using the
+`~astropy.io.votable.tree.Table.format` attribute, or globally using
+the `~astropy.io.votable.tree.VOTableFile.set_all_tables_format`
+method::
+
+  votable.get_first_table().format = 'binary'
+  votable.set_all_tables_format('binary')
+  votable.to_xml('binary.xml')
+
+Using `io.votable`
+==================
+
+Standard compliance
+-------------------
+
+`astropy.io.votable.table` supports the `VOTable Format Definition
+Version 1.1
+<http://www.ivoa.net/Documents/REC/VOTable/VOTable-20040811.html>`_
+and `Version 1.2
+<http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html>`_.
+Some flexibility is provided to support the 1.0 draft version and
+other non-standard usage in the wild.  To support these cases, set the
+keyword argument ``pedantic`` to ``False`` when parsing.
+
+.. note::
+
+  Each warning and VOTABLE-specific exception emitted has a number and
+  is documented in more detail in :ref:`warnings` and
+  :ref:`exceptions`.
+
+Output always conforms to the 1.1 or 1.2 spec, depending on the input.
+
+.. _pedantic-mode:
+
+Pedantic mode
+^^^^^^^^^^^^^
+
+Many VOTABLE files in the wild do not conform to the VOTABLE
+specification.  If reading one of these files causes exceptions, you
+may turn off pedantic mode in `astropy.io.votable` by passing
+``pedantic=False`` to the `~astropy.io.votable.parse` or
+`~astropy.io.votable.parse_single_table` functions::
+
+  from astropy.io.votable import parse
+  votable = parse("votable.xml", pedantic=False)
+
+Note, however, that it is good practice to report these errors to the
+author of the application that generated the VOTABLE file to bring the
+file into compliance with the specification.
+
+Even with ``pedantic`` turned off, many warnings may still be omitted.
+These warnings are all of the type
+`~astropy.io.votable.exceptions.VOTableSpecWarning` and can be turned
+off using the standard Python `warnings` module.
+
+Missing values
+--------------
+
+Any value in the table may be "missing".  `astropy.io.votable` stores
+a Numpy masked array in each `~astropy.io.votable.tree.Table`
+instance.  This behaves like an ordinary Numpy masked array, except
+for variable-length fields.  For those fields, the datatype of the
+column is "object" and another Numpy masked array is stored there.
+Therefore, operations on variable length columns will not work -- this
+is simply because variable length columns are not directly supported
+by Numpy masked arrays.
+
+Datatype mappings
+-----------------
+
+The datatype specified by a ``FIELD`` element is mapped to a Numpy
+type according to the following table:
+
+  ================================ ========================================================================
+  VOTABLE type                     Numpy type
+  ================================ ========================================================================
+  boolean                          b1
+  -------------------------------- ------------------------------------------------------------------------
+  bit                              b1
+  -------------------------------- ------------------------------------------------------------------------
+  unsignedByte                     u1
+  -------------------------------- ------------------------------------------------------------------------
+  char (*variable length*)         O - In Python 2.x, a `str` object; in 3.x, a `bytes` object.
+  -------------------------------- ------------------------------------------------------------------------
+  char (*fixed length*)            S
+  -------------------------------- ------------------------------------------------------------------------
+  unicodeChar (*variable length*)  O - In Python 2.x, a `unicode` object, in utf-16; in 3.x a `str` object
+  -------------------------------- ------------------------------------------------------------------------
+  unicodeChar (*fixed length*)     U
+  -------------------------------- ------------------------------------------------------------------------
+  short                            i2
+  -------------------------------- ------------------------------------------------------------------------
+  int                              i4
+  -------------------------------- ------------------------------------------------------------------------
+  long                             i8
+  -------------------------------- ------------------------------------------------------------------------
+  float                            f4
+  -------------------------------- ------------------------------------------------------------------------
+  double                           f8
+  -------------------------------- ------------------------------------------------------------------------
+  floatComplex                     c8
+  -------------------------------- ------------------------------------------------------------------------
+  doubleComplex                    c16
+  ================================ ========================================================================
+
+If the field is a fixed size array, the data is stored as a Numpy
+fixed-size array.
+
+If the field is a variable size array (that is ``arraysize`` contains
+a '*'), the cell will contain a Python list of Numpy values.  Each
+value may be either an array or scalar depending on the ``arraysize``
+specifier.
+
+Examining field types
+---------------------
+
+To look up more information about a field in a table, one can use the
+`~astropy.io.votable.tree.Table.get_field_by_id` method, which returns
+the `~astropy.io.votable.tree.Field` object with the given ID.  For
+example::
+
+  >>> field = table.get_field_or_param_by_id('Dec')
+  >>> field.datatype
+  'char'
+  >>> field.unit
+  'deg'
+
+.. note::
+   Field descriptors should not be mutated.  To change the set of
+   columns, convert the Table to an `astropy.table.Table`, make the
+   changes, and then convert it back.
+
+Converting to/from an `astropy.table.Table`
+-------------------------------------------
+
+The VOTable standard does not map conceptually to an
+`astropy.table.Table`.  However, a single table within the `VOTable`
+file may be converted to and from an `astropy.table.Table`::
+
+  from astropy.io.votable import parse_single_table
+  table = parse_single_table("votable.xml").to_table()
+
+As a convenience, there is also a function to create an entire VOTable
+file with just a single table::
+
+  from astropy.io.votable import from_table, writeto
+  votable = from_table(table)
+  writeto(votable, "output.xml")
+
+Performance considerations
+--------------------------
+
+File reads will be moderately faster if the ``TABLE`` element includes
+an nrows_ attribute.  If the number of rows is not specified, the
+record array must be resized repeatedly during load.
+
+.. _nrows: http://www.ivoa.net/Documents/REC/VOTable/VOTable-20040811.html#ToC10
+
+See Also
+========
+
+- `VOTable Format Definition Version 1.1
+  <http://www.ivoa.net/Documents/REC/VOTable/VOTable-20040811.html>`_
+
+- `VOTable Format Definition Version 1.2
+  <http://www.ivoa.net/Documents/VOTable/20091130/REC-VOTable-1.2.html>`_
+
+Reference/API
+=============
+
+.. automodapi:: astropy.io.votable
+   :no-inheritance-diagram:
+   :skip: VOWarning
+   :skip: VOTableChangeWarning
+   :skip: VOTableSpecWarning
+   :skip: UnimplementedWarning
+   :skip: IOWarning
+   :skip: VOTableSpecError
+
+.. automodapi:: astropy.io.votable.tree
+   :no-inheritance-diagram:
+
+.. automodapi:: astropy.io.votable.converters
+   :no-inheritance-diagram:
+
+.. automodapi:: astropy.io.votable.ucd
+   :no-inheritance-diagram:
+
+.. automodapi:: astropy.io.votable.util
+   :no-inheritance-diagram:
+
+.. automodapi:: astropy.io.votable.validator
+   :no-inheritance-diagram:
+
+.. automodapi:: astropy.io.votable.xmlutil
+   :no-inheritance-diagram:
+
+astropy.io.votable.exceptions Module
+------------------------------------
+
+.. toctree::
+   :maxdepth: 1
+
+   api_exceptions.rst
diff --git a/docs/io/vo/references.txt b/docs/io/votable/references.txt
similarity index 100%
rename from docs/io/vo/references.txt
rename to docs/io/votable/references.txt
diff --git a/docs/logo/astropy_banner_96.png b/docs/logo/astropy_banner_96.png
deleted file mode 100644
index 89ca2ce..0000000
Binary files a/docs/logo/astropy_banner_96.png and /dev/null differ
diff --git a/docs/logo/astropyicon.ico b/docs/logo/astropyicon.ico
deleted file mode 100644
index 858e358..0000000
Binary files a/docs/logo/astropyicon.ico and /dev/null differ
diff --git a/docs/logo/astropylogo.png b/docs/logo/astropylogo.png
deleted file mode 100644
index 1386310..0000000
Binary files a/docs/logo/astropylogo.png and /dev/null differ
diff --git a/docs/logo/astropylogo.svg b/docs/logo/astropylogo.svg
deleted file mode 100644
index 4b7c9ce..0000000
--- a/docs/logo/astropylogo.svg
+++ /dev/null
@@ -1,298 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-
-<svg
-   xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:xlink="http://www.w3.org/1999/xlink"
-   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   width="1200"
-   height="220"
-   id="svg2"
-   version="1.1"
-   inkscape:version="0.48.1 r9760"
-   sodipodi:docname="astropylogo.svg"
-   inkscape:export-filename="/home/kyle/Projects/AstroPy Logo/astropylogo.png"
-   inkscape:export-xdpi="40.875"
-   inkscape:export-ydpi="40.875">
-  <defs
-     id="defs4">
-    <linearGradient
-       id="linearGradient3804">
-      <stop
-         style="stop-color:#ffa900;stop-opacity:1;"
-         offset="0"
-         id="stop3806" />
-      <stop
-         style="stop-color:#fd0000;stop-opacity:1;"
-         offset="1"
-         id="stop3808" />
-    </linearGradient>
-    <linearGradient
-       id="linearGradient5252"
-       osb:paint="solid">
-      <stop
-         style="stop-color:#4d4d4d;stop-opacity:1;"
-         offset="0"
-         id="stop5254" />
-    </linearGradient>
-    <linearGradient
-       id="linearGradient3767">
-      <stop
-         id="stop3800"
-         offset="0"
-         style="stop-color:#ffa900;stop-opacity:1;" />
-      <stop
-         id="stop3775"
-         offset="1"
-         style="stop-color:#fd0000;stop-opacity:1;" />
-    </linearGradient>
-    <inkscape:path-effect
-       effect="spiro"
-       id="path-effect3934"
-       is_visible="true" />
-    <filter
-       id="filter3014"
-       inkscape:label="Diffuse light"
-       inkscape:menu="ABCs"
-       inkscape:menu-tooltip="Basic diffuse bevel to use for building textures"
-       color-interpolation-filters="sRGB">
-      <feGaussianBlur
-         id="feGaussianBlur3016"
-         stdDeviation="6"
-         in="SourceGraphic"
-         result="result0" />
-      <feDiffuseLighting
-         id="feDiffuseLighting3018"
-         diffuseConstant="1"
-         surfaceScale="10"
-         result="result5">
-        <feDistantLight
-           id="feDistantLight3020"
-           elevation="25"
-           azimuth="235" />
-      </feDiffuseLighting>
-      <feComposite
-         id="feComposite3022"
-         in2="SourceGraphic"
-         k1="1"
-         in="result5"
-         result="result4"
-         operator="arithmetic"
-         k2="0"
-         k3="0.6" />
-    </filter>
-    <filter
-       id="filter3844"
-       inkscape:label="Diffuse light"
-       inkscape:menu="ABCs"
-       inkscape:menu-tooltip="Basic diffuse bevel to use for building textures"
-       color-interpolation-filters="sRGB">
-      <feGaussianBlur
-         id="feGaussianBlur3846"
-         stdDeviation="6"
-         in="SourceGraphic"
-         result="result0" />
-      <feDiffuseLighting
-         id="feDiffuseLighting3848"
-         diffuseConstant="1"
-         surfaceScale="10"
-         result="result5">
-        <feDistantLight
-           id="feDistantLight3850"
-           elevation="25"
-           azimuth="235" />
-      </feDiffuseLighting>
-      <feComposite
-         id="feComposite3852"
-         in2="SourceGraphic"
-         k1="1"
-         in="result5"
-         result="result4"
-         operator="arithmetic"
-         k2="0"
-         k3="0.6" />
-    </filter>
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient3767"
-       id="linearGradient3798"
-       x1="195.5511"
-       y1="163.12114"
-       x2="83.651718"
-       y2="298.258"
-       gradientUnits="userSpaceOnUse"
-       spreadMethod="repeat" />
-  </defs>
-  <sodipodi:namedview
-     id="base"
-     pagecolor="#ffffff"
-     bordercolor="#666666"
-     borderopacity="1.0"
-     inkscape:pageopacity="0"
-     inkscape:pageshadow="2"
-     inkscape:zoom="0.7"
-     inkscape:cx="353.29313"
-     inkscape:cy="28.477553"
-     inkscape:document-units="px"
-     inkscape:current-layer="layer1"
-     showgrid="false"
-     inkscape:snap-global="true"
-     inkscape:snap-grids="true"
-     inkscape:window-width="1230"
-     inkscape:window-height="776"
-     inkscape:window-x="50"
-     inkscape:window-y="24"
-     inkscape:window-maximized="1"
-     fit-margin-top="5"
-     fit-margin-left="5"
-     fit-margin-right="5"
-     fit-margin-bottom="5" />
-  <metadata
-     id="metadata7">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-        <dc:title />
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <g
-     inkscape:label="Layer 1"
-     inkscape:groupmode="layer"
-     id="layer1"
-     transform="translate(2.5547457,54.766869)">
-    <path
-       sodipodi:type="arc"
-       style="fill:url(#linearGradient3798);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-opacity:1"
-       id="path3837"
-       sodipodi:cx="140.91628"
-       sodipodi:cy="233.12846"
-       sodipodi:rx="80.322945"
-       sodipodi:ry="68.372307"
-       d="m 221.23922,233.12846 c 0,37.76099 -35.96181,68.37231 -80.32294,68.37231 -44.361142,0 -80.32295,-30.61132 -80.32295,-68.37231 0,-37.76098 35.961808,-68.3723 80.32295,-68.3723 44.36113,0 80.32294,30.61132 80.32294,68.3723 z"
-       transform="matrix(1.0651076,-0.90408718,0.89013474,1.0731629,-250.16148,-67.548145)"
-       mask="none"
-       clip-path="none" />
-    <path
-       sodipodi:type="spiral"
-       style="fill:none;stroke:#ffffff;stroke-width:14.33045673;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
-       id="path5413"
-       sodipodi:cx="238.396"
-       sodipodi:cy="198.78328"
-       sodipodi:expansion="0.40000001"
-       sodipodi:revolution="0.74833119"
-       sodipodi:radius="60.381268"
-       sodipodi:argument="-6.0698166"
-       sodipodi:t0="0"
-       d="m 238.396,198.78328 c 32.61949,7.06756 15.40308,37.20961 -8.24653,38.06088 -26.00022,0.93589 -44.08994,-24.61831 -41.97511,-48.94224 2.67817,-30.80329 32.53302,-51.80129 62.38812,-48.26147"
-       transform="matrix(-0.71212781,-0.99456325,-0.9777811,0.72852659,474.31246,145.67479)" />
-    <flowRoot
-       xml:space="preserve"
-       id="flowRoot3007"
-       style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#476dd5;fill-opacity:1;stroke:none;font-family:Sans"
-       transform="matrix(3.6810943,0,0,3.6466025,-855.26062,-688.82542)"><flowRegion
-         id="flowRegion3009"><rect
-           id="rect3011"
-           width="152.88016"
-           height="43.933758"
-           x="292.94424"
-           y="170.77602"
-           style="fill:#476dd5;fill-opacity:1" /></flowRegion><flowPara
-         id="flowPara3013"
-         style="font-size:46.39981461px;font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Myriad Pro;-inkscape-font-specification:Myriad Pro Semi-Bold"><flowSpan
-           style="fill:#4d4d4d"
-           id="flowSpan2996">astro</flowSpan><flowSpan
-           style="font-size:46.39981460999999285px;font-style:normal;font-variant:normal;font-weight:300;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#ff5000;fill-opacity:1;font-family:Myriad Pro;-inkscape-font-specification:Myriad Pro Light"
-           id="flowSpan2998">py</flowSpan></flowPara><flowPara
-         style="font-size:46.39981461px;font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Myriad Pro;-inkscape-font-specification:Myriad Pro Semi-Bold"
-         id="flowPara3777">A</flowPara><flowPara
-         style="font-size:46.39981461px;font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Myriad Pro;-inkscape-font-specification:Myriad Pro Semi-Bold"
-         id="flowPara3779" /></flowRoot>    <path
-       sodipodi:type="arc"
-       style="fill:#ffffff;fill-opacity:1;stroke:none"
-       id="path3819"
-       sodipodi:cx="122.22845"
-       sodipodi:cy="337.67926"
-       sodipodi:rx="22.223356"
-       sodipodi:ry="12.626906"
-       d="m 144.4518,337.67926 c 0,6.97365 -9.94973,12.62691 -22.22335,12.62691 -12.27362,0 -22.22336,-5.65326 -22.22336,-12.62691 0,-6.97365 9.94974,-12.62691 22.22336,-12.62691 12.27362,0 22.22335,5.65326 22.22335,12.62691 z"
-       transform="matrix(1.0512298,0.82294962,-0.97239782,0.94168108,304.90482,-361.44933)" />
-    <path
-       style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:2.36031604;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
-       d="m 136.88413,-13.10567 13.09858,22.1959915 20.1541,-20.0243955 -25.57713,-10.690029 z"
-       id="path3853"
-       inkscape:connector-curvature="0"
-       sodipodi:nodetypes="ccccc" />
-    <g
-       id="g3804"
-       transform="matrix(0.95039189,0,0,0.93299787,-2.487134,-0.56516029)">
-      <path
-         inkscape:connector-curvature="0"
-         id="path3855-7"
-         d="m 142.07904,-24.83606 -2.29208,-13.70422 0.18559,0.452199 0,0"
-         style="fill:none;stroke:#ffffff;stroke-width:3.72635746;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
-      <path
-         inkscape:connector-curvature="0"
-         id="path3855-7-0"
-         d="m 127.81295,-26.11257 15.12343,0.663566 -0.4755,0.06597 0,0"
-         style="fill:none;stroke:#ffffff;stroke-width:4.02542162;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
-      <path
-         inkscape:connector-curvature="0"
-         id="path3855-7-05"
-         d="m 150.77669,-18.240009 -9.57586,-7.57806 0.46343,0.302121 0,0"
-         style="fill:none;stroke:#ffffff;stroke-width:4.06302309;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
-    </g>
-    <path
-       style="fill:none;stroke:#ffffff;stroke-width:17.45736313;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
-       d="m 67.476992,131.73602 c 3.410653,2.96251 14.804165,7.71706 18.766169,12.74152 4.041356,5.12504 3.407665,10.98393 3.371624,14.32634"
-       id="path3942"
-       inkscape:connector-curvature="0"
-       sodipodi:nodetypes="csc" />
-    <path
-       sodipodi:type="spiral"
-       style="fill:none;stroke:#ffffff;stroke-width:13.93870544;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
-       id="path2987-5"
-       sodipodi:cx="238.396"
-       sodipodi:cy="198.78328"
-       sodipodi:expansion="0.40000001"
-       sodipodi:revolution="0.75884885"
-       sodipodi:radius="60.719246"
-       sodipodi:argument="-6.0698166"
-       sodipodi:t0="0"
-       d="m 238.396,198.78328 c 32.61946,7.06755 15.40307,37.20957 -8.24652,38.06085 -26.0002,0.93588 -44.0899,-24.61829 -41.97507,-48.9422 2.70006,-31.05511 32.97695,-52.07076 63.01891,-48.18321 1.11735,0.14459 2.2306,0.32088 3.33799,0.52843"
-       transform="matrix(0.95949998,0.82835015,0.79893463,-0.95307413,-285.3304,56.888018)" />
-    <flowRoot
-       xml:space="preserve"
-       id="flowRoot3781"
-       style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
-       transform="translate(-2.5547457,-54.766869)"><flowRegion
-         id="flowRegion3783"><rect
-           id="rect3785"
-           width="565.68542"
-           height="52.527931"
-           x="237.38585"
-           y="157.37054" /></flowRegion><flowPara
-         id="flowPara3787"
-         style="-inkscape-font-specification:Myriad Pro;font-family:Myriad Pro;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;font-size:72px">Community</flowPara></flowRoot>    <flowRoot
-       xml:space="preserve"
-       id="flowRoot3789"
-       style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
-       transform="translate(-2.5547457,-56.766869)"><flowRegion
-         id="flowRegion3791"><rect
-           id="rect3793"
-           width="927.32001"
-           height="79.802055"
-           x="229.30463"
-           y="161.41115" /></flowRegion><flowPara
-         id="flowPara3795"
-         style="font-size:48px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#4d4d4d;fill-opacity:1;font-family:Myriad Pro;-inkscape-font-specification:Myriad Pro">A Community Python Library for Astronomy</flowPara></flowRoot>  </g>
-</svg>
diff --git a/docs/logo/astropylogo32.png b/docs/logo/astropylogo32.png
deleted file mode 100644
index d0e320d..0000000
Binary files a/docs/logo/astropylogo32.png and /dev/null differ
diff --git a/docs/logo/astropylogo64.png b/docs/logo/astropylogo64.png
deleted file mode 100644
index 691b3cb..0000000
Binary files a/docs/logo/astropylogo64.png and /dev/null differ
diff --git a/docs/logo/credits b/docs/logo/credits
deleted file mode 100644
index 7c57fc6..0000000
--- a/docs/logo/credits
+++ /dev/null
@@ -1 +0,0 @@
-The Astropy logo was designed by Kyle Barbary
diff --git a/docs/nddata/index.rst b/docs/nddata/index.rst
index 2bb555d..ae0e796 100644
--- a/docs/nddata/index.rst
+++ b/docs/nddata/index.rst
@@ -9,53 +9,53 @@ Introduction
 
 `astropy.nddata` provides the `~astropy.nddata.nddata.NDData`
 class and related tools to manage n-dimensional array-based data (e.g.
-CCD images, IFU Data, grid-based simulation data, ...). This is more than
+CCD images, IFU data, grid-based simulation data, ...). This is more than
 just `numpy.ndarray` objects, because it provides metadata that cannot
 be easily provided by a single array.
 
 This subpackage also provides new convolution routines that differ from
 Scipy in that they offer a proper treatment of NaN values.
 
+.. note:: The `~astropy.nddata.nddata.NDData` class is still under
+          development, and support for WCS and units is not yet implemented.
 
 Getting started
 ===============
 
-The `~astropy.nddata.nddata.NDData` class is still under development, and
-many of it's more advanced features are not yet implemented.  It already
-functions as an array container with metadata, however::
+An `~astropy.nddata.nddata.NDData` object can be instantiated by passing it an
+n-dimensional Numpy array::
 
     >>> from astropy.nddata import NDData
-    >>> ndd = NDData(mydataarray, error=myerrorarray)
-    >>> ndd['Exposure time(s)'] = 5
+    >>> array = np.random.random((12, 12, 12))  # a random 3-dimensional array
+    >>> ndd = NDData(array)
 
-You can, also make use of the new convolution routines. For example, if your
-data is 1D, you might smooth it by a gaussian kernel by doing::
+This object has a few attributes in common with Numpy:
 
-    >>> from astropy.nddata import convolve, make_kernel
-    >>> kernel = make_kernel((9,), 1.5, 'gaussian')
-    >>> ndd.data = convolve(ndd.data, kernel)
+    >>> ndd.ndim
+    3
+    >>> ndd.shape
+    (12, 12, 12)
+    >>> ndd.dtype
+    dtype('float64')
 
-The convolution routines can also be used on bare arrays.
+The underlying Numpy array can be accessed via the `data` attribute::
 
-`~astropy.nddata.nddata.NDData` objects can also be easily converted to
-numpy arrays::
+    >>> ndd.data
+    array([[[ 0.05621944,  0.85569765,  0.71609697, ...,  0.76049288,
+    ...
 
-    >>> import numpy as np
-    >>> arr = np.array(ndd)
-    >>> np.all(arr == mydataarray)
-    True
+Values can be masked using the `mask` attribute, which should be a boolean
+Numpy array with the same dimensions as the data, e.g.::
 
-If a `mask` is defined, this will result in a `~numpy.ma.MaskedArray`, so
-in all cases a useable `numpy.ndarray` or subclass will result. This allows
-straightforward plotting of `~astropy.nddata.nddata.NDData` objects with 1-
-and 2-dimensional datasets using `matplotlib`::
+     >>> ndd.mask = ndd.data > 0.9
 
-    >>> from matplotlib import pyplot as plt
-    >>> plt.plot(ndd)
-
-This works because the `matplotlib` plotting functions automatically convert
-their inputs using `numpy.array`.
+A mask value of `True` indicates a value that should be ignored, while a mask
+value of `False` indicates a valid value.
 
+Similarly, attributes are available to store generic meta-data, flags, and
+uncertainties, and the `~astropy.nddata.nddata.NDData` class includes methods to
+combine datasets with arithmetic operations (which include uncertainties propagation).
+These are described in :doc:`nddata`.
 
 Using `nddata`
 ==============
@@ -63,7 +63,9 @@ Using `nddata`
 .. toctree::
    :maxdepth: 2
 
+   nddata.rst
    convolution.rst
+   subclassing.rst
 
 Reference/API
 =============
diff --git a/docs/nddata/nddata.rst b/docs/nddata/nddata.rst
new file mode 100644
index 0000000..c9ea24f
--- /dev/null
+++ b/docs/nddata/nddata.rst
@@ -0,0 +1,142 @@
+NDData overview
+===============
+
+Initializing
+------------
+
+An `~astropy.nddata.nddata.NDData` object can be instantiated by passing it an
+n-dimensional Numpy array::
+
+    >>> from astropy.nddata import NDData
+    >>> array = np.random.random((12, 12, 12))  # a random 3-dimensional array
+    >>> ndd = NDData(array)
+
+or by passing it an `~astropy.nddata.nddata.NDData` object:
+
+    >>> ndd1 = NDData(array)
+    >>> ndd2 = NDData(ndd1)
+
+
+This object has a few attributes in common with Numpy:
+
+    >>> ndd.ndim
+    3
+    >>> ndd.shape
+    (12, 12, 12)
+    >>> ndd.dtype
+    dtype('float64')
+
+The underlying Numpy array can be accessed via the `data` attribute::
+
+    >>> ndd.data
+    array([[[ 0.05621944,  0.85569765,  0.71609697, ...,  0.76049288,
+    ...
+
+Mask
+----
+
+Values can be masked using the `mask` attribute, which should be a boolean
+Numpy array with the same dimensions as the data, e.g.::
+
+     >>> ndd.mask = ndd.data > 0.9
+
+A mask value of `True` indicates a value that should be ignored, while a mask
+value of `False` indicates a valid value.
+
+Flags
+-----
+
+Values can be assigned one or more flags. The `flags` attribute is used to
+store either a single Numpy array (of any type) with dimensions matching that
+of the data, or a `~astropy.nddata.flag_collection.FlagCollection`, which is
+essentially a dictionary of Numpy arrays (of any type) with the same shape as
+the data. The following example demonstrates setting a single set of integer
+flags::
+
+    >>> ndd.flags = np.zeros(ndd.shape)
+    >>> ndd.flags[ndd.data < 0.1] = 1
+    >>> ndd.flags[ndd.data < 0.01] = 2
+
+but one can also have multiple flag layers with different types::
+
+    >>> from astropy.nddata import FlagCollection
+    >>> ndd.flags = FlagCollection(shape=(12, 12, 12))
+    >>> ndd.flags['photometry'] = np.zeros(ndd.shape, dtype=str)
+    >>> ndd.flags['photometry'][ndd.data > 0.9] = 's'
+    >>> ndd.flags['cosmic_rays'] = np.zeros(ndd.shape, dtype=int)
+    >>> ndd.flags['cosmic_rays'][ndd.data > 0.99] = 99
+
+and flags can easily be used to set the mask::
+
+    >>> ndd.mask = ndd.flags['cosmic_rays'] == 99
+
+Uncertainties
+-------------
+
+`~astropy.nddata.nddata.NDData` objects have an `uncertainty` attribute that can be
+used to set the uncertainty on the data values. This is done by using classes
+to represent the uncertainties of a given type. For example, to set standard
+deviation uncertainties on the pixel values, you can do::
+
+    >>> from astropy.nddata import StdDevUncertainty
+    >>> ndd.uncertainty = StdDevUncertainty(np.ones((12, 12, 12)) * 0.1)
+
+.. note:: For information on creating your own uncertainty classes,
+          see :doc:`subclassing`.
+
+Arithmetic
+----------
+
+Provided that the world coordinate system (WCS), units, and shape match, two
+:class:`~astropy.nddata.nddata.NDData` instances can be added or subtracted
+from each other, with uncertainty propagation, creating a new
+:class:`~astropy.nddata.nddata.NDData` object::
+
+    ndd3 = ndd1.add(ndd2)
+    ndd4 = ndd1.subtract(ndd2)
+
+The purpose of the :meth:`~astropy.nddata.nddata.NDData.add` and
+:meth:`~astropy.nddata.nddata.NDData.subtract` methods is to allow the
+combination of two data objects that have common WCS, units, and shape, with
+consistent behavior for masks and flags, and with a framework to propagate
+uncertainties. These methods are intended for use by sub-classes and functions
+that deal with more complex combinations.
+
+.. warning:: Uncertainty propagation is still experimental, and does not take into
+             account correlated uncertainties.
+
+Meta-data
+---------
+
+The :class:`~astropy.nddata.nddata.NDData` class includes a ``meta`` attribute
+that defaults to an empty dictionary, and can be used to set overall meta-data
+for the dataset::
+
+    ndd.meta['exposure_time'] = 340.
+    ndd.meta['filter'] = 'J'
+
+Elements of the meta-data dictionary can be set to any valid Python object::
+
+    ndd.meta['history'] = ['calibrated', 'aligned', 'flat-fielded']
+
+Converting to Numpy arrays
+--------------------------
+
+`~astropy.nddata.nddata.NDData` objects can also be easily converted to
+numpy arrays::
+
+    >>> import numpy as np
+    >>> arr = np.array(ndd)
+    >>> np.all(arr == mydataarray)
+    True
+
+If a `mask` is defined, this will result in a `~numpy.ma.MaskedArray`, so
+in all cases a useable `numpy.ndarray` or subclass will result. This allows
+straightforward plotting of `~astropy.nddata.nddata.NDData` objects with 1-
+and 2-dimensional datasets using `matplotlib`::
+
+    >>> from matplotlib import pyplot as plt
+    >>> plt.plot(ndd)
+
+This works because the `matplotlib` plotting functions automatically convert
+their inputs using `numpy.array`.
\ No newline at end of file
diff --git a/docs/nddata/subclassing.rst b/docs/nddata/subclassing.rst
new file mode 100644
index 0000000..07a6233
--- /dev/null
+++ b/docs/nddata/subclassing.rst
@@ -0,0 +1,58 @@
+Subclassing `~astropy.nddata.nddata.NDData` and `~astropy.nddata.nderror.NDUncertainty`
+=======================================================================================
+
+Subclassing `~astropy.nddata.nderror.NDUncertainty`
+---------------------------------------------------
+
+New error classes should sub-class from `~astropy.nddata.nderror.NDUncertainty`, and
+should provide methods with the following API::
+
+   class MyUncertainty(NDUncertainty):
+
+       def propagate_add(self, other_nddata, result_data):
+           ...
+           result_uncertainty = MyUncertainty(...)
+           return result_uncertainty
+
+       def propagate_subtract(self, other_nddata, result_data):
+           ...
+           result_uncertainty = MyUncertainty(...)
+           return result_uncertainty
+
+       def propagate_multiply(self, other_nddata, result_data):
+           ...
+           result_uncertainty = MyUncertainty(...)
+           return result_uncertainty
+
+       def propagate_divide(self, other_nddata, result_data):
+           ...
+           result_uncertainty = MyUncertainty(...)
+           return result_uncertainty
+
+All error sub-classes inherit an attribute ``self.parent_nddata`` that is
+automatically set to the parent `~astropy.nddata.nddata.NDData` object that they
+are attached to. The arguments passed to the error propagation methods are
+``other_nddata``, which is the `~astropy.nddata.nddata.NDData` object that is being
+combined with ``self.parent_nddata``, and ``result_data``, which is a Numpy
+array that contains the data array after the arithmetic operation. All these
+methods should return an error instance ``result_uncertainty``, and should not
+modify ``parent_nddata`` directly. For subtraction and division, the order of
+the operations is ``parent_nddata - other_nddata`` and ``parent_nddata /
+other_nddata``.
+
+To make it easier and clearer to code up the error propagation, you can use
+variables with more explicit names, e.g::
+
+   class MyUncertainty(NDUncertainty):
+
+       def propogate_add(self, other_nddata, result_data):
+
+           left_uncertainty = self.parent.uncertainty.array
+           right_uncertainty = other_nddata.uncertainty.array
+
+           ...
+           
+Note that the above example assumes that the errors are stored in an ``array``
+attribute, but this does not have to be the case.
+
+For an example of a complete implementation, see `~astropy.nddata.nduncertainty.StdDevUncertainty`.
\ No newline at end of file
diff --git a/docs/stability.rst b/docs/stability.rst
new file mode 100644
index 0000000..af72cae
--- /dev/null
+++ b/docs/stability.rst
@@ -0,0 +1,218 @@
+******************************
+Current status of sub-packages
+******************************
+
+Astropy has benefited from the addition of widely tested legacy code, as well
+as new development, resulting in variations in stability accross
+sub-packages. This document summarises the current status of the Astropy
+sub-packages, so that users understand where they might expect changes in
+future, and which sub-packages they can safely use for production code.
+
+Note that until version 1.0, even sub-packages considered *Mature* could
+undergo some user interface changes as we work to integrate the packages
+better. Thus, we cannot guarantee complete backward-compatibility between
+versions at this stage.
+
+.. |planned| image:: _static/planned.png
+
+.. |dev| image:: _static/dev.png
+
+.. |stable| image:: _static/stable.png
+
+.. |mature| image:: _static/mature.png
+
+The classification is as follows:
+
+.. raw:: html
+
+    <table align='center'>
+      <tr>
+        <td align='center'><img src='_images/planned.png'></td>
+        <td>Planned</td>
+      </tr>
+      <tr>
+        <td align='center'><img src='_images/dev.png'></td>
+        <td>Actively developed, be prepared for possible significant changes</td>
+      </tr>
+      <tr>
+        <td align='center'><img src='_images/stable.png'></td>
+        <td>Reasonably stable, no major changes likely</td>
+      </tr>
+      <tr>
+        <td align='center'><img src='_images/mature.png'></td>
+        <td>Mature</td>
+      </tr>
+    </table>
+
+The current planned and existing sub-packages are:
+
+.. raw:: html
+
+    <table border="1" class="docutils" align='center'>
+        <tr>
+            <th class="head">
+                Sub-Package
+            </th>
+            <th class="head">
+                 
+            </th>
+            <th class="head">
+                Comments
+            </th>
+        </tr>
+        <tr>
+            <td>
+                astropy.constants
+            </td>
+            <td align='center'>
+                <img alt="dev" src="_images/dev.png">
+            </td>
+            <td>
+                Constants have been changed to <tt class="docutils literal"><span class="pre">Quantity</span></tt> objects in v0.2.
+            </td>
+        </tr>
+        <tr>
+            <td>
+                astropy.coordinates
+            </td>
+            <td align='center'>
+                <img alt="dev" src="_images/dev.png">
+            </td>
+            <td>
+                New in v0.2
+            </td>
+        </tr>
+        <tr>
+            <td>
+                astropy.cosmology
+            </td>
+            <td align='center'>
+                <img alt="stable" src="_images/stable.png">
+            </td>
+            <td>
+                Incremental improvements since v0.1, but mostly stable API.
+            </td>
+        </tr>
+        <tr>
+            <td>
+                astropy.io.ascii
+            </td>
+            <td align='center'>
+                <img alt="mature" src="_images/mature.png">
+            </td>
+            <td>
+                Originally developed as <tt class="docutils literal"><span class="pre">asciitable</span></tt>, and has maintained a stable API.
+            </td>
+        </tr>
+        <tr>
+            <td>
+                astropy.io.fits
+            </td>
+            <td align='center'>
+                <img alt="mature" src="_images/mature.png">
+            </td>
+            <td>
+                Originally developed as <tt class="docutils literal"><span class="pre">pyfits</span></tt>, and retains an API consistent with the standalone version.
+            </td>
+        </tr>
+        <tr>
+            <td>
+                astropy.io.votable
+            </td>
+            <td align='center'>
+                <img alt="mature" src="_images/mature.png">
+            </td>
+            <td>
+                Originally developed as <tt class="docutils literal"><span class="pre">vo.table</span></tt>, and has a stable API.
+            </td>
+        </tr>
+        <tr>
+            <td>
+                astropy.photometry
+            </td>
+            <td align='center'>
+                <img alt="planned" src="_images/planned.png">
+            </td>
+            <td>
+                 
+            </td>
+        </tr>
+        <tr>
+            <td>
+                astropy.stats
+            </td>
+            <td align='center'>
+                <img alt="dev" src="_images/dev.png">
+            </td>
+            <td>
+                Still in development, and does not yet contain much functionality.
+            </td>
+        </tr>
+        <tr>
+            <td>
+                astropy.table
+            </td>
+            <td align='center'>
+                <img alt="stable" src="_images/stable.png">
+            </td>
+            <td>
+                Incremental improvements since v0.1, but mostly stable API.
+            </td>
+        </tr>
+        <tr>
+            <td>
+                astropy.time
+            </td>
+            <td align='center'>
+                <img alt="stable" src="_images/stable.png">
+            </td>
+            <td>
+                Incremental improvements since v0.1, but mostly stable API.
+            </td>
+        </tr>
+        <tr>
+            <td>
+                astropy.units
+            </td>
+            <td align='center'>
+                <img alt="stable" src="_images/stable.png">
+            </td>
+            <td>
+                New in v0.2. Adapted from <tt class="docutils literal"><span class="pre">pnbody</span></tt> and integrated into Astropy.
+            </td>
+        </tr>
+        <tr>
+            <td>
+                astropy.utils
+            </td>
+            <td align='center'>
+                <img alt="dev" src="_images/dev.png">
+            </td>
+            <td>
+                This sub-package contains mostly utilities destined for use in other parts of Astropy, and is not yet stable.
+            </td>
+        </tr>
+        <tr>
+            <td>
+                astropy.vo
+            </td>
+            <td align='center'>
+                <img alt="planned" src="_images/planned.png">
+            </td>
+            <td>
+                 
+            </td>
+        </tr>
+        <tr>
+            <td>
+                astropy.wcs
+            </td>
+            <td align='center'>
+                <img alt="stable" src="_images/stable.png">
+            </td>
+            <td>
+                Originally developed as <tt class="docutils literal"><span class="pre">pywcs</span></tt>, and has a stable API for now. However, there are plans to generalize the WCS interface to accommodate non-FITS WCS transformations, and this may lead to small changes in the user interface.
+            </td>
+        </tr>
+    </table>
+
diff --git a/docs/stats/index.rst b/docs/stats/index.rst
new file mode 100644
index 0000000..40a46a7
--- /dev/null
+++ b/docs/stats/index.rst
@@ -0,0 +1,51 @@
+.. _tools:
+
+***************************************
+Astrostatistics Tools (`astropy.stats`)
+***************************************
+
+Introduction
+============
+
+The `astropy.stats` package holds statsitical functions or algorithms used
+in astronomy and astropy.
+
+
+Getting Started
+===============
+
+The current tools are fairly self-contained, and include relevant examples in
+their docstrings.  For example, see `~astropy.tools.misc.sigma_clip`.
+
+
+
+.. NOTE TO FUTURE DEVS: When this subpackage gets more populated, it will be
+.. wise to add a section of the form shown below.  Be sure to move this file
+.. to docs/tools/index.rst and update docs/index.rst to tools/index when
+.. that happens.
+
+.. Using packagename
+.. -----------------
+
+.. For more complicated packages that require multiple documents, this
+.. should just be a table of contents referencing those documents:
+
+.. .. toctree::
+..     packagename/subdoc1
+..     packagename/subdoc2
+..     packagename/subdoc3
+
+
+See Also
+========
+
+* :mod:`scipy.stats`
+    This scipy package contains a variety of useful statistical functions and
+    classes.  The functionality in `astropy.stats` is intended to supplement
+    this, *not* replace it.
+
+
+Reference/API
+=============
+
+.. automodapi:: astropy.stats
diff --git a/docs/table/access_table.rst b/docs/table/access_table.rst
index 8734c8a..3a781e9 100644
--- a/docs/table/access_table.rst
+++ b/docs/table/access_table.rst
@@ -9,7 +9,7 @@ Accessing the table properties and data is straightforward and is generally cons
 the basic interface for `numpy` structured arrays.
 
 Quick overview
---------------
+^^^^^^^^^^^^^^
 
 For the impatient, the code below shows the basics of accessing table data.
 Where relevant there is a comment about what sort of object.  Except where
@@ -18,27 +18,27 @@ update table data or properties.
 In cases where is returned and how
 the data contained in that object relate to the original table data
 (i.e. whether it is a copy or reference, see :ref:`copy_versus_reference`).
-  
+
 **Make table**
 ::
-  
+
   from astropy.table import Table
   import numpy as np
-  
+
   arr = np.arange(15).reshape(5, 3)
   t = Table(arr, names=('a', 'b', 'c'), meta={'keywords': {'key1': 'val1'}})
-  
+
 **Table properties**
 ::
-  
+
   t.columns   # Dict of table columns
   t.colnames  # List of column names
   t.meta      # Dict of meta-data
   len(t)      # Number of table rows
-  
+
 **Access table data**
 ::
-  
+
   t['a']       # Column 'a'
   t['a'][1]    # Row 1 of column 'a'
   t[1]         # Row obj for with row 1 values
@@ -69,20 +69,20 @@ the data contained in that object relate to the original table data
 
 
 Details
--------
+^^^^^^^
 
 For all the following examples it is assumed that the table has been created as below::
 
   >>> from astropy.table import Table, Column
   >>> import numpy as np
-  
+
   >>> arr = np.arange(15).reshape(5, 3)
   >>> t = Table(arr, names=('a', 'b', 'c'), meta={'keywords': {'key1': 'val1'}})
   >>> t['a'].format = "%6.3f"  # print as a float with 3 digits after decimal point
   >>> t['a'].units = 'm sec^-1'
   >>> t['a'].description = 'unladen swallow velocity'
   >>> print t
-    a     b   c 
+    a     b   c
   ------ --- ---
    0.000   1   2
    3.000   4   5
@@ -91,7 +91,7 @@ For all the following examples it is assumed that the table has been created as
   12.000  13  14
 
 Accessing properties
-^^^^^^^^^^^^^^^^^^^^
+""""""""""""""""""""
 
 The code below shows accessing the table columns as a |TableColumns| object,
 getting the column names, table meta-data, and number of table rows.  The table
@@ -100,19 +100,19 @@ meta-data is simply an ordered dictionary (OrderedDict_) by default.
 
   >>> t.columns
   <TableColumns names=('a','b','c')>
-  
+
   >>> t.colnames
   ['a', 'b', 'c']
-  
+
   >>> t.meta  # Dict of meta-data
   {'keywords': {'key1': 'val1'}}
-  
+
   >>> len(t)
   5
 
 
 Accessing data
-^^^^^^^^^^^^^^
+""""""""""""""
 
 As expected one can access a table column by name and get an element from that
 column with a numerical index::
@@ -123,7 +123,7 @@ column with a numerical index::
 
   >>> t['a'][1]  # Row 1 of column 'a'
   3
-  
+
 When a table column is printed, either with ``print`` or via the ``str()``
 built-in function, it is formatted according to the ``format`` attribute (see
 :ref:`table_format_string`)::
@@ -137,15 +137,15 @@ Likewise a table row and a column from that row can be selected::
   <Row 1 of table
    values=(3, 4, 5)
    dtype=[('a', '<i8'), ('b', '<i8'), ('c', '<i8')]>
-  
+
   >>> t[1]['a']  # Column 'a' of row 1
   3
-  
+
 A |Row| object has the same columns and meta-data as its parent table::
 
   >>> t[1].columns
   <TableColumns names=('a','b','c')>
-  
+
   >>> t[1].colnames
   ['a', 'b', 'c']
 
@@ -156,9 +156,9 @@ meta-data and column definitions are copied.
 
   >>> t[2:5]  # Table object with rows 2:5 (reference)
   <Table rows=3 names=('a','b','c')>
-  array([(6, 7, 8), (9, 10, 11), (12, 13, 14)], 
+  array([(6, 7, 8), (9, 10, 11), (12, 13, 14)],
         dtype=[('a', '<i8'), ('b', '<i8'), ('c', '<i8')])
-  
+
 It is possible to select table rows with an array of indexes or by providing
 specifying multiple column names.  This returns a copy of the original table
 for the selected rows.  ::
@@ -169,14 +169,14 @@ for the selected rows.  ::
    3.000   4   5
    9.000  10  11
   12.000  13  14
-  
+
   >>> print t[np.array([1, 3, 4])]  # Table object with rows 1, 3, 4 (copy)
     a     b   c
   ------ --- ---
    3.000   4   5
    9.000  10  11
   12.000  13  14
-  
+
   >>> print t['a', 'c']  # Table with cols 'a', 'c' (copy)
     a     c
   ------ ---
@@ -194,7 +194,7 @@ structured array by creating a copy or reference with ``np.array``::
 
 
 Formatted printing
-^^^^^^^^^^^^^^^^^^
+""""""""""""""""""
 
 The values in a table or column can be printed or retrieved as a formatted
 table using one of several methods:
@@ -205,7 +205,7 @@ table using one of several methods:
   through table values.
 - Table :func:`~astropy.table.table.Table.pprint` or Column
   :func:`~astropy.table.table.Column.pprint` methods to print a formatted version of
-  the table to the screen.  
+  the table to the screen.
 - Table :func:`~astropy.table.table.Table.pformat` or Column
   :func:`~astropy.table.table.Column.pformat` methods to return the formatted table
   or column as a list of fixed-width strings.  This could be used as a quick
@@ -243,7 +243,7 @@ too large then rows and/or columns are cut from the middle so it fits.  For exam
   2970 2971 2972 2973 2974 2975 2976 ...  2994  2995  2996  2997  2998  2999
 
 more() method
-"""""""""""""
+'''''''''''''
 
 In order to browse all rows of a table or column use the Table
 :func:`~astropy.table.table.Table.more` or Column :func:`~astropy.table.table.Column.more`
@@ -262,7 +262,7 @@ supported navigation keys are:
 |  **h** : print this help
 
 pprint() method
-"""""""""""""""
+'''''''''''''''
 
 In order to fully control the print output use the Table
 :func:`~astropy.table.table.Table.pprint` or Column
@@ -278,7 +278,7 @@ meaning as shown below::
   >>> t['col29'].units = 'kg sec m**-2'
 
   >>> t.pprint(max_lines=8, max_width=40)
-      col0         col1    ... col29 
+      col0         col1    ... col29
   ------------ ----------- ... ------
   0.000000e+00    1.000000 ...   29.0
   3.000000e+01   31.000000 ...   59.0
@@ -288,7 +288,7 @@ meaning as shown below::
   2.970000e+03 2971.000000 ... 2999.0
 
   >>> t.pprint(max_lines=8, max_width=40, show_units=True)
-      col0     ...    col29    
+      col0     ...    col29
      km**2     ... kg sec m**-2
   ------------ ... ------------
   0.000000e+00 ...         29.0
@@ -315,7 +315,7 @@ table in this example one sees 6 lines of wrapped output like the following::
 
       col0         col1     col2   col3   col4   col5   col6   col7   col8   col
   9  col10  col11  col12  col13  col14  col15  col16  col17  col18  col19  col20
-    col21  col22  col23  col24  col25  col26  col27  col28  col29 
+    col21  col22  col23  col24  col25  col26  col27  col28  col29
   ------------ ----------- ------ ------ ------ ------ ------ ------ ------ ----
   -- ------ ------ ------ ------ ------ ------ ------ ------ ------ ------ -----
   - ------ ------ ------ ------ ------ ------ ------ ------ ------
@@ -337,7 +337,7 @@ For columns the syntax and behavior of
 ``max_width`` keyword argument::
 
   >>> t['col3'].pprint(max_lines=8)
-   col3 
+   col3
   ------
      3.0
     33.0
@@ -347,7 +347,7 @@ For columns the syntax and behavior of
   2973.0
 
 pformat() method
-""""""""""""""""
+''''''''''''''''
 
 In order to get the formatted output for manipulation or writing to a file use
 the Table :func:`~astropy.table.table.Table.pformat` or Column
@@ -360,10 +360,10 @@ the Table :func:`~astropy.table.table.Table.pformat` or Column
   ['  col3', '------', '   3.0', '  33.0', '  63.0', '   ...', '2943.0', '2973.0']
 
 Multidimensional columns
-""""""""""""""""""""""""
+''''''''''''''''''''''''
 
 If a column has more than one dimension then each element of the column is
-itself an array.  In the example below there are 3 rows, each of which is a 
+itself an array.  In the example below there are 3 rows, each of which is a
 ``2 x 2`` array.  The formatted output for such a column shows only the first
 and last value of each row element and indicates the array dimensions in the
 column name header::
@@ -371,11 +371,11 @@ column name header::
   >>> from astropy.table import Table, Column
   >>> import numpy as np
   >>> t = Table()
-  >>> arr = [ np.array([[ 1,  2],   
-  ...                   [10, 20]]), 
-  ...         np.array([[ 3,  4],   
-  ...                   [30, 40]]), 
-  ...         np.array([[ 5,  6],   
+  >>> arr = [ np.array([[ 1,  2],
+  ...                   [10, 20]]),
+  ...         np.array([[ 3,  4],
+  ...                   [30, 40]]),
+  ...         np.array([[ 5,  6],
   ...                   [50, 60]]) ]
   >>> t.add_column(Column('a', arr))
   >>> t['a'].shape
diff --git a/docs/table/construct_table.rst b/docs/table/construct_table.rst
index d1256c5..064740a 100644
--- a/docs/table/construct_table.rst
+++ b/docs/table/construct_table.rst
@@ -7,20 +7,20 @@ Constructing a table
 
 There is great deal of flexibility in the way that a table can be initially
 constructed.  Details on the inputs to the |Table|
-constructor are in the `Initialization Details`_ section.  However, the 
+constructor are in the `Initialization Details`_ section.  However, the
 easiest way to understand how to make a table is by example.
 
 Examples
---------
+^^^^^^^^
 
 Much of the flexibility lies in the types of data structures
 which can be used to initialize the table data.  The examples below show how to
 create a table from scratch with no initial data, create a table with a list of
 columns, a dictionary of columns, or from `numpy` arrays (either structured or
-homogeneous).  
+homogeneous).
 
 Setup
-^^^^^
+"""""
 For the following examples you need to import the |Table| and |Column| classes
 along with the `numpy` package::
 
@@ -28,12 +28,12 @@ along with the `numpy` package::
   >>> import numpy as np
 
 Creating from scratch
-^^^^^^^^^^^^^^^^^^^^^
+"""""""""""""""""""""
 A Table can be created without any initial input data or even without any
 initial columns.  This is useful for building tables dynamically if the initial
-size, columns, or data are not known.  
+size, columns, or data are not known.
 
-.. Note:: 
+.. Note::
    Adding columns or rows requires making a new copy of the entire
    table table each time, so in the case of large tables this may be slow.
 
@@ -50,7 +50,7 @@ size, columns, or data are not known.
 
 
 List input
-^^^^^^^^^^
+""""""""""
 A typical case is where you have a number of data columns with the same length
 defined in different variables.  These might be Python lists or `numpy` arrays
 or a mix of the two.  These can be used to create a |Table| by putting the column
@@ -66,7 +66,7 @@ keyword or they will be auto-generated as ``col<N>``.
   >>> t = Table([a, b, c], names=('a', 'b', 'c'))
   >>> t
   <Table rows=2 names=('a','b','c')>
-  array([(1, 2.0, 'x'), (4, 5.0, 'y')], 
+  array([(1, 2.0, 'x'), (4, 5.0, 'y')],
         dtype=[('a', '<i8'), ('b', '<f8'), ('c', '|S1')])
 
 **Make a new table using columns from the first table**
@@ -76,7 +76,7 @@ and putting this into a Python list, e.g. ``[ t['c'], t['a'] ]``::
 
   >>> Table([t['c'], t['a']])
   <Table rows=2 names=('c','a')>
-  array([('x', 1), ('y', 4)], 
+  array([('x', 1), ('y', 4)],
         dtype=[('c', '|S1'), ('a', '<i8')])
 
 **Make a new table using expressions involving columns**
@@ -87,7 +87,7 @@ new table with modified column values::
 
   >>> Table([t['a']**2, t['b'] + 10])
   <Table rows=2 names=('a','b')>
-  array([(1, 12.0), (16, 15.0)], 
+  array([(1, 12.0), (16, 15.0)],
         dtype=[('a', '<i8'), ('b', '<f8')])
 
 
@@ -102,22 +102,22 @@ of different data types to initialize a table::
   >>> arr = (a, b, c)
   >>> Table(arr)  # Data column named "c" has a name "axis" that table
   <Table rows=2 names=('col0','col1','axis')>
-  array([(1, [2, 3], 'x'), (4, [5, 6], 'y')], 
+  array([(1, [2, 3], 'x'), (4, [5, 6], 'y')],
         dtype=[('col0', '<i8'), ('col1', '<i8', (2,)), ('axis', '|S1')])
 
 Notice that in the third column the existing column name ``'axis'`` is used.
 
 Dictionary input
-^^^^^^^^^^^^^^^^
+""""""""""""""""
 A dictionary of column data can be used to initialize a |Table|.
 
   >>> arr = {'a': [1, 4],
   ...        'b': [2.0, 5.0],
   ...        'c': ['x', 'y']}
-  >>> 
+  >>>
   >>> Table(arr)
   <Table rows=2 names=('a','c','b')>
-  array([(1, 'x', 2.0), (4, 'y', 5.0)], 
+  array([(1, 'x', 2.0), (4, 'y', 5.0)],
         dtype=[('a', '<i8'), ('c', '|S1'), ('b', '<f8')])
 
 **Specify the column order and optionally the data types**
@@ -125,7 +125,7 @@ A dictionary of column data can be used to initialize a |Table|.
 
   >>> Table(arr, names=('a', 'b', 'c'), dtypes=('f4', 'i4', 'S2'))
   <Table rows=2 names=('a','b','c')>
-  array([(1.0, 2, 'x'), (4.0, 5, 'y')], 
+  array([(1.0, 2, 'x'), (4.0, 5, 'y')],
         dtype=[('a', '<f4'), ('b', '<i4'), ('c', '|S2')])
 
 **Different types of column data**
@@ -137,7 +137,7 @@ The input column data can be any data type that can initialize a |Column| object
              'c': Column('axis', ['x', 'y'])}
   >>> Table(arr, names=('a', 'b', 'c'))
   <Table rows=2 names=('a','b','c')>
-  array([(1, [2, 3], 'x'), (4, [5, 6], 'y')], 
+  array([(1, [2, 3], 'x'), (4, [5, 6], 'y')],
         dtype=[('a', '<i8'), ('b', '<i8', (2,)), ('c', '|S1')])
 
 Notice that the key ``'c'`` takes precendence over the existing column name
@@ -158,24 +158,24 @@ column where each row element is itself a 2-element array.
 
 
 NumPy structured array
-^^^^^^^^^^^^^^^^^^^^^^
+""""""""""""""""""""""
 The structured array is the standard mechanism in `numpy` for storing heterogenous
 table data.  Most scientific I/O packages that read table files (e.g.
 `PyFITS <http://www.stsci.edu/resources/software_hardware/pyfits>`_,
 `vo.table <http://stsdas.stsci.edu/astrolib/vo/html/intro_table.html>`_,
-`asciitable <http://cxc.harvard.edu/contrib/asciitable/>`_) 
+`asciitable <http://cxc.harvard.edu/contrib/asciitable/>`_)
 will return the table in an object that is based on the structured array.
 A structured array can be created using::
 
   >>> arr = np.array([(1, 2.0, 'x'),
   ...                 (4, 5.0, 'y')],
   ...                dtype=[('a', 'i8'), ('b', 'f8'), ('c', 'S2')])
-  
+
 From ``arr`` it is simple to create the corresponding |Table| object::
 
   >>> Table(arr)
   <Table rows=2 names=('a','b','c')>
-  array([(1, 2.0, 'x'), (4, 5.0, 'y')], 
+  array([(1, 2.0, 'x'), (4, 5.0, 'y')],
         dtype=[('a', '<i8'), ('b', '<f8'), ('c', '|S2')])
 
 Note that in the above example and most the following ones we are creating a
@@ -192,7 +192,7 @@ The column names can be changed from the original values by providing the
 
   >>> Table(arr, names=('a_new', 'b_new', 'c_new'))
   <Table rows=2 names=('a_new','b_new','c_new')>
-  array([(1, 2.0, 'x'), (4, 5.0, 'y')], 
+  array([(1, 2.0, 'x'), (4, 5.0, 'y')],
         dtype=[('a_new', '<i8'), ('b_new', '<f8'), ('c_new', '|S2')])
 
 **New data types**
@@ -201,18 +201,18 @@ Likewise the data type for each column can by changed with ``dtypes``::
 
   >>> Table(arr, dtypes=('f4', 'i4', 'S4'))
   <Table rows=2 names=('a','b','c')>
-  array([(1.0, 2, 'x'), (4.0, 5, 'y')], 
+  array([(1.0, 2, 'x'), (4.0, 5, 'y')],
         dtype=[('a', '<f4'), ('b', '<i4'), ('c', '|S4')])
 
   >>> Table(arr, names=('a_new', 'b_new', 'c_new'), dtypes=('f4', 'i4', 'S4'))
   <Table rows=2 names=('a_new','b_new','c_new')>
-  array([(1.0, 2, 'x'), (4.0, 5, 'y')], 
+  array([(1.0, 2, 'x'), (4.0, 5, 'y')],
         dtype=[('a_new', '<f4'), ('b_new', '<i4'), ('c_new', '|S4')])
 
 
 
 NumPy homogeneous array
-^^^^^^^^^^^^^^^^^^^^^^^
+"""""""""""""""""""""""
 A normal `numpy` 2-d array (where all elements have the same type) can be
 converted into a |Table|.  In this case the column names are not specified by
 the data and must either be provided by the user or will be automatically
@@ -225,7 +225,7 @@ generated as ``col<N>`` where ``<N>`` is the column number.
   ...                 [4, 5, 6]])
   >>> Table(arr)
   <Table rows=2 names=('col0','col1','col2')>
-  array([(1, 2, 3), (4, 5, 6)], 
+  array([(1, 2, 3), (4, 5, 6)],
         dtype=[('col0', '<i8'), ('col1', '<i8'), ('col2', '<i8')])
 
 **Column names and types specified**
@@ -233,7 +233,7 @@ generated as ``col<N>`` where ``<N>`` is the column number.
 
   >>> Table(arr, names=('a_new', 'b_new', 'c_new'), dtypes=('f4', 'i4', 'S4'))
   <Table rows=2 names=('a_new','b_new','c_new')>
-  array([(1.0, 2, '3'), (4.0, 5, '6')], 
+  array([(1.0, 2, '3'), (4.0, 5, '6')],
         dtype=[('a_new', '<f4'), ('b_new', '<i4'), ('c_new', '|S4')])
 
 **Referencing the original data**
@@ -250,23 +250,23 @@ that |Table| objects are created.  Any data input that looks like a Python list
 (including a tuple) is considered to be a list of columns.  In contrast an
 homogeneous `numpy` array input is interpreted as a list of rows::
 
-  >>> arr = [[1, 2, 3], 
+  >>> arr = [[1, 2, 3],
   ...        [4, 5, 6]]
   >>> np_arr = np.array(arr)
 
   >>> Table(arr)    # Two columns, three rows
   <Table rows=3 names=('col0','col1')>
-  array([(1, 4), (2, 5), (3, 6)], 
+  array([(1, 4), (2, 5), (3, 6)],
         dtype=[('col0', '<i8'), ('col1', '<i8')])
 
   >>> Table(np_arr)  # Three columns, two rows
   <Table rows=2 names=('col0','col1','col2')>
-  array([(1, 2, 3), (4, 5, 6)], 
+  array([(1, 2, 3), (4, 5, 6)],
         dtype=[('col0', '<i8'), ('col1', '<i8'), ('col2', '<i8')])
 
 This dichotomy is needed to support flexible list input while retaining the
 natural interpretation of 2-d `numpy` arrays where the first index corresponds
-to data "rows" and the second index corresponds to data "columns".  
+to data "rows" and the second index corresponds to data "columns".
 
 If you have a Python list which is structured as a list of data rows, use the
 following trick to effectively transpose into a list of columns for
@@ -280,7 +280,7 @@ initializing a |Table| object::
    >>> t = Table(col_arr)
 
 Table columns
-^^^^^^^^^^^^^
+"""""""""""""
 A new table can be created by selecting a subset of columns in an existing
 table::
 
@@ -288,7 +288,7 @@ table::
   >>> t2 = t['c', 'b', 'a']  # Makes a copy of the data
   >>> print t2
   <Table rows=0 names=('c','b','a')>
-  array([], 
+  array([],
         dtype=[('c', '<f8'), ('b', '<f8'), ('a', '<f8')])
 
 An alternate way to use the ``columns`` attribute (explained in the
@@ -297,17 +297,17 @@ columns by their numerical index or name and supports slicing syntax::
 
   >>> Table(t.columns[0:2])
   <Table rows=0 names=('a','b')>
-  array([], 
+  array([],
         dtype=[('a', '<f8'), ('b', '<f8')])
-  
+
   >>> Table([t.columns[0], t.columns['c']])
   <Table rows=0 names=('a','c')>
-  array([], 
+  array([],
         dtype=[('a', '<f8'), ('c', '<f8')])
 
 
 Initialization Details
-----------------------
+^^^^^^^^^^^^^^^^^^^^^^
 
 A table object is created by initializing a |Table| class
 object with the following arguments, all of which are optional:
@@ -327,7 +327,7 @@ The following subsections provide further detail on the values and options for
 each of the keyword arguments that can be used to create a new |Table| object.
 
 data
-^^^^
+""""
 
 The |Table| object can be initialized with several different forms
 for the ``data`` argument.
@@ -373,7 +373,7 @@ for the ``data`` argument.
     are provided then the corresponding columns are created.
 
 names
-^^^^^
+"""""
 
 The ``names`` argument provides a way to specify the table column names or
 override the existing ones.  By default the column names are either taken
@@ -388,7 +388,7 @@ must then contain each of the keys in the ``data`` dict.  If ``names`` is not
 supplied then the order of columns in the output table is not determinate.
 
 dtypes
-^^^^^^
+""""""
 
 The ``dtypes`` argument provides a way to specify the table column data
 types or override the existing types.  By default the types are either
@@ -403,7 +403,7 @@ must be accompanied by a corresponding ``names`` argument in order to uniquely
 specify the column ordering.
 
 meta
-^^^^
+""""
 
 The ``meta`` argument is simply an object that contains meta-data associated
 with the table.  It is recommended that this object be a dict or
@@ -412,7 +412,7 @@ the standard library ``copy.deepcopy()`` routine.  By default ``meta`` is
 an empty OrderedDict_.
 
 copy
-^^^^
+""""
 
 By default the input ``data`` are copied into a new internal ``np.ndarray``
 object in the Table object.  In the case where ``data`` is either an
@@ -427,7 +427,7 @@ information.
 .. _copy_versus_reference:
 
 Copy versus Reference
----------------------
+^^^^^^^^^^^^^^^^^^^^^
 
 Normally when a new |Table| object is created, the input data are *copied* into
 a new internal array object.  This ensures that if the new table elements are
@@ -474,13 +474,13 @@ the data to a new memory location which would corrupt the input data object.
 
 
 Column and TableColumns classes
--------------------------------
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 There are two classes, |Column| and |TableColumns|, that are useful when
 constructing new tables.
 
 Column
-^^^^^^
+""""""
 
 A |Column| object can be created as follows, where in all cases the column
 ``name`` is required as the first argument and one can optionally provide
@@ -496,7 +496,8 @@ these values:
     Meta-data associated with the column
 
 Initialization options
-""""""""""""""""""""""
+''''''''''''''''''''''
+
 The column data values, shape, and data type are specified in one of two ways:
 
 **Provide a ``data`` value and optionally a ``dtype`` value**
@@ -537,7 +538,8 @@ The column data values, shape, and data type are specified in one of two ways:
 .. _table_format_string:
 
 Format string
-"""""""""""""
+'''''''''''''
+
 The format string controls the output of column values when a table or column
 is printed or written to an ASCII table.  The format string can be either
 "old-style" or "new-style":
@@ -553,7 +555,7 @@ This corresponds to syntax like ``"%.4f" % value`` as documented in
 
 **New-style**
 
-This corresponds to syntax like ``"{:.4f}".format(value)`` as documented in 
+This corresponds to syntax like ``"{:.4f}".format(value)`` as documented in
 `format string syntax
 <http://docs.python.org/library/string.html#format-string-syntax>`_.
 
@@ -565,7 +567,7 @@ Note that in either case any Python format string that formats exactly
 one value is valid, so ``{:.4f} angstroms`` or ``Value: %12.2f`` would both work.
 
 TableColumns
-^^^^^^^^^^^^
+""""""""""""
 
 Each |Table| object has an attribute ``columns`` which is an ordered dictionary
 that stores all of the |Column| objects in the table (see also the `Column`_
@@ -584,7 +586,7 @@ So now look at the ways to select columns from a |TableColumns| object:
 ::
 
   >>> t = Table(names=('a', 'b', 'c', 'd'))
-  
+
   >>> t.columns['d', 'c', 'b']
   <TableColumns names=('d','c','b')>
 
@@ -593,7 +595,7 @@ So now look at the ways to select columns from a |TableColumns| object:
 
   >>> t.columns[0:2]  # Select first two columns
   <TableColumns names=('a','b')>
-  
+
   >>> t.columns[::-1]  # Reverse column order
   <TableColumns names=('d','c','b','a')>
 
@@ -603,7 +605,7 @@ So now look at the ways to select columns from a |TableColumns| object:
   >>> t.columns[1]  # Choose columns by index
   <Column name='b' units=None format=None description=None>
   array([], dtype=float64)
-  
+
   >>> t.columns['b']  # Choose column by name
   <Column name='b' units=None format=None description=None>
   array([], dtype=float64)
diff --git a/docs/table/index.rst b/docs/table/index.rst
index 0faac68..67b0576 100644
--- a/docs/table/index.rst
+++ b/docs/table/index.rst
@@ -17,6 +17,7 @@ notable features of this package are:
 * Initialize a table from a wide variety of input data structures and types.
 * Modify a table by adding or removing columns, changing column names,
   or adding new rows of data.
+* Handle tables containing missing values.
 * Include table and column metadata as flexible data structures.
 * Specify a description, units and output formatting for columns.
 * Interactively scroll through long tables similar to using ``more``.
@@ -25,8 +26,9 @@ notable features of this package are:
 * Create a table by referencing (not copying) an existing `numpy` table.
 
 Currently `astropy.table` is used when reading an ASCII table using
-`astropy.io.ascii`.  Future releases of AstroPy are expected to use the |Table|
-class for other subpackages such as `astropy.io.vo` and `astropy.io.fits`.
+`astropy.io.ascii`.  Future releases of AstroPy are expected to use
+the |Table| class for other subpackages such as `astropy.io.votable`
+and `astropy.io.fits`.
 
 Getting Started
 ===============
@@ -53,7 +55,12 @@ about the table values and column definitions as follows::
   array([(1, 2.0, 'x'), (4, 5.0, 'y'), (5, 8.2, 'z')],
         dtype=[('a', '<i8'), ('b', '<f8'), ('c', '|S1')])
 
-If instead you print the table then a nicely formatted version appears::
+From within the IPython notebook, the table is displayed as a formatted HTML table:
+
+.. image:: table_repr_html.png
+
+If you print the table (either from the noteboook or in a text console session) then a
+formatted version appears::
 
   >>> print(t)
     a   b   c
@@ -67,6 +74,7 @@ time::
 
   >>> t.more()
 
+
 Now examine some high-level information about the table::
 
   >>> t.colnames
@@ -131,12 +139,31 @@ Add, remove, and rename columns with the following::
   >>> t.colnames
   ['A', 'b', 'd']
 
-Lastly, adding a new row of data to the table is as follows::
+Adding a new row of data to the table is as follows::
 
   >>> t.add_row([-8, -9, 10])
   >>> len(t)
   4
 
+Lastly, one can create a table with support for missing values, for example by setting
+``masked=True``::
+
+  >>> t = Table([a, b, c], names=('a', 'b', 'c'), masked=True)
+  >>> t['a'].mask = [True, True, False]
+  >>> t
+  <Table rows=3 names=('a','b','c')>
+  masked_array(data = [(--, 2.0, 'x') (--, 5.0, 'y') (5, 8.2, 'z')],
+               mask = [(True, False, False) (True, False, False) (False, False, False)],
+         fill_value = (999999, 1e+20, 'N'),
+              dtype = [('a', '<i8'), ('b', '<f8'), ('c', '|S1')])
+  
+  >>> print(t)
+   a   b   c 
+  --- --- ---
+   -- 2.0   x
+   -- 5.0   y
+    5 8.2   z
+
 .. _using_astropy_table:
 
 Using `table`
@@ -151,8 +178,11 @@ The details of using `astropy.table` are provided in the following sections:
    access_table.rst
    modify_table.rst
    masking.rst
+   io.rst
 
 Reference/API
 =============
 
 .. automodapi:: astropy.table
+
+.. automodapi:: astropy.table.io_registry
diff --git a/docs/table/io.rst b/docs/table/io.rst
new file mode 100644
index 0000000..71c7c08
--- /dev/null
+++ b/docs/table/io.rst
@@ -0,0 +1,333 @@
+.. _table_io:
+
+Reading and writing Table objects
+---------------------------------
+
+Introduction
+^^^^^^^^^^^^
+
+The :class:`~astropy.table.table.Table` class includes two methods,
+:meth:`~astropy.table.table.Table.read` and
+:meth:`~astropy.table.table.Table.write`, that make it possible to read from
+and write to files. A number of formats are automatically supported (see
+`Built-in readers/writers`_) and new file formats and extensions can be
+registered with the :class:`~astropy.table.table.Table` class (see `Creating a
+custom reader/writer`_). After importing the :class:`~astropy.table.table.Table` class::
+
+    >>> from astropy.table import Table
+
+the :meth:`~astropy.table.table.Table.read` method should be used as::
+
+    >>> t = Table.read(filename, format='format')
+
+where ``'format'`` is the format of the file to read in, e.g.::
+
+    >>> t = Table.read('photometry.dat', format='daophot')
+
+For certain file formats, the format can be automatically detected, for
+example from the filename extension::
+
+    >>> t = Table.read('table.tex')
+
+Similarly, for writing, the format can be explicitly specified::
+
+    >>> t.write(filename, format='format')
+
+but as for the :meth:`~astropy.table.table.Table.read` method, the format may
+be automatically identified in some cases.
+
+Any additional arguments specified will depend on the format (see e.g. see
+`Built-in readers/writers`_)
+
+Built-in readers/writers
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+ASCII formats
+"""""""""""""
+
+The :meth:`~astropy.table.table.Table.read` and
+:meth:`~astropy.table.table.Table.write` methods can be used to read and write formats
+supported by `astropy.io.ascii`:
+
+IPAC
+++++
+
+`IPAC tables <http://irsa.ipac.caltech.edu/applications/DDGEN/Doc/ipac_tbl.html>`_
+can be read with ``format='ipac'``::
+
+  >>> t = Table.read('2mass.tbl', format='ipac')
+
+Note that there are different conventions for characters occuring below the
+position of the ``|`` symbol in IPAC tables. By default, any character
+below a ``|`` will be ignored (since this is the current standard),
+but if you need to read files that assume characters below the ``|``
+symbols belong to the column before or after the ``|``, you can specify
+``definition='left'`` or ``definition='right'`` respectively when reading
+the table (the default is ``definition='ignore'``). The following examples demonstrate the different conventions:
+
+* ``definition='ignore'``::
+
+    |   ra  |  dec  |
+    | float | float |
+      1.2345  6.7890
+
+* ``definition='left'``::
+
+    |   ra  |  dec  |
+    | float | float |
+       1.2345  6.7890
+
+* ``definition='right'``::
+
+    |   ra  |  dec  |
+    | float | float |
+    1.2345  6.7890
+
+
+Advanced information is available in the :class:`~astropy.io.ascii.ipac.Ipac`
+class (any arguments apart from the filename and ``format`` are passed to
+this class when ``format='ipac'``).
+
+CDS/Machine Readable
+++++++++++++++++++++
+
+`CDS/Machine readable tables <http://vizier.u-strasbg.fr/doc/catstd.htx>`_ can be read with ``format='cds'``::
+
+    >>> t = Table.read('aj285677t3.txt', format='cds')
+
+If the table definition is given in a separate ``ReadMe`` file, this can be
+specified with::
+
+    >>> t = Table.read('aj285677t3.txt', format='cds', readme="ReadMe")
+
+Advanced information is available in the :class:`~astropy.io.ascii.cds.Cds`
+class (any arguments apart from the filename and ``format`` are passed to
+this class when ``format='cds'``).
+
+DAOPhot
++++++++
+
+`DAOPhot <http://stsdas.stsci.edu/cgi-bin/gethelp.cgi?daophot.hlp>`_ tables
+can be read with ``format='daophot'``::
+
+  >>> t = Table.read('photometry.dat', format='daophot')
+
+Advanced information is available in the
+:class:`~astropy.io.ascii.daophot.Daophot` class (any arguments apart from
+the filename and ``format`` are passed to this class when
+``format='daophot'``).
+
+LaTeX
++++++
+
+`LaTeX <http://www.latex-project.org/>`_ tables can be read and written with
+``format='latex'``. Provided the ``.tex``` extension is used, the format does
+not need to be explicitly specified::
+
+      >>> t = Table.read('paper_table.tex')
+      >>> t.write('new_paper_table.tex')
+
+If a different extension is used, the format should be specified::
+
+      >>> t.write('new_paper_table.inc', format='latex')
+
+Advanced information is available in the
+:class:`~astropy.io.ascii.latex.Latex` class (any arguments apart from the
+filename and ``format`` are passed to this class  when ``format='latex'``).
+
+RDB
++++
+
+`RDB <http://hea-www.harvard.edu/MST/simul/software/docs/rdb.html>`_ tables
+can be read and written with ``format='rdb'`` Provided the ``.rdb`` extension
+is used, the format does not need to be explicitly specified::
+
+      >>> t = Table.read('discovery_data.rdb')
+      >>> t.write('updated_data.rdb')
+
+If a different extension is used, the format should be specified::
+
+      >>> t.write('updated_data.txt', format='rdb')
+
+Advanced information is available in the :class:`~astropy.io.ascii.basic.Rdb`
+class (any arguments apart from the filename and ``format`` are passed to
+this class when ``format='rdb'``).
+
+Arbitrary ASCII formats
++++++++++++++++++++++++
+
+``format='ascii'`` can be used to interface to the bare
+:func:`~astropy.io.ascii.ui.read` and :func:`~astropy.io.ascii.ui.write`
+functions from `astropy.io.ascii`, e.g.::
+
+       >>> t = Table.read('table.tex', format='ascii')
+
+All additional arguments are passed to the `astropy.io.ascii`
+:func:`~astropy.io.ascii.ui.read` and
+:func:`~astropy.io.ascii.ui.write`. For example, in the following case::
+
+       >>> t = Table.read('photometry.dat', format='ascii', data_start=2, delimiter='|')
+
+the ``data_start`` and ``delimiter`` arguments are passed to the
+:func:`~astropy.io.ascii.ui.read` function from `astropy.io.ascii` (and
+similarly for writing).
+
+HDF5
+""""
+
+Reading/writing from/to `HDF5 <http://www.hdfgroup.org/HDF5/>`_ files is
+supported with ``format='hdf5'`` (this requires `h5py
+<http://code.google.com/p/h5py/>`_ to be installed). However, the ``.hdf5``
+file extension is automatically recognized when writing files, and HDF5 files
+are automatically identified (even with a different extension) when reading
+in (using the first few bytes of the file to identify the format), so in most
+cases you will not need to explicitly specify ``format='hdf5'``.
+
+Since HDF5 files can contain multiple tables, the full path to the table
+should be specified via the ``path=`` argument when reading and writing.
+For example, to read a table called ``data`` from an HDF5 file named
+``observations.hdf5``, you can do::
+
+    >>> t = Table.read('observations.hdf5', path='data')
+
+To read a table nested in a group in the HDF5 file, you can do::
+
+    >>> t = Table.read('observations.hdf5', path='group/data')
+
+To write a table to a new file, the path should also be specified::
+
+    >>> t.write('new_file.hdf5', path='updated_data')
+
+It is also possible to write a table to an existing file using ``append=True``::
+
+    >>> t.write('observations.hdf5', path='updated_data', append=True)
+
+Finally, when writing to HDF5 files, the ``compression=`` argument can be
+used to ensure that the data is compressed on disk::
+
+    >>> t.write('new_file.hdf5', path='updated_data', compression=True)
+
+As with other formats, the ``overwrite=True`` argument is supported for
+overwriting existing files.
+
+VO Tables
+"""""""""
+
+Reading/writing from/to `VO table <http://www.ivoa.net/Documents/VOTable/>`_
+files is supported with ``format='votable'``. In most cases, existing VO
+tables should be automatically identified as such based on the header of the
+file, but if not, or if writing to disk, then the format should be explicitly
+specified.
+
+If a VO table file only contains a single table, then it can be read in with::
+
+    >>> t = Table.read('aj285677t3_votable.xml')
+
+If more that one table are present in the file, an error will be raised,
+unless the table ID is specified via the ``table_id=`` argument::
+
+    >>> t = Table.read('catalog.xml')
+    Traceback (most recent call last):
+      File "<stdin>", line 1, in <module>
+      File "/Volumes/Raptor/Library/Python/2.7/lib/python/site-packages/astropy/table/table.py", line 1559, in read
+        table = reader(*args, **kwargs)
+      File "/Volumes/Raptor/Library/Python/2.7/lib/python/site-packages/astropy/io/votable/connect.py", line 44, in read_table_votable
+        raise ValueError("Multiple tables found: table id should be set via the id= argument. The available tables are " + ', '.join(tables.keys()))
+    ValueError: Multiple tables found: table id should be set via the table_id= argument. The available tables are twomass, spitzer
+
+    >>> t = Table.read('catalog.xml', table_id='twomass')
+
+To write to a new file, the ID of the table should also be specified (unless
+``t.meta['ID']`` is defined)::
+
+    >>> t.write('new_catalog.xml', table_id='updated_table', format='votable')
+
+When writing, the ``compression=True`` argument can be used to force
+compression of the data on disk, and the ``overwrite=True`` argument can be
+used to overwrite an existing file.
+
+Other
+"""""
+
+In future, FITS tables will also be supported via the
+:class:`~astropy.table.table.Table` class. For now, these can be read and
+written directly with `astropy.io.fits`.
+
+Creating a custom reader/writer
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The following example demonstrates how to create a reader for the
+Table class. First, we can create a highly simplistic FITS reader
+which just reads the data as a structured array::
+
+    from astropy.table import Table
+
+    def fits_reader(filename, hdu=1):
+        from astropy.io import fits
+        data = fits.open(filename)[hdu].data
+        return Table(data)
+
+and then register it with astropy.table::
+
+    from astropy.table import io_registry
+    io_registry.register_reader('fits', fits_reader)
+
+Reader functions can take any arguments except ``format`` (since this
+is reserved for the ``Table.read`` method) and should return a
+``Table`` object.
+
+We can then read in a FITS table with::
+
+    t = Table.read('catalog.fits', format='fits')
+
+In practice, it would be nice to have the ``read`` method automatically
+identify that this file was a FITS file, so we can construct a function that
+can recognize FITS files, which we refer to here as an *identifier*
+function. An identifier function should take three arguments: the first
+should be a string which indicates whether the identifier is being called
+from ``read`` or ``write``, and the second and third are the positional and
+keyword arguments passed to ``Table.read`` respectively (and are therefore a
+list and a dictionary). We can write a simplistic function that only looks
+at filenames (but in practice, this function could even look at the first
+few bytes of the file for example). The only requirement is that it return a
+boolean indicating whether the input matches that expected for the format::
+
+    def fits_identify(origin, args, kwargs):
+        return isinstance(args[0], basestring) and \
+               args[0].lower().split('.')[-1] in ['fits', 'fit']
+
+.. note:: Identifier functions should be prepared for arbitrary input - in
+          particular, the first argument may not be a filename or file
+          object, so it should not assume that this is the case.
+
+We then register this identifier function with ``astropy.table``::
+
+    io_registry.register_identifier('fits', fits_identify)
+
+And we can then do::
+
+    t = Table.read('catalog.fits')
+
+If multiple formats match the current input, then an exception is
+raised, and similarly if no format matches the current input. In that
+case, the format should be explicitly given with the ``format=``
+keyword argument.
+
+Similarly, it is possible to create custom writers. To go with our simplistic FITS reader above, we can write a simplistic FITS writer::
+
+   def fits_writer(table, filename, clobber=False):
+       import numpy as np
+       from astropy.io import fits
+       fits.writeto(filename, np.array(table), clobber=clobber)
+
+We then register the writer::
+
+   io_registry.register_writer('fits', fits_writer)
+
+And we can then write the file out to a FITS file::
+
+   t.write('catalog_new.fits', format='fits')
+
+If we have registered the identifier as above, we can simply do::
+
+   t.write('catalog_new.fits')
diff --git a/docs/table/masking.rst b/docs/table/masking.rst
index 105cad4..ef7ac58 100644
--- a/docs/table/masking.rst
+++ b/docs/table/masking.rst
@@ -1,6 +1,182 @@
-Masking and null values
------------------------
+.. include:: references.txt
 
-At this time the ``astropy.table`` package has no support for masking and null
-values.  This is to be done.
+Masking and missing values
+--------------------------
 
+The `astropy.table` package provides support for masking and missing
+values in a table by wrapping the `numpy.ma` masked array package.
+This allows handling tables with missing or invalid entries in much
+the same manner as for standard (unmasked) tables.  It
+is useful to be familiar with the `masked array
+<http://docs.scipy.org/doc/numpy/reference/maskedarray.generic.html>`_
+documentation when using masked tables within `astropy.table`.
+
+In a nutshell, the concept is to define a boolean mask that mirrors
+the structure of the table data array.  Wherever a mask value is
+``True``, the corresponding entry is considered to be missing or invalid.
+Operations involving column or row access and slicing are unchanged.
+The key difference is that arithmetic or reduction operations involving
+columns or column slices follow the rules for `operations
+on masked arrays
+<http://docs.scipy.org/doc/numpy/reference/maskedarray.generic.html#operations-on-masked-arrays>`_.
+
+.. Note::
+
+   Reduction operations like `numpy.sum` or `numpy.mean` follow the
+   convention of ignoring masked (invalid) values.  This differs from
+   the behavior of the floating point ``NaN``, for which the sum of an
+   array including one or more ``NaN's`` will result in ``NaN``.
+   See `<http://numpy.scipy.org/NA-overview.html>`_ for a very
+   interesting discussion of different strategies for handling
+   missing data in the context of `numpy`.
+
+.. Note::
+
+   Masked tables are only available for `numpy` version 1.5 and later
+   because of issues in the masked array implementation for
+   prior `numpy` versions.
+
+Table creation
+^^^^^^^^^^^^^^^
+
+A masked table can be created in several ways:
+
+**Create a new table object and specify masked=True** ::
+
+  >>> from astropy.table import Table, Column, MaskedColumn
+  >>> t = Table([(1, 2), (3, 4)], names=('a', 'b'), masked=True)
+  >>> t
+  <Table rows=2 names=('a','b')>
+  masked_array(data = [(1, 3) (2, 4)],
+               mask = [(False, False) (False, False)],
+         fill_value = (999999, 999999),
+              dtype = [('a', '<i8'), ('b', '<i8')])
+
+Notice the table attributes ``mask`` and ``fill_value`` that are
+available for a masked table.
+
+**Create a table with one or more columns as a MaskedColumn object**
+
+  >>> a = MaskedColumn('a', [1, 2])
+  >>> b = Column('b', [3, 4])
+  >>> t = Table([a, b])
+
+The |MaskedColumn| is the masked analog of the |Column| class and
+provides the interface for creating and manipulating a column of
+masked data.  The |MaskedColumn| class inherits from
+`numpy.ma.MaskedArray`, in contrast to |Column| which inherits from
+`numpy.ndarray`.  This distinction is the main reason there are
+different classes for these two cases.
+
+**Create a table with one or more columns as a numpy MaskedArray**
+
+  >>> from numpy import ma  # masked array package
+  >>> a = ma.array([1, 2])
+  >>> b = [3, 4]
+  >>> t = Table([a, b], names=('a', 'b'))
+
+**Add a MaskedColumn object to an existing table**
+
+  >>> a = Column('a', [1, 2])
+  >>> b = MaskedColumn('b', [3, 4], mask=[True, False])
+  >>> t = Table([a])
+  >>> t.add_column(b)
+  INFO: Upgrading Table to masked Table [astropy.table.table]
+
+Note the INFO message because the underlying type of the table is modified in this operation.
+
+**Add a new row to an existing table and specify a mask argument**
+
+  >>> a = Column('a', [1, 2])
+  >>> b = Column('b', [3, 4])
+  >>> t = Table([a, b])
+  >>> t.add_row([3, 6], mask=[True, False])
+  INFO: Upgrading Table to masked Table [astropy.table.table]
+
+**Convert an existing table to a masked table**
+
+  >>> t = Table([[1, 2], ['x', 'y']])  # standard (unmasked) table
+  >>> t = Table(t, masked=True)  # convert to masked table
+
+Table access
+^^^^^^^^^^^^
+
+Nearly all the of standard methods for accessing and modifying data
+columns, rows, and individual elements also apply to masked tables.
+
+There are two minor differences for the |Row| object that is obtained by
+indexing a single row of a table:  
+
+- For standard tables, two such rows can be compared for equality, but
+  in masked tables this comparison will produce an exception.
+- For standard tables a |Row| object provides a view of the underlying
+  table data so that it is possible to modify a table by modifying the
+  row values.  In masked tables this is a copy so that modifying the
+  |Row| object has no effect on the original table data.
+
+Both of these differences are due to issues in the underlying
+`numpy.ma.MaskedArray` implementation.
+
+Masking and filling
+^^^^^^^^^^^^^^^^^^^^
+
+Both the |Table| and |MaskedColumn| classes provide 
+attributes and methods to support manipulating tables with missing or
+invalid data.
+
+Mask
+""""
+
+The actual mask for the table as a whole or a single column can be
+viewed and modified via the ``mask`` attribute::
+
+  >>> t = Table([(1, 2), (3, 4)], names=('a', 'b'), masked=True)
+  >>> t.mask['a'] = [False, True]  # Modify table mask (structured array)
+  >>> t['b'].mask = [True, False]  # Modify column mask (boolean array)
+  >>> print(t)
+   a   b 
+  --- ---
+    1  --
+   --   4
+
+Masked entries are shown as ``--`` when the table is printed.
+
+Filling
+"""""""
+
+The entries which are masked (i.e. missing or invalid) can be replaced
+with specified fill values.  In this case the |MaskedColumn| or masked
+|Table| will be converted to a standard |Column| or table. Each column
+in a masked table has a ``fill_value`` attribute that specifies the
+default fill value for that column.  To perform the actual replacement
+operation the ``filled()`` method is called.  This takes an optional
+argument which can override the default column ``fill_value``
+attribute.
+::
+
+  >>> t['a'].fill_value = -99
+  >>> t['b'].fill_value = 33
+
+  >>> print t.filled()
+   a   b 
+  --- ---
+    1  33
+  -99   4
+
+  >>> print t['a'].filled()
+   a 
+  ---
+    1
+  -99
+
+  >>> print t['a'].filled(999)
+   a 
+  ---
+    1
+  999
+
+  >>> print t.filled(1000)
+   a    b  
+  ---- ----
+     1 1000
+  1000    4
diff --git a/docs/table/modify_table.rst b/docs/table/modify_table.rst
index cb0921c..eceabef 100644
--- a/docs/table/modify_table.rst
+++ b/docs/table/modify_table.rst
@@ -12,7 +12,7 @@ is the ability to easily modify the structure of the table: one can add or
 remove columns, and add new rows of data.
 
 Quick overview
---------------
+^^^^^^^^^^^^^^
 
 The code below shows the basics of modifying a table and its data.
 
@@ -94,7 +94,7 @@ The code below shows the basics of modifying a table and its data.
 
 
 Caveats
--------
+^^^^^^^
 
 Modifying the table data and properties is fairly straightforward.  There are
 only a few things to keep in mind:
diff --git a/docs/table/references.txt b/docs/table/references.txt
index d2eb391..6079533 100644
--- a/docs/table/references.txt
+++ b/docs/table/references.txt
@@ -1,5 +1,6 @@
 .. |Row| replace:: :class:`~astropy.table.table.Row`
 .. |Table| replace:: :class:`~astropy.table.table.Table`
 .. |Column| replace:: :class:`~astropy.table.table.Column`
+.. |MaskedColumn| replace:: :class:`~astropy.table.table.MaskedColumn`
 .. |TableColumns| replace:: :class:`~astropy.table.table.TableColumns`
 .. _OrderedDict: http://docs.python.org/library/collections.html#collections.OrderedDict
diff --git a/docs/table/table_repr_html.png b/docs/table/table_repr_html.png
new file mode 100644
index 0000000..b57ea0f
Binary files /dev/null and b/docs/table/table_repr_html.png differ
diff --git a/docs/time/index.rst b/docs/time/index.rst
new file mode 100644
index 0000000..1511b7d
--- /dev/null
+++ b/docs/time/index.rst
@@ -0,0 +1,531 @@
+.. _astropy_time:
+
+.. include:: references.txt
+
+****************************************************
+Time and Dates (`astropy.time`)
+****************************************************
+
+Introduction
+============
+
+The `astropy.time` package provides functionality for manipulating times and
+dates.  Specific emphasis is placed on supporting time scales (e.g. UTC, TAI, UT1) and
+time representations (e.g. JD, MJD, ISO 8601) that are used in astronomy.
+It uses Cython to wrap the C language `SOFA`_ time and calendar
+routines.  All time scale conversions are done by Cython vectorized versions
+of the `SOFA`_ routines and are fast and memory efficient.
+
+Getting Started
+===============
+
+The basic way to use `astropy.time` is to create a |Time|
+object by supplying one or more input time values as well as the `time format`_ and
+`time scale`_ of those values.  The input time(s) can either be a single scalar like
+`"2010-01-01 00:00:00"` or a list or a `numpy` array of values as shown below.
+In general any output values have the same shape (scalar or array) as the input.
+
+  >>> from astropy.time import Time
+
+  >>> times = ['1999-01-01 00:00:00.123456789', '2010-01-01 00:00:00']
+  >>> t = Time(times, format='iso', scale='utc')
+  >>> t
+  <Time object: scale='utc' format='iso' vals=['1999-01-01 00:00:00.123' '2010-01-01 00:00:00.000']>
+
+The ``format`` argument specifies how to interpret the input values, e.g. ISO
+or JD or Unix time.  The ``scale`` argument specifies the `time scale`_ for the
+values, e.g. UTC or TT or UT1.
+
+Now let's get the representation of these times in the JD and MJD
+formats by requesting the corresponding |Time| attributes::
+
+  >>> t.jd
+  array([ 2451179.50000143,  2455197.5       ])
+  >>> t.mjd
+  array([ 51179.00000143,  55197.        ])
+
+We can also convert to a different time scale, for instance from UTC to
+TT.  This uses the same attribute mechanism as above but now returns a new
+|Time| object::
+
+  >>> t2 = t.tt
+  >>> t2
+  <Time object: scale='tt' format='iso' vals=['1999-01-01 00:01:04.307' '2010-01-01 00:01:06.184']>
+  >>> t2.jd
+  array([ 2451179.5007443 ,  2455197.50076602])
+
+Note that both the ISO and JD representations of ``t2`` are different than for
+``t`` because they are expressed relative to the TT time scale.
+
+
+Using `astropy.time`
+=====================
+
+Time object basics
+-------------------
+
+In `astropy.time` a "time" is a single instant of time which is
+independent of the way the time is represented (the "format") and the time
+"scale" which specifies the offset and scaling relation of the unit of time.
+There is no distinction made between a "date" and a "time" since both concepts
+(as loosely defined in common usage) are just different representations of a
+moment in time.
+
+Once a |Time| object is created it cannot be altered internally.  In code lingo
+it is immutable.  In particular the common operation of "converting" to a
+different `time scale`_ is always performed by returning a copy of the original
+|Time| object which has been converted to the new time scale.
+
+
+Time Format
+^^^^^^^^^^^
+
+The time format specifies how an instant of time is represented.  The currently
+available formats are can be found in the ``Time.FORMATS`` dict and
+are listed in the table below.  Each of these formats is implemented as a class
+that derives from the base :class:`~astropy.time.core.TimeFormat` class.
+This class structure can be easily adapted and extended by users for
+specialized time formats not supplied in `astropy.time`.
+
+=========  ====================================================
+Format            Class
+=========  ====================================================
+byear      :class:`~astropy.time.core.TimeBesselianEpoch`
+byear_str  :class:`~astropy.time.core.TimeBesselianEpochString`
+cxcsec     :class:`~astropy.time.core.TimeCxcSec`
+iso        :class:`~astropy.time.core.TimeISO`
+isot       :class:`~astropy.time.core.TimeISOT`
+jd         :class:`~astropy.time.core.TimeJD`
+jyear      :class:`~astropy.time.core.TimeJulianEpoch`
+jyear_str  :class:`~astropy.time.core.TimeJulianEpochString`
+mjd        :class:`~astropy.time.core.TimeMJD`
+unix       :class:`~astropy.time.core.TimeUnix`
+yday       :class:`~astropy.time.core.TimeYearDayTime`
+=========  ====================================================
+
+Subformat
+""""""""""
+
+The time format classes :class:`~astropy.time.core.TimeISO`,
+:class:`~astropy.time.core.TimeISO`, and
+:class:`~astropy.time.core.TimeYearDayTime` support the concept of
+subformats.  This allows for variations on the basic theme of a format in both
+the input string parsing and the output.
+
+The supported subformats are ``date_hms``, ``date_hm``, and ``date``.  The
+table below illustrates these subformats for `iso` and `yday` formats:
+
+=========  ========== ===========================
+Format     Subformat  Input / output
+=========  ========== ===========================
+``iso``    date_hms   2001-01-02 03:04:05.678
+``iso``    date_hm    2001-01-02 03:04
+``iso``    date       2001-01-02
+``yday``   date_hms   2001:032:03:04:05.678
+``yday``   date_hm    2001:032:03:04
+``yday``   date       2001:032
+=========  ========== ===========================
+
+
+Time Scale
+^^^^^^^^^^
+
+The time scale (or `time standard
+<http://en.wikipedia.org/wiki/Time_standard>`_) is "a specification for
+measuring time: either the rate at which time passes; or points in time; or
+both" [#]_. See also [#]_ and [#]_.
+::
+
+  >>> Time.SCALES
+  ('tai', 'tcb', 'tcg', 'tdb', 'tt', 'ut1', 'utc')
+
+====== =================================
+Scale        Description
+====== =================================
+tai    International Atomic Time   (TAI)
+tcb    Barycentric Coordinate Time (TCB)
+tcg    Geocentric Coordinate Time  (TCG)
+tdb    Barycentric Dynamical Time  (TDB)
+tt     Terrestrial Time            (TT)
+ut1    Universal Time              (UT1)
+utc    Coordinated Universal Time  (UTC)
+====== =================================
+
+.. [#] Wikipedia `time standard <http://en.wikipedia.org/wiki/Time_standard>`_ article
+.. [#] SOFA Time Scale and Calendar Tools
+       `(PDF) <http://www.iausofa.org/2012_0301_C/sofa/sofa_ts_c.pdf>`_
+.. [#] `<http://www.ucolick.org/~sla/leapsecs/timescales.html>`_
+
+The system of transformation between supported time scales is shown in the
+figure below.  Further details are provided in the `Convert time scale`_ section.
+
+.. image:: time_scale_conversion.png
+
+Scalar or Array
+^^^^^^^^^^^^^^^^
+
+A |Time| object can hold either a single time value or an array of time values.
+The distinction is made entirely by the form of the input time(s).  If a |Time|
+object holds a single value then any format outputs will be a single scalar
+value, and likewise for arrays.  ::
+
+  >>> from astropy.time import Time
+  >>> t = Time(100.0, format='mjd', scale='utc')
+  >>> t.jd
+  2400100.5
+  >>> t = Time([100.0, 200.0], format='mjd', scale='utc')
+  >>> t.jd
+  array([ 2400100.5,  2400200.5])
+
+Inferring input format
+^^^^^^^^^^^^^^^^^^^^^^^
+
+The |Time| class initializer will not accept ambiguous inputs,
+but it will make automatic inferences in cases where the inputs are
+unambiguous.  This can apply when the times are supplied as a list of strings,
+in which case it is not required to specify the format because the available
+string formats have no overlap.  However, if the format is known in advance
+the string parsing will be faster if the format is provided.
+::
+
+  >>> t = Time('2010-01-02 01:02:03', scale='utc')
+  >>> t.format
+  'iso'
+
+Internal representation
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+The |Time| object maintains an internal representation of time as a pair of
+double precision numbers expressing Julian days. The sum of the two numbers is
+the Julian Date for that time relative to the given `time scale`_.  Users
+requiring no better than microsecond precision over human time scales (~100
+years) can safely ignore the internal representation details and skip this section.
+
+This representation is driven by the underlying SOFA C-library implementation.
+The SOFA routines take care throughout to maintain overall precision of the
+double pair.  The user is free to choose the way in which total JD is
+distributed between the two values.
+
+The internal JD pair is available via the ``jd1`` and ``jd2`` attributes.
+Notice in the example below that when converting from UTC to TAI, the
+small offset is placed in the ``jd2`` value thus maintaining the highest
+numeric precision::
+
+  >>> t = Time('2010-01-01 00:00:00', scale='utc')
+  >>> t.jd1, t.jd2
+  (2455197.5, 0.0)
+  >>> t2 = t.tai
+  >>> t2.jd1. t2.jd2
+  (2455197.5, 0.0003935185185185185)
+
+Creating a Time object
+------------------------
+
+The allowed |Time| arguments to create a time object are listed below:
+
+**val** : numpy ndarray, list, str, or number
+    Data to initialize table.
+**val2** : numpy ndarray, list, str, or number; optional
+    Data to initialize table.
+**format** : str, optional
+    Format of input value(s)
+**scale** : str, optional
+    Time scale of input value(s)
+**precision** : int between 0 and 9 inclusive
+    Decimal precision when outputting seconds as floating point
+**in_subfmt** : str
+    Unix glob to select subformats for parsing string input times
+**out_subfmt** : str
+    Unix glob to select subformats for outputting string times
+**lat** : float, optional
+    Earth latitude of observer
+**lon** : float, optional
+    Earth longitude of observer
+
+val
+^^^^^^^^^^^
+
+The ``val`` argument is the only argument that is always required when creating a
+|Time| object.  This argument specifies the input time or times and
+can be a single string or number, or it can be a Python list or `numpy` array
+of strings or numbers.
+
+In most situations one also needs to specify the `time scale`_ via the
+``scale`` argument.  The |Time| class will never guess the `time scale`_,
+so a simple example would be::
+
+  >>> t = Time('2010-01-01 00:00:00', scale='utc')
+  >>> t2 = Time(50100.0, format='mjd', scale='tt')
+
+val2
+^^^^^^^^^^^
+
+The ``val2`` argument is available for specialized situations where extremely
+high precision is required.  Recall that the internal representation of time
+within `astropy.time` is two double-precision numbers that when summed give
+the Julian date.  If provided the ``val2`` argument is used in combination with
+``val`` to set the second the internal time values.  The exact interpretation of
+``val2`` is determined by the input format class.  As of this release all
+string-valued formats ignore ``val2`` and all numeric inputs effectively add
+the two values in a way that maintains the highest precision.  Example::
+
+  >>> t = Time(100.0, 0.000001, format='mjd', scale='tt')
+  >>> t.jd, t.jd1, t.jd2
+  (2400100.500001, 2400100.5, 1e-06)
+
+format
+^^^^^^^^^^^
+
+The ``format`` argument sets the time `time format`_, and as mentioned it is
+required unless the format can be unambiguously determined from the input times.
+
+
+scale
+^^^^^^^^^^^
+
+The ``scale`` argument sets the `time scale`_ and is required except for time
+formats such as 'cxcsec' (:class:`~astropy.time.core.TimeCxcSec`) and 'unix'
+(:class:`~astropy.time.core.TimeUnix`).  These formats represent the duration
+in SI seconds since a fixed instant in time which is independent of time scale.
+
+precision
+^^^^^^^^^^
+
+The ``precision`` setting affects string formats when outputting a value that
+includes seconds.  It must be an integer between 0 and 9.  There is no effect
+when inputting time values from strings.  The default precision is 3.  Note
+that the limit of 9 digits is driven by the way that SOFA handles fractional
+seconds.  In practice this should should not be an issue.  ::
+
+  >>> t = Time('B1950.0', scale='utc', precision=3)
+  >>> t.byear_str
+  'B1950.000'
+  >>> t.precision = 0
+  >>> t.byear_str
+  'B1950'
+
+in_subfmt
+^^^^^^^^^^^
+
+The ``in_subfmt`` argument provides a mechanism to select one or more
+`subformat`_ values from the available subformats for string input.  Multiple
+allowed subformats can be selected using Unix-style wildcard characters, in
+particular ``*`` and ``?``, as documented in the Python `fnmatch
+<http://docs.python.org/library/fnmatch.html>`_ module.
+
+The default value for ``in_subfmt`` is ``*`` which matches any available
+subformat.  This allows for convenient input of values with unknown or
+heterogeous subformat::
+
+  >>> Time(['2000:001', '2000:002:03:04', '2001:003:04:05:06.789'], scale='utc')
+  <Time object: scale='utc' format='yday'
+   vals=['2000:001:00:00:00.000' '2000:002:03:04:00.000' '2001:003:04:05:06.789']>
+
+One can explicitly specify ``in_subfmt`` in order to strictly require a
+certain subformat::
+
+  >>> t = Time('2000:002:03:04', scale='utc', in_subfmt='date_hm')
+  >>> t = Time('2000:002', scale='utc', in_subfmt='date_hm')
+  ERROR: ValueError: Input values did not match any of format classes
+  ['iso', 'isot', 'yday']
+
+out_subfmt
+^^^^^^^^^^^
+
+The ``out_subfmt`` argument is similar to ``in_subfmt`` except that it applies
+to output formatting.  In the case of multiple matching subformats the first
+matching subformat is used.
+
+  >>> Time('2000-01-01 02:03:04', scale='utc', out_subfmt='date').iso
+  '2000-01-01'
+  >>> Time('2000-01-01 02:03:04', scale='utc', out_subfmt='date_hms').iso
+  '2000-01-01 02:03:04.000'
+  >>> Time('2000-01-01 02:03:04', scale='utc', out_subfmt='date*').iso
+  '2000-01-01 02:03:04.000'
+
+lat and lon
+^^^^^^^^^^^^
+
+These optional parameters specify the observer latitude and longitude in
+decimal degrees.  They default to 0.0 and are used for time scales that are
+sensitive to observer position.  Currently the only time scale for which this
+applies is TDB, which relies on the SOFA routine ``iauDtdb`` to determine the
+time offset between TDB and TT.
+
+
+Using Time objects
+-------------------
+
+There are three basic operations available with |Time| objects:
+
+- Get the representation of the time value(s) in a particular `time format`_.
+- Get a new time object for the same time value(s) but referenced to a different
+  `time scale`_.
+- Do time arithmetic involving |Time| and/or |TimeDelta| objects.
+
+Get representation
+^^^^^^^^^^^^^^^^^^^
+
+Instants of time can be represented in different ways, for instance as an
+ISO-format date string (``'1999-07-23 04:31:00'``) or seconds since 1998.0
+(``49091460.0``) or Modified Julian Date (``51382.187451574``).
+
+The representation of a |Time| object in a particular format is available
+by getting the object attribute corresponding to the format name.  The list of
+available format names is in the `time format`_ section.
+
+  >>> t = Time('2010-01-01 00:00:00', format='iso', scale='utc')
+  >>> t.jd        # JD representation of time in current scale (UTC)
+  2455197.5
+  >>> t.iso       # ISO representation of time in current scale (UTC)
+  '2010-01-01 00:00:00.000'
+  >>> t.unix      # seconds since 1970.0 (UTC)
+  1262304000.0
+  >>> t.cxcsec    # SI seconds since 1998.0 (TT)
+  378691266.184
+
+Convert time scale
+^^^^^^^^^^^^^^^^^^^^
+
+A new |Time| object for the same time value(s) but referenced to a new `time
+scale`_ can be created getting the object attribute corresponding to the time
+scale name.  The list of available time scale names is in the `time scale`_
+section and in the figure below illustrating the network of time scale
+transformations.
+
+.. image:: time_scale_conversion.png
+
+Examples::
+
+  >>> t = Time('2010-01-01 00:00:00', format='iso', scale='utc')
+  >>> t.tt        # TT scale
+  <Time object: scale='tt' format='iso' vals=2010-01-01 00:01:06.184>
+  >>> t.tai
+  <Time object: scale='tai' format='iso' vals=2010-01-01 00:00:34.000>
+
+In this process the ``format`` and other object attributes like ``lat``,
+``lon``, and ``precision`` are also propagated to the new object.
+
+
+As noted in the `Time object basics` section, a |Time| object is immutable and
+the internal time values cannot be altered once the object is created.  The
+process of changing the time scale therefore begins by making a copy of the
+original object and then converting the internal time values in the copy to the
+new time scale.  The new |Time| object is returned by the attribute access.
+
+Transformation offsets
+""""""""""""""""""""""
+
+Time scale transformations that cross one of the orange circles in the image
+above require an additional offset time value that is model or
+observation-dependent.  See `SOFA Time Scale and Calendar Tools
+<http://www.iausofa.org/2012_0301_C/sofa/sofa_ts_c.pdf>`_ for further details.
+
+The two attributes :attr:`~astropy.time.Time.delta_ut1_utc` and
+:attr:`~astropy.time.Time.delta_tdb_tt` provide a way to set
+these offset times explicitly.  These represent the time scale offsets
+UT1 - UTC and TDB - TT, respectively.  As an example::
+
+  >>> t = Time('2010-01-01 00:00:00', format='iso', scale='utc')
+  >>> t.delta_ut1_utc = 0.334  # Explicitly set one part of the transformation
+  >>> t.ut1.iso    # ISO representation of time in UT1 scale
+ '2010-01-01 00:00:00.334'
+
+In the case of the TDB to TT offset, most users need only provide the ``lat``
+and ``lon`` values when creating the |Time| object.  If the
+:attr:`~astropy.time.Time.delta_tdb_tt` attribute is not explicitly set
+then the SOFA C-library routine ``iauDtdb`` will be used to compute the
+TDB to TT offset.  Note that ``lat`` and ``lon`` are initialized to 0.0 by
+default, so those defaults will be used if they are not provided.
+
+The following code replicates an example in the `SOFA Time Scale and Calendar
+Tools <http://www.iausofa.org/2012_0301_C/sofa/sofa_ts_c.pdf>`_ document.  It
+does the transform from UTC to all supported time scales (TAI, TCB, TCG, TDB,
+TT, UT1, UTC).  This requires auxilliary information (latitude and longitude).
+::
+
+  >>> lat = 19.48125
+  >>> lon = -155.933222
+  >>> t = Time('2006-01-15 21:24:37.5', format='iso', scale='utc',
+  ...          lat=lat, lon=lon, precision=6)
+  >>> t.delta_ut1_utc = 0.3341  # Explicitly set one part of the transformation
+  >>> t.utc.iso
+  '2006-01-15 21:24:37.500000'
+  >>> t.ut1.iso
+  '2006-01-15 21:24:37.834100'
+  >>> t.tai.iso
+  '2006-01-15 21:25:10.500000'
+  >>> t.tt.iso
+  '2006-01-15 21:25:42.684000'
+  >>> t.tcg.iso
+  '2006-01-15 21:25:43.322690'
+  >>> t.tdb.iso
+  '2006-01-15 21:25:42.683799'
+  >>> t.tcb.iso
+  '2006-01-15 21:25:56.893378'
+
+Time Deltas
+------------
+
+Simple time arithmetic is supported using via the |TimeDelta| class.  The
+following operations are available:
+
+- Create a TimeDelta explicitly by instantiating a class object
+- Create a TimeDelta by subtracting two Times
+- Add a TimeDelta to a Time object to get a new Time
+- Subtract a TimeDelta from a Time object to get a new Time
+- Add two TimeDelta objects to get a new TimeDelta
+
+The |TimeDelta| class is derived from the |Time| class and shares many of its
+properties.  The key difference is that the time scale is always TAI so that
+all time deltas are referenced to a uniform Julian Day which is exactly 86400
+standard SI seconds.
+
+The available time formats are:
+
+=========  ===================================================
+Format            Class
+=========  ===================================================
+sec        :class:`~astropy.time.core.TimeDeltaSec`
+jd         :class:`~astropy.time.core.TimeDeltaJD`
+=========  ===================================================
+
+Examples
+^^^^^^^^^
+
+Use of the |TimeDelta| object is easily illustrated in the few examples below::
+
+  >>> t1 = Time('2010-01-01 00:00:00', scale='utc')
+  >>> t2 = Time('2010-02-01 00:00:00', scale='utc')
+  >>> dt = t2 - t1  # Difference between two Times
+  >>> dt
+  <TimeDelta object: scale='tai' format='jd' vals=31.0>
+  >>> dt.sec
+  2678400.0
+
+  >>> from astropy.time import TimeDelta
+  >>> dt2 = TimeDelta(50.0, format='sec')
+  >>> t3 = t2 + dt2  # Add a TimeDelta to a Time
+  >>> t3.iso
+  '2010-02-01 00:00:50.000'
+
+  >>> t2 - dt2  # Subtract a TimeDelta from a Time
+  <Time object: scale='utc' format='iso' vals=2010-01-31 23:59:10.000>
+
+  >>> dt + dt2
+  <TimeDelta object: scale='tai' format='jd' vals=31.0005787037>
+
+Reference/API
+=============
+
+.. automodapi:: astropy.time.core
+
+
+Acknowledgments and Licenses
+=======================================
+
+This package makes use of the `SOFA Software
+<http://www.iausofa.org/index.html>`_ ANSI C library.  The copyright of the SOFA
+Software belongs to the Standards Of Fundamental Astronomy Board of the
+International Astronomical Union.  This library is made available under the
+terms of the `SOFA license <http://www.iausofa.org/tandc.html>`_.
diff --git a/docs/time/references.txt b/docs/time/references.txt
new file mode 100644
index 0000000..7c92d3f
--- /dev/null
+++ b/docs/time/references.txt
@@ -0,0 +1,3 @@
+.. |Time| replace:: :class:`~astropy.time.core.Time`
+.. |TimeDelta| replace:: :class:`~astropy.time.core.TimeDelta`
+.. _SOFA: http://www.iausofa.org/index.html
diff --git a/docs/time/time_scale_conversion.odg b/docs/time/time_scale_conversion.odg
new file mode 100644
index 0000000..08478c1
Binary files /dev/null and b/docs/time/time_scale_conversion.odg differ
diff --git a/docs/time/time_scale_conversion.png b/docs/time/time_scale_conversion.png
new file mode 100644
index 0000000..4e2f8dc
Binary files /dev/null and b/docs/time/time_scale_conversion.png differ
diff --git a/docs/tools/index.rst b/docs/tools/index.rst
deleted file mode 100644
index 08a0c28..0000000
--- a/docs/tools/index.rst
+++ /dev/null
@@ -1,54 +0,0 @@
-.. _tools:
-
-******************************************
-Astronomy-Oriented Tools (`astropy.tools`)
-******************************************
-
-Introduction
-============
-
-The `astropy.tools` package holds smallish general astronomy functions
-or algorithms that are likely of use to users, but either not related to
-functionality in an existing package or of general use across multiple
-packages.
-
-
-
-Getting Started
-===============
-
-The current tools are fairly self-contained, and include relevant examples in
-their docstrings.  For example, see `~astropy.tools.misc.sigma_clip`.
-
-
-
-.. NOTE TO FUTURE DEVS: When this subpackage gets more populated, it will be
-.. wise to add a section of the form shown below.  Be sure to move this file
-.. to docs/tools/index.rst and update docs/index.rst to tools/index when
-.. that happens.
-
-.. Using packagename
-.. -----------------
-
-.. For more complicated packages that require multiple documents, this
-.. should just be a table of contents referencing those documents:
-
-.. .. toctree::
-..     packagename/subdoc1
-..     packagename/subdoc2
-..     packagename/subdoc3
-
-
-See Also
-========
-
-* :ref:`utils`
-    The subpackage for utilities that are oriented towards developers, rather than
-    users.  These utilities are more general-purposes, while `astropy.tools` is
-    more astronomy-focused.
-
-
-Reference/API
-=============
-
-.. automodapi:: astropy.tools
diff --git a/docs/units/composing_and_defining.rst b/docs/units/composing_and_defining.rst
new file mode 100644
index 0000000..c3500f7
--- /dev/null
+++ b/docs/units/composing_and_defining.rst
@@ -0,0 +1,42 @@
+Composing and defining units
+============================
+
+Units can be composed together using the regular Python numeric
+operators.  For example::
+
+  >>> from astropy import units as u
+  >>> fluxunit = u.erg / (u.cm ** 2 * u.s)
+  >>> fluxunit
+  Unit("erg / (cm2 s)")
+
+Users are free to define new units, either fundamental or compound
+using the `~astropy.units.core.def_unit` function.  For example::
+
+  >>> bakers_fortnight = u.def_unit('bakers_fortnight', 13 * u.day)
+
+The addition of a string gives the new unit a name that will show up
+when the unit is printed.
+
+Creating a new fundamental unit is simple::
+
+  >>> titter = u.def_unit('titter')
+  >>> chuckle = u.def_unit('chuckle', 5 * titter)
+  >>> laugh = u.def_unit('laugh', 4 * chuckle)
+  >>> guffaw = u.def_unit('guffaw', 3 * laugh)
+  >>> rofl = u.def_unit('rofl', 4 * guffaw)
+  >>> death_by_laughing = u.def_unit('death_by_laughing', 10 * rofl)
+  >>> rofl.to(titter, 1)
+  240
+
+Reducing a unit to its irreducible parts
+----------------------------------------
+
+A unit can be decomposed into its irreducible parts using the
+`~astropy.units.core.UnitBase.decompose` method::
+
+  >>> u.Ry
+  Unit("Ry")
+  >>> u.Ry.decompose()
+  Unit("2.18e-18 m2 kg / (s2)")
+
+.. TODO: Add function and description to factor units into high-level pieces
diff --git a/docs/units/conversion.rst b/docs/units/conversion.rst
new file mode 100644
index 0000000..2fd8e87
--- /dev/null
+++ b/docs/units/conversion.rst
@@ -0,0 +1,59 @@
+Unit Conversion
+===============
+
+There are two ways of handling conversions between units.
+
+Direct Conversion
+-----------------
+
+In this case, given a source and destination unit, the value(s) in the
+new units is(are) returned.
+
+  >>> from astropy import units as u
+  >>> u.pc.to(u.m, 3.26)
+  1.0059317615e+17
+
+This converts 3.26 parsecs to meters.
+
+Arrays are permitted as arguments.
+
+  >>> u.h.to(u.s, [1, 2, 5, 10.1])
+  array([  3600.,   7200.,  18000.,  36360.])
+
+Obtaining a Conversion Function
+-------------------------------
+
+Finally, one may obtain a function that can be used to convert to the
+new unit. Normally this may seem like overkill when all one needs to
+do is multiply by a scale factor, but there are cases when the
+transformation between units may not be as simple as a single scale
+factor, for example when a custom equivalency table is in use.
+
+Conversion to different units involves obtaining a conversion function
+and then applying it to the value, or values to be converted.
+
+  >>> cms = u.cm / u.s
+  >>> cms_to_mph = cms.get_converter(u.mile / u.hour)
+  >>> cms_to_mph(100.)
+  2.2366936292054402
+  >>> cms_to_mph([1000, 2000])
+  array([ 22.36936292,  44.73872584])
+
+Incompatible Conversions
+------------------------
+
+If you attempt to convert to a incompatible unit, an exception will result:
+
+  >>> cms.to(u.mile)
+  ...
+  UnitsException: 'cm / (s)' (speed) and 'mi' (length) are not convertible
+
+You can check whether a particular conversion is possible using the
+`~astropy.units.core.UnitBase.is_equivalent` method::
+
+  >>> u.m.is_equivalent(u.foot)
+  True
+  >>> u.m.is_equivalent("second")
+  False
+  >>> (u.m ** 2).is_equivalent(u.acre)
+  True
diff --git a/docs/units/equivalencies.rst b/docs/units/equivalencies.rst
new file mode 100644
index 0000000..262b594
--- /dev/null
+++ b/docs/units/equivalencies.rst
@@ -0,0 +1,139 @@
+.. _unit_equivalencies:
+
+Equivalencies
+=============
+
+The unit module has machinery for supporting equivalences between
+different units in certain contexts. Namely when equations can
+uniquely relate a value in one unit to a different unit. A good
+example is the equivalence between wavelength, frequency and energy
+for specifying a wavelength of radiation. Normally these units are not
+convertible, but when understood as representing light, they are
+convertible.  This will describe how to use two of the equivalencies
+include in `astropy.units` and then describe how to define new
+equivalencies.
+
+Equivalencies are used by passing a list of equivalency pairs to the
+`equivs` keyword argument of `~astropy.units.core.UnitBase.to` or
+`~astropy.units.core.UnitBase.get_converter` methods.
+
+Built-in equivalencies
+----------------------
+
+Spectral Units
+^^^^^^^^^^^^^^
+
+`~astropy.units.equivalencies.spectral` is a function that returns an
+equivalency list to handle conversions between wavelength, frequency
+and energy.
+
+Length and frequency are not normally convertible, so
+`~astropy.units.core.UnitBase.to` raises an exception::
+
+  >>> from astropy import units as u
+  >>> u.nm.to(u.Hz, [1000, 2000])
+  UnitsException: 'nm' (length) and 'Hz' (frequency) are not convertible
+
+However, when passing the result of `~astropy.units.equivalencies.spectral`
+as the third argument to the `~astropy.units.core.UnitBase.to` method,
+wavelength, frequency and energy can be converted.
+
+  >>> u.nm.to(u.Hz, [1000, 2000], equivs=u.spectral())
+  array([  2.99792458e+14,   1.49896229e+14])
+  >>> u.nm.to(u.eV, [1000, 2000], equivs=u.spectral())
+  array([ 1.23984201,  0.61992101])
+
+These equivalencies even work with non-base units::
+
+  >>> # Inches to calories
+  >>> u.inch.to(u.Cal, 1, equivs=u.spectral())
+  1.869180759162485e-27
+
+Spectral Flux Density Units
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+There is also support for spectral flux density units. Their use is more
+complex, since it is necessary to also supply the location in the spectrum for
+which the conversions will be done, and the units of those spectral locations.
+The function that handles these unit conversions is
+`~astropy.units.equivalencies.spectral_density`. This function takes as its
+arguments the unit and value for the spectral location. For example::
+
+  >>> u.Jy.to(u.erg / u.cm**2 / u.s / u.Hz, 1., equivs=u.spectral_density(u.AA, 3500))
+  1.0000000000000001e-23
+
+  >>> u.Jy.to(u.erg / u.cm**2 / u.s / u.micron, 1., equivs=u.spectral_density(u.AA, 3500))
+  2.4472853714285712e-08
+
+Writing new equivalencies
+-------------------------
+
+An equivalence list is just a list of tuples, where each tuple has 4
+elements::
+
+  (from_unit, to_unit, forward, backward)
+
+`from_unit` and `to_unit` are the equivalent units.  `forward` and
+`backward` are functions that convert values between those units.
+
+For example, until 1964 the metric liter was defined as the volume of
+1kg of water at 4°C at 760mm mercury pressure.  Volumes and masses are
+not normally directly convertible, but if we hold the constants in the
+1964 definition of the liter as true, we could build an equivalency
+for them::
+
+  >>> liters_water = [
+         (u.l, u.g, lambda x: 1000.0 * x, lambda x: x / 1000.0)
+      ]
+  >>> u.l.to(u.kg, 1, equivs=liters_water)
+  1.0
+
+Note that the equivalency can be used with any other compatible units::
+
+  >>> u.gallon.to(u.pound, 1, equivs=liters_water)
+  8.345404463333525
+
+And it also works in the other direction::
+
+  >>> u.lb.to(u.pint, 1, equivs=liters_water)
+  0.9586114172355458
+
+Displaying available equivalencies
+----------------------------------
+
+The `find_equivalent_units` function also understands equivalencies.
+For example, without passing equivalencies, there are no compatible
+units for `Hz` in the standard set::
+
+  >>> u.Hz.find_equivalent_units()
+    Primary name | Unit definition | Aliases
+  [
+    Hz           | 1 / (s)         | Hertz, hertz ,
+  ]
+
+However, when passing the spectral equivalency, you can see there are
+all kinds of things that `Hz` can be converted to::
+
+  >>> u.Hz.find_equivalent_units(equivs=u.spectral())
+    Primary name | Unit definition           | Aliases
+  [
+    AU           | 1.495979e+11 m            | au                                 ,
+    Angstrom     | 1.000000e-10 m            | AA, angstrom                       ,
+    BTU          | 1.055056e+03 kg m2 / (s2) | btu                                ,
+    Hz           | 1 / (s)                   | Hertz, hertz                       ,
+    J            | kg m2 / (s2)              | Joule, joule                       ,
+    Ry           | 2.179872e-18 kg m2 / (s2) | rydberg                            ,
+    cal          | 4.184000e+00 kg m2 / (s2) | calorie                            ,
+    eV           | 1.602177e-19 kg m2 / (s2) | electronvolt                       ,
+    erg          | 1.000000e-07 kg m2 / (s2) |                                    ,
+    ft           | 3.048000e-01 m            | foot                               ,
+    inch         | 2.540000e-02 m            |                                    ,
+    kcal         | 4.184000e+03 kg m2 / (s2) | Cal, Calorie, kilocal, kilocalorie ,
+    lyr          | 9.460730e+15 m            |                                    ,
+    m            | irreducible               | meter                              ,
+    mi           | 1.609344e+03 m            | mile                               ,
+    micron       | 1.000000e-06 m            |                                    ,
+    pc           | 3.085678e+16 m            | parsec                             ,
+    solRad       | 6.955080e+08 m            |                                    ,
+    yd           | 9.144000e-01 m            | yard                               ,
+  ]
diff --git a/docs/units/format.rst b/docs/units/format.rst
new file mode 100644
index 0000000..d010aa6
--- /dev/null
+++ b/docs/units/format.rst
@@ -0,0 +1,137 @@
+Unit formats
+============
+
+Units can be created from strings using the `~astropy.units.core.Unit`
+class::
+
+  >>> from astropy import units as u
+  >>> u.Unit("m")
+  Unit("m")
+  >>> u.Unit("erg / (s cm2)")
+  Unit("erg / (s cm2)")
+
+.. note::
+
+   Creating units from strings requires the use of a specialized
+   parser for the unit language, which results in a performance
+   penalty if units are created using strings.  Thus, it is much
+   faster to use unit objects directly (e.g., ``unit = u.degree /
+   u.minute``) instead of via string parsing (``unit =
+   u.Unit('deg/min')``).
+
+Units can be converted to strings using the
+`~astropy.units.core.UnitBase.to_string` method::
+
+  >>> fluxunit = u.erg / (u.cm ** 2 * u.s)
+  >>> fluxunit.to_string()
+  u'erg / (cm2 s)'
+
+By default, the string format used is referred to as the "generic"
+format, which is based on syntax of the FITS standard's format for
+representing units, but supports all of the units defined within the
+`astropy.units` framework, including user-defined units.  The
+`~astropy.units.core.Unit` and
+`~astropy.units.core.UnitBase.to_string` functions also take an
+optional `format` parameter to select a different format.
+
+Built-in formats
+----------------
+
+`astropy.units` includes support for parsing and writing the following
+formats:
+
+  - ``"fits"``: This is the format defined in the Units section of the
+    `FITS Standard <http://fits.gsfc.nasa.gov/fits_standard.html>`_.
+    Unlike the "generic" string format, this will only accept or
+    generate units defined in the FITS standard.
+
+  - ``"vounit"``: The `proposed IVOA standard
+    <http://www.ivoa.net/Documents/VOUnits/>`_ for representing units
+    in the VO.  Again, based on the FITS syntax, but the collection of
+    supported units is different.
+
+  - ``"cds"``: `Standards for astronomical catalogues from Centre de
+    Données astronomiques de Strasbourg
+    <http://cds.u-strasbg.fr/doc/catstd-3.2.htx>`_: This is the
+    standard used, for example, by VOTable versions 1.2 and earlier.
+
+.. These are to-be-implemented
+
+  - OGIP Units: A standard for storing units in `OGIP FITS files
+    <http://heasarc.gsfc.nasa.gov/docs/heasarc/ofwg/docs/general/ogip_93_001/>`_.
+
+`astropy.units` is also able to write, but not read, units in the
+following formats:
+
+  - ``"latex"``: Writes units out using LaTeX math syntax using the
+    `IAU Style Manual
+    <http://www.iau.org/static/publications/stylemanual1989.pdf>`_
+    recommendations for unit presentation.  This format is
+    automatically used when printing a unit in the IPython notebook::
+
+      >>> fluxunit
+
+    .. math::
+
+       \mathrm{\frac{erg}{s\ cm^{2}}}
+
+  - ``"console"``: Writes a multi-line representation of the unit
+    useful for display in a text console::
+
+      >>> print fluxunit.to_string('console')
+       erg
+      ------
+      s cm^2
+
+  - ``"unicode"``: Same as ``"console"``, except uses Unicode
+    characters::
+
+      >>> print u.Ry.decompose().to_string('unicode')
+                 m² kg
+      2.18×10-¹⁸ ─────
+                  s²
+
+Unrecognized Units
+------------------
+
+Since many files in found in the wild have unit strings that do not
+correspond to any given standard, `astropy.units` also has a
+consistent way to store and pass around unit strings that did not
+parse.
+
+Normally, passing an unrecognized unit string raises an exception::
+
+  >>> u.Unit("m/s/s")  # The FITS standard only allows one '/'
+  ValueError: Expected end of text (at char 3) in 'm/s/s'
+
+However, the `~astropy.units.core.Unit` constructor has the keyword
+argument `parse_strict` that can take one of three values to control
+this behavior:
+
+  - ``'raise'``: (default) raise a ValueError exception.
+
+  - ``'warn'``: emit a Warning, and return an
+    `~astropy.units.core.UnrecognizedUnit` instance.
+
+  - ``'silent'``: return an `~astropy.units.core.UnrecognizedUnit`
+    instance.
+
+So, for example, one can do::
+
+   >>> x = u.Unit("m/s/s", parse_strict="warn")
+   WARNING: UnitsWarning: 'm/s/s' did not parse using format 'generic'.
+   Expected end of text (at char 3) in 'm/s/s' [astropy.units.core]
+
+This `~astropy.units.core.UnrecognizedUnit` object remembers the
+original string it was created with, so it can be written back out,
+but any meaningful operations on it, such as converting to another
+unit or composing with other units, will fail.
+
+   >>> x.to_string()
+   'm/s/s'
+   >>> x.to(u.km / u.s / u.s)
+   ValueError: The unit 'm/s/s' is unrecognized.  It can not be converted to
+   other units.
+   >>> x / u.m
+   ValueError: The unit 'm/s/s' is unrecognized, so all arithmetic operations
+   with it are invalid.
diff --git a/docs/units/index.rst b/docs/units/index.rst
new file mode 100644
index 0000000..641edc1
--- /dev/null
+++ b/docs/units/index.rst
@@ -0,0 +1,121 @@
+***********************
+Units (`astropy.units`)
+***********************
+
+.. currentmodule:: astropy.units
+
+Introduction
+============
+
+``astropy.units`` is a Python package to handle defining and converting
+between physical units, and performing arithmetic with physical quantities
+(numbers with associated units).
+
+Getting Started
+===============
+
+  >>> from astropy import units as u
+  >>> # Convert from parsec to meter
+  >>> u.pc.to(u.m)
+  3.0856776e+16
+  >>> cms = u.cm / u.s
+  >>> mph = u.mile / u.hour
+  >>> cms.to(mph, 1)
+  0.02236936292054402
+  >>> cms.to(mph, [1., 1000., 5000.])
+  array([  2.23693629e-02,   2.23693629e+01,   1.11846815e+02])
+
+Units that "cancel out" become a special unit called the
+"dimensionless unit":
+
+  >>> u.m / u.m
+  Unit(dimensionless)
+
+`astropy.units` also handles equivalencies, such as that between
+wavelength and frequency.  To use that feature, equivalence objects
+are passed to the `~astropy.units.core.UnitBase.to` conversion method::
+
+  # Wavelength to frequency doesn't normally work
+  >>> u.nm.to(u.Hz, [1000, 2000])
+  UnitsException: 'nm' (length) and 'Hz' (frequency) are not convertible
+  # ...but by passing an equivalency unit (spectral()), it does...
+  >>> u.nm.to(u.Hz, [1000, 2000], equivs=u.spectral())
+  array([  2.99792458e+14,   1.49896229e+14])
+  >>> u.nm.to(u.eV, [1000, 2000], equivs=u.spectral())
+  array([ 1.23984201,  0.61992101])
+
+Also included in the `astropy.units` package is the `~astropy.units.quantity.Quantity` object,
+which represents a numerical value with an associated unit. These objects
+support arithmetic with other numbers and `~astropy.units.quantity.Quantity`  objects and preserve
+units::
+
+   >>> from astropy import units as u
+   >>> 15.1*u.meter / (32.0*u.second)
+   <Quantity 0.471875 m / (s)>
+   >>> 3.0*u.kilometer / (130.51*u.meter/u.second)
+   <Quantity 0.0229867443108 km s / (m)>
+   >>> (3.0*u.kilometer / (130.51*u.meter/u.second)).simplify_units()
+   <Quantity 22.9867443108 s>
+
+Using `astropy.units`
+=====================
+
+.. toctree::
+   :maxdepth: 2
+
+   standard_units
+   composing_and_defining
+   conversion
+   format
+   equivalencies
+   quantity
+
+See Also
+========
+
+- `FITS Standard <http://fits.gsfc.nasa.gov/fits_standard.html>`_ for
+  units in FITS.
+
+- The `proposed IVOA standard
+  <http://www.ivoa.net/Documents/VOUnits/>`_ for representing units in
+  the VO.
+
+- OGIP Units: A standard for storing units in `OGIP FITS files
+  <http://heasarc.gsfc.nasa.gov/docs/heasarc/ofwg/docs/general/ogip_93_001/>`_.
+
+- `Standards for astronomical catalogues units
+  <http://cds.u-strasbg.fr/doc/catstd-3.2.htx>`_.
+
+- `IAU Style Manual
+  <http://www.iau.org/static/publications/stylemanual1989.pdf>`_.
+
+- `A table of astronomical unit equivalencies
+  <http://astro.wku.edu/strolger/UNITS.txt>`_
+
+Reference/API
+=============
+
+.. automodapi:: astropy.units.core
+
+.. automodapi:: astropy.units.format
+
+.. automodapi:: astropy.units.si
+
+.. automodapi:: astropy.units.cgs
+
+.. automodapi:: astropy.units.astrophys
+
+.. automodapi:: astropy.units.imperial
+
+.. automodapi:: astropy.units.equivalencies
+
+.. automodapi:: astropy.units.quantity
+
+
+Acknowledgments
+===============
+
+This code is adapted from the `pynbody
+<http://code.google.com/p/pynbody/>`_ units module written by Andrew
+Pontzen, who has granted the Astropy project permission to use the
+code under a BSD license.
diff --git a/docs/units/quantity.rst b/docs/units/quantity.rst
new file mode 100644
index 0000000..f1473a0
--- /dev/null
+++ b/docs/units/quantity.rst
@@ -0,0 +1,98 @@
+Quantity
+========
+
+The `Quantity` object is meant to represent a value that has some unit
+associated with the number.
+
+Creating Quantity instances
+---------------------------
+
+`Quantity` objects are created through multiplication or divison with
+`Unit` objects. For example, to create a `Quantity` to represent
+:math:`15\frac{m}{s}`
+
+    >>> import astropy.units as u
+    >>> 15*u.m/u.s
+    <Quantity 15 m / (s)>
+
+or :math:`1.14s^{-1}`
+
+    >>> 1.14/u.s
+    <Quantity 1.14 1 / (s)>
+
+You can also create instances using the `Quantity` constructor directly,
+by specifying a value and unit
+
+    >>> u.Quantity(15, u.m/u.s)
+    <Quantity 15 m / (s)>
+
+Arithmetic
+----------
+
+Addition and Subtraction
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+Addition or subtraction between `Quantity` objects is supported when their
+units are equivalent (see `Unit` documentation). When the units are equal,
+the resulting object has the same unit
+
+    >>> 11*u.s + 30*u.s
+    <Quantity 41 s>
+    >>> 30*u.s - 11*u.s
+    <Quantity 19 s>
+
+If the units are equivalent, but not equal (e.g. kilometer and meter), the
+resulting object **has units of the object on the left**
+
+    >>> 1100.1*u.m + 13.5*u.km
+    <Quantity 14600.1 m>
+    >>> 13.5*u.km + 1100.1*u.m
+    <Quantity 14.6001 km>
+    >>> 1100.1*u.m - 13.5*u.km
+    <Quantity -12399.9 m>
+    >>> 13.5*u.km - 1100.1*u.m
+    <Quantity 12.3999 km>
+
+Addition and subtraction is not supported between `Quantity` objects and
+basic numeric types
+
+    >>> 13.5*u.km + 19.412
+    TypeError: Object of type '<type 'float'>' cannot be added with a Quantity object. Addition is only supported between Quantity objects.
+
+Multiplication and Division
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Multiplication and division is supported between `Quantity` objects with
+any units, and with numeric types. For these operations between objects
+with equivalent units, the **resulting object has composite units**
+
+    >>> 1.1*u.m * 140.3*u.cm
+    <Quantity 154.33 cm m>
+    >>> 140.3*u.cm * 1.1*u.m
+    <Quantity 154.33 cm m>
+    >>> 1.*u.m / (20.*u.cm)
+    <Quantity 0.05 m / (cm)>
+    >>> 20.*u.cm / (1.*u.m)
+    <Quantity 20.0 cm / (m)>
+
+For multiplication, you can choose how to represent the resulting
+object by using the `~astropy.units.quantity.Quantity.to` method
+
+    >>> (1.1*u.m * 140.3*u.cm).to(u.m**2)
+    <Quantity 1.5433 m2>
+    >>> (1.1*u.m * 140.3*u.cm).to(u.cm**2)
+    <Quantity 15433.0 cm2>
+
+For division, if the units are equivalent, you may want to make the
+resulting object dimensionless by reducing the units. To do this,
+use the `.simplify_units()` method
+
+    >>> (20.*u.cm / (1.*u.m)).simplify_units()
+    <Quantity 0.2 >
+
+This method is also useful for more complicated arithmetic
+
+    >>> 15.*u.kg * 32.*u.cm * 15*u.m / (11.*u.s * 1914.15*u.ms)
+    <Quantity 0.341950972779 cm kg m / (ms s)>
+    >>> (15.*u.kg * 32.*u.cm * 15*u.m / (11.*u.s * 1914.15*u.ms)).simplify_units()
+    <Quantity 3.41950972779 kg m2 / (s2)>
diff --git a/docs/units/standard_units.rst b/docs/units/standard_units.rst
new file mode 100644
index 0000000..9b75c03
--- /dev/null
+++ b/docs/units/standard_units.rst
@@ -0,0 +1,80 @@
+Standard units
+==============
+
+Standard units are defined in the `astropy.units` package as object
+instances.
+
+All units are defined in term of basic 'irreducible' units. The
+irreducible units include:
+
+  - Length (meter)
+  - Time (second)
+  - Mass (kilogram)
+  - Current (ampere)
+  - Temperature (Kelvin)
+  - Angular distance (radian)
+  - Solid angle (steradian)
+  - Luminous intensity (candela)
+  - Stellar magnitude (mag)
+  - Amount of substance (mole)
+  - Photon count (photon)
+
+(There are also some more obscure base units required by the FITS
+standard that are no longer recommended for use.)
+
+Units that involve combinations of fundamental units are instances of
+`~astropy.units.core.CompositeUnit`. In most cases, one does not need
+to worry about the various kinds of unit classes unless one wants to
+design a more complex case.
+
+There are many units already predefined in the module. One may use the
+following function to list all the existing predefined units of a
+given type::
+
+  >>> from astropy import units as u
+  >>> u.g.find_equivalent_units()
+    Primary name | Unit definition | Aliases
+  [
+    M_e          | 9.109383e-31 kg |            ,
+    M_p          | 1.672622e-27 kg |            ,
+    g            | 1.000000e-03 kg | gram       ,
+    kg           | irreducible     | kilogram   ,
+    lb           | 4.535924e-01 kg | pound      ,
+    oz           | 2.834952e-02 kg | ounce      ,
+    solMass      | 1.989100e+30 kg |            ,
+    t            | 1.000000e+03 kg | tonne      ,
+    ton          | 9.071847e+02 kg |            ,
+    u            | 1.660539e-27 kg | Da, Dalton ,
+  ]
+
+The dimensionless unit
+----------------------
+
+In addition to these units, `astropy.units` includes the concept of
+the dimensionless unit, used to indicate quantities that don't have a
+physical dimension.  This is distinct in concept from unit that is
+equal to `None`: that indicates that no unit was specified in the data
+or by the user.
+
+To obtain the dimensionless unit, use the
+`~astropy.units.dimensionless` object::
+
+   >>> from astropy import units as u
+   >>> u.dimensionless
+   Unit(dimensionless)
+
+Dimensionless quantities are often defined as products or ratios of
+quantities that are not dimensionless, but whose dimensions cancel out
+when their powers are multiplied.  For example::
+
+   >>> u.m / u.m
+   Unit(dimensionless)
+
+For compatibility with the supported unit string formats, this is
+equivalent to ``Unit('')`` and ``Unit(1)``, though using
+``u.dimensionless`` in Python code is preferred for readability::
+
+   >>> u.dimensionless == u.Unit('')
+   True
+   >>> u.dimensionless == u.Unit(1)
+   True
diff --git a/docs/utils/index.rst b/docs/utils/index.rst
index b2ec4fd..d394064 100644
--- a/docs/utils/index.rst
+++ b/docs/utils/index.rst
@@ -1,23 +1,24 @@
 .. _utils:
 
-**********************************************
-Developer-Oriented Utilities (`astropy.utils`)
-**********************************************
+************************************************
+Astropy Core Package Utilities (`astropy.utils`)
+************************************************
 
 Introduction
 ============
 
-The `astropy.utils` package contains general-purpose utilities
-functions and classes that such as general-purpose data structures,
-version intercompatibility functions. Basically, if it's not
-astronomy-related, but likely useful for other developers, it probably
-lives here. These are safe for users to make use of, but they are
-typically more complicated or esoteric enough that they are mostly of
-interest to developers.
+The `astropy.utils` package contains general-purpose utility functions and
+classes.  Examples include data structures, tools for downloading and caching
+from URLs, and version intercompatibility functions.
 
-Because of the mostly standalone and grab-bag nature of these utilities,
-they are generally best understood through their docstrings, and hence
-only the reference section is currently provided for this subpackage.
+This functionality is not astronomy-specific, but is intended primarily for
+use by Astropy developers. It is all safe for users to use, but the functions
+and classes are typically more complicated or specific to a particuly need of
+Astropy.
+
+Because of the mostly standalone and grab-bag nature of these utilities, they
+are generally best understood through their docstrings, and hence this
+documentation does not have detailed sections like the other packages.
 
 .. note::
     The `astropy.utils.compat` subpackage is not included in this
@@ -28,19 +29,46 @@ only the reference section is currently provided for this subpackage.
     subpackage, but it cannot be reliably included here because of the
     large amount of version-specific code it contains.
 
-See Also
-========
-
-* :ref:`tools`
-    The subpackage for tools that are oriented towards users, rather than
-    developers.  It is somewhat more astronomy-specific, while these are more
-    general-purpose.
-
 
 Reference/API
 =============
 
-.. automodapi:: astropy.utils
-    :no-main-section:
-    :subsections: collections, console, xml.check, xml.iterparser, xml.validate, xml.writer, misc
+.. automodapi:: astropy.utils.misc
+    :no-inheritance-diagram:
+
+.. automodapi:: astropy.utils.collections
+    :no-inheritance-diagram:
+
+.. automodapi:: astropy.utils.console
+    :no-inheritance-diagram:
+
+File Downloads
+--------------
+
+.. automodapi:: astropy.utils.data
     :no-inheritance-diagram:
+
+XML
+---
+The ``astropy.utils.xml.*`` modules provide various
+`XML <http://www.w3.org/XML/>`_ processing tools.
+
+.. automodapi:: astropy.utils.xml.check
+    :no-inheritance-diagram:
+    :headings: ^"
+
+.. automodapi:: astropy.utils.xml.iterparser
+    :no-inheritance-diagram:
+    :headings: ^"
+
+.. automodapi:: astropy.utils.xml.validate
+    :no-inheritance-diagram:
+    :headings: ^"
+
+.. automodapi:: astropy.utils.xml.writer
+    :no-inheritance-diagram:
+    :headings: ^"
+
+
+
+
diff --git a/docs/wcs/index.rst b/docs/wcs/index.rst
index cc5ef5a..a996c1c 100644
--- a/docs/wcs/index.rst
+++ b/docs/wcs/index.rst
@@ -28,36 +28,39 @@ The basic workflow is as follows:
 
     1. ``from astropy import wcs``
 
-    2. Call the `wcs.WCS` constructor with an `astropy.io.fits` header
-       and/or hdulist object.
+    2. Call the `~astropy.wcs.wcs.WCS` constructor with an
+       `astropy.io.fits` header and/or hdulist object.
 
     3. Optionally, if the FITS file uses any deprecated or
        non-standard features, you may need to call one of the
-       `~astropy.wcs.WCS.fix` methods on the object.
+       `~astropy.wcs.wcs.WCS.fix` methods on the object.
 
     4. Use one of the following transformation methods:
 
-       - `~WCS.all_pix2world`: Perform all three transformations from
-         pixel to world coordinates.
+       - `~astropy.wcs.wcs.WCS.all_pix2world`: Perform all three
+         transformations from pixel to world coordinates.
 
-       - `~WCS.wcs_pix2world`: Perform just the core WCS
-         transformation from pixel to world coordinates.
+       - `~astropy.wcs.wcs.WCS.wcs_pix2world`: Perform just the core
+         WCS transformation from pixel to world coordinates.
 
-       - `~WCS.wcs_world2pix`: Perform just the core WCS
-         transformation from world to pixel coordinates.
+       - `~astropy.wcs.wcs.WCS.wcs_world2pix`: Perform just the core
+         WCS transformation from world to pixel coordinates.
 
-       - `~WCS.sip_pix2foc`: Convert from pixel to focal plane
-         coordinates using the `SIP`_ polynomial coefficients.
+       - `~astropy.wcs.wcs.WCS.sip_pix2foc`: Convert from pixel to
+         focal plane coordinates using the `SIP`_ polynomial
+         coefficients.
 
-       - `~WCS.sip_foc2pix`: Convert from focal plane to pixel
-         coordinates using the `SIP`_ polynomial coefficients.
+       - `~astropy.wcs.wcs.WCS.sip_foc2pix`: Convert from focal plane
+         to pixel coordinates using the `SIP`_ polynomial
+         coefficients.
 
-       - `~WCS.p4_pix2foc`: Convert from pixel to focal plane
-         coordinates using the table lookup distortion method
-         described in `Paper IV`_.
+       - `~astropy.wcs.wcs.WCS.p4_pix2foc`: Convert from pixel to
+         focal plane coordinates using the table lookup distortion
+         method described in `Paper IV`_.
 
-       - `~WCS.det2im`: Convert from detector coordinates to image
-         coordinates.  Commonly used for narrow column correction.
+       - `~astropy.wcs.wcs.WCS.det2im`: Convert from detector
+         coordinates to image coordinates.  Commonly used for narrow
+         column correction.
 
 
 Using `astropy.wcs`
@@ -89,7 +92,6 @@ Other information
    :maxdepth: 1
 
    relax
-   units
    history
 
 
diff --git a/docs/wcs/relax.rst b/docs/wcs/relax.rst
index 3a7cb6b..10d2b38 100644
--- a/docs/wcs/relax.rst
+++ b/docs/wcs/relax.rst
@@ -363,3 +363,5 @@ The flag bits are:
   lists.  While the constructor treats ``WCSNna`` and ``TWCSna`` as
   equivalent, other parsers may not.  Consequently, this usage is
   potentially unsafe and is not recommended at this time.
+
+- `WCSHDO_SIP`: Write out Simple Imaging Polynomial (SIP) keywords.
diff --git a/docs/wcs/units.rst b/docs/wcs/units.rst
deleted file mode 100644
index f8fac7e..0000000
--- a/docs/wcs/units.rst
+++ /dev/null
@@ -1,291 +0,0 @@
-.. include:: references.txt
-
-.. _fits-unit:
-
-FITS unit specification
-=======================
-
-Supported units
----------------
-
-The following units are supported by the FITS standard:
-
-**SI base & supplementary units**
-
-====================== ============ =================
-Quantity               Unit String  Meaning
-====================== ============ =================
-length                 m            metre
-mass                   kg           kilogram
-time                   s            second of time
-plane angle            rad          radian
-solid angle            sr           steradian
-temperature            K            kelvin
-electric current       A            ampere
-amount of substance    mol          mole
-luminous intensity     cd           candela
-====================== ============ =================
-
-**IAU-recognized derived units**
-
-====================== ============ ================= ==================
-Quantity               Unit String  Meaning           Equivalence
-====================== ============ ================= ==================
-frequency              Hz           hertz             s\ :sup:`-1`
-energy                 J            joule             N m
-power                  W            watt              J s\ :sup:`-1`
-electric potential     V            volts             J C\ :sup:`-1`
-force                  N            newton            kg m s\ :sup:`-2`
-pressure, stress       Pa           pascal            N m\ :sup:`-2`
-electric charge        C            coulomb           A s
-electric resistance    ohm          ohm (Ω)           V A\ :sup:`-1`
-electric conductance   S            siemens           A V\ :sup:`-1`
-electric capacitance   F            farad             C V\ :sup:`-1`
-magnetic flux          Wb           weber             V s
-magnetic flux density  T            tesla             Wb m\ :sup:`-2`
-inductance             H            henry             Wb A\ :sup:`-1`
-luminous flux          lm           lumen             cd sr
-illuminance            lx           lux               lm m\ :sup:`-2`
-====================== ============ ================= ==================
-
-**Additional units**
-
-====================== ============ ======================== ============================================
-Quantity               Unit String  Meaning                  Equivalence
-====================== ============ ======================== ============================================
-mass                   u            unified atomic mass unit 1.6605387 x 10\ :sup:`-27` kg
-mass                   solMass      solar mass               1.9891 x 10\ :sup:`30` kg
-plane angle            deg          degree of arc            1.745533 x 10\ :sup:`-2` rad
-plane angle            arcsec       second of arc            4.848137 x 10\ :sup:`-6` rad
-plane angle            arcmin       minute of arc            2.90888 x 10\ :sup:`-4` rad
-time                   min          minute
-time                   h            hour
-time                   d            day                      8.64 x 10\ :sup:`4` s
-time                   yr           year (Julian)            3.15576 x10\ :sup:`-7` s (365.25 d)
-energy                 eV           electron volt            1.602177 x 10\ :sup:`-19` J
-energy                 erg          erg                      10\ :sup:`-7` J
-energy                 Ry           Rydberg                  13.605692 eV
-length                 angstrom     angstrom                 10\ :sup:`-10` m
-length                 AU           astronomical unit        1.49598 x 10\ :sup:`11` m
-length                 lyr          light year               9.460530 x 10\ :sup:`-15` m
-length                 pc           parsec                   3.0857 x 10\ :sup:`-16` m
-length                 solRad       solar radius             6.9599 x 10\ :sup:`8` m
-events                 count        counts
-events                 photon       photons
-flux density           Jy           jansky                   10\ :sup:`-16` W m\ :sup:`-2` Hz\ :sup:`-1`
-flux density           mag          (stellar) magnitude
-flux density           Crab         'crab'
-flux density           beam         beam                     Jy/beam
-flux density           solLum       solar luminosity
-magnetic field         G            gauss                    10\ :sup:`-4` T
-area                   pixel        (image/detector) pixel
-area                   voxel        3-d analog of pixel
-area                   barn         barn                     10\ :sup:`-28` m\ :sup:`2`
-device                 chan         (detector) channel
-device                 byte         (computer) byte
-device                 bit          (computer) bits
-device                 adu          A/D converter units
-misc                   bin          numerous applications
-misc                   Sun          wrt. sun
-====================== ============ ======================== ============================================
-
-Potentially unsafe translations of ``"D"``, ``"H"``, and ``"S"``, are
-optional, using the *translate_units* parameter.
-
-.. _unit-aliases:
-
-Unit aliases
-------------
-
-When converting non-standard units to standard ones, a case-sensitive
-match is required for the aliases listed below, in particular the only
-recognized aliases with metric prefixes are ``"KM"``, ``"KHZ"``,
-``"MHZ"``, and ``"GHZ"``.
-
-========== =============================================================
-Unit       Recognized aliases
-========== =============================================================
-Angstrom   angstrom
-arcmin     arcmins, ARCMIN, ARCMINS
-arcsec     arcsecs, ARCSEC, ARCSECS
-beam       BEAM
-byte       Byte
-count      ct
-d          day, days, (D), DAY, DAYS
-deg        degree, degrees, DEG, DEGREE, DEGREES
-GHz        GHZ
-h          hr, (H), HR
-Hz         hz, HZ
-kHz        KHZ
-Jy         JY
-K          kelvin, kelvins, Kelvin, Kelvins, KELVIN, KELVINS
-km         KM
-m          metre, meter, metres, meters, M, METRE, METER, METRES, METERS
-min        MIN
-MHz        MHZ
-Ohm        ohm
-Pa         pascal, pascals, Pascal, Pascals, PASCAL, PASCALS
-photon     ph
-pixel      pixels, PIXEL, PIXELS, pix
-rad        radian, radians, RAD, RADIAN, RADIANS
-s          sec, second, seconds, (S), SEC, SECOND, SECONDS
-V          volt, volts, Volt, Volts, VOLT, VOLTS
-yr         year, years, YR, YEAR, YEARS
-========== =============================================================
-
-The aliases ``"angstrom"``, ``"ohm"``, and ``"Byte"`` for (Angstrom,
-Ohm, and byte) are recognized by astropy.wcs/wcslib itself as an
-unofficial extension of the standard, but they are converted to the
-standard form here.
-
-Prefixes
---------
-
-The following metric prefixes are supported:
-
-======= ======= ===================
-Prefix  String  Magnitude
-======= ======= ===================
-yocto   y       10\ :sup:`-24`
-zepto   z       10\ :sup:`-21`
-atto    a       10\ :sup:`-18`
-femto   f       10\ :sup:`-15`
-pico    p       10\ :sup:`-12`
-nano    n       10\ :sup:`-9`
-micro   u       10\ :sup:`-6`
-milli   m       10\ :sup:`-3`
-centi   c       10\ :sup:`-2`
-deci    d       10\ :sup:`-1`
-deka    da      10\ :sup:`1`
-hecto   h       10\ :sup:`2`
-kilo    k       10\ :sup:`3`
-Mega    M       10\ :sup:`6`
-Giga    G       10\ :sup:`9`
-Tera    T       10\ :sup:`12`
-Peta    P       10\ :sup:`15`
-Exa     E       10\ :sup:`18`
-Zetta   Z       10\ :sup:`21`
-Yotta   Y       10\ :sup:`24`
-======= ======= ===================
-
-Table 6 of WCS Paper I lists eleven units for which metric prefixes
-are allowed.  However, in this implementation only prefixes greater
-than unity are allowed for ``"a"`` (annum), ``"yr"`` (year), ``"pc"``
-(parsec), ``"bit"``, and ``"byte"``, and only prefixes less than unity
-are allowed for ``"mag"`` (stellar magnitude).
-
-Metric prefix ``"P"`` (peta) is specifically forbidden for ``"a"``
-(annum) to avoid confusion with ``"Pa"`` (Pascal, not peta-annum).
-Note that metric prefixes are specifically disallowed for ``"h"``
-(hour) and ``"d"`` (day) so that ``"ph"`` (photons) cannot be
-interpreted as pico-hours, nor ``"cd"`` (candela) as centi-days.
-
-Operators
----------
-
-A compound unit is considered to be formed by a series of sub-strings
-of component units & mathematical operations. Each of these
-sub-strings must be separated by at least one space or a mathematical
-operator (``*`` or ``/``).
-
-Multiplication
-^^^^^^^^^^^^^^
-
-Multiplicative units can be specified either:
-
-- by simply using one or more preceding spaces, e.g. ``str1 str2``
-  (The recommended method).
-
-- by the use of a single asterisk (``*``) with optional whitespace,
-  e.g. ``str1 * str2``.
-
-Division
-^^^^^^^^
-
-Units which form the denominator of a compound expression can be
-specified either:
-
-- by using a slash (``/``) with optional whitespace, e.g. ``str1 /
-  str2``.  If such a syntax is used, it is recommended that no space
-  is included between the slash and the unit string.
-
-- by raising a multiplicative unit to a negative power (see below).
-
-It should be stressed that the slash character only effects the
-sub-string it immediately precedes. Thus, unless brackets are used,
-subsequent sub-strings which also form part of the denominator of the
-compound expression must also be preceded by a slash.  For example,
-``str1 /str2 str3`` is equivalent to ``str1 str3 /str2`` whilst ``str1
-/str2 /str3`` is equivalent to ``str1 /(str2 * str3)``.
-
-Raising to Powers
-^^^^^^^^^^^^^^^^^
-
-A unit string raised to the power *y* is specified:
-
-- by using two asterisks (``**``) followed by the index enclosed
-  within round brackets and with no preceding or intervening spaces,
-  e.g. ``str1**(y)`` or ``str1**(-y)``.
-
-However, if *y* is positive, then the brackets need not be included,
-but a following space is recommended if additional sub-strings follow.
-
-Use of brackets
-^^^^^^^^^^^^^^^
-
-Any number of pairs of round brackets (``()``) may be used within the
-string for a compound unit in order to prevent ambiguities. As
-described within this section, a number of rules always/often require
-their use. However, it is suggested that conservative use is made of
-such pairs of brackets in order to minimize the total length of
-compound strings.  (It should be remembered that a maximum of 68
-characters are allowed in the card image of keywords.)
-
-Avoidance of underflows & overflows
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-The inclusion of numerical factors within the unit string should
-generally be avoided (by the use of multiples and/or submultiples of
-component basic units).
-
-However, occasionally it may be preferable to include such factors on
-the grounds of user-friendliness and/or to minimize the risk of
-computer under- or overflows. In such cases, the numerical factor can
-simply be considered a basic unit string.
-
-The following additional guidelines are suggested:
-
-- the numerical factor should precede any unit strings
-
-- only powers of 10 are used as numerical factors
-
-Mathematical Operations & Functions
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-A number of mathematical operations are supported.  It should be noted
-that the (round) brackets are mandatory in all cases in which they are
-included in the table.
-
-=============== ==================================================
-String          Meaning
-=============== ==================================================
-``str1*str2``   Multiplication
-``str1 /str2``  Division
-``str1**(y)``   Raised to the power *y*
-``log(str1)``   Common Logarithm (to base 10)
-``ln(str1)``    Natural Logarithm
-``exp(str1)``   Exponential (exp\ :sup:`str1`\ )
-``sqrt(str1)``  Square root
-``sin(str1)``   Sine
-``cos(str1)``   Cosine
-``tan(str1)``   Tangent
-``asin(str1)``  Arc Sine
-``acos(str1)``  Arc Cosine
-``atan(str1)``  Arc Tangent
-``sinh(str1)``  Hyperbolic Sine
-``cosh(str1)``  Hyperbolic Cosine
-``tanh(str1)``  Hyperbolic Tangent
-=============== ==================================================
-
-Function types ``log()``, ``ln()`` and ``exp()`` may only occur at the
-start of the units specification.
diff --git a/docs/whatsnew/0.1.rst b/docs/whatsnew/0.1.rst
new file mode 100644
index 0000000..4c3b75e
--- /dev/null
+++ b/docs/whatsnew/0.1.rst
@@ -0,0 +1,26 @@
+=========================
+What's New in Astropy 0.1
+=========================
+
+This was the initial version of Astropy, released on June 19, 2012.  It was
+released primarily as a "developer preview" for developers interested in
+working directly on Astropy, on affiliated packages, or on other software that
+might integrate with Astropy.
+
+Astropy 0.1 integrated several existing packages under a single ``astropy``
+package with a unified installer, including:
+
+ * asciitable as :mod:`astropy.io.ascii`
+ * PyFITS as :mod:`astropy.io.fits`
+ * votable as :mod:`astropy.io.vo`
+ * PyWCS as :mod:`astropy.wcs`
+
+It also added the beginnings of the :mod:`astropy.cosmology` package, and new
+common data structures for science data in the :mod:`astropy.nddata` and
+:mod:`astropy.table` packages.
+
+It also laid much of the groundwork for Astropy's installation and
+documentation frameworks, as well as tools for managing configuration and data
+management.  These facilities are designed to be shared by Astropy's affiliated
+packages in the hopes of providing a framework on which other Astronomy-related
+Python packages can build.
diff --git a/docs/whatsnew/0.2.rst b/docs/whatsnew/0.2.rst
new file mode 100644
index 0000000..fb2913f
--- /dev/null
+++ b/docs/whatsnew/0.2.rst
@@ -0,0 +1,5 @@
+.. _whatsnew-0.2:
+
+=========================
+What's New in Astropy 0.2
+=========================
diff --git a/docs/whatsnew/index.rst b/docs/whatsnew/index.rst
new file mode 100644
index 0000000..9f64916
--- /dev/null
+++ b/docs/whatsnew/index.rst
@@ -0,0 +1,9 @@
+=====================
+Major Release History
+=====================
+
+.. toctree::
+   :maxdepth: 1
+
+   0.2
+   0.1
diff --git a/licenses/PYFITS.rst b/licenses/PYFITS.rst
index 422950c..26cd60a 100644
--- a/licenses/PYFITS.rst
+++ b/licenses/PYFITS.rst
@@ -1,4 +1,4 @@
-Copyright (C) 2005 Association of Universities for Research in Astronomy (AURA)
+Copyright (C) 2012 Association of Universities for Research in Astronomy (AURA)
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:
diff --git a/licenses/PYPARSING_LICENSE.rst b/licenses/PYPARSING_LICENSE.rst
new file mode 100644
index 0000000..bbc959e
--- /dev/null
+++ b/licenses/PYPARSING_LICENSE.rst
@@ -0,0 +1,18 @@
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/licenses/PYTEST_LICENSE.rst b/licenses/PYTEST_LICENSE.rst
new file mode 100644
index 0000000..ff33b8f
--- /dev/null
+++ b/licenses/PYTEST_LICENSE.rst
@@ -0,0 +1,18 @@
+
+  Permission is hereby granted, free of charge, to any person obtaining a copy
+  of this software and associated documentation files (the "Software"), to deal
+  in the Software without restriction, including without limitation the rights
+  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+  copies of the Software, and to permit persons to whom the Software is
+  furnished to do so, subject to the following conditions:
+
+  The above copyright notice and this permission notice shall be included in all
+  copies or substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+  SOFTWARE.
diff --git a/licenses/SOFA.rst b/licenses/SOFA.rst
new file mode 100644
index 0000000..d5de76a
--- /dev/null
+++ b/licenses/SOFA.rst
@@ -0,0 +1,97 @@
+.. Complete SOFA Software License.  This is included in a verbatim block
+   to retain the exact formatting of the original as included in the
+   SOFA C software library code "sofa.c".
+
+::
+
+  Copyright (C) 2012
+  Standards Of Fundamental Astronomy Board
+  of the International Astronomical Union.
+
+  =====================
+  SOFA Software License
+  =====================
+
+  NOTICE TO USER:
+
+  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND
+  CONDITIONS WHICH APPLY TO ITS USE.
+
+  1. The Software is owned by the IAU SOFA Board ("SOFA").
+
+  2. Permission is granted to anyone to use the SOFA software for any
+     purpose, including commercial applications, free of charge and
+     without payment of royalties, subject to the conditions and
+     restrictions listed below.
+
+  3. You (the user) may copy and distribute SOFA source code to others,
+     and use and adapt its code and algorithms in your own software,
+     on a world-wide, royalty-free basis.  That portion of your
+     distribution that does not consist of intact and unchanged copies
+     of SOFA source code files is a "derived work" that must comply
+     with the following requirements:
+
+     a) Your work shall be marked or carry a statement that it
+        (i) uses routines and computations derived by you from
+        software provided by SOFA under license to you; and
+        (ii) does not itself constitute software provided by and/or
+        endorsed by SOFA.
+
+     b) The source code of your derived work must contain descriptions
+        of how the derived work is based upon, contains and/or differs
+        from the original SOFA software.
+
+     c) The names of all routines in your derived work shall not
+        include the prefix "iau" or "sofa" or trivial modifications
+        thereof such as changes of case.
+
+     d) The origin of the SOFA components of your derived work must
+        not be misrepresented;  you must not claim that you wrote the
+        original software, nor file a patent application for SOFA
+        software or algorithms embedded in the SOFA software.
+
+     e) These requirements must be reproduced intact in any source
+        distribution and shall apply to anyone to whom you have
+        granted a further right to modify the source code of your
+        derived work.
+
+     Note that, as originally distributed, the SOFA software is
+     intended to be a definitive implementation of the IAU standards,
+     and consequently third-party modifications are discouraged.  All
+     variations, no matter how minor, must be explicitly marked as
+     such, as explained above.
+
+  4. You shall not cause the SOFA software to be brought into
+     disrepute, either by misuse, or use for inappropriate tasks, or
+     by inappropriate modification.
+
+  5. The SOFA software is provided "as is" and SOFA makes no warranty
+     as to its use or performance.   SOFA does not and cannot warrant
+     the performance or results which the user may obtain by using the
+     SOFA software.  SOFA makes no warranties, express or implied, as
+     to non-infringement of third party rights, merchantability, or
+     fitness for any particular purpose.  In no event will SOFA be
+     liable to the user for any consequential, incidental, or special
+     damages, including any lost profits or lost savings, even if a
+     SOFA representative has been advised of such damages, or for any
+     claim by any third party.
+
+  6. The provision of any version of the SOFA software under the terms
+     and conditions specified herein does not imply that future
+     versions will also be made available under the same terms and
+     conditions.
+
+  In any published work or commercial product which uses the SOFA
+  software directly, acknowledgement (see www.iausofa.org) is
+  appreciated.
+
+  Correspondence concerning SOFA software should be addressed as
+  follows:
+
+      By email:  sofa at ukho.gov.uk
+      By post:   IAU SOFA Center
+                 HM Nautical Almanac Office
+                 UK Hydrographic Office
+                 Admiralty Way, Taunton
+                 Somerset, TA1 2DN
+                 United Kingdom
diff --git a/scripts/volint b/scripts/volint
index a633f1b..899600e 100755
--- a/scripts/volint
+++ b/scripts/volint
@@ -1,5 +1,5 @@
 #!/usr/bin/env python
 
-import astropy.io.vo.volint
+import astropy.io.votable.volint
 
-astropy.io.vo.volint.main()
\ No newline at end of file
+astropy.io.votable.volint.main()
diff --git a/setup.cfg b/setup.cfg
index c04d0c8..43cd418 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -8,5 +8,10 @@ upload-dir = docs/_build/html
 show-response = 1
 
 [pytest]
-minversion = 2.2
-norecursedirs = build docs/_build
+minversion = 2.3.3
+norecursedirs = build docs/_build astropy/extern
+
+[bdist_dmg]
+background = .dmg_background.png
+# Note: The SVG source file for the DMG background image is located in the
+# repository at https://github.com/astropy/astropy-logo
diff --git a/setup.py b/setup.py
index 4e2c6c9..a2d5464 100755
--- a/setup.py
+++ b/setup.py
@@ -13,8 +13,6 @@ import sys
 from setuptools import setup, find_packages
 
 #A dirty hack to get around some early import/configurations ambiguities
-#This is the same as setup_helpers.set_build_mode(), but does not require
-#importing setup_helpers
 if sys.version_info[0] >= 3:
     import builtins
 else:
@@ -26,12 +24,12 @@ from astropy import setup_helpers
 from astropy.version_helper import get_git_devstr, generate_version_py
 
 #version should be PEP386 compatible (http://www.python.org/dev/peps/pep-0386)
-version = '0.1'
+version = '0.2b1'
 
 # Indicates if this version is a release version
 release = 'dev' not in version
 
-download_base_url = 'http://cloud.github.com/downloads/astropy/astropy'
+download_base_url = 'http://pypi.python.org/packages/source/a/astropy'
 
 # Adjust the compiler in case the default on this platform is to use a
 # broken one.
@@ -44,25 +42,52 @@ generate_version_py('astropy', version, release,
 
 # Use the find_packages tool to locate all packages and modules
 packagenames = find_packages()
+packagenames = setup_helpers.filter_packages(packagenames)
 
 # Treat everything in scripts except README.rst as a script to be installed
 scripts = glob.glob(os.path.join('scripts', '*'))
 scripts.remove(os.path.join('scripts', 'README.rst'))
 
-# Check that Numpy is installed.
-# NOTE: We cannot use setuptools/distribute/packaging to handle this
-# dependency for us, since some of the subpackages need to be able to
-# access numpy at build time, and they are configured before
-# setuptools has a chance to check and resolve the dependency.
-setup_helpers.check_numpy()
-
 # This dictionary stores the command classes used in setup below
 cmdclassd = {'test': setup_helpers.setup_test_command('astropy'),
 
              # Use distutils' sdist because it respects package_data.
              # setuptools/distributes sdist requires duplication of
              # information in MANIFEST.in
-             'sdist': sdist.sdist}
+             'sdist': sdist.sdist,
+
+             # Use a custom build command which understands additional
+             # commandline arguments
+             'build': setup_helpers.AstropyBuild,
+
+             # Use a custom install command which understands additional
+             # commandline arguments
+             'install': setup_helpers.AstropyInstall,
+
+             'register': setup_helpers.AstropyRegister
+             }
+
+try:
+    import bdist_mpkg
+except ImportError:
+    pass
+else:
+    # Use a custom command to build a dmg (on MacOS X)
+    cmdclassd['bdist_dmg'] = setup_helpers.bdist_dmg
+
+if setup_helpers.HAVE_CYTHON and not release:
+    from Cython.Distutils import build_ext
+    # Builds Cython->C if in dev mode and Cython is present
+    cmdclassd['build_ext'] = setup_helpers.wrap_build_ext(build_ext)
+else:
+    cmdclassd['build_ext'] = setup_helpers.wrap_build_ext()
+
+if setup_helpers.HAVE_SPHINX:
+    cmdclassd['build_sphinx'] = setup_helpers.AstropyBuildSphinx
+
+# Set our custom command class mapping in setup_helpers, so that
+# setup_helpers.get_distutils_option will use the custom classes.
+setup_helpers.cmdclassd = cmdclassd
 
 # Additional C extensions that are not Cython-based should be added here.
 extensions = []
@@ -80,15 +105,6 @@ package_dirs = {}
 setup_helpers.update_package_files('astropy', extensions, package_data,
                                    packagenames, package_dirs)
 
-if setup_helpers.HAVE_CYTHON and not release:
-    from Cython.Distutils import build_ext
-    # Builds Cython->C if in dev mode and Cython is present
-    cmdclassd['build_ext'] = build_ext
-
-if setup_helpers.AstropyBuildSphinx is not None:
-    cmdclassd['build_sphinx'] = setup_helpers.AstropyBuildSphinx
-
-
 # Currently the only entry points installed by Astropy are hooks to
 # zest.releaser for doing Astropy's releases
 entry_points = {}
@@ -116,6 +132,19 @@ setup(name='astropy',
       url='http://astropy.org',
       long_description=astropy.__doc__,
       download_url='%s/astropy-%s.tar.gz' % (download_base_url, version),
+      classifiers=[
+          'Intended Audience :: Science/Research',
+          'License :: OSI Approved :: BSD License',
+          'Operating System :: OS Independent',
+          'Programming Language :: C',
+          'Programming Language :: Cython',
+          'Programming Language :: Python :: 2.6',
+          'Programming Language :: Python :: 2.7',
+          'Programming Language :: Python :: 3',
+          'Programming Language :: Python :: Implementation :: CPython',
+          'Topic :: Scientific/Engineering :: Astronomy',
+          'Topic :: Scientific/Engineering :: Physics'
+      ],
       cmdclass=cmdclassd,
       zip_safe=False,
       use_2to3=True,

-- 
Core functionality for performing astronomy and astrophysics with Python



More information about the debian-science-commits mailing list